]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/ldns/dnssec_verify.c
Upgrade to OpenSSH 6.2p1. The most important new features are support
[FreeBSD/FreeBSD.git] / contrib / ldns / dnssec_verify.c
1 #include <ldns/config.h>
2
3 #include <ldns/ldns.h>
4
5 #include <strings.h>
6 #include <time.h>
7
8 #ifdef HAVE_SSL
9 /* this entire file is rather useless when you don't have
10  * crypto...
11  */
12 #include <openssl/ssl.h>
13 #include <openssl/evp.h>
14 #include <openssl/rand.h>
15 #include <openssl/err.h>
16 #include <openssl/md5.h>
17
18 ldns_dnssec_data_chain *
19 ldns_dnssec_data_chain_new(void)
20 {
21         ldns_dnssec_data_chain *nc = LDNS_CALLOC(ldns_dnssec_data_chain, 1);
22         if(!nc) return NULL;
23         /* 
24          * not needed anymore because CALLOC initalizes everything to zero.
25
26         nc->rrset = NULL;
27         nc->parent_type = 0;
28         nc->parent = NULL;
29         nc->signatures = NULL;
30         nc->packet_rcode = 0;
31         nc->packet_qtype = 0;
32         nc->packet_nodata = false;
33
34          */
35         return nc;
36 }
37
38 void
39 ldns_dnssec_data_chain_free(ldns_dnssec_data_chain *chain)
40 {
41         LDNS_FREE(chain);
42 }
43
44 void
45 ldns_dnssec_data_chain_deep_free(ldns_dnssec_data_chain *chain)
46 {
47         ldns_rr_list_deep_free(chain->rrset);
48         ldns_rr_list_deep_free(chain->signatures);
49         if (chain->parent) {
50                 ldns_dnssec_data_chain_deep_free(chain->parent);
51         }
52         LDNS_FREE(chain);
53 }
54
55 void
56 ldns_dnssec_data_chain_print_fmt(FILE *out, const ldns_output_format *fmt,
57                 const ldns_dnssec_data_chain *chain)
58 {
59         ldns_lookup_table *rcode;
60         const ldns_rr_descriptor *rr_descriptor;
61         if (chain) {
62                 ldns_dnssec_data_chain_print_fmt(out, fmt, chain->parent);
63                 if (ldns_rr_list_rr_count(chain->rrset) > 0) {
64                         rcode = ldns_lookup_by_id(ldns_rcodes,
65                                                                  (int) chain->packet_rcode);
66                         if (rcode) {
67                                 fprintf(out, ";; rcode: %s\n", rcode->name);
68                         }
69
70                         rr_descriptor = ldns_rr_descript(chain->packet_qtype);
71                         if (rr_descriptor && rr_descriptor->_name) {
72                                 fprintf(out, ";; qtype: %s\n", rr_descriptor->_name);
73                         } else if (chain->packet_qtype != 0) {
74                                 fprintf(out, "TYPE%u", 
75                                            chain->packet_qtype);
76                         }
77                         if (chain->packet_nodata) {
78                                 fprintf(out, ";; NODATA response\n");
79                         }
80                         fprintf(out, "rrset:\n");
81                         ldns_rr_list_print_fmt(out, fmt, chain->rrset);
82                         fprintf(out, "sigs:\n");
83                         ldns_rr_list_print_fmt(out, fmt, chain->signatures);
84                         fprintf(out, "---\n");
85                 } else {
86                         fprintf(out, "<no data>\n");
87                 }
88         }
89 }
90 void
91 ldns_dnssec_data_chain_print(FILE *out, const ldns_dnssec_data_chain *chain)
92 {
93         ldns_dnssec_data_chain_print_fmt(
94                         out, ldns_output_format_default, chain);
95 }
96
97
98 static void
99 ldns_dnssec_build_data_chain_dnskey(ldns_resolver *res,
100                                             uint16_t qflags,
101                                             const ldns_pkt *pkt,
102                                             ldns_rr_list *signatures,
103                                                 ldns_dnssec_data_chain *new_chain,
104                                                 ldns_rdf *key_name,
105                                                 ldns_rr_class c) {
106         ldns_rr_list *keys;
107         ldns_pkt *my_pkt;
108         if (signatures && ldns_rr_list_rr_count(signatures) > 0) {
109                 new_chain->signatures = ldns_rr_list_clone(signatures);
110                 new_chain->parent_type = 0;
111
112                 keys = ldns_pkt_rr_list_by_name_and_type(
113                                   pkt,
114                                  key_name,
115                                  LDNS_RR_TYPE_DNSKEY,
116                                  LDNS_SECTION_ANY_NOQUESTION
117                           );
118                 if (!keys) {
119                         my_pkt = ldns_resolver_query(res,
120                                                                         key_name,
121                                                                         LDNS_RR_TYPE_DNSKEY,
122                                                                         c,
123                                                                         qflags);
124                         if (my_pkt) {
125                         keys = ldns_pkt_rr_list_by_name_and_type(
126                                           my_pkt,
127                                          key_name,
128                                          LDNS_RR_TYPE_DNSKEY,
129                                          LDNS_SECTION_ANY_NOQUESTION
130                                   );
131                         new_chain->parent = ldns_dnssec_build_data_chain(res,
132                                                                                                         qflags,
133                                                                                                         keys,
134                                                                                                         my_pkt,
135                                                                                                         NULL);
136                         new_chain->parent->packet_qtype = LDNS_RR_TYPE_DNSKEY;
137                         ldns_pkt_free(my_pkt);
138                         }
139                 } else {
140                         new_chain->parent = ldns_dnssec_build_data_chain(res,
141                                                                                                         qflags,
142                                                                                                         keys,
143                                                                                                         pkt,
144                                                                                                         NULL);
145                         new_chain->parent->packet_qtype = LDNS_RR_TYPE_DNSKEY;
146                 }
147                 ldns_rr_list_deep_free(keys);
148         }
149 }
150
151 static void
152 ldns_dnssec_build_data_chain_other(ldns_resolver *res,
153                                             uint16_t qflags,
154                                                 ldns_dnssec_data_chain *new_chain,
155                                                 ldns_rdf *key_name,
156                                                 ldns_rr_class c,
157                                                 ldns_rr_list *dss)
158 {
159         /* 'self-signed', parent is a DS */
160         
161         /* okay, either we have other keys signing the current one,
162          * or the current
163          * one should have a DS record in the parent zone.
164          * How do we find this out? Try both?
165          *
166          * request DNSKEYS for current zone,
167          * add all signatures to current level
168          */
169         ldns_pkt *my_pkt;
170         ldns_rr_list *signatures2;
171         
172         new_chain->parent_type = 1;
173
174         my_pkt = ldns_resolver_query(res,
175                                                         key_name,
176                                                         LDNS_RR_TYPE_DS,
177                                                         c,
178                                                         qflags);
179         if (my_pkt) {
180         dss = ldns_pkt_rr_list_by_name_and_type(my_pkt,
181                                                                         key_name,
182                                                                         LDNS_RR_TYPE_DS,
183                                                                         LDNS_SECTION_ANY_NOQUESTION
184                                                                         );
185         if (dss) {
186                 new_chain->parent = ldns_dnssec_build_data_chain(res,
187                                                                                                 qflags,
188                                                                                                 dss,
189                                                                                                 my_pkt,
190                                                                                                 NULL);
191                 new_chain->parent->packet_qtype = LDNS_RR_TYPE_DS;
192                 ldns_rr_list_deep_free(dss);
193         }
194         ldns_pkt_free(my_pkt);
195         }
196
197         my_pkt = ldns_resolver_query(res,
198                                                         key_name,
199                                                         LDNS_RR_TYPE_DNSKEY,
200                                                         c,
201                                                         qflags);
202         if (my_pkt) {
203         signatures2 = ldns_pkt_rr_list_by_name_and_type(my_pkt,
204                                                                                    key_name,
205                                                                                    LDNS_RR_TYPE_RRSIG,
206                                                                                    LDNS_SECTION_ANSWER);
207         if (signatures2) {
208                 if (new_chain->signatures) {
209                         printf("There were already sigs!\n");
210                         ldns_rr_list_deep_free(new_chain->signatures);
211                         printf("replacing the old sigs\n");
212                 }
213                 new_chain->signatures = signatures2;
214         }
215         ldns_pkt_free(my_pkt);
216         }
217 }
218
219 static ldns_dnssec_data_chain *
220 ldns_dnssec_build_data_chain_nokeyname(ldns_resolver *res,
221                                        uint16_t qflags,
222                                        ldns_rr *orig_rr,
223                                        const ldns_rr_list *rrset,
224                                        ldns_dnssec_data_chain *new_chain)
225 {
226         ldns_rdf *possible_parent_name;
227         ldns_pkt *my_pkt;
228         /* apparently we were not able to find a signing key, so
229            we assume the chain ends here
230         */
231         /* try parents for auth denial of DS */
232         if (orig_rr) {
233                 possible_parent_name = ldns_rr_owner(orig_rr);
234         } else if (rrset && ldns_rr_list_rr_count(rrset) > 0) {
235                 possible_parent_name = ldns_rr_owner(ldns_rr_list_rr(rrset, 0));
236         } else {
237                 /* no information to go on, give up */
238                 return new_chain;
239         }
240
241         my_pkt = ldns_resolver_query(res,
242                       possible_parent_name,
243                       LDNS_RR_TYPE_DS,
244                       LDNS_RR_CLASS_IN,
245                       qflags);
246         if (!my_pkt) {
247                 return new_chain;
248         }
249
250         if (ldns_pkt_ancount(my_pkt) > 0) {
251                 /* add error, no sigs but DS in parent */
252                 /*ldns_pkt_print(stdout, my_pkt);*/
253                 ldns_pkt_free(my_pkt);
254         } else {
255                 /* are there signatures? */
256                 new_chain->parent =  ldns_dnssec_build_data_chain(res, 
257                                           qflags, 
258                                           NULL,
259                                           my_pkt,
260                                           NULL);
261
262                 new_chain->parent->packet_qtype = LDNS_RR_TYPE_DS;
263                 
264         }
265         return new_chain;
266 }
267
268
269 ldns_dnssec_data_chain *
270 ldns_dnssec_build_data_chain(ldns_resolver *res,
271                                             uint16_t qflags,
272                                             const ldns_rr_list *rrset,
273                                             const ldns_pkt *pkt,
274                                             ldns_rr *orig_rr)
275 {
276         ldns_rr_list *signatures = NULL;
277         ldns_rr_list *dss = NULL;
278         
279         ldns_rr_list *my_rrset;
280
281         ldns_pkt *my_pkt;
282
283         ldns_rdf *name = NULL, *key_name = NULL;
284         ldns_rr_type type = 0;
285         ldns_rr_class c = 0;
286
287         bool other_rrset = false;
288
289         ldns_dnssec_data_chain *new_chain = ldns_dnssec_data_chain_new();
290
291         assert(pkt != NULL);
292
293         if (!ldns_dnssec_pkt_has_rrsigs(pkt)) {
294                 /* hmm. no dnssec data in the packet. go up to try and deny
295                  * DS? */
296                 return new_chain;
297         }
298
299         if (orig_rr) {
300                 new_chain->rrset = ldns_rr_list_new();
301                 ldns_rr_list_push_rr(new_chain->rrset, orig_rr);
302                 new_chain->parent = ldns_dnssec_build_data_chain(res,
303                                                                                             qflags,
304                                                                                             rrset,
305                                                                                             pkt,
306                                                                                             NULL);
307                 new_chain->packet_rcode = ldns_pkt_get_rcode(pkt);
308                 new_chain->packet_qtype = ldns_rr_get_type(orig_rr);
309                 if (ldns_pkt_ancount(pkt) == 0) {
310                         new_chain->packet_nodata = true;
311                 }
312                 return new_chain;
313         }
314         
315         if (!rrset || ldns_rr_list_rr_count(rrset) < 1) {
316                 /* hmm, no data, do we have denial? only works if pkt was given,
317                    otherwise caller has to do the check himself */
318                 new_chain->packet_nodata = true;
319                 if (pkt) {
320                         my_rrset = ldns_pkt_rr_list_by_type(pkt,
321                                                                                  LDNS_RR_TYPE_NSEC,
322                                                                                  LDNS_SECTION_ANY_NOQUESTION
323                                                                                  );
324                         if (my_rrset) {
325                                 if (ldns_rr_list_rr_count(my_rrset) > 0) {
326                                         type = LDNS_RR_TYPE_NSEC;
327                                         other_rrset = true;
328                                 } else {
329                                         ldns_rr_list_deep_free(my_rrset);
330                                         my_rrset = NULL;
331                                 }
332                         } else {
333                                 /* nothing, try nsec3 */
334                                 my_rrset = ldns_pkt_rr_list_by_type(pkt,
335                                                      LDNS_RR_TYPE_NSEC3,
336                                                         LDNS_SECTION_ANY_NOQUESTION);
337                                 if (my_rrset) {
338                                         if (ldns_rr_list_rr_count(my_rrset) > 0) {
339                                                 type = LDNS_RR_TYPE_NSEC3;
340                                                 other_rrset = true;
341                                         } else {
342                                                 ldns_rr_list_deep_free(my_rrset);
343                                                 my_rrset = NULL;
344                                         }
345                                 } else {
346                                         /* nothing, stop */
347                                         /* try parent zone? for denied insecure? */
348                                         return new_chain;
349                                 }
350                         }
351                 } else {
352                         return new_chain;
353                 }
354         } else {
355                 my_rrset = (ldns_rr_list *) rrset;
356         }
357         
358         if (my_rrset && ldns_rr_list_rr_count(my_rrset) > 0) {
359                 new_chain->rrset = ldns_rr_list_clone(my_rrset);
360                 name = ldns_rr_owner(ldns_rr_list_rr(my_rrset, 0));
361                 type = ldns_rr_get_type(ldns_rr_list_rr(my_rrset, 0));
362                 c = ldns_rr_get_class(ldns_rr_list_rr(my_rrset, 0));
363         }
364         
365         if (other_rrset) {
366                 ldns_rr_list_deep_free(my_rrset);
367         }
368         
369         /* normally there will only be 1 signature 'set'
370            but there can be more than 1 denial (wildcards)
371            so check for NSEC
372         */
373         if (type == LDNS_RR_TYPE_NSEC || type == LDNS_RR_TYPE_NSEC3) {
374                 /* just throw in all signatures, the tree builder must sort
375                    this out */
376                 if (pkt) {
377                         signatures = ldns_dnssec_pkt_get_rrsigs_for_type(pkt, type);
378                 } else {
379                         my_pkt = ldns_resolver_query(res, name, type, c, qflags);
380                         if (my_pkt) {
381                         signatures = ldns_dnssec_pkt_get_rrsigs_for_type(pkt, type);
382                         ldns_pkt_free(my_pkt);
383                         }
384                 }
385         } else {
386                 if (pkt) {
387                         signatures =
388                                 ldns_dnssec_pkt_get_rrsigs_for_name_and_type(pkt,
389                                                                                                         name,
390                                                                                                         type);
391                 }
392                 if (!signatures) {
393                         my_pkt = ldns_resolver_query(res, name, type, c, qflags);
394                         if (my_pkt) {
395                         signatures =
396                                 ldns_dnssec_pkt_get_rrsigs_for_name_and_type(my_pkt,
397                                                                                                         name,
398                                                                                                         type);
399                         ldns_pkt_free(my_pkt);
400                         }
401                 }
402         }
403
404         if (signatures && ldns_rr_list_rr_count(signatures) > 0) {
405                 key_name = ldns_rr_rdf(ldns_rr_list_rr(signatures, 0), 7);
406         }
407         if (!key_name) {
408                 if (signatures) {
409                         ldns_rr_list_deep_free(signatures);
410                 }
411                 return ldns_dnssec_build_data_chain_nokeyname(res,
412                                                               qflags,
413                                                               orig_rr,
414                                                               rrset,
415                                                               new_chain);
416         }
417         if (type != LDNS_RR_TYPE_DNSKEY) {
418                 ldns_dnssec_build_data_chain_dnskey(res,
419                                                     qflags,
420                                                     pkt,
421                                                     signatures,
422                                                     new_chain,
423                                                     key_name,
424                                                     c
425                                                    );
426         } else {
427                 ldns_dnssec_build_data_chain_other(res,
428                                                    qflags,
429                                                    new_chain,
430                                                    key_name,
431                                                    c,
432                                                    dss
433                                                   );
434         }
435         if (signatures) {
436                 ldns_rr_list_deep_free(signatures);
437         }
438         return new_chain;
439 }
440
441 ldns_dnssec_trust_tree *
442 ldns_dnssec_trust_tree_new(void)
443 {
444         ldns_dnssec_trust_tree *new_tree = LDNS_XMALLOC(ldns_dnssec_trust_tree,
445                                                                                    1);
446         if(!new_tree) return NULL;
447         new_tree->rr = NULL;
448         new_tree->rrset = NULL;
449         new_tree->parent_count = 0;
450
451         return new_tree;
452 }
453
454 void
455 ldns_dnssec_trust_tree_free(ldns_dnssec_trust_tree *tree)
456 {
457         size_t i;
458         if (tree) {
459                 for (i = 0; i < tree->parent_count; i++) {
460                         ldns_dnssec_trust_tree_free(tree->parents[i]);
461                 }
462         }
463         LDNS_FREE(tree);
464 }
465
466 size_t
467 ldns_dnssec_trust_tree_depth(ldns_dnssec_trust_tree *tree)
468 {
469         size_t result = 0;
470         size_t parent = 0;
471         size_t i;
472         
473         for (i = 0; i < tree->parent_count; i++) {
474                 parent = ldns_dnssec_trust_tree_depth(tree->parents[i]);
475                 if (parent > result) {
476                         result = parent;
477                 }
478         }
479         return 1 + result;
480 }
481
482 /* TODO ldns_ */
483 static void
484 print_tabs(FILE *out, size_t nr, uint8_t *map, size_t treedepth)
485 {
486         size_t i;
487         for (i = 0; i < nr; i++) {
488                 if (i == nr - 1) {
489                         fprintf(out, "|---");
490                 } else if (map && i < treedepth && map[i] == 1) {
491                         fprintf(out, "|   ");
492                 } else {
493                         fprintf(out, "    ");
494                 }
495         }
496 }
497
498 static void
499 ldns_dnssec_trust_tree_print_sm_fmt(FILE *out, 
500                 const ldns_output_format *fmt,
501                 ldns_dnssec_trust_tree *tree,
502                 size_t tabs,
503                 bool extended,
504                 uint8_t *sibmap,
505                 size_t treedepth)
506 {
507         size_t i;
508         const ldns_rr_descriptor *descriptor;
509         bool mapset = false;
510         
511         if (!sibmap) {
512                 treedepth = ldns_dnssec_trust_tree_depth(tree);
513                 sibmap = LDNS_XMALLOC(uint8_t, treedepth);
514                 if(!sibmap)
515                         return; /* mem err */
516                 memset(sibmap, 0, treedepth);
517                 mapset = true;
518         }
519         
520         if (tree) {
521                 if (tree->rr) {
522                         print_tabs(out, tabs, sibmap, treedepth);
523                         ldns_rdf_print(out, ldns_rr_owner(tree->rr));
524                         descriptor = ldns_rr_descript(ldns_rr_get_type(tree->rr));
525
526                         if (descriptor->_name) {
527                                 fprintf(out, " (%s", descriptor->_name);
528                         } else {
529                                 fprintf(out, " (TYPE%d", 
530                                            ldns_rr_get_type(tree->rr));
531                         }
532                         if (tabs > 0) {
533                                 if (ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_DNSKEY) {
534                                         fprintf(out, " keytag: %u",
535                                                 (unsigned int) ldns_calc_keytag(tree->rr));
536                                         fprintf(out, " alg: ");
537                                         ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 2));
538                                         fprintf(out, " flags: ");
539                                         ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 0));
540                                 } else if (ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_DS) {
541                                         fprintf(out, " keytag: ");
542                                         ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 0));
543                                         fprintf(out, " digest type: ");
544                                         ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 2));
545                                 }
546                                 if (ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_NSEC) {
547                                         fprintf(out, " ");
548                                         ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 0));
549                                         fprintf(out, " ");
550                                         ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 1));
551                                 }
552                         }
553                         
554                         fprintf(out, ")\n");
555                         for (i = 0; i < tree->parent_count; i++) {
556                                 if (tree->parent_count > 1 && i < tree->parent_count - 1) {
557                                         sibmap[tabs] = 1;
558                                 } else {
559                                         sibmap[tabs] = 0;
560                                 }
561                                 /* only print errors */
562                                 if (ldns_rr_get_type(tree->parents[i]->rr) == 
563                                     LDNS_RR_TYPE_NSEC ||
564                                     ldns_rr_get_type(tree->parents[i]->rr) ==
565                                     LDNS_RR_TYPE_NSEC3) {
566                                         if (tree->parent_status[i] == LDNS_STATUS_OK) {
567                                                 print_tabs(out, tabs + 1, sibmap, treedepth);
568                                                 if (tabs == 0 &&
569                                                     ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_NS &&
570                                                         ldns_rr_rd_count(tree->rr) > 0) {
571                                                         fprintf(out, "Existence of DS is denied by:\n");
572                                                 } else {
573                                                         fprintf(out, "Existence is denied by:\n");
574                                                 }
575                                         } else {
576                                                 /* NS records aren't signed */
577                                                 if (ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_NS) {
578                                                         fprintf(out, "Existence of DS is denied by:\n");
579                                                 } else {
580                                                         print_tabs(out, tabs + 1, sibmap, treedepth);
581                                                         fprintf(out,
582                                                                    "Error in denial of existence: %s\n",
583                                                                    ldns_get_errorstr_by_id(
584                                                                            tree->parent_status[i]));
585                                                 }
586                                         }
587                                 } else
588                                         if (tree->parent_status[i] != LDNS_STATUS_OK) {
589                                                 print_tabs(out, tabs + 1, sibmap, treedepth);
590                                                 fprintf(out,
591                                                            "%s:\n",
592                                                            ldns_get_errorstr_by_id(
593                                                                tree->parent_status[i]));
594                                                 if (tree->parent_status[i]
595                                                     == LDNS_STATUS_SSL_ERR) {
596                                                         printf("; SSL Error: ");
597                                                         ERR_load_crypto_strings();
598                                                         ERR_print_errors_fp(stdout);
599                                                         printf("\n");
600                                                 }
601                                                 ldns_rr_print_fmt(out, fmt, 
602                                                         tree->
603                                                         parent_signature[i]);
604                                                 printf("For RRset:\n");
605                                                 ldns_rr_list_print_fmt(out, fmt,
606                                                                 tree->rrset);
607                                                 printf("With key:\n");
608                                                 ldns_rr_print_fmt(out, fmt,
609                                                         tree->parents[i]->rr);
610                                         }
611                                 ldns_dnssec_trust_tree_print_sm_fmt(out, fmt,
612                                                 tree->parents[i],
613                                                 tabs+1,
614                                                 extended,
615                                                 sibmap,
616                                                 treedepth);
617                         }
618                 } else {
619                         print_tabs(out, tabs, sibmap, treedepth);
620                         fprintf(out, "<no data>\n");
621                 }
622         } else {
623                 fprintf(out, "<null pointer>\n");
624         }
625         
626         if (mapset) {
627                 LDNS_FREE(sibmap);
628         }
629 }
630
631 #if 0
632 static void
633 ldns_dnssec_trust_tree_print_sm(FILE *out, 
634                 ldns_dnssec_trust_tree *tree,
635                 size_t tabs,
636                 bool extended,
637                 uint8_t *sibmap,
638                 size_t treedepth)
639 {
640         ldns_dnssec_trust_tree_print_sm_fmt(out, ldns_output_format_default, 
641                         tree, tabs, extended, sibmap, treedepth);
642 }
643 #endif
644
645 void
646 ldns_dnssec_trust_tree_print_fmt(FILE *out, const ldns_output_format *fmt,
647                 ldns_dnssec_trust_tree *tree,
648                 size_t tabs,
649                 bool extended)
650 {
651         ldns_dnssec_trust_tree_print_sm_fmt(out, fmt, 
652                         tree, tabs, extended, NULL, 0);
653 }
654
655 void
656 ldns_dnssec_trust_tree_print(FILE *out,
657                 ldns_dnssec_trust_tree *tree,
658                 size_t tabs,
659                 bool extended)
660 {
661         ldns_dnssec_trust_tree_print_fmt(out, ldns_output_format_default, 
662                         tree, tabs, extended);
663 }
664
665
666 ldns_status
667 ldns_dnssec_trust_tree_add_parent(ldns_dnssec_trust_tree *tree,
668                                   const ldns_dnssec_trust_tree *parent,
669                                   const ldns_rr *signature,
670                                   const ldns_status parent_status)
671 {
672         if (tree
673             && parent
674             && tree->parent_count < LDNS_DNSSEC_TRUST_TREE_MAX_PARENTS) {
675                 /*
676                   printf("Add parent for: ");
677                   ldns_rr_print(stdout, tree->rr);
678                   printf("parent: ");
679                   ldns_rr_print(stdout, parent->rr);
680                 */
681                 tree->parents[tree->parent_count] =
682                         (ldns_dnssec_trust_tree *) parent;
683                 tree->parent_status[tree->parent_count] = parent_status;
684                 tree->parent_signature[tree->parent_count] = (ldns_rr *) signature;
685                 tree->parent_count++;
686                 return LDNS_STATUS_OK;
687         } else {
688                 return LDNS_STATUS_ERR;
689         }
690 }
691
692 /* if rr is null, take the first from the rrset */
693 ldns_dnssec_trust_tree *
694 ldns_dnssec_derive_trust_tree_time(
695                 ldns_dnssec_data_chain *data_chain, 
696                 ldns_rr *rr, 
697                 time_t check_time
698                 )
699 {
700         ldns_rr_list *cur_rrset;
701         ldns_rr_list *cur_sigs;
702         ldns_rr *cur_rr = NULL;
703         ldns_rr *cur_sig_rr;
704         size_t i, j;
705
706         ldns_dnssec_trust_tree *new_tree = ldns_dnssec_trust_tree_new();
707         if(!new_tree)
708                 return NULL;
709         
710         if (data_chain && data_chain->rrset) {
711                 cur_rrset = data_chain->rrset;
712         
713                 cur_sigs = data_chain->signatures;
714
715                 if (rr) {
716                         cur_rr = rr;
717                 }
718
719                 if (!cur_rr && ldns_rr_list_rr_count(cur_rrset) > 0) {
720                         cur_rr = ldns_rr_list_rr(cur_rrset, 0);
721                 }
722
723                 if (cur_rr) {
724                         new_tree->rr = cur_rr;
725                         new_tree->rrset = cur_rrset;
726                         /* there are three possibilities:
727                            1 - 'normal' rrset, signed by a key
728                            2 - dnskey signed by other dnskey
729                            3 - dnskey proven by higher level DS
730                            (data denied by nsec is a special case that can
731                            occur in multiple places)
732                                    
733                         */
734                         if (cur_sigs) {
735                                 for (i = 0; i < ldns_rr_list_rr_count(cur_sigs); i++) {
736                                         /* find the appropriate key in the parent list */
737                                         cur_sig_rr = ldns_rr_list_rr(cur_sigs, i);
738
739                                         if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_NSEC) {
740                                                 if (ldns_dname_compare(ldns_rr_owner(cur_sig_rr),
741                                                                                    ldns_rr_owner(cur_rr)))
742                                                         {
743                                                                 /* find first that does match */
744
745                                                                 for (j = 0;
746                                                                      j < ldns_rr_list_rr_count(cur_rrset) && 
747                                                                                 ldns_dname_compare(ldns_rr_owner(cur_sig_rr),ldns_rr_owner(cur_rr)) != 0;
748                                                                      j++) {
749                                                                         cur_rr = ldns_rr_list_rr(cur_rrset, j);
750                                                                         
751                                                                 }
752                                                                 if (ldns_dname_compare(ldns_rr_owner(cur_sig_rr), 
753                                                                                                    ldns_rr_owner(cur_rr)))
754                                                                         {
755                                                                                 break;
756                                                                         }
757                                                         }
758                                                         
759                                         }
760                                         /* option 1 */
761                                         if (data_chain->parent) {
762                                                 ldns_dnssec_derive_trust_tree_normal_rrset_time(
763                                                     new_tree,
764                                                     data_chain,
765                                                     cur_sig_rr,
766                                                     check_time);
767                                         }
768
769                                         /* option 2 */
770                                         ldns_dnssec_derive_trust_tree_dnskey_rrset_time(
771                                             new_tree,
772                                             data_chain,
773                                             cur_rr,
774                                             cur_sig_rr,
775                                             check_time);
776                                 }
777                                         
778                                 ldns_dnssec_derive_trust_tree_ds_rrset_time(
779                                                 new_tree, data_chain, 
780                                                 cur_rr, check_time);
781                         } else {
782                                 /* no signatures? maybe it's nsec data */
783                                         
784                                 /* just add every rr from parent as new parent */
785                                 ldns_dnssec_derive_trust_tree_no_sig_time(
786                                         new_tree, data_chain, check_time);
787                         }
788                 }
789         }
790
791         return new_tree;
792 }
793
794 ldns_dnssec_trust_tree *
795 ldns_dnssec_derive_trust_tree(ldns_dnssec_data_chain *data_chain, ldns_rr *rr)
796 {
797         return ldns_dnssec_derive_trust_tree_time(data_chain, rr, ldns_time(NULL));
798 }
799
800 void
801 ldns_dnssec_derive_trust_tree_normal_rrset_time(
802                 ldns_dnssec_trust_tree *new_tree, 
803                 ldns_dnssec_data_chain *data_chain, 
804                 ldns_rr *cur_sig_rr,
805                 time_t check_time)
806 {
807         size_t i, j;
808         ldns_rr_list *cur_rrset = ldns_rr_list_clone(data_chain->rrset); 
809         ldns_dnssec_trust_tree *cur_parent_tree;
810         ldns_rr *cur_parent_rr;
811         uint16_t cur_keytag;
812         ldns_rr_list *tmp_rrset = NULL;
813         ldns_status cur_status;
814
815         cur_keytag = ldns_rdf2native_int16(ldns_rr_rrsig_keytag(cur_sig_rr));
816         
817         for (j = 0; j < ldns_rr_list_rr_count(data_chain->parent->rrset); j++) {
818                 cur_parent_rr = ldns_rr_list_rr(data_chain->parent->rrset, j);
819                 if (ldns_rr_get_type(cur_parent_rr) == LDNS_RR_TYPE_DNSKEY) {
820                         if (ldns_calc_keytag(cur_parent_rr) == cur_keytag) {
821
822                                 /* TODO: check wildcard nsec too */
823                                 if (cur_rrset && ldns_rr_list_rr_count(cur_rrset) > 0) {
824                                         tmp_rrset = cur_rrset;
825                                         if (ldns_rr_get_type(ldns_rr_list_rr(cur_rrset, 0))
826                                             == LDNS_RR_TYPE_NSEC ||
827                                             ldns_rr_get_type(ldns_rr_list_rr(cur_rrset, 0))
828                                             == LDNS_RR_TYPE_NSEC3) {
829                                                 /* might contain different names! 
830                                                    sort and split */
831                                                 ldns_rr_list_sort(cur_rrset);
832                                                 assert(tmp_rrset == cur_rrset);
833                                                 tmp_rrset = ldns_rr_list_pop_rrset(cur_rrset);
834                                                 
835                                                 /* with nsecs, this might be the wrong one */
836                                                 while (tmp_rrset &&
837                                                        ldns_rr_list_rr_count(cur_rrset) > 0 &&
838                                                        ldns_dname_compare(
839                                                                 ldns_rr_owner(ldns_rr_list_rr(
840                                                                                         tmp_rrset, 0)),
841                                                                 ldns_rr_owner(cur_sig_rr)) != 0) {
842                                                         ldns_rr_list_deep_free(tmp_rrset);
843                                                         tmp_rrset =
844                                                                 ldns_rr_list_pop_rrset(cur_rrset);
845                                                 }
846                                         }
847                                         cur_status = ldns_verify_rrsig_time(
848                                                         tmp_rrset, 
849                                                         cur_sig_rr, 
850                                                         cur_parent_rr,
851                                                         check_time);
852                                         if (tmp_rrset && tmp_rrset != cur_rrset
853                                                         ) {
854                                                 ldns_rr_list_deep_free(
855                                                                 tmp_rrset);
856                                                 tmp_rrset = NULL;
857                                         }
858                                         /* avoid dupes */
859                                         for (i = 0; i < new_tree->parent_count; i++) {
860                                                 if (cur_parent_rr == new_tree->parents[i]->rr) {
861                                                         goto done;
862                                                 }
863                                         }
864
865                                         cur_parent_tree =
866                                                 ldns_dnssec_derive_trust_tree_time(
867                                                                 data_chain->parent,
868                                                                 cur_parent_rr,
869                                                                 check_time);
870                                         (void)ldns_dnssec_trust_tree_add_parent(new_tree,
871                                                    cur_parent_tree,
872                                                    cur_sig_rr,
873                                                    cur_status);
874                                 }
875                         }
876                 }
877         }
878  done:
879         ldns_rr_list_deep_free(cur_rrset);
880 }
881
882 void
883 ldns_dnssec_derive_trust_tree_normal_rrset(ldns_dnssec_trust_tree *new_tree,
884                                            ldns_dnssec_data_chain *data_chain,
885                                            ldns_rr *cur_sig_rr)
886 {
887         ldns_dnssec_derive_trust_tree_normal_rrset_time(
888                         new_tree, data_chain, cur_sig_rr, ldns_time(NULL));
889 }
890
891 void
892 ldns_dnssec_derive_trust_tree_dnskey_rrset_time(
893                 ldns_dnssec_trust_tree *new_tree, 
894                 ldns_dnssec_data_chain *data_chain, 
895                 ldns_rr *cur_rr, 
896                 ldns_rr *cur_sig_rr,
897                 time_t check_time)
898 {
899         size_t j;
900         ldns_rr_list *cur_rrset = data_chain->rrset;
901         ldns_dnssec_trust_tree *cur_parent_tree;
902         ldns_rr *cur_parent_rr;
903         uint16_t cur_keytag;
904         ldns_status cur_status;
905
906         cur_keytag = ldns_rdf2native_int16(ldns_rr_rrsig_keytag(cur_sig_rr));
907
908         for (j = 0; j < ldns_rr_list_rr_count(cur_rrset); j++) {
909                 cur_parent_rr = ldns_rr_list_rr(cur_rrset, j);
910                 if (cur_parent_rr != cur_rr &&
911                     ldns_rr_get_type(cur_parent_rr) == LDNS_RR_TYPE_DNSKEY) {
912                         if (ldns_calc_keytag(cur_parent_rr) == cur_keytag
913                             ) {
914                                 cur_parent_tree = ldns_dnssec_trust_tree_new();
915                                 cur_parent_tree->rr = cur_parent_rr;
916                                 cur_parent_tree->rrset = cur_rrset;
917                                 cur_status = ldns_verify_rrsig_time(
918                                                 cur_rrset, cur_sig_rr, 
919                                                 cur_parent_rr, check_time);
920                                 (void) ldns_dnssec_trust_tree_add_parent(new_tree,
921                                             cur_parent_tree, cur_sig_rr, cur_status);
922                         }
923                 }
924         }
925 }
926
927 void
928 ldns_dnssec_derive_trust_tree_dnskey_rrset(ldns_dnssec_trust_tree *new_tree,
929                                            ldns_dnssec_data_chain *data_chain,
930                                            ldns_rr *cur_rr,
931                                            ldns_rr *cur_sig_rr)
932 {
933         ldns_dnssec_derive_trust_tree_dnskey_rrset_time(
934                         new_tree, data_chain, cur_rr, cur_sig_rr, ldns_time(NULL));
935 }
936
937 void
938 ldns_dnssec_derive_trust_tree_ds_rrset_time(
939                 ldns_dnssec_trust_tree *new_tree,
940                 ldns_dnssec_data_chain *data_chain, 
941                 ldns_rr *cur_rr,
942                 time_t check_time)
943 {
944         size_t j, h;
945         ldns_rr_list *cur_rrset = data_chain->rrset;
946         ldns_dnssec_trust_tree *cur_parent_tree;
947         ldns_rr *cur_parent_rr;
948
949         /* try the parent to see whether there are DSs there */
950         if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_DNSKEY &&
951             data_chain->parent &&
952             data_chain->parent->rrset
953             ) {
954                 for (j = 0;
955                         j < ldns_rr_list_rr_count(data_chain->parent->rrset);
956                         j++) {
957                         cur_parent_rr = ldns_rr_list_rr(data_chain->parent->rrset, j);
958                         if (ldns_rr_get_type(cur_parent_rr) == LDNS_RR_TYPE_DS) {
959                                 for (h = 0; h < ldns_rr_list_rr_count(cur_rrset); h++) {
960                                         cur_rr = ldns_rr_list_rr(cur_rrset, h);
961                                         if (ldns_rr_compare_ds(cur_rr, cur_parent_rr)) {
962                                                 cur_parent_tree =
963                                                         ldns_dnssec_derive_trust_tree_time(
964                                                             data_chain->parent, 
965                                                             cur_parent_rr,
966                                                             check_time);
967                                                 (void) ldns_dnssec_trust_tree_add_parent(
968                                                             new_tree,
969                                                             cur_parent_tree,
970                                                             NULL,
971                                                             LDNS_STATUS_OK);
972                                         } else {
973                                                 /*ldns_rr_print(stdout, cur_parent_rr);*/
974                                         }
975                                 }
976                         }
977                 }
978         }
979 }
980
981 void
982 ldns_dnssec_derive_trust_tree_ds_rrset(ldns_dnssec_trust_tree *new_tree,
983                                        ldns_dnssec_data_chain *data_chain,
984                                        ldns_rr *cur_rr)
985 {
986         ldns_dnssec_derive_trust_tree_ds_rrset_time(
987                         new_tree, data_chain, cur_rr, ldns_time(NULL));
988 }
989
990 void
991 ldns_dnssec_derive_trust_tree_no_sig_time(
992                 ldns_dnssec_trust_tree *new_tree, 
993                 ldns_dnssec_data_chain *data_chain,
994                 time_t check_time)
995 {
996         size_t i;
997         ldns_rr_list *cur_rrset;
998         ldns_rr *cur_parent_rr;
999         ldns_dnssec_trust_tree *cur_parent_tree;
1000         ldns_status result;
1001         
1002         if (data_chain->parent && data_chain->parent->rrset) {
1003                 cur_rrset = data_chain->parent->rrset;
1004                 /* nsec? */
1005                 if (cur_rrset && ldns_rr_list_rr_count(cur_rrset) > 0) {
1006                         if (ldns_rr_get_type(ldns_rr_list_rr(cur_rrset, 0)) ==
1007                             LDNS_RR_TYPE_NSEC3) {
1008                                 result = ldns_dnssec_verify_denial_nsec3(
1009                                                 new_tree->rr,
1010                                                    cur_rrset,
1011                                                    data_chain->parent->signatures,
1012                                                    data_chain->packet_rcode,
1013                                                    data_chain->packet_qtype,
1014                                                    data_chain->packet_nodata);
1015                         } else if (ldns_rr_get_type(ldns_rr_list_rr(cur_rrset, 0)) ==
1016                                          LDNS_RR_TYPE_NSEC) {
1017                                 result = ldns_dnssec_verify_denial(
1018                                                 new_tree->rr,
1019                                                    cur_rrset,
1020                                                    data_chain->parent->signatures);
1021                         } else {
1022                                 /* unsigned zone, unsigned parent */
1023                                 result = LDNS_STATUS_OK;
1024                         }
1025                 } else {
1026                         result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED;
1027                 }
1028                 for (i = 0; i < ldns_rr_list_rr_count(cur_rrset); i++) {
1029                         cur_parent_rr = ldns_rr_list_rr(cur_rrset, i);
1030                         cur_parent_tree = 
1031                                 ldns_dnssec_derive_trust_tree_time(
1032                                                 data_chain->parent, 
1033                                                 cur_parent_rr,
1034                                                 check_time);
1035                         (void) ldns_dnssec_trust_tree_add_parent(new_tree,
1036                                     cur_parent_tree, NULL, result);
1037                 }
1038         }
1039 }
1040
1041 void
1042 ldns_dnssec_derive_trust_tree_no_sig(ldns_dnssec_trust_tree *new_tree,
1043                                      ldns_dnssec_data_chain *data_chain)
1044 {
1045         ldns_dnssec_derive_trust_tree_no_sig_time(
1046                         new_tree, data_chain, ldns_time(NULL));
1047 }
1048
1049 /*
1050  * returns OK if there is a path from tree to key with only OK
1051  * the (first) error in between otherwise
1052  * or NOT_FOUND if the key wasn't present at all
1053  */
1054 ldns_status
1055 ldns_dnssec_trust_tree_contains_keys(ldns_dnssec_trust_tree *tree,
1056                                                           ldns_rr_list *trusted_keys)
1057 {
1058         size_t i;
1059         ldns_status result = LDNS_STATUS_CRYPTO_NO_DNSKEY;
1060         bool equal;
1061         ldns_status parent_result;
1062         
1063         if (tree && trusted_keys && ldns_rr_list_rr_count(trusted_keys) > 0)
1064                 { if (tree->rr) {
1065                                 for (i = 0; i < ldns_rr_list_rr_count(trusted_keys); i++) {
1066                                         equal = ldns_rr_compare_ds(
1067                                                           tree->rr,
1068                                                           ldns_rr_list_rr(trusted_keys, i));
1069                                         if (equal) {
1070                                                 result = LDNS_STATUS_OK;
1071                                                 return result;
1072                                         }
1073                                 }
1074                         }
1075                         for (i = 0; i < tree->parent_count; i++) {
1076                                 parent_result =
1077                                         ldns_dnssec_trust_tree_contains_keys(tree->parents[i],
1078                                                                                                   trusted_keys);
1079                                 if (parent_result != LDNS_STATUS_CRYPTO_NO_DNSKEY) {
1080                                         if (tree->parent_status[i] != LDNS_STATUS_OK) {
1081                                                 result = tree->parent_status[i];
1082                                         } else {
1083                                                 if (tree->rr &&
1084                                                     ldns_rr_get_type(tree->rr)
1085                                                     == LDNS_RR_TYPE_NSEC &&
1086                                                     parent_result == LDNS_STATUS_OK
1087                                                     ) {
1088                                                         result =
1089                                                                 LDNS_STATUS_DNSSEC_EXISTENCE_DENIED;
1090                                                 } else {
1091                                                         result = parent_result;
1092                                                 }
1093                                         }
1094                                 }
1095                         }
1096                 } else {
1097                 result = LDNS_STATUS_ERR;
1098         }
1099         
1100         return result;
1101 }
1102
1103 ldns_status
1104 ldns_verify_time(
1105                 ldns_rr_list *rrset,
1106                 ldns_rr_list *rrsig, 
1107                 const ldns_rr_list *keys, 
1108                 time_t check_time,
1109                 ldns_rr_list *good_keys
1110                 )
1111 {
1112         uint16_t i;
1113         ldns_status verify_result = LDNS_STATUS_ERR;
1114
1115         if (!rrset || !rrsig || !keys) {
1116                 return LDNS_STATUS_ERR;
1117         }
1118
1119         if (ldns_rr_list_rr_count(rrset) < 1) {
1120                 return LDNS_STATUS_ERR;
1121         }
1122
1123         if (ldns_rr_list_rr_count(rrsig) < 1) {
1124                 return LDNS_STATUS_CRYPTO_NO_RRSIG;
1125         }
1126         
1127         if (ldns_rr_list_rr_count(keys) < 1) {
1128                 verify_result = LDNS_STATUS_CRYPTO_NO_TRUSTED_DNSKEY;
1129         } else {
1130                 for (i = 0; i < ldns_rr_list_rr_count(rrsig); i++) {
1131                         ldns_status s = ldns_verify_rrsig_keylist_time(
1132                                         rrset, ldns_rr_list_rr(rrsig, i), 
1133                                         keys, check_time, good_keys);
1134                         /* try a little to get more descriptive error */
1135                         if(s == LDNS_STATUS_OK) {
1136                                 verify_result = LDNS_STATUS_OK;
1137                         } else if(verify_result == LDNS_STATUS_ERR)
1138                                 verify_result = s;
1139                         else if(s !=  LDNS_STATUS_ERR && verify_result ==
1140                                 LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY)
1141                                 verify_result = s;
1142                 }
1143         }
1144         return verify_result;
1145 }
1146
1147 ldns_status
1148 ldns_verify(ldns_rr_list *rrset, ldns_rr_list *rrsig, const ldns_rr_list *keys, 
1149                   ldns_rr_list *good_keys)
1150 {
1151         return ldns_verify_time(rrset, rrsig, keys, ldns_time(NULL), good_keys);
1152 }
1153
1154 ldns_status
1155 ldns_verify_notime(ldns_rr_list *rrset, ldns_rr_list *rrsig,
1156         const ldns_rr_list *keys, ldns_rr_list *good_keys)
1157 {
1158         uint16_t i;
1159         ldns_status verify_result = LDNS_STATUS_ERR;
1160
1161         if (!rrset || !rrsig || !keys) {
1162                 return LDNS_STATUS_ERR;
1163         }
1164
1165         if (ldns_rr_list_rr_count(rrset) < 1) {
1166                 return LDNS_STATUS_ERR;
1167         }
1168
1169         if (ldns_rr_list_rr_count(rrsig) < 1) {
1170                 return LDNS_STATUS_CRYPTO_NO_RRSIG;
1171         }
1172
1173         if (ldns_rr_list_rr_count(keys) < 1) {
1174                 verify_result = LDNS_STATUS_CRYPTO_NO_TRUSTED_DNSKEY;
1175         } else {
1176                 for (i = 0; i < ldns_rr_list_rr_count(rrsig); i++) {
1177                         ldns_status s = ldns_verify_rrsig_keylist_notime(rrset,
1178                                 ldns_rr_list_rr(rrsig, i), keys, good_keys);
1179
1180                         /* try a little to get more descriptive error */
1181                         if (s == LDNS_STATUS_OK) {
1182                                 verify_result = LDNS_STATUS_OK;
1183                         } else if (verify_result == LDNS_STATUS_ERR) {
1184                                 verify_result = s;
1185                         } else if (s !=  LDNS_STATUS_ERR && verify_result ==
1186                                 LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY) {
1187                                 verify_result = s;
1188                         }
1189                 }
1190         }
1191         return verify_result;
1192 }
1193
1194 ldns_rr_list *
1195 ldns_fetch_valid_domain_keys_time(const ldns_resolver *res,
1196                              const ldns_rdf *domain,
1197                              const ldns_rr_list *keys,
1198                              time_t check_time,
1199                              ldns_status *status)
1200 {
1201         ldns_rr_list * trusted_keys = NULL;
1202         ldns_rr_list * ds_keys = NULL;
1203         ldns_rdf * prev_parent_domain;
1204         ldns_rdf *      parent_domain;
1205         ldns_rr_list * parent_keys = NULL;
1206
1207         if (res && domain && keys) {
1208
1209                 if ((trusted_keys = ldns_validate_domain_dnskey_time(res,
1210                                          domain, keys, check_time))) {
1211                         *status = LDNS_STATUS_OK;
1212                 } else {
1213                         /* No trusted keys in this domain, we'll have to find some in the parent domain */
1214                         *status = LDNS_STATUS_CRYPTO_NO_TRUSTED_DNSKEY;
1215
1216                         parent_domain = ldns_dname_left_chop(domain);
1217                         while (parent_domain && /* Fail if we are at the root*/
1218                                         ldns_rdf_size(parent_domain) > 0) {
1219         
1220                                 if ((parent_keys = 
1221                                         ldns_fetch_valid_domain_keys_time(res,
1222                                              parent_domain,
1223                                              keys,
1224                                              check_time,
1225                                              status))) {
1226                                         /* Check DS records */
1227                                         if ((ds_keys =
1228                                                 ldns_validate_domain_ds_time(res,
1229                                                      domain,
1230                                                      parent_keys,
1231                                                      check_time))) {
1232                                                 trusted_keys =
1233                                                 ldns_fetch_valid_domain_keys_time(
1234                                                                 res, 
1235                                                                 domain, 
1236                                                                 ds_keys, 
1237                                                                 check_time,
1238                                                                 status);
1239                                                 ldns_rr_list_deep_free(ds_keys);
1240                                         } else {
1241                                                 /* No valid DS at the parent -- fail */
1242                                                 *status = LDNS_STATUS_CRYPTO_NO_TRUSTED_DS ;
1243                                         }
1244                                         ldns_rr_list_deep_free(parent_keys);
1245                                         break;
1246                                 } else {
1247                                         parent_domain = ldns_dname_left_chop((
1248                                                 prev_parent_domain 
1249                                                         = parent_domain
1250                                                 ));
1251                                         ldns_rdf_deep_free(prev_parent_domain);
1252                                 }
1253                         }
1254                         if (parent_domain) {
1255                                 ldns_rdf_deep_free(parent_domain);
1256                         }
1257                 }
1258         }
1259         return trusted_keys;
1260 }
1261
1262 ldns_rr_list *
1263 ldns_fetch_valid_domain_keys(const ldns_resolver *res,
1264                              const ldns_rdf *domain,
1265                              const ldns_rr_list *keys,
1266                              ldns_status *status)
1267 {
1268         return ldns_fetch_valid_domain_keys_time(
1269                         res, domain, keys, ldns_time(NULL), status);
1270 }
1271
1272 ldns_rr_list *
1273 ldns_validate_domain_dnskey_time(
1274                 const ldns_resolver * res,
1275                 const ldns_rdf * domain,
1276                 const ldns_rr_list * keys,
1277                 time_t check_time
1278                 )
1279 {
1280         ldns_pkt * keypkt;
1281         ldns_rr * cur_key;
1282         uint16_t key_i; uint16_t key_j; uint16_t key_k;
1283         uint16_t sig_i; ldns_rr * cur_sig;
1284
1285         ldns_rr_list * domain_keys = NULL;
1286         ldns_rr_list * domain_sigs = NULL;
1287         ldns_rr_list * trusted_keys = NULL;
1288
1289         /* Fetch keys for the domain */
1290         keypkt = ldns_resolver_query(res, domain,
1291                 LDNS_RR_TYPE_DNSKEY, LDNS_RR_CLASS_IN, LDNS_RD);
1292         if (keypkt) {
1293                 domain_keys = ldns_pkt_rr_list_by_type(keypkt,
1294                                                                             LDNS_RR_TYPE_DNSKEY,
1295                                                                             LDNS_SECTION_ANSWER);
1296                 domain_sigs = ldns_pkt_rr_list_by_type(keypkt,
1297                                                                             LDNS_RR_TYPE_RRSIG,
1298                                                                             LDNS_SECTION_ANSWER);
1299
1300                 /* Try to validate the record using our keys */
1301                 for (key_i=0; key_i< ldns_rr_list_rr_count(domain_keys); key_i++) {
1302       
1303                         cur_key = ldns_rr_list_rr(domain_keys, key_i);
1304                         for (key_j=0; key_j<ldns_rr_list_rr_count(keys); key_j++) {
1305                                 if (ldns_rr_compare_ds(ldns_rr_list_rr(keys, key_j),
1306                                                                    cur_key)) {
1307           
1308                                         /* Current key is trusted -- validate */
1309                                         trusted_keys = ldns_rr_list_new();
1310           
1311                                         for (sig_i=0;
1312                                                 sig_i<ldns_rr_list_rr_count(domain_sigs);
1313                                                 sig_i++) {
1314                                                 cur_sig = ldns_rr_list_rr(domain_sigs, sig_i);
1315                                                 /* Avoid non-matching sigs */
1316                                                 if (ldns_rdf2native_int16(
1317                                                            ldns_rr_rrsig_keytag(cur_sig))
1318                                                     == ldns_calc_keytag(cur_key)) {
1319                                                         if (ldns_verify_rrsig_time(
1320                                                                         domain_keys,
1321                                                                         cur_sig,
1322                                                                         cur_key,
1323                                                                         check_time)
1324                                                             == LDNS_STATUS_OK) {
1325                 
1326                                                                 /* Push the whole rrset 
1327                                                                    -- we can't do much more */
1328                                                                 for (key_k=0;
1329                                                                         key_k<ldns_rr_list_rr_count(
1330                                                                                         domain_keys);
1331                                                                         key_k++) {
1332                                                                         ldns_rr_list_push_rr(
1333                                                                             trusted_keys,
1334                                                                             ldns_rr_clone(
1335                                                                                    ldns_rr_list_rr(
1336                                                                                           domain_keys,
1337                                                                                           key_k)));
1338                                                                 }
1339                 
1340                                                                 ldns_rr_list_deep_free(domain_keys);
1341                                                                 ldns_rr_list_deep_free(domain_sigs);
1342                                                                 ldns_pkt_free(keypkt);
1343                                                                 return trusted_keys;
1344                                                         }
1345                                                 }
1346                                         }
1347           
1348                                         /* Only push our trusted key */
1349                                         ldns_rr_list_push_rr(trusted_keys,
1350                                                                          ldns_rr_clone(cur_key));
1351                                 }
1352                         }
1353                 }
1354
1355                 ldns_rr_list_deep_free(domain_keys);
1356                 ldns_rr_list_deep_free(domain_sigs);
1357                 ldns_pkt_free(keypkt);
1358
1359         } else {
1360                 /* LDNS_STATUS_CRYPTO_NO_DNSKEY */
1361         }
1362     
1363         return trusted_keys;
1364 }
1365
1366 ldns_rr_list *
1367 ldns_validate_domain_dnskey(const ldns_resolver * res,
1368                                            const ldns_rdf * domain,
1369                                            const ldns_rr_list * keys)
1370 {
1371         return ldns_validate_domain_dnskey_time(
1372                         res, domain, keys, ldns_time(NULL));
1373 }
1374
1375 ldns_rr_list *
1376 ldns_validate_domain_ds_time(
1377                 const ldns_resolver *res, 
1378                 const ldns_rdf * domain,
1379                 const ldns_rr_list * keys,
1380                 time_t check_time)
1381 {
1382         ldns_pkt * dspkt;
1383         uint16_t key_i;
1384         ldns_rr_list * rrset = NULL;
1385         ldns_rr_list * sigs = NULL;
1386         ldns_rr_list * trusted_keys = NULL;
1387
1388         /* Fetch DS for the domain */
1389         dspkt = ldns_resolver_query(res, domain,
1390                 LDNS_RR_TYPE_DS, LDNS_RR_CLASS_IN, LDNS_RD);
1391         if (dspkt) {
1392                 rrset = ldns_pkt_rr_list_by_type(dspkt,
1393                                                                    LDNS_RR_TYPE_DS,
1394                                                                    LDNS_SECTION_ANSWER);
1395                 sigs = ldns_pkt_rr_list_by_type(dspkt,
1396                                                                   LDNS_RR_TYPE_RRSIG,
1397                                                                   LDNS_SECTION_ANSWER);
1398
1399                 /* Validate sigs */
1400                 if (ldns_verify_time(rrset, sigs, keys, check_time, NULL)
1401                                 == LDNS_STATUS_OK) {
1402                         trusted_keys = ldns_rr_list_new();
1403                         for (key_i=0; key_i<ldns_rr_list_rr_count(rrset); key_i++) {
1404                                 ldns_rr_list_push_rr(trusted_keys,
1405                                                                  ldns_rr_clone(ldns_rr_list_rr(rrset,
1406                                                                                                                  key_i)
1407                                                                                         )
1408                                                                  );
1409                         }
1410                 }
1411
1412                 ldns_rr_list_deep_free(rrset);
1413                 ldns_rr_list_deep_free(sigs);
1414                 ldns_pkt_free(dspkt);
1415
1416         } else {
1417                 /* LDNS_STATUS_CRYPTO_NO_DS */
1418         }
1419
1420         return trusted_keys;
1421 }
1422
1423 ldns_rr_list *
1424 ldns_validate_domain_ds(const ldns_resolver *res,
1425                                     const ldns_rdf * domain,
1426                                     const ldns_rr_list * keys)
1427 {
1428         return ldns_validate_domain_ds_time(res, domain, keys, ldns_time(NULL));
1429 }
1430
1431 ldns_status
1432 ldns_verify_trusted_time(
1433                 ldns_resolver *res, 
1434                 ldns_rr_list *rrset, 
1435                 ldns_rr_list * rrsigs, 
1436                 time_t check_time,
1437                 ldns_rr_list * validating_keys
1438                 )
1439 {
1440         uint16_t sig_i; uint16_t key_i;
1441         ldns_rr * cur_sig; ldns_rr * cur_key;
1442         ldns_rr_list * trusted_keys = NULL;
1443         ldns_status result = LDNS_STATUS_ERR;
1444
1445         if (!res || !rrset || !rrsigs) {
1446                 return LDNS_STATUS_ERR;
1447         }
1448
1449         if (ldns_rr_list_rr_count(rrset) < 1) {
1450                 return LDNS_STATUS_ERR;
1451         }
1452
1453         if (ldns_rr_list_rr_count(rrsigs) < 1) {
1454                 return LDNS_STATUS_CRYPTO_NO_RRSIG;
1455         }
1456   
1457         /* Look at each sig */
1458         for (sig_i=0; sig_i < ldns_rr_list_rr_count(rrsigs); sig_i++) {
1459
1460                 cur_sig = ldns_rr_list_rr(rrsigs, sig_i);
1461                 /* Get a valid signer key and validate the sig */
1462                 if ((trusted_keys = ldns_fetch_valid_domain_keys_time(
1463                                         res, 
1464                                         ldns_rr_rrsig_signame(cur_sig), 
1465                                         ldns_resolver_dnssec_anchors(res), 
1466                                         check_time,
1467                                         &result))) {
1468
1469                         for (key_i = 0;
1470                                 key_i < ldns_rr_list_rr_count(trusted_keys);
1471                                 key_i++) {
1472                                 cur_key = ldns_rr_list_rr(trusted_keys, key_i);
1473
1474                                 if ((result = ldns_verify_rrsig_time(rrset,
1475                                                                 cur_sig, 
1476                                                                 cur_key,
1477                                                                 check_time))
1478                                     == LDNS_STATUS_OK) {
1479                                         if (validating_keys) {
1480                                                 ldns_rr_list_push_rr(validating_keys,
1481                                                                                  ldns_rr_clone(cur_key));
1482                                         }
1483                                         ldns_rr_list_deep_free(trusted_keys);
1484                                         return LDNS_STATUS_OK;
1485                                 } 
1486                         }
1487                 }
1488         }
1489
1490         ldns_rr_list_deep_free(trusted_keys);
1491         return result;
1492 }
1493
1494 ldns_status
1495 ldns_verify_trusted(
1496                 ldns_resolver *res,
1497                 ldns_rr_list *rrset, 
1498                 ldns_rr_list * rrsigs, 
1499                 ldns_rr_list * validating_keys)
1500 {
1501         return ldns_verify_trusted_time(
1502                         res, rrset, rrsigs, ldns_time(NULL), validating_keys);
1503 }
1504
1505
1506 ldns_status
1507 ldns_dnssec_verify_denial(ldns_rr *rr,
1508                           ldns_rr_list *nsecs,
1509                           ldns_rr_list *rrsigs)
1510 {
1511         ldns_rdf *rr_name;
1512         ldns_rdf *wildcard_name;
1513         ldns_rdf *chopped_dname;
1514         ldns_rr *cur_nsec;
1515         size_t i;
1516         ldns_status result;
1517         /* needed for wildcard check on exact match */
1518         ldns_rr *rrsig;
1519         bool name_covered = false;
1520         bool type_covered = false;
1521         bool wildcard_covered = false;
1522         bool wildcard_type_covered = false;
1523
1524         wildcard_name = ldns_dname_new_frm_str("*");
1525         rr_name = ldns_rr_owner(rr);
1526         chopped_dname = ldns_dname_left_chop(rr_name);
1527         result = ldns_dname_cat(wildcard_name, chopped_dname);
1528         ldns_rdf_deep_free(chopped_dname);
1529         if (result != LDNS_STATUS_OK) {
1530                 return result;
1531         }
1532         
1533         for  (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) {
1534                 cur_nsec = ldns_rr_list_rr(nsecs, i);
1535                 if (ldns_dname_compare(rr_name, ldns_rr_owner(cur_nsec)) == 0) {
1536                         /* see section 5.4 of RFC4035, if the label count of the NSEC's
1537                            RRSIG is equal, then it is proven that wildcard expansion 
1538                            could not have been used to match the request */
1539                         rrsig = ldns_dnssec_get_rrsig_for_name_and_type(
1540                                           ldns_rr_owner(cur_nsec),
1541                                           ldns_rr_get_type(cur_nsec),
1542                                           rrsigs);
1543                         if (rrsig && ldns_rdf2native_int8(ldns_rr_rrsig_labels(rrsig))
1544                             == ldns_dname_label_count(rr_name)) {
1545                                 wildcard_covered = true;
1546                         }
1547                         
1548                         if (ldns_nsec_bitmap_covers_type(ldns_nsec_get_bitmap(cur_nsec),
1549                                                                            ldns_rr_get_type(rr))) {
1550                                 type_covered = true;
1551                         }
1552                 }
1553                 if (ldns_nsec_covers_name(cur_nsec, rr_name)) {
1554                         name_covered = true;
1555                 }
1556                 
1557                 if (ldns_dname_compare(wildcard_name,
1558                                                    ldns_rr_owner(cur_nsec)) == 0) {
1559                         if (ldns_nsec_bitmap_covers_type(ldns_nsec_get_bitmap(cur_nsec),
1560                                                                            ldns_rr_get_type(rr))) {
1561                                 wildcard_type_covered = true;
1562                         }
1563                 }
1564                 
1565                 if (ldns_nsec_covers_name(cur_nsec, wildcard_name)) {
1566                         wildcard_covered = true;
1567                 }
1568                 
1569         }
1570         
1571         ldns_rdf_deep_free(wildcard_name);
1572         
1573         if (type_covered || !name_covered) {
1574                 return LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED;
1575         }
1576         
1577         if (wildcard_type_covered || !wildcard_covered) {
1578                 return LDNS_STATUS_DNSSEC_NSEC_WILDCARD_NOT_COVERED;
1579         }
1580
1581         return LDNS_STATUS_OK;
1582 }
1583
1584 ldns_status
1585 ldns_dnssec_verify_denial_nsec3_match( ldns_rr *rr
1586                                      , ldns_rr_list *nsecs
1587                                      , ATTR_UNUSED(ldns_rr_list *rrsigs)
1588                                      , ldns_pkt_rcode packet_rcode
1589                                      , ldns_rr_type packet_qtype
1590                                      , bool packet_nodata
1591                                      , ldns_rr **match
1592                                      )
1593 {
1594         ldns_rdf *closest_encloser;
1595         ldns_rdf *wildcard;
1596         ldns_rdf *hashed_wildcard_name;
1597         bool wildcard_covered = false;
1598         ldns_rdf *zone_name;
1599         ldns_rdf *hashed_name;
1600         /* self assignment to suppress uninitialized warning */
1601         ldns_rdf *next_closer = next_closer;
1602         ldns_rdf *hashed_next_closer;
1603         size_t i;
1604         ldns_status result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED;
1605
1606         if (match) {
1607                 *match = NULL;
1608         }
1609
1610         zone_name = ldns_dname_left_chop(ldns_rr_owner(ldns_rr_list_rr(nsecs,0)));
1611
1612         /* section 8.4 */
1613         if (packet_rcode == LDNS_RCODE_NXDOMAIN) {
1614                 closest_encloser = ldns_dnssec_nsec3_closest_encloser(
1615                                                    ldns_rr_owner(rr),
1616                                                    ldns_rr_get_type(rr),
1617                                                    nsecs);
1618                 if(!closest_encloser) {
1619                         result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED;
1620                         goto done;
1621                 }
1622
1623                 wildcard = ldns_dname_new_frm_str("*");
1624                 (void) ldns_dname_cat(wildcard, closest_encloser);
1625
1626                 for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) {
1627                         hashed_wildcard_name =
1628                                 ldns_nsec3_hash_name_frm_nsec3(ldns_rr_list_rr(nsecs, 0),
1629                                                                                  wildcard
1630                                                                                  );
1631                         (void) ldns_dname_cat(hashed_wildcard_name, zone_name);
1632
1633                         if (ldns_nsec_covers_name(ldns_rr_list_rr(nsecs, i),
1634                                                                  hashed_wildcard_name)) {
1635                                 wildcard_covered = true;
1636                                 if (match) {
1637                                         *match = ldns_rr_list_rr(nsecs, i);
1638                                 }
1639                         }
1640                         ldns_rdf_deep_free(hashed_wildcard_name);
1641                 }
1642
1643                 if (! wildcard_covered) {
1644                         result = LDNS_STATUS_DNSSEC_NSEC_WILDCARD_NOT_COVERED;
1645                 } else {
1646                         result = LDNS_STATUS_OK;
1647                 }
1648                 ldns_rdf_deep_free(closest_encloser);
1649                 ldns_rdf_deep_free(wildcard);
1650
1651         } else if (packet_nodata && packet_qtype != LDNS_RR_TYPE_DS) {
1652                 /* section 8.5 */
1653                 hashed_name = ldns_nsec3_hash_name_frm_nsec3(
1654                                    ldns_rr_list_rr(nsecs, 0),
1655                                    ldns_rr_owner(rr));
1656                 (void) ldns_dname_cat(hashed_name, zone_name);
1657                 for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) {
1658                         if (ldns_dname_compare(hashed_name,
1659                                  ldns_rr_owner(ldns_rr_list_rr(nsecs, i)))
1660                             == 0) {
1661                                 if (!ldns_nsec_bitmap_covers_type(
1662                                             ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)),
1663                                             packet_qtype)
1664                                     &&
1665                                     !ldns_nsec_bitmap_covers_type(
1666                                             ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)),
1667                                             LDNS_RR_TYPE_CNAME)) {
1668                                         result = LDNS_STATUS_OK;
1669                                         if (match) {
1670                                                 *match = ldns_rr_list_rr(nsecs, i);
1671                                         }
1672                                         goto done;
1673                                 }
1674                         }
1675                 }
1676                 result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED;
1677                 /* wildcard no data? section 8.7 */
1678                 closest_encloser = ldns_dnssec_nsec3_closest_encloser(
1679                                    ldns_rr_owner(rr),
1680                                    ldns_rr_get_type(rr),
1681                                    nsecs);
1682                 if(!closest_encloser) {
1683                         result = LDNS_STATUS_NSEC3_ERR;
1684                         goto done;
1685                 }
1686                 wildcard = ldns_dname_new_frm_str("*");
1687                 (void) ldns_dname_cat(wildcard, closest_encloser);
1688                 for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) {
1689                         hashed_wildcard_name =
1690                                 ldns_nsec3_hash_name_frm_nsec3(ldns_rr_list_rr(nsecs, 0),
1691                                          wildcard);
1692                         (void) ldns_dname_cat(hashed_wildcard_name, zone_name);
1693
1694                         if (ldns_dname_compare(hashed_wildcard_name,
1695                                  ldns_rr_owner(ldns_rr_list_rr(nsecs, i)))
1696                             == 0) {
1697                                 if (!ldns_nsec_bitmap_covers_type(
1698                                             ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)),
1699                                             packet_qtype)
1700                                     &&
1701                                     !ldns_nsec_bitmap_covers_type(
1702                                             ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)),
1703                                             LDNS_RR_TYPE_CNAME)) {
1704                                         result = LDNS_STATUS_OK;
1705                                         if (match) {
1706                                                 *match = ldns_rr_list_rr(nsecs, i);
1707                                         }
1708                                 }
1709                         }
1710                         ldns_rdf_deep_free(hashed_wildcard_name);
1711                         if (result == LDNS_STATUS_OK) {
1712                                 break;
1713                         }
1714                 }
1715                 ldns_rdf_deep_free(closest_encloser);
1716                 ldns_rdf_deep_free(wildcard);
1717         } else if (packet_nodata && packet_qtype == LDNS_RR_TYPE_DS) {
1718                 /* section 8.6 */
1719                 /* note: up to XXX this is the same as for 8.5 */
1720                 hashed_name = ldns_nsec3_hash_name_frm_nsec3(ldns_rr_list_rr(nsecs,
1721                                                                                                                  0),
1722                                                                                         ldns_rr_owner(rr)
1723                                                                                         );
1724                 (void) ldns_dname_cat(hashed_name, zone_name);
1725                 for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) {
1726                         if (ldns_dname_compare(hashed_name,
1727                                                            ldns_rr_owner(ldns_rr_list_rr(nsecs,
1728                                                                                                            i)))
1729                             == 0) {
1730                                 if (!ldns_nsec_bitmap_covers_type(
1731                                             ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)),
1732                                             LDNS_RR_TYPE_DS)
1733                                     && 
1734                                     !ldns_nsec_bitmap_covers_type(
1735                                             ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)),
1736                                             LDNS_RR_TYPE_CNAME)) {
1737                                         result = LDNS_STATUS_OK;
1738                                         if (match) {
1739                                                 *match = ldns_rr_list_rr(nsecs, i);
1740                                         }
1741                                         goto done;
1742                                 }
1743                         }
1744                 }
1745
1746                 /* XXX see note above */
1747                 result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED;
1748
1749                 closest_encloser = ldns_dnssec_nsec3_closest_encloser(
1750                                    ldns_rr_owner(rr),
1751                                    ldns_rr_get_type(rr),
1752                                    nsecs);
1753                 if(!closest_encloser) {
1754                         result = LDNS_STATUS_NSEC3_ERR;
1755                         goto done;
1756                 }
1757                 /* Now check if we have a Opt-Out NSEC3 that covers the "next closer"*/
1758
1759                 if (ldns_dname_label_count(closest_encloser) + 1
1760                     >= ldns_dname_label_count(ldns_rr_owner(rr))) {
1761                         
1762                         /* Query name *is* the "next closer". */
1763                         hashed_next_closer = hashed_name;
1764                 } else {
1765
1766                         /* "next closer" has less labels than the query name.
1767                          * Create the name and hash it.
1768                          */
1769                         next_closer = ldns_dname_clone_from(
1770                                         ldns_rr_owner(rr),
1771                                         ldns_dname_label_count(ldns_rr_owner(rr))
1772                                         - (ldns_dname_label_count(closest_encloser) + 1)
1773                                         );
1774                         hashed_next_closer = ldns_nsec3_hash_name_frm_nsec3(
1775                                         ldns_rr_list_rr(nsecs, 0),
1776                                         next_closer
1777                                         );
1778                         (void) ldns_dname_cat(hashed_next_closer, zone_name);
1779                 }
1780                 /* Find the NSEC3 that covers the "next closer" */
1781                 for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) {
1782                         if (ldns_nsec_covers_name(ldns_rr_list_rr(nsecs, i),
1783                                                   hashed_next_closer) && 
1784                                 ldns_nsec3_optout(ldns_rr_list_rr(nsecs, i))) {
1785
1786                                 result = LDNS_STATUS_OK;
1787                                 if (match) {
1788                                         *match = ldns_rr_list_rr(nsecs, i);
1789                                 }
1790                                 break;
1791                         }
1792                 }
1793                 if (ldns_dname_label_count(closest_encloser) + 1
1794                     < ldns_dname_label_count(ldns_rr_owner(rr))) {
1795
1796                         /* "next closer" has less labels than the query name.
1797                          * Dispose of the temporary variables that held that name.
1798                          */
1799                         ldns_rdf_deep_free(hashed_next_closer);
1800                         ldns_rdf_deep_free(next_closer);
1801                 }
1802                 ldns_rdf_deep_free(closest_encloser);
1803         }
1804
1805  done:
1806         ldns_rdf_deep_free(zone_name);
1807         return result;
1808 }
1809
1810 ldns_status
1811 ldns_dnssec_verify_denial_nsec3(ldns_rr *rr,
1812                                                   ldns_rr_list *nsecs,
1813                                                   ldns_rr_list *rrsigs,
1814                                                   ldns_pkt_rcode packet_rcode,
1815                                                   ldns_rr_type packet_qtype,
1816                                                   bool packet_nodata)
1817 {
1818         return ldns_dnssec_verify_denial_nsec3_match(
1819                                 rr, nsecs, rrsigs, packet_rcode,
1820                                 packet_qtype, packet_nodata, NULL
1821                );
1822 }
1823
1824 #ifdef USE_GOST
1825 EVP_PKEY*
1826 ldns_gost2pkey_raw(unsigned char* key, size_t keylen)
1827 {
1828         /* prefix header for X509 encoding */
1829         uint8_t asn[37] = { 0x30, 0x63, 0x30, 0x1c, 0x06, 0x06, 0x2a, 0x85, 
1830                 0x03, 0x02, 0x02, 0x13, 0x30, 0x12, 0x06, 0x07, 0x2a, 0x85, 
1831                 0x03, 0x02, 0x02, 0x23, 0x01, 0x06, 0x07, 0x2a, 0x85, 0x03, 
1832                 0x02, 0x02, 0x1e, 0x01, 0x03, 0x43, 0x00, 0x04, 0x40};
1833         unsigned char encoded[37+64];
1834         const unsigned char* pp;
1835         if(keylen != 64) {
1836                 /* key wrong size */
1837                 return NULL;
1838         }
1839
1840         /* create evp_key */
1841         memmove(encoded, asn, 37);
1842         memmove(encoded+37, key, 64);
1843         pp = (unsigned char*)&encoded[0];
1844
1845         return d2i_PUBKEY(NULL, &pp, (int)sizeof(encoded));
1846 }
1847
1848 static ldns_status
1849 ldns_verify_rrsig_gost_raw(unsigned char* sig, size_t siglen, 
1850         ldns_buffer* rrset, unsigned char* key, size_t keylen)
1851 {
1852         EVP_PKEY *evp_key;
1853         ldns_status result;
1854
1855         (void) ldns_key_EVP_load_gost_id();
1856         evp_key = ldns_gost2pkey_raw(key, keylen);
1857         if(!evp_key) {
1858                 /* could not convert key */
1859                 return LDNS_STATUS_CRYPTO_BOGUS;
1860         }
1861
1862         /* verify signature */
1863         result = ldns_verify_rrsig_evp_raw(sig, siglen, rrset, 
1864                 evp_key, EVP_get_digestbyname("md_gost94"));
1865         EVP_PKEY_free(evp_key);
1866
1867         return result;
1868 }
1869 #endif
1870
1871 #ifdef USE_ECDSA
1872 EVP_PKEY*
1873 ldns_ecdsa2pkey_raw(unsigned char* key, size_t keylen, uint8_t algo)
1874 {
1875         unsigned char buf[256+2]; /* sufficient for 2*384/8+1 */
1876         const unsigned char* pp = buf;
1877         EVP_PKEY *evp_key;
1878         EC_KEY *ec;
1879         /* check length, which uncompressed must be 2 bignums */
1880         if(algo == LDNS_ECDSAP256SHA256) {
1881                 if(keylen != 2*256/8) return NULL;
1882                 ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
1883         } else if(algo == LDNS_ECDSAP384SHA384) {
1884                 if(keylen != 2*384/8) return NULL;
1885                 ec = EC_KEY_new_by_curve_name(NID_secp384r1);
1886         } else    ec = NULL;
1887         if(!ec) return NULL;
1888         if(keylen+1 > sizeof(buf))
1889                 return NULL; /* sanity check */
1890         /* prepend the 0x02 (from docs) (or actually 0x04 from implementation
1891          * of openssl) for uncompressed data */
1892         buf[0] = POINT_CONVERSION_UNCOMPRESSED;
1893         memmove(buf+1, key, keylen);
1894         if(!o2i_ECPublicKey(&ec, &pp, (int)keylen+1)) {
1895                 EC_KEY_free(ec);
1896                 return NULL;
1897         }
1898         evp_key = EVP_PKEY_new();
1899         if(!evp_key) {
1900                 EC_KEY_free(ec);
1901                 return NULL;
1902         }
1903         if (!EVP_PKEY_assign_EC_KEY(evp_key, ec)) {
1904                 EVP_PKEY_free(evp_key);
1905                 EC_KEY_free(ec);
1906                 return NULL;
1907         }
1908         return evp_key;
1909 }
1910
1911 static ldns_status
1912 ldns_verify_rrsig_ecdsa_raw(unsigned char* sig, size_t siglen, 
1913         ldns_buffer* rrset, unsigned char* key, size_t keylen, uint8_t algo)
1914 {
1915         EVP_PKEY *evp_key;
1916         ldns_status result;
1917         const EVP_MD *d;
1918
1919         evp_key = ldns_ecdsa2pkey_raw(key, keylen, algo);
1920         if(!evp_key) {
1921                 /* could not convert key */
1922                 return LDNS_STATUS_CRYPTO_BOGUS;
1923         }
1924         if(algo == LDNS_ECDSAP256SHA256)
1925                 d = EVP_sha256();
1926         else    d = EVP_sha384(); /* LDNS_ECDSAP384SHA384 */
1927         result = ldns_verify_rrsig_evp_raw(sig, siglen, rrset, evp_key, d);
1928         EVP_PKEY_free(evp_key);
1929         return result;
1930 }
1931 #endif
1932
1933 ldns_status
1934 ldns_verify_rrsig_buffers(ldns_buffer *rawsig_buf, ldns_buffer *verify_buf, 
1935                                          ldns_buffer *key_buf, uint8_t algo)
1936 {
1937         return ldns_verify_rrsig_buffers_raw(
1938                          (unsigned char*)ldns_buffer_begin(rawsig_buf),
1939                          ldns_buffer_position(rawsig_buf),
1940                          verify_buf,
1941                          (unsigned char*)ldns_buffer_begin(key_buf), 
1942                          ldns_buffer_position(key_buf), algo);
1943 }
1944
1945 ldns_status
1946 ldns_verify_rrsig_buffers_raw(unsigned char* sig, size_t siglen,
1947                                                 ldns_buffer *verify_buf, unsigned char* key, size_t keylen, 
1948                                                 uint8_t algo)
1949 {
1950         /* check for right key */
1951         switch(algo) {
1952         case LDNS_DSA:
1953         case LDNS_DSA_NSEC3:
1954                 return ldns_verify_rrsig_dsa_raw(sig,
1955                                                                    siglen,
1956                                                                    verify_buf,
1957                                                                    key,
1958                                                                    keylen);
1959                 break;
1960         case LDNS_RSASHA1:
1961         case LDNS_RSASHA1_NSEC3:
1962                 return ldns_verify_rrsig_rsasha1_raw(sig,
1963                                                                           siglen,
1964                                                                           verify_buf,
1965                                                                           key,
1966                                                                           keylen);
1967                 break;
1968 #ifdef USE_SHA2
1969         case LDNS_RSASHA256:
1970                 return ldns_verify_rrsig_rsasha256_raw(sig,
1971                                                                             siglen,
1972                                                                             verify_buf,
1973                                                                             key,
1974                                                                             keylen);
1975                 break;
1976         case LDNS_RSASHA512:
1977                 return ldns_verify_rrsig_rsasha512_raw(sig,
1978                                                                             siglen,
1979                                                                             verify_buf,
1980                                                                             key,
1981                                                                             keylen);
1982                 break;
1983 #endif
1984 #ifdef USE_GOST
1985         case LDNS_ECC_GOST:
1986                 return ldns_verify_rrsig_gost_raw(sig, siglen, verify_buf,
1987                         key, keylen);
1988                 break;
1989 #endif
1990 #ifdef USE_ECDSA
1991         case LDNS_ECDSAP256SHA256:
1992         case LDNS_ECDSAP384SHA384:
1993                 return ldns_verify_rrsig_ecdsa_raw(sig, siglen, verify_buf,
1994                         key, keylen, algo);
1995                 break;
1996 #endif
1997         case LDNS_RSAMD5:
1998                 return ldns_verify_rrsig_rsamd5_raw(sig,
1999                                                                          siglen,
2000                                                                          verify_buf,
2001                                                                          key,
2002                                                                          keylen);
2003                 break;
2004         default:
2005                 /* do you know this alg?! */
2006                 return LDNS_STATUS_CRYPTO_UNKNOWN_ALGO;
2007         }
2008 }
2009
2010
2011 /**
2012  * Reset the ttl in the rrset with the orig_ttl from the sig 
2013  * and update owner name if it was wildcard 
2014  * Also canonicalizes the rrset.
2015  * @param rrset: rrset to modify
2016  * @param sig: signature to take TTL and wildcard values from
2017  */
2018 static void
2019 ldns_rrset_use_signature_ttl(ldns_rr_list* rrset_clone, ldns_rr* rrsig)
2020 {
2021         uint32_t orig_ttl;
2022         uint16_t i;
2023         uint8_t label_count;
2024         ldns_rdf *wildcard_name;
2025         ldns_rdf *wildcard_chopped;
2026         ldns_rdf *wildcard_chopped_tmp;
2027         
2028         if ((rrsig == NULL) || ldns_rr_rd_count(rrsig) < 4) {
2029                 return;
2030         }
2031
2032         orig_ttl = ldns_rdf2native_int32( ldns_rr_rdf(rrsig, 3));
2033         label_count = ldns_rdf2native_int8(ldns_rr_rdf(rrsig, 2));
2034
2035         for(i = 0; i < ldns_rr_list_rr_count(rrset_clone); i++) {
2036                 if (label_count < 
2037                     ldns_dname_label_count(
2038                            ldns_rr_owner(ldns_rr_list_rr(rrset_clone, i)))) {
2039                         (void) ldns_str2rdf_dname(&wildcard_name, "*");
2040                         wildcard_chopped = ldns_rdf_clone(ldns_rr_owner(
2041                                 ldns_rr_list_rr(rrset_clone, i)));
2042                         while (label_count < ldns_dname_label_count(wildcard_chopped)) {
2043                                 wildcard_chopped_tmp = ldns_dname_left_chop(
2044                                         wildcard_chopped);
2045                                 ldns_rdf_deep_free(wildcard_chopped);
2046                                 wildcard_chopped = wildcard_chopped_tmp;
2047                         }
2048                         (void) ldns_dname_cat(wildcard_name, wildcard_chopped);
2049                         ldns_rdf_deep_free(wildcard_chopped);
2050                         ldns_rdf_deep_free(ldns_rr_owner(ldns_rr_list_rr(
2051                                 rrset_clone, i)));
2052                         ldns_rr_set_owner(ldns_rr_list_rr(rrset_clone, i), 
2053                                 wildcard_name);
2054                 }
2055                 ldns_rr_set_ttl(ldns_rr_list_rr(rrset_clone, i), orig_ttl);
2056                 /* convert to lowercase */
2057                 ldns_rr2canonical(ldns_rr_list_rr(rrset_clone, i));
2058         }
2059 }
2060
2061 /**
2062  * Make raw signature buffer out of rrsig
2063  * @param rawsig_buf: raw signature buffer for result
2064  * @param rrsig: signature to convert
2065  * @return OK or more specific error.
2066  */
2067 static ldns_status
2068 ldns_rrsig2rawsig_buffer(ldns_buffer* rawsig_buf, ldns_rr* rrsig)
2069 {
2070         uint8_t sig_algo;
2071        
2072         if (rrsig == NULL) {
2073                 return LDNS_STATUS_CRYPTO_NO_RRSIG;
2074         }
2075         if (ldns_rr_rdf(rrsig, 1) == NULL) {
2076                 return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG;
2077         }
2078         sig_algo = ldns_rdf2native_int8(ldns_rr_rdf(rrsig, 1));
2079         /* check for known and implemented algo's now (otherwise 
2080          * the function could return a wrong error
2081          */
2082         /* create a buffer with signature rdata */
2083         /* for some algorithms we need other data than for others... */
2084         /* (the DSA API wants DER encoding for instance) */
2085
2086         switch(sig_algo) {
2087         case LDNS_RSAMD5:
2088         case LDNS_RSASHA1:
2089         case LDNS_RSASHA1_NSEC3:
2090 #ifdef USE_SHA2
2091         case LDNS_RSASHA256:
2092         case LDNS_RSASHA512:
2093 #endif
2094 #ifdef USE_GOST
2095         case LDNS_ECC_GOST:
2096 #endif
2097                 if (ldns_rr_rdf(rrsig, 8) == NULL) {
2098                         return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG;
2099                 }
2100                 if (ldns_rdf2buffer_wire(rawsig_buf, ldns_rr_rdf(rrsig, 8))
2101                                 != LDNS_STATUS_OK) {
2102                         return LDNS_STATUS_MEM_ERR;
2103                 }
2104                 break;
2105         case LDNS_DSA:
2106         case LDNS_DSA_NSEC3:
2107                 /* EVP takes rfc2459 format, which is a tad longer than dns format */
2108                 if (ldns_rr_rdf(rrsig, 8) == NULL) {
2109                         return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG;
2110                 }
2111                 if (ldns_convert_dsa_rrsig_rdf2asn1(
2112                                         rawsig_buf, ldns_rr_rdf(rrsig, 8)) 
2113                                 != LDNS_STATUS_OK) {
2114                         /*
2115                           if (ldns_rdf2buffer_wire(rawsig_buf,
2116                           ldns_rr_rdf(rrsig, 8)) != LDNS_STATUS_OK) {
2117                         */
2118                         return LDNS_STATUS_MEM_ERR;
2119                 }
2120                 break;
2121 #ifdef USE_ECDSA
2122         case LDNS_ECDSAP256SHA256:
2123         case LDNS_ECDSAP384SHA384:
2124                 /* EVP produces an ASN prefix on the signature, which is
2125                  * not used in the DNS */
2126                 if (ldns_rr_rdf(rrsig, 8) == NULL) {
2127                         return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG;
2128                 }
2129                 if (ldns_convert_ecdsa_rrsig_rdf2asn1(
2130                                         rawsig_buf, ldns_rr_rdf(rrsig, 8))
2131                                 != LDNS_STATUS_OK) {
2132                         return LDNS_STATUS_MEM_ERR;
2133                 }
2134                 break;
2135 #endif
2136         case LDNS_DH:
2137         case LDNS_ECC:
2138         case LDNS_INDIRECT:
2139                 return LDNS_STATUS_CRYPTO_ALGO_NOT_IMPL;
2140         default:
2141                 return LDNS_STATUS_CRYPTO_UNKNOWN_ALGO;
2142         }
2143         return LDNS_STATUS_OK;
2144 }
2145
2146 /**
2147  * Check RRSIG timestamps against the given 'now' time.
2148  * @param rrsig: signature to check.
2149  * @param now: the current time in seconds epoch.
2150  * @return status code LDNS_STATUS_OK if all is fine.
2151  */
2152 static ldns_status
2153 ldns_rrsig_check_timestamps(ldns_rr* rrsig, time_t now)
2154 {
2155         int32_t inception, expiration;
2156         
2157         /* check the signature time stamps */
2158         inception = (int32_t)ldns_rdf2native_time_t(
2159                 ldns_rr_rrsig_inception(rrsig));
2160         expiration = (int32_t)ldns_rdf2native_time_t(
2161                 ldns_rr_rrsig_expiration(rrsig));
2162
2163         if (expiration - inception < 0) {
2164                 /* bad sig, expiration before inception?? Tsssg */
2165                 return LDNS_STATUS_CRYPTO_EXPIRATION_BEFORE_INCEPTION;
2166         }
2167         if (((int32_t) now) - inception < 0) {
2168                 /* bad sig, inception date has not yet come to pass */
2169                 return LDNS_STATUS_CRYPTO_SIG_NOT_INCEPTED;
2170         }
2171         if (expiration - ((int32_t) now) < 0) {
2172                 /* bad sig, expiration date has passed */
2173                 return LDNS_STATUS_CRYPTO_SIG_EXPIRED;
2174         }
2175         return LDNS_STATUS_OK;
2176 }
2177
2178 /**
2179  * Prepare for verification.
2180  * @param rawsig_buf: raw signature buffer made ready.
2181  * @param verify_buf: data for verification buffer made ready.
2182  * @param rrset_clone: made ready.
2183  * @param rrsig: signature to prepare for.
2184  * @return LDNS_STATUS_OK is all went well. Otherwise specific error.
2185  */
2186 static ldns_status
2187 ldns_prepare_for_verify(ldns_buffer* rawsig_buf, ldns_buffer* verify_buf, 
2188         ldns_rr_list* rrset_clone, ldns_rr* rrsig)
2189 {
2190         ldns_status result;
2191
2192         /* canonicalize the sig */
2193         ldns_dname2canonical(ldns_rr_owner(rrsig));
2194         
2195         /* check if the typecovered is equal to the type checked */
2196         if (ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rrsig)) !=
2197             ldns_rr_get_type(ldns_rr_list_rr(rrset_clone, 0)))
2198                 return LDNS_STATUS_CRYPTO_TYPE_COVERED_ERR;
2199         
2200         /* create a buffer with b64 signature rdata */
2201         result = ldns_rrsig2rawsig_buffer(rawsig_buf, rrsig);
2202         if(result != LDNS_STATUS_OK)
2203                 return result;
2204
2205         /* use TTL from signature. Use wildcard names for wildcards */
2206         /* also canonicalizes rrset_clone */
2207         ldns_rrset_use_signature_ttl(rrset_clone, rrsig);
2208
2209         /* sort the rrset in canonical order  */
2210         ldns_rr_list_sort(rrset_clone);
2211
2212         /* put the signature rr (without the b64) to the verify_buf */
2213         if (ldns_rrsig2buffer_wire(verify_buf, rrsig) != LDNS_STATUS_OK)
2214                 return LDNS_STATUS_MEM_ERR;
2215
2216         /* add the rrset in verify_buf */
2217         if(ldns_rr_list2buffer_wire(verify_buf, rrset_clone) 
2218                 != LDNS_STATUS_OK)
2219                 return LDNS_STATUS_MEM_ERR;
2220
2221         return LDNS_STATUS_OK;
2222 }
2223
2224 /**
2225  * Check if a key matches a signature.
2226  * Checks keytag, sigalgo and signature.
2227  * @param rawsig_buf: raw signature buffer for verify
2228  * @param verify_buf: raw data buffer for verify
2229  * @param rrsig: the rrsig
2230  * @param key: key to attempt.
2231  * @return LDNS_STATUS_OK if OK, else some specific error.
2232  */
2233 static ldns_status
2234 ldns_verify_test_sig_key(ldns_buffer* rawsig_buf, ldns_buffer* verify_buf, 
2235         ldns_rr* rrsig, ldns_rr* key)
2236 {
2237         uint8_t sig_algo;
2238        
2239         if (rrsig == NULL) {
2240                 return LDNS_STATUS_CRYPTO_NO_RRSIG;
2241         }
2242         if (ldns_rr_rdf(rrsig, 1) == NULL) {
2243                 return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG;
2244         }
2245         sig_algo = ldns_rdf2native_int8(ldns_rr_rdf(rrsig, 1));
2246
2247         /* before anything, check if the keytags match */
2248         if (ldns_calc_keytag(key)
2249             ==
2250             ldns_rdf2native_int16(ldns_rr_rrsig_keytag(rrsig))
2251             ) {
2252                 ldns_buffer* key_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN);
2253                 ldns_status result = LDNS_STATUS_ERR;
2254
2255                 /* put the key-data in a buffer, that's the third rdf, with
2256                  * the base64 encoded key data */
2257                 if (ldns_rr_rdf(key, 3) == NULL) {
2258                         ldns_buffer_free(key_buf);
2259                         return LDNS_STATUS_MISSING_RDATA_FIELDS_KEY;
2260                 }
2261                 if (ldns_rdf2buffer_wire(key_buf, ldns_rr_rdf(key, 3))
2262                                 != LDNS_STATUS_OK) {
2263                         ldns_buffer_free(key_buf); 
2264                         /* returning is bad might screw up
2265                            good keys later in the list
2266                            what to do? */
2267                         return LDNS_STATUS_ERR;
2268                 }
2269
2270                 if (ldns_rr_rdf(key, 2) == NULL) {
2271                         result = LDNS_STATUS_MISSING_RDATA_FIELDS_KEY;
2272                 }
2273                 else if (sig_algo == ldns_rdf2native_int8(
2274                                         ldns_rr_rdf(key, 2))) {
2275                         result = ldns_verify_rrsig_buffers(rawsig_buf, 
2276                                 verify_buf, key_buf, sig_algo);
2277                 } else {
2278                         /* No keys with the corresponding algorithm are found */
2279                         result = LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY;
2280                 }
2281
2282                 ldns_buffer_free(key_buf); 
2283                 return result;
2284         }
2285         else {
2286                 /* No keys with the corresponding keytag are found */
2287                 return LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY;
2288         }
2289 }
2290
2291 /* 
2292  * to verify:
2293  * - create the wire fmt of the b64 key rdata
2294  * - create the wire fmt of the sorted rrset
2295  * - create the wire fmt of the b64 sig rdata
2296  * - create the wire fmt of the sig without the b64 rdata
2297  * - cat the sig data (without b64 rdata) to the rrset
2298  * - verify the rrset+sig, with the b64 data and the b64 key data
2299  */
2300 ldns_status
2301 ldns_verify_rrsig_keylist_time(
2302                 ldns_rr_list *rrset,
2303                 ldns_rr *rrsig,
2304                 const ldns_rr_list *keys, 
2305                 time_t check_time,
2306                 ldns_rr_list *good_keys)
2307 {
2308         ldns_status result;
2309         ldns_rr_list *valid = ldns_rr_list_new();
2310         if (!valid)
2311                 return LDNS_STATUS_MEM_ERR;
2312
2313         result = ldns_verify_rrsig_keylist_notime(rrset, rrsig, keys, valid);
2314         if(result != LDNS_STATUS_OK) {
2315                 ldns_rr_list_free(valid); 
2316                 return result;
2317         }
2318
2319         /* check timestamps last; its OK except time */
2320         result = ldns_rrsig_check_timestamps(rrsig, check_time);
2321         if(result != LDNS_STATUS_OK) {
2322                 ldns_rr_list_free(valid); 
2323                 return result;
2324         }
2325
2326         ldns_rr_list_cat(good_keys, valid);
2327         ldns_rr_list_free(valid);
2328         return LDNS_STATUS_OK;
2329 }
2330
2331 /* 
2332  * to verify:
2333  * - create the wire fmt of the b64 key rdata
2334  * - create the wire fmt of the sorted rrset
2335  * - create the wire fmt of the b64 sig rdata
2336  * - create the wire fmt of the sig without the b64 rdata
2337  * - cat the sig data (without b64 rdata) to the rrset
2338  * - verify the rrset+sig, with the b64 data and the b64 key data
2339  */
2340 ldns_status
2341 ldns_verify_rrsig_keylist(ldns_rr_list *rrset,
2342                                          ldns_rr *rrsig,
2343                                          const ldns_rr_list *keys, 
2344                                          ldns_rr_list *good_keys)
2345 {
2346         return ldns_verify_rrsig_keylist_time(
2347                         rrset, rrsig, keys, ldns_time(NULL), good_keys);
2348 }
2349
2350 ldns_status
2351 ldns_verify_rrsig_keylist_notime(ldns_rr_list *rrset,
2352                                          ldns_rr *rrsig,
2353                                          const ldns_rr_list *keys, 
2354                                          ldns_rr_list *good_keys)
2355 {
2356         ldns_buffer *rawsig_buf;
2357         ldns_buffer *verify_buf;
2358         uint16_t i;
2359         ldns_status result, status;
2360         ldns_rr_list *rrset_clone;
2361         ldns_rr_list *validkeys;
2362
2363         if (!rrset) {
2364                 return LDNS_STATUS_ERR;
2365         }
2366
2367         validkeys = ldns_rr_list_new();
2368         if (!validkeys) {
2369                 return LDNS_STATUS_MEM_ERR;
2370         }
2371         
2372         /* clone the rrset so that we can fiddle with it */
2373         rrset_clone = ldns_rr_list_clone(rrset);
2374
2375         /* create the buffers which will certainly hold the raw data */
2376         rawsig_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN);
2377         verify_buf  = ldns_buffer_new(LDNS_MAX_PACKETLEN);
2378
2379         result = ldns_prepare_for_verify(rawsig_buf, verify_buf, 
2380                 rrset_clone, rrsig);
2381         if(result != LDNS_STATUS_OK) {
2382                 ldns_buffer_free(verify_buf);
2383                 ldns_buffer_free(rawsig_buf);
2384                 ldns_rr_list_deep_free(rrset_clone);
2385                 ldns_rr_list_free(validkeys);
2386                 return result;
2387         }
2388
2389         result = LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY;
2390         for(i = 0; i < ldns_rr_list_rr_count(keys); i++) {
2391                 status = ldns_verify_test_sig_key(rawsig_buf, verify_buf, 
2392                         rrsig, ldns_rr_list_rr(keys, i));
2393                 if (status == LDNS_STATUS_OK) {
2394                         /* one of the keys has matched, don't break
2395                          * here, instead put the 'winning' key in
2396                          * the validkey list and return the list 
2397                          * later */
2398                         if (!ldns_rr_list_push_rr(validkeys, 
2399                                 ldns_rr_list_rr(keys,i))) {
2400                                 /* couldn't push the key?? */
2401                                 ldns_buffer_free(rawsig_buf);
2402                                 ldns_buffer_free(verify_buf);
2403                                 ldns_rr_list_deep_free(rrset_clone);
2404                                 ldns_rr_list_free(validkeys);
2405                                 return LDNS_STATUS_MEM_ERR;
2406                         }
2407
2408                         result = status;
2409                 }
2410
2411                 if (result == LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY) {
2412                         result = status;
2413                 }
2414         }
2415
2416         /* no longer needed */
2417         ldns_rr_list_deep_free(rrset_clone);
2418         ldns_buffer_free(rawsig_buf);
2419         ldns_buffer_free(verify_buf);
2420
2421         if (ldns_rr_list_rr_count(validkeys) == 0) {
2422                 /* no keys were added, return last error */
2423                 ldns_rr_list_free(validkeys); 
2424                 return result;
2425         }
2426
2427         /* do not check timestamps */
2428
2429         ldns_rr_list_cat(good_keys, validkeys);
2430         ldns_rr_list_free(validkeys);
2431         return LDNS_STATUS_OK;
2432 }
2433
2434 ldns_status
2435 ldns_verify_rrsig_time(
2436                 ldns_rr_list *rrset, 
2437                 ldns_rr *rrsig, 
2438                 ldns_rr *key, 
2439                 time_t check_time)
2440 {
2441         ldns_buffer *rawsig_buf;
2442         ldns_buffer *verify_buf;
2443         ldns_status result;
2444         ldns_rr_list *rrset_clone;
2445
2446         if (!rrset) {
2447                 return LDNS_STATUS_NO_DATA;
2448         }
2449         /* clone the rrset so that we can fiddle with it */
2450         rrset_clone = ldns_rr_list_clone(rrset);
2451         /* create the buffers which will certainly hold the raw data */
2452         rawsig_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN);
2453         verify_buf  = ldns_buffer_new(LDNS_MAX_PACKETLEN);
2454
2455         result = ldns_prepare_for_verify(rawsig_buf, verify_buf, 
2456                 rrset_clone, rrsig);
2457         if(result != LDNS_STATUS_OK) {
2458                 ldns_rr_list_deep_free(rrset_clone);
2459                 ldns_buffer_free(rawsig_buf);
2460                 ldns_buffer_free(verify_buf);
2461                 return result;
2462         }
2463         result = ldns_verify_test_sig_key(rawsig_buf, verify_buf, 
2464                 rrsig, key);
2465         /* no longer needed */
2466         ldns_rr_list_deep_free(rrset_clone);
2467         ldns_buffer_free(rawsig_buf);
2468         ldns_buffer_free(verify_buf);
2469
2470         /* check timestamp last, apart from time its OK */
2471         if(result == LDNS_STATUS_OK)
2472                 result = ldns_rrsig_check_timestamps(rrsig, check_time);
2473
2474         return result;
2475 }
2476
2477 ldns_status
2478 ldns_verify_rrsig(ldns_rr_list *rrset, ldns_rr *rrsig, ldns_rr *key)
2479 {
2480         return ldns_verify_rrsig_time(rrset, rrsig, key, ldns_time(NULL));
2481 }
2482
2483
2484 ldns_status
2485 ldns_verify_rrsig_evp(ldns_buffer *sig,
2486                                   ldns_buffer *rrset,
2487                                   EVP_PKEY *key,
2488                                   const EVP_MD *digest_type)
2489 {
2490         return ldns_verify_rrsig_evp_raw(
2491                          (unsigned char*)ldns_buffer_begin(sig),
2492                          ldns_buffer_position(sig),
2493                          rrset,
2494                          key,
2495                          digest_type);
2496 }
2497
2498 ldns_status
2499 ldns_verify_rrsig_evp_raw(unsigned char *sig, size_t siglen, 
2500                                          ldns_buffer *rrset, EVP_PKEY *key, const EVP_MD *digest_type)
2501 {
2502         EVP_MD_CTX ctx;
2503         int res;
2504
2505         EVP_MD_CTX_init(&ctx);
2506         
2507         EVP_VerifyInit(&ctx, digest_type);
2508         EVP_VerifyUpdate(&ctx,
2509                                   ldns_buffer_begin(rrset),
2510                                   ldns_buffer_position(rrset));
2511         res = EVP_VerifyFinal(&ctx, sig, (unsigned int) siglen, key);
2512         
2513         EVP_MD_CTX_cleanup(&ctx);
2514         
2515         if (res == 1) {
2516                 return LDNS_STATUS_OK;
2517         } else if (res == 0) {
2518                 return LDNS_STATUS_CRYPTO_BOGUS;
2519         }
2520         /* TODO how to communicate internal SSL error?
2521            let caller use ssl's get_error() */
2522         return LDNS_STATUS_SSL_ERR;
2523 }
2524
2525 ldns_status
2526 ldns_verify_rrsig_dsa(ldns_buffer *sig, ldns_buffer *rrset, ldns_buffer *key)
2527 {
2528         return ldns_verify_rrsig_dsa_raw(
2529                          (unsigned char*) ldns_buffer_begin(sig),
2530                          ldns_buffer_position(sig),
2531                          rrset,
2532                          (unsigned char*) ldns_buffer_begin(key),
2533                          ldns_buffer_position(key));
2534 }
2535
2536 ldns_status
2537 ldns_verify_rrsig_rsasha1(ldns_buffer *sig, ldns_buffer *rrset, ldns_buffer *key)
2538 {
2539         return ldns_verify_rrsig_rsasha1_raw(
2540                          (unsigned char*)ldns_buffer_begin(sig),
2541                          ldns_buffer_position(sig),
2542                          rrset,
2543                          (unsigned char*) ldns_buffer_begin(key),
2544                          ldns_buffer_position(key));
2545 }
2546
2547 ldns_status
2548 ldns_verify_rrsig_rsamd5(ldns_buffer *sig, ldns_buffer *rrset, ldns_buffer *key)
2549 {
2550         return ldns_verify_rrsig_rsamd5_raw(
2551                          (unsigned char*)ldns_buffer_begin(sig),
2552                          ldns_buffer_position(sig),
2553                          rrset,
2554                          (unsigned char*) ldns_buffer_begin(key),
2555                          ldns_buffer_position(key));
2556 }
2557
2558 ldns_status
2559 ldns_verify_rrsig_dsa_raw(unsigned char* sig, size_t siglen,
2560                                          ldns_buffer* rrset, unsigned char* key, size_t keylen)
2561 {
2562         EVP_PKEY *evp_key;
2563         ldns_status result;
2564
2565         evp_key = EVP_PKEY_new();
2566         if (EVP_PKEY_assign_DSA(evp_key, ldns_key_buf2dsa_raw(key, keylen))) {
2567                 result = ldns_verify_rrsig_evp_raw(sig,
2568                                                                 siglen,
2569                                                                 rrset,
2570                                                                 evp_key,
2571                                                                 EVP_dss1());
2572         } else {
2573                 result = LDNS_STATUS_SSL_ERR;
2574         }
2575         EVP_PKEY_free(evp_key);
2576         return result;
2577
2578 }
2579
2580 ldns_status
2581 ldns_verify_rrsig_rsasha1_raw(unsigned char* sig, size_t siglen,
2582                                                 ldns_buffer* rrset, unsigned char* key, size_t keylen)
2583 {
2584         EVP_PKEY *evp_key;
2585         ldns_status result;
2586
2587         evp_key = EVP_PKEY_new();
2588         if (EVP_PKEY_assign_RSA(evp_key, ldns_key_buf2rsa_raw(key, keylen))) {
2589                 result = ldns_verify_rrsig_evp_raw(sig,
2590                                                                 siglen,
2591                                                                 rrset,
2592                                                                 evp_key,
2593                                                                 EVP_sha1());
2594         } else {
2595                 result = LDNS_STATUS_SSL_ERR;
2596         }
2597         EVP_PKEY_free(evp_key);
2598
2599         return result;
2600 }
2601
2602 ldns_status
2603 ldns_verify_rrsig_rsasha256_raw(unsigned char* sig,
2604                                                   size_t siglen,
2605                                                   ldns_buffer* rrset,
2606                                                   unsigned char* key,
2607                                                   size_t keylen)
2608 {
2609 #ifdef USE_SHA2
2610         EVP_PKEY *evp_key;
2611         ldns_status result;
2612
2613         evp_key = EVP_PKEY_new();
2614         if (EVP_PKEY_assign_RSA(evp_key, ldns_key_buf2rsa_raw(key, keylen))) {
2615                 result = ldns_verify_rrsig_evp_raw(sig,
2616                                                                 siglen,
2617                                                                 rrset,
2618                                                                 evp_key,
2619                                                                 EVP_sha256());
2620         } else {
2621                 result = LDNS_STATUS_SSL_ERR;
2622         }
2623         EVP_PKEY_free(evp_key);
2624
2625         return result;
2626 #else
2627         /* touch these to prevent compiler warnings */
2628         (void) sig;
2629         (void) siglen;
2630         (void) rrset;
2631         (void) key;
2632         (void) keylen;
2633         return LDNS_STATUS_CRYPTO_UNKNOWN_ALGO;
2634 #endif
2635 }
2636
2637 ldns_status
2638 ldns_verify_rrsig_rsasha512_raw(unsigned char* sig,
2639                                                   size_t siglen,
2640                                                   ldns_buffer* rrset,
2641                                                   unsigned char* key,
2642                                                   size_t keylen)
2643 {
2644 #ifdef USE_SHA2
2645         EVP_PKEY *evp_key;
2646         ldns_status result;
2647
2648         evp_key = EVP_PKEY_new();
2649         if (EVP_PKEY_assign_RSA(evp_key, ldns_key_buf2rsa_raw(key, keylen))) {
2650                 result = ldns_verify_rrsig_evp_raw(sig,
2651                                                                 siglen,
2652                                                                 rrset,
2653                                                                 evp_key,
2654                                                                 EVP_sha512());
2655         } else {
2656                 result = LDNS_STATUS_SSL_ERR;
2657         }
2658         EVP_PKEY_free(evp_key);
2659
2660         return result;
2661 #else
2662         /* touch these to prevent compiler warnings */
2663         (void) sig;
2664         (void) siglen;
2665         (void) rrset;
2666         (void) key;
2667         (void) keylen;
2668         return LDNS_STATUS_CRYPTO_UNKNOWN_ALGO;
2669 #endif
2670 }
2671
2672
2673 ldns_status
2674 ldns_verify_rrsig_rsamd5_raw(unsigned char* sig,
2675                                             size_t siglen,
2676                                             ldns_buffer* rrset,
2677                                             unsigned char* key,
2678                                             size_t keylen)
2679 {
2680         EVP_PKEY *evp_key;
2681         ldns_status result;
2682
2683         evp_key = EVP_PKEY_new();
2684         if (EVP_PKEY_assign_RSA(evp_key, ldns_key_buf2rsa_raw(key, keylen))) {
2685                 result = ldns_verify_rrsig_evp_raw(sig,
2686                                                                 siglen,
2687                                                                 rrset,
2688                                                                 evp_key,
2689                                                                 EVP_md5());
2690         } else {
2691                 result = LDNS_STATUS_SSL_ERR;
2692         }
2693         EVP_PKEY_free(evp_key);
2694
2695         return result;
2696 }
2697
2698 #endif