17b5038d7SDag-Erling Smørgrav /* 27b5038d7SDag-Erling Smørgrav * dnssec.c 37b5038d7SDag-Erling Smørgrav * 47b5038d7SDag-Erling Smørgrav * contains the cryptographic function needed for DNSSEC in ldns 57b5038d7SDag-Erling Smørgrav * The crypto library used is openssl 67b5038d7SDag-Erling Smørgrav * 77b5038d7SDag-Erling Smørgrav * (c) NLnet Labs, 2004-2008 87b5038d7SDag-Erling Smørgrav * 97b5038d7SDag-Erling Smørgrav * See the file LICENSE for the license 107b5038d7SDag-Erling Smørgrav */ 117b5038d7SDag-Erling Smørgrav 127b5038d7SDag-Erling Smørgrav #include <ldns/config.h> 137b5038d7SDag-Erling Smørgrav 147b5038d7SDag-Erling Smørgrav #include <ldns/ldns.h> 157b5038d7SDag-Erling Smørgrav #include <ldns/dnssec.h> 167b5038d7SDag-Erling Smørgrav 177b5038d7SDag-Erling Smørgrav #include <strings.h> 187b5038d7SDag-Erling Smørgrav #include <time.h> 197b5038d7SDag-Erling Smørgrav 207b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL 217b5038d7SDag-Erling Smørgrav #include <openssl/ssl.h> 227b5038d7SDag-Erling Smørgrav #include <openssl/evp.h> 237b5038d7SDag-Erling Smørgrav #include <openssl/rand.h> 247b5038d7SDag-Erling Smørgrav #include <openssl/err.h> 257b5038d7SDag-Erling Smørgrav #include <openssl/md5.h> 267b5038d7SDag-Erling Smørgrav #endif 277b5038d7SDag-Erling Smørgrav 287b5038d7SDag-Erling Smørgrav ldns_rr * 297b5038d7SDag-Erling Smørgrav ldns_dnssec_get_rrsig_for_name_and_type(const ldns_rdf *name, 307b5038d7SDag-Erling Smørgrav const ldns_rr_type type, 317b5038d7SDag-Erling Smørgrav const ldns_rr_list *rrs) 327b5038d7SDag-Erling Smørgrav { 337b5038d7SDag-Erling Smørgrav size_t i; 347b5038d7SDag-Erling Smørgrav ldns_rr *candidate; 357b5038d7SDag-Erling Smørgrav 367b5038d7SDag-Erling Smørgrav if (!name || !rrs) { 377b5038d7SDag-Erling Smørgrav return NULL; 387b5038d7SDag-Erling Smørgrav } 397b5038d7SDag-Erling Smørgrav 407b5038d7SDag-Erling Smørgrav for (i = 0; i < ldns_rr_list_rr_count(rrs); i++) { 417b5038d7SDag-Erling Smørgrav candidate = ldns_rr_list_rr(rrs, i); 427b5038d7SDag-Erling Smørgrav if (ldns_rr_get_type(candidate) == LDNS_RR_TYPE_RRSIG) { 437b5038d7SDag-Erling Smørgrav if (ldns_dname_compare(ldns_rr_owner(candidate), 447b5038d7SDag-Erling Smørgrav name) == 0 && 457b5038d7SDag-Erling Smørgrav ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(candidate)) 467b5038d7SDag-Erling Smørgrav == type 477b5038d7SDag-Erling Smørgrav ) { 487b5038d7SDag-Erling Smørgrav return candidate; 497b5038d7SDag-Erling Smørgrav } 507b5038d7SDag-Erling Smørgrav } 517b5038d7SDag-Erling Smørgrav } 527b5038d7SDag-Erling Smørgrav 537b5038d7SDag-Erling Smørgrav return NULL; 547b5038d7SDag-Erling Smørgrav } 557b5038d7SDag-Erling Smørgrav 567b5038d7SDag-Erling Smørgrav ldns_rr * 577b5038d7SDag-Erling Smørgrav ldns_dnssec_get_dnskey_for_rrsig(const ldns_rr *rrsig, 587b5038d7SDag-Erling Smørgrav const ldns_rr_list *rrs) 597b5038d7SDag-Erling Smørgrav { 607b5038d7SDag-Erling Smørgrav size_t i; 617b5038d7SDag-Erling Smørgrav ldns_rr *candidate; 627b5038d7SDag-Erling Smørgrav 637b5038d7SDag-Erling Smørgrav if (!rrsig || !rrs) { 647b5038d7SDag-Erling Smørgrav return NULL; 657b5038d7SDag-Erling Smørgrav } 667b5038d7SDag-Erling Smørgrav 677b5038d7SDag-Erling Smørgrav for (i = 0; i < ldns_rr_list_rr_count(rrs); i++) { 687b5038d7SDag-Erling Smørgrav candidate = ldns_rr_list_rr(rrs, i); 697b5038d7SDag-Erling Smørgrav if (ldns_rr_get_type(candidate) == LDNS_RR_TYPE_DNSKEY) { 707b5038d7SDag-Erling Smørgrav if (ldns_dname_compare(ldns_rr_owner(candidate), 717b5038d7SDag-Erling Smørgrav ldns_rr_rrsig_signame(rrsig)) == 0 && 727b5038d7SDag-Erling Smørgrav ldns_rdf2native_int16(ldns_rr_rrsig_keytag(rrsig)) == 737b5038d7SDag-Erling Smørgrav ldns_calc_keytag(candidate) 747b5038d7SDag-Erling Smørgrav ) { 757b5038d7SDag-Erling Smørgrav return candidate; 767b5038d7SDag-Erling Smørgrav } 777b5038d7SDag-Erling Smørgrav } 787b5038d7SDag-Erling Smørgrav } 797b5038d7SDag-Erling Smørgrav 807b5038d7SDag-Erling Smørgrav return NULL; 817b5038d7SDag-Erling Smørgrav } 827b5038d7SDag-Erling Smørgrav 837b5038d7SDag-Erling Smørgrav ldns_rdf * 847b5038d7SDag-Erling Smørgrav ldns_nsec_get_bitmap(ldns_rr *nsec) { 857b5038d7SDag-Erling Smørgrav if (ldns_rr_get_type(nsec) == LDNS_RR_TYPE_NSEC) { 867b5038d7SDag-Erling Smørgrav return ldns_rr_rdf(nsec, 1); 877b5038d7SDag-Erling Smørgrav } else if (ldns_rr_get_type(nsec) == LDNS_RR_TYPE_NSEC3) { 887b5038d7SDag-Erling Smørgrav return ldns_rr_rdf(nsec, 5); 897b5038d7SDag-Erling Smørgrav } else { 907b5038d7SDag-Erling Smørgrav return NULL; 917b5038d7SDag-Erling Smørgrav } 927b5038d7SDag-Erling Smørgrav } 937b5038d7SDag-Erling Smørgrav 947b5038d7SDag-Erling Smørgrav /*return the owner name of the closest encloser for name from the list of rrs */ 957b5038d7SDag-Erling Smørgrav /* this is NOT the hash, but the original name! */ 967b5038d7SDag-Erling Smørgrav ldns_rdf * 977b5038d7SDag-Erling Smørgrav ldns_dnssec_nsec3_closest_encloser(ldns_rdf *qname, 987b5038d7SDag-Erling Smørgrav ATTR_UNUSED(ldns_rr_type qtype), 997b5038d7SDag-Erling Smørgrav ldns_rr_list *nsec3s) 1007b5038d7SDag-Erling Smørgrav { 1017b5038d7SDag-Erling Smørgrav /* remember parameters, they must match */ 1027b5038d7SDag-Erling Smørgrav uint8_t algorithm; 1037b5038d7SDag-Erling Smørgrav uint32_t iterations; 1047b5038d7SDag-Erling Smørgrav uint8_t salt_length; 1057b5038d7SDag-Erling Smørgrav uint8_t *salt; 1067b5038d7SDag-Erling Smørgrav 1077b5038d7SDag-Erling Smørgrav ldns_rdf *sname, *hashed_sname, *tmp; 1087b5038d7SDag-Erling Smørgrav bool flag; 1097b5038d7SDag-Erling Smørgrav 1107b5038d7SDag-Erling Smørgrav bool exact_match_found; 1117b5038d7SDag-Erling Smørgrav bool in_range_found; 1127b5038d7SDag-Erling Smørgrav 1137b5038d7SDag-Erling Smørgrav ldns_status status; 1147b5038d7SDag-Erling Smørgrav ldns_rdf *zone_name; 1157b5038d7SDag-Erling Smørgrav 1167b5038d7SDag-Erling Smørgrav size_t nsec_i; 1177b5038d7SDag-Erling Smørgrav ldns_rr *nsec; 1187b5038d7SDag-Erling Smørgrav ldns_rdf *result = NULL; 1197b5038d7SDag-Erling Smørgrav 1207b5038d7SDag-Erling Smørgrav if (!qname || !nsec3s || ldns_rr_list_rr_count(nsec3s) < 1) { 1217b5038d7SDag-Erling Smørgrav return NULL; 1227b5038d7SDag-Erling Smørgrav } 1237b5038d7SDag-Erling Smørgrav 1247b5038d7SDag-Erling Smørgrav nsec = ldns_rr_list_rr(nsec3s, 0); 1257b5038d7SDag-Erling Smørgrav algorithm = ldns_nsec3_algorithm(nsec); 1267b5038d7SDag-Erling Smørgrav salt_length = ldns_nsec3_salt_length(nsec); 1277b5038d7SDag-Erling Smørgrav salt = ldns_nsec3_salt_data(nsec); 1287b5038d7SDag-Erling Smørgrav iterations = ldns_nsec3_iterations(nsec); 1297b5038d7SDag-Erling Smørgrav 1307b5038d7SDag-Erling Smørgrav sname = ldns_rdf_clone(qname); 1317b5038d7SDag-Erling Smørgrav 1327b5038d7SDag-Erling Smørgrav flag = false; 1337b5038d7SDag-Erling Smørgrav 1347b5038d7SDag-Erling Smørgrav zone_name = ldns_dname_left_chop(ldns_rr_owner(nsec)); 1357b5038d7SDag-Erling Smørgrav 1367b5038d7SDag-Erling Smørgrav /* algorithm from nsec3-07 8.3 */ 1377b5038d7SDag-Erling Smørgrav while (ldns_dname_label_count(sname) > 0) { 1387b5038d7SDag-Erling Smørgrav exact_match_found = false; 1397b5038d7SDag-Erling Smørgrav in_range_found = false; 1407b5038d7SDag-Erling Smørgrav 1417b5038d7SDag-Erling Smørgrav hashed_sname = ldns_nsec3_hash_name(sname, 1427b5038d7SDag-Erling Smørgrav algorithm, 1437b5038d7SDag-Erling Smørgrav iterations, 1447b5038d7SDag-Erling Smørgrav salt_length, 1457b5038d7SDag-Erling Smørgrav salt); 1467b5038d7SDag-Erling Smørgrav 1477b5038d7SDag-Erling Smørgrav status = ldns_dname_cat(hashed_sname, zone_name); 1487b5038d7SDag-Erling Smørgrav if(status != LDNS_STATUS_OK) { 1497b5038d7SDag-Erling Smørgrav LDNS_FREE(salt); 1507b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(zone_name); 1517b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(sname); 1527b5038d7SDag-Erling Smørgrav return NULL; 1537b5038d7SDag-Erling Smørgrav } 1547b5038d7SDag-Erling Smørgrav 1557b5038d7SDag-Erling Smørgrav for (nsec_i = 0; nsec_i < ldns_rr_list_rr_count(nsec3s); nsec_i++) { 1567b5038d7SDag-Erling Smørgrav nsec = ldns_rr_list_rr(nsec3s, nsec_i); 1577b5038d7SDag-Erling Smørgrav 1587b5038d7SDag-Erling Smørgrav /* check values of iterations etc! */ 1597b5038d7SDag-Erling Smørgrav 1607b5038d7SDag-Erling Smørgrav /* exact match? */ 1617b5038d7SDag-Erling Smørgrav if (ldns_dname_compare(ldns_rr_owner(nsec), hashed_sname) == 0) { 1627b5038d7SDag-Erling Smørgrav exact_match_found = true; 1637b5038d7SDag-Erling Smørgrav } else if (ldns_nsec_covers_name(nsec, hashed_sname)) { 1647b5038d7SDag-Erling Smørgrav in_range_found = true; 1657b5038d7SDag-Erling Smørgrav } 1667b5038d7SDag-Erling Smørgrav 1677b5038d7SDag-Erling Smørgrav } 1687b5038d7SDag-Erling Smørgrav if (!exact_match_found && in_range_found) { 1697b5038d7SDag-Erling Smørgrav flag = true; 1707b5038d7SDag-Erling Smørgrav } else if (exact_match_found && flag) { 1717b5038d7SDag-Erling Smørgrav result = ldns_rdf_clone(sname); 1727b5038d7SDag-Erling Smørgrav /* RFC 5155: 8.3. 2.** "The proof is complete" */ 1737b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(hashed_sname); 1747b5038d7SDag-Erling Smørgrav goto done; 1757b5038d7SDag-Erling Smørgrav } else if (exact_match_found && !flag) { 1767b5038d7SDag-Erling Smørgrav /* error! */ 1777b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(hashed_sname); 1787b5038d7SDag-Erling Smørgrav goto done; 1797b5038d7SDag-Erling Smørgrav } else { 1807b5038d7SDag-Erling Smørgrav flag = false; 1817b5038d7SDag-Erling Smørgrav } 1827b5038d7SDag-Erling Smørgrav 1837b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(hashed_sname); 1847b5038d7SDag-Erling Smørgrav tmp = sname; 1857b5038d7SDag-Erling Smørgrav sname = ldns_dname_left_chop(sname); 1867b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(tmp); 1877b5038d7SDag-Erling Smørgrav } 1887b5038d7SDag-Erling Smørgrav 1897b5038d7SDag-Erling Smørgrav done: 1907b5038d7SDag-Erling Smørgrav LDNS_FREE(salt); 1917b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(zone_name); 1927b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(sname); 1937b5038d7SDag-Erling Smørgrav 1947b5038d7SDag-Erling Smørgrav return result; 1957b5038d7SDag-Erling Smørgrav } 1967b5038d7SDag-Erling Smørgrav 1977b5038d7SDag-Erling Smørgrav bool 1987b5038d7SDag-Erling Smørgrav ldns_dnssec_pkt_has_rrsigs(const ldns_pkt *pkt) 1997b5038d7SDag-Erling Smørgrav { 2007b5038d7SDag-Erling Smørgrav size_t i; 2017b5038d7SDag-Erling Smørgrav for (i = 0; i < ldns_pkt_ancount(pkt); i++) { 2027b5038d7SDag-Erling Smørgrav if (ldns_rr_get_type(ldns_rr_list_rr(ldns_pkt_answer(pkt), i)) == 2037b5038d7SDag-Erling Smørgrav LDNS_RR_TYPE_RRSIG) { 2047b5038d7SDag-Erling Smørgrav return true; 2057b5038d7SDag-Erling Smørgrav } 2067b5038d7SDag-Erling Smørgrav } 2077b5038d7SDag-Erling Smørgrav for (i = 0; i < ldns_pkt_nscount(pkt); i++) { 2087b5038d7SDag-Erling Smørgrav if (ldns_rr_get_type(ldns_rr_list_rr(ldns_pkt_authority(pkt), i)) == 2097b5038d7SDag-Erling Smørgrav LDNS_RR_TYPE_RRSIG) { 2107b5038d7SDag-Erling Smørgrav return true; 2117b5038d7SDag-Erling Smørgrav } 2127b5038d7SDag-Erling Smørgrav } 2137b5038d7SDag-Erling Smørgrav return false; 2147b5038d7SDag-Erling Smørgrav } 2157b5038d7SDag-Erling Smørgrav 2167b5038d7SDag-Erling Smørgrav ldns_rr_list * 2177b5038d7SDag-Erling Smørgrav ldns_dnssec_pkt_get_rrsigs_for_name_and_type(const ldns_pkt *pkt, 2187b5038d7SDag-Erling Smørgrav ldns_rdf *name, 2197b5038d7SDag-Erling Smørgrav ldns_rr_type type) 2207b5038d7SDag-Erling Smørgrav { 2217b5038d7SDag-Erling Smørgrav uint16_t t_netorder; 2227b5038d7SDag-Erling Smørgrav ldns_rr_list *sigs; 2237b5038d7SDag-Erling Smørgrav ldns_rr_list *sigs_covered; 2247b5038d7SDag-Erling Smørgrav ldns_rdf *rdf_t; 2257b5038d7SDag-Erling Smørgrav 2267b5038d7SDag-Erling Smørgrav sigs = ldns_pkt_rr_list_by_name_and_type(pkt, 2277b5038d7SDag-Erling Smørgrav name, 2287b5038d7SDag-Erling Smørgrav LDNS_RR_TYPE_RRSIG, 2297b5038d7SDag-Erling Smørgrav LDNS_SECTION_ANY_NOQUESTION 2307b5038d7SDag-Erling Smørgrav ); 2317b5038d7SDag-Erling Smørgrav 2327b5038d7SDag-Erling Smørgrav t_netorder = htons(type); /* rdf are in network order! */ 2337b5038d7SDag-Erling Smørgrav rdf_t = ldns_rdf_new(LDNS_RDF_TYPE_TYPE, LDNS_RDF_SIZE_WORD, &t_netorder); 2347b5038d7SDag-Erling Smørgrav sigs_covered = ldns_rr_list_subtype_by_rdf(sigs, rdf_t, 0); 2357b5038d7SDag-Erling Smørgrav 2367b5038d7SDag-Erling Smørgrav ldns_rdf_free(rdf_t); 2377b5038d7SDag-Erling Smørgrav ldns_rr_list_deep_free(sigs); 2387b5038d7SDag-Erling Smørgrav 2397b5038d7SDag-Erling Smørgrav return sigs_covered; 2407b5038d7SDag-Erling Smørgrav 2417b5038d7SDag-Erling Smørgrav } 2427b5038d7SDag-Erling Smørgrav 2437b5038d7SDag-Erling Smørgrav ldns_rr_list * 2447b5038d7SDag-Erling Smørgrav ldns_dnssec_pkt_get_rrsigs_for_type(const ldns_pkt *pkt, ldns_rr_type type) 2457b5038d7SDag-Erling Smørgrav { 2467b5038d7SDag-Erling Smørgrav uint16_t t_netorder; 2477b5038d7SDag-Erling Smørgrav ldns_rr_list *sigs; 2487b5038d7SDag-Erling Smørgrav ldns_rr_list *sigs_covered; 2497b5038d7SDag-Erling Smørgrav ldns_rdf *rdf_t; 2507b5038d7SDag-Erling Smørgrav 2517b5038d7SDag-Erling Smørgrav sigs = ldns_pkt_rr_list_by_type(pkt, 2527b5038d7SDag-Erling Smørgrav LDNS_RR_TYPE_RRSIG, 2537b5038d7SDag-Erling Smørgrav LDNS_SECTION_ANY_NOQUESTION 2547b5038d7SDag-Erling Smørgrav ); 2557b5038d7SDag-Erling Smørgrav 2567b5038d7SDag-Erling Smørgrav t_netorder = htons(type); /* rdf are in network order! */ 2577b5038d7SDag-Erling Smørgrav rdf_t = ldns_rdf_new(LDNS_RDF_TYPE_TYPE, 2587b5038d7SDag-Erling Smørgrav 2, 2597b5038d7SDag-Erling Smørgrav &t_netorder); 2607b5038d7SDag-Erling Smørgrav sigs_covered = ldns_rr_list_subtype_by_rdf(sigs, rdf_t, 0); 2617b5038d7SDag-Erling Smørgrav 2627b5038d7SDag-Erling Smørgrav ldns_rdf_free(rdf_t); 2637b5038d7SDag-Erling Smørgrav ldns_rr_list_deep_free(sigs); 2647b5038d7SDag-Erling Smørgrav 2657b5038d7SDag-Erling Smørgrav return sigs_covered; 2667b5038d7SDag-Erling Smørgrav 2677b5038d7SDag-Erling Smørgrav } 2687b5038d7SDag-Erling Smørgrav 2697b5038d7SDag-Erling Smørgrav /* used only on the public key RR */ 2707b5038d7SDag-Erling Smørgrav uint16_t 2717b5038d7SDag-Erling Smørgrav ldns_calc_keytag(const ldns_rr *key) 2727b5038d7SDag-Erling Smørgrav { 2737b5038d7SDag-Erling Smørgrav uint16_t ac16; 2747b5038d7SDag-Erling Smørgrav ldns_buffer *keybuf; 2757b5038d7SDag-Erling Smørgrav size_t keysize; 2767b5038d7SDag-Erling Smørgrav 2777b5038d7SDag-Erling Smørgrav if (!key) { 2787b5038d7SDag-Erling Smørgrav return 0; 2797b5038d7SDag-Erling Smørgrav } 2807b5038d7SDag-Erling Smørgrav 2817b5038d7SDag-Erling Smørgrav if (ldns_rr_get_type(key) != LDNS_RR_TYPE_DNSKEY && 2827b5038d7SDag-Erling Smørgrav ldns_rr_get_type(key) != LDNS_RR_TYPE_KEY 2837b5038d7SDag-Erling Smørgrav ) { 2847b5038d7SDag-Erling Smørgrav return 0; 2857b5038d7SDag-Erling Smørgrav } 2867b5038d7SDag-Erling Smørgrav 2877b5038d7SDag-Erling Smørgrav /* rdata to buf - only put the rdata in a buffer */ 2887b5038d7SDag-Erling Smørgrav keybuf = ldns_buffer_new(LDNS_MIN_BUFLEN); /* grows */ 2897b5038d7SDag-Erling Smørgrav if (!keybuf) { 2907b5038d7SDag-Erling Smørgrav return 0; 2917b5038d7SDag-Erling Smørgrav } 2927b5038d7SDag-Erling Smørgrav (void)ldns_rr_rdata2buffer_wire(keybuf, key); 2937b5038d7SDag-Erling Smørgrav /* the current pos in the buffer is the keysize */ 2947b5038d7SDag-Erling Smørgrav keysize= ldns_buffer_position(keybuf); 2957b5038d7SDag-Erling Smørgrav 2967b5038d7SDag-Erling Smørgrav ac16 = ldns_calc_keytag_raw(ldns_buffer_begin(keybuf), keysize); 2977b5038d7SDag-Erling Smørgrav ldns_buffer_free(keybuf); 2987b5038d7SDag-Erling Smørgrav return ac16; 2997b5038d7SDag-Erling Smørgrav } 3007b5038d7SDag-Erling Smørgrav 3017b5038d7SDag-Erling Smørgrav uint16_t ldns_calc_keytag_raw(uint8_t* key, size_t keysize) 3027b5038d7SDag-Erling Smørgrav { 3037b5038d7SDag-Erling Smørgrav unsigned int i; 3047b5038d7SDag-Erling Smørgrav uint32_t ac32; 3057b5038d7SDag-Erling Smørgrav uint16_t ac16; 3067b5038d7SDag-Erling Smørgrav 3077b5038d7SDag-Erling Smørgrav if(keysize < 4) { 3087b5038d7SDag-Erling Smørgrav return 0; 3097b5038d7SDag-Erling Smørgrav } 3107b5038d7SDag-Erling Smørgrav /* look at the algorithm field, copied from 2535bis */ 3117b5038d7SDag-Erling Smørgrav if (key[3] == LDNS_RSAMD5) { 3127b5038d7SDag-Erling Smørgrav ac16 = 0; 3137b5038d7SDag-Erling Smørgrav if (keysize > 4) { 3147b5038d7SDag-Erling Smørgrav memmove(&ac16, key + keysize - 3, 2); 3157b5038d7SDag-Erling Smørgrav } 3167b5038d7SDag-Erling Smørgrav ac16 = ntohs(ac16); 3177b5038d7SDag-Erling Smørgrav return (uint16_t) ac16; 3187b5038d7SDag-Erling Smørgrav } else { 3197b5038d7SDag-Erling Smørgrav ac32 = 0; 3207b5038d7SDag-Erling Smørgrav for (i = 0; (size_t)i < keysize; ++i) { 3217b5038d7SDag-Erling Smørgrav ac32 += (i & 1) ? key[i] : key[i] << 8; 3227b5038d7SDag-Erling Smørgrav } 3237b5038d7SDag-Erling Smørgrav ac32 += (ac32 >> 16) & 0xFFFF; 3247b5038d7SDag-Erling Smørgrav return (uint16_t) (ac32 & 0xFFFF); 3257b5038d7SDag-Erling Smørgrav } 3267b5038d7SDag-Erling Smørgrav } 3277b5038d7SDag-Erling Smørgrav 3287b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL 3297b5038d7SDag-Erling Smørgrav DSA * 3307b5038d7SDag-Erling Smørgrav ldns_key_buf2dsa(ldns_buffer *key) 3317b5038d7SDag-Erling Smørgrav { 3327b5038d7SDag-Erling Smørgrav return ldns_key_buf2dsa_raw((unsigned char*)ldns_buffer_begin(key), 3337b5038d7SDag-Erling Smørgrav ldns_buffer_position(key)); 3347b5038d7SDag-Erling Smørgrav } 3357b5038d7SDag-Erling Smørgrav 3367b5038d7SDag-Erling Smørgrav DSA * 3377b5038d7SDag-Erling Smørgrav ldns_key_buf2dsa_raw(unsigned char* key, size_t len) 3387b5038d7SDag-Erling Smørgrav { 3397b5038d7SDag-Erling Smørgrav uint8_t T; 3407b5038d7SDag-Erling Smørgrav uint16_t length; 3417b5038d7SDag-Erling Smørgrav uint16_t offset; 3427b5038d7SDag-Erling Smørgrav DSA *dsa; 3437b5038d7SDag-Erling Smørgrav BIGNUM *Q; BIGNUM *P; 3447b5038d7SDag-Erling Smørgrav BIGNUM *G; BIGNUM *Y; 3457b5038d7SDag-Erling Smørgrav 3467b5038d7SDag-Erling Smørgrav if(len == 0) 3477b5038d7SDag-Erling Smørgrav return NULL; 3487b5038d7SDag-Erling Smørgrav T = (uint8_t)key[0]; 3497b5038d7SDag-Erling Smørgrav length = (64 + T * 8); 3507b5038d7SDag-Erling Smørgrav offset = 1; 3517b5038d7SDag-Erling Smørgrav 3527b5038d7SDag-Erling Smørgrav if (T > 8) { 3537b5038d7SDag-Erling Smørgrav return NULL; 3547b5038d7SDag-Erling Smørgrav } 3557b5038d7SDag-Erling Smørgrav if(len < (size_t)1 + SHA_DIGEST_LENGTH + 3*length) 3567b5038d7SDag-Erling Smørgrav return NULL; 3577b5038d7SDag-Erling Smørgrav 3587b5038d7SDag-Erling Smørgrav Q = BN_bin2bn(key+offset, SHA_DIGEST_LENGTH, NULL); 3597b5038d7SDag-Erling Smørgrav offset += SHA_DIGEST_LENGTH; 3607b5038d7SDag-Erling Smørgrav 3617b5038d7SDag-Erling Smørgrav P = BN_bin2bn(key+offset, (int)length, NULL); 3627b5038d7SDag-Erling Smørgrav offset += length; 3637b5038d7SDag-Erling Smørgrav 3647b5038d7SDag-Erling Smørgrav G = BN_bin2bn(key+offset, (int)length, NULL); 3657b5038d7SDag-Erling Smørgrav offset += length; 3667b5038d7SDag-Erling Smørgrav 3677b5038d7SDag-Erling Smørgrav Y = BN_bin2bn(key+offset, (int)length, NULL); 3687b5038d7SDag-Erling Smørgrav offset += length; 3697b5038d7SDag-Erling Smørgrav 3707b5038d7SDag-Erling Smørgrav /* create the key and set its properties */ 3717b5038d7SDag-Erling Smørgrav if(!Q || !P || !G || !Y || !(dsa = DSA_new())) { 3727b5038d7SDag-Erling Smørgrav BN_free(Q); 3737b5038d7SDag-Erling Smørgrav BN_free(P); 3747b5038d7SDag-Erling Smørgrav BN_free(G); 3757b5038d7SDag-Erling Smørgrav BN_free(Y); 3767b5038d7SDag-Erling Smørgrav return NULL; 3777b5038d7SDag-Erling Smørgrav } 3787b5038d7SDag-Erling Smørgrav #ifndef S_SPLINT_S 3797b5038d7SDag-Erling Smørgrav dsa->p = P; 3807b5038d7SDag-Erling Smørgrav dsa->q = Q; 3817b5038d7SDag-Erling Smørgrav dsa->g = G; 3827b5038d7SDag-Erling Smørgrav dsa->pub_key = Y; 3837b5038d7SDag-Erling Smørgrav #endif /* splint */ 3847b5038d7SDag-Erling Smørgrav 3857b5038d7SDag-Erling Smørgrav return dsa; 3867b5038d7SDag-Erling Smørgrav } 3877b5038d7SDag-Erling Smørgrav 3887b5038d7SDag-Erling Smørgrav RSA * 3897b5038d7SDag-Erling Smørgrav ldns_key_buf2rsa(ldns_buffer *key) 3907b5038d7SDag-Erling Smørgrav { 3917b5038d7SDag-Erling Smørgrav return ldns_key_buf2rsa_raw((unsigned char*)ldns_buffer_begin(key), 3927b5038d7SDag-Erling Smørgrav ldns_buffer_position(key)); 3937b5038d7SDag-Erling Smørgrav } 3947b5038d7SDag-Erling Smørgrav 3957b5038d7SDag-Erling Smørgrav RSA * 3967b5038d7SDag-Erling Smørgrav ldns_key_buf2rsa_raw(unsigned char* key, size_t len) 3977b5038d7SDag-Erling Smørgrav { 3987b5038d7SDag-Erling Smørgrav uint16_t offset; 3997b5038d7SDag-Erling Smørgrav uint16_t exp; 4007b5038d7SDag-Erling Smørgrav uint16_t int16; 4017b5038d7SDag-Erling Smørgrav RSA *rsa; 4027b5038d7SDag-Erling Smørgrav BIGNUM *modulus; 4037b5038d7SDag-Erling Smørgrav BIGNUM *exponent; 4047b5038d7SDag-Erling Smørgrav 4057b5038d7SDag-Erling Smørgrav if (len == 0) 4067b5038d7SDag-Erling Smørgrav return NULL; 4077b5038d7SDag-Erling Smørgrav if (key[0] == 0) { 4087b5038d7SDag-Erling Smørgrav if(len < 3) 4097b5038d7SDag-Erling Smørgrav return NULL; 4107b5038d7SDag-Erling Smørgrav /* need some smart comment here XXX*/ 4117b5038d7SDag-Erling Smørgrav /* the exponent is too large so it's places 4127b5038d7SDag-Erling Smørgrav * futher...???? */ 4137b5038d7SDag-Erling Smørgrav memmove(&int16, key+1, 2); 4147b5038d7SDag-Erling Smørgrav exp = ntohs(int16); 4157b5038d7SDag-Erling Smørgrav offset = 3; 4167b5038d7SDag-Erling Smørgrav } else { 4177b5038d7SDag-Erling Smørgrav exp = key[0]; 4187b5038d7SDag-Erling Smørgrav offset = 1; 4197b5038d7SDag-Erling Smørgrav } 4207b5038d7SDag-Erling Smørgrav 4217b5038d7SDag-Erling Smørgrav /* key length at least one */ 4227b5038d7SDag-Erling Smørgrav if(len < (size_t)offset + exp + 1) 4237b5038d7SDag-Erling Smørgrav return NULL; 4247b5038d7SDag-Erling Smørgrav 4257b5038d7SDag-Erling Smørgrav /* Exponent */ 4267b5038d7SDag-Erling Smørgrav exponent = BN_new(); 4277b5038d7SDag-Erling Smørgrav if(!exponent) return NULL; 4287b5038d7SDag-Erling Smørgrav (void) BN_bin2bn(key+offset, (int)exp, exponent); 4297b5038d7SDag-Erling Smørgrav offset += exp; 4307b5038d7SDag-Erling Smørgrav 4317b5038d7SDag-Erling Smørgrav /* Modulus */ 4327b5038d7SDag-Erling Smørgrav modulus = BN_new(); 4337b5038d7SDag-Erling Smørgrav if(!modulus) { 4347b5038d7SDag-Erling Smørgrav BN_free(exponent); 4357b5038d7SDag-Erling Smørgrav return NULL; 4367b5038d7SDag-Erling Smørgrav } 4377b5038d7SDag-Erling Smørgrav /* length of the buffer must match the key length! */ 4387b5038d7SDag-Erling Smørgrav (void) BN_bin2bn(key+offset, (int)(len - offset), modulus); 4397b5038d7SDag-Erling Smørgrav 4407b5038d7SDag-Erling Smørgrav rsa = RSA_new(); 4417b5038d7SDag-Erling Smørgrav if(!rsa) { 4427b5038d7SDag-Erling Smørgrav BN_free(exponent); 4437b5038d7SDag-Erling Smørgrav BN_free(modulus); 4447b5038d7SDag-Erling Smørgrav return NULL; 4457b5038d7SDag-Erling Smørgrav } 4467b5038d7SDag-Erling Smørgrav #ifndef S_SPLINT_S 4477b5038d7SDag-Erling Smørgrav rsa->n = modulus; 4487b5038d7SDag-Erling Smørgrav rsa->e = exponent; 4497b5038d7SDag-Erling Smørgrav #endif /* splint */ 4507b5038d7SDag-Erling Smørgrav 4517b5038d7SDag-Erling Smørgrav return rsa; 4527b5038d7SDag-Erling Smørgrav } 4537b5038d7SDag-Erling Smørgrav 4547b5038d7SDag-Erling Smørgrav int 4557b5038d7SDag-Erling Smørgrav ldns_digest_evp(unsigned char* data, unsigned int len, unsigned char* dest, 4567b5038d7SDag-Erling Smørgrav const EVP_MD* md) 4577b5038d7SDag-Erling Smørgrav { 4587b5038d7SDag-Erling Smørgrav EVP_MD_CTX* ctx; 4597b5038d7SDag-Erling Smørgrav ctx = EVP_MD_CTX_create(); 4607b5038d7SDag-Erling Smørgrav if(!ctx) 4617b5038d7SDag-Erling Smørgrav return false; 4627b5038d7SDag-Erling Smørgrav if(!EVP_DigestInit_ex(ctx, md, NULL) || 4637b5038d7SDag-Erling Smørgrav !EVP_DigestUpdate(ctx, data, len) || 4647b5038d7SDag-Erling Smørgrav !EVP_DigestFinal_ex(ctx, dest, NULL)) { 4657b5038d7SDag-Erling Smørgrav EVP_MD_CTX_destroy(ctx); 4667b5038d7SDag-Erling Smørgrav return false; 4677b5038d7SDag-Erling Smørgrav } 4687b5038d7SDag-Erling Smørgrav EVP_MD_CTX_destroy(ctx); 4697b5038d7SDag-Erling Smørgrav return true; 4707b5038d7SDag-Erling Smørgrav } 4717b5038d7SDag-Erling Smørgrav #endif /* HAVE_SSL */ 4727b5038d7SDag-Erling Smørgrav 4737b5038d7SDag-Erling Smørgrav ldns_rr * 4747b5038d7SDag-Erling Smørgrav ldns_key_rr2ds(const ldns_rr *key, ldns_hash h) 4757b5038d7SDag-Erling Smørgrav { 4767b5038d7SDag-Erling Smørgrav ldns_rdf *tmp; 4777b5038d7SDag-Erling Smørgrav ldns_rr *ds; 4787b5038d7SDag-Erling Smørgrav uint16_t keytag; 4797b5038d7SDag-Erling Smørgrav uint8_t sha1hash; 4807b5038d7SDag-Erling Smørgrav uint8_t *digest; 4817b5038d7SDag-Erling Smørgrav ldns_buffer *data_buf; 4827b5038d7SDag-Erling Smørgrav #ifdef USE_GOST 4837b5038d7SDag-Erling Smørgrav const EVP_MD* md = NULL; 4847b5038d7SDag-Erling Smørgrav #endif 4857b5038d7SDag-Erling Smørgrav 4867b5038d7SDag-Erling Smørgrav if (ldns_rr_get_type(key) != LDNS_RR_TYPE_DNSKEY) { 4877b5038d7SDag-Erling Smørgrav return NULL; 4887b5038d7SDag-Erling Smørgrav } 4897b5038d7SDag-Erling Smørgrav 4907b5038d7SDag-Erling Smørgrav ds = ldns_rr_new(); 4917b5038d7SDag-Erling Smørgrav if (!ds) { 4927b5038d7SDag-Erling Smørgrav return NULL; 4937b5038d7SDag-Erling Smørgrav } 4947b5038d7SDag-Erling Smørgrav ldns_rr_set_type(ds, LDNS_RR_TYPE_DS); 4957b5038d7SDag-Erling Smørgrav ldns_rr_set_owner(ds, ldns_rdf_clone( 4967b5038d7SDag-Erling Smørgrav ldns_rr_owner(key))); 4977b5038d7SDag-Erling Smørgrav ldns_rr_set_ttl(ds, ldns_rr_ttl(key)); 4987b5038d7SDag-Erling Smørgrav ldns_rr_set_class(ds, ldns_rr_get_class(key)); 4997b5038d7SDag-Erling Smørgrav 5007b5038d7SDag-Erling Smørgrav switch(h) { 5017b5038d7SDag-Erling Smørgrav default: 5027b5038d7SDag-Erling Smørgrav case LDNS_SHA1: 5037b5038d7SDag-Erling Smørgrav digest = LDNS_XMALLOC(uint8_t, LDNS_SHA1_DIGEST_LENGTH); 5047b5038d7SDag-Erling Smørgrav if (!digest) { 5057b5038d7SDag-Erling Smørgrav ldns_rr_free(ds); 5067b5038d7SDag-Erling Smørgrav return NULL; 5077b5038d7SDag-Erling Smørgrav } 5087b5038d7SDag-Erling Smørgrav break; 5097b5038d7SDag-Erling Smørgrav case LDNS_SHA256: 5107b5038d7SDag-Erling Smørgrav digest = LDNS_XMALLOC(uint8_t, LDNS_SHA256_DIGEST_LENGTH); 5117b5038d7SDag-Erling Smørgrav if (!digest) { 5127b5038d7SDag-Erling Smørgrav ldns_rr_free(ds); 5137b5038d7SDag-Erling Smørgrav return NULL; 5147b5038d7SDag-Erling Smørgrav } 5157b5038d7SDag-Erling Smørgrav break; 5167b5038d7SDag-Erling Smørgrav case LDNS_HASH_GOST: 5177b5038d7SDag-Erling Smørgrav #ifdef USE_GOST 5187b5038d7SDag-Erling Smørgrav (void)ldns_key_EVP_load_gost_id(); 5197b5038d7SDag-Erling Smørgrav md = EVP_get_digestbyname("md_gost94"); 5207b5038d7SDag-Erling Smørgrav if(!md) { 5217b5038d7SDag-Erling Smørgrav ldns_rr_free(ds); 5227b5038d7SDag-Erling Smørgrav return NULL; 5237b5038d7SDag-Erling Smørgrav } 5247b5038d7SDag-Erling Smørgrav digest = LDNS_XMALLOC(uint8_t, EVP_MD_size(md)); 5257b5038d7SDag-Erling Smørgrav if (!digest) { 5267b5038d7SDag-Erling Smørgrav ldns_rr_free(ds); 5277b5038d7SDag-Erling Smørgrav return NULL; 5287b5038d7SDag-Erling Smørgrav } 5297b5038d7SDag-Erling Smørgrav break; 5307b5038d7SDag-Erling Smørgrav #else 5317b5038d7SDag-Erling Smørgrav /* not implemented */ 5327b5038d7SDag-Erling Smørgrav ldns_rr_free(ds); 5337b5038d7SDag-Erling Smørgrav return NULL; 5347b5038d7SDag-Erling Smørgrav #endif 5357b5038d7SDag-Erling Smørgrav case LDNS_SHA384: 5367b5038d7SDag-Erling Smørgrav #ifdef USE_ECDSA 5377b5038d7SDag-Erling Smørgrav digest = LDNS_XMALLOC(uint8_t, SHA384_DIGEST_LENGTH); 5387b5038d7SDag-Erling Smørgrav if (!digest) { 5397b5038d7SDag-Erling Smørgrav ldns_rr_free(ds); 5407b5038d7SDag-Erling Smørgrav return NULL; 5417b5038d7SDag-Erling Smørgrav } 5427b5038d7SDag-Erling Smørgrav break; 5437b5038d7SDag-Erling Smørgrav #else 5447b5038d7SDag-Erling Smørgrav /* not implemented */ 5457b5038d7SDag-Erling Smørgrav ldns_rr_free(ds); 5467b5038d7SDag-Erling Smørgrav return NULL; 5477b5038d7SDag-Erling Smørgrav #endif 5487b5038d7SDag-Erling Smørgrav } 5497b5038d7SDag-Erling Smørgrav 5507b5038d7SDag-Erling Smørgrav data_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN); 5517b5038d7SDag-Erling Smørgrav if (!data_buf) { 5527b5038d7SDag-Erling Smørgrav LDNS_FREE(digest); 5537b5038d7SDag-Erling Smørgrav ldns_rr_free(ds); 5547b5038d7SDag-Erling Smørgrav return NULL; 5557b5038d7SDag-Erling Smørgrav } 5567b5038d7SDag-Erling Smørgrav 5577b5038d7SDag-Erling Smørgrav /* keytag */ 5587b5038d7SDag-Erling Smørgrav keytag = htons(ldns_calc_keytag((ldns_rr*)key)); 5597b5038d7SDag-Erling Smørgrav tmp = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_INT16, 5607b5038d7SDag-Erling Smørgrav sizeof(uint16_t), 5617b5038d7SDag-Erling Smørgrav &keytag); 5627b5038d7SDag-Erling Smørgrav ldns_rr_push_rdf(ds, tmp); 5637b5038d7SDag-Erling Smørgrav 5647b5038d7SDag-Erling Smørgrav /* copy the algorithm field */ 5657b5038d7SDag-Erling Smørgrav if ((tmp = ldns_rr_rdf(key, 2)) == NULL) { 5667b5038d7SDag-Erling Smørgrav LDNS_FREE(digest); 5677b5038d7SDag-Erling Smørgrav ldns_buffer_free(data_buf); 5687b5038d7SDag-Erling Smørgrav ldns_rr_free(ds); 5697b5038d7SDag-Erling Smørgrav return NULL; 5707b5038d7SDag-Erling Smørgrav } else { 5717b5038d7SDag-Erling Smørgrav ldns_rr_push_rdf(ds, ldns_rdf_clone( tmp )); 5727b5038d7SDag-Erling Smørgrav } 5737b5038d7SDag-Erling Smørgrav 5747b5038d7SDag-Erling Smørgrav /* digest hash type */ 5757b5038d7SDag-Erling Smørgrav sha1hash = (uint8_t)h; 5767b5038d7SDag-Erling Smørgrav tmp = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_INT8, 5777b5038d7SDag-Erling Smørgrav sizeof(uint8_t), 5787b5038d7SDag-Erling Smørgrav &sha1hash); 5797b5038d7SDag-Erling Smørgrav ldns_rr_push_rdf(ds, tmp); 5807b5038d7SDag-Erling Smørgrav 5817b5038d7SDag-Erling Smørgrav /* digest */ 5827b5038d7SDag-Erling Smørgrav /* owner name */ 5837b5038d7SDag-Erling Smørgrav tmp = ldns_rdf_clone(ldns_rr_owner(key)); 5847b5038d7SDag-Erling Smørgrav ldns_dname2canonical(tmp); 5857b5038d7SDag-Erling Smørgrav if (ldns_rdf2buffer_wire(data_buf, tmp) != LDNS_STATUS_OK) { 5867b5038d7SDag-Erling Smørgrav LDNS_FREE(digest); 5877b5038d7SDag-Erling Smørgrav ldns_buffer_free(data_buf); 5887b5038d7SDag-Erling Smørgrav ldns_rr_free(ds); 5897b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(tmp); 5907b5038d7SDag-Erling Smørgrav return NULL; 5917b5038d7SDag-Erling Smørgrav } 5927b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(tmp); 5937b5038d7SDag-Erling Smørgrav 5947b5038d7SDag-Erling Smørgrav /* all the rdata's */ 5957b5038d7SDag-Erling Smørgrav if (ldns_rr_rdata2buffer_wire(data_buf, 5967b5038d7SDag-Erling Smørgrav (ldns_rr*)key) != LDNS_STATUS_OK) { 5977b5038d7SDag-Erling Smørgrav LDNS_FREE(digest); 5987b5038d7SDag-Erling Smørgrav ldns_buffer_free(data_buf); 5997b5038d7SDag-Erling Smørgrav ldns_rr_free(ds); 6007b5038d7SDag-Erling Smørgrav return NULL; 6017b5038d7SDag-Erling Smørgrav } 6027b5038d7SDag-Erling Smørgrav switch(h) { 6037b5038d7SDag-Erling Smørgrav case LDNS_SHA1: 6047b5038d7SDag-Erling Smørgrav (void) ldns_sha1((unsigned char *) ldns_buffer_begin(data_buf), 6057b5038d7SDag-Erling Smørgrav (unsigned int) ldns_buffer_position(data_buf), 6067b5038d7SDag-Erling Smørgrav (unsigned char *) digest); 6077b5038d7SDag-Erling Smørgrav 6087b5038d7SDag-Erling Smørgrav tmp = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_HEX, 6097b5038d7SDag-Erling Smørgrav LDNS_SHA1_DIGEST_LENGTH, 6107b5038d7SDag-Erling Smørgrav digest); 6117b5038d7SDag-Erling Smørgrav ldns_rr_push_rdf(ds, tmp); 6127b5038d7SDag-Erling Smørgrav 6137b5038d7SDag-Erling Smørgrav break; 6147b5038d7SDag-Erling Smørgrav case LDNS_SHA256: 6157b5038d7SDag-Erling Smørgrav (void) ldns_sha256((unsigned char *) ldns_buffer_begin(data_buf), 6167b5038d7SDag-Erling Smørgrav (unsigned int) ldns_buffer_position(data_buf), 6177b5038d7SDag-Erling Smørgrav (unsigned char *) digest); 6187b5038d7SDag-Erling Smørgrav tmp = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_HEX, 6197b5038d7SDag-Erling Smørgrav LDNS_SHA256_DIGEST_LENGTH, 6207b5038d7SDag-Erling Smørgrav digest); 6217b5038d7SDag-Erling Smørgrav ldns_rr_push_rdf(ds, tmp); 6227b5038d7SDag-Erling Smørgrav break; 6237b5038d7SDag-Erling Smørgrav case LDNS_HASH_GOST: 6247b5038d7SDag-Erling Smørgrav #ifdef USE_GOST 6257b5038d7SDag-Erling Smørgrav if(!ldns_digest_evp((unsigned char *) ldns_buffer_begin(data_buf), 6267b5038d7SDag-Erling Smørgrav (unsigned int) ldns_buffer_position(data_buf), 6277b5038d7SDag-Erling Smørgrav (unsigned char *) digest, md)) { 6287b5038d7SDag-Erling Smørgrav LDNS_FREE(digest); 6297b5038d7SDag-Erling Smørgrav ldns_buffer_free(data_buf); 6307b5038d7SDag-Erling Smørgrav ldns_rr_free(ds); 6317b5038d7SDag-Erling Smørgrav return NULL; 6327b5038d7SDag-Erling Smørgrav } 6337b5038d7SDag-Erling Smørgrav tmp = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_HEX, 6347b5038d7SDag-Erling Smørgrav (size_t)EVP_MD_size(md), 6357b5038d7SDag-Erling Smørgrav digest); 6367b5038d7SDag-Erling Smørgrav ldns_rr_push_rdf(ds, tmp); 6377b5038d7SDag-Erling Smørgrav #endif 6387b5038d7SDag-Erling Smørgrav break; 6397b5038d7SDag-Erling Smørgrav case LDNS_SHA384: 6407b5038d7SDag-Erling Smørgrav #ifdef USE_ECDSA 6417b5038d7SDag-Erling Smørgrav (void) SHA384((unsigned char *) ldns_buffer_begin(data_buf), 6427b5038d7SDag-Erling Smørgrav (unsigned int) ldns_buffer_position(data_buf), 6437b5038d7SDag-Erling Smørgrav (unsigned char *) digest); 6447b5038d7SDag-Erling Smørgrav tmp = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_HEX, 6457b5038d7SDag-Erling Smørgrav SHA384_DIGEST_LENGTH, 6467b5038d7SDag-Erling Smørgrav digest); 6477b5038d7SDag-Erling Smørgrav ldns_rr_push_rdf(ds, tmp); 6487b5038d7SDag-Erling Smørgrav #endif 6497b5038d7SDag-Erling Smørgrav break; 6507b5038d7SDag-Erling Smørgrav } 6517b5038d7SDag-Erling Smørgrav 6527b5038d7SDag-Erling Smørgrav LDNS_FREE(digest); 6537b5038d7SDag-Erling Smørgrav ldns_buffer_free(data_buf); 6547b5038d7SDag-Erling Smørgrav return ds; 6557b5038d7SDag-Erling Smørgrav } 6567b5038d7SDag-Erling Smørgrav 657*17d15b25SDag-Erling Smørgrav /* From RFC3845: 658*17d15b25SDag-Erling Smørgrav * 659*17d15b25SDag-Erling Smørgrav * 2.1.2. The List of Type Bit Map(s) Field 660*17d15b25SDag-Erling Smørgrav * 661*17d15b25SDag-Erling Smørgrav * The RR type space is split into 256 window blocks, each representing 662*17d15b25SDag-Erling Smørgrav * the low-order 8 bits of the 16-bit RR type space. Each block that 663*17d15b25SDag-Erling Smørgrav * has at least one active RR type is encoded using a single octet 664*17d15b25SDag-Erling Smørgrav * window number (from 0 to 255), a single octet bitmap length (from 1 665*17d15b25SDag-Erling Smørgrav * to 32) indicating the number of octets used for the window block's 666*17d15b25SDag-Erling Smørgrav * bitmap, and up to 32 octets (256 bits) of bitmap. 667*17d15b25SDag-Erling Smørgrav * 668*17d15b25SDag-Erling Smørgrav * Window blocks are present in the NSEC RR RDATA in increasing 669*17d15b25SDag-Erling Smørgrav * numerical order. 670*17d15b25SDag-Erling Smørgrav * 671*17d15b25SDag-Erling Smørgrav * "|" denotes concatenation 672*17d15b25SDag-Erling Smørgrav * 673*17d15b25SDag-Erling Smørgrav * Type Bit Map(s) Field = ( Window Block # | Bitmap Length | Bitmap ) + 674*17d15b25SDag-Erling Smørgrav * 675*17d15b25SDag-Erling Smørgrav * <cut> 676*17d15b25SDag-Erling Smørgrav * 677*17d15b25SDag-Erling Smørgrav * Blocks with no types present MUST NOT be included. Trailing zero 678*17d15b25SDag-Erling Smørgrav * octets in the bitmap MUST be omitted. The length of each block's 679*17d15b25SDag-Erling Smørgrav * bitmap is determined by the type code with the largest numerical 680*17d15b25SDag-Erling Smørgrav * value within that block, among the set of RR types present at the 681*17d15b25SDag-Erling Smørgrav * NSEC RR's owner name. Trailing zero octets not specified MUST be 682*17d15b25SDag-Erling Smørgrav * interpreted as zero octets. 683*17d15b25SDag-Erling Smørgrav */ 6847b5038d7SDag-Erling Smørgrav ldns_rdf * 6857b5038d7SDag-Erling Smørgrav ldns_dnssec_create_nsec_bitmap(ldns_rr_type rr_type_list[], 6867b5038d7SDag-Erling Smørgrav size_t size, 6877b5038d7SDag-Erling Smørgrav ldns_rr_type nsec_type) 6887b5038d7SDag-Erling Smørgrav { 689*17d15b25SDag-Erling Smørgrav uint8_t window; /* most significant octet of type */ 690*17d15b25SDag-Erling Smørgrav uint8_t subtype; /* least significant octet of type */ 691*17d15b25SDag-Erling Smørgrav uint16_t windows[256] /* Max subtype per window */ 692*17d15b25SDag-Erling Smørgrav #ifndef S_SPLINT_S 693*17d15b25SDag-Erling Smørgrav = { 0 } /* Initialize ALL elements with 0 */ 694*17d15b25SDag-Erling Smørgrav #endif 695*17d15b25SDag-Erling Smørgrav ; 696*17d15b25SDag-Erling Smørgrav ldns_rr_type* d; /* used to traverse rr_type_list*/ 697*17d15b25SDag-Erling Smørgrav size_t i; /* used to traverse windows array */ 6987b5038d7SDag-Erling Smørgrav 699*17d15b25SDag-Erling Smørgrav size_t sz; /* size needed for type bitmap rdf */ 700*17d15b25SDag-Erling Smørgrav uint8_t* data = NULL; /* rdf data */ 701*17d15b25SDag-Erling Smørgrav uint8_t* dptr; /* used to itraverse rdf data */ 702*17d15b25SDag-Erling Smørgrav ldns_rdf* rdf; /* bitmap rdf to return */ 7037b5038d7SDag-Erling Smørgrav 7047b5038d7SDag-Erling Smørgrav if (nsec_type != LDNS_RR_TYPE_NSEC && 7057b5038d7SDag-Erling Smørgrav nsec_type != LDNS_RR_TYPE_NSEC3) { 7067b5038d7SDag-Erling Smørgrav return NULL; 7077b5038d7SDag-Erling Smørgrav } 7087b5038d7SDag-Erling Smørgrav 709*17d15b25SDag-Erling Smørgrav /* Which other windows need to be in the bitmap rdf? 710*17d15b25SDag-Erling Smørgrav */ 711*17d15b25SDag-Erling Smørgrav for (d = rr_type_list; d < rr_type_list + size; d++) { 712*17d15b25SDag-Erling Smørgrav window = *d >> 8; 713*17d15b25SDag-Erling Smørgrav subtype = *d & 0xff; 714*17d15b25SDag-Erling Smørgrav if (windows[window] < subtype) { 715*17d15b25SDag-Erling Smørgrav windows[window] = subtype; 7167b5038d7SDag-Erling Smørgrav } 7177b5038d7SDag-Erling Smørgrav } 7187b5038d7SDag-Erling Smørgrav 719*17d15b25SDag-Erling Smørgrav /* How much space do we need in the rdf for those windows? 720*17d15b25SDag-Erling Smørgrav */ 721*17d15b25SDag-Erling Smørgrav sz = 0; 722*17d15b25SDag-Erling Smørgrav for (i = 0; i < 256; i++) { 723*17d15b25SDag-Erling Smørgrav if (windows[i]) { 724*17d15b25SDag-Erling Smørgrav sz += windows[i] / 8 + 3; 7257b5038d7SDag-Erling Smørgrav } 7267b5038d7SDag-Erling Smørgrav } 727*17d15b25SDag-Erling Smørgrav if (sz > 0) { 728*17d15b25SDag-Erling Smørgrav /* Format rdf data according RFC3845 Section 2.1.2 (see above) 729*17d15b25SDag-Erling Smørgrav */ 730*17d15b25SDag-Erling Smørgrav dptr = data = LDNS_CALLOC(uint8_t, sz); 7317b5038d7SDag-Erling Smørgrav if (!data) { 7327b5038d7SDag-Erling Smørgrav return NULL; 7337b5038d7SDag-Erling Smørgrav } 734*17d15b25SDag-Erling Smørgrav for (i = 0; i < 256; i++) { 735*17d15b25SDag-Erling Smørgrav if (windows[i]) { 736*17d15b25SDag-Erling Smørgrav *dptr++ = (uint8_t)i; 737*17d15b25SDag-Erling Smørgrav *dptr++ = (uint8_t)(windows[i] / 8 + 1); 7387b5038d7SDag-Erling Smørgrav 739*17d15b25SDag-Erling Smørgrav /* Now let windows[i] index the bitmap 740*17d15b25SDag-Erling Smørgrav * within data 741*17d15b25SDag-Erling Smørgrav */ 742*17d15b25SDag-Erling Smørgrav windows[i] = (uint16_t)(dptr - data); 743*17d15b25SDag-Erling Smørgrav 744*17d15b25SDag-Erling Smørgrav dptr += dptr[-1]; 745*17d15b25SDag-Erling Smørgrav } 746*17d15b25SDag-Erling Smørgrav } 747*17d15b25SDag-Erling Smørgrav } 748*17d15b25SDag-Erling Smørgrav 749*17d15b25SDag-Erling Smørgrav /* Set the bits? 750*17d15b25SDag-Erling Smørgrav */ 751*17d15b25SDag-Erling Smørgrav for (d = rr_type_list; d < rr_type_list + size; d++) { 752*17d15b25SDag-Erling Smørgrav subtype = *d & 0xff; 753*17d15b25SDag-Erling Smørgrav data[windows[*d >> 8] + subtype/8] |= (0x80 >> (subtype % 8)); 754*17d15b25SDag-Erling Smørgrav } 755*17d15b25SDag-Erling Smørgrav 756*17d15b25SDag-Erling Smørgrav /* Allocate and return rdf structure for the data 757*17d15b25SDag-Erling Smørgrav */ 758*17d15b25SDag-Erling Smørgrav rdf = ldns_rdf_new(LDNS_RDF_TYPE_BITMAP, sz, data); 759*17d15b25SDag-Erling Smørgrav if (!rdf) { 7607b5038d7SDag-Erling Smørgrav LDNS_FREE(data); 761*17d15b25SDag-Erling Smørgrav return NULL; 762*17d15b25SDag-Erling Smørgrav } 763*17d15b25SDag-Erling Smørgrav return rdf; 7647b5038d7SDag-Erling Smørgrav } 7657b5038d7SDag-Erling Smørgrav 7667b5038d7SDag-Erling Smørgrav int 7677b5038d7SDag-Erling Smørgrav ldns_dnssec_rrsets_contains_type(ldns_dnssec_rrsets *rrsets, 7687b5038d7SDag-Erling Smørgrav ldns_rr_type type) 7697b5038d7SDag-Erling Smørgrav { 7707b5038d7SDag-Erling Smørgrav ldns_dnssec_rrsets *cur_rrset = rrsets; 7717b5038d7SDag-Erling Smørgrav while (cur_rrset) { 7727b5038d7SDag-Erling Smørgrav if (cur_rrset->type == type) { 7737b5038d7SDag-Erling Smørgrav return 1; 7747b5038d7SDag-Erling Smørgrav } 7757b5038d7SDag-Erling Smørgrav cur_rrset = cur_rrset->next; 7767b5038d7SDag-Erling Smørgrav } 7777b5038d7SDag-Erling Smørgrav return 0; 7787b5038d7SDag-Erling Smørgrav } 7797b5038d7SDag-Erling Smørgrav 7807b5038d7SDag-Erling Smørgrav ldns_rr * 7817b5038d7SDag-Erling Smørgrav ldns_dnssec_create_nsec(ldns_dnssec_name *from, 7827b5038d7SDag-Erling Smørgrav ldns_dnssec_name *to, 7837b5038d7SDag-Erling Smørgrav ldns_rr_type nsec_type) 7847b5038d7SDag-Erling Smørgrav { 7857b5038d7SDag-Erling Smørgrav ldns_rr *nsec_rr; 7867b5038d7SDag-Erling Smørgrav ldns_rr_type types[65536]; 7877b5038d7SDag-Erling Smørgrav size_t type_count = 0; 7887b5038d7SDag-Erling Smørgrav ldns_dnssec_rrsets *cur_rrsets; 7897b5038d7SDag-Erling Smørgrav int on_delegation_point; 7907b5038d7SDag-Erling Smørgrav 7917b5038d7SDag-Erling Smørgrav if (!from || !to || (nsec_type != LDNS_RR_TYPE_NSEC)) { 7927b5038d7SDag-Erling Smørgrav return NULL; 7937b5038d7SDag-Erling Smørgrav } 7947b5038d7SDag-Erling Smørgrav 7957b5038d7SDag-Erling Smørgrav nsec_rr = ldns_rr_new(); 7967b5038d7SDag-Erling Smørgrav ldns_rr_set_type(nsec_rr, nsec_type); 7977b5038d7SDag-Erling Smørgrav ldns_rr_set_owner(nsec_rr, ldns_rdf_clone(ldns_dnssec_name_name(from))); 7987b5038d7SDag-Erling Smørgrav ldns_rr_push_rdf(nsec_rr, ldns_rdf_clone(ldns_dnssec_name_name(to))); 7997b5038d7SDag-Erling Smørgrav 8007b5038d7SDag-Erling Smørgrav on_delegation_point = ldns_dnssec_rrsets_contains_type( 8017b5038d7SDag-Erling Smørgrav from->rrsets, LDNS_RR_TYPE_NS) 8027b5038d7SDag-Erling Smørgrav && !ldns_dnssec_rrsets_contains_type( 8037b5038d7SDag-Erling Smørgrav from->rrsets, LDNS_RR_TYPE_SOA); 8047b5038d7SDag-Erling Smørgrav 8057b5038d7SDag-Erling Smørgrav cur_rrsets = from->rrsets; 8067b5038d7SDag-Erling Smørgrav while (cur_rrsets) { 8077b5038d7SDag-Erling Smørgrav /* Do not include non-authoritative rrsets on the delegation point 8087b5038d7SDag-Erling Smørgrav * in the type bitmap */ 8097b5038d7SDag-Erling Smørgrav if ((on_delegation_point && ( 8107b5038d7SDag-Erling Smørgrav cur_rrsets->type == LDNS_RR_TYPE_NS 8117b5038d7SDag-Erling Smørgrav || cur_rrsets->type == LDNS_RR_TYPE_DS)) 8127b5038d7SDag-Erling Smørgrav || (!on_delegation_point && 8137b5038d7SDag-Erling Smørgrav cur_rrsets->type != LDNS_RR_TYPE_RRSIG 8147b5038d7SDag-Erling Smørgrav && cur_rrsets->type != LDNS_RR_TYPE_NSEC)) { 8157b5038d7SDag-Erling Smørgrav 8167b5038d7SDag-Erling Smørgrav types[type_count] = cur_rrsets->type; 8177b5038d7SDag-Erling Smørgrav type_count++; 8187b5038d7SDag-Erling Smørgrav } 8197b5038d7SDag-Erling Smørgrav cur_rrsets = cur_rrsets->next; 8207b5038d7SDag-Erling Smørgrav 8217b5038d7SDag-Erling Smørgrav } 8227b5038d7SDag-Erling Smørgrav types[type_count] = LDNS_RR_TYPE_RRSIG; 8237b5038d7SDag-Erling Smørgrav type_count++; 8247b5038d7SDag-Erling Smørgrav types[type_count] = LDNS_RR_TYPE_NSEC; 8257b5038d7SDag-Erling Smørgrav type_count++; 8267b5038d7SDag-Erling Smørgrav 8277b5038d7SDag-Erling Smørgrav ldns_rr_push_rdf(nsec_rr, ldns_dnssec_create_nsec_bitmap(types, 8287b5038d7SDag-Erling Smørgrav type_count, 8297b5038d7SDag-Erling Smørgrav nsec_type)); 8307b5038d7SDag-Erling Smørgrav 8317b5038d7SDag-Erling Smørgrav return nsec_rr; 8327b5038d7SDag-Erling Smørgrav } 8337b5038d7SDag-Erling Smørgrav 8347b5038d7SDag-Erling Smørgrav ldns_rr * 8357b5038d7SDag-Erling Smørgrav ldns_dnssec_create_nsec3(ldns_dnssec_name *from, 8367b5038d7SDag-Erling Smørgrav ldns_dnssec_name *to, 8377b5038d7SDag-Erling Smørgrav ldns_rdf *zone_name, 8387b5038d7SDag-Erling Smørgrav uint8_t algorithm, 8397b5038d7SDag-Erling Smørgrav uint8_t flags, 8407b5038d7SDag-Erling Smørgrav uint16_t iterations, 8417b5038d7SDag-Erling Smørgrav uint8_t salt_length, 8427b5038d7SDag-Erling Smørgrav uint8_t *salt) 8437b5038d7SDag-Erling Smørgrav { 8447b5038d7SDag-Erling Smørgrav ldns_rr *nsec_rr; 8457b5038d7SDag-Erling Smørgrav ldns_rr_type types[65536]; 8467b5038d7SDag-Erling Smørgrav size_t type_count = 0; 8477b5038d7SDag-Erling Smørgrav ldns_dnssec_rrsets *cur_rrsets; 8487b5038d7SDag-Erling Smørgrav ldns_status status; 8497b5038d7SDag-Erling Smørgrav int on_delegation_point; 8507b5038d7SDag-Erling Smørgrav 8517b5038d7SDag-Erling Smørgrav if (!from) { 8527b5038d7SDag-Erling Smørgrav return NULL; 8537b5038d7SDag-Erling Smørgrav } 8547b5038d7SDag-Erling Smørgrav 8557b5038d7SDag-Erling Smørgrav nsec_rr = ldns_rr_new_frm_type(LDNS_RR_TYPE_NSEC3); 8567b5038d7SDag-Erling Smørgrav ldns_rr_set_owner(nsec_rr, 8577b5038d7SDag-Erling Smørgrav ldns_nsec3_hash_name(ldns_dnssec_name_name(from), 8587b5038d7SDag-Erling Smørgrav algorithm, 8597b5038d7SDag-Erling Smørgrav iterations, 8607b5038d7SDag-Erling Smørgrav salt_length, 8617b5038d7SDag-Erling Smørgrav salt)); 8627b5038d7SDag-Erling Smørgrav status = ldns_dname_cat(ldns_rr_owner(nsec_rr), zone_name); 8637b5038d7SDag-Erling Smørgrav if(status != LDNS_STATUS_OK) { 8647b5038d7SDag-Erling Smørgrav ldns_rr_free(nsec_rr); 8657b5038d7SDag-Erling Smørgrav return NULL; 8667b5038d7SDag-Erling Smørgrav } 8677b5038d7SDag-Erling Smørgrav ldns_nsec3_add_param_rdfs(nsec_rr, 8687b5038d7SDag-Erling Smørgrav algorithm, 8697b5038d7SDag-Erling Smørgrav flags, 8707b5038d7SDag-Erling Smørgrav iterations, 8717b5038d7SDag-Erling Smørgrav salt_length, 8727b5038d7SDag-Erling Smørgrav salt); 8737b5038d7SDag-Erling Smørgrav 8747b5038d7SDag-Erling Smørgrav on_delegation_point = ldns_dnssec_rrsets_contains_type( 8757b5038d7SDag-Erling Smørgrav from->rrsets, LDNS_RR_TYPE_NS) 8767b5038d7SDag-Erling Smørgrav && !ldns_dnssec_rrsets_contains_type( 8777b5038d7SDag-Erling Smørgrav from->rrsets, LDNS_RR_TYPE_SOA); 8787b5038d7SDag-Erling Smørgrav cur_rrsets = from->rrsets; 8797b5038d7SDag-Erling Smørgrav while (cur_rrsets) { 8807b5038d7SDag-Erling Smørgrav /* Do not include non-authoritative rrsets on the delegation point 8817b5038d7SDag-Erling Smørgrav * in the type bitmap. Potentionally not skipping insecure 8827b5038d7SDag-Erling Smørgrav * delegation should have been done earlier, in function 8837b5038d7SDag-Erling Smørgrav * ldns_dnssec_zone_create_nsec3s, or even earlier in: 8847b5038d7SDag-Erling Smørgrav * ldns_dnssec_zone_sign_nsec3_flg . 8857b5038d7SDag-Erling Smørgrav */ 8867b5038d7SDag-Erling Smørgrav if ((on_delegation_point && ( 8877b5038d7SDag-Erling Smørgrav cur_rrsets->type == LDNS_RR_TYPE_NS 8887b5038d7SDag-Erling Smørgrav || cur_rrsets->type == LDNS_RR_TYPE_DS)) 8897b5038d7SDag-Erling Smørgrav || (!on_delegation_point && 8907b5038d7SDag-Erling Smørgrav cur_rrsets->type != LDNS_RR_TYPE_RRSIG)) { 8917b5038d7SDag-Erling Smørgrav 8927b5038d7SDag-Erling Smørgrav types[type_count] = cur_rrsets->type; 8937b5038d7SDag-Erling Smørgrav type_count++; 8947b5038d7SDag-Erling Smørgrav } 8957b5038d7SDag-Erling Smørgrav cur_rrsets = cur_rrsets->next; 8967b5038d7SDag-Erling Smørgrav } 8977b5038d7SDag-Erling Smørgrav /* always add rrsig type if this is not an unsigned 8987b5038d7SDag-Erling Smørgrav * delegation 8997b5038d7SDag-Erling Smørgrav */ 9007b5038d7SDag-Erling Smørgrav if (type_count > 0 && 9017b5038d7SDag-Erling Smørgrav !(type_count == 1 && types[0] == LDNS_RR_TYPE_NS)) { 9027b5038d7SDag-Erling Smørgrav types[type_count] = LDNS_RR_TYPE_RRSIG; 9037b5038d7SDag-Erling Smørgrav type_count++; 9047b5038d7SDag-Erling Smørgrav } 9057b5038d7SDag-Erling Smørgrav 9067b5038d7SDag-Erling Smørgrav /* leave next rdata empty if they weren't precomputed yet */ 9077b5038d7SDag-Erling Smørgrav if (to && to->hashed_name) { 9087b5038d7SDag-Erling Smørgrav (void) ldns_rr_set_rdf(nsec_rr, 9097b5038d7SDag-Erling Smørgrav ldns_rdf_clone(to->hashed_name), 9107b5038d7SDag-Erling Smørgrav 4); 9117b5038d7SDag-Erling Smørgrav } else { 9127b5038d7SDag-Erling Smørgrav (void) ldns_rr_set_rdf(nsec_rr, NULL, 4); 9137b5038d7SDag-Erling Smørgrav } 9147b5038d7SDag-Erling Smørgrav 9157b5038d7SDag-Erling Smørgrav ldns_rr_push_rdf(nsec_rr, 9167b5038d7SDag-Erling Smørgrav ldns_dnssec_create_nsec_bitmap(types, 9177b5038d7SDag-Erling Smørgrav type_count, 9187b5038d7SDag-Erling Smørgrav LDNS_RR_TYPE_NSEC3)); 9197b5038d7SDag-Erling Smørgrav 9207b5038d7SDag-Erling Smørgrav return nsec_rr; 9217b5038d7SDag-Erling Smørgrav } 9227b5038d7SDag-Erling Smørgrav 9237b5038d7SDag-Erling Smørgrav ldns_rr * 9247b5038d7SDag-Erling Smørgrav ldns_create_nsec(ldns_rdf *cur_owner, ldns_rdf *next_owner, ldns_rr_list *rrs) 9257b5038d7SDag-Erling Smørgrav { 9267b5038d7SDag-Erling Smørgrav /* we do not do any check here - garbage in, garbage out */ 9277b5038d7SDag-Erling Smørgrav 9287b5038d7SDag-Erling Smørgrav /* the the start and end names - get the type from the 9297b5038d7SDag-Erling Smørgrav * before rrlist */ 9307b5038d7SDag-Erling Smørgrav 9317b5038d7SDag-Erling Smørgrav /* inefficient, just give it a name, a next name, and a list of rrs */ 9327b5038d7SDag-Erling Smørgrav /* we make 1 big uberbitmap first, then windows */ 9337b5038d7SDag-Erling Smørgrav /* todo: make something more efficient :) */ 9347b5038d7SDag-Erling Smørgrav uint16_t i; 9357b5038d7SDag-Erling Smørgrav ldns_rr *i_rr; 9367b5038d7SDag-Erling Smørgrav uint16_t i_type; 9377b5038d7SDag-Erling Smørgrav 9387b5038d7SDag-Erling Smørgrav ldns_rr *nsec = NULL; 9397b5038d7SDag-Erling Smørgrav ldns_rr_type i_type_list[65536]; 9407b5038d7SDag-Erling Smørgrav size_t type_count = 0; 9417b5038d7SDag-Erling Smørgrav 9427b5038d7SDag-Erling Smørgrav nsec = ldns_rr_new(); 9437b5038d7SDag-Erling Smørgrav ldns_rr_set_type(nsec, LDNS_RR_TYPE_NSEC); 9447b5038d7SDag-Erling Smørgrav ldns_rr_set_owner(nsec, ldns_rdf_clone(cur_owner)); 9457b5038d7SDag-Erling Smørgrav ldns_rr_push_rdf(nsec, ldns_rdf_clone(next_owner)); 9467b5038d7SDag-Erling Smørgrav 9477b5038d7SDag-Erling Smørgrav for (i = 0; i < ldns_rr_list_rr_count(rrs); i++) { 9487b5038d7SDag-Erling Smørgrav i_rr = ldns_rr_list_rr(rrs, i); 9497b5038d7SDag-Erling Smørgrav if (ldns_rdf_compare(cur_owner, 9507b5038d7SDag-Erling Smørgrav ldns_rr_owner(i_rr)) == 0) { 9517b5038d7SDag-Erling Smørgrav i_type = ldns_rr_get_type(i_rr); 9527b5038d7SDag-Erling Smørgrav if (i_type != LDNS_RR_TYPE_RRSIG && i_type != LDNS_RR_TYPE_NSEC) { 9537b5038d7SDag-Erling Smørgrav if (type_count == 0 || i_type_list[type_count-1] != i_type) { 9547b5038d7SDag-Erling Smørgrav i_type_list[type_count] = i_type; 9557b5038d7SDag-Erling Smørgrav type_count++; 9567b5038d7SDag-Erling Smørgrav } 9577b5038d7SDag-Erling Smørgrav } 9587b5038d7SDag-Erling Smørgrav } 9597b5038d7SDag-Erling Smørgrav } 9607b5038d7SDag-Erling Smørgrav 9617b5038d7SDag-Erling Smørgrav i_type_list[type_count] = LDNS_RR_TYPE_RRSIG; 9627b5038d7SDag-Erling Smørgrav type_count++; 9637b5038d7SDag-Erling Smørgrav i_type_list[type_count] = LDNS_RR_TYPE_NSEC; 9647b5038d7SDag-Erling Smørgrav type_count++; 9657b5038d7SDag-Erling Smørgrav 9667b5038d7SDag-Erling Smørgrav ldns_rr_push_rdf(nsec, 9677b5038d7SDag-Erling Smørgrav ldns_dnssec_create_nsec_bitmap(i_type_list, 9687b5038d7SDag-Erling Smørgrav type_count, LDNS_RR_TYPE_NSEC)); 9697b5038d7SDag-Erling Smørgrav 9707b5038d7SDag-Erling Smørgrav return nsec; 9717b5038d7SDag-Erling Smørgrav } 9727b5038d7SDag-Erling Smørgrav 9737b5038d7SDag-Erling Smørgrav ldns_rdf * 9747b5038d7SDag-Erling Smørgrav ldns_nsec3_hash_name(ldns_rdf *name, 9757b5038d7SDag-Erling Smørgrav uint8_t algorithm, 9767b5038d7SDag-Erling Smørgrav uint16_t iterations, 9777b5038d7SDag-Erling Smørgrav uint8_t salt_length, 9787b5038d7SDag-Erling Smørgrav uint8_t *salt) 9797b5038d7SDag-Erling Smørgrav { 9807b5038d7SDag-Erling Smørgrav size_t hashed_owner_str_len; 9817b5038d7SDag-Erling Smørgrav ldns_rdf *cann; 9827b5038d7SDag-Erling Smørgrav ldns_rdf *hashed_owner; 9837b5038d7SDag-Erling Smørgrav unsigned char *hashed_owner_str; 9847b5038d7SDag-Erling Smørgrav char *hashed_owner_b32; 9857b5038d7SDag-Erling Smørgrav size_t hashed_owner_b32_len; 9867b5038d7SDag-Erling Smørgrav uint32_t cur_it; 9877b5038d7SDag-Erling Smørgrav /* define to contain the largest possible hash, which is 9887b5038d7SDag-Erling Smørgrav * sha1 at the moment */ 9897b5038d7SDag-Erling Smørgrav unsigned char hash[LDNS_SHA1_DIGEST_LENGTH]; 9907b5038d7SDag-Erling Smørgrav ldns_status status; 9917b5038d7SDag-Erling Smørgrav 9927b5038d7SDag-Erling Smørgrav /* TODO: mnemonic list for hash algs SHA-1, default to 1 now (sha1) */ 9937b5038d7SDag-Erling Smørgrav if (algorithm != LDNS_SHA1) { 9947b5038d7SDag-Erling Smørgrav return NULL; 9957b5038d7SDag-Erling Smørgrav } 9967b5038d7SDag-Erling Smørgrav 9977b5038d7SDag-Erling Smørgrav /* prepare the owner name according to the draft section bla */ 9987b5038d7SDag-Erling Smørgrav cann = ldns_rdf_clone(name); 9997b5038d7SDag-Erling Smørgrav if(!cann) { 1000*17d15b25SDag-Erling Smørgrav #ifdef STDERR_MSGS 10017b5038d7SDag-Erling Smørgrav fprintf(stderr, "Memory error\n"); 1002*17d15b25SDag-Erling Smørgrav #endif 10037b5038d7SDag-Erling Smørgrav return NULL; 10047b5038d7SDag-Erling Smørgrav } 10057b5038d7SDag-Erling Smørgrav ldns_dname2canonical(cann); 10067b5038d7SDag-Erling Smørgrav 10077b5038d7SDag-Erling Smørgrav hashed_owner_str_len = salt_length + ldns_rdf_size(cann); 10087b5038d7SDag-Erling Smørgrav hashed_owner_str = LDNS_XMALLOC(unsigned char, hashed_owner_str_len); 10097b5038d7SDag-Erling Smørgrav if(!hashed_owner_str) { 10107b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(cann); 10117b5038d7SDag-Erling Smørgrav return NULL; 10127b5038d7SDag-Erling Smørgrav } 10137b5038d7SDag-Erling Smørgrav memcpy(hashed_owner_str, ldns_rdf_data(cann), ldns_rdf_size(cann)); 10147b5038d7SDag-Erling Smørgrav memcpy(hashed_owner_str + ldns_rdf_size(cann), salt, salt_length); 10157b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(cann); 10167b5038d7SDag-Erling Smørgrav 10177b5038d7SDag-Erling Smørgrav for (cur_it = iterations + 1; cur_it > 0; cur_it--) { 10187b5038d7SDag-Erling Smørgrav (void) ldns_sha1((unsigned char *) hashed_owner_str, 10197b5038d7SDag-Erling Smørgrav (unsigned int) hashed_owner_str_len, hash); 10207b5038d7SDag-Erling Smørgrav 10217b5038d7SDag-Erling Smørgrav LDNS_FREE(hashed_owner_str); 10227b5038d7SDag-Erling Smørgrav hashed_owner_str_len = salt_length + LDNS_SHA1_DIGEST_LENGTH; 10237b5038d7SDag-Erling Smørgrav hashed_owner_str = LDNS_XMALLOC(unsigned char, hashed_owner_str_len); 10247b5038d7SDag-Erling Smørgrav if (!hashed_owner_str) { 10257b5038d7SDag-Erling Smørgrav return NULL; 10267b5038d7SDag-Erling Smørgrav } 10277b5038d7SDag-Erling Smørgrav memcpy(hashed_owner_str, hash, LDNS_SHA1_DIGEST_LENGTH); 10287b5038d7SDag-Erling Smørgrav memcpy(hashed_owner_str + LDNS_SHA1_DIGEST_LENGTH, salt, salt_length); 10297b5038d7SDag-Erling Smørgrav hashed_owner_str_len = LDNS_SHA1_DIGEST_LENGTH + salt_length; 10307b5038d7SDag-Erling Smørgrav } 10317b5038d7SDag-Erling Smørgrav 10327b5038d7SDag-Erling Smørgrav LDNS_FREE(hashed_owner_str); 10337b5038d7SDag-Erling Smørgrav hashed_owner_str = hash; 10347b5038d7SDag-Erling Smørgrav hashed_owner_str_len = LDNS_SHA1_DIGEST_LENGTH; 10357b5038d7SDag-Erling Smørgrav 10367b5038d7SDag-Erling Smørgrav hashed_owner_b32 = LDNS_XMALLOC(char, 10377b5038d7SDag-Erling Smørgrav ldns_b32_ntop_calculate_size(hashed_owner_str_len) + 1); 10387b5038d7SDag-Erling Smørgrav if(!hashed_owner_b32) { 10397b5038d7SDag-Erling Smørgrav return NULL; 10407b5038d7SDag-Erling Smørgrav } 10417b5038d7SDag-Erling Smørgrav hashed_owner_b32_len = (size_t) ldns_b32_ntop_extended_hex( 10427b5038d7SDag-Erling Smørgrav (uint8_t *) hashed_owner_str, 10437b5038d7SDag-Erling Smørgrav hashed_owner_str_len, 10447b5038d7SDag-Erling Smørgrav hashed_owner_b32, 10457b5038d7SDag-Erling Smørgrav ldns_b32_ntop_calculate_size(hashed_owner_str_len)+1); 10467b5038d7SDag-Erling Smørgrav if (hashed_owner_b32_len < 1) { 1047*17d15b25SDag-Erling Smørgrav #ifdef STDERR_MSGS 10487b5038d7SDag-Erling Smørgrav fprintf(stderr, "Error in base32 extended hex encoding "); 10497b5038d7SDag-Erling Smørgrav fprintf(stderr, "of hashed owner name (name: "); 10507b5038d7SDag-Erling Smørgrav ldns_rdf_print(stderr, name); 10517b5038d7SDag-Erling Smørgrav fprintf(stderr, ", return code: %u)\n", 10527b5038d7SDag-Erling Smørgrav (unsigned int) hashed_owner_b32_len); 1053*17d15b25SDag-Erling Smørgrav #endif 10547b5038d7SDag-Erling Smørgrav LDNS_FREE(hashed_owner_b32); 10557b5038d7SDag-Erling Smørgrav return NULL; 10567b5038d7SDag-Erling Smørgrav } 10577b5038d7SDag-Erling Smørgrav hashed_owner_b32[hashed_owner_b32_len] = '\0'; 10587b5038d7SDag-Erling Smørgrav 10597b5038d7SDag-Erling Smørgrav status = ldns_str2rdf_dname(&hashed_owner, hashed_owner_b32); 10607b5038d7SDag-Erling Smørgrav if (status != LDNS_STATUS_OK) { 1061*17d15b25SDag-Erling Smørgrav #ifdef STDERR_MSGS 10627b5038d7SDag-Erling Smørgrav fprintf(stderr, "Error creating rdf from %s\n", hashed_owner_b32); 1063*17d15b25SDag-Erling Smørgrav #endif 10647b5038d7SDag-Erling Smørgrav LDNS_FREE(hashed_owner_b32); 10657b5038d7SDag-Erling Smørgrav return NULL; 10667b5038d7SDag-Erling Smørgrav } 10677b5038d7SDag-Erling Smørgrav 10687b5038d7SDag-Erling Smørgrav LDNS_FREE(hashed_owner_b32); 10697b5038d7SDag-Erling Smørgrav return hashed_owner; 10707b5038d7SDag-Erling Smørgrav } 10717b5038d7SDag-Erling Smørgrav 10727b5038d7SDag-Erling Smørgrav void 10737b5038d7SDag-Erling Smørgrav ldns_nsec3_add_param_rdfs(ldns_rr *rr, 10747b5038d7SDag-Erling Smørgrav uint8_t algorithm, 10757b5038d7SDag-Erling Smørgrav uint8_t flags, 10767b5038d7SDag-Erling Smørgrav uint16_t iterations, 10777b5038d7SDag-Erling Smørgrav uint8_t salt_length, 10787b5038d7SDag-Erling Smørgrav uint8_t *salt) 10797b5038d7SDag-Erling Smørgrav { 10807b5038d7SDag-Erling Smørgrav ldns_rdf *salt_rdf = NULL; 10817b5038d7SDag-Erling Smørgrav uint8_t *salt_data = NULL; 10827b5038d7SDag-Erling Smørgrav ldns_rdf *old; 10837b5038d7SDag-Erling Smørgrav 10847b5038d7SDag-Erling Smørgrav old = ldns_rr_set_rdf(rr, 10857b5038d7SDag-Erling Smørgrav ldns_rdf_new_frm_data(LDNS_RDF_TYPE_INT8, 10867b5038d7SDag-Erling Smørgrav 1, (void*)&algorithm), 10877b5038d7SDag-Erling Smørgrav 0); 10887b5038d7SDag-Erling Smørgrav if (old) ldns_rdf_deep_free(old); 10897b5038d7SDag-Erling Smørgrav 10907b5038d7SDag-Erling Smørgrav old = ldns_rr_set_rdf(rr, 10917b5038d7SDag-Erling Smørgrav ldns_rdf_new_frm_data(LDNS_RDF_TYPE_INT8, 10927b5038d7SDag-Erling Smørgrav 1, (void*)&flags), 10937b5038d7SDag-Erling Smørgrav 1); 10947b5038d7SDag-Erling Smørgrav if (old) ldns_rdf_deep_free(old); 10957b5038d7SDag-Erling Smørgrav 10967b5038d7SDag-Erling Smørgrav old = ldns_rr_set_rdf(rr, 10977b5038d7SDag-Erling Smørgrav ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, 10987b5038d7SDag-Erling Smørgrav iterations), 10997b5038d7SDag-Erling Smørgrav 2); 11007b5038d7SDag-Erling Smørgrav if (old) ldns_rdf_deep_free(old); 11017b5038d7SDag-Erling Smørgrav 11027b5038d7SDag-Erling Smørgrav salt_data = LDNS_XMALLOC(uint8_t, salt_length + 1); 11037b5038d7SDag-Erling Smørgrav if(!salt_data) { 11047b5038d7SDag-Erling Smørgrav /* no way to return error */ 11057b5038d7SDag-Erling Smørgrav return; 11067b5038d7SDag-Erling Smørgrav } 11077b5038d7SDag-Erling Smørgrav salt_data[0] = salt_length; 11087b5038d7SDag-Erling Smørgrav memcpy(salt_data + 1, salt, salt_length); 11097b5038d7SDag-Erling Smørgrav salt_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_NSEC3_SALT, 11107b5038d7SDag-Erling Smørgrav salt_length + 1, 11117b5038d7SDag-Erling Smørgrav salt_data); 11127b5038d7SDag-Erling Smørgrav if(!salt_rdf) { 11137b5038d7SDag-Erling Smørgrav LDNS_FREE(salt_data); 11147b5038d7SDag-Erling Smørgrav /* no way to return error */ 11157b5038d7SDag-Erling Smørgrav return; 11167b5038d7SDag-Erling Smørgrav } 11177b5038d7SDag-Erling Smørgrav 11187b5038d7SDag-Erling Smørgrav old = ldns_rr_set_rdf(rr, salt_rdf, 3); 11197b5038d7SDag-Erling Smørgrav if (old) ldns_rdf_deep_free(old); 11207b5038d7SDag-Erling Smørgrav LDNS_FREE(salt_data); 11217b5038d7SDag-Erling Smørgrav } 11227b5038d7SDag-Erling Smørgrav 11237b5038d7SDag-Erling Smørgrav static int 11247b5038d7SDag-Erling Smørgrav rr_list_delegation_only(ldns_rdf *origin, ldns_rr_list *rr_list) 11257b5038d7SDag-Erling Smørgrav { 11267b5038d7SDag-Erling Smørgrav size_t i; 11277b5038d7SDag-Erling Smørgrav ldns_rr *cur_rr; 11287b5038d7SDag-Erling Smørgrav if (!origin || !rr_list) return 0; 11297b5038d7SDag-Erling Smørgrav for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) { 11307b5038d7SDag-Erling Smørgrav cur_rr = ldns_rr_list_rr(rr_list, i); 11317b5038d7SDag-Erling Smørgrav if (ldns_dname_compare(ldns_rr_owner(cur_rr), origin) == 0) { 11327b5038d7SDag-Erling Smørgrav return 0; 11337b5038d7SDag-Erling Smørgrav } 11347b5038d7SDag-Erling Smørgrav if (ldns_rr_get_type(cur_rr) != LDNS_RR_TYPE_NS) { 11357b5038d7SDag-Erling Smørgrav return 0; 11367b5038d7SDag-Erling Smørgrav } 11377b5038d7SDag-Erling Smørgrav } 11387b5038d7SDag-Erling Smørgrav return 1; 11397b5038d7SDag-Erling Smørgrav } 11407b5038d7SDag-Erling Smørgrav 11417b5038d7SDag-Erling Smørgrav /* this will NOT return the NSEC3 completed, you will have to run the 11427b5038d7SDag-Erling Smørgrav finalize function on the rrlist later! */ 11437b5038d7SDag-Erling Smørgrav ldns_rr * 11447b5038d7SDag-Erling Smørgrav ldns_create_nsec3(ldns_rdf *cur_owner, 11457b5038d7SDag-Erling Smørgrav ldns_rdf *cur_zone, 11467b5038d7SDag-Erling Smørgrav ldns_rr_list *rrs, 11477b5038d7SDag-Erling Smørgrav uint8_t algorithm, 11487b5038d7SDag-Erling Smørgrav uint8_t flags, 11497b5038d7SDag-Erling Smørgrav uint16_t iterations, 11507b5038d7SDag-Erling Smørgrav uint8_t salt_length, 11517b5038d7SDag-Erling Smørgrav uint8_t *salt, 11527b5038d7SDag-Erling Smørgrav bool emptynonterminal) 11537b5038d7SDag-Erling Smørgrav { 11547b5038d7SDag-Erling Smørgrav size_t i; 11557b5038d7SDag-Erling Smørgrav ldns_rr *i_rr; 11567b5038d7SDag-Erling Smørgrav uint16_t i_type; 11577b5038d7SDag-Erling Smørgrav 11587b5038d7SDag-Erling Smørgrav ldns_rr *nsec = NULL; 11597b5038d7SDag-Erling Smørgrav ldns_rdf *hashed_owner = NULL; 11607b5038d7SDag-Erling Smørgrav 11617b5038d7SDag-Erling Smørgrav ldns_status status; 11627b5038d7SDag-Erling Smørgrav 11637b5038d7SDag-Erling Smørgrav ldns_rr_type i_type_list[1024]; 11647b5038d7SDag-Erling Smørgrav size_t type_count = 0; 11657b5038d7SDag-Erling Smørgrav 11667b5038d7SDag-Erling Smørgrav hashed_owner = ldns_nsec3_hash_name(cur_owner, 11677b5038d7SDag-Erling Smørgrav algorithm, 11687b5038d7SDag-Erling Smørgrav iterations, 11697b5038d7SDag-Erling Smørgrav salt_length, 11707b5038d7SDag-Erling Smørgrav salt); 11717b5038d7SDag-Erling Smørgrav status = ldns_dname_cat(hashed_owner, cur_zone); 11722787e39aSDag-Erling Smørgrav if(status != LDNS_STATUS_OK) { 11732787e39aSDag-Erling Smørgrav ldns_rdf_deep_free(hashed_owner); 11747b5038d7SDag-Erling Smørgrav return NULL; 11752787e39aSDag-Erling Smørgrav } 11767b5038d7SDag-Erling Smørgrav nsec = ldns_rr_new_frm_type(LDNS_RR_TYPE_NSEC3); 11772787e39aSDag-Erling Smørgrav if(!nsec) { 11782787e39aSDag-Erling Smørgrav ldns_rdf_deep_free(hashed_owner); 11797b5038d7SDag-Erling Smørgrav return NULL; 11802787e39aSDag-Erling Smørgrav } 11817b5038d7SDag-Erling Smørgrav ldns_rr_set_type(nsec, LDNS_RR_TYPE_NSEC3); 11827b5038d7SDag-Erling Smørgrav ldns_rr_set_owner(nsec, hashed_owner); 11837b5038d7SDag-Erling Smørgrav 11847b5038d7SDag-Erling Smørgrav ldns_nsec3_add_param_rdfs(nsec, 11857b5038d7SDag-Erling Smørgrav algorithm, 11867b5038d7SDag-Erling Smørgrav flags, 11877b5038d7SDag-Erling Smørgrav iterations, 11887b5038d7SDag-Erling Smørgrav salt_length, 11897b5038d7SDag-Erling Smørgrav salt); 11907b5038d7SDag-Erling Smørgrav (void) ldns_rr_set_rdf(nsec, NULL, 4); 11917b5038d7SDag-Erling Smørgrav 11927b5038d7SDag-Erling Smørgrav 11937b5038d7SDag-Erling Smørgrav for (i = 0; i < ldns_rr_list_rr_count(rrs); i++) { 11947b5038d7SDag-Erling Smørgrav i_rr = ldns_rr_list_rr(rrs, i); 11957b5038d7SDag-Erling Smørgrav if (ldns_rdf_compare(cur_owner, 11967b5038d7SDag-Erling Smørgrav ldns_rr_owner(i_rr)) == 0) { 11977b5038d7SDag-Erling Smørgrav i_type = ldns_rr_get_type(i_rr); 11987b5038d7SDag-Erling Smørgrav if (type_count == 0 || i_type_list[type_count-1] != i_type) { 11997b5038d7SDag-Erling Smørgrav i_type_list[type_count] = i_type; 12007b5038d7SDag-Erling Smørgrav type_count++; 12017b5038d7SDag-Erling Smørgrav } 12027b5038d7SDag-Erling Smørgrav } 12037b5038d7SDag-Erling Smørgrav } 12047b5038d7SDag-Erling Smørgrav 12057b5038d7SDag-Erling Smørgrav /* add RRSIG anyway, but only if this is not an ENT or 12067b5038d7SDag-Erling Smørgrav * an unsigned delegation */ 12077b5038d7SDag-Erling Smørgrav if (!emptynonterminal && !rr_list_delegation_only(cur_zone, rrs)) { 12087b5038d7SDag-Erling Smørgrav i_type_list[type_count] = LDNS_RR_TYPE_RRSIG; 12097b5038d7SDag-Erling Smørgrav type_count++; 12107b5038d7SDag-Erling Smørgrav } 12117b5038d7SDag-Erling Smørgrav 12127b5038d7SDag-Erling Smørgrav /* and SOA if owner == zone */ 12137b5038d7SDag-Erling Smørgrav if (ldns_dname_compare(cur_zone, cur_owner) == 0) { 12147b5038d7SDag-Erling Smørgrav i_type_list[type_count] = LDNS_RR_TYPE_SOA; 12157b5038d7SDag-Erling Smørgrav type_count++; 12167b5038d7SDag-Erling Smørgrav } 12177b5038d7SDag-Erling Smørgrav 12187b5038d7SDag-Erling Smørgrav ldns_rr_push_rdf(nsec, 12197b5038d7SDag-Erling Smørgrav ldns_dnssec_create_nsec_bitmap(i_type_list, 12207b5038d7SDag-Erling Smørgrav type_count, LDNS_RR_TYPE_NSEC3)); 12217b5038d7SDag-Erling Smørgrav 12227b5038d7SDag-Erling Smørgrav return nsec; 12237b5038d7SDag-Erling Smørgrav } 12247b5038d7SDag-Erling Smørgrav 12257b5038d7SDag-Erling Smørgrav uint8_t 12267b5038d7SDag-Erling Smørgrav ldns_nsec3_algorithm(const ldns_rr *nsec3_rr) 12277b5038d7SDag-Erling Smørgrav { 12287b5038d7SDag-Erling Smørgrav if (nsec3_rr && 12297b5038d7SDag-Erling Smørgrav (ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3 || 12307b5038d7SDag-Erling Smørgrav ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3PARAM) 12317b5038d7SDag-Erling Smørgrav && (ldns_rr_rdf(nsec3_rr, 0) != NULL) 12327b5038d7SDag-Erling Smørgrav && ldns_rdf_size(ldns_rr_rdf(nsec3_rr, 0)) > 0) { 12337b5038d7SDag-Erling Smørgrav return ldns_rdf2native_int8(ldns_rr_rdf(nsec3_rr, 0)); 12347b5038d7SDag-Erling Smørgrav } 12357b5038d7SDag-Erling Smørgrav return 0; 12367b5038d7SDag-Erling Smørgrav } 12377b5038d7SDag-Erling Smørgrav 12387b5038d7SDag-Erling Smørgrav uint8_t 12397b5038d7SDag-Erling Smørgrav ldns_nsec3_flags(const ldns_rr *nsec3_rr) 12407b5038d7SDag-Erling Smørgrav { 12417b5038d7SDag-Erling Smørgrav if (nsec3_rr && 12427b5038d7SDag-Erling Smørgrav (ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3 || 12437b5038d7SDag-Erling Smørgrav ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3PARAM) 12447b5038d7SDag-Erling Smørgrav && (ldns_rr_rdf(nsec3_rr, 1) != NULL) 12457b5038d7SDag-Erling Smørgrav && ldns_rdf_size(ldns_rr_rdf(nsec3_rr, 1)) > 0) { 12467b5038d7SDag-Erling Smørgrav return ldns_rdf2native_int8(ldns_rr_rdf(nsec3_rr, 1)); 12477b5038d7SDag-Erling Smørgrav } 12487b5038d7SDag-Erling Smørgrav return 0; 12497b5038d7SDag-Erling Smørgrav } 12507b5038d7SDag-Erling Smørgrav 12517b5038d7SDag-Erling Smørgrav bool 12527b5038d7SDag-Erling Smørgrav ldns_nsec3_optout(const ldns_rr *nsec3_rr) 12537b5038d7SDag-Erling Smørgrav { 12547b5038d7SDag-Erling Smørgrav return (ldns_nsec3_flags(nsec3_rr) & LDNS_NSEC3_VARS_OPTOUT_MASK); 12557b5038d7SDag-Erling Smørgrav } 12567b5038d7SDag-Erling Smørgrav 12577b5038d7SDag-Erling Smørgrav uint16_t 12587b5038d7SDag-Erling Smørgrav ldns_nsec3_iterations(const ldns_rr *nsec3_rr) 12597b5038d7SDag-Erling Smørgrav { 12607b5038d7SDag-Erling Smørgrav if (nsec3_rr && 12617b5038d7SDag-Erling Smørgrav (ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3 || 12627b5038d7SDag-Erling Smørgrav ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3PARAM) 12637b5038d7SDag-Erling Smørgrav && (ldns_rr_rdf(nsec3_rr, 2) != NULL) 12647b5038d7SDag-Erling Smørgrav && ldns_rdf_size(ldns_rr_rdf(nsec3_rr, 2)) > 0) { 12657b5038d7SDag-Erling Smørgrav return ldns_rdf2native_int16(ldns_rr_rdf(nsec3_rr, 2)); 12667b5038d7SDag-Erling Smørgrav } 12677b5038d7SDag-Erling Smørgrav return 0; 12687b5038d7SDag-Erling Smørgrav 12697b5038d7SDag-Erling Smørgrav } 12707b5038d7SDag-Erling Smørgrav 12717b5038d7SDag-Erling Smørgrav ldns_rdf * 12727b5038d7SDag-Erling Smørgrav ldns_nsec3_salt(const ldns_rr *nsec3_rr) 12737b5038d7SDag-Erling Smørgrav { 12747b5038d7SDag-Erling Smørgrav if (nsec3_rr && 12757b5038d7SDag-Erling Smørgrav (ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3 || 12767b5038d7SDag-Erling Smørgrav ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3PARAM) 12777b5038d7SDag-Erling Smørgrav ) { 12787b5038d7SDag-Erling Smørgrav return ldns_rr_rdf(nsec3_rr, 3); 12797b5038d7SDag-Erling Smørgrav } 12807b5038d7SDag-Erling Smørgrav return NULL; 12817b5038d7SDag-Erling Smørgrav } 12827b5038d7SDag-Erling Smørgrav 12837b5038d7SDag-Erling Smørgrav uint8_t 12847b5038d7SDag-Erling Smørgrav ldns_nsec3_salt_length(const ldns_rr *nsec3_rr) 12857b5038d7SDag-Erling Smørgrav { 12867b5038d7SDag-Erling Smørgrav ldns_rdf *salt_rdf = ldns_nsec3_salt(nsec3_rr); 12877b5038d7SDag-Erling Smørgrav if (salt_rdf && ldns_rdf_size(salt_rdf) > 0) { 12887b5038d7SDag-Erling Smørgrav return (uint8_t) ldns_rdf_data(salt_rdf)[0]; 12897b5038d7SDag-Erling Smørgrav } 12907b5038d7SDag-Erling Smørgrav return 0; 12917b5038d7SDag-Erling Smørgrav } 12927b5038d7SDag-Erling Smørgrav 12937b5038d7SDag-Erling Smørgrav /* allocs data, free with LDNS_FREE() */ 12947b5038d7SDag-Erling Smørgrav uint8_t * 12957b5038d7SDag-Erling Smørgrav ldns_nsec3_salt_data(const ldns_rr *nsec3_rr) 12967b5038d7SDag-Erling Smørgrav { 12977b5038d7SDag-Erling Smørgrav uint8_t salt_length; 12987b5038d7SDag-Erling Smørgrav uint8_t *salt; 12997b5038d7SDag-Erling Smørgrav 13007b5038d7SDag-Erling Smørgrav ldns_rdf *salt_rdf = ldns_nsec3_salt(nsec3_rr); 13017b5038d7SDag-Erling Smørgrav if (salt_rdf && ldns_rdf_size(salt_rdf) > 0) { 13027b5038d7SDag-Erling Smørgrav salt_length = ldns_rdf_data(salt_rdf)[0]; 13037b5038d7SDag-Erling Smørgrav salt = LDNS_XMALLOC(uint8_t, salt_length); 13047b5038d7SDag-Erling Smørgrav if(!salt) return NULL; 13057b5038d7SDag-Erling Smørgrav memcpy(salt, &ldns_rdf_data(salt_rdf)[1], salt_length); 13067b5038d7SDag-Erling Smørgrav return salt; 13077b5038d7SDag-Erling Smørgrav } 13087b5038d7SDag-Erling Smørgrav return NULL; 13097b5038d7SDag-Erling Smørgrav } 13107b5038d7SDag-Erling Smørgrav 13117b5038d7SDag-Erling Smørgrav ldns_rdf * 13127b5038d7SDag-Erling Smørgrav ldns_nsec3_next_owner(const ldns_rr *nsec3_rr) 13137b5038d7SDag-Erling Smørgrav { 13147b5038d7SDag-Erling Smørgrav if (!nsec3_rr || ldns_rr_get_type(nsec3_rr) != LDNS_RR_TYPE_NSEC3) { 13157b5038d7SDag-Erling Smørgrav return NULL; 13167b5038d7SDag-Erling Smørgrav } else { 13177b5038d7SDag-Erling Smørgrav return ldns_rr_rdf(nsec3_rr, 4); 13187b5038d7SDag-Erling Smørgrav } 13197b5038d7SDag-Erling Smørgrav } 13207b5038d7SDag-Erling Smørgrav 13217b5038d7SDag-Erling Smørgrav ldns_rdf * 13227b5038d7SDag-Erling Smørgrav ldns_nsec3_bitmap(const ldns_rr *nsec3_rr) 13237b5038d7SDag-Erling Smørgrav { 13247b5038d7SDag-Erling Smørgrav if (!nsec3_rr || ldns_rr_get_type(nsec3_rr) != LDNS_RR_TYPE_NSEC3) { 13257b5038d7SDag-Erling Smørgrav return NULL; 13267b5038d7SDag-Erling Smørgrav } else { 13277b5038d7SDag-Erling Smørgrav return ldns_rr_rdf(nsec3_rr, 5); 13287b5038d7SDag-Erling Smørgrav } 13297b5038d7SDag-Erling Smørgrav } 13307b5038d7SDag-Erling Smørgrav 13317b5038d7SDag-Erling Smørgrav ldns_rdf * 13327b5038d7SDag-Erling Smørgrav ldns_nsec3_hash_name_frm_nsec3(const ldns_rr *nsec, ldns_rdf *name) 13337b5038d7SDag-Erling Smørgrav { 13347b5038d7SDag-Erling Smørgrav uint8_t algorithm; 13357b5038d7SDag-Erling Smørgrav uint16_t iterations; 13367b5038d7SDag-Erling Smørgrav uint8_t salt_length; 13377b5038d7SDag-Erling Smørgrav uint8_t *salt = 0; 13387b5038d7SDag-Erling Smørgrav 13397b5038d7SDag-Erling Smørgrav ldns_rdf *hashed_owner; 13407b5038d7SDag-Erling Smørgrav 13417b5038d7SDag-Erling Smørgrav algorithm = ldns_nsec3_algorithm(nsec); 13427b5038d7SDag-Erling Smørgrav salt_length = ldns_nsec3_salt_length(nsec); 13437b5038d7SDag-Erling Smørgrav salt = ldns_nsec3_salt_data(nsec); 13447b5038d7SDag-Erling Smørgrav iterations = ldns_nsec3_iterations(nsec); 13457b5038d7SDag-Erling Smørgrav 13467b5038d7SDag-Erling Smørgrav hashed_owner = ldns_nsec3_hash_name(name, 13477b5038d7SDag-Erling Smørgrav algorithm, 13487b5038d7SDag-Erling Smørgrav iterations, 13497b5038d7SDag-Erling Smørgrav salt_length, 13507b5038d7SDag-Erling Smørgrav salt); 13517b5038d7SDag-Erling Smørgrav 13527b5038d7SDag-Erling Smørgrav LDNS_FREE(salt); 13537b5038d7SDag-Erling Smørgrav return hashed_owner; 13547b5038d7SDag-Erling Smørgrav } 13557b5038d7SDag-Erling Smørgrav 13567b5038d7SDag-Erling Smørgrav bool 1357*17d15b25SDag-Erling Smørgrav ldns_nsec_bitmap_covers_type(const ldns_rdf* bitmap, ldns_rr_type type) 13587b5038d7SDag-Erling Smørgrav { 1359*17d15b25SDag-Erling Smørgrav uint8_t* dptr; 1360*17d15b25SDag-Erling Smørgrav uint8_t* dend; 13617b5038d7SDag-Erling Smørgrav 1362*17d15b25SDag-Erling Smørgrav /* From RFC3845 Section 2.1.2: 1363*17d15b25SDag-Erling Smørgrav * 1364*17d15b25SDag-Erling Smørgrav * "The RR type space is split into 256 window blocks, each re- 1365*17d15b25SDag-Erling Smørgrav * presenting the low-order 8 bits of the 16-bit RR type space." 1366*17d15b25SDag-Erling Smørgrav */ 1367*17d15b25SDag-Erling Smørgrav uint8_t window = type >> 8; 1368*17d15b25SDag-Erling Smørgrav uint8_t subtype = type & 0xff; 1369*17d15b25SDag-Erling Smørgrav 1370*17d15b25SDag-Erling Smørgrav if (! bitmap) { 13717b5038d7SDag-Erling Smørgrav return false; 13727b5038d7SDag-Erling Smørgrav } 1373*17d15b25SDag-Erling Smørgrav assert(ldns_rdf_get_type(bitmap) == LDNS_RDF_TYPE_BITMAP); 13747b5038d7SDag-Erling Smørgrav 1375*17d15b25SDag-Erling Smørgrav dptr = ldns_rdf_data(bitmap); 1376*17d15b25SDag-Erling Smørgrav dend = ldns_rdf_data(bitmap) + ldns_rdf_size(bitmap); 13777b5038d7SDag-Erling Smørgrav 1378*17d15b25SDag-Erling Smørgrav /* Type Bitmap = ( Window Block # | Bitmap Length | Bitmap ) + 1379*17d15b25SDag-Erling Smørgrav * dptr[0] dptr[1] dptr[2:] 1380*17d15b25SDag-Erling Smørgrav */ 1381*17d15b25SDag-Erling Smørgrav while (dptr < dend && dptr[0] <= window) { 1382*17d15b25SDag-Erling Smørgrav 1383*17d15b25SDag-Erling Smørgrav if (dptr[0] == window && subtype / 8 < dptr[1] && 1384*17d15b25SDag-Erling Smørgrav dptr + dptr[1] + 2 <= dend) { 1385*17d15b25SDag-Erling Smørgrav 1386*17d15b25SDag-Erling Smørgrav return dptr[2 + subtype / 8] & (0x80 >> (subtype % 8)); 1387*17d15b25SDag-Erling Smørgrav } 1388*17d15b25SDag-Erling Smørgrav dptr += dptr[1] + 2; /* next window */ 13897b5038d7SDag-Erling Smørgrav } 13907b5038d7SDag-Erling Smørgrav return false; 13917b5038d7SDag-Erling Smørgrav } 13927b5038d7SDag-Erling Smørgrav 1393*17d15b25SDag-Erling Smørgrav ldns_status 1394*17d15b25SDag-Erling Smørgrav ldns_nsec_bitmap_set_type(ldns_rdf* bitmap, ldns_rr_type type) 1395*17d15b25SDag-Erling Smørgrav { 1396*17d15b25SDag-Erling Smørgrav uint8_t* dptr; 1397*17d15b25SDag-Erling Smørgrav uint8_t* dend; 1398*17d15b25SDag-Erling Smørgrav 1399*17d15b25SDag-Erling Smørgrav /* From RFC3845 Section 2.1.2: 1400*17d15b25SDag-Erling Smørgrav * 1401*17d15b25SDag-Erling Smørgrav * "The RR type space is split into 256 window blocks, each re- 1402*17d15b25SDag-Erling Smørgrav * presenting the low-order 8 bits of the 16-bit RR type space." 1403*17d15b25SDag-Erling Smørgrav */ 1404*17d15b25SDag-Erling Smørgrav uint8_t window = type >> 8; 1405*17d15b25SDag-Erling Smørgrav uint8_t subtype = type & 0xff; 1406*17d15b25SDag-Erling Smørgrav 1407*17d15b25SDag-Erling Smørgrav if (! bitmap) { 1408*17d15b25SDag-Erling Smørgrav return false; 1409*17d15b25SDag-Erling Smørgrav } 1410*17d15b25SDag-Erling Smørgrav assert(ldns_rdf_get_type(bitmap) == LDNS_RDF_TYPE_BITMAP); 1411*17d15b25SDag-Erling Smørgrav 1412*17d15b25SDag-Erling Smørgrav dptr = ldns_rdf_data(bitmap); 1413*17d15b25SDag-Erling Smørgrav dend = ldns_rdf_data(bitmap) + ldns_rdf_size(bitmap); 1414*17d15b25SDag-Erling Smørgrav 1415*17d15b25SDag-Erling Smørgrav /* Type Bitmap = ( Window Block # | Bitmap Length | Bitmap ) + 1416*17d15b25SDag-Erling Smørgrav * dptr[0] dptr[1] dptr[2:] 1417*17d15b25SDag-Erling Smørgrav */ 1418*17d15b25SDag-Erling Smørgrav while (dptr < dend && dptr[0] <= window) { 1419*17d15b25SDag-Erling Smørgrav 1420*17d15b25SDag-Erling Smørgrav if (dptr[0] == window && subtype / 8 < dptr[1] && 1421*17d15b25SDag-Erling Smørgrav dptr + dptr[1] + 2 <= dend) { 1422*17d15b25SDag-Erling Smørgrav 1423*17d15b25SDag-Erling Smørgrav dptr[2 + subtype / 8] |= (0x80 >> (subtype % 8)); 1424*17d15b25SDag-Erling Smørgrav return LDNS_STATUS_OK; 1425*17d15b25SDag-Erling Smørgrav } 1426*17d15b25SDag-Erling Smørgrav dptr += dptr[1] + 2; /* next window */ 1427*17d15b25SDag-Erling Smørgrav } 1428*17d15b25SDag-Erling Smørgrav return LDNS_STATUS_TYPE_NOT_IN_BITMAP; 1429*17d15b25SDag-Erling Smørgrav } 1430*17d15b25SDag-Erling Smørgrav 1431*17d15b25SDag-Erling Smørgrav ldns_status 1432*17d15b25SDag-Erling Smørgrav ldns_nsec_bitmap_clear_type(ldns_rdf* bitmap, ldns_rr_type type) 1433*17d15b25SDag-Erling Smørgrav { 1434*17d15b25SDag-Erling Smørgrav uint8_t* dptr; 1435*17d15b25SDag-Erling Smørgrav uint8_t* dend; 1436*17d15b25SDag-Erling Smørgrav 1437*17d15b25SDag-Erling Smørgrav /* From RFC3845 Section 2.1.2: 1438*17d15b25SDag-Erling Smørgrav * 1439*17d15b25SDag-Erling Smørgrav * "The RR type space is split into 256 window blocks, each re- 1440*17d15b25SDag-Erling Smørgrav * presenting the low-order 8 bits of the 16-bit RR type space." 1441*17d15b25SDag-Erling Smørgrav */ 1442*17d15b25SDag-Erling Smørgrav uint8_t window = type >> 8; 1443*17d15b25SDag-Erling Smørgrav uint8_t subtype = type & 0xff; 1444*17d15b25SDag-Erling Smørgrav 1445*17d15b25SDag-Erling Smørgrav if (! bitmap) { 1446*17d15b25SDag-Erling Smørgrav return false; 1447*17d15b25SDag-Erling Smørgrav } 1448*17d15b25SDag-Erling Smørgrav 1449*17d15b25SDag-Erling Smørgrav assert(ldns_rdf_get_type(bitmap) == LDNS_RDF_TYPE_BITMAP); 1450*17d15b25SDag-Erling Smørgrav 1451*17d15b25SDag-Erling Smørgrav dptr = ldns_rdf_data(bitmap); 1452*17d15b25SDag-Erling Smørgrav dend = ldns_rdf_data(bitmap) + ldns_rdf_size(bitmap); 1453*17d15b25SDag-Erling Smørgrav 1454*17d15b25SDag-Erling Smørgrav /* Type Bitmap = ( Window Block # | Bitmap Length | Bitmap ) + 1455*17d15b25SDag-Erling Smørgrav * dptr[0] dptr[1] dptr[2:] 1456*17d15b25SDag-Erling Smørgrav */ 1457*17d15b25SDag-Erling Smørgrav while (dptr < dend && dptr[0] <= window) { 1458*17d15b25SDag-Erling Smørgrav 1459*17d15b25SDag-Erling Smørgrav if (dptr[0] == window && subtype / 8 < dptr[1] && 1460*17d15b25SDag-Erling Smørgrav dptr + dptr[1] + 2 <= dend) { 1461*17d15b25SDag-Erling Smørgrav 1462*17d15b25SDag-Erling Smørgrav dptr[2 + subtype / 8] &= ~(0x80 >> (subtype % 8)); 1463*17d15b25SDag-Erling Smørgrav return LDNS_STATUS_OK; 1464*17d15b25SDag-Erling Smørgrav } 1465*17d15b25SDag-Erling Smørgrav dptr += dptr[1] + 2; /* next window */ 1466*17d15b25SDag-Erling Smørgrav } 1467*17d15b25SDag-Erling Smørgrav return LDNS_STATUS_TYPE_NOT_IN_BITMAP; 1468*17d15b25SDag-Erling Smørgrav } 1469*17d15b25SDag-Erling Smørgrav 1470*17d15b25SDag-Erling Smørgrav 14717b5038d7SDag-Erling Smørgrav bool 14727b5038d7SDag-Erling Smørgrav ldns_nsec_covers_name(const ldns_rr *nsec, const ldns_rdf *name) 14737b5038d7SDag-Erling Smørgrav { 14747b5038d7SDag-Erling Smørgrav ldns_rdf *nsec_owner = ldns_rr_owner(nsec); 14757b5038d7SDag-Erling Smørgrav ldns_rdf *hash_next; 14767b5038d7SDag-Erling Smørgrav char *next_hash_str; 14777b5038d7SDag-Erling Smørgrav ldns_rdf *nsec_next = NULL; 14787b5038d7SDag-Erling Smørgrav ldns_status status; 14797b5038d7SDag-Erling Smørgrav ldns_rdf *chopped_dname; 14807b5038d7SDag-Erling Smørgrav bool result; 14817b5038d7SDag-Erling Smørgrav 14827b5038d7SDag-Erling Smørgrav if (ldns_rr_get_type(nsec) == LDNS_RR_TYPE_NSEC) { 14837b5038d7SDag-Erling Smørgrav if (ldns_rr_rdf(nsec, 0) != NULL) { 14847b5038d7SDag-Erling Smørgrav nsec_next = ldns_rdf_clone(ldns_rr_rdf(nsec, 0)); 14857b5038d7SDag-Erling Smørgrav } else { 14867b5038d7SDag-Erling Smørgrav return false; 14877b5038d7SDag-Erling Smørgrav } 14887b5038d7SDag-Erling Smørgrav } else if (ldns_rr_get_type(nsec) == LDNS_RR_TYPE_NSEC3) { 14897b5038d7SDag-Erling Smørgrav hash_next = ldns_nsec3_next_owner(nsec); 14907b5038d7SDag-Erling Smørgrav next_hash_str = ldns_rdf2str(hash_next); 14917b5038d7SDag-Erling Smørgrav nsec_next = ldns_dname_new_frm_str(next_hash_str); 14927b5038d7SDag-Erling Smørgrav LDNS_FREE(next_hash_str); 14937b5038d7SDag-Erling Smørgrav chopped_dname = ldns_dname_left_chop(nsec_owner); 14947b5038d7SDag-Erling Smørgrav status = ldns_dname_cat(nsec_next, chopped_dname); 14957b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(chopped_dname); 14967b5038d7SDag-Erling Smørgrav if (status != LDNS_STATUS_OK) { 14977b5038d7SDag-Erling Smørgrav printf("error catting: %s\n", ldns_get_errorstr_by_id(status)); 14987b5038d7SDag-Erling Smørgrav } 14997b5038d7SDag-Erling Smørgrav } else { 15007b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(nsec_next); 15017b5038d7SDag-Erling Smørgrav return false; 15027b5038d7SDag-Erling Smørgrav } 15037b5038d7SDag-Erling Smørgrav 15047b5038d7SDag-Erling Smørgrav /* in the case of the last nsec */ 15057b5038d7SDag-Erling Smørgrav if(ldns_dname_compare(nsec_owner, nsec_next) > 0) { 15067b5038d7SDag-Erling Smørgrav result = (ldns_dname_compare(nsec_owner, name) <= 0 || 15077b5038d7SDag-Erling Smørgrav ldns_dname_compare(name, nsec_next) < 0); 1508*17d15b25SDag-Erling Smørgrav } else if(ldns_dname_compare(nsec_owner, nsec_next) < 0) { 15097b5038d7SDag-Erling Smørgrav result = (ldns_dname_compare(nsec_owner, name) <= 0 && 15107b5038d7SDag-Erling Smørgrav ldns_dname_compare(name, nsec_next) < 0); 1511*17d15b25SDag-Erling Smørgrav } else { 1512*17d15b25SDag-Erling Smørgrav result = true; 15137b5038d7SDag-Erling Smørgrav } 15147b5038d7SDag-Erling Smørgrav 15157b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(nsec_next); 15167b5038d7SDag-Erling Smørgrav return result; 15177b5038d7SDag-Erling Smørgrav } 15187b5038d7SDag-Erling Smørgrav 15197b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL 15207b5038d7SDag-Erling Smørgrav /* sig may be null - if so look in the packet */ 15217b5038d7SDag-Erling Smørgrav 15227b5038d7SDag-Erling Smørgrav ldns_status 15237b5038d7SDag-Erling Smørgrav ldns_pkt_verify_time(ldns_pkt *p, ldns_rr_type t, ldns_rdf *o, 15247b5038d7SDag-Erling Smørgrav ldns_rr_list *k, ldns_rr_list *s, 15257b5038d7SDag-Erling Smørgrav time_t check_time, ldns_rr_list *good_keys) 15267b5038d7SDag-Erling Smørgrav { 15277b5038d7SDag-Erling Smørgrav ldns_rr_list *rrset; 15287b5038d7SDag-Erling Smørgrav ldns_rr_list *sigs; 15297b5038d7SDag-Erling Smørgrav ldns_rr_list *sigs_covered; 15307b5038d7SDag-Erling Smørgrav ldns_rdf *rdf_t; 15317b5038d7SDag-Erling Smørgrav ldns_rr_type t_netorder; 15327b5038d7SDag-Erling Smørgrav 15337b5038d7SDag-Erling Smørgrav if (!k) { 15347b5038d7SDag-Erling Smørgrav return LDNS_STATUS_ERR; 15357b5038d7SDag-Erling Smørgrav /* return LDNS_STATUS_CRYPTO_NO_DNSKEY; */ 15367b5038d7SDag-Erling Smørgrav } 15377b5038d7SDag-Erling Smørgrav 15387b5038d7SDag-Erling Smørgrav if (t == LDNS_RR_TYPE_RRSIG) { 15397b5038d7SDag-Erling Smørgrav /* we don't have RRSIG(RRSIG) (yet? ;-) ) */ 15407b5038d7SDag-Erling Smørgrav return LDNS_STATUS_ERR; 15417b5038d7SDag-Erling Smørgrav } 15427b5038d7SDag-Erling Smørgrav 15437b5038d7SDag-Erling Smørgrav if (s) { 15447b5038d7SDag-Erling Smørgrav /* if s is not NULL, the sigs are given to use */ 15457b5038d7SDag-Erling Smørgrav sigs = s; 15467b5038d7SDag-Erling Smørgrav } else { 15477b5038d7SDag-Erling Smørgrav /* otherwise get them from the packet */ 15482787e39aSDag-Erling Smørgrav sigs = ldns_pkt_rr_list_by_name_and_type(p, o, 15492787e39aSDag-Erling Smørgrav LDNS_RR_TYPE_RRSIG, 15507b5038d7SDag-Erling Smørgrav LDNS_SECTION_ANY_NOQUESTION); 15517b5038d7SDag-Erling Smørgrav if (!sigs) { 15527b5038d7SDag-Erling Smørgrav /* no sigs */ 15537b5038d7SDag-Erling Smørgrav return LDNS_STATUS_ERR; 15547b5038d7SDag-Erling Smørgrav /* return LDNS_STATUS_CRYPTO_NO_RRSIG; */ 15557b5038d7SDag-Erling Smørgrav } 15567b5038d7SDag-Erling Smørgrav } 15577b5038d7SDag-Erling Smørgrav 15587b5038d7SDag-Erling Smørgrav /* rrsig are subtyped, so now we need to find the correct 15597b5038d7SDag-Erling Smørgrav * sigs for the type t 15607b5038d7SDag-Erling Smørgrav */ 15617b5038d7SDag-Erling Smørgrav t_netorder = htons(t); /* rdf are in network order! */ 15627b5038d7SDag-Erling Smørgrav /* a type identifier is a 16-bit number, so the size is 2 bytes */ 15632787e39aSDag-Erling Smørgrav rdf_t = ldns_rdf_new(LDNS_RDF_TYPE_TYPE, 2, &t_netorder); 15642787e39aSDag-Erling Smørgrav 15657b5038d7SDag-Erling Smørgrav sigs_covered = ldns_rr_list_subtype_by_rdf(sigs, rdf_t, 0); 15662787e39aSDag-Erling Smørgrav ldns_rdf_free(rdf_t); 15677b5038d7SDag-Erling Smørgrav if (! sigs_covered) { 15682787e39aSDag-Erling Smørgrav if (! s) { 15692787e39aSDag-Erling Smørgrav ldns_rr_list_deep_free(sigs); 15702787e39aSDag-Erling Smørgrav } 15717b5038d7SDag-Erling Smørgrav return LDNS_STATUS_ERR; 15727b5038d7SDag-Erling Smørgrav } 15732787e39aSDag-Erling Smørgrav ldns_rr_list_deep_free(sigs_covered); 15747b5038d7SDag-Erling Smørgrav 15752787e39aSDag-Erling Smørgrav rrset = ldns_pkt_rr_list_by_name_and_type(p, o, t, 15762787e39aSDag-Erling Smørgrav LDNS_SECTION_ANY_NOQUESTION); 15772787e39aSDag-Erling Smørgrav if (!rrset) { 15782787e39aSDag-Erling Smørgrav if (! s) { 15792787e39aSDag-Erling Smørgrav ldns_rr_list_deep_free(sigs); 15802787e39aSDag-Erling Smørgrav } 15812787e39aSDag-Erling Smørgrav return LDNS_STATUS_ERR; 15822787e39aSDag-Erling Smørgrav } 15837b5038d7SDag-Erling Smørgrav return ldns_verify_time(rrset, sigs, k, check_time, good_keys); 15847b5038d7SDag-Erling Smørgrav } 15857b5038d7SDag-Erling Smørgrav 15867b5038d7SDag-Erling Smørgrav ldns_status 15877b5038d7SDag-Erling Smørgrav ldns_pkt_verify(ldns_pkt *p, ldns_rr_type t, ldns_rdf *o, 15887b5038d7SDag-Erling Smørgrav ldns_rr_list *k, ldns_rr_list *s, ldns_rr_list *good_keys) 15897b5038d7SDag-Erling Smørgrav { 15907b5038d7SDag-Erling Smørgrav return ldns_pkt_verify_time(p, t, o, k, s, ldns_time(NULL), good_keys); 15917b5038d7SDag-Erling Smørgrav } 15927b5038d7SDag-Erling Smørgrav #endif /* HAVE_SSL */ 15937b5038d7SDag-Erling Smørgrav 15947b5038d7SDag-Erling Smørgrav ldns_status 15957b5038d7SDag-Erling Smørgrav ldns_dnssec_chain_nsec3_list(ldns_rr_list *nsec3_rrs) 15967b5038d7SDag-Erling Smørgrav { 15977b5038d7SDag-Erling Smørgrav size_t i; 15987b5038d7SDag-Erling Smørgrav char *next_nsec_owner_str; 15997b5038d7SDag-Erling Smørgrav ldns_rdf *next_nsec_owner_label; 16007b5038d7SDag-Erling Smørgrav ldns_rdf *next_nsec_rdf; 16017b5038d7SDag-Erling Smørgrav ldns_status status = LDNS_STATUS_OK; 16027b5038d7SDag-Erling Smørgrav 16037b5038d7SDag-Erling Smørgrav for (i = 0; i < ldns_rr_list_rr_count(nsec3_rrs); i++) { 16047b5038d7SDag-Erling Smørgrav if (i == ldns_rr_list_rr_count(nsec3_rrs) - 1) { 16057b5038d7SDag-Erling Smørgrav next_nsec_owner_label = 16067b5038d7SDag-Erling Smørgrav ldns_dname_label(ldns_rr_owner(ldns_rr_list_rr(nsec3_rrs, 16077b5038d7SDag-Erling Smørgrav 0)), 0); 16087b5038d7SDag-Erling Smørgrav next_nsec_owner_str = ldns_rdf2str(next_nsec_owner_label); 16097b5038d7SDag-Erling Smørgrav if (next_nsec_owner_str[strlen(next_nsec_owner_str) - 1] 16107b5038d7SDag-Erling Smørgrav == '.') { 16117b5038d7SDag-Erling Smørgrav next_nsec_owner_str[strlen(next_nsec_owner_str) - 1] 16127b5038d7SDag-Erling Smørgrav = '\0'; 16137b5038d7SDag-Erling Smørgrav } 16147b5038d7SDag-Erling Smørgrav status = ldns_str2rdf_b32_ext(&next_nsec_rdf, 16157b5038d7SDag-Erling Smørgrav next_nsec_owner_str); 16167b5038d7SDag-Erling Smørgrav if (!ldns_rr_set_rdf(ldns_rr_list_rr(nsec3_rrs, i), 16177b5038d7SDag-Erling Smørgrav next_nsec_rdf, 4)) { 16187b5038d7SDag-Erling Smørgrav /* todo: error */ 16197b5038d7SDag-Erling Smørgrav } 16207b5038d7SDag-Erling Smørgrav 16217b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(next_nsec_owner_label); 16227b5038d7SDag-Erling Smørgrav LDNS_FREE(next_nsec_owner_str); 16237b5038d7SDag-Erling Smørgrav } else { 16247b5038d7SDag-Erling Smørgrav next_nsec_owner_label = 16257b5038d7SDag-Erling Smørgrav ldns_dname_label(ldns_rr_owner(ldns_rr_list_rr(nsec3_rrs, 16267b5038d7SDag-Erling Smørgrav i + 1)), 16277b5038d7SDag-Erling Smørgrav 0); 16287b5038d7SDag-Erling Smørgrav next_nsec_owner_str = ldns_rdf2str(next_nsec_owner_label); 16297b5038d7SDag-Erling Smørgrav if (next_nsec_owner_str[strlen(next_nsec_owner_str) - 1] 16307b5038d7SDag-Erling Smørgrav == '.') { 16317b5038d7SDag-Erling Smørgrav next_nsec_owner_str[strlen(next_nsec_owner_str) - 1] 16327b5038d7SDag-Erling Smørgrav = '\0'; 16337b5038d7SDag-Erling Smørgrav } 16347b5038d7SDag-Erling Smørgrav status = ldns_str2rdf_b32_ext(&next_nsec_rdf, 16357b5038d7SDag-Erling Smørgrav next_nsec_owner_str); 16367b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(next_nsec_owner_label); 16377b5038d7SDag-Erling Smørgrav LDNS_FREE(next_nsec_owner_str); 16387b5038d7SDag-Erling Smørgrav if (!ldns_rr_set_rdf(ldns_rr_list_rr(nsec3_rrs, i), 16397b5038d7SDag-Erling Smørgrav next_nsec_rdf, 4)) { 16407b5038d7SDag-Erling Smørgrav /* todo: error */ 16417b5038d7SDag-Erling Smørgrav } 16427b5038d7SDag-Erling Smørgrav } 16437b5038d7SDag-Erling Smørgrav } 16447b5038d7SDag-Erling Smørgrav return status; 16457b5038d7SDag-Erling Smørgrav } 16467b5038d7SDag-Erling Smørgrav 16477b5038d7SDag-Erling Smørgrav int 16487b5038d7SDag-Erling Smørgrav qsort_rr_compare_nsec3(const void *a, const void *b) 16497b5038d7SDag-Erling Smørgrav { 16507b5038d7SDag-Erling Smørgrav const ldns_rr *rr1 = * (const ldns_rr **) a; 16517b5038d7SDag-Erling Smørgrav const ldns_rr *rr2 = * (const ldns_rr **) b; 16527b5038d7SDag-Erling Smørgrav if (rr1 == NULL && rr2 == NULL) { 16537b5038d7SDag-Erling Smørgrav return 0; 16547b5038d7SDag-Erling Smørgrav } 16557b5038d7SDag-Erling Smørgrav if (rr1 == NULL) { 16567b5038d7SDag-Erling Smørgrav return -1; 16577b5038d7SDag-Erling Smørgrav } 16587b5038d7SDag-Erling Smørgrav if (rr2 == NULL) { 16597b5038d7SDag-Erling Smørgrav return 1; 16607b5038d7SDag-Erling Smørgrav } 16617b5038d7SDag-Erling Smørgrav return ldns_rdf_compare(ldns_rr_owner(rr1), ldns_rr_owner(rr2)); 16627b5038d7SDag-Erling Smørgrav } 16637b5038d7SDag-Erling Smørgrav 16647b5038d7SDag-Erling Smørgrav void 16657b5038d7SDag-Erling Smørgrav ldns_rr_list_sort_nsec3(ldns_rr_list *unsorted) 16667b5038d7SDag-Erling Smørgrav { 16677b5038d7SDag-Erling Smørgrav qsort(unsorted->_rrs, 16687b5038d7SDag-Erling Smørgrav ldns_rr_list_rr_count(unsorted), 16697b5038d7SDag-Erling Smørgrav sizeof(ldns_rr *), 16707b5038d7SDag-Erling Smørgrav qsort_rr_compare_nsec3); 16717b5038d7SDag-Erling Smørgrav } 16727b5038d7SDag-Erling Smørgrav 16737b5038d7SDag-Erling Smørgrav int 16747b5038d7SDag-Erling Smørgrav ldns_dnssec_default_add_to_signatures( ATTR_UNUSED(ldns_rr *sig) 16757b5038d7SDag-Erling Smørgrav , ATTR_UNUSED(void *n) 16767b5038d7SDag-Erling Smørgrav ) 16777b5038d7SDag-Erling Smørgrav { 16787b5038d7SDag-Erling Smørgrav return LDNS_SIGNATURE_LEAVE_ADD_NEW; 16797b5038d7SDag-Erling Smørgrav } 16807b5038d7SDag-Erling Smørgrav 16817b5038d7SDag-Erling Smørgrav int 16827b5038d7SDag-Erling Smørgrav ldns_dnssec_default_leave_signatures( ATTR_UNUSED(ldns_rr *sig) 16837b5038d7SDag-Erling Smørgrav , ATTR_UNUSED(void *n) 16847b5038d7SDag-Erling Smørgrav ) 16857b5038d7SDag-Erling Smørgrav { 16867b5038d7SDag-Erling Smørgrav return LDNS_SIGNATURE_LEAVE_NO_ADD; 16877b5038d7SDag-Erling Smørgrav } 16887b5038d7SDag-Erling Smørgrav 16897b5038d7SDag-Erling Smørgrav int 16907b5038d7SDag-Erling Smørgrav ldns_dnssec_default_delete_signatures( ATTR_UNUSED(ldns_rr *sig) 16917b5038d7SDag-Erling Smørgrav , ATTR_UNUSED(void *n) 16927b5038d7SDag-Erling Smørgrav ) 16937b5038d7SDag-Erling Smørgrav { 16947b5038d7SDag-Erling Smørgrav return LDNS_SIGNATURE_REMOVE_NO_ADD; 16957b5038d7SDag-Erling Smørgrav } 16967b5038d7SDag-Erling Smørgrav 16977b5038d7SDag-Erling Smørgrav int 16987b5038d7SDag-Erling Smørgrav ldns_dnssec_default_replace_signatures( ATTR_UNUSED(ldns_rr *sig) 16997b5038d7SDag-Erling Smørgrav , ATTR_UNUSED(void *n) 17007b5038d7SDag-Erling Smørgrav ) 17017b5038d7SDag-Erling Smørgrav { 17027b5038d7SDag-Erling Smørgrav return LDNS_SIGNATURE_REMOVE_ADD_NEW; 17037b5038d7SDag-Erling Smørgrav } 17047b5038d7SDag-Erling Smørgrav 17057b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL 17067b5038d7SDag-Erling Smørgrav ldns_rdf * 17077b5038d7SDag-Erling Smørgrav ldns_convert_dsa_rrsig_asn12rdf(const ldns_buffer *sig, 17087b5038d7SDag-Erling Smørgrav const long sig_len) 17097b5038d7SDag-Erling Smørgrav { 17107b5038d7SDag-Erling Smørgrav ldns_rdf *sigdata_rdf; 17117b5038d7SDag-Erling Smørgrav DSA_SIG *dsasig; 17127b5038d7SDag-Erling Smørgrav unsigned char *dsasig_data = (unsigned char*)ldns_buffer_begin(sig); 17137b5038d7SDag-Erling Smørgrav size_t byte_offset; 17147b5038d7SDag-Erling Smørgrav 17157b5038d7SDag-Erling Smørgrav dsasig = d2i_DSA_SIG(NULL, 17167b5038d7SDag-Erling Smørgrav (const unsigned char **)&dsasig_data, 17177b5038d7SDag-Erling Smørgrav sig_len); 17187b5038d7SDag-Erling Smørgrav if (!dsasig) { 17197b5038d7SDag-Erling Smørgrav DSA_SIG_free(dsasig); 17207b5038d7SDag-Erling Smørgrav return NULL; 17217b5038d7SDag-Erling Smørgrav } 17227b5038d7SDag-Erling Smørgrav 17237b5038d7SDag-Erling Smørgrav dsasig_data = LDNS_XMALLOC(unsigned char, 41); 17247b5038d7SDag-Erling Smørgrav if(!dsasig_data) { 17257b5038d7SDag-Erling Smørgrav DSA_SIG_free(dsasig); 17267b5038d7SDag-Erling Smørgrav return NULL; 17277b5038d7SDag-Erling Smørgrav } 17287b5038d7SDag-Erling Smørgrav dsasig_data[0] = 0; 17297b5038d7SDag-Erling Smørgrav byte_offset = (size_t) (20 - BN_num_bytes(dsasig->r)); 17307b5038d7SDag-Erling Smørgrav if (byte_offset > 20) { 17317b5038d7SDag-Erling Smørgrav DSA_SIG_free(dsasig); 17327b5038d7SDag-Erling Smørgrav LDNS_FREE(dsasig_data); 17337b5038d7SDag-Erling Smørgrav return NULL; 17347b5038d7SDag-Erling Smørgrav } 17357b5038d7SDag-Erling Smørgrav memset(&dsasig_data[1], 0, byte_offset); 17367b5038d7SDag-Erling Smørgrav BN_bn2bin(dsasig->r, &dsasig_data[1 + byte_offset]); 17377b5038d7SDag-Erling Smørgrav byte_offset = (size_t) (20 - BN_num_bytes(dsasig->s)); 17387b5038d7SDag-Erling Smørgrav if (byte_offset > 20) { 17397b5038d7SDag-Erling Smørgrav DSA_SIG_free(dsasig); 17407b5038d7SDag-Erling Smørgrav LDNS_FREE(dsasig_data); 17417b5038d7SDag-Erling Smørgrav return NULL; 17427b5038d7SDag-Erling Smørgrav } 17437b5038d7SDag-Erling Smørgrav memset(&dsasig_data[21], 0, byte_offset); 17447b5038d7SDag-Erling Smørgrav BN_bn2bin(dsasig->s, &dsasig_data[21 + byte_offset]); 17457b5038d7SDag-Erling Smørgrav 17467b5038d7SDag-Erling Smørgrav sigdata_rdf = ldns_rdf_new(LDNS_RDF_TYPE_B64, 41, dsasig_data); 17477b5038d7SDag-Erling Smørgrav if(!sigdata_rdf) { 17487b5038d7SDag-Erling Smørgrav LDNS_FREE(dsasig_data); 17497b5038d7SDag-Erling Smørgrav } 17507b5038d7SDag-Erling Smørgrav DSA_SIG_free(dsasig); 17517b5038d7SDag-Erling Smørgrav 17527b5038d7SDag-Erling Smørgrav return sigdata_rdf; 17537b5038d7SDag-Erling Smørgrav } 17547b5038d7SDag-Erling Smørgrav 17557b5038d7SDag-Erling Smørgrav ldns_status 17567b5038d7SDag-Erling Smørgrav ldns_convert_dsa_rrsig_rdf2asn1(ldns_buffer *target_buffer, 17577b5038d7SDag-Erling Smørgrav const ldns_rdf *sig_rdf) 17587b5038d7SDag-Erling Smørgrav { 17597b5038d7SDag-Erling Smørgrav /* the EVP api wants the DER encoding of the signature... */ 17607b5038d7SDag-Erling Smørgrav BIGNUM *R, *S; 17617b5038d7SDag-Erling Smørgrav DSA_SIG *dsasig; 17627b5038d7SDag-Erling Smørgrav unsigned char *raw_sig = NULL; 17637b5038d7SDag-Erling Smørgrav int raw_sig_len; 17647b5038d7SDag-Erling Smørgrav 17657b5038d7SDag-Erling Smørgrav if(ldns_rdf_size(sig_rdf) < 1 + 2*SHA_DIGEST_LENGTH) 17667b5038d7SDag-Erling Smørgrav return LDNS_STATUS_SYNTAX_RDATA_ERR; 17677b5038d7SDag-Erling Smørgrav /* extract the R and S field from the sig buffer */ 17687b5038d7SDag-Erling Smørgrav R = BN_new(); 17697b5038d7SDag-Erling Smørgrav if(!R) return LDNS_STATUS_MEM_ERR; 17707b5038d7SDag-Erling Smørgrav (void) BN_bin2bn((unsigned char *) ldns_rdf_data(sig_rdf) + 1, 17717b5038d7SDag-Erling Smørgrav SHA_DIGEST_LENGTH, R); 17727b5038d7SDag-Erling Smørgrav S = BN_new(); 17737b5038d7SDag-Erling Smørgrav if(!S) { 17747b5038d7SDag-Erling Smørgrav BN_free(R); 17757b5038d7SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR; 17767b5038d7SDag-Erling Smørgrav } 17777b5038d7SDag-Erling Smørgrav (void) BN_bin2bn((unsigned char *) ldns_rdf_data(sig_rdf) + 21, 17787b5038d7SDag-Erling Smørgrav SHA_DIGEST_LENGTH, S); 17797b5038d7SDag-Erling Smørgrav 17807b5038d7SDag-Erling Smørgrav dsasig = DSA_SIG_new(); 17817b5038d7SDag-Erling Smørgrav if (!dsasig) { 17827b5038d7SDag-Erling Smørgrav BN_free(R); 17837b5038d7SDag-Erling Smørgrav BN_free(S); 17847b5038d7SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR; 17857b5038d7SDag-Erling Smørgrav } 17867b5038d7SDag-Erling Smørgrav 17877b5038d7SDag-Erling Smørgrav dsasig->r = R; 17887b5038d7SDag-Erling Smørgrav dsasig->s = S; 17897b5038d7SDag-Erling Smørgrav 17907b5038d7SDag-Erling Smørgrav raw_sig_len = i2d_DSA_SIG(dsasig, &raw_sig); 17917b5038d7SDag-Erling Smørgrav if (raw_sig_len < 0) { 17927b5038d7SDag-Erling Smørgrav DSA_SIG_free(dsasig); 17937b5038d7SDag-Erling Smørgrav free(raw_sig); 17947b5038d7SDag-Erling Smørgrav return LDNS_STATUS_SSL_ERR; 17957b5038d7SDag-Erling Smørgrav } 17967b5038d7SDag-Erling Smørgrav if (ldns_buffer_reserve(target_buffer, (size_t) raw_sig_len)) { 17977b5038d7SDag-Erling Smørgrav ldns_buffer_write(target_buffer, raw_sig, (size_t)raw_sig_len); 17987b5038d7SDag-Erling Smørgrav } 17997b5038d7SDag-Erling Smørgrav 18007b5038d7SDag-Erling Smørgrav DSA_SIG_free(dsasig); 18017b5038d7SDag-Erling Smørgrav free(raw_sig); 18027b5038d7SDag-Erling Smørgrav 18037b5038d7SDag-Erling Smørgrav return ldns_buffer_status(target_buffer); 18047b5038d7SDag-Erling Smørgrav } 18057b5038d7SDag-Erling Smørgrav 18067b5038d7SDag-Erling Smørgrav #ifdef USE_ECDSA 18077b5038d7SDag-Erling Smørgrav #ifndef S_SPLINT_S 18087b5038d7SDag-Erling Smørgrav ldns_rdf * 18097b5038d7SDag-Erling Smørgrav ldns_convert_ecdsa_rrsig_asn12rdf(const ldns_buffer *sig, const long sig_len) 18107b5038d7SDag-Erling Smørgrav { 18117b5038d7SDag-Erling Smørgrav ECDSA_SIG* ecdsa_sig; 18127b5038d7SDag-Erling Smørgrav unsigned char *data = (unsigned char*)ldns_buffer_begin(sig); 18137b5038d7SDag-Erling Smørgrav ldns_rdf* rdf; 18147b5038d7SDag-Erling Smørgrav ecdsa_sig = d2i_ECDSA_SIG(NULL, (const unsigned char **)&data, sig_len); 18157b5038d7SDag-Erling Smørgrav if(!ecdsa_sig) return NULL; 18167b5038d7SDag-Erling Smørgrav 18177b5038d7SDag-Erling Smørgrav /* "r | s". */ 18187b5038d7SDag-Erling Smørgrav data = LDNS_XMALLOC(unsigned char, 18197b5038d7SDag-Erling Smørgrav BN_num_bytes(ecdsa_sig->r) + BN_num_bytes(ecdsa_sig->s)); 18207b5038d7SDag-Erling Smørgrav if(!data) { 18217b5038d7SDag-Erling Smørgrav ECDSA_SIG_free(ecdsa_sig); 18227b5038d7SDag-Erling Smørgrav return NULL; 18237b5038d7SDag-Erling Smørgrav } 18247b5038d7SDag-Erling Smørgrav BN_bn2bin(ecdsa_sig->r, data); 18257b5038d7SDag-Erling Smørgrav BN_bn2bin(ecdsa_sig->s, data+BN_num_bytes(ecdsa_sig->r)); 18267b5038d7SDag-Erling Smørgrav rdf = ldns_rdf_new(LDNS_RDF_TYPE_B64, (size_t)( 18277b5038d7SDag-Erling Smørgrav BN_num_bytes(ecdsa_sig->r) + BN_num_bytes(ecdsa_sig->s)), data); 18287b5038d7SDag-Erling Smørgrav ECDSA_SIG_free(ecdsa_sig); 18297b5038d7SDag-Erling Smørgrav return rdf; 18307b5038d7SDag-Erling Smørgrav } 18317b5038d7SDag-Erling Smørgrav 18327b5038d7SDag-Erling Smørgrav ldns_status 18337b5038d7SDag-Erling Smørgrav ldns_convert_ecdsa_rrsig_rdf2asn1(ldns_buffer *target_buffer, 18347b5038d7SDag-Erling Smørgrav const ldns_rdf *sig_rdf) 18357b5038d7SDag-Erling Smørgrav { 18367b5038d7SDag-Erling Smørgrav ECDSA_SIG* sig; 18377b5038d7SDag-Erling Smørgrav int raw_sig_len; 18387b5038d7SDag-Erling Smørgrav long bnsize = (long)ldns_rdf_size(sig_rdf) / 2; 18397b5038d7SDag-Erling Smørgrav /* if too short, or not even length, do not bother */ 18407b5038d7SDag-Erling Smørgrav if(bnsize < 16 || (size_t)bnsize*2 != ldns_rdf_size(sig_rdf)) 18417b5038d7SDag-Erling Smørgrav return LDNS_STATUS_ERR; 18427b5038d7SDag-Erling Smørgrav 18437b5038d7SDag-Erling Smørgrav /* use the raw data to parse two evenly long BIGNUMs, "r | s". */ 18447b5038d7SDag-Erling Smørgrav sig = ECDSA_SIG_new(); 18457b5038d7SDag-Erling Smørgrav if(!sig) return LDNS_STATUS_MEM_ERR; 18467b5038d7SDag-Erling Smørgrav sig->r = BN_bin2bn((const unsigned char*)ldns_rdf_data(sig_rdf), 18477b5038d7SDag-Erling Smørgrav bnsize, sig->r); 18487b5038d7SDag-Erling Smørgrav sig->s = BN_bin2bn((const unsigned char*)ldns_rdf_data(sig_rdf)+bnsize, 18497b5038d7SDag-Erling Smørgrav bnsize, sig->s); 18507b5038d7SDag-Erling Smørgrav if(!sig->r || !sig->s) { 18517b5038d7SDag-Erling Smørgrav ECDSA_SIG_free(sig); 18527b5038d7SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR; 18537b5038d7SDag-Erling Smørgrav } 18547b5038d7SDag-Erling Smørgrav 18557b5038d7SDag-Erling Smørgrav raw_sig_len = i2d_ECDSA_SIG(sig, NULL); 18567b5038d7SDag-Erling Smørgrav if (ldns_buffer_reserve(target_buffer, (size_t) raw_sig_len)) { 18577b5038d7SDag-Erling Smørgrav unsigned char* pp = (unsigned char*) 18587b5038d7SDag-Erling Smørgrav ldns_buffer_current(target_buffer); 18597b5038d7SDag-Erling Smørgrav raw_sig_len = i2d_ECDSA_SIG(sig, &pp); 18607b5038d7SDag-Erling Smørgrav ldns_buffer_skip(target_buffer, (ssize_t) raw_sig_len); 18617b5038d7SDag-Erling Smørgrav } 18627b5038d7SDag-Erling Smørgrav ECDSA_SIG_free(sig); 18637b5038d7SDag-Erling Smørgrav 18647b5038d7SDag-Erling Smørgrav return ldns_buffer_status(target_buffer); 18657b5038d7SDag-Erling Smørgrav } 18667b5038d7SDag-Erling Smørgrav 18677b5038d7SDag-Erling Smørgrav #endif /* S_SPLINT_S */ 18687b5038d7SDag-Erling Smørgrav #endif /* USE_ECDSA */ 18697b5038d7SDag-Erling Smørgrav #endif /* HAVE_SSL */ 1870