From db1e9877fdabaf88494e2314cd527f09d5790281 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 1 Sep 2023 15:32:46 -0400 Subject: [PATCH] Return the correct value in EVP_CIPHER_CTX_iv_length after EVP_CTRL_AEAD_SET_IVLEN Previously, EVP_CIPHER_CTX_iv_length always returned the cipher's fixed IV length. Now, after modification with EVP_CTRL_AEAD_SET_IVLEN, it returns the correct value. Fixed: 626 Change-Id: Id98c929439850b3e83a80111f35aabebc6e5d47a Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/62907 Commit-Queue: Bob Beck Reviewed-by: Bob Beck --- crypto/cipher_extra/cipher_test.cc | 1 + crypto/fipsmodule/cipher/cipher.c | 10 ++++++++++ crypto/fipsmodule/cipher/e_aes.c | 4 ++++ include/openssl/cipher.h | 1 + 4 files changed, 16 insertions(+) diff --git a/crypto/cipher_extra/cipher_test.cc b/crypto/cipher_extra/cipher_test.cc index 6101ef9661..9375bc195e 100644 --- a/crypto/cipher_extra/cipher_test.cc +++ b/crypto/cipher_extra/cipher_test.cc @@ -211,6 +211,7 @@ static void TestCipherAPI(const EVP_CIPHER *cipher, Operation op, bool padding, ASSERT_LE(iv.size(), size_t{INT_MAX}); ASSERT_TRUE(EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_AEAD_SET_IVLEN, static_cast(iv.size()), 0)); + ASSERT_EQ(EVP_CIPHER_CTX_iv_length(ctx.get()), iv.size()); } else { ASSERT_EQ(iv.size(), EVP_CIPHER_CTX_iv_length(ctx.get())); } diff --git a/crypto/fipsmodule/cipher/cipher.c b/crypto/fipsmodule/cipher/cipher.c index 18b5e0a5e9..bff7996a5d 100644 --- a/crypto/fipsmodule/cipher/cipher.c +++ b/crypto/fipsmodule/cipher/cipher.c @@ -586,6 +586,16 @@ unsigned EVP_CIPHER_CTX_key_length(const EVP_CIPHER_CTX *ctx) { } unsigned EVP_CIPHER_CTX_iv_length(const EVP_CIPHER_CTX *ctx) { + if (EVP_CIPHER_mode(ctx->cipher) == EVP_CIPH_GCM_MODE) { + int length; + int res = EVP_CIPHER_CTX_ctrl((EVP_CIPHER_CTX *)ctx, EVP_CTRL_GET_IVLEN, 0, + &length); + // EVP_CIPHER_CTX_ctrl returning an error should be impossible under this + // circumstance. If it somehow did, fallback to the static cipher iv_len. + if (res == 1) { + return length; + } + } return ctx->cipher->iv_len; } diff --git a/crypto/fipsmodule/cipher/e_aes.c b/crypto/fipsmodule/cipher/e_aes.c index 0db77b846b..6d91cc4c31 100644 --- a/crypto/fipsmodule/cipher/e_aes.c +++ b/crypto/fipsmodule/cipher/e_aes.c @@ -454,6 +454,10 @@ static int aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) { gctx->ivlen = arg; return 1; + case EVP_CTRL_GET_IVLEN: + *(int *)ptr = gctx->ivlen; + return 1; + case EVP_CTRL_AEAD_SET_TAG: if (arg <= 0 || arg > 16 || c->encrypt) { return 0; diff --git a/include/openssl/cipher.h b/include/openssl/cipher.h index 310d7c237f..18c1e708a4 100644 --- a/include/openssl/cipher.h +++ b/include/openssl/cipher.h @@ -542,6 +542,7 @@ OPENSSL_EXPORT void EVP_CIPHER_CTX_set_flags(const EVP_CIPHER_CTX *ctx, #define EVP_CTRL_AEAD_SET_MAC_KEY 0x17 // EVP_CTRL_GCM_SET_IV_INV sets the GCM invocation field, decrypt only #define EVP_CTRL_GCM_SET_IV_INV 0x18 +#define EVP_CTRL_GET_IVLEN 0x19 // The following constants are unused. #define EVP_GCM_TLS_FIXED_IV_LEN 4