Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
143 changes: 142 additions & 1 deletion wolfcrypt/src/aes.c

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions wolfcrypt/src/port/af_alg/afalg_aes.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions wolfcrypt/src/port/caam/caam_aes.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions wolfcrypt/src/port/devcrypto/devcrypto_aes.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
3 changes: 3 additions & 0 deletions wolfcrypt/src/port/kcapi/kcapi_aes.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
3 changes: 3 additions & 0 deletions wolfcrypt/src/port/silabs/silabs_aes.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions wolfcrypt/src/port/ti/ti-aes.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) || \
Expand Down
180 changes: 180 additions & 0 deletions wolfcrypt/test/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) !=
Comment thread
julek-wolfssl marked this conversation as resolved.
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)
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down
6 changes: 6 additions & 0 deletions wolfssl/wolfcrypt/aes.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Comment thread
Frauschi marked this conversation as resolved.

Comment thread
julek-wolfssl marked this conversation as resolved.
ALIGN16 word32 reg[WC_AES_BLOCK_SIZE / sizeof(word32)]; /* for CBC mode */
ALIGN16 word32 tmp[WC_AES_BLOCK_SIZE / sizeof(word32)]; /* same */

Expand Down
Loading