From 7e38b6bee6f61be1113714cacfc3a45baee914a3 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Fri, 25 Sep 2020 11:03:58 +0200 Subject: [PATCH] Test 2 part GCM data and EVP context re-use --- tests/api.c | 21 ++++++- wolfcrypt/src/evp.c | 134 ++++++++++++++++++------------------------ wolfssl/openssl/evp.h | 4 +- 3 files changed, 77 insertions(+), 82 deletions(-) diff --git a/tests/api.c b/tests/api.c index 546b6ab04..b5f7042ad 100644 --- a/tests/api.c +++ b/tests/api.c @@ -35362,25 +35362,40 @@ static void test_wolfssl_EVP_aes_gcm_AAD_2_parts(void) printf(testingFmt, "wolfssl_EVP_aes_gcm_AAD_2_parts"); - /* Send AAD in 1 part */ + /* Send AAD and data in 1 part */ AssertNotNull(ctx = EVP_CIPHER_CTX_new()); AssertIntEQ(EVP_EncryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL), 1); AssertIntEQ(EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv), 1); AssertIntEQ(EVP_EncryptUpdate(ctx, NULL, &len, aad, sizeof(aad)), 1); AssertIntEQ(EVP_EncryptUpdate(ctx, out1Part, &len, cleartext, sizeof(cleartext)), 1); AssertIntEQ(EVP_EncryptFinal_ex(ctx, out1Part, &len), 1); + AssertIntEQ(len, sizeof(cleartext)); AssertIntEQ(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, 16, outTag1Part), 1); EVP_CIPHER_CTX_free(ctx); - /* Send AAD in 2 parts */ + /* Send AAD and data in 2 parts */ AssertNotNull(ctx = EVP_CIPHER_CTX_new()); AssertIntEQ(EVP_EncryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL), 1); AssertIntEQ(EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv), 1); AssertIntEQ(EVP_EncryptUpdate(ctx, NULL, &len, aad, 1), 1); AssertIntEQ(EVP_EncryptUpdate(ctx, NULL, &len, aad + 1, sizeof(aad) - 1), 1); - AssertIntEQ(EVP_EncryptUpdate(ctx, out2Part, &len, cleartext, sizeof(cleartext)), 1); + AssertIntEQ(EVP_EncryptUpdate(ctx, out2Part, &len, cleartext, 1), 1); + AssertIntEQ(EVP_EncryptUpdate(ctx, out2Part, &len, cleartext + 1, + sizeof(cleartext) - 1), 1); AssertIntEQ(EVP_EncryptFinal_ex(ctx, out2Part, &len), 1); + AssertIntEQ(len, sizeof(cleartext)); AssertIntEQ(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, 16, outTag2Part), 1); + + AssertIntEQ(XMEMCMP(out1Part, out2Part, sizeof(out1Part)), 0); + AssertIntEQ(XMEMCMP(outTag1Part, outTag2Part, sizeof(outTag1Part)), 0); + + /* Test AAD re-use */ + AssertIntEQ(EVP_EncryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL), 1); + AssertIntEQ(EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv), 1); + AssertIntEQ(EVP_EncryptUpdate(ctx, out1Part, &len, cleartext, sizeof(cleartext)), 1); + AssertIntEQ(EVP_EncryptFinal_ex(ctx, out1Part, &len), 1); + AssertIntEQ(len, sizeof(cleartext)); + AssertIntEQ(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, 16, outTag1Part), 1); EVP_CIPHER_CTX_free(ctx); AssertIntEQ(XMEMCMP(out1Part, out2Part, sizeof(out1Part)), 0); diff --git a/wolfcrypt/src/evp.c b/wolfcrypt/src/evp.c index b48801340..262f256b5 100644 --- a/wolfcrypt/src/evp.c +++ b/wolfcrypt/src/evp.c @@ -572,72 +572,26 @@ static int wolfSSL_EVP_CipherUpdate_GCM(WOLFSSL_EVP_CIPHER_CTX *ctx, int ret = 0; *outl = inl; - if (ctx->enc) { - if (out) { - if (ctx->gcmAuthIn) { - /* authenticated, non-confidential data */ - XMEMSET(ctx->authTag, 0, ctx->authTagSz); - ret = wc_AesGcmEncrypt(&ctx->cipher.aes, NULL, NULL, 0, - ctx->iv, ctx->ivSz, ctx->authTag, ctx->authTagSz, - ctx->gcmAuthIn, ctx->gcmAuthInSz); - /* Reset partial authTag error for AAD*/ - if (ret == AES_GCM_AUTH_E) - ret = 0; - if (ret == 0) { - XFREE(ctx->gcmAuthIn, NULL, DYNAMIC_TYPE_OPENSSL); - ctx->gcmAuthIn = NULL; - ctx->gcmAuthInSz = 0; - } + if (out) { + /* Buffer input for one-shot API */ + if (ret == 0) { + byte* tmp; + tmp = (byte*)XREALLOC(ctx->gcmBuffer, + ctx->gcmBufferLen + inl, NULL, + DYNAMIC_TYPE_OPENSSL); + if (tmp) { + XMEMCPY(tmp + ctx->gcmBufferLen, in, inl); + ctx->gcmBufferLen += inl; + ctx->gcmBuffer = tmp; + *outl = 0; + } + else { + ret = MEMORY_E; } - - /* encrypt confidential data*/ - if (ret == 0) - ret = wc_AesGcmEncrypt(&ctx->cipher.aes, out, in, inl, - ctx->iv, ctx->ivSz, ctx->authTag, ctx->authTagSz, - NULL, 0); - } - else { - ret = wolfSSL_EVP_CipherUpdate_GCM_AAD(ctx, in, inl); } } else { - if (out) { - byte* tmp; - - if (ctx->gcmAuthIn) { - /* authenticated, non-confidential data*/ - ret = wc_AesGcmDecrypt(&ctx->cipher.aes, NULL, NULL, 0, - ctx->iv, ctx->ivSz, - ctx->authTag, ctx->authTagSz, - ctx->gcmAuthIn, ctx->gcmAuthInSz); - /* Reset partial authTag error for AAD*/ - if (ret == AES_GCM_AUTH_E) - ret = 0; - if (ret == 0) { - XFREE(ctx->gcmAuthIn, NULL, DYNAMIC_TYPE_OPENSSL); - ctx->gcmAuthIn = NULL; - ctx->gcmAuthInSz = 0; - } - } - - if (ret == 0) { - tmp = (byte*)XREALLOC(ctx->gcmDecryptBuffer, - ctx->gcmDecryptBufferLen + inl, NULL, - DYNAMIC_TYPE_OPENSSL); - if (tmp) { - XMEMCPY(tmp + ctx->gcmDecryptBufferLen, in, inl); - ctx->gcmDecryptBufferLen += inl; - ctx->gcmDecryptBuffer = tmp; - *outl = 0; - } - else { - ret = MEMORY_E; - } - } - } - else { - ret = wolfSSL_EVP_CipherUpdate_GCM_AAD(ctx, in, inl); - } + ret = wolfSSL_EVP_CipherUpdate_GCM_AAD(ctx, in, inl); } if (ret != 0) { @@ -810,25 +764,51 @@ int wolfSSL_EVP_CipherFinal(WOLFSSL_EVP_CIPHER_CTX *ctx, case AES_128_GCM_TYPE: case AES_192_GCM_TYPE: case AES_256_GCM_TYPE: - if (!ctx->enc && ctx->gcmDecryptBuffer && - ctx->gcmDecryptBufferLen > 0) { - /* decrypt confidential data*/ - ret = wc_AesGcmDecrypt(&ctx->cipher.aes, out, - ctx->gcmDecryptBuffer, ctx->gcmDecryptBufferLen, - ctx->iv, ctx->ivSz, ctx->authTag, ctx->authTagSz, - NULL, 0); + if (ctx->gcmBuffer && + ctx->gcmBufferLen > 0) { + if (ctx->gcmAuthIn) { + /* authenticated, non-confidential data*/ + if (ctx->enc) { + XMEMSET(ctx->authTag, 0, ctx->authTagSz); + ret = wc_AesGcmEncrypt(&ctx->cipher.aes, NULL, NULL, 0, + ctx->iv, ctx->ivSz, ctx->authTag, ctx->authTagSz, + ctx->gcmAuthIn, ctx->gcmAuthInSz); + } + else { + ret = wc_AesGcmDecrypt(&ctx->cipher.aes, NULL, NULL, 0, + ctx->iv, ctx->ivSz, ctx->authTag, ctx->authTagSz, + ctx->gcmAuthIn, ctx->gcmAuthInSz); + /* Reset partial authTag error for AAD*/ + if (ret == AES_GCM_AUTH_E) + ret = 0; + } + } + + if (ctx->enc) + /* encrypt confidential data*/ + ret = wc_AesGcmEncrypt(&ctx->cipher.aes, out, + ctx->gcmBuffer, ctx->gcmBufferLen, + ctx->iv, ctx->ivSz, ctx->authTag, ctx->authTagSz, + NULL, 0); + else + /* decrypt confidential data*/ + ret = wc_AesGcmDecrypt(&ctx->cipher.aes, out, + ctx->gcmBuffer, ctx->gcmBufferLen, + ctx->iv, ctx->ivSz, ctx->authTag, ctx->authTagSz, + NULL, 0); + if (ret == 0) { ret = WOLFSSL_SUCCESS; - *outl = ctx->gcmDecryptBufferLen; + *outl = ctx->gcmBufferLen; } else { ret = WOLFSSL_FAILURE; *outl = 0; } - XFREE(ctx->gcmDecryptBuffer, NULL, DYNAMIC_TYPE_OPENSSL); - ctx->gcmDecryptBuffer = NULL; - ctx->gcmDecryptBufferLen = 0; + XFREE(ctx->gcmBuffer, NULL, DYNAMIC_TYPE_OPENSSL); + ctx->gcmBuffer = NULL; + ctx->gcmBufferLen = 0; } else { *outl = 0; @@ -4156,11 +4136,11 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) ctx->cipherType = WOLFSSL_EVP_CIPH_TYPE_INIT; /* not yet initialized */ ctx->keyLen = 0; #ifdef HAVE_AESGCM - if (ctx->gcmDecryptBuffer) { - XFREE(ctx->gcmDecryptBuffer, NULL, DYNAMIC_TYPE_OPENSSL); - ctx->gcmDecryptBuffer = NULL; + if (ctx->gcmBuffer) { + XFREE(ctx->gcmBuffer, NULL, DYNAMIC_TYPE_OPENSSL); + ctx->gcmBuffer = NULL; } - ctx->gcmDecryptBufferLen = 0; + ctx->gcmBufferLen = 0; if (ctx->gcmAuthIn) { XFREE(ctx->gcmAuthIn, NULL, DYNAMIC_TYPE_OPENSSL); ctx->gcmAuthIn = NULL; diff --git a/wolfssl/openssl/evp.h b/wolfssl/openssl/evp.h index e9dd79c5b..fa1065a9d 100644 --- a/wolfssl/openssl/evp.h +++ b/wolfssl/openssl/evp.h @@ -354,8 +354,8 @@ struct WOLFSSL_EVP_CIPHER_CTX { #define HAVE_WOLFSSL_EVP_CIPHER_CTX_IV int ivSz; #ifdef HAVE_AESGCM - byte* gcmDecryptBuffer; - int gcmDecryptBufferLen; + byte* gcmBuffer; + int gcmBufferLen; ALIGN16 unsigned char authTag[AES_BLOCK_SIZE]; int authTagSz; byte* gcmAuthIn;