]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Use thread_local EVP_MD_CTX in isc_iterated_hash()
authorOndřej Surý <ondrej@isc.org>
Mon, 16 Jan 2023 10:12:06 +0000 (11:12 +0100)
committerOndřej Surý <ondrej@isc.org>
Wed, 18 Jan 2023 18:36:21 +0000 (19:36 +0100)
As this code is on hot path (NSEC3) this introduces an additional
optimization of the EVP_MD API - instead of calling EVP_MD_CTX_new() on
every call to isc_iterated_hash(), we create two thread_local objects
for each thread - a basectx and mdctx, initialize basectx once and then
use EVP_MD_CTX_copy_ex() to flip the initialized state into mdctx.  This
saves us couple more valuable microseconds from the isc_iterated_hash()
call.

lib/isc/include/isc/iterated_hash.h
lib/isc/iterated_hash.c
lib/isc/lib.c
lib/isc/trampoline.c

index b5d6ab676ba22bee34f0e605936eb3ddba899ea3..cb21761c962ac4a16a6491e5a823340dba8f07c7 100644 (file)
@@ -35,4 +35,13 @@ isc_iterated_hash(unsigned char *out, const unsigned int hashalg,
                  const int saltlength, const unsigned char *in,
                  const int inlength);
 
+/*
+ * Private
+ */
+
+void
+isc__iterated_hash_initialize(void);
+void
+isc__iterated_hash_shutdown(void);
+
 ISC_LANG_ENDDECLS
index a2a6e234cfb3f84cd7fec80ace98596ab5cccacd..cafbb5a9776f6e2d62f1bd1d1d351010bacdee09 100644 (file)
@@ -65,26 +65,39 @@ isc_iterated_hash(unsigned char *out, const unsigned int hashalg,
        return (SHA_DIGEST_LENGTH);
 }
 
-#else
+void
+isc__iterated_hash_initialize(void) {
+       /* empty */
+}
+
+void
+isc__iterated_hash_shutdown(void) {
+       /* empty */
+}
+
+#else /* HAVE_SHA1_INIT */
 
 #include <openssl/evp.h>
 
 #include <isc/md.h>
 
+static thread_local bool initialized = false;
+static thread_local EVP_MD_CTX *mdctx = NULL;
+static thread_local EVP_MD_CTX *basectx = NULL;
+
 int
 isc_iterated_hash(unsigned char *out, const unsigned int hashalg,
                  const int iterations, const unsigned char *salt,
                  const int saltlength, const unsigned char *in,
                  const int inlength) {
        REQUIRE(out != NULL);
+       REQUIRE(mdctx != NULL);
+       REQUIRE(basectx != NULL);
 
        int n = 0;
        size_t len;
        unsigned int outlength = 0;
        const unsigned char *buf;
-       EVP_MD_CTX *ctx = EVP_MD_CTX_create();
-
-       RUNTIME_CHECK(ctx != NULL);
 
        if (hashalg != 1) {
                return (0);
@@ -92,21 +105,20 @@ isc_iterated_hash(unsigned char *out, const unsigned int hashalg,
 
        buf = in;
        len = inlength;
-
        do {
-               if (EVP_DigestInit_ex(ctx, ISC_MD_SHA1, NULL) != 1) {
+               if (EVP_MD_CTX_copy_ex(mdctx, basectx) != 1) {
                        goto fail;
                }
 
-               if (EVP_DigestUpdate(ctx, buf, len) != 1) {
+               if (EVP_DigestUpdate(mdctx, buf, len) != 1) {
                        goto fail;
                }
 
-               if (EVP_DigestUpdate(ctx, salt, saltlength) != 1) {
+               if (EVP_DigestUpdate(mdctx, salt, saltlength) != 1) {
                        goto fail;
                }
 
-               if (EVP_DigestFinal_ex(ctx, out, &outlength) != 1) {
+               if (EVP_DigestFinal_ex(mdctx, out, &outlength) != 1) {
                        goto fail;
                }
 
@@ -114,13 +126,41 @@ isc_iterated_hash(unsigned char *out, const unsigned int hashalg,
                len = outlength;
        } while (n++ < iterations);
 
-       EVP_MD_CTX_free(ctx);
-
        return (outlength);
 
 fail:
-       EVP_MD_CTX_free(ctx);
        return (0);
 }
 
-#endif
+void
+isc__iterated_hash_initialize(void) {
+       if (initialized) {
+               return;
+       }
+
+       basectx = EVP_MD_CTX_new();
+       INSIST(basectx != NULL);
+       mdctx = EVP_MD_CTX_new();
+       INSIST(mdctx != NULL);
+
+       RUNTIME_CHECK(EVP_DigestInit_ex(basectx, ISC_MD_SHA1, NULL) == 1);
+       initialized = true;
+}
+
+void
+isc__iterated_hash_shutdown(void) {
+       if (!initialized) {
+               return;
+       }
+
+       REQUIRE(mdctx != NULL);
+       EVP_MD_CTX_free(mdctx);
+       mdctx = NULL;
+       REQUIRE(basectx != NULL);
+       EVP_MD_CTX_free(basectx);
+       basectx = NULL;
+
+       initialized = false;
+}
+
+#endif /* HAVE_SHA1_INIT */
index 33c874906d3549fa32ba0e18b8c573e8a3cef0f4..daf00a59711fd1c8f8f8a06e40a3f4566a30b40c 100644 (file)
@@ -14,6 +14,7 @@
 /*! \file */
 
 #include <isc/bind9.h>
+#include <isc/iterated_hash.h>
 #include <isc/md.h>
 #include <isc/mem.h>
 #include <isc/os.h>
@@ -51,11 +52,13 @@ isc__initialize(void) {
        isc__uv_initialize();
        isc__xml_initialize();
        isc__md_initialize();
+       isc__iterated_hash_initialize();
        (void)isc_os_ncpus();
 }
 
 void
 isc__shutdown(void) {
+       isc__iterated_hash_shutdown();
        isc__md_shutdown();
        isc__xml_shutdown();
        isc__uv_shutdown();
index c862ba37b0beef6ddbcea2603a307d46de7b9eaa..736c5840df4dd6c7b6c0e5eb19cc238133681638 100644 (file)
@@ -16,6 +16,8 @@
 #include <inttypes.h>
 #include <stdlib.h>
 
+#include <isc/iterated_hash.h>
+#include <isc/md.h>
 #include <isc/mem.h>
 #include <isc/once.h>
 #include <isc/thread.h>
@@ -194,9 +196,13 @@ isc__trampoline_run(isc_threadarg_t arg) {
 
        isc__trampoline_attach(trampoline);
 
+       isc__iterated_hash_initialize();
+
        /* Run the main function */
        result = (trampoline->start)(trampoline->arg);
 
+       isc__iterated_hash_shutdown();
+
        isc__trampoline_detach(trampoline);
 
        return (result);