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 * 84*986ba33cSDag-Erling Smørgrav ldns_nsec_get_bitmap(const 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 * 97*986ba33cSDag-Erling Smørgrav ldns_dnssec_nsec3_closest_encloser(const ldns_rdf *qname, 987b5038d7SDag-Erling Smørgrav ATTR_UNUSED(ldns_rr_type qtype), 99*986ba33cSDag-Erling Smørgrav const 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, 218*986ba33cSDag-Erling Smørgrav const 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 301*986ba33cSDag-Erling Smørgrav uint16_t ldns_calc_keytag_raw(const 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 * 330*986ba33cSDag-Erling Smørgrav ldns_key_buf2dsa(const ldns_buffer *key) 3317b5038d7SDag-Erling Smørgrav { 332*986ba33cSDag-Erling Smørgrav return ldns_key_buf2dsa_raw((const 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 * 337*986ba33cSDag-Erling Smørgrav ldns_key_buf2dsa_raw(const 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 } 378*986ba33cSDag-Erling Smørgrav #if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL) 3797b5038d7SDag-Erling Smørgrav #ifndef S_SPLINT_S 3807b5038d7SDag-Erling Smørgrav dsa->p = P; 3817b5038d7SDag-Erling Smørgrav dsa->q = Q; 3827b5038d7SDag-Erling Smørgrav dsa->g = G; 3837b5038d7SDag-Erling Smørgrav dsa->pub_key = Y; 3847b5038d7SDag-Erling Smørgrav #endif /* splint */ 385*986ba33cSDag-Erling Smørgrav #else /* OPENSSL_VERSION_NUMBER */ 386*986ba33cSDag-Erling Smørgrav if (!DSA_set0_pqg(dsa, P, Q, G)) { 387*986ba33cSDag-Erling Smørgrav /* QPG not yet attached, need to free */ 388*986ba33cSDag-Erling Smørgrav BN_free(Q); 389*986ba33cSDag-Erling Smørgrav BN_free(P); 390*986ba33cSDag-Erling Smørgrav BN_free(G); 3917b5038d7SDag-Erling Smørgrav 392*986ba33cSDag-Erling Smørgrav DSA_free(dsa); 393*986ba33cSDag-Erling Smørgrav BN_free(Y); 394*986ba33cSDag-Erling Smørgrav return NULL; 395*986ba33cSDag-Erling Smørgrav } 396*986ba33cSDag-Erling Smørgrav if (!DSA_set0_key(dsa, Y, NULL)) { 397*986ba33cSDag-Erling Smørgrav /* QPG attached, cleaned up by DSA_fre() */ 398*986ba33cSDag-Erling Smørgrav DSA_free(dsa); 399*986ba33cSDag-Erling Smørgrav BN_free(Y); 400*986ba33cSDag-Erling Smørgrav return NULL; 401*986ba33cSDag-Erling Smørgrav } 402*986ba33cSDag-Erling Smørgrav #endif /* OPENSSL_VERSION_NUMBER */ 4037b5038d7SDag-Erling Smørgrav return dsa; 4047b5038d7SDag-Erling Smørgrav } 4057b5038d7SDag-Erling Smørgrav 4067b5038d7SDag-Erling Smørgrav RSA * 407*986ba33cSDag-Erling Smørgrav ldns_key_buf2rsa(const ldns_buffer *key) 4087b5038d7SDag-Erling Smørgrav { 409*986ba33cSDag-Erling Smørgrav return ldns_key_buf2rsa_raw((const unsigned char*)ldns_buffer_begin(key), 4107b5038d7SDag-Erling Smørgrav ldns_buffer_position(key)); 4117b5038d7SDag-Erling Smørgrav } 4127b5038d7SDag-Erling Smørgrav 4137b5038d7SDag-Erling Smørgrav RSA * 414*986ba33cSDag-Erling Smørgrav ldns_key_buf2rsa_raw(const unsigned char* key, size_t len) 4157b5038d7SDag-Erling Smørgrav { 4167b5038d7SDag-Erling Smørgrav uint16_t offset; 4177b5038d7SDag-Erling Smørgrav uint16_t exp; 4187b5038d7SDag-Erling Smørgrav uint16_t int16; 4197b5038d7SDag-Erling Smørgrav RSA *rsa; 4207b5038d7SDag-Erling Smørgrav BIGNUM *modulus; 4217b5038d7SDag-Erling Smørgrav BIGNUM *exponent; 4227b5038d7SDag-Erling Smørgrav 4237b5038d7SDag-Erling Smørgrav if (len == 0) 4247b5038d7SDag-Erling Smørgrav return NULL; 4257b5038d7SDag-Erling Smørgrav if (key[0] == 0) { 4267b5038d7SDag-Erling Smørgrav if(len < 3) 4277b5038d7SDag-Erling Smørgrav return NULL; 4287b5038d7SDag-Erling Smørgrav /* need some smart comment here XXX*/ 4297b5038d7SDag-Erling Smørgrav /* the exponent is too large so it's places 4307b5038d7SDag-Erling Smørgrav * futher...???? */ 4317b5038d7SDag-Erling Smørgrav memmove(&int16, key+1, 2); 4327b5038d7SDag-Erling Smørgrav exp = ntohs(int16); 4337b5038d7SDag-Erling Smørgrav offset = 3; 4347b5038d7SDag-Erling Smørgrav } else { 4357b5038d7SDag-Erling Smørgrav exp = key[0]; 4367b5038d7SDag-Erling Smørgrav offset = 1; 4377b5038d7SDag-Erling Smørgrav } 4387b5038d7SDag-Erling Smørgrav 4397b5038d7SDag-Erling Smørgrav /* key length at least one */ 4407b5038d7SDag-Erling Smørgrav if(len < (size_t)offset + exp + 1) 4417b5038d7SDag-Erling Smørgrav return NULL; 4427b5038d7SDag-Erling Smørgrav 4437b5038d7SDag-Erling Smørgrav /* Exponent */ 4447b5038d7SDag-Erling Smørgrav exponent = BN_new(); 4457b5038d7SDag-Erling Smørgrav if(!exponent) return NULL; 4467b5038d7SDag-Erling Smørgrav (void) BN_bin2bn(key+offset, (int)exp, exponent); 4477b5038d7SDag-Erling Smørgrav offset += exp; 4487b5038d7SDag-Erling Smørgrav 4497b5038d7SDag-Erling Smørgrav /* Modulus */ 4507b5038d7SDag-Erling Smørgrav modulus = BN_new(); 4517b5038d7SDag-Erling Smørgrav if(!modulus) { 4527b5038d7SDag-Erling Smørgrav BN_free(exponent); 4537b5038d7SDag-Erling Smørgrav return NULL; 4547b5038d7SDag-Erling Smørgrav } 4557b5038d7SDag-Erling Smørgrav /* length of the buffer must match the key length! */ 4567b5038d7SDag-Erling Smørgrav (void) BN_bin2bn(key+offset, (int)(len - offset), modulus); 4577b5038d7SDag-Erling Smørgrav 4587b5038d7SDag-Erling Smørgrav rsa = RSA_new(); 4597b5038d7SDag-Erling Smørgrav if(!rsa) { 4607b5038d7SDag-Erling Smørgrav BN_free(exponent); 4617b5038d7SDag-Erling Smørgrav BN_free(modulus); 4627b5038d7SDag-Erling Smørgrav return NULL; 4637b5038d7SDag-Erling Smørgrav } 464*986ba33cSDag-Erling Smørgrav #if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL) 4657b5038d7SDag-Erling Smørgrav #ifndef S_SPLINT_S 4667b5038d7SDag-Erling Smørgrav rsa->n = modulus; 4677b5038d7SDag-Erling Smørgrav rsa->e = exponent; 4687b5038d7SDag-Erling Smørgrav #endif /* splint */ 469*986ba33cSDag-Erling Smørgrav #else /* OPENSSL_VERSION_NUMBER */ 470*986ba33cSDag-Erling Smørgrav if (!RSA_set0_key(rsa, modulus, exponent, NULL)) { 471*986ba33cSDag-Erling Smørgrav BN_free(exponent); 472*986ba33cSDag-Erling Smørgrav BN_free(modulus); 473*986ba33cSDag-Erling Smørgrav RSA_free(rsa); 474*986ba33cSDag-Erling Smørgrav return NULL; 475*986ba33cSDag-Erling Smørgrav } 476*986ba33cSDag-Erling Smørgrav #endif /* OPENSSL_VERSION_NUMBER */ 4777b5038d7SDag-Erling Smørgrav 4787b5038d7SDag-Erling Smørgrav return rsa; 4797b5038d7SDag-Erling Smørgrav } 4807b5038d7SDag-Erling Smørgrav 4817b5038d7SDag-Erling Smørgrav int 482*986ba33cSDag-Erling Smørgrav ldns_digest_evp(const unsigned char* data, unsigned int len, unsigned char* dest, 4837b5038d7SDag-Erling Smørgrav const EVP_MD* md) 4847b5038d7SDag-Erling Smørgrav { 4857b5038d7SDag-Erling Smørgrav EVP_MD_CTX* ctx; 4867b5038d7SDag-Erling Smørgrav ctx = EVP_MD_CTX_create(); 4877b5038d7SDag-Erling Smørgrav if(!ctx) 4887b5038d7SDag-Erling Smørgrav return false; 4897b5038d7SDag-Erling Smørgrav if(!EVP_DigestInit_ex(ctx, md, NULL) || 4907b5038d7SDag-Erling Smørgrav !EVP_DigestUpdate(ctx, data, len) || 4917b5038d7SDag-Erling Smørgrav !EVP_DigestFinal_ex(ctx, dest, NULL)) { 4927b5038d7SDag-Erling Smørgrav EVP_MD_CTX_destroy(ctx); 4937b5038d7SDag-Erling Smørgrav return false; 4947b5038d7SDag-Erling Smørgrav } 4957b5038d7SDag-Erling Smørgrav EVP_MD_CTX_destroy(ctx); 4967b5038d7SDag-Erling Smørgrav return true; 4977b5038d7SDag-Erling Smørgrav } 4987b5038d7SDag-Erling Smørgrav #endif /* HAVE_SSL */ 4997b5038d7SDag-Erling Smørgrav 5007b5038d7SDag-Erling Smørgrav ldns_rr * 5017b5038d7SDag-Erling Smørgrav ldns_key_rr2ds(const ldns_rr *key, ldns_hash h) 5027b5038d7SDag-Erling Smørgrav { 5037b5038d7SDag-Erling Smørgrav ldns_rdf *tmp; 5047b5038d7SDag-Erling Smørgrav ldns_rr *ds; 5057b5038d7SDag-Erling Smørgrav uint16_t keytag; 5067b5038d7SDag-Erling Smørgrav uint8_t sha1hash; 5077b5038d7SDag-Erling Smørgrav uint8_t *digest; 5087b5038d7SDag-Erling Smørgrav ldns_buffer *data_buf; 5097b5038d7SDag-Erling Smørgrav #ifdef USE_GOST 5107b5038d7SDag-Erling Smørgrav const EVP_MD* md = NULL; 5117b5038d7SDag-Erling Smørgrav #endif 5127b5038d7SDag-Erling Smørgrav 5137b5038d7SDag-Erling Smørgrav if (ldns_rr_get_type(key) != LDNS_RR_TYPE_DNSKEY) { 5147b5038d7SDag-Erling Smørgrav return NULL; 5157b5038d7SDag-Erling Smørgrav } 5167b5038d7SDag-Erling Smørgrav 5177b5038d7SDag-Erling Smørgrav ds = ldns_rr_new(); 5187b5038d7SDag-Erling Smørgrav if (!ds) { 5197b5038d7SDag-Erling Smørgrav return NULL; 5207b5038d7SDag-Erling Smørgrav } 5217b5038d7SDag-Erling Smørgrav ldns_rr_set_type(ds, LDNS_RR_TYPE_DS); 5227b5038d7SDag-Erling Smørgrav ldns_rr_set_owner(ds, ldns_rdf_clone( 5237b5038d7SDag-Erling Smørgrav ldns_rr_owner(key))); 5247b5038d7SDag-Erling Smørgrav ldns_rr_set_ttl(ds, ldns_rr_ttl(key)); 5257b5038d7SDag-Erling Smørgrav ldns_rr_set_class(ds, ldns_rr_get_class(key)); 5267b5038d7SDag-Erling Smørgrav 5277b5038d7SDag-Erling Smørgrav switch(h) { 5287b5038d7SDag-Erling Smørgrav default: 5297b5038d7SDag-Erling Smørgrav case LDNS_SHA1: 5307b5038d7SDag-Erling Smørgrav digest = LDNS_XMALLOC(uint8_t, LDNS_SHA1_DIGEST_LENGTH); 5317b5038d7SDag-Erling Smørgrav if (!digest) { 5327b5038d7SDag-Erling Smørgrav ldns_rr_free(ds); 5337b5038d7SDag-Erling Smørgrav return NULL; 5347b5038d7SDag-Erling Smørgrav } 5357b5038d7SDag-Erling Smørgrav break; 5367b5038d7SDag-Erling Smørgrav case LDNS_SHA256: 5377b5038d7SDag-Erling Smørgrav digest = LDNS_XMALLOC(uint8_t, LDNS_SHA256_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 case LDNS_HASH_GOST: 5447b5038d7SDag-Erling Smørgrav #ifdef USE_GOST 5457b5038d7SDag-Erling Smørgrav (void)ldns_key_EVP_load_gost_id(); 5467b5038d7SDag-Erling Smørgrav md = EVP_get_digestbyname("md_gost94"); 5477b5038d7SDag-Erling Smørgrav if(!md) { 5487b5038d7SDag-Erling Smørgrav ldns_rr_free(ds); 5497b5038d7SDag-Erling Smørgrav return NULL; 5507b5038d7SDag-Erling Smørgrav } 5517b5038d7SDag-Erling Smørgrav digest = LDNS_XMALLOC(uint8_t, EVP_MD_size(md)); 5527b5038d7SDag-Erling Smørgrav if (!digest) { 5537b5038d7SDag-Erling Smørgrav ldns_rr_free(ds); 5547b5038d7SDag-Erling Smørgrav return NULL; 5557b5038d7SDag-Erling Smørgrav } 5567b5038d7SDag-Erling Smørgrav break; 5577b5038d7SDag-Erling Smørgrav #else 5587b5038d7SDag-Erling Smørgrav /* not implemented */ 5597b5038d7SDag-Erling Smørgrav ldns_rr_free(ds); 5607b5038d7SDag-Erling Smørgrav return NULL; 5617b5038d7SDag-Erling Smørgrav #endif 5627b5038d7SDag-Erling Smørgrav case LDNS_SHA384: 5637b5038d7SDag-Erling Smørgrav #ifdef USE_ECDSA 5647b5038d7SDag-Erling Smørgrav digest = LDNS_XMALLOC(uint8_t, SHA384_DIGEST_LENGTH); 5657b5038d7SDag-Erling Smørgrav if (!digest) { 5667b5038d7SDag-Erling Smørgrav ldns_rr_free(ds); 5677b5038d7SDag-Erling Smørgrav return NULL; 5687b5038d7SDag-Erling Smørgrav } 5697b5038d7SDag-Erling Smørgrav break; 5707b5038d7SDag-Erling Smørgrav #else 5717b5038d7SDag-Erling Smørgrav /* not implemented */ 5727b5038d7SDag-Erling Smørgrav ldns_rr_free(ds); 5737b5038d7SDag-Erling Smørgrav return NULL; 5747b5038d7SDag-Erling Smørgrav #endif 5757b5038d7SDag-Erling Smørgrav } 5767b5038d7SDag-Erling Smørgrav 5777b5038d7SDag-Erling Smørgrav data_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN); 5787b5038d7SDag-Erling Smørgrav if (!data_buf) { 5797b5038d7SDag-Erling Smørgrav LDNS_FREE(digest); 5807b5038d7SDag-Erling Smørgrav ldns_rr_free(ds); 5817b5038d7SDag-Erling Smørgrav return NULL; 5827b5038d7SDag-Erling Smørgrav } 5837b5038d7SDag-Erling Smørgrav 5847b5038d7SDag-Erling Smørgrav /* keytag */ 5857b5038d7SDag-Erling Smørgrav keytag = htons(ldns_calc_keytag((ldns_rr*)key)); 5867b5038d7SDag-Erling Smørgrav tmp = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_INT16, 5877b5038d7SDag-Erling Smørgrav sizeof(uint16_t), 5887b5038d7SDag-Erling Smørgrav &keytag); 5897b5038d7SDag-Erling Smørgrav ldns_rr_push_rdf(ds, tmp); 5907b5038d7SDag-Erling Smørgrav 5917b5038d7SDag-Erling Smørgrav /* copy the algorithm field */ 5927b5038d7SDag-Erling Smørgrav if ((tmp = ldns_rr_rdf(key, 2)) == NULL) { 5937b5038d7SDag-Erling Smørgrav LDNS_FREE(digest); 5947b5038d7SDag-Erling Smørgrav ldns_buffer_free(data_buf); 5957b5038d7SDag-Erling Smørgrav ldns_rr_free(ds); 5967b5038d7SDag-Erling Smørgrav return NULL; 5977b5038d7SDag-Erling Smørgrav } else { 5987b5038d7SDag-Erling Smørgrav ldns_rr_push_rdf(ds, ldns_rdf_clone( tmp )); 5997b5038d7SDag-Erling Smørgrav } 6007b5038d7SDag-Erling Smørgrav 6017b5038d7SDag-Erling Smørgrav /* digest hash type */ 6027b5038d7SDag-Erling Smørgrav sha1hash = (uint8_t)h; 6037b5038d7SDag-Erling Smørgrav tmp = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_INT8, 6047b5038d7SDag-Erling Smørgrav sizeof(uint8_t), 6057b5038d7SDag-Erling Smørgrav &sha1hash); 6067b5038d7SDag-Erling Smørgrav ldns_rr_push_rdf(ds, tmp); 6077b5038d7SDag-Erling Smørgrav 6087b5038d7SDag-Erling Smørgrav /* digest */ 6097b5038d7SDag-Erling Smørgrav /* owner name */ 6107b5038d7SDag-Erling Smørgrav tmp = ldns_rdf_clone(ldns_rr_owner(key)); 6117b5038d7SDag-Erling Smørgrav ldns_dname2canonical(tmp); 6127b5038d7SDag-Erling Smørgrav if (ldns_rdf2buffer_wire(data_buf, tmp) != LDNS_STATUS_OK) { 6137b5038d7SDag-Erling Smørgrav LDNS_FREE(digest); 6147b5038d7SDag-Erling Smørgrav ldns_buffer_free(data_buf); 6157b5038d7SDag-Erling Smørgrav ldns_rr_free(ds); 6167b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(tmp); 6177b5038d7SDag-Erling Smørgrav return NULL; 6187b5038d7SDag-Erling Smørgrav } 6197b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(tmp); 6207b5038d7SDag-Erling Smørgrav 6217b5038d7SDag-Erling Smørgrav /* all the rdata's */ 6227b5038d7SDag-Erling Smørgrav if (ldns_rr_rdata2buffer_wire(data_buf, 6237b5038d7SDag-Erling Smørgrav (ldns_rr*)key) != LDNS_STATUS_OK) { 6247b5038d7SDag-Erling Smørgrav LDNS_FREE(digest); 6257b5038d7SDag-Erling Smørgrav ldns_buffer_free(data_buf); 6267b5038d7SDag-Erling Smørgrav ldns_rr_free(ds); 6277b5038d7SDag-Erling Smørgrav return NULL; 6287b5038d7SDag-Erling Smørgrav } 6297b5038d7SDag-Erling Smørgrav switch(h) { 6307b5038d7SDag-Erling Smørgrav case LDNS_SHA1: 6317b5038d7SDag-Erling Smørgrav (void) ldns_sha1((unsigned char *) ldns_buffer_begin(data_buf), 6327b5038d7SDag-Erling Smørgrav (unsigned int) ldns_buffer_position(data_buf), 6337b5038d7SDag-Erling Smørgrav (unsigned char *) digest); 6347b5038d7SDag-Erling Smørgrav 6357b5038d7SDag-Erling Smørgrav tmp = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_HEX, 6367b5038d7SDag-Erling Smørgrav LDNS_SHA1_DIGEST_LENGTH, 6377b5038d7SDag-Erling Smørgrav digest); 6387b5038d7SDag-Erling Smørgrav ldns_rr_push_rdf(ds, tmp); 6397b5038d7SDag-Erling Smørgrav 6407b5038d7SDag-Erling Smørgrav break; 6417b5038d7SDag-Erling Smørgrav case LDNS_SHA256: 6427b5038d7SDag-Erling Smørgrav (void) ldns_sha256((unsigned char *) ldns_buffer_begin(data_buf), 6437b5038d7SDag-Erling Smørgrav (unsigned int) ldns_buffer_position(data_buf), 6447b5038d7SDag-Erling Smørgrav (unsigned char *) digest); 6457b5038d7SDag-Erling Smørgrav tmp = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_HEX, 6467b5038d7SDag-Erling Smørgrav LDNS_SHA256_DIGEST_LENGTH, 6477b5038d7SDag-Erling Smørgrav digest); 6487b5038d7SDag-Erling Smørgrav ldns_rr_push_rdf(ds, tmp); 6497b5038d7SDag-Erling Smørgrav break; 6507b5038d7SDag-Erling Smørgrav case LDNS_HASH_GOST: 6517b5038d7SDag-Erling Smørgrav #ifdef USE_GOST 6527b5038d7SDag-Erling Smørgrav if(!ldns_digest_evp((unsigned char *) ldns_buffer_begin(data_buf), 6537b5038d7SDag-Erling Smørgrav (unsigned int) ldns_buffer_position(data_buf), 6547b5038d7SDag-Erling Smørgrav (unsigned char *) digest, md)) { 6557b5038d7SDag-Erling Smørgrav LDNS_FREE(digest); 6567b5038d7SDag-Erling Smørgrav ldns_buffer_free(data_buf); 6577b5038d7SDag-Erling Smørgrav ldns_rr_free(ds); 6587b5038d7SDag-Erling Smørgrav return NULL; 6597b5038d7SDag-Erling Smørgrav } 6607b5038d7SDag-Erling Smørgrav tmp = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_HEX, 6617b5038d7SDag-Erling Smørgrav (size_t)EVP_MD_size(md), 6627b5038d7SDag-Erling Smørgrav digest); 6637b5038d7SDag-Erling Smørgrav ldns_rr_push_rdf(ds, tmp); 6647b5038d7SDag-Erling Smørgrav #endif 6657b5038d7SDag-Erling Smørgrav break; 6667b5038d7SDag-Erling Smørgrav case LDNS_SHA384: 6677b5038d7SDag-Erling Smørgrav #ifdef USE_ECDSA 6687b5038d7SDag-Erling Smørgrav (void) SHA384((unsigned char *) ldns_buffer_begin(data_buf), 6697b5038d7SDag-Erling Smørgrav (unsigned int) ldns_buffer_position(data_buf), 6707b5038d7SDag-Erling Smørgrav (unsigned char *) digest); 6717b5038d7SDag-Erling Smørgrav tmp = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_HEX, 6727b5038d7SDag-Erling Smørgrav SHA384_DIGEST_LENGTH, 6737b5038d7SDag-Erling Smørgrav digest); 6747b5038d7SDag-Erling Smørgrav ldns_rr_push_rdf(ds, tmp); 6757b5038d7SDag-Erling Smørgrav #endif 6767b5038d7SDag-Erling Smørgrav break; 6777b5038d7SDag-Erling Smørgrav } 6787b5038d7SDag-Erling Smørgrav 6797b5038d7SDag-Erling Smørgrav LDNS_FREE(digest); 6807b5038d7SDag-Erling Smørgrav ldns_buffer_free(data_buf); 6817b5038d7SDag-Erling Smørgrav return ds; 6827b5038d7SDag-Erling Smørgrav } 6837b5038d7SDag-Erling Smørgrav 68417d15b25SDag-Erling Smørgrav /* From RFC3845: 68517d15b25SDag-Erling Smørgrav * 68617d15b25SDag-Erling Smørgrav * 2.1.2. The List of Type Bit Map(s) Field 68717d15b25SDag-Erling Smørgrav * 68817d15b25SDag-Erling Smørgrav * The RR type space is split into 256 window blocks, each representing 68917d15b25SDag-Erling Smørgrav * the low-order 8 bits of the 16-bit RR type space. Each block that 69017d15b25SDag-Erling Smørgrav * has at least one active RR type is encoded using a single octet 69117d15b25SDag-Erling Smørgrav * window number (from 0 to 255), a single octet bitmap length (from 1 69217d15b25SDag-Erling Smørgrav * to 32) indicating the number of octets used for the window block's 69317d15b25SDag-Erling Smørgrav * bitmap, and up to 32 octets (256 bits) of bitmap. 69417d15b25SDag-Erling Smørgrav * 69517d15b25SDag-Erling Smørgrav * Window blocks are present in the NSEC RR RDATA in increasing 69617d15b25SDag-Erling Smørgrav * numerical order. 69717d15b25SDag-Erling Smørgrav * 69817d15b25SDag-Erling Smørgrav * "|" denotes concatenation 69917d15b25SDag-Erling Smørgrav * 70017d15b25SDag-Erling Smørgrav * Type Bit Map(s) Field = ( Window Block # | Bitmap Length | Bitmap ) + 70117d15b25SDag-Erling Smørgrav * 70217d15b25SDag-Erling Smørgrav * <cut> 70317d15b25SDag-Erling Smørgrav * 70417d15b25SDag-Erling Smørgrav * Blocks with no types present MUST NOT be included. Trailing zero 70517d15b25SDag-Erling Smørgrav * octets in the bitmap MUST be omitted. The length of each block's 70617d15b25SDag-Erling Smørgrav * bitmap is determined by the type code with the largest numerical 70717d15b25SDag-Erling Smørgrav * value within that block, among the set of RR types present at the 70817d15b25SDag-Erling Smørgrav * NSEC RR's owner name. Trailing zero octets not specified MUST be 70917d15b25SDag-Erling Smørgrav * interpreted as zero octets. 71017d15b25SDag-Erling Smørgrav */ 7117b5038d7SDag-Erling Smørgrav ldns_rdf * 7127b5038d7SDag-Erling Smørgrav ldns_dnssec_create_nsec_bitmap(ldns_rr_type rr_type_list[], 7137b5038d7SDag-Erling Smørgrav size_t size, 7147b5038d7SDag-Erling Smørgrav ldns_rr_type nsec_type) 7157b5038d7SDag-Erling Smørgrav { 71617d15b25SDag-Erling Smørgrav uint8_t window; /* most significant octet of type */ 71717d15b25SDag-Erling Smørgrav uint8_t subtype; /* least significant octet of type */ 718*986ba33cSDag-Erling Smørgrav int windows[256]; /* Max subtype per window */ 719*986ba33cSDag-Erling Smørgrav uint8_t windowpresent[256]; /* bool if window appears in bitmap */ 72017d15b25SDag-Erling Smørgrav ldns_rr_type* d; /* used to traverse rr_type_list*/ 72117d15b25SDag-Erling Smørgrav size_t i; /* used to traverse windows array */ 7227b5038d7SDag-Erling Smørgrav 72317d15b25SDag-Erling Smørgrav size_t sz; /* size needed for type bitmap rdf */ 72417d15b25SDag-Erling Smørgrav uint8_t* data = NULL; /* rdf data */ 72517d15b25SDag-Erling Smørgrav uint8_t* dptr; /* used to itraverse rdf data */ 72617d15b25SDag-Erling Smørgrav ldns_rdf* rdf; /* bitmap rdf to return */ 7277b5038d7SDag-Erling Smørgrav 7287b5038d7SDag-Erling Smørgrav if (nsec_type != LDNS_RR_TYPE_NSEC && 7297b5038d7SDag-Erling Smørgrav nsec_type != LDNS_RR_TYPE_NSEC3) { 7307b5038d7SDag-Erling Smørgrav return NULL; 7317b5038d7SDag-Erling Smørgrav } 732*986ba33cSDag-Erling Smørgrav memset(windows, 0, sizeof(int)*256); 733*986ba33cSDag-Erling Smørgrav memset(windowpresent, 0, 256); 7347b5038d7SDag-Erling Smørgrav 73517d15b25SDag-Erling Smørgrav /* Which other windows need to be in the bitmap rdf? 73617d15b25SDag-Erling Smørgrav */ 73717d15b25SDag-Erling Smørgrav for (d = rr_type_list; d < rr_type_list + size; d++) { 73817d15b25SDag-Erling Smørgrav window = *d >> 8; 73917d15b25SDag-Erling Smørgrav subtype = *d & 0xff; 740*986ba33cSDag-Erling Smørgrav windowpresent[window] = 1; 741*986ba33cSDag-Erling Smørgrav if (windows[window] < (int)subtype) { 742*986ba33cSDag-Erling Smørgrav windows[window] = (int)subtype; 7437b5038d7SDag-Erling Smørgrav } 7447b5038d7SDag-Erling Smørgrav } 7457b5038d7SDag-Erling Smørgrav 74617d15b25SDag-Erling Smørgrav /* How much space do we need in the rdf for those windows? 74717d15b25SDag-Erling Smørgrav */ 74817d15b25SDag-Erling Smørgrav sz = 0; 74917d15b25SDag-Erling Smørgrav for (i = 0; i < 256; i++) { 750*986ba33cSDag-Erling Smørgrav if (windowpresent[i]) { 75117d15b25SDag-Erling Smørgrav sz += windows[i] / 8 + 3; 7527b5038d7SDag-Erling Smørgrav } 7537b5038d7SDag-Erling Smørgrav } 75417d15b25SDag-Erling Smørgrav if (sz > 0) { 75517d15b25SDag-Erling Smørgrav /* Format rdf data according RFC3845 Section 2.1.2 (see above) 75617d15b25SDag-Erling Smørgrav */ 75717d15b25SDag-Erling Smørgrav dptr = data = LDNS_CALLOC(uint8_t, sz); 7587b5038d7SDag-Erling Smørgrav if (!data) { 7597b5038d7SDag-Erling Smørgrav return NULL; 7607b5038d7SDag-Erling Smørgrav } 76117d15b25SDag-Erling Smørgrav for (i = 0; i < 256; i++) { 762*986ba33cSDag-Erling Smørgrav if (windowpresent[i]) { 76317d15b25SDag-Erling Smørgrav *dptr++ = (uint8_t)i; 76417d15b25SDag-Erling Smørgrav *dptr++ = (uint8_t)(windows[i] / 8 + 1); 7657b5038d7SDag-Erling Smørgrav 76617d15b25SDag-Erling Smørgrav /* Now let windows[i] index the bitmap 76717d15b25SDag-Erling Smørgrav * within data 76817d15b25SDag-Erling Smørgrav */ 769*986ba33cSDag-Erling Smørgrav windows[i] = (int)(dptr - data); 77017d15b25SDag-Erling Smørgrav 77117d15b25SDag-Erling Smørgrav dptr += dptr[-1]; 77217d15b25SDag-Erling Smørgrav } 77317d15b25SDag-Erling Smørgrav } 77417d15b25SDag-Erling Smørgrav } 77517d15b25SDag-Erling Smørgrav 77617d15b25SDag-Erling Smørgrav /* Set the bits? 77717d15b25SDag-Erling Smørgrav */ 77817d15b25SDag-Erling Smørgrav for (d = rr_type_list; d < rr_type_list + size; d++) { 77917d15b25SDag-Erling Smørgrav subtype = *d & 0xff; 78017d15b25SDag-Erling Smørgrav data[windows[*d >> 8] + subtype/8] |= (0x80 >> (subtype % 8)); 78117d15b25SDag-Erling Smørgrav } 78217d15b25SDag-Erling Smørgrav 78317d15b25SDag-Erling Smørgrav /* Allocate and return rdf structure for the data 78417d15b25SDag-Erling Smørgrav */ 78517d15b25SDag-Erling Smørgrav rdf = ldns_rdf_new(LDNS_RDF_TYPE_BITMAP, sz, data); 78617d15b25SDag-Erling Smørgrav if (!rdf) { 7877b5038d7SDag-Erling Smørgrav LDNS_FREE(data); 78817d15b25SDag-Erling Smørgrav return NULL; 78917d15b25SDag-Erling Smørgrav } 79017d15b25SDag-Erling Smørgrav return rdf; 7917b5038d7SDag-Erling Smørgrav } 7927b5038d7SDag-Erling Smørgrav 7937b5038d7SDag-Erling Smørgrav int 794*986ba33cSDag-Erling Smørgrav ldns_dnssec_rrsets_contains_type(const ldns_dnssec_rrsets *rrsets, 7957b5038d7SDag-Erling Smørgrav ldns_rr_type type) 7967b5038d7SDag-Erling Smørgrav { 797*986ba33cSDag-Erling Smørgrav const ldns_dnssec_rrsets *cur_rrset = rrsets; 7987b5038d7SDag-Erling Smørgrav while (cur_rrset) { 7997b5038d7SDag-Erling Smørgrav if (cur_rrset->type == type) { 8007b5038d7SDag-Erling Smørgrav return 1; 8017b5038d7SDag-Erling Smørgrav } 8027b5038d7SDag-Erling Smørgrav cur_rrset = cur_rrset->next; 8037b5038d7SDag-Erling Smørgrav } 8047b5038d7SDag-Erling Smørgrav return 0; 8057b5038d7SDag-Erling Smørgrav } 8067b5038d7SDag-Erling Smørgrav 8077b5038d7SDag-Erling Smørgrav ldns_rr * 808*986ba33cSDag-Erling Smørgrav ldns_dnssec_create_nsec(const ldns_dnssec_name *from, 809*986ba33cSDag-Erling Smørgrav const ldns_dnssec_name *to, 8107b5038d7SDag-Erling Smørgrav ldns_rr_type nsec_type) 8117b5038d7SDag-Erling Smørgrav { 8127b5038d7SDag-Erling Smørgrav ldns_rr *nsec_rr; 8137b5038d7SDag-Erling Smørgrav ldns_rr_type types[65536]; 8147b5038d7SDag-Erling Smørgrav size_t type_count = 0; 8157b5038d7SDag-Erling Smørgrav ldns_dnssec_rrsets *cur_rrsets; 8167b5038d7SDag-Erling Smørgrav int on_delegation_point; 8177b5038d7SDag-Erling Smørgrav 8187b5038d7SDag-Erling Smørgrav if (!from || !to || (nsec_type != LDNS_RR_TYPE_NSEC)) { 8197b5038d7SDag-Erling Smørgrav return NULL; 8207b5038d7SDag-Erling Smørgrav } 8217b5038d7SDag-Erling Smørgrav 8227b5038d7SDag-Erling Smørgrav nsec_rr = ldns_rr_new(); 8237b5038d7SDag-Erling Smørgrav ldns_rr_set_type(nsec_rr, nsec_type); 8247b5038d7SDag-Erling Smørgrav ldns_rr_set_owner(nsec_rr, ldns_rdf_clone(ldns_dnssec_name_name(from))); 8257b5038d7SDag-Erling Smørgrav ldns_rr_push_rdf(nsec_rr, ldns_rdf_clone(ldns_dnssec_name_name(to))); 8267b5038d7SDag-Erling Smørgrav 8277b5038d7SDag-Erling Smørgrav on_delegation_point = ldns_dnssec_rrsets_contains_type( 8287b5038d7SDag-Erling Smørgrav from->rrsets, LDNS_RR_TYPE_NS) 8297b5038d7SDag-Erling Smørgrav && !ldns_dnssec_rrsets_contains_type( 8307b5038d7SDag-Erling Smørgrav from->rrsets, LDNS_RR_TYPE_SOA); 8317b5038d7SDag-Erling Smørgrav 8327b5038d7SDag-Erling Smørgrav cur_rrsets = from->rrsets; 8337b5038d7SDag-Erling Smørgrav while (cur_rrsets) { 8347b5038d7SDag-Erling Smørgrav /* Do not include non-authoritative rrsets on the delegation point 8357b5038d7SDag-Erling Smørgrav * in the type bitmap */ 8367b5038d7SDag-Erling Smørgrav if ((on_delegation_point && ( 8377b5038d7SDag-Erling Smørgrav cur_rrsets->type == LDNS_RR_TYPE_NS 8387b5038d7SDag-Erling Smørgrav || cur_rrsets->type == LDNS_RR_TYPE_DS)) 8397b5038d7SDag-Erling Smørgrav || (!on_delegation_point && 8407b5038d7SDag-Erling Smørgrav cur_rrsets->type != LDNS_RR_TYPE_RRSIG 8417b5038d7SDag-Erling Smørgrav && cur_rrsets->type != LDNS_RR_TYPE_NSEC)) { 8427b5038d7SDag-Erling Smørgrav 8437b5038d7SDag-Erling Smørgrav types[type_count] = cur_rrsets->type; 8447b5038d7SDag-Erling Smørgrav type_count++; 8457b5038d7SDag-Erling Smørgrav } 8467b5038d7SDag-Erling Smørgrav cur_rrsets = cur_rrsets->next; 8477b5038d7SDag-Erling Smørgrav 8487b5038d7SDag-Erling Smørgrav } 8497b5038d7SDag-Erling Smørgrav types[type_count] = LDNS_RR_TYPE_RRSIG; 8507b5038d7SDag-Erling Smørgrav type_count++; 8517b5038d7SDag-Erling Smørgrav types[type_count] = LDNS_RR_TYPE_NSEC; 8527b5038d7SDag-Erling Smørgrav type_count++; 8537b5038d7SDag-Erling Smørgrav 8547b5038d7SDag-Erling Smørgrav ldns_rr_push_rdf(nsec_rr, ldns_dnssec_create_nsec_bitmap(types, 8557b5038d7SDag-Erling Smørgrav type_count, 8567b5038d7SDag-Erling Smørgrav nsec_type)); 8577b5038d7SDag-Erling Smørgrav 8587b5038d7SDag-Erling Smørgrav return nsec_rr; 8597b5038d7SDag-Erling Smørgrav } 8607b5038d7SDag-Erling Smørgrav 8617b5038d7SDag-Erling Smørgrav ldns_rr * 862*986ba33cSDag-Erling Smørgrav ldns_dnssec_create_nsec3(const ldns_dnssec_name *from, 863*986ba33cSDag-Erling Smørgrav const ldns_dnssec_name *to, 864*986ba33cSDag-Erling Smørgrav const ldns_rdf *zone_name, 8657b5038d7SDag-Erling Smørgrav uint8_t algorithm, 8667b5038d7SDag-Erling Smørgrav uint8_t flags, 8677b5038d7SDag-Erling Smørgrav uint16_t iterations, 8687b5038d7SDag-Erling Smørgrav uint8_t salt_length, 869*986ba33cSDag-Erling Smørgrav const uint8_t *salt) 8707b5038d7SDag-Erling Smørgrav { 8717b5038d7SDag-Erling Smørgrav ldns_rr *nsec_rr; 8727b5038d7SDag-Erling Smørgrav ldns_rr_type types[65536]; 8737b5038d7SDag-Erling Smørgrav size_t type_count = 0; 8747b5038d7SDag-Erling Smørgrav ldns_dnssec_rrsets *cur_rrsets; 8757b5038d7SDag-Erling Smørgrav ldns_status status; 8767b5038d7SDag-Erling Smørgrav int on_delegation_point; 8777b5038d7SDag-Erling Smørgrav 8787b5038d7SDag-Erling Smørgrav if (!from) { 8797b5038d7SDag-Erling Smørgrav return NULL; 8807b5038d7SDag-Erling Smørgrav } 8817b5038d7SDag-Erling Smørgrav 8827b5038d7SDag-Erling Smørgrav nsec_rr = ldns_rr_new_frm_type(LDNS_RR_TYPE_NSEC3); 8837b5038d7SDag-Erling Smørgrav ldns_rr_set_owner(nsec_rr, 8847b5038d7SDag-Erling Smørgrav ldns_nsec3_hash_name(ldns_dnssec_name_name(from), 8857b5038d7SDag-Erling Smørgrav algorithm, 8867b5038d7SDag-Erling Smørgrav iterations, 8877b5038d7SDag-Erling Smørgrav salt_length, 8887b5038d7SDag-Erling Smørgrav salt)); 8897b5038d7SDag-Erling Smørgrav status = ldns_dname_cat(ldns_rr_owner(nsec_rr), zone_name); 8907b5038d7SDag-Erling Smørgrav if(status != LDNS_STATUS_OK) { 8917b5038d7SDag-Erling Smørgrav ldns_rr_free(nsec_rr); 8927b5038d7SDag-Erling Smørgrav return NULL; 8937b5038d7SDag-Erling Smørgrav } 8947b5038d7SDag-Erling Smørgrav ldns_nsec3_add_param_rdfs(nsec_rr, 8957b5038d7SDag-Erling Smørgrav algorithm, 8967b5038d7SDag-Erling Smørgrav flags, 8977b5038d7SDag-Erling Smørgrav iterations, 8987b5038d7SDag-Erling Smørgrav salt_length, 8997b5038d7SDag-Erling Smørgrav salt); 9007b5038d7SDag-Erling Smørgrav 9017b5038d7SDag-Erling Smørgrav on_delegation_point = ldns_dnssec_rrsets_contains_type( 9027b5038d7SDag-Erling Smørgrav from->rrsets, LDNS_RR_TYPE_NS) 9037b5038d7SDag-Erling Smørgrav && !ldns_dnssec_rrsets_contains_type( 9047b5038d7SDag-Erling Smørgrav from->rrsets, LDNS_RR_TYPE_SOA); 9057b5038d7SDag-Erling Smørgrav cur_rrsets = from->rrsets; 9067b5038d7SDag-Erling Smørgrav while (cur_rrsets) { 9077b5038d7SDag-Erling Smørgrav /* Do not include non-authoritative rrsets on the delegation point 9087b5038d7SDag-Erling Smørgrav * in the type bitmap. Potentionally not skipping insecure 9097b5038d7SDag-Erling Smørgrav * delegation should have been done earlier, in function 9107b5038d7SDag-Erling Smørgrav * ldns_dnssec_zone_create_nsec3s, or even earlier in: 9117b5038d7SDag-Erling Smørgrav * ldns_dnssec_zone_sign_nsec3_flg . 9127b5038d7SDag-Erling Smørgrav */ 9137b5038d7SDag-Erling Smørgrav if ((on_delegation_point && ( 9147b5038d7SDag-Erling Smørgrav cur_rrsets->type == LDNS_RR_TYPE_NS 9157b5038d7SDag-Erling Smørgrav || cur_rrsets->type == LDNS_RR_TYPE_DS)) 9167b5038d7SDag-Erling Smørgrav || (!on_delegation_point && 9177b5038d7SDag-Erling Smørgrav cur_rrsets->type != LDNS_RR_TYPE_RRSIG)) { 9187b5038d7SDag-Erling Smørgrav 9197b5038d7SDag-Erling Smørgrav types[type_count] = cur_rrsets->type; 9207b5038d7SDag-Erling Smørgrav type_count++; 9217b5038d7SDag-Erling Smørgrav } 9227b5038d7SDag-Erling Smørgrav cur_rrsets = cur_rrsets->next; 9237b5038d7SDag-Erling Smørgrav } 9247b5038d7SDag-Erling Smørgrav /* always add rrsig type if this is not an unsigned 9257b5038d7SDag-Erling Smørgrav * delegation 9267b5038d7SDag-Erling Smørgrav */ 9277b5038d7SDag-Erling Smørgrav if (type_count > 0 && 9287b5038d7SDag-Erling Smørgrav !(type_count == 1 && types[0] == LDNS_RR_TYPE_NS)) { 9297b5038d7SDag-Erling Smørgrav types[type_count] = LDNS_RR_TYPE_RRSIG; 9307b5038d7SDag-Erling Smørgrav type_count++; 9317b5038d7SDag-Erling Smørgrav } 9327b5038d7SDag-Erling Smørgrav 9337b5038d7SDag-Erling Smørgrav /* leave next rdata empty if they weren't precomputed yet */ 9347b5038d7SDag-Erling Smørgrav if (to && to->hashed_name) { 9357b5038d7SDag-Erling Smørgrav (void) ldns_rr_set_rdf(nsec_rr, 9367b5038d7SDag-Erling Smørgrav ldns_rdf_clone(to->hashed_name), 9377b5038d7SDag-Erling Smørgrav 4); 9387b5038d7SDag-Erling Smørgrav } else { 9397b5038d7SDag-Erling Smørgrav (void) ldns_rr_set_rdf(nsec_rr, NULL, 4); 9407b5038d7SDag-Erling Smørgrav } 9417b5038d7SDag-Erling Smørgrav 9427b5038d7SDag-Erling Smørgrav ldns_rr_push_rdf(nsec_rr, 9437b5038d7SDag-Erling Smørgrav ldns_dnssec_create_nsec_bitmap(types, 9447b5038d7SDag-Erling Smørgrav type_count, 9457b5038d7SDag-Erling Smørgrav LDNS_RR_TYPE_NSEC3)); 9467b5038d7SDag-Erling Smørgrav 9477b5038d7SDag-Erling Smørgrav return nsec_rr; 9487b5038d7SDag-Erling Smørgrav } 9497b5038d7SDag-Erling Smørgrav 9507b5038d7SDag-Erling Smørgrav ldns_rr * 9517b5038d7SDag-Erling Smørgrav ldns_create_nsec(ldns_rdf *cur_owner, ldns_rdf *next_owner, ldns_rr_list *rrs) 9527b5038d7SDag-Erling Smørgrav { 9537b5038d7SDag-Erling Smørgrav /* we do not do any check here - garbage in, garbage out */ 9547b5038d7SDag-Erling Smørgrav 9557b5038d7SDag-Erling Smørgrav /* the the start and end names - get the type from the 9567b5038d7SDag-Erling Smørgrav * before rrlist */ 9577b5038d7SDag-Erling Smørgrav 9587b5038d7SDag-Erling Smørgrav /* inefficient, just give it a name, a next name, and a list of rrs */ 9597b5038d7SDag-Erling Smørgrav /* we make 1 big uberbitmap first, then windows */ 9607b5038d7SDag-Erling Smørgrav /* todo: make something more efficient :) */ 9617b5038d7SDag-Erling Smørgrav uint16_t i; 9627b5038d7SDag-Erling Smørgrav ldns_rr *i_rr; 9637b5038d7SDag-Erling Smørgrav uint16_t i_type; 9647b5038d7SDag-Erling Smørgrav 9657b5038d7SDag-Erling Smørgrav ldns_rr *nsec = NULL; 9667b5038d7SDag-Erling Smørgrav ldns_rr_type i_type_list[65536]; 9677b5038d7SDag-Erling Smørgrav size_t type_count = 0; 9687b5038d7SDag-Erling Smørgrav 9697b5038d7SDag-Erling Smørgrav nsec = ldns_rr_new(); 9707b5038d7SDag-Erling Smørgrav ldns_rr_set_type(nsec, LDNS_RR_TYPE_NSEC); 9717b5038d7SDag-Erling Smørgrav ldns_rr_set_owner(nsec, ldns_rdf_clone(cur_owner)); 9727b5038d7SDag-Erling Smørgrav ldns_rr_push_rdf(nsec, ldns_rdf_clone(next_owner)); 9737b5038d7SDag-Erling Smørgrav 9747b5038d7SDag-Erling Smørgrav for (i = 0; i < ldns_rr_list_rr_count(rrs); i++) { 9757b5038d7SDag-Erling Smørgrav i_rr = ldns_rr_list_rr(rrs, i); 9767b5038d7SDag-Erling Smørgrav if (ldns_rdf_compare(cur_owner, 9777b5038d7SDag-Erling Smørgrav ldns_rr_owner(i_rr)) == 0) { 9787b5038d7SDag-Erling Smørgrav i_type = ldns_rr_get_type(i_rr); 9797b5038d7SDag-Erling Smørgrav if (i_type != LDNS_RR_TYPE_RRSIG && i_type != LDNS_RR_TYPE_NSEC) { 9807b5038d7SDag-Erling Smørgrav if (type_count == 0 || i_type_list[type_count-1] != i_type) { 9817b5038d7SDag-Erling Smørgrav i_type_list[type_count] = i_type; 9827b5038d7SDag-Erling Smørgrav type_count++; 9837b5038d7SDag-Erling Smørgrav } 9847b5038d7SDag-Erling Smørgrav } 9857b5038d7SDag-Erling Smørgrav } 9867b5038d7SDag-Erling Smørgrav } 9877b5038d7SDag-Erling Smørgrav 9887b5038d7SDag-Erling Smørgrav i_type_list[type_count] = LDNS_RR_TYPE_RRSIG; 9897b5038d7SDag-Erling Smørgrav type_count++; 9907b5038d7SDag-Erling Smørgrav i_type_list[type_count] = LDNS_RR_TYPE_NSEC; 9917b5038d7SDag-Erling Smørgrav type_count++; 9927b5038d7SDag-Erling Smørgrav 9937b5038d7SDag-Erling Smørgrav ldns_rr_push_rdf(nsec, 9947b5038d7SDag-Erling Smørgrav ldns_dnssec_create_nsec_bitmap(i_type_list, 9957b5038d7SDag-Erling Smørgrav type_count, LDNS_RR_TYPE_NSEC)); 9967b5038d7SDag-Erling Smørgrav 9977b5038d7SDag-Erling Smørgrav return nsec; 9987b5038d7SDag-Erling Smørgrav } 9997b5038d7SDag-Erling Smørgrav 10007b5038d7SDag-Erling Smørgrav ldns_rdf * 1001*986ba33cSDag-Erling Smørgrav ldns_nsec3_hash_name(const ldns_rdf *name, 10027b5038d7SDag-Erling Smørgrav uint8_t algorithm, 10037b5038d7SDag-Erling Smørgrav uint16_t iterations, 10047b5038d7SDag-Erling Smørgrav uint8_t salt_length, 1005*986ba33cSDag-Erling Smørgrav const uint8_t *salt) 10067b5038d7SDag-Erling Smørgrav { 10077b5038d7SDag-Erling Smørgrav size_t hashed_owner_str_len; 10087b5038d7SDag-Erling Smørgrav ldns_rdf *cann; 10097b5038d7SDag-Erling Smørgrav ldns_rdf *hashed_owner; 10107b5038d7SDag-Erling Smørgrav unsigned char *hashed_owner_str; 10117b5038d7SDag-Erling Smørgrav char *hashed_owner_b32; 10127b5038d7SDag-Erling Smørgrav size_t hashed_owner_b32_len; 10137b5038d7SDag-Erling Smørgrav uint32_t cur_it; 10147b5038d7SDag-Erling Smørgrav /* define to contain the largest possible hash, which is 10157b5038d7SDag-Erling Smørgrav * sha1 at the moment */ 10167b5038d7SDag-Erling Smørgrav unsigned char hash[LDNS_SHA1_DIGEST_LENGTH]; 10177b5038d7SDag-Erling Smørgrav ldns_status status; 10187b5038d7SDag-Erling Smørgrav 10197b5038d7SDag-Erling Smørgrav /* TODO: mnemonic list for hash algs SHA-1, default to 1 now (sha1) */ 10207b5038d7SDag-Erling Smørgrav if (algorithm != LDNS_SHA1) { 10217b5038d7SDag-Erling Smørgrav return NULL; 10227b5038d7SDag-Erling Smørgrav } 10237b5038d7SDag-Erling Smørgrav 10247b5038d7SDag-Erling Smørgrav /* prepare the owner name according to the draft section bla */ 10257b5038d7SDag-Erling Smørgrav cann = ldns_rdf_clone(name); 10267b5038d7SDag-Erling Smørgrav if(!cann) { 102717d15b25SDag-Erling Smørgrav #ifdef STDERR_MSGS 10287b5038d7SDag-Erling Smørgrav fprintf(stderr, "Memory error\n"); 102917d15b25SDag-Erling Smørgrav #endif 10307b5038d7SDag-Erling Smørgrav return NULL; 10317b5038d7SDag-Erling Smørgrav } 10327b5038d7SDag-Erling Smørgrav ldns_dname2canonical(cann); 10337b5038d7SDag-Erling Smørgrav 10347b5038d7SDag-Erling Smørgrav hashed_owner_str_len = salt_length + ldns_rdf_size(cann); 10357b5038d7SDag-Erling Smørgrav hashed_owner_str = LDNS_XMALLOC(unsigned char, hashed_owner_str_len); 10367b5038d7SDag-Erling Smørgrav if(!hashed_owner_str) { 10377b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(cann); 10387b5038d7SDag-Erling Smørgrav return NULL; 10397b5038d7SDag-Erling Smørgrav } 10407b5038d7SDag-Erling Smørgrav memcpy(hashed_owner_str, ldns_rdf_data(cann), ldns_rdf_size(cann)); 10417b5038d7SDag-Erling Smørgrav memcpy(hashed_owner_str + ldns_rdf_size(cann), salt, salt_length); 10427b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(cann); 10437b5038d7SDag-Erling Smørgrav 10447b5038d7SDag-Erling Smørgrav for (cur_it = iterations + 1; cur_it > 0; cur_it--) { 10457b5038d7SDag-Erling Smørgrav (void) ldns_sha1((unsigned char *) hashed_owner_str, 10467b5038d7SDag-Erling Smørgrav (unsigned int) hashed_owner_str_len, hash); 10477b5038d7SDag-Erling Smørgrav 10487b5038d7SDag-Erling Smørgrav LDNS_FREE(hashed_owner_str); 10497b5038d7SDag-Erling Smørgrav hashed_owner_str_len = salt_length + LDNS_SHA1_DIGEST_LENGTH; 10507b5038d7SDag-Erling Smørgrav hashed_owner_str = LDNS_XMALLOC(unsigned char, hashed_owner_str_len); 10517b5038d7SDag-Erling Smørgrav if (!hashed_owner_str) { 10527b5038d7SDag-Erling Smørgrav return NULL; 10537b5038d7SDag-Erling Smørgrav } 10547b5038d7SDag-Erling Smørgrav memcpy(hashed_owner_str, hash, LDNS_SHA1_DIGEST_LENGTH); 10557b5038d7SDag-Erling Smørgrav memcpy(hashed_owner_str + LDNS_SHA1_DIGEST_LENGTH, salt, salt_length); 10567b5038d7SDag-Erling Smørgrav hashed_owner_str_len = LDNS_SHA1_DIGEST_LENGTH + salt_length; 10577b5038d7SDag-Erling Smørgrav } 10587b5038d7SDag-Erling Smørgrav 10597b5038d7SDag-Erling Smørgrav LDNS_FREE(hashed_owner_str); 10607b5038d7SDag-Erling Smørgrav hashed_owner_str = hash; 10617b5038d7SDag-Erling Smørgrav hashed_owner_str_len = LDNS_SHA1_DIGEST_LENGTH; 10627b5038d7SDag-Erling Smørgrav 10637b5038d7SDag-Erling Smørgrav hashed_owner_b32 = LDNS_XMALLOC(char, 10647b5038d7SDag-Erling Smørgrav ldns_b32_ntop_calculate_size(hashed_owner_str_len) + 1); 10657b5038d7SDag-Erling Smørgrav if(!hashed_owner_b32) { 10667b5038d7SDag-Erling Smørgrav return NULL; 10677b5038d7SDag-Erling Smørgrav } 10687b5038d7SDag-Erling Smørgrav hashed_owner_b32_len = (size_t) ldns_b32_ntop_extended_hex( 10697b5038d7SDag-Erling Smørgrav (uint8_t *) hashed_owner_str, 10707b5038d7SDag-Erling Smørgrav hashed_owner_str_len, 10717b5038d7SDag-Erling Smørgrav hashed_owner_b32, 10727b5038d7SDag-Erling Smørgrav ldns_b32_ntop_calculate_size(hashed_owner_str_len)+1); 10737b5038d7SDag-Erling Smørgrav if (hashed_owner_b32_len < 1) { 107417d15b25SDag-Erling Smørgrav #ifdef STDERR_MSGS 10757b5038d7SDag-Erling Smørgrav fprintf(stderr, "Error in base32 extended hex encoding "); 10767b5038d7SDag-Erling Smørgrav fprintf(stderr, "of hashed owner name (name: "); 10777b5038d7SDag-Erling Smørgrav ldns_rdf_print(stderr, name); 10787b5038d7SDag-Erling Smørgrav fprintf(stderr, ", return code: %u)\n", 10797b5038d7SDag-Erling Smørgrav (unsigned int) hashed_owner_b32_len); 108017d15b25SDag-Erling Smørgrav #endif 10817b5038d7SDag-Erling Smørgrav LDNS_FREE(hashed_owner_b32); 10827b5038d7SDag-Erling Smørgrav return NULL; 10837b5038d7SDag-Erling Smørgrav } 10847b5038d7SDag-Erling Smørgrav hashed_owner_b32[hashed_owner_b32_len] = '\0'; 10857b5038d7SDag-Erling Smørgrav 10867b5038d7SDag-Erling Smørgrav status = ldns_str2rdf_dname(&hashed_owner, hashed_owner_b32); 10877b5038d7SDag-Erling Smørgrav if (status != LDNS_STATUS_OK) { 108817d15b25SDag-Erling Smørgrav #ifdef STDERR_MSGS 10897b5038d7SDag-Erling Smørgrav fprintf(stderr, "Error creating rdf from %s\n", hashed_owner_b32); 109017d15b25SDag-Erling Smørgrav #endif 10917b5038d7SDag-Erling Smørgrav LDNS_FREE(hashed_owner_b32); 10927b5038d7SDag-Erling Smørgrav return NULL; 10937b5038d7SDag-Erling Smørgrav } 10947b5038d7SDag-Erling Smørgrav 10957b5038d7SDag-Erling Smørgrav LDNS_FREE(hashed_owner_b32); 10967b5038d7SDag-Erling Smørgrav return hashed_owner; 10977b5038d7SDag-Erling Smørgrav } 10987b5038d7SDag-Erling Smørgrav 10997b5038d7SDag-Erling Smørgrav void 11007b5038d7SDag-Erling Smørgrav ldns_nsec3_add_param_rdfs(ldns_rr *rr, 11017b5038d7SDag-Erling Smørgrav uint8_t algorithm, 11027b5038d7SDag-Erling Smørgrav uint8_t flags, 11037b5038d7SDag-Erling Smørgrav uint16_t iterations, 11047b5038d7SDag-Erling Smørgrav uint8_t salt_length, 1105*986ba33cSDag-Erling Smørgrav const uint8_t *salt) 11067b5038d7SDag-Erling Smørgrav { 11077b5038d7SDag-Erling Smørgrav ldns_rdf *salt_rdf = NULL; 11087b5038d7SDag-Erling Smørgrav uint8_t *salt_data = NULL; 11097b5038d7SDag-Erling Smørgrav ldns_rdf *old; 11107b5038d7SDag-Erling Smørgrav 11117b5038d7SDag-Erling Smørgrav old = ldns_rr_set_rdf(rr, 11127b5038d7SDag-Erling Smørgrav ldns_rdf_new_frm_data(LDNS_RDF_TYPE_INT8, 11137b5038d7SDag-Erling Smørgrav 1, (void*)&algorithm), 11147b5038d7SDag-Erling Smørgrav 0); 11157b5038d7SDag-Erling Smørgrav if (old) ldns_rdf_deep_free(old); 11167b5038d7SDag-Erling Smørgrav 11177b5038d7SDag-Erling Smørgrav old = ldns_rr_set_rdf(rr, 11187b5038d7SDag-Erling Smørgrav ldns_rdf_new_frm_data(LDNS_RDF_TYPE_INT8, 11197b5038d7SDag-Erling Smørgrav 1, (void*)&flags), 11207b5038d7SDag-Erling Smørgrav 1); 11217b5038d7SDag-Erling Smørgrav if (old) ldns_rdf_deep_free(old); 11227b5038d7SDag-Erling Smørgrav 11237b5038d7SDag-Erling Smørgrav old = ldns_rr_set_rdf(rr, 11247b5038d7SDag-Erling Smørgrav ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, 11257b5038d7SDag-Erling Smørgrav iterations), 11267b5038d7SDag-Erling Smørgrav 2); 11277b5038d7SDag-Erling Smørgrav if (old) ldns_rdf_deep_free(old); 11287b5038d7SDag-Erling Smørgrav 11297b5038d7SDag-Erling Smørgrav salt_data = LDNS_XMALLOC(uint8_t, salt_length + 1); 11307b5038d7SDag-Erling Smørgrav if(!salt_data) { 11317b5038d7SDag-Erling Smørgrav /* no way to return error */ 11327b5038d7SDag-Erling Smørgrav return; 11337b5038d7SDag-Erling Smørgrav } 11347b5038d7SDag-Erling Smørgrav salt_data[0] = salt_length; 11357b5038d7SDag-Erling Smørgrav memcpy(salt_data + 1, salt, salt_length); 11367b5038d7SDag-Erling Smørgrav salt_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_NSEC3_SALT, 11377b5038d7SDag-Erling Smørgrav salt_length + 1, 11387b5038d7SDag-Erling Smørgrav salt_data); 11397b5038d7SDag-Erling Smørgrav if(!salt_rdf) { 11407b5038d7SDag-Erling Smørgrav LDNS_FREE(salt_data); 11417b5038d7SDag-Erling Smørgrav /* no way to return error */ 11427b5038d7SDag-Erling Smørgrav return; 11437b5038d7SDag-Erling Smørgrav } 11447b5038d7SDag-Erling Smørgrav 11457b5038d7SDag-Erling Smørgrav old = ldns_rr_set_rdf(rr, salt_rdf, 3); 11467b5038d7SDag-Erling Smørgrav if (old) ldns_rdf_deep_free(old); 11477b5038d7SDag-Erling Smørgrav LDNS_FREE(salt_data); 11487b5038d7SDag-Erling Smørgrav } 11497b5038d7SDag-Erling Smørgrav 11507b5038d7SDag-Erling Smørgrav static int 1151*986ba33cSDag-Erling Smørgrav rr_list_delegation_only(const ldns_rdf *origin, const ldns_rr_list *rr_list) 11527b5038d7SDag-Erling Smørgrav { 11537b5038d7SDag-Erling Smørgrav size_t i; 11547b5038d7SDag-Erling Smørgrav ldns_rr *cur_rr; 11557b5038d7SDag-Erling Smørgrav if (!origin || !rr_list) return 0; 11567b5038d7SDag-Erling Smørgrav for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) { 11577b5038d7SDag-Erling Smørgrav cur_rr = ldns_rr_list_rr(rr_list, i); 11587b5038d7SDag-Erling Smørgrav if (ldns_dname_compare(ldns_rr_owner(cur_rr), origin) == 0) { 11597b5038d7SDag-Erling Smørgrav return 0; 11607b5038d7SDag-Erling Smørgrav } 11617b5038d7SDag-Erling Smørgrav if (ldns_rr_get_type(cur_rr) != LDNS_RR_TYPE_NS) { 11627b5038d7SDag-Erling Smørgrav return 0; 11637b5038d7SDag-Erling Smørgrav } 11647b5038d7SDag-Erling Smørgrav } 11657b5038d7SDag-Erling Smørgrav return 1; 11667b5038d7SDag-Erling Smørgrav } 11677b5038d7SDag-Erling Smørgrav 11687b5038d7SDag-Erling Smørgrav /* this will NOT return the NSEC3 completed, you will have to run the 11697b5038d7SDag-Erling Smørgrav finalize function on the rrlist later! */ 11707b5038d7SDag-Erling Smørgrav ldns_rr * 1171*986ba33cSDag-Erling Smørgrav ldns_create_nsec3(const ldns_rdf *cur_owner, 1172*986ba33cSDag-Erling Smørgrav const ldns_rdf *cur_zone, 1173*986ba33cSDag-Erling Smørgrav const ldns_rr_list *rrs, 11747b5038d7SDag-Erling Smørgrav uint8_t algorithm, 11757b5038d7SDag-Erling Smørgrav uint8_t flags, 11767b5038d7SDag-Erling Smørgrav uint16_t iterations, 11777b5038d7SDag-Erling Smørgrav uint8_t salt_length, 1178*986ba33cSDag-Erling Smørgrav const uint8_t *salt, 11797b5038d7SDag-Erling Smørgrav bool emptynonterminal) 11807b5038d7SDag-Erling Smørgrav { 11817b5038d7SDag-Erling Smørgrav size_t i; 11827b5038d7SDag-Erling Smørgrav ldns_rr *i_rr; 11837b5038d7SDag-Erling Smørgrav uint16_t i_type; 11847b5038d7SDag-Erling Smørgrav 11857b5038d7SDag-Erling Smørgrav ldns_rr *nsec = NULL; 11867b5038d7SDag-Erling Smørgrav ldns_rdf *hashed_owner = NULL; 11877b5038d7SDag-Erling Smørgrav 11887b5038d7SDag-Erling Smørgrav ldns_status status; 11897b5038d7SDag-Erling Smørgrav 11907b5038d7SDag-Erling Smørgrav ldns_rr_type i_type_list[1024]; 11917b5038d7SDag-Erling Smørgrav size_t type_count = 0; 11927b5038d7SDag-Erling Smørgrav 11937b5038d7SDag-Erling Smørgrav hashed_owner = ldns_nsec3_hash_name(cur_owner, 11947b5038d7SDag-Erling Smørgrav algorithm, 11957b5038d7SDag-Erling Smørgrav iterations, 11967b5038d7SDag-Erling Smørgrav salt_length, 11977b5038d7SDag-Erling Smørgrav salt); 11987b5038d7SDag-Erling Smørgrav status = ldns_dname_cat(hashed_owner, cur_zone); 11992787e39aSDag-Erling Smørgrav if(status != LDNS_STATUS_OK) { 12002787e39aSDag-Erling Smørgrav ldns_rdf_deep_free(hashed_owner); 12017b5038d7SDag-Erling Smørgrav return NULL; 12022787e39aSDag-Erling Smørgrav } 12037b5038d7SDag-Erling Smørgrav nsec = ldns_rr_new_frm_type(LDNS_RR_TYPE_NSEC3); 12042787e39aSDag-Erling Smørgrav if(!nsec) { 12052787e39aSDag-Erling Smørgrav ldns_rdf_deep_free(hashed_owner); 12067b5038d7SDag-Erling Smørgrav return NULL; 12072787e39aSDag-Erling Smørgrav } 12087b5038d7SDag-Erling Smørgrav ldns_rr_set_type(nsec, LDNS_RR_TYPE_NSEC3); 12097b5038d7SDag-Erling Smørgrav ldns_rr_set_owner(nsec, hashed_owner); 12107b5038d7SDag-Erling Smørgrav 12117b5038d7SDag-Erling Smørgrav ldns_nsec3_add_param_rdfs(nsec, 12127b5038d7SDag-Erling Smørgrav algorithm, 12137b5038d7SDag-Erling Smørgrav flags, 12147b5038d7SDag-Erling Smørgrav iterations, 12157b5038d7SDag-Erling Smørgrav salt_length, 12167b5038d7SDag-Erling Smørgrav salt); 12177b5038d7SDag-Erling Smørgrav (void) ldns_rr_set_rdf(nsec, NULL, 4); 12187b5038d7SDag-Erling Smørgrav 12197b5038d7SDag-Erling Smørgrav 12207b5038d7SDag-Erling Smørgrav for (i = 0; i < ldns_rr_list_rr_count(rrs); i++) { 12217b5038d7SDag-Erling Smørgrav i_rr = ldns_rr_list_rr(rrs, i); 12227b5038d7SDag-Erling Smørgrav if (ldns_rdf_compare(cur_owner, 12237b5038d7SDag-Erling Smørgrav ldns_rr_owner(i_rr)) == 0) { 12247b5038d7SDag-Erling Smørgrav i_type = ldns_rr_get_type(i_rr); 12257b5038d7SDag-Erling Smørgrav if (type_count == 0 || i_type_list[type_count-1] != i_type) { 12267b5038d7SDag-Erling Smørgrav i_type_list[type_count] = i_type; 12277b5038d7SDag-Erling Smørgrav type_count++; 12287b5038d7SDag-Erling Smørgrav } 12297b5038d7SDag-Erling Smørgrav } 12307b5038d7SDag-Erling Smørgrav } 12317b5038d7SDag-Erling Smørgrav 12327b5038d7SDag-Erling Smørgrav /* add RRSIG anyway, but only if this is not an ENT or 12337b5038d7SDag-Erling Smørgrav * an unsigned delegation */ 12347b5038d7SDag-Erling Smørgrav if (!emptynonterminal && !rr_list_delegation_only(cur_zone, rrs)) { 12357b5038d7SDag-Erling Smørgrav i_type_list[type_count] = LDNS_RR_TYPE_RRSIG; 12367b5038d7SDag-Erling Smørgrav type_count++; 12377b5038d7SDag-Erling Smørgrav } 12387b5038d7SDag-Erling Smørgrav 12397b5038d7SDag-Erling Smørgrav /* and SOA if owner == zone */ 12407b5038d7SDag-Erling Smørgrav if (ldns_dname_compare(cur_zone, cur_owner) == 0) { 12417b5038d7SDag-Erling Smørgrav i_type_list[type_count] = LDNS_RR_TYPE_SOA; 12427b5038d7SDag-Erling Smørgrav type_count++; 12437b5038d7SDag-Erling Smørgrav } 12447b5038d7SDag-Erling Smørgrav 12457b5038d7SDag-Erling Smørgrav ldns_rr_push_rdf(nsec, 12467b5038d7SDag-Erling Smørgrav ldns_dnssec_create_nsec_bitmap(i_type_list, 12477b5038d7SDag-Erling Smørgrav type_count, LDNS_RR_TYPE_NSEC3)); 12487b5038d7SDag-Erling Smørgrav 12497b5038d7SDag-Erling Smørgrav return nsec; 12507b5038d7SDag-Erling Smørgrav } 12517b5038d7SDag-Erling Smørgrav 12527b5038d7SDag-Erling Smørgrav uint8_t 12537b5038d7SDag-Erling Smørgrav ldns_nsec3_algorithm(const ldns_rr *nsec3_rr) 12547b5038d7SDag-Erling Smørgrav { 12557b5038d7SDag-Erling Smørgrav if (nsec3_rr && 12567b5038d7SDag-Erling Smørgrav (ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3 || 12577b5038d7SDag-Erling Smørgrav ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3PARAM) 12587b5038d7SDag-Erling Smørgrav && (ldns_rr_rdf(nsec3_rr, 0) != NULL) 12597b5038d7SDag-Erling Smørgrav && ldns_rdf_size(ldns_rr_rdf(nsec3_rr, 0)) > 0) { 12607b5038d7SDag-Erling Smørgrav return ldns_rdf2native_int8(ldns_rr_rdf(nsec3_rr, 0)); 12617b5038d7SDag-Erling Smørgrav } 12627b5038d7SDag-Erling Smørgrav return 0; 12637b5038d7SDag-Erling Smørgrav } 12647b5038d7SDag-Erling Smørgrav 12657b5038d7SDag-Erling Smørgrav uint8_t 12667b5038d7SDag-Erling Smørgrav ldns_nsec3_flags(const ldns_rr *nsec3_rr) 12677b5038d7SDag-Erling Smørgrav { 12687b5038d7SDag-Erling Smørgrav if (nsec3_rr && 12697b5038d7SDag-Erling Smørgrav (ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3 || 12707b5038d7SDag-Erling Smørgrav ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3PARAM) 12717b5038d7SDag-Erling Smørgrav && (ldns_rr_rdf(nsec3_rr, 1) != NULL) 12727b5038d7SDag-Erling Smørgrav && ldns_rdf_size(ldns_rr_rdf(nsec3_rr, 1)) > 0) { 12737b5038d7SDag-Erling Smørgrav return ldns_rdf2native_int8(ldns_rr_rdf(nsec3_rr, 1)); 12747b5038d7SDag-Erling Smørgrav } 12757b5038d7SDag-Erling Smørgrav return 0; 12767b5038d7SDag-Erling Smørgrav } 12777b5038d7SDag-Erling Smørgrav 12787b5038d7SDag-Erling Smørgrav bool 12797b5038d7SDag-Erling Smørgrav ldns_nsec3_optout(const ldns_rr *nsec3_rr) 12807b5038d7SDag-Erling Smørgrav { 12817b5038d7SDag-Erling Smørgrav return (ldns_nsec3_flags(nsec3_rr) & LDNS_NSEC3_VARS_OPTOUT_MASK); 12827b5038d7SDag-Erling Smørgrav } 12837b5038d7SDag-Erling Smørgrav 12847b5038d7SDag-Erling Smørgrav uint16_t 12857b5038d7SDag-Erling Smørgrav ldns_nsec3_iterations(const ldns_rr *nsec3_rr) 12867b5038d7SDag-Erling Smørgrav { 12877b5038d7SDag-Erling Smørgrav if (nsec3_rr && 12887b5038d7SDag-Erling Smørgrav (ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3 || 12897b5038d7SDag-Erling Smørgrav ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3PARAM) 12907b5038d7SDag-Erling Smørgrav && (ldns_rr_rdf(nsec3_rr, 2) != NULL) 12917b5038d7SDag-Erling Smørgrav && ldns_rdf_size(ldns_rr_rdf(nsec3_rr, 2)) > 0) { 12927b5038d7SDag-Erling Smørgrav return ldns_rdf2native_int16(ldns_rr_rdf(nsec3_rr, 2)); 12937b5038d7SDag-Erling Smørgrav } 12947b5038d7SDag-Erling Smørgrav return 0; 12957b5038d7SDag-Erling Smørgrav 12967b5038d7SDag-Erling Smørgrav } 12977b5038d7SDag-Erling Smørgrav 12987b5038d7SDag-Erling Smørgrav ldns_rdf * 12997b5038d7SDag-Erling Smørgrav ldns_nsec3_salt(const ldns_rr *nsec3_rr) 13007b5038d7SDag-Erling Smørgrav { 13017b5038d7SDag-Erling Smørgrav if (nsec3_rr && 13027b5038d7SDag-Erling Smørgrav (ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3 || 13037b5038d7SDag-Erling Smørgrav ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3PARAM) 13047b5038d7SDag-Erling Smørgrav ) { 13057b5038d7SDag-Erling Smørgrav return ldns_rr_rdf(nsec3_rr, 3); 13067b5038d7SDag-Erling Smørgrav } 13077b5038d7SDag-Erling Smørgrav return NULL; 13087b5038d7SDag-Erling Smørgrav } 13097b5038d7SDag-Erling Smørgrav 13107b5038d7SDag-Erling Smørgrav uint8_t 13117b5038d7SDag-Erling Smørgrav ldns_nsec3_salt_length(const ldns_rr *nsec3_rr) 13127b5038d7SDag-Erling Smørgrav { 13137b5038d7SDag-Erling Smørgrav ldns_rdf *salt_rdf = ldns_nsec3_salt(nsec3_rr); 13147b5038d7SDag-Erling Smørgrav if (salt_rdf && ldns_rdf_size(salt_rdf) > 0) { 13157b5038d7SDag-Erling Smørgrav return (uint8_t) ldns_rdf_data(salt_rdf)[0]; 13167b5038d7SDag-Erling Smørgrav } 13177b5038d7SDag-Erling Smørgrav return 0; 13187b5038d7SDag-Erling Smørgrav } 13197b5038d7SDag-Erling Smørgrav 13207b5038d7SDag-Erling Smørgrav /* allocs data, free with LDNS_FREE() */ 13217b5038d7SDag-Erling Smørgrav uint8_t * 13227b5038d7SDag-Erling Smørgrav ldns_nsec3_salt_data(const ldns_rr *nsec3_rr) 13237b5038d7SDag-Erling Smørgrav { 13247b5038d7SDag-Erling Smørgrav uint8_t salt_length; 13257b5038d7SDag-Erling Smørgrav uint8_t *salt; 13267b5038d7SDag-Erling Smørgrav 13277b5038d7SDag-Erling Smørgrav ldns_rdf *salt_rdf = ldns_nsec3_salt(nsec3_rr); 13287b5038d7SDag-Erling Smørgrav if (salt_rdf && ldns_rdf_size(salt_rdf) > 0) { 13297b5038d7SDag-Erling Smørgrav salt_length = ldns_rdf_data(salt_rdf)[0]; 13307b5038d7SDag-Erling Smørgrav salt = LDNS_XMALLOC(uint8_t, salt_length); 13317b5038d7SDag-Erling Smørgrav if(!salt) return NULL; 13327b5038d7SDag-Erling Smørgrav memcpy(salt, &ldns_rdf_data(salt_rdf)[1], salt_length); 13337b5038d7SDag-Erling Smørgrav return salt; 13347b5038d7SDag-Erling Smørgrav } 13357b5038d7SDag-Erling Smørgrav return NULL; 13367b5038d7SDag-Erling Smørgrav } 13377b5038d7SDag-Erling Smørgrav 13387b5038d7SDag-Erling Smørgrav ldns_rdf * 13397b5038d7SDag-Erling Smørgrav ldns_nsec3_next_owner(const ldns_rr *nsec3_rr) 13407b5038d7SDag-Erling Smørgrav { 13417b5038d7SDag-Erling Smørgrav if (!nsec3_rr || ldns_rr_get_type(nsec3_rr) != LDNS_RR_TYPE_NSEC3) { 13427b5038d7SDag-Erling Smørgrav return NULL; 13437b5038d7SDag-Erling Smørgrav } else { 13447b5038d7SDag-Erling Smørgrav return ldns_rr_rdf(nsec3_rr, 4); 13457b5038d7SDag-Erling Smørgrav } 13467b5038d7SDag-Erling Smørgrav } 13477b5038d7SDag-Erling Smørgrav 13487b5038d7SDag-Erling Smørgrav ldns_rdf * 13497b5038d7SDag-Erling Smørgrav ldns_nsec3_bitmap(const ldns_rr *nsec3_rr) 13507b5038d7SDag-Erling Smørgrav { 13517b5038d7SDag-Erling Smørgrav if (!nsec3_rr || ldns_rr_get_type(nsec3_rr) != LDNS_RR_TYPE_NSEC3) { 13527b5038d7SDag-Erling Smørgrav return NULL; 13537b5038d7SDag-Erling Smørgrav } else { 13547b5038d7SDag-Erling Smørgrav return ldns_rr_rdf(nsec3_rr, 5); 13557b5038d7SDag-Erling Smørgrav } 13567b5038d7SDag-Erling Smørgrav } 13577b5038d7SDag-Erling Smørgrav 13587b5038d7SDag-Erling Smørgrav ldns_rdf * 1359*986ba33cSDag-Erling Smørgrav ldns_nsec3_hash_name_frm_nsec3(const ldns_rr *nsec, const ldns_rdf *name) 13607b5038d7SDag-Erling Smørgrav { 13617b5038d7SDag-Erling Smørgrav uint8_t algorithm; 13627b5038d7SDag-Erling Smørgrav uint16_t iterations; 13637b5038d7SDag-Erling Smørgrav uint8_t salt_length; 13647b5038d7SDag-Erling Smørgrav uint8_t *salt = 0; 13657b5038d7SDag-Erling Smørgrav 13667b5038d7SDag-Erling Smørgrav ldns_rdf *hashed_owner; 13677b5038d7SDag-Erling Smørgrav 13687b5038d7SDag-Erling Smørgrav algorithm = ldns_nsec3_algorithm(nsec); 13697b5038d7SDag-Erling Smørgrav salt_length = ldns_nsec3_salt_length(nsec); 13707b5038d7SDag-Erling Smørgrav salt = ldns_nsec3_salt_data(nsec); 13717b5038d7SDag-Erling Smørgrav iterations = ldns_nsec3_iterations(nsec); 13727b5038d7SDag-Erling Smørgrav 13737b5038d7SDag-Erling Smørgrav hashed_owner = ldns_nsec3_hash_name(name, 13747b5038d7SDag-Erling Smørgrav algorithm, 13757b5038d7SDag-Erling Smørgrav iterations, 13767b5038d7SDag-Erling Smørgrav salt_length, 13777b5038d7SDag-Erling Smørgrav salt); 13787b5038d7SDag-Erling Smørgrav 13797b5038d7SDag-Erling Smørgrav LDNS_FREE(salt); 13807b5038d7SDag-Erling Smørgrav return hashed_owner; 13817b5038d7SDag-Erling Smørgrav } 13827b5038d7SDag-Erling Smørgrav 13837b5038d7SDag-Erling Smørgrav bool 138417d15b25SDag-Erling Smørgrav ldns_nsec_bitmap_covers_type(const ldns_rdf* bitmap, ldns_rr_type type) 13857b5038d7SDag-Erling Smørgrav { 138617d15b25SDag-Erling Smørgrav uint8_t* dptr; 138717d15b25SDag-Erling Smørgrav uint8_t* dend; 13887b5038d7SDag-Erling Smørgrav 138917d15b25SDag-Erling Smørgrav /* From RFC3845 Section 2.1.2: 139017d15b25SDag-Erling Smørgrav * 139117d15b25SDag-Erling Smørgrav * "The RR type space is split into 256 window blocks, each re- 139217d15b25SDag-Erling Smørgrav * presenting the low-order 8 bits of the 16-bit RR type space." 139317d15b25SDag-Erling Smørgrav */ 139417d15b25SDag-Erling Smørgrav uint8_t window = type >> 8; 139517d15b25SDag-Erling Smørgrav uint8_t subtype = type & 0xff; 139617d15b25SDag-Erling Smørgrav 139717d15b25SDag-Erling Smørgrav if (! bitmap) { 13987b5038d7SDag-Erling Smørgrav return false; 13997b5038d7SDag-Erling Smørgrav } 140017d15b25SDag-Erling Smørgrav assert(ldns_rdf_get_type(bitmap) == LDNS_RDF_TYPE_BITMAP); 14017b5038d7SDag-Erling Smørgrav 140217d15b25SDag-Erling Smørgrav dptr = ldns_rdf_data(bitmap); 140317d15b25SDag-Erling Smørgrav dend = ldns_rdf_data(bitmap) + ldns_rdf_size(bitmap); 14047b5038d7SDag-Erling Smørgrav 140517d15b25SDag-Erling Smørgrav /* Type Bitmap = ( Window Block # | Bitmap Length | Bitmap ) + 140617d15b25SDag-Erling Smørgrav * dptr[0] dptr[1] dptr[2:] 140717d15b25SDag-Erling Smørgrav */ 140817d15b25SDag-Erling Smørgrav while (dptr < dend && dptr[0] <= window) { 140917d15b25SDag-Erling Smørgrav 141017d15b25SDag-Erling Smørgrav if (dptr[0] == window && subtype / 8 < dptr[1] && 141117d15b25SDag-Erling Smørgrav dptr + dptr[1] + 2 <= dend) { 141217d15b25SDag-Erling Smørgrav 141317d15b25SDag-Erling Smørgrav return dptr[2 + subtype / 8] & (0x80 >> (subtype % 8)); 141417d15b25SDag-Erling Smørgrav } 141517d15b25SDag-Erling Smørgrav dptr += dptr[1] + 2; /* next window */ 14167b5038d7SDag-Erling Smørgrav } 14177b5038d7SDag-Erling Smørgrav return false; 14187b5038d7SDag-Erling Smørgrav } 14197b5038d7SDag-Erling Smørgrav 142017d15b25SDag-Erling Smørgrav ldns_status 142117d15b25SDag-Erling Smørgrav ldns_nsec_bitmap_set_type(ldns_rdf* bitmap, ldns_rr_type type) 142217d15b25SDag-Erling Smørgrav { 142317d15b25SDag-Erling Smørgrav uint8_t* dptr; 142417d15b25SDag-Erling Smørgrav uint8_t* dend; 142517d15b25SDag-Erling Smørgrav 142617d15b25SDag-Erling Smørgrav /* From RFC3845 Section 2.1.2: 142717d15b25SDag-Erling Smørgrav * 142817d15b25SDag-Erling Smørgrav * "The RR type space is split into 256 window blocks, each re- 142917d15b25SDag-Erling Smørgrav * presenting the low-order 8 bits of the 16-bit RR type space." 143017d15b25SDag-Erling Smørgrav */ 143117d15b25SDag-Erling Smørgrav uint8_t window = type >> 8; 143217d15b25SDag-Erling Smørgrav uint8_t subtype = type & 0xff; 143317d15b25SDag-Erling Smørgrav 143417d15b25SDag-Erling Smørgrav if (! bitmap) { 143517d15b25SDag-Erling Smørgrav return false; 143617d15b25SDag-Erling Smørgrav } 143717d15b25SDag-Erling Smørgrav assert(ldns_rdf_get_type(bitmap) == LDNS_RDF_TYPE_BITMAP); 143817d15b25SDag-Erling Smørgrav 143917d15b25SDag-Erling Smørgrav dptr = ldns_rdf_data(bitmap); 144017d15b25SDag-Erling Smørgrav dend = ldns_rdf_data(bitmap) + ldns_rdf_size(bitmap); 144117d15b25SDag-Erling Smørgrav 144217d15b25SDag-Erling Smørgrav /* Type Bitmap = ( Window Block # | Bitmap Length | Bitmap ) + 144317d15b25SDag-Erling Smørgrav * dptr[0] dptr[1] dptr[2:] 144417d15b25SDag-Erling Smørgrav */ 144517d15b25SDag-Erling Smørgrav while (dptr < dend && dptr[0] <= window) { 144617d15b25SDag-Erling Smørgrav 144717d15b25SDag-Erling Smørgrav if (dptr[0] == window && subtype / 8 < dptr[1] && 144817d15b25SDag-Erling Smørgrav dptr + dptr[1] + 2 <= dend) { 144917d15b25SDag-Erling Smørgrav 145017d15b25SDag-Erling Smørgrav dptr[2 + subtype / 8] |= (0x80 >> (subtype % 8)); 145117d15b25SDag-Erling Smørgrav return LDNS_STATUS_OK; 145217d15b25SDag-Erling Smørgrav } 145317d15b25SDag-Erling Smørgrav dptr += dptr[1] + 2; /* next window */ 145417d15b25SDag-Erling Smørgrav } 145517d15b25SDag-Erling Smørgrav return LDNS_STATUS_TYPE_NOT_IN_BITMAP; 145617d15b25SDag-Erling Smørgrav } 145717d15b25SDag-Erling Smørgrav 145817d15b25SDag-Erling Smørgrav ldns_status 145917d15b25SDag-Erling Smørgrav ldns_nsec_bitmap_clear_type(ldns_rdf* bitmap, ldns_rr_type type) 146017d15b25SDag-Erling Smørgrav { 146117d15b25SDag-Erling Smørgrav uint8_t* dptr; 146217d15b25SDag-Erling Smørgrav uint8_t* dend; 146317d15b25SDag-Erling Smørgrav 146417d15b25SDag-Erling Smørgrav /* From RFC3845 Section 2.1.2: 146517d15b25SDag-Erling Smørgrav * 146617d15b25SDag-Erling Smørgrav * "The RR type space is split into 256 window blocks, each re- 146717d15b25SDag-Erling Smørgrav * presenting the low-order 8 bits of the 16-bit RR type space." 146817d15b25SDag-Erling Smørgrav */ 146917d15b25SDag-Erling Smørgrav uint8_t window = type >> 8; 147017d15b25SDag-Erling Smørgrav uint8_t subtype = type & 0xff; 147117d15b25SDag-Erling Smørgrav 147217d15b25SDag-Erling Smørgrav if (! bitmap) { 147317d15b25SDag-Erling Smørgrav return false; 147417d15b25SDag-Erling Smørgrav } 147517d15b25SDag-Erling Smørgrav 147617d15b25SDag-Erling Smørgrav assert(ldns_rdf_get_type(bitmap) == LDNS_RDF_TYPE_BITMAP); 147717d15b25SDag-Erling Smørgrav 147817d15b25SDag-Erling Smørgrav dptr = ldns_rdf_data(bitmap); 147917d15b25SDag-Erling Smørgrav dend = ldns_rdf_data(bitmap) + ldns_rdf_size(bitmap); 148017d15b25SDag-Erling Smørgrav 148117d15b25SDag-Erling Smørgrav /* Type Bitmap = ( Window Block # | Bitmap Length | Bitmap ) + 148217d15b25SDag-Erling Smørgrav * dptr[0] dptr[1] dptr[2:] 148317d15b25SDag-Erling Smørgrav */ 148417d15b25SDag-Erling Smørgrav while (dptr < dend && dptr[0] <= window) { 148517d15b25SDag-Erling Smørgrav 148617d15b25SDag-Erling Smørgrav if (dptr[0] == window && subtype / 8 < dptr[1] && 148717d15b25SDag-Erling Smørgrav dptr + dptr[1] + 2 <= dend) { 148817d15b25SDag-Erling Smørgrav 148917d15b25SDag-Erling Smørgrav dptr[2 + subtype / 8] &= ~(0x80 >> (subtype % 8)); 149017d15b25SDag-Erling Smørgrav return LDNS_STATUS_OK; 149117d15b25SDag-Erling Smørgrav } 149217d15b25SDag-Erling Smørgrav dptr += dptr[1] + 2; /* next window */ 149317d15b25SDag-Erling Smørgrav } 149417d15b25SDag-Erling Smørgrav return LDNS_STATUS_TYPE_NOT_IN_BITMAP; 149517d15b25SDag-Erling Smørgrav } 149617d15b25SDag-Erling Smørgrav 149717d15b25SDag-Erling Smørgrav 14987b5038d7SDag-Erling Smørgrav bool 14997b5038d7SDag-Erling Smørgrav ldns_nsec_covers_name(const ldns_rr *nsec, const ldns_rdf *name) 15007b5038d7SDag-Erling Smørgrav { 15017b5038d7SDag-Erling Smørgrav ldns_rdf *nsec_owner = ldns_rr_owner(nsec); 15027b5038d7SDag-Erling Smørgrav ldns_rdf *hash_next; 15037b5038d7SDag-Erling Smørgrav char *next_hash_str; 15047b5038d7SDag-Erling Smørgrav ldns_rdf *nsec_next = NULL; 15057b5038d7SDag-Erling Smørgrav ldns_status status; 15067b5038d7SDag-Erling Smørgrav ldns_rdf *chopped_dname; 15077b5038d7SDag-Erling Smørgrav bool result; 15087b5038d7SDag-Erling Smørgrav 15097b5038d7SDag-Erling Smørgrav if (ldns_rr_get_type(nsec) == LDNS_RR_TYPE_NSEC) { 15107b5038d7SDag-Erling Smørgrav if (ldns_rr_rdf(nsec, 0) != NULL) { 15117b5038d7SDag-Erling Smørgrav nsec_next = ldns_rdf_clone(ldns_rr_rdf(nsec, 0)); 15127b5038d7SDag-Erling Smørgrav } else { 15137b5038d7SDag-Erling Smørgrav return false; 15147b5038d7SDag-Erling Smørgrav } 15157b5038d7SDag-Erling Smørgrav } else if (ldns_rr_get_type(nsec) == LDNS_RR_TYPE_NSEC3) { 15167b5038d7SDag-Erling Smørgrav hash_next = ldns_nsec3_next_owner(nsec); 15177b5038d7SDag-Erling Smørgrav next_hash_str = ldns_rdf2str(hash_next); 15187b5038d7SDag-Erling Smørgrav nsec_next = ldns_dname_new_frm_str(next_hash_str); 15197b5038d7SDag-Erling Smørgrav LDNS_FREE(next_hash_str); 15207b5038d7SDag-Erling Smørgrav chopped_dname = ldns_dname_left_chop(nsec_owner); 15217b5038d7SDag-Erling Smørgrav status = ldns_dname_cat(nsec_next, chopped_dname); 15227b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(chopped_dname); 15237b5038d7SDag-Erling Smørgrav if (status != LDNS_STATUS_OK) { 15247b5038d7SDag-Erling Smørgrav printf("error catting: %s\n", ldns_get_errorstr_by_id(status)); 15257b5038d7SDag-Erling Smørgrav } 15267b5038d7SDag-Erling Smørgrav } else { 15277b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(nsec_next); 15287b5038d7SDag-Erling Smørgrav return false; 15297b5038d7SDag-Erling Smørgrav } 15307b5038d7SDag-Erling Smørgrav 15317b5038d7SDag-Erling Smørgrav /* in the case of the last nsec */ 15327b5038d7SDag-Erling Smørgrav if(ldns_dname_compare(nsec_owner, nsec_next) > 0) { 15337b5038d7SDag-Erling Smørgrav result = (ldns_dname_compare(nsec_owner, name) <= 0 || 15347b5038d7SDag-Erling Smørgrav ldns_dname_compare(name, nsec_next) < 0); 153517d15b25SDag-Erling Smørgrav } else if(ldns_dname_compare(nsec_owner, nsec_next) < 0) { 15367b5038d7SDag-Erling Smørgrav result = (ldns_dname_compare(nsec_owner, name) <= 0 && 15377b5038d7SDag-Erling Smørgrav ldns_dname_compare(name, nsec_next) < 0); 153817d15b25SDag-Erling Smørgrav } else { 153917d15b25SDag-Erling Smørgrav result = true; 15407b5038d7SDag-Erling Smørgrav } 15417b5038d7SDag-Erling Smørgrav 15427b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(nsec_next); 15437b5038d7SDag-Erling Smørgrav return result; 15447b5038d7SDag-Erling Smørgrav } 15457b5038d7SDag-Erling Smørgrav 15467b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL 15477b5038d7SDag-Erling Smørgrav /* sig may be null - if so look in the packet */ 15487b5038d7SDag-Erling Smørgrav 15497b5038d7SDag-Erling Smørgrav ldns_status 1550*986ba33cSDag-Erling Smørgrav ldns_pkt_verify_time(const ldns_pkt *p, ldns_rr_type t, const ldns_rdf *o, 1551*986ba33cSDag-Erling Smørgrav const ldns_rr_list *k, const ldns_rr_list *s, 15527b5038d7SDag-Erling Smørgrav time_t check_time, ldns_rr_list *good_keys) 15537b5038d7SDag-Erling Smørgrav { 15547b5038d7SDag-Erling Smørgrav ldns_rr_list *rrset; 15557b5038d7SDag-Erling Smørgrav ldns_rr_list *sigs; 15567b5038d7SDag-Erling Smørgrav ldns_rr_list *sigs_covered; 15577b5038d7SDag-Erling Smørgrav ldns_rdf *rdf_t; 15587b5038d7SDag-Erling Smørgrav ldns_rr_type t_netorder; 15597b5038d7SDag-Erling Smørgrav 15607b5038d7SDag-Erling Smørgrav if (!k) { 15617b5038d7SDag-Erling Smørgrav return LDNS_STATUS_ERR; 15627b5038d7SDag-Erling Smørgrav /* return LDNS_STATUS_CRYPTO_NO_DNSKEY; */ 15637b5038d7SDag-Erling Smørgrav } 15647b5038d7SDag-Erling Smørgrav 15657b5038d7SDag-Erling Smørgrav if (t == LDNS_RR_TYPE_RRSIG) { 15667b5038d7SDag-Erling Smørgrav /* we don't have RRSIG(RRSIG) (yet? ;-) ) */ 15677b5038d7SDag-Erling Smørgrav return LDNS_STATUS_ERR; 15687b5038d7SDag-Erling Smørgrav } 15697b5038d7SDag-Erling Smørgrav 15707b5038d7SDag-Erling Smørgrav if (s) { 15717b5038d7SDag-Erling Smørgrav /* if s is not NULL, the sigs are given to use */ 1572*986ba33cSDag-Erling Smørgrav sigs = (ldns_rr_list *)s; 15737b5038d7SDag-Erling Smørgrav } else { 15747b5038d7SDag-Erling Smørgrav /* otherwise get them from the packet */ 15752787e39aSDag-Erling Smørgrav sigs = ldns_pkt_rr_list_by_name_and_type(p, o, 15762787e39aSDag-Erling Smørgrav LDNS_RR_TYPE_RRSIG, 15777b5038d7SDag-Erling Smørgrav LDNS_SECTION_ANY_NOQUESTION); 15787b5038d7SDag-Erling Smørgrav if (!sigs) { 15797b5038d7SDag-Erling Smørgrav /* no sigs */ 15807b5038d7SDag-Erling Smørgrav return LDNS_STATUS_ERR; 15817b5038d7SDag-Erling Smørgrav /* return LDNS_STATUS_CRYPTO_NO_RRSIG; */ 15827b5038d7SDag-Erling Smørgrav } 15837b5038d7SDag-Erling Smørgrav } 15847b5038d7SDag-Erling Smørgrav 15857b5038d7SDag-Erling Smørgrav /* rrsig are subtyped, so now we need to find the correct 15867b5038d7SDag-Erling Smørgrav * sigs for the type t 15877b5038d7SDag-Erling Smørgrav */ 15887b5038d7SDag-Erling Smørgrav t_netorder = htons(t); /* rdf are in network order! */ 15897b5038d7SDag-Erling Smørgrav /* a type identifier is a 16-bit number, so the size is 2 bytes */ 15902787e39aSDag-Erling Smørgrav rdf_t = ldns_rdf_new(LDNS_RDF_TYPE_TYPE, 2, &t_netorder); 15912787e39aSDag-Erling Smørgrav 15927b5038d7SDag-Erling Smørgrav sigs_covered = ldns_rr_list_subtype_by_rdf(sigs, rdf_t, 0); 15932787e39aSDag-Erling Smørgrav ldns_rdf_free(rdf_t); 15947b5038d7SDag-Erling Smørgrav if (! sigs_covered) { 15952787e39aSDag-Erling Smørgrav if (! s) { 15962787e39aSDag-Erling Smørgrav ldns_rr_list_deep_free(sigs); 15972787e39aSDag-Erling Smørgrav } 15987b5038d7SDag-Erling Smørgrav return LDNS_STATUS_ERR; 15997b5038d7SDag-Erling Smørgrav } 16002787e39aSDag-Erling Smørgrav ldns_rr_list_deep_free(sigs_covered); 16017b5038d7SDag-Erling Smørgrav 16022787e39aSDag-Erling Smørgrav rrset = ldns_pkt_rr_list_by_name_and_type(p, o, t, 16032787e39aSDag-Erling Smørgrav LDNS_SECTION_ANY_NOQUESTION); 16042787e39aSDag-Erling Smørgrav if (!rrset) { 16052787e39aSDag-Erling Smørgrav if (! s) { 16062787e39aSDag-Erling Smørgrav ldns_rr_list_deep_free(sigs); 16072787e39aSDag-Erling Smørgrav } 16082787e39aSDag-Erling Smørgrav return LDNS_STATUS_ERR; 16092787e39aSDag-Erling Smørgrav } 16107b5038d7SDag-Erling Smørgrav return ldns_verify_time(rrset, sigs, k, check_time, good_keys); 16117b5038d7SDag-Erling Smørgrav } 16127b5038d7SDag-Erling Smørgrav 16137b5038d7SDag-Erling Smørgrav ldns_status 1614*986ba33cSDag-Erling Smørgrav ldns_pkt_verify(const ldns_pkt *p, ldns_rr_type t, const ldns_rdf *o, 1615*986ba33cSDag-Erling Smørgrav const ldns_rr_list *k, const ldns_rr_list *s, ldns_rr_list *good_keys) 16167b5038d7SDag-Erling Smørgrav { 16177b5038d7SDag-Erling Smørgrav return ldns_pkt_verify_time(p, t, o, k, s, ldns_time(NULL), good_keys); 16187b5038d7SDag-Erling Smørgrav } 16197b5038d7SDag-Erling Smørgrav #endif /* HAVE_SSL */ 16207b5038d7SDag-Erling Smørgrav 16217b5038d7SDag-Erling Smørgrav ldns_status 16227b5038d7SDag-Erling Smørgrav ldns_dnssec_chain_nsec3_list(ldns_rr_list *nsec3_rrs) 16237b5038d7SDag-Erling Smørgrav { 16247b5038d7SDag-Erling Smørgrav size_t i; 16257b5038d7SDag-Erling Smørgrav char *next_nsec_owner_str; 16267b5038d7SDag-Erling Smørgrav ldns_rdf *next_nsec_owner_label; 16277b5038d7SDag-Erling Smørgrav ldns_rdf *next_nsec_rdf; 16287b5038d7SDag-Erling Smørgrav ldns_status status = LDNS_STATUS_OK; 16297b5038d7SDag-Erling Smørgrav 16307b5038d7SDag-Erling Smørgrav for (i = 0; i < ldns_rr_list_rr_count(nsec3_rrs); i++) { 16317b5038d7SDag-Erling Smørgrav if (i == ldns_rr_list_rr_count(nsec3_rrs) - 1) { 16327b5038d7SDag-Erling Smørgrav next_nsec_owner_label = 16337b5038d7SDag-Erling Smørgrav ldns_dname_label(ldns_rr_owner(ldns_rr_list_rr(nsec3_rrs, 16347b5038d7SDag-Erling Smørgrav 0)), 0); 16357b5038d7SDag-Erling Smørgrav next_nsec_owner_str = ldns_rdf2str(next_nsec_owner_label); 16367b5038d7SDag-Erling Smørgrav if (next_nsec_owner_str[strlen(next_nsec_owner_str) - 1] 16377b5038d7SDag-Erling Smørgrav == '.') { 16387b5038d7SDag-Erling Smørgrav next_nsec_owner_str[strlen(next_nsec_owner_str) - 1] 16397b5038d7SDag-Erling Smørgrav = '\0'; 16407b5038d7SDag-Erling Smørgrav } 16417b5038d7SDag-Erling Smørgrav status = ldns_str2rdf_b32_ext(&next_nsec_rdf, 16427b5038d7SDag-Erling Smørgrav next_nsec_owner_str); 16437b5038d7SDag-Erling Smørgrav if (!ldns_rr_set_rdf(ldns_rr_list_rr(nsec3_rrs, i), 16447b5038d7SDag-Erling Smørgrav next_nsec_rdf, 4)) { 16457b5038d7SDag-Erling Smørgrav /* todo: error */ 16467b5038d7SDag-Erling Smørgrav } 16477b5038d7SDag-Erling Smørgrav 16487b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(next_nsec_owner_label); 16497b5038d7SDag-Erling Smørgrav LDNS_FREE(next_nsec_owner_str); 16507b5038d7SDag-Erling Smørgrav } else { 16517b5038d7SDag-Erling Smørgrav next_nsec_owner_label = 16527b5038d7SDag-Erling Smørgrav ldns_dname_label(ldns_rr_owner(ldns_rr_list_rr(nsec3_rrs, 16537b5038d7SDag-Erling Smørgrav i + 1)), 16547b5038d7SDag-Erling Smørgrav 0); 16557b5038d7SDag-Erling Smørgrav next_nsec_owner_str = ldns_rdf2str(next_nsec_owner_label); 16567b5038d7SDag-Erling Smørgrav if (next_nsec_owner_str[strlen(next_nsec_owner_str) - 1] 16577b5038d7SDag-Erling Smørgrav == '.') { 16587b5038d7SDag-Erling Smørgrav next_nsec_owner_str[strlen(next_nsec_owner_str) - 1] 16597b5038d7SDag-Erling Smørgrav = '\0'; 16607b5038d7SDag-Erling Smørgrav } 16617b5038d7SDag-Erling Smørgrav status = ldns_str2rdf_b32_ext(&next_nsec_rdf, 16627b5038d7SDag-Erling Smørgrav next_nsec_owner_str); 16637b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(next_nsec_owner_label); 16647b5038d7SDag-Erling Smørgrav LDNS_FREE(next_nsec_owner_str); 16657b5038d7SDag-Erling Smørgrav if (!ldns_rr_set_rdf(ldns_rr_list_rr(nsec3_rrs, i), 16667b5038d7SDag-Erling Smørgrav next_nsec_rdf, 4)) { 16677b5038d7SDag-Erling Smørgrav /* todo: error */ 16687b5038d7SDag-Erling Smørgrav } 16697b5038d7SDag-Erling Smørgrav } 16707b5038d7SDag-Erling Smørgrav } 16717b5038d7SDag-Erling Smørgrav return status; 16727b5038d7SDag-Erling Smørgrav } 16737b5038d7SDag-Erling Smørgrav 16747b5038d7SDag-Erling Smørgrav int 16757b5038d7SDag-Erling Smørgrav qsort_rr_compare_nsec3(const void *a, const void *b) 16767b5038d7SDag-Erling Smørgrav { 16777b5038d7SDag-Erling Smørgrav const ldns_rr *rr1 = * (const ldns_rr **) a; 16787b5038d7SDag-Erling Smørgrav const ldns_rr *rr2 = * (const ldns_rr **) b; 16797b5038d7SDag-Erling Smørgrav if (rr1 == NULL && rr2 == NULL) { 16807b5038d7SDag-Erling Smørgrav return 0; 16817b5038d7SDag-Erling Smørgrav } 16827b5038d7SDag-Erling Smørgrav if (rr1 == NULL) { 16837b5038d7SDag-Erling Smørgrav return -1; 16847b5038d7SDag-Erling Smørgrav } 16857b5038d7SDag-Erling Smørgrav if (rr2 == NULL) { 16867b5038d7SDag-Erling Smørgrav return 1; 16877b5038d7SDag-Erling Smørgrav } 16887b5038d7SDag-Erling Smørgrav return ldns_rdf_compare(ldns_rr_owner(rr1), ldns_rr_owner(rr2)); 16897b5038d7SDag-Erling Smørgrav } 16907b5038d7SDag-Erling Smørgrav 16917b5038d7SDag-Erling Smørgrav void 16927b5038d7SDag-Erling Smørgrav ldns_rr_list_sort_nsec3(ldns_rr_list *unsorted) 16937b5038d7SDag-Erling Smørgrav { 16947b5038d7SDag-Erling Smørgrav qsort(unsorted->_rrs, 16957b5038d7SDag-Erling Smørgrav ldns_rr_list_rr_count(unsorted), 16967b5038d7SDag-Erling Smørgrav sizeof(ldns_rr *), 16977b5038d7SDag-Erling Smørgrav qsort_rr_compare_nsec3); 16987b5038d7SDag-Erling Smørgrav } 16997b5038d7SDag-Erling Smørgrav 17007b5038d7SDag-Erling Smørgrav int 17017b5038d7SDag-Erling Smørgrav ldns_dnssec_default_add_to_signatures( ATTR_UNUSED(ldns_rr *sig) 17027b5038d7SDag-Erling Smørgrav , ATTR_UNUSED(void *n) 17037b5038d7SDag-Erling Smørgrav ) 17047b5038d7SDag-Erling Smørgrav { 17057b5038d7SDag-Erling Smørgrav return LDNS_SIGNATURE_LEAVE_ADD_NEW; 17067b5038d7SDag-Erling Smørgrav } 17077b5038d7SDag-Erling Smørgrav 17087b5038d7SDag-Erling Smørgrav int 17097b5038d7SDag-Erling Smørgrav ldns_dnssec_default_leave_signatures( ATTR_UNUSED(ldns_rr *sig) 17107b5038d7SDag-Erling Smørgrav , ATTR_UNUSED(void *n) 17117b5038d7SDag-Erling Smørgrav ) 17127b5038d7SDag-Erling Smørgrav { 17137b5038d7SDag-Erling Smørgrav return LDNS_SIGNATURE_LEAVE_NO_ADD; 17147b5038d7SDag-Erling Smørgrav } 17157b5038d7SDag-Erling Smørgrav 17167b5038d7SDag-Erling Smørgrav int 17177b5038d7SDag-Erling Smørgrav ldns_dnssec_default_delete_signatures( ATTR_UNUSED(ldns_rr *sig) 17187b5038d7SDag-Erling Smørgrav , ATTR_UNUSED(void *n) 17197b5038d7SDag-Erling Smørgrav ) 17207b5038d7SDag-Erling Smørgrav { 17217b5038d7SDag-Erling Smørgrav return LDNS_SIGNATURE_REMOVE_NO_ADD; 17227b5038d7SDag-Erling Smørgrav } 17237b5038d7SDag-Erling Smørgrav 17247b5038d7SDag-Erling Smørgrav int 17257b5038d7SDag-Erling Smørgrav ldns_dnssec_default_replace_signatures( ATTR_UNUSED(ldns_rr *sig) 17267b5038d7SDag-Erling Smørgrav , ATTR_UNUSED(void *n) 17277b5038d7SDag-Erling Smørgrav ) 17287b5038d7SDag-Erling Smørgrav { 17297b5038d7SDag-Erling Smørgrav return LDNS_SIGNATURE_REMOVE_ADD_NEW; 17307b5038d7SDag-Erling Smørgrav } 17317b5038d7SDag-Erling Smørgrav 17327b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL 17337b5038d7SDag-Erling Smørgrav ldns_rdf * 17347b5038d7SDag-Erling Smørgrav ldns_convert_dsa_rrsig_asn12rdf(const ldns_buffer *sig, 17357b5038d7SDag-Erling Smørgrav const long sig_len) 17367b5038d7SDag-Erling Smørgrav { 1737*986ba33cSDag-Erling Smørgrav #ifdef USE_DSA 17387b5038d7SDag-Erling Smørgrav ldns_rdf *sigdata_rdf; 17397b5038d7SDag-Erling Smørgrav DSA_SIG *dsasig; 1740*986ba33cSDag-Erling Smørgrav const BIGNUM *R, *S; 17417b5038d7SDag-Erling Smørgrav unsigned char *dsasig_data = (unsigned char*)ldns_buffer_begin(sig); 17427b5038d7SDag-Erling Smørgrav size_t byte_offset; 17437b5038d7SDag-Erling Smørgrav 17447b5038d7SDag-Erling Smørgrav dsasig = d2i_DSA_SIG(NULL, 17457b5038d7SDag-Erling Smørgrav (const unsigned char **)&dsasig_data, 17467b5038d7SDag-Erling Smørgrav sig_len); 17477b5038d7SDag-Erling Smørgrav if (!dsasig) { 17487b5038d7SDag-Erling Smørgrav DSA_SIG_free(dsasig); 17497b5038d7SDag-Erling Smørgrav return NULL; 17507b5038d7SDag-Erling Smørgrav } 17517b5038d7SDag-Erling Smørgrav 17527b5038d7SDag-Erling Smørgrav dsasig_data = LDNS_XMALLOC(unsigned char, 41); 17537b5038d7SDag-Erling Smørgrav if(!dsasig_data) { 17547b5038d7SDag-Erling Smørgrav DSA_SIG_free(dsasig); 17557b5038d7SDag-Erling Smørgrav return NULL; 17567b5038d7SDag-Erling Smørgrav } 17577b5038d7SDag-Erling Smørgrav dsasig_data[0] = 0; 1758*986ba33cSDag-Erling Smørgrav # ifdef HAVE_DSA_SIG_GET0 1759*986ba33cSDag-Erling Smørgrav DSA_SIG_get0(dsasig, &R, &S); 1760*986ba33cSDag-Erling Smørgrav # else 1761*986ba33cSDag-Erling Smørgrav R = dsasig->r; 1762*986ba33cSDag-Erling Smørgrav S = dsasig->s; 1763*986ba33cSDag-Erling Smørgrav # endif 1764*986ba33cSDag-Erling Smørgrav byte_offset = (size_t) (20 - BN_num_bytes(R)); 17657b5038d7SDag-Erling Smørgrav if (byte_offset > 20) { 17667b5038d7SDag-Erling Smørgrav DSA_SIG_free(dsasig); 17677b5038d7SDag-Erling Smørgrav LDNS_FREE(dsasig_data); 17687b5038d7SDag-Erling Smørgrav return NULL; 17697b5038d7SDag-Erling Smørgrav } 17707b5038d7SDag-Erling Smørgrav memset(&dsasig_data[1], 0, byte_offset); 1771*986ba33cSDag-Erling Smørgrav BN_bn2bin(R, &dsasig_data[1 + byte_offset]); 1772*986ba33cSDag-Erling Smørgrav byte_offset = (size_t) (20 - BN_num_bytes(S)); 17737b5038d7SDag-Erling Smørgrav if (byte_offset > 20) { 17747b5038d7SDag-Erling Smørgrav DSA_SIG_free(dsasig); 17757b5038d7SDag-Erling Smørgrav LDNS_FREE(dsasig_data); 17767b5038d7SDag-Erling Smørgrav return NULL; 17777b5038d7SDag-Erling Smørgrav } 17787b5038d7SDag-Erling Smørgrav memset(&dsasig_data[21], 0, byte_offset); 1779*986ba33cSDag-Erling Smørgrav BN_bn2bin(S, &dsasig_data[21 + byte_offset]); 17807b5038d7SDag-Erling Smørgrav 17817b5038d7SDag-Erling Smørgrav sigdata_rdf = ldns_rdf_new(LDNS_RDF_TYPE_B64, 41, dsasig_data); 17827b5038d7SDag-Erling Smørgrav if(!sigdata_rdf) { 17837b5038d7SDag-Erling Smørgrav LDNS_FREE(dsasig_data); 17847b5038d7SDag-Erling Smørgrav } 17857b5038d7SDag-Erling Smørgrav DSA_SIG_free(dsasig); 17867b5038d7SDag-Erling Smørgrav 17877b5038d7SDag-Erling Smørgrav return sigdata_rdf; 1788*986ba33cSDag-Erling Smørgrav #else 1789*986ba33cSDag-Erling Smørgrav (void)sig; (void)sig_len; 1790*986ba33cSDag-Erling Smørgrav return NULL; 1791*986ba33cSDag-Erling Smørgrav #endif 17927b5038d7SDag-Erling Smørgrav } 17937b5038d7SDag-Erling Smørgrav 17947b5038d7SDag-Erling Smørgrav ldns_status 17957b5038d7SDag-Erling Smørgrav ldns_convert_dsa_rrsig_rdf2asn1(ldns_buffer *target_buffer, 17967b5038d7SDag-Erling Smørgrav const ldns_rdf *sig_rdf) 17977b5038d7SDag-Erling Smørgrav { 1798*986ba33cSDag-Erling Smørgrav #ifdef USE_DSA 17997b5038d7SDag-Erling Smørgrav /* the EVP api wants the DER encoding of the signature... */ 18007b5038d7SDag-Erling Smørgrav BIGNUM *R, *S; 18017b5038d7SDag-Erling Smørgrav DSA_SIG *dsasig; 18027b5038d7SDag-Erling Smørgrav unsigned char *raw_sig = NULL; 18037b5038d7SDag-Erling Smørgrav int raw_sig_len; 18047b5038d7SDag-Erling Smørgrav 18057b5038d7SDag-Erling Smørgrav if(ldns_rdf_size(sig_rdf) < 1 + 2*SHA_DIGEST_LENGTH) 18067b5038d7SDag-Erling Smørgrav return LDNS_STATUS_SYNTAX_RDATA_ERR; 18077b5038d7SDag-Erling Smørgrav /* extract the R and S field from the sig buffer */ 18087b5038d7SDag-Erling Smørgrav R = BN_new(); 18097b5038d7SDag-Erling Smørgrav if(!R) return LDNS_STATUS_MEM_ERR; 18107b5038d7SDag-Erling Smørgrav (void) BN_bin2bn((unsigned char *) ldns_rdf_data(sig_rdf) + 1, 18117b5038d7SDag-Erling Smørgrav SHA_DIGEST_LENGTH, R); 18127b5038d7SDag-Erling Smørgrav S = BN_new(); 18137b5038d7SDag-Erling Smørgrav if(!S) { 18147b5038d7SDag-Erling Smørgrav BN_free(R); 18157b5038d7SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR; 18167b5038d7SDag-Erling Smørgrav } 18177b5038d7SDag-Erling Smørgrav (void) BN_bin2bn((unsigned char *) ldns_rdf_data(sig_rdf) + 21, 18187b5038d7SDag-Erling Smørgrav SHA_DIGEST_LENGTH, S); 18197b5038d7SDag-Erling Smørgrav 18207b5038d7SDag-Erling Smørgrav dsasig = DSA_SIG_new(); 18217b5038d7SDag-Erling Smørgrav if (!dsasig) { 18227b5038d7SDag-Erling Smørgrav BN_free(R); 18237b5038d7SDag-Erling Smørgrav BN_free(S); 18247b5038d7SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR; 18257b5038d7SDag-Erling Smørgrav } 1826*986ba33cSDag-Erling Smørgrav # ifdef HAVE_DSA_SIG_SET0 1827*986ba33cSDag-Erling Smørgrav if (! DSA_SIG_set0(dsasig, R, S)) 1828*986ba33cSDag-Erling Smørgrav return LDNS_STATUS_SSL_ERR; 1829*986ba33cSDag-Erling Smørgrav # else 18307b5038d7SDag-Erling Smørgrav dsasig->r = R; 18317b5038d7SDag-Erling Smørgrav dsasig->s = S; 1832*986ba33cSDag-Erling Smørgrav # endif 18337b5038d7SDag-Erling Smørgrav 18347b5038d7SDag-Erling Smørgrav raw_sig_len = i2d_DSA_SIG(dsasig, &raw_sig); 18357b5038d7SDag-Erling Smørgrav if (raw_sig_len < 0) { 18367b5038d7SDag-Erling Smørgrav DSA_SIG_free(dsasig); 18377b5038d7SDag-Erling Smørgrav free(raw_sig); 18387b5038d7SDag-Erling Smørgrav return LDNS_STATUS_SSL_ERR; 18397b5038d7SDag-Erling Smørgrav } 18407b5038d7SDag-Erling Smørgrav if (ldns_buffer_reserve(target_buffer, (size_t) raw_sig_len)) { 18417b5038d7SDag-Erling Smørgrav ldns_buffer_write(target_buffer, raw_sig, (size_t)raw_sig_len); 18427b5038d7SDag-Erling Smørgrav } 18437b5038d7SDag-Erling Smørgrav 18447b5038d7SDag-Erling Smørgrav DSA_SIG_free(dsasig); 18457b5038d7SDag-Erling Smørgrav free(raw_sig); 18467b5038d7SDag-Erling Smørgrav 18477b5038d7SDag-Erling Smørgrav return ldns_buffer_status(target_buffer); 1848*986ba33cSDag-Erling Smørgrav #else 1849*986ba33cSDag-Erling Smørgrav (void)target_buffer; (void)sig_rdf; 1850*986ba33cSDag-Erling Smørgrav return LDNS_STATUS_CRYPTO_ALGO_NOT_IMPL; 1851*986ba33cSDag-Erling Smørgrav #endif 18527b5038d7SDag-Erling Smørgrav } 18537b5038d7SDag-Erling Smørgrav 18547b5038d7SDag-Erling Smørgrav #ifdef USE_ECDSA 18557b5038d7SDag-Erling Smørgrav #ifndef S_SPLINT_S 18567b5038d7SDag-Erling Smørgrav ldns_rdf * 1857*986ba33cSDag-Erling Smørgrav ldns_convert_ecdsa_rrsig_asn1len2rdf(const ldns_buffer *sig, 1858*986ba33cSDag-Erling Smørgrav const long sig_len, int num_bytes) 18597b5038d7SDag-Erling Smørgrav { 18607b5038d7SDag-Erling Smørgrav ECDSA_SIG* ecdsa_sig; 1861*986ba33cSDag-Erling Smørgrav const BIGNUM *r, *s; 18627b5038d7SDag-Erling Smørgrav unsigned char *data = (unsigned char*)ldns_buffer_begin(sig); 18637b5038d7SDag-Erling Smørgrav ldns_rdf* rdf; 18647b5038d7SDag-Erling Smørgrav ecdsa_sig = d2i_ECDSA_SIG(NULL, (const unsigned char **)&data, sig_len); 18657b5038d7SDag-Erling Smørgrav if(!ecdsa_sig) return NULL; 18667b5038d7SDag-Erling Smørgrav 1867*986ba33cSDag-Erling Smørgrav #ifdef HAVE_ECDSA_SIG_GET0 1868*986ba33cSDag-Erling Smørgrav ECDSA_SIG_get0(ecdsa_sig, &r, &s); 1869*986ba33cSDag-Erling Smørgrav #else 1870*986ba33cSDag-Erling Smørgrav r = ecdsa_sig->r; 1871*986ba33cSDag-Erling Smørgrav s = ecdsa_sig->s; 1872*986ba33cSDag-Erling Smørgrav #endif 18737b5038d7SDag-Erling Smørgrav /* "r | s". */ 1874*986ba33cSDag-Erling Smørgrav if(BN_num_bytes(r) > num_bytes || 1875*986ba33cSDag-Erling Smørgrav BN_num_bytes(s) > num_bytes) { 1876*986ba33cSDag-Erling Smørgrav ECDSA_SIG_free(ecdsa_sig); 1877*986ba33cSDag-Erling Smørgrav return NULL; /* numbers too big for passed curve size */ 1878*986ba33cSDag-Erling Smørgrav } 1879*986ba33cSDag-Erling Smørgrav data = LDNS_XMALLOC(unsigned char, num_bytes*2); 18807b5038d7SDag-Erling Smørgrav if(!data) { 18817b5038d7SDag-Erling Smørgrav ECDSA_SIG_free(ecdsa_sig); 18827b5038d7SDag-Erling Smørgrav return NULL; 18837b5038d7SDag-Erling Smørgrav } 1884*986ba33cSDag-Erling Smørgrav /* write the bignums (in big-endian) a little offset if the BN code 1885*986ba33cSDag-Erling Smørgrav * wants to write a shorter number of bytes, with zeroes prefixed */ 1886*986ba33cSDag-Erling Smørgrav memset(data, 0, num_bytes*2); 1887*986ba33cSDag-Erling Smørgrav BN_bn2bin(r, data+num_bytes-BN_num_bytes(r)); 1888*986ba33cSDag-Erling Smørgrav BN_bn2bin(s, data+num_bytes*2-BN_num_bytes(s)); 1889*986ba33cSDag-Erling Smørgrav rdf = ldns_rdf_new(LDNS_RDF_TYPE_B64, (size_t)(num_bytes*2), data); 18907b5038d7SDag-Erling Smørgrav ECDSA_SIG_free(ecdsa_sig); 18917b5038d7SDag-Erling Smørgrav return rdf; 18927b5038d7SDag-Erling Smørgrav } 18937b5038d7SDag-Erling Smørgrav 18947b5038d7SDag-Erling Smørgrav ldns_status 18957b5038d7SDag-Erling Smørgrav ldns_convert_ecdsa_rrsig_rdf2asn1(ldns_buffer *target_buffer, 18967b5038d7SDag-Erling Smørgrav const ldns_rdf *sig_rdf) 18977b5038d7SDag-Erling Smørgrav { 1898*986ba33cSDag-Erling Smørgrav /* convert from two BIGNUMs in the rdata buffer, to ASN notation. 1899*986ba33cSDag-Erling Smørgrav * ASN preable: 30440220 <R 32bytefor256> 0220 <S 32bytefor256> 1900*986ba33cSDag-Erling Smørgrav * the '20' is the length of that field (=bnsize). 1901*986ba33cSDag-Erling Smørgrav * the '44' is the total remaining length. 1902*986ba33cSDag-Erling Smørgrav * if negative, start with leading zero. 1903*986ba33cSDag-Erling Smørgrav * if starts with 00s, remove them from the number. 1904*986ba33cSDag-Erling Smørgrav */ 1905*986ba33cSDag-Erling Smørgrav uint8_t pre[] = {0x30, 0x44, 0x02, 0x20}; 1906*986ba33cSDag-Erling Smørgrav int pre_len = 4; 1907*986ba33cSDag-Erling Smørgrav uint8_t mid[] = {0x02, 0x20}; 1908*986ba33cSDag-Erling Smørgrav int mid_len = 2; 1909*986ba33cSDag-Erling Smørgrav int raw_sig_len, r_high, s_high, r_rem=0, s_rem=0; 19107b5038d7SDag-Erling Smørgrav long bnsize = (long)ldns_rdf_size(sig_rdf) / 2; 1911*986ba33cSDag-Erling Smørgrav uint8_t* d = ldns_rdf_data(sig_rdf); 19127b5038d7SDag-Erling Smørgrav /* if too short, or not even length, do not bother */ 19137b5038d7SDag-Erling Smørgrav if(bnsize < 16 || (size_t)bnsize*2 != ldns_rdf_size(sig_rdf)) 19147b5038d7SDag-Erling Smørgrav return LDNS_STATUS_ERR; 1915*986ba33cSDag-Erling Smørgrav /* strip leading zeroes from r (but not last one) */ 1916*986ba33cSDag-Erling Smørgrav while(r_rem < bnsize-1 && d[r_rem] == 0) 1917*986ba33cSDag-Erling Smørgrav r_rem++; 1918*986ba33cSDag-Erling Smørgrav /* strip leading zeroes from s (but not last one) */ 1919*986ba33cSDag-Erling Smørgrav while(s_rem < bnsize-1 && d[bnsize+s_rem] == 0) 1920*986ba33cSDag-Erling Smørgrav s_rem++; 19217b5038d7SDag-Erling Smørgrav 1922*986ba33cSDag-Erling Smørgrav r_high = ((d[0+r_rem]&0x80)?1:0); 1923*986ba33cSDag-Erling Smørgrav s_high = ((d[bnsize+s_rem]&0x80)?1:0); 1924*986ba33cSDag-Erling Smørgrav raw_sig_len = pre_len + r_high + bnsize - r_rem + mid_len + 1925*986ba33cSDag-Erling Smørgrav s_high + bnsize - s_rem; 19267b5038d7SDag-Erling Smørgrav if(ldns_buffer_reserve(target_buffer, (size_t) raw_sig_len)) { 1927*986ba33cSDag-Erling Smørgrav ldns_buffer_write_u8(target_buffer, pre[0]); 1928*986ba33cSDag-Erling Smørgrav ldns_buffer_write_u8(target_buffer, raw_sig_len-2); 1929*986ba33cSDag-Erling Smørgrav ldns_buffer_write_u8(target_buffer, pre[2]); 1930*986ba33cSDag-Erling Smørgrav ldns_buffer_write_u8(target_buffer, bnsize + r_high - r_rem); 1931*986ba33cSDag-Erling Smørgrav if(r_high) 1932*986ba33cSDag-Erling Smørgrav ldns_buffer_write_u8(target_buffer, 0); 1933*986ba33cSDag-Erling Smørgrav ldns_buffer_write(target_buffer, d+r_rem, bnsize-r_rem); 1934*986ba33cSDag-Erling Smørgrav ldns_buffer_write(target_buffer, mid, mid_len-1); 1935*986ba33cSDag-Erling Smørgrav ldns_buffer_write_u8(target_buffer, bnsize + s_high - s_rem); 1936*986ba33cSDag-Erling Smørgrav if(s_high) 1937*986ba33cSDag-Erling Smørgrav ldns_buffer_write_u8(target_buffer, 0); 1938*986ba33cSDag-Erling Smørgrav ldns_buffer_write(target_buffer, d+bnsize+s_rem, bnsize-s_rem); 19397b5038d7SDag-Erling Smørgrav } 19407b5038d7SDag-Erling Smørgrav return ldns_buffer_status(target_buffer); 19417b5038d7SDag-Erling Smørgrav } 19427b5038d7SDag-Erling Smørgrav 19437b5038d7SDag-Erling Smørgrav #endif /* S_SPLINT_S */ 19447b5038d7SDag-Erling Smørgrav #endif /* USE_ECDSA */ 1945*986ba33cSDag-Erling Smørgrav 1946*986ba33cSDag-Erling Smørgrav #if defined(USE_ED25519) || defined(USE_ED448) 1947*986ba33cSDag-Erling Smørgrav /* debug printout routine */ 1948*986ba33cSDag-Erling Smørgrav static void print_hex(const char* str, uint8_t* d, int len) 1949*986ba33cSDag-Erling Smørgrav { 1950*986ba33cSDag-Erling Smørgrav const char hex[] = "0123456789abcdef"; 1951*986ba33cSDag-Erling Smørgrav int i; 1952*986ba33cSDag-Erling Smørgrav printf("%s [len=%d]: ", str, len); 1953*986ba33cSDag-Erling Smørgrav for(i=0; i<len; i++) { 1954*986ba33cSDag-Erling Smørgrav int x = (d[i]&0xf0)>>4; 1955*986ba33cSDag-Erling Smørgrav int y = (d[i]&0x0f); 1956*986ba33cSDag-Erling Smørgrav printf("%c%c", hex[x], hex[y]); 1957*986ba33cSDag-Erling Smørgrav } 1958*986ba33cSDag-Erling Smørgrav printf("\n"); 1959*986ba33cSDag-Erling Smørgrav } 1960*986ba33cSDag-Erling Smørgrav #endif 1961*986ba33cSDag-Erling Smørgrav 1962*986ba33cSDag-Erling Smørgrav #ifdef USE_ED25519 1963*986ba33cSDag-Erling Smørgrav ldns_rdf * 1964*986ba33cSDag-Erling Smørgrav ldns_convert_ed25519_rrsig_asn12rdf(const ldns_buffer *sig, long sig_len) 1965*986ba33cSDag-Erling Smørgrav { 1966*986ba33cSDag-Erling Smørgrav unsigned char *data = (unsigned char*)ldns_buffer_begin(sig); 1967*986ba33cSDag-Erling Smørgrav ldns_rdf* rdf = NULL; 1968*986ba33cSDag-Erling Smørgrav 1969*986ba33cSDag-Erling Smørgrav /* TODO when Openssl supports signing and you can test this */ 1970*986ba33cSDag-Erling Smørgrav print_hex("sig in ASN", data, sig_len); 1971*986ba33cSDag-Erling Smørgrav 1972*986ba33cSDag-Erling Smørgrav return rdf; 1973*986ba33cSDag-Erling Smørgrav } 1974*986ba33cSDag-Erling Smørgrav 1975*986ba33cSDag-Erling Smørgrav ldns_status 1976*986ba33cSDag-Erling Smørgrav ldns_convert_ed25519_rrsig_rdf2asn1(ldns_buffer *target_buffer, 1977*986ba33cSDag-Erling Smørgrav const ldns_rdf *sig_rdf) 1978*986ba33cSDag-Erling Smørgrav { 1979*986ba33cSDag-Erling Smørgrav /* TODO when Openssl supports signing and you can test this. */ 1980*986ba33cSDag-Erling Smørgrav /* convert sig_buf into ASN1 into the target_buffer */ 1981*986ba33cSDag-Erling Smørgrav print_hex("sig raw", ldns_rdf_data(sig_rdf), ldns_rdf_size(sig_rdf)); 1982*986ba33cSDag-Erling Smørgrav return ldns_buffer_status(target_buffer); 1983*986ba33cSDag-Erling Smørgrav } 1984*986ba33cSDag-Erling Smørgrav #endif /* USE_ED25519 */ 1985*986ba33cSDag-Erling Smørgrav 1986*986ba33cSDag-Erling Smørgrav #ifdef USE_ED448 1987*986ba33cSDag-Erling Smørgrav ldns_rdf * 1988*986ba33cSDag-Erling Smørgrav ldns_convert_ed448_rrsig_asn12rdf(const ldns_buffer *sig, long sig_len) 1989*986ba33cSDag-Erling Smørgrav { 1990*986ba33cSDag-Erling Smørgrav unsigned char *data = (unsigned char*)ldns_buffer_begin(sig); 1991*986ba33cSDag-Erling Smørgrav ldns_rdf* rdf = NULL; 1992*986ba33cSDag-Erling Smørgrav 1993*986ba33cSDag-Erling Smørgrav /* TODO when Openssl supports signing and you can test this */ 1994*986ba33cSDag-Erling Smørgrav print_hex("sig in ASN", data, sig_len); 1995*986ba33cSDag-Erling Smørgrav 1996*986ba33cSDag-Erling Smørgrav return rdf; 1997*986ba33cSDag-Erling Smørgrav } 1998*986ba33cSDag-Erling Smørgrav 1999*986ba33cSDag-Erling Smørgrav ldns_status 2000*986ba33cSDag-Erling Smørgrav ldns_convert_ed448_rrsig_rdf2asn1(ldns_buffer *target_buffer, 2001*986ba33cSDag-Erling Smørgrav const ldns_rdf *sig_rdf) 2002*986ba33cSDag-Erling Smørgrav { 2003*986ba33cSDag-Erling Smørgrav /* TODO when Openssl supports signing and you can test this. */ 2004*986ba33cSDag-Erling Smørgrav /* convert sig_buf into ASN1 into the target_buffer */ 2005*986ba33cSDag-Erling Smørgrav print_hex("sig raw", ldns_rdf_data(sig_rdf), ldns_rdf_size(sig_rdf)); 2006*986ba33cSDag-Erling Smørgrav return ldns_buffer_status(target_buffer); 2007*986ba33cSDag-Erling Smørgrav } 2008*986ba33cSDag-Erling Smørgrav #endif /* USE_ED448 */ 2009*986ba33cSDag-Erling Smørgrav 20107b5038d7SDag-Erling Smørgrav #endif /* HAVE_SSL */ 2011