17b5038d7SDag-Erling Smørgrav /* 27b5038d7SDag-Erling Smørgrav * dnssec.c 37b5038d7SDag-Erling Smørgrav * 47b5038d7SDag-Erling Smørgrav * contains the cryptographic function needed for DNSSEC in ldns 57b5038d7SDag-Erling Smørgrav * The crypto library used is openssl 67b5038d7SDag-Erling Smørgrav * 77b5038d7SDag-Erling Smørgrav * (c) NLnet Labs, 2004-2008 87b5038d7SDag-Erling Smørgrav * 97b5038d7SDag-Erling Smørgrav * See the file LICENSE for the license 107b5038d7SDag-Erling Smørgrav */ 117b5038d7SDag-Erling Smørgrav 127b5038d7SDag-Erling Smørgrav #include <ldns/config.h> 137b5038d7SDag-Erling Smørgrav 147b5038d7SDag-Erling Smørgrav #include <ldns/ldns.h> 157b5038d7SDag-Erling Smørgrav #include <ldns/dnssec.h> 167b5038d7SDag-Erling Smørgrav 177b5038d7SDag-Erling Smørgrav #include <strings.h> 187b5038d7SDag-Erling Smørgrav #include <time.h> 197b5038d7SDag-Erling Smørgrav 207b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL 217b5038d7SDag-Erling Smørgrav #include <openssl/ssl.h> 227b5038d7SDag-Erling Smørgrav #include <openssl/evp.h> 237b5038d7SDag-Erling Smørgrav #include <openssl/rand.h> 247b5038d7SDag-Erling Smørgrav #include <openssl/err.h> 257b5038d7SDag-Erling Smørgrav #include <openssl/md5.h> 267b5038d7SDag-Erling Smørgrav #endif 277b5038d7SDag-Erling Smørgrav 287b5038d7SDag-Erling Smørgrav ldns_rr * 297b5038d7SDag-Erling Smørgrav ldns_dnssec_get_rrsig_for_name_and_type(const ldns_rdf *name, 307b5038d7SDag-Erling Smørgrav const ldns_rr_type type, 317b5038d7SDag-Erling Smørgrav const ldns_rr_list *rrs) 327b5038d7SDag-Erling Smørgrav { 337b5038d7SDag-Erling Smørgrav size_t i; 347b5038d7SDag-Erling Smørgrav ldns_rr *candidate; 357b5038d7SDag-Erling Smørgrav 367b5038d7SDag-Erling Smørgrav if (!name || !rrs) { 377b5038d7SDag-Erling Smørgrav return NULL; 387b5038d7SDag-Erling Smørgrav } 397b5038d7SDag-Erling Smørgrav 407b5038d7SDag-Erling Smørgrav for (i = 0; i < ldns_rr_list_rr_count(rrs); i++) { 417b5038d7SDag-Erling Smørgrav candidate = ldns_rr_list_rr(rrs, i); 427b5038d7SDag-Erling Smørgrav if (ldns_rr_get_type(candidate) == LDNS_RR_TYPE_RRSIG) { 437b5038d7SDag-Erling Smørgrav if (ldns_dname_compare(ldns_rr_owner(candidate), 447b5038d7SDag-Erling Smørgrav name) == 0 && 457b5038d7SDag-Erling Smørgrav ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(candidate)) 467b5038d7SDag-Erling Smørgrav == type 477b5038d7SDag-Erling Smørgrav ) { 487b5038d7SDag-Erling Smørgrav return candidate; 497b5038d7SDag-Erling Smørgrav } 507b5038d7SDag-Erling Smørgrav } 517b5038d7SDag-Erling Smørgrav } 527b5038d7SDag-Erling Smørgrav 537b5038d7SDag-Erling Smørgrav return NULL; 547b5038d7SDag-Erling Smørgrav } 557b5038d7SDag-Erling Smørgrav 567b5038d7SDag-Erling Smørgrav ldns_rr * 577b5038d7SDag-Erling Smørgrav ldns_dnssec_get_dnskey_for_rrsig(const ldns_rr *rrsig, 587b5038d7SDag-Erling Smørgrav const ldns_rr_list *rrs) 597b5038d7SDag-Erling Smørgrav { 607b5038d7SDag-Erling Smørgrav size_t i; 617b5038d7SDag-Erling Smørgrav ldns_rr *candidate; 627b5038d7SDag-Erling Smørgrav 637b5038d7SDag-Erling Smørgrav if (!rrsig || !rrs) { 647b5038d7SDag-Erling Smørgrav return NULL; 657b5038d7SDag-Erling Smørgrav } 667b5038d7SDag-Erling Smørgrav 677b5038d7SDag-Erling Smørgrav for (i = 0; i < ldns_rr_list_rr_count(rrs); i++) { 687b5038d7SDag-Erling Smørgrav candidate = ldns_rr_list_rr(rrs, i); 697b5038d7SDag-Erling Smørgrav if (ldns_rr_get_type(candidate) == LDNS_RR_TYPE_DNSKEY) { 707b5038d7SDag-Erling Smørgrav if (ldns_dname_compare(ldns_rr_owner(candidate), 717b5038d7SDag-Erling Smørgrav ldns_rr_rrsig_signame(rrsig)) == 0 && 727b5038d7SDag-Erling Smørgrav ldns_rdf2native_int16(ldns_rr_rrsig_keytag(rrsig)) == 737b5038d7SDag-Erling Smørgrav ldns_calc_keytag(candidate) 747b5038d7SDag-Erling Smørgrav ) { 757b5038d7SDag-Erling Smørgrav return candidate; 767b5038d7SDag-Erling Smørgrav } 777b5038d7SDag-Erling Smørgrav } 787b5038d7SDag-Erling Smørgrav } 797b5038d7SDag-Erling Smørgrav 807b5038d7SDag-Erling Smørgrav return NULL; 817b5038d7SDag-Erling Smørgrav } 827b5038d7SDag-Erling Smørgrav 837b5038d7SDag-Erling Smørgrav ldns_rdf * 847b5038d7SDag-Erling Smørgrav ldns_nsec_get_bitmap(ldns_rr *nsec) { 857b5038d7SDag-Erling Smørgrav if (ldns_rr_get_type(nsec) == LDNS_RR_TYPE_NSEC) { 867b5038d7SDag-Erling Smørgrav return ldns_rr_rdf(nsec, 1); 877b5038d7SDag-Erling Smørgrav } else if (ldns_rr_get_type(nsec) == LDNS_RR_TYPE_NSEC3) { 887b5038d7SDag-Erling Smørgrav return ldns_rr_rdf(nsec, 5); 897b5038d7SDag-Erling Smørgrav } else { 907b5038d7SDag-Erling Smørgrav return NULL; 917b5038d7SDag-Erling Smørgrav } 927b5038d7SDag-Erling Smørgrav } 937b5038d7SDag-Erling Smørgrav 947b5038d7SDag-Erling Smørgrav /*return the owner name of the closest encloser for name from the list of rrs */ 957b5038d7SDag-Erling Smørgrav /* this is NOT the hash, but the original name! */ 967b5038d7SDag-Erling Smørgrav ldns_rdf * 977b5038d7SDag-Erling Smørgrav ldns_dnssec_nsec3_closest_encloser(ldns_rdf *qname, 987b5038d7SDag-Erling Smørgrav ATTR_UNUSED(ldns_rr_type qtype), 997b5038d7SDag-Erling Smørgrav ldns_rr_list *nsec3s) 1007b5038d7SDag-Erling Smørgrav { 1017b5038d7SDag-Erling Smørgrav /* remember parameters, they must match */ 1027b5038d7SDag-Erling Smørgrav uint8_t algorithm; 1037b5038d7SDag-Erling Smørgrav uint32_t iterations; 1047b5038d7SDag-Erling Smørgrav uint8_t salt_length; 1057b5038d7SDag-Erling Smørgrav uint8_t *salt; 1067b5038d7SDag-Erling Smørgrav 1077b5038d7SDag-Erling Smørgrav ldns_rdf *sname, *hashed_sname, *tmp; 1087b5038d7SDag-Erling Smørgrav bool flag; 1097b5038d7SDag-Erling Smørgrav 1107b5038d7SDag-Erling Smørgrav bool exact_match_found; 1117b5038d7SDag-Erling Smørgrav bool in_range_found; 1127b5038d7SDag-Erling Smørgrav 1137b5038d7SDag-Erling Smørgrav ldns_status status; 1147b5038d7SDag-Erling Smørgrav ldns_rdf *zone_name; 1157b5038d7SDag-Erling Smørgrav 1167b5038d7SDag-Erling Smørgrav size_t nsec_i; 1177b5038d7SDag-Erling Smørgrav ldns_rr *nsec; 1187b5038d7SDag-Erling Smørgrav ldns_rdf *result = NULL; 1197b5038d7SDag-Erling Smørgrav 1207b5038d7SDag-Erling Smørgrav if (!qname || !nsec3s || ldns_rr_list_rr_count(nsec3s) < 1) { 1217b5038d7SDag-Erling Smørgrav return NULL; 1227b5038d7SDag-Erling Smørgrav } 1237b5038d7SDag-Erling Smørgrav 1247b5038d7SDag-Erling Smørgrav nsec = ldns_rr_list_rr(nsec3s, 0); 1257b5038d7SDag-Erling Smørgrav algorithm = ldns_nsec3_algorithm(nsec); 1267b5038d7SDag-Erling Smørgrav salt_length = ldns_nsec3_salt_length(nsec); 1277b5038d7SDag-Erling Smørgrav salt = ldns_nsec3_salt_data(nsec); 1287b5038d7SDag-Erling Smørgrav iterations = ldns_nsec3_iterations(nsec); 1297b5038d7SDag-Erling Smørgrav 1307b5038d7SDag-Erling Smørgrav sname = ldns_rdf_clone(qname); 1317b5038d7SDag-Erling Smørgrav 1327b5038d7SDag-Erling Smørgrav flag = false; 1337b5038d7SDag-Erling Smørgrav 1347b5038d7SDag-Erling Smørgrav zone_name = ldns_dname_left_chop(ldns_rr_owner(nsec)); 1357b5038d7SDag-Erling Smørgrav 1367b5038d7SDag-Erling Smørgrav /* algorithm from nsec3-07 8.3 */ 1377b5038d7SDag-Erling Smørgrav while (ldns_dname_label_count(sname) > 0) { 1387b5038d7SDag-Erling Smørgrav exact_match_found = false; 1397b5038d7SDag-Erling Smørgrav in_range_found = false; 1407b5038d7SDag-Erling Smørgrav 1417b5038d7SDag-Erling Smørgrav hashed_sname = ldns_nsec3_hash_name(sname, 1427b5038d7SDag-Erling Smørgrav algorithm, 1437b5038d7SDag-Erling Smørgrav iterations, 1447b5038d7SDag-Erling Smørgrav salt_length, 1457b5038d7SDag-Erling Smørgrav salt); 1467b5038d7SDag-Erling Smørgrav 1477b5038d7SDag-Erling Smørgrav status = ldns_dname_cat(hashed_sname, zone_name); 1487b5038d7SDag-Erling Smørgrav if(status != LDNS_STATUS_OK) { 1497b5038d7SDag-Erling Smørgrav LDNS_FREE(salt); 1507b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(zone_name); 1517b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(sname); 1527b5038d7SDag-Erling Smørgrav return NULL; 1537b5038d7SDag-Erling Smørgrav } 1547b5038d7SDag-Erling Smørgrav 1557b5038d7SDag-Erling Smørgrav for (nsec_i = 0; nsec_i < ldns_rr_list_rr_count(nsec3s); nsec_i++) { 1567b5038d7SDag-Erling Smørgrav nsec = ldns_rr_list_rr(nsec3s, nsec_i); 1577b5038d7SDag-Erling Smørgrav 1587b5038d7SDag-Erling Smørgrav /* check values of iterations etc! */ 1597b5038d7SDag-Erling Smørgrav 1607b5038d7SDag-Erling Smørgrav /* exact match? */ 1617b5038d7SDag-Erling Smørgrav if (ldns_dname_compare(ldns_rr_owner(nsec), hashed_sname) == 0) { 1627b5038d7SDag-Erling Smørgrav exact_match_found = true; 1637b5038d7SDag-Erling Smørgrav } else if (ldns_nsec_covers_name(nsec, hashed_sname)) { 1647b5038d7SDag-Erling Smørgrav in_range_found = true; 1657b5038d7SDag-Erling Smørgrav } 1667b5038d7SDag-Erling Smørgrav 1677b5038d7SDag-Erling Smørgrav } 1687b5038d7SDag-Erling Smørgrav if (!exact_match_found && in_range_found) { 1697b5038d7SDag-Erling Smørgrav flag = true; 1707b5038d7SDag-Erling Smørgrav } else if (exact_match_found && flag) { 1717b5038d7SDag-Erling Smørgrav result = ldns_rdf_clone(sname); 1727b5038d7SDag-Erling Smørgrav /* RFC 5155: 8.3. 2.** "The proof is complete" */ 1737b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(hashed_sname); 1747b5038d7SDag-Erling Smørgrav goto done; 1757b5038d7SDag-Erling Smørgrav } else if (exact_match_found && !flag) { 1767b5038d7SDag-Erling Smørgrav /* error! */ 1777b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(hashed_sname); 1787b5038d7SDag-Erling Smørgrav goto done; 1797b5038d7SDag-Erling Smørgrav } else { 1807b5038d7SDag-Erling Smørgrav flag = false; 1817b5038d7SDag-Erling Smørgrav } 1827b5038d7SDag-Erling Smørgrav 1837b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(hashed_sname); 1847b5038d7SDag-Erling Smørgrav tmp = sname; 1857b5038d7SDag-Erling Smørgrav sname = ldns_dname_left_chop(sname); 1867b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(tmp); 1877b5038d7SDag-Erling Smørgrav } 1887b5038d7SDag-Erling Smørgrav 1897b5038d7SDag-Erling Smørgrav done: 1907b5038d7SDag-Erling Smørgrav LDNS_FREE(salt); 1917b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(zone_name); 1927b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(sname); 1937b5038d7SDag-Erling Smørgrav 1947b5038d7SDag-Erling Smørgrav return result; 1957b5038d7SDag-Erling Smørgrav } 1967b5038d7SDag-Erling Smørgrav 1977b5038d7SDag-Erling Smørgrav bool 1987b5038d7SDag-Erling Smørgrav ldns_dnssec_pkt_has_rrsigs(const ldns_pkt *pkt) 1997b5038d7SDag-Erling Smørgrav { 2007b5038d7SDag-Erling Smørgrav size_t i; 2017b5038d7SDag-Erling Smørgrav for (i = 0; i < ldns_pkt_ancount(pkt); i++) { 2027b5038d7SDag-Erling Smørgrav if (ldns_rr_get_type(ldns_rr_list_rr(ldns_pkt_answer(pkt), i)) == 2037b5038d7SDag-Erling Smørgrav LDNS_RR_TYPE_RRSIG) { 2047b5038d7SDag-Erling Smørgrav return true; 2057b5038d7SDag-Erling Smørgrav } 2067b5038d7SDag-Erling Smørgrav } 2077b5038d7SDag-Erling Smørgrav for (i = 0; i < ldns_pkt_nscount(pkt); i++) { 2087b5038d7SDag-Erling Smørgrav if (ldns_rr_get_type(ldns_rr_list_rr(ldns_pkt_authority(pkt), i)) == 2097b5038d7SDag-Erling Smørgrav LDNS_RR_TYPE_RRSIG) { 2107b5038d7SDag-Erling Smørgrav return true; 2117b5038d7SDag-Erling Smørgrav } 2127b5038d7SDag-Erling Smørgrav } 2137b5038d7SDag-Erling Smørgrav return false; 2147b5038d7SDag-Erling Smørgrav } 2157b5038d7SDag-Erling Smørgrav 2167b5038d7SDag-Erling Smørgrav ldns_rr_list * 2177b5038d7SDag-Erling Smørgrav ldns_dnssec_pkt_get_rrsigs_for_name_and_type(const ldns_pkt *pkt, 2187b5038d7SDag-Erling Smørgrav ldns_rdf *name, 2197b5038d7SDag-Erling Smørgrav ldns_rr_type type) 2207b5038d7SDag-Erling Smørgrav { 2217b5038d7SDag-Erling Smørgrav uint16_t t_netorder; 2227b5038d7SDag-Erling Smørgrav ldns_rr_list *sigs; 2237b5038d7SDag-Erling Smørgrav ldns_rr_list *sigs_covered; 2247b5038d7SDag-Erling Smørgrav ldns_rdf *rdf_t; 2257b5038d7SDag-Erling Smørgrav 2267b5038d7SDag-Erling Smørgrav sigs = ldns_pkt_rr_list_by_name_and_type(pkt, 2277b5038d7SDag-Erling Smørgrav name, 2287b5038d7SDag-Erling Smørgrav LDNS_RR_TYPE_RRSIG, 2297b5038d7SDag-Erling Smørgrav LDNS_SECTION_ANY_NOQUESTION 2307b5038d7SDag-Erling Smørgrav ); 2317b5038d7SDag-Erling Smørgrav 2327b5038d7SDag-Erling Smørgrav t_netorder = htons(type); /* rdf are in network order! */ 2337b5038d7SDag-Erling Smørgrav rdf_t = ldns_rdf_new(LDNS_RDF_TYPE_TYPE, LDNS_RDF_SIZE_WORD, &t_netorder); 2347b5038d7SDag-Erling Smørgrav sigs_covered = ldns_rr_list_subtype_by_rdf(sigs, rdf_t, 0); 2357b5038d7SDag-Erling Smørgrav 2367b5038d7SDag-Erling Smørgrav ldns_rdf_free(rdf_t); 2377b5038d7SDag-Erling Smørgrav ldns_rr_list_deep_free(sigs); 2387b5038d7SDag-Erling Smørgrav 2397b5038d7SDag-Erling Smørgrav return sigs_covered; 2407b5038d7SDag-Erling Smørgrav 2417b5038d7SDag-Erling Smørgrav } 2427b5038d7SDag-Erling Smørgrav 2437b5038d7SDag-Erling Smørgrav ldns_rr_list * 2447b5038d7SDag-Erling Smørgrav ldns_dnssec_pkt_get_rrsigs_for_type(const ldns_pkt *pkt, ldns_rr_type type) 2457b5038d7SDag-Erling Smørgrav { 2467b5038d7SDag-Erling Smørgrav uint16_t t_netorder; 2477b5038d7SDag-Erling Smørgrav ldns_rr_list *sigs; 2487b5038d7SDag-Erling Smørgrav ldns_rr_list *sigs_covered; 2497b5038d7SDag-Erling Smørgrav ldns_rdf *rdf_t; 2507b5038d7SDag-Erling Smørgrav 2517b5038d7SDag-Erling Smørgrav sigs = ldns_pkt_rr_list_by_type(pkt, 2527b5038d7SDag-Erling Smørgrav LDNS_RR_TYPE_RRSIG, 2537b5038d7SDag-Erling Smørgrav LDNS_SECTION_ANY_NOQUESTION 2547b5038d7SDag-Erling Smørgrav ); 2557b5038d7SDag-Erling Smørgrav 2567b5038d7SDag-Erling Smørgrav t_netorder = htons(type); /* rdf are in network order! */ 2577b5038d7SDag-Erling Smørgrav rdf_t = ldns_rdf_new(LDNS_RDF_TYPE_TYPE, 2587b5038d7SDag-Erling Smørgrav 2, 2597b5038d7SDag-Erling Smørgrav &t_netorder); 2607b5038d7SDag-Erling Smørgrav sigs_covered = ldns_rr_list_subtype_by_rdf(sigs, rdf_t, 0); 2617b5038d7SDag-Erling Smørgrav 2627b5038d7SDag-Erling Smørgrav ldns_rdf_free(rdf_t); 2637b5038d7SDag-Erling Smørgrav ldns_rr_list_deep_free(sigs); 2647b5038d7SDag-Erling Smørgrav 2657b5038d7SDag-Erling Smørgrav return sigs_covered; 2667b5038d7SDag-Erling Smørgrav 2677b5038d7SDag-Erling Smørgrav } 2687b5038d7SDag-Erling Smørgrav 2697b5038d7SDag-Erling Smørgrav /* used only on the public key RR */ 2707b5038d7SDag-Erling Smørgrav uint16_t 2717b5038d7SDag-Erling Smørgrav ldns_calc_keytag(const ldns_rr *key) 2727b5038d7SDag-Erling Smørgrav { 2737b5038d7SDag-Erling Smørgrav uint16_t ac16; 2747b5038d7SDag-Erling Smørgrav ldns_buffer *keybuf; 2757b5038d7SDag-Erling Smørgrav size_t keysize; 2767b5038d7SDag-Erling Smørgrav 2777b5038d7SDag-Erling Smørgrav if (!key) { 2787b5038d7SDag-Erling Smørgrav return 0; 2797b5038d7SDag-Erling Smørgrav } 2807b5038d7SDag-Erling Smørgrav 2817b5038d7SDag-Erling Smørgrav if (ldns_rr_get_type(key) != LDNS_RR_TYPE_DNSKEY && 2827b5038d7SDag-Erling Smørgrav ldns_rr_get_type(key) != LDNS_RR_TYPE_KEY 2837b5038d7SDag-Erling Smørgrav ) { 2847b5038d7SDag-Erling Smørgrav return 0; 2857b5038d7SDag-Erling Smørgrav } 2867b5038d7SDag-Erling Smørgrav 2877b5038d7SDag-Erling Smørgrav /* rdata to buf - only put the rdata in a buffer */ 2887b5038d7SDag-Erling Smørgrav keybuf = ldns_buffer_new(LDNS_MIN_BUFLEN); /* grows */ 2897b5038d7SDag-Erling Smørgrav if (!keybuf) { 2907b5038d7SDag-Erling Smørgrav return 0; 2917b5038d7SDag-Erling Smørgrav } 2927b5038d7SDag-Erling Smørgrav (void)ldns_rr_rdata2buffer_wire(keybuf, key); 2937b5038d7SDag-Erling Smørgrav /* the current pos in the buffer is the keysize */ 2947b5038d7SDag-Erling Smørgrav keysize= ldns_buffer_position(keybuf); 2957b5038d7SDag-Erling Smørgrav 2967b5038d7SDag-Erling Smørgrav ac16 = ldns_calc_keytag_raw(ldns_buffer_begin(keybuf), keysize); 2977b5038d7SDag-Erling Smørgrav ldns_buffer_free(keybuf); 2987b5038d7SDag-Erling Smørgrav return ac16; 2997b5038d7SDag-Erling Smørgrav } 3007b5038d7SDag-Erling Smørgrav 3017b5038d7SDag-Erling Smørgrav uint16_t ldns_calc_keytag_raw(uint8_t* key, size_t keysize) 3027b5038d7SDag-Erling Smørgrav { 3037b5038d7SDag-Erling Smørgrav unsigned int i; 3047b5038d7SDag-Erling Smørgrav uint32_t ac32; 3057b5038d7SDag-Erling Smørgrav uint16_t ac16; 3067b5038d7SDag-Erling Smørgrav 3077b5038d7SDag-Erling Smørgrav if(keysize < 4) { 3087b5038d7SDag-Erling Smørgrav return 0; 3097b5038d7SDag-Erling Smørgrav } 3107b5038d7SDag-Erling Smørgrav /* look at the algorithm field, copied from 2535bis */ 3117b5038d7SDag-Erling Smørgrav if (key[3] == LDNS_RSAMD5) { 3127b5038d7SDag-Erling Smørgrav ac16 = 0; 3137b5038d7SDag-Erling Smørgrav if (keysize > 4) { 3147b5038d7SDag-Erling Smørgrav memmove(&ac16, key + keysize - 3, 2); 3157b5038d7SDag-Erling Smørgrav } 3167b5038d7SDag-Erling Smørgrav ac16 = ntohs(ac16); 3177b5038d7SDag-Erling Smørgrav return (uint16_t) ac16; 3187b5038d7SDag-Erling Smørgrav } else { 3197b5038d7SDag-Erling Smørgrav ac32 = 0; 3207b5038d7SDag-Erling Smørgrav for (i = 0; (size_t)i < keysize; ++i) { 3217b5038d7SDag-Erling Smørgrav ac32 += (i & 1) ? key[i] : key[i] << 8; 3227b5038d7SDag-Erling Smørgrav } 3237b5038d7SDag-Erling Smørgrav ac32 += (ac32 >> 16) & 0xFFFF; 3247b5038d7SDag-Erling Smørgrav return (uint16_t) (ac32 & 0xFFFF); 3257b5038d7SDag-Erling Smørgrav } 3267b5038d7SDag-Erling Smørgrav } 3277b5038d7SDag-Erling Smørgrav 3287b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL 3297b5038d7SDag-Erling Smørgrav DSA * 3307b5038d7SDag-Erling Smørgrav ldns_key_buf2dsa(ldns_buffer *key) 3317b5038d7SDag-Erling Smørgrav { 3327b5038d7SDag-Erling Smørgrav return ldns_key_buf2dsa_raw((unsigned char*)ldns_buffer_begin(key), 3337b5038d7SDag-Erling Smørgrav ldns_buffer_position(key)); 3347b5038d7SDag-Erling Smørgrav } 3357b5038d7SDag-Erling Smørgrav 3367b5038d7SDag-Erling Smørgrav DSA * 3377b5038d7SDag-Erling Smørgrav ldns_key_buf2dsa_raw(unsigned char* key, size_t len) 3387b5038d7SDag-Erling Smørgrav { 3397b5038d7SDag-Erling Smørgrav uint8_t T; 3407b5038d7SDag-Erling Smørgrav uint16_t length; 3417b5038d7SDag-Erling Smørgrav uint16_t offset; 3427b5038d7SDag-Erling Smørgrav DSA *dsa; 3437b5038d7SDag-Erling Smørgrav BIGNUM *Q; BIGNUM *P; 3447b5038d7SDag-Erling Smørgrav BIGNUM *G; BIGNUM *Y; 3457b5038d7SDag-Erling Smørgrav 3467b5038d7SDag-Erling Smørgrav if(len == 0) 3477b5038d7SDag-Erling Smørgrav return NULL; 3487b5038d7SDag-Erling Smørgrav T = (uint8_t)key[0]; 3497b5038d7SDag-Erling Smørgrav length = (64 + T * 8); 3507b5038d7SDag-Erling Smørgrav offset = 1; 3517b5038d7SDag-Erling Smørgrav 3527b5038d7SDag-Erling Smørgrav if (T > 8) { 3537b5038d7SDag-Erling Smørgrav return NULL; 3547b5038d7SDag-Erling Smørgrav } 3557b5038d7SDag-Erling Smørgrav if(len < (size_t)1 + SHA_DIGEST_LENGTH + 3*length) 3567b5038d7SDag-Erling Smørgrav return NULL; 3577b5038d7SDag-Erling Smørgrav 3587b5038d7SDag-Erling Smørgrav Q = BN_bin2bn(key+offset, SHA_DIGEST_LENGTH, NULL); 3597b5038d7SDag-Erling Smørgrav offset += SHA_DIGEST_LENGTH; 3607b5038d7SDag-Erling Smørgrav 3617b5038d7SDag-Erling Smørgrav P = BN_bin2bn(key+offset, (int)length, NULL); 3627b5038d7SDag-Erling Smørgrav offset += length; 3637b5038d7SDag-Erling Smørgrav 3647b5038d7SDag-Erling Smørgrav G = BN_bin2bn(key+offset, (int)length, NULL); 3657b5038d7SDag-Erling Smørgrav offset += length; 3667b5038d7SDag-Erling Smørgrav 3677b5038d7SDag-Erling Smørgrav Y = BN_bin2bn(key+offset, (int)length, NULL); 3687b5038d7SDag-Erling Smørgrav offset += length; 3697b5038d7SDag-Erling Smørgrav 3707b5038d7SDag-Erling Smørgrav /* create the key and set its properties */ 3717b5038d7SDag-Erling Smørgrav if(!Q || !P || !G || !Y || !(dsa = DSA_new())) { 3727b5038d7SDag-Erling Smørgrav BN_free(Q); 3737b5038d7SDag-Erling Smørgrav BN_free(P); 3747b5038d7SDag-Erling Smørgrav BN_free(G); 3757b5038d7SDag-Erling Smørgrav BN_free(Y); 3767b5038d7SDag-Erling Smørgrav return NULL; 3777b5038d7SDag-Erling Smørgrav } 3787b5038d7SDag-Erling Smørgrav #ifndef S_SPLINT_S 3797b5038d7SDag-Erling Smørgrav dsa->p = P; 3807b5038d7SDag-Erling Smørgrav dsa->q = Q; 3817b5038d7SDag-Erling Smørgrav dsa->g = G; 3827b5038d7SDag-Erling Smørgrav dsa->pub_key = Y; 3837b5038d7SDag-Erling Smørgrav #endif /* splint */ 3847b5038d7SDag-Erling Smørgrav 3857b5038d7SDag-Erling Smørgrav return dsa; 3867b5038d7SDag-Erling Smørgrav } 3877b5038d7SDag-Erling Smørgrav 3887b5038d7SDag-Erling Smørgrav RSA * 3897b5038d7SDag-Erling Smørgrav ldns_key_buf2rsa(ldns_buffer *key) 3907b5038d7SDag-Erling Smørgrav { 3917b5038d7SDag-Erling Smørgrav return ldns_key_buf2rsa_raw((unsigned char*)ldns_buffer_begin(key), 3927b5038d7SDag-Erling Smørgrav ldns_buffer_position(key)); 3937b5038d7SDag-Erling Smørgrav } 3947b5038d7SDag-Erling Smørgrav 3957b5038d7SDag-Erling Smørgrav RSA * 3967b5038d7SDag-Erling Smørgrav ldns_key_buf2rsa_raw(unsigned char* key, size_t len) 3977b5038d7SDag-Erling Smørgrav { 3987b5038d7SDag-Erling Smørgrav uint16_t offset; 3997b5038d7SDag-Erling Smørgrav uint16_t exp; 4007b5038d7SDag-Erling Smørgrav uint16_t int16; 4017b5038d7SDag-Erling Smørgrav RSA *rsa; 4027b5038d7SDag-Erling Smørgrav BIGNUM *modulus; 4037b5038d7SDag-Erling Smørgrav BIGNUM *exponent; 4047b5038d7SDag-Erling Smørgrav 4057b5038d7SDag-Erling Smørgrav if (len == 0) 4067b5038d7SDag-Erling Smørgrav return NULL; 4077b5038d7SDag-Erling Smørgrav if (key[0] == 0) { 4087b5038d7SDag-Erling Smørgrav if(len < 3) 4097b5038d7SDag-Erling Smørgrav return NULL; 4107b5038d7SDag-Erling Smørgrav /* need some smart comment here XXX*/ 4117b5038d7SDag-Erling Smørgrav /* the exponent is too large so it's places 4127b5038d7SDag-Erling Smørgrav * futher...???? */ 4137b5038d7SDag-Erling Smørgrav memmove(&int16, key+1, 2); 4147b5038d7SDag-Erling Smørgrav exp = ntohs(int16); 4157b5038d7SDag-Erling Smørgrav offset = 3; 4167b5038d7SDag-Erling Smørgrav } else { 4177b5038d7SDag-Erling Smørgrav exp = key[0]; 4187b5038d7SDag-Erling Smørgrav offset = 1; 4197b5038d7SDag-Erling Smørgrav } 4207b5038d7SDag-Erling Smørgrav 4217b5038d7SDag-Erling Smørgrav /* key length at least one */ 4227b5038d7SDag-Erling Smørgrav if(len < (size_t)offset + exp + 1) 4237b5038d7SDag-Erling Smørgrav return NULL; 4247b5038d7SDag-Erling Smørgrav 4257b5038d7SDag-Erling Smørgrav /* Exponent */ 4267b5038d7SDag-Erling Smørgrav exponent = BN_new(); 4277b5038d7SDag-Erling Smørgrav if(!exponent) return NULL; 4287b5038d7SDag-Erling Smørgrav (void) BN_bin2bn(key+offset, (int)exp, exponent); 4297b5038d7SDag-Erling Smørgrav offset += exp; 4307b5038d7SDag-Erling Smørgrav 4317b5038d7SDag-Erling Smørgrav /* Modulus */ 4327b5038d7SDag-Erling Smørgrav modulus = BN_new(); 4337b5038d7SDag-Erling Smørgrav if(!modulus) { 4347b5038d7SDag-Erling Smørgrav BN_free(exponent); 4357b5038d7SDag-Erling Smørgrav return NULL; 4367b5038d7SDag-Erling Smørgrav } 4377b5038d7SDag-Erling Smørgrav /* length of the buffer must match the key length! */ 4387b5038d7SDag-Erling Smørgrav (void) BN_bin2bn(key+offset, (int)(len - offset), modulus); 4397b5038d7SDag-Erling Smørgrav 4407b5038d7SDag-Erling Smørgrav rsa = RSA_new(); 4417b5038d7SDag-Erling Smørgrav if(!rsa) { 4427b5038d7SDag-Erling Smørgrav BN_free(exponent); 4437b5038d7SDag-Erling Smørgrav BN_free(modulus); 4447b5038d7SDag-Erling Smørgrav return NULL; 4457b5038d7SDag-Erling Smørgrav } 4467b5038d7SDag-Erling Smørgrav #ifndef S_SPLINT_S 4477b5038d7SDag-Erling Smørgrav rsa->n = modulus; 4487b5038d7SDag-Erling Smørgrav rsa->e = exponent; 4497b5038d7SDag-Erling Smørgrav #endif /* splint */ 4507b5038d7SDag-Erling Smørgrav 4517b5038d7SDag-Erling Smørgrav return rsa; 4527b5038d7SDag-Erling Smørgrav } 4537b5038d7SDag-Erling Smørgrav 4547b5038d7SDag-Erling Smørgrav int 4557b5038d7SDag-Erling Smørgrav ldns_digest_evp(unsigned char* data, unsigned int len, unsigned char* dest, 4567b5038d7SDag-Erling Smørgrav const EVP_MD* md) 4577b5038d7SDag-Erling Smørgrav { 4587b5038d7SDag-Erling Smørgrav EVP_MD_CTX* ctx; 4597b5038d7SDag-Erling Smørgrav ctx = EVP_MD_CTX_create(); 4607b5038d7SDag-Erling Smørgrav if(!ctx) 4617b5038d7SDag-Erling Smørgrav return false; 4627b5038d7SDag-Erling Smørgrav if(!EVP_DigestInit_ex(ctx, md, NULL) || 4637b5038d7SDag-Erling Smørgrav !EVP_DigestUpdate(ctx, data, len) || 4647b5038d7SDag-Erling Smørgrav !EVP_DigestFinal_ex(ctx, dest, NULL)) { 4657b5038d7SDag-Erling Smørgrav EVP_MD_CTX_destroy(ctx); 4667b5038d7SDag-Erling Smørgrav return false; 4677b5038d7SDag-Erling Smørgrav } 4687b5038d7SDag-Erling Smørgrav EVP_MD_CTX_destroy(ctx); 4697b5038d7SDag-Erling Smørgrav return true; 4707b5038d7SDag-Erling Smørgrav } 4717b5038d7SDag-Erling Smørgrav #endif /* HAVE_SSL */ 4727b5038d7SDag-Erling Smørgrav 4737b5038d7SDag-Erling Smørgrav ldns_rr * 4747b5038d7SDag-Erling Smørgrav ldns_key_rr2ds(const ldns_rr *key, ldns_hash h) 4757b5038d7SDag-Erling Smørgrav { 4767b5038d7SDag-Erling Smørgrav ldns_rdf *tmp; 4777b5038d7SDag-Erling Smørgrav ldns_rr *ds; 4787b5038d7SDag-Erling Smørgrav uint16_t keytag; 4797b5038d7SDag-Erling Smørgrav uint8_t sha1hash; 4807b5038d7SDag-Erling Smørgrav uint8_t *digest; 4817b5038d7SDag-Erling Smørgrav ldns_buffer *data_buf; 4827b5038d7SDag-Erling Smørgrav #ifdef USE_GOST 4837b5038d7SDag-Erling Smørgrav const EVP_MD* md = NULL; 4847b5038d7SDag-Erling Smørgrav #endif 4857b5038d7SDag-Erling Smørgrav 4867b5038d7SDag-Erling Smørgrav if (ldns_rr_get_type(key) != LDNS_RR_TYPE_DNSKEY) { 4877b5038d7SDag-Erling Smørgrav return NULL; 4887b5038d7SDag-Erling Smørgrav } 4897b5038d7SDag-Erling Smørgrav 4907b5038d7SDag-Erling Smørgrav ds = ldns_rr_new(); 4917b5038d7SDag-Erling Smørgrav if (!ds) { 4927b5038d7SDag-Erling Smørgrav return NULL; 4937b5038d7SDag-Erling Smørgrav } 4947b5038d7SDag-Erling Smørgrav ldns_rr_set_type(ds, LDNS_RR_TYPE_DS); 4957b5038d7SDag-Erling Smørgrav ldns_rr_set_owner(ds, ldns_rdf_clone( 4967b5038d7SDag-Erling Smørgrav ldns_rr_owner(key))); 4977b5038d7SDag-Erling Smørgrav ldns_rr_set_ttl(ds, ldns_rr_ttl(key)); 4987b5038d7SDag-Erling Smørgrav ldns_rr_set_class(ds, ldns_rr_get_class(key)); 4997b5038d7SDag-Erling Smørgrav 5007b5038d7SDag-Erling Smørgrav switch(h) { 5017b5038d7SDag-Erling Smørgrav default: 5027b5038d7SDag-Erling Smørgrav case LDNS_SHA1: 5037b5038d7SDag-Erling Smørgrav digest = LDNS_XMALLOC(uint8_t, LDNS_SHA1_DIGEST_LENGTH); 5047b5038d7SDag-Erling Smørgrav if (!digest) { 5057b5038d7SDag-Erling Smørgrav ldns_rr_free(ds); 5067b5038d7SDag-Erling Smørgrav return NULL; 5077b5038d7SDag-Erling Smørgrav } 5087b5038d7SDag-Erling Smørgrav break; 5097b5038d7SDag-Erling Smørgrav case LDNS_SHA256: 5107b5038d7SDag-Erling Smørgrav digest = LDNS_XMALLOC(uint8_t, LDNS_SHA256_DIGEST_LENGTH); 5117b5038d7SDag-Erling Smørgrav if (!digest) { 5127b5038d7SDag-Erling Smørgrav ldns_rr_free(ds); 5137b5038d7SDag-Erling Smørgrav return NULL; 5147b5038d7SDag-Erling Smørgrav } 5157b5038d7SDag-Erling Smørgrav break; 5167b5038d7SDag-Erling Smørgrav case LDNS_HASH_GOST: 5177b5038d7SDag-Erling Smørgrav #ifdef USE_GOST 5187b5038d7SDag-Erling Smørgrav (void)ldns_key_EVP_load_gost_id(); 5197b5038d7SDag-Erling Smørgrav md = EVP_get_digestbyname("md_gost94"); 5207b5038d7SDag-Erling Smørgrav if(!md) { 5217b5038d7SDag-Erling Smørgrav ldns_rr_free(ds); 5227b5038d7SDag-Erling Smørgrav return NULL; 5237b5038d7SDag-Erling Smørgrav } 5247b5038d7SDag-Erling Smørgrav digest = LDNS_XMALLOC(uint8_t, EVP_MD_size(md)); 5257b5038d7SDag-Erling Smørgrav if (!digest) { 5267b5038d7SDag-Erling Smørgrav ldns_rr_free(ds); 5277b5038d7SDag-Erling Smørgrav return NULL; 5287b5038d7SDag-Erling Smørgrav } 5297b5038d7SDag-Erling Smørgrav break; 5307b5038d7SDag-Erling Smørgrav #else 5317b5038d7SDag-Erling Smørgrav /* not implemented */ 5327b5038d7SDag-Erling Smørgrav ldns_rr_free(ds); 5337b5038d7SDag-Erling Smørgrav return NULL; 5347b5038d7SDag-Erling Smørgrav #endif 5357b5038d7SDag-Erling Smørgrav case LDNS_SHA384: 5367b5038d7SDag-Erling Smørgrav #ifdef USE_ECDSA 5377b5038d7SDag-Erling Smørgrav digest = LDNS_XMALLOC(uint8_t, SHA384_DIGEST_LENGTH); 5387b5038d7SDag-Erling Smørgrav if (!digest) { 5397b5038d7SDag-Erling Smørgrav ldns_rr_free(ds); 5407b5038d7SDag-Erling Smørgrav return NULL; 5417b5038d7SDag-Erling Smørgrav } 5427b5038d7SDag-Erling Smørgrav break; 5437b5038d7SDag-Erling Smørgrav #else 5447b5038d7SDag-Erling Smørgrav /* not implemented */ 5457b5038d7SDag-Erling Smørgrav ldns_rr_free(ds); 5467b5038d7SDag-Erling Smørgrav return NULL; 5477b5038d7SDag-Erling Smørgrav #endif 5487b5038d7SDag-Erling Smørgrav } 5497b5038d7SDag-Erling Smørgrav 5507b5038d7SDag-Erling Smørgrav data_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN); 5517b5038d7SDag-Erling Smørgrav if (!data_buf) { 5527b5038d7SDag-Erling Smørgrav LDNS_FREE(digest); 5537b5038d7SDag-Erling Smørgrav ldns_rr_free(ds); 5547b5038d7SDag-Erling Smørgrav return NULL; 5557b5038d7SDag-Erling Smørgrav } 5567b5038d7SDag-Erling Smørgrav 5577b5038d7SDag-Erling Smørgrav /* keytag */ 5587b5038d7SDag-Erling Smørgrav keytag = htons(ldns_calc_keytag((ldns_rr*)key)); 5597b5038d7SDag-Erling Smørgrav tmp = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_INT16, 5607b5038d7SDag-Erling Smørgrav sizeof(uint16_t), 5617b5038d7SDag-Erling Smørgrav &keytag); 5627b5038d7SDag-Erling Smørgrav ldns_rr_push_rdf(ds, tmp); 5637b5038d7SDag-Erling Smørgrav 5647b5038d7SDag-Erling Smørgrav /* copy the algorithm field */ 5657b5038d7SDag-Erling Smørgrav if ((tmp = ldns_rr_rdf(key, 2)) == NULL) { 5667b5038d7SDag-Erling Smørgrav LDNS_FREE(digest); 5677b5038d7SDag-Erling Smørgrav ldns_buffer_free(data_buf); 5687b5038d7SDag-Erling Smørgrav ldns_rr_free(ds); 5697b5038d7SDag-Erling Smørgrav return NULL; 5707b5038d7SDag-Erling Smørgrav } else { 5717b5038d7SDag-Erling Smørgrav ldns_rr_push_rdf(ds, ldns_rdf_clone( tmp )); 5727b5038d7SDag-Erling Smørgrav } 5737b5038d7SDag-Erling Smørgrav 5747b5038d7SDag-Erling Smørgrav /* digest hash type */ 5757b5038d7SDag-Erling Smørgrav sha1hash = (uint8_t)h; 5767b5038d7SDag-Erling Smørgrav tmp = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_INT8, 5777b5038d7SDag-Erling Smørgrav sizeof(uint8_t), 5787b5038d7SDag-Erling Smørgrav &sha1hash); 5797b5038d7SDag-Erling Smørgrav ldns_rr_push_rdf(ds, tmp); 5807b5038d7SDag-Erling Smørgrav 5817b5038d7SDag-Erling Smørgrav /* digest */ 5827b5038d7SDag-Erling Smørgrav /* owner name */ 5837b5038d7SDag-Erling Smørgrav tmp = ldns_rdf_clone(ldns_rr_owner(key)); 5847b5038d7SDag-Erling Smørgrav ldns_dname2canonical(tmp); 5857b5038d7SDag-Erling Smørgrav if (ldns_rdf2buffer_wire(data_buf, tmp) != LDNS_STATUS_OK) { 5867b5038d7SDag-Erling Smørgrav LDNS_FREE(digest); 5877b5038d7SDag-Erling Smørgrav ldns_buffer_free(data_buf); 5887b5038d7SDag-Erling Smørgrav ldns_rr_free(ds); 5897b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(tmp); 5907b5038d7SDag-Erling Smørgrav return NULL; 5917b5038d7SDag-Erling Smørgrav } 5927b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(tmp); 5937b5038d7SDag-Erling Smørgrav 5947b5038d7SDag-Erling Smørgrav /* all the rdata's */ 5957b5038d7SDag-Erling Smørgrav if (ldns_rr_rdata2buffer_wire(data_buf, 5967b5038d7SDag-Erling Smørgrav (ldns_rr*)key) != LDNS_STATUS_OK) { 5977b5038d7SDag-Erling Smørgrav LDNS_FREE(digest); 5987b5038d7SDag-Erling Smørgrav ldns_buffer_free(data_buf); 5997b5038d7SDag-Erling Smørgrav ldns_rr_free(ds); 6007b5038d7SDag-Erling Smørgrav return NULL; 6017b5038d7SDag-Erling Smørgrav } 6027b5038d7SDag-Erling Smørgrav switch(h) { 6037b5038d7SDag-Erling Smørgrav case LDNS_SHA1: 6047b5038d7SDag-Erling Smørgrav (void) ldns_sha1((unsigned char *) ldns_buffer_begin(data_buf), 6057b5038d7SDag-Erling Smørgrav (unsigned int) ldns_buffer_position(data_buf), 6067b5038d7SDag-Erling Smørgrav (unsigned char *) digest); 6077b5038d7SDag-Erling Smørgrav 6087b5038d7SDag-Erling Smørgrav tmp = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_HEX, 6097b5038d7SDag-Erling Smørgrav LDNS_SHA1_DIGEST_LENGTH, 6107b5038d7SDag-Erling Smørgrav digest); 6117b5038d7SDag-Erling Smørgrav ldns_rr_push_rdf(ds, tmp); 6127b5038d7SDag-Erling Smørgrav 6137b5038d7SDag-Erling Smørgrav break; 6147b5038d7SDag-Erling Smørgrav case LDNS_SHA256: 6157b5038d7SDag-Erling Smørgrav (void) ldns_sha256((unsigned char *) ldns_buffer_begin(data_buf), 6167b5038d7SDag-Erling Smørgrav (unsigned int) ldns_buffer_position(data_buf), 6177b5038d7SDag-Erling Smørgrav (unsigned char *) digest); 6187b5038d7SDag-Erling Smørgrav tmp = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_HEX, 6197b5038d7SDag-Erling Smørgrav LDNS_SHA256_DIGEST_LENGTH, 6207b5038d7SDag-Erling Smørgrav digest); 6217b5038d7SDag-Erling Smørgrav ldns_rr_push_rdf(ds, tmp); 6227b5038d7SDag-Erling Smørgrav break; 6237b5038d7SDag-Erling Smørgrav case LDNS_HASH_GOST: 6247b5038d7SDag-Erling Smørgrav #ifdef USE_GOST 6257b5038d7SDag-Erling Smørgrav if(!ldns_digest_evp((unsigned char *) ldns_buffer_begin(data_buf), 6267b5038d7SDag-Erling Smørgrav (unsigned int) ldns_buffer_position(data_buf), 6277b5038d7SDag-Erling Smørgrav (unsigned char *) digest, md)) { 6287b5038d7SDag-Erling Smørgrav LDNS_FREE(digest); 6297b5038d7SDag-Erling Smørgrav ldns_buffer_free(data_buf); 6307b5038d7SDag-Erling Smørgrav ldns_rr_free(ds); 6317b5038d7SDag-Erling Smørgrav return NULL; 6327b5038d7SDag-Erling Smørgrav } 6337b5038d7SDag-Erling Smørgrav tmp = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_HEX, 6347b5038d7SDag-Erling Smørgrav (size_t)EVP_MD_size(md), 6357b5038d7SDag-Erling Smørgrav digest); 6367b5038d7SDag-Erling Smørgrav ldns_rr_push_rdf(ds, tmp); 6377b5038d7SDag-Erling Smørgrav #endif 6387b5038d7SDag-Erling Smørgrav break; 6397b5038d7SDag-Erling Smørgrav case LDNS_SHA384: 6407b5038d7SDag-Erling Smørgrav #ifdef USE_ECDSA 6417b5038d7SDag-Erling Smørgrav (void) SHA384((unsigned char *) ldns_buffer_begin(data_buf), 6427b5038d7SDag-Erling Smørgrav (unsigned int) ldns_buffer_position(data_buf), 6437b5038d7SDag-Erling Smørgrav (unsigned char *) digest); 6447b5038d7SDag-Erling Smørgrav tmp = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_HEX, 6457b5038d7SDag-Erling Smørgrav SHA384_DIGEST_LENGTH, 6467b5038d7SDag-Erling Smørgrav digest); 6477b5038d7SDag-Erling Smørgrav ldns_rr_push_rdf(ds, tmp); 6487b5038d7SDag-Erling Smørgrav #endif 6497b5038d7SDag-Erling Smørgrav break; 6507b5038d7SDag-Erling Smørgrav } 6517b5038d7SDag-Erling Smørgrav 6527b5038d7SDag-Erling Smørgrav LDNS_FREE(digest); 6537b5038d7SDag-Erling Smørgrav ldns_buffer_free(data_buf); 6547b5038d7SDag-Erling Smørgrav return ds; 6557b5038d7SDag-Erling Smørgrav } 6567b5038d7SDag-Erling Smørgrav 6577b5038d7SDag-Erling Smørgrav ldns_rdf * 6587b5038d7SDag-Erling Smørgrav ldns_dnssec_create_nsec_bitmap(ldns_rr_type rr_type_list[], 6597b5038d7SDag-Erling Smørgrav size_t size, 6607b5038d7SDag-Erling Smørgrav ldns_rr_type nsec_type) 6617b5038d7SDag-Erling Smørgrav { 6627b5038d7SDag-Erling Smørgrav size_t i; 6637b5038d7SDag-Erling Smørgrav uint8_t *bitmap; 6647b5038d7SDag-Erling Smørgrav uint16_t bm_len = 0; 6657b5038d7SDag-Erling Smørgrav uint16_t i_type; 6667b5038d7SDag-Erling Smørgrav ldns_rdf *bitmap_rdf; 6677b5038d7SDag-Erling Smørgrav 6687b5038d7SDag-Erling Smørgrav uint8_t *data = NULL; 6697b5038d7SDag-Erling Smørgrav uint8_t cur_data[32]; 6707b5038d7SDag-Erling Smørgrav uint8_t cur_window = 0; 6717b5038d7SDag-Erling Smørgrav uint8_t cur_window_max = 0; 6727b5038d7SDag-Erling Smørgrav uint16_t cur_data_size = 0; 6737b5038d7SDag-Erling Smørgrav 6747b5038d7SDag-Erling Smørgrav if (nsec_type != LDNS_RR_TYPE_NSEC && 6757b5038d7SDag-Erling Smørgrav nsec_type != LDNS_RR_TYPE_NSEC3) { 6767b5038d7SDag-Erling Smørgrav return NULL; 6777b5038d7SDag-Erling Smørgrav } 6787b5038d7SDag-Erling Smørgrav 6797b5038d7SDag-Erling Smørgrav i_type = 0; 6807b5038d7SDag-Erling Smørgrav for (i = 0; i < size; i++) { 6817b5038d7SDag-Erling Smørgrav if (i_type < rr_type_list[i]) 6827b5038d7SDag-Erling Smørgrav i_type = rr_type_list[i]; 6837b5038d7SDag-Erling Smørgrav } 6847b5038d7SDag-Erling Smørgrav if (i_type < nsec_type) { 6857b5038d7SDag-Erling Smørgrav i_type = nsec_type; 6867b5038d7SDag-Erling Smørgrav } 6877b5038d7SDag-Erling Smørgrav 6887b5038d7SDag-Erling Smørgrav bm_len = i_type / 8 + 2; 6897b5038d7SDag-Erling Smørgrav bitmap = LDNS_XMALLOC(uint8_t, bm_len); 6907b5038d7SDag-Erling Smørgrav if(!bitmap) return NULL; 6917b5038d7SDag-Erling Smørgrav for (i = 0; i < bm_len; i++) { 6927b5038d7SDag-Erling Smørgrav bitmap[i] = 0; 6937b5038d7SDag-Erling Smørgrav } 6947b5038d7SDag-Erling Smørgrav 6957b5038d7SDag-Erling Smørgrav for (i = 0; i < size; i++) { 6967b5038d7SDag-Erling Smørgrav i_type = rr_type_list[i]; 6977b5038d7SDag-Erling Smørgrav ldns_set_bit(bitmap + (int) i_type / 8, 6987b5038d7SDag-Erling Smørgrav (int) (7 - (i_type % 8)), 6997b5038d7SDag-Erling Smørgrav true); 7007b5038d7SDag-Erling Smørgrav } 7017b5038d7SDag-Erling Smørgrav 7027b5038d7SDag-Erling Smørgrav /* fold it into windows TODO: can this be done directly? */ 7037b5038d7SDag-Erling Smørgrav memset(cur_data, 0, 32); 7047b5038d7SDag-Erling Smørgrav for (i = 0; i < bm_len; i++) { 7057b5038d7SDag-Erling Smørgrav if (i / 32 > cur_window) { 7067b5038d7SDag-Erling Smørgrav /* check, copy, new */ 7077b5038d7SDag-Erling Smørgrav if (cur_window_max > 0) { 7087b5038d7SDag-Erling Smørgrav /* this window has stuff, add it */ 7097b5038d7SDag-Erling Smørgrav data = LDNS_XREALLOC(data, 7107b5038d7SDag-Erling Smørgrav uint8_t, 7117b5038d7SDag-Erling Smørgrav cur_data_size + cur_window_max + 3); 7127b5038d7SDag-Erling Smørgrav if(!data) { 7137b5038d7SDag-Erling Smørgrav LDNS_FREE(bitmap); 7147b5038d7SDag-Erling Smørgrav return NULL; 7157b5038d7SDag-Erling Smørgrav } 7167b5038d7SDag-Erling Smørgrav data[cur_data_size] = cur_window; 7177b5038d7SDag-Erling Smørgrav data[cur_data_size + 1] = cur_window_max + 1; 7187b5038d7SDag-Erling Smørgrav memcpy(data + cur_data_size + 2, 7197b5038d7SDag-Erling Smørgrav cur_data, 7207b5038d7SDag-Erling Smørgrav cur_window_max+1); 7217b5038d7SDag-Erling Smørgrav cur_data_size += cur_window_max + 3; 7227b5038d7SDag-Erling Smørgrav } 7237b5038d7SDag-Erling Smørgrav cur_window++; 7247b5038d7SDag-Erling Smørgrav cur_window_max = 0; 7257b5038d7SDag-Erling Smørgrav memset(cur_data, 0, 32); 7267b5038d7SDag-Erling Smørgrav } 7277b5038d7SDag-Erling Smørgrav cur_data[i%32] = bitmap[i]; 7287b5038d7SDag-Erling Smørgrav if (bitmap[i] > 0) { 7297b5038d7SDag-Erling Smørgrav cur_window_max = i%32; 7307b5038d7SDag-Erling Smørgrav } 7317b5038d7SDag-Erling Smørgrav } 7327b5038d7SDag-Erling Smørgrav if (cur_window_max > 0 || cur_data[0] != 0) { 7337b5038d7SDag-Erling Smørgrav /* this window has stuff, add it */ 7347b5038d7SDag-Erling Smørgrav data = LDNS_XREALLOC(data, 7357b5038d7SDag-Erling Smørgrav uint8_t, 7367b5038d7SDag-Erling Smørgrav cur_data_size + cur_window_max + 3); 7377b5038d7SDag-Erling Smørgrav if(!data) { 7387b5038d7SDag-Erling Smørgrav LDNS_FREE(bitmap); 7397b5038d7SDag-Erling Smørgrav return NULL; 7407b5038d7SDag-Erling Smørgrav } 7417b5038d7SDag-Erling Smørgrav data[cur_data_size] = cur_window; 7427b5038d7SDag-Erling Smørgrav data[cur_data_size + 1] = cur_window_max + 1; 7437b5038d7SDag-Erling Smørgrav memcpy(data + cur_data_size + 2, cur_data, cur_window_max+1); 7447b5038d7SDag-Erling Smørgrav cur_data_size += cur_window_max + 3; 7457b5038d7SDag-Erling Smørgrav } 7467b5038d7SDag-Erling Smørgrav bitmap_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_NSEC, 7477b5038d7SDag-Erling Smørgrav cur_data_size, 7487b5038d7SDag-Erling Smørgrav data); 7497b5038d7SDag-Erling Smørgrav 7507b5038d7SDag-Erling Smørgrav LDNS_FREE(bitmap); 7517b5038d7SDag-Erling Smørgrav LDNS_FREE(data); 7527b5038d7SDag-Erling Smørgrav 7537b5038d7SDag-Erling Smørgrav return bitmap_rdf; 7547b5038d7SDag-Erling Smørgrav } 7557b5038d7SDag-Erling Smørgrav 7567b5038d7SDag-Erling Smørgrav int 7577b5038d7SDag-Erling Smørgrav ldns_dnssec_rrsets_contains_type(ldns_dnssec_rrsets *rrsets, 7587b5038d7SDag-Erling Smørgrav ldns_rr_type type) 7597b5038d7SDag-Erling Smørgrav { 7607b5038d7SDag-Erling Smørgrav ldns_dnssec_rrsets *cur_rrset = rrsets; 7617b5038d7SDag-Erling Smørgrav while (cur_rrset) { 7627b5038d7SDag-Erling Smørgrav if (cur_rrset->type == type) { 7637b5038d7SDag-Erling Smørgrav return 1; 7647b5038d7SDag-Erling Smørgrav } 7657b5038d7SDag-Erling Smørgrav cur_rrset = cur_rrset->next; 7667b5038d7SDag-Erling Smørgrav } 7677b5038d7SDag-Erling Smørgrav return 0; 7687b5038d7SDag-Erling Smørgrav } 7697b5038d7SDag-Erling Smørgrav 7707b5038d7SDag-Erling Smørgrav ldns_rr * 7717b5038d7SDag-Erling Smørgrav ldns_dnssec_create_nsec(ldns_dnssec_name *from, 7727b5038d7SDag-Erling Smørgrav ldns_dnssec_name *to, 7737b5038d7SDag-Erling Smørgrav ldns_rr_type nsec_type) 7747b5038d7SDag-Erling Smørgrav { 7757b5038d7SDag-Erling Smørgrav ldns_rr *nsec_rr; 7767b5038d7SDag-Erling Smørgrav ldns_rr_type types[65536]; 7777b5038d7SDag-Erling Smørgrav size_t type_count = 0; 7787b5038d7SDag-Erling Smørgrav ldns_dnssec_rrsets *cur_rrsets; 7797b5038d7SDag-Erling Smørgrav int on_delegation_point; 7807b5038d7SDag-Erling Smørgrav 7817b5038d7SDag-Erling Smørgrav if (!from || !to || (nsec_type != LDNS_RR_TYPE_NSEC)) { 7827b5038d7SDag-Erling Smørgrav return NULL; 7837b5038d7SDag-Erling Smørgrav } 7847b5038d7SDag-Erling Smørgrav 7857b5038d7SDag-Erling Smørgrav nsec_rr = ldns_rr_new(); 7867b5038d7SDag-Erling Smørgrav ldns_rr_set_type(nsec_rr, nsec_type); 7877b5038d7SDag-Erling Smørgrav ldns_rr_set_owner(nsec_rr, ldns_rdf_clone(ldns_dnssec_name_name(from))); 7887b5038d7SDag-Erling Smørgrav ldns_rr_push_rdf(nsec_rr, ldns_rdf_clone(ldns_dnssec_name_name(to))); 7897b5038d7SDag-Erling Smørgrav 7907b5038d7SDag-Erling Smørgrav on_delegation_point = ldns_dnssec_rrsets_contains_type( 7917b5038d7SDag-Erling Smørgrav from->rrsets, LDNS_RR_TYPE_NS) 7927b5038d7SDag-Erling Smørgrav && !ldns_dnssec_rrsets_contains_type( 7937b5038d7SDag-Erling Smørgrav from->rrsets, LDNS_RR_TYPE_SOA); 7947b5038d7SDag-Erling Smørgrav 7957b5038d7SDag-Erling Smørgrav cur_rrsets = from->rrsets; 7967b5038d7SDag-Erling Smørgrav while (cur_rrsets) { 7977b5038d7SDag-Erling Smørgrav /* Do not include non-authoritative rrsets on the delegation point 7987b5038d7SDag-Erling Smørgrav * in the type bitmap */ 7997b5038d7SDag-Erling Smørgrav if ((on_delegation_point && ( 8007b5038d7SDag-Erling Smørgrav cur_rrsets->type == LDNS_RR_TYPE_NS 8017b5038d7SDag-Erling Smørgrav || cur_rrsets->type == LDNS_RR_TYPE_DS)) 8027b5038d7SDag-Erling Smørgrav || (!on_delegation_point && 8037b5038d7SDag-Erling Smørgrav cur_rrsets->type != LDNS_RR_TYPE_RRSIG 8047b5038d7SDag-Erling Smørgrav && cur_rrsets->type != LDNS_RR_TYPE_NSEC)) { 8057b5038d7SDag-Erling Smørgrav 8067b5038d7SDag-Erling Smørgrav types[type_count] = cur_rrsets->type; 8077b5038d7SDag-Erling Smørgrav type_count++; 8087b5038d7SDag-Erling Smørgrav } 8097b5038d7SDag-Erling Smørgrav cur_rrsets = cur_rrsets->next; 8107b5038d7SDag-Erling Smørgrav 8117b5038d7SDag-Erling Smørgrav } 8127b5038d7SDag-Erling Smørgrav types[type_count] = LDNS_RR_TYPE_RRSIG; 8137b5038d7SDag-Erling Smørgrav type_count++; 8147b5038d7SDag-Erling Smørgrav types[type_count] = LDNS_RR_TYPE_NSEC; 8157b5038d7SDag-Erling Smørgrav type_count++; 8167b5038d7SDag-Erling Smørgrav 8177b5038d7SDag-Erling Smørgrav ldns_rr_push_rdf(nsec_rr, ldns_dnssec_create_nsec_bitmap(types, 8187b5038d7SDag-Erling Smørgrav type_count, 8197b5038d7SDag-Erling Smørgrav nsec_type)); 8207b5038d7SDag-Erling Smørgrav 8217b5038d7SDag-Erling Smørgrav return nsec_rr; 8227b5038d7SDag-Erling Smørgrav } 8237b5038d7SDag-Erling Smørgrav 8247b5038d7SDag-Erling Smørgrav ldns_rr * 8257b5038d7SDag-Erling Smørgrav ldns_dnssec_create_nsec3(ldns_dnssec_name *from, 8267b5038d7SDag-Erling Smørgrav ldns_dnssec_name *to, 8277b5038d7SDag-Erling Smørgrav ldns_rdf *zone_name, 8287b5038d7SDag-Erling Smørgrav uint8_t algorithm, 8297b5038d7SDag-Erling Smørgrav uint8_t flags, 8307b5038d7SDag-Erling Smørgrav uint16_t iterations, 8317b5038d7SDag-Erling Smørgrav uint8_t salt_length, 8327b5038d7SDag-Erling Smørgrav uint8_t *salt) 8337b5038d7SDag-Erling Smørgrav { 8347b5038d7SDag-Erling Smørgrav ldns_rr *nsec_rr; 8357b5038d7SDag-Erling Smørgrav ldns_rr_type types[65536]; 8367b5038d7SDag-Erling Smørgrav size_t type_count = 0; 8377b5038d7SDag-Erling Smørgrav ldns_dnssec_rrsets *cur_rrsets; 8387b5038d7SDag-Erling Smørgrav ldns_status status; 8397b5038d7SDag-Erling Smørgrav int on_delegation_point; 8407b5038d7SDag-Erling Smørgrav 8417b5038d7SDag-Erling Smørgrav if (!from) { 8427b5038d7SDag-Erling Smørgrav return NULL; 8437b5038d7SDag-Erling Smørgrav } 8447b5038d7SDag-Erling Smørgrav 8457b5038d7SDag-Erling Smørgrav nsec_rr = ldns_rr_new_frm_type(LDNS_RR_TYPE_NSEC3); 8467b5038d7SDag-Erling Smørgrav ldns_rr_set_owner(nsec_rr, 8477b5038d7SDag-Erling Smørgrav ldns_nsec3_hash_name(ldns_dnssec_name_name(from), 8487b5038d7SDag-Erling Smørgrav algorithm, 8497b5038d7SDag-Erling Smørgrav iterations, 8507b5038d7SDag-Erling Smørgrav salt_length, 8517b5038d7SDag-Erling Smørgrav salt)); 8527b5038d7SDag-Erling Smørgrav status = ldns_dname_cat(ldns_rr_owner(nsec_rr), zone_name); 8537b5038d7SDag-Erling Smørgrav if(status != LDNS_STATUS_OK) { 8547b5038d7SDag-Erling Smørgrav ldns_rr_free(nsec_rr); 8557b5038d7SDag-Erling Smørgrav return NULL; 8567b5038d7SDag-Erling Smørgrav } 8577b5038d7SDag-Erling Smørgrav ldns_nsec3_add_param_rdfs(nsec_rr, 8587b5038d7SDag-Erling Smørgrav algorithm, 8597b5038d7SDag-Erling Smørgrav flags, 8607b5038d7SDag-Erling Smørgrav iterations, 8617b5038d7SDag-Erling Smørgrav salt_length, 8627b5038d7SDag-Erling Smørgrav salt); 8637b5038d7SDag-Erling Smørgrav 8647b5038d7SDag-Erling Smørgrav on_delegation_point = ldns_dnssec_rrsets_contains_type( 8657b5038d7SDag-Erling Smørgrav from->rrsets, LDNS_RR_TYPE_NS) 8667b5038d7SDag-Erling Smørgrav && !ldns_dnssec_rrsets_contains_type( 8677b5038d7SDag-Erling Smørgrav from->rrsets, LDNS_RR_TYPE_SOA); 8687b5038d7SDag-Erling Smørgrav cur_rrsets = from->rrsets; 8697b5038d7SDag-Erling Smørgrav while (cur_rrsets) { 8707b5038d7SDag-Erling Smørgrav /* Do not include non-authoritative rrsets on the delegation point 8717b5038d7SDag-Erling Smørgrav * in the type bitmap. Potentionally not skipping insecure 8727b5038d7SDag-Erling Smørgrav * delegation should have been done earlier, in function 8737b5038d7SDag-Erling Smørgrav * ldns_dnssec_zone_create_nsec3s, or even earlier in: 8747b5038d7SDag-Erling Smørgrav * ldns_dnssec_zone_sign_nsec3_flg . 8757b5038d7SDag-Erling Smørgrav */ 8767b5038d7SDag-Erling Smørgrav if ((on_delegation_point && ( 8777b5038d7SDag-Erling Smørgrav cur_rrsets->type == LDNS_RR_TYPE_NS 8787b5038d7SDag-Erling Smørgrav || cur_rrsets->type == LDNS_RR_TYPE_DS)) 8797b5038d7SDag-Erling Smørgrav || (!on_delegation_point && 8807b5038d7SDag-Erling Smørgrav cur_rrsets->type != LDNS_RR_TYPE_RRSIG)) { 8817b5038d7SDag-Erling Smørgrav 8827b5038d7SDag-Erling Smørgrav types[type_count] = cur_rrsets->type; 8837b5038d7SDag-Erling Smørgrav type_count++; 8847b5038d7SDag-Erling Smørgrav } 8857b5038d7SDag-Erling Smørgrav cur_rrsets = cur_rrsets->next; 8867b5038d7SDag-Erling Smørgrav } 8877b5038d7SDag-Erling Smørgrav /* always add rrsig type if this is not an unsigned 8887b5038d7SDag-Erling Smørgrav * delegation 8897b5038d7SDag-Erling Smørgrav */ 8907b5038d7SDag-Erling Smørgrav if (type_count > 0 && 8917b5038d7SDag-Erling Smørgrav !(type_count == 1 && types[0] == LDNS_RR_TYPE_NS)) { 8927b5038d7SDag-Erling Smørgrav types[type_count] = LDNS_RR_TYPE_RRSIG; 8937b5038d7SDag-Erling Smørgrav type_count++; 8947b5038d7SDag-Erling Smørgrav } 8957b5038d7SDag-Erling Smørgrav 8967b5038d7SDag-Erling Smørgrav /* leave next rdata empty if they weren't precomputed yet */ 8977b5038d7SDag-Erling Smørgrav if (to && to->hashed_name) { 8987b5038d7SDag-Erling Smørgrav (void) ldns_rr_set_rdf(nsec_rr, 8997b5038d7SDag-Erling Smørgrav ldns_rdf_clone(to->hashed_name), 9007b5038d7SDag-Erling Smørgrav 4); 9017b5038d7SDag-Erling Smørgrav } else { 9027b5038d7SDag-Erling Smørgrav (void) ldns_rr_set_rdf(nsec_rr, NULL, 4); 9037b5038d7SDag-Erling Smørgrav } 9047b5038d7SDag-Erling Smørgrav 9057b5038d7SDag-Erling Smørgrav ldns_rr_push_rdf(nsec_rr, 9067b5038d7SDag-Erling Smørgrav ldns_dnssec_create_nsec_bitmap(types, 9077b5038d7SDag-Erling Smørgrav type_count, 9087b5038d7SDag-Erling Smørgrav LDNS_RR_TYPE_NSEC3)); 9097b5038d7SDag-Erling Smørgrav 9107b5038d7SDag-Erling Smørgrav return nsec_rr; 9117b5038d7SDag-Erling Smørgrav } 9127b5038d7SDag-Erling Smørgrav 9137b5038d7SDag-Erling Smørgrav ldns_rr * 9147b5038d7SDag-Erling Smørgrav ldns_create_nsec(ldns_rdf *cur_owner, ldns_rdf *next_owner, ldns_rr_list *rrs) 9157b5038d7SDag-Erling Smørgrav { 9167b5038d7SDag-Erling Smørgrav /* we do not do any check here - garbage in, garbage out */ 9177b5038d7SDag-Erling Smørgrav 9187b5038d7SDag-Erling Smørgrav /* the the start and end names - get the type from the 9197b5038d7SDag-Erling Smørgrav * before rrlist */ 9207b5038d7SDag-Erling Smørgrav 9217b5038d7SDag-Erling Smørgrav /* inefficient, just give it a name, a next name, and a list of rrs */ 9227b5038d7SDag-Erling Smørgrav /* we make 1 big uberbitmap first, then windows */ 9237b5038d7SDag-Erling Smørgrav /* todo: make something more efficient :) */ 9247b5038d7SDag-Erling Smørgrav uint16_t i; 9257b5038d7SDag-Erling Smørgrav ldns_rr *i_rr; 9267b5038d7SDag-Erling Smørgrav uint16_t i_type; 9277b5038d7SDag-Erling Smørgrav 9287b5038d7SDag-Erling Smørgrav ldns_rr *nsec = NULL; 9297b5038d7SDag-Erling Smørgrav ldns_rr_type i_type_list[65536]; 9307b5038d7SDag-Erling Smørgrav size_t type_count = 0; 9317b5038d7SDag-Erling Smørgrav 9327b5038d7SDag-Erling Smørgrav nsec = ldns_rr_new(); 9337b5038d7SDag-Erling Smørgrav ldns_rr_set_type(nsec, LDNS_RR_TYPE_NSEC); 9347b5038d7SDag-Erling Smørgrav ldns_rr_set_owner(nsec, ldns_rdf_clone(cur_owner)); 9357b5038d7SDag-Erling Smørgrav ldns_rr_push_rdf(nsec, ldns_rdf_clone(next_owner)); 9367b5038d7SDag-Erling Smørgrav 9377b5038d7SDag-Erling Smørgrav for (i = 0; i < ldns_rr_list_rr_count(rrs); i++) { 9387b5038d7SDag-Erling Smørgrav i_rr = ldns_rr_list_rr(rrs, i); 9397b5038d7SDag-Erling Smørgrav if (ldns_rdf_compare(cur_owner, 9407b5038d7SDag-Erling Smørgrav ldns_rr_owner(i_rr)) == 0) { 9417b5038d7SDag-Erling Smørgrav i_type = ldns_rr_get_type(i_rr); 9427b5038d7SDag-Erling Smørgrav if (i_type != LDNS_RR_TYPE_RRSIG && i_type != LDNS_RR_TYPE_NSEC) { 9437b5038d7SDag-Erling Smørgrav if (type_count == 0 || i_type_list[type_count-1] != i_type) { 9447b5038d7SDag-Erling Smørgrav i_type_list[type_count] = i_type; 9457b5038d7SDag-Erling Smørgrav type_count++; 9467b5038d7SDag-Erling Smørgrav } 9477b5038d7SDag-Erling Smørgrav } 9487b5038d7SDag-Erling Smørgrav } 9497b5038d7SDag-Erling Smørgrav } 9507b5038d7SDag-Erling Smørgrav 9517b5038d7SDag-Erling Smørgrav i_type_list[type_count] = LDNS_RR_TYPE_RRSIG; 9527b5038d7SDag-Erling Smørgrav type_count++; 9537b5038d7SDag-Erling Smørgrav i_type_list[type_count] = LDNS_RR_TYPE_NSEC; 9547b5038d7SDag-Erling Smørgrav type_count++; 9557b5038d7SDag-Erling Smørgrav 9567b5038d7SDag-Erling Smørgrav ldns_rr_push_rdf(nsec, 9577b5038d7SDag-Erling Smørgrav ldns_dnssec_create_nsec_bitmap(i_type_list, 9587b5038d7SDag-Erling Smørgrav type_count, LDNS_RR_TYPE_NSEC)); 9597b5038d7SDag-Erling Smørgrav 9607b5038d7SDag-Erling Smørgrav return nsec; 9617b5038d7SDag-Erling Smørgrav } 9627b5038d7SDag-Erling Smørgrav 9637b5038d7SDag-Erling Smørgrav ldns_rdf * 9647b5038d7SDag-Erling Smørgrav ldns_nsec3_hash_name(ldns_rdf *name, 9657b5038d7SDag-Erling Smørgrav uint8_t algorithm, 9667b5038d7SDag-Erling Smørgrav uint16_t iterations, 9677b5038d7SDag-Erling Smørgrav uint8_t salt_length, 9687b5038d7SDag-Erling Smørgrav uint8_t *salt) 9697b5038d7SDag-Erling Smørgrav { 9707b5038d7SDag-Erling Smørgrav size_t hashed_owner_str_len; 9717b5038d7SDag-Erling Smørgrav ldns_rdf *cann; 9727b5038d7SDag-Erling Smørgrav ldns_rdf *hashed_owner; 9737b5038d7SDag-Erling Smørgrav unsigned char *hashed_owner_str; 9747b5038d7SDag-Erling Smørgrav char *hashed_owner_b32; 9757b5038d7SDag-Erling Smørgrav size_t hashed_owner_b32_len; 9767b5038d7SDag-Erling Smørgrav uint32_t cur_it; 9777b5038d7SDag-Erling Smørgrav /* define to contain the largest possible hash, which is 9787b5038d7SDag-Erling Smørgrav * sha1 at the moment */ 9797b5038d7SDag-Erling Smørgrav unsigned char hash[LDNS_SHA1_DIGEST_LENGTH]; 9807b5038d7SDag-Erling Smørgrav ldns_status status; 9817b5038d7SDag-Erling Smørgrav 9827b5038d7SDag-Erling Smørgrav /* TODO: mnemonic list for hash algs SHA-1, default to 1 now (sha1) */ 9837b5038d7SDag-Erling Smørgrav if (algorithm != LDNS_SHA1) { 9847b5038d7SDag-Erling Smørgrav return NULL; 9857b5038d7SDag-Erling Smørgrav } 9867b5038d7SDag-Erling Smørgrav 9877b5038d7SDag-Erling Smørgrav /* prepare the owner name according to the draft section bla */ 9887b5038d7SDag-Erling Smørgrav cann = ldns_rdf_clone(name); 9897b5038d7SDag-Erling Smørgrav if(!cann) { 9907b5038d7SDag-Erling Smørgrav fprintf(stderr, "Memory error\n"); 9917b5038d7SDag-Erling Smørgrav return NULL; 9927b5038d7SDag-Erling Smørgrav } 9937b5038d7SDag-Erling Smørgrav ldns_dname2canonical(cann); 9947b5038d7SDag-Erling Smørgrav 9957b5038d7SDag-Erling Smørgrav hashed_owner_str_len = salt_length + ldns_rdf_size(cann); 9967b5038d7SDag-Erling Smørgrav hashed_owner_str = LDNS_XMALLOC(unsigned char, hashed_owner_str_len); 9977b5038d7SDag-Erling Smørgrav if(!hashed_owner_str) { 9987b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(cann); 9997b5038d7SDag-Erling Smørgrav return NULL; 10007b5038d7SDag-Erling Smørgrav } 10017b5038d7SDag-Erling Smørgrav memcpy(hashed_owner_str, ldns_rdf_data(cann), ldns_rdf_size(cann)); 10027b5038d7SDag-Erling Smørgrav memcpy(hashed_owner_str + ldns_rdf_size(cann), salt, salt_length); 10037b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(cann); 10047b5038d7SDag-Erling Smørgrav 10057b5038d7SDag-Erling Smørgrav for (cur_it = iterations + 1; cur_it > 0; cur_it--) { 10067b5038d7SDag-Erling Smørgrav (void) ldns_sha1((unsigned char *) hashed_owner_str, 10077b5038d7SDag-Erling Smørgrav (unsigned int) hashed_owner_str_len, hash); 10087b5038d7SDag-Erling Smørgrav 10097b5038d7SDag-Erling Smørgrav LDNS_FREE(hashed_owner_str); 10107b5038d7SDag-Erling Smørgrav hashed_owner_str_len = salt_length + LDNS_SHA1_DIGEST_LENGTH; 10117b5038d7SDag-Erling Smørgrav hashed_owner_str = LDNS_XMALLOC(unsigned char, hashed_owner_str_len); 10127b5038d7SDag-Erling Smørgrav if (!hashed_owner_str) { 10137b5038d7SDag-Erling Smørgrav return NULL; 10147b5038d7SDag-Erling Smørgrav } 10157b5038d7SDag-Erling Smørgrav memcpy(hashed_owner_str, hash, LDNS_SHA1_DIGEST_LENGTH); 10167b5038d7SDag-Erling Smørgrav memcpy(hashed_owner_str + LDNS_SHA1_DIGEST_LENGTH, salt, salt_length); 10177b5038d7SDag-Erling Smørgrav hashed_owner_str_len = LDNS_SHA1_DIGEST_LENGTH + salt_length; 10187b5038d7SDag-Erling Smørgrav } 10197b5038d7SDag-Erling Smørgrav 10207b5038d7SDag-Erling Smørgrav LDNS_FREE(hashed_owner_str); 10217b5038d7SDag-Erling Smørgrav hashed_owner_str = hash; 10227b5038d7SDag-Erling Smørgrav hashed_owner_str_len = LDNS_SHA1_DIGEST_LENGTH; 10237b5038d7SDag-Erling Smørgrav 10247b5038d7SDag-Erling Smørgrav hashed_owner_b32 = LDNS_XMALLOC(char, 10257b5038d7SDag-Erling Smørgrav ldns_b32_ntop_calculate_size(hashed_owner_str_len) + 1); 10267b5038d7SDag-Erling Smørgrav if(!hashed_owner_b32) { 10277b5038d7SDag-Erling Smørgrav return NULL; 10287b5038d7SDag-Erling Smørgrav } 10297b5038d7SDag-Erling Smørgrav hashed_owner_b32_len = (size_t) ldns_b32_ntop_extended_hex( 10307b5038d7SDag-Erling Smørgrav (uint8_t *) hashed_owner_str, 10317b5038d7SDag-Erling Smørgrav hashed_owner_str_len, 10327b5038d7SDag-Erling Smørgrav hashed_owner_b32, 10337b5038d7SDag-Erling Smørgrav ldns_b32_ntop_calculate_size(hashed_owner_str_len)+1); 10347b5038d7SDag-Erling Smørgrav if (hashed_owner_b32_len < 1) { 10357b5038d7SDag-Erling Smørgrav fprintf(stderr, "Error in base32 extended hex encoding "); 10367b5038d7SDag-Erling Smørgrav fprintf(stderr, "of hashed owner name (name: "); 10377b5038d7SDag-Erling Smørgrav ldns_rdf_print(stderr, name); 10387b5038d7SDag-Erling Smørgrav fprintf(stderr, ", return code: %u)\n", 10397b5038d7SDag-Erling Smørgrav (unsigned int) hashed_owner_b32_len); 10407b5038d7SDag-Erling Smørgrav LDNS_FREE(hashed_owner_b32); 10417b5038d7SDag-Erling Smørgrav return NULL; 10427b5038d7SDag-Erling Smørgrav } 10437b5038d7SDag-Erling Smørgrav hashed_owner_b32[hashed_owner_b32_len] = '\0'; 10447b5038d7SDag-Erling Smørgrav 10457b5038d7SDag-Erling Smørgrav status = ldns_str2rdf_dname(&hashed_owner, hashed_owner_b32); 10467b5038d7SDag-Erling Smørgrav if (status != LDNS_STATUS_OK) { 10477b5038d7SDag-Erling Smørgrav fprintf(stderr, "Error creating rdf from %s\n", hashed_owner_b32); 10487b5038d7SDag-Erling Smørgrav LDNS_FREE(hashed_owner_b32); 10497b5038d7SDag-Erling Smørgrav return NULL; 10507b5038d7SDag-Erling Smørgrav } 10517b5038d7SDag-Erling Smørgrav 10527b5038d7SDag-Erling Smørgrav LDNS_FREE(hashed_owner_b32); 10537b5038d7SDag-Erling Smørgrav return hashed_owner; 10547b5038d7SDag-Erling Smørgrav } 10557b5038d7SDag-Erling Smørgrav 10567b5038d7SDag-Erling Smørgrav void 10577b5038d7SDag-Erling Smørgrav ldns_nsec3_add_param_rdfs(ldns_rr *rr, 10587b5038d7SDag-Erling Smørgrav uint8_t algorithm, 10597b5038d7SDag-Erling Smørgrav uint8_t flags, 10607b5038d7SDag-Erling Smørgrav uint16_t iterations, 10617b5038d7SDag-Erling Smørgrav uint8_t salt_length, 10627b5038d7SDag-Erling Smørgrav uint8_t *salt) 10637b5038d7SDag-Erling Smørgrav { 10647b5038d7SDag-Erling Smørgrav ldns_rdf *salt_rdf = NULL; 10657b5038d7SDag-Erling Smørgrav uint8_t *salt_data = NULL; 10667b5038d7SDag-Erling Smørgrav ldns_rdf *old; 10677b5038d7SDag-Erling Smørgrav 10687b5038d7SDag-Erling Smørgrav old = ldns_rr_set_rdf(rr, 10697b5038d7SDag-Erling Smørgrav ldns_rdf_new_frm_data(LDNS_RDF_TYPE_INT8, 10707b5038d7SDag-Erling Smørgrav 1, (void*)&algorithm), 10717b5038d7SDag-Erling Smørgrav 0); 10727b5038d7SDag-Erling Smørgrav if (old) ldns_rdf_deep_free(old); 10737b5038d7SDag-Erling Smørgrav 10747b5038d7SDag-Erling Smørgrav old = ldns_rr_set_rdf(rr, 10757b5038d7SDag-Erling Smørgrav ldns_rdf_new_frm_data(LDNS_RDF_TYPE_INT8, 10767b5038d7SDag-Erling Smørgrav 1, (void*)&flags), 10777b5038d7SDag-Erling Smørgrav 1); 10787b5038d7SDag-Erling Smørgrav if (old) ldns_rdf_deep_free(old); 10797b5038d7SDag-Erling Smørgrav 10807b5038d7SDag-Erling Smørgrav old = ldns_rr_set_rdf(rr, 10817b5038d7SDag-Erling Smørgrav ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, 10827b5038d7SDag-Erling Smørgrav iterations), 10837b5038d7SDag-Erling Smørgrav 2); 10847b5038d7SDag-Erling Smørgrav if (old) ldns_rdf_deep_free(old); 10857b5038d7SDag-Erling Smørgrav 10867b5038d7SDag-Erling Smørgrav salt_data = LDNS_XMALLOC(uint8_t, salt_length + 1); 10877b5038d7SDag-Erling Smørgrav if(!salt_data) { 10887b5038d7SDag-Erling Smørgrav /* no way to return error */ 10897b5038d7SDag-Erling Smørgrav return; 10907b5038d7SDag-Erling Smørgrav } 10917b5038d7SDag-Erling Smørgrav salt_data[0] = salt_length; 10927b5038d7SDag-Erling Smørgrav memcpy(salt_data + 1, salt, salt_length); 10937b5038d7SDag-Erling Smørgrav salt_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_NSEC3_SALT, 10947b5038d7SDag-Erling Smørgrav salt_length + 1, 10957b5038d7SDag-Erling Smørgrav salt_data); 10967b5038d7SDag-Erling Smørgrav if(!salt_rdf) { 10977b5038d7SDag-Erling Smørgrav LDNS_FREE(salt_data); 10987b5038d7SDag-Erling Smørgrav /* no way to return error */ 10997b5038d7SDag-Erling Smørgrav return; 11007b5038d7SDag-Erling Smørgrav } 11017b5038d7SDag-Erling Smørgrav 11027b5038d7SDag-Erling Smørgrav old = ldns_rr_set_rdf(rr, salt_rdf, 3); 11037b5038d7SDag-Erling Smørgrav if (old) ldns_rdf_deep_free(old); 11047b5038d7SDag-Erling Smørgrav LDNS_FREE(salt_data); 11057b5038d7SDag-Erling Smørgrav } 11067b5038d7SDag-Erling Smørgrav 11077b5038d7SDag-Erling Smørgrav static int 11087b5038d7SDag-Erling Smørgrav rr_list_delegation_only(ldns_rdf *origin, ldns_rr_list *rr_list) 11097b5038d7SDag-Erling Smørgrav { 11107b5038d7SDag-Erling Smørgrav size_t i; 11117b5038d7SDag-Erling Smørgrav ldns_rr *cur_rr; 11127b5038d7SDag-Erling Smørgrav if (!origin || !rr_list) return 0; 11137b5038d7SDag-Erling Smørgrav for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) { 11147b5038d7SDag-Erling Smørgrav cur_rr = ldns_rr_list_rr(rr_list, i); 11157b5038d7SDag-Erling Smørgrav if (ldns_dname_compare(ldns_rr_owner(cur_rr), origin) == 0) { 11167b5038d7SDag-Erling Smørgrav return 0; 11177b5038d7SDag-Erling Smørgrav } 11187b5038d7SDag-Erling Smørgrav if (ldns_rr_get_type(cur_rr) != LDNS_RR_TYPE_NS) { 11197b5038d7SDag-Erling Smørgrav return 0; 11207b5038d7SDag-Erling Smørgrav } 11217b5038d7SDag-Erling Smørgrav } 11227b5038d7SDag-Erling Smørgrav return 1; 11237b5038d7SDag-Erling Smørgrav } 11247b5038d7SDag-Erling Smørgrav 11257b5038d7SDag-Erling Smørgrav /* this will NOT return the NSEC3 completed, you will have to run the 11267b5038d7SDag-Erling Smørgrav finalize function on the rrlist later! */ 11277b5038d7SDag-Erling Smørgrav ldns_rr * 11287b5038d7SDag-Erling Smørgrav ldns_create_nsec3(ldns_rdf *cur_owner, 11297b5038d7SDag-Erling Smørgrav ldns_rdf *cur_zone, 11307b5038d7SDag-Erling Smørgrav ldns_rr_list *rrs, 11317b5038d7SDag-Erling Smørgrav uint8_t algorithm, 11327b5038d7SDag-Erling Smørgrav uint8_t flags, 11337b5038d7SDag-Erling Smørgrav uint16_t iterations, 11347b5038d7SDag-Erling Smørgrav uint8_t salt_length, 11357b5038d7SDag-Erling Smørgrav uint8_t *salt, 11367b5038d7SDag-Erling Smørgrav bool emptynonterminal) 11377b5038d7SDag-Erling Smørgrav { 11387b5038d7SDag-Erling Smørgrav size_t i; 11397b5038d7SDag-Erling Smørgrav ldns_rr *i_rr; 11407b5038d7SDag-Erling Smørgrav uint16_t i_type; 11417b5038d7SDag-Erling Smørgrav 11427b5038d7SDag-Erling Smørgrav ldns_rr *nsec = NULL; 11437b5038d7SDag-Erling Smørgrav ldns_rdf *hashed_owner = NULL; 11447b5038d7SDag-Erling Smørgrav 11457b5038d7SDag-Erling Smørgrav ldns_status status; 11467b5038d7SDag-Erling Smørgrav 11477b5038d7SDag-Erling Smørgrav ldns_rr_type i_type_list[1024]; 11487b5038d7SDag-Erling Smørgrav size_t type_count = 0; 11497b5038d7SDag-Erling Smørgrav 11507b5038d7SDag-Erling Smørgrav hashed_owner = ldns_nsec3_hash_name(cur_owner, 11517b5038d7SDag-Erling Smørgrav algorithm, 11527b5038d7SDag-Erling Smørgrav iterations, 11537b5038d7SDag-Erling Smørgrav salt_length, 11547b5038d7SDag-Erling Smørgrav salt); 11557b5038d7SDag-Erling Smørgrav status = ldns_dname_cat(hashed_owner, cur_zone); 1156*2787e39aSDag-Erling Smørgrav if(status != LDNS_STATUS_OK) { 1157*2787e39aSDag-Erling Smørgrav ldns_rdf_deep_free(hashed_owner); 11587b5038d7SDag-Erling Smørgrav return NULL; 1159*2787e39aSDag-Erling Smørgrav } 11607b5038d7SDag-Erling Smørgrav nsec = ldns_rr_new_frm_type(LDNS_RR_TYPE_NSEC3); 1161*2787e39aSDag-Erling Smørgrav if(!nsec) { 1162*2787e39aSDag-Erling Smørgrav ldns_rdf_deep_free(hashed_owner); 11637b5038d7SDag-Erling Smørgrav return NULL; 1164*2787e39aSDag-Erling Smørgrav } 11657b5038d7SDag-Erling Smørgrav ldns_rr_set_type(nsec, LDNS_RR_TYPE_NSEC3); 11667b5038d7SDag-Erling Smørgrav ldns_rr_set_owner(nsec, hashed_owner); 11677b5038d7SDag-Erling Smørgrav 11687b5038d7SDag-Erling Smørgrav ldns_nsec3_add_param_rdfs(nsec, 11697b5038d7SDag-Erling Smørgrav algorithm, 11707b5038d7SDag-Erling Smørgrav flags, 11717b5038d7SDag-Erling Smørgrav iterations, 11727b5038d7SDag-Erling Smørgrav salt_length, 11737b5038d7SDag-Erling Smørgrav salt); 11747b5038d7SDag-Erling Smørgrav (void) ldns_rr_set_rdf(nsec, NULL, 4); 11757b5038d7SDag-Erling Smørgrav 11767b5038d7SDag-Erling Smørgrav 11777b5038d7SDag-Erling Smørgrav for (i = 0; i < ldns_rr_list_rr_count(rrs); i++) { 11787b5038d7SDag-Erling Smørgrav i_rr = ldns_rr_list_rr(rrs, i); 11797b5038d7SDag-Erling Smørgrav if (ldns_rdf_compare(cur_owner, 11807b5038d7SDag-Erling Smørgrav ldns_rr_owner(i_rr)) == 0) { 11817b5038d7SDag-Erling Smørgrav i_type = ldns_rr_get_type(i_rr); 11827b5038d7SDag-Erling Smørgrav if (type_count == 0 || i_type_list[type_count-1] != i_type) { 11837b5038d7SDag-Erling Smørgrav i_type_list[type_count] = i_type; 11847b5038d7SDag-Erling Smørgrav type_count++; 11857b5038d7SDag-Erling Smørgrav } 11867b5038d7SDag-Erling Smørgrav } 11877b5038d7SDag-Erling Smørgrav } 11887b5038d7SDag-Erling Smørgrav 11897b5038d7SDag-Erling Smørgrav /* add RRSIG anyway, but only if this is not an ENT or 11907b5038d7SDag-Erling Smørgrav * an unsigned delegation */ 11917b5038d7SDag-Erling Smørgrav if (!emptynonterminal && !rr_list_delegation_only(cur_zone, rrs)) { 11927b5038d7SDag-Erling Smørgrav i_type_list[type_count] = LDNS_RR_TYPE_RRSIG; 11937b5038d7SDag-Erling Smørgrav type_count++; 11947b5038d7SDag-Erling Smørgrav } 11957b5038d7SDag-Erling Smørgrav 11967b5038d7SDag-Erling Smørgrav /* and SOA if owner == zone */ 11977b5038d7SDag-Erling Smørgrav if (ldns_dname_compare(cur_zone, cur_owner) == 0) { 11987b5038d7SDag-Erling Smørgrav i_type_list[type_count] = LDNS_RR_TYPE_SOA; 11997b5038d7SDag-Erling Smørgrav type_count++; 12007b5038d7SDag-Erling Smørgrav } 12017b5038d7SDag-Erling Smørgrav 12027b5038d7SDag-Erling Smørgrav ldns_rr_push_rdf(nsec, 12037b5038d7SDag-Erling Smørgrav ldns_dnssec_create_nsec_bitmap(i_type_list, 12047b5038d7SDag-Erling Smørgrav type_count, LDNS_RR_TYPE_NSEC3)); 12057b5038d7SDag-Erling Smørgrav 12067b5038d7SDag-Erling Smørgrav return nsec; 12077b5038d7SDag-Erling Smørgrav } 12087b5038d7SDag-Erling Smørgrav 12097b5038d7SDag-Erling Smørgrav uint8_t 12107b5038d7SDag-Erling Smørgrav ldns_nsec3_algorithm(const ldns_rr *nsec3_rr) 12117b5038d7SDag-Erling Smørgrav { 12127b5038d7SDag-Erling Smørgrav if (nsec3_rr && 12137b5038d7SDag-Erling Smørgrav (ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3 || 12147b5038d7SDag-Erling Smørgrav ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3PARAM) 12157b5038d7SDag-Erling Smørgrav && (ldns_rr_rdf(nsec3_rr, 0) != NULL) 12167b5038d7SDag-Erling Smørgrav && ldns_rdf_size(ldns_rr_rdf(nsec3_rr, 0)) > 0) { 12177b5038d7SDag-Erling Smørgrav return ldns_rdf2native_int8(ldns_rr_rdf(nsec3_rr, 0)); 12187b5038d7SDag-Erling Smørgrav } 12197b5038d7SDag-Erling Smørgrav return 0; 12207b5038d7SDag-Erling Smørgrav } 12217b5038d7SDag-Erling Smørgrav 12227b5038d7SDag-Erling Smørgrav uint8_t 12237b5038d7SDag-Erling Smørgrav ldns_nsec3_flags(const ldns_rr *nsec3_rr) 12247b5038d7SDag-Erling Smørgrav { 12257b5038d7SDag-Erling Smørgrav if (nsec3_rr && 12267b5038d7SDag-Erling Smørgrav (ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3 || 12277b5038d7SDag-Erling Smørgrav ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3PARAM) 12287b5038d7SDag-Erling Smørgrav && (ldns_rr_rdf(nsec3_rr, 1) != NULL) 12297b5038d7SDag-Erling Smørgrav && ldns_rdf_size(ldns_rr_rdf(nsec3_rr, 1)) > 0) { 12307b5038d7SDag-Erling Smørgrav return ldns_rdf2native_int8(ldns_rr_rdf(nsec3_rr, 1)); 12317b5038d7SDag-Erling Smørgrav } 12327b5038d7SDag-Erling Smørgrav return 0; 12337b5038d7SDag-Erling Smørgrav } 12347b5038d7SDag-Erling Smørgrav 12357b5038d7SDag-Erling Smørgrav bool 12367b5038d7SDag-Erling Smørgrav ldns_nsec3_optout(const ldns_rr *nsec3_rr) 12377b5038d7SDag-Erling Smørgrav { 12387b5038d7SDag-Erling Smørgrav return (ldns_nsec3_flags(nsec3_rr) & LDNS_NSEC3_VARS_OPTOUT_MASK); 12397b5038d7SDag-Erling Smørgrav } 12407b5038d7SDag-Erling Smørgrav 12417b5038d7SDag-Erling Smørgrav uint16_t 12427b5038d7SDag-Erling Smørgrav ldns_nsec3_iterations(const ldns_rr *nsec3_rr) 12437b5038d7SDag-Erling Smørgrav { 12447b5038d7SDag-Erling Smørgrav if (nsec3_rr && 12457b5038d7SDag-Erling Smørgrav (ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3 || 12467b5038d7SDag-Erling Smørgrav ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3PARAM) 12477b5038d7SDag-Erling Smørgrav && (ldns_rr_rdf(nsec3_rr, 2) != NULL) 12487b5038d7SDag-Erling Smørgrav && ldns_rdf_size(ldns_rr_rdf(nsec3_rr, 2)) > 0) { 12497b5038d7SDag-Erling Smørgrav return ldns_rdf2native_int16(ldns_rr_rdf(nsec3_rr, 2)); 12507b5038d7SDag-Erling Smørgrav } 12517b5038d7SDag-Erling Smørgrav return 0; 12527b5038d7SDag-Erling Smørgrav 12537b5038d7SDag-Erling Smørgrav } 12547b5038d7SDag-Erling Smørgrav 12557b5038d7SDag-Erling Smørgrav ldns_rdf * 12567b5038d7SDag-Erling Smørgrav ldns_nsec3_salt(const ldns_rr *nsec3_rr) 12577b5038d7SDag-Erling Smørgrav { 12587b5038d7SDag-Erling Smørgrav if (nsec3_rr && 12597b5038d7SDag-Erling Smørgrav (ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3 || 12607b5038d7SDag-Erling Smørgrav ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3PARAM) 12617b5038d7SDag-Erling Smørgrav ) { 12627b5038d7SDag-Erling Smørgrav return ldns_rr_rdf(nsec3_rr, 3); 12637b5038d7SDag-Erling Smørgrav } 12647b5038d7SDag-Erling Smørgrav return NULL; 12657b5038d7SDag-Erling Smørgrav } 12667b5038d7SDag-Erling Smørgrav 12677b5038d7SDag-Erling Smørgrav uint8_t 12687b5038d7SDag-Erling Smørgrav ldns_nsec3_salt_length(const ldns_rr *nsec3_rr) 12697b5038d7SDag-Erling Smørgrav { 12707b5038d7SDag-Erling Smørgrav ldns_rdf *salt_rdf = ldns_nsec3_salt(nsec3_rr); 12717b5038d7SDag-Erling Smørgrav if (salt_rdf && ldns_rdf_size(salt_rdf) > 0) { 12727b5038d7SDag-Erling Smørgrav return (uint8_t) ldns_rdf_data(salt_rdf)[0]; 12737b5038d7SDag-Erling Smørgrav } 12747b5038d7SDag-Erling Smørgrav return 0; 12757b5038d7SDag-Erling Smørgrav } 12767b5038d7SDag-Erling Smørgrav 12777b5038d7SDag-Erling Smørgrav /* allocs data, free with LDNS_FREE() */ 12787b5038d7SDag-Erling Smørgrav uint8_t * 12797b5038d7SDag-Erling Smørgrav ldns_nsec3_salt_data(const ldns_rr *nsec3_rr) 12807b5038d7SDag-Erling Smørgrav { 12817b5038d7SDag-Erling Smørgrav uint8_t salt_length; 12827b5038d7SDag-Erling Smørgrav uint8_t *salt; 12837b5038d7SDag-Erling Smørgrav 12847b5038d7SDag-Erling Smørgrav ldns_rdf *salt_rdf = ldns_nsec3_salt(nsec3_rr); 12857b5038d7SDag-Erling Smørgrav if (salt_rdf && ldns_rdf_size(salt_rdf) > 0) { 12867b5038d7SDag-Erling Smørgrav salt_length = ldns_rdf_data(salt_rdf)[0]; 12877b5038d7SDag-Erling Smørgrav salt = LDNS_XMALLOC(uint8_t, salt_length); 12887b5038d7SDag-Erling Smørgrav if(!salt) return NULL; 12897b5038d7SDag-Erling Smørgrav memcpy(salt, &ldns_rdf_data(salt_rdf)[1], salt_length); 12907b5038d7SDag-Erling Smørgrav return salt; 12917b5038d7SDag-Erling Smørgrav } 12927b5038d7SDag-Erling Smørgrav return NULL; 12937b5038d7SDag-Erling Smørgrav } 12947b5038d7SDag-Erling Smørgrav 12957b5038d7SDag-Erling Smørgrav ldns_rdf * 12967b5038d7SDag-Erling Smørgrav ldns_nsec3_next_owner(const ldns_rr *nsec3_rr) 12977b5038d7SDag-Erling Smørgrav { 12987b5038d7SDag-Erling Smørgrav if (!nsec3_rr || ldns_rr_get_type(nsec3_rr) != LDNS_RR_TYPE_NSEC3) { 12997b5038d7SDag-Erling Smørgrav return NULL; 13007b5038d7SDag-Erling Smørgrav } else { 13017b5038d7SDag-Erling Smørgrav return ldns_rr_rdf(nsec3_rr, 4); 13027b5038d7SDag-Erling Smørgrav } 13037b5038d7SDag-Erling Smørgrav } 13047b5038d7SDag-Erling Smørgrav 13057b5038d7SDag-Erling Smørgrav ldns_rdf * 13067b5038d7SDag-Erling Smørgrav ldns_nsec3_bitmap(const ldns_rr *nsec3_rr) 13077b5038d7SDag-Erling Smørgrav { 13087b5038d7SDag-Erling Smørgrav if (!nsec3_rr || ldns_rr_get_type(nsec3_rr) != LDNS_RR_TYPE_NSEC3) { 13097b5038d7SDag-Erling Smørgrav return NULL; 13107b5038d7SDag-Erling Smørgrav } else { 13117b5038d7SDag-Erling Smørgrav return ldns_rr_rdf(nsec3_rr, 5); 13127b5038d7SDag-Erling Smørgrav } 13137b5038d7SDag-Erling Smørgrav } 13147b5038d7SDag-Erling Smørgrav 13157b5038d7SDag-Erling Smørgrav ldns_rdf * 13167b5038d7SDag-Erling Smørgrav ldns_nsec3_hash_name_frm_nsec3(const ldns_rr *nsec, ldns_rdf *name) 13177b5038d7SDag-Erling Smørgrav { 13187b5038d7SDag-Erling Smørgrav uint8_t algorithm; 13197b5038d7SDag-Erling Smørgrav uint16_t iterations; 13207b5038d7SDag-Erling Smørgrav uint8_t salt_length; 13217b5038d7SDag-Erling Smørgrav uint8_t *salt = 0; 13227b5038d7SDag-Erling Smørgrav 13237b5038d7SDag-Erling Smørgrav ldns_rdf *hashed_owner; 13247b5038d7SDag-Erling Smørgrav 13257b5038d7SDag-Erling Smørgrav algorithm = ldns_nsec3_algorithm(nsec); 13267b5038d7SDag-Erling Smørgrav salt_length = ldns_nsec3_salt_length(nsec); 13277b5038d7SDag-Erling Smørgrav salt = ldns_nsec3_salt_data(nsec); 13287b5038d7SDag-Erling Smørgrav iterations = ldns_nsec3_iterations(nsec); 13297b5038d7SDag-Erling Smørgrav 13307b5038d7SDag-Erling Smørgrav hashed_owner = ldns_nsec3_hash_name(name, 13317b5038d7SDag-Erling Smørgrav algorithm, 13327b5038d7SDag-Erling Smørgrav iterations, 13337b5038d7SDag-Erling Smørgrav salt_length, 13347b5038d7SDag-Erling Smørgrav salt); 13357b5038d7SDag-Erling Smørgrav 13367b5038d7SDag-Erling Smørgrav LDNS_FREE(salt); 13377b5038d7SDag-Erling Smørgrav return hashed_owner; 13387b5038d7SDag-Erling Smørgrav } 13397b5038d7SDag-Erling Smørgrav 13407b5038d7SDag-Erling Smørgrav bool 13417b5038d7SDag-Erling Smørgrav ldns_nsec_bitmap_covers_type(const ldns_rdf *nsec_bitmap, ldns_rr_type type) 13427b5038d7SDag-Erling Smørgrav { 13437b5038d7SDag-Erling Smørgrav uint8_t window_block_nr; 13447b5038d7SDag-Erling Smørgrav uint8_t bitmap_length; 13457b5038d7SDag-Erling Smørgrav uint16_t cur_type; 13467b5038d7SDag-Erling Smørgrav uint16_t pos = 0; 13477b5038d7SDag-Erling Smørgrav uint16_t bit_pos; 13487b5038d7SDag-Erling Smørgrav uint8_t *data; 13497b5038d7SDag-Erling Smørgrav 13507b5038d7SDag-Erling Smørgrav if (nsec_bitmap == NULL) { 13517b5038d7SDag-Erling Smørgrav return false; 13527b5038d7SDag-Erling Smørgrav } 13537b5038d7SDag-Erling Smørgrav data = ldns_rdf_data(nsec_bitmap); 13547b5038d7SDag-Erling Smørgrav while(pos < ldns_rdf_size(nsec_bitmap)) { 13557b5038d7SDag-Erling Smørgrav window_block_nr = data[pos]; 13567b5038d7SDag-Erling Smørgrav bitmap_length = data[pos + 1]; 13577b5038d7SDag-Erling Smørgrav pos += 2; 13587b5038d7SDag-Erling Smørgrav 13597b5038d7SDag-Erling Smørgrav for (bit_pos = 0; bit_pos < (bitmap_length) * 8; bit_pos++) { 13607b5038d7SDag-Erling Smørgrav if (ldns_get_bit(&data[pos], bit_pos)) { 13617b5038d7SDag-Erling Smørgrav cur_type = 256 * (uint16_t) window_block_nr + bit_pos; 13627b5038d7SDag-Erling Smørgrav if (cur_type == type) { 13637b5038d7SDag-Erling Smørgrav return true; 13647b5038d7SDag-Erling Smørgrav } 13657b5038d7SDag-Erling Smørgrav } 13667b5038d7SDag-Erling Smørgrav } 13677b5038d7SDag-Erling Smørgrav 13687b5038d7SDag-Erling Smørgrav pos += (uint16_t) bitmap_length; 13697b5038d7SDag-Erling Smørgrav } 13707b5038d7SDag-Erling Smørgrav return false; 13717b5038d7SDag-Erling Smørgrav } 13727b5038d7SDag-Erling Smørgrav 13737b5038d7SDag-Erling Smørgrav bool 13747b5038d7SDag-Erling Smørgrav ldns_nsec_covers_name(const ldns_rr *nsec, const ldns_rdf *name) 13757b5038d7SDag-Erling Smørgrav { 13767b5038d7SDag-Erling Smørgrav ldns_rdf *nsec_owner = ldns_rr_owner(nsec); 13777b5038d7SDag-Erling Smørgrav ldns_rdf *hash_next; 13787b5038d7SDag-Erling Smørgrav char *next_hash_str; 13797b5038d7SDag-Erling Smørgrav ldns_rdf *nsec_next = NULL; 13807b5038d7SDag-Erling Smørgrav ldns_status status; 13817b5038d7SDag-Erling Smørgrav ldns_rdf *chopped_dname; 13827b5038d7SDag-Erling Smørgrav bool result; 13837b5038d7SDag-Erling Smørgrav 13847b5038d7SDag-Erling Smørgrav if (ldns_rr_get_type(nsec) == LDNS_RR_TYPE_NSEC) { 13857b5038d7SDag-Erling Smørgrav if (ldns_rr_rdf(nsec, 0) != NULL) { 13867b5038d7SDag-Erling Smørgrav nsec_next = ldns_rdf_clone(ldns_rr_rdf(nsec, 0)); 13877b5038d7SDag-Erling Smørgrav } else { 13887b5038d7SDag-Erling Smørgrav return false; 13897b5038d7SDag-Erling Smørgrav } 13907b5038d7SDag-Erling Smørgrav } else if (ldns_rr_get_type(nsec) == LDNS_RR_TYPE_NSEC3) { 13917b5038d7SDag-Erling Smørgrav hash_next = ldns_nsec3_next_owner(nsec); 13927b5038d7SDag-Erling Smørgrav next_hash_str = ldns_rdf2str(hash_next); 13937b5038d7SDag-Erling Smørgrav nsec_next = ldns_dname_new_frm_str(next_hash_str); 13947b5038d7SDag-Erling Smørgrav LDNS_FREE(next_hash_str); 13957b5038d7SDag-Erling Smørgrav chopped_dname = ldns_dname_left_chop(nsec_owner); 13967b5038d7SDag-Erling Smørgrav status = ldns_dname_cat(nsec_next, chopped_dname); 13977b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(chopped_dname); 13987b5038d7SDag-Erling Smørgrav if (status != LDNS_STATUS_OK) { 13997b5038d7SDag-Erling Smørgrav printf("error catting: %s\n", ldns_get_errorstr_by_id(status)); 14007b5038d7SDag-Erling Smørgrav } 14017b5038d7SDag-Erling Smørgrav } else { 14027b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(nsec_next); 14037b5038d7SDag-Erling Smørgrav return false; 14047b5038d7SDag-Erling Smørgrav } 14057b5038d7SDag-Erling Smørgrav 14067b5038d7SDag-Erling Smørgrav /* in the case of the last nsec */ 14077b5038d7SDag-Erling Smørgrav if(ldns_dname_compare(nsec_owner, nsec_next) > 0) { 14087b5038d7SDag-Erling Smørgrav result = (ldns_dname_compare(nsec_owner, name) <= 0 || 14097b5038d7SDag-Erling Smørgrav ldns_dname_compare(name, nsec_next) < 0); 14107b5038d7SDag-Erling Smørgrav } else { 14117b5038d7SDag-Erling Smørgrav result = (ldns_dname_compare(nsec_owner, name) <= 0 && 14127b5038d7SDag-Erling Smørgrav ldns_dname_compare(name, nsec_next) < 0); 14137b5038d7SDag-Erling Smørgrav } 14147b5038d7SDag-Erling Smørgrav 14157b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(nsec_next); 14167b5038d7SDag-Erling Smørgrav return result; 14177b5038d7SDag-Erling Smørgrav } 14187b5038d7SDag-Erling Smørgrav 14197b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL 14207b5038d7SDag-Erling Smørgrav /* sig may be null - if so look in the packet */ 14217b5038d7SDag-Erling Smørgrav 14227b5038d7SDag-Erling Smørgrav ldns_status 14237b5038d7SDag-Erling Smørgrav ldns_pkt_verify_time(ldns_pkt *p, ldns_rr_type t, ldns_rdf *o, 14247b5038d7SDag-Erling Smørgrav ldns_rr_list *k, ldns_rr_list *s, 14257b5038d7SDag-Erling Smørgrav time_t check_time, ldns_rr_list *good_keys) 14267b5038d7SDag-Erling Smørgrav { 14277b5038d7SDag-Erling Smørgrav ldns_rr_list *rrset; 14287b5038d7SDag-Erling Smørgrav ldns_rr_list *sigs; 14297b5038d7SDag-Erling Smørgrav ldns_rr_list *sigs_covered; 14307b5038d7SDag-Erling Smørgrav ldns_rdf *rdf_t; 14317b5038d7SDag-Erling Smørgrav ldns_rr_type t_netorder; 14327b5038d7SDag-Erling Smørgrav 14337b5038d7SDag-Erling Smørgrav if (!k) { 14347b5038d7SDag-Erling Smørgrav return LDNS_STATUS_ERR; 14357b5038d7SDag-Erling Smørgrav /* return LDNS_STATUS_CRYPTO_NO_DNSKEY; */ 14367b5038d7SDag-Erling Smørgrav } 14377b5038d7SDag-Erling Smørgrav 14387b5038d7SDag-Erling Smørgrav if (t == LDNS_RR_TYPE_RRSIG) { 14397b5038d7SDag-Erling Smørgrav /* we don't have RRSIG(RRSIG) (yet? ;-) ) */ 14407b5038d7SDag-Erling Smørgrav return LDNS_STATUS_ERR; 14417b5038d7SDag-Erling Smørgrav } 14427b5038d7SDag-Erling Smørgrav 14437b5038d7SDag-Erling Smørgrav if (s) { 14447b5038d7SDag-Erling Smørgrav /* if s is not NULL, the sigs are given to use */ 14457b5038d7SDag-Erling Smørgrav sigs = s; 14467b5038d7SDag-Erling Smørgrav } else { 14477b5038d7SDag-Erling Smørgrav /* otherwise get them from the packet */ 1448*2787e39aSDag-Erling Smørgrav sigs = ldns_pkt_rr_list_by_name_and_type(p, o, 1449*2787e39aSDag-Erling Smørgrav LDNS_RR_TYPE_RRSIG, 14507b5038d7SDag-Erling Smørgrav LDNS_SECTION_ANY_NOQUESTION); 14517b5038d7SDag-Erling Smørgrav if (!sigs) { 14527b5038d7SDag-Erling Smørgrav /* no sigs */ 14537b5038d7SDag-Erling Smørgrav return LDNS_STATUS_ERR; 14547b5038d7SDag-Erling Smørgrav /* return LDNS_STATUS_CRYPTO_NO_RRSIG; */ 14557b5038d7SDag-Erling Smørgrav } 14567b5038d7SDag-Erling Smørgrav } 14577b5038d7SDag-Erling Smørgrav 14587b5038d7SDag-Erling Smørgrav /* rrsig are subtyped, so now we need to find the correct 14597b5038d7SDag-Erling Smørgrav * sigs for the type t 14607b5038d7SDag-Erling Smørgrav */ 14617b5038d7SDag-Erling Smørgrav t_netorder = htons(t); /* rdf are in network order! */ 14627b5038d7SDag-Erling Smørgrav /* a type identifier is a 16-bit number, so the size is 2 bytes */ 1463*2787e39aSDag-Erling Smørgrav rdf_t = ldns_rdf_new(LDNS_RDF_TYPE_TYPE, 2, &t_netorder); 1464*2787e39aSDag-Erling Smørgrav 14657b5038d7SDag-Erling Smørgrav sigs_covered = ldns_rr_list_subtype_by_rdf(sigs, rdf_t, 0); 1466*2787e39aSDag-Erling Smørgrav ldns_rdf_free(rdf_t); 14677b5038d7SDag-Erling Smørgrav if (! sigs_covered) { 1468*2787e39aSDag-Erling Smørgrav if (! s) { 1469*2787e39aSDag-Erling Smørgrav ldns_rr_list_deep_free(sigs); 1470*2787e39aSDag-Erling Smørgrav } 14717b5038d7SDag-Erling Smørgrav return LDNS_STATUS_ERR; 14727b5038d7SDag-Erling Smørgrav } 1473*2787e39aSDag-Erling Smørgrav ldns_rr_list_deep_free(sigs_covered); 14747b5038d7SDag-Erling Smørgrav 1475*2787e39aSDag-Erling Smørgrav rrset = ldns_pkt_rr_list_by_name_and_type(p, o, t, 1476*2787e39aSDag-Erling Smørgrav LDNS_SECTION_ANY_NOQUESTION); 1477*2787e39aSDag-Erling Smørgrav if (!rrset) { 1478*2787e39aSDag-Erling Smørgrav if (! s) { 1479*2787e39aSDag-Erling Smørgrav ldns_rr_list_deep_free(sigs); 1480*2787e39aSDag-Erling Smørgrav } 1481*2787e39aSDag-Erling Smørgrav return LDNS_STATUS_ERR; 1482*2787e39aSDag-Erling Smørgrav } 14837b5038d7SDag-Erling Smørgrav return ldns_verify_time(rrset, sigs, k, check_time, good_keys); 14847b5038d7SDag-Erling Smørgrav } 14857b5038d7SDag-Erling Smørgrav 14867b5038d7SDag-Erling Smørgrav ldns_status 14877b5038d7SDag-Erling Smørgrav ldns_pkt_verify(ldns_pkt *p, ldns_rr_type t, ldns_rdf *o, 14887b5038d7SDag-Erling Smørgrav ldns_rr_list *k, ldns_rr_list *s, ldns_rr_list *good_keys) 14897b5038d7SDag-Erling Smørgrav { 14907b5038d7SDag-Erling Smørgrav return ldns_pkt_verify_time(p, t, o, k, s, ldns_time(NULL), good_keys); 14917b5038d7SDag-Erling Smørgrav } 14927b5038d7SDag-Erling Smørgrav #endif /* HAVE_SSL */ 14937b5038d7SDag-Erling Smørgrav 14947b5038d7SDag-Erling Smørgrav ldns_status 14957b5038d7SDag-Erling Smørgrav ldns_dnssec_chain_nsec3_list(ldns_rr_list *nsec3_rrs) 14967b5038d7SDag-Erling Smørgrav { 14977b5038d7SDag-Erling Smørgrav size_t i; 14987b5038d7SDag-Erling Smørgrav char *next_nsec_owner_str; 14997b5038d7SDag-Erling Smørgrav ldns_rdf *next_nsec_owner_label; 15007b5038d7SDag-Erling Smørgrav ldns_rdf *next_nsec_rdf; 15017b5038d7SDag-Erling Smørgrav ldns_status status = LDNS_STATUS_OK; 15027b5038d7SDag-Erling Smørgrav 15037b5038d7SDag-Erling Smørgrav for (i = 0; i < ldns_rr_list_rr_count(nsec3_rrs); i++) { 15047b5038d7SDag-Erling Smørgrav if (i == ldns_rr_list_rr_count(nsec3_rrs) - 1) { 15057b5038d7SDag-Erling Smørgrav next_nsec_owner_label = 15067b5038d7SDag-Erling Smørgrav ldns_dname_label(ldns_rr_owner(ldns_rr_list_rr(nsec3_rrs, 15077b5038d7SDag-Erling Smørgrav 0)), 0); 15087b5038d7SDag-Erling Smørgrav next_nsec_owner_str = ldns_rdf2str(next_nsec_owner_label); 15097b5038d7SDag-Erling Smørgrav if (next_nsec_owner_str[strlen(next_nsec_owner_str) - 1] 15107b5038d7SDag-Erling Smørgrav == '.') { 15117b5038d7SDag-Erling Smørgrav next_nsec_owner_str[strlen(next_nsec_owner_str) - 1] 15127b5038d7SDag-Erling Smørgrav = '\0'; 15137b5038d7SDag-Erling Smørgrav } 15147b5038d7SDag-Erling Smørgrav status = ldns_str2rdf_b32_ext(&next_nsec_rdf, 15157b5038d7SDag-Erling Smørgrav next_nsec_owner_str); 15167b5038d7SDag-Erling Smørgrav if (!ldns_rr_set_rdf(ldns_rr_list_rr(nsec3_rrs, i), 15177b5038d7SDag-Erling Smørgrav next_nsec_rdf, 4)) { 15187b5038d7SDag-Erling Smørgrav /* todo: error */ 15197b5038d7SDag-Erling Smørgrav } 15207b5038d7SDag-Erling Smørgrav 15217b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(next_nsec_owner_label); 15227b5038d7SDag-Erling Smørgrav LDNS_FREE(next_nsec_owner_str); 15237b5038d7SDag-Erling Smørgrav } else { 15247b5038d7SDag-Erling Smørgrav next_nsec_owner_label = 15257b5038d7SDag-Erling Smørgrav ldns_dname_label(ldns_rr_owner(ldns_rr_list_rr(nsec3_rrs, 15267b5038d7SDag-Erling Smørgrav i + 1)), 15277b5038d7SDag-Erling Smørgrav 0); 15287b5038d7SDag-Erling Smørgrav next_nsec_owner_str = ldns_rdf2str(next_nsec_owner_label); 15297b5038d7SDag-Erling Smørgrav if (next_nsec_owner_str[strlen(next_nsec_owner_str) - 1] 15307b5038d7SDag-Erling Smørgrav == '.') { 15317b5038d7SDag-Erling Smørgrav next_nsec_owner_str[strlen(next_nsec_owner_str) - 1] 15327b5038d7SDag-Erling Smørgrav = '\0'; 15337b5038d7SDag-Erling Smørgrav } 15347b5038d7SDag-Erling Smørgrav status = ldns_str2rdf_b32_ext(&next_nsec_rdf, 15357b5038d7SDag-Erling Smørgrav next_nsec_owner_str); 15367b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(next_nsec_owner_label); 15377b5038d7SDag-Erling Smørgrav LDNS_FREE(next_nsec_owner_str); 15387b5038d7SDag-Erling Smørgrav if (!ldns_rr_set_rdf(ldns_rr_list_rr(nsec3_rrs, i), 15397b5038d7SDag-Erling Smørgrav next_nsec_rdf, 4)) { 15407b5038d7SDag-Erling Smørgrav /* todo: error */ 15417b5038d7SDag-Erling Smørgrav } 15427b5038d7SDag-Erling Smørgrav } 15437b5038d7SDag-Erling Smørgrav } 15447b5038d7SDag-Erling Smørgrav return status; 15457b5038d7SDag-Erling Smørgrav } 15467b5038d7SDag-Erling Smørgrav 15477b5038d7SDag-Erling Smørgrav int 15487b5038d7SDag-Erling Smørgrav qsort_rr_compare_nsec3(const void *a, const void *b) 15497b5038d7SDag-Erling Smørgrav { 15507b5038d7SDag-Erling Smørgrav const ldns_rr *rr1 = * (const ldns_rr **) a; 15517b5038d7SDag-Erling Smørgrav const ldns_rr *rr2 = * (const ldns_rr **) b; 15527b5038d7SDag-Erling Smørgrav if (rr1 == NULL && rr2 == NULL) { 15537b5038d7SDag-Erling Smørgrav return 0; 15547b5038d7SDag-Erling Smørgrav } 15557b5038d7SDag-Erling Smørgrav if (rr1 == NULL) { 15567b5038d7SDag-Erling Smørgrav return -1; 15577b5038d7SDag-Erling Smørgrav } 15587b5038d7SDag-Erling Smørgrav if (rr2 == NULL) { 15597b5038d7SDag-Erling Smørgrav return 1; 15607b5038d7SDag-Erling Smørgrav } 15617b5038d7SDag-Erling Smørgrav return ldns_rdf_compare(ldns_rr_owner(rr1), ldns_rr_owner(rr2)); 15627b5038d7SDag-Erling Smørgrav } 15637b5038d7SDag-Erling Smørgrav 15647b5038d7SDag-Erling Smørgrav void 15657b5038d7SDag-Erling Smørgrav ldns_rr_list_sort_nsec3(ldns_rr_list *unsorted) 15667b5038d7SDag-Erling Smørgrav { 15677b5038d7SDag-Erling Smørgrav qsort(unsorted->_rrs, 15687b5038d7SDag-Erling Smørgrav ldns_rr_list_rr_count(unsorted), 15697b5038d7SDag-Erling Smørgrav sizeof(ldns_rr *), 15707b5038d7SDag-Erling Smørgrav qsort_rr_compare_nsec3); 15717b5038d7SDag-Erling Smørgrav } 15727b5038d7SDag-Erling Smørgrav 15737b5038d7SDag-Erling Smørgrav int 15747b5038d7SDag-Erling Smørgrav ldns_dnssec_default_add_to_signatures( ATTR_UNUSED(ldns_rr *sig) 15757b5038d7SDag-Erling Smørgrav , ATTR_UNUSED(void *n) 15767b5038d7SDag-Erling Smørgrav ) 15777b5038d7SDag-Erling Smørgrav { 15787b5038d7SDag-Erling Smørgrav return LDNS_SIGNATURE_LEAVE_ADD_NEW; 15797b5038d7SDag-Erling Smørgrav } 15807b5038d7SDag-Erling Smørgrav 15817b5038d7SDag-Erling Smørgrav int 15827b5038d7SDag-Erling Smørgrav ldns_dnssec_default_leave_signatures( ATTR_UNUSED(ldns_rr *sig) 15837b5038d7SDag-Erling Smørgrav , ATTR_UNUSED(void *n) 15847b5038d7SDag-Erling Smørgrav ) 15857b5038d7SDag-Erling Smørgrav { 15867b5038d7SDag-Erling Smørgrav return LDNS_SIGNATURE_LEAVE_NO_ADD; 15877b5038d7SDag-Erling Smørgrav } 15887b5038d7SDag-Erling Smørgrav 15897b5038d7SDag-Erling Smørgrav int 15907b5038d7SDag-Erling Smørgrav ldns_dnssec_default_delete_signatures( ATTR_UNUSED(ldns_rr *sig) 15917b5038d7SDag-Erling Smørgrav , ATTR_UNUSED(void *n) 15927b5038d7SDag-Erling Smørgrav ) 15937b5038d7SDag-Erling Smørgrav { 15947b5038d7SDag-Erling Smørgrav return LDNS_SIGNATURE_REMOVE_NO_ADD; 15957b5038d7SDag-Erling Smørgrav } 15967b5038d7SDag-Erling Smørgrav 15977b5038d7SDag-Erling Smørgrav int 15987b5038d7SDag-Erling Smørgrav ldns_dnssec_default_replace_signatures( ATTR_UNUSED(ldns_rr *sig) 15997b5038d7SDag-Erling Smørgrav , ATTR_UNUSED(void *n) 16007b5038d7SDag-Erling Smørgrav ) 16017b5038d7SDag-Erling Smørgrav { 16027b5038d7SDag-Erling Smørgrav return LDNS_SIGNATURE_REMOVE_ADD_NEW; 16037b5038d7SDag-Erling Smørgrav } 16047b5038d7SDag-Erling Smørgrav 16057b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL 16067b5038d7SDag-Erling Smørgrav ldns_rdf * 16077b5038d7SDag-Erling Smørgrav ldns_convert_dsa_rrsig_asn12rdf(const ldns_buffer *sig, 16087b5038d7SDag-Erling Smørgrav const long sig_len) 16097b5038d7SDag-Erling Smørgrav { 16107b5038d7SDag-Erling Smørgrav ldns_rdf *sigdata_rdf; 16117b5038d7SDag-Erling Smørgrav DSA_SIG *dsasig; 16127b5038d7SDag-Erling Smørgrav unsigned char *dsasig_data = (unsigned char*)ldns_buffer_begin(sig); 16137b5038d7SDag-Erling Smørgrav size_t byte_offset; 16147b5038d7SDag-Erling Smørgrav 16157b5038d7SDag-Erling Smørgrav dsasig = d2i_DSA_SIG(NULL, 16167b5038d7SDag-Erling Smørgrav (const unsigned char **)&dsasig_data, 16177b5038d7SDag-Erling Smørgrav sig_len); 16187b5038d7SDag-Erling Smørgrav if (!dsasig) { 16197b5038d7SDag-Erling Smørgrav DSA_SIG_free(dsasig); 16207b5038d7SDag-Erling Smørgrav return NULL; 16217b5038d7SDag-Erling Smørgrav } 16227b5038d7SDag-Erling Smørgrav 16237b5038d7SDag-Erling Smørgrav dsasig_data = LDNS_XMALLOC(unsigned char, 41); 16247b5038d7SDag-Erling Smørgrav if(!dsasig_data) { 16257b5038d7SDag-Erling Smørgrav DSA_SIG_free(dsasig); 16267b5038d7SDag-Erling Smørgrav return NULL; 16277b5038d7SDag-Erling Smørgrav } 16287b5038d7SDag-Erling Smørgrav dsasig_data[0] = 0; 16297b5038d7SDag-Erling Smørgrav byte_offset = (size_t) (20 - BN_num_bytes(dsasig->r)); 16307b5038d7SDag-Erling Smørgrav if (byte_offset > 20) { 16317b5038d7SDag-Erling Smørgrav DSA_SIG_free(dsasig); 16327b5038d7SDag-Erling Smørgrav LDNS_FREE(dsasig_data); 16337b5038d7SDag-Erling Smørgrav return NULL; 16347b5038d7SDag-Erling Smørgrav } 16357b5038d7SDag-Erling Smørgrav memset(&dsasig_data[1], 0, byte_offset); 16367b5038d7SDag-Erling Smørgrav BN_bn2bin(dsasig->r, &dsasig_data[1 + byte_offset]); 16377b5038d7SDag-Erling Smørgrav byte_offset = (size_t) (20 - BN_num_bytes(dsasig->s)); 16387b5038d7SDag-Erling Smørgrav if (byte_offset > 20) { 16397b5038d7SDag-Erling Smørgrav DSA_SIG_free(dsasig); 16407b5038d7SDag-Erling Smørgrav LDNS_FREE(dsasig_data); 16417b5038d7SDag-Erling Smørgrav return NULL; 16427b5038d7SDag-Erling Smørgrav } 16437b5038d7SDag-Erling Smørgrav memset(&dsasig_data[21], 0, byte_offset); 16447b5038d7SDag-Erling Smørgrav BN_bn2bin(dsasig->s, &dsasig_data[21 + byte_offset]); 16457b5038d7SDag-Erling Smørgrav 16467b5038d7SDag-Erling Smørgrav sigdata_rdf = ldns_rdf_new(LDNS_RDF_TYPE_B64, 41, dsasig_data); 16477b5038d7SDag-Erling Smørgrav if(!sigdata_rdf) { 16487b5038d7SDag-Erling Smørgrav LDNS_FREE(dsasig_data); 16497b5038d7SDag-Erling Smørgrav } 16507b5038d7SDag-Erling Smørgrav DSA_SIG_free(dsasig); 16517b5038d7SDag-Erling Smørgrav 16527b5038d7SDag-Erling Smørgrav return sigdata_rdf; 16537b5038d7SDag-Erling Smørgrav } 16547b5038d7SDag-Erling Smørgrav 16557b5038d7SDag-Erling Smørgrav ldns_status 16567b5038d7SDag-Erling Smørgrav ldns_convert_dsa_rrsig_rdf2asn1(ldns_buffer *target_buffer, 16577b5038d7SDag-Erling Smørgrav const ldns_rdf *sig_rdf) 16587b5038d7SDag-Erling Smørgrav { 16597b5038d7SDag-Erling Smørgrav /* the EVP api wants the DER encoding of the signature... */ 16607b5038d7SDag-Erling Smørgrav BIGNUM *R, *S; 16617b5038d7SDag-Erling Smørgrav DSA_SIG *dsasig; 16627b5038d7SDag-Erling Smørgrav unsigned char *raw_sig = NULL; 16637b5038d7SDag-Erling Smørgrav int raw_sig_len; 16647b5038d7SDag-Erling Smørgrav 16657b5038d7SDag-Erling Smørgrav if(ldns_rdf_size(sig_rdf) < 1 + 2*SHA_DIGEST_LENGTH) 16667b5038d7SDag-Erling Smørgrav return LDNS_STATUS_SYNTAX_RDATA_ERR; 16677b5038d7SDag-Erling Smørgrav /* extract the R and S field from the sig buffer */ 16687b5038d7SDag-Erling Smørgrav R = BN_new(); 16697b5038d7SDag-Erling Smørgrav if(!R) return LDNS_STATUS_MEM_ERR; 16707b5038d7SDag-Erling Smørgrav (void) BN_bin2bn((unsigned char *) ldns_rdf_data(sig_rdf) + 1, 16717b5038d7SDag-Erling Smørgrav SHA_DIGEST_LENGTH, R); 16727b5038d7SDag-Erling Smørgrav S = BN_new(); 16737b5038d7SDag-Erling Smørgrav if(!S) { 16747b5038d7SDag-Erling Smørgrav BN_free(R); 16757b5038d7SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR; 16767b5038d7SDag-Erling Smørgrav } 16777b5038d7SDag-Erling Smørgrav (void) BN_bin2bn((unsigned char *) ldns_rdf_data(sig_rdf) + 21, 16787b5038d7SDag-Erling Smørgrav SHA_DIGEST_LENGTH, S); 16797b5038d7SDag-Erling Smørgrav 16807b5038d7SDag-Erling Smørgrav dsasig = DSA_SIG_new(); 16817b5038d7SDag-Erling Smørgrav if (!dsasig) { 16827b5038d7SDag-Erling Smørgrav BN_free(R); 16837b5038d7SDag-Erling Smørgrav BN_free(S); 16847b5038d7SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR; 16857b5038d7SDag-Erling Smørgrav } 16867b5038d7SDag-Erling Smørgrav 16877b5038d7SDag-Erling Smørgrav dsasig->r = R; 16887b5038d7SDag-Erling Smørgrav dsasig->s = S; 16897b5038d7SDag-Erling Smørgrav 16907b5038d7SDag-Erling Smørgrav raw_sig_len = i2d_DSA_SIG(dsasig, &raw_sig); 16917b5038d7SDag-Erling Smørgrav if (raw_sig_len < 0) { 16927b5038d7SDag-Erling Smørgrav DSA_SIG_free(dsasig); 16937b5038d7SDag-Erling Smørgrav free(raw_sig); 16947b5038d7SDag-Erling Smørgrav return LDNS_STATUS_SSL_ERR; 16957b5038d7SDag-Erling Smørgrav } 16967b5038d7SDag-Erling Smørgrav if (ldns_buffer_reserve(target_buffer, (size_t) raw_sig_len)) { 16977b5038d7SDag-Erling Smørgrav ldns_buffer_write(target_buffer, raw_sig, (size_t)raw_sig_len); 16987b5038d7SDag-Erling Smørgrav } 16997b5038d7SDag-Erling Smørgrav 17007b5038d7SDag-Erling Smørgrav DSA_SIG_free(dsasig); 17017b5038d7SDag-Erling Smørgrav free(raw_sig); 17027b5038d7SDag-Erling Smørgrav 17037b5038d7SDag-Erling Smørgrav return ldns_buffer_status(target_buffer); 17047b5038d7SDag-Erling Smørgrav } 17057b5038d7SDag-Erling Smørgrav 17067b5038d7SDag-Erling Smørgrav #ifdef USE_ECDSA 17077b5038d7SDag-Erling Smørgrav #ifndef S_SPLINT_S 17087b5038d7SDag-Erling Smørgrav ldns_rdf * 17097b5038d7SDag-Erling Smørgrav ldns_convert_ecdsa_rrsig_asn12rdf(const ldns_buffer *sig, const long sig_len) 17107b5038d7SDag-Erling Smørgrav { 17117b5038d7SDag-Erling Smørgrav ECDSA_SIG* ecdsa_sig; 17127b5038d7SDag-Erling Smørgrav unsigned char *data = (unsigned char*)ldns_buffer_begin(sig); 17137b5038d7SDag-Erling Smørgrav ldns_rdf* rdf; 17147b5038d7SDag-Erling Smørgrav ecdsa_sig = d2i_ECDSA_SIG(NULL, (const unsigned char **)&data, sig_len); 17157b5038d7SDag-Erling Smørgrav if(!ecdsa_sig) return NULL; 17167b5038d7SDag-Erling Smørgrav 17177b5038d7SDag-Erling Smørgrav /* "r | s". */ 17187b5038d7SDag-Erling Smørgrav data = LDNS_XMALLOC(unsigned char, 17197b5038d7SDag-Erling Smørgrav BN_num_bytes(ecdsa_sig->r) + BN_num_bytes(ecdsa_sig->s)); 17207b5038d7SDag-Erling Smørgrav if(!data) { 17217b5038d7SDag-Erling Smørgrav ECDSA_SIG_free(ecdsa_sig); 17227b5038d7SDag-Erling Smørgrav return NULL; 17237b5038d7SDag-Erling Smørgrav } 17247b5038d7SDag-Erling Smørgrav BN_bn2bin(ecdsa_sig->r, data); 17257b5038d7SDag-Erling Smørgrav BN_bn2bin(ecdsa_sig->s, data+BN_num_bytes(ecdsa_sig->r)); 17267b5038d7SDag-Erling Smørgrav rdf = ldns_rdf_new(LDNS_RDF_TYPE_B64, (size_t)( 17277b5038d7SDag-Erling Smørgrav BN_num_bytes(ecdsa_sig->r) + BN_num_bytes(ecdsa_sig->s)), data); 17287b5038d7SDag-Erling Smørgrav ECDSA_SIG_free(ecdsa_sig); 17297b5038d7SDag-Erling Smørgrav return rdf; 17307b5038d7SDag-Erling Smørgrav } 17317b5038d7SDag-Erling Smørgrav 17327b5038d7SDag-Erling Smørgrav ldns_status 17337b5038d7SDag-Erling Smørgrav ldns_convert_ecdsa_rrsig_rdf2asn1(ldns_buffer *target_buffer, 17347b5038d7SDag-Erling Smørgrav const ldns_rdf *sig_rdf) 17357b5038d7SDag-Erling Smørgrav { 17367b5038d7SDag-Erling Smørgrav ECDSA_SIG* sig; 17377b5038d7SDag-Erling Smørgrav int raw_sig_len; 17387b5038d7SDag-Erling Smørgrav long bnsize = (long)ldns_rdf_size(sig_rdf) / 2; 17397b5038d7SDag-Erling Smørgrav /* if too short, or not even length, do not bother */ 17407b5038d7SDag-Erling Smørgrav if(bnsize < 16 || (size_t)bnsize*2 != ldns_rdf_size(sig_rdf)) 17417b5038d7SDag-Erling Smørgrav return LDNS_STATUS_ERR; 17427b5038d7SDag-Erling Smørgrav 17437b5038d7SDag-Erling Smørgrav /* use the raw data to parse two evenly long BIGNUMs, "r | s". */ 17447b5038d7SDag-Erling Smørgrav sig = ECDSA_SIG_new(); 17457b5038d7SDag-Erling Smørgrav if(!sig) return LDNS_STATUS_MEM_ERR; 17467b5038d7SDag-Erling Smørgrav sig->r = BN_bin2bn((const unsigned char*)ldns_rdf_data(sig_rdf), 17477b5038d7SDag-Erling Smørgrav bnsize, sig->r); 17487b5038d7SDag-Erling Smørgrav sig->s = BN_bin2bn((const unsigned char*)ldns_rdf_data(sig_rdf)+bnsize, 17497b5038d7SDag-Erling Smørgrav bnsize, sig->s); 17507b5038d7SDag-Erling Smørgrav if(!sig->r || !sig->s) { 17517b5038d7SDag-Erling Smørgrav ECDSA_SIG_free(sig); 17527b5038d7SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR; 17537b5038d7SDag-Erling Smørgrav } 17547b5038d7SDag-Erling Smørgrav 17557b5038d7SDag-Erling Smørgrav raw_sig_len = i2d_ECDSA_SIG(sig, NULL); 17567b5038d7SDag-Erling Smørgrav if (ldns_buffer_reserve(target_buffer, (size_t) raw_sig_len)) { 17577b5038d7SDag-Erling Smørgrav unsigned char* pp = (unsigned char*) 17587b5038d7SDag-Erling Smørgrav ldns_buffer_current(target_buffer); 17597b5038d7SDag-Erling Smørgrav raw_sig_len = i2d_ECDSA_SIG(sig, &pp); 17607b5038d7SDag-Erling Smørgrav ldns_buffer_skip(target_buffer, (ssize_t) raw_sig_len); 17617b5038d7SDag-Erling Smørgrav } 17627b5038d7SDag-Erling Smørgrav ECDSA_SIG_free(sig); 17637b5038d7SDag-Erling Smørgrav 17647b5038d7SDag-Erling Smørgrav return ldns_buffer_status(target_buffer); 17657b5038d7SDag-Erling Smørgrav } 17667b5038d7SDag-Erling Smørgrav 17677b5038d7SDag-Erling Smørgrav #endif /* S_SPLINT_S */ 17687b5038d7SDag-Erling Smørgrav #endif /* USE_ECDSA */ 17697b5038d7SDag-Erling Smørgrav #endif /* HAVE_SSL */ 1770