xref: /freebsd/contrib/ldns/dnssec_verify.c (revision 7b5038d71c5c74ab863c1ff3fec33de94bf35a57)
1*7b5038d7SDag-Erling Smørgrav #include <ldns/config.h>
2*7b5038d7SDag-Erling Smørgrav 
3*7b5038d7SDag-Erling Smørgrav #include <ldns/ldns.h>
4*7b5038d7SDag-Erling Smørgrav 
5*7b5038d7SDag-Erling Smørgrav #include <strings.h>
6*7b5038d7SDag-Erling Smørgrav #include <time.h>
7*7b5038d7SDag-Erling Smørgrav 
8*7b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL
9*7b5038d7SDag-Erling Smørgrav /* this entire file is rather useless when you don't have
10*7b5038d7SDag-Erling Smørgrav  * crypto...
11*7b5038d7SDag-Erling Smørgrav  */
12*7b5038d7SDag-Erling Smørgrav #include <openssl/ssl.h>
13*7b5038d7SDag-Erling Smørgrav #include <openssl/evp.h>
14*7b5038d7SDag-Erling Smørgrav #include <openssl/rand.h>
15*7b5038d7SDag-Erling Smørgrav #include <openssl/err.h>
16*7b5038d7SDag-Erling Smørgrav #include <openssl/md5.h>
17*7b5038d7SDag-Erling Smørgrav 
18*7b5038d7SDag-Erling Smørgrav ldns_dnssec_data_chain *
19*7b5038d7SDag-Erling Smørgrav ldns_dnssec_data_chain_new(void)
20*7b5038d7SDag-Erling Smørgrav {
21*7b5038d7SDag-Erling Smørgrav 	ldns_dnssec_data_chain *nc = LDNS_CALLOC(ldns_dnssec_data_chain, 1);
22*7b5038d7SDag-Erling Smørgrav         if(!nc) return NULL;
23*7b5038d7SDag-Erling Smørgrav 	/*
24*7b5038d7SDag-Erling Smørgrav 	 * not needed anymore because CALLOC initalizes everything to zero.
25*7b5038d7SDag-Erling Smørgrav 
26*7b5038d7SDag-Erling Smørgrav 	nc->rrset = NULL;
27*7b5038d7SDag-Erling Smørgrav 	nc->parent_type = 0;
28*7b5038d7SDag-Erling Smørgrav 	nc->parent = NULL;
29*7b5038d7SDag-Erling Smørgrav 	nc->signatures = NULL;
30*7b5038d7SDag-Erling Smørgrav 	nc->packet_rcode = 0;
31*7b5038d7SDag-Erling Smørgrav 	nc->packet_qtype = 0;
32*7b5038d7SDag-Erling Smørgrav 	nc->packet_nodata = false;
33*7b5038d7SDag-Erling Smørgrav 
34*7b5038d7SDag-Erling Smørgrav 	 */
35*7b5038d7SDag-Erling Smørgrav 	return nc;
36*7b5038d7SDag-Erling Smørgrav }
37*7b5038d7SDag-Erling Smørgrav 
38*7b5038d7SDag-Erling Smørgrav void
39*7b5038d7SDag-Erling Smørgrav ldns_dnssec_data_chain_free(ldns_dnssec_data_chain *chain)
40*7b5038d7SDag-Erling Smørgrav {
41*7b5038d7SDag-Erling Smørgrav 	LDNS_FREE(chain);
42*7b5038d7SDag-Erling Smørgrav }
43*7b5038d7SDag-Erling Smørgrav 
44*7b5038d7SDag-Erling Smørgrav void
45*7b5038d7SDag-Erling Smørgrav ldns_dnssec_data_chain_deep_free(ldns_dnssec_data_chain *chain)
46*7b5038d7SDag-Erling Smørgrav {
47*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list_deep_free(chain->rrset);
48*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list_deep_free(chain->signatures);
49*7b5038d7SDag-Erling Smørgrav 	if (chain->parent) {
50*7b5038d7SDag-Erling Smørgrav 		ldns_dnssec_data_chain_deep_free(chain->parent);
51*7b5038d7SDag-Erling Smørgrav 	}
52*7b5038d7SDag-Erling Smørgrav 	LDNS_FREE(chain);
53*7b5038d7SDag-Erling Smørgrav }
54*7b5038d7SDag-Erling Smørgrav 
55*7b5038d7SDag-Erling Smørgrav void
56*7b5038d7SDag-Erling Smørgrav ldns_dnssec_data_chain_print_fmt(FILE *out, const ldns_output_format *fmt,
57*7b5038d7SDag-Erling Smørgrav 		const ldns_dnssec_data_chain *chain)
58*7b5038d7SDag-Erling Smørgrav {
59*7b5038d7SDag-Erling Smørgrav 	ldns_lookup_table *rcode;
60*7b5038d7SDag-Erling Smørgrav 	const ldns_rr_descriptor *rr_descriptor;
61*7b5038d7SDag-Erling Smørgrav 	if (chain) {
62*7b5038d7SDag-Erling Smørgrav 		ldns_dnssec_data_chain_print_fmt(out, fmt, chain->parent);
63*7b5038d7SDag-Erling Smørgrav 		if (ldns_rr_list_rr_count(chain->rrset) > 0) {
64*7b5038d7SDag-Erling Smørgrav 			rcode = ldns_lookup_by_id(ldns_rcodes,
65*7b5038d7SDag-Erling Smørgrav 								 (int) chain->packet_rcode);
66*7b5038d7SDag-Erling Smørgrav 			if (rcode) {
67*7b5038d7SDag-Erling Smørgrav 				fprintf(out, ";; rcode: %s\n", rcode->name);
68*7b5038d7SDag-Erling Smørgrav 			}
69*7b5038d7SDag-Erling Smørgrav 
70*7b5038d7SDag-Erling Smørgrav 			rr_descriptor = ldns_rr_descript(chain->packet_qtype);
71*7b5038d7SDag-Erling Smørgrav 			if (rr_descriptor && rr_descriptor->_name) {
72*7b5038d7SDag-Erling Smørgrav 				fprintf(out, ";; qtype: %s\n", rr_descriptor->_name);
73*7b5038d7SDag-Erling Smørgrav 			} else if (chain->packet_qtype != 0) {
74*7b5038d7SDag-Erling Smørgrav 				fprintf(out, "TYPE%u",
75*7b5038d7SDag-Erling Smørgrav 					   chain->packet_qtype);
76*7b5038d7SDag-Erling Smørgrav 			}
77*7b5038d7SDag-Erling Smørgrav 			if (chain->packet_nodata) {
78*7b5038d7SDag-Erling Smørgrav 				fprintf(out, ";; NODATA response\n");
79*7b5038d7SDag-Erling Smørgrav 			}
80*7b5038d7SDag-Erling Smørgrav 			fprintf(out, "rrset:\n");
81*7b5038d7SDag-Erling Smørgrav 			ldns_rr_list_print_fmt(out, fmt, chain->rrset);
82*7b5038d7SDag-Erling Smørgrav 			fprintf(out, "sigs:\n");
83*7b5038d7SDag-Erling Smørgrav 			ldns_rr_list_print_fmt(out, fmt, chain->signatures);
84*7b5038d7SDag-Erling Smørgrav 			fprintf(out, "---\n");
85*7b5038d7SDag-Erling Smørgrav 		} else {
86*7b5038d7SDag-Erling Smørgrav 			fprintf(out, "<no data>\n");
87*7b5038d7SDag-Erling Smørgrav 		}
88*7b5038d7SDag-Erling Smørgrav 	}
89*7b5038d7SDag-Erling Smørgrav }
90*7b5038d7SDag-Erling Smørgrav void
91*7b5038d7SDag-Erling Smørgrav ldns_dnssec_data_chain_print(FILE *out, const ldns_dnssec_data_chain *chain)
92*7b5038d7SDag-Erling Smørgrav {
93*7b5038d7SDag-Erling Smørgrav 	ldns_dnssec_data_chain_print_fmt(
94*7b5038d7SDag-Erling Smørgrav 			out, ldns_output_format_default, chain);
95*7b5038d7SDag-Erling Smørgrav }
96*7b5038d7SDag-Erling Smørgrav 
97*7b5038d7SDag-Erling Smørgrav 
98*7b5038d7SDag-Erling Smørgrav static void
99*7b5038d7SDag-Erling Smørgrav ldns_dnssec_build_data_chain_dnskey(ldns_resolver *res,
100*7b5038d7SDag-Erling Smørgrav 					    uint16_t qflags,
101*7b5038d7SDag-Erling Smørgrav 					    const ldns_pkt *pkt,
102*7b5038d7SDag-Erling Smørgrav 					    ldns_rr_list *signatures,
103*7b5038d7SDag-Erling Smørgrav 						ldns_dnssec_data_chain *new_chain,
104*7b5038d7SDag-Erling Smørgrav 						ldns_rdf *key_name,
105*7b5038d7SDag-Erling Smørgrav 						ldns_rr_class c) {
106*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list *keys;
107*7b5038d7SDag-Erling Smørgrav 	ldns_pkt *my_pkt;
108*7b5038d7SDag-Erling Smørgrav 	if (signatures && ldns_rr_list_rr_count(signatures) > 0) {
109*7b5038d7SDag-Erling Smørgrav 		new_chain->signatures = ldns_rr_list_clone(signatures);
110*7b5038d7SDag-Erling Smørgrav 		new_chain->parent_type = 0;
111*7b5038d7SDag-Erling Smørgrav 
112*7b5038d7SDag-Erling Smørgrav 		keys = ldns_pkt_rr_list_by_name_and_type(
113*7b5038d7SDag-Erling Smørgrav 				  pkt,
114*7b5038d7SDag-Erling Smørgrav 				 key_name,
115*7b5038d7SDag-Erling Smørgrav 				 LDNS_RR_TYPE_DNSKEY,
116*7b5038d7SDag-Erling Smørgrav 				 LDNS_SECTION_ANY_NOQUESTION
117*7b5038d7SDag-Erling Smørgrav 			  );
118*7b5038d7SDag-Erling Smørgrav 		if (!keys) {
119*7b5038d7SDag-Erling Smørgrav 			my_pkt = ldns_resolver_query(res,
120*7b5038d7SDag-Erling Smørgrav 									key_name,
121*7b5038d7SDag-Erling Smørgrav 									LDNS_RR_TYPE_DNSKEY,
122*7b5038d7SDag-Erling Smørgrav 									c,
123*7b5038d7SDag-Erling Smørgrav 									qflags);
124*7b5038d7SDag-Erling Smørgrav 			if (my_pkt) {
125*7b5038d7SDag-Erling Smørgrav 			keys = ldns_pkt_rr_list_by_name_and_type(
126*7b5038d7SDag-Erling Smørgrav 					  my_pkt,
127*7b5038d7SDag-Erling Smørgrav 					 key_name,
128*7b5038d7SDag-Erling Smørgrav 					 LDNS_RR_TYPE_DNSKEY,
129*7b5038d7SDag-Erling Smørgrav 					 LDNS_SECTION_ANY_NOQUESTION
130*7b5038d7SDag-Erling Smørgrav 				  );
131*7b5038d7SDag-Erling Smørgrav 			new_chain->parent = ldns_dnssec_build_data_chain(res,
132*7b5038d7SDag-Erling Smørgrav 													qflags,
133*7b5038d7SDag-Erling Smørgrav 													keys,
134*7b5038d7SDag-Erling Smørgrav 													my_pkt,
135*7b5038d7SDag-Erling Smørgrav 													NULL);
136*7b5038d7SDag-Erling Smørgrav 			new_chain->parent->packet_qtype = LDNS_RR_TYPE_DNSKEY;
137*7b5038d7SDag-Erling Smørgrav 			ldns_pkt_free(my_pkt);
138*7b5038d7SDag-Erling Smørgrav 			}
139*7b5038d7SDag-Erling Smørgrav 		} else {
140*7b5038d7SDag-Erling Smørgrav 			new_chain->parent = ldns_dnssec_build_data_chain(res,
141*7b5038d7SDag-Erling Smørgrav 													qflags,
142*7b5038d7SDag-Erling Smørgrav 													keys,
143*7b5038d7SDag-Erling Smørgrav 													pkt,
144*7b5038d7SDag-Erling Smørgrav 													NULL);
145*7b5038d7SDag-Erling Smørgrav 			new_chain->parent->packet_qtype = LDNS_RR_TYPE_DNSKEY;
146*7b5038d7SDag-Erling Smørgrav 		}
147*7b5038d7SDag-Erling Smørgrav 		ldns_rr_list_deep_free(keys);
148*7b5038d7SDag-Erling Smørgrav 	}
149*7b5038d7SDag-Erling Smørgrav }
150*7b5038d7SDag-Erling Smørgrav 
151*7b5038d7SDag-Erling Smørgrav static void
152*7b5038d7SDag-Erling Smørgrav ldns_dnssec_build_data_chain_other(ldns_resolver *res,
153*7b5038d7SDag-Erling Smørgrav 					    uint16_t qflags,
154*7b5038d7SDag-Erling Smørgrav 						ldns_dnssec_data_chain *new_chain,
155*7b5038d7SDag-Erling Smørgrav 						ldns_rdf *key_name,
156*7b5038d7SDag-Erling Smørgrav 						ldns_rr_class c,
157*7b5038d7SDag-Erling Smørgrav 						ldns_rr_list *dss)
158*7b5038d7SDag-Erling Smørgrav {
159*7b5038d7SDag-Erling Smørgrav 	/* 'self-signed', parent is a DS */
160*7b5038d7SDag-Erling Smørgrav 
161*7b5038d7SDag-Erling Smørgrav 	/* okay, either we have other keys signing the current one,
162*7b5038d7SDag-Erling Smørgrav 	 * or the current
163*7b5038d7SDag-Erling Smørgrav 	 * one should have a DS record in the parent zone.
164*7b5038d7SDag-Erling Smørgrav 	 * How do we find this out? Try both?
165*7b5038d7SDag-Erling Smørgrav 	 *
166*7b5038d7SDag-Erling Smørgrav 	 * request DNSKEYS for current zone,
167*7b5038d7SDag-Erling Smørgrav 	 * add all signatures to current level
168*7b5038d7SDag-Erling Smørgrav 	 */
169*7b5038d7SDag-Erling Smørgrav 	ldns_pkt *my_pkt;
170*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list *signatures2;
171*7b5038d7SDag-Erling Smørgrav 
172*7b5038d7SDag-Erling Smørgrav 	new_chain->parent_type = 1;
173*7b5038d7SDag-Erling Smørgrav 
174*7b5038d7SDag-Erling Smørgrav 	my_pkt = ldns_resolver_query(res,
175*7b5038d7SDag-Erling Smørgrav 							key_name,
176*7b5038d7SDag-Erling Smørgrav 							LDNS_RR_TYPE_DS,
177*7b5038d7SDag-Erling Smørgrav 							c,
178*7b5038d7SDag-Erling Smørgrav 							qflags);
179*7b5038d7SDag-Erling Smørgrav 	if (my_pkt) {
180*7b5038d7SDag-Erling Smørgrav 	dss = ldns_pkt_rr_list_by_name_and_type(my_pkt,
181*7b5038d7SDag-Erling Smørgrav 									key_name,
182*7b5038d7SDag-Erling Smørgrav 									LDNS_RR_TYPE_DS,
183*7b5038d7SDag-Erling Smørgrav 									LDNS_SECTION_ANY_NOQUESTION
184*7b5038d7SDag-Erling Smørgrav 									);
185*7b5038d7SDag-Erling Smørgrav 	if (dss) {
186*7b5038d7SDag-Erling Smørgrav 		new_chain->parent = ldns_dnssec_build_data_chain(res,
187*7b5038d7SDag-Erling Smørgrav 												qflags,
188*7b5038d7SDag-Erling Smørgrav 												dss,
189*7b5038d7SDag-Erling Smørgrav 												my_pkt,
190*7b5038d7SDag-Erling Smørgrav 												NULL);
191*7b5038d7SDag-Erling Smørgrav 		new_chain->parent->packet_qtype = LDNS_RR_TYPE_DS;
192*7b5038d7SDag-Erling Smørgrav 		ldns_rr_list_deep_free(dss);
193*7b5038d7SDag-Erling Smørgrav 	}
194*7b5038d7SDag-Erling Smørgrav 	ldns_pkt_free(my_pkt);
195*7b5038d7SDag-Erling Smørgrav 	}
196*7b5038d7SDag-Erling Smørgrav 
197*7b5038d7SDag-Erling Smørgrav 	my_pkt = ldns_resolver_query(res,
198*7b5038d7SDag-Erling Smørgrav 							key_name,
199*7b5038d7SDag-Erling Smørgrav 							LDNS_RR_TYPE_DNSKEY,
200*7b5038d7SDag-Erling Smørgrav 							c,
201*7b5038d7SDag-Erling Smørgrav 							qflags);
202*7b5038d7SDag-Erling Smørgrav 	if (my_pkt) {
203*7b5038d7SDag-Erling Smørgrav 	signatures2 = ldns_pkt_rr_list_by_name_and_type(my_pkt,
204*7b5038d7SDag-Erling Smørgrav 										   key_name,
205*7b5038d7SDag-Erling Smørgrav 										   LDNS_RR_TYPE_RRSIG,
206*7b5038d7SDag-Erling Smørgrav 										   LDNS_SECTION_ANSWER);
207*7b5038d7SDag-Erling Smørgrav 	if (signatures2) {
208*7b5038d7SDag-Erling Smørgrav 		if (new_chain->signatures) {
209*7b5038d7SDag-Erling Smørgrav 			printf("There were already sigs!\n");
210*7b5038d7SDag-Erling Smørgrav 			ldns_rr_list_deep_free(new_chain->signatures);
211*7b5038d7SDag-Erling Smørgrav 			printf("replacing the old sigs\n");
212*7b5038d7SDag-Erling Smørgrav 		}
213*7b5038d7SDag-Erling Smørgrav 		new_chain->signatures = signatures2;
214*7b5038d7SDag-Erling Smørgrav 	}
215*7b5038d7SDag-Erling Smørgrav 	ldns_pkt_free(my_pkt);
216*7b5038d7SDag-Erling Smørgrav 	}
217*7b5038d7SDag-Erling Smørgrav }
218*7b5038d7SDag-Erling Smørgrav 
219*7b5038d7SDag-Erling Smørgrav static ldns_dnssec_data_chain *
220*7b5038d7SDag-Erling Smørgrav ldns_dnssec_build_data_chain_nokeyname(ldns_resolver *res,
221*7b5038d7SDag-Erling Smørgrav                                        uint16_t qflags,
222*7b5038d7SDag-Erling Smørgrav                                        ldns_rr *orig_rr,
223*7b5038d7SDag-Erling Smørgrav                                        const ldns_rr_list *rrset,
224*7b5038d7SDag-Erling Smørgrav                                        ldns_dnssec_data_chain *new_chain)
225*7b5038d7SDag-Erling Smørgrav {
226*7b5038d7SDag-Erling Smørgrav 	ldns_rdf *possible_parent_name;
227*7b5038d7SDag-Erling Smørgrav 	ldns_pkt *my_pkt;
228*7b5038d7SDag-Erling Smørgrav 	/* apparently we were not able to find a signing key, so
229*7b5038d7SDag-Erling Smørgrav 	   we assume the chain ends here
230*7b5038d7SDag-Erling Smørgrav 	*/
231*7b5038d7SDag-Erling Smørgrav 	/* try parents for auth denial of DS */
232*7b5038d7SDag-Erling Smørgrav 	if (orig_rr) {
233*7b5038d7SDag-Erling Smørgrav 		possible_parent_name = ldns_rr_owner(orig_rr);
234*7b5038d7SDag-Erling Smørgrav 	} else if (rrset && ldns_rr_list_rr_count(rrset) > 0) {
235*7b5038d7SDag-Erling Smørgrav 		possible_parent_name = ldns_rr_owner(ldns_rr_list_rr(rrset, 0));
236*7b5038d7SDag-Erling Smørgrav 	} else {
237*7b5038d7SDag-Erling Smørgrav 		/* no information to go on, give up */
238*7b5038d7SDag-Erling Smørgrav 		return new_chain;
239*7b5038d7SDag-Erling Smørgrav 	}
240*7b5038d7SDag-Erling Smørgrav 
241*7b5038d7SDag-Erling Smørgrav 	my_pkt = ldns_resolver_query(res,
242*7b5038d7SDag-Erling Smørgrav 	              possible_parent_name,
243*7b5038d7SDag-Erling Smørgrav 	              LDNS_RR_TYPE_DS,
244*7b5038d7SDag-Erling Smørgrav 	              LDNS_RR_CLASS_IN,
245*7b5038d7SDag-Erling Smørgrav 	              qflags);
246*7b5038d7SDag-Erling Smørgrav 	if (!my_pkt) {
247*7b5038d7SDag-Erling Smørgrav 		return new_chain;
248*7b5038d7SDag-Erling Smørgrav 	}
249*7b5038d7SDag-Erling Smørgrav 
250*7b5038d7SDag-Erling Smørgrav 	if (ldns_pkt_ancount(my_pkt) > 0) {
251*7b5038d7SDag-Erling Smørgrav 		/* add error, no sigs but DS in parent */
252*7b5038d7SDag-Erling Smørgrav 		/*ldns_pkt_print(stdout, my_pkt);*/
253*7b5038d7SDag-Erling Smørgrav 		ldns_pkt_free(my_pkt);
254*7b5038d7SDag-Erling Smørgrav 	} else {
255*7b5038d7SDag-Erling Smørgrav 		/* are there signatures? */
256*7b5038d7SDag-Erling Smørgrav 		new_chain->parent =  ldns_dnssec_build_data_chain(res,
257*7b5038d7SDag-Erling Smørgrav 		                          qflags,
258*7b5038d7SDag-Erling Smørgrav 		                          NULL,
259*7b5038d7SDag-Erling Smørgrav 		                          my_pkt,
260*7b5038d7SDag-Erling Smørgrav 		                          NULL);
261*7b5038d7SDag-Erling Smørgrav 
262*7b5038d7SDag-Erling Smørgrav 		new_chain->parent->packet_qtype = LDNS_RR_TYPE_DS;
263*7b5038d7SDag-Erling Smørgrav 
264*7b5038d7SDag-Erling Smørgrav 	}
265*7b5038d7SDag-Erling Smørgrav 	return new_chain;
266*7b5038d7SDag-Erling Smørgrav }
267*7b5038d7SDag-Erling Smørgrav 
268*7b5038d7SDag-Erling Smørgrav 
269*7b5038d7SDag-Erling Smørgrav ldns_dnssec_data_chain *
270*7b5038d7SDag-Erling Smørgrav ldns_dnssec_build_data_chain(ldns_resolver *res,
271*7b5038d7SDag-Erling Smørgrav 					    uint16_t qflags,
272*7b5038d7SDag-Erling Smørgrav 					    const ldns_rr_list *rrset,
273*7b5038d7SDag-Erling Smørgrav 					    const ldns_pkt *pkt,
274*7b5038d7SDag-Erling Smørgrav 					    ldns_rr *orig_rr)
275*7b5038d7SDag-Erling Smørgrav {
276*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list *signatures = NULL;
277*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list *dss = NULL;
278*7b5038d7SDag-Erling Smørgrav 
279*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list *my_rrset;
280*7b5038d7SDag-Erling Smørgrav 
281*7b5038d7SDag-Erling Smørgrav 	ldns_pkt *my_pkt;
282*7b5038d7SDag-Erling Smørgrav 
283*7b5038d7SDag-Erling Smørgrav 	ldns_rdf *name = NULL, *key_name = NULL;
284*7b5038d7SDag-Erling Smørgrav 	ldns_rr_type type = 0;
285*7b5038d7SDag-Erling Smørgrav 	ldns_rr_class c = 0;
286*7b5038d7SDag-Erling Smørgrav 
287*7b5038d7SDag-Erling Smørgrav 	bool other_rrset = false;
288*7b5038d7SDag-Erling Smørgrav 
289*7b5038d7SDag-Erling Smørgrav 	ldns_dnssec_data_chain *new_chain = ldns_dnssec_data_chain_new();
290*7b5038d7SDag-Erling Smørgrav 
291*7b5038d7SDag-Erling Smørgrav 	if (!ldns_dnssec_pkt_has_rrsigs(pkt)) {
292*7b5038d7SDag-Erling Smørgrav 		/* hmm. no dnssec data in the packet. go up to try and deny
293*7b5038d7SDag-Erling Smørgrav 		 * DS? */
294*7b5038d7SDag-Erling Smørgrav 		return new_chain;
295*7b5038d7SDag-Erling Smørgrav 	}
296*7b5038d7SDag-Erling Smørgrav 
297*7b5038d7SDag-Erling Smørgrav 	if (orig_rr) {
298*7b5038d7SDag-Erling Smørgrav 		new_chain->rrset = ldns_rr_list_new();
299*7b5038d7SDag-Erling Smørgrav 		ldns_rr_list_push_rr(new_chain->rrset, orig_rr);
300*7b5038d7SDag-Erling Smørgrav 		new_chain->parent = ldns_dnssec_build_data_chain(res,
301*7b5038d7SDag-Erling Smørgrav 											    qflags,
302*7b5038d7SDag-Erling Smørgrav 											    rrset,
303*7b5038d7SDag-Erling Smørgrav 											    pkt,
304*7b5038d7SDag-Erling Smørgrav 											    NULL);
305*7b5038d7SDag-Erling Smørgrav 		new_chain->packet_rcode = ldns_pkt_get_rcode(pkt);
306*7b5038d7SDag-Erling Smørgrav 		new_chain->packet_qtype = ldns_rr_get_type(orig_rr);
307*7b5038d7SDag-Erling Smørgrav 		if (ldns_pkt_ancount(pkt) == 0) {
308*7b5038d7SDag-Erling Smørgrav 			new_chain->packet_nodata = true;
309*7b5038d7SDag-Erling Smørgrav 		}
310*7b5038d7SDag-Erling Smørgrav 		return new_chain;
311*7b5038d7SDag-Erling Smørgrav 	}
312*7b5038d7SDag-Erling Smørgrav 
313*7b5038d7SDag-Erling Smørgrav 	if (!rrset || ldns_rr_list_rr_count(rrset) < 1) {
314*7b5038d7SDag-Erling Smørgrav 		/* hmm, no data, do we have denial? only works if pkt was given,
315*7b5038d7SDag-Erling Smørgrav 		   otherwise caller has to do the check himself */
316*7b5038d7SDag-Erling Smørgrav 		new_chain->packet_nodata = true;
317*7b5038d7SDag-Erling Smørgrav 		if (pkt) {
318*7b5038d7SDag-Erling Smørgrav 			my_rrset = ldns_pkt_rr_list_by_type(pkt,
319*7b5038d7SDag-Erling Smørgrav 										 LDNS_RR_TYPE_NSEC,
320*7b5038d7SDag-Erling Smørgrav 										 LDNS_SECTION_ANY_NOQUESTION
321*7b5038d7SDag-Erling Smørgrav 										 );
322*7b5038d7SDag-Erling Smørgrav 			if (my_rrset) {
323*7b5038d7SDag-Erling Smørgrav 				if (ldns_rr_list_rr_count(my_rrset) > 0) {
324*7b5038d7SDag-Erling Smørgrav 					type = LDNS_RR_TYPE_NSEC;
325*7b5038d7SDag-Erling Smørgrav 					other_rrset = true;
326*7b5038d7SDag-Erling Smørgrav 				} else {
327*7b5038d7SDag-Erling Smørgrav 					ldns_rr_list_deep_free(my_rrset);
328*7b5038d7SDag-Erling Smørgrav 					my_rrset = NULL;
329*7b5038d7SDag-Erling Smørgrav 				}
330*7b5038d7SDag-Erling Smørgrav 			} else {
331*7b5038d7SDag-Erling Smørgrav 				/* nothing, try nsec3 */
332*7b5038d7SDag-Erling Smørgrav 				my_rrset = ldns_pkt_rr_list_by_type(pkt,
333*7b5038d7SDag-Erling Smørgrav 						     LDNS_RR_TYPE_NSEC3,
334*7b5038d7SDag-Erling Smørgrav 							LDNS_SECTION_ANY_NOQUESTION);
335*7b5038d7SDag-Erling Smørgrav 				if (my_rrset) {
336*7b5038d7SDag-Erling Smørgrav 					if (ldns_rr_list_rr_count(my_rrset) > 0) {
337*7b5038d7SDag-Erling Smørgrav 						type = LDNS_RR_TYPE_NSEC3;
338*7b5038d7SDag-Erling Smørgrav 						other_rrset = true;
339*7b5038d7SDag-Erling Smørgrav 					} else {
340*7b5038d7SDag-Erling Smørgrav 						ldns_rr_list_deep_free(my_rrset);
341*7b5038d7SDag-Erling Smørgrav 						my_rrset = NULL;
342*7b5038d7SDag-Erling Smørgrav 					}
343*7b5038d7SDag-Erling Smørgrav 				} else {
344*7b5038d7SDag-Erling Smørgrav 					/* nothing, stop */
345*7b5038d7SDag-Erling Smørgrav 					/* try parent zone? for denied insecure? */
346*7b5038d7SDag-Erling Smørgrav 					return new_chain;
347*7b5038d7SDag-Erling Smørgrav 				}
348*7b5038d7SDag-Erling Smørgrav 			}
349*7b5038d7SDag-Erling Smørgrav 		} else {
350*7b5038d7SDag-Erling Smørgrav 			return new_chain;
351*7b5038d7SDag-Erling Smørgrav 		}
352*7b5038d7SDag-Erling Smørgrav 	} else {
353*7b5038d7SDag-Erling Smørgrav 		my_rrset = (ldns_rr_list *) rrset;
354*7b5038d7SDag-Erling Smørgrav 	}
355*7b5038d7SDag-Erling Smørgrav 
356*7b5038d7SDag-Erling Smørgrav 	if (my_rrset && ldns_rr_list_rr_count(my_rrset) > 0) {
357*7b5038d7SDag-Erling Smørgrav 		new_chain->rrset = ldns_rr_list_clone(my_rrset);
358*7b5038d7SDag-Erling Smørgrav 		name = ldns_rr_owner(ldns_rr_list_rr(my_rrset, 0));
359*7b5038d7SDag-Erling Smørgrav 		type = ldns_rr_get_type(ldns_rr_list_rr(my_rrset, 0));
360*7b5038d7SDag-Erling Smørgrav 		c = ldns_rr_get_class(ldns_rr_list_rr(my_rrset, 0));
361*7b5038d7SDag-Erling Smørgrav 	}
362*7b5038d7SDag-Erling Smørgrav 
363*7b5038d7SDag-Erling Smørgrav 	if (other_rrset) {
364*7b5038d7SDag-Erling Smørgrav 		ldns_rr_list_deep_free(my_rrset);
365*7b5038d7SDag-Erling Smørgrav 	}
366*7b5038d7SDag-Erling Smørgrav 
367*7b5038d7SDag-Erling Smørgrav 	/* normally there will only be 1 signature 'set'
368*7b5038d7SDag-Erling Smørgrav 	   but there can be more than 1 denial (wildcards)
369*7b5038d7SDag-Erling Smørgrav 	   so check for NSEC
370*7b5038d7SDag-Erling Smørgrav 	*/
371*7b5038d7SDag-Erling Smørgrav 	if (type == LDNS_RR_TYPE_NSEC || type == LDNS_RR_TYPE_NSEC3) {
372*7b5038d7SDag-Erling Smørgrav 		/* just throw in all signatures, the tree builder must sort
373*7b5038d7SDag-Erling Smørgrav 		   this out */
374*7b5038d7SDag-Erling Smørgrav 		if (pkt) {
375*7b5038d7SDag-Erling Smørgrav 			signatures = ldns_dnssec_pkt_get_rrsigs_for_type(pkt, type);
376*7b5038d7SDag-Erling Smørgrav 		} else {
377*7b5038d7SDag-Erling Smørgrav 			my_pkt = ldns_resolver_query(res, name, type, c, qflags);
378*7b5038d7SDag-Erling Smørgrav 			if (my_pkt) {
379*7b5038d7SDag-Erling Smørgrav 			signatures = ldns_dnssec_pkt_get_rrsigs_for_type(pkt, type);
380*7b5038d7SDag-Erling Smørgrav 			ldns_pkt_free(my_pkt);
381*7b5038d7SDag-Erling Smørgrav 			}
382*7b5038d7SDag-Erling Smørgrav 		}
383*7b5038d7SDag-Erling Smørgrav 	} else {
384*7b5038d7SDag-Erling Smørgrav 		if (pkt) {
385*7b5038d7SDag-Erling Smørgrav 			signatures =
386*7b5038d7SDag-Erling Smørgrav 				ldns_dnssec_pkt_get_rrsigs_for_name_and_type(pkt,
387*7b5038d7SDag-Erling Smørgrav 													name,
388*7b5038d7SDag-Erling Smørgrav 													type);
389*7b5038d7SDag-Erling Smørgrav 		}
390*7b5038d7SDag-Erling Smørgrav 		if (!signatures) {
391*7b5038d7SDag-Erling Smørgrav 			my_pkt = ldns_resolver_query(res, name, type, c, qflags);
392*7b5038d7SDag-Erling Smørgrav 			if (my_pkt) {
393*7b5038d7SDag-Erling Smørgrav 			signatures =
394*7b5038d7SDag-Erling Smørgrav 				ldns_dnssec_pkt_get_rrsigs_for_name_and_type(my_pkt,
395*7b5038d7SDag-Erling Smørgrav 													name,
396*7b5038d7SDag-Erling Smørgrav 													type);
397*7b5038d7SDag-Erling Smørgrav 			ldns_pkt_free(my_pkt);
398*7b5038d7SDag-Erling Smørgrav 			}
399*7b5038d7SDag-Erling Smørgrav 		}
400*7b5038d7SDag-Erling Smørgrav 	}
401*7b5038d7SDag-Erling Smørgrav 
402*7b5038d7SDag-Erling Smørgrav 	if (signatures && ldns_rr_list_rr_count(signatures) > 0) {
403*7b5038d7SDag-Erling Smørgrav 		key_name = ldns_rr_rdf(ldns_rr_list_rr(signatures, 0), 7);
404*7b5038d7SDag-Erling Smørgrav 	}
405*7b5038d7SDag-Erling Smørgrav 
406*7b5038d7SDag-Erling Smørgrav 	if (!key_name) {
407*7b5038d7SDag-Erling Smørgrav 		return ldns_dnssec_build_data_chain_nokeyname(res,
408*7b5038d7SDag-Erling Smørgrav 		                                              qflags,
409*7b5038d7SDag-Erling Smørgrav 		                                              orig_rr,
410*7b5038d7SDag-Erling Smørgrav 		                                              rrset,
411*7b5038d7SDag-Erling Smørgrav 		                                              new_chain);
412*7b5038d7SDag-Erling Smørgrav 	}
413*7b5038d7SDag-Erling Smørgrav 
414*7b5038d7SDag-Erling Smørgrav 	if (type != LDNS_RR_TYPE_DNSKEY) {
415*7b5038d7SDag-Erling Smørgrav 		ldns_dnssec_build_data_chain_dnskey(res,
416*7b5038d7SDag-Erling Smørgrav 		                                    qflags,
417*7b5038d7SDag-Erling Smørgrav 		                                    pkt,
418*7b5038d7SDag-Erling Smørgrav 		                                    signatures,
419*7b5038d7SDag-Erling Smørgrav 		                                    new_chain,
420*7b5038d7SDag-Erling Smørgrav 		                                    key_name,
421*7b5038d7SDag-Erling Smørgrav 		                                    c
422*7b5038d7SDag-Erling Smørgrav 		                                    );
423*7b5038d7SDag-Erling Smørgrav 	} else {
424*7b5038d7SDag-Erling Smørgrav 		ldns_dnssec_build_data_chain_other(res,
425*7b5038d7SDag-Erling Smørgrav 		                                   qflags,
426*7b5038d7SDag-Erling Smørgrav 		                                   new_chain,
427*7b5038d7SDag-Erling Smørgrav 		                                   key_name,
428*7b5038d7SDag-Erling Smørgrav 		                                   c,
429*7b5038d7SDag-Erling Smørgrav 		                                   dss
430*7b5038d7SDag-Erling Smørgrav 
431*7b5038d7SDag-Erling Smørgrav 		                                    );
432*7b5038d7SDag-Erling Smørgrav 	}
433*7b5038d7SDag-Erling Smørgrav 	if (signatures) {
434*7b5038d7SDag-Erling Smørgrav 		ldns_rr_list_deep_free(signatures);
435*7b5038d7SDag-Erling Smørgrav 	}
436*7b5038d7SDag-Erling Smørgrav 
437*7b5038d7SDag-Erling Smørgrav 	return new_chain;
438*7b5038d7SDag-Erling Smørgrav }
439*7b5038d7SDag-Erling Smørgrav 
440*7b5038d7SDag-Erling Smørgrav ldns_dnssec_trust_tree *
441*7b5038d7SDag-Erling Smørgrav ldns_dnssec_trust_tree_new(void)
442*7b5038d7SDag-Erling Smørgrav {
443*7b5038d7SDag-Erling Smørgrav 	ldns_dnssec_trust_tree *new_tree = LDNS_XMALLOC(ldns_dnssec_trust_tree,
444*7b5038d7SDag-Erling Smørgrav 										   1);
445*7b5038d7SDag-Erling Smørgrav         if(!new_tree) return NULL;
446*7b5038d7SDag-Erling Smørgrav 	new_tree->rr = NULL;
447*7b5038d7SDag-Erling Smørgrav 	new_tree->rrset = NULL;
448*7b5038d7SDag-Erling Smørgrav 	new_tree->parent_count = 0;
449*7b5038d7SDag-Erling Smørgrav 
450*7b5038d7SDag-Erling Smørgrav 	return new_tree;
451*7b5038d7SDag-Erling Smørgrav }
452*7b5038d7SDag-Erling Smørgrav 
453*7b5038d7SDag-Erling Smørgrav void
454*7b5038d7SDag-Erling Smørgrav ldns_dnssec_trust_tree_free(ldns_dnssec_trust_tree *tree)
455*7b5038d7SDag-Erling Smørgrav {
456*7b5038d7SDag-Erling Smørgrav 	size_t i;
457*7b5038d7SDag-Erling Smørgrav 	if (tree) {
458*7b5038d7SDag-Erling Smørgrav 		for (i = 0; i < tree->parent_count; i++) {
459*7b5038d7SDag-Erling Smørgrav 			ldns_dnssec_trust_tree_free(tree->parents[i]);
460*7b5038d7SDag-Erling Smørgrav 		}
461*7b5038d7SDag-Erling Smørgrav 	}
462*7b5038d7SDag-Erling Smørgrav 	LDNS_FREE(tree);
463*7b5038d7SDag-Erling Smørgrav }
464*7b5038d7SDag-Erling Smørgrav 
465*7b5038d7SDag-Erling Smørgrav size_t
466*7b5038d7SDag-Erling Smørgrav ldns_dnssec_trust_tree_depth(ldns_dnssec_trust_tree *tree)
467*7b5038d7SDag-Erling Smørgrav {
468*7b5038d7SDag-Erling Smørgrav 	size_t result = 0;
469*7b5038d7SDag-Erling Smørgrav 	size_t parent = 0;
470*7b5038d7SDag-Erling Smørgrav 	size_t i;
471*7b5038d7SDag-Erling Smørgrav 
472*7b5038d7SDag-Erling Smørgrav 	for (i = 0; i < tree->parent_count; i++) {
473*7b5038d7SDag-Erling Smørgrav 		parent = ldns_dnssec_trust_tree_depth(tree->parents[i]);
474*7b5038d7SDag-Erling Smørgrav 		if (parent > result) {
475*7b5038d7SDag-Erling Smørgrav 			result = parent;
476*7b5038d7SDag-Erling Smørgrav 		}
477*7b5038d7SDag-Erling Smørgrav 	}
478*7b5038d7SDag-Erling Smørgrav 	return 1 + result;
479*7b5038d7SDag-Erling Smørgrav }
480*7b5038d7SDag-Erling Smørgrav 
481*7b5038d7SDag-Erling Smørgrav /* TODO ldns_ */
482*7b5038d7SDag-Erling Smørgrav static void
483*7b5038d7SDag-Erling Smørgrav print_tabs(FILE *out, size_t nr, uint8_t *map, size_t treedepth)
484*7b5038d7SDag-Erling Smørgrav {
485*7b5038d7SDag-Erling Smørgrav 	size_t i;
486*7b5038d7SDag-Erling Smørgrav 	for (i = 0; i < nr; i++) {
487*7b5038d7SDag-Erling Smørgrav 		if (i == nr - 1) {
488*7b5038d7SDag-Erling Smørgrav 			fprintf(out, "|---");
489*7b5038d7SDag-Erling Smørgrav 		} else if (map && i < treedepth && map[i] == 1) {
490*7b5038d7SDag-Erling Smørgrav 			fprintf(out, "|   ");
491*7b5038d7SDag-Erling Smørgrav 		} else {
492*7b5038d7SDag-Erling Smørgrav 			fprintf(out, "    ");
493*7b5038d7SDag-Erling Smørgrav 		}
494*7b5038d7SDag-Erling Smørgrav 	}
495*7b5038d7SDag-Erling Smørgrav }
496*7b5038d7SDag-Erling Smørgrav 
497*7b5038d7SDag-Erling Smørgrav static void
498*7b5038d7SDag-Erling Smørgrav ldns_dnssec_trust_tree_print_sm_fmt(FILE *out,
499*7b5038d7SDag-Erling Smørgrav 		const ldns_output_format *fmt,
500*7b5038d7SDag-Erling Smørgrav 		ldns_dnssec_trust_tree *tree,
501*7b5038d7SDag-Erling Smørgrav 		size_t tabs,
502*7b5038d7SDag-Erling Smørgrav 		bool extended,
503*7b5038d7SDag-Erling Smørgrav 		uint8_t *sibmap,
504*7b5038d7SDag-Erling Smørgrav 		size_t treedepth)
505*7b5038d7SDag-Erling Smørgrav {
506*7b5038d7SDag-Erling Smørgrav 	size_t i;
507*7b5038d7SDag-Erling Smørgrav 	const ldns_rr_descriptor *descriptor;
508*7b5038d7SDag-Erling Smørgrav 	bool mapset = false;
509*7b5038d7SDag-Erling Smørgrav 
510*7b5038d7SDag-Erling Smørgrav 	if (!sibmap) {
511*7b5038d7SDag-Erling Smørgrav 		treedepth = ldns_dnssec_trust_tree_depth(tree);
512*7b5038d7SDag-Erling Smørgrav 		sibmap = LDNS_XMALLOC(uint8_t, treedepth);
513*7b5038d7SDag-Erling Smørgrav                 if(!sibmap)
514*7b5038d7SDag-Erling Smørgrav                         return; /* mem err */
515*7b5038d7SDag-Erling Smørgrav 		memset(sibmap, 0, treedepth);
516*7b5038d7SDag-Erling Smørgrav 		mapset = true;
517*7b5038d7SDag-Erling Smørgrav 	}
518*7b5038d7SDag-Erling Smørgrav 
519*7b5038d7SDag-Erling Smørgrav 	if (tree) {
520*7b5038d7SDag-Erling Smørgrav 		if (tree->rr) {
521*7b5038d7SDag-Erling Smørgrav 			print_tabs(out, tabs, sibmap, treedepth);
522*7b5038d7SDag-Erling Smørgrav 			ldns_rdf_print(out, ldns_rr_owner(tree->rr));
523*7b5038d7SDag-Erling Smørgrav 			descriptor = ldns_rr_descript(ldns_rr_get_type(tree->rr));
524*7b5038d7SDag-Erling Smørgrav 
525*7b5038d7SDag-Erling Smørgrav 			if (descriptor->_name) {
526*7b5038d7SDag-Erling Smørgrav 				fprintf(out, " (%s", descriptor->_name);
527*7b5038d7SDag-Erling Smørgrav 			} else {
528*7b5038d7SDag-Erling Smørgrav 				fprintf(out, " (TYPE%d",
529*7b5038d7SDag-Erling Smørgrav 					   ldns_rr_get_type(tree->rr));
530*7b5038d7SDag-Erling Smørgrav 			}
531*7b5038d7SDag-Erling Smørgrav 			if (tabs > 0) {
532*7b5038d7SDag-Erling Smørgrav 				if (ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_DNSKEY) {
533*7b5038d7SDag-Erling Smørgrav 					fprintf(out, " keytag: %u",
534*7b5038d7SDag-Erling Smørgrav 					        (unsigned int) ldns_calc_keytag(tree->rr));
535*7b5038d7SDag-Erling Smørgrav 					fprintf(out, " alg: ");
536*7b5038d7SDag-Erling Smørgrav 					ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 2));
537*7b5038d7SDag-Erling Smørgrav 					fprintf(out, " flags: ");
538*7b5038d7SDag-Erling Smørgrav 					ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 0));
539*7b5038d7SDag-Erling Smørgrav 				} else if (ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_DS) {
540*7b5038d7SDag-Erling Smørgrav 					fprintf(out, " keytag: ");
541*7b5038d7SDag-Erling Smørgrav 					ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 0));
542*7b5038d7SDag-Erling Smørgrav 					fprintf(out, " digest type: ");
543*7b5038d7SDag-Erling Smørgrav 					ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 2));
544*7b5038d7SDag-Erling Smørgrav 				}
545*7b5038d7SDag-Erling Smørgrav 				if (ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_NSEC) {
546*7b5038d7SDag-Erling Smørgrav 					fprintf(out, " ");
547*7b5038d7SDag-Erling Smørgrav 					ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 0));
548*7b5038d7SDag-Erling Smørgrav 					fprintf(out, " ");
549*7b5038d7SDag-Erling Smørgrav 					ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 1));
550*7b5038d7SDag-Erling Smørgrav 				}
551*7b5038d7SDag-Erling Smørgrav 			}
552*7b5038d7SDag-Erling Smørgrav 
553*7b5038d7SDag-Erling Smørgrav 			fprintf(out, ")\n");
554*7b5038d7SDag-Erling Smørgrav 			for (i = 0; i < tree->parent_count; i++) {
555*7b5038d7SDag-Erling Smørgrav 				if (tree->parent_count > 1 && i < tree->parent_count - 1) {
556*7b5038d7SDag-Erling Smørgrav 					sibmap[tabs] = 1;
557*7b5038d7SDag-Erling Smørgrav 				} else {
558*7b5038d7SDag-Erling Smørgrav 					sibmap[tabs] = 0;
559*7b5038d7SDag-Erling Smørgrav 				}
560*7b5038d7SDag-Erling Smørgrav 				/* only print errors */
561*7b5038d7SDag-Erling Smørgrav 				if (ldns_rr_get_type(tree->parents[i]->rr) ==
562*7b5038d7SDag-Erling Smørgrav 				    LDNS_RR_TYPE_NSEC ||
563*7b5038d7SDag-Erling Smørgrav 				    ldns_rr_get_type(tree->parents[i]->rr) ==
564*7b5038d7SDag-Erling Smørgrav 				    LDNS_RR_TYPE_NSEC3) {
565*7b5038d7SDag-Erling Smørgrav 					if (tree->parent_status[i] == LDNS_STATUS_OK) {
566*7b5038d7SDag-Erling Smørgrav 						print_tabs(out, tabs + 1, sibmap, treedepth);
567*7b5038d7SDag-Erling Smørgrav 						if (tabs == 0 &&
568*7b5038d7SDag-Erling Smørgrav 						    ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_NS &&
569*7b5038d7SDag-Erling Smørgrav 							ldns_rr_rd_count(tree->rr) > 0) {
570*7b5038d7SDag-Erling Smørgrav 							fprintf(out, "Existence of DS is denied by:\n");
571*7b5038d7SDag-Erling Smørgrav 						} else {
572*7b5038d7SDag-Erling Smørgrav 							fprintf(out, "Existence is denied by:\n");
573*7b5038d7SDag-Erling Smørgrav 						}
574*7b5038d7SDag-Erling Smørgrav 					} else {
575*7b5038d7SDag-Erling Smørgrav 						/* NS records aren't signed */
576*7b5038d7SDag-Erling Smørgrav 						if (ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_NS) {
577*7b5038d7SDag-Erling Smørgrav 							fprintf(out, "Existence of DS is denied by:\n");
578*7b5038d7SDag-Erling Smørgrav 						} else {
579*7b5038d7SDag-Erling Smørgrav 							print_tabs(out, tabs + 1, sibmap, treedepth);
580*7b5038d7SDag-Erling Smørgrav 							fprintf(out,
581*7b5038d7SDag-Erling Smørgrav 								   "Error in denial of existence: %s\n",
582*7b5038d7SDag-Erling Smørgrav 								   ldns_get_errorstr_by_id(
583*7b5038d7SDag-Erling Smørgrav 									   tree->parent_status[i]));
584*7b5038d7SDag-Erling Smørgrav 						}
585*7b5038d7SDag-Erling Smørgrav 					}
586*7b5038d7SDag-Erling Smørgrav 				} else
587*7b5038d7SDag-Erling Smørgrav 					if (tree->parent_status[i] != LDNS_STATUS_OK) {
588*7b5038d7SDag-Erling Smørgrav 						print_tabs(out, tabs + 1, sibmap, treedepth);
589*7b5038d7SDag-Erling Smørgrav 						fprintf(out,
590*7b5038d7SDag-Erling Smørgrav 							   "%s:\n",
591*7b5038d7SDag-Erling Smørgrav 							   ldns_get_errorstr_by_id(
592*7b5038d7SDag-Erling Smørgrav 							       tree->parent_status[i]));
593*7b5038d7SDag-Erling Smørgrav 						if (tree->parent_status[i]
594*7b5038d7SDag-Erling Smørgrav 						    == LDNS_STATUS_SSL_ERR) {
595*7b5038d7SDag-Erling Smørgrav 							printf("; SSL Error: ");
596*7b5038d7SDag-Erling Smørgrav 							ERR_load_crypto_strings();
597*7b5038d7SDag-Erling Smørgrav 							ERR_print_errors_fp(stdout);
598*7b5038d7SDag-Erling Smørgrav 							printf("\n");
599*7b5038d7SDag-Erling Smørgrav 						}
600*7b5038d7SDag-Erling Smørgrav 						ldns_rr_print_fmt(out, fmt,
601*7b5038d7SDag-Erling Smørgrav 							tree->
602*7b5038d7SDag-Erling Smørgrav 							parent_signature[i]);
603*7b5038d7SDag-Erling Smørgrav 						printf("For RRset:\n");
604*7b5038d7SDag-Erling Smørgrav 						ldns_rr_list_print_fmt(out, fmt,
605*7b5038d7SDag-Erling Smørgrav 								tree->rrset);
606*7b5038d7SDag-Erling Smørgrav 						printf("With key:\n");
607*7b5038d7SDag-Erling Smørgrav 						ldns_rr_print_fmt(out, fmt,
608*7b5038d7SDag-Erling Smørgrav 							tree->parents[i]->rr);
609*7b5038d7SDag-Erling Smørgrav 					}
610*7b5038d7SDag-Erling Smørgrav 				ldns_dnssec_trust_tree_print_sm_fmt(out, fmt,
611*7b5038d7SDag-Erling Smørgrav 						tree->parents[i],
612*7b5038d7SDag-Erling Smørgrav 						tabs+1,
613*7b5038d7SDag-Erling Smørgrav 						extended,
614*7b5038d7SDag-Erling Smørgrav 						sibmap,
615*7b5038d7SDag-Erling Smørgrav 						treedepth);
616*7b5038d7SDag-Erling Smørgrav 			}
617*7b5038d7SDag-Erling Smørgrav 		} else {
618*7b5038d7SDag-Erling Smørgrav 			print_tabs(out, tabs, sibmap, treedepth);
619*7b5038d7SDag-Erling Smørgrav 			fprintf(out, "<no data>\n");
620*7b5038d7SDag-Erling Smørgrav 		}
621*7b5038d7SDag-Erling Smørgrav 	} else {
622*7b5038d7SDag-Erling Smørgrav 		fprintf(out, "<null pointer>\n");
623*7b5038d7SDag-Erling Smørgrav 	}
624*7b5038d7SDag-Erling Smørgrav 
625*7b5038d7SDag-Erling Smørgrav 	if (mapset) {
626*7b5038d7SDag-Erling Smørgrav 		LDNS_FREE(sibmap);
627*7b5038d7SDag-Erling Smørgrav 	}
628*7b5038d7SDag-Erling Smørgrav }
629*7b5038d7SDag-Erling Smørgrav 
630*7b5038d7SDag-Erling Smørgrav static void
631*7b5038d7SDag-Erling Smørgrav ldns_dnssec_trust_tree_print_sm(FILE *out,
632*7b5038d7SDag-Erling Smørgrav 		ldns_dnssec_trust_tree *tree,
633*7b5038d7SDag-Erling Smørgrav 		size_t tabs,
634*7b5038d7SDag-Erling Smørgrav 		bool extended,
635*7b5038d7SDag-Erling Smørgrav 		uint8_t *sibmap,
636*7b5038d7SDag-Erling Smørgrav 		size_t treedepth)
637*7b5038d7SDag-Erling Smørgrav {
638*7b5038d7SDag-Erling Smørgrav 	ldns_dnssec_trust_tree_print_sm_fmt(out, ldns_output_format_default,
639*7b5038d7SDag-Erling Smørgrav 			tree, tabs, extended, sibmap, treedepth);
640*7b5038d7SDag-Erling Smørgrav }
641*7b5038d7SDag-Erling Smørgrav 
642*7b5038d7SDag-Erling Smørgrav void
643*7b5038d7SDag-Erling Smørgrav ldns_dnssec_trust_tree_print_fmt(FILE *out, const ldns_output_format *fmt,
644*7b5038d7SDag-Erling Smørgrav 		ldns_dnssec_trust_tree *tree,
645*7b5038d7SDag-Erling Smørgrav 		size_t tabs,
646*7b5038d7SDag-Erling Smørgrav 		bool extended)
647*7b5038d7SDag-Erling Smørgrav {
648*7b5038d7SDag-Erling Smørgrav 	ldns_dnssec_trust_tree_print_sm_fmt(out, fmt,
649*7b5038d7SDag-Erling Smørgrav 			tree, tabs, extended, NULL, 0);
650*7b5038d7SDag-Erling Smørgrav }
651*7b5038d7SDag-Erling Smørgrav 
652*7b5038d7SDag-Erling Smørgrav void
653*7b5038d7SDag-Erling Smørgrav ldns_dnssec_trust_tree_print(FILE *out,
654*7b5038d7SDag-Erling Smørgrav 		ldns_dnssec_trust_tree *tree,
655*7b5038d7SDag-Erling Smørgrav 		size_t tabs,
656*7b5038d7SDag-Erling Smørgrav 		bool extended)
657*7b5038d7SDag-Erling Smørgrav {
658*7b5038d7SDag-Erling Smørgrav 	ldns_dnssec_trust_tree_print_fmt(out, ldns_output_format_default,
659*7b5038d7SDag-Erling Smørgrav 			tree, tabs, extended);
660*7b5038d7SDag-Erling Smørgrav }
661*7b5038d7SDag-Erling Smørgrav 
662*7b5038d7SDag-Erling Smørgrav 
663*7b5038d7SDag-Erling Smørgrav ldns_status
664*7b5038d7SDag-Erling Smørgrav ldns_dnssec_trust_tree_add_parent(ldns_dnssec_trust_tree *tree,
665*7b5038d7SDag-Erling Smørgrav                                   const ldns_dnssec_trust_tree *parent,
666*7b5038d7SDag-Erling Smørgrav                                   const ldns_rr *signature,
667*7b5038d7SDag-Erling Smørgrav                                   const ldns_status parent_status)
668*7b5038d7SDag-Erling Smørgrav {
669*7b5038d7SDag-Erling Smørgrav 	if (tree
670*7b5038d7SDag-Erling Smørgrav 	    && parent
671*7b5038d7SDag-Erling Smørgrav 	    && tree->parent_count < LDNS_DNSSEC_TRUST_TREE_MAX_PARENTS) {
672*7b5038d7SDag-Erling Smørgrav 		/*
673*7b5038d7SDag-Erling Smørgrav 		  printf("Add parent for: ");
674*7b5038d7SDag-Erling Smørgrav 		  ldns_rr_print(stdout, tree->rr);
675*7b5038d7SDag-Erling Smørgrav 		  printf("parent: ");
676*7b5038d7SDag-Erling Smørgrav 		  ldns_rr_print(stdout, parent->rr);
677*7b5038d7SDag-Erling Smørgrav 		*/
678*7b5038d7SDag-Erling Smørgrav 		tree->parents[tree->parent_count] =
679*7b5038d7SDag-Erling Smørgrav 			(ldns_dnssec_trust_tree *) parent;
680*7b5038d7SDag-Erling Smørgrav 		tree->parent_status[tree->parent_count] = parent_status;
681*7b5038d7SDag-Erling Smørgrav 		tree->parent_signature[tree->parent_count] = (ldns_rr *) signature;
682*7b5038d7SDag-Erling Smørgrav 		tree->parent_count++;
683*7b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_OK;
684*7b5038d7SDag-Erling Smørgrav 	} else {
685*7b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_ERR;
686*7b5038d7SDag-Erling Smørgrav 	}
687*7b5038d7SDag-Erling Smørgrav }
688*7b5038d7SDag-Erling Smørgrav 
689*7b5038d7SDag-Erling Smørgrav /* if rr is null, take the first from the rrset */
690*7b5038d7SDag-Erling Smørgrav ldns_dnssec_trust_tree *
691*7b5038d7SDag-Erling Smørgrav ldns_dnssec_derive_trust_tree_time(
692*7b5038d7SDag-Erling Smørgrav 		ldns_dnssec_data_chain *data_chain,
693*7b5038d7SDag-Erling Smørgrav 		ldns_rr *rr,
694*7b5038d7SDag-Erling Smørgrav 		time_t check_time
695*7b5038d7SDag-Erling Smørgrav 		)
696*7b5038d7SDag-Erling Smørgrav {
697*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list *cur_rrset;
698*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list *cur_sigs;
699*7b5038d7SDag-Erling Smørgrav 	ldns_rr *cur_rr = NULL;
700*7b5038d7SDag-Erling Smørgrav 	ldns_rr *cur_sig_rr;
701*7b5038d7SDag-Erling Smørgrav 	size_t i, j;
702*7b5038d7SDag-Erling Smørgrav 
703*7b5038d7SDag-Erling Smørgrav 	ldns_dnssec_trust_tree *new_tree = ldns_dnssec_trust_tree_new();
704*7b5038d7SDag-Erling Smørgrav         if(!new_tree)
705*7b5038d7SDag-Erling Smørgrav                 return NULL;
706*7b5038d7SDag-Erling Smørgrav 
707*7b5038d7SDag-Erling Smørgrav 	if (data_chain && data_chain->rrset) {
708*7b5038d7SDag-Erling Smørgrav 		cur_rrset = data_chain->rrset;
709*7b5038d7SDag-Erling Smørgrav 
710*7b5038d7SDag-Erling Smørgrav 		cur_sigs = data_chain->signatures;
711*7b5038d7SDag-Erling Smørgrav 
712*7b5038d7SDag-Erling Smørgrav 		if (rr) {
713*7b5038d7SDag-Erling Smørgrav 			cur_rr = rr;
714*7b5038d7SDag-Erling Smørgrav 		}
715*7b5038d7SDag-Erling Smørgrav 
716*7b5038d7SDag-Erling Smørgrav 		if (!cur_rr && ldns_rr_list_rr_count(cur_rrset) > 0) {
717*7b5038d7SDag-Erling Smørgrav 			cur_rr = ldns_rr_list_rr(cur_rrset, 0);
718*7b5038d7SDag-Erling Smørgrav 		}
719*7b5038d7SDag-Erling Smørgrav 
720*7b5038d7SDag-Erling Smørgrav 		if (cur_rr) {
721*7b5038d7SDag-Erling Smørgrav 			new_tree->rr = cur_rr;
722*7b5038d7SDag-Erling Smørgrav 			new_tree->rrset = cur_rrset;
723*7b5038d7SDag-Erling Smørgrav 			/* there are three possibilities:
724*7b5038d7SDag-Erling Smørgrav 			   1 - 'normal' rrset, signed by a key
725*7b5038d7SDag-Erling Smørgrav 			   2 - dnskey signed by other dnskey
726*7b5038d7SDag-Erling Smørgrav 			   3 - dnskey proven by higher level DS
727*7b5038d7SDag-Erling Smørgrav 			   (data denied by nsec is a special case that can
728*7b5038d7SDag-Erling Smørgrav 			   occur in multiple places)
729*7b5038d7SDag-Erling Smørgrav 
730*7b5038d7SDag-Erling Smørgrav 			*/
731*7b5038d7SDag-Erling Smørgrav 			if (cur_sigs) {
732*7b5038d7SDag-Erling Smørgrav 				for (i = 0; i < ldns_rr_list_rr_count(cur_sigs); i++) {
733*7b5038d7SDag-Erling Smørgrav 					/* find the appropriate key in the parent list */
734*7b5038d7SDag-Erling Smørgrav 					cur_sig_rr = ldns_rr_list_rr(cur_sigs, i);
735*7b5038d7SDag-Erling Smørgrav 
736*7b5038d7SDag-Erling Smørgrav 					if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_NSEC) {
737*7b5038d7SDag-Erling Smørgrav 						if (ldns_dname_compare(ldns_rr_owner(cur_sig_rr),
738*7b5038d7SDag-Erling Smørgrav 										   ldns_rr_owner(cur_rr)))
739*7b5038d7SDag-Erling Smørgrav 							{
740*7b5038d7SDag-Erling Smørgrav 								/* find first that does match */
741*7b5038d7SDag-Erling Smørgrav 
742*7b5038d7SDag-Erling Smørgrav 								for (j = 0;
743*7b5038d7SDag-Erling Smørgrav 								     j < ldns_rr_list_rr_count(cur_rrset) &&
744*7b5038d7SDag-Erling Smørgrav 										ldns_dname_compare(ldns_rr_owner(cur_sig_rr),ldns_rr_owner(cur_rr)) != 0;
745*7b5038d7SDag-Erling Smørgrav 								     j++) {
746*7b5038d7SDag-Erling Smørgrav 									cur_rr = ldns_rr_list_rr(cur_rrset, j);
747*7b5038d7SDag-Erling Smørgrav 
748*7b5038d7SDag-Erling Smørgrav 								}
749*7b5038d7SDag-Erling Smørgrav 								if (ldns_dname_compare(ldns_rr_owner(cur_sig_rr),
750*7b5038d7SDag-Erling Smørgrav 												   ldns_rr_owner(cur_rr)))
751*7b5038d7SDag-Erling Smørgrav 									{
752*7b5038d7SDag-Erling Smørgrav 										break;
753*7b5038d7SDag-Erling Smørgrav 									}
754*7b5038d7SDag-Erling Smørgrav 							}
755*7b5038d7SDag-Erling Smørgrav 
756*7b5038d7SDag-Erling Smørgrav 					}
757*7b5038d7SDag-Erling Smørgrav 					/* option 1 */
758*7b5038d7SDag-Erling Smørgrav 					if (data_chain->parent) {
759*7b5038d7SDag-Erling Smørgrav 						ldns_dnssec_derive_trust_tree_normal_rrset_time(
760*7b5038d7SDag-Erling Smørgrav 						    new_tree,
761*7b5038d7SDag-Erling Smørgrav 						    data_chain,
762*7b5038d7SDag-Erling Smørgrav 						    cur_sig_rr,
763*7b5038d7SDag-Erling Smørgrav 						    check_time);
764*7b5038d7SDag-Erling Smørgrav 					}
765*7b5038d7SDag-Erling Smørgrav 
766*7b5038d7SDag-Erling Smørgrav 					/* option 2 */
767*7b5038d7SDag-Erling Smørgrav 					ldns_dnssec_derive_trust_tree_dnskey_rrset_time(
768*7b5038d7SDag-Erling Smørgrav 					    new_tree,
769*7b5038d7SDag-Erling Smørgrav 					    data_chain,
770*7b5038d7SDag-Erling Smørgrav 					    cur_rr,
771*7b5038d7SDag-Erling Smørgrav 					    cur_sig_rr,
772*7b5038d7SDag-Erling Smørgrav 					    check_time);
773*7b5038d7SDag-Erling Smørgrav 				}
774*7b5038d7SDag-Erling Smørgrav 
775*7b5038d7SDag-Erling Smørgrav 				ldns_dnssec_derive_trust_tree_ds_rrset_time(
776*7b5038d7SDag-Erling Smørgrav 						new_tree, data_chain,
777*7b5038d7SDag-Erling Smørgrav 						cur_rr, check_time);
778*7b5038d7SDag-Erling Smørgrav 			} else {
779*7b5038d7SDag-Erling Smørgrav 				/* no signatures? maybe it's nsec data */
780*7b5038d7SDag-Erling Smørgrav 
781*7b5038d7SDag-Erling Smørgrav 				/* just add every rr from parent as new parent */
782*7b5038d7SDag-Erling Smørgrav 				ldns_dnssec_derive_trust_tree_no_sig_time(
783*7b5038d7SDag-Erling Smørgrav 					new_tree, data_chain, check_time);
784*7b5038d7SDag-Erling Smørgrav 			}
785*7b5038d7SDag-Erling Smørgrav 		}
786*7b5038d7SDag-Erling Smørgrav 	}
787*7b5038d7SDag-Erling Smørgrav 
788*7b5038d7SDag-Erling Smørgrav 	return new_tree;
789*7b5038d7SDag-Erling Smørgrav }
790*7b5038d7SDag-Erling Smørgrav 
791*7b5038d7SDag-Erling Smørgrav ldns_dnssec_trust_tree *
792*7b5038d7SDag-Erling Smørgrav ldns_dnssec_derive_trust_tree(ldns_dnssec_data_chain *data_chain, ldns_rr *rr)
793*7b5038d7SDag-Erling Smørgrav {
794*7b5038d7SDag-Erling Smørgrav 	return ldns_dnssec_derive_trust_tree_time(data_chain, rr, ldns_time(NULL));
795*7b5038d7SDag-Erling Smørgrav }
796*7b5038d7SDag-Erling Smørgrav 
797*7b5038d7SDag-Erling Smørgrav void
798*7b5038d7SDag-Erling Smørgrav ldns_dnssec_derive_trust_tree_normal_rrset_time(
799*7b5038d7SDag-Erling Smørgrav 		ldns_dnssec_trust_tree *new_tree,
800*7b5038d7SDag-Erling Smørgrav 		ldns_dnssec_data_chain *data_chain,
801*7b5038d7SDag-Erling Smørgrav 		ldns_rr *cur_sig_rr,
802*7b5038d7SDag-Erling Smørgrav 		time_t check_time)
803*7b5038d7SDag-Erling Smørgrav {
804*7b5038d7SDag-Erling Smørgrav 	size_t i, j;
805*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list *cur_rrset = ldns_rr_list_clone(data_chain->rrset);
806*7b5038d7SDag-Erling Smørgrav 	ldns_dnssec_trust_tree *cur_parent_tree;
807*7b5038d7SDag-Erling Smørgrav 	ldns_rr *cur_parent_rr;
808*7b5038d7SDag-Erling Smørgrav 	uint16_t cur_keytag;
809*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list *tmp_rrset = NULL;
810*7b5038d7SDag-Erling Smørgrav 	ldns_status cur_status;
811*7b5038d7SDag-Erling Smørgrav 
812*7b5038d7SDag-Erling Smørgrav 	cur_keytag = ldns_rdf2native_int16(ldns_rr_rrsig_keytag(cur_sig_rr));
813*7b5038d7SDag-Erling Smørgrav 
814*7b5038d7SDag-Erling Smørgrav 	for (j = 0; j < ldns_rr_list_rr_count(data_chain->parent->rrset); j++) {
815*7b5038d7SDag-Erling Smørgrav 		cur_parent_rr = ldns_rr_list_rr(data_chain->parent->rrset, j);
816*7b5038d7SDag-Erling Smørgrav 		if (ldns_rr_get_type(cur_parent_rr) == LDNS_RR_TYPE_DNSKEY) {
817*7b5038d7SDag-Erling Smørgrav 			if (ldns_calc_keytag(cur_parent_rr) == cur_keytag) {
818*7b5038d7SDag-Erling Smørgrav 
819*7b5038d7SDag-Erling Smørgrav 				/* TODO: check wildcard nsec too */
820*7b5038d7SDag-Erling Smørgrav 				if (cur_rrset && ldns_rr_list_rr_count(cur_rrset) > 0) {
821*7b5038d7SDag-Erling Smørgrav 					tmp_rrset = cur_rrset;
822*7b5038d7SDag-Erling Smørgrav 					if (ldns_rr_get_type(ldns_rr_list_rr(cur_rrset, 0))
823*7b5038d7SDag-Erling Smørgrav 					    == LDNS_RR_TYPE_NSEC ||
824*7b5038d7SDag-Erling Smørgrav 					    ldns_rr_get_type(ldns_rr_list_rr(cur_rrset, 0))
825*7b5038d7SDag-Erling Smørgrav 					    == LDNS_RR_TYPE_NSEC3) {
826*7b5038d7SDag-Erling Smørgrav 						/* might contain different names!
827*7b5038d7SDag-Erling Smørgrav 						   sort and split */
828*7b5038d7SDag-Erling Smørgrav 						ldns_rr_list_sort(cur_rrset);
829*7b5038d7SDag-Erling Smørgrav 						if (tmp_rrset && tmp_rrset != cur_rrset) {
830*7b5038d7SDag-Erling Smørgrav 							ldns_rr_list_deep_free(tmp_rrset);
831*7b5038d7SDag-Erling Smørgrav 							tmp_rrset = NULL;
832*7b5038d7SDag-Erling Smørgrav 						}
833*7b5038d7SDag-Erling Smørgrav 						tmp_rrset = ldns_rr_list_pop_rrset(cur_rrset);
834*7b5038d7SDag-Erling Smørgrav 
835*7b5038d7SDag-Erling Smørgrav 						/* with nsecs, this might be the wrong one */
836*7b5038d7SDag-Erling Smørgrav 						while (tmp_rrset &&
837*7b5038d7SDag-Erling Smørgrav 						       ldns_rr_list_rr_count(cur_rrset) > 0 &&
838*7b5038d7SDag-Erling Smørgrav 						       ldns_dname_compare(
839*7b5038d7SDag-Erling Smørgrav 								ldns_rr_owner(ldns_rr_list_rr(
840*7b5038d7SDag-Erling Smørgrav 										        tmp_rrset, 0)),
841*7b5038d7SDag-Erling Smørgrav 								ldns_rr_owner(cur_sig_rr)) != 0) {
842*7b5038d7SDag-Erling Smørgrav 							ldns_rr_list_deep_free(tmp_rrset);
843*7b5038d7SDag-Erling Smørgrav 							tmp_rrset =
844*7b5038d7SDag-Erling Smørgrav 								ldns_rr_list_pop_rrset(cur_rrset);
845*7b5038d7SDag-Erling Smørgrav 						}
846*7b5038d7SDag-Erling Smørgrav 					}
847*7b5038d7SDag-Erling Smørgrav 					cur_status = ldns_verify_rrsig_time(
848*7b5038d7SDag-Erling Smørgrav 							tmp_rrset,
849*7b5038d7SDag-Erling Smørgrav 							cur_sig_rr,
850*7b5038d7SDag-Erling Smørgrav 							cur_parent_rr,
851*7b5038d7SDag-Erling Smørgrav 							check_time);
852*7b5038d7SDag-Erling Smørgrav 					/* avoid dupes */
853*7b5038d7SDag-Erling Smørgrav 					for (i = 0; i < new_tree->parent_count; i++) {
854*7b5038d7SDag-Erling Smørgrav 						if (cur_parent_rr == new_tree->parents[i]->rr) {
855*7b5038d7SDag-Erling Smørgrav 							goto done;
856*7b5038d7SDag-Erling Smørgrav 						}
857*7b5038d7SDag-Erling Smørgrav 					}
858*7b5038d7SDag-Erling Smørgrav 
859*7b5038d7SDag-Erling Smørgrav 					cur_parent_tree =
860*7b5038d7SDag-Erling Smørgrav 						ldns_dnssec_derive_trust_tree_time(
861*7b5038d7SDag-Erling Smørgrav 								data_chain->parent,
862*7b5038d7SDag-Erling Smørgrav 						                cur_parent_rr,
863*7b5038d7SDag-Erling Smørgrav 								check_time);
864*7b5038d7SDag-Erling Smørgrav 					(void)ldns_dnssec_trust_tree_add_parent(new_tree,
865*7b5038d7SDag-Erling Smørgrav 					           cur_parent_tree,
866*7b5038d7SDag-Erling Smørgrav 					           cur_sig_rr,
867*7b5038d7SDag-Erling Smørgrav 					           cur_status);
868*7b5038d7SDag-Erling Smørgrav 				}
869*7b5038d7SDag-Erling Smørgrav 			}
870*7b5038d7SDag-Erling Smørgrav 		}
871*7b5038d7SDag-Erling Smørgrav 	}
872*7b5038d7SDag-Erling Smørgrav  done:
873*7b5038d7SDag-Erling Smørgrav 	if (tmp_rrset && tmp_rrset != cur_rrset) {
874*7b5038d7SDag-Erling Smørgrav 		ldns_rr_list_deep_free(tmp_rrset);
875*7b5038d7SDag-Erling Smørgrav 	}
876*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list_deep_free(cur_rrset);
877*7b5038d7SDag-Erling Smørgrav }
878*7b5038d7SDag-Erling Smørgrav 
879*7b5038d7SDag-Erling Smørgrav void
880*7b5038d7SDag-Erling Smørgrav ldns_dnssec_derive_trust_tree_normal_rrset(ldns_dnssec_trust_tree *new_tree,
881*7b5038d7SDag-Erling Smørgrav                                            ldns_dnssec_data_chain *data_chain,
882*7b5038d7SDag-Erling Smørgrav                                            ldns_rr *cur_sig_rr)
883*7b5038d7SDag-Erling Smørgrav {
884*7b5038d7SDag-Erling Smørgrav 	ldns_dnssec_derive_trust_tree_normal_rrset_time(
885*7b5038d7SDag-Erling Smørgrav 			new_tree, data_chain, cur_sig_rr, ldns_time(NULL));
886*7b5038d7SDag-Erling Smørgrav }
887*7b5038d7SDag-Erling Smørgrav 
888*7b5038d7SDag-Erling Smørgrav void
889*7b5038d7SDag-Erling Smørgrav ldns_dnssec_derive_trust_tree_dnskey_rrset_time(
890*7b5038d7SDag-Erling Smørgrav 		ldns_dnssec_trust_tree *new_tree,
891*7b5038d7SDag-Erling Smørgrav 		ldns_dnssec_data_chain *data_chain,
892*7b5038d7SDag-Erling Smørgrav 		ldns_rr *cur_rr,
893*7b5038d7SDag-Erling Smørgrav 		ldns_rr *cur_sig_rr,
894*7b5038d7SDag-Erling Smørgrav 		time_t check_time)
895*7b5038d7SDag-Erling Smørgrav {
896*7b5038d7SDag-Erling Smørgrav 	size_t j;
897*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list *cur_rrset = data_chain->rrset;
898*7b5038d7SDag-Erling Smørgrav 	ldns_dnssec_trust_tree *cur_parent_tree;
899*7b5038d7SDag-Erling Smørgrav 	ldns_rr *cur_parent_rr;
900*7b5038d7SDag-Erling Smørgrav 	uint16_t cur_keytag;
901*7b5038d7SDag-Erling Smørgrav 	ldns_status cur_status;
902*7b5038d7SDag-Erling Smørgrav 
903*7b5038d7SDag-Erling Smørgrav 	cur_keytag = ldns_rdf2native_int16(ldns_rr_rrsig_keytag(cur_sig_rr));
904*7b5038d7SDag-Erling Smørgrav 
905*7b5038d7SDag-Erling Smørgrav 	for (j = 0; j < ldns_rr_list_rr_count(cur_rrset); j++) {
906*7b5038d7SDag-Erling Smørgrav 		cur_parent_rr = ldns_rr_list_rr(cur_rrset, j);
907*7b5038d7SDag-Erling Smørgrav 		if (cur_parent_rr != cur_rr &&
908*7b5038d7SDag-Erling Smørgrav 		    ldns_rr_get_type(cur_parent_rr) == LDNS_RR_TYPE_DNSKEY) {
909*7b5038d7SDag-Erling Smørgrav 			if (ldns_calc_keytag(cur_parent_rr) == cur_keytag
910*7b5038d7SDag-Erling Smørgrav 			    ) {
911*7b5038d7SDag-Erling Smørgrav 				cur_parent_tree = ldns_dnssec_trust_tree_new();
912*7b5038d7SDag-Erling Smørgrav 				cur_parent_tree->rr = cur_parent_rr;
913*7b5038d7SDag-Erling Smørgrav 				cur_parent_tree->rrset = cur_rrset;
914*7b5038d7SDag-Erling Smørgrav 				cur_status = ldns_verify_rrsig_time(
915*7b5038d7SDag-Erling Smørgrav 						cur_rrset, cur_sig_rr,
916*7b5038d7SDag-Erling Smørgrav 						cur_parent_rr, check_time);
917*7b5038d7SDag-Erling Smørgrav 				(void) ldns_dnssec_trust_tree_add_parent(new_tree,
918*7b5038d7SDag-Erling Smørgrav 				            cur_parent_tree, cur_sig_rr, cur_status);
919*7b5038d7SDag-Erling Smørgrav 			}
920*7b5038d7SDag-Erling Smørgrav 		}
921*7b5038d7SDag-Erling Smørgrav 	}
922*7b5038d7SDag-Erling Smørgrav }
923*7b5038d7SDag-Erling Smørgrav 
924*7b5038d7SDag-Erling Smørgrav void
925*7b5038d7SDag-Erling Smørgrav ldns_dnssec_derive_trust_tree_dnskey_rrset(ldns_dnssec_trust_tree *new_tree,
926*7b5038d7SDag-Erling Smørgrav                                            ldns_dnssec_data_chain *data_chain,
927*7b5038d7SDag-Erling Smørgrav                                            ldns_rr *cur_rr,
928*7b5038d7SDag-Erling Smørgrav                                            ldns_rr *cur_sig_rr)
929*7b5038d7SDag-Erling Smørgrav {
930*7b5038d7SDag-Erling Smørgrav 	ldns_dnssec_derive_trust_tree_dnskey_rrset_time(
931*7b5038d7SDag-Erling Smørgrav 			new_tree, data_chain, cur_rr, cur_sig_rr, ldns_time(NULL));
932*7b5038d7SDag-Erling Smørgrav }
933*7b5038d7SDag-Erling Smørgrav 
934*7b5038d7SDag-Erling Smørgrav void
935*7b5038d7SDag-Erling Smørgrav ldns_dnssec_derive_trust_tree_ds_rrset_time(
936*7b5038d7SDag-Erling Smørgrav 		ldns_dnssec_trust_tree *new_tree,
937*7b5038d7SDag-Erling Smørgrav 		ldns_dnssec_data_chain *data_chain,
938*7b5038d7SDag-Erling Smørgrav 		ldns_rr *cur_rr,
939*7b5038d7SDag-Erling Smørgrav 		time_t check_time)
940*7b5038d7SDag-Erling Smørgrav {
941*7b5038d7SDag-Erling Smørgrav 	size_t j, h;
942*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list *cur_rrset = data_chain->rrset;
943*7b5038d7SDag-Erling Smørgrav 	ldns_dnssec_trust_tree *cur_parent_tree;
944*7b5038d7SDag-Erling Smørgrav 	ldns_rr *cur_parent_rr;
945*7b5038d7SDag-Erling Smørgrav 
946*7b5038d7SDag-Erling Smørgrav 	/* try the parent to see whether there are DSs there */
947*7b5038d7SDag-Erling Smørgrav 	if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_DNSKEY &&
948*7b5038d7SDag-Erling Smørgrav 	    data_chain->parent &&
949*7b5038d7SDag-Erling Smørgrav 	    data_chain->parent->rrset
950*7b5038d7SDag-Erling Smørgrav 	    ) {
951*7b5038d7SDag-Erling Smørgrav 		for (j = 0;
952*7b5038d7SDag-Erling Smørgrav 			j < ldns_rr_list_rr_count(data_chain->parent->rrset);
953*7b5038d7SDag-Erling Smørgrav 			j++) {
954*7b5038d7SDag-Erling Smørgrav 			cur_parent_rr = ldns_rr_list_rr(data_chain->parent->rrset, j);
955*7b5038d7SDag-Erling Smørgrav 			if (ldns_rr_get_type(cur_parent_rr) == LDNS_RR_TYPE_DS) {
956*7b5038d7SDag-Erling Smørgrav 				for (h = 0; h < ldns_rr_list_rr_count(cur_rrset); h++) {
957*7b5038d7SDag-Erling Smørgrav 					cur_rr = ldns_rr_list_rr(cur_rrset, h);
958*7b5038d7SDag-Erling Smørgrav 					if (ldns_rr_compare_ds(cur_rr, cur_parent_rr)) {
959*7b5038d7SDag-Erling Smørgrav 						cur_parent_tree =
960*7b5038d7SDag-Erling Smørgrav 							ldns_dnssec_derive_trust_tree_time(
961*7b5038d7SDag-Erling Smørgrav 							    data_chain->parent,
962*7b5038d7SDag-Erling Smørgrav 							    cur_parent_rr,
963*7b5038d7SDag-Erling Smørgrav 							    check_time);
964*7b5038d7SDag-Erling Smørgrav 						(void) ldns_dnssec_trust_tree_add_parent(
965*7b5038d7SDag-Erling Smørgrav 						            new_tree,
966*7b5038d7SDag-Erling Smørgrav 						            cur_parent_tree,
967*7b5038d7SDag-Erling Smørgrav 						            NULL,
968*7b5038d7SDag-Erling Smørgrav 						            LDNS_STATUS_OK);
969*7b5038d7SDag-Erling Smørgrav 					} else {
970*7b5038d7SDag-Erling Smørgrav 						/*ldns_rr_print(stdout, cur_parent_rr);*/
971*7b5038d7SDag-Erling Smørgrav 					}
972*7b5038d7SDag-Erling Smørgrav 				}
973*7b5038d7SDag-Erling Smørgrav 			}
974*7b5038d7SDag-Erling Smørgrav 		}
975*7b5038d7SDag-Erling Smørgrav 	}
976*7b5038d7SDag-Erling Smørgrav }
977*7b5038d7SDag-Erling Smørgrav 
978*7b5038d7SDag-Erling Smørgrav void
979*7b5038d7SDag-Erling Smørgrav ldns_dnssec_derive_trust_tree_ds_rrset(ldns_dnssec_trust_tree *new_tree,
980*7b5038d7SDag-Erling Smørgrav                                        ldns_dnssec_data_chain *data_chain,
981*7b5038d7SDag-Erling Smørgrav                                        ldns_rr *cur_rr)
982*7b5038d7SDag-Erling Smørgrav {
983*7b5038d7SDag-Erling Smørgrav 	ldns_dnssec_derive_trust_tree_ds_rrset_time(
984*7b5038d7SDag-Erling Smørgrav 			new_tree, data_chain, cur_rr, ldns_time(NULL));
985*7b5038d7SDag-Erling Smørgrav }
986*7b5038d7SDag-Erling Smørgrav 
987*7b5038d7SDag-Erling Smørgrav void
988*7b5038d7SDag-Erling Smørgrav ldns_dnssec_derive_trust_tree_no_sig_time(
989*7b5038d7SDag-Erling Smørgrav 		ldns_dnssec_trust_tree *new_tree,
990*7b5038d7SDag-Erling Smørgrav 		ldns_dnssec_data_chain *data_chain,
991*7b5038d7SDag-Erling Smørgrav 		time_t check_time)
992*7b5038d7SDag-Erling Smørgrav {
993*7b5038d7SDag-Erling Smørgrav 	size_t i;
994*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list *cur_rrset;
995*7b5038d7SDag-Erling Smørgrav 	ldns_rr *cur_parent_rr;
996*7b5038d7SDag-Erling Smørgrav 	ldns_dnssec_trust_tree *cur_parent_tree;
997*7b5038d7SDag-Erling Smørgrav 	ldns_status result;
998*7b5038d7SDag-Erling Smørgrav 
999*7b5038d7SDag-Erling Smørgrav 	if (data_chain->parent && data_chain->parent->rrset) {
1000*7b5038d7SDag-Erling Smørgrav 		cur_rrset = data_chain->parent->rrset;
1001*7b5038d7SDag-Erling Smørgrav 		/* nsec? */
1002*7b5038d7SDag-Erling Smørgrav 		if (cur_rrset && ldns_rr_list_rr_count(cur_rrset) > 0) {
1003*7b5038d7SDag-Erling Smørgrav 			if (ldns_rr_get_type(ldns_rr_list_rr(cur_rrset, 0)) ==
1004*7b5038d7SDag-Erling Smørgrav 			    LDNS_RR_TYPE_NSEC3) {
1005*7b5038d7SDag-Erling Smørgrav 				result = ldns_dnssec_verify_denial_nsec3(
1006*7b5038d7SDag-Erling Smørgrav 					        new_tree->rr,
1007*7b5038d7SDag-Erling Smørgrav 						   cur_rrset,
1008*7b5038d7SDag-Erling Smørgrav 						   data_chain->parent->signatures,
1009*7b5038d7SDag-Erling Smørgrav 						   data_chain->packet_rcode,
1010*7b5038d7SDag-Erling Smørgrav 						   data_chain->packet_qtype,
1011*7b5038d7SDag-Erling Smørgrav 						   data_chain->packet_nodata);
1012*7b5038d7SDag-Erling Smørgrav 			} else if (ldns_rr_get_type(ldns_rr_list_rr(cur_rrset, 0)) ==
1013*7b5038d7SDag-Erling Smørgrav 					 LDNS_RR_TYPE_NSEC) {
1014*7b5038d7SDag-Erling Smørgrav 				result = ldns_dnssec_verify_denial(
1015*7b5038d7SDag-Erling Smørgrav 					        new_tree->rr,
1016*7b5038d7SDag-Erling Smørgrav 						   cur_rrset,
1017*7b5038d7SDag-Erling Smørgrav 						   data_chain->parent->signatures);
1018*7b5038d7SDag-Erling Smørgrav 			} else {
1019*7b5038d7SDag-Erling Smørgrav 				/* unsigned zone, unsigned parent */
1020*7b5038d7SDag-Erling Smørgrav 				result = LDNS_STATUS_OK;
1021*7b5038d7SDag-Erling Smørgrav 			}
1022*7b5038d7SDag-Erling Smørgrav 		} else {
1023*7b5038d7SDag-Erling Smørgrav 			result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED;
1024*7b5038d7SDag-Erling Smørgrav 		}
1025*7b5038d7SDag-Erling Smørgrav 		for (i = 0; i < ldns_rr_list_rr_count(cur_rrset); i++) {
1026*7b5038d7SDag-Erling Smørgrav 			cur_parent_rr = ldns_rr_list_rr(cur_rrset, i);
1027*7b5038d7SDag-Erling Smørgrav 			cur_parent_tree =
1028*7b5038d7SDag-Erling Smørgrav 				ldns_dnssec_derive_trust_tree_time(
1029*7b5038d7SDag-Erling Smørgrav 						data_chain->parent,
1030*7b5038d7SDag-Erling Smørgrav 						cur_parent_rr,
1031*7b5038d7SDag-Erling Smørgrav 						check_time);
1032*7b5038d7SDag-Erling Smørgrav 			(void) ldns_dnssec_trust_tree_add_parent(new_tree,
1033*7b5038d7SDag-Erling Smørgrav 			            cur_parent_tree, NULL, result);
1034*7b5038d7SDag-Erling Smørgrav 		}
1035*7b5038d7SDag-Erling Smørgrav 	}
1036*7b5038d7SDag-Erling Smørgrav }
1037*7b5038d7SDag-Erling Smørgrav 
1038*7b5038d7SDag-Erling Smørgrav void
1039*7b5038d7SDag-Erling Smørgrav ldns_dnssec_derive_trust_tree_no_sig(ldns_dnssec_trust_tree *new_tree,
1040*7b5038d7SDag-Erling Smørgrav                                      ldns_dnssec_data_chain *data_chain)
1041*7b5038d7SDag-Erling Smørgrav {
1042*7b5038d7SDag-Erling Smørgrav 	ldns_dnssec_derive_trust_tree_no_sig_time(
1043*7b5038d7SDag-Erling Smørgrav 			new_tree, data_chain, ldns_time(NULL));
1044*7b5038d7SDag-Erling Smørgrav }
1045*7b5038d7SDag-Erling Smørgrav 
1046*7b5038d7SDag-Erling Smørgrav /*
1047*7b5038d7SDag-Erling Smørgrav  * returns OK if there is a path from tree to key with only OK
1048*7b5038d7SDag-Erling Smørgrav  * the (first) error in between otherwise
1049*7b5038d7SDag-Erling Smørgrav  * or NOT_FOUND if the key wasn't present at all
1050*7b5038d7SDag-Erling Smørgrav  */
1051*7b5038d7SDag-Erling Smørgrav ldns_status
1052*7b5038d7SDag-Erling Smørgrav ldns_dnssec_trust_tree_contains_keys(ldns_dnssec_trust_tree *tree,
1053*7b5038d7SDag-Erling Smørgrav 							  ldns_rr_list *trusted_keys)
1054*7b5038d7SDag-Erling Smørgrav {
1055*7b5038d7SDag-Erling Smørgrav 	size_t i;
1056*7b5038d7SDag-Erling Smørgrav 	ldns_status result = LDNS_STATUS_CRYPTO_NO_DNSKEY;
1057*7b5038d7SDag-Erling Smørgrav 	bool equal;
1058*7b5038d7SDag-Erling Smørgrav 	ldns_status parent_result;
1059*7b5038d7SDag-Erling Smørgrav 
1060*7b5038d7SDag-Erling Smørgrav 	if (tree && trusted_keys && ldns_rr_list_rr_count(trusted_keys) > 0)
1061*7b5038d7SDag-Erling Smørgrav 		{ if (tree->rr) {
1062*7b5038d7SDag-Erling Smørgrav 				for (i = 0; i < ldns_rr_list_rr_count(trusted_keys); i++) {
1063*7b5038d7SDag-Erling Smørgrav 					equal = ldns_rr_compare_ds(
1064*7b5038d7SDag-Erling Smørgrav 							  tree->rr,
1065*7b5038d7SDag-Erling Smørgrav 							  ldns_rr_list_rr(trusted_keys, i));
1066*7b5038d7SDag-Erling Smørgrav 					if (equal) {
1067*7b5038d7SDag-Erling Smørgrav 						result = LDNS_STATUS_OK;
1068*7b5038d7SDag-Erling Smørgrav 						return result;
1069*7b5038d7SDag-Erling Smørgrav 					}
1070*7b5038d7SDag-Erling Smørgrav 				}
1071*7b5038d7SDag-Erling Smørgrav 			}
1072*7b5038d7SDag-Erling Smørgrav 			for (i = 0; i < tree->parent_count; i++) {
1073*7b5038d7SDag-Erling Smørgrav 				parent_result =
1074*7b5038d7SDag-Erling Smørgrav 					ldns_dnssec_trust_tree_contains_keys(tree->parents[i],
1075*7b5038d7SDag-Erling Smørgrav 												  trusted_keys);
1076*7b5038d7SDag-Erling Smørgrav 				if (parent_result != LDNS_STATUS_CRYPTO_NO_DNSKEY) {
1077*7b5038d7SDag-Erling Smørgrav 					if (tree->parent_status[i] != LDNS_STATUS_OK) {
1078*7b5038d7SDag-Erling Smørgrav 						result = tree->parent_status[i];
1079*7b5038d7SDag-Erling Smørgrav 					} else {
1080*7b5038d7SDag-Erling Smørgrav 						if (ldns_rr_get_type(tree->rr)
1081*7b5038d7SDag-Erling Smørgrav 						    == LDNS_RR_TYPE_NSEC &&
1082*7b5038d7SDag-Erling Smørgrav 						    parent_result == LDNS_STATUS_OK
1083*7b5038d7SDag-Erling Smørgrav 						    ) {
1084*7b5038d7SDag-Erling Smørgrav 							result =
1085*7b5038d7SDag-Erling Smørgrav 								LDNS_STATUS_DNSSEC_EXISTENCE_DENIED;
1086*7b5038d7SDag-Erling Smørgrav 						} else {
1087*7b5038d7SDag-Erling Smørgrav 							result = parent_result;
1088*7b5038d7SDag-Erling Smørgrav 						}
1089*7b5038d7SDag-Erling Smørgrav 					}
1090*7b5038d7SDag-Erling Smørgrav 				}
1091*7b5038d7SDag-Erling Smørgrav 			}
1092*7b5038d7SDag-Erling Smørgrav 		} else {
1093*7b5038d7SDag-Erling Smørgrav 		result = LDNS_STATUS_ERR;
1094*7b5038d7SDag-Erling Smørgrav 	}
1095*7b5038d7SDag-Erling Smørgrav 
1096*7b5038d7SDag-Erling Smørgrav 	return result;
1097*7b5038d7SDag-Erling Smørgrav }
1098*7b5038d7SDag-Erling Smørgrav 
1099*7b5038d7SDag-Erling Smørgrav ldns_status
1100*7b5038d7SDag-Erling Smørgrav ldns_verify_time(
1101*7b5038d7SDag-Erling Smørgrav 		ldns_rr_list *rrset,
1102*7b5038d7SDag-Erling Smørgrav 		ldns_rr_list *rrsig,
1103*7b5038d7SDag-Erling Smørgrav 		const ldns_rr_list *keys,
1104*7b5038d7SDag-Erling Smørgrav 		time_t check_time,
1105*7b5038d7SDag-Erling Smørgrav 		ldns_rr_list *good_keys
1106*7b5038d7SDag-Erling Smørgrav 		)
1107*7b5038d7SDag-Erling Smørgrav {
1108*7b5038d7SDag-Erling Smørgrav 	uint16_t i;
1109*7b5038d7SDag-Erling Smørgrav 	ldns_status verify_result = LDNS_STATUS_ERR;
1110*7b5038d7SDag-Erling Smørgrav 
1111*7b5038d7SDag-Erling Smørgrav 	if (!rrset || !rrsig || !keys) {
1112*7b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_ERR;
1113*7b5038d7SDag-Erling Smørgrav 	}
1114*7b5038d7SDag-Erling Smørgrav 
1115*7b5038d7SDag-Erling Smørgrav 	if (ldns_rr_list_rr_count(rrset) < 1) {
1116*7b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_ERR;
1117*7b5038d7SDag-Erling Smørgrav 	}
1118*7b5038d7SDag-Erling Smørgrav 
1119*7b5038d7SDag-Erling Smørgrav 	if (ldns_rr_list_rr_count(rrsig) < 1) {
1120*7b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_CRYPTO_NO_RRSIG;
1121*7b5038d7SDag-Erling Smørgrav 	}
1122*7b5038d7SDag-Erling Smørgrav 
1123*7b5038d7SDag-Erling Smørgrav 	if (ldns_rr_list_rr_count(keys) < 1) {
1124*7b5038d7SDag-Erling Smørgrav 		verify_result = LDNS_STATUS_CRYPTO_NO_TRUSTED_DNSKEY;
1125*7b5038d7SDag-Erling Smørgrav 	} else {
1126*7b5038d7SDag-Erling Smørgrav 		for (i = 0; i < ldns_rr_list_rr_count(rrsig); i++) {
1127*7b5038d7SDag-Erling Smørgrav 			ldns_status s = ldns_verify_rrsig_keylist_time(
1128*7b5038d7SDag-Erling Smørgrav 					rrset, ldns_rr_list_rr(rrsig, i),
1129*7b5038d7SDag-Erling Smørgrav 					keys, check_time, good_keys);
1130*7b5038d7SDag-Erling Smørgrav 			/* try a little to get more descriptive error */
1131*7b5038d7SDag-Erling Smørgrav 			if(s == LDNS_STATUS_OK) {
1132*7b5038d7SDag-Erling Smørgrav 				verify_result = LDNS_STATUS_OK;
1133*7b5038d7SDag-Erling Smørgrav 			} else if(verify_result == LDNS_STATUS_ERR)
1134*7b5038d7SDag-Erling Smørgrav 				verify_result = s;
1135*7b5038d7SDag-Erling Smørgrav 			else if(s !=  LDNS_STATUS_ERR && verify_result ==
1136*7b5038d7SDag-Erling Smørgrav 				LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY)
1137*7b5038d7SDag-Erling Smørgrav 				verify_result = s;
1138*7b5038d7SDag-Erling Smørgrav 		}
1139*7b5038d7SDag-Erling Smørgrav 	}
1140*7b5038d7SDag-Erling Smørgrav 	return verify_result;
1141*7b5038d7SDag-Erling Smørgrav }
1142*7b5038d7SDag-Erling Smørgrav 
1143*7b5038d7SDag-Erling Smørgrav ldns_status
1144*7b5038d7SDag-Erling Smørgrav ldns_verify(ldns_rr_list *rrset, ldns_rr_list *rrsig, const ldns_rr_list *keys,
1145*7b5038d7SDag-Erling Smørgrav 		  ldns_rr_list *good_keys)
1146*7b5038d7SDag-Erling Smørgrav {
1147*7b5038d7SDag-Erling Smørgrav 	return ldns_verify_time(rrset, rrsig, keys, ldns_time(NULL), good_keys);
1148*7b5038d7SDag-Erling Smørgrav }
1149*7b5038d7SDag-Erling Smørgrav 
1150*7b5038d7SDag-Erling Smørgrav ldns_status
1151*7b5038d7SDag-Erling Smørgrav ldns_verify_notime(ldns_rr_list *rrset, ldns_rr_list *rrsig,
1152*7b5038d7SDag-Erling Smørgrav 	const ldns_rr_list *keys, ldns_rr_list *good_keys)
1153*7b5038d7SDag-Erling Smørgrav {
1154*7b5038d7SDag-Erling Smørgrav 	uint16_t i;
1155*7b5038d7SDag-Erling Smørgrav 	ldns_status verify_result = LDNS_STATUS_ERR;
1156*7b5038d7SDag-Erling Smørgrav 
1157*7b5038d7SDag-Erling Smørgrav 	if (!rrset || !rrsig || !keys) {
1158*7b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_ERR;
1159*7b5038d7SDag-Erling Smørgrav 	}
1160*7b5038d7SDag-Erling Smørgrav 
1161*7b5038d7SDag-Erling Smørgrav 	if (ldns_rr_list_rr_count(rrset) < 1) {
1162*7b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_ERR;
1163*7b5038d7SDag-Erling Smørgrav 	}
1164*7b5038d7SDag-Erling Smørgrav 
1165*7b5038d7SDag-Erling Smørgrav 	if (ldns_rr_list_rr_count(rrsig) < 1) {
1166*7b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_CRYPTO_NO_RRSIG;
1167*7b5038d7SDag-Erling Smørgrav 	}
1168*7b5038d7SDag-Erling Smørgrav 
1169*7b5038d7SDag-Erling Smørgrav 	if (ldns_rr_list_rr_count(keys) < 1) {
1170*7b5038d7SDag-Erling Smørgrav 		verify_result = LDNS_STATUS_CRYPTO_NO_TRUSTED_DNSKEY;
1171*7b5038d7SDag-Erling Smørgrav 	} else {
1172*7b5038d7SDag-Erling Smørgrav 		for (i = 0; i < ldns_rr_list_rr_count(rrsig); i++) {
1173*7b5038d7SDag-Erling Smørgrav 			ldns_status s = ldns_verify_rrsig_keylist_notime(rrset,
1174*7b5038d7SDag-Erling Smørgrav 				ldns_rr_list_rr(rrsig, i), keys, good_keys);
1175*7b5038d7SDag-Erling Smørgrav 
1176*7b5038d7SDag-Erling Smørgrav 			/* try a little to get more descriptive error */
1177*7b5038d7SDag-Erling Smørgrav 			if (s == LDNS_STATUS_OK) {
1178*7b5038d7SDag-Erling Smørgrav 				verify_result = LDNS_STATUS_OK;
1179*7b5038d7SDag-Erling Smørgrav 			} else if (verify_result == LDNS_STATUS_ERR) {
1180*7b5038d7SDag-Erling Smørgrav 				verify_result = s;
1181*7b5038d7SDag-Erling Smørgrav 			} else if (s !=  LDNS_STATUS_ERR && verify_result ==
1182*7b5038d7SDag-Erling Smørgrav 				LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY) {
1183*7b5038d7SDag-Erling Smørgrav 				verify_result = s;
1184*7b5038d7SDag-Erling Smørgrav 			}
1185*7b5038d7SDag-Erling Smørgrav 		}
1186*7b5038d7SDag-Erling Smørgrav 	}
1187*7b5038d7SDag-Erling Smørgrav 	return verify_result;
1188*7b5038d7SDag-Erling Smørgrav }
1189*7b5038d7SDag-Erling Smørgrav 
1190*7b5038d7SDag-Erling Smørgrav ldns_rr_list *
1191*7b5038d7SDag-Erling Smørgrav ldns_fetch_valid_domain_keys_time(const ldns_resolver *res,
1192*7b5038d7SDag-Erling Smørgrav                              const ldns_rdf *domain,
1193*7b5038d7SDag-Erling Smørgrav                              const ldns_rr_list *keys,
1194*7b5038d7SDag-Erling Smørgrav 			     time_t check_time,
1195*7b5038d7SDag-Erling Smørgrav                              ldns_status *status)
1196*7b5038d7SDag-Erling Smørgrav {
1197*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list * trusted_keys = NULL;
1198*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list * ds_keys = NULL;
1199*7b5038d7SDag-Erling Smørgrav 	ldns_rdf * prev_parent_domain;
1200*7b5038d7SDag-Erling Smørgrav 	ldns_rdf *      parent_domain;
1201*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list * parent_keys = NULL;
1202*7b5038d7SDag-Erling Smørgrav 
1203*7b5038d7SDag-Erling Smørgrav 	if (res && domain && keys) {
1204*7b5038d7SDag-Erling Smørgrav 
1205*7b5038d7SDag-Erling Smørgrav 		if ((trusted_keys = ldns_validate_domain_dnskey_time(res,
1206*7b5038d7SDag-Erling Smørgrav                                          domain, keys, check_time))) {
1207*7b5038d7SDag-Erling Smørgrav 			*status = LDNS_STATUS_OK;
1208*7b5038d7SDag-Erling Smørgrav 		} else {
1209*7b5038d7SDag-Erling Smørgrav 			/* No trusted keys in this domain, we'll have to find some in the parent domain */
1210*7b5038d7SDag-Erling Smørgrav 			*status = LDNS_STATUS_CRYPTO_NO_TRUSTED_DNSKEY;
1211*7b5038d7SDag-Erling Smørgrav 
1212*7b5038d7SDag-Erling Smørgrav 			parent_domain = ldns_dname_left_chop(domain);
1213*7b5038d7SDag-Erling Smørgrav 			while (ldns_rdf_size(parent_domain) > 0) {
1214*7b5038d7SDag-Erling Smørgrav 				/* Fail if we are at the root */
1215*7b5038d7SDag-Erling Smørgrav 
1216*7b5038d7SDag-Erling Smørgrav 				if ((parent_keys =
1217*7b5038d7SDag-Erling Smørgrav 					ldns_fetch_valid_domain_keys_time(res,
1218*7b5038d7SDag-Erling Smørgrav 					     parent_domain,
1219*7b5038d7SDag-Erling Smørgrav 					     keys,
1220*7b5038d7SDag-Erling Smørgrav 					     check_time,
1221*7b5038d7SDag-Erling Smørgrav 					     status))) {
1222*7b5038d7SDag-Erling Smørgrav 					/* Check DS records */
1223*7b5038d7SDag-Erling Smørgrav 					if ((ds_keys =
1224*7b5038d7SDag-Erling Smørgrav 						ldns_validate_domain_ds_time(res,
1225*7b5038d7SDag-Erling Smørgrav 						     domain,
1226*7b5038d7SDag-Erling Smørgrav 						     parent_keys,
1227*7b5038d7SDag-Erling Smørgrav 						     check_time))) {
1228*7b5038d7SDag-Erling Smørgrav 						trusted_keys =
1229*7b5038d7SDag-Erling Smørgrav 						ldns_fetch_valid_domain_keys_time(
1230*7b5038d7SDag-Erling Smørgrav 								res,
1231*7b5038d7SDag-Erling Smørgrav 								domain,
1232*7b5038d7SDag-Erling Smørgrav 								ds_keys,
1233*7b5038d7SDag-Erling Smørgrav 								check_time,
1234*7b5038d7SDag-Erling Smørgrav 								status);
1235*7b5038d7SDag-Erling Smørgrav 						ldns_rr_list_deep_free(ds_keys);
1236*7b5038d7SDag-Erling Smørgrav 					} else {
1237*7b5038d7SDag-Erling Smørgrav 						/* No valid DS at the parent -- fail */
1238*7b5038d7SDag-Erling Smørgrav 						*status = LDNS_STATUS_CRYPTO_NO_TRUSTED_DS ;
1239*7b5038d7SDag-Erling Smørgrav 					}
1240*7b5038d7SDag-Erling Smørgrav 					ldns_rr_list_deep_free(parent_keys);
1241*7b5038d7SDag-Erling Smørgrav 					break;
1242*7b5038d7SDag-Erling Smørgrav 				} else {
1243*7b5038d7SDag-Erling Smørgrav 					parent_domain = ldns_dname_left_chop((
1244*7b5038d7SDag-Erling Smørgrav 						prev_parent_domain
1245*7b5038d7SDag-Erling Smørgrav 							= parent_domain
1246*7b5038d7SDag-Erling Smørgrav 						));
1247*7b5038d7SDag-Erling Smørgrav 					ldns_rdf_deep_free(prev_parent_domain);
1248*7b5038d7SDag-Erling Smørgrav 				}
1249*7b5038d7SDag-Erling Smørgrav 			}
1250*7b5038d7SDag-Erling Smørgrav 			ldns_rdf_deep_free(parent_domain);
1251*7b5038d7SDag-Erling Smørgrav 		}
1252*7b5038d7SDag-Erling Smørgrav 	}
1253*7b5038d7SDag-Erling Smørgrav 	return trusted_keys;
1254*7b5038d7SDag-Erling Smørgrav }
1255*7b5038d7SDag-Erling Smørgrav 
1256*7b5038d7SDag-Erling Smørgrav ldns_rr_list *
1257*7b5038d7SDag-Erling Smørgrav ldns_fetch_valid_domain_keys(const ldns_resolver *res,
1258*7b5038d7SDag-Erling Smørgrav                              const ldns_rdf *domain,
1259*7b5038d7SDag-Erling Smørgrav                              const ldns_rr_list *keys,
1260*7b5038d7SDag-Erling Smørgrav                              ldns_status *status)
1261*7b5038d7SDag-Erling Smørgrav {
1262*7b5038d7SDag-Erling Smørgrav 	return ldns_fetch_valid_domain_keys_time(
1263*7b5038d7SDag-Erling Smørgrav 			res, domain, keys, ldns_time(NULL), status);
1264*7b5038d7SDag-Erling Smørgrav }
1265*7b5038d7SDag-Erling Smørgrav 
1266*7b5038d7SDag-Erling Smørgrav ldns_rr_list *
1267*7b5038d7SDag-Erling Smørgrav ldns_validate_domain_dnskey_time(
1268*7b5038d7SDag-Erling Smørgrav 		const ldns_resolver * res,
1269*7b5038d7SDag-Erling Smørgrav 		const ldns_rdf * domain,
1270*7b5038d7SDag-Erling Smørgrav 		const ldns_rr_list * keys,
1271*7b5038d7SDag-Erling Smørgrav 		time_t check_time
1272*7b5038d7SDag-Erling Smørgrav 		)
1273*7b5038d7SDag-Erling Smørgrav {
1274*7b5038d7SDag-Erling Smørgrav 	ldns_pkt * keypkt;
1275*7b5038d7SDag-Erling Smørgrav 	ldns_rr * cur_key;
1276*7b5038d7SDag-Erling Smørgrav 	uint16_t key_i; uint16_t key_j; uint16_t key_k;
1277*7b5038d7SDag-Erling Smørgrav 	uint16_t sig_i; ldns_rr * cur_sig;
1278*7b5038d7SDag-Erling Smørgrav 
1279*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list * domain_keys = NULL;
1280*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list * domain_sigs = NULL;
1281*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list * trusted_keys = NULL;
1282*7b5038d7SDag-Erling Smørgrav 
1283*7b5038d7SDag-Erling Smørgrav 	/* Fetch keys for the domain */
1284*7b5038d7SDag-Erling Smørgrav 	keypkt = ldns_resolver_query(res, domain,
1285*7b5038d7SDag-Erling Smørgrav 		LDNS_RR_TYPE_DNSKEY, LDNS_RR_CLASS_IN, LDNS_RD);
1286*7b5038d7SDag-Erling Smørgrav 	if (keypkt) {
1287*7b5038d7SDag-Erling Smørgrav 		domain_keys = ldns_pkt_rr_list_by_type(keypkt,
1288*7b5038d7SDag-Erling Smørgrav 									    LDNS_RR_TYPE_DNSKEY,
1289*7b5038d7SDag-Erling Smørgrav 									    LDNS_SECTION_ANSWER);
1290*7b5038d7SDag-Erling Smørgrav 		domain_sigs = ldns_pkt_rr_list_by_type(keypkt,
1291*7b5038d7SDag-Erling Smørgrav 									    LDNS_RR_TYPE_RRSIG,
1292*7b5038d7SDag-Erling Smørgrav 									    LDNS_SECTION_ANSWER);
1293*7b5038d7SDag-Erling Smørgrav 
1294*7b5038d7SDag-Erling Smørgrav 		/* Try to validate the record using our keys */
1295*7b5038d7SDag-Erling Smørgrav 		for (key_i=0; key_i< ldns_rr_list_rr_count(domain_keys); key_i++) {
1296*7b5038d7SDag-Erling Smørgrav 
1297*7b5038d7SDag-Erling Smørgrav 			cur_key = ldns_rr_list_rr(domain_keys, key_i);
1298*7b5038d7SDag-Erling Smørgrav 			for (key_j=0; key_j<ldns_rr_list_rr_count(keys); key_j++) {
1299*7b5038d7SDag-Erling Smørgrav 				if (ldns_rr_compare_ds(ldns_rr_list_rr(keys, key_j),
1300*7b5038d7SDag-Erling Smørgrav 								   cur_key)) {
1301*7b5038d7SDag-Erling Smørgrav 
1302*7b5038d7SDag-Erling Smørgrav 					/* Current key is trusted -- validate */
1303*7b5038d7SDag-Erling Smørgrav 					trusted_keys = ldns_rr_list_new();
1304*7b5038d7SDag-Erling Smørgrav 
1305*7b5038d7SDag-Erling Smørgrav 					for (sig_i=0;
1306*7b5038d7SDag-Erling Smørgrav 						sig_i<ldns_rr_list_rr_count(domain_sigs);
1307*7b5038d7SDag-Erling Smørgrav 						sig_i++) {
1308*7b5038d7SDag-Erling Smørgrav 						cur_sig = ldns_rr_list_rr(domain_sigs, sig_i);
1309*7b5038d7SDag-Erling Smørgrav 						/* Avoid non-matching sigs */
1310*7b5038d7SDag-Erling Smørgrav 						if (ldns_rdf2native_int16(
1311*7b5038d7SDag-Erling Smørgrav 							   ldns_rr_rrsig_keytag(cur_sig))
1312*7b5038d7SDag-Erling Smørgrav 						    == ldns_calc_keytag(cur_key)) {
1313*7b5038d7SDag-Erling Smørgrav 							if (ldns_verify_rrsig_time(
1314*7b5038d7SDag-Erling Smørgrav 									domain_keys,
1315*7b5038d7SDag-Erling Smørgrav 									cur_sig,
1316*7b5038d7SDag-Erling Smørgrav 									cur_key,
1317*7b5038d7SDag-Erling Smørgrav 									check_time)
1318*7b5038d7SDag-Erling Smørgrav 							    == LDNS_STATUS_OK) {
1319*7b5038d7SDag-Erling Smørgrav 
1320*7b5038d7SDag-Erling Smørgrav 								/* Push the whole rrset
1321*7b5038d7SDag-Erling Smørgrav 								   -- we can't do much more */
1322*7b5038d7SDag-Erling Smørgrav 								for (key_k=0;
1323*7b5038d7SDag-Erling Smørgrav 									key_k<ldns_rr_list_rr_count(
1324*7b5038d7SDag-Erling Smørgrav 											domain_keys);
1325*7b5038d7SDag-Erling Smørgrav 									key_k++) {
1326*7b5038d7SDag-Erling Smørgrav 									ldns_rr_list_push_rr(
1327*7b5038d7SDag-Erling Smørgrav 									    trusted_keys,
1328*7b5038d7SDag-Erling Smørgrav 									    ldns_rr_clone(
1329*7b5038d7SDag-Erling Smørgrav 										   ldns_rr_list_rr(
1330*7b5038d7SDag-Erling Smørgrav 											  domain_keys,
1331*7b5038d7SDag-Erling Smørgrav 											  key_k)));
1332*7b5038d7SDag-Erling Smørgrav 								}
1333*7b5038d7SDag-Erling Smørgrav 
1334*7b5038d7SDag-Erling Smørgrav 								ldns_rr_list_deep_free(domain_keys);
1335*7b5038d7SDag-Erling Smørgrav 								ldns_rr_list_deep_free(domain_sigs);
1336*7b5038d7SDag-Erling Smørgrav 								ldns_pkt_free(keypkt);
1337*7b5038d7SDag-Erling Smørgrav 								return trusted_keys;
1338*7b5038d7SDag-Erling Smørgrav 							}
1339*7b5038d7SDag-Erling Smørgrav 						}
1340*7b5038d7SDag-Erling Smørgrav 					}
1341*7b5038d7SDag-Erling Smørgrav 
1342*7b5038d7SDag-Erling Smørgrav 					/* Only push our trusted key */
1343*7b5038d7SDag-Erling Smørgrav 					ldns_rr_list_push_rr(trusted_keys,
1344*7b5038d7SDag-Erling Smørgrav 									 ldns_rr_clone(cur_key));
1345*7b5038d7SDag-Erling Smørgrav 				}
1346*7b5038d7SDag-Erling Smørgrav 			}
1347*7b5038d7SDag-Erling Smørgrav 		}
1348*7b5038d7SDag-Erling Smørgrav 
1349*7b5038d7SDag-Erling Smørgrav 		ldns_rr_list_deep_free(domain_keys);
1350*7b5038d7SDag-Erling Smørgrav 		ldns_rr_list_deep_free(domain_sigs);
1351*7b5038d7SDag-Erling Smørgrav 		ldns_pkt_free(keypkt);
1352*7b5038d7SDag-Erling Smørgrav 
1353*7b5038d7SDag-Erling Smørgrav 	} else {
1354*7b5038d7SDag-Erling Smørgrav 		/* LDNS_STATUS_CRYPTO_NO_DNSKEY */
1355*7b5038d7SDag-Erling Smørgrav 	}
1356*7b5038d7SDag-Erling Smørgrav 
1357*7b5038d7SDag-Erling Smørgrav 	return trusted_keys;
1358*7b5038d7SDag-Erling Smørgrav }
1359*7b5038d7SDag-Erling Smørgrav 
1360*7b5038d7SDag-Erling Smørgrav ldns_rr_list *
1361*7b5038d7SDag-Erling Smørgrav ldns_validate_domain_dnskey(const ldns_resolver * res,
1362*7b5038d7SDag-Erling Smørgrav 					   const ldns_rdf * domain,
1363*7b5038d7SDag-Erling Smørgrav 					   const ldns_rr_list * keys)
1364*7b5038d7SDag-Erling Smørgrav {
1365*7b5038d7SDag-Erling Smørgrav 	return ldns_validate_domain_dnskey_time(
1366*7b5038d7SDag-Erling Smørgrav 			res, domain, keys, ldns_time(NULL));
1367*7b5038d7SDag-Erling Smørgrav }
1368*7b5038d7SDag-Erling Smørgrav 
1369*7b5038d7SDag-Erling Smørgrav ldns_rr_list *
1370*7b5038d7SDag-Erling Smørgrav ldns_validate_domain_ds_time(
1371*7b5038d7SDag-Erling Smørgrav 		const ldns_resolver *res,
1372*7b5038d7SDag-Erling Smørgrav 		const ldns_rdf * domain,
1373*7b5038d7SDag-Erling Smørgrav 		const ldns_rr_list * keys,
1374*7b5038d7SDag-Erling Smørgrav 		time_t check_time)
1375*7b5038d7SDag-Erling Smørgrav {
1376*7b5038d7SDag-Erling Smørgrav 	ldns_pkt * dspkt;
1377*7b5038d7SDag-Erling Smørgrav 	uint16_t key_i;
1378*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list * rrset = NULL;
1379*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list * sigs = NULL;
1380*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list * trusted_keys = NULL;
1381*7b5038d7SDag-Erling Smørgrav 
1382*7b5038d7SDag-Erling Smørgrav 	/* Fetch DS for the domain */
1383*7b5038d7SDag-Erling Smørgrav 	dspkt = ldns_resolver_query(res, domain,
1384*7b5038d7SDag-Erling Smørgrav 		LDNS_RR_TYPE_DS, LDNS_RR_CLASS_IN, LDNS_RD);
1385*7b5038d7SDag-Erling Smørgrav 	if (dspkt) {
1386*7b5038d7SDag-Erling Smørgrav 		rrset = ldns_pkt_rr_list_by_type(dspkt,
1387*7b5038d7SDag-Erling Smørgrav 								   LDNS_RR_TYPE_DS,
1388*7b5038d7SDag-Erling Smørgrav 								   LDNS_SECTION_ANSWER);
1389*7b5038d7SDag-Erling Smørgrav 		sigs = ldns_pkt_rr_list_by_type(dspkt,
1390*7b5038d7SDag-Erling Smørgrav 								  LDNS_RR_TYPE_RRSIG,
1391*7b5038d7SDag-Erling Smørgrav 								  LDNS_SECTION_ANSWER);
1392*7b5038d7SDag-Erling Smørgrav 
1393*7b5038d7SDag-Erling Smørgrav 		/* Validate sigs */
1394*7b5038d7SDag-Erling Smørgrav 		if (ldns_verify_time(rrset, sigs, keys, check_time, NULL)
1395*7b5038d7SDag-Erling Smørgrav 			       	== LDNS_STATUS_OK) {
1396*7b5038d7SDag-Erling Smørgrav 			trusted_keys = ldns_rr_list_new();
1397*7b5038d7SDag-Erling Smørgrav 			for (key_i=0; key_i<ldns_rr_list_rr_count(rrset); key_i++) {
1398*7b5038d7SDag-Erling Smørgrav 				ldns_rr_list_push_rr(trusted_keys,
1399*7b5038d7SDag-Erling Smørgrav 								 ldns_rr_clone(ldns_rr_list_rr(rrset,
1400*7b5038d7SDag-Erling Smørgrav 														 key_i)
1401*7b5038d7SDag-Erling Smørgrav 											)
1402*7b5038d7SDag-Erling Smørgrav 								 );
1403*7b5038d7SDag-Erling Smørgrav 			}
1404*7b5038d7SDag-Erling Smørgrav 		}
1405*7b5038d7SDag-Erling Smørgrav 
1406*7b5038d7SDag-Erling Smørgrav 		ldns_rr_list_deep_free(rrset);
1407*7b5038d7SDag-Erling Smørgrav 		ldns_rr_list_deep_free(sigs);
1408*7b5038d7SDag-Erling Smørgrav 		ldns_pkt_free(dspkt);
1409*7b5038d7SDag-Erling Smørgrav 
1410*7b5038d7SDag-Erling Smørgrav 	} else {
1411*7b5038d7SDag-Erling Smørgrav 		/* LDNS_STATUS_CRYPTO_NO_DS */
1412*7b5038d7SDag-Erling Smørgrav 	}
1413*7b5038d7SDag-Erling Smørgrav 
1414*7b5038d7SDag-Erling Smørgrav 	return trusted_keys;
1415*7b5038d7SDag-Erling Smørgrav }
1416*7b5038d7SDag-Erling Smørgrav 
1417*7b5038d7SDag-Erling Smørgrav ldns_rr_list *
1418*7b5038d7SDag-Erling Smørgrav ldns_validate_domain_ds(const ldns_resolver *res,
1419*7b5038d7SDag-Erling Smørgrav 				    const ldns_rdf * domain,
1420*7b5038d7SDag-Erling Smørgrav 				    const ldns_rr_list * keys)
1421*7b5038d7SDag-Erling Smørgrav {
1422*7b5038d7SDag-Erling Smørgrav 	return ldns_validate_domain_ds_time(res, domain, keys, ldns_time(NULL));
1423*7b5038d7SDag-Erling Smørgrav }
1424*7b5038d7SDag-Erling Smørgrav 
1425*7b5038d7SDag-Erling Smørgrav ldns_status
1426*7b5038d7SDag-Erling Smørgrav ldns_verify_trusted_time(
1427*7b5038d7SDag-Erling Smørgrav 		ldns_resolver *res,
1428*7b5038d7SDag-Erling Smørgrav 		ldns_rr_list *rrset,
1429*7b5038d7SDag-Erling Smørgrav 		ldns_rr_list * rrsigs,
1430*7b5038d7SDag-Erling Smørgrav 		time_t check_time,
1431*7b5038d7SDag-Erling Smørgrav 		ldns_rr_list * validating_keys
1432*7b5038d7SDag-Erling Smørgrav 		)
1433*7b5038d7SDag-Erling Smørgrav {
1434*7b5038d7SDag-Erling Smørgrav 	uint16_t sig_i; uint16_t key_i;
1435*7b5038d7SDag-Erling Smørgrav 	ldns_rr * cur_sig; ldns_rr * cur_key;
1436*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list * trusted_keys = NULL;
1437*7b5038d7SDag-Erling Smørgrav 	ldns_status result = LDNS_STATUS_ERR;
1438*7b5038d7SDag-Erling Smørgrav 
1439*7b5038d7SDag-Erling Smørgrav 	if (!res || !rrset || !rrsigs) {
1440*7b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_ERR;
1441*7b5038d7SDag-Erling Smørgrav 	}
1442*7b5038d7SDag-Erling Smørgrav 
1443*7b5038d7SDag-Erling Smørgrav 	if (ldns_rr_list_rr_count(rrset) < 1) {
1444*7b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_ERR;
1445*7b5038d7SDag-Erling Smørgrav 	}
1446*7b5038d7SDag-Erling Smørgrav 
1447*7b5038d7SDag-Erling Smørgrav 	if (ldns_rr_list_rr_count(rrsigs) < 1) {
1448*7b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_CRYPTO_NO_RRSIG;
1449*7b5038d7SDag-Erling Smørgrav 	}
1450*7b5038d7SDag-Erling Smørgrav 
1451*7b5038d7SDag-Erling Smørgrav 	/* Look at each sig */
1452*7b5038d7SDag-Erling Smørgrav 	for (sig_i=0; sig_i < ldns_rr_list_rr_count(rrsigs); sig_i++) {
1453*7b5038d7SDag-Erling Smørgrav 
1454*7b5038d7SDag-Erling Smørgrav 		cur_sig = ldns_rr_list_rr(rrsigs, sig_i);
1455*7b5038d7SDag-Erling Smørgrav 		/* Get a valid signer key and validate the sig */
1456*7b5038d7SDag-Erling Smørgrav 		if ((trusted_keys = ldns_fetch_valid_domain_keys_time(
1457*7b5038d7SDag-Erling Smørgrav 					res,
1458*7b5038d7SDag-Erling Smørgrav 					ldns_rr_rrsig_signame(cur_sig),
1459*7b5038d7SDag-Erling Smørgrav 					ldns_resolver_dnssec_anchors(res),
1460*7b5038d7SDag-Erling Smørgrav 					check_time,
1461*7b5038d7SDag-Erling Smørgrav 					&result))) {
1462*7b5038d7SDag-Erling Smørgrav 
1463*7b5038d7SDag-Erling Smørgrav 			for (key_i = 0;
1464*7b5038d7SDag-Erling Smørgrav 				key_i < ldns_rr_list_rr_count(trusted_keys);
1465*7b5038d7SDag-Erling Smørgrav 				key_i++) {
1466*7b5038d7SDag-Erling Smørgrav 				cur_key = ldns_rr_list_rr(trusted_keys, key_i);
1467*7b5038d7SDag-Erling Smørgrav 
1468*7b5038d7SDag-Erling Smørgrav 				if ((result = ldns_verify_rrsig_time(rrset,
1469*7b5038d7SDag-Erling Smørgrav 								cur_sig,
1470*7b5038d7SDag-Erling Smørgrav 								cur_key,
1471*7b5038d7SDag-Erling Smørgrav 								check_time))
1472*7b5038d7SDag-Erling Smørgrav 				    == LDNS_STATUS_OK) {
1473*7b5038d7SDag-Erling Smørgrav 					if (validating_keys) {
1474*7b5038d7SDag-Erling Smørgrav 						ldns_rr_list_push_rr(validating_keys,
1475*7b5038d7SDag-Erling Smørgrav 										 ldns_rr_clone(cur_key));
1476*7b5038d7SDag-Erling Smørgrav 					}
1477*7b5038d7SDag-Erling Smørgrav 					ldns_rr_list_deep_free(trusted_keys);
1478*7b5038d7SDag-Erling Smørgrav 					return LDNS_STATUS_OK;
1479*7b5038d7SDag-Erling Smørgrav 				}
1480*7b5038d7SDag-Erling Smørgrav 			}
1481*7b5038d7SDag-Erling Smørgrav 		}
1482*7b5038d7SDag-Erling Smørgrav 	}
1483*7b5038d7SDag-Erling Smørgrav 
1484*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list_deep_free(trusted_keys);
1485*7b5038d7SDag-Erling Smørgrav 	return result;
1486*7b5038d7SDag-Erling Smørgrav }
1487*7b5038d7SDag-Erling Smørgrav 
1488*7b5038d7SDag-Erling Smørgrav ldns_status
1489*7b5038d7SDag-Erling Smørgrav ldns_verify_trusted(
1490*7b5038d7SDag-Erling Smørgrav 		ldns_resolver *res,
1491*7b5038d7SDag-Erling Smørgrav 		ldns_rr_list *rrset,
1492*7b5038d7SDag-Erling Smørgrav 		ldns_rr_list * rrsigs,
1493*7b5038d7SDag-Erling Smørgrav 		ldns_rr_list * validating_keys)
1494*7b5038d7SDag-Erling Smørgrav {
1495*7b5038d7SDag-Erling Smørgrav 	return ldns_verify_trusted_time(
1496*7b5038d7SDag-Erling Smørgrav 			res, rrset, rrsigs, ldns_time(NULL), validating_keys);
1497*7b5038d7SDag-Erling Smørgrav }
1498*7b5038d7SDag-Erling Smørgrav 
1499*7b5038d7SDag-Erling Smørgrav 
1500*7b5038d7SDag-Erling Smørgrav ldns_status
1501*7b5038d7SDag-Erling Smørgrav ldns_dnssec_verify_denial(ldns_rr *rr,
1502*7b5038d7SDag-Erling Smørgrav                           ldns_rr_list *nsecs,
1503*7b5038d7SDag-Erling Smørgrav                           ldns_rr_list *rrsigs)
1504*7b5038d7SDag-Erling Smørgrav {
1505*7b5038d7SDag-Erling Smørgrav 	ldns_rdf *rr_name;
1506*7b5038d7SDag-Erling Smørgrav 	ldns_rdf *wildcard_name;
1507*7b5038d7SDag-Erling Smørgrav 	ldns_rdf *chopped_dname;
1508*7b5038d7SDag-Erling Smørgrav 	ldns_rr *cur_nsec;
1509*7b5038d7SDag-Erling Smørgrav 	size_t i;
1510*7b5038d7SDag-Erling Smørgrav 	ldns_status result;
1511*7b5038d7SDag-Erling Smørgrav 	/* needed for wildcard check on exact match */
1512*7b5038d7SDag-Erling Smørgrav 	ldns_rr *rrsig;
1513*7b5038d7SDag-Erling Smørgrav 	bool name_covered = false;
1514*7b5038d7SDag-Erling Smørgrav 	bool type_covered = false;
1515*7b5038d7SDag-Erling Smørgrav 	bool wildcard_covered = false;
1516*7b5038d7SDag-Erling Smørgrav 	bool wildcard_type_covered = false;
1517*7b5038d7SDag-Erling Smørgrav 
1518*7b5038d7SDag-Erling Smørgrav 	wildcard_name = ldns_dname_new_frm_str("*");
1519*7b5038d7SDag-Erling Smørgrav 	rr_name = ldns_rr_owner(rr);
1520*7b5038d7SDag-Erling Smørgrav 	chopped_dname = ldns_dname_left_chop(rr_name);
1521*7b5038d7SDag-Erling Smørgrav 	result = ldns_dname_cat(wildcard_name, chopped_dname);
1522*7b5038d7SDag-Erling Smørgrav 	if (result != LDNS_STATUS_OK) {
1523*7b5038d7SDag-Erling Smørgrav 		return result;
1524*7b5038d7SDag-Erling Smørgrav 	}
1525*7b5038d7SDag-Erling Smørgrav 
1526*7b5038d7SDag-Erling Smørgrav 	ldns_rdf_deep_free(chopped_dname);
1527*7b5038d7SDag-Erling Smørgrav 
1528*7b5038d7SDag-Erling Smørgrav 	for  (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) {
1529*7b5038d7SDag-Erling Smørgrav 		cur_nsec = ldns_rr_list_rr(nsecs, i);
1530*7b5038d7SDag-Erling Smørgrav 		if (ldns_dname_compare(rr_name, ldns_rr_owner(cur_nsec)) == 0) {
1531*7b5038d7SDag-Erling Smørgrav 			/* see section 5.4 of RFC4035, if the label count of the NSEC's
1532*7b5038d7SDag-Erling Smørgrav 			   RRSIG is equal, then it is proven that wildcard expansion
1533*7b5038d7SDag-Erling Smørgrav 			   could not have been used to match the request */
1534*7b5038d7SDag-Erling Smørgrav 			rrsig = ldns_dnssec_get_rrsig_for_name_and_type(
1535*7b5038d7SDag-Erling Smørgrav 					  ldns_rr_owner(cur_nsec),
1536*7b5038d7SDag-Erling Smørgrav 					  ldns_rr_get_type(cur_nsec),
1537*7b5038d7SDag-Erling Smørgrav 					  rrsigs);
1538*7b5038d7SDag-Erling Smørgrav 			if (rrsig && ldns_rdf2native_int8(ldns_rr_rrsig_labels(rrsig))
1539*7b5038d7SDag-Erling Smørgrav 			    == ldns_dname_label_count(rr_name)) {
1540*7b5038d7SDag-Erling Smørgrav 				wildcard_covered = true;
1541*7b5038d7SDag-Erling Smørgrav 			}
1542*7b5038d7SDag-Erling Smørgrav 
1543*7b5038d7SDag-Erling Smørgrav 			if (ldns_nsec_bitmap_covers_type(ldns_nsec_get_bitmap(cur_nsec),
1544*7b5038d7SDag-Erling Smørgrav 									   ldns_rr_get_type(rr))) {
1545*7b5038d7SDag-Erling Smørgrav 				type_covered = true;
1546*7b5038d7SDag-Erling Smørgrav 			}
1547*7b5038d7SDag-Erling Smørgrav 		}
1548*7b5038d7SDag-Erling Smørgrav 		if (ldns_nsec_covers_name(cur_nsec, rr_name)) {
1549*7b5038d7SDag-Erling Smørgrav 			name_covered = true;
1550*7b5038d7SDag-Erling Smørgrav 		}
1551*7b5038d7SDag-Erling Smørgrav 
1552*7b5038d7SDag-Erling Smørgrav 		if (ldns_dname_compare(wildcard_name,
1553*7b5038d7SDag-Erling Smørgrav 						   ldns_rr_owner(cur_nsec)) == 0) {
1554*7b5038d7SDag-Erling Smørgrav 			if (ldns_nsec_bitmap_covers_type(ldns_nsec_get_bitmap(cur_nsec),
1555*7b5038d7SDag-Erling Smørgrav 									   ldns_rr_get_type(rr))) {
1556*7b5038d7SDag-Erling Smørgrav 				wildcard_type_covered = true;
1557*7b5038d7SDag-Erling Smørgrav 			}
1558*7b5038d7SDag-Erling Smørgrav 		}
1559*7b5038d7SDag-Erling Smørgrav 
1560*7b5038d7SDag-Erling Smørgrav 		if (ldns_nsec_covers_name(cur_nsec, wildcard_name)) {
1561*7b5038d7SDag-Erling Smørgrav 			wildcard_covered = true;
1562*7b5038d7SDag-Erling Smørgrav 		}
1563*7b5038d7SDag-Erling Smørgrav 
1564*7b5038d7SDag-Erling Smørgrav 	}
1565*7b5038d7SDag-Erling Smørgrav 
1566*7b5038d7SDag-Erling Smørgrav 	ldns_rdf_deep_free(wildcard_name);
1567*7b5038d7SDag-Erling Smørgrav 
1568*7b5038d7SDag-Erling Smørgrav 	if (type_covered || !name_covered) {
1569*7b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED;
1570*7b5038d7SDag-Erling Smørgrav 	}
1571*7b5038d7SDag-Erling Smørgrav 
1572*7b5038d7SDag-Erling Smørgrav 	if (wildcard_type_covered || !wildcard_covered) {
1573*7b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_DNSSEC_NSEC_WILDCARD_NOT_COVERED;
1574*7b5038d7SDag-Erling Smørgrav 	}
1575*7b5038d7SDag-Erling Smørgrav 
1576*7b5038d7SDag-Erling Smørgrav 	return LDNS_STATUS_OK;
1577*7b5038d7SDag-Erling Smørgrav }
1578*7b5038d7SDag-Erling Smørgrav 
1579*7b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL
1580*7b5038d7SDag-Erling Smørgrav ldns_status
1581*7b5038d7SDag-Erling Smørgrav ldns_dnssec_verify_denial_nsec3_match( ldns_rr *rr
1582*7b5038d7SDag-Erling Smørgrav 				     , ldns_rr_list *nsecs
1583*7b5038d7SDag-Erling Smørgrav 				     , ATTR_UNUSED(ldns_rr_list *rrsigs)
1584*7b5038d7SDag-Erling Smørgrav 				     , ldns_pkt_rcode packet_rcode
1585*7b5038d7SDag-Erling Smørgrav 				     , ldns_rr_type packet_qtype
1586*7b5038d7SDag-Erling Smørgrav 				     , bool packet_nodata
1587*7b5038d7SDag-Erling Smørgrav 				     , ldns_rr **match
1588*7b5038d7SDag-Erling Smørgrav 				     )
1589*7b5038d7SDag-Erling Smørgrav {
1590*7b5038d7SDag-Erling Smørgrav 	ldns_rdf *closest_encloser;
1591*7b5038d7SDag-Erling Smørgrav 	ldns_rdf *wildcard;
1592*7b5038d7SDag-Erling Smørgrav 	ldns_rdf *hashed_wildcard_name;
1593*7b5038d7SDag-Erling Smørgrav 	bool wildcard_covered = false;
1594*7b5038d7SDag-Erling Smørgrav 	ldns_rdf *zone_name;
1595*7b5038d7SDag-Erling Smørgrav 	ldns_rdf *hashed_name;
1596*7b5038d7SDag-Erling Smørgrav 	/* self assignment to suppress uninitialized warning */
1597*7b5038d7SDag-Erling Smørgrav 	ldns_rdf *next_closer = next_closer;
1598*7b5038d7SDag-Erling Smørgrav 	ldns_rdf *hashed_next_closer;
1599*7b5038d7SDag-Erling Smørgrav 	size_t i;
1600*7b5038d7SDag-Erling Smørgrav 	ldns_status result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED;
1601*7b5038d7SDag-Erling Smørgrav 
1602*7b5038d7SDag-Erling Smørgrav 	if (match) {
1603*7b5038d7SDag-Erling Smørgrav 		*match = NULL;
1604*7b5038d7SDag-Erling Smørgrav 	}
1605*7b5038d7SDag-Erling Smørgrav 
1606*7b5038d7SDag-Erling Smørgrav 	zone_name = ldns_dname_left_chop(ldns_rr_owner(ldns_rr_list_rr(nsecs,0)));
1607*7b5038d7SDag-Erling Smørgrav 
1608*7b5038d7SDag-Erling Smørgrav 	/* section 8.4 */
1609*7b5038d7SDag-Erling Smørgrav 	if (packet_rcode == LDNS_RCODE_NXDOMAIN) {
1610*7b5038d7SDag-Erling Smørgrav 		closest_encloser = ldns_dnssec_nsec3_closest_encloser(
1611*7b5038d7SDag-Erling Smørgrav 						   ldns_rr_owner(rr),
1612*7b5038d7SDag-Erling Smørgrav 						   ldns_rr_get_type(rr),
1613*7b5038d7SDag-Erling Smørgrav 						   nsecs);
1614*7b5038d7SDag-Erling Smørgrav                 if(!closest_encloser) {
1615*7b5038d7SDag-Erling Smørgrav                         result = LDNS_STATUS_NSEC3_ERR;
1616*7b5038d7SDag-Erling Smørgrav                         goto done;
1617*7b5038d7SDag-Erling Smørgrav                 }
1618*7b5038d7SDag-Erling Smørgrav 
1619*7b5038d7SDag-Erling Smørgrav 		wildcard = ldns_dname_new_frm_str("*");
1620*7b5038d7SDag-Erling Smørgrav 		(void) ldns_dname_cat(wildcard, closest_encloser);
1621*7b5038d7SDag-Erling Smørgrav 
1622*7b5038d7SDag-Erling Smørgrav 		for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) {
1623*7b5038d7SDag-Erling Smørgrav 			hashed_wildcard_name =
1624*7b5038d7SDag-Erling Smørgrav 				ldns_nsec3_hash_name_frm_nsec3(ldns_rr_list_rr(nsecs, 0),
1625*7b5038d7SDag-Erling Smørgrav 										 wildcard
1626*7b5038d7SDag-Erling Smørgrav 										 );
1627*7b5038d7SDag-Erling Smørgrav 			(void) ldns_dname_cat(hashed_wildcard_name, zone_name);
1628*7b5038d7SDag-Erling Smørgrav 
1629*7b5038d7SDag-Erling Smørgrav 			if (ldns_nsec_covers_name(ldns_rr_list_rr(nsecs, i),
1630*7b5038d7SDag-Erling Smørgrav 								 hashed_wildcard_name)) {
1631*7b5038d7SDag-Erling Smørgrav 				wildcard_covered = true;
1632*7b5038d7SDag-Erling Smørgrav 				if (match) {
1633*7b5038d7SDag-Erling Smørgrav 					*match = ldns_rr_list_rr(nsecs, i);
1634*7b5038d7SDag-Erling Smørgrav 				}
1635*7b5038d7SDag-Erling Smørgrav 			}
1636*7b5038d7SDag-Erling Smørgrav 			ldns_rdf_deep_free(hashed_wildcard_name);
1637*7b5038d7SDag-Erling Smørgrav 		}
1638*7b5038d7SDag-Erling Smørgrav 
1639*7b5038d7SDag-Erling Smørgrav 		ldns_rdf_deep_free(closest_encloser);
1640*7b5038d7SDag-Erling Smørgrav 		ldns_rdf_deep_free(wildcard);
1641*7b5038d7SDag-Erling Smørgrav 
1642*7b5038d7SDag-Erling Smørgrav 		if (!wildcard_covered) {
1643*7b5038d7SDag-Erling Smørgrav 			result = LDNS_STATUS_DNSSEC_NSEC_WILDCARD_NOT_COVERED;
1644*7b5038d7SDag-Erling Smørgrav 		} else if (closest_encloser && wildcard_covered) {
1645*7b5038d7SDag-Erling Smørgrav 			result = LDNS_STATUS_OK;
1646*7b5038d7SDag-Erling Smørgrav 		} else {
1647*7b5038d7SDag-Erling Smørgrav 			result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED;
1648*7b5038d7SDag-Erling Smørgrav 		}
1649*7b5038d7SDag-Erling Smørgrav 	} else if (packet_nodata && packet_qtype != LDNS_RR_TYPE_DS) {
1650*7b5038d7SDag-Erling Smørgrav 		/* section 8.5 */
1651*7b5038d7SDag-Erling Smørgrav 		hashed_name = ldns_nsec3_hash_name_frm_nsec3(
1652*7b5038d7SDag-Erling Smørgrav 		                   ldns_rr_list_rr(nsecs, 0),
1653*7b5038d7SDag-Erling Smørgrav 		                   ldns_rr_owner(rr));
1654*7b5038d7SDag-Erling Smørgrav 		(void) ldns_dname_cat(hashed_name, zone_name);
1655*7b5038d7SDag-Erling Smørgrav 		for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) {
1656*7b5038d7SDag-Erling Smørgrav 			if (ldns_dname_compare(hashed_name,
1657*7b5038d7SDag-Erling Smørgrav 			         ldns_rr_owner(ldns_rr_list_rr(nsecs, i)))
1658*7b5038d7SDag-Erling Smørgrav 			    == 0) {
1659*7b5038d7SDag-Erling Smørgrav 				if (!ldns_nsec_bitmap_covers_type(
1660*7b5038d7SDag-Erling Smørgrav 					    ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)),
1661*7b5038d7SDag-Erling Smørgrav 					    packet_qtype)
1662*7b5038d7SDag-Erling Smørgrav 				    &&
1663*7b5038d7SDag-Erling Smørgrav 				    !ldns_nsec_bitmap_covers_type(
1664*7b5038d7SDag-Erling Smørgrav 					    ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)),
1665*7b5038d7SDag-Erling Smørgrav 					    LDNS_RR_TYPE_CNAME)) {
1666*7b5038d7SDag-Erling Smørgrav 					result = LDNS_STATUS_OK;
1667*7b5038d7SDag-Erling Smørgrav 					if (match) {
1668*7b5038d7SDag-Erling Smørgrav 						*match = ldns_rr_list_rr(nsecs, i);
1669*7b5038d7SDag-Erling Smørgrav 					}
1670*7b5038d7SDag-Erling Smørgrav 					goto done;
1671*7b5038d7SDag-Erling Smørgrav 				}
1672*7b5038d7SDag-Erling Smørgrav 			}
1673*7b5038d7SDag-Erling Smørgrav 		}
1674*7b5038d7SDag-Erling Smørgrav 		result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED;
1675*7b5038d7SDag-Erling Smørgrav 		/* wildcard no data? section 8.7 */
1676*7b5038d7SDag-Erling Smørgrav 		closest_encloser = ldns_dnssec_nsec3_closest_encloser(
1677*7b5038d7SDag-Erling Smørgrav 				   ldns_rr_owner(rr),
1678*7b5038d7SDag-Erling Smørgrav 				   ldns_rr_get_type(rr),
1679*7b5038d7SDag-Erling Smørgrav 				   nsecs);
1680*7b5038d7SDag-Erling Smørgrav 		if(!closest_encloser) {
1681*7b5038d7SDag-Erling Smørgrav 			result = LDNS_STATUS_NSEC3_ERR;
1682*7b5038d7SDag-Erling Smørgrav 			goto done;
1683*7b5038d7SDag-Erling Smørgrav 		}
1684*7b5038d7SDag-Erling Smørgrav 		wildcard = ldns_dname_new_frm_str("*");
1685*7b5038d7SDag-Erling Smørgrav 		(void) ldns_dname_cat(wildcard, closest_encloser);
1686*7b5038d7SDag-Erling Smørgrav 		for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) {
1687*7b5038d7SDag-Erling Smørgrav 			hashed_wildcard_name =
1688*7b5038d7SDag-Erling Smørgrav 				ldns_nsec3_hash_name_frm_nsec3(ldns_rr_list_rr(nsecs, 0),
1689*7b5038d7SDag-Erling Smørgrav 					 wildcard);
1690*7b5038d7SDag-Erling Smørgrav 			(void) ldns_dname_cat(hashed_wildcard_name, zone_name);
1691*7b5038d7SDag-Erling Smørgrav 
1692*7b5038d7SDag-Erling Smørgrav 			if (ldns_dname_compare(hashed_wildcard_name,
1693*7b5038d7SDag-Erling Smørgrav 			         ldns_rr_owner(ldns_rr_list_rr(nsecs, i)))
1694*7b5038d7SDag-Erling Smørgrav 			    == 0) {
1695*7b5038d7SDag-Erling Smørgrav 				if (!ldns_nsec_bitmap_covers_type(
1696*7b5038d7SDag-Erling Smørgrav 					    ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)),
1697*7b5038d7SDag-Erling Smørgrav 					    packet_qtype)
1698*7b5038d7SDag-Erling Smørgrav 				    &&
1699*7b5038d7SDag-Erling Smørgrav 				    !ldns_nsec_bitmap_covers_type(
1700*7b5038d7SDag-Erling Smørgrav 					    ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)),
1701*7b5038d7SDag-Erling Smørgrav 					    LDNS_RR_TYPE_CNAME)) {
1702*7b5038d7SDag-Erling Smørgrav 					result = LDNS_STATUS_OK;
1703*7b5038d7SDag-Erling Smørgrav 					if (match) {
1704*7b5038d7SDag-Erling Smørgrav 						*match = ldns_rr_list_rr(nsecs, i);
1705*7b5038d7SDag-Erling Smørgrav 					}
1706*7b5038d7SDag-Erling Smørgrav 				}
1707*7b5038d7SDag-Erling Smørgrav 			}
1708*7b5038d7SDag-Erling Smørgrav 			ldns_rdf_deep_free(hashed_wildcard_name);
1709*7b5038d7SDag-Erling Smørgrav 			if (result == LDNS_STATUS_OK) {
1710*7b5038d7SDag-Erling Smørgrav 				break;
1711*7b5038d7SDag-Erling Smørgrav 			}
1712*7b5038d7SDag-Erling Smørgrav 		}
1713*7b5038d7SDag-Erling Smørgrav 		ldns_rdf_deep_free(closest_encloser);
1714*7b5038d7SDag-Erling Smørgrav 		ldns_rdf_deep_free(wildcard);
1715*7b5038d7SDag-Erling Smørgrav 	} else if (packet_nodata && packet_qtype == LDNS_RR_TYPE_DS) {
1716*7b5038d7SDag-Erling Smørgrav 		/* section 8.6 */
1717*7b5038d7SDag-Erling Smørgrav 		/* note: up to XXX this is the same as for 8.5 */
1718*7b5038d7SDag-Erling Smørgrav 		hashed_name = ldns_nsec3_hash_name_frm_nsec3(ldns_rr_list_rr(nsecs,
1719*7b5038d7SDag-Erling Smørgrav 														 0),
1720*7b5038d7SDag-Erling Smørgrav 											ldns_rr_owner(rr)
1721*7b5038d7SDag-Erling Smørgrav 											);
1722*7b5038d7SDag-Erling Smørgrav 		(void) ldns_dname_cat(hashed_name, zone_name);
1723*7b5038d7SDag-Erling Smørgrav 		for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) {
1724*7b5038d7SDag-Erling Smørgrav 			if (ldns_dname_compare(hashed_name,
1725*7b5038d7SDag-Erling Smørgrav 							   ldns_rr_owner(ldns_rr_list_rr(nsecs,
1726*7b5038d7SDag-Erling Smørgrav 													   i)))
1727*7b5038d7SDag-Erling Smørgrav 			    == 0) {
1728*7b5038d7SDag-Erling Smørgrav 				if (!ldns_nsec_bitmap_covers_type(
1729*7b5038d7SDag-Erling Smørgrav 					    ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)),
1730*7b5038d7SDag-Erling Smørgrav 					    LDNS_RR_TYPE_DS)
1731*7b5038d7SDag-Erling Smørgrav 				    &&
1732*7b5038d7SDag-Erling Smørgrav 				    !ldns_nsec_bitmap_covers_type(
1733*7b5038d7SDag-Erling Smørgrav 					    ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)),
1734*7b5038d7SDag-Erling Smørgrav 					    LDNS_RR_TYPE_CNAME)) {
1735*7b5038d7SDag-Erling Smørgrav 					result = LDNS_STATUS_OK;
1736*7b5038d7SDag-Erling Smørgrav 					if (match) {
1737*7b5038d7SDag-Erling Smørgrav 						*match = ldns_rr_list_rr(nsecs, i);
1738*7b5038d7SDag-Erling Smørgrav 					}
1739*7b5038d7SDag-Erling Smørgrav 					goto done;
1740*7b5038d7SDag-Erling Smørgrav 				}
1741*7b5038d7SDag-Erling Smørgrav 			}
1742*7b5038d7SDag-Erling Smørgrav 		}
1743*7b5038d7SDag-Erling Smørgrav 
1744*7b5038d7SDag-Erling Smørgrav 		/* XXX see note above */
1745*7b5038d7SDag-Erling Smørgrav 		result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED;
1746*7b5038d7SDag-Erling Smørgrav 
1747*7b5038d7SDag-Erling Smørgrav 		closest_encloser = ldns_dnssec_nsec3_closest_encloser(
1748*7b5038d7SDag-Erling Smørgrav 				   ldns_rr_owner(rr),
1749*7b5038d7SDag-Erling Smørgrav 				   ldns_rr_get_type(rr),
1750*7b5038d7SDag-Erling Smørgrav 				   nsecs);
1751*7b5038d7SDag-Erling Smørgrav 		if(!closest_encloser) {
1752*7b5038d7SDag-Erling Smørgrav 			result = LDNS_STATUS_NSEC3_ERR;
1753*7b5038d7SDag-Erling Smørgrav 			goto done;
1754*7b5038d7SDag-Erling Smørgrav 		}
1755*7b5038d7SDag-Erling Smørgrav 		/* Now check if we have a Opt-Out NSEC3 that covers the "next closer"*/
1756*7b5038d7SDag-Erling Smørgrav 
1757*7b5038d7SDag-Erling Smørgrav 		if (ldns_dname_label_count(closest_encloser) + 1
1758*7b5038d7SDag-Erling Smørgrav 		    >= ldns_dname_label_count(ldns_rr_owner(rr))) {
1759*7b5038d7SDag-Erling Smørgrav 
1760*7b5038d7SDag-Erling Smørgrav 			/* Query name *is* the "next closer". */
1761*7b5038d7SDag-Erling Smørgrav 			hashed_next_closer = hashed_name;
1762*7b5038d7SDag-Erling Smørgrav 		} else {
1763*7b5038d7SDag-Erling Smørgrav 
1764*7b5038d7SDag-Erling Smørgrav 			/* "next closer" has less labels than the query name.
1765*7b5038d7SDag-Erling Smørgrav 			 * Create the name and hash it.
1766*7b5038d7SDag-Erling Smørgrav 			 */
1767*7b5038d7SDag-Erling Smørgrav 			next_closer = ldns_dname_clone_from(
1768*7b5038d7SDag-Erling Smørgrav 					ldns_rr_owner(rr),
1769*7b5038d7SDag-Erling Smørgrav 					ldns_dname_label_count(ldns_rr_owner(rr))
1770*7b5038d7SDag-Erling Smørgrav 					- (ldns_dname_label_count(closest_encloser) + 1)
1771*7b5038d7SDag-Erling Smørgrav 					);
1772*7b5038d7SDag-Erling Smørgrav 			hashed_next_closer = ldns_nsec3_hash_name_frm_nsec3(
1773*7b5038d7SDag-Erling Smørgrav 					ldns_rr_list_rr(nsecs, 0),
1774*7b5038d7SDag-Erling Smørgrav 					next_closer
1775*7b5038d7SDag-Erling Smørgrav 					);
1776*7b5038d7SDag-Erling Smørgrav 			(void) ldns_dname_cat(hashed_next_closer, zone_name);
1777*7b5038d7SDag-Erling Smørgrav 		}
1778*7b5038d7SDag-Erling Smørgrav 		/* Find the NSEC3 that covers the "next closer" */
1779*7b5038d7SDag-Erling Smørgrav 		for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) {
1780*7b5038d7SDag-Erling Smørgrav 			if (ldns_nsec_covers_name(ldns_rr_list_rr(nsecs, i),
1781*7b5038d7SDag-Erling Smørgrav 			                          hashed_next_closer) &&
1782*7b5038d7SDag-Erling Smørgrav 				ldns_nsec3_optout(ldns_rr_list_rr(nsecs, i))) {
1783*7b5038d7SDag-Erling Smørgrav 
1784*7b5038d7SDag-Erling Smørgrav 				result = LDNS_STATUS_OK;
1785*7b5038d7SDag-Erling Smørgrav 				if (match) {
1786*7b5038d7SDag-Erling Smørgrav 					*match = ldns_rr_list_rr(nsecs, i);
1787*7b5038d7SDag-Erling Smørgrav 				}
1788*7b5038d7SDag-Erling Smørgrav 				break;
1789*7b5038d7SDag-Erling Smørgrav 			}
1790*7b5038d7SDag-Erling Smørgrav 		}
1791*7b5038d7SDag-Erling Smørgrav 		if (ldns_dname_label_count(closest_encloser) + 1
1792*7b5038d7SDag-Erling Smørgrav 		    < ldns_dname_label_count(ldns_rr_owner(rr))) {
1793*7b5038d7SDag-Erling Smørgrav 
1794*7b5038d7SDag-Erling Smørgrav 			/* "next closer" has less labels than the query name.
1795*7b5038d7SDag-Erling Smørgrav 			 * Dispose of the temporary variables that held that name.
1796*7b5038d7SDag-Erling Smørgrav 			 */
1797*7b5038d7SDag-Erling Smørgrav 			ldns_rdf_deep_free(hashed_next_closer);
1798*7b5038d7SDag-Erling Smørgrav 			ldns_rdf_deep_free(next_closer);
1799*7b5038d7SDag-Erling Smørgrav 		}
1800*7b5038d7SDag-Erling Smørgrav 		ldns_rdf_deep_free(closest_encloser);
1801*7b5038d7SDag-Erling Smørgrav 	}
1802*7b5038d7SDag-Erling Smørgrav 
1803*7b5038d7SDag-Erling Smørgrav  done:
1804*7b5038d7SDag-Erling Smørgrav 	ldns_rdf_deep_free(zone_name);
1805*7b5038d7SDag-Erling Smørgrav 	return result;
1806*7b5038d7SDag-Erling Smørgrav }
1807*7b5038d7SDag-Erling Smørgrav 
1808*7b5038d7SDag-Erling Smørgrav ldns_status
1809*7b5038d7SDag-Erling Smørgrav ldns_dnssec_verify_denial_nsec3(ldns_rr *rr,
1810*7b5038d7SDag-Erling Smørgrav 						  ldns_rr_list *nsecs,
1811*7b5038d7SDag-Erling Smørgrav 						  ldns_rr_list *rrsigs,
1812*7b5038d7SDag-Erling Smørgrav 						  ldns_pkt_rcode packet_rcode,
1813*7b5038d7SDag-Erling Smørgrav 						  ldns_rr_type packet_qtype,
1814*7b5038d7SDag-Erling Smørgrav 						  bool packet_nodata)
1815*7b5038d7SDag-Erling Smørgrav {
1816*7b5038d7SDag-Erling Smørgrav 	return ldns_dnssec_verify_denial_nsec3_match(
1817*7b5038d7SDag-Erling Smørgrav 				rr, nsecs, rrsigs, packet_rcode,
1818*7b5038d7SDag-Erling Smørgrav 				packet_qtype, packet_nodata, NULL
1819*7b5038d7SDag-Erling Smørgrav 	       );
1820*7b5038d7SDag-Erling Smørgrav }
1821*7b5038d7SDag-Erling Smørgrav 
1822*7b5038d7SDag-Erling Smørgrav 
1823*7b5038d7SDag-Erling Smørgrav #endif /* HAVE_SSL */
1824*7b5038d7SDag-Erling Smørgrav 
1825*7b5038d7SDag-Erling Smørgrav #ifdef USE_GOST
1826*7b5038d7SDag-Erling Smørgrav EVP_PKEY*
1827*7b5038d7SDag-Erling Smørgrav ldns_gost2pkey_raw(unsigned char* key, size_t keylen)
1828*7b5038d7SDag-Erling Smørgrav {
1829*7b5038d7SDag-Erling Smørgrav 	/* prefix header for X509 encoding */
1830*7b5038d7SDag-Erling Smørgrav 	uint8_t asn[37] = { 0x30, 0x63, 0x30, 0x1c, 0x06, 0x06, 0x2a, 0x85,
1831*7b5038d7SDag-Erling Smørgrav 		0x03, 0x02, 0x02, 0x13, 0x30, 0x12, 0x06, 0x07, 0x2a, 0x85,
1832*7b5038d7SDag-Erling Smørgrav 		0x03, 0x02, 0x02, 0x23, 0x01, 0x06, 0x07, 0x2a, 0x85, 0x03,
1833*7b5038d7SDag-Erling Smørgrav 		0x02, 0x02, 0x1e, 0x01, 0x03, 0x43, 0x00, 0x04, 0x40};
1834*7b5038d7SDag-Erling Smørgrav 	unsigned char encoded[37+64];
1835*7b5038d7SDag-Erling Smørgrav 	const unsigned char* pp;
1836*7b5038d7SDag-Erling Smørgrav 	if(keylen != 64) {
1837*7b5038d7SDag-Erling Smørgrav 		/* key wrong size */
1838*7b5038d7SDag-Erling Smørgrav 		return NULL;
1839*7b5038d7SDag-Erling Smørgrav 	}
1840*7b5038d7SDag-Erling Smørgrav 
1841*7b5038d7SDag-Erling Smørgrav 	/* create evp_key */
1842*7b5038d7SDag-Erling Smørgrav 	memmove(encoded, asn, 37);
1843*7b5038d7SDag-Erling Smørgrav 	memmove(encoded+37, key, 64);
1844*7b5038d7SDag-Erling Smørgrav 	pp = (unsigned char*)&encoded[0];
1845*7b5038d7SDag-Erling Smørgrav 
1846*7b5038d7SDag-Erling Smørgrav 	return d2i_PUBKEY(NULL, &pp, (int)sizeof(encoded));
1847*7b5038d7SDag-Erling Smørgrav }
1848*7b5038d7SDag-Erling Smørgrav 
1849*7b5038d7SDag-Erling Smørgrav static ldns_status
1850*7b5038d7SDag-Erling Smørgrav ldns_verify_rrsig_gost_raw(unsigned char* sig, size_t siglen,
1851*7b5038d7SDag-Erling Smørgrav 	ldns_buffer* rrset, unsigned char* key, size_t keylen)
1852*7b5038d7SDag-Erling Smørgrav {
1853*7b5038d7SDag-Erling Smørgrav 	EVP_PKEY *evp_key;
1854*7b5038d7SDag-Erling Smørgrav 	ldns_status result;
1855*7b5038d7SDag-Erling Smørgrav 
1856*7b5038d7SDag-Erling Smørgrav 	(void) ldns_key_EVP_load_gost_id();
1857*7b5038d7SDag-Erling Smørgrav 	evp_key = ldns_gost2pkey_raw(key, keylen);
1858*7b5038d7SDag-Erling Smørgrav 	if(!evp_key) {
1859*7b5038d7SDag-Erling Smørgrav 		/* could not convert key */
1860*7b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_CRYPTO_BOGUS;
1861*7b5038d7SDag-Erling Smørgrav 	}
1862*7b5038d7SDag-Erling Smørgrav 
1863*7b5038d7SDag-Erling Smørgrav 	/* verify signature */
1864*7b5038d7SDag-Erling Smørgrav 	result = ldns_verify_rrsig_evp_raw(sig, siglen, rrset,
1865*7b5038d7SDag-Erling Smørgrav 		evp_key, EVP_get_digestbyname("md_gost94"));
1866*7b5038d7SDag-Erling Smørgrav 	EVP_PKEY_free(evp_key);
1867*7b5038d7SDag-Erling Smørgrav 
1868*7b5038d7SDag-Erling Smørgrav 	return result;
1869*7b5038d7SDag-Erling Smørgrav }
1870*7b5038d7SDag-Erling Smørgrav #endif
1871*7b5038d7SDag-Erling Smørgrav 
1872*7b5038d7SDag-Erling Smørgrav #ifdef USE_ECDSA
1873*7b5038d7SDag-Erling Smørgrav EVP_PKEY*
1874*7b5038d7SDag-Erling Smørgrav ldns_ecdsa2pkey_raw(unsigned char* key, size_t keylen, uint8_t algo)
1875*7b5038d7SDag-Erling Smørgrav {
1876*7b5038d7SDag-Erling Smørgrav 	unsigned char buf[256+2]; /* sufficient for 2*384/8+1 */
1877*7b5038d7SDag-Erling Smørgrav         const unsigned char* pp = buf;
1878*7b5038d7SDag-Erling Smørgrav         EVP_PKEY *evp_key;
1879*7b5038d7SDag-Erling Smørgrav         EC_KEY *ec;
1880*7b5038d7SDag-Erling Smørgrav 	/* check length, which uncompressed must be 2 bignums */
1881*7b5038d7SDag-Erling Smørgrav         if(algo == LDNS_ECDSAP256SHA256) {
1882*7b5038d7SDag-Erling Smørgrav 		if(keylen != 2*256/8) return NULL;
1883*7b5038d7SDag-Erling Smørgrav                 ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
1884*7b5038d7SDag-Erling Smørgrav         } else if(algo == LDNS_ECDSAP384SHA384) {
1885*7b5038d7SDag-Erling Smørgrav 		if(keylen != 2*384/8) return NULL;
1886*7b5038d7SDag-Erling Smørgrav                 ec = EC_KEY_new_by_curve_name(NID_secp384r1);
1887*7b5038d7SDag-Erling Smørgrav         } else    ec = NULL;
1888*7b5038d7SDag-Erling Smørgrav         if(!ec) return NULL;
1889*7b5038d7SDag-Erling Smørgrav 	if(keylen+1 > sizeof(buf))
1890*7b5038d7SDag-Erling Smørgrav 		return NULL; /* sanity check */
1891*7b5038d7SDag-Erling Smørgrav 	/* prepend the 0x02 (from docs) (or actually 0x04 from implementation
1892*7b5038d7SDag-Erling Smørgrav 	 * of openssl) for uncompressed data */
1893*7b5038d7SDag-Erling Smørgrav 	buf[0] = POINT_CONVERSION_UNCOMPRESSED;
1894*7b5038d7SDag-Erling Smørgrav 	memmove(buf+1, key, keylen);
1895*7b5038d7SDag-Erling Smørgrav         if(!o2i_ECPublicKey(&ec, &pp, (int)keylen+1)) {
1896*7b5038d7SDag-Erling Smørgrav                 EC_KEY_free(ec);
1897*7b5038d7SDag-Erling Smørgrav                 return NULL;
1898*7b5038d7SDag-Erling Smørgrav         }
1899*7b5038d7SDag-Erling Smørgrav         evp_key = EVP_PKEY_new();
1900*7b5038d7SDag-Erling Smørgrav         if(!evp_key) {
1901*7b5038d7SDag-Erling Smørgrav                 EC_KEY_free(ec);
1902*7b5038d7SDag-Erling Smørgrav                 return NULL;
1903*7b5038d7SDag-Erling Smørgrav         }
1904*7b5038d7SDag-Erling Smørgrav         if (!EVP_PKEY_assign_EC_KEY(evp_key, ec)) {
1905*7b5038d7SDag-Erling Smørgrav 		EVP_PKEY_free(evp_key);
1906*7b5038d7SDag-Erling Smørgrav 		EC_KEY_free(ec);
1907*7b5038d7SDag-Erling Smørgrav 		return NULL;
1908*7b5038d7SDag-Erling Smørgrav 	}
1909*7b5038d7SDag-Erling Smørgrav         return evp_key;
1910*7b5038d7SDag-Erling Smørgrav }
1911*7b5038d7SDag-Erling Smørgrav 
1912*7b5038d7SDag-Erling Smørgrav static ldns_status
1913*7b5038d7SDag-Erling Smørgrav ldns_verify_rrsig_ecdsa_raw(unsigned char* sig, size_t siglen,
1914*7b5038d7SDag-Erling Smørgrav 	ldns_buffer* rrset, unsigned char* key, size_t keylen, uint8_t algo)
1915*7b5038d7SDag-Erling Smørgrav {
1916*7b5038d7SDag-Erling Smørgrav         EVP_PKEY *evp_key;
1917*7b5038d7SDag-Erling Smørgrav         ldns_status result;
1918*7b5038d7SDag-Erling Smørgrav         const EVP_MD *d;
1919*7b5038d7SDag-Erling Smørgrav 
1920*7b5038d7SDag-Erling Smørgrav         evp_key = ldns_ecdsa2pkey_raw(key, keylen, algo);
1921*7b5038d7SDag-Erling Smørgrav         if(!evp_key) {
1922*7b5038d7SDag-Erling Smørgrav 		/* could not convert key */
1923*7b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_CRYPTO_BOGUS;
1924*7b5038d7SDag-Erling Smørgrav         }
1925*7b5038d7SDag-Erling Smørgrav         if(algo == LDNS_ECDSAP256SHA256)
1926*7b5038d7SDag-Erling Smørgrav                 d = EVP_sha256();
1927*7b5038d7SDag-Erling Smørgrav         else    d = EVP_sha384(); /* LDNS_ECDSAP384SHA384 */
1928*7b5038d7SDag-Erling Smørgrav 	result = ldns_verify_rrsig_evp_raw(sig, siglen, rrset, evp_key, d);
1929*7b5038d7SDag-Erling Smørgrav 	EVP_PKEY_free(evp_key);
1930*7b5038d7SDag-Erling Smørgrav 	return result;
1931*7b5038d7SDag-Erling Smørgrav }
1932*7b5038d7SDag-Erling Smørgrav #endif
1933*7b5038d7SDag-Erling Smørgrav 
1934*7b5038d7SDag-Erling Smørgrav ldns_status
1935*7b5038d7SDag-Erling Smørgrav ldns_verify_rrsig_buffers(ldns_buffer *rawsig_buf, ldns_buffer *verify_buf,
1936*7b5038d7SDag-Erling Smørgrav 					 ldns_buffer *key_buf, uint8_t algo)
1937*7b5038d7SDag-Erling Smørgrav {
1938*7b5038d7SDag-Erling Smørgrav 	return ldns_verify_rrsig_buffers_raw(
1939*7b5038d7SDag-Erling Smørgrav 			 (unsigned char*)ldns_buffer_begin(rawsig_buf),
1940*7b5038d7SDag-Erling Smørgrav 			 ldns_buffer_position(rawsig_buf),
1941*7b5038d7SDag-Erling Smørgrav 			 verify_buf,
1942*7b5038d7SDag-Erling Smørgrav 			 (unsigned char*)ldns_buffer_begin(key_buf),
1943*7b5038d7SDag-Erling Smørgrav 			 ldns_buffer_position(key_buf), algo);
1944*7b5038d7SDag-Erling Smørgrav }
1945*7b5038d7SDag-Erling Smørgrav 
1946*7b5038d7SDag-Erling Smørgrav ldns_status
1947*7b5038d7SDag-Erling Smørgrav ldns_verify_rrsig_buffers_raw(unsigned char* sig, size_t siglen,
1948*7b5038d7SDag-Erling Smørgrav 						ldns_buffer *verify_buf, unsigned char* key, size_t keylen,
1949*7b5038d7SDag-Erling Smørgrav 						uint8_t algo)
1950*7b5038d7SDag-Erling Smørgrav {
1951*7b5038d7SDag-Erling Smørgrav 	/* check for right key */
1952*7b5038d7SDag-Erling Smørgrav 	switch(algo) {
1953*7b5038d7SDag-Erling Smørgrav 	case LDNS_DSA:
1954*7b5038d7SDag-Erling Smørgrav 	case LDNS_DSA_NSEC3:
1955*7b5038d7SDag-Erling Smørgrav 		return ldns_verify_rrsig_dsa_raw(sig,
1956*7b5038d7SDag-Erling Smørgrav 								   siglen,
1957*7b5038d7SDag-Erling Smørgrav 								   verify_buf,
1958*7b5038d7SDag-Erling Smørgrav 								   key,
1959*7b5038d7SDag-Erling Smørgrav 								   keylen);
1960*7b5038d7SDag-Erling Smørgrav 		break;
1961*7b5038d7SDag-Erling Smørgrav 	case LDNS_RSASHA1:
1962*7b5038d7SDag-Erling Smørgrav 	case LDNS_RSASHA1_NSEC3:
1963*7b5038d7SDag-Erling Smørgrav 		return ldns_verify_rrsig_rsasha1_raw(sig,
1964*7b5038d7SDag-Erling Smørgrav 									  siglen,
1965*7b5038d7SDag-Erling Smørgrav 									  verify_buf,
1966*7b5038d7SDag-Erling Smørgrav 									  key,
1967*7b5038d7SDag-Erling Smørgrav 									  keylen);
1968*7b5038d7SDag-Erling Smørgrav 		break;
1969*7b5038d7SDag-Erling Smørgrav #ifdef USE_SHA2
1970*7b5038d7SDag-Erling Smørgrav 	case LDNS_RSASHA256:
1971*7b5038d7SDag-Erling Smørgrav 		return ldns_verify_rrsig_rsasha256_raw(sig,
1972*7b5038d7SDag-Erling Smørgrav 									    siglen,
1973*7b5038d7SDag-Erling Smørgrav 									    verify_buf,
1974*7b5038d7SDag-Erling Smørgrav 									    key,
1975*7b5038d7SDag-Erling Smørgrav 									    keylen);
1976*7b5038d7SDag-Erling Smørgrav 		break;
1977*7b5038d7SDag-Erling Smørgrav 	case LDNS_RSASHA512:
1978*7b5038d7SDag-Erling Smørgrav 		return ldns_verify_rrsig_rsasha512_raw(sig,
1979*7b5038d7SDag-Erling Smørgrav 									    siglen,
1980*7b5038d7SDag-Erling Smørgrav 									    verify_buf,
1981*7b5038d7SDag-Erling Smørgrav 									    key,
1982*7b5038d7SDag-Erling Smørgrav 									    keylen);
1983*7b5038d7SDag-Erling Smørgrav 		break;
1984*7b5038d7SDag-Erling Smørgrav #endif
1985*7b5038d7SDag-Erling Smørgrav #ifdef USE_GOST
1986*7b5038d7SDag-Erling Smørgrav 	case LDNS_ECC_GOST:
1987*7b5038d7SDag-Erling Smørgrav 		return ldns_verify_rrsig_gost_raw(sig, siglen, verify_buf,
1988*7b5038d7SDag-Erling Smørgrav 			key, keylen);
1989*7b5038d7SDag-Erling Smørgrav 		break;
1990*7b5038d7SDag-Erling Smørgrav #endif
1991*7b5038d7SDag-Erling Smørgrav #ifdef USE_ECDSA
1992*7b5038d7SDag-Erling Smørgrav         case LDNS_ECDSAP256SHA256:
1993*7b5038d7SDag-Erling Smørgrav         case LDNS_ECDSAP384SHA384:
1994*7b5038d7SDag-Erling Smørgrav 		return ldns_verify_rrsig_ecdsa_raw(sig, siglen, verify_buf,
1995*7b5038d7SDag-Erling Smørgrav 			key, keylen, algo);
1996*7b5038d7SDag-Erling Smørgrav 		break;
1997*7b5038d7SDag-Erling Smørgrav #endif
1998*7b5038d7SDag-Erling Smørgrav 	case LDNS_RSAMD5:
1999*7b5038d7SDag-Erling Smørgrav 		return ldns_verify_rrsig_rsamd5_raw(sig,
2000*7b5038d7SDag-Erling Smørgrav 									 siglen,
2001*7b5038d7SDag-Erling Smørgrav 									 verify_buf,
2002*7b5038d7SDag-Erling Smørgrav 									 key,
2003*7b5038d7SDag-Erling Smørgrav 									 keylen);
2004*7b5038d7SDag-Erling Smørgrav 		break;
2005*7b5038d7SDag-Erling Smørgrav 	default:
2006*7b5038d7SDag-Erling Smørgrav 		/* do you know this alg?! */
2007*7b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_CRYPTO_UNKNOWN_ALGO;
2008*7b5038d7SDag-Erling Smørgrav 	}
2009*7b5038d7SDag-Erling Smørgrav }
2010*7b5038d7SDag-Erling Smørgrav 
2011*7b5038d7SDag-Erling Smørgrav 
2012*7b5038d7SDag-Erling Smørgrav /**
2013*7b5038d7SDag-Erling Smørgrav  * Reset the ttl in the rrset with the orig_ttl from the sig
2014*7b5038d7SDag-Erling Smørgrav  * and update owner name if it was wildcard
2015*7b5038d7SDag-Erling Smørgrav  * Also canonicalizes the rrset.
2016*7b5038d7SDag-Erling Smørgrav  * @param rrset: rrset to modify
2017*7b5038d7SDag-Erling Smørgrav  * @param sig: signature to take TTL and wildcard values from
2018*7b5038d7SDag-Erling Smørgrav  */
2019*7b5038d7SDag-Erling Smørgrav static void
2020*7b5038d7SDag-Erling Smørgrav ldns_rrset_use_signature_ttl(ldns_rr_list* rrset_clone, ldns_rr* rrsig)
2021*7b5038d7SDag-Erling Smørgrav {
2022*7b5038d7SDag-Erling Smørgrav 	uint32_t orig_ttl;
2023*7b5038d7SDag-Erling Smørgrav 	uint16_t i;
2024*7b5038d7SDag-Erling Smørgrav 	uint8_t label_count;
2025*7b5038d7SDag-Erling Smørgrav 	ldns_rdf *wildcard_name;
2026*7b5038d7SDag-Erling Smørgrav 	ldns_rdf *wildcard_chopped;
2027*7b5038d7SDag-Erling Smørgrav 	ldns_rdf *wildcard_chopped_tmp;
2028*7b5038d7SDag-Erling Smørgrav 
2029*7b5038d7SDag-Erling Smørgrav 	if ((rrsig == NULL) || ldns_rr_rd_count(rrsig) < 4) {
2030*7b5038d7SDag-Erling Smørgrav 		return;
2031*7b5038d7SDag-Erling Smørgrav 	}
2032*7b5038d7SDag-Erling Smørgrav 
2033*7b5038d7SDag-Erling Smørgrav 	orig_ttl = ldns_rdf2native_int32( ldns_rr_rdf(rrsig, 3));
2034*7b5038d7SDag-Erling Smørgrav 	label_count = ldns_rdf2native_int8(ldns_rr_rdf(rrsig, 2));
2035*7b5038d7SDag-Erling Smørgrav 
2036*7b5038d7SDag-Erling Smørgrav 	for(i = 0; i < ldns_rr_list_rr_count(rrset_clone); i++) {
2037*7b5038d7SDag-Erling Smørgrav 		if (label_count <
2038*7b5038d7SDag-Erling Smørgrav 		    ldns_dname_label_count(
2039*7b5038d7SDag-Erling Smørgrav 			   ldns_rr_owner(ldns_rr_list_rr(rrset_clone, i)))) {
2040*7b5038d7SDag-Erling Smørgrav 			(void) ldns_str2rdf_dname(&wildcard_name, "*");
2041*7b5038d7SDag-Erling Smørgrav 			wildcard_chopped = ldns_rdf_clone(ldns_rr_owner(
2042*7b5038d7SDag-Erling Smørgrav 				ldns_rr_list_rr(rrset_clone, i)));
2043*7b5038d7SDag-Erling Smørgrav 			while (label_count < ldns_dname_label_count(wildcard_chopped)) {
2044*7b5038d7SDag-Erling Smørgrav 				wildcard_chopped_tmp = ldns_dname_left_chop(
2045*7b5038d7SDag-Erling Smørgrav 					wildcard_chopped);
2046*7b5038d7SDag-Erling Smørgrav 				ldns_rdf_deep_free(wildcard_chopped);
2047*7b5038d7SDag-Erling Smørgrav 				wildcard_chopped = wildcard_chopped_tmp;
2048*7b5038d7SDag-Erling Smørgrav 			}
2049*7b5038d7SDag-Erling Smørgrav 			(void) ldns_dname_cat(wildcard_name, wildcard_chopped);
2050*7b5038d7SDag-Erling Smørgrav 			ldns_rdf_deep_free(wildcard_chopped);
2051*7b5038d7SDag-Erling Smørgrav 			ldns_rdf_deep_free(ldns_rr_owner(ldns_rr_list_rr(
2052*7b5038d7SDag-Erling Smørgrav 				rrset_clone, i)));
2053*7b5038d7SDag-Erling Smørgrav 			ldns_rr_set_owner(ldns_rr_list_rr(rrset_clone, i),
2054*7b5038d7SDag-Erling Smørgrav 				wildcard_name);
2055*7b5038d7SDag-Erling Smørgrav 		}
2056*7b5038d7SDag-Erling Smørgrav 		ldns_rr_set_ttl(ldns_rr_list_rr(rrset_clone, i), orig_ttl);
2057*7b5038d7SDag-Erling Smørgrav 		/* convert to lowercase */
2058*7b5038d7SDag-Erling Smørgrav 		ldns_rr2canonical(ldns_rr_list_rr(rrset_clone, i));
2059*7b5038d7SDag-Erling Smørgrav 	}
2060*7b5038d7SDag-Erling Smørgrav }
2061*7b5038d7SDag-Erling Smørgrav 
2062*7b5038d7SDag-Erling Smørgrav /**
2063*7b5038d7SDag-Erling Smørgrav  * Make raw signature buffer out of rrsig
2064*7b5038d7SDag-Erling Smørgrav  * @param rawsig_buf: raw signature buffer for result
2065*7b5038d7SDag-Erling Smørgrav  * @param rrsig: signature to convert
2066*7b5038d7SDag-Erling Smørgrav  * @return OK or more specific error.
2067*7b5038d7SDag-Erling Smørgrav  */
2068*7b5038d7SDag-Erling Smørgrav static ldns_status
2069*7b5038d7SDag-Erling Smørgrav ldns_rrsig2rawsig_buffer(ldns_buffer* rawsig_buf, ldns_rr* rrsig)
2070*7b5038d7SDag-Erling Smørgrav {
2071*7b5038d7SDag-Erling Smørgrav 	uint8_t sig_algo;
2072*7b5038d7SDag-Erling Smørgrav 
2073*7b5038d7SDag-Erling Smørgrav 	if (rrsig == NULL) {
2074*7b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_CRYPTO_NO_RRSIG;
2075*7b5038d7SDag-Erling Smørgrav 	}
2076*7b5038d7SDag-Erling Smørgrav 	if (ldns_rr_rdf(rrsig, 1) == NULL) {
2077*7b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG;
2078*7b5038d7SDag-Erling Smørgrav 	}
2079*7b5038d7SDag-Erling Smørgrav 	sig_algo = ldns_rdf2native_int8(ldns_rr_rdf(rrsig, 1));
2080*7b5038d7SDag-Erling Smørgrav 	/* check for known and implemented algo's now (otherwise
2081*7b5038d7SDag-Erling Smørgrav 	 * the function could return a wrong error
2082*7b5038d7SDag-Erling Smørgrav 	 */
2083*7b5038d7SDag-Erling Smørgrav 	/* create a buffer with signature rdata */
2084*7b5038d7SDag-Erling Smørgrav 	/* for some algorithms we need other data than for others... */
2085*7b5038d7SDag-Erling Smørgrav 	/* (the DSA API wants DER encoding for instance) */
2086*7b5038d7SDag-Erling Smørgrav 
2087*7b5038d7SDag-Erling Smørgrav 	switch(sig_algo) {
2088*7b5038d7SDag-Erling Smørgrav 	case LDNS_RSAMD5:
2089*7b5038d7SDag-Erling Smørgrav 	case LDNS_RSASHA1:
2090*7b5038d7SDag-Erling Smørgrav 	case LDNS_RSASHA1_NSEC3:
2091*7b5038d7SDag-Erling Smørgrav #ifdef USE_SHA2
2092*7b5038d7SDag-Erling Smørgrav 	case LDNS_RSASHA256:
2093*7b5038d7SDag-Erling Smørgrav 	case LDNS_RSASHA512:
2094*7b5038d7SDag-Erling Smørgrav #endif
2095*7b5038d7SDag-Erling Smørgrav #ifdef USE_GOST
2096*7b5038d7SDag-Erling Smørgrav 	case LDNS_ECC_GOST:
2097*7b5038d7SDag-Erling Smørgrav #endif
2098*7b5038d7SDag-Erling Smørgrav 		if (ldns_rr_rdf(rrsig, 8) == NULL) {
2099*7b5038d7SDag-Erling Smørgrav 			return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG;
2100*7b5038d7SDag-Erling Smørgrav 		}
2101*7b5038d7SDag-Erling Smørgrav 		if (ldns_rdf2buffer_wire(rawsig_buf, ldns_rr_rdf(rrsig, 8))
2102*7b5038d7SDag-Erling Smørgrav 			       	!= LDNS_STATUS_OK) {
2103*7b5038d7SDag-Erling Smørgrav 			return LDNS_STATUS_MEM_ERR;
2104*7b5038d7SDag-Erling Smørgrav 		}
2105*7b5038d7SDag-Erling Smørgrav 		break;
2106*7b5038d7SDag-Erling Smørgrav 	case LDNS_DSA:
2107*7b5038d7SDag-Erling Smørgrav 	case LDNS_DSA_NSEC3:
2108*7b5038d7SDag-Erling Smørgrav 		/* EVP takes rfc2459 format, which is a tad longer than dns format */
2109*7b5038d7SDag-Erling Smørgrav 		if (ldns_rr_rdf(rrsig, 8) == NULL) {
2110*7b5038d7SDag-Erling Smørgrav 			return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG;
2111*7b5038d7SDag-Erling Smørgrav 		}
2112*7b5038d7SDag-Erling Smørgrav 		if (ldns_convert_dsa_rrsig_rdf2asn1(
2113*7b5038d7SDag-Erling Smørgrav 					rawsig_buf, ldns_rr_rdf(rrsig, 8))
2114*7b5038d7SDag-Erling Smørgrav 				!= LDNS_STATUS_OK) {
2115*7b5038d7SDag-Erling Smørgrav 			/*
2116*7b5038d7SDag-Erling Smørgrav 			  if (ldns_rdf2buffer_wire(rawsig_buf,
2117*7b5038d7SDag-Erling Smørgrav 			  ldns_rr_rdf(rrsig, 8)) != LDNS_STATUS_OK) {
2118*7b5038d7SDag-Erling Smørgrav 			*/
2119*7b5038d7SDag-Erling Smørgrav 			return LDNS_STATUS_MEM_ERR;
2120*7b5038d7SDag-Erling Smørgrav 		}
2121*7b5038d7SDag-Erling Smørgrav 		break;
2122*7b5038d7SDag-Erling Smørgrav #ifdef USE_ECDSA
2123*7b5038d7SDag-Erling Smørgrav         case LDNS_ECDSAP256SHA256:
2124*7b5038d7SDag-Erling Smørgrav         case LDNS_ECDSAP384SHA384:
2125*7b5038d7SDag-Erling Smørgrav                 /* EVP produces an ASN prefix on the signature, which is
2126*7b5038d7SDag-Erling Smørgrav                  * not used in the DNS */
2127*7b5038d7SDag-Erling Smørgrav 		if (ldns_rr_rdf(rrsig, 8) == NULL) {
2128*7b5038d7SDag-Erling Smørgrav 			return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG;
2129*7b5038d7SDag-Erling Smørgrav 		}
2130*7b5038d7SDag-Erling Smørgrav 		if (ldns_convert_ecdsa_rrsig_rdf2asn1(
2131*7b5038d7SDag-Erling Smørgrav 					rawsig_buf, ldns_rr_rdf(rrsig, 8))
2132*7b5038d7SDag-Erling Smørgrav 				!= LDNS_STATUS_OK) {
2133*7b5038d7SDag-Erling Smørgrav 			return LDNS_STATUS_MEM_ERR;
2134*7b5038d7SDag-Erling Smørgrav                 }
2135*7b5038d7SDag-Erling Smørgrav                 break;
2136*7b5038d7SDag-Erling Smørgrav #endif
2137*7b5038d7SDag-Erling Smørgrav 	case LDNS_DH:
2138*7b5038d7SDag-Erling Smørgrav 	case LDNS_ECC:
2139*7b5038d7SDag-Erling Smørgrav 	case LDNS_INDIRECT:
2140*7b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_CRYPTO_ALGO_NOT_IMPL;
2141*7b5038d7SDag-Erling Smørgrav 	default:
2142*7b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_CRYPTO_UNKNOWN_ALGO;
2143*7b5038d7SDag-Erling Smørgrav 	}
2144*7b5038d7SDag-Erling Smørgrav 	return LDNS_STATUS_OK;
2145*7b5038d7SDag-Erling Smørgrav }
2146*7b5038d7SDag-Erling Smørgrav 
2147*7b5038d7SDag-Erling Smørgrav /**
2148*7b5038d7SDag-Erling Smørgrav  * Check RRSIG timestamps against the given 'now' time.
2149*7b5038d7SDag-Erling Smørgrav  * @param rrsig: signature to check.
2150*7b5038d7SDag-Erling Smørgrav  * @param now: the current time in seconds epoch.
2151*7b5038d7SDag-Erling Smørgrav  * @return status code LDNS_STATUS_OK if all is fine.
2152*7b5038d7SDag-Erling Smørgrav  */
2153*7b5038d7SDag-Erling Smørgrav static ldns_status
2154*7b5038d7SDag-Erling Smørgrav ldns_rrsig_check_timestamps(ldns_rr* rrsig, time_t now)
2155*7b5038d7SDag-Erling Smørgrav {
2156*7b5038d7SDag-Erling Smørgrav 	int32_t inception, expiration;
2157*7b5038d7SDag-Erling Smørgrav 
2158*7b5038d7SDag-Erling Smørgrav 	/* check the signature time stamps */
2159*7b5038d7SDag-Erling Smørgrav 	inception = (int32_t)ldns_rdf2native_time_t(
2160*7b5038d7SDag-Erling Smørgrav 		ldns_rr_rrsig_inception(rrsig));
2161*7b5038d7SDag-Erling Smørgrav 	expiration = (int32_t)ldns_rdf2native_time_t(
2162*7b5038d7SDag-Erling Smørgrav 		ldns_rr_rrsig_expiration(rrsig));
2163*7b5038d7SDag-Erling Smørgrav 
2164*7b5038d7SDag-Erling Smørgrav 	if (expiration - inception < 0) {
2165*7b5038d7SDag-Erling Smørgrav 		/* bad sig, expiration before inception?? Tsssg */
2166*7b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_CRYPTO_EXPIRATION_BEFORE_INCEPTION;
2167*7b5038d7SDag-Erling Smørgrav 	}
2168*7b5038d7SDag-Erling Smørgrav 	if (((int32_t) now) - inception < 0) {
2169*7b5038d7SDag-Erling Smørgrav 		/* bad sig, inception date has not yet come to pass */
2170*7b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_CRYPTO_SIG_NOT_INCEPTED;
2171*7b5038d7SDag-Erling Smørgrav 	}
2172*7b5038d7SDag-Erling Smørgrav 	if (expiration - ((int32_t) now) < 0) {
2173*7b5038d7SDag-Erling Smørgrav 		/* bad sig, expiration date has passed */
2174*7b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_CRYPTO_SIG_EXPIRED;
2175*7b5038d7SDag-Erling Smørgrav 	}
2176*7b5038d7SDag-Erling Smørgrav 	return LDNS_STATUS_OK;
2177*7b5038d7SDag-Erling Smørgrav }
2178*7b5038d7SDag-Erling Smørgrav 
2179*7b5038d7SDag-Erling Smørgrav /**
2180*7b5038d7SDag-Erling Smørgrav  * Prepare for verification.
2181*7b5038d7SDag-Erling Smørgrav  * @param rawsig_buf: raw signature buffer made ready.
2182*7b5038d7SDag-Erling Smørgrav  * @param verify_buf: data for verification buffer made ready.
2183*7b5038d7SDag-Erling Smørgrav  * @param rrset_clone: made ready.
2184*7b5038d7SDag-Erling Smørgrav  * @param rrsig: signature to prepare for.
2185*7b5038d7SDag-Erling Smørgrav  * @return LDNS_STATUS_OK is all went well. Otherwise specific error.
2186*7b5038d7SDag-Erling Smørgrav  */
2187*7b5038d7SDag-Erling Smørgrav static ldns_status
2188*7b5038d7SDag-Erling Smørgrav ldns_prepare_for_verify(ldns_buffer* rawsig_buf, ldns_buffer* verify_buf,
2189*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list* rrset_clone, ldns_rr* rrsig)
2190*7b5038d7SDag-Erling Smørgrav {
2191*7b5038d7SDag-Erling Smørgrav 	ldns_status result;
2192*7b5038d7SDag-Erling Smørgrav 
2193*7b5038d7SDag-Erling Smørgrav 	/* canonicalize the sig */
2194*7b5038d7SDag-Erling Smørgrav 	ldns_dname2canonical(ldns_rr_owner(rrsig));
2195*7b5038d7SDag-Erling Smørgrav 
2196*7b5038d7SDag-Erling Smørgrav 	/* check if the typecovered is equal to the type checked */
2197*7b5038d7SDag-Erling Smørgrav 	if (ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rrsig)) !=
2198*7b5038d7SDag-Erling Smørgrav 	    ldns_rr_get_type(ldns_rr_list_rr(rrset_clone, 0)))
2199*7b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_CRYPTO_TYPE_COVERED_ERR;
2200*7b5038d7SDag-Erling Smørgrav 
2201*7b5038d7SDag-Erling Smørgrav 	/* create a buffer with b64 signature rdata */
2202*7b5038d7SDag-Erling Smørgrav 	result = ldns_rrsig2rawsig_buffer(rawsig_buf, rrsig);
2203*7b5038d7SDag-Erling Smørgrav 	if(result != LDNS_STATUS_OK)
2204*7b5038d7SDag-Erling Smørgrav 		return result;
2205*7b5038d7SDag-Erling Smørgrav 
2206*7b5038d7SDag-Erling Smørgrav 	/* use TTL from signature. Use wildcard names for wildcards */
2207*7b5038d7SDag-Erling Smørgrav 	/* also canonicalizes rrset_clone */
2208*7b5038d7SDag-Erling Smørgrav 	ldns_rrset_use_signature_ttl(rrset_clone, rrsig);
2209*7b5038d7SDag-Erling Smørgrav 
2210*7b5038d7SDag-Erling Smørgrav 	/* sort the rrset in canonical order  */
2211*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list_sort(rrset_clone);
2212*7b5038d7SDag-Erling Smørgrav 
2213*7b5038d7SDag-Erling Smørgrav 	/* put the signature rr (without the b64) to the verify_buf */
2214*7b5038d7SDag-Erling Smørgrav 	if (ldns_rrsig2buffer_wire(verify_buf, rrsig) != LDNS_STATUS_OK)
2215*7b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_MEM_ERR;
2216*7b5038d7SDag-Erling Smørgrav 
2217*7b5038d7SDag-Erling Smørgrav 	/* add the rrset in verify_buf */
2218*7b5038d7SDag-Erling Smørgrav 	if(ldns_rr_list2buffer_wire(verify_buf, rrset_clone)
2219*7b5038d7SDag-Erling Smørgrav 		!= LDNS_STATUS_OK)
2220*7b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_MEM_ERR;
2221*7b5038d7SDag-Erling Smørgrav 
2222*7b5038d7SDag-Erling Smørgrav 	return LDNS_STATUS_OK;
2223*7b5038d7SDag-Erling Smørgrav }
2224*7b5038d7SDag-Erling Smørgrav 
2225*7b5038d7SDag-Erling Smørgrav /**
2226*7b5038d7SDag-Erling Smørgrav  * Check if a key matches a signature.
2227*7b5038d7SDag-Erling Smørgrav  * Checks keytag, sigalgo and signature.
2228*7b5038d7SDag-Erling Smørgrav  * @param rawsig_buf: raw signature buffer for verify
2229*7b5038d7SDag-Erling Smørgrav  * @param verify_buf: raw data buffer for verify
2230*7b5038d7SDag-Erling Smørgrav  * @param rrsig: the rrsig
2231*7b5038d7SDag-Erling Smørgrav  * @param key: key to attempt.
2232*7b5038d7SDag-Erling Smørgrav  * @return LDNS_STATUS_OK if OK, else some specific error.
2233*7b5038d7SDag-Erling Smørgrav  */
2234*7b5038d7SDag-Erling Smørgrav static ldns_status
2235*7b5038d7SDag-Erling Smørgrav ldns_verify_test_sig_key(ldns_buffer* rawsig_buf, ldns_buffer* verify_buf,
2236*7b5038d7SDag-Erling Smørgrav 	ldns_rr* rrsig, ldns_rr* key)
2237*7b5038d7SDag-Erling Smørgrav {
2238*7b5038d7SDag-Erling Smørgrav 	uint8_t sig_algo;
2239*7b5038d7SDag-Erling Smørgrav 
2240*7b5038d7SDag-Erling Smørgrav 	if (rrsig == NULL) {
2241*7b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_CRYPTO_NO_RRSIG;
2242*7b5038d7SDag-Erling Smørgrav 	}
2243*7b5038d7SDag-Erling Smørgrav 	if (ldns_rr_rdf(rrsig, 1) == NULL) {
2244*7b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG;
2245*7b5038d7SDag-Erling Smørgrav 	}
2246*7b5038d7SDag-Erling Smørgrav 	sig_algo = ldns_rdf2native_int8(ldns_rr_rdf(rrsig, 1));
2247*7b5038d7SDag-Erling Smørgrav 
2248*7b5038d7SDag-Erling Smørgrav 	/* before anything, check if the keytags match */
2249*7b5038d7SDag-Erling Smørgrav 	if (ldns_calc_keytag(key)
2250*7b5038d7SDag-Erling Smørgrav 	    ==
2251*7b5038d7SDag-Erling Smørgrav 	    ldns_rdf2native_int16(ldns_rr_rrsig_keytag(rrsig))
2252*7b5038d7SDag-Erling Smørgrav 	    ) {
2253*7b5038d7SDag-Erling Smørgrav 		ldns_buffer* key_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN);
2254*7b5038d7SDag-Erling Smørgrav 		ldns_status result = LDNS_STATUS_ERR;
2255*7b5038d7SDag-Erling Smørgrav 
2256*7b5038d7SDag-Erling Smørgrav 		/* put the key-data in a buffer, that's the third rdf, with
2257*7b5038d7SDag-Erling Smørgrav 		 * the base64 encoded key data */
2258*7b5038d7SDag-Erling Smørgrav 		if (ldns_rr_rdf(key, 3) == NULL) {
2259*7b5038d7SDag-Erling Smørgrav 			ldns_buffer_free(key_buf);
2260*7b5038d7SDag-Erling Smørgrav 			return LDNS_STATUS_MISSING_RDATA_FIELDS_KEY;
2261*7b5038d7SDag-Erling Smørgrav 		}
2262*7b5038d7SDag-Erling Smørgrav 		if (ldns_rdf2buffer_wire(key_buf, ldns_rr_rdf(key, 3))
2263*7b5038d7SDag-Erling Smørgrav 			       	!= LDNS_STATUS_OK) {
2264*7b5038d7SDag-Erling Smørgrav 			ldns_buffer_free(key_buf);
2265*7b5038d7SDag-Erling Smørgrav 			/* returning is bad might screw up
2266*7b5038d7SDag-Erling Smørgrav 			   good keys later in the list
2267*7b5038d7SDag-Erling Smørgrav 			   what to do? */
2268*7b5038d7SDag-Erling Smørgrav 			return LDNS_STATUS_ERR;
2269*7b5038d7SDag-Erling Smørgrav 		}
2270*7b5038d7SDag-Erling Smørgrav 
2271*7b5038d7SDag-Erling Smørgrav 		if (ldns_rr_rdf(key, 2) == NULL) {
2272*7b5038d7SDag-Erling Smørgrav 			result = LDNS_STATUS_MISSING_RDATA_FIELDS_KEY;
2273*7b5038d7SDag-Erling Smørgrav 		}
2274*7b5038d7SDag-Erling Smørgrav 		else if (sig_algo == ldns_rdf2native_int8(
2275*7b5038d7SDag-Erling Smørgrav 					ldns_rr_rdf(key, 2))) {
2276*7b5038d7SDag-Erling Smørgrav 			result = ldns_verify_rrsig_buffers(rawsig_buf,
2277*7b5038d7SDag-Erling Smørgrav 				verify_buf, key_buf, sig_algo);
2278*7b5038d7SDag-Erling Smørgrav 		} else {
2279*7b5038d7SDag-Erling Smørgrav 			/* No keys with the corresponding algorithm are found */
2280*7b5038d7SDag-Erling Smørgrav 			result = LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY;
2281*7b5038d7SDag-Erling Smørgrav 		}
2282*7b5038d7SDag-Erling Smørgrav 
2283*7b5038d7SDag-Erling Smørgrav 		ldns_buffer_free(key_buf);
2284*7b5038d7SDag-Erling Smørgrav 		return result;
2285*7b5038d7SDag-Erling Smørgrav 	}
2286*7b5038d7SDag-Erling Smørgrav 	else {
2287*7b5038d7SDag-Erling Smørgrav 		/* No keys with the corresponding keytag are found */
2288*7b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY;
2289*7b5038d7SDag-Erling Smørgrav 	}
2290*7b5038d7SDag-Erling Smørgrav }
2291*7b5038d7SDag-Erling Smørgrav 
2292*7b5038d7SDag-Erling Smørgrav /*
2293*7b5038d7SDag-Erling Smørgrav  * to verify:
2294*7b5038d7SDag-Erling Smørgrav  * - create the wire fmt of the b64 key rdata
2295*7b5038d7SDag-Erling Smørgrav  * - create the wire fmt of the sorted rrset
2296*7b5038d7SDag-Erling Smørgrav  * - create the wire fmt of the b64 sig rdata
2297*7b5038d7SDag-Erling Smørgrav  * - create the wire fmt of the sig without the b64 rdata
2298*7b5038d7SDag-Erling Smørgrav  * - cat the sig data (without b64 rdata) to the rrset
2299*7b5038d7SDag-Erling Smørgrav  * - verify the rrset+sig, with the b64 data and the b64 key data
2300*7b5038d7SDag-Erling Smørgrav  */
2301*7b5038d7SDag-Erling Smørgrav ldns_status
2302*7b5038d7SDag-Erling Smørgrav ldns_verify_rrsig_keylist_time(
2303*7b5038d7SDag-Erling Smørgrav 		ldns_rr_list *rrset,
2304*7b5038d7SDag-Erling Smørgrav 		ldns_rr *rrsig,
2305*7b5038d7SDag-Erling Smørgrav 		const ldns_rr_list *keys,
2306*7b5038d7SDag-Erling Smørgrav 		time_t check_time,
2307*7b5038d7SDag-Erling Smørgrav 		ldns_rr_list *good_keys)
2308*7b5038d7SDag-Erling Smørgrav {
2309*7b5038d7SDag-Erling Smørgrav 	ldns_status result;
2310*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list *valid = ldns_rr_list_new();
2311*7b5038d7SDag-Erling Smørgrav 	if (!valid)
2312*7b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_MEM_ERR;
2313*7b5038d7SDag-Erling Smørgrav 
2314*7b5038d7SDag-Erling Smørgrav 	result = ldns_verify_rrsig_keylist_notime(rrset, rrsig, keys, valid);
2315*7b5038d7SDag-Erling Smørgrav 	if(result != LDNS_STATUS_OK) {
2316*7b5038d7SDag-Erling Smørgrav 		ldns_rr_list_free(valid);
2317*7b5038d7SDag-Erling Smørgrav 		return result;
2318*7b5038d7SDag-Erling Smørgrav 	}
2319*7b5038d7SDag-Erling Smørgrav 
2320*7b5038d7SDag-Erling Smørgrav 	/* check timestamps last; its OK except time */
2321*7b5038d7SDag-Erling Smørgrav 	result = ldns_rrsig_check_timestamps(rrsig, check_time);
2322*7b5038d7SDag-Erling Smørgrav 	if(result != LDNS_STATUS_OK) {
2323*7b5038d7SDag-Erling Smørgrav 		ldns_rr_list_free(valid);
2324*7b5038d7SDag-Erling Smørgrav 		return result;
2325*7b5038d7SDag-Erling Smørgrav 	}
2326*7b5038d7SDag-Erling Smørgrav 
2327*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list_cat(good_keys, valid);
2328*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list_free(valid);
2329*7b5038d7SDag-Erling Smørgrav 	return LDNS_STATUS_OK;
2330*7b5038d7SDag-Erling Smørgrav }
2331*7b5038d7SDag-Erling Smørgrav 
2332*7b5038d7SDag-Erling Smørgrav /*
2333*7b5038d7SDag-Erling Smørgrav  * to verify:
2334*7b5038d7SDag-Erling Smørgrav  * - create the wire fmt of the b64 key rdata
2335*7b5038d7SDag-Erling Smørgrav  * - create the wire fmt of the sorted rrset
2336*7b5038d7SDag-Erling Smørgrav  * - create the wire fmt of the b64 sig rdata
2337*7b5038d7SDag-Erling Smørgrav  * - create the wire fmt of the sig without the b64 rdata
2338*7b5038d7SDag-Erling Smørgrav  * - cat the sig data (without b64 rdata) to the rrset
2339*7b5038d7SDag-Erling Smørgrav  * - verify the rrset+sig, with the b64 data and the b64 key data
2340*7b5038d7SDag-Erling Smørgrav  */
2341*7b5038d7SDag-Erling Smørgrav ldns_status
2342*7b5038d7SDag-Erling Smørgrav ldns_verify_rrsig_keylist(ldns_rr_list *rrset,
2343*7b5038d7SDag-Erling Smørgrav 					 ldns_rr *rrsig,
2344*7b5038d7SDag-Erling Smørgrav 					 const ldns_rr_list *keys,
2345*7b5038d7SDag-Erling Smørgrav 					 ldns_rr_list *good_keys)
2346*7b5038d7SDag-Erling Smørgrav {
2347*7b5038d7SDag-Erling Smørgrav 	return ldns_verify_rrsig_keylist_time(
2348*7b5038d7SDag-Erling Smørgrav 			rrset, rrsig, keys, ldns_time(NULL), good_keys);
2349*7b5038d7SDag-Erling Smørgrav }
2350*7b5038d7SDag-Erling Smørgrav 
2351*7b5038d7SDag-Erling Smørgrav ldns_status
2352*7b5038d7SDag-Erling Smørgrav ldns_verify_rrsig_keylist_notime(ldns_rr_list *rrset,
2353*7b5038d7SDag-Erling Smørgrav 					 ldns_rr *rrsig,
2354*7b5038d7SDag-Erling Smørgrav 					 const ldns_rr_list *keys,
2355*7b5038d7SDag-Erling Smørgrav 					 ldns_rr_list *good_keys)
2356*7b5038d7SDag-Erling Smørgrav {
2357*7b5038d7SDag-Erling Smørgrav 	ldns_buffer *rawsig_buf;
2358*7b5038d7SDag-Erling Smørgrav 	ldns_buffer *verify_buf;
2359*7b5038d7SDag-Erling Smørgrav 	uint16_t i;
2360*7b5038d7SDag-Erling Smørgrav 	ldns_status result, status;
2361*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list *rrset_clone;
2362*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list *validkeys;
2363*7b5038d7SDag-Erling Smørgrav 
2364*7b5038d7SDag-Erling Smørgrav 	if (!rrset) {
2365*7b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_ERR;
2366*7b5038d7SDag-Erling Smørgrav 	}
2367*7b5038d7SDag-Erling Smørgrav 
2368*7b5038d7SDag-Erling Smørgrav 	validkeys = ldns_rr_list_new();
2369*7b5038d7SDag-Erling Smørgrav 	if (!validkeys) {
2370*7b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_MEM_ERR;
2371*7b5038d7SDag-Erling Smørgrav 	}
2372*7b5038d7SDag-Erling Smørgrav 
2373*7b5038d7SDag-Erling Smørgrav 	/* clone the rrset so that we can fiddle with it */
2374*7b5038d7SDag-Erling Smørgrav 	rrset_clone = ldns_rr_list_clone(rrset);
2375*7b5038d7SDag-Erling Smørgrav 
2376*7b5038d7SDag-Erling Smørgrav 	/* create the buffers which will certainly hold the raw data */
2377*7b5038d7SDag-Erling Smørgrav 	rawsig_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN);
2378*7b5038d7SDag-Erling Smørgrav 	verify_buf  = ldns_buffer_new(LDNS_MAX_PACKETLEN);
2379*7b5038d7SDag-Erling Smørgrav 
2380*7b5038d7SDag-Erling Smørgrav 	result = ldns_prepare_for_verify(rawsig_buf, verify_buf,
2381*7b5038d7SDag-Erling Smørgrav 		rrset_clone, rrsig);
2382*7b5038d7SDag-Erling Smørgrav 	if(result != LDNS_STATUS_OK) {
2383*7b5038d7SDag-Erling Smørgrav 		ldns_buffer_free(verify_buf);
2384*7b5038d7SDag-Erling Smørgrav 		ldns_buffer_free(rawsig_buf);
2385*7b5038d7SDag-Erling Smørgrav 		ldns_rr_list_deep_free(rrset_clone);
2386*7b5038d7SDag-Erling Smørgrav 		ldns_rr_list_free(validkeys);
2387*7b5038d7SDag-Erling Smørgrav 		return result;
2388*7b5038d7SDag-Erling Smørgrav 	}
2389*7b5038d7SDag-Erling Smørgrav 
2390*7b5038d7SDag-Erling Smørgrav 	result = LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY;
2391*7b5038d7SDag-Erling Smørgrav 	for(i = 0; i < ldns_rr_list_rr_count(keys); i++) {
2392*7b5038d7SDag-Erling Smørgrav 		status = ldns_verify_test_sig_key(rawsig_buf, verify_buf,
2393*7b5038d7SDag-Erling Smørgrav 			rrsig, ldns_rr_list_rr(keys, i));
2394*7b5038d7SDag-Erling Smørgrav 		if (status == LDNS_STATUS_OK) {
2395*7b5038d7SDag-Erling Smørgrav 			/* one of the keys has matched, don't break
2396*7b5038d7SDag-Erling Smørgrav 			 * here, instead put the 'winning' key in
2397*7b5038d7SDag-Erling Smørgrav 			 * the validkey list and return the list
2398*7b5038d7SDag-Erling Smørgrav 			 * later */
2399*7b5038d7SDag-Erling Smørgrav 			if (!ldns_rr_list_push_rr(validkeys,
2400*7b5038d7SDag-Erling Smørgrav 				ldns_rr_list_rr(keys,i))) {
2401*7b5038d7SDag-Erling Smørgrav 				/* couldn't push the key?? */
2402*7b5038d7SDag-Erling Smørgrav 				ldns_buffer_free(rawsig_buf);
2403*7b5038d7SDag-Erling Smørgrav 				ldns_buffer_free(verify_buf);
2404*7b5038d7SDag-Erling Smørgrav 				ldns_rr_list_deep_free(rrset_clone);
2405*7b5038d7SDag-Erling Smørgrav 				ldns_rr_list_free(validkeys);
2406*7b5038d7SDag-Erling Smørgrav 				return LDNS_STATUS_MEM_ERR;
2407*7b5038d7SDag-Erling Smørgrav 			}
2408*7b5038d7SDag-Erling Smørgrav 
2409*7b5038d7SDag-Erling Smørgrav 			result = status;
2410*7b5038d7SDag-Erling Smørgrav 		}
2411*7b5038d7SDag-Erling Smørgrav 
2412*7b5038d7SDag-Erling Smørgrav 		if (result == LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY) {
2413*7b5038d7SDag-Erling Smørgrav 			result = status;
2414*7b5038d7SDag-Erling Smørgrav 		}
2415*7b5038d7SDag-Erling Smørgrav 	}
2416*7b5038d7SDag-Erling Smørgrav 
2417*7b5038d7SDag-Erling Smørgrav 	/* no longer needed */
2418*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list_deep_free(rrset_clone);
2419*7b5038d7SDag-Erling Smørgrav 	ldns_buffer_free(rawsig_buf);
2420*7b5038d7SDag-Erling Smørgrav 	ldns_buffer_free(verify_buf);
2421*7b5038d7SDag-Erling Smørgrav 
2422*7b5038d7SDag-Erling Smørgrav 	if (ldns_rr_list_rr_count(validkeys) == 0) {
2423*7b5038d7SDag-Erling Smørgrav 		/* no keys were added, return last error */
2424*7b5038d7SDag-Erling Smørgrav 		ldns_rr_list_free(validkeys);
2425*7b5038d7SDag-Erling Smørgrav 		return result;
2426*7b5038d7SDag-Erling Smørgrav 	}
2427*7b5038d7SDag-Erling Smørgrav 
2428*7b5038d7SDag-Erling Smørgrav 	/* do not check timestamps */
2429*7b5038d7SDag-Erling Smørgrav 
2430*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list_cat(good_keys, validkeys);
2431*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list_free(validkeys);
2432*7b5038d7SDag-Erling Smørgrav 	return LDNS_STATUS_OK;
2433*7b5038d7SDag-Erling Smørgrav }
2434*7b5038d7SDag-Erling Smørgrav 
2435*7b5038d7SDag-Erling Smørgrav ldns_status
2436*7b5038d7SDag-Erling Smørgrav ldns_verify_rrsig_time(
2437*7b5038d7SDag-Erling Smørgrav 		ldns_rr_list *rrset,
2438*7b5038d7SDag-Erling Smørgrav 		ldns_rr *rrsig,
2439*7b5038d7SDag-Erling Smørgrav 		ldns_rr *key,
2440*7b5038d7SDag-Erling Smørgrav 		time_t check_time)
2441*7b5038d7SDag-Erling Smørgrav {
2442*7b5038d7SDag-Erling Smørgrav 	ldns_buffer *rawsig_buf;
2443*7b5038d7SDag-Erling Smørgrav 	ldns_buffer *verify_buf;
2444*7b5038d7SDag-Erling Smørgrav 	ldns_status result;
2445*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list *rrset_clone;
2446*7b5038d7SDag-Erling Smørgrav 
2447*7b5038d7SDag-Erling Smørgrav 	if (!rrset) {
2448*7b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_NO_DATA;
2449*7b5038d7SDag-Erling Smørgrav 	}
2450*7b5038d7SDag-Erling Smørgrav 	/* clone the rrset so that we can fiddle with it */
2451*7b5038d7SDag-Erling Smørgrav 	rrset_clone = ldns_rr_list_clone(rrset);
2452*7b5038d7SDag-Erling Smørgrav 	/* create the buffers which will certainly hold the raw data */
2453*7b5038d7SDag-Erling Smørgrav 	rawsig_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN);
2454*7b5038d7SDag-Erling Smørgrav 	verify_buf  = ldns_buffer_new(LDNS_MAX_PACKETLEN);
2455*7b5038d7SDag-Erling Smørgrav 
2456*7b5038d7SDag-Erling Smørgrav 	result = ldns_prepare_for_verify(rawsig_buf, verify_buf,
2457*7b5038d7SDag-Erling Smørgrav 		rrset_clone, rrsig);
2458*7b5038d7SDag-Erling Smørgrav 	if(result != LDNS_STATUS_OK) {
2459*7b5038d7SDag-Erling Smørgrav 		ldns_rr_list_deep_free(rrset_clone);
2460*7b5038d7SDag-Erling Smørgrav 		ldns_buffer_free(rawsig_buf);
2461*7b5038d7SDag-Erling Smørgrav 		ldns_buffer_free(verify_buf);
2462*7b5038d7SDag-Erling Smørgrav 		return result;
2463*7b5038d7SDag-Erling Smørgrav 	}
2464*7b5038d7SDag-Erling Smørgrav 	result = ldns_verify_test_sig_key(rawsig_buf, verify_buf,
2465*7b5038d7SDag-Erling Smørgrav 		rrsig, key);
2466*7b5038d7SDag-Erling Smørgrav 	/* no longer needed */
2467*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list_deep_free(rrset_clone);
2468*7b5038d7SDag-Erling Smørgrav 	ldns_buffer_free(rawsig_buf);
2469*7b5038d7SDag-Erling Smørgrav 	ldns_buffer_free(verify_buf);
2470*7b5038d7SDag-Erling Smørgrav 
2471*7b5038d7SDag-Erling Smørgrav 	/* check timestamp last, apart from time its OK */
2472*7b5038d7SDag-Erling Smørgrav 	if(result == LDNS_STATUS_OK)
2473*7b5038d7SDag-Erling Smørgrav 		result = ldns_rrsig_check_timestamps(rrsig, check_time);
2474*7b5038d7SDag-Erling Smørgrav 
2475*7b5038d7SDag-Erling Smørgrav 	return result;
2476*7b5038d7SDag-Erling Smørgrav }
2477*7b5038d7SDag-Erling Smørgrav 
2478*7b5038d7SDag-Erling Smørgrav ldns_status
2479*7b5038d7SDag-Erling Smørgrav ldns_verify_rrsig(ldns_rr_list *rrset, ldns_rr *rrsig, ldns_rr *key)
2480*7b5038d7SDag-Erling Smørgrav {
2481*7b5038d7SDag-Erling Smørgrav 	return ldns_verify_rrsig_time(rrset, rrsig, key, ldns_time(NULL));
2482*7b5038d7SDag-Erling Smørgrav }
2483*7b5038d7SDag-Erling Smørgrav 
2484*7b5038d7SDag-Erling Smørgrav 
2485*7b5038d7SDag-Erling Smørgrav ldns_status
2486*7b5038d7SDag-Erling Smørgrav ldns_verify_rrsig_evp(ldns_buffer *sig,
2487*7b5038d7SDag-Erling Smørgrav 				  ldns_buffer *rrset,
2488*7b5038d7SDag-Erling Smørgrav 				  EVP_PKEY *key,
2489*7b5038d7SDag-Erling Smørgrav 				  const EVP_MD *digest_type)
2490*7b5038d7SDag-Erling Smørgrav {
2491*7b5038d7SDag-Erling Smørgrav 	return ldns_verify_rrsig_evp_raw(
2492*7b5038d7SDag-Erling Smørgrav 			 (unsigned char*)ldns_buffer_begin(sig),
2493*7b5038d7SDag-Erling Smørgrav 			 ldns_buffer_position(sig),
2494*7b5038d7SDag-Erling Smørgrav 			 rrset,
2495*7b5038d7SDag-Erling Smørgrav 			 key,
2496*7b5038d7SDag-Erling Smørgrav 			 digest_type);
2497*7b5038d7SDag-Erling Smørgrav }
2498*7b5038d7SDag-Erling Smørgrav 
2499*7b5038d7SDag-Erling Smørgrav ldns_status
2500*7b5038d7SDag-Erling Smørgrav ldns_verify_rrsig_evp_raw(unsigned char *sig, size_t siglen,
2501*7b5038d7SDag-Erling Smørgrav 					 ldns_buffer *rrset, EVP_PKEY *key, const EVP_MD *digest_type)
2502*7b5038d7SDag-Erling Smørgrav {
2503*7b5038d7SDag-Erling Smørgrav 	EVP_MD_CTX ctx;
2504*7b5038d7SDag-Erling Smørgrav 	int res;
2505*7b5038d7SDag-Erling Smørgrav 
2506*7b5038d7SDag-Erling Smørgrav 	EVP_MD_CTX_init(&ctx);
2507*7b5038d7SDag-Erling Smørgrav 
2508*7b5038d7SDag-Erling Smørgrav 	EVP_VerifyInit(&ctx, digest_type);
2509*7b5038d7SDag-Erling Smørgrav 	EVP_VerifyUpdate(&ctx,
2510*7b5038d7SDag-Erling Smørgrav 				  ldns_buffer_begin(rrset),
2511*7b5038d7SDag-Erling Smørgrav 				  ldns_buffer_position(rrset));
2512*7b5038d7SDag-Erling Smørgrav 	res = EVP_VerifyFinal(&ctx, sig, (unsigned int) siglen, key);
2513*7b5038d7SDag-Erling Smørgrav 
2514*7b5038d7SDag-Erling Smørgrav 	EVP_MD_CTX_cleanup(&ctx);
2515*7b5038d7SDag-Erling Smørgrav 
2516*7b5038d7SDag-Erling Smørgrav 	if (res == 1) {
2517*7b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_OK;
2518*7b5038d7SDag-Erling Smørgrav 	} else if (res == 0) {
2519*7b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_CRYPTO_BOGUS;
2520*7b5038d7SDag-Erling Smørgrav 	}
2521*7b5038d7SDag-Erling Smørgrav 	/* TODO how to communicate internal SSL error?
2522*7b5038d7SDag-Erling Smørgrav 	   let caller use ssl's get_error() */
2523*7b5038d7SDag-Erling Smørgrav 	return LDNS_STATUS_SSL_ERR;
2524*7b5038d7SDag-Erling Smørgrav }
2525*7b5038d7SDag-Erling Smørgrav 
2526*7b5038d7SDag-Erling Smørgrav ldns_status
2527*7b5038d7SDag-Erling Smørgrav ldns_verify_rrsig_dsa(ldns_buffer *sig, ldns_buffer *rrset, ldns_buffer *key)
2528*7b5038d7SDag-Erling Smørgrav {
2529*7b5038d7SDag-Erling Smørgrav 	return ldns_verify_rrsig_dsa_raw(
2530*7b5038d7SDag-Erling Smørgrav 			 (unsigned char*) ldns_buffer_begin(sig),
2531*7b5038d7SDag-Erling Smørgrav 			 ldns_buffer_position(sig),
2532*7b5038d7SDag-Erling Smørgrav 			 rrset,
2533*7b5038d7SDag-Erling Smørgrav 			 (unsigned char*) ldns_buffer_begin(key),
2534*7b5038d7SDag-Erling Smørgrav 			 ldns_buffer_position(key));
2535*7b5038d7SDag-Erling Smørgrav }
2536*7b5038d7SDag-Erling Smørgrav 
2537*7b5038d7SDag-Erling Smørgrav ldns_status
2538*7b5038d7SDag-Erling Smørgrav ldns_verify_rrsig_rsasha1(ldns_buffer *sig, ldns_buffer *rrset, ldns_buffer *key)
2539*7b5038d7SDag-Erling Smørgrav {
2540*7b5038d7SDag-Erling Smørgrav 	return ldns_verify_rrsig_rsasha1_raw(
2541*7b5038d7SDag-Erling Smørgrav 			 (unsigned char*)ldns_buffer_begin(sig),
2542*7b5038d7SDag-Erling Smørgrav 			 ldns_buffer_position(sig),
2543*7b5038d7SDag-Erling Smørgrav 			 rrset,
2544*7b5038d7SDag-Erling Smørgrav 			 (unsigned char*) ldns_buffer_begin(key),
2545*7b5038d7SDag-Erling Smørgrav 			 ldns_buffer_position(key));
2546*7b5038d7SDag-Erling Smørgrav }
2547*7b5038d7SDag-Erling Smørgrav 
2548*7b5038d7SDag-Erling Smørgrav ldns_status
2549*7b5038d7SDag-Erling Smørgrav ldns_verify_rrsig_rsamd5(ldns_buffer *sig, ldns_buffer *rrset, ldns_buffer *key)
2550*7b5038d7SDag-Erling Smørgrav {
2551*7b5038d7SDag-Erling Smørgrav 	return ldns_verify_rrsig_rsamd5_raw(
2552*7b5038d7SDag-Erling Smørgrav 			 (unsigned char*)ldns_buffer_begin(sig),
2553*7b5038d7SDag-Erling Smørgrav 			 ldns_buffer_position(sig),
2554*7b5038d7SDag-Erling Smørgrav 			 rrset,
2555*7b5038d7SDag-Erling Smørgrav 			 (unsigned char*) ldns_buffer_begin(key),
2556*7b5038d7SDag-Erling Smørgrav 			 ldns_buffer_position(key));
2557*7b5038d7SDag-Erling Smørgrav }
2558*7b5038d7SDag-Erling Smørgrav 
2559*7b5038d7SDag-Erling Smørgrav ldns_status
2560*7b5038d7SDag-Erling Smørgrav ldns_verify_rrsig_dsa_raw(unsigned char* sig, size_t siglen,
2561*7b5038d7SDag-Erling Smørgrav 					 ldns_buffer* rrset, unsigned char* key, size_t keylen)
2562*7b5038d7SDag-Erling Smørgrav {
2563*7b5038d7SDag-Erling Smørgrav 	EVP_PKEY *evp_key;
2564*7b5038d7SDag-Erling Smørgrav 	ldns_status result;
2565*7b5038d7SDag-Erling Smørgrav 
2566*7b5038d7SDag-Erling Smørgrav 	evp_key = EVP_PKEY_new();
2567*7b5038d7SDag-Erling Smørgrav 	if (EVP_PKEY_assign_DSA(evp_key, ldns_key_buf2dsa_raw(key, keylen))) {
2568*7b5038d7SDag-Erling Smørgrav 		result = ldns_verify_rrsig_evp_raw(sig,
2569*7b5038d7SDag-Erling Smørgrav 								siglen,
2570*7b5038d7SDag-Erling Smørgrav 								rrset,
2571*7b5038d7SDag-Erling Smørgrav 								evp_key,
2572*7b5038d7SDag-Erling Smørgrav 								EVP_dss1());
2573*7b5038d7SDag-Erling Smørgrav 	} else {
2574*7b5038d7SDag-Erling Smørgrav 		result = LDNS_STATUS_SSL_ERR;
2575*7b5038d7SDag-Erling Smørgrav 	}
2576*7b5038d7SDag-Erling Smørgrav 	EVP_PKEY_free(evp_key);
2577*7b5038d7SDag-Erling Smørgrav 	return result;
2578*7b5038d7SDag-Erling Smørgrav 
2579*7b5038d7SDag-Erling Smørgrav }
2580*7b5038d7SDag-Erling Smørgrav 
2581*7b5038d7SDag-Erling Smørgrav ldns_status
2582*7b5038d7SDag-Erling Smørgrav ldns_verify_rrsig_rsasha1_raw(unsigned char* sig, size_t siglen,
2583*7b5038d7SDag-Erling Smørgrav 						ldns_buffer* rrset, unsigned char* key, size_t keylen)
2584*7b5038d7SDag-Erling Smørgrav {
2585*7b5038d7SDag-Erling Smørgrav 	EVP_PKEY *evp_key;
2586*7b5038d7SDag-Erling Smørgrav 	ldns_status result;
2587*7b5038d7SDag-Erling Smørgrav 
2588*7b5038d7SDag-Erling Smørgrav 	evp_key = EVP_PKEY_new();
2589*7b5038d7SDag-Erling Smørgrav 	if (EVP_PKEY_assign_RSA(evp_key, ldns_key_buf2rsa_raw(key, keylen))) {
2590*7b5038d7SDag-Erling Smørgrav 		result = ldns_verify_rrsig_evp_raw(sig,
2591*7b5038d7SDag-Erling Smørgrav 								siglen,
2592*7b5038d7SDag-Erling Smørgrav 								rrset,
2593*7b5038d7SDag-Erling Smørgrav 								evp_key,
2594*7b5038d7SDag-Erling Smørgrav 								EVP_sha1());
2595*7b5038d7SDag-Erling Smørgrav 	} else {
2596*7b5038d7SDag-Erling Smørgrav 		result = LDNS_STATUS_SSL_ERR;
2597*7b5038d7SDag-Erling Smørgrav 	}
2598*7b5038d7SDag-Erling Smørgrav 	EVP_PKEY_free(evp_key);
2599*7b5038d7SDag-Erling Smørgrav 
2600*7b5038d7SDag-Erling Smørgrav 	return result;
2601*7b5038d7SDag-Erling Smørgrav }
2602*7b5038d7SDag-Erling Smørgrav 
2603*7b5038d7SDag-Erling Smørgrav ldns_status
2604*7b5038d7SDag-Erling Smørgrav ldns_verify_rrsig_rsasha256_raw(unsigned char* sig,
2605*7b5038d7SDag-Erling Smørgrav 						  size_t siglen,
2606*7b5038d7SDag-Erling Smørgrav 						  ldns_buffer* rrset,
2607*7b5038d7SDag-Erling Smørgrav 						  unsigned char* key,
2608*7b5038d7SDag-Erling Smørgrav 						  size_t keylen)
2609*7b5038d7SDag-Erling Smørgrav {
2610*7b5038d7SDag-Erling Smørgrav #ifdef USE_SHA2
2611*7b5038d7SDag-Erling Smørgrav 	EVP_PKEY *evp_key;
2612*7b5038d7SDag-Erling Smørgrav 	ldns_status result;
2613*7b5038d7SDag-Erling Smørgrav 
2614*7b5038d7SDag-Erling Smørgrav 	evp_key = EVP_PKEY_new();
2615*7b5038d7SDag-Erling Smørgrav 	if (EVP_PKEY_assign_RSA(evp_key, ldns_key_buf2rsa_raw(key, keylen))) {
2616*7b5038d7SDag-Erling Smørgrav 		result = ldns_verify_rrsig_evp_raw(sig,
2617*7b5038d7SDag-Erling Smørgrav 								siglen,
2618*7b5038d7SDag-Erling Smørgrav 								rrset,
2619*7b5038d7SDag-Erling Smørgrav 								evp_key,
2620*7b5038d7SDag-Erling Smørgrav 								EVP_sha256());
2621*7b5038d7SDag-Erling Smørgrav 	} else {
2622*7b5038d7SDag-Erling Smørgrav 		result = LDNS_STATUS_SSL_ERR;
2623*7b5038d7SDag-Erling Smørgrav 	}
2624*7b5038d7SDag-Erling Smørgrav 	EVP_PKEY_free(evp_key);
2625*7b5038d7SDag-Erling Smørgrav 
2626*7b5038d7SDag-Erling Smørgrav 	return result;
2627*7b5038d7SDag-Erling Smørgrav #else
2628*7b5038d7SDag-Erling Smørgrav 	/* touch these to prevent compiler warnings */
2629*7b5038d7SDag-Erling Smørgrav 	(void) sig;
2630*7b5038d7SDag-Erling Smørgrav 	(void) siglen;
2631*7b5038d7SDag-Erling Smørgrav 	(void) rrset;
2632*7b5038d7SDag-Erling Smørgrav 	(void) key;
2633*7b5038d7SDag-Erling Smørgrav 	(void) keylen;
2634*7b5038d7SDag-Erling Smørgrav 	return LDNS_STATUS_CRYPTO_UNKNOWN_ALGO;
2635*7b5038d7SDag-Erling Smørgrav #endif
2636*7b5038d7SDag-Erling Smørgrav }
2637*7b5038d7SDag-Erling Smørgrav 
2638*7b5038d7SDag-Erling Smørgrav ldns_status
2639*7b5038d7SDag-Erling Smørgrav ldns_verify_rrsig_rsasha512_raw(unsigned char* sig,
2640*7b5038d7SDag-Erling Smørgrav 						  size_t siglen,
2641*7b5038d7SDag-Erling Smørgrav 						  ldns_buffer* rrset,
2642*7b5038d7SDag-Erling Smørgrav 						  unsigned char* key,
2643*7b5038d7SDag-Erling Smørgrav 						  size_t keylen)
2644*7b5038d7SDag-Erling Smørgrav {
2645*7b5038d7SDag-Erling Smørgrav #ifdef USE_SHA2
2646*7b5038d7SDag-Erling Smørgrav 	EVP_PKEY *evp_key;
2647*7b5038d7SDag-Erling Smørgrav 	ldns_status result;
2648*7b5038d7SDag-Erling Smørgrav 
2649*7b5038d7SDag-Erling Smørgrav 	evp_key = EVP_PKEY_new();
2650*7b5038d7SDag-Erling Smørgrav 	if (EVP_PKEY_assign_RSA(evp_key, ldns_key_buf2rsa_raw(key, keylen))) {
2651*7b5038d7SDag-Erling Smørgrav 		result = ldns_verify_rrsig_evp_raw(sig,
2652*7b5038d7SDag-Erling Smørgrav 								siglen,
2653*7b5038d7SDag-Erling Smørgrav 								rrset,
2654*7b5038d7SDag-Erling Smørgrav 								evp_key,
2655*7b5038d7SDag-Erling Smørgrav 								EVP_sha512());
2656*7b5038d7SDag-Erling Smørgrav 	} else {
2657*7b5038d7SDag-Erling Smørgrav 		result = LDNS_STATUS_SSL_ERR;
2658*7b5038d7SDag-Erling Smørgrav 	}
2659*7b5038d7SDag-Erling Smørgrav 	EVP_PKEY_free(evp_key);
2660*7b5038d7SDag-Erling Smørgrav 
2661*7b5038d7SDag-Erling Smørgrav 	return result;
2662*7b5038d7SDag-Erling Smørgrav #else
2663*7b5038d7SDag-Erling Smørgrav 	/* touch these to prevent compiler warnings */
2664*7b5038d7SDag-Erling Smørgrav 	(void) sig;
2665*7b5038d7SDag-Erling Smørgrav 	(void) siglen;
2666*7b5038d7SDag-Erling Smørgrav 	(void) rrset;
2667*7b5038d7SDag-Erling Smørgrav 	(void) key;
2668*7b5038d7SDag-Erling Smørgrav 	(void) keylen;
2669*7b5038d7SDag-Erling Smørgrav 	return LDNS_STATUS_CRYPTO_UNKNOWN_ALGO;
2670*7b5038d7SDag-Erling Smørgrav #endif
2671*7b5038d7SDag-Erling Smørgrav }
2672*7b5038d7SDag-Erling Smørgrav 
2673*7b5038d7SDag-Erling Smørgrav 
2674*7b5038d7SDag-Erling Smørgrav ldns_status
2675*7b5038d7SDag-Erling Smørgrav ldns_verify_rrsig_rsamd5_raw(unsigned char* sig,
2676*7b5038d7SDag-Erling Smørgrav 					    size_t siglen,
2677*7b5038d7SDag-Erling Smørgrav 					    ldns_buffer* rrset,
2678*7b5038d7SDag-Erling Smørgrav 					    unsigned char* key,
2679*7b5038d7SDag-Erling Smørgrav 					    size_t keylen)
2680*7b5038d7SDag-Erling Smørgrav {
2681*7b5038d7SDag-Erling Smørgrav 	EVP_PKEY *evp_key;
2682*7b5038d7SDag-Erling Smørgrav 	ldns_status result;
2683*7b5038d7SDag-Erling Smørgrav 
2684*7b5038d7SDag-Erling Smørgrav 	evp_key = EVP_PKEY_new();
2685*7b5038d7SDag-Erling Smørgrav 	if (EVP_PKEY_assign_RSA(evp_key, ldns_key_buf2rsa_raw(key, keylen))) {
2686*7b5038d7SDag-Erling Smørgrav 		result = ldns_verify_rrsig_evp_raw(sig,
2687*7b5038d7SDag-Erling Smørgrav 								siglen,
2688*7b5038d7SDag-Erling Smørgrav 								rrset,
2689*7b5038d7SDag-Erling Smørgrav 								evp_key,
2690*7b5038d7SDag-Erling Smørgrav 								EVP_md5());
2691*7b5038d7SDag-Erling Smørgrav 	} else {
2692*7b5038d7SDag-Erling Smørgrav 		result = LDNS_STATUS_SSL_ERR;
2693*7b5038d7SDag-Erling Smørgrav 	}
2694*7b5038d7SDag-Erling Smørgrav 	EVP_PKEY_free(evp_key);
2695*7b5038d7SDag-Erling Smørgrav 
2696*7b5038d7SDag-Erling Smørgrav 	return result;
2697*7b5038d7SDag-Erling Smørgrav }
2698*7b5038d7SDag-Erling Smørgrav 
2699*7b5038d7SDag-Erling Smørgrav #endif
2700