From: Libor Peltan Date: Thu, 30 Apr 2020 12:25:56 +0000 (+0200) Subject: dnssec: enable speedup of rrsig validation by deterministic ECDSA X-Git-Tag: v3.0.0~25^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=03029bcbfeaa90eccc5a601009d63e283f6604e0;p=thirdparty%2Fknot-dns.git dnssec: enable speedup of rrsig validation by deterministic ECDSA --- diff --git a/src/knot/dnssec/rrset-sign.c b/src/knot/dnssec/rrset-sign.c index eabd58a098..2175541a4b 100644 --- a/src/knot/dnssec/rrset-sign.c +++ b/src/knot/dnssec/rrset-sign.c @@ -406,5 +406,9 @@ int knot_check_signature(const knot_rrset_t *covered, return result; } - return dnssec_sign_verify(sign_ctx, &signature); + bool sign_cmp = dnssec_ctx->policy->reproducible_sign && + dnssec_algorithm_allow_dsa_reproducible( + dnssec_ctx->policy->algorithm); + + return dnssec_sign_verify(sign_ctx, sign_cmp, &signature); } diff --git a/src/knot/zone/semantic-check.c b/src/knot/zone/semantic-check.c index 47bb1ea83b..ab89188659 100644 --- a/src/knot/zone/semantic-check.c +++ b/src/knot/zone/semantic-check.c @@ -223,7 +223,7 @@ static int check_signature(const knot_rdata_t *rrsig, const dnssec_key_t *key, goto fail; } - if (dnssec_sign_verify(sign_ctx, &signature) != KNOT_EOK) { + if (dnssec_sign_verify(sign_ctx, false, &signature) != KNOT_EOK) { ret = KNOT_EINVAL; goto fail; } diff --git a/src/libdnssec/key.h b/src/libdnssec/key.h index 64991017c6..61bb9f8ab2 100644 --- a/src/libdnssec/key.h +++ b/src/libdnssec/key.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2018 CZ.NIC, z.s.p.o. +/* Copyright (C) 2020 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -107,6 +107,11 @@ typedef struct dnssec_key dnssec_key_t; */ bool dnssec_algorithm_key_support(dnssec_key_algorithm_t algo); +/*! + * Tell whether algo allows DSA deterministing signing. + */ +bool dnssec_algorithm_allow_dsa_reproducible(dnssec_key_algorithm_t algo); + /*! * Allocate new DNSSEC key. * diff --git a/src/libdnssec/key/algorithm.c b/src/libdnssec/key/algorithm.c index d250d0d8f6..2e9a485135 100644 --- a/src/libdnssec/key/algorithm.c +++ b/src/libdnssec/key/algorithm.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2018 CZ.NIC, z.s.p.o. +/* Copyright (C) 2020 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -115,6 +115,22 @@ bool dnssec_algorithm_key_support(dnssec_key_algorithm_t algo) return algorithm_to_gnutls(algo) != GNUTLS_PK_UNKNOWN; } +_public_ +bool dnssec_algorithm_allow_dsa_reproducible(dnssec_key_algorithm_t algo) +{ +#ifdef HAVE_GLNUTLS_REPRODUCIBLE + switch (algo) { + case DNSSEC_KEY_ALGORITHM_ECDSA_P256_SHA256: + case DNSSEC_KEY_ALGORITHM_ECDSA_P384_SHA384: + return true; + default: + return false; + } +#else + return false; +#endif +} + _public_ int dnssec_algorithm_key_size_range(dnssec_key_algorithm_t algorithm, unsigned *min_ptr, unsigned *max_ptr) diff --git a/src/libdnssec/sign.h b/src/libdnssec/sign.h index b876490f99..247f9682fb 100644 --- a/src/libdnssec/sign.h +++ b/src/libdnssec/sign.h @@ -127,18 +127,22 @@ int dnssec_sign_add(dnssec_sign_ctx_t *ctx, const dnssec_binary_t *data); * * \return Error code, DNSSEC_EOK if successful. */ -int dnssec_sign_write(dnssec_sign_ctx_t *ctx, dnssec_sign_flags_t flags, dnssec_binary_t *signature); +int dnssec_sign_write(dnssec_sign_ctx_t *ctx, dnssec_sign_flags_t flags, + dnssec_binary_t *signature); /*! * Verify DNSSEC signature. * * \param ctx Signing context. + * \param sign_cmp Verify by signing and comparing signatures. + * Not possible for non-deterministic algorithms! * \param signature Signature to be verified. * * \return Error code. * \retval DNSSEC_EOK Validation successful, valid signature. * \retval DNSSEC_INVALID_SIGNATURE Validation successful, invalid signature. */ -int dnssec_sign_verify(dnssec_sign_ctx_t *ctx, const dnssec_binary_t *signature); +int dnssec_sign_verify(dnssec_sign_ctx_t *ctx, bool sign_cmp, + const dnssec_binary_t *signature); /*! @} */ diff --git a/src/libdnssec/sign/sign.c b/src/libdnssec/sign/sign.c index 56ea93aabf..3f9557aaff 100644 --- a/src/libdnssec/sign/sign.c +++ b/src/libdnssec/sign/sign.c @@ -378,12 +378,23 @@ int dnssec_sign_write(dnssec_sign_ctx_t *ctx, dnssec_sign_flags_t flags, dnssec_ } _public_ -int dnssec_sign_verify(dnssec_sign_ctx_t *ctx, const dnssec_binary_t *signature) +int dnssec_sign_verify(dnssec_sign_ctx_t *ctx, bool sign_cmp, const dnssec_binary_t *signature) { if (!ctx || !signature) { return DNSSEC_EINVAL; } + if (sign_cmp && dnssec_key_can_sign(ctx->key)) { + dnssec_binary_t sign = { 0 }; + int ret = dnssec_sign_write(ctx, DNSSEC_SIGN_REPRODUCIBLE, &sign); + if (ret == KNOT_EOK) { + ret = dnssec_binary_cmp(&sign, signature) + ? DNSSEC_INVALID_SIGNATURE + : DNSSEC_EOK; + } + return ret; + } + if (!dnssec_key_can_verify(ctx->key)) { return DNSSEC_NO_PUBLIC_KEY; } diff --git a/tests-extra/tests/dnssec/no_resign2/test.py b/tests-extra/tests/dnssec/no_resign2/test.py index 8273f6b567..4d2b020e5b 100644 --- a/tests-extra/tests/dnssec/no_resign2/test.py +++ b/tests-extra/tests/dnssec/no_resign2/test.py @@ -14,6 +14,7 @@ zone = t.zone("example.com.", storage=".") t.link(zone, master, ixfr=True, journal_content="all") master.dnssec(zone).enable = True +master.dnssec(zone).repro_sign = True t.start() diff --git a/tests/libdnssec/test_keystore_pkcs11.c b/tests/libdnssec/test_keystore_pkcs11.c index 78e897be58..9d4ef102db 100644 --- a/tests/libdnssec/test_keystore_pkcs11.c +++ b/tests/libdnssec/test_keystore_pkcs11.c @@ -291,7 +291,7 @@ static void test_sign(dnssec_key_t *p11_key, dnssec_key_t *soft_key) r = dnssec_sign_add(ctx, &input); ok(r == DNSSEC_EOK, MSG_PKCS11 " dnssec_sign_add()"); - r = dnssec_sign_verify(ctx, &sign); + r = dnssec_sign_verify(ctx, false, &sign); ok(r == DNSSEC_EOK, MSG_PKCS11 " dnssec_sign_verify()"); // software verification @@ -305,7 +305,7 @@ static void test_sign(dnssec_key_t *p11_key, dnssec_key_t *soft_key) r = dnssec_sign_add(ctx, &input); ok(r == DNSSEC_EOK, MSG_SOFTWARE " dnssec_sign_add()"); - r = dnssec_sign_verify(ctx, &sign); + r = dnssec_sign_verify(ctx, false, &sign); ok(r == DNSSEC_EOK, MSG_SOFTWARE " dnssec_sign_verify()"); dnssec_binary_free(&sign); diff --git a/tests/libdnssec/test_sign.c b/tests/libdnssec/test_sign.c index 217eef51d5..57cd0e78ba 100644 --- a/tests/libdnssec/test_sign.c +++ b/tests/libdnssec/test_sign.c @@ -96,7 +96,7 @@ static void check_key(const key_parameters_t *key_data, const dnssec_binary_t *d ok(r == DNSSEC_EOK, "create signing context"); r = dnssec_sign_add(ctx, data); ok(r == DNSSEC_EOK, "add data to be signed"); - r = dnssec_sign_verify(ctx, signature); + r = dnssec_sign_verify(ctx, false, signature); ok(r == DNSSEC_EOK, "signature verified"); // create new signature and self-validate @@ -114,7 +114,7 @@ static void check_key(const key_parameters_t *key_data, const dnssec_binary_t *d ok(r == DNSSEC_EOK, "write the signature"); ok(dnssec_binary_cmp(signature, &new_signature) == 0, "signature exact match"); - r = dnssec_sign_verify(ctx, &new_signature); + r = dnssec_sign_verify(ctx, false, &new_signature); ok(r == DNSSEC_EOK, "reverify the new signature"); dnssec_binary_free(&new_signature); } @@ -152,7 +152,7 @@ static void check_key(const key_parameters_t *key_data, const dnssec_binary_t *d r = dnssec_sign_add(ctx, &tmp); ok(r == DNSSEC_EOK, "add data (4)"); - r = dnssec_sign_verify(ctx, &new_signature); + r = dnssec_sign_verify(ctx, false, &new_signature); ok(r == DNSSEC_EOK, "verify signature"); dnssec_binary_free(&new_signature);