Merge pull request #2928 from julek-wolfssl/evp-aes-gcm-fix

Fix AES-GCM in EVP layer to have compatiblity with OpenSSL
This commit is contained in:
Sean Parkinson
2020-04-29 09:00:04 +10:00
committed by GitHub
5 changed files with 154 additions and 114 deletions

View File

@@ -440,7 +440,7 @@ AC_ARG_ENABLE([mcast],
# List of open source project defines using our openssl compatibility layer:
# openssh (--enable-openssh) WOLFSSL_OPENSSH
# openvpn (--enable-openvpn)
# openvpn (--enable-openvpn) WOLFSSL_OPENVPN
# nginix (--enable-nginx) WOLFSSL_NGINX
# haproxy (--enable-haproxy) WOLFSSL_HAPROXY
# wpa_supplicant (--enable-wpas) WOLFSSL_WPAS
@@ -3543,7 +3543,7 @@ fi
if test "$ENABLED_OPENVPN" = "yes"
then
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DES_ECB -DHAVE_EX_DATA -DWOLFSSL_KEY_GEN"
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DES_ECB -DHAVE_EX_DATA -DWOLFSSL_KEY_GEN -DWOLFSSL_OPENVPN"
fi

View File

@@ -30844,10 +30844,10 @@ static void test_wolfssl_EVP_aes_gcm(void)
}
AssertIntEQ(1, EVP_DecryptUpdate(&de[i], NULL, &len, aad, aadSz));
AssertIntEQ(1, EVP_CIPHER_CTX_ctrl(&de[i], EVP_CTRL_GCM_SET_TAG, AES_BLOCK_SIZE, tag));
AssertIntEQ(1, EVP_DecryptUpdate(&de[i], decryptedtxt, &len, ciphertxt, ciphertxtSz));
decryptedtxtSz = len;
AssertIntGT(EVP_DecryptFinal_ex(&de[i], decryptedtxt, &len), 0);
AssertIntEQ(1, EVP_CIPHER_CTX_ctrl(&de[i], EVP_CTRL_GCM_SET_TAG, AES_BLOCK_SIZE, tag));
AssertIntEQ(1, EVP_DecryptFinal_ex(&de[i], decryptedtxt, &len));
decryptedtxtSz += len;
AssertIntEQ(ciphertxtSz, decryptedtxtSz);
AssertIntEQ(0, XMEMCMP(plaintxt, decryptedtxt, decryptedtxtSz));
@@ -30857,7 +30857,8 @@ static void test_wolfssl_EVP_aes_gcm(void)
AssertIntEQ(1, EVP_DecryptUpdate(&de[i], NULL, &len, aad, aadSz));
AssertIntEQ(1, EVP_CIPHER_CTX_ctrl(&de[i], EVP_CTRL_GCM_SET_TAG, AES_BLOCK_SIZE, tag));
/* fail due to wrong tag */
AssertIntEQ(0, EVP_DecryptUpdate(&de[i], decryptedtxt, &len, ciphertxt, ciphertxtSz));
AssertIntEQ(1, EVP_DecryptUpdate(&de[i], decryptedtxt, &len, ciphertxt, ciphertxtSz));
AssertIntEQ(0, EVP_DecryptFinal_ex(&de[i], decryptedtxt, &len));
AssertIntEQ(0, len);
}
printf(resultFmt, passed);

View File

@@ -417,47 +417,6 @@ static int evpCipherBlock(WOLFSSL_EVP_CIPHER_CTX *ctx,
ret = wc_AesCbcDecrypt(&ctx->cipher.aes, out, in, inl);
break;
#endif
#if defined(HAVE_AESGCM)
case AES_128_GCM_TYPE:
case AES_192_GCM_TYPE:
case AES_256_GCM_TYPE:
if (ctx->enc) {
if (out){
/* encrypt confidential data*/
ret = wc_AesGcmEncrypt(&ctx->cipher.aes, out, in, inl,
ctx->iv, ctx->ivSz, ctx->authTag, ctx->authTagSz,
NULL, 0);
}
else {
/* authenticated, non-confidential data */
ret = wc_AesGcmEncrypt(&ctx->cipher.aes, NULL, NULL, 0,
ctx->iv, ctx->ivSz, ctx->authTag, ctx->authTagSz,
in, inl);
/* Reset partial authTag error for AAD*/
if (ret == AES_GCM_AUTH_E)
ret = 0;
}
}
else {
if (out){
/* decrypt confidential data*/
ret = wc_AesGcmDecrypt(&ctx->cipher.aes, out, in, inl,
ctx->iv, ctx->ivSz, ctx->authTag, ctx->authTagSz,
NULL, 0);
}
else {
/* authenticated, non-confidential data*/
ret = wc_AesGcmDecrypt(&ctx->cipher.aes, NULL, NULL, 0,
ctx->iv, ctx->ivSz,
ctx->authTag, ctx->authTagSz,
in, inl);
/* Reset partial authTag error for AAD*/
if (ret == AES_GCM_AUTH_E)
ret = 0;
}
}
break;
#endif
#if defined(WOLFSSL_AES_COUNTER)
case AES_128_CTR_TYPE:
case AES_192_CTR_TYPE:
@@ -575,10 +534,60 @@ static int wolfSSL_EVP_CipherUpdate_GCM(WOLFSSL_EVP_CIPHER_CTX *ctx,
unsigned char *out, int *outl,
const unsigned char *in, int inl)
{
/* process blocks */
if (evpCipherBlock(ctx, out, in, inl) == 0)
return WOLFSSL_FAILURE;
int ret = 0;
*outl = inl;
if (ctx->enc) {
if (out) {
/* encrypt confidential data*/
ret = wc_AesGcmEncrypt(&ctx->cipher.aes, out, in, inl,
ctx->iv, ctx->ivSz, ctx->authTag, ctx->authTagSz,
NULL, 0);
}
else {
/* 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,
in, inl);
/* Reset partial authTag error for AAD*/
if (ret == AES_GCM_AUTH_E)
ret = 0;
}
}
else {
if (out) {
byte* tmp;
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 = WOLFSSL_FAILURE;
}
}
else {
/* authenticated, non-confidential data*/
ret = wc_AesGcmDecrypt(&ctx->cipher.aes, NULL, NULL, 0,
ctx->iv, ctx->ivSz,
ctx->authTag, ctx->authTagSz,
in, inl);
/* Reset partial authTag error for AAD*/
if (ret == AES_GCM_AUTH_E)
ret = 0;
}
}
if (ret != 0) {
*outl = 0;
return WOLFSSL_FAILURE;
}
return WOLFSSL_SUCCESS;
}
#endif
@@ -739,22 +748,39 @@ int wolfSSL_EVP_CipherFinal(WOLFSSL_EVP_CIPHER_CTX *ctx,
return WOLFSSL_FAILURE;
WOLFSSL_ENTER("wolfSSL_EVP_CipherFinal");
#if !defined(NO_AES) && defined(HAVE_AESGCM)
switch (ctx->cipherType) {
#if !defined(NO_AES) && defined(HAVE_AESGCM)
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 (ret == 0) {
ret = WOLFSSL_SUCCESS;
*outl = ctx->gcmDecryptBufferLen;
}
else {
ret = WOLFSSL_FAILURE;
*outl = 0;
}
XFREE(ctx->gcmDecryptBuffer, NULL, DYNAMIC_TYPE_OPENSSL);
ctx->gcmDecryptBuffer = NULL;
ctx->gcmDecryptBufferLen = 0;
}
else {
*outl = 0;
}
/* Clear IV, since IV reuse is not recommended for AES GCM. */
XMEMSET(ctx->iv, 0, AES_BLOCK_SIZE);
return WOLFSSL_SUCCESS;
default:
/* fall-through */
break;
}
#endif /* !NO_AES && HAVE_AESGCM */
default:
if (!out)
return WOLFSSL_FAILURE;
@@ -795,7 +821,8 @@ int wolfSSL_EVP_CipherFinal(WOLFSSL_EVP_CIPHER_CTX *ctx,
XMEMCPY(out, ctx->lastBlock, fl);
*outl = fl;
if (ctx->lastUsed == 0 && ctx->bufUsed == 0) {
/* return error in cases where the block length is incorrect */
/* return error in cases where the block length is
* incorrect */
WOLFSSL_MSG("Final Cipher Block bad length");
ret = WOLFSSL_FAILURE;
}
@@ -805,10 +832,14 @@ int wolfSSL_EVP_CipherFinal(WOLFSSL_EVP_CIPHER_CTX *ctx,
}
}
else if (ctx->lastUsed == 0 && ctx->bufUsed == 0) {
/* return error in cases where the block length is incorrect */
/* return error in cases where the block length is
* incorrect */
ret = WOLFSSL_FAILURE;
}
}
break;
}
if (ret == WOLFSSL_SUCCESS) {
/* reset cipher state after final */
wolfSSL_EVP_CipherInit(ctx, NULL, NULL, NULL, -1);
@@ -4040,6 +4071,13 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md)
if (ctx) {
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;
}
ctx->gcmDecryptBufferLen = 0;
#endif
}
return WOLFSSL_SUCCESS;
@@ -4266,7 +4304,6 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md)
ctx->authTagSz = AES_BLOCK_SIZE;
ctx->ivSz = GCM_NONCE_MID_SZ;
XMEMSET(ctx->authTag, 0, ctx->authTagSz);
if (key && wc_AesGcmSetKey(&ctx->cipher.aes, key, ctx->keyLen)) {
WOLFSSL_MSG("wc_AesGcmSetKey() failed");
return WOLFSSL_FAILURE;
@@ -4291,7 +4328,6 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md)
ctx->authTagSz = AES_BLOCK_SIZE;
ctx->ivSz = GCM_NONCE_MID_SZ;
XMEMSET(ctx->authTag, 0, ctx->authTagSz);
if (key && wc_AesGcmSetKey(&ctx->cipher.aes, key, ctx->keyLen)) {
WOLFSSL_MSG("wc_AesGcmSetKey() failed");
return WOLFSSL_FAILURE;
@@ -4316,7 +4352,6 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md)
ctx->authTagSz = AES_BLOCK_SIZE;
ctx->ivSz = GCM_NONCE_MID_SZ;
XMEMSET(ctx->authTag, 0, ctx->authTagSz);
if (key && wc_AesGcmSetKey(&ctx->cipher.aes, key, ctx->keyLen)) {
WOLFSSL_MSG("wc_AesGcmSetKey() failed");
return WOLFSSL_FAILURE;

View File

@@ -353,6 +353,10 @@ struct WOLFSSL_EVP_CIPHER_CTX {
defined(HAVE_AESGCM) || defined (WOLFSSL_AES_XTS)
#define HAVE_WOLFSSL_EVP_CIPHER_CTX_IV
int ivSz;
#ifdef HAVE_AESGCM
byte* gcmDecryptBuffer;
int gcmDecryptBufferLen;
#endif
ALIGN16 unsigned char authTag[AES_BLOCK_SIZE];
int authTagSz;
#endif

View File

@@ -31,10 +31,10 @@
#define OPENSSL_VERSION_NUMBER 0x10100000L
#elif defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) || defined(HAVE_LIGHTY) || \
defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \
defined(WOLFSSL_OPENSSH) || defined(WOLFSSL_QT)
defined(WOLFSSL_OPENSSH) || defined(WOLFSSL_QT) || defined(WOLFSSL_OPENVPN)
/* version number can be increased for Lighty after compatibility for ECDH
is added */
#define OPENSSL_VERSION_NUMBER 0x1000100fL
#define OPENSSL_VERSION_NUMBER 0x10001040L
#else
#define OPENSSL_VERSION_NUMBER 0x0090810fL
#endif