Merge pull request #5170 from haydenroche5/evp_cipher_aes_gcm
Fix EVP_CTRL_GCM_IV_GEN with AES-GCM.
This commit is contained in:
commit
81cd1e652e
284
tests/api.c
284
tests/api.c
@ -45185,27 +45185,279 @@ static void test_wolfSSL_EVP_BytesToKey(void)
|
||||
printf(resultFmt, passed);
|
||||
#endif
|
||||
}
|
||||
static void test_IncCtr(void)
|
||||
static void test_evp_cipher_aes_gcm(void)
|
||||
{
|
||||
#if defined(HAVE_AESGCM) && !defined(HAVE_FIPS)
|
||||
byte key[AES_128_KEY_SIZE] = {0};
|
||||
byte iv[GCM_NONCE_MID_SZ] = {0};
|
||||
int type = EVP_CTRL_GCM_IV_GEN;
|
||||
int arg = 0;
|
||||
void *ptr = NULL;
|
||||
#if defined(HAVE_AESGCM) && ((!defined(HAVE_FIPS) && \
|
||||
!defined(HAVE_SELFTEST)) || (defined(HAVE_FIPS_VERSION) && \
|
||||
(HAVE_FIPS_VERSION >= 2)))
|
||||
/*
|
||||
* This test checks data at various points in the encrypt/decrypt process
|
||||
* against known values produced using the same test with OpenSSL. This
|
||||
* interop testing is critical for verifying the correctness of our
|
||||
* EVP_Cipher implementation with AES-GCM. Specifically, this test exercises
|
||||
* a flow supported by OpenSSL that uses the control command
|
||||
* EVP_CTRL_GCM_IV_GEN to increment the IV between cipher operations without
|
||||
* the need to call EVP_CipherInit. OpenSSH uses this flow, for example. We
|
||||
* had a bug with OpenSSH where wolfSSL OpenSSH servers could only talk to
|
||||
* wolfSSL OpenSSH clients because there was a bug in this flow that
|
||||
* happened to "cancel out" if both sides of the connection had the bug.
|
||||
*/
|
||||
enum {
|
||||
NUM_ENCRYPTIONS = 3,
|
||||
AAD_SIZE = 4
|
||||
};
|
||||
byte plainText1[] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
|
||||
0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
|
||||
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23
|
||||
};
|
||||
byte plainText2[] = {
|
||||
0x42, 0x49, 0x3b, 0x27, 0x03, 0x35, 0x59, 0x14, 0x41, 0x47, 0x37, 0x14,
|
||||
0x0e, 0x34, 0x0d, 0x28, 0x63, 0x09, 0x0a, 0x5b, 0x22, 0x57, 0x42, 0x22,
|
||||
0x0f, 0x5c, 0x1e, 0x53, 0x45, 0x15, 0x62, 0x08, 0x60, 0x43, 0x50, 0x2c
|
||||
};
|
||||
byte plainText3[] = {
|
||||
0x36, 0x0d, 0x2b, 0x09, 0x4a, 0x56, 0x3b, 0x4c, 0x21, 0x22, 0x58, 0x0e,
|
||||
0x5b, 0x57, 0x10
|
||||
};
|
||||
byte* plainTexts[NUM_ENCRYPTIONS] = {
|
||||
plainText1,
|
||||
plainText2,
|
||||
plainText3
|
||||
};
|
||||
const int plainTextSzs[NUM_ENCRYPTIONS] = {
|
||||
sizeof(plainText1),
|
||||
sizeof(plainText2),
|
||||
sizeof(plainText3)
|
||||
};
|
||||
byte aad1[AAD_SIZE] = {
|
||||
0x00, 0x00, 0x00, 0x01
|
||||
};
|
||||
byte aad2[AAD_SIZE] = {
|
||||
0x00, 0x00, 0x00, 0x10
|
||||
};
|
||||
byte aad3[AAD_SIZE] = {
|
||||
0x00, 0x00, 0x01, 0x00
|
||||
};
|
||||
byte* aads[NUM_ENCRYPTIONS] = {
|
||||
aad1,
|
||||
aad2,
|
||||
aad3
|
||||
};
|
||||
const byte iv[GCM_NONCE_MID_SZ] = {
|
||||
0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF
|
||||
};
|
||||
byte currentIv[GCM_NONCE_MID_SZ];
|
||||
const byte key[] = {
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
|
||||
0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
|
||||
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f
|
||||
};
|
||||
const byte expIvs[NUM_ENCRYPTIONS][GCM_NONCE_MID_SZ] = {
|
||||
{
|
||||
0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE,
|
||||
0xEF
|
||||
},
|
||||
{
|
||||
0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE,
|
||||
0xF0
|
||||
},
|
||||
{
|
||||
0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE,
|
||||
0xF1
|
||||
}
|
||||
};
|
||||
const byte expTags[NUM_ENCRYPTIONS][AES_BLOCK_SIZE] = {
|
||||
{
|
||||
0x65, 0x4F, 0xF7, 0xA0, 0xBB, 0x7B, 0x90, 0xB7, 0x9C, 0xC8, 0x14,
|
||||
0x3D, 0x32, 0x18, 0x34, 0xA9
|
||||
},
|
||||
{
|
||||
0x50, 0x3A, 0x13, 0x8D, 0x91, 0x1D, 0xEC, 0xBB, 0xBA, 0x5B, 0x57,
|
||||
0xA2, 0xFD, 0x2D, 0x6B, 0x7F
|
||||
},
|
||||
{
|
||||
0x3B, 0xED, 0x18, 0x9C, 0xB3, 0xE3, 0x61, 0x1E, 0x11, 0xEB, 0x13,
|
||||
0x5B, 0xEC, 0x52, 0x49, 0x32,
|
||||
}
|
||||
};
|
||||
|
||||
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
|
||||
const EVP_CIPHER *init = EVP_aes_128_gcm();
|
||||
const byte expCipherText1[] = {
|
||||
0xCB, 0x93, 0x4F, 0xC8, 0x22, 0xE2, 0xC0, 0x35, 0xAA, 0x6B, 0x41, 0x15,
|
||||
0x17, 0x30, 0x2F, 0x97, 0x20, 0x74, 0x39, 0x28, 0xF8, 0xEB, 0xC5, 0x51,
|
||||
0x7B, 0xD9, 0x8A, 0x36, 0xB8, 0xDA, 0x24, 0x80, 0xE7, 0x9E, 0x09, 0xDE
|
||||
};
|
||||
const byte expCipherText2[] = {
|
||||
0xF9, 0x32, 0xE1, 0x87, 0x37, 0x0F, 0x04, 0xC1, 0xB5, 0x59, 0xF0, 0x45,
|
||||
0x3A, 0x0D, 0xA0, 0x26, 0xFF, 0xA6, 0x8D, 0x38, 0xFE, 0xB8, 0xE5, 0xC2,
|
||||
0x2A, 0x98, 0x4A, 0x54, 0x8F, 0x1F, 0xD6, 0x13, 0x03, 0xB2, 0x1B, 0xC0
|
||||
};
|
||||
const byte expCipherText3[] = {
|
||||
0xD0, 0x37, 0x59, 0x1C, 0x2F, 0x85, 0x39, 0x4D, 0xED, 0xC2, 0x32, 0x5B,
|
||||
0x80, 0x5E, 0x6B,
|
||||
};
|
||||
const byte* expCipherTexts[NUM_ENCRYPTIONS] = {
|
||||
expCipherText1,
|
||||
expCipherText2,
|
||||
expCipherText3
|
||||
};
|
||||
byte* cipherText;
|
||||
byte* calcPlainText;
|
||||
byte tag[AES_BLOCK_SIZE];
|
||||
EVP_CIPHER_CTX* encCtx = NULL;
|
||||
EVP_CIPHER_CTX* decCtx = NULL;
|
||||
int i, j, outl;
|
||||
|
||||
printf(testingFmt, "IncCtr");
|
||||
printf(testingFmt, "test_evp_cipher_aes_gcm");
|
||||
|
||||
AssertNotNull(ctx);
|
||||
wolfSSL_EVP_CIPHER_CTX_init(ctx);
|
||||
AssertIntEQ(EVP_CipherInit(ctx, init, key, iv, 1), WOLFSSL_SUCCESS);
|
||||
/****************************************************/
|
||||
for (i = 0; i < 3; ++i) {
|
||||
AssertNotNull(encCtx = EVP_CIPHER_CTX_new());
|
||||
AssertNotNull(decCtx = EVP_CIPHER_CTX_new());
|
||||
|
||||
AssertIntEQ(wolfSSL_EVP_CIPHER_CTX_ctrl(ctx, type, arg, ptr), WOLFSSL_SUCCESS);
|
||||
/* First iteration, set key before IV. */
|
||||
if (i == 0) {
|
||||
AssertIntEQ(EVP_CipherInit(encCtx, EVP_aes_256_gcm(), key, NULL, 1),
|
||||
SSL_SUCCESS);
|
||||
AssertIntEQ(EVP_CipherInit(encCtx, NULL, NULL, iv, 1),
|
||||
SSL_SUCCESS);
|
||||
AssertIntEQ(EVP_CipherInit(decCtx, EVP_aes_256_gcm(), key, NULL, 0),
|
||||
SSL_SUCCESS);
|
||||
AssertIntEQ(EVP_CipherInit(decCtx, NULL, NULL, iv, 0),
|
||||
SSL_SUCCESS);
|
||||
}
|
||||
/* Second iteration, IV before key. */
|
||||
else {
|
||||
AssertIntEQ(EVP_CipherInit(encCtx, EVP_aes_256_gcm(), NULL, iv, 1),
|
||||
SSL_SUCCESS);
|
||||
AssertIntEQ(EVP_CipherInit(encCtx, NULL, key, NULL, 1),
|
||||
SSL_SUCCESS);
|
||||
AssertIntEQ(EVP_CipherInit(decCtx, EVP_aes_256_gcm(), NULL, iv, 0),
|
||||
SSL_SUCCESS);
|
||||
AssertIntEQ(EVP_CipherInit(decCtx, NULL, key, NULL, 0),
|
||||
SSL_SUCCESS);
|
||||
}
|
||||
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
/*
|
||||
* EVP_CTRL_GCM_IV_GEN should fail if EVP_CTRL_GCM_SET_IV_FIXED hasn't
|
||||
* been issued first.
|
||||
*/
|
||||
AssertIntEQ(EVP_CIPHER_CTX_ctrl(encCtx, EVP_CTRL_GCM_IV_GEN, -1,
|
||||
currentIv), SSL_FAILURE);
|
||||
|
||||
AssertIntEQ(EVP_CIPHER_CTX_ctrl(encCtx, EVP_CTRL_GCM_SET_IV_FIXED, -1,
|
||||
(void*)iv), SSL_SUCCESS);
|
||||
AssertIntEQ(EVP_CIPHER_CTX_ctrl(decCtx, EVP_CTRL_GCM_SET_IV_FIXED, -1,
|
||||
(void*)iv), SSL_SUCCESS);
|
||||
|
||||
for (j = 0; j < NUM_ENCRYPTIONS; ++j) {
|
||||
/*************** Encrypt ***************/
|
||||
AssertIntEQ(EVP_CIPHER_CTX_ctrl(encCtx, EVP_CTRL_GCM_IV_GEN, -1,
|
||||
currentIv), SSL_SUCCESS);
|
||||
/* Check current IV against expected. */
|
||||
AssertIntEQ(XMEMCMP(currentIv, expIvs[j], GCM_NONCE_MID_SZ), 0);
|
||||
|
||||
/* Add AAD. */
|
||||
if (i == 2) {
|
||||
/* Test streaming API. */
|
||||
AssertIntEQ(EVP_CipherUpdate(encCtx, NULL, &outl, aads[j],
|
||||
AAD_SIZE), SSL_SUCCESS);
|
||||
}
|
||||
else {
|
||||
AssertIntEQ(EVP_Cipher(encCtx, NULL, aads[j], AAD_SIZE),
|
||||
AAD_SIZE);
|
||||
}
|
||||
|
||||
AssertNotNull(cipherText = (byte*)XMALLOC(plainTextSzs[j], NULL,
|
||||
DYNAMIC_TYPE_TMP_BUFFER));
|
||||
|
||||
/* Encrypt plaintext. */
|
||||
if (i == 2){
|
||||
AssertIntEQ(EVP_CipherUpdate(encCtx, cipherText, &outl,
|
||||
plainTexts[j], plainTextSzs[j]),
|
||||
SSL_SUCCESS);
|
||||
}
|
||||
else {
|
||||
AssertIntEQ(EVP_Cipher(encCtx, cipherText, plainTexts[j],
|
||||
plainTextSzs[j]), plainTextSzs[j]);
|
||||
}
|
||||
|
||||
if (i == 2) {
|
||||
AssertIntEQ(EVP_CipherFinal(encCtx, cipherText, &outl),
|
||||
SSL_SUCCESS);
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* Calling EVP_Cipher with NULL input and output for AES-GCM is
|
||||
* akin to calling EVP_CipherFinal.
|
||||
*/
|
||||
AssertIntGE(EVP_Cipher(encCtx, NULL, NULL, 0), 0);
|
||||
}
|
||||
|
||||
/* Check ciphertext against expected. */
|
||||
AssertIntEQ(XMEMCMP(cipherText, expCipherTexts[j], plainTextSzs[j]),
|
||||
0);
|
||||
|
||||
/* Get and check tag against expected. */
|
||||
AssertIntEQ(EVP_CIPHER_CTX_ctrl(encCtx, EVP_CTRL_GCM_GET_TAG,
|
||||
sizeof(tag), tag), SSL_SUCCESS);
|
||||
AssertIntEQ(XMEMCMP(tag, expTags[j], sizeof(tag)), 0);
|
||||
|
||||
/*************** Decrypt ***************/
|
||||
AssertIntEQ(EVP_CIPHER_CTX_ctrl(decCtx, EVP_CTRL_GCM_IV_GEN, -1,
|
||||
currentIv), SSL_SUCCESS);
|
||||
/* Check current IV against expected. */
|
||||
AssertIntEQ(XMEMCMP(currentIv, expIvs[j], GCM_NONCE_MID_SZ), 0);
|
||||
|
||||
/* Add AAD. */
|
||||
if (i == 2) {
|
||||
/* Test streaming API. */
|
||||
AssertIntEQ(EVP_CipherUpdate(decCtx, NULL, &outl, aads[j],
|
||||
AAD_SIZE), SSL_SUCCESS);
|
||||
}
|
||||
else {
|
||||
AssertIntEQ(EVP_Cipher(decCtx, NULL, aads[j], AAD_SIZE),
|
||||
AAD_SIZE);
|
||||
}
|
||||
|
||||
/* Set expected tag. */
|
||||
AssertIntEQ(EVP_CIPHER_CTX_ctrl(decCtx, EVP_CTRL_GCM_SET_TAG,
|
||||
sizeof(tag), tag), SSL_SUCCESS);
|
||||
|
||||
/* Decrypt ciphertext. */
|
||||
AssertNotNull(calcPlainText = (byte*)XMALLOC(plainTextSzs[j], NULL,
|
||||
DYNAMIC_TYPE_TMP_BUFFER));
|
||||
if (i == 2){
|
||||
AssertIntEQ(EVP_CipherUpdate(decCtx, calcPlainText, &outl,
|
||||
cipherText, plainTextSzs[j]),
|
||||
SSL_SUCCESS);
|
||||
}
|
||||
else {
|
||||
/* This first EVP_Cipher call will check the tag, too. */
|
||||
AssertIntEQ(EVP_Cipher(decCtx, calcPlainText, cipherText,
|
||||
plainTextSzs[j]), plainTextSzs[j]);
|
||||
}
|
||||
|
||||
if (i == 2) {
|
||||
AssertIntEQ(EVP_CipherFinal(decCtx, calcPlainText, &outl),
|
||||
SSL_SUCCESS);
|
||||
}
|
||||
else {
|
||||
AssertIntGE(EVP_Cipher(decCtx, NULL, NULL, 0), 0);
|
||||
}
|
||||
|
||||
/* Check plaintext against expected. */
|
||||
AssertIntEQ(XMEMCMP(calcPlainText, plainTexts[j], plainTextSzs[j]),
|
||||
0);
|
||||
|
||||
XFREE(cipherText, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
XFREE(calcPlainText, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
}
|
||||
|
||||
EVP_CIPHER_CTX_free(encCtx);
|
||||
EVP_CIPHER_CTX_free(decCtx);
|
||||
}
|
||||
|
||||
printf(resultFmt, passed);
|
||||
#endif
|
||||
}
|
||||
@ -54485,7 +54737,7 @@ void ApiTest(void)
|
||||
test_wolfSSL_EVP_BytesToKey();
|
||||
test_wolfSSL_EVP_PKEY_param_check();
|
||||
test_wolfSSL_QT_EVP_PKEY_CTX_free();
|
||||
test_IncCtr();
|
||||
test_evp_cipher_aes_gcm();
|
||||
test_wolfSSL_OBJ_ln();
|
||||
test_wolfSSL_OBJ_sn();
|
||||
test_wolfSSL_TXT_DB();
|
||||
|
@ -824,17 +824,36 @@ static int checkPad(WOLFSSL_EVP_CIPHER_CTX *ctx, unsigned char *buff)
|
||||
return ctx->block_size - n;
|
||||
}
|
||||
|
||||
int wolfSSL_EVP_CipherFinal(WOLFSSL_EVP_CIPHER_CTX *ctx,
|
||||
unsigned char *out, int *outl)
|
||||
#if defined(HAVE_AESGCM) && ((!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) \
|
||||
|| FIPS_VERSION_GE(2,0))
|
||||
static WC_INLINE void IncCtr(byte* ctr, word32 ctrSz)
|
||||
{
|
||||
int i;
|
||||
for (i = ctrSz-1; i >= 0; i--) {
|
||||
if (++ctr[i])
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_AESGCM && ((!HAVE_FIPS && !HAVE_SELFTEST) ||
|
||||
* HAVE_FIPS_VERSION >= 2 */
|
||||
|
||||
int wolfSSL_EVP_CipherFinal(WOLFSSL_EVP_CIPHER_CTX *ctx, unsigned char *out,
|
||||
int *outl)
|
||||
{
|
||||
int fl;
|
||||
int ret = WOLFSSL_SUCCESS;
|
||||
#if defined(HAVE_AESGCM) && ((!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) \
|
||||
|| FIPS_VERSION_GE(2,0))
|
||||
byte tmp = 0;
|
||||
#endif
|
||||
|
||||
if (!ctx || !outl)
|
||||
return WOLFSSL_FAILURE;
|
||||
|
||||
WOLFSSL_ENTER("wolfSSL_EVP_CipherFinal");
|
||||
switch (ctx->cipherType) {
|
||||
#if !defined(NO_AES) && defined(HAVE_AESGCM)
|
||||
#if defined(HAVE_AESGCM) && ((!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) \
|
||||
|| FIPS_VERSION_GE(2,0))
|
||||
case AES_128_GCM_TYPE:
|
||||
case AES_192_GCM_TYPE:
|
||||
case AES_256_GCM_TYPE:
|
||||
@ -864,6 +883,12 @@ int wolfSSL_EVP_CipherFinal(WOLFSSL_EVP_CIPHER_CTX *ctx,
|
||||
XFREE(ctx->gcmBuffer, NULL, DYNAMIC_TYPE_OPENSSL);
|
||||
ctx->gcmBuffer = NULL;
|
||||
ctx->gcmBufferLen = 0;
|
||||
|
||||
if (ctx->gcmIncIv) {
|
||||
IncCtr((byte*)ctx->cipher.aes.reg,
|
||||
ctx->cipher.aes.nonceSz);
|
||||
ctx->gcmIncIv = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
*outl = 0;
|
||||
@ -878,18 +903,41 @@ int wolfSSL_EVP_CipherFinal(WOLFSSL_EVP_CIPHER_CTX *ctx,
|
||||
else {
|
||||
ret = wc_AesGcmDecryptFinal(&ctx->cipher.aes, ctx->authTag,
|
||||
ctx->authTagSz);
|
||||
if (ctx->gcmIncIv) {
|
||||
IncCtr((byte*)ctx->cipher.aes.reg, ctx->cipher.aes.nonceSz);
|
||||
}
|
||||
}
|
||||
if (ret == 0) {
|
||||
ret = WOLFSSL_SUCCESS;
|
||||
/* Reinitialize for subsequent wolfSSL_EVP_Cipher calls. */
|
||||
if (wc_AesGcmInit(&ctx->cipher.aes, NULL, 0,
|
||||
(byte*)ctx->cipher.aes.reg,
|
||||
ctx->ivSz) != 0) {
|
||||
WOLFSSL_MSG("wc_AesGcmInit failed");
|
||||
ret = WOLFSSL_FAILURE;
|
||||
}
|
||||
else {
|
||||
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);
|
||||
if (ret == WOLFSSL_SUCCESS) {
|
||||
if (ctx->gcmIncIv) {
|
||||
ctx->gcmIncIv = 0;
|
||||
}
|
||||
else {
|
||||
/* Clear IV, since IV reuse is not recommended for AES GCM. */
|
||||
XMEMSET(ctx->iv, 0, AES_BLOCK_SIZE);
|
||||
}
|
||||
if (wolfSSL_StoreExternalIV(ctx) != WOLFSSL_SUCCESS) {
|
||||
ret = WOLFSSL_FAILURE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif /* !NO_AES && HAVE_AESGCM */
|
||||
#endif /* HAVE_AESGCM && ((!HAVE_FIPS && !HAVE_SELFTEST) ||
|
||||
* HAVE_FIPS_VERSION >= 2 */
|
||||
#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
|
||||
case CHACHA20_POLY1305_TYPE:
|
||||
if (wc_ChaCha20Poly1305_Final(&ctx->cipher.chachaPoly,
|
||||
@ -962,9 +1010,33 @@ int wolfSSL_EVP_CipherFinal(WOLFSSL_EVP_CIPHER_CTX *ctx,
|
||||
}
|
||||
|
||||
if (ret == WOLFSSL_SUCCESS) {
|
||||
#if defined(HAVE_AESGCM) && ((!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) \
|
||||
|| FIPS_VERSION_GE(2,0))
|
||||
/*
|
||||
* This flag needs to retain its value between wolfSSL_EVP_CipherFinal
|
||||
* calls. wolfSSL_EVP_CipherInit will clear it, so we save and restore
|
||||
* it here.
|
||||
*/
|
||||
if (ctx->cipherType == AES_128_GCM_TYPE ||
|
||||
ctx->cipherType == AES_192_GCM_TYPE ||
|
||||
ctx->cipherType == AES_256_GCM_TYPE) {
|
||||
tmp = ctx->gcmIvGenEnable;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* reset cipher state after final */
|
||||
ret = wolfSSL_EVP_CipherInit(ctx, NULL, NULL, NULL, -1);
|
||||
|
||||
#if defined(HAVE_AESGCM) && ((!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) \
|
||||
|| FIPS_VERSION_GE(2,0))
|
||||
if (ctx->cipherType == AES_128_GCM_TYPE ||
|
||||
ctx->cipherType == AES_192_GCM_TYPE ||
|
||||
ctx->cipherType == AES_256_GCM_TYPE) {
|
||||
ctx->gcmIvGenEnable = tmp;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -5287,17 +5359,6 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD* type)
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(HAVE_AESGCM) && !defined(HAVE_SELFTEST)
|
||||
static WC_INLINE void IncCtr(byte* ctr, word32 ctrSz)
|
||||
{
|
||||
int i;
|
||||
for (i = ctrSz-1; i >= 0; i--) {
|
||||
if (++ctr[i])
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* This function allows cipher specific parameters to be
|
||||
determined and set. */
|
||||
int wolfSSL_EVP_CIPHER_CTX_ctrl(WOLFSSL_EVP_CIPHER_CTX *ctx, int type, \
|
||||
@ -5381,35 +5442,58 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD* type)
|
||||
break;
|
||||
}
|
||||
}
|
||||
#ifdef HAVE_AESGCM
|
||||
if (ret == WOLFSSL_SUCCESS) {
|
||||
/*
|
||||
* OpenSSL requires that a EVP_CTRL_AEAD_SET_IV_FIXED
|
||||
* command be issued before a EVP_CTRL_GCM_IV_GEN command.
|
||||
* This flag is used to enforce that.
|
||||
*/
|
||||
ctx->gcmIvGenEnable = 1;
|
||||
}
|
||||
#endif
|
||||
#endif /* !WC_NO_RNG */
|
||||
break;
|
||||
#if defined(HAVE_AESGCM) && !defined(_WIN32) && !defined(HAVE_SELFTEST) && \
|
||||
(!defined(HAVE_FIPS) || FIPS_VERSION_GE(2,0))
|
||||
/*
|
||||
* Using EVP_CTRL_GCM_IV_GEN is a way to do AES-GCM encrypt/decrypt
|
||||
* multiple times with EVP_Cipher without having to call
|
||||
* EVP_CipherInit between each iteration. The IV is incremented for
|
||||
* each subsequent EVP_Cipher call to prevent IV reuse.
|
||||
*/
|
||||
case EVP_CTRL_GCM_IV_GEN:
|
||||
if ((ctx->flags & WOLFSSL_EVP_CIPH_FLAG_AEAD_CIPHER) == 0)
|
||||
break;
|
||||
if (!ctx->gcmIvGenEnable) {
|
||||
WOLFSSL_MSG("Must use EVP_CTRL_AEAD_SET_IV_FIXED before "
|
||||
"EVP_CTRL_GCM_IV_GEN");
|
||||
break;
|
||||
}
|
||||
if (ctx->cipher.aes.keylen == 0 || ctx->ivSz == 0) {
|
||||
WOLFSSL_MSG("Key or IV not set");
|
||||
break;
|
||||
}
|
||||
if (wc_AesGcmSetExtIV(&ctx->cipher.aes, ctx->iv,
|
||||
ctx->ivSz) != 0) {
|
||||
WOLFSSL_MSG("wc_AesGcmSetIV failed");
|
||||
if (ptr == NULL) {
|
||||
WOLFSSL_MSG("Destination buffer for IV bytes NULL.");
|
||||
break;
|
||||
}
|
||||
#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");
|
||||
break;
|
||||
if (arg <= 0 || arg > ctx->ivSz) {
|
||||
XMEMCPY(ptr, ctx->iv, ctx->ivSz);
|
||||
}
|
||||
#endif /* WOLFSSL_AESGCM_STREAM */
|
||||
/* OpenSSL increments the IV. Not sure why */
|
||||
IncCtr(ctx->iv, ctx->ivSz);
|
||||
/* Clear any leftover AAD. */
|
||||
if (ctx->gcmAuthIn != NULL)
|
||||
XMEMSET(ctx->gcmAuthIn, 0, ctx->gcmAuthInSz);
|
||||
ctx->gcmAuthInSz = 0;
|
||||
else {
|
||||
/*
|
||||
* Copy the last "arg" bytes of ctx->iv into the buffer at
|
||||
* "ptr." Not sure why OpenSSL does this, but it does.
|
||||
*/
|
||||
XMEMCPY(ptr, ctx->iv + ctx->ivSz - arg, arg);
|
||||
}
|
||||
|
||||
/*
|
||||
* The gcmIncIV flag indicates that the IV should be incremented
|
||||
* after the next cipher operation.
|
||||
*/
|
||||
ctx->gcmIncIv = 1;
|
||||
ret = WOLFSSL_SUCCESS;
|
||||
break;
|
||||
#endif /* HAVE_AESGCM && !_WIN32 && !HAVE_SELFTEST && (!HAVE_FIPS ||
|
||||
@ -5498,6 +5582,8 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD* type)
|
||||
ctx->gcmAuthIn = NULL;
|
||||
}
|
||||
ctx->gcmAuthInSz = 0;
|
||||
ctx->gcmIvGenEnable = 0;
|
||||
ctx->gcmIncIv = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -5608,8 +5694,190 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD* type)
|
||||
#endif /* AES_ANY_SIZE && AES_SET_KEY */
|
||||
#endif /* NO_AES */
|
||||
|
||||
#if defined(HAVE_AESGCM) && ((!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) \
|
||||
|| FIPS_VERSION_GE(2,0))
|
||||
static int EvpCipherInitAesGCM(WOLFSSL_EVP_CIPHER_CTX* ctx,
|
||||
const WOLFSSL_EVP_CIPHER* type,
|
||||
const byte* key, const byte* iv, int enc)
|
||||
{
|
||||
int ret = WOLFSSL_SUCCESS;
|
||||
|
||||
ctx->block_size = AES_BLOCK_SIZE;
|
||||
ctx->authTagSz = AES_BLOCK_SIZE;
|
||||
if (ctx->ivSz == 0) {
|
||||
ctx->ivSz = GCM_NONCE_MID_SZ;
|
||||
}
|
||||
ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE;
|
||||
ctx->flags |= WOLFSSL_EVP_CIPH_GCM_MODE |
|
||||
WOLFSSL_EVP_CIPH_FLAG_AEAD_CIPHER;
|
||||
if (enc == 0 || enc == 1) {
|
||||
ctx->enc = enc ? 1 : 0;
|
||||
}
|
||||
|
||||
#ifdef WOLFSSL_AES_128
|
||||
if (ctx->cipherType == AES_128_GCM_TYPE ||
|
||||
(type && EVP_CIPHER_TYPE_MATCHES(type, EVP_AES_128_GCM))) {
|
||||
WOLFSSL_MSG("EVP_AES_128_GCM");
|
||||
ctx->cipherType = AES_128_GCM_TYPE;
|
||||
ctx->keyLen = AES_128_KEY_SIZE;
|
||||
}
|
||||
#endif
|
||||
#ifdef WOLFSSL_AES_192
|
||||
if (ctx->cipherType == AES_192_GCM_TYPE ||
|
||||
(type && EVP_CIPHER_TYPE_MATCHES(type, EVP_AES_192_GCM))) {
|
||||
WOLFSSL_MSG("EVP_AES_192_GCM");
|
||||
ctx->cipherType = AES_192_GCM_TYPE;
|
||||
ctx->keyLen = AES_192_KEY_SIZE;
|
||||
}
|
||||
#endif
|
||||
#ifdef WOLFSSL_AES_256
|
||||
if (ctx->cipherType == AES_256_GCM_TYPE ||
|
||||
(type && EVP_CIPHER_TYPE_MATCHES(type, EVP_AES_256_GCM))) {
|
||||
WOLFSSL_MSG("EVP_AES_256_GCM");
|
||||
ctx->cipherType = AES_256_GCM_TYPE;
|
||||
ctx->keyLen = AES_256_KEY_SIZE;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef WOLFSSL_AESGCM_STREAM
|
||||
if (ret == WOLFSSL_SUCCESS && key &&
|
||||
wc_AesGcmSetKey(&ctx->cipher.aes, key, ctx->keyLen)) {
|
||||
WOLFSSL_MSG("wc_AesGcmSetKey() failed");
|
||||
ret = WOLFSSL_FAILURE;
|
||||
}
|
||||
#endif /* !WOLFSSL_AESGCM_STREAM */
|
||||
if (ret == WOLFSSL_SUCCESS && iv &&
|
||||
wc_AesGcmSetExtIV(&ctx->cipher.aes, iv, ctx->ivSz)) {
|
||||
WOLFSSL_MSG("wc_AesGcmSetExtIV() failed");
|
||||
ret = WOLFSSL_FAILURE;
|
||||
}
|
||||
#ifdef WOLFSSL_AESGCM_STREAM
|
||||
/*
|
||||
* Initialize with key and IV if available. wc_AesGcmInit will fail
|
||||
* if called with IV only and no key has been set.
|
||||
*/
|
||||
if (ret == WOLFSSL_SUCCESS &&
|
||||
(key || (iv && ctx->cipher.aes.gcmKeySet)) &&
|
||||
wc_AesGcmInit(&ctx->cipher.aes, key,
|
||||
(key == NULL) ? 0 : ctx->keyLen, iv,
|
||||
(iv == NULL) ? 0 : ctx->ivSz) != 0) {
|
||||
WOLFSSL_MSG("wc_AesGcmInit() failed");
|
||||
ret = WOLFSSL_FAILURE;
|
||||
}
|
||||
#endif /* WOLFSSL_AESGCM_STREAM */
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int EvpCipherAesGCM(WOLFSSL_EVP_CIPHER_CTX* ctx, byte* dst,
|
||||
byte* src, word32 len)
|
||||
{
|
||||
int ret = WOLFSSL_FAILURE;
|
||||
|
||||
#ifndef WOLFSSL_AESGCM_STREAM
|
||||
/* No destination means only AAD. */
|
||||
if (src != NULL && dst == NULL) {
|
||||
ret = wolfSSL_EVP_CipherUpdate_GCM_AAD(ctx, src, len);
|
||||
}
|
||||
else if (src != NULL && dst != NULL) {
|
||||
if (ctx->enc) {
|
||||
ret = wc_AesGcmEncrypt(&ctx->cipher.aes, dst, src,
|
||||
len, ctx->iv, ctx->ivSz, ctx->authTag,
|
||||
ctx->authTagSz, ctx->gcmAuthIn,
|
||||
ctx->gcmAuthInSz);
|
||||
}
|
||||
else {
|
||||
ret = wc_AesGcmDecrypt(&ctx->cipher.aes, dst, src,
|
||||
len, ctx->iv, ctx->ivSz, ctx->authTag,
|
||||
ctx->authTagSz, ctx->gcmAuthIn,
|
||||
ctx->gcmAuthInSz);
|
||||
}
|
||||
if (ctx->gcmIncIv) {
|
||||
IncCtr((byte*)ctx->cipher.aes.reg,
|
||||
ctx->cipher.aes.nonceSz);
|
||||
ctx->gcmIncIv = 0;
|
||||
}
|
||||
}
|
||||
#else
|
||||
/*
|
||||
* No need to call wc_AesGcmInit. Should have been called by
|
||||
* wolfSSL_EVP_CipherInit.
|
||||
*/
|
||||
/* NULL dst and non-NULL src means only AAD. */
|
||||
if (src != NULL && 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 plain/cipher text. */
|
||||
else if (src != NULL && dst != NULL) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* src == NULL is analogous to other "final"-type functions
|
||||
* (e.g. EVP_CipherFinal). Calculates tag on encrypt
|
||||
* and checks tag on decrypt.
|
||||
*/
|
||||
else {
|
||||
if (ctx->enc) {
|
||||
/* Calculate authentication tag. */
|
||||
ret = wc_AesGcmEncryptFinal(&ctx->cipher.aes,
|
||||
ctx->authTag, ctx->authTagSz);
|
||||
/*
|
||||
* wc_AesGcmEncryptFinal increments the IV in
|
||||
* ctx->cipher.aes.reg, so we don't call IncCtr here.
|
||||
*/
|
||||
}
|
||||
else {
|
||||
/* Calculate authentication tag and compare. */
|
||||
ret = wc_AesGcmDecryptFinal(&ctx->cipher.aes,
|
||||
ctx->authTag, ctx->authTagSz);
|
||||
if (ctx->gcmIncIv) {
|
||||
IncCtr((byte*)ctx->cipher.aes.reg,
|
||||
ctx->cipher.aes.nonceSz);
|
||||
}
|
||||
}
|
||||
/* Reinitialize for subsequent wolfSSL_EVP_Cipher calls. */
|
||||
if (wc_AesGcmInit(&ctx->cipher.aes, NULL, 0,
|
||||
(byte*)ctx->cipher.aes.reg,
|
||||
ctx->ivSz) != 0) {
|
||||
WOLFSSL_MSG("wc_AesGcmInit failed");
|
||||
return WOLFSSL_FATAL_ERROR;
|
||||
}
|
||||
ctx->gcmIncIv = 0;
|
||||
}
|
||||
#endif /* WOLFSSL_AESGCM_STREAM */
|
||||
if (src == NULL) {
|
||||
/*
|
||||
* Clear any leftover AAD on final (final is when src is
|
||||
* NULL).
|
||||
*/
|
||||
XMEMSET(ctx->gcmAuthIn, 0, ctx->gcmAuthInSz);
|
||||
ctx->gcmAuthInSz = 0;
|
||||
}
|
||||
if (ret == 0) {
|
||||
ret = len;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* HAVE_AESGCM && ((!HAVE_FIPS && !HAVE_SELFTEST) ||
|
||||
* HAVE_FIPS_VERSION >= 2 */
|
||||
|
||||
/* return WOLFSSL_SUCCESS on ok, 0 on failure to match API compatibility */
|
||||
int wolfSSL_EVP_CipherInit(WOLFSSL_EVP_CIPHER_CTX* ctx,
|
||||
int wolfSSL_EVP_CipherInit(WOLFSSL_EVP_CIPHER_CTX* ctx,
|
||||
const WOLFSSL_EVP_CIPHER* type, const byte* key,
|
||||
const byte* iv, int enc)
|
||||
{
|
||||
@ -5648,6 +5916,8 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD* type)
|
||||
ctx->gcmAuthIn = NULL;
|
||||
}
|
||||
ctx->gcmAuthInSz = 0;
|
||||
ctx->gcmIvGenEnable = 0;
|
||||
ctx->gcmIncIv = 0;
|
||||
#endif
|
||||
|
||||
#ifndef NO_AES
|
||||
@ -5732,125 +6002,29 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD* type)
|
||||
}
|
||||
#endif /* WOLFSSL_AES_256 */
|
||||
#endif /* HAVE_AES_CBC || WOLFSSL_AES_DIRECT */
|
||||
#if (!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) || \
|
||||
(defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2))
|
||||
#ifdef HAVE_AESGCM
|
||||
#if defined(HAVE_AESGCM) && ((!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) \
|
||||
|| FIPS_VERSION_GE(2,0))
|
||||
if (
|
||||
#ifdef WOLFSSL_AES_128
|
||||
if (ctx->cipherType == AES_128_GCM_TYPE ||
|
||||
(type && EVP_CIPHER_TYPE_MATCHES(type, EVP_AES_128_GCM))) {
|
||||
WOLFSSL_MSG("EVP_AES_128_GCM");
|
||||
ctx->cipherType = AES_128_GCM_TYPE;
|
||||
ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE;
|
||||
ctx->flags |= WOLFSSL_EVP_CIPH_GCM_MODE |
|
||||
WOLFSSL_EVP_CIPH_FLAG_AEAD_CIPHER;
|
||||
ctx->keyLen = 16;
|
||||
ctx->block_size = AES_BLOCK_SIZE;
|
||||
ctx->authTagSz = AES_BLOCK_SIZE;
|
||||
if (ctx->ivSz == 0) {
|
||||
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, ctx->ivSz)) {
|
||||
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 : ctx->ivSz) != 0) {
|
||||
WOLFSSL_MSG("wc_AesGcmInit() failed");
|
||||
return WOLFSSL_FAILURE;
|
||||
}
|
||||
#endif /* WOLFSSL_AESGCM_STREAM */
|
||||
if (enc == 0 || enc == 1)
|
||||
ctx->enc = enc ? 1 : 0;
|
||||
}
|
||||
#endif /* WOLFSSL_AES_128 */
|
||||
ctx->cipherType == AES_128_GCM_TYPE ||
|
||||
(type && EVP_CIPHER_TYPE_MATCHES(type, EVP_AES_128_GCM))
|
||||
#endif
|
||||
#ifdef WOLFSSL_AES_192
|
||||
if (ctx->cipherType == AES_192_GCM_TYPE ||
|
||||
(type && EVP_CIPHER_TYPE_MATCHES(type, EVP_AES_192_GCM))) {
|
||||
WOLFSSL_MSG("EVP_AES_192_GCM");
|
||||
ctx->cipherType = AES_192_GCM_TYPE;
|
||||
ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE;
|
||||
ctx->flags |= WOLFSSL_EVP_CIPH_GCM_MODE |
|
||||
WOLFSSL_EVP_CIPH_FLAG_AEAD_CIPHER;
|
||||
ctx->keyLen = 24;
|
||||
ctx->block_size = AES_BLOCK_SIZE;
|
||||
ctx->authTagSz = AES_BLOCK_SIZE;
|
||||
if (ctx->ivSz == 0) {
|
||||
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, ctx->ivSz)) {
|
||||
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 : ctx->ivSz) != 0) {
|
||||
WOLFSSL_MSG("wc_AesGcmInit() failed");
|
||||
return WOLFSSL_FAILURE;
|
||||
}
|
||||
#endif /* WOLFSSL_AESGCM_STREAM */
|
||||
if (enc == 0 || enc == 1)
|
||||
ctx->enc = enc ? 1 : 0;
|
||||
}
|
||||
#endif /* WOLFSSL_AES_192 */
|
||||
|| ctx->cipherType == AES_192_GCM_TYPE ||
|
||||
(type && EVP_CIPHER_TYPE_MATCHES(type, EVP_AES_192_GCM))
|
||||
#endif
|
||||
#ifdef WOLFSSL_AES_256
|
||||
if (ctx->cipherType == AES_256_GCM_TYPE ||
|
||||
(type && EVP_CIPHER_TYPE_MATCHES(type, EVP_AES_256_GCM))) {
|
||||
WOLFSSL_MSG("EVP_AES_256_GCM");
|
||||
ctx->cipherType = AES_256_GCM_TYPE;
|
||||
ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE;
|
||||
ctx->flags |= WOLFSSL_EVP_CIPH_GCM_MODE |
|
||||
WOLFSSL_EVP_CIPH_FLAG_AEAD_CIPHER;
|
||||
ctx->keyLen = 32;
|
||||
ctx->block_size = AES_BLOCK_SIZE;
|
||||
ctx->authTagSz = AES_BLOCK_SIZE;
|
||||
if (ctx->ivSz == 0) {
|
||||
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");
|
||||
|| ctx->cipherType == AES_256_GCM_TYPE ||
|
||||
(type && EVP_CIPHER_TYPE_MATCHES(type, EVP_AES_256_GCM))
|
||||
#endif
|
||||
) {
|
||||
if (EvpCipherInitAesGCM(ctx, type, key, iv, enc)
|
||||
!= WOLFSSL_SUCCESS) {
|
||||
return WOLFSSL_FAILURE;
|
||||
}
|
||||
#endif /* !WOLFSSL_AESGCM_STREAM */
|
||||
if (iv && wc_AesGcmSetExtIV(&ctx->cipher.aes, iv, ctx->ivSz)) {
|
||||
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 : ctx->ivSz) != 0) {
|
||||
WOLFSSL_MSG("wc_AesGcmInit() failed");
|
||||
return WOLFSSL_FAILURE;
|
||||
}
|
||||
#endif /* WOLFSSL_AESGCM_STREAM */
|
||||
if (enc == 0 || enc == 1)
|
||||
ctx->enc = enc ? 1 : 0;
|
||||
}
|
||||
#endif /* WOLFSSL_AES_256 */
|
||||
#endif /* HAVE_AESGCM */
|
||||
#endif /* (!HAVE_FIPS && !HAVE_SELFTEST) || HAVE_FIPS_VERSION >= 2 */
|
||||
#endif /* HAVE_AESGCM && ((!HAVE_FIPS && !HAVE_SELFTEST) ||
|
||||
* HAVE_FIPS_VERSION >= 2 */
|
||||
#ifdef WOLFSSL_AES_COUNTER
|
||||
#ifdef WOLFSSL_AES_128
|
||||
if (ctx->cipherType == AES_128_CTR_TYPE ||
|
||||
@ -6596,31 +6770,23 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD* type)
|
||||
|
||||
/* Return length on ok */
|
||||
int wolfSSL_EVP_Cipher(WOLFSSL_EVP_CIPHER_CTX* ctx, byte* dst, byte* src,
|
||||
word32 len)
|
||||
word32 len)
|
||||
{
|
||||
int ret = 0;
|
||||
int ret = WOLFSSL_FAILURE;
|
||||
|
||||
WOLFSSL_ENTER("wolfSSL_EVP_Cipher");
|
||||
|
||||
if (ctx == NULL) {
|
||||
WOLFSSL_MSG("Bad function argument");
|
||||
if (ctx == NULL || ((src == NULL || dst == NULL) &&
|
||||
(ctx->cipherType != AES_128_GCM_TYPE &&
|
||||
ctx->cipherType != AES_192_GCM_TYPE &&
|
||||
ctx->cipherType != AES_256_GCM_TYPE))) {
|
||||
WOLFSSL_MSG("Bad argument.");
|
||||
return WOLFSSL_FATAL_ERROR;
|
||||
}
|
||||
|
||||
if (src == NULL || dst == NULL) {
|
||||
if (src != NULL && dst == NULL &&
|
||||
(ctx->cipherType == AES_128_GCM_TYPE ||
|
||||
ctx->cipherType == AES_192_GCM_TYPE ||
|
||||
ctx->cipherType == AES_256_GCM_TYPE)) {
|
||||
WOLFSSL_MSG("Setting GCM AAD.");
|
||||
}
|
||||
else {
|
||||
WOLFSSL_MSG("Bad function argument");
|
||||
return WOLFSSL_FATAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->cipherType == 0xff) {
|
||||
WOLFSSL_MSG("no init");
|
||||
if (ctx->cipherType == WOLFSSL_EVP_CIPH_TYPE_INIT) {
|
||||
WOLFSSL_MSG("Cipher operation not initialized. Call "
|
||||
"wolfSSL_EVP_CipherInit.");
|
||||
return WOLFSSL_FATAL_ERROR;
|
||||
}
|
||||
|
||||
@ -6706,74 +6872,16 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD* type)
|
||||
break;
|
||||
#endif /* WOLFSSL_AES_XTS */
|
||||
|
||||
#ifdef HAVE_AESGCM
|
||||
#if defined(HAVE_AESGCM) && ((!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) \
|
||||
|| FIPS_VERSION_GE(2,0))
|
||||
case AES_128_GCM_TYPE :
|
||||
case AES_192_GCM_TYPE :
|
||||
case AES_256_GCM_TYPE :
|
||||
WOLFSSL_MSG("AES GCM");
|
||||
#ifndef WOLFSSL_AESGCM_STREAM
|
||||
/* No destination means only AAD. */
|
||||
if (!dst) {
|
||||
ret = wolfSSL_EVP_CipherUpdate_GCM_AAD(ctx, src, len);
|
||||
}
|
||||
else {
|
||||
if (ctx->enc)
|
||||
ret = wc_AesGcmEncrypt(&ctx->cipher.aes, dst, src,
|
||||
len, ctx->iv, ctx->ivSz, ctx->authTag,
|
||||
ctx->authTagSz, ctx->gcmAuthIn, ctx->gcmAuthInSz);
|
||||
else
|
||||
ret = wc_AesGcmDecrypt(&ctx->cipher.aes, dst, src,
|
||||
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;
|
||||
ret = EvpCipherAesGCM(ctx, dst, src, len);
|
||||
break;
|
||||
#endif /* HAVE_AESGCM */
|
||||
#endif /* HAVE_AESGCM && ((!HAVE_FIPS && !HAVE_SELFTEST) ||
|
||||
* HAVE_FIPS_VERSION >= 2 */
|
||||
#ifdef HAVE_AES_ECB
|
||||
case AES_128_ECB_TYPE :
|
||||
case AES_192_ECB_TYPE :
|
||||
|
@ -438,6 +438,10 @@ struct WOLFSSL_EVP_CIPHER_CTX {
|
||||
#endif
|
||||
int authTagSz;
|
||||
#endif
|
||||
#ifdef HAVE_AESGCM
|
||||
byte gcmIvGenEnable:1;
|
||||
byte gcmIncIv:1;
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user