Skip to content

Commit 7a15bf4

Browse files
committed
WOLF_CRYPTO_CB_ONLY_AES: add support + swdev for testing
Modes (CTR, GCM, CCM, etc.) can be supported either directly or fallback to invoking the crypto callback with a "direct" (ECB) mode. Software implementation and AES tables are stripped under CB_ONLY_AES. wc_swdev gains AES support so WOLF_CRYPTO_CB_ONLY_AES builds can be tested. crypto find cb support added to wc_AesSetKey in order to support current CI tests that use INVALID_DEVID.
1 parent 994b806 commit 7a15bf4

9 files changed

Lines changed: 464 additions & 14 deletions

File tree

.github/workflows/cryptocb-only.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,19 @@ jobs:
3535
- name: SHA256
3636
extra_config: --disable-sha224
3737
cppflags: -DWOLF_CRYPTO_CB_ONLY_SHA256
38+
# WOLF_CRYPTO_CB_ONLY_AES: strips software AES; swdev provides the
39+
# software path via cryptocb.
40+
- name: AES
41+
cppflags: -DWOLF_CRYPTO_CB_ONLY_AES
42+
# All four ONLY_* macros at once: every supported software primitive
43+
# is stripped and dispatched through cryptocb. Catches any cross-
44+
# algorithm call that a single-strip entry would still resolve via
45+
# the remaining software paths.
46+
- name: ALL
47+
extra_config: --disable-sha224
48+
cppflags: >-
49+
-DWOLF_CRYPTO_CB_ONLY_ECC -DWOLF_CRYPTO_CB_ONLY_RSA
50+
-DWOLF_CRYPTO_CB_ONLY_SHA256 -DWOLF_CRYPTO_CB_ONLY_AES
3851
name: make check (${{ matrix.name }})
3952
if: github.repository_owner == 'wolfssl'
4053
runs-on: ubuntu-24.04

tests/api.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28472,7 +28472,7 @@ static int test_SSL_CIPHER_get_xxx(void)
2847228472
}
2847328473

2847428474
#if defined(WOLF_CRYPTO_CB) && defined(HAVE_IO_TESTS_DEPENDENCIES) && \
28475-
!defined(WOLF_CRYPTO_CB_ONLY_SHA256) && \
28475+
!defined(WOLF_CRYPTO_CB_ONLY_SHA256) && !defined(WOLF_CRYPTO_CB_ONLY_AES) && \
2847628476
!defined(WOLF_CRYPTO_CB_ONLY_ECC) && !defined(WOLF_CRYPTO_CB_ONLY_RSA)
2847728477

2847828478
static int load_pem_key_file_as_der(const char* privKeyFile, DerBuffer** pDer,
@@ -29476,7 +29476,7 @@ static int test_wc_CryptoCb(void)
2947629476
{
2947729477
EXPECT_DECLS;
2947829478
#if defined(WOLF_CRYPTO_CB) && \
29479-
!defined(WOLF_CRYPTO_CB_ONLY_SHA256) && \
29479+
!defined(WOLF_CRYPTO_CB_ONLY_SHA256) && !defined(WOLF_CRYPTO_CB_ONLY_AES) && \
2948029480
!defined(WOLF_CRYPTO_CB_ONLY_ECC) && !defined(WOLF_CRYPTO_CB_ONLY_RSA)
2948129481
/* TODO: Add crypto callback API tests */
2948229482

@@ -36809,7 +36809,7 @@ static int test_pkcs7_padding(void)
3680936809

3681036810
/* Encode EncryptedData */
3681136811
XMEMSET(&pkcs7, 0, sizeof(pkcs7));
36812-
ExpectIntEQ(wc_PKCS7_Init(&pkcs7, NULL, 0), 0);
36812+
ExpectIntEQ(wc_PKCS7_Init(&pkcs7, NULL, INVALID_DEVID), 0);
3681336813
pkcs7.content = plaintext;
3681436814
pkcs7.contentSz = sizeof(plaintext);
3681536815
pkcs7.contentOID = DATA;
@@ -36838,7 +36838,7 @@ static int test_pkcs7_padding(void)
3683836838

3683936839
/* Decrypt modified ciphertext - must fail, not succeed */
3684036840
XMEMSET(&pkcs7, 0, sizeof(pkcs7));
36841-
ExpectIntEQ(wc_PKCS7_Init(&pkcs7, NULL, 0), 0);
36841+
ExpectIntEQ(wc_PKCS7_Init(&pkcs7, NULL, INVALID_DEVID), 0);
3684236842
pkcs7.encryptionKey = key;
3684336843
pkcs7.encryptionKeySz = sizeof(key);
3684436844

tests/swdev/swdev.c

Lines changed: 277 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
#ifndef NO_SHA256
1717
#include <wolfssl/wolfcrypt/sha256.h>
1818
#endif
19+
#ifndef NO_AES
20+
#include <wolfssl/wolfcrypt/aes.h>
21+
#endif
1922

2023
static int swdev_initialized = 0;
2124

@@ -179,6 +182,253 @@ static int swdev_sha256(wc_CryptoInfo* info)
179182
}
180183
#endif /* !NO_SHA256 */
181184

185+
#ifndef NO_AES
186+
/* Rebuild a software AES shadow from the caller's raw devKey, since the
187+
* caller's Aes has no software round-key schedule under CB_ONLY_AES. */
188+
static int swdev_aes_shadow_init(Aes* shadow, const Aes* aes, int dir)
189+
{
190+
int ret;
191+
192+
if (shadow == NULL || aes == NULL)
193+
return BAD_FUNC_ARG;
194+
if (aes->keylen <= 0 || aes->keylen > (int)sizeof(aes->devKey))
195+
return BAD_FUNC_ARG;
196+
197+
ret = wc_AesInit(shadow, aes->heap, INVALID_DEVID);
198+
if (ret != 0)
199+
return ret;
200+
201+
ret = wc_AesSetKey(shadow, (const byte*)aes->devKey,
202+
(word32)aes->keylen, (const byte*)aes->reg, dir);
203+
if (ret != 0) {
204+
wc_AesFree(shadow);
205+
return ret;
206+
}
207+
208+
XMEMCPY(shadow->tmp, aes->tmp, sizeof(shadow->tmp));
209+
#if defined(WOLFSSL_AES_COUNTER) || defined(WOLFSSL_AES_CFB) || \
210+
defined(WOLFSSL_AES_OFB) || defined(WOLFSSL_AES_XTS) || \
211+
defined(WOLFSSL_AES_CTS)
212+
shadow->left = aes->left;
213+
#endif
214+
215+
return 0;
216+
}
217+
218+
static void swdev_aes_shadow_sync(Aes* dst, const Aes* src)
219+
{
220+
XMEMCPY(dst->reg, src->reg, sizeof(dst->reg));
221+
XMEMCPY(dst->tmp, src->tmp, sizeof(dst->tmp));
222+
#if defined(WOLFSSL_AES_COUNTER) || defined(WOLFSSL_AES_CFB) || \
223+
defined(WOLFSSL_AES_OFB) || defined(WOLFSSL_AES_XTS) || \
224+
defined(WOLFSSL_AES_CTS)
225+
dst->left = src->left;
226+
#endif
227+
}
228+
229+
#ifdef HAVE_AES_CBC
230+
static int swdev_aes_cbc(wc_CryptoInfo* info)
231+
{
232+
Aes* aes = info->cipher.aescbc.aes;
233+
byte* out = info->cipher.aescbc.out;
234+
const byte* in = info->cipher.aescbc.in;
235+
word32 sz = info->cipher.aescbc.sz;
236+
Aes shadow;
237+
int ret;
238+
239+
ret = swdev_aes_shadow_init(&shadow, aes,
240+
info->cipher.enc ? AES_ENCRYPTION : AES_DECRYPTION);
241+
if (ret != 0)
242+
return ret;
243+
244+
if (info->cipher.enc)
245+
ret = wc_AesCbcEncrypt(&shadow, out, in, sz);
246+
#ifdef HAVE_AES_DECRYPT
247+
else
248+
ret = wc_AesCbcDecrypt(&shadow, out, in, sz);
249+
#else
250+
else
251+
ret = CRYPTOCB_UNAVAILABLE;
252+
#endif
253+
swdev_aes_shadow_sync(aes, &shadow);
254+
wc_AesFree(&shadow);
255+
return ret;
256+
}
257+
#endif /* HAVE_AES_CBC */
258+
259+
#ifdef WOLFSSL_AES_COUNTER
260+
static int swdev_aes_ctr(wc_CryptoInfo* info)
261+
{
262+
Aes* aes = info->cipher.aesctr.aes;
263+
Aes shadow;
264+
int ret;
265+
266+
ret = swdev_aes_shadow_init(&shadow, aes, AES_ENCRYPTION);
267+
if (ret != 0)
268+
return ret;
269+
270+
ret = wc_AesCtrEncrypt(&shadow, info->cipher.aesctr.out,
271+
info->cipher.aesctr.in, info->cipher.aesctr.sz);
272+
swdev_aes_shadow_sync(aes, &shadow);
273+
wc_AesFree(&shadow);
274+
return ret;
275+
}
276+
#endif
277+
278+
#if defined(HAVE_AES_ECB) || defined(WOLFSSL_AES_DIRECT)
279+
static int swdev_aes_ecb(wc_CryptoInfo* info)
280+
{
281+
Aes* aes = info->cipher.aesecb.aes;
282+
byte* out = info->cipher.aesecb.out;
283+
const byte* in = info->cipher.aesecb.in;
284+
word32 sz = info->cipher.aesecb.sz;
285+
Aes shadow;
286+
int ret;
287+
288+
ret = swdev_aes_shadow_init(&shadow, aes,
289+
info->cipher.enc ? AES_ENCRYPTION : AES_DECRYPTION);
290+
if (ret != 0)
291+
return ret;
292+
293+
#ifdef HAVE_AES_ECB
294+
if (info->cipher.enc)
295+
ret = wc_AesEcbEncrypt(&shadow, out, in, sz);
296+
#ifdef HAVE_AES_DECRYPT
297+
else
298+
ret = wc_AesEcbDecrypt(&shadow, out, in, sz);
299+
#else
300+
else
301+
ret = CRYPTOCB_UNAVAILABLE;
302+
#endif
303+
#elif defined(WOLFSSL_AES_DIRECT)
304+
if (sz != WC_AES_BLOCK_SIZE) {
305+
ret = CRYPTOCB_UNAVAILABLE;
306+
}
307+
else if (info->cipher.enc) {
308+
ret = wc_AesEncryptDirect(&shadow, out, in);
309+
}
310+
#ifdef HAVE_AES_DECRYPT
311+
else {
312+
ret = wc_AesDecryptDirect(&shadow, out, in);
313+
}
314+
#else
315+
else {
316+
ret = CRYPTOCB_UNAVAILABLE;
317+
}
318+
#endif
319+
#else
320+
(void)out;
321+
(void)in;
322+
(void)sz;
323+
ret = CRYPTOCB_UNAVAILABLE;
324+
#endif
325+
326+
wc_AesFree(&shadow);
327+
return ret;
328+
}
329+
#endif /* HAVE_AES_ECB || WOLFSSL_AES_DIRECT */
330+
331+
#ifdef HAVE_AESGCM
332+
static int swdev_aes_gcm(wc_CryptoInfo* info)
333+
{
334+
Aes* aes = info->cipher.enc ? info->cipher.aesgcm_enc.aes :
335+
info->cipher.aesgcm_dec.aes;
336+
Aes shadow;
337+
int ret;
338+
339+
if (aes == NULL || aes->keylen <= 0 || aes->keylen > (int)sizeof(aes->devKey))
340+
return BAD_FUNC_ARG;
341+
342+
ret = wc_AesInit(&shadow, aes->heap, INVALID_DEVID);
343+
if (ret != 0)
344+
return ret;
345+
346+
ret = wc_AesGcmSetKey(&shadow, (const byte*)aes->devKey, (word32)aes->keylen);
347+
if (ret != 0) {
348+
wc_AesFree(&shadow);
349+
return ret;
350+
}
351+
352+
if (info->cipher.enc) {
353+
ret = wc_AesGcmEncrypt(&shadow,
354+
info->cipher.aesgcm_enc.out, info->cipher.aesgcm_enc.in,
355+
info->cipher.aesgcm_enc.sz,
356+
info->cipher.aesgcm_enc.iv, info->cipher.aesgcm_enc.ivSz,
357+
info->cipher.aesgcm_enc.authTag,
358+
info->cipher.aesgcm_enc.authTagSz,
359+
info->cipher.aesgcm_enc.authIn,
360+
info->cipher.aesgcm_enc.authInSz);
361+
}
362+
else {
363+
ret = wc_AesGcmDecrypt(&shadow, info->cipher.aesgcm_dec.out,
364+
info->cipher.aesgcm_dec.in, info->cipher.aesgcm_dec.sz,
365+
info->cipher.aesgcm_dec.iv, info->cipher.aesgcm_dec.ivSz,
366+
info->cipher.aesgcm_dec.authTag,
367+
info->cipher.aesgcm_dec.authTagSz,
368+
info->cipher.aesgcm_dec.authIn,
369+
info->cipher.aesgcm_dec.authInSz);
370+
}
371+
372+
wc_AesFree(&shadow);
373+
return ret;
374+
}
375+
#endif /* HAVE_AESGCM */
376+
377+
#ifdef HAVE_AESCCM
378+
static int swdev_aes_ccm(wc_CryptoInfo* info)
379+
{
380+
Aes* aes = info->cipher.enc ? info->cipher.aesccm_enc.aes :
381+
info->cipher.aesccm_dec.aes;
382+
Aes shadow;
383+
int ret;
384+
385+
if (aes == NULL || aes->keylen <= 0 || aes->keylen > (int)sizeof(aes->devKey))
386+
return BAD_FUNC_ARG;
387+
388+
ret = wc_AesInit(&shadow, aes->heap, INVALID_DEVID);
389+
if (ret != 0)
390+
return ret;
391+
392+
ret = wc_AesCcmSetKey(&shadow, (const byte*)aes->devKey, (word32)aes->keylen);
393+
if (ret != 0) {
394+
wc_AesFree(&shadow);
395+
return ret;
396+
}
397+
398+
if (info->cipher.enc) {
399+
ret = wc_AesCcmEncrypt(&shadow,
400+
info->cipher.aesccm_enc.out, info->cipher.aesccm_enc.in,
401+
info->cipher.aesccm_enc.sz,
402+
info->cipher.aesccm_enc.nonce,
403+
info->cipher.aesccm_enc.nonceSz,
404+
info->cipher.aesccm_enc.authTag,
405+
info->cipher.aesccm_enc.authTagSz,
406+
info->cipher.aesccm_enc.authIn,
407+
info->cipher.aesccm_enc.authInSz);
408+
}
409+
#ifdef HAVE_AES_DECRYPT
410+
else {
411+
ret = wc_AesCcmDecrypt(&shadow, info->cipher.aesccm_dec.out,
412+
info->cipher.aesccm_dec.in, info->cipher.aesccm_dec.sz,
413+
info->cipher.aesccm_dec.nonce,
414+
info->cipher.aesccm_dec.nonceSz,
415+
info->cipher.aesccm_dec.authTag,
416+
info->cipher.aesccm_dec.authTagSz,
417+
info->cipher.aesccm_dec.authIn,
418+
info->cipher.aesccm_dec.authInSz);
419+
}
420+
#else
421+
else {
422+
ret = CRYPTOCB_UNAVAILABLE;
423+
}
424+
#endif
425+
426+
wc_AesFree(&shadow);
427+
return ret;
428+
}
429+
#endif /* HAVE_AESCCM */
430+
#endif /* !NO_AES */
431+
182432
WC_SWDEV_EXPORT int wc_SwDev_Callback(int devId, wc_CryptoInfo* info,
183433
void* ctx)
184434
{
@@ -233,6 +483,33 @@ WC_SWDEV_EXPORT int wc_SwDev_Callback(int devId, wc_CryptoInfo* info,
233483
return CRYPTOCB_UNAVAILABLE;
234484
}
235485
#endif
486+
#ifndef NO_AES
487+
case WC_ALGO_TYPE_CIPHER:
488+
switch (info->cipher.type) {
489+
#ifdef HAVE_AES_CBC
490+
case WC_CIPHER_AES_CBC:
491+
return swdev_aes_cbc(info);
492+
#endif
493+
#ifdef WOLFSSL_AES_COUNTER
494+
case WC_CIPHER_AES_CTR:
495+
return swdev_aes_ctr(info);
496+
#endif
497+
#if defined(HAVE_AES_ECB) || defined(WOLFSSL_AES_DIRECT)
498+
case WC_CIPHER_AES_ECB:
499+
return swdev_aes_ecb(info);
500+
#endif
501+
#ifdef HAVE_AESGCM
502+
case WC_CIPHER_AES_GCM:
503+
return swdev_aes_gcm(info);
504+
#endif
505+
#ifdef HAVE_AESCCM
506+
case WC_CIPHER_AES_CCM:
507+
return swdev_aes_ccm(info);
508+
#endif
509+
default:
510+
return CRYPTOCB_UNAVAILABLE;
511+
}
512+
#endif /* !NO_AES */
236513
default:
237514
return CRYPTOCB_UNAVAILABLE;
238515
}

tests/swdev/user_settings.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#undef WOLF_CRYPTO_CB_ONLY_RSA
1717
#undef WOLF_CRYPTO_CB_ONLY_ECC
1818
#undef WOLF_CRYPTO_CB_ONLY_SHA256
19+
#undef WOLF_CRYPTO_CB_ONLY_AES
1920

2021
#ifndef WOLF_CRYPTO_CB
2122
#error "wc_swdev requires the main build to define WOLF_CRYPTO_CB"

0 commit comments

Comments
 (0)