mirror of
https://github.com/isc-projects/bind9.git
synced 2026-06-08 21:52:06 -04:00
Merge branch '3795-speed-up-EVP_DigestInit_ex' into 'main'
Avoid implicit algorithm fetch for OpenSSL EVP_MD family See merge request isc-projects/bind9!7375
This commit is contained in:
commit
35e2842d00
11 changed files with 301 additions and 55 deletions
6
CHANGES
6
CHANGES
|
|
@ -1,3 +1,9 @@
|
|||
6072. [bug] Avoid the OpenSSL lock contention when initializing
|
||||
Message Digest Contexts by using explicit algorithm
|
||||
fetching, initializing static contexts for every
|
||||
supported algorithms, and initializing the new context
|
||||
by copying the static copy. [GL #3795]
|
||||
|
||||
6071. [func] The use of "port" when configuring query-source,
|
||||
transfer-source, notify-source and parental-source
|
||||
addresses has been deprecated, along with the
|
||||
|
|
|
|||
|
|
@ -55,6 +55,9 @@ Bug Fixes
|
|||
cause increased memory consumption due to delayed cleaning of view memory.
|
||||
This has been fixed. :gl:`#3801`
|
||||
|
||||
- Improve the speed of the message digest algorithms (MD5, SHA-1,
|
||||
SHA-2) and NSEC3 hashing. :gl:`#3795`
|
||||
|
||||
Known Issues
|
||||
~~~~~~~~~~~~
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -37,25 +37,19 @@ typedef void isc_md_t;
|
|||
*/
|
||||
typedef void isc_md_type_t;
|
||||
|
||||
#define ISC_MD_MD5 isc__md_md5()
|
||||
#define ISC_MD_SHA1 isc__md_sha1()
|
||||
#define ISC_MD_SHA224 isc__md_sha224()
|
||||
#define ISC_MD_SHA256 isc__md_sha256()
|
||||
#define ISC_MD_SHA384 isc__md_sha384()
|
||||
#define ISC_MD_SHA512 isc__md_sha512()
|
||||
extern const isc_md_type_t *isc__md_md5;
|
||||
extern const isc_md_type_t *isc__md_sha1;
|
||||
extern const isc_md_type_t *isc__md_sha224;
|
||||
extern const isc_md_type_t *isc__md_sha256;
|
||||
extern const isc_md_type_t *isc__md_sha384;
|
||||
extern const isc_md_type_t *isc__md_sha512;
|
||||
|
||||
const isc_md_type_t *
|
||||
isc__md_md5(void);
|
||||
const isc_md_type_t *
|
||||
isc__md_sha1(void);
|
||||
const isc_md_type_t *
|
||||
isc__md_sha224(void);
|
||||
const isc_md_type_t *
|
||||
isc__md_sha256(void);
|
||||
const isc_md_type_t *
|
||||
isc__md_sha384(void);
|
||||
const isc_md_type_t *
|
||||
isc__md_sha512(void);
|
||||
#define ISC_MD_MD5 isc__md_md5
|
||||
#define ISC_MD_SHA1 isc__md_sha1
|
||||
#define ISC_MD_SHA224 isc__md_sha224
|
||||
#define ISC_MD_SHA256 isc__md_sha256
|
||||
#define ISC_MD_SHA384 isc__md_sha384
|
||||
#define ISC_MD_SHA512 isc__md_sha512
|
||||
|
||||
#define ISC_MD5_DIGESTLENGTH isc_md_type_get_size(ISC_MD_MD5)
|
||||
#define ISC_MD5_BLOCK_LENGTH isc_md_type_get_block_size(ISC_MD_MD5)
|
||||
|
|
@ -202,3 +196,13 @@ isc_md_type_get_size(const isc_md_type_t *md_type);
|
|||
*/
|
||||
size_t
|
||||
isc_md_type_get_block_size(const isc_md_type_t *md_type);
|
||||
|
||||
/**
|
||||
* Private
|
||||
*/
|
||||
|
||||
void
|
||||
isc__md_initialize(void);
|
||||
|
||||
void
|
||||
isc__md_shutdown(void);
|
||||
|
|
|
|||
|
|
@ -13,64 +13,154 @@
|
|||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <openssl/opensslv.h>
|
||||
|
||||
#include <isc/iterated_hash.h>
|
||||
#include <isc/md.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000
|
||||
|
||||
#include <openssl/sha.h>
|
||||
|
||||
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) {
|
||||
isc_md_t *md;
|
||||
isc_result_t result;
|
||||
REQUIRE(out != NULL);
|
||||
|
||||
int n = 0;
|
||||
unsigned int outlength = 0;
|
||||
size_t len;
|
||||
const unsigned char *buf;
|
||||
|
||||
REQUIRE(out != NULL);
|
||||
SHA_CTX ctx;
|
||||
|
||||
if (hashalg != 1) {
|
||||
return (0);
|
||||
}
|
||||
|
||||
if ((md = isc_md_new()) == NULL) {
|
||||
buf = in;
|
||||
len = inlength;
|
||||
|
||||
do {
|
||||
if (SHA1_Init(&ctx) != 1) {
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (SHA1_Update(&ctx, buf, len) != 1) {
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (SHA1_Update(&ctx, salt, saltlength) != 1) {
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (SHA1_Final(out, &ctx) != 1) {
|
||||
return (0);
|
||||
}
|
||||
|
||||
buf = out;
|
||||
len = SHA_DIGEST_LENGTH;
|
||||
} while (n++ < iterations);
|
||||
|
||||
return (SHA_DIGEST_LENGTH);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (hashalg != 1) {
|
||||
return (0);
|
||||
}
|
||||
|
||||
len = inlength;
|
||||
buf = in;
|
||||
len = inlength;
|
||||
do {
|
||||
result = isc_md_init(md, ISC_MD_SHA1);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto md_fail;
|
||||
if (EVP_MD_CTX_copy_ex(mdctx, basectx) != 1) {
|
||||
goto fail;
|
||||
}
|
||||
result = isc_md_update(md, buf, len);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto md_fail;
|
||||
|
||||
if (EVP_DigestUpdate(mdctx, buf, len) != 1) {
|
||||
goto fail;
|
||||
}
|
||||
result = isc_md_update(md, salt, saltlength);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto md_fail;
|
||||
|
||||
if (EVP_DigestUpdate(mdctx, salt, saltlength) != 1) {
|
||||
goto fail;
|
||||
}
|
||||
result = isc_md_final(md, out, &outlength);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto md_fail;
|
||||
}
|
||||
result = isc_md_reset(md);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto md_fail;
|
||||
|
||||
if (EVP_DigestFinal_ex(mdctx, out, &outlength) != 1) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
buf = out;
|
||||
len = outlength;
|
||||
} while (n++ < iterations);
|
||||
|
||||
isc_md_free(md);
|
||||
|
||||
return (outlength);
|
||||
md_fail:
|
||||
isc_md_free(md);
|
||||
|
||||
fail:
|
||||
return (0);
|
||||
}
|
||||
#undef RETERR
|
||||
|
||||
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 */
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@
|
|||
/*! \file */
|
||||
|
||||
#include <isc/bind9.h>
|
||||
#include <isc/iterated_hash.h>
|
||||
#include <isc/md.h>
|
||||
#include <isc/mem.h>
|
||||
#include <isc/os.h>
|
||||
#include <isc/tls.h>
|
||||
|
|
@ -49,11 +51,15 @@ isc__initialize(void) {
|
|||
isc__trampoline_initialize();
|
||||
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();
|
||||
isc__trampoline_shutdown();
|
||||
|
|
|
|||
60
lib/isc/md.c
60
lib/isc/md.c
|
|
@ -164,12 +164,56 @@ end:
|
|||
return (res);
|
||||
}
|
||||
|
||||
#define md_register_algorithm(alg) \
|
||||
const isc_md_type_t *isc__md_##alg(void) { return (EVP_##alg()); }
|
||||
#ifndef UNIT_TESTING
|
||||
const isc_md_type_t *isc__md_md5 = NULL;
|
||||
const isc_md_type_t *isc__md_sha1 = NULL;
|
||||
const isc_md_type_t *isc__md_sha224 = NULL;
|
||||
const isc_md_type_t *isc__md_sha256 = NULL;
|
||||
const isc_md_type_t *isc__md_sha384 = NULL;
|
||||
const isc_md_type_t *isc__md_sha512 = NULL;
|
||||
|
||||
md_register_algorithm(md5);
|
||||
md_register_algorithm(sha1);
|
||||
md_register_algorithm(sha224);
|
||||
md_register_algorithm(sha256);
|
||||
md_register_algorithm(sha384);
|
||||
md_register_algorithm(sha512);
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
#define md_register_algorithm(alg, algname) \
|
||||
{ \
|
||||
REQUIRE(isc__md_##alg == NULL); \
|
||||
isc__md_##alg = EVP_MD_fetch(NULL, algname, NULL); \
|
||||
RUNTIME_CHECK(isc__md_##alg != NULL); \
|
||||
}
|
||||
|
||||
#define md_unregister_algorithm(alg) \
|
||||
{ \
|
||||
REQUIRE(isc__md_##alg != NULL); \
|
||||
EVP_MD_free(*(isc_md_type_t **)&isc__md_##alg); \
|
||||
isc__md_##alg = NULL; \
|
||||
}
|
||||
|
||||
#else
|
||||
#define md_register_algorithm(alg, algname) \
|
||||
{ \
|
||||
isc__md_##alg = EVP_##alg(); \
|
||||
RUNTIME_CHECK(isc__md_##alg != NULL); \
|
||||
}
|
||||
#define md_unregister_algorithm(alg)
|
||||
#endif
|
||||
|
||||
void
|
||||
isc__md_initialize(void) {
|
||||
md_register_algorithm(md5, "MD5");
|
||||
md_register_algorithm(sha1, "SHA1");
|
||||
md_register_algorithm(sha224, "SHA224");
|
||||
md_register_algorithm(sha256, "SHA256");
|
||||
md_register_algorithm(sha384, "SHA384");
|
||||
md_register_algorithm(sha512, "SHA512");
|
||||
}
|
||||
|
||||
void
|
||||
isc__md_shutdown(void) {
|
||||
md_unregister_algorithm(sha512);
|
||||
md_unregister_algorithm(sha384);
|
||||
md_unregister_algorithm(sha256);
|
||||
md_unregister_algorithm(sha224);
|
||||
md_unregister_algorithm(sha1);
|
||||
md_unregister_algorithm(md5);
|
||||
}
|
||||
|
||||
#endif /* UNIT_TESTING */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
1
tests/bench/.gitignore
vendored
1
tests/bench/.gitignore
vendored
|
|
@ -1,4 +1,5 @@
|
|||
/ascii
|
||||
/compress
|
||||
/iterated_hash
|
||||
/dns_name_fromwire
|
||||
/siphash
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ LDADD += \
|
|||
noinst_PROGRAMS = \
|
||||
ascii \
|
||||
compress \
|
||||
iterated_hash \
|
||||
dns_name_fromwire \
|
||||
siphash
|
||||
|
||||
|
|
|
|||
76
tests/bench/iterated_hash.c
Normal file
76
tests/bench/iterated_hash.c
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* See the COPYRIGHT file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <isc/iterated_hash.h>
|
||||
#include <isc/random.h>
|
||||
#include <isc/time.h>
|
||||
|
||||
#include <dns/name.h>
|
||||
|
||||
static void
|
||||
time_it(const int count, const int iterations, const unsigned char *salt,
|
||||
const int saltlen, const unsigned char *in, const int inlen) {
|
||||
uint8_t out[NSEC3_MAX_HASH_LENGTH] = { 0 };
|
||||
isc_time_t start, finish;
|
||||
|
||||
printf("%d iterations, %d salt length, %d input length: ", iterations,
|
||||
saltlen, inlen);
|
||||
fflush(stdout);
|
||||
|
||||
isc_time_now_hires(&start);
|
||||
|
||||
int i = 0;
|
||||
while (i++ < count) {
|
||||
isc_iterated_hash(out, 1, iterations, salt, saltlen, in, inlen);
|
||||
}
|
||||
|
||||
isc_time_now_hires(&finish);
|
||||
|
||||
uint64_t microseconds = isc_time_microdiff(&finish, &start);
|
||||
printf("%0.2f us per iterated_hash()\n", (double)microseconds / count);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
int
|
||||
main(void) {
|
||||
uint8_t salt[DNS_NAME_MAXWIRE];
|
||||
uint8_t in[DNS_NAME_MAXWIRE];
|
||||
size_t saltlen = sizeof(salt);
|
||||
size_t inlen = sizeof(in);
|
||||
|
||||
isc_random_buf(salt, saltlen);
|
||||
isc_random_buf(in, inlen);
|
||||
|
||||
time_it(10000, 150, salt, saltlen, in, inlen);
|
||||
time_it(10000, 15, salt, saltlen, in, inlen);
|
||||
time_it(10000, 0, salt, saltlen, in, inlen);
|
||||
|
||||
saltlen = 32;
|
||||
inlen = 32;
|
||||
|
||||
time_it(10000, 150, salt, 32, in, inlen);
|
||||
time_it(10000, 15, salt, 32, in, inlen);
|
||||
time_it(10000, 0, salt, saltlen, in, inlen);
|
||||
|
||||
saltlen = 0;
|
||||
inlen = 1;
|
||||
|
||||
time_it(10000, 150, salt, 32, in, inlen);
|
||||
time_it(10000, 15, salt, 32, in, inlen);
|
||||
time_it(10000, 0, salt, saltlen, in, inlen);
|
||||
}
|
||||
Loading…
Reference in a new issue