Skip to content

Commit 1fbc984

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

File tree

5 files changed

+459
-25
lines changed

5 files changed

+459
-25
lines changed

tests/api/test_aes.c

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

tests/api/test_aes.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,17 @@ 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(WOLF_CRYPTO_CB_AES_SETKEY) && \
57+
!defined(NO_AES) && defined(HAVE_AESGCM)
58+
int test_wc_CryptoCb_AesSetKey(void);
59+
#endif
60+
61+
#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_AES_SETKEY) && \
62+
!defined(NO_AES) && defined(HAVE_AESGCM)
63+
#define TEST_CRYPTOCB_AES_SETKEY_DECL , TEST_DECL_GROUP("aes", test_wc_CryptoCb_AesSetKey)
64+
#else
65+
#define TEST_CRYPTOCB_AES_SETKEY_DECL
66+
#endif
5667

5768
#define TEST_AES_DECLS \
5869
TEST_DECL_GROUP("aes", test_wc_AesSetKey), \
@@ -74,7 +85,8 @@ int test_wc_GmacUpdate(void);
7485
TEST_DECL_GROUP("aes", test_wc_AesCcmEncryptDecrypt), \
7586
TEST_DECL_GROUP("aes", test_wc_AesXtsSetKey), \
7687
TEST_DECL_GROUP("aes", test_wc_AesXtsEncryptDecrypt_Sizes), \
77-
TEST_DECL_GROUP("aes", test_wc_AesXtsEncryptDecrypt)
88+
TEST_DECL_GROUP("aes", test_wc_AesXtsEncryptDecrypt) \
89+
TEST_CRYPTOCB_AES_SETKEY_DECL
7890

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

0 commit comments

Comments
 (0)