diff --git a/.github/workflows/os-check.yml b/.github/workflows/os-check.yml index a6b9b945940..da114b398d0 100644 --- a/.github/workflows/os-check.yml +++ b/.github/workflows/os-check.yml @@ -243,6 +243,10 @@ jobs: {"name": "cryptocb-utils-setkey-export-find", "minutes": 2.2, "configure": ["--enable-cryptocb", "--enable-keygen", "--enable-cryptocbutils=setkey,export", "CPPFLAGS=-DWOLF_CRYPTO_CB_FIND"]}, + {"name": "cryptocb-aes-cfb-ofb", "minutes": 2.2, + "comment": "Exercises the AES-CFB/OFB crypto callback wiring (wc_CryptoCb_AesCfb/Ofb Encrypt/Decrypt, the aes.c hooks, and the dedicated offload unit tests). A normal (non-ONLY) cryptocb build keeps the host software AES present as the callbacks' offload fallback; WOLF_CRYPTO_CB_ONLY_AES (no software fallback) is covered separately by cryptocb-only.yml via swdev.", + "configure": ["--enable-cryptocb", "--enable-aescfb", + "--enable-aesofb", "--enable-aesctr"]}, {"name": "opensslall-rng-seed-cb-no-getpid", "minutes": 2.1, "configure": ["--enable-opensslall", "--enable-opensslextra", "CPPFLAGS=-DWC_RNG_SEED_CB -DWOLFSSL_NO_GETPID"]}, diff --git a/tests/api/test_aes.c b/tests/api/test_aes.c index 72221cd04ad..322be5ae31a 100644 --- a/tests/api/test_aes.c +++ b/tests/api/test_aes.c @@ -8701,6 +8701,306 @@ int test_wc_CryptoCb_AesGcm_EncryptDecrypt(void) #endif /* WOLF_CRYPTO_CB && WOLF_CRYPTO_CB_AES_SETKEY && !NO_AES && HAVE_AESGCM */ +/*----------------------------------------------------------------------------* + | CryptoCB AES-CFB End-to-End Offload Test + *----------------------------------------------------------------------------*/ + +#if defined(WOLF_CRYPTO_CB) && !defined(NO_AES) && defined(WOLFSSL_AES_CFB) && \ + !defined(WOLF_CRYPTO_CB_ONLY_AES) + +#define TEST_CRYPTOCB_AESCFB_DEVID 10 + +static int cryptoCbAesCfbEncryptCalled = 0; +static int cryptoCbAesCfbDecryptCalled = 0; + +/* Mock CryptoCB callback that "offloads" AES-CFB. It routes the request back + * to the software implementation, temporarily setting devId to INVALID_DEVID + * so the nested wc_AesCfb*crypt() call runs in software instead of recursing + * into the callback. */ +static int test_CryptoCb_AesCfb_Cb(int devId, wc_CryptoInfo* info, void* ctx) +{ + (void)ctx; + + if (devId != TEST_CRYPTOCB_AESCFB_DEVID) + return CRYPTOCB_UNAVAILABLE; + + if (info->algo_type == WC_ALGO_TYPE_CIPHER && + info->cipher.type == WC_CIPHER_AES_CFB) { + Aes* aes = info->cipher.aescfb.aes; + int ret; + + if (aes == NULL) + return BAD_FUNC_ARG; + + /* run software, no recursion */ + aes->devId = INVALID_DEVID; + if (info->cipher.enc) { + cryptoCbAesCfbEncryptCalled++; + ret = wc_AesCfbEncrypt(aes, info->cipher.aescfb.out, + info->cipher.aescfb.in, info->cipher.aescfb.sz); + } +#ifdef HAVE_AES_DECRYPT + else { + cryptoCbAesCfbDecryptCalled++; + ret = wc_AesCfbDecrypt(aes, info->cipher.aescfb.out, + info->cipher.aescfb.in, info->cipher.aescfb.sz); + } +#else + else { + ret = NOT_COMPILED_IN; + } +#endif + aes->devId = TEST_CRYPTOCB_AESCFB_DEVID; + + return ret; + } + + return CRYPTOCB_UNAVAILABLE; +} + +/* + * Test: End-to-End AES-CFB Offload via CryptoCB + * Verifies that wc_AesCfbEncrypt/Decrypt route through a registered CryptoCB + * device, that the callback is invoked for both directions, that the offloaded + * ciphertext matches a software-only reference (correctness), and that the + * offloaded round-trip recovers the plaintext. + */ +int test_wc_CryptoCb_AesCfb_EncryptDecrypt(void) +{ + EXPECT_DECLS; +#if defined(WOLFSSL_AES_128) + Aes enc; +#ifdef HAVE_AES_DECRYPT + Aes dec; +#endif + static const byte key[AES_128_KEY_SIZE] = { + 0x2b,0x7e,0x15,0x16, 0x28,0xae,0xd2,0xa6, + 0xab,0xf7,0x15,0x88, 0x09,0xcf,0x4f,0x3c + }; + static const byte iv[WC_AES_BLOCK_SIZE] = { + 0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07, + 0x08,0x09,0x0a,0x0b, 0x0c,0x0d,0x0e,0x0f + }; + static const byte plain[2 * WC_AES_BLOCK_SIZE] = { + 0x6b,0xc1,0xbe,0xe2, 0x2e,0x40,0x9f,0x96, + 0xe9,0x3d,0x7e,0x11, 0x73,0x93,0x17,0x2a, + 0xae,0x2d,0x8a,0x57, 0x1e,0x03,0xac,0x9c, + 0x9e,0xb7,0x6f,0xac, 0x45,0xaf,0x8e,0x51 + }; + byte refCipher[2 * WC_AES_BLOCK_SIZE]; + byte cipher[2 * WC_AES_BLOCK_SIZE]; + byte decrypted[2 * WC_AES_BLOCK_SIZE]; + int devRegistered = 0; + + XMEMSET(&enc, 0, sizeof(enc)); +#ifdef HAVE_AES_DECRYPT + XMEMSET(&dec, 0, sizeof(dec)); +#endif + XMEMSET(refCipher, 0, sizeof(refCipher)); + XMEMSET(cipher, 0, sizeof(cipher)); + XMEMSET(decrypted, 0, sizeof(decrypted)); + + cryptoCbAesCfbEncryptCalled = 0; + cryptoCbAesCfbDecryptCalled = 0; + + /* Software-only reference ciphertext (no devId, no callback). */ + ExpectIntEQ(wc_AesInit(&enc, NULL, INVALID_DEVID), 0); + ExpectIntEQ(wc_AesSetKey(&enc, key, sizeof(key), iv, AES_ENCRYPTION), 0); + ExpectIntEQ(wc_AesCfbEncrypt(&enc, refCipher, plain, sizeof(plain)), 0); + wc_AesFree(&enc); + XMEMSET(&enc, 0, sizeof(enc)); + + /* Register the offload callback. */ + ExpectIntEQ(wc_CryptoCb_RegisterDevice(TEST_CRYPTOCB_AESCFB_DEVID, + test_CryptoCb_AesCfb_Cb, NULL), 0); + if (EXPECT_SUCCESS()) + devRegistered = 1; + + /* Both contexts carry the offload devId so the AES-CFB calls route through + * the callback. */ + ExpectIntEQ(wc_AesInit(&enc, NULL, TEST_CRYPTOCB_AESCFB_DEVID), 0); + ExpectIntEQ(wc_AesSetKey(&enc, key, sizeof(key), iv, AES_ENCRYPTION), 0); +#ifdef HAVE_AES_DECRYPT + ExpectIntEQ(wc_AesInit(&dec, NULL, TEST_CRYPTOCB_AESCFB_DEVID), 0); + ExpectIntEQ(wc_AesSetKey(&dec, key, sizeof(key), iv, AES_ENCRYPTION), 0); +#endif + + /* Encrypt - must route through the callback and match the SW reference. */ + ExpectIntEQ(wc_AesCfbEncrypt(&enc, cipher, plain, sizeof(plain)), 0); + ExpectIntEQ(cryptoCbAesCfbEncryptCalled, 1); + ExpectBufEQ(cipher, refCipher, sizeof(refCipher)); + +#ifdef HAVE_AES_DECRYPT + /* Decrypt - must route through the callback and recover the plaintext. */ + ExpectIntEQ(wc_AesCfbDecrypt(&dec, decrypted, cipher, sizeof(cipher)), 0); + ExpectIntEQ(cryptoCbAesCfbDecryptCalled, 1); + ExpectBufEQ(decrypted, plain, sizeof(plain)); +#endif + + wc_AesFree(&enc); +#ifdef HAVE_AES_DECRYPT + wc_AesFree(&dec); +#endif + + if (devRegistered) + wc_CryptoCb_UnRegisterDevice(TEST_CRYPTOCB_AESCFB_DEVID); +#endif /* WOLFSSL_AES_128 */ + return EXPECT_RESULT(); +} + +#endif /* WOLF_CRYPTO_CB && !NO_AES && WOLFSSL_AES_CFB && !WOLF_CRYPTO_CB_ONLY_AES */ + + +/*----------------------------------------------------------------------------* + | CryptoCB AES-OFB End-to-End Offload Test + *----------------------------------------------------------------------------*/ + +#if defined(WOLF_CRYPTO_CB) && !defined(NO_AES) && defined(WOLFSSL_AES_OFB) && \ + !defined(WOLF_CRYPTO_CB_ONLY_AES) + +#define TEST_CRYPTOCB_AESOFB_DEVID 11 + +static int cryptoCbAesOfbEncryptCalled = 0; +static int cryptoCbAesOfbDecryptCalled = 0; + +/* Mock CryptoCB callback that "offloads" AES-OFB. It routes the request back + * to the software implementation, temporarily setting devId to INVALID_DEVID + * so the nested wc_AesOfb*crypt() call runs in software instead of recursing + * into the callback. */ +static int test_CryptoCb_AesOfb_Cb(int devId, wc_CryptoInfo* info, void* ctx) +{ + (void)ctx; + + if (devId != TEST_CRYPTOCB_AESOFB_DEVID) + return CRYPTOCB_UNAVAILABLE; + + if (info->algo_type == WC_ALGO_TYPE_CIPHER && + info->cipher.type == WC_CIPHER_AES_OFB) { + Aes* aes = info->cipher.aesofb.aes; + int ret; + + if (aes == NULL) + return BAD_FUNC_ARG; + + /* run software, no recursion */ + aes->devId = INVALID_DEVID; + if (info->cipher.enc) { + cryptoCbAesOfbEncryptCalled++; + ret = wc_AesOfbEncrypt(aes, info->cipher.aesofb.out, + info->cipher.aesofb.in, info->cipher.aesofb.sz); + } +#ifdef HAVE_AES_DECRYPT + else { + cryptoCbAesOfbDecryptCalled++; + ret = wc_AesOfbDecrypt(aes, info->cipher.aesofb.out, + info->cipher.aesofb.in, info->cipher.aesofb.sz); + } +#else + else { + ret = NOT_COMPILED_IN; + } +#endif + aes->devId = TEST_CRYPTOCB_AESOFB_DEVID; + + return ret; + } + + return CRYPTOCB_UNAVAILABLE; +} + +/* + * Test: End-to-End AES-OFB Offload via CryptoCB + * Verifies that wc_AesOfbEncrypt/Decrypt route through a registered CryptoCB + * device, that the callback is invoked for both directions, that the offloaded + * ciphertext matches a software-only reference (correctness), and that the + * offloaded round-trip recovers the plaintext. + */ +int test_wc_CryptoCb_AesOfb_EncryptDecrypt(void) +{ + EXPECT_DECLS; +#if defined(WOLFSSL_AES_128) + Aes enc; +#ifdef HAVE_AES_DECRYPT + Aes dec; +#endif + static const byte key[AES_128_KEY_SIZE] = { + 0x2b,0x7e,0x15,0x16, 0x28,0xae,0xd2,0xa6, + 0xab,0xf7,0x15,0x88, 0x09,0xcf,0x4f,0x3c + }; + static const byte iv[WC_AES_BLOCK_SIZE] = { + 0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07, + 0x08,0x09,0x0a,0x0b, 0x0c,0x0d,0x0e,0x0f + }; + static const byte plain[2 * WC_AES_BLOCK_SIZE] = { + 0x6b,0xc1,0xbe,0xe2, 0x2e,0x40,0x9f,0x96, + 0xe9,0x3d,0x7e,0x11, 0x73,0x93,0x17,0x2a, + 0xae,0x2d,0x8a,0x57, 0x1e,0x03,0xac,0x9c, + 0x9e,0xb7,0x6f,0xac, 0x45,0xaf,0x8e,0x51 + }; + byte refCipher[2 * WC_AES_BLOCK_SIZE]; + byte cipher[2 * WC_AES_BLOCK_SIZE]; + byte decrypted[2 * WC_AES_BLOCK_SIZE]; + int devRegistered = 0; + + XMEMSET(&enc, 0, sizeof(enc)); +#ifdef HAVE_AES_DECRYPT + XMEMSET(&dec, 0, sizeof(dec)); +#endif + XMEMSET(refCipher, 0, sizeof(refCipher)); + XMEMSET(cipher, 0, sizeof(cipher)); + XMEMSET(decrypted, 0, sizeof(decrypted)); + + cryptoCbAesOfbEncryptCalled = 0; + cryptoCbAesOfbDecryptCalled = 0; + + /* Software-only reference ciphertext (no devId, no callback). */ + ExpectIntEQ(wc_AesInit(&enc, NULL, INVALID_DEVID), 0); + ExpectIntEQ(wc_AesSetKey(&enc, key, sizeof(key), iv, AES_ENCRYPTION), 0); + ExpectIntEQ(wc_AesOfbEncrypt(&enc, refCipher, plain, sizeof(plain)), 0); + wc_AesFree(&enc); + XMEMSET(&enc, 0, sizeof(enc)); + + /* Register the offload callback. */ + ExpectIntEQ(wc_CryptoCb_RegisterDevice(TEST_CRYPTOCB_AESOFB_DEVID, + test_CryptoCb_AesOfb_Cb, NULL), 0); + if (EXPECT_SUCCESS()) + devRegistered = 1; + + /* Both contexts carry the offload devId so the AES-OFB calls route through + * the callback. */ + ExpectIntEQ(wc_AesInit(&enc, NULL, TEST_CRYPTOCB_AESOFB_DEVID), 0); + ExpectIntEQ(wc_AesSetKey(&enc, key, sizeof(key), iv, AES_ENCRYPTION), 0); +#ifdef HAVE_AES_DECRYPT + ExpectIntEQ(wc_AesInit(&dec, NULL, TEST_CRYPTOCB_AESOFB_DEVID), 0); + ExpectIntEQ(wc_AesSetKey(&dec, key, sizeof(key), iv, AES_ENCRYPTION), 0); +#endif + + /* Encrypt - must route through the callback and match the SW reference. */ + ExpectIntEQ(wc_AesOfbEncrypt(&enc, cipher, plain, sizeof(plain)), 0); + ExpectIntEQ(cryptoCbAesOfbEncryptCalled, 1); + ExpectBufEQ(cipher, refCipher, sizeof(refCipher)); + +#ifdef HAVE_AES_DECRYPT + /* Decrypt - must route through the callback and recover the plaintext. */ + ExpectIntEQ(wc_AesOfbDecrypt(&dec, decrypted, cipher, sizeof(cipher)), 0); + ExpectIntEQ(cryptoCbAesOfbDecryptCalled, 1); + ExpectBufEQ(decrypted, plain, sizeof(plain)); +#endif + + wc_AesFree(&enc); +#ifdef HAVE_AES_DECRYPT + wc_AesFree(&dec); +#endif + + if (devRegistered) + wc_CryptoCb_UnRegisterDevice(TEST_CRYPTOCB_AESOFB_DEVID); +#endif /* WOLFSSL_AES_128 */ + return EXPECT_RESULT(); +} + +#endif /* WOLF_CRYPTO_CB && !NO_AES && WOLFSSL_AES_OFB && !WOLF_CRYPTO_CB_ONLY_AES */ + + /*----------------------------------------------------------------------------* | CryptoCB AES-GCM TLS 1.3 Key Zeroing Tests *----------------------------------------------------------------------------*/ diff --git a/tests/api/test_aes.h b/tests/api/test_aes.h index 73e4b715ac9..42cb36ec71b 100644 --- a/tests/api/test_aes.h +++ b/tests/api/test_aes.h @@ -94,6 +94,14 @@ int test_wc_GmacUpdate(void); int test_wc_CryptoCb_AesSetKey(void); int test_wc_CryptoCb_AesGcm_EncryptDecrypt(void); #endif +#if defined(WOLF_CRYPTO_CB) && !defined(NO_AES) && defined(WOLFSSL_AES_CFB) && \ + !defined(WOLF_CRYPTO_CB_ONLY_AES) +int test_wc_CryptoCb_AesCfb_EncryptDecrypt(void); +#endif +#if defined(WOLF_CRYPTO_CB) && !defined(NO_AES) && defined(WOLFSSL_AES_OFB) && \ + !defined(WOLF_CRYPTO_CB_ONLY_AES) +int test_wc_CryptoCb_AesOfb_EncryptDecrypt(void); +#endif /* These test functions always have a (possibly empty) definition in * test_aes.c so that callers can reference them unconditionally. Declare @@ -121,6 +129,22 @@ int test_wc_CryptoCb_Tls13_Key_No_Zero_Without_Offload(void); #define TEST_CRYPTOCB_AES_SETKEY_DECL #endif +#if defined(WOLF_CRYPTO_CB) && !defined(NO_AES) && defined(WOLFSSL_AES_CFB) && \ + !defined(WOLF_CRYPTO_CB_ONLY_AES) +#define TEST_CRYPTOCB_AESCFB_DECL \ + , TEST_DECL_GROUP("aes", test_wc_CryptoCb_AesCfb_EncryptDecrypt) +#else +#define TEST_CRYPTOCB_AESCFB_DECL +#endif + +#if defined(WOLF_CRYPTO_CB) && !defined(NO_AES) && defined(WOLFSSL_AES_OFB) && \ + !defined(WOLF_CRYPTO_CB_ONLY_AES) +#define TEST_CRYPTOCB_AESOFB_DECL \ + , TEST_DECL_GROUP("aes", test_wc_CryptoCb_AesOfb_EncryptDecrypt) +#else +#define TEST_CRYPTOCB_AESOFB_DECL +#endif + #define TEST_AES_DECLS \ TEST_DECL_GROUP("aes", test_wc_AesSetKey), \ TEST_DECL_GROUP("aes", test_wc_AesSetIV), \ @@ -174,7 +198,9 @@ int test_wc_CryptoCb_Tls13_Key_No_Zero_Without_Offload(void); TEST_DECL_GROUP("aes", test_wc_AesCfb_MonteCarlo), \ TEST_DECL_GROUP("aes", test_wc_AesOfb_MonteCarlo) \ TEST_CRYPTOCB_AES_SETKEY_DECL \ - TEST_CRYPTOCB_TLS13_KEY_ZERO_DECL + TEST_CRYPTOCB_TLS13_KEY_ZERO_DECL \ + TEST_CRYPTOCB_AESCFB_DECL \ + TEST_CRYPTOCB_AESOFB_DECL #if defined(WOLFSSL_AES_EAX) && defined(WOLFSSL_AES_256) && \ (!defined(HAVE_FIPS) || FIPS_VERSION_GE(5, 3)) && !defined(HAVE_SELFTEST) diff --git a/wolfcrypt/src/aes.c b/wolfcrypt/src/aes.c index 6806acbc965..104ab56315d 100644 --- a/wolfcrypt/src/aes.c +++ b/wolfcrypt/src/aes.c @@ -14886,6 +14886,19 @@ static WARN_UNUSED_RESULT int AesCfbDecrypt_C(Aes* aes, byte* out, /* Software AES - CFB Encrypt */ int wc_AesCfbEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) { +#ifdef WOLF_CRYPTO_CB + if (aes == NULL) + return BAD_FUNC_ARG; + #ifndef WOLF_CRYPTO_CB_FIND + if (aes->devId != INVALID_DEVID) + #endif + { + int crypto_cb_ret = wc_CryptoCb_AesCfbEncrypt(aes, out, in, sz); + if (crypto_cb_ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) + return crypto_cb_ret; + /* fall-through when unavailable */ + } +#endif return AesCfbEncrypt_C(aes, out, in, sz); } @@ -14904,6 +14917,19 @@ int wc_AesCfbEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) /* Software AES - CFB Decrypt */ int wc_AesCfbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) { +#ifdef WOLF_CRYPTO_CB + if (aes == NULL) + return BAD_FUNC_ARG; + #ifndef WOLF_CRYPTO_CB_FIND + if (aes->devId != INVALID_DEVID) + #endif + { + int crypto_cb_ret = wc_CryptoCb_AesCfbDecrypt(aes, out, in, sz); + if (crypto_cb_ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) + return crypto_cb_ret; + /* fall-through when unavailable */ + } +#endif return AesCfbDecrypt_C(aes, out, in, sz, AES_CFB_MODE); } #endif /* HAVE_AES_DECRYPT */ @@ -15224,6 +15250,19 @@ static WARN_UNUSED_RESULT int AesOfbCrypt_C(Aes* aes, byte* out, const byte* in, /* Software AES - OFB Encrypt */ int wc_AesOfbEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) { +#ifdef WOLF_CRYPTO_CB + if (aes == NULL) + return BAD_FUNC_ARG; + #ifndef WOLF_CRYPTO_CB_FIND + if (aes->devId != INVALID_DEVID) + #endif + { + int crypto_cb_ret = wc_CryptoCb_AesOfbEncrypt(aes, out, in, sz); + if (crypto_cb_ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) + return crypto_cb_ret; + /* fall-through when unavailable */ + } +#endif return AesOfbCrypt_C(aes, out, in, sz); } @@ -15242,6 +15281,19 @@ int wc_AesOfbEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) /* Software AES - OFB Decrypt */ int wc_AesOfbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) { +#ifdef WOLF_CRYPTO_CB + if (aes == NULL) + return BAD_FUNC_ARG; + #ifndef WOLF_CRYPTO_CB_FIND + if (aes->devId != INVALID_DEVID) + #endif + { + int crypto_cb_ret = wc_CryptoCb_AesOfbDecrypt(aes, out, in, sz); + if (crypto_cb_ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) + return crypto_cb_ret; + /* fall-through when unavailable */ + } +#endif return AesOfbCrypt_C(aes, out, in, sz); } #endif /* HAVE_AES_DECRYPT */ diff --git a/wolfcrypt/src/cryptocb.c b/wolfcrypt/src/cryptocb.c index 3218e6efb27..492b6351e5c 100644 --- a/wolfcrypt/src/cryptocb.c +++ b/wolfcrypt/src/cryptocb.c @@ -170,6 +170,7 @@ static const char* GetCipherTypeStr(int cipher) case WC_CIPHER_AES_CTR: return "AES CTR"; case WC_CIPHER_AES_XTS: return "AES XTS"; case WC_CIPHER_AES_CFB: return "AES CFB"; + case WC_CIPHER_AES_OFB: return "AES OFB"; case WC_CIPHER_DES3: return "DES3"; case WC_CIPHER_DES: return "DES"; case WC_CIPHER_CHACHA: return "ChaCha20"; @@ -1741,6 +1742,136 @@ int wc_CryptoCb_AesCtrEncrypt(Aes* aes, byte* out, return wc_CryptoCb_TranslateErrorCode(ret); } #endif /* WOLFSSL_AES_COUNTER */ +#ifdef WOLFSSL_AES_CFB +int wc_CryptoCb_AesCfbEncrypt(Aes* aes, byte* out, + const byte* in, word32 sz) +{ + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); + CryptoCb* dev; + + /* locate registered callback */ + if (aes) { + dev = wc_CryptoCb_FindDevice(aes->devId, WC_ALGO_TYPE_CIPHER); + } + else { + /* locate first callback and try using it */ + dev = wc_CryptoCb_FindDeviceByIndex(0); + } + + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_CIPHER; + cryptoInfo.cipher.type = WC_CIPHER_AES_CFB; + cryptoInfo.cipher.enc = 1; + cryptoInfo.cipher.aescfb.aes = aes; + cryptoInfo.cipher.aescfb.out = out; + cryptoInfo.cipher.aescfb.in = in; + cryptoInfo.cipher.aescfb.sz = sz; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} + +int wc_CryptoCb_AesCfbDecrypt(Aes* aes, byte* out, + const byte* in, word32 sz) +{ + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); + CryptoCb* dev; + + /* locate registered callback */ + if (aes) { + dev = wc_CryptoCb_FindDevice(aes->devId, WC_ALGO_TYPE_CIPHER); + } + else { + /* locate first callback and try using it */ + dev = wc_CryptoCb_FindDeviceByIndex(0); + } + + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_CIPHER; + cryptoInfo.cipher.type = WC_CIPHER_AES_CFB; + cryptoInfo.cipher.enc = 0; + cryptoInfo.cipher.aescfb.aes = aes; + cryptoInfo.cipher.aescfb.out = out; + cryptoInfo.cipher.aescfb.in = in; + cryptoInfo.cipher.aescfb.sz = sz; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} +#endif /* WOLFSSL_AES_CFB */ +#ifdef WOLFSSL_AES_OFB +int wc_CryptoCb_AesOfbEncrypt(Aes* aes, byte* out, + const byte* in, word32 sz) +{ + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); + CryptoCb* dev; + + /* locate registered callback */ + if (aes) { + dev = wc_CryptoCb_FindDevice(aes->devId, WC_ALGO_TYPE_CIPHER); + } + else { + /* locate first callback and try using it */ + dev = wc_CryptoCb_FindDeviceByIndex(0); + } + + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_CIPHER; + cryptoInfo.cipher.type = WC_CIPHER_AES_OFB; + cryptoInfo.cipher.enc = 1; + cryptoInfo.cipher.aesofb.aes = aes; + cryptoInfo.cipher.aesofb.out = out; + cryptoInfo.cipher.aesofb.in = in; + cryptoInfo.cipher.aesofb.sz = sz; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} + +int wc_CryptoCb_AesOfbDecrypt(Aes* aes, byte* out, + const byte* in, word32 sz) +{ + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); + CryptoCb* dev; + + /* locate registered callback */ + if (aes) { + dev = wc_CryptoCb_FindDevice(aes->devId, WC_ALGO_TYPE_CIPHER); + } + else { + /* locate first callback and try using it */ + dev = wc_CryptoCb_FindDeviceByIndex(0); + } + + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_CIPHER; + cryptoInfo.cipher.type = WC_CIPHER_AES_OFB; + cryptoInfo.cipher.enc = 0; + cryptoInfo.cipher.aesofb.aes = aes; + cryptoInfo.cipher.aesofb.out = out; + cryptoInfo.cipher.aesofb.in = in; + cryptoInfo.cipher.aesofb.sz = sz; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} +#endif /* WOLFSSL_AES_OFB */ #if defined(HAVE_AES_ECB) || defined(WOLFSSL_AES_DIRECT) || \ defined(WOLF_CRYPTO_CB_ONLY_AES) int wc_CryptoCb_AesEcbEncrypt(Aes* aes, byte* out, diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index e95bba5ae5e..9a1975ed8d9 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -73420,6 +73420,70 @@ static int myCryptoDevCb(int devIdArg, wc_CryptoInfo* info, void* ctx) info->cipher.aesctr.aes->devId = devIdArg; } #endif /* WOLFSSL_AES_COUNTER */ + #ifdef WOLFSSL_AES_CFB + if (info->cipher.type == WC_CIPHER_AES_CFB) { + if (info->cipher.enc) { + /* set devId to invalid, so software is used */ + info->cipher.aescfb.aes->devId = INVALID_DEVID; + + ret = wc_AesCfbEncrypt( + info->cipher.aescfb.aes, + info->cipher.aescfb.out, + info->cipher.aescfb.in, + info->cipher.aescfb.sz); + + /* reset devId */ + info->cipher.aescfb.aes->devId = devIdArg; + } + #ifdef HAVE_AES_DECRYPT + else { + /* set devId to invalid, so software is used */ + info->cipher.aescfb.aes->devId = INVALID_DEVID; + + ret = wc_AesCfbDecrypt( + info->cipher.aescfb.aes, + info->cipher.aescfb.out, + info->cipher.aescfb.in, + info->cipher.aescfb.sz); + + /* reset devId */ + info->cipher.aescfb.aes->devId = devIdArg; + } + #endif /* HAVE_AES_DECRYPT */ + } + #endif /* WOLFSSL_AES_CFB */ + #ifdef WOLFSSL_AES_OFB + if (info->cipher.type == WC_CIPHER_AES_OFB) { + if (info->cipher.enc) { + /* set devId to invalid, so software is used */ + info->cipher.aesofb.aes->devId = INVALID_DEVID; + + ret = wc_AesOfbEncrypt( + info->cipher.aesofb.aes, + info->cipher.aesofb.out, + info->cipher.aesofb.in, + info->cipher.aesofb.sz); + + /* reset devId */ + info->cipher.aesofb.aes->devId = devIdArg; + } + #ifdef HAVE_AES_DECRYPT + else { + /* set devId to invalid, so software is used */ + info->cipher.aesofb.aes->devId = INVALID_DEVID; + + ret = wc_AesOfbDecrypt( + info->cipher.aesofb.aes, + info->cipher.aesofb.out, + info->cipher.aesofb.in, + info->cipher.aesofb.sz); + + /* reset devId */ + info->cipher.aesofb.aes->devId = devIdArg; + } + #endif /* HAVE_AES_DECRYPT */ + } + #endif /* WOLFSSL_AES_OFB */ #if defined(HAVE_AESCCM) && defined(WOLFSSL_AES_128) if (info->cipher.type == WC_CIPHER_AES_CCM) { if (info->cipher.enc) { @@ -74797,6 +74861,14 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cryptocb_test(void) if (ret == 0) ret = aes_test(); #endif + #ifdef WOLFSSL_AES_CFB + if (ret == 0) + ret = aes_cfb_test(); + #endif + #ifdef WOLFSSL_AES_OFB + if (ret == 0) + ret = aesofb_test(); + #endif #ifdef WOLFSSL_AES_XTS if (ret == 0) ret = aes_xts_test(); diff --git a/wolfssl/wolfcrypt/cryptocb.h b/wolfssl/wolfcrypt/cryptocb.h index b0aaad2f374..2ffbcd8fa48 100644 --- a/wolfssl/wolfcrypt/cryptocb.h +++ b/wolfssl/wolfcrypt/cryptocb.h @@ -418,6 +418,22 @@ typedef struct wc_CryptoInfo { word32 sz; } aesctr; #endif /* WOLFSSL_AES_COUNTER */ + #if defined(WOLFSSL_AES_CFB) + struct { + Aes* aes; + byte* out; + const byte* in; + word32 sz; + } aescfb; + #endif /* WOLFSSL_AES_CFB */ + #if defined(WOLFSSL_AES_OFB) + struct { + Aes* aes; + byte* out; + const byte* in; + word32 sz; + } aesofb; + #endif /* WOLFSSL_AES_OFB */ #if defined(HAVE_AES_ECB) || defined(WOLFSSL_AES_DIRECT) || \ defined(WOLF_CRYPTO_CB_ONLY_AES) struct { @@ -833,6 +849,18 @@ WOLFSSL_LOCAL int wc_CryptoCb_AesCbcDecrypt(Aes* aes, byte* out, WOLFSSL_LOCAL int wc_CryptoCb_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz); #endif /* WOLFSSL_AES_COUNTER */ +#ifdef WOLFSSL_AES_CFB +WOLFSSL_LOCAL int wc_CryptoCb_AesCfbEncrypt(Aes* aes, byte* out, + const byte* in, word32 sz); +WOLFSSL_LOCAL int wc_CryptoCb_AesCfbDecrypt(Aes* aes, byte* out, + const byte* in, word32 sz); +#endif /* WOLFSSL_AES_CFB */ +#ifdef WOLFSSL_AES_OFB +WOLFSSL_LOCAL int wc_CryptoCb_AesOfbEncrypt(Aes* aes, byte* out, + const byte* in, word32 sz); +WOLFSSL_LOCAL int wc_CryptoCb_AesOfbDecrypt(Aes* aes, byte* out, + const byte* in, word32 sz); +#endif /* WOLFSSL_AES_OFB */ #if defined(HAVE_AES_ECB) || defined(WOLFSSL_AES_DIRECT) || \ defined(WOLF_CRYPTO_CB_ONLY_AES) WOLFSSL_LOCAL int wc_CryptoCb_AesEcbEncrypt(Aes* aes, byte* out, diff --git a/wolfssl/wolfcrypt/types.h b/wolfssl/wolfcrypt/types.h index 3a1efb79556..74fba9de315 100644 --- a/wolfssl/wolfcrypt/types.h +++ b/wolfssl/wolfcrypt/types.h @@ -1538,6 +1538,7 @@ enum wc_CipherType { WC_CIPHER_AES_CFB = 6, WC_CIPHER_AES_CCM = 12, WC_CIPHER_AES_ECB = 13, + WC_CIPHER_AES_OFB = 14, WC_CIPHER_DES3 = 7, WC_CIPHER_DES = 8, WC_CIPHER_CHACHA = 9,