From: W.C.A. Wijngaards Date: Wed, 21 Oct 2020 10:04:53 +0000 (+0200) Subject: zonemd, zonemd unit test in own file. X-Git-Tag: release-1.13.2rc1~269^2~45 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c32c9a0ae24d99771b2f2aab255d7f3d9e7ec73e;p=thirdparty%2Funbound.git zonemd, zonemd unit test in own file. --- diff --git a/Makefile.in b/Makefile.in index d2600e71f..690a757ab 100644 --- a/Makefile.in +++ b/Makefile.in @@ -173,10 +173,10 @@ UNITTEST_SRC=testcode/unitanchor.c testcode/unitdname.c \ testcode/unitlruhash.c testcode/unitmain.c testcode/unitmsgparse.c \ testcode/unitneg.c testcode/unitregional.c testcode/unitslabhash.c \ testcode/unitverify.c testcode/readhex.c testcode/testpkts.c testcode/unitldns.c \ -testcode/unitecs.c testcode/unitauth.c +testcode/unitecs.c testcode/unitauth.c testcode/unitzonemd.c UNITTEST_OBJ=unitanchor.lo unitdname.lo unitlruhash.lo unitmain.lo \ unitmsgparse.lo unitneg.lo unitregional.lo unitslabhash.lo unitverify.lo \ -readhex.lo testpkts.lo unitldns.lo unitecs.lo unitauth.lo +readhex.lo testpkts.lo unitldns.lo unitecs.lo unitauth.lo unitzonemd.lo UNITTEST_OBJ_LINK=$(UNITTEST_OBJ) worker_cb.lo $(COMMON_OBJ) $(SLDNS_OBJ) \ $(COMPAT_OBJ) DAEMON_SRC=daemon/acl_list.c daemon/cachedump.c daemon/daemon.c \ @@ -1217,6 +1217,7 @@ unitldns.lo unitldns.o: $(srcdir)/testcode/unitldns.c config.h $(srcdir)/util/lo $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/wire2str.h \ $(srcdir)/sldns/parseutil.h unitecs.lo unitecs.o: $(srcdir)/testcode/unitecs.c config.h +unitzonemd.lo unitzonemd.o: $(srcdir)/testcode/unitzonemd.c config.h $(srcdir)/services/authzone.h unitauth.lo unitauth.o: $(srcdir)/testcode/unitauth.c config.h $(srcdir)/services/authzone.h \ $(srcdir)/util/rbtree.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/services/mesh.h $(srcdir)/util/netevent.h \ $(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/util/data/msgparse.h \ diff --git a/testcode/unitmain.c b/testcode/unitmain.c index ba2d33fc4..6a099b15e 100644 --- a/testcode/unitmain.c +++ b/testcode/unitmain.c @@ -839,380 +839,6 @@ static void respip_test(void) respip_conf_actions_test(); } -#include -#include "sldns/str2wire.h" -#include "services/authzone.h" -#include "util/data/dname.h" -#include "util/regional.h" -#include "validator/val_anchor.h" -/** Add zone from file for testing */ -struct auth_zone* authtest_addzone(struct auth_zones* az, const char* name, - char* fname); - -/** zonemd unit test, generate a zonemd digest and check if correct */ -static void zonemd_generate_test(const char* zname, char* zfile, - int scheme, int hashalgo, const char* digest) -{ - uint8_t zonemd_hash[512]; - size_t hashlen = 0; - char output[1024+1]; - size_t i; - struct auth_zones* az; - struct auth_zone* z; - int result; - struct regional* region = NULL; - struct sldns_buffer* buf = NULL; - char* reason = NULL; - char* digestdup; - - if(!zonemd_hashalgo_supported(hashalgo)) - return; /* cannot test unsupported algo */ - - /* setup environment */ - az = auth_zones_create(); - unit_assert(az); - region = regional_create(); - unit_assert(region); - buf = sldns_buffer_new(65535); - unit_assert(buf); - - /* read file */ - z = authtest_addzone(az, zname, zfile); - unit_assert(z); - - /* create zonemd digest */ - result = auth_zone_generate_zonemd_hash(z, scheme, hashalgo, - zonemd_hash, sizeof(zonemd_hash), &hashlen, region, buf, - &reason); - if(reason) printf("zonemd failure reason: %s\n", reason); - unit_assert(result); - - /* check digest */ - unit_assert(hashlen*2+1 <= sizeof(output)); - for(i=0; i>4]; - output[i*2+1] = hexl[zonemd_hash[i]&0xf]; - } - output[hashlen*2] = 0; - digestdup = strdup(digest); - unit_assert(digestdup); - for(i=0; i= VERB_ALGO) { - char zname[255+1]; - dname_str(z->name, zname); - printf("zonemd generated for %s in %s with " - "scheme=%d hashalgo=%d\n", zname, z->zonefile, - scheme, hashalgo); - printf("digest %s\n", output); - printf("wanted %s\n", digestdup); - } - unit_assert(strcmp(output, digestdup) == 0); - - /* delete environment */ - free(digestdup); - auth_zones_delete(az); - regional_destroy(region); - sldns_buffer_free(buf); - - if(verbosity >= VERB_ALGO) { - printf("\n"); - } -} - -/** loop over files and test generated zonemd digest */ -static void zonemd_generate_tests(void) -{ - unit_show_func("services/authzone.c", "auth_zone_generate_zonemd_hash"); - zonemd_generate_test("example.org", "testdata/zonemd.example1.zone", - 1, 2, "20564D10F50A0CEBEC856C64032B7DFB53D3C449A421A5BC7A21F7627B4ACEA4DF29F2C6FE82ED9C23ADF6F4D420D5DD63EF6E6349D60FDAB910B65DF8D481B7"); - - /* https://tools.ietf.org/html/draft-ietf-dnsop-dns-zone-digest-12 - * from section A.1 */ - zonemd_generate_test("example", "testdata/zonemd.example_a1.zone", - 1, 1, "c68090d90a7aed716bc459f9340e3d7c1370d4d24b7e2fc3a1ddc0b9a87153b9a9713b3c9ae5cc27777f98b8e730044c"); - - /* https://tools.ietf.org/html/draft-ietf-dnsop-dns-zone-digest-12 - * from section A.2 */ - zonemd_generate_test("example", "testdata/zonemd.example_a2.zone", - 1, 1, "31cefb03814f5062ad12fa951ba0ef5f8da6ae354a415767246f7dc932ceb1e742a2108f529db6a33a11c01493de358d"); - - /* https://tools.ietf.org/html/draft-ietf-dnsop-dns-zone-digest-12 - * from section A.3 SHA384 digest */ - zonemd_generate_test("example", "testdata/zonemd.example_a3.zone", - 1, 1, "62e6cf51b02e54b9b5f967d547ce43136792901f9f88e637493daaf401c92c279dd10f0edb1c56f8080211f8480ee306"); - - /* https://tools.ietf.org/html/draft-ietf-dnsop-dns-zone-digest-12 - * from section A.3 SHA512 digest*/ - zonemd_generate_test("example", "testdata/zonemd.example_a3.zone", - 1, 2, "08cfa1115c7b948c4163a901270395ea226a930cd2cbcf2fa9a5e6eb85f37c8a4e114d884e66f176eab121cb02db7d652e0cc4827e7a3204f166b47e5613fd27"); - - /* https://tools.ietf.org/html/draft-ietf-dnsop-dns-zone-digest-12 - * from section A.4 */ - zonemd_generate_test("uri.arpa", "testdata/zonemd.example_a4.zone", - 1, 1, "1291b78ddf7669b1a39d014d87626b709b55774c5d7d58fadc556439889a10eaf6f11d615900a4f996bd46279514e473"); - - /* https://tools.ietf.org/html/draft-ietf-dnsop-dns-zone-digest-12 - * from section A.5 */ - zonemd_generate_test("root-servers.net", "testdata/zonemd.example_a5.zone", - 1, 1, "f1ca0ccd91bd5573d9f431c00ee0101b2545c97602be0a978a3b11dbfc1c776d5b3e86ae3d973d6b5349ba7f04340f79"); -} - -/** test the zonemd check routine */ -static void zonemd_check_test(void) -{ - const char* zname = "example.org"; - char* zfile = "testdata/zonemd.example1.zone"; - int scheme = 1; - int hashalgo = 2; - const char* digest = "20564D10F50A0CEBEC856C64032B7DFB53D3C449A421A5BC7A21F7627B4ACEA4DF29F2C6FE82ED9C23ADF6F4D420D5DD63EF6E6349D60FDAB910B65DF8D481B7"; - const char* digestwrong = "20564D10F50A0CEBEC856C64032B7DFB53D3C449A421A5BC7A21F7627B4ACEA4DF29F2C6FE82ED9C23ADF6F4D420D5DD63EF6E6349D60FDAB910B65DF8D48100"; - uint8_t hash[512], hashwrong[512]; - size_t hashlen = 0, hashwronglen = 0; - struct auth_zones* az; - struct auth_zone* z; - int result; - struct regional* region = NULL; - struct sldns_buffer* buf = NULL; - char* reason = NULL; - - if(!zonemd_hashalgo_supported(hashalgo)) - return; /* cannot test unsupported algo */ - unit_show_func("services/authzone.c", "auth_zone_generate_zonemd_check"); - - /* setup environment */ - az = auth_zones_create(); - unit_assert(az); - region = regional_create(); - unit_assert(region); - buf = sldns_buffer_new(65535); - unit_assert(buf); - - /* read file */ - z = authtest_addzone(az, zname, zfile); - unit_assert(z); - hashlen = sizeof(hash); - if(sldns_str2wire_hex_buf(digest, hash, &hashlen) != 0) { - unit_assert(0); /* parse failure */ - } - hashwronglen = sizeof(hashwrong); - if(sldns_str2wire_hex_buf(digestwrong, hashwrong, &hashwronglen) != 0) { - unit_assert(0); /* parse failure */ - } - - /* check return values of the check routine */ - result = auth_zone_generate_zonemd_check(z, scheme, hashalgo, - hash, hashlen, region, buf, &reason); - unit_assert(result && reason == NULL); - result = auth_zone_generate_zonemd_check(z, 241, hashalgo, - hash, hashlen, region, buf, &reason); - unit_assert(!result && strcmp(reason, "unsupported scheme")==0); - result = auth_zone_generate_zonemd_check(z, scheme, 242, - hash, hashlen, region, buf, &reason); - unit_assert(!result && strcmp(reason, "unsupported algorithm")==0); - result = auth_zone_generate_zonemd_check(z, scheme, hashalgo, - hash, 2, region, buf, &reason); - unit_assert(!result && strcmp(reason, "digest length too small, less than 12")==0); - result = auth_zone_generate_zonemd_check(z, scheme, hashalgo, - hashwrong, hashwronglen, region, buf, &reason); - unit_assert(!result && strcmp(reason, "incorrect digest")==0); - result = auth_zone_generate_zonemd_check(z, scheme, hashalgo, - hashwrong, hashwronglen-3, region, buf, &reason); - unit_assert(!result && strcmp(reason, "incorrect digest length")==0); - - /* delete environment */ - auth_zones_delete(az); - regional_destroy(region); - sldns_buffer_free(buf); - - if(verbosity >= VERB_ALGO) { - printf("\n"); - } -} - -/** zonemd test verify */ -static void zonemd_verify_test(char* zname, char* zfile, char* tastr, - char* date_override, char* result_wanted) -{ - time_t now = 0; - struct module_stack mods; - struct module_env env; - char* result = NULL; - struct auth_zone* z; - - /* setup test harness */ - memset(&mods, 0, sizeof(mods)); - memset(&env, 0, sizeof(env)); - env.scratch = regional_create(); - if(!env.scratch) - fatal_exit("out of memory"); - env.scratch_buffer = sldns_buffer_new(65553); - if(!env.scratch_buffer) - fatal_exit("out of memory"); - env.cfg = config_create(); - if(!env.cfg) - fatal_exit("out of memory"); - env.now = &now; - env.cfg->val_date_override = cfg_convert_timeval(date_override); - if(!env.cfg->val_date_override) - fatal_exit("could not parse datetime %s", date_override); - if(env.cfg->module_conf) - free(env.cfg->module_conf); - env.cfg->module_conf = strdup("validator iterator"); - if(!env.cfg->module_conf) - fatal_exit("out of memory"); - if(tastr) { - if(!cfg_strlist_insert(&env.cfg->trust_anchor_list, - strdup(tastr))) - fatal_exit("out of memory"); - } - env.anchors = anchors_create(); - if(!env.anchors) - fatal_exit("out of memory"); - env.auth_zones = auth_zones_create(); - if(!env.auth_zones) - fatal_exit("out of memory"); - modstack_init(&mods); - if(!modstack_setup(&mods, env.cfg->module_conf, &env)) - fatal_exit("could not modstack_setup"); - env.mesh = mesh_create(&mods, &env); - if(!env.mesh) - fatal_exit("out of memory"); - - /* load data */ - z = authtest_addzone(env.auth_zones, zname, zfile); - if(!z) - fatal_exit("could not addzone %s %s", zname, zfile); - - /* test */ - lock_rw_wrlock(&z->lock); - auth_zone_verify_zonemd(z, &env, &result); - lock_rw_unlock(&z->lock); - if(verbosity >= VERB_ALGO) { - printf("auth zone %s: ZONEMD verification %s: %s\n", zname, - (strcmp(result, "ZONEMD verification successful")==0?"successful":"failed"), - result); - } - if(!result) - fatal_exit("out of memory"); - unit_assert(strcmp(result, result_wanted) == 0); - if(strcmp(result, "ZONEMD verification successful") == 0 || - strcmp(result, "DNSSEC verified nonexistence of ZONEMD") == 0 || - strcmp(result, "no ZONEMD present") == 0) { - lock_rw_rdlock(&z->lock); - unit_assert(!z->zone_expired); - lock_rw_unlock(&z->lock); - } else { - lock_rw_rdlock(&z->lock); - unit_assert(z->zone_expired); - lock_rw_unlock(&z->lock); - } - free(result); - - /* desetup test harness */ - mesh_delete(env.mesh); - modstack_desetup(&mods, &env); - auth_zones_delete(env.auth_zones); - anchors_delete(env.anchors); - config_delete(env.cfg); - regional_destroy(env.scratch); - sldns_buffer_free(env.scratch_buffer); - - if(verbosity >= VERB_ALGO) { - printf("\n"); - } -} - -/** zonemd test verify suite */ -static void zonemd_verify_tests(void) -{ - unit_show_func("services/authzone.c", "auth_zone_verify_zonemd"); - zonemd_verify_test("example.org", - "testdata/zonemd.example1.zone", - "example.org. IN DS 55566 8 2 9c148338951ce1c3b5cd3da532f3d90dfcf92595148022f2c2fd98e5deee90af", - "20180302005009", - "have trust anchor, but zone has no DNSKEY"); - zonemd_verify_test("example.org", - "testdata/zonemd.example1.zone", - NULL, - "20180302005009", - "no ZONEMD present"); - /* no trust anchor, so it succeeds */ - zonemd_verify_test("example.com", - "testdata/zonemd.example2.zone", - NULL, - "20180302005009", - "ZONEMD verification successful"); - /* trust anchor for another zone, so it is indeterminate */ - zonemd_verify_test("example.com", - "testdata/zonemd.example2.zone", - "example.org. IN DS 55566 8 2 9c148338951ce1c3b5cd3da532f3d90dfcf92595148022f2c2fd98e5deee90af", - "20180302005009", - "ZONEMD verification successful"); - - /* load a DNSSEC signed zone, but no trust anchor */ - zonemd_verify_test("example.com", - "testdata/zonemd.example3.zone", - NULL, - "20180302005009", - "incorrect digest"); - /* load a DNSSEC zone with NSEC3, but no trust anchor */ - zonemd_verify_test("example.com", - "testdata/zonemd.example4.zone", - NULL, - "20180302005009", - "incorrect digest"); - /* valid zonemd, in dnssec signed zone, no trust anchor*/ - zonemd_verify_test("example.com", - "testdata/zonemd.example5.zone", - NULL, - "20180302005009", - "ZONEMD verification successful"); - /* valid zonemd, in dnssec NSEC3 zone, no trust anchor*/ - zonemd_verify_test("example.com", - "testdata/zonemd.example6.zone", - NULL, - "20180302005009", - "ZONEMD verification successful"); - - /* load a DNSSEC signed zone with a trust anchor, valid ZONEMD */ - zonemd_verify_test("example.com", - "testdata/zonemd.example5.zone", - "example.com. IN DS 55566 8 2 9c148338951ce1c3b5cd3da532f3d90dfcf92595148022f2c2fd98e5deee90af", - "20201020135527", - "ZONEMD verification successful"); - /* load a DNSSEC NSEC3 signed zone with a trust anchor, valid ZONEMD */ - zonemd_verify_test("example.com", - "testdata/zonemd.example6.zone", - "example.com. IN DS 55566 8 2 9c148338951ce1c3b5cd3da532f3d90dfcf92595148022f2c2fd98e5deee90af", - "20201020135527", - "ZONEMD verification successful"); - - /* load a DNSSEC NSEC zone without ZONEMD */ - zonemd_verify_test("example.com", - "testdata/zonemd.example7.zone", - "example.com. IN DS 55566 8 2 9c148338951ce1c3b5cd3da532f3d90dfcf92595148022f2c2fd98e5deee90af", - "20201020135527", - "DNSSEC verified nonexistence of ZONEMD"); - /* load a DNSSEC NSEC3 zone without ZONEMD */ - zonemd_verify_test("example.com", - "testdata/zonemd.example8.zone", - "example.com. IN DS 55566 8 2 9c148338951ce1c3b5cd3da532f3d90dfcf92595148022f2c2fd98e5deee90af", - "20201020135527", - "DNSSEC verified nonexistence of ZONEMD"); -} - -/** zonemd unit tests */ -static void zonemd_test(void) -{ - unit_show_feature("zonemd"); - zonemd_generate_tests(); - zonemd_check_test(); - zonemd_verify_tests(); -} - void unit_show_func(const char* file, const char* func) { printf("test %s:%s\n", file, func); diff --git a/testcode/unitmain.h b/testcode/unitmain.h index e5c6109a2..66d1322f2 100644 --- a/testcode/unitmain.h +++ b/testcode/unitmain.h @@ -80,5 +80,7 @@ void ecs_test(void); void ldns_test(void); /** unit test for auth zone functions */ void authzone_test(void); +/** unit test for zonemd functions */ +void zonemd_test(void); #endif /* TESTCODE_UNITMAIN_H */ diff --git a/testcode/unitzonemd.c b/testcode/unitzonemd.c new file mode 100644 index 000000000..8ba8fedc6 --- /dev/null +++ b/testcode/unitzonemd.c @@ -0,0 +1,417 @@ +/* + * testcode/unitzonemd.c - unit test for zonemd. + * + * Copyright (c) 2020, NLnet Labs. All rights reserved. + * + * This software is open source. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NLNET LABS nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** + * \file + * Unit tests for ZONEMD functionality. + */ + +#include "config.h" +#include +#include "util/log.h" +#include "testcode/unitmain.h" +#include "sldns/str2wire.h" +#include "services/authzone.h" +#include "util/data/dname.h" +#include "util/regional.h" +#include "validator/val_anchor.h" + +/** Add zone from file for testing */ +struct auth_zone* authtest_addzone(struct auth_zones* az, const char* name, + char* fname); + +/** zonemd unit test, generate a zonemd digest and check if correct */ +static void zonemd_generate_test(const char* zname, char* zfile, + int scheme, int hashalgo, const char* digest) +{ + uint8_t zonemd_hash[512]; + size_t hashlen = 0; + char output[1024+1]; + size_t i; + struct auth_zones* az; + struct auth_zone* z; + int result; + struct regional* region = NULL; + struct sldns_buffer* buf = NULL; + char* reason = NULL; + char* digestdup; + + if(!zonemd_hashalgo_supported(hashalgo)) + return; /* cannot test unsupported algo */ + + /* setup environment */ + az = auth_zones_create(); + unit_assert(az); + region = regional_create(); + unit_assert(region); + buf = sldns_buffer_new(65535); + unit_assert(buf); + + /* read file */ + z = authtest_addzone(az, zname, zfile); + unit_assert(z); + + /* create zonemd digest */ + result = auth_zone_generate_zonemd_hash(z, scheme, hashalgo, + zonemd_hash, sizeof(zonemd_hash), &hashlen, region, buf, + &reason); + if(reason) printf("zonemd failure reason: %s\n", reason); + unit_assert(result); + + /* check digest */ + unit_assert(hashlen*2+1 <= sizeof(output)); + for(i=0; i>4]; + output[i*2+1] = hexl[zonemd_hash[i]&0xf]; + } + output[hashlen*2] = 0; + digestdup = strdup(digest); + unit_assert(digestdup); + for(i=0; i= VERB_ALGO) { + char zname[255+1]; + dname_str(z->name, zname); + printf("zonemd generated for %s in %s with " + "scheme=%d hashalgo=%d\n", zname, z->zonefile, + scheme, hashalgo); + printf("digest %s\n", output); + printf("wanted %s\n", digestdup); + } + unit_assert(strcmp(output, digestdup) == 0); + + /* delete environment */ + free(digestdup); + auth_zones_delete(az); + regional_destroy(region); + sldns_buffer_free(buf); + + if(verbosity >= VERB_ALGO) { + printf("\n"); + } +} + +/** loop over files and test generated zonemd digest */ +static void zonemd_generate_tests(void) +{ + unit_show_func("services/authzone.c", "auth_zone_generate_zonemd_hash"); + zonemd_generate_test("example.org", "testdata/zonemd.example1.zone", + 1, 2, "20564D10F50A0CEBEC856C64032B7DFB53D3C449A421A5BC7A21F7627B4ACEA4DF29F2C6FE82ED9C23ADF6F4D420D5DD63EF6E6349D60FDAB910B65DF8D481B7"); + + /* https://tools.ietf.org/html/draft-ietf-dnsop-dns-zone-digest-12 + * from section A.1 */ + zonemd_generate_test("example", "testdata/zonemd.example_a1.zone", + 1, 1, "c68090d90a7aed716bc459f9340e3d7c1370d4d24b7e2fc3a1ddc0b9a87153b9a9713b3c9ae5cc27777f98b8e730044c"); + + /* https://tools.ietf.org/html/draft-ietf-dnsop-dns-zone-digest-12 + * from section A.2 */ + zonemd_generate_test("example", "testdata/zonemd.example_a2.zone", + 1, 1, "31cefb03814f5062ad12fa951ba0ef5f8da6ae354a415767246f7dc932ceb1e742a2108f529db6a33a11c01493de358d"); + + /* https://tools.ietf.org/html/draft-ietf-dnsop-dns-zone-digest-12 + * from section A.3 SHA384 digest */ + zonemd_generate_test("example", "testdata/zonemd.example_a3.zone", + 1, 1, "62e6cf51b02e54b9b5f967d547ce43136792901f9f88e637493daaf401c92c279dd10f0edb1c56f8080211f8480ee306"); + + /* https://tools.ietf.org/html/draft-ietf-dnsop-dns-zone-digest-12 + * from section A.3 SHA512 digest*/ + zonemd_generate_test("example", "testdata/zonemd.example_a3.zone", + 1, 2, "08cfa1115c7b948c4163a901270395ea226a930cd2cbcf2fa9a5e6eb85f37c8a4e114d884e66f176eab121cb02db7d652e0cc4827e7a3204f166b47e5613fd27"); + + /* https://tools.ietf.org/html/draft-ietf-dnsop-dns-zone-digest-12 + * from section A.4 */ + zonemd_generate_test("uri.arpa", "testdata/zonemd.example_a4.zone", + 1, 1, "1291b78ddf7669b1a39d014d87626b709b55774c5d7d58fadc556439889a10eaf6f11d615900a4f996bd46279514e473"); + + /* https://tools.ietf.org/html/draft-ietf-dnsop-dns-zone-digest-12 + * from section A.5 */ + zonemd_generate_test("root-servers.net", "testdata/zonemd.example_a5.zone", + 1, 1, "f1ca0ccd91bd5573d9f431c00ee0101b2545c97602be0a978a3b11dbfc1c776d5b3e86ae3d973d6b5349ba7f04340f79"); +} + +/** test the zonemd check routine */ +static void zonemd_check_test(void) +{ + const char* zname = "example.org"; + char* zfile = "testdata/zonemd.example1.zone"; + int scheme = 1; + int hashalgo = 2; + const char* digest = "20564D10F50A0CEBEC856C64032B7DFB53D3C449A421A5BC7A21F7627B4ACEA4DF29F2C6FE82ED9C23ADF6F4D420D5DD63EF6E6349D60FDAB910B65DF8D481B7"; + const char* digestwrong = "20564D10F50A0CEBEC856C64032B7DFB53D3C449A421A5BC7A21F7627B4ACEA4DF29F2C6FE82ED9C23ADF6F4D420D5DD63EF6E6349D60FDAB910B65DF8D48100"; + uint8_t hash[512], hashwrong[512]; + size_t hashlen = 0, hashwronglen = 0; + struct auth_zones* az; + struct auth_zone* z; + int result; + struct regional* region = NULL; + struct sldns_buffer* buf = NULL; + char* reason = NULL; + + if(!zonemd_hashalgo_supported(hashalgo)) + return; /* cannot test unsupported algo */ + unit_show_func("services/authzone.c", "auth_zone_generate_zonemd_check"); + + /* setup environment */ + az = auth_zones_create(); + unit_assert(az); + region = regional_create(); + unit_assert(region); + buf = sldns_buffer_new(65535); + unit_assert(buf); + + /* read file */ + z = authtest_addzone(az, zname, zfile); + unit_assert(z); + hashlen = sizeof(hash); + if(sldns_str2wire_hex_buf(digest, hash, &hashlen) != 0) { + unit_assert(0); /* parse failure */ + } + hashwronglen = sizeof(hashwrong); + if(sldns_str2wire_hex_buf(digestwrong, hashwrong, &hashwronglen) != 0) { + unit_assert(0); /* parse failure */ + } + + /* check return values of the check routine */ + result = auth_zone_generate_zonemd_check(z, scheme, hashalgo, + hash, hashlen, region, buf, &reason); + unit_assert(result && reason == NULL); + result = auth_zone_generate_zonemd_check(z, 241, hashalgo, + hash, hashlen, region, buf, &reason); + unit_assert(!result && strcmp(reason, "unsupported scheme")==0); + result = auth_zone_generate_zonemd_check(z, scheme, 242, + hash, hashlen, region, buf, &reason); + unit_assert(!result && strcmp(reason, "unsupported algorithm")==0); + result = auth_zone_generate_zonemd_check(z, scheme, hashalgo, + hash, 2, region, buf, &reason); + unit_assert(!result && strcmp(reason, "digest length too small, less than 12")==0); + result = auth_zone_generate_zonemd_check(z, scheme, hashalgo, + hashwrong, hashwronglen, region, buf, &reason); + unit_assert(!result && strcmp(reason, "incorrect digest")==0); + result = auth_zone_generate_zonemd_check(z, scheme, hashalgo, + hashwrong, hashwronglen-3, region, buf, &reason); + unit_assert(!result && strcmp(reason, "incorrect digest length")==0); + + /* delete environment */ + auth_zones_delete(az); + regional_destroy(region); + sldns_buffer_free(buf); + + if(verbosity >= VERB_ALGO) { + printf("\n"); + } +} + +/** zonemd test verify */ +static void zonemd_verify_test(char* zname, char* zfile, char* tastr, + char* date_override, char* result_wanted) +{ + time_t now = 0; + struct module_stack mods; + struct module_env env; + char* result = NULL; + struct auth_zone* z; + + /* setup test harness */ + memset(&mods, 0, sizeof(mods)); + memset(&env, 0, sizeof(env)); + env.scratch = regional_create(); + if(!env.scratch) + fatal_exit("out of memory"); + env.scratch_buffer = sldns_buffer_new(65553); + if(!env.scratch_buffer) + fatal_exit("out of memory"); + env.cfg = config_create(); + if(!env.cfg) + fatal_exit("out of memory"); + env.now = &now; + env.cfg->val_date_override = cfg_convert_timeval(date_override); + if(!env.cfg->val_date_override) + fatal_exit("could not parse datetime %s", date_override); + if(env.cfg->module_conf) + free(env.cfg->module_conf); + env.cfg->module_conf = strdup("validator iterator"); + if(!env.cfg->module_conf) + fatal_exit("out of memory"); + if(tastr) { + if(!cfg_strlist_insert(&env.cfg->trust_anchor_list, + strdup(tastr))) + fatal_exit("out of memory"); + } + env.anchors = anchors_create(); + if(!env.anchors) + fatal_exit("out of memory"); + env.auth_zones = auth_zones_create(); + if(!env.auth_zones) + fatal_exit("out of memory"); + modstack_init(&mods); + if(!modstack_setup(&mods, env.cfg->module_conf, &env)) + fatal_exit("could not modstack_setup"); + env.mesh = mesh_create(&mods, &env); + if(!env.mesh) + fatal_exit("out of memory"); + + /* load data */ + z = authtest_addzone(env.auth_zones, zname, zfile); + if(!z) + fatal_exit("could not addzone %s %s", zname, zfile); + + /* test */ + lock_rw_wrlock(&z->lock); + auth_zone_verify_zonemd(z, &env, &result); + lock_rw_unlock(&z->lock); + if(verbosity >= VERB_ALGO) { + printf("auth zone %s: ZONEMD verification %s: %s\n", zname, + (strcmp(result, "ZONEMD verification successful")==0?"successful":"failed"), + result); + } + if(!result) + fatal_exit("out of memory"); + unit_assert(strcmp(result, result_wanted) == 0); + if(strcmp(result, "ZONEMD verification successful") == 0 || + strcmp(result, "DNSSEC verified nonexistence of ZONEMD") == 0 || + strcmp(result, "no ZONEMD present") == 0) { + lock_rw_rdlock(&z->lock); + unit_assert(!z->zone_expired); + lock_rw_unlock(&z->lock); + } else { + lock_rw_rdlock(&z->lock); + unit_assert(z->zone_expired); + lock_rw_unlock(&z->lock); + } + free(result); + + /* desetup test harness */ + mesh_delete(env.mesh); + modstack_desetup(&mods, &env); + auth_zones_delete(env.auth_zones); + anchors_delete(env.anchors); + config_delete(env.cfg); + regional_destroy(env.scratch); + sldns_buffer_free(env.scratch_buffer); + + if(verbosity >= VERB_ALGO) { + printf("\n"); + } +} + +/** zonemd test verify suite */ +static void zonemd_verify_tests(void) +{ + unit_show_func("services/authzone.c", "auth_zone_verify_zonemd"); + zonemd_verify_test("example.org", + "testdata/zonemd.example1.zone", + "example.org. IN DS 55566 8 2 9c148338951ce1c3b5cd3da532f3d90dfcf92595148022f2c2fd98e5deee90af", + "20180302005009", + "have trust anchor, but zone has no DNSKEY"); + zonemd_verify_test("example.org", + "testdata/zonemd.example1.zone", + NULL, + "20180302005009", + "no ZONEMD present"); + /* no trust anchor, so it succeeds */ + zonemd_verify_test("example.com", + "testdata/zonemd.example2.zone", + NULL, + "20180302005009", + "ZONEMD verification successful"); + /* trust anchor for another zone, so it is indeterminate */ + zonemd_verify_test("example.com", + "testdata/zonemd.example2.zone", + "example.org. IN DS 55566 8 2 9c148338951ce1c3b5cd3da532f3d90dfcf92595148022f2c2fd98e5deee90af", + "20180302005009", + "ZONEMD verification successful"); + + /* load a DNSSEC signed zone, but no trust anchor */ + zonemd_verify_test("example.com", + "testdata/zonemd.example3.zone", + NULL, + "20180302005009", + "incorrect digest"); + /* load a DNSSEC zone with NSEC3, but no trust anchor */ + zonemd_verify_test("example.com", + "testdata/zonemd.example4.zone", + NULL, + "20180302005009", + "incorrect digest"); + /* valid zonemd, in dnssec signed zone, no trust anchor*/ + zonemd_verify_test("example.com", + "testdata/zonemd.example5.zone", + NULL, + "20180302005009", + "ZONEMD verification successful"); + /* valid zonemd, in dnssec NSEC3 zone, no trust anchor*/ + zonemd_verify_test("example.com", + "testdata/zonemd.example6.zone", + NULL, + "20180302005009", + "ZONEMD verification successful"); + + /* load a DNSSEC signed zone with a trust anchor, valid ZONEMD */ + zonemd_verify_test("example.com", + "testdata/zonemd.example5.zone", + "example.com. IN DS 55566 8 2 9c148338951ce1c3b5cd3da532f3d90dfcf92595148022f2c2fd98e5deee90af", + "20201020135527", + "ZONEMD verification successful"); + /* load a DNSSEC NSEC3 signed zone with a trust anchor, valid ZONEMD */ + zonemd_verify_test("example.com", + "testdata/zonemd.example6.zone", + "example.com. IN DS 55566 8 2 9c148338951ce1c3b5cd3da532f3d90dfcf92595148022f2c2fd98e5deee90af", + "20201020135527", + "ZONEMD verification successful"); + + /* load a DNSSEC NSEC zone without ZONEMD */ + zonemd_verify_test("example.com", + "testdata/zonemd.example7.zone", + "example.com. IN DS 55566 8 2 9c148338951ce1c3b5cd3da532f3d90dfcf92595148022f2c2fd98e5deee90af", + "20201020135527", + "DNSSEC verified nonexistence of ZONEMD"); + /* load a DNSSEC NSEC3 zone without ZONEMD */ + zonemd_verify_test("example.com", + "testdata/zonemd.example8.zone", + "example.com. IN DS 55566 8 2 9c148338951ce1c3b5cd3da532f3d90dfcf92595148022f2c2fd98e5deee90af", + "20201020135527", + "DNSSEC verified nonexistence of ZONEMD"); +} + +/** zonemd unit tests */ +void zonemd_test(void) +{ + unit_show_feature("zonemd"); + zonemd_generate_tests(); + zonemd_check_test(); + zonemd_verify_tests(); +}