mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-07-05 15:00:49 +02:00
Merge pull request #10380 from padelsbach/lms-xmss
Add crypto callbacks for LMS and XMSS
This commit is contained in:
@@ -1017,6 +1017,154 @@ int wc_CryptoCb_Ed25519Verify(const byte* sig, word32 sigLen,
|
||||
}
|
||||
#endif /* HAVE_ED25519 */
|
||||
|
||||
#if defined(WOLFSSL_HAVE_LMS) || defined(WOLFSSL_HAVE_XMSS)
|
||||
int wc_CryptoCb_PqcStatefulSigGetDevId(int type, void* key)
|
||||
{
|
||||
int devId = INVALID_DEVID;
|
||||
|
||||
if (key == NULL)
|
||||
return devId;
|
||||
|
||||
#if defined(WOLFSSL_HAVE_LMS)
|
||||
if (type == WC_PQC_STATEFUL_SIG_TYPE_LMS) {
|
||||
devId = ((LmsKey*)key)->devId;
|
||||
}
|
||||
#endif
|
||||
#if defined(WOLFSSL_HAVE_XMSS)
|
||||
if (type == WC_PQC_STATEFUL_SIG_TYPE_XMSS) {
|
||||
devId = ((XmssKey*)key)->devId;
|
||||
}
|
||||
#endif
|
||||
|
||||
return devId;
|
||||
}
|
||||
|
||||
int wc_CryptoCb_PqcStatefulSigKeyGen(int type, void* key, WC_RNG* rng)
|
||||
{
|
||||
int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE);
|
||||
int devId = INVALID_DEVID;
|
||||
CryptoCb* dev;
|
||||
|
||||
if (key == NULL)
|
||||
return ret;
|
||||
|
||||
devId = wc_CryptoCb_PqcStatefulSigGetDevId(type, key);
|
||||
if (devId == INVALID_DEVID)
|
||||
return ret;
|
||||
|
||||
dev = wc_CryptoCb_FindDevice(devId, WC_ALGO_TYPE_PK);
|
||||
if (dev && dev->cb) {
|
||||
wc_CryptoInfo cryptoInfo;
|
||||
XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo));
|
||||
cryptoInfo.algo_type = WC_ALGO_TYPE_PK;
|
||||
cryptoInfo.pk.type = WC_PK_TYPE_PQC_STATEFUL_SIG_KEYGEN;
|
||||
cryptoInfo.pk.pqc_stateful_sig_kg.rng = rng;
|
||||
cryptoInfo.pk.pqc_stateful_sig_kg.key = key;
|
||||
cryptoInfo.pk.pqc_stateful_sig_kg.type = type;
|
||||
|
||||
ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx);
|
||||
}
|
||||
|
||||
return wc_CryptoCb_TranslateErrorCode(ret);
|
||||
}
|
||||
|
||||
int wc_CryptoCb_PqcStatefulSigSign(const byte* msg, word32 msgSz, byte* out,
|
||||
word32* outSz, int type, void* key)
|
||||
{
|
||||
int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE);
|
||||
int devId = INVALID_DEVID;
|
||||
CryptoCb* dev;
|
||||
|
||||
if (key == NULL)
|
||||
return ret;
|
||||
|
||||
devId = wc_CryptoCb_PqcStatefulSigGetDevId(type, key);
|
||||
if (devId == INVALID_DEVID)
|
||||
return ret;
|
||||
|
||||
dev = wc_CryptoCb_FindDevice(devId, WC_ALGO_TYPE_PK);
|
||||
if (dev && dev->cb) {
|
||||
wc_CryptoInfo cryptoInfo;
|
||||
XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo));
|
||||
cryptoInfo.algo_type = WC_ALGO_TYPE_PK;
|
||||
cryptoInfo.pk.type = WC_PK_TYPE_PQC_STATEFUL_SIG_SIGN;
|
||||
cryptoInfo.pk.pqc_stateful_sig_sign.msg = msg;
|
||||
cryptoInfo.pk.pqc_stateful_sig_sign.msgSz = msgSz;
|
||||
cryptoInfo.pk.pqc_stateful_sig_sign.out = out;
|
||||
cryptoInfo.pk.pqc_stateful_sig_sign.outSz = outSz;
|
||||
cryptoInfo.pk.pqc_stateful_sig_sign.key = key;
|
||||
cryptoInfo.pk.pqc_stateful_sig_sign.type = type;
|
||||
|
||||
ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx);
|
||||
}
|
||||
|
||||
return wc_CryptoCb_TranslateErrorCode(ret);
|
||||
}
|
||||
|
||||
int wc_CryptoCb_PqcStatefulSigVerify(const byte* sig, word32 sigSz,
|
||||
const byte* msg, word32 msgSz, int* res, int type, void* key)
|
||||
{
|
||||
int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE);
|
||||
int devId = INVALID_DEVID;
|
||||
CryptoCb* dev;
|
||||
|
||||
if (key == NULL)
|
||||
return ret;
|
||||
|
||||
devId = wc_CryptoCb_PqcStatefulSigGetDevId(type, key);
|
||||
if (devId == INVALID_DEVID)
|
||||
return ret;
|
||||
|
||||
dev = wc_CryptoCb_FindDevice(devId, WC_ALGO_TYPE_PK);
|
||||
if (dev && dev->cb) {
|
||||
wc_CryptoInfo cryptoInfo;
|
||||
XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo));
|
||||
cryptoInfo.algo_type = WC_ALGO_TYPE_PK;
|
||||
cryptoInfo.pk.type = WC_PK_TYPE_PQC_STATEFUL_SIG_VERIFY;
|
||||
cryptoInfo.pk.pqc_stateful_sig_verify.sig = sig;
|
||||
cryptoInfo.pk.pqc_stateful_sig_verify.sigSz = sigSz;
|
||||
cryptoInfo.pk.pqc_stateful_sig_verify.msg = msg;
|
||||
cryptoInfo.pk.pqc_stateful_sig_verify.msgSz = msgSz;
|
||||
cryptoInfo.pk.pqc_stateful_sig_verify.res = res;
|
||||
cryptoInfo.pk.pqc_stateful_sig_verify.key = key;
|
||||
cryptoInfo.pk.pqc_stateful_sig_verify.type = type;
|
||||
|
||||
ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx);
|
||||
}
|
||||
|
||||
return wc_CryptoCb_TranslateErrorCode(ret);
|
||||
}
|
||||
|
||||
int wc_CryptoCb_PqcStatefulSigSigsLeft(int type, void* key, word32* sigsLeft)
|
||||
{
|
||||
int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE);
|
||||
int devId = INVALID_DEVID;
|
||||
CryptoCb* dev;
|
||||
|
||||
if (key == NULL)
|
||||
return ret;
|
||||
|
||||
devId = wc_CryptoCb_PqcStatefulSigGetDevId(type, key);
|
||||
if (devId == INVALID_DEVID)
|
||||
return ret;
|
||||
|
||||
dev = wc_CryptoCb_FindDevice(devId, WC_ALGO_TYPE_PK);
|
||||
if (dev && dev->cb) {
|
||||
wc_CryptoInfo cryptoInfo;
|
||||
XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo));
|
||||
cryptoInfo.algo_type = WC_ALGO_TYPE_PK;
|
||||
cryptoInfo.pk.type = WC_PK_TYPE_PQC_STATEFUL_SIG_SIGS_LEFT;
|
||||
cryptoInfo.pk.pqc_stateful_sig_sigs_left.key = key;
|
||||
cryptoInfo.pk.pqc_stateful_sig_sigs_left.sigsLeft = sigsLeft;
|
||||
cryptoInfo.pk.pqc_stateful_sig_sigs_left.type = type;
|
||||
|
||||
ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx);
|
||||
}
|
||||
|
||||
return wc_CryptoCb_TranslateErrorCode(ret);
|
||||
}
|
||||
#endif /* WOLFSSL_HAVE_LMS || WOLFSSL_HAVE_XMSS */
|
||||
|
||||
#if defined(WOLFSSL_HAVE_MLKEM)
|
||||
int wc_CryptoCb_PqcKemGetDevId(int type, void* key)
|
||||
{
|
||||
|
||||
+208
-24
@@ -28,6 +28,7 @@
|
||||
#define FIPS_NO_WRAPPERS
|
||||
#endif
|
||||
#include <wolfssl/wolfcrypt/wc_lms.h>
|
||||
#include <wolfssl/wolfcrypt/hash.h>
|
||||
|
||||
#ifdef NO_INLINE
|
||||
#include <wolfssl/wolfcrypt/misc.h>
|
||||
@@ -36,6 +37,10 @@
|
||||
#include <wolfcrypt/src/misc.c>
|
||||
#endif
|
||||
|
||||
#ifdef WOLF_CRYPTO_CB
|
||||
#include <wolfssl/wolfcrypt/cryptocb.h>
|
||||
#endif
|
||||
|
||||
|
||||
/* Calculate u. Appendix B. Works for w of 1, 2, 4, or 8.
|
||||
*
|
||||
@@ -642,6 +647,72 @@ int wc_LmsKey_Init(LmsKey* key, void* heap, int devId)
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef WOLF_PRIVATE_KEY_ID
|
||||
/* Initialize an LmsKey and bind it to a device-side key identifier.
|
||||
*
|
||||
* @param [in,out] key LmsKey to initialize.
|
||||
* @param [in] id Identifier bytes (may be NULL when len is 0).
|
||||
* @param [in] len Length of id; must be in [0, LMS_MAX_ID_LEN].
|
||||
* @param [in] heap Heap hint forwarded to wc_LmsKey_Init.
|
||||
* @param [in] devId Device identifier.
|
||||
*
|
||||
* @return 0 on success.
|
||||
* @return BAD_FUNC_ARG when key is NULL.
|
||||
* @return BUFFER_E when len is negative or exceeds LMS_MAX_ID_LEN.
|
||||
*/
|
||||
int wc_LmsKey_InitId(LmsKey* key, const unsigned char* id, int len, void* heap,
|
||||
int devId)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (key == NULL)
|
||||
ret = BAD_FUNC_ARG;
|
||||
if (ret == 0 && (len < 0 || len > LMS_MAX_ID_LEN))
|
||||
ret = BUFFER_E;
|
||||
if (ret == 0)
|
||||
ret = wc_LmsKey_Init(key, heap, devId);
|
||||
if (ret == 0 && id != NULL && len != 0) {
|
||||
XMEMCPY(key->id, id, (size_t)len);
|
||||
key->idLen = len;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Initialize an LmsKey and bind it to a device-side key label.
|
||||
*
|
||||
* @param [in,out] key LmsKey to initialize.
|
||||
* @param [in] label NUL-terminated label string (must be non-empty).
|
||||
* @param [in] heap Heap hint forwarded to wc_LmsKey_Init.
|
||||
* @param [in] devId Device identifier.
|
||||
*
|
||||
* @return 0 on success.
|
||||
* @return BAD_FUNC_ARG when key or label is NULL.
|
||||
* @return BUFFER_E when label is empty or longer than LMS_MAX_LABEL_LEN.
|
||||
*/
|
||||
int wc_LmsKey_InitLabel(LmsKey* key, 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 > LMS_MAX_LABEL_LEN)
|
||||
ret = BUFFER_E;
|
||||
}
|
||||
if (ret == 0)
|
||||
ret = wc_LmsKey_Init(key, heap, devId);
|
||||
if (ret == 0) {
|
||||
XMEMCPY(key->label, label, (size_t)labelLen);
|
||||
key->labelLen = labelLen;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* WOLF_PRIVATE_KEY_ID */
|
||||
|
||||
/* Get the string representation of the LMS parameter set.
|
||||
*
|
||||
* @param [in] lmsParm LMS parameter set identifier.
|
||||
@@ -923,8 +994,10 @@ int wc_LmsKey_SetContext(LmsKey* key, void* context)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
/* Validate parameters. */
|
||||
if ((key == NULL) || (context == NULL)) {
|
||||
/* Validate parameters. NULL context is allowed: callers with stub
|
||||
* read/write callbacks (e.g. HSM-backed keys whose private state lives
|
||||
* in the device) have no meaningful context to pass. */
|
||||
if (key == NULL) {
|
||||
ret = BAD_FUNC_ARG;
|
||||
}
|
||||
/* Setting context of an already working key is forbidden. */
|
||||
@@ -969,17 +1042,31 @@ int wc_LmsKey_MakeKey(LmsKey* key, WC_RNG* rng)
|
||||
WOLFSSL_MSG("error: LmsKey not ready for generation");
|
||||
ret = BAD_STATE_E;
|
||||
}
|
||||
|
||||
#ifdef WOLF_CRYPTO_CB
|
||||
/* HSM-backed keys skip the software write/context callbacks because the
|
||||
* device owns the private state. On CRYPTOCB_UNAVAILABLE fall-through the
|
||||
* software checks below still run. */
|
||||
if ((ret == 0) && (key->devId != INVALID_DEVID)) {
|
||||
ret = wc_CryptoCb_PqcStatefulSigKeyGen(WC_PQC_STATEFUL_SIG_TYPE_LMS,
|
||||
key, rng);
|
||||
if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
|
||||
/* On success, mirror the software path's terminal state so
|
||||
* subsequent Sign/Verify calls don't fail with BAD_STATE_E. */
|
||||
if (ret == 0) {
|
||||
key->state = WC_LMS_STATE_OK;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
ret = 0; /* fall through to software path */
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Check write callback set. */
|
||||
if ((ret == 0) && (key->write_private_key == NULL)) {
|
||||
WOLFSSL_MSG("error: LmsKey write callback is not set");
|
||||
ret = BAD_FUNC_ARG;
|
||||
}
|
||||
/* Check callback context set. */
|
||||
if ((ret == 0) && (key->context == NULL)) {
|
||||
WOLFSSL_MSG("error: LmsKey context is not set");
|
||||
ret = BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
const LmsParams* params = key->params;
|
||||
priv_data_len = LMS_PRIV_DATA_LEN(params->levels, params->height,
|
||||
@@ -1077,16 +1164,21 @@ int wc_LmsKey_Reload(LmsKey* key)
|
||||
WOLFSSL_MSG("error: LmsKey not ready for reload");
|
||||
ret = BAD_STATE_E;
|
||||
}
|
||||
|
||||
#ifdef WOLF_CRYPTO_CB
|
||||
/* State for HSM-backed keys lives in the device; no software reload. */
|
||||
if ((ret == 0) && (key->devId != INVALID_DEVID)) {
|
||||
WOLFSSL_MSG("wc_LmsKey_Reload is a no-op for HSM-backed keys");
|
||||
key->state = WC_LMS_STATE_OK;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Check read callback present. */
|
||||
if ((ret == 0) && (key->read_private_key == NULL)) {
|
||||
WOLFSSL_MSG("error: LmsKey read callback is not set");
|
||||
ret = BAD_FUNC_ARG;
|
||||
}
|
||||
/* Check context for callback set */
|
||||
if ((ret == 0) && (key->context == NULL)) {
|
||||
WOLFSSL_MSG("error: LmsKey context is not set");
|
||||
ret = BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
const LmsParams* params = key->params;
|
||||
@@ -1236,16 +1328,25 @@ int wc_LmsKey_Sign(LmsKey* key, byte* sig, word32* sigSz, const byte* msg,
|
||||
WOLFSSL_MSG("error: LMS sig buffer too small");
|
||||
ret = BUFFER_E;
|
||||
}
|
||||
|
||||
#ifdef WOLF_CRYPTO_CB
|
||||
/* HSM-backed keys skip the software write/context callbacks because the
|
||||
* device owns the private state. On CRYPTOCB_UNAVAILABLE fall-through the
|
||||
* software checks below still run. */
|
||||
if ((ret == 0) && (key->devId != INVALID_DEVID)) {
|
||||
ret = wc_CryptoCb_PqcStatefulSigSign(msg, (word32)msgSz, sig, sigSz,
|
||||
WC_PQC_STATEFUL_SIG_TYPE_LMS, key);
|
||||
if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
|
||||
return ret;
|
||||
ret = 0; /* fall through to software path */
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Check read and write callbacks available. */
|
||||
if ((ret == 0) && (key->write_private_key == NULL)) {
|
||||
WOLFSSL_MSG("error: LmsKey write/read callbacks are not set");
|
||||
ret = BAD_FUNC_ARG;
|
||||
}
|
||||
/* Check read/write callback context available. */
|
||||
if ((ret == 0) && (key->context == NULL)) {
|
||||
WOLFSSL_MSG("error: LmsKey context is not set");
|
||||
ret = BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
WC_DECLARE_VAR(state, LmsState, 1, 0);
|
||||
@@ -1313,6 +1414,25 @@ int wc_LmsKey_SigsLeft(LmsKey* key)
|
||||
|
||||
/* NULL keys have no signatures remaining. */
|
||||
if (key != NULL) {
|
||||
#ifdef WOLF_CRYPTO_CB
|
||||
if (key->devId != INVALID_DEVID) {
|
||||
word32 sigsLeft = 0;
|
||||
int cbRet = wc_CryptoCb_PqcStatefulSigSigsLeft(
|
||||
WC_PQC_STATEFUL_SIG_TYPE_LMS, key, &sigsLeft);
|
||||
if (cbRet == 0) {
|
||||
return (sigsLeft != 0) ? 1 : 0;
|
||||
}
|
||||
/* The device owns the private state; no safe software fallback
|
||||
* exists because key->priv_raw does not reflect HSM state. */
|
||||
if (cbRet != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
|
||||
WOLFSSL_MSG("PqcStatefulSigSigsLeft returned an error");
|
||||
}
|
||||
else {
|
||||
WOLFSSL_MSG("LMS SigsLeft not supported by device");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
ret = wc_hss_sigsleft(key->params, key->priv_raw);
|
||||
}
|
||||
|
||||
@@ -1345,22 +1465,27 @@ int wc_LmsKey_GetPubLen(const LmsKey* key, word32* len)
|
||||
}
|
||||
|
||||
/* Export a generated public key and parameter set from one LmsKey
|
||||
* to another. Use this to prepare a signature verification LmsKey
|
||||
* that is pub only.
|
||||
* to another, with explicit heap and device bindings.
|
||||
*
|
||||
* Though the public key is all that is used to verify signatures,
|
||||
* the parameter set is needed to calculate the signature length
|
||||
* before hand.
|
||||
* The destination is fully (re)initialized as a verify-only key;
|
||||
* any prior state on keyDst is discarded.
|
||||
*
|
||||
* @param [out] keyDst LMS key to copy into.
|
||||
* @param [in] keySrc LMS key to copy.
|
||||
* @param [in] heap Heap hint for keyDst.
|
||||
* @param [in] devId Device identifier for keyDst.
|
||||
* Use INVALID_DEVID when not using a device.
|
||||
* @return 0 on success.
|
||||
* @return BAD_FUNC_ARG when keyDst or keySrc is NULL.
|
||||
*/
|
||||
int wc_LmsKey_ExportPub(LmsKey* keyDst, const LmsKey* keySrc)
|
||||
int wc_LmsKey_ExportPub_ex(LmsKey* keyDst, const LmsKey* keySrc,
|
||||
void* heap, int devId)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
(void)heap;
|
||||
(void)devId;
|
||||
|
||||
if ((keyDst == NULL) || (keySrc == NULL)) {
|
||||
ret = BAD_FUNC_ARG;
|
||||
}
|
||||
@@ -1371,6 +1496,13 @@ int wc_LmsKey_ExportPub(LmsKey* keyDst, const LmsKey* keySrc)
|
||||
keyDst->params = keySrc->params;
|
||||
XMEMCPY(keyDst->pub, keySrc->pub, sizeof(keySrc->pub));
|
||||
|
||||
#ifndef WOLFSSL_LMS_VERIFY_ONLY
|
||||
keyDst->heap = heap;
|
||||
#endif
|
||||
#ifdef WOLF_CRYPTO_CB
|
||||
keyDst->devId = devId;
|
||||
#endif
|
||||
|
||||
/* Mark this key as verify only, to prevent misuse. */
|
||||
keyDst->state = WC_LMS_STATE_VERIFYONLY;
|
||||
}
|
||||
@@ -1378,6 +1510,34 @@ int wc_LmsKey_ExportPub(LmsKey* keyDst, const LmsKey* keySrc)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Export a generated public key and parameter set from one LmsKey
|
||||
* to another. Use this to prepare a signature verification LmsKey
|
||||
* that is pub only.
|
||||
*
|
||||
* Though the public key is all that is used to verify signatures,
|
||||
* the parameter set is needed to calculate the signature length
|
||||
* before hand.
|
||||
*
|
||||
* The destination key is left with no heap hint and no device
|
||||
* binding. Callers that need either should use
|
||||
* wc_LmsKey_ExportPub_ex.
|
||||
*
|
||||
* @param [out] keyDst LMS key to copy into.
|
||||
* @param [in] keySrc LMS key to copy.
|
||||
* @return 0 on success.
|
||||
* @return BAD_FUNC_ARG when keyDst or keySrc is NULL.
|
||||
*/
|
||||
int wc_LmsKey_ExportPub(LmsKey* keyDst, const LmsKey* keySrc)
|
||||
{
|
||||
return wc_LmsKey_ExportPub_ex(keyDst, keySrc,
|
||||
#ifndef WOLFSSL_LMS_VERIFY_ONLY
|
||||
(keySrc != NULL) ? keySrc->heap : NULL,
|
||||
#else
|
||||
NULL,
|
||||
#endif
|
||||
INVALID_DEVID);
|
||||
}
|
||||
|
||||
/* Exports the raw LMS public key buffer from key to out buffer.
|
||||
* The out buffer should be large enough to hold the public key, and
|
||||
* outLen should indicate the size of the buffer.
|
||||
@@ -1522,6 +1682,20 @@ int wc_LmsKey_Verify(LmsKey* key, const byte* sig, word32 sigSz,
|
||||
ret = BUFFER_E;
|
||||
}
|
||||
|
||||
#ifdef WOLF_CRYPTO_CB
|
||||
if ((ret == 0) && (key->devId != INVALID_DEVID)) {
|
||||
int res = 0;
|
||||
ret = wc_CryptoCb_PqcStatefulSigVerify(sig, sigSz, msg, (word32)msgSz,
|
||||
&res, WC_PQC_STATEFUL_SIG_TYPE_LMS, key);
|
||||
if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
|
||||
if (ret == 0 && res != 1)
|
||||
ret = SIG_VERIFY_E;
|
||||
return ret;
|
||||
}
|
||||
ret = 0; /* fall through to software path */
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ret == 0) {
|
||||
WC_DECLARE_VAR(state, LmsState, 1, 0);
|
||||
|
||||
@@ -1567,6 +1741,16 @@ int wc_LmsKey_GetKid(LmsKey * key, const byte ** kid, word32* kidSz)
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
#ifdef WOLF_CRYPTO_CB
|
||||
/* priv_raw is not populated for HSM-backed keys where the device owns
|
||||
* the private state; the returned KID will be zero bytes. Extend the
|
||||
* CryptoCb surface if device-side KID retrieval becomes a requirement. */
|
||||
if (key->devId != INVALID_DEVID) {
|
||||
WOLFSSL_MSG(
|
||||
"wc_LmsKey_GetKid: priv_raw may be uninitialised for HSM keys");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* SEED length is hash length. */
|
||||
offset = HSS_Q_LEN + HSS_PRIV_KEY_PARAM_SET_LEN + key->params->hash_len;
|
||||
*kid = key->priv_raw + offset;
|
||||
|
||||
+238
-29
@@ -28,6 +28,7 @@
|
||||
#define FIPS_NO_WRAPPERS
|
||||
#endif
|
||||
#include <wolfssl/wolfcrypt/wc_xmss.h>
|
||||
#include <wolfssl/wolfcrypt/hash.h>
|
||||
|
||||
#ifdef NO_INLINE
|
||||
#include <wolfssl/wolfcrypt/misc.h>
|
||||
@@ -36,6 +37,9 @@
|
||||
#include <wolfcrypt/src/misc.c>
|
||||
#endif
|
||||
|
||||
#ifdef WOLF_CRYPTO_CB
|
||||
#include <wolfssl/wolfcrypt/cryptocb.h>
|
||||
#endif
|
||||
|
||||
/***************************
|
||||
* DIGEST init and free.
|
||||
@@ -814,7 +818,7 @@ static WC_INLINE int wc_xmsskey_signupdate(XmssKey* key, byte* sig,
|
||||
*
|
||||
* @param [in] key The XMSS key to init.
|
||||
* @param [in] heap Dynamic memory hint used by subsequent allocations.
|
||||
* @param [in] devId Unused.
|
||||
* @param [in] devId Device identifier (used with WOLF_CRYPTO_CB).
|
||||
*
|
||||
* @return 0 on success.
|
||||
* @return BAD_FUNC_ARG when a parameter is NULL.
|
||||
@@ -823,7 +827,9 @@ int wc_XmssKey_Init(XmssKey* key, void* heap, int devId)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
#ifndef WOLF_CRYPTO_CB
|
||||
(void) devId;
|
||||
#endif
|
||||
|
||||
/* Validate parameters. */
|
||||
if (key == NULL) {
|
||||
@@ -834,12 +840,82 @@ int wc_XmssKey_Init(XmssKey* key, void* heap, int devId)
|
||||
/* Zeroize key and set state to initialized. */
|
||||
ForceZero(key, sizeof(XmssKey));
|
||||
key->heap = heap;
|
||||
#ifdef WOLF_CRYPTO_CB
|
||||
key->devId = devId;
|
||||
#endif
|
||||
key->state = WC_XMSS_STATE_INITED;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef WOLF_PRIVATE_KEY_ID
|
||||
/* Initialize an XmssKey and bind it to a device-side key identifier.
|
||||
*
|
||||
* @param [in,out] key XmssKey to initialize.
|
||||
* @param [in] id Identifier bytes (may be NULL when len is 0).
|
||||
* @param [in] len Length of id; must be in [0, XMSS_MAX_ID_LEN].
|
||||
* @param [in] heap Heap hint forwarded to wc_XmssKey_Init.
|
||||
* @param [in] devId Device identifier.
|
||||
*
|
||||
* @return 0 on success.
|
||||
* @return BAD_FUNC_ARG when key is NULL.
|
||||
* @return BUFFER_E when len is negative or exceeds XMSS_MAX_ID_LEN.
|
||||
*/
|
||||
int wc_XmssKey_InitId(XmssKey* key, const unsigned char* id, int len,
|
||||
void* heap, int devId)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (key == NULL)
|
||||
ret = BAD_FUNC_ARG;
|
||||
if (ret == 0 && (len < 0 || len > XMSS_MAX_ID_LEN))
|
||||
ret = BUFFER_E;
|
||||
if (ret == 0)
|
||||
ret = wc_XmssKey_Init(key, heap, devId);
|
||||
if (ret == 0 && id != NULL && len != 0) {
|
||||
XMEMCPY(key->id, id, (size_t)len);
|
||||
key->idLen = len;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Initialize an XmssKey and bind it to a device-side key label.
|
||||
*
|
||||
* @param [in,out] key XmssKey to initialize.
|
||||
* @param [in] label NUL-terminated label string (must be non-empty).
|
||||
* @param [in] heap Heap hint forwarded to wc_XmssKey_Init.
|
||||
* @param [in] devId Device identifier.
|
||||
*
|
||||
* @return 0 on success.
|
||||
* @return BAD_FUNC_ARG when key or label is NULL.
|
||||
* @return BUFFER_E when label is empty or longer than XMSS_MAX_LABEL_LEN.
|
||||
*/
|
||||
int wc_XmssKey_InitLabel(XmssKey* key, 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 > XMSS_MAX_LABEL_LEN)
|
||||
ret = BUFFER_E;
|
||||
}
|
||||
if (ret == 0)
|
||||
ret = wc_XmssKey_Init(key, heap, devId);
|
||||
if (ret == 0) {
|
||||
XMEMCPY(key->label, label, (size_t)labelLen);
|
||||
key->labelLen = labelLen;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* WOLF_PRIVATE_KEY_ID */
|
||||
|
||||
/* Set the XMSS key parameter string.
|
||||
*
|
||||
* The input string must be one of the supported parm set names in
|
||||
@@ -899,6 +975,62 @@ int wc_XmssKey_SetParamStr(XmssKey* key, const char* str)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Get the XMSS key parameter string for a key whose params have been set.
|
||||
*
|
||||
* Performs a reverse lookup from key->oid (and key->is_xmssmt) into the
|
||||
* supported algorithm tables and returns a pointer to the static parameter
|
||||
* string (e.g. "XMSS-SHA2_10_256" or "XMSSMT-SHA2_20/4_256"). The returned
|
||||
* pointer remains valid for the lifetime of the program.
|
||||
*
|
||||
* @param [in] key XMSS key with params set via wc_XmssKey_SetParamStr.
|
||||
* @param [out] str On success, set to the algorithm name.
|
||||
*
|
||||
* @return 0 on success.
|
||||
* @return BAD_FUNC_ARG when a parameter is NULL.
|
||||
* @return BAD_STATE_E when params have not been set.
|
||||
* @return NOT_COMPILED_IN when the OID is not in the supported tables.
|
||||
*/
|
||||
int wc_XmssKey_GetParamStr(const XmssKey* key, const char** str)
|
||||
{
|
||||
int ret = WC_NO_ERR_TRACE(NOT_COMPILED_IN);
|
||||
unsigned int i;
|
||||
|
||||
if ((key == NULL) || (str == NULL)) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
if (key->state != WC_XMSS_STATE_PARMSET &&
|
||||
key->state != WC_XMSS_STATE_OK &&
|
||||
key->state != WC_XMSS_STATE_VERIFYONLY &&
|
||||
key->state != WC_XMSS_STATE_NOSIGS) {
|
||||
return BAD_STATE_E;
|
||||
}
|
||||
|
||||
if (key->is_xmssmt) {
|
||||
#if WOLFSSL_XMSS_MAX_HEIGHT >= 20
|
||||
for (i = 0; i < WC_XMSSMT_ALG_LEN; i++) {
|
||||
if (wc_xmssmt_alg[i].oid == key->oid) {
|
||||
*str = wc_xmssmt_alg[i].str;
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
#if WOLFSSL_XMSS_MIN_HEIGHT <= 20
|
||||
for (i = 0; i < WC_XMSS_ALG_LEN; i++) {
|
||||
if (wc_xmss_alg[i].oid == key->oid) {
|
||||
*str = wc_xmss_alg[i].str;
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Force zeros and frees the XMSS key from memory.
|
||||
*
|
||||
* This does not touch the private key saved to non-volatile storage.
|
||||
@@ -1011,8 +1143,10 @@ int wc_XmssKey_SetContext(XmssKey* key, void* context)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
/* Validate parameters. */
|
||||
if ((key == NULL) || (context == NULL)) {
|
||||
/* Validate parameters. NULL context is allowed: callers with stub
|
||||
* read/write callbacks (e.g. HSM-backed keys whose private state lives
|
||||
* in the device) have no meaningful context to pass. */
|
||||
if (key == NULL) {
|
||||
ret = BAD_FUNC_ARG;
|
||||
}
|
||||
/* Setting context of an already working key is forbidden. */
|
||||
@@ -1070,17 +1204,30 @@ int wc_XmssKey_MakeKey(XmssKey* key, WC_RNG* rng)
|
||||
WOLFSSL_MSG("error: XmssKey not ready for generation");
|
||||
ret = BAD_STATE_E;
|
||||
}
|
||||
#ifdef WOLF_CRYPTO_CB
|
||||
/* HSM-backed keys skip the software write/context callbacks because the
|
||||
* device owns the private state. On CRYPTOCB_UNAVAILABLE fall-through the
|
||||
* software checks below still run. */
|
||||
if ((ret == 0) && (key->devId != INVALID_DEVID)) {
|
||||
ret = wc_CryptoCb_PqcStatefulSigKeyGen(WC_PQC_STATEFUL_SIG_TYPE_XMSS,
|
||||
key, rng);
|
||||
if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
|
||||
/* On success, mirror the software path's terminal state so
|
||||
* subsequent Sign/Verify calls don't fail with BAD_STATE_E. */
|
||||
if (ret == 0) {
|
||||
key->state = WC_XMSS_STATE_OK;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
ret = 0; /* fall through to software path */
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Ensure write callback available. */
|
||||
if ((ret == 0) && (key->write_private_key == NULL)) {
|
||||
WOLFSSL_MSG("error: XmssKey write callback is not set");
|
||||
ret = BAD_FUNC_ARG;
|
||||
}
|
||||
/* Ensure read/write callback context available. */
|
||||
if ((ret == 0) && (key->context == NULL)) {
|
||||
WOLFSSL_MSG("error: XmssKey context is not set");
|
||||
ret = BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
/* Allocate sk array. */
|
||||
ret = wc_xmsskey_alloc_sk(key);
|
||||
@@ -1195,17 +1342,22 @@ int wc_XmssKey_Reload(XmssKey* key)
|
||||
WOLFSSL_MSG("error: XmssKey not ready for reload");
|
||||
ret = BAD_STATE_E;
|
||||
}
|
||||
|
||||
#ifdef WOLF_CRYPTO_CB
|
||||
/* State for HSM-backed keys lives in the device; no software reload. */
|
||||
if ((ret == 0) && (key->devId != INVALID_DEVID)) {
|
||||
WOLFSSL_MSG("wc_XmssKey_Reload is a no-op for HSM-backed keys");
|
||||
key->state = WC_XMSS_STATE_OK;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Ensure read and write callbacks are available. */
|
||||
if ((ret == 0) && ((key->write_private_key == NULL) ||
|
||||
(key->read_private_key == NULL))) {
|
||||
WOLFSSL_MSG("error: XmssKey write/read callbacks are not set");
|
||||
ret = BAD_FUNC_ARG;
|
||||
}
|
||||
/* Ensure read and write callback context is available. */
|
||||
if ((ret == 0) && (key->context == NULL)) {
|
||||
WOLFSSL_MSG("error: XmssKey context is not set");
|
||||
ret = BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
/* Allocate sk array. */
|
||||
@@ -1317,17 +1469,26 @@ int wc_XmssKey_Sign(XmssKey* key, byte* sig, word32* sigLen, const byte* msg,
|
||||
WOLFSSL_MSG("error: XMSS sig buffer too small");
|
||||
ret = BUFFER_E;
|
||||
}
|
||||
|
||||
#ifdef WOLF_CRYPTO_CB
|
||||
/* HSM-backed keys skip the software write/context callbacks because the
|
||||
* device owns the private state. On CRYPTOCB_UNAVAILABLE fall-through the
|
||||
* software checks below still run. */
|
||||
if ((ret == 0) && (key->devId != INVALID_DEVID)) {
|
||||
ret = wc_CryptoCb_PqcStatefulSigSign(msg, (word32)msgLen, sig, sigLen,
|
||||
WC_PQC_STATEFUL_SIG_TYPE_XMSS, key);
|
||||
if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
|
||||
return ret;
|
||||
ret = 0; /* fall through to software path */
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Check read and write callbacks available. */
|
||||
if ((ret == 0) && ((key->write_private_key == NULL) ||
|
||||
(key->read_private_key == NULL))) {
|
||||
WOLFSSL_MSG("error: XmssKey write/read callbacks are not set");
|
||||
ret = BAD_FUNC_ARG;
|
||||
}
|
||||
/* Check read/write callback context available. */
|
||||
if ((ret == 0) && (key->context == NULL)) {
|
||||
WOLFSSL_MSG("error: XmssKey context is not set");
|
||||
ret = BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
*sigLen = key->params->sig_len;
|
||||
@@ -1346,14 +1507,34 @@ int wc_XmssKey_Sign(XmssKey* key, byte* sig, word32* sigLen, const byte* msg,
|
||||
*/
|
||||
int wc_XmssKey_SigsLeft(XmssKey* key)
|
||||
{
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
/* Validate parameter. */
|
||||
if (key == NULL) {
|
||||
ret = 0;
|
||||
if (key == NULL)
|
||||
return 0;
|
||||
|
||||
#ifdef WOLF_CRYPTO_CB
|
||||
if (key->devId != INVALID_DEVID) {
|
||||
word32 sigsLeft = 0;
|
||||
int cbRet = wc_CryptoCb_PqcStatefulSigSigsLeft(
|
||||
WC_PQC_STATEFUL_SIG_TYPE_XMSS, key, &sigsLeft);
|
||||
if (cbRet == 0) {
|
||||
return (sigsLeft != 0) ? 1 : 0;
|
||||
}
|
||||
/* The device owns the private state; no safe software fallback
|
||||
* exists because key->sk does not reflect HSM state. */
|
||||
if (cbRet != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
|
||||
WOLFSSL_MSG("PqcStatefulSigSigsLeft returned an error");
|
||||
}
|
||||
else {
|
||||
WOLFSSL_MSG("XMSS SigsLeft not supported by device");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Validate state. */
|
||||
else if (key->state == WC_XMSS_STATE_NOSIGS) {
|
||||
if (key->state == WC_XMSS_STATE_NOSIGS) {
|
||||
WOLFSSL_MSG("error: XMSS signatures exhausted");
|
||||
ret = 0;
|
||||
}
|
||||
@@ -1414,10 +1595,15 @@ int wc_XmssKey_GetPubLen(const XmssKey* key, word32* len)
|
||||
* @return BAD_FUNC_ARG when a key is NULL.
|
||||
* @return Other negative when digest algorithm initialization failed.
|
||||
*/
|
||||
int wc_XmssKey_ExportPub(XmssKey* keyDst, const XmssKey* keySrc)
|
||||
int wc_XmssKey_ExportPub_ex(XmssKey* keyDst, const XmssKey* keySrc,
|
||||
void* heap, int devId)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
#ifndef WOLF_CRYPTO_CB
|
||||
(void)devId;
|
||||
#endif
|
||||
|
||||
/* Validate parameters. */
|
||||
if ((keyDst == NULL) || (keySrc == NULL)) {
|
||||
ret = BAD_FUNC_ARG;
|
||||
@@ -1434,14 +1620,23 @@ int wc_XmssKey_ExportPub(XmssKey* keyDst, const XmssKey* keySrc)
|
||||
keyDst->oid = keySrc->oid;
|
||||
keyDst->is_xmssmt = keySrc->is_xmssmt;
|
||||
keyDst->params = keySrc->params;
|
||||
keyDst->heap = keySrc->heap;
|
||||
}
|
||||
if (ret == 0) {
|
||||
keyDst->heap = heap;
|
||||
|
||||
#ifdef WOLF_CRYPTO_CB
|
||||
keyDst->devId = devId;
|
||||
#endif
|
||||
|
||||
/* Mark keyDst as verify only, to prevent misuse. */
|
||||
keyDst->state = WC_XMSS_STATE_VERIFYONLY;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wc_XmssKey_ExportPub(XmssKey* keyDst, const XmssKey* keySrc)
|
||||
{
|
||||
return wc_XmssKey_ExportPub_ex(keyDst, keySrc,
|
||||
(keySrc != NULL) ? keySrc->heap : NULL, INVALID_DEVID);
|
||||
}
|
||||
|
||||
/* Exports the raw XMSS public key buffer from key to out buffer.
|
||||
@@ -1606,7 +1801,7 @@ int wc_XmssKey_GetSigLen(const XmssKey* key, word32* len)
|
||||
int wc_XmssKey_Verify(XmssKey* key, const byte* sig, word32 sigLen,
|
||||
const byte* m, int mLen)
|
||||
{
|
||||
int ret = 0;
|
||||
int ret = 0;
|
||||
|
||||
/* Validate parameters. */
|
||||
if ((key == NULL) || (sig == NULL) || (m == NULL) || (mLen <= 0)) {
|
||||
@@ -1626,6 +1821,20 @@ int wc_XmssKey_Verify(XmssKey* key, const byte* sig, word32 sigLen,
|
||||
ret = BUFFER_E;
|
||||
}
|
||||
|
||||
#ifdef WOLF_CRYPTO_CB
|
||||
if ((ret == 0) && (key->devId != INVALID_DEVID)) {
|
||||
int res = 0;
|
||||
ret = wc_CryptoCb_PqcStatefulSigVerify(sig, sigLen, m, (word32)mLen,
|
||||
&res, WC_PQC_STATEFUL_SIG_TYPE_XMSS, key);
|
||||
if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
|
||||
if (ret == 0 && res != 1)
|
||||
ret = SIG_VERIFY_E;
|
||||
return ret;
|
||||
}
|
||||
ret = 0; /* fall through to software path */
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ret == 0) {
|
||||
WC_DECLARE_VAR(state, XmssState, 1, 0);
|
||||
|
||||
|
||||
+121
-12
@@ -53136,7 +53136,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t xmss_test(void)
|
||||
if (ret != 0) { ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); }
|
||||
|
||||
/* Export the pub to a verify key. */
|
||||
ret = wc_XmssKey_ExportPub(&verifyKey, &signingKey);
|
||||
ret = wc_XmssKey_ExportPub_ex(&verifyKey, &signingKey, NULL, devId);
|
||||
if (ret != 0) { ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); }
|
||||
|
||||
/* Repeat a few times to check that:
|
||||
@@ -53809,7 +53809,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t lms_test(void)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_I(kidSz), out);
|
||||
}
|
||||
|
||||
ret = wc_LmsKey_ExportPub(&verifyKey, &signingKey);
|
||||
ret = wc_LmsKey_ExportPub_ex(&verifyKey, &signingKey, NULL, devId);
|
||||
if (ret != 0) { ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); }
|
||||
|
||||
ret = wc_LmsKey_GetSigLen(&verifyKey, &sigSz);
|
||||
@@ -53824,7 +53824,6 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t lms_test(void)
|
||||
{
|
||||
word32 smallSz = 1;
|
||||
wc_lms_write_private_key_cb saved_write_cb;
|
||||
void* saved_ctx;
|
||||
|
||||
/* Undersized sig buffer should return BUFFER_E. */
|
||||
ret = wc_LmsKey_Sign(&signingKey, sig, &smallSz, (byte *) msg, msgSz);
|
||||
@@ -53841,15 +53840,6 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t lms_test(void)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
}
|
||||
|
||||
/* NULL context should return BAD_FUNC_ARG. */
|
||||
saved_ctx = signingKey.context;
|
||||
signingKey.context = NULL;
|
||||
ret = wc_LmsKey_Sign(&signingKey, sig, &sigSz, (byte *) msg, msgSz);
|
||||
signingKey.context = saved_ctx;
|
||||
if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) {
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
@@ -68726,6 +68716,117 @@ static int myCryptoDevCb(int devIdArg, wc_CryptoInfo* info, void* ctx)
|
||||
}
|
||||
#endif
|
||||
#endif /* HAVE_ED25519 */
|
||||
#if defined(WOLFSSL_HAVE_LMS) || defined(WOLFSSL_HAVE_XMSS)
|
||||
if (info->pk.type == WC_PK_TYPE_PQC_STATEFUL_SIG_KEYGEN) {
|
||||
int pqcType = info->pk.pqc_stateful_sig_kg.type;
|
||||
(void)pqcType;
|
||||
#if defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_VERIFY_ONLY)
|
||||
if (pqcType == WC_PQC_STATEFUL_SIG_TYPE_LMS) {
|
||||
LmsKey* lk = (LmsKey*)info->pk.pqc_stateful_sig_kg.key;
|
||||
lk->devId = INVALID_DEVID;
|
||||
ret = wc_LmsKey_MakeKey(lk, info->pk.pqc_stateful_sig_kg.rng);
|
||||
lk->devId = devIdArg;
|
||||
}
|
||||
#endif
|
||||
#if defined(WOLFSSL_HAVE_XMSS) && !defined(WOLFSSL_XMSS_VERIFY_ONLY)
|
||||
if (pqcType == WC_PQC_STATEFUL_SIG_TYPE_XMSS) {
|
||||
XmssKey* xk = (XmssKey*)info->pk.pqc_stateful_sig_kg.key;
|
||||
xk->devId = INVALID_DEVID;
|
||||
ret = wc_XmssKey_MakeKey(xk, info->pk.pqc_stateful_sig_kg.rng);
|
||||
xk->devId = devIdArg;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if (info->pk.type == WC_PK_TYPE_PQC_STATEFUL_SIG_SIGN) {
|
||||
int pqcType = info->pk.pqc_stateful_sig_sign.type;
|
||||
word32 sigSz = *info->pk.pqc_stateful_sig_sign.outSz;
|
||||
(void)pqcType;
|
||||
#if defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_VERIFY_ONLY)
|
||||
if (pqcType == WC_PQC_STATEFUL_SIG_TYPE_LMS) {
|
||||
LmsKey* lk = (LmsKey*)info->pk.pqc_stateful_sig_sign.key;
|
||||
lk->devId = INVALID_DEVID;
|
||||
ret = wc_LmsKey_Sign(lk,
|
||||
info->pk.pqc_stateful_sig_sign.out, &sigSz,
|
||||
info->pk.pqc_stateful_sig_sign.msg,
|
||||
(int)info->pk.pqc_stateful_sig_sign.msgSz);
|
||||
lk->devId = devIdArg;
|
||||
}
|
||||
#endif
|
||||
#if defined(WOLFSSL_HAVE_XMSS) && !defined(WOLFSSL_XMSS_VERIFY_ONLY)
|
||||
if (pqcType == WC_PQC_STATEFUL_SIG_TYPE_XMSS) {
|
||||
XmssKey* xk = (XmssKey*)info->pk.pqc_stateful_sig_sign.key;
|
||||
xk->devId = INVALID_DEVID;
|
||||
ret = wc_XmssKey_Sign(xk,
|
||||
info->pk.pqc_stateful_sig_sign.out, &sigSz,
|
||||
info->pk.pqc_stateful_sig_sign.msg,
|
||||
(int)info->pk.pqc_stateful_sig_sign.msgSz);
|
||||
xk->devId = devIdArg;
|
||||
}
|
||||
#endif
|
||||
*info->pk.pqc_stateful_sig_sign.outSz = sigSz;
|
||||
}
|
||||
else if (info->pk.type == WC_PK_TYPE_PQC_STATEFUL_SIG_VERIFY) {
|
||||
int pqcType = info->pk.pqc_stateful_sig_verify.type;
|
||||
int verifyRet = WC_NO_ERR_TRACE(NOT_COMPILED_IN);
|
||||
#if defined(WOLFSSL_HAVE_LMS)
|
||||
if (pqcType == WC_PQC_STATEFUL_SIG_TYPE_LMS) {
|
||||
LmsKey* lk = (LmsKey*)info->pk.pqc_stateful_sig_verify.key;
|
||||
lk->devId = INVALID_DEVID;
|
||||
verifyRet = wc_LmsKey_Verify(lk,
|
||||
info->pk.pqc_stateful_sig_verify.sig,
|
||||
info->pk.pqc_stateful_sig_verify.sigSz,
|
||||
info->pk.pqc_stateful_sig_verify.msg,
|
||||
(int)info->pk.pqc_stateful_sig_verify.msgSz);
|
||||
lk->devId = devIdArg;
|
||||
}
|
||||
#endif
|
||||
#if defined(WOLFSSL_HAVE_XMSS)
|
||||
if (pqcType == WC_PQC_STATEFUL_SIG_TYPE_XMSS) {
|
||||
XmssKey* xk = (XmssKey*)info->pk.pqc_stateful_sig_verify.key;
|
||||
xk->devId = INVALID_DEVID;
|
||||
verifyRet = wc_XmssKey_Verify(xk,
|
||||
info->pk.pqc_stateful_sig_verify.sig,
|
||||
info->pk.pqc_stateful_sig_verify.sigSz,
|
||||
info->pk.pqc_stateful_sig_verify.msg,
|
||||
(int)info->pk.pqc_stateful_sig_verify.msgSz);
|
||||
xk->devId = devIdArg;
|
||||
}
|
||||
#endif
|
||||
if (info->pk.pqc_stateful_sig_verify.res != NULL) {
|
||||
*info->pk.pqc_stateful_sig_verify.res =
|
||||
(verifyRet == 0) ? 1 : 0;
|
||||
}
|
||||
/* SIG_VERIFY_E is a validity signal, not a crypto error, so
|
||||
* translate it back to success for the dispatcher. */
|
||||
if (verifyRet == WC_NO_ERR_TRACE(SIG_VERIFY_E))
|
||||
verifyRet = 0;
|
||||
ret = verifyRet;
|
||||
}
|
||||
else if (info->pk.type == WC_PK_TYPE_PQC_STATEFUL_SIG_SIGS_LEFT) {
|
||||
int pqcType = info->pk.pqc_stateful_sig_sigs_left.type;
|
||||
int count = 0;
|
||||
(void)pqcType;
|
||||
#if defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_VERIFY_ONLY)
|
||||
if (pqcType == WC_PQC_STATEFUL_SIG_TYPE_LMS) {
|
||||
LmsKey* lk = (LmsKey*)info->pk.pqc_stateful_sig_sigs_left.key;
|
||||
lk->devId = INVALID_DEVID;
|
||||
count = wc_LmsKey_SigsLeft(lk);
|
||||
lk->devId = devIdArg;
|
||||
}
|
||||
#endif
|
||||
#if defined(WOLFSSL_HAVE_XMSS) && !defined(WOLFSSL_XMSS_VERIFY_ONLY)
|
||||
if (pqcType == WC_PQC_STATEFUL_SIG_TYPE_XMSS) {
|
||||
XmssKey* xk = (XmssKey*)info->pk.pqc_stateful_sig_sigs_left.key;
|
||||
xk->devId = INVALID_DEVID;
|
||||
count = wc_XmssKey_SigsLeft(xk);
|
||||
xk->devId = devIdArg;
|
||||
}
|
||||
#endif
|
||||
if (info->pk.pqc_stateful_sig_sigs_left.sigsLeft != NULL)
|
||||
*info->pk.pqc_stateful_sig_sigs_left.sigsLeft = (word32)count;
|
||||
ret = 0;
|
||||
}
|
||||
#endif /* WOLFSSL_HAVE_LMS || WOLFSSL_HAVE_XMSS */
|
||||
#ifdef WOLFSSL_HAVE_MLKEM
|
||||
if (info->pk.type == WC_PK_TYPE_PQC_KEM_KEYGEN) {
|
||||
if ((info->pk.pqc_kem_kg.type == WC_PQC_KEM_TYPE_KYBER) &&
|
||||
@@ -70159,6 +70260,14 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cryptocb_test(void)
|
||||
if (ret == 0)
|
||||
ret = dilithium_test();
|
||||
#endif
|
||||
#if defined(WOLFSSL_HAVE_XMSS) && !defined(WOLFSSL_XMSS_VERIFY_ONLY)
|
||||
if (ret == 0)
|
||||
ret = xmss_test();
|
||||
#endif
|
||||
#if defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_VERIFY_ONLY)
|
||||
if (ret == 0)
|
||||
ret = lms_test();
|
||||
#endif
|
||||
#ifdef HAVE_ED25519
|
||||
PRIVATE_KEY_UNLOCK();
|
||||
if (ret == 0)
|
||||
|
||||
@@ -86,6 +86,12 @@
|
||||
#if defined(HAVE_FALCON)
|
||||
#include <wolfssl/wolfcrypt/falcon.h>
|
||||
#endif
|
||||
#if defined(WOLFSSL_HAVE_LMS)
|
||||
#include <wolfssl/wolfcrypt/wc_lms.h>
|
||||
#endif
|
||||
#if defined(WOLFSSL_HAVE_XMSS)
|
||||
#include <wolfssl/wolfcrypt/wc_xmss.h>
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef WOLF_CRYPTO_CB_CMD
|
||||
@@ -344,6 +350,35 @@ typedef struct wc_CryptoInfo {
|
||||
int type; /* enum wc_PqcSignatureType */
|
||||
} pqc_sig_check;
|
||||
#endif
|
||||
#if defined(WOLFSSL_HAVE_LMS) || defined(WOLFSSL_HAVE_XMSS)
|
||||
struct {
|
||||
WC_RNG* rng;
|
||||
void* key;
|
||||
int type; /* enum wc_PqcStatefulSignatureType */
|
||||
} pqc_stateful_sig_kg;
|
||||
struct {
|
||||
const byte* msg;
|
||||
word32 msgSz;
|
||||
byte* out;
|
||||
word32* outSz;
|
||||
void* key;
|
||||
int type; /* enum wc_PqcStatefulSignatureType */
|
||||
} pqc_stateful_sig_sign;
|
||||
struct {
|
||||
const byte* sig;
|
||||
word32 sigSz;
|
||||
const byte* msg;
|
||||
word32 msgSz;
|
||||
int* res;
|
||||
void* key;
|
||||
int type; /* enum wc_PqcStatefulSignatureType */
|
||||
} pqc_stateful_sig_verify;
|
||||
struct {
|
||||
void* key;
|
||||
word32* sigsLeft;
|
||||
int type; /* enum wc_PqcStatefulSignatureType */
|
||||
} pqc_stateful_sig_sigs_left;
|
||||
#endif
|
||||
#ifdef HAVE_ANONYMOUS_INLINE_AGGREGATES
|
||||
};
|
||||
#endif
|
||||
@@ -711,6 +746,20 @@ WOLFSSL_LOCAL int wc_CryptoCb_Ed25519Verify(const byte* sig, word32 sigLen,
|
||||
const byte* context, byte contextLen);
|
||||
#endif /* HAVE_ED25519 */
|
||||
|
||||
#if defined(WOLFSSL_HAVE_LMS) || defined(WOLFSSL_HAVE_XMSS)
|
||||
WOLFSSL_LOCAL int wc_CryptoCb_PqcStatefulSigGetDevId(int type, void* key);
|
||||
|
||||
WOLFSSL_LOCAL int wc_CryptoCb_PqcStatefulSigKeyGen(int type, void* key,
|
||||
WC_RNG* rng);
|
||||
WOLFSSL_LOCAL int wc_CryptoCb_PqcStatefulSigSign(const byte* msg,
|
||||
word32 msgSz, byte* out, word32* outSz, int type, void* key);
|
||||
WOLFSSL_LOCAL int wc_CryptoCb_PqcStatefulSigVerify(const byte* sig,
|
||||
word32 sigSz, const byte* msg, word32 msgSz, int* res, int type,
|
||||
void* key);
|
||||
WOLFSSL_LOCAL int wc_CryptoCb_PqcStatefulSigSigsLeft(int type, void* key,
|
||||
word32* sigsLeft);
|
||||
#endif /* WOLFSSL_HAVE_LMS || WOLFSSL_HAVE_XMSS */
|
||||
|
||||
#if defined(WOLFSSL_HAVE_MLKEM)
|
||||
WOLFSSL_LOCAL int wc_CryptoCb_PqcKemGetDevId(int type, void* key);
|
||||
|
||||
|
||||
@@ -1573,6 +1573,14 @@ enum wc_PkType {
|
||||
WC_PK_TYPE_EC_GET_SIG_SIZE = 29,
|
||||
#undef _WC_PK_TYPE_MAX
|
||||
#define _WC_PK_TYPE_MAX WC_PK_TYPE_EC_GET_SIG_SIZE
|
||||
#if defined(WOLFSSL_HAVE_LMS) || defined(WOLFSSL_HAVE_XMSS)
|
||||
WC_PK_TYPE_PQC_STATEFUL_SIG_KEYGEN = 30,
|
||||
WC_PK_TYPE_PQC_STATEFUL_SIG_SIGN = 31,
|
||||
WC_PK_TYPE_PQC_STATEFUL_SIG_VERIFY = 32,
|
||||
WC_PK_TYPE_PQC_STATEFUL_SIG_SIGS_LEFT = 33,
|
||||
#undef _WC_PK_TYPE_MAX
|
||||
#define _WC_PK_TYPE_MAX WC_PK_TYPE_PQC_STATEFUL_SIG_SIGS_LEFT
|
||||
#endif
|
||||
WC_PK_TYPE_MAX = _WC_PK_TYPE_MAX
|
||||
};
|
||||
|
||||
@@ -1607,6 +1615,25 @@ enum wc_PkType {
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(WOLFSSL_HAVE_LMS) || defined(WOLFSSL_HAVE_XMSS)
|
||||
/* Post quantum stateful hash-based signature algorithms. */
|
||||
enum wc_PqcStatefulSignatureType {
|
||||
WC_PQC_STATEFUL_SIG_TYPE_NONE = 0,
|
||||
#define _WC_PQC_STATEFUL_SIG_TYPE_MAX WC_PQC_STATEFUL_SIG_TYPE_NONE
|
||||
#if defined(WOLFSSL_HAVE_LMS)
|
||||
WC_PQC_STATEFUL_SIG_TYPE_LMS = 1,
|
||||
#undef _WC_PQC_STATEFUL_SIG_TYPE_MAX
|
||||
#define _WC_PQC_STATEFUL_SIG_TYPE_MAX WC_PQC_STATEFUL_SIG_TYPE_LMS
|
||||
#endif
|
||||
#if defined(WOLFSSL_HAVE_XMSS)
|
||||
WC_PQC_STATEFUL_SIG_TYPE_XMSS = 2,
|
||||
#undef _WC_PQC_STATEFUL_SIG_TYPE_MAX
|
||||
#define _WC_PQC_STATEFUL_SIG_TYPE_MAX WC_PQC_STATEFUL_SIG_TYPE_XMSS
|
||||
#endif
|
||||
WC_PQC_STATEFUL_SIG_TYPE_MAX = _WC_PQC_STATEFUL_SIG_TYPE_MAX
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
/* settings detection for compile vs runtime math incompatibilities */
|
||||
enum {
|
||||
|
||||
@@ -741,6 +741,13 @@ typedef struct HssPrivKey {
|
||||
#endif
|
||||
} HssPrivKey;
|
||||
|
||||
#ifndef LMS_MAX_ID_LEN
|
||||
#define LMS_MAX_ID_LEN 32
|
||||
#endif
|
||||
#ifndef LMS_MAX_LABEL_LEN
|
||||
#define LMS_MAX_LABEL_LEN 32
|
||||
#endif
|
||||
|
||||
typedef struct LmsKey {
|
||||
/* Public key. */
|
||||
ALIGN16 byte pub[HSS_PUBLIC_KEY_LEN(LMS_MAX_NODE_LEN)];
|
||||
@@ -769,6 +776,16 @@ typedef struct LmsKey {
|
||||
#ifdef WOLF_CRYPTO_CB
|
||||
/* Device Identifier. */
|
||||
int devId;
|
||||
/* Per-device opaque context, populated by the callback. */
|
||||
void* devCtx;
|
||||
#endif
|
||||
#ifdef WOLF_PRIVATE_KEY_ID
|
||||
/* Optional device-side key identifier. */
|
||||
byte id[LMS_MAX_ID_LEN];
|
||||
int idLen;
|
||||
/* Optional device-side key label. */
|
||||
char label[LMS_MAX_LABEL_LEN];
|
||||
int labelLen;
|
||||
#endif
|
||||
} LmsKey;
|
||||
|
||||
@@ -777,6 +794,12 @@ typedef struct LmsKey {
|
||||
#endif
|
||||
|
||||
WOLFSSL_API int wc_LmsKey_Init(LmsKey * key, void * heap, int devId);
|
||||
#ifdef WOLF_PRIVATE_KEY_ID
|
||||
WOLFSSL_API int wc_LmsKey_InitId(LmsKey * key, const unsigned char * id,
|
||||
int len, void * heap, int devId);
|
||||
WOLFSSL_API int wc_LmsKey_InitLabel(LmsKey * key, const char * label,
|
||||
void * heap, int devId);
|
||||
#endif
|
||||
WOLFSSL_API int wc_LmsKey_SetLmsParm(LmsKey * key, enum wc_LmsParm lmsParm);
|
||||
WOLFSSL_API int wc_LmsKey_SetParameters(LmsKey * key, int levels,
|
||||
int height, int winternitz);
|
||||
@@ -799,6 +822,8 @@ WOLFSSL_API void wc_LmsKey_Free(LmsKey * key);
|
||||
WOLFSSL_API int wc_LmsKey_GetSigLen(const LmsKey * key, word32 * len);
|
||||
WOLFSSL_API int wc_LmsKey_GetPubLen(const LmsKey * key, word32 * len);
|
||||
WOLFSSL_API int wc_LmsKey_ExportPub(LmsKey * keyDst, const LmsKey * keySrc);
|
||||
WOLFSSL_API int wc_LmsKey_ExportPub_ex(LmsKey * keyDst, const LmsKey * keySrc,
|
||||
void * heap, int devId);
|
||||
WOLFSSL_API int wc_LmsKey_ExportPubRaw(const LmsKey * key, byte * out,
|
||||
word32 * outLen);
|
||||
WOLFSSL_API int wc_LmsKey_ImportPubRaw(LmsKey * key, const byte * in,
|
||||
|
||||
@@ -339,6 +339,13 @@ typedef struct XmssParams {
|
||||
word8 bds_k;
|
||||
} XmssParams;
|
||||
|
||||
#ifndef XMSS_MAX_ID_LEN
|
||||
#define XMSS_MAX_ID_LEN 32
|
||||
#endif
|
||||
#ifndef XMSS_MAX_LABEL_LEN
|
||||
#define XMSS_MAX_LABEL_LEN 32
|
||||
#endif
|
||||
|
||||
typedef struct XmssKey {
|
||||
/* Public key. */
|
||||
unsigned char pk[2 * WC_XMSS_MAX_N];
|
||||
@@ -364,6 +371,20 @@ typedef struct XmssKey {
|
||||
void* heap;
|
||||
/* State of key. */
|
||||
enum wc_XmssState state;
|
||||
#ifdef WOLF_CRYPTO_CB
|
||||
/* Device Identifier. */
|
||||
int devId;
|
||||
/* Per-device opaque context, populated by the callback. */
|
||||
void* devCtx;
|
||||
#endif
|
||||
#ifdef WOLF_PRIVATE_KEY_ID
|
||||
/* Optional device-side key identifier. */
|
||||
byte id[XMSS_MAX_ID_LEN];
|
||||
int idLen;
|
||||
/* Optional device-side key label. */
|
||||
char label[XMSS_MAX_LABEL_LEN];
|
||||
int labelLen;
|
||||
#endif
|
||||
} XmssKey;
|
||||
|
||||
typedef struct XmssState {
|
||||
@@ -405,7 +426,14 @@ typedef struct XmssState {
|
||||
#endif
|
||||
|
||||
WOLFSSL_API int wc_XmssKey_Init(XmssKey* key, void* heap, int devId);
|
||||
#ifdef WOLF_PRIVATE_KEY_ID
|
||||
WOLFSSL_API int wc_XmssKey_InitId(XmssKey* key, const unsigned char* id,
|
||||
int len, void* heap, int devId);
|
||||
WOLFSSL_API int wc_XmssKey_InitLabel(XmssKey* key, const char* label,
|
||||
void* heap, int devId);
|
||||
#endif
|
||||
WOLFSSL_API int wc_XmssKey_SetParamStr(XmssKey* key, const char* str);
|
||||
WOLFSSL_API int wc_XmssKey_GetParamStr(const XmssKey* key, const char** str);
|
||||
#ifndef WOLFSSL_XMSS_VERIFY_ONLY
|
||||
WOLFSSL_API int wc_XmssKey_SetWriteCb(XmssKey* key,
|
||||
wc_xmss_write_private_key_cb write_cb);
|
||||
@@ -423,6 +451,8 @@ WOLFSSL_API void wc_XmssKey_Free(XmssKey* key);
|
||||
WOLFSSL_API int wc_XmssKey_GetSigLen(const XmssKey* key, word32* len);
|
||||
WOLFSSL_API int wc_XmssKey_GetPubLen(const XmssKey* key, word32* len);
|
||||
WOLFSSL_API int wc_XmssKey_ExportPub(XmssKey* keyDst, const XmssKey* keySrc);
|
||||
WOLFSSL_API int wc_XmssKey_ExportPub_ex(XmssKey* keyDst, const XmssKey* keySrc,
|
||||
void* heap, int devId);
|
||||
WOLFSSL_API int wc_XmssKey_ExportPubRaw(const XmssKey* key, byte* out,
|
||||
word32* outLen);
|
||||
WOLFSSL_API int wc_XmssKey_ImportPubRaw(XmssKey* key, const byte* in,
|
||||
|
||||
Reference in New Issue
Block a user