val_sigcrypt.c revision 291767
1139969Simp/*
21556Srgrimes * validator/val_sigcrypt.c - validator signature crypto functions.
31556Srgrimes *
41556Srgrimes * Copyright (c) 2007, NLnet Labs. All rights reserved.
51556Srgrimes *
61556Srgrimes * This software is open source.
71556Srgrimes *
81556Srgrimes * Redistribution and use in source and binary forms, with or without
91556Srgrimes * modification, are permitted provided that the following conditions
101556Srgrimes * are met:
111556Srgrimes *
121556Srgrimes * Redistributions of source code must retain the above copyright notice,
131556Srgrimes * this list of conditions and the following disclaimer.
141556Srgrimes *
151556Srgrimes * Redistributions in binary form must reproduce the above copyright notice,
161556Srgrimes * this list of conditions and the following disclaimer in the documentation
171556Srgrimes * and/or other materials provided with the distribution.
181556Srgrimes *
191556Srgrimes * Neither the name of the NLNET LABS nor the names of its contributors may
201556Srgrimes * be used to endorse or promote products derived from this software without
211556Srgrimes * specific prior written permission.
221556Srgrimes *
231556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
241556Srgrimes * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
251556Srgrimes * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
261556Srgrimes * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
271556Srgrimes * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
281556Srgrimes * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
291556Srgrimes * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
301556Srgrimes * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
311556Srgrimes * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
321556Srgrimes * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
331556Srgrimes * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3427958Ssteve */
351556Srgrimes
361556Srgrimes/**
3727967Ssteve * \file
3827967Ssteve *
3990153Smarkm * This file contains helper functions for the validator module.
4027967Ssteve * The functions help with signature verification and checking, the
4127967Ssteve * bridging between RR wireformat data and crypto calls.
4290153Smarkm */
4327967Ssteve#include "config.h"
4499109Sobrien#include "validator/val_sigcrypt.h"
4599109Sobrien#include "validator/val_secalgo.h"
461556Srgrimes#include "validator/validator.h"
47226509Sdes#include "util/data/msgreply.h"
481556Srgrimes#include "util/data/msgparse.h"
491556Srgrimes#include "util/data/dname.h"
50105832Srwatson#include "util/rbtree.h"
511556Srgrimes#include "util/module.h"
521556Srgrimes#include "util/net_help.h"
531556Srgrimes#include "util/regional.h"
541556Srgrimes#include "sldns/keyraw.h"
551556Srgrimes#include "sldns/sbuffer.h"
5690878Simp#include "sldns/parseutil.h"
57114583Smarkm#include "sldns/wire2str.h"
5850050Ssheldonh
5950050Ssheldonh#include <ctype.h>
6090878Simp#if !defined(HAVE_SSL) && !defined(HAVE_NSS)
611556Srgrimes#error "Need crypto library to do digital signature cryptography"
621556Srgrimes#endif
631556Srgrimes
6461289Sache#ifdef HAVE_OPENSSL_ERR_H
6561268Sjoe#include <openssl/err.h>
6661289Sache#endif
6761289Sache
6861268Sjoe#ifdef HAVE_OPENSSL_RAND_H
691556Srgrimes#include <openssl/rand.h>
701556Srgrimes#endif
711556Srgrimes
721556Srgrimes#ifdef HAVE_OPENSSL_CONF_H
7350050Ssheldonh#include <openssl/conf.h>
7450050Ssheldonh#endif
7550050Ssheldonh
7650050Ssheldonh#ifdef HAVE_OPENSSL_ENGINE_H
7750050Ssheldonh#include <openssl/engine.h>
7850051Ssheldonh#endif
7950050Ssheldonh
80114583Smarkm/** return number of rrs in an rrset */
81242840Speterstatic size_t
82114583Smarkmrrset_get_count(struct ub_packed_rrset_key* rrset)
83114583Smarkm{
84114583Smarkm	struct packed_rrset_data* d = (struct packed_rrset_data*)
85114583Smarkm	rrset->entry.data;
86114583Smarkm	if(!d) return 0;
87114583Smarkm	return d->count;
88114583Smarkm}
89114583Smarkm
90114583Smarkm/**
91114583Smarkm * Get RR signature count
92114583Smarkm */
93114583Smarkmstatic size_t
94114583Smarkmrrset_get_sigcount(struct ub_packed_rrset_key* k)
95114583Smarkm{
96103726Swollman	struct packed_rrset_data* d = (struct packed_rrset_data*)k->entry.data;
9790110Simp	return d->rrsig_count;
981556Srgrimes}
99114583Smarkm
10090110Simp/**
1011556Srgrimes * Get signature keytag value
1021556Srgrimes * @param k: rrset (with signatures)
1031556Srgrimes * @param sig_idx: signature index.
1041556Srgrimes * @return keytag or 0 if malformed rrsig.
1051556Srgrimes */
10690150Smarkmstatic uint16_t
107157098Sjhbrrset_get_sig_keytag(struct ub_packed_rrset_key* k, size_t sig_idx)
10890150Smarkm{
10990150Smarkm	uint16_t t;
11090150Smarkm	struct packed_rrset_data* d = (struct packed_rrset_data*)k->entry.data;
11190150Smarkm	log_assert(sig_idx < d->rrsig_count);
112242725Sgrog	if(d->rr_len[d->count + sig_idx] < 2+18)
11390150Smarkm		return 0;
11490150Smarkm	memmove(&t, d->rr_data[d->count + sig_idx]+2+16, 2);
115242725Sgrog	return ntohs(t);
116152469Sru}
117203665Sjh
11890150Smarkm/**
11990150Smarkm * Get signature signing algorithm value
12090150Smarkm * @param k: rrset (with signatures)
12190150Smarkm * @param sig_idx: signature index.
12290150Smarkm * @return algo or 0 if malformed rrsig.
12390150Smarkm */
12490150Smarkmstatic int
12590150Smarkmrrset_get_sig_algo(struct ub_packed_rrset_key* k, size_t sig_idx)
126242725Sgrog{
127242725Sgrog	struct packed_rrset_data* d = (struct packed_rrset_data*)k->entry.data;
12890150Smarkm	log_assert(sig_idx < d->rrsig_count);
12990150Smarkm	if(d->rr_len[d->count + sig_idx] < 2+3)
130242725Sgrog		return 0;
13196892Stjr	return (int)d->rr_data[d->count + sig_idx][2+2];
132177907Sgrog}
13390150Smarkm
134114583Smarkm/** get rdata pointer and size */
135242725Sgrogstatic void
136242807Sgrogrrset_get_rdata(struct ub_packed_rrset_key* k, size_t idx, uint8_t** rdata,
13790150Smarkm	size_t* len)
13890150Smarkm{
13990150Smarkm	struct packed_rrset_data* d = (struct packed_rrset_data*)k->entry.data;
140242725Sgrog	log_assert(d && idx < (d->count + d->rrsig_count));
14161268Sjoe	*rdata = d->rr_data[idx];
14290150Smarkm	*len = d->rr_len[idx];
14361271Sjoe}
14461271Sjoe
14561271Sjoeuint16_t
14661271Sjoednskey_get_flags(struct ub_packed_rrset_key* k, size_t idx)
14788583Sjoe{
14888583Sjoe	uint8_t* rdata;
14961268Sjoe	size_t len;
1501556Srgrimes	uint16_t f;
15190150Smarkm	rrset_get_rdata(k, idx, &rdata, &len);
15217852Sadam	if(len < 2+2)
1531556Srgrimes		return 0;
15490110Simp	memmove(&f, rdata+2, 2);
1551556Srgrimes	f = ntohs(f);
15688602Sjoe	return f;
1571556Srgrimes}
1581556Srgrimes
1591556Srgrimes/**
16061271Sjoe * Get DNSKEY protocol value from rdata
16188602Sjoe * @param k: DNSKEY rrset.
16288602Sjoe * @param idx: which key.
16361271Sjoe * @return protocol octet value
16461271Sjoe */
16561271Sjoestatic int
16688602Sjoednskey_get_protocol(struct ub_packed_rrset_key* k, size_t idx)
16711808Sache{
1681556Srgrimes	uint8_t* rdata;
1691556Srgrimes	size_t len;
17097803Stjr	rrset_get_rdata(k, idx, &rdata, &len);
17197803Stjr	if(len < 2+4)
17297803Stjr		return 0;
17397803Stjr	return (int)rdata[2+2];
17497803Stjr}
1751556Srgrimes
17690150Smarkmint
1775158Sjoergdnskey_get_algo(struct ub_packed_rrset_key* k, size_t idx)
1781556Srgrimes{
1795158Sjoerg	uint8_t* rdata;
18090150Smarkm	size_t len;
18190150Smarkm	rrset_get_rdata(k, idx, &rdata, &len);
1825158Sjoerg	if(len < 2+4)
1835158Sjoerg		return 0;
1841556Srgrimes	return (int)rdata[2+3];
1851556Srgrimes}
186242725Sgrog
187242725Sgrog/** get public key rdata field from a dnskey RR and do some checks */
188242807Sgrogstatic void
189242725Sgrogdnskey_get_pubkey(struct ub_packed_rrset_key* k, size_t idx,
1901556Srgrimes	unsigned char** pk, unsigned int* pklen)
1911556Srgrimes{
19296892Stjr	uint8_t* rdata;
19396892Stjr	size_t len;
1941556Srgrimes	rrset_get_rdata(k, idx, &rdata, &len);
1951556Srgrimes	if(len < 2+5) {
1961556Srgrimes		*pk = NULL;
19790150Smarkm		*pklen = 0;
19896892Stjr		return;
1991556Srgrimes	}
2001556Srgrimes	*pk = (unsigned char*)rdata+2+4;
20196892Stjr	*pklen = (unsigned)len-2-4;
2021556Srgrimes}
2031556Srgrimes
2041556Srgrimesint
20590150Smarkmds_get_key_algo(struct ub_packed_rrset_key* k, size_t idx)
20696892Stjr{
2071556Srgrimes	uint8_t* rdata;
20896892Stjr	size_t len;
20996892Stjr	rrset_get_rdata(k, idx, &rdata, &len);
21096892Stjr	if(len < 2+3)
21196892Stjr		return 0;
21296892Stjr	return (int)rdata[2+2];
213157098Sjhb}
2141556Srgrimes
2151556Srgrimesint
2161556Srgrimesds_get_digest_algo(struct ub_packed_rrset_key* k, size_t idx)
217157098Sjhb{
2181556Srgrimes	uint8_t* rdata;
2191556Srgrimes	size_t len;
2201556Srgrimes	rrset_get_rdata(k, idx, &rdata, &len);
2211556Srgrimes	if(len < 2+4)
222157098Sjhb		return 0;
2231556Srgrimes	return (int)rdata[2+3];
224157098Sjhb}
225157098Sjhb
226157098Sjhbuint16_t
227157098Sjhbds_get_keytag(struct ub_packed_rrset_key* ds_rrset, size_t ds_idx)
228157098Sjhb{
229242722Sgrog	uint16_t t;
230242722Sgrog	uint8_t* rdata;
231242722Sgrog	size_t len;
232242722Sgrog	rrset_get_rdata(ds_rrset, ds_idx, &rdata, &len);
233242722Sgrog	if(len < 2+2)
234242722Sgrog		return 0;
235242722Sgrog	memmove(&t, rdata+2, 2);
236242722Sgrog	return ntohs(t);
237242722Sgrog}
238242722Sgrog
239242722Sgrog/**
240242722Sgrog * Return pointer to the digest in a DS RR.
241242722Sgrog * @param k: DS rrset.
242242722Sgrog * @param idx: which DS.
243242722Sgrog * @param digest: digest data is returned.
244242840Speter *	on error, this is NULL.
245242725Sgrog * @param len: length of digest is returned.
246242725Sgrog *	on error, the length is 0.
247242725Sgrog */
248242722Sgrogstatic void
249242722Sgrogds_get_sigdata(struct ub_packed_rrset_key* k, size_t idx, uint8_t** digest,
250242722Sgrog        size_t* len)
251242722Sgrog{
252242722Sgrog	uint8_t* rdata;
253242807Sgrog	size_t rdlen;
254242807Sgrog	rrset_get_rdata(k, idx, &rdata, &rdlen);
255242807Sgrog	if(rdlen < 2+5) {
256242807Sgrog		*digest = NULL;
2571556Srgrimes		*len = 0;
25896892Stjr		return;
2591556Srgrimes	}
260242722Sgrog	*digest = rdata + 2 + 4;
261242722Sgrog	*len = rdlen - 2 - 4;
262242722Sgrog}
26335426Sdes
26488602Sjoe/**
265203665Sjh * Return size of DS digest according to its hash algorithm.
26635426Sdes * @param k: DS rrset.
267242722Sgrog * @param idx: which DS.
268242722Sgrog * @return size in bytes of digest, or 0 if not supported.
26961178Sjoe */
2701556Srgrimesstatic size_t
2711556Srgrimesds_digest_size_algo(struct ub_packed_rrset_key* k, size_t idx)
2721556Srgrimes{
273203665Sjh	return ds_digest_size_supported(ds_get_digest_algo(k, idx));
2741556Srgrimes}
27535426Sdes
27688602Sjoe/**
27735426Sdes * Create a DS digest for a DNSKEY entry.
27835426Sdes *
279203665Sjh * @param env: module environment. Uses scratch space.
28035426Sdes * @param dnskey_rrset: DNSKEY rrset.
2811556Srgrimes * @param dnskey_idx: index of RR in rrset.
2821556Srgrimes * @param ds_rrset: DS rrset
2831556Srgrimes * @param ds_idx: index of RR in DS rrset.
284242722Sgrog * @param digest: digest is returned in here (must be correctly sized).
285242722Sgrog * @return false on error.
2861556Srgrimes */
287242722Sgrogstatic int
288242722Sgrogds_create_dnskey_digest(struct module_env* env,
289152256Smux	struct ub_packed_rrset_key* dnskey_rrset, size_t dnskey_idx,
290242722Sgrog	struct ub_packed_rrset_key* ds_rrset, size_t ds_idx,
291242722Sgrog	uint8_t* digest)
292242722Sgrog{
293242722Sgrog	sldns_buffer* b = env->scratch_buffer;
294242722Sgrog	uint8_t* dnskey_rdata;
295242722Sgrog	size_t dnskey_len;
296242722Sgrog	rrset_get_rdata(dnskey_rrset, dnskey_idx, &dnskey_rdata, &dnskey_len);
297242722Sgrog
2981556Srgrimes	/* create digest source material in buffer
2991556Srgrimes	 * digest = digest_algorithm( DNSKEY owner name | DNSKEY RDATA);
3001556Srgrimes	 *	DNSKEY RDATA = Flags | Protocol | Algorithm | Public Key. */
3011556Srgrimes	sldns_buffer_clear(b);
3021556Srgrimes	sldns_buffer_write(b, dnskey_rrset->rk.dname,
3031556Srgrimes		dnskey_rrset->rk.dname_len);
3041556Srgrimes	query_dname_tolower(sldns_buffer_begin(b));
3051556Srgrimes	sldns_buffer_write(b, dnskey_rdata+2, dnskey_len-2); /* skip rdatalen*/
30688602Sjoe	sldns_buffer_flip(b);
3071556Srgrimes
30888591Sjoe	return secalgo_ds_digest(ds_get_digest_algo(ds_rrset, ds_idx),
30988591Sjoe		(unsigned char*)sldns_buffer_begin(b), sldns_buffer_limit(b),
31088591Sjoe		(unsigned char*)digest);
3111556Srgrimes}
3121556Srgrimes
3131556Srgrimesint ds_digest_match_dnskey(struct module_env* env,
3142889Spst	struct ub_packed_rrset_key* dnskey_rrset, size_t dnskey_idx,
315123089Sobrien	struct ub_packed_rrset_key* ds_rrset, size_t ds_idx)
3162889Spst{
3172889Spst	uint8_t* ds;	/* DS digest */
31896892Stjr	size_t dslen;
31996892Stjr	uint8_t* digest; /* generated digest */
32096892Stjr	size_t digestlen = ds_digest_size_algo(ds_rrset, ds_idx);
32196892Stjr
32296892Stjr	if(digestlen == 0) {
32349373Ssheldonh		verbose(VERB_QUERY, "DS fail: not supported, or DS RR "
32449373Ssheldonh			"format error");
32549373Ssheldonh		return 0; /* not supported, or DS RR format error */
3261556Srgrimes	}
3271556Srgrimes	/* check digest length in DS with length from hash function */
3281556Srgrimes	ds_get_sigdata(ds_rrset, ds_idx, &ds, &dslen);
32996892Stjr	if(!ds || dslen != digestlen) {
33096892Stjr		verbose(VERB_QUERY, "DS fail: DS RR algo and digest do not "
33196892Stjr			"match each other");
33296892Stjr		return 0; /* DS algorithm and digest do not match */
3331556Srgrimes	}
3341556Srgrimes
33535373Sdes	digest = regional_alloc(env->scratch, digestlen);
33688602Sjoe	if(!digest) {
3371556Srgrimes		verbose(VERB_QUERY, "DS fail: out of memory");
3381556Srgrimes		return 0; /* mem error */
3391556Srgrimes	}
3401556Srgrimes	if(!ds_create_dnskey_digest(env, dnskey_rrset, dnskey_idx, ds_rrset,
3411556Srgrimes		ds_idx, digest)) {
3421556Srgrimes		verbose(VERB_QUERY, "DS fail: could not calc key digest");
3431556Srgrimes		return 0; /* digest algo failed */
34488603Sjoe	}
34588603Sjoe	if(memcmp(digest, ds, dslen) != 0) {
34688603Sjoe		verbose(VERB_QUERY, "DS fail: digest is different");
34788603Sjoe		return 0; /* digest different */
34888603Sjoe	}
349242725Sgrog	return 1;
350242725Sgrog}
351242725Sgrog
3521556Srgrimesint
3531556Srgrimesds_digest_algo_is_supported(struct ub_packed_rrset_key* ds_rrset,
3541556Srgrimes	size_t ds_idx)
3551556Srgrimes{
3561556Srgrimes	return (ds_digest_size_algo(ds_rrset, ds_idx) != 0);
3571556Srgrimes}
3581556Srgrimes
3591556Srgrimesint
360152469Sruds_key_algo_is_supported(struct ub_packed_rrset_key* ds_rrset,
361152469Sru	size_t ds_idx)
362152256Smux{
363152256Smux	return dnskey_algo_id_is_supported(ds_get_key_algo(ds_rrset, ds_idx));
36464568Sjoe}
36564568Sjoe
36664568Sjoeuint16_t
36764604Sjoednskey_calc_keytag(struct ub_packed_rrset_key* dnskey_rrset, size_t dnskey_idx)
36864568Sjoe{
36964568Sjoe	uint8_t* data;
37064568Sjoe	size_t len;
37188583Sjoe	rrset_get_rdata(dnskey_rrset, dnskey_idx, &data, &len);
37288583Sjoe	/* do not pass rdatalen to ldns */
37364568Sjoe	return sldns_calc_keytag_raw(data+2, len-2);
37464568Sjoe}
37564568Sjoe
37664568Sjoeint dnskey_algo_is_supported(struct ub_packed_rrset_key* dnskey_rrset,
37764568Sjoe        size_t dnskey_idx)
37864568Sjoe{
37964568Sjoe	return dnskey_algo_id_is_supported(dnskey_get_algo(dnskey_rrset,
38064568Sjoe		dnskey_idx));
38164568Sjoe}
38264568Sjoe
38364604Sjoevoid algo_needs_init_dnskey_add(struct algo_needs* n,
384106479Stjr        struct ub_packed_rrset_key* dnskey, uint8_t* sigalg)
38564604Sjoe{
38664568Sjoe	uint8_t algo;
38764604Sjoe	size_t i, total = n->num;
38861289Sache	size_t num = rrset_get_count(dnskey);
38961337Sache
39061337Sache	for(i=0; i<num; i++) {
39161337Sache		algo = (uint8_t)dnskey_get_algo(dnskey, i);
39261337Sache		if(!dnskey_algo_id_is_supported((int)algo))
39361337Sache			continue;
39461337Sache		if(n->needs[algo] == 0) {
39588602Sjoe			n->needs[algo] = 1;
39688602Sjoe			sigalg[total] = algo;
39761178Sjoe			total++;
39861289Sache		}
39961268Sjoe	}
40061178Sjoe	sigalg[total] = 0;
4011556Srgrimes	n->num = total;
402146924Sdd}
40361178Sjoe
40461178Sjoevoid algo_needs_init_list(struct algo_needs* n, uint8_t* sigalg)
4051556Srgrimes{
406146924Sdd	uint8_t algo;
407146924Sdd	size_t total = 0;
40861268Sjoe
40961268Sjoe	memset(n->needs, 0, sizeof(uint8_t)*ALGO_NEEDS_MAX);
41061268Sjoe	while( (algo=*sigalg++) != 0) {
41188602Sjoe		log_assert(dnskey_algo_id_is_supported((int)algo));
4121556Srgrimes		log_assert(n->needs[algo] == 0);
4131556Srgrimes		n->needs[algo] = 1;
4141556Srgrimes		total++;
415203665Sjh	}
4161556Srgrimes	n->num = total;
4171556Srgrimes}
418203665Sjh
4191556Srgrimesvoid algo_needs_init_ds(struct algo_needs* n, struct ub_packed_rrset_key* ds,
4201556Srgrimes	int fav_ds_algo, uint8_t* sigalg)
42120417Ssteve{
42220417Ssteve	uint8_t algo;
42320417Ssteve	size_t i, total = 0;
42420417Ssteve	size_t num = rrset_get_count(ds);
42520417Ssteve
42620417Ssteve	memset(n->needs, 0, sizeof(uint8_t)*ALGO_NEEDS_MAX);
42720417Ssteve	for(i=0; i<num; i++) {
42820417Ssteve		if(ds_get_digest_algo(ds, i) != fav_ds_algo)
429226546Sdes			continue;
430226546Sdes		algo = (uint8_t)ds_get_key_algo(ds, i);
4312889Spst		if(!dnskey_algo_id_is_supported((int)algo))
4327282Sphk			continue;
4337282Sphk		log_assert(algo != 0); /* we do not support 0 and is EOS */
4347282Sphk		if(n->needs[algo] == 0) {
4357282Sphk			n->needs[algo] = 1;
4367282Sphk			sigalg[total] = algo;
4371556Srgrimes			total++;
4381556Srgrimes		}
4391556Srgrimes	}
440146924Sdd	sigalg[total] = 0;
4411556Srgrimes	n->num = total;
442157100Sjhb}
443157100Sjhb
4441556Srgrimesint algo_needs_set_secure(struct algo_needs* n, uint8_t algo)
4451556Srgrimes{
446157098Sjhb	if(n->needs[algo]) {
447157098Sjhb		n->needs[algo] = 0;
4481556Srgrimes		n->num --;
4491556Srgrimes		if(n->num == 0) /* done! */
45088602Sjoe			return 1;
4511556Srgrimes	}
4521556Srgrimes	return 0;
453146924Sdd}
4541556Srgrimes
455157100Sjhbvoid algo_needs_set_bogus(struct algo_needs* n, uint8_t algo)
456157100Sjhb{
4571556Srgrimes	if(n->needs[algo]) n->needs[algo] = 2; /* need it, but bogus */
4581556Srgrimes}
459157098Sjhb
460157098Sjhbsize_t algo_needs_num_missing(struct algo_needs* n)
4611556Srgrimes{
4621556Srgrimes	return n->num;
46388602Sjoe}
4641556Srgrimes
4651556Srgrimesint algo_needs_missing(struct algo_needs* n)
4661556Srgrimes{
4671556Srgrimes	int i;
4681556Srgrimes	/* first check if a needed algo was bogus - report that */
4691556Srgrimes	for(i=0; i<ALGO_NEEDS_MAX; i++)
4701556Srgrimes		if(n->needs[i] == 2)
4711556Srgrimes			return 0;
47296892Stjr	/* now check which algo is missing */
47396892Stjr	for(i=0; i<ALGO_NEEDS_MAX; i++)
4741556Srgrimes		if(n->needs[i] == 1)
4751556Srgrimes			return i;
4761556Srgrimes	return 0;
4771556Srgrimes}
4781556Srgrimes
4791556Srgrimesenum sec_status
4801556Srgrimesdnskeyset_verify_rrset(struct module_env* env, struct val_env* ve,
48117852Sadam	struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey,
4821556Srgrimes	uint8_t* sigalg, char** reason)
4831556Srgrimes{
48488602Sjoe	enum sec_status sec;
4851556Srgrimes	size_t i, num;
4861556Srgrimes	rbtree_t* sortree = NULL;
4871556Srgrimes	/* make sure that for all DNSKEY algorithms there are valid sigs */
4881556Srgrimes	struct algo_needs needs;
4891556Srgrimes	int alg;
4901556Srgrimes
4911556Srgrimes	num = rrset_get_sigcount(rrset);
4921556Srgrimes	if(num == 0) {
49390110Simp		verbose(VERB_QUERY, "rrset failed to verify due to a lack of "
4941556Srgrimes			"signatures");
4951556Srgrimes		*reason = "no signatures";
4961556Srgrimes		return sec_status_bogus;
4971556Srgrimes	}
4981556Srgrimes
4991556Srgrimes	if(sigalg) {
5001556Srgrimes		algo_needs_init_list(&needs, sigalg);
50199744Sdillon		if(algo_needs_num_missing(&needs) == 0) {
5021556Srgrimes			verbose(VERB_QUERY, "zone has no known algorithms");
503130237Sdas			*reason = "zone has no known algorithms";
504130237Sdas			return sec_status_insecure;
505130237Sdas		}
506130237Sdas	}
507130237Sdas	for(i=0; i<num; i++) {
508130237Sdas		sec = dnskeyset_verify_rrset_sig(env, ve, *env->now, rrset,
509130237Sdas			dnskey, i, &sortree, reason);
5101556Srgrimes		/* see which algorithm has been fixed up */
5111556Srgrimes		if(sec == sec_status_secure) {
5121556Srgrimes			if(!sigalg)
5131556Srgrimes				return sec; /* done! */
5141556Srgrimes			else if(algo_needs_set_secure(&needs,
5151556Srgrimes				(uint8_t)rrset_get_sig_algo(rrset, i)))
5161556Srgrimes				return sec; /* done! */
517108057Srwatson		} else if(sigalg && sec == sec_status_bogus) {
518108057Srwatson			algo_needs_set_bogus(&needs,
5191556Srgrimes				(uint8_t)rrset_get_sig_algo(rrset, i));
5201556Srgrimes		}
5211556Srgrimes	}
5221556Srgrimes	if(sigalg && (alg=algo_needs_missing(&needs)) != 0) {
5231556Srgrimes		verbose(VERB_ALGO, "rrset failed to verify: "
5241556Srgrimes			"no valid signatures for %d algorithms",
5251556Srgrimes			(int)algo_needs_num_missing(&needs));
5261556Srgrimes		algo_needs_reason(env, alg, reason, "no signatures");
527202944Sjh	} else {
52817852Sadam		verbose(VERB_ALGO, "rrset failed to verify: "
5291556Srgrimes			"no valid signatures");
5301556Srgrimes	}
5311556Srgrimes	return sec_status_bogus;
532152469Sru}
5331556Srgrimes
5341556Srgrimesvoid algo_needs_reason(struct module_env* env, int alg, char** reason, char* s)
5351556Srgrimes{
5361556Srgrimes	char buf[256];
537242840Speter	sldns_lookup_table *t = sldns_lookup_by_id(sldns_algorithms, alg);
5381556Srgrimes	if(t&&t->name)
5391556Srgrimes		snprintf(buf, sizeof(buf), "%s with algorithm %s", s, t->name);
540105390Stjr	else	snprintf(buf, sizeof(buf), "%s with algorithm ALG%u", s,
541105390Stjr			(unsigned)alg);
542114583Smarkm	*reason = regional_strdup(env->scratch, buf);
543105390Stjr	if(!*reason)
544105390Stjr		*reason = s;
545114583Smarkm}
546105390Stjr
5471556Srgrimesenum sec_status
5481556Srgrimesdnskey_verify_rrset(struct module_env* env, struct val_env* ve,
5491556Srgrimes        struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey,
550105832Srwatson	size_t dnskey_idx, char** reason)
5511556Srgrimes{
5521556Srgrimes	enum sec_status sec;
5531556Srgrimes	size_t i, num, numchecked = 0;
5541556Srgrimes	rbtree_t* sortree = NULL;
55596681Sbillf	int buf_canon = 0;
55696681Sbillf	uint16_t tag = dnskey_calc_keytag(dnskey, dnskey_idx);
5571556Srgrimes	int algo = dnskey_get_algo(dnskey, dnskey_idx);
5581556Srgrimes
5591556Srgrimes	num = rrset_get_sigcount(rrset);
5601556Srgrimes	if(num == 0) {
5611556Srgrimes		verbose(VERB_QUERY, "rrset failed to verify due to a lack of "
5621556Srgrimes			"signatures");
5631556Srgrimes		*reason = "no signatures";
5641556Srgrimes		return sec_status_bogus;
5651556Srgrimes	}
5661556Srgrimes	for(i=0; i<num; i++) {
5671556Srgrimes		/* see if sig matches keytag and algo */
568114583Smarkm		if(algo != rrset_get_sig_algo(rrset, i) ||
5691556Srgrimes			tag != rrset_get_sig_keytag(rrset, i))
5701556Srgrimes			continue;
5711556Srgrimes		buf_canon = 0;
5721556Srgrimes		sec = dnskey_verify_rrset_sig(env->scratch,
5731556Srgrimes			env->scratch_buffer, ve, *env->now, rrset,
57490150Smarkm			dnskey, dnskey_idx, i, &sortree, &buf_canon, reason);
575114583Smarkm		if(sec == sec_status_secure)
576241014Smdf			return sec;
577241014Smdf		numchecked ++;
578105832Srwatson	}
579225847Sed	verbose(VERB_ALGO, "rrset failed to verify: all signatures are bogus");
580202945Sjh	if(!numchecked) *reason = "signature missing";
58190150Smarkm	return sec_status_bogus;
58290150Smarkm}
58390150Smarkm
58437932Shoekenum sec_status
5851556Srgrimesdnskeyset_verify_rrset_sig(struct module_env* env, struct val_env* ve,
58696649Sjmallett	time_t now, struct ub_packed_rrset_key* rrset,
587105832Srwatson	struct ub_packed_rrset_key* dnskey, size_t sig_idx,
58850050Ssheldonh	struct rbtree_t** sortree, char** reason)
58950050Ssheldonh{
5901556Srgrimes	/* find matching keys and check them */
5911556Srgrimes	enum sec_status sec = sec_status_bogus;
5921556Srgrimes	uint16_t tag = rrset_get_sig_keytag(rrset, sig_idx);
59337932Shoek	int algo = rrset_get_sig_algo(rrset, sig_idx);
59437932Shoek	size_t i, num = rrset_get_count(dnskey);
59537932Shoek	size_t numchecked = 0;
596241014Smdf	int buf_canon = 0;
597241014Smdf	verbose(VERB_ALGO, "verify sig %d %d", (int)tag, algo);
598241014Smdf	if(!dnskey_algo_id_is_supported(algo)) {
59937932Shoek		verbose(VERB_QUERY, "verify sig: unknown algorithm");
60037932Shoek		return sec_status_insecure;
60137932Shoek	}
60237932Shoek
60337932Shoek	for(i=0; i<num; i++) {
604114583Smarkm		/* see if key matches keytag and algo */
60537932Shoek		if(algo != dnskey_get_algo(dnskey, i) ||
60699744Sdillon			tag != dnskey_calc_keytag(dnskey, i))
607114583Smarkm			continue;
60837932Shoek		numchecked ++;
60937932Shoek
61037932Shoek		/* see if key verifies */
61137932Shoek		sec = dnskey_verify_rrset_sig(env->scratch,
61237932Shoek			env->scratch_buffer, ve, now, rrset, dnskey, i,
61337932Shoek			sig_idx, sortree, &buf_canon, reason);
61437932Shoek		if(sec == sec_status_secure)
61537932Shoek			return sec;
61637932Shoek	}
61737932Shoek	if(numchecked == 0) {
61837932Shoek		*reason = "signatures from unknown keys";
61937932Shoek		verbose(VERB_QUERY, "verify: could not find appropriate key");
62037932Shoek		return sec_status_bogus;
62137932Shoek	}
62288602Sjoe	return sec_status_bogus;
62388602Sjoe}
62437932Shoek
62537932Shoek/**
626241014Smdf * RR entries in a canonical sorted tree of RRs
62737932Shoek */
628105832Srwatsonstruct canon_rr {
62937932Shoek	/** rbtree node, key is this structure */
63037932Shoek	rbnode_t node;
63188602Sjoe	/** rrset the RR is in */
63288602Sjoe	struct ub_packed_rrset_key* rrset;
633102410Scharnier	/** which RR in the rrset */
63488602Sjoe	size_t rr_idx;
63588602Sjoe};
636102410Scharnier
63788602Sjoe/**
63888602Sjoe * Compare two RR for canonical order, in a field-style sweep.
639102410Scharnier * @param d: rrset data
64088602Sjoe * @param desc: ldns wireformat descriptor.
64188602Sjoe * @param i: first RR to compare
642102410Scharnier * @param j: first RR to compare
64388602Sjoe * @return comparison code.
64488602Sjoe */
645102410Scharnierstatic int
64688602Sjoecanonical_compare_byfield(struct packed_rrset_data* d,
64788602Sjoe	const sldns_rr_descriptor* desc, size_t i, size_t j)
648102410Scharnier{
64988602Sjoe	/* sweep across rdata, keep track of some state:
65088602Sjoe	 * 	which rr field, and bytes left in field.
651102410Scharnier	 * 	current position in rdata, length left.
65288602Sjoe	 * 	are we in a dname, length left in a label.
65388602Sjoe	 */
654102410Scharnier	int wfi = -1;	/* current wireformat rdata field (rdf) */
65588602Sjoe	int wfj = -1;
656105832Srwatson	uint8_t* di = d->rr_data[i]+2; /* ptr to current rdata byte */
657102410Scharnier	uint8_t* dj = d->rr_data[j]+2;
65861338Sache	size_t ilen = d->rr_len[i]-2; /* length left in rdata */
65988602Sjoe	size_t jlen = d->rr_len[j]-2;
66061337Sache	int dname_i = 0;  /* true if these bytes are part of a name */
66188602Sjoe	int dname_j = 0;
662102410Scharnier	size_t lablen_i = 0; /* 0 for label length byte,for first byte of rdf*/
66390150Smarkm	size_t lablen_j = 0; /* otherwise remaining length of rdf or label */
66496681Sbillf	int dname_num_i = (int)desc->_dname_count; /* decreased at root label */
66537932Shoek	int dname_num_j = (int)desc->_dname_count;
666114583Smarkm
667114583Smarkm	/* loop while there are rdata bytes available for both rrs,
668114583Smarkm	 * and still some lowercasing needs to be done; either the dnames
669114583Smarkm	 * have not been reached yet, or they are currently being processed */
670130029Sle	while(ilen > 0 && jlen > 0 && (dname_num_i > 0 || dname_num_j > 0)) {
67190150Smarkm		/* compare these two bytes */
672225847Sed		/* lowercase if in a dname and not a label length byte */
673225847Sed		if( ((dname_i && lablen_i)?(uint8_t)tolower((int)*di):*di)
6747165Sjoerg		 != ((dname_j && lablen_j)?(uint8_t)tolower((int)*dj):*dj)
6751556Srgrimes		 ) {
6761556Srgrimes		  if(((dname_i && lablen_i)?(uint8_t)tolower((int)*di):*di)
6771556Srgrimes		  < ((dname_j && lablen_j)?(uint8_t)tolower((int)*dj):*dj))
6781556Srgrimes		 	return -1;
6791556Srgrimes		    return 1;
68017852Sadam		}
6811556Srgrimes		ilen--;
6821556Srgrimes		jlen--;
6831556Srgrimes		/* bytes are equal */
6841556Srgrimes
6851556Srgrimes		/* advance field i */
6861556Srgrimes		/* lablen 0 means that this byte is the first byte of the
6871556Srgrimes		 * next rdata field; inspect this rdata field and setup
6881556Srgrimes		 * to process the rest of this rdata field.
6891556Srgrimes		 * The reason to first read the byte, then setup the rdf,
6901556Srgrimes		 * is that we are then sure the byte is available and short
6911556Srgrimes		 * rdata is handled gracefully (even if it is a formerr). */
6921556Srgrimes		if(lablen_i == 0) {
6931556Srgrimes			if(dname_i) {
6941556Srgrimes				/* scan this dname label */
695152469Sru				/* capture length to lowercase */
6961556Srgrimes				lablen_i = (size_t)*di;
6971556Srgrimes				if(lablen_i == 0) {
6981556Srgrimes					/* end root label */
6991556Srgrimes					dname_i = 0;
7001556Srgrimes					dname_num_i--;
7011556Srgrimes					/* if dname num is 0, then the
70235417Sdes					 * remainder is binary only */
70388602Sjoe					if(dname_num_i == 0)
70488602Sjoe						lablen_i = ilen;
70588602Sjoe				}
70688602Sjoe			} else {
70737932Shoek				/* scan this rdata field */
7081556Srgrimes				wfi++;
7091556Srgrimes				if(desc->_wireformat[wfi]
7101556Srgrimes					== LDNS_RDF_TYPE_DNAME) {
7111556Srgrimes					dname_i = 1;
7121556Srgrimes					lablen_i = (size_t)*di;
7131556Srgrimes					if(lablen_i == 0) {
7141556Srgrimes						dname_i = 0;
7151556Srgrimes						dname_num_i--;
7161556Srgrimes						if(dname_num_i == 0)
7171556Srgrimes							lablen_i = ilen;
7181556Srgrimes					}
7191556Srgrimes				} else if(desc->_wireformat[wfi]
7201556Srgrimes					== LDNS_RDF_TYPE_STR)
72149373Ssheldonh					lablen_i = (size_t)*di;
72249373Ssheldonh				else	lablen_i = get_rdf_size(
72349373Ssheldonh					desc->_wireformat[wfi]) - 1;
72449373Ssheldonh			}
72549373Ssheldonh		} else	lablen_i--;
72649373Ssheldonh
72749373Ssheldonh		/* advance field j; same as for i */
72849373Ssheldonh		if(lablen_j == 0) {
72949373Ssheldonh			if(dname_j) {
73049373Ssheldonh				lablen_j = (size_t)*dj;
73149373Ssheldonh				if(lablen_j == 0) {
7321556Srgrimes					dname_j = 0;
7331556Srgrimes					dname_num_j--;
7341556Srgrimes					if(dname_num_j == 0)
7351556Srgrimes						lablen_j = jlen;
7361556Srgrimes				}
73761749Sjoe			} else {
73861749Sjoe				wfj++;
73961749Sjoe				if(desc->_wireformat[wfj]
74061749Sjoe					== LDNS_RDF_TYPE_DNAME) {
74161749Sjoe					dname_j = 1;
74261749Sjoe					lablen_j = (size_t)*dj;
74399744Sdillon					if(lablen_j == 0) {
74490150Smarkm						dname_j = 0;
74590150Smarkm						dname_num_j--;
7461556Srgrimes						if(dname_num_j == 0)
7471556Srgrimes							lablen_j = jlen;
7481556Srgrimes					}
749105832Srwatson				} else if(desc->_wireformat[wfj]
750105832Srwatson					== LDNS_RDF_TYPE_STR)
751105836Srwatson					lablen_j = (size_t)*dj;
752105832Srwatson				else	lablen_j = get_rdf_size(
753105832Srwatson					desc->_wireformat[wfj]) - 1;
754105832Srwatson			}
755105832Srwatson		} else	lablen_j--;
756105832Srwatson		di++;
757108057Srwatson		dj++;
758108057Srwatson	}
759108057Srwatson	/* end of the loop; because we advanced byte by byte; now we have
760105832Srwatson	 * that the rdata has ended, or that there is a binary remainder */
761105832Srwatson	/* shortest first */
762105832Srwatson	if(ilen == 0 && jlen == 0)
763105836Srwatson		return 0;
764105836Srwatson	if(ilen == 0)
765105836Srwatson		return -1;
766105836Srwatson	if(jlen == 0)
767105836Srwatson		return 1;
768108057Srwatson	/* binary remainder, capture comparison in wfi variable */
769108057Srwatson	if((wfi = memcmp(di, dj, (ilen<jlen)?ilen:jlen)) != 0)
770105836Srwatson		return wfi;
771105832Srwatson	if(ilen < jlen)
772105836Srwatson		return -1;
773105836Srwatson	if(jlen < ilen)
774105832Srwatson		return 1;
775105836Srwatson	return 0;
776105836Srwatson}
777105832Srwatson
778108057Srwatson/**
779108057Srwatson * Compare two RRs in the same RRset and determine their relative
780108057Srwatson * canonical order.
781105832Srwatson * @param rrset: the rrset in which to perform compares.
782105832Srwatson * @param i: first RR to compare
783105832Srwatson * @param j: first RR to compare
784105832Srwatson * @return 0 if RR i== RR j, -1 if <, +1 if >.
785105832Srwatson */
786105832Srwatsonstatic int
787105832Srwatsoncanonical_compare(struct ub_packed_rrset_key* rrset, size_t i, size_t j)
788108057Srwatson{
789108057Srwatson	struct packed_rrset_data* d = (struct packed_rrset_data*)
790108057Srwatson		rrset->entry.data;
791105832Srwatson	const sldns_rr_descriptor* desc;
792105832Srwatson	uint16_t type = ntohs(rrset->rk.type);
793105832Srwatson	size_t minlen;
794105832Srwatson	int c;
795105832Srwatson
796105832Srwatson	if(i==j)
797114047Srwatson		return 0;
798105832Srwatson
799105832Srwatson	switch(type) {
800105832Srwatson		/* These RR types have only a name as RDATA.
80186922Sgreen		 * This name has to be canonicalized.*/
802105832Srwatson		case LDNS_RR_TYPE_NS:
8031556Srgrimes		case LDNS_RR_TYPE_MD:
804105832Srwatson		case LDNS_RR_TYPE_MF:
80586922Sgreen		case LDNS_RR_TYPE_CNAME:
80699744Sdillon		case LDNS_RR_TYPE_MB:
8071556Srgrimes		case LDNS_RR_TYPE_MG:
8081556Srgrimes		case LDNS_RR_TYPE_MR:
8091556Srgrimes		case LDNS_RR_TYPE_PTR:
8101556Srgrimes		case LDNS_RR_TYPE_DNAME:
8111556Srgrimes			/* the wireread function has already checked these
8121556Srgrimes			 * dname's for correctness, and this double checks */
813225847Sed			if(!dname_valid(d->rr_data[i]+2, d->rr_len[i]-2) ||
814225847Sed				!dname_valid(d->rr_data[j]+2, d->rr_len[j]-2))
815225847Sed				return 0;
816225847Sed			return query_dname_compare(d->rr_data[i]+2,
817225847Sed				d->rr_data[j]+2);
818225847Sed
819202945Sjh		/* These RR types have STR and fixed size rdata fields
8201556Srgrimes		 * before one or more name fields that need canonicalizing,
8211556Srgrimes		 * and after that a byte-for byte remainder can be compared.
8221556Srgrimes		 */
82388602Sjoe		/* type starts with the name; remainder is binary compared */
82461749Sjoe		case LDNS_RR_TYPE_NXT:
8251556Srgrimes		/* use rdata field formats */
826105832Srwatson		case LDNS_RR_TYPE_MINFO:
827105832Srwatson		case LDNS_RR_TYPE_RP:
82886922Sgreen		case LDNS_RR_TYPE_SOA:
829105832Srwatson		case LDNS_RR_TYPE_RT:
830105832Srwatson		case LDNS_RR_TYPE_AFSDB:
83186922Sgreen		case LDNS_RR_TYPE_KX:
8321556Srgrimes		case LDNS_RR_TYPE_MX:
8331556Srgrimes		case LDNS_RR_TYPE_SIG:
8341556Srgrimes		/* RRSIG signer name has to be downcased */
8351556Srgrimes		case LDNS_RR_TYPE_RRSIG:
8361556Srgrimes		case LDNS_RR_TYPE_PX:
8371556Srgrimes		case LDNS_RR_TYPE_NAPTR:
838130237Sdas		case LDNS_RR_TYPE_SRV:
839130237Sdas			desc = sldns_rr_descript(type);
840130237Sdas			log_assert(desc);
841130237Sdas			/* this holds for the types that need canonicalizing */
842130237Sdas			log_assert(desc->_minimum == desc->_maximum);
843130237Sdas			return canonical_compare_byfield(d, desc, i, j);
844130237Sdas
8451556Srgrimes		case LDNS_RR_TYPE_HINFO: /* no longer downcased */
8461556Srgrimes		case LDNS_RR_TYPE_NSEC:
8471556Srgrimes	default:
8481556Srgrimes		/* For unknown RR types, or types not listed above,
8491556Srgrimes		 * no canonicalization is needed, do binary compare */
8501556Srgrimes		/* byte for byte compare, equal means shortest first*/
8511556Srgrimes		minlen = d->rr_len[i]-2;
852226509Sdes		if(minlen > d->rr_len[j]-2)
8531556Srgrimes			minlen = d->rr_len[j]-2;
854105832Srwatson		c = memcmp(d->rr_data[i]+2, d->rr_data[j]+2, minlen);
8551556Srgrimes		if(c!=0)
856241014Smdf			return c;
857225847Sed		/* rdata equal, shortest is first */
858225847Sed		if(d->rr_len[i] < d->rr_len[j])
859225847Sed			return -1;
860225847Sed		if(d->rr_len[i] > d->rr_len[j])
861225847Sed			return 1;
8621556Srgrimes		/* rdata equal, length equal */
8631556Srgrimes		break;
864242807Sgrog	}
865242725Sgrog	return 0;
8661556Srgrimes}
8671556Srgrimes
8681556Srgrimesint
8691556Srgrimescanonical_tree_compare(const void* k1, const void* k2)
8701556Srgrimes{
8711556Srgrimes	struct canon_rr* r1 = (struct canon_rr*)k1;
8721556Srgrimes	struct canon_rr* r2 = (struct canon_rr*)k2;
8731556Srgrimes	log_assert(r1->rrset == r2->rrset);
8741556Srgrimes	return canonical_compare(r1->rrset, r1->rr_idx, r2->rr_idx);
8751556Srgrimes}
8761556Srgrimes
877242840Speter/**
8781556Srgrimes * Sort RRs for rrset in canonical order.
8791556Srgrimes * Does not actually canonicalize the RR rdatas.
8801556Srgrimes * Does not touch rrsigs.
881103726Swollman * @param rrset: to sort.
8821556Srgrimes * @param d: rrset data.
8831556Srgrimes * @param sortree: tree to sort into.
8841556Srgrimes * @param rrs: rr storage.
8851556Srgrimes */
8861556Srgrimesstatic void
8871556Srgrimescanonical_sort(struct ub_packed_rrset_key* rrset, struct packed_rrset_data* d,
8881556Srgrimes	rbtree_t* sortree, struct canon_rr* rrs)
8891556Srgrimes{
8901556Srgrimes	size_t i;
8911556Srgrimes	/* insert into rbtree to sort and detect duplicates */
8921556Srgrimes	for(i=0; i<d->count; i++) {
8931556Srgrimes		rrs[i].node.key = &rrs[i];
8941556Srgrimes		rrs[i].rrset = rrset;
89529560Ssef		rrs[i].rr_idx = i;
89629560Ssef		if(!rbtree_insert(sortree, &rrs[i].node)) {
8971556Srgrimes			/* this was a duplicate */
8981556Srgrimes		}
89929560Ssef	}
9001556Srgrimes}
90129560Ssef
90229560Ssef/**
9031556Srgrimes * Inser canonical owner name into buffer.
904 * @param buf: buffer to insert into at current position.
905 * @param k: rrset with its owner name.
906 * @param sig: signature with signer name and label count.
907 * 	must be length checked, at least 18 bytes long.
908 * @param can_owner: position in buffer returned for future use.
909 * @param can_owner_len: length of canonical owner name.
910 */
911static void
912insert_can_owner(sldns_buffer* buf, struct ub_packed_rrset_key* k,
913	uint8_t* sig, uint8_t** can_owner, size_t* can_owner_len)
914{
915	int rrsig_labels = (int)sig[3];
916	int fqdn_labels = dname_signame_label_count(k->rk.dname);
917	*can_owner = sldns_buffer_current(buf);
918	if(rrsig_labels == fqdn_labels) {
919		/* no change */
920		sldns_buffer_write(buf, k->rk.dname, k->rk.dname_len);
921		query_dname_tolower(*can_owner);
922		*can_owner_len = k->rk.dname_len;
923		return;
924	}
925	log_assert(rrsig_labels < fqdn_labels);
926	/* *. | fqdn(rightmost rrsig_labels) */
927	if(rrsig_labels < fqdn_labels) {
928		int i;
929		uint8_t* nm = k->rk.dname;
930		size_t len = k->rk.dname_len;
931		/* so skip fqdn_labels-rrsig_labels */
932		for(i=0; i<fqdn_labels-rrsig_labels; i++) {
933			dname_remove_label(&nm, &len);
934		}
935		*can_owner_len = len+2;
936		sldns_buffer_write(buf, (uint8_t*)"\001*", 2);
937		sldns_buffer_write(buf, nm, len);
938		query_dname_tolower(*can_owner);
939	}
940}
941
942/**
943 * Canonicalize Rdata in buffer.
944 * @param buf: buffer at position just after the rdata.
945 * @param rrset: rrset with type.
946 * @param len: length of the rdata (including rdatalen uint16).
947 */
948static void
949canonicalize_rdata(sldns_buffer* buf, struct ub_packed_rrset_key* rrset,
950	size_t len)
951{
952	uint8_t* datstart = sldns_buffer_current(buf)-len+2;
953	switch(ntohs(rrset->rk.type)) {
954		case LDNS_RR_TYPE_NXT:
955		case LDNS_RR_TYPE_NS:
956		case LDNS_RR_TYPE_MD:
957		case LDNS_RR_TYPE_MF:
958		case LDNS_RR_TYPE_CNAME:
959		case LDNS_RR_TYPE_MB:
960		case LDNS_RR_TYPE_MG:
961		case LDNS_RR_TYPE_MR:
962		case LDNS_RR_TYPE_PTR:
963		case LDNS_RR_TYPE_DNAME:
964			/* type only has a single argument, the name */
965			query_dname_tolower(datstart);
966			return;
967		case LDNS_RR_TYPE_MINFO:
968		case LDNS_RR_TYPE_RP:
969		case LDNS_RR_TYPE_SOA:
970			/* two names after another */
971			query_dname_tolower(datstart);
972			query_dname_tolower(datstart +
973				dname_valid(datstart, len-2));
974			return;
975		case LDNS_RR_TYPE_RT:
976		case LDNS_RR_TYPE_AFSDB:
977		case LDNS_RR_TYPE_KX:
978		case LDNS_RR_TYPE_MX:
979			/* skip fixed part */
980			if(len < 2+2+1) /* rdlen, skiplen, 1byteroot */
981				return;
982			datstart += 2;
983			query_dname_tolower(datstart);
984			return;
985		case LDNS_RR_TYPE_SIG:
986		/* downcase the RRSIG, compat with BIND (kept it from SIG) */
987		case LDNS_RR_TYPE_RRSIG:
988			/* skip fixed part */
989			if(len < 2+18+1)
990				return;
991			datstart += 18;
992			query_dname_tolower(datstart);
993			return;
994		case LDNS_RR_TYPE_PX:
995			/* skip, then two names after another */
996			if(len < 2+2+1)
997				return;
998			datstart += 2;
999			query_dname_tolower(datstart);
1000			query_dname_tolower(datstart +
1001				dname_valid(datstart, len-2-2));
1002			return;
1003		case LDNS_RR_TYPE_NAPTR:
1004			if(len < 2+4)
1005				return;
1006			len -= 2+4;
1007			datstart += 4;
1008			if(len < (size_t)datstart[0]+1) /* skip text field */
1009				return;
1010			len -= (size_t)datstart[0]+1;
1011			datstart += (size_t)datstart[0]+1;
1012			if(len < (size_t)datstart[0]+1) /* skip text field */
1013				return;
1014			len -= (size_t)datstart[0]+1;
1015			datstart += (size_t)datstart[0]+1;
1016			if(len < (size_t)datstart[0]+1) /* skip text field */
1017				return;
1018			len -= (size_t)datstart[0]+1;
1019			datstart += (size_t)datstart[0]+1;
1020			if(len < 1)	/* check name is at least 1 byte*/
1021				return;
1022			query_dname_tolower(datstart);
1023			return;
1024		case LDNS_RR_TYPE_SRV:
1025			/* skip fixed part */
1026			if(len < 2+6+1)
1027				return;
1028			datstart += 6;
1029			query_dname_tolower(datstart);
1030			return;
1031
1032		/* do not canonicalize NSEC rdata name, compat with
1033		 * from bind 9.4 signer, where it does not do so */
1034		case LDNS_RR_TYPE_NSEC: /* type starts with the name */
1035		case LDNS_RR_TYPE_HINFO: /* not downcased */
1036		/* A6 not supported */
1037		default:
1038			/* nothing to do for unknown types */
1039			return;
1040	}
1041}
1042
1043int rrset_canonical_equal(struct regional* region,
1044	struct ub_packed_rrset_key* k1, struct ub_packed_rrset_key* k2)
1045{
1046	struct rbtree_t sortree1, sortree2;
1047	struct canon_rr *rrs1, *rrs2, *p1, *p2;
1048	struct packed_rrset_data* d1=(struct packed_rrset_data*)k1->entry.data;
1049	struct packed_rrset_data* d2=(struct packed_rrset_data*)k2->entry.data;
1050	struct ub_packed_rrset_key fk;
1051	struct packed_rrset_data fd;
1052	size_t flen[2];
1053	uint8_t* fdata[2];
1054
1055	/* basic compare */
1056	if(k1->rk.dname_len != k2->rk.dname_len ||
1057		k1->rk.flags != k2->rk.flags ||
1058		k1->rk.type != k2->rk.type ||
1059		k1->rk.rrset_class != k2->rk.rrset_class ||
1060		query_dname_compare(k1->rk.dname, k2->rk.dname) != 0)
1061		return 0;
1062	if(d1->ttl != d2->ttl ||
1063		d1->count != d2->count ||
1064		d1->rrsig_count != d2->rrsig_count ||
1065		d1->trust != d2->trust ||
1066		d1->security != d2->security)
1067		return 0;
1068
1069	/* init */
1070	memset(&fk, 0, sizeof(fk));
1071	memset(&fd, 0, sizeof(fd));
1072	fk.entry.data = &fd;
1073	fd.count = 2;
1074	fd.rr_len = flen;
1075	fd.rr_data = fdata;
1076	rbtree_init(&sortree1, &canonical_tree_compare);
1077	rbtree_init(&sortree2, &canonical_tree_compare);
1078	if(d1->count > RR_COUNT_MAX || d2->count > RR_COUNT_MAX)
1079		return 1; /* protection against integer overflow */
1080	rrs1 = regional_alloc(region, sizeof(struct canon_rr)*d1->count);
1081	rrs2 = regional_alloc(region, sizeof(struct canon_rr)*d2->count);
1082	if(!rrs1 || !rrs2) return 1; /* alloc failure */
1083
1084	/* sort */
1085	canonical_sort(k1, d1, &sortree1, rrs1);
1086	canonical_sort(k2, d2, &sortree2, rrs2);
1087
1088	/* compare canonical-sorted RRs for canonical-equality */
1089	if(sortree1.count != sortree2.count)
1090		return 0;
1091	p1 = (struct canon_rr*)rbtree_first(&sortree1);
1092	p2 = (struct canon_rr*)rbtree_first(&sortree2);
1093	while(p1 != (struct canon_rr*)RBTREE_NULL &&
1094		p2 != (struct canon_rr*)RBTREE_NULL) {
1095		flen[0] = d1->rr_len[p1->rr_idx];
1096		flen[1] = d2->rr_len[p2->rr_idx];
1097		fdata[0] = d1->rr_data[p1->rr_idx];
1098		fdata[1] = d2->rr_data[p2->rr_idx];
1099
1100		if(canonical_compare(&fk, 0, 1) != 0)
1101			return 0;
1102		p1 = (struct canon_rr*)rbtree_next(&p1->node);
1103		p2 = (struct canon_rr*)rbtree_next(&p2->node);
1104	}
1105	return 1;
1106}
1107
1108/**
1109 * Create canonical form of rrset in the scratch buffer.
1110 * @param region: temporary region.
1111 * @param buf: the buffer to use.
1112 * @param k: the rrset to insert.
1113 * @param sig: RRSIG rdata to include.
1114 * @param siglen: RRSIG rdata len excluding signature field, but inclusive
1115 * 	signer name length.
1116 * @param sortree: if NULL is passed a new sorted rrset tree is built.
1117 * 	Otherwise it is reused.
1118 * @return false on alloc error.
1119 */
1120static int
1121rrset_canonical(struct regional* region, sldns_buffer* buf,
1122	struct ub_packed_rrset_key* k, uint8_t* sig, size_t siglen,
1123	struct rbtree_t** sortree)
1124{
1125	struct packed_rrset_data* d = (struct packed_rrset_data*)k->entry.data;
1126	uint8_t* can_owner = NULL;
1127	size_t can_owner_len = 0;
1128	struct canon_rr* walk;
1129	struct canon_rr* rrs;
1130
1131	if(!*sortree) {
1132		*sortree = (struct rbtree_t*)regional_alloc(region,
1133			sizeof(rbtree_t));
1134		if(!*sortree)
1135			return 0;
1136		if(d->count > RR_COUNT_MAX)
1137			return 0; /* integer overflow protection */
1138		rrs = regional_alloc(region, sizeof(struct canon_rr)*d->count);
1139		if(!rrs) {
1140			*sortree = NULL;
1141			return 0;
1142		}
1143		rbtree_init(*sortree, &canonical_tree_compare);
1144		canonical_sort(k, d, *sortree, rrs);
1145	}
1146
1147	sldns_buffer_clear(buf);
1148	sldns_buffer_write(buf, sig, siglen);
1149	/* canonicalize signer name */
1150	query_dname_tolower(sldns_buffer_begin(buf)+18);
1151	RBTREE_FOR(walk, struct canon_rr*, (*sortree)) {
1152		/* see if there is enough space left in the buffer */
1153		if(sldns_buffer_remaining(buf) < can_owner_len + 2 + 2 + 4
1154			+ d->rr_len[walk->rr_idx]) {
1155			log_err("verify: failed to canonicalize, "
1156				"rrset too big");
1157			return 0;
1158		}
1159		/* determine canonical owner name */
1160		if(can_owner)
1161			sldns_buffer_write(buf, can_owner, can_owner_len);
1162		else	insert_can_owner(buf, k, sig, &can_owner,
1163				&can_owner_len);
1164		sldns_buffer_write(buf, &k->rk.type, 2);
1165		sldns_buffer_write(buf, &k->rk.rrset_class, 2);
1166		sldns_buffer_write(buf, sig+4, 4);
1167		sldns_buffer_write(buf, d->rr_data[walk->rr_idx],
1168			d->rr_len[walk->rr_idx]);
1169		canonicalize_rdata(buf, k, d->rr_len[walk->rr_idx]);
1170	}
1171	sldns_buffer_flip(buf);
1172	return 1;
1173}
1174
1175/** pretty print rrsig error with dates */
1176static void
1177sigdate_error(const char* str, int32_t expi, int32_t incep, int32_t now)
1178{
1179	struct tm tm;
1180	char expi_buf[16];
1181	char incep_buf[16];
1182	char now_buf[16];
1183	time_t te, ti, tn;
1184
1185	if(verbosity < VERB_QUERY)
1186		return;
1187	te = (time_t)expi;
1188	ti = (time_t)incep;
1189	tn = (time_t)now;
1190	memset(&tm, 0, sizeof(tm));
1191	if(gmtime_r(&te, &tm) && strftime(expi_buf, 15, "%Y%m%d%H%M%S", &tm)
1192	 &&gmtime_r(&ti, &tm) && strftime(incep_buf, 15, "%Y%m%d%H%M%S", &tm)
1193	 &&gmtime_r(&tn, &tm) && strftime(now_buf, 15, "%Y%m%d%H%M%S", &tm)) {
1194		log_info("%s expi=%s incep=%s now=%s", str, expi_buf,
1195			incep_buf, now_buf);
1196	} else
1197		log_info("%s expi=%u incep=%u now=%u", str, (unsigned)expi,
1198			(unsigned)incep, (unsigned)now);
1199}
1200
1201/** check rrsig dates */
1202static int
1203check_dates(struct val_env* ve, uint32_t unow,
1204	uint8_t* expi_p, uint8_t* incep_p, char** reason)
1205{
1206	/* read out the dates */
1207	int32_t expi, incep, now;
1208	memmove(&expi, expi_p, sizeof(expi));
1209	memmove(&incep, incep_p, sizeof(incep));
1210	expi = ntohl(expi);
1211	incep = ntohl(incep);
1212
1213	/* get current date */
1214	if(ve->date_override) {
1215		if(ve->date_override == -1) {
1216			verbose(VERB_ALGO, "date override: ignore date");
1217			return 1;
1218		}
1219		now = ve->date_override;
1220		verbose(VERB_ALGO, "date override option %d", (int)now);
1221	} else	now = (int32_t)unow;
1222
1223	/* check them */
1224	if(incep - expi > 0) {
1225		sigdate_error("verify: inception after expiration, "
1226			"signature bad", expi, incep, now);
1227		*reason = "signature inception after expiration";
1228		return 0;
1229	}
1230	if(incep - now > 0) {
1231		/* within skew ? (calc here to avoid calculation normally) */
1232		int32_t skew = (expi-incep)/10;
1233		if(skew < ve->skew_min) skew = ve->skew_min;
1234		if(skew > ve->skew_max) skew = ve->skew_max;
1235		if(incep - now > skew) {
1236			sigdate_error("verify: signature bad, current time is"
1237				" before inception date", expi, incep, now);
1238			*reason = "signature before inception date";
1239			return 0;
1240		}
1241		sigdate_error("verify warning suspicious signature inception "
1242			" or bad local clock", expi, incep, now);
1243	}
1244	if(now - expi > 0) {
1245		int32_t skew = (expi-incep)/10;
1246		if(skew < ve->skew_min) skew = ve->skew_min;
1247		if(skew > ve->skew_max) skew = ve->skew_max;
1248		if(now - expi > skew) {
1249			sigdate_error("verify: signature expired", expi,
1250				incep, now);
1251			*reason = "signature expired";
1252			return 0;
1253		}
1254		sigdate_error("verify warning suspicious signature expiration "
1255			" or bad local clock", expi, incep, now);
1256	}
1257	return 1;
1258}
1259
1260/** adjust rrset TTL for verified rrset, compare to original TTL and expi */
1261static void
1262adjust_ttl(struct val_env* ve, uint32_t unow,
1263	struct ub_packed_rrset_key* rrset, uint8_t* orig_p,
1264	uint8_t* expi_p, uint8_t* incep_p)
1265{
1266	struct packed_rrset_data* d =
1267		(struct packed_rrset_data*)rrset->entry.data;
1268	/* read out the dates */
1269	int32_t origttl, expittl, expi, incep, now;
1270	memmove(&origttl, orig_p, sizeof(origttl));
1271	memmove(&expi, expi_p, sizeof(expi));
1272	memmove(&incep, incep_p, sizeof(incep));
1273	expi = ntohl(expi);
1274	incep = ntohl(incep);
1275	origttl = ntohl(origttl);
1276
1277	/* get current date */
1278	if(ve->date_override) {
1279		now = ve->date_override;
1280	} else	now = (int32_t)unow;
1281	expittl = expi - now;
1282
1283	/* so now:
1284	 * d->ttl: rrset ttl read from message or cache. May be reduced
1285	 * origttl: original TTL from signature, authoritative TTL max.
1286	 * expittl: TTL until the signature expires.
1287	 *
1288	 * Use the smallest of these.
1289	 */
1290	if(d->ttl > (time_t)origttl) {
1291		verbose(VERB_QUERY, "rrset TTL larger than original TTL,"
1292			" adjusting TTL downwards");
1293		d->ttl = origttl;
1294	}
1295	if(expittl > 0 && d->ttl > (time_t)expittl) {
1296		verbose(VERB_ALGO, "rrset TTL larger than sig expiration ttl,"
1297			" adjusting TTL downwards");
1298		d->ttl = expittl;
1299	}
1300}
1301
1302enum sec_status
1303dnskey_verify_rrset_sig(struct regional* region, sldns_buffer* buf,
1304	struct val_env* ve, time_t now,
1305        struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey,
1306        size_t dnskey_idx, size_t sig_idx,
1307	struct rbtree_t** sortree, int* buf_canon, char** reason)
1308{
1309	enum sec_status sec;
1310	uint8_t* sig;		/* RRSIG rdata */
1311	size_t siglen;
1312	size_t rrnum = rrset_get_count(rrset);
1313	uint8_t* signer;	/* rrsig signer name */
1314	size_t signer_len;
1315	unsigned char* sigblock; /* signature rdata field */
1316	unsigned int sigblock_len;
1317	uint16_t ktag;		/* DNSKEY key tag */
1318	unsigned char* key;	/* public key rdata field */
1319	unsigned int keylen;
1320	rrset_get_rdata(rrset, rrnum + sig_idx, &sig, &siglen);
1321	/* min length of rdatalen, fixed rrsig, root signer, 1 byte sig */
1322	if(siglen < 2+20) {
1323		verbose(VERB_QUERY, "verify: signature too short");
1324		*reason = "signature too short";
1325		return sec_status_bogus;
1326	}
1327
1328	if(!(dnskey_get_flags(dnskey, dnskey_idx) & DNSKEY_BIT_ZSK)) {
1329		verbose(VERB_QUERY, "verify: dnskey without ZSK flag");
1330		*reason = "dnskey without ZSK flag";
1331		return sec_status_bogus;
1332	}
1333
1334	if(dnskey_get_protocol(dnskey, dnskey_idx) != LDNS_DNSSEC_KEYPROTO) {
1335		/* RFC 4034 says DNSKEY PROTOCOL MUST be 3 */
1336		verbose(VERB_QUERY, "verify: dnskey has wrong key protocol");
1337		*reason = "dnskey has wrong protocolnumber";
1338		return sec_status_bogus;
1339	}
1340
1341	/* verify as many fields in rrsig as possible */
1342	signer = sig+2+18;
1343	signer_len = dname_valid(signer, siglen-2-18);
1344	if(!signer_len) {
1345		verbose(VERB_QUERY, "verify: malformed signer name");
1346		*reason = "signer name malformed";
1347		return sec_status_bogus; /* signer name invalid */
1348	}
1349	if(!dname_subdomain_c(rrset->rk.dname, signer)) {
1350		verbose(VERB_QUERY, "verify: signer name is off-tree");
1351		*reason = "signer name off-tree";
1352		return sec_status_bogus; /* signer name offtree */
1353	}
1354	sigblock = (unsigned char*)signer+signer_len;
1355	if(siglen < 2+18+signer_len+1) {
1356		verbose(VERB_QUERY, "verify: too short, no signature data");
1357		*reason = "signature too short, no signature data";
1358		return sec_status_bogus; /* sig rdf is < 1 byte */
1359	}
1360	sigblock_len = (unsigned int)(siglen - 2 - 18 - signer_len);
1361
1362	/* verify key dname == sig signer name */
1363	if(query_dname_compare(signer, dnskey->rk.dname) != 0) {
1364		verbose(VERB_QUERY, "verify: wrong key for rrsig");
1365		log_nametypeclass(VERB_QUERY, "RRSIG signername is",
1366			signer, 0, 0);
1367		log_nametypeclass(VERB_QUERY, "the key name is",
1368			dnskey->rk.dname, 0, 0);
1369		*reason = "signer name mismatches key name";
1370		return sec_status_bogus;
1371	}
1372
1373	/* verify covered type */
1374	/* memcmp works because type is in network format for rrset */
1375	if(memcmp(sig+2, &rrset->rk.type, 2) != 0) {
1376		verbose(VERB_QUERY, "verify: wrong type covered");
1377		*reason = "signature covers wrong type";
1378		return sec_status_bogus;
1379	}
1380	/* verify keytag and sig algo (possibly again) */
1381	if((int)sig[2+2] != dnskey_get_algo(dnskey, dnskey_idx)) {
1382		verbose(VERB_QUERY, "verify: wrong algorithm");
1383		*reason = "signature has wrong algorithm";
1384		return sec_status_bogus;
1385	}
1386	ktag = htons(dnskey_calc_keytag(dnskey, dnskey_idx));
1387	if(memcmp(sig+2+16, &ktag, 2) != 0) {
1388		verbose(VERB_QUERY, "verify: wrong keytag");
1389		*reason = "signature has wrong keytag";
1390		return sec_status_bogus;
1391	}
1392
1393	/* verify labels is in a valid range */
1394	if((int)sig[2+3] > dname_signame_label_count(rrset->rk.dname)) {
1395		verbose(VERB_QUERY, "verify: labelcount out of range");
1396		*reason = "signature labelcount out of range";
1397		return sec_status_bogus;
1398	}
1399
1400	/* original ttl, always ok */
1401
1402	if(!*buf_canon) {
1403		/* create rrset canonical format in buffer, ready for
1404		 * signature */
1405		if(!rrset_canonical(region, buf, rrset, sig+2,
1406			18 + signer_len, sortree)) {
1407			log_err("verify: failed due to alloc error");
1408			return sec_status_unchecked;
1409		}
1410		*buf_canon = 1;
1411	}
1412
1413	/* check that dnskey is available */
1414	dnskey_get_pubkey(dnskey, dnskey_idx, &key, &keylen);
1415	if(!key) {
1416		verbose(VERB_QUERY, "verify: short DNSKEY RR");
1417		return sec_status_unchecked;
1418	}
1419
1420	/* verify */
1421	sec = verify_canonrrset(buf, (int)sig[2+2],
1422		sigblock, sigblock_len, key, keylen, reason);
1423
1424	if(sec == sec_status_secure) {
1425		/* check if TTL is too high - reduce if so */
1426		adjust_ttl(ve, now, rrset, sig+2+4, sig+2+8, sig+2+12);
1427
1428		/* verify inception, expiration dates
1429		 * Do this last so that if you ignore expired-sigs the
1430		 * rest is sure to be OK. */
1431		if(!check_dates(ve, now, sig+2+8, sig+2+12, reason)) {
1432			return sec_status_bogus;
1433		}
1434	}
1435
1436	return sec;
1437}
1438