1*be771a7bSCy Schubert /* 2*be771a7bSCy Schubert * testcode/unitverify.c - unit test for signature verification routines. 3*be771a7bSCy Schubert * 4*be771a7bSCy Schubert * Copyright (c) 2007, NLnet Labs. All rights reserved. 5*be771a7bSCy Schubert * 6*be771a7bSCy Schubert * This software is open source. 7*be771a7bSCy Schubert * 8*be771a7bSCy Schubert * Redistribution and use in source and binary forms, with or without 9*be771a7bSCy Schubert * modification, are permitted provided that the following conditions 10*be771a7bSCy Schubert * are met: 11*be771a7bSCy Schubert * 12*be771a7bSCy Schubert * Redistributions of source code must retain the above copyright notice, 13*be771a7bSCy Schubert * this list of conditions and the following disclaimer. 14*be771a7bSCy Schubert * 15*be771a7bSCy Schubert * Redistributions in binary form must reproduce the above copyright notice, 16*be771a7bSCy Schubert * this list of conditions and the following disclaimer in the documentation 17*be771a7bSCy Schubert * and/or other materials provided with the distribution. 18*be771a7bSCy Schubert * 19*be771a7bSCy Schubert * Neither the name of the NLNET LABS nor the names of its contributors may 20*be771a7bSCy Schubert * be used to endorse or promote products derived from this software without 21*be771a7bSCy Schubert * specific prior written permission. 22*be771a7bSCy Schubert * 23*be771a7bSCy Schubert * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24*be771a7bSCy Schubert * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25*be771a7bSCy Schubert * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26*be771a7bSCy Schubert * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27*be771a7bSCy Schubert * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28*be771a7bSCy Schubert * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29*be771a7bSCy Schubert * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30*be771a7bSCy Schubert * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31*be771a7bSCy Schubert * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32*be771a7bSCy Schubert * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33*be771a7bSCy Schubert * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34*be771a7bSCy Schubert * 35*be771a7bSCy Schubert */ 36*be771a7bSCy Schubert /** 37*be771a7bSCy Schubert * \file 38*be771a7bSCy Schubert * Calls verification unit tests. Exits with code 1 on a failure. 39*be771a7bSCy Schubert */ 40*be771a7bSCy Schubert 41*be771a7bSCy Schubert #include "config.h" 42*be771a7bSCy Schubert #include "util/log.h" 43*be771a7bSCy Schubert #include "testcode/unitmain.h" 44*be771a7bSCy Schubert #include "validator/val_sigcrypt.h" 45*be771a7bSCy Schubert #include "validator/val_secalgo.h" 46*be771a7bSCy Schubert #include "validator/val_nsec.h" 47*be771a7bSCy Schubert #include "validator/val_nsec3.h" 48*be771a7bSCy Schubert #include "validator/validator.h" 49*be771a7bSCy Schubert #include "testcode/testpkts.h" 50*be771a7bSCy Schubert #include "util/data/msgreply.h" 51*be771a7bSCy Schubert #include "util/data/msgparse.h" 52*be771a7bSCy Schubert #include "util/data/dname.h" 53*be771a7bSCy Schubert #include "util/regional.h" 54*be771a7bSCy Schubert #include "util/alloc.h" 55*be771a7bSCy Schubert #include "util/rbtree.h" 56*be771a7bSCy Schubert #include "util/net_help.h" 57*be771a7bSCy Schubert #include "util/module.h" 58*be771a7bSCy Schubert #include "util/config_file.h" 59*be771a7bSCy Schubert #include "sldns/sbuffer.h" 60*be771a7bSCy Schubert #include "sldns/keyraw.h" 61*be771a7bSCy Schubert #include "sldns/str2wire.h" 62*be771a7bSCy Schubert #include "sldns/wire2str.h" 63*be771a7bSCy Schubert 64*be771a7bSCy Schubert /** verbose signature test */ 65*be771a7bSCy Schubert static int vsig = 0; 66*be771a7bSCy Schubert 67*be771a7bSCy Schubert /** entry to packet buffer with wireformat */ 68*be771a7bSCy Schubert static void 69*be771a7bSCy Schubert entry_to_buf(struct entry* e, sldns_buffer* pkt) 70*be771a7bSCy Schubert { 71*be771a7bSCy Schubert unit_assert(e->reply_list); 72*be771a7bSCy Schubert if(e->reply_list->reply_from_hex) { 73*be771a7bSCy Schubert sldns_buffer_copy(pkt, e->reply_list->reply_from_hex); 74*be771a7bSCy Schubert } else { 75*be771a7bSCy Schubert sldns_buffer_clear(pkt); 76*be771a7bSCy Schubert sldns_buffer_write(pkt, e->reply_list->reply_pkt, 77*be771a7bSCy Schubert e->reply_list->reply_len); 78*be771a7bSCy Schubert sldns_buffer_flip(pkt); 79*be771a7bSCy Schubert } 80*be771a7bSCy Schubert } 81*be771a7bSCy Schubert 82*be771a7bSCy Schubert /** entry to reply info conversion */ 83*be771a7bSCy Schubert static void 84*be771a7bSCy Schubert entry_to_repinfo(struct entry* e, struct alloc_cache* alloc, 85*be771a7bSCy Schubert struct regional* region, sldns_buffer* pkt, struct query_info* qi, 86*be771a7bSCy Schubert struct reply_info** rep) 87*be771a7bSCy Schubert { 88*be771a7bSCy Schubert int ret; 89*be771a7bSCy Schubert struct edns_data edns; 90*be771a7bSCy Schubert entry_to_buf(e, pkt); 91*be771a7bSCy Schubert /* lock alloc lock to please lock checking software. 92*be771a7bSCy Schubert * alloc_special_obtain assumes it is talking to a ub-alloc, 93*be771a7bSCy Schubert * and does not need to perform locking. Here the alloc is 94*be771a7bSCy Schubert * the only one, so we lock it here */ 95*be771a7bSCy Schubert lock_quick_lock(&alloc->lock); 96*be771a7bSCy Schubert ret = reply_info_parse(pkt, alloc, qi, rep, region, &edns); 97*be771a7bSCy Schubert lock_quick_unlock(&alloc->lock); 98*be771a7bSCy Schubert if(ret != 0) { 99*be771a7bSCy Schubert char rcode[16]; 100*be771a7bSCy Schubert sldns_wire2str_rcode_buf(ret, rcode, sizeof(rcode)); 101*be771a7bSCy Schubert printf("parse code %d: %s\n", ret, rcode); 102*be771a7bSCy Schubert unit_assert(ret != 0); 103*be771a7bSCy Schubert } 104*be771a7bSCy Schubert } 105*be771a7bSCy Schubert 106*be771a7bSCy Schubert /** extract DNSKEY rrset from answer and convert it */ 107*be771a7bSCy Schubert static struct ub_packed_rrset_key* 108*be771a7bSCy Schubert extract_keys(struct entry* e, struct alloc_cache* alloc, 109*be771a7bSCy Schubert struct regional* region, sldns_buffer* pkt) 110*be771a7bSCy Schubert { 111*be771a7bSCy Schubert struct ub_packed_rrset_key* dnskey = NULL; 112*be771a7bSCy Schubert struct query_info qinfo; 113*be771a7bSCy Schubert struct reply_info* rep = NULL; 114*be771a7bSCy Schubert size_t i; 115*be771a7bSCy Schubert 116*be771a7bSCy Schubert entry_to_repinfo(e, alloc, region, pkt, &qinfo, &rep); 117*be771a7bSCy Schubert for(i=0; i<rep->an_numrrsets; i++) { 118*be771a7bSCy Schubert if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_DNSKEY) { 119*be771a7bSCy Schubert dnskey = rep->rrsets[i]; 120*be771a7bSCy Schubert rep->rrsets[i] = NULL; 121*be771a7bSCy Schubert break; 122*be771a7bSCy Schubert } 123*be771a7bSCy Schubert } 124*be771a7bSCy Schubert unit_assert(dnskey); 125*be771a7bSCy Schubert 126*be771a7bSCy Schubert reply_info_parsedelete(rep, alloc); 127*be771a7bSCy Schubert query_info_clear(&qinfo); 128*be771a7bSCy Schubert return dnskey; 129*be771a7bSCy Schubert } 130*be771a7bSCy Schubert 131*be771a7bSCy Schubert /** return true if answer should be bogus */ 132*be771a7bSCy Schubert static int 133*be771a7bSCy Schubert should_be_bogus(struct ub_packed_rrset_key* rrset, struct query_info* qinfo) 134*be771a7bSCy Schubert { 135*be771a7bSCy Schubert struct packed_rrset_data* d = (struct packed_rrset_data*)rrset-> 136*be771a7bSCy Schubert entry.data; 137*be771a7bSCy Schubert if(d->rrsig_count == 0) 138*be771a7bSCy Schubert return 1; 139*be771a7bSCy Schubert /* name 'bogus' as first label signals bogus */ 140*be771a7bSCy Schubert if(rrset->rk.dname_len > 6 && memcmp(rrset->rk.dname+1, "bogus", 5)==0) 141*be771a7bSCy Schubert return 1; 142*be771a7bSCy Schubert if(qinfo->qname_len > 6 && memcmp(qinfo->qname+1, "bogus", 5)==0) 143*be771a7bSCy Schubert return 1; 144*be771a7bSCy Schubert return 0; 145*be771a7bSCy Schubert } 146*be771a7bSCy Schubert 147*be771a7bSCy Schubert /** return number of rrs in an rrset */ 148*be771a7bSCy Schubert static size_t 149*be771a7bSCy Schubert rrset_get_count(struct ub_packed_rrset_key* rrset) 150*be771a7bSCy Schubert { 151*be771a7bSCy Schubert struct packed_rrset_data* d = (struct packed_rrset_data*) 152*be771a7bSCy Schubert rrset->entry.data; 153*be771a7bSCy Schubert if(!d) return 0; 154*be771a7bSCy Schubert return d->count; 155*be771a7bSCy Schubert } 156*be771a7bSCy Schubert 157*be771a7bSCy Schubert /** setup sig alg list from dnskey */ 158*be771a7bSCy Schubert static void 159*be771a7bSCy Schubert setup_sigalg(struct ub_packed_rrset_key* dnskey, uint8_t* sigalg) 160*be771a7bSCy Schubert { 161*be771a7bSCy Schubert uint8_t a[ALGO_NEEDS_MAX]; 162*be771a7bSCy Schubert size_t i, n = 0; 163*be771a7bSCy Schubert memset(a, 0, sizeof(a)); 164*be771a7bSCy Schubert for(i=0; i<rrset_get_count(dnskey); i++) { 165*be771a7bSCy Schubert uint8_t algo = (uint8_t)dnskey_get_algo(dnskey, i); 166*be771a7bSCy Schubert if(a[algo] == 0) { 167*be771a7bSCy Schubert a[algo] = 1; 168*be771a7bSCy Schubert sigalg[n++] = algo; 169*be771a7bSCy Schubert } 170*be771a7bSCy Schubert } 171*be771a7bSCy Schubert sigalg[n] = 0; 172*be771a7bSCy Schubert } 173*be771a7bSCy Schubert 174*be771a7bSCy Schubert /** verify and test one rrset against the key rrset */ 175*be771a7bSCy Schubert static void 176*be771a7bSCy Schubert verifytest_rrset(struct module_env* env, struct val_env* ve, 177*be771a7bSCy Schubert struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey, 178*be771a7bSCy Schubert struct query_info* qinfo) 179*be771a7bSCy Schubert { 180*be771a7bSCy Schubert enum sec_status sec; 181*be771a7bSCy Schubert char reasonbuf[256]; 182*be771a7bSCy Schubert char* reason = NULL; 183*be771a7bSCy Schubert uint8_t sigalg[ALGO_NEEDS_MAX+1]; 184*be771a7bSCy Schubert int verified = 0; 185*be771a7bSCy Schubert if(vsig) { 186*be771a7bSCy Schubert log_nametypeclass(VERB_QUERY, "verify of rrset", 187*be771a7bSCy Schubert rrset->rk.dname, ntohs(rrset->rk.type), 188*be771a7bSCy Schubert ntohs(rrset->rk.rrset_class)); 189*be771a7bSCy Schubert } 190*be771a7bSCy Schubert setup_sigalg(dnskey, sigalg); /* check all algorithms in the dnskey */ 191*be771a7bSCy Schubert /* ok to give null as qstate here, won't be used for answer section. */ 192*be771a7bSCy Schubert sec = dnskeyset_verify_rrset(env, ve, rrset, dnskey, sigalg, &reason, 193*be771a7bSCy Schubert NULL, LDNS_SECTION_ANSWER, NULL, &verified, reasonbuf, 194*be771a7bSCy Schubert sizeof(reasonbuf)); 195*be771a7bSCy Schubert if(vsig) { 196*be771a7bSCy Schubert printf("verify outcome is: %s %s\n", sec_status_to_string(sec), 197*be771a7bSCy Schubert reason?reason:""); 198*be771a7bSCy Schubert } 199*be771a7bSCy Schubert if(should_be_bogus(rrset, qinfo)) { 200*be771a7bSCy Schubert unit_assert(sec == sec_status_bogus); 201*be771a7bSCy Schubert } else { 202*be771a7bSCy Schubert unit_assert(sec == sec_status_secure); 203*be771a7bSCy Schubert } 204*be771a7bSCy Schubert } 205*be771a7bSCy Schubert 206*be771a7bSCy Schubert /** verify and test an entry - every rr in the message */ 207*be771a7bSCy Schubert static void 208*be771a7bSCy Schubert verifytest_entry(struct entry* e, struct alloc_cache* alloc, 209*be771a7bSCy Schubert struct regional* region, sldns_buffer* pkt, 210*be771a7bSCy Schubert struct ub_packed_rrset_key* dnskey, struct module_env* env, 211*be771a7bSCy Schubert struct val_env* ve) 212*be771a7bSCy Schubert { 213*be771a7bSCy Schubert struct query_info qinfo; 214*be771a7bSCy Schubert struct reply_info* rep = NULL; 215*be771a7bSCy Schubert size_t i; 216*be771a7bSCy Schubert 217*be771a7bSCy Schubert regional_free_all(region); 218*be771a7bSCy Schubert if(vsig) { 219*be771a7bSCy Schubert char* s = sldns_wire2str_pkt(e->reply_list->reply_pkt, 220*be771a7bSCy Schubert e->reply_list->reply_len); 221*be771a7bSCy Schubert printf("verifying pkt:\n%s\n", s?s:"outofmemory"); 222*be771a7bSCy Schubert free(s); 223*be771a7bSCy Schubert } 224*be771a7bSCy Schubert entry_to_repinfo(e, alloc, region, pkt, &qinfo, &rep); 225*be771a7bSCy Schubert 226*be771a7bSCy Schubert for(i=0; i<rep->rrset_count; i++) { 227*be771a7bSCy Schubert verifytest_rrset(env, ve, rep->rrsets[i], dnskey, &qinfo); 228*be771a7bSCy Schubert } 229*be771a7bSCy Schubert 230*be771a7bSCy Schubert reply_info_parsedelete(rep, alloc); 231*be771a7bSCy Schubert query_info_clear(&qinfo); 232*be771a7bSCy Schubert } 233*be771a7bSCy Schubert 234*be771a7bSCy Schubert /** find RRset in reply by type */ 235*be771a7bSCy Schubert static struct ub_packed_rrset_key* 236*be771a7bSCy Schubert find_rrset_type(struct reply_info* rep, uint16_t type) 237*be771a7bSCy Schubert { 238*be771a7bSCy Schubert size_t i; 239*be771a7bSCy Schubert for(i=0; i<rep->rrset_count; i++) { 240*be771a7bSCy Schubert if(ntohs(rep->rrsets[i]->rk.type) == type) 241*be771a7bSCy Schubert return rep->rrsets[i]; 242*be771a7bSCy Schubert } 243*be771a7bSCy Schubert return NULL; 244*be771a7bSCy Schubert } 245*be771a7bSCy Schubert 246*be771a7bSCy Schubert /** DS sig test an entry - get DNSKEY and DS in entry and verify */ 247*be771a7bSCy Schubert static void 248*be771a7bSCy Schubert dstest_entry(struct entry* e, struct alloc_cache* alloc, 249*be771a7bSCy Schubert struct regional* region, sldns_buffer* pkt, struct module_env* env) 250*be771a7bSCy Schubert { 251*be771a7bSCy Schubert struct query_info qinfo; 252*be771a7bSCy Schubert struct reply_info* rep = NULL; 253*be771a7bSCy Schubert struct ub_packed_rrset_key* ds, *dnskey; 254*be771a7bSCy Schubert int ret; 255*be771a7bSCy Schubert 256*be771a7bSCy Schubert regional_free_all(region); 257*be771a7bSCy Schubert if(vsig) { 258*be771a7bSCy Schubert char* s = sldns_wire2str_pkt(e->reply_list->reply_pkt, 259*be771a7bSCy Schubert e->reply_list->reply_len); 260*be771a7bSCy Schubert printf("verifying DS-DNSKEY match:\n%s\n", s?s:"outofmemory"); 261*be771a7bSCy Schubert free(s); 262*be771a7bSCy Schubert } 263*be771a7bSCy Schubert entry_to_repinfo(e, alloc, region, pkt, &qinfo, &rep); 264*be771a7bSCy Schubert ds = find_rrset_type(rep, LDNS_RR_TYPE_DS); 265*be771a7bSCy Schubert dnskey = find_rrset_type(rep, LDNS_RR_TYPE_DNSKEY); 266*be771a7bSCy Schubert /* check test is OK */ 267*be771a7bSCy Schubert unit_assert(ds && dnskey); 268*be771a7bSCy Schubert 269*be771a7bSCy Schubert ret = ds_digest_match_dnskey(env, dnskey, 0, ds, 0); 270*be771a7bSCy Schubert if(strncmp((char*)qinfo.qname, "\003yes", 4) == 0) { 271*be771a7bSCy Schubert if(vsig) { 272*be771a7bSCy Schubert printf("result(yes)= %s\n", ret?"yes":"no"); 273*be771a7bSCy Schubert } 274*be771a7bSCy Schubert unit_assert(ret); 275*be771a7bSCy Schubert } else if (strncmp((char*)qinfo.qname, "\002no", 3) == 0) { 276*be771a7bSCy Schubert if(vsig) { 277*be771a7bSCy Schubert printf("result(no)= %s\n", ret?"yes":"no"); 278*be771a7bSCy Schubert } 279*be771a7bSCy Schubert unit_assert(!ret); 280*be771a7bSCy Schubert verbose(VERB_QUERY, "DS fail: OK; matched unit test"); 281*be771a7bSCy Schubert } else { 282*be771a7bSCy Schubert fatal_exit("Bad qname in DS unit test, yes or no"); 283*be771a7bSCy Schubert } 284*be771a7bSCy Schubert 285*be771a7bSCy Schubert reply_info_parsedelete(rep, alloc); 286*be771a7bSCy Schubert query_info_clear(&qinfo); 287*be771a7bSCy Schubert } 288*be771a7bSCy Schubert 289*be771a7bSCy Schubert /** verify from a file */ 290*be771a7bSCy Schubert static void 291*be771a7bSCy Schubert verifytest_file(const char* fname, const char* at_date) 292*be771a7bSCy Schubert { 293*be771a7bSCy Schubert /* 294*be771a7bSCy Schubert * The file contains a list of ldns-testpkts entries. 295*be771a7bSCy Schubert * The first entry must be a query for DNSKEY. 296*be771a7bSCy Schubert * The answer rrset is the keyset that will be used for verification 297*be771a7bSCy Schubert */ 298*be771a7bSCy Schubert struct ub_packed_rrset_key* dnskey; 299*be771a7bSCy Schubert struct regional* region = regional_create(); 300*be771a7bSCy Schubert struct alloc_cache alloc; 301*be771a7bSCy Schubert sldns_buffer* buf = sldns_buffer_new(65535); 302*be771a7bSCy Schubert struct entry* e; 303*be771a7bSCy Schubert struct entry* list = read_datafile(fname, 1); 304*be771a7bSCy Schubert struct module_env env; 305*be771a7bSCy Schubert struct val_env ve; 306*be771a7bSCy Schubert time_t now = time(NULL); 307*be771a7bSCy Schubert unit_show_func("signature verify", fname); 308*be771a7bSCy Schubert 309*be771a7bSCy Schubert if(!list) 310*be771a7bSCy Schubert fatal_exit("could not read %s: %s", fname, strerror(errno)); 311*be771a7bSCy Schubert alloc_init(&alloc, NULL, 1); 312*be771a7bSCy Schubert memset(&env, 0, sizeof(env)); 313*be771a7bSCy Schubert memset(&ve, 0, sizeof(ve)); 314*be771a7bSCy Schubert env.scratch = region; 315*be771a7bSCy Schubert env.scratch_buffer = buf; 316*be771a7bSCy Schubert env.now = &now; 317*be771a7bSCy Schubert ve.date_override = cfg_convert_timeval(at_date); 318*be771a7bSCy Schubert unit_assert(region && buf); 319*be771a7bSCy Schubert dnskey = extract_keys(list, &alloc, region, buf); 320*be771a7bSCy Schubert if(vsig) log_nametypeclass(VERB_QUERY, "test dnskey", 321*be771a7bSCy Schubert dnskey->rk.dname, ntohs(dnskey->rk.type), 322*be771a7bSCy Schubert ntohs(dnskey->rk.rrset_class)); 323*be771a7bSCy Schubert /* ready to go! */ 324*be771a7bSCy Schubert for(e = list->next; e; e = e->next) { 325*be771a7bSCy Schubert verifytest_entry(e, &alloc, region, buf, dnskey, &env, &ve); 326*be771a7bSCy Schubert } 327*be771a7bSCy Schubert 328*be771a7bSCy Schubert ub_packed_rrset_parsedelete(dnskey, &alloc); 329*be771a7bSCy Schubert delete_entry(list); 330*be771a7bSCy Schubert regional_destroy(region); 331*be771a7bSCy Schubert alloc_clear(&alloc); 332*be771a7bSCy Schubert sldns_buffer_free(buf); 333*be771a7bSCy Schubert } 334*be771a7bSCy Schubert 335*be771a7bSCy Schubert /** verify DS matches DNSKEY from a file */ 336*be771a7bSCy Schubert static void 337*be771a7bSCy Schubert dstest_file(const char* fname) 338*be771a7bSCy Schubert { 339*be771a7bSCy Schubert /* 340*be771a7bSCy Schubert * The file contains a list of ldns-testpkts entries. 341*be771a7bSCy Schubert * The first entry must be a query for DNSKEY. 342*be771a7bSCy Schubert * The answer rrset is the keyset that will be used for verification 343*be771a7bSCy Schubert */ 344*be771a7bSCy Schubert struct regional* region = regional_create(); 345*be771a7bSCy Schubert struct alloc_cache alloc; 346*be771a7bSCy Schubert sldns_buffer* buf = sldns_buffer_new(65535); 347*be771a7bSCy Schubert struct entry* e; 348*be771a7bSCy Schubert struct entry* list = read_datafile(fname, 1); 349*be771a7bSCy Schubert struct module_env env; 350*be771a7bSCy Schubert unit_show_func("DS verify", fname); 351*be771a7bSCy Schubert 352*be771a7bSCy Schubert if(!list) 353*be771a7bSCy Schubert fatal_exit("could not read %s: %s", fname, strerror(errno)); 354*be771a7bSCy Schubert alloc_init(&alloc, NULL, 1); 355*be771a7bSCy Schubert memset(&env, 0, sizeof(env)); 356*be771a7bSCy Schubert env.scratch = region; 357*be771a7bSCy Schubert env.scratch_buffer = buf; 358*be771a7bSCy Schubert unit_assert(region && buf); 359*be771a7bSCy Schubert 360*be771a7bSCy Schubert /* ready to go! */ 361*be771a7bSCy Schubert for(e = list; e; e = e->next) { 362*be771a7bSCy Schubert dstest_entry(e, &alloc, region, buf, &env); 363*be771a7bSCy Schubert } 364*be771a7bSCy Schubert 365*be771a7bSCy Schubert delete_entry(list); 366*be771a7bSCy Schubert regional_destroy(region); 367*be771a7bSCy Schubert alloc_clear(&alloc); 368*be771a7bSCy Schubert sldns_buffer_free(buf); 369*be771a7bSCy Schubert } 370*be771a7bSCy Schubert 371*be771a7bSCy Schubert /** helper for unittest of NSEC routines */ 372*be771a7bSCy Schubert static int 373*be771a7bSCy Schubert unitest_nsec_has_type_rdata(char* bitmap, size_t len, uint16_t type) 374*be771a7bSCy Schubert { 375*be771a7bSCy Schubert return nsecbitmap_has_type_rdata((uint8_t*)bitmap, len, type); 376*be771a7bSCy Schubert } 377*be771a7bSCy Schubert 378*be771a7bSCy Schubert /** Test NSEC type bitmap routine */ 379*be771a7bSCy Schubert static void 380*be771a7bSCy Schubert nsectest(void) 381*be771a7bSCy Schubert { 382*be771a7bSCy Schubert /* bitmap starts at type bitmap rdata field */ 383*be771a7bSCy Schubert /* from rfc 4034 example */ 384*be771a7bSCy Schubert char* bitmap = "\000\006\100\001\000\000\000\003" 385*be771a7bSCy Schubert "\004\033\000\000\000\000\000\000" 386*be771a7bSCy Schubert "\000\000\000\000\000\000\000\000" 387*be771a7bSCy Schubert "\000\000\000\000\000\000\000\000" 388*be771a7bSCy Schubert "\000\000\000\000\040"; 389*be771a7bSCy Schubert size_t len = 37; 390*be771a7bSCy Schubert 391*be771a7bSCy Schubert unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 0)); 392*be771a7bSCy Schubert unit_assert(unitest_nsec_has_type_rdata(bitmap, len, LDNS_RR_TYPE_A)); 393*be771a7bSCy Schubert unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 2)); 394*be771a7bSCy Schubert unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 3)); 395*be771a7bSCy Schubert unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 4)); 396*be771a7bSCy Schubert unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 5)); 397*be771a7bSCy Schubert unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 6)); 398*be771a7bSCy Schubert unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 7)); 399*be771a7bSCy Schubert unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 8)); 400*be771a7bSCy Schubert unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 9)); 401*be771a7bSCy Schubert unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 10)); 402*be771a7bSCy Schubert unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 11)); 403*be771a7bSCy Schubert unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 12)); 404*be771a7bSCy Schubert unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 13)); 405*be771a7bSCy Schubert unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 14)); 406*be771a7bSCy Schubert unit_assert(unitest_nsec_has_type_rdata(bitmap, len, LDNS_RR_TYPE_MX)); 407*be771a7bSCy Schubert unit_assert(unitest_nsec_has_type_rdata(bitmap, len, LDNS_RR_TYPE_RRSIG)); 408*be771a7bSCy Schubert unit_assert(unitest_nsec_has_type_rdata(bitmap, len, LDNS_RR_TYPE_NSEC)); 409*be771a7bSCy Schubert unit_assert(unitest_nsec_has_type_rdata(bitmap, len, 1234)); 410*be771a7bSCy Schubert unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1233)); 411*be771a7bSCy Schubert unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1235)); 412*be771a7bSCy Schubert unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1236)); 413*be771a7bSCy Schubert unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1237)); 414*be771a7bSCy Schubert unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1238)); 415*be771a7bSCy Schubert unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1239)); 416*be771a7bSCy Schubert unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1240)); 417*be771a7bSCy Schubert unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 2230)); 418*be771a7bSCy Schubert } 419*be771a7bSCy Schubert 420*be771a7bSCy Schubert /** Test hash algo - NSEC3 hash it and compare result */ 421*be771a7bSCy Schubert static void 422*be771a7bSCy Schubert nsec3_hash_test_entry(struct entry* e, rbtree_type* ct, 423*be771a7bSCy Schubert struct alloc_cache* alloc, struct regional* region, 424*be771a7bSCy Schubert sldns_buffer* buf) 425*be771a7bSCy Schubert { 426*be771a7bSCy Schubert struct query_info qinfo; 427*be771a7bSCy Schubert struct reply_info* rep = NULL; 428*be771a7bSCy Schubert struct ub_packed_rrset_key* answer, *nsec3, *nsec3_region; 429*be771a7bSCy Schubert struct nsec3_cached_hash* hash = NULL; 430*be771a7bSCy Schubert int ret; 431*be771a7bSCy Schubert uint8_t* qname; 432*be771a7bSCy Schubert 433*be771a7bSCy Schubert if(vsig) { 434*be771a7bSCy Schubert char* s = sldns_wire2str_pkt(e->reply_list->reply_pkt, 435*be771a7bSCy Schubert e->reply_list->reply_len); 436*be771a7bSCy Schubert printf("verifying NSEC3 hash:\n%s\n", s?s:"outofmemory"); 437*be771a7bSCy Schubert free(s); 438*be771a7bSCy Schubert } 439*be771a7bSCy Schubert entry_to_repinfo(e, alloc, region, buf, &qinfo, &rep); 440*be771a7bSCy Schubert nsec3 = find_rrset_type(rep, LDNS_RR_TYPE_NSEC3); 441*be771a7bSCy Schubert answer = find_rrset_type(rep, LDNS_RR_TYPE_AAAA); 442*be771a7bSCy Schubert qname = regional_alloc_init(region, qinfo.qname, qinfo.qname_len); 443*be771a7bSCy Schubert /* check test is OK */ 444*be771a7bSCy Schubert unit_assert(nsec3 && answer && qname); 445*be771a7bSCy Schubert 446*be771a7bSCy Schubert /* Copy the nsec3 to the region, so it can stay referenced by the 447*be771a7bSCy Schubert * ct tree entry. The region is freed when the file is done. */ 448*be771a7bSCy Schubert nsec3_region = packed_rrset_copy_region(nsec3, region, 0); 449*be771a7bSCy Schubert 450*be771a7bSCy Schubert ret = nsec3_hash_name(ct, region, buf, nsec3_region, 0, qname, 451*be771a7bSCy Schubert qinfo.qname_len, &hash); 452*be771a7bSCy Schubert if(ret < 1) { 453*be771a7bSCy Schubert printf("Bad nsec3_hash_name retcode %d\n", ret); 454*be771a7bSCy Schubert unit_assert(ret == 1 || ret == 2); 455*be771a7bSCy Schubert } 456*be771a7bSCy Schubert unit_assert(hash->dname && hash->hash && hash->hash_len && 457*be771a7bSCy Schubert hash->b32 && hash->b32_len); 458*be771a7bSCy Schubert unit_assert(hash->b32_len == (size_t)answer->rk.dname[0]); 459*be771a7bSCy Schubert /* does not do lowercasing. */ 460*be771a7bSCy Schubert unit_assert(memcmp(hash->b32, answer->rk.dname+1, hash->b32_len) 461*be771a7bSCy Schubert == 0); 462*be771a7bSCy Schubert 463*be771a7bSCy Schubert reply_info_parsedelete(rep, alloc); 464*be771a7bSCy Schubert query_info_clear(&qinfo); 465*be771a7bSCy Schubert } 466*be771a7bSCy Schubert 467*be771a7bSCy Schubert 468*be771a7bSCy Schubert /** Read file to test NSEC3 hash algo */ 469*be771a7bSCy Schubert static void 470*be771a7bSCy Schubert nsec3_hash_test(const char* fname) 471*be771a7bSCy Schubert { 472*be771a7bSCy Schubert /* 473*be771a7bSCy Schubert * The list contains a list of ldns-testpkts entries. 474*be771a7bSCy Schubert * Every entry is a test. 475*be771a7bSCy Schubert * The qname is hashed. 476*be771a7bSCy Schubert * The answer section AAAA RR name is the required result. 477*be771a7bSCy Schubert * The auth section NSEC3 is used to get hash parameters. 478*be771a7bSCy Schubert * The hash cache is maintained per file. 479*be771a7bSCy Schubert * 480*be771a7bSCy Schubert * The test does not perform canonicalization during the compare. 481*be771a7bSCy Schubert */ 482*be771a7bSCy Schubert rbtree_type ct; 483*be771a7bSCy Schubert struct regional* region = regional_create(); 484*be771a7bSCy Schubert struct alloc_cache alloc; 485*be771a7bSCy Schubert sldns_buffer* buf = sldns_buffer_new(65535); 486*be771a7bSCy Schubert struct entry* e; 487*be771a7bSCy Schubert struct entry* list = read_datafile(fname, 1); 488*be771a7bSCy Schubert unit_show_func("NSEC3 hash", fname); 489*be771a7bSCy Schubert 490*be771a7bSCy Schubert if(!list) 491*be771a7bSCy Schubert fatal_exit("could not read %s: %s", fname, strerror(errno)); 492*be771a7bSCy Schubert rbtree_init(&ct, &nsec3_hash_cmp); 493*be771a7bSCy Schubert alloc_init(&alloc, NULL, 1); 494*be771a7bSCy Schubert unit_assert(region && buf); 495*be771a7bSCy Schubert 496*be771a7bSCy Schubert /* ready to go! */ 497*be771a7bSCy Schubert for(e = list; e; e = e->next) { 498*be771a7bSCy Schubert nsec3_hash_test_entry(e, &ct, &alloc, region, buf); 499*be771a7bSCy Schubert } 500*be771a7bSCy Schubert 501*be771a7bSCy Schubert delete_entry(list); 502*be771a7bSCy Schubert regional_destroy(region); 503*be771a7bSCy Schubert alloc_clear(&alloc); 504*be771a7bSCy Schubert sldns_buffer_free(buf); 505*be771a7bSCy Schubert } 506*be771a7bSCy Schubert 507*be771a7bSCy Schubert #define xstr(s) str(s) 508*be771a7bSCy Schubert #define str(s) #s 509*be771a7bSCy Schubert 510*be771a7bSCy Schubert #define SRCDIRSTR xstr(SRCDIR) 511*be771a7bSCy Schubert 512*be771a7bSCy Schubert void 513*be771a7bSCy Schubert verify_test(void) 514*be771a7bSCy Schubert { 515*be771a7bSCy Schubert unit_show_feature("signature verify"); 516*be771a7bSCy Schubert #ifdef USE_SHA1 517*be771a7bSCy Schubert verifytest_file(SRCDIRSTR "/testdata/test_signatures.1", "20070818005004"); 518*be771a7bSCy Schubert #endif 519*be771a7bSCy Schubert #if defined(USE_DSA) && defined(USE_SHA1) 520*be771a7bSCy Schubert verifytest_file(SRCDIRSTR "/testdata/test_signatures.2", "20080414005004"); 521*be771a7bSCy Schubert verifytest_file(SRCDIRSTR "/testdata/test_signatures.3", "20080416005004"); 522*be771a7bSCy Schubert verifytest_file(SRCDIRSTR "/testdata/test_signatures.4", "20080416005004"); 523*be771a7bSCy Schubert verifytest_file(SRCDIRSTR "/testdata/test_signatures.5", "20080416005004"); 524*be771a7bSCy Schubert verifytest_file(SRCDIRSTR "/testdata/test_signatures.6", "20080416005004"); 525*be771a7bSCy Schubert verifytest_file(SRCDIRSTR "/testdata/test_signatures.7", "20070829144150"); 526*be771a7bSCy Schubert #endif /* USE_DSA */ 527*be771a7bSCy Schubert #ifdef USE_SHA1 528*be771a7bSCy Schubert verifytest_file(SRCDIRSTR "/testdata/test_signatures.8", "20070829144150"); 529*be771a7bSCy Schubert #endif 530*be771a7bSCy Schubert #if (defined(HAVE_EVP_SHA256) || defined(HAVE_NSS) || defined(HAVE_NETTLE)) && defined(USE_SHA2) 531*be771a7bSCy Schubert verifytest_file(SRCDIRSTR "/testdata/test_sigs.rsasha256", "20070829144150"); 532*be771a7bSCy Schubert # ifdef USE_SHA1 533*be771a7bSCy Schubert verifytest_file(SRCDIRSTR "/testdata/test_sigs.sha1_and_256", "20070829144150"); 534*be771a7bSCy Schubert # endif 535*be771a7bSCy Schubert verifytest_file(SRCDIRSTR "/testdata/test_sigs.rsasha256_draft", "20090101000000"); 536*be771a7bSCy Schubert #endif 537*be771a7bSCy Schubert #if (defined(HAVE_EVP_SHA512) || defined(HAVE_NSS) || defined(HAVE_NETTLE)) && defined(USE_SHA2) 538*be771a7bSCy Schubert verifytest_file(SRCDIRSTR "/testdata/test_sigs.rsasha512_draft", "20070829144150"); 539*be771a7bSCy Schubert verifytest_file(SRCDIRSTR "/testdata/test_signatures.9", "20171215000000"); 540*be771a7bSCy Schubert #endif 541*be771a7bSCy Schubert #ifdef USE_SHA1 542*be771a7bSCy Schubert verifytest_file(SRCDIRSTR "/testdata/test_sigs.hinfo", "20090107100022"); 543*be771a7bSCy Schubert verifytest_file(SRCDIRSTR "/testdata/test_sigs.revoked", "20080414005004"); 544*be771a7bSCy Schubert #endif 545*be771a7bSCy Schubert #ifdef USE_GOST 546*be771a7bSCy Schubert if(sldns_key_EVP_load_gost_id()) 547*be771a7bSCy Schubert verifytest_file(SRCDIRSTR "/testdata/test_sigs.gost", "20090807060504"); 548*be771a7bSCy Schubert else printf("Warning: skipped GOST, openssl does not provide gost.\n"); 549*be771a7bSCy Schubert #endif 550*be771a7bSCy Schubert #ifdef USE_ECDSA 551*be771a7bSCy Schubert /* test for support in case we use libNSS and ECC is removed */ 552*be771a7bSCy Schubert if(dnskey_algo_id_is_supported(LDNS_ECDSAP256SHA256)) { 553*be771a7bSCy Schubert verifytest_file(SRCDIRSTR "/testdata/test_sigs.ecdsa_p256", "20100908100439"); 554*be771a7bSCy Schubert verifytest_file(SRCDIRSTR "/testdata/test_sigs.ecdsa_p384", "20100908100439"); 555*be771a7bSCy Schubert } 556*be771a7bSCy Schubert dstest_file(SRCDIRSTR "/testdata/test_ds.sha384"); 557*be771a7bSCy Schubert #endif 558*be771a7bSCy Schubert #ifdef USE_ED25519 559*be771a7bSCy Schubert if(dnskey_algo_id_is_supported(LDNS_ED25519)) { 560*be771a7bSCy Schubert verifytest_file(SRCDIRSTR "/testdata/test_sigs.ed25519", "20170530140439"); 561*be771a7bSCy Schubert } 562*be771a7bSCy Schubert #endif 563*be771a7bSCy Schubert #ifdef USE_ED448 564*be771a7bSCy Schubert if(dnskey_algo_id_is_supported(LDNS_ED448)) { 565*be771a7bSCy Schubert verifytest_file(SRCDIRSTR "/testdata/test_sigs.ed448", "20180408143630"); 566*be771a7bSCy Schubert } 567*be771a7bSCy Schubert #endif 568*be771a7bSCy Schubert #ifdef USE_SHA1 569*be771a7bSCy Schubert dstest_file(SRCDIRSTR "/testdata/test_ds.sha1"); 570*be771a7bSCy Schubert #endif 571*be771a7bSCy Schubert nsectest(); 572*be771a7bSCy Schubert nsec3_hash_test(SRCDIRSTR "/testdata/test_nsec3_hash.1"); 573*be771a7bSCy Schubert } 574