mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-07-05 11:50:52 +02:00
wolfcrypt/src/aes.c, wolfcrypt/src/port/caam/caam_aes.c, wolfcrypt/src/port/riscv/riscv-64-aes.c, wolfcrypt/src/port/silabs/silabs_aes.c, wolfcrypt/src/port/ti/ti-aes.c: implement AES-CCM counter overflow checks for ports;
wolfcrypt/test/test.c: add missing !HAVE_SELFTEST gate around AES-CCM counter overflow test in aesccm_128_badarg_test();
wolfcrypt/src/error.c and wolfssl/wolfcrypt/error-crypt.h: update messages for AES_{GCM,CCM}_OVERFLOW_E.
This commit is contained in:
@@ -13384,6 +13384,18 @@ int wc_AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz,
|
||||
return status;
|
||||
}
|
||||
|
||||
{
|
||||
word32 lenSz = (word32)WC_AES_BLOCK_SIZE - 1U - nonceSz;
|
||||
/* With a large nonce, B[] runs out of room to represent inSz, and beyond
|
||||
* that, the counter itself can wrap.
|
||||
*/
|
||||
if ((lenSz < sizeof(inSz)) &&
|
||||
(inSz >= ((word32)1 << (lenSz * 8))))
|
||||
{
|
||||
return AES_CCM_OVERFLOW_E;
|
||||
}
|
||||
}
|
||||
|
||||
status = wolfSSL_CryptHwMutexLock();
|
||||
if (status != 0)
|
||||
return status;
|
||||
@@ -13418,6 +13430,18 @@ int wc_AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz,
|
||||
return status;
|
||||
}
|
||||
|
||||
{
|
||||
word32 lenSz = (word32)WC_AES_BLOCK_SIZE - 1U - nonceSz;
|
||||
/* With a large nonce, B[] runs out of room to represent inSz, and beyond
|
||||
* that, the counter itself can wrap.
|
||||
*/
|
||||
if ((lenSz < sizeof(inSz)) &&
|
||||
(inSz >= ((word32)1 << (lenSz * 8))))
|
||||
{
|
||||
return AES_CCM_OVERFLOW_E;
|
||||
}
|
||||
}
|
||||
|
||||
status = wolfSSL_CryptHwMutexLock();
|
||||
if (status != 0)
|
||||
return status;
|
||||
|
||||
@@ -498,10 +498,10 @@ const char* wc_GetErrorString(int error)
|
||||
return "wolfcrypt FIPS ECDHE Known Answer Test Failure";
|
||||
|
||||
case AES_GCM_OVERFLOW_E:
|
||||
return "AES-GCM invocation counter overflow";
|
||||
return "AES-GCM internal overflow averted";
|
||||
|
||||
case AES_CCM_OVERFLOW_E:
|
||||
return "AES-CCM invocation counter overflow";
|
||||
return "AES-CCM internal overflow averted";
|
||||
|
||||
case RSA_KEY_PAIR_E:
|
||||
return "RSA Key Pair-Wise Consistency check fail";
|
||||
|
||||
@@ -494,7 +494,7 @@ int wc_AesCcmEncrypt(Aes* aes, byte* out,
|
||||
word32 keySz;
|
||||
word32 i;
|
||||
byte B0Ctr0[WC_AES_BLOCK_SIZE + WC_AES_BLOCK_SIZE];
|
||||
int lenSz;
|
||||
word32 lenSz;
|
||||
byte mask = 0xFF;
|
||||
const word32 wordSz = (word32)sizeof(word32);
|
||||
int ret;
|
||||
@@ -513,10 +513,20 @@ int wc_AesCcmEncrypt(Aes* aes, byte* out,
|
||||
return ret;
|
||||
}
|
||||
|
||||
lenSz = WC_AES_BLOCK_SIZE - 1 - (byte)nonceSz;
|
||||
/* With a large nonce, B[] runs out of room to represent inSz, and beyond
|
||||
* that, the counter itself can wrap.
|
||||
*/
|
||||
if ((lenSz < sizeof(inSz)) &&
|
||||
(inSz >= ((word32)1 << (lenSz * 8))))
|
||||
{
|
||||
return AES_CCM_OVERFLOW_E;
|
||||
}
|
||||
|
||||
/* set up B0 and CTR0 similar to how wolfcrypt/src/aes.c does */
|
||||
XMEMCPY(B0Ctr0+1, nonce, nonceSz);
|
||||
XMEMCPY(B0Ctr0+WC_AES_BLOCK_SIZE+1, nonce, nonceSz);
|
||||
lenSz = WC_AES_BLOCK_SIZE - 1 - (byte)nonceSz;
|
||||
|
||||
B0Ctr0[0] = (authInSz > 0 ? 64 : 0)
|
||||
+ (8 * (((byte)authTagSz - 2) / 2))
|
||||
+ (lenSz - 1);
|
||||
@@ -577,7 +587,7 @@ int wc_AesCcmDecrypt(Aes* aes, byte* out,
|
||||
word32 i;
|
||||
byte B0Ctr0[WC_AES_BLOCK_SIZE + WC_AES_BLOCK_SIZE];
|
||||
byte tag[WC_AES_BLOCK_SIZE];
|
||||
int lenSz;
|
||||
word32 lenSz;
|
||||
byte mask = 0xFF;
|
||||
const word32 wordSz = (word32)sizeof(word32);
|
||||
int ret;
|
||||
@@ -596,10 +606,20 @@ int wc_AesCcmDecrypt(Aes* aes, byte* out,
|
||||
return ret;
|
||||
}
|
||||
|
||||
lenSz = WC_AES_BLOCK_SIZE - 1 - (byte)nonceSz;
|
||||
/* With a large nonce, B[] runs out of room to represent inSz, and beyond
|
||||
* that, the counter itself can wrap.
|
||||
*/
|
||||
if ((lenSz < sizeof(inSz)) &&
|
||||
(inSz >= ((word32)1 << (lenSz * 8))))
|
||||
{
|
||||
return AES_CCM_OVERFLOW_E;
|
||||
}
|
||||
|
||||
/* set up B0 and CTR0 similar to how wolfcrypt/src/aes.c does */
|
||||
XMEMCPY(B0Ctr0+1, nonce, nonceSz);
|
||||
XMEMCPY(B0Ctr0+WC_AES_BLOCK_SIZE+1, nonce, nonceSz);
|
||||
lenSz = WC_AES_BLOCK_SIZE - 1 - (byte)nonceSz;
|
||||
|
||||
B0Ctr0[0] = (authInSz > 0 ? 64 : 0)
|
||||
+ (8 * (((byte)authTagSz - 2) / 2))
|
||||
+ (lenSz - 1);
|
||||
|
||||
@@ -9102,6 +9102,7 @@ int wc_AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz,
|
||||
const byte* authIn, word32 authInSz)
|
||||
{
|
||||
int ret = 0;
|
||||
byte lenSz = 0;
|
||||
|
||||
/* sanity check on arguments */
|
||||
if ((aes == NULL) || ((inSz != 0) && ((in == NULL) || (out == NULL))) ||
|
||||
@@ -9114,14 +9115,26 @@ int wc_AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz,
|
||||
ret = BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
lenSz = WC_AES_BLOCK_SIZE - 1 - (byte)nonceSz;
|
||||
|
||||
/* With a large nonce, B[] runs out of room to represent inSz, and beyond
|
||||
* that, the counter itself can wrap.
|
||||
*/
|
||||
if ((lenSz < sizeof(inSz)) &&
|
||||
(inSz >= ((word32)1 << (lenSz * 8))))
|
||||
{
|
||||
ret = AES_CCM_OVERFLOW_E;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
byte A[WC_AES_BLOCK_SIZE];
|
||||
byte B[WC_AES_BLOCK_SIZE];
|
||||
byte lenSz;
|
||||
byte i;
|
||||
|
||||
XMEMCPY(B+1, nonce, nonceSz);
|
||||
lenSz = WC_AES_BLOCK_SIZE - 1 - (byte)nonceSz;
|
||||
|
||||
B[0] = (authInSz > 0 ? 64 : 0)
|
||||
+ (8 * (((byte)authTagSz - 2) / 2))
|
||||
+ (lenSz - 1);
|
||||
@@ -9180,6 +9193,7 @@ int wc_AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz,
|
||||
const byte* authIn, word32 authInSz)
|
||||
{
|
||||
int ret = 0;
|
||||
byte lenSz = 0;
|
||||
|
||||
/* sanity check on arguments */
|
||||
if ((aes == NULL) || ((inSz != 0) && ((in == NULL) || (out == NULL))) ||
|
||||
@@ -9192,16 +9206,27 @@ int wc_AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz,
|
||||
ret = BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
lenSz = WC_AES_BLOCK_SIZE - 1 - (byte)nonceSz;
|
||||
|
||||
/* With a large nonce, B[] runs out of room to represent inSz, and beyond
|
||||
* that, the counter itself can wrap.
|
||||
*/
|
||||
if ((lenSz < sizeof(inSz)) &&
|
||||
(inSz >= ((word32)1 << (lenSz * 8))))
|
||||
{
|
||||
ret = AES_CCM_OVERFLOW_E;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
byte A[WC_AES_BLOCK_SIZE];
|
||||
byte B[WC_AES_BLOCK_SIZE];
|
||||
byte lenSz;
|
||||
byte i;
|
||||
byte* o = out;
|
||||
word32 oSz = inSz;
|
||||
|
||||
XMEMCPY(B+1, nonce, nonceSz);
|
||||
lenSz = WC_AES_BLOCK_SIZE - 1 - (byte)nonceSz;
|
||||
|
||||
B[0] = lenSz - 1;
|
||||
for (i = 0; i < lenSz; i++) {
|
||||
|
||||
@@ -273,10 +273,23 @@ int wc_AesCcmEncrypt_silabs (Aes* aes, byte* out, const byte* in, word32 sz,
|
||||
{
|
||||
sl_status_t status;
|
||||
if ((in == NULL) || (out == NULL) || (iv == NULL) || (authTag == NULL) ||
|
||||
(ivSz < CCM_NONCE_MIN_SZ) || (ivSz > CCM_NONCE_MAX_SZ) ||
|
||||
(authIn == NULL && authInSz != 0) || (aes == NULL)) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
{
|
||||
word32 lenSz = (word32)WC_AES_BLOCK_SIZE - 1U - ivSz;
|
||||
/* With a large nonce, B[] runs out of room to represent inSz, and beyond
|
||||
* that, the counter itself can wrap.
|
||||
*/
|
||||
if ((lenSz < sizeof(sz)) &&
|
||||
(sz >= ((word32)1 << (lenSz * 8))))
|
||||
{
|
||||
return AES_CCM_OVERFLOW_E;
|
||||
}
|
||||
}
|
||||
|
||||
status = sl_se_ccm_encrypt_and_tag(
|
||||
&(aes->ctx.cmd_ctx),
|
||||
&(aes->ctx.key),
|
||||
@@ -301,10 +314,23 @@ int wc_AesCcmDecrypt_silabs (Aes* aes, byte* out, const byte* in, word32 sz,
|
||||
{
|
||||
sl_status_t status;
|
||||
if ((in == NULL) || (out == NULL) || (iv == NULL) || (authTag == NULL) ||
|
||||
(ivSz < CCM_NONCE_MIN_SZ) || (ivSz > CCM_NONCE_MAX_SZ) ||
|
||||
(authIn == NULL && authInSz != 0) || (aes == NULL)) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
{
|
||||
word32 lenSz = (word32)WC_AES_BLOCK_SIZE - 1U - ivSz;
|
||||
/* With a large nonce, B[] runs out of room to represent inSz, and beyond
|
||||
* that, the counter itself can wrap.
|
||||
*/
|
||||
if ((lenSz < sizeof(sz)) &&
|
||||
(sz >= ((word32)1 << (lenSz * 8))))
|
||||
{
|
||||
return AES_CCM_OVERFLOW_E;
|
||||
}
|
||||
}
|
||||
|
||||
status = sl_se_ccm_auth_decrypt(
|
||||
&(aes->ctx.cmd_ctx),
|
||||
&(aes->ctx.key),
|
||||
|
||||
@@ -330,7 +330,7 @@ static int AesAuthSetKey(Aes* aes, const byte* key, word32 keySz)
|
||||
static int AesAuthArgCheck(Aes* aes, byte* out, const byte* in, word32 inSz,
|
||||
const byte* nonce, word32 nonceSz,
|
||||
const byte* authTag, word32 authTagSz,
|
||||
word32 *M, word32 *L)
|
||||
word32 *M, word32 *L, int mode)
|
||||
{
|
||||
if (aes == NULL || nonce == NULL || authTag == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
@@ -376,6 +376,19 @@ static int AesAuthArgCheck(Aes* aes, byte* out, const byte* in, word32 inSz,
|
||||
default:
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
if (mode == AES_CFG_MODE_CCM) {
|
||||
word32 lenSz = (word32)WC_AES_BLOCK_SIZE - 1U - nonceSz;
|
||||
/* With a large nonce, B[] runs out of room to represent inSz, and beyond
|
||||
* that, the counter itself can wrap.
|
||||
*/
|
||||
if ((lenSz < sizeof(inSz)) &&
|
||||
(inSz >= ((word32)1 << (lenSz * 8))))
|
||||
{
|
||||
return AES_CCM_OVERFLOW_E;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -468,8 +481,8 @@ static int AesAuthEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz,
|
||||
word32 tmpTag[WC_AES_BLOCK_SIZE/sizeof(word32)];
|
||||
|
||||
ret = AesAuthArgCheck(aes, out, in, inSz, nonce, nonceSz, authTag,
|
||||
authTagSz, &M, &L);
|
||||
if (ret == WC_NO_ERR_TRACE(BAD_FUNC_ARG)) {
|
||||
authTagSz, &M, &L, mode);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
if ((authIn == NULL) && (authInSz > 0)) {
|
||||
@@ -571,8 +584,8 @@ static int AesAuthDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz,
|
||||
word32 tmpTag[WC_AES_BLOCK_SIZE/sizeof(word32)];
|
||||
|
||||
ret = AesAuthArgCheck(aes, out, in, inSz, nonce, nonceSz, authTag,
|
||||
authTagSz, &M, &L);
|
||||
if (ret == WC_NO_ERR_TRACE(BAD_FUNC_ARG)) {
|
||||
authTagSz, &M, &L, mode);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
if ((authIn == NULL) && (authInSz > 0)) {
|
||||
|
||||
@@ -21167,7 +21167,7 @@ static wc_test_ret_t aesccm_128_badarg_test(Aes* enc)
|
||||
}
|
||||
#endif /* !BENCH_EMBEDDED && !WOLFSSL_NO_MALLOC */
|
||||
|
||||
#if !defined(HAVE_FIPS) || FIPS_VERSION3_GE(7, 0, 0)
|
||||
#if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION3_GE(7, 0, 0))
|
||||
|
||||
ret = wc_AesCcmEncrypt(enc, buf, (const byte *)"", (word32)1 << 16,
|
||||
iv, 13, t_empty2, sizeof(t_empty2),
|
||||
@@ -21211,7 +21211,7 @@ static wc_test_ret_t aesccm_128_badarg_test(Aes* enc)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* !HAVE_FIPS || FIPS_VERSION3_GE(7, 0, 0) */
|
||||
#endif /* !HAVE_SELFTEST && (!HAVE_FIPS || FIPS_VERSION3_GE(7, 0, 0)) */
|
||||
|
||||
ret = 0;
|
||||
out:
|
||||
|
||||
@@ -251,8 +251,8 @@ enum wolfCrypt_ErrorCodes {
|
||||
AESCCM_KAT_FIPS_E = -257, /* AESCCM KAT failure */
|
||||
SHA3_KAT_FIPS_E = -258, /* SHA-3 KAT failure */
|
||||
ECDHE_KAT_FIPS_E = -259, /* ECDHE KAT failure */
|
||||
AES_GCM_OVERFLOW_E = -260, /* AES-GCM invocation counter overflow. */
|
||||
AES_CCM_OVERFLOW_E = -261, /* AES-CCM invocation counter overflow. */
|
||||
AES_GCM_OVERFLOW_E = -260, /* AES-GCM internal overflow averted */
|
||||
AES_CCM_OVERFLOW_E = -261, /* AES-CCM internal overflow averted */
|
||||
RSA_KEY_PAIR_E = -262, /* RSA Key Pair-Wise Consistency check fail. */
|
||||
DH_CHECK_PRIV_E = -263, /* DH Check Priv Key error */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user