mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2025-07-30 02:37:28 +02:00
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:
@ -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
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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,76 +748,98 @@ int wolfSSL_EVP_CipherFinal(WOLFSSL_EVP_CIPHER_CTX *ctx,
|
||||
return WOLFSSL_FAILURE;
|
||||
|
||||
WOLFSSL_ENTER("wolfSSL_EVP_CipherFinal");
|
||||
|
||||
switch (ctx->cipherType) {
|
||||
#if !defined(NO_AES) && defined(HAVE_AESGCM)
|
||||
switch (ctx->cipherType) {
|
||||
case AES_128_GCM_TYPE:
|
||||
case AES_192_GCM_TYPE:
|
||||
case AES_256_GCM_TYPE:
|
||||
*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 */
|
||||
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;
|
||||
}
|
||||
|
||||
if (!out)
|
||||
return WOLFSSL_FAILURE;
|
||||
|
||||
if (ctx->flags & WOLFSSL_EVP_CIPH_NO_PADDING) {
|
||||
if (ctx->bufUsed != 0) return WOLFSSL_FAILURE;
|
||||
*outl = 0;
|
||||
}
|
||||
else if (ctx->enc) {
|
||||
if (ctx->block_size == 1) {
|
||||
*outl = 0;
|
||||
}
|
||||
else if ((ctx->bufUsed >= 0) && (ctx->block_size != 1)) {
|
||||
padBlock(ctx);
|
||||
PRINT_BUF(ctx->buf, ctx->block_size);
|
||||
if (evpCipherBlock(ctx, out, ctx->buf, ctx->block_size) == 0) {
|
||||
WOLFSSL_MSG("Final Cipher Block failed");
|
||||
ret = WOLFSSL_FAILURE;
|
||||
XFREE(ctx->gcmDecryptBuffer, NULL, DYNAMIC_TYPE_OPENSSL);
|
||||
ctx->gcmDecryptBuffer = NULL;
|
||||
ctx->gcmDecryptBufferLen = 0;
|
||||
}
|
||||
else {
|
||||
PRINT_BUF(out, ctx->block_size);
|
||||
*outl = ctx->block_size;
|
||||
*outl = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (ctx->block_size == 1) {
|
||||
*outl = 0;
|
||||
}
|
||||
else if ((ctx->bufUsed % ctx->block_size) != 0) {
|
||||
*outl = 0;
|
||||
/* not enough padding for decrypt */
|
||||
WOLFSSL_MSG("Final Cipher Block not enough padding");
|
||||
ret = WOLFSSL_FAILURE;
|
||||
}
|
||||
else if (ctx->lastUsed) {
|
||||
PRINT_BUF(ctx->lastBlock, ctx->block_size);
|
||||
if ((fl = checkPad(ctx, ctx->lastBlock)) >= 0) {
|
||||
XMEMCPY(out, ctx->lastBlock, fl);
|
||||
*outl = fl;
|
||||
if (ctx->lastUsed == 0 && ctx->bufUsed == 0) {
|
||||
/* return error in cases where the block length is incorrect */
|
||||
WOLFSSL_MSG("Final Cipher Block bad length");
|
||||
ret = WOLFSSL_FAILURE;
|
||||
/* Clear IV, since IV reuse is not recommended for AES GCM. */
|
||||
XMEMSET(ctx->iv, 0, AES_BLOCK_SIZE);
|
||||
break;
|
||||
#endif /* !NO_AES && HAVE_AESGCM */
|
||||
default:
|
||||
if (!out)
|
||||
return WOLFSSL_FAILURE;
|
||||
|
||||
if (ctx->flags & WOLFSSL_EVP_CIPH_NO_PADDING) {
|
||||
if (ctx->bufUsed != 0) return WOLFSSL_FAILURE;
|
||||
*outl = 0;
|
||||
}
|
||||
else if (ctx->enc) {
|
||||
if (ctx->block_size == 1) {
|
||||
*outl = 0;
|
||||
}
|
||||
else if ((ctx->bufUsed >= 0) && (ctx->block_size != 1)) {
|
||||
padBlock(ctx);
|
||||
PRINT_BUF(ctx->buf, ctx->block_size);
|
||||
if (evpCipherBlock(ctx, out, ctx->buf, ctx->block_size) == 0) {
|
||||
WOLFSSL_MSG("Final Cipher Block failed");
|
||||
ret = WOLFSSL_FAILURE;
|
||||
}
|
||||
else {
|
||||
PRINT_BUF(out, ctx->block_size);
|
||||
*outl = ctx->block_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
ret = WOLFSSL_FAILURE;
|
||||
if (ctx->block_size == 1) {
|
||||
*outl = 0;
|
||||
}
|
||||
else if ((ctx->bufUsed % ctx->block_size) != 0) {
|
||||
*outl = 0;
|
||||
/* not enough padding for decrypt */
|
||||
WOLFSSL_MSG("Final Cipher Block not enough padding");
|
||||
ret = WOLFSSL_FAILURE;
|
||||
}
|
||||
else if (ctx->lastUsed) {
|
||||
PRINT_BUF(ctx->lastBlock, ctx->block_size);
|
||||
if ((fl = checkPad(ctx, ctx->lastBlock)) >= 0) {
|
||||
XMEMCPY(out, ctx->lastBlock, fl);
|
||||
*outl = fl;
|
||||
if (ctx->lastUsed == 0 && ctx->bufUsed == 0) {
|
||||
/* return error in cases where the block length is
|
||||
* incorrect */
|
||||
WOLFSSL_MSG("Final Cipher Block bad length");
|
||||
ret = WOLFSSL_FAILURE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ret = WOLFSSL_FAILURE;
|
||||
}
|
||||
}
|
||||
else if (ctx->lastUsed == 0 && ctx->bufUsed == 0) {
|
||||
/* return error in cases where the block length is
|
||||
* incorrect */
|
||||
ret = WOLFSSL_FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ctx->lastUsed == 0 && ctx->bufUsed == 0) {
|
||||
/* 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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Reference in New Issue
Block a user