From f3753d591fbc5057997e08eaf0b41c91ef466b2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= Date: Mon, 16 Jan 2023 11:12:06 +0100 Subject: [PATCH] Use thread_local EVP_MD_CTX in isc_iterated_hash() 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 | 9 ++++ lib/isc/iterated_hash.c | 66 +++++++++++++++++++++++------ lib/isc/lib.c | 3 ++ lib/isc/trampoline.c | 6 +++ 4 files changed, 71 insertions(+), 13 deletions(-) diff --git a/lib/isc/include/isc/iterated_hash.h b/lib/isc/include/isc/iterated_hash.h index b5d6ab676b..cb21761c96 100644 --- a/lib/isc/include/isc/iterated_hash.h +++ b/lib/isc/include/isc/iterated_hash.h @@ -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 diff --git a/lib/isc/iterated_hash.c b/lib/isc/iterated_hash.c index a2a6e234cf..cafbb5a977 100644 --- a/lib/isc/iterated_hash.c +++ b/lib/isc/iterated_hash.c @@ -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 #include +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 */ diff --git a/lib/isc/lib.c b/lib/isc/lib.c index 33c874906d..daf00a5971 100644 --- a/lib/isc/lib.c +++ b/lib/isc/lib.c @@ -14,6 +14,7 @@ /*! \file */ #include +#include #include #include #include @@ -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(); diff --git a/lib/isc/trampoline.c b/lib/isc/trampoline.c index c862ba37b0..736c5840df 100644 --- a/lib/isc/trampoline.c +++ b/lib/isc/trampoline.c @@ -16,6 +16,8 @@ #include #include +#include +#include #include #include #include @@ -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);