1712b2f30Ssthen /* 2712b2f30Ssthen * testcode/unitverify.c - unit test for signature verification routines. 3712b2f30Ssthen * 4712b2f30Ssthen * Copyright (c) 2007, NLnet Labs. All rights reserved. 5712b2f30Ssthen * 6712b2f30Ssthen * This software is open source. 7712b2f30Ssthen * 8712b2f30Ssthen * Redistribution and use in source and binary forms, with or without 9712b2f30Ssthen * modification, are permitted provided that the following conditions 10712b2f30Ssthen * are met: 11712b2f30Ssthen * 12712b2f30Ssthen * Redistributions of source code must retain the above copyright notice, 13712b2f30Ssthen * this list of conditions and the following disclaimer. 14712b2f30Ssthen * 15712b2f30Ssthen * Redistributions in binary form must reproduce the above copyright notice, 16712b2f30Ssthen * this list of conditions and the following disclaimer in the documentation 17712b2f30Ssthen * and/or other materials provided with the distribution. 18712b2f30Ssthen * 19712b2f30Ssthen * Neither the name of the NLNET LABS nor the names of its contributors may 20712b2f30Ssthen * be used to endorse or promote products derived from this software without 21712b2f30Ssthen * specific prior written permission. 22712b2f30Ssthen * 23712b2f30Ssthen * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24712b2f30Ssthen * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25712b2f30Ssthen * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26712b2f30Ssthen * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27712b2f30Ssthen * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28712b2f30Ssthen * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29712b2f30Ssthen * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30712b2f30Ssthen * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31712b2f30Ssthen * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32712b2f30Ssthen * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33712b2f30Ssthen * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34712b2f30Ssthen * 35712b2f30Ssthen */ 36712b2f30Ssthen /** 37712b2f30Ssthen * \file 38712b2f30Ssthen * Calls verification unit tests. Exits with code 1 on a failure. 39712b2f30Ssthen */ 40712b2f30Ssthen 41712b2f30Ssthen #include "config.h" 42712b2f30Ssthen #include "util/log.h" 43712b2f30Ssthen #include "testcode/unitmain.h" 44712b2f30Ssthen #include "validator/val_sigcrypt.h" 45712b2f30Ssthen #include "validator/val_secalgo.h" 46712b2f30Ssthen #include "validator/val_nsec.h" 47712b2f30Ssthen #include "validator/val_nsec3.h" 48712b2f30Ssthen #include "validator/validator.h" 49712b2f30Ssthen #include "testcode/testpkts.h" 50712b2f30Ssthen #include "util/data/msgreply.h" 51712b2f30Ssthen #include "util/data/msgparse.h" 52712b2f30Ssthen #include "util/data/dname.h" 53712b2f30Ssthen #include "util/regional.h" 54712b2f30Ssthen #include "util/alloc.h" 55712b2f30Ssthen #include "util/rbtree.h" 56712b2f30Ssthen #include "util/net_help.h" 57712b2f30Ssthen #include "util/module.h" 58712b2f30Ssthen #include "util/config_file.h" 59712b2f30Ssthen #include "sldns/sbuffer.h" 60712b2f30Ssthen #include "sldns/keyraw.h" 61712b2f30Ssthen #include "sldns/str2wire.h" 62712b2f30Ssthen #include "sldns/wire2str.h" 63712b2f30Ssthen 64712b2f30Ssthen /** verbose signature test */ 65712b2f30Ssthen static int vsig = 0; 66712b2f30Ssthen 67712b2f30Ssthen /** entry to packet buffer with wireformat */ 68712b2f30Ssthen static void 69712b2f30Ssthen entry_to_buf(struct entry* e, sldns_buffer* pkt) 70712b2f30Ssthen { 71712b2f30Ssthen unit_assert(e->reply_list); 72712b2f30Ssthen if(e->reply_list->reply_from_hex) { 73712b2f30Ssthen sldns_buffer_copy(pkt, e->reply_list->reply_from_hex); 74712b2f30Ssthen } else { 75712b2f30Ssthen sldns_buffer_clear(pkt); 76712b2f30Ssthen sldns_buffer_write(pkt, e->reply_list->reply_pkt, 77712b2f30Ssthen e->reply_list->reply_len); 78712b2f30Ssthen sldns_buffer_flip(pkt); 79712b2f30Ssthen } 80712b2f30Ssthen } 81712b2f30Ssthen 82712b2f30Ssthen /** entry to reply info conversion */ 83712b2f30Ssthen static void 84712b2f30Ssthen entry_to_repinfo(struct entry* e, struct alloc_cache* alloc, 85712b2f30Ssthen struct regional* region, sldns_buffer* pkt, struct query_info* qi, 86712b2f30Ssthen struct reply_info** rep) 87712b2f30Ssthen { 88712b2f30Ssthen int ret; 89712b2f30Ssthen struct edns_data edns; 90712b2f30Ssthen entry_to_buf(e, pkt); 91712b2f30Ssthen /* lock alloc lock to please lock checking software. 92712b2f30Ssthen * alloc_special_obtain assumes it is talking to a ub-alloc, 93712b2f30Ssthen * and does not need to perform locking. Here the alloc is 94712b2f30Ssthen * the only one, so we lock it here */ 95712b2f30Ssthen lock_quick_lock(&alloc->lock); 96712b2f30Ssthen ret = reply_info_parse(pkt, alloc, qi, rep, region, &edns); 97712b2f30Ssthen lock_quick_unlock(&alloc->lock); 98712b2f30Ssthen if(ret != 0) { 99712b2f30Ssthen char rcode[16]; 100712b2f30Ssthen sldns_wire2str_rcode_buf(ret, rcode, sizeof(rcode)); 101712b2f30Ssthen printf("parse code %d: %s\n", ret, rcode); 102712b2f30Ssthen unit_assert(ret != 0); 103712b2f30Ssthen } 104712b2f30Ssthen } 105712b2f30Ssthen 106712b2f30Ssthen /** extract DNSKEY rrset from answer and convert it */ 107712b2f30Ssthen static struct ub_packed_rrset_key* 108712b2f30Ssthen extract_keys(struct entry* e, struct alloc_cache* alloc, 109712b2f30Ssthen struct regional* region, sldns_buffer* pkt) 110712b2f30Ssthen { 111712b2f30Ssthen struct ub_packed_rrset_key* dnskey = NULL; 112712b2f30Ssthen struct query_info qinfo; 113712b2f30Ssthen struct reply_info* rep = NULL; 114712b2f30Ssthen size_t i; 115712b2f30Ssthen 116712b2f30Ssthen entry_to_repinfo(e, alloc, region, pkt, &qinfo, &rep); 117712b2f30Ssthen for(i=0; i<rep->an_numrrsets; i++) { 118712b2f30Ssthen if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_DNSKEY) { 119712b2f30Ssthen dnskey = rep->rrsets[i]; 120712b2f30Ssthen rep->rrsets[i] = NULL; 121712b2f30Ssthen break; 122712b2f30Ssthen } 123712b2f30Ssthen } 124712b2f30Ssthen unit_assert(dnskey); 125712b2f30Ssthen 126712b2f30Ssthen reply_info_parsedelete(rep, alloc); 127712b2f30Ssthen query_info_clear(&qinfo); 128712b2f30Ssthen return dnskey; 129712b2f30Ssthen } 130712b2f30Ssthen 131712b2f30Ssthen /** return true if answer should be bogus */ 132712b2f30Ssthen static int 133712b2f30Ssthen should_be_bogus(struct ub_packed_rrset_key* rrset, struct query_info* qinfo) 134712b2f30Ssthen { 135712b2f30Ssthen struct packed_rrset_data* d = (struct packed_rrset_data*)rrset-> 136712b2f30Ssthen entry.data; 137712b2f30Ssthen if(d->rrsig_count == 0) 138712b2f30Ssthen return 1; 139712b2f30Ssthen /* name 'bogus' as first label signals bogus */ 140712b2f30Ssthen if(rrset->rk.dname_len > 6 && memcmp(rrset->rk.dname+1, "bogus", 5)==0) 141712b2f30Ssthen return 1; 142712b2f30Ssthen if(qinfo->qname_len > 6 && memcmp(qinfo->qname+1, "bogus", 5)==0) 143712b2f30Ssthen return 1; 144712b2f30Ssthen return 0; 145712b2f30Ssthen } 146712b2f30Ssthen 147712b2f30Ssthen /** return number of rrs in an rrset */ 148712b2f30Ssthen static size_t 149712b2f30Ssthen rrset_get_count(struct ub_packed_rrset_key* rrset) 150712b2f30Ssthen { 151712b2f30Ssthen struct packed_rrset_data* d = (struct packed_rrset_data*) 152712b2f30Ssthen rrset->entry.data; 153712b2f30Ssthen if(!d) return 0; 154712b2f30Ssthen return d->count; 155712b2f30Ssthen } 156712b2f30Ssthen 157712b2f30Ssthen /** setup sig alg list from dnskey */ 158712b2f30Ssthen static void 159712b2f30Ssthen setup_sigalg(struct ub_packed_rrset_key* dnskey, uint8_t* sigalg) 160712b2f30Ssthen { 161712b2f30Ssthen uint8_t a[ALGO_NEEDS_MAX]; 162712b2f30Ssthen size_t i, n = 0; 163712b2f30Ssthen memset(a, 0, sizeof(a)); 164712b2f30Ssthen for(i=0; i<rrset_get_count(dnskey); i++) { 165712b2f30Ssthen uint8_t algo = (uint8_t)dnskey_get_algo(dnskey, i); 166712b2f30Ssthen if(a[algo] == 0) { 167712b2f30Ssthen a[algo] = 1; 168712b2f30Ssthen sigalg[n++] = algo; 169712b2f30Ssthen } 170712b2f30Ssthen } 171712b2f30Ssthen sigalg[n] = 0; 172712b2f30Ssthen } 173712b2f30Ssthen 174712b2f30Ssthen /** verify and test one rrset against the key rrset */ 175712b2f30Ssthen static void 176712b2f30Ssthen verifytest_rrset(struct module_env* env, struct val_env* ve, 177712b2f30Ssthen struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey, 178712b2f30Ssthen struct query_info* qinfo) 179712b2f30Ssthen { 180712b2f30Ssthen enum sec_status sec; 181*98bc733bSsthen char reasonbuf[256]; 182712b2f30Ssthen char* reason = NULL; 183712b2f30Ssthen uint8_t sigalg[ALGO_NEEDS_MAX+1]; 184817bdb8fSflorian int verified = 0; 185712b2f30Ssthen if(vsig) { 186712b2f30Ssthen log_nametypeclass(VERB_QUERY, "verify of rrset", 187712b2f30Ssthen rrset->rk.dname, ntohs(rrset->rk.type), 188712b2f30Ssthen ntohs(rrset->rk.rrset_class)); 189712b2f30Ssthen } 190712b2f30Ssthen setup_sigalg(dnskey, sigalg); /* check all algorithms in the dnskey */ 191712b2f30Ssthen /* ok to give null as qstate here, won't be used for answer section. */ 192*98bc733bSsthen sec = dnskeyset_verify_rrset(env, ve, rrset, dnskey, sigalg, &reason, 193*98bc733bSsthen NULL, LDNS_SECTION_ANSWER, NULL, &verified, reasonbuf, 194*98bc733bSsthen sizeof(reasonbuf)); 195712b2f30Ssthen if(vsig) { 196712b2f30Ssthen printf("verify outcome is: %s %s\n", sec_status_to_string(sec), 197712b2f30Ssthen reason?reason:""); 198712b2f30Ssthen } 199712b2f30Ssthen if(should_be_bogus(rrset, qinfo)) { 200712b2f30Ssthen unit_assert(sec == sec_status_bogus); 201712b2f30Ssthen } else { 202712b2f30Ssthen unit_assert(sec == sec_status_secure); 203712b2f30Ssthen } 204712b2f30Ssthen } 205712b2f30Ssthen 206712b2f30Ssthen /** verify and test an entry - every rr in the message */ 207712b2f30Ssthen static void 208712b2f30Ssthen verifytest_entry(struct entry* e, struct alloc_cache* alloc, 209712b2f30Ssthen struct regional* region, sldns_buffer* pkt, 210712b2f30Ssthen struct ub_packed_rrset_key* dnskey, struct module_env* env, 211712b2f30Ssthen struct val_env* ve) 212712b2f30Ssthen { 213712b2f30Ssthen struct query_info qinfo; 214712b2f30Ssthen struct reply_info* rep = NULL; 215712b2f30Ssthen size_t i; 216712b2f30Ssthen 217712b2f30Ssthen regional_free_all(region); 218712b2f30Ssthen if(vsig) { 219712b2f30Ssthen char* s = sldns_wire2str_pkt(e->reply_list->reply_pkt, 220712b2f30Ssthen e->reply_list->reply_len); 221712b2f30Ssthen printf("verifying pkt:\n%s\n", s?s:"outofmemory"); 222712b2f30Ssthen free(s); 223712b2f30Ssthen } 224712b2f30Ssthen entry_to_repinfo(e, alloc, region, pkt, &qinfo, &rep); 225712b2f30Ssthen 226712b2f30Ssthen for(i=0; i<rep->rrset_count; i++) { 227712b2f30Ssthen verifytest_rrset(env, ve, rep->rrsets[i], dnskey, &qinfo); 228712b2f30Ssthen } 229712b2f30Ssthen 230712b2f30Ssthen reply_info_parsedelete(rep, alloc); 231712b2f30Ssthen query_info_clear(&qinfo); 232712b2f30Ssthen } 233712b2f30Ssthen 234712b2f30Ssthen /** find RRset in reply by type */ 235712b2f30Ssthen static struct ub_packed_rrset_key* 236712b2f30Ssthen find_rrset_type(struct reply_info* rep, uint16_t type) 237712b2f30Ssthen { 238712b2f30Ssthen size_t i; 239712b2f30Ssthen for(i=0; i<rep->rrset_count; i++) { 240712b2f30Ssthen if(ntohs(rep->rrsets[i]->rk.type) == type) 241712b2f30Ssthen return rep->rrsets[i]; 242712b2f30Ssthen } 243712b2f30Ssthen return NULL; 244712b2f30Ssthen } 245712b2f30Ssthen 246712b2f30Ssthen /** DS sig test an entry - get DNSKEY and DS in entry and verify */ 247712b2f30Ssthen static void 248712b2f30Ssthen dstest_entry(struct entry* e, struct alloc_cache* alloc, 249712b2f30Ssthen struct regional* region, sldns_buffer* pkt, struct module_env* env) 250712b2f30Ssthen { 251712b2f30Ssthen struct query_info qinfo; 252712b2f30Ssthen struct reply_info* rep = NULL; 253712b2f30Ssthen struct ub_packed_rrset_key* ds, *dnskey; 254712b2f30Ssthen int ret; 255712b2f30Ssthen 256712b2f30Ssthen regional_free_all(region); 257712b2f30Ssthen if(vsig) { 258712b2f30Ssthen char* s = sldns_wire2str_pkt(e->reply_list->reply_pkt, 259712b2f30Ssthen e->reply_list->reply_len); 260712b2f30Ssthen printf("verifying DS-DNSKEY match:\n%s\n", s?s:"outofmemory"); 261712b2f30Ssthen free(s); 262712b2f30Ssthen } 263712b2f30Ssthen entry_to_repinfo(e, alloc, region, pkt, &qinfo, &rep); 264712b2f30Ssthen ds = find_rrset_type(rep, LDNS_RR_TYPE_DS); 265712b2f30Ssthen dnskey = find_rrset_type(rep, LDNS_RR_TYPE_DNSKEY); 266712b2f30Ssthen /* check test is OK */ 267712b2f30Ssthen unit_assert(ds && dnskey); 268712b2f30Ssthen 269712b2f30Ssthen ret = ds_digest_match_dnskey(env, dnskey, 0, ds, 0); 270712b2f30Ssthen if(strncmp((char*)qinfo.qname, "\003yes", 4) == 0) { 271712b2f30Ssthen if(vsig) { 272712b2f30Ssthen printf("result(yes)= %s\n", ret?"yes":"no"); 273712b2f30Ssthen } 274712b2f30Ssthen unit_assert(ret); 275712b2f30Ssthen } else if (strncmp((char*)qinfo.qname, "\002no", 3) == 0) { 276712b2f30Ssthen if(vsig) { 277712b2f30Ssthen printf("result(no)= %s\n", ret?"yes":"no"); 278712b2f30Ssthen } 279712b2f30Ssthen unit_assert(!ret); 280712b2f30Ssthen verbose(VERB_QUERY, "DS fail: OK; matched unit test"); 281712b2f30Ssthen } else { 282712b2f30Ssthen fatal_exit("Bad qname in DS unit test, yes or no"); 283712b2f30Ssthen } 284712b2f30Ssthen 285712b2f30Ssthen reply_info_parsedelete(rep, alloc); 286712b2f30Ssthen query_info_clear(&qinfo); 287712b2f30Ssthen } 288712b2f30Ssthen 289712b2f30Ssthen /** verify from a file */ 290712b2f30Ssthen static void 291712b2f30Ssthen verifytest_file(const char* fname, const char* at_date) 292712b2f30Ssthen { 293712b2f30Ssthen /* 294712b2f30Ssthen * The file contains a list of ldns-testpkts entries. 295712b2f30Ssthen * The first entry must be a query for DNSKEY. 296712b2f30Ssthen * The answer rrset is the keyset that will be used for verification 297712b2f30Ssthen */ 298712b2f30Ssthen struct ub_packed_rrset_key* dnskey; 299712b2f30Ssthen struct regional* region = regional_create(); 300712b2f30Ssthen struct alloc_cache alloc; 301712b2f30Ssthen sldns_buffer* buf = sldns_buffer_new(65535); 302712b2f30Ssthen struct entry* e; 303712b2f30Ssthen struct entry* list = read_datafile(fname, 1); 304712b2f30Ssthen struct module_env env; 305712b2f30Ssthen struct val_env ve; 306712b2f30Ssthen time_t now = time(NULL); 307712b2f30Ssthen unit_show_func("signature verify", fname); 308712b2f30Ssthen 309712b2f30Ssthen if(!list) 310712b2f30Ssthen fatal_exit("could not read %s: %s", fname, strerror(errno)); 311712b2f30Ssthen alloc_init(&alloc, NULL, 1); 312712b2f30Ssthen memset(&env, 0, sizeof(env)); 313712b2f30Ssthen memset(&ve, 0, sizeof(ve)); 314712b2f30Ssthen env.scratch = region; 315712b2f30Ssthen env.scratch_buffer = buf; 316712b2f30Ssthen env.now = &now; 317712b2f30Ssthen ve.date_override = cfg_convert_timeval(at_date); 318712b2f30Ssthen unit_assert(region && buf); 319712b2f30Ssthen dnskey = extract_keys(list, &alloc, region, buf); 320712b2f30Ssthen if(vsig) log_nametypeclass(VERB_QUERY, "test dnskey", 321712b2f30Ssthen dnskey->rk.dname, ntohs(dnskey->rk.type), 322712b2f30Ssthen ntohs(dnskey->rk.rrset_class)); 323712b2f30Ssthen /* ready to go! */ 324712b2f30Ssthen for(e = list->next; e; e = e->next) { 325712b2f30Ssthen verifytest_entry(e, &alloc, region, buf, dnskey, &env, &ve); 326712b2f30Ssthen } 327712b2f30Ssthen 328712b2f30Ssthen ub_packed_rrset_parsedelete(dnskey, &alloc); 329712b2f30Ssthen delete_entry(list); 330712b2f30Ssthen regional_destroy(region); 331712b2f30Ssthen alloc_clear(&alloc); 332712b2f30Ssthen sldns_buffer_free(buf); 333712b2f30Ssthen } 334712b2f30Ssthen 335712b2f30Ssthen /** verify DS matches DNSKEY from a file */ 336712b2f30Ssthen static void 337712b2f30Ssthen dstest_file(const char* fname) 338712b2f30Ssthen { 339712b2f30Ssthen /* 340712b2f30Ssthen * The file contains a list of ldns-testpkts entries. 341712b2f30Ssthen * The first entry must be a query for DNSKEY. 342712b2f30Ssthen * The answer rrset is the keyset that will be used for verification 343712b2f30Ssthen */ 344712b2f30Ssthen struct regional* region = regional_create(); 345712b2f30Ssthen struct alloc_cache alloc; 346712b2f30Ssthen sldns_buffer* buf = sldns_buffer_new(65535); 347712b2f30Ssthen struct entry* e; 348712b2f30Ssthen struct entry* list = read_datafile(fname, 1); 349712b2f30Ssthen struct module_env env; 350712b2f30Ssthen unit_show_func("DS verify", fname); 351712b2f30Ssthen 352712b2f30Ssthen if(!list) 353712b2f30Ssthen fatal_exit("could not read %s: %s", fname, strerror(errno)); 354712b2f30Ssthen alloc_init(&alloc, NULL, 1); 355712b2f30Ssthen memset(&env, 0, sizeof(env)); 356712b2f30Ssthen env.scratch = region; 357712b2f30Ssthen env.scratch_buffer = buf; 358712b2f30Ssthen unit_assert(region && buf); 359712b2f30Ssthen 360712b2f30Ssthen /* ready to go! */ 361712b2f30Ssthen for(e = list; e; e = e->next) { 362712b2f30Ssthen dstest_entry(e, &alloc, region, buf, &env); 363712b2f30Ssthen } 364712b2f30Ssthen 365712b2f30Ssthen delete_entry(list); 366712b2f30Ssthen regional_destroy(region); 367712b2f30Ssthen alloc_clear(&alloc); 368712b2f30Ssthen sldns_buffer_free(buf); 369712b2f30Ssthen } 370712b2f30Ssthen 371712b2f30Ssthen /** helper for unittest of NSEC routines */ 372712b2f30Ssthen static int 373712b2f30Ssthen unitest_nsec_has_type_rdata(char* bitmap, size_t len, uint16_t type) 374712b2f30Ssthen { 375712b2f30Ssthen return nsecbitmap_has_type_rdata((uint8_t*)bitmap, len, type); 376712b2f30Ssthen } 377712b2f30Ssthen 378712b2f30Ssthen /** Test NSEC type bitmap routine */ 379712b2f30Ssthen static void 380712b2f30Ssthen nsectest(void) 381712b2f30Ssthen { 382712b2f30Ssthen /* bitmap starts at type bitmap rdata field */ 383712b2f30Ssthen /* from rfc 4034 example */ 384712b2f30Ssthen char* bitmap = "\000\006\100\001\000\000\000\003" 385712b2f30Ssthen "\004\033\000\000\000\000\000\000" 386712b2f30Ssthen "\000\000\000\000\000\000\000\000" 387712b2f30Ssthen "\000\000\000\000\000\000\000\000" 388712b2f30Ssthen "\000\000\000\000\040"; 389712b2f30Ssthen size_t len = 37; 390712b2f30Ssthen 391712b2f30Ssthen unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 0)); 392712b2f30Ssthen unit_assert(unitest_nsec_has_type_rdata(bitmap, len, LDNS_RR_TYPE_A)); 393712b2f30Ssthen unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 2)); 394712b2f30Ssthen unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 3)); 395712b2f30Ssthen unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 4)); 396712b2f30Ssthen unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 5)); 397712b2f30Ssthen unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 6)); 398712b2f30Ssthen unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 7)); 399712b2f30Ssthen unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 8)); 400712b2f30Ssthen unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 9)); 401712b2f30Ssthen unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 10)); 402712b2f30Ssthen unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 11)); 403712b2f30Ssthen unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 12)); 404712b2f30Ssthen unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 13)); 405712b2f30Ssthen unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 14)); 406712b2f30Ssthen unit_assert(unitest_nsec_has_type_rdata(bitmap, len, LDNS_RR_TYPE_MX)); 407712b2f30Ssthen unit_assert(unitest_nsec_has_type_rdata(bitmap, len, LDNS_RR_TYPE_RRSIG)); 408712b2f30Ssthen unit_assert(unitest_nsec_has_type_rdata(bitmap, len, LDNS_RR_TYPE_NSEC)); 409712b2f30Ssthen unit_assert(unitest_nsec_has_type_rdata(bitmap, len, 1234)); 410712b2f30Ssthen unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1233)); 411712b2f30Ssthen unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1235)); 412712b2f30Ssthen unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1236)); 413712b2f30Ssthen unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1237)); 414712b2f30Ssthen unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1238)); 415712b2f30Ssthen unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1239)); 416712b2f30Ssthen unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1240)); 417712b2f30Ssthen unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 2230)); 418712b2f30Ssthen } 419712b2f30Ssthen 420712b2f30Ssthen /** Test hash algo - NSEC3 hash it and compare result */ 421712b2f30Ssthen static void 422712b2f30Ssthen nsec3_hash_test_entry(struct entry* e, rbtree_type* ct, 423712b2f30Ssthen struct alloc_cache* alloc, struct regional* region, 424712b2f30Ssthen sldns_buffer* buf) 425712b2f30Ssthen { 426712b2f30Ssthen struct query_info qinfo; 427712b2f30Ssthen struct reply_info* rep = NULL; 428712b2f30Ssthen struct ub_packed_rrset_key* answer, *nsec3; 429712b2f30Ssthen struct nsec3_cached_hash* hash = NULL; 430712b2f30Ssthen int ret; 431712b2f30Ssthen uint8_t* qname; 432712b2f30Ssthen 433712b2f30Ssthen if(vsig) { 434712b2f30Ssthen char* s = sldns_wire2str_pkt(e->reply_list->reply_pkt, 435712b2f30Ssthen e->reply_list->reply_len); 436712b2f30Ssthen printf("verifying NSEC3 hash:\n%s\n", s?s:"outofmemory"); 437712b2f30Ssthen free(s); 438712b2f30Ssthen } 439712b2f30Ssthen entry_to_repinfo(e, alloc, region, buf, &qinfo, &rep); 440712b2f30Ssthen nsec3 = find_rrset_type(rep, LDNS_RR_TYPE_NSEC3); 441712b2f30Ssthen answer = find_rrset_type(rep, LDNS_RR_TYPE_AAAA); 442712b2f30Ssthen qname = regional_alloc_init(region, qinfo.qname, qinfo.qname_len); 443712b2f30Ssthen /* check test is OK */ 444712b2f30Ssthen unit_assert(nsec3 && answer && qname); 445712b2f30Ssthen 446712b2f30Ssthen ret = nsec3_hash_name(ct, region, buf, nsec3, 0, qname, 447712b2f30Ssthen qinfo.qname_len, &hash); 448817bdb8fSflorian if(ret < 1) { 449712b2f30Ssthen printf("Bad nsec3_hash_name retcode %d\n", ret); 450817bdb8fSflorian unit_assert(ret == 1 || ret == 2); 451712b2f30Ssthen } 452712b2f30Ssthen unit_assert(hash->dname && hash->hash && hash->hash_len && 453712b2f30Ssthen hash->b32 && hash->b32_len); 454712b2f30Ssthen unit_assert(hash->b32_len == (size_t)answer->rk.dname[0]); 455712b2f30Ssthen /* does not do lowercasing. */ 456712b2f30Ssthen unit_assert(memcmp(hash->b32, answer->rk.dname+1, hash->b32_len) 457712b2f30Ssthen == 0); 458712b2f30Ssthen 459712b2f30Ssthen reply_info_parsedelete(rep, alloc); 460712b2f30Ssthen query_info_clear(&qinfo); 461712b2f30Ssthen } 462712b2f30Ssthen 463712b2f30Ssthen 464712b2f30Ssthen /** Read file to test NSEC3 hash algo */ 465712b2f30Ssthen static void 466712b2f30Ssthen nsec3_hash_test(const char* fname) 467712b2f30Ssthen { 468712b2f30Ssthen /* 469712b2f30Ssthen * The list contains a list of ldns-testpkts entries. 470712b2f30Ssthen * Every entry is a test. 471712b2f30Ssthen * The qname is hashed. 472712b2f30Ssthen * The answer section AAAA RR name is the required result. 473712b2f30Ssthen * The auth section NSEC3 is used to get hash parameters. 474712b2f30Ssthen * The hash cache is maintained per file. 475712b2f30Ssthen * 476712b2f30Ssthen * The test does not perform canonicalization during the compare. 477712b2f30Ssthen */ 478712b2f30Ssthen rbtree_type ct; 479712b2f30Ssthen struct regional* region = regional_create(); 480712b2f30Ssthen struct alloc_cache alloc; 481712b2f30Ssthen sldns_buffer* buf = sldns_buffer_new(65535); 482712b2f30Ssthen struct entry* e; 483712b2f30Ssthen struct entry* list = read_datafile(fname, 1); 484712b2f30Ssthen unit_show_func("NSEC3 hash", fname); 485712b2f30Ssthen 486712b2f30Ssthen if(!list) 487712b2f30Ssthen fatal_exit("could not read %s: %s", fname, strerror(errno)); 488712b2f30Ssthen rbtree_init(&ct, &nsec3_hash_cmp); 489712b2f30Ssthen alloc_init(&alloc, NULL, 1); 490712b2f30Ssthen unit_assert(region && buf); 491712b2f30Ssthen 492712b2f30Ssthen /* ready to go! */ 493712b2f30Ssthen for(e = list; e; e = e->next) { 494712b2f30Ssthen nsec3_hash_test_entry(e, &ct, &alloc, region, buf); 495712b2f30Ssthen } 496712b2f30Ssthen 497712b2f30Ssthen delete_entry(list); 498712b2f30Ssthen regional_destroy(region); 499712b2f30Ssthen alloc_clear(&alloc); 500712b2f30Ssthen sldns_buffer_free(buf); 501712b2f30Ssthen } 502712b2f30Ssthen 5037bc20e6dSsthen #define xstr(s) str(s) 5047bc20e6dSsthen #define str(s) #s 5057bc20e6dSsthen 5067bc20e6dSsthen #define SRCDIRSTR xstr(SRCDIR) 5077bc20e6dSsthen 508712b2f30Ssthen void 509712b2f30Ssthen verify_test(void) 510712b2f30Ssthen { 511712b2f30Ssthen unit_show_feature("signature verify"); 512712b2f30Ssthen #ifdef USE_SHA1 5137bc20e6dSsthen verifytest_file(SRCDIRSTR "/testdata/test_signatures.1", "20070818005004"); 514712b2f30Ssthen #endif 515712b2f30Ssthen #if defined(USE_DSA) && defined(USE_SHA1) 5167bc20e6dSsthen verifytest_file(SRCDIRSTR "/testdata/test_signatures.2", "20080414005004"); 5177bc20e6dSsthen verifytest_file(SRCDIRSTR "/testdata/test_signatures.3", "20080416005004"); 5187bc20e6dSsthen verifytest_file(SRCDIRSTR "/testdata/test_signatures.4", "20080416005004"); 5197bc20e6dSsthen verifytest_file(SRCDIRSTR "/testdata/test_signatures.5", "20080416005004"); 5207bc20e6dSsthen verifytest_file(SRCDIRSTR "/testdata/test_signatures.6", "20080416005004"); 5217bc20e6dSsthen verifytest_file(SRCDIRSTR "/testdata/test_signatures.7", "20070829144150"); 522712b2f30Ssthen #endif /* USE_DSA */ 523712b2f30Ssthen #ifdef USE_SHA1 5247bc20e6dSsthen verifytest_file(SRCDIRSTR "/testdata/test_signatures.8", "20070829144150"); 525712b2f30Ssthen #endif 526712b2f30Ssthen #if (defined(HAVE_EVP_SHA256) || defined(HAVE_NSS) || defined(HAVE_NETTLE)) && defined(USE_SHA2) 5277bc20e6dSsthen verifytest_file(SRCDIRSTR "/testdata/test_sigs.rsasha256", "20070829144150"); 528712b2f30Ssthen # ifdef USE_SHA1 5297bc20e6dSsthen verifytest_file(SRCDIRSTR "/testdata/test_sigs.sha1_and_256", "20070829144150"); 530712b2f30Ssthen # endif 5317bc20e6dSsthen verifytest_file(SRCDIRSTR "/testdata/test_sigs.rsasha256_draft", "20090101000000"); 532712b2f30Ssthen #endif 533712b2f30Ssthen #if (defined(HAVE_EVP_SHA512) || defined(HAVE_NSS) || defined(HAVE_NETTLE)) && defined(USE_SHA2) 5347bc20e6dSsthen verifytest_file(SRCDIRSTR "/testdata/test_sigs.rsasha512_draft", "20070829144150"); 5357bc20e6dSsthen verifytest_file(SRCDIRSTR "/testdata/test_signatures.9", "20171215000000"); 536712b2f30Ssthen #endif 537712b2f30Ssthen #ifdef USE_SHA1 5387bc20e6dSsthen verifytest_file(SRCDIRSTR "/testdata/test_sigs.hinfo", "20090107100022"); 5397bc20e6dSsthen verifytest_file(SRCDIRSTR "/testdata/test_sigs.revoked", "20080414005004"); 540712b2f30Ssthen #endif 541712b2f30Ssthen #ifdef USE_GOST 542712b2f30Ssthen if(sldns_key_EVP_load_gost_id()) 5437bc20e6dSsthen verifytest_file(SRCDIRSTR "/testdata/test_sigs.gost", "20090807060504"); 544712b2f30Ssthen else printf("Warning: skipped GOST, openssl does not provide gost.\n"); 545712b2f30Ssthen #endif 546712b2f30Ssthen #ifdef USE_ECDSA 547712b2f30Ssthen /* test for support in case we use libNSS and ECC is removed */ 548712b2f30Ssthen if(dnskey_algo_id_is_supported(LDNS_ECDSAP256SHA256)) { 5497bc20e6dSsthen verifytest_file(SRCDIRSTR "/testdata/test_sigs.ecdsa_p256", "20100908100439"); 5507bc20e6dSsthen verifytest_file(SRCDIRSTR "/testdata/test_sigs.ecdsa_p384", "20100908100439"); 551712b2f30Ssthen } 5527bc20e6dSsthen dstest_file(SRCDIRSTR "/testdata/test_ds.sha384"); 553712b2f30Ssthen #endif 554712b2f30Ssthen #ifdef USE_ED25519 555712b2f30Ssthen if(dnskey_algo_id_is_supported(LDNS_ED25519)) { 5567bc20e6dSsthen verifytest_file(SRCDIRSTR "/testdata/test_sigs.ed25519", "20170530140439"); 557712b2f30Ssthen } 558712b2f30Ssthen #endif 559712b2f30Ssthen #ifdef USE_ED448 560712b2f30Ssthen if(dnskey_algo_id_is_supported(LDNS_ED448)) { 5617bc20e6dSsthen verifytest_file(SRCDIRSTR "/testdata/test_sigs.ed448", "20180408143630"); 562712b2f30Ssthen } 563712b2f30Ssthen #endif 564712b2f30Ssthen #ifdef USE_SHA1 5657bc20e6dSsthen dstest_file(SRCDIRSTR "/testdata/test_ds.sha1"); 566712b2f30Ssthen #endif 567712b2f30Ssthen nsectest(); 5687bc20e6dSsthen nsec3_hash_test(SRCDIRSTR "/testdata/test_nsec3_hash.1"); 569712b2f30Ssthen } 570