From adc8d8fe531a43fc26f7501dea5087ad184848f2 Mon Sep 17 00:00:00 2001 From: kaleb-himes Date: Thu, 21 May 2026 11:15:11 -0700 Subject: [PATCH] Add PQ documentation Co-Pilot feedback --- .../header_files/doxygen_groups.h | 64 ++ doc/dox_comments/header_files/wc_lms.h | 643 ++++++++++++ doc/dox_comments/header_files/wc_mldsa.h | 932 ++++++++++++++++++ doc/dox_comments/header_files/wc_mlkem.h | 472 +++++++++ doc/dox_comments/header_files/wc_xmss.h | 530 ++++++++++ 5 files changed, 2641 insertions(+) create mode 100644 doc/dox_comments/header_files/wc_lms.h create mode 100644 doc/dox_comments/header_files/wc_mldsa.h create mode 100644 doc/dox_comments/header_files/wc_mlkem.h create mode 100644 doc/dox_comments/header_files/wc_xmss.h diff --git a/doc/dox_comments/header_files/doxygen_groups.h b/doc/dox_comments/header_files/doxygen_groups.h index c9469fe186..1f308964f9 100644 --- a/doc/dox_comments/header_files/doxygen_groups.h +++ b/doc/dox_comments/header_files/doxygen_groups.h @@ -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 ). + + 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). diff --git a/doc/dox_comments/header_files/wc_lms.h b/doc/dox_comments/header_files/wc_lms.h new file mode 100644 index 0000000000..485b964dbc --- /dev/null +++ b/doc/dox_comments/header_files/wc_lms.h @@ -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); diff --git a/doc/dox_comments/header_files/wc_mldsa.h b/doc/dox_comments/header_files/wc_mldsa.h new file mode 100644 index 0000000000..9a6be48153 --- /dev/null +++ b/doc/dox_comments/header_files/wc_mldsa.h @@ -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); diff --git a/doc/dox_comments/header_files/wc_mlkem.h b/doc/dox_comments/header_files/wc_mlkem.h new file mode 100644 index 0000000000..08aac84050 --- /dev/null +++ b/doc/dox_comments/header_files/wc_mlkem.h @@ -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); diff --git a/doc/dox_comments/header_files/wc_xmss.h b/doc/dox_comments/header_files/wc_xmss.h new file mode 100644 index 0000000000..7af2666ed7 --- /dev/null +++ b/doc/dox_comments/header_files/wc_xmss.h @@ -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-__" (single-tree) or + "XMSSMT-_/_" (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);