separated TLS-AEAD and AES-GCM so TLS-AEAD can also use AES-CCM

This commit is contained in:
John Safranek
2013-01-14 15:59:53 -08:00
parent d9a8bfbb80
commit eb221238c2
7 changed files with 126 additions and 134 deletions

View File

@@ -198,12 +198,11 @@ void bench_aesgcm(void)
double start, total, persec; double start, total, persec;
int i; int i;
AesGcmSetKey(&enc, key, 16, iv); AesGcmSetKey(&enc, key, 16);
AesGcmSetExpIV(&enc, iv+4);
start = current_time(); start = current_time();
for(i = 0; i < megs; i++) for(i = 0; i < megs; i++)
AesGcmEncrypt(&enc, cipher, plain, sizeof(plain), AesGcmEncrypt(&enc, cipher, plain, sizeof(plain), iv, 12,
tag, 16, additional, 13); tag, 16, additional, 13);
total = current_time() - start; total = current_time() - start;
@@ -222,11 +221,11 @@ void bench_aesccm(void)
double start, total, persec; double start, total, persec;
int i; int i;
AesCcmSetKey(&enc, key, 16, iv, 12); AesCcmSetKey(&enc, key, 16);
start = current_time(); start = current_time();
for(i = 0; i < megs; i++) for(i = 0; i < megs; i++)
AesCcmEncrypt(&enc, cipher, plain, sizeof(plain), AesCcmEncrypt(&enc, cipher, plain, sizeof(plain), iv, 12,
tag, 16, additional, 13); tag, 16, additional, 13);
total = current_time() - start; total = current_time() - start;

View File

@@ -1807,8 +1807,6 @@ void AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
*/ */
enum { enum {
IMPLICIT_IV_SZ = 4,
EXPLICIT_IV_SZ = 8,
CTR_SZ = 4 CTR_SZ = 4
}; };
@@ -1834,36 +1832,6 @@ static INLINE void IncrementGcmCounter(byte* inOutCtr)
} }
/*
* The explicit IV is set by the caller. A common practice is to treat it as
* a sequence number seeded with a random number. The caller manages
* incrementing the explicit IV when appropriate.
*/
void AesGcmSetExpIV(Aes* aes, const byte* iv)
{
XMEMCPY((byte*)aes->reg + IMPLICIT_IV_SZ, iv, EXPLICIT_IV_SZ);
}
void AesGcmGetExpIV(Aes* aes, byte* iv)
{
XMEMCPY(iv, (byte*)aes->reg + IMPLICIT_IV_SZ, EXPLICIT_IV_SZ);
}
void AesGcmIncExpIV(Aes* aes)
{
int i;
byte* iv = (byte*)aes->reg + IMPLICIT_IV_SZ;
for (i = EXPLICIT_IV_SZ - 1; i >= 0; i--) {
if (++iv[i])
return;
}
}
#if defined(GCM_SMALL) || defined(GCM_TABLE) #if defined(GCM_SMALL) || defined(GCM_TABLE)
static INLINE void FlattenSzInBits(byte* buf, word32 sz) static INLINE void FlattenSzInBits(byte* buf, word32 sz)
@@ -1929,20 +1897,17 @@ static void GenerateM0(Aes* aes)
#endif /* GCM_TABLE */ #endif /* GCM_TABLE */
void AesGcmSetKey(Aes* aes, const byte* key, word32 len, void AesGcmSetKey(Aes* aes, const byte* key, word32 len)
const byte* implicitIV)
{ {
byte fullIV[AES_BLOCK_SIZE]; byte iv[AES_BLOCK_SIZE];
if (!((len == 16) || (len == 24) || (len == 32))) if (!((len == 16) || (len == 24) || (len == 32)))
return; return;
XMEMSET(fullIV, 0, AES_BLOCK_SIZE); XMEMSET(iv, 0, AES_BLOCK_SIZE);
XMEMCPY(fullIV, implicitIV, IMPLICIT_IV_SZ); AesSetKeyLocal(aes, key, len, iv, AES_ENCRYPTION);
AesSetKeyLocal(aes, key, len, fullIV, AES_ENCRYPTION);
XMEMSET(fullIV, 0, AES_BLOCK_SIZE); AesEncrypt(aes, iv, aes->H);
AesEncrypt(aes, fullIV, aes->H);
#ifdef GCM_TABLE #ifdef GCM_TABLE
GenerateM0(aes); GenerateM0(aes);
#endif /* GCM_TABLE */ #endif /* GCM_TABLE */
@@ -2449,6 +2414,7 @@ static void GHASH(Aes* aes, const byte* a, word32 aSz,
void AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, void AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz,
const byte* iv, word32 ivSz,
byte* authTag, word32 authTagSz, byte* authTag, word32 authTagSz,
const byte* authIn, word32 authInSz) const byte* authIn, word32 authInSz)
{ {
@@ -2461,9 +2427,8 @@ void AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz,
CYASSL_ENTER("AesGcmEncrypt"); CYASSL_ENTER("AesGcmEncrypt");
/* Initialize the counter with the MS 96 bits of IV, and the counter XMEMSET(ctr, 0, AES_BLOCK_SIZE);
* portion set to "1". */ XMEMCPY(ctr, iv, ivSz);
XMEMCPY(ctr, aes->reg, AES_BLOCK_SIZE);
InitGcmCounter(ctr); InitGcmCounter(ctr);
while (blocks--) { while (blocks--) {
@@ -2489,6 +2454,7 @@ void AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz,
int AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, int AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz,
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)
{ {
@@ -2501,9 +2467,8 @@ int AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz,
CYASSL_ENTER("AesGcmDecrypt"); CYASSL_ENTER("AesGcmDecrypt");
/* Initialize the counter with the MS 96 bits of IV, and the counter XMEMSET(ctr, 0, AES_BLOCK_SIZE);
* portion set to "1". */ XMEMCPY(ctr, iv, ivSz);
XMEMCPY(ctr, aes->reg, AES_BLOCK_SIZE);
InitGcmCounter(ctr); InitGcmCounter(ctr);
/* Calculate the authTag again using the received auth data and the /* Calculate the authTag again using the received auth data and the
@@ -2543,26 +2508,15 @@ int AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz,
#ifdef HAVE_AESCCM #ifdef HAVE_AESCCM
void AesCcmSetKey(Aes* aes, const byte* key, word32 keySz, void AesCcmSetKey(Aes* aes, const byte* key, word32 keySz)
const byte* implicitIV, word32 ivSz)
{ {
byte fullIV[AES_BLOCK_SIZE]; byte nonce[AES_BLOCK_SIZE];
if (!((keySz == 16) || (keySz == 24) || (keySz == 32))) if (!((keySz == 16) || (keySz == 24) || (keySz == 32)))
return; return;
if (ivSz > AES_BLOCK_SIZE - 2) { XMEMSET(nonce, 0, sizeof(nonce));
CYASSL_MSG("AES-CCM IV is too long"); AesSetKeyLocal(aes, key, keySz, nonce, AES_ENCRYPTION);
return;
}
XMEMSET(fullIV, 0, sizeof(fullIV));
XMEMCPY(fullIV + 1, implicitIV, ivSz);
AesSetKeyLocal(aes, key, keySz, fullIV, AES_ENCRYPTION);
aes->lenSz = AES_BLOCK_SIZE - 1 - ivSz;
XMEMSET(fullIV, 0, sizeof(fullIV));
} }
@@ -2641,18 +2595,20 @@ static INLINE void AesCcmCtrInc(byte* B, word32 lenSz)
void AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz, void AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz,
const byte* nonce, word32 nonceSz,
byte* authTag, word32 authTagSz, byte* authTag, word32 authTagSz,
const byte* authIn, word32 authInSz) const byte* authIn, word32 authInSz)
{ {
byte A[AES_BLOCK_SIZE]; byte A[AES_BLOCK_SIZE];
byte B[AES_BLOCK_SIZE]; byte B[AES_BLOCK_SIZE];
word32 i; word32 i, lenSz;
XMEMCPY(B, aes->reg, AES_BLOCK_SIZE); XMEMCPY(B+1, nonce, nonceSz);
lenSz = AES_BLOCK_SIZE - 1 - nonceSz;
B[0] = (authInSz > 0 ? 64 : 0) B[0] = (authInSz > 0 ? 64 : 0)
+ (8 * ((authTagSz - 2) / 2)) + (8 * ((authTagSz - 2) / 2))
+ (aes->lenSz - 1); + (lenSz - 1);
for (i = 0; i < aes->lenSz; i++) for (i = 0; i < lenSz; i++)
B[AES_BLOCK_SIZE - 1 - i] = (inSz >> (8 * i)) & 0xFF; B[AES_BLOCK_SIZE - 1 - i] = (inSz >> (8 * i)) & 0xFF;
AesEncrypt(aes, B, A); AesEncrypt(aes, B, A);
@@ -2662,8 +2618,8 @@ void AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz,
roll_x(aes, in, inSz, A); roll_x(aes, in, inSz, A);
XMEMCPY(authTag, A, authTagSz); XMEMCPY(authTag, A, authTagSz);
B[0] = (aes->lenSz - 1); B[0] = (lenSz - 1);
for (i = 0; i < aes->lenSz; i++) for (i = 0; i < lenSz; i++)
B[AES_BLOCK_SIZE - 1 - i] = 0; B[AES_BLOCK_SIZE - 1 - i] = 0;
AesEncrypt(aes, B, A); AesEncrypt(aes, B, A);
xorbuf(authTag, A, authTagSz); xorbuf(authTag, A, authTagSz);
@@ -2674,7 +2630,7 @@ void AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz,
xorbuf(A, in, AES_BLOCK_SIZE); xorbuf(A, in, AES_BLOCK_SIZE);
XMEMCPY(out, A, AES_BLOCK_SIZE); XMEMCPY(out, A, AES_BLOCK_SIZE);
AesCcmCtrInc(B, aes->lenSz); AesCcmCtrInc(B, lenSz);
inSz -= AES_BLOCK_SIZE; inSz -= AES_BLOCK_SIZE;
in += AES_BLOCK_SIZE; in += AES_BLOCK_SIZE;
out += AES_BLOCK_SIZE; out += AES_BLOCK_SIZE;
@@ -2691,19 +2647,21 @@ void AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz,
int AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz, int AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz,
const byte* nonce, word32 nonceSz,
const byte* authTag, word32 authTagSz, const byte* authTag, word32 authTagSz,
const byte* authIn, word32 authInSz) const byte* authIn, word32 authInSz)
{ {
byte A[AES_BLOCK_SIZE]; byte A[AES_BLOCK_SIZE];
byte B[AES_BLOCK_SIZE]; byte B[AES_BLOCK_SIZE];
byte* o; byte* o;
word32 i, oSz, result = 0; word32 i, lenSz, oSz, result = 0;
o = out; o = out;
oSz = inSz; oSz = inSz;
XMEMCPY(B, aes->reg, AES_BLOCK_SIZE); XMEMCPY(B+1, nonce, AES_BLOCK_SIZE);
B[0] = (aes->lenSz - 1); lenSz = AES_BLOCK_SIZE - 1 - nonceSz;
for (i = 0; i < aes->lenSz - 1; i++) B[0] = (lenSz - 1);
for (i = 0; i < lenSz - 1; i++)
B[AES_BLOCK_SIZE - 1 - i] = 0; B[AES_BLOCK_SIZE - 1 - i] = 0;
B[15] = 1; B[15] = 1;
while (oSz >= AES_BLOCK_SIZE) { while (oSz >= AES_BLOCK_SIZE) {
@@ -2711,7 +2669,7 @@ int AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz,
xorbuf(A, in, AES_BLOCK_SIZE); xorbuf(A, in, AES_BLOCK_SIZE);
XMEMCPY(o, A, AES_BLOCK_SIZE); XMEMCPY(o, A, AES_BLOCK_SIZE);
AesCcmCtrInc(B, aes->lenSz); AesCcmCtrInc(B, lenSz);
oSz -= AES_BLOCK_SIZE; oSz -= AES_BLOCK_SIZE;
in += AES_BLOCK_SIZE; in += AES_BLOCK_SIZE;
o += AES_BLOCK_SIZE; o += AES_BLOCK_SIZE;
@@ -2722,7 +2680,7 @@ int AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz,
XMEMCPY(o, A, oSz); XMEMCPY(o, A, oSz);
} }
for (i = 0; i < aes->lenSz; i++) for (i = 0; i < lenSz; i++)
B[AES_BLOCK_SIZE - 1 - i] = 0; B[AES_BLOCK_SIZE - 1 - i] = 0;
AesEncrypt(aes, B, A); AesEncrypt(aes, B, A);
@@ -2731,8 +2689,8 @@ int AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz,
B[0] = (authInSz > 0 ? 64 : 0) B[0] = (authInSz > 0 ? 64 : 0)
+ (8 * ((authTagSz - 2) / 2)) + (8 * ((authTagSz - 2) / 2))
+ (aes->lenSz - 1); + (lenSz - 1);
for (i = 0; i < aes->lenSz; i++) for (i = 0; i < lenSz; i++)
B[AES_BLOCK_SIZE - 1 - i] = (inSz >> (8 * i)) & 0xFF; B[AES_BLOCK_SIZE - 1 - i] = (inSz >> (8 * i)) & 0xFF;
AesEncrypt(aes, B, A); AesEncrypt(aes, B, A);
@@ -2741,8 +2699,8 @@ int AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz,
if (inSz > 0) if (inSz > 0)
roll_x(aes, o, oSz, A); roll_x(aes, o, oSz, A);
B[0] = (aes->lenSz - 1); B[0] = (lenSz - 1);
for (i = 0; i < aes->lenSz; i++) for (i = 0; i < lenSz; i++)
B[AES_BLOCK_SIZE - 1 - i] = 0; B[AES_BLOCK_SIZE - 1 - i] = 0;
AesEncrypt(aes, B, B); AesEncrypt(aes, B, B);
xorbuf(A, B, authTagSz); xorbuf(A, B, authTagSz);

View File

@@ -1518,7 +1518,7 @@ int aesgcm_test(void)
const byte iv[] = const byte iv[] =
{ {
0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
0xde, 0xca, 0xf8, 0x88, 0x00, 0x00, 0x00, 0x00 0xde, 0xca, 0xf8, 0x88
}; };
const byte p[] = const byte p[] =
@@ -1558,27 +1558,27 @@ int aesgcm_test(void)
0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b
}; };
byte t2[16]; byte t2[sizeof(t)];
byte p2[60]; byte p2[sizeof(c)];
byte c2[60]; byte c2[sizeof(p)];
int result; int result;
memset(t2, 0, 16); memset(t2, 0, sizeof(t2));
memset(c2, 0, 60); memset(c2, 0, sizeof(c2));
memset(p2, 0, 60); memset(p2, 0, sizeof(p2));
AesGcmSetKey(&enc, k, sizeof(k), iv); AesGcmSetKey(&enc, k, sizeof(k));
AesGcmSetExpIV(&enc, iv + /*AES_GCM_IMP_IV_SZ*/ 4);
/* AES-GCM encrypt and decrypt both use AES encrypt internally */ /* AES-GCM encrypt and decrypt both use AES encrypt internally */
AesGcmEncrypt(&enc, c2, p, sizeof(c2), t2, sizeof(t2), a, sizeof(a)); AesGcmEncrypt(&enc, c2, p, sizeof(c2), iv, sizeof(iv),
t2, sizeof(t2), a, sizeof(a));
if (memcmp(c, c2, sizeof(c2))) if (memcmp(c, c2, sizeof(c2)))
return -68; return -68;
if (memcmp(t, t2, sizeof(t2))) if (memcmp(t, t2, sizeof(t2)))
return -69; return -69;
result = AesGcmDecrypt(&enc, result = AesGcmDecrypt(&enc, p2, c2, sizeof(p2), iv, sizeof(iv),
p2, c2, sizeof(p2), t2, sizeof(t2), a, sizeof(a)); t2, sizeof(t2), a, sizeof(a));
if (result != 0) if (result != 0)
return -70; return -70;
if (memcmp(p, p2, sizeof(p2))) if (memcmp(p, p2, sizeof(p2)))
@@ -1642,16 +1642,17 @@ int aesccm_test(void)
memset(c2, 0, sizeof(c2)); memset(c2, 0, sizeof(c2));
memset(p2, 0, sizeof(p2)); memset(p2, 0, sizeof(p2));
AesCcmSetKey(&enc, k, sizeof(k), iv, sizeof(iv)); AesCcmSetKey(&enc, k, sizeof(k));
/* AES-CCM encrypt and decrypt both use AES encrypt internally */ /* AES-CCM encrypt and decrypt both use AES encrypt internally */
AesCcmEncrypt(&enc, c2, p, sizeof(c2), t2, sizeof(t2), a, sizeof(a)); AesCcmEncrypt(&enc, c2, p, sizeof(c2), iv, sizeof(iv),
t2, sizeof(t2), a, sizeof(a));
if (memcmp(c, c2, sizeof(c2))) if (memcmp(c, c2, sizeof(c2)))
return -107; return -107;
if (memcmp(t, t2, sizeof(t2))) if (memcmp(t, t2, sizeof(t2)))
return -108; return -108;
result = AesCcmDecrypt(&enc, result = AesCcmDecrypt(&enc, p2, c2, sizeof(p2), iv, sizeof(iv),
p2, c2, sizeof(p2), t2, sizeof(t2), a, sizeof(a)); t2, sizeof(t2), a, sizeof(a));
if (result != 0) if (result != 0)
return -109; return -109;
if (memcmp(p, p2, sizeof(p2))) if (memcmp(p, p2, sizeof(p2)))
@@ -1659,8 +1660,8 @@ int aesccm_test(void)
/* Test the authentication failure */ /* Test the authentication failure */
t2[0]++; /* Corrupt the authentication tag. */ t2[0]++; /* Corrupt the authentication tag. */
result = AesCcmDecrypt(&enc, result = AesCcmDecrypt(&enc, p2, c, sizeof(p2), iv, sizeof(iv),
p2, c, sizeof(p2), t2, sizeof(t2), a, sizeof(a)); t2, sizeof(t2), a, sizeof(a));
if (result == 0) if (result == 0)
return -111; return -111;

View File

@@ -76,9 +76,6 @@ typedef struct Aes {
ALIGN16 byte M0[256][AES_BLOCK_SIZE]; ALIGN16 byte M0[256][AES_BLOCK_SIZE];
#endif /* GCM_TABLE */ #endif /* GCM_TABLE */
#endif /* HAVE_AESGCM */ #endif /* HAVE_AESGCM */
#ifdef HAVE_AESCCM
word32 lenSz;
#endif
#ifdef CYASSL_AESNI #ifdef CYASSL_AESNI
byte use_aesni; byte use_aesni;
#endif /* CYASSL_AESNI */ #endif /* CYASSL_AESNI */
@@ -96,25 +93,24 @@ CYASSL_API void AesDecryptDirect(Aes* aes, byte* out, const byte* in);
CYASSL_API int AesSetKeyDirect(Aes* aes, const byte* key, word32 len, CYASSL_API int AesSetKeyDirect(Aes* aes, const byte* key, word32 len,
const byte* iv, int dir); const byte* iv, int dir);
#ifdef HAVE_AESGCM #ifdef HAVE_AESGCM
CYASSL_API void AesGcmSetKey(Aes* aes, const byte* key, word32 len, CYASSL_API void AesGcmSetKey(Aes* aes, const byte* key, word32 len);
const byte* implicitIV);
CYASSL_API void AesGcmSetExpIV(Aes* aes, const byte* iv);
CYASSL_API void AesGcmGetExpIV(Aes* aes, byte* iv);
CYASSL_API void AesGcmIncExpIV(Aes* aes);
CYASSL_API void AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, CYASSL_API void AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz,
const byte* iv, word32 ivSz,
byte* authTag, word32 authTagSz, byte* authTag, word32 authTagSz,
const byte* authIn, word32 authInSz); const byte* authIn, word32 authInSz);
CYASSL_API int AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, CYASSL_API int AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz,
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);
#endif /* HAVE_AESGCM */ #endif /* HAVE_AESGCM */
#ifdef HAVE_AESCCM #ifdef HAVE_AESCCM
CYASSL_API void AesCcmSetKey(Aes* aes, const byte* key, word32 keySz, CYASSL_API void AesCcmSetKey(Aes* aes, const byte* key, word32 keySz);
const byte* implicitIV, word32 ivSz);
CYASSL_API void AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz, CYASSL_API void AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz,
const byte* nonce, word32 nonceSz,
byte* authTag, word32 authTagSz, byte* authTag, word32 authTagSz,
const byte* authIn, word32 authInSz); const byte* authIn, word32 authInSz);
CYASSL_API int AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz, CYASSL_API int AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz,
const byte* nonce, word32 nonceSz,
const byte* authTag, word32 authTagSz, const byte* authTag, word32 authTagSz,
const byte* authIn, word32 authInSz); const byte* authIn, word32 authInSz);
#endif /* HAVE_AESCCM */ #endif /* HAVE_AESCCM */

View File

@@ -284,6 +284,10 @@ void c32to24(word32 in, word24 out);
#define AES_BLOCK_SIZE 16 #define AES_BLOCK_SIZE 16
#endif #endif
#if defined(BUILD_AESGCM) || defined(HAVE_AESCCM)
#define HAVE_AEAD
#endif
/* actual cipher values, 2nd byte */ /* actual cipher values, 2nd byte */
enum { enum {
@@ -471,6 +475,7 @@ enum Misc {
AEAD_LEN_OFFSET = 11, /* Auth Data: Length */ AEAD_LEN_OFFSET = 11, /* Auth Data: Length */
AEAD_AUTH_TAG_SZ = 16, /* Size of the authentication tag */ AEAD_AUTH_TAG_SZ = 16, /* Size of the authentication tag */
AEAD_AUTH_DATA_SZ = 13, /* Size of the data to authenticate */ AEAD_AUTH_DATA_SZ = 13, /* Size of the data to authenticate */
AEAD_NONCE_SZ = AES_GCM_EXP_IV_SZ + AES_GCM_IMP_IV_SZ,
HC_128_KEY_SIZE = 16, /* 128 bits */ HC_128_KEY_SIZE = 16, /* 128 bits */
HC_128_IV_SIZE = 16, /* also 128 bits */ HC_128_IV_SIZE = 16, /* also 128 bits */
@@ -1046,6 +1051,11 @@ typedef struct Keys {
byte server_write_key[AES_256_KEY_SIZE]; byte server_write_key[AES_256_KEY_SIZE];
byte client_write_IV[AES_IV_SIZE]; /* max sizes */ byte client_write_IV[AES_IV_SIZE]; /* max sizes */
byte server_write_IV[AES_IV_SIZE]; byte server_write_IV[AES_IV_SIZE];
#ifdef HAVE_AEAD
byte aead_exp_IV[AES_GCM_EXP_IV_SZ];
byte aead_enc_imp_IV[AES_GCM_IMP_IV_SZ];
byte aead_dec_imp_IV[AES_GCM_IMP_IV_SZ];
#endif
word32 peer_sequence_number; word32 peer_sequence_number;
word32 sequence_number; word32 sequence_number;

View File

@@ -2930,6 +2930,17 @@ static INLINE word32 GetSEQIncrement(CYASSL* ssl, int verify)
} }
#ifdef HAVE_AEAD
static INLINE void AeadIncrementExpIV(CYASSL* ssl)
{
int i;
for (i = AES_GCM_EXP_IV_SZ-1; i >= 0; i--) {
if (++ssl->keys.aead_exp_IV[i]) return;
}
}
#endif
static INLINE int Encrypt(CYASSL* ssl, byte* out, const byte* input, word32 sz) static INLINE int Encrypt(CYASSL* ssl, byte* out, const byte* input, word32 sz)
{ {
(void)out; (void)out;
@@ -2976,6 +2987,7 @@ static INLINE int Encrypt(CYASSL* ssl, byte* out, const byte* input, word32 sz)
case aes_gcm: case aes_gcm:
{ {
byte additional[AES_BLOCK_SIZE]; byte additional[AES_BLOCK_SIZE];
byte nonce[AEAD_NONCE_SZ];
XMEMSET(additional, 0, AES_BLOCK_SIZE); XMEMSET(additional, 0, AES_BLOCK_SIZE);
@@ -2991,12 +3003,18 @@ static INLINE int Encrypt(CYASSL* ssl, byte* out, const byte* input, word32 sz)
* IV length minus the authentication tag size. */ * IV length minus the authentication tag size. */
c16toa(sz - AES_GCM_EXP_IV_SZ - AEAD_AUTH_TAG_SZ, c16toa(sz - AES_GCM_EXP_IV_SZ - AEAD_AUTH_TAG_SZ,
additional + AEAD_LEN_OFFSET); additional + AEAD_LEN_OFFSET);
XMEMCPY(nonce,
ssl->keys.aead_enc_imp_IV, AES_GCM_IMP_IV_SZ);
XMEMCPY(nonce + AES_GCM_IMP_IV_SZ,
ssl->keys.aead_exp_IV, AES_GCM_EXP_IV_SZ);
AesGcmEncrypt(ssl->encrypt.aes, AesGcmEncrypt(ssl->encrypt.aes,
out + AES_GCM_EXP_IV_SZ, input + AES_GCM_EXP_IV_SZ, out + AES_GCM_EXP_IV_SZ, input + AES_GCM_EXP_IV_SZ,
sz - AES_GCM_EXP_IV_SZ - AEAD_AUTH_TAG_SZ, sz - AES_GCM_EXP_IV_SZ - AEAD_AUTH_TAG_SZ,
nonce, AEAD_NONCE_SZ,
out + sz - AEAD_AUTH_TAG_SZ, AEAD_AUTH_TAG_SZ, out + sz - AEAD_AUTH_TAG_SZ, AEAD_AUTH_TAG_SZ,
additional, AEAD_AUTH_DATA_SZ); additional, AEAD_AUTH_DATA_SZ);
AesGcmIncExpIV(ssl->encrypt.aes); AeadIncrementExpIV(ssl);
XMEMSET(nonce, 0, AEAD_NONCE_SZ);
} }
break; break;
#endif #endif
@@ -3089,8 +3107,8 @@ static INLINE int Decrypt(CYASSL* ssl, byte* plain, const byte* input,
case aes_gcm: case aes_gcm:
{ {
byte additional[AES_BLOCK_SIZE]; byte additional[AES_BLOCK_SIZE];
byte nonce[AEAD_NONCE_SZ];
AesGcmSetExpIV(ssl->decrypt.aes, input);
XMEMSET(additional, 0, AES_BLOCK_SIZE); XMEMSET(additional, 0, AES_BLOCK_SIZE);
/* sequence number field is 64-bits, we only use 32-bits */ /* sequence number field is 64-bits, we only use 32-bits */
@@ -3102,15 +3120,20 @@ static INLINE int Decrypt(CYASSL* ssl, byte* plain, const byte* input,
c16toa(sz - AES_GCM_EXP_IV_SZ - AEAD_AUTH_TAG_SZ, c16toa(sz - AES_GCM_EXP_IV_SZ - AEAD_AUTH_TAG_SZ,
additional + AEAD_LEN_OFFSET); additional + AEAD_LEN_OFFSET);
XMEMCPY(nonce, ssl->keys.aead_dec_imp_IV, AES_GCM_IMP_IV_SZ);
XMEMCPY(nonce + AES_GCM_IMP_IV_SZ, input, AES_GCM_EXP_IV_SZ);
if (AesGcmDecrypt(ssl->decrypt.aes, if (AesGcmDecrypt(ssl->decrypt.aes,
plain + AES_GCM_EXP_IV_SZ, plain + AES_GCM_EXP_IV_SZ,
input + AES_GCM_EXP_IV_SZ, input + AES_GCM_EXP_IV_SZ,
sz - AES_GCM_EXP_IV_SZ - AEAD_AUTH_TAG_SZ, sz - AES_GCM_EXP_IV_SZ - AEAD_AUTH_TAG_SZ,
nonce, AEAD_NONCE_SZ,
input + sz - AEAD_AUTH_TAG_SZ, AEAD_AUTH_TAG_SZ, input + sz - AEAD_AUTH_TAG_SZ, AEAD_AUTH_TAG_SZ,
additional, AEAD_AUTH_DATA_SZ) < 0) { additional, AEAD_AUTH_DATA_SZ) < 0) {
SendAlert(ssl, alert_fatal, bad_record_mac); SendAlert(ssl, alert_fatal, bad_record_mac);
XMEMSET(nonce, 0, AEAD_NONCE_SZ);
return VERIFY_MAC_ERROR; return VERIFY_MAC_ERROR;
} }
XMEMSET(nonce, 0, AEAD_NONCE_SZ);
break; break;
} }
#endif #endif
@@ -4149,7 +4172,7 @@ static int BuildMessage(CYASSL* ssl, byte* output, const byte* input, int inSz,
if (ssl->specs.cipher_type == aead) { if (ssl->specs.cipher_type == aead) {
ivSz = AES_GCM_EXP_IV_SZ; ivSz = AES_GCM_EXP_IV_SZ;
sz += (ivSz + 16 - digestSz); sz += (ivSz + 16 - digestSz);
AesGcmGetExpIV(ssl->encrypt.aes, iv); XMEMCPY(iv, ssl->keys.aead_exp_IV, AES_GCM_EXP_IV_SZ);
} }
#endif #endif
size = (word16)(sz - headerSz); /* include mac and digest */ size = (word16)(sz - headerSz); /* include mac and digest */

View File

@@ -1006,7 +1006,7 @@ static int SetPrefix(byte* sha_input, int idx)
static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs,
byte side, void* heap, RNG* rng) byte side, void* heap)
{ {
#ifdef BUILD_ARC4 #ifdef BUILD_ARC4
word32 sz = specs->key_size; word32 sz = specs->key_size;
@@ -1136,7 +1136,6 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs,
#ifdef BUILD_AESGCM #ifdef BUILD_AESGCM
if (specs->bulk_cipher_algorithm == aes_gcm) { if (specs->bulk_cipher_algorithm == aes_gcm) {
byte iv[AES_GCM_EXP_IV_SZ];
enc->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); enc->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER);
if (enc->aes == NULL) if (enc->aes == NULL)
return MEMORY_E; return MEMORY_E;
@@ -1144,21 +1143,21 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs,
if (dec->aes == NULL) if (dec->aes == NULL)
return MEMORY_E; return MEMORY_E;
/* Initialize the AES-GCM explicit IV to a random number. */
RNG_GenerateBlock(rng, iv, sizeof(iv));
AesGcmSetExpIV(enc->aes, iv);
if (side == CLIENT_END) { if (side == CLIENT_END) {
AesGcmSetKey(enc->aes, keys->client_write_key, specs->key_size, AesGcmSetKey(enc->aes, keys->client_write_key, specs->key_size);
keys->client_write_IV); XMEMCPY(keys->aead_enc_imp_IV,
AesGcmSetKey(dec->aes, keys->server_write_key, specs->key_size, keys->client_write_IV, AES_GCM_IMP_IV_SZ);
keys->server_write_IV); AesGcmSetKey(dec->aes, keys->server_write_key, specs->key_size);
XMEMCPY(keys->aead_dec_imp_IV,
keys->server_write_IV, AES_GCM_IMP_IV_SZ);
} }
else { else {
AesGcmSetKey(enc->aes, keys->server_write_key, specs->key_size, AesGcmSetKey(enc->aes, keys->server_write_key, specs->key_size);
keys->server_write_IV); XMEMCPY(keys->aead_enc_imp_IV,
AesGcmSetKey(dec->aes, keys->client_write_key, specs->key_size, keys->server_write_IV, AES_GCM_IMP_IV_SZ);
keys->client_write_IV); AesGcmSetKey(dec->aes, keys->client_write_key, specs->key_size);
XMEMCPY(keys->aead_dec_imp_IV,
keys->client_write_IV, AES_GCM_IMP_IV_SZ);
} }
enc->setup = 1; enc->setup = 1;
dec->setup = 1; dec->setup = 1;
@@ -1175,7 +1174,6 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs,
keys->sequence_number = 0; keys->sequence_number = 0;
keys->peer_sequence_number = 0; keys->peer_sequence_number = 0;
keys->encryptionOn = 0; keys->encryptionOn = 0;
(void)rng;
(void)side; (void)side;
(void)heap; (void)heap;
(void)enc; (void)enc;
@@ -1209,8 +1207,15 @@ int StoreKeys(CYASSL* ssl, const byte* keyData)
i += sz; i += sz;
XMEMCPY(ssl->keys.server_write_IV, &keyData[i], sz); XMEMCPY(ssl->keys.server_write_IV, &keyData[i], sz);
#ifdef HAVE_AEAD
if (ssl->specs.cipher_type == aead) {
/* Initialize the AES-GCM explicit IV to a random number. */
RNG_GenerateBlock(ssl->rng, ssl->keys.aead_exp_IV, AES_GCM_EXP_IV_SZ);
}
#endif
return SetKeys(&ssl->encrypt, &ssl->decrypt, &ssl->keys, &ssl->specs, return SetKeys(&ssl->encrypt, &ssl->decrypt, &ssl->keys, &ssl->specs,
ssl->options.side, ssl->heap, ssl->rng); ssl->options.side, ssl->heap);
} }
#ifndef NO_OLD_TLS #ifndef NO_OLD_TLS