summaryrefslogtreecommitdiffstats
path: root/crypto/evp/digest.c
diff options
context:
space:
mode:
authorMatt Caswell <matt@openssl.org>2020-12-22 11:36:30 +0000
committerDmitry Belyavskiy <beldmit@gmail.com>2020-12-23 21:12:18 +0100
commit38f7931429859a3bd07725dbc451c0b4cac26a10 (patch)
tree91e461bb329371007d84763525632235a7bd4d06 /crypto/evp/digest.c
parentae69da05a7749e21c7526831173405e3570917b2 (diff)
Cache Digest constants
EVP_CIPHER already caches certain constants so that we don't have to query the provider every time. We do the same thing with EVP_MD constants. Without this we can get performance issues, e.g. running "speed" with small blocks of data to digest can spend a long time in EVP_MD_size(), which should be quick. Partialy fixes #13578 Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com> (Merged from https://github.com/openssl/openssl/pull/13730)
Diffstat (limited to 'crypto/evp/digest.c')
-rw-r--r--crypto/evp/digest.c29
1 files changed, 29 insertions, 0 deletions
diff --git a/crypto/evp/digest.c b/crypto/evp/digest.c
index 1d16c52060..46f4d201d9 100644
--- a/crypto/evp/digest.c
+++ b/crypto/evp/digest.c
@@ -827,6 +827,29 @@ static void set_legacy_nid(const char *name, void *vlegacy_nid)
}
#endif
+static int evp_md_cache_constants(EVP_MD *md)
+{
+ int ok;
+ size_t blksz = 0;
+ size_t mdsize = 0;
+ unsigned long flags = 0;
+ OSSL_PARAM params[4];
+
+ params[0] = OSSL_PARAM_construct_size_t(OSSL_DIGEST_PARAM_BLOCK_SIZE, &blksz);
+ params[1] = OSSL_PARAM_construct_size_t(OSSL_DIGEST_PARAM_SIZE, &mdsize);
+ params[2] = OSSL_PARAM_construct_ulong(OSSL_DIGEST_PARAM_FLAGS, &flags);
+ params[3] = OSSL_PARAM_construct_end();
+ ok = evp_do_md_getparams(md, params);
+ if (mdsize > INT_MAX || blksz > INT_MAX)
+ ok = 0;
+ if (ok) {
+ md->block_size = (int)blksz;
+ md->md_size = (int)mdsize;
+ md->flags = flags;
+ }
+ return ok;
+}
+
static void *evp_md_from_dispatch(int name_id,
const OSSL_DISPATCH *fns,
OSSL_PROVIDER *prov)
@@ -938,6 +961,12 @@ static void *evp_md_from_dispatch(int name_id,
if (prov != NULL)
ossl_provider_up_ref(prov);
+ if (!evp_md_cache_constants(md)) {
+ EVP_MD_free(md);
+ ERR_raise(ERR_LIB_EVP, EVP_R_CACHE_CONSTANTS_FAILED);
+ md = NULL;
+ }
+
return md;
}