diff options
author | Shane Lontis <shane.lontis@oracle.com> | 2020-07-22 02:40:55 +0200 |
---|---|---|
committer | Shane Lontis <shane.lontis@oracle.com> | 2020-07-22 02:40:55 +0200 |
commit | 90409da6a520812b0266fcb1303175406dea81fe (patch) | |
tree | a9d4fcbae513c3daaa7dabb9dce681e30465bd90 /crypto/modes/siv128.c | |
parent | Avoid errors with a priori inapplicable protocol bounds (diff) | |
download | openssl-90409da6a520812b0266fcb1303175406dea81fe.tar.xz openssl-90409da6a520812b0266fcb1303175406dea81fe.zip |
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 <tmraz@fedoraproject.org>
(Merged from https://github.com/openssl/openssl/pull/12413)
Diffstat (limited to 'crypto/modes/siv128.c')
-rw-r--r-- | crypto/modes/siv128.c | 24 |
1 files changed, 19 insertions, 5 deletions
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; } |