1. Fixed bug where AES-GCM IVs had to only be 12 bytes. Now

accepts any length.
2. Added test case for AES-GCM using an 60 byte IV.
3. AesGcmSetKey doesn't calculate H value in AES-NI mode.
This commit is contained in:
John Safranek
2015-11-03 16:47:42 -08:00
parent 427405fff9
commit 23ba31cbdd
2 changed files with 117 additions and 49 deletions

View File

@@ -2651,19 +2651,11 @@ int wc_AesSetIV(Aes* aes, const byte* iv)
#endif
enum {
CTR_SZ = 4
NONCE_SZ = 12,
CTR_SZ = 4
};
static INLINE void InitGcmCounter(byte* inOutCtr)
{
inOutCtr[AES_BLOCK_SIZE - 4] = 0;
inOutCtr[AES_BLOCK_SIZE - 3] = 0;
inOutCtr[AES_BLOCK_SIZE - 2] = 0;
inOutCtr[AES_BLOCK_SIZE - 1] = 1;
}
static INLINE void IncrementGcmCounter(byte* inOutCtr)
{
int i;
@@ -2752,6 +2744,12 @@ int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len)
XMEMSET(iv, 0, AES_BLOCK_SIZE);
ret = wc_AesSetKey(aes, key, len, iv, AES_ENCRYPTION);
#ifdef WOLFSSL_AESNI
/* AES-NI code generates its own H value. */
if (haveAESNI)
return ret;
#endif /* WOLFSSL_AESNI */
if (ret == 0) {
wc_AesEncrypt(aes, iv, aes->H);
#ifdef GCM_TABLE
@@ -3696,6 +3694,7 @@ int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz,
const byte* p = in;
byte* c = out;
byte counter[AES_BLOCK_SIZE];
byte initialCounter[AES_BLOCK_SIZE];
byte *ctr ;
byte scratch[AES_BLOCK_SIZE];
@@ -3715,9 +3714,15 @@ int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz,
ctr = counter ;
#endif
XMEMSET(ctr, 0, AES_BLOCK_SIZE);
XMEMCPY(ctr, iv, ivSz);
InitGcmCounter(ctr);
XMEMSET(initialCounter, 0, AES_BLOCK_SIZE);
if (ivSz == NONCE_SZ) {
XMEMCPY(initialCounter, iv, ivSz);
initialCounter[AES_BLOCK_SIZE - 1] = 1;
}
else {
GHASH(aes, NULL, 0, iv, ivSz, initialCounter, AES_BLOCK_SIZE);
}
XMEMCPY(ctr, initialCounter, AES_BLOCK_SIZE);
#ifdef WOLFSSL_PIC32MZ_CRYPT
if(blocks)
@@ -3744,8 +3749,7 @@ int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz,
}
GHASH(aes, authIn, authInSz, out, sz, authTag, authTagSz);
InitGcmCounter(ctr);
wc_AesEncrypt(aes, ctr, scratch);
wc_AesEncrypt(aes, initialCounter, scratch);
xorbuf(authTag, scratch, authTagSz);
return 0;
@@ -3762,6 +3766,7 @@ int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz,
const byte* c = in;
byte* p = out;
byte counter[AES_BLOCK_SIZE];
byte initialCounter[AES_BLOCK_SIZE];
byte *ctr ;
byte scratch[AES_BLOCK_SIZE];
@@ -3782,9 +3787,15 @@ int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz,
ctr = counter ;
#endif
XMEMSET(ctr, 0, AES_BLOCK_SIZE);
XMEMCPY(ctr, iv, ivSz);
InitGcmCounter(ctr);
XMEMSET(initialCounter, 0, AES_BLOCK_SIZE);
if (ivSz == NONCE_SZ) {
XMEMCPY(initialCounter, iv, ivSz);
initialCounter[AES_BLOCK_SIZE - 1] = 1;
}
else {
GHASH(aes, NULL, 0, iv, ivSz, initialCounter, AES_BLOCK_SIZE);
}
XMEMCPY(ctr, initialCounter, AES_BLOCK_SIZE);
/* Calculate the authTag again using the received auth data and the
* cipher text. */

View File

@@ -2729,20 +2729,6 @@ int aesgcm_test(void)
* Counter Mode of Operation (GCM) by McGrew and
* Viega.
*/
const byte k[] =
{
0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08
};
const byte iv[] =
{
0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
0xde, 0xca, 0xf8, 0x88
};
const byte p[] =
{
0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
@@ -2762,7 +2748,21 @@ int aesgcm_test(void)
0xab, 0xad, 0xda, 0xd2
};
const byte c[] =
const byte k1[] =
{
0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08
};
const byte iv1[] =
{
0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
0xde, 0xca, 0xf8, 0x88
};
const byte c1[] =
{
0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
@@ -2774,38 +2774,95 @@ int aesgcm_test(void)
0xbc, 0xc9, 0xf6, 0x62
};
const byte t[] =
const byte t1[] =
{
0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b
};
byte t2[sizeof(t)];
byte p2[sizeof(c)];
byte c2[sizeof(p)];
/* Test Case 12, uses same plaintext and AAD data. */
const byte k2[] =
{
0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c
};
int result;
const byte iv2[] =
{
0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,
0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
0xa6, 0x37, 0xb3, 0x9b
};
memset(t2, 0, sizeof(t2));
memset(c2, 0, sizeof(c2));
memset(p2, 0, sizeof(p2));
const byte c2[] =
{
0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c,
0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff,
0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef,
0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45,
0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9,
0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3,
0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,
0xe9, 0xb7, 0x37, 0x3b
};
wc_AesGcmSetKey(&enc, k, sizeof(k));
const byte t2[] =
{
0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb,
0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9
};
byte resultT[sizeof(t1)];
byte resultP[sizeof(p)];
byte resultC[sizeof(p)];
int result;
memset(resultT, 0, sizeof(resultT));
memset(resultC, 0, sizeof(resultC));
memset(resultP, 0, sizeof(resultP));
wc_AesGcmSetKey(&enc, k1, sizeof(k1));
/* AES-GCM encrypt and decrypt both use AES encrypt internally */
wc_AesGcmEncrypt(&enc, c2, p, sizeof(c2), iv, sizeof(iv),
t2, sizeof(t2), a, sizeof(a));
if (memcmp(c, c2, sizeof(c2)))
wc_AesGcmEncrypt(&enc, resultC, p, sizeof(p), iv1, sizeof(iv1),
resultT, sizeof(resultT), a, sizeof(a));
if (memcmp(c1, resultC, sizeof(resultC)))
return -68;
if (memcmp(t, t2, sizeof(t2)))
if (memcmp(t1, resultT, sizeof(resultT)))
return -69;
result = wc_AesGcmDecrypt(&enc, p2, c2, sizeof(p2), iv, sizeof(iv),
t2, sizeof(t2), a, sizeof(a));
result = wc_AesGcmDecrypt(&enc, resultP, resultC, sizeof(resultC),
iv1, sizeof(iv1), resultT, sizeof(resultT), a, sizeof(a));
if (result != 0)
return -70;
if (memcmp(p, p2, sizeof(p2)))
if (memcmp(p, resultP, sizeof(resultP)))
return -71;
memset(resultT, 0, sizeof(resultT));
memset(resultC, 0, sizeof(resultC));
memset(resultP, 0, sizeof(resultP));
wc_AesGcmSetKey(&enc, k2, sizeof(k2));
/* AES-GCM encrypt and decrypt both use AES encrypt internally */
wc_AesGcmEncrypt(&enc, resultC, p, sizeof(p), iv2, sizeof(iv2),
resultT, sizeof(resultT), a, sizeof(a));
if (memcmp(c2, resultC, sizeof(resultC)))
return -230;
if (memcmp(t2, resultT, sizeof(resultT)))
return -231;
result = wc_AesGcmDecrypt(&enc, resultP, resultC, sizeof(resultC),
iv2, sizeof(iv2), resultT, sizeof(resultT), a, sizeof(a));
if (result != 0)
return -232;
if (memcmp(p, resultP, sizeof(resultP)))
return -233;
return 0;
}