@@ -260,11 +260,15 @@ int wc_SlhDsaKey_Sign(SlhDsaKey* key, const byte* ctx,
260260 \ingroup SLH_DSA
261261
262262 \brief Verifies an SLH-DSA signature over a message using the external
263- (pure) interface. This is FIPS 205 Algorithm 23 . The message is wrapped
263+ (pure) interface. This is FIPS 205 Algorithm 24 . The message is wrapped
264264 internally as M' = 0x00 || len(ctx) || ctx || M before verification.
265265
266266 \return 0 on success (signature valid).
267- \return BAD_FUNC_ARG if key, msg, or sig is NULL.
267+ \return BAD_FUNC_ARG if key, msg, or sig is NULL, or ctx is NULL but
268+ ctxSz is greater than 0.
269+ \return BAD_LENGTH_E if sigSz does not match the parameter set's
270+ signature length.
271+ \return MISSING_KEY if the public key has not been set.
268272 \return SIG_VERIFY_E if the signature is invalid.
269273
270274 \param [in] key Pointer to a public SlhDsaKey.
@@ -397,6 +401,9 @@ int wc_SlhDsaKey_SignMsgWithRandom(SlhDsaKey* key,
397401
398402 \return 0 on success (signature valid).
399403 \return BAD_FUNC_ARG if key, mprime, or sig is NULL.
404+ \return BAD_LENGTH_E if sigSz does not match the parameter set's
405+ signature length.
406+ \return MISSING_KEY if the public key has not been set.
400407 \return SIG_VERIFY_E if the signature is invalid.
401408
402409 \param [in] key Pointer to a public SlhDsaKey.
@@ -513,7 +520,7 @@ int wc_SlhDsaKey_SignHashDeterministic(SlhDsaKey* key,
513520*/
514521int wc_SlhDsaKey_SignHashWithRandom (SlhDsaKey * key ,
515522 const byte * ctx , byte ctxSz , const byte * hash , word32 hashSz ,
516- enum wc_HashType hashType , byte * sig , word32 * sigSz , byte * addRnd );
523+ enum wc_HashType hashType , byte * sig , word32 * sigSz , const byte * addRnd );
517524
518525/*!
519526 \ingroup SLH_DSA
@@ -553,7 +560,7 @@ int wc_SlhDsaKey_SignHash(SlhDsaKey* key, const byte* ctx,
553560 \ingroup SLH_DSA
554561
555562 \brief Verifies an SLH-DSA signature using the external HashSLH-DSA
556- interface (FIPS 205 Algorithm 24 ). The caller must hash the application
563+ interface (FIPS 205 Algorithm 25 ). The caller must hash the application
557564 message with hashType first and pass the digest as hash; this function
558565 does NOT hash its input.
559566
@@ -835,3 +842,187 @@ int wc_SlhDsaKey_PublicSizeFromParam(enum SlhDsaParam param);
835842 \sa wc_SlhDsaKey_SigSize
836843*/
837844int wc_SlhDsaKey_SigSizeFromParam (enum SlhDsaParam param );
845+
846+ /*!
847+ \ingroup SLH_DSA
848+
849+ \brief Decodes a DER-encoded SLH-DSA private key in the PKCS#8
850+ OneAsymmetricKey format defined by RFC 9909. The privateKey OCTET STRING
851+ contains the raw concatenation SK.seed || SK.prf || PK.seed || PK.root
852+ (4*n bytes) directly, without a nested OCTET STRING wrapper as used by
853+ Ed25519/Ed448. The SLH-DSA parameter set is detected from the
854+ AlgorithmIdentifier OID and key->params is updated to match. Available
855+ only when WOLFSSL_SLHDSA_VERIFY_ONLY is not defined.
856+
857+ On a failure that is detected before any write to key->sk
858+ (BAD_FUNC_ARG, header/OID parse errors, or wrong privateKey length), the
859+ key state is left untouched. On a failure detected after
860+ wc_SlhDsaKey_ImportPrivate has populated key->sk (a SHA-2 precompute
861+ error, or a trailing-field validation error), key->sk is scrubbed with
862+ ForceZero and the WC_SLHDSA_FLAG_PRIVATE/PUBLIC flags are cleared so
863+ flags can never claim valid bytes that were zeroed. In both rollback
864+ cases, key->params and inOutIdx are restored to their pre-call values.
865+
866+ \return 0 on success.
867+ \return BAD_FUNC_ARG if input, inOutIdx, or key is NULL, or inSz is 0.
868+ \return ASN_PARSE_E if the DER cannot be parsed as an SLH-DSA private
869+ key (malformed input, wrong key size, or trailing-field violation).
870+ \return NOT_COMPILED_IN if the OID names an SLH-DSA variant that is not
871+ built into this library.
872+
873+ \param [in] input DER-encoded key data.
874+ \param [in,out] inOutIdx On input, starting offset into input. On output,
875+ advanced past the parsed key (unchanged on failure).
876+ \param [in,out] key SLH-DSA key. Parameter set is auto-detected from the
877+ encoded OID.
878+ \param [in] inSz Total size of input in bytes.
879+
880+ \sa wc_SlhDsaKey_KeyToDer
881+ \sa wc_SlhDsaKey_PublicKeyDecode
882+ \sa wc_SlhDsaKey_ImportPrivate
883+ */
884+ int wc_SlhDsaKey_PrivateKeyDecode (const byte * input , word32 * inOutIdx ,
885+ SlhDsaKey * key , word32 inSz );
886+
887+ /*!
888+ \ingroup SLH_DSA
889+
890+ \brief Decodes a DER-encoded SLH-DSA public key in the
891+ SubjectPublicKeyInfo (SPKI) format. The SLH-DSA parameter set is
892+ detected from the AlgorithmIdentifier OID and key->params is updated
893+ accordingly.
894+
895+ As a fast path, if key->params is already set the function first hands
896+ the entire window from inOutIdx to inSz to wc_SlhDsaKey_ImportPublic.
897+ ImportPublic's length check is the disambiguator: a window of exactly
898+ 2*n bytes is accepted as a raw public key (PK.seed || PK.root) and
899+ consumed in full; any other length is rejected and the function falls
900+ through to SPKI parsing. SPKI input always carries enough
901+ AlgorithmIdentifier/BIT STRING overhead that it never collides with the
902+ 2*n raw length, so it falls through cleanly. The caller does not need
903+ to pre-trim the window to 2*n.
904+
905+ On a failure detected before any write (BAD_FUNC_ARG or a malformed
906+ SPKI), the key state is left untouched. On a failure detected after
907+ ImportPublic has populated the public half of key->sk (a SHA-2
908+ precompute error), the public half sk[2*n .. 4*n] is scrubbed and
909+ WC_SLHDSA_FLAG_PUBLIC is cleared from the flags; the private half is
910+ left intact in case the caller imported it earlier. key->params and
911+ inOutIdx are restored to their pre-call values.
912+
913+ \return 0 on success.
914+ \return BAD_FUNC_ARG if input, inOutIdx, or key is NULL, or inSz is 0.
915+ \return ASN_PARSE_E if the DER cannot be parsed as an SLH-DSA public
916+ key.
917+ \return NOT_COMPILED_IN if the OID names an SLH-DSA variant that is not
918+ built into this library.
919+
920+ \param [in] input DER-encoded key data, or a raw 2*n public key when
921+ key->params is already set.
922+ \param [in,out] inOutIdx On input, starting offset into input. On output,
923+ advanced past the parsed key (unchanged on failure).
924+ \param [in,out] key SLH-DSA key. Parameter set is auto-detected from the
925+ encoded OID, or honored as-is in the raw fast path.
926+ \param [in] inSz Total size of input in bytes.
927+
928+ \sa wc_SlhDsaKey_PublicKeyToDer
929+ \sa wc_SlhDsaKey_PrivateKeyDecode
930+ \sa wc_SlhDsaKey_ImportPublic
931+ */
932+ int wc_SlhDsaKey_PublicKeyDecode (const byte * input , word32 * inOutIdx ,
933+ SlhDsaKey * key , word32 inSz );
934+
935+ /*!
936+ \ingroup SLH_DSA
937+
938+ \brief Encodes an SLH-DSA private key to DER in the PKCS#8
939+ OneAsymmetricKey format defined by RFC 9909. The privateKey OCTET STRING
940+ contains the raw 4*n bytes (SK.seed || SK.prf || PK.seed || PK.root)
941+ directly, without the nested OCTET STRING wrapping used by Ed25519/Ed448.
942+
943+ Available only when WOLFSSL_SLHDSA_VERIFY_ONLY is not defined and
944+ WC_ENABLE_ASYM_KEY_EXPORT is set.
945+
946+ \return Size of the encoded DER in bytes on success. Pass NULL as output
947+ to query the required buffer size without writing.
948+ \return BAD_FUNC_ARG if key or key->params is NULL.
949+ \return MISSING_KEY if the private key has not been set.
950+ \return BUFFER_E if output is non-NULL and inLen is smaller than the
951+ required size.
952+ \return NOT_COMPILED_IN if key->params names an SLH-DSA variant whose
953+ parameter set is not built in.
954+
955+ \param [in] key SLH-DSA key with a populated private key.
956+ \param [out] output Buffer to receive the DER encoding, or NULL to query
957+ the required size.
958+ \param [in] inLen Size of output in bytes (ignored when output is NULL).
959+
960+ \sa wc_SlhDsaKey_PrivateKeyDecode
961+ \sa wc_SlhDsaKey_PrivateKeyToDer
962+ \sa wc_SlhDsaKey_PublicKeyToDer
963+ */
964+ int wc_SlhDsaKey_KeyToDer (SlhDsaKey * key , byte * output , word32 inLen );
965+
966+ /*!
967+ \ingroup SLH_DSA
968+
969+ \brief Encodes an SLH-DSA private key to DER. RFC 9909 packs
970+ SK.seed || SK.prf || PK.seed || PK.root into a single OCTET STRING, so
971+ SLH-DSA has no distinct private-only encoding. This function is an
972+ intentional alias of wc_SlhDsaKey_KeyToDer, kept for API parity with
973+ Ed25519/Ed448 which do have a separate private form.
974+
975+ Available only when WOLFSSL_SLHDSA_VERIFY_ONLY is not defined and
976+ WC_ENABLE_ASYM_KEY_EXPORT is set.
977+
978+ Return codes are inherited unchanged from wc_SlhDsaKey_KeyToDer.
979+
980+ \return Size of the encoded DER in bytes on success. Pass NULL as output
981+ to query the required buffer size.
982+ \return BAD_FUNC_ARG if key or key->params is NULL.
983+ \return MISSING_KEY if the private key has not been set.
984+ \return BUFFER_E if output is non-NULL and inLen is smaller than the
985+ required size.
986+ \return NOT_COMPILED_IN if key->params names an SLH-DSA variant whose
987+ parameter set is not built in.
988+
989+ \param [in] key SLH-DSA key with a populated private key.
990+ \param [out] output Buffer to receive the DER encoding, or NULL to query
991+ the required size.
992+ \param [in] inLen Size of output in bytes (ignored when output is NULL).
993+
994+ \sa wc_SlhDsaKey_KeyToDer
995+ \sa wc_SlhDsaKey_PrivateKeyDecode
996+ */
997+ int wc_SlhDsaKey_PrivateKeyToDer (SlhDsaKey * key , byte * output , word32 inLen );
998+
999+ /*!
1000+ \ingroup SLH_DSA
1001+
1002+ \brief Encodes an SLH-DSA public key to DER. When withAlg is non-zero
1003+ the output is a full SubjectPublicKeyInfo structure (AlgorithmIdentifier
1004+ plus BIT STRING). When withAlg is zero the output contains the raw
1005+ public key bytes without the SPKI wrapping.
1006+
1007+ Available only when WC_ENABLE_ASYM_KEY_EXPORT is set.
1008+
1009+ \return Size of the encoded DER in bytes on success. Pass NULL as output
1010+ to query the required buffer size.
1011+ \return BAD_FUNC_ARG if key or key->params is NULL.
1012+ \return BUFFER_E if output is non-NULL and inLen is smaller than the
1013+ required size.
1014+ \return NOT_COMPILED_IN if key->params names an SLH-DSA variant whose
1015+ parameter set is not built in.
1016+
1017+ \param [in] key SLH-DSA key with a populated public key.
1018+ \param [out] output Buffer to receive the DER encoding, or NULL to query
1019+ the required size.
1020+ \param [in] inLen Size of output in bytes (ignored when output is NULL).
1021+ \param [in] withAlg Non-zero to emit SubjectPublicKeyInfo (with
1022+ AlgorithmIdentifier); zero to emit the raw public key only.
1023+
1024+ \sa wc_SlhDsaKey_PublicKeyDecode
1025+ \sa wc_SlhDsaKey_KeyToDer
1026+ */
1027+ int wc_SlhDsaKey_PublicKeyToDer (SlhDsaKey * key , byte * output , word32 inLen ,
1028+ int withAlg );
0 commit comments