diff --git a/wolfcrypt/src/aes.c b/wolfcrypt/src/aes.c index 6806acbc965..fcb5529ad0f 100644 --- a/wolfcrypt/src/aes.c +++ b/wolfcrypt/src/aes.c @@ -4228,6 +4228,7 @@ static WARN_UNUSED_RESULT int wc_AesDecrypt(Aes* aes, const byte* inBlock, rk = aes->key; aes->keylen = keylen; + aes->keyInstalled = 1; aes->rounds = keylen/4 + 6; XMEMCPY(rk, userKey, keylen); #if !defined(WOLFSSL_STM32_CUBEMX) || defined(STM32_HAL_V2) @@ -4309,6 +4310,7 @@ static WARN_UNUSED_RESULT int wc_AesDecrypt(Aes* aes, const byte* inBlock, #endif aes->keylen = keylen; + aes->keyInstalled = 1; aes->rounds = keylen/4 + 6; XMEMCPY(aes->key, userKey, keylen); @@ -4393,6 +4395,7 @@ static WARN_UNUSED_RESULT int wc_AesDecrypt(Aes* aes, const byte* inBlock, #endif aes->keylen = keylen; + aes->keyInstalled = 1; aes->rounds = keylen/4 + 6; XMEMCPY(aes->key, userKey, keylen); ret = nrf51_aes_set_key(userKey); @@ -4452,6 +4455,7 @@ static WARN_UNUSED_RESULT int wc_AesDecrypt(Aes* aes, const byte* inBlock, #endif aes->keylen = keylen; + aes->keyInstalled = 1; aes->rounds = keylen/4 + 6; XMEMCPY(aes->key, userKey, keylen); @@ -4514,6 +4518,7 @@ static WARN_UNUSED_RESULT int wc_AesDecrypt(Aes* aes, const byte* inBlock, } aes->keylen = keylen; + aes->keyInstalled = 1; aes->rounds = keylen/4 + 6; XMEMCPY(aes->key, userKey, keylen); @@ -4579,6 +4584,7 @@ static WARN_UNUSED_RESULT int wc_AesDecrypt(Aes* aes, const byte* inBlock, aes->keylen = (int)keylen; aes->rounds = (keylen/4) + 6; + aes->keyInstalled = 1; #ifndef WOLFSSL_ARMASM_NO_HW_CRYPTO AES_set_key_AARCH32(userKey, keylen, (byte*)aes->key, dir); @@ -4631,6 +4637,7 @@ static WARN_UNUSED_RESULT int wc_AesDecrypt(Aes* aes, const byte* inBlock, if (ret == 0) { /* Callback succeeded - SE owns the key */ aes->keylen = (int)keylen; + aes->keyInstalled = 1; if (iv != NULL) XMEMCPY(aes->reg, iv, WC_AES_BLOCK_SIZE); else @@ -4691,6 +4698,7 @@ static WARN_UNUSED_RESULT int wc_AesDecrypt(Aes* aes, const byte* inBlock, aes->keylen = (int)keylen; aes->rounds = (keylen/4) + 6; + aes->keyInstalled = 1; AES_set_encrypt_key(userKey, keylen * 8, (byte*)aes->key); @@ -4736,6 +4744,7 @@ static WARN_UNUSED_RESULT int wc_AesDecrypt(Aes* aes, const byte* inBlock, if (ret == 0) { /* Callback succeeded - SE owns the key */ aes->keylen = (int)keylen; + aes->keyInstalled = 1; if (iv != NULL) XMEMCPY(aes->reg, iv, WC_AES_BLOCK_SIZE); else @@ -4871,7 +4880,10 @@ static WARN_UNUSED_RESULT int wc_AesDecrypt(Aes* aes, const byte* inBlock, int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, const byte* iv, int dir) { - return wc_Psoc6_Aes_SetKey(aes, userKey, keylen, iv, dir); + int ret = wc_Psoc6_Aes_SetKey(aes, userKey, keylen, iv, dir); + if (ret == 0 && aes != NULL) + aes->keyInstalled = 1; + return ret; } #if defined(WOLFSSL_AES_DIRECT) @@ -5188,6 +5200,7 @@ static void AesSetKey_C(Aes* aes, const byte* key, word32 keySz, int dir) if (ret == 0) { /* Callback succeeded - SE owns the key */ aes->keylen = (int)keylen; + aes->keyInstalled = 1; if (iv != NULL) XMEMCPY(aes->reg, iv, WC_AES_BLOCK_SIZE); else @@ -5304,6 +5317,7 @@ static void AesSetKey_C(Aes* aes, const byte* key, word32 keySz, int dir) * reads it as the source of truth for the configured key size. */ aes->keylen = (int)keylen; aes->rounds = (keylen / 4) + 6; + aes->keyInstalled = 1; #if defined(WOLFSSL_AES_COUNTER) || defined(WOLFSSL_AES_CFB) || \ defined(WOLFSSL_AES_OFB) || defined(WOLFSSL_AES_XTS) || \ defined(WOLFSSL_AES_CTS) @@ -5333,6 +5347,7 @@ static void AesSetKey_C(Aes* aes, const byte* key, word32 keySz, int dir) aes->keylen = (int)keylen; aes->rounds = (keylen/4) + 6; + aes->keyInstalled = 1; ret = wc_AesSetIV(aes, iv); if (ret != 0) return ret; @@ -6599,6 +6614,11 @@ int wc_AesSetIV(Aes* aes, const byte* iv) { int ret; + if (aes == NULL || aes->keyInstalled == 0) { + WOLFSSL_MSG("AES key not set"); + return BAD_FUNC_ARG; + } + if (sz == 0) return 0; @@ -6629,6 +6649,11 @@ int wc_AesSetIV(Aes* aes, const byte* iv) int ret; byte scratch[WC_AES_BLOCK_SIZE]; + if (aes == NULL || aes->keyInstalled == 0) { + WOLFSSL_MSG("AES key not set"); + return BAD_FUNC_ARG; + } + if (sz == 0) return 0; @@ -6699,12 +6724,20 @@ int wc_AesSetIV(Aes* aes, const byte* iv) int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) { + if (aes == NULL || aes->keyInstalled == 0) { + WOLFSSL_MSG("AES key not set"); + return BAD_FUNC_ARG; + } return wc_Psoc6_Aes_CbcEncrypt(aes, out, in, sz); } #if defined(HAVE_AES_DECRYPT) int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) { + if (aes == NULL || aes->keyInstalled == 0) { + WOLFSSL_MSG("AES key not set"); + return BAD_FUNC_ARG; + } return wc_Psoc6_Aes_CbcDecrypt(aes, out, in, sz); } #endif /* HAVE_AES_DECRYPT */ @@ -6760,6 +6793,13 @@ int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) /* fall-through when unavailable */ } #endif + + /* Software/HW key schedule required from here on. */ + if (aes->keyInstalled == 0) { + WOLFSSL_MSG("AES key not set"); + return BAD_FUNC_ARG; + } + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES) /* if async and byte count above threshold */ if (aes->asyncDev.marker == WOLFSSL_ASYNC_MARKER_AES && @@ -6970,6 +7010,13 @@ int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) /* fall-through when unavailable */ } #endif + + /* Software/HW key schedule required from here on. */ + if (aes->keyInstalled == 0) { + WOLFSSL_MSG("AES key not set"); + return BAD_FUNC_ARG; + } + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES) /* if async and byte count above threshold */ if (aes->asyncDev.marker == WOLFSSL_ASYNC_MARKER_AES && @@ -7425,6 +7472,12 @@ int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) } #endif + /* Software/HW key schedule required from here on. */ + if (aes->keyInstalled == 0) { + WOLFSSL_MSG("AES key not set"); + return BAD_FUNC_ARG; + } + /* consume any unused bytes left in aes->tmp */ processed = min(aes->left, sz); xorbufout(out, in, (byte*)aes->tmp + WC_AES_BLOCK_SIZE - aes->left, @@ -10423,6 +10476,12 @@ int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, } #endif + /* Software/HW key schedule (and hash subkey H) required from here on. */ + if (aes->keyInstalled == 0) { + WOLFSSL_MSG("AES key not set"); + return BAD_FUNC_ARG; + } + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES) /* if async and byte count above threshold */ /* only 12-byte IV is supported in HW */ @@ -11173,6 +11232,12 @@ int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, } #endif + /* Software/HW key schedule (and hash subkey H) required from here on. */ + if (aes->keyInstalled == 0) { + WOLFSSL_MSG("AES key not set"); + return BAD_FUNC_ARG; + } + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES) /* if async and byte count above threshold */ /* only 12-byte IV is supported in HW */ @@ -14449,6 +14514,10 @@ int wc_AesEcbEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) { if ((in == NULL) || (out == NULL) || (aes == NULL)) return BAD_FUNC_ARG; + if (aes->keyInstalled == 0) { + WOLFSSL_MSG("AES key not set"); + return BAD_FUNC_ARG; + } return wc_Psoc6_Aes_EcbEncrypt(aes, out, in, sz); } @@ -14460,6 +14529,10 @@ int wc_AesEcbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) { if ((in == NULL) || (out == NULL) || (aes == NULL)) return BAD_FUNC_ARG; + if (aes->keyInstalled == 0) { + WOLFSSL_MSG("AES key not set"); + return BAD_FUNC_ARG; + } return wc_Psoc6_Aes_EcbDecrypt(aes, out, in, sz); } @@ -14497,6 +14570,12 @@ static WARN_UNUSED_RESULT int _AesEcbEncrypt( return DCPAesEcbEncrypt(aes, out, in, sz); #endif + /* Software key schedule required from here on. */ + if (aes->keyInstalled == 0) { + WOLFSSL_MSG("AES key not set"); + return BAD_FUNC_ARG; + } + VECTOR_REGISTERS_PUSH; #if !defined(__aarch64__) && defined(WOLFSSL_ARMASM) @@ -14592,6 +14671,12 @@ static WARN_UNUSED_RESULT int _AesEcbDecrypt( return DCPAesEcbDecrypt(aes, out, in, sz); #endif + /* Software key schedule required from here on. */ + if (aes->keyInstalled == 0) { + WOLFSSL_MSG("AES key not set"); + return BAD_FUNC_ARG; + } + VECTOR_REGISTERS_PUSH; #if !defined(__aarch64__) && defined(WOLFSSL_ARMASM) @@ -14694,12 +14779,20 @@ int wc_AesEcbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) int wc_AesCfbEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) { + if (aes == NULL || aes->keyInstalled == 0) { + WOLFSSL_MSG("AES key not set"); + return BAD_FUNC_ARG; + } return wc_Psoc6_Aes_CfbEncrypt(aes, out, in, sz); } #ifdef HAVE_AES_DECRYPT int wc_AesCfbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) { + if (aes == NULL || aes->keyInstalled == 0) { + WOLFSSL_MSG("AES key not set"); + return BAD_FUNC_ARG; + } return wc_Psoc6_Aes_CfbDecrypt(aes, out, in, sz); } #endif /* HAVE_AES_DECRYPT */ @@ -14732,6 +14825,10 @@ static WARN_UNUSED_RESULT int AesCfbEncrypt_C(Aes* aes, byte* out, if (sz == 0) { return 0; } + if (aes->keyInstalled == 0) { + WOLFSSL_MSG("AES key not set"); + return BAD_FUNC_ARG; + } if (aes->left > 0) { /* consume any unused bytes left in aes->tmp */ @@ -14807,6 +14904,10 @@ static WARN_UNUSED_RESULT int AesCfbDecrypt_C(Aes* aes, byte* out, if (sz == 0) { return 0; } + if (aes->keyInstalled == 0) { + WOLFSSL_MSG("AES key not set"); + return BAD_FUNC_ARG; + } if (aes->left > 0) { /* consume any unused bytes left in aes->tmp */ @@ -14951,6 +15052,10 @@ static WARN_UNUSED_RESULT int wc_AesFeedbackCFB8( if (sz == 0) { return 0; } + if (aes->keyInstalled == 0) { + WOLFSSL_MSG("AES key not set"); + return BAD_FUNC_ARG; + } VECTOR_REGISTERS_PUSH; @@ -15011,6 +15116,10 @@ static WARN_UNUSED_RESULT int wc_AesFeedbackCFB1( if (sz == 0) { return 0; } + if (aes->keyInstalled == 0) { + WOLFSSL_MSG("AES key not set"); + return BAD_FUNC_ARG; + } VECTOR_REGISTERS_PUSH; @@ -15169,6 +15278,10 @@ static WARN_UNUSED_RESULT int AesOfbCrypt_C(Aes* aes, byte* out, const byte* in, if (sz == 0) { return 0; } + if (aes->keyInstalled == 0) { + WOLFSSL_MSG("AES key not set"); + return BAD_FUNC_ARG; + } if (aes->left > 0) { /* consume any unused bytes left in aes->tmp */ diff --git a/wolfcrypt/src/port/riscv/riscv-64-aes.c b/wolfcrypt/src/port/riscv/riscv-64-aes.c index 8dee9a87d51..4ccdabbcb12 100644 --- a/wolfcrypt/src/port/riscv/riscv-64-aes.c +++ b/wolfcrypt/src/port/riscv/riscv-64-aes.c @@ -506,6 +506,7 @@ int wc_AesSetKey(Aes* aes, const byte* key, word32 keyLen, const byte* iv, if (ret == 0) { /* Finish setting the AES object. */ aes->keylen = keyLen; + aes->keyInstalled = 1; #if defined(WOLFSSL_AES_COUNTER) || defined(WOLFSSL_AES_CFB) || \ defined(WOLFSSL_AES_OFB) || defined(WOLFSSL_AES_XTS) aes->left = 0; @@ -698,6 +699,10 @@ int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) if ((aes == NULL) || (out == NULL) || (in == NULL)) { ret = BAD_FUNC_ARG; } + /* A key must have been installed. */ + if ((ret == 0) && (aes->keyInstalled == 0)) { + ret = BAD_FUNC_ARG; + } #ifdef WOLFSSL_AES_CBC_LENGTH_CHECKS /* Ensure a multiple of blocks is to be encrypted. */ if ((ret == 0) && (sz % WC_AES_BLOCK_SIZE)) { @@ -910,6 +915,10 @@ int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) if ((aes == NULL) || (out == NULL) || (in == NULL)) { ret = BAD_FUNC_ARG; } + /* A key must have been installed. */ + if ((ret == 0) && (aes->keyInstalled == 0)) { + ret = BAD_FUNC_ARG; + } /* Ensure a multiple of blocks is being decrypted. */ if ((ret == 0) && (sz % WC_AES_BLOCK_SIZE)) { #ifdef WOLFSSL_AES_CBC_LENGTH_CHECKS @@ -1778,6 +1787,7 @@ int wc_AesSetKey(Aes* aes, const byte* key, word32 keyLen, const byte* iv, if (ret == 0) { /* Finish setting the AES object. */ aes->keylen = keyLen; + aes->keyInstalled = 1; #if defined(WOLFSSL_AES_COUNTER) || defined(WOLFSSL_AES_CFB) || \ defined(WOLFSSL_AES_OFB) || defined(WOLFSSL_AES_XTS) aes->left = 0; @@ -2988,6 +2998,7 @@ int wc_AesSetKey(Aes* aes, const byte* key, word32 keyLen, const byte* iv, #endif aes->keylen = (int)keyLen; aes->rounds = (keyLen / 4) + 6; + aes->keyInstalled = 1; /* Compute the key schedule. */ AesSetKey_C(aes, key, keyLen, dir); @@ -3870,6 +3881,10 @@ int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) if ((aes == NULL) || (out == NULL) || (in == NULL)) { ret = BAD_FUNC_ARG; } + /* A key must have been installed. */ + if ((ret == 0) && (aes->keyInstalled == 0)) { + ret = BAD_FUNC_ARG; + } #ifdef WOLFSSL_AES_CBC_LENGTH_CHECKS /* Ensure a multiple of blocks is to be encrypted. */ if ((ret == 0) && (sz % WC_AES_BLOCK_SIZE)) { @@ -3938,6 +3953,10 @@ int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) if ((aes == NULL) || (out == NULL) || (in == NULL)) { ret = BAD_FUNC_ARG; } + /* A key must have been installed. */ + if ((ret == 0) && (aes->keyInstalled == 0)) { + ret = BAD_FUNC_ARG; + } /* Ensure a multiple of blocks is being decrypted. */ if ((ret == 0) && (sz % WC_AES_BLOCK_SIZE)) { #ifdef WOLFSSL_AES_CBC_LENGTH_CHECKS @@ -4011,6 +4030,10 @@ int wc_AesEcbEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) if ((aes == NULL) || (out == NULL) || (in == NULL)) { ret = BAD_FUNC_ARG; } + /* A key must have been installed. */ + if ((ret == 0) && (aes->keyInstalled == 0)) { + ret = BAD_FUNC_ARG; + } /* Ensure a multiple of blocks is to be encrypted. */ if ((ret == 0) && ((sz % WC_AES_BLOCK_SIZE) != 0)) { ret = BAD_LENGTH_E; @@ -4048,6 +4071,10 @@ int wc_AesEcbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) if ((aes == NULL) || (out == NULL) || (in == NULL)) { ret = BAD_FUNC_ARG; } + /* A key must have been installed. */ + if ((ret == 0) && (aes->keyInstalled == 0)) { + ret = BAD_FUNC_ARG; + } /* Ensure a multiple of blocks is to be decrypted. */ if ((ret == 0) && ((sz % WC_AES_BLOCK_SIZE) != 0)) { ret = BAD_LENGTH_E; @@ -6937,6 +6964,10 @@ int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, WOLFSSL_MSG("GcmEncrypt tagSz error"); ret = BAD_FUNC_ARG; } + /* A key must have been installed. */ + if ((ret == 0) && (aes->keyInstalled == 0)) { + ret = BAD_FUNC_ARG; + } if (ret == 0) { switch (aes->rounds) { @@ -8840,6 +8871,10 @@ int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, WOLFSSL_MSG("GcmEncrypt tagSz error"); ret = BAD_FUNC_ARG; } + /* A key must have been installed. */ + if ((ret == 0) && (aes->keyInstalled == 0)) { + ret = BAD_FUNC_ARG; + } if (ret == 0) { @@ -8937,6 +8972,10 @@ int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, WOLFSSL_MSG("a NULL parameter passed in when size is larger than 0"); ret = BAD_FUNC_ARG; } + /* A key must have been installed. */ + if ((ret == 0) && (aes->keyInstalled == 0)) { + ret = BAD_FUNC_ARG; + } if (ret == 0) { if (nonceSz == GCM_NONCE_MID_SZ) { diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index e95bba5ae5e..69c287fc10e 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -16122,12 +16122,149 @@ static wc_test_ret_t aes_ecb_direct_test(void) } #endif /* HAVE_AES_ECB || WOLFSSL_AES_DIRECT */ +/* The keyInstalled guard is a non-FIPS hardening; under FIPS/selftest the AES + * functions come from the validated module and don't reject a missing key, so + * this test does not apply there. */ +#if (defined(HAVE_AES_CBC) || defined(WOLFSSL_AES_COUNTER) || \ + defined(HAVE_AESGCM) || defined(HAVE_AES_ECB) || \ + defined(WOLFSSL_AES_CFB) || defined(WOLFSSL_AES_OFB)) && \ + !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) +#define WC_TEST_HAVE_AES_NO_KEY_SET +/* Ensure AES mode APIs fail when used before wc_AesSetKey installs a key, + * instead of running with the all-zero key schedule left by wc_AesInit. */ +static wc_test_ret_t aes_no_key_set_test(void) +{ + wc_test_ret_t ret = 0; +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) + Aes *aes = NULL; +#else + Aes aes[1]; +#endif + byte plain[WC_AES_BLOCK_SIZE]; + byte cipher[WC_AES_BLOCK_SIZE]; +#ifdef HAVE_AESGCM + byte iv[WC_AES_BLOCK_SIZE]; + byte tag[WC_AES_BLOCK_SIZE]; +#endif + + XMEMSET(plain, 0, sizeof(plain)); + XMEMSET(cipher, 0, sizeof(cipher)); +#ifdef HAVE_AESGCM + XMEMSET(iv, 0, sizeof(iv)); + XMEMSET(tag, 0, sizeof(tag)); +#endif + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) + aes = wc_AesNew(HEAP_HINT, devId, &ret); + if (aes == NULL) + return WC_TEST_RET_ENC_EC(ret); +#else + ret = wc_AesInit(aes, HEAP_HINT, devId); + if (ret != 0) + return WC_TEST_RET_ENC_EC(ret); +#endif + + /* No wc_AesSetKey: aes->keylen is 0, so every mode must reject the call. */ +#ifdef HAVE_AES_CBC + if (wc_AesCbcEncrypt(aes, cipher, plain, WC_AES_BLOCK_SIZE) != + WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + ERROR_OUT(WC_TEST_RET_ENC_NC, out); +#ifdef HAVE_AES_DECRYPT + if (wc_AesCbcDecrypt(aes, cipher, plain, WC_AES_BLOCK_SIZE) != + WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + ERROR_OUT(WC_TEST_RET_ENC_NC, out); +#endif +#endif /* HAVE_AES_CBC */ + +#ifdef WOLFSSL_AES_COUNTER + if (wc_AesCtrEncrypt(aes, cipher, plain, WC_AES_BLOCK_SIZE) != + WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + ERROR_OUT(WC_TEST_RET_ENC_NC, out); +#endif + +#ifdef HAVE_AESGCM + if (wc_AesGcmEncrypt(aes, cipher, plain, WC_AES_BLOCK_SIZE, iv, sizeof(iv), + tag, sizeof(tag), NULL, 0) != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + ERROR_OUT(WC_TEST_RET_ENC_NC, out); + if (wc_AesGcmDecrypt(aes, cipher, plain, WC_AES_BLOCK_SIZE, iv, sizeof(iv), + tag, sizeof(tag), NULL, 0) != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + ERROR_OUT(WC_TEST_RET_ENC_NC, out); +#endif + +#ifdef HAVE_AES_ECB + if (wc_AesEcbEncrypt(aes, cipher, plain, WC_AES_BLOCK_SIZE) != + WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + ERROR_OUT(WC_TEST_RET_ENC_NC, out); +#ifdef HAVE_AES_DECRYPT + if (wc_AesEcbDecrypt(aes, cipher, plain, WC_AES_BLOCK_SIZE) != + WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + ERROR_OUT(WC_TEST_RET_ENC_NC, out); +#endif +#endif /* HAVE_AES_ECB */ + +#ifdef WOLFSSL_AES_CFB + if (wc_AesCfbEncrypt(aes, cipher, plain, WC_AES_BLOCK_SIZE) != + WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + ERROR_OUT(WC_TEST_RET_ENC_NC, out); +#ifdef HAVE_AES_DECRYPT + if (wc_AesCfbDecrypt(aes, cipher, plain, WC_AES_BLOCK_SIZE) != + WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + ERROR_OUT(WC_TEST_RET_ENC_NC, out); +#endif +#if !defined(WOLFSSL_NO_AES_CFB_1_8) + if (wc_AesCfb1Encrypt(aes, cipher, plain, 8) != + WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + ERROR_OUT(WC_TEST_RET_ENC_NC, out); + if (wc_AesCfb8Encrypt(aes, cipher, plain, 1) != + WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + ERROR_OUT(WC_TEST_RET_ENC_NC, out); +#ifdef HAVE_AES_DECRYPT + if (wc_AesCfb1Decrypt(aes, cipher, plain, 8) != + WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + ERROR_OUT(WC_TEST_RET_ENC_NC, out); + if (wc_AesCfb8Decrypt(aes, cipher, plain, 1) != + WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + ERROR_OUT(WC_TEST_RET_ENC_NC, out); +#endif +#endif /* !WOLFSSL_NO_AES_CFB_1_8 */ +#endif /* WOLFSSL_AES_CFB */ + +#ifdef WOLFSSL_AES_OFB + if (wc_AesOfbEncrypt(aes, cipher, plain, WC_AES_BLOCK_SIZE) != + WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + ERROR_OUT(WC_TEST_RET_ENC_NC, out); +#ifdef HAVE_AES_DECRYPT + if (wc_AesOfbDecrypt(aes, cipher, plain, WC_AES_BLOCK_SIZE) != + WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + ERROR_OUT(WC_TEST_RET_ENC_NC, out); +#endif +#endif /* WOLFSSL_AES_OFB */ + + ret = 0; /* success */ + out: + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) + wc_AesDelete(aes, &aes); +#else + wc_AesFree(aes); +#endif + + return ret; +} +#endif /* any AES mode for aes_no_key_set_test */ + WOLFSSL_TEST_SUBROUTINE wc_test_ret_t aes_test(void) { wc_test_ret_t ret = 0; WOLFSSL_ENTER("aes_test"); +#ifdef WC_TEST_HAVE_AES_NO_KEY_SET + ret = aes_no_key_set_test(); + if (ret != 0) + return ret; +#endif + #ifndef HAVE_RENESAS_SYNC ret = aes_key_size_test(); if (ret != 0) @@ -27242,6 +27379,9 @@ static wc_test_ret_t rsa_decode_test(RsaKey* keyPub) static wc_test_ret_t rsa_pss_test(WC_RNG* rng, RsaKey* key) { byte digest[WC_MAX_DIGEST_SIZE]; +#ifndef WOLFSSL_MICROCHIP_TA100 + byte tamperedDigest[WC_MAX_DIGEST_SIZE]; +#endif wc_test_ret_t ret = 0; const char inStr[] = TEST_STRING; word32 inLen = (word32)TEST_STRING_SZ; @@ -27369,6 +27509,31 @@ static wc_test_ret_t rsa_pss_test(WC_RNG* rng, RsaKey* key) #endif if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit_rsa_pss); + + /* A well-formed PSS structure must not verify against a different + * message hash. Flip one digest bit, keep the correct salt length, + * and confirm the signature-to-message binding rejects it. */ + XMEMCPY(tamperedDigest, digest, digestSz); + tamperedDigest[0] ^= 0x01; +#if defined(HAVE_SELFTEST) && \ + (!defined(HAVE_SELFTEST_VERSION) || (HAVE_SELFTEST_VERSION < 2)) + ret = wc_RsaPSS_CheckPadding_ex(tamperedDigest, digestSz, plain, + plainSz, hash[j], -1); +#elif defined(HAVE_SELFTEST) && (HAVE_SELFTEST_VERSION == 2) + ret = wc_RsaPSS_CheckPadding_ex(tamperedDigest, digestSz, plain, + plainSz, hash[j], -1, 0); +#else + ret = wc_RsaPSS_CheckPadding_ex2(tamperedDigest, digestSz, plain, + plainSz, hash[j], -1, wc_RsaEncryptSize(key)*8, + HEAP_HINT); +#endif + /* Negative test: any result other than BAD_PADDING_E is a + * failure. In particular a 0 return (tampered digest wrongly + * accepted) must fail the test, so use a ret-independent, + * non-zero code rather than encoding ret. */ + if (ret != WC_NO_ERR_TRACE(BAD_PADDING_E)) + ERROR_OUT(WC_TEST_RET_ENC_NC, exit_rsa_pss); + ret = 0; #endif /* WOLFSSL_MICROCHIP_TA100 */ #ifdef RSA_PSS_TEST_WRONG_PARAMS diff --git a/wolfssl/wolfcrypt/aes.h b/wolfssl/wolfcrypt/aes.h index e3d7637470d..108c121054b 100644 --- a/wolfssl/wolfcrypt/aes.h +++ b/wolfssl/wolfcrypt/aes.h @@ -292,6 +292,12 @@ struct Aes { #endif int keylen; + /* Set to 1 once a key has been installed (wc_AesSetKey/SetKeyDirect/ + * GcmSetKey). Checked by the mode APIs so they fail instead of running + * with the all-zero key schedule left by wc_AesInit. Distinct from the + * Cavium-only keySet field below. */ + WC_BITFIELD keyInstalled:1; + ALIGN16 word32 reg[WC_AES_BLOCK_SIZE / sizeof(word32)]; /* for CBC mode */ ALIGN16 word32 tmp[WC_AES_BLOCK_SIZE / sizeof(word32)]; /* same */