Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 4 additions & 0 deletions .github/workflows/os-check.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
name: Ubuntu-Macos-Windows Tests

# START OF COMMON SECTION
Expand Down Expand Up @@ -243,6 +243,10 @@
{"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"]},
Expand Down
300 changes: 300 additions & 0 deletions tests/api/test_aes.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
*----------------------------------------------------------------------------*/
Expand Down
28 changes: 27 additions & 1 deletion tests/api/test_aes.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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), \
Expand Down Expand Up @@ -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)
Expand Down
Loading
Loading