From 1f37cedc03e6742bbe098f94912091db8c65e688 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 12 May 2026 08:53:32 +0000 Subject: [PATCH] slhdsa: add WOLF_CRYPTO_CB and WOLF_PRIVATE_KEY_ID support Wires 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 adds 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; reject negative wc_HashType in SignHash / VerifyHash; scrub id/label/devCtx and NULL params on free for double-free / cryptocb-recursive-free safety. The SignHash / VerifyHash hooks pass (hash, hashSz, hashType) directly to the device, matching the prehash API as merged in master (PR #10450). test.c: - Route slhdsa_test through cryptocb_test by passing the global devId to wc_SlhDsaKey_Init in slhdsa_test_param (mirrors dilithium_test). - Extend myCryptoDevCb's WC_PK_TYPE_PQC_SIG_KEYGEN free dispatch with a WC_PQC_SIG_TYPE_SLHDSA arm. - Add slhdsa_id_label_test() covering Init_id / Init_label argument validation and id/label round-trip (gated on WOLF_PRIVATE_KEY_ID + one 128-bit param). --- wolfcrypt/src/cryptocb.c | 10 +- wolfcrypt/src/wc_slhdsa.c | 216 +++++++++++++++++++++++++++++++++- wolfcrypt/test/test.c | 131 ++++++++++++++++++++- wolfssl/wolfcrypt/cryptocb.h | 11 +- wolfssl/wolfcrypt/types.h | 11 +- wolfssl/wolfcrypt/wc_slhdsa.h | 23 ++++ 6 files changed, 389 insertions(+), 13 deletions(-) diff --git a/wolfcrypt/src/cryptocb.c b/wolfcrypt/src/cryptocb.c index 0036556ba96..5e2312c4974 100644 --- a/wolfcrypt/src/cryptocb.c +++ b/wolfcrypt/src/cryptocb.c @@ -1286,7 +1286,8 @@ int wc_CryptoCb_PqcDecapsulate(const byte* ciphertext, word32 ciphertextLen, } #endif /* WOLFSSL_HAVE_MLKEM */ -#if defined(HAVE_FALCON) || defined(HAVE_DILITHIUM) +#if defined(HAVE_FALCON) || defined(HAVE_DILITHIUM) || \ + defined(WOLFSSL_HAVE_SLHDSA) int wc_CryptoCb_PqcSigGetDevId(int type, void* key) { int devId = INVALID_DEVID; @@ -1305,6 +1306,11 @@ int wc_CryptoCb_PqcSigGetDevId(int type, void* key) devId = ((falcon_key*) key)->devId; } #endif +#if defined(WOLFSSL_HAVE_SLHDSA) + if (type == WC_PQC_SIG_TYPE_SLHDSA) { + devId = ((SlhDsaKey*) key)->devId; + } +#endif return devId; } @@ -1454,7 +1460,7 @@ int wc_CryptoCb_PqcSignatureCheckPrivKey(void* key, int type, return wc_CryptoCb_TranslateErrorCode(ret); } -#endif /* HAVE_FALCON || HAVE_DILITHIUM */ +#endif /* HAVE_FALCON || HAVE_DILITHIUM || WOLFSSL_HAVE_SLHDSA */ #ifndef NO_AES #ifdef HAVE_AESGCM diff --git a/wolfcrypt/src/wc_slhdsa.c b/wolfcrypt/src/wc_slhdsa.c index eb4a022113f..7cf166b255a 100644 --- a/wolfcrypt/src/wc_slhdsa.c +++ b/wolfcrypt/src/wc_slhdsa.c @@ -6557,9 +6557,14 @@ int wc_SlhDsaKey_Init(SlhDsaKey* key, enum SlhDsaParam param, void* heap, /* Set heap hint to use with all allocations. */ key->heap = heap; #ifdef WOLF_CRYPTO_CB - /* Set device id. */ + /* Set device context and id. */ + key->devCtx = NULL; key->devId = devId; #endif + #ifdef WOLF_PRIVATE_KEY_ID + key->idLen = 0; + key->labelLen = 0; + #endif #ifdef WOLFSSL_SLHDSA_SHA2 if (SLHDSA_IS_SHA2(param)) { @@ -6595,14 +6600,106 @@ int wc_SlhDsaKey_Init(SlhDsaKey* key, enum SlhDsaParam param, void* heap, return ret; } +#ifdef WOLF_PRIVATE_KEY_ID +/* Initialize an SLH-DSA key with a device key id. + * + * @param [in] key SLH-DSA key. + * @param [in] param SLH-DSA parameter set to use. + * @param [in] id Device-side key handle bytes. + * @param [in] len Length of id in bytes. + * @param [in] heap Dynamic memory allocation hint. + * @param [in] devId Device Id. + * @return 0 on success. + * @return BAD_FUNC_ARG when key is NULL or when id is NULL with len > 0. + * @return BUFFER_E when len is negative or larger than SLHDSA_MAX_ID_LEN. + */ +int wc_SlhDsaKey_Init_id(SlhDsaKey* key, enum SlhDsaParam param, + const unsigned char* id, int len, void* heap, int devId) +{ + int ret = 0; + + if (key == NULL) { + ret = BAD_FUNC_ARG; + } + /* Reject id == NULL with len > 0. */ + if ((ret == 0) && (id == NULL) && (len > 0)) { + ret = BAD_FUNC_ARG; + } + if ((ret == 0) && ((len < 0) || (len > SLHDSA_MAX_ID_LEN))) { + ret = BUFFER_E; + } + + if (ret == 0) { + ret = wc_SlhDsaKey_Init(key, param, heap, devId); + } + if ((ret == 0) && (id != NULL) && (len > 0)) { + XMEMCPY(key->id, id, (size_t)len); + key->idLen = len; + } + + return ret; +} + +/* Initialize an SLH-DSA key with a device key label. + * + * Label length is taken via XSTRLEN; embedded NULs terminate the label. + * + * @param [in] key SLH-DSA key. + * @param [in] param SLH-DSA parameter set to use. + * @param [in] label NUL-terminated device-side key label. + * @param [in] heap Dynamic memory allocation hint. + * @param [in] devId Device Id. + * @return 0 on success. + * @return BAD_FUNC_ARG when key or label is NULL. + * @return BUFFER_E when label is empty or longer than SLHDSA_MAX_LABEL_LEN. + */ +int wc_SlhDsaKey_Init_label(SlhDsaKey* key, enum SlhDsaParam param, + const char* label, void* heap, int devId) +{ + int ret = 0; + int labelLen = 0; + + if ((key == NULL) || (label == NULL)) { + ret = BAD_FUNC_ARG; + } + if (ret == 0) { + labelLen = (int)XSTRLEN(label); + if ((labelLen == 0) || (labelLen > SLHDSA_MAX_LABEL_LEN)) { + ret = BUFFER_E; + } + } + + if (ret == 0) { + ret = wc_SlhDsaKey_Init(key, param, heap, devId); + } + if (ret == 0) { + XMEMCPY(key->label, label, (size_t)labelLen); + key->labelLen = labelLen; + } + + return ret; +} +#endif /* WOLF_PRIVATE_KEY_ID */ + /* Free the SLH-DSA key. * * @param [in] key SLH-DSA key. Cannot be used after this call. */ void wc_SlhDsaKey_Free(SlhDsaKey* key) { - /* Check we have a valid key to free. */ - if ((key != NULL) && (key->params != NULL)) { + if (key == NULL) + return; + +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_FREE) + if ((key->params != NULL) && (key->devId != INVALID_DEVID)) { + (void)wc_CryptoCb_Free(key->devId, WC_ALGO_TYPE_PK, + WC_PK_TYPE_PQC_SIG_KEYGEN, + WC_PQC_SIG_TYPE_SLHDSA, + (void*)key); + } +#endif + + if (key->params != NULL) { /* Ensure the private key data is zeroized. */ ForceZero(key->sk, (size_t)key->params->n * 2); #ifdef WOLFSSL_SLHDSA_SHA2 @@ -6641,6 +6738,17 @@ void wc_SlhDsaKey_Free(SlhDsaKey* key) wc_Shake256_Free(&key->hash.shk.shake); } } + +#ifdef WOLF_PRIVATE_KEY_ID + key->idLen = 0; + key->labelLen = 0; +#endif +#ifdef WOLF_CRYPTO_CB + key->devCtx = NULL; + key->devId = INVALID_DEVID; +#endif + /* Marks the key freed; subsequent Frees become no-ops. */ + key->params = NULL; } /* Set the HashAddress based on message digest data. @@ -6752,6 +6860,24 @@ int wc_SlhDsaKey_MakeKey(SlhDsaKey* key, WC_RNG* rng) if ((key == NULL) || (key->params == NULL) || (rng == NULL)) { ret = BAD_FUNC_ARG; } + +#ifdef WOLF_CRYPTO_CB + if (ret == 0) { + #ifndef WOLF_CRYPTO_CB_FIND + if (key->devId != INVALID_DEVID) + #endif + { + /* size is the SlhDsaParam enum (S/F variants are distinct). */ + ret = wc_CryptoCb_MakePqcSignatureKey(rng, + WC_PQC_SIG_TYPE_SLHDSA, (int)key->params->param, key); + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) + return ret; + /* fall-through when unavailable */ + ret = 0; + } + } +#endif + if (ret == 0) { /* Steps 1-5: Generate the 3 random hashes. */ ret = wc_RNG_GenerateBlock(rng, key->sk, 3U * key->params->n); @@ -7251,6 +7377,23 @@ int wc_SlhDsaKey_Sign(SlhDsaKey* key, const byte* ctx, byte ctxSz, else if ((key->flags & WC_SLHDSA_FLAG_PRIVATE) == 0) { ret = MISSING_KEY; } + +#ifdef WOLF_CRYPTO_CB + if (ret == 0) { + #ifndef WOLF_CRYPTO_CB_FIND + if (key->devId != INVALID_DEVID) + #endif + { + ret = wc_CryptoCb_PqcSign(msg, msgSz, sig, sigSz, ctx, ctxSz, + WC_HASH_TYPE_NONE, rng, WC_PQC_SIG_TYPE_SLHDSA, key); + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) + return ret; + /* fall-through when unavailable */ + ret = 0; + } + } +#endif + if (ret == 0) { /* Generate n bytes of random. */ ret = wc_RNG_GenerateBlock(rng, addRnd, key->params->n); @@ -7459,6 +7602,27 @@ int wc_SlhDsaKey_Verify(SlhDsaKey* key, const byte* ctx, byte ctxSz, else if ((key->flags & WC_SLHDSA_FLAG_PUBLIC) == 0) { ret = MISSING_KEY; } + +#ifdef WOLF_CRYPTO_CB + if (ret == 0) { + #ifndef WOLF_CRYPTO_CB_FIND + if (key->devId != INVALID_DEVID) + #endif + { + int res = 0; + ret = wc_CryptoCb_PqcVerify(sig, sigSz, msg, msgSz, ctx, ctxSz, + WC_HASH_TYPE_NONE, &res, WC_PQC_SIG_TYPE_SLHDSA, key); + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) { + if (ret != 0) + return ret; + return (res == 1) ? 0 : SIG_VERIFY_E; + } + /* fall-through when unavailable */ + ret = 0; + } + } +#endif + if (ret == 0) { byte md[SLHDSA_MAX_MD]; byte n = key->params->n; @@ -8119,6 +8283,27 @@ int wc_SlhDsaKey_SignHash(SlhDsaKey* key, const byte* ctx, byte ctxSz, else if ((key->flags & WC_SLHDSA_FLAG_PRIVATE) == 0) { ret = MISSING_KEY; } + /* Reject negative wc_HashType before any cast/dispatch. */ + else if ((int)hashType < 0) { + ret = BAD_FUNC_ARG; + } + +#ifdef WOLF_CRYPTO_CB + if (ret == 0) { + #ifndef WOLF_CRYPTO_CB_FIND + if (key->devId != INVALID_DEVID) + #endif + { + ret = wc_CryptoCb_PqcSign(hash, hashSz, sig, sigSz, ctx, ctxSz, + (word32)hashType, rng, WC_PQC_SIG_TYPE_SLHDSA, key); + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) + return ret; + /* fall-through when unavailable */ + ret = 0; + } + } +#endif + if (ret == 0) { /* Generate n bytes of random. */ ret = wc_RNG_GenerateBlock(rng, addRnd, key->params->n); @@ -8221,6 +8406,31 @@ int wc_SlhDsaKey_VerifyHash(SlhDsaKey* key, const byte* ctx, byte ctxSz, else if ((key->flags & WC_SLHDSA_FLAG_PUBLIC) == 0) { ret = MISSING_KEY; } + /* Reject negative wc_HashType before any cast/dispatch. */ + else if ((int)hashType < 0) { + ret = BAD_FUNC_ARG; + } + +#ifdef WOLF_CRYPTO_CB + if (ret == 0) { + #ifndef WOLF_CRYPTO_CB_FIND + if (key->devId != INVALID_DEVID) + #endif + { + int res = 0; + ret = wc_CryptoCb_PqcVerify(sig, sigSz, hash, hashSz, ctx, ctxSz, + (word32)hashType, &res, WC_PQC_SIG_TYPE_SLHDSA, key); + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) { + if (ret != 0) + return ret; + return (res == 1) ? 0 : SIG_VERIFY_E; + } + /* fall-through when unavailable */ + ret = 0; + } + } +#endif + if (ret == 0) { /* Alg 24, Steps 4-19: Validate caller-supplied pre-hashed digest length * and select OID for the chosen hash algorithm. */ diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index ed33d6ffb46..f5201771861 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -54684,7 +54684,7 @@ static wc_test_ret_t slhdsa_test_param(enum SlhDsaParam param) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); } - ret = wc_SlhDsaKey_Init(key, param, NULL, INVALID_DEVID); + ret = wc_SlhDsaKey_Init(key, param, NULL, devId); if (ret != 0) { ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); } @@ -54707,7 +54707,7 @@ static wc_test_ret_t slhdsa_test_param(enum SlhDsaParam param) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); } - ret = wc_SlhDsaKey_Init(key_vfy, param, NULL, INVALID_DEVID); + ret = wc_SlhDsaKey_Init(key_vfy, param, NULL, devId); if (ret != 0) { ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); } @@ -54848,6 +54848,108 @@ static wc_test_ret_t slhdsa_test_param(enum SlhDsaParam param) #define SLHDSA_TEST_HAVE_ANY_PARAM #endif +#if defined(WOLF_PRIVATE_KEY_ID) && \ + (defined(WOLFSSL_SLHDSA_PARAM_128S) || defined(WOLFSSL_SLHDSA_PARAM_128F)) +/* Exercise wc_SlhDsaKey_Init_id / _Init_label argument validation and + * id/label storage round-trip. Independent of any cryptocb device. */ +static wc_test_ret_t slhdsa_id_label_test(void) +{ + wc_test_ret_t ret; + SlhDsaKey key; + static const unsigned char id[] = { + 0xa1, 0xb2, 0xc3, 0xd4, 0xe5, 0xf6, 0x07, 0x18, + 0x29, 0x3a, 0x4b, 0x5c, 0x6d, 0x7e, 0x8f, 0x90 + }; + static const char label[] = "slh-dsa-test-label"; + enum SlhDsaParam param = +#ifdef WOLFSSL_SLHDSA_PARAM_128S + SLHDSA_SHAKE128S; +#else + SLHDSA_SHAKE128F; +#endif + + /* Zero the stack key so rejection-path tests below don't read + * uninitialized fields if a future Init refactor inspects key state + * before zeroizing it. */ + XMEMSET(&key, 0, sizeof(key)); + + /* NULL key rejected. */ + ret = wc_SlhDsaKey_Init_id(NULL, param, id, (int)sizeof(id), HEAP_HINT, + INVALID_DEVID); + if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + return WC_TEST_RET_ENC_EC(ret); + + /* (id == NULL, len > 0) is the silent-contradiction case the original + * review flagged; must be rejected. */ + ret = wc_SlhDsaKey_Init_id(&key, param, NULL, 8, HEAP_HINT, INVALID_DEVID); + if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + return WC_TEST_RET_ENC_EC(ret); + + /* Length over the cap rejected with BUFFER_E. */ + ret = wc_SlhDsaKey_Init_id(&key, param, id, SLHDSA_MAX_ID_LEN + 1, + HEAP_HINT, INVALID_DEVID); + if (ret != WC_NO_ERR_TRACE(BUFFER_E)) + return WC_TEST_RET_ENC_EC(ret); + + /* Negative length rejected. */ + ret = wc_SlhDsaKey_Init_id(&key, param, id, -1, HEAP_HINT, INVALID_DEVID); + if (ret != WC_NO_ERR_TRACE(BUFFER_E)) + return WC_TEST_RET_ENC_EC(ret); + + /* Successful init copies the id and stores its length. */ + ret = wc_SlhDsaKey_Init_id(&key, param, id, (int)sizeof(id), HEAP_HINT, + INVALID_DEVID); + if (ret != 0) + return WC_TEST_RET_ENC_EC(ret); + if (key.idLen != (int)sizeof(id)) + ret = WC_TEST_RET_ENC_NC; + if ((ret == 0) && (XMEMCMP(key.id, id, sizeof(id)) != 0)) + ret = WC_TEST_RET_ENC_NC; + wc_SlhDsaKey_Free(&key); + if (ret != 0) + return ret; + + /* (id != NULL, len == 0) is accepted as a no-op. */ + ret = wc_SlhDsaKey_Init_id(&key, param, id, 0, HEAP_HINT, INVALID_DEVID); + if (ret != 0) + return WC_TEST_RET_ENC_EC(ret); + if (key.idLen != 0) + ret = WC_TEST_RET_ENC_NC; + wc_SlhDsaKey_Free(&key); + if (ret != 0) + return ret; + + /* Init_label: NULL label / NULL key rejected. */ + ret = wc_SlhDsaKey_Init_label(NULL, param, label, HEAP_HINT, + INVALID_DEVID); + if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + return WC_TEST_RET_ENC_EC(ret); + ret = wc_SlhDsaKey_Init_label(&key, param, NULL, HEAP_HINT, + INVALID_DEVID); + if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + return WC_TEST_RET_ENC_EC(ret); + + /* Empty label is rejected. */ + ret = wc_SlhDsaKey_Init_label(&key, param, "", HEAP_HINT, INVALID_DEVID); + if (ret != WC_NO_ERR_TRACE(BUFFER_E)) + return WC_TEST_RET_ENC_EC(ret); + + /* Successful init copies the label and stores its length. */ + ret = wc_SlhDsaKey_Init_label(&key, param, label, HEAP_HINT, + INVALID_DEVID); + if (ret != 0) + return WC_TEST_RET_ENC_EC(ret); + if (key.labelLen != (int)XSTRLEN(label)) + ret = WC_TEST_RET_ENC_NC; + if ((ret == 0) && + (XMEMCMP(key.label, label, (size_t)key.labelLen) != 0)) + ret = WC_TEST_RET_ENC_NC; + wc_SlhDsaKey_Free(&key); + + return ret; +} +#endif /* WOLF_PRIVATE_KEY_ID && (SHAKE128S || SHAKE128F) */ + wc_test_ret_t slhdsa_test(void) { int ret = 0; @@ -56657,6 +56759,15 @@ wc_test_ret_t slhdsa_test(void) } #endif +#if defined(WOLF_PRIVATE_KEY_ID) && \ + (defined(WOLFSSL_SLHDSA_PARAM_128S) || defined(WOLFSSL_SLHDSA_PARAM_128F)) + ret = slhdsa_id_label_test(); + if (ret != 0) { + wc_test_render_error_message("SLHDSA_ID_LABEL", 0); + goto out; + } +#endif + #endif /* !WOLFSSL_SLHDSA_VERIFY_ONLY */ #ifdef SLHDSA_TEST_HAVE_ANY_PARAM @@ -69938,15 +70049,25 @@ static int myCryptoDevCb(int devIdArg, wc_CryptoInfo* info, void* ctx) break; } #endif -#ifdef HAVE_DILITHIUM +#if defined(HAVE_DILITHIUM) || defined(WOLFSSL_HAVE_SLHDSA) case WC_PK_TYPE_PQC_SIG_KEYGEN: { + #ifdef HAVE_DILITHIUM if (info->free.subType == WC_PQC_SIG_TYPE_DILITHIUM) { dilithium_key* dil = (dilithium_key*)info->free.obj; dil->devId = INVALID_DEVID; wc_dilithium_free(dil); ret = 0; } + #endif + #ifdef WOLFSSL_HAVE_SLHDSA + if (info->free.subType == WC_PQC_SIG_TYPE_SLHDSA) { + SlhDsaKey* slh = (SlhDsaKey*)info->free.obj; + slh->devId = INVALID_DEVID; + wc_SlhDsaKey_Free(slh); + ret = 0; + } + #endif break; } #endif @@ -70601,6 +70722,10 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cryptocb_test(void) if (ret == 0) ret = dilithium_test(); #endif +#ifdef WOLFSSL_HAVE_SLHDSA + if (ret == 0) + ret = slhdsa_test(); +#endif #if defined(WOLFSSL_HAVE_XMSS) && !defined(WOLFSSL_XMSS_VERIFY_ONLY) if (ret == 0) ret = xmss_test(); diff --git a/wolfssl/wolfcrypt/cryptocb.h b/wolfssl/wolfcrypt/cryptocb.h index eee9e231823..c50fb823f43 100644 --- a/wolfssl/wolfcrypt/cryptocb.h +++ b/wolfssl/wolfcrypt/cryptocb.h @@ -86,6 +86,9 @@ #if defined(HAVE_FALCON) #include #endif +#if defined(WOLFSSL_HAVE_SLHDSA) + #include +#endif #if defined(WOLFSSL_HAVE_LMS) #include #endif @@ -312,7 +315,8 @@ typedef struct wc_CryptoInfo { int type; /* enum wc_PqcKemType */ } pqc_decaps; #endif - #if defined(HAVE_FALCON) || defined(HAVE_DILITHIUM) + #if defined(HAVE_FALCON) || defined(HAVE_DILITHIUM) || \ + defined(WOLFSSL_HAVE_SLHDSA) struct { WC_RNG* rng; int size; @@ -775,7 +779,8 @@ WOLFSSL_LOCAL int wc_CryptoCb_PqcDecapsulate(const byte* ciphertext, int type, void* key); #endif /* WOLFSSL_HAVE_MLKEM */ -#if defined(HAVE_FALCON) || defined(HAVE_DILITHIUM) +#if defined(HAVE_FALCON) || defined(HAVE_DILITHIUM) || \ + defined(WOLFSSL_HAVE_SLHDSA) WOLFSSL_LOCAL int wc_CryptoCb_PqcSigGetDevId(int type, void* key); 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, WOLFSSL_LOCAL int wc_CryptoCb_PqcSignatureCheckPrivKey(void* key, int type, const byte* pubKey, word32 pubKeySz); -#endif /* HAVE_FALCON || HAVE_DILITHIUM */ +#endif /* HAVE_FALCON || HAVE_DILITHIUM || WOLFSSL_HAVE_SLHDSA */ #ifndef NO_AES #ifdef HAVE_AESGCM diff --git a/wolfssl/wolfcrypt/types.h b/wolfssl/wolfcrypt/types.h index da5a680dbcb..1b787ccf737 100644 --- a/wolfssl/wolfcrypt/types.h +++ b/wolfssl/wolfcrypt/types.h @@ -1559,7 +1559,8 @@ enum wc_PkType { #undef _WC_PK_TYPE_MAX #define _WC_PK_TYPE_MAX WC_PK_TYPE_PQC_KEM_DECAPS #endif -#if defined(HAVE_DILITHIUM) || defined(HAVE_FALCON) +#if defined(HAVE_DILITHIUM) || defined(HAVE_FALCON) || \ + defined(WOLFSSL_HAVE_SLHDSA) WC_PK_TYPE_PQC_SIG_KEYGEN = 21, WC_PK_TYPE_PQC_SIG_SIGN = 22, WC_PK_TYPE_PQC_SIG_VERIFY = 23, @@ -1597,7 +1598,8 @@ enum wc_PkType { }; #endif -#if defined(HAVE_DILITHIUM) || defined(HAVE_FALCON) +#if defined(HAVE_DILITHIUM) || defined(HAVE_FALCON) || \ + defined(WOLFSSL_HAVE_SLHDSA) /* Post quantum signature algorithms */ enum wc_PqcSignatureType { WC_PQC_SIG_TYPE_NONE = 0, @@ -1611,6 +1613,11 @@ enum wc_PkType { WC_PQC_SIG_TYPE_FALCON = 2, #undef _WC_PQC_SIG_TYPE_MAX #define _WC_PQC_SIG_TYPE_MAX WC_PQC_SIG_TYPE_FALCON + #endif + #if defined(WOLFSSL_HAVE_SLHDSA) + WC_PQC_SIG_TYPE_SLHDSA = 3, + #undef _WC_PQC_SIG_TYPE_MAX + #define _WC_PQC_SIG_TYPE_MAX WC_PQC_SIG_TYPE_SLHDSA #endif WC_PQC_SIG_TYPE_MAX = _WC_PQC_SIG_TYPE_MAX }; diff --git a/wolfssl/wolfcrypt/wc_slhdsa.h b/wolfssl/wolfcrypt/wc_slhdsa.h index 323731334ba..5e3e9eb11b5 100644 --- a/wolfssl/wolfcrypt/wc_slhdsa.h +++ b/wolfssl/wolfcrypt/wc_slhdsa.h @@ -24,6 +24,10 @@ #include +#ifdef WOLF_CRYPTO_CB + #include +#endif + #if FIPS_VERSION3_GE(7,0,0) #include #endif @@ -591,6 +595,11 @@ typedef struct SlhDsaParameters { #define WC_SLHDSA_FLAG_BOTH_KEYS (WC_SLHDSA_FLAG_PRIVATE | \ WC_SLHDSA_FLAG_PUBLIC) +#ifdef WOLF_PRIVATE_KEY_ID +#define SLHDSA_MAX_ID_LEN 32 +#define SLHDSA_MAX_LABEL_LEN 32 +#endif + /* SLH-DSA key data and state. */ typedef struct SlhDsaKey { /* Parameters. */ @@ -600,9 +609,17 @@ typedef struct SlhDsaKey { /* Dynamic memory hint. */ void* heap; #ifdef WOLF_CRYPTO_CB + /* Device context (opaque, owned by the registered callback). */ + void* devCtx; /* Device Identifier. */ int devId; #endif +#ifdef WOLF_PRIVATE_KEY_ID + byte id[SLHDSA_MAX_ID_LEN]; + int idLen; + char label[SLHDSA_MAX_LABEL_LEN]; + int labelLen; +#endif /* sk_seed | sk_prf | pk_seed, pk_root */ byte sk[32 * 4]; @@ -641,6 +658,12 @@ typedef struct SlhDsaKey { WOLFSSL_API int wc_SlhDsaKey_Init(SlhDsaKey* key, enum SlhDsaParam param, void* heap, int devId); +#ifdef WOLF_PRIVATE_KEY_ID +WOLFSSL_API int wc_SlhDsaKey_Init_id(SlhDsaKey* key, enum SlhDsaParam param, + const unsigned char* id, int len, void* heap, int devId); +WOLFSSL_API int wc_SlhDsaKey_Init_label(SlhDsaKey* key, enum SlhDsaParam param, + const char* label, void* heap, int devId); +#endif WOLFSSL_API void wc_SlhDsaKey_Free(SlhDsaKey* key); #ifndef WOLFSSL_SLHDSA_VERIFY_ONLY