diff --git a/wolfcrypt/src/aes.c b/wolfcrypt/src/aes.c index 924b27e39..4178e18f7 100644 --- a/wolfcrypt/src/aes.c +++ b/wolfcrypt/src/aes.c @@ -3374,7 +3374,9 @@ int wc_AesSetIV(Aes* aes, const byte* iv) */ enum { - GCM_NONCE_SZ = 12, + GCM_NONCE_MAX_SZ = 16, /* wolfCrypt's maximum nonce size allowed. */ + GCM_NONCE_MID_SZ = 12, /* The usual default nonce size for AES-GCM. */ + GCM_NONCE_MIN_SZ = 8, /* wolfCrypt's minimum nonce size allowed. */ CCM_NONCE_MIN_SZ = 7, CCM_NONCE_MAX_SZ = 13, CTR_SZ = 4, @@ -7497,7 +7499,7 @@ int AES_GCM_encrypt_C(Aes* aes, byte* out, const byte* in, word32 sz, ctr = counter; XMEMSET(initialCounter, 0, AES_BLOCK_SIZE); - if (ivSz == GCM_NONCE_SZ) { + if (ivSz == GCM_NONCE_MID_SZ) { XMEMCPY(initialCounter, iv, ivSz); initialCounter[AES_BLOCK_SIZE - 1] = 1; } @@ -7584,7 +7586,7 @@ int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, defined(WOLFSSL_STM32F7)) /* additional argument checks - STM32 HW only supports 12 byte IV */ - if (ivSz != GCM_NONCE_SZ) { + if (ivSz != GCM_NONCE_MID_SZ) { return BAD_FUNC_ARG; } @@ -7732,7 +7734,7 @@ int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, } /* additional argument checks - STM32 HW only supports 12 byte IV */ - if (ivSz != GCM_NONCE_SZ) { + if (ivSz != GCM_NONCE_MID_SZ) { return BAD_FUNC_ARG; } @@ -7866,7 +7868,7 @@ int AES_GCM_decrypt_C(Aes* aes, byte* out, const byte* in, word32 sz, ctr = counter; XMEMSET(initialCounter, 0, AES_BLOCK_SIZE); - if (ivSz == GCM_NONCE_SZ) { + if (ivSz == GCM_NONCE_MID_SZ) { XMEMCPY(initialCounter, iv, ivSz); initialCounter[AES_BLOCK_SIZE - 1] = 1; } @@ -8036,18 +8038,43 @@ int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, #ifndef WC_NO_RNG -int wc_AesGcmSetIV(Aes* aes, const byte* extIv, word32 ivSz, +int wc_AesGcmSetExtIV(Aes* aes, const byte* iv, word32 ivSz) +{ + int ret = 0; + + if (aes == NULL || iv == NULL || + (ivSz != GCM_NONCE_MIN_SZ && ivSz != GCM_NONCE_MID_SZ && + ivSz != GCM_NONCE_MAX_SZ)) { + + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + XMEMCPY((byte*)aes->reg, iv, ivSz); + + /* If the IV is 96, allow for a 2^64 invocation counter. + * For any other size for the nonce, limit the invocation + * counter to 32-bits. (SP 800-38D 8.3) */ + aes->invokeCtr[0] = 0; + aes->invokeCtr[1] = (ivSz == GCM_NONCE_MID_SZ) ? 0 : 0xFFFFFFFF; + aes->nonceSz = ivSz; + } + + return ret; +} + + +int wc_AesGcmSetIV(Aes* aes, word32 ivSz, const byte* ivFixed, word32 ivFixedSz, WC_RNG* rng) { int ret = 0; - if (aes == NULL || - (extIv != NULL && ivFixed != NULL) || - (extIv == NULL && ivFixed == NULL && rng == NULL) || + if (aes == NULL || rng == NULL || + (ivSz != GCM_NONCE_MIN_SZ && ivSz != GCM_NONCE_MID_SZ && + ivSz != GCM_NONCE_MAX_SZ) || (ivFixed == NULL && ivFixedSz != 0) || - (ivFixed != NULL && ivFixedSz != AES_IV_FIXED_SZ) || - ivSz != GCM_NONCE_SZ) { + (ivFixed != NULL && ivFixedSz != AES_IV_FIXED_SZ)) { ret = BAD_FUNC_ARG; } @@ -8055,24 +8082,19 @@ int wc_AesGcmSetIV(Aes* aes, const byte* extIv, word32 ivSz, if (ret == 0) { byte* iv = (byte*)aes->reg; - if (extIv == NULL) { - if (ivFixedSz) - XMEMCPY((byte*)aes->reg, ivFixed, ivFixedSz); + if (ivFixedSz) + XMEMCPY(iv, ivFixed, ivFixedSz); - if (rng == NULL) - XMEMSET(iv + ivFixedSz, 0, ivSz - ivFixedSz); - else - ret = wc_RNG_GenerateBlock(rng, - iv + ivFixedSz, ivSz - ivFixedSz); - } - else - XMEMCPY(iv, extIv, ivSz); + ret = wc_RNG_GenerateBlock(rng, iv + ivFixedSz, ivSz - ivFixedSz); } if (ret == 0) { - /* If the IV is 96-bits, allow for a 2^64 invocation counter. */ + /* If the IV is 96, allow for a 2^64 invocation counter. + * For any other size for the nonce, limit the invocation + * counter to 32-bits. (SP 800-38D 8.3) */ aes->invokeCtr[0] = 0; - aes->invokeCtr[1] = 0; + aes->invokeCtr[1] = (ivSz == GCM_NONCE_MID_SZ) ? 0 : 0xFFFFFFFF; + aes->nonceSz = ivSz; } return ret; @@ -8087,7 +8109,7 @@ int wc_AesGcmEncrypt_ex(Aes* aes, byte* out, const byte* in, word32 sz, int ret = 0; if (aes == NULL || (sz != 0 && (in == NULL || out == NULL)) || - ivOut == NULL || ivOutSz != GCM_NONCE_SZ || + ivOut == NULL || ivOutSz != aes->nonceSz || (authIn == NULL && authInSz != 0)) { ret = BAD_FUNC_ARG; @@ -8104,11 +8126,11 @@ int wc_AesGcmEncrypt_ex(Aes* aes, byte* out, const byte* in, word32 sz, if (ret == 0) { ret = wc_AesGcmEncrypt(aes, out, in, sz, - (byte*)aes->reg, GCM_NONCE_SZ, + (byte*)aes->reg, ivOutSz, authTag, authTagSz, authIn, authInSz); - XMEMCPY(ivOut, aes->reg, GCM_NONCE_SZ); - IncCtr((byte*)aes->reg, GCM_NONCE_SZ); + XMEMCPY(ivOut, aes->reg, ivOutSz); + IncCtr((byte*)aes->reg, ivOutSz); } return ret; @@ -8121,9 +8143,8 @@ int wc_Gmac(const byte* key, word32 keySz, byte* iv, word32 ivSz, Aes aes; int ret = 0; - if (key == NULL || iv == NULL || ivSz != GCM_NONCE_SZ || - (authIn == NULL && authInSz != 0) || authTag == NULL || - authTagSz == 0 || rng == NULL) { + if (key == NULL || iv == NULL || (authIn == NULL && authInSz != 0) || + authTag == NULL || authTagSz == 0 || rng == NULL) { ret = BAD_FUNC_ARG; } @@ -8131,7 +8152,7 @@ int wc_Gmac(const byte* key, word32 keySz, byte* iv, word32 ivSz, if (ret == 0) ret = wc_AesGcmSetKey(&aes, key, keySz); if (ret == 0) - ret = wc_AesGcmSetIV(&aes, NULL, GCM_NONCE_SZ, NULL, 0, rng); + ret = wc_AesGcmSetIV(&aes, ivSz, NULL, 0, rng); if (ret == 0) ret = wc_AesGcmEncrypt_ex(&aes, NULL, NULL, 0, iv, ivSz, authTag, authTagSz, authIn, authInSz); @@ -8148,9 +8169,8 @@ int wc_GmacVerify(const byte* key, word32 keySz, Aes aes; int ret = 0; - if (key == NULL || iv == NULL || ivSz != GCM_NONCE_SZ || - (authIn == NULL && authInSz != 0) || authTag == NULL || - authTagSz == 0 || authTagSz > AES_BLOCK_SIZE) { + if (key == NULL || iv == NULL || (authIn == NULL && authInSz != 0) || + authTag == NULL || authTagSz == 0 || authTagSz > AES_BLOCK_SIZE) { ret = BAD_FUNC_ARG; } diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 0449f17d5..fc96102ae 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -6618,7 +6618,7 @@ int aesgcm_test(void) XMEMSET(resultP, 0, sizeof(resultP)); wc_AesGcmSetKey(&enc, k1, sizeof(k1)); - result = wc_AesGcmSetIV(&enc, NULL, sizeof(randIV), NULL, 0, &rng); + result = wc_AesGcmSetIV(&enc, sizeof(randIV), NULL, 0, &rng); if (result != 0) return -8213; diff --git a/wolfssl/wolfcrypt/aes.h b/wolfssl/wolfcrypt/aes.h index 184c65efd..612574eb9 100644 --- a/wolfssl/wolfcrypt/aes.h +++ b/wolfssl/wolfcrypt/aes.h @@ -111,8 +111,6 @@ typedef struct Aes { #if defined(HAVE_AESGCM) || defined(HAVE_AESCCM) word32 invokeCtr[2]; -#endif -#ifdef HAVE_AESCCM word32 nonceSz; #endif #ifdef HAVE_AESGCM @@ -225,7 +223,8 @@ WOLFSSL_API int wc_AesEcbDecrypt(Aes* aes, byte* out, const byte* authIn, word32 authInSz); #ifndef WC_NO_RNG - WOLFSSL_API int wc_AesGcmSetIV(Aes* aes, const byte* extIv, word32 ivSz, + WOLFSSL_API int wc_AesGcmSetExtIV(Aes* aes, const byte* iv, word32 ivSz); + WOLFSSL_API int wc_AesGcmSetIV(Aes* aes, word32 ivSz, const byte* ivFixed, word32 ivFixedSz, WC_RNG* rng); WOLFSSL_API int wc_AesGcmEncrypt_ex(Aes* aes, byte* out,