mirror of https://github.com/wolfSSL/wolfssl.git
Merge pull request #10762 from julek-wolfssl/fenrir/20260623
AES reject-no-key guard and RSA-PSS hash-binding test (F-6151, F-6157)pull/11224/head
commit
08c7d3389b
|
|
@ -959,6 +959,7 @@ WOLFSSL_NEW_PRIME_CHECK
|
|||
WOLFSSL_NONBLOCK_OCSP
|
||||
WOLFSSL_NOSHA3_384
|
||||
WOLFSSL_NOT_WINDOWS_API
|
||||
WOLFSSL_NO_AES_KEY_SET_CHECK
|
||||
WOLFSSL_NO_BIO_ADDR_IN
|
||||
WOLFSSL_NO_CHACHA20_POLY1305_FUSED
|
||||
WOLFSSL_NO_CHACHA20_POLY1305_FUSED_IFMA
|
||||
|
|
|
|||
|
|
@ -94,6 +94,13 @@ block cipher mechanism that uses n-bit binary string parameter key with 128-bits
|
|||
* WC_AES_BITSLICED: Use bitsliced AES implementation default: off
|
||||
* AES_GCM_GMULT_NCT: GCM GMULT non-constant-time default: off
|
||||
* NO_WOLFSSL_ALLOC_ALIGN: Disable aligned memory allocation default: off
|
||||
* WOLFSSL_AES_REQUIRE_KEY_SET:
|
||||
* Reject mode calls made before a key default: on,
|
||||
* is installed. Off automatically on see aes.h
|
||||
* backends that replace the mode
|
||||
* entry points.
|
||||
* WOLFSSL_NO_AES_KEY_SET_CHECK:
|
||||
* Force the above check off default: off
|
||||
*
|
||||
* Hardware Acceleration (AES-specific):
|
||||
* WC_ASYNC_ENABLE_AES: Enable async AES operations default: off
|
||||
|
|
@ -4632,6 +4639,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
|
||||
|
|
@ -4721,6 +4729,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);
|
||||
|
||||
|
|
@ -4758,6 +4767,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) || \
|
||||
|
|
@ -4805,6 +4815,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);
|
||||
|
|
@ -4864,6 +4875,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);
|
||||
|
|
@ -4926,6 +4938,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);
|
||||
|
||||
|
|
@ -4991,6 +5004,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
|
||||
#ifdef WOLFSSL_ARM32_AES_DISPATCH
|
||||
|
|
@ -5054,6 +5068,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
|
||||
|
|
@ -5071,8 +5086,15 @@ static WARN_UNUSED_RESULT int wc_AesDecrypt(Aes* aes, const byte* inBlock,
|
|||
WC_SETKEY_AES, aes, (void*)userKey, keylen,
|
||||
(void*)iv,
|
||||
(iv != NULL) ? WC_AES_BLOCK_SIZE : 0, dir);
|
||||
if (cbRet != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
|
||||
if (cbRet != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
|
||||
if (cbRet == 0) {
|
||||
/* Callback succeeded - the device owns the key, so mark it
|
||||
* installed like the AES_SETKEY path above. */
|
||||
aes->keylen = (int)keylen;
|
||||
aes->keyInstalled = 1;
|
||||
}
|
||||
return cbRet;
|
||||
}
|
||||
/* CRYPTOCB_UNAVAILABLE: fall through to software setup */
|
||||
#endif /* WOLF_CRYPTO_CB_SETKEY */
|
||||
/* Standard CryptoCB path - copy key to devKey for encrypt/decrypt offload */
|
||||
|
|
@ -5114,6 +5136,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. */
|
||||
|
|
@ -5162,6 +5185,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
|
||||
|
|
@ -5270,6 +5294,8 @@ static WARN_UNUSED_RESULT int wc_AesDecrypt(Aes* aes, const byte* inBlock,
|
|||
#endif
|
||||
wolfSSL_CryptHwMutexUnLock();
|
||||
|
||||
aes->keyInstalled = 1;
|
||||
|
||||
ret = wc_AesSetIV(aes, iv);
|
||||
}
|
||||
|
||||
|
|
@ -5297,7 +5323,15 @@ 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;
|
||||
|
||||
if (aes == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
ret = wc_Psoc6_Aes_SetKey(aes, userKey, keylen, iv, dir);
|
||||
if (ret == 0)
|
||||
aes->keyInstalled = 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if defined(WOLFSSL_AES_DIRECT)
|
||||
|
|
@ -5570,12 +5604,38 @@ static void AesSetKey_C(Aes* aes, const byte* key, word32 keySz, int dir)
|
|||
|
||||
#endif /* NEED_AES_TABLES */
|
||||
|
||||
/* AES - SetKey (block schedule via generated asm on RISC-V) */
|
||||
static WARN_UNUSED_RESULT int AesSetKeyLocal_body(
|
||||
Aes* aes, const byte* userKey, word32 keylen, const byte* iv, int dir,
|
||||
int checkKeyLen);
|
||||
|
||||
/* AES - SetKey (block schedule via generated asm on RISC-V)
|
||||
*
|
||||
* keyInstalled is derived from the return value here rather than set
|
||||
* inside the body. The body has failure returns after the point where the
|
||||
* key material is accepted (AES-NI SAVE_VECTOR_REGISTERS2/BAD_ALIGN_E, the
|
||||
* hardware key installs), and marking the context keyed on those paths
|
||||
* would let it pass WC_AES_KEY_IS_SET with an all-zero key schedule. */
|
||||
static WARN_UNUSED_RESULT int wc_AesSetKeyLocal(
|
||||
Aes* aes, const byte* userKey, word32 keylen, const byte* iv, int dir,
|
||||
int checkKeyLen)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (aes == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
aes->keyInstalled = 0;
|
||||
ret = AesSetKeyLocal_body(aes, userKey, keylen, iv, dir, checkKeyLen);
|
||||
aes->keyInstalled = (ret == 0) ? 1 : 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static WARN_UNUSED_RESULT int AesSetKeyLocal_body(
|
||||
Aes* aes, const byte* userKey, word32 keylen, const byte* iv, int dir,
|
||||
int checkKeyLen)
|
||||
{
|
||||
int ret;
|
||||
#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_SETKEY)
|
||||
int cbRet;
|
||||
#endif
|
||||
|
|
@ -5637,8 +5697,15 @@ static void AesSetKey_C(Aes* aes, const byte* key, word32 keySz, int dir)
|
|||
WC_SETKEY_AES, aes, (void*)userKey, keylen,
|
||||
(void*)iv,
|
||||
(iv != NULL) ? WC_AES_BLOCK_SIZE : 0, dir);
|
||||
if (cbRet != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
|
||||
if (cbRet != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
|
||||
if (cbRet == 0) {
|
||||
/* Callback succeeded - the device owns the key. rounds is
|
||||
* left at 0: there is no software key schedule, and the
|
||||
* XTS entry points use that to reject the context. */
|
||||
aes->keylen = (int)keylen;
|
||||
}
|
||||
return cbRet;
|
||||
}
|
||||
/* CRYPTOCB_UNAVAILABLE: fall through to software setup */
|
||||
#endif /* WOLF_CRYPTO_CB_SETKEY */
|
||||
/* Standard CryptoCB path - copy key to devKey */
|
||||
|
|
@ -6244,6 +6311,10 @@ int wc_AesSetIV(Aes* aes, const byte* iv)
|
|||
|
||||
if (aes == NULL || out == NULL || in == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
if (!WC_AES_KEY_IS_SET(aes)) {
|
||||
WOLFSSL_MSG("AES key not set");
|
||||
return MISSING_KEY;
|
||||
}
|
||||
VECTOR_REGISTERS_PUSH;
|
||||
ret = wc_AesEncrypt(aes, in, out);
|
||||
VECTOR_REGISTERS_POP;
|
||||
|
|
@ -6265,6 +6336,10 @@ int wc_AesSetIV(Aes* aes, const byte* iv)
|
|||
|
||||
if (aes == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
if (!WC_AES_KEY_IS_SET(aes)) {
|
||||
WOLFSSL_MSG("AES key not set");
|
||||
return MISSING_KEY;
|
||||
}
|
||||
VECTOR_REGISTERS_PUSH;
|
||||
ret = wc_AesDecrypt(aes, in, out);
|
||||
VECTOR_REGISTERS_POP;
|
||||
|
|
@ -7039,6 +7114,14 @@ int wc_AesSetIV(Aes* aes, const byte* iv)
|
|||
{
|
||||
int ret;
|
||||
|
||||
if (aes == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
if (!WC_AES_KEY_IS_SET(aes)) {
|
||||
WOLFSSL_MSG("AES key not set");
|
||||
return MISSING_KEY;
|
||||
}
|
||||
|
||||
if (sz == 0)
|
||||
return 0;
|
||||
|
||||
|
|
@ -7069,6 +7152,14 @@ int wc_AesSetIV(Aes* aes, const byte* iv)
|
|||
int ret;
|
||||
byte scratch[WC_AES_BLOCK_SIZE];
|
||||
|
||||
if (aes == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
if (!WC_AES_KEY_IS_SET(aes)) {
|
||||
WOLFSSL_MSG("AES key not set");
|
||||
return MISSING_KEY;
|
||||
}
|
||||
|
||||
if (sz == 0)
|
||||
return 0;
|
||||
|
||||
|
|
@ -7139,12 +7230,24 @@ int wc_AesSetIV(Aes* aes, const byte* iv)
|
|||
|
||||
int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
|
||||
{
|
||||
if (aes == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
if (!WC_AES_KEY_IS_SET(aes)) {
|
||||
WOLFSSL_MSG("AES key not set");
|
||||
return MISSING_KEY;
|
||||
}
|
||||
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)
|
||||
return BAD_FUNC_ARG;
|
||||
if (!WC_AES_KEY_IS_SET(aes)) {
|
||||
WOLFSSL_MSG("AES key not set");
|
||||
return MISSING_KEY;
|
||||
}
|
||||
return wc_Psoc6_Aes_CbcDecrypt(aes, out, in, sz);
|
||||
}
|
||||
#endif /* HAVE_AES_DECRYPT */
|
||||
|
|
@ -7170,6 +7273,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;
|
||||
}
|
||||
|
||||
|
|
@ -7183,14 +7288,6 @@ int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if defined(WOLFSSL_RISCV_ASM)
|
||||
AES_CBC_encrypt_RISCV64(in, out, sz, (byte*)aes->reg, (byte*)aes->key,
|
||||
(int)aes->rounds);
|
||||
(void)blocks;
|
||||
(void)ret;
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
#ifdef WOLFSSL_IMXRT_DCP
|
||||
/* Implemented in wolfcrypt/src/port/nxp/dcp_port.c */
|
||||
if (aes->keylen == 16)
|
||||
|
|
@ -7208,6 +7305,21 @@ int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
|
|||
/* fall-through when unavailable */
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Single key guard after all offload dispatches. */
|
||||
if (!WC_AES_KEY_IS_SET(aes)) {
|
||||
WOLFSSL_MSG("AES key not set");
|
||||
return MISSING_KEY;
|
||||
}
|
||||
|
||||
#if defined(WOLFSSL_RISCV_ASM)
|
||||
AES_CBC_encrypt_RISCV64(in, out, sz, (byte*)aes->reg, (byte*)aes->key,
|
||||
(int)aes->rounds);
|
||||
(void)blocks;
|
||||
(void)ret;
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
#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 &&
|
||||
|
|
@ -7391,6 +7503,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;
|
||||
}
|
||||
|
||||
|
|
@ -7420,14 +7534,6 @@ int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
|
|||
#endif
|
||||
}
|
||||
|
||||
#if defined(WOLFSSL_RISCV_ASM)
|
||||
AES_CBC_decrypt_RISCV64(in, out, sz, (byte*)aes->reg, (byte*)aes->key,
|
||||
(int)aes->rounds);
|
||||
(void)blocks;
|
||||
(void)ret;
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
#ifdef WOLFSSL_IMXRT_DCP
|
||||
/* Implemented in wolfcrypt/src/port/nxp/dcp_port.c */
|
||||
if (aes->keylen == 16)
|
||||
|
|
@ -7445,6 +7551,21 @@ int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
|
|||
/* fall-through when unavailable */
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Single key guard after all offload dispatches. */
|
||||
if (!WC_AES_KEY_IS_SET(aes)) {
|
||||
WOLFSSL_MSG("AES key not set");
|
||||
return MISSING_KEY;
|
||||
}
|
||||
|
||||
#if defined(WOLFSSL_RISCV_ASM)
|
||||
AES_CBC_decrypt_RISCV64(in, out, sz, (byte*)aes->reg, (byte*)aes->key,
|
||||
(int)aes->rounds);
|
||||
(void)blocks;
|
||||
(void)ret;
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
#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 &&
|
||||
|
|
@ -7932,6 +8053,12 @@ int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
|
|||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
if (sz == 0) {
|
||||
/* Keep above the crypto-cb dispatch: it must not see sz == 0.
|
||||
* A missing key is only reported when there is work. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef WOLF_CRYPTO_CB
|
||||
#ifndef WOLF_CRYPTO_CB_FIND
|
||||
if (aes->devId != INVALID_DEVID)
|
||||
|
|
@ -7944,6 +8071,12 @@ int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
|
|||
}
|
||||
#endif
|
||||
|
||||
/* Software/HW key schedule required from here on. */
|
||||
if (!WC_AES_KEY_IS_SET(aes)) {
|
||||
WOLFSSL_MSG("AES key not set");
|
||||
return MISSING_KEY;
|
||||
}
|
||||
|
||||
/* 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,
|
||||
|
|
@ -11374,6 +11507,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 (!WC_AES_KEY_IS_SET(aes)) {
|
||||
WOLFSSL_MSG("AES key not set");
|
||||
return MISSING_KEY;
|
||||
}
|
||||
|
||||
#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 */
|
||||
|
|
@ -12229,6 +12368,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 (!WC_AES_KEY_IS_SET(aes)) {
|
||||
WOLFSSL_MSG("AES key not set");
|
||||
return MISSING_KEY;
|
||||
}
|
||||
|
||||
#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 */
|
||||
|
|
@ -15527,6 +15672,12 @@ int wc_AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz,
|
|||
}
|
||||
#endif
|
||||
|
||||
/* Software/HW key schedule required from here on. */
|
||||
if (!WC_AES_KEY_IS_SET(aes)) {
|
||||
WOLFSSL_MSG("AES key not set");
|
||||
return MISSING_KEY;
|
||||
}
|
||||
|
||||
XMEMSET(A, 0, sizeof(A));
|
||||
XMEMCPY(B+1, nonce, nonceSz);
|
||||
|
||||
|
|
@ -15691,6 +15842,12 @@ int wc_AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz,
|
|||
}
|
||||
#endif
|
||||
|
||||
/* Software/HW key schedule required from here on. */
|
||||
if (!WC_AES_KEY_IS_SET(aes)) {
|
||||
WOLFSSL_MSG("AES key not set");
|
||||
return MISSING_KEY;
|
||||
}
|
||||
|
||||
o = out;
|
||||
oSz = inSz;
|
||||
XMEMSET(A, 0, sizeof A);
|
||||
|
|
@ -16048,6 +16205,8 @@ int wc_AesInit_Id(Aes* aes, unsigned char* id, int len, void* heap, int devId)
|
|||
XMEMCPY(aes->id, id, (size_t)len);
|
||||
aes->idLen = len;
|
||||
aes->labelLen = 0;
|
||||
/* keyInstalled stays 0: the key lives on the device, not in the
|
||||
* software schedule. See the field comment in aes.h. */
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
@ -16072,6 +16231,7 @@ int wc_AesInit_Label(Aes* aes, const char* label, void* heap, int devId)
|
|||
XMEMCPY(aes->label, label, labelLen);
|
||||
aes->labelLen = (int)labelLen;
|
||||
aes->idLen = 0;
|
||||
/* keyInstalled stays 0: see wc_AesInit_Id() above. */
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
@ -16095,6 +16255,9 @@ void wc_AesFree(Aes* aes)
|
|||
#ifdef WOLF_CRYPTO_CB_AES_SETKEY
|
||||
aes->devCtx = NULL; /* Clear device context handle */
|
||||
#endif
|
||||
/* This path skips the ForceZero below, so clear the flag here or a
|
||||
* reused context passes the key-set guard with a freed key. */
|
||||
aes->keyInstalled = 0;
|
||||
/* If callback wants standard free, it can set devId to INVALID_DEVID.
|
||||
* Otherwise assume the callback handled cleanup. */
|
||||
if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
|
||||
|
|
@ -16318,6 +16481,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 (!WC_AES_KEY_IS_SET(aes)) {
|
||||
WOLFSSL_MSG("AES key not set");
|
||||
return MISSING_KEY;
|
||||
}
|
||||
|
||||
return wc_Psoc6_Aes_EcbEncrypt(aes, out, in, sz);
|
||||
}
|
||||
|
|
@ -16329,6 +16496,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 (!WC_AES_KEY_IS_SET(aes)) {
|
||||
WOLFSSL_MSG("AES key not set");
|
||||
return MISSING_KEY;
|
||||
}
|
||||
|
||||
return wc_Psoc6_Aes_EcbDecrypt(aes, out, in, sz);
|
||||
}
|
||||
|
|
@ -16366,6 +16537,12 @@ static WARN_UNUSED_RESULT int _AesEcbEncrypt(
|
|||
return DCPAesEcbEncrypt(aes, out, in, sz);
|
||||
#endif
|
||||
|
||||
/* Software key schedule required from here on. */
|
||||
if (!WC_AES_KEY_IS_SET(aes)) {
|
||||
WOLFSSL_MSG("AES key not set");
|
||||
return MISSING_KEY;
|
||||
}
|
||||
|
||||
VECTOR_REGISTERS_PUSH;
|
||||
|
||||
#if defined(WOLFSSL_RISCV_ASM)
|
||||
|
|
@ -16476,6 +16653,12 @@ static WARN_UNUSED_RESULT int _AesEcbDecrypt(
|
|||
return DCPAesEcbDecrypt(aes, out, in, sz);
|
||||
#endif
|
||||
|
||||
/* Software key schedule required from here on. */
|
||||
if (!WC_AES_KEY_IS_SET(aes)) {
|
||||
WOLFSSL_MSG("AES key not set");
|
||||
return MISSING_KEY;
|
||||
}
|
||||
|
||||
VECTOR_REGISTERS_PUSH;
|
||||
|
||||
#if defined(WOLFSSL_RISCV_ASM)
|
||||
|
|
@ -16593,12 +16776,24 @@ 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)
|
||||
return BAD_FUNC_ARG;
|
||||
if (!WC_AES_KEY_IS_SET(aes)) {
|
||||
WOLFSSL_MSG("AES key not set");
|
||||
return MISSING_KEY;
|
||||
}
|
||||
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)
|
||||
return BAD_FUNC_ARG;
|
||||
if (!WC_AES_KEY_IS_SET(aes)) {
|
||||
WOLFSSL_MSG("AES key not set");
|
||||
return MISSING_KEY;
|
||||
}
|
||||
return wc_Psoc6_Aes_CfbDecrypt(aes, out, in, sz);
|
||||
}
|
||||
#endif /* HAVE_AES_DECRYPT */
|
||||
|
|
@ -16628,6 +16823,10 @@ static WARN_UNUSED_RESULT int AesCfbEncrypt_C(Aes* aes, byte* out,
|
|||
if ((aes == NULL) || (out == NULL) || (in == NULL)) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
if (!WC_AES_KEY_IS_SET(aes)) {
|
||||
WOLFSSL_MSG("AES key not set");
|
||||
return MISSING_KEY;
|
||||
}
|
||||
if (sz == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -16711,6 +16910,10 @@ static WARN_UNUSED_RESULT int AesCfbDecrypt_C(Aes* aes, byte* out,
|
|||
if ((aes == NULL) || (out == NULL) || (in == NULL)) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
if (!WC_AES_KEY_IS_SET(aes)) {
|
||||
WOLFSSL_MSG("AES key not set");
|
||||
return MISSING_KEY;
|
||||
}
|
||||
if (sz == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -16939,6 +17142,10 @@ static WARN_UNUSED_RESULT int wc_AesFeedbackCFB8(
|
|||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
if (!WC_AES_KEY_IS_SET(aes)) {
|
||||
WOLFSSL_MSG("AES key not set");
|
||||
return MISSING_KEY;
|
||||
}
|
||||
if (sz == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -16999,6 +17206,10 @@ static WARN_UNUSED_RESULT int wc_AesFeedbackCFB1(
|
|||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
if (!WC_AES_KEY_IS_SET(aes)) {
|
||||
WOLFSSL_MSG("AES key not set");
|
||||
return MISSING_KEY;
|
||||
}
|
||||
if (sz == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -17157,6 +17368,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 (!WC_AES_KEY_IS_SET(aes)) {
|
||||
WOLFSSL_MSG("AES key not set");
|
||||
return MISSING_KEY;
|
||||
}
|
||||
if (sz == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -17322,6 +17537,17 @@ static int AesKeyWrapRaw(Aes* aes, word32 inSz, byte* out, const byte* aiv)
|
|||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
#ifndef HAVE_AES_ECB
|
||||
/* The block loop below uses the wc_AesEncryptDirect macro, which bypasses
|
||||
* the public function's guard. With HAVE_AES_ECB the loop calls
|
||||
* wc_AesEcbEncrypt instead, whose own guard sits after the crypto
|
||||
* callback dispatch, so a device-held key still reaches the device. */
|
||||
if (!WC_AES_KEY_IS_SET(aes)) {
|
||||
WOLFSSL_MSG("AES key not set");
|
||||
return MISSING_KEY;
|
||||
}
|
||||
#endif
|
||||
|
||||
r = out + KEYWRAP_BLOCK_SIZE;
|
||||
XMEMSET(t, 0, sizeof(t));
|
||||
|
||||
|
|
@ -17477,6 +17703,17 @@ static int AesKeyUnWrapRaw(Aes* aes, const byte* in, word32 inSz, byte* out,
|
|||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
#ifndef HAVE_AES_ECB
|
||||
/* The block loop below uses the wc_AesDecryptDirect macro, which bypasses
|
||||
* the public function's guard. With HAVE_AES_ECB the loop calls
|
||||
* wc_AesEcbDecrypt instead, whose own guard sits after the crypto
|
||||
* callback dispatch, so a device-held key still reaches the device. */
|
||||
if (!WC_AES_KEY_IS_SET(aes)) {
|
||||
WOLFSSL_MSG("AES key not set");
|
||||
return MISSING_KEY;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* A = C[0], R[i] = C[i]; XMEMMOVE so in-place unwrap (in == out) is safe */
|
||||
XMEMCPY(tmp, in, KEYWRAP_BLOCK_SIZE);
|
||||
XMEMMOVE(out, in + KEYWRAP_BLOCK_SIZE, inSz - KEYWRAP_BLOCK_SIZE);
|
||||
|
|
@ -18533,7 +18770,9 @@ int wc_AesXtsEncrypt(XtsAes* xaes, byte* out, const byte* in, word32 sz,
|
|||
|
||||
aes = &xaes->aes;
|
||||
|
||||
if (aes->keylen == 0) {
|
||||
/* rounds == 0 means no software key schedule: XTS has no crypto
|
||||
* callback dispatch, so a device-owned key is unusable here. */
|
||||
if ((aes->keylen == 0) || (aes->rounds == 0)) {
|
||||
WOLFSSL_MSG("wc_AesXtsEncrypt called with unset encryption key.");
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
|
@ -18683,7 +18922,9 @@ int wc_AesXtsEncryptInit(XtsAes* xaes, const byte* i, word32 iSz,
|
|||
|
||||
aes = &xaes->aes;
|
||||
|
||||
if (aes->keylen == 0) {
|
||||
/* rounds == 0 means no software key schedule: XTS has no crypto
|
||||
* callback dispatch, so a device-owned key is unusable here. */
|
||||
if ((aes->keylen == 0) || (aes->rounds == 0)) {
|
||||
WOLFSSL_MSG("wc_AesXtsEncrypt called with unset encryption key.");
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
|
@ -19094,7 +19335,9 @@ int wc_AesXtsDecrypt(XtsAes* xaes, byte* out, const byte* in, word32 sz,
|
|||
* not a sequence of complete blocks.
|
||||
*/
|
||||
|
||||
if (aes->keylen == 0) {
|
||||
/* rounds == 0 means no software key schedule: XTS has no crypto
|
||||
* callback dispatch, so a device-owned key is unusable here. */
|
||||
if ((aes->keylen == 0) || (aes->rounds == 0)) {
|
||||
WOLFSSL_MSG("wc_AesXtsDecrypt called with unset decryption key.");
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
|
@ -19246,7 +19489,9 @@ int wc_AesXtsDecryptInit(XtsAes* xaes, const byte* i, word32 iSz,
|
|||
aes = &xaes->aes;
|
||||
#endif
|
||||
|
||||
if (aes->keylen == 0) {
|
||||
/* rounds == 0 means no software key schedule: XTS has no crypto
|
||||
* callback dispatch, so a device-owned key is unusable here. */
|
||||
if ((aes->keylen == 0) || (aes->rounds == 0)) {
|
||||
WOLFSSL_MSG("wc_AesXtsDecrypt called with unset decryption key.");
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -958,6 +958,7 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen,
|
|||
aes->ctx.wrapped_key = (FSPSM_AES_PWKEY)userKey;
|
||||
aes->keylen = (int)keylen;
|
||||
aes->ctx.keySize = keylen;
|
||||
aes->keyInstalled = 1;
|
||||
|
||||
return wc_AesSetIV(aes, iv);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 (!WC_AES_KEY_IS_SET(aes)) {
|
||||
return MISSING_KEY;
|
||||
}
|
||||
|
||||
if (aes->alFd == WC_SOCK_NOTSET) {
|
||||
aes->alFd = wc_Afalg_Socket();
|
||||
if (aes->alFd < 0) {
|
||||
|
|
@ -167,6 +171,10 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen,
|
|||
/* save key until type is known i.e. CBC, ECB, ... */
|
||||
XMEMCPY((byte*)(aes->key), userKey, keylen);
|
||||
aes->dir = dir;
|
||||
/* Mark key installed so the shared aes.c mode guards accept this
|
||||
* context. Only after the key is copied, so a failed setup above does
|
||||
* not leave a keyless context marked as keyed. */
|
||||
aes->keyInstalled = 1;
|
||||
|
||||
return wc_AesSetIV(aes, iv);
|
||||
}
|
||||
|
|
@ -192,6 +200,10 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen,
|
|||
}
|
||||
#endif
|
||||
|
||||
if (!WC_AES_KEY_IS_SET(aes)) {
|
||||
return MISSING_KEY;
|
||||
}
|
||||
|
||||
if (aes->dir != AES_ENCRYPTION) {
|
||||
return KEYUSAGE_E;
|
||||
}
|
||||
|
|
@ -261,6 +273,10 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen,
|
|||
#endif
|
||||
}
|
||||
|
||||
if (!WC_AES_KEY_IS_SET(aes)) {
|
||||
return MISSING_KEY;
|
||||
}
|
||||
|
||||
if (aes->dir != AES_DECRYPTION) {
|
||||
return KEYUSAGE_E;
|
||||
}
|
||||
|
|
@ -362,6 +378,10 @@ static int wc_Afalg_AesDirect(Aes* aes, byte* out, const byte* in, word32 sz)
|
|||
#if defined(WOLFSSL_AES_DIRECT) && defined(WOLFSSL_AFALG)
|
||||
int wc_AesEncryptDirect(Aes* aes, byte* out, const byte* in)
|
||||
{
|
||||
if ((aes != NULL) && !WC_AES_KEY_IS_SET(aes)) {
|
||||
return MISSING_KEY;
|
||||
}
|
||||
|
||||
if (aes && (aes->dir != AES_ENCRYPTION)) {
|
||||
return KEYUSAGE_E;
|
||||
}
|
||||
|
|
@ -372,6 +392,10 @@ int wc_AesEncryptDirect(Aes* aes, byte* out, const byte* in)
|
|||
|
||||
int wc_AesDecryptDirect(Aes* aes, byte* out, const byte* in)
|
||||
{
|
||||
if ((aes != NULL) && !WC_AES_KEY_IS_SET(aes)) {
|
||||
return MISSING_KEY;
|
||||
}
|
||||
|
||||
if (aes && (aes->dir != AES_DECRYPTION)) {
|
||||
return KEYUSAGE_E;
|
||||
}
|
||||
|
|
@ -414,6 +438,10 @@ int wc_AesSetKeyDirect(Aes* aes, const byte* userKey, word32 keylen,
|
|||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
if (!WC_AES_KEY_IS_SET(aes)) {
|
||||
return MISSING_KEY;
|
||||
}
|
||||
|
||||
if (aes->dir != AES_ENCRYPTION) {
|
||||
return KEYUSAGE_E;
|
||||
}
|
||||
|
|
@ -578,6 +606,11 @@ int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len)
|
|||
XMEMCPY((byte*)(aes->key), key, len);
|
||||
#endif
|
||||
|
||||
/* Mark key installed so the shared aes.c mode guards accept this
|
||||
* context. Only after the key is copied, so a failed setup above does
|
||||
* not leave a keyless context marked as keyed. */
|
||||
aes->keyInstalled = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -622,6 +655,10 @@ int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz,
|
|||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
if (!WC_AES_KEY_IS_SET(aes)) {
|
||||
return MISSING_KEY;
|
||||
}
|
||||
|
||||
if (aes->alFd == WC_SOCK_NOTSET) {
|
||||
WOLFSSL_MSG("AF_ALG GcmEncrypt called with alFd unset");
|
||||
return BAD_FUNC_ARG;
|
||||
|
|
@ -818,6 +855,10 @@ int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz,
|
|||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
if (!WC_AES_KEY_IS_SET(aes)) {
|
||||
return MISSING_KEY;
|
||||
}
|
||||
|
||||
if (ivSz > WC_SYSTEM_AESGCM_IV)
|
||||
ivSz = WC_SYSTEM_AESGCM_IV;
|
||||
|
||||
|
|
@ -991,6 +1032,10 @@ int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz,
|
|||
#ifdef HAVE_AES_ECB
|
||||
int wc_AesEcbEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
|
||||
{
|
||||
if ((aes != NULL) && !WC_AES_KEY_IS_SET(aes)) {
|
||||
return MISSING_KEY;
|
||||
}
|
||||
|
||||
if (aes && (aes->dir != AES_ENCRYPTION)) {
|
||||
return KEYUSAGE_E;
|
||||
}
|
||||
|
|
@ -1001,6 +1046,10 @@ int wc_AesEcbEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
|
|||
|
||||
int wc_AesEcbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz)
|
||||
{
|
||||
if ((aes != NULL) && !WC_AES_KEY_IS_SET(aes)) {
|
||||
return MISSING_KEY;
|
||||
}
|
||||
|
||||
if (aes && (aes->dir != AES_DECRYPTION)) {
|
||||
return KEYUSAGE_E;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -103,6 +103,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) || \
|
||||
|
|
@ -1055,6 +1057,7 @@ int wc_AesInit(Aes* aes, void* heap, int devId)
|
|||
if (aes == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
XMEMSET(aes, 0, sizeof(Aes));
|
||||
aes->heap = heap;
|
||||
(void)devId;
|
||||
|
||||
|
|
|
|||
|
|
@ -16758,12 +16758,199 @@ 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. WOLF_CRYPTO_CB_FIND routes every call to the
|
||||
* callback regardless of devId, so the software guard is unreachable and the
|
||||
* callback rejects with its own error rather than MISSING_KEY.
|
||||
* WOLFSSL_AES_REQUIRE_KEY_SET additionally excludes the backends that replace
|
||||
* the mode entry points. */
|
||||
#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(WOLFSSL_AES_DIRECT) || defined(HAVE_AES_KEYWRAP)) && \
|
||||
defined(WOLFSSL_AES_REQUIRE_KEY_SET) && \
|
||||
!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) && \
|
||||
!defined(WOLF_CRYPTO_CB_FIND)
|
||||
#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
|
||||
#ifdef HAVE_AES_KEYWRAP
|
||||
byte wrapped[WC_AES_BLOCK_SIZE + KEYWRAP_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
|
||||
#ifdef HAVE_AES_KEYWRAP
|
||||
XMEMSET(wrapped, 0, sizeof(wrapped));
|
||||
#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(MISSING_KEY))
|
||||
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(MISSING_KEY))
|
||||
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(MISSING_KEY))
|
||||
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(MISSING_KEY))
|
||||
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(MISSING_KEY))
|
||||
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(MISSING_KEY))
|
||||
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(MISSING_KEY))
|
||||
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(MISSING_KEY))
|
||||
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(MISSING_KEY))
|
||||
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(MISSING_KEY))
|
||||
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(MISSING_KEY))
|
||||
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(MISSING_KEY))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
if (wc_AesCfb8Encrypt(aes, cipher, plain, 1) !=
|
||||
WC_NO_ERR_TRACE(MISSING_KEY))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
#ifdef HAVE_AES_DECRYPT
|
||||
if (wc_AesCfb1Decrypt(aes, cipher, plain, 8) !=
|
||||
WC_NO_ERR_TRACE(MISSING_KEY))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
if (wc_AesCfb8Decrypt(aes, cipher, plain, 1) !=
|
||||
WC_NO_ERR_TRACE(MISSING_KEY))
|
||||
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(MISSING_KEY))
|
||||
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(MISSING_KEY))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
#endif
|
||||
#endif /* WOLFSSL_AES_OFB */
|
||||
|
||||
#ifdef WOLFSSL_AES_DIRECT
|
||||
if (wc_AesEncryptDirect(aes, cipher, plain) !=
|
||||
WC_NO_ERR_TRACE(MISSING_KEY))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
#ifdef HAVE_AES_DECRYPT
|
||||
if (wc_AesDecryptDirect(aes, plain, cipher) !=
|
||||
WC_NO_ERR_TRACE(MISSING_KEY))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
#endif
|
||||
#endif /* WOLFSSL_AES_DIRECT */
|
||||
|
||||
#ifdef HAVE_AES_KEYWRAP
|
||||
if (wc_AesKeyWrap_ex(aes, plain, sizeof(plain), wrapped, sizeof(wrapped),
|
||||
NULL) != WC_NO_ERR_TRACE(MISSING_KEY))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
#ifdef HAVE_AES_DECRYPT
|
||||
if (wc_AesKeyUnWrap_ex(aes, wrapped, sizeof(wrapped), cipher,
|
||||
sizeof(cipher), NULL) != WC_NO_ERR_TRACE(MISSING_KEY))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
#endif
|
||||
#endif /* HAVE_AES_KEYWRAP */
|
||||
|
||||
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)
|
||||
|
|
@ -29908,6 +30095,9 @@ done:
|
|||
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;
|
||||
|
|
@ -30035,6 +30225,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
|
||||
|
|
|
|||
|
|
@ -189,6 +189,45 @@ WOLFSSL_LOCAL void WC_ARG_NOT_NULL(1) GHASH(Gcm* gcm, const byte* a,
|
|||
#include "cy_crypto_common.h"
|
||||
#endif /* WOLFSSL_PSOC6_CRYPTO */
|
||||
|
||||
/* Backends that replace one or more AES mode entry points, either with a
|
||||
* hardware arm in aes.c or with a port file. Those entry points do not carry
|
||||
* the key-set guard, so the check is not applied on these builds. */
|
||||
#if defined(STM32_CRYPTO) || \
|
||||
defined(HAVE_COLDFIRE_SEC) || \
|
||||
defined(FREESCALE_LTC) || \
|
||||
defined(FREESCALE_MMCAU) || \
|
||||
(defined(MAX3266X_AES) && !defined(MAX3266X_CB)) || \
|
||||
(defined(WOLFSSL_CRYPTOCELL) && defined(WOLFSSL_CRYPTOCELL_AES)) || \
|
||||
(defined(WOLFSSL_SCE) && !defined(WOLFSSL_SCE_NO_AES)) || \
|
||||
defined(WOLFSSL_SILABS_SE_ACCEL) || \
|
||||
defined(WOLFSSL_TI_CRYPT) || \
|
||||
(defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES) && \
|
||||
!defined(WOLFSSL_QNX_CAAM)) || \
|
||||
defined(WOLFSSL_KCAPI_AES) || \
|
||||
defined(WOLFSSL_DEVCRYPTO_AES) || defined(WOLFSSL_DEVCRYPTO_CBC) || \
|
||||
defined(WOLFSSL_NXP_HASHCRYPT_AES) || \
|
||||
(defined(WOLFSSL_HAVE_PSA) && !defined(WOLFSSL_PSA_NO_AES)) || \
|
||||
defined(WOLFSSL_XILINX_CRYPT) || \
|
||||
defined(WOLF_CRYPTO_CB_ONLY_AES)
|
||||
#define WC_AES_KEY_SET_CHECK_UNSUPPORTED
|
||||
#endif
|
||||
|
||||
/* Make the AES mode APIs return MISSING_KEY when called before a key is
|
||||
* installed, instead of running with the all-zero key schedule left by
|
||||
* wc_AesInit. Define WOLFSSL_AES_REQUIRE_KEY_SET to force the check on, or
|
||||
* WOLFSSL_NO_AES_KEY_SET_CHECK to force it off. */
|
||||
#if !defined(WOLFSSL_AES_REQUIRE_KEY_SET) && \
|
||||
!defined(WOLFSSL_NO_AES_KEY_SET_CHECK) && \
|
||||
!defined(WC_AES_KEY_SET_CHECK_UNSUPPORTED)
|
||||
#define WOLFSSL_AES_REQUIRE_KEY_SET
|
||||
#endif
|
||||
|
||||
#ifdef WOLFSSL_AES_REQUIRE_KEY_SET
|
||||
#define WC_AES_KEY_IS_SET(aes) ((aes)->keyInstalled != 0)
|
||||
#else
|
||||
#define WC_AES_KEY_IS_SET(aes) (1)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
|
@ -482,6 +521,22 @@ struct Aes {
|
|||
cy_stc_crypto_aes_gcm_state_t aes_gcm_state;
|
||||
#endif
|
||||
#endif /* WOLFSSL_PSOC6_CRYPTO */
|
||||
|
||||
/* Set to 1 once a key has been installed (wc_AesSetKey/SetKeyDirect/
|
||||
* GcmSetKey), including when a crypto callback takes ownership of it.
|
||||
* 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. Appended at the end of the struct so existing member
|
||||
* offsets are unchanged. Always maintained, so the layout does not depend
|
||||
* on WOLFSSL_AES_REQUIRE_KEY_SET.
|
||||
*
|
||||
* Deliberately NOT set by wc_AesInit_Id()/wc_AesInit_Label(): those name a
|
||||
* key held by the device and leave the software key schedule empty. The
|
||||
* guard sits after every offload dispatch, so such a context still reaches
|
||||
* its crypto callback; it only fails if it falls through to a software
|
||||
* path, which is exactly the case that would otherwise encrypt with an
|
||||
* all-zero key. */
|
||||
WC_BITFIELD keyInstalled:1;
|
||||
};
|
||||
|
||||
#ifndef WC_AES_TYPE_DEFINED
|
||||
|
|
|
|||
Loading…
Reference in New Issue