From 90409da6a520812b0266fcb1303175406dea81fe Mon Sep 17 00:00:00 2001 From: Shane Lontis Date: Wed, 22 Jul 2020 10:40:55 +1000 Subject: Fix provider cipher reinit issue Fixes #12405 Fixes #12377 Calling Init()/Update() and then Init()/Update() again gave a different result when using the same key and iv. Cipher modes that were using ctx->num were not resetting this value, this includes OFB, CFB & CTR. The fix is to reset this value during the ciphers einit() and dinit() methods. Most ciphers go thru a generic method so one line fixes most cases. Add test for calling EVP_EncryptInit()/EVP_EncryptUpdate() multiple times for all ciphers. Ciphers should return the same value for both updates. DES3-WRAP does not since it uses a random in the update. CCM modes currently also fail on the second update (This also happens in 1_1_1). Fix memory leak in AES_OCB cipher if EVP_EncryptInit is called multiple times. Fix AES_SIV cipher dup_ctx and init. Calling EVP_CIPHER_init multiple times resulted in a memory leak in the siv. Fixing this leak also showed that the dup ctx was not working for siv mode. Note: aes_siv_cleanup() can not be used by aes_siv_dupctx() as it clears data that is required for the decrypt (e.g the tag). Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/12413) --- crypto/evp/e_aes.c | 2 +- crypto/modes/siv128.c | 24 +++++++++++++++++++----- 2 files changed, 20 insertions(+), 6 deletions(-) (limited to 'crypto') diff --git a/crypto/evp/e_aes.c b/crypto/evp/e_aes.c index 05be21901d..c037090695 100644 --- a/crypto/evp/e_aes.c +++ b/crypto/evp/e_aes.c @@ -4061,7 +4061,7 @@ static int aes_siv_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, /* klen is the length of the underlying cipher, not the input key, which should be twice as long */ - return CRYPTO_siv128_init(sctx, key, klen, cbc, ctr); + return CRYPTO_siv128_init(sctx, key, klen, cbc, ctr, NULL, NULL); } #define aesni_siv_cipher aes_siv_cipher diff --git a/crypto/modes/siv128.c b/crypto/modes/siv128.c index d3655674b4..27e29c3cc6 100644 --- a/crypto/modes/siv128.c +++ b/crypto/modes/siv128.c @@ -140,13 +140,15 @@ __owur static ossl_inline int siv128_do_encrypt(EVP_CIPHER_CTX *ctx, unsigned ch /* * Create a new SIV128_CONTEXT */ -SIV128_CONTEXT *CRYPTO_siv128_new(const unsigned char *key, int klen, EVP_CIPHER* cbc, EVP_CIPHER* ctr) +SIV128_CONTEXT *CRYPTO_siv128_new(const unsigned char *key, int klen, + EVP_CIPHER *cbc, EVP_CIPHER *ctr, + OPENSSL_CTX *libctx, const char *propq) { SIV128_CONTEXT *ctx; int ret; if ((ctx = OPENSSL_malloc(sizeof(*ctx))) != NULL) { - ret = CRYPTO_siv128_init(ctx, key, klen, cbc, ctr); + ret = CRYPTO_siv128_init(ctx, key, klen, cbc, ctr, libctx, propq); if (ret) return ctx; OPENSSL_free(ctx); @@ -159,7 +161,8 @@ SIV128_CONTEXT *CRYPTO_siv128_new(const unsigned char *key, int klen, EVP_CIPHER * Initialise an existing SIV128_CONTEXT */ int CRYPTO_siv128_init(SIV128_CONTEXT *ctx, const unsigned char *key, int klen, - const EVP_CIPHER* cbc, const EVP_CIPHER* ctr) + const EVP_CIPHER *cbc, const EVP_CIPHER *ctr, + OPENSSL_CTX *libctx, const char *propq) { static const unsigned char zero[SIV_LEN] = { 0 }; size_t out_len = SIV_LEN; @@ -174,14 +177,17 @@ int CRYPTO_siv128_init(SIV128_CONTEXT *ctx, const unsigned char *key, int klen, params[2] = OSSL_PARAM_construct_end(); memset(&ctx->d, 0, sizeof(ctx->d)); + EVP_CIPHER_CTX_free(ctx->cipher_ctx); + EVP_MAC_CTX_free(ctx->mac_ctx_init); + EVP_MAC_free(ctx->mac); + ctx->mac = NULL; ctx->cipher_ctx = NULL; ctx->mac_ctx_init = NULL; if (key == NULL || cbc == NULL || ctr == NULL || (ctx->cipher_ctx = EVP_CIPHER_CTX_new()) == NULL - /* TODO(3.0) library context */ || (ctx->mac = - EVP_MAC_fetch(NULL, OSSL_MAC_NAME_CMAC, NULL)) == NULL + EVP_MAC_fetch(libctx, OSSL_MAC_NAME_CMAC, propq)) == NULL || (ctx->mac_ctx_init = EVP_MAC_CTX_new(ctx->mac)) == NULL || !EVP_MAC_CTX_set_params(ctx->mac_ctx_init, params) || !EVP_EncryptInit_ex(ctx->cipher_ctx, ctr, NULL, key + klen, NULL) @@ -209,12 +215,20 @@ int CRYPTO_siv128_init(SIV128_CONTEXT *ctx, const unsigned char *key, int klen, int CRYPTO_siv128_copy_ctx(SIV128_CONTEXT *dest, SIV128_CONTEXT *src) { memcpy(&dest->d, &src->d, sizeof(src->d)); + if (dest->cipher_ctx == NULL) { + dest->cipher_ctx = EVP_CIPHER_CTX_new(); + if (dest->cipher_ctx == NULL) + return 0; + } if (!EVP_CIPHER_CTX_copy(dest->cipher_ctx, src->cipher_ctx)) return 0; EVP_MAC_CTX_free(dest->mac_ctx_init); dest->mac_ctx_init = EVP_MAC_CTX_dup(src->mac_ctx_init); if (dest->mac_ctx_init == NULL) return 0; + dest->mac = src->mac; + if (dest->mac != NULL) + EVP_MAC_up_ref(dest->mac); return 1; } -- cgit v1.2.1