1a6cc1574Ssthen /* 2a6cc1574Ssthen * testcode/unitzonemd.c - unit test for zonemd. 3a6cc1574Ssthen * 4a6cc1574Ssthen * Copyright (c) 2020, NLnet Labs. All rights reserved. 5a6cc1574Ssthen * 6a6cc1574Ssthen * This software is open source. 7a6cc1574Ssthen * 8a6cc1574Ssthen * Redistribution and use in source and binary forms, with or without 9a6cc1574Ssthen * modification, are permitted provided that the following conditions 10a6cc1574Ssthen * are met: 11a6cc1574Ssthen * 12a6cc1574Ssthen * Redistributions of source code must retain the above copyright notice, 13a6cc1574Ssthen * this list of conditions and the following disclaimer. 14a6cc1574Ssthen * 15a6cc1574Ssthen * Redistributions in binary form must reproduce the above copyright notice, 16a6cc1574Ssthen * this list of conditions and the following disclaimer in the documentation 17a6cc1574Ssthen * and/or other materials provided with the distribution. 18a6cc1574Ssthen * 19a6cc1574Ssthen * Neither the name of the NLNET LABS nor the names of its contributors may 20a6cc1574Ssthen * be used to endorse or promote products derived from this software without 21a6cc1574Ssthen * specific prior written permission. 22a6cc1574Ssthen * 23a6cc1574Ssthen * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24a6cc1574Ssthen * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25a6cc1574Ssthen * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26a6cc1574Ssthen * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27a6cc1574Ssthen * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28a6cc1574Ssthen * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29a6cc1574Ssthen * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30a6cc1574Ssthen * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31a6cc1574Ssthen * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32a6cc1574Ssthen * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33a6cc1574Ssthen * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34a6cc1574Ssthen * 35a6cc1574Ssthen */ 36a6cc1574Ssthen /** 37a6cc1574Ssthen * \file 38a6cc1574Ssthen * Unit tests for ZONEMD functionality. 39a6cc1574Ssthen */ 40a6cc1574Ssthen 41a6cc1574Ssthen #include "config.h" 42a6cc1574Ssthen #include <ctype.h> 43a6cc1574Ssthen #include "util/log.h" 44a6cc1574Ssthen #include "testcode/unitmain.h" 45a6cc1574Ssthen #include "sldns/str2wire.h" 46a6cc1574Ssthen #include "services/authzone.h" 47a6cc1574Ssthen #include "util/data/dname.h" 48a6cc1574Ssthen #include "util/regional.h" 49a6cc1574Ssthen #include "validator/val_anchor.h" 50a6cc1574Ssthen 51a6cc1574Ssthen #define xstr(s) str(s) 52a6cc1574Ssthen #define str(s) #s 53a6cc1574Ssthen #define SRCDIRSTR xstr(SRCDIR) 54a6cc1574Ssthen 55a6cc1574Ssthen /** Add zone from file for testing */ 56a6cc1574Ssthen struct auth_zone* authtest_addzone(struct auth_zones* az, const char* name, 57a6cc1574Ssthen char* fname); 58a6cc1574Ssthen 59a6cc1574Ssthen /** zonemd unit test, generate a zonemd digest and check if correct */ 60a6cc1574Ssthen static void zonemd_generate_test(const char* zname, char* zfile, 61a6cc1574Ssthen int scheme, int hashalgo, const char* digest) 62a6cc1574Ssthen { 63a6cc1574Ssthen uint8_t zonemd_hash[512]; 64a6cc1574Ssthen size_t hashlen = 0; 65a6cc1574Ssthen char output[1024+1]; 66a6cc1574Ssthen size_t i; 67a6cc1574Ssthen struct auth_zones* az; 68a6cc1574Ssthen struct auth_zone* z; 69a6cc1574Ssthen int result; 70a6cc1574Ssthen struct regional* region = NULL; 71a6cc1574Ssthen struct sldns_buffer* buf = NULL; 72a6cc1574Ssthen char* reason = NULL; 73a6cc1574Ssthen char* digestdup; 74a6cc1574Ssthen 75a6cc1574Ssthen if(!zonemd_hashalgo_supported(hashalgo)) 76a6cc1574Ssthen return; /* cannot test unsupported algo */ 77a6cc1574Ssthen 78a6cc1574Ssthen /* setup environment */ 79a6cc1574Ssthen az = auth_zones_create(); 80a6cc1574Ssthen unit_assert(az); 81a6cc1574Ssthen region = regional_create(); 82a6cc1574Ssthen unit_assert(region); 83a6cc1574Ssthen buf = sldns_buffer_new(65535); 84a6cc1574Ssthen unit_assert(buf); 85a6cc1574Ssthen 86a6cc1574Ssthen /* read file */ 87a6cc1574Ssthen z = authtest_addzone(az, zname, zfile); 88a6cc1574Ssthen unit_assert(z); 89a6cc1574Ssthen lock_rw_wrlock(&z->lock); 90a6cc1574Ssthen z->zonemd_check = 1; 91a6cc1574Ssthen lock_rw_unlock(&z->lock); 92a6cc1574Ssthen 93a6cc1574Ssthen /* create zonemd digest */ 94a6cc1574Ssthen result = auth_zone_generate_zonemd_hash(z, scheme, hashalgo, 95a6cc1574Ssthen zonemd_hash, sizeof(zonemd_hash), &hashlen, region, buf, 96a6cc1574Ssthen &reason); 97a6cc1574Ssthen if(reason) printf("zonemd failure reason: %s\n", reason); 98a6cc1574Ssthen unit_assert(result); 99a6cc1574Ssthen 100a6cc1574Ssthen /* check digest */ 101a6cc1574Ssthen unit_assert(hashlen*2+1 <= sizeof(output)); 102a6cc1574Ssthen for(i=0; i<hashlen; i++) { 103a6cc1574Ssthen const char* hexl = "0123456789ABCDEF"; 104a6cc1574Ssthen output[i*2] = hexl[(zonemd_hash[i]&0xf0)>>4]; 105a6cc1574Ssthen output[i*2+1] = hexl[zonemd_hash[i]&0xf]; 106a6cc1574Ssthen } 107a6cc1574Ssthen output[hashlen*2] = 0; 108a6cc1574Ssthen digestdup = strdup(digest); 109a6cc1574Ssthen unit_assert(digestdup); 110a6cc1574Ssthen for(i=0; i<strlen(digestdup); i++) { 111a6cc1574Ssthen digestdup[i] = toupper(digestdup[i]); 112a6cc1574Ssthen } 113a6cc1574Ssthen if(verbosity >= VERB_ALGO) { 114a6cc1574Ssthen char zname[255+1]; 115a6cc1574Ssthen dname_str(z->name, zname); 116a6cc1574Ssthen printf("zonemd generated for %s in %s with " 117a6cc1574Ssthen "scheme=%d hashalgo=%d\n", zname, z->zonefile, 118a6cc1574Ssthen scheme, hashalgo); 119a6cc1574Ssthen printf("digest %s\n", output); 120a6cc1574Ssthen printf("wanted %s\n", digestdup); 121a6cc1574Ssthen } 122a6cc1574Ssthen unit_assert(strcmp(output, digestdup) == 0); 123a6cc1574Ssthen 124a6cc1574Ssthen /* delete environment */ 125a6cc1574Ssthen free(digestdup); 126a6cc1574Ssthen auth_zones_delete(az); 127a6cc1574Ssthen regional_destroy(region); 128a6cc1574Ssthen sldns_buffer_free(buf); 129a6cc1574Ssthen 130a6cc1574Ssthen if(verbosity >= VERB_ALGO) { 131a6cc1574Ssthen printf("\n"); 132a6cc1574Ssthen } 133a6cc1574Ssthen } 134a6cc1574Ssthen 135a6cc1574Ssthen /** loop over files and test generated zonemd digest */ 136a6cc1574Ssthen static void zonemd_generate_tests(void) 137a6cc1574Ssthen { 138a6cc1574Ssthen unit_show_func("services/authzone.c", "auth_zone_generate_zonemd_hash"); 139a6cc1574Ssthen zonemd_generate_test("example.org", SRCDIRSTR "/testdata/zonemd.example1.zone", 140a6cc1574Ssthen 1, 2, "20564D10F50A0CEBEC856C64032B7DFB53D3C449A421A5BC7A21F7627B4ACEA4DF29F2C6FE82ED9C23ADF6F4D420D5DD63EF6E6349D60FDAB910B65DF8D481B7"); 141a6cc1574Ssthen 142a6cc1574Ssthen /* https://tools.ietf.org/html/draft-ietf-dnsop-dns-zone-digest-12 143a6cc1574Ssthen * from section A.1 */ 144a6cc1574Ssthen zonemd_generate_test("example", SRCDIRSTR "/testdata/zonemd.example_a1.zone", 145a6cc1574Ssthen 1, 1, "c68090d90a7aed716bc459f9340e3d7c1370d4d24b7e2fc3a1ddc0b9a87153b9a9713b3c9ae5cc27777f98b8e730044c"); 146a6cc1574Ssthen 147a6cc1574Ssthen /* https://tools.ietf.org/html/draft-ietf-dnsop-dns-zone-digest-12 148a6cc1574Ssthen * from section A.2 */ 149a6cc1574Ssthen zonemd_generate_test("example", SRCDIRSTR "/testdata/zonemd.example_a2.zone", 150a6cc1574Ssthen 1, 1, "31cefb03814f5062ad12fa951ba0ef5f8da6ae354a415767246f7dc932ceb1e742a2108f529db6a33a11c01493de358d"); 151a6cc1574Ssthen 152a6cc1574Ssthen /* https://tools.ietf.org/html/draft-ietf-dnsop-dns-zone-digest-12 153a6cc1574Ssthen * from section A.3 SHA384 digest */ 154a6cc1574Ssthen zonemd_generate_test("example", SRCDIRSTR "/testdata/zonemd.example_a3.zone", 155a6cc1574Ssthen 1, 1, "62e6cf51b02e54b9b5f967d547ce43136792901f9f88e637493daaf401c92c279dd10f0edb1c56f8080211f8480ee306"); 156a6cc1574Ssthen 157a6cc1574Ssthen /* https://tools.ietf.org/html/draft-ietf-dnsop-dns-zone-digest-12 158a6cc1574Ssthen * from section A.3 SHA512 digest*/ 159a6cc1574Ssthen zonemd_generate_test("example", SRCDIRSTR "/testdata/zonemd.example_a3.zone", 160a6cc1574Ssthen 1, 2, "08cfa1115c7b948c4163a901270395ea226a930cd2cbcf2fa9a5e6eb85f37c8a4e114d884e66f176eab121cb02db7d652e0cc4827e7a3204f166b47e5613fd27"); 161a6cc1574Ssthen 162a6cc1574Ssthen /* https://tools.ietf.org/html/draft-ietf-dnsop-dns-zone-digest-12 163a6cc1574Ssthen * from section A.4 */ 164a6cc1574Ssthen zonemd_generate_test("uri.arpa", SRCDIRSTR "/testdata/zonemd.example_a4.zone", 165a6cc1574Ssthen 1, 1, "1291b78ddf7669b1a39d014d87626b709b55774c5d7d58fadc556439889a10eaf6f11d615900a4f996bd46279514e473"); 166a6cc1574Ssthen 167a6cc1574Ssthen /* https://tools.ietf.org/html/draft-ietf-dnsop-dns-zone-digest-12 168a6cc1574Ssthen * from section A.5 */ 169a6cc1574Ssthen zonemd_generate_test("root-servers.net", SRCDIRSTR "/testdata/zonemd.example_a5.zone", 170a6cc1574Ssthen 1, 1, "f1ca0ccd91bd5573d9f431c00ee0101b2545c97602be0a978a3b11dbfc1c776d5b3e86ae3d973d6b5349ba7f04340f79"); 171a6cc1574Ssthen } 172a6cc1574Ssthen 173a6cc1574Ssthen /** test the zonemd check routine */ 174a6cc1574Ssthen static void zonemd_check_test(void) 175a6cc1574Ssthen { 176a6cc1574Ssthen const char* zname = "example.org"; 177a6cc1574Ssthen char* zfile = SRCDIRSTR "/testdata/zonemd.example1.zone"; 178a6cc1574Ssthen int scheme = 1; 179a6cc1574Ssthen int hashalgo = 2; 180a6cc1574Ssthen const char* digest = "20564D10F50A0CEBEC856C64032B7DFB53D3C449A421A5BC7A21F7627B4ACEA4DF29F2C6FE82ED9C23ADF6F4D420D5DD63EF6E6349D60FDAB910B65DF8D481B7"; 181a6cc1574Ssthen const char* digestwrong = "20564D10F50A0CEBEC856C64032B7DFB53D3C449A421A5BC7A21F7627B4ACEA4DF29F2C6FE82ED9C23ADF6F4D420D5DD63EF6E6349D60FDAB910B65DF8D48100"; 182a6cc1574Ssthen uint8_t hash[512], hashwrong[512]; 183a6cc1574Ssthen size_t hashlen = 0, hashwronglen = 0; 184a6cc1574Ssthen struct auth_zones* az; 185a6cc1574Ssthen struct auth_zone* z; 186a6cc1574Ssthen int result; 187a6cc1574Ssthen struct regional* region = NULL; 188a6cc1574Ssthen struct sldns_buffer* buf = NULL; 189a6cc1574Ssthen char* reason = NULL; 190a6cc1574Ssthen 191a6cc1574Ssthen if(!zonemd_hashalgo_supported(hashalgo)) 192a6cc1574Ssthen return; /* cannot test unsupported algo */ 193a6cc1574Ssthen unit_show_func("services/authzone.c", "auth_zone_generate_zonemd_check"); 194a6cc1574Ssthen 195a6cc1574Ssthen /* setup environment */ 196a6cc1574Ssthen az = auth_zones_create(); 197a6cc1574Ssthen unit_assert(az); 198a6cc1574Ssthen region = regional_create(); 199a6cc1574Ssthen unit_assert(region); 200a6cc1574Ssthen buf = sldns_buffer_new(65535); 201a6cc1574Ssthen unit_assert(buf); 202a6cc1574Ssthen 203a6cc1574Ssthen /* read file */ 204a6cc1574Ssthen z = authtest_addzone(az, zname, zfile); 205a6cc1574Ssthen unit_assert(z); 206a6cc1574Ssthen lock_rw_wrlock(&z->lock); 207a6cc1574Ssthen z->zonemd_check = 1; 208a6cc1574Ssthen lock_rw_unlock(&z->lock); 209a6cc1574Ssthen hashlen = sizeof(hash); 210a6cc1574Ssthen if(sldns_str2wire_hex_buf(digest, hash, &hashlen) != 0) { 211a6cc1574Ssthen unit_assert(0); /* parse failure */ 212a6cc1574Ssthen } 213a6cc1574Ssthen hashwronglen = sizeof(hashwrong); 214a6cc1574Ssthen if(sldns_str2wire_hex_buf(digestwrong, hashwrong, &hashwronglen) != 0) { 215a6cc1574Ssthen unit_assert(0); /* parse failure */ 216a6cc1574Ssthen } 217a6cc1574Ssthen 218a6cc1574Ssthen /* check return values of the check routine */ 219a6cc1574Ssthen result = auth_zone_generate_zonemd_check(z, scheme, hashalgo, 220a6cc1574Ssthen hash, hashlen, region, buf, &reason); 221a6cc1574Ssthen unit_assert(result && reason == NULL); 222a6cc1574Ssthen result = auth_zone_generate_zonemd_check(z, 241, hashalgo, 223a6cc1574Ssthen hash, hashlen, region, buf, &reason); 224c2862f41Ssthen unit_assert(result && strcmp(reason, "unsupported scheme")==0); 225a6cc1574Ssthen result = auth_zone_generate_zonemd_check(z, scheme, 242, 226a6cc1574Ssthen hash, hashlen, region, buf, &reason); 227c2862f41Ssthen unit_assert(result && strcmp(reason, "unsupported algorithm")==0); 228a6cc1574Ssthen result = auth_zone_generate_zonemd_check(z, scheme, hashalgo, 229a6cc1574Ssthen hash, 2, region, buf, &reason); 230a6cc1574Ssthen unit_assert(!result && strcmp(reason, "digest length too small, less than 12")==0); 231a6cc1574Ssthen result = auth_zone_generate_zonemd_check(z, scheme, hashalgo, 232a6cc1574Ssthen hashwrong, hashwronglen, region, buf, &reason); 233a6cc1574Ssthen unit_assert(!result && strcmp(reason, "incorrect digest")==0); 234a6cc1574Ssthen result = auth_zone_generate_zonemd_check(z, scheme, hashalgo, 235a6cc1574Ssthen hashwrong, hashwronglen-3, region, buf, &reason); 236a6cc1574Ssthen unit_assert(!result && strcmp(reason, "incorrect digest length")==0); 237a6cc1574Ssthen 238a6cc1574Ssthen /* delete environment */ 239a6cc1574Ssthen auth_zones_delete(az); 240a6cc1574Ssthen regional_destroy(region); 241a6cc1574Ssthen sldns_buffer_free(buf); 242a6cc1574Ssthen 243a6cc1574Ssthen if(verbosity >= VERB_ALGO) { 244a6cc1574Ssthen printf("\n"); 245a6cc1574Ssthen } 246a6cc1574Ssthen } 247a6cc1574Ssthen 248a6cc1574Ssthen /** zonemd test verify */ 249a6cc1574Ssthen static void zonemd_verify_test(char* zname, char* zfile, char* tastr, 250a6cc1574Ssthen char* date_override, char* result_wanted) 251a6cc1574Ssthen { 252a6cc1574Ssthen time_t now = 0; 253a6cc1574Ssthen struct module_stack mods; 254a6cc1574Ssthen struct module_env env; 255a6cc1574Ssthen char* result = NULL; 256a6cc1574Ssthen struct auth_zone* z; 257a6cc1574Ssthen 258a6cc1574Ssthen /* setup test harness */ 259a6cc1574Ssthen memset(&env, 0, sizeof(env)); 260a6cc1574Ssthen env.scratch = regional_create(); 261a6cc1574Ssthen if(!env.scratch) 262a6cc1574Ssthen fatal_exit("out of memory"); 263a6cc1574Ssthen env.scratch_buffer = sldns_buffer_new(65553); 264a6cc1574Ssthen if(!env.scratch_buffer) 265a6cc1574Ssthen fatal_exit("out of memory"); 266a6cc1574Ssthen env.cfg = config_create(); 267a6cc1574Ssthen if(!env.cfg) 268a6cc1574Ssthen fatal_exit("out of memory"); 269a6cc1574Ssthen env.now = &now; 270a6cc1574Ssthen env.cfg->val_date_override = cfg_convert_timeval(date_override); 271a6cc1574Ssthen if(!env.cfg->val_date_override) 272a6cc1574Ssthen fatal_exit("could not parse datetime %s", date_override); 273a6cc1574Ssthen if(env.cfg->module_conf) 274a6cc1574Ssthen free(env.cfg->module_conf); 275a6cc1574Ssthen env.cfg->module_conf = strdup("validator iterator"); 276a6cc1574Ssthen if(!env.cfg->module_conf) 277a6cc1574Ssthen fatal_exit("out of memory"); 278a6cc1574Ssthen if(tastr) { 279a6cc1574Ssthen if(!cfg_strlist_insert(&env.cfg->trust_anchor_list, 280a6cc1574Ssthen strdup(tastr))) 281a6cc1574Ssthen fatal_exit("out of memory"); 282a6cc1574Ssthen } 283a6cc1574Ssthen env.anchors = anchors_create(); 284a6cc1574Ssthen if(!env.anchors) 285a6cc1574Ssthen fatal_exit("out of memory"); 286a6cc1574Ssthen env.auth_zones = auth_zones_create(); 287a6cc1574Ssthen if(!env.auth_zones) 288a6cc1574Ssthen fatal_exit("out of memory"); 289a6cc1574Ssthen modstack_init(&mods); 290*a43524d9Ssthen if(!modstack_call_startup(&mods, env.cfg->module_conf, &env)) 291*a43524d9Ssthen fatal_exit("could not modstack_startup"); 292*a43524d9Ssthen if(!modstack_call_init(&mods, env.cfg->module_conf, &env)) 293*a43524d9Ssthen fatal_exit("could not modstack_call_init"); 294a6cc1574Ssthen env.mesh = mesh_create(&mods, &env); 295a6cc1574Ssthen if(!env.mesh) 296a6cc1574Ssthen fatal_exit("out of memory"); 297a6cc1574Ssthen 298a6cc1574Ssthen /* load data */ 299a6cc1574Ssthen z = authtest_addzone(env.auth_zones, zname, zfile); 300a6cc1574Ssthen if(!z) 301a6cc1574Ssthen fatal_exit("could not addzone %s %s", zname, zfile); 302a6cc1574Ssthen 303a6cc1574Ssthen /* test */ 304a6cc1574Ssthen lock_rw_wrlock(&z->lock); 305a6cc1574Ssthen z->zonemd_check = 1; 306a6cc1574Ssthen auth_zone_verify_zonemd(z, &env, &mods, &result, 1, 0); 307a6cc1574Ssthen lock_rw_unlock(&z->lock); 308a6cc1574Ssthen if(verbosity >= VERB_ALGO) { 309a6cc1574Ssthen printf("auth zone %s: ZONEMD verification %s: %s\n", zname, 310a6cc1574Ssthen (strcmp(result, "ZONEMD verification successful")==0?"successful":"failed"), 311a6cc1574Ssthen result); 312a6cc1574Ssthen } 313a6cc1574Ssthen if(!result) 314a6cc1574Ssthen fatal_exit("out of memory"); 315a6cc1574Ssthen unit_assert(strcmp(result, result_wanted) == 0); 316a6cc1574Ssthen if(strcmp(result, "ZONEMD verification successful") == 0 || 317a6cc1574Ssthen strcmp(result, "DNSSEC verified nonexistence of ZONEMD") == 0 || 318a6cc1574Ssthen strcmp(result, "no ZONEMD present") == 0) { 319a6cc1574Ssthen lock_rw_rdlock(&z->lock); 320a6cc1574Ssthen unit_assert(!z->zone_expired); 321a6cc1574Ssthen lock_rw_unlock(&z->lock); 322a6cc1574Ssthen } else { 323a6cc1574Ssthen lock_rw_rdlock(&z->lock); 324a6cc1574Ssthen unit_assert(z->zone_expired); 325a6cc1574Ssthen lock_rw_unlock(&z->lock); 326a6cc1574Ssthen } 327a6cc1574Ssthen free(result); 328a6cc1574Ssthen 329a6cc1574Ssthen /* desetup test harness */ 330a6cc1574Ssthen mesh_delete(env.mesh); 331*a43524d9Ssthen modstack_call_deinit(&mods, &env); 332*a43524d9Ssthen modstack_call_destartup(&mods, &env); 333*a43524d9Ssthen modstack_free(&mods); 334a6cc1574Ssthen auth_zones_delete(env.auth_zones); 335a6cc1574Ssthen anchors_delete(env.anchors); 336a6cc1574Ssthen config_delete(env.cfg); 337a6cc1574Ssthen regional_destroy(env.scratch); 338a6cc1574Ssthen sldns_buffer_free(env.scratch_buffer); 339a6cc1574Ssthen 340a6cc1574Ssthen if(verbosity >= VERB_ALGO) { 341a6cc1574Ssthen printf("\n"); 342a6cc1574Ssthen } 343a6cc1574Ssthen } 344a6cc1574Ssthen 345a6cc1574Ssthen /** zonemd test verify suite */ 346a6cc1574Ssthen static void zonemd_verify_tests(void) 347a6cc1574Ssthen { 348a6cc1574Ssthen unit_show_func("services/authzone.c", "auth_zone_verify_zonemd"); 349a6cc1574Ssthen /* give trustanchor for unsigned zone, should fail */ 350a6cc1574Ssthen zonemd_verify_test("example.org", 351a6cc1574Ssthen SRCDIRSTR "/testdata/zonemd.example1.zone", 352a6cc1574Ssthen "example.org. IN DS 55566 8 2 9c148338951ce1c3b5cd3da532f3d90dfcf92595148022f2c2fd98e5deee90af", 353a6cc1574Ssthen "20180302005009", 354a6cc1574Ssthen "verify DNSKEY RRset with trust anchor failed: have trust anchor, but zone has no DNSKEY"); 355a6cc1574Ssthen /* unsigned zone without ZONEMD in it */ 356a6cc1574Ssthen zonemd_verify_test("example.org", 357a6cc1574Ssthen SRCDIRSTR "/testdata/zonemd.example1.zone", 358a6cc1574Ssthen NULL, 359a6cc1574Ssthen "20180302005009", 360a6cc1574Ssthen "no ZONEMD present"); 361a6cc1574Ssthen /* no trust anchor, so it succeeds for zone with a correct ZONEMD */ 362a6cc1574Ssthen zonemd_verify_test("example.com", 363a6cc1574Ssthen SRCDIRSTR "/testdata/zonemd.example2.zone", 364a6cc1574Ssthen NULL, 365a6cc1574Ssthen "20180302005009", 366a6cc1574Ssthen "ZONEMD verification successful"); 367a6cc1574Ssthen /* trust anchor for another zone, so it is indeterminate */ 368a6cc1574Ssthen zonemd_verify_test("example.com", 369a6cc1574Ssthen SRCDIRSTR "/testdata/zonemd.example2.zone", 370a6cc1574Ssthen "example.org. IN DS 55566 8 2 9c148338951ce1c3b5cd3da532f3d90dfcf92595148022f2c2fd98e5deee90af", 371a6cc1574Ssthen "20180302005009", 372a6cc1574Ssthen "ZONEMD verification successful"); 373a6cc1574Ssthen 374a6cc1574Ssthen /* load a DNSSEC signed zone, but no trust anchor */ 375a6cc1574Ssthen /* this zonefile has an incorrect ZONEMD digest, with correct 376a6cc1574Ssthen * DNSSEC signature. */ 377a6cc1574Ssthen zonemd_verify_test("example.com", 378a6cc1574Ssthen SRCDIRSTR "/testdata/zonemd.example3.zone", 379a6cc1574Ssthen NULL, 380a6cc1574Ssthen "20180302005009", 381a6cc1574Ssthen "incorrect digest"); 382a6cc1574Ssthen /* load a DNSSEC zone with NSEC3, but no trust anchor */ 383a6cc1574Ssthen /* this zonefile has an incorrect ZONEMD digest, with correct 384a6cc1574Ssthen * DNSSEC signature. */ 385a6cc1574Ssthen zonemd_verify_test("example.com", 386a6cc1574Ssthen SRCDIRSTR "/testdata/zonemd.example4.zone", 387a6cc1574Ssthen NULL, 388a6cc1574Ssthen "20180302005009", 389a6cc1574Ssthen "incorrect digest"); 390a6cc1574Ssthen /* valid zonemd, in dnssec signed zone, no trust anchor*/ 391a6cc1574Ssthen /* this zonefile has a correct ZONEMD digest and 392a6cc1574Ssthen * correct DNSSEC signature */ 393a6cc1574Ssthen zonemd_verify_test("example.com", 394a6cc1574Ssthen SRCDIRSTR "/testdata/zonemd.example5.zone", 395a6cc1574Ssthen NULL, 396a6cc1574Ssthen "20180302005009", 397a6cc1574Ssthen "ZONEMD verification successful"); 398a6cc1574Ssthen /* valid zonemd, in dnssec NSEC3 zone, no trust anchor*/ 399a6cc1574Ssthen zonemd_verify_test("example.com", 400a6cc1574Ssthen SRCDIRSTR "/testdata/zonemd.example6.zone", 401a6cc1574Ssthen NULL, 402a6cc1574Ssthen "20180302005009", 403a6cc1574Ssthen "ZONEMD verification successful"); 404a6cc1574Ssthen 405a6cc1574Ssthen /* load a DNSSEC signed zone with a trust anchor, valid ZONEMD */ 406a6cc1574Ssthen zonemd_verify_test("example.com", 407a6cc1574Ssthen SRCDIRSTR "/testdata/zonemd.example5.zone", 408a6cc1574Ssthen "example.com. IN DS 55566 8 2 9c148338951ce1c3b5cd3da532f3d90dfcf92595148022f2c2fd98e5deee90af", 409a6cc1574Ssthen "20201020135527", 410a6cc1574Ssthen "ZONEMD verification successful"); 411a6cc1574Ssthen /* load a DNSSEC NSEC3 signed zone with a trust anchor, valid ZONEMD */ 412a6cc1574Ssthen zonemd_verify_test("example.com", 413a6cc1574Ssthen SRCDIRSTR "/testdata/zonemd.example6.zone", 414a6cc1574Ssthen "example.com. IN DS 55566 8 2 9c148338951ce1c3b5cd3da532f3d90dfcf92595148022f2c2fd98e5deee90af", 415a6cc1574Ssthen "20201020135527", 416a6cc1574Ssthen "ZONEMD verification successful"); 417a6cc1574Ssthen 418a6cc1574Ssthen /* load a DNSSEC NSEC zone without ZONEMD */ 419a6cc1574Ssthen zonemd_verify_test("example.com", 420a6cc1574Ssthen SRCDIRSTR "/testdata/zonemd.example7.zone", 421a6cc1574Ssthen "example.com. IN DS 55566 8 2 9c148338951ce1c3b5cd3da532f3d90dfcf92595148022f2c2fd98e5deee90af", 422a6cc1574Ssthen "20201020135527", 423a6cc1574Ssthen "DNSSEC verified nonexistence of ZONEMD"); 424a6cc1574Ssthen /* load a DNSSEC NSEC3 zone without ZONEMD */ 425a6cc1574Ssthen zonemd_verify_test("example.com", 426a6cc1574Ssthen SRCDIRSTR "/testdata/zonemd.example8.zone", 427a6cc1574Ssthen "example.com. IN DS 55566 8 2 9c148338951ce1c3b5cd3da532f3d90dfcf92595148022f2c2fd98e5deee90af", 428a6cc1574Ssthen "20201020135527", 429a6cc1574Ssthen "DNSSEC verified nonexistence of ZONEMD"); 430a6cc1574Ssthen 431a6cc1574Ssthen /* load DNSSEC zone but RRSIG on ZONEMD is wrong */ 432a6cc1574Ssthen zonemd_verify_test("example.com", 433a6cc1574Ssthen SRCDIRSTR "/testdata/zonemd.example9.zone", 434a6cc1574Ssthen "example.com. IN DS 55566 8 2 9c148338951ce1c3b5cd3da532f3d90dfcf92595148022f2c2fd98e5deee90af", 435a6cc1574Ssthen "20201020135527", 436a6cc1574Ssthen #ifdef HAVE_SSL 437a6cc1574Ssthen "DNSSEC verify failed for ZONEMD RRset: signature crypto failed" 438a6cc1574Ssthen #else /* HAVE_NETTLE */ 439a6cc1574Ssthen "DNSSEC verify failed for ZONEMD RRset: RSA signature verification failed" 440a6cc1574Ssthen #endif 441a6cc1574Ssthen ); 442a6cc1574Ssthen /* load DNSSEC zone but RRSIG on SOA is wrong */ 443a6cc1574Ssthen zonemd_verify_test("example.com", 444a6cc1574Ssthen SRCDIRSTR "/testdata/zonemd.example10.zone", 445a6cc1574Ssthen "example.com. IN DS 55566 8 2 9c148338951ce1c3b5cd3da532f3d90dfcf92595148022f2c2fd98e5deee90af", 446a6cc1574Ssthen "20201020135527", 447a6cc1574Ssthen #ifdef HAVE_SSL 448a6cc1574Ssthen "DNSSEC verify failed for SOA RRset: signature crypto failed" 449a6cc1574Ssthen #else /* HAVE_NETTLE */ 450a6cc1574Ssthen "DNSSEC verify failed for SOA RRset: RSA signature verification failed" 451a6cc1574Ssthen #endif 452a6cc1574Ssthen ); 453a6cc1574Ssthen 454a6cc1574Ssthen /* load DNSSEC zone without ZONEMD, but NSEC bitmap says it exists */ 455a6cc1574Ssthen zonemd_verify_test("example.com", 456a6cc1574Ssthen SRCDIRSTR "/testdata/zonemd.example11.zone", 457a6cc1574Ssthen "example.com. IN DS 55566 8 2 9c148338951ce1c3b5cd3da532f3d90dfcf92595148022f2c2fd98e5deee90af", 458a6cc1574Ssthen "20201020135527", 459a6cc1574Ssthen "DNSSEC NSEC bitmap says type ZONEMD exists"); 460a6cc1574Ssthen /* load DNSSEC zone without ZONEMD, but NSEC3 bitmap says it exists */ 461a6cc1574Ssthen zonemd_verify_test("example.com", 462a6cc1574Ssthen SRCDIRSTR "/testdata/zonemd.example12.zone", 463a6cc1574Ssthen "example.com. IN DS 55566 8 2 9c148338951ce1c3b5cd3da532f3d90dfcf92595148022f2c2fd98e5deee90af", 464a6cc1574Ssthen "20201020135527", 465a6cc1574Ssthen "DNSSEC NSEC3 bitmap says type ZONEMD exists"); 466a6cc1574Ssthen 467a6cc1574Ssthen /* load DNSSEC zone without ZONEMD, but RRSIG on NSEC not okay */ 468a6cc1574Ssthen zonemd_verify_test("example.com", 469a6cc1574Ssthen SRCDIRSTR "/testdata/zonemd.example13.zone", 470a6cc1574Ssthen "example.com. IN DS 55566 8 2 9c148338951ce1c3b5cd3da532f3d90dfcf92595148022f2c2fd98e5deee90af", 471a6cc1574Ssthen "20201020135527", 472a6cc1574Ssthen #ifdef HAVE_SSL 473a6cc1574Ssthen "DNSSEC verify failed for NSEC RRset: signature crypto failed" 474a6cc1574Ssthen #else /* HAVE_NETTLE */ 475a6cc1574Ssthen "DNSSEC verify failed for NSEC RRset: RSA signature verification failed" 476a6cc1574Ssthen #endif 477a6cc1574Ssthen ); 478a6cc1574Ssthen /* load DNSSEC zone without ZONEMD, but RRSIG on NSEC3 not okay */ 479a6cc1574Ssthen zonemd_verify_test("example.com", 480a6cc1574Ssthen SRCDIRSTR "/testdata/zonemd.example14.zone", 481a6cc1574Ssthen "example.com. IN DS 55566 8 2 9c148338951ce1c3b5cd3da532f3d90dfcf92595148022f2c2fd98e5deee90af", 482a6cc1574Ssthen "20201020135527", 483a6cc1574Ssthen #ifdef HAVE_SSL 484a6cc1574Ssthen "DNSSEC verify failed for NSEC3 RRset: signature crypto failed" 485a6cc1574Ssthen #else /* HAVE_NETTLE */ 486a6cc1574Ssthen "DNSSEC verify failed for NSEC3 RRset: RSA signature verification failed" 487a6cc1574Ssthen #endif 488a6cc1574Ssthen ); 489a6cc1574Ssthen 490a6cc1574Ssthen /* load DNSSEC zone, with ZONEMD, but DNSKEY RRSIG is not okay. */ 491a6cc1574Ssthen zonemd_verify_test("example.com", 492a6cc1574Ssthen SRCDIRSTR "/testdata/zonemd.example15.zone", 493a6cc1574Ssthen "example.com. IN DS 55566 8 2 9c148338951ce1c3b5cd3da532f3d90dfcf92595148022f2c2fd98e5deee90af", 494a6cc1574Ssthen "20201020135527", 495a6cc1574Ssthen #ifdef HAVE_SSL 496a6cc1574Ssthen "verify DNSKEY RRset with trust anchor failed: signature crypto failed" 497a6cc1574Ssthen #else /* HAVE_NETTLE */ 498a6cc1574Ssthen "verify DNSKEY RRset with trust anchor failed: RSA signature verification failed" 499a6cc1574Ssthen #endif 500a6cc1574Ssthen ); 501a6cc1574Ssthen /* load DNSSEC zone, but trust anchor mismatches DNSKEY */ 502a6cc1574Ssthen zonemd_verify_test("example.com", 503a6cc1574Ssthen SRCDIRSTR "/testdata/zonemd.example5.zone", 504a6cc1574Ssthen /* okay anchor is 505a6cc1574Ssthen "example.com. IN DS 55566 8 2 9c148338951ce1c3b5cd3da532f3d90dfcf92595148022f2c2fd98e5deee90af", */ 506a6cc1574Ssthen "example.com. IN DS 55566 8 2 0000000000111111222223333444444dfcf92595148022f2c2fd98e5deee90af", 507a6cc1574Ssthen "20201020135527", 508a6cc1574Ssthen "verify DNSKEY RRset with trust anchor failed: DS hash mismatches key"); 509a6cc1574Ssthen /* load DNSSEC zone, but trust anchor fails because the zone 510a6cc1574Ssthen * has expired signatures. We set the date for it */ 511a6cc1574Ssthen zonemd_verify_test("example.com", 512a6cc1574Ssthen SRCDIRSTR "/testdata/zonemd.example5.zone", 513a6cc1574Ssthen "example.com. IN DS 55566 8 2 9c148338951ce1c3b5cd3da532f3d90dfcf92595148022f2c2fd98e5deee90af", 514a6cc1574Ssthen /* okay date: "20201020135527", */ 515a6cc1574Ssthen "20221020135527", 516a6cc1574Ssthen "verify DNSKEY RRset with trust anchor failed: signature expired"); 517a6cc1574Ssthen 518a6cc1574Ssthen /* duplicate zonemd with same scheme and algorithm */ 519a6cc1574Ssthen zonemd_verify_test("example.com", 520a6cc1574Ssthen SRCDIRSTR "/testdata/zonemd.example16.zone", 521a6cc1574Ssthen NULL, 522a6cc1574Ssthen "20180302005009", 523a6cc1574Ssthen "ZONEMD RRSet contains more than one RR with the same scheme and hash algorithm"); 524a6cc1574Ssthen /* different capitalisation of ns name and owner names, should 525a6cc1574Ssthen * be canonicalized. */ 526a6cc1574Ssthen zonemd_verify_test("example.com", 527a6cc1574Ssthen SRCDIRSTR "/testdata/zonemd.example17.zone", 528a6cc1574Ssthen NULL, 529a6cc1574Ssthen "20180302005009", 530a6cc1574Ssthen "ZONEMD verification successful"); 531a6cc1574Ssthen } 532a6cc1574Ssthen 533a6cc1574Ssthen /** zonemd unit tests */ 534a6cc1574Ssthen void zonemd_test(void) 535a6cc1574Ssthen { 536a6cc1574Ssthen unit_show_feature("zonemd"); 537a6cc1574Ssthen zonemd_generate_tests(); 538a6cc1574Ssthen zonemd_check_test(); 539a6cc1574Ssthen zonemd_verify_tests(); 540a6cc1574Ssthen } 541