]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Optimize selecting the signing key
authorOndřej Surý <ondrej@isc.org>
Thu, 11 Jan 2024 12:58:52 +0000 (13:58 +0100)
committerMichał Kępień <michal@isc.org>
Thu, 1 Feb 2024 20:51:07 +0000 (21:51 +0100)
Don't parse the crypto data before parsing and matching the id and the
algorithm for consecutive DNSKEYs.  This allows us to parse the RData
only in case the other parameters match allowing us to skip keys that
are of no interest to us, but still would consume precious CPU time by
parsing possibly garbage with OpenSSL.

(cherry picked from commit f39cd17a26959e80b3ff4ce38e98936312395610)

lib/dns/dst_api.c
lib/dns/include/dst/dst.h
lib/dns/validator.c

index d49beb2ec99cb6491644a7cbddf9f8d14694d3b0..df5a358e5faea40a56c4f3f03aed6c1566f2d1ad 100644 (file)
@@ -164,7 +164,8 @@ computeid(dst_key_t *key);
 static isc_result_t
 frombuffer(const dns_name_t *name, unsigned int alg, unsigned int flags,
           unsigned int protocol, dns_rdataclass_t rdclass,
-          isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp);
+          isc_buffer_t *source, isc_mem_t *mctx, bool no_rdata,
+          dst_key_t **keyp);
 
 static isc_result_t
 algorithm_status(unsigned int alg);
@@ -780,6 +781,13 @@ dst_key_todns(const dst_key_t *key, isc_buffer_t *target) {
 isc_result_t
 dst_key_fromdns(const dns_name_t *name, dns_rdataclass_t rdclass,
                isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp) {
+       return (dst_key_fromdns_ex(name, rdclass, source, mctx, false, keyp));
+}
+
+isc_result_t
+dst_key_fromdns_ex(const dns_name_t *name, dns_rdataclass_t rdclass,
+                  isc_buffer_t *source, isc_mem_t *mctx, bool no_rdata,
+                  dst_key_t **keyp) {
        uint8_t alg, proto;
        uint32_t flags, extflags;
        dst_key_t *key = NULL;
@@ -810,7 +818,7 @@ dst_key_fromdns(const dns_name_t *name, dns_rdataclass_t rdclass,
        }
 
        result = frombuffer(name, alg, flags, proto, rdclass, source, mctx,
-                           &key);
+                           no_rdata, &key);
        if (result != ISC_R_SUCCESS) {
                return (result);
        }
@@ -831,7 +839,7 @@ dst_key_frombuffer(const dns_name_t *name, unsigned int alg, unsigned int flags,
        REQUIRE(dst_initialized);
 
        result = frombuffer(name, alg, flags, protocol, rdclass, source, mctx,
-                           &key);
+                           false, &key);
        if (result != ISC_R_SUCCESS) {
                return (result);
        }
@@ -2337,7 +2345,8 @@ computeid(dst_key_t *key) {
 static isc_result_t
 frombuffer(const dns_name_t *name, unsigned int alg, unsigned int flags,
           unsigned int protocol, dns_rdataclass_t rdclass,
-          isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp) {
+          isc_buffer_t *source, isc_mem_t *mctx, bool no_rdata,
+          dst_key_t **keyp) {
        dst_key_t *key;
        isc_result_t ret;
 
@@ -2362,10 +2371,12 @@ frombuffer(const dns_name_t *name, unsigned int alg, unsigned int flags,
                        return (DST_R_UNSUPPORTEDALG);
                }
 
-               ret = key->func->fromdns(key, source);
-               if (ret != ISC_R_SUCCESS) {
-                       dst_key_free(&key);
-                       return (ret);
+               if (!no_rdata) {
+                       ret = key->func->fromdns(key, source);
+                       if (ret != ISC_R_SUCCESS) {
+                               dst_key_free(&key);
+                               return (ret);
+                       }
                }
        }
 
index 3185e9f91b820b3897f7c873bfcc76c9887a11c8..3e3cfe6a68c30812cfa021c4a652b8d4396e3ecf 100644 (file)
@@ -471,6 +471,10 @@ dst_key_tofile(const dst_key_t *key, int type, const char *directory);
  */
 
 isc_result_t
+dst_key_fromdns_ex(const dns_name_t *name, dns_rdataclass_t rdclass,
+                  isc_buffer_t *source, isc_mem_t *mctx, bool no_rdata,
+                  dst_key_t **keyp);
+isc_result_t
 dst_key_fromdns(const dns_name_t *name, dns_rdataclass_t rdclass,
                isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp);
 /*%<
index 9dce5581286b07ecc83da2cf4cd2d419cf316ab0..243b19f64e21c75c396eca5ab04410a8c3abbdc1 100644 (file)
@@ -1118,6 +1118,7 @@ select_signing_key(dns_validator_t *val, dns_rdataset_t *rdataset) {
        isc_buffer_t b;
        dns_rdata_t rdata = DNS_RDATA_INIT;
        dst_key_t *oldkey = val->key;
+       bool no_rdata = false;
 
        if (oldkey == NULL) {
                result = dns_rdataset_first(rdataset);
@@ -1127,7 +1128,7 @@ select_signing_key(dns_validator_t *val, dns_rdataset_t *rdataset) {
                result = dns_rdataset_next(rdataset);
        }
        if (result != ISC_R_SUCCESS) {
-               goto failure;
+               goto done;
        }
 
        do {
@@ -1136,8 +1137,9 @@ select_signing_key(dns_validator_t *val, dns_rdataset_t *rdataset) {
                isc_buffer_init(&b, rdata.data, rdata.length);
                isc_buffer_add(&b, rdata.length);
                INSIST(val->key == NULL);
-               result = dst_key_fromdns(&siginfo->signer, rdata.rdclass, &b,
-                                        val->view->mctx, &val->key);
+               result = dst_key_fromdns_ex(&siginfo->signer, rdata.rdclass, &b,
+                                           val->view->mctx, no_rdata,
+                                           &val->key);
                if (result == ISC_R_SUCCESS) {
                        if (siginfo->algorithm ==
                                    (dns_secalg_t)dst_key_alg(val->key) &&
@@ -1147,18 +1149,24 @@ select_signing_key(dns_validator_t *val, dns_rdataset_t *rdataset) {
                                    0 &&
                            dst_key_iszonekey(val->key))
                        {
-                               /*
-                                * This is the key we're looking for.
-                                */
-                               return (ISC_R_SUCCESS);
+                               if (no_rdata) {
+                                       /* Retry with full key */
+                                       dns_rdata_reset(&rdata);
+                                       dst_key_free(&val->key);
+                                       no_rdata = false;
+                                       continue;
+                               }
+                               /* This is the key we're looking for. */
+                               goto done;
                        }
                        dst_key_free(&val->key);
                }
                dns_rdata_reset(&rdata);
                result = dns_rdataset_next(rdataset);
+               no_rdata = true;
        } while (result == ISC_R_SUCCESS);
 
-failure:
+done:
        if (result == ISC_R_NOMORE) {
                result = ISC_R_NOTFOUND;
        }