137 lines
4.8 KiB
Diff
137 lines
4.8 KiB
Diff
|
|
From bbbccd795940114cb18722fc6fffe2b25ce3c436 Mon Sep 17 00:00:00 2001
|
||
|
|
From: Pauli <pauli@openssl.org>
|
||
|
|
Date: Thu, 27 Jan 2022 13:33:36 +1100
|
||
|
|
Subject: [PATCH] evp enc: cache cipher key length
|
||
|
|
|
||
|
|
Instead of doing a heavy params based query every time a context is
|
||
|
|
asked for its key length, this value is cached in the context and only
|
||
|
|
queried if it could have been modified.
|
||
|
|
|
||
|
|
Fixes #17064
|
||
|
|
|
||
|
|
Reviewed-by: Tomas Mraz <tomas@openssl.org>
|
||
|
|
(Merged from https://github.com/openssl/openssl/pull/17543)
|
||
|
|
|
||
|
|
(cherry picked from commit 70f39a487d3f7d976a01e0ee7ae98a82ceeea7a0)
|
||
|
|
Reviewed-by: Hugo Landau <hlandau@openssl.org>
|
||
|
|
---
|
||
|
|
crypto/evp/evp_enc.c | 31 ++++++++++++++++++++++++-------
|
||
|
|
crypto/evp/evp_lib.c | 26 ++++++++++++++++++++------
|
||
|
|
2 files changed, 44 insertions(+), 13 deletions(-)
|
||
|
|
|
||
|
|
diff --git a/crypto/evp/evp_enc.c b/crypto/evp/evp_enc.c
|
||
|
|
index 921d24dd3d..a6468f6767 100644
|
||
|
|
--- a/crypto/evp/evp_enc.c
|
||
|
|
+++ b/crypto/evp/evp_enc.c
|
||
|
|
@@ -62,7 +62,7 @@ int EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *ctx)
|
||
|
|
ENGINE_finish(ctx->engine);
|
||
|
|
#endif
|
||
|
|
memset(ctx, 0, sizeof(*ctx));
|
||
|
|
- ctx->iv_len = -1;
|
||
|
|
+ ctx->iv_len = 0;
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
@@ -994,7 +994,7 @@ int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *c, int keylen)
|
||
|
|
if (c->cipher->prov != NULL) {
|
||
|
|
int ok;
|
||
|
|
OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
|
||
|
|
- size_t len = keylen;
|
||
|
|
+ size_t len;
|
||
|
|
|
||
|
|
if (EVP_CIPHER_CTX_get_key_length(c) == keylen)
|
||
|
|
return 1;
|
||
|
|
@@ -1007,9 +1007,13 @@ int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *c, int keylen)
|
||
|
|
}
|
||
|
|
|
||
|
|
params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_KEYLEN, &len);
|
||
|
|
+ if (!OSSL_PARAM_set_int(params, keylen))
|
||
|
|
+ return 0;
|
||
|
|
ok = evp_do_ciph_ctx_setparams(c->cipher, c->algctx, params);
|
||
|
|
-
|
||
|
|
- return ok > 0 ? 1 : 0;
|
||
|
|
+ if (ok <= 0)
|
||
|
|
+ return 0;
|
||
|
|
+ c->key_len = keylen;
|
||
|
|
+ return 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Code below to be removed when legacy support is dropped. */
|
||
|
|
@@ -1070,6 +1074,7 @@ int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)
|
||
|
|
switch (type) {
|
||
|
|
case EVP_CTRL_SET_KEY_LENGTH:
|
||
|
|
params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_KEYLEN, &sz);
|
||
|
|
+ ctx->key_len = -1;
|
||
|
|
break;
|
||
|
|
case EVP_CTRL_RAND_KEY: /* Used by DES */
|
||
|
|
set_params = 0;
|
||
|
|
@@ -1265,11 +1270,23 @@ int EVP_CIPHER_get_params(EVP_CIPHER *cipher, OSSL_PARAM params[])
|
||
|
|
|
||
|
|
int EVP_CIPHER_CTX_set_params(EVP_CIPHER_CTX *ctx, const OSSL_PARAM params[])
|
||
|
|
{
|
||
|
|
+ int r = 0;
|
||
|
|
+ const OSSL_PARAM *p;
|
||
|
|
+
|
||
|
|
if (ctx->cipher != NULL && ctx->cipher->set_ctx_params != NULL) {
|
||
|
|
- ctx->iv_len = -1;
|
||
|
|
- return ctx->cipher->set_ctx_params(ctx->algctx, params);
|
||
|
|
+ r = ctx->cipher->set_ctx_params(ctx->algctx, params);
|
||
|
|
+ if (r > 0) {
|
||
|
|
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN);
|
||
|
|
+ if (p != NULL && !OSSL_PARAM_get_int(p, &ctx->key_len))
|
||
|
|
+ r = 0;
|
||
|
|
+ }
|
||
|
|
+ if (r > 0) {
|
||
|
|
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_IVLEN);
|
||
|
|
+ if (p != NULL && !OSSL_PARAM_get_int(p, &ctx->iv_len))
|
||
|
|
+ r = 0;
|
||
|
|
+ }
|
||
|
|
}
|
||
|
|
- return 0;
|
||
|
|
+ return r;
|
||
|
|
}
|
||
|
|
|
||
|
|
int EVP_CIPHER_CTX_get_params(EVP_CIPHER_CTX *ctx, OSSL_PARAM params[])
|
||
|
|
diff --git a/crypto/evp/evp_lib.c b/crypto/evp/evp_lib.c
|
||
|
|
index d88066d0a2..98bb25655d 100644
|
||
|
|
--- a/crypto/evp/evp_lib.c
|
||
|
|
+++ b/crypto/evp/evp_lib.c
|
||
|
|
@@ -652,14 +652,28 @@ int EVP_CIPHER_get_key_length(const EVP_CIPHER *cipher)
|
||
|
|
|
||
|
|
int EVP_CIPHER_CTX_get_key_length(const EVP_CIPHER_CTX *ctx)
|
||
|
|
{
|
||
|
|
- int ok;
|
||
|
|
- size_t v = ctx->key_len;
|
||
|
|
- OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
|
||
|
|
+ if (ctx->key_len <= 0 && ctx->cipher->prov != NULL) {
|
||
|
|
+ int ok;
|
||
|
|
+ OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
|
||
|
|
+ size_t len;
|
||
|
|
|
||
|
|
- params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_KEYLEN, &v);
|
||
|
|
- ok = evp_do_ciph_ctx_getparams(ctx->cipher, ctx->algctx, params);
|
||
|
|
+ params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_KEYLEN, &len);
|
||
|
|
+ ok = evp_do_ciph_ctx_getparams(ctx->cipher, ctx->algctx, params);
|
||
|
|
+ if (ok <= 0)
|
||
|
|
+ return EVP_CTRL_RET_UNSUPPORTED;
|
||
|
|
|
||
|
|
- return ok != 0 ? (int)v : EVP_CTRL_RET_UNSUPPORTED;
|
||
|
|
+ /*-
|
||
|
|
+ * The if branch should never be taken since EVP_MAX_KEY_LENGTH is
|
||
|
|
+ * less than INT_MAX but best to be safe.
|
||
|
|
+ *
|
||
|
|
+ * Casting away the const is annoying but required here. We need to
|
||
|
|
+ * cache the result for performance reasons.
|
||
|
|
+ */
|
||
|
|
+ if (!OSSL_PARAM_get_int(params, &((EVP_CIPHER_CTX *)ctx)->key_len))
|
||
|
|
+ return -1;
|
||
|
|
+ ((EVP_CIPHER_CTX *)ctx)->key_len = (int)len;
|
||
|
|
+ }
|
||
|
|
+ return ctx->key_len;
|
||
|
|
}
|
||
|
|
|
||
|
|
int EVP_CIPHER_get_nid(const EVP_CIPHER *cipher)
|
||
|
|
--
|
||
|
|
2.33.0
|
||
|
|
|