/* * Copyright (C) 2022 - 2026, Stephan Mueller * * License: see LICENSE file in root directory * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ /* * This code is derived in parts from the code distribution provided with * https://github.com/pq-crystals/sphincs * * That code is released under Public Domain * (https://creativecommons.org/share-your-work/public-domain/cc0/); * or Apache 2.0 License (https://www.apache.org/licenses/LICENSE-2.0.html). */ #ifndef LC_SPHINCS_H #define LC_SPHINCS_H #include "ext_headers.h" #include "lc_status.h" #if defined __has_include #if __has_include("lc_sphincs_shake_256s.h") #include "lc_sphincs_shake_256s.h" #define LC_SPHINCS_SHAKE_256s_ENABLED #endif #if __has_include("lc_sphincs_shake_256f.h") #include "lc_sphincs_shake_256f.h" #define LC_SPHINCS_SHAKE_256f_ENABLED #endif #if __has_include("lc_sphincs_shake_192s.h") #include "lc_sphincs_shake_192s.h" #define LC_SPHINCS_SHAKE_192s_ENABLED #endif #if __has_include("lc_sphincs_shake_192f.h") #include "lc_sphincs_shake_192f.h" #define LC_SPHINCS_SHAKE_192f_ENABLED #endif #if __has_include("lc_sphincs_shake_128s.h") #include "lc_sphincs_shake_128s.h" #define LC_SPHINCS_SHAKE_128s_ENABLED #endif #if __has_include("lc_sphincs_shake_128f.h") #include "lc_sphincs_shake_128f.h" #define LC_SPHINCS_SHAKE_128f_ENABLED #endif #else #error "Compiler misses __has_include" #endif #ifdef __cplusplus extern "C" { #endif enum lc_sphincs_type { /** Unknown key type */ LC_SPHINCS_UNKNOWN, /** Sphincs 256s using SHAKE for signature operation */ LC_SPHINCS_SHAKE_256s, /** Sphincs 256f using SHAKE for signature operation */ LC_SPHINCS_SHAKE_256f, /** Sphincs 192s using SHAKE for signature operation */ LC_SPHINCS_SHAKE_192s, /** Sphincs 192f using SHAKE for signature operation */ LC_SPHINCS_SHAKE_192f, /** Sphincs 128s using SHAKE for signature operation */ LC_SPHINCS_SHAKE_128s, /** Sphincs 128f using SHAKE for signature operation */ LC_SPHINCS_SHAKE_128f, }; /** @defgroup Sphincs SLH-DSA Signature Mechanism * * \note Although the API uses the term "sphincs", the implementation provides * Sphincs Plus and complies with FIPS 205. Thus the terms Sphincs and SLH-DSA * are used interchangeably. * * Sphincs API concept * * The Sphincs API is accessible via the following header files with the * mentioned purpose. * * * lc_sphincs.h: This API is the generic API allowing the caller to select * which Sphincs type (Sphincs 256s, 256f, 192s, 192f, 128s, 128f) are to be * used. The selection is made either with the flag specified during key * generation or by matching the size of the imported data with the different * lc_sphincs_*_load API calls. All remaining APIs take the information about * the Sphincs type from the provided input data. * * This header file only provides inline functions which selectively call * the API provided with the header files below. * * * lc_sphincs_shake_256s.h: Direct access to Sphincs 256s using SHAKE. * * * lc_sphincs_shake_256f.h: Direct access to Sphincs 256f using SHAKE. * * * lc_sphincs_shake_192s.h: Direct access to Sphincs 192s using SHAKE. * * * lc_sphincs_shake_192f.h: Direct access to Sphincs 192f using SHAKE. * * * lc_sphincs_shake_128s.h: Direct access to Sphincs 128s using SHAKE. * * * lc_sphincs_shake_128f.h: Direct access to Sphincs 128f using SHAKE. * * To support the stream mode of the Sphincs signature operation, a * context structure is required. This context structure can be allocated either * on the stack or heap with \p LC_SPHINCS_CTX_ON_STACK or * \p lc_sphincs_ctx_alloc. The context should be zeroized * and freed (only for heap) with \p lc_sphincs_ctx_zero or * \p lc_sphincs_ctx_zero_free. */ /** * @brief Sphincs secret key */ struct lc_sphincs_sk { enum lc_sphincs_type sphincs_type; union { #ifdef LC_SPHINCS_SHAKE_256s_ENABLED struct lc_sphincs_shake_256s_sk sk_shake_256s; #endif #ifdef LC_SPHINCS_SHAKE_256f_ENABLED struct lc_sphincs_shake_256f_sk sk_shake_256f; #endif #ifdef LC_SPHINCS_SHAKE_192s_ENABLED struct lc_sphincs_shake_192s_sk sk_shake_192s; #endif #ifdef LC_SPHINCS_SHAKE_192f_ENABLED struct lc_sphincs_shake_192f_sk sk_shake_192f; #endif #ifdef LC_SPHINCS_SHAKE_128s_ENABLED struct lc_sphincs_shake_128s_sk sk_shake_128s; #endif #ifdef LC_SPHINCS_SHAKE_128f_ENABLED struct lc_sphincs_shake_128f_sk sk_shake_128f; #endif } key; }; /** * @brief Sphincs public key */ struct lc_sphincs_pk { enum lc_sphincs_type sphincs_type; union { #ifdef LC_SPHINCS_SHAKE_256s_ENABLED struct lc_sphincs_shake_256s_pk pk_shake_256s; #endif #ifdef LC_SPHINCS_SHAKE_256f_ENABLED struct lc_sphincs_shake_256f_pk pk_shake_256f; #endif #ifdef LC_SPHINCS_SHAKE_192s_ENABLED struct lc_sphincs_shake_192s_pk pk_shake_192s; #endif #ifdef LC_SPHINCS_SHAKE_192f_ENABLED struct lc_sphincs_shake_192f_pk pk_shake_192f; #endif #ifdef LC_SPHINCS_SHAKE_128s_ENABLED struct lc_sphincs_shake_128s_pk pk_shake_128s; #endif #ifdef LC_SPHINCS_SHAKE_128f_ENABLED struct lc_sphincs_shake_128f_pk pk_shake_128f; #endif } key; }; /** * @brief Sphincs signature */ struct lc_sphincs_sig { enum lc_sphincs_type sphincs_type; union { #ifdef LC_SPHINCS_SHAKE_256s_ENABLED struct lc_sphincs_shake_256s_sig sig_shake_256s; #endif #ifdef LC_SPHINCS_SHAKE_256f_ENABLED struct lc_sphincs_shake_256f_sig sig_shake_256f; #endif #ifdef LC_SPHINCS_SHAKE_192s_ENABLED struct lc_sphincs_shake_192s_sig sig_shake_192s; #endif #ifdef LC_SPHINCS_SHAKE_192f_ENABLED struct lc_sphincs_shake_192f_sig sig_shake_192f; #endif #ifdef LC_SPHINCS_SHAKE_128s_ENABLED struct lc_sphincs_shake_128s_sig sig_shake_128s; #endif #ifdef LC_SPHINCS_SHAKE_128f_ENABLED struct lc_sphincs_shake_128f_sig sig_shake_128f; #endif } sig; }; /** * @ingroup Sphincs * @brief Allocates Sphincs context on heap * * @param [out] ctx Sphincs context pointer * * @return 0 (success) or < 0 on error */ int lc_sphincs_ctx_alloc(struct lc_sphincs_ctx **ctx); /** * @ingroup Sphincs * @brief Zeroizes and frees Sphincs context on heap * * @param [out] ctx Sphincs context pointer */ void lc_sphincs_ctx_zero_free(struct lc_sphincs_ctx *ctx); /** * @ingroup Sphincs * @brief Zeroizes Sphincs context either on heap or on stack * * @param [out] ctx Sphincs context pointer */ void lc_sphincs_ctx_zero(struct lc_sphincs_ctx *ctx); /** * @ingroup Sphincs * @brief Mark the Sphincs context to execute SLH-DSA.Sign_internal / * SLH-DSA.Verify_internal. * * @param [in] ctx Sphincs context */ void lc_sphincs_ctx_internal(struct lc_sphincs_ctx *ctx); /** * @ingroup Sphincs * @brief Set the hash type that was used for pre-hashing the message. The * message digest is used with the HashSLH-DSA. The message digest * is to be provided via the message pointer in the sign/verify APIs. * * @param [in] ctx Sphincs context * @param [in] hash Hash context referencing the used hash for pre-hashing the * message */ void lc_sphincs_ctx_hash(struct lc_sphincs_ctx *ctx, const struct lc_hash *hash); /** * @ingroup Sphincs * @brief Specify the optional user context string to be applied with the * Sphincs signature operation. * * @param [in] ctx Sphincs context * @param [in] userctx User context string * @param [in] userctxlen Size of the user context string */ void lc_sphincs_ctx_userctx(struct lc_sphincs_ctx *ctx, const uint8_t *userctx, size_t userctxlen); /** * @ingroup Sphincs * @brief Obtain Sphincs type from secret key * * @param [in] sk Secret key from which the type is to be obtained * * @return key type */ enum lc_sphincs_type lc_sphincs_sk_type(const struct lc_sphincs_sk *sk); /** * @ingroup Sphincs * @brief Obtain Sphincs type from public key * * @param [in] pk Public key from which the type is to be obtained * * @return key type */ enum lc_sphincs_type lc_sphincs_pk_type(const struct lc_sphincs_pk *pk); /** * @ingroup Sphincs * @brief Obtain Sphincs type from signature * * @param [in] sig Signature from which the type is to be obtained * * @return key type */ enum lc_sphincs_type lc_sphincs_sig_type(const struct lc_sphincs_sig *sig); /** * @ingroup Sphincs * @brief Return the size of the Sphincs secret key. * * @param [in] sphincs_type Sphincs type for which the size is requested * * @return requested size */ LC_PURE unsigned int lc_sphincs_sk_size(enum lc_sphincs_type sphincs_type); /** * @ingroup Sphincs * @brief Return the size of the Sphincs public key. * * @param [in] sphincs_type Sphincs type for which the size is requested * * @return requested size */ LC_PURE unsigned int lc_sphincs_pk_size(enum lc_sphincs_type sphincs_type); /** * @ingroup Sphincs * @brief Return the size of the Sphincs signature. * * @param [in] sphincs_type Sphincs type for which the size is requested * * @return requested size */ LC_PURE unsigned int lc_sphincs_sig_size(enum lc_sphincs_type sphincs_type); /** * @ingroup Sphincs * @brief Load a Sphincs secret key provided with a buffer into the leancrypto * data structure. * * @param [out] sk Secret key to be filled (the caller must have it allocated) * @param [in] src_key Buffer that holds the key to be imported * @param [in] src_key_len Buffer length that holds the key to be imported * * @return 0 on success or < 0 on error */ int lc_sphincs_sk_load(struct lc_sphincs_sk *sk, const uint8_t *src_key, size_t src_key_len); /** * @ingroup Sphincs * @brief Set Sphincs key type to fast * * When loading a secret key, the load mechanism cannot detect whether the * key is to be used for the fast or small Sphincs operation (e.g. 256f vs * 256s). This API allows the caller to make the setting after key loading. * The library uses that decision for further operations. * * @param [in] sk Secret key to be set * * @return 0 on success or < 0 on error */ int lc_sphincs_sk_set_keytype_fast(struct lc_sphincs_sk *sk); /** * @ingroup Sphincs * @brief Set Sphincs key type to small * * When loading a secret key, the load mechanism cannot detect whether the * key is to be used for the fast or small Sphincs operation (e.g. 256f vs * 256s). This API allows the caller to make the setting after key loading. * The library uses that decision for further operations. * * @param [in] sk Secret key to be set * * @return 0 on success or < 0 on error */ int lc_sphincs_sk_set_keytype_small(struct lc_sphincs_sk *sk); /** * @ingroup Sphincs * @brief Load a Sphincs public key provided with a buffer into the leancrypto * data structure. * * @param [out] pk Secret key to be filled (the caller must have it allocated) * @param [in] src_key Buffer that holds the key to be imported * @param [in] src_key_len Buffer length that holds the key to be imported * * @return 0 on success or < 0 on error */ int lc_sphincs_pk_load(struct lc_sphincs_pk *pk, const uint8_t *src_key, size_t src_key_len); /** * @ingroup Sphincs * @brief Set Sphincs key type to fast * * When loading a public key, the load mechanism cannot detect whether the * key is to be used for the fast or small Sphincs operation (e.g. 256f vs * 256s). This API allows the caller to make the setting after key loading. * The library uses that decision for further operations. * * @param [in] pk Public key to be set * * @return 0 on success or < 0 on error */ int lc_sphincs_pk_set_keytype_fast(struct lc_sphincs_pk *pk); /** * @ingroup Sphincs * @brief Set Sphincs key type to small * * When loading a public key, the load mechanism cannot detect whether the * key is to be used for the fast or small Sphincs operation (e.g. 256f vs * 256s). This API allows the caller to make the setting after key loading. * The library uses that decision for further operations. * * @param [in] pk Public key to be set * * @return 0 on success or < 0 on error */ int lc_sphincs_pk_set_keytype_small(struct lc_sphincs_pk *pk); /** * @ingroup Sphincs * @brief Load a Sphincs signature provided with a buffer into the leancrypto * data structure. * * @param [out] sig Secret key to be filled (the caller must have it allocated) * @param [in] src_sig Buffer that holds the signature to be imported * @param [in] src_sig_len Buffer length that holds the signature to be imported * * @return 0 on success or < 0 on error */ int lc_sphincs_sig_load(struct lc_sphincs_sig *sig, const uint8_t *src_sig, size_t src_sig_len); /** * @ingroup Sphincs * @brief Obtain the reference to the Sphincs key and its length * * \note Only pointer references into the leancrypto data structure are returned * which implies that any modification will modify the leancrypto key, too. * * @param [out] sphincs_key Sphincs key pointer * @param [out] sphincs_key_len Length of the key buffer * @param [in] sk Sphincs secret key from which the references are obtained * * @return 0 on success, != 0 on error */ int lc_sphincs_sk_ptr(uint8_t **sphincs_key, size_t *sphincs_key_len, struct lc_sphincs_sk *sk); /** * @ingroup Sphincs * @brief Obtain the reference to the Sphincs key and its length * * \note Only pointer references into the leancrypto data structure are returned * which implies that any modification will modify the leancrypto key, too. * * @param [out] sphincs_key Sphincs key pointer * @param [out] sphincs_key_len Length of the key buffer * @param [in] pk Sphincs publi key from which the references are obtained * * @return 0 on success, != 0 on error */ int lc_sphincs_pk_ptr(uint8_t **sphincs_key, size_t *sphincs_key_len, struct lc_sphincs_pk *pk); /** * @ingroup Sphincs * @brief Obtain the reference to the Sphincs signature and its length * * \note Only pointer references into the leancrypto data structure are returned * which implies that any modification will modify the leancrypto signature, * too. * * @param [out] sphincs_sig Sphincs signature pointer * @param [out] sphincs_sig_len Length of the signature buffer * @param [in] sig Sphincs signature from which the references are obtained * * @return 0 on success, != 0 on error */ int lc_sphincs_sig_ptr(uint8_t **sphincs_sig, size_t *sphincs_sig_len, struct lc_sphincs_sig *sig); /** * @ingroup Sphincs * @brief Generates Sphincs public and private key. * * @param [out] pk pointer to allocated output public key * @param [out] sk pointer to allocated output private key * @param [in] rng_ctx pointer to seeded random number generator context * @param [in] sphincs_type type of the Sphincs key to generate * * @return 0 (success) or < 0 on error */ int lc_sphincs_keypair(struct lc_sphincs_pk *pk, struct lc_sphincs_sk *sk, struct lc_rng_ctx *rng_ctx, enum lc_sphincs_type sphincs_type); /** * @ingroup Sphincs * @brief Generates Sphincs public and private key from a given seed. * * \warning FIPS 205 does not allow such a call. Therefore, this call will * always return -EOPNOTSUPP. The call is provided to allow seampless switch * from ML-DSA to SLH-DSA and back. * * @param [out] pk pointer to allocated output public key * @param [out] sk pointer to allocated output private key * @param [in] seed buffer with the seed data which must be exactly 32 bytes * in size * @param [in] seedlen length of the seed buffer * @param [in] sphincs_type type of the Sphincs key to generate * * @return 0 (success) or < 0 on error */ int lc_sphincs_keypair_from_seed(struct lc_sphincs_pk *pk, struct lc_sphincs_sk *sk, const uint8_t *seed, size_t seedlen, enum lc_sphincs_type sphincs_type); /** * @ingroup Sphincs * @brief Generates Sphincs public from private key. * * @param [out] pk pointer to allocated output public key * @param [in] sk pointer private key * * @return 0 (success) or < 0 on error */ int lc_sphincs_pk_from_sk(struct lc_sphincs_pk *pk, const struct lc_sphincs_sk *sk); /** * @brief Pairwise consistency check as per FIPS 140 IG * * This call should be invoked after generating a key pair in FIPS mode * * @param [in] pk Public key * @param [in] sk Secret key * * @return 0 on success, < 0 on error */ int lc_sphincs_pct(const struct lc_sphincs_pk *pk, const struct lc_sphincs_sk *sk); /** * @ingroup Sphincs * @brief Computes signature in one shot * * @param [out] sig pointer to output signature * @param [in] m pointer to message to be signed * @param [in] mlen length of message * @param [in] sk pointer to secret key * @param [in] rng_ctx pointer to seeded random number generator context - when * pointer is non-NULL, perform a randomized signing. * Otherwise use deterministic signing. * * @return 0 (success) or < 0 on error */ int lc_sphincs_sign(struct lc_sphincs_sig *sig, const uint8_t *m, size_t mlen, const struct lc_sphincs_sk *sk, struct lc_rng_ctx *rng_ctx); /** * @ingroup Sphincs * @brief Computes signature woth user context in one shot * * This API allows the caller to provide an arbitrary context buffer which * is hashed together with the message to form the message digest to be signed. * * Using the ctx structure, the caller can select 3 different types of SLH-DSA: * * * ctx->sphincs_prehash_type set to a hash type, HashSLH-DSA is assumed which * implies that the message m must be exactly digest size (FIPS 204 section * 5.4) * * * ctx->ml_dsa_internal set to 1, the SLH-DSA.Sign_internal and * .Verify_internal are executed (FIPS 204 chapter 6) * * * both aforementioned parameter set to NULL / 0, SLH-DSA.Sign and * SLH-DSA.Verify are executed (FIPS 204 sections 5.2 and 5.3) * * @param [out] sig pointer to output signature * @param [in] ctx reference to the allocated Sphincs context handle * @param [in] m pointer to message to be signed * @param [in] mlen length of message * @param [in] sk pointer to secret key * @param [in] rng_ctx pointer to seeded random number generator context - when * pointer is non-NULL, perform a randomized signing. * Otherwise use deterministic signing. * * @return 0 (success) or < 0 on error */ int lc_sphincs_sign_ctx(struct lc_sphincs_sig *sig, struct lc_sphincs_ctx *ctx, const uint8_t *m, size_t mlen, const struct lc_sphincs_sk *sk, struct lc_rng_ctx *rng_ctx); /** * @ingroup Sphincs * @brief Initializes a signature operation * * This call is intended to support messages that are located in non-contiguous * places and even becomes available at different times. This call is to be * used together with the lc_sphincs_sign_update and lc_sphincs_sign_final. * * \parblock * The use of the init/update/final API implies that automatically * HashSLH-DSA is used. This is due to the fact that SLH-DSA cannot be used * in the init/update/final mode due to mathematical issues. By default, the * following hashes are used which are compliant to the requirement that the * message digest must be twice as large as the parameter n: * * * Sphincs 256s/f: SHA3-512 * * Sphincs 192s/f: SHA3-384 * * Sphincs 128s/f: SHA3-256 * * It is permissible for the caller to select other message digest algorithms * by using setting the requested algorithm in the ctx using the * lc_sphincs_ctx_hash method *before* this init function is used. But mind * the basic requirement that the message digest size must be at least twice * the parameter n! This is checked by leancrypto during the signature * generation. * \endparblock * * @param [in,out] ctx pointer Sphincs context * @param [in] sk pointer to secret key * * @return 0 (success) or < 0 on error; -EOPNOTSUPP is returned if a different * hash than lc_shake256 is used. */ int lc_sphincs_sign_init(struct lc_sphincs_ctx *ctx, const struct lc_sphincs_sk *sk); /** * @ingroup Sphincs * @brief Add more data to an already initialized signature state * * This call is intended to support messages that are located in non-contiguous * places and even becomes available at different times. This call is to be * used together with the lc_sphincs_sign_init and lc_sphincs_sign_final. * * @param [in] ctx pointer to Sphincs context that was initialized with * lc_sphincs_sign_init * @param [in] m pointer to message to be signed * @param [in] mlen length of message * * @return 0 (success) or < 0 on error */ int lc_sphincs_sign_update(struct lc_sphincs_ctx *ctx, const uint8_t *m, size_t mlen); /** * @ingroup Sphincs * @brief Computes signature * * @param [out] sig pointer to output signature * @param [in] ctx pointer to Sphincs context that was initialized with * lc_sphincs_sign_init and filled with * lc_sphincs_sign_update * @param [in] sk pointer to secret key * @param [in] rng_ctx pointer to seeded random number generator context - when * pointer is non-NULL, perform a randomized signing. * Otherwise use deterministic signing. * * @return 0 (success) or < 0 on error */ int lc_sphincs_sign_final(struct lc_sphincs_sig *sig, struct lc_sphincs_ctx *ctx, const struct lc_sphincs_sk *sk, struct lc_rng_ctx *rng_ctx); /** * @ingroup Sphincs * @brief Verifies signature in one shot * * @param [in] sig pointer to input signature * @param [in] m pointer to message * @param [in] mlen length of message * @param [in] pk pointer to public key * * @return 0 if signature could be verified correctly and -EBADMSG when * signature cannot be verified, < 0 on other errors */ int lc_sphincs_verify(const struct lc_sphincs_sig *sig, const uint8_t *m, size_t mlen, const struct lc_sphincs_pk *pk); /** * @ingroup Sphincs * @brief Verifies signature with Sphincs context in one shot * * This API allows the caller to provide an arbitrary context buffer which * is hashed together with the message to form the message digest to be signed. * * @param [in] sig pointer to input signature * @param [in] ctx reference to the allocated Sphincs context handle * @param [in] m pointer to message * @param [in] mlen length of message * @param [in] pk pointer to public key * * @return 0 if signature could be verified correctly and -EBADMSG when * signature cannot be verified, < 0 on other errors */ int lc_sphincs_verify_ctx(const struct lc_sphincs_sig *sig, struct lc_sphincs_ctx *ctx, const uint8_t *m, size_t mlen, const struct lc_sphincs_pk *pk); /** * @ingroup Sphincs * @brief Initializes a signature verification operation * * This call is intended to support messages that are located in non-contiguous * places and even becomes available at different times. This call is to be * used together with the lc_sphincs_verify_update and * lc_sphincs_verify_final. * * \parblock * The use of the init/update/final API implies that automatically * HashSLH-DSA is used. This is due to the fact that SLH-DSA cannot be used * in the init/update/final mode due to mathematical issues. By default, the * following hashes are used which are compliant to the requirement that the * message digest must be twice as large as the parameter n: * * * Sphincs 256s/f: SHA3-512 * * Sphincs 192s/f: SHA3-384 * * Sphincs 128s/f: SHA3-256 * * It is permissible for the caller to select other message digest algorithms * by using setting the requested algorithm in the ctx using the * lc_sphincs_ctx_hash method *before* this init function is used.But mind * the basic requirement that the message digest size must be at least twice * the parameter n! This is checked by leancrypto during the signature * verification. * \endparblock * * @param [in,out] ctx pointer to an allocated Sphincs context * @param [in] pk pointer to public key * * @return 0 (success) or < 0 on error; -EOPNOTSUPP is returned if a different * hash than lc_shake256 is used. */ int lc_sphincs_verify_init(struct lc_sphincs_ctx *ctx, const struct lc_sphincs_pk *pk); /** * @ingroup Sphincs * @brief Add more data to an already initialized signature state * * This call is intended to support messages that are located in non-contiguous * places and even becomes available at different times. This call is to be * used together with the lc_sphincs_verify_init and * lc_sphincs_verify_final. * * @param [in] ctx pointer to Sphincs context that was initialized with * lc_sphincs_sign_init * @param [in] m pointer to message to be signed * @param [in] mlen length of message * * @return 0 (success) or < 0 on error */ int lc_sphincs_verify_update(struct lc_sphincs_ctx *ctx, const uint8_t *m, size_t mlen); /** * @ingroup Sphincs * @brief Verifies signature * * @param [in] sig pointer to output signature * @param [in] ctx pointer to Sphincs context that was initialized with * lc_sphincs_sign_init and filled with * lc_sphincs_sign_update * @param [in] pk pointer to public key * * @return 0 if signature could be verified correctly and -EBADMSG when * signature cannot be verified, < 0 on other errors */ int lc_sphincs_verify_final(const struct lc_sphincs_sig *sig, struct lc_sphincs_ctx *ctx, const struct lc_sphincs_pk *pk); enum lc_sphincs_alg_operation { /** Unknown operation */ lc_alg_operation_sphincs_unknown, /** ML-DSA: key generation operation */ lc_alg_operation_sphincs_keygen, /** ML-DSA: signature generation operation */ lc_alg_operation_sphincs_siggen, /** ML-DSA: signature generation operation */ lc_alg_operation_sphincs_sigver, }; /** * @ingroup Sphincs * @brief Obtain algorithm status * * @param [in] sphincs_type SLH-DSA algorithm type * @param [in] operation SLH-DSA algorithm operation * * @return algorithm status */ enum lc_alg_status_val lc_sphincs_alg_status(const enum lc_sphincs_type sphincs_type, const enum lc_sphincs_alg_operation operation); #ifdef __cplusplus } #endif #endif /* LC_SPHINCS_H */