diff --git a/tests/api/test_aes.c b/tests/api/test_aes.c index c463cea61d3..ce0c842e490 100644 --- a/tests/api/test_aes.c +++ b/tests/api/test_aes.c @@ -12321,3 +12321,179 @@ int test_wc_AesOfb_MonteCarlo(void) #endif return EXPECT_RESULT(); } + +#if defined(WOLF_CRYPTO_CB) && !defined(NO_AES) && defined(HAVE_AES_ECB) && \ + defined(WOLFSSL_AES_128) && !defined(WOLF_CRYPTO_CB_ONLY_AES) && \ + (defined(WOLFSSL_AES_COUNTER) || defined(HAVE_AESGCM)) + +#define TEST_CRYPTOCB_AESECB_FAIL_DEVID 13 + +static int cryptoCbAesEcbFailCalled = 0; + +static int test_CryptoCb_AesEcbFail_Cb(int devId, wc_CryptoInfo* info, + void* ctx) +{ + (void)devId; + (void)ctx; + + if (info->algo_type == WC_ALGO_TYPE_CIPHER && + info->cipher.type == WC_CIPHER_AES_ECB) { + cryptoCbAesEcbFailCalled++; + return WC_HW_E; + } + + return CRYPTOCB_UNAVAILABLE; +} + +#define TEST_AESECB_FAIL_SZ (2 * WC_AES_BLOCK_SIZE) + +int test_wc_AesEcb_RetCodeChecked(void) +{ + EXPECT_DECLS; + const byte key[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f + }; + byte plain[TEST_AESECB_FAIL_SZ]; + byte out[TEST_AESECB_FAIL_SZ]; + byte zeros[TEST_AESECB_FAIL_SZ]; + int devRegistered = 0; + int exercised = 0; + + XMEMSET(plain, 0x5a, sizeof(plain)); + XMEMSET(zeros, 0, sizeof(zeros)); + + ExpectIntEQ(wc_CryptoCb_RegisterDevice(TEST_CRYPTOCB_AESECB_FAIL_DEVID, + test_CryptoCb_AesEcbFail_Cb, NULL), 0); + if (EXPECT_SUCCESS()) + devRegistered = 1; + +#ifdef WOLFSSL_AES_COUNTER + { + Aes aes; + int ret = 0; + byte iv[WC_AES_BLOCK_SIZE] = { + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0x00 + }; + + XMEMSET(&aes, 0, sizeof(aes)); + XMEMSET(out, 0, sizeof(out)); + cryptoCbAesEcbFailCalled = 0; + + ExpectIntEQ(wc_AesInit(&aes, NULL, TEST_CRYPTOCB_AESECB_FAIL_DEVID), 0); + ExpectIntEQ(wc_AesSetKey(&aes, key, sizeof(key), iv, AES_ENCRYPTION), 0); +#ifdef WOLFSSL_AESNI + aes.use_aesni = 0; +#endif + if (EXPECT_SUCCESS()) + ret = wc_AesCtrEncrypt(&aes, out, plain, sizeof(plain)); + + if (cryptoCbAesEcbFailCalled != 0) { + exercised = 1; + ExpectIntEQ(ret, WC_NO_ERR_TRACE(WC_HW_E)); + ExpectBufEQ(out, zeros, sizeof(out)); + } + + wc_AesFree(&aes); + } +#endif /* WOLFSSL_AES_COUNTER */ + +#ifdef HAVE_AESGCM + { + Aes aes; + int ret = 0; + byte iv[GCM_NONCE_MID_SZ] = { + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, + 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb + }; + byte tag[WC_AES_BLOCK_SIZE]; + + XMEMSET(tag, 0, sizeof(tag)); + + XMEMSET(&aes, 0, sizeof(aes)); + XMEMSET(out, 0, sizeof(out)); + cryptoCbAesEcbFailCalled = 0; + + ExpectIntEQ(wc_AesInit(&aes, NULL, TEST_CRYPTOCB_AESECB_FAIL_DEVID), 0); + ExpectIntEQ(wc_AesGcmSetKey(&aes, key, sizeof(key)), 0); +#ifdef WOLFSSL_AESNI + aes.use_aesni = 0; +#endif + if (EXPECT_SUCCESS()) { + ret = wc_AesGcmEncrypt(&aes, out, plain, sizeof(plain), + iv, sizeof(iv), tag, sizeof(tag), NULL, 0); + } + if (cryptoCbAesEcbFailCalled != 0) { + exercised = 1; + ExpectIntEQ(ret, WC_NO_ERR_TRACE(WC_HW_E)); + ExpectBufEQ(out, zeros, sizeof(out)); + } + wc_AesFree(&aes); + + XMEMSET(&aes, 0, sizeof(aes)); + XMEMSET(out, 0, sizeof(out)); + cryptoCbAesEcbFailCalled = 0; + + ExpectIntEQ(wc_AesInit(&aes, NULL, TEST_CRYPTOCB_AESECB_FAIL_DEVID), 0); + ExpectIntEQ(wc_AesGcmSetKey(&aes, key, sizeof(key)), 0); +#ifdef WOLFSSL_AESNI + aes.use_aesni = 0; +#endif + /* the tag is bogus, but the ECB failure is hit before it is checked + * unless the build authenticates early */ + if (EXPECT_SUCCESS()) { + ret = wc_AesGcmDecrypt(&aes, out, plain, sizeof(plain), + iv, sizeof(iv), tag, sizeof(tag), NULL, 0); + } + if (cryptoCbAesEcbFailCalled != 0) { + exercised = 1; + ExpectIntEQ(ret, WC_NO_ERR_TRACE(WC_HW_E)); + ExpectBufEQ(out, zeros, sizeof(out)); + } + wc_AesFree(&aes); + +#ifdef WOLFSSL_AESGCM_STREAM + XMEMSET(&aes, 0, sizeof(aes)); + XMEMSET(out, 0, sizeof(out)); + cryptoCbAesEcbFailCalled = 0; + + ExpectIntEQ(wc_AesInit(&aes, NULL, TEST_CRYPTOCB_AESECB_FAIL_DEVID), 0); + ExpectIntEQ(wc_AesGcmEncryptInit(&aes, key, sizeof(key), iv, + sizeof(iv)), 0); +#ifdef WOLFSSL_AESNI + aes.use_aesni = 0; +#endif + if (EXPECT_SUCCESS()) { + ret = wc_AesGcmEncryptUpdate(&aes, out, plain, sizeof(plain), + NULL, 0); + } + if (cryptoCbAesEcbFailCalled != 0) { + exercised = 1; + ExpectIntEQ(ret, WC_NO_ERR_TRACE(WC_HW_E)); + ExpectBufEQ(out, zeros, sizeof(out)); + } + wc_AesFree(&aes); +#endif /* WOLFSSL_AESGCM_STREAM */ + } +#endif /* HAVE_AESGCM */ + + if (devRegistered) + wc_CryptoCb_UnRegisterDevice(TEST_CRYPTOCB_AESECB_FAIL_DEVID); + + /* no mode in this build stages its keystream with wc_AesEcbEncrypt() */ + if (EXPECT_SUCCESS() && !exercised) + return TEST_SKIPPED; + + return EXPECT_RESULT(); +} + +#else + +int test_wc_AesEcb_RetCodeChecked(void) +{ + return TEST_SKIPPED; +} + +#endif /* WOLF_CRYPTO_CB && !NO_AES && HAVE_AES_ECB && WOLFSSL_AES_128 && + * !WOLF_CRYPTO_CB_ONLY_AES && (WOLFSSL_AES_COUNTER || HAVE_AESGCM) */ diff --git a/tests/api/test_aes.h b/tests/api/test_aes.h index 7b067a21d05..3021189db70 100644 --- a/tests/api/test_aes.h +++ b/tests/api/test_aes.h @@ -119,6 +119,7 @@ int test_wc_CryptoCb_AesCfb_EncryptDecrypt(void); !defined(WOLF_CRYPTO_CB_ONLY_AES) int test_wc_CryptoCb_AesOfb_EncryptDecrypt(void); #endif +int test_wc_AesEcb_RetCodeChecked(void); /* These test functions always have a (possibly empty) definition in * test_aes.c so that callers can reference them unconditionally. Declare @@ -226,7 +227,8 @@ int test_wc_CryptoCb_Tls13_Key_No_Zero_Without_Offload(void); TEST_DECL_GROUP("aes", test_wc_AesGcm_MonteCarlo), \ TEST_DECL_GROUP("aes", test_wc_AesCcm_MonteCarlo), \ TEST_DECL_GROUP("aes", test_wc_AesCfb_MonteCarlo), \ - TEST_DECL_GROUP("aes", test_wc_AesOfb_MonteCarlo) \ + TEST_DECL_GROUP("aes", test_wc_AesOfb_MonteCarlo), \ + TEST_DECL_GROUP("aes", test_wc_AesEcb_RetCodeChecked) \ TEST_CRYPTOCB_AES_SETKEY_DECL \ TEST_CRYPTOCB_TLS13_KEY_ZERO_DECL \ TEST_CRYPTOCB_AESCFB_DECL \ diff --git a/wolfcrypt/src/aes.c b/wolfcrypt/src/aes.c index 77b73d9d57c..2642b1c1a0a 100644 --- a/wolfcrypt/src/aes.c +++ b/wolfcrypt/src/aes.c @@ -7921,11 +7921,17 @@ int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) /* reset number of blocks and then do encryption */ blocks = sz / WC_AES_BLOCK_SIZE; - wc_AesEcbEncrypt(aes, out, out, WC_AES_BLOCK_SIZE * blocks); - xorbuf(out, in, WC_AES_BLOCK_SIZE * blocks); - in += WC_AES_BLOCK_SIZE * blocks; - out += WC_AES_BLOCK_SIZE * blocks; - sz -= blocks * WC_AES_BLOCK_SIZE; + ret = wc_AesEcbEncrypt(aes, out, out, + WC_AES_BLOCK_SIZE * blocks); + if (ret == 0) { + xorbuf(out, in, WC_AES_BLOCK_SIZE * blocks); + in += WC_AES_BLOCK_SIZE * blocks; + out += WC_AES_BLOCK_SIZE * blocks; + sz -= blocks * WC_AES_BLOCK_SIZE; + } + else { + ForceZero(out, WC_AES_BLOCK_SIZE * blocks); + } } else #endif @@ -10752,7 +10758,11 @@ WARN_UNUSED_RESULT int AES_GCM_encrypt_C( /* reset number of blocks and then do encryption */ blocks = sz / WC_AES_BLOCK_SIZE; - wc_AesEcbEncrypt(aes, out, out, WC_AES_BLOCK_SIZE * blocks); + ret = wc_AesEcbEncrypt(aes, out, out, WC_AES_BLOCK_SIZE * blocks); + if (ret != 0) { + ForceZero(out, WC_AES_BLOCK_SIZE * blocks); + return ret; + } xorbuf(out, p, WC_AES_BLOCK_SIZE * blocks); p += WC_AES_BLOCK_SIZE * blocks; } @@ -11572,7 +11582,11 @@ int WARN_UNUSED_RESULT AES_GCM_decrypt_C( /* reset number of blocks and then do encryption */ blocks = sz / WC_AES_BLOCK_SIZE; - wc_AesEcbEncrypt(aes, out, out, WC_AES_BLOCK_SIZE * blocks); + ret = wc_AesEcbEncrypt(aes, out, out, WC_AES_BLOCK_SIZE * blocks); + if (ret != 0) { + ForceZero(out, WC_AES_BLOCK_SIZE * blocks); + return ret; + } xorbuf(out, c, WC_AES_BLOCK_SIZE * blocks); c += WC_AES_BLOCK_SIZE * blocks; } @@ -12081,7 +12095,11 @@ static WARN_UNUSED_RESULT int AesGcmCryptUpdate_C( } /* Encrypt counter blocks. */ - wc_AesEcbEncrypt(aes, out, out, WC_AES_BLOCK_SIZE * blocks); + ret = wc_AesEcbEncrypt(aes, out, out, WC_AES_BLOCK_SIZE * blocks); + if (ret != 0) { + ForceZero(out, WC_AES_BLOCK_SIZE * blocks); + return ret; + } /* XOR in plaintext. */ xorbuf(out, in, WC_AES_BLOCK_SIZE * blocks); /* Skip over processed data. */