Skip to content

Commit 5e13b4d

Browse files
committed
aes offload
Signed-off-by: Sameeh Jubran <sameeh@wolfssl.com>
1 parent 5f68ea0 commit 5e13b4d

File tree

5 files changed

+420
-35
lines changed

5 files changed

+420
-35
lines changed

tests/api/test_aes.c

Lines changed: 296 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5222,3 +5222,299 @@ int test_wc_AesEaxDecryptAuth(void)
52225222
* (!HAVE_FIPS || FIPS_VERSION_GE(5, 3)) && !HAVE_SELFTEST
52235223
*/
52245224

5225+
/*----------------------------------------------------------------------------*
5226+
| CryptoCB AES SetKey Proxy-Key Test
5227+
*----------------------------------------------------------------------------*/
5228+
5229+
#if defined(WOLF_CRYPTO_CB) && !defined(NO_AES) && defined(HAVE_AESGCM)
5230+
5231+
#include <wolfssl/wolfcrypt/cryptocb.h>
5232+
5233+
#define TEST_CRYPTOCB_AES_DEVID 7
5234+
5235+
/* Test state tracking */
5236+
static int g_ccAesSetKeyCalled = 0;
5237+
static int g_ccAesFreeCalled = 0;
5238+
5239+
/* Simulated SE key storage - in real SE this would be in secure hardware */
5240+
typedef struct {
5241+
byte key[AES_256_KEY_SIZE];
5242+
word32 keySz;
5243+
int valid;
5244+
} MockSeKeySlot;
5245+
5246+
static MockSeKeySlot g_mockSeKey = {0};
5247+
5248+
/* Mock handle pointing to our key slot */
5249+
static void* g_ccAesMockHandle = (void*)&g_mockSeKey;
5250+
5251+
/* Test CryptoCB callback for AES proxy-key operations
5252+
* This emulates a Secure Element by:
5253+
* - Storing the key on SetKey (simulating SE key import)
5254+
* - Using stored key for encrypt/decrypt (simulating SE crypto)
5255+
* - Clearing key on Free (simulating SE key deletion)
5256+
*/
5257+
static int test_CryptoCb_Aes_Cb(int devId, wc_CryptoInfo* info, void* ctx)
5258+
{
5259+
(void)ctx;
5260+
5261+
if (devId != TEST_CRYPTOCB_AES_DEVID)
5262+
return CRYPTOCB_UNAVAILABLE;
5263+
5264+
/* AES SetKey operation - simulate SE key import */
5265+
if (info->algo_type == WC_ALGO_TYPE_CIPHER &&
5266+
info->cipher.type == WC_CIPHER_AES &&
5267+
info->cipher.aessetkey.aes != NULL) {
5268+
5269+
Aes* aes = info->cipher.aessetkey.aes;
5270+
const byte* key = info->cipher.aessetkey.key;
5271+
word32 keySz = info->cipher.aessetkey.keySz;
5272+
5273+
/* Validate key */
5274+
if (key == NULL || keySz == 0 || keySz > AES_256_KEY_SIZE) {
5275+
return BAD_FUNC_ARG;
5276+
}
5277+
5278+
/* "Import" key to simulated SE storage */
5279+
XMEMCPY(g_mockSeKey.key, key, keySz);
5280+
g_mockSeKey.keySz = keySz;
5281+
g_mockSeKey.valid = 1;
5282+
5283+
/* Store handle in aes->devCtx - this is what wolfSSL will use */
5284+
aes->devCtx = g_ccAesMockHandle;
5285+
5286+
g_ccAesSetKeyCalled++;
5287+
5288+
return 0;
5289+
}
5290+
5291+
/* AES-GCM Encrypt - simulate SE encryption using stored key */
5292+
if (info->algo_type == WC_ALGO_TYPE_CIPHER &&
5293+
info->cipher.type == WC_CIPHER_AES_GCM &&
5294+
info->cipher.enc) {
5295+
5296+
Aes* aes = info->cipher.aesgcm_enc.aes;
5297+
MockSeKeySlot* slot;
5298+
Aes tempAes;
5299+
int ret;
5300+
5301+
/* Verify handle points to our key slot */
5302+
if (aes == NULL || aes->devCtx != g_ccAesMockHandle) {
5303+
return BAD_FUNC_ARG;
5304+
}
5305+
5306+
slot = (MockSeKeySlot*)aes->devCtx;
5307+
if (!slot->valid) {
5308+
return BAD_STATE_E;
5309+
}
5310+
5311+
/* Initialize a temporary Aes for software crypto (simulating SE internal operation) */
5312+
XMEMSET(&tempAes, 0, sizeof(tempAes));
5313+
ret = wc_AesInit(&tempAes, NULL, INVALID_DEVID); /* No CryptoCB for internal use */
5314+
if (ret != 0) return ret;
5315+
5316+
ret = wc_AesGcmSetKey(&tempAes, slot->key, slot->keySz);
5317+
if (ret != 0) {
5318+
wc_AesFree(&tempAes);
5319+
return ret;
5320+
}
5321+
5322+
/* Perform the actual encryption */
5323+
ret = wc_AesGcmEncrypt(&tempAes,
5324+
info->cipher.aesgcm_enc.out,
5325+
info->cipher.aesgcm_enc.in,
5326+
info->cipher.aesgcm_enc.sz,
5327+
info->cipher.aesgcm_enc.iv,
5328+
info->cipher.aesgcm_enc.ivSz,
5329+
info->cipher.aesgcm_enc.authTag,
5330+
info->cipher.aesgcm_enc.authTagSz,
5331+
info->cipher.aesgcm_enc.authIn,
5332+
info->cipher.aesgcm_enc.authInSz);
5333+
5334+
wc_AesFree(&tempAes);
5335+
5336+
return ret;
5337+
}
5338+
5339+
/* AES-GCM Decrypt - simulate SE decryption using stored key */
5340+
if (info->algo_type == WC_ALGO_TYPE_CIPHER &&
5341+
info->cipher.type == WC_CIPHER_AES_GCM &&
5342+
!info->cipher.enc) {
5343+
5344+
Aes* aes = info->cipher.aesgcm_dec.aes;
5345+
MockSeKeySlot* slot;
5346+
Aes tempAes;
5347+
int ret;
5348+
5349+
/* Verify handle points to our key slot */
5350+
if (aes == NULL || aes->devCtx != g_ccAesMockHandle) {
5351+
return BAD_FUNC_ARG;
5352+
}
5353+
5354+
slot = (MockSeKeySlot*)aes->devCtx;
5355+
if (!slot->valid) {
5356+
return BAD_STATE_E;
5357+
}
5358+
5359+
/* Initialize a temporary Aes for software crypto (simulating SE internal operation) */
5360+
XMEMSET(&tempAes, 0, sizeof(tempAes));
5361+
ret = wc_AesInit(&tempAes, NULL, INVALID_DEVID);
5362+
if (ret != 0) return ret;
5363+
5364+
ret = wc_AesGcmSetKey(&tempAes, slot->key, slot->keySz);
5365+
if (ret != 0) {
5366+
wc_AesFree(&tempAes);
5367+
return ret;
5368+
}
5369+
5370+
/* Perform the actual decryption */
5371+
ret = wc_AesGcmDecrypt(&tempAes,
5372+
info->cipher.aesgcm_dec.out,
5373+
info->cipher.aesgcm_dec.in,
5374+
info->cipher.aesgcm_dec.sz,
5375+
info->cipher.aesgcm_dec.iv,
5376+
info->cipher.aesgcm_dec.ivSz,
5377+
info->cipher.aesgcm_dec.authTag,
5378+
info->cipher.aesgcm_dec.authTagSz,
5379+
info->cipher.aesgcm_dec.authIn,
5380+
info->cipher.aesgcm_dec.authInSz);
5381+
5382+
wc_AesFree(&tempAes);
5383+
5384+
return ret;
5385+
}
5386+
5387+
#ifdef WOLF_CRYPTO_CB_FREE
5388+
/* Free operation - simulate SE key deletion */
5389+
if (info->algo_type == WC_ALGO_TYPE_FREE &&
5390+
info->free.algo == WC_ALGO_TYPE_CIPHER &&
5391+
info->free.type == WC_CIPHER_AES) {
5392+
5393+
Aes* aes = (Aes*)info->free.obj;
5394+
5395+
if (aes != NULL && aes->devCtx == g_ccAesMockHandle) {
5396+
/* "Delete" key from simulated SE */
5397+
ForceZero(&g_mockSeKey, sizeof(g_mockSeKey));
5398+
g_ccAesFreeCalled++;
5399+
}
5400+
5401+
return 0;
5402+
}
5403+
#endif
5404+
5405+
return CRYPTOCB_UNAVAILABLE;
5406+
}
5407+
5408+
/*
5409+
* Test: CryptoCB AES SetKey hook for proxy-key / secure element support
5410+
*/
5411+
int test_wc_CryptoCb_AesSetKey(void)
5412+
{
5413+
EXPECT_DECLS;
5414+
Aes aes;
5415+
byte key[AES_128_KEY_SIZE] = {
5416+
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
5417+
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
5418+
};
5419+
byte iv[GCM_NONCE_MID_SZ] = {0};
5420+
byte plain[16] = {
5421+
0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x77,
5422+
0x6f, 0x6c, 0x66, 0x53, 0x53, 0x4c, 0x21, 0x00
5423+
};
5424+
byte cipher[16];
5425+
byte decrypted[16];
5426+
byte authTag[AES_BLOCK_SIZE];
5427+
int ret;
5428+
5429+
XMEMSET(&aes, 0, sizeof(aes));
5430+
XMEMSET(&g_mockSeKey, 0, sizeof(g_mockSeKey));
5431+
5432+
/* Reset test state */
5433+
g_ccAesSetKeyCalled = 0;
5434+
g_ccAesFreeCalled = 0;
5435+
5436+
/* Register test callback */
5437+
ret = wc_CryptoCb_RegisterDevice(TEST_CRYPTOCB_AES_DEVID,
5438+
test_CryptoCb_Aes_Cb, NULL);
5439+
ExpectIntEQ(ret, 0);
5440+
5441+
/* Initialize Aes with device ID */
5442+
ret = wc_AesInit(&aes, NULL, TEST_CRYPTOCB_AES_DEVID);
5443+
ExpectIntEQ(ret, 0);
5444+
ExpectIntEQ(aes.devId, TEST_CRYPTOCB_AES_DEVID);
5445+
5446+
/* Set key - should trigger CryptoCB and "import" to mock SE */
5447+
ret = wc_AesGcmSetKey(&aes, key, sizeof(key));
5448+
ExpectIntEQ(ret, 0);
5449+
5450+
/* Verify callback was invoked */
5451+
ExpectIntEQ(g_ccAesSetKeyCalled, 1);
5452+
5453+
/* Verify handle stored in devCtx */
5454+
ExpectPtrEq(aes.devCtx, g_ccAesMockHandle);
5455+
5456+
/* Verify key was "imported" to mock SE */
5457+
ExpectIntEQ(g_mockSeKey.valid, 1);
5458+
ExpectIntEQ(g_mockSeKey.keySz, (int)sizeof(key));
5459+
5460+
/* Verify keylen metadata stored in Aes struct */
5461+
ExpectIntEQ(aes.keylen, (int)sizeof(key));
5462+
5463+
/* Test encrypt - callback performs crypto using stored key */
5464+
ret = wc_AesGcmEncrypt(&aes, cipher, plain, sizeof(plain),
5465+
iv, sizeof(iv), authTag, sizeof(authTag),
5466+
NULL, 0);
5467+
ExpectIntEQ(ret, 0);
5468+
5469+
/* Test decrypt - callback performs crypto using stored key */
5470+
ret = wc_AesGcmDecrypt(&aes, decrypted, cipher, sizeof(cipher),
5471+
iv, sizeof(iv), authTag, sizeof(authTag),
5472+
NULL, 0);
5473+
ExpectIntEQ(ret, 0);
5474+
5475+
/* Verify round-trip */
5476+
ExpectIntEQ(XMEMCMP(plain, decrypted, sizeof(plain)), 0);
5477+
5478+
#ifdef WOLF_CRYPTO_CB_FREE
5479+
/* Free should trigger callback and "delete" key from mock SE */
5480+
g_ccAesFreeCalled = 0;
5481+
wc_AesFree(&aes);
5482+
5483+
/* Verify free callback invoked */
5484+
ExpectIntEQ(g_ccAesFreeCalled, 1);
5485+
5486+
/* Verify devCtx cleared */
5487+
ExpectPtrEq(aes.devCtx, NULL);
5488+
5489+
/* Verify key was "deleted" from mock SE */
5490+
ExpectIntEQ(g_mockSeKey.valid, 0);
5491+
#else
5492+
wc_AesFree(&aes);
5493+
#endif
5494+
5495+
/* Cleanup */
5496+
wc_CryptoCb_UnRegisterDevice(TEST_CRYPTOCB_AES_DEVID);
5497+
5498+
/* Test software path (no devId) still works */
5499+
XMEMSET(&aes, 0, sizeof(aes));
5500+
g_ccAesSetKeyCalled = 0;
5501+
5502+
ret = wc_AesInit(&aes, NULL, INVALID_DEVID);
5503+
ExpectIntEQ(ret, 0);
5504+
5505+
ret = wc_AesGcmSetKey(&aes, key, sizeof(key));
5506+
ExpectIntEQ(ret, 0);
5507+
5508+
/* Callback should NOT have been invoked */
5509+
ExpectIntEQ(g_ccAesSetKeyCalled, 0);
5510+
5511+
/* devCtx should be NULL */
5512+
ExpectPtrEq(aes.devCtx, NULL);
5513+
5514+
wc_AesFree(&aes);
5515+
5516+
return EXPECT_RESULT();
5517+
}
5518+
5519+
#endif /* WOLF_CRYPTO_CB && !NO_AES && HAVE_AESGCM */
5520+

tests/api/test_aes.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,15 @@ int test_wc_AesEaxDecryptAuth(void);
5353

5454
int test_wc_GmacSetKey(void);
5555
int test_wc_GmacUpdate(void);
56+
#if defined(WOLF_CRYPTO_CB) && !defined(NO_AES) && defined(HAVE_AESGCM)
57+
int test_wc_CryptoCb_AesSetKey(void);
58+
#endif
59+
60+
#if defined(WOLF_CRYPTO_CB) && !defined(NO_AES) && defined(HAVE_AESGCM)
61+
#define TEST_CRYPTOCB_AES_SETKEY_DECL , TEST_DECL_GROUP("aes", test_wc_CryptoCb_AesSetKey)
62+
#else
63+
#define TEST_CRYPTOCB_AES_SETKEY_DECL
64+
#endif
5665

5766
#define TEST_AES_DECLS \
5867
TEST_DECL_GROUP("aes", test_wc_AesSetKey), \
@@ -74,7 +83,8 @@ int test_wc_GmacUpdate(void);
7483
TEST_DECL_GROUP("aes", test_wc_AesCcmEncryptDecrypt), \
7584
TEST_DECL_GROUP("aes", test_wc_AesXtsSetKey), \
7685
TEST_DECL_GROUP("aes", test_wc_AesXtsEncryptDecrypt_Sizes), \
77-
TEST_DECL_GROUP("aes", test_wc_AesXtsEncryptDecrypt)
86+
TEST_DECL_GROUP("aes", test_wc_AesXtsEncryptDecrypt) \
87+
TEST_CRYPTOCB_AES_SETKEY_DECL
7888

7989
#if defined(WOLFSSL_AES_EAX) && defined(WOLFSSL_AES_256) && \
8090
(!defined(HAVE_FIPS) || FIPS_VERSION_GE(5, 3)) && !defined(HAVE_SELFTEST)

0 commit comments

Comments
 (0)