From 23ba31cbdd81a2832beafc357765c98d86271970 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Tue, 3 Nov 2015 16:47:42 -0800 Subject: [PATCH] 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. --- wolfcrypt/src/aes.c | 47 ++++++++++------- wolfcrypt/test/test.c | 119 +++++++++++++++++++++++++++++++----------- 2 files changed, 117 insertions(+), 49 deletions(-) diff --git a/wolfcrypt/src/aes.c b/wolfcrypt/src/aes.c index d7524b66a..20e6ce874 100644 --- a/wolfcrypt/src/aes.c +++ b/wolfcrypt/src/aes.c @@ -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. */ diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index fbdc43a63..e22ac3908 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -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; }