mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-07-05 09:40:51 +02:00
SLH-DSA fixes
Follow up to PR #10450 with some minor fixes: * FIPS 205 numbering: slh_sign is §10.2.1 Alg 22; slh_verify is Alg 24; hash_slh_verify is Alg 25 (impl comments and doxygen). * Widen wc_SlhDsaKey_SignHashWithRandom's addRnd to const byte* to match wc_SlhDsaKey_SignWithRandom. * Make the SLHDSA_PHMSG_MAX_LEN invariant explicit with a named SLHDSA_LARGEST_APPROVED_PHM_LEN constant and a wc_static_assert. * SHAKE128/SHAKE256 round-trip and length-rejection coverage for both SignHash and VerifyHash. * Doxygen: briefs for the five DER encode/decode APIs; accurate decoder failure-rollback wording; tighter return-code lists for Verify and VerifyMsg. * ChangeLog: silent-failure caveat for raw messages whose length happens to equal the digest size of the chosen hashType.
This commit is contained in:
+10
-5
@@ -12,11 +12,16 @@
|
||||
for SHAKE128, 64 bytes for SHAKE256 per FIPS 205 Section 10.2.2); otherwise
|
||||
`BAD_LENGTH_E` is returned. Migration: hash the message yourself before the
|
||||
call (callers using positional arguments are source-compatible; only the
|
||||
parameter names changed). The pre-existing `wc_SlhDsaKey_SignMsgDeterministic`
|
||||
and `wc_SlhDsaKey_SignMsgWithRandom` (FIPS 205 internal interface, M'
|
||||
supplied directly) are unaffected and gain stricter input validation
|
||||
matching the `*Hash*` family. `wc_SlhDsaKey_VerifyMsg` is unchanged. All
|
||||
three gain doxygen coverage.
|
||||
parameter names changed). Caveat: callers who today pass a raw message
|
||||
whose length happens to equal the digest size for the chosen `hashType`
|
||||
(e.g., signing a 32-byte handle/IV/seed with `WC_HASH_TYPE_SHA256`) will
|
||||
not trip `BAD_LENGTH_E`; the resulting signature is syntactically valid
|
||||
but is over the wrong bytes. The pre-existing
|
||||
`wc_SlhDsaKey_SignMsgDeterministic` and `wc_SlhDsaKey_SignMsgWithRandom`
|
||||
retain their M'-supplied-directly contract (FIPS 205 internal interface,
|
||||
Algorithm 19); their input validation is hardened with the same
|
||||
NULL/length/`MISSING_KEY` checks as the `*Hash*` family.
|
||||
`wc_SlhDsaKey_VerifyMsg` is unchanged. All three gain doxygen coverage.
|
||||
|
||||
* TLS 1.3: zero traffic key staging buffers in `SetKeysSide()` once a
|
||||
CryptoCB callback has imported the AES key into a Secure Element
|
||||
|
||||
@@ -260,11 +260,15 @@ int wc_SlhDsaKey_Sign(SlhDsaKey* key, const byte* ctx,
|
||||
\ingroup SLH_DSA
|
||||
|
||||
\brief Verifies an SLH-DSA signature over a message using the external
|
||||
(pure) interface. This is FIPS 205 Algorithm 23. The message is wrapped
|
||||
(pure) interface. This is FIPS 205 Algorithm 24. The message is wrapped
|
||||
internally as M' = 0x00 || len(ctx) || ctx || M before verification.
|
||||
|
||||
\return 0 on success (signature valid).
|
||||
\return BAD_FUNC_ARG if key, msg, or sig is NULL.
|
||||
\return BAD_FUNC_ARG if key, msg, or sig is NULL, or ctx is NULL but
|
||||
ctxSz is greater than 0.
|
||||
\return BAD_LENGTH_E if sigSz does not match the parameter set's
|
||||
signature length.
|
||||
\return MISSING_KEY if the public key has not been set.
|
||||
\return SIG_VERIFY_E if the signature is invalid.
|
||||
|
||||
\param [in] key Pointer to a public SlhDsaKey.
|
||||
@@ -397,6 +401,9 @@ int wc_SlhDsaKey_SignMsgWithRandom(SlhDsaKey* key,
|
||||
|
||||
\return 0 on success (signature valid).
|
||||
\return BAD_FUNC_ARG if key, mprime, or sig is NULL.
|
||||
\return BAD_LENGTH_E if sigSz does not match the parameter set's
|
||||
signature length.
|
||||
\return MISSING_KEY if the public key has not been set.
|
||||
\return SIG_VERIFY_E if the signature is invalid.
|
||||
|
||||
\param [in] key Pointer to a public SlhDsaKey.
|
||||
@@ -513,7 +520,7 @@ int wc_SlhDsaKey_SignHashDeterministic(SlhDsaKey* key,
|
||||
*/
|
||||
int wc_SlhDsaKey_SignHashWithRandom(SlhDsaKey* key,
|
||||
const byte* ctx, byte ctxSz, const byte* hash, word32 hashSz,
|
||||
enum wc_HashType hashType, byte* sig, word32* sigSz, byte* addRnd);
|
||||
enum wc_HashType hashType, byte* sig, word32* sigSz, const byte* addRnd);
|
||||
|
||||
/*!
|
||||
\ingroup SLH_DSA
|
||||
@@ -553,7 +560,7 @@ int wc_SlhDsaKey_SignHash(SlhDsaKey* key, const byte* ctx,
|
||||
\ingroup SLH_DSA
|
||||
|
||||
\brief Verifies an SLH-DSA signature using the external HashSLH-DSA
|
||||
interface (FIPS 205 Algorithm 24). The caller must hash the application
|
||||
interface (FIPS 205 Algorithm 25). The caller must hash the application
|
||||
message with hashType first and pass the digest as hash; this function
|
||||
does NOT hash its input.
|
||||
|
||||
@@ -835,3 +842,187 @@ int wc_SlhDsaKey_PublicSizeFromParam(enum SlhDsaParam param);
|
||||
\sa wc_SlhDsaKey_SigSize
|
||||
*/
|
||||
int wc_SlhDsaKey_SigSizeFromParam(enum SlhDsaParam param);
|
||||
|
||||
/*!
|
||||
\ingroup SLH_DSA
|
||||
|
||||
\brief Decodes a DER-encoded SLH-DSA private key in the PKCS#8
|
||||
OneAsymmetricKey format defined by RFC 9909. The privateKey OCTET STRING
|
||||
contains the raw concatenation SK.seed || SK.prf || PK.seed || PK.root
|
||||
(4*n bytes) directly, without a nested OCTET STRING wrapper as used by
|
||||
Ed25519/Ed448. The SLH-DSA parameter set is detected from the
|
||||
AlgorithmIdentifier OID and key->params is updated to match. Available
|
||||
only when WOLFSSL_SLHDSA_VERIFY_ONLY is not defined.
|
||||
|
||||
On a failure that is detected before any write to key->sk
|
||||
(BAD_FUNC_ARG, header/OID parse errors, or wrong privateKey length), the
|
||||
key state is left untouched. On a failure detected after
|
||||
wc_SlhDsaKey_ImportPrivate has populated key->sk (a SHA-2 precompute
|
||||
error, or a trailing-field validation error), key->sk is scrubbed with
|
||||
ForceZero and the WC_SLHDSA_FLAG_PRIVATE/PUBLIC flags are cleared so
|
||||
flags can never claim valid bytes that were zeroed. In both rollback
|
||||
cases, key->params and inOutIdx are restored to their pre-call values.
|
||||
|
||||
\return 0 on success.
|
||||
\return BAD_FUNC_ARG if input, inOutIdx, or key is NULL, or inSz is 0.
|
||||
\return ASN_PARSE_E if the DER cannot be parsed as an SLH-DSA private
|
||||
key (malformed input, wrong key size, or trailing-field violation).
|
||||
\return NOT_COMPILED_IN if the OID names an SLH-DSA variant that is not
|
||||
built into this library.
|
||||
|
||||
\param [in] input DER-encoded key data.
|
||||
\param [in,out] inOutIdx On input, starting offset into input. On output,
|
||||
advanced past the parsed key (unchanged on failure).
|
||||
\param [in,out] key SLH-DSA key. Parameter set is auto-detected from the
|
||||
encoded OID.
|
||||
\param [in] inSz Total size of input in bytes.
|
||||
|
||||
\sa wc_SlhDsaKey_KeyToDer
|
||||
\sa wc_SlhDsaKey_PublicKeyDecode
|
||||
\sa wc_SlhDsaKey_ImportPrivate
|
||||
*/
|
||||
int wc_SlhDsaKey_PrivateKeyDecode(const byte* input, word32* inOutIdx,
|
||||
SlhDsaKey* key, word32 inSz);
|
||||
|
||||
/*!
|
||||
\ingroup SLH_DSA
|
||||
|
||||
\brief Decodes a DER-encoded SLH-DSA public key in the
|
||||
SubjectPublicKeyInfo (SPKI) format. The SLH-DSA parameter set is
|
||||
detected from the AlgorithmIdentifier OID and key->params is updated
|
||||
accordingly.
|
||||
|
||||
As a fast path, if key->params is already set the function first hands
|
||||
the entire window from inOutIdx to inSz to wc_SlhDsaKey_ImportPublic.
|
||||
ImportPublic's length check is the disambiguator: a window of exactly
|
||||
2*n bytes is accepted as a raw public key (PK.seed || PK.root) and
|
||||
consumed in full; any other length is rejected and the function falls
|
||||
through to SPKI parsing. SPKI input always carries enough
|
||||
AlgorithmIdentifier/BIT STRING overhead that it never collides with the
|
||||
2*n raw length, so it falls through cleanly. The caller does not need
|
||||
to pre-trim the window to 2*n.
|
||||
|
||||
On a failure detected before any write (BAD_FUNC_ARG or a malformed
|
||||
SPKI), the key state is left untouched. On a failure detected after
|
||||
ImportPublic has populated the public half of key->sk (a SHA-2
|
||||
precompute error), the public half sk[2*n .. 4*n] is scrubbed and
|
||||
WC_SLHDSA_FLAG_PUBLIC is cleared from the flags; the private half is
|
||||
left intact in case the caller imported it earlier. key->params and
|
||||
inOutIdx are restored to their pre-call values.
|
||||
|
||||
\return 0 on success.
|
||||
\return BAD_FUNC_ARG if input, inOutIdx, or key is NULL, or inSz is 0.
|
||||
\return ASN_PARSE_E if the DER cannot be parsed as an SLH-DSA public
|
||||
key.
|
||||
\return NOT_COMPILED_IN if the OID names an SLH-DSA variant that is not
|
||||
built into this library.
|
||||
|
||||
\param [in] input DER-encoded key data, or a raw 2*n public key when
|
||||
key->params is already set.
|
||||
\param [in,out] inOutIdx On input, starting offset into input. On output,
|
||||
advanced past the parsed key (unchanged on failure).
|
||||
\param [in,out] key SLH-DSA key. Parameter set is auto-detected from the
|
||||
encoded OID, or honored as-is in the raw fast path.
|
||||
\param [in] inSz Total size of input in bytes.
|
||||
|
||||
\sa wc_SlhDsaKey_PublicKeyToDer
|
||||
\sa wc_SlhDsaKey_PrivateKeyDecode
|
||||
\sa wc_SlhDsaKey_ImportPublic
|
||||
*/
|
||||
int wc_SlhDsaKey_PublicKeyDecode(const byte* input, word32* inOutIdx,
|
||||
SlhDsaKey* key, word32 inSz);
|
||||
|
||||
/*!
|
||||
\ingroup SLH_DSA
|
||||
|
||||
\brief Encodes an SLH-DSA private key to DER in the PKCS#8
|
||||
OneAsymmetricKey format defined by RFC 9909. The privateKey OCTET STRING
|
||||
contains the raw 4*n bytes (SK.seed || SK.prf || PK.seed || PK.root)
|
||||
directly, without the nested OCTET STRING wrapping used by Ed25519/Ed448.
|
||||
|
||||
Available only when WOLFSSL_SLHDSA_VERIFY_ONLY is not defined and
|
||||
WC_ENABLE_ASYM_KEY_EXPORT is set.
|
||||
|
||||
\return Size of the encoded DER in bytes on success. Pass NULL as output
|
||||
to query the required buffer size without writing.
|
||||
\return BAD_FUNC_ARG if key or key->params is NULL.
|
||||
\return MISSING_KEY if the private key has not been set.
|
||||
\return BUFFER_E if output is non-NULL and inLen is smaller than the
|
||||
required size.
|
||||
\return NOT_COMPILED_IN if key->params names an SLH-DSA variant whose
|
||||
parameter set is not built in.
|
||||
|
||||
\param [in] key SLH-DSA key with a populated private key.
|
||||
\param [out] output Buffer to receive the DER encoding, or NULL to query
|
||||
the required size.
|
||||
\param [in] inLen Size of output in bytes (ignored when output is NULL).
|
||||
|
||||
\sa wc_SlhDsaKey_PrivateKeyDecode
|
||||
\sa wc_SlhDsaKey_PrivateKeyToDer
|
||||
\sa wc_SlhDsaKey_PublicKeyToDer
|
||||
*/
|
||||
int wc_SlhDsaKey_KeyToDer(SlhDsaKey* key, byte* output, word32 inLen);
|
||||
|
||||
/*!
|
||||
\ingroup SLH_DSA
|
||||
|
||||
\brief Encodes an SLH-DSA private key to DER. RFC 9909 packs
|
||||
SK.seed || SK.prf || PK.seed || PK.root into a single OCTET STRING, so
|
||||
SLH-DSA has no distinct private-only encoding. This function is an
|
||||
intentional alias of wc_SlhDsaKey_KeyToDer, kept for API parity with
|
||||
Ed25519/Ed448 which do have a separate private form.
|
||||
|
||||
Available only when WOLFSSL_SLHDSA_VERIFY_ONLY is not defined and
|
||||
WC_ENABLE_ASYM_KEY_EXPORT is set.
|
||||
|
||||
Return codes are inherited unchanged from wc_SlhDsaKey_KeyToDer.
|
||||
|
||||
\return Size of the encoded DER in bytes on success. Pass NULL as output
|
||||
to query the required buffer size.
|
||||
\return BAD_FUNC_ARG if key or key->params is NULL.
|
||||
\return MISSING_KEY if the private key has not been set.
|
||||
\return BUFFER_E if output is non-NULL and inLen is smaller than the
|
||||
required size.
|
||||
\return NOT_COMPILED_IN if key->params names an SLH-DSA variant whose
|
||||
parameter set is not built in.
|
||||
|
||||
\param [in] key SLH-DSA key with a populated private key.
|
||||
\param [out] output Buffer to receive the DER encoding, or NULL to query
|
||||
the required size.
|
||||
\param [in] inLen Size of output in bytes (ignored when output is NULL).
|
||||
|
||||
\sa wc_SlhDsaKey_KeyToDer
|
||||
\sa wc_SlhDsaKey_PrivateKeyDecode
|
||||
*/
|
||||
int wc_SlhDsaKey_PrivateKeyToDer(SlhDsaKey* key, byte* output, word32 inLen);
|
||||
|
||||
/*!
|
||||
\ingroup SLH_DSA
|
||||
|
||||
\brief Encodes an SLH-DSA public key to DER. When withAlg is non-zero
|
||||
the output is a full SubjectPublicKeyInfo structure (AlgorithmIdentifier
|
||||
plus BIT STRING). When withAlg is zero the output contains the raw
|
||||
public key bytes without the SPKI wrapping.
|
||||
|
||||
Available only when WC_ENABLE_ASYM_KEY_EXPORT is set.
|
||||
|
||||
\return Size of the encoded DER in bytes on success. Pass NULL as output
|
||||
to query the required buffer size.
|
||||
\return BAD_FUNC_ARG if key or key->params is NULL.
|
||||
\return BUFFER_E if output is non-NULL and inLen is smaller than the
|
||||
required size.
|
||||
\return NOT_COMPILED_IN if key->params names an SLH-DSA variant whose
|
||||
parameter set is not built in.
|
||||
|
||||
\param [in] key SLH-DSA key with a populated public key.
|
||||
\param [out] output Buffer to receive the DER encoding, or NULL to query
|
||||
the required size.
|
||||
\param [in] inLen Size of output in bytes (ignored when output is NULL).
|
||||
\param [in] withAlg Non-zero to emit SubjectPublicKeyInfo (with
|
||||
AlgorithmIdentifier); zero to emit the raw public key only.
|
||||
|
||||
\sa wc_SlhDsaKey_PublicKeyDecode
|
||||
\sa wc_SlhDsaKey_KeyToDer
|
||||
*/
|
||||
int wc_SlhDsaKey_PublicKeyToDer(SlhDsaKey* key, byte* output, word32 inLen,
|
||||
int withAlg);
|
||||
|
||||
@@ -1151,6 +1151,22 @@ int test_wc_slhdsa_sign_hash(void)
|
||||
WC_NO_ERR_TRACE(BAD_LENGTH_E));
|
||||
#endif
|
||||
|
||||
#ifdef WOLFSSL_SHAKE128
|
||||
/* SHAKE128 PHM is fixed at 256 bits per FIPS 205 Section 10.2.2. */
|
||||
sigLen = WC_SLHDSA_MAX_SIG_LEN;
|
||||
ExpectIntEQ(wc_SlhDsaKey_SignHash(&key, ctx, sizeof(ctx), hash, 32,
|
||||
WC_HASH_TYPE_SHAKE128, sig, &sigLen, &rng), 0);
|
||||
ExpectIntEQ(wc_SlhDsaKey_VerifyHash(&key, ctx, sizeof(ctx), hash, 32,
|
||||
WC_HASH_TYPE_SHAKE128, sig, sigLen), 0);
|
||||
/* SignHash and VerifyHash both reject mismatched digest length. */
|
||||
ExpectIntEQ(wc_SlhDsaKey_SignHash(&key, ctx, sizeof(ctx), hash, 64,
|
||||
WC_HASH_TYPE_SHAKE128, sig, &sigLen, &rng),
|
||||
WC_NO_ERR_TRACE(BAD_LENGTH_E));
|
||||
ExpectIntEQ(wc_SlhDsaKey_VerifyHash(&key, ctx, sizeof(ctx), hash, 64,
|
||||
WC_HASH_TYPE_SHAKE128, sig, sigLen),
|
||||
WC_NO_ERR_TRACE(BAD_LENGTH_E));
|
||||
#endif
|
||||
|
||||
#ifdef WOLFSSL_SHAKE256
|
||||
/* SHAKE256 PHM is fixed at 512 bits per FIPS 205 Section 10.2.2. */
|
||||
sigLen = WC_SLHDSA_MAX_SIG_LEN;
|
||||
@@ -1158,9 +1174,13 @@ int test_wc_slhdsa_sign_hash(void)
|
||||
WC_HASH_TYPE_SHAKE256, sig, &sigLen, &rng), 0);
|
||||
ExpectIntEQ(wc_SlhDsaKey_VerifyHash(&key, ctx, sizeof(ctx), hash, 64,
|
||||
WC_HASH_TYPE_SHAKE256, sig, sigLen), 0);
|
||||
/* SignHash and VerifyHash both reject mismatched digest length. */
|
||||
ExpectIntEQ(wc_SlhDsaKey_SignHash(&key, ctx, sizeof(ctx), hash, 32,
|
||||
WC_HASH_TYPE_SHAKE256, sig, &sigLen, &rng),
|
||||
WC_NO_ERR_TRACE(BAD_LENGTH_E));
|
||||
ExpectIntEQ(wc_SlhDsaKey_VerifyHash(&key, ctx, sizeof(ctx), hash, 32,
|
||||
WC_HASH_TYPE_SHAKE256, sig, sigLen),
|
||||
WC_NO_ERR_TRACE(BAD_LENGTH_E));
|
||||
#endif
|
||||
|
||||
wc_SlhDsaKey_Free(&key);
|
||||
|
||||
+30
-18
@@ -7015,7 +7015,7 @@ static int slhdsakey_sign_internal_msg(SlhDsaKey* key, const byte* m,
|
||||
|
||||
/* Upper-level sign: construct M' from ctx + msg, then call internal.
|
||||
*
|
||||
* FIPS 205. Section 10.2.2. Algorithm 22.
|
||||
* FIPS 205. Section 10.2.1. Algorithm 22.
|
||||
* slh_sign(M, ctx, SK)
|
||||
* 8: M' <- toByte(0, 1) || toByte(|ctx|, 1) || ctx || M
|
||||
* 9: SIG <- slh_sign_internal(M', SK, addrnd)
|
||||
@@ -7414,7 +7414,7 @@ static int slhdsakey_verify(SlhDsaKey* key, byte* md, const byte* sig)
|
||||
* 9: md <- digest [0 : upper(k.a / 8)] > first upper(k.a / 8) bytes
|
||||
* ...
|
||||
*
|
||||
* FIPS 205. Section 10.3. Algorithm 23.
|
||||
* FIPS 205. Section 10.3. Algorithm 24.
|
||||
* slh_verify(M, SIG, ctx, PK)
|
||||
* 1: if |ctx| > 255 then
|
||||
* 2: return false
|
||||
@@ -7464,7 +7464,7 @@ int wc_SlhDsaKey_Verify(SlhDsaKey* key, const byte* ctx, byte ctxSz,
|
||||
byte n = key->params->n;
|
||||
byte hdr[2];
|
||||
|
||||
/* Alg 23, Step 4: Make M' header. */
|
||||
/* Alg 24, Step 4: Make M' header. */
|
||||
hdr[0] = 0;
|
||||
hdr[1] = ctxSz;
|
||||
|
||||
@@ -7501,7 +7501,7 @@ int wc_SlhDsaKey_Verify(SlhDsaKey* key, const byte* ctx, byte ctxSz,
|
||||
}
|
||||
}
|
||||
if (ret == 0) {
|
||||
/* Alg 23, Step 5: Verify M'.
|
||||
/* Alg 24, Step 5: Verify M'.
|
||||
* Alg 20, Steps 4,6-18: Verify digest. */
|
||||
ret = slhdsakey_verify(key, md, sig);
|
||||
}
|
||||
@@ -7582,12 +7582,20 @@ int wc_SlhDsaKey_VerifyMsg(SlhDsaKey* key, const byte* mprime,
|
||||
/* All HashSLH-DSA hash OIDs are DER-encoded as tag(0x06) + length(0x09) + 9
|
||||
* bytes, so any approved hash OID is exactly 11 bytes. The PRF_msg / H_msg
|
||||
* input for the SHA-2 path is the concatenation OID || PHM, bounded by
|
||||
* SLHDSA_OID_MAX_LEN + WC_MAX_DIGEST_SIZE. WC_MAX_DIGEST_SIZE is the project-
|
||||
* wide max digest size (>= 64 today) and absorbs any future hash with a
|
||||
* larger digest as long as slhdsakey_validate_prehash continues to enforce
|
||||
* hashSz <= WC_MAX_DIGEST_SIZE. */
|
||||
#define SLHDSA_OID_MAX_LEN 11
|
||||
#define SLHDSA_PHMSG_MAX_LEN (SLHDSA_OID_MAX_LEN + WC_MAX_DIGEST_SIZE)
|
||||
* SLHDSA_OID_MAX_LEN + WC_MAX_DIGEST_SIZE. The PHM buffer fits in
|
||||
* WC_MAX_DIGEST_SIZE bytes because slhdsakey_validate_prehash enforces
|
||||
* hashSz == expectedLen[hashType] for every supported hashType and every
|
||||
* supported expectedLen is <= WC_MAX_DIGEST_SIZE. The largest FIPS 205
|
||||
* approved PHM is 64 bytes (SHA-512 digest size, also the SHAKE256 PHM
|
||||
* length fixed at 512 bits per Section 10.2.2). The static assert below
|
||||
* catches a future hash being added whose digest exceeds the bound. The
|
||||
* literal 64 is used directly because WC_SHA512_DIGEST_SIZE is only
|
||||
* defined when SHA-512 is compiled in. */
|
||||
#define SLHDSA_OID_MAX_LEN 11
|
||||
#define SLHDSA_LARGEST_APPROVED_PHM_LEN 64
|
||||
#define SLHDSA_PHMSG_MAX_LEN (SLHDSA_OID_MAX_LEN + \
|
||||
WC_MAX_DIGEST_SIZE)
|
||||
wc_static_assert(WC_MAX_DIGEST_SIZE >= SLHDSA_LARGEST_APPROVED_PHM_LEN);
|
||||
|
||||
#ifdef WOLFSSL_SHA224
|
||||
/* OID for SHA-224 for hash signing/verification. */
|
||||
@@ -7863,13 +7871,13 @@ static int slhdsakey_validate_prehash(word32 hashSz,
|
||||
* @return BAD_FUNC_ARG when ctx is NULL but ctx length is greater than 0.
|
||||
* @return BAD_LENGTH_E when sigSz is less than required signature length, or
|
||||
* when hashSz does not equal the digest size for hashType.
|
||||
* @return NOT_COMPILED in when hash algorithm is not supported.
|
||||
* @return NOT_COMPILED_IN when hash algorithm is not supported.
|
||||
* @return MEMORY_E on dynamic memory allocation failure.
|
||||
* @return SHAKE-256 error return code on digest failure.
|
||||
*/
|
||||
static int slhdsakey_signhash_external(SlhDsaKey* key, const byte* ctx,
|
||||
byte ctxSz, const byte* hash, word32 hashSz, enum wc_HashType hashType,
|
||||
byte* sig, word32* sigSz, byte* addRnd)
|
||||
byte* sig, word32* sigSz, const byte* addRnd)
|
||||
{
|
||||
int ret = 0;
|
||||
const byte* oid = NULL;
|
||||
@@ -8064,7 +8072,7 @@ int wc_SlhDsaKey_SignHashDeterministic(SlhDsaKey* key, const byte* ctx,
|
||||
*/
|
||||
int wc_SlhDsaKey_SignHashWithRandom(SlhDsaKey* key, const byte* ctx, byte ctxSz,
|
||||
const byte* hash, word32 hashSz, enum wc_HashType hashType, byte* sig,
|
||||
word32* sigSz, byte* addRnd)
|
||||
word32* sigSz, const byte* addRnd)
|
||||
{
|
||||
/* HashSLH-DSA sign with caller-supplied digest. */
|
||||
return slhdsakey_signhash_external(key, ctx, ctxSz, hash, hashSz, hashType,
|
||||
@@ -8105,7 +8113,11 @@ int wc_SlhDsaKey_SignHash(SlhDsaKey* key, const byte* ctx, byte ctxSz,
|
||||
int ret = 0;
|
||||
byte addRnd[SLHDSA_MAX_N];
|
||||
|
||||
/* Validate parameters before generating random. */
|
||||
/* Validate parameters before generating random.
|
||||
* hashSz / hashType validation lives in the internal worker and therefore
|
||||
* runs after wc_RNG_GenerateBlock. A call with a bad hashSz/hashType will
|
||||
* waste n bytes of DRBG output before the error is reported (similar to
|
||||
* ML-DSA pre-hash handling). */
|
||||
if ((key == NULL) || (key->params == NULL) ||
|
||||
((ctx == NULL) && (ctxSz > 0)) || (hash == NULL) || (sig == NULL) ||
|
||||
(sigSz == NULL) || (rng == NULL)) {
|
||||
@@ -8149,7 +8161,7 @@ int wc_SlhDsaKey_SignHash(SlhDsaKey* key, const byte* ctx, byte ctxSz,
|
||||
* 9: md <- digest [0 : upper(k.a / 8)] > first upper(k.a / 8) bytes
|
||||
* ...
|
||||
*
|
||||
* FIPS 205. Section 10.3. Algorithm 24.
|
||||
* FIPS 205. Section 10.3. Algorithm 25.
|
||||
* hash_slh_verify(M, SIG, ctx, PH, PK)
|
||||
* 1: if |ctx| > 255 then
|
||||
* 2: return false
|
||||
@@ -8222,7 +8234,7 @@ int wc_SlhDsaKey_VerifyHash(SlhDsaKey* key, const byte* ctx, byte ctxSz,
|
||||
ret = MISSING_KEY;
|
||||
}
|
||||
if (ret == 0) {
|
||||
/* Alg 24, Steps 4-19: Validate caller-supplied pre-hashed digest length
|
||||
/* Alg 25, Steps 4-19: Validate caller-supplied pre-hashed digest length
|
||||
* and select OID for the chosen hash algorithm. */
|
||||
ret = slhdsakey_validate_prehash(hashSz, hashType, &oid, &oidLen);
|
||||
}
|
||||
@@ -8231,7 +8243,7 @@ int wc_SlhDsaKey_VerifyHash(SlhDsaKey* key, const byte* ctx, byte ctxSz,
|
||||
byte md[SLHDSA_MAX_MD];
|
||||
byte hdr[2];
|
||||
|
||||
/* Alg 24, Step 20: Make M' header. */
|
||||
/* Alg 25, Step 20: Make M' header. */
|
||||
hdr[0] = 1;
|
||||
hdr[1] = ctxSz;
|
||||
|
||||
@@ -8277,7 +8289,7 @@ int wc_SlhDsaKey_VerifyHash(SlhDsaKey* key, const byte* ctx, byte ctxSz,
|
||||
}
|
||||
}
|
||||
if (ret == 0) {
|
||||
/* Alg 24, Step 21: Verify M'.
|
||||
/* Alg 25, Step 21: Verify M'.
|
||||
* Alg 20, Steps 4,6-18: Verify digest. */
|
||||
ret = slhdsakey_verify(key, md, sig);
|
||||
}
|
||||
|
||||
@@ -685,7 +685,7 @@ WOLFSSL_API int wc_SlhDsaKey_SignHashDeterministic(SlhDsaKey* key,
|
||||
enum wc_HashType hashType, byte* sig, word32* sigSz);
|
||||
WOLFSSL_API int wc_SlhDsaKey_SignHashWithRandom(SlhDsaKey* key,
|
||||
const byte* ctx, byte ctxSz, const byte* hash, word32 hashSz,
|
||||
enum wc_HashType hashType, byte* sig, word32* sigSz, byte* addRnd);
|
||||
enum wc_HashType hashType, byte* sig, word32* sigSz, const byte* addRnd);
|
||||
WOLFSSL_API int wc_SlhDsaKey_SignHash(SlhDsaKey* key, const byte* ctx,
|
||||
byte ctxSz, const byte* hash, word32 hashSz, enum wc_HashType hashType,
|
||||
byte* sig, word32* sigSz, WC_RNG* rng);
|
||||
|
||||
Reference in New Issue
Block a user