Skip to content

Commit eb1c9a2

Browse files
committed
slhdsa: add WOLF_CRYPTO_CB and WOLF_PRIVATE_KEY_ID support
Wire SLH-DSA into the existing PQC CryptoCb dispatch (the same path already used by ML-DSA / Dilithium) so a registered device can intercept key generation, signing, verification, and key release. Also add algorithm-specific id/label storage on SlhDsaKey for use with WOLF_PRIVATE_KEY_ID, mirroring the dilithium_key API. - types.h: add WC_PQC_SIG_TYPE_SLHDSA and widen the WC_PK_TYPE_PQC_SIG_* / wc_PqcSignatureType guards to include WOLFSSL_HAVE_SLHDSA. - cryptocb.h/.c: include wc_slhdsa.h, widen the PQC sig guards, and teach wc_CryptoCb_PqcSigGetDevId to extract devId from SlhDsaKey. - wc_slhdsa.h: add devCtx (alongside devId) under WOLF_CRYPTO_CB; add id/label storage and SLHDSA_MAX_{ID,LABEL}_LEN under WOLF_PRIVATE_KEY_ID; declare wc_SlhDsaKey_Init_id and _Init_label. - wc_slhdsa.c: implement Init_id / Init_label; hook wc_CryptoCb_MakePqcSignatureKey in MakeKey, wc_CryptoCb_PqcSign in Sign / SignHash, wc_CryptoCb_PqcVerify in Verify / VerifyHash, and wc_CryptoCb_Free in Free; scrub id/label/devCtx on free.
1 parent 7d1516f commit eb1c9a2

5 files changed

Lines changed: 242 additions & 8 deletions

File tree

wolfcrypt/src/cryptocb.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1286,7 +1286,8 @@ int wc_CryptoCb_PqcDecapsulate(const byte* ciphertext, word32 ciphertextLen,
12861286
}
12871287
#endif /* WOLFSSL_HAVE_MLKEM */
12881288

1289-
#if defined(HAVE_FALCON) || defined(HAVE_DILITHIUM)
1289+
#if defined(HAVE_FALCON) || defined(HAVE_DILITHIUM) || \
1290+
defined(WOLFSSL_HAVE_SLHDSA)
12901291
int wc_CryptoCb_PqcSigGetDevId(int type, void* key)
12911292
{
12921293
int devId = INVALID_DEVID;
@@ -1305,6 +1306,11 @@ int wc_CryptoCb_PqcSigGetDevId(int type, void* key)
13051306
devId = ((falcon_key*) key)->devId;
13061307
}
13071308
#endif
1309+
#if defined(WOLFSSL_HAVE_SLHDSA)
1310+
if (type == WC_PQC_SIG_TYPE_SLHDSA) {
1311+
devId = ((SlhDsaKey*) key)->devId;
1312+
}
1313+
#endif
13081314

13091315
return devId;
13101316
}
@@ -1454,7 +1460,7 @@ int wc_CryptoCb_PqcSignatureCheckPrivKey(void* key, int type,
14541460

14551461
return wc_CryptoCb_TranslateErrorCode(ret);
14561462
}
1457-
#endif /* HAVE_FALCON || HAVE_DILITHIUM */
1463+
#endif /* HAVE_FALCON || HAVE_DILITHIUM || WOLFSSL_HAVE_SLHDSA */
14581464

14591465
#ifndef NO_AES
14601466
#ifdef HAVE_AESGCM

wolfcrypt/src/wc_slhdsa.c

Lines changed: 194 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6557,9 +6557,14 @@ int wc_SlhDsaKey_Init(SlhDsaKey* key, enum SlhDsaParam param, void* heap,
65576557
/* Set heap hint to use with all allocations. */
65586558
key->heap = heap;
65596559
#ifdef WOLF_CRYPTO_CB
6560-
/* Set device id. */
6560+
/* Set device context and id. */
6561+
key->devCtx = NULL;
65616562
key->devId = devId;
65626563
#endif
6564+
#ifdef WOLF_PRIVATE_KEY_ID
6565+
key->idLen = 0;
6566+
key->labelLen = 0;
6567+
#endif
65636568

65646569
#ifdef WOLFSSL_SLHDSA_SHA2
65656570
if (SLHDSA_IS_SHA2(param)) {
@@ -6595,6 +6600,86 @@ int wc_SlhDsaKey_Init(SlhDsaKey* key, enum SlhDsaParam param, void* heap,
65956600
return ret;
65966601
}
65976602

6603+
#ifdef WOLF_PRIVATE_KEY_ID
6604+
/* Initialize an SLH-DSA key with a device key id.
6605+
*
6606+
* Mirrors wc_dilithium_init_id: initialize the key, then store an
6607+
* opaque device-side handle (id) of length len.
6608+
*
6609+
* @param [in] key SLH-DSA key.
6610+
* @param [in] param SLH-DSA parameter set to use.
6611+
* @param [in] id Device-side key handle bytes.
6612+
* @param [in] len Length of id in bytes.
6613+
* @param [in] heap Dynamic memory allocation hint.
6614+
* @param [in] devId Device Id.
6615+
* @return 0 on success.
6616+
* @return BAD_FUNC_ARG when key is NULL.
6617+
* @return BUFFER_E when len is negative or larger than SLHDSA_MAX_ID_LEN.
6618+
*/
6619+
int wc_SlhDsaKey_Init_id(SlhDsaKey* key, enum SlhDsaParam param,
6620+
const unsigned char* id, int len, void* heap, int devId)
6621+
{
6622+
int ret = 0;
6623+
6624+
if (key == NULL) {
6625+
ret = BAD_FUNC_ARG;
6626+
}
6627+
if ((ret == 0) && ((len < 0) || (len > SLHDSA_MAX_ID_LEN))) {
6628+
ret = BUFFER_E;
6629+
}
6630+
6631+
if (ret == 0) {
6632+
ret = wc_SlhDsaKey_Init(key, param, heap, devId);
6633+
}
6634+
if ((ret == 0) && (id != NULL) && (len != 0)) {
6635+
XMEMCPY(key->id, id, (size_t)len);
6636+
key->idLen = len;
6637+
}
6638+
6639+
return ret;
6640+
}
6641+
6642+
/* Initialize an SLH-DSA key with a device key label.
6643+
*
6644+
* Mirrors wc_dilithium_init_label.
6645+
*
6646+
* @param [in] key SLH-DSA key.
6647+
* @param [in] param SLH-DSA parameter set to use.
6648+
* @param [in] label NUL-terminated device-side key label.
6649+
* @param [in] heap Dynamic memory allocation hint.
6650+
* @param [in] devId Device Id.
6651+
* @return 0 on success.
6652+
* @return BAD_FUNC_ARG when key or label is NULL.
6653+
* @return BUFFER_E when label is empty or longer than SLHDSA_MAX_LABEL_LEN.
6654+
*/
6655+
int wc_SlhDsaKey_Init_label(SlhDsaKey* key, enum SlhDsaParam param,
6656+
const char* label, void* heap, int devId)
6657+
{
6658+
int ret = 0;
6659+
int labelLen = 0;
6660+
6661+
if ((key == NULL) || (label == NULL)) {
6662+
ret = BAD_FUNC_ARG;
6663+
}
6664+
if (ret == 0) {
6665+
labelLen = (int)XSTRLEN(label);
6666+
if ((labelLen == 0) || (labelLen > SLHDSA_MAX_LABEL_LEN)) {
6667+
ret = BUFFER_E;
6668+
}
6669+
}
6670+
6671+
if (ret == 0) {
6672+
ret = wc_SlhDsaKey_Init(key, param, heap, devId);
6673+
}
6674+
if (ret == 0) {
6675+
XMEMCPY(key->label, label, (size_t)labelLen);
6676+
key->labelLen = labelLen;
6677+
}
6678+
6679+
return ret;
6680+
}
6681+
#endif /* WOLF_PRIVATE_KEY_ID */
6682+
65986683
/* Free the SLH-DSA key.
65996684
*
66006685
* @param [in] key SLH-DSA key. Cannot be used after this call.
@@ -6603,6 +6688,15 @@ void wc_SlhDsaKey_Free(SlhDsaKey* key)
66036688
{
66046689
/* Check we have a valid key to free. */
66056690
if ((key != NULL) && (key->params != NULL)) {
6691+
#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_FREE)
6692+
if (key->devId != INVALID_DEVID) {
6693+
(void)wc_CryptoCb_Free(key->devId, WC_ALGO_TYPE_PK,
6694+
WC_PK_TYPE_PQC_SIG_KEYGEN,
6695+
WC_PQC_SIG_TYPE_SLHDSA,
6696+
(void*)key);
6697+
/* always continue to software cleanup */
6698+
}
6699+
#endif
66066700
/* Ensure the private key data is zeroized. */
66076701
ForceZero(key->sk, (size_t)key->params->n * 2);
66086702
#ifdef WOLFSSL_SLHDSA_SHA2
@@ -6641,6 +6735,18 @@ void wc_SlhDsaKey_Free(SlhDsaKey* key)
66416735
wc_Shake256_Free(&key->hash.shk.shake);
66426736
}
66436737
}
6738+
if (key != NULL) {
6739+
#ifdef WOLF_PRIVATE_KEY_ID
6740+
ForceZero(key->id, sizeof(key->id));
6741+
ForceZero(key->label, sizeof(key->label));
6742+
key->idLen = 0;
6743+
key->labelLen = 0;
6744+
#endif
6745+
#ifdef WOLF_CRYPTO_CB
6746+
key->devCtx = NULL;
6747+
key->devId = INVALID_DEVID;
6748+
#endif
6749+
}
66446750
}
66456751

66466752
/* Set the HashAddress based on message digest data.
@@ -6752,6 +6858,23 @@ int wc_SlhDsaKey_MakeKey(SlhDsaKey* key, WC_RNG* rng)
67526858
if ((key == NULL) || (key->params == NULL) || (rng == NULL)) {
67536859
ret = BAD_FUNC_ARG;
67546860
}
6861+
6862+
#ifdef WOLF_CRYPTO_CB
6863+
if (ret == 0) {
6864+
#ifndef WOLF_CRYPTO_CB_FIND
6865+
if (key->devId != INVALID_DEVID)
6866+
#endif
6867+
{
6868+
ret = wc_CryptoCb_MakePqcSignatureKey(rng,
6869+
WC_PQC_SIG_TYPE_SLHDSA, (int)key->params->param, key);
6870+
if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
6871+
return ret;
6872+
/* fall-through when unavailable */
6873+
ret = 0;
6874+
}
6875+
}
6876+
#endif
6877+
67556878
if (ret == 0) {
67566879
/* Steps 1-5: Generate the 3 random hashes. */
67576880
ret = wc_RNG_GenerateBlock(rng, key->sk, 3U * key->params->n);
@@ -7251,6 +7374,23 @@ int wc_SlhDsaKey_Sign(SlhDsaKey* key, const byte* ctx, byte ctxSz,
72517374
else if ((key->flags & WC_SLHDSA_FLAG_PRIVATE) == 0) {
72527375
ret = MISSING_KEY;
72537376
}
7377+
7378+
#ifdef WOLF_CRYPTO_CB
7379+
if (ret == 0) {
7380+
#ifndef WOLF_CRYPTO_CB_FIND
7381+
if (key->devId != INVALID_DEVID)
7382+
#endif
7383+
{
7384+
ret = wc_CryptoCb_PqcSign(msg, msgSz, sig, sigSz, ctx, ctxSz,
7385+
WC_HASH_TYPE_NONE, rng, WC_PQC_SIG_TYPE_SLHDSA, key);
7386+
if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
7387+
return ret;
7388+
/* fall-through when unavailable */
7389+
ret = 0;
7390+
}
7391+
}
7392+
#endif
7393+
72547394
if (ret == 0) {
72557395
/* Generate n bytes of random. */
72567396
ret = wc_RNG_GenerateBlock(rng, addRnd, key->params->n);
@@ -7418,6 +7558,24 @@ int wc_SlhDsaKey_Verify(SlhDsaKey* key, const byte* ctx, byte ctxSz,
74187558
else if ((key->flags & WC_SLHDSA_FLAG_PUBLIC) == 0) {
74197559
ret = MISSING_KEY;
74207560
}
7561+
7562+
#ifdef WOLF_CRYPTO_CB
7563+
if (ret == 0) {
7564+
#ifndef WOLF_CRYPTO_CB_FIND
7565+
if (key->devId != INVALID_DEVID)
7566+
#endif
7567+
{
7568+
int res = 0;
7569+
ret = wc_CryptoCb_PqcVerify(sig, sigSz, msg, msgSz, ctx, ctxSz,
7570+
WC_HASH_TYPE_NONE, &res, WC_PQC_SIG_TYPE_SLHDSA, key);
7571+
if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
7572+
return (ret == 0 && res == 1) ? 0 : SIG_VERIFY_E;
7573+
/* fall-through when unavailable */
7574+
ret = 0;
7575+
}
7576+
}
7577+
#endif
7578+
74217579
if (ret == 0) {
74227580
byte md[SLHDSA_MAX_MD];
74237581
byte n = key->params->n;
@@ -8048,6 +8206,23 @@ int wc_SlhDsaKey_SignHash(SlhDsaKey* key, const byte* ctx, byte ctxSz,
80488206
else if ((key->flags & WC_SLHDSA_FLAG_PRIVATE) == 0) {
80498207
ret = MISSING_KEY;
80508208
}
8209+
8210+
#ifdef WOLF_CRYPTO_CB
8211+
if (ret == 0) {
8212+
#ifndef WOLF_CRYPTO_CB_FIND
8213+
if (key->devId != INVALID_DEVID)
8214+
#endif
8215+
{
8216+
ret = wc_CryptoCb_PqcSign(msg, msgSz, sig, sigSz, ctx, ctxSz,
8217+
(word32)hashType, rng, WC_PQC_SIG_TYPE_SLHDSA, key);
8218+
if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
8219+
return ret;
8220+
/* fall-through when unavailable */
8221+
ret = 0;
8222+
}
8223+
}
8224+
#endif
8225+
80518226
if (ret == 0) {
80528227
/* Generate n bytes of random. */
80538228
ret = wc_RNG_GenerateBlock(rng, addRnd, key->params->n);
@@ -8147,6 +8322,24 @@ int wc_SlhDsaKey_VerifyHash(SlhDsaKey* key, const byte* ctx, byte ctxSz,
81478322
else if ((key->flags & WC_SLHDSA_FLAG_PUBLIC) == 0) {
81488323
ret = MISSING_KEY;
81498324
}
8325+
8326+
#ifdef WOLF_CRYPTO_CB
8327+
if (ret == 0) {
8328+
#ifndef WOLF_CRYPTO_CB_FIND
8329+
if (key->devId != INVALID_DEVID)
8330+
#endif
8331+
{
8332+
int res = 0;
8333+
ret = wc_CryptoCb_PqcVerify(sig, sigSz, msg, msgSz, ctx, ctxSz,
8334+
(word32)hashType, &res, WC_PQC_SIG_TYPE_SLHDSA, key);
8335+
if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
8336+
return (ret == 0 && res == 1) ? 0 : SIG_VERIFY_E;
8337+
/* fall-through when unavailable */
8338+
ret = 0;
8339+
}
8340+
}
8341+
#endif
8342+
81508343
if (ret == 0) {
81518344
/* Alg 24, Steps 4-19: Pre-hash message with hash algorithm specified.
81528345
*/

wolfssl/wolfcrypt/cryptocb.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@
8686
#if defined(HAVE_FALCON)
8787
#include <wolfssl/wolfcrypt/falcon.h>
8888
#endif
89+
#if defined(WOLFSSL_HAVE_SLHDSA)
90+
#include <wolfssl/wolfcrypt/wc_slhdsa.h>
91+
#endif
8992
#if defined(WOLFSSL_HAVE_LMS)
9093
#include <wolfssl/wolfcrypt/wc_lms.h>
9194
#endif
@@ -312,7 +315,8 @@ typedef struct wc_CryptoInfo {
312315
int type; /* enum wc_PqcKemType */
313316
} pqc_decaps;
314317
#endif
315-
#if defined(HAVE_FALCON) || defined(HAVE_DILITHIUM)
318+
#if defined(HAVE_FALCON) || defined(HAVE_DILITHIUM) || \
319+
defined(WOLFSSL_HAVE_SLHDSA)
316320
struct {
317321
WC_RNG* rng;
318322
int size;
@@ -775,7 +779,8 @@ WOLFSSL_LOCAL int wc_CryptoCb_PqcDecapsulate(const byte* ciphertext,
775779
int type, void* key);
776780
#endif /* WOLFSSL_HAVE_MLKEM */
777781

778-
#if defined(HAVE_FALCON) || defined(HAVE_DILITHIUM)
782+
#if defined(HAVE_FALCON) || defined(HAVE_DILITHIUM) || \
783+
defined(WOLFSSL_HAVE_SLHDSA)
779784
WOLFSSL_LOCAL int wc_CryptoCb_PqcSigGetDevId(int type, void* key);
780785

781786
WOLFSSL_LOCAL int wc_CryptoCb_MakePqcSignatureKey(WC_RNG* rng, int type,
@@ -791,7 +796,7 @@ WOLFSSL_LOCAL int wc_CryptoCb_PqcVerify(const byte* sig, word32 siglen,
791796

792797
WOLFSSL_LOCAL int wc_CryptoCb_PqcSignatureCheckPrivKey(void* key, int type,
793798
const byte* pubKey, word32 pubKeySz);
794-
#endif /* HAVE_FALCON || HAVE_DILITHIUM */
799+
#endif /* HAVE_FALCON || HAVE_DILITHIUM || WOLFSSL_HAVE_SLHDSA */
795800

796801
#ifndef NO_AES
797802
#ifdef HAVE_AESGCM

wolfssl/wolfcrypt/types.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1559,7 +1559,8 @@ enum wc_PkType {
15591559
#undef _WC_PK_TYPE_MAX
15601560
#define _WC_PK_TYPE_MAX WC_PK_TYPE_PQC_KEM_DECAPS
15611561
#endif
1562-
#if defined(HAVE_DILITHIUM) || defined(HAVE_FALCON)
1562+
#if defined(HAVE_DILITHIUM) || defined(HAVE_FALCON) || \
1563+
defined(WOLFSSL_HAVE_SLHDSA)
15631564
WC_PK_TYPE_PQC_SIG_KEYGEN = 21,
15641565
WC_PK_TYPE_PQC_SIG_SIGN = 22,
15651566
WC_PK_TYPE_PQC_SIG_VERIFY = 23,
@@ -1597,7 +1598,8 @@ enum wc_PkType {
15971598
};
15981599
#endif
15991600

1600-
#if defined(HAVE_DILITHIUM) || defined(HAVE_FALCON)
1601+
#if defined(HAVE_DILITHIUM) || defined(HAVE_FALCON) || \
1602+
defined(WOLFSSL_HAVE_SLHDSA)
16011603
/* Post quantum signature algorithms */
16021604
enum wc_PqcSignatureType {
16031605
WC_PQC_SIG_TYPE_NONE = 0,
@@ -1611,6 +1613,11 @@ enum wc_PkType {
16111613
WC_PQC_SIG_TYPE_FALCON = 2,
16121614
#undef _WC_PQC_SIG_TYPE_MAX
16131615
#define _WC_PQC_SIG_TYPE_MAX WC_PQC_SIG_TYPE_FALCON
1616+
#endif
1617+
#if defined(WOLFSSL_HAVE_SLHDSA)
1618+
WC_PQC_SIG_TYPE_SLHDSA = 3,
1619+
#undef _WC_PQC_SIG_TYPE_MAX
1620+
#define _WC_PQC_SIG_TYPE_MAX WC_PQC_SIG_TYPE_SLHDSA
16141621
#endif
16151622
WC_PQC_SIG_TYPE_MAX = _WC_PQC_SIG_TYPE_MAX
16161623
};

0 commit comments

Comments
 (0)