]> git.ipfire.org Git - thirdparty/knot-dns.git/commitdiff
dnssec: enable speedup of rrsig validation by deterministic ECDSA
authorLibor Peltan <libor.peltan@nic.cz>
Thu, 30 Apr 2020 12:25:56 +0000 (14:25 +0200)
committerDaniel Salzman <daniel.salzman@nic.cz>
Wed, 26 Aug 2020 09:10:02 +0000 (11:10 +0200)
src/knot/dnssec/rrset-sign.c
src/knot/zone/semantic-check.c
src/libdnssec/key.h
src/libdnssec/key/algorithm.c
src/libdnssec/sign.h
src/libdnssec/sign/sign.c
tests-extra/tests/dnssec/no_resign2/test.py
tests/libdnssec/test_keystore_pkcs11.c
tests/libdnssec/test_sign.c

index eabd58a098b3572986f9d8234dc48d2763639e75..2175541a4ba1232d9c5e5e42dc6b71a585e5d0cc 100644 (file)
@@ -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);
 }
index 47bb1ea83b2b9a3843a11f50df525a2e5e53fe6e..ab891886591dd47094ec753394507ba5b78cd095 100644 (file)
@@ -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;
        }
index 64991017c650075c11492b3536d07de8b099259d..61bb9f8ab2c73489896261fcccf0aa54042868fd 100644 (file)
@@ -1,4 +1,4 @@
-/*  Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+/*  Copyright (C) 2020 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
 
     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.
  *
index d250d0d8f61b2d283521a0bba7bbca63d2af2156..2e9a485135d632c00492f1f343da61f0966616f7 100644 (file)
@@ -1,4 +1,4 @@
-/*  Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+/*  Copyright (C) 2020 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
 
     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)
index b876490f99e64c9d4ef470fb9178d954bdb5afaa..247f9682fb1238307bb1496cb7da96f018ddeb88 100644 (file)
@@ -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);
 
 /*! @} */
index 56ea93aabf552eee217ed86521eac5a4e4f66aca..3f9557aaffcb524bf6050463ded1a06b888f13db 100644 (file)
@@ -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;
        }
index 8273f6b567263bff7c96c2f8b58705ccbc605073..4d2b020e5b1f450b696a9818462f76f40b44426e 100644 (file)
@@ -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()
 
index 78e897be583390c9282de06da4676bd3418f5426..9d4ef102db8f2219ec24d072bcd0e7d6a46c1c6e 100644 (file)
@@ -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);
index 217eef51d511a5cb47f3543b124fecb581961e4e..57cd0e78ba83e5820c0ccec8aa05c145f37f3ca7 100644 (file)
@@ -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);