dnssec_verify.c revision 246883
119370Spst#include <ldns/config.h>
298948Sobrien
3130809Smarcel#include <ldns/ldns.h>
419370Spst
519370Spst#include <strings.h>
698948Sobrien#include <time.h>
719370Spst
898948Sobrien#ifdef HAVE_SSL
998948Sobrien/* this entire file is rather useless when you don't have
1098948Sobrien * crypto...
1198948Sobrien */
1219370Spst#include <openssl/ssl.h>
1398948Sobrien#include <openssl/evp.h>
1498948Sobrien#include <openssl/rand.h>
1598948Sobrien#include <openssl/err.h>
1698948Sobrien#include <openssl/md5.h>
1719370Spst
1898948Sobrienldns_dnssec_data_chain *
1998948Sobrienldns_dnssec_data_chain_new(void)
2098948Sobrien{
2198948Sobrien	ldns_dnssec_data_chain *nc = LDNS_CALLOC(ldns_dnssec_data_chain, 1);
2219370Spst        if(!nc) return NULL;
2319370Spst	/*
2419370Spst	 * not needed anymore because CALLOC initalizes everything to zero.
2519370Spst
2619370Spst	nc->rrset = NULL;
2719370Spst	nc->parent_type = 0;
2819370Spst	nc->parent = NULL;
2919370Spst	nc->signatures = NULL;
3019370Spst	nc->packet_rcode = 0;
3119370Spst	nc->packet_qtype = 0;
3219370Spst	nc->packet_nodata = false;
3319370Spst
3419370Spst	 */
3519370Spst	return nc;
3619370Spst}
3719370Spst
3819370Spstvoid
3919370Spstldns_dnssec_data_chain_free(ldns_dnssec_data_chain *chain)
4019370Spst{
4119370Spst	LDNS_FREE(chain);
4219370Spst}
4319370Spst
4419370Spstvoid
45130809Smarcelldns_dnssec_data_chain_deep_free(ldns_dnssec_data_chain *chain)
4619370Spst{
4719370Spst	ldns_rr_list_deep_free(chain->rrset);
4819370Spst	ldns_rr_list_deep_free(chain->signatures);
4919370Spst	if (chain->parent) {
5019370Spst		ldns_dnssec_data_chain_deep_free(chain->parent);
5198948Sobrien	}
5219370Spst	LDNS_FREE(chain);
5319370Spst}
5419370Spst
5519370Spstvoid
5619370Spstldns_dnssec_data_chain_print_fmt(FILE *out, const ldns_output_format *fmt,
5798948Sobrien		const ldns_dnssec_data_chain *chain)
5819370Spst{
5998948Sobrien	ldns_lookup_table *rcode;
60130809Smarcel	const ldns_rr_descriptor *rr_descriptor;
6119370Spst	if (chain) {
6219370Spst		ldns_dnssec_data_chain_print_fmt(out, fmt, chain->parent);
6319370Spst		if (ldns_rr_list_rr_count(chain->rrset) > 0) {
6498948Sobrien			rcode = ldns_lookup_by_id(ldns_rcodes,
6519370Spst								 (int) chain->packet_rcode);
6619370Spst			if (rcode) {
6719370Spst				fprintf(out, ";; rcode: %s\n", rcode->name);
6819370Spst			}
6998948Sobrien
7098948Sobrien			rr_descriptor = ldns_rr_descript(chain->packet_qtype);
7198948Sobrien			if (rr_descriptor && rr_descriptor->_name) {
7298948Sobrien				fprintf(out, ";; qtype: %s\n", rr_descriptor->_name);
7319370Spst			} else if (chain->packet_qtype != 0) {
7498948Sobrien				fprintf(out, "TYPE%u",
7519370Spst					   chain->packet_qtype);
7698948Sobrien			}
7798948Sobrien			if (chain->packet_nodata) {
7898948Sobrien				fprintf(out, ";; NODATA response\n");
7998948Sobrien			}
8098948Sobrien			fprintf(out, "rrset:\n");
8119370Spst			ldns_rr_list_print_fmt(out, fmt, chain->rrset);
8298948Sobrien			fprintf(out, "sigs:\n");
8319370Spst			ldns_rr_list_print_fmt(out, fmt, chain->signatures);
8498948Sobrien			fprintf(out, "---\n");
8519370Spst		} else {
8698948Sobrien			fprintf(out, "<no data>\n");
8719370Spst		}
8898948Sobrien	}
8998948Sobrien}
9019370Spstvoid
9198948Sobrienldns_dnssec_data_chain_print(FILE *out, const ldns_dnssec_data_chain *chain)
9298948Sobrien{
9398948Sobrien	ldns_dnssec_data_chain_print_fmt(
9498948Sobrien			out, ldns_output_format_default, chain);
9519370Spst}
9619370Spst
9719370Spst
9819370Spststatic void
9919370Spstldns_dnssec_build_data_chain_dnskey(ldns_resolver *res,
10019370Spst					    uint16_t qflags,
10119370Spst					    const ldns_pkt *pkt,
10219370Spst					    ldns_rr_list *signatures,
10398948Sobrien						ldns_dnssec_data_chain *new_chain,
10419370Spst						ldns_rdf *key_name,
10519370Spst						ldns_rr_class c) {
10619370Spst	ldns_rr_list *keys;
10719370Spst	ldns_pkt *my_pkt;
10819370Spst	if (signatures && ldns_rr_list_rr_count(signatures) > 0) {
10919370Spst		new_chain->signatures = ldns_rr_list_clone(signatures);
11019370Spst		new_chain->parent_type = 0;
11119370Spst
11219370Spst		keys = ldns_pkt_rr_list_by_name_and_type(
11319370Spst				  pkt,
11419370Spst				 key_name,
11519370Spst				 LDNS_RR_TYPE_DNSKEY,
11619370Spst				 LDNS_SECTION_ANY_NOQUESTION
11719370Spst			  );
11819370Spst		if (!keys) {
11946283Sdfr			my_pkt = ldns_resolver_query(res,
12046283Sdfr									key_name,
12119370Spst									LDNS_RR_TYPE_DNSKEY,
12219370Spst									c,
12346283Sdfr									qflags);
12446283Sdfr			if (my_pkt) {
12519370Spst			keys = ldns_pkt_rr_list_by_name_and_type(
12619370Spst					  my_pkt,
12719370Spst					 key_name,
12846283Sdfr					 LDNS_RR_TYPE_DNSKEY,
12946283Sdfr					 LDNS_SECTION_ANY_NOQUESTION
13046283Sdfr				  );
13146283Sdfr			new_chain->parent = ldns_dnssec_build_data_chain(res,
13246283Sdfr													qflags,
13319370Spst													keys,
13419370Spst													my_pkt,
13519370Spst													NULL);
13646283Sdfr			new_chain->parent->packet_qtype = LDNS_RR_TYPE_DNSKEY;
13746283Sdfr			ldns_pkt_free(my_pkt);
13846283Sdfr			}
13919370Spst		} else {
14019370Spst			new_chain->parent = ldns_dnssec_build_data_chain(res,
14119370Spst													qflags,
14246283Sdfr													keys,
14346283Sdfr													pkt,
14419370Spst													NULL);
14519370Spst			new_chain->parent->packet_qtype = LDNS_RR_TYPE_DNSKEY;
14619370Spst		}
14719370Spst		ldns_rr_list_deep_free(keys);
14819370Spst	}
14919370Spst}
15019370Spst
15119370Spststatic void
15246283Sdfrldns_dnssec_build_data_chain_other(ldns_resolver *res,
15319370Spst					    uint16_t qflags,
15419370Spst						ldns_dnssec_data_chain *new_chain,
15546283Sdfr						ldns_rdf *key_name,
15646283Sdfr						ldns_rr_class c,
15746283Sdfr						ldns_rr_list *dss)
15846283Sdfr{
15946283Sdfr	/* 'self-signed', parent is a DS */
16019370Spst
16119370Spst	/* okay, either we have other keys signing the current one,
162130809Smarcel	 * or the current
163130809Smarcel	 * one should have a DS record in the parent zone.
164130809Smarcel	 * How do we find this out? Try both?
165130809Smarcel	 *
166130809Smarcel	 * request DNSKEYS for current zone,
16719370Spst	 * add all signatures to current level
168130809Smarcel	 */
169130809Smarcel	ldns_pkt *my_pkt;
170130809Smarcel	ldns_rr_list *signatures2;
171130809Smarcel
172130809Smarcel	new_chain->parent_type = 1;
173130809Smarcel
17419370Spst	my_pkt = ldns_resolver_query(res,
175130809Smarcel							key_name,
176130809Smarcel							LDNS_RR_TYPE_DS,
177130809Smarcel							c,
178130809Smarcel							qflags);
179130809Smarcel	if (my_pkt) {
180130809Smarcel	dss = ldns_pkt_rr_list_by_name_and_type(my_pkt,
181130809Smarcel									key_name,
18219370Spst									LDNS_RR_TYPE_DS,
18398948Sobrien									LDNS_SECTION_ANY_NOQUESTION
18498948Sobrien									);
18598948Sobrien	if (dss) {
18698948Sobrien		new_chain->parent = ldns_dnssec_build_data_chain(res,
18798948Sobrien												qflags,
18898948Sobrien												dss,
18998948Sobrien												my_pkt,
19098948Sobrien												NULL);
19198948Sobrien		new_chain->parent->packet_qtype = LDNS_RR_TYPE_DS;
19298948Sobrien		ldns_rr_list_deep_free(dss);
19398948Sobrien	}
19498948Sobrien	ldns_pkt_free(my_pkt);
19598948Sobrien	}
19698948Sobrien
19798948Sobrien	my_pkt = ldns_resolver_query(res,
19898948Sobrien							key_name,
19998948Sobrien							LDNS_RR_TYPE_DNSKEY,
20098948Sobrien							c,
20198948Sobrien							qflags);
20298948Sobrien	if (my_pkt) {
20398948Sobrien	signatures2 = ldns_pkt_rr_list_by_name_and_type(my_pkt,
20498948Sobrien										   key_name,
20598948Sobrien										   LDNS_RR_TYPE_RRSIG,
20698948Sobrien										   LDNS_SECTION_ANSWER);
20798948Sobrien	if (signatures2) {
20898948Sobrien		if (new_chain->signatures) {
20998948Sobrien			printf("There were already sigs!\n");
21098948Sobrien			ldns_rr_list_deep_free(new_chain->signatures);
21198948Sobrien			printf("replacing the old sigs\n");
21298948Sobrien		}
21398948Sobrien		new_chain->signatures = signatures2;
21498948Sobrien	}
21598948Sobrien	ldns_pkt_free(my_pkt);
21698948Sobrien	}
21798948Sobrien}
21898948Sobrien
21998948Sobrienstatic ldns_dnssec_data_chain *
22098948Sobrienldns_dnssec_build_data_chain_nokeyname(ldns_resolver *res,
22198948Sobrien                                       uint16_t qflags,
22298948Sobrien                                       ldns_rr *orig_rr,
22398948Sobrien                                       const ldns_rr_list *rrset,
22498948Sobrien                                       ldns_dnssec_data_chain *new_chain)
22598948Sobrien{
22698948Sobrien	ldns_rdf *possible_parent_name;
22798948Sobrien	ldns_pkt *my_pkt;
22898948Sobrien	/* apparently we were not able to find a signing key, so
22998948Sobrien	   we assume the chain ends here
23098948Sobrien	*/
23119370Spst	/* try parents for auth denial of DS */
23219370Spst	if (orig_rr) {
23319370Spst		possible_parent_name = ldns_rr_owner(orig_rr);
23419370Spst	} else if (rrset && ldns_rr_list_rr_count(rrset) > 0) {
23519370Spst		possible_parent_name = ldns_rr_owner(ldns_rr_list_rr(rrset, 0));
23619370Spst	} else {
23719370Spst		/* no information to go on, give up */
23819370Spst		return new_chain;
23919370Spst	}
24019370Spst
24119370Spst	my_pkt = ldns_resolver_query(res,
24219370Spst	              possible_parent_name,
24319370Spst	              LDNS_RR_TYPE_DS,
24419370Spst	              LDNS_RR_CLASS_IN,
24519370Spst	              qflags);
24619370Spst	if (!my_pkt) {
24719370Spst		return new_chain;
24819370Spst	}
24919370Spst
25098948Sobrien	if (ldns_pkt_ancount(my_pkt) > 0) {
25146283Sdfr		/* add error, no sigs but DS in parent */
25298948Sobrien		/*ldns_pkt_print(stdout, my_pkt);*/
25319370Spst		ldns_pkt_free(my_pkt);
25498948Sobrien	} else {
25519370Spst		/* are there signatures? */
25698948Sobrien		new_chain->parent =  ldns_dnssec_build_data_chain(res,
25719370Spst		                          qflags,
25898948Sobrien		                          NULL,
25919370Spst		                          my_pkt,
26098948Sobrien		                          NULL);
26119370Spst
26298948Sobrien		new_chain->parent->packet_qtype = LDNS_RR_TYPE_DS;
26319370Spst
26498948Sobrien	}
26519370Spst	return new_chain;
26698948Sobrien}
26719370Spst
26898948Sobrien
26919370Spstldns_dnssec_data_chain *
27098948Sobrienldns_dnssec_build_data_chain(ldns_resolver *res,
27119370Spst					    uint16_t qflags,
27298948Sobrien					    const ldns_rr_list *rrset,
27319370Spst					    const ldns_pkt *pkt,
27498948Sobrien					    ldns_rr *orig_rr)
27519370Spst{
27698948Sobrien	ldns_rr_list *signatures = NULL;
27719370Spst	ldns_rr_list *dss = NULL;
27898948Sobrien
27919370Spst	ldns_rr_list *my_rrset;
28098948Sobrien
28119370Spst	ldns_pkt *my_pkt;
28298948Sobrien
28319370Spst	ldns_rdf *name = NULL, *key_name = NULL;
28498948Sobrien	ldns_rr_type type = 0;
28519370Spst	ldns_rr_class c = 0;
28698948Sobrien
28719370Spst	bool other_rrset = false;
28898948Sobrien
28919370Spst	ldns_dnssec_data_chain *new_chain = ldns_dnssec_data_chain_new();
29098948Sobrien
29198948Sobrien	assert(pkt != NULL);
29298948Sobrien
29398948Sobrien	if (!ldns_dnssec_pkt_has_rrsigs(pkt)) {
29419370Spst		/* hmm. no dnssec data in the packet. go up to try and deny
29519370Spst		 * DS? */
29619370Spst		return new_chain;
29798948Sobrien	}
29898948Sobrien
29919370Spst	if (orig_rr) {
30019370Spst		new_chain->rrset = ldns_rr_list_new();
30119370Spst		ldns_rr_list_push_rr(new_chain->rrset, orig_rr);
30298948Sobrien		new_chain->parent = ldns_dnssec_build_data_chain(res,
30319370Spst											    qflags,
30419370Spst											    rrset,
30519370Spst											    pkt,
30619370Spst											    NULL);
30719370Spst		new_chain->packet_rcode = ldns_pkt_get_rcode(pkt);
30819370Spst		new_chain->packet_qtype = ldns_rr_get_type(orig_rr);
30919370Spst		if (ldns_pkt_ancount(pkt) == 0) {
31098948Sobrien			new_chain->packet_nodata = true;
31198948Sobrien		}
31219370Spst		return new_chain;
31319370Spst	}
31419370Spst
31519370Spst	if (!rrset || ldns_rr_list_rr_count(rrset) < 1) {
31619370Spst		/* hmm, no data, do we have denial? only works if pkt was given,
31719370Spst		   otherwise caller has to do the check himself */
31819370Spst		new_chain->packet_nodata = true;
31919370Spst		if (pkt) {
32019370Spst			my_rrset = ldns_pkt_rr_list_by_type(pkt,
32198948Sobrien										 LDNS_RR_TYPE_NSEC,
32219370Spst										 LDNS_SECTION_ANY_NOQUESTION
32319370Spst										 );
32419370Spst			if (my_rrset) {
32519370Spst				if (ldns_rr_list_rr_count(my_rrset) > 0) {
32619370Spst					type = LDNS_RR_TYPE_NSEC;
32719370Spst					other_rrset = true;
32898948Sobrien				} else {
32919370Spst					ldns_rr_list_deep_free(my_rrset);
33019370Spst					my_rrset = NULL;
33119370Spst				}
33219370Spst			} else {
33319370Spst				/* nothing, try nsec3 */
33419370Spst				my_rrset = ldns_pkt_rr_list_by_type(pkt,
33519370Spst						     LDNS_RR_TYPE_NSEC3,
33619370Spst							LDNS_SECTION_ANY_NOQUESTION);
33719370Spst				if (my_rrset) {
33819370Spst					if (ldns_rr_list_rr_count(my_rrset) > 0) {
33919370Spst						type = LDNS_RR_TYPE_NSEC3;
34098948Sobrien						other_rrset = true;
34119370Spst					} else {
342130809Smarcel						ldns_rr_list_deep_free(my_rrset);
343130809Smarcel						my_rrset = NULL;
34419370Spst					}
34546283Sdfr				} else {
346130809Smarcel					/* nothing, stop */
34719370Spst					/* try parent zone? for denied insecure? */
34819370Spst					return new_chain;
34919370Spst				}
35019370Spst			}
351130809Smarcel		} else {
35219370Spst			return new_chain;
35319370Spst		}
35419370Spst	} else {
35519370Spst		my_rrset = (ldns_rr_list *) rrset;
35619370Spst	}
35719370Spst
35819370Spst	if (my_rrset && ldns_rr_list_rr_count(my_rrset) > 0) {
35919370Spst		new_chain->rrset = ldns_rr_list_clone(my_rrset);
36019370Spst		name = ldns_rr_owner(ldns_rr_list_rr(my_rrset, 0));
36119370Spst		type = ldns_rr_get_type(ldns_rr_list_rr(my_rrset, 0));
36219370Spst		c = ldns_rr_get_class(ldns_rr_list_rr(my_rrset, 0));
36319370Spst	}
36419370Spst
36519370Spst	if (other_rrset) {
36698948Sobrien		ldns_rr_list_deep_free(my_rrset);
36719370Spst	}
368130809Smarcel
369130809Smarcel	/* normally there will only be 1 signature 'set'
37019370Spst	   but there can be more than 1 denial (wildcards)
37119370Spst	   so check for NSEC
37219370Spst	*/
37346283Sdfr	if (type == LDNS_RR_TYPE_NSEC || type == LDNS_RR_TYPE_NSEC3) {
37446283Sdfr		/* just throw in all signatures, the tree builder must sort
37546283Sdfr		   this out */
37619370Spst		if (pkt) {
37746283Sdfr			signatures = ldns_dnssec_pkt_get_rrsigs_for_type(pkt, type);
37846283Sdfr		} else {
37946283Sdfr			my_pkt = ldns_resolver_query(res, name, type, c, qflags);
38046283Sdfr			if (my_pkt) {
38146283Sdfr			signatures = ldns_dnssec_pkt_get_rrsigs_for_type(pkt, type);
38246283Sdfr			ldns_pkt_free(my_pkt);
38346283Sdfr			}
38446283Sdfr		}
38546283Sdfr	} else {
38646283Sdfr		if (pkt) {
38746283Sdfr			signatures =
38846283Sdfr				ldns_dnssec_pkt_get_rrsigs_for_name_and_type(pkt,
38946283Sdfr													name,
39046283Sdfr													type);
39119370Spst		}
39219370Spst		if (!signatures) {
39319370Spst			my_pkt = ldns_resolver_query(res, name, type, c, qflags);
39419370Spst			if (my_pkt) {
39546283Sdfr			signatures =
39646283Sdfr				ldns_dnssec_pkt_get_rrsigs_for_name_and_type(my_pkt,
39798948Sobrien													name,
39846283Sdfr													type);
39946283Sdfr			ldns_pkt_free(my_pkt);
40046283Sdfr			}
40119370Spst		}
40246283Sdfr	}
40319370Spst
40419370Spst	if (signatures && ldns_rr_list_rr_count(signatures) > 0) {
40519370Spst		key_name = ldns_rr_rdf(ldns_rr_list_rr(signatures, 0), 7);
40619370Spst	}
40719370Spst	if (!key_name) {
40819370Spst		if (signatures) {
40998948Sobrien			ldns_rr_list_deep_free(signatures);
41019370Spst		}
411130809Smarcel		return ldns_dnssec_build_data_chain_nokeyname(res,
41219370Spst		                                              qflags,
41319370Spst		                                              orig_rr,
41419370Spst		                                              rrset,
41519370Spst		                                              new_chain);
41619370Spst	}
41719370Spst	if (type != LDNS_RR_TYPE_DNSKEY) {
41819370Spst		ldns_dnssec_build_data_chain_dnskey(res,
41998948Sobrien		                                    qflags,
42019370Spst		                                    pkt,
42119370Spst		                                    signatures,
42219370Spst		                                    new_chain,
42319370Spst		                                    key_name,
42419370Spst		                                    c
42519370Spst		                                   );
42698948Sobrien	} else {
42798948Sobrien		ldns_dnssec_build_data_chain_other(res,
42819370Spst		                                   qflags,
42919370Spst		                                   new_chain,
43019370Spst		                                   key_name,
43146283Sdfr		                                   c,
43219370Spst		                                   dss
43319370Spst		                                  );
43419370Spst	}
43519370Spst	if (signatures) {
43619370Spst		ldns_rr_list_deep_free(signatures);
43798948Sobrien	}
43846283Sdfr	return new_chain;
43919370Spst}
44019370Spst
44119370Spstldns_dnssec_trust_tree *
44298948Sobrienldns_dnssec_trust_tree_new(void)
44346283Sdfr{
44419370Spst	ldns_dnssec_trust_tree *new_tree = LDNS_XMALLOC(ldns_dnssec_trust_tree,
44519370Spst										   1);
44619370Spst        if(!new_tree) return NULL;
44798948Sobrien	new_tree->rr = NULL;
44846283Sdfr	new_tree->rrset = NULL;
44919370Spst	new_tree->parent_count = 0;
45019370Spst
45119370Spst	return new_tree;
45219370Spst}
45346283Sdfr
45419370Spstvoid
45519370Spstldns_dnssec_trust_tree_free(ldns_dnssec_trust_tree *tree)
45619370Spst{
45719370Spst	size_t i;
45898948Sobrien	if (tree) {
45946283Sdfr		for (i = 0; i < tree->parent_count; i++) {
46019370Spst			ldns_dnssec_trust_tree_free(tree->parents[i]);
46119370Spst		}
46219370Spst	}
46398948Sobrien	LDNS_FREE(tree);
46498948Sobrien}
46519370Spst
46698948Sobriensize_t
46746283Sdfrldns_dnssec_trust_tree_depth(ldns_dnssec_trust_tree *tree)
46819370Spst{
46919370Spst	size_t result = 0;
47019370Spst	size_t parent = 0;
47119370Spst	size_t i;
47219370Spst
47319370Spst	for (i = 0; i < tree->parent_count; i++) {
47419370Spst		parent = ldns_dnssec_trust_tree_depth(tree->parents[i]);
47598948Sobrien		if (parent > result) {
47646283Sdfr			result = parent;
47719370Spst		}
47819370Spst	}
47919370Spst	return 1 + result;
48019370Spst}
48119370Spst
48298948Sobrien/* TODO ldns_ */
48398948Sobrienstatic void
48498948Sobrienprint_tabs(FILE *out, size_t nr, uint8_t *map, size_t treedepth)
485130809Smarcel{
48619370Spst	size_t i;
48719370Spst	for (i = 0; i < nr; i++) {
48819370Spst		if (i == nr - 1) {
48919370Spst			fprintf(out, "|---");
49019370Spst		} else if (map && i < treedepth && map[i] == 1) {
49119370Spst			fprintf(out, "|   ");
49219370Spst		} else {
49398948Sobrien			fprintf(out, "    ");
49419370Spst		}
49519370Spst	}
49698948Sobrien}
49746283Sdfr
49819370Spststatic void
49919370Spstldns_dnssec_trust_tree_print_sm_fmt(FILE *out,
50019370Spst		const ldns_output_format *fmt,
50198948Sobrien		ldns_dnssec_trust_tree *tree,
50246283Sdfr		size_t tabs,
50319370Spst		bool extended,
50419370Spst		uint8_t *sibmap,
50519370Spst		size_t treedepth)
50619370Spst{
50746283Sdfr	size_t i;
50819370Spst	const ldns_rr_descriptor *descriptor;
50998948Sobrien	bool mapset = false;
51019370Spst
51119370Spst	if (!sibmap) {
51219370Spst		treedepth = ldns_dnssec_trust_tree_depth(tree);
51319370Spst		sibmap = LDNS_XMALLOC(uint8_t, treedepth);
51419370Spst                if(!sibmap)
51519370Spst                        return; /* mem err */
51646283Sdfr		memset(sibmap, 0, treedepth);
51719370Spst		mapset = true;
51819370Spst	}
51919370Spst
52019370Spst	if (tree) {
52119370Spst		if (tree->rr) {
52219370Spst			print_tabs(out, tabs, sibmap, treedepth);
52319370Spst			ldns_rdf_print(out, ldns_rr_owner(tree->rr));
52419370Spst			descriptor = ldns_rr_descript(ldns_rr_get_type(tree->rr));
52519370Spst
52619370Spst			if (descriptor->_name) {
52719370Spst				fprintf(out, " (%s", descriptor->_name);
52898948Sobrien			} else {
52919370Spst				fprintf(out, " (TYPE%d",
53019370Spst					   ldns_rr_get_type(tree->rr));
53119370Spst			}
53219370Spst			if (tabs > 0) {
53319370Spst				if (ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_DNSKEY) {
53446283Sdfr					fprintf(out, " keytag: %u",
53546283Sdfr					        (unsigned int) ldns_calc_keytag(tree->rr));
53619370Spst					fprintf(out, " alg: ");
53719370Spst					ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 2));
53846283Sdfr					fprintf(out, " flags: ");
53919370Spst					ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 0));
54046283Sdfr				} else if (ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_DS) {
54119370Spst					fprintf(out, " keytag: ");
54219370Spst					ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 0));
54319370Spst					fprintf(out, " digest type: ");
54419370Spst					ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 2));
54519370Spst				}
54619370Spst				if (ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_NSEC) {
54746283Sdfr					fprintf(out, " ");
54846283Sdfr					ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 0));
54946283Sdfr					fprintf(out, " ");
55046283Sdfr					ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 1));
55198948Sobrien				}
55246283Sdfr			}
55319370Spst
55446283Sdfr			fprintf(out, ")\n");
55519370Spst			for (i = 0; i < tree->parent_count; i++) {
55619370Spst				if (tree->parent_count > 1 && i < tree->parent_count - 1) {
55719370Spst					sibmap[tabs] = 1;
55819370Spst				} else {
55919370Spst					sibmap[tabs] = 0;
56098948Sobrien				}
56198948Sobrien				/* only print errors */
56219370Spst				if (ldns_rr_get_type(tree->parents[i]->rr) ==
56319370Spst				    LDNS_RR_TYPE_NSEC ||
56419370Spst				    ldns_rr_get_type(tree->parents[i]->rr) ==
56519370Spst				    LDNS_RR_TYPE_NSEC3) {
56619370Spst					if (tree->parent_status[i] == LDNS_STATUS_OK) {
56746283Sdfr						print_tabs(out, tabs + 1, sibmap, treedepth);
56898948Sobrien						if (tabs == 0 &&
56919370Spst						    ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_NS &&
57019370Spst							ldns_rr_rd_count(tree->rr) > 0) {
57198948Sobrien							fprintf(out, "Existence of DS is denied by:\n");
57219370Spst						} else {
57398948Sobrien							fprintf(out, "Existence is denied by:\n");
57419370Spst						}
57598948Sobrien					} else {
57619370Spst						/* NS records aren't signed */
57719370Spst						if (ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_NS) {
57819370Spst							fprintf(out, "Existence of DS is denied by:\n");
57998948Sobrien						} else {
58019370Spst							print_tabs(out, tabs + 1, sibmap, treedepth);
58119370Spst							fprintf(out,
58219370Spst								   "Error in denial of existence: %s\n",
58319370Spst								   ldns_get_errorstr_by_id(
58419370Spst									   tree->parent_status[i]));
58519370Spst						}
58619370Spst					}
58719370Spst				} else
58819370Spst					if (tree->parent_status[i] != LDNS_STATUS_OK) {
58919370Spst						print_tabs(out, tabs + 1, sibmap, treedepth);
59019370Spst						fprintf(out,
59119370Spst							   "%s:\n",
59219370Spst							   ldns_get_errorstr_by_id(
59319370Spst							       tree->parent_status[i]));
59498948Sobrien						if (tree->parent_status[i]
59519370Spst						    == LDNS_STATUS_SSL_ERR) {
59619370Spst							printf("; SSL Error: ");
59719370Spst							ERR_load_crypto_strings();
59819370Spst							ERR_print_errors_fp(stdout);
59919370Spst							printf("\n");
60019370Spst						}
60119370Spst						ldns_rr_print_fmt(out, fmt,
60219370Spst							tree->
60319370Spst							parent_signature[i]);
60419370Spst						printf("For RRset:\n");
60519370Spst						ldns_rr_list_print_fmt(out, fmt,
60619370Spst								tree->rrset);
60719370Spst						printf("With key:\n");
60819370Spst						ldns_rr_print_fmt(out, fmt,
60919370Spst							tree->parents[i]->rr);
61019370Spst					}
61119370Spst				ldns_dnssec_trust_tree_print_sm_fmt(out, fmt,
61219370Spst						tree->parents[i],
61319370Spst						tabs+1,
61419370Spst						extended,
61598948Sobrien						sibmap,
61619370Spst						treedepth);
61719370Spst			}
61898948Sobrien		} else {
61919370Spst			print_tabs(out, tabs, sibmap, treedepth);
62019370Spst			fprintf(out, "<no data>\n");
62119370Spst		}
62219370Spst	} else {
62319370Spst		fprintf(out, "<null pointer>\n");
62419370Spst	}
62519370Spst
62619370Spst	if (mapset) {
62746283Sdfr		LDNS_FREE(sibmap);
62898948Sobrien	}
629130809Smarcel}
63019370Spst
63146283Sdfr#if 0
63246283Sdfrstatic void
63346283Sdfrldns_dnssec_trust_tree_print_sm(FILE *out,
63446283Sdfr		ldns_dnssec_trust_tree *tree,
63519370Spst		size_t tabs,
63619370Spst		bool extended,
63719370Spst		uint8_t *sibmap,
63819370Spst		size_t treedepth)
63919370Spst{
64019370Spst	ldns_dnssec_trust_tree_print_sm_fmt(out, ldns_output_format_default,
64119370Spst			tree, tabs, extended, sibmap, treedepth);
64298948Sobrien}
64319370Spst#endif
64419370Spst
64519370Spstvoid
64619370Spstldns_dnssec_trust_tree_print_fmt(FILE *out, const ldns_output_format *fmt,
64719370Spst		ldns_dnssec_trust_tree *tree,
64819370Spst		size_t tabs,
64919370Spst		bool extended)
65019370Spst{
65119370Spst	ldns_dnssec_trust_tree_print_sm_fmt(out, fmt,
65219370Spst			tree, tabs, extended, NULL, 0);
653130809Smarcel}
654130809Smarcel
65519370Spstvoid
65619370Spstldns_dnssec_trust_tree_print(FILE *out,
65719370Spst		ldns_dnssec_trust_tree *tree,
65819370Spst		size_t tabs,
659130809Smarcel		bool extended)
66019370Spst{
66119370Spst	ldns_dnssec_trust_tree_print_fmt(out, ldns_output_format_default,
66219370Spst			tree, tabs, extended);
66319370Spst}
66419370Spst
66519370Spst
66619370Spstldns_status
66719370Spstldns_dnssec_trust_tree_add_parent(ldns_dnssec_trust_tree *tree,
66819370Spst                                  const ldns_dnssec_trust_tree *parent,
66998948Sobrien                                  const ldns_rr *signature,
67098948Sobrien                                  const ldns_status parent_status)
67119370Spst{
67219370Spst	if (tree
67319370Spst	    && parent
67419370Spst	    && tree->parent_count < LDNS_DNSSEC_TRUST_TREE_MAX_PARENTS) {
67519370Spst		/*
67619370Spst		  printf("Add parent for: ");
67719370Spst		  ldns_rr_print(stdout, tree->rr);
67819370Spst		  printf("parent: ");
67998948Sobrien		  ldns_rr_print(stdout, parent->rr);
680130809Smarcel		*/
681130809Smarcel		tree->parents[tree->parent_count] =
68219370Spst			(ldns_dnssec_trust_tree *) parent;
68319370Spst		tree->parent_status[tree->parent_count] = parent_status;
68419370Spst		tree->parent_signature[tree->parent_count] = (ldns_rr *) signature;
68519370Spst		tree->parent_count++;
68619370Spst		return LDNS_STATUS_OK;
68719370Spst	} else {
68819370Spst		return LDNS_STATUS_ERR;
68919370Spst	}
69019370Spst}
69119370Spst
69219370Spst/* if rr is null, take the first from the rrset */
69319370Spstldns_dnssec_trust_tree *
69419370Spstldns_dnssec_derive_trust_tree_time(
69519370Spst		ldns_dnssec_data_chain *data_chain,
69619370Spst		ldns_rr *rr,
69719370Spst		time_t check_time
69819370Spst		)
69919370Spst{
70019370Spst	ldns_rr_list *cur_rrset;
70119370Spst	ldns_rr_list *cur_sigs;
70219370Spst	ldns_rr *cur_rr = NULL;
70319370Spst	ldns_rr *cur_sig_rr;
70498948Sobrien	size_t i, j;
70519370Spst
70619370Spst	ldns_dnssec_trust_tree *new_tree = ldns_dnssec_trust_tree_new();
70719370Spst        if(!new_tree)
70819370Spst                return NULL;
70998948Sobrien
71019370Spst	if (data_chain && data_chain->rrset) {
711130809Smarcel		cur_rrset = data_chain->rrset;
71219370Spst
71319370Spst		cur_sigs = data_chain->signatures;
71498948Sobrien
71519370Spst		if (rr) {
71698948Sobrien			cur_rr = rr;
71719370Spst		}
71819370Spst
71919370Spst		if (!cur_rr && ldns_rr_list_rr_count(cur_rrset) > 0) {
72098948Sobrien			cur_rr = ldns_rr_list_rr(cur_rrset, 0);
72198948Sobrien		}
72298948Sobrien
72319370Spst		if (cur_rr) {
72419370Spst			new_tree->rr = cur_rr;
72519370Spst			new_tree->rrset = cur_rrset;
72619370Spst			/* there are three possibilities:
72719370Spst			   1 - 'normal' rrset, signed by a key
72819370Spst			   2 - dnskey signed by other dnskey
72919370Spst			   3 - dnskey proven by higher level DS
73019370Spst			   (data denied by nsec is a special case that can
73119370Spst			   occur in multiple places)
73219370Spst
73319370Spst			*/
73419370Spst			if (cur_sigs) {
73598948Sobrien				for (i = 0; i < ldns_rr_list_rr_count(cur_sigs); i++) {
73619370Spst					/* find the appropriate key in the parent list */
73719370Spst					cur_sig_rr = ldns_rr_list_rr(cur_sigs, i);
73819370Spst
73946283Sdfr					if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_NSEC) {
74046283Sdfr						if (ldns_dname_compare(ldns_rr_owner(cur_sig_rr),
741130809Smarcel										   ldns_rr_owner(cur_rr)))
742130809Smarcel							{
74346283Sdfr								/* find first that does match */
74446283Sdfr
74546283Sdfr								for (j = 0;
74698948Sobrien								     j < ldns_rr_list_rr_count(cur_rrset) &&
74798948Sobrien										ldns_dname_compare(ldns_rr_owner(cur_sig_rr),ldns_rr_owner(cur_rr)) != 0;
74846283Sdfr								     j++) {
74998948Sobrien									cur_rr = ldns_rr_list_rr(cur_rrset, j);
75046283Sdfr
75198948Sobrien								}
75219370Spst								if (ldns_dname_compare(ldns_rr_owner(cur_sig_rr),
75319370Spst												   ldns_rr_owner(cur_rr)))
75419370Spst									{
75598948Sobrien										break;
75619370Spst									}
75719370Spst							}
75846283Sdfr
75919370Spst					}
76019370Spst					/* option 1 */
76119370Spst					if (data_chain->parent) {
76219370Spst						ldns_dnssec_derive_trust_tree_normal_rrset_time(
76319370Spst						    new_tree,
76419370Spst						    data_chain,
76519370Spst						    cur_sig_rr,
76619370Spst						    check_time);
76719370Spst					}
76819370Spst
76919370Spst					/* option 2 */
77019370Spst					ldns_dnssec_derive_trust_tree_dnskey_rrset_time(
77119370Spst					    new_tree,
77219370Spst					    data_chain,
77319370Spst					    cur_rr,
77419370Spst					    cur_sig_rr,
77519370Spst					    check_time);
77619370Spst				}
77719370Spst
77819370Spst				ldns_dnssec_derive_trust_tree_ds_rrset_time(
77919370Spst						new_tree, data_chain,
78019370Spst						cur_rr, check_time);
78119370Spst			} else {
782130809Smarcel				/* no signatures? maybe it's nsec data */
783130809Smarcel
784130809Smarcel				/* just add every rr from parent as new parent */
785130809Smarcel				ldns_dnssec_derive_trust_tree_no_sig_time(
78619370Spst					new_tree, data_chain, check_time);
78719370Spst			}
78819370Spst		}
78919370Spst	}
79019370Spst
79119370Spst	return new_tree;
79219370Spst}
79398948Sobrien
79419370Spstldns_dnssec_trust_tree *
79519370Spstldns_dnssec_derive_trust_tree(ldns_dnssec_data_chain *data_chain, ldns_rr *rr)
79619370Spst{
79719370Spst	return ldns_dnssec_derive_trust_tree_time(data_chain, rr, ldns_time(NULL));
798130809Smarcel}
799130809Smarcel
800130809Smarcelvoid
801130809Smarcelldns_dnssec_derive_trust_tree_normal_rrset_time(
802130809Smarcel		ldns_dnssec_trust_tree *new_tree,
803130809Smarcel		ldns_dnssec_data_chain *data_chain,
804130809Smarcel		ldns_rr *cur_sig_rr,
805130809Smarcel		time_t check_time)
806130809Smarcel{
807130809Smarcel	size_t i, j;
808130809Smarcel	ldns_rr_list *cur_rrset = ldns_rr_list_clone(data_chain->rrset);
809130809Smarcel	ldns_dnssec_trust_tree *cur_parent_tree;
81019370Spst	ldns_rr *cur_parent_rr;
81119370Spst	uint16_t cur_keytag;
81219370Spst	ldns_rr_list *tmp_rrset = NULL;
81319370Spst	ldns_status cur_status;
81419370Spst
81519370Spst	cur_keytag = ldns_rdf2native_int16(ldns_rr_rrsig_keytag(cur_sig_rr));
81619370Spst
81719370Spst	for (j = 0; j < ldns_rr_list_rr_count(data_chain->parent->rrset); j++) {
81819370Spst		cur_parent_rr = ldns_rr_list_rr(data_chain->parent->rrset, j);
81919370Spst		if (ldns_rr_get_type(cur_parent_rr) == LDNS_RR_TYPE_DNSKEY) {
82019370Spst			if (ldns_calc_keytag(cur_parent_rr) == cur_keytag) {
82119370Spst
82219370Spst				/* TODO: check wildcard nsec too */
82319370Spst				if (cur_rrset && ldns_rr_list_rr_count(cur_rrset) > 0) {
82419370Spst					tmp_rrset = cur_rrset;
825130809Smarcel					if (ldns_rr_get_type(ldns_rr_list_rr(cur_rrset, 0))
82619370Spst					    == LDNS_RR_TYPE_NSEC ||
82719370Spst					    ldns_rr_get_type(ldns_rr_list_rr(cur_rrset, 0))
82819370Spst					    == LDNS_RR_TYPE_NSEC3) {
82919370Spst						/* might contain different names!
83019370Spst						   sort and split */
83119370Spst						ldns_rr_list_sort(cur_rrset);
83219370Spst						assert(tmp_rrset == cur_rrset);
83319370Spst						tmp_rrset = ldns_rr_list_pop_rrset(cur_rrset);
83419370Spst
83519370Spst						/* with nsecs, this might be the wrong one */
83619370Spst						while (tmp_rrset &&
83719370Spst						       ldns_rr_list_rr_count(cur_rrset) > 0 &&
838130809Smarcel						       ldns_dname_compare(
839130809Smarcel								ldns_rr_owner(ldns_rr_list_rr(
840130809Smarcel										        tmp_rrset, 0)),
841130809Smarcel								ldns_rr_owner(cur_sig_rr)) != 0) {
842130809Smarcel							ldns_rr_list_deep_free(tmp_rrset);
843130809Smarcel							tmp_rrset =
844130809Smarcel								ldns_rr_list_pop_rrset(cur_rrset);
845130809Smarcel						}
846130809Smarcel					}
847130809Smarcel					cur_status = ldns_verify_rrsig_time(
848130809Smarcel							tmp_rrset,
849130809Smarcel							cur_sig_rr,
85046283Sdfr							cur_parent_rr,
85146283Sdfr							check_time);
85246283Sdfr					if (tmp_rrset && tmp_rrset != cur_rrset
85346283Sdfr							) {
85446283Sdfr						ldns_rr_list_deep_free(
85598948Sobrien								tmp_rrset);
85698948Sobrien						tmp_rrset = NULL;
85798948Sobrien					}
85898948Sobrien					/* avoid dupes */
85946283Sdfr					for (i = 0; i < new_tree->parent_count; i++) {
86046283Sdfr						if (cur_parent_rr == new_tree->parents[i]->rr) {
86119370Spst							goto done;
86219370Spst						}
86319370Spst					}
86419370Spst
86519370Spst					cur_parent_tree =
86619370Spst						ldns_dnssec_derive_trust_tree_time(
86719370Spst								data_chain->parent,
86819370Spst						                cur_parent_rr,
86919370Spst								check_time);
87019370Spst					(void)ldns_dnssec_trust_tree_add_parent(new_tree,
87198948Sobrien					           cur_parent_tree,
87219370Spst					           cur_sig_rr,
87346283Sdfr					           cur_status);
87446283Sdfr				}
87519370Spst			}
87619370Spst		}
87746283Sdfr	}
87819370Spst done:
87998948Sobrien	ldns_rr_list_deep_free(cur_rrset);
88019370Spst}
88146283Sdfr
88246283Sdfrvoid
88346283Sdfrldns_dnssec_derive_trust_tree_normal_rrset(ldns_dnssec_trust_tree *new_tree,
88446283Sdfr                                           ldns_dnssec_data_chain *data_chain,
88519370Spst                                           ldns_rr *cur_sig_rr)
88619370Spst{
88719370Spst	ldns_dnssec_derive_trust_tree_normal_rrset_time(
88819370Spst			new_tree, data_chain, cur_sig_rr, ldns_time(NULL));
88919370Spst}
89019370Spst
89198948Sobrienvoid
89219370Spstldns_dnssec_derive_trust_tree_dnskey_rrset_time(
89319370Spst		ldns_dnssec_trust_tree *new_tree,
89419370Spst		ldns_dnssec_data_chain *data_chain,
89598948Sobrien		ldns_rr *cur_rr,
89619370Spst		ldns_rr *cur_sig_rr,
89719370Spst		time_t check_time)
89819370Spst{
89919370Spst	size_t j;
90019370Spst	ldns_rr_list *cur_rrset = data_chain->rrset;
90198948Sobrien	ldns_dnssec_trust_tree *cur_parent_tree;
90219370Spst	ldns_rr *cur_parent_rr;
90319370Spst	uint16_t cur_keytag;
90419370Spst	ldns_status cur_status;
90519370Spst
90619370Spst	cur_keytag = ldns_rdf2native_int16(ldns_rr_rrsig_keytag(cur_sig_rr));
90719370Spst
90898948Sobrien	for (j = 0; j < ldns_rr_list_rr_count(cur_rrset); j++) {
90998948Sobrien		cur_parent_rr = ldns_rr_list_rr(cur_rrset, j);
91019370Spst		if (cur_parent_rr != cur_rr &&
91119370Spst		    ldns_rr_get_type(cur_parent_rr) == LDNS_RR_TYPE_DNSKEY) {
91219370Spst			if (ldns_calc_keytag(cur_parent_rr) == cur_keytag
91319370Spst			    ) {
91419370Spst				cur_parent_tree = ldns_dnssec_trust_tree_new();
91519370Spst				cur_parent_tree->rr = cur_parent_rr;
91619370Spst				cur_parent_tree->rrset = cur_rrset;
91719370Spst				cur_status = ldns_verify_rrsig_time(
91819370Spst						cur_rrset, cur_sig_rr,
91919370Spst						cur_parent_rr, check_time);
92019370Spst				(void) ldns_dnssec_trust_tree_add_parent(new_tree,
92119370Spst				            cur_parent_tree, cur_sig_rr, cur_status);
92298948Sobrien			}
92319370Spst		}
92419370Spst	}
92519370Spst}
92619370Spst
92719370Spstvoid
928130809Smarcelldns_dnssec_derive_trust_tree_dnskey_rrset(ldns_dnssec_trust_tree *new_tree,
92919370Spst                                           ldns_dnssec_data_chain *data_chain,
93019370Spst                                           ldns_rr *cur_rr,
931130809Smarcel                                           ldns_rr *cur_sig_rr)
93219370Spst{
93319370Spst	ldns_dnssec_derive_trust_tree_dnskey_rrset_time(
93419370Spst			new_tree, data_chain, cur_rr, cur_sig_rr, ldns_time(NULL));
93519370Spst}
93619370Spst
93719370Spstvoid
93898948Sobrienldns_dnssec_derive_trust_tree_ds_rrset_time(
93919370Spst		ldns_dnssec_trust_tree *new_tree,
940130809Smarcel		ldns_dnssec_data_chain *data_chain,
94119370Spst		ldns_rr *cur_rr,
94219370Spst		time_t check_time)
94319370Spst{
94498948Sobrien	size_t j, h;
94598948Sobrien	ldns_rr_list *cur_rrset = data_chain->rrset;
94698948Sobrien	ldns_dnssec_trust_tree *cur_parent_tree;
94798948Sobrien	ldns_rr *cur_parent_rr;
94898948Sobrien
94998948Sobrien	/* try the parent to see whether there are DSs there */
95098948Sobrien	if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_DNSKEY &&
95198948Sobrien	    data_chain->parent &&
95298948Sobrien	    data_chain->parent->rrset
95398948Sobrien	    ) {
95498948Sobrien		for (j = 0;
95598948Sobrien			j < ldns_rr_list_rr_count(data_chain->parent->rrset);
95698948Sobrien			j++) {
95798948Sobrien			cur_parent_rr = ldns_rr_list_rr(data_chain->parent->rrset, j);
95898948Sobrien			if (ldns_rr_get_type(cur_parent_rr) == LDNS_RR_TYPE_DS) {
95998948Sobrien				for (h = 0; h < ldns_rr_list_rr_count(cur_rrset); h++) {
96098948Sobrien					cur_rr = ldns_rr_list_rr(cur_rrset, h);
96198948Sobrien					if (ldns_rr_compare_ds(cur_rr, cur_parent_rr)) {
96298948Sobrien						cur_parent_tree =
96398948Sobrien							ldns_dnssec_derive_trust_tree_time(
96498948Sobrien							    data_chain->parent,
96598948Sobrien							    cur_parent_rr,
96698948Sobrien							    check_time);
96798948Sobrien						(void) ldns_dnssec_trust_tree_add_parent(
968130809Smarcel						            new_tree,
969130809Smarcel						            cur_parent_tree,
97098948Sobrien						            NULL,
97198948Sobrien						            LDNS_STATUS_OK);
97298948Sobrien					} else {
97398948Sobrien						/*ldns_rr_print(stdout, cur_parent_rr);*/
97498948Sobrien					}
97598948Sobrien				}
97698948Sobrien			}
97798948Sobrien		}
97819370Spst	}
97919370Spst}
98019370Spst
98119370Spstvoid
98298948Sobrienldns_dnssec_derive_trust_tree_ds_rrset(ldns_dnssec_trust_tree *new_tree,
98319370Spst                                       ldns_dnssec_data_chain *data_chain,
98419370Spst                                       ldns_rr *cur_rr)
98519370Spst{
98619370Spst	ldns_dnssec_derive_trust_tree_ds_rrset_time(
98719370Spst			new_tree, data_chain, cur_rr, ldns_time(NULL));
98819370Spst}
98919370Spst
99019370Spstvoid
99119370Spstldns_dnssec_derive_trust_tree_no_sig_time(
99219370Spst		ldns_dnssec_trust_tree *new_tree,
99319370Spst		ldns_dnssec_data_chain *data_chain,
99419370Spst		time_t check_time)
99519370Spst{
99619370Spst	size_t i;
99719370Spst	ldns_rr_list *cur_rrset;
99819370Spst	ldns_rr *cur_parent_rr;
99919370Spst	ldns_dnssec_trust_tree *cur_parent_tree;
100019370Spst	ldns_status result;
100119370Spst
100219370Spst	if (data_chain->parent && data_chain->parent->rrset) {
100319370Spst		cur_rrset = data_chain->parent->rrset;
100419370Spst		/* nsec? */
100519370Spst		if (cur_rrset && ldns_rr_list_rr_count(cur_rrset) > 0) {
100619370Spst			if (ldns_rr_get_type(ldns_rr_list_rr(cur_rrset, 0)) ==
100719370Spst			    LDNS_RR_TYPE_NSEC3) {
100819370Spst				result = ldns_dnssec_verify_denial_nsec3(
100919370Spst					        new_tree->rr,
101019370Spst						   cur_rrset,
101119370Spst						   data_chain->parent->signatures,
101219370Spst						   data_chain->packet_rcode,
101398948Sobrien						   data_chain->packet_qtype,
101419370Spst						   data_chain->packet_nodata);
101519370Spst			} else if (ldns_rr_get_type(ldns_rr_list_rr(cur_rrset, 0)) ==
101619370Spst					 LDNS_RR_TYPE_NSEC) {
101719370Spst				result = ldns_dnssec_verify_denial(
101819370Spst					        new_tree->rr,
101919370Spst						   cur_rrset,
102019370Spst						   data_chain->parent->signatures);
102119370Spst			} else {
102219370Spst				/* unsigned zone, unsigned parent */
102319370Spst				result = LDNS_STATUS_OK;
102419370Spst			}
102519370Spst		} else {
102619370Spst			result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED;
102719370Spst		}
102819370Spst		for (i = 0; i < ldns_rr_list_rr_count(cur_rrset); i++) {
102919370Spst			cur_parent_rr = ldns_rr_list_rr(cur_rrset, i);
103019370Spst			cur_parent_tree =
103119370Spst				ldns_dnssec_derive_trust_tree_time(
103219370Spst						data_chain->parent,
103319370Spst						cur_parent_rr,
103419370Spst						check_time);
103519370Spst			(void) ldns_dnssec_trust_tree_add_parent(new_tree,
103619370Spst			            cur_parent_tree, NULL, result);
103719370Spst		}
103819370Spst	}
103919370Spst}
104098948Sobrien
104119370Spstvoid
104219370Spstldns_dnssec_derive_trust_tree_no_sig(ldns_dnssec_trust_tree *new_tree,
104319370Spst                                     ldns_dnssec_data_chain *data_chain)
104419370Spst{
104598948Sobrien	ldns_dnssec_derive_trust_tree_no_sig_time(
104619370Spst			new_tree, data_chain, ldns_time(NULL));
104719370Spst}
104819370Spst
104919370Spst/*
105098948Sobrien * returns OK if there is a path from tree to key with only OK
105119370Spst * the (first) error in between otherwise
105219370Spst * or NOT_FOUND if the key wasn't present at all
105319370Spst */
105419370Spstldns_status
105519370Spstldns_dnssec_trust_tree_contains_keys(ldns_dnssec_trust_tree *tree,
105619370Spst							  ldns_rr_list *trusted_keys)
105719370Spst{
105819370Spst	size_t i;
105919370Spst	ldns_status result = LDNS_STATUS_CRYPTO_NO_DNSKEY;
106019370Spst	bool equal;
106119370Spst	ldns_status parent_result;
106219370Spst
106319370Spst	if (tree && trusted_keys && ldns_rr_list_rr_count(trusted_keys) > 0)
106419370Spst		{ if (tree->rr) {
106519370Spst				for (i = 0; i < ldns_rr_list_rr_count(trusted_keys); i++) {
106619370Spst					equal = ldns_rr_compare_ds(
106719370Spst							  tree->rr,
106819370Spst							  ldns_rr_list_rr(trusted_keys, i));
106919370Spst					if (equal) {
107019370Spst						result = LDNS_STATUS_OK;
107119370Spst						return result;
107219370Spst					}
107319370Spst				}
107498948Sobrien			}
107519370Spst			for (i = 0; i < tree->parent_count; i++) {
107698948Sobrien				parent_result =
107719370Spst					ldns_dnssec_trust_tree_contains_keys(tree->parents[i],
107819370Spst												  trusted_keys);
107919370Spst				if (parent_result != LDNS_STATUS_CRYPTO_NO_DNSKEY) {
108019370Spst					if (tree->parent_status[i] != LDNS_STATUS_OK) {
108119370Spst						result = tree->parent_status[i];
108219370Spst					} else {
108319370Spst						if (tree->rr &&
108419370Spst						    ldns_rr_get_type(tree->rr)
108519370Spst						    == LDNS_RR_TYPE_NSEC &&
108619370Spst						    parent_result == LDNS_STATUS_OK
108719370Spst						    ) {
108819370Spst							result =
108919370Spst								LDNS_STATUS_DNSSEC_EXISTENCE_DENIED;
109019370Spst						} else {
109198948Sobrien							result = parent_result;
109219370Spst						}
109319370Spst					}
109419370Spst				}
109519370Spst			}
109619370Spst		} else {
109719370Spst		result = LDNS_STATUS_ERR;
109819370Spst	}
109919370Spst
110019370Spst	return result;
110119370Spst}
110219370Spst
110319370Spstldns_status
110419370Spstldns_verify_time(
110519370Spst		ldns_rr_list *rrset,
110619370Spst		ldns_rr_list *rrsig,
110719370Spst		const ldns_rr_list *keys,
110819370Spst		time_t check_time,
110919370Spst		ldns_rr_list *good_keys
111019370Spst		)
111119370Spst{
111219370Spst	uint16_t i;
111346283Sdfr	ldns_status verify_result = LDNS_STATUS_ERR;
111446283Sdfr
111519370Spst	if (!rrset || !rrsig || !keys) {
111619370Spst		return LDNS_STATUS_ERR;
111719370Spst	}
111819370Spst
111919370Spst	if (ldns_rr_list_rr_count(rrset) < 1) {
1120130809Smarcel		return LDNS_STATUS_ERR;
1121130809Smarcel	}
1122130809Smarcel
1123130809Smarcel	if (ldns_rr_list_rr_count(rrsig) < 1) {
1124130809Smarcel		return LDNS_STATUS_CRYPTO_NO_RRSIG;
1125130809Smarcel	}
1126130809Smarcel
1127130809Smarcel	if (ldns_rr_list_rr_count(keys) < 1) {
1128130809Smarcel		verify_result = LDNS_STATUS_CRYPTO_NO_TRUSTED_DNSKEY;
1129130809Smarcel	} else {
1130130809Smarcel		for (i = 0; i < ldns_rr_list_rr_count(rrsig); i++) {
1131130809Smarcel			ldns_status s = ldns_verify_rrsig_keylist_time(
1132130809Smarcel					rrset, ldns_rr_list_rr(rrsig, i),
1133130809Smarcel					keys, check_time, good_keys);
1134130809Smarcel			/* try a little to get more descriptive error */
1135130809Smarcel			if(s == LDNS_STATUS_OK) {
1136130809Smarcel				verify_result = LDNS_STATUS_OK;
1137130809Smarcel			} else if(verify_result == LDNS_STATUS_ERR)
1138130809Smarcel				verify_result = s;
1139130809Smarcel			else if(s !=  LDNS_STATUS_ERR && verify_result ==
1140130809Smarcel				LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY)
1141130809Smarcel				verify_result = s;
1142130809Smarcel		}
1143130809Smarcel	}
1144130809Smarcel	return verify_result;
1145130809Smarcel}
1146130809Smarcel
1147130809Smarcelldns_status
1148130809Smarcelldns_verify(ldns_rr_list *rrset, ldns_rr_list *rrsig, const ldns_rr_list *keys,
1149130809Smarcel		  ldns_rr_list *good_keys)
1150130809Smarcel{
1151130809Smarcel	return ldns_verify_time(rrset, rrsig, keys, ldns_time(NULL), good_keys);
1152130809Smarcel}
1153130809Smarcel
1154130809Smarcelldns_status
1155130809Smarcelldns_verify_notime(ldns_rr_list *rrset, ldns_rr_list *rrsig,
1156130809Smarcel	const ldns_rr_list *keys, ldns_rr_list *good_keys)
1157130809Smarcel{
1158130809Smarcel	uint16_t i;
1159130809Smarcel	ldns_status verify_result = LDNS_STATUS_ERR;
1160130809Smarcel
1161130809Smarcel	if (!rrset || !rrsig || !keys) {
1162130809Smarcel		return LDNS_STATUS_ERR;
1163130809Smarcel	}
1164130809Smarcel
1165130809Smarcel	if (ldns_rr_list_rr_count(rrset) < 1) {
1166130809Smarcel		return LDNS_STATUS_ERR;
1167130809Smarcel	}
1168130809Smarcel
1169130809Smarcel	if (ldns_rr_list_rr_count(rrsig) < 1) {
1170130809Smarcel		return LDNS_STATUS_CRYPTO_NO_RRSIG;
1171130809Smarcel	}
1172130809Smarcel
1173130809Smarcel	if (ldns_rr_list_rr_count(keys) < 1) {
117498948Sobrien		verify_result = LDNS_STATUS_CRYPTO_NO_TRUSTED_DNSKEY;
117598948Sobrien	} else {
117619370Spst		for (i = 0; i < ldns_rr_list_rr_count(rrsig); i++) {
117719370Spst			ldns_status s = ldns_verify_rrsig_keylist_notime(rrset,
117898948Sobrien				ldns_rr_list_rr(rrsig, i), keys, good_keys);
117919370Spst
1180130809Smarcel			/* try a little to get more descriptive error */
118146283Sdfr			if (s == LDNS_STATUS_OK) {
118298948Sobrien				verify_result = LDNS_STATUS_OK;
118398948Sobrien			} else if (verify_result == LDNS_STATUS_ERR) {
118446283Sdfr				verify_result = s;
1185130809Smarcel			} else if (s !=  LDNS_STATUS_ERR && verify_result ==
118619370Spst				LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY) {
118719370Spst				verify_result = s;
118819370Spst			}
118919370Spst		}
119019370Spst	}
119119370Spst	return verify_result;
119246283Sdfr}
1193130809Smarcel
119419370Spstldns_rr_list *
119519370Spstldns_fetch_valid_domain_keys_time(const ldns_resolver *res,
119619370Spst                             const ldns_rdf *domain,
119719370Spst                             const ldns_rr_list *keys,
119819370Spst			     time_t check_time,
119919370Spst                             ldns_status *status)
120019370Spst{
120119370Spst	ldns_rr_list * trusted_keys = NULL;
120219370Spst	ldns_rr_list * ds_keys = NULL;
120319370Spst	ldns_rdf * prev_parent_domain;
120419370Spst	ldns_rdf *      parent_domain;
120519370Spst	ldns_rr_list * parent_keys = NULL;
120619370Spst
120798948Sobrien	if (res && domain && keys) {
120898948Sobrien
120998948Sobrien		if ((trusted_keys = ldns_validate_domain_dnskey_time(res,
121019370Spst                                         domain, keys, check_time))) {
121119370Spst			*status = LDNS_STATUS_OK;
121219370Spst		} else {
121319370Spst			/* No trusted keys in this domain, we'll have to find some in the parent domain */
121419370Spst			*status = LDNS_STATUS_CRYPTO_NO_TRUSTED_DNSKEY;
121519370Spst
121698948Sobrien			parent_domain = ldns_dname_left_chop(domain);
121719370Spst			while (parent_domain && /* Fail if we are at the root*/
121819370Spst					ldns_rdf_size(parent_domain) > 0) {
121919370Spst
122019370Spst				if ((parent_keys =
122119370Spst					ldns_fetch_valid_domain_keys_time(res,
122219370Spst					     parent_domain,
122319370Spst					     keys,
122419370Spst					     check_time,
122519370Spst					     status))) {
122619370Spst					/* Check DS records */
122719370Spst					if ((ds_keys =
122819370Spst						ldns_validate_domain_ds_time(res,
122919370Spst						     domain,
123019370Spst						     parent_keys,
123119370Spst						     check_time))) {
123298948Sobrien						trusted_keys =
123319370Spst						ldns_fetch_valid_domain_keys_time(
123419370Spst								res,
123519370Spst								domain,
123698948Sobrien								ds_keys,
123719370Spst								check_time,
123819370Spst								status);
123919370Spst						ldns_rr_list_deep_free(ds_keys);
124019370Spst					} else {
124119370Spst						/* No valid DS at the parent -- fail */
124246283Sdfr						*status = LDNS_STATUS_CRYPTO_NO_TRUSTED_DS ;
124346283Sdfr					}
124419370Spst					ldns_rr_list_deep_free(parent_keys);
1245130809Smarcel					break;
1246130809Smarcel				} else {
1247130809Smarcel					parent_domain = ldns_dname_left_chop((
1248130809Smarcel						prev_parent_domain
1249130809Smarcel							= parent_domain
1250130809Smarcel						));
1251130809Smarcel					ldns_rdf_deep_free(prev_parent_domain);
1252130809Smarcel				}
1253130809Smarcel			}
1254130809Smarcel			if (parent_domain) {
1255130809Smarcel				ldns_rdf_deep_free(parent_domain);
1256130809Smarcel			}
1257130809Smarcel		}
1258130809Smarcel	}
1259130809Smarcel	return trusted_keys;
1260130809Smarcel}
1261130809Smarcel
1262130809Smarcelldns_rr_list *
1263130809Smarcelldns_fetch_valid_domain_keys(const ldns_resolver *res,
1264130809Smarcel                             const ldns_rdf *domain,
1265130809Smarcel                             const ldns_rr_list *keys,
1266130809Smarcel                             ldns_status *status)
1267130809Smarcel{
1268130809Smarcel	return ldns_fetch_valid_domain_keys_time(
1269130809Smarcel			res, domain, keys, ldns_time(NULL), status);
1270130809Smarcel}
1271130809Smarcel
1272130809Smarcelldns_rr_list *
1273130809Smarcelldns_validate_domain_dnskey_time(
1274130809Smarcel		const ldns_resolver * res,
1275130809Smarcel		const ldns_rdf * domain,
1276130809Smarcel		const ldns_rr_list * keys,
127719370Spst		time_t check_time
127819370Spst		)
127919370Spst{
128098948Sobrien	ldns_pkt * keypkt;
128119370Spst	ldns_rr * cur_key;
128219370Spst	uint16_t key_i; uint16_t key_j; uint16_t key_k;
128319370Spst	uint16_t sig_i; ldns_rr * cur_sig;
128419370Spst
128519370Spst	ldns_rr_list * domain_keys = NULL;
128619370Spst	ldns_rr_list * domain_sigs = NULL;
128719370Spst	ldns_rr_list * trusted_keys = NULL;
128846283Sdfr
128946283Sdfr	/* Fetch keys for the domain */
129046283Sdfr	keypkt = ldns_resolver_query(res, domain,
129146283Sdfr		LDNS_RR_TYPE_DNSKEY, LDNS_RR_CLASS_IN, LDNS_RD);
129246283Sdfr	if (keypkt) {
129319370Spst		domain_keys = ldns_pkt_rr_list_by_type(keypkt,
129446283Sdfr									    LDNS_RR_TYPE_DNSKEY,
129519370Spst									    LDNS_SECTION_ANSWER);
129619370Spst		domain_sigs = ldns_pkt_rr_list_by_type(keypkt,
129719370Spst									    LDNS_RR_TYPE_RRSIG,
129819370Spst									    LDNS_SECTION_ANSWER);
129919370Spst
130019370Spst		/* Try to validate the record using our keys */
130119370Spst		for (key_i=0; key_i< ldns_rr_list_rr_count(domain_keys); key_i++) {
130298948Sobrien
130398948Sobrien			cur_key = ldns_rr_list_rr(domain_keys, key_i);
130498948Sobrien			for (key_j=0; key_j<ldns_rr_list_rr_count(keys); key_j++) {
130598948Sobrien				if (ldns_rr_compare_ds(ldns_rr_list_rr(keys, key_j),
130698948Sobrien								   cur_key)) {
130798948Sobrien
130819370Spst					/* Current key is trusted -- validate */
130998948Sobrien					trusted_keys = ldns_rr_list_new();
131098948Sobrien
131198948Sobrien					for (sig_i=0;
131298948Sobrien						sig_i<ldns_rr_list_rr_count(domain_sigs);
131398948Sobrien						sig_i++) {
131498948Sobrien						cur_sig = ldns_rr_list_rr(domain_sigs, sig_i);
131519370Spst						/* Avoid non-matching sigs */
131698948Sobrien						if (ldns_rdf2native_int16(
131798948Sobrien							   ldns_rr_rrsig_keytag(cur_sig))
131898948Sobrien						    == ldns_calc_keytag(cur_key)) {
131998948Sobrien							if (ldns_verify_rrsig_time(
132019370Spst									domain_keys,
132198948Sobrien									cur_sig,
132298948Sobrien									cur_key,
132398948Sobrien									check_time)
132498948Sobrien							    == LDNS_STATUS_OK) {
132598948Sobrien
132698948Sobrien								/* Push the whole rrset
132798948Sobrien								   -- we can't do much more */
132898948Sobrien								for (key_k=0;
132998948Sobrien									key_k<ldns_rr_list_rr_count(
133098948Sobrien											domain_keys);
133198948Sobrien									key_k++) {
133298948Sobrien									ldns_rr_list_push_rr(
133398948Sobrien									    trusted_keys,
133498948Sobrien									    ldns_rr_clone(
133598948Sobrien										   ldns_rr_list_rr(
133698948Sobrien											  domain_keys,
133798948Sobrien											  key_k)));
133898948Sobrien								}
133998948Sobrien
134098948Sobrien								ldns_rr_list_deep_free(domain_keys);
134198948Sobrien								ldns_rr_list_deep_free(domain_sigs);
134298948Sobrien								ldns_pkt_free(keypkt);
134398948Sobrien								return trusted_keys;
134498948Sobrien							}
134598948Sobrien						}
134698948Sobrien					}
134798948Sobrien
134898948Sobrien					/* Only push our trusted key */
134998948Sobrien					ldns_rr_list_push_rr(trusted_keys,
135098948Sobrien									 ldns_rr_clone(cur_key));
135198948Sobrien				}
135298948Sobrien			}
135398948Sobrien		}
135498948Sobrien
135598948Sobrien		ldns_rr_list_deep_free(domain_keys);
135698948Sobrien		ldns_rr_list_deep_free(domain_sigs);
135798948Sobrien		ldns_pkt_free(keypkt);
135898948Sobrien
135998948Sobrien	} else {
136098948Sobrien		/* LDNS_STATUS_CRYPTO_NO_DNSKEY */
136198948Sobrien	}
136298948Sobrien
136398948Sobrien	return trusted_keys;
1364130809Smarcel}
1365130809Smarcel
136698948Sobrienldns_rr_list *
136798948Sobrienldns_validate_domain_dnskey(const ldns_resolver * res,
136898948Sobrien					   const ldns_rdf * domain,
136998948Sobrien					   const ldns_rr_list * keys)
1370130809Smarcel{
137198948Sobrien	return ldns_validate_domain_dnskey_time(
137298948Sobrien			res, domain, keys, ldns_time(NULL));
137398948Sobrien}
1374130809Smarcel
1375130809Smarcelldns_rr_list *
137698948Sobrienldns_validate_domain_ds_time(
137798948Sobrien		const ldns_resolver *res,
137898948Sobrien		const ldns_rdf * domain,
137998948Sobrien		const ldns_rr_list * keys,
138098948Sobrien		time_t check_time)
138198948Sobrien{
138298948Sobrien	ldns_pkt * dspkt;
138398948Sobrien	uint16_t key_i;
138498948Sobrien	ldns_rr_list * rrset = NULL;
138598948Sobrien	ldns_rr_list * sigs = NULL;
138698948Sobrien	ldns_rr_list * trusted_keys = NULL;
138798948Sobrien
138898948Sobrien	/* Fetch DS for the domain */
138998948Sobrien	dspkt = ldns_resolver_query(res, domain,
139098948Sobrien		LDNS_RR_TYPE_DS, LDNS_RR_CLASS_IN, LDNS_RD);
139198948Sobrien	if (dspkt) {
139298948Sobrien		rrset = ldns_pkt_rr_list_by_type(dspkt,
139398948Sobrien								   LDNS_RR_TYPE_DS,
139498948Sobrien								   LDNS_SECTION_ANSWER);
139598948Sobrien		sigs = ldns_pkt_rr_list_by_type(dspkt,
139698948Sobrien								  LDNS_RR_TYPE_RRSIG,
139798948Sobrien								  LDNS_SECTION_ANSWER);
139898948Sobrien
139998948Sobrien		/* Validate sigs */
140098948Sobrien		if (ldns_verify_time(rrset, sigs, keys, check_time, NULL)
140198948Sobrien			       	== LDNS_STATUS_OK) {
140298948Sobrien			trusted_keys = ldns_rr_list_new();
140398948Sobrien			for (key_i=0; key_i<ldns_rr_list_rr_count(rrset); key_i++) {
140498948Sobrien				ldns_rr_list_push_rr(trusted_keys,
140598948Sobrien								 ldns_rr_clone(ldns_rr_list_rr(rrset,
140698948Sobrien														 key_i)
140798948Sobrien											)
140898948Sobrien								 );
140998948Sobrien			}
141098948Sobrien		}
141198948Sobrien
141298948Sobrien		ldns_rr_list_deep_free(rrset);
141398948Sobrien		ldns_rr_list_deep_free(sigs);
141498948Sobrien		ldns_pkt_free(dspkt);
141598948Sobrien
141698948Sobrien	} else {
141798948Sobrien		/* LDNS_STATUS_CRYPTO_NO_DS */
141898948Sobrien	}
141998948Sobrien
142098948Sobrien	return trusted_keys;
142198948Sobrien}
142298948Sobrien
142398948Sobrienldns_rr_list *
142498948Sobrienldns_validate_domain_ds(const ldns_resolver *res,
142598948Sobrien				    const ldns_rdf * domain,
142698948Sobrien				    const ldns_rr_list * keys)
142798948Sobrien{
142898948Sobrien	return ldns_validate_domain_ds_time(res, domain, keys, ldns_time(NULL));
142998948Sobrien}
143098948Sobrien
143198948Sobrienldns_status
143298948Sobrienldns_verify_trusted_time(
143398948Sobrien		ldns_resolver *res,
143498948Sobrien		ldns_rr_list *rrset,
143598948Sobrien		ldns_rr_list * rrsigs,
143698948Sobrien		time_t check_time,
143798948Sobrien		ldns_rr_list * validating_keys
143898948Sobrien		)
143998948Sobrien{
144098948Sobrien	uint16_t sig_i; uint16_t key_i;
144198948Sobrien	ldns_rr * cur_sig; ldns_rr * cur_key;
144298948Sobrien	ldns_rr_list * trusted_keys = NULL;
144398948Sobrien	ldns_status result = LDNS_STATUS_ERR;
144498948Sobrien
144598948Sobrien	if (!res || !rrset || !rrsigs) {
144698948Sobrien		return LDNS_STATUS_ERR;
144798948Sobrien	}
144898948Sobrien
144998948Sobrien	if (ldns_rr_list_rr_count(rrset) < 1) {
145098948Sobrien		return LDNS_STATUS_ERR;
145198948Sobrien	}
145298948Sobrien
145398948Sobrien	if (ldns_rr_list_rr_count(rrsigs) < 1) {
145498948Sobrien		return LDNS_STATUS_CRYPTO_NO_RRSIG;
145598948Sobrien	}
145698948Sobrien
145798948Sobrien	/* Look at each sig */
145898948Sobrien	for (sig_i=0; sig_i < ldns_rr_list_rr_count(rrsigs); sig_i++) {
145998948Sobrien
146098948Sobrien		cur_sig = ldns_rr_list_rr(rrsigs, sig_i);
146198948Sobrien		/* Get a valid signer key and validate the sig */
146298948Sobrien		if ((trusted_keys = ldns_fetch_valid_domain_keys_time(
146398948Sobrien					res,
146498948Sobrien					ldns_rr_rrsig_signame(cur_sig),
146598948Sobrien					ldns_resolver_dnssec_anchors(res),
146698948Sobrien					check_time,
146798948Sobrien					&result))) {
146898948Sobrien
146998948Sobrien			for (key_i = 0;
147098948Sobrien				key_i < ldns_rr_list_rr_count(trusted_keys);
147198948Sobrien				key_i++) {
147298948Sobrien				cur_key = ldns_rr_list_rr(trusted_keys, key_i);
147398948Sobrien
147498948Sobrien				if ((result = ldns_verify_rrsig_time(rrset,
147598948Sobrien								cur_sig,
147698948Sobrien								cur_key,
147798948Sobrien								check_time))
147898948Sobrien				    == LDNS_STATUS_OK) {
147998948Sobrien					if (validating_keys) {
148098948Sobrien						ldns_rr_list_push_rr(validating_keys,
148198948Sobrien										 ldns_rr_clone(cur_key));
148298948Sobrien					}
148398948Sobrien					ldns_rr_list_deep_free(trusted_keys);
148498948Sobrien					return LDNS_STATUS_OK;
148598948Sobrien				}
148698948Sobrien			}
148798948Sobrien		}
148898948Sobrien	}
148998948Sobrien
149098948Sobrien	ldns_rr_list_deep_free(trusted_keys);
149198948Sobrien	return result;
149298948Sobrien}
149398948Sobrien
149498948Sobrienldns_status
149598948Sobrienldns_verify_trusted(
149698948Sobrien		ldns_resolver *res,
1497130809Smarcel		ldns_rr_list *rrset,
149898948Sobrien		ldns_rr_list * rrsigs,
149998948Sobrien		ldns_rr_list * validating_keys)
150098948Sobrien{
150198948Sobrien	return ldns_verify_trusted_time(
150298948Sobrien			res, rrset, rrsigs, ldns_time(NULL), validating_keys);
150398948Sobrien}
150498948Sobrien
150598948Sobrien
150698948Sobrienldns_status
150798948Sobrienldns_dnssec_verify_denial(ldns_rr *rr,
150898948Sobrien                          ldns_rr_list *nsecs,
150998948Sobrien                          ldns_rr_list *rrsigs)
151098948Sobrien{
151198948Sobrien	ldns_rdf *rr_name;
151298948Sobrien	ldns_rdf *wildcard_name;
151398948Sobrien	ldns_rdf *chopped_dname;
151498948Sobrien	ldns_rr *cur_nsec;
151598948Sobrien	size_t i;
151698948Sobrien	ldns_status result;
151798948Sobrien	/* needed for wildcard check on exact match */
151898948Sobrien	ldns_rr *rrsig;
151998948Sobrien	bool name_covered = false;
152098948Sobrien	bool type_covered = false;
152198948Sobrien	bool wildcard_covered = false;
152298948Sobrien	bool wildcard_type_covered = false;
152398948Sobrien
152498948Sobrien	wildcard_name = ldns_dname_new_frm_str("*");
152598948Sobrien	rr_name = ldns_rr_owner(rr);
152698948Sobrien	chopped_dname = ldns_dname_left_chop(rr_name);
152798948Sobrien	result = ldns_dname_cat(wildcard_name, chopped_dname);
152898948Sobrien	ldns_rdf_deep_free(chopped_dname);
152998948Sobrien	if (result != LDNS_STATUS_OK) {
153098948Sobrien		return result;
153198948Sobrien	}
153298948Sobrien
153398948Sobrien	for  (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) {
153498948Sobrien		cur_nsec = ldns_rr_list_rr(nsecs, i);
153598948Sobrien		if (ldns_dname_compare(rr_name, ldns_rr_owner(cur_nsec)) == 0) {
153698948Sobrien			/* see section 5.4 of RFC4035, if the label count of the NSEC's
153798948Sobrien			   RRSIG is equal, then it is proven that wildcard expansion
153898948Sobrien			   could not have been used to match the request */
153998948Sobrien			rrsig = ldns_dnssec_get_rrsig_for_name_and_type(
154098948Sobrien					  ldns_rr_owner(cur_nsec),
154198948Sobrien					  ldns_rr_get_type(cur_nsec),
154298948Sobrien					  rrsigs);
154398948Sobrien			if (rrsig && ldns_rdf2native_int8(ldns_rr_rrsig_labels(rrsig))
154498948Sobrien			    == ldns_dname_label_count(rr_name)) {
154598948Sobrien				wildcard_covered = true;
154698948Sobrien			}
154798948Sobrien
154898948Sobrien			if (ldns_nsec_bitmap_covers_type(ldns_nsec_get_bitmap(cur_nsec),
154998948Sobrien									   ldns_rr_get_type(rr))) {
155098948Sobrien				type_covered = true;
155198948Sobrien			}
155298948Sobrien		}
155398948Sobrien		if (ldns_nsec_covers_name(cur_nsec, rr_name)) {
155498948Sobrien			name_covered = true;
155598948Sobrien		}
155698948Sobrien
155798948Sobrien		if (ldns_dname_compare(wildcard_name,
155898948Sobrien						   ldns_rr_owner(cur_nsec)) == 0) {
155998948Sobrien			if (ldns_nsec_bitmap_covers_type(ldns_nsec_get_bitmap(cur_nsec),
156098948Sobrien									   ldns_rr_get_type(rr))) {
1561130809Smarcel				wildcard_type_covered = true;
1562130809Smarcel			}
1563130809Smarcel		}
156498948Sobrien
156598948Sobrien		if (ldns_nsec_covers_name(cur_nsec, wildcard_name)) {
156698948Sobrien			wildcard_covered = true;
156798948Sobrien		}
156898948Sobrien
156998948Sobrien	}
157098948Sobrien
157198948Sobrien	ldns_rdf_deep_free(wildcard_name);
157298948Sobrien
157398948Sobrien	if (type_covered || !name_covered) {
157498948Sobrien		return LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED;
157598948Sobrien	}
157698948Sobrien
157798948Sobrien	if (wildcard_type_covered || !wildcard_covered) {
157898948Sobrien		return LDNS_STATUS_DNSSEC_NSEC_WILDCARD_NOT_COVERED;
157998948Sobrien	}
158098948Sobrien
158198948Sobrien	return LDNS_STATUS_OK;
158298948Sobrien}
158398948Sobrien
158498948Sobrienldns_status
158598948Sobrienldns_dnssec_verify_denial_nsec3_match( ldns_rr *rr
158698948Sobrien				     , ldns_rr_list *nsecs
158798948Sobrien				     , ATTR_UNUSED(ldns_rr_list *rrsigs)
158898948Sobrien				     , ldns_pkt_rcode packet_rcode
158998948Sobrien				     , ldns_rr_type packet_qtype
159098948Sobrien				     , bool packet_nodata
159198948Sobrien				     , ldns_rr **match
159298948Sobrien				     )
159398948Sobrien{
159498948Sobrien	ldns_rdf *closest_encloser;
159598948Sobrien	ldns_rdf *wildcard;
159698948Sobrien	ldns_rdf *hashed_wildcard_name;
159798948Sobrien	bool wildcard_covered = false;
159898948Sobrien	ldns_rdf *zone_name;
159998948Sobrien	ldns_rdf *hashed_name;
1600130809Smarcel	/* self assignment to suppress uninitialized warning */
160198948Sobrien	ldns_rdf *next_closer = next_closer;
160298948Sobrien	ldns_rdf *hashed_next_closer;
1603130809Smarcel	size_t i;
160498948Sobrien	ldns_status result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED;
1605130809Smarcel
160698948Sobrien	if (match) {
160798948Sobrien		*match = NULL;
160898948Sobrien	}
160998948Sobrien
161098948Sobrien	zone_name = ldns_dname_left_chop(ldns_rr_owner(ldns_rr_list_rr(nsecs,0)));
161198948Sobrien
161298948Sobrien	/* section 8.4 */
161398948Sobrien	if (packet_rcode == LDNS_RCODE_NXDOMAIN) {
161498948Sobrien		closest_encloser = ldns_dnssec_nsec3_closest_encloser(
161598948Sobrien						   ldns_rr_owner(rr),
161698948Sobrien						   ldns_rr_get_type(rr),
161798948Sobrien						   nsecs);
161898948Sobrien                if(!closest_encloser) {
161998948Sobrien                        result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED;
162098948Sobrien                        goto done;
162198948Sobrien                }
162298948Sobrien
162398948Sobrien		wildcard = ldns_dname_new_frm_str("*");
1624130809Smarcel		(void) ldns_dname_cat(wildcard, closest_encloser);
162598948Sobrien
162698948Sobrien		for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) {
162798948Sobrien			hashed_wildcard_name =
162898948Sobrien				ldns_nsec3_hash_name_frm_nsec3(ldns_rr_list_rr(nsecs, 0),
162998948Sobrien										 wildcard
163098948Sobrien										 );
163198948Sobrien			(void) ldns_dname_cat(hashed_wildcard_name, zone_name);
163298948Sobrien
163398948Sobrien			if (ldns_nsec_covers_name(ldns_rr_list_rr(nsecs, i),
163498948Sobrien								 hashed_wildcard_name)) {
163598948Sobrien				wildcard_covered = true;
163698948Sobrien				if (match) {
163798948Sobrien					*match = ldns_rr_list_rr(nsecs, i);
163898948Sobrien				}
163998948Sobrien			}
164098948Sobrien			ldns_rdf_deep_free(hashed_wildcard_name);
164198948Sobrien		}
164298948Sobrien
164398948Sobrien		if (! wildcard_covered) {
164498948Sobrien			result = LDNS_STATUS_DNSSEC_NSEC_WILDCARD_NOT_COVERED;
164598948Sobrien		} else {
164698948Sobrien			result = LDNS_STATUS_OK;
164798948Sobrien		}
164898948Sobrien		ldns_rdf_deep_free(closest_encloser);
164998948Sobrien		ldns_rdf_deep_free(wildcard);
165098948Sobrien
165198948Sobrien	} else if (packet_nodata && packet_qtype != LDNS_RR_TYPE_DS) {
165298948Sobrien		/* section 8.5 */
165398948Sobrien		hashed_name = ldns_nsec3_hash_name_frm_nsec3(
165498948Sobrien		                   ldns_rr_list_rr(nsecs, 0),
165598948Sobrien		                   ldns_rr_owner(rr));
165698948Sobrien		(void) ldns_dname_cat(hashed_name, zone_name);
165798948Sobrien		for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) {
1658130809Smarcel			if (ldns_dname_compare(hashed_name,
1659130809Smarcel			         ldns_rr_owner(ldns_rr_list_rr(nsecs, i)))
166098948Sobrien			    == 0) {
166198948Sobrien				if (!ldns_nsec_bitmap_covers_type(
166298948Sobrien					    ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)),
166398948Sobrien					    packet_qtype)
166498948Sobrien				    &&
166598948Sobrien				    !ldns_nsec_bitmap_covers_type(
166698948Sobrien					    ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)),
166798948Sobrien					    LDNS_RR_TYPE_CNAME)) {
166898948Sobrien					result = LDNS_STATUS_OK;
166998948Sobrien					if (match) {
167098948Sobrien						*match = ldns_rr_list_rr(nsecs, i);
167198948Sobrien					}
167298948Sobrien					goto done;
167398948Sobrien				}
167498948Sobrien			}
167598948Sobrien		}
167698948Sobrien		result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED;
167798948Sobrien		/* wildcard no data? section 8.7 */
167898948Sobrien		closest_encloser = ldns_dnssec_nsec3_closest_encloser(
1679130809Smarcel				   ldns_rr_owner(rr),
168098948Sobrien				   ldns_rr_get_type(rr),
168198948Sobrien				   nsecs);
168298948Sobrien		if(!closest_encloser) {
168398948Sobrien			result = LDNS_STATUS_NSEC3_ERR;
1684130809Smarcel			goto done;
168598948Sobrien		}
168698948Sobrien		wildcard = ldns_dname_new_frm_str("*");
168798948Sobrien		(void) ldns_dname_cat(wildcard, closest_encloser);
168898948Sobrien		for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) {
168998948Sobrien			hashed_wildcard_name =
1690130809Smarcel				ldns_nsec3_hash_name_frm_nsec3(ldns_rr_list_rr(nsecs, 0),
169198948Sobrien					 wildcard);
169298948Sobrien			(void) ldns_dname_cat(hashed_wildcard_name, zone_name);
169398948Sobrien
1694130809Smarcel			if (ldns_dname_compare(hashed_wildcard_name,
169598948Sobrien			         ldns_rr_owner(ldns_rr_list_rr(nsecs, i)))
169698948Sobrien			    == 0) {
169798948Sobrien				if (!ldns_nsec_bitmap_covers_type(
169898948Sobrien					    ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)),
169998948Sobrien					    packet_qtype)
170098948Sobrien				    &&
170198948Sobrien				    !ldns_nsec_bitmap_covers_type(
170298948Sobrien					    ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)),
170398948Sobrien					    LDNS_RR_TYPE_CNAME)) {
170498948Sobrien					result = LDNS_STATUS_OK;
170598948Sobrien					if (match) {
170698948Sobrien						*match = ldns_rr_list_rr(nsecs, i);
170798948Sobrien					}
170898948Sobrien				}
170998948Sobrien			}
171098948Sobrien			ldns_rdf_deep_free(hashed_wildcard_name);
171198948Sobrien			if (result == LDNS_STATUS_OK) {
1712130809Smarcel				break;
171398948Sobrien			}
171498948Sobrien		}
171598948Sobrien		ldns_rdf_deep_free(closest_encloser);
171698948Sobrien		ldns_rdf_deep_free(wildcard);
171798948Sobrien	} else if (packet_nodata && packet_qtype == LDNS_RR_TYPE_DS) {
171898948Sobrien		/* section 8.6 */
171998948Sobrien		/* note: up to XXX this is the same as for 8.5 */
1720130809Smarcel		hashed_name = ldns_nsec3_hash_name_frm_nsec3(ldns_rr_list_rr(nsecs,
172198948Sobrien														 0),
172298948Sobrien											ldns_rr_owner(rr)
172398948Sobrien											);
172498948Sobrien		(void) ldns_dname_cat(hashed_name, zone_name);
172598948Sobrien		for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) {
172698948Sobrien			if (ldns_dname_compare(hashed_name,
172798948Sobrien							   ldns_rr_owner(ldns_rr_list_rr(nsecs,
172898948Sobrien													   i)))
172998948Sobrien			    == 0) {
173098948Sobrien				if (!ldns_nsec_bitmap_covers_type(
173198948Sobrien					    ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)),
1732130809Smarcel					    LDNS_RR_TYPE_DS)
173398948Sobrien				    &&
173498948Sobrien				    !ldns_nsec_bitmap_covers_type(
173598948Sobrien					    ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)),
173698948Sobrien					    LDNS_RR_TYPE_CNAME)) {
173798948Sobrien					result = LDNS_STATUS_OK;
173898948Sobrien					if (match) {
173998948Sobrien						*match = ldns_rr_list_rr(nsecs, i);
174098948Sobrien					}
174198948Sobrien					goto done;
174298948Sobrien				}
174398948Sobrien			}
174498948Sobrien		}
174598948Sobrien
174698948Sobrien		/* XXX see note above */
174798948Sobrien		result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED;
174898948Sobrien
174998948Sobrien		closest_encloser = ldns_dnssec_nsec3_closest_encloser(
175098948Sobrien				   ldns_rr_owner(rr),
175198948Sobrien				   ldns_rr_get_type(rr),
175298948Sobrien				   nsecs);
175398948Sobrien		if(!closest_encloser) {
175498948Sobrien			result = LDNS_STATUS_NSEC3_ERR;
175598948Sobrien			goto done;
175698948Sobrien		}
175798948Sobrien		/* Now check if we have a Opt-Out NSEC3 that covers the "next closer"*/
175898948Sobrien
175998948Sobrien		if (ldns_dname_label_count(closest_encloser) + 1
176098948Sobrien		    >= ldns_dname_label_count(ldns_rr_owner(rr))) {
176198948Sobrien
176298948Sobrien			/* Query name *is* the "next closer". */
176398948Sobrien			hashed_next_closer = hashed_name;
176498948Sobrien		} else {
176598948Sobrien
176698948Sobrien			/* "next closer" has less labels than the query name.
176798948Sobrien			 * Create the name and hash it.
176898948Sobrien			 */
176998948Sobrien			next_closer = ldns_dname_clone_from(
177098948Sobrien					ldns_rr_owner(rr),
177198948Sobrien					ldns_dname_label_count(ldns_rr_owner(rr))
177298948Sobrien					- (ldns_dname_label_count(closest_encloser) + 1)
177398948Sobrien					);
177498948Sobrien			hashed_next_closer = ldns_nsec3_hash_name_frm_nsec3(
177598948Sobrien					ldns_rr_list_rr(nsecs, 0),
177698948Sobrien					next_closer
177798948Sobrien					);
177898948Sobrien			(void) ldns_dname_cat(hashed_next_closer, zone_name);
177998948Sobrien		}
178098948Sobrien		/* Find the NSEC3 that covers the "next closer" */
178198948Sobrien		for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) {
178298948Sobrien			if (ldns_nsec_covers_name(ldns_rr_list_rr(nsecs, i),
178398948Sobrien			                          hashed_next_closer) &&
178498948Sobrien				ldns_nsec3_optout(ldns_rr_list_rr(nsecs, i))) {
178598948Sobrien
178698948Sobrien				result = LDNS_STATUS_OK;
178798948Sobrien				if (match) {
178898948Sobrien					*match = ldns_rr_list_rr(nsecs, i);
178998948Sobrien				}
179098948Sobrien				break;
179198948Sobrien			}
179298948Sobrien		}
179398948Sobrien		if (ldns_dname_label_count(closest_encloser) + 1
1794130809Smarcel		    < ldns_dname_label_count(ldns_rr_owner(rr))) {
179598948Sobrien
179698948Sobrien			/* "next closer" has less labels than the query name.
179798948Sobrien			 * Dispose of the temporary variables that held that name.
179898948Sobrien			 */
179998948Sobrien			ldns_rdf_deep_free(hashed_next_closer);
180098948Sobrien			ldns_rdf_deep_free(next_closer);
180198948Sobrien		}
180298948Sobrien		ldns_rdf_deep_free(closest_encloser);
180398948Sobrien	}
180498948Sobrien
180598948Sobrien done:
180698948Sobrien	ldns_rdf_deep_free(zone_name);
180798948Sobrien	return result;
180898948Sobrien}
180998948Sobrien
181098948Sobrienldns_status
1811130809Smarcelldns_dnssec_verify_denial_nsec3(ldns_rr *rr,
181298948Sobrien						  ldns_rr_list *nsecs,
181398948Sobrien						  ldns_rr_list *rrsigs,
181498948Sobrien						  ldns_pkt_rcode packet_rcode,
181598948Sobrien						  ldns_rr_type packet_qtype,
181698948Sobrien						  bool packet_nodata)
181798948Sobrien{
181898948Sobrien	return ldns_dnssec_verify_denial_nsec3_match(
181998948Sobrien				rr, nsecs, rrsigs, packet_rcode,
182098948Sobrien				packet_qtype, packet_nodata, NULL
182198948Sobrien	       );
182298948Sobrien}
1823130809Smarcel
182498948Sobrien#ifdef USE_GOST
182598948SobrienEVP_PKEY*
182698948Sobrienldns_gost2pkey_raw(unsigned char* key, size_t keylen)
182798948Sobrien{
182898948Sobrien	/* prefix header for X509 encoding */
182998948Sobrien	uint8_t asn[37] = { 0x30, 0x63, 0x30, 0x1c, 0x06, 0x06, 0x2a, 0x85,
183098948Sobrien		0x03, 0x02, 0x02, 0x13, 0x30, 0x12, 0x06, 0x07, 0x2a, 0x85,
183198948Sobrien		0x03, 0x02, 0x02, 0x23, 0x01, 0x06, 0x07, 0x2a, 0x85, 0x03,
183298948Sobrien		0x02, 0x02, 0x1e, 0x01, 0x03, 0x43, 0x00, 0x04, 0x40};
183398948Sobrien	unsigned char encoded[37+64];
183498948Sobrien	const unsigned char* pp;
183598948Sobrien	if(keylen != 64) {
183698948Sobrien		/* key wrong size */
183798948Sobrien		return NULL;
183898948Sobrien	}
183998948Sobrien
184098948Sobrien	/* create evp_key */
184198948Sobrien	memmove(encoded, asn, 37);
184298948Sobrien	memmove(encoded+37, key, 64);
184398948Sobrien	pp = (unsigned char*)&encoded[0];
184498948Sobrien
184598948Sobrien	return d2i_PUBKEY(NULL, &pp, (int)sizeof(encoded));
184698948Sobrien}
1847130809Smarcel
184898948Sobrienstatic ldns_status
184998948Sobrienldns_verify_rrsig_gost_raw(unsigned char* sig, size_t siglen,
185098948Sobrien	ldns_buffer* rrset, unsigned char* key, size_t keylen)
185198948Sobrien{
185298948Sobrien	EVP_PKEY *evp_key;
185398948Sobrien	ldns_status result;
185498948Sobrien
185598948Sobrien	(void) ldns_key_EVP_load_gost_id();
185698948Sobrien	evp_key = ldns_gost2pkey_raw(key, keylen);
185798948Sobrien	if(!evp_key) {
185898948Sobrien		/* could not convert key */
185998948Sobrien		return LDNS_STATUS_CRYPTO_BOGUS;
186098948Sobrien	}
186198948Sobrien
186298948Sobrien	/* verify signature */
1863130809Smarcel	result = ldns_verify_rrsig_evp_raw(sig, siglen, rrset,
186498948Sobrien		evp_key, EVP_get_digestbyname("md_gost94"));
186598948Sobrien	EVP_PKEY_free(evp_key);
186698948Sobrien
186798948Sobrien	return result;
1868130809Smarcel}
186998948Sobrien#endif
187098948Sobrien
187198948Sobrien#ifdef USE_ECDSA
1872130809SmarcelEVP_PKEY*
187398948Sobrienldns_ecdsa2pkey_raw(unsigned char* key, size_t keylen, uint8_t algo)
187498948Sobrien{
187598948Sobrien	unsigned char buf[256+2]; /* sufficient for 2*384/8+1 */
187698948Sobrien        const unsigned char* pp = buf;
187798948Sobrien        EVP_PKEY *evp_key;
187898948Sobrien        EC_KEY *ec;
187998948Sobrien	/* check length, which uncompressed must be 2 bignums */
188098948Sobrien        if(algo == LDNS_ECDSAP256SHA256) {
188198948Sobrien		if(keylen != 2*256/8) return NULL;
188298948Sobrien                ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
188398948Sobrien        } else if(algo == LDNS_ECDSAP384SHA384) {
188498948Sobrien		if(keylen != 2*384/8) return NULL;
188598948Sobrien                ec = EC_KEY_new_by_curve_name(NID_secp384r1);
188698948Sobrien        } else    ec = NULL;
188798948Sobrien        if(!ec) return NULL;
1888130809Smarcel	if(keylen+1 > sizeof(buf))
188998948Sobrien		return NULL; /* sanity check */
189098948Sobrien	/* prepend the 0x02 (from docs) (or actually 0x04 from implementation
189198948Sobrien	 * of openssl) for uncompressed data */
189298948Sobrien	buf[0] = POINT_CONVERSION_UNCOMPRESSED;
189398948Sobrien	memmove(buf+1, key, keylen);
189498948Sobrien        if(!o2i_ECPublicKey(&ec, &pp, (int)keylen+1)) {
189598948Sobrien                EC_KEY_free(ec);
189698948Sobrien                return NULL;
189798948Sobrien        }
189898948Sobrien        evp_key = EVP_PKEY_new();
189998948Sobrien        if(!evp_key) {
190098948Sobrien                EC_KEY_free(ec);
190198948Sobrien                return NULL;
190298948Sobrien        }
190398948Sobrien        if (!EVP_PKEY_assign_EC_KEY(evp_key, ec)) {
190498948Sobrien		EVP_PKEY_free(evp_key);
190598948Sobrien		EC_KEY_free(ec);
190698948Sobrien		return NULL;
190798948Sobrien	}
190898948Sobrien        return evp_key;
190998948Sobrien}
191098948Sobrien
191198948Sobrienstatic ldns_status
1912130809Smarcelldns_verify_rrsig_ecdsa_raw(unsigned char* sig, size_t siglen,
191398948Sobrien	ldns_buffer* rrset, unsigned char* key, size_t keylen, uint8_t algo)
191498948Sobrien{
191598948Sobrien        EVP_PKEY *evp_key;
191698948Sobrien        ldns_status result;
191798948Sobrien        const EVP_MD *d;
191898948Sobrien
191998948Sobrien        evp_key = ldns_ecdsa2pkey_raw(key, keylen, algo);
192098948Sobrien        if(!evp_key) {
192198948Sobrien		/* could not convert key */
192298948Sobrien		return LDNS_STATUS_CRYPTO_BOGUS;
192398948Sobrien        }
192498948Sobrien        if(algo == LDNS_ECDSAP256SHA256)
192598948Sobrien                d = EVP_sha256();
192698948Sobrien        else    d = EVP_sha384(); /* LDNS_ECDSAP384SHA384 */
192798948Sobrien	result = ldns_verify_rrsig_evp_raw(sig, siglen, rrset, evp_key, d);
1928130809Smarcel	EVP_PKEY_free(evp_key);
192998948Sobrien	return result;
193098948Sobrien}
193198948Sobrien#endif
193298948Sobrien
1933130809Smarcelldns_status
193498948Sobrienldns_verify_rrsig_buffers(ldns_buffer *rawsig_buf, ldns_buffer *verify_buf,
193598948Sobrien					 ldns_buffer *key_buf, uint8_t algo)
193698948Sobrien{
1937130809Smarcel	return ldns_verify_rrsig_buffers_raw(
193898948Sobrien			 (unsigned char*)ldns_buffer_begin(rawsig_buf),
193998948Sobrien			 ldns_buffer_position(rawsig_buf),
194098948Sobrien			 verify_buf,
194198948Sobrien			 (unsigned char*)ldns_buffer_begin(key_buf),
194298948Sobrien			 ldns_buffer_position(key_buf), algo);
194398948Sobrien}
194498948Sobrien
194598948Sobrienldns_status
194698948Sobrienldns_verify_rrsig_buffers_raw(unsigned char* sig, size_t siglen,
194798948Sobrien						ldns_buffer *verify_buf, unsigned char* key, size_t keylen,
194898948Sobrien						uint8_t algo)
194998948Sobrien{
195098948Sobrien	/* check for right key */
195198948Sobrien	switch(algo) {
195298948Sobrien	case LDNS_DSA:
195398948Sobrien	case LDNS_DSA_NSEC3:
195498948Sobrien		return ldns_verify_rrsig_dsa_raw(sig,
195598948Sobrien								   siglen,
195698948Sobrien								   verify_buf,
195798948Sobrien								   key,
195898948Sobrien								   keylen);
195998948Sobrien		break;
196098948Sobrien	case LDNS_RSASHA1:
196198948Sobrien	case LDNS_RSASHA1_NSEC3:
196298948Sobrien		return ldns_verify_rrsig_rsasha1_raw(sig,
196398948Sobrien									  siglen,
196498948Sobrien									  verify_buf,
196598948Sobrien									  key,
196698948Sobrien									  keylen);
196798948Sobrien		break;
196898948Sobrien#ifdef USE_SHA2
196998948Sobrien	case LDNS_RSASHA256:
197098948Sobrien		return ldns_verify_rrsig_rsasha256_raw(sig,
197198948Sobrien									    siglen,
197298948Sobrien									    verify_buf,
197398948Sobrien									    key,
197498948Sobrien									    keylen);
197598948Sobrien		break;
197698948Sobrien	case LDNS_RSASHA512:
197798948Sobrien		return ldns_verify_rrsig_rsasha512_raw(sig,
197898948Sobrien									    siglen,
197998948Sobrien									    verify_buf,
1980130809Smarcel									    key,
1981130809Smarcel									    keylen);
198298948Sobrien		break;
198398948Sobrien#endif
198498948Sobrien#ifdef USE_GOST
198598948Sobrien	case LDNS_ECC_GOST:
198698948Sobrien		return ldns_verify_rrsig_gost_raw(sig, siglen, verify_buf,
198798948Sobrien			key, keylen);
198898948Sobrien		break;
198998948Sobrien#endif
199098948Sobrien#ifdef USE_ECDSA
199198948Sobrien        case LDNS_ECDSAP256SHA256:
199298948Sobrien        case LDNS_ECDSAP384SHA384:
199398948Sobrien		return ldns_verify_rrsig_ecdsa_raw(sig, siglen, verify_buf,
199498948Sobrien			key, keylen, algo);
199598948Sobrien		break;
199698948Sobrien#endif
199798948Sobrien	case LDNS_RSAMD5:
199898948Sobrien		return ldns_verify_rrsig_rsamd5_raw(sig,
199998948Sobrien									 siglen,
200098948Sobrien									 verify_buf,
200198948Sobrien									 key,
200298948Sobrien									 keylen);
200398948Sobrien		break;
200498948Sobrien	default:
200598948Sobrien		/* do you know this alg?! */
200698948Sobrien		return LDNS_STATUS_CRYPTO_UNKNOWN_ALGO;
200798948Sobrien	}
200898948Sobrien}
200998948Sobrien
201098948Sobrien
201198948Sobrien/**
201298948Sobrien * Reset the ttl in the rrset with the orig_ttl from the sig
201398948Sobrien * and update owner name if it was wildcard
201498948Sobrien * Also canonicalizes the rrset.
201598948Sobrien * @param rrset: rrset to modify
201698948Sobrien * @param sig: signature to take TTL and wildcard values from
201798948Sobrien */
201898948Sobrienstatic void
201998948Sobrienldns_rrset_use_signature_ttl(ldns_rr_list* rrset_clone, ldns_rr* rrsig)
202098948Sobrien{
202198948Sobrien	uint32_t orig_ttl;
202298948Sobrien	uint16_t i;
202398948Sobrien	uint8_t label_count;
202498948Sobrien	ldns_rdf *wildcard_name;
202598948Sobrien	ldns_rdf *wildcard_chopped;
202698948Sobrien	ldns_rdf *wildcard_chopped_tmp;
2027130809Smarcel
202898948Sobrien	if ((rrsig == NULL) || ldns_rr_rd_count(rrsig) < 4) {
202998948Sobrien		return;
203098948Sobrien	}
203198948Sobrien
203298948Sobrien	orig_ttl = ldns_rdf2native_int32( ldns_rr_rdf(rrsig, 3));
203398948Sobrien	label_count = ldns_rdf2native_int8(ldns_rr_rdf(rrsig, 2));
203498948Sobrien
203598948Sobrien	for(i = 0; i < ldns_rr_list_rr_count(rrset_clone); i++) {
203698948Sobrien		if (label_count <
203798948Sobrien		    ldns_dname_label_count(
203898948Sobrien			   ldns_rr_owner(ldns_rr_list_rr(rrset_clone, i)))) {
203998948Sobrien			(void) ldns_str2rdf_dname(&wildcard_name, "*");
204098948Sobrien			wildcard_chopped = ldns_rdf_clone(ldns_rr_owner(
204198948Sobrien				ldns_rr_list_rr(rrset_clone, i)));
204298948Sobrien			while (label_count < ldns_dname_label_count(wildcard_chopped)) {
2043130809Smarcel				wildcard_chopped_tmp = ldns_dname_left_chop(
204498948Sobrien					wildcard_chopped);
204598948Sobrien				ldns_rdf_deep_free(wildcard_chopped);
204698948Sobrien				wildcard_chopped = wildcard_chopped_tmp;
204798948Sobrien			}
204898948Sobrien			(void) ldns_dname_cat(wildcard_name, wildcard_chopped);
204998948Sobrien			ldns_rdf_deep_free(wildcard_chopped);
205098948Sobrien			ldns_rdf_deep_free(ldns_rr_owner(ldns_rr_list_rr(
205198948Sobrien				rrset_clone, i)));
205298948Sobrien			ldns_rr_set_owner(ldns_rr_list_rr(rrset_clone, i),
205398948Sobrien				wildcard_name);
205498948Sobrien		}
205598948Sobrien		ldns_rr_set_ttl(ldns_rr_list_rr(rrset_clone, i), orig_ttl);
205698948Sobrien		/* convert to lowercase */
205798948Sobrien		ldns_rr2canonical(ldns_rr_list_rr(rrset_clone, i));
205898948Sobrien	}
205998948Sobrien}
206098948Sobrien
206198948Sobrien/**
206298948Sobrien * Make raw signature buffer out of rrsig
206398948Sobrien * @param rawsig_buf: raw signature buffer for result
206498948Sobrien * @param rrsig: signature to convert
206598948Sobrien * @return OK or more specific error.
206698948Sobrien */
206798948Sobrienstatic ldns_status
206898948Sobrienldns_rrsig2rawsig_buffer(ldns_buffer* rawsig_buf, ldns_rr* rrsig)
206998948Sobrien{
207098948Sobrien	uint8_t sig_algo;
207198948Sobrien
207298948Sobrien	if (rrsig == NULL) {
207398948Sobrien		return LDNS_STATUS_CRYPTO_NO_RRSIG;
207498948Sobrien	}
207598948Sobrien	if (ldns_rr_rdf(rrsig, 1) == NULL) {
207698948Sobrien		return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG;
207798948Sobrien	}
207898948Sobrien	sig_algo = ldns_rdf2native_int8(ldns_rr_rdf(rrsig, 1));
207998948Sobrien	/* check for known and implemented algo's now (otherwise
208098948Sobrien	 * the function could return a wrong error
208198948Sobrien	 */
208298948Sobrien	/* create a buffer with signature rdata */
208398948Sobrien	/* for some algorithms we need other data than for others... */
208498948Sobrien	/* (the DSA API wants DER encoding for instance) */
208598948Sobrien
208698948Sobrien	switch(sig_algo) {
208798948Sobrien	case LDNS_RSAMD5:
2088130809Smarcel	case LDNS_RSASHA1:
208998948Sobrien	case LDNS_RSASHA1_NSEC3:
209098948Sobrien#ifdef USE_SHA2
209198948Sobrien	case LDNS_RSASHA256:
209298948Sobrien	case LDNS_RSASHA512:
209398948Sobrien#endif
209498948Sobrien#ifdef USE_GOST
209598948Sobrien	case LDNS_ECC_GOST:
2096130809Smarcel#endif
209798948Sobrien		if (ldns_rr_rdf(rrsig, 8) == NULL) {
209898948Sobrien			return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG;
209919370Spst		}
210019370Spst		if (ldns_rdf2buffer_wire(rawsig_buf, ldns_rr_rdf(rrsig, 8))
210119370Spst			       	!= LDNS_STATUS_OK) {
210298948Sobrien			return LDNS_STATUS_MEM_ERR;
210398948Sobrien		}
210419370Spst		break;
210598948Sobrien	case LDNS_DSA:
210698948Sobrien	case LDNS_DSA_NSEC3:
210719370Spst		/* EVP takes rfc2459 format, which is a tad longer than dns format */
2108130809Smarcel		if (ldns_rr_rdf(rrsig, 8) == NULL) {
2109130809Smarcel			return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG;
211019370Spst		}
211119370Spst		if (ldns_convert_dsa_rrsig_rdf2asn1(
211219370Spst					rawsig_buf, ldns_rr_rdf(rrsig, 8))
211319370Spst				!= LDNS_STATUS_OK) {
211446283Sdfr			/*
211546283Sdfr			  if (ldns_rdf2buffer_wire(rawsig_buf,
211698948Sobrien			  ldns_rr_rdf(rrsig, 8)) != LDNS_STATUS_OK) {
211798948Sobrien			*/
211846283Sdfr			return LDNS_STATUS_MEM_ERR;
211946283Sdfr		}
212046283Sdfr		break;
212119370Spst#ifdef USE_ECDSA
212219370Spst        case LDNS_ECDSAP256SHA256:
2123130809Smarcel        case LDNS_ECDSAP384SHA384:
212446283Sdfr                /* EVP produces an ASN prefix on the signature, which is
212519370Spst                 * not used in the DNS */
212619370Spst		if (ldns_rr_rdf(rrsig, 8) == NULL) {
212719370Spst			return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG;
212819370Spst		}
212919370Spst		if (ldns_convert_ecdsa_rrsig_rdf2asn1(
213019370Spst					rawsig_buf, ldns_rr_rdf(rrsig, 8))
213119370Spst				!= LDNS_STATUS_OK) {
213219370Spst			return LDNS_STATUS_MEM_ERR;
213319370Spst                }
213419370Spst                break;
213519370Spst#endif
213619370Spst	case LDNS_DH:
213719370Spst	case LDNS_ECC:
213898948Sobrien	case LDNS_INDIRECT:
213998948Sobrien		return LDNS_STATUS_CRYPTO_ALGO_NOT_IMPL;
214098948Sobrien	default:
214198948Sobrien		return LDNS_STATUS_CRYPTO_UNKNOWN_ALGO;
214219370Spst	}
214319370Spst	return LDNS_STATUS_OK;
214498948Sobrien}
214598948Sobrien
214619370Spst/**
214719370Spst * Check RRSIG timestamps against the given 'now' time.
2148130809Smarcel * @param rrsig: signature to check.
214998948Sobrien * @param now: the current time in seconds epoch.
215019370Spst * @return status code LDNS_STATUS_OK if all is fine.
215198948Sobrien */
215298948Sobrienstatic ldns_status
215398948Sobrienldns_rrsig_check_timestamps(ldns_rr* rrsig, time_t now)
215498948Sobrien{
215519370Spst	int32_t inception, expiration;
215619370Spst
215719370Spst	/* check the signature time stamps */
215819370Spst	inception = (int32_t)ldns_rdf2native_time_t(
215919370Spst		ldns_rr_rrsig_inception(rrsig));
216019370Spst	expiration = (int32_t)ldns_rdf2native_time_t(
216119370Spst		ldns_rr_rrsig_expiration(rrsig));
216219370Spst
216319370Spst	if (expiration - inception < 0) {
216419370Spst		/* bad sig, expiration before inception?? Tsssg */
216519370Spst		return LDNS_STATUS_CRYPTO_EXPIRATION_BEFORE_INCEPTION;
216619370Spst	}
216719370Spst	if (((int32_t) now) - inception < 0) {
216819370Spst		/* bad sig, inception date has not yet come to pass */
216919370Spst		return LDNS_STATUS_CRYPTO_SIG_NOT_INCEPTED;
217019370Spst	}
217119370Spst	if (expiration - ((int32_t) now) < 0) {
217219370Spst		/* bad sig, expiration date has passed */
217319370Spst		return LDNS_STATUS_CRYPTO_SIG_EXPIRED;
217498948Sobrien	}
217598948Sobrien	return LDNS_STATUS_OK;
217698948Sobrien}
217798948Sobrien
217819370Spst/**
217919370Spst * Prepare for verification.
218098948Sobrien * @param rawsig_buf: raw signature buffer made ready.
218119370Spst * @param verify_buf: data for verification buffer made ready.
218219370Spst * @param rrset_clone: made ready.
218398948Sobrien * @param rrsig: signature to prepare for.
2184130809Smarcel * @return LDNS_STATUS_OK is all went well. Otherwise specific error.
218519370Spst */
218619370Spststatic ldns_status
218719370Spstldns_prepare_for_verify(ldns_buffer* rawsig_buf, ldns_buffer* verify_buf,
218819370Spst	ldns_rr_list* rrset_clone, ldns_rr* rrsig)
218919370Spst{
219098948Sobrien	ldns_status result;
219119370Spst
219246283Sdfr	/* canonicalize the sig */
219346283Sdfr	ldns_dname2canonical(ldns_rr_owner(rrsig));
219419370Spst
219519370Spst	/* check if the typecovered is equal to the type checked */
219698948Sobrien	if (ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rrsig)) !=
219719370Spst	    ldns_rr_get_type(ldns_rr_list_rr(rrset_clone, 0)))
219819370Spst		return LDNS_STATUS_CRYPTO_TYPE_COVERED_ERR;
219919370Spst
220019370Spst	/* create a buffer with b64 signature rdata */
220119370Spst	result = ldns_rrsig2rawsig_buffer(rawsig_buf, rrsig);
2202130809Smarcel	if(result != LDNS_STATUS_OK)
220346283Sdfr		return result;
220446283Sdfr
220546283Sdfr	/* use TTL from signature. Use wildcard names for wildcards */
220646283Sdfr	/* also canonicalizes rrset_clone */
220719370Spst	ldns_rrset_use_signature_ttl(rrset_clone, rrsig);
220846283Sdfr
220946283Sdfr	/* sort the rrset in canonical order  */
221046283Sdfr	ldns_rr_list_sort(rrset_clone);
221146283Sdfr
221246283Sdfr	/* put the signature rr (without the b64) to the verify_buf */
221346283Sdfr	if (ldns_rrsig2buffer_wire(verify_buf, rrsig) != LDNS_STATUS_OK)
221446283Sdfr		return LDNS_STATUS_MEM_ERR;
221598948Sobrien
221646283Sdfr	/* add the rrset in verify_buf */
221746283Sdfr	if(ldns_rr_list2buffer_wire(verify_buf, rrset_clone)
221846283Sdfr		!= LDNS_STATUS_OK)
221946283Sdfr		return LDNS_STATUS_MEM_ERR;
222046283Sdfr
222146283Sdfr	return LDNS_STATUS_OK;
222246283Sdfr}
222346283Sdfr
222446283Sdfr/**
222546283Sdfr * Check if a key matches a signature.
222619370Spst * Checks keytag, sigalgo and signature.
222746283Sdfr * @param rawsig_buf: raw signature buffer for verify
2228130809Smarcel * @param verify_buf: raw data buffer for verify
222919370Spst * @param rrsig: the rrsig
223046283Sdfr * @param key: key to attempt.
223146283Sdfr * @return LDNS_STATUS_OK if OK, else some specific error.
223219370Spst */
223319370Spststatic ldns_status
223446283Sdfrldns_verify_test_sig_key(ldns_buffer* rawsig_buf, ldns_buffer* verify_buf,
2235130809Smarcel	ldns_rr* rrsig, ldns_rr* key)
223646283Sdfr{
223746283Sdfr	uint8_t sig_algo;
223846283Sdfr
223919370Spst	if (rrsig == NULL) {
224046283Sdfr		return LDNS_STATUS_CRYPTO_NO_RRSIG;
224198948Sobrien	}
224298948Sobrien	if (ldns_rr_rdf(rrsig, 1) == NULL) {
224398948Sobrien		return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG;
224498948Sobrien	}
224519370Spst	sig_algo = ldns_rdf2native_int8(ldns_rr_rdf(rrsig, 1));
224646283Sdfr
224798948Sobrien	/* before anything, check if the keytags match */
2248130809Smarcel	if (ldns_calc_keytag(key)
224998948Sobrien	    ==
2250130809Smarcel	    ldns_rdf2native_int16(ldns_rr_rrsig_keytag(rrsig))
225198948Sobrien	    ) {
2252130809Smarcel		ldns_buffer* key_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN);
2253130809Smarcel		ldns_status result = LDNS_STATUS_ERR;
225498948Sobrien
225598948Sobrien		/* put the key-data in a buffer, that's the third rdf, with
225619370Spst		 * the base64 encoded key data */
225719370Spst		if (ldns_rr_rdf(key, 3) == NULL) {
225819370Spst			ldns_buffer_free(key_buf);
225919370Spst			return LDNS_STATUS_MISSING_RDATA_FIELDS_KEY;
226019370Spst		}
226119370Spst		if (ldns_rdf2buffer_wire(key_buf, ldns_rr_rdf(key, 3))
226219370Spst			       	!= LDNS_STATUS_OK) {
226319370Spst			ldns_buffer_free(key_buf);
226419370Spst			/* returning is bad might screw up
226519370Spst			   good keys later in the list
226619370Spst			   what to do? */
226719370Spst			return LDNS_STATUS_ERR;
226819370Spst		}
226919370Spst
2270130809Smarcel		if (ldns_rr_rdf(key, 2) == NULL) {
227198948Sobrien			result = LDNS_STATUS_MISSING_RDATA_FIELDS_KEY;
227219370Spst		}
227398948Sobrien		else if (sig_algo == ldns_rdf2native_int8(
227419370Spst					ldns_rr_rdf(key, 2))) {
227519370Spst			result = ldns_verify_rrsig_buffers(rawsig_buf,
227619370Spst				verify_buf, key_buf, sig_algo);
227719370Spst		} else {
227819370Spst			/* No keys with the corresponding algorithm are found */
227919370Spst			result = LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY;
228019370Spst		}
228198948Sobrien
228219370Spst		ldns_buffer_free(key_buf);
228398948Sobrien		return result;
228419370Spst	}
228519370Spst	else {
2286130809Smarcel		/* No keys with the corresponding keytag are found */
228798948Sobrien		return LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY;
228898948Sobrien	}
228998948Sobrien}
2290130809Smarcel
2291130809Smarcel/*
229219370Spst * to verify:
229319370Spst * - create the wire fmt of the b64 key rdata
229498948Sobrien * - create the wire fmt of the sorted rrset
229519370Spst * - create the wire fmt of the b64 sig rdata
2296130809Smarcel * - create the wire fmt of the sig without the b64 rdata
229719370Spst * - cat the sig data (without b64 rdata) to the rrset
229819370Spst * - verify the rrset+sig, with the b64 data and the b64 key data
229919370Spst */
230019370Spstldns_status
230119370Spstldns_verify_rrsig_keylist_time(
230219370Spst		ldns_rr_list *rrset,
230398948Sobrien		ldns_rr *rrsig,
230498948Sobrien		const ldns_rr_list *keys,
230519370Spst		time_t check_time,
230619370Spst		ldns_rr_list *good_keys)
230719370Spst{
230819370Spst	ldns_status result;
230919370Spst	ldns_rr_list *valid = ldns_rr_list_new();
231019370Spst	if (!valid)
231119370Spst		return LDNS_STATUS_MEM_ERR;
231219370Spst
231319370Spst	result = ldns_verify_rrsig_keylist_notime(rrset, rrsig, keys, valid);
231419370Spst	if(result != LDNS_STATUS_OK) {
231519370Spst		ldns_rr_list_free(valid);
231619370Spst		return result;
231719370Spst	}
231819370Spst
231919370Spst	/* check timestamps last; its OK except time */
232019370Spst	result = ldns_rrsig_check_timestamps(rrsig, check_time);
232146283Sdfr	if(result != LDNS_STATUS_OK) {
232246283Sdfr		ldns_rr_list_free(valid);
232319370Spst		return result;
232419370Spst	}
232598948Sobrien
232619370Spst	ldns_rr_list_cat(good_keys, valid);
232798948Sobrien	ldns_rr_list_free(valid);
232898948Sobrien	return LDNS_STATUS_OK;
232998948Sobrien}
233098948Sobrien
233119370Spst/*
233246283Sdfr * to verify:
233319370Spst * - create the wire fmt of the b64 key rdata
233419370Spst * - create the wire fmt of the sorted rrset
233598948Sobrien * - create the wire fmt of the b64 sig rdata
233619370Spst * - create the wire fmt of the sig without the b64 rdata
233719370Spst * - cat the sig data (without b64 rdata) to the rrset
233819370Spst * - verify the rrset+sig, with the b64 data and the b64 key data
233919370Spst */
234019370Spstldns_status
234198948Sobrienldns_verify_rrsig_keylist(ldns_rr_list *rrset,
234219370Spst					 ldns_rr *rrsig,
234319370Spst					 const ldns_rr_list *keys,
234419370Spst					 ldns_rr_list *good_keys)
234598948Sobrien{
234619370Spst	return ldns_verify_rrsig_keylist_time(
234719370Spst			rrset, rrsig, keys, ldns_time(NULL), good_keys);
234819370Spst}
234919370Spst
235019370Spstldns_status
235119370Spstldns_verify_rrsig_keylist_notime(ldns_rr_list *rrset,
235298948Sobrien					 ldns_rr *rrsig,
235319370Spst					 const ldns_rr_list *keys,
235419370Spst					 ldns_rr_list *good_keys)
235519370Spst{
235619370Spst	ldns_buffer *rawsig_buf;
235719370Spst	ldns_buffer *verify_buf;
235819370Spst	uint16_t i;
235919370Spst	ldns_status result, status;
236019370Spst	ldns_rr_list *rrset_clone;
236119370Spst	ldns_rr_list *validkeys;
236219370Spst
236319370Spst	if (!rrset) {
236419370Spst		return LDNS_STATUS_ERR;
236519370Spst	}
236619370Spst
236719370Spst	validkeys = ldns_rr_list_new();
236898948Sobrien	if (!validkeys) {
236919370Spst		return LDNS_STATUS_MEM_ERR;
237019370Spst	}
237119370Spst
237219370Spst	/* clone the rrset so that we can fiddle with it */
237319370Spst	rrset_clone = ldns_rr_list_clone(rrset);
237498948Sobrien
237519370Spst	/* create the buffers which will certainly hold the raw data */
237619370Spst	rawsig_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN);
237719370Spst	verify_buf  = ldns_buffer_new(LDNS_MAX_PACKETLEN);
237819370Spst
237998948Sobrien	result = ldns_prepare_for_verify(rawsig_buf, verify_buf,
238019370Spst		rrset_clone, rrsig);
238119370Spst	if(result != LDNS_STATUS_OK) {
238219370Spst		ldns_buffer_free(verify_buf);
238319370Spst		ldns_buffer_free(rawsig_buf);
238419370Spst		ldns_rr_list_deep_free(rrset_clone);
238519370Spst		ldns_rr_list_free(validkeys);
238619370Spst		return result;
238719370Spst	}
238819370Spst
238919370Spst	result = LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY;
239019370Spst	for(i = 0; i < ldns_rr_list_rr_count(keys); i++) {
239119370Spst		status = ldns_verify_test_sig_key(rawsig_buf, verify_buf,
239219370Spst			rrsig, ldns_rr_list_rr(keys, i));
239319370Spst		if (status == LDNS_STATUS_OK) {
239419370Spst			/* one of the keys has matched, don't break
239519370Spst			 * here, instead put the 'winning' key in
239619370Spst			 * the validkey list and return the list
239798948Sobrien			 * later */
239819370Spst			if (!ldns_rr_list_push_rr(validkeys,
239919370Spst				ldns_rr_list_rr(keys,i))) {
2400130809Smarcel				/* couldn't push the key?? */
240119370Spst				ldns_buffer_free(rawsig_buf);
240219370Spst				ldns_buffer_free(verify_buf);
240319370Spst				ldns_rr_list_deep_free(rrset_clone);
240419370Spst				ldns_rr_list_free(validkeys);
240519370Spst				return LDNS_STATUS_MEM_ERR;
240619370Spst			}
240719370Spst
240898948Sobrien			result = status;
240919370Spst		}
241019370Spst
241119370Spst		if (result == LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY) {
241298948Sobrien			result = status;
241319370Spst		}
241419370Spst	}
241598948Sobrien
241619370Spst	/* no longer needed */
241719370Spst	ldns_rr_list_deep_free(rrset_clone);
241819370Spst	ldns_buffer_free(rawsig_buf);
241919370Spst	ldns_buffer_free(verify_buf);
242019370Spst
242119370Spst	if (ldns_rr_list_rr_count(validkeys) == 0) {
242219370Spst		/* no keys were added, return last error */
242319370Spst		ldns_rr_list_free(validkeys);
242419370Spst		return result;
242519370Spst	}
2426130809Smarcel
2427130809Smarcel	/* do not check timestamps */
2428130809Smarcel
2429130809Smarcel	ldns_rr_list_cat(good_keys, validkeys);
2430130809Smarcel	ldns_rr_list_free(validkeys);
2431130809Smarcel	return LDNS_STATUS_OK;
2432130809Smarcel}
2433130809Smarcel
2434130809Smarcelldns_status
2435130809Smarcelldns_verify_rrsig_time(
243619370Spst		ldns_rr_list *rrset,
243719370Spst		ldns_rr *rrsig,
2438130809Smarcel		ldns_rr *key,
2439130809Smarcel		time_t check_time)
2440130809Smarcel{
244119370Spst	ldns_buffer *rawsig_buf;
244219370Spst	ldns_buffer *verify_buf;
244319370Spst	ldns_status result;
244419370Spst	ldns_rr_list *rrset_clone;
244519370Spst
244619370Spst	if (!rrset) {
244719370Spst		return LDNS_STATUS_NO_DATA;
244819370Spst	}
244919370Spst	/* clone the rrset so that we can fiddle with it */
245019370Spst	rrset_clone = ldns_rr_list_clone(rrset);
245119370Spst	/* create the buffers which will certainly hold the raw data */
245298948Sobrien	rawsig_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN);
245319370Spst	verify_buf  = ldns_buffer_new(LDNS_MAX_PACKETLEN);
245498948Sobrien
245519370Spst	result = ldns_prepare_for_verify(rawsig_buf, verify_buf,
2456130809Smarcel		rrset_clone, rrsig);
2457130809Smarcel	if(result != LDNS_STATUS_OK) {
245846283Sdfr		ldns_rr_list_deep_free(rrset_clone);
245919370Spst		ldns_buffer_free(rawsig_buf);
246019370Spst		ldns_buffer_free(verify_buf);
2461130809Smarcel		return result;
246219370Spst	}
246319370Spst	result = ldns_verify_test_sig_key(rawsig_buf, verify_buf,
246419370Spst		rrsig, key);
246519370Spst	/* no longer needed */
246619370Spst	ldns_rr_list_deep_free(rrset_clone);
246719370Spst	ldns_buffer_free(rawsig_buf);
246819370Spst	ldns_buffer_free(verify_buf);
246919370Spst
247098948Sobrien	/* check timestamp last, apart from time its OK */
247198948Sobrien	if(result == LDNS_STATUS_OK)
2472130809Smarcel		result = ldns_rrsig_check_timestamps(rrsig, check_time);
2473130809Smarcel
247498948Sobrien	return result;
247598948Sobrien}
247698948Sobrien
247798948Sobrienldns_status
247819370Spstldns_verify_rrsig(ldns_rr_list *rrset, ldns_rr *rrsig, ldns_rr *key)
247919370Spst{
248019370Spst	return ldns_verify_rrsig_time(rrset, rrsig, key, ldns_time(NULL));
248119370Spst}
248219370Spst
248319370Spst
248419370Spstldns_status
248519370Spstldns_verify_rrsig_evp(ldns_buffer *sig,
248619370Spst				  ldns_buffer *rrset,
248719370Spst				  EVP_PKEY *key,
248819370Spst				  const EVP_MD *digest_type)
2489130809Smarcel{
2490130809Smarcel	return ldns_verify_rrsig_evp_raw(
249119370Spst			 (unsigned char*)ldns_buffer_begin(sig),
249219370Spst			 ldns_buffer_position(sig),
249319370Spst			 rrset,
249419370Spst			 key,
249519370Spst			 digest_type);
249619370Spst}
249719370Spst
249898948Sobrienldns_status
249919370Spstldns_verify_rrsig_evp_raw(unsigned char *sig, size_t siglen,
2500130809Smarcel					 ldns_buffer *rrset, EVP_PKEY *key, const EVP_MD *digest_type)
250119370Spst{
250219370Spst	EVP_MD_CTX ctx;
250346283Sdfr	int res;
250419370Spst
250519370Spst	EVP_MD_CTX_init(&ctx);
250698948Sobrien
250719370Spst	EVP_VerifyInit(&ctx, digest_type);
250819370Spst	EVP_VerifyUpdate(&ctx,
250946283Sdfr				  ldns_buffer_begin(rrset),
251019370Spst				  ldns_buffer_position(rrset));
251119370Spst	res = EVP_VerifyFinal(&ctx, sig, (unsigned int) siglen, key);
251219370Spst
2513130809Smarcel	EVP_MD_CTX_cleanup(&ctx);
251419370Spst
2515130809Smarcel	if (res == 1) {
251619370Spst		return LDNS_STATUS_OK;
251719370Spst	} else if (res == 0) {
251819370Spst		return LDNS_STATUS_CRYPTO_BOGUS;
2519130809Smarcel	}
252019370Spst	/* TODO how to communicate internal SSL error?
252119370Spst	   let caller use ssl's get_error() */
252219370Spst	return LDNS_STATUS_SSL_ERR;
252319370Spst}
252498948Sobrien
252519370Spstldns_status
252698948Sobrienldns_verify_rrsig_dsa(ldns_buffer *sig, ldns_buffer *rrset, ldns_buffer *key)
252798948Sobrien{
252898948Sobrien	return ldns_verify_rrsig_dsa_raw(
252919370Spst			 (unsigned char*) ldns_buffer_begin(sig),
253019370Spst			 ldns_buffer_position(sig),
253119370Spst			 rrset,
253219370Spst			 (unsigned char*) ldns_buffer_begin(key),
253319370Spst			 ldns_buffer_position(key));
253419370Spst}
253519370Spst
253698948Sobrienldns_status
253719370Spstldns_verify_rrsig_rsasha1(ldns_buffer *sig, ldns_buffer *rrset, ldns_buffer *key)
253819370Spst{
253919370Spst	return ldns_verify_rrsig_rsasha1_raw(
254019370Spst			 (unsigned char*)ldns_buffer_begin(sig),
254198948Sobrien			 ldns_buffer_position(sig),
254298948Sobrien			 rrset,
2543130809Smarcel			 (unsigned char*) ldns_buffer_begin(key),
254419370Spst			 ldns_buffer_position(key));
254519370Spst}
254619370Spst
254719370Spstldns_status
254819370Spstldns_verify_rrsig_rsamd5(ldns_buffer *sig, ldns_buffer *rrset, ldns_buffer *key)
254919370Spst{
255046283Sdfr	return ldns_verify_rrsig_rsamd5_raw(
255198948Sobrien			 (unsigned char*)ldns_buffer_begin(sig),
255219370Spst			 ldns_buffer_position(sig),
255319370Spst			 rrset,
255419370Spst			 (unsigned char*) ldns_buffer_begin(key),
255519370Spst			 ldns_buffer_position(key));
255619370Spst}
255719370Spst
255819370Spstldns_status
255919370Spstldns_verify_rrsig_dsa_raw(unsigned char* sig, size_t siglen,
256019370Spst					 ldns_buffer* rrset, unsigned char* key, size_t keylen)
256198948Sobrien{
256219370Spst	EVP_PKEY *evp_key;
256346283Sdfr	ldns_status result;
256419370Spst
256519370Spst	evp_key = EVP_PKEY_new();
256646283Sdfr	if (EVP_PKEY_assign_DSA(evp_key, ldns_key_buf2dsa_raw(key, keylen))) {
256719370Spst		result = ldns_verify_rrsig_evp_raw(sig,
256898948Sobrien								siglen,
256919370Spst								rrset,
257098948Sobrien								evp_key,
257198948Sobrien								EVP_dss1());
257246283Sdfr	} else {
257319370Spst		result = LDNS_STATUS_SSL_ERR;
257498948Sobrien	}
257519370Spst	EVP_PKEY_free(evp_key);
257619370Spst	return result;
257719370Spst
257819370Spst}
257919370Spst
258019370Spstldns_status
258119370Spstldns_verify_rrsig_rsasha1_raw(unsigned char* sig, size_t siglen,
258219370Spst						ldns_buffer* rrset, unsigned char* key, size_t keylen)
258319370Spst{
258419370Spst	EVP_PKEY *evp_key;
2585130809Smarcel	ldns_status result;
258619370Spst
2587130809Smarcel	evp_key = EVP_PKEY_new();
258819370Spst	if (EVP_PKEY_assign_RSA(evp_key, ldns_key_buf2rsa_raw(key, keylen))) {
258919370Spst		result = ldns_verify_rrsig_evp_raw(sig,
259098948Sobrien								siglen,
259198948Sobrien								rrset,
259298948Sobrien								evp_key,
259319370Spst								EVP_sha1());
259419370Spst	} else {
259519370Spst		result = LDNS_STATUS_SSL_ERR;
259619370Spst	}
259798948Sobrien	EVP_PKEY_free(evp_key);
259819370Spst
259998948Sobrien	return result;
260098948Sobrien}
260198948Sobrien
260298948Sobrienldns_status
260319370Spstldns_verify_rrsig_rsasha256_raw(unsigned char* sig,
260419370Spst						  size_t siglen,
260519370Spst						  ldns_buffer* rrset,
260619370Spst						  unsigned char* key,
260719370Spst						  size_t keylen)
260819370Spst{
260919370Spst#ifdef USE_SHA2
261019370Spst	EVP_PKEY *evp_key;
261119370Spst	ldns_status result;
261219370Spst
261398948Sobrien	evp_key = EVP_PKEY_new();
261419370Spst	if (EVP_PKEY_assign_RSA(evp_key, ldns_key_buf2rsa_raw(key, keylen))) {
261519370Spst		result = ldns_verify_rrsig_evp_raw(sig,
261619370Spst								siglen,
261719370Spst								rrset,
261819370Spst								evp_key,
261919370Spst								EVP_sha256());
2620130809Smarcel	} else {
262119370Spst		result = LDNS_STATUS_SSL_ERR;
262219370Spst	}
262319370Spst	EVP_PKEY_free(evp_key);
262419370Spst
262519370Spst	return result;
2626130809Smarcel#else
262719370Spst	/* touch these to prevent compiler warnings */
262819370Spst	(void) sig;
262919370Spst	(void) siglen;
263098948Sobrien	(void) rrset;
263146283Sdfr	(void) key;
263219370Spst	(void) keylen;
263319370Spst	return LDNS_STATUS_CRYPTO_UNKNOWN_ALGO;
263498948Sobrien#endif
263519370Spst}
263619370Spst
263719370Spstldns_status
263819370Spstldns_verify_rrsig_rsasha512_raw(unsigned char* sig,
263919370Spst						  size_t siglen,
264019370Spst						  ldns_buffer* rrset,
264119370Spst						  unsigned char* key,
264219370Spst						  size_t keylen)
264319370Spst{
264498948Sobrien#ifdef USE_SHA2
264598948Sobrien	EVP_PKEY *evp_key;
264698948Sobrien	ldns_status result;
264798948Sobrien
264898948Sobrien	evp_key = EVP_PKEY_new();
264919370Spst	if (EVP_PKEY_assign_RSA(evp_key, ldns_key_buf2rsa_raw(key, keylen))) {
265098948Sobrien		result = ldns_verify_rrsig_evp_raw(sig,
265119370Spst								siglen,
265219370Spst								rrset,
265398948Sobrien								evp_key,
265498948Sobrien								EVP_sha512());
265598948Sobrien	} else {
265619370Spst		result = LDNS_STATUS_SSL_ERR;
265719370Spst	}
265819370Spst	EVP_PKEY_free(evp_key);
265919370Spst
266019370Spst	return result;
266119370Spst#else
266219370Spst	/* touch these to prevent compiler warnings */
266319370Spst	(void) sig;
266419370Spst	(void) siglen;
266519370Spst	(void) rrset;
266619370Spst	(void) key;
266719370Spst	(void) keylen;
2668130809Smarcel	return LDNS_STATUS_CRYPTO_UNKNOWN_ALGO;
266919370Spst#endif
267019370Spst}
267119370Spst
267219370Spst
267319370Spstldns_status
267419370Spstldns_verify_rrsig_rsamd5_raw(unsigned char* sig,
267519370Spst					    size_t siglen,
267698948Sobrien					    ldns_buffer* rrset,
267798948Sobrien					    unsigned char* key,
267898948Sobrien					    size_t keylen)
267998948Sobrien{
2680130809Smarcel	EVP_PKEY *evp_key;
2681130809Smarcel	ldns_status result;
2682130809Smarcel
2683130809Smarcel	evp_key = EVP_PKEY_new();
268498948Sobrien	if (EVP_PKEY_assign_RSA(evp_key, ldns_key_buf2rsa_raw(key, keylen))) {
268598948Sobrien		result = ldns_verify_rrsig_evp_raw(sig,
268619370Spst								siglen,
268719370Spst								rrset,
268819370Spst								evp_key,
268919370Spst								EVP_md5());
269019370Spst	} else {
269119370Spst		result = LDNS_STATUS_SSL_ERR;
269219370Spst	}
269319370Spst	EVP_PKEY_free(evp_key);
269419370Spst
269519370Spst	return result;
269619370Spst}
269798948Sobrien
269819370Spst#endif
269919370Spst