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