1 1.1 christos /* 2 1.1 christos * testcode/unitverify.c - unit test for signature verification routines. 3 1.1 christos * 4 1.1 christos * Copyright (c) 2007, NLnet Labs. All rights reserved. 5 1.1 christos * 6 1.1 christos * This software is open source. 7 1.1 christos * 8 1.1 christos * Redistribution and use in source and binary forms, with or without 9 1.1 christos * modification, are permitted provided that the following conditions 10 1.1 christos * are met: 11 1.1 christos * 12 1.1 christos * Redistributions of source code must retain the above copyright notice, 13 1.1 christos * this list of conditions and the following disclaimer. 14 1.1 christos * 15 1.1 christos * Redistributions in binary form must reproduce the above copyright notice, 16 1.1 christos * this list of conditions and the following disclaimer in the documentation 17 1.1 christos * and/or other materials provided with the distribution. 18 1.1 christos * 19 1.1 christos * Neither the name of the NLNET LABS nor the names of its contributors may 20 1.1 christos * be used to endorse or promote products derived from this software without 21 1.1 christos * specific prior written permission. 22 1.1 christos * 23 1.1 christos * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 1.1 christos * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 1.1 christos * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26 1.1 christos * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27 1.1 christos * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28 1.1 christos * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29 1.1 christos * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30 1.1 christos * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 1.1 christos * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 1.1 christos * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 1.1 christos * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 1.1 christos * 35 1.1 christos */ 36 1.1 christos /** 37 1.1 christos * \file 38 1.1 christos * Calls verification unit tests. Exits with code 1 on a failure. 39 1.1 christos */ 40 1.1 christos 41 1.1 christos #include "config.h" 42 1.1 christos #include "util/log.h" 43 1.1 christos #include "testcode/unitmain.h" 44 1.1 christos #include "validator/val_sigcrypt.h" 45 1.1 christos #include "validator/val_secalgo.h" 46 1.1 christos #include "validator/val_nsec.h" 47 1.1 christos #include "validator/val_nsec3.h" 48 1.1 christos #include "validator/validator.h" 49 1.1 christos #include "testcode/testpkts.h" 50 1.1 christos #include "util/data/msgreply.h" 51 1.1 christos #include "util/data/msgparse.h" 52 1.1 christos #include "util/data/dname.h" 53 1.1 christos #include "util/regional.h" 54 1.1 christos #include "util/alloc.h" 55 1.1 christos #include "util/rbtree.h" 56 1.1 christos #include "util/net_help.h" 57 1.1 christos #include "util/module.h" 58 1.1 christos #include "util/config_file.h" 59 1.1 christos #include "sldns/sbuffer.h" 60 1.1 christos #include "sldns/keyraw.h" 61 1.1 christos #include "sldns/str2wire.h" 62 1.1 christos #include "sldns/wire2str.h" 63 1.1 christos 64 1.1.1.8 christos #ifdef HAVE_SSL 65 1.1.1.8 christos #ifdef HAVE_OPENSSL_ERR_H 66 1.1.1.8 christos #include <openssl/err.h> 67 1.1.1.8 christos #endif 68 1.1.1.8 christos #endif 69 1.1.1.8 christos 70 1.1 christos /** verbose signature test */ 71 1.1 christos static int vsig = 0; 72 1.1 christos 73 1.1 christos /** entry to packet buffer with wireformat */ 74 1.1 christos static void 75 1.1 christos entry_to_buf(struct entry* e, sldns_buffer* pkt) 76 1.1 christos { 77 1.1 christos unit_assert(e->reply_list); 78 1.1 christos if(e->reply_list->reply_from_hex) { 79 1.1 christos sldns_buffer_copy(pkt, e->reply_list->reply_from_hex); 80 1.1 christos } else { 81 1.1 christos sldns_buffer_clear(pkt); 82 1.1 christos sldns_buffer_write(pkt, e->reply_list->reply_pkt, 83 1.1 christos e->reply_list->reply_len); 84 1.1 christos sldns_buffer_flip(pkt); 85 1.1 christos } 86 1.1 christos } 87 1.1 christos 88 1.1 christos /** entry to reply info conversion */ 89 1.1 christos static void 90 1.1 christos entry_to_repinfo(struct entry* e, struct alloc_cache* alloc, 91 1.1 christos struct regional* region, sldns_buffer* pkt, struct query_info* qi, 92 1.1 christos struct reply_info** rep) 93 1.1 christos { 94 1.1 christos int ret; 95 1.1 christos struct edns_data edns; 96 1.1 christos entry_to_buf(e, pkt); 97 1.1 christos /* lock alloc lock to please lock checking software. 98 1.1 christos * alloc_special_obtain assumes it is talking to a ub-alloc, 99 1.1 christos * and does not need to perform locking. Here the alloc is 100 1.1 christos * the only one, so we lock it here */ 101 1.1 christos lock_quick_lock(&alloc->lock); 102 1.1 christos ret = reply_info_parse(pkt, alloc, qi, rep, region, &edns); 103 1.1 christos lock_quick_unlock(&alloc->lock); 104 1.1 christos if(ret != 0) { 105 1.1 christos char rcode[16]; 106 1.1 christos sldns_wire2str_rcode_buf(ret, rcode, sizeof(rcode)); 107 1.1 christos printf("parse code %d: %s\n", ret, rcode); 108 1.1 christos unit_assert(ret != 0); 109 1.1 christos } 110 1.1 christos } 111 1.1 christos 112 1.1 christos /** extract DNSKEY rrset from answer and convert it */ 113 1.1 christos static struct ub_packed_rrset_key* 114 1.1 christos extract_keys(struct entry* e, struct alloc_cache* alloc, 115 1.1 christos struct regional* region, sldns_buffer* pkt) 116 1.1 christos { 117 1.1 christos struct ub_packed_rrset_key* dnskey = NULL; 118 1.1 christos struct query_info qinfo; 119 1.1 christos struct reply_info* rep = NULL; 120 1.1 christos size_t i; 121 1.1 christos 122 1.1 christos entry_to_repinfo(e, alloc, region, pkt, &qinfo, &rep); 123 1.1 christos for(i=0; i<rep->an_numrrsets; i++) { 124 1.1 christos if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_DNSKEY) { 125 1.1 christos dnskey = rep->rrsets[i]; 126 1.1 christos rep->rrsets[i] = NULL; 127 1.1 christos break; 128 1.1 christos } 129 1.1 christos } 130 1.1 christos unit_assert(dnskey); 131 1.1 christos 132 1.1 christos reply_info_parsedelete(rep, alloc); 133 1.1 christos query_info_clear(&qinfo); 134 1.1 christos return dnskey; 135 1.1 christos } 136 1.1 christos 137 1.1 christos /** return true if answer should be bogus */ 138 1.1 christos static int 139 1.1 christos should_be_bogus(struct ub_packed_rrset_key* rrset, struct query_info* qinfo) 140 1.1 christos { 141 1.1 christos struct packed_rrset_data* d = (struct packed_rrset_data*)rrset-> 142 1.1 christos entry.data; 143 1.1 christos if(d->rrsig_count == 0) 144 1.1 christos return 1; 145 1.1 christos /* name 'bogus' as first label signals bogus */ 146 1.1 christos if(rrset->rk.dname_len > 6 && memcmp(rrset->rk.dname+1, "bogus", 5)==0) 147 1.1 christos return 1; 148 1.1 christos if(qinfo->qname_len > 6 && memcmp(qinfo->qname+1, "bogus", 5)==0) 149 1.1 christos return 1; 150 1.1 christos return 0; 151 1.1 christos } 152 1.1 christos 153 1.1 christos /** return number of rrs in an rrset */ 154 1.1 christos static size_t 155 1.1 christos rrset_get_count(struct ub_packed_rrset_key* rrset) 156 1.1 christos { 157 1.1 christos struct packed_rrset_data* d = (struct packed_rrset_data*) 158 1.1 christos rrset->entry.data; 159 1.1 christos if(!d) return 0; 160 1.1 christos return d->count; 161 1.1 christos } 162 1.1 christos 163 1.1 christos /** setup sig alg list from dnskey */ 164 1.1 christos static void 165 1.1 christos setup_sigalg(struct ub_packed_rrset_key* dnskey, uint8_t* sigalg) 166 1.1 christos { 167 1.1 christos uint8_t a[ALGO_NEEDS_MAX]; 168 1.1 christos size_t i, n = 0; 169 1.1 christos memset(a, 0, sizeof(a)); 170 1.1 christos for(i=0; i<rrset_get_count(dnskey); i++) { 171 1.1 christos uint8_t algo = (uint8_t)dnskey_get_algo(dnskey, i); 172 1.1 christos if(a[algo] == 0) { 173 1.1 christos a[algo] = 1; 174 1.1 christos sigalg[n++] = algo; 175 1.1 christos } 176 1.1 christos } 177 1.1 christos sigalg[n] = 0; 178 1.1 christos } 179 1.1 christos 180 1.1 christos /** verify and test one rrset against the key rrset */ 181 1.1 christos static void 182 1.1 christos verifytest_rrset(struct module_env* env, struct val_env* ve, 183 1.1 christos struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey, 184 1.1 christos struct query_info* qinfo) 185 1.1 christos { 186 1.1 christos enum sec_status sec; 187 1.1.1.7 christos char reasonbuf[256]; 188 1.1 christos char* reason = NULL; 189 1.1 christos uint8_t sigalg[ALGO_NEEDS_MAX+1]; 190 1.1.1.6 christos int verified = 0; 191 1.1 christos if(vsig) { 192 1.1 christos log_nametypeclass(VERB_QUERY, "verify of rrset", 193 1.1 christos rrset->rk.dname, ntohs(rrset->rk.type), 194 1.1 christos ntohs(rrset->rk.rrset_class)); 195 1.1 christos } 196 1.1 christos setup_sigalg(dnskey, sigalg); /* check all algorithms in the dnskey */ 197 1.1.1.2 christos /* ok to give null as qstate here, won't be used for answer section. */ 198 1.1.1.7 christos sec = dnskeyset_verify_rrset(env, ve, rrset, dnskey, sigalg, &reason, 199 1.1.1.7 christos NULL, LDNS_SECTION_ANSWER, NULL, &verified, reasonbuf, 200 1.1.1.7 christos sizeof(reasonbuf)); 201 1.1 christos if(vsig) { 202 1.1 christos printf("verify outcome is: %s %s\n", sec_status_to_string(sec), 203 1.1 christos reason?reason:""); 204 1.1 christos } 205 1.1 christos if(should_be_bogus(rrset, qinfo)) { 206 1.1 christos unit_assert(sec == sec_status_bogus); 207 1.1 christos } else { 208 1.1 christos unit_assert(sec == sec_status_secure); 209 1.1 christos } 210 1.1 christos } 211 1.1 christos 212 1.1 christos /** verify and test an entry - every rr in the message */ 213 1.1 christos static void 214 1.1 christos verifytest_entry(struct entry* e, struct alloc_cache* alloc, 215 1.1 christos struct regional* region, sldns_buffer* pkt, 216 1.1 christos struct ub_packed_rrset_key* dnskey, struct module_env* env, 217 1.1 christos struct val_env* ve) 218 1.1 christos { 219 1.1 christos struct query_info qinfo; 220 1.1 christos struct reply_info* rep = NULL; 221 1.1 christos size_t i; 222 1.1 christos 223 1.1 christos regional_free_all(region); 224 1.1 christos if(vsig) { 225 1.1 christos char* s = sldns_wire2str_pkt(e->reply_list->reply_pkt, 226 1.1 christos e->reply_list->reply_len); 227 1.1 christos printf("verifying pkt:\n%s\n", s?s:"outofmemory"); 228 1.1 christos free(s); 229 1.1 christos } 230 1.1 christos entry_to_repinfo(e, alloc, region, pkt, &qinfo, &rep); 231 1.1 christos 232 1.1 christos for(i=0; i<rep->rrset_count; i++) { 233 1.1 christos verifytest_rrset(env, ve, rep->rrsets[i], dnskey, &qinfo); 234 1.1 christos } 235 1.1 christos 236 1.1 christos reply_info_parsedelete(rep, alloc); 237 1.1 christos query_info_clear(&qinfo); 238 1.1 christos } 239 1.1 christos 240 1.1 christos /** find RRset in reply by type */ 241 1.1 christos static struct ub_packed_rrset_key* 242 1.1 christos find_rrset_type(struct reply_info* rep, uint16_t type) 243 1.1 christos { 244 1.1 christos size_t i; 245 1.1 christos for(i=0; i<rep->rrset_count; i++) { 246 1.1 christos if(ntohs(rep->rrsets[i]->rk.type) == type) 247 1.1 christos return rep->rrsets[i]; 248 1.1 christos } 249 1.1 christos return NULL; 250 1.1 christos } 251 1.1 christos 252 1.1 christos /** DS sig test an entry - get DNSKEY and DS in entry and verify */ 253 1.1 christos static void 254 1.1 christos dstest_entry(struct entry* e, struct alloc_cache* alloc, 255 1.1 christos struct regional* region, sldns_buffer* pkt, struct module_env* env) 256 1.1 christos { 257 1.1 christos struct query_info qinfo; 258 1.1 christos struct reply_info* rep = NULL; 259 1.1 christos struct ub_packed_rrset_key* ds, *dnskey; 260 1.1 christos int ret; 261 1.1 christos 262 1.1 christos regional_free_all(region); 263 1.1 christos if(vsig) { 264 1.1 christos char* s = sldns_wire2str_pkt(e->reply_list->reply_pkt, 265 1.1 christos e->reply_list->reply_len); 266 1.1 christos printf("verifying DS-DNSKEY match:\n%s\n", s?s:"outofmemory"); 267 1.1 christos free(s); 268 1.1 christos } 269 1.1 christos entry_to_repinfo(e, alloc, region, pkt, &qinfo, &rep); 270 1.1 christos ds = find_rrset_type(rep, LDNS_RR_TYPE_DS); 271 1.1 christos dnskey = find_rrset_type(rep, LDNS_RR_TYPE_DNSKEY); 272 1.1 christos /* check test is OK */ 273 1.1 christos unit_assert(ds && dnskey); 274 1.1 christos 275 1.1 christos ret = ds_digest_match_dnskey(env, dnskey, 0, ds, 0); 276 1.1 christos if(strncmp((char*)qinfo.qname, "\003yes", 4) == 0) { 277 1.1 christos if(vsig) { 278 1.1 christos printf("result(yes)= %s\n", ret?"yes":"no"); 279 1.1 christos } 280 1.1 christos unit_assert(ret); 281 1.1 christos } else if (strncmp((char*)qinfo.qname, "\002no", 3) == 0) { 282 1.1 christos if(vsig) { 283 1.1 christos printf("result(no)= %s\n", ret?"yes":"no"); 284 1.1 christos } 285 1.1 christos unit_assert(!ret); 286 1.1 christos verbose(VERB_QUERY, "DS fail: OK; matched unit test"); 287 1.1 christos } else { 288 1.1 christos fatal_exit("Bad qname in DS unit test, yes or no"); 289 1.1 christos } 290 1.1 christos 291 1.1 christos reply_info_parsedelete(rep, alloc); 292 1.1 christos query_info_clear(&qinfo); 293 1.1 christos } 294 1.1 christos 295 1.1 christos /** verify from a file */ 296 1.1 christos static void 297 1.1 christos verifytest_file(const char* fname, const char* at_date) 298 1.1 christos { 299 1.1 christos /* 300 1.1 christos * The file contains a list of ldns-testpkts entries. 301 1.1 christos * The first entry must be a query for DNSKEY. 302 1.1 christos * The answer rrset is the keyset that will be used for verification 303 1.1 christos */ 304 1.1 christos struct ub_packed_rrset_key* dnskey; 305 1.1 christos struct regional* region = regional_create(); 306 1.1 christos struct alloc_cache alloc; 307 1.1 christos sldns_buffer* buf = sldns_buffer_new(65535); 308 1.1 christos struct entry* e; 309 1.1 christos struct entry* list = read_datafile(fname, 1); 310 1.1 christos struct module_env env; 311 1.1 christos struct val_env ve; 312 1.1 christos time_t now = time(NULL); 313 1.1.1.2 christos unit_show_func("signature verify", fname); 314 1.1 christos 315 1.1 christos if(!list) 316 1.1 christos fatal_exit("could not read %s: %s", fname, strerror(errno)); 317 1.1 christos alloc_init(&alloc, NULL, 1); 318 1.1 christos memset(&env, 0, sizeof(env)); 319 1.1 christos memset(&ve, 0, sizeof(ve)); 320 1.1 christos env.scratch = region; 321 1.1 christos env.scratch_buffer = buf; 322 1.1 christos env.now = &now; 323 1.1 christos ve.date_override = cfg_convert_timeval(at_date); 324 1.1 christos unit_assert(region && buf); 325 1.1 christos dnskey = extract_keys(list, &alloc, region, buf); 326 1.1 christos if(vsig) log_nametypeclass(VERB_QUERY, "test dnskey", 327 1.1 christos dnskey->rk.dname, ntohs(dnskey->rk.type), 328 1.1 christos ntohs(dnskey->rk.rrset_class)); 329 1.1 christos /* ready to go! */ 330 1.1 christos for(e = list->next; e; e = e->next) { 331 1.1 christos verifytest_entry(e, &alloc, region, buf, dnskey, &env, &ve); 332 1.1 christos } 333 1.1 christos 334 1.1 christos ub_packed_rrset_parsedelete(dnskey, &alloc); 335 1.1 christos delete_entry(list); 336 1.1 christos regional_destroy(region); 337 1.1 christos alloc_clear(&alloc); 338 1.1 christos sldns_buffer_free(buf); 339 1.1 christos } 340 1.1 christos 341 1.1 christos /** verify DS matches DNSKEY from a file */ 342 1.1 christos static void 343 1.1 christos dstest_file(const char* fname) 344 1.1 christos { 345 1.1 christos /* 346 1.1 christos * The file contains a list of ldns-testpkts entries. 347 1.1 christos * The first entry must be a query for DNSKEY. 348 1.1 christos * The answer rrset is the keyset that will be used for verification 349 1.1 christos */ 350 1.1 christos struct regional* region = regional_create(); 351 1.1 christos struct alloc_cache alloc; 352 1.1 christos sldns_buffer* buf = sldns_buffer_new(65535); 353 1.1 christos struct entry* e; 354 1.1 christos struct entry* list = read_datafile(fname, 1); 355 1.1 christos struct module_env env; 356 1.1.1.2 christos unit_show_func("DS verify", fname); 357 1.1 christos 358 1.1 christos if(!list) 359 1.1 christos fatal_exit("could not read %s: %s", fname, strerror(errno)); 360 1.1 christos alloc_init(&alloc, NULL, 1); 361 1.1 christos memset(&env, 0, sizeof(env)); 362 1.1 christos env.scratch = region; 363 1.1 christos env.scratch_buffer = buf; 364 1.1 christos unit_assert(region && buf); 365 1.1 christos 366 1.1 christos /* ready to go! */ 367 1.1 christos for(e = list; e; e = e->next) { 368 1.1 christos dstest_entry(e, &alloc, region, buf, &env); 369 1.1 christos } 370 1.1 christos 371 1.1 christos delete_entry(list); 372 1.1 christos regional_destroy(region); 373 1.1 christos alloc_clear(&alloc); 374 1.1 christos sldns_buffer_free(buf); 375 1.1 christos } 376 1.1 christos 377 1.1 christos /** helper for unittest of NSEC routines */ 378 1.1 christos static int 379 1.1 christos unitest_nsec_has_type_rdata(char* bitmap, size_t len, uint16_t type) 380 1.1 christos { 381 1.1 christos return nsecbitmap_has_type_rdata((uint8_t*)bitmap, len, type); 382 1.1 christos } 383 1.1 christos 384 1.1 christos /** Test NSEC type bitmap routine */ 385 1.1 christos static void 386 1.1 christos nsectest(void) 387 1.1 christos { 388 1.1 christos /* bitmap starts at type bitmap rdata field */ 389 1.1 christos /* from rfc 4034 example */ 390 1.1 christos char* bitmap = "\000\006\100\001\000\000\000\003" 391 1.1 christos "\004\033\000\000\000\000\000\000" 392 1.1 christos "\000\000\000\000\000\000\000\000" 393 1.1 christos "\000\000\000\000\000\000\000\000" 394 1.1 christos "\000\000\000\000\040"; 395 1.1 christos size_t len = 37; 396 1.1 christos 397 1.1 christos unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 0)); 398 1.1 christos unit_assert(unitest_nsec_has_type_rdata(bitmap, len, LDNS_RR_TYPE_A)); 399 1.1 christos unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 2)); 400 1.1 christos unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 3)); 401 1.1 christos unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 4)); 402 1.1 christos unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 5)); 403 1.1 christos unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 6)); 404 1.1 christos unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 7)); 405 1.1 christos unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 8)); 406 1.1 christos unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 9)); 407 1.1 christos unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 10)); 408 1.1 christos unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 11)); 409 1.1 christos unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 12)); 410 1.1 christos unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 13)); 411 1.1 christos unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 14)); 412 1.1 christos unit_assert(unitest_nsec_has_type_rdata(bitmap, len, LDNS_RR_TYPE_MX)); 413 1.1 christos unit_assert(unitest_nsec_has_type_rdata(bitmap, len, LDNS_RR_TYPE_RRSIG)); 414 1.1 christos unit_assert(unitest_nsec_has_type_rdata(bitmap, len, LDNS_RR_TYPE_NSEC)); 415 1.1 christos unit_assert(unitest_nsec_has_type_rdata(bitmap, len, 1234)); 416 1.1 christos unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1233)); 417 1.1 christos unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1235)); 418 1.1 christos unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1236)); 419 1.1 christos unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1237)); 420 1.1 christos unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1238)); 421 1.1 christos unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1239)); 422 1.1 christos unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1240)); 423 1.1 christos unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 2230)); 424 1.1 christos } 425 1.1 christos 426 1.1 christos /** Test hash algo - NSEC3 hash it and compare result */ 427 1.1 christos static void 428 1.1.1.2 christos nsec3_hash_test_entry(struct entry* e, rbtree_type* ct, 429 1.1 christos struct alloc_cache* alloc, struct regional* region, 430 1.1 christos sldns_buffer* buf) 431 1.1 christos { 432 1.1 christos struct query_info qinfo; 433 1.1 christos struct reply_info* rep = NULL; 434 1.1.1.7 christos struct ub_packed_rrset_key* answer, *nsec3, *nsec3_region; 435 1.1 christos struct nsec3_cached_hash* hash = NULL; 436 1.1 christos int ret; 437 1.1 christos uint8_t* qname; 438 1.1 christos 439 1.1 christos if(vsig) { 440 1.1 christos char* s = sldns_wire2str_pkt(e->reply_list->reply_pkt, 441 1.1 christos e->reply_list->reply_len); 442 1.1 christos printf("verifying NSEC3 hash:\n%s\n", s?s:"outofmemory"); 443 1.1 christos free(s); 444 1.1 christos } 445 1.1 christos entry_to_repinfo(e, alloc, region, buf, &qinfo, &rep); 446 1.1 christos nsec3 = find_rrset_type(rep, LDNS_RR_TYPE_NSEC3); 447 1.1 christos answer = find_rrset_type(rep, LDNS_RR_TYPE_AAAA); 448 1.1 christos qname = regional_alloc_init(region, qinfo.qname, qinfo.qname_len); 449 1.1 christos /* check test is OK */ 450 1.1 christos unit_assert(nsec3 && answer && qname); 451 1.1 christos 452 1.1.1.7 christos /* Copy the nsec3 to the region, so it can stay referenced by the 453 1.1.1.7 christos * ct tree entry. The region is freed when the file is done. */ 454 1.1.1.7 christos nsec3_region = packed_rrset_copy_region(nsec3, region, 0); 455 1.1.1.7 christos 456 1.1.1.7 christos ret = nsec3_hash_name(ct, region, buf, nsec3_region, 0, qname, 457 1.1 christos qinfo.qname_len, &hash); 458 1.1.1.6 christos if(ret < 1) { 459 1.1 christos printf("Bad nsec3_hash_name retcode %d\n", ret); 460 1.1.1.6 christos unit_assert(ret == 1 || ret == 2); 461 1.1 christos } 462 1.1 christos unit_assert(hash->dname && hash->hash && hash->hash_len && 463 1.1 christos hash->b32 && hash->b32_len); 464 1.1 christos unit_assert(hash->b32_len == (size_t)answer->rk.dname[0]); 465 1.1 christos /* does not do lowercasing. */ 466 1.1 christos unit_assert(memcmp(hash->b32, answer->rk.dname+1, hash->b32_len) 467 1.1 christos == 0); 468 1.1 christos 469 1.1 christos reply_info_parsedelete(rep, alloc); 470 1.1 christos query_info_clear(&qinfo); 471 1.1 christos } 472 1.1 christos 473 1.1 christos 474 1.1 christos /** Read file to test NSEC3 hash algo */ 475 1.1 christos static void 476 1.1 christos nsec3_hash_test(const char* fname) 477 1.1 christos { 478 1.1 christos /* 479 1.1 christos * The list contains a list of ldns-testpkts entries. 480 1.1 christos * Every entry is a test. 481 1.1 christos * The qname is hashed. 482 1.1 christos * The answer section AAAA RR name is the required result. 483 1.1 christos * The auth section NSEC3 is used to get hash parameters. 484 1.1 christos * The hash cache is maintained per file. 485 1.1 christos * 486 1.1 christos * The test does not perform canonicalization during the compare. 487 1.1 christos */ 488 1.1.1.2 christos rbtree_type ct; 489 1.1 christos struct regional* region = regional_create(); 490 1.1 christos struct alloc_cache alloc; 491 1.1 christos sldns_buffer* buf = sldns_buffer_new(65535); 492 1.1 christos struct entry* e; 493 1.1 christos struct entry* list = read_datafile(fname, 1); 494 1.1.1.2 christos unit_show_func("NSEC3 hash", fname); 495 1.1 christos 496 1.1 christos if(!list) 497 1.1 christos fatal_exit("could not read %s: %s", fname, strerror(errno)); 498 1.1 christos rbtree_init(&ct, &nsec3_hash_cmp); 499 1.1 christos alloc_init(&alloc, NULL, 1); 500 1.1 christos unit_assert(region && buf); 501 1.1 christos 502 1.1 christos /* ready to go! */ 503 1.1 christos for(e = list; e; e = e->next) { 504 1.1 christos nsec3_hash_test_entry(e, &ct, &alloc, region, buf); 505 1.1 christos } 506 1.1 christos 507 1.1 christos delete_entry(list); 508 1.1 christos regional_destroy(region); 509 1.1 christos alloc_clear(&alloc); 510 1.1 christos sldns_buffer_free(buf); 511 1.1 christos } 512 1.1 christos 513 1.1.1.4 christos #define xstr(s) str(s) 514 1.1.1.4 christos #define str(s) #s 515 1.1.1.4 christos 516 1.1.1.4 christos #define SRCDIRSTR xstr(SRCDIR) 517 1.1.1.4 christos 518 1.1.1.8 christos #if defined(HAVE_SSL) && defined(USE_SHA1) 519 1.1.1.8 christos /* Detect if openssl is configured to disable RSASHA1 signatures, 520 1.1.1.8 christos * with the rh-allow-sha1-signatures disabled. */ 521 1.1.1.8 christos static int 522 1.1.1.8 christos rh_allow_sha1_signatures_disabled(void) 523 1.1.1.8 christos { 524 1.1.1.8 christos EVP_MD_CTX* ctx; 525 1.1.1.8 christos EVP_PKEY* evp_key; 526 1.1.1.8 christos /* This key is rdata from nlnetlabs.nl DNSKEY from 20250424005001, 527 1.1.1.8 christos * with id=50602 (ksk), size=2048b. 528 1.1.1.8 christos * A 2048 bit key is taken to avoid key too small errors. */ 529 1.1.1.8 christos unsigned char key[] = { 530 1.1.1.8 christos 0x03, 0x01, 0x00, 0x01, 0xBC, 0x0B, 0xE8, 0xBB, 531 1.1.1.8 christos 0x97, 0x4C, 0xB5, 0xED, 0x6F, 0x6D, 0xC2, 0xB1, 532 1.1.1.8 christos 0x78, 0x69, 0x93, 0x1C, 0x72, 0x19, 0xB1, 0x05, 533 1.1.1.8 christos 0x51, 0x13, 0xA1, 0xFC, 0xBF, 0x01, 0x58, 0x0D, 534 1.1.1.8 christos 0x44, 0x10, 0x5F, 0x0B, 0x75, 0x0E, 0x11, 0x9A, 535 1.1.1.8 christos 0xC8, 0xF8, 0x0F, 0x90, 0xFC, 0xB8, 0x09, 0xD1, 536 1.1.1.8 christos 0x14, 0x39, 0x0D, 0x84, 0xCE, 0x97, 0x88, 0x82, 537 1.1.1.8 christos 0x3D, 0xC5, 0xCB, 0x1A, 0xBF, 0x00, 0x46, 0x37, 538 1.1.1.8 christos 0x01, 0xF1, 0xCD, 0x46, 0xA2, 0x8F, 0x83, 0x19, 539 1.1.1.8 christos 0x42, 0xED, 0x6F, 0xAF, 0x37, 0x1F, 0x18, 0x82, 540 1.1.1.8 christos 0x4B, 0x70, 0x2D, 0x50, 0xA5, 0xA6, 0x66, 0x48, 541 1.1.1.8 christos 0x7F, 0x56, 0xA8, 0x86, 0x05, 0x41, 0xC8, 0xBE, 542 1.1.1.8 christos 0x4F, 0x8B, 0x38, 0x51, 0xF0, 0xEB, 0xAD, 0x2F, 543 1.1.1.8 christos 0x7A, 0xC0, 0xEF, 0xC7, 0xD2, 0x72, 0x6F, 0x16, 544 1.1.1.8 christos 0x66, 0xAF, 0x59, 0x55, 0xFF, 0xEE, 0x9D, 0x50, 545 1.1.1.8 christos 0xE9, 0xDB, 0xF4, 0x02, 0xBC, 0x33, 0x5C, 0xC5, 546 1.1.1.8 christos 0xDA, 0x1C, 0x6A, 0xD1, 0x55, 0xD1, 0x20, 0x2B, 547 1.1.1.8 christos 0x63, 0x03, 0x4B, 0x77, 0x45, 0x46, 0x78, 0x31, 548 1.1.1.8 christos 0xE4, 0x90, 0xB9, 0x7F, 0x00, 0xFB, 0x62, 0x7C, 549 1.1.1.8 christos 0x07, 0xD3, 0xC1, 0x00, 0xA0, 0x54, 0x63, 0x74, 550 1.1.1.8 christos 0x0A, 0x17, 0x7B, 0xE7, 0xAD, 0x38, 0x07, 0x86, 551 1.1.1.8 christos 0x68, 0xE4, 0xFD, 0x20, 0x68, 0xD5, 0x33, 0x92, 552 1.1.1.8 christos 0xCA, 0x90, 0xDD, 0xA4, 0xE9, 0xF2, 0x11, 0xBD, 553 1.1.1.8 christos 0x9D, 0xA5, 0xF5, 0xEB, 0xB9, 0xFE, 0x8F, 0xA1, 554 1.1.1.8 christos 0xE4, 0xBF, 0xA4, 0xA4, 0x34, 0x5C, 0x6A, 0x95, 555 1.1.1.8 christos 0xB6, 0x42, 0x22, 0xF6, 0xD6, 0x10, 0x9C, 0x9B, 556 1.1.1.8 christos 0x0A, 0x56, 0xE7, 0x42, 0xE5, 0x7F, 0x1F, 0x4E, 557 1.1.1.8 christos 0xBE, 0x4F, 0x8C, 0xED, 0x30, 0x63, 0xA7, 0x88, 558 1.1.1.8 christos 0x93, 0xED, 0x37, 0x3C, 0x80, 0xBC, 0xD1, 0x66, 559 1.1.1.8 christos 0xBD, 0xB8, 0x2E, 0x65, 0xC4, 0xC8, 0x00, 0x5B, 560 1.1.1.8 christos 0xE7, 0x85, 0x96, 0xDD, 0xAA, 0x05, 0xE6, 0x4F, 561 1.1.1.8 christos 0x03, 0x64, 0xFA, 0x2D, 0xF6, 0x88, 0x14, 0x8F, 562 1.1.1.8 christos 0x15, 0x4D, 0xFD, 0xD3 563 1.1.1.8 christos }; 564 1.1.1.8 christos size_t keylen = 260; 565 1.1.1.8 christos 566 1.1.1.8 christos #ifdef HAVE_EVP_MD_CTX_NEW 567 1.1.1.8 christos ctx = EVP_MD_CTX_new(); 568 1.1.1.8 christos #else 569 1.1.1.8 christos ctx = (EVP_MD_CTX*)malloc(sizeof(*ctx)); 570 1.1.1.8 christos if(ctx) EVP_MD_CTX_init(ctx); 571 1.1.1.8 christos #endif 572 1.1.1.8 christos if(!ctx) return 0; 573 1.1.1.8 christos 574 1.1.1.8 christos evp_key = sldns_key_rsa2pkey_raw(key, keylen); 575 1.1.1.8 christos if(!evp_key) { 576 1.1.1.8 christos #ifdef HAVE_EVP_MD_CTX_NEW 577 1.1.1.8 christos EVP_MD_CTX_destroy(ctx); 578 1.1.1.8 christos #else 579 1.1.1.8 christos EVP_MD_CTX_cleanup(ctx); 580 1.1.1.8 christos free(ctx); 581 1.1.1.8 christos #endif 582 1.1.1.8 christos return 0; 583 1.1.1.8 christos } 584 1.1.1.8 christos 585 1.1.1.8 christos #ifndef HAVE_EVP_DIGESTVERIFY 586 1.1.1.8 christos (void)evp_key; /* not used */ 587 1.1.1.8 christos if(EVP_DigestInit(ctx, EVP_sha1()) == 0) 588 1.1.1.8 christos #else 589 1.1.1.8 christos if(EVP_DigestVerifyInit(ctx, NULL, EVP_sha1(), NULL, evp_key) == 0) 590 1.1.1.8 christos #endif 591 1.1.1.8 christos { 592 1.1.1.8 christos unsigned long e = ERR_get_error(); 593 1.1.1.8 christos #ifdef EVP_R_INVALID_DIGEST 594 1.1.1.8 christos if (ERR_GET_LIB(e) == ERR_LIB_EVP && 595 1.1.1.8 christos ERR_GET_REASON(e) == EVP_R_INVALID_DIGEST) { 596 1.1.1.8 christos /* rh-allow-sha1-signatures makes use of sha1 invalid. */ 597 1.1.1.8 christos if(vsig) 598 1.1.1.8 christos printf("Detected that rh-allow-sha1-signatures is off, and disables SHA1 signatures\n"); 599 1.1.1.8 christos #ifdef HAVE_EVP_MD_CTX_NEW 600 1.1.1.8 christos EVP_MD_CTX_destroy(ctx); 601 1.1.1.8 christos #else 602 1.1.1.8 christos EVP_MD_CTX_cleanup(ctx); 603 1.1.1.8 christos free(ctx); 604 1.1.1.8 christos #endif 605 1.1.1.8 christos EVP_PKEY_free(evp_key); 606 1.1.1.8 christos return 1; 607 1.1.1.8 christos } 608 1.1.1.8 christos #endif /* EVP_R_INVALID_DIGEST */ 609 1.1.1.8 christos /* The signature verify failed for another reason. */ 610 1.1.1.8 christos log_crypto_err_code("EVP_DigestVerifyInit", e); 611 1.1.1.8 christos #ifdef HAVE_EVP_MD_CTX_NEW 612 1.1.1.8 christos EVP_MD_CTX_destroy(ctx); 613 1.1.1.8 christos #else 614 1.1.1.8 christos EVP_MD_CTX_cleanup(ctx); 615 1.1.1.8 christos free(ctx); 616 1.1.1.8 christos #endif 617 1.1.1.8 christos EVP_PKEY_free(evp_key); 618 1.1.1.8 christos return 0; 619 1.1.1.8 christos } 620 1.1.1.8 christos #ifdef HAVE_EVP_MD_CTX_NEW 621 1.1.1.8 christos EVP_MD_CTX_destroy(ctx); 622 1.1.1.8 christos #else 623 1.1.1.8 christos EVP_MD_CTX_cleanup(ctx); 624 1.1.1.8 christos free(ctx); 625 1.1.1.8 christos #endif 626 1.1.1.8 christos EVP_PKEY_free(evp_key); 627 1.1.1.8 christos return 0; 628 1.1.1.8 christos } 629 1.1.1.8 christos #endif /* HAVE_SSL && USE_SHA1 */ 630 1.1.1.8 christos 631 1.1 christos void 632 1.1 christos verify_test(void) 633 1.1 christos { 634 1.1 christos unit_show_feature("signature verify"); 635 1.1.1.8 christos 636 1.1.1.8 christos #if defined(HAVE_SSL) && defined(USE_SHA1) 637 1.1.1.8 christos if(rh_allow_sha1_signatures_disabled()) { 638 1.1.1.8 christos /* Allow the use of SHA1 signatures for the test, 639 1.1.1.8 christos * in case that OpenSSL disallows use of RSASHA1 640 1.1.1.8 christos * with rh-allow-sha1-signatures disabled. */ 641 1.1.1.8 christos #ifndef UB_ON_WINDOWS 642 1.1.1.8 christos setenv("OPENSSL_ENABLE_SHA1_SIGNATURES", "1", 0); 643 1.1.1.8 christos #else 644 1.1.1.8 christos _putenv("OPENSSL_ENABLE_SHA1_SIGNATURES=1"); 645 1.1.1.8 christos #endif 646 1.1.1.8 christos } 647 1.1.1.8 christos #endif 648 1.1.1.8 christos 649 1.1.1.2 christos #ifdef USE_SHA1 650 1.1.1.4 christos verifytest_file(SRCDIRSTR "/testdata/test_signatures.1", "20070818005004"); 651 1.1.1.2 christos #endif 652 1.1.1.2 christos #if defined(USE_DSA) && defined(USE_SHA1) 653 1.1.1.4 christos verifytest_file(SRCDIRSTR "/testdata/test_signatures.2", "20080414005004"); 654 1.1.1.4 christos verifytest_file(SRCDIRSTR "/testdata/test_signatures.3", "20080416005004"); 655 1.1.1.4 christos verifytest_file(SRCDIRSTR "/testdata/test_signatures.4", "20080416005004"); 656 1.1.1.4 christos verifytest_file(SRCDIRSTR "/testdata/test_signatures.5", "20080416005004"); 657 1.1.1.4 christos verifytest_file(SRCDIRSTR "/testdata/test_signatures.6", "20080416005004"); 658 1.1.1.4 christos verifytest_file(SRCDIRSTR "/testdata/test_signatures.7", "20070829144150"); 659 1.1 christos #endif /* USE_DSA */ 660 1.1.1.2 christos #ifdef USE_SHA1 661 1.1.1.4 christos verifytest_file(SRCDIRSTR "/testdata/test_signatures.8", "20070829144150"); 662 1.1.1.2 christos #endif 663 1.1 christos #if (defined(HAVE_EVP_SHA256) || defined(HAVE_NSS) || defined(HAVE_NETTLE)) && defined(USE_SHA2) 664 1.1.1.4 christos verifytest_file(SRCDIRSTR "/testdata/test_sigs.rsasha256", "20070829144150"); 665 1.1.1.2 christos # ifdef USE_SHA1 666 1.1.1.4 christos verifytest_file(SRCDIRSTR "/testdata/test_sigs.sha1_and_256", "20070829144150"); 667 1.1.1.2 christos # endif 668 1.1.1.4 christos verifytest_file(SRCDIRSTR "/testdata/test_sigs.rsasha256_draft", "20090101000000"); 669 1.1 christos #endif 670 1.1 christos #if (defined(HAVE_EVP_SHA512) || defined(HAVE_NSS) || defined(HAVE_NETTLE)) && defined(USE_SHA2) 671 1.1.1.4 christos verifytest_file(SRCDIRSTR "/testdata/test_sigs.rsasha512_draft", "20070829144150"); 672 1.1.1.4 christos verifytest_file(SRCDIRSTR "/testdata/test_signatures.9", "20171215000000"); 673 1.1 christos #endif 674 1.1.1.2 christos #ifdef USE_SHA1 675 1.1.1.4 christos verifytest_file(SRCDIRSTR "/testdata/test_sigs.hinfo", "20090107100022"); 676 1.1.1.4 christos verifytest_file(SRCDIRSTR "/testdata/test_sigs.revoked", "20080414005004"); 677 1.1.1.2 christos #endif 678 1.1 christos #ifdef USE_GOST 679 1.1 christos if(sldns_key_EVP_load_gost_id()) 680 1.1.1.4 christos verifytest_file(SRCDIRSTR "/testdata/test_sigs.gost", "20090807060504"); 681 1.1 christos else printf("Warning: skipped GOST, openssl does not provide gost.\n"); 682 1.1 christos #endif 683 1.1 christos #ifdef USE_ECDSA 684 1.1 christos /* test for support in case we use libNSS and ECC is removed */ 685 1.1 christos if(dnskey_algo_id_is_supported(LDNS_ECDSAP256SHA256)) { 686 1.1.1.4 christos verifytest_file(SRCDIRSTR "/testdata/test_sigs.ecdsa_p256", "20100908100439"); 687 1.1.1.4 christos verifytest_file(SRCDIRSTR "/testdata/test_sigs.ecdsa_p384", "20100908100439"); 688 1.1 christos } 689 1.1.1.4 christos dstest_file(SRCDIRSTR "/testdata/test_ds.sha384"); 690 1.1 christos #endif 691 1.1.1.2 christos #ifdef USE_ED25519 692 1.1.1.2 christos if(dnskey_algo_id_is_supported(LDNS_ED25519)) { 693 1.1.1.4 christos verifytest_file(SRCDIRSTR "/testdata/test_sigs.ed25519", "20170530140439"); 694 1.1.1.2 christos } 695 1.1.1.2 christos #endif 696 1.1.1.3 christos #ifdef USE_ED448 697 1.1.1.3 christos if(dnskey_algo_id_is_supported(LDNS_ED448)) { 698 1.1.1.4 christos verifytest_file(SRCDIRSTR "/testdata/test_sigs.ed448", "20180408143630"); 699 1.1.1.3 christos } 700 1.1.1.3 christos #endif 701 1.1.1.2 christos #ifdef USE_SHA1 702 1.1.1.4 christos dstest_file(SRCDIRSTR "/testdata/test_ds.sha1"); 703 1.1.1.2 christos #endif 704 1.1 christos nsectest(); 705 1.1.1.4 christos nsec3_hash_test(SRCDIRSTR "/testdata/test_nsec3_hash.1"); 706 1.1 christos } 707