diff --git a/wolfcrypt/src/aes.c b/wolfcrypt/src/aes.c index 46a89a6ad80..59eeba22b87 100644 --- a/wolfcrypt/src/aes.c +++ b/wolfcrypt/src/aes.c @@ -4522,6 +4522,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); #ifdef WOLF_CRYPTO_CB @@ -4611,6 +4612,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); @@ -4648,6 +4650,7 @@ static WARN_UNUSED_RESULT int wc_AesDecrypt(Aes* aes, const byte* inBlock, aes->rounds = keylen/4 + 6; XMEMCPY(aes->key, userKey, keylen); + aes->keyInstalled = 1; #if defined(WOLFSSL_AES_COUNTER) || defined(WOLFSSL_AES_CFB) || \ defined(WOLFSSL_AES_OFB) || defined(WOLFSSL_AES_XTS) || \ @@ -4695,6 +4698,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); @@ -4754,6 +4758,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); @@ -4816,6 +4821,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); @@ -4881,6 +4887,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); @@ -4933,6 +4940,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 @@ -4993,6 +5001,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; /* Determine base vs vector-crypto before the (dispatched) key setup so * the schedule matches the mode functions that later consume it. */ @@ -5041,6 +5050,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 @@ -5149,6 +5159,8 @@ static WARN_UNUSED_RESULT int wc_AesDecrypt(Aes* aes, const byte* inBlock, #endif wolfSSL_CryptHwMutexUnLock(); + aes->keyInstalled = 1; + ret = wc_AesSetIV(aes, iv); } @@ -5176,7 +5188,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) @@ -5492,6 +5507,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 @@ -5580,6 +5596,7 @@ static void AesSetKey_C(Aes* aes, const byte* key, word32 keySz, int dir) return WC_HW_E; } aes->blackKey = keyIdOut; + aes->keyInstalled = 1; return 0; } #endif @@ -5608,6 +5625,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) @@ -5637,6 +5655,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; @@ -6869,6 +6888,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; @@ -6899,6 +6923,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; @@ -6969,12 +6998,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 */ @@ -7000,6 +7037,8 @@ int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) } if (sz == 0) { + /* Keep above the DCP/crypto-cb dispatches: they must not see + * sz == 0. A missing key is only reported when there is work. */ return 0; } @@ -7014,6 +7053,10 @@ int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) #endif #if defined(WOLFSSL_RISCV_ASM) + if (aes->keyInstalled == 0) { + WOLFSSL_MSG("AES key not set"); + return BAD_FUNC_ARG; + } AES_CBC_encrypt_RISCV64(in, out, sz, (byte*)aes->reg, (byte*)aes->key, (int)aes->rounds); (void)blocks; @@ -7038,6 +7081,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 && @@ -7212,6 +7262,8 @@ int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) } if (sz == 0) { + /* Keep above the DCP/crypto-cb dispatches: they must not see + * sz == 0. A missing key is only reported when there is work. */ return 0; } @@ -7242,6 +7294,10 @@ int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) } #if defined(WOLFSSL_RISCV_ASM) + if (aes->keyInstalled == 0) { + WOLFSSL_MSG("AES key not set"); + return BAD_FUNC_ARG; + } AES_CBC_decrypt_RISCV64(in, out, sz, (byte*)aes->reg, (byte*)aes->key, (int)aes->rounds); (void)blocks; @@ -7266,6 +7322,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 && @@ -7745,6 +7808,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, @@ -10966,6 +11035,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 */ @@ -11778,6 +11853,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 */ @@ -14963,6 +15044,12 @@ int wc_AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz, } #endif + /* Software/HW key schedule required from here on. */ + if (aes->keyInstalled == 0) { + WOLFSSL_MSG("AES key not set"); + return BAD_FUNC_ARG; + } + XMEMSET(A, 0, sizeof(A)); XMEMCPY(B+1, nonce, nonceSz); @@ -15127,6 +15214,12 @@ int wc_AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz, } #endif + /* Software/HW key schedule required from here on. */ + if (aes->keyInstalled == 0) { + WOLFSSL_MSG("AES key not set"); + return BAD_FUNC_ARG; + } + o = out; oSz = inSz; XMEMSET(A, 0, sizeof A); @@ -15750,6 +15843,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); } @@ -15761,6 +15858,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); } @@ -15798,6 +15899,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(WOLFSSL_RISCV_ASM) @@ -15899,6 +16006,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(WOLFSSL_RISCV_ASM) @@ -16007,12 +16120,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 */ @@ -16042,6 +16163,10 @@ static WARN_UNUSED_RESULT int AesCfbEncrypt_C(Aes* aes, byte* out, if ((aes == NULL) || (out == NULL) || (in == NULL)) { return BAD_FUNC_ARG; } + if (aes->keyInstalled == 0) { + WOLFSSL_MSG("AES key not set"); + return BAD_FUNC_ARG; + } if (sz == 0) { return 0; } @@ -16125,6 +16250,10 @@ static WARN_UNUSED_RESULT int AesCfbDecrypt_C(Aes* aes, byte* out, if ((aes == NULL) || (out == NULL) || (in == NULL)) { return BAD_FUNC_ARG; } + if (aes->keyInstalled == 0) { + WOLFSSL_MSG("AES key not set"); + return BAD_FUNC_ARG; + } if (sz == 0) { return 0; } @@ -16353,6 +16482,10 @@ static WARN_UNUSED_RESULT int wc_AesFeedbackCFB8( return BAD_FUNC_ARG; } + if (aes->keyInstalled == 0) { + WOLFSSL_MSG("AES key not set"); + return BAD_FUNC_ARG; + } if (sz == 0) { return 0; } @@ -16413,6 +16546,10 @@ static WARN_UNUSED_RESULT int wc_AesFeedbackCFB1( return BAD_FUNC_ARG; } + if (aes->keyInstalled == 0) { + WOLFSSL_MSG("AES key not set"); + return BAD_FUNC_ARG; + } if (sz == 0) { return 0; } @@ -16571,6 +16708,10 @@ static WARN_UNUSED_RESULT int AesOfbCrypt_C(Aes* aes, byte* out, const byte* in, if ((aes == NULL) || (out == NULL) || (in == NULL)) { return BAD_FUNC_ARG; } + if (aes->keyInstalled == 0) { + WOLFSSL_MSG("AES key not set"); + return BAD_FUNC_ARG; + } if (sz == 0) { return 0; } diff --git a/wolfcrypt/src/port/af_alg/afalg_aes.c b/wolfcrypt/src/port/af_alg/afalg_aes.c index efbf6358594..8fefe25ff41 100644 --- a/wolfcrypt/src/port/af_alg/afalg_aes.c +++ b/wolfcrypt/src/port/af_alg/afalg_aes.c @@ -60,6 +60,10 @@ static int wc_AesSetup(Aes* aes, const char* type, const char* name, int ivSz, i byte* key = (byte*)aes->key; #endif + if (aes->keyInstalled == 0) { + return BAD_FUNC_ARG; + } + if (aes->alFd == WC_SOCK_NOTSET) { aes->alFd = wc_Afalg_Socket(); if (aes->alFd < 0) { @@ -146,6 +150,8 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, #endif aes->keylen = keylen; aes->rounds = keylen/4 + 6; + /* Mark key installed so the shared aes.c mode guards accept this context. */ + aes->keyInstalled = 1; #ifdef WOLFSSL_AES_COUNTER aes->left = 0; @@ -556,6 +562,8 @@ int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len) aes->keylen = len; aes->rounds = len/4 + 6; aes->dir = AES_ENCRYPTION; + /* Mark key installed so the shared aes.c mode guards accept this context. */ + aes->keyInstalled = 1; if (aes->rdFd > WC_SOCK_NOTSET) { (void)close(aes->rdFd); diff --git a/wolfcrypt/src/port/caam/caam_aes.c b/wolfcrypt/src/port/caam/caam_aes.c index 4ab3ee7f944..79e6a8056a3 100644 --- a/wolfcrypt/src/port/caam/caam_aes.c +++ b/wolfcrypt/src/port/caam/caam_aes.c @@ -88,6 +88,8 @@ int wc_AesSetKey(Aes* aes, const byte* key, word32 len, default: return BAD_FUNC_ARG; } + /* Mark key installed so the shared aes.c mode guards accept this context. */ + aes->keyInstalled = 1; if ((ret = wc_AesSetIV(aes, iv)) != 0) { return ret; diff --git a/wolfcrypt/src/port/devcrypto/devcrypto_aes.c b/wolfcrypt/src/port/devcrypto/devcrypto_aes.c index 62cd624f017..30f4661bb09 100644 --- a/wolfcrypt/src/port/devcrypto/devcrypto_aes.c +++ b/wolfcrypt/src/port/devcrypto/devcrypto_aes.c @@ -123,6 +123,8 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, #endif aes->keylen = keylen; aes->rounds = keylen/4 + 6; + /* Mark key installed so the shared aes.c mode guards accept this context. */ + aes->keyInstalled = 1; #if defined(WOLFSSL_AES_COUNTER) || defined(WOLFSSL_AES_CFB) || \ defined(WOLFSSL_AES_OFB) || defined(WOLFSSL_AES_XTS) diff --git a/wolfcrypt/src/port/kcapi/kcapi_aes.c b/wolfcrypt/src/port/kcapi/kcapi_aes.c index 0aab365a3cb..d2cd8be371d 100644 --- a/wolfcrypt/src/port/kcapi/kcapi_aes.c +++ b/wolfcrypt/src/port/kcapi/kcapi_aes.c @@ -208,6 +208,9 @@ int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len) if (ret == 0) { aes->keylen = len; aes->rounds = len/4 + 6; + /* Mark key installed so the shared aes.c mode guards accept this + * context. */ + aes->keyInstalled = 1; /* save key until type is known i.e. CBC, ECB, ... */ XMEMCPY((byte*)(aes->devKey), key, len); diff --git a/wolfcrypt/src/port/silabs/silabs_aes.c b/wolfcrypt/src/port/silabs/silabs_aes.c index 498acea21c5..10b69955146 100644 --- a/wolfcrypt/src/port/silabs/silabs_aes.c +++ b/wolfcrypt/src/port/silabs/silabs_aes.c @@ -87,6 +87,9 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, aes->ctx.key.storage.location.buffer.pointer = (void*)aes->key; aes->ctx.key.storage.location.buffer.size = keylen; aes->ctx.key.size = keylen; + /* Mark key installed so the shared aes.c mode guards accept this + * context. */ + aes->keyInstalled = 1; } return ret; diff --git a/wolfcrypt/src/port/ti/ti-aes.c b/wolfcrypt/src/port/ti/ti-aes.c index 4d77dcfe16e..4cc820b5a03 100644 --- a/wolfcrypt/src/port/ti/ti-aes.c +++ b/wolfcrypt/src/port/ti/ti-aes.c @@ -97,6 +97,8 @@ int wc_AesSetKey(Aes* aes, const byte* key, word32 len, const byte* iv, int dir) } aes->keylen = len; aes->rounds = len / 4 + 6; + /* Mark key installed so the shared aes.c mode guards accept this context. */ + aes->keyInstalled = 1; XMEMCPY(aes->key, key, len); #if defined(WOLFSSL_AES_COUNTER) || defined(WOLFSSL_AES_CFB) || \ diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 40924f6983b..9b50e8e73af 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -16503,12 +16503,164 @@ 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_AESCCM) || 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]; +#if defined(HAVE_AESGCM) || defined(HAVE_AESCCM) + byte iv[WC_AES_BLOCK_SIZE]; + byte tag[WC_AES_BLOCK_SIZE]; +#endif + + XMEMSET(plain, 0, sizeof(plain)); + XMEMSET(cipher, 0, sizeof(cipher)); +#if defined(HAVE_AESGCM) || defined(HAVE_AESCCM) + XMEMSET(iv, 0, sizeof(iv)); + XMEMSET(tag, 0, sizeof(tag)); +#endif + + /* The keyInstalled guard is pure-software hardening placed after the + * crypto-cb dispatch, so use INVALID_DEVID here: a registered device would + * route these calls to the callback (against a zero key) and never reach + * the guard. */ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) + aes = wc_AesNew(HEAP_HINT, INVALID_DEVID, &ret); + if (aes == NULL) + return WC_TEST_RET_ENC_EC(ret); +#else + ret = wc_AesInit(aes, HEAP_HINT, INVALID_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_AESCCM + if (wc_AesCcmEncrypt(aes, cipher, plain, WC_AES_BLOCK_SIZE, iv, 13, + tag, sizeof(tag), NULL, 0) != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + ERROR_OUT(WC_TEST_RET_ENC_NC, out); +#ifdef HAVE_AES_DECRYPT + if (wc_AesCcmDecrypt(aes, cipher, plain, WC_AES_BLOCK_SIZE, iv, 13, + tag, sizeof(tag), NULL, 0) != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + ERROR_OUT(WC_TEST_RET_ENC_NC, out); +#endif +#endif /* HAVE_AESCCM */ + +#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) @@ -28319,6 +28471,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; @@ -28446,6 +28601,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 183aad072f8..d8b80d83078 100644 --- a/wolfssl/wolfcrypt/aes.h +++ b/wolfssl/wolfcrypt/aes.h @@ -294,6 +294,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 */