From 21f69b010f56b94361da902c91833e84361f12bd Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Wed, 23 Jun 2021 19:52:08 +1000 Subject: [PATCH] Add dns_zonemd functions - dns_zonemd_buildrdata() iterates a zone database and constructs a ZONEMD record using the SIMPLE digest scheme described in RFC 8976. - dns_zonemd_supported() checks a ZONEMD record and returns true if the scheme and hash algorithm are supported by this server. (Currently the only supported scheme is SIMPLE, and the supported hash algorithms are SHA-384 and SHA-512.) --- lib/dns/dnssec.c | 70 +--- lib/dns/include/dns/rdataset.h | 17 + lib/dns/include/dns/zonemd.h | 27 ++ lib/dns/meson.build | 1 + lib/dns/rdataset.c | 48 +++ lib/dns/zonemd.c | 441 +++++++++++++++++++++++ tests/dns/meson.build | 1 + tests/dns/testdata/zonemd/rfc8976.A.1.db | 13 + tests/dns/testdata/zonemd/rfc8976.A.2.db | 34 ++ tests/dns/testdata/zonemd/rfc8976.A.3.db | 30 ++ tests/dns/testdata/zonemd/rfc8976.A.4.db | 128 +++++++ tests/dns/testdata/zonemd/rfc8976.A.5.db | 48 +++ tests/dns/zonemd_test.c | 142 ++++++++ 13 files changed, 936 insertions(+), 64 deletions(-) create mode 100644 lib/dns/include/dns/zonemd.h create mode 100644 lib/dns/zonemd.c create mode 100644 tests/dns/testdata/zonemd/rfc8976.A.1.db create mode 100644 tests/dns/testdata/zonemd/rfc8976.A.2.db create mode 100644 tests/dns/testdata/zonemd/rfc8976.A.3.db create mode 100644 tests/dns/testdata/zonemd/rfc8976.A.4.db create mode 100644 tests/dns/testdata/zonemd/rfc8976.A.5.db create mode 100644 tests/dns/zonemd_test.c diff --git a/lib/dns/dnssec.c b/lib/dns/dnssec.c index dffddd9a0b..41c887f37f 100644 --- a/lib/dns/dnssec.c +++ b/lib/dns/dnssec.c @@ -56,13 +56,6 @@ isc_stats_t *dns_dnssec_stats; static isc_result_t digest_callback(void *arg, isc_region_t *data); -static int -rdata_compare_wrapper(const void *rdata1, const void *rdata2); - -static isc_result_t -rdataset_to_sortedarray(dns_rdataset_t *set, isc_mem_t *mctx, - dns_rdata_t **rdata, int *nrdata); - static isc_result_t digest_callback(void *arg, isc_region_t *data) { dst_context_t *ctx = arg; @@ -77,57 +70,6 @@ inc_stat(isc_statscounter_t counter) { } } -/* - * Make qsort happy. - */ -static int -rdata_compare_wrapper(const void *rdata1, const void *rdata2) { - return dns_rdata_compare((const dns_rdata_t *)rdata1, - (const dns_rdata_t *)rdata2); -} - -/* - * Sort the rdataset into an array. - */ -static isc_result_t -rdataset_to_sortedarray(dns_rdataset_t *set, isc_mem_t *mctx, - dns_rdata_t **rdata, int *nrdata) { - isc_result_t ret; - int i = 0, n; - dns_rdata_t *data; - dns_rdataset_t rdataset; - - n = dns_rdataset_count(set); - - data = isc_mem_cget(mctx, n, sizeof(dns_rdata_t)); - - dns_rdataset_init(&rdataset); - dns_rdataset_clone(set, &rdataset); - ret = dns_rdataset_first(&rdataset); - if (ret != ISC_R_SUCCESS) { - dns_rdataset_disassociate(&rdataset); - isc_mem_cput(mctx, data, n, sizeof(dns_rdata_t)); - return ret; - } - - /* - * Put them in the array. - */ - do { - dns_rdata_init(&data[i]); - dns_rdataset_current(&rdataset, &data[i++]); - } while (dns_rdataset_next(&rdataset) == ISC_R_SUCCESS); - - /* - * Sort the array. - */ - qsort(data, n, sizeof(dns_rdata_t), rdata_compare_wrapper); - *rdata = data; - *nrdata = n; - dns_rdataset_disassociate(&rdataset); - return ISC_R_SUCCESS; -} - isc_result_t dns_dnssec_keyfromrdata(const dns_name_t *name, const dns_rdata_t *rdata, isc_mem_t *mctx, dst_key_t **key) { @@ -183,8 +125,8 @@ dns_dnssec_sign(const dns_name_t *name, dns_rdataset_t *set, dst_key_t *key, isc_mem_t *mctx, isc_buffer_t *buffer, dns_rdata_t *sigrdata) { dns_rdata_rrsig_t sig; dns_rdata_t tmpsigrdata; - dns_rdata_t *rdatas; - int nrdatas, i; + dns_rdata_t *rdatas = NULL; + unsigned int nrdatas, i; isc_buffer_t sigbuf, envbuf; isc_region_t r; dst_context_t *ctx = NULL; @@ -280,7 +222,7 @@ dns_dnssec_sign(const dns_name_t *name, dns_rdataset_t *set, dst_key_t *key, isc_buffer_putuint16(&envbuf, set->rdclass); isc_buffer_putuint32(&envbuf, set->ttl); - ret = rdataset_to_sortedarray(set, mctx, &rdatas, &nrdatas); + ret = dns_rdataset_tosortedarray(set, mctx, &rdatas, &nrdatas); if (ret != ISC_R_SUCCESS) { goto cleanup_context; } @@ -360,8 +302,8 @@ dns_dnssec_verify(const dns_name_t *name, dns_rdataset_t *set, dst_key_t *key, dns_fixedname_t fnewname; isc_region_t r; isc_buffer_t envbuf; - dns_rdata_t *rdatas; - int nrdatas, i; + dns_rdata_t *rdatas = NULL; + unsigned int nrdatas, i; isc_stdtime_t now; isc_result_t ret; unsigned char data[300]; @@ -476,7 +418,7 @@ again: isc_buffer_putuint16(&envbuf, set->rdclass); isc_buffer_putuint32(&envbuf, sig.originalttl); - ret = rdataset_to_sortedarray(set, mctx, &rdatas, &nrdatas); + ret = dns_rdataset_tosortedarray(set, mctx, &rdatas, &nrdatas); if (ret != ISC_R_SUCCESS) { goto cleanup_context; } diff --git a/lib/dns/include/dns/rdataset.h b/lib/dns/include/dns/rdataset.h index 5934d9b0ac..c31333f93d 100644 --- a/lib/dns/include/dns/rdataset.h +++ b/lib/dns/include/dns/rdataset.h @@ -413,6 +413,23 @@ dns_rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata); *\li 'rdataset'. */ +isc_result_t +dns_rdataset_tosortedarray(dns_rdataset_t *rdataset, isc_mem_t *mctx, + dns_rdata_t **rdata, unsigned int *nrdata); +/*%< + * Sort the rdata that make up the 'rdataset' in the the array 'rdata' + * in DNSSEC order with the length of the array returned in 'nrdata'. + * + * Requires: + *\li 'rdataset' is a valid, associated rdataset. + * + *\li 'mctx' is valid. + * + *\li 'rdata' is non-NULL and '*rdata' is NULL. + * + *\li 'nrdata' is non-NULL. + */ + isc_result_t dns_rdataset_totext(dns_rdataset_t *rdataset, const dns_name_t *owner_name, bool omit_final_dot, bool question, isc_buffer_t *target); diff --git a/lib/dns/include/dns/zonemd.h b/lib/dns/include/dns/zonemd.h new file mode 100644 index 0000000000..a6061478ac --- /dev/null +++ b/lib/dns/include/dns/zonemd.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#pragma once + +#include + +#define DNS_ZONEMD_BUFFERSIZE (6U + 64U) + +isc_result_t +dns_zonemd_buildrdata(dns_rdata_t *rdata, dns_db_t *db, + dns_dbversion_t *version, uint8_t scheme, + uint8_t algorithm, isc_mem_t *mctx, unsigned char *buf, + size_t size); + +bool +dns_zonemd_supported(dns_rdata_t *rdata); diff --git a/lib/dns/meson.build b/lib/dns/meson.build index 4fa3ccf914..9fcadc7c5f 100644 --- a/lib/dns/meson.build +++ b/lib/dns/meson.build @@ -160,6 +160,7 @@ dns_srcset.add( 'validator.c', 'view.c', 'zone.c', + 'zonemd.c', 'zoneverify.c', 'zt.c', ), diff --git a/lib/dns/rdataset.c b/lib/dns/rdataset.c index fb7a919459..51b8e4393b 100644 --- a/lib/dns/rdataset.c +++ b/lib/dns/rdataset.c @@ -657,3 +657,51 @@ dns_rdataset_equals(const dns_rdataset_t *rdataset1, return false; } + +static int +rdata_compare_wrapper(const void *rdata1, const void *rdata2) { + return dns_rdata_compare((const dns_rdata_t *)rdata1, + (const dns_rdata_t *)rdata2); +} + +isc_result_t +dns_rdataset_tosortedarray(dns_rdataset_t *set, isc_mem_t *mctx, + dns_rdata_t **rdata, unsigned int *nrdata) { + isc_result_t ret; + int i = 0, n; + dns_rdata_t *data = NULL; + dns_rdataset_t rdataset; + + REQUIRE(rdata != NULL && *rdata == NULL); + REQUIRE(nrdata != NULL); + + n = dns_rdataset_count(set); + + data = isc_mem_cget(mctx, n, sizeof(dns_rdata_t)); + + dns_rdataset_init(&rdataset); + dns_rdataset_clone(set, &rdataset); + ret = dns_rdataset_first(&rdataset); + if (ret != ISC_R_SUCCESS) { + dns_rdataset_disassociate(&rdataset); + isc_mem_cput(mctx, data, n, sizeof(dns_rdata_t)); + return ret; + } + + /* + * Put them in the array. + */ + do { + dns_rdata_init(&data[i]); + dns_rdataset_current(&rdataset, &data[i++]); + } while (dns_rdataset_next(&rdataset) == ISC_R_SUCCESS); + + /* + * Sort the array. + */ + qsort(data, n, sizeof(dns_rdata_t), rdata_compare_wrapper); + *rdata = data; + *nrdata = n; + dns_rdataset_disassociate(&rdataset); + return ISC_R_SUCCESS; +} diff --git a/lib/dns/zonemd.c b/lib/dns/zonemd.c new file mode 100644 index 0000000000..85f19a6053 --- /dev/null +++ b/lib/dns/zonemd.c @@ -0,0 +1,441 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#define CHECK(r) \ + do { \ + result = (r); \ + if (result != ISC_R_SUCCESS) \ + goto cleanup; \ + } while (0) + +static isc_result_t +digest_callback(void *arg, isc_region_t *data) { +#ifdef ISC_ZONEMD_DEBUG + unsigned int j; + for (j = 0; j < data->length; j++) { + fprintf(stderr, "%02x", data->base[j]); + } +#endif + return isc_md_update(arg, data->base, data->length); +} + +static isc_result_t +digest_rdataset(dns_name_t *name, dns_rdataset_t *rds, isc_mem_t *mctx, + isc_md_t *md) { + dns_fixedname_t fixed; + isc_region_t r; + char data[256 + 8]; + isc_buffer_t envbuf; + isc_result_t result; + dns_rdata_t *rdatas = NULL; + unsigned int i, nrdatas; +#ifdef ISC_ZONEMD_DEBUG + char namebuf[DNS_NAME_FORMATSIZE]; +#endif + + dns_fixedname_init(&fixed); + RUNTIME_CHECK(dns_name_downcase(name, dns_fixedname_name(&fixed)) == + ISC_R_SUCCESS); + dns_name_toregion(dns_fixedname_name(&fixed), &r); +#ifdef ISC_ZONEMD_DEBUG + dns_name_format(dns_fixedname_name(&fixed), namebuf, sizeof(namebuf)); +#endif + + /* + * Create an envelope for each rdata: . + */ + isc_buffer_init(&envbuf, data, sizeof(data)); + memmove(data, r.base, r.length); + isc_buffer_add(&envbuf, r.length); + isc_buffer_putuint16(&envbuf, rds->type); + isc_buffer_putuint16(&envbuf, rds->rdclass); + isc_buffer_putuint32(&envbuf, rds->ttl); + + CHECK(dns_rdataset_tosortedarray(rds, mctx, &rdatas, &nrdatas)); + + isc_buffer_usedregion(&envbuf, &r); + + for (i = 0; i < nrdatas; i++) { + unsigned char len[2]; + + /* + * Skip duplicates. + */ + if (i > 0 && dns_rdata_compare(&rdatas[i], &rdatas[i - 1]) == 0) + { + continue; + } + + /* + * Digest the envelope. + */ + CHECK(isc_md_update(md, r.base, r.length)); + + /* + * Digest the length of the rdata. + */ + len[0] = rdatas[i].length >> 8; + len[1] = rdatas[i].length & 0xff; + CHECK(isc_md_update(md, len, 2)); + +#ifdef ISC_ZONEMD_DEBUG + isc_buffer_t b; + char rdatabuf[65 * 1024]; + unsigned int j; + isc_buffer_init(&b, rdatabuf, sizeof(rdatabuf)); + dns_rdata_totext(&rdatas[i], NULL, &b); + fprintf(stderr, + "digest %s type=%u class=%u ttl=%u rdlen=%u %.*s\n", + namebuf, rds->type, rds->rdclass, rds->ttl, + rdatas[i].length, (int)isc_buffer_usedlength(&b), + rdatabuf); + fprintf(stderr, "DIGEST:"); + for (j = 0; j < r.length; j++) { + fprintf(stderr, "%02x", r.base[j]); + } + fprintf(stderr, "%02x%02x", len[0], len[1]); +#endif + /* + * Digest the rdata. + */ + CHECK(dns_rdata_digest(&rdatas[i], digest_callback, md)); +#ifdef ISC_ZONEMD_DEBUG + fprintf(stderr, "\n"); +#endif + } + +cleanup: + if (rdatas != NULL) { + isc_mem_cput(mctx, rdatas, nrdatas, sizeof(*rdatas)); + } + + return result; +} + +static isc_result_t +get_serial(dns_rdataset_t *rds, unsigned char *buf) { + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdata_soa_t soa; + isc_result_t result; + + CHECK(dns_rdataset_first(rds)); + dns_rdataset_current(rds, &rdata); + CHECK(dns_rdata_tostruct(&rdata, &soa, NULL)); + buf[0] = (soa.serial >> 24) & 0xff; + buf[1] = (soa.serial >> 16) & 0xff; + buf[2] = (soa.serial >> 8) & 0xff; + buf[3] = (soa.serial >> 0) & 0xff; +cleanup: + return result; +} + +static bool +bytype(void *a, void *b) { + dns_rdataset_t *ra = (dns_rdataset_t *)a, *rb = (dns_rdataset_t *)b; + + if (ra->type < rb->type) { + return true; + } + if (ra->type != dns_rdatatype_rrsig) { + return false; + } + if (ra->covers < rb->covers) { + return true; + } + return false; +} + +static isc_result_t +add_rdatasets(dns_db_t *db, dns_dbversion_t *version, dns_dbnode_t *node, + isc_mem_t *mctx, isc_heap_t *heap) { + dns_rdatasetiter_t *iter = NULL; + isc_result_t result; + + CHECK(dns_db_allrdatasets(db, node, version, 0, 0, &iter)); + DNS_RDATASETITER_FOREACH(iter) { + dns_rdataset_t *rdataset = isc_mem_get(mctx, sizeof(*rdataset)); + dns_rdataset_init(rdataset); + dns_rdatasetiter_current(iter, rdataset); + isc_heap_insert(heap, rdataset); + } + +cleanup: + if (iter != NULL) { + dns_rdatasetiter_destroy(&iter); + } + return result; +} + +static isc_result_t +process_name(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name, + dns_dbnode_t *nsecnode, dns_dbnode_t *nsec3node, isc_heap_t *heap, + isc_mem_t *mctx, unsigned char *buf, isc_md_t *md, + bool *seen_soa) { + dns_rdataset_t *rdataset = NULL; + isc_result_t result = ISC_R_SUCCESS; + + char namebuf[DNS_NAME_FORMATSIZE]; + dns_name_format(name, namebuf, sizeof(namebuf)); + + if (!dns_name_issubdomain(name, dns_db_origin(db))) { +#ifdef ISC_ZONEMD_DEBUG + fprintf(stderr, "skipping %s out-of-zone\n", namebuf); +#endif + return ISC_R_SUCCESS; + } + + if (nsecnode != NULL) { + CHECK(add_rdatasets(db, version, nsecnode, mctx, heap)); + } + if (nsec3node != NULL) { + CHECK(add_rdatasets(db, version, nsec3node, mctx, heap)); + } + + while ((rdataset = isc_heap_element(heap, 1)) != NULL) { +#ifdef ISC_ZONEMD_DEBUG + fprintf(stderr, "looking at %s %u/%u\n", namebuf, + rdataset->type, rdataset->covers); +#endif + /* + * Don't digest ZONEMD or RRSIG(ZONEMD). + */ + if ((rdataset->type == dns_rdatatype_zonemd || + (rdataset->type == dns_rdatatype_rrsig && + rdataset->covers == dns_rdatatype_zonemd)) && + dns_name_equal(name, dns_db_origin(db))) + { + goto skip; + } + if (rdataset->type == dns_rdatatype_soa && + dns_name_equal(name, dns_db_origin(db))) + { + CHECK(get_serial(rdataset, buf)); + *seen_soa = true; + } + + CHECK(digest_rdataset(name, rdataset, mctx, md)); + skip: + isc_heap_delete(heap, 1); + dns_rdataset_disassociate(rdataset); + isc_mem_put(mctx, rdataset, sizeof(*rdataset)); + } +cleanup: + while ((rdataset = isc_heap_element(heap, 1)) != NULL) { + isc_heap_delete(heap, 1); + dns_rdataset_disassociate(rdataset); + isc_mem_put(mctx, rdataset, sizeof(*rdataset)); + } + return result; +} + +static isc_result_t +zonemd_simple(dns_rdata_t *rdata, dns_db_t *db, dns_dbversion_t *version, + uint8_t algorithm, isc_mem_t *mctx, unsigned char *buf, + size_t size) { + bool seen_soa = false; + dns_dbiterator_t *nsecdbiter = NULL; + dns_dbiterator_t *nsec3dbiter = NULL; + dns_dbnode_t *nsecnode = NULL; + dns_dbnode_t *nsec3node = NULL; + dns_fixedname_t nsecfixed; + dns_fixedname_t nsec3fixed; + dns_name_t *nsecname; + dns_name_t *nsec3name; + isc_md_t *md = isc_md_new(); + isc_heap_t *heap = NULL; + isc_result_t result, nsecresult, nsec3result; + isc_region_t r; + + if (md == NULL) { + CHECK(ISC_R_NOMEMORY); + } + switch (algorithm) { + case DNS_ZONEMD_DIGEST_SHA384: + if (size < ISC_SHA384_DIGESTLENGTH + 6) { + CHECK(ISC_R_NOSPACE); + } + r.base = buf; + r.length = ISC_SHA384_DIGESTLENGTH + 6; + CHECK(isc_md_init(md, ISC_MD_SHA384)); + break; + case DNS_ZONEMD_DIGEST_SHA512: + if (size < ISC_SHA512_DIGESTLENGTH + 6) { + CHECK(ISC_R_NOSPACE); + } + r.base = buf; + r.length = ISC_SHA512_DIGESTLENGTH + 6; + CHECK(isc_md_init(md, ISC_MD_SHA512)); + break; + default: + CHECK(ISC_R_NOTIMPLEMENTED); + } + dns_fixedname_init(&nsecfixed); + dns_fixedname_init(&nsec3fixed); + isc_heap_create(mctx, bytype, NULL, 0, &heap); + CHECK(dns_db_createiterator(db, DNS_DB_NONSEC3, &nsecdbiter)); + CHECK(dns_db_createiterator(db, DNS_DB_NSEC3ONLY, &nsec3dbiter)); + nsecresult = dns_dbiterator_first(nsecdbiter); + nsec3result = dns_dbiterator_first(nsec3dbiter); + while (nsecresult == ISC_R_SUCCESS || nsec3result == ISC_R_SUCCESS) { + if (nsecresult == ISC_R_SUCCESS) { + nsecname = dns_fixedname_name(&nsecfixed); + CHECK(dns_dbiterator_current(nsecdbiter, &nsecnode, + nsecname)); + dns_dbiterator_pause(nsecdbiter); + } else { + nsecname = NULL; + } + if (nsec3result == ISC_R_SUCCESS) { + nsec3name = dns_fixedname_name(&nsec3fixed); + CHECK(dns_dbiterator_current(nsec3dbiter, &nsec3node, + nsec3name)); + dns_dbiterator_pause(nsec3dbiter); + } else { + nsec3name = NULL; + } + /* + * Workout which name / node to process next. + */ + if (nsecname != NULL && nsec3name != NULL) { + int n = dns_name_compare(nsecname, nsec3name); + if (n < 0) { + nsec3name = NULL; + if (nsec3node != NULL) { + dns_db_detachnode(&nsec3node); + } + } + if (n > 0) { + nsecname = NULL; + if (nsecnode != NULL) { + dns_db_detachnode(&nsecnode); + } + } + } + CHECK(process_name( + db, version, nsecname != NULL ? nsecname : nsec3name, + nsecnode, nsec3node, heap, mctx, buf, md, &seen_soa)); + if (nsecnode != NULL) { + dns_db_detachnode(&nsecnode); + } + if (nsec3node != NULL) { + dns_db_detachnode(&nsec3node); + } + if (nsecname != NULL) { + nsecresult = dns_dbiterator_next(nsecdbiter); + } + if (nsec3name != NULL) { + nsec3result = dns_dbiterator_next(nsec3dbiter); + } + } + if (nsecresult == ISC_R_NOMORE && nsec3result == ISC_R_NOMORE) { + unsigned int len = size - 6; + buf[4] = 1; + buf[5] = algorithm; + CHECK(isc_md_final(md, buf + 6, &len)); + if (!seen_soa) { + CHECK(DNS_R_BADZONE); + } + if (len + 6 != r.length) { + CHECK(ISC_R_FAILURE); + } + if (rdata != NULL) { + dns_rdata_fromregion(rdata, dns_db_class(db), + dns_rdatatype_zonemd, &r); + } + } else { + result = nsecresult != ISC_R_NOMORE ? nsecresult : nsec3result; + } + +cleanup: + if (md != NULL) { + isc_md_free(md); + } + if (heap != NULL) { + isc_heap_destroy(&heap); + } + if (nsecnode != NULL) { + dns_db_detachnode(&nsecnode); + } + if (nsec3node != NULL) { + dns_db_detachnode(&nsec3node); + } + if (nsecdbiter != NULL) { + dns_dbiterator_destroy(&nsecdbiter); + } + if (nsec3dbiter != NULL) { + dns_dbiterator_destroy(&nsec3dbiter); + } + return result; +} + +isc_result_t +dns_zonemd_buildrdata(dns_rdata_t *rdata, dns_db_t *db, + dns_dbversion_t *version, uint8_t scheme, + uint8_t algorithm, isc_mem_t *mctx, unsigned char *buf, + size_t size) { + REQUIRE(db != NULL); + REQUIRE(buf != NULL); + + /* + * Check for supported scheme/algorithm combinations. + */ + switch (scheme) { + case DNS_ZONEMD_SCHEME_SIMPLE: + switch (algorithm) { + case DNS_ZONEMD_DIGEST_SHA384: + case DNS_ZONEMD_DIGEST_SHA512: + return zonemd_simple(rdata, db, version, algorithm, + mctx, buf, size); + default: + return ISC_R_NOTIMPLEMENTED; + } + default: + return ISC_R_NOTIMPLEMENTED; + } +} + +bool +dns_zonemd_supported(dns_rdata_t *rdata) { + REQUIRE(rdata != NULL); + REQUIRE(rdata->length >= 6); + REQUIRE(rdata->type == dns_rdatatype_zonemd); + + switch (rdata->data[4]) { + case DNS_ZONEMD_SCHEME_SIMPLE: + switch (rdata->data[5]) { + case DNS_ZONEMD_DIGEST_SHA384: + case DNS_ZONEMD_DIGEST_SHA512: + return true; + default: + return false; + } + default: + return false; + } +} diff --git a/tests/dns/meson.build b/tests/dns/meson.build index 55d4dee47c..b8078345f6 100644 --- a/tests/dns/meson.build +++ b/tests/dns/meson.build @@ -44,6 +44,7 @@ dns_tests = [ 'unreachcache', 'update', 'zonefile', + 'zonemd', 'zonemgr', 'zt', ] diff --git a/tests/dns/testdata/zonemd/rfc8976.A.1.db b/tests/dns/testdata/zonemd/rfc8976.A.1.db new file mode 100644 index 0000000000..01cdf1e908 --- /dev/null +++ b/tests/dns/testdata/zonemd/rfc8976.A.1.db @@ -0,0 +1,13 @@ +example. 86400 IN SOA ns1 admin 2018031900 ( + 1800 900 604800 86400 ) + 86400 IN NS ns1 + 86400 IN NS ns2 + 86400 IN ZONEMD 2018031900 1 1 ( + c68090d90a7aed71 + 6bc459f9340e3d7c + 1370d4d24b7e2fc3 + a1ddc0b9a87153b9 + a9713b3c9ae5cc27 + 777f98b8e730044c ) +ns1 3600 IN A 203.0.113.63 +ns2 3600 IN AAAA 2001:db8::63 diff --git a/tests/dns/testdata/zonemd/rfc8976.A.2.db b/tests/dns/testdata/zonemd/rfc8976.A.2.db new file mode 100644 index 0000000000..08394a18e8 --- /dev/null +++ b/tests/dns/testdata/zonemd/rfc8976.A.2.db @@ -0,0 +1,34 @@ +example. 86400 IN SOA ns1 admin 2018031900 ( + 1800 900 604800 86400 ) + 86400 IN NS ns1 + 86400 IN NS ns2 + 86400 IN ZONEMD 2018031900 1 1 ( + a3b69bad980a3504 + e1cffcb0fd6397f9 + 3848071c93151f55 + 2ae2f6b1711d4bd2 + d8b39808226d7b9d + b71e34b72077f8fe ) +ns1 3600 IN A 203.0.113.63 +NS2 3600 IN AAAA 2001:db8::63 +occluded.sub 7200 IN TXT "I'm occluded but must be digested" +sub 7200 IN NS ns1 +duplicate 300 IN TXT "I must be digested just once" +duplicate 300 IN TXT "I must be digested just once" +foo.test. 555 IN TXT "out-of-zone data must be excluded" +UPPERCASE 3600 IN TXT "canonicalize uppercase owner names" +* 777 IN PTR dont-forget-about-wildcards +mail 3600 IN MX 20 MAIL1 +mail 3600 IN MX 10 Mail2.Example. +sortme 3600 IN AAAA 2001:db8::5:61 +sortme 3600 IN AAAA 2001:db8::3:62 +sortme 3600 IN AAAA 2001:db8::4:63 +sortme 3600 IN AAAA 2001:db8::1:65 +sortme 3600 IN AAAA 2001:db8::2:64 +non-apex 900 IN ZONEMD 2018031900 1 1 ( + 616c6c6f77656420 + 6275742069676e6f + 7265642e20616c6c + 6f77656420627574 + 2069676e6f726564 + 2e20616c6c6f7765 ) diff --git a/tests/dns/testdata/zonemd/rfc8976.A.3.db b/tests/dns/testdata/zonemd/rfc8976.A.3.db new file mode 100644 index 0000000000..fdb37dfc71 --- /dev/null +++ b/tests/dns/testdata/zonemd/rfc8976.A.3.db @@ -0,0 +1,30 @@ +example. 86400 IN SOA ns1 admin 2018031900 ( + 1800 900 604800 86400 ) +example. 86400 IN NS ns1.example. +example. 86400 IN NS ns2.example. +example. 86400 IN ZONEMD 2018031900 1 1 ( + 62e6cf51b02e54b9 + b5f967d547ce4313 + 6792901f9f88e637 + 493daaf401c92c27 + 9dd10f0edb1c56f8 + 080211f8480ee306 ) +example. 86400 IN ZONEMD 2018031900 1 2 ( + 08cfa1115c7b948c + 4163a901270395ea + 226a930cd2cbcf2f + a9a5e6eb85f37c8a + 4e114d884e66f176 + eab121cb02db7d65 + 2e0cc4827e7a3204 + f166b47e5613fd27 ) +example. 86400 IN ZONEMD 2018031900 1 240 ( + e2d523f654b9422a + 96c5a8f44607bbee ) +example. 86400 IN ZONEMD 2018031900 241 1 ( + e1846540e33a9e41 + 89792d18d5d131f6 + 05fc283e ) +ns1.example. 3600 IN A 203.0.113.63 +ns2.example. 86400 IN TXT "This example has multiple digests" +NS2.EXAMPLE. 3600 IN AAAA 2001:db8::63 diff --git a/tests/dns/testdata/zonemd/rfc8976.A.4.db b/tests/dns/testdata/zonemd/rfc8976.A.4.db new file mode 100644 index 0000000000..1e158a4341 --- /dev/null +++ b/tests/dns/testdata/zonemd/rfc8976.A.4.db @@ -0,0 +1,128 @@ +uri.arpa. 3600 IN SOA sns.dns.icann.org. ( + noc.dns.icann.org. 2018100702 10800 3600 1209600 3600 ) +uri.arpa. 3600 IN RRSIG SOA 8 2 3600 ( + 20210217232440 20210120232440 37444 uri.arpa. + GzQw+QzwLDJr13REPGVmpEChjD1D2XlX0ie1DnWHpgaEw1E/dhs3lCN3+B + mHd4Kx3tffTRgiyq65HxR6feQ5v7VmAifjyXUYB1DZur1eP5q0Ms2ygCB3 + byoeMgCNsFS1oKZ2LdzNBRpy3oace8xQn1SpmHGfyrsgg+WbHKCT1dY= ) +uri.arpa. 86400 IN NS a.iana-servers.net. +uri.arpa. 86400 IN NS b.iana-servers.net. +uri.arpa. 86400 IN NS c.iana-servers.net. +uri.arpa. 86400 IN NS ns2.lacnic.net. +uri.arpa. 86400 IN NS sec3.apnic.net. +uri.arpa. 86400 IN RRSIG NS 8 2 86400 ( + 20210217232440 20210120232440 37444 uri.arpa. + M+Iei2lcewWGaMtkPlrhM9FpUAHXFkCHTVpeyrjxjEONeNgKtHZor5e4V4 + qJBOzNqo8go/qJpWlFBm+T5Hn3asaBZVstFIYky38/C8UeRLPKq1hTTHAR + YUlFrexr5fMtSUAVOgOQPSBfH3xBq/BgSccTdRb9clD+HE7djpqrLS4= ) +uri.arpa. 600 IN MX 10 pechora.icann.org. +uri.arpa. 600 IN RRSIG MX 8 2 600 ( + 20210217232440 20210120232440 37444 uri.arpa. + kQAJQivmv6A5hqYBK8h6Z13ESY69gmosXwKI6WE09I8RFetfrxr24ecdnY + d0lpnDtgNNSoHkYRSOoB+C4+zuJsoyAAzGo9uoWMWj97/2xeGhf3PTC9me + Q9Ohi6hul9By7OR76XYmGhdWX8PBi60RUmZ1guslFBfQ8izwPqzuphs= ) +uri.arpa. 3600 IN DNSKEY 256 3 8 ( + AwEAAbMxuFuLeVDuOwIMzYOTD/bTREjLflo7wOi6ieIJhqltEzgjNzmWJf + 9kGwwDmzxU7kbthMEhBNBZNn84zmcyRSCMzuStWveL7xmqqUlE3swL8kLO + vdZvc75XnmpHrk3ndTyEb6eZM7slh2C63Oh6K8VR5VkiZAkEGg0uZIT3Nj + sF ) +uri.arpa. 3600 IN DNSKEY 257 3 8 ( + AwEAAdkTaWkZtZuRh7/OobBUFxM+ytTst+bCu0r9w+rEwXD7GbDs0pIMhM + enrZzoAvmv1fQxw2MGs6Ri6yPKfNULcFOSt9l8i6BVBLI+SKTY6XXeDUQp + SEmSaxohHeRPMQFzpysfjxINp/L2rGtZ7yPmxY/XRiFPSO0myqwGJa9r06 + Zw9CHM5UDHKWV/E+zxPFq/I7CfPbrrzbUotBX7Z6Vh3Sarllbe8cGUB2UF + NaTRgwB0TwDBPRD5ER3w2Dzbry9NhbElTr7vVfhaGWeOGuqAUXwlXEg6Cr + NkmJXJ2F1Rzr9WHUzhp7uWxhAbmJREGfi2dEyPAbUAyCjBqhFaqglknvc= ) +uri.arpa. 3600 IN DNSKEY 257 3 8 ( + AwEAAenQaBoFmDmvRT+/H5oNbm0Tr5FmNRNDEun0Jpj/ELkzeUrTWhNpQm + ZeIMC8I0kZ185tEvOnRvn8OvV39B17QIdrvvKGIh2HlgeDRCLolhaojfn2 + QM0DStjF/WWHpxJOmE6CIuvhqYEU37yoJscGAPpPVPzNvnL1HhYTaao1VR + YWQ/maMrJ+bfHg+YX1N6M/8MnRjIKBif1FWjbCKvsn6dnuGGL9oCWYUFJ3 + DwofXuhgPyZMkzPc88YkJj5EMvbMH4wtelbCwC+ivx732l0w/rXJn0ciQS + OgoeVvDio8dIJmWQITWQAuP+q/ZHFEFHPlrP3gvQh5mcVS48eLX71Bq7c= ) +uri.arpa. 3600 IN RRSIG DNSKEY 8 2 3600 ( + 20210217232440 20210120232440 12670 uri.arpa. + DBE2gkKAoxJCfz47KKxzoImN/0AKArhIVHE7TyTwy0DdRPo44V5R+vL6th + UxlQ1CJi2Rw0jwAXymx5Y3Q873pOEllH+4bJoIT4dmoBmPXfYWW7Clvw9U + PKHRP0igKHmCVwIeBYDTU3gfLcMTbR4nEWPDN0GxlL1Mf7ITaC2Ioabo79 + Ip3M/MR8I3Vx/xZ4ZKKPHtLn3xUuJluPNanqJrED2gTslL2xWZ1tqjsAjJ + v7JnJo2HJ8XVRB5zBto0IaJ2oBlqcjdcQ/0VlyoM8uOy1pDwHQ2BJl7322 + gNMHBP9HSiUPIOaIDNUCwW8eUcW6DIUk+s9u3GN1uTqwWzsYB/rA== ) +uri.arpa. 3600 IN RRSIG DNSKEY 8 2 3600 ( + 20210217232440 20210120232440 30577 uri.arpa. + Kx6HwP4UlkGc1UZ7SERXtQjPajOF4iUvkwDj7MEG1xbQFB1KoJiEb/eiW0 + qmSWdIhMDv8myhgauejRLyJxwxz8HDRV4xOeHWnRGfWBk4XGYwkejVzOHz + oIArVdUVRbr2JKigcTOoyFN+uu52cNB7hRYu7dH5y1hlc6UbOnzRpMtGxc + gVyKQ+/ARbIqGG3pegdEOvV49wTPWEiyY65P2urqhvnRg5ok/jzwAdMx4X + Gshiib7Ojq0sRVl2ZIzj4rFgY/qsSO8SEXEhMo2VuSkoJNiofVzYoqpxEe + GnANkIT7Tx2xJL1BWyJxyc7E8Wr2QSgCcc+rYL6IkHDtJGHy7TaQ== ) +uri.arpa. 3600 IN ZONEMD 2018100702 1 1 ( + 0dbc3c4dbfd75777c12ca19c337854b1577799901307c482e9d91d5d15 + cd934d16319d98e30c4201cf25a1d5a0254960 ) +uri.arpa. 3600 IN RRSIG ZONEMD 8 2 3600 ( + 20210217232440 20210120232440 37444 uri.arpa. + QDo4XZcL3HMyn8aAHyCUsu/Tqj4Gkth8xY1EqByOb8XOTwVtA4ZNQORE1s + iqNqjtJUbeJPtJSbLNqCL7rCq0CzNNnBscv6IIf4gnqJZjlGtHO30ohXtK + vEc4z7SU3IASsi6bB3nLmEAyERdYSeU6UBfx8vatQDIRhkgEnnWUTh4= ) +uri.arpa. 3600 IN NSEC ftp.uri.arpa. ( + NS SOA MX RRSIG NSEC DNSKEY ZONEMD ) +uri.arpa. 3600 IN RRSIG NSEC 8 2 3600 ( + 20210217232440 20210120232440 37444 uri.arpa. + dU/rXLM/naWd1+1PiWiYVaNJyCkiuyZJSccr91pJI673T8r3685B4ODMYF + afZRboVgwnl3ZrXddY6xOhZL3n9V9nxXZwjLJ2HJUojFoKcXTlpnUyYUYv + VQ2kj4GHAo6fcGCEp5QFJ2KbCpeJoS+PhKGRRx28icCiNT4/uXQvO2E= ) +ftp.uri.arpa. 604800 IN NAPTR 0 0 "" "" ( + "!^ftp://([^:/?#]*).*$!\\1!i" . ) +ftp.uri.arpa. 604800 IN RRSIG NAPTR 8 3 604800 ( + 20210217232440 20210120232440 37444 uri.arpa. + EygekDgl+Lyyq4NMSEpPyOrOywYf9Y3FAB4v1DT44J3R5QGidaH8l7ZFjH + oYFI8sY64iYOCV4sBnX/dh6C1L5NgpY+8l5065Xu3vvjyzbtuJ2k6YYwJr + rCbvl5DDn53zAhhO2hL9uLgyLraZGi9i7TFGd0sm3zNyUF/EVL0CcxU= ) +ftp.uri.arpa. 3600 IN NSEC http.uri.arpa. ( + NAPTR RRSIG NSEC ) +ftp.uri.arpa. 3600 IN RRSIG NSEC 8 3 3600 ( + 20210217232440 20210120232440 37444 uri.arpa. + pbP4KxevPXCu/bDqcvXiuBppXyFEmtHyiy0eAN5gS7mi6mp9Z9bWFjx/Ld + H9+6oFGYa5vGmJ5itu/4EDMe8iQeZbI8yrpM4TquB7RR/MGfBnTd8S+sjy + QtlRYG7yqEu77Vd78Fme22BKPJ+MVqjS0JHMUE/YUGomPkAjLJJwwGw= ) +http.uri.arpa. 604800 IN NAPTR 0 0 "" "" ( + "!^http://([^:/?#]*).*$!\\1!i" . ) +http.uri.arpa. 604800 IN RRSIG NAPTR 8 3 604800 ( + 20210217232440 20210120232440 37444 uri.arpa. + eTqbWvt1GvTeXozuvm4ebaAfkXFQKrtdu0cEiExto80sHIiCbO0WL8UDa/ + J3cDivtQca7LgUbOb6c17NESsrsVkc6zNPx5RK2tG7ZQYmhYmtqtfg1oU5 + BRdHZ5TyqIXcHlw9Blo2pir1Y9IQgshhD7UOGkbkEmvB1Lrd0aHhAAg= ) +http.uri.arpa. 3600 IN NSEC mailto.uri.arpa. ( + NAPTR RRSIG NSEC ) +http.uri.arpa. 3600 IN RRSIG NSEC 8 3 3600 ( + 20210217232440 20210120232440 37444 uri.arpa. + R9rlNzw1CVz2N08q6DhULzcsuUm0UKcPaGAWEU40tr81jEDHsFHNM+khCd + OI8nDstzA42aee4rwCEgijxJpRCcY9hrO1Ysrrr2fdqNz60JikMdarvU5O + 0p0VXeaaJDfJQT44+o+YXaBwI7Qod3FTMx7aRib8i7istvPm1Rr7ixA= ) +mailto.uri.arpa. 604800 IN NAPTR 0 0 "" "" ( + "!^mailto:(.*)@(.*)$!\\2!i" . ) +mailto.uri.arpa. 604800 IN RRSIG NAPTR 8 3 604800 ( + 20210217232440 20210120232440 37444 uri.arpa. + Ch2zTG2F1plEvQPyIH4Yd80XXLjXOPvMbiqDjpJBcnCJsV8QF7kr0wTLnU + T3dB+asQudOjPyzaHGwFlMzmrrAsszN4XAMJ6htDtFJdsgTMP/NkHhYRSm + Vv6rLeAhd+mVfObY12M//b/GGVTjeUI/gJaLW0fLVZxr1Fp5U5CRjyw= ) +mailto.uri.arpa. 3600 IN NSEC urn.uri.arpa. ( + NAPTR RRSIG NSEC ) +mailto.uri.arpa. 3600 IN RRSIG NSEC 8 3 3600 ( + 20210217232440 20210120232440 37444 uri.arpa. + fQUbSIE6E7JDi2rosah4SpCOTrKufeszFyj5YEavbQuYlQ5cNFvtm8KuE2 + xXMRgRI4RGvM2leVqcoDw5hS3m2pOJLxH8l2WE72YjYvWhvnwc5Rofe/8y + B/vaSK9WCnqN8y2q6Vmy73AGP0fuiwmuBra7LlkOiqmyx3amSFizwms= ) +urn.uri.arpa. 604800 IN NAPTR 0 0 "" "" ( + "/urn:([^:]+)/\\1/i" . ) +urn.uri.arpa. 604800 IN RRSIG NAPTR 8 3 604800 ( + 20210217232440 20210120232440 37444 uri.arpa. + CVt2Tgz0e5ZmaSXqRfNys/8OtVCk9nfP0zhezhN8Bo6MDt6yyKZ2kEEWJP + jkN7PCYHjO8fGjnUn0AHZI2qBNv7PKHcpR42VY03q927q85a65weOO1YE0 + vPYMzACpua9TOtfNnynM2Ws0uN9URxUyvYkXBdqOC81N3sx1dVELcwc= ) +urn.uri.arpa. 3600 IN NSEC uri.arpa. NAPTR RRSIG NSEC +urn.uri.arpa. 3600 IN RRSIG NSEC 8 3 3600 ( + 20210217232440 20210120232440 37444 uri.arpa. + JuKkMiC3/j9iM3V8/izcouXWAVGnSZjkOgEgFPhutMqoylQNRcSkbEZQzF + K8B/PIVdzZF0Y5xkO6zaKQjOzz6OkSaNPIo1a7Vyyl3wDY/uLCRRAHRJfp + knuY7O+AUNXvVVIEYJqZggd4kl/Rjh1GTzPYZTRrVi5eQidI1LqCOeg= ) diff --git a/tests/dns/testdata/zonemd/rfc8976.A.5.db b/tests/dns/testdata/zonemd/rfc8976.A.5.db new file mode 100644 index 0000000000..246f5e2376 --- /dev/null +++ b/tests/dns/testdata/zonemd/rfc8976.A.5.db @@ -0,0 +1,48 @@ +root-servers.net. 3600000 IN SOA a.root-servers.net. ( + nstld.verisign-grs.com. 2018091100 14400 7200 1209600 3600000 ) +root-servers.net. 3600000 IN NS a.root-servers.net. +root-servers.net. 3600000 IN NS b.root-servers.net. +root-servers.net. 3600000 IN NS c.root-servers.net. +root-servers.net. 3600000 IN NS d.root-servers.net. +root-servers.net. 3600000 IN NS e.root-servers.net. +root-servers.net. 3600000 IN NS f.root-servers.net. +root-servers.net. 3600000 IN NS g.root-servers.net. +root-servers.net. 3600000 IN NS h.root-servers.net. +root-servers.net. 3600000 IN NS i.root-servers.net. +root-servers.net. 3600000 IN NS j.root-servers.net. +root-servers.net. 3600000 IN NS k.root-servers.net. +root-servers.net. 3600000 IN NS l.root-servers.net. +root-servers.net. 3600000 IN NS m.root-servers.net. +a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30 +a.root-servers.net. 3600000 IN A 198.41.0.4 +b.root-servers.net. 3600000 IN MX 20 mail.isi.edu. +b.root-servers.net. 3600000 IN AAAA 2001:500:200::b +b.root-servers.net. 3600000 IN A 199.9.14.201 +c.root-servers.net. 3600000 IN AAAA 2001:500:2::c +c.root-servers.net. 3600000 IN A 192.33.4.12 +d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d +d.root-servers.net. 3600000 IN A 199.7.91.13 +e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e +e.root-servers.net. 3600000 IN A 192.203.230.10 +f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f +f.root-servers.net. 3600000 IN A 192.5.5.241 +g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d +g.root-servers.net. 3600000 IN A 192.112.36.4 +h.root-servers.net. 3600000 IN AAAA 2001:500:1::53 +h.root-servers.net. 3600000 IN A 198.97.190.53 +i.root-servers.net. 3600000 IN MX 10 mx.i.root-servers.org. +i.root-servers.net. 3600000 IN AAAA 2001:7fe::53 +i.root-servers.net. 3600000 IN A 192.36.148.17 +j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30 +j.root-servers.net. 3600000 IN A 192.58.128.30 +k.root-servers.net. 3600000 IN AAAA 2001:7fd::1 +k.root-servers.net. 3600000 IN A 193.0.14.129 +l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42 +l.root-servers.net. 3600000 IN A 199.7.83.42 +m.root-servers.net. 3600000 IN AAAA 2001:dc3::35 +m.root-servers.net. 3600000 IN A 202.12.27.33 +root-servers.net. 3600000 IN SOA a.root-servers.net. ( + nstld.verisign-grs.com. 2018091100 14400 7200 1209600 3600000 ) +root-servers.net. 3600000 IN ZONEMD 2018091100 1 1 ( + f1ca0ccd91bd5573d9f431c00ee0101b2545c97602be0a97 + 8a3b11dbfc1c776d5b3e86ae3d973d6b5349ba7f04340f79 ) diff --git a/tests/dns/zonemd_test.c b/tests/dns/zonemd_test.c new file mode 100644 index 0000000000..d171bf7f2d --- /dev/null +++ b/tests/dns/zonemd_test.c @@ -0,0 +1,142 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include /* IWYU pragma: keep */ +#include +#include +#include +#include +#include +#include +#include + +#define UNIT_TESTING + +#include + +#include +#include +#include +#include + +#include + +/* + * Individual unit tests + */ + +/* zonemd_buildrdata */ +static void +check_dns_zonemd_buildrdata(const char *origin, const char *file, + uint32_t serial, uint32_t digest_type, + uint32_t digest_length, const char *digest) { + dns_db_t *db = NULL; + dns_rdata_t rdata = DNS_RDATA_INIT; + isc_buffer_t target; + isc_result_t result; + unsigned char buf[DNS_ZONEMD_BUFFERSIZE]; + char text[1024] = { 0 }; + dns_rdata_zonemd_t zonemd; + + if (debug) { + fprintf(stderr, "Loading %s\n", file); + } + + result = dns_test_loaddb(&db, dns_dbtype_zone, origin, file); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_zonemd_buildrdata(&rdata, db, NULL, + DNS_ZONEMD_SCHEME_SIMPLE, digest_type, + isc_g_mctx, buf, sizeof(buf)); + assert_int_equal(result, ISC_R_SUCCESS); + + if (debug) { + isc_buffer_init(&target, text, sizeof(text)); + result = dns_rdata_totext(&rdata, NULL, &target); + assert_int_equal(result, ISC_R_SUCCESS); + fprintf(stderr, "%.*s\n", (int)isc_buffer_usedlength(&target), + text); + } + + assert_int_equal(rdata.length, 6 + digest_length); + dns_rdata_tostruct(&rdata, &zonemd, NULL); + assert_int_equal(zonemd.serial, serial); + assert_int_equal(zonemd.scheme, DNS_ZONEMD_SCHEME_SIMPLE); + assert_int_equal(zonemd.digest_type, digest_type); + assert_int_equal(zonemd.length, digest_length); + assert_memory_equal(zonemd.digest, digest, digest_length); + dns_rdata_reset(&rdata); + dns_db_detach(&db); +} + +ISC_RUN_TEST_IMPL(zonemd_buildrdata) { + UNUSED(state); + + assert_return_code(chdir(TESTS_DIR), 0); + + check_dns_zonemd_buildrdata( + "example", "testdata/zonemd/rfc8976.A.1.db", 2018031900, + DNS_ZONEMD_DIGEST_SHA384, 384 / 8, + "\xc6\x80\x90\xd9\x0a\x7a\xed\x71\x6b\xc4\x59\xf9" + "\x34\x0e\x3d\x7c\x13\x70\xd4\xd2\x4b\x7e\x2f\xc3" + "\xa1\xdd\xc0\xb9\xa8\x71\x53\xb9\xa9\x71\x3b\x3c" + "\x9a\xe5\xcc\x27\x77\x7f\x98\xb8\xe7\x30\x04\x4c"); + + check_dns_zonemd_buildrdata( + "example", "testdata/zonemd/rfc8976.A.2.db", 2018031900, + DNS_ZONEMD_DIGEST_SHA384, 384 / 8, + "\xa3\xb6\x9b\xad\x98\x0a\x35\x04\xe1\xcf\xfc\xb0" + "\xfd\x63\x97\xf9\x38\x48\x07\x1c\x93\x15\x1f\x55" + "\x2a\xe2\xf6\xb1\x71\x1d\x4b\xd2\xd8\xb3\x98\x08" + "\x22\x6d\x7b\x9d\xb7\x1e\x34\xb7\x20\x77\xf8\xfe"); + + check_dns_zonemd_buildrdata( + "example", "testdata/zonemd/rfc8976.A.3.db", 2018031900, + DNS_ZONEMD_DIGEST_SHA384, 384 / 8, + "\x62\xe6\xcf\x51\xb0\x2e\x54\xb9\xb5\xf9\x67\xd5" + "\x47\xce\x43\x13\x67\x92\x90\x1f\x9f\x88\xe6\x37" + "\x49\x3d\xaa\xf4\x01\xc9\x2c\x27\x9d\xd1\x0f\x0e" + "\xdb\x1c\x56\xf8\x08\x02\x11\xf8\x48\x0e\xe3\x06"); + + check_dns_zonemd_buildrdata( + "example", "testdata/zonemd/rfc8976.A.3.db", 2018031900, + DNS_ZONEMD_DIGEST_SHA512, 512 / 8, + "\x08\xcf\xa1\x11\x5c\x7b\x94\x8c\x41\x63\xa9\x01" + "\x27\x03\x95\xea\x22\x6a\x93\x0c\xd2\xcb\xcf\x2f" + "\xa9\xa5\xe6\xeb\x85\xf3\x7c\x8a\x4e\x11\x4d\x88" + "\x4e\x66\xf1\x76\xea\xb1\x21\xcb\x02\xdb\x7d\x65" + "\x2e\x0c\xc4\x82\x7e\x7a\x32\x04\xf1\x66\xb4\x7e" + "\x56\x13\xfd\x27"); + + check_dns_zonemd_buildrdata( + "uri.arpa", "testdata/zonemd/rfc8976.A.4.db", 2018100702, + DNS_ZONEMD_DIGEST_SHA384, 384 / 8, + "\x0d\xbc\x3c\x4d\xbf\xd7\x57\x77\xc1\x2c\xa1\x9c" + "\x33\x78\x54\xb1\x57\x77\x99\x90\x13\x07\xc4\x82" + "\xe9\xd9\x1d\x5d\x15\xcd\x93\x4d\x16\x31\x9d\x98" + "\xe3\x0c\x42\x01\xcf\x25\xa1\xd5\xa0\x25\x49\x60"); + + check_dns_zonemd_buildrdata( + "root-servers.net", "testdata/zonemd/rfc8976.A.5.db", + 2018091100, DNS_ZONEMD_DIGEST_SHA384, 384 / 8, + "\xf1\xca\x0c\xcd\x91\xbd\x55\x73\xd9\xf4\x31\xc0" + "\x0e\xe0\x10\x1b\x25\x45\xc9\x76\x02\xbe\x0a\x97" + "\x8a\x3b\x11\xdb\xfc\x1c\x77\x6d\x5b\x3e\x86\xae" + "\x3d\x97\x3d\x6b\x53\x49\xba\x7f\x04\x34\x0f\x79"); +} + +ISC_TEST_LIST_START +ISC_TEST_ENTRY(zonemd_buildrdata) +ISC_TEST_LIST_END + +ISC_TEST_MAIN