forked from wolfSSL/wolfssl
Merge pull request #3841 from SparkiDev/aes_gcm_stream
AES GCM: implement streaming
This commit is contained in:
15
configure.ac
15
configure.ac
@@ -1300,6 +1300,11 @@ AC_ARG_ENABLE([aesgcm],
|
||||
[ ENABLED_AESGCM=$enableval ],
|
||||
[ 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
|
||||
if test "$ENABLED_LEANPSK" = "yes" || ( test "$ENABLED_LEANTLS" = "yes" &&
|
||||
@@ -5979,6 +5984,16 @@ then
|
||||
|
||||
AM_CFLAGS="$AM_CFLAGS -DHAVE_AESGCM"
|
||||
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"],
|
||||
|
295
tests/api.c
295
tests/api.c
@@ -11614,6 +11614,208 @@ static int test_wc_AesCmacGenerate (void)
|
||||
} /* 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 key[16] = { 0 };
|
||||
const byte cleartext[16] = { 0 };
|
||||
const byte aad[] = {0x01, 0x10, 0x00, 0x2a, 0x08, 0x00, 0x04, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0xdc, 0x4d,
|
||||
0xad, 0x6b, 0x06, 0x93, 0x4f};
|
||||
const byte aad[] = {
|
||||
0x01, 0x10, 0x00, 0x2a, 0x08, 0x00, 0x04, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
|
||||
0x00, 0x00, 0xdc, 0x4d, 0xad, 0x6b, 0x06, 0x93,
|
||||
0x4f
|
||||
};
|
||||
byte out1Part[16];
|
||||
byte outTag1Part[16];
|
||||
byte out2Part[16];
|
||||
byte outTag2Part[16];
|
||||
byte decryptBuf[16];
|
||||
int len;
|
||||
int tlen;
|
||||
EVP_CIPHER_CTX* ctx = NULL;
|
||||
|
||||
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 */
|
||||
/* 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);
|
||||
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_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(len, sizeof(cleartext));
|
||||
AssertIntEQ(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, 16, outTag1Part), 1);
|
||||
tlen += len;
|
||||
AssertIntEQ(tlen, sizeof(cleartext));
|
||||
AssertIntEQ(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, 16,
|
||||
outTag1Part), 1);
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
|
||||
/* DECRYPT */
|
||||
/* Send AAD and data in 1 part */
|
||||
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_DecryptUpdate(ctx, NULL, &len, aad, sizeof(aad)), 1);
|
||||
AssertIntEQ(EVP_DecryptUpdate(ctx, decryptBuf, &len, out1Part, sizeof(cleartext)), 1);
|
||||
AssertIntEQ(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, 16, outTag1Part), 1);
|
||||
AssertIntEQ(EVP_DecryptUpdate(ctx, decryptBuf, &len, out1Part,
|
||||
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(len, sizeof(cleartext));
|
||||
tlen += len;
|
||||
AssertIntEQ(tlen, sizeof(cleartext));
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
|
||||
AssertIntEQ(XMEMCMP(decryptBuf, cleartext, len), 0);
|
||||
@@ -39790,16 +40008,23 @@ static void test_wolfssl_EVP_aes_gcm_AAD_2_parts(void)
|
||||
/* ENCRYPT */
|
||||
/* 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);
|
||||
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_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,
|
||||
tlen += len;
|
||||
AssertIntEQ(EVP_EncryptUpdate(ctx, out2Part + tlen, &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);
|
||||
tlen += len;
|
||||
AssertIntEQ(EVP_EncryptFinal_ex(ctx, out2Part + tlen, &len), 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(outTag1Part, outTag2Part, sizeof(outTag1Part)), 0);
|
||||
@@ -39808,16 +40033,23 @@ static void test_wolfssl_EVP_aes_gcm_AAD_2_parts(void)
|
||||
/* DECRYPT */
|
||||
/* Send AAD and data in 2 parts */
|
||||
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_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,
|
||||
tlen += len;
|
||||
AssertIntEQ(EVP_DecryptUpdate(ctx, decryptBuf + tlen, &len, out1Part + 1,
|
||||
sizeof(cleartext) - 1), 1);
|
||||
AssertIntEQ(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, 16, outTag1Part), 1);
|
||||
AssertIntEQ(EVP_DecryptFinal_ex(ctx, decryptBuf, &len), 1);
|
||||
AssertIntEQ(len, sizeof(cleartext));
|
||||
tlen += len;
|
||||
AssertIntEQ(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, 16,
|
||||
outTag1Part), 1);
|
||||
AssertIntEQ(EVP_DecryptFinal_ex(ctx, decryptBuf + tlen, &len), 1);
|
||||
tlen += len;
|
||||
AssertIntEQ(tlen, sizeof(cleartext));
|
||||
|
||||
AssertIntEQ(XMEMCMP(decryptBuf, cleartext, len), 0);
|
||||
|
||||
@@ -39834,14 +40066,15 @@ static void test_wolfssl_EVP_aes_gcm_zeroLen(void)
|
||||
{
|
||||
/* Zero length plain text */
|
||||
|
||||
byte key[] =
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
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}; /* align */
|
||||
byte iv[] =
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
|
||||
/* align */
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
|
||||
}; /* align */
|
||||
byte iv[] = {
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
|
||||
}; /* align */
|
||||
byte plaintxt[0];
|
||||
int ivSz = 12;
|
||||
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_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));
|
||||
ciphertxtSz += len;
|
||||
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_CmacFinal(), 0);
|
||||
AssertIntEQ(test_wc_AesCmacGenerate(), 0);
|
||||
AssertIntEQ(test_wc_AesGcmStream(), 0);
|
||||
|
||||
AssertIntEQ(test_wc_Des3_SetIV(), 0);
|
||||
AssertIntEQ(test_wc_Des3_SetKey(), 0);
|
||||
|
@@ -2394,10 +2394,23 @@ static void bench_aesgcm_internal(int doAsync, const byte* key, word32 keySz,
|
||||
/* while free pending slots in queue, submit ops */
|
||||
for (i = 0; i < BENCH_MAX_PENDING; i++) {
|
||||
if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&enc[i]), 0, ×, numBlocks, &pending)) {
|
||||
#ifndef BENCHMARK_AESGCM_STREAM
|
||||
ret = wc_AesGcmEncrypt(&enc[i], bench_cipher,
|
||||
bench_plain, BENCH_SIZE,
|
||||
iv, ivSz, bench_tag, AES_AUTH_TAG_SZ,
|
||||
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, ×, &pending)) {
|
||||
goto exit_aes_gcm;
|
||||
}
|
||||
@@ -2433,10 +2446,23 @@ exit_aes_gcm:
|
||||
/* while free pending slots in queue, submit ops */
|
||||
for (i = 0; i < BENCH_MAX_PENDING; i++) {
|
||||
if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&dec[i]), 0, ×, numBlocks, &pending)) {
|
||||
#ifndef BENCHMARK_AESGCM_STREAM
|
||||
ret = wc_AesGcmDecrypt(&dec[i], bench_plain,
|
||||
bench_cipher, BENCH_SIZE,
|
||||
iv, ivSz, bench_tag, AES_AUTH_TAG_SZ,
|
||||
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, ×, &pending)) {
|
||||
goto exit_aes_gcm_dec;
|
||||
}
|
||||
|
1560
wolfcrypt/src/aes.c
1560
wolfcrypt/src/aes.c
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -521,6 +521,12 @@ const char* wc_GetErrorString(int error)
|
||||
case SAKKE_VERIFY_FAIL_E:
|
||||
return "SAKKE derivation verification error";
|
||||
|
||||
case MISSING_IV:
|
||||
return "Required IV not set";
|
||||
|
||||
case MISSING_KEY:
|
||||
return "Required key not set";
|
||||
|
||||
default:
|
||||
return "unknown error number";
|
||||
|
||||
|
@@ -553,6 +553,7 @@ static int evpCipherBlock(WOLFSSL_EVP_CIPHER_CTX *ctx,
|
||||
}
|
||||
|
||||
#if defined(HAVE_AESGCM)
|
||||
#ifndef WOLFSSL_AESGCM_STREAM
|
||||
static int wolfSSL_EVP_CipherUpdate_GCM_AAD(WOLFSSL_EVP_CIPHER_CTX *ctx,
|
||||
const unsigned char *in, int inl) {
|
||||
if (in && inl > 0) {
|
||||
@@ -570,11 +571,13 @@ static int wolfSSL_EVP_CipherUpdate_GCM_AAD(WOLFSSL_EVP_CIPHER_CTX *ctx,
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* WOLFSSL_AESGCM_STREAM */
|
||||
|
||||
static int wolfSSL_EVP_CipherUpdate_GCM(WOLFSSL_EVP_CIPHER_CTX *ctx,
|
||||
unsigned char *out, int *outl,
|
||||
const unsigned char *in, int inl)
|
||||
{
|
||||
#ifndef WOLFSSL_AESGCM_STREAM
|
||||
int ret = 0;
|
||||
|
||||
*outl = inl;
|
||||
@@ -606,8 +609,42 @@ static int wolfSSL_EVP_CipherUpdate_GCM(WOLFSSL_EVP_CIPHER_CTX *ctx,
|
||||
}
|
||||
|
||||
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 */
|
||||
WOLFSSL_API int wolfSSL_EVP_CipherUpdate(WOLFSSL_EVP_CIPHER_CTX *ctx,
|
||||
@@ -626,16 +663,16 @@ WOLFSSL_API int wolfSSL_EVP_CipherUpdate(WOLFSSL_EVP_CIPHER_CTX *ctx,
|
||||
*outl = 0;
|
||||
|
||||
#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:
|
||||
/* if out == NULL, in/inl contains the additional authenticated data for GCM */
|
||||
return wolfSSL_EVP_CipherUpdate_GCM(ctx, out, outl, in, inl);
|
||||
default:
|
||||
/* fall-through */
|
||||
break;
|
||||
}
|
||||
switch (ctx->cipherType) {
|
||||
case AES_128_GCM_TYPE:
|
||||
case AES_192_GCM_TYPE:
|
||||
case AES_256_GCM_TYPE:
|
||||
/* if out == NULL, in/inl contains the additional authenticated data * for GCM */
|
||||
return wolfSSL_EVP_CipherUpdate_GCM(ctx, out, outl, in, inl);
|
||||
default:
|
||||
/* fall-through */
|
||||
break;
|
||||
}
|
||||
#endif /* !defined(NO_AES) && defined(HAVE_AESGCM) */
|
||||
|
||||
if (out == NULL) {
|
||||
@@ -770,6 +807,7 @@ int wolfSSL_EVP_CipherFinal(WOLFSSL_EVP_CIPHER_CTX *ctx,
|
||||
case AES_128_GCM_TYPE:
|
||||
case AES_192_GCM_TYPE:
|
||||
case AES_256_GCM_TYPE:
|
||||
#ifndef WOLFSSL_AESGCM_STREAM
|
||||
if ((ctx->gcmBuffer && ctx->gcmBufferLen > 0)
|
||||
|| (ctx->gcmBufferLen == 0)) {
|
||||
if (ctx->enc)
|
||||
@@ -799,6 +837,24 @@ int wolfSSL_EVP_CipherFinal(WOLFSSL_EVP_CIPHER_CTX *ctx,
|
||||
else {
|
||||
*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. */
|
||||
XMEMSET(ctx->iv, 0, AES_BLOCK_SIZE);
|
||||
break;
|
||||
@@ -4073,10 +4129,18 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md)
|
||||
WOLFSSL_MSG("Key or IV not set");
|
||||
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");
|
||||
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 */
|
||||
IncCtr(ctx->iv, ctx->ivSz);
|
||||
break;
|
||||
@@ -4373,14 +4437,25 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md)
|
||||
ctx->authTagSz = AES_BLOCK_SIZE;
|
||||
ctx->ivSz = GCM_NONCE_MID_SZ;
|
||||
|
||||
#ifndef WOLFSSL_AESGCM_STREAM
|
||||
if (key && wc_AesGcmSetKey(&ctx->cipher.aes, key, ctx->keyLen)) {
|
||||
WOLFSSL_MSG("wc_AesGcmSetKey() failed");
|
||||
return WOLFSSL_FAILURE;
|
||||
}
|
||||
#endif /* !WOLFSSL_AESGCM_STREAM */
|
||||
if (iv && wc_AesGcmSetExtIV(&ctx->cipher.aes, iv, GCM_NONCE_MID_SZ)) {
|
||||
WOLFSSL_MSG("wc_AesGcmSetExtIV() failed");
|
||||
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)
|
||||
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->ivSz = GCM_NONCE_MID_SZ;
|
||||
|
||||
#ifndef WOLFSSL_AESGCM_STREAM
|
||||
if (key && wc_AesGcmSetKey(&ctx->cipher.aes, key, ctx->keyLen)) {
|
||||
WOLFSSL_MSG("wc_AesGcmSetKey() failed");
|
||||
return WOLFSSL_FAILURE;
|
||||
}
|
||||
#endif /* !WOLFSSL_AESGCM_STREAM */
|
||||
if (iv && wc_AesGcmSetExtIV(&ctx->cipher.aes, iv, GCM_NONCE_MID_SZ)) {
|
||||
WOLFSSL_MSG("wc_AesGcmSetExtIV() failed");
|
||||
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)
|
||||
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->ivSz = GCM_NONCE_MID_SZ;
|
||||
|
||||
#ifndef WOLFSSL_AESGCM_STREAM
|
||||
if (key && wc_AesGcmSetKey(&ctx->cipher.aes, key, ctx->keyLen)) {
|
||||
WOLFSSL_MSG("wc_AesGcmSetKey() failed");
|
||||
return WOLFSSL_FAILURE;
|
||||
}
|
||||
#endif /* !WOLFSSL_AESGCM_STREAM */
|
||||
if (iv && wc_AesGcmSetExtIV(&ctx->cipher.aes, iv, GCM_NONCE_MID_SZ)) {
|
||||
WOLFSSL_MSG("wc_AesGcmSetExtIV() failed");
|
||||
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)
|
||||
ctx->enc = enc ? 1 : 0;
|
||||
}
|
||||
@@ -4482,7 +4579,7 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md)
|
||||
if (enc == 0 || enc == 1)
|
||||
ctx->enc = enc ? 1 : 0;
|
||||
if (key) {
|
||||
ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv,
|
||||
ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv,
|
||||
AES_ENCRYPTION, 1);
|
||||
if (ret != 0)
|
||||
return WOLFSSL_FAILURE;
|
||||
@@ -4510,7 +4607,7 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md)
|
||||
if (enc == 0 || enc == 1)
|
||||
ctx->enc = enc ? 1 : 0;
|
||||
if (key) {
|
||||
ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv,
|
||||
ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv,
|
||||
AES_ENCRYPTION, 1);
|
||||
if (ret != 0)
|
||||
return WOLFSSL_FAILURE;
|
||||
@@ -4536,7 +4633,7 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md)
|
||||
if (enc == 0 || enc == 1)
|
||||
ctx->enc = enc ? 1 : 0;
|
||||
if (key) {
|
||||
ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, NULL,
|
||||
ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, NULL,
|
||||
ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION, 1);
|
||||
}
|
||||
if (ret != 0)
|
||||
@@ -5262,6 +5359,7 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md)
|
||||
case AES_192_GCM_TYPE :
|
||||
case AES_256_GCM_TYPE :
|
||||
WOLFSSL_MSG("AES GCM");
|
||||
#ifndef WOLFSSL_AESGCM_STREAM
|
||||
if (!dst) {
|
||||
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,
|
||||
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)
|
||||
ret = len;
|
||||
break;
|
||||
|
@@ -10045,6 +10045,103 @@ WOLFSSL_TEST_SUBROUTINE int aesgcm_test(void)
|
||||
#endif /* WOLFSSL_AES_256 && !(WC_NO_RNG || HAVE_SELFTEST) */
|
||||
#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(dec);
|
||||
|
||||
|
@@ -250,6 +250,21 @@ struct Aes {
|
||||
silabs_aes_t ctx;
|
||||
#endif
|
||||
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
|
||||
@@ -361,6 +376,26 @@ WOLFSSL_API int wc_AesEcbDecrypt(Aes* aes, byte* out,
|
||||
const byte* iv, word32 ivSz,
|
||||
const byte* authTag, word32 authTagSz,
|
||||
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
|
||||
WOLFSSL_API int wc_AesGcmSetExtIV(Aes* aes, const byte* iv, word32 ivSz);
|
||||
|
@@ -235,8 +235,10 @@ enum {
|
||||
CHACHA_POLY_OVERFLOW =-274, /* ChaCha20Poly1305 limit overflow */
|
||||
ASN_SELF_SIGNED_E = -275, /* ASN self-signed certificate 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 */
|
||||
|
||||
/* add new companion error id strings for any new error codes
|
||||
|
Reference in New Issue
Block a user