diff options
author | Pauli <pauli@openssl.org> | 2023-10-06 01:26:23 +0200 |
---|---|---|
committer | Matt Caswell <matt@openssl.org> | 2023-10-24 15:32:24 +0200 |
commit | f3a7e6c057b5054aa05710f3d528b92e3e885268 (patch) | |
tree | 8bb8924b1c0813932b1f1560cb816c21583f336d /crypto/evp | |
parent | Fix Coverity 1547856: memset() uses only the lowest byte of c (diff) | |
download | openssl-f3a7e6c057b5054aa05710f3d528b92e3e885268.tar.xz openssl-f3a7e6c057b5054aa05710f3d528b92e3e885268.zip |
evp: process key length and iv length early if present
evp_cipher_init_internal() takes a params array argument and this is processed
late in the initialisation process for some ciphers (AEAD ones).
This means that changing the IV length as a parameter will either truncate the
IV (very bad if SP 800-38d section 8.2.1 is used) or grab extra uninitialised
bytes.
Truncation is very bad if SP 800-38d section 8.2.1 is being used to
contruct a deterministic IV. This leads to an instant loss of confidentiality.
Grabbing extra bytes isn't so serious, it will most likely result in a bad
decryption.
Problem reported by Tony Battersby of Cybernetics.com but earlier discovered
and raised as issue #19822.
Fixes CVE-2023-5363
Fixes #19822
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Hugo Landau <hlandau@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
Diffstat (limited to 'crypto/evp')
-rw-r--r-- | crypto/evp/evp_enc.c | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/crypto/evp/evp_enc.c b/crypto/evp/evp_enc.c index e1d3eeef64..e9faf31057 100644 --- a/crypto/evp/evp_enc.c +++ b/crypto/evp/evp_enc.c @@ -233,6 +233,42 @@ static int evp_cipher_init_internal(EVP_CIPHER_CTX *ctx, return 0; } +#ifndef FIPS_MODULE + /* + * Fix for CVE-2023-5363 + * Passing in a size as part of the init call takes effect late + * so, force such to occur before the initialisation. + * + * The FIPS provider's internal library context is used in a manner + * such that this is not an issue. + */ + if (params != NULL) { + OSSL_PARAM param_lens[3] = { OSSL_PARAM_END, OSSL_PARAM_END, + OSSL_PARAM_END }; + OSSL_PARAM *q = param_lens; + const OSSL_PARAM *p; + + p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN); + if (p != NULL) + memcpy(q++, p, sizeof(*q)); + + /* + * Note that OSSL_CIPHER_PARAM_AEAD_IVLEN is a synomym for + * OSSL_CIPHER_PARAM_IVLEN so both are covered here. + */ + p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_IVLEN); + if (p != NULL) + memcpy(q++, p, sizeof(*q)); + + if (q != param_lens) { + if (!EVP_CIPHER_CTX_set_params(ctx, param_lens)) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_LENGTH); + return 0; + } + } + } +#endif + if (enc) { if (ctx->cipher->einit == NULL) { ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); |