Merge pull request #10514 from kaleb-himes/PQ-DOX

Add PQ documentation
This commit is contained in:
Daniel Pouzzner
2026-06-05 16:23:05 -05:00
committed by GitHub
5 changed files with 2641 additions and 0 deletions
@@ -15,6 +15,70 @@
\defgroup ECC Algorithms - ECC
\defgroup ED25519 Algorithms - ED25519
\defgroup ED448 Algorithms - ED448
\defgroup ML_DSA Algorithms - ML-DSA (FIPS 204)
ML-DSA (Module-Lattice-based Digital Signature Algorithm) is a
quantum-resistant digital signature scheme standardized by NIST as
FIPS 204. The pre-standardization name was Dilithium; legacy
Dilithium type and macro names remain as aliases for unmigrated
consumer code (see <wolfssl/wolfcrypt/dilithium.h>).
ML-DSA defines three parameter sets identified by NIST security
category: ML-DSA-44 (level 2), ML-DSA-65 (level 3) and ML-DSA-87
(level 5). All three are supported by the same wc_MlDsaKey object;
the parameter set is selected with wc_MlDsaKey_SetParams().
\defgroup ML_KEM Algorithms - ML-KEM (FIPS 203)
ML-KEM (Module-Lattice-based Key Encapsulation Mechanism) is a
quantum-resistant key encapsulation mechanism standardized by NIST
as FIPS 203. The pre-standardization name was Kyber; legacy Kyber
type and macro names remain as aliases for unmigrated consumer
code.
ML-KEM defines three parameter sets: ML-KEM-512 (NIST level 1),
ML-KEM-768 (level 3) and ML-KEM-1024 (level 5). The variant is
selected when the key is initialized via wc_MlKemKey_Init() or
wc_MlKemKey_New().
\defgroup SLH_DSA Algorithms - SLH-DSA (FIPS 205)
SLH-DSA (Stateless Hash-based Digital Signature Algorithm) is a
quantum-resistant signature scheme standardized by NIST as
FIPS 205. It descends from the SPHINCS+ submission and is
stateless: signing does not mutate the private key, so there is no
key-state synchronization burden on the application.
Twelve parameter sets are supported, formed by combining a hash
family (SHAKE or SHA2), a security category (128/192/256) and a
speed/size tradeoff (s = small signatures, f = fast signing). The
parameter set is selected when the key is initialized via
wc_SlhDsaKey_Init().
\defgroup LMS Algorithms - LMS / HSS (RFC 8554)
LMS (Leighton-Micali Signatures) and its multi-tree composition
HSS (Hierarchical Signature System) are stateful hash-based
signature schemes specified in RFC 8554 and NIST SP 800-208. Each
signature consumes a one-time component of the private key, so the
application MUST persist the private key state (via the read/write
callbacks registered with wc_LmsKey_SetReadCb() and
wc_LmsKey_SetWriteCb()) between signing operations. Reusing a
one-time key destroys the security of the scheme.
The number of signatures available from a key is bounded by the
parameter set; query the remaining count with
wc_LmsKey_SigsLeft().
\defgroup XMSS Algorithms - XMSS / XMSS^MT (RFC 8391)
XMSS (eXtended Merkle Signature Scheme) and its multi-tree variant
XMSS^MT are stateful hash-based signature schemes specified in
RFC 8391 and NIST SP 800-208. As with LMS, each signature consumes
a one-time component of the private key, so the application MUST
persist the private key state via the callbacks registered with
wc_XmssKey_SetReadCb() and wc_XmssKey_SetWriteCb(). Reusing a
one-time key destroys the security of the scheme.
The number of signatures available from a key is bounded by the
parameter set; query the remaining count with
wc_XmssKey_SigsLeft().
\defgroup ECCSI_Overview Overview of ECCSI
ECCSI (Elliptic Curve-Based Certificateless Signatures for Identity-Based Encryption) is specified in RFC 6507 (https://tools.ietf.org/html/rfc6507).
+643
View File
@@ -0,0 +1,643 @@
/*!
\ingroup LMS
\brief Initializes an LmsKey object. Must be called before any
other LMS/HSS operation. Use wc_LmsKey_Free() to release resources
when done.
LMS (Leighton-Micali Signatures) and the HSS multi-tree
composition (RFC 8554, NIST SP 800-208) are STATEFUL hash-based
signature schemes: each call to wc_LmsKey_Sign() consumes a
one-time component of the private key, and reusing a one-time key
breaks the security of the scheme. Applications MUST persist the
private key state between sign calls; see wc_LmsKey_SetWriteCb()
and wc_LmsKey_SetReadCb().
After init the key is in state WC_LMS_STATE_INITED. The
parameters must be set with wc_LmsKey_SetLmsParm() or
wc_LmsKey_SetParameters() before generating or reloading a key.
\return 0 on success.
\return BAD_FUNC_ARG if key is NULL.
\param [in,out] key Pointer to the LmsKey to initialize.
\param [in] heap Heap hint for dynamic memory allocation. May be
NULL.
\param [in] devId Device identifier for hardware crypto callbacks.
Use INVALID_DEVID for software-only.
_Example_
\code
LmsKey key;
int ret;
ret = wc_LmsKey_Init(&key, NULL, INVALID_DEVID);
if (ret != 0) {
// error initializing key
}
wc_LmsKey_SetLmsParm(&key, WC_LMS_PARM_L2_H10_W8);
// ... use key ...
wc_LmsKey_Free(&key);
\endcode
\sa wc_LmsKey_Free
\sa wc_LmsKey_SetLmsParm
\sa wc_LmsKey_SetParameters
\sa wc_LmsKey_MakeKey
*/
int wc_LmsKey_Init(LmsKey* key, void* heap, int devId);
/*!
\ingroup LMS
\brief Initializes an LmsKey with a device-side key identifier.
Equivalent to wc_LmsKey_Init() but also stashes a binary id that
a crypto callback can use to look up the underlying key material
on the device. Only available when wolfSSL is built with
WOLF_PRIVATE_KEY_ID.
The id is copied into the key object; the caller may free its
buffer immediately after this call returns.
\return 0 on success.
\return BAD_FUNC_ARG if key is NULL, or id is NULL while len > 0.
\return BUFFER_E if len is negative or greater than
LMS_MAX_ID_LEN.
\param [in,out] key Pointer to the LmsKey to initialize.
\param [in] id Pointer to the device-side key identifier bytes.
May be NULL when len is 0.
\param [in] len Number of bytes in id; must be in
[0, LMS_MAX_ID_LEN].
\param [in] heap Heap hint for dynamic memory allocation.
\param [in] devId Device identifier for the crypto callback.
\sa wc_LmsKey_Init
\sa wc_LmsKey_InitLabel
\sa wc_LmsKey_Free
*/
int wc_LmsKey_InitId(LmsKey* key, const unsigned char* id, int len,
void* heap, int devId);
/*!
\ingroup LMS
\brief Initializes an LmsKey with a device-side key label.
Equivalent to wc_LmsKey_Init() but also stashes a label string
that a crypto callback can use to look up the underlying key
material on the device. Only available when wolfSSL is built with
WOLF_PRIVATE_KEY_ID.
\return 0 on success.
\return BAD_FUNC_ARG if key or label is NULL.
\return BUFFER_E if label is empty or longer than
LMS_MAX_LABEL_LEN.
\param [in,out] key Pointer to the LmsKey to initialize.
\param [in] label NUL-terminated device-side key label.
\param [in] heap Heap hint for dynamic memory allocation.
\param [in] devId Device identifier for the crypto callback.
\sa wc_LmsKey_Init
\sa wc_LmsKey_InitId
*/
int wc_LmsKey_InitLabel(LmsKey* key, const char* label, void* heap,
int devId);
/*!
\ingroup LMS
\brief Selects a predefined LMS/HSS parameter set by name. The
enum wc_LmsParm encodes the tree depth (levels), per-tree height,
Winternitz parameter and hash family in a single value. See the
wc_LmsParm definition for the list of names available in a given
build.
\return 0 on success.
\return BAD_FUNC_ARG if key is NULL, or if lmsParm is not
recognized or names a parameter set that was not compiled in.
\return BAD_STATE_E if key is not in state WC_LMS_STATE_INITED.
\param [in,out] key Pointer to an LmsKey in state
WC_LMS_STATE_INITED.
\param [in] lmsParm A wc_LmsParm constant (e.g.
WC_LMS_PARM_L2_H10_W8).
_Example_
\code
LmsKey key;
wc_LmsKey_Init(&key, NULL, INVALID_DEVID);
wc_LmsKey_SetLmsParm(&key, WC_LMS_PARM_L2_H10_W8);
\endcode
\sa wc_LmsKey_SetParameters
\sa wc_LmsKey_GetParameters
\sa wc_LmsKey_ParmToStr
*/
int wc_LmsKey_SetLmsParm(LmsKey* key, enum wc_LmsParm lmsParm);
/*!
\ingroup LMS
\brief Sets the LMS/HSS parameters individually. The default
SHA-256/256 hash is used. For finer control over the hash family
use wc_LmsKey_SetParameters_ex().
The combination of parameters must match one of the allowed sets
in RFC 8554:
- levels: 1..8
- height: 5, 10, 15, 20 (and 25 in some builds)
- winternitz: 1, 2, 4, or 8
The maximum number of signatures available from a key is
2^(levels * height).
\return 0 on success.
\return BAD_FUNC_ARG if key is NULL, or if the requested
parameter combination is not supported in this build.
\return BAD_STATE_E if key is not in state WC_LMS_STATE_INITED.
\param [in,out] key Pointer to an LmsKey in state
WC_LMS_STATE_INITED.
\param [in] levels Number of Merkle-tree levels in the HSS chain.
\param [in] height Height of each individual Merkle tree.
\param [in] winternitz Winternitz parameter (1, 2, 4 or 8).
\sa wc_LmsKey_SetParameters_ex
\sa wc_LmsKey_SetLmsParm
\sa wc_LmsKey_GetParameters
*/
int wc_LmsKey_SetParameters(LmsKey* key, int levels, int height,
int winternitz);
/*!
\ingroup LMS
\brief Sets the LMS/HSS parameters individually with an explicit
hash family selector.
\return 0 on success.
\return BAD_FUNC_ARG if key is NULL, or if the requested
parameter combination is not supported in this build.
\return BAD_STATE_E if key is not in state WC_LMS_STATE_INITED.
\param [in,out] key Pointer to an LmsKey in state
WC_LMS_STATE_INITED.
\param [in] levels Number of Merkle-tree levels.
\param [in] height Height of each tree.
\param [in] winternitz Winternitz parameter (1, 2, 4 or 8).
\param [in] hash Hash family selector identifying SHA-256/256,
SHA-256/192, SHAKE256/256 or SHAKE256/192, as supported by the
build.
\sa wc_LmsKey_SetParameters
\sa wc_LmsKey_GetParameters_ex
*/
int wc_LmsKey_SetParameters_ex(LmsKey* key, int levels, int height,
int winternitz, int hash);
/*!
\ingroup LMS
\brief Retrieves the LMS/HSS parameters previously set on this
key.
\return 0 on success.
\return BAD_FUNC_ARG if any pointer is NULL or no parameters are
set.
\param [in] key Pointer to an LmsKey with parameters set.
\param [out] levels Receives the number of tree levels.
\param [out] height Receives the per-tree height.
\param [out] winternitz Receives the Winternitz parameter.
\sa wc_LmsKey_SetParameters
\sa wc_LmsKey_GetParameters_ex
*/
int wc_LmsKey_GetParameters(const LmsKey* key, int* levels, int* height,
int* winternitz);
/*!
\ingroup LMS
\brief Retrieves the LMS/HSS parameters and hash family selector
from this key.
\return 0 on success.
\return BAD_FUNC_ARG if any pointer is NULL or no parameters are
set.
\param [in] key Pointer to an LmsKey with parameters set.
\param [out] levels Receives the number of tree levels.
\param [out] height Receives the per-tree height.
\param [out] winternitz Receives the Winternitz parameter.
\param [out] hash Receives the hash family selector.
\sa wc_LmsKey_SetParameters_ex
*/
int wc_LmsKey_GetParameters_ex(const LmsKey* key, int* levels, int* height,
int* winternitz, int* hash);
/*!
\ingroup LMS
\brief Registers the callback that wolfSSL invokes to persist
updated private key state. Because LMS/HSS is stateful, the
application MUST persist the private key after each successful
sign before the signature is released to a peer; otherwise a
crash or restart can lead to one-time key reuse and break the
scheme.
The callback receives the encoded private key bytes and returns
one of the wc_LmsRc codes. WC_LMS_RC_SAVED_TO_NV_MEMORY signals a
durable write; other return codes are treated as failures.
\return 0 on success.
\return BAD_FUNC_ARG if key or write_cb is NULL.
\param [in,out] key Pointer to an LmsKey.
\param [in] write_cb Callback invoked to persist the private key.
\sa wc_LmsKey_SetReadCb
\sa wc_LmsKey_SetContext
\sa wc_LmsKey_Sign
*/
int wc_LmsKey_SetWriteCb(LmsKey* key, wc_lms_write_private_key_cb write_cb);
/*!
\ingroup LMS
\brief Registers the callback that wolfSSL invokes to load
persisted private key state. Used by wc_LmsKey_Reload() to bring
a saved key back into memory for further signing.
\return 0 on success.
\return BAD_FUNC_ARG if key or read_cb is NULL.
\param [in,out] key Pointer to an LmsKey.
\param [in] read_cb Callback invoked to load the private key.
\sa wc_LmsKey_SetWriteCb
\sa wc_LmsKey_SetContext
\sa wc_LmsKey_Reload
*/
int wc_LmsKey_SetReadCb(LmsKey* key, wc_lms_read_private_key_cb read_cb);
/*!
\ingroup LMS
\brief Sets the opaque context pointer passed to both the read
and write private-key callbacks. Typically used to carry a file
handle, database connection, or other persistence-layer state.
\return 0 on success.
\return BAD_FUNC_ARG if key is NULL.
\param [in,out] key Pointer to an LmsKey.
\param [in] context Application-defined pointer; may be NULL.
\sa wc_LmsKey_SetReadCb
\sa wc_LmsKey_SetWriteCb
*/
int wc_LmsKey_SetContext(LmsKey* key, void* context);
/*!
\ingroup LMS
\brief Generates a fresh LMS/HSS key pair. Parameters must
already be set (via wc_LmsKey_SetLmsParm() or
wc_LmsKey_SetParameters()) and read/write callbacks must be
registered. The newly generated private key is persisted via the
write callback before the function returns; on success the key
transitions to state WC_LMS_STATE_OK.
Key generation runtime grows quickly with the first tree's
height: a 3-level h=5 tree is much faster than a 1-level h=15
tree even though both yield the same total signature count.
\return 0 on success.
\return BAD_FUNC_ARG if any required pointer is NULL.
\return MEMORY_E on allocation failure.
\param [in,out] key Pointer to an LmsKey in state
WC_LMS_STATE_PARMSET with callbacks set.
\param [in] rng Pointer to an initialized WC_RNG.
_Example_
\code
LmsKey key;
WC_RNG rng;
wc_LmsKey_Init(&key, NULL, INVALID_DEVID);
wc_LmsKey_SetLmsParm(&key, WC_LMS_PARM_L2_H10_W8);
wc_LmsKey_SetWriteCb(&key, my_write_cb);
wc_LmsKey_SetReadCb(&key, my_read_cb);
wc_LmsKey_SetContext(&key, &my_storage);
wc_InitRng(&rng);
if (wc_LmsKey_MakeKey(&key, &rng) != 0) {
// error generating key
}
\endcode
\sa wc_LmsKey_Sign
\sa wc_LmsKey_Reload
*/
int wc_LmsKey_MakeKey(LmsKey* key, WC_RNG* rng);
/*!
\ingroup LMS
\brief Reloads a previously generated LMS/HSS private key from
persistent storage using the registered read callback, restoring
the key to a state where it can sign further messages. On success
the key is in state WC_LMS_STATE_OK.
The same parameters set at key-generation time must be reapplied
to the LmsKey before calling Reload (the persisted blob is just
the private key bytes; the parameter set is metadata the
application owns).
\return 0 on success.
\return BAD_FUNC_ARG if any required pointer is NULL.
\return WC_LMS_RC_* mapped error if the read callback fails.
\param [in,out] key Pointer to an LmsKey with parameters and read
callback set.
\sa wc_LmsKey_MakeKey
\sa wc_LmsKey_SetReadCb
*/
int wc_LmsKey_Reload(LmsKey* key);
/*!
\ingroup LMS
\brief Returns the size in bytes of the encoded private key for
the parameter set selected on this key.
\return 0 on success.
\return BAD_FUNC_ARG if key or len is NULL.
\param [in] key Pointer to an LmsKey with parameters set.
\param [out] len Receives the private key size in bytes.
\sa wc_LmsKey_GetPubLen
\sa wc_LmsKey_GetSigLen
*/
int wc_LmsKey_GetPrivLen(const LmsKey* key, word32* len);
/*!
\ingroup LMS
\brief Returns the size in bytes of the LMS/HSS public key for
the parameter set selected on this key.
\return 0 on success.
\return BAD_FUNC_ARG if key or len is NULL.
\param [in] key Pointer to an LmsKey with parameters set.
\param [out] len Receives the public key size in bytes.
\sa wc_LmsKey_ExportPubRaw
\sa wc_LmsKey_GetPrivLen
*/
int wc_LmsKey_GetPubLen(const LmsKey* key, word32* len);
/*!
\ingroup LMS
\brief Returns the LMS/HSS signature size in bytes for the
parameter set selected on this key.
\return 0 on success.
\return BAD_FUNC_ARG if key or len is NULL.
\param [in] key Pointer to an LmsKey with parameters set.
\param [out] len Receives the signature size in bytes.
\sa wc_LmsKey_Sign
*/
int wc_LmsKey_GetSigLen(const LmsKey* key, word32* len);
/*!
\ingroup LMS
\brief Signs msg with the LMS/HSS private key in key. On entry
*sigSz is the size of the sig buffer; on success it is updated to
the bytes written.
Each successful sign call consumes a one-time component of the
private key. The updated key state is persisted via the
registered write callback BEFORE the new signature is returned to
the caller. If the write callback fails the sign call fails and
the signature is not released. When the supply of one-time keys
is exhausted the key transitions to state WC_LMS_STATE_NOSIGS and
further sign attempts return SIG_OTHER_E (or similar) -- query
wc_LmsKey_SigsLeft() to detect this condition in advance.
\return 0 on success.
\return BAD_FUNC_ARG if any required pointer is NULL.
\return BUFFER_E if *sigSz is smaller than the signature size.
\return -1 (or similar) if all one-time keys have been used.
\param [in,out] key Pointer to an LmsKey in state WC_LMS_STATE_OK.
\param [out] sig Buffer that receives the signature.
\param [in,out] sigSz In: size of sig. Out: bytes written.
\param [in] msg Message to sign.
\param [in] msgSz Length of msg in bytes.
\sa wc_LmsKey_Verify
\sa wc_LmsKey_SigsLeft
\sa wc_LmsKey_SetWriteCb
*/
int wc_LmsKey_Sign(LmsKey* key, byte* sig, word32* sigSz, const byte* msg,
int msgSz);
/*!
\ingroup LMS
\brief Returns the number of one-time signatures still available
from this key. When the count reaches zero the key can no longer
sign and should be retired.
\return Non-negative number of remaining signatures on success.
\return Negative error code on failure (e.g. BAD_FUNC_ARG if key
is NULL).
\param [in,out] key Pointer to an LmsKey in state WC_LMS_STATE_OK.
\sa wc_LmsKey_Sign
*/
int wc_LmsKey_SigsLeft(LmsKey* key);
/*!
\ingroup LMS
\brief Releases resources held by an LmsKey. Safe to call with a
NULL pointer. After this call the key is in state
WC_LMS_STATE_FREED and must be re-initialized before reuse.
\param [in,out] key Pointer to the LmsKey to free.
\sa wc_LmsKey_Init
*/
void wc_LmsKey_Free(LmsKey* key);
/*!
\ingroup LMS
\brief Copies the public part of keySrc into keyDst. The
destination key inherits the same parameters and may be used for
verification; it does not carry the private key state and cannot
sign. Useful for handing a verifier the minimal data it needs.
\return 0 on success.
\return BAD_FUNC_ARG if keyDst or keySrc is NULL.
\param [in,out] keyDst Pointer to an initialized destination
LmsKey.
\param [in] keySrc Pointer to an LmsKey with the public key.
\sa wc_LmsKey_ExportPub_ex
\sa wc_LmsKey_ExportPubRaw
*/
int wc_LmsKey_ExportPub(LmsKey* keyDst, const LmsKey* keySrc);
/*!
\ingroup LMS
\brief Like wc_LmsKey_ExportPub() but the destination key is
initialized fresh with the supplied heap and devId.
\return 0 on success.
\return BAD_FUNC_ARG if keyDst or keySrc is NULL.
\param [in,out] keyDst Pointer to an LmsKey to populate.
\param [in] keySrc Pointer to an LmsKey with the public key.
\param [in] heap Heap hint for keyDst.
\param [in] devId Device identifier for keyDst.
\sa wc_LmsKey_ExportPub
*/
int wc_LmsKey_ExportPub_ex(LmsKey* keyDst, const LmsKey* keySrc, void* heap,
int devId);
/*!
\ingroup LMS
\brief Exports the LMS/HSS public key as a raw byte string. On
entry *outLen is the size of out; on success it is updated to the
bytes written.
\return 0 on success.
\return BAD_FUNC_ARG if any required pointer is NULL.
\return BUFFER_E if *outLen is smaller than the public key size.
\param [in] key Pointer to an LmsKey.
\param [out] out Buffer that receives the public key.
\param [in,out] outLen In: size of out. Out: bytes written.
\sa wc_LmsKey_ImportPubRaw
\sa wc_LmsKey_GetPubLen
*/
int wc_LmsKey_ExportPubRaw(const LmsKey* key, byte* out, word32* outLen);
/*!
\ingroup LMS
\brief Imports a raw LMS/HSS public key into key. The key must be
in state WC_LMS_STATE_INITED. Parameter information is recovered
from the encoded header, after which the key transitions to
state WC_LMS_STATE_VERIFYONLY.
\return 0 on success.
\return BAD_FUNC_ARG if any required pointer is NULL.
\return BUFFER_E if inLen is too small.
\param [in,out] key Pointer to an LmsKey in WC_LMS_STATE_INITED.
\param [in] in Raw public key bytes.
\param [in] inLen Length of in in bytes.
\sa wc_LmsKey_ExportPubRaw
\sa wc_LmsKey_Verify
*/
int wc_LmsKey_ImportPubRaw(LmsKey* key, const byte* in, word32 inLen);
/*!
\ingroup LMS
\brief Verifies an LMS/HSS signature against msg using the public
key held in key. The function returns 0 only when the signature
is valid; any other value indicates the signature was rejected.
\return 0 on a valid signature.
\return BAD_FUNC_ARG if any required pointer is NULL.
\return SIG_VERIFY_E (or similar) if the signature is invalid or
malformed.
\param [in,out] key Pointer to an LmsKey with the public key set.
\param [in] sig Signature bytes to verify.
\param [in] sigSz Length of sig in bytes.
\param [in] msg Message that was signed.
\param [in] msgSz Length of msg in bytes.
\sa wc_LmsKey_Sign
\sa wc_LmsKey_ImportPubRaw
*/
int wc_LmsKey_Verify(LmsKey* key, const byte* sig, word32 sigSz,
const byte* msg, int msgSz);
/*!
\ingroup LMS
\brief Returns a static, NUL-terminated string describing an LMS
parameter set. Useful for logging and diagnostics.
\return Pointer to a static string on success.
\return NULL if lmsParm is not recognized.
\param [in] lmsParm A wc_LmsParm constant.
\sa wc_LmsKey_SetLmsParm
*/
const char* wc_LmsKey_ParmToStr(enum wc_LmsParm lmsParm);
/*!
\ingroup LMS
\brief Returns a pointer to the 16-byte LMS Key Identifier (I)
embedded in the private key, together with its length. The
returned pointer aliases internal key memory and is valid only
until the key is freed.
\return 0 on success.
\return BAD_FUNC_ARG if any required pointer is NULL.
\param [in,out] key Pointer to an LmsKey with a private key.
\param [out] kid Receives a pointer to the I bytes.
\param [out] kidSz Receives the length (16 / WC_LMS_I_LEN).
\sa wc_LmsKey_GetKidFromPrivRaw
*/
int wc_LmsKey_GetKid(LmsKey* key, const byte** kid, word32* kidSz);
/*!
\ingroup LMS
\brief Returns a pointer to the LMS Key Identifier (I) within a
raw encoded private key buffer, without requiring an LmsKey
object. Used to look up the matching state record in persistent
storage during reload.
\return Pointer to the I bytes within priv on success.
\return NULL if priv is NULL or privSz is too small to contain a
valid header.
\param [in] priv Encoded private key bytes.
\param [in] privSz Length of priv in bytes.
\sa wc_LmsKey_GetKid
*/
const byte* wc_LmsKey_GetKidFromPrivRaw(const byte* priv, word32 privSz);
+932
View File
@@ -0,0 +1,932 @@
/*!
\ingroup ML_DSA
\brief Initializes a wc_MlDsaKey object. Must be called before any
other ML-DSA operation. Use wc_MlDsaKey_Free() to release resources
when done.
ML-DSA (FIPS 204) is a quantum-resistant digital signature
algorithm. Three parameter sets are defined and selected via
wc_MlDsaKey_SetParams() after init:
- WC_ML_DSA_44 (NIST security level 2),
- WC_ML_DSA_65 (level 3),
- WC_ML_DSA_87 (level 5).
\return 0 on success.
\return BAD_FUNC_ARG if key is NULL.
\param [in,out] key Pointer to the wc_MlDsaKey to initialize.
\param [in] heap Heap hint for dynamic memory allocation. May be
NULL.
\param [in] devId Device identifier for hardware crypto callbacks.
Use INVALID_DEVID for software-only.
_Example_
\code
wc_MlDsaKey key;
int ret;
ret = wc_MlDsaKey_Init(&key, NULL, INVALID_DEVID);
if (ret != 0) {
// error initializing key
}
ret = wc_MlDsaKey_SetParams(&key, WC_ML_DSA_65);
// ... use key ...
wc_MlDsaKey_Free(&key);
\endcode
\sa wc_MlDsaKey_Free
\sa wc_MlDsaKey_SetParams
\sa wc_MlDsaKey_MakeKey
*/
int wc_MlDsaKey_Init(wc_MlDsaKey* key, void* heap, int devId);
/*!
\ingroup ML_DSA
\brief Allocates and initializes a new wc_MlDsaKey on the heap.
The returned pointer must be released with wc_MlDsaKey_Delete().
Only available when wolfSSL is built without WC_NO_CONSTRUCTORS.
\return Pointer to a freshly allocated wc_MlDsaKey on success.
\return NULL on allocation failure.
\param [in] heap Heap hint for dynamic memory allocation. May be
NULL.
\param [in] devId Device identifier for hardware crypto callbacks.
Use INVALID_DEVID for software-only.
_Example_
\code
wc_MlDsaKey* key = wc_MlDsaKey_New(NULL, INVALID_DEVID);
if (key == NULL) {
// allocation failed
}
// ... use key ...
wc_MlDsaKey_Delete(key, &key);
\endcode
\sa wc_MlDsaKey_Delete
\sa wc_MlDsaKey_Init
*/
wc_MlDsaKey* wc_MlDsaKey_New(void* heap, int devId);
/*!
\ingroup ML_DSA
\brief Frees and zeros a heap-allocated wc_MlDsaKey previously
returned by wc_MlDsaKey_New(). On success the caller's pointer
variable is set to NULL via key_p when key_p is not NULL. Only
available when wolfSSL is built without WC_NO_CONSTRUCTORS.
\return 0 on success.
\return BAD_FUNC_ARG if key is NULL.
\param [in,out] key The wc_MlDsaKey to free.
\param [in,out] key_p Optional address of the caller's pointer
variable; when not NULL, it is set to NULL on success.
\sa wc_MlDsaKey_New
*/
int wc_MlDsaKey_Delete(wc_MlDsaKey* key, wc_MlDsaKey** key_p);
/*!
\ingroup ML_DSA
\brief Initializes a wc_MlDsaKey with a device-side key
identifier. Equivalent to wc_MlDsaKey_Init() but also stashes a
binary id that a crypto callback can use to look up the underlying
key material on the device. Only available when wolfSSL is built
with WOLF_PRIVATE_KEY_ID.
The id is copied into the key object; the caller may free its
buffer immediately after this call returns.
\return 0 on success.
\return BAD_FUNC_ARG if key is NULL.
\return BUFFER_E if len is negative or exceeds MLDSA_MAX_ID_LEN.
\param [in,out] key Pointer to the wc_MlDsaKey to initialize.
\param [in] id Pointer to the device-side key identifier bytes.
May be NULL when len is 0.
\param [in] len Number of bytes in id; must be in
[0, MLDSA_MAX_ID_LEN].
\param [in] heap Heap hint for dynamic memory allocation. May be
NULL.
\param [in] devId Device identifier for the crypto callback.
Should be a registered cb devId, not INVALID_DEVID.
\sa wc_MlDsaKey_Init
\sa wc_MlDsaKey_InitLabel
\sa wc_MlDsaKey_Free
*/
int wc_MlDsaKey_InitId(wc_MlDsaKey* key, const unsigned char* id, int len,
void* heap, int devId);
/*!
\ingroup ML_DSA
\brief Initializes a wc_MlDsaKey with a device-side key label.
Equivalent to wc_MlDsaKey_Init() but also stashes a label string
that a crypto callback can use to look up the underlying key
material on the device. Only available when wolfSSL is built with
WOLF_PRIVATE_KEY_ID.
The label length is taken via XSTRLEN, so embedded NUL bytes
terminate the label.
\return 0 on success.
\return BAD_FUNC_ARG if key or label is NULL.
\return BUFFER_E if label is empty or longer than
MLDSA_MAX_LABEL_LEN.
\param [in,out] key Pointer to the wc_MlDsaKey to initialize.
\param [in] label NUL-terminated device-side key label string.
\param [in] heap Heap hint for dynamic memory allocation. May be
NULL.
\param [in] devId Device identifier for the crypto callback.
\sa wc_MlDsaKey_Init
\sa wc_MlDsaKey_InitId
\sa wc_MlDsaKey_Free
*/
int wc_MlDsaKey_InitLabel(wc_MlDsaKey* key, const char* label, void* heap,
int devId);
/*!
\ingroup ML_DSA
\brief Selects the ML-DSA parameter set for this key. Must be
called after wc_MlDsaKey_Init() and before key generation, signing
or verifying.
\return 0 on success.
\return BAD_FUNC_ARG if key is NULL or level is not a recognized
parameter set.
\return NOT_COMPILED_IN if level names a parameter set that was
disabled at build time.
\param [in,out] key Pointer to an initialized wc_MlDsaKey.
\param [in] level Parameter set: WC_ML_DSA_44, WC_ML_DSA_65 or
WC_ML_DSA_87.
\sa wc_MlDsaKey_GetParams
\sa wc_MlDsaKey_Init
*/
int wc_MlDsaKey_SetParams(wc_MlDsaKey* key, byte level);
/*!
\ingroup ML_DSA
\brief Retrieves the ML-DSA parameter set currently selected on
this key.
\return 0 on success.
\return BAD_FUNC_ARG if key or level is NULL.
\param [in] key Pointer to an initialized wc_MlDsaKey.
\param [out] level Receives WC_ML_DSA_44, WC_ML_DSA_65 or
WC_ML_DSA_87.
\sa wc_MlDsaKey_SetParams
*/
int wc_MlDsaKey_GetParams(wc_MlDsaKey* key, byte* level);
/*!
\ingroup ML_DSA
\brief Releases resources held by a wc_MlDsaKey. After this call
the object must be re-initialized with wc_MlDsaKey_Init() before
it can be used again. Safe to call with a NULL pointer.
\param [in,out] key Pointer to the wc_MlDsaKey to free.
\sa wc_MlDsaKey_Init
*/
void wc_MlDsaKey_Free(wc_MlDsaKey* key);
/*!
\ingroup ML_DSA
\brief Generates a new ML-DSA key pair using the provided RNG.
The parameter set must already be set with wc_MlDsaKey_SetParams().
Both the public and private key components are populated on
success.
\return 0 on success.
\return BAD_FUNC_ARG if key or rng is NULL.
\return MEMORY_E on allocation failure.
\param [in,out] key Pointer to a wc_MlDsaKey with parameters set.
\param [in] rng Pointer to an initialized WC_RNG.
_Example_
\code
wc_MlDsaKey key;
WC_RNG rng;
wc_MlDsaKey_Init(&key, NULL, INVALID_DEVID);
wc_MlDsaKey_SetParams(&key, WC_ML_DSA_65);
wc_InitRng(&rng);
if (wc_MlDsaKey_MakeKey(&key, &rng) != 0) {
// error generating key pair
}
\endcode
\sa wc_MlDsaKey_MakeKeyFromSeed
\sa wc_MlDsaKey_SetParams
*/
int wc_MlDsaKey_MakeKey(wc_MlDsaKey* key, WC_RNG* rng);
/*!
\ingroup ML_DSA
\brief Deterministically generates an ML-DSA key pair from a
32-byte seed. Useful for known-answer tests and for applications
that derive the seed from another secret. The seed buffer must
contain exactly 32 bytes.
\return 0 on success.
\return BAD_FUNC_ARG if key or seed is NULL.
\param [in,out] key Pointer to a wc_MlDsaKey with parameters set.
\param [in] seed Pointer to a 32-byte seed buffer.
\sa wc_MlDsaKey_MakeKey
*/
int wc_MlDsaKey_MakeKeyFromSeed(wc_MlDsaKey* key, const byte* seed);
/*!
\ingroup ML_DSA
\brief Signs a message with ML-DSA using the FIPS 204
randomized-with-context signing API. Pass ctx=NULL and ctxLen=0
for an empty context.
On entry *sigLen is the size of the sig buffer; on success it is
updated to the number of bytes written. Use wc_MlDsaKey_SigSize()
or wc_MlDsaKey_GetSigLen() to determine the required buffer size.
\return 0 on success.
\return BAD_FUNC_ARG if any required pointer is NULL or ctxLen is
invalid.
\return BUFFER_E if the sig buffer is too small.
\param [in,out] key Pointer to a wc_MlDsaKey with the private key.
\param [in] ctx Optional context string (may be NULL when
ctxLen=0).
\param [in] ctxLen Length of ctx in bytes; must be 0 when ctx is
NULL, and no greater than 255.
\param [out] sig Buffer that receives the signature.
\param [in,out] sigLen In: size of sig. Out: bytes written.
\param [in] msg Message to sign.
\param [in] msgLen Length of msg in bytes.
\param [in] rng Pointer to an initialized WC_RNG.
\sa wc_MlDsaKey_VerifyCtx
\sa wc_MlDsaKey_SignCtxWithSeed
\sa wc_MlDsaKey_SignCtxHash
*/
int wc_MlDsaKey_SignCtx(wc_MlDsaKey* key, const byte* ctx, byte ctxLen,
byte* sig, word32* sigLen, const byte* msg, word32 msgLen, WC_RNG* rng);
/*!
\ingroup ML_DSA
\brief HashML-DSA signing variant: signs a pre-hashed message.
The caller supplies the hash bytes and identifies the hash
algorithm. This is the "pre-hash" mode of FIPS 204.
\return 0 on success.
\return BAD_FUNC_ARG if any required pointer is NULL, ctxLen is
invalid, or hashAlg is not supported.
\return BUFFER_E if the sig buffer is too small.
\param [in,out] key Pointer to a wc_MlDsaKey with the private key.
\param [in] ctx Optional context string (NULL when ctxLen=0).
\param [in] ctxLen Length of ctx in bytes; no greater than 255.
\param [out] sig Buffer that receives the signature.
\param [in,out] sigLen In: size of sig. Out: bytes written.
\param [in] hash The message digest to sign.
\param [in] hashLen Length of hash in bytes.
\param [in] hashAlg Hash algorithm identifier (e.g. WC_HASH_TYPE_SHA256).
\param [in] rng Pointer to an initialized WC_RNG.
\sa wc_MlDsaKey_SignCtx
\sa wc_MlDsaKey_VerifyCtxHash
*/
int wc_MlDsaKey_SignCtxHash(wc_MlDsaKey* key, const byte* ctx, byte ctxLen,
byte* sig, word32* sigLen, const byte* hash, word32 hashLen,
int hashAlg, WC_RNG* rng);
/*!
\ingroup ML_DSA
\brief Legacy ML-DSA signing API without a context parameter.
Only available when wolfSSL is built with WOLFSSL_MLDSA_NO_CTX.
New code should call wc_MlDsaKey_SignCtx() with ctx=NULL and
ctxLen=0 for a FIPS 204 compliant empty-context signature.
\return See wc_MlDsaKey_SignCtx().
\param [in,out] key Pointer to a wc_MlDsaKey with the private key.
\param [out] sig Buffer that receives the signature.
\param [in,out] sigLen In: size of sig. Out: bytes written.
\param [in] msg Message to sign.
\param [in] msgLen Length of msg in bytes.
\param [in] rng Pointer to an initialized WC_RNG.
\sa wc_MlDsaKey_SignCtx
\sa wc_MlDsaKey_Verify
*/
int wc_MlDsaKey_Sign(wc_MlDsaKey* key, byte* sig, word32* sigLen,
const byte* msg, word32 msgLen, WC_RNG* rng);
/*!
\ingroup ML_DSA
\brief Deterministic signing variant of wc_MlDsaKey_SignCtx(). The
32-byte seed replaces the randomness an RNG would supply, so the
same key/ctx/msg/seed always produces the same signature.
\return See wc_MlDsaKey_SignCtx().
\param [in,out] key Pointer to a wc_MlDsaKey with the private key.
\param [in] ctx Optional context string (NULL when ctxLen=0).
\param [in] ctxLen Length of ctx; no greater than 255.
\param [out] sig Buffer that receives the signature.
\param [in,out] sigLen In: size of sig. Out: bytes written.
\param [in] msg Message to sign.
\param [in] msgLen Length of msg in bytes.
\param [in] seed 32-byte seed bytes.
\sa wc_MlDsaKey_SignCtx
\sa wc_MlDsaKey_SignCtxHashWithSeed
*/
int wc_MlDsaKey_SignCtxWithSeed(wc_MlDsaKey* key, const byte* ctx, byte ctxLen,
byte* sig, word32* sigLen, const byte* msg, word32 msgLen,
const byte* seed);
/*!
\ingroup ML_DSA
\brief Deterministic HashML-DSA signing: like
wc_MlDsaKey_SignCtxHash() but uses the supplied 32-byte seed in
place of an RNG.
\return See wc_MlDsaKey_SignCtxHash().
\param [in,out] key Pointer to a wc_MlDsaKey with the private key.
\param [in] ctx Optional context string (NULL when ctxLen=0).
\param [in] ctxLen Length of ctx; no greater than 255.
\param [out] sig Buffer that receives the signature.
\param [in,out] sigLen In: size of sig. Out: bytes written.
\param [in] hash The message digest to sign.
\param [in] hashLen Length of hash in bytes.
\param [in] hashAlg Hash algorithm identifier.
\param [in] seed 32-byte seed bytes.
\sa wc_MlDsaKey_SignCtxHash
*/
int wc_MlDsaKey_SignCtxHashWithSeed(wc_MlDsaKey* key, const byte* ctx,
byte ctxLen, byte* sig, word32* sigLen, const byte* hash,
word32 hashLen, int hashAlg, const byte* seed);
/*!
\ingroup ML_DSA
\brief Signs a pre-computed mu value (the externally derived
SHAKE256 hash of (tr || ctx || msg) per FIPS 204) using a
deterministic 32-byte seed. Used by protocols that need to split
the message-hashing step from the signing step.
\return 0 on success.
\return BAD_FUNC_ARG if any required pointer is NULL or muLen is
not 64.
\return BUFFER_E if the sig buffer is too small.
\param [in,out] key Pointer to a wc_MlDsaKey with the private key.
\param [out] sig Buffer that receives the signature.
\param [in,out] sigLen In: size of sig. Out: bytes written.
\param [in] mu The 64-byte mu value (SHAKE256 output).
\param [in] muLen Length of mu; must be 64.
\param [in] seed 32-byte seed bytes.
\sa wc_MlDsaKey_VerifyMu
*/
int wc_MlDsaKey_SignMuWithSeed(wc_MlDsaKey* key, byte* sig, word32* sigLen,
const byte* mu, word32 muLen, const byte* seed);
/*!
\ingroup ML_DSA
\brief Legacy seed-based signing API without a context parameter.
Only available when wolfSSL is built with WOLFSSL_MLDSA_NO_CTX.
New code should use wc_MlDsaKey_SignCtxWithSeed().
\return See wc_MlDsaKey_SignCtxWithSeed().
\param [in,out] key Pointer to a wc_MlDsaKey with the private key.
\param [out] sig Buffer that receives the signature.
\param [in,out] sigLen In: size of sig. Out: bytes written.
\param [in] msg Message to sign.
\param [in] msgLen Length of msg in bytes.
\param [in] seed 32-byte seed bytes.
\sa wc_MlDsaKey_SignCtxWithSeed
*/
int wc_MlDsaKey_SignWithSeed(wc_MlDsaKey* key, byte* sig, word32* sigLen,
const byte* msg, word32 msgLen, const byte* seed);
/*!
\ingroup ML_DSA
\brief Verifies an ML-DSA signature produced by
wc_MlDsaKey_SignCtx() or one of its variants. On entry res is set
to 0; on success it is set to 1 when the signature is valid and
left at 0 otherwise. The function's return value reports whether
verification could be carried out at all; a bad signature is NOT a
function-level error.
\return 0 if verification completed (check res for the result).
\return BAD_FUNC_ARG if any required pointer is NULL or ctxLen is
invalid.
\param [in,out] key Pointer to a wc_MlDsaKey with the public key.
\param [in] sig Signature bytes to verify.
\param [in] sigLen Length of sig in bytes.
\param [in] ctx Optional context string (NULL when ctxLen=0).
\param [in] ctxLen Length of ctx; no greater than 255.
\param [in] msg Message that was signed.
\param [in] msgLen Length of msg in bytes.
\param [out] res Set to 1 on a valid signature, 0 otherwise.
\sa wc_MlDsaKey_SignCtx
\sa wc_MlDsaKey_VerifyCtxHash
\sa wc_MlDsaKey_VerifyMu
*/
int wc_MlDsaKey_VerifyCtx(wc_MlDsaKey* key, const byte* sig, word32 sigLen,
const byte* ctx, byte ctxLen, const byte* msg, word32 msgLen, int* res);
/*!
\ingroup ML_DSA
\brief Verifies a HashML-DSA signature where the message digest
was supplied directly. See wc_MlDsaKey_VerifyCtx() for the
semantics of res.
\return 0 if verification completed (check res for the result).
\return BAD_FUNC_ARG if any required pointer is NULL, ctxLen is
invalid, or hashAlg is unsupported.
\param [in,out] key Pointer to a wc_MlDsaKey with the public key.
\param [in] sig Signature bytes to verify.
\param [in] sigLen Length of sig in bytes.
\param [in] ctx Optional context string (NULL when ctxLen=0).
\param [in] ctxLen Length of ctx; no greater than 255.
\param [in] hash The message digest that was signed.
\param [in] hashLen Length of hash in bytes.
\param [in] hashAlg Hash algorithm identifier.
\param [out] res Set to 1 on a valid signature, 0 otherwise.
\sa wc_MlDsaKey_SignCtxHash
\sa wc_MlDsaKey_VerifyCtx
*/
int wc_MlDsaKey_VerifyCtxHash(wc_MlDsaKey* key, const byte* sig, word32 sigLen,
const byte* ctx, byte ctxLen, const byte* hash, word32 hashLen,
int hashAlg, int* res);
/*!
\ingroup ML_DSA
\brief Verifies a signature over a pre-computed 64-byte mu value
(see wc_MlDsaKey_SignMuWithSeed()). See wc_MlDsaKey_VerifyCtx()
for the semantics of res.
\return 0 if verification completed (check res for the result).
\return BAD_FUNC_ARG if any required pointer is NULL or muLen is
not 64.
\param [in,out] key Pointer to a wc_MlDsaKey with the public key.
\param [in] sig Signature bytes to verify.
\param [in] sigLen Length of sig in bytes.
\param [in] mu The 64-byte mu value.
\param [in] muLen Length of mu; must be 64.
\param [out] res Set to 1 on a valid signature, 0 otherwise.
\sa wc_MlDsaKey_SignMuWithSeed
*/
int wc_MlDsaKey_VerifyMu(wc_MlDsaKey* key, const byte* sig, word32 sigLen,
const byte* mu, word32 muLen, int* res);
/*!
\ingroup ML_DSA
\brief Legacy ML-DSA verify API without a context parameter. Only
available when wolfSSL is built with WOLFSSL_MLDSA_NO_CTX. New
code should use wc_MlDsaKey_VerifyCtx() with ctx=NULL and
ctxLen=0.
\return See wc_MlDsaKey_VerifyCtx().
\param [in,out] key Pointer to a wc_MlDsaKey with the public key.
\param [in] sig Signature bytes to verify.
\param [in] sigLen Length of sig in bytes.
\param [in] msg Message that was signed.
\param [in] msgLen Length of msg in bytes.
\param [out] res Set to 1 on a valid signature, 0 otherwise.
\sa wc_MlDsaKey_VerifyCtx
\sa wc_MlDsaKey_Sign
*/
int wc_MlDsaKey_Verify(wc_MlDsaKey* key, const byte* sig, word32 sigLen,
const byte* msg, word32 msgLen, int* res);
/*!
\ingroup ML_DSA
\brief Returns the size in bytes of the encoded private key for
the parameter set selected on this key. Equivalent to
wc_MlDsaKey_PrivSize() and provided for API compatibility.
\return Encoded private key size in bytes on success (positive
value).
\return BAD_FUNC_ARG if key is NULL or no parameter set is
selected.
\param [in] key Pointer to a wc_MlDsaKey with parameters set.
\sa wc_MlDsaKey_PrivSize
\sa wc_MlDsaKey_PubSize
\sa wc_MlDsaKey_SigSize
*/
int wc_MlDsaKey_Size(wc_MlDsaKey* key);
/*!
\ingroup ML_DSA
\brief Returns the size in bytes of the encoded private key for
the parameter set selected on this key.
\return Encoded private key size on success (positive value).
\return BAD_FUNC_ARG if key is NULL or no parameter set is
selected.
\param [in] key Pointer to a wc_MlDsaKey with parameters set.
\sa wc_MlDsaKey_PubSize
\sa wc_MlDsaKey_GetPrivLen
*/
int wc_MlDsaKey_PrivSize(wc_MlDsaKey* key);
/*!
\ingroup ML_DSA
\brief Returns the size in bytes of the encoded public key for the
parameter set selected on this key.
\return Encoded public key size on success (positive value).
\return BAD_FUNC_ARG if key is NULL or no parameter set is
selected.
\param [in] key Pointer to a wc_MlDsaKey with parameters set.
\sa wc_MlDsaKey_PrivSize
\sa wc_MlDsaKey_GetPubLen
*/
int wc_MlDsaKey_PubSize(wc_MlDsaKey* key);
/*!
\ingroup ML_DSA
\brief Returns the size in bytes of the signature produced by
this key's parameter set.
\return Signature size on success (positive value).
\return BAD_FUNC_ARG if key is NULL or no parameter set is
selected.
\param [in] key Pointer to a wc_MlDsaKey with parameters set.
\sa wc_MlDsaKey_GetSigLen
\sa wc_MlDsaKey_SignCtx
*/
int wc_MlDsaKey_SigSize(wc_MlDsaKey* key);
/*!
\ingroup ML_DSA
\brief Writes the encoded private key size into *len. Equivalent
information to wc_MlDsaKey_PrivSize() but uses an out-parameter
style.
\return 0 on success.
\return BAD_FUNC_ARG if key or len is NULL, or no parameter set is
selected.
\param [in] key Pointer to a wc_MlDsaKey with parameters set.
\param [out] len Receives the private key size in bytes.
\sa wc_MlDsaKey_PrivSize
*/
int wc_MlDsaKey_GetPrivLen(wc_MlDsaKey* key, int* len);
/*!
\ingroup ML_DSA
\brief Writes the encoded public key size into *len. Equivalent
information to wc_MlDsaKey_PubSize() but uses an out-parameter
style.
\return 0 on success.
\return BAD_FUNC_ARG if key or len is NULL, or no parameter set is
selected.
\param [in] key Pointer to a wc_MlDsaKey with parameters set.
\param [out] len Receives the public key size in bytes.
\sa wc_MlDsaKey_PubSize
*/
int wc_MlDsaKey_GetPubLen(wc_MlDsaKey* key, int* len);
/*!
\ingroup ML_DSA
\brief Writes the signature size into *len. Equivalent
information to wc_MlDsaKey_SigSize() but uses an out-parameter
style.
\return 0 on success.
\return BAD_FUNC_ARG if key or len is NULL, or no parameter set is
selected.
\param [in] key Pointer to a wc_MlDsaKey with parameters set.
\param [out] len Receives the signature size in bytes.
\sa wc_MlDsaKey_SigSize
*/
int wc_MlDsaKey_GetSigLen(wc_MlDsaKey* key, int* len);
/*!
\ingroup ML_DSA
\brief Self-checks an ML-DSA key by recomputing the public key
from the private and comparing against the stored public. Only
available when wolfSSL is built with WOLFSSL_MLDSA_CHECK_KEY.
\return 0 if the key is consistent.
\return BAD_FUNC_ARG if key is NULL.
\return PUBLIC_KEY_E if the recomputed public does not match.
\param [in] key Pointer to a wc_MlDsaKey with both public and
private parts populated.
*/
int wc_MlDsaKey_CheckKey(wc_MlDsaKey* key);
/*!
\ingroup ML_DSA
\brief Imports a raw ML-DSA public key. The parameter set must
already be selected on the key. inLen must match the size returned
by wc_MlDsaKey_PubSize() for the selected parameter set.
\return 0 on success.
\return BAD_FUNC_ARG if key or in is NULL.
\return BUFFER_E if inLen does not match the expected public key
size.
\param [in,out] key Pointer to a wc_MlDsaKey with parameters set.
\param [in] in Raw public key bytes.
\param [in] inLen Length of in in bytes.
\sa wc_MlDsaKey_ExportPubRaw
\sa wc_MlDsaKey_ImportPrivRaw
*/
int wc_MlDsaKey_ImportPubRaw(wc_MlDsaKey* key, const byte* in, word32 inLen);
/*!
\ingroup ML_DSA
\brief Imports a raw ML-DSA private key. The parameter set must
already be selected. privSz must match the size returned by
wc_MlDsaKey_PrivSize().
\return 0 on success.
\return BAD_FUNC_ARG if key or priv is NULL.
\return BUFFER_E if privSz does not match the expected private key
size.
\param [in,out] key Pointer to a wc_MlDsaKey with parameters set.
\param [in] priv Raw private key bytes.
\param [in] privSz Length of priv in bytes.
\sa wc_MlDsaKey_ExportPrivRaw
\sa wc_MlDsaKey_ImportKey
*/
int wc_MlDsaKey_ImportPrivRaw(wc_MlDsaKey* key, const byte* priv,
word32 privSz);
/*!
\ingroup ML_DSA
\brief Imports a raw ML-DSA key pair (private and public parts
together). The parameter set must already be selected.
\return 0 on success.
\return BAD_FUNC_ARG if any required pointer is NULL.
\return BUFFER_E if privSz or pubSz does not match the expected
sizes.
\param [in,out] key Pointer to a wc_MlDsaKey with parameters set.
\param [in] priv Raw private key bytes.
\param [in] privSz Length of priv.
\param [in] pub Raw public key bytes.
\param [in] pubSz Length of pub.
\sa wc_MlDsaKey_ExportKey
*/
int wc_MlDsaKey_ImportKey(wc_MlDsaKey* key, const byte* priv, word32 privSz,
const byte* pub, word32 pubSz);
/*!
\ingroup ML_DSA
\brief Exports the raw ML-DSA public key. On entry *outLen is the
size of out; on success it is updated to the bytes written.
\return 0 on success.
\return BAD_FUNC_ARG if any required pointer is NULL.
\return BUFFER_E if *outLen is smaller than the public key size.
\param [in] key Pointer to a wc_MlDsaKey with a public key.
\param [out] out Buffer that receives the public key.
\param [in,out] outLen In: size of out. Out: bytes written.
\sa wc_MlDsaKey_ImportPubRaw
*/
int wc_MlDsaKey_ExportPubRaw(wc_MlDsaKey* key, byte* out, word32* outLen);
/*!
\ingroup ML_DSA
\brief Exports the raw ML-DSA private key. On entry *outLen is the
size of out; on success it is updated to the bytes written.
\return 0 on success.
\return BAD_FUNC_ARG if any required pointer is NULL.
\return BUFFER_E if *outLen is smaller than the private key size.
\param [in] key Pointer to a wc_MlDsaKey with a private key.
\param [out] out Buffer that receives the private key.
\param [in,out] outLen In: size of out. Out: bytes written.
\sa wc_MlDsaKey_ImportPrivRaw
*/
int wc_MlDsaKey_ExportPrivRaw(wc_MlDsaKey* key, byte* out, word32* outLen);
/*!
\ingroup ML_DSA
\brief Exports both raw public and private ML-DSA key components
in one call.
\return 0 on success.
\return BAD_FUNC_ARG if any required pointer is NULL.
\return BUFFER_E if either buffer is too small.
\param [in] key Pointer to a wc_MlDsaKey with both key parts.
\param [out] priv Buffer that receives the private key.
\param [in,out] privSz In: size of priv. Out: bytes written.
\param [out] pub Buffer that receives the public key.
\param [in,out] pubSz In: size of pub. Out: bytes written.
\sa wc_MlDsaKey_ImportKey
*/
int wc_MlDsaKey_ExportKey(wc_MlDsaKey* key, byte* priv, word32 *privSz,
byte* pub, word32 *pubSz);
/*!
\ingroup ML_DSA
\brief Parses an ML-DSA private key from a DER/ASN.1 encoded
buffer (PKCS#8 OneAsymmetricKey). The parameter set is inferred
from the algorithm identifier in the encoding, so it does NOT
need to be set beforehand. On success *inOutIdx is advanced past
the consumed bytes.
Only available when WOLFSSL_MLDSA_NO_ASN1 is not defined.
\return 0 on success.
\return BAD_FUNC_ARG if any required pointer is NULL.
\return ASN_PARSE_E on malformed encoding.
\param [in,out] key Pointer to an initialized wc_MlDsaKey.
\param [in] input DER-encoded private key bytes.
\param [in] inSz Length of input in bytes.
\param [in,out] inOutIdx In: offset into input where decoding
starts. Out: offset past the consumed bytes.
\sa wc_MlDsaKey_PrivateKeyToDer
\sa wc_MlDsaKey_PublicKeyDecode
*/
int wc_MlDsaKey_PrivateKeyDecode(wc_MlDsaKey* key, const byte* input,
word32 inSz, word32* inOutIdx);
/*!
\ingroup ML_DSA
\brief Parses an ML-DSA public key from a DER/ASN.1 encoded
buffer (SubjectPublicKeyInfo). The parameter set is inferred from
the algorithm identifier. On success *inOutIdx is advanced past
the consumed bytes.
\return 0 on success.
\return BAD_FUNC_ARG if any required pointer is NULL.
\return ASN_PARSE_E on malformed encoding.
\param [in,out] key Pointer to an initialized wc_MlDsaKey.
\param [in] input DER-encoded SPKI bytes.
\param [in] inSz Length of input in bytes.
\param [in,out] inOutIdx In: offset into input where decoding
starts. Out: offset past the consumed bytes.
\sa wc_MlDsaKey_PublicKeyToDer
*/
int wc_MlDsaKey_PublicKeyDecode(wc_MlDsaKey* key, const byte* input,
word32 inSz, word32* inOutIdx);
/*!
\ingroup ML_DSA
\brief Encodes an ML-DSA public key to DER. When withAlg is
non-zero the output is a full SubjectPublicKeyInfo (with
AlgorithmIdentifier); when zero the output is the raw public key
bytes.
Pass NULL as output to query the required buffer size.
\return Size of the encoded DER in bytes on success.
\return BAD_FUNC_ARG if key is NULL or no parameter set is
selected.
\return BUFFER_E if output is non-NULL and inLen is smaller than
the required size.
\param [in] key Pointer to a wc_MlDsaKey with a public key.
\param [out] output Buffer that receives the DER encoding, or
NULL to query size.
\param [in] inLen Size of output (ignored when output is NULL).
\param [in] withAlg Non-zero to emit SubjectPublicKeyInfo, zero
for the raw public key only.
\sa wc_MlDsaKey_PublicKeyDecode
\sa wc_MlDsaKey_KeyToDer
*/
int wc_MlDsaKey_PublicKeyToDer(wc_MlDsaKey* key, byte* output,
word32 inLen, int withAlg);
/*!
\ingroup ML_DSA
\brief Encodes an ML-DSA key pair (public + private) to DER as a
PKCS#8 OneAsymmetricKey structure. Pass NULL as output to query
the required buffer size.
\return Size of the encoded DER in bytes on success.
\return BAD_FUNC_ARG if key is NULL or no parameter set is
selected.
\return MISSING_KEY if the private key has not been set.
\return BUFFER_E if output is non-NULL and inLen is too small.
\param [in] key Pointer to a wc_MlDsaKey with the private key.
\param [out] output Buffer that receives the DER encoding, or
NULL to query size.
\param [in] inLen Size of output (ignored when output is NULL).
\sa wc_MlDsaKey_PrivateKeyDecode
\sa wc_MlDsaKey_PrivateKeyToDer
\sa wc_MlDsaKey_PublicKeyToDer
*/
int wc_MlDsaKey_KeyToDer(wc_MlDsaKey* key, byte* output, word32 inLen);
/*!
\ingroup ML_DSA
\brief Encodes the ML-DSA private key to DER. Per FIPS 204 the
private key encoding includes the public component, so this
function is currently an alias of wc_MlDsaKey_KeyToDer() kept for
API parity with other algorithms.
\return Size of the encoded DER in bytes on success.
\return Inherited error codes from wc_MlDsaKey_KeyToDer().
\param [in] key Pointer to a wc_MlDsaKey with the private key.
\param [out] output Buffer that receives the DER encoding, or
NULL to query size.
\param [in] inLen Size of output (ignored when output is NULL).
\sa wc_MlDsaKey_KeyToDer
\sa wc_MlDsaKey_PrivateKeyDecode
*/
int wc_MlDsaKey_PrivateKeyToDer(wc_MlDsaKey* key, byte* output,
word32 inLen);
+472
View File
@@ -0,0 +1,472 @@
/*!
\ingroup ML_KEM
\brief Allocates and initializes a new MlKemKey on the heap. The
returned pointer must be released with wc_MlKemKey_Delete().
ML-KEM (FIPS 203) is a quantum-resistant key encapsulation
mechanism. The type parameter selects the variant: WC_ML_KEM_512
(NIST security level 1), WC_ML_KEM_768 (level 3) or
WC_ML_KEM_1024 (level 5).
\return Pointer to a freshly allocated MlKemKey on success.
\return NULL on allocation failure or if type is invalid.
\param [in] type ML-KEM variant: WC_ML_KEM_512, WC_ML_KEM_768 or
WC_ML_KEM_1024.
\param [in] heap Heap hint for dynamic memory allocation. May be
NULL.
\param [in] devId Device identifier for hardware crypto callbacks.
Use INVALID_DEVID for software-only.
_Example_
\code
MlKemKey* key = wc_MlKemKey_New(WC_ML_KEM_768, NULL,
INVALID_DEVID);
if (key == NULL) {
// allocation failed
}
// ... use key ...
wc_MlKemKey_Delete(key, &key);
\endcode
\sa wc_MlKemKey_Delete
\sa wc_MlKemKey_Init
*/
MlKemKey* wc_MlKemKey_New(int type, void* heap, int devId);
/*!
\ingroup ML_KEM
\brief Frees and zeros a heap-allocated MlKemKey previously
returned by wc_MlKemKey_New(). On success the caller's pointer
variable is set to NULL via key_p when key_p is not NULL.
\return 0 on success.
\return BAD_FUNC_ARG if key is NULL.
\param [in,out] key The MlKemKey to free.
\param [in,out] key_p Optional address of the caller's pointer
variable; when not NULL, it is set to NULL on success.
\sa wc_MlKemKey_New
*/
int wc_MlKemKey_Delete(MlKemKey* key, MlKemKey** key_p);
/*!
\ingroup ML_KEM
\brief Initializes an MlKemKey object in place. The type parameter
selects the ML-KEM variant and must be one of WC_ML_KEM_512,
WC_ML_KEM_768 or WC_ML_KEM_1024.
\return 0 on success.
\return BAD_FUNC_ARG if key is NULL or type is invalid.
\return NOT_COMPILED_IN if type names a variant that was disabled
at build time.
\param [in,out] key Pointer to the MlKemKey to initialize.
\param [in] type ML-KEM variant: WC_ML_KEM_512, WC_ML_KEM_768 or
WC_ML_KEM_1024.
\param [in] heap Heap hint for dynamic memory allocation. May be
NULL.
\param [in] devId Device identifier for hardware crypto callbacks.
_Example_
\code
MlKemKey key;
int ret;
ret = wc_MlKemKey_Init(&key, WC_ML_KEM_768, NULL, INVALID_DEVID);
if (ret != 0) {
// error initializing key
}
// ... use key ...
wc_MlKemKey_Free(&key);
\endcode
\sa wc_MlKemKey_Free
\sa wc_MlKemKey_MakeKey
*/
int wc_MlKemKey_Init(MlKemKey* key, int type, void* heap, int devId);
/*!
\ingroup ML_KEM
\brief Releases resources held by an MlKemKey. After this call
the object must be re-initialized with wc_MlKemKey_Init() before
it can be used again. Safe to call with a NULL pointer.
\return 0 on success, including when key is NULL.
\param [in,out] key Pointer to the MlKemKey to free.
\sa wc_MlKemKey_Init
*/
int wc_MlKemKey_Free(MlKemKey* key);
/*!
\ingroup ML_KEM
\brief Initializes an MlKemKey with a device-side key identifier.
Equivalent to wc_MlKemKey_Init() but also stashes a binary id that
a crypto callback can use to look up the underlying key material
on the device. Only available when wolfSSL is built with
WOLF_PRIVATE_KEY_ID.
The id is copied into the key object; the caller may free its
buffer immediately after this call returns.
\return 0 on success.
\return BAD_FUNC_ARG if key is NULL, if id is NULL while len is
non-zero, or if type is invalid.
\return BUFFER_E if len is negative or exceeds MLKEM_MAX_ID_LEN.
\param [in,out] key Pointer to the MlKemKey to initialize.
\param [in] type ML-KEM variant identifier.
\param [in] id Pointer to the device-side key identifier bytes.
May be NULL when len is 0.
\param [in] len Number of bytes in id. Must be in the range
[0, MLKEM_MAX_ID_LEN].
\param [in] heap Heap hint for dynamic memory allocation.
\param [in] devId Device identifier for the crypto callback.
\sa wc_MlKemKey_Init
\sa wc_MlKemKey_Init_Label
\sa wc_MlKemKey_Free
*/
int wc_MlKemKey_Init_Id(MlKemKey* key, int type, const unsigned char* id,
int len, void* heap, int devId);
/*!
\ingroup ML_KEM
\brief Initializes an MlKemKey with a device-side key label.
Equivalent to wc_MlKemKey_Init() but also stashes a label string
that a crypto callback can use to look up the underlying key
material on the device. Only available when wolfSSL is built with
WOLF_PRIVATE_KEY_ID.
\return 0 on success.
\return BAD_FUNC_ARG if key or label is NULL or type is invalid.
\param [in,out] key Pointer to the MlKemKey to initialize.
\param [in] type ML-KEM variant identifier.
\param [in] label NUL-terminated device-side key label.
\param [in] heap Heap hint for dynamic memory allocation.
\param [in] devId Device identifier for the crypto callback.
\sa wc_MlKemKey_Init
\sa wc_MlKemKey_Init_Id
\sa wc_MlKemKey_Free
*/
int wc_MlKemKey_Init_Label(MlKemKey* key, int type, const char* label,
void* heap, int devId);
/*!
\ingroup ML_KEM
\brief Generates a new ML-KEM key pair using the provided RNG.
Both the public and private components are populated on success.
\return 0 on success.
\return BAD_FUNC_ARG if key or rng is NULL.
\return MEMORY_E on allocation failure.
\param [in,out] key Pointer to an initialized MlKemKey.
\param [in] rng Pointer to an initialized WC_RNG.
_Example_
\code
MlKemKey key;
WC_RNG rng;
wc_MlKemKey_Init(&key, WC_ML_KEM_768, NULL, INVALID_DEVID);
wc_InitRng(&rng);
if (wc_MlKemKey_MakeKey(&key, &rng) != 0) {
// error generating key pair
}
\endcode
\sa wc_MlKemKey_MakeKeyWithRandom
\sa wc_MlKemKey_Encapsulate
\sa wc_MlKemKey_Decapsulate
*/
int wc_MlKemKey_MakeKey(MlKemKey* key, WC_RNG* rng);
/*!
\ingroup ML_KEM
\brief Deterministic key generation: produces an ML-KEM key pair
from the supplied 64 bytes of randomness instead of an RNG. Useful
for known-answer tests and for applications that derive key
randomness from another secret.
\return 0 on success.
\return BAD_FUNC_ARG if any required pointer is NULL or len is
not 64.
\param [in,out] key Pointer to an initialized MlKemKey.
\param [in] rand Pointer to a buffer of randomness.
\param [in] len Length of rand in bytes; must be 64.
\sa wc_MlKemKey_MakeKey
*/
int wc_MlKemKey_MakeKeyWithRandom(MlKemKey* key, const unsigned char* rand,
int len);
/*!
\ingroup ML_KEM
\brief Returns the ciphertext size in bytes for the variant
selected on this key.
\return 0 on success.
\return BAD_FUNC_ARG if key or len is NULL.
\param [in] key Pointer to an initialized MlKemKey.
\param [out] len Receives the ciphertext size in bytes.
\sa wc_MlKemKey_SharedSecretSize
\sa wc_MlKemKey_Encapsulate
*/
int wc_MlKemKey_CipherTextSize(MlKemKey* key, word32* len);
/*!
\ingroup ML_KEM
\brief Returns the shared-secret size in bytes for ML-KEM. The
value is the same (32 bytes) across all parameter sets but is
queried programmatically for symmetry with
wc_MlKemKey_CipherTextSize().
\return 0 on success.
\return BAD_FUNC_ARG if key or len is NULL.
\param [in] key Pointer to an initialized MlKemKey.
\param [out] len Receives the shared-secret size in bytes.
\sa wc_MlKemKey_CipherTextSize
*/
int wc_MlKemKey_SharedSecretSize(MlKemKey* key, word32* len);
/*!
\ingroup ML_KEM
\brief Encapsulates a fresh shared secret against the public key
held in key. Produces a ciphertext that the holder of the
corresponding private key can pass to wc_MlKemKey_Decapsulate() to
recover the same shared secret.
The ct buffer must be at least wc_MlKemKey_CipherTextSize() bytes
and ss must be at least wc_MlKemKey_SharedSecretSize() bytes.
\return 0 on success.
\return BAD_FUNC_ARG if any required pointer is NULL.
\return BAD_STATE_E if the public key has not been set.
\return NOT_COMPILED_IN if wolfSSL was built with WC_NO_RNG.
\return MEMORY_E on allocation failure inside the encapsulation
routine.
\param [in,out] key Pointer to an MlKemKey containing a public key.
\param [out] ct Buffer that receives the ciphertext.
\param [out] ss Buffer that receives the 32-byte shared secret.
\param [in] rng Pointer to an initialized WC_RNG.
_Example_
\code
MlKemKey key;
unsigned char ct[WC_ML_KEM_768_CIPHER_TEXT_SIZE];
unsigned char ss[WC_ML_KEM_SS_SZ];
// ... key holds the recipient's public key ...
if (wc_MlKemKey_Encapsulate(&key, ct, ss, &rng) != 0) {
// error during encapsulation
}
// Send ct to the holder of the matching private key.
\endcode
\sa wc_MlKemKey_EncapsulateWithRandom
\sa wc_MlKemKey_Decapsulate
*/
int wc_MlKemKey_Encapsulate(MlKemKey* key, unsigned char* ct,
unsigned char* ss, WC_RNG* rng);
/*!
\ingroup ML_KEM
\brief Deterministic variant of wc_MlKemKey_Encapsulate(). Uses
the supplied 32 bytes of randomness instead of consuming output
from an RNG.
\return 0 on success.
\return BAD_FUNC_ARG if any required pointer is NULL or len is
not 32.
\param [in,out] key Pointer to an MlKemKey containing a public key.
\param [out] ct Buffer that receives the ciphertext.
\param [out] ss Buffer that receives the 32-byte shared secret.
\param [in] rand Buffer of randomness.
\param [in] len Length of rand in bytes; must be 32.
\sa wc_MlKemKey_Encapsulate
*/
int wc_MlKemKey_EncapsulateWithRandom(MlKemKey* key, unsigned char* ct,
unsigned char* ss, const unsigned char* rand, int len);
/*!
\ingroup ML_KEM
\brief Decapsulates a ciphertext using the private key held in key
and recovers the shared secret produced by
wc_MlKemKey_Encapsulate(). ML-KEM decapsulation is constant time
and includes an implicit-rejection check on malformed ciphertexts
(an attacker cannot learn the validity of ct from the runtime).
The ss buffer must be at least wc_MlKemKey_SharedSecretSize()
bytes and ct must be exactly wc_MlKemKey_CipherTextSize() bytes.
\return 0 on success (a shared secret was written to ss).
\return BAD_FUNC_ARG if any required pointer is NULL.
\return BAD_STATE_E if the private key has not been set.
\return BUFFER_E if len does not match the expected ciphertext
size for the configured ML-KEM variant.
\return NOT_COMPILED_IN if the key's ML-KEM variant was disabled
at build time.
\return MEMORY_E on allocation failure.
\param [in,out] key Pointer to an MlKemKey with the private key.
\param [out] ss Buffer that receives the 32-byte shared secret.
\param [in] ct The ciphertext to decapsulate.
\param [in] len Length of ct in bytes.
\sa wc_MlKemKey_Encapsulate
\sa wc_MlKemKey_CipherTextSize
*/
int wc_MlKemKey_Decapsulate(MlKemKey* key, unsigned char* ss,
const unsigned char* ct, word32 len);
/*!
\ingroup ML_KEM
\brief Decodes a raw ML-KEM private key into key. The variant must
already be selected on the key (typically via wc_MlKemKey_Init()
or wc_MlKemKey_New()) and len must match the private key size for
that variant.
\return 0 on success.
\return BAD_FUNC_ARG if any required pointer is NULL or len does
not match the expected size.
\param [in,out] key Pointer to an initialized MlKemKey.
\param [in] in Raw private key bytes.
\param [in] len Length of in in bytes.
\sa wc_MlKemKey_EncodePrivateKey
\sa wc_MlKemKey_PrivateKeySize
*/
int wc_MlKemKey_DecodePrivateKey(MlKemKey* key, const unsigned char* in,
word32 len);
/*!
\ingroup ML_KEM
\brief Decodes a raw ML-KEM public key into key. The variant must
already be selected on the key and len must match the public key
size for that variant.
\return 0 on success.
\return BAD_FUNC_ARG if any required pointer is NULL or len does
not match the expected size.
\param [in,out] key Pointer to an initialized MlKemKey.
\param [in] in Raw public key bytes.
\param [in] len Length of in in bytes.
\sa wc_MlKemKey_EncodePublicKey
\sa wc_MlKemKey_PublicKeySize
*/
int wc_MlKemKey_DecodePublicKey(MlKemKey* key, const unsigned char* in,
word32 len);
/*!
\ingroup ML_KEM
\brief Returns the encoded private key size in bytes for the
variant selected on this key.
\return 0 on success.
\return BAD_FUNC_ARG if key or len is NULL.
\param [in] key Pointer to an initialized MlKemKey.
\param [out] len Receives the private key size in bytes.
\sa wc_MlKemKey_PublicKeySize
*/
int wc_MlKemKey_PrivateKeySize(MlKemKey* key, word32* len);
/*!
\ingroup ML_KEM
\brief Returns the encoded public key size in bytes for the
variant selected on this key.
\return 0 on success.
\return BAD_FUNC_ARG if key or len is NULL.
\param [in] key Pointer to an initialized MlKemKey.
\param [out] len Receives the public key size in bytes.
\sa wc_MlKemKey_PrivateKeySize
*/
int wc_MlKemKey_PublicKeySize(MlKemKey* key, word32* len);
/*!
\ingroup ML_KEM
\brief Encodes the ML-KEM private key into out. The out buffer
length must be exactly wc_MlKemKey_PrivateKeySize() bytes.
\return 0 on success.
\return BAD_FUNC_ARG if any required pointer is NULL.
\return BAD_STATE_E if the private and public keys are not both
set on the key object.
\return BUFFER_E if len does not exactly equal the encoded
private key size for the configured ML-KEM variant.
\return NOT_COMPILED_IN if the key's ML-KEM variant was disabled
at build time.
\param [in] key Pointer to an MlKemKey with a private key.
\param [out] out Buffer that receives the encoded private key.
\param [in] len Length of out in bytes.
\sa wc_MlKemKey_DecodePrivateKey
\sa wc_MlKemKey_PrivateKeySize
*/
int wc_MlKemKey_EncodePrivateKey(MlKemKey* key, unsigned char* out,
word32 len);
/*!
\ingroup ML_KEM
\brief Encodes the ML-KEM public key into out. The out buffer
length must be exactly wc_MlKemKey_PublicKeySize() bytes.
\return 0 on success.
\return BAD_FUNC_ARG if any required pointer is NULL.
\return BAD_STATE_E if the public key has not been set.
\return BUFFER_E if len does not exactly equal the encoded public
key size for the configured ML-KEM variant.
\return NOT_COMPILED_IN if the key's ML-KEM variant was disabled
at build time.
\param [in] key Pointer to an MlKemKey with a public key.
\param [out] out Buffer that receives the encoded public key.
\param [in] len Length of out in bytes.
\sa wc_MlKemKey_DecodePublicKey
\sa wc_MlKemKey_PublicKeySize
*/
int wc_MlKemKey_EncodePublicKey(MlKemKey* key, unsigned char* out,
word32 len);
+530
View File
@@ -0,0 +1,530 @@
/*!
\ingroup XMSS
\brief Initializes an XmssKey object. Must be called before any
other XMSS/XMSS^MT operation. Use wc_XmssKey_Free() to release
resources when done.
XMSS (eXtended Merkle Signature Scheme) and its multi-tree
variant XMSS^MT (RFC 8391, NIST SP 800-208) are STATEFUL
hash-based signature schemes: each call to wc_XmssKey_Sign()
consumes a one-time component of the private key, and reusing a
one-time key destroys the security of the scheme. Applications
MUST persist the private key state between sign calls; see
wc_XmssKey_SetWriteCb() and wc_XmssKey_SetReadCb().
After init the key is in state WC_XMSS_STATE_INITED. The
parameter set must be selected by name with
wc_XmssKey_SetParamStr() before generating or reloading a key.
\return 0 on success.
\return BAD_FUNC_ARG if key is NULL.
\param [in,out] key Pointer to the XmssKey to initialize.
\param [in] heap Heap hint for dynamic memory allocation. May be
NULL.
\param [in] devId Device identifier for hardware crypto callbacks.
Use INVALID_DEVID for software-only.
_Example_
\code
XmssKey key;
int ret;
ret = wc_XmssKey_Init(&key, NULL, INVALID_DEVID);
if (ret != 0) {
// error initializing key
}
wc_XmssKey_SetParamStr(&key, "XMSS-SHA2_10_256");
// ... use key ...
wc_XmssKey_Free(&key);
\endcode
\sa wc_XmssKey_Free
\sa wc_XmssKey_SetParamStr
\sa wc_XmssKey_MakeKey
*/
int wc_XmssKey_Init(XmssKey* key, void* heap, int devId);
/*!
\ingroup XMSS
\brief Initializes an XmssKey with a device-side key identifier.
Equivalent to wc_XmssKey_Init() but also stashes a binary id that
a crypto callback can use to look up the underlying key material
on the device. Only available when wolfSSL is built with
WOLF_PRIVATE_KEY_ID.
The id is copied into the key object; the caller may free its
buffer immediately after this call returns.
\return 0 on success.
\return BAD_FUNC_ARG if key is NULL, or id is NULL while len > 0.
\return BUFFER_E if len is negative or greater than
XMSS_MAX_ID_LEN.
\param [in,out] key Pointer to the XmssKey to initialize.
\param [in] id Pointer to the device-side key identifier bytes.
\param [in] len Number of bytes in id; must be in
[0, XMSS_MAX_ID_LEN].
\param [in] heap Heap hint for dynamic memory allocation.
\param [in] devId Device identifier for the crypto callback.
\sa wc_XmssKey_Init
\sa wc_XmssKey_InitLabel
\sa wc_XmssKey_Free
*/
int wc_XmssKey_InitId(XmssKey* key, const unsigned char* id, int len,
void* heap, int devId);
/*!
\ingroup XMSS
\brief Initializes an XmssKey with a device-side key label.
Equivalent to wc_XmssKey_Init() but also stashes a label string
that a crypto callback can use to look up the underlying key
material on the device. Only available when wolfSSL is built with
WOLF_PRIVATE_KEY_ID.
\return 0 on success.
\return BAD_FUNC_ARG if key or label is NULL.
\return BUFFER_E if label is empty or longer than
XMSS_MAX_LABEL_LEN.
\param [in,out] key Pointer to the XmssKey to initialize.
\param [in] label NUL-terminated device-side key label.
\param [in] heap Heap hint for dynamic memory allocation.
\param [in] devId Device identifier for the crypto callback.
\sa wc_XmssKey_Init
\sa wc_XmssKey_InitId
*/
int wc_XmssKey_InitLabel(XmssKey* key, const char* label, void* heap,
int devId);
/*!
\ingroup XMSS
\brief Selects an XMSS or XMSS^MT parameter set by its RFC 8391
name. Accepted names take the form
"XMSS-<hash>_<height>_<n>" (single-tree) or
"XMSSMT-<hash>_<total_height>/<layers>_<n>" (multi-tree), for
example "XMSS-SHA2_10_256" or "XMSSMT-SHA2_20/2_256". The set of
names actually accepted depends on the hash families and tree
heights enabled at build time.
\return 0 on success.
\return BAD_FUNC_ARG if key or str is NULL, or if the named
parameter set is unknown or not compiled in.
\return BAD_STATE_E if key is not in state WC_XMSS_STATE_INITED.
\param [in,out] key Pointer to an XmssKey in state
WC_XMSS_STATE_INITED.
\param [in] str Parameter set name (NUL-terminated).
_Example_
\code
XmssKey key;
wc_XmssKey_Init(&key, NULL, INVALID_DEVID);
wc_XmssKey_SetParamStr(&key, "XMSS-SHA2_10_256");
\endcode
\sa wc_XmssKey_GetParamStr
\sa wc_XmssKey_MakeKey
*/
int wc_XmssKey_SetParamStr(XmssKey* key, const char* str);
/*!
\ingroup XMSS
\brief Retrieves the parameter set name currently selected on
this key. The returned pointer is a static string and must not be
freed by the caller.
\return 0 on success.
\return BAD_FUNC_ARG if key or str is NULL, or no parameter set
has been selected.
\param [in] key Pointer to an XmssKey with a parameter set
selected.
\param [out] str Receives a pointer to a static parameter name
string.
\sa wc_XmssKey_SetParamStr
*/
int wc_XmssKey_GetParamStr(const XmssKey* key, const char** str);
/*!
\ingroup XMSS
\brief Registers the callback that wolfSSL invokes to persist
updated private key state. Because XMSS/XMSS^MT is stateful, the
application MUST persist the private key after each successful
sign before the signature is released; otherwise a crash or
restart can lead to one-time key reuse and break the scheme.
The callback returns one of the wc_XmssRc codes;
WC_XMSS_RC_SAVED_TO_NV_MEMORY signals a durable write.
\return 0 on success.
\return BAD_FUNC_ARG if key or write_cb is NULL.
\param [in,out] key Pointer to an XmssKey.
\param [in] write_cb Callback invoked to persist the private key.
\sa wc_XmssKey_SetReadCb
\sa wc_XmssKey_SetContext
\sa wc_XmssKey_Sign
*/
int wc_XmssKey_SetWriteCb(XmssKey* key, wc_xmss_write_private_key_cb write_cb);
/*!
\ingroup XMSS
\brief Registers the callback that wolfSSL invokes to load
persisted private key state. Used by wc_XmssKey_Reload() to bring
a saved key back into memory for further signing.
\return 0 on success.
\return BAD_FUNC_ARG if key or read_cb is NULL.
\param [in,out] key Pointer to an XmssKey.
\param [in] read_cb Callback invoked to load the private key.
\sa wc_XmssKey_SetWriteCb
\sa wc_XmssKey_Reload
*/
int wc_XmssKey_SetReadCb(XmssKey* key, wc_xmss_read_private_key_cb read_cb);
/*!
\ingroup XMSS
\brief Sets the opaque context pointer passed to both the read
and write private-key callbacks.
\return 0 on success.
\return BAD_FUNC_ARG if key is NULL.
\param [in,out] key Pointer to an XmssKey.
\param [in] context Application-defined pointer; may be NULL.
\sa wc_XmssKey_SetReadCb
\sa wc_XmssKey_SetWriteCb
*/
int wc_XmssKey_SetContext(XmssKey* key, void* context);
/*!
\ingroup XMSS
\brief Generates a fresh XMSS/XMSS^MT key pair. The parameter set
must already be selected via wc_XmssKey_SetParamStr() and the
read/write callbacks must be registered. The newly generated
private key is persisted via the write callback before the
function returns; on success the key transitions to state
WC_XMSS_STATE_OK.
Key generation can be slow for large tree heights; XMSS^MT
variants amortize the cost over multiple smaller trees and
generate noticeably faster than equivalent single-tree XMSS
parameter sets.
\return 0 on success.
\return BAD_FUNC_ARG if any required pointer is NULL.
\return MEMORY_E on allocation failure.
\param [in,out] key Pointer to an XmssKey in state
WC_XMSS_STATE_PARMSET with callbacks set.
\param [in] rng Pointer to an initialized WC_RNG.
_Example_
\code
XmssKey key;
WC_RNG rng;
wc_XmssKey_Init(&key, NULL, INVALID_DEVID);
wc_XmssKey_SetParamStr(&key, "XMSS-SHA2_10_256");
wc_XmssKey_SetWriteCb(&key, my_write_cb);
wc_XmssKey_SetReadCb(&key, my_read_cb);
wc_XmssKey_SetContext(&key, &my_storage);
wc_InitRng(&rng);
if (wc_XmssKey_MakeKey(&key, &rng) != 0) {
// error generating key
}
\endcode
\sa wc_XmssKey_Sign
\sa wc_XmssKey_Reload
*/
int wc_XmssKey_MakeKey(XmssKey* key, WC_RNG* rng);
/*!
\ingroup XMSS
\brief Reloads a previously generated XMSS/XMSS^MT private key
from persistent storage using the registered read callback,
restoring the key to a state where it can sign further messages.
On success the key is in state WC_XMSS_STATE_OK.
The same parameter set selected at key-generation time must be
reapplied with wc_XmssKey_SetParamStr() before calling Reload.
\return 0 on success.
\return BAD_FUNC_ARG if any required pointer is NULL.
\return WC_XMSS_RC_* mapped error if the read callback fails.
\param [in,out] key Pointer to an XmssKey with parameters and
read callback set.
\sa wc_XmssKey_MakeKey
\sa wc_XmssKey_SetReadCb
*/
int wc_XmssKey_Reload(XmssKey* key);
/*!
\ingroup XMSS
\brief Returns the size in bytes of the encoded private key for
the parameter set selected on this key.
\return 0 on success.
\return BAD_FUNC_ARG if key or len is NULL.
\param [in] key Pointer to an XmssKey with parameters set.
\param [out] len Receives the private key size in bytes.
\sa wc_XmssKey_GetPubLen
\sa wc_XmssKey_GetSigLen
*/
int wc_XmssKey_GetPrivLen(const XmssKey* key, word32* len);
/*!
\ingroup XMSS
\brief Returns the size in bytes of the XMSS/XMSS^MT public key
for the parameter set selected on this key.
\return 0 on success.
\return BAD_FUNC_ARG if key or len is NULL.
\param [in] key Pointer to an XmssKey with parameters set.
\param [out] len Receives the public key size in bytes.
\sa wc_XmssKey_ExportPubRaw
*/
int wc_XmssKey_GetPubLen(const XmssKey* key, word32* len);
/*!
\ingroup XMSS
\brief Returns the signature size in bytes for the parameter set
selected on this key.
\return 0 on success.
\return BAD_FUNC_ARG if key or len is NULL.
\param [in] key Pointer to an XmssKey with parameters set.
\param [out] len Receives the signature size in bytes.
\sa wc_XmssKey_Sign
*/
int wc_XmssKey_GetSigLen(const XmssKey* key, word32* len);
/*!
\ingroup XMSS
\brief Signs msg with the XMSS/XMSS^MT private key in key. On
entry *sigSz is the size of the sig buffer; on success it is
updated to the bytes written.
Each successful sign call consumes a one-time component of the
private key. The updated key state is persisted via the
registered write callback BEFORE the new signature is returned to
the caller. If the write callback fails the sign call fails and
the signature is not released. When the supply of one-time keys
is exhausted the key transitions to state WC_XMSS_STATE_NOSIGS
and further sign attempts fail -- query wc_XmssKey_SigsLeft() to
detect this condition in advance.
\return 0 on success.
\return BAD_FUNC_ARG if any required pointer is NULL.
\return BUFFER_E if *sigSz is smaller than the signature size.
\return Negative error if all one-time keys have been used.
\param [in,out] key Pointer to an XmssKey in state
WC_XMSS_STATE_OK.
\param [out] sig Buffer that receives the signature.
\param [in,out] sigSz In: size of sig. Out: bytes written.
\param [in] msg Message to sign.
\param [in] msgSz Length of msg in bytes.
\sa wc_XmssKey_Verify
\sa wc_XmssKey_SigsLeft
\sa wc_XmssKey_SetWriteCb
*/
int wc_XmssKey_Sign(XmssKey* key, byte* sig, word32* sigSz, const byte* msg,
int msgSz);
/*!
\ingroup XMSS
\brief Returns the number of one-time signatures still available
from this key. When the count reaches zero the key can no longer
sign and should be retired.
\return Non-negative number of remaining signatures on success.
\return Negative error code on failure (e.g. BAD_FUNC_ARG if key
is NULL).
\param [in,out] key Pointer to an XmssKey in state
WC_XMSS_STATE_OK.
\sa wc_XmssKey_Sign
*/
int wc_XmssKey_SigsLeft(XmssKey* key);
/*!
\ingroup XMSS
\brief Releases resources held by an XmssKey. Safe to call with a
NULL pointer. After this call the key is in state
WC_XMSS_STATE_FREED and must be re-initialized before reuse.
\param [in,out] key Pointer to the XmssKey to free.
\sa wc_XmssKey_Init
*/
void wc_XmssKey_Free(XmssKey* key);
/*!
\ingroup XMSS
\brief Copies the public part of keySrc into keyDst. The
destination key inherits the same parameter set and may be used
for verification; it does not carry the private key state and
cannot sign. Useful for handing a verifier the minimal data it
needs.
\return 0 on success.
\return BAD_FUNC_ARG if keyDst or keySrc is NULL.
\param [in,out] keyDst Pointer to an initialized destination
XmssKey.
\param [in] keySrc Pointer to an XmssKey with the public key.
\sa wc_XmssKey_ExportPub_ex
\sa wc_XmssKey_ExportPubRaw
*/
int wc_XmssKey_ExportPub(XmssKey* keyDst, const XmssKey* keySrc);
/*!
\ingroup XMSS
\brief Like wc_XmssKey_ExportPub() but the destination key is
initialized fresh with the supplied heap and devId.
\return 0 on success.
\return BAD_FUNC_ARG if keyDst or keySrc is NULL.
\param [in,out] keyDst Pointer to an XmssKey to populate.
\param [in] keySrc Pointer to an XmssKey with the public key.
\param [in] heap Heap hint for keyDst.
\param [in] devId Device identifier for keyDst.
\sa wc_XmssKey_ExportPub
*/
int wc_XmssKey_ExportPub_ex(XmssKey* keyDst, const XmssKey* keySrc,
void* heap, int devId);
/*!
\ingroup XMSS
\brief Exports the XMSS/XMSS^MT public key as a raw byte string.
On entry *outLen is the size of out; on success it is updated to
the bytes written.
\return 0 on success.
\return BAD_FUNC_ARG if any required pointer is NULL.
\return BUFFER_E if *outLen is smaller than the public key size.
\param [in] key Pointer to an XmssKey.
\param [out] out Buffer that receives the public key.
\param [in,out] outLen In: size of out. Out: bytes written.
\sa wc_XmssKey_ImportPubRaw
\sa wc_XmssKey_GetPubLen
*/
int wc_XmssKey_ExportPubRaw(const XmssKey* key, byte* out, word32* outLen);
/*!
\ingroup XMSS
\brief Imports a raw XMSS public key into key. The key must be in
state WC_XMSS_STATE_INITED and the parameter set must already be
selected (the raw encoding does NOT carry the parameter set, so
the caller must apply it via wc_XmssKey_SetParamStr() first). On
success the key transitions to state WC_XMSS_STATE_VERIFYONLY.
\return 0 on success.
\return BAD_FUNC_ARG if any required pointer is NULL.
\return BUFFER_E if inLen does not match the expected public key
size.
\param [in,out] key Pointer to an XmssKey with a parameter set.
\param [in] in Raw public key bytes.
\param [in] inLen Length of in in bytes.
\sa wc_XmssKey_ImportPubRaw_ex
\sa wc_XmssKey_ExportPubRaw
\sa wc_XmssKey_Verify
*/
int wc_XmssKey_ImportPubRaw(XmssKey* key, const byte* in, word32 inLen);
/*!
\ingroup XMSS
\brief Like wc_XmssKey_ImportPubRaw() but explicitly declares
whether the encoded key is single-tree XMSS or multi-tree XMSS^MT
(pass non-zero for XMSS^MT, zero for XMSS).
\return 0 on success.
\return BAD_FUNC_ARG if any required pointer is NULL.
\return BUFFER_E if inLen does not match the expected public key
size.
\param [in,out] key Pointer to an XmssKey with a parameter set.
\param [in] in Raw public key bytes.
\param [in] inLen Length of in in bytes.
\param [in] is_xmssmt Non-zero if the key is XMSS^MT, zero if
plain XMSS.
\sa wc_XmssKey_ImportPubRaw
*/
int wc_XmssKey_ImportPubRaw_ex(XmssKey* key, const byte* in, word32 inLen,
int is_xmssmt);
/*!
\ingroup XMSS
\brief Verifies an XMSS/XMSS^MT signature against msg using the
public key held in key. The function returns 0 only when the
signature is valid; any other value indicates the signature was
rejected.
\return 0 on a valid signature.
\return BAD_FUNC_ARG if any required pointer is NULL.
\return SIG_VERIFY_E (or similar) if the signature is invalid or
malformed.
\param [in,out] key Pointer to an XmssKey with the public key.
\param [in] sig Signature bytes to verify.
\param [in] sigSz Length of sig in bytes.
\param [in] msg Message that was signed.
\param [in] msgSz Length of msg in bytes.
\sa wc_XmssKey_Sign
\sa wc_XmssKey_ImportPubRaw
*/
int wc_XmssKey_Verify(XmssKey* key, const byte* sig, word32 sigSz,
const byte* msg, int msgSz);