diff options
author | Matt Caswell <matt@openssl.org> | 2019-11-14 16:05:19 +0000 |
---|---|---|
committer | Matt Caswell <matt@openssl.org> | 2019-11-19 13:33:54 +0000 |
commit | d23adad1133c5445cd834cab0e598d7817effc6b (patch) | |
tree | dc8c9bc7b108d453097a85898541d1bcc225df0c /crypto/evp/evp_enc.c | |
parent | dbca036435e210348e73d43a8dad14f0de6a9a18 (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/evp/evp_enc.c')
-rw-r--r-- | crypto/evp/evp_enc.c | 28 |
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) |