Merge pull request #3841 from SparkiDev/aes_gcm_stream

AES GCM: implement streaming
This commit is contained in:
toddouska
2021-03-18 14:36:55 -07:00
committed by GitHub
10 changed files with 9286 additions and 84 deletions

View File

@@ -1300,6 +1300,11 @@ AC_ARG_ENABLE([aesgcm],
[ ENABLED_AESGCM=$enableval ], [ ENABLED_AESGCM=$enableval ],
[ ENABLED_AESGCM=yes ] [ ENABLED_AESGCM=yes ]
) )
AC_ARG_ENABLE([aesgcm-stream],
[AS_HELP_STRING([--enable-aesgcm-stream],[Enable wolfSSL AES-GCM support with streaming APIs (default: enabled)])],
[ ENABLED_AESGCM_STREAM=$enableval ],
[ ENABLED_AESGCM_STREAM=no ]
)
# leanpsk and leantls don't need gcm # leanpsk and leantls don't need gcm
if test "$ENABLED_LEANPSK" = "yes" || ( test "$ENABLED_LEANTLS" = "yes" && if test "$ENABLED_LEANPSK" = "yes" || ( test "$ENABLED_LEANTLS" = "yes" &&
@@ -5979,6 +5984,16 @@ then
AM_CFLAGS="$AM_CFLAGS -DHAVE_AESGCM" AM_CFLAGS="$AM_CFLAGS -DHAVE_AESGCM"
fi fi
if test "$ENABLED_AESGCM_STREAM" != "no"
then
if test "$ENABLED_AESGCM" = "no"
then
AC_MSG_ERROR([AES-GCM streaming enabled but AES-GCM is disabled])
else
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AESGCM_STREAM"
AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_AESGCM_STREAM"
fi
fi
AS_IF([test "x$ENABLED_MAXSTRENGTH" = "xyes"], AS_IF([test "x$ENABLED_MAXSTRENGTH" = "xyes"],

View File

@@ -11614,6 +11614,208 @@ static int test_wc_AesCmacGenerate (void)
} /* END test_wc_AesCmacGenerate */ } /* END test_wc_AesCmacGenerate */
/*
* Testing streaming AES-GCM API.
*/
static int test_wc_AesGcmStream (void)
{
int ret = 0;
#if !defined(NO_AES) && defined(WOLFSSL_AES_128) && defined(HAVE_AESGCM) && \
defined(WOLFSSL_AESGCM_STREAM)
int i;
WC_RNG rng[1];
Aes aesEnc[1];
Aes aesDec[1];
byte tag[AES_BLOCK_SIZE];
byte in[AES_BLOCK_SIZE * 3 + 2] = { 0, };
byte out[AES_BLOCK_SIZE * 3 + 2];
byte plain[AES_BLOCK_SIZE * 3 + 2];
byte aad[AES_BLOCK_SIZE * 3 + 2] = { 0, };
byte key[AES_128_KEY_SIZE] = { 0, };
byte iv[AES_IV_SIZE] = { 1, };
byte ivOut[AES_IV_SIZE];
static const byte expTagAAD1[AES_BLOCK_SIZE] = {
0x6c, 0x35, 0xe6, 0x7f, 0x59, 0x9e, 0xa9, 0x2f,
0x27, 0x2d, 0x5f, 0x8e, 0x7e, 0x42, 0xd3, 0x05
};
static const byte expTagPlain1[AES_BLOCK_SIZE] = {
0x24, 0xba, 0x57, 0x95, 0xd0, 0x27, 0x9e, 0x78,
0x3a, 0x88, 0x4c, 0x0a, 0x5d, 0x50, 0x23, 0xd1
};
static const byte expTag[AES_BLOCK_SIZE] = {
0x22, 0x91, 0x70, 0xad, 0x42, 0xc3, 0xad, 0x96,
0xe0, 0x31, 0x57, 0x60, 0xb7, 0x92, 0xa3, 0x6d
};
/* Create a random for generating IV/nonce. */
AssertIntEQ(wc_InitRng(rng), 0);
/* Initialize data structures. */
AssertIntEQ(wc_AesInit(aesEnc, NULL, INVALID_DEVID), 0);
AssertIntEQ(wc_AesInit(aesDec, NULL, INVALID_DEVID), 0);
/* BadParameters to streaming init. */
AssertIntEQ(wc_AesGcmEncryptInit(NULL, NULL, 0, NULL, 0), BAD_FUNC_ARG);
AssertIntEQ(wc_AesGcmDecryptInit(NULL, NULL, 0, NULL, 0), BAD_FUNC_ARG);
AssertIntEQ(wc_AesGcmDecryptInit(aesEnc, NULL, AES_128_KEY_SIZE, NULL, 0),
BAD_FUNC_ARG);
AssertIntEQ(wc_AesGcmDecryptInit(aesEnc, NULL, 0, NULL, GCM_NONCE_MID_SZ),
BAD_FUNC_ARG);
/* Bad parameters to encrypt update. */
AssertIntEQ(wc_AesGcmEncryptUpdate(NULL, NULL, NULL, 0, NULL, 0),
BAD_FUNC_ARG);
AssertIntEQ(wc_AesGcmEncryptUpdate(aesEnc, NULL, NULL, 1, NULL, 0),
BAD_FUNC_ARG);
AssertIntEQ(wc_AesGcmEncryptUpdate(aesEnc, NULL, in, 1, NULL, 0),
BAD_FUNC_ARG);
AssertIntEQ(wc_AesGcmEncryptUpdate(aesEnc, out, NULL, 1, NULL, 0),
BAD_FUNC_ARG);
AssertIntEQ(wc_AesGcmEncryptUpdate(aesEnc, NULL, NULL, 0, NULL, 1),
BAD_FUNC_ARG);
/* Bad parameters to decrypt update. */
AssertIntEQ(wc_AesGcmDecryptUpdate(NULL, NULL, NULL, 0, NULL, 0),
BAD_FUNC_ARG);
AssertIntEQ(wc_AesGcmDecryptUpdate(aesDec, NULL, NULL, 1, NULL, 0),
BAD_FUNC_ARG);
AssertIntEQ(wc_AesGcmDecryptUpdate(aesDec, NULL, in, 1, NULL, 0),
BAD_FUNC_ARG);
AssertIntEQ(wc_AesGcmDecryptUpdate(aesDec, out, NULL, 1, NULL, 0),
BAD_FUNC_ARG);
AssertIntEQ(wc_AesGcmDecryptUpdate(aesDec, NULL, NULL, 0, NULL, 1),
BAD_FUNC_ARG);
/* Bad parameters to encrypt final. */
AssertIntEQ(wc_AesGcmEncryptFinal(NULL, NULL, 0), BAD_FUNC_ARG);
AssertIntEQ(wc_AesGcmEncryptFinal(NULL, tag, 0), BAD_FUNC_ARG);
AssertIntEQ(wc_AesGcmEncryptFinal(NULL, NULL, AES_BLOCK_SIZE),
BAD_FUNC_ARG);
AssertIntEQ(wc_AesGcmEncryptFinal(aesEnc, tag, 0), BAD_FUNC_ARG);
AssertIntEQ(wc_AesGcmEncryptFinal(aesEnc, NULL, AES_BLOCK_SIZE),
BAD_FUNC_ARG);
AssertIntEQ(wc_AesGcmEncryptFinal(aesEnc, tag, AES_BLOCK_SIZE + 1),
BAD_FUNC_ARG);
/* Bad parameters to decrypt final. */
AssertIntEQ(wc_AesGcmDecryptFinal(NULL, NULL, 0), BAD_FUNC_ARG);
AssertIntEQ(wc_AesGcmDecryptFinal(NULL, tag, 0), BAD_FUNC_ARG);
AssertIntEQ(wc_AesGcmDecryptFinal(NULL, NULL, AES_BLOCK_SIZE),
BAD_FUNC_ARG);
AssertIntEQ(wc_AesGcmDecryptFinal(aesDec, tag, 0), BAD_FUNC_ARG);
AssertIntEQ(wc_AesGcmDecryptFinal(aesDec, NULL, AES_BLOCK_SIZE),
BAD_FUNC_ARG);
AssertIntEQ(wc_AesGcmDecryptFinal(aesDec, tag, AES_BLOCK_SIZE + 1),
BAD_FUNC_ARG);
/* Check calling final before setting key fails. */
AssertIntEQ(wc_AesGcmEncryptFinal(aesEnc, tag, sizeof(tag)), MISSING_KEY);
AssertIntEQ(wc_AesGcmEncryptFinal(aesDec, tag, sizeof(tag)), MISSING_KEY);
/* Check calling update before setting key else fails. */
AssertIntEQ(wc_AesGcmEncryptUpdate(aesEnc, NULL, NULL, 0, aad, 1),
MISSING_KEY);
AssertIntEQ(wc_AesGcmDecryptUpdate(aesDec, NULL, NULL, 0, aad, 1),
MISSING_KEY);
/* Set key but not IV. */
AssertIntEQ(wc_AesGcmInit(aesEnc, key, sizeof(key), NULL, 0), 0);
AssertIntEQ(wc_AesGcmInit(aesDec, key, sizeof(key), NULL, 0), 0);
/* Check calling final before setting IV fails. */
AssertIntEQ(wc_AesGcmEncryptFinal(aesEnc, tag, sizeof(tag)), MISSING_IV);
AssertIntEQ(wc_AesGcmEncryptFinal(aesDec, tag, sizeof(tag)), MISSING_IV);
/* Check calling update before setting IV else fails. */
AssertIntEQ(wc_AesGcmEncryptUpdate(aesEnc, NULL, NULL, 0, aad, 1),
MISSING_IV);
AssertIntEQ(wc_AesGcmDecryptUpdate(aesDec, NULL, NULL, 0, aad, 1),
MISSING_IV);
/* Set IV using fixed part IV and external IV APIs. */
AssertIntEQ(wc_AesGcmSetIV(aesEnc, GCM_NONCE_MID_SZ, iv, AES_IV_FIXED_SZ,
rng), 0);
AssertIntEQ(wc_AesGcmEncryptInit_ex(aesEnc, NULL, 0, ivOut,
GCM_NONCE_MID_SZ), 0);
AssertIntEQ(wc_AesGcmSetExtIV(aesDec, ivOut, GCM_NONCE_MID_SZ), 0);
AssertIntEQ(wc_AesGcmInit(aesDec, NULL, 0, NULL, 0), 0);
/* Encrypt and decrypt data. */
AssertIntEQ(wc_AesGcmEncryptUpdate(aesEnc, out, in, 1, aad, 1), 0);
AssertIntEQ(wc_AesGcmDecryptUpdate(aesDec, plain, out, 1, aad, 1), 0);
AssertIntEQ(XMEMCMP(plain, in, 1), 0);
/* Finalize and check tag matches. */
AssertIntEQ(wc_AesGcmEncryptFinal(aesEnc, tag, AES_BLOCK_SIZE), 0);
AssertIntEQ(wc_AesGcmDecryptFinal(aesDec, tag, AES_BLOCK_SIZE), 0);
/* Set key and IV through streaming init API. */
AssertIntEQ(wc_AesGcmInit(aesEnc, key, sizeof(key), iv, AES_IV_SIZE), 0);
AssertIntEQ(wc_AesGcmInit(aesDec, key, sizeof(key), iv, AES_IV_SIZE), 0);
/* Encrypt/decrypt one block and AAD of one block. */
AssertIntEQ(wc_AesGcmEncryptUpdate(aesEnc, out, in, AES_BLOCK_SIZE, aad,
AES_BLOCK_SIZE), 0);
AssertIntEQ(wc_AesGcmDecryptUpdate(aesDec, plain, out, AES_BLOCK_SIZE, aad,
AES_BLOCK_SIZE), 0);
AssertIntEQ(XMEMCMP(plain, in, AES_BLOCK_SIZE), 0);
/* Finalize and check tag matches. */
AssertIntEQ(wc_AesGcmEncryptFinal(aesEnc, tag, AES_BLOCK_SIZE), 0);
AssertIntEQ(wc_AesGcmDecryptFinal(aesDec, tag, AES_BLOCK_SIZE), 0);
/* Set key and IV through streaming init API. */
AssertIntEQ(wc_AesGcmInit(aesEnc, key, sizeof(key), iv, AES_IV_SIZE), 0);
AssertIntEQ(wc_AesGcmInit(aesDec, key, sizeof(key), iv, AES_IV_SIZE), 0);
/* No data to encrypt/decrypt one byte of AAD. */
AssertIntEQ(wc_AesGcmEncryptUpdate(aesEnc, NULL, NULL, 0, aad, 1), 0);
AssertIntEQ(wc_AesGcmDecryptUpdate(aesDec, NULL, NULL, 0, aad, 1), 0);
/* Finalize and check tag matches. */
AssertIntEQ(wc_AesGcmEncryptFinal(aesEnc, tag, AES_BLOCK_SIZE), 0);
AssertIntEQ(XMEMCMP(tag, expTagAAD1, AES_BLOCK_SIZE), 0);
AssertIntEQ(wc_AesGcmDecryptFinal(aesDec, tag, AES_BLOCK_SIZE), 0);
/* Set key and IV through streaming init API. */
AssertIntEQ(wc_AesGcmInit(aesEnc, key, sizeof(key), iv, AES_IV_SIZE), 0);
AssertIntEQ(wc_AesGcmInit(aesDec, key, sizeof(key), iv, AES_IV_SIZE), 0);
/* Encrypt/decrypt one byte and no AAD. */
AssertIntEQ(wc_AesGcmEncryptUpdate(aesEnc, out, in, 1, NULL, 0), 0);
AssertIntEQ(wc_AesGcmDecryptUpdate(aesDec, plain, out, 1, NULL, 0), 0);
AssertIntEQ(XMEMCMP(plain, in, 1), 0);
/* Finalize and check tag matches. */
AssertIntEQ(wc_AesGcmEncryptFinal(aesEnc, tag, AES_BLOCK_SIZE), 0);
AssertIntEQ(XMEMCMP(tag, expTagPlain1, AES_BLOCK_SIZE), 0);
AssertIntEQ(wc_AesGcmDecryptFinal(aesDec, tag, AES_BLOCK_SIZE), 0);
/* Set key and IV through streaming init API. */
AssertIntEQ(wc_AesGcmInit(aesEnc, key, sizeof(key), iv, AES_IV_SIZE), 0);
AssertIntEQ(wc_AesGcmInit(aesDec, key, sizeof(key), iv, AES_IV_SIZE), 0);
/* Encryption AES is one byte at a time */
for (i = 0; i < (int)sizeof(aad); i++) {
AssertIntEQ(wc_AesGcmEncryptUpdate(aesEnc, NULL, NULL, 0, aad + i, 1),
0);
}
for (i = 0; i < (int)sizeof(in); i++) {
AssertIntEQ(wc_AesGcmEncryptUpdate(aesEnc, out + i, in + i, 1, NULL, 0),
0);
}
/* Decryption AES is two bytes at a time */
for (i = 0; i < (int)sizeof(aad); i += 2) {
AssertIntEQ(wc_AesGcmDecryptUpdate(aesDec, NULL, NULL, 0, aad + i, 2),
0);
}
for (i = 0; i < (int)sizeof(aad); i += 2) {
AssertIntEQ(wc_AesGcmDecryptUpdate(aesDec, plain + i, out + i, 2, NULL,
0), 0);
}
AssertIntEQ(XMEMCMP(plain, in, sizeof(in)), 0);
/* Finalize and check tag matches. */
AssertIntEQ(wc_AesGcmEncryptFinal(aesEnc, tag, AES_BLOCK_SIZE), 0);
AssertIntEQ(XMEMCMP(tag, expTag, AES_BLOCK_SIZE), 0);
AssertIntEQ(wc_AesGcmDecryptFinal(aesDec, tag, AES_BLOCK_SIZE), 0);
/* Check streaming encryption can be decrypted with one shot. */
AssertIntEQ(wc_AesGcmSetKey(aesDec, key, sizeof(key)), 0);
AssertIntEQ(wc_AesGcmDecrypt(aesDec, plain, out, sizeof(in), iv,
AES_IV_SIZE, tag, AES_BLOCK_SIZE, aad, sizeof(aad)), 0);
AssertIntEQ(XMEMCMP(plain, in, sizeof(in)), 0);
#endif
return ret;
} /* END test_wc_AesGcmStream */
/* /*
@@ -39748,15 +39950,19 @@ static void test_wolfssl_EVP_aes_gcm_AAD_2_parts(void)
const byte iv[12] = { 0 }; const byte iv[12] = { 0 };
const byte key[16] = { 0 }; const byte key[16] = { 0 };
const byte cleartext[16] = { 0 }; const byte cleartext[16] = { 0 };
const byte aad[] = {0x01, 0x10, 0x00, 0x2a, 0x08, 0x00, 0x04, 0x00, 0x00, const byte aad[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0xdc, 0x4d, 0x01, 0x10, 0x00, 0x2a, 0x08, 0x00, 0x04, 0x00,
0xad, 0x6b, 0x06, 0x93, 0x4f}; 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
0x00, 0x00, 0xdc, 0x4d, 0xad, 0x6b, 0x06, 0x93,
0x4f
};
byte out1Part[16]; byte out1Part[16];
byte outTag1Part[16]; byte outTag1Part[16];
byte out2Part[16]; byte out2Part[16];
byte outTag2Part[16]; byte outTag2Part[16];
byte decryptBuf[16]; byte decryptBuf[16];
int len; int len;
int tlen;
EVP_CIPHER_CTX* ctx = NULL; EVP_CIPHER_CTX* ctx = NULL;
printf(testingFmt, "wolfssl_EVP_aes_gcm_AAD_2_parts"); printf(testingFmt, "wolfssl_EVP_aes_gcm_AAD_2_parts");
@@ -39764,25 +39970,37 @@ static void test_wolfssl_EVP_aes_gcm_AAD_2_parts(void)
/* ENCRYPT */ /* ENCRYPT */
/* Send AAD and data in 1 part */ /* Send AAD and data in 1 part */
AssertNotNull(ctx = EVP_CIPHER_CTX_new()); AssertNotNull(ctx = EVP_CIPHER_CTX_new());
AssertIntEQ(EVP_EncryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL), 1); tlen = 0;
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_EncryptInit_ex(ctx, NULL, NULL, key, iv), 1);
AssertIntEQ(EVP_EncryptUpdate(ctx, NULL, &len, aad, sizeof(aad)), 1); AssertIntEQ(EVP_EncryptUpdate(ctx, NULL, &len, aad, sizeof(aad)), 1);
AssertIntEQ(EVP_EncryptUpdate(ctx, out1Part, &len, cleartext, sizeof(cleartext)), 1); AssertIntEQ(EVP_EncryptUpdate(ctx, out1Part, &len, cleartext,
sizeof(cleartext)), 1);
tlen += len;
AssertIntEQ(EVP_EncryptFinal_ex(ctx, out1Part, &len), 1); AssertIntEQ(EVP_EncryptFinal_ex(ctx, out1Part, &len), 1);
AssertIntEQ(len, sizeof(cleartext)); tlen += len;
AssertIntEQ(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, 16, outTag1Part), 1); AssertIntEQ(tlen, sizeof(cleartext));
AssertIntEQ(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, 16,
outTag1Part), 1);
EVP_CIPHER_CTX_free(ctx); EVP_CIPHER_CTX_free(ctx);
/* DECRYPT */ /* DECRYPT */
/* Send AAD and data in 1 part */ /* Send AAD and data in 1 part */
AssertNotNull(ctx = EVP_CIPHER_CTX_new()); AssertNotNull(ctx = EVP_CIPHER_CTX_new());
AssertIntEQ(EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL), 1); tlen = 0;
AssertIntEQ(EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL),
1);
AssertIntEQ(EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv), 1); AssertIntEQ(EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv), 1);
AssertIntEQ(EVP_DecryptUpdate(ctx, NULL, &len, aad, sizeof(aad)), 1); AssertIntEQ(EVP_DecryptUpdate(ctx, NULL, &len, aad, sizeof(aad)), 1);
AssertIntEQ(EVP_DecryptUpdate(ctx, decryptBuf, &len, out1Part, sizeof(cleartext)), 1); AssertIntEQ(EVP_DecryptUpdate(ctx, decryptBuf, &len, out1Part,
AssertIntEQ(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, 16, outTag1Part), 1); sizeof(cleartext)), 1);
tlen += len;
AssertIntEQ(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, 16,
outTag1Part), 1);
AssertIntEQ(EVP_DecryptFinal_ex(ctx, decryptBuf, &len), 1); AssertIntEQ(EVP_DecryptFinal_ex(ctx, decryptBuf, &len), 1);
AssertIntEQ(len, sizeof(cleartext)); tlen += len;
AssertIntEQ(tlen, sizeof(cleartext));
EVP_CIPHER_CTX_free(ctx); EVP_CIPHER_CTX_free(ctx);
AssertIntEQ(XMEMCMP(decryptBuf, cleartext, len), 0); AssertIntEQ(XMEMCMP(decryptBuf, cleartext, len), 0);
@@ -39790,16 +40008,23 @@ static void test_wolfssl_EVP_aes_gcm_AAD_2_parts(void)
/* ENCRYPT */ /* ENCRYPT */
/* Send AAD and data in 2 parts */ /* Send AAD and data in 2 parts */
AssertNotNull(ctx = EVP_CIPHER_CTX_new()); AssertNotNull(ctx = EVP_CIPHER_CTX_new());
AssertIntEQ(EVP_EncryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL), 1); tlen = 0;
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_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), 1);
AssertIntEQ(EVP_EncryptUpdate(ctx, NULL, &len, aad + 1, sizeof(aad) - 1), 1); AssertIntEQ(EVP_EncryptUpdate(ctx, NULL, &len, aad + 1, sizeof(aad) - 1),
1);
AssertIntEQ(EVP_EncryptUpdate(ctx, out2Part, &len, cleartext, 1), 1); AssertIntEQ(EVP_EncryptUpdate(ctx, out2Part, &len, cleartext, 1), 1);
AssertIntEQ(EVP_EncryptUpdate(ctx, out2Part, &len, cleartext + 1, tlen += len;
AssertIntEQ(EVP_EncryptUpdate(ctx, out2Part + tlen, &len, cleartext + 1,
sizeof(cleartext) - 1), 1); sizeof(cleartext) - 1), 1);
AssertIntEQ(EVP_EncryptFinal_ex(ctx, out2Part, &len), 1); tlen += len;
AssertIntEQ(len, sizeof(cleartext)); AssertIntEQ(EVP_EncryptFinal_ex(ctx, out2Part + tlen, &len), 1);
AssertIntEQ(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, 16, outTag2Part), 1); tlen += len;
AssertIntEQ(tlen, 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(out1Part, out2Part, sizeof(out1Part)), 0);
AssertIntEQ(XMEMCMP(outTag1Part, outTag2Part, sizeof(outTag1Part)), 0); AssertIntEQ(XMEMCMP(outTag1Part, outTag2Part, sizeof(outTag1Part)), 0);
@@ -39808,16 +40033,23 @@ static void test_wolfssl_EVP_aes_gcm_AAD_2_parts(void)
/* DECRYPT */ /* DECRYPT */
/* Send AAD and data in 2 parts */ /* Send AAD and data in 2 parts */
AssertNotNull(ctx = EVP_CIPHER_CTX_new()); AssertNotNull(ctx = EVP_CIPHER_CTX_new());
AssertIntEQ(EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL), 1); tlen = 0;
AssertIntEQ(EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL),
1);
AssertIntEQ(EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv), 1); AssertIntEQ(EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv), 1);
AssertIntEQ(EVP_DecryptUpdate(ctx, NULL, &len, aad, 1), 1); AssertIntEQ(EVP_DecryptUpdate(ctx, NULL, &len, aad, 1), 1);
AssertIntEQ(EVP_DecryptUpdate(ctx, NULL, &len, aad + 1, sizeof(aad) - 1), 1); AssertIntEQ(EVP_DecryptUpdate(ctx, NULL, &len, aad + 1, sizeof(aad) - 1),
1);
AssertIntEQ(EVP_DecryptUpdate(ctx, decryptBuf, &len, out1Part, 1), 1); AssertIntEQ(EVP_DecryptUpdate(ctx, decryptBuf, &len, out1Part, 1), 1);
AssertIntEQ(EVP_DecryptUpdate(ctx, decryptBuf, &len, out1Part + 1, tlen += len;
AssertIntEQ(EVP_DecryptUpdate(ctx, decryptBuf + tlen, &len, out1Part + 1,
sizeof(cleartext) - 1), 1); sizeof(cleartext) - 1), 1);
AssertIntEQ(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, 16, outTag1Part), 1); tlen += len;
AssertIntEQ(EVP_DecryptFinal_ex(ctx, decryptBuf, &len), 1); AssertIntEQ(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, 16,
AssertIntEQ(len, sizeof(cleartext)); outTag1Part), 1);
AssertIntEQ(EVP_DecryptFinal_ex(ctx, decryptBuf + tlen, &len), 1);
tlen += len;
AssertIntEQ(tlen, sizeof(cleartext));
AssertIntEQ(XMEMCMP(decryptBuf, cleartext, len), 0); AssertIntEQ(XMEMCMP(decryptBuf, cleartext, len), 0);
@@ -39834,14 +40066,15 @@ static void test_wolfssl_EVP_aes_gcm_zeroLen(void)
{ {
/* Zero length plain text */ /* Zero length plain text */
byte key[] = byte key[] = {
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; /* align */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
byte iv[] = 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; }; /* align */
/* align */ byte iv[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
}; /* align */
byte plaintxt[0]; byte plaintxt[0];
int ivSz = 12; int ivSz = 12;
int plaintxtSz = 0; int plaintxtSz = 0;
@@ -39861,7 +40094,8 @@ static void test_wolfssl_EVP_aes_gcm_zeroLen(void)
AssertIntEQ(1, EVP_EncryptInit_ex(en, EVP_aes_256_gcm(), NULL, key, iv)); AssertIntEQ(1, EVP_EncryptInit_ex(en, EVP_aes_256_gcm(), NULL, key, iv));
AssertIntEQ(1, EVP_CIPHER_CTX_ctrl(en, EVP_CTRL_GCM_SET_IVLEN, ivSz, NULL)); AssertIntEQ(1, EVP_CIPHER_CTX_ctrl(en, EVP_CTRL_GCM_SET_IVLEN, ivSz, NULL));
AssertIntEQ(1, EVP_EncryptUpdate(en, ciphertxt, &ciphertxtSz , plaintxt, plaintxtSz)); AssertIntEQ(1, EVP_EncryptUpdate(en, ciphertxt, &ciphertxtSz , plaintxt,
plaintxtSz));
AssertIntEQ(1, EVP_EncryptFinal_ex(en, ciphertxt, &len)); AssertIntEQ(1, EVP_EncryptFinal_ex(en, ciphertxt, &len));
ciphertxtSz += len; ciphertxtSz += len;
AssertIntEQ(1, EVP_CIPHER_CTX_ctrl(en, EVP_CTRL_GCM_GET_TAG, 16, tag)); AssertIntEQ(1, EVP_CIPHER_CTX_ctrl(en, EVP_CTRL_GCM_GET_TAG, 16, tag));
@@ -41833,6 +42067,7 @@ void ApiTest(void)
AssertIntEQ(test_wc_CmacUpdate(), 0); AssertIntEQ(test_wc_CmacUpdate(), 0);
AssertIntEQ(test_wc_CmacFinal(), 0); AssertIntEQ(test_wc_CmacFinal(), 0);
AssertIntEQ(test_wc_AesCmacGenerate(), 0); AssertIntEQ(test_wc_AesCmacGenerate(), 0);
AssertIntEQ(test_wc_AesGcmStream(), 0);
AssertIntEQ(test_wc_Des3_SetIV(), 0); AssertIntEQ(test_wc_Des3_SetIV(), 0);
AssertIntEQ(test_wc_Des3_SetKey(), 0); AssertIntEQ(test_wc_Des3_SetKey(), 0);

View File

@@ -2394,10 +2394,23 @@ static void bench_aesgcm_internal(int doAsync, const byte* key, word32 keySz,
/* while free pending slots in queue, submit ops */ /* while free pending slots in queue, submit ops */
for (i = 0; i < BENCH_MAX_PENDING; i++) { for (i = 0; i < BENCH_MAX_PENDING; i++) {
if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&enc[i]), 0, &times, numBlocks, &pending)) { if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&enc[i]), 0, &times, numBlocks, &pending)) {
#ifndef BENCHMARK_AESGCM_STREAM
ret = wc_AesGcmEncrypt(&enc[i], bench_cipher, ret = wc_AesGcmEncrypt(&enc[i], bench_cipher,
bench_plain, BENCH_SIZE, bench_plain, BENCH_SIZE,
iv, ivSz, bench_tag, AES_AUTH_TAG_SZ, iv, ivSz, bench_tag, AES_AUTH_TAG_SZ,
bench_additional, aesAuthAddSz); bench_additional, aesAuthAddSz);
#else
ret = wc_AesGcmEncryptInit(&enc[i], NULL, 0, iv, ivSz);
if (ret == 0) {
ret = wc_AesGcmEncryptUpdate(&enc[i], bench_cipher,
bench_plain, BENCH_SIZE, bench_additional,
aesAuthAddSz);
}
if (ret == 0) {
ret = wc_AesGcmEncryptFinal(&enc[i], bench_tag,
AES_AUTH_TAG_SZ);
}
#endif
if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&enc[i]), 0, &times, &pending)) { if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&enc[i]), 0, &times, &pending)) {
goto exit_aes_gcm; goto exit_aes_gcm;
} }
@@ -2433,10 +2446,23 @@ exit_aes_gcm:
/* while free pending slots in queue, submit ops */ /* while free pending slots in queue, submit ops */
for (i = 0; i < BENCH_MAX_PENDING; i++) { for (i = 0; i < BENCH_MAX_PENDING; i++) {
if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&dec[i]), 0, &times, numBlocks, &pending)) { if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&dec[i]), 0, &times, numBlocks, &pending)) {
#ifndef BENCHMARK_AESGCM_STREAM
ret = wc_AesGcmDecrypt(&dec[i], bench_plain, ret = wc_AesGcmDecrypt(&dec[i], bench_plain,
bench_cipher, BENCH_SIZE, bench_cipher, BENCH_SIZE,
iv, ivSz, bench_tag, AES_AUTH_TAG_SZ, iv, ivSz, bench_tag, AES_AUTH_TAG_SZ,
bench_additional, aesAuthAddSz); bench_additional, aesAuthAddSz);
#else
ret = wc_AesGcmDecryptInit(&enc[i], NULL, 0, iv, ivSz);
if (ret == 0) {
ret = wc_AesGcmDecryptUpdate(&enc[i], bench_plain,
bench_cipher, BENCH_SIZE, bench_additional,
aesAuthAddSz);
}
if (ret == 0) {
ret = wc_AesGcmDecryptFinal(&enc[i], bench_tag,
AES_AUTH_TAG_SZ);
}
#endif
if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&dec[i]), 0, &times, &pending)) { if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&dec[i]), 0, &times, &pending)) {
goto exit_aes_gcm_dec; goto exit_aes_gcm_dec;
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -521,6 +521,12 @@ const char* wc_GetErrorString(int error)
case SAKKE_VERIFY_FAIL_E: case SAKKE_VERIFY_FAIL_E:
return "SAKKE derivation verification error"; return "SAKKE derivation verification error";
case MISSING_IV:
return "Required IV not set";
case MISSING_KEY:
return "Required key not set";
default: default:
return "unknown error number"; return "unknown error number";

View File

@@ -553,6 +553,7 @@ static int evpCipherBlock(WOLFSSL_EVP_CIPHER_CTX *ctx,
} }
#if defined(HAVE_AESGCM) #if defined(HAVE_AESGCM)
#ifndef WOLFSSL_AESGCM_STREAM
static int wolfSSL_EVP_CipherUpdate_GCM_AAD(WOLFSSL_EVP_CIPHER_CTX *ctx, static int wolfSSL_EVP_CipherUpdate_GCM_AAD(WOLFSSL_EVP_CIPHER_CTX *ctx,
const unsigned char *in, int inl) { const unsigned char *in, int inl) {
if (in && inl > 0) { if (in && inl > 0) {
@@ -570,11 +571,13 @@ static int wolfSSL_EVP_CipherUpdate_GCM_AAD(WOLFSSL_EVP_CIPHER_CTX *ctx,
} }
return 0; return 0;
} }
#endif /* WOLFSSL_AESGCM_STREAM */
static int wolfSSL_EVP_CipherUpdate_GCM(WOLFSSL_EVP_CIPHER_CTX *ctx, static int wolfSSL_EVP_CipherUpdate_GCM(WOLFSSL_EVP_CIPHER_CTX *ctx,
unsigned char *out, int *outl, unsigned char *out, int *outl,
const unsigned char *in, int inl) const unsigned char *in, int inl)
{ {
#ifndef WOLFSSL_AESGCM_STREAM
int ret = 0; int ret = 0;
*outl = inl; *outl = inl;
@@ -606,8 +609,42 @@ static int wolfSSL_EVP_CipherUpdate_GCM(WOLFSSL_EVP_CIPHER_CTX *ctx,
} }
return WOLFSSL_SUCCESS; return WOLFSSL_SUCCESS;
#else
int ret;
/* When out is NULL then this is AAD. */
if (out == NULL) {
if (ctx->enc) {
ret = wc_AesGcmEncryptUpdate(&ctx->cipher.aes, NULL, NULL, 0, in,
inl);
}
else {
ret = wc_AesGcmDecryptUpdate(&ctx->cipher.aes, NULL, NULL, 0, in,
inl);
}
}
/* When out is not NULL then this is plaintext/cipher text. */
else {
if (ctx->enc) {
ret = wc_AesGcmEncryptUpdate(&ctx->cipher.aes, out, in, inl, NULL,
0);
}
else {
ret = wc_AesGcmDecryptUpdate(&ctx->cipher.aes, out, in, inl, NULL,
0);
}
}
*outl = inl;
if (ret == 0) {
ret = WOLFSSL_SUCCESS;
}
else {
ret = WOLFSSL_FAILURE;
}
return ret;
#endif /* WOLFSSL_AESGCM_STREAM */
} }
#endif #endif /* HAVE_AESGCM */
/* returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure */ /* returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure */
WOLFSSL_API int wolfSSL_EVP_CipherUpdate(WOLFSSL_EVP_CIPHER_CTX *ctx, WOLFSSL_API int wolfSSL_EVP_CipherUpdate(WOLFSSL_EVP_CIPHER_CTX *ctx,
@@ -630,7 +667,7 @@ WOLFSSL_API int wolfSSL_EVP_CipherUpdate(WOLFSSL_EVP_CIPHER_CTX *ctx,
case AES_128_GCM_TYPE: case AES_128_GCM_TYPE:
case AES_192_GCM_TYPE: case AES_192_GCM_TYPE:
case AES_256_GCM_TYPE: case AES_256_GCM_TYPE:
/* if out == NULL, in/inl contains the additional authenticated data for GCM */ /* if out == NULL, in/inl contains the additional authenticated data * for GCM */
return wolfSSL_EVP_CipherUpdate_GCM(ctx, out, outl, in, inl); return wolfSSL_EVP_CipherUpdate_GCM(ctx, out, outl, in, inl);
default: default:
/* fall-through */ /* fall-through */
@@ -770,6 +807,7 @@ int wolfSSL_EVP_CipherFinal(WOLFSSL_EVP_CIPHER_CTX *ctx,
case AES_128_GCM_TYPE: case AES_128_GCM_TYPE:
case AES_192_GCM_TYPE: case AES_192_GCM_TYPE:
case AES_256_GCM_TYPE: case AES_256_GCM_TYPE:
#ifndef WOLFSSL_AESGCM_STREAM
if ((ctx->gcmBuffer && ctx->gcmBufferLen > 0) if ((ctx->gcmBuffer && ctx->gcmBufferLen > 0)
|| (ctx->gcmBufferLen == 0)) { || (ctx->gcmBufferLen == 0)) {
if (ctx->enc) if (ctx->enc)
@@ -799,6 +837,24 @@ int wolfSSL_EVP_CipherFinal(WOLFSSL_EVP_CIPHER_CTX *ctx,
else { else {
*outl = 0; *outl = 0;
} }
#else
/* No data to return - all handled in Update. */
*outl = 0;
if (ctx->enc) {
ret = wc_AesGcmEncryptFinal(&ctx->cipher.aes, ctx->authTag,
ctx->authTagSz);
}
else {
ret = wc_AesGcmDecryptFinal(&ctx->cipher.aes, ctx->authTag,
ctx->authTagSz);
}
if (ret == 0) {
ret = WOLFSSL_SUCCESS;
}
else {
ret = WOLFSSL_FAILURE;
}
#endif /* WOLFSSL_AESGCM_STREAM */
/* Clear IV, since IV reuse is not recommended for AES GCM. */ /* Clear IV, since IV reuse is not recommended for AES GCM. */
XMEMSET(ctx->iv, 0, AES_BLOCK_SIZE); XMEMSET(ctx->iv, 0, AES_BLOCK_SIZE);
break; break;
@@ -4073,10 +4129,18 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md)
WOLFSSL_MSG("Key or IV not set"); WOLFSSL_MSG("Key or IV not set");
break; break;
} }
if ((ret = wc_AesGcmSetExtIV(&ctx->cipher.aes, ctx->iv, ctx->ivSz)) != 0) { if ((ret = wc_AesGcmSetExtIV(&ctx->cipher.aes, ctx->iv,
ctx->ivSz)) != 0) {
WOLFSSL_MSG("wc_AesGcmSetIV failed"); WOLFSSL_MSG("wc_AesGcmSetIV failed");
ret = WOLFSSL_FAILURE; ret = WOLFSSL_FAILURE;
} }
#ifdef WOLFSSL_AESGCM_STREAM
/* Initialize using IV cached in Aes object. */
if (wc_AesGcmInit(&ctx->cipher.aes, NULL, 0, NULL, 0) != 0) {
WOLFSSL_MSG("wc_AesGcmInit failed");
ret = WOLFSSL_FAILURE;
}
#endif /* WOLFSSL_AESGCM_STREAM */
/* OpenSSL increments the IV. Not sure why */ /* OpenSSL increments the IV. Not sure why */
IncCtr(ctx->iv, ctx->ivSz); IncCtr(ctx->iv, ctx->ivSz);
break; break;
@@ -4373,14 +4437,25 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md)
ctx->authTagSz = AES_BLOCK_SIZE; ctx->authTagSz = AES_BLOCK_SIZE;
ctx->ivSz = GCM_NONCE_MID_SZ; ctx->ivSz = GCM_NONCE_MID_SZ;
#ifndef WOLFSSL_AESGCM_STREAM
if (key && wc_AesGcmSetKey(&ctx->cipher.aes, key, ctx->keyLen)) { if (key && wc_AesGcmSetKey(&ctx->cipher.aes, key, ctx->keyLen)) {
WOLFSSL_MSG("wc_AesGcmSetKey() failed"); WOLFSSL_MSG("wc_AesGcmSetKey() failed");
return WOLFSSL_FAILURE; return WOLFSSL_FAILURE;
} }
#endif /* !WOLFSSL_AESGCM_STREAM */
if (iv && wc_AesGcmSetExtIV(&ctx->cipher.aes, iv, GCM_NONCE_MID_SZ)) { if (iv && wc_AesGcmSetExtIV(&ctx->cipher.aes, iv, GCM_NONCE_MID_SZ)) {
WOLFSSL_MSG("wc_AesGcmSetExtIV() failed"); WOLFSSL_MSG("wc_AesGcmSetExtIV() failed");
return WOLFSSL_FAILURE; return WOLFSSL_FAILURE;
} }
#ifdef WOLFSSL_AESGCM_STREAM
/* Initialize with key and IV if available. */
if (wc_AesGcmInit(&ctx->cipher.aes, key,
(key == NULL) ? 0 : ctx->keyLen, iv,
(iv == NULL) ? 0 : GCM_NONCE_MID_SZ) != 0) {
WOLFSSL_MSG("wc_AesGcmInit() failed");
return WOLFSSL_FAILURE;
}
#endif /* WOLFSSL_AESGCM_STREAM */
if (enc == 0 || enc == 1) if (enc == 0 || enc == 1)
ctx->enc = enc ? 1 : 0; ctx->enc = enc ? 1 : 0;
} }
@@ -4398,14 +4473,25 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md)
ctx->authTagSz = AES_BLOCK_SIZE; ctx->authTagSz = AES_BLOCK_SIZE;
ctx->ivSz = GCM_NONCE_MID_SZ; ctx->ivSz = GCM_NONCE_MID_SZ;
#ifndef WOLFSSL_AESGCM_STREAM
if (key && wc_AesGcmSetKey(&ctx->cipher.aes, key, ctx->keyLen)) { if (key && wc_AesGcmSetKey(&ctx->cipher.aes, key, ctx->keyLen)) {
WOLFSSL_MSG("wc_AesGcmSetKey() failed"); WOLFSSL_MSG("wc_AesGcmSetKey() failed");
return WOLFSSL_FAILURE; return WOLFSSL_FAILURE;
} }
#endif /* !WOLFSSL_AESGCM_STREAM */
if (iv && wc_AesGcmSetExtIV(&ctx->cipher.aes, iv, GCM_NONCE_MID_SZ)) { if (iv && wc_AesGcmSetExtIV(&ctx->cipher.aes, iv, GCM_NONCE_MID_SZ)) {
WOLFSSL_MSG("wc_AesGcmSetExtIV() failed"); WOLFSSL_MSG("wc_AesGcmSetExtIV() failed");
return WOLFSSL_FAILURE; return WOLFSSL_FAILURE;
} }
#ifdef WOLFSSL_AESGCM_STREAM
/* Initialize with key and IV if available. */
if (wc_AesGcmInit(&ctx->cipher.aes, key,
(key == NULL) ? 0 : ctx->keyLen, iv,
(iv == NULL) ? 0 : GCM_NONCE_MID_SZ) != 0) {
WOLFSSL_MSG("wc_AesGcmInit() failed");
return WOLFSSL_FAILURE;
}
#endif /* WOLFSSL_AESGCM_STREAM */
if (enc == 0 || enc == 1) if (enc == 0 || enc == 1)
ctx->enc = enc ? 1 : 0; ctx->enc = enc ? 1 : 0;
} }
@@ -4423,14 +4509,25 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md)
ctx->authTagSz = AES_BLOCK_SIZE; ctx->authTagSz = AES_BLOCK_SIZE;
ctx->ivSz = GCM_NONCE_MID_SZ; ctx->ivSz = GCM_NONCE_MID_SZ;
#ifndef WOLFSSL_AESGCM_STREAM
if (key && wc_AesGcmSetKey(&ctx->cipher.aes, key, ctx->keyLen)) { if (key && wc_AesGcmSetKey(&ctx->cipher.aes, key, ctx->keyLen)) {
WOLFSSL_MSG("wc_AesGcmSetKey() failed"); WOLFSSL_MSG("wc_AesGcmSetKey() failed");
return WOLFSSL_FAILURE; return WOLFSSL_FAILURE;
} }
#endif /* !WOLFSSL_AESGCM_STREAM */
if (iv && wc_AesGcmSetExtIV(&ctx->cipher.aes, iv, GCM_NONCE_MID_SZ)) { if (iv && wc_AesGcmSetExtIV(&ctx->cipher.aes, iv, GCM_NONCE_MID_SZ)) {
WOLFSSL_MSG("wc_AesGcmSetExtIV() failed"); WOLFSSL_MSG("wc_AesGcmSetExtIV() failed");
return WOLFSSL_FAILURE; return WOLFSSL_FAILURE;
} }
#ifdef WOLFSSL_AESGCM_STREAM
/* Initialize with key and IV if available. */
if (wc_AesGcmInit(&ctx->cipher.aes,
key, (key == NULL) ? 0 : ctx->keyLen,
iv, (iv == NULL) ? 0 : GCM_NONCE_MID_SZ) != 0) {
WOLFSSL_MSG("wc_AesGcmInit() failed");
return WOLFSSL_FAILURE;
}
#endif /* WOLFSSL_AESGCM_STREAM */
if (enc == 0 || enc == 1) if (enc == 0 || enc == 1)
ctx->enc = enc ? 1 : 0; ctx->enc = enc ? 1 : 0;
} }
@@ -5262,6 +5359,7 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md)
case AES_192_GCM_TYPE : case AES_192_GCM_TYPE :
case AES_256_GCM_TYPE : case AES_256_GCM_TYPE :
WOLFSSL_MSG("AES GCM"); WOLFSSL_MSG("AES GCM");
#ifndef WOLFSSL_AESGCM_STREAM
if (!dst) { if (!dst) {
ret = wolfSSL_EVP_CipherUpdate_GCM_AAD(ctx, src, len); ret = wolfSSL_EVP_CipherUpdate_GCM_AAD(ctx, src, len);
} }
@@ -5275,6 +5373,50 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md)
len, ctx->iv, ctx->ivSz, ctx->authTag, len, ctx->iv, ctx->ivSz, ctx->authTag,
ctx->authTagSz, ctx->gcmAuthIn, ctx->gcmAuthInSz); ctx->authTagSz, ctx->gcmAuthIn, ctx->gcmAuthInSz);
} }
#else
/* Do one shot operation with streaming API as other
* initialization set up for streaming. */
ret = wc_AesGcmInit(&ctx->cipher.aes, NULL, 0, ctx->iv,
ctx->ivSz);
/* No destination means only AAD. */
if ((ret == 0) && (dst == NULL)) {
if (ctx->enc) {
ret = wc_AesGcmEncryptUpdate(&ctx->cipher.aes, NULL,
NULL, 0, src, len);
}
else {
ret = wc_AesGcmDecryptUpdate(&ctx->cipher.aes, NULL,
NULL, 0, src, len);
}
}
/* Only plaintext/cipher text. */
else if (ret == 0) {
if (ctx->enc) {
ret = wc_AesGcmEncryptUpdate(&ctx->cipher.aes, dst, src,
len, NULL, 0);
}
else {
ret = wc_AesGcmDecryptUpdate(&ctx->cipher.aes, dst, src,
len, NULL, 0);
if (ret == 0) {
ret = wc_AesGcmDecryptFinal(&ctx->cipher.aes,
ctx->authTag, ctx->authTagSz);
}
}
}
if (ret == 0) {
if (ctx->enc) {
/* Calculate authentication tag. */
ret = wc_AesGcmEncryptFinal(&ctx->cipher.aes,
ctx->authTag, ctx->authTagSz);
}
else {
/* Calculate authentication tag and compare. */
ret = wc_AesGcmDecryptFinal(&ctx->cipher.aes,
ctx->authTag, ctx->authTagSz);
}
}
#endif /* WOLFSSL_AESGCM_STREAM */
if (ret == 0) if (ret == 0)
ret = len; ret = len;
break; break;

View File

@@ -10045,6 +10045,103 @@ WOLFSSL_TEST_SUBROUTINE int aesgcm_test(void)
#endif /* WOLFSSL_AES_256 && !(WC_NO_RNG || HAVE_SELFTEST) */ #endif /* WOLFSSL_AES_256 && !(WC_NO_RNG || HAVE_SELFTEST) */
#endif /* HAVE_FIPS_VERSION >= 2 */ #endif /* HAVE_FIPS_VERSION >= 2 */
#if !defined(WOLFSSL_AFALG_XILINX_AES) && !defined(WOLFSSL_XILINX_CRYPT)
#ifdef WOLFSSL_AES_256
#ifdef WOLFSSL_AESGCM_STREAM
result = wc_AesGcmEncryptInit(enc, k1, sizeof(k1), iv1, sizeof(iv1));
if (result != 0)
ERROR_OUT(-6360, out);
result = wc_AesGcmEncryptUpdate(enc, resultC, p, sizeof(p), a, sizeof(a));
if (result != 0)
ERROR_OUT(-6361, out);
result = wc_AesGcmEncryptFinal(enc, resultT, sizeof(resultT));
if (result != 0)
ERROR_OUT(-6362, out);
if (XMEMCMP(resultC, c1, sizeof(c1)) != 0)
ERROR_OUT(-6363, out);
if (XMEMCMP(resultT, t1, sizeof(t1)) != 0)
ERROR_OUT(-6364, out);
#ifdef HAVE_AES_DECRYPT
result = wc_AesGcmDecryptInit(enc, k1, sizeof(k1), iv1, sizeof(iv1));
if (result != 0)
ERROR_OUT(-6370, out);
result = wc_AesGcmDecryptUpdate(enc, resultP, c1, sizeof(c1), a, sizeof(a));
if (result != 0)
ERROR_OUT(-6371, out);
result = wc_AesGcmDecryptFinal(enc, t1, sizeof(t1));
if (result != 0)
ERROR_OUT(-6372, out);
if (XMEMCMP(resultP, p, sizeof(p)) != 0)
ERROR_OUT(-6373, out);
#endif
/* alen is the size to pass in with each update. */
for (alen = 1; alen < AES_BLOCK_SIZE + 1; alen++) {
result = wc_AesGcmEncryptInit(enc, k1, sizeof(k1), iv1, sizeof(iv1));
if (result != 0)
ERROR_OUT(-6380, out);
/* plen is the offset into AAD to update with. */
for (plen = 0; plen < (int)sizeof(a); plen += alen) {
int len = sizeof(a) - plen;
if (len > alen) len = alen;
result = wc_AesGcmEncryptUpdate(enc, NULL, NULL, 0, a + plen, len);
if (result != 0)
ERROR_OUT(-6381, out);
}
/* plen is the offset into plaintext to update with. */
for (plen = 0; plen < (int)sizeof(p); plen += alen) {
int len = sizeof(p) - plen;
if (len > alen) len = alen;
result = wc_AesGcmEncryptUpdate(enc, resultC + plen, p + plen, len,
NULL, 0);
if (result != 0)
ERROR_OUT(-6382, out);
}
result = wc_AesGcmEncryptFinal(enc, resultT, sizeof(resultT));
if (result != 0)
ERROR_OUT(-6383, out);
if (XMEMCMP(resultC, c1, sizeof(c1)) != 0)
ERROR_OUT(-6384, out);
if (XMEMCMP(resultT, t1, sizeof(t1)) != 0)
ERROR_OUT(-6385, out);
}
#ifdef HAVE_AES_DECRYPT
for (alen = 1; alen < AES_BLOCK_SIZE + 1; alen++) {
result = wc_AesGcmDecryptInit(enc, k1, sizeof(k1), iv1, sizeof(iv1));
if (result != 0)
ERROR_OUT(-6390, out);
/* plen is the offset into AAD to update with. */
for (plen = 0; plen < (int)sizeof(a); plen += alen) {
int len = sizeof(a) - plen;
if (len > alen) len = alen;
result = wc_AesGcmDecryptUpdate(enc, NULL, NULL, 0, a + plen, len);
if (result != 0)
ERROR_OUT(-6391, out);
}
/* plen is the offset into cipher text to update with. */
for (plen = 0; plen < (int)sizeof(c1); plen += alen) {
int len = sizeof(c1) - plen;
if (len > alen) len = alen;
result = wc_AesGcmDecryptUpdate(enc, resultP + plen, c1 + plen, len,
NULL, 0);
if (result != 0)
ERROR_OUT(-6392, out);
}
result = wc_AesGcmDecryptFinal(enc, t1, sizeof(t1));
if (result != 0)
ERROR_OUT(-6393, out);
if (XMEMCMP(resultP, p, sizeof(p)) != 0)
ERROR_OUT(-6394, out);
}
#endif /* HAVE_AES_DECRYPT */
#endif /* WOLFSSL_AESGCM_STREAM */
#endif /* WOLFSSL_AES_256 */
#endif /* !WOLFSSL_AFALG_XILINX_AES && !WOLFSSL_XILINX_CRYPT */
wc_AesFree(enc); wc_AesFree(enc);
wc_AesFree(dec); wc_AesFree(dec);

View File

@@ -250,6 +250,21 @@ struct Aes {
silabs_aes_t ctx; silabs_aes_t ctx;
#endif #endif
void* heap; /* memory hint to use */ void* heap; /* memory hint to use */
#ifdef WOLFSSL_AESGCM_STREAM
#if !defined(WOLFSSL_SMALL_STACK) || defined(WOLFSSL_AESNI)
ALIGN16 byte streamData[5 * AES_BLOCK_SIZE];
#else
byte* streamData;
#endif
word32 aSz;
word32 cSz;
byte over;
byte aOver;
byte cOver;
byte gcmKeySet:1;
byte nonceSet:1;
byte ctrSet:1;
#endif
}; };
#ifndef WC_AES_TYPE_DEFINED #ifndef WC_AES_TYPE_DEFINED
@@ -361,6 +376,26 @@ WOLFSSL_API int wc_AesEcbDecrypt(Aes* aes, byte* out,
const byte* iv, word32 ivSz, const byte* iv, word32 ivSz,
const byte* authTag, word32 authTagSz, const byte* authTag, word32 authTagSz,
const byte* authIn, word32 authInSz); const byte* authIn, word32 authInSz);
#ifdef WOLFSSL_AESGCM_STREAM
WOLFSSL_API int wc_AesGcmInit(Aes* aes, const byte* key, word32 len,
const byte* iv, word32 ivSz);
WOLFSSL_API int wc_AesGcmEncryptInit(Aes* aes, const byte* key, word32 len,
const byte* iv, word32 ivSz);
WOLFSSL_API int wc_AesGcmEncryptInit_ex(Aes* aes, const byte* key, word32 len,
byte* ivOut, word32 ivOutSz);
WOLFSSL_API int wc_AesGcmEncryptUpdate(Aes* aes, byte* out, const byte* in,
word32 sz, const byte* authIn, word32 authInSz);
WOLFSSL_API int wc_AesGcmEncryptFinal(Aes* aes, byte* authTag,
word32 authTagSz);
WOLFSSL_API int wc_AesGcmDecryptInit(Aes* aes, const byte* key, word32 len,
const byte* iv, word32 ivSz);
WOLFSSL_API int wc_AesGcmDecryptUpdate(Aes* aes, byte* out, const byte* in,
word32 sz, const byte* authIn, word32 authInSz);
WOLFSSL_API int wc_AesGcmDecryptFinal(Aes* aes, const byte* authTag,
word32 authTagSz);
#endif
#ifndef WC_NO_RNG #ifndef WC_NO_RNG
WOLFSSL_API int wc_AesGcmSetExtIV(Aes* aes, const byte* iv, word32 ivSz); WOLFSSL_API int wc_AesGcmSetExtIV(Aes* aes, const byte* iv, word32 ivSz);

View File

@@ -235,8 +235,10 @@ enum {
CHACHA_POLY_OVERFLOW =-274, /* ChaCha20Poly1305 limit overflow */ CHACHA_POLY_OVERFLOW =-274, /* ChaCha20Poly1305 limit overflow */
ASN_SELF_SIGNED_E = -275, /* ASN self-signed certificate error */ ASN_SELF_SIGNED_E = -275, /* ASN self-signed certificate error */
SAKKE_VERIFY_FAIL_E = -276, /* SAKKE derivation verification error */ SAKKE_VERIFY_FAIL_E = -276, /* SAKKE derivation verification error */
MISSING_IV = -277, /* IV was not set */
MISSING_KEY = -278, /* Key was not set */
WC_LAST_E = -276, /* Update this to indicate last error */ WC_LAST_E = -278, /* Update this to indicate last error */
MIN_CODE_E = -300 /* errors -101 - -299 */ MIN_CODE_E = -300 /* errors -101 - -299 */
/* add new companion error id strings for any new error codes /* add new companion error id strings for any new error codes