17b5038d7SDag-Erling Smørgrav #include <ldns/config.h> 27b5038d7SDag-Erling Smørgrav 37b5038d7SDag-Erling Smørgrav #include <ldns/ldns.h> 47b5038d7SDag-Erling Smørgrav 57b5038d7SDag-Erling Smørgrav #include <strings.h> 67b5038d7SDag-Erling Smørgrav #include <time.h> 77b5038d7SDag-Erling Smørgrav 87b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL 97b5038d7SDag-Erling Smørgrav /* this entire file is rather useless when you don't have 107b5038d7SDag-Erling Smørgrav * crypto... 117b5038d7SDag-Erling Smørgrav */ 127b5038d7SDag-Erling Smørgrav #include <openssl/ssl.h> 137b5038d7SDag-Erling Smørgrav #include <openssl/evp.h> 147b5038d7SDag-Erling Smørgrav #include <openssl/rand.h> 157b5038d7SDag-Erling Smørgrav #include <openssl/err.h> 167b5038d7SDag-Erling Smørgrav #include <openssl/md5.h> 177b5038d7SDag-Erling Smørgrav 187b5038d7SDag-Erling Smørgrav ldns_dnssec_data_chain * 197b5038d7SDag-Erling Smørgrav ldns_dnssec_data_chain_new(void) 207b5038d7SDag-Erling Smørgrav { 217b5038d7SDag-Erling Smørgrav ldns_dnssec_data_chain *nc = LDNS_CALLOC(ldns_dnssec_data_chain, 1); 227b5038d7SDag-Erling Smørgrav if(!nc) return NULL; 237b5038d7SDag-Erling Smørgrav /* 247b5038d7SDag-Erling Smørgrav * not needed anymore because CALLOC initalizes everything to zero. 257b5038d7SDag-Erling Smørgrav 267b5038d7SDag-Erling Smørgrav nc->rrset = NULL; 277b5038d7SDag-Erling Smørgrav nc->parent_type = 0; 287b5038d7SDag-Erling Smørgrav nc->parent = NULL; 297b5038d7SDag-Erling Smørgrav nc->signatures = NULL; 307b5038d7SDag-Erling Smørgrav nc->packet_rcode = 0; 317b5038d7SDag-Erling Smørgrav nc->packet_qtype = 0; 327b5038d7SDag-Erling Smørgrav nc->packet_nodata = false; 337b5038d7SDag-Erling Smørgrav 347b5038d7SDag-Erling Smørgrav */ 357b5038d7SDag-Erling Smørgrav return nc; 367b5038d7SDag-Erling Smørgrav } 377b5038d7SDag-Erling Smørgrav 387b5038d7SDag-Erling Smørgrav void 397b5038d7SDag-Erling Smørgrav ldns_dnssec_data_chain_free(ldns_dnssec_data_chain *chain) 407b5038d7SDag-Erling Smørgrav { 417b5038d7SDag-Erling Smørgrav LDNS_FREE(chain); 427b5038d7SDag-Erling Smørgrav } 437b5038d7SDag-Erling Smørgrav 447b5038d7SDag-Erling Smørgrav void 457b5038d7SDag-Erling Smørgrav ldns_dnssec_data_chain_deep_free(ldns_dnssec_data_chain *chain) 467b5038d7SDag-Erling Smørgrav { 477b5038d7SDag-Erling Smørgrav ldns_rr_list_deep_free(chain->rrset); 487b5038d7SDag-Erling Smørgrav ldns_rr_list_deep_free(chain->signatures); 497b5038d7SDag-Erling Smørgrav if (chain->parent) { 507b5038d7SDag-Erling Smørgrav ldns_dnssec_data_chain_deep_free(chain->parent); 517b5038d7SDag-Erling Smørgrav } 527b5038d7SDag-Erling Smørgrav LDNS_FREE(chain); 537b5038d7SDag-Erling Smørgrav } 547b5038d7SDag-Erling Smørgrav 557b5038d7SDag-Erling Smørgrav void 567b5038d7SDag-Erling Smørgrav ldns_dnssec_data_chain_print_fmt(FILE *out, const ldns_output_format *fmt, 577b5038d7SDag-Erling Smørgrav const ldns_dnssec_data_chain *chain) 587b5038d7SDag-Erling Smørgrav { 597b5038d7SDag-Erling Smørgrav ldns_lookup_table *rcode; 607b5038d7SDag-Erling Smørgrav const ldns_rr_descriptor *rr_descriptor; 617b5038d7SDag-Erling Smørgrav if (chain) { 627b5038d7SDag-Erling Smørgrav ldns_dnssec_data_chain_print_fmt(out, fmt, chain->parent); 637b5038d7SDag-Erling Smørgrav if (ldns_rr_list_rr_count(chain->rrset) > 0) { 647b5038d7SDag-Erling Smørgrav rcode = ldns_lookup_by_id(ldns_rcodes, 657b5038d7SDag-Erling Smørgrav (int) chain->packet_rcode); 667b5038d7SDag-Erling Smørgrav if (rcode) { 677b5038d7SDag-Erling Smørgrav fprintf(out, ";; rcode: %s\n", rcode->name); 687b5038d7SDag-Erling Smørgrav } 697b5038d7SDag-Erling Smørgrav 707b5038d7SDag-Erling Smørgrav rr_descriptor = ldns_rr_descript(chain->packet_qtype); 717b5038d7SDag-Erling Smørgrav if (rr_descriptor && rr_descriptor->_name) { 727b5038d7SDag-Erling Smørgrav fprintf(out, ";; qtype: %s\n", rr_descriptor->_name); 737b5038d7SDag-Erling Smørgrav } else if (chain->packet_qtype != 0) { 747b5038d7SDag-Erling Smørgrav fprintf(out, "TYPE%u", 757b5038d7SDag-Erling Smørgrav chain->packet_qtype); 767b5038d7SDag-Erling Smørgrav } 777b5038d7SDag-Erling Smørgrav if (chain->packet_nodata) { 787b5038d7SDag-Erling Smørgrav fprintf(out, ";; NODATA response\n"); 797b5038d7SDag-Erling Smørgrav } 807b5038d7SDag-Erling Smørgrav fprintf(out, "rrset:\n"); 817b5038d7SDag-Erling Smørgrav ldns_rr_list_print_fmt(out, fmt, chain->rrset); 827b5038d7SDag-Erling Smørgrav fprintf(out, "sigs:\n"); 837b5038d7SDag-Erling Smørgrav ldns_rr_list_print_fmt(out, fmt, chain->signatures); 847b5038d7SDag-Erling Smørgrav fprintf(out, "---\n"); 857b5038d7SDag-Erling Smørgrav } else { 867b5038d7SDag-Erling Smørgrav fprintf(out, "<no data>\n"); 877b5038d7SDag-Erling Smørgrav } 887b5038d7SDag-Erling Smørgrav } 897b5038d7SDag-Erling Smørgrav } 907b5038d7SDag-Erling Smørgrav void 917b5038d7SDag-Erling Smørgrav ldns_dnssec_data_chain_print(FILE *out, const ldns_dnssec_data_chain *chain) 927b5038d7SDag-Erling Smørgrav { 937b5038d7SDag-Erling Smørgrav ldns_dnssec_data_chain_print_fmt( 947b5038d7SDag-Erling Smørgrav out, ldns_output_format_default, chain); 957b5038d7SDag-Erling Smørgrav } 967b5038d7SDag-Erling Smørgrav 977b5038d7SDag-Erling Smørgrav 987b5038d7SDag-Erling Smørgrav static void 997b5038d7SDag-Erling Smørgrav ldns_dnssec_build_data_chain_dnskey(ldns_resolver *res, 1007b5038d7SDag-Erling Smørgrav uint16_t qflags, 1017b5038d7SDag-Erling Smørgrav const ldns_pkt *pkt, 1027b5038d7SDag-Erling Smørgrav ldns_rr_list *signatures, 1037b5038d7SDag-Erling Smørgrav ldns_dnssec_data_chain *new_chain, 1047b5038d7SDag-Erling Smørgrav ldns_rdf *key_name, 1057b5038d7SDag-Erling Smørgrav ldns_rr_class c) { 1067b5038d7SDag-Erling Smørgrav ldns_rr_list *keys; 1077b5038d7SDag-Erling Smørgrav ldns_pkt *my_pkt; 1087b5038d7SDag-Erling Smørgrav if (signatures && ldns_rr_list_rr_count(signatures) > 0) { 1097b5038d7SDag-Erling Smørgrav new_chain->signatures = ldns_rr_list_clone(signatures); 1107b5038d7SDag-Erling Smørgrav new_chain->parent_type = 0; 1117b5038d7SDag-Erling Smørgrav 1127b5038d7SDag-Erling Smørgrav keys = ldns_pkt_rr_list_by_name_and_type( 1137b5038d7SDag-Erling Smørgrav pkt, 1147b5038d7SDag-Erling Smørgrav key_name, 1157b5038d7SDag-Erling Smørgrav LDNS_RR_TYPE_DNSKEY, 1167b5038d7SDag-Erling Smørgrav LDNS_SECTION_ANY_NOQUESTION 1177b5038d7SDag-Erling Smørgrav ); 1187b5038d7SDag-Erling Smørgrav if (!keys) { 1197b5038d7SDag-Erling Smørgrav my_pkt = ldns_resolver_query(res, 1207b5038d7SDag-Erling Smørgrav key_name, 1217b5038d7SDag-Erling Smørgrav LDNS_RR_TYPE_DNSKEY, 1227b5038d7SDag-Erling Smørgrav c, 1237b5038d7SDag-Erling Smørgrav qflags); 1247b5038d7SDag-Erling Smørgrav if (my_pkt) { 1257b5038d7SDag-Erling Smørgrav keys = ldns_pkt_rr_list_by_name_and_type( 1267b5038d7SDag-Erling Smørgrav my_pkt, 1277b5038d7SDag-Erling Smørgrav key_name, 1287b5038d7SDag-Erling Smørgrav LDNS_RR_TYPE_DNSKEY, 1297b5038d7SDag-Erling Smørgrav LDNS_SECTION_ANY_NOQUESTION 1307b5038d7SDag-Erling Smørgrav ); 1317b5038d7SDag-Erling Smørgrav new_chain->parent = ldns_dnssec_build_data_chain(res, 1327b5038d7SDag-Erling Smørgrav qflags, 1337b5038d7SDag-Erling Smørgrav keys, 1347b5038d7SDag-Erling Smørgrav my_pkt, 1357b5038d7SDag-Erling Smørgrav NULL); 1367b5038d7SDag-Erling Smørgrav new_chain->parent->packet_qtype = LDNS_RR_TYPE_DNSKEY; 1377b5038d7SDag-Erling Smørgrav ldns_pkt_free(my_pkt); 1387b5038d7SDag-Erling Smørgrav } 1397b5038d7SDag-Erling Smørgrav } else { 1407b5038d7SDag-Erling Smørgrav new_chain->parent = ldns_dnssec_build_data_chain(res, 1417b5038d7SDag-Erling Smørgrav qflags, 1427b5038d7SDag-Erling Smørgrav keys, 1437b5038d7SDag-Erling Smørgrav pkt, 1447b5038d7SDag-Erling Smørgrav NULL); 1457b5038d7SDag-Erling Smørgrav new_chain->parent->packet_qtype = LDNS_RR_TYPE_DNSKEY; 1467b5038d7SDag-Erling Smørgrav } 1477b5038d7SDag-Erling Smørgrav ldns_rr_list_deep_free(keys); 1487b5038d7SDag-Erling Smørgrav } 1497b5038d7SDag-Erling Smørgrav } 1507b5038d7SDag-Erling Smørgrav 1517b5038d7SDag-Erling Smørgrav static void 1527b5038d7SDag-Erling Smørgrav ldns_dnssec_build_data_chain_other(ldns_resolver *res, 1537b5038d7SDag-Erling Smørgrav uint16_t qflags, 1547b5038d7SDag-Erling Smørgrav ldns_dnssec_data_chain *new_chain, 1557b5038d7SDag-Erling Smørgrav ldns_rdf *key_name, 1567b5038d7SDag-Erling Smørgrav ldns_rr_class c, 1577b5038d7SDag-Erling Smørgrav ldns_rr_list *dss) 1587b5038d7SDag-Erling Smørgrav { 1597b5038d7SDag-Erling Smørgrav /* 'self-signed', parent is a DS */ 1607b5038d7SDag-Erling Smørgrav 1617b5038d7SDag-Erling Smørgrav /* okay, either we have other keys signing the current one, 1627b5038d7SDag-Erling Smørgrav * or the current 1637b5038d7SDag-Erling Smørgrav * one should have a DS record in the parent zone. 1647b5038d7SDag-Erling Smørgrav * How do we find this out? Try both? 1657b5038d7SDag-Erling Smørgrav * 1667b5038d7SDag-Erling Smørgrav * request DNSKEYS for current zone, 1677b5038d7SDag-Erling Smørgrav * add all signatures to current level 1687b5038d7SDag-Erling Smørgrav */ 1697b5038d7SDag-Erling Smørgrav ldns_pkt *my_pkt; 1707b5038d7SDag-Erling Smørgrav ldns_rr_list *signatures2; 1717b5038d7SDag-Erling Smørgrav 1727b5038d7SDag-Erling Smørgrav new_chain->parent_type = 1; 1737b5038d7SDag-Erling Smørgrav 1747b5038d7SDag-Erling Smørgrav my_pkt = ldns_resolver_query(res, 1757b5038d7SDag-Erling Smørgrav key_name, 1767b5038d7SDag-Erling Smørgrav LDNS_RR_TYPE_DS, 1777b5038d7SDag-Erling Smørgrav c, 1787b5038d7SDag-Erling Smørgrav qflags); 1797b5038d7SDag-Erling Smørgrav if (my_pkt) { 1807b5038d7SDag-Erling Smørgrav dss = ldns_pkt_rr_list_by_name_and_type(my_pkt, 1817b5038d7SDag-Erling Smørgrav key_name, 1827b5038d7SDag-Erling Smørgrav LDNS_RR_TYPE_DS, 1837b5038d7SDag-Erling Smørgrav LDNS_SECTION_ANY_NOQUESTION 1847b5038d7SDag-Erling Smørgrav ); 1857b5038d7SDag-Erling Smørgrav if (dss) { 1867b5038d7SDag-Erling Smørgrav new_chain->parent = ldns_dnssec_build_data_chain(res, 1877b5038d7SDag-Erling Smørgrav qflags, 1887b5038d7SDag-Erling Smørgrav dss, 1897b5038d7SDag-Erling Smørgrav my_pkt, 1907b5038d7SDag-Erling Smørgrav NULL); 1917b5038d7SDag-Erling Smørgrav new_chain->parent->packet_qtype = LDNS_RR_TYPE_DS; 1927b5038d7SDag-Erling Smørgrav ldns_rr_list_deep_free(dss); 1937b5038d7SDag-Erling Smørgrav } 1947b5038d7SDag-Erling Smørgrav ldns_pkt_free(my_pkt); 1957b5038d7SDag-Erling Smørgrav } 1967b5038d7SDag-Erling Smørgrav 1977b5038d7SDag-Erling Smørgrav my_pkt = ldns_resolver_query(res, 1987b5038d7SDag-Erling Smørgrav key_name, 1997b5038d7SDag-Erling Smørgrav LDNS_RR_TYPE_DNSKEY, 2007b5038d7SDag-Erling Smørgrav c, 2017b5038d7SDag-Erling Smørgrav qflags); 2027b5038d7SDag-Erling Smørgrav if (my_pkt) { 2037b5038d7SDag-Erling Smørgrav signatures2 = ldns_pkt_rr_list_by_name_and_type(my_pkt, 2047b5038d7SDag-Erling Smørgrav key_name, 2057b5038d7SDag-Erling Smørgrav LDNS_RR_TYPE_RRSIG, 2067b5038d7SDag-Erling Smørgrav LDNS_SECTION_ANSWER); 2077b5038d7SDag-Erling Smørgrav if (signatures2) { 2087b5038d7SDag-Erling Smørgrav if (new_chain->signatures) { 2097b5038d7SDag-Erling Smørgrav printf("There were already sigs!\n"); 2107b5038d7SDag-Erling Smørgrav ldns_rr_list_deep_free(new_chain->signatures); 2117b5038d7SDag-Erling Smørgrav printf("replacing the old sigs\n"); 2127b5038d7SDag-Erling Smørgrav } 2137b5038d7SDag-Erling Smørgrav new_chain->signatures = signatures2; 2147b5038d7SDag-Erling Smørgrav } 2157b5038d7SDag-Erling Smørgrav ldns_pkt_free(my_pkt); 2167b5038d7SDag-Erling Smørgrav } 2177b5038d7SDag-Erling Smørgrav } 2187b5038d7SDag-Erling Smørgrav 2197b5038d7SDag-Erling Smørgrav static ldns_dnssec_data_chain * 2207b5038d7SDag-Erling Smørgrav ldns_dnssec_build_data_chain_nokeyname(ldns_resolver *res, 2217b5038d7SDag-Erling Smørgrav uint16_t qflags, 2227b5038d7SDag-Erling Smørgrav ldns_rr *orig_rr, 2237b5038d7SDag-Erling Smørgrav const ldns_rr_list *rrset, 2247b5038d7SDag-Erling Smørgrav ldns_dnssec_data_chain *new_chain) 2257b5038d7SDag-Erling Smørgrav { 2267b5038d7SDag-Erling Smørgrav ldns_rdf *possible_parent_name; 2277b5038d7SDag-Erling Smørgrav ldns_pkt *my_pkt; 2287b5038d7SDag-Erling Smørgrav /* apparently we were not able to find a signing key, so 2297b5038d7SDag-Erling Smørgrav we assume the chain ends here 2307b5038d7SDag-Erling Smørgrav */ 2317b5038d7SDag-Erling Smørgrav /* try parents for auth denial of DS */ 2327b5038d7SDag-Erling Smørgrav if (orig_rr) { 2337b5038d7SDag-Erling Smørgrav possible_parent_name = ldns_rr_owner(orig_rr); 2347b5038d7SDag-Erling Smørgrav } else if (rrset && ldns_rr_list_rr_count(rrset) > 0) { 2357b5038d7SDag-Erling Smørgrav possible_parent_name = ldns_rr_owner(ldns_rr_list_rr(rrset, 0)); 2367b5038d7SDag-Erling Smørgrav } else { 2377b5038d7SDag-Erling Smørgrav /* no information to go on, give up */ 2387b5038d7SDag-Erling Smørgrav return new_chain; 2397b5038d7SDag-Erling Smørgrav } 2407b5038d7SDag-Erling Smørgrav 2417b5038d7SDag-Erling Smørgrav my_pkt = ldns_resolver_query(res, 2427b5038d7SDag-Erling Smørgrav possible_parent_name, 2437b5038d7SDag-Erling Smørgrav LDNS_RR_TYPE_DS, 2447b5038d7SDag-Erling Smørgrav LDNS_RR_CLASS_IN, 2457b5038d7SDag-Erling Smørgrav qflags); 2467b5038d7SDag-Erling Smørgrav if (!my_pkt) { 2477b5038d7SDag-Erling Smørgrav return new_chain; 2487b5038d7SDag-Erling Smørgrav } 2497b5038d7SDag-Erling Smørgrav 2507b5038d7SDag-Erling Smørgrav if (ldns_pkt_ancount(my_pkt) > 0) { 2517b5038d7SDag-Erling Smørgrav /* add error, no sigs but DS in parent */ 2527b5038d7SDag-Erling Smørgrav /*ldns_pkt_print(stdout, my_pkt);*/ 2537b5038d7SDag-Erling Smørgrav ldns_pkt_free(my_pkt); 2547b5038d7SDag-Erling Smørgrav } else { 2557b5038d7SDag-Erling Smørgrav /* are there signatures? */ 2567b5038d7SDag-Erling Smørgrav new_chain->parent = ldns_dnssec_build_data_chain(res, 2577b5038d7SDag-Erling Smørgrav qflags, 2587b5038d7SDag-Erling Smørgrav NULL, 2597b5038d7SDag-Erling Smørgrav my_pkt, 2607b5038d7SDag-Erling Smørgrav NULL); 2617b5038d7SDag-Erling Smørgrav 2627b5038d7SDag-Erling Smørgrav new_chain->parent->packet_qtype = LDNS_RR_TYPE_DS; 2637b5038d7SDag-Erling Smørgrav 2647b5038d7SDag-Erling Smørgrav } 2657b5038d7SDag-Erling Smørgrav return new_chain; 2667b5038d7SDag-Erling Smørgrav } 2677b5038d7SDag-Erling Smørgrav 2687b5038d7SDag-Erling Smørgrav 2697b5038d7SDag-Erling Smørgrav ldns_dnssec_data_chain * 2707b5038d7SDag-Erling Smørgrav ldns_dnssec_build_data_chain(ldns_resolver *res, 2717b5038d7SDag-Erling Smørgrav uint16_t qflags, 2727b5038d7SDag-Erling Smørgrav const ldns_rr_list *rrset, 2737b5038d7SDag-Erling Smørgrav const ldns_pkt *pkt, 2747b5038d7SDag-Erling Smørgrav ldns_rr *orig_rr) 2757b5038d7SDag-Erling Smørgrav { 2767b5038d7SDag-Erling Smørgrav ldns_rr_list *signatures = NULL; 2777b5038d7SDag-Erling Smørgrav ldns_rr_list *dss = NULL; 2787b5038d7SDag-Erling Smørgrav 2797b5038d7SDag-Erling Smørgrav ldns_rr_list *my_rrset; 2807b5038d7SDag-Erling Smørgrav 2817b5038d7SDag-Erling Smørgrav ldns_pkt *my_pkt; 2827b5038d7SDag-Erling Smørgrav 2837b5038d7SDag-Erling Smørgrav ldns_rdf *name = NULL, *key_name = NULL; 2847b5038d7SDag-Erling Smørgrav ldns_rr_type type = 0; 2857b5038d7SDag-Erling Smørgrav ldns_rr_class c = 0; 2867b5038d7SDag-Erling Smørgrav 2877b5038d7SDag-Erling Smørgrav bool other_rrset = false; 2887b5038d7SDag-Erling Smørgrav 2897b5038d7SDag-Erling Smørgrav ldns_dnssec_data_chain *new_chain = ldns_dnssec_data_chain_new(); 2907b5038d7SDag-Erling Smørgrav 291*2787e39aSDag-Erling Smørgrav assert(pkt != NULL); 292*2787e39aSDag-Erling Smørgrav 2937b5038d7SDag-Erling Smørgrav if (!ldns_dnssec_pkt_has_rrsigs(pkt)) { 2947b5038d7SDag-Erling Smørgrav /* hmm. no dnssec data in the packet. go up to try and deny 2957b5038d7SDag-Erling Smørgrav * DS? */ 2967b5038d7SDag-Erling Smørgrav return new_chain; 2977b5038d7SDag-Erling Smørgrav } 2987b5038d7SDag-Erling Smørgrav 2997b5038d7SDag-Erling Smørgrav if (orig_rr) { 3007b5038d7SDag-Erling Smørgrav new_chain->rrset = ldns_rr_list_new(); 3017b5038d7SDag-Erling Smørgrav ldns_rr_list_push_rr(new_chain->rrset, orig_rr); 3027b5038d7SDag-Erling Smørgrav new_chain->parent = ldns_dnssec_build_data_chain(res, 3037b5038d7SDag-Erling Smørgrav qflags, 3047b5038d7SDag-Erling Smørgrav rrset, 3057b5038d7SDag-Erling Smørgrav pkt, 3067b5038d7SDag-Erling Smørgrav NULL); 3077b5038d7SDag-Erling Smørgrav new_chain->packet_rcode = ldns_pkt_get_rcode(pkt); 3087b5038d7SDag-Erling Smørgrav new_chain->packet_qtype = ldns_rr_get_type(orig_rr); 3097b5038d7SDag-Erling Smørgrav if (ldns_pkt_ancount(pkt) == 0) { 3107b5038d7SDag-Erling Smørgrav new_chain->packet_nodata = true; 3117b5038d7SDag-Erling Smørgrav } 3127b5038d7SDag-Erling Smørgrav return new_chain; 3137b5038d7SDag-Erling Smørgrav } 3147b5038d7SDag-Erling Smørgrav 3157b5038d7SDag-Erling Smørgrav if (!rrset || ldns_rr_list_rr_count(rrset) < 1) { 3167b5038d7SDag-Erling Smørgrav /* hmm, no data, do we have denial? only works if pkt was given, 3177b5038d7SDag-Erling Smørgrav otherwise caller has to do the check himself */ 3187b5038d7SDag-Erling Smørgrav new_chain->packet_nodata = true; 3197b5038d7SDag-Erling Smørgrav if (pkt) { 3207b5038d7SDag-Erling Smørgrav my_rrset = ldns_pkt_rr_list_by_type(pkt, 3217b5038d7SDag-Erling Smørgrav LDNS_RR_TYPE_NSEC, 3227b5038d7SDag-Erling Smørgrav LDNS_SECTION_ANY_NOQUESTION 3237b5038d7SDag-Erling Smørgrav ); 3247b5038d7SDag-Erling Smørgrav if (my_rrset) { 3257b5038d7SDag-Erling Smørgrav if (ldns_rr_list_rr_count(my_rrset) > 0) { 3267b5038d7SDag-Erling Smørgrav type = LDNS_RR_TYPE_NSEC; 3277b5038d7SDag-Erling Smørgrav other_rrset = true; 3287b5038d7SDag-Erling Smørgrav } else { 3297b5038d7SDag-Erling Smørgrav ldns_rr_list_deep_free(my_rrset); 3307b5038d7SDag-Erling Smørgrav my_rrset = NULL; 3317b5038d7SDag-Erling Smørgrav } 3327b5038d7SDag-Erling Smørgrav } else { 3337b5038d7SDag-Erling Smørgrav /* nothing, try nsec3 */ 3347b5038d7SDag-Erling Smørgrav my_rrset = ldns_pkt_rr_list_by_type(pkt, 3357b5038d7SDag-Erling Smørgrav LDNS_RR_TYPE_NSEC3, 3367b5038d7SDag-Erling Smørgrav LDNS_SECTION_ANY_NOQUESTION); 3377b5038d7SDag-Erling Smørgrav if (my_rrset) { 3387b5038d7SDag-Erling Smørgrav if (ldns_rr_list_rr_count(my_rrset) > 0) { 3397b5038d7SDag-Erling Smørgrav type = LDNS_RR_TYPE_NSEC3; 3407b5038d7SDag-Erling Smørgrav other_rrset = true; 3417b5038d7SDag-Erling Smørgrav } else { 3427b5038d7SDag-Erling Smørgrav ldns_rr_list_deep_free(my_rrset); 3437b5038d7SDag-Erling Smørgrav my_rrset = NULL; 3447b5038d7SDag-Erling Smørgrav } 3457b5038d7SDag-Erling Smørgrav } else { 3467b5038d7SDag-Erling Smørgrav /* nothing, stop */ 3477b5038d7SDag-Erling Smørgrav /* try parent zone? for denied insecure? */ 3487b5038d7SDag-Erling Smørgrav return new_chain; 3497b5038d7SDag-Erling Smørgrav } 3507b5038d7SDag-Erling Smørgrav } 3517b5038d7SDag-Erling Smørgrav } else { 3527b5038d7SDag-Erling Smørgrav return new_chain; 3537b5038d7SDag-Erling Smørgrav } 3547b5038d7SDag-Erling Smørgrav } else { 3557b5038d7SDag-Erling Smørgrav my_rrset = (ldns_rr_list *) rrset; 3567b5038d7SDag-Erling Smørgrav } 3577b5038d7SDag-Erling Smørgrav 3587b5038d7SDag-Erling Smørgrav if (my_rrset && ldns_rr_list_rr_count(my_rrset) > 0) { 3597b5038d7SDag-Erling Smørgrav new_chain->rrset = ldns_rr_list_clone(my_rrset); 3607b5038d7SDag-Erling Smørgrav name = ldns_rr_owner(ldns_rr_list_rr(my_rrset, 0)); 3617b5038d7SDag-Erling Smørgrav type = ldns_rr_get_type(ldns_rr_list_rr(my_rrset, 0)); 3627b5038d7SDag-Erling Smørgrav c = ldns_rr_get_class(ldns_rr_list_rr(my_rrset, 0)); 3637b5038d7SDag-Erling Smørgrav } 3647b5038d7SDag-Erling Smørgrav 3657b5038d7SDag-Erling Smørgrav if (other_rrset) { 3667b5038d7SDag-Erling Smørgrav ldns_rr_list_deep_free(my_rrset); 3677b5038d7SDag-Erling Smørgrav } 3687b5038d7SDag-Erling Smørgrav 3697b5038d7SDag-Erling Smørgrav /* normally there will only be 1 signature 'set' 3707b5038d7SDag-Erling Smørgrav but there can be more than 1 denial (wildcards) 3717b5038d7SDag-Erling Smørgrav so check for NSEC 3727b5038d7SDag-Erling Smørgrav */ 3737b5038d7SDag-Erling Smørgrav if (type == LDNS_RR_TYPE_NSEC || type == LDNS_RR_TYPE_NSEC3) { 3747b5038d7SDag-Erling Smørgrav /* just throw in all signatures, the tree builder must sort 3757b5038d7SDag-Erling Smørgrav this out */ 3767b5038d7SDag-Erling Smørgrav if (pkt) { 3777b5038d7SDag-Erling Smørgrav signatures = ldns_dnssec_pkt_get_rrsigs_for_type(pkt, type); 3787b5038d7SDag-Erling Smørgrav } else { 3797b5038d7SDag-Erling Smørgrav my_pkt = ldns_resolver_query(res, name, type, c, qflags); 3807b5038d7SDag-Erling Smørgrav if (my_pkt) { 3817b5038d7SDag-Erling Smørgrav signatures = ldns_dnssec_pkt_get_rrsigs_for_type(pkt, type); 3827b5038d7SDag-Erling Smørgrav ldns_pkt_free(my_pkt); 3837b5038d7SDag-Erling Smørgrav } 3847b5038d7SDag-Erling Smørgrav } 3857b5038d7SDag-Erling Smørgrav } else { 3867b5038d7SDag-Erling Smørgrav if (pkt) { 3877b5038d7SDag-Erling Smørgrav signatures = 3887b5038d7SDag-Erling Smørgrav ldns_dnssec_pkt_get_rrsigs_for_name_and_type(pkt, 3897b5038d7SDag-Erling Smørgrav name, 3907b5038d7SDag-Erling Smørgrav type); 3917b5038d7SDag-Erling Smørgrav } 3927b5038d7SDag-Erling Smørgrav if (!signatures) { 3937b5038d7SDag-Erling Smørgrav my_pkt = ldns_resolver_query(res, name, type, c, qflags); 3947b5038d7SDag-Erling Smørgrav if (my_pkt) { 3957b5038d7SDag-Erling Smørgrav signatures = 3967b5038d7SDag-Erling Smørgrav ldns_dnssec_pkt_get_rrsigs_for_name_and_type(my_pkt, 3977b5038d7SDag-Erling Smørgrav name, 3987b5038d7SDag-Erling Smørgrav type); 3997b5038d7SDag-Erling Smørgrav ldns_pkt_free(my_pkt); 4007b5038d7SDag-Erling Smørgrav } 4017b5038d7SDag-Erling Smørgrav } 4027b5038d7SDag-Erling Smørgrav } 4037b5038d7SDag-Erling Smørgrav 4047b5038d7SDag-Erling Smørgrav if (signatures && ldns_rr_list_rr_count(signatures) > 0) { 4057b5038d7SDag-Erling Smørgrav key_name = ldns_rr_rdf(ldns_rr_list_rr(signatures, 0), 7); 4067b5038d7SDag-Erling Smørgrav } 4077b5038d7SDag-Erling Smørgrav if (!key_name) { 408*2787e39aSDag-Erling Smørgrav if (signatures) { 409*2787e39aSDag-Erling Smørgrav ldns_rr_list_deep_free(signatures); 410*2787e39aSDag-Erling Smørgrav } 4117b5038d7SDag-Erling Smørgrav return ldns_dnssec_build_data_chain_nokeyname(res, 4127b5038d7SDag-Erling Smørgrav qflags, 4137b5038d7SDag-Erling Smørgrav orig_rr, 4147b5038d7SDag-Erling Smørgrav rrset, 4157b5038d7SDag-Erling Smørgrav new_chain); 4167b5038d7SDag-Erling Smørgrav } 4177b5038d7SDag-Erling Smørgrav if (type != LDNS_RR_TYPE_DNSKEY) { 4187b5038d7SDag-Erling Smørgrav ldns_dnssec_build_data_chain_dnskey(res, 4197b5038d7SDag-Erling Smørgrav qflags, 4207b5038d7SDag-Erling Smørgrav pkt, 4217b5038d7SDag-Erling Smørgrav signatures, 4227b5038d7SDag-Erling Smørgrav new_chain, 4237b5038d7SDag-Erling Smørgrav key_name, 4247b5038d7SDag-Erling Smørgrav c 4257b5038d7SDag-Erling Smørgrav ); 4267b5038d7SDag-Erling Smørgrav } else { 4277b5038d7SDag-Erling Smørgrav ldns_dnssec_build_data_chain_other(res, 4287b5038d7SDag-Erling Smørgrav qflags, 4297b5038d7SDag-Erling Smørgrav new_chain, 4307b5038d7SDag-Erling Smørgrav key_name, 4317b5038d7SDag-Erling Smørgrav c, 4327b5038d7SDag-Erling Smørgrav dss 4337b5038d7SDag-Erling Smørgrav ); 4347b5038d7SDag-Erling Smørgrav } 4357b5038d7SDag-Erling Smørgrav if (signatures) { 4367b5038d7SDag-Erling Smørgrav ldns_rr_list_deep_free(signatures); 4377b5038d7SDag-Erling Smørgrav } 4387b5038d7SDag-Erling Smørgrav return new_chain; 4397b5038d7SDag-Erling Smørgrav } 4407b5038d7SDag-Erling Smørgrav 4417b5038d7SDag-Erling Smørgrav ldns_dnssec_trust_tree * 4427b5038d7SDag-Erling Smørgrav ldns_dnssec_trust_tree_new(void) 4437b5038d7SDag-Erling Smørgrav { 4447b5038d7SDag-Erling Smørgrav ldns_dnssec_trust_tree *new_tree = LDNS_XMALLOC(ldns_dnssec_trust_tree, 4457b5038d7SDag-Erling Smørgrav 1); 4467b5038d7SDag-Erling Smørgrav if(!new_tree) return NULL; 4477b5038d7SDag-Erling Smørgrav new_tree->rr = NULL; 4487b5038d7SDag-Erling Smørgrav new_tree->rrset = NULL; 4497b5038d7SDag-Erling Smørgrav new_tree->parent_count = 0; 4507b5038d7SDag-Erling Smørgrav 4517b5038d7SDag-Erling Smørgrav return new_tree; 4527b5038d7SDag-Erling Smørgrav } 4537b5038d7SDag-Erling Smørgrav 4547b5038d7SDag-Erling Smørgrav void 4557b5038d7SDag-Erling Smørgrav ldns_dnssec_trust_tree_free(ldns_dnssec_trust_tree *tree) 4567b5038d7SDag-Erling Smørgrav { 4577b5038d7SDag-Erling Smørgrav size_t i; 4587b5038d7SDag-Erling Smørgrav if (tree) { 4597b5038d7SDag-Erling Smørgrav for (i = 0; i < tree->parent_count; i++) { 4607b5038d7SDag-Erling Smørgrav ldns_dnssec_trust_tree_free(tree->parents[i]); 4617b5038d7SDag-Erling Smørgrav } 4627b5038d7SDag-Erling Smørgrav } 4637b5038d7SDag-Erling Smørgrav LDNS_FREE(tree); 4647b5038d7SDag-Erling Smørgrav } 4657b5038d7SDag-Erling Smørgrav 4667b5038d7SDag-Erling Smørgrav size_t 4677b5038d7SDag-Erling Smørgrav ldns_dnssec_trust_tree_depth(ldns_dnssec_trust_tree *tree) 4687b5038d7SDag-Erling Smørgrav { 4697b5038d7SDag-Erling Smørgrav size_t result = 0; 4707b5038d7SDag-Erling Smørgrav size_t parent = 0; 4717b5038d7SDag-Erling Smørgrav size_t i; 4727b5038d7SDag-Erling Smørgrav 4737b5038d7SDag-Erling Smørgrav for (i = 0; i < tree->parent_count; i++) { 4747b5038d7SDag-Erling Smørgrav parent = ldns_dnssec_trust_tree_depth(tree->parents[i]); 4757b5038d7SDag-Erling Smørgrav if (parent > result) { 4767b5038d7SDag-Erling Smørgrav result = parent; 4777b5038d7SDag-Erling Smørgrav } 4787b5038d7SDag-Erling Smørgrav } 4797b5038d7SDag-Erling Smørgrav return 1 + result; 4807b5038d7SDag-Erling Smørgrav } 4817b5038d7SDag-Erling Smørgrav 4827b5038d7SDag-Erling Smørgrav /* TODO ldns_ */ 4837b5038d7SDag-Erling Smørgrav static void 4847b5038d7SDag-Erling Smørgrav print_tabs(FILE *out, size_t nr, uint8_t *map, size_t treedepth) 4857b5038d7SDag-Erling Smørgrav { 4867b5038d7SDag-Erling Smørgrav size_t i; 4877b5038d7SDag-Erling Smørgrav for (i = 0; i < nr; i++) { 4887b5038d7SDag-Erling Smørgrav if (i == nr - 1) { 4897b5038d7SDag-Erling Smørgrav fprintf(out, "|---"); 4907b5038d7SDag-Erling Smørgrav } else if (map && i < treedepth && map[i] == 1) { 4917b5038d7SDag-Erling Smørgrav fprintf(out, "| "); 4927b5038d7SDag-Erling Smørgrav } else { 4937b5038d7SDag-Erling Smørgrav fprintf(out, " "); 4947b5038d7SDag-Erling Smørgrav } 4957b5038d7SDag-Erling Smørgrav } 4967b5038d7SDag-Erling Smørgrav } 4977b5038d7SDag-Erling Smørgrav 4987b5038d7SDag-Erling Smørgrav static void 4997b5038d7SDag-Erling Smørgrav ldns_dnssec_trust_tree_print_sm_fmt(FILE *out, 5007b5038d7SDag-Erling Smørgrav const ldns_output_format *fmt, 5017b5038d7SDag-Erling Smørgrav ldns_dnssec_trust_tree *tree, 5027b5038d7SDag-Erling Smørgrav size_t tabs, 5037b5038d7SDag-Erling Smørgrav bool extended, 5047b5038d7SDag-Erling Smørgrav uint8_t *sibmap, 5057b5038d7SDag-Erling Smørgrav size_t treedepth) 5067b5038d7SDag-Erling Smørgrav { 5077b5038d7SDag-Erling Smørgrav size_t i; 5087b5038d7SDag-Erling Smørgrav const ldns_rr_descriptor *descriptor; 5097b5038d7SDag-Erling Smørgrav bool mapset = false; 5107b5038d7SDag-Erling Smørgrav 5117b5038d7SDag-Erling Smørgrav if (!sibmap) { 5127b5038d7SDag-Erling Smørgrav treedepth = ldns_dnssec_trust_tree_depth(tree); 5137b5038d7SDag-Erling Smørgrav sibmap = LDNS_XMALLOC(uint8_t, treedepth); 5147b5038d7SDag-Erling Smørgrav if(!sibmap) 5157b5038d7SDag-Erling Smørgrav return; /* mem err */ 5167b5038d7SDag-Erling Smørgrav memset(sibmap, 0, treedepth); 5177b5038d7SDag-Erling Smørgrav mapset = true; 5187b5038d7SDag-Erling Smørgrav } 5197b5038d7SDag-Erling Smørgrav 5207b5038d7SDag-Erling Smørgrav if (tree) { 5217b5038d7SDag-Erling Smørgrav if (tree->rr) { 5227b5038d7SDag-Erling Smørgrav print_tabs(out, tabs, sibmap, treedepth); 5237b5038d7SDag-Erling Smørgrav ldns_rdf_print(out, ldns_rr_owner(tree->rr)); 5247b5038d7SDag-Erling Smørgrav descriptor = ldns_rr_descript(ldns_rr_get_type(tree->rr)); 5257b5038d7SDag-Erling Smørgrav 5267b5038d7SDag-Erling Smørgrav if (descriptor->_name) { 5277b5038d7SDag-Erling Smørgrav fprintf(out, " (%s", descriptor->_name); 5287b5038d7SDag-Erling Smørgrav } else { 5297b5038d7SDag-Erling Smørgrav fprintf(out, " (TYPE%d", 5307b5038d7SDag-Erling Smørgrav ldns_rr_get_type(tree->rr)); 5317b5038d7SDag-Erling Smørgrav } 5327b5038d7SDag-Erling Smørgrav if (tabs > 0) { 5337b5038d7SDag-Erling Smørgrav if (ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_DNSKEY) { 5347b5038d7SDag-Erling Smørgrav fprintf(out, " keytag: %u", 5357b5038d7SDag-Erling Smørgrav (unsigned int) ldns_calc_keytag(tree->rr)); 5367b5038d7SDag-Erling Smørgrav fprintf(out, " alg: "); 5377b5038d7SDag-Erling Smørgrav ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 2)); 5387b5038d7SDag-Erling Smørgrav fprintf(out, " flags: "); 5397b5038d7SDag-Erling Smørgrav ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 0)); 5407b5038d7SDag-Erling Smørgrav } else if (ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_DS) { 5417b5038d7SDag-Erling Smørgrav fprintf(out, " keytag: "); 5427b5038d7SDag-Erling Smørgrav ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 0)); 5437b5038d7SDag-Erling Smørgrav fprintf(out, " digest type: "); 5447b5038d7SDag-Erling Smørgrav ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 2)); 5457b5038d7SDag-Erling Smørgrav } 5467b5038d7SDag-Erling Smørgrav if (ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_NSEC) { 5477b5038d7SDag-Erling Smørgrav fprintf(out, " "); 5487b5038d7SDag-Erling Smørgrav ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 0)); 5497b5038d7SDag-Erling Smørgrav fprintf(out, " "); 5507b5038d7SDag-Erling Smørgrav ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 1)); 5517b5038d7SDag-Erling Smørgrav } 5527b5038d7SDag-Erling Smørgrav } 5537b5038d7SDag-Erling Smørgrav 5547b5038d7SDag-Erling Smørgrav fprintf(out, ")\n"); 5557b5038d7SDag-Erling Smørgrav for (i = 0; i < tree->parent_count; i++) { 5567b5038d7SDag-Erling Smørgrav if (tree->parent_count > 1 && i < tree->parent_count - 1) { 5577b5038d7SDag-Erling Smørgrav sibmap[tabs] = 1; 5587b5038d7SDag-Erling Smørgrav } else { 5597b5038d7SDag-Erling Smørgrav sibmap[tabs] = 0; 5607b5038d7SDag-Erling Smørgrav } 5617b5038d7SDag-Erling Smørgrav /* only print errors */ 5627b5038d7SDag-Erling Smørgrav if (ldns_rr_get_type(tree->parents[i]->rr) == 5637b5038d7SDag-Erling Smørgrav LDNS_RR_TYPE_NSEC || 5647b5038d7SDag-Erling Smørgrav ldns_rr_get_type(tree->parents[i]->rr) == 5657b5038d7SDag-Erling Smørgrav LDNS_RR_TYPE_NSEC3) { 5667b5038d7SDag-Erling Smørgrav if (tree->parent_status[i] == LDNS_STATUS_OK) { 5677b5038d7SDag-Erling Smørgrav print_tabs(out, tabs + 1, sibmap, treedepth); 5687b5038d7SDag-Erling Smørgrav if (tabs == 0 && 5697b5038d7SDag-Erling Smørgrav ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_NS && 5707b5038d7SDag-Erling Smørgrav ldns_rr_rd_count(tree->rr) > 0) { 5717b5038d7SDag-Erling Smørgrav fprintf(out, "Existence of DS is denied by:\n"); 5727b5038d7SDag-Erling Smørgrav } else { 5737b5038d7SDag-Erling Smørgrav fprintf(out, "Existence is denied by:\n"); 5747b5038d7SDag-Erling Smørgrav } 5757b5038d7SDag-Erling Smørgrav } else { 5767b5038d7SDag-Erling Smørgrav /* NS records aren't signed */ 5777b5038d7SDag-Erling Smørgrav if (ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_NS) { 5787b5038d7SDag-Erling Smørgrav fprintf(out, "Existence of DS is denied by:\n"); 5797b5038d7SDag-Erling Smørgrav } else { 5807b5038d7SDag-Erling Smørgrav print_tabs(out, tabs + 1, sibmap, treedepth); 5817b5038d7SDag-Erling Smørgrav fprintf(out, 5827b5038d7SDag-Erling Smørgrav "Error in denial of existence: %s\n", 5837b5038d7SDag-Erling Smørgrav ldns_get_errorstr_by_id( 5847b5038d7SDag-Erling Smørgrav tree->parent_status[i])); 5857b5038d7SDag-Erling Smørgrav } 5867b5038d7SDag-Erling Smørgrav } 5877b5038d7SDag-Erling Smørgrav } else 5887b5038d7SDag-Erling Smørgrav if (tree->parent_status[i] != LDNS_STATUS_OK) { 5897b5038d7SDag-Erling Smørgrav print_tabs(out, tabs + 1, sibmap, treedepth); 5907b5038d7SDag-Erling Smørgrav fprintf(out, 5917b5038d7SDag-Erling Smørgrav "%s:\n", 5927b5038d7SDag-Erling Smørgrav ldns_get_errorstr_by_id( 5937b5038d7SDag-Erling Smørgrav tree->parent_status[i])); 5947b5038d7SDag-Erling Smørgrav if (tree->parent_status[i] 5957b5038d7SDag-Erling Smørgrav == LDNS_STATUS_SSL_ERR) { 5967b5038d7SDag-Erling Smørgrav printf("; SSL Error: "); 5977b5038d7SDag-Erling Smørgrav ERR_load_crypto_strings(); 5987b5038d7SDag-Erling Smørgrav ERR_print_errors_fp(stdout); 5997b5038d7SDag-Erling Smørgrav printf("\n"); 6007b5038d7SDag-Erling Smørgrav } 6017b5038d7SDag-Erling Smørgrav ldns_rr_print_fmt(out, fmt, 6027b5038d7SDag-Erling Smørgrav tree-> 6037b5038d7SDag-Erling Smørgrav parent_signature[i]); 6047b5038d7SDag-Erling Smørgrav printf("For RRset:\n"); 6057b5038d7SDag-Erling Smørgrav ldns_rr_list_print_fmt(out, fmt, 6067b5038d7SDag-Erling Smørgrav tree->rrset); 6077b5038d7SDag-Erling Smørgrav printf("With key:\n"); 6087b5038d7SDag-Erling Smørgrav ldns_rr_print_fmt(out, fmt, 6097b5038d7SDag-Erling Smørgrav tree->parents[i]->rr); 6107b5038d7SDag-Erling Smørgrav } 6117b5038d7SDag-Erling Smørgrav ldns_dnssec_trust_tree_print_sm_fmt(out, fmt, 6127b5038d7SDag-Erling Smørgrav tree->parents[i], 6137b5038d7SDag-Erling Smørgrav tabs+1, 6147b5038d7SDag-Erling Smørgrav extended, 6157b5038d7SDag-Erling Smørgrav sibmap, 6167b5038d7SDag-Erling Smørgrav treedepth); 6177b5038d7SDag-Erling Smørgrav } 6187b5038d7SDag-Erling Smørgrav } else { 6197b5038d7SDag-Erling Smørgrav print_tabs(out, tabs, sibmap, treedepth); 6207b5038d7SDag-Erling Smørgrav fprintf(out, "<no data>\n"); 6217b5038d7SDag-Erling Smørgrav } 6227b5038d7SDag-Erling Smørgrav } else { 6237b5038d7SDag-Erling Smørgrav fprintf(out, "<null pointer>\n"); 6247b5038d7SDag-Erling Smørgrav } 6257b5038d7SDag-Erling Smørgrav 6267b5038d7SDag-Erling Smørgrav if (mapset) { 6277b5038d7SDag-Erling Smørgrav LDNS_FREE(sibmap); 6287b5038d7SDag-Erling Smørgrav } 6297b5038d7SDag-Erling Smørgrav } 6307b5038d7SDag-Erling Smørgrav 6317b5038d7SDag-Erling Smørgrav static void 6327b5038d7SDag-Erling Smørgrav ldns_dnssec_trust_tree_print_sm(FILE *out, 6337b5038d7SDag-Erling Smørgrav ldns_dnssec_trust_tree *tree, 6347b5038d7SDag-Erling Smørgrav size_t tabs, 6357b5038d7SDag-Erling Smørgrav bool extended, 6367b5038d7SDag-Erling Smørgrav uint8_t *sibmap, 6377b5038d7SDag-Erling Smørgrav size_t treedepth) 6387b5038d7SDag-Erling Smørgrav { 6397b5038d7SDag-Erling Smørgrav ldns_dnssec_trust_tree_print_sm_fmt(out, ldns_output_format_default, 6407b5038d7SDag-Erling Smørgrav tree, tabs, extended, sibmap, treedepth); 6417b5038d7SDag-Erling Smørgrav } 6427b5038d7SDag-Erling Smørgrav 6437b5038d7SDag-Erling Smørgrav void 6447b5038d7SDag-Erling Smørgrav ldns_dnssec_trust_tree_print_fmt(FILE *out, const ldns_output_format *fmt, 6457b5038d7SDag-Erling Smørgrav ldns_dnssec_trust_tree *tree, 6467b5038d7SDag-Erling Smørgrav size_t tabs, 6477b5038d7SDag-Erling Smørgrav bool extended) 6487b5038d7SDag-Erling Smørgrav { 6497b5038d7SDag-Erling Smørgrav ldns_dnssec_trust_tree_print_sm_fmt(out, fmt, 6507b5038d7SDag-Erling Smørgrav tree, tabs, extended, NULL, 0); 6517b5038d7SDag-Erling Smørgrav } 6527b5038d7SDag-Erling Smørgrav 6537b5038d7SDag-Erling Smørgrav void 6547b5038d7SDag-Erling Smørgrav ldns_dnssec_trust_tree_print(FILE *out, 6557b5038d7SDag-Erling Smørgrav ldns_dnssec_trust_tree *tree, 6567b5038d7SDag-Erling Smørgrav size_t tabs, 6577b5038d7SDag-Erling Smørgrav bool extended) 6587b5038d7SDag-Erling Smørgrav { 6597b5038d7SDag-Erling Smørgrav ldns_dnssec_trust_tree_print_fmt(out, ldns_output_format_default, 6607b5038d7SDag-Erling Smørgrav tree, tabs, extended); 6617b5038d7SDag-Erling Smørgrav } 6627b5038d7SDag-Erling Smørgrav 6637b5038d7SDag-Erling Smørgrav 6647b5038d7SDag-Erling Smørgrav ldns_status 6657b5038d7SDag-Erling Smørgrav ldns_dnssec_trust_tree_add_parent(ldns_dnssec_trust_tree *tree, 6667b5038d7SDag-Erling Smørgrav const ldns_dnssec_trust_tree *parent, 6677b5038d7SDag-Erling Smørgrav const ldns_rr *signature, 6687b5038d7SDag-Erling Smørgrav const ldns_status parent_status) 6697b5038d7SDag-Erling Smørgrav { 6707b5038d7SDag-Erling Smørgrav if (tree 6717b5038d7SDag-Erling Smørgrav && parent 6727b5038d7SDag-Erling Smørgrav && tree->parent_count < LDNS_DNSSEC_TRUST_TREE_MAX_PARENTS) { 6737b5038d7SDag-Erling Smørgrav /* 6747b5038d7SDag-Erling Smørgrav printf("Add parent for: "); 6757b5038d7SDag-Erling Smørgrav ldns_rr_print(stdout, tree->rr); 6767b5038d7SDag-Erling Smørgrav printf("parent: "); 6777b5038d7SDag-Erling Smørgrav ldns_rr_print(stdout, parent->rr); 6787b5038d7SDag-Erling Smørgrav */ 6797b5038d7SDag-Erling Smørgrav tree->parents[tree->parent_count] = 6807b5038d7SDag-Erling Smørgrav (ldns_dnssec_trust_tree *) parent; 6817b5038d7SDag-Erling Smørgrav tree->parent_status[tree->parent_count] = parent_status; 6827b5038d7SDag-Erling Smørgrav tree->parent_signature[tree->parent_count] = (ldns_rr *) signature; 6837b5038d7SDag-Erling Smørgrav tree->parent_count++; 6847b5038d7SDag-Erling Smørgrav return LDNS_STATUS_OK; 6857b5038d7SDag-Erling Smørgrav } else { 6867b5038d7SDag-Erling Smørgrav return LDNS_STATUS_ERR; 6877b5038d7SDag-Erling Smørgrav } 6887b5038d7SDag-Erling Smørgrav } 6897b5038d7SDag-Erling Smørgrav 6907b5038d7SDag-Erling Smørgrav /* if rr is null, take the first from the rrset */ 6917b5038d7SDag-Erling Smørgrav ldns_dnssec_trust_tree * 6927b5038d7SDag-Erling Smørgrav ldns_dnssec_derive_trust_tree_time( 6937b5038d7SDag-Erling Smørgrav ldns_dnssec_data_chain *data_chain, 6947b5038d7SDag-Erling Smørgrav ldns_rr *rr, 6957b5038d7SDag-Erling Smørgrav time_t check_time 6967b5038d7SDag-Erling Smørgrav ) 6977b5038d7SDag-Erling Smørgrav { 6987b5038d7SDag-Erling Smørgrav ldns_rr_list *cur_rrset; 6997b5038d7SDag-Erling Smørgrav ldns_rr_list *cur_sigs; 7007b5038d7SDag-Erling Smørgrav ldns_rr *cur_rr = NULL; 7017b5038d7SDag-Erling Smørgrav ldns_rr *cur_sig_rr; 7027b5038d7SDag-Erling Smørgrav size_t i, j; 7037b5038d7SDag-Erling Smørgrav 7047b5038d7SDag-Erling Smørgrav ldns_dnssec_trust_tree *new_tree = ldns_dnssec_trust_tree_new(); 7057b5038d7SDag-Erling Smørgrav if(!new_tree) 7067b5038d7SDag-Erling Smørgrav return NULL; 7077b5038d7SDag-Erling Smørgrav 7087b5038d7SDag-Erling Smørgrav if (data_chain && data_chain->rrset) { 7097b5038d7SDag-Erling Smørgrav cur_rrset = data_chain->rrset; 7107b5038d7SDag-Erling Smørgrav 7117b5038d7SDag-Erling Smørgrav cur_sigs = data_chain->signatures; 7127b5038d7SDag-Erling Smørgrav 7137b5038d7SDag-Erling Smørgrav if (rr) { 7147b5038d7SDag-Erling Smørgrav cur_rr = rr; 7157b5038d7SDag-Erling Smørgrav } 7167b5038d7SDag-Erling Smørgrav 7177b5038d7SDag-Erling Smørgrav if (!cur_rr && ldns_rr_list_rr_count(cur_rrset) > 0) { 7187b5038d7SDag-Erling Smørgrav cur_rr = ldns_rr_list_rr(cur_rrset, 0); 7197b5038d7SDag-Erling Smørgrav } 7207b5038d7SDag-Erling Smørgrav 7217b5038d7SDag-Erling Smørgrav if (cur_rr) { 7227b5038d7SDag-Erling Smørgrav new_tree->rr = cur_rr; 7237b5038d7SDag-Erling Smørgrav new_tree->rrset = cur_rrset; 7247b5038d7SDag-Erling Smørgrav /* there are three possibilities: 7257b5038d7SDag-Erling Smørgrav 1 - 'normal' rrset, signed by a key 7267b5038d7SDag-Erling Smørgrav 2 - dnskey signed by other dnskey 7277b5038d7SDag-Erling Smørgrav 3 - dnskey proven by higher level DS 7287b5038d7SDag-Erling Smørgrav (data denied by nsec is a special case that can 7297b5038d7SDag-Erling Smørgrav occur in multiple places) 7307b5038d7SDag-Erling Smørgrav 7317b5038d7SDag-Erling Smørgrav */ 7327b5038d7SDag-Erling Smørgrav if (cur_sigs) { 7337b5038d7SDag-Erling Smørgrav for (i = 0; i < ldns_rr_list_rr_count(cur_sigs); i++) { 7347b5038d7SDag-Erling Smørgrav /* find the appropriate key in the parent list */ 7357b5038d7SDag-Erling Smørgrav cur_sig_rr = ldns_rr_list_rr(cur_sigs, i); 7367b5038d7SDag-Erling Smørgrav 7377b5038d7SDag-Erling Smørgrav if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_NSEC) { 7387b5038d7SDag-Erling Smørgrav if (ldns_dname_compare(ldns_rr_owner(cur_sig_rr), 7397b5038d7SDag-Erling Smørgrav ldns_rr_owner(cur_rr))) 7407b5038d7SDag-Erling Smørgrav { 7417b5038d7SDag-Erling Smørgrav /* find first that does match */ 7427b5038d7SDag-Erling Smørgrav 7437b5038d7SDag-Erling Smørgrav for (j = 0; 7447b5038d7SDag-Erling Smørgrav j < ldns_rr_list_rr_count(cur_rrset) && 7457b5038d7SDag-Erling Smørgrav ldns_dname_compare(ldns_rr_owner(cur_sig_rr),ldns_rr_owner(cur_rr)) != 0; 7467b5038d7SDag-Erling Smørgrav j++) { 7477b5038d7SDag-Erling Smørgrav cur_rr = ldns_rr_list_rr(cur_rrset, j); 7487b5038d7SDag-Erling Smørgrav 7497b5038d7SDag-Erling Smørgrav } 7507b5038d7SDag-Erling Smørgrav if (ldns_dname_compare(ldns_rr_owner(cur_sig_rr), 7517b5038d7SDag-Erling Smørgrav ldns_rr_owner(cur_rr))) 7527b5038d7SDag-Erling Smørgrav { 7537b5038d7SDag-Erling Smørgrav break; 7547b5038d7SDag-Erling Smørgrav } 7557b5038d7SDag-Erling Smørgrav } 7567b5038d7SDag-Erling Smørgrav 7577b5038d7SDag-Erling Smørgrav } 7587b5038d7SDag-Erling Smørgrav /* option 1 */ 7597b5038d7SDag-Erling Smørgrav if (data_chain->parent) { 7607b5038d7SDag-Erling Smørgrav ldns_dnssec_derive_trust_tree_normal_rrset_time( 7617b5038d7SDag-Erling Smørgrav new_tree, 7627b5038d7SDag-Erling Smørgrav data_chain, 7637b5038d7SDag-Erling Smørgrav cur_sig_rr, 7647b5038d7SDag-Erling Smørgrav check_time); 7657b5038d7SDag-Erling Smørgrav } 7667b5038d7SDag-Erling Smørgrav 7677b5038d7SDag-Erling Smørgrav /* option 2 */ 7687b5038d7SDag-Erling Smørgrav ldns_dnssec_derive_trust_tree_dnskey_rrset_time( 7697b5038d7SDag-Erling Smørgrav new_tree, 7707b5038d7SDag-Erling Smørgrav data_chain, 7717b5038d7SDag-Erling Smørgrav cur_rr, 7727b5038d7SDag-Erling Smørgrav cur_sig_rr, 7737b5038d7SDag-Erling Smørgrav check_time); 7747b5038d7SDag-Erling Smørgrav } 7757b5038d7SDag-Erling Smørgrav 7767b5038d7SDag-Erling Smørgrav ldns_dnssec_derive_trust_tree_ds_rrset_time( 7777b5038d7SDag-Erling Smørgrav new_tree, data_chain, 7787b5038d7SDag-Erling Smørgrav cur_rr, check_time); 7797b5038d7SDag-Erling Smørgrav } else { 7807b5038d7SDag-Erling Smørgrav /* no signatures? maybe it's nsec data */ 7817b5038d7SDag-Erling Smørgrav 7827b5038d7SDag-Erling Smørgrav /* just add every rr from parent as new parent */ 7837b5038d7SDag-Erling Smørgrav ldns_dnssec_derive_trust_tree_no_sig_time( 7847b5038d7SDag-Erling Smørgrav new_tree, data_chain, check_time); 7857b5038d7SDag-Erling Smørgrav } 7867b5038d7SDag-Erling Smørgrav } 7877b5038d7SDag-Erling Smørgrav } 7887b5038d7SDag-Erling Smørgrav 7897b5038d7SDag-Erling Smørgrav return new_tree; 7907b5038d7SDag-Erling Smørgrav } 7917b5038d7SDag-Erling Smørgrav 7927b5038d7SDag-Erling Smørgrav ldns_dnssec_trust_tree * 7937b5038d7SDag-Erling Smørgrav ldns_dnssec_derive_trust_tree(ldns_dnssec_data_chain *data_chain, ldns_rr *rr) 7947b5038d7SDag-Erling Smørgrav { 7957b5038d7SDag-Erling Smørgrav return ldns_dnssec_derive_trust_tree_time(data_chain, rr, ldns_time(NULL)); 7967b5038d7SDag-Erling Smørgrav } 7977b5038d7SDag-Erling Smørgrav 7987b5038d7SDag-Erling Smørgrav void 7997b5038d7SDag-Erling Smørgrav ldns_dnssec_derive_trust_tree_normal_rrset_time( 8007b5038d7SDag-Erling Smørgrav ldns_dnssec_trust_tree *new_tree, 8017b5038d7SDag-Erling Smørgrav ldns_dnssec_data_chain *data_chain, 8027b5038d7SDag-Erling Smørgrav ldns_rr *cur_sig_rr, 8037b5038d7SDag-Erling Smørgrav time_t check_time) 8047b5038d7SDag-Erling Smørgrav { 8057b5038d7SDag-Erling Smørgrav size_t i, j; 8067b5038d7SDag-Erling Smørgrav ldns_rr_list *cur_rrset = ldns_rr_list_clone(data_chain->rrset); 8077b5038d7SDag-Erling Smørgrav ldns_dnssec_trust_tree *cur_parent_tree; 8087b5038d7SDag-Erling Smørgrav ldns_rr *cur_parent_rr; 8097b5038d7SDag-Erling Smørgrav uint16_t cur_keytag; 8107b5038d7SDag-Erling Smørgrav ldns_rr_list *tmp_rrset = NULL; 8117b5038d7SDag-Erling Smørgrav ldns_status cur_status; 8127b5038d7SDag-Erling Smørgrav 8137b5038d7SDag-Erling Smørgrav cur_keytag = ldns_rdf2native_int16(ldns_rr_rrsig_keytag(cur_sig_rr)); 8147b5038d7SDag-Erling Smørgrav 8157b5038d7SDag-Erling Smørgrav for (j = 0; j < ldns_rr_list_rr_count(data_chain->parent->rrset); j++) { 8167b5038d7SDag-Erling Smørgrav cur_parent_rr = ldns_rr_list_rr(data_chain->parent->rrset, j); 8177b5038d7SDag-Erling Smørgrav if (ldns_rr_get_type(cur_parent_rr) == LDNS_RR_TYPE_DNSKEY) { 8187b5038d7SDag-Erling Smørgrav if (ldns_calc_keytag(cur_parent_rr) == cur_keytag) { 8197b5038d7SDag-Erling Smørgrav 8207b5038d7SDag-Erling Smørgrav /* TODO: check wildcard nsec too */ 8217b5038d7SDag-Erling Smørgrav if (cur_rrset && ldns_rr_list_rr_count(cur_rrset) > 0) { 8227b5038d7SDag-Erling Smørgrav tmp_rrset = cur_rrset; 8237b5038d7SDag-Erling Smørgrav if (ldns_rr_get_type(ldns_rr_list_rr(cur_rrset, 0)) 8247b5038d7SDag-Erling Smørgrav == LDNS_RR_TYPE_NSEC || 8257b5038d7SDag-Erling Smørgrav ldns_rr_get_type(ldns_rr_list_rr(cur_rrset, 0)) 8267b5038d7SDag-Erling Smørgrav == LDNS_RR_TYPE_NSEC3) { 8277b5038d7SDag-Erling Smørgrav /* might contain different names! 8287b5038d7SDag-Erling Smørgrav sort and split */ 8297b5038d7SDag-Erling Smørgrav ldns_rr_list_sort(cur_rrset); 830*2787e39aSDag-Erling Smørgrav assert(tmp_rrset == cur_rrset); 8317b5038d7SDag-Erling Smørgrav tmp_rrset = ldns_rr_list_pop_rrset(cur_rrset); 8327b5038d7SDag-Erling Smørgrav 8337b5038d7SDag-Erling Smørgrav /* with nsecs, this might be the wrong one */ 8347b5038d7SDag-Erling Smørgrav while (tmp_rrset && 8357b5038d7SDag-Erling Smørgrav ldns_rr_list_rr_count(cur_rrset) > 0 && 8367b5038d7SDag-Erling Smørgrav ldns_dname_compare( 8377b5038d7SDag-Erling Smørgrav ldns_rr_owner(ldns_rr_list_rr( 8387b5038d7SDag-Erling Smørgrav tmp_rrset, 0)), 8397b5038d7SDag-Erling Smørgrav ldns_rr_owner(cur_sig_rr)) != 0) { 8407b5038d7SDag-Erling Smørgrav ldns_rr_list_deep_free(tmp_rrset); 8417b5038d7SDag-Erling Smørgrav tmp_rrset = 8427b5038d7SDag-Erling Smørgrav ldns_rr_list_pop_rrset(cur_rrset); 8437b5038d7SDag-Erling Smørgrav } 8447b5038d7SDag-Erling Smørgrav } 8457b5038d7SDag-Erling Smørgrav cur_status = ldns_verify_rrsig_time( 8467b5038d7SDag-Erling Smørgrav tmp_rrset, 8477b5038d7SDag-Erling Smørgrav cur_sig_rr, 8487b5038d7SDag-Erling Smørgrav cur_parent_rr, 8497b5038d7SDag-Erling Smørgrav check_time); 850*2787e39aSDag-Erling Smørgrav if (tmp_rrset && tmp_rrset != cur_rrset 851*2787e39aSDag-Erling Smørgrav ) { 852*2787e39aSDag-Erling Smørgrav ldns_rr_list_deep_free( 853*2787e39aSDag-Erling Smørgrav tmp_rrset); 854*2787e39aSDag-Erling Smørgrav tmp_rrset = NULL; 855*2787e39aSDag-Erling Smørgrav } 8567b5038d7SDag-Erling Smørgrav /* avoid dupes */ 8577b5038d7SDag-Erling Smørgrav for (i = 0; i < new_tree->parent_count; i++) { 8587b5038d7SDag-Erling Smørgrav if (cur_parent_rr == new_tree->parents[i]->rr) { 8597b5038d7SDag-Erling Smørgrav goto done; 8607b5038d7SDag-Erling Smørgrav } 8617b5038d7SDag-Erling Smørgrav } 8627b5038d7SDag-Erling Smørgrav 8637b5038d7SDag-Erling Smørgrav cur_parent_tree = 8647b5038d7SDag-Erling Smørgrav ldns_dnssec_derive_trust_tree_time( 8657b5038d7SDag-Erling Smørgrav data_chain->parent, 8667b5038d7SDag-Erling Smørgrav cur_parent_rr, 8677b5038d7SDag-Erling Smørgrav check_time); 8687b5038d7SDag-Erling Smørgrav (void)ldns_dnssec_trust_tree_add_parent(new_tree, 8697b5038d7SDag-Erling Smørgrav cur_parent_tree, 8707b5038d7SDag-Erling Smørgrav cur_sig_rr, 8717b5038d7SDag-Erling Smørgrav cur_status); 8727b5038d7SDag-Erling Smørgrav } 8737b5038d7SDag-Erling Smørgrav } 8747b5038d7SDag-Erling Smørgrav } 8757b5038d7SDag-Erling Smørgrav } 8767b5038d7SDag-Erling Smørgrav done: 8777b5038d7SDag-Erling Smørgrav ldns_rr_list_deep_free(cur_rrset); 8787b5038d7SDag-Erling Smørgrav } 8797b5038d7SDag-Erling Smørgrav 8807b5038d7SDag-Erling Smørgrav void 8817b5038d7SDag-Erling Smørgrav ldns_dnssec_derive_trust_tree_normal_rrset(ldns_dnssec_trust_tree *new_tree, 8827b5038d7SDag-Erling Smørgrav ldns_dnssec_data_chain *data_chain, 8837b5038d7SDag-Erling Smørgrav ldns_rr *cur_sig_rr) 8847b5038d7SDag-Erling Smørgrav { 8857b5038d7SDag-Erling Smørgrav ldns_dnssec_derive_trust_tree_normal_rrset_time( 8867b5038d7SDag-Erling Smørgrav new_tree, data_chain, cur_sig_rr, ldns_time(NULL)); 8877b5038d7SDag-Erling Smørgrav } 8887b5038d7SDag-Erling Smørgrav 8897b5038d7SDag-Erling Smørgrav void 8907b5038d7SDag-Erling Smørgrav ldns_dnssec_derive_trust_tree_dnskey_rrset_time( 8917b5038d7SDag-Erling Smørgrav ldns_dnssec_trust_tree *new_tree, 8927b5038d7SDag-Erling Smørgrav ldns_dnssec_data_chain *data_chain, 8937b5038d7SDag-Erling Smørgrav ldns_rr *cur_rr, 8947b5038d7SDag-Erling Smørgrav ldns_rr *cur_sig_rr, 8957b5038d7SDag-Erling Smørgrav time_t check_time) 8967b5038d7SDag-Erling Smørgrav { 8977b5038d7SDag-Erling Smørgrav size_t j; 8987b5038d7SDag-Erling Smørgrav ldns_rr_list *cur_rrset = data_chain->rrset; 8997b5038d7SDag-Erling Smørgrav ldns_dnssec_trust_tree *cur_parent_tree; 9007b5038d7SDag-Erling Smørgrav ldns_rr *cur_parent_rr; 9017b5038d7SDag-Erling Smørgrav uint16_t cur_keytag; 9027b5038d7SDag-Erling Smørgrav ldns_status cur_status; 9037b5038d7SDag-Erling Smørgrav 9047b5038d7SDag-Erling Smørgrav cur_keytag = ldns_rdf2native_int16(ldns_rr_rrsig_keytag(cur_sig_rr)); 9057b5038d7SDag-Erling Smørgrav 9067b5038d7SDag-Erling Smørgrav for (j = 0; j < ldns_rr_list_rr_count(cur_rrset); j++) { 9077b5038d7SDag-Erling Smørgrav cur_parent_rr = ldns_rr_list_rr(cur_rrset, j); 9087b5038d7SDag-Erling Smørgrav if (cur_parent_rr != cur_rr && 9097b5038d7SDag-Erling Smørgrav ldns_rr_get_type(cur_parent_rr) == LDNS_RR_TYPE_DNSKEY) { 9107b5038d7SDag-Erling Smørgrav if (ldns_calc_keytag(cur_parent_rr) == cur_keytag 9117b5038d7SDag-Erling Smørgrav ) { 9127b5038d7SDag-Erling Smørgrav cur_parent_tree = ldns_dnssec_trust_tree_new(); 9137b5038d7SDag-Erling Smørgrav cur_parent_tree->rr = cur_parent_rr; 9147b5038d7SDag-Erling Smørgrav cur_parent_tree->rrset = cur_rrset; 9157b5038d7SDag-Erling Smørgrav cur_status = ldns_verify_rrsig_time( 9167b5038d7SDag-Erling Smørgrav cur_rrset, cur_sig_rr, 9177b5038d7SDag-Erling Smørgrav cur_parent_rr, check_time); 9187b5038d7SDag-Erling Smørgrav (void) ldns_dnssec_trust_tree_add_parent(new_tree, 9197b5038d7SDag-Erling Smørgrav cur_parent_tree, cur_sig_rr, cur_status); 9207b5038d7SDag-Erling Smørgrav } 9217b5038d7SDag-Erling Smørgrav } 9227b5038d7SDag-Erling Smørgrav } 9237b5038d7SDag-Erling Smørgrav } 9247b5038d7SDag-Erling Smørgrav 9257b5038d7SDag-Erling Smørgrav void 9267b5038d7SDag-Erling Smørgrav ldns_dnssec_derive_trust_tree_dnskey_rrset(ldns_dnssec_trust_tree *new_tree, 9277b5038d7SDag-Erling Smørgrav ldns_dnssec_data_chain *data_chain, 9287b5038d7SDag-Erling Smørgrav ldns_rr *cur_rr, 9297b5038d7SDag-Erling Smørgrav ldns_rr *cur_sig_rr) 9307b5038d7SDag-Erling Smørgrav { 9317b5038d7SDag-Erling Smørgrav ldns_dnssec_derive_trust_tree_dnskey_rrset_time( 9327b5038d7SDag-Erling Smørgrav new_tree, data_chain, cur_rr, cur_sig_rr, ldns_time(NULL)); 9337b5038d7SDag-Erling Smørgrav } 9347b5038d7SDag-Erling Smørgrav 9357b5038d7SDag-Erling Smørgrav void 9367b5038d7SDag-Erling Smørgrav ldns_dnssec_derive_trust_tree_ds_rrset_time( 9377b5038d7SDag-Erling Smørgrav ldns_dnssec_trust_tree *new_tree, 9387b5038d7SDag-Erling Smørgrav ldns_dnssec_data_chain *data_chain, 9397b5038d7SDag-Erling Smørgrav ldns_rr *cur_rr, 9407b5038d7SDag-Erling Smørgrav time_t check_time) 9417b5038d7SDag-Erling Smørgrav { 9427b5038d7SDag-Erling Smørgrav size_t j, h; 9437b5038d7SDag-Erling Smørgrav ldns_rr_list *cur_rrset = data_chain->rrset; 9447b5038d7SDag-Erling Smørgrav ldns_dnssec_trust_tree *cur_parent_tree; 9457b5038d7SDag-Erling Smørgrav ldns_rr *cur_parent_rr; 9467b5038d7SDag-Erling Smørgrav 9477b5038d7SDag-Erling Smørgrav /* try the parent to see whether there are DSs there */ 9487b5038d7SDag-Erling Smørgrav if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_DNSKEY && 9497b5038d7SDag-Erling Smørgrav data_chain->parent && 9507b5038d7SDag-Erling Smørgrav data_chain->parent->rrset 9517b5038d7SDag-Erling Smørgrav ) { 9527b5038d7SDag-Erling Smørgrav for (j = 0; 9537b5038d7SDag-Erling Smørgrav j < ldns_rr_list_rr_count(data_chain->parent->rrset); 9547b5038d7SDag-Erling Smørgrav j++) { 9557b5038d7SDag-Erling Smørgrav cur_parent_rr = ldns_rr_list_rr(data_chain->parent->rrset, j); 9567b5038d7SDag-Erling Smørgrav if (ldns_rr_get_type(cur_parent_rr) == LDNS_RR_TYPE_DS) { 9577b5038d7SDag-Erling Smørgrav for (h = 0; h < ldns_rr_list_rr_count(cur_rrset); h++) { 9587b5038d7SDag-Erling Smørgrav cur_rr = ldns_rr_list_rr(cur_rrset, h); 9597b5038d7SDag-Erling Smørgrav if (ldns_rr_compare_ds(cur_rr, cur_parent_rr)) { 9607b5038d7SDag-Erling Smørgrav cur_parent_tree = 9617b5038d7SDag-Erling Smørgrav ldns_dnssec_derive_trust_tree_time( 9627b5038d7SDag-Erling Smørgrav data_chain->parent, 9637b5038d7SDag-Erling Smørgrav cur_parent_rr, 9647b5038d7SDag-Erling Smørgrav check_time); 9657b5038d7SDag-Erling Smørgrav (void) ldns_dnssec_trust_tree_add_parent( 9667b5038d7SDag-Erling Smørgrav new_tree, 9677b5038d7SDag-Erling Smørgrav cur_parent_tree, 9687b5038d7SDag-Erling Smørgrav NULL, 9697b5038d7SDag-Erling Smørgrav LDNS_STATUS_OK); 9707b5038d7SDag-Erling Smørgrav } else { 9717b5038d7SDag-Erling Smørgrav /*ldns_rr_print(stdout, cur_parent_rr);*/ 9727b5038d7SDag-Erling Smørgrav } 9737b5038d7SDag-Erling Smørgrav } 9747b5038d7SDag-Erling Smørgrav } 9757b5038d7SDag-Erling Smørgrav } 9767b5038d7SDag-Erling Smørgrav } 9777b5038d7SDag-Erling Smørgrav } 9787b5038d7SDag-Erling Smørgrav 9797b5038d7SDag-Erling Smørgrav void 9807b5038d7SDag-Erling Smørgrav ldns_dnssec_derive_trust_tree_ds_rrset(ldns_dnssec_trust_tree *new_tree, 9817b5038d7SDag-Erling Smørgrav ldns_dnssec_data_chain *data_chain, 9827b5038d7SDag-Erling Smørgrav ldns_rr *cur_rr) 9837b5038d7SDag-Erling Smørgrav { 9847b5038d7SDag-Erling Smørgrav ldns_dnssec_derive_trust_tree_ds_rrset_time( 9857b5038d7SDag-Erling Smørgrav new_tree, data_chain, cur_rr, ldns_time(NULL)); 9867b5038d7SDag-Erling Smørgrav } 9877b5038d7SDag-Erling Smørgrav 9887b5038d7SDag-Erling Smørgrav void 9897b5038d7SDag-Erling Smørgrav ldns_dnssec_derive_trust_tree_no_sig_time( 9907b5038d7SDag-Erling Smørgrav ldns_dnssec_trust_tree *new_tree, 9917b5038d7SDag-Erling Smørgrav ldns_dnssec_data_chain *data_chain, 9927b5038d7SDag-Erling Smørgrav time_t check_time) 9937b5038d7SDag-Erling Smørgrav { 9947b5038d7SDag-Erling Smørgrav size_t i; 9957b5038d7SDag-Erling Smørgrav ldns_rr_list *cur_rrset; 9967b5038d7SDag-Erling Smørgrav ldns_rr *cur_parent_rr; 9977b5038d7SDag-Erling Smørgrav ldns_dnssec_trust_tree *cur_parent_tree; 9987b5038d7SDag-Erling Smørgrav ldns_status result; 9997b5038d7SDag-Erling Smørgrav 10007b5038d7SDag-Erling Smørgrav if (data_chain->parent && data_chain->parent->rrset) { 10017b5038d7SDag-Erling Smørgrav cur_rrset = data_chain->parent->rrset; 10027b5038d7SDag-Erling Smørgrav /* nsec? */ 10037b5038d7SDag-Erling Smørgrav if (cur_rrset && ldns_rr_list_rr_count(cur_rrset) > 0) { 10047b5038d7SDag-Erling Smørgrav if (ldns_rr_get_type(ldns_rr_list_rr(cur_rrset, 0)) == 10057b5038d7SDag-Erling Smørgrav LDNS_RR_TYPE_NSEC3) { 10067b5038d7SDag-Erling Smørgrav result = ldns_dnssec_verify_denial_nsec3( 10077b5038d7SDag-Erling Smørgrav new_tree->rr, 10087b5038d7SDag-Erling Smørgrav cur_rrset, 10097b5038d7SDag-Erling Smørgrav data_chain->parent->signatures, 10107b5038d7SDag-Erling Smørgrav data_chain->packet_rcode, 10117b5038d7SDag-Erling Smørgrav data_chain->packet_qtype, 10127b5038d7SDag-Erling Smørgrav data_chain->packet_nodata); 10137b5038d7SDag-Erling Smørgrav } else if (ldns_rr_get_type(ldns_rr_list_rr(cur_rrset, 0)) == 10147b5038d7SDag-Erling Smørgrav LDNS_RR_TYPE_NSEC) { 10157b5038d7SDag-Erling Smørgrav result = ldns_dnssec_verify_denial( 10167b5038d7SDag-Erling Smørgrav new_tree->rr, 10177b5038d7SDag-Erling Smørgrav cur_rrset, 10187b5038d7SDag-Erling Smørgrav data_chain->parent->signatures); 10197b5038d7SDag-Erling Smørgrav } else { 10207b5038d7SDag-Erling Smørgrav /* unsigned zone, unsigned parent */ 10217b5038d7SDag-Erling Smørgrav result = LDNS_STATUS_OK; 10227b5038d7SDag-Erling Smørgrav } 10237b5038d7SDag-Erling Smørgrav } else { 10247b5038d7SDag-Erling Smørgrav result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED; 10257b5038d7SDag-Erling Smørgrav } 10267b5038d7SDag-Erling Smørgrav for (i = 0; i < ldns_rr_list_rr_count(cur_rrset); i++) { 10277b5038d7SDag-Erling Smørgrav cur_parent_rr = ldns_rr_list_rr(cur_rrset, i); 10287b5038d7SDag-Erling Smørgrav cur_parent_tree = 10297b5038d7SDag-Erling Smørgrav ldns_dnssec_derive_trust_tree_time( 10307b5038d7SDag-Erling Smørgrav data_chain->parent, 10317b5038d7SDag-Erling Smørgrav cur_parent_rr, 10327b5038d7SDag-Erling Smørgrav check_time); 10337b5038d7SDag-Erling Smørgrav (void) ldns_dnssec_trust_tree_add_parent(new_tree, 10347b5038d7SDag-Erling Smørgrav cur_parent_tree, NULL, result); 10357b5038d7SDag-Erling Smørgrav } 10367b5038d7SDag-Erling Smørgrav } 10377b5038d7SDag-Erling Smørgrav } 10387b5038d7SDag-Erling Smørgrav 10397b5038d7SDag-Erling Smørgrav void 10407b5038d7SDag-Erling Smørgrav ldns_dnssec_derive_trust_tree_no_sig(ldns_dnssec_trust_tree *new_tree, 10417b5038d7SDag-Erling Smørgrav ldns_dnssec_data_chain *data_chain) 10427b5038d7SDag-Erling Smørgrav { 10437b5038d7SDag-Erling Smørgrav ldns_dnssec_derive_trust_tree_no_sig_time( 10447b5038d7SDag-Erling Smørgrav new_tree, data_chain, ldns_time(NULL)); 10457b5038d7SDag-Erling Smørgrav } 10467b5038d7SDag-Erling Smørgrav 10477b5038d7SDag-Erling Smørgrav /* 10487b5038d7SDag-Erling Smørgrav * returns OK if there is a path from tree to key with only OK 10497b5038d7SDag-Erling Smørgrav * the (first) error in between otherwise 10507b5038d7SDag-Erling Smørgrav * or NOT_FOUND if the key wasn't present at all 10517b5038d7SDag-Erling Smørgrav */ 10527b5038d7SDag-Erling Smørgrav ldns_status 10537b5038d7SDag-Erling Smørgrav ldns_dnssec_trust_tree_contains_keys(ldns_dnssec_trust_tree *tree, 10547b5038d7SDag-Erling Smørgrav ldns_rr_list *trusted_keys) 10557b5038d7SDag-Erling Smørgrav { 10567b5038d7SDag-Erling Smørgrav size_t i; 10577b5038d7SDag-Erling Smørgrav ldns_status result = LDNS_STATUS_CRYPTO_NO_DNSKEY; 10587b5038d7SDag-Erling Smørgrav bool equal; 10597b5038d7SDag-Erling Smørgrav ldns_status parent_result; 10607b5038d7SDag-Erling Smørgrav 10617b5038d7SDag-Erling Smørgrav if (tree && trusted_keys && ldns_rr_list_rr_count(trusted_keys) > 0) 10627b5038d7SDag-Erling Smørgrav { if (tree->rr) { 10637b5038d7SDag-Erling Smørgrav for (i = 0; i < ldns_rr_list_rr_count(trusted_keys); i++) { 10647b5038d7SDag-Erling Smørgrav equal = ldns_rr_compare_ds( 10657b5038d7SDag-Erling Smørgrav tree->rr, 10667b5038d7SDag-Erling Smørgrav ldns_rr_list_rr(trusted_keys, i)); 10677b5038d7SDag-Erling Smørgrav if (equal) { 10687b5038d7SDag-Erling Smørgrav result = LDNS_STATUS_OK; 10697b5038d7SDag-Erling Smørgrav return result; 10707b5038d7SDag-Erling Smørgrav } 10717b5038d7SDag-Erling Smørgrav } 10727b5038d7SDag-Erling Smørgrav } 10737b5038d7SDag-Erling Smørgrav for (i = 0; i < tree->parent_count; i++) { 10747b5038d7SDag-Erling Smørgrav parent_result = 10757b5038d7SDag-Erling Smørgrav ldns_dnssec_trust_tree_contains_keys(tree->parents[i], 10767b5038d7SDag-Erling Smørgrav trusted_keys); 10777b5038d7SDag-Erling Smørgrav if (parent_result != LDNS_STATUS_CRYPTO_NO_DNSKEY) { 10787b5038d7SDag-Erling Smørgrav if (tree->parent_status[i] != LDNS_STATUS_OK) { 10797b5038d7SDag-Erling Smørgrav result = tree->parent_status[i]; 10807b5038d7SDag-Erling Smørgrav } else { 1081*2787e39aSDag-Erling Smørgrav if (tree->rr && 1082*2787e39aSDag-Erling Smørgrav ldns_rr_get_type(tree->rr) 10837b5038d7SDag-Erling Smørgrav == LDNS_RR_TYPE_NSEC && 10847b5038d7SDag-Erling Smørgrav parent_result == LDNS_STATUS_OK 10857b5038d7SDag-Erling Smørgrav ) { 10867b5038d7SDag-Erling Smørgrav result = 10877b5038d7SDag-Erling Smørgrav LDNS_STATUS_DNSSEC_EXISTENCE_DENIED; 10887b5038d7SDag-Erling Smørgrav } else { 10897b5038d7SDag-Erling Smørgrav result = parent_result; 10907b5038d7SDag-Erling Smørgrav } 10917b5038d7SDag-Erling Smørgrav } 10927b5038d7SDag-Erling Smørgrav } 10937b5038d7SDag-Erling Smørgrav } 10947b5038d7SDag-Erling Smørgrav } else { 10957b5038d7SDag-Erling Smørgrav result = LDNS_STATUS_ERR; 10967b5038d7SDag-Erling Smørgrav } 10977b5038d7SDag-Erling Smørgrav 10987b5038d7SDag-Erling Smørgrav return result; 10997b5038d7SDag-Erling Smørgrav } 11007b5038d7SDag-Erling Smørgrav 11017b5038d7SDag-Erling Smørgrav ldns_status 11027b5038d7SDag-Erling Smørgrav ldns_verify_time( 11037b5038d7SDag-Erling Smørgrav ldns_rr_list *rrset, 11047b5038d7SDag-Erling Smørgrav ldns_rr_list *rrsig, 11057b5038d7SDag-Erling Smørgrav const ldns_rr_list *keys, 11067b5038d7SDag-Erling Smørgrav time_t check_time, 11077b5038d7SDag-Erling Smørgrav ldns_rr_list *good_keys 11087b5038d7SDag-Erling Smørgrav ) 11097b5038d7SDag-Erling Smørgrav { 11107b5038d7SDag-Erling Smørgrav uint16_t i; 11117b5038d7SDag-Erling Smørgrav ldns_status verify_result = LDNS_STATUS_ERR; 11127b5038d7SDag-Erling Smørgrav 11137b5038d7SDag-Erling Smørgrav if (!rrset || !rrsig || !keys) { 11147b5038d7SDag-Erling Smørgrav return LDNS_STATUS_ERR; 11157b5038d7SDag-Erling Smørgrav } 11167b5038d7SDag-Erling Smørgrav 11177b5038d7SDag-Erling Smørgrav if (ldns_rr_list_rr_count(rrset) < 1) { 11187b5038d7SDag-Erling Smørgrav return LDNS_STATUS_ERR; 11197b5038d7SDag-Erling Smørgrav } 11207b5038d7SDag-Erling Smørgrav 11217b5038d7SDag-Erling Smørgrav if (ldns_rr_list_rr_count(rrsig) < 1) { 11227b5038d7SDag-Erling Smørgrav return LDNS_STATUS_CRYPTO_NO_RRSIG; 11237b5038d7SDag-Erling Smørgrav } 11247b5038d7SDag-Erling Smørgrav 11257b5038d7SDag-Erling Smørgrav if (ldns_rr_list_rr_count(keys) < 1) { 11267b5038d7SDag-Erling Smørgrav verify_result = LDNS_STATUS_CRYPTO_NO_TRUSTED_DNSKEY; 11277b5038d7SDag-Erling Smørgrav } else { 11287b5038d7SDag-Erling Smørgrav for (i = 0; i < ldns_rr_list_rr_count(rrsig); i++) { 11297b5038d7SDag-Erling Smørgrav ldns_status s = ldns_verify_rrsig_keylist_time( 11307b5038d7SDag-Erling Smørgrav rrset, ldns_rr_list_rr(rrsig, i), 11317b5038d7SDag-Erling Smørgrav keys, check_time, good_keys); 11327b5038d7SDag-Erling Smørgrav /* try a little to get more descriptive error */ 11337b5038d7SDag-Erling Smørgrav if(s == LDNS_STATUS_OK) { 11347b5038d7SDag-Erling Smørgrav verify_result = LDNS_STATUS_OK; 11357b5038d7SDag-Erling Smørgrav } else if(verify_result == LDNS_STATUS_ERR) 11367b5038d7SDag-Erling Smørgrav verify_result = s; 11377b5038d7SDag-Erling Smørgrav else if(s != LDNS_STATUS_ERR && verify_result == 11387b5038d7SDag-Erling Smørgrav LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY) 11397b5038d7SDag-Erling Smørgrav verify_result = s; 11407b5038d7SDag-Erling Smørgrav } 11417b5038d7SDag-Erling Smørgrav } 11427b5038d7SDag-Erling Smørgrav return verify_result; 11437b5038d7SDag-Erling Smørgrav } 11447b5038d7SDag-Erling Smørgrav 11457b5038d7SDag-Erling Smørgrav ldns_status 11467b5038d7SDag-Erling Smørgrav ldns_verify(ldns_rr_list *rrset, ldns_rr_list *rrsig, const ldns_rr_list *keys, 11477b5038d7SDag-Erling Smørgrav ldns_rr_list *good_keys) 11487b5038d7SDag-Erling Smørgrav { 11497b5038d7SDag-Erling Smørgrav return ldns_verify_time(rrset, rrsig, keys, ldns_time(NULL), good_keys); 11507b5038d7SDag-Erling Smørgrav } 11517b5038d7SDag-Erling Smørgrav 11527b5038d7SDag-Erling Smørgrav ldns_status 11537b5038d7SDag-Erling Smørgrav ldns_verify_notime(ldns_rr_list *rrset, ldns_rr_list *rrsig, 11547b5038d7SDag-Erling Smørgrav const ldns_rr_list *keys, ldns_rr_list *good_keys) 11557b5038d7SDag-Erling Smørgrav { 11567b5038d7SDag-Erling Smørgrav uint16_t i; 11577b5038d7SDag-Erling Smørgrav ldns_status verify_result = LDNS_STATUS_ERR; 11587b5038d7SDag-Erling Smørgrav 11597b5038d7SDag-Erling Smørgrav if (!rrset || !rrsig || !keys) { 11607b5038d7SDag-Erling Smørgrav return LDNS_STATUS_ERR; 11617b5038d7SDag-Erling Smørgrav } 11627b5038d7SDag-Erling Smørgrav 11637b5038d7SDag-Erling Smørgrav if (ldns_rr_list_rr_count(rrset) < 1) { 11647b5038d7SDag-Erling Smørgrav return LDNS_STATUS_ERR; 11657b5038d7SDag-Erling Smørgrav } 11667b5038d7SDag-Erling Smørgrav 11677b5038d7SDag-Erling Smørgrav if (ldns_rr_list_rr_count(rrsig) < 1) { 11687b5038d7SDag-Erling Smørgrav return LDNS_STATUS_CRYPTO_NO_RRSIG; 11697b5038d7SDag-Erling Smørgrav } 11707b5038d7SDag-Erling Smørgrav 11717b5038d7SDag-Erling Smørgrav if (ldns_rr_list_rr_count(keys) < 1) { 11727b5038d7SDag-Erling Smørgrav verify_result = LDNS_STATUS_CRYPTO_NO_TRUSTED_DNSKEY; 11737b5038d7SDag-Erling Smørgrav } else { 11747b5038d7SDag-Erling Smørgrav for (i = 0; i < ldns_rr_list_rr_count(rrsig); i++) { 11757b5038d7SDag-Erling Smørgrav ldns_status s = ldns_verify_rrsig_keylist_notime(rrset, 11767b5038d7SDag-Erling Smørgrav ldns_rr_list_rr(rrsig, i), keys, good_keys); 11777b5038d7SDag-Erling Smørgrav 11787b5038d7SDag-Erling Smørgrav /* try a little to get more descriptive error */ 11797b5038d7SDag-Erling Smørgrav if (s == LDNS_STATUS_OK) { 11807b5038d7SDag-Erling Smørgrav verify_result = LDNS_STATUS_OK; 11817b5038d7SDag-Erling Smørgrav } else if (verify_result == LDNS_STATUS_ERR) { 11827b5038d7SDag-Erling Smørgrav verify_result = s; 11837b5038d7SDag-Erling Smørgrav } else if (s != LDNS_STATUS_ERR && verify_result == 11847b5038d7SDag-Erling Smørgrav LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY) { 11857b5038d7SDag-Erling Smørgrav verify_result = s; 11867b5038d7SDag-Erling Smørgrav } 11877b5038d7SDag-Erling Smørgrav } 11887b5038d7SDag-Erling Smørgrav } 11897b5038d7SDag-Erling Smørgrav return verify_result; 11907b5038d7SDag-Erling Smørgrav } 11917b5038d7SDag-Erling Smørgrav 11927b5038d7SDag-Erling Smørgrav ldns_rr_list * 11937b5038d7SDag-Erling Smørgrav ldns_fetch_valid_domain_keys_time(const ldns_resolver *res, 11947b5038d7SDag-Erling Smørgrav const ldns_rdf *domain, 11957b5038d7SDag-Erling Smørgrav const ldns_rr_list *keys, 11967b5038d7SDag-Erling Smørgrav time_t check_time, 11977b5038d7SDag-Erling Smørgrav ldns_status *status) 11987b5038d7SDag-Erling Smørgrav { 11997b5038d7SDag-Erling Smørgrav ldns_rr_list * trusted_keys = NULL; 12007b5038d7SDag-Erling Smørgrav ldns_rr_list * ds_keys = NULL; 12017b5038d7SDag-Erling Smørgrav ldns_rdf * prev_parent_domain; 12027b5038d7SDag-Erling Smørgrav ldns_rdf * parent_domain; 12037b5038d7SDag-Erling Smørgrav ldns_rr_list * parent_keys = NULL; 12047b5038d7SDag-Erling Smørgrav 12057b5038d7SDag-Erling Smørgrav if (res && domain && keys) { 12067b5038d7SDag-Erling Smørgrav 12077b5038d7SDag-Erling Smørgrav if ((trusted_keys = ldns_validate_domain_dnskey_time(res, 12087b5038d7SDag-Erling Smørgrav domain, keys, check_time))) { 12097b5038d7SDag-Erling Smørgrav *status = LDNS_STATUS_OK; 12107b5038d7SDag-Erling Smørgrav } else { 12117b5038d7SDag-Erling Smørgrav /* No trusted keys in this domain, we'll have to find some in the parent domain */ 12127b5038d7SDag-Erling Smørgrav *status = LDNS_STATUS_CRYPTO_NO_TRUSTED_DNSKEY; 12137b5038d7SDag-Erling Smørgrav 12147b5038d7SDag-Erling Smørgrav parent_domain = ldns_dname_left_chop(domain); 1215*2787e39aSDag-Erling Smørgrav while (parent_domain && /* Fail if we are at the root*/ 1216*2787e39aSDag-Erling Smørgrav ldns_rdf_size(parent_domain) > 0) { 12177b5038d7SDag-Erling Smørgrav 12187b5038d7SDag-Erling Smørgrav if ((parent_keys = 12197b5038d7SDag-Erling Smørgrav ldns_fetch_valid_domain_keys_time(res, 12207b5038d7SDag-Erling Smørgrav parent_domain, 12217b5038d7SDag-Erling Smørgrav keys, 12227b5038d7SDag-Erling Smørgrav check_time, 12237b5038d7SDag-Erling Smørgrav status))) { 12247b5038d7SDag-Erling Smørgrav /* Check DS records */ 12257b5038d7SDag-Erling Smørgrav if ((ds_keys = 12267b5038d7SDag-Erling Smørgrav ldns_validate_domain_ds_time(res, 12277b5038d7SDag-Erling Smørgrav domain, 12287b5038d7SDag-Erling Smørgrav parent_keys, 12297b5038d7SDag-Erling Smørgrav check_time))) { 12307b5038d7SDag-Erling Smørgrav trusted_keys = 12317b5038d7SDag-Erling Smørgrav ldns_fetch_valid_domain_keys_time( 12327b5038d7SDag-Erling Smørgrav res, 12337b5038d7SDag-Erling Smørgrav domain, 12347b5038d7SDag-Erling Smørgrav ds_keys, 12357b5038d7SDag-Erling Smørgrav check_time, 12367b5038d7SDag-Erling Smørgrav status); 12377b5038d7SDag-Erling Smørgrav ldns_rr_list_deep_free(ds_keys); 12387b5038d7SDag-Erling Smørgrav } else { 12397b5038d7SDag-Erling Smørgrav /* No valid DS at the parent -- fail */ 12407b5038d7SDag-Erling Smørgrav *status = LDNS_STATUS_CRYPTO_NO_TRUSTED_DS ; 12417b5038d7SDag-Erling Smørgrav } 12427b5038d7SDag-Erling Smørgrav ldns_rr_list_deep_free(parent_keys); 12437b5038d7SDag-Erling Smørgrav break; 12447b5038d7SDag-Erling Smørgrav } else { 12457b5038d7SDag-Erling Smørgrav parent_domain = ldns_dname_left_chop(( 12467b5038d7SDag-Erling Smørgrav prev_parent_domain 12477b5038d7SDag-Erling Smørgrav = parent_domain 12487b5038d7SDag-Erling Smørgrav )); 12497b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(prev_parent_domain); 12507b5038d7SDag-Erling Smørgrav } 12517b5038d7SDag-Erling Smørgrav } 1252*2787e39aSDag-Erling Smørgrav if (parent_domain) { 12537b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(parent_domain); 12547b5038d7SDag-Erling Smørgrav } 12557b5038d7SDag-Erling Smørgrav } 1256*2787e39aSDag-Erling Smørgrav } 12577b5038d7SDag-Erling Smørgrav return trusted_keys; 12587b5038d7SDag-Erling Smørgrav } 12597b5038d7SDag-Erling Smørgrav 12607b5038d7SDag-Erling Smørgrav ldns_rr_list * 12617b5038d7SDag-Erling Smørgrav ldns_fetch_valid_domain_keys(const ldns_resolver *res, 12627b5038d7SDag-Erling Smørgrav const ldns_rdf *domain, 12637b5038d7SDag-Erling Smørgrav const ldns_rr_list *keys, 12647b5038d7SDag-Erling Smørgrav ldns_status *status) 12657b5038d7SDag-Erling Smørgrav { 12667b5038d7SDag-Erling Smørgrav return ldns_fetch_valid_domain_keys_time( 12677b5038d7SDag-Erling Smørgrav res, domain, keys, ldns_time(NULL), status); 12687b5038d7SDag-Erling Smørgrav } 12697b5038d7SDag-Erling Smørgrav 12707b5038d7SDag-Erling Smørgrav ldns_rr_list * 12717b5038d7SDag-Erling Smørgrav ldns_validate_domain_dnskey_time( 12727b5038d7SDag-Erling Smørgrav const ldns_resolver * res, 12737b5038d7SDag-Erling Smørgrav const ldns_rdf * domain, 12747b5038d7SDag-Erling Smørgrav const ldns_rr_list * keys, 12757b5038d7SDag-Erling Smørgrav time_t check_time 12767b5038d7SDag-Erling Smørgrav ) 12777b5038d7SDag-Erling Smørgrav { 12787b5038d7SDag-Erling Smørgrav ldns_pkt * keypkt; 12797b5038d7SDag-Erling Smørgrav ldns_rr * cur_key; 12807b5038d7SDag-Erling Smørgrav uint16_t key_i; uint16_t key_j; uint16_t key_k; 12817b5038d7SDag-Erling Smørgrav uint16_t sig_i; ldns_rr * cur_sig; 12827b5038d7SDag-Erling Smørgrav 12837b5038d7SDag-Erling Smørgrav ldns_rr_list * domain_keys = NULL; 12847b5038d7SDag-Erling Smørgrav ldns_rr_list * domain_sigs = NULL; 12857b5038d7SDag-Erling Smørgrav ldns_rr_list * trusted_keys = NULL; 12867b5038d7SDag-Erling Smørgrav 12877b5038d7SDag-Erling Smørgrav /* Fetch keys for the domain */ 12887b5038d7SDag-Erling Smørgrav keypkt = ldns_resolver_query(res, domain, 12897b5038d7SDag-Erling Smørgrav LDNS_RR_TYPE_DNSKEY, LDNS_RR_CLASS_IN, LDNS_RD); 12907b5038d7SDag-Erling Smørgrav if (keypkt) { 12917b5038d7SDag-Erling Smørgrav domain_keys = ldns_pkt_rr_list_by_type(keypkt, 12927b5038d7SDag-Erling Smørgrav LDNS_RR_TYPE_DNSKEY, 12937b5038d7SDag-Erling Smørgrav LDNS_SECTION_ANSWER); 12947b5038d7SDag-Erling Smørgrav domain_sigs = ldns_pkt_rr_list_by_type(keypkt, 12957b5038d7SDag-Erling Smørgrav LDNS_RR_TYPE_RRSIG, 12967b5038d7SDag-Erling Smørgrav LDNS_SECTION_ANSWER); 12977b5038d7SDag-Erling Smørgrav 12987b5038d7SDag-Erling Smørgrav /* Try to validate the record using our keys */ 12997b5038d7SDag-Erling Smørgrav for (key_i=0; key_i< ldns_rr_list_rr_count(domain_keys); key_i++) { 13007b5038d7SDag-Erling Smørgrav 13017b5038d7SDag-Erling Smørgrav cur_key = ldns_rr_list_rr(domain_keys, key_i); 13027b5038d7SDag-Erling Smørgrav for (key_j=0; key_j<ldns_rr_list_rr_count(keys); key_j++) { 13037b5038d7SDag-Erling Smørgrav if (ldns_rr_compare_ds(ldns_rr_list_rr(keys, key_j), 13047b5038d7SDag-Erling Smørgrav cur_key)) { 13057b5038d7SDag-Erling Smørgrav 13067b5038d7SDag-Erling Smørgrav /* Current key is trusted -- validate */ 13077b5038d7SDag-Erling Smørgrav trusted_keys = ldns_rr_list_new(); 13087b5038d7SDag-Erling Smørgrav 13097b5038d7SDag-Erling Smørgrav for (sig_i=0; 13107b5038d7SDag-Erling Smørgrav sig_i<ldns_rr_list_rr_count(domain_sigs); 13117b5038d7SDag-Erling Smørgrav sig_i++) { 13127b5038d7SDag-Erling Smørgrav cur_sig = ldns_rr_list_rr(domain_sigs, sig_i); 13137b5038d7SDag-Erling Smørgrav /* Avoid non-matching sigs */ 13147b5038d7SDag-Erling Smørgrav if (ldns_rdf2native_int16( 13157b5038d7SDag-Erling Smørgrav ldns_rr_rrsig_keytag(cur_sig)) 13167b5038d7SDag-Erling Smørgrav == ldns_calc_keytag(cur_key)) { 13177b5038d7SDag-Erling Smørgrav if (ldns_verify_rrsig_time( 13187b5038d7SDag-Erling Smørgrav domain_keys, 13197b5038d7SDag-Erling Smørgrav cur_sig, 13207b5038d7SDag-Erling Smørgrav cur_key, 13217b5038d7SDag-Erling Smørgrav check_time) 13227b5038d7SDag-Erling Smørgrav == LDNS_STATUS_OK) { 13237b5038d7SDag-Erling Smørgrav 13247b5038d7SDag-Erling Smørgrav /* Push the whole rrset 13257b5038d7SDag-Erling Smørgrav -- we can't do much more */ 13267b5038d7SDag-Erling Smørgrav for (key_k=0; 13277b5038d7SDag-Erling Smørgrav key_k<ldns_rr_list_rr_count( 13287b5038d7SDag-Erling Smørgrav domain_keys); 13297b5038d7SDag-Erling Smørgrav key_k++) { 13307b5038d7SDag-Erling Smørgrav ldns_rr_list_push_rr( 13317b5038d7SDag-Erling Smørgrav trusted_keys, 13327b5038d7SDag-Erling Smørgrav ldns_rr_clone( 13337b5038d7SDag-Erling Smørgrav ldns_rr_list_rr( 13347b5038d7SDag-Erling Smørgrav domain_keys, 13357b5038d7SDag-Erling Smørgrav key_k))); 13367b5038d7SDag-Erling Smørgrav } 13377b5038d7SDag-Erling Smørgrav 13387b5038d7SDag-Erling Smørgrav ldns_rr_list_deep_free(domain_keys); 13397b5038d7SDag-Erling Smørgrav ldns_rr_list_deep_free(domain_sigs); 13407b5038d7SDag-Erling Smørgrav ldns_pkt_free(keypkt); 13417b5038d7SDag-Erling Smørgrav return trusted_keys; 13427b5038d7SDag-Erling Smørgrav } 13437b5038d7SDag-Erling Smørgrav } 13447b5038d7SDag-Erling Smørgrav } 13457b5038d7SDag-Erling Smørgrav 13467b5038d7SDag-Erling Smørgrav /* Only push our trusted key */ 13477b5038d7SDag-Erling Smørgrav ldns_rr_list_push_rr(trusted_keys, 13487b5038d7SDag-Erling Smørgrav ldns_rr_clone(cur_key)); 13497b5038d7SDag-Erling Smørgrav } 13507b5038d7SDag-Erling Smørgrav } 13517b5038d7SDag-Erling Smørgrav } 13527b5038d7SDag-Erling Smørgrav 13537b5038d7SDag-Erling Smørgrav ldns_rr_list_deep_free(domain_keys); 13547b5038d7SDag-Erling Smørgrav ldns_rr_list_deep_free(domain_sigs); 13557b5038d7SDag-Erling Smørgrav ldns_pkt_free(keypkt); 13567b5038d7SDag-Erling Smørgrav 13577b5038d7SDag-Erling Smørgrav } else { 13587b5038d7SDag-Erling Smørgrav /* LDNS_STATUS_CRYPTO_NO_DNSKEY */ 13597b5038d7SDag-Erling Smørgrav } 13607b5038d7SDag-Erling Smørgrav 13617b5038d7SDag-Erling Smørgrav return trusted_keys; 13627b5038d7SDag-Erling Smørgrav } 13637b5038d7SDag-Erling Smørgrav 13647b5038d7SDag-Erling Smørgrav ldns_rr_list * 13657b5038d7SDag-Erling Smørgrav ldns_validate_domain_dnskey(const ldns_resolver * res, 13667b5038d7SDag-Erling Smørgrav const ldns_rdf * domain, 13677b5038d7SDag-Erling Smørgrav const ldns_rr_list * keys) 13687b5038d7SDag-Erling Smørgrav { 13697b5038d7SDag-Erling Smørgrav return ldns_validate_domain_dnskey_time( 13707b5038d7SDag-Erling Smørgrav res, domain, keys, ldns_time(NULL)); 13717b5038d7SDag-Erling Smørgrav } 13727b5038d7SDag-Erling Smørgrav 13737b5038d7SDag-Erling Smørgrav ldns_rr_list * 13747b5038d7SDag-Erling Smørgrav ldns_validate_domain_ds_time( 13757b5038d7SDag-Erling Smørgrav const ldns_resolver *res, 13767b5038d7SDag-Erling Smørgrav const ldns_rdf * domain, 13777b5038d7SDag-Erling Smørgrav const ldns_rr_list * keys, 13787b5038d7SDag-Erling Smørgrav time_t check_time) 13797b5038d7SDag-Erling Smørgrav { 13807b5038d7SDag-Erling Smørgrav ldns_pkt * dspkt; 13817b5038d7SDag-Erling Smørgrav uint16_t key_i; 13827b5038d7SDag-Erling Smørgrav ldns_rr_list * rrset = NULL; 13837b5038d7SDag-Erling Smørgrav ldns_rr_list * sigs = NULL; 13847b5038d7SDag-Erling Smørgrav ldns_rr_list * trusted_keys = NULL; 13857b5038d7SDag-Erling Smørgrav 13867b5038d7SDag-Erling Smørgrav /* Fetch DS for the domain */ 13877b5038d7SDag-Erling Smørgrav dspkt = ldns_resolver_query(res, domain, 13887b5038d7SDag-Erling Smørgrav LDNS_RR_TYPE_DS, LDNS_RR_CLASS_IN, LDNS_RD); 13897b5038d7SDag-Erling Smørgrav if (dspkt) { 13907b5038d7SDag-Erling Smørgrav rrset = ldns_pkt_rr_list_by_type(dspkt, 13917b5038d7SDag-Erling Smørgrav LDNS_RR_TYPE_DS, 13927b5038d7SDag-Erling Smørgrav LDNS_SECTION_ANSWER); 13937b5038d7SDag-Erling Smørgrav sigs = ldns_pkt_rr_list_by_type(dspkt, 13947b5038d7SDag-Erling Smørgrav LDNS_RR_TYPE_RRSIG, 13957b5038d7SDag-Erling Smørgrav LDNS_SECTION_ANSWER); 13967b5038d7SDag-Erling Smørgrav 13977b5038d7SDag-Erling Smørgrav /* Validate sigs */ 13987b5038d7SDag-Erling Smørgrav if (ldns_verify_time(rrset, sigs, keys, check_time, NULL) 13997b5038d7SDag-Erling Smørgrav == LDNS_STATUS_OK) { 14007b5038d7SDag-Erling Smørgrav trusted_keys = ldns_rr_list_new(); 14017b5038d7SDag-Erling Smørgrav for (key_i=0; key_i<ldns_rr_list_rr_count(rrset); key_i++) { 14027b5038d7SDag-Erling Smørgrav ldns_rr_list_push_rr(trusted_keys, 14037b5038d7SDag-Erling Smørgrav ldns_rr_clone(ldns_rr_list_rr(rrset, 14047b5038d7SDag-Erling Smørgrav key_i) 14057b5038d7SDag-Erling Smørgrav ) 14067b5038d7SDag-Erling Smørgrav ); 14077b5038d7SDag-Erling Smørgrav } 14087b5038d7SDag-Erling Smørgrav } 14097b5038d7SDag-Erling Smørgrav 14107b5038d7SDag-Erling Smørgrav ldns_rr_list_deep_free(rrset); 14117b5038d7SDag-Erling Smørgrav ldns_rr_list_deep_free(sigs); 14127b5038d7SDag-Erling Smørgrav ldns_pkt_free(dspkt); 14137b5038d7SDag-Erling Smørgrav 14147b5038d7SDag-Erling Smørgrav } else { 14157b5038d7SDag-Erling Smørgrav /* LDNS_STATUS_CRYPTO_NO_DS */ 14167b5038d7SDag-Erling Smørgrav } 14177b5038d7SDag-Erling Smørgrav 14187b5038d7SDag-Erling Smørgrav return trusted_keys; 14197b5038d7SDag-Erling Smørgrav } 14207b5038d7SDag-Erling Smørgrav 14217b5038d7SDag-Erling Smørgrav ldns_rr_list * 14227b5038d7SDag-Erling Smørgrav ldns_validate_domain_ds(const ldns_resolver *res, 14237b5038d7SDag-Erling Smørgrav const ldns_rdf * domain, 14247b5038d7SDag-Erling Smørgrav const ldns_rr_list * keys) 14257b5038d7SDag-Erling Smørgrav { 14267b5038d7SDag-Erling Smørgrav return ldns_validate_domain_ds_time(res, domain, keys, ldns_time(NULL)); 14277b5038d7SDag-Erling Smørgrav } 14287b5038d7SDag-Erling Smørgrav 14297b5038d7SDag-Erling Smørgrav ldns_status 14307b5038d7SDag-Erling Smørgrav ldns_verify_trusted_time( 14317b5038d7SDag-Erling Smørgrav ldns_resolver *res, 14327b5038d7SDag-Erling Smørgrav ldns_rr_list *rrset, 14337b5038d7SDag-Erling Smørgrav ldns_rr_list * rrsigs, 14347b5038d7SDag-Erling Smørgrav time_t check_time, 14357b5038d7SDag-Erling Smørgrav ldns_rr_list * validating_keys 14367b5038d7SDag-Erling Smørgrav ) 14377b5038d7SDag-Erling Smørgrav { 14387b5038d7SDag-Erling Smørgrav uint16_t sig_i; uint16_t key_i; 14397b5038d7SDag-Erling Smørgrav ldns_rr * cur_sig; ldns_rr * cur_key; 14407b5038d7SDag-Erling Smørgrav ldns_rr_list * trusted_keys = NULL; 14417b5038d7SDag-Erling Smørgrav ldns_status result = LDNS_STATUS_ERR; 14427b5038d7SDag-Erling Smørgrav 14437b5038d7SDag-Erling Smørgrav if (!res || !rrset || !rrsigs) { 14447b5038d7SDag-Erling Smørgrav return LDNS_STATUS_ERR; 14457b5038d7SDag-Erling Smørgrav } 14467b5038d7SDag-Erling Smørgrav 14477b5038d7SDag-Erling Smørgrav if (ldns_rr_list_rr_count(rrset) < 1) { 14487b5038d7SDag-Erling Smørgrav return LDNS_STATUS_ERR; 14497b5038d7SDag-Erling Smørgrav } 14507b5038d7SDag-Erling Smørgrav 14517b5038d7SDag-Erling Smørgrav if (ldns_rr_list_rr_count(rrsigs) < 1) { 14527b5038d7SDag-Erling Smørgrav return LDNS_STATUS_CRYPTO_NO_RRSIG; 14537b5038d7SDag-Erling Smørgrav } 14547b5038d7SDag-Erling Smørgrav 14557b5038d7SDag-Erling Smørgrav /* Look at each sig */ 14567b5038d7SDag-Erling Smørgrav for (sig_i=0; sig_i < ldns_rr_list_rr_count(rrsigs); sig_i++) { 14577b5038d7SDag-Erling Smørgrav 14587b5038d7SDag-Erling Smørgrav cur_sig = ldns_rr_list_rr(rrsigs, sig_i); 14597b5038d7SDag-Erling Smørgrav /* Get a valid signer key and validate the sig */ 14607b5038d7SDag-Erling Smørgrav if ((trusted_keys = ldns_fetch_valid_domain_keys_time( 14617b5038d7SDag-Erling Smørgrav res, 14627b5038d7SDag-Erling Smørgrav ldns_rr_rrsig_signame(cur_sig), 14637b5038d7SDag-Erling Smørgrav ldns_resolver_dnssec_anchors(res), 14647b5038d7SDag-Erling Smørgrav check_time, 14657b5038d7SDag-Erling Smørgrav &result))) { 14667b5038d7SDag-Erling Smørgrav 14677b5038d7SDag-Erling Smørgrav for (key_i = 0; 14687b5038d7SDag-Erling Smørgrav key_i < ldns_rr_list_rr_count(trusted_keys); 14697b5038d7SDag-Erling Smørgrav key_i++) { 14707b5038d7SDag-Erling Smørgrav cur_key = ldns_rr_list_rr(trusted_keys, key_i); 14717b5038d7SDag-Erling Smørgrav 14727b5038d7SDag-Erling Smørgrav if ((result = ldns_verify_rrsig_time(rrset, 14737b5038d7SDag-Erling Smørgrav cur_sig, 14747b5038d7SDag-Erling Smørgrav cur_key, 14757b5038d7SDag-Erling Smørgrav check_time)) 14767b5038d7SDag-Erling Smørgrav == LDNS_STATUS_OK) { 14777b5038d7SDag-Erling Smørgrav if (validating_keys) { 14787b5038d7SDag-Erling Smørgrav ldns_rr_list_push_rr(validating_keys, 14797b5038d7SDag-Erling Smørgrav ldns_rr_clone(cur_key)); 14807b5038d7SDag-Erling Smørgrav } 14817b5038d7SDag-Erling Smørgrav ldns_rr_list_deep_free(trusted_keys); 14827b5038d7SDag-Erling Smørgrav return LDNS_STATUS_OK; 14837b5038d7SDag-Erling Smørgrav } 14847b5038d7SDag-Erling Smørgrav } 14857b5038d7SDag-Erling Smørgrav } 14867b5038d7SDag-Erling Smørgrav } 14877b5038d7SDag-Erling Smørgrav 14887b5038d7SDag-Erling Smørgrav ldns_rr_list_deep_free(trusted_keys); 14897b5038d7SDag-Erling Smørgrav return result; 14907b5038d7SDag-Erling Smørgrav } 14917b5038d7SDag-Erling Smørgrav 14927b5038d7SDag-Erling Smørgrav ldns_status 14937b5038d7SDag-Erling Smørgrav ldns_verify_trusted( 14947b5038d7SDag-Erling Smørgrav ldns_resolver *res, 14957b5038d7SDag-Erling Smørgrav ldns_rr_list *rrset, 14967b5038d7SDag-Erling Smørgrav ldns_rr_list * rrsigs, 14977b5038d7SDag-Erling Smørgrav ldns_rr_list * validating_keys) 14987b5038d7SDag-Erling Smørgrav { 14997b5038d7SDag-Erling Smørgrav return ldns_verify_trusted_time( 15007b5038d7SDag-Erling Smørgrav res, rrset, rrsigs, ldns_time(NULL), validating_keys); 15017b5038d7SDag-Erling Smørgrav } 15027b5038d7SDag-Erling Smørgrav 15037b5038d7SDag-Erling Smørgrav 15047b5038d7SDag-Erling Smørgrav ldns_status 15057b5038d7SDag-Erling Smørgrav ldns_dnssec_verify_denial(ldns_rr *rr, 15067b5038d7SDag-Erling Smørgrav ldns_rr_list *nsecs, 15077b5038d7SDag-Erling Smørgrav ldns_rr_list *rrsigs) 15087b5038d7SDag-Erling Smørgrav { 15097b5038d7SDag-Erling Smørgrav ldns_rdf *rr_name; 15107b5038d7SDag-Erling Smørgrav ldns_rdf *wildcard_name; 15117b5038d7SDag-Erling Smørgrav ldns_rdf *chopped_dname; 15127b5038d7SDag-Erling Smørgrav ldns_rr *cur_nsec; 15137b5038d7SDag-Erling Smørgrav size_t i; 15147b5038d7SDag-Erling Smørgrav ldns_status result; 15157b5038d7SDag-Erling Smørgrav /* needed for wildcard check on exact match */ 15167b5038d7SDag-Erling Smørgrav ldns_rr *rrsig; 15177b5038d7SDag-Erling Smørgrav bool name_covered = false; 15187b5038d7SDag-Erling Smørgrav bool type_covered = false; 15197b5038d7SDag-Erling Smørgrav bool wildcard_covered = false; 15207b5038d7SDag-Erling Smørgrav bool wildcard_type_covered = false; 15217b5038d7SDag-Erling Smørgrav 15227b5038d7SDag-Erling Smørgrav wildcard_name = ldns_dname_new_frm_str("*"); 15237b5038d7SDag-Erling Smørgrav rr_name = ldns_rr_owner(rr); 15247b5038d7SDag-Erling Smørgrav chopped_dname = ldns_dname_left_chop(rr_name); 15257b5038d7SDag-Erling Smørgrav result = ldns_dname_cat(wildcard_name, chopped_dname); 1526*2787e39aSDag-Erling Smørgrav ldns_rdf_deep_free(chopped_dname); 15277b5038d7SDag-Erling Smørgrav if (result != LDNS_STATUS_OK) { 15287b5038d7SDag-Erling Smørgrav return result; 15297b5038d7SDag-Erling Smørgrav } 15307b5038d7SDag-Erling Smørgrav 15317b5038d7SDag-Erling Smørgrav for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) { 15327b5038d7SDag-Erling Smørgrav cur_nsec = ldns_rr_list_rr(nsecs, i); 15337b5038d7SDag-Erling Smørgrav if (ldns_dname_compare(rr_name, ldns_rr_owner(cur_nsec)) == 0) { 15347b5038d7SDag-Erling Smørgrav /* see section 5.4 of RFC4035, if the label count of the NSEC's 15357b5038d7SDag-Erling Smørgrav RRSIG is equal, then it is proven that wildcard expansion 15367b5038d7SDag-Erling Smørgrav could not have been used to match the request */ 15377b5038d7SDag-Erling Smørgrav rrsig = ldns_dnssec_get_rrsig_for_name_and_type( 15387b5038d7SDag-Erling Smørgrav ldns_rr_owner(cur_nsec), 15397b5038d7SDag-Erling Smørgrav ldns_rr_get_type(cur_nsec), 15407b5038d7SDag-Erling Smørgrav rrsigs); 15417b5038d7SDag-Erling Smørgrav if (rrsig && ldns_rdf2native_int8(ldns_rr_rrsig_labels(rrsig)) 15427b5038d7SDag-Erling Smørgrav == ldns_dname_label_count(rr_name)) { 15437b5038d7SDag-Erling Smørgrav wildcard_covered = true; 15447b5038d7SDag-Erling Smørgrav } 15457b5038d7SDag-Erling Smørgrav 15467b5038d7SDag-Erling Smørgrav if (ldns_nsec_bitmap_covers_type(ldns_nsec_get_bitmap(cur_nsec), 15477b5038d7SDag-Erling Smørgrav ldns_rr_get_type(rr))) { 15487b5038d7SDag-Erling Smørgrav type_covered = true; 15497b5038d7SDag-Erling Smørgrav } 15507b5038d7SDag-Erling Smørgrav } 15517b5038d7SDag-Erling Smørgrav if (ldns_nsec_covers_name(cur_nsec, rr_name)) { 15527b5038d7SDag-Erling Smørgrav name_covered = true; 15537b5038d7SDag-Erling Smørgrav } 15547b5038d7SDag-Erling Smørgrav 15557b5038d7SDag-Erling Smørgrav if (ldns_dname_compare(wildcard_name, 15567b5038d7SDag-Erling Smørgrav ldns_rr_owner(cur_nsec)) == 0) { 15577b5038d7SDag-Erling Smørgrav if (ldns_nsec_bitmap_covers_type(ldns_nsec_get_bitmap(cur_nsec), 15587b5038d7SDag-Erling Smørgrav ldns_rr_get_type(rr))) { 15597b5038d7SDag-Erling Smørgrav wildcard_type_covered = true; 15607b5038d7SDag-Erling Smørgrav } 15617b5038d7SDag-Erling Smørgrav } 15627b5038d7SDag-Erling Smørgrav 15637b5038d7SDag-Erling Smørgrav if (ldns_nsec_covers_name(cur_nsec, wildcard_name)) { 15647b5038d7SDag-Erling Smørgrav wildcard_covered = true; 15657b5038d7SDag-Erling Smørgrav } 15667b5038d7SDag-Erling Smørgrav 15677b5038d7SDag-Erling Smørgrav } 15687b5038d7SDag-Erling Smørgrav 15697b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(wildcard_name); 15707b5038d7SDag-Erling Smørgrav 15717b5038d7SDag-Erling Smørgrav if (type_covered || !name_covered) { 15727b5038d7SDag-Erling Smørgrav return LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED; 15737b5038d7SDag-Erling Smørgrav } 15747b5038d7SDag-Erling Smørgrav 15757b5038d7SDag-Erling Smørgrav if (wildcard_type_covered || !wildcard_covered) { 15767b5038d7SDag-Erling Smørgrav return LDNS_STATUS_DNSSEC_NSEC_WILDCARD_NOT_COVERED; 15777b5038d7SDag-Erling Smørgrav } 15787b5038d7SDag-Erling Smørgrav 15797b5038d7SDag-Erling Smørgrav return LDNS_STATUS_OK; 15807b5038d7SDag-Erling Smørgrav } 15817b5038d7SDag-Erling Smørgrav 15827b5038d7SDag-Erling Smørgrav ldns_status 15837b5038d7SDag-Erling Smørgrav ldns_dnssec_verify_denial_nsec3_match( ldns_rr *rr 15847b5038d7SDag-Erling Smørgrav , ldns_rr_list *nsecs 15857b5038d7SDag-Erling Smørgrav , ATTR_UNUSED(ldns_rr_list *rrsigs) 15867b5038d7SDag-Erling Smørgrav , ldns_pkt_rcode packet_rcode 15877b5038d7SDag-Erling Smørgrav , ldns_rr_type packet_qtype 15887b5038d7SDag-Erling Smørgrav , bool packet_nodata 15897b5038d7SDag-Erling Smørgrav , ldns_rr **match 15907b5038d7SDag-Erling Smørgrav ) 15917b5038d7SDag-Erling Smørgrav { 15927b5038d7SDag-Erling Smørgrav ldns_rdf *closest_encloser; 15937b5038d7SDag-Erling Smørgrav ldns_rdf *wildcard; 15947b5038d7SDag-Erling Smørgrav ldns_rdf *hashed_wildcard_name; 15957b5038d7SDag-Erling Smørgrav bool wildcard_covered = false; 15967b5038d7SDag-Erling Smørgrav ldns_rdf *zone_name; 15977b5038d7SDag-Erling Smørgrav ldns_rdf *hashed_name; 15987b5038d7SDag-Erling Smørgrav /* self assignment to suppress uninitialized warning */ 15997b5038d7SDag-Erling Smørgrav ldns_rdf *next_closer = next_closer; 16007b5038d7SDag-Erling Smørgrav ldns_rdf *hashed_next_closer; 16017b5038d7SDag-Erling Smørgrav size_t i; 16027b5038d7SDag-Erling Smørgrav ldns_status result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED; 16037b5038d7SDag-Erling Smørgrav 16047b5038d7SDag-Erling Smørgrav if (match) { 16057b5038d7SDag-Erling Smørgrav *match = NULL; 16067b5038d7SDag-Erling Smørgrav } 16077b5038d7SDag-Erling Smørgrav 16087b5038d7SDag-Erling Smørgrav zone_name = ldns_dname_left_chop(ldns_rr_owner(ldns_rr_list_rr(nsecs,0))); 16097b5038d7SDag-Erling Smørgrav 16107b5038d7SDag-Erling Smørgrav /* section 8.4 */ 16117b5038d7SDag-Erling Smørgrav if (packet_rcode == LDNS_RCODE_NXDOMAIN) { 16127b5038d7SDag-Erling Smørgrav closest_encloser = ldns_dnssec_nsec3_closest_encloser( 16137b5038d7SDag-Erling Smørgrav ldns_rr_owner(rr), 16147b5038d7SDag-Erling Smørgrav ldns_rr_get_type(rr), 16157b5038d7SDag-Erling Smørgrav nsecs); 16167b5038d7SDag-Erling Smørgrav if(!closest_encloser) { 1617*2787e39aSDag-Erling Smørgrav result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED; 16187b5038d7SDag-Erling Smørgrav goto done; 16197b5038d7SDag-Erling Smørgrav } 16207b5038d7SDag-Erling Smørgrav 16217b5038d7SDag-Erling Smørgrav wildcard = ldns_dname_new_frm_str("*"); 16227b5038d7SDag-Erling Smørgrav (void) ldns_dname_cat(wildcard, closest_encloser); 16237b5038d7SDag-Erling Smørgrav 16247b5038d7SDag-Erling Smørgrav for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) { 16257b5038d7SDag-Erling Smørgrav hashed_wildcard_name = 16267b5038d7SDag-Erling Smørgrav ldns_nsec3_hash_name_frm_nsec3(ldns_rr_list_rr(nsecs, 0), 16277b5038d7SDag-Erling Smørgrav wildcard 16287b5038d7SDag-Erling Smørgrav ); 16297b5038d7SDag-Erling Smørgrav (void) ldns_dname_cat(hashed_wildcard_name, zone_name); 16307b5038d7SDag-Erling Smørgrav 16317b5038d7SDag-Erling Smørgrav if (ldns_nsec_covers_name(ldns_rr_list_rr(nsecs, i), 16327b5038d7SDag-Erling Smørgrav hashed_wildcard_name)) { 16337b5038d7SDag-Erling Smørgrav wildcard_covered = true; 16347b5038d7SDag-Erling Smørgrav if (match) { 16357b5038d7SDag-Erling Smørgrav *match = ldns_rr_list_rr(nsecs, i); 16367b5038d7SDag-Erling Smørgrav } 16377b5038d7SDag-Erling Smørgrav } 16387b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(hashed_wildcard_name); 16397b5038d7SDag-Erling Smørgrav } 16407b5038d7SDag-Erling Smørgrav 1641*2787e39aSDag-Erling Smørgrav if (! wildcard_covered) { 1642*2787e39aSDag-Erling Smørgrav result = LDNS_STATUS_DNSSEC_NSEC_WILDCARD_NOT_COVERED; 1643*2787e39aSDag-Erling Smørgrav } else { 1644*2787e39aSDag-Erling Smørgrav result = LDNS_STATUS_OK; 1645*2787e39aSDag-Erling Smørgrav } 16467b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(closest_encloser); 16477b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(wildcard); 16487b5038d7SDag-Erling Smørgrav 16497b5038d7SDag-Erling Smørgrav } else if (packet_nodata && packet_qtype != LDNS_RR_TYPE_DS) { 16507b5038d7SDag-Erling Smørgrav /* section 8.5 */ 16517b5038d7SDag-Erling Smørgrav hashed_name = ldns_nsec3_hash_name_frm_nsec3( 16527b5038d7SDag-Erling Smørgrav ldns_rr_list_rr(nsecs, 0), 16537b5038d7SDag-Erling Smørgrav ldns_rr_owner(rr)); 16547b5038d7SDag-Erling Smørgrav (void) ldns_dname_cat(hashed_name, zone_name); 16557b5038d7SDag-Erling Smørgrav for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) { 16567b5038d7SDag-Erling Smørgrav if (ldns_dname_compare(hashed_name, 16577b5038d7SDag-Erling Smørgrav ldns_rr_owner(ldns_rr_list_rr(nsecs, i))) 16587b5038d7SDag-Erling Smørgrav == 0) { 16597b5038d7SDag-Erling Smørgrav if (!ldns_nsec_bitmap_covers_type( 16607b5038d7SDag-Erling Smørgrav ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)), 16617b5038d7SDag-Erling Smørgrav packet_qtype) 16627b5038d7SDag-Erling Smørgrav && 16637b5038d7SDag-Erling Smørgrav !ldns_nsec_bitmap_covers_type( 16647b5038d7SDag-Erling Smørgrav ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)), 16657b5038d7SDag-Erling Smørgrav LDNS_RR_TYPE_CNAME)) { 16667b5038d7SDag-Erling Smørgrav result = LDNS_STATUS_OK; 16677b5038d7SDag-Erling Smørgrav if (match) { 16687b5038d7SDag-Erling Smørgrav *match = ldns_rr_list_rr(nsecs, i); 16697b5038d7SDag-Erling Smørgrav } 16707b5038d7SDag-Erling Smørgrav goto done; 16717b5038d7SDag-Erling Smørgrav } 16727b5038d7SDag-Erling Smørgrav } 16737b5038d7SDag-Erling Smørgrav } 16747b5038d7SDag-Erling Smørgrav result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED; 16757b5038d7SDag-Erling Smørgrav /* wildcard no data? section 8.7 */ 16767b5038d7SDag-Erling Smørgrav closest_encloser = ldns_dnssec_nsec3_closest_encloser( 16777b5038d7SDag-Erling Smørgrav ldns_rr_owner(rr), 16787b5038d7SDag-Erling Smørgrav ldns_rr_get_type(rr), 16797b5038d7SDag-Erling Smørgrav nsecs); 16807b5038d7SDag-Erling Smørgrav if(!closest_encloser) { 16817b5038d7SDag-Erling Smørgrav result = LDNS_STATUS_NSEC3_ERR; 16827b5038d7SDag-Erling Smørgrav goto done; 16837b5038d7SDag-Erling Smørgrav } 16847b5038d7SDag-Erling Smørgrav wildcard = ldns_dname_new_frm_str("*"); 16857b5038d7SDag-Erling Smørgrav (void) ldns_dname_cat(wildcard, closest_encloser); 16867b5038d7SDag-Erling Smørgrav for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) { 16877b5038d7SDag-Erling Smørgrav hashed_wildcard_name = 16887b5038d7SDag-Erling Smørgrav ldns_nsec3_hash_name_frm_nsec3(ldns_rr_list_rr(nsecs, 0), 16897b5038d7SDag-Erling Smørgrav wildcard); 16907b5038d7SDag-Erling Smørgrav (void) ldns_dname_cat(hashed_wildcard_name, zone_name); 16917b5038d7SDag-Erling Smørgrav 16927b5038d7SDag-Erling Smørgrav if (ldns_dname_compare(hashed_wildcard_name, 16937b5038d7SDag-Erling Smørgrav ldns_rr_owner(ldns_rr_list_rr(nsecs, i))) 16947b5038d7SDag-Erling Smørgrav == 0) { 16957b5038d7SDag-Erling Smørgrav if (!ldns_nsec_bitmap_covers_type( 16967b5038d7SDag-Erling Smørgrav ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)), 16977b5038d7SDag-Erling Smørgrav packet_qtype) 16987b5038d7SDag-Erling Smørgrav && 16997b5038d7SDag-Erling Smørgrav !ldns_nsec_bitmap_covers_type( 17007b5038d7SDag-Erling Smørgrav ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)), 17017b5038d7SDag-Erling Smørgrav LDNS_RR_TYPE_CNAME)) { 17027b5038d7SDag-Erling Smørgrav result = LDNS_STATUS_OK; 17037b5038d7SDag-Erling Smørgrav if (match) { 17047b5038d7SDag-Erling Smørgrav *match = ldns_rr_list_rr(nsecs, i); 17057b5038d7SDag-Erling Smørgrav } 17067b5038d7SDag-Erling Smørgrav } 17077b5038d7SDag-Erling Smørgrav } 17087b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(hashed_wildcard_name); 17097b5038d7SDag-Erling Smørgrav if (result == LDNS_STATUS_OK) { 17107b5038d7SDag-Erling Smørgrav break; 17117b5038d7SDag-Erling Smørgrav } 17127b5038d7SDag-Erling Smørgrav } 17137b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(closest_encloser); 17147b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(wildcard); 17157b5038d7SDag-Erling Smørgrav } else if (packet_nodata && packet_qtype == LDNS_RR_TYPE_DS) { 17167b5038d7SDag-Erling Smørgrav /* section 8.6 */ 17177b5038d7SDag-Erling Smørgrav /* note: up to XXX this is the same as for 8.5 */ 17187b5038d7SDag-Erling Smørgrav hashed_name = ldns_nsec3_hash_name_frm_nsec3(ldns_rr_list_rr(nsecs, 17197b5038d7SDag-Erling Smørgrav 0), 17207b5038d7SDag-Erling Smørgrav ldns_rr_owner(rr) 17217b5038d7SDag-Erling Smørgrav ); 17227b5038d7SDag-Erling Smørgrav (void) ldns_dname_cat(hashed_name, zone_name); 17237b5038d7SDag-Erling Smørgrav for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) { 17247b5038d7SDag-Erling Smørgrav if (ldns_dname_compare(hashed_name, 17257b5038d7SDag-Erling Smørgrav ldns_rr_owner(ldns_rr_list_rr(nsecs, 17267b5038d7SDag-Erling Smørgrav i))) 17277b5038d7SDag-Erling Smørgrav == 0) { 17287b5038d7SDag-Erling Smørgrav if (!ldns_nsec_bitmap_covers_type( 17297b5038d7SDag-Erling Smørgrav ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)), 17307b5038d7SDag-Erling Smørgrav LDNS_RR_TYPE_DS) 17317b5038d7SDag-Erling Smørgrav && 17327b5038d7SDag-Erling Smørgrav !ldns_nsec_bitmap_covers_type( 17337b5038d7SDag-Erling Smørgrav ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)), 17347b5038d7SDag-Erling Smørgrav LDNS_RR_TYPE_CNAME)) { 17357b5038d7SDag-Erling Smørgrav result = LDNS_STATUS_OK; 17367b5038d7SDag-Erling Smørgrav if (match) { 17377b5038d7SDag-Erling Smørgrav *match = ldns_rr_list_rr(nsecs, i); 17387b5038d7SDag-Erling Smørgrav } 17397b5038d7SDag-Erling Smørgrav goto done; 17407b5038d7SDag-Erling Smørgrav } 17417b5038d7SDag-Erling Smørgrav } 17427b5038d7SDag-Erling Smørgrav } 17437b5038d7SDag-Erling Smørgrav 17447b5038d7SDag-Erling Smørgrav /* XXX see note above */ 17457b5038d7SDag-Erling Smørgrav result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED; 17467b5038d7SDag-Erling Smørgrav 17477b5038d7SDag-Erling Smørgrav closest_encloser = ldns_dnssec_nsec3_closest_encloser( 17487b5038d7SDag-Erling Smørgrav ldns_rr_owner(rr), 17497b5038d7SDag-Erling Smørgrav ldns_rr_get_type(rr), 17507b5038d7SDag-Erling Smørgrav nsecs); 17517b5038d7SDag-Erling Smørgrav if(!closest_encloser) { 17527b5038d7SDag-Erling Smørgrav result = LDNS_STATUS_NSEC3_ERR; 17537b5038d7SDag-Erling Smørgrav goto done; 17547b5038d7SDag-Erling Smørgrav } 17557b5038d7SDag-Erling Smørgrav /* Now check if we have a Opt-Out NSEC3 that covers the "next closer"*/ 17567b5038d7SDag-Erling Smørgrav 17577b5038d7SDag-Erling Smørgrav if (ldns_dname_label_count(closest_encloser) + 1 17587b5038d7SDag-Erling Smørgrav >= ldns_dname_label_count(ldns_rr_owner(rr))) { 17597b5038d7SDag-Erling Smørgrav 17607b5038d7SDag-Erling Smørgrav /* Query name *is* the "next closer". */ 17617b5038d7SDag-Erling Smørgrav hashed_next_closer = hashed_name; 17627b5038d7SDag-Erling Smørgrav } else { 17637b5038d7SDag-Erling Smørgrav 17647b5038d7SDag-Erling Smørgrav /* "next closer" has less labels than the query name. 17657b5038d7SDag-Erling Smørgrav * Create the name and hash it. 17667b5038d7SDag-Erling Smørgrav */ 17677b5038d7SDag-Erling Smørgrav next_closer = ldns_dname_clone_from( 17687b5038d7SDag-Erling Smørgrav ldns_rr_owner(rr), 17697b5038d7SDag-Erling Smørgrav ldns_dname_label_count(ldns_rr_owner(rr)) 17707b5038d7SDag-Erling Smørgrav - (ldns_dname_label_count(closest_encloser) + 1) 17717b5038d7SDag-Erling Smørgrav ); 17727b5038d7SDag-Erling Smørgrav hashed_next_closer = ldns_nsec3_hash_name_frm_nsec3( 17737b5038d7SDag-Erling Smørgrav ldns_rr_list_rr(nsecs, 0), 17747b5038d7SDag-Erling Smørgrav next_closer 17757b5038d7SDag-Erling Smørgrav ); 17767b5038d7SDag-Erling Smørgrav (void) ldns_dname_cat(hashed_next_closer, zone_name); 17777b5038d7SDag-Erling Smørgrav } 17787b5038d7SDag-Erling Smørgrav /* Find the NSEC3 that covers the "next closer" */ 17797b5038d7SDag-Erling Smørgrav for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) { 17807b5038d7SDag-Erling Smørgrav if (ldns_nsec_covers_name(ldns_rr_list_rr(nsecs, i), 17817b5038d7SDag-Erling Smørgrav hashed_next_closer) && 17827b5038d7SDag-Erling Smørgrav ldns_nsec3_optout(ldns_rr_list_rr(nsecs, i))) { 17837b5038d7SDag-Erling Smørgrav 17847b5038d7SDag-Erling Smørgrav result = LDNS_STATUS_OK; 17857b5038d7SDag-Erling Smørgrav if (match) { 17867b5038d7SDag-Erling Smørgrav *match = ldns_rr_list_rr(nsecs, i); 17877b5038d7SDag-Erling Smørgrav } 17887b5038d7SDag-Erling Smørgrav break; 17897b5038d7SDag-Erling Smørgrav } 17907b5038d7SDag-Erling Smørgrav } 17917b5038d7SDag-Erling Smørgrav if (ldns_dname_label_count(closest_encloser) + 1 17927b5038d7SDag-Erling Smørgrav < ldns_dname_label_count(ldns_rr_owner(rr))) { 17937b5038d7SDag-Erling Smørgrav 17947b5038d7SDag-Erling Smørgrav /* "next closer" has less labels than the query name. 17957b5038d7SDag-Erling Smørgrav * Dispose of the temporary variables that held that name. 17967b5038d7SDag-Erling Smørgrav */ 17977b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(hashed_next_closer); 17987b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(next_closer); 17997b5038d7SDag-Erling Smørgrav } 18007b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(closest_encloser); 18017b5038d7SDag-Erling Smørgrav } 18027b5038d7SDag-Erling Smørgrav 18037b5038d7SDag-Erling Smørgrav done: 18047b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(zone_name); 18057b5038d7SDag-Erling Smørgrav return result; 18067b5038d7SDag-Erling Smørgrav } 18077b5038d7SDag-Erling Smørgrav 18087b5038d7SDag-Erling Smørgrav ldns_status 18097b5038d7SDag-Erling Smørgrav ldns_dnssec_verify_denial_nsec3(ldns_rr *rr, 18107b5038d7SDag-Erling Smørgrav ldns_rr_list *nsecs, 18117b5038d7SDag-Erling Smørgrav ldns_rr_list *rrsigs, 18127b5038d7SDag-Erling Smørgrav ldns_pkt_rcode packet_rcode, 18137b5038d7SDag-Erling Smørgrav ldns_rr_type packet_qtype, 18147b5038d7SDag-Erling Smørgrav bool packet_nodata) 18157b5038d7SDag-Erling Smørgrav { 18167b5038d7SDag-Erling Smørgrav return ldns_dnssec_verify_denial_nsec3_match( 18177b5038d7SDag-Erling Smørgrav rr, nsecs, rrsigs, packet_rcode, 18187b5038d7SDag-Erling Smørgrav packet_qtype, packet_nodata, NULL 18197b5038d7SDag-Erling Smørgrav ); 18207b5038d7SDag-Erling Smørgrav } 18217b5038d7SDag-Erling Smørgrav 18227b5038d7SDag-Erling Smørgrav #ifdef USE_GOST 18237b5038d7SDag-Erling Smørgrav EVP_PKEY* 18247b5038d7SDag-Erling Smørgrav ldns_gost2pkey_raw(unsigned char* key, size_t keylen) 18257b5038d7SDag-Erling Smørgrav { 18267b5038d7SDag-Erling Smørgrav /* prefix header for X509 encoding */ 18277b5038d7SDag-Erling Smørgrav uint8_t asn[37] = { 0x30, 0x63, 0x30, 0x1c, 0x06, 0x06, 0x2a, 0x85, 18287b5038d7SDag-Erling Smørgrav 0x03, 0x02, 0x02, 0x13, 0x30, 0x12, 0x06, 0x07, 0x2a, 0x85, 18297b5038d7SDag-Erling Smørgrav 0x03, 0x02, 0x02, 0x23, 0x01, 0x06, 0x07, 0x2a, 0x85, 0x03, 18307b5038d7SDag-Erling Smørgrav 0x02, 0x02, 0x1e, 0x01, 0x03, 0x43, 0x00, 0x04, 0x40}; 18317b5038d7SDag-Erling Smørgrav unsigned char encoded[37+64]; 18327b5038d7SDag-Erling Smørgrav const unsigned char* pp; 18337b5038d7SDag-Erling Smørgrav if(keylen != 64) { 18347b5038d7SDag-Erling Smørgrav /* key wrong size */ 18357b5038d7SDag-Erling Smørgrav return NULL; 18367b5038d7SDag-Erling Smørgrav } 18377b5038d7SDag-Erling Smørgrav 18387b5038d7SDag-Erling Smørgrav /* create evp_key */ 18397b5038d7SDag-Erling Smørgrav memmove(encoded, asn, 37); 18407b5038d7SDag-Erling Smørgrav memmove(encoded+37, key, 64); 18417b5038d7SDag-Erling Smørgrav pp = (unsigned char*)&encoded[0]; 18427b5038d7SDag-Erling Smørgrav 18437b5038d7SDag-Erling Smørgrav return d2i_PUBKEY(NULL, &pp, (int)sizeof(encoded)); 18447b5038d7SDag-Erling Smørgrav } 18457b5038d7SDag-Erling Smørgrav 18467b5038d7SDag-Erling Smørgrav static ldns_status 18477b5038d7SDag-Erling Smørgrav ldns_verify_rrsig_gost_raw(unsigned char* sig, size_t siglen, 18487b5038d7SDag-Erling Smørgrav ldns_buffer* rrset, unsigned char* key, size_t keylen) 18497b5038d7SDag-Erling Smørgrav { 18507b5038d7SDag-Erling Smørgrav EVP_PKEY *evp_key; 18517b5038d7SDag-Erling Smørgrav ldns_status result; 18527b5038d7SDag-Erling Smørgrav 18537b5038d7SDag-Erling Smørgrav (void) ldns_key_EVP_load_gost_id(); 18547b5038d7SDag-Erling Smørgrav evp_key = ldns_gost2pkey_raw(key, keylen); 18557b5038d7SDag-Erling Smørgrav if(!evp_key) { 18567b5038d7SDag-Erling Smørgrav /* could not convert key */ 18577b5038d7SDag-Erling Smørgrav return LDNS_STATUS_CRYPTO_BOGUS; 18587b5038d7SDag-Erling Smørgrav } 18597b5038d7SDag-Erling Smørgrav 18607b5038d7SDag-Erling Smørgrav /* verify signature */ 18617b5038d7SDag-Erling Smørgrav result = ldns_verify_rrsig_evp_raw(sig, siglen, rrset, 18627b5038d7SDag-Erling Smørgrav evp_key, EVP_get_digestbyname("md_gost94")); 18637b5038d7SDag-Erling Smørgrav EVP_PKEY_free(evp_key); 18647b5038d7SDag-Erling Smørgrav 18657b5038d7SDag-Erling Smørgrav return result; 18667b5038d7SDag-Erling Smørgrav } 18677b5038d7SDag-Erling Smørgrav #endif 18687b5038d7SDag-Erling Smørgrav 18697b5038d7SDag-Erling Smørgrav #ifdef USE_ECDSA 18707b5038d7SDag-Erling Smørgrav EVP_PKEY* 18717b5038d7SDag-Erling Smørgrav ldns_ecdsa2pkey_raw(unsigned char* key, size_t keylen, uint8_t algo) 18727b5038d7SDag-Erling Smørgrav { 18737b5038d7SDag-Erling Smørgrav unsigned char buf[256+2]; /* sufficient for 2*384/8+1 */ 18747b5038d7SDag-Erling Smørgrav const unsigned char* pp = buf; 18757b5038d7SDag-Erling Smørgrav EVP_PKEY *evp_key; 18767b5038d7SDag-Erling Smørgrav EC_KEY *ec; 18777b5038d7SDag-Erling Smørgrav /* check length, which uncompressed must be 2 bignums */ 18787b5038d7SDag-Erling Smørgrav if(algo == LDNS_ECDSAP256SHA256) { 18797b5038d7SDag-Erling Smørgrav if(keylen != 2*256/8) return NULL; 18807b5038d7SDag-Erling Smørgrav ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); 18817b5038d7SDag-Erling Smørgrav } else if(algo == LDNS_ECDSAP384SHA384) { 18827b5038d7SDag-Erling Smørgrav if(keylen != 2*384/8) return NULL; 18837b5038d7SDag-Erling Smørgrav ec = EC_KEY_new_by_curve_name(NID_secp384r1); 18847b5038d7SDag-Erling Smørgrav } else ec = NULL; 18857b5038d7SDag-Erling Smørgrav if(!ec) return NULL; 18867b5038d7SDag-Erling Smørgrav if(keylen+1 > sizeof(buf)) 18877b5038d7SDag-Erling Smørgrav return NULL; /* sanity check */ 18887b5038d7SDag-Erling Smørgrav /* prepend the 0x02 (from docs) (or actually 0x04 from implementation 18897b5038d7SDag-Erling Smørgrav * of openssl) for uncompressed data */ 18907b5038d7SDag-Erling Smørgrav buf[0] = POINT_CONVERSION_UNCOMPRESSED; 18917b5038d7SDag-Erling Smørgrav memmove(buf+1, key, keylen); 18927b5038d7SDag-Erling Smørgrav if(!o2i_ECPublicKey(&ec, &pp, (int)keylen+1)) { 18937b5038d7SDag-Erling Smørgrav EC_KEY_free(ec); 18947b5038d7SDag-Erling Smørgrav return NULL; 18957b5038d7SDag-Erling Smørgrav } 18967b5038d7SDag-Erling Smørgrav evp_key = EVP_PKEY_new(); 18977b5038d7SDag-Erling Smørgrav if(!evp_key) { 18987b5038d7SDag-Erling Smørgrav EC_KEY_free(ec); 18997b5038d7SDag-Erling Smørgrav return NULL; 19007b5038d7SDag-Erling Smørgrav } 19017b5038d7SDag-Erling Smørgrav if (!EVP_PKEY_assign_EC_KEY(evp_key, ec)) { 19027b5038d7SDag-Erling Smørgrav EVP_PKEY_free(evp_key); 19037b5038d7SDag-Erling Smørgrav EC_KEY_free(ec); 19047b5038d7SDag-Erling Smørgrav return NULL; 19057b5038d7SDag-Erling Smørgrav } 19067b5038d7SDag-Erling Smørgrav return evp_key; 19077b5038d7SDag-Erling Smørgrav } 19087b5038d7SDag-Erling Smørgrav 19097b5038d7SDag-Erling Smørgrav static ldns_status 19107b5038d7SDag-Erling Smørgrav ldns_verify_rrsig_ecdsa_raw(unsigned char* sig, size_t siglen, 19117b5038d7SDag-Erling Smørgrav ldns_buffer* rrset, unsigned char* key, size_t keylen, uint8_t algo) 19127b5038d7SDag-Erling Smørgrav { 19137b5038d7SDag-Erling Smørgrav EVP_PKEY *evp_key; 19147b5038d7SDag-Erling Smørgrav ldns_status result; 19157b5038d7SDag-Erling Smørgrav const EVP_MD *d; 19167b5038d7SDag-Erling Smørgrav 19177b5038d7SDag-Erling Smørgrav evp_key = ldns_ecdsa2pkey_raw(key, keylen, algo); 19187b5038d7SDag-Erling Smørgrav if(!evp_key) { 19197b5038d7SDag-Erling Smørgrav /* could not convert key */ 19207b5038d7SDag-Erling Smørgrav return LDNS_STATUS_CRYPTO_BOGUS; 19217b5038d7SDag-Erling Smørgrav } 19227b5038d7SDag-Erling Smørgrav if(algo == LDNS_ECDSAP256SHA256) 19237b5038d7SDag-Erling Smørgrav d = EVP_sha256(); 19247b5038d7SDag-Erling Smørgrav else d = EVP_sha384(); /* LDNS_ECDSAP384SHA384 */ 19257b5038d7SDag-Erling Smørgrav result = ldns_verify_rrsig_evp_raw(sig, siglen, rrset, evp_key, d); 19267b5038d7SDag-Erling Smørgrav EVP_PKEY_free(evp_key); 19277b5038d7SDag-Erling Smørgrav return result; 19287b5038d7SDag-Erling Smørgrav } 19297b5038d7SDag-Erling Smørgrav #endif 19307b5038d7SDag-Erling Smørgrav 19317b5038d7SDag-Erling Smørgrav ldns_status 19327b5038d7SDag-Erling Smørgrav ldns_verify_rrsig_buffers(ldns_buffer *rawsig_buf, ldns_buffer *verify_buf, 19337b5038d7SDag-Erling Smørgrav ldns_buffer *key_buf, uint8_t algo) 19347b5038d7SDag-Erling Smørgrav { 19357b5038d7SDag-Erling Smørgrav return ldns_verify_rrsig_buffers_raw( 19367b5038d7SDag-Erling Smørgrav (unsigned char*)ldns_buffer_begin(rawsig_buf), 19377b5038d7SDag-Erling Smørgrav ldns_buffer_position(rawsig_buf), 19387b5038d7SDag-Erling Smørgrav verify_buf, 19397b5038d7SDag-Erling Smørgrav (unsigned char*)ldns_buffer_begin(key_buf), 19407b5038d7SDag-Erling Smørgrav ldns_buffer_position(key_buf), algo); 19417b5038d7SDag-Erling Smørgrav } 19427b5038d7SDag-Erling Smørgrav 19437b5038d7SDag-Erling Smørgrav ldns_status 19447b5038d7SDag-Erling Smørgrav ldns_verify_rrsig_buffers_raw(unsigned char* sig, size_t siglen, 19457b5038d7SDag-Erling Smørgrav ldns_buffer *verify_buf, unsigned char* key, size_t keylen, 19467b5038d7SDag-Erling Smørgrav uint8_t algo) 19477b5038d7SDag-Erling Smørgrav { 19487b5038d7SDag-Erling Smørgrav /* check for right key */ 19497b5038d7SDag-Erling Smørgrav switch(algo) { 19507b5038d7SDag-Erling Smørgrav case LDNS_DSA: 19517b5038d7SDag-Erling Smørgrav case LDNS_DSA_NSEC3: 19527b5038d7SDag-Erling Smørgrav return ldns_verify_rrsig_dsa_raw(sig, 19537b5038d7SDag-Erling Smørgrav siglen, 19547b5038d7SDag-Erling Smørgrav verify_buf, 19557b5038d7SDag-Erling Smørgrav key, 19567b5038d7SDag-Erling Smørgrav keylen); 19577b5038d7SDag-Erling Smørgrav break; 19587b5038d7SDag-Erling Smørgrav case LDNS_RSASHA1: 19597b5038d7SDag-Erling Smørgrav case LDNS_RSASHA1_NSEC3: 19607b5038d7SDag-Erling Smørgrav return ldns_verify_rrsig_rsasha1_raw(sig, 19617b5038d7SDag-Erling Smørgrav siglen, 19627b5038d7SDag-Erling Smørgrav verify_buf, 19637b5038d7SDag-Erling Smørgrav key, 19647b5038d7SDag-Erling Smørgrav keylen); 19657b5038d7SDag-Erling Smørgrav break; 19667b5038d7SDag-Erling Smørgrav #ifdef USE_SHA2 19677b5038d7SDag-Erling Smørgrav case LDNS_RSASHA256: 19687b5038d7SDag-Erling Smørgrav return ldns_verify_rrsig_rsasha256_raw(sig, 19697b5038d7SDag-Erling Smørgrav siglen, 19707b5038d7SDag-Erling Smørgrav verify_buf, 19717b5038d7SDag-Erling Smørgrav key, 19727b5038d7SDag-Erling Smørgrav keylen); 19737b5038d7SDag-Erling Smørgrav break; 19747b5038d7SDag-Erling Smørgrav case LDNS_RSASHA512: 19757b5038d7SDag-Erling Smørgrav return ldns_verify_rrsig_rsasha512_raw(sig, 19767b5038d7SDag-Erling Smørgrav siglen, 19777b5038d7SDag-Erling Smørgrav verify_buf, 19787b5038d7SDag-Erling Smørgrav key, 19797b5038d7SDag-Erling Smørgrav keylen); 19807b5038d7SDag-Erling Smørgrav break; 19817b5038d7SDag-Erling Smørgrav #endif 19827b5038d7SDag-Erling Smørgrav #ifdef USE_GOST 19837b5038d7SDag-Erling Smørgrav case LDNS_ECC_GOST: 19847b5038d7SDag-Erling Smørgrav return ldns_verify_rrsig_gost_raw(sig, siglen, verify_buf, 19857b5038d7SDag-Erling Smørgrav key, keylen); 19867b5038d7SDag-Erling Smørgrav break; 19877b5038d7SDag-Erling Smørgrav #endif 19887b5038d7SDag-Erling Smørgrav #ifdef USE_ECDSA 19897b5038d7SDag-Erling Smørgrav case LDNS_ECDSAP256SHA256: 19907b5038d7SDag-Erling Smørgrav case LDNS_ECDSAP384SHA384: 19917b5038d7SDag-Erling Smørgrav return ldns_verify_rrsig_ecdsa_raw(sig, siglen, verify_buf, 19927b5038d7SDag-Erling Smørgrav key, keylen, algo); 19937b5038d7SDag-Erling Smørgrav break; 19947b5038d7SDag-Erling Smørgrav #endif 19957b5038d7SDag-Erling Smørgrav case LDNS_RSAMD5: 19967b5038d7SDag-Erling Smørgrav return ldns_verify_rrsig_rsamd5_raw(sig, 19977b5038d7SDag-Erling Smørgrav siglen, 19987b5038d7SDag-Erling Smørgrav verify_buf, 19997b5038d7SDag-Erling Smørgrav key, 20007b5038d7SDag-Erling Smørgrav keylen); 20017b5038d7SDag-Erling Smørgrav break; 20027b5038d7SDag-Erling Smørgrav default: 20037b5038d7SDag-Erling Smørgrav /* do you know this alg?! */ 20047b5038d7SDag-Erling Smørgrav return LDNS_STATUS_CRYPTO_UNKNOWN_ALGO; 20057b5038d7SDag-Erling Smørgrav } 20067b5038d7SDag-Erling Smørgrav } 20077b5038d7SDag-Erling Smørgrav 20087b5038d7SDag-Erling Smørgrav 20097b5038d7SDag-Erling Smørgrav /** 20107b5038d7SDag-Erling Smørgrav * Reset the ttl in the rrset with the orig_ttl from the sig 20117b5038d7SDag-Erling Smørgrav * and update owner name if it was wildcard 20127b5038d7SDag-Erling Smørgrav * Also canonicalizes the rrset. 20137b5038d7SDag-Erling Smørgrav * @param rrset: rrset to modify 20147b5038d7SDag-Erling Smørgrav * @param sig: signature to take TTL and wildcard values from 20157b5038d7SDag-Erling Smørgrav */ 20167b5038d7SDag-Erling Smørgrav static void 20177b5038d7SDag-Erling Smørgrav ldns_rrset_use_signature_ttl(ldns_rr_list* rrset_clone, ldns_rr* rrsig) 20187b5038d7SDag-Erling Smørgrav { 20197b5038d7SDag-Erling Smørgrav uint32_t orig_ttl; 20207b5038d7SDag-Erling Smørgrav uint16_t i; 20217b5038d7SDag-Erling Smørgrav uint8_t label_count; 20227b5038d7SDag-Erling Smørgrav ldns_rdf *wildcard_name; 20237b5038d7SDag-Erling Smørgrav ldns_rdf *wildcard_chopped; 20247b5038d7SDag-Erling Smørgrav ldns_rdf *wildcard_chopped_tmp; 20257b5038d7SDag-Erling Smørgrav 20267b5038d7SDag-Erling Smørgrav if ((rrsig == NULL) || ldns_rr_rd_count(rrsig) < 4) { 20277b5038d7SDag-Erling Smørgrav return; 20287b5038d7SDag-Erling Smørgrav } 20297b5038d7SDag-Erling Smørgrav 20307b5038d7SDag-Erling Smørgrav orig_ttl = ldns_rdf2native_int32( ldns_rr_rdf(rrsig, 3)); 20317b5038d7SDag-Erling Smørgrav label_count = ldns_rdf2native_int8(ldns_rr_rdf(rrsig, 2)); 20327b5038d7SDag-Erling Smørgrav 20337b5038d7SDag-Erling Smørgrav for(i = 0; i < ldns_rr_list_rr_count(rrset_clone); i++) { 20347b5038d7SDag-Erling Smørgrav if (label_count < 20357b5038d7SDag-Erling Smørgrav ldns_dname_label_count( 20367b5038d7SDag-Erling Smørgrav ldns_rr_owner(ldns_rr_list_rr(rrset_clone, i)))) { 20377b5038d7SDag-Erling Smørgrav (void) ldns_str2rdf_dname(&wildcard_name, "*"); 20387b5038d7SDag-Erling Smørgrav wildcard_chopped = ldns_rdf_clone(ldns_rr_owner( 20397b5038d7SDag-Erling Smørgrav ldns_rr_list_rr(rrset_clone, i))); 20407b5038d7SDag-Erling Smørgrav while (label_count < ldns_dname_label_count(wildcard_chopped)) { 20417b5038d7SDag-Erling Smørgrav wildcard_chopped_tmp = ldns_dname_left_chop( 20427b5038d7SDag-Erling Smørgrav wildcard_chopped); 20437b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(wildcard_chopped); 20447b5038d7SDag-Erling Smørgrav wildcard_chopped = wildcard_chopped_tmp; 20457b5038d7SDag-Erling Smørgrav } 20467b5038d7SDag-Erling Smørgrav (void) ldns_dname_cat(wildcard_name, wildcard_chopped); 20477b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(wildcard_chopped); 20487b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(ldns_rr_owner(ldns_rr_list_rr( 20497b5038d7SDag-Erling Smørgrav rrset_clone, i))); 20507b5038d7SDag-Erling Smørgrav ldns_rr_set_owner(ldns_rr_list_rr(rrset_clone, i), 20517b5038d7SDag-Erling Smørgrav wildcard_name); 20527b5038d7SDag-Erling Smørgrav } 20537b5038d7SDag-Erling Smørgrav ldns_rr_set_ttl(ldns_rr_list_rr(rrset_clone, i), orig_ttl); 20547b5038d7SDag-Erling Smørgrav /* convert to lowercase */ 20557b5038d7SDag-Erling Smørgrav ldns_rr2canonical(ldns_rr_list_rr(rrset_clone, i)); 20567b5038d7SDag-Erling Smørgrav } 20577b5038d7SDag-Erling Smørgrav } 20587b5038d7SDag-Erling Smørgrav 20597b5038d7SDag-Erling Smørgrav /** 20607b5038d7SDag-Erling Smørgrav * Make raw signature buffer out of rrsig 20617b5038d7SDag-Erling Smørgrav * @param rawsig_buf: raw signature buffer for result 20627b5038d7SDag-Erling Smørgrav * @param rrsig: signature to convert 20637b5038d7SDag-Erling Smørgrav * @return OK or more specific error. 20647b5038d7SDag-Erling Smørgrav */ 20657b5038d7SDag-Erling Smørgrav static ldns_status 20667b5038d7SDag-Erling Smørgrav ldns_rrsig2rawsig_buffer(ldns_buffer* rawsig_buf, ldns_rr* rrsig) 20677b5038d7SDag-Erling Smørgrav { 20687b5038d7SDag-Erling Smørgrav uint8_t sig_algo; 20697b5038d7SDag-Erling Smørgrav 20707b5038d7SDag-Erling Smørgrav if (rrsig == NULL) { 20717b5038d7SDag-Erling Smørgrav return LDNS_STATUS_CRYPTO_NO_RRSIG; 20727b5038d7SDag-Erling Smørgrav } 20737b5038d7SDag-Erling Smørgrav if (ldns_rr_rdf(rrsig, 1) == NULL) { 20747b5038d7SDag-Erling Smørgrav return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG; 20757b5038d7SDag-Erling Smørgrav } 20767b5038d7SDag-Erling Smørgrav sig_algo = ldns_rdf2native_int8(ldns_rr_rdf(rrsig, 1)); 20777b5038d7SDag-Erling Smørgrav /* check for known and implemented algo's now (otherwise 20787b5038d7SDag-Erling Smørgrav * the function could return a wrong error 20797b5038d7SDag-Erling Smørgrav */ 20807b5038d7SDag-Erling Smørgrav /* create a buffer with signature rdata */ 20817b5038d7SDag-Erling Smørgrav /* for some algorithms we need other data than for others... */ 20827b5038d7SDag-Erling Smørgrav /* (the DSA API wants DER encoding for instance) */ 20837b5038d7SDag-Erling Smørgrav 20847b5038d7SDag-Erling Smørgrav switch(sig_algo) { 20857b5038d7SDag-Erling Smørgrav case LDNS_RSAMD5: 20867b5038d7SDag-Erling Smørgrav case LDNS_RSASHA1: 20877b5038d7SDag-Erling Smørgrav case LDNS_RSASHA1_NSEC3: 20887b5038d7SDag-Erling Smørgrav #ifdef USE_SHA2 20897b5038d7SDag-Erling Smørgrav case LDNS_RSASHA256: 20907b5038d7SDag-Erling Smørgrav case LDNS_RSASHA512: 20917b5038d7SDag-Erling Smørgrav #endif 20927b5038d7SDag-Erling Smørgrav #ifdef USE_GOST 20937b5038d7SDag-Erling Smørgrav case LDNS_ECC_GOST: 20947b5038d7SDag-Erling Smørgrav #endif 20957b5038d7SDag-Erling Smørgrav if (ldns_rr_rdf(rrsig, 8) == NULL) { 20967b5038d7SDag-Erling Smørgrav return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG; 20977b5038d7SDag-Erling Smørgrav } 20987b5038d7SDag-Erling Smørgrav if (ldns_rdf2buffer_wire(rawsig_buf, ldns_rr_rdf(rrsig, 8)) 20997b5038d7SDag-Erling Smørgrav != LDNS_STATUS_OK) { 21007b5038d7SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR; 21017b5038d7SDag-Erling Smørgrav } 21027b5038d7SDag-Erling Smørgrav break; 21037b5038d7SDag-Erling Smørgrav case LDNS_DSA: 21047b5038d7SDag-Erling Smørgrav case LDNS_DSA_NSEC3: 21057b5038d7SDag-Erling Smørgrav /* EVP takes rfc2459 format, which is a tad longer than dns format */ 21067b5038d7SDag-Erling Smørgrav if (ldns_rr_rdf(rrsig, 8) == NULL) { 21077b5038d7SDag-Erling Smørgrav return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG; 21087b5038d7SDag-Erling Smørgrav } 21097b5038d7SDag-Erling Smørgrav if (ldns_convert_dsa_rrsig_rdf2asn1( 21107b5038d7SDag-Erling Smørgrav rawsig_buf, ldns_rr_rdf(rrsig, 8)) 21117b5038d7SDag-Erling Smørgrav != LDNS_STATUS_OK) { 21127b5038d7SDag-Erling Smørgrav /* 21137b5038d7SDag-Erling Smørgrav if (ldns_rdf2buffer_wire(rawsig_buf, 21147b5038d7SDag-Erling Smørgrav ldns_rr_rdf(rrsig, 8)) != LDNS_STATUS_OK) { 21157b5038d7SDag-Erling Smørgrav */ 21167b5038d7SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR; 21177b5038d7SDag-Erling Smørgrav } 21187b5038d7SDag-Erling Smørgrav break; 21197b5038d7SDag-Erling Smørgrav #ifdef USE_ECDSA 21207b5038d7SDag-Erling Smørgrav case LDNS_ECDSAP256SHA256: 21217b5038d7SDag-Erling Smørgrav case LDNS_ECDSAP384SHA384: 21227b5038d7SDag-Erling Smørgrav /* EVP produces an ASN prefix on the signature, which is 21237b5038d7SDag-Erling Smørgrav * not used in the DNS */ 21247b5038d7SDag-Erling Smørgrav if (ldns_rr_rdf(rrsig, 8) == NULL) { 21257b5038d7SDag-Erling Smørgrav return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG; 21267b5038d7SDag-Erling Smørgrav } 21277b5038d7SDag-Erling Smørgrav if (ldns_convert_ecdsa_rrsig_rdf2asn1( 21287b5038d7SDag-Erling Smørgrav rawsig_buf, ldns_rr_rdf(rrsig, 8)) 21297b5038d7SDag-Erling Smørgrav != LDNS_STATUS_OK) { 21307b5038d7SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR; 21317b5038d7SDag-Erling Smørgrav } 21327b5038d7SDag-Erling Smørgrav break; 21337b5038d7SDag-Erling Smørgrav #endif 21347b5038d7SDag-Erling Smørgrav case LDNS_DH: 21357b5038d7SDag-Erling Smørgrav case LDNS_ECC: 21367b5038d7SDag-Erling Smørgrav case LDNS_INDIRECT: 21377b5038d7SDag-Erling Smørgrav return LDNS_STATUS_CRYPTO_ALGO_NOT_IMPL; 21387b5038d7SDag-Erling Smørgrav default: 21397b5038d7SDag-Erling Smørgrav return LDNS_STATUS_CRYPTO_UNKNOWN_ALGO; 21407b5038d7SDag-Erling Smørgrav } 21417b5038d7SDag-Erling Smørgrav return LDNS_STATUS_OK; 21427b5038d7SDag-Erling Smørgrav } 21437b5038d7SDag-Erling Smørgrav 21447b5038d7SDag-Erling Smørgrav /** 21457b5038d7SDag-Erling Smørgrav * Check RRSIG timestamps against the given 'now' time. 21467b5038d7SDag-Erling Smørgrav * @param rrsig: signature to check. 21477b5038d7SDag-Erling Smørgrav * @param now: the current time in seconds epoch. 21487b5038d7SDag-Erling Smørgrav * @return status code LDNS_STATUS_OK if all is fine. 21497b5038d7SDag-Erling Smørgrav */ 21507b5038d7SDag-Erling Smørgrav static ldns_status 21517b5038d7SDag-Erling Smørgrav ldns_rrsig_check_timestamps(ldns_rr* rrsig, time_t now) 21527b5038d7SDag-Erling Smørgrav { 21537b5038d7SDag-Erling Smørgrav int32_t inception, expiration; 21547b5038d7SDag-Erling Smørgrav 21557b5038d7SDag-Erling Smørgrav /* check the signature time stamps */ 21567b5038d7SDag-Erling Smørgrav inception = (int32_t)ldns_rdf2native_time_t( 21577b5038d7SDag-Erling Smørgrav ldns_rr_rrsig_inception(rrsig)); 21587b5038d7SDag-Erling Smørgrav expiration = (int32_t)ldns_rdf2native_time_t( 21597b5038d7SDag-Erling Smørgrav ldns_rr_rrsig_expiration(rrsig)); 21607b5038d7SDag-Erling Smørgrav 21617b5038d7SDag-Erling Smørgrav if (expiration - inception < 0) { 21627b5038d7SDag-Erling Smørgrav /* bad sig, expiration before inception?? Tsssg */ 21637b5038d7SDag-Erling Smørgrav return LDNS_STATUS_CRYPTO_EXPIRATION_BEFORE_INCEPTION; 21647b5038d7SDag-Erling Smørgrav } 21657b5038d7SDag-Erling Smørgrav if (((int32_t) now) - inception < 0) { 21667b5038d7SDag-Erling Smørgrav /* bad sig, inception date has not yet come to pass */ 21677b5038d7SDag-Erling Smørgrav return LDNS_STATUS_CRYPTO_SIG_NOT_INCEPTED; 21687b5038d7SDag-Erling Smørgrav } 21697b5038d7SDag-Erling Smørgrav if (expiration - ((int32_t) now) < 0) { 21707b5038d7SDag-Erling Smørgrav /* bad sig, expiration date has passed */ 21717b5038d7SDag-Erling Smørgrav return LDNS_STATUS_CRYPTO_SIG_EXPIRED; 21727b5038d7SDag-Erling Smørgrav } 21737b5038d7SDag-Erling Smørgrav return LDNS_STATUS_OK; 21747b5038d7SDag-Erling Smørgrav } 21757b5038d7SDag-Erling Smørgrav 21767b5038d7SDag-Erling Smørgrav /** 21777b5038d7SDag-Erling Smørgrav * Prepare for verification. 21787b5038d7SDag-Erling Smørgrav * @param rawsig_buf: raw signature buffer made ready. 21797b5038d7SDag-Erling Smørgrav * @param verify_buf: data for verification buffer made ready. 21807b5038d7SDag-Erling Smørgrav * @param rrset_clone: made ready. 21817b5038d7SDag-Erling Smørgrav * @param rrsig: signature to prepare for. 21827b5038d7SDag-Erling Smørgrav * @return LDNS_STATUS_OK is all went well. Otherwise specific error. 21837b5038d7SDag-Erling Smørgrav */ 21847b5038d7SDag-Erling Smørgrav static ldns_status 21857b5038d7SDag-Erling Smørgrav ldns_prepare_for_verify(ldns_buffer* rawsig_buf, ldns_buffer* verify_buf, 21867b5038d7SDag-Erling Smørgrav ldns_rr_list* rrset_clone, ldns_rr* rrsig) 21877b5038d7SDag-Erling Smørgrav { 21887b5038d7SDag-Erling Smørgrav ldns_status result; 21897b5038d7SDag-Erling Smørgrav 21907b5038d7SDag-Erling Smørgrav /* canonicalize the sig */ 21917b5038d7SDag-Erling Smørgrav ldns_dname2canonical(ldns_rr_owner(rrsig)); 21927b5038d7SDag-Erling Smørgrav 21937b5038d7SDag-Erling Smørgrav /* check if the typecovered is equal to the type checked */ 21947b5038d7SDag-Erling Smørgrav if (ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rrsig)) != 21957b5038d7SDag-Erling Smørgrav ldns_rr_get_type(ldns_rr_list_rr(rrset_clone, 0))) 21967b5038d7SDag-Erling Smørgrav return LDNS_STATUS_CRYPTO_TYPE_COVERED_ERR; 21977b5038d7SDag-Erling Smørgrav 21987b5038d7SDag-Erling Smørgrav /* create a buffer with b64 signature rdata */ 21997b5038d7SDag-Erling Smørgrav result = ldns_rrsig2rawsig_buffer(rawsig_buf, rrsig); 22007b5038d7SDag-Erling Smørgrav if(result != LDNS_STATUS_OK) 22017b5038d7SDag-Erling Smørgrav return result; 22027b5038d7SDag-Erling Smørgrav 22037b5038d7SDag-Erling Smørgrav /* use TTL from signature. Use wildcard names for wildcards */ 22047b5038d7SDag-Erling Smørgrav /* also canonicalizes rrset_clone */ 22057b5038d7SDag-Erling Smørgrav ldns_rrset_use_signature_ttl(rrset_clone, rrsig); 22067b5038d7SDag-Erling Smørgrav 22077b5038d7SDag-Erling Smørgrav /* sort the rrset in canonical order */ 22087b5038d7SDag-Erling Smørgrav ldns_rr_list_sort(rrset_clone); 22097b5038d7SDag-Erling Smørgrav 22107b5038d7SDag-Erling Smørgrav /* put the signature rr (without the b64) to the verify_buf */ 22117b5038d7SDag-Erling Smørgrav if (ldns_rrsig2buffer_wire(verify_buf, rrsig) != LDNS_STATUS_OK) 22127b5038d7SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR; 22137b5038d7SDag-Erling Smørgrav 22147b5038d7SDag-Erling Smørgrav /* add the rrset in verify_buf */ 22157b5038d7SDag-Erling Smørgrav if(ldns_rr_list2buffer_wire(verify_buf, rrset_clone) 22167b5038d7SDag-Erling Smørgrav != LDNS_STATUS_OK) 22177b5038d7SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR; 22187b5038d7SDag-Erling Smørgrav 22197b5038d7SDag-Erling Smørgrav return LDNS_STATUS_OK; 22207b5038d7SDag-Erling Smørgrav } 22217b5038d7SDag-Erling Smørgrav 22227b5038d7SDag-Erling Smørgrav /** 22237b5038d7SDag-Erling Smørgrav * Check if a key matches a signature. 22247b5038d7SDag-Erling Smørgrav * Checks keytag, sigalgo and signature. 22257b5038d7SDag-Erling Smørgrav * @param rawsig_buf: raw signature buffer for verify 22267b5038d7SDag-Erling Smørgrav * @param verify_buf: raw data buffer for verify 22277b5038d7SDag-Erling Smørgrav * @param rrsig: the rrsig 22287b5038d7SDag-Erling Smørgrav * @param key: key to attempt. 22297b5038d7SDag-Erling Smørgrav * @return LDNS_STATUS_OK if OK, else some specific error. 22307b5038d7SDag-Erling Smørgrav */ 22317b5038d7SDag-Erling Smørgrav static ldns_status 22327b5038d7SDag-Erling Smørgrav ldns_verify_test_sig_key(ldns_buffer* rawsig_buf, ldns_buffer* verify_buf, 22337b5038d7SDag-Erling Smørgrav ldns_rr* rrsig, ldns_rr* key) 22347b5038d7SDag-Erling Smørgrav { 22357b5038d7SDag-Erling Smørgrav uint8_t sig_algo; 22367b5038d7SDag-Erling Smørgrav 22377b5038d7SDag-Erling Smørgrav if (rrsig == NULL) { 22387b5038d7SDag-Erling Smørgrav return LDNS_STATUS_CRYPTO_NO_RRSIG; 22397b5038d7SDag-Erling Smørgrav } 22407b5038d7SDag-Erling Smørgrav if (ldns_rr_rdf(rrsig, 1) == NULL) { 22417b5038d7SDag-Erling Smørgrav return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG; 22427b5038d7SDag-Erling Smørgrav } 22437b5038d7SDag-Erling Smørgrav sig_algo = ldns_rdf2native_int8(ldns_rr_rdf(rrsig, 1)); 22447b5038d7SDag-Erling Smørgrav 22457b5038d7SDag-Erling Smørgrav /* before anything, check if the keytags match */ 22467b5038d7SDag-Erling Smørgrav if (ldns_calc_keytag(key) 22477b5038d7SDag-Erling Smørgrav == 22487b5038d7SDag-Erling Smørgrav ldns_rdf2native_int16(ldns_rr_rrsig_keytag(rrsig)) 22497b5038d7SDag-Erling Smørgrav ) { 22507b5038d7SDag-Erling Smørgrav ldns_buffer* key_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN); 22517b5038d7SDag-Erling Smørgrav ldns_status result = LDNS_STATUS_ERR; 22527b5038d7SDag-Erling Smørgrav 22537b5038d7SDag-Erling Smørgrav /* put the key-data in a buffer, that's the third rdf, with 22547b5038d7SDag-Erling Smørgrav * the base64 encoded key data */ 22557b5038d7SDag-Erling Smørgrav if (ldns_rr_rdf(key, 3) == NULL) { 22567b5038d7SDag-Erling Smørgrav ldns_buffer_free(key_buf); 22577b5038d7SDag-Erling Smørgrav return LDNS_STATUS_MISSING_RDATA_FIELDS_KEY; 22587b5038d7SDag-Erling Smørgrav } 22597b5038d7SDag-Erling Smørgrav if (ldns_rdf2buffer_wire(key_buf, ldns_rr_rdf(key, 3)) 22607b5038d7SDag-Erling Smørgrav != LDNS_STATUS_OK) { 22617b5038d7SDag-Erling Smørgrav ldns_buffer_free(key_buf); 22627b5038d7SDag-Erling Smørgrav /* returning is bad might screw up 22637b5038d7SDag-Erling Smørgrav good keys later in the list 22647b5038d7SDag-Erling Smørgrav what to do? */ 22657b5038d7SDag-Erling Smørgrav return LDNS_STATUS_ERR; 22667b5038d7SDag-Erling Smørgrav } 22677b5038d7SDag-Erling Smørgrav 22687b5038d7SDag-Erling Smørgrav if (ldns_rr_rdf(key, 2) == NULL) { 22697b5038d7SDag-Erling Smørgrav result = LDNS_STATUS_MISSING_RDATA_FIELDS_KEY; 22707b5038d7SDag-Erling Smørgrav } 22717b5038d7SDag-Erling Smørgrav else if (sig_algo == ldns_rdf2native_int8( 22727b5038d7SDag-Erling Smørgrav ldns_rr_rdf(key, 2))) { 22737b5038d7SDag-Erling Smørgrav result = ldns_verify_rrsig_buffers(rawsig_buf, 22747b5038d7SDag-Erling Smørgrav verify_buf, key_buf, sig_algo); 22757b5038d7SDag-Erling Smørgrav } else { 22767b5038d7SDag-Erling Smørgrav /* No keys with the corresponding algorithm are found */ 22777b5038d7SDag-Erling Smørgrav result = LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY; 22787b5038d7SDag-Erling Smørgrav } 22797b5038d7SDag-Erling Smørgrav 22807b5038d7SDag-Erling Smørgrav ldns_buffer_free(key_buf); 22817b5038d7SDag-Erling Smørgrav return result; 22827b5038d7SDag-Erling Smørgrav } 22837b5038d7SDag-Erling Smørgrav else { 22847b5038d7SDag-Erling Smørgrav /* No keys with the corresponding keytag are found */ 22857b5038d7SDag-Erling Smørgrav return LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY; 22867b5038d7SDag-Erling Smørgrav } 22877b5038d7SDag-Erling Smørgrav } 22887b5038d7SDag-Erling Smørgrav 22897b5038d7SDag-Erling Smørgrav /* 22907b5038d7SDag-Erling Smørgrav * to verify: 22917b5038d7SDag-Erling Smørgrav * - create the wire fmt of the b64 key rdata 22927b5038d7SDag-Erling Smørgrav * - create the wire fmt of the sorted rrset 22937b5038d7SDag-Erling Smørgrav * - create the wire fmt of the b64 sig rdata 22947b5038d7SDag-Erling Smørgrav * - create the wire fmt of the sig without the b64 rdata 22957b5038d7SDag-Erling Smørgrav * - cat the sig data (without b64 rdata) to the rrset 22967b5038d7SDag-Erling Smørgrav * - verify the rrset+sig, with the b64 data and the b64 key data 22977b5038d7SDag-Erling Smørgrav */ 22987b5038d7SDag-Erling Smørgrav ldns_status 22997b5038d7SDag-Erling Smørgrav ldns_verify_rrsig_keylist_time( 23007b5038d7SDag-Erling Smørgrav ldns_rr_list *rrset, 23017b5038d7SDag-Erling Smørgrav ldns_rr *rrsig, 23027b5038d7SDag-Erling Smørgrav const ldns_rr_list *keys, 23037b5038d7SDag-Erling Smørgrav time_t check_time, 23047b5038d7SDag-Erling Smørgrav ldns_rr_list *good_keys) 23057b5038d7SDag-Erling Smørgrav { 23067b5038d7SDag-Erling Smørgrav ldns_status result; 23077b5038d7SDag-Erling Smørgrav ldns_rr_list *valid = ldns_rr_list_new(); 23087b5038d7SDag-Erling Smørgrav if (!valid) 23097b5038d7SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR; 23107b5038d7SDag-Erling Smørgrav 23117b5038d7SDag-Erling Smørgrav result = ldns_verify_rrsig_keylist_notime(rrset, rrsig, keys, valid); 23127b5038d7SDag-Erling Smørgrav if(result != LDNS_STATUS_OK) { 23137b5038d7SDag-Erling Smørgrav ldns_rr_list_free(valid); 23147b5038d7SDag-Erling Smørgrav return result; 23157b5038d7SDag-Erling Smørgrav } 23167b5038d7SDag-Erling Smørgrav 23177b5038d7SDag-Erling Smørgrav /* check timestamps last; its OK except time */ 23187b5038d7SDag-Erling Smørgrav result = ldns_rrsig_check_timestamps(rrsig, check_time); 23197b5038d7SDag-Erling Smørgrav if(result != LDNS_STATUS_OK) { 23207b5038d7SDag-Erling Smørgrav ldns_rr_list_free(valid); 23217b5038d7SDag-Erling Smørgrav return result; 23227b5038d7SDag-Erling Smørgrav } 23237b5038d7SDag-Erling Smørgrav 23247b5038d7SDag-Erling Smørgrav ldns_rr_list_cat(good_keys, valid); 23257b5038d7SDag-Erling Smørgrav ldns_rr_list_free(valid); 23267b5038d7SDag-Erling Smørgrav return LDNS_STATUS_OK; 23277b5038d7SDag-Erling Smørgrav } 23287b5038d7SDag-Erling Smørgrav 23297b5038d7SDag-Erling Smørgrav /* 23307b5038d7SDag-Erling Smørgrav * to verify: 23317b5038d7SDag-Erling Smørgrav * - create the wire fmt of the b64 key rdata 23327b5038d7SDag-Erling Smørgrav * - create the wire fmt of the sorted rrset 23337b5038d7SDag-Erling Smørgrav * - create the wire fmt of the b64 sig rdata 23347b5038d7SDag-Erling Smørgrav * - create the wire fmt of the sig without the b64 rdata 23357b5038d7SDag-Erling Smørgrav * - cat the sig data (without b64 rdata) to the rrset 23367b5038d7SDag-Erling Smørgrav * - verify the rrset+sig, with the b64 data and the b64 key data 23377b5038d7SDag-Erling Smørgrav */ 23387b5038d7SDag-Erling Smørgrav ldns_status 23397b5038d7SDag-Erling Smørgrav ldns_verify_rrsig_keylist(ldns_rr_list *rrset, 23407b5038d7SDag-Erling Smørgrav ldns_rr *rrsig, 23417b5038d7SDag-Erling Smørgrav const ldns_rr_list *keys, 23427b5038d7SDag-Erling Smørgrav ldns_rr_list *good_keys) 23437b5038d7SDag-Erling Smørgrav { 23447b5038d7SDag-Erling Smørgrav return ldns_verify_rrsig_keylist_time( 23457b5038d7SDag-Erling Smørgrav rrset, rrsig, keys, ldns_time(NULL), good_keys); 23467b5038d7SDag-Erling Smørgrav } 23477b5038d7SDag-Erling Smørgrav 23487b5038d7SDag-Erling Smørgrav ldns_status 23497b5038d7SDag-Erling Smørgrav ldns_verify_rrsig_keylist_notime(ldns_rr_list *rrset, 23507b5038d7SDag-Erling Smørgrav ldns_rr *rrsig, 23517b5038d7SDag-Erling Smørgrav const ldns_rr_list *keys, 23527b5038d7SDag-Erling Smørgrav ldns_rr_list *good_keys) 23537b5038d7SDag-Erling Smørgrav { 23547b5038d7SDag-Erling Smørgrav ldns_buffer *rawsig_buf; 23557b5038d7SDag-Erling Smørgrav ldns_buffer *verify_buf; 23567b5038d7SDag-Erling Smørgrav uint16_t i; 23577b5038d7SDag-Erling Smørgrav ldns_status result, status; 23587b5038d7SDag-Erling Smørgrav ldns_rr_list *rrset_clone; 23597b5038d7SDag-Erling Smørgrav ldns_rr_list *validkeys; 23607b5038d7SDag-Erling Smørgrav 23617b5038d7SDag-Erling Smørgrav if (!rrset) { 23627b5038d7SDag-Erling Smørgrav return LDNS_STATUS_ERR; 23637b5038d7SDag-Erling Smørgrav } 23647b5038d7SDag-Erling Smørgrav 23657b5038d7SDag-Erling Smørgrav validkeys = ldns_rr_list_new(); 23667b5038d7SDag-Erling Smørgrav if (!validkeys) { 23677b5038d7SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR; 23687b5038d7SDag-Erling Smørgrav } 23697b5038d7SDag-Erling Smørgrav 23707b5038d7SDag-Erling Smørgrav /* clone the rrset so that we can fiddle with it */ 23717b5038d7SDag-Erling Smørgrav rrset_clone = ldns_rr_list_clone(rrset); 23727b5038d7SDag-Erling Smørgrav 23737b5038d7SDag-Erling Smørgrav /* create the buffers which will certainly hold the raw data */ 23747b5038d7SDag-Erling Smørgrav rawsig_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN); 23757b5038d7SDag-Erling Smørgrav verify_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN); 23767b5038d7SDag-Erling Smørgrav 23777b5038d7SDag-Erling Smørgrav result = ldns_prepare_for_verify(rawsig_buf, verify_buf, 23787b5038d7SDag-Erling Smørgrav rrset_clone, rrsig); 23797b5038d7SDag-Erling Smørgrav if(result != LDNS_STATUS_OK) { 23807b5038d7SDag-Erling Smørgrav ldns_buffer_free(verify_buf); 23817b5038d7SDag-Erling Smørgrav ldns_buffer_free(rawsig_buf); 23827b5038d7SDag-Erling Smørgrav ldns_rr_list_deep_free(rrset_clone); 23837b5038d7SDag-Erling Smørgrav ldns_rr_list_free(validkeys); 23847b5038d7SDag-Erling Smørgrav return result; 23857b5038d7SDag-Erling Smørgrav } 23867b5038d7SDag-Erling Smørgrav 23877b5038d7SDag-Erling Smørgrav result = LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY; 23887b5038d7SDag-Erling Smørgrav for(i = 0; i < ldns_rr_list_rr_count(keys); i++) { 23897b5038d7SDag-Erling Smørgrav status = ldns_verify_test_sig_key(rawsig_buf, verify_buf, 23907b5038d7SDag-Erling Smørgrav rrsig, ldns_rr_list_rr(keys, i)); 23917b5038d7SDag-Erling Smørgrav if (status == LDNS_STATUS_OK) { 23927b5038d7SDag-Erling Smørgrav /* one of the keys has matched, don't break 23937b5038d7SDag-Erling Smørgrav * here, instead put the 'winning' key in 23947b5038d7SDag-Erling Smørgrav * the validkey list and return the list 23957b5038d7SDag-Erling Smørgrav * later */ 23967b5038d7SDag-Erling Smørgrav if (!ldns_rr_list_push_rr(validkeys, 23977b5038d7SDag-Erling Smørgrav ldns_rr_list_rr(keys,i))) { 23987b5038d7SDag-Erling Smørgrav /* couldn't push the key?? */ 23997b5038d7SDag-Erling Smørgrav ldns_buffer_free(rawsig_buf); 24007b5038d7SDag-Erling Smørgrav ldns_buffer_free(verify_buf); 24017b5038d7SDag-Erling Smørgrav ldns_rr_list_deep_free(rrset_clone); 24027b5038d7SDag-Erling Smørgrav ldns_rr_list_free(validkeys); 24037b5038d7SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR; 24047b5038d7SDag-Erling Smørgrav } 24057b5038d7SDag-Erling Smørgrav 24067b5038d7SDag-Erling Smørgrav result = status; 24077b5038d7SDag-Erling Smørgrav } 24087b5038d7SDag-Erling Smørgrav 24097b5038d7SDag-Erling Smørgrav if (result == LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY) { 24107b5038d7SDag-Erling Smørgrav result = status; 24117b5038d7SDag-Erling Smørgrav } 24127b5038d7SDag-Erling Smørgrav } 24137b5038d7SDag-Erling Smørgrav 24147b5038d7SDag-Erling Smørgrav /* no longer needed */ 24157b5038d7SDag-Erling Smørgrav ldns_rr_list_deep_free(rrset_clone); 24167b5038d7SDag-Erling Smørgrav ldns_buffer_free(rawsig_buf); 24177b5038d7SDag-Erling Smørgrav ldns_buffer_free(verify_buf); 24187b5038d7SDag-Erling Smørgrav 24197b5038d7SDag-Erling Smørgrav if (ldns_rr_list_rr_count(validkeys) == 0) { 24207b5038d7SDag-Erling Smørgrav /* no keys were added, return last error */ 24217b5038d7SDag-Erling Smørgrav ldns_rr_list_free(validkeys); 24227b5038d7SDag-Erling Smørgrav return result; 24237b5038d7SDag-Erling Smørgrav } 24247b5038d7SDag-Erling Smørgrav 24257b5038d7SDag-Erling Smørgrav /* do not check timestamps */ 24267b5038d7SDag-Erling Smørgrav 24277b5038d7SDag-Erling Smørgrav ldns_rr_list_cat(good_keys, validkeys); 24287b5038d7SDag-Erling Smørgrav ldns_rr_list_free(validkeys); 24297b5038d7SDag-Erling Smørgrav return LDNS_STATUS_OK; 24307b5038d7SDag-Erling Smørgrav } 24317b5038d7SDag-Erling Smørgrav 24327b5038d7SDag-Erling Smørgrav ldns_status 24337b5038d7SDag-Erling Smørgrav ldns_verify_rrsig_time( 24347b5038d7SDag-Erling Smørgrav ldns_rr_list *rrset, 24357b5038d7SDag-Erling Smørgrav ldns_rr *rrsig, 24367b5038d7SDag-Erling Smørgrav ldns_rr *key, 24377b5038d7SDag-Erling Smørgrav time_t check_time) 24387b5038d7SDag-Erling Smørgrav { 24397b5038d7SDag-Erling Smørgrav ldns_buffer *rawsig_buf; 24407b5038d7SDag-Erling Smørgrav ldns_buffer *verify_buf; 24417b5038d7SDag-Erling Smørgrav ldns_status result; 24427b5038d7SDag-Erling Smørgrav ldns_rr_list *rrset_clone; 24437b5038d7SDag-Erling Smørgrav 24447b5038d7SDag-Erling Smørgrav if (!rrset) { 24457b5038d7SDag-Erling Smørgrav return LDNS_STATUS_NO_DATA; 24467b5038d7SDag-Erling Smørgrav } 24477b5038d7SDag-Erling Smørgrav /* clone the rrset so that we can fiddle with it */ 24487b5038d7SDag-Erling Smørgrav rrset_clone = ldns_rr_list_clone(rrset); 24497b5038d7SDag-Erling Smørgrav /* create the buffers which will certainly hold the raw data */ 24507b5038d7SDag-Erling Smørgrav rawsig_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN); 24517b5038d7SDag-Erling Smørgrav verify_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN); 24527b5038d7SDag-Erling Smørgrav 24537b5038d7SDag-Erling Smørgrav result = ldns_prepare_for_verify(rawsig_buf, verify_buf, 24547b5038d7SDag-Erling Smørgrav rrset_clone, rrsig); 24557b5038d7SDag-Erling Smørgrav if(result != LDNS_STATUS_OK) { 24567b5038d7SDag-Erling Smørgrav ldns_rr_list_deep_free(rrset_clone); 24577b5038d7SDag-Erling Smørgrav ldns_buffer_free(rawsig_buf); 24587b5038d7SDag-Erling Smørgrav ldns_buffer_free(verify_buf); 24597b5038d7SDag-Erling Smørgrav return result; 24607b5038d7SDag-Erling Smørgrav } 24617b5038d7SDag-Erling Smørgrav result = ldns_verify_test_sig_key(rawsig_buf, verify_buf, 24627b5038d7SDag-Erling Smørgrav rrsig, key); 24637b5038d7SDag-Erling Smørgrav /* no longer needed */ 24647b5038d7SDag-Erling Smørgrav ldns_rr_list_deep_free(rrset_clone); 24657b5038d7SDag-Erling Smørgrav ldns_buffer_free(rawsig_buf); 24667b5038d7SDag-Erling Smørgrav ldns_buffer_free(verify_buf); 24677b5038d7SDag-Erling Smørgrav 24687b5038d7SDag-Erling Smørgrav /* check timestamp last, apart from time its OK */ 24697b5038d7SDag-Erling Smørgrav if(result == LDNS_STATUS_OK) 24707b5038d7SDag-Erling Smørgrav result = ldns_rrsig_check_timestamps(rrsig, check_time); 24717b5038d7SDag-Erling Smørgrav 24727b5038d7SDag-Erling Smørgrav return result; 24737b5038d7SDag-Erling Smørgrav } 24747b5038d7SDag-Erling Smørgrav 24757b5038d7SDag-Erling Smørgrav ldns_status 24767b5038d7SDag-Erling Smørgrav ldns_verify_rrsig(ldns_rr_list *rrset, ldns_rr *rrsig, ldns_rr *key) 24777b5038d7SDag-Erling Smørgrav { 24787b5038d7SDag-Erling Smørgrav return ldns_verify_rrsig_time(rrset, rrsig, key, ldns_time(NULL)); 24797b5038d7SDag-Erling Smørgrav } 24807b5038d7SDag-Erling Smørgrav 24817b5038d7SDag-Erling Smørgrav 24827b5038d7SDag-Erling Smørgrav ldns_status 24837b5038d7SDag-Erling Smørgrav ldns_verify_rrsig_evp(ldns_buffer *sig, 24847b5038d7SDag-Erling Smørgrav ldns_buffer *rrset, 24857b5038d7SDag-Erling Smørgrav EVP_PKEY *key, 24867b5038d7SDag-Erling Smørgrav const EVP_MD *digest_type) 24877b5038d7SDag-Erling Smørgrav { 24887b5038d7SDag-Erling Smørgrav return ldns_verify_rrsig_evp_raw( 24897b5038d7SDag-Erling Smørgrav (unsigned char*)ldns_buffer_begin(sig), 24907b5038d7SDag-Erling Smørgrav ldns_buffer_position(sig), 24917b5038d7SDag-Erling Smørgrav rrset, 24927b5038d7SDag-Erling Smørgrav key, 24937b5038d7SDag-Erling Smørgrav digest_type); 24947b5038d7SDag-Erling Smørgrav } 24957b5038d7SDag-Erling Smørgrav 24967b5038d7SDag-Erling Smørgrav ldns_status 24977b5038d7SDag-Erling Smørgrav ldns_verify_rrsig_evp_raw(unsigned char *sig, size_t siglen, 24987b5038d7SDag-Erling Smørgrav ldns_buffer *rrset, EVP_PKEY *key, const EVP_MD *digest_type) 24997b5038d7SDag-Erling Smørgrav { 25007b5038d7SDag-Erling Smørgrav EVP_MD_CTX ctx; 25017b5038d7SDag-Erling Smørgrav int res; 25027b5038d7SDag-Erling Smørgrav 25037b5038d7SDag-Erling Smørgrav EVP_MD_CTX_init(&ctx); 25047b5038d7SDag-Erling Smørgrav 25057b5038d7SDag-Erling Smørgrav EVP_VerifyInit(&ctx, digest_type); 25067b5038d7SDag-Erling Smørgrav EVP_VerifyUpdate(&ctx, 25077b5038d7SDag-Erling Smørgrav ldns_buffer_begin(rrset), 25087b5038d7SDag-Erling Smørgrav ldns_buffer_position(rrset)); 25097b5038d7SDag-Erling Smørgrav res = EVP_VerifyFinal(&ctx, sig, (unsigned int) siglen, key); 25107b5038d7SDag-Erling Smørgrav 25117b5038d7SDag-Erling Smørgrav EVP_MD_CTX_cleanup(&ctx); 25127b5038d7SDag-Erling Smørgrav 25137b5038d7SDag-Erling Smørgrav if (res == 1) { 25147b5038d7SDag-Erling Smørgrav return LDNS_STATUS_OK; 25157b5038d7SDag-Erling Smørgrav } else if (res == 0) { 25167b5038d7SDag-Erling Smørgrav return LDNS_STATUS_CRYPTO_BOGUS; 25177b5038d7SDag-Erling Smørgrav } 25187b5038d7SDag-Erling Smørgrav /* TODO how to communicate internal SSL error? 25197b5038d7SDag-Erling Smørgrav let caller use ssl's get_error() */ 25207b5038d7SDag-Erling Smørgrav return LDNS_STATUS_SSL_ERR; 25217b5038d7SDag-Erling Smørgrav } 25227b5038d7SDag-Erling Smørgrav 25237b5038d7SDag-Erling Smørgrav ldns_status 25247b5038d7SDag-Erling Smørgrav ldns_verify_rrsig_dsa(ldns_buffer *sig, ldns_buffer *rrset, ldns_buffer *key) 25257b5038d7SDag-Erling Smørgrav { 25267b5038d7SDag-Erling Smørgrav return ldns_verify_rrsig_dsa_raw( 25277b5038d7SDag-Erling Smørgrav (unsigned char*) ldns_buffer_begin(sig), 25287b5038d7SDag-Erling Smørgrav ldns_buffer_position(sig), 25297b5038d7SDag-Erling Smørgrav rrset, 25307b5038d7SDag-Erling Smørgrav (unsigned char*) ldns_buffer_begin(key), 25317b5038d7SDag-Erling Smørgrav ldns_buffer_position(key)); 25327b5038d7SDag-Erling Smørgrav } 25337b5038d7SDag-Erling Smørgrav 25347b5038d7SDag-Erling Smørgrav ldns_status 25357b5038d7SDag-Erling Smørgrav ldns_verify_rrsig_rsasha1(ldns_buffer *sig, ldns_buffer *rrset, ldns_buffer *key) 25367b5038d7SDag-Erling Smørgrav { 25377b5038d7SDag-Erling Smørgrav return ldns_verify_rrsig_rsasha1_raw( 25387b5038d7SDag-Erling Smørgrav (unsigned char*)ldns_buffer_begin(sig), 25397b5038d7SDag-Erling Smørgrav ldns_buffer_position(sig), 25407b5038d7SDag-Erling Smørgrav rrset, 25417b5038d7SDag-Erling Smørgrav (unsigned char*) ldns_buffer_begin(key), 25427b5038d7SDag-Erling Smørgrav ldns_buffer_position(key)); 25437b5038d7SDag-Erling Smørgrav } 25447b5038d7SDag-Erling Smørgrav 25457b5038d7SDag-Erling Smørgrav ldns_status 25467b5038d7SDag-Erling Smørgrav ldns_verify_rrsig_rsamd5(ldns_buffer *sig, ldns_buffer *rrset, ldns_buffer *key) 25477b5038d7SDag-Erling Smørgrav { 25487b5038d7SDag-Erling Smørgrav return ldns_verify_rrsig_rsamd5_raw( 25497b5038d7SDag-Erling Smørgrav (unsigned char*)ldns_buffer_begin(sig), 25507b5038d7SDag-Erling Smørgrav ldns_buffer_position(sig), 25517b5038d7SDag-Erling Smørgrav rrset, 25527b5038d7SDag-Erling Smørgrav (unsigned char*) ldns_buffer_begin(key), 25537b5038d7SDag-Erling Smørgrav ldns_buffer_position(key)); 25547b5038d7SDag-Erling Smørgrav } 25557b5038d7SDag-Erling Smørgrav 25567b5038d7SDag-Erling Smørgrav ldns_status 25577b5038d7SDag-Erling Smørgrav ldns_verify_rrsig_dsa_raw(unsigned char* sig, size_t siglen, 25587b5038d7SDag-Erling Smørgrav ldns_buffer* rrset, unsigned char* key, size_t keylen) 25597b5038d7SDag-Erling Smørgrav { 25607b5038d7SDag-Erling Smørgrav EVP_PKEY *evp_key; 25617b5038d7SDag-Erling Smørgrav ldns_status result; 25627b5038d7SDag-Erling Smørgrav 25637b5038d7SDag-Erling Smørgrav evp_key = EVP_PKEY_new(); 25647b5038d7SDag-Erling Smørgrav if (EVP_PKEY_assign_DSA(evp_key, ldns_key_buf2dsa_raw(key, keylen))) { 25657b5038d7SDag-Erling Smørgrav result = ldns_verify_rrsig_evp_raw(sig, 25667b5038d7SDag-Erling Smørgrav siglen, 25677b5038d7SDag-Erling Smørgrav rrset, 25687b5038d7SDag-Erling Smørgrav evp_key, 25697b5038d7SDag-Erling Smørgrav EVP_dss1()); 25707b5038d7SDag-Erling Smørgrav } else { 25717b5038d7SDag-Erling Smørgrav result = LDNS_STATUS_SSL_ERR; 25727b5038d7SDag-Erling Smørgrav } 25737b5038d7SDag-Erling Smørgrav EVP_PKEY_free(evp_key); 25747b5038d7SDag-Erling Smørgrav return result; 25757b5038d7SDag-Erling Smørgrav 25767b5038d7SDag-Erling Smørgrav } 25777b5038d7SDag-Erling Smørgrav 25787b5038d7SDag-Erling Smørgrav ldns_status 25797b5038d7SDag-Erling Smørgrav ldns_verify_rrsig_rsasha1_raw(unsigned char* sig, size_t siglen, 25807b5038d7SDag-Erling Smørgrav ldns_buffer* rrset, unsigned char* key, size_t keylen) 25817b5038d7SDag-Erling Smørgrav { 25827b5038d7SDag-Erling Smørgrav EVP_PKEY *evp_key; 25837b5038d7SDag-Erling Smørgrav ldns_status result; 25847b5038d7SDag-Erling Smørgrav 25857b5038d7SDag-Erling Smørgrav evp_key = EVP_PKEY_new(); 25867b5038d7SDag-Erling Smørgrav if (EVP_PKEY_assign_RSA(evp_key, ldns_key_buf2rsa_raw(key, keylen))) { 25877b5038d7SDag-Erling Smørgrav result = ldns_verify_rrsig_evp_raw(sig, 25887b5038d7SDag-Erling Smørgrav siglen, 25897b5038d7SDag-Erling Smørgrav rrset, 25907b5038d7SDag-Erling Smørgrav evp_key, 25917b5038d7SDag-Erling Smørgrav EVP_sha1()); 25927b5038d7SDag-Erling Smørgrav } else { 25937b5038d7SDag-Erling Smørgrav result = LDNS_STATUS_SSL_ERR; 25947b5038d7SDag-Erling Smørgrav } 25957b5038d7SDag-Erling Smørgrav EVP_PKEY_free(evp_key); 25967b5038d7SDag-Erling Smørgrav 25977b5038d7SDag-Erling Smørgrav return result; 25987b5038d7SDag-Erling Smørgrav } 25997b5038d7SDag-Erling Smørgrav 26007b5038d7SDag-Erling Smørgrav ldns_status 26017b5038d7SDag-Erling Smørgrav ldns_verify_rrsig_rsasha256_raw(unsigned char* sig, 26027b5038d7SDag-Erling Smørgrav size_t siglen, 26037b5038d7SDag-Erling Smørgrav ldns_buffer* rrset, 26047b5038d7SDag-Erling Smørgrav unsigned char* key, 26057b5038d7SDag-Erling Smørgrav size_t keylen) 26067b5038d7SDag-Erling Smørgrav { 26077b5038d7SDag-Erling Smørgrav #ifdef USE_SHA2 26087b5038d7SDag-Erling Smørgrav EVP_PKEY *evp_key; 26097b5038d7SDag-Erling Smørgrav ldns_status result; 26107b5038d7SDag-Erling Smørgrav 26117b5038d7SDag-Erling Smørgrav evp_key = EVP_PKEY_new(); 26127b5038d7SDag-Erling Smørgrav if (EVP_PKEY_assign_RSA(evp_key, ldns_key_buf2rsa_raw(key, keylen))) { 26137b5038d7SDag-Erling Smørgrav result = ldns_verify_rrsig_evp_raw(sig, 26147b5038d7SDag-Erling Smørgrav siglen, 26157b5038d7SDag-Erling Smørgrav rrset, 26167b5038d7SDag-Erling Smørgrav evp_key, 26177b5038d7SDag-Erling Smørgrav EVP_sha256()); 26187b5038d7SDag-Erling Smørgrav } else { 26197b5038d7SDag-Erling Smørgrav result = LDNS_STATUS_SSL_ERR; 26207b5038d7SDag-Erling Smørgrav } 26217b5038d7SDag-Erling Smørgrav EVP_PKEY_free(evp_key); 26227b5038d7SDag-Erling Smørgrav 26237b5038d7SDag-Erling Smørgrav return result; 26247b5038d7SDag-Erling Smørgrav #else 26257b5038d7SDag-Erling Smørgrav /* touch these to prevent compiler warnings */ 26267b5038d7SDag-Erling Smørgrav (void) sig; 26277b5038d7SDag-Erling Smørgrav (void) siglen; 26287b5038d7SDag-Erling Smørgrav (void) rrset; 26297b5038d7SDag-Erling Smørgrav (void) key; 26307b5038d7SDag-Erling Smørgrav (void) keylen; 26317b5038d7SDag-Erling Smørgrav return LDNS_STATUS_CRYPTO_UNKNOWN_ALGO; 26327b5038d7SDag-Erling Smørgrav #endif 26337b5038d7SDag-Erling Smørgrav } 26347b5038d7SDag-Erling Smørgrav 26357b5038d7SDag-Erling Smørgrav ldns_status 26367b5038d7SDag-Erling Smørgrav ldns_verify_rrsig_rsasha512_raw(unsigned char* sig, 26377b5038d7SDag-Erling Smørgrav size_t siglen, 26387b5038d7SDag-Erling Smørgrav ldns_buffer* rrset, 26397b5038d7SDag-Erling Smørgrav unsigned char* key, 26407b5038d7SDag-Erling Smørgrav size_t keylen) 26417b5038d7SDag-Erling Smørgrav { 26427b5038d7SDag-Erling Smørgrav #ifdef USE_SHA2 26437b5038d7SDag-Erling Smørgrav EVP_PKEY *evp_key; 26447b5038d7SDag-Erling Smørgrav ldns_status result; 26457b5038d7SDag-Erling Smørgrav 26467b5038d7SDag-Erling Smørgrav evp_key = EVP_PKEY_new(); 26477b5038d7SDag-Erling Smørgrav if (EVP_PKEY_assign_RSA(evp_key, ldns_key_buf2rsa_raw(key, keylen))) { 26487b5038d7SDag-Erling Smørgrav result = ldns_verify_rrsig_evp_raw(sig, 26497b5038d7SDag-Erling Smørgrav siglen, 26507b5038d7SDag-Erling Smørgrav rrset, 26517b5038d7SDag-Erling Smørgrav evp_key, 26527b5038d7SDag-Erling Smørgrav EVP_sha512()); 26537b5038d7SDag-Erling Smørgrav } else { 26547b5038d7SDag-Erling Smørgrav result = LDNS_STATUS_SSL_ERR; 26557b5038d7SDag-Erling Smørgrav } 26567b5038d7SDag-Erling Smørgrav EVP_PKEY_free(evp_key); 26577b5038d7SDag-Erling Smørgrav 26587b5038d7SDag-Erling Smørgrav return result; 26597b5038d7SDag-Erling Smørgrav #else 26607b5038d7SDag-Erling Smørgrav /* touch these to prevent compiler warnings */ 26617b5038d7SDag-Erling Smørgrav (void) sig; 26627b5038d7SDag-Erling Smørgrav (void) siglen; 26637b5038d7SDag-Erling Smørgrav (void) rrset; 26647b5038d7SDag-Erling Smørgrav (void) key; 26657b5038d7SDag-Erling Smørgrav (void) keylen; 26667b5038d7SDag-Erling Smørgrav return LDNS_STATUS_CRYPTO_UNKNOWN_ALGO; 26677b5038d7SDag-Erling Smørgrav #endif 26687b5038d7SDag-Erling Smørgrav } 26697b5038d7SDag-Erling Smørgrav 26707b5038d7SDag-Erling Smørgrav 26717b5038d7SDag-Erling Smørgrav ldns_status 26727b5038d7SDag-Erling Smørgrav ldns_verify_rrsig_rsamd5_raw(unsigned char* sig, 26737b5038d7SDag-Erling Smørgrav size_t siglen, 26747b5038d7SDag-Erling Smørgrav ldns_buffer* rrset, 26757b5038d7SDag-Erling Smørgrav unsigned char* key, 26767b5038d7SDag-Erling Smørgrav size_t keylen) 26777b5038d7SDag-Erling Smørgrav { 26787b5038d7SDag-Erling Smørgrav EVP_PKEY *evp_key; 26797b5038d7SDag-Erling Smørgrav ldns_status result; 26807b5038d7SDag-Erling Smørgrav 26817b5038d7SDag-Erling Smørgrav evp_key = EVP_PKEY_new(); 26827b5038d7SDag-Erling Smørgrav if (EVP_PKEY_assign_RSA(evp_key, ldns_key_buf2rsa_raw(key, keylen))) { 26837b5038d7SDag-Erling Smørgrav result = ldns_verify_rrsig_evp_raw(sig, 26847b5038d7SDag-Erling Smørgrav siglen, 26857b5038d7SDag-Erling Smørgrav rrset, 26867b5038d7SDag-Erling Smørgrav evp_key, 26877b5038d7SDag-Erling Smørgrav EVP_md5()); 26887b5038d7SDag-Erling Smørgrav } else { 26897b5038d7SDag-Erling Smørgrav result = LDNS_STATUS_SSL_ERR; 26907b5038d7SDag-Erling Smørgrav } 26917b5038d7SDag-Erling Smørgrav EVP_PKEY_free(evp_key); 26927b5038d7SDag-Erling Smørgrav 26937b5038d7SDag-Erling Smørgrav return result; 26947b5038d7SDag-Erling Smørgrav } 26957b5038d7SDag-Erling Smørgrav 26967b5038d7SDag-Erling Smørgrav #endif 2697