diff --git a/wolfcrypt/src/aes.c b/wolfcrypt/src/aes.c index 6806acbc965..728f52e07a1 100644 --- a/wolfcrypt/src/aes.c +++ b/wolfcrypt/src/aes.c @@ -4871,7 +4871,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->keySet = 1; + return ret; } #if defined(WOLFSSL_AES_DIRECT) @@ -5188,6 +5191,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->keySet = 1; if (iv != NULL) XMEMCPY(aes->reg, iv, WC_AES_BLOCK_SIZE); else @@ -5304,6 +5308,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->keySet = 1; #if defined(WOLFSSL_AES_COUNTER) || defined(WOLFSSL_AES_CFB) || \ defined(WOLFSSL_AES_OFB) || defined(WOLFSSL_AES_XTS) || \ defined(WOLFSSL_AES_CTS) @@ -5333,6 +5338,7 @@ static void AesSetKey_C(Aes* aes, const byte* key, word32 keySz, int dir) aes->keylen = (int)keylen; aes->rounds = (keylen/4) + 6; + aes->keySet = 1; ret = wc_AesSetIV(aes, iv); if (ret != 0) return ret; @@ -6699,12 +6705,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->keySet == 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->keySet == 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 +6774,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->keySet == 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 +6991,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->keySet == 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 +7453,12 @@ int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) } #endif + /* Software/HW key schedule required from here on. */ + if (aes->keySet == 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 +10457,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->keySet == 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 +11213,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->keySet == 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 +14495,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->keySet == 0) { + WOLFSSL_MSG("AES key not set"); + return BAD_FUNC_ARG; + } return wc_Psoc6_Aes_EcbEncrypt(aes, out, in, sz); } @@ -14460,6 +14510,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->keySet == 0) { + WOLFSSL_MSG("AES key not set"); + return BAD_FUNC_ARG; + } return wc_Psoc6_Aes_EcbDecrypt(aes, out, in, sz); } @@ -14497,6 +14551,12 @@ static WARN_UNUSED_RESULT int _AesEcbEncrypt( return DCPAesEcbEncrypt(aes, out, in, sz); #endif + /* Software key schedule required from here on. */ + if (aes->keySet == 0) { + WOLFSSL_MSG("AES key not set"); + return BAD_FUNC_ARG; + } + VECTOR_REGISTERS_PUSH; #if !defined(__aarch64__) && defined(WOLFSSL_ARMASM) @@ -14592,6 +14652,12 @@ static WARN_UNUSED_RESULT int _AesEcbDecrypt( return DCPAesEcbDecrypt(aes, out, in, sz); #endif + /* Software key schedule required from here on. */ + if (aes->keySet == 0) { + WOLFSSL_MSG("AES key not set"); + return BAD_FUNC_ARG; + } + VECTOR_REGISTERS_PUSH; #if !defined(__aarch64__) && defined(WOLFSSL_ARMASM) @@ -14694,12 +14760,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->keySet == 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->keySet == 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 +14806,10 @@ static WARN_UNUSED_RESULT int AesCfbEncrypt_C(Aes* aes, byte* out, if (sz == 0) { return 0; } + if (aes->keySet == 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 +14885,10 @@ static WARN_UNUSED_RESULT int AesCfbDecrypt_C(Aes* aes, byte* out, if (sz == 0) { return 0; } + if (aes->keySet == 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 +15033,10 @@ static WARN_UNUSED_RESULT int wc_AesFeedbackCFB8( if (sz == 0) { return 0; } + if (aes->keySet == 0) { + WOLFSSL_MSG("AES key not set"); + return BAD_FUNC_ARG; + } VECTOR_REGISTERS_PUSH; @@ -15011,6 +15097,10 @@ static WARN_UNUSED_RESULT int wc_AesFeedbackCFB1( if (sz == 0) { return 0; } + if (aes->keySet == 0) { + WOLFSSL_MSG("AES key not set"); + return BAD_FUNC_ARG; + } VECTOR_REGISTERS_PUSH; @@ -15169,6 +15259,10 @@ static WARN_UNUSED_RESULT int AesOfbCrypt_C(Aes* aes, byte* out, const byte* in, if (sz == 0) { return 0; } + if (aes->keySet == 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/test/test.c b/wolfcrypt/test/test.c index e95bba5ae5e..6abf9276536 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -16122,12 +16122,145 @@ static wc_test_ret_t aes_ecb_direct_test(void) } #endif /* HAVE_AES_ECB || WOLFSSL_AES_DIRECT */ +#if defined(HAVE_AES_CBC) || defined(WOLFSSL_AES_COUNTER) || \ + defined(HAVE_AESGCM) || defined(HAVE_AES_ECB) || \ + defined(WOLFSSL_AES_CFB) || defined(WOLFSSL_AES_OFB) +#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 +27375,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 +27505,27 @@ 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 + if (ret != WC_NO_ERR_TRACE(BAD_PADDING_E)) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), 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..1ed4c73ef4e 100644 --- a/wolfssl/wolfcrypt/aes.h +++ b/wolfssl/wolfcrypt/aes.h @@ -292,6 +292,11 @@ 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. */ + WC_BITFIELD keySet:1; + ALIGN16 word32 reg[WC_AES_BLOCK_SIZE / sizeof(word32)]; /* for CBC mode */ ALIGN16 word32 tmp[WC_AES_BLOCK_SIZE / sizeof(word32)]; /* same */