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