]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Optimise dnssec-verify
authorMark Andrews <marka@isc.org>
Wed, 25 Nov 2020 06:52:22 +0000 (17:52 +1100)
committerMark Andrews <marka@isc.org>
Thu, 28 Jan 2021 00:07:03 +0000 (11:07 +1100)
dns_dnssec_keyfromrdata() only needs to be called once per DNSKEY
rather than once per verification attempt.

lib/dns/zoneverify.c

index 4219a710e5f97e838ae0a67eea687e829d3e4c59..a7780aa87e9faefe93ae0d580be268161506624f 100644 (file)
@@ -161,37 +161,22 @@ has_dname(const vctx_t *vctx, dns_dbnode_t *node) {
 
 static bool
 goodsig(const vctx_t *vctx, dns_rdata_t *sigrdata, const dns_name_t *name,
-       dns_rdataset_t *keyrdataset, dns_rdataset_t *rdataset) {
-       dns_rdata_dnskey_t key;
+       dst_key_t **dstkeys, size_t nkeys, dns_rdataset_t *rdataset) {
        dns_rdata_rrsig_t sig;
-       dst_key_t *dstkey = NULL;
        isc_result_t result;
 
        result = dns_rdata_tostruct(sigrdata, &sig, NULL);
        RUNTIME_CHECK(result == ISC_R_SUCCESS);
 
-       for (result = dns_rdataset_first(keyrdataset); result == ISC_R_SUCCESS;
-            result = dns_rdataset_next(keyrdataset))
-       {
-               dns_rdata_t rdata = DNS_RDATA_INIT;
-               dns_rdataset_current(keyrdataset, &rdata);
-               result = dns_rdata_tostruct(&rdata, &key, NULL);
-               RUNTIME_CHECK(result == ISC_R_SUCCESS);
-               result = dns_dnssec_keyfromrdata(vctx->origin, &rdata,
-                                                vctx->mctx, &dstkey);
-               if (result != ISC_R_SUCCESS) {
-                       return (false);
-               }
-               if (sig.algorithm != key.algorithm ||
-                   sig.keyid != dst_key_id(dstkey) ||
+       for (size_t key = 0; key < nkeys; key++) {
+               if (sig.algorithm != dst_key_alg(dstkeys[key]) ||
+                   sig.keyid != dst_key_id(dstkeys[key]) ||
                    !dns_name_equal(&sig.signer, vctx->origin))
                {
-                       dst_key_free(&dstkey);
                        continue;
                }
-               result = dns_dnssec_verify(name, rdataset, dstkey, false, 0,
-                                          vctx->mctx, sigrdata, NULL);
-               dst_key_free(&dstkey);
+               result = dns_dnssec_verify(name, rdataset, dstkeys[key], false,
+                                          0, vctx->mctx, sigrdata, NULL);
                if (result == ISC_R_SUCCESS || result == DNS_R_FROMWILDCARD) {
                        return (true);
                }
@@ -816,7 +801,7 @@ verifynsec3s(const vctx_t *vctx, const dns_name_t *name,
 
 static isc_result_t
 verifyset(vctx_t *vctx, dns_rdataset_t *rdataset, const dns_name_t *name,
-         dns_dbnode_t *node, dns_rdataset_t *keyrdataset) {
+         dns_dbnode_t *node, dst_key_t **dstkeys, size_t nkeys) {
        unsigned char set_algorithms[256];
        char namebuf[DNS_NAME_FORMATSIZE];
        char algbuf[DNS_SECALG_FORMATSIZE];
@@ -883,7 +868,7 @@ verifyset(vctx_t *vctx, dns_rdataset_t *rdataset, const dns_name_t *name,
                {
                        continue;
                }
-               if (goodsig(vctx, &rdata, name, keyrdataset, rdataset)) {
+               if (goodsig(vctx, &rdata, name, dstkeys, nkeys, rdataset)) {
                        dns_rdataset_settrust(rdataset, dns_trust_secure);
                        dns_rdataset_settrust(&sigrdataset, dns_trust_secure);
                        set_algorithms[sig.algorithm] = 1;
@@ -919,7 +904,7 @@ done:
 
 static isc_result_t
 verifynode(vctx_t *vctx, const dns_name_t *name, dns_dbnode_t *node,
-          bool delegation, dns_rdataset_t *keyrdataset,
+          bool delegation, dst_key_t **dstkeys, size_t nkeys,
           dns_rdataset_t *nsecset, dns_rdataset_t *nsec3paramset,
           const dns_name_t *nextname, isc_result_t *vresult) {
        unsigned char types[8192];
@@ -953,8 +938,8 @@ verifynode(vctx_t *vctx, const dns_name_t *name, dns_dbnode_t *node,
                    (!delegation || rdataset.type == dns_rdatatype_ds ||
                     rdataset.type == dns_rdatatype_nsec))
                {
-                       result = verifyset(vctx, &rdataset, name, node,
-                                          keyrdataset);
+                       result = verifyset(vctx, &rdataset, name, node, dstkeys,
+                                          nkeys);
                        if (result != ISC_R_SUCCESS) {
                                dns_rdataset_disassociate(&rdataset);
                                dns_rdatasetiter_destroy(&rdsiter);
@@ -1724,6 +1709,8 @@ verify_nodes(vctx_t *vctx, isc_result_t *vresult) {
        dns_name_t *name, *nextname, *prevname, *zonecut;
        dns_dbnode_t *node = NULL, *nextnode;
        dns_dbiterator_t *dbiter = NULL;
+       dst_key_t **dstkeys;
+       size_t count, nkeys = 0;
        bool done = false;
        isc_result_t tvresult = ISC_R_UNSET;
        isc_result_t result;
@@ -1735,11 +1722,27 @@ verify_nodes(vctx_t *vctx, isc_result_t *vresult) {
        dns_fixedname_init(&fzonecut);
        zonecut = NULL;
 
+       count = dns_rdataset_count(&vctx->keyset);
+       dstkeys = isc_mem_get(vctx->mctx, sizeof(*dstkeys) * count);
+
+       for (result = dns_rdataset_first(&vctx->keyset);
+            result == ISC_R_SUCCESS; result = dns_rdataset_next(&vctx->keyset))
+       {
+               dns_rdata_t rdata = DNS_RDATA_INIT;
+               dns_rdataset_current(&vctx->keyset, &rdata);
+               dstkeys[nkeys] = NULL;
+               result = dns_dnssec_keyfromrdata(vctx->origin, &rdata,
+                                                vctx->mctx, &dstkeys[nkeys]);
+               if (result == ISC_R_SUCCESS) {
+                       nkeys++;
+               }
+       }
+
        result = dns_db_createiterator(vctx->db, DNS_DB_NONSEC3, &dbiter);
        if (result != ISC_R_SUCCESS) {
                zoneverify_log_error(vctx, "dns_db_createiterator(): %s",
                                     isc_result_totext(result));
-               return (result);
+               goto done;
        }
 
        result = dns_dbiterator_first(dbiter);
@@ -1839,9 +1842,9 @@ verify_nodes(vctx_t *vctx, isc_result_t *vresult) {
                        dns_db_detachnode(vctx->db, &node);
                        goto done;
                }
-               result = verifynode(vctx, name, node, isdelegation,
-                                   &vctx->keyset, &vctx->nsecset,
-                                   &vctx->nsec3paramset, nextname, &tvresult);
+               result = verifynode(vctx, name, node, isdelegation, dstkeys,
+                                   nkeys, &vctx->nsecset, &vctx->nsec3paramset,
+                                   nextname, &tvresult);
                if (result != ISC_R_SUCCESS) {
                        dns_db_detachnode(vctx->db, &node);
                        goto done;
@@ -1889,7 +1892,7 @@ verify_nodes(vctx_t *vctx, isc_result_t *vresult) {
                                             isc_result_totext(result));
                        goto done;
                }
-               result = verifynode(vctx, name, node, false, &vctx->keyset,
+               result = verifynode(vctx, name, node, false, dstkeys, nkeys,
                                    NULL, NULL, NULL, NULL);
                if (result != ISC_R_SUCCESS) {
                        zoneverify_log_error(vctx, "verifynode: %s",
@@ -1907,7 +1910,13 @@ verify_nodes(vctx_t *vctx, isc_result_t *vresult) {
        result = ISC_R_SUCCESS;
 
 done:
-       dns_dbiterator_destroy(&dbiter);
+       while (nkeys-- > 0U) {
+               dst_key_free(&dstkeys[nkeys]);
+       }
+       isc_mem_put(vctx->mctx, dstkeys, sizeof(*dstkeys) * count);
+       if (dbiter != NULL) {
+               dns_dbiterator_destroy(&dbiter);
+       }
 
        return (result);
 }