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