summaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorMatt Caswell <matt@openssl.org>2019-11-14 16:05:19 +0000
committerMatt Caswell <matt@openssl.org>2019-11-19 13:33:54 +0000
commitd23adad1133c5445cd834cab0e598d7817effc6b (patch)
treedc8c9bc7b108d453097a85898541d1bcc225df0c /crypto
parentdbca036435e210348e73d43a8dad14f0de6a9a18 (diff)
EVP_CIPHER_CTX_set_keylen should not succeed if a bad keylen is passed
EVP_CIPHER_CTX_set_keylen() was succeeding even though a bad key length is passed to it. This is because the set_ctx_params() were all accepting this parameter and blindly changing the keylen even though the cipher did not accept a variable key length. Even removing this didn't entirely resolve the issue because set_ctx_params() functions succeed even if passed a parameter they do not recognise. This should fix various issues found by OSSfuzz/Cryptofuzz. Reviewed-by: Shane Lontis <shane.lontis@oracle.com> (Merged from https://github.com/openssl/openssl/pull/10449)
Diffstat (limited to 'crypto')
-rw-r--r--crypto/evp/evp_enc.c28
1 files changed, 21 insertions, 7 deletions
diff --git a/crypto/evp/evp_enc.c b/crypto/evp/evp_enc.c
index 3346e57dae..45e1dc67c2 100644
--- a/crypto/evp/evp_enc.c
+++ b/crypto/evp/evp_enc.c
@@ -1026,17 +1026,31 @@ int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *c, int keylen)
{
- int ok;
- OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
- size_t len = keylen;
+ if (c->cipher->prov != NULL) {
+ int ok;
+ OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
+ size_t len = keylen;
+
+ if (EVP_CIPHER_CTX_key_length(c) == keylen)
+ return 1;
+
+ /* Check the cipher actually understands this parameter */
+ if (OSSL_PARAM_locate_const(EVP_CIPHER_settable_ctx_params(c->cipher),
+ OSSL_CIPHER_PARAM_KEYLEN) == NULL)
+ return 0;
- params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_KEYLEN, &len);
- ok = evp_do_ciph_ctx_setparams(c->cipher, c->provctx, params);
+ params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_KEYLEN, &len);
+ ok = evp_do_ciph_ctx_setparams(c->cipher, c->provctx, params);
- if (ok != EVP_CTRL_RET_UNSUPPORTED)
- return ok;
+ return ok > 0 ? 1 : 0;
+ }
/* TODO(3.0) legacy code follows */
+
+ /*
+ * Note there have never been any built-in ciphers that define this flag
+ * since it was first introduced.
+ */
if (c->cipher->flags & EVP_CIPH_CUSTOM_KEY_LENGTH)
return EVP_CIPHER_CTX_ctrl(c, EVP_CTRL_SET_KEY_LENGTH, keylen, NULL);
if (EVP_CIPHER_CTX_key_length(c) == keylen)