Skip to content

Commit 37b0c37

Browse files
committed
Add crypto callback only mode for ed25519
1 parent e79c581 commit 37b0c37

7 files changed

Lines changed: 167 additions & 14 deletions

File tree

.github/workflows/cryptocb-only.yml

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,8 +200,27 @@ jobs:
200200
"--enable-ocspstapling2", "--enable-dtls", "--enable-dtls13",
201201
"--enable-tls13",
202202
"CPPFLAGS=-DWOLF_CRYPTO_CB_ONLY_AES -DSWDEV_AES_ONLYECB"]},
203+
{"name": "ed25519", "minutes": 2,
204+
"comment": "WOLF_CRYPTO_CB_ONLY_ED25519: strips software Ed25519 (keygen/sign/verify); swdev provides the software path via cryptocb. Streaming verify has no callback path and is left disabled.",
205+
"configure": ["--enable-swdev", "--enable-cryptocb", "--enable-ecc",
206+
"--enable-rsa", "--enable-dh", "--enable-aesgcm",
207+
"--enable-aesccm", "--enable-aesctr", "--enable-aescfb",
208+
"--enable-aeskeywrap", "--enable-aessiv", "--enable-aesofb",
209+
"--enable-aesxts", "--enable-camellia", "--enable-chacha",
210+
"--enable-poly1305", "--enable-sha", "--enable-sha3",
211+
"--enable-shake128", "--enable-shake256", "--enable-blake2",
212+
"--enable-blake2s", "--enable-hkdf", "--enable-hashdrbg",
213+
"--enable-hashflags", "--enable-curve25519", "--enable-ed25519",
214+
"--enable-curve448", "--enable-ed448", "--enable-mlkem",
215+
"--enable-dilithium", "--enable-scrypt", "--enable-pwdbased",
216+
"--enable-pkcs7", "--enable-pkcs12", "--enable-certgen",
217+
"--enable-certreq", "--enable-certext", "--enable-keygen",
218+
"--enable-asn=all", "--enable-cmac", "--enable-xchacha",
219+
"--enable-crl", "--enable-ocsp", "--enable-ocspstapling",
220+
"--enable-ocspstapling2", "--enable-dtls", "--enable-dtls13",
221+
"--enable-tls13", "CPPFLAGS=-DWOLF_CRYPTO_CB_ONLY_ED25519"]},
203222
{"name": "all", "minutes": 2,
204-
"comment": "All five ONLY_* macros at once: every supported software primitive is stripped and dispatched through cryptocb. Catches any cross-algorithm call that a single-strip entry would still resolve via the remaining software paths.",
223+
"comment": "All six ONLY_* macros at once: every supported software primitive is stripped and dispatched through cryptocb. Catches any cross-algorithm call that a single-strip entry would still resolve via the remaining software paths.",
205224
"configure": ["--enable-swdev", "--enable-cryptocb", "--enable-ecc",
206225
"--enable-rsa", "--enable-dh", "--enable-aesgcm",
207226
"--enable-aesccm", "--enable-aesctr", "--enable-aescfb",
@@ -219,7 +238,7 @@ jobs:
219238
"--enable-crl", "--enable-ocsp", "--enable-ocspstapling",
220239
"--enable-ocspstapling2", "--enable-dtls", "--enable-dtls13",
221240
"--enable-tls13",
222-
"CPPFLAGS=-DWOLF_CRYPTO_CB_ONLY_ECC -DWOLF_CRYPTO_CB_ONLY_RSA -DWOLF_CRYPTO_CB_ONLY_SHA256 -DWOLF_CRYPTO_CB_ONLY_SHA512 -DWOLF_CRYPTO_CB_ONLY_AES"]}
241+
"CPPFLAGS=-DWOLF_CRYPTO_CB_ONLY_ECC -DWOLF_CRYPTO_CB_ONLY_RSA -DWOLF_CRYPTO_CB_ONLY_SHA256 -DWOLF_CRYPTO_CB_ONLY_SHA512 -DWOLF_CRYPTO_CB_ONLY_AES -DWOLF_CRYPTO_CB_ONLY_ED25519"]}
223242
]
224243
EOF
225244
.github/scripts/parallel-make-check.py \

tests/swdev/README.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,16 @@ compiled separately from the main library, linked into the test
66
programs only, and exposes exactly two C symbols. **It is not a
77
production component and must not be linked into shipping binaries.**
88

9-
The four switches it supports are:
9+
The switches it supports are:
1010

1111
| Macro | Strips | Test target |
1212
|--------------------------------|----------------|--------------------|
1313
| `WOLF_CRYPTO_CB_ONLY_RSA` | software RSA | RSA via CryptoCb |
1414
| `WOLF_CRYPTO_CB_ONLY_ECC` | software ECC | ECC via CryptoCb |
1515
| `WOLF_CRYPTO_CB_ONLY_SHA256` | software SHA-256 | SHA-256 via CryptoCb |
16+
| `WOLF_CRYPTO_CB_ONLY_SHA512` | software SHA-512 | SHA-512 via CryptoCb |
1617
| `WOLF_CRYPTO_CB_ONLY_AES` | software AES | AES via CryptoCb |
18+
| `WOLF_CRYPTO_CB_ONLY_ED25519` | software Ed25519 | Ed25519 via CryptoCb |
1719

1820
When a test program calls e.g. `wc_AesCbcEncrypt()` against a libwolfssl
1921
built with `-DWOLF_CRYPTO_CB_ONLY_AES`, the software AES path is gone;
@@ -55,7 +57,7 @@ internal copy of the AES code, and returns the result.
5557
| wc_SwDev_Callback(devId, info, ctx) |
5658
| - swdev_ensure_init() lazy wolfCrypt_Init |
5759
| - switch (info->algo_type): |
58-
| PK -> RSA / ECC software impl |
60+
| PK -> RSA / ECC / Ed25519 software impl |
5961
| HASH -> SHA-256 software impl |
6062
| CIPHER -> AES (CBC/CTR/ECB/GCM/CCM) software impl |
6163
| |
@@ -70,10 +72,10 @@ internal copy of the AES code, and returns the result.
7072
The whole mechanism rests on compiling the wolfcrypt sources twice:
7173

7274
1. **libwolfssl** is built normally with the user's `_ONLY_*` flags
73-
set, so its software RSA/ECC/SHA-256/AES paths are gone.
75+
set, so its software RSA/ECC/SHA-256/SHA-512/AES/Ed25519 paths are gone.
7476
2. **swdev** recompiles the same source set under
75-
`tests/swdev/user_settings.h`, which `#undef`s all four `_ONLY_*`
76-
macros. swdev therefore contains the full software implementations.
77+
`tests/swdev/user_settings.h`, which `#undef`s every `_ONLY_*`
78+
macro. swdev therefore contains the full software implementations.
7779

7880
To prevent symbol collisions when both are linked into the same test
7981
binary, `tests/swdev/Makefile` does the following:

tests/swdev/swdev.c

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@
4040
#ifndef NO_AES
4141
#include <wolfssl/wolfcrypt/aes.h>
4242
#endif
43+
#ifdef HAVE_ED25519
44+
#include <wolfssl/wolfcrypt/ed25519.h>
45+
#endif
4346

4447
static int swdev_initialized = 0;
4548

@@ -238,6 +241,38 @@ static int swdev_ecc_check_pub(wc_CryptoInfo* info)
238241
#endif /* HAVE_ECC_CHECK_KEY */
239242
#endif /* HAVE_ECC */
240243

244+
#ifdef HAVE_ED25519
245+
#ifdef HAVE_ED25519_MAKE_KEY
246+
static int swdev_ed25519_keygen(wc_CryptoInfo* info)
247+
{
248+
return wc_ed25519_make_key(info->pk.ed25519kg.rng,
249+
info->pk.ed25519kg.size, info->pk.ed25519kg.key);
250+
}
251+
#endif
252+
253+
#ifdef HAVE_ED25519_SIGN
254+
static int swdev_ed25519_sign(wc_CryptoInfo* info)
255+
{
256+
return wc_ed25519_sign_msg_ex(info->pk.ed25519sign.in,
257+
info->pk.ed25519sign.inLen, info->pk.ed25519sign.out,
258+
info->pk.ed25519sign.outLen, info->pk.ed25519sign.key,
259+
info->pk.ed25519sign.type, info->pk.ed25519sign.context,
260+
info->pk.ed25519sign.contextLen);
261+
}
262+
#endif
263+
264+
#ifdef HAVE_ED25519_VERIFY
265+
static int swdev_ed25519_verify(wc_CryptoInfo* info)
266+
{
267+
return wc_ed25519_verify_msg_ex(info->pk.ed25519verify.sig,
268+
info->pk.ed25519verify.sigLen, info->pk.ed25519verify.msg,
269+
info->pk.ed25519verify.msgLen, info->pk.ed25519verify.res,
270+
info->pk.ed25519verify.key, info->pk.ed25519verify.type,
271+
info->pk.ed25519verify.context, info->pk.ed25519verify.contextLen);
272+
}
273+
#endif
274+
#endif /* HAVE_ED25519 */
275+
241276
#ifndef NO_SHA256
242277
/* Copy hash state between caller's wc_Sha256 and swdev's shadow, leaving
243278
* admin fields (heap, devId, devCtx, W, async, HW ctx) per-side. */
@@ -771,7 +806,7 @@ WC_SWDEV_EXPORT int wc_SwDev_Callback(int devId, wc_CryptoInfo* info,
771806
return ret;
772807

773808
switch (info->algo_type) {
774-
#if !defined(NO_RSA) || defined(HAVE_ECC)
809+
#if !defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519)
775810
case WC_ALGO_TYPE_PK:
776811
switch (info->pk.type) {
777812
#ifndef NO_RSA
@@ -802,6 +837,20 @@ WC_SWDEV_EXPORT int wc_SwDev_Callback(int devId, wc_CryptoInfo* info,
802837
return swdev_ecc_check_pub(info);
803838
#endif
804839
#endif /* HAVE_ECC */
840+
#ifdef HAVE_ED25519
841+
#ifdef HAVE_ED25519_MAKE_KEY
842+
case WC_PK_TYPE_ED25519_KEYGEN:
843+
return swdev_ed25519_keygen(info);
844+
#endif
845+
#ifdef HAVE_ED25519_SIGN
846+
case WC_PK_TYPE_ED25519_SIGN:
847+
return swdev_ed25519_sign(info);
848+
#endif
849+
#ifdef HAVE_ED25519_VERIFY
850+
case WC_PK_TYPE_ED25519_VERIFY:
851+
return swdev_ed25519_verify(info);
852+
#endif
853+
#endif /* HAVE_ED25519 */
805854
default:
806855
return CRYPTOCB_UNAVAILABLE;
807856
}

tests/swdev/user_settings.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#undef WOLF_CRYPTO_CB_ONLY_SHA256
2828
#undef WOLF_CRYPTO_CB_ONLY_SHA512
2929
#undef WOLF_CRYPTO_CB_ONLY_AES
30+
#undef WOLF_CRYPTO_CB_ONLY_ED25519
3031

3132
#ifndef WOLF_CRYPTO_CB
3233
#error "wc_swdev requires the main build to define WOLF_CRYPTO_CB"

wolfcrypt/src/cryptocb.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ Crypto Callback Build Options:
6464
* WOLF_CRYPTO_CB_ONLY_SHA256: Use only callbacks for SHA-256 default: off
6565
* WOLF_CRYPTO_CB_ONLY_SHA512: Use only callbacks for SHA-512 default: off
6666
* WOLF_CRYPTO_CB_ONLY_AES: Use only callbacks for AES default: off
67+
* WOLF_CRYPTO_CB_ONLY_ED25519: Use only callbacks for Ed25519 default: off
6768
*/
6869

6970
#include <wolfssl/wolfcrypt/libwolfssl_sources.h>

wolfcrypt/src/ed25519.c

Lines changed: 68 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -376,14 +376,20 @@ int wc_ed25519_make_key(WC_RNG* rng, int keySz, ed25519_key* key)
376376
key->pubKeySet = 0;
377377

378378
#ifdef WOLF_CRYPTO_CB
379-
if (key->devId != INVALID_DEVID) {
379+
#ifndef WOLF_CRYPTO_CB_FIND
380+
if (key->devId != INVALID_DEVID)
381+
#endif
382+
{
380383
ret = wc_CryptoCb_Ed25519Gen(rng, keySz, key);
381384
if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
382385
return ret;
383386
/* fall-through when unavailable */
384387
}
385388
#endif
386389

390+
#ifdef WOLF_CRYPTO_CB_ONLY_ED25519
391+
return NO_VALID_DEVID;
392+
#else
387393
ret = wc_RNG_GenerateBlock(rng, key->k, ED25519_KEY_SIZE);
388394
if (ret != 0)
389395
return ret;
@@ -407,6 +413,7 @@ int wc_ed25519_make_key(WC_RNG* rng, int keySz, ed25519_key* key)
407413
#endif
408414

409415
return ret;
416+
#endif /* WOLF_CRYPTO_CB_ONLY_ED25519 */
410417
}
411418
#endif /* HAVE_ED25519_MAKE_KEY */
412419

@@ -434,6 +441,30 @@ int wc_ed25519_sign_msg_ex(const byte* in, word32 inLen, byte* out,
434441
(void)contextLen;
435442
(void)type;
436443
ret = se050_ed25519_sign_msg(in, inLen, out, outLen, key);
444+
#elif defined(WOLF_CRYPTO_CB_ONLY_ED25519)
445+
ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE);
446+
447+
if (in == NULL || out == NULL || outLen == NULL || key == NULL ||
448+
(context == NULL && contextLen != 0)) {
449+
return BAD_FUNC_ARG;
450+
}
451+
452+
if ((type == Ed25519ph) &&
453+
(inLen != WC_SHA512_DIGEST_SIZE))
454+
{
455+
return BAD_LENGTH_E;
456+
}
457+
458+
#ifndef WOLF_CRYPTO_CB_FIND
459+
if (key->devId != INVALID_DEVID)
460+
#endif
461+
{
462+
ret = wc_CryptoCb_Ed25519Sign(in, inLen, out, outLen, key, type,
463+
context, contextLen);
464+
}
465+
if (ret == WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
466+
ret = NO_VALID_DEVID;
467+
}
437468
#else
438469
#ifdef FREESCALE_LTC_ECC
439470
ALIGN16 byte tempBuf[ED25519_PRV_KEY_SIZE];
@@ -461,7 +492,10 @@ int wc_ed25519_sign_msg_ex(const byte* in, word32 inLen, byte* out,
461492
}
462493

463494
#ifdef WOLF_CRYPTO_CB
464-
if (key->devId != INVALID_DEVID) {
495+
#ifndef WOLF_CRYPTO_CB_FIND
496+
if (key->devId != INVALID_DEVID)
497+
#endif
498+
{
465499
ret = wc_CryptoCb_Ed25519Sign(in, inLen, out, outLen, key, type,
466500
context, contextLen);
467501
if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
@@ -599,7 +633,8 @@ int wc_ed25519_sign_msg_ex(const byte* in, word32 inLen, byte* out,
599633
ForceZero(nonce, sizeof(nonce));
600634
#endif /* WOLFSSL_SE050 */
601635

602-
#ifdef WOLFSSL_EDDSA_CHECK_PRIV_ON_SIGN
636+
#if defined(WOLFSSL_EDDSA_CHECK_PRIV_ON_SIGN) && \
637+
!defined(WOLF_CRYPTO_CB_ONLY_ED25519)
603638
if (ret == 0) {
604639
int i;
605640
byte c = 0;
@@ -696,7 +731,7 @@ int wc_ed25519ph_sign_msg(const byte* in, word32 inLen, byte* out,
696731
#endif /* HAVE_ED25519_SIGN */
697732

698733
#ifdef HAVE_ED25519_VERIFY
699-
#ifndef WOLFSSL_SE050
734+
#if !defined(WOLFSSL_SE050) && !defined(WOLF_CRYPTO_CB_ONLY_ED25519)
700735

701736
#ifdef WOLFSSL_CHECK_VER_FAULTS
702737
static const byte sha512_empty[] = {
@@ -928,7 +963,7 @@ static int ed25519_verify_msg_final_with_sha(const byte* sig, word32 sigLen,
928963

929964
return ret;
930965
}
931-
#endif /* WOLFSSL_SE050 */
966+
#endif /* !WOLFSSL_SE050 && !WOLF_CRYPTO_CB_ONLY_ED25519 */
932967

933968
#if defined(WOLFSSL_ED25519_STREAMING_VERIFY) && !defined(WOLFSSL_SE050)
934969

@@ -972,6 +1007,30 @@ int wc_ed25519_verify_msg_ex(const byte* sig, word32 sigLen, const byte* msg,
9721007
(void)contextLen;
9731008
(void)ed25519Ctx;
9741009
ret = se050_ed25519_verify_msg(sig, sigLen, msg, msgLen, key, res);
1010+
#elif defined(WOLF_CRYPTO_CB_ONLY_ED25519)
1011+
(void)ed25519Ctx;
1012+
ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE);
1013+
1014+
if (sig == NULL || msg == NULL || res == NULL || key == NULL ||
1015+
(context == NULL && contextLen != 0))
1016+
return BAD_FUNC_ARG;
1017+
1018+
if ((type == Ed25519ph) &&
1019+
(msgLen != WC_SHA512_DIGEST_SIZE))
1020+
{
1021+
return BAD_LENGTH_E;
1022+
}
1023+
1024+
#ifndef WOLF_CRYPTO_CB_FIND
1025+
if (key->devId != INVALID_DEVID)
1026+
#endif
1027+
{
1028+
ret = wc_CryptoCb_Ed25519Verify(sig, sigLen, msg, msgLen, res, key,
1029+
type, context, contextLen);
1030+
}
1031+
if (ret == WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
1032+
ret = NO_VALID_DEVID;
1033+
}
9751034
#else
9761035
#ifdef WOLFSSL_ED25519_PERSISTENT_SHA
9771036
wc_Sha512 *sha;
@@ -991,7 +1050,10 @@ int wc_ed25519_verify_msg_ex(const byte* sig, word32 sigLen, const byte* msg,
9911050
}
9921051

9931052
#ifdef WOLF_CRYPTO_CB
994-
if (key->devId != INVALID_DEVID) {
1053+
#ifndef WOLF_CRYPTO_CB_FIND
1054+
if (key->devId != INVALID_DEVID)
1055+
#endif
1056+
{
9951057
ret = wc_CryptoCb_Ed25519Verify(sig, sigLen, msg, msgLen, res, key,
9961058
type, context, contextLen);
9971059
if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))

wolfssl/wolfcrypt/settings.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5536,6 +5536,25 @@ blinding by defining WC_BLINDING_NO_RNG_ACKNOWLEDGE_WEAKNESS."
55365536
#if defined(WOLF_CRYPTO_CB_ONLY_AES) && !defined(WOLF_CRYPTO_CB)
55375537
#error "WOLF_CRYPTO_CB_ONLY_AES requires WOLF_CRYPTO_CB"
55385538
#endif
5539+
#if defined(WOLF_CRYPTO_CB_ONLY_ED25519) && !defined(WOLF_CRYPTO_CB)
5540+
#error "WOLF_CRYPTO_CB_ONLY_ED25519 requires WOLF_CRYPTO_CB"
5541+
#endif
5542+
#if defined(WOLF_CRYPTO_CB_ONLY_ED25519) && !defined(HAVE_ED25519)
5543+
#error "WOLF_CRYPTO_CB_ONLY_ED25519 requires HAVE_ED25519"
5544+
#endif
5545+
/* Software Ed25519 is stripped, so no in-tree Ed25519 backend may be present
5546+
* and the streaming verify API (which has no callback path) must be off. */
5547+
#if defined(WOLF_CRYPTO_CB_ONLY_ED25519) && defined(WOLFSSL_SE050)
5548+
#error "WOLF_CRYPTO_CB_ONLY_ED25519 is incompatible with WOLFSSL_SE050"
5549+
#endif
5550+
#if defined(WOLF_CRYPTO_CB_ONLY_ED25519) && defined(HAVE_FIPS)
5551+
#error "WOLF_CRYPTO_CB_ONLY_ED25519 is incompatible with FIPS builds"
5552+
#endif
5553+
#if defined(WOLF_CRYPTO_CB_ONLY_ED25519) && \
5554+
defined(WOLFSSL_ED25519_STREAMING_VERIFY)
5555+
#error "WOLF_CRYPTO_CB_ONLY_ED25519 is incompatible with " \
5556+
"WOLFSSL_ED25519_STREAMING_VERIFY"
5557+
#endif
55395558

55405559
/* Early Data / Session Rules */
55415560
#if !defined(WOLFCRYPT_ONLY) && defined(WOLFSSL_EARLY_DATA) && \

0 commit comments

Comments
 (0)