Add APIC_ID to extract apic id from local apic id field
[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         
35         current_sig = ldns_rr_new_frm_type(LDNS_RR_TYPE_RRSIG);
36         
37         /* set the type on the new signature */
38         orig_ttl = ldns_rr_ttl(ldns_rr_list_rr(rrset, 0));
39         orig_class = ldns_rr_get_class(ldns_rr_list_rr(rrset, 0));
40
41         ldns_rr_set_ttl(current_sig, orig_ttl);
42         ldns_rr_set_class(current_sig, orig_class);
43         ldns_rr_set_owner(current_sig, 
44                           ldns_rdf_clone(
45                                ldns_rr_owner(
46                                     ldns_rr_list_rr(rrset,
47                                                     0))));
48
49         /* fill in what we know of the signature */
50         
51         /* set the orig_ttl */
52         (void)ldns_rr_rrsig_set_origttl(
53                    current_sig, 
54                    ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32,
55                                          orig_ttl));
56         /* the signers name */
57         (void)ldns_rr_rrsig_set_signame(
58                         current_sig, 
59                         ldns_rdf_clone(ldns_key_pubkey_owner(current_key)));
60         /* label count - get it from the first rr in the rr_list */
61         (void)ldns_rr_rrsig_set_labels(
62                         current_sig, 
63                         ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8,
64                                              label_count));
65         /* inception, expiration */
66         now = time(NULL);
67         if (ldns_key_inception(current_key) != 0) {
68                 (void)ldns_rr_rrsig_set_inception(
69                                 current_sig,
70                                 ldns_native2rdf_int32(
71                                     LDNS_RDF_TYPE_TIME, 
72                                     ldns_key_inception(current_key)));
73         } else {
74                 (void)ldns_rr_rrsig_set_inception(
75                                 current_sig,
76                                 ldns_native2rdf_int32(LDNS_RDF_TYPE_TIME, now));
77         }
78         if (ldns_key_expiration(current_key) != 0) {
79                 (void)ldns_rr_rrsig_set_expiration(
80                                 current_sig,
81                                 ldns_native2rdf_int32(
82                                     LDNS_RDF_TYPE_TIME, 
83                                     ldns_key_expiration(current_key)));
84         } else {
85                 (void)ldns_rr_rrsig_set_expiration(
86                              current_sig,
87                                 ldns_native2rdf_int32(
88                                     LDNS_RDF_TYPE_TIME, 
89                                     now + LDNS_DEFAULT_EXP_TIME));
90         }
91
92         (void)ldns_rr_rrsig_set_keytag(
93                    current_sig,
94                    ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, 
95                                          ldns_key_keytag(current_key)));
96
97         (void)ldns_rr_rrsig_set_algorithm(
98                         current_sig,
99                         ldns_native2rdf_int8(
100                             LDNS_RDF_TYPE_ALG, 
101                             ldns_key_algorithm(current_key)));
102
103         (void)ldns_rr_rrsig_set_typecovered(
104                         current_sig,
105                         ldns_native2rdf_int16(
106                             LDNS_RDF_TYPE_TYPE,
107                             ldns_rr_get_type(ldns_rr_list_rr(rrset,
108                                                              0))));
109         return current_sig;
110 }
111
112 #ifdef HAVE_SSL
113 ldns_rdf *
114 ldns_sign_public_buffer(ldns_buffer *sign_buf, ldns_key *current_key)
115 {
116         ldns_rdf *b64rdf = NULL;
117
118         switch(ldns_key_algorithm(current_key)) {
119         case LDNS_SIGN_DSA:
120         case LDNS_DSA_NSEC3:
121                 b64rdf = ldns_sign_public_evp(
122                                    sign_buf,
123                                    ldns_key_evp_key(current_key),
124                                    EVP_dss1());
125                 break;
126         case LDNS_SIGN_RSASHA1:
127         case LDNS_SIGN_RSASHA1_NSEC3:
128                 b64rdf = ldns_sign_public_evp(
129                                    sign_buf,
130                                    ldns_key_evp_key(current_key),
131                                    EVP_sha1());
132                 break;
133 #ifdef USE_SHA2
134         case LDNS_SIGN_RSASHA256:
135                 b64rdf = ldns_sign_public_evp(
136                                    sign_buf,
137                                    ldns_key_evp_key(current_key),
138                                    EVP_sha256());
139                 break;
140         case LDNS_SIGN_RSASHA512:
141                 b64rdf = ldns_sign_public_evp(
142                                    sign_buf,
143                                    ldns_key_evp_key(current_key),
144                                    EVP_sha512());
145                 break;
146 #endif /* USE_SHA2 */
147 #ifdef USE_GOST
148         case LDNS_SIGN_GOST:
149                 b64rdf = ldns_sign_public_evp(
150                                    sign_buf,
151                                    ldns_key_evp_key(current_key),
152                                    EVP_get_digestbyname("md_gost94"));
153                 break;
154 #endif /* USE_GOST */
155         case LDNS_SIGN_RSAMD5:
156                 b64rdf = ldns_sign_public_evp(
157                                    sign_buf,
158                                    ldns_key_evp_key(current_key),
159                                    EVP_md5());
160                 break;
161         default:
162                 /* do _you_ know this alg? */
163                 printf("unknown algorithm, ");
164                 printf("is the one used available on this system?\n");
165                 break;
166         }
167         
168         return b64rdf;
169 }
170
171 /**
172  * use this function to sign with a public/private key alg
173  * return the created signatures
174  */
175 ldns_rr_list *
176 ldns_sign_public(ldns_rr_list *rrset, ldns_key_list *keys)
177 {
178         ldns_rr_list *signatures;
179         ldns_rr_list *rrset_clone;
180         ldns_rr *current_sig;
181         ldns_rdf *b64rdf;
182         ldns_key *current_key;
183         size_t key_count;
184         uint16_t i;
185         ldns_buffer *sign_buf;
186         ldns_rdf *new_owner;
187
188         if (!rrset || ldns_rr_list_rr_count(rrset) < 1 || !keys) {
189                 return NULL;
190         }
191         
192         new_owner = NULL;
193
194         key_count = 0;
195         signatures = ldns_rr_list_new();
196
197         /* prepare a signature and add all the know data
198          * prepare the rrset. Sign this together.  */
199         rrset_clone = ldns_rr_list_clone(rrset);
200         if (!rrset_clone) {
201                 return NULL;
202         }
203
204         /* make it canonical */
205         for(i = 0; i < ldns_rr_list_rr_count(rrset_clone); i++) {
206                 ldns_rr_set_ttl(ldns_rr_list_rr(rrset_clone, i), 
207                         ldns_rr_ttl(ldns_rr_list_rr(rrset, 0)));
208                 ldns_rr2canonical(ldns_rr_list_rr(rrset_clone, i));
209         }
210         /* sort */
211         ldns_rr_list_sort(rrset_clone);
212         
213         for (key_count = 0;
214                 key_count < ldns_key_list_key_count(keys);
215                 key_count++) {
216                 if (!ldns_key_use(ldns_key_list_key(keys, key_count))) {
217                         continue;
218                 }
219                 sign_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN);
220                 if (!sign_buf) {
221                         ldns_rr_list_free(rrset_clone);
222                         ldns_rr_list_free(signatures);
223                         ldns_rdf_free(new_owner);
224                         return NULL;
225                 }
226                 b64rdf = NULL;
227
228                 current_key = ldns_key_list_key(keys, key_count);
229                 /* sign all RRs with keys that have ZSKbit, !SEPbit.
230                    sign DNSKEY RRs with keys that have ZSKbit&SEPbit */
231                 if (
232                     ldns_key_flags(current_key) & LDNS_KEY_ZONE_KEY &&
233                     (!(ldns_key_flags(current_key) & LDNS_KEY_SEP_KEY)
234                         || ldns_rr_get_type(ldns_rr_list_rr(rrset, 0))
235                         == LDNS_RR_TYPE_DNSKEY)
236                     ) {
237                         current_sig = ldns_create_empty_rrsig(rrset_clone,
238                                                               current_key);
239
240                         /* right now, we have: a key, a semi-sig and an rrset. For
241                          * which we can create the sig and base64 encode that and
242                          * add that to the signature */
243
244                         if (ldns_rrsig2buffer_wire(sign_buf, current_sig)
245                             != LDNS_STATUS_OK) {
246                                 ldns_buffer_free(sign_buf);
247                                 /* ERROR */
248                                 ldns_rr_list_deep_free(rrset_clone);
249                                 return NULL;
250                         }
251
252                         /* add the rrset in sign_buf */
253                         if (ldns_rr_list2buffer_wire(sign_buf, rrset_clone)
254                             != LDNS_STATUS_OK) {
255                                 ldns_buffer_free(sign_buf);
256                                 ldns_rr_list_deep_free(rrset_clone);
257                                 return NULL;
258                         }
259
260                         b64rdf = ldns_sign_public_buffer(sign_buf, current_key);
261
262                         if (!b64rdf) {
263                                 /* signing went wrong */
264                                 ldns_rr_list_deep_free(rrset_clone);
265                                 return NULL;
266                         }
267
268                         ldns_rr_rrsig_set_sig(current_sig, b64rdf);
269
270                         /* push the signature to the signatures list */
271                         ldns_rr_list_push_rr(signatures, current_sig);
272                 }
273                 ldns_buffer_free(sign_buf); /* restart for the next key */
274         }
275         ldns_rr_list_deep_free(rrset_clone);
276
277         return signatures;
278 }
279
280 /**
281  * Sign data with DSA
282  *
283  * \param[in] to_sign The ldns_buffer containing raw data that is
284  *                    to be signed
285  * \param[in] key The DSA key structure to sign with
286  * \return ldns_rdf for the RRSIG ldns_rr
287  */
288 ldns_rdf *
289 ldns_sign_public_dsa(ldns_buffer *to_sign, DSA *key)
290 {
291         unsigned char *sha1_hash;
292         ldns_rdf *sigdata_rdf;
293         ldns_buffer *b64sig;
294
295         DSA_SIG *sig;
296         uint8_t *data;
297         size_t pad;
298
299         b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN);
300         if (!b64sig) {
301                 return NULL;
302         }
303         
304         sha1_hash = SHA1((unsigned char*)ldns_buffer_begin(to_sign),
305                                   ldns_buffer_position(to_sign), NULL);
306         if (!sha1_hash) {
307                 ldns_buffer_free(b64sig);
308                 return NULL;
309         }
310
311
312         sig = DSA_do_sign(sha1_hash, SHA_DIGEST_LENGTH, key);
313
314         data = LDNS_XMALLOC(uint8_t, 1 + 2 * SHA_DIGEST_LENGTH);
315
316         data[0] = 1;
317         pad = 20 - (size_t) BN_num_bytes(sig->r);
318         if (pad > 0) {
319                 memset(data + 1, 0, pad);
320         }
321         BN_bn2bin(sig->r, (unsigned char *) (data + 1) + pad);
322
323         pad = 20 - (size_t) BN_num_bytes(sig->s);
324         if (pad > 0) {
325                 memset(data + 1 + SHA_DIGEST_LENGTH, 0, pad);
326         }
327         BN_bn2bin(sig->s, (unsigned char *) (data + 1 + SHA_DIGEST_LENGTH + pad));
328
329         sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64,
330                                                                  1 + 2 * SHA_DIGEST_LENGTH,
331                                                                  data);
332
333         ldns_buffer_free(b64sig);
334         LDNS_FREE(data);
335
336         return sigdata_rdf;
337 }
338
339 ldns_rdf *
340 ldns_sign_public_evp(ldns_buffer *to_sign,
341                                  EVP_PKEY *key,
342                                  const EVP_MD *digest_type)
343 {
344         unsigned int siglen;
345         ldns_rdf *sigdata_rdf;
346         ldns_buffer *b64sig;
347         EVP_MD_CTX ctx;
348         const EVP_MD *md_type;
349         int r;
350
351         siglen = 0;
352         b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN);
353         if (!b64sig) {
354                 return NULL;
355         }
356
357         /* initializes a signing context */
358         md_type = digest_type;
359         if(!md_type) {
360                 /* unknown message difest */
361                 ldns_buffer_free(b64sig);
362                 return NULL;
363         }
364
365         EVP_MD_CTX_init(&ctx);
366         r = EVP_SignInit(&ctx, md_type);
367         if(r == 1) {
368                 r = EVP_SignUpdate(&ctx, (unsigned char*)
369                                             ldns_buffer_begin(to_sign), 
370                                             ldns_buffer_position(to_sign));
371         } else {
372                 ldns_buffer_free(b64sig);
373                 return NULL;
374         }
375         if(r == 1) {
376                 r = EVP_SignFinal(&ctx, (unsigned char*)
377                                            ldns_buffer_begin(b64sig), &siglen, key);
378         } else {
379                 ldns_buffer_free(b64sig);
380                 return NULL;
381         }
382         if(r != 1) {
383                 ldns_buffer_free(b64sig);
384                 return NULL;
385         }
386
387         /* unfortunately, OpenSSL output is differenct from DNS DSA format */
388         if (EVP_PKEY_type(key->type) == EVP_PKEY_DSA) {
389                 sigdata_rdf = ldns_convert_dsa_rrsig_asn12rdf(b64sig, siglen);
390         } else {
391                 /* ok output for other types is the same */
392                 sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, siglen,
393                                                                          ldns_buffer_begin(b64sig));
394         }
395         ldns_buffer_free(b64sig);
396         EVP_MD_CTX_cleanup(&ctx);
397         return sigdata_rdf;
398 }
399
400 ldns_rdf *
401 ldns_sign_public_rsasha1(ldns_buffer *to_sign, RSA *key)
402 {
403         unsigned char *sha1_hash;
404         unsigned int siglen;
405         ldns_rdf *sigdata_rdf;
406         ldns_buffer *b64sig;
407         int result;
408
409         siglen = 0;
410         b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN);
411         if (!b64sig) {
412                 return NULL;
413         }
414
415         sha1_hash = SHA1((unsigned char*)ldns_buffer_begin(to_sign),
416                                   ldns_buffer_position(to_sign), NULL);
417         if (!sha1_hash) {
418                 ldns_buffer_free(b64sig);
419                 return NULL;
420         }
421
422         result = RSA_sign(NID_sha1, sha1_hash, SHA_DIGEST_LENGTH,
423                                    (unsigned char*)ldns_buffer_begin(b64sig),
424                                    &siglen, key);
425         if (result != 1) {
426                 return NULL;
427         }
428
429         if (result != 1) {
430                 return NULL;
431         }
432
433         sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, siglen, 
434                                                                  ldns_buffer_begin(b64sig));
435         ldns_buffer_free(b64sig); /* can't free this buffer ?? */
436         return sigdata_rdf;
437 }
438
439 ldns_rdf *
440 ldns_sign_public_rsamd5(ldns_buffer *to_sign, RSA *key)
441 {
442         unsigned char *md5_hash;
443         unsigned int siglen;
444         ldns_rdf *sigdata_rdf;
445         ldns_buffer *b64sig;
446
447         b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN);
448         if (!b64sig) {
449                 return NULL;
450         }
451         
452         md5_hash = MD5((unsigned char*)ldns_buffer_begin(to_sign),
453                                 ldns_buffer_position(to_sign), NULL);
454         if (!md5_hash) {
455                 ldns_buffer_free(b64sig);
456                 return NULL;
457         }
458
459         RSA_sign(NID_md5, md5_hash, MD5_DIGEST_LENGTH,
460                     (unsigned char*)ldns_buffer_begin(b64sig),
461                     &siglen, key);
462
463         sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, siglen, 
464                                                                  ldns_buffer_begin(b64sig));
465         ldns_buffer_free(b64sig);
466         return sigdata_rdf;
467 }
468 #endif /* HAVE_SSL */
469
470 static int
471 ldns_dnssec_name_has_only_a(ldns_dnssec_name *cur_name)
472 {
473         ldns_dnssec_rrsets *cur_rrset;
474         cur_rrset = cur_name->rrsets;
475         while (cur_rrset) {
476                 if (cur_rrset->type != LDNS_RR_TYPE_A &&
477                         cur_rrset->type != LDNS_RR_TYPE_AAAA) {
478                         return 0;
479                 } else {
480                         cur_rrset = cur_rrset->next;
481                 }
482         }
483         return 1;
484 }
485
486 ldns_status
487 ldns_dnssec_zone_mark_glue(ldns_dnssec_zone *zone)
488 {
489         ldns_rbnode_t *cur_node;
490         ldns_dnssec_name *cur_name;
491         ldns_rdf *cur_owner, *cur_parent;
492
493         cur_node = ldns_rbtree_first(zone->names);
494         while (cur_node != LDNS_RBTREE_NULL) {
495                 cur_name = (ldns_dnssec_name *) cur_node->data;
496                 cur_node = ldns_rbtree_next(cur_node);
497                 if (ldns_dnssec_name_has_only_a(cur_name)) {
498                         /* assume glue XXX check for zone cur */
499                         cur_owner = ldns_rdf_clone(ldns_rr_owner(
500                                               cur_name->rrsets->rrs->rr));
501                         while (ldns_dname_label_count(cur_owner) >
502                                   ldns_dname_label_count(zone->soa->name)) {
503                                 if (ldns_dnssec_zone_find_rrset(zone,
504                                                                                   cur_owner,
505                                                                                   LDNS_RR_TYPE_NS)) {
506                                         /*
507                                         fprintf(stderr, "[XX] Marking as glue: ");
508                                         ldns_rdf_print(stderr, cur_name->name);
509                                         fprintf(stderr, "\n");
510                                         */
511                                         cur_name->is_glue = true;
512                                 }
513                                 cur_parent = ldns_dname_left_chop(cur_owner);
514                                 ldns_rdf_deep_free(cur_owner);
515                                 cur_owner = cur_parent;
516                         }
517                         ldns_rdf_deep_free(cur_owner);
518                 }
519         }
520         return LDNS_STATUS_OK;
521 }
522
523 ldns_rbnode_t *
524 ldns_dnssec_name_node_next_nonglue(ldns_rbnode_t *node)
525 {
526         ldns_rbnode_t *next_node = NULL;
527         ldns_dnssec_name *next_name = NULL;
528         bool done = false;
529
530         if (node == LDNS_RBTREE_NULL) {
531                 return NULL;
532         }
533         next_node = node;
534         while (!done) {
535                 if (next_node == LDNS_RBTREE_NULL) {
536                         return NULL;
537                 } else {
538                         next_name = (ldns_dnssec_name *)next_node->data;
539                         if (!next_name->is_glue) {
540                                 done = true;
541                         } else {
542                                 next_node = ldns_rbtree_next(next_node);
543                         }
544                 }
545         }
546         return next_node;
547 }
548
549 ldns_status
550 ldns_dnssec_zone_create_nsecs(ldns_dnssec_zone *zone,
551                               ldns_rr_list *new_rrs)
552 {
553
554         ldns_rbnode_t *first_node, *cur_node, *next_node;
555         ldns_dnssec_name *cur_name, *next_name;
556         ldns_rr *nsec_rr;
557         uint32_t nsec_ttl;
558         ldns_dnssec_rrsets *soa;
559         
560         /* the TTL of NSEC rrs should be set to the minimum TTL of
561          * the zone SOA (RFC4035 Section 2.3)
562          */
563         soa = ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_SOA);
564         
565         /* did the caller actually set it? if not,
566          * fall back to default ttl
567          */
568         if (soa && soa->rrs && soa->rrs->rr) {
569                 nsec_ttl = ldns_rdf2native_int32(ldns_rr_rdf(
570                                                      soa->rrs->rr, 6));
571         } else {
572                 nsec_ttl = LDNS_DEFAULT_TTL;
573         }
574         
575         first_node = ldns_dnssec_name_node_next_nonglue(
576                                ldns_rbtree_first(zone->names));
577         cur_node = first_node;
578         if (cur_node) {
579                 next_node = ldns_dnssec_name_node_next_nonglue(
580                                    ldns_rbtree_next(cur_node));
581         } else {
582                 next_node = NULL;
583         }
584
585         while (cur_node && next_node) {
586                 cur_name = (ldns_dnssec_name *)cur_node->data;
587                 next_name = (ldns_dnssec_name *)next_node->data;
588                 nsec_rr = ldns_dnssec_create_nsec(cur_name,
589                                                   next_name,
590                                                   LDNS_RR_TYPE_NSEC);
591                 ldns_rr_set_ttl(nsec_rr, nsec_ttl);
592                 ldns_dnssec_name_add_rr(cur_name, nsec_rr);
593                 ldns_rr_list_push_rr(new_rrs, nsec_rr);
594                 cur_node = next_node;
595                 if (cur_node) {
596                         next_node = ldns_dnssec_name_node_next_nonglue(
597                                ldns_rbtree_next(cur_node));
598                 }
599         }
600
601         if (cur_node && !next_node) {
602                 cur_name = (ldns_dnssec_name *)cur_node->data;
603                 next_name = (ldns_dnssec_name *)first_node->data;
604                 nsec_rr = ldns_dnssec_create_nsec(cur_name,
605                                                   next_name,
606                                                   LDNS_RR_TYPE_NSEC);
607                 ldns_rr_set_ttl(nsec_rr, nsec_ttl);
608                 ldns_dnssec_name_add_rr(cur_name, nsec_rr);
609                 ldns_rr_list_push_rr(new_rrs, nsec_rr);
610         } else {
611                 printf("error\n");
612         }
613
614         return LDNS_STATUS_OK;
615 }
616
617 #ifdef HAVE_SSL
618 ldns_status
619 ldns_dnssec_zone_create_nsec3s(ldns_dnssec_zone *zone,
620                                                  ldns_rr_list *new_rrs,
621                                                  uint8_t algorithm,
622                                                  uint8_t flags,
623                                                  uint16_t iterations,
624                                                  uint8_t salt_length,
625                                                  uint8_t *salt)
626 {
627         ldns_rbnode_t *first_name_node;
628         ldns_rbnode_t *current_name_node;
629         ldns_dnssec_name *current_name;
630         ldns_status result = LDNS_STATUS_OK;
631         ldns_rr *nsec_rr;
632         ldns_rr_list *nsec3_list;
633         uint32_t nsec_ttl;
634         ldns_dnssec_rrsets *soa;
635         
636         if (!zone || !new_rrs || !zone->names) {
637                 return LDNS_STATUS_ERR;
638         }
639         
640         /* the TTL of NSEC rrs should be set to the minimum TTL of
641          * the zone SOA (RFC4035 Section 2.3)
642          */
643         soa = ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_SOA);
644         
645         /* did the caller actually set it? if not,
646          * fall back to default ttl
647          */
648         if (soa && soa->rrs && soa->rrs->rr) {
649                 nsec_ttl = ldns_rdf2native_int32(ldns_rr_rdf(
650                                                      soa->rrs->rr, 6));
651         } else {
652                 nsec_ttl = LDNS_DEFAULT_TTL;
653         }
654
655         nsec3_list = ldns_rr_list_new();
656
657         first_name_node = ldns_dnssec_name_node_next_nonglue(
658                                           ldns_rbtree_first(zone->names));
659         
660         current_name_node = first_name_node;
661
662         while (current_name_node &&
663                current_name_node != LDNS_RBTREE_NULL) {
664                 current_name = (ldns_dnssec_name *) current_name_node->data;
665                 nsec_rr = ldns_dnssec_create_nsec3(current_name,
666                                                    NULL,
667                                                    zone->soa->name,
668                                                    algorithm,
669                                                    flags,
670                                                    iterations,
671                                                    salt_length,
672                                                    salt);
673                 /* by default, our nsec based generator adds rrsigs
674                  * remove the bitmap for empty nonterminals */
675                 if (!current_name->rrsets) {
676                         ldns_rdf_deep_free(ldns_rr_pop_rdf(nsec_rr));
677                 }
678                 ldns_rr_set_ttl(nsec_rr, nsec_ttl);
679                 ldns_dnssec_name_add_rr(current_name, nsec_rr);
680                 ldns_rr_list_push_rr(new_rrs, nsec_rr);
681                 ldns_rr_list_push_rr(nsec3_list, nsec_rr);
682                 current_name_node = ldns_dnssec_name_node_next_nonglue(
683                                    ldns_rbtree_next(current_name_node));
684         }
685
686         ldns_rr_list_sort_nsec3(nsec3_list);
687         ldns_dnssec_chain_nsec3_list(nsec3_list);
688         if (result != LDNS_STATUS_OK) {
689                 return result;
690         }
691         
692         ldns_rr_list_free(nsec3_list);
693         return result;
694 }
695 #endif /* HAVE_SSL */
696
697 ldns_dnssec_rrs *
698 ldns_dnssec_remove_signatures(ldns_dnssec_rrs *signatures,
699                                                 ldns_key_list *key_list,
700                                                 int (*func)(ldns_rr *, void *),
701                                                 void *arg)
702 {
703         ldns_dnssec_rrs *base_rrs = signatures;
704         ldns_dnssec_rrs *cur_rr = base_rrs;
705         ldns_dnssec_rrs *prev_rr = NULL;
706         ldns_dnssec_rrs *next_rr;
707
708         uint16_t keytag;
709         size_t i;
710         int v;
711
712         key_list = key_list;
713
714         if (!cur_rr) {
715                 switch(func(NULL, arg)) {
716                 case LDNS_SIGNATURE_LEAVE_ADD_NEW:
717                 case LDNS_SIGNATURE_REMOVE_ADD_NEW:
718                 break;
719                 case LDNS_SIGNATURE_LEAVE_NO_ADD:
720                 case LDNS_SIGNATURE_REMOVE_NO_ADD:
721                 ldns_key_list_set_use(key_list, false);
722                 break;
723                 default:
724                         fprintf(stderr, "[XX] unknown return value from callback\n");
725                         break;
726                 }
727                 return NULL;
728         }
729         v = func(cur_rr->rr, arg);
730
731         while (cur_rr) {
732                 next_rr = cur_rr->next;
733                 
734                 switch (func(cur_rr->rr, arg)) {
735                 case  LDNS_SIGNATURE_LEAVE_ADD_NEW:
736                         prev_rr = cur_rr;
737                         break;
738                 case LDNS_SIGNATURE_LEAVE_NO_ADD:
739                         keytag = ldns_rdf2native_int16(
740                                            ldns_rr_rrsig_keytag(cur_rr->rr));
741                         for (i = 0; i < ldns_key_list_key_count(key_list); i++) {
742                                 if (ldns_key_keytag(ldns_key_list_key(key_list, i)) ==
743                                     keytag) {
744                                         ldns_key_set_use(ldns_key_list_key(key_list, i),
745                                                                   false);
746                                 }
747                         }
748                         prev_rr = cur_rr;
749                         break;
750                 case LDNS_SIGNATURE_REMOVE_NO_ADD:
751                         keytag = ldns_rdf2native_int16(
752                                            ldns_rr_rrsig_keytag(cur_rr->rr));
753                         for (i = 0; i < ldns_key_list_key_count(key_list); i++) {
754                                 if (ldns_key_keytag(ldns_key_list_key(key_list, i))
755                                     == keytag) {
756                                         ldns_key_set_use(ldns_key_list_key(key_list, i),
757                                                                   false);
758                                 }
759                         }
760                         if (prev_rr) {
761                                 prev_rr->next = next_rr;
762                         } else {
763                                 base_rrs = next_rr;
764                         }
765                         LDNS_FREE(cur_rr);
766                         break;
767                 case LDNS_SIGNATURE_REMOVE_ADD_NEW:
768                         if (prev_rr) {
769                                 prev_rr->next = next_rr;
770                         } else {
771                                 base_rrs = next_rr;
772                         }
773                         LDNS_FREE(cur_rr);
774                         break;
775                 default:
776                         fprintf(stderr, "[XX] unknown return value from callback\n");
777                         break;
778                 }
779                 cur_rr = next_rr;
780         }
781
782         return base_rrs;
783 }
784
785 #ifdef HAVE_SSL
786 ldns_status
787 ldns_dnssec_zone_create_rrsigs(ldns_dnssec_zone *zone,
788                                ldns_rr_list *new_rrs,
789                                ldns_key_list *key_list,
790                                int (*func)(ldns_rr *, void*),
791                                void *arg)
792 {
793         return ldns_dnssec_zone_create_rrsigs_flg(zone, new_rrs, key_list, 
794                 func, arg, 0);
795 }
796
797 /** If there are KSKs use only them and mark ZSKs unused */
798 static void
799 ldns_key_list_filter_for_dnskey(ldns_key_list *key_list)
800 {
801         int saw_ksk = 0;
802         size_t i;
803         for(i=0; i<ldns_key_list_key_count(key_list); i++)
804                 if((ldns_key_flags(ldns_key_list_key(key_list, i))&LDNS_KEY_SEP_KEY)) {
805                         saw_ksk = 1;
806                         break;
807                 }
808         if(!saw_ksk)
809                 return;
810         for(i=0; i<ldns_key_list_key_count(key_list); i++)
811                 if(!(ldns_key_flags(ldns_key_list_key(key_list, i))&LDNS_KEY_SEP_KEY))
812                         ldns_key_set_use(ldns_key_list_key(key_list, i), 0);
813 }
814
815 ldns_status
816 ldns_dnssec_zone_create_rrsigs_flg(ldns_dnssec_zone *zone,
817                                ldns_rr_list *new_rrs,
818                                ldns_key_list *key_list,
819                                int (*func)(ldns_rr *, void*),
820                                void *arg,
821                                int flags)
822 {
823         ldns_status result = LDNS_STATUS_OK;
824
825         ldns_rbnode_t *cur_node;
826         ldns_rr_list *rr_list;
827
828         ldns_dnssec_name *cur_name;
829         ldns_dnssec_rrsets *cur_rrset;
830         ldns_dnssec_rrs *cur_rr;
831
832         ldns_rr_list *siglist;
833         
834         size_t i;
835
836         ldns_rr_list *pubkey_list = ldns_rr_list_new();
837         zone = zone;
838         new_rrs = new_rrs;
839         key_list = key_list;
840         for (i = 0; i<ldns_key_list_key_count(key_list); i++) {
841                 ldns_rr_list_push_rr(pubkey_list,
842                                                  ldns_key2rr(ldns_key_list_key(key_list, i)));
843         }
844         /* TODO: callback to see is list should be signed */
845         /* TODO: remove 'old' signatures from signature list */
846         cur_node = ldns_rbtree_first(zone->names);
847         while (cur_node != LDNS_RBTREE_NULL) {
848                 cur_name = (ldns_dnssec_name *) cur_node->data;
849
850                 if (!cur_name->is_glue) {
851                         cur_rrset = cur_name->rrsets;
852                         while (cur_rrset) {
853                                 /* reset keys to use */
854                                 ldns_key_list_set_use(key_list, true);
855                                 
856                                 /* walk through old sigs, remove the old,
857                                    and mark which keys (not) to use) */
858                                 cur_rrset->signatures =
859                                         ldns_dnssec_remove_signatures(cur_rrset->signatures,
860                                                                                         key_list,
861                                                                                         func,
862                                                                                         arg);
863                                 if(!(flags&LDNS_SIGN_DNSKEY_WITH_ZSK) &&
864                                         cur_rrset->type == LDNS_RR_TYPE_DNSKEY)
865                                         ldns_key_list_filter_for_dnskey(key_list);
866                                 
867                                 /* TODO: just set count to zero? */
868                                 rr_list = ldns_rr_list_new();
869                                 
870                                 cur_rr = cur_rrset->rrs;
871                                 while (cur_rr) {
872                                         ldns_rr_list_push_rr(rr_list, cur_rr->rr);
873                                         cur_rr = cur_rr->next;
874                                 }
875                                 
876                                 /* only sign non-delegation RRsets */
877                                 /* (glue should have been marked earlier) */
878                                 if ((ldns_rr_list_type(rr_list) != LDNS_RR_TYPE_NS ||
879                                         ldns_dname_compare(ldns_rr_list_owner(rr_list),
880                                         zone->soa->name) == 0) &&
881                                         /* OK, there is also the possibility that the record
882                                          * is glue, but at the same owner name as other records that
883                                          * are not NS nor A/AAAA. Bleh, our current data structure
884                                          * doesn't really support that... */
885                                         !((ldns_rr_list_type(rr_list) == LDNS_RR_TYPE_A ||
886                                          ldns_rr_list_type(rr_list) == LDNS_RR_TYPE_AAAA) &&
887                                          !ldns_dname_compare(ldns_rr_list_owner(rr_list), zone->soa->name) == 0 &&
888                                          ldns_dnssec_zone_find_rrset(zone, ldns_rr_list_owner(rr_list), LDNS_RR_TYPE_NS)
889                                          )) {
890
891                                         siglist = ldns_sign_public(rr_list, key_list);
892                                         for (i = 0; i < ldns_rr_list_rr_count(siglist); i++) {
893                                                 if (cur_rrset->signatures) {
894                                                         ldns_dnssec_rrs_add_rr(cur_rrset->signatures,
895                                                                                            ldns_rr_list_rr(siglist,
896                                                                                                                     i));
897                                                 } else {
898                                                         cur_rrset->signatures = ldns_dnssec_rrs_new();
899                                                         cur_rrset->signatures->rr =
900                                                                 ldns_rr_list_rr(siglist, i);
901                                                         ldns_rr_list_push_rr(new_rrs,
902                                                                                          ldns_rr_list_rr(siglist,
903                                                                                                                   i));
904                                                 }
905                                         }
906                                         ldns_rr_list_free(siglist);
907                                 }
908                                 
909                                 ldns_rr_list_free(rr_list);
910                                 
911                                 cur_rrset = cur_rrset->next;
912                         }
913                         
914                         /* sign the nsec */
915                         cur_name->nsec_signatures =
916                                 ldns_dnssec_remove_signatures(cur_name->nsec_signatures,
917                                                                                 key_list,
918                                                                                 func,
919                                                                                 arg);
920                         
921                         rr_list = ldns_rr_list_new();
922                         ldns_rr_list_push_rr(rr_list, cur_name->nsec);
923                         siglist = ldns_sign_public(rr_list, key_list);
924                         
925                         for (i = 0; i < ldns_rr_list_rr_count(siglist); i++) {
926                                 if (cur_name->nsec_signatures) {
927                                         ldns_dnssec_rrs_add_rr(cur_name->nsec_signatures,
928                                                                            ldns_rr_list_rr(siglist, i));
929                                 } else {
930                                         cur_name->nsec_signatures = ldns_dnssec_rrs_new();
931                                         cur_name->nsec_signatures->rr =
932                                                 ldns_rr_list_rr(siglist, i);
933                                         ldns_rr_list_push_rr(new_rrs,
934                                                                          ldns_rr_list_rr(siglist, i));
935                                 }
936                         }
937                         
938                         ldns_rr_list_free(siglist);
939                         ldns_rr_list_free(rr_list);
940                 }
941                 cur_node = ldns_rbtree_next(cur_node);
942         }
943
944         ldns_rr_list_deep_free(pubkey_list);
945         return result;
946 }
947
948 ldns_status
949 ldns_dnssec_zone_sign(ldns_dnssec_zone *zone,
950                                   ldns_rr_list *new_rrs,
951                                   ldns_key_list *key_list,
952                                   int (*func)(ldns_rr *, void *),
953                                   void *arg)
954 {
955         return ldns_dnssec_zone_sign_flg(zone, new_rrs, key_list, func, arg, 0);
956 }
957
958 ldns_status
959 ldns_dnssec_zone_sign_flg(ldns_dnssec_zone *zone,
960                                   ldns_rr_list *new_rrs,
961                                   ldns_key_list *key_list,
962                                   int (*func)(ldns_rr *, void *),
963                                   void *arg,
964                                   int flags)
965 {
966         ldns_status result = LDNS_STATUS_OK;
967
968         if (!zone || !new_rrs || !key_list) {
969                 return LDNS_STATUS_ERR;
970         }
971
972         /* zone is already sorted */
973         ldns_dnssec_zone_mark_glue(zone);
974         
975         /* check whether we need to add nsecs */
976         if (zone->names && !((ldns_dnssec_name *)zone->names->root->data)->nsec) {
977                 result = ldns_dnssec_zone_create_nsecs(zone, new_rrs);
978                 if (result != LDNS_STATUS_OK) {
979                         return result;
980                 }
981         }
982
983         result = ldns_dnssec_zone_create_rrsigs_flg(zone,
984                                         new_rrs,
985                                         key_list,
986                                         func,
987                                         arg,
988                                         flags);
989
990         return result;
991 }
992
993 ldns_status
994 ldns_dnssec_zone_sign_nsec3(ldns_dnssec_zone *zone,
995                                            ldns_rr_list *new_rrs,
996                                            ldns_key_list *key_list,
997                                            int (*func)(ldns_rr *, void *),
998                                            void *arg,
999                                            uint8_t algorithm,
1000                                            uint8_t flags,
1001                                            uint16_t iterations,
1002                                            uint8_t salt_length,
1003                                            uint8_t *salt)
1004 {
1005         return ldns_dnssec_zone_sign_nsec3_flg(zone, new_rrs, key_list,
1006                 func, arg, algorithm, flags, iterations, salt_length, salt, 0);
1007 }
1008
1009 ldns_status
1010 ldns_dnssec_zone_sign_nsec3_flg(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                                            uint8_t algorithm,
1016                                            uint8_t flags,
1017                                            uint16_t iterations,
1018                                            uint8_t salt_length,
1019                                            uint8_t *salt,
1020                                            int signflags)
1021 {
1022         ldns_rr *nsec3, *nsec3params;
1023         ldns_status result = LDNS_STATUS_OK;
1024
1025         /* zone is already sorted */
1026         ldns_dnssec_zone_mark_glue(zone);
1027
1028         /* TODO if there are already nsec3s presents and their
1029          * parameters are the same as these, we don't have to recreate
1030          */
1031         if (zone->names) {
1032                 /* add empty nonterminals */
1033                 ldns_dnssec_zone_add_empty_nonterminals(zone);
1034
1035                 nsec3 = ((ldns_dnssec_name *)zone->names->root->data)->nsec;
1036                 if (nsec3 && ldns_rr_get_type(nsec3) == LDNS_RR_TYPE_NSEC3) {
1037                         /* no need to recreate */
1038                 } else {
1039                         if (!ldns_dnssec_zone_find_rrset(zone,
1040                                                                            zone->soa->name,
1041                                                                            LDNS_RR_TYPE_NSEC3PARAMS)) {
1042                                 /* create and add the nsec3params rr */
1043                                 nsec3params =
1044                                         ldns_rr_new_frm_type(LDNS_RR_TYPE_NSEC3PARAMS);
1045                                 ldns_rr_set_owner(nsec3params,
1046                                                            ldns_rdf_clone(zone->soa->name));
1047                                 ldns_nsec3_add_param_rdfs(nsec3params,
1048                                                                          algorithm,
1049                                                                          flags,
1050                                                                          iterations,
1051                                                                          salt_length,
1052                                                                          salt);
1053                                 /* always set bit 7 of the flags to zero, according to
1054                                  * rfc5155 section 11 */
1055                                 ldns_set_bit(ldns_rdf_data(ldns_rr_rdf(nsec3params, 1)), 7, 0);
1056                                 ldns_dnssec_zone_add_rr(zone, nsec3params);
1057                                 ldns_rr_list_push_rr(new_rrs, nsec3params);
1058                         }
1059                         result = ldns_dnssec_zone_create_nsec3s(zone,
1060                                                                                         new_rrs,
1061                                                                                         algorithm,
1062                                                                                         flags,
1063                                                                                         iterations,
1064                                                                                         salt_length,
1065                                                                                         salt);
1066                         if (result != LDNS_STATUS_OK) {
1067                                 return result;
1068                         }
1069                 }
1070
1071                 result = ldns_dnssec_zone_create_rrsigs_flg(zone,
1072                                                 new_rrs,
1073                                                 key_list,
1074                                                 func,
1075                                                 arg,
1076                                                 signflags);
1077         }
1078         
1079         return result;
1080 }
1081
1082
1083 ldns_zone *
1084 ldns_zone_sign(const ldns_zone *zone, ldns_key_list *key_list)
1085 {
1086         ldns_dnssec_zone *dnssec_zone;
1087         ldns_zone *signed_zone;
1088         ldns_rr_list *new_rrs;
1089         size_t i;
1090
1091         signed_zone = ldns_zone_new();
1092         dnssec_zone = ldns_dnssec_zone_new();
1093
1094         (void) ldns_dnssec_zone_add_rr(dnssec_zone, ldns_zone_soa(zone));
1095         ldns_zone_set_soa(signed_zone, ldns_zone_soa(zone));
1096         
1097         for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(zone)); i++) {
1098                 (void) ldns_dnssec_zone_add_rr(dnssec_zone,
1099                                                                  ldns_rr_list_rr(ldns_zone_rrs(zone),
1100                                                                                           i));
1101                 ldns_zone_push_rr(signed_zone, 
1102                                            ldns_rr_clone(ldns_rr_list_rr(ldns_zone_rrs(zone),
1103                                                                                            i)));
1104         }
1105
1106         new_rrs = ldns_rr_list_new();
1107         (void) ldns_dnssec_zone_sign(dnssec_zone,
1108                                                     new_rrs,
1109                                                     key_list,
1110                                                     ldns_dnssec_default_replace_signatures,
1111                                                     NULL);
1112
1113         for (i = 0; i < ldns_rr_list_rr_count(new_rrs); i++) {
1114                 ldns_rr_list_push_rr(ldns_zone_rrs(signed_zone),
1115                                                  ldns_rr_clone(ldns_rr_list_rr(new_rrs, i)));
1116         }
1117
1118         ldns_rr_list_deep_free(new_rrs);
1119         ldns_dnssec_zone_free(dnssec_zone);
1120
1121         return signed_zone;
1122 }
1123
1124 ldns_zone *
1125 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)
1126 {
1127         ldns_dnssec_zone *dnssec_zone;
1128         ldns_zone *signed_zone;
1129         ldns_rr_list *new_rrs;
1130         size_t i;
1131
1132         signed_zone = ldns_zone_new();
1133         dnssec_zone = ldns_dnssec_zone_new();
1134
1135         (void) ldns_dnssec_zone_add_rr(dnssec_zone, ldns_zone_soa(zone));
1136         ldns_zone_set_soa(signed_zone, ldns_zone_soa(zone));
1137         
1138         for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(zone)); i++) {
1139                 (void) ldns_dnssec_zone_add_rr(dnssec_zone,
1140                                                                  ldns_rr_list_rr(ldns_zone_rrs(zone),
1141                                                                                           i));
1142                 ldns_zone_push_rr(signed_zone, 
1143                                            ldns_rr_clone(ldns_rr_list_rr(ldns_zone_rrs(zone),
1144                                                                                            i)));
1145         }
1146
1147         new_rrs = ldns_rr_list_new();
1148         (void) ldns_dnssec_zone_sign_nsec3(dnssec_zone,
1149                                                                 new_rrs,
1150                                                                 key_list,
1151                                                                 ldns_dnssec_default_replace_signatures,
1152                                                                 NULL,
1153                                                                 algorithm,
1154                                                                 flags,
1155                                                                 iterations,
1156                                                                 salt_length,
1157                                                                 salt);
1158
1159         for (i = 0; i < ldns_rr_list_rr_count(new_rrs); i++) {
1160                 ldns_rr_list_push_rr(ldns_zone_rrs(signed_zone),
1161                                                  ldns_rr_clone(ldns_rr_list_rr(new_rrs, i)));
1162         }
1163
1164         ldns_rr_list_deep_free(new_rrs);
1165         ldns_dnssec_zone_free(dnssec_zone);
1166
1167         return signed_zone;
1168 }
1169 #endif /* HAVE_SSL */
1170