Skip to content

Commit f9ee825

Browse files
committed
allow full offload (with GCM)
Signed-off-by: Sameeh Jubran <sameeh@wolfssl.com>
1 parent 74a94c0 commit f9ee825

File tree

6 files changed

+329
-21
lines changed

6 files changed

+329
-21
lines changed

tests/api/test_aes.c

Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5284,6 +5284,11 @@ static int test_CryptoCb_Aes_Cb(int devId, wc_CryptoInfo* info, void* ctx)
52845284
/* Store handle in aes->devCtx - this is what wolfSSL will use */
52855285
aes->devCtx = cryptoCbAesMockHandle;
52865286

5287+
/* CRITICAL: Declare full AES-GCM offload capability.
5288+
* This tells wolfSSL to skip GCM table generation and expect
5289+
* all GCM operations to go through CryptoCB. */
5290+
info->cipher.aessetkey.capabilities = WC_CRYPTOCB_AES_GCM;
5291+
52875292
cryptoCbAesSetKeyCalled++;
52885293

52895294
return 0;
@@ -5486,6 +5491,9 @@ int test_wc_CryptoCb_AesSetKey(void)
54865491
/* Verify callback was invoked */
54875492
ExpectIntEQ(cryptoCbAesSetKeyCalled, 1);
54885493

5494+
/* Verify GCM offload flag was set (callback declared capability) */
5495+
ExpectIntEQ(aes->gcmCryptoCbOffload, 1);
5496+
54895497
/* Verify handle stored in devCtx */
54905498
ExpectPtrEq(aes->devCtx, cryptoCbAesMockHandle);
54915499

@@ -5628,6 +5636,11 @@ static int test_CryptoCb_AesGcm_Offload_Cb(int devId, wc_CryptoInfo* info, void*
56285636
/* Store handle in aes->devCtx - this is what wolfSSL will use */
56295637
aes->devCtx = cryptoCbAesGcmMockHandle;
56305638

5639+
/* CRITICAL: Declare full AES-GCM offload capability.
5640+
* This tells wolfSSL to skip GCM table generation and expect
5641+
* all GCM operations to go through CryptoCB. */
5642+
info->cipher.aessetkey.capabilities = WC_CRYPTOCB_AES_GCM;
5643+
56315644
cryptoCbAesGcmSetKeyCalled++;
56325645

56335646
return 0;
@@ -5863,6 +5876,9 @@ int test_wc_CryptoCb_AesGcm_EncryptDecrypt(void)
58635876
/* Verify SetKey callback was invoked */
58645877
ExpectIntEQ(cryptoCbAesGcmSetKeyCalled, 1);
58655878

5879+
/* Verify GCM offload flag was set (callback declared capability) */
5880+
ExpectIntEQ(aes->gcmCryptoCbOffload, 1);
5881+
58665882
/* Verify handle stored in devCtx */
58675883
ExpectPtrEq(aes->devCtx, cryptoCbAesGcmMockHandle);
58685884

@@ -5950,5 +5966,201 @@ int test_wc_CryptoCb_AesGcm_EncryptDecrypt(void)
59505966
return EXPECT_RESULT();
59515967
}
59525968

5969+
/*
5970+
* Test: Key import only callback - verifies software fallback works
5971+
* when callback does NOT declare WC_CRYPTOCB_AES_GCM capability
5972+
*/
5973+
#define TEST_CRYPTOCB_AES_KEYIMPORT_ONLY_DEVID 9
5974+
5975+
/* Test state tracking for key-import-only test */
5976+
static int cryptoCbKeyImportOnlySetKeyCalled = 0;
5977+
static void* cryptoCbKeyImportOnlyMockHandle = (void*)0xDEADBEEF;
5978+
5979+
/* Mock SE key storage for key-import-only test */
5980+
static struct {
5981+
byte key[AES_256_KEY_SIZE];
5982+
word32 keySz;
5983+
int valid;
5984+
} mockSeKeyImportOnly;
5985+
5986+
/* Callback that handles key import but NOT GCM operations */
5987+
static int test_CryptoCb_KeyImportOnly_Cb(int devId, wc_CryptoInfo* info, void* ctx)
5988+
{
5989+
(void)ctx;
5990+
5991+
if (devId != TEST_CRYPTOCB_AES_KEYIMPORT_ONLY_DEVID)
5992+
return CRYPTOCB_UNAVAILABLE;
5993+
5994+
/* AES SetKey operation - simulate SE key import */
5995+
if (info->algo_type == WC_ALGO_TYPE_CIPHER &&
5996+
info->cipher.type == WC_CIPHER_AES &&
5997+
info->cipher.aessetkey.aes != NULL) {
5998+
5999+
Aes* aes = info->cipher.aessetkey.aes;
6000+
const byte* key = info->cipher.aessetkey.key;
6001+
word32 keySz = info->cipher.aessetkey.keySz;
6002+
6003+
/* Validate key */
6004+
if (key == NULL || keySz == 0 || keySz > AES_256_KEY_SIZE) {
6005+
return BAD_FUNC_ARG;
6006+
}
6007+
6008+
/* "Import" key to simulated SE storage */
6009+
XMEMCPY(mockSeKeyImportOnly.key, key, keySz);
6010+
mockSeKeyImportOnly.keySz = keySz;
6011+
mockSeKeyImportOnly.valid = 1;
6012+
6013+
/* Store handle in aes->devCtx */
6014+
aes->devCtx = cryptoCbKeyImportOnlyMockHandle;
6015+
6016+
/* CRITICAL: DO NOT set WC_CRYPTOCB_AES_GCM capability.
6017+
* This simulates a device that can import keys but cannot
6018+
* perform GCM operations. wolfSSL should generate GCM tables
6019+
* and use software fallback for GCM operations. */
6020+
/* info->cipher.aessetkey.capabilities stays 0 (default) */
6021+
6022+
cryptoCbKeyImportOnlySetKeyCalled++;
6023+
6024+
return 0;
6025+
}
6026+
6027+
/* GCM operations not supported - return UNAVAILABLE to trigger software fallback */
6028+
if (info->algo_type == WC_ALGO_TYPE_CIPHER &&
6029+
info->cipher.type == WC_CIPHER_AES_GCM) {
6030+
return CRYPTOCB_UNAVAILABLE;
6031+
}
6032+
6033+
return CRYPTOCB_UNAVAILABLE;
6034+
}
6035+
6036+
int test_wc_CryptoCb_AesKeyImportOnly(void)
6037+
{
6038+
EXPECT_DECLS;
6039+
#ifdef WOLFSSL_SMALL_STACK
6040+
Aes* aes = NULL;
6041+
byte* key = NULL;
6042+
byte* iv = NULL;
6043+
byte* plaintext = NULL;
6044+
byte* ciphertext = NULL;
6045+
byte* decrypted = NULL;
6046+
byte* authTag = NULL;
6047+
byte* aad = NULL;
6048+
#else
6049+
Aes aes[1];
6050+
byte key[AES_128_KEY_SIZE];
6051+
byte iv[GCM_NONCE_MID_SZ];
6052+
byte plaintext[32];
6053+
byte ciphertext[32];
6054+
byte decrypted[32];
6055+
byte authTag[AES_BLOCK_SIZE];
6056+
byte aad[16];
6057+
#endif
6058+
int ret;
6059+
6060+
#ifdef WOLFSSL_SMALL_STACK
6061+
aes = (Aes*)XMALLOC(sizeof(Aes), NULL, DYNAMIC_TYPE_TMP_BUFFER);
6062+
key = (byte*)XMALLOC(AES_128_KEY_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
6063+
iv = (byte*)XMALLOC(GCM_NONCE_MID_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER);
6064+
plaintext = (byte*)XMALLOC(32, NULL, DYNAMIC_TYPE_TMP_BUFFER);
6065+
ciphertext = (byte*)XMALLOC(32, NULL, DYNAMIC_TYPE_TMP_BUFFER);
6066+
decrypted = (byte*)XMALLOC(32, NULL, DYNAMIC_TYPE_TMP_BUFFER);
6067+
authTag = (byte*)XMALLOC(AES_BLOCK_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
6068+
aad = (byte*)XMALLOC(16, NULL, DYNAMIC_TYPE_TMP_BUFFER);
6069+
6070+
if (aes == NULL || key == NULL || iv == NULL || plaintext == NULL ||
6071+
ciphertext == NULL || decrypted == NULL || authTag == NULL || aad == NULL) {
6072+
ret = MEMORY_E;
6073+
goto out;
6074+
}
6075+
#endif
6076+
6077+
/* Initialize test data */
6078+
XMEMSET(key, 0x01, AES_128_KEY_SIZE);
6079+
XMEMSET(iv, 0x02, GCM_NONCE_MID_SZ);
6080+
XMEMSET(plaintext, 0x03, 32);
6081+
XMEMSET(aad, 0x04, 16);
6082+
XMEMSET(aes, 0, sizeof(Aes));
6083+
XMEMSET(&mockSeKeyImportOnly, 0, sizeof(mockSeKeyImportOnly));
6084+
cryptoCbKeyImportOnlySetKeyCalled = 0;
6085+
6086+
/* Register callback for key-import-only device */
6087+
ret = wc_CryptoCb_RegisterDevice(TEST_CRYPTOCB_AES_KEYIMPORT_ONLY_DEVID,
6088+
test_CryptoCb_KeyImportOnly_Cb, NULL);
6089+
ExpectIntEQ(ret, 0);
6090+
6091+
/* Initialize Aes with device ID */
6092+
ret = wc_AesInit(aes, NULL, TEST_CRYPTOCB_AES_KEYIMPORT_ONLY_DEVID);
6093+
ExpectIntEQ(ret, 0);
6094+
ExpectIntEQ(aes->devId, TEST_CRYPTOCB_AES_KEYIMPORT_ONLY_DEVID);
6095+
6096+
/* Set key - should trigger CryptoCB and "import" to mock SE */
6097+
ret = wc_AesGcmSetKey(aes, key, sizeof(key));
6098+
ExpectIntEQ(ret, 0);
6099+
6100+
/* Verify SetKey callback was invoked (callback is called but then we fall through) */
6101+
ExpectIntEQ(cryptoCbKeyImportOnlySetKeyCalled, 1);
6102+
6103+
/* CRITICAL: Verify GCM offload flag is 0 (capability NOT declared) */
6104+
ExpectIntEQ(aes->gcmCryptoCbOffload, 0);
6105+
6106+
/* Verify keylen is set (software path sets this after falling through) */
6107+
ExpectIntEQ(aes->keylen, (int)sizeof(key));
6108+
6109+
/* Note: The callback sets devCtx, but since capability is not set, we fall through
6110+
* to software path. The software path will set up the key in aes->key for GCM
6111+
* table generation. devCtx may or may not be cleared by software path. */
6112+
6113+
/* CRITICAL: Verify GCM tables were generated (H table should be non-zero) */
6114+
/* If gcmCryptoCbOffload is 0, tables should be generated for software fallback */
6115+
{
6116+
int hTableNonZero = 0;
6117+
int i;
6118+
for (i = 0; i < WC_AES_BLOCK_SIZE; i++) {
6119+
if (aes->gcm.H[i] != 0) {
6120+
hTableNonZero = 1;
6121+
break;
6122+
}
6123+
}
6124+
ExpectIntEQ(hTableNonZero, 1); /* H table should be generated */
6125+
}
6126+
6127+
/* Encrypt via wolfCrypt API - should fall back to software */
6128+
/* Callback will return CRYPTOCB_UNAVAILABLE, triggering software path */
6129+
ret = wc_AesGcmEncrypt(aes, ciphertext, plaintext, 32,
6130+
iv, sizeof(iv), authTag, sizeof(authTag),
6131+
aad, 16);
6132+
ExpectIntEQ(ret, 0);
6133+
6134+
/* Decrypt via wolfCrypt API - should fall back to software */
6135+
ret = wc_AesGcmDecrypt(aes, decrypted, ciphertext, 32,
6136+
iv, sizeof(iv), authTag, sizeof(authTag),
6137+
aad, 16);
6138+
ExpectIntEQ(ret, 0);
6139+
6140+
/* Verify decrypted plaintext matches original */
6141+
ExpectIntEQ(XMEMCMP(plaintext, decrypted, 32), 0);
6142+
6143+
/* Cleanup */
6144+
wc_AesFree(aes);
6145+
wc_CryptoCb_UnRegisterDevice(TEST_CRYPTOCB_AES_KEYIMPORT_ONLY_DEVID);
6146+
6147+
/* Note: mockSeKeyImportOnly.valid may still be 1 since callback was called,
6148+
* but the key is not actually used (software path is taken) */
6149+
6150+
#ifdef WOLFSSL_SMALL_STACK
6151+
out:
6152+
XFREE(aes, NULL, DYNAMIC_TYPE_TMP_BUFFER);
6153+
XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
6154+
XFREE(iv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
6155+
XFREE(aad, NULL, DYNAMIC_TYPE_TMP_BUFFER);
6156+
XFREE(plaintext, NULL, DYNAMIC_TYPE_TMP_BUFFER);
6157+
XFREE(ciphertext, NULL, DYNAMIC_TYPE_TMP_BUFFER);
6158+
XFREE(decrypted, NULL, DYNAMIC_TYPE_TMP_BUFFER);
6159+
XFREE(authTag, NULL, DYNAMIC_TYPE_TMP_BUFFER);
6160+
#endif
6161+
6162+
return EXPECT_RESULT();
6163+
}
6164+
59536165
#endif /* WOLF_CRYPTO_CB && WOLF_CRYPTO_CB_AES_SETKEY && !NO_AES && HAVE_AESGCM */
59546166

tests/api/test_aes.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,14 @@ int test_wc_GmacUpdate(void);
5757
!defined(NO_AES) && defined(HAVE_AESGCM)
5858
int test_wc_CryptoCb_AesSetKey(void);
5959
int test_wc_CryptoCb_AesGcm_EncryptDecrypt(void);
60+
int test_wc_CryptoCb_AesKeyImportOnly(void);
6061
#endif
6162

6263
#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_AES_SETKEY) && \
6364
!defined(NO_AES) && defined(HAVE_AESGCM)
6465
#define TEST_CRYPTOCB_AES_SETKEY_DECL , TEST_DECL_GROUP("aes", test_wc_CryptoCb_AesSetKey), \
65-
TEST_DECL_GROUP("aes", test_wc_CryptoCb_AesGcm_EncryptDecrypt)
66+
TEST_DECL_GROUP("aes", test_wc_CryptoCb_AesGcm_EncryptDecrypt), \
67+
TEST_DECL_GROUP("aes", test_wc_CryptoCb_AesKeyImportOnly)
6668
#else
6769
#define TEST_CRYPTOCB_AES_SETKEY_DECL
6870
#endif

0 commit comments

Comments
 (0)