]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/ldns/dnssec_sign.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / ldns / dnssec_sign.c
1 #include <ldns/config.h>
2
3 #include <ldns/ldns.h>
4
5 #include <ldns/dnssec.h>
6 #include <ldns/dnssec_sign.h>
7
8 #include <strings.h>
9 #include <time.h>
10
11 #ifdef HAVE_SSL
12 /* this entire file is rather useless when you don't have
13  * crypto...
14  */
15 #include <openssl/ssl.h>
16 #include <openssl/evp.h>
17 #include <openssl/rand.h>
18 #include <openssl/err.h>
19 #include <openssl/md5.h>
20 #endif /* HAVE_SSL */
21
22 ldns_rr *
23 ldns_create_empty_rrsig(ldns_rr_list *rrset,
24                         ldns_key *current_key)
25 {
26         uint32_t orig_ttl;
27         ldns_rr_class orig_class;
28         time_t now;
29         ldns_rr *current_sig;
30         uint8_t label_count;
31         ldns_rdf *signame;
32
33         label_count = ldns_dname_label_count(ldns_rr_owner(ldns_rr_list_rr(rrset,
34                                                            0)));
35         /* RFC4035 2.2: not counting the leftmost label if it is a wildcard */
36         if(ldns_dname_is_wildcard(ldns_rr_owner(ldns_rr_list_rr(rrset, 0))))
37                 label_count --;
38
39         current_sig = ldns_rr_new_frm_type(LDNS_RR_TYPE_RRSIG);
40
41         /* set the type on the new signature */
42         orig_ttl = ldns_rr_ttl(ldns_rr_list_rr(rrset, 0));
43         orig_class = ldns_rr_get_class(ldns_rr_list_rr(rrset, 0));
44
45         ldns_rr_set_ttl(current_sig, orig_ttl);
46         ldns_rr_set_class(current_sig, orig_class);
47         ldns_rr_set_owner(current_sig,
48                           ldns_rdf_clone(
49                                ldns_rr_owner(
50                                     ldns_rr_list_rr(rrset,
51                                                     0))));
52
53         /* fill in what we know of the signature */
54
55         /* set the orig_ttl */
56         (void)ldns_rr_rrsig_set_origttl(
57                    current_sig,
58                    ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32,
59                                          orig_ttl));
60         /* the signers name */
61         signame = ldns_rdf_clone(ldns_key_pubkey_owner(current_key));
62         ldns_dname2canonical(signame);
63         (void)ldns_rr_rrsig_set_signame(
64                         current_sig,
65                         signame);
66         /* label count - get it from the first rr in the rr_list */
67         (void)ldns_rr_rrsig_set_labels(
68                         current_sig,
69                         ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8,
70                                              label_count));
71         /* inception, expiration */
72         now = time(NULL);
73         if (ldns_key_inception(current_key) != 0) {
74                 (void)ldns_rr_rrsig_set_inception(
75                                 current_sig,
76                                 ldns_native2rdf_int32(
77                                     LDNS_RDF_TYPE_TIME,
78                                     ldns_key_inception(current_key)));
79         } else {
80                 (void)ldns_rr_rrsig_set_inception(
81                                 current_sig,
82                                 ldns_native2rdf_int32(LDNS_RDF_TYPE_TIME, now));
83         }
84         if (ldns_key_expiration(current_key) != 0) {
85                 (void)ldns_rr_rrsig_set_expiration(
86                                 current_sig,
87                                 ldns_native2rdf_int32(
88                                     LDNS_RDF_TYPE_TIME,
89                                     ldns_key_expiration(current_key)));
90         } else {
91                 (void)ldns_rr_rrsig_set_expiration(
92                              current_sig,
93                                 ldns_native2rdf_int32(
94                                     LDNS_RDF_TYPE_TIME,
95                                     now + LDNS_DEFAULT_EXP_TIME));
96         }
97
98         (void)ldns_rr_rrsig_set_keytag(
99                    current_sig,
100                    ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16,
101                                          ldns_key_keytag(current_key)));
102
103         (void)ldns_rr_rrsig_set_algorithm(
104                         current_sig,
105                         ldns_native2rdf_int8(
106                             LDNS_RDF_TYPE_ALG,
107                             ldns_key_algorithm(current_key)));
108
109         (void)ldns_rr_rrsig_set_typecovered(
110                         current_sig,
111                         ldns_native2rdf_int16(
112                             LDNS_RDF_TYPE_TYPE,
113                             ldns_rr_get_type(ldns_rr_list_rr(rrset,
114                                                              0))));
115         return current_sig;
116 }
117
118 #ifdef HAVE_SSL
119 ldns_rdf *
120 ldns_sign_public_buffer(ldns_buffer *sign_buf, ldns_key *current_key)
121 {
122         ldns_rdf *b64rdf = NULL;
123
124         switch(ldns_key_algorithm(current_key)) {
125         case LDNS_SIGN_DSA:
126         case LDNS_SIGN_DSA_NSEC3:
127                 b64rdf = ldns_sign_public_evp(
128                                    sign_buf,
129                                    ldns_key_evp_key(current_key),
130                                    EVP_dss1());
131                 break;
132         case LDNS_SIGN_RSASHA1:
133         case LDNS_SIGN_RSASHA1_NSEC3:
134                 b64rdf = ldns_sign_public_evp(
135                                    sign_buf,
136                                    ldns_key_evp_key(current_key),
137                                    EVP_sha1());
138                 break;
139 #ifdef USE_SHA2
140         case LDNS_SIGN_RSASHA256:
141                 b64rdf = ldns_sign_public_evp(
142                                    sign_buf,
143                                    ldns_key_evp_key(current_key),
144                                    EVP_sha256());
145                 break;
146         case LDNS_SIGN_RSASHA512:
147                 b64rdf = ldns_sign_public_evp(
148                                    sign_buf,
149                                    ldns_key_evp_key(current_key),
150                                    EVP_sha512());
151                 break;
152 #endif /* USE_SHA2 */
153 #ifdef USE_GOST
154         case LDNS_SIGN_ECC_GOST:
155                 b64rdf = ldns_sign_public_evp(
156                                    sign_buf,
157                                    ldns_key_evp_key(current_key),
158                                    EVP_get_digestbyname("md_gost94"));
159                 break;
160 #endif /* USE_GOST */
161 #ifdef USE_ECDSA
162         case LDNS_SIGN_ECDSAP256SHA256:
163                 b64rdf = ldns_sign_public_evp(
164                                    sign_buf,
165                                    ldns_key_evp_key(current_key),
166                                    EVP_sha256());
167                 break;
168         case LDNS_SIGN_ECDSAP384SHA384:
169                 b64rdf = ldns_sign_public_evp(
170                                    sign_buf,
171                                    ldns_key_evp_key(current_key),
172                                    EVP_sha384());
173                 break;
174 #endif
175         case LDNS_SIGN_RSAMD5:
176                 b64rdf = ldns_sign_public_evp(
177                                    sign_buf,
178                                    ldns_key_evp_key(current_key),
179                                    EVP_md5());
180                 break;
181         default:
182                 /* do _you_ know this alg? */
183                 printf("unknown algorithm, ");
184                 printf("is the one used available on this system?\n");
185                 break;
186         }
187
188         return b64rdf;
189 }
190
191 /**
192  * use this function to sign with a public/private key alg
193  * return the created signatures
194  */
195 ldns_rr_list *
196 ldns_sign_public(ldns_rr_list *rrset, ldns_key_list *keys)
197 {
198         ldns_rr_list *signatures;
199         ldns_rr_list *rrset_clone;
200         ldns_rr *current_sig;
201         ldns_rdf *b64rdf;
202         ldns_key *current_key;
203         size_t key_count;
204         uint16_t i;
205         ldns_buffer *sign_buf;
206         ldns_rdf *new_owner;
207
208         if (!rrset || ldns_rr_list_rr_count(rrset) < 1 || !keys) {
209                 return NULL;
210         }
211
212         new_owner = NULL;
213
214         signatures = ldns_rr_list_new();
215
216         /* prepare a signature and add all the know data
217          * prepare the rrset. Sign this together.  */
218         rrset_clone = ldns_rr_list_clone(rrset);
219         if (!rrset_clone) {
220                 return NULL;
221         }
222
223         /* make it canonical */
224         for(i = 0; i < ldns_rr_list_rr_count(rrset_clone); i++) {
225                 ldns_rr_set_ttl(ldns_rr_list_rr(rrset_clone, i), 
226                         ldns_rr_ttl(ldns_rr_list_rr(rrset, 0)));
227                 ldns_rr2canonical(ldns_rr_list_rr(rrset_clone, i));
228         }
229         /* sort */
230         ldns_rr_list_sort(rrset_clone);
231
232         for (key_count = 0;
233                 key_count < ldns_key_list_key_count(keys);
234                 key_count++) {
235                 if (!ldns_key_use(ldns_key_list_key(keys, key_count))) {
236                         continue;
237                 }
238                 sign_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN);
239                 if (!sign_buf) {
240                         ldns_rr_list_free(rrset_clone);
241                         ldns_rr_list_free(signatures);
242                         ldns_rdf_free(new_owner);
243                         return NULL;
244                 }
245                 b64rdf = NULL;
246
247                 current_key = ldns_key_list_key(keys, key_count);
248                 /* sign all RRs with keys that have ZSKbit, !SEPbit.
249                    sign DNSKEY RRs with keys that have ZSKbit&SEPbit */
250                 if (ldns_key_flags(current_key) & LDNS_KEY_ZONE_KEY) {
251                         current_sig = ldns_create_empty_rrsig(rrset_clone,
252                                                               current_key);
253
254                         /* right now, we have: a key, a semi-sig and an rrset. For
255                          * which we can create the sig and base64 encode that and
256                          * add that to the signature */
257
258                         if (ldns_rrsig2buffer_wire(sign_buf, current_sig)
259                             != LDNS_STATUS_OK) {
260                                 ldns_buffer_free(sign_buf);
261                                 /* ERROR */
262                                 ldns_rr_list_deep_free(rrset_clone);
263                                 ldns_rr_free(current_sig);
264                                 ldns_rr_list_deep_free(signatures);
265                                 return NULL;
266                         }
267
268                         /* add the rrset in sign_buf */
269                         if (ldns_rr_list2buffer_wire(sign_buf, rrset_clone)
270                             != LDNS_STATUS_OK) {
271                                 ldns_buffer_free(sign_buf);
272                                 ldns_rr_list_deep_free(rrset_clone);
273                                 ldns_rr_free(current_sig);
274                                 ldns_rr_list_deep_free(signatures);
275                                 return NULL;
276                         }
277
278                         b64rdf = ldns_sign_public_buffer(sign_buf, current_key);
279
280                         if (!b64rdf) {
281                                 /* signing went wrong */
282                                 ldns_rr_list_deep_free(rrset_clone);
283                                 ldns_rr_free(current_sig);
284                                 ldns_rr_list_deep_free(signatures);
285                                 return NULL;
286                         }
287
288                         ldns_rr_rrsig_set_sig(current_sig, b64rdf);
289
290                         /* push the signature to the signatures list */
291                         ldns_rr_list_push_rr(signatures, current_sig);
292                 }
293                 ldns_buffer_free(sign_buf); /* restart for the next key */
294         }
295         ldns_rr_list_deep_free(rrset_clone);
296
297         return signatures;
298 }
299
300 /**
301  * Sign data with DSA
302  *
303  * \param[in] to_sign The ldns_buffer containing raw data that is
304  *                    to be signed
305  * \param[in] key The DSA key structure to sign with
306  * \return ldns_rdf for the RRSIG ldns_rr
307  */
308 ldns_rdf *
309 ldns_sign_public_dsa(ldns_buffer *to_sign, DSA *key)
310 {
311         unsigned char *sha1_hash;
312         ldns_rdf *sigdata_rdf;
313         ldns_buffer *b64sig;
314
315         DSA_SIG *sig;
316         uint8_t *data;
317         size_t pad;
318
319         b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN);
320         if (!b64sig) {
321                 return NULL;
322         }
323
324         sha1_hash = SHA1((unsigned char*)ldns_buffer_begin(to_sign),
325                                   ldns_buffer_position(to_sign), NULL);
326         if (!sha1_hash) {
327                 ldns_buffer_free(b64sig);
328                 return NULL;
329         }
330
331         sig = DSA_do_sign(sha1_hash, SHA_DIGEST_LENGTH, key);
332         if(!sig) {
333                 ldns_buffer_free(b64sig);
334                 return NULL;
335         }
336
337         data = LDNS_XMALLOC(uint8_t, 1 + 2 * SHA_DIGEST_LENGTH);
338         if(!data) {
339                 ldns_buffer_free(b64sig);
340                 DSA_SIG_free(sig);
341                 return NULL;
342         }
343
344         data[0] = 1;
345         pad = 20 - (size_t) BN_num_bytes(sig->r);
346         if (pad > 0) {
347                 memset(data + 1, 0, pad);
348         }
349         BN_bn2bin(sig->r, (unsigned char *) (data + 1) + pad);
350
351         pad = 20 - (size_t) BN_num_bytes(sig->s);
352         if (pad > 0) {
353                 memset(data + 1 + SHA_DIGEST_LENGTH, 0, pad);
354         }
355         BN_bn2bin(sig->s, (unsigned char *) (data + 1 + SHA_DIGEST_LENGTH + pad));
356
357         sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64,
358                                                                  1 + 2 * SHA_DIGEST_LENGTH,
359                                                                  data);
360
361         ldns_buffer_free(b64sig);
362         LDNS_FREE(data);
363         DSA_SIG_free(sig);
364
365         return sigdata_rdf;
366 }
367
368 #ifdef USE_ECDSA
369 #ifndef S_SPLINT_S
370 static int
371 ldns_pkey_is_ecdsa(EVP_PKEY* pkey)
372 {
373         EC_KEY* ec;
374         const EC_GROUP* g;
375         if(EVP_PKEY_type(pkey->type) != EVP_PKEY_EC)
376                 return 0;
377         ec = EVP_PKEY_get1_EC_KEY(pkey);
378         g = EC_KEY_get0_group(ec);
379         if(!g) {
380                 EC_KEY_free(ec);
381                 return 0;
382         }
383         if(EC_GROUP_get_curve_name(g) == NID_secp224r1 ||
384                 EC_GROUP_get_curve_name(g) == NID_X9_62_prime256v1 ||
385                 EC_GROUP_get_curve_name(g) == NID_secp384r1) {
386                 EC_KEY_free(ec);
387                 return 1;
388         }
389         /* downref the eckey, the original is still inside the pkey */
390         EC_KEY_free(ec);
391         return 0;
392 }
393 #endif /* splint */
394 #endif /* USE_ECDSA */
395
396 ldns_rdf *
397 ldns_sign_public_evp(ldns_buffer *to_sign,
398                                  EVP_PKEY *key,
399                                  const EVP_MD *digest_type)
400 {
401         unsigned int siglen;
402         ldns_rdf *sigdata_rdf;
403         ldns_buffer *b64sig;
404         EVP_MD_CTX ctx;
405         const EVP_MD *md_type;
406         int r;
407
408         siglen = 0;
409         b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN);
410         if (!b64sig) {
411                 return NULL;
412         }
413
414         /* initializes a signing context */
415         md_type = digest_type;
416         if(!md_type) {
417                 /* unknown message difest */
418                 ldns_buffer_free(b64sig);
419                 return NULL;
420         }
421
422         EVP_MD_CTX_init(&ctx);
423         r = EVP_SignInit(&ctx, md_type);
424         if(r == 1) {
425                 r = EVP_SignUpdate(&ctx, (unsigned char*)
426                                             ldns_buffer_begin(to_sign),
427                                             ldns_buffer_position(to_sign));
428         } else {
429                 ldns_buffer_free(b64sig);
430                 return NULL;
431         }
432         if(r == 1) {
433                 r = EVP_SignFinal(&ctx, (unsigned char*)
434                                            ldns_buffer_begin(b64sig), &siglen, key);
435         } else {
436                 ldns_buffer_free(b64sig);
437                 return NULL;
438         }
439         if(r != 1) {
440                 ldns_buffer_free(b64sig);
441                 return NULL;
442         }
443
444         /* unfortunately, OpenSSL output is differenct from DNS DSA format */
445 #ifndef S_SPLINT_S
446         if (EVP_PKEY_type(key->type) == EVP_PKEY_DSA) {
447                 sigdata_rdf = ldns_convert_dsa_rrsig_asn12rdf(b64sig, siglen);
448 #ifdef USE_ECDSA
449         } else if(EVP_PKEY_type(key->type) == EVP_PKEY_EC &&
450                 ldns_pkey_is_ecdsa(key)) {
451                 sigdata_rdf = ldns_convert_ecdsa_rrsig_asn12rdf(b64sig, siglen);
452 #endif
453         } else {
454                 /* ok output for other types is the same */
455                 sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, siglen,
456                                                                          ldns_buffer_begin(b64sig));
457         }
458 #endif /* splint */
459         ldns_buffer_free(b64sig);
460         EVP_MD_CTX_cleanup(&ctx);
461         return sigdata_rdf;
462 }
463
464 ldns_rdf *
465 ldns_sign_public_rsasha1(ldns_buffer *to_sign, RSA *key)
466 {
467         unsigned char *sha1_hash;
468         unsigned int siglen;
469         ldns_rdf *sigdata_rdf;
470         ldns_buffer *b64sig;
471         int result;
472
473         siglen = 0;
474         b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN);
475         if (!b64sig) {
476                 return NULL;
477         }
478
479         sha1_hash = SHA1((unsigned char*)ldns_buffer_begin(to_sign),
480                                   ldns_buffer_position(to_sign), NULL);
481         if (!sha1_hash) {
482                 ldns_buffer_free(b64sig);
483                 return NULL;
484         }
485
486         result = RSA_sign(NID_sha1, sha1_hash, SHA_DIGEST_LENGTH,
487                                    (unsigned char*)ldns_buffer_begin(b64sig),
488                                    &siglen, key);
489         if (result != 1) {
490                 ldns_buffer_free(b64sig);
491                 return NULL;
492         }
493
494         sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, siglen, 
495                                                                  ldns_buffer_begin(b64sig));
496         ldns_buffer_free(b64sig); /* can't free this buffer ?? */
497         return sigdata_rdf;
498 }
499
500 ldns_rdf *
501 ldns_sign_public_rsamd5(ldns_buffer *to_sign, RSA *key)
502 {
503         unsigned char *md5_hash;
504         unsigned int siglen;
505         ldns_rdf *sigdata_rdf;
506         ldns_buffer *b64sig;
507
508         b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN);
509         if (!b64sig) {
510                 return NULL;
511         }
512
513         md5_hash = MD5((unsigned char*)ldns_buffer_begin(to_sign),
514                                 ldns_buffer_position(to_sign), NULL);
515         if (!md5_hash) {
516                 ldns_buffer_free(b64sig);
517                 return NULL;
518         }
519
520         RSA_sign(NID_md5, md5_hash, MD5_DIGEST_LENGTH,
521                     (unsigned char*)ldns_buffer_begin(b64sig),
522                     &siglen, key);
523
524         sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, siglen,
525                                                                  ldns_buffer_begin(b64sig));
526         ldns_buffer_free(b64sig);
527         return sigdata_rdf;
528 }
529 #endif /* HAVE_SSL */
530
531 /**
532  * Pushes all rrs from the rrsets of type A and AAAA on gluelist.
533  */
534 static ldns_status
535 ldns_dnssec_addresses_on_glue_list(
536                 ldns_dnssec_rrsets *cur_rrset,
537                 ldns_rr_list *glue_list)
538 {
539         ldns_dnssec_rrs *cur_rrs;
540         while (cur_rrset) {
541                 if (cur_rrset->type == LDNS_RR_TYPE_A 
542                                 || cur_rrset->type == LDNS_RR_TYPE_AAAA) {
543                         for (cur_rrs = cur_rrset->rrs; 
544                                         cur_rrs; 
545                                         cur_rrs = cur_rrs->next) {
546                                 if (cur_rrs->rr) {
547                                         if (!ldns_rr_list_push_rr(glue_list, 
548                                                         cur_rrs->rr)) {
549                                                 return LDNS_STATUS_MEM_ERR; 
550                                                 /* ldns_rr_list_push_rr()
551                                                  * returns false when unable
552                                                  * to increase the capacity
553                                                  * of the ldsn_rr_list
554                                                  */
555                                         }
556                                 }
557                         }
558                 }
559                 cur_rrset = cur_rrset->next;
560         }
561         return LDNS_STATUS_OK;
562 }
563
564 /**
565  * Marks the names in the zone that are occluded. Those names will be skipped
566  * when walking the tree with the ldns_dnssec_name_node_next_nonglue()
567  * function. But watch out! Names that are partially occluded (like glue with
568  * the same name as the delegation) will not be marked and should specifically 
569  * be taken into account separately.
570  *
571  * When glue_list is given (not NULL), in the process of marking the names, all
572  * glue resource records will be pushed to that list, even glue at delegation names.
573  *
574  * \param[in] zone the zone in which to mark the names
575  * \param[in] glue_list the list to which to push the glue rrs
576  * \return LDNS_STATUS_OK on success, an error code otherwise
577  */
578 ldns_status
579 ldns_dnssec_zone_mark_and_get_glue(ldns_dnssec_zone *zone, 
580         ldns_rr_list *glue_list)
581 {
582         ldns_rbnode_t    *node;
583         ldns_dnssec_name *name;
584         ldns_rdf         *owner;
585         ldns_rdf         *cut = NULL; /* keeps track of zone cuts */
586         /* When the cut is caused by a delegation, below_delegation will be 1.
587          * When caused by a DNAME, below_delegation will be 0.
588          */
589         int below_delegation = -1; /* init suppresses comiler warning */
590         ldns_status s;
591
592         if (!zone || !zone->names) {
593                 return LDNS_STATUS_NULL;
594         }
595         for (node = ldns_rbtree_first(zone->names); 
596                         node != LDNS_RBTREE_NULL; 
597                         node = ldns_rbtree_next(node)) {
598                 name = (ldns_dnssec_name *) node->data;
599                 owner = ldns_dnssec_name_name(name);
600
601                 if (cut) { 
602                         /* The previous node was a zone cut, or a subdomain
603                          * below a zone cut. Is this node (still) a subdomain
604                          * below the cut? Then the name is occluded. Unless
605                          * the name contains a SOA, after which we are 
606                          * authoritative again.
607                          *
608                          * FIXME! If there are labels in between the SOA and
609                          * the cut, going from the authoritative space (below
610                          * the SOA) up into occluded space again, will not be
611                          * detected with the contruct below!
612                          */
613                         if (ldns_dname_is_subdomain(owner, cut) &&
614                                         !ldns_dnssec_rrsets_contains_type(
615                                         name->rrsets, LDNS_RR_TYPE_SOA)) {
616
617                                 if (below_delegation && glue_list) {
618                                         s = ldns_dnssec_addresses_on_glue_list(
619                                                 name->rrsets, glue_list);
620                                         if (s != LDNS_STATUS_OK) {
621                                                 return s;
622                                         }
623                                 }
624                                 name->is_glue = true; /* Mark occluded name! */
625                                 continue;
626                         } else {
627                                 cut = NULL;
628                         }
629                 }
630
631                 /* The node is not below a zone cut. Is it a zone cut itself?
632                  * Everything below a SOA is authoritative of course; Except
633                  * when the name also contains a DNAME :).
634                  */
635                 if (ldns_dnssec_rrsets_contains_type(
636                                 name->rrsets, LDNS_RR_TYPE_NS)
637                             && !ldns_dnssec_rrsets_contains_type(
638                                 name->rrsets, LDNS_RR_TYPE_SOA)) {
639                         cut = owner;
640                         below_delegation = 1;
641                         if (glue_list) { /* record glue on the zone cut */
642                                 s = ldns_dnssec_addresses_on_glue_list(
643                                         name->rrsets, glue_list);
644                                 if (s != LDNS_STATUS_OK) {
645                                         return s;
646                                 }
647                         }
648                 } else if (ldns_dnssec_rrsets_contains_type(
649                                 name->rrsets, LDNS_RR_TYPE_DNAME)) {
650                         cut = owner;
651                         below_delegation = 0;
652                 }
653         }
654         return LDNS_STATUS_OK;
655 }
656
657 /**
658  * Marks the names in the zone that are occluded. Those names will be skipped
659  * when walking the tree with the ldns_dnssec_name_node_next_nonglue()
660  * function. But watch out! Names that are partially occluded (like glue with
661  * the same name as the delegation) will not be marked and should specifically 
662  * be taken into account separately.
663  *
664  * \param[in] zone the zone in which to mark the names
665  * \return LDNS_STATUS_OK on success, an error code otherwise
666  */
667 ldns_status
668 ldns_dnssec_zone_mark_glue(ldns_dnssec_zone *zone)
669 {
670         return ldns_dnssec_zone_mark_and_get_glue(zone, NULL);
671 }
672
673 ldns_rbnode_t *
674 ldns_dnssec_name_node_next_nonglue(ldns_rbnode_t *node)
675 {
676         ldns_rbnode_t *next_node = NULL;
677         ldns_dnssec_name *next_name = NULL;
678         bool done = false;
679
680         if (node == LDNS_RBTREE_NULL) {
681                 return NULL;
682         }
683         next_node = node;
684         while (!done) {
685                 if (next_node == LDNS_RBTREE_NULL) {
686                         return NULL;
687                 } else {
688                         next_name = (ldns_dnssec_name *)next_node->data;
689                         if (!next_name->is_glue) {
690                                 done = true;
691                         } else {
692                                 next_node = ldns_rbtree_next(next_node);
693                         }
694                 }
695         }
696         return next_node;
697 }
698
699 ldns_status
700 ldns_dnssec_zone_create_nsecs(ldns_dnssec_zone *zone,
701                               ldns_rr_list *new_rrs)
702 {
703
704         ldns_rbnode_t *first_node, *cur_node, *next_node;
705         ldns_dnssec_name *cur_name, *next_name;
706         ldns_rr *nsec_rr;
707         uint32_t nsec_ttl;
708         ldns_dnssec_rrsets *soa;
709
710         /* the TTL of NSEC rrs should be set to the minimum TTL of
711          * the zone SOA (RFC4035 Section 2.3)
712          */
713         soa = ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_SOA);
714
715         /* did the caller actually set it? if not,
716          * fall back to default ttl
717          */
718         if (soa && soa->rrs && soa->rrs->rr
719                         && (ldns_rr_rdf(soa->rrs->rr, 6) != NULL)) {
720                 nsec_ttl = ldns_rdf2native_int32(ldns_rr_rdf(soa->rrs->rr, 6));
721         } else {
722                 nsec_ttl = LDNS_DEFAULT_TTL;
723         }
724
725         first_node = ldns_dnssec_name_node_next_nonglue(
726                                ldns_rbtree_first(zone->names));
727         cur_node = first_node;
728         if (cur_node) {
729                 next_node = ldns_dnssec_name_node_next_nonglue(
730                                    ldns_rbtree_next(cur_node));
731         } else {
732                 next_node = NULL;
733         }
734
735         while (cur_node && next_node) {
736                 cur_name = (ldns_dnssec_name *)cur_node->data;
737                 next_name = (ldns_dnssec_name *)next_node->data;
738                 nsec_rr = ldns_dnssec_create_nsec(cur_name,
739                                                   next_name,
740                                                   LDNS_RR_TYPE_NSEC);
741                 ldns_rr_set_ttl(nsec_rr, nsec_ttl);
742                 if(ldns_dnssec_name_add_rr(cur_name, nsec_rr)!=LDNS_STATUS_OK){
743                         ldns_rr_free(nsec_rr);
744                         return LDNS_STATUS_ERR;
745                 }
746                 ldns_rr_list_push_rr(new_rrs, nsec_rr);
747                 cur_node = next_node;
748                 if (cur_node) {
749                         next_node = ldns_dnssec_name_node_next_nonglue(
750                                ldns_rbtree_next(cur_node));
751                 }
752         }
753
754         if (cur_node && !next_node) {
755                 cur_name = (ldns_dnssec_name *)cur_node->data;
756                 next_name = (ldns_dnssec_name *)first_node->data;
757                 nsec_rr = ldns_dnssec_create_nsec(cur_name,
758                                                   next_name,
759                                                   LDNS_RR_TYPE_NSEC);
760                 ldns_rr_set_ttl(nsec_rr, nsec_ttl);
761                 if(ldns_dnssec_name_add_rr(cur_name, nsec_rr)!=LDNS_STATUS_OK){
762                         ldns_rr_free(nsec_rr);
763                         return LDNS_STATUS_ERR;
764                 }
765                 ldns_rr_list_push_rr(new_rrs, nsec_rr);
766         } else {
767                 printf("error\n");
768         }
769
770         return LDNS_STATUS_OK;
771 }
772
773 #ifdef HAVE_SSL
774 static void
775 ldns_hashed_names_node_free(ldns_rbnode_t *node, void *arg) {
776         (void) arg;
777         LDNS_FREE(node);
778 }
779
780 static ldns_status
781 ldns_dnssec_zone_create_nsec3s_mkmap(ldns_dnssec_zone *zone,
782                 ldns_rr_list *new_rrs,
783                 uint8_t algorithm,
784                 uint8_t flags,
785                 uint16_t iterations,
786                 uint8_t salt_length,
787                 uint8_t *salt,
788                 ldns_rbtree_t **map)
789 {
790         ldns_rbnode_t *first_name_node;
791         ldns_rbnode_t *current_name_node;
792         ldns_dnssec_name *current_name;
793         ldns_status result = LDNS_STATUS_OK;
794         ldns_rr *nsec_rr;
795         ldns_rr_list *nsec3_list;
796         uint32_t nsec_ttl;
797         ldns_dnssec_rrsets *soa;
798         ldns_rbnode_t *hashmap_node;
799
800         if (!zone || !new_rrs || !zone->names) {
801                 return LDNS_STATUS_ERR;
802         }
803
804         /* the TTL of NSEC rrs should be set to the minimum TTL of
805          * the zone SOA (RFC4035 Section 2.3)
806          */
807         soa = ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_SOA);
808
809         /* did the caller actually set it? if not,
810          * fall back to default ttl
811          */
812         if (soa && soa->rrs && soa->rrs->rr
813                         && ldns_rr_rdf(soa->rrs->rr, 6) != NULL) {
814                 nsec_ttl = ldns_rdf2native_int32(ldns_rr_rdf(soa->rrs->rr, 6));
815         } else {
816                 nsec_ttl = LDNS_DEFAULT_TTL;
817         }
818
819         if (zone->hashed_names) {
820                 ldns_traverse_postorder(zone->hashed_names,
821                                 ldns_hashed_names_node_free, NULL);
822                 LDNS_FREE(zone->hashed_names);
823         }
824         zone->hashed_names = ldns_rbtree_create(ldns_dname_compare_v);
825         if (zone->hashed_names && map) {
826                 *map = zone->hashed_names;
827         }
828
829         first_name_node = ldns_dnssec_name_node_next_nonglue(
830                                           ldns_rbtree_first(zone->names));
831
832         current_name_node = first_name_node;
833
834         while (current_name_node && current_name_node != LDNS_RBTREE_NULL &&
835                         result == LDNS_STATUS_OK) {
836
837                 current_name = (ldns_dnssec_name *) current_name_node->data;
838                 nsec_rr = ldns_dnssec_create_nsec3(current_name,
839                                                    NULL,
840                                                    zone->soa->name,
841                                                    algorithm,
842                                                    flags,
843                                                    iterations,
844                                                    salt_length,
845                                                    salt);
846                 /* by default, our nsec based generator adds rrsigs
847                  * remove the bitmap for empty nonterminals */
848                 if (!current_name->rrsets) {
849                         ldns_rdf_deep_free(ldns_rr_pop_rdf(nsec_rr));
850                 }
851                 ldns_rr_set_ttl(nsec_rr, nsec_ttl);
852                 result = ldns_dnssec_name_add_rr(current_name, nsec_rr);
853                 ldns_rr_list_push_rr(new_rrs, nsec_rr);
854                 if (ldns_rr_owner(nsec_rr)) {
855                         hashmap_node = LDNS_MALLOC(ldns_rbnode_t);
856                         if (hashmap_node == NULL) {
857                                 return LDNS_STATUS_MEM_ERR;
858                         }
859                         current_name->hashed_name = 
860                                 ldns_dname_label(ldns_rr_owner(nsec_rr), 0);
861
862                         if (current_name->hashed_name == NULL) {
863                                 LDNS_FREE(hashmap_node);
864                                 return LDNS_STATUS_MEM_ERR;
865                         }
866                         hashmap_node->key  = current_name->hashed_name;
867                         hashmap_node->data = current_name;
868
869                         if (! ldns_rbtree_insert(zone->hashed_names
870                                                 , hashmap_node)) {
871                                 LDNS_FREE(hashmap_node);
872                         }
873                 }
874                 current_name_node = ldns_dnssec_name_node_next_nonglue(
875                                    ldns_rbtree_next(current_name_node));
876         }
877         if (result != LDNS_STATUS_OK) {
878                 return result;
879         }
880
881         /* Make sorted list of nsec3s (via zone->hashed_names)
882          */
883         nsec3_list = ldns_rr_list_new();
884         if (nsec3_list == NULL) {
885                 return LDNS_STATUS_MEM_ERR;
886         }
887         for ( hashmap_node  = ldns_rbtree_first(zone->hashed_names)
888             ; hashmap_node != LDNS_RBTREE_NULL
889             ; hashmap_node  = ldns_rbtree_next(hashmap_node)
890             ) {
891                 current_name = (ldns_dnssec_name *) hashmap_node->data;
892                 nsec_rr = ((ldns_dnssec_name *) hashmap_node->data)->nsec;
893                 if (nsec_rr) {
894                         ldns_rr_list_push_rr(nsec3_list, nsec_rr);
895                 }
896         }
897         result = ldns_dnssec_chain_nsec3_list(nsec3_list);
898         ldns_rr_list_free(nsec3_list);
899
900         return result;
901 }
902
903 ldns_status
904 ldns_dnssec_zone_create_nsec3s(ldns_dnssec_zone *zone,
905                 ldns_rr_list *new_rrs,
906                 uint8_t algorithm,
907                 uint8_t flags,
908                 uint16_t iterations,
909                 uint8_t salt_length,
910                 uint8_t *salt)
911 {
912         return ldns_dnssec_zone_create_nsec3s_mkmap(zone, new_rrs, algorithm,
913                         flags, iterations, salt_length, salt, NULL);
914
915 }
916 #endif /* HAVE_SSL */
917
918 ldns_dnssec_rrs *
919 ldns_dnssec_remove_signatures( ldns_dnssec_rrs *signatures
920                              , ATTR_UNUSED(ldns_key_list *key_list)
921                              , int (*func)(ldns_rr *, void *)
922                              , void *arg
923                              )
924 {
925         ldns_dnssec_rrs *base_rrs = signatures;
926         ldns_dnssec_rrs *cur_rr = base_rrs;
927         ldns_dnssec_rrs *prev_rr = NULL;
928         ldns_dnssec_rrs *next_rr;
929
930         uint16_t keytag;
931         size_t i;
932
933         if (!cur_rr) {
934                 switch(func(NULL, arg)) {
935                 case LDNS_SIGNATURE_LEAVE_ADD_NEW:
936                 case LDNS_SIGNATURE_REMOVE_ADD_NEW:
937                 break;
938                 case LDNS_SIGNATURE_LEAVE_NO_ADD:
939                 case LDNS_SIGNATURE_REMOVE_NO_ADD:
940                 ldns_key_list_set_use(key_list, false);
941                 break;
942                 default:
943 #ifdef STDERR_MSGS
944                         fprintf(stderr, "[XX] unknown return value from callback\n");
945 #endif
946                         break;
947                 }
948                 return NULL;
949         }
950         (void)func(cur_rr->rr, arg);
951
952         while (cur_rr) {
953                 next_rr = cur_rr->next;
954
955                 switch (func(cur_rr->rr, arg)) {
956                 case  LDNS_SIGNATURE_LEAVE_ADD_NEW:
957                         prev_rr = cur_rr;
958                         break;
959                 case LDNS_SIGNATURE_LEAVE_NO_ADD:
960                         keytag = ldns_rdf2native_int16(
961                                            ldns_rr_rrsig_keytag(cur_rr->rr));
962                         for (i = 0; i < ldns_key_list_key_count(key_list); i++) {
963                                 if (ldns_key_keytag(ldns_key_list_key(key_list, i)) ==
964                                     keytag) {
965                                         ldns_key_set_use(ldns_key_list_key(key_list, i),
966                                                                   false);
967                                 }
968                         }
969                         prev_rr = cur_rr;
970                         break;
971                 case LDNS_SIGNATURE_REMOVE_NO_ADD:
972                         keytag = ldns_rdf2native_int16(
973                                            ldns_rr_rrsig_keytag(cur_rr->rr));
974                         for (i = 0; i < ldns_key_list_key_count(key_list); i++) {
975                                 if (ldns_key_keytag(ldns_key_list_key(key_list, i))
976                                     == keytag) {
977                                         ldns_key_set_use(ldns_key_list_key(key_list, i),
978                                                                   false);
979                                 }
980                         }
981                         if (prev_rr) {
982                                 prev_rr->next = next_rr;
983                         } else {
984                                 base_rrs = next_rr;
985                         }
986                         LDNS_FREE(cur_rr);
987                         break;
988                 case LDNS_SIGNATURE_REMOVE_ADD_NEW:
989                         if (prev_rr) {
990                                 prev_rr->next = next_rr;
991                         } else {
992                                 base_rrs = next_rr;
993                         }
994                         LDNS_FREE(cur_rr);
995                         break;
996                 default:
997 #ifdef STDERR_MSGS
998                         fprintf(stderr, "[XX] unknown return value from callback\n");
999 #endif
1000                         break;
1001                 }
1002                 cur_rr = next_rr;
1003         }
1004
1005         return base_rrs;
1006 }
1007
1008 #ifdef HAVE_SSL
1009 ldns_status
1010 ldns_dnssec_zone_create_rrsigs(ldns_dnssec_zone *zone,
1011                                ldns_rr_list *new_rrs,
1012                                ldns_key_list *key_list,
1013                                int (*func)(ldns_rr *, void*),
1014                                void *arg)
1015 {
1016         return ldns_dnssec_zone_create_rrsigs_flg(zone, new_rrs, key_list,
1017                 func, arg, 0);
1018 }
1019
1020 /** If there are KSKs use only them and mark ZSKs unused */
1021 static void
1022 ldns_key_list_filter_for_dnskey(ldns_key_list *key_list)
1023 {
1024         int saw_ksk = 0;
1025         size_t i;
1026         for(i=0; i<ldns_key_list_key_count(key_list); i++)
1027                 if((ldns_key_flags(ldns_key_list_key(key_list, i))&LDNS_KEY_SEP_KEY)) {
1028                         saw_ksk = 1;
1029                         break;
1030                 }
1031         if(!saw_ksk)
1032                 return;
1033         for(i=0; i<ldns_key_list_key_count(key_list); i++)
1034                 if(!(ldns_key_flags(ldns_key_list_key(key_list, i))&LDNS_KEY_SEP_KEY))
1035                         ldns_key_set_use(ldns_key_list_key(key_list, i), 0);
1036 }
1037
1038 /** If there are no ZSKs use KSK as ZSK */
1039 static void
1040 ldns_key_list_filter_for_non_dnskey(ldns_key_list *key_list)
1041 {
1042         int saw_zsk = 0;
1043         size_t i;
1044         for(i=0; i<ldns_key_list_key_count(key_list); i++)
1045                 if(!(ldns_key_flags(ldns_key_list_key(key_list, i))&LDNS_KEY_SEP_KEY)) {
1046                         saw_zsk = 1;
1047                         break;
1048                 }
1049         if(!saw_zsk)
1050                 return;
1051         /* else filter all KSKs */
1052         for(i=0; i<ldns_key_list_key_count(key_list); i++)
1053                 if((ldns_key_flags(ldns_key_list_key(key_list, i))&LDNS_KEY_SEP_KEY))
1054                         ldns_key_set_use(ldns_key_list_key(key_list, i), 0);
1055 }
1056
1057 ldns_status
1058 ldns_dnssec_zone_create_rrsigs_flg( ldns_dnssec_zone *zone
1059                                   , ldns_rr_list *new_rrs
1060                                   , ldns_key_list *key_list
1061                                   , int (*func)(ldns_rr *, void*)
1062                                   , void *arg
1063                                   , int flags
1064                                   )
1065 {
1066         ldns_status result = LDNS_STATUS_OK;
1067
1068         ldns_rbnode_t *cur_node;
1069         ldns_rr_list *rr_list;
1070
1071         ldns_dnssec_name *cur_name;
1072         ldns_dnssec_rrsets *cur_rrset;
1073         ldns_dnssec_rrs *cur_rr;
1074
1075         ldns_rr_list *siglist;
1076
1077         size_t i;
1078
1079         int on_delegation_point = 0; /* handle partially occluded names */
1080
1081         ldns_rr_list *pubkey_list = ldns_rr_list_new();
1082         for (i = 0; i<ldns_key_list_key_count(key_list); i++) {
1083                 ldns_rr_list_push_rr( pubkey_list
1084                                     , ldns_key2rr(ldns_key_list_key(
1085                                                         key_list, i))
1086                                     );
1087         }
1088         /* TODO: callback to see is list should be signed */
1089         /* TODO: remove 'old' signatures from signature list */
1090         cur_node = ldns_rbtree_first(zone->names);
1091         while (cur_node != LDNS_RBTREE_NULL) {
1092                 cur_name = (ldns_dnssec_name *) cur_node->data;
1093
1094                 if (!cur_name->is_glue) {
1095                         on_delegation_point = ldns_dnssec_rrsets_contains_type(
1096                                         cur_name->rrsets, LDNS_RR_TYPE_NS)
1097                                 && !ldns_dnssec_rrsets_contains_type(
1098                                         cur_name->rrsets, LDNS_RR_TYPE_SOA);
1099                         cur_rrset = cur_name->rrsets;
1100                         while (cur_rrset) {
1101                                 /* reset keys to use */
1102                                 ldns_key_list_set_use(key_list, true);
1103
1104                                 /* walk through old sigs, remove the old,
1105                                    and mark which keys (not) to use) */
1106                                 cur_rrset->signatures =
1107                                         ldns_dnssec_remove_signatures(cur_rrset->signatures,
1108                                                                                         key_list,
1109                                                                                         func,
1110                                                                                         arg);
1111                                 if(!(flags&LDNS_SIGN_DNSKEY_WITH_ZSK) &&
1112                                         cur_rrset->type == LDNS_RR_TYPE_DNSKEY)
1113                                         ldns_key_list_filter_for_dnskey(key_list);
1114
1115                                 if(cur_rrset->type != LDNS_RR_TYPE_DNSKEY)
1116                                         ldns_key_list_filter_for_non_dnskey(key_list);
1117
1118                                 /* TODO: just set count to zero? */
1119                                 rr_list = ldns_rr_list_new();
1120
1121                                 cur_rr = cur_rrset->rrs;
1122                                 while (cur_rr) {
1123                                         ldns_rr_list_push_rr(rr_list, cur_rr->rr);
1124                                         cur_rr = cur_rr->next;
1125                                 }
1126
1127                                 /* only sign non-delegation RRsets */
1128                                 /* (glue should have been marked earlier, 
1129                                  *  except on the delegation points itself) */
1130                                 if (!on_delegation_point ||
1131                                                 ldns_rr_list_type(rr_list) 
1132                                                         == LDNS_RR_TYPE_DS ||
1133                                                 ldns_rr_list_type(rr_list) 
1134                                                         == LDNS_RR_TYPE_NSEC ||
1135                                                 ldns_rr_list_type(rr_list) 
1136                                                         == LDNS_RR_TYPE_NSEC3) {
1137                                         siglist = ldns_sign_public(rr_list, key_list);
1138                                         for (i = 0; i < ldns_rr_list_rr_count(siglist); i++) {
1139                                                 if (cur_rrset->signatures) {
1140                                                         result = ldns_dnssec_rrs_add_rr(cur_rrset->signatures,
1141                                                                                            ldns_rr_list_rr(siglist,
1142                                                                                                                     i));
1143                                                 } else {
1144                                                         cur_rrset->signatures = ldns_dnssec_rrs_new();
1145                                                         cur_rrset->signatures->rr =
1146                                                                 ldns_rr_list_rr(siglist, i);
1147                                                 }
1148                                                 if (new_rrs) {
1149                                                         ldns_rr_list_push_rr(new_rrs,
1150                                                                                                  ldns_rr_list_rr(siglist,
1151                                                                                                                           i));
1152                                                 }
1153                                         }
1154                                         ldns_rr_list_free(siglist);
1155                                 }
1156
1157                                 ldns_rr_list_free(rr_list);
1158
1159                                 cur_rrset = cur_rrset->next;
1160                         }
1161
1162                         /* sign the nsec */
1163                         ldns_key_list_set_use(key_list, true);
1164                         cur_name->nsec_signatures =
1165                                 ldns_dnssec_remove_signatures(cur_name->nsec_signatures,
1166                                                                                 key_list,
1167                                                                                 func,
1168                                                                                 arg);
1169                         ldns_key_list_filter_for_non_dnskey(key_list);
1170
1171                         rr_list = ldns_rr_list_new();
1172                         ldns_rr_list_push_rr(rr_list, cur_name->nsec);
1173                         siglist = ldns_sign_public(rr_list, key_list);
1174
1175                         for (i = 0; i < ldns_rr_list_rr_count(siglist); i++) {
1176                                 if (cur_name->nsec_signatures) {
1177                                         result = ldns_dnssec_rrs_add_rr(cur_name->nsec_signatures,
1178                                                                            ldns_rr_list_rr(siglist, i));
1179                                 } else {
1180                                         cur_name->nsec_signatures = ldns_dnssec_rrs_new();
1181                                         cur_name->nsec_signatures->rr =
1182                                                 ldns_rr_list_rr(siglist, i);
1183                                 }
1184                                 if (new_rrs) {
1185                                         ldns_rr_list_push_rr(new_rrs,
1186                                                                  ldns_rr_list_rr(siglist, i));
1187                                 }
1188                         }
1189
1190                         ldns_rr_list_free(siglist);
1191                         ldns_rr_list_free(rr_list);
1192                 }
1193                 cur_node = ldns_rbtree_next(cur_node);
1194         }
1195
1196         ldns_rr_list_deep_free(pubkey_list);
1197         return result;
1198 }
1199
1200 ldns_status
1201 ldns_dnssec_zone_sign(ldns_dnssec_zone *zone,
1202                                   ldns_rr_list *new_rrs,
1203                                   ldns_key_list *key_list,
1204                                   int (*func)(ldns_rr *, void *),
1205                                   void *arg)
1206 {
1207         return ldns_dnssec_zone_sign_flg(zone, new_rrs, key_list, func, arg, 0);
1208 }
1209
1210 ldns_status
1211 ldns_dnssec_zone_sign_flg(ldns_dnssec_zone *zone,
1212                                   ldns_rr_list *new_rrs,
1213                                   ldns_key_list *key_list,
1214                                   int (*func)(ldns_rr *, void *),
1215                                   void *arg,
1216                                   int flags)
1217 {
1218         ldns_status result = LDNS_STATUS_OK;
1219
1220         if (!zone || !new_rrs || !key_list) {
1221                 return LDNS_STATUS_ERR;
1222         }
1223
1224         /* zone is already sorted */
1225         result = ldns_dnssec_zone_mark_glue(zone);
1226         if (result != LDNS_STATUS_OK) {
1227                 return result;
1228         }
1229
1230         /* check whether we need to add nsecs */
1231         if (zone->names && !((ldns_dnssec_name *)zone->names->root->data)->nsec) {
1232                 result = ldns_dnssec_zone_create_nsecs(zone, new_rrs);
1233                 if (result != LDNS_STATUS_OK) {
1234                         return result;
1235                 }
1236         }
1237
1238         result = ldns_dnssec_zone_create_rrsigs_flg(zone,
1239                                         new_rrs,
1240                                         key_list,
1241                                         func,
1242                                         arg,
1243                                         flags);
1244
1245         return result;
1246 }
1247
1248 ldns_status
1249 ldns_dnssec_zone_sign_nsec3(ldns_dnssec_zone *zone,
1250                                            ldns_rr_list *new_rrs,
1251                                            ldns_key_list *key_list,
1252                                            int (*func)(ldns_rr *, void *),
1253                                            void *arg,
1254                                            uint8_t algorithm,
1255                                            uint8_t flags,
1256                                            uint16_t iterations,
1257                                            uint8_t salt_length,
1258                                            uint8_t *salt)
1259 {
1260         return ldns_dnssec_zone_sign_nsec3_flg_mkmap(zone, new_rrs, key_list,
1261                 func, arg, algorithm, flags, iterations, salt_length, salt, 0,
1262                 NULL);
1263 }
1264
1265 ldns_status
1266 ldns_dnssec_zone_sign_nsec3_flg_mkmap(ldns_dnssec_zone *zone,
1267                 ldns_rr_list *new_rrs,
1268                 ldns_key_list *key_list,
1269                 int (*func)(ldns_rr *, void *),
1270                 void *arg,
1271                 uint8_t algorithm,
1272                 uint8_t flags,
1273                 uint16_t iterations,
1274                 uint8_t salt_length,
1275                 uint8_t *salt,
1276                 int signflags,
1277                 ldns_rbtree_t **map)
1278 {
1279         ldns_rr *nsec3, *nsec3param;
1280         ldns_status result = LDNS_STATUS_OK;
1281
1282         /* zone is already sorted */
1283         result = ldns_dnssec_zone_mark_glue(zone);
1284         if (result != LDNS_STATUS_OK) {
1285                 return result;
1286         }
1287
1288         /* TODO if there are already nsec3s presents and their
1289          * parameters are the same as these, we don't have to recreate
1290          */
1291         if (zone->names) {
1292                 /* add empty nonterminals */
1293                 result = ldns_dnssec_zone_add_empty_nonterminals(zone);
1294                 if (result != LDNS_STATUS_OK) {
1295                         return result;
1296                 }
1297
1298                 nsec3 = ((ldns_dnssec_name *)zone->names->root->data)->nsec;
1299                 if (nsec3 && ldns_rr_get_type(nsec3) == LDNS_RR_TYPE_NSEC3) {
1300                         /* no need to recreate */
1301                 } else {
1302                         if (!ldns_dnssec_zone_find_rrset(zone,
1303                                                                            zone->soa->name,
1304                                                                            LDNS_RR_TYPE_NSEC3PARAM)) {
1305                                 /* create and add the nsec3param rr */
1306                                 nsec3param =
1307                                         ldns_rr_new_frm_type(LDNS_RR_TYPE_NSEC3PARAM);
1308                                 ldns_rr_set_owner(nsec3param,
1309                                                            ldns_rdf_clone(zone->soa->name));
1310                                 ldns_nsec3_add_param_rdfs(nsec3param,
1311                                                                          algorithm,
1312                                                                          flags,
1313                                                                          iterations,
1314                                                                          salt_length,
1315                                                                          salt);
1316                                 /* always set bit 7 of the flags to zero, according to
1317                                  * rfc5155 section 11. The bits are counted from right to left,
1318                                  * so bit 7 in rfc5155 is bit 0 in ldns */
1319                                 ldns_set_bit(ldns_rdf_data(ldns_rr_rdf(nsec3param, 1)), 0, 0);
1320                                 result = ldns_dnssec_zone_add_rr(zone, nsec3param);
1321                                 if (result != LDNS_STATUS_OK) {
1322                                         return result;
1323                                 }
1324                                 ldns_rr_list_push_rr(new_rrs, nsec3param);
1325                         }
1326                         result = ldns_dnssec_zone_create_nsec3s_mkmap(zone,
1327                                                                                         new_rrs,
1328                                                                                         algorithm,
1329                                                                                         flags,
1330                                                                                         iterations,
1331                                                                                         salt_length,
1332                                                                                         salt,
1333                                                                                         map);
1334                         if (result != LDNS_STATUS_OK) {
1335                                 return result;
1336                         }
1337                 }
1338
1339                 result = ldns_dnssec_zone_create_rrsigs_flg(zone,
1340                                                 new_rrs,
1341                                                 key_list,
1342                                                 func,
1343                                                 arg,
1344                                                 signflags);
1345         }
1346
1347         return result;
1348 }
1349
1350 ldns_status
1351 ldns_dnssec_zone_sign_nsec3_flg(ldns_dnssec_zone *zone,
1352                 ldns_rr_list *new_rrs,
1353                 ldns_key_list *key_list,
1354                 int (*func)(ldns_rr *, void *),
1355                 void *arg,
1356                 uint8_t algorithm,
1357                 uint8_t flags,
1358                 uint16_t iterations,
1359                 uint8_t salt_length,
1360                 uint8_t *salt,
1361                 int signflags)
1362 {
1363         return ldns_dnssec_zone_sign_nsec3_flg_mkmap(zone, new_rrs, key_list,
1364                 func, arg, algorithm, flags, iterations, salt_length, salt,
1365                 signflags, NULL);
1366 }
1367
1368 ldns_zone *
1369 ldns_zone_sign(const ldns_zone *zone, ldns_key_list *key_list)
1370 {
1371         ldns_dnssec_zone *dnssec_zone;
1372         ldns_zone *signed_zone;
1373         ldns_rr_list *new_rrs;
1374         size_t i;
1375
1376         signed_zone = ldns_zone_new();
1377         dnssec_zone = ldns_dnssec_zone_new();
1378
1379         (void) ldns_dnssec_zone_add_rr(dnssec_zone, ldns_zone_soa(zone));
1380         ldns_zone_set_soa(signed_zone, ldns_rr_clone(ldns_zone_soa(zone)));
1381
1382         for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(zone)); i++) {
1383                 (void) ldns_dnssec_zone_add_rr(dnssec_zone,
1384                                                                  ldns_rr_list_rr(ldns_zone_rrs(zone),
1385                                                                                           i));
1386                 ldns_zone_push_rr(signed_zone,
1387                                            ldns_rr_clone(ldns_rr_list_rr(ldns_zone_rrs(zone),
1388                                                                                            i)));
1389         }
1390
1391         new_rrs = ldns_rr_list_new();
1392         (void) ldns_dnssec_zone_sign(dnssec_zone,
1393                                                     new_rrs,
1394                                                     key_list,
1395                                                     ldns_dnssec_default_replace_signatures,
1396                                                     NULL);
1397
1398         for (i = 0; i < ldns_rr_list_rr_count(new_rrs); i++) {
1399                 ldns_rr_list_push_rr(ldns_zone_rrs(signed_zone),
1400                                                  ldns_rr_clone(ldns_rr_list_rr(new_rrs, i)));
1401         }
1402
1403         ldns_rr_list_deep_free(new_rrs);
1404         ldns_dnssec_zone_free(dnssec_zone);
1405
1406         return signed_zone;
1407 }
1408
1409 ldns_zone *
1410 ldns_zone_sign_nsec3(ldns_zone *zone, ldns_key_list *key_list, uint8_t algorithm, uint8_t flags, uint16_t iterations, uint8_t salt_length, uint8_t *salt)
1411 {
1412         ldns_dnssec_zone *dnssec_zone;
1413         ldns_zone *signed_zone;
1414         ldns_rr_list *new_rrs;
1415         size_t i;
1416
1417         signed_zone = ldns_zone_new();
1418         dnssec_zone = ldns_dnssec_zone_new();
1419
1420         (void) ldns_dnssec_zone_add_rr(dnssec_zone, ldns_zone_soa(zone));
1421         ldns_zone_set_soa(signed_zone, ldns_rr_clone(ldns_zone_soa(zone)));
1422
1423         for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(zone)); i++) {
1424                 (void) ldns_dnssec_zone_add_rr(dnssec_zone,
1425                                                                  ldns_rr_list_rr(ldns_zone_rrs(zone),
1426                                                                                           i));
1427                 ldns_zone_push_rr(signed_zone, 
1428                                            ldns_rr_clone(ldns_rr_list_rr(ldns_zone_rrs(zone),
1429                                                                                            i)));
1430         }
1431
1432         new_rrs = ldns_rr_list_new();
1433         (void) ldns_dnssec_zone_sign_nsec3(dnssec_zone,
1434                                                                 new_rrs,
1435                                                                 key_list,
1436                                                                 ldns_dnssec_default_replace_signatures,
1437                                                                 NULL,
1438                                                                 algorithm,
1439                                                                 flags,
1440                                                                 iterations,
1441                                                                 salt_length,
1442                                                                 salt);
1443
1444         for (i = 0; i < ldns_rr_list_rr_count(new_rrs); i++) {
1445                 ldns_rr_list_push_rr(ldns_zone_rrs(signed_zone),
1446                                                  ldns_rr_clone(ldns_rr_list_rr(new_rrs, i)));
1447         }
1448
1449         ldns_rr_list_deep_free(new_rrs);
1450         ldns_dnssec_zone_free(dnssec_zone);
1451
1452         return signed_zone;
1453 }
1454 #endif /* HAVE_SSL */
1455
1456