diff options
-rw-r--r-- | src/resolve/RFCs | 1 | ||||
-rw-r--r-- | src/resolve/resolved-dns-dnssec.c | 225 | ||||
-rw-r--r-- | src/resolve/resolved-dns-rr.c | 2 | ||||
-rw-r--r-- | src/resolve/resolved-dns-rr.h | 2 | ||||
-rw-r--r-- | src/resolve/test-dnssec.c | 186 |
5 files changed, 378 insertions, 38 deletions
diff --git a/src/resolve/RFCs b/src/resolve/RFCs index 09c85f9518..7190c16faa 100644 --- a/src/resolve/RFCs +++ b/src/resolve/RFCs @@ -53,6 +53,7 @@ Y https://tools.ietf.org/html/rfc6975 → Signaling Cryptographic Algorithm Unde Y https://tools.ietf.org/html/rfc7129 → Authenticated Denial of Existence in the DNS Y https://tools.ietf.org/html/rfc7646 → Definition and Use of DNSSEC Negative Trust Anchors ~ https://tools.ietf.org/html/rfc7719 → DNS Terminology +Y https://tools.ietf.org/html/rfc8080 → Edwards-Curve Digital Security Algorithm (EdDSA) for DNSSEC Also relevant: diff --git a/src/resolve/resolved-dns-dnssec.c b/src/resolve/resolved-dns-dnssec.c index f04b246a3d..e3eca7e62c 100644 --- a/src/resolve/resolved-dns-dnssec.c +++ b/src/resolve/resolved-dns-dnssec.c @@ -18,12 +18,16 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include <stdio_ext.h> + #if HAVE_GCRYPT #include <gcrypt.h> #endif #include "alloc-util.h" #include "dns-domain.h" +#include "fd-util.h" +#include "fileio.h" #include "gcrypt-util.h" #include "hexdecoct.h" #include "resolved-dns-dnssec.h" @@ -436,6 +440,99 @@ static int dnssec_ecdsa_verify( q, key_size*2+1); } +#if GCRYPT_VERSION_NUMBER >= 0x010600 +static int dnssec_eddsa_verify_raw( + const char *curve, + const void *signature_r, size_t signature_r_size, + const void *signature_s, size_t signature_s_size, + const void *data, size_t data_size, + const void *key, size_t key_size) { + + gcry_sexp_t public_key_sexp = NULL, data_sexp = NULL, signature_sexp = NULL; + gcry_error_t ge; + int k; + + ge = gcry_sexp_build(&signature_sexp, + NULL, + "(sig-val (eddsa (r %b) (s %b)))", + (int) signature_r_size, + signature_r, + (int) signature_s_size, + signature_s); + if (ge != 0) { + k = -EIO; + goto finish; + } + + ge = gcry_sexp_build(&data_sexp, + NULL, + "(data (flags eddsa) (hash-algo sha512) (value %b))", + (int) data_size, + data); + if (ge != 0) { + k = -EIO; + goto finish; + } + + ge = gcry_sexp_build(&public_key_sexp, + NULL, + "(public-key (ecc (curve %s) (flags eddsa) (q %b)))", + curve, + (int) key_size, + key); + if (ge != 0) { + k = -EIO; + goto finish; + } + + ge = gcry_pk_verify(signature_sexp, data_sexp, public_key_sexp); + if (gpg_err_code(ge) == GPG_ERR_BAD_SIGNATURE) + k = 0; + else if (ge != 0) { + log_debug("EdDSA signature check failed: %s", gpg_strerror(ge)); + k = -EIO; + } else + k = 1; +finish: + if (public_key_sexp) + gcry_sexp_release(public_key_sexp); + if (signature_sexp) + gcry_sexp_release(signature_sexp); + if (data_sexp) + gcry_sexp_release(data_sexp); + + return k; +} + +static int dnssec_eddsa_verify( + int algorithm, + const void *data, size_t data_size, + DnsResourceRecord *rrsig, + DnsResourceRecord *dnskey) { + const char *curve; + size_t key_size; + + if (algorithm == DNSSEC_ALGORITHM_ED25519) { + curve = "Ed25519"; + key_size = 32; + } else + return -EOPNOTSUPP; + + if (dnskey->dnskey.key_size != key_size) + return -EINVAL; + + if (rrsig->rrsig.signature_size != key_size * 2) + return -EINVAL; + + return dnssec_eddsa_verify_raw( + curve, + rrsig->rrsig.signature, key_size, + (uint8_t*) rrsig->rrsig.signature + key_size, key_size, + data, data_size, + dnskey->dnskey.key, key_size); +} +#endif + static void md_add_uint8(gcry_md_hd_t md, uint8_t v) { gcry_md_write(md, &v, sizeof(v)); } @@ -445,9 +542,18 @@ static void md_add_uint16(gcry_md_hd_t md, uint16_t v) { gcry_md_write(md, &v, sizeof(v)); } -static void md_add_uint32(gcry_md_hd_t md, uint32_t v) { +static void fwrite_uint8(FILE *fp, uint8_t v) { + fwrite(&v, sizeof(v), 1, fp); +} + +static void fwrite_uint16(FILE *fp, uint16_t v) { + v = htobe16(v); + fwrite(&v, sizeof(v), 1, fp); +} + +static void fwrite_uint32(FILE *fp, uint32_t v) { v = htobe32(v); - gcry_md_write(md, &v, sizeof(v)); + fwrite(&v, sizeof(v), 1, fp); } static int dnssec_rrsig_prepare(DnsResourceRecord *rrsig) { @@ -613,6 +719,9 @@ int dnssec_verify_rrset( gcry_md_hd_t md = NULL; int r, md_algorithm; size_t k, n = 0; + size_t sig_size = 0; + _cleanup_free_ char *sig_data = NULL; + _cleanup_fclose_ FILE *f = NULL; size_t hash_size; void *hash; bool wildcard; @@ -628,14 +737,6 @@ int dnssec_verify_rrset( * using the signature "rrsig" and the key "dnskey". It's * assumed that RRSIG and DNSKEY match. */ - md_algorithm = algorithm_to_gcrypt_md(rrsig->rrsig.algorithm); - if (md_algorithm == -EOPNOTSUPP) { - *result = DNSSEC_UNSUPPORTED_ALGORITHM; - return 0; - } - if (md_algorithm < 0) - return md_algorithm; - r = dnssec_rrsig_prepare(rrsig); if (r == -EINVAL) { *result = DNSSEC_INVALID; @@ -725,28 +826,23 @@ int dnssec_verify_rrset( /* Bring the RRs into canonical order */ qsort_safe(list, n, sizeof(DnsResourceRecord*), rr_compare); - /* OK, the RRs are now in canonical order. Let's calculate the digest */ - initialize_libgcrypt(false); - - hash_size = gcry_md_get_algo_dlen(md_algorithm); - assert(hash_size > 0); - - gcry_md_open(&md, md_algorithm, 0); - if (!md) - return -EIO; + f = open_memstream(&sig_data, &sig_size); + if (!f) + return -ENOMEM; + __fsetlocking(f, FSETLOCKING_BYCALLER); - md_add_uint16(md, rrsig->rrsig.type_covered); - md_add_uint8(md, rrsig->rrsig.algorithm); - md_add_uint8(md, rrsig->rrsig.labels); - md_add_uint32(md, rrsig->rrsig.original_ttl); - md_add_uint32(md, rrsig->rrsig.expiration); - md_add_uint32(md, rrsig->rrsig.inception); - md_add_uint16(md, rrsig->rrsig.key_tag); + fwrite_uint16(f, rrsig->rrsig.type_covered); + fwrite_uint8(f, rrsig->rrsig.algorithm); + fwrite_uint8(f, rrsig->rrsig.labels); + fwrite_uint32(f, rrsig->rrsig.original_ttl); + fwrite_uint32(f, rrsig->rrsig.expiration); + fwrite_uint32(f, rrsig->rrsig.inception); + fwrite_uint16(f, rrsig->rrsig.key_tag); r = dns_name_to_wire_format(rrsig->rrsig.signer, wire_format_name, sizeof(wire_format_name), true); if (r < 0) goto finish; - gcry_md_write(md, wire_format_name, r); + fwrite(wire_format_name, 1, r, f); /* Convert the source of synthesis into wire format */ r = dns_name_to_wire_format(source, wire_format_name, sizeof(wire_format_name), true); @@ -760,24 +856,66 @@ int dnssec_verify_rrset( /* Hash the source of synthesis. If this is a wildcard, then prefix it with the *. label */ if (wildcard) - gcry_md_write(md, (uint8_t[]) { 1, '*'}, 2); - gcry_md_write(md, wire_format_name, r); + fwrite((uint8_t[]) { 1, '*'}, sizeof(uint8_t), 2, f); + fwrite(wire_format_name, 1, r, f); - md_add_uint16(md, rr->key->type); - md_add_uint16(md, rr->key->class); - md_add_uint32(md, rrsig->rrsig.original_ttl); + fwrite_uint16(f, rr->key->type); + fwrite_uint16(f, rr->key->class); + fwrite_uint32(f, rrsig->rrsig.original_ttl); l = DNS_RESOURCE_RECORD_RDATA_SIZE(rr); assert(l <= 0xFFFF); - md_add_uint16(md, (uint16_t) l); - gcry_md_write(md, DNS_RESOURCE_RECORD_RDATA(rr), l); + fwrite_uint16(f, (uint16_t) l); + fwrite(DNS_RESOURCE_RECORD_RDATA(rr), 1, l, f); } - hash = gcry_md_read(md, 0); - if (!hash) { - r = -EIO; + r = fflush_and_check(f); + if (r < 0) + return r; + + initialize_libgcrypt(false); + + switch (rrsig->rrsig.algorithm) { +#if GCRYPT_VERSION_NUMBER >= 0x010600 + case DNSSEC_ALGORITHM_ED25519: + break; +#else + case DNSSEC_ALGORITHM_ED25519: +#endif + case DNSSEC_ALGORITHM_ED448: + *result = DNSSEC_UNSUPPORTED_ALGORITHM; + r = 0; goto finish; + default: + /* OK, the RRs are now in canonical order. Let's calculate the digest */ + md_algorithm = algorithm_to_gcrypt_md(rrsig->rrsig.algorithm); + if (md_algorithm == -EOPNOTSUPP) { + *result = DNSSEC_UNSUPPORTED_ALGORITHM; + r = 0; + goto finish; + } + if (md_algorithm < 0) { + r = md_algorithm; + goto finish; + } + + gcry_md_open(&md, md_algorithm, 0); + if (!md) { + r = -EIO; + goto finish; + } + + hash_size = gcry_md_get_algo_dlen(md_algorithm); + assert(hash_size > 0); + + gcry_md_write(md, sig_data, sig_size); + + hash = gcry_md_read(md, 0); + if (!hash) { + r = -EIO; + goto finish; + } } switch (rrsig->rrsig.algorithm) { @@ -802,6 +940,15 @@ int dnssec_verify_rrset( rrsig, dnskey); break; +#if GCRYPT_VERSION_NUMBER >= 0x010600 + case DNSSEC_ALGORITHM_ED25519: + r = dnssec_eddsa_verify( + rrsig->rrsig.algorithm, + sig_data, sig_size, + rrsig, + dnskey); + break; +#endif } if (r < 0) @@ -821,7 +968,9 @@ int dnssec_verify_rrset( r = 0; finish: - gcry_md_close(md); + if (md) + gcry_md_close(md); + return r; } diff --git a/src/resolve/resolved-dns-rr.c b/src/resolve/resolved-dns-rr.c index 4a0c1d6a35..26d2cbcc20 100644 --- a/src/resolve/resolved-dns-rr.c +++ b/src/resolve/resolved-dns-rr.c @@ -1849,6 +1849,8 @@ static const char* const dnssec_algorithm_table[_DNSSEC_ALGORITHM_MAX_DEFINED] = [DNSSEC_ALGORITHM_ECC_GOST] = "ECC-GOST", [DNSSEC_ALGORITHM_ECDSAP256SHA256] = "ECDSAP256SHA256", [DNSSEC_ALGORITHM_ECDSAP384SHA384] = "ECDSAP384SHA384", + [DNSSEC_ALGORITHM_ED25519] = "ED25519", + [DNSSEC_ALGORITHM_ED448] = "ED448", [DNSSEC_ALGORITHM_INDIRECT] = "INDIRECT", [DNSSEC_ALGORITHM_PRIVATEDNS] = "PRIVATEDNS", [DNSSEC_ALGORITHM_PRIVATEOID] = "PRIVATEOID", diff --git a/src/resolve/resolved-dns-rr.h b/src/resolve/resolved-dns-rr.h index 3f3d46e6b3..8e1a6bb2dc 100644 --- a/src/resolve/resolved-dns-rr.h +++ b/src/resolve/resolved-dns-rr.h @@ -57,6 +57,8 @@ enum { DNSSEC_ALGORITHM_ECC_GOST = 12, /* RFC 5933 */ DNSSEC_ALGORITHM_ECDSAP256SHA256 = 13, /* RFC 6605 */ DNSSEC_ALGORITHM_ECDSAP384SHA384 = 14, /* RFC 6605 */ + DNSSEC_ALGORITHM_ED25519 = 15, /* RFC 8080 */ + DNSSEC_ALGORITHM_ED448 = 16, /* RFC 8080 */ DNSSEC_ALGORITHM_INDIRECT = 252, DNSSEC_ALGORITHM_PRIVATEDNS, DNSSEC_ALGORITHM_PRIVATEOID, diff --git a/src/resolve/test-dnssec.c b/src/resolve/test-dnssec.c index aea7fff1d6..2d2b5e31bf 100644 --- a/src/resolve/test-dnssec.c +++ b/src/resolve/test-dnssec.c @@ -19,6 +19,7 @@ ***/ #include <arpa/inet.h> +#include <gcrypt.h> #include <netinet/in.h> #include <sys/socket.h> @@ -124,6 +125,189 @@ static void test_dnssec_verify_dns_key(void) { assert_se(dnssec_verify_dnskey_by_ds(dnskey, ds2, false) > 0); } +static void test_dnssec_verify_rfc8080_ed25519_example1(void) { + static const uint8_t dnskey_blob[] = { + 0x97, 0x4d, 0x96, 0xa2, 0x2d, 0x22, 0x4b, 0xc0, 0x1a, 0xdb, 0x91, 0x50, 0x91, 0x47, 0x7d, + 0x44, 0xcc, 0xd9, 0x1c, 0x9a, 0x41, 0xa1, 0x14, 0x30, 0x01, 0x01, 0x17, 0xd5, 0x2c, 0x59, + 0x24, 0xe + }; + static const uint8_t ds_fprint[] = { + 0xdd, 0xa6, 0xb9, 0x69, 0xbd, 0xfb, 0x79, 0xf7, 0x1e, 0xe7, 0xb7, 0xfb, 0xdf, 0xb7, 0xdc, + 0xd7, 0xad, 0xbb, 0xd3, 0x5d, 0xdf, 0x79, 0xed, 0x3b, 0x6d, 0xd7, 0xf6, 0xe3, 0x56, 0xdd, + 0xd7, 0x47, 0xf7, 0x6f, 0x5f, 0x7a, 0xe1, 0xa6, 0xf9, 0xe5, 0xce, 0xfc, 0x7b, 0xbf, 0x5a, + 0xdf, 0x4e, 0x1b + }; + static const uint8_t signature_blob[] = { + 0xa0, 0xbf, 0x64, 0xac, 0x9b, 0xa7, 0xef, 0x17, 0xc1, 0x38, 0x85, 0x9c, 0x18, 0x78, 0xbb, + 0x99, 0xa8, 0x39, 0xfe, 0x17, 0x59, 0xac, 0xa5, 0xb0, 0xd7, 0x98, 0xcf, 0x1a, 0xb1, 0xe9, + 0x8d, 0x07, 0x91, 0x02, 0xf4, 0xdd, 0xb3, 0x36, 0x8f, 0x0f, 0xe4, 0x0b, 0xb3, 0x77, 0xf1, + 0xf0, 0x0e, 0x0c, 0xdd, 0xed, 0xb7, 0x99, 0x16, 0x7d, 0x56, 0xb6, 0xe9, 0x32, 0x78, 0x30, + 0x72, 0xba, 0x8d, 0x02 + }; + + _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *dnskey = NULL, *ds = NULL, *mx = NULL, + *rrsig = NULL; + _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL; + DnssecResult result; + + dnskey = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DNSKEY, "example.com."); + assert_se(dnskey); + + dnskey->dnskey.flags = 257; + dnskey->dnskey.protocol = 3; + dnskey->dnskey.algorithm = DNSSEC_ALGORITHM_ED25519; + dnskey->dnskey.key_size = sizeof(dnskey_blob); + dnskey->dnskey.key = memdup(dnskey_blob, sizeof(dnskey_blob)); + assert_se(dnskey->dnskey.key); + + log_info("DNSKEY: %s", strna(dns_resource_record_to_string(dnskey))); + + ds = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DS, "example.com."); + assert_se(ds); + + ds->ds.key_tag = 3613; + ds->ds.algorithm = DNSSEC_ALGORITHM_ED25519; + ds->ds.digest_type = DNSSEC_DIGEST_SHA256; + ds->ds.digest_size = sizeof(ds_fprint); + ds->ds.digest = memdup(ds_fprint, ds->ds.digest_size); + assert_se(ds->ds.digest); + + log_info("DS: %s", strna(dns_resource_record_to_string(ds))); + + mx = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_MX, "example.com."); + assert_se(mx); + + mx->mx.priority = 10; + mx->mx.exchange = strdup("mail.example.com."); + assert_se(mx->mx.exchange); + + log_info("MX: %s", strna(dns_resource_record_to_string(mx))); + + rrsig = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_RRSIG, "example.com."); + assert_se(rrsig); + + rrsig->rrsig.type_covered = DNS_TYPE_MX; + rrsig->rrsig.algorithm = DNSSEC_ALGORITHM_ED25519; + rrsig->rrsig.labels = 2; + rrsig->rrsig.original_ttl = 3600; + rrsig->rrsig.expiration = 1440021600; + rrsig->rrsig.inception = 1438207200; + rrsig->rrsig.key_tag = 3613; + rrsig->rrsig.signer = strdup("example.com."); + assert_se(rrsig->rrsig.signer); + rrsig->rrsig.signature_size = sizeof(signature_blob); + rrsig->rrsig.signature = memdup(signature_blob, rrsig->rrsig.signature_size); + assert_se(rrsig->rrsig.signature); + + log_info("RRSIG: %s", strna(dns_resource_record_to_string(rrsig))); + + assert_se(dnssec_key_match_rrsig(mx->key, rrsig) > 0); + assert_se(dnssec_rrsig_match_dnskey(rrsig, dnskey, false) > 0); + + answer = dns_answer_new(1); + assert_se(answer); + assert_se(dns_answer_add(answer, mx, 0, DNS_ANSWER_AUTHENTICATED) >= 0); + + assert_se(dnssec_verify_rrset(answer, mx->key, rrsig, dnskey, + rrsig->rrsig.inception * USEC_PER_SEC, &result) >= 0); +#if GCRYPT_VERSION_NUMBER >= 0x010600 + assert_se(result == DNSSEC_VALIDATED); +#else + assert_se(result == DNSSEC_UNSUPPORTED_ALGORITHM); +#endif +} + +static void test_dnssec_verify_rfc8080_ed25519_example2(void) { + static const uint8_t dnskey_blob[] = { + 0xcc, 0xf9, 0xd9, 0xfd, 0x0c, 0x04, 0x7b, 0xb4, 0xbc, 0x0b, 0x94, 0x8f, 0xcf, 0x63, 0x9f, + 0x4b, 0x94, 0x51, 0xe3, 0x40, 0x13, 0x93, 0x6f, 0xeb, 0x62, 0x71, 0x3d, 0xc4, 0x72, 0x4, + 0x8a, 0x3b + }; + static const uint8_t ds_fprint[] = { + 0xe3, 0x4d, 0x7b, 0xf3, 0x56, 0xfd, 0xdf, 0x87, 0xb7, 0xf7, 0x67, 0x5e, 0xe3, 0xdd, 0x9e, + 0x73, 0xbe, 0xda, 0x7b, 0x67, 0xb5, 0xe5, 0xde, 0xf4, 0x7f, 0xae, 0x7b, 0xe5, 0xad, 0x5c, + 0xd1, 0xb7, 0x39, 0xf5, 0xce, 0x76, 0xef, 0x97, 0x34, 0xe1, 0xe6, 0xde, 0xf3, 0x47, 0x3a, + 0xeb, 0x5e, 0x1c + }; + static const uint8_t signature_blob[] = { + 0xcd, 0x74, 0x34, 0x6e, 0x46, 0x20, 0x41, 0x31, 0x05, 0xc9, 0xf2, 0xf2, 0x8b, 0xd4, 0x28, + 0x89, 0x8e, 0x83, 0xf1, 0x97, 0x58, 0xa3, 0x8c, 0x32, 0x52, 0x15, 0x62, 0xa1, 0x86, 0x57, + 0x15, 0xd4, 0xf8, 0xd7, 0x44, 0x0f, 0x44, 0x84, 0xd0, 0x4a, 0xa2, 0x52, 0x9f, 0x34, 0x28, + 0x4a, 0x6e, 0x69, 0xa0, 0x9e, 0xe0, 0x0f, 0xb0, 0x10, 0x47, 0x43, 0xbb, 0x2a, 0xe2, 0x39, + 0x93, 0x6a, 0x5c, 0x06 + }; + + _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *dnskey = NULL, *ds = NULL, *mx = NULL, + *rrsig = NULL; + _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL; + DnssecResult result; + + dnskey = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DNSKEY, "example.com."); + assert_se(dnskey); + + dnskey->dnskey.flags = 257; + dnskey->dnskey.protocol = 3; + dnskey->dnskey.algorithm = DNSSEC_ALGORITHM_ED25519; + dnskey->dnskey.key_size = sizeof(dnskey_blob); + dnskey->dnskey.key = memdup(dnskey_blob, sizeof(dnskey_blob)); + assert_se(dnskey->dnskey.key); + + log_info("DNSKEY: %s", strna(dns_resource_record_to_string(dnskey))); + + ds = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DS, "example.com."); + assert_se(ds); + + ds->ds.key_tag = 35217; + ds->ds.algorithm = DNSSEC_ALGORITHM_ED25519; + ds->ds.digest_type = DNSSEC_DIGEST_SHA256; + ds->ds.digest_size = sizeof(ds_fprint); + ds->ds.digest = memdup(ds_fprint, ds->ds.digest_size); + assert_se(ds->ds.digest); + + log_info("DS: %s", strna(dns_resource_record_to_string(ds))); + + mx = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_MX, "example.com."); + assert_se(mx); + + mx->mx.priority = 10; + mx->mx.exchange = strdup("mail.example.com."); + assert_se(mx->mx.exchange); + + log_info("MX: %s", strna(dns_resource_record_to_string(mx))); + + rrsig = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_RRSIG, "example.com."); + assert_se(rrsig); + + rrsig->rrsig.type_covered = DNS_TYPE_MX; + rrsig->rrsig.algorithm = DNSSEC_ALGORITHM_ED25519; + rrsig->rrsig.labels = 2; + rrsig->rrsig.original_ttl = 3600; + rrsig->rrsig.expiration = 1440021600; + rrsig->rrsig.inception = 1438207200; + rrsig->rrsig.key_tag = 35217; + rrsig->rrsig.signer = strdup("example.com."); + assert_se(rrsig->rrsig.signer); + rrsig->rrsig.signature_size = sizeof(signature_blob); + rrsig->rrsig.signature = memdup(signature_blob, rrsig->rrsig.signature_size); + assert_se(rrsig->rrsig.signature); + + log_info("RRSIG: %s", strna(dns_resource_record_to_string(rrsig))); + + assert_se(dnssec_key_match_rrsig(mx->key, rrsig) > 0); + assert_se(dnssec_rrsig_match_dnskey(rrsig, dnskey, false) > 0); + + answer = dns_answer_new(1); + assert_se(answer); + assert_se(dns_answer_add(answer, mx, 0, DNS_ANSWER_AUTHENTICATED) >= 0); + + assert_se(dnssec_verify_rrset(answer, mx->key, rrsig, dnskey, + rrsig->rrsig.inception * USEC_PER_SEC, &result) >= 0); +#if GCRYPT_VERSION_NUMBER >= 0x010600 + assert_se(result == DNSSEC_VALIDATED); +#else + assert_se(result == DNSSEC_UNSUPPORTED_ALGORITHM); +#endif +} static void test_dnssec_verify_rrset(void) { static const uint8_t signature_blob[] = { @@ -335,6 +519,8 @@ int main(int argc, char*argv[]) { #if HAVE_GCRYPT test_dnssec_verify_dns_key(); + test_dnssec_verify_rfc8080_ed25519_example1(); + test_dnssec_verify_rfc8080_ed25519_example2(); test_dnssec_verify_rrset(); test_dnssec_verify_rrset2(); test_dnssec_nsec3_hash(); |