summaryrefslogtreecommitdiffstats
path: root/crypto/evp
diff options
context:
space:
mode:
authorPauli <pauli@openssl.org>2023-10-06 01:26:23 +0200
committerMatt Caswell <matt@openssl.org>2023-10-24 15:32:24 +0200
commitf3a7e6c057b5054aa05710f3d528b92e3e885268 (patch)
tree8bb8924b1c0813932b1f1560cb816c21583f336d /crypto/evp
parentFix Coverity 1547856: memset() uses only the lowest byte of c (diff)
downloadopenssl-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.c36
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);