summaryrefslogtreecommitdiffstats
path: root/crypto/evp
diff options
context:
space:
mode:
authorPauli <pauli@openssl.org>2022-01-27 13:33:36 +1100
committerPauli <pauli@openssl.org>2022-02-07 09:46:16 +1100
commit70f39a487d3f7d976a01e0ee7ae98a82ceeea7a0 (patch)
treed73af15d85194f56614a4a0165e6a6060e3be32b /crypto/evp
parentb30b45b7247d056b569e2b5139f8b503d36e646c (diff)
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)
Diffstat (limited to 'crypto/evp')
-rw-r--r--crypto/evp/evp_enc.c31
-rw-r--r--crypto/evp/evp_lib.c26
2 files changed, 44 insertions, 13 deletions
diff --git a/crypto/evp/evp_enc.c b/crypto/evp/evp_enc.c
index ff315bd922..7ae92df98b 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;
}
@@ -984,7 +984,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;
@@ -997,9 +997,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. */
@@ -1060,6 +1064,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;
@@ -1255,11 +1260,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 8bac09bba0..7e03d03bf6 100644
--- a/crypto/evp/evp_lib.c
+++ b/crypto/evp/evp_lib.c
@@ -647,14 +647,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)