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