Skip to content

Commit dc84530

Browse files
committed
Add crypto callback hooks for Ed448, CMAC free, and RSA-PSS verify
Add WOLF_CRYPTO_CB dispatch hooks so a device can service: * Ed448 sign and verify, mirroring the existing Ed25519 hooks. * CMAC context free on wc_CmacFree (WOLF_CRYPTO_CB_FREE), letting a device release offload state. * RSA-PSS verify with the digest (WOLF_CRYPTO_CB_RSA_PAD) so the device does the full signature and padding check. On that path *out is set to NULL with a positive return, documented in rsa.h. Includes testwolfcrypt and API unit test coverage for each hook.
1 parent bd6388c commit dc84530

15 files changed

Lines changed: 898 additions & 5 deletions

File tree

doc/dox_comments/header_files/rsa.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -742,10 +742,13 @@ int wc_RsaPSS_VerifyCheck_ex(byte* in, word32 inLen,
742742
The key has to be associated with RNG by wc_RsaSetRNG when WC_RSA_BLINDING is enabled.
743743
744744
\return the length of the PSS data on success and negative indicates failure.
745+
On the crypto callback path *out is set to NULL though the return stays
746+
positive, so callers must not dereference *out.
745747
746748
\param in The byte array to be decrypted.
747749
\param inLen The length of in.
748-
\param out The byte array for the decrypted data to be stored.
750+
\param out The byte array for the decrypted data to be stored. Set to NULL
751+
when a crypto callback device performed the verify (see \return).
749752
\param digest Hash of the data that is being verified.
750753
\param digestLen Length of hash.
751754
\param hash The hash type to be in message

tests/api/test_cmac.c

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -720,3 +720,80 @@ int test_wc_AesCmacVerify_CryptoCb_LenMismatch(void)
720720
return EXPECT_RESULT();
721721
} /* END test_wc_AesCmacVerify_CryptoCb_LenMismatch */
722722

723+
/* Test that wc_CmacFree() dispatches a WC_ALGO_TYPE_FREE / WC_ALGO_TYPE_CMAC
724+
* request to a registered crypto callback (CryptoCb) device. */
725+
#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_FREE) && \
726+
defined(WOLFSSL_CMAC) && !defined(NO_AES) && defined(WOLFSSL_AES_DIRECT)
727+
/* Spy device: declines every request (software handles the work) but counts
728+
* CMAC free dispatches. */
729+
static int cmac_free_test_crypto_cb(int devIdArg, wc_CryptoInfo* info, void* ctx)
730+
{
731+
int* freeSeen = (int*)ctx;
732+
733+
(void)devIdArg;
734+
735+
if (info == NULL) {
736+
return BAD_FUNC_ARG;
737+
}
738+
739+
if (info->algo_type == WC_ALGO_TYPE_FREE &&
740+
info->free.algo == WC_ALGO_TYPE_CMAC) {
741+
if (freeSeen != NULL) {
742+
(*freeSeen)++;
743+
}
744+
}
745+
746+
return WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE);
747+
}
748+
#endif
749+
750+
int test_wc_CryptoCb_CmacFree(void)
751+
{
752+
EXPECT_DECLS;
753+
#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_FREE) && \
754+
defined(WOLFSSL_CMAC) && !defined(NO_AES) && defined(WOLFSSL_AES_DIRECT)
755+
int devId = 4460;
756+
int freeSeen = 0;
757+
byte key16[16] = {
758+
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
759+
0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10
760+
};
761+
byte in[16] = {
762+
0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
763+
0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00
764+
};
765+
byte tag[WC_AES_BLOCK_SIZE];
766+
word32 tagSz = (word32)sizeof(tag);
767+
WC_DECLARE_VAR(cmac, Cmac, 1, HEAP_HINT);
768+
769+
WC_ALLOC_VAR(cmac, Cmac, 1, HEAP_HINT);
770+
#ifdef WC_DECLARE_VAR_IS_HEAP_ALLOC
771+
ExpectNotNull(cmac);
772+
#endif
773+
774+
ExpectIntEQ(wc_CryptoCb_RegisterDevice(devId, cmac_free_test_crypto_cb,
775+
&freeSeen), 0);
776+
777+
/* wc_CmacFinal() internally frees the Cmac -> free dispatched to device. */
778+
ExpectIntEQ(wc_InitCmac_ex(cmac, key16, (word32)sizeof(key16), WC_CMAC_AES,
779+
NULL, HEAP_HINT, devId), 0);
780+
ExpectIntEQ(wc_CmacUpdate(cmac, in, (word32)sizeof(in)), 0);
781+
freeSeen = 0;
782+
ExpectIntEQ(wc_CmacFinal(cmac, tag, &tagSz), 0);
783+
ExpectIntGE(freeSeen, 1);
784+
785+
/* Explicit wc_CmacFree() also dispatches to the device. */
786+
tagSz = (word32)sizeof(tag);
787+
ExpectIntEQ(wc_InitCmac_ex(cmac, key16, (word32)sizeof(key16), WC_CMAC_AES,
788+
NULL, HEAP_HINT, devId), 0);
789+
ExpectIntEQ(wc_CmacUpdate(cmac, in, (word32)sizeof(in)), 0);
790+
freeSeen = 0;
791+
ExpectIntEQ(wc_CmacFree(cmac), 0);
792+
ExpectIntGE(freeSeen, 1);
793+
794+
wc_CryptoCb_UnRegisterDevice(devId);
795+
796+
WC_FREE_VAR(cmac, HEAP_HINT);
797+
#endif
798+
return EXPECT_RESULT();
799+
} /* END test_wc_CryptoCb_CmacFree */

tests/api/test_cmac.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ int test_wc_InitCmac_Label(void);
3434
int test_wc_AesCmacGenerateExDecisionCoverage(void);
3535
int test_wc_AesCmacVerifyExDecisionCoverage(void);
3636
int test_wc_AesCmacVerify_CryptoCb_LenMismatch(void);
37+
int test_wc_CryptoCb_CmacFree(void);
3738

3839
#define TEST_CMAC_DECLS \
3940
TEST_DECL_GROUP("cmac", test_wc_InitCmac), \
@@ -45,6 +46,7 @@ int test_wc_AesCmacVerify_CryptoCb_LenMismatch(void);
4546
TEST_DECL_GROUP("cmac", test_wc_InitCmac_Label), \
4647
TEST_DECL_GROUP("cmac", test_wc_AesCmacGenerateExDecisionCoverage), \
4748
TEST_DECL_GROUP("cmac", test_wc_AesCmacVerifyExDecisionCoverage), \
48-
TEST_DECL_GROUP("cmac", test_wc_AesCmacVerify_CryptoCb_LenMismatch)
49+
TEST_DECL_GROUP("cmac", test_wc_AesCmacVerify_CryptoCb_LenMismatch), \
50+
TEST_DECL_GROUP("cmac", test_wc_CryptoCb_CmacFree)
4951

5052
#endif /* WOLFCRYPT_TEST_CMAC_H */

tests/api/test_ed448.c

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@
3030

3131
#include <wolfssl/wolfcrypt/ed448.h>
3232
#include <wolfssl/wolfcrypt/types.h>
33+
#ifdef WOLF_CRYPTO_CB
34+
#include <wolfssl/wolfcrypt/cryptocb.h>
35+
#endif
3336
#include <tests/api/api.h>
3437
#include <tests/api/test_ed448.h>
3538

@@ -1369,3 +1372,123 @@ int test_wc_ed448_check_key_decisions(void)
13691372
return EXPECT_RESULT();
13701373
} /* END test_wc_ed448_check_key_decisions */
13711374

1375+
/* Test Ed448 sign/verify routed through a crypto callback (CryptoCb) device. */
1376+
#if defined(WOLF_CRYPTO_CB) && defined(HAVE_ED448) && \
1377+
defined(HAVE_ED448_SIGN) && defined(HAVE_ED448_VERIFY) && \
1378+
!defined(WC_NO_RNG)
1379+
typedef struct ed448SpyCtx {
1380+
int signSeen;
1381+
int verifySeen;
1382+
} ed448SpyCtx;
1383+
1384+
/* Spy device: services Ed448 sign/verify in software (devId cleared) and counts
1385+
* each; declines everything else so make_key runs in software. */
1386+
static int ed448_test_crypto_cb(int devIdArg, wc_CryptoInfo* info, void* ctx)
1387+
{
1388+
ed448SpyCtx* spy = (ed448SpyCtx*)ctx;
1389+
int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE);
1390+
1391+
(void)devIdArg;
1392+
1393+
if (info == NULL || spy == NULL) {
1394+
return BAD_FUNC_ARG;
1395+
}
1396+
1397+
if (info->algo_type == WC_ALGO_TYPE_PK) {
1398+
#ifdef HAVE_ED448_SIGN
1399+
if (info->pk.type == WC_PK_TYPE_ED448) {
1400+
int save = info->pk.ed448sign.key->devId;
1401+
info->pk.ed448sign.key->devId = INVALID_DEVID;
1402+
ret = wc_ed448_sign_msg_ex(
1403+
info->pk.ed448sign.in, info->pk.ed448sign.inLen,
1404+
info->pk.ed448sign.out, info->pk.ed448sign.outLen,
1405+
info->pk.ed448sign.key, info->pk.ed448sign.type,
1406+
info->pk.ed448sign.context, info->pk.ed448sign.contextLen);
1407+
info->pk.ed448sign.key->devId = save;
1408+
spy->signSeen++;
1409+
}
1410+
#endif
1411+
#ifdef HAVE_ED448_VERIFY
1412+
if (info->pk.type == WC_PK_TYPE_ED448_VERIFY) {
1413+
int save = info->pk.ed448verify.key->devId;
1414+
info->pk.ed448verify.key->devId = INVALID_DEVID;
1415+
ret = wc_ed448_verify_msg_ex(
1416+
info->pk.ed448verify.sig, info->pk.ed448verify.sigLen,
1417+
info->pk.ed448verify.msg, info->pk.ed448verify.msgLen,
1418+
info->pk.ed448verify.res, info->pk.ed448verify.key,
1419+
info->pk.ed448verify.type, info->pk.ed448verify.context,
1420+
info->pk.ed448verify.contextLen);
1421+
info->pk.ed448verify.key->devId = save;
1422+
spy->verifySeen++;
1423+
}
1424+
#endif
1425+
}
1426+
1427+
return ret;
1428+
}
1429+
#endif
1430+
1431+
int test_wc_ed448_cryptocb(void)
1432+
{
1433+
EXPECT_DECLS;
1434+
#if defined(WOLF_CRYPTO_CB) && defined(HAVE_ED448) && \
1435+
defined(HAVE_ED448_SIGN) && defined(HAVE_ED448_VERIFY) && \
1436+
!defined(WC_NO_RNG)
1437+
int devId = 4448;
1438+
ed448SpyCtx spy;
1439+
WC_RNG rng;
1440+
byte msg[32];
1441+
word32 sigLen = ED448_SIG_SIZE;
1442+
int verify = 0;
1443+
WC_DECLARE_VAR(key, ed448_key, 1, HEAP_HINT);
1444+
WC_DECLARE_VAR(sig, byte, ED448_SIG_SIZE, HEAP_HINT);
1445+
1446+
XMEMSET(&rng, 0, sizeof(rng));
1447+
XMEMSET(&spy, 0, sizeof(spy));
1448+
XMEMSET(msg, 0x5a, sizeof(msg));
1449+
1450+
WC_ALLOC_VAR(key, ed448_key, 1, HEAP_HINT);
1451+
WC_ALLOC_VAR(sig, byte, ED448_SIG_SIZE, HEAP_HINT);
1452+
#ifdef WC_DECLARE_VAR_IS_HEAP_ALLOC
1453+
ExpectNotNull(key);
1454+
ExpectNotNull(sig);
1455+
#endif
1456+
1457+
ExpectIntEQ(wc_CryptoCb_RegisterDevice(devId, ed448_test_crypto_cb, &spy),
1458+
0);
1459+
ExpectIntEQ(wc_InitRng(&rng), 0);
1460+
ExpectIntEQ(wc_ed448_init_ex(key, HEAP_HINT, devId), 0);
1461+
ExpectIntEQ(wc_ed448_make_key(&rng, ED448_KEY_SIZE, key), 0);
1462+
1463+
/* Sign routes through the device callback. */
1464+
ExpectIntEQ(wc_ed448_sign_msg(msg, (word32)sizeof(msg), sig, &sigLen, key,
1465+
NULL, 0), 0);
1466+
ExpectIntGE(spy.signSeen, 1);
1467+
1468+
/* Verify routes through the device callback. */
1469+
ExpectIntEQ(wc_ed448_verify_msg(sig, sigLen, msg, (word32)sizeof(msg),
1470+
&verify, key, NULL, 0), 0);
1471+
ExpectIntGE(spy.verifySeen, 1);
1472+
ExpectIntEQ(verify, 1);
1473+
1474+
/* Negative: corrupt the signature. Ed448 reports a bad signature as
1475+
* SIG_VERIFY_E, exercising the device verify error path (verify == 0). */
1476+
if (WC_VAR_OK(sig)) {
1477+
sig[0] ^= 0xFF;
1478+
}
1479+
verify = 1;
1480+
ExpectIntEQ(wc_ed448_verify_msg(sig, sigLen, msg, (word32)sizeof(msg),
1481+
&verify, key, NULL, 0),
1482+
WC_NO_ERR_TRACE(SIG_VERIFY_E));
1483+
ExpectIntGE(spy.verifySeen, 2);
1484+
ExpectIntEQ(verify, 0);
1485+
1486+
wc_ed448_free(key);
1487+
DoExpectIntEQ(wc_FreeRng(&rng), 0);
1488+
wc_CryptoCb_UnRegisterDevice(devId);
1489+
1490+
WC_FREE_VAR(sig, HEAP_HINT);
1491+
WC_FREE_VAR(key, HEAP_HINT);
1492+
#endif
1493+
return EXPECT_RESULT();
1494+
}

tests/api/test_ed448.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ int test_wc_Ed448DecisionCoverage(void);
4242
int test_wc_Ed448FeatureCoverage(void);
4343
int test_wc_ed448_import_private_only(void);
4444
int test_wc_ed448_check_key_decisions(void);
45+
int test_wc_ed448_cryptocb(void);
4546

4647
#define TEST_ED448_DECLS \
4748
TEST_DECL_GROUP("ed448", test_wc_ed448_make_key), \
@@ -61,6 +62,7 @@ int test_wc_ed448_check_key_decisions(void);
6162
TEST_DECL_GROUP("ed448", test_wc_Ed448DecisionCoverage), \
6263
TEST_DECL_GROUP("ed448", test_wc_Ed448FeatureCoverage), \
6364
TEST_DECL_GROUP("ed448", test_wc_ed448_import_private_only), \
64-
TEST_DECL_GROUP("ed448", test_wc_ed448_check_key_decisions)
65+
TEST_DECL_GROUP("ed448", test_wc_ed448_check_key_decisions), \
66+
TEST_DECL_GROUP("ed448", test_wc_ed448_cryptocb)
6567

6668
#endif /* WOLFCRYPT_TEST_ED448_H */

0 commit comments

Comments
 (0)