mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-07-06 06:30:49 +02:00
Merge pull request #10450 from Frauschi/slhdsa_pre_hash
HashSLH-DSA APIs take the pre-hashed digest, not the raw message
This commit is contained in:
+181
-108
@@ -7266,9 +7266,11 @@ int wc_SlhDsaKey_Sign(SlhDsaKey* key, const byte* ctx, byte ctxSz,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Sign using internal interface -- M' provided directly (deterministic).
|
||||
/* Sign using the FIPS 205 internal interface (Algorithm 19) -- M' provided
|
||||
* directly by the caller, deterministic variant (opt_rand = PK.seed).
|
||||
*
|
||||
* opt_rand = PK.seed for the deterministic variant.
|
||||
* Used for HashSLH-DSA implementations that build M' externally and for ACVP
|
||||
* signatureInterface=internal test vectors.
|
||||
*
|
||||
* @param [in] key SLH-DSA key.
|
||||
* @param [in] mprime M' message (already in internal format).
|
||||
@@ -7276,16 +7278,29 @@ int wc_SlhDsaKey_Sign(SlhDsaKey* key, const byte* ctx, byte ctxSz,
|
||||
* @param [out] sig Buffer to hold signature.
|
||||
* @param [in, out] sigSz On in, buffer length. On out, signature length.
|
||||
* @return 0 on success.
|
||||
* @return BAD_FUNC_ARG when key, key's parameters, mprime, sig or sigSz is
|
||||
* NULL.
|
||||
* @return BAD_LENGTH_E when sigSz is less than required signature length.
|
||||
* @return MISSING_KEY when private key not set.
|
||||
* @return MEMORY_E on dynamic memory allocation failure.
|
||||
* @return SHAKE-256 error return code on digest failure.
|
||||
*/
|
||||
int wc_SlhDsaKey_SignMsgDeterministic(SlhDsaKey* key, const byte* mprime,
|
||||
word32 mprimeSz, byte* sig, word32* sigSz)
|
||||
{
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
if ((key == NULL) || (key->params == NULL)) {
|
||||
if ((key == NULL) || (key->params == NULL) || (mprime == NULL) ||
|
||||
(sig == NULL) || (sigSz == NULL)) {
|
||||
ret = BAD_FUNC_ARG;
|
||||
}
|
||||
else {
|
||||
else if (*sigSz < key->params->sigLen) {
|
||||
ret = BAD_LENGTH_E;
|
||||
}
|
||||
else if ((key->flags & WC_SLHDSA_FLAG_PRIVATE) == 0) {
|
||||
ret = MISSING_KEY;
|
||||
}
|
||||
if (ret == 0) {
|
||||
ret = slhdsakey_sign_internal_msg(key, mprime, mprimeSz, sig, sigSz,
|
||||
key->sk + 2 * key->params->n);
|
||||
}
|
||||
@@ -7293,7 +7308,11 @@ int wc_SlhDsaKey_SignMsgDeterministic(SlhDsaKey* key, const byte* mprime,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Sign using internal interface -- M' provided directly (with explicit random).
|
||||
/* Sign using the FIPS 205 internal interface (Algorithm 19) -- M' provided
|
||||
* directly by the caller, with explicit randomness.
|
||||
*
|
||||
* Used for HashSLH-DSA implementations that build M' externally and for ACVP
|
||||
* signatureInterface=internal test vectors.
|
||||
*
|
||||
* @param [in] key SLH-DSA key.
|
||||
* @param [in] mprime M' message (already in internal format).
|
||||
@@ -7302,12 +7321,34 @@ int wc_SlhDsaKey_SignMsgDeterministic(SlhDsaKey* key, const byte* mprime,
|
||||
* @param [in, out] sigSz On in, buffer length. On out, signature length.
|
||||
* @param [in] addRnd opt_rand value.
|
||||
* @return 0 on success.
|
||||
* @return BAD_FUNC_ARG when key, key's parameters, mprime, sig, sigSz or
|
||||
* addRnd is NULL.
|
||||
* @return BAD_LENGTH_E when sigSz is less than required signature length.
|
||||
* @return MISSING_KEY when private key not set.
|
||||
* @return MEMORY_E on dynamic memory allocation failure.
|
||||
* @return SHAKE-256 error return code on digest failure.
|
||||
*/
|
||||
int wc_SlhDsaKey_SignMsgWithRandom(SlhDsaKey* key, const byte* mprime,
|
||||
word32 mprimeSz, byte* sig, word32* sigSz, const byte* addRnd)
|
||||
{
|
||||
return slhdsakey_sign_internal_msg(key, mprime, mprimeSz, sig, sigSz,
|
||||
addRnd);
|
||||
int ret = 0;
|
||||
|
||||
if ((key == NULL) || (key->params == NULL) || (mprime == NULL) ||
|
||||
(sig == NULL) || (sigSz == NULL) || (addRnd == NULL)) {
|
||||
ret = BAD_FUNC_ARG;
|
||||
}
|
||||
else if (*sigSz < key->params->sigLen) {
|
||||
ret = BAD_LENGTH_E;
|
||||
}
|
||||
else if ((key->flags & WC_SLHDSA_FLAG_PRIVATE) == 0) {
|
||||
ret = MISSING_KEY;
|
||||
}
|
||||
if (ret == 0) {
|
||||
ret = slhdsakey_sign_internal_msg(key, mprime, mprimeSz, sig, sigSz,
|
||||
addRnd);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* !WOLFSSL_SLHDSA_VERIFY_ONLY */
|
||||
@@ -7538,6 +7579,16 @@ int wc_SlhDsaKey_VerifyMsg(SlhDsaKey* key, const byte* mprime,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
|
||||
#ifdef WOLFSSL_SHA224
|
||||
/* OID for SHA-224 for hash signing/verification. */
|
||||
static const byte slhdsakey_oid_sha224[] = {
|
||||
@@ -7613,70 +7664,73 @@ static const byte slhdsakey_oid_sha3_512[] = {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Pre-hash the message with the hash specified.
|
||||
/* Validate the caller-supplied pre-hashed digest length and look up the
|
||||
* corresponding OID for the chosen hash algorithm.
|
||||
*
|
||||
* @param [in] msg Message to hash.
|
||||
* @param [in] msgSz Length of message in bytes.
|
||||
* @param [in] hashType Hash algorithm.
|
||||
* @param [out] ph Prehash buffer.
|
||||
* @param [out] phLen Length of prehash data.
|
||||
* The HashSLH-DSA family takes the digest as input rather than the full
|
||||
* message. This mirrors the wc_dilithium_*_ctx_hash interface and matches the
|
||||
* convention used by NIST ACVP signatureInterface=external / preHash test
|
||||
* vectors and other libraries (OpenSSL HASH-ML-DSA, leancrypto SLH-DSA,
|
||||
* mldsa-native pre_hash_internal). The expected digest length is fixed by
|
||||
* FIPS 205 Section 10.2.2 and equals wc_HashGetDigestSize(hashType) for the
|
||||
* fixed-output hashes; for SHAKE128/256 the standard fixes the XOF output to
|
||||
* 256/512 bits respectively. Callers feed the caller-supplied digest buffer
|
||||
* directly into the M' construction -- there is no copy.
|
||||
*
|
||||
* @param [in] hashSz Length of the caller-supplied digest in bytes.
|
||||
* @param [in] hashType Hash algorithm identifier (selects OID and length).
|
||||
* @param [out] oid OID data for hash algorithm.
|
||||
* @param [out] oidLen Length of OID data for hash algorithm.
|
||||
* @return 0 on success.
|
||||
* @return BAD_LENGTH_E when hashSz does not equal the expected digest size.
|
||||
* @return NOT_COMPILED_IN when hash algorithm not supported.
|
||||
*/
|
||||
static int slhdsakey_prehash_msg(const byte* msg, word32 msgSz,
|
||||
enum wc_HashType hashType, byte* ph, byte* phLen, const byte** oid,
|
||||
byte* oidLen)
|
||||
static int slhdsakey_validate_prehash(word32 hashSz,
|
||||
enum wc_HashType hashType, const byte** oid, byte* oidLen)
|
||||
{
|
||||
int ret;
|
||||
int ret = 0;
|
||||
word32 expectedLen = 0;
|
||||
|
||||
switch ((int)hashType) {
|
||||
#ifdef WOLFSSL_SHA224
|
||||
case WC_HASH_TYPE_SHA224:
|
||||
*oid = slhdsakey_oid_sha224;
|
||||
*oidLen = (byte)sizeof(slhdsakey_oid_sha224);
|
||||
*phLen = WC_SHA224_DIGEST_SIZE;
|
||||
ret = wc_Sha224Hash(msg, msgSz, ph);
|
||||
expectedLen = WC_SHA224_DIGEST_SIZE;
|
||||
break;
|
||||
#endif
|
||||
#ifndef NO_SHA256
|
||||
case WC_HASH_TYPE_SHA256:
|
||||
*oid = slhdsakey_oid_sha256;
|
||||
*oidLen = (byte)sizeof(slhdsakey_oid_sha256);
|
||||
*phLen = WC_SHA256_DIGEST_SIZE;
|
||||
ret = wc_Sha256Hash(msg, msgSz, ph);
|
||||
expectedLen = WC_SHA256_DIGEST_SIZE;
|
||||
break;
|
||||
#endif
|
||||
#ifdef WOLFSSL_SHA384
|
||||
case WC_HASH_TYPE_SHA384:
|
||||
*oid = slhdsakey_oid_sha384;
|
||||
*oidLen = (byte)sizeof(slhdsakey_oid_sha384);
|
||||
*phLen = WC_SHA384_DIGEST_SIZE;
|
||||
ret = wc_Sha384Hash(msg, msgSz, ph);
|
||||
expectedLen = WC_SHA384_DIGEST_SIZE;
|
||||
break;
|
||||
#endif
|
||||
#ifdef WOLFSSL_SHA512
|
||||
case WC_HASH_TYPE_SHA512:
|
||||
*oid = slhdsakey_oid_sha512;
|
||||
*oidLen = (byte)sizeof(slhdsakey_oid_sha512);
|
||||
*phLen = WC_SHA512_DIGEST_SIZE;
|
||||
ret = wc_Sha512Hash(msg, msgSz, ph);
|
||||
expectedLen = WC_SHA512_DIGEST_SIZE;
|
||||
break;
|
||||
#ifndef WOLFSSL_NOSHA512_224
|
||||
case WC_HASH_TYPE_SHA512_224:
|
||||
*oid = slhdsakey_oid_sha512_224;
|
||||
*oidLen = (byte)sizeof(slhdsakey_oid_sha512_224);
|
||||
*phLen = WC_SHA512_224_DIGEST_SIZE;
|
||||
ret = wc_Sha512_224Hash(msg, msgSz, ph);
|
||||
expectedLen = WC_SHA512_224_DIGEST_SIZE;
|
||||
break;
|
||||
#endif
|
||||
#ifndef WOLFSSL_NOSHA512_256
|
||||
case WC_HASH_TYPE_SHA512_256:
|
||||
*oid = slhdsakey_oid_sha512_256;
|
||||
*oidLen = (byte)sizeof(slhdsakey_oid_sha512_256);
|
||||
*phLen = WC_SHA512_256_DIGEST_SIZE;
|
||||
ret = wc_Sha512_256Hash(msg, msgSz, ph);
|
||||
expectedLen = WC_SHA512_256_DIGEST_SIZE;
|
||||
break;
|
||||
#endif
|
||||
#endif
|
||||
@@ -7684,16 +7738,16 @@ static int slhdsakey_prehash_msg(const byte* msg, word32 msgSz,
|
||||
case WC_HASH_TYPE_SHAKE128:
|
||||
*oid = slhdsakey_oid_shake128;
|
||||
*oidLen = (byte)sizeof(slhdsakey_oid_shake128);
|
||||
*phLen = WC_SHA3_256_DIGEST_SIZE;
|
||||
ret = wc_Shake128Hash(msg, msgSz, ph, WC_SHA3_256_DIGEST_SIZE);
|
||||
/* FIPS 205 Section 10.2.2 fixes SHAKE128 PHM length at 256 bits. */
|
||||
expectedLen = WC_SHA3_256_DIGEST_SIZE;
|
||||
break;
|
||||
#endif
|
||||
#ifdef WOLFSSL_SHAKE256
|
||||
case WC_HASH_TYPE_SHAKE256:
|
||||
*oid = slhdsakey_oid_shake256;
|
||||
*oidLen = (byte)sizeof(slhdsakey_oid_shake256);
|
||||
*phLen = WC_SHA3_512_DIGEST_SIZE;
|
||||
ret = wc_Shake256Hash(msg, msgSz, ph, WC_SHA3_512_DIGEST_SIZE);
|
||||
/* FIPS 205 Section 10.2.2 fixes SHAKE256 PHM length at 512 bits. */
|
||||
expectedLen = WC_SHA3_512_DIGEST_SIZE;
|
||||
break;
|
||||
#endif
|
||||
#ifdef WOLFSSL_SHA3
|
||||
@@ -7701,32 +7755,28 @@ static int slhdsakey_prehash_msg(const byte* msg, word32 msgSz,
|
||||
case WC_HASH_TYPE_SHA3_224:
|
||||
*oid = slhdsakey_oid_sha3_224;
|
||||
*oidLen = (byte)sizeof(slhdsakey_oid_sha3_224);
|
||||
*phLen = WC_SHA3_224_DIGEST_SIZE;
|
||||
ret = wc_Sha3_224Hash(msg, msgSz, ph);
|
||||
expectedLen = WC_SHA3_224_DIGEST_SIZE;
|
||||
break;
|
||||
#endif
|
||||
#ifndef WOLFSSL_NOSHA3_256
|
||||
case WC_HASH_TYPE_SHA3_256:
|
||||
*oid = slhdsakey_oid_sha3_256;
|
||||
*oidLen = (byte)sizeof(slhdsakey_oid_sha3_256);
|
||||
*phLen = WC_SHA3_256_DIGEST_SIZE;
|
||||
ret = wc_Sha3_256Hash(msg, msgSz, ph);
|
||||
expectedLen = WC_SHA3_256_DIGEST_SIZE;
|
||||
break;
|
||||
#endif
|
||||
#ifndef WOLFSSL_NOSHA3_384
|
||||
case WC_HASH_TYPE_SHA3_384:
|
||||
*oid = slhdsakey_oid_sha3_384;
|
||||
*oidLen = (byte)sizeof(slhdsakey_oid_sha3_384);
|
||||
*phLen = WC_SHA3_384_DIGEST_SIZE;
|
||||
ret = wc_Sha3_384Hash(msg, msgSz, ph);
|
||||
expectedLen = WC_SHA3_384_DIGEST_SIZE;
|
||||
break;
|
||||
#endif
|
||||
#ifndef WOLFSSL_NOSHA3_512
|
||||
case WC_HASH_TYPE_SHA3_512:
|
||||
*oid = slhdsakey_oid_sha3_512;
|
||||
*oidLen = (byte)sizeof(slhdsakey_oid_sha3_512);
|
||||
*phLen = WC_SHA3_512_DIGEST_SIZE;
|
||||
ret = wc_Sha3_512Hash(msg, msgSz, ph);
|
||||
expectedLen = WC_SHA3_512_DIGEST_SIZE;
|
||||
break;
|
||||
#endif
|
||||
#endif
|
||||
@@ -7735,6 +7785,10 @@ static int slhdsakey_prehash_msg(const byte* msg, word32 msgSz,
|
||||
break;
|
||||
}
|
||||
|
||||
if ((ret == 0) && (hashSz != expectedLen)) {
|
||||
ret = BAD_LENGTH_E;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -7790,37 +7844,40 @@ static int slhdsakey_prehash_msg(const byte* msg, word32 msgSz,
|
||||
*
|
||||
* Note: ctx length is of type byte which means it can never be more than 255.
|
||||
*
|
||||
* The caller MUST pre-hash the application message with hashType before
|
||||
* calling and pass the digest as hash. hashSz must equal the digest size of
|
||||
* hashType (32 for SHAKE128, 64 for SHAKE256 per FIPS 205 Section 10.2.2).
|
||||
*
|
||||
* @param [in] key SLH-DSA key.
|
||||
* @param [in] ctx Context of signing.
|
||||
* @param [in] ctxSz Length of context in bytes.
|
||||
* @param [in] msg Message to sign.
|
||||
* @param [in] msgSz Length of message in bytes.
|
||||
* @param [in] hashType Hash algorithm to use in pre-hash.
|
||||
* @param [in] hash Pre-hashed message digest to sign.
|
||||
* @param [in] hashSz Length of digest in bytes.
|
||||
* @param [in] hashType Hash algorithm used for pre-hash (selects OID).
|
||||
* @param [out] sig Buffer to hold signature.
|
||||
* @param [in, out] sigSz On in, length of signature buffer.
|
||||
* On out, length of signature data.
|
||||
* @return 0 on success.
|
||||
* @return BAD_FUNC_ARG when key, key's parameters, msg, sig, sigSz or addRnd
|
||||
* @return BAD_FUNC_ARG when key, key's parameters, hash, sig, sigSz or addRnd
|
||||
* is NULL.
|
||||
* @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.
|
||||
* @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 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* msg, word32 msgSz, enum wc_HashType hashType,
|
||||
byte ctxSz, const byte* hash, word32 hashSz, enum wc_HashType hashType,
|
||||
byte* sig, word32* sigSz, byte* addRnd)
|
||||
{
|
||||
int ret = 0;
|
||||
byte ph[WC_MAX_DIGEST_SIZE];
|
||||
byte phLen = 0;
|
||||
const byte* oid = NULL;
|
||||
byte oidLen = 0;
|
||||
|
||||
/* Validate parameters. */
|
||||
if ((key == NULL) || (key->params == NULL) ||
|
||||
((ctx == NULL) && (ctxSz > 0)) || (msg == NULL) || (sig == NULL) ||
|
||||
((ctx == NULL) && (ctxSz > 0)) || (hash == NULL) || (sig == NULL) ||
|
||||
(sigSz == NULL)) {
|
||||
ret = BAD_FUNC_ARG;
|
||||
}
|
||||
@@ -7834,10 +7891,9 @@ static int slhdsakey_signhash_external(SlhDsaKey* key, const byte* ctx,
|
||||
ret = BAD_FUNC_ARG;
|
||||
}
|
||||
if (ret == 0) {
|
||||
/* Alg 23, Steps 8-23: Pre-hash message with hash algorithm specified.
|
||||
*/
|
||||
ret = slhdsakey_prehash_msg(msg, msgSz, hashType, ph, &phLen, &oid,
|
||||
&oidLen);
|
||||
/* Alg 23, Steps 8-23: Validate caller-supplied pre-hashed digest length
|
||||
* and select OID for the chosen hash algorithm. */
|
||||
ret = slhdsakey_validate_prehash(hashSz, hashType, &oid, &oidLen);
|
||||
}
|
||||
if (ret == 0) {
|
||||
byte n = key->params->n;
|
||||
@@ -7850,12 +7906,12 @@ static int slhdsakey_signhash_external(SlhDsaKey* key, const byte* ctx,
|
||||
|
||||
#ifdef WOLFSSL_SLHDSA_SHA2
|
||||
if (SLHDSA_IS_SHA2(key->params->param)) {
|
||||
/* SHA2: Build oid||ph as message for PRF_msg/H_msg. */
|
||||
byte phMsg[80]; /* Max: 11 byte OID + 64 byte hash */
|
||||
word32 phMsgLen = (word32)oidLen + phLen;
|
||||
/* SHA2: Build oid||hash as message for PRF_msg/H_msg. */
|
||||
byte phMsg[SLHDSA_PHMSG_MAX_LEN];
|
||||
word32 phMsgLen = (word32)oidLen + hashSz;
|
||||
|
||||
XMEMCPY(phMsg, oid, oidLen);
|
||||
XMEMCPY(phMsg + oidLen, ph, phLen);
|
||||
XMEMCPY(phMsg + oidLen, hash, hashSz);
|
||||
|
||||
ret = slhdsakey_prf_msg_sha2(key, key->sk + n, addRnd, hdr, ctx,
|
||||
ctxSz, phMsg, phMsgLen, n, sig);
|
||||
@@ -7885,7 +7941,7 @@ static int slhdsakey_signhash_external(SlhDsaKey* key, const byte* ctx,
|
||||
ret = slhdsakey_hash_update(&key->hash.shk.shake, oid, oidLen);
|
||||
}
|
||||
if (ret == 0) {
|
||||
ret = slhdsakey_hash_update(&key->hash.shk.shake, ph, phLen);
|
||||
ret = slhdsakey_hash_update(&key->hash.shk.shake, hash, hashSz);
|
||||
}
|
||||
if (ret == 0) {
|
||||
ret = slhdsakey_hash_final(&key->hash.shk.shake, sig, n);
|
||||
@@ -7910,7 +7966,7 @@ static int slhdsakey_signhash_external(SlhDsaKey* key, const byte* ctx,
|
||||
ret = slhdsakey_hash_update(&key->hash.shk.shake, oid, oidLen);
|
||||
}
|
||||
if (ret == 0) {
|
||||
ret = slhdsakey_hash_update(&key->hash.shk.shake, ph, phLen);
|
||||
ret = slhdsakey_hash_update(&key->hash.shk.shake, hash, hashSz);
|
||||
}
|
||||
if (ret == 0) {
|
||||
ret = slhdsakey_hash_final(&key->hash.shk.shake, md,
|
||||
@@ -7931,29 +7987,33 @@ static int slhdsakey_signhash_external(SlhDsaKey* key, const byte* ctx,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Generate a deterministic pre-hash SLH-DSA signature.
|
||||
/* Generate a deterministic HashSLH-DSA signature.
|
||||
*
|
||||
* addrnd is the public key seed.
|
||||
* addrnd is the public key seed. The caller MUST pre-hash the application
|
||||
* message with hashType before calling and pass the digest as hash; hashSz
|
||||
* must equal the digest size of hashType (32 for SHAKE128, 64 for SHAKE256
|
||||
* per FIPS 205 Section 10.2.2).
|
||||
*
|
||||
* @param [in] key SLH-DSA key.
|
||||
* @param [in] ctx Context of signing.
|
||||
* @param [in] ctxSz Length of context in bytes.
|
||||
* @param [in] msg Message to sign.
|
||||
* @param [in] msgSz Length of message in bytes.
|
||||
* @param [in] hashType Hash algorithm to use in pre-hash.
|
||||
* @param [in] hash Pre-hashed message digest to sign.
|
||||
* @param [in] hashSz Length of digest in bytes.
|
||||
* @param [in] hashType Hash algorithm used for pre-hash (selects OID).
|
||||
* @param [out] sig Buffer to hold signature.
|
||||
* @param [in, out] sigSz On in, length of signature buffer.
|
||||
* On out, length of signature data.
|
||||
* @return 0 on success.
|
||||
* @return BAD_FUNC_ARG when key, key's parameters, msg, sig or sigSz is NULL.
|
||||
* @return BAD_FUNC_ARG when key, key's parameters, hash, sig or sigSz is NULL.
|
||||
* @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.
|
||||
* @return BAD_LENGTH_E when sigSz is less than required signature length, or
|
||||
* when hashSz does not equal the digest size for hashType.
|
||||
* @return MISSING_KEY when private key not set.
|
||||
* @return MEMORY_E on dynamic memory allocation failure.
|
||||
* @return SHAKE-256 error return code on digest failure.
|
||||
*/
|
||||
int wc_SlhDsaKey_SignHashDeterministic(SlhDsaKey* key, const byte* ctx,
|
||||
byte ctxSz, const byte* msg, word32 msgSz, enum wc_HashType hashType,
|
||||
byte ctxSz, const byte* hash, word32 hashSz, enum wc_HashType hashType,
|
||||
byte* sig, word32* sigSz)
|
||||
{
|
||||
int ret;
|
||||
@@ -7967,68 +8027,79 @@ int wc_SlhDsaKey_SignHashDeterministic(SlhDsaKey* key, const byte* ctx,
|
||||
ret = MISSING_KEY;
|
||||
}
|
||||
else {
|
||||
/* Pre-hash sign. */
|
||||
ret = slhdsakey_signhash_external(key, ctx, ctxSz, msg, msgSz, hashType,
|
||||
sig, sigSz, key->sk + 2 * key->params->n);
|
||||
/* HashSLH-DSA sign with caller-supplied digest. */
|
||||
ret = slhdsakey_signhash_external(key, ctx, ctxSz, hash, hashSz,
|
||||
hashType, sig, sigSz, key->sk + 2 * key->params->n);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Generate a pre-hash SLH-DSA signature.
|
||||
/* Generate a HashSLH-DSA signature with explicit randomness.
|
||||
*
|
||||
* The caller MUST pre-hash the application message with hashType before
|
||||
* calling and pass the digest as hash; hashSz must equal the digest size of
|
||||
* hashType (32 for SHAKE128, 64 for SHAKE256 per FIPS 205 Section 10.2.2).
|
||||
*
|
||||
* @param [in] key SLH-DSA key.
|
||||
* @param [in] ctx Context of signing.
|
||||
* @param [in] ctxSz Length of context in bytes.
|
||||
* @param [in] msg Message to sign.
|
||||
* @param [in] msgSz Length of message in bytes.
|
||||
* @param [in] hashType Hash algorithm to use in pre-hash.
|
||||
* @param [in] hash Pre-hashed message digest to sign.
|
||||
* @param [in] hashSz Length of digest in bytes.
|
||||
* @param [in] hashType Hash algorithm used for pre-hash (selects OID).
|
||||
* @param [out] sig Buffer to hold signature.
|
||||
* @param [in, out] sigSz On in, length of signature buffer.
|
||||
* On out, length of signature data.
|
||||
* @param [in] addRnd Additional random for signature.
|
||||
* @return 0 on success.
|
||||
* @return BAD_FUNC_ARG when key, key's parameters, msg, sig, sigSz or addrnd
|
||||
* @return BAD_FUNC_ARG when key, key's parameters, hash, sig, sigSz or addrnd
|
||||
* is NULL.
|
||||
* @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.
|
||||
* @return BAD_LENGTH_E when sigSz is less than required signature length, or
|
||||
* when hashSz does not equal the digest size for hashType.
|
||||
* @return MISSING_KEY when private key not set.
|
||||
* @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.
|
||||
*/
|
||||
int wc_SlhDsaKey_SignHashWithRandom(SlhDsaKey* key, const byte* ctx, byte ctxSz,
|
||||
const byte* msg, word32 msgSz, enum wc_HashType hashType, byte* sig,
|
||||
const byte* hash, word32 hashSz, enum wc_HashType hashType, byte* sig,
|
||||
word32* sigSz, byte* addRnd)
|
||||
{
|
||||
/* Pre-hash sign */
|
||||
return slhdsakey_signhash_external(key, ctx, ctxSz, msg, msgSz, hashType,
|
||||
/* HashSLH-DSA sign with caller-supplied digest. */
|
||||
return slhdsakey_signhash_external(key, ctx, ctxSz, hash, hashSz, hashType,
|
||||
sig, sigSz, addRnd);
|
||||
}
|
||||
|
||||
/* Generate a pre-hash SLH-DSA signature with a random number generator.
|
||||
/* Generate a HashSLH-DSA signature using an RNG for added randomness.
|
||||
*
|
||||
* The caller MUST pre-hash the application message with hashType before
|
||||
* calling and pass the digest as hash; hashSz must equal the digest size of
|
||||
* hashType (32 for SHAKE128, 64 for SHAKE256 per FIPS 205 Section 10.2.2).
|
||||
*
|
||||
* @param [in] key SLH-DSA key.
|
||||
* @param [in] ctx Context of signing.
|
||||
* @param [in] ctxSz Length of context in bytes.
|
||||
* @param [in] msg Message to sign.
|
||||
* @param [in] msgSz Length of message in bytes.
|
||||
* @param [in] hashType Hash algorithm to use in pre-hash.
|
||||
* @param [in] hash Pre-hashed message digest to sign.
|
||||
* @param [in] hashSz Length of digest in bytes.
|
||||
* @param [in] hashType Hash algorithm used for pre-hash (selects OID).
|
||||
* @param [out] sig Buffer to hold signature.
|
||||
* @param [in, out] sigSz On in, length of signature buffer.
|
||||
* On out, length of signature data.
|
||||
* @param [in] rng Random number generator.
|
||||
* @return 0 on success.
|
||||
* @return BAD_FUNC_ARG when key, key's parameters, msg, sig, sigSz or rng is
|
||||
* @return BAD_FUNC_ARG when key, key's parameters, hash, sig, sigSz or rng is
|
||||
* NULL.
|
||||
* @return BAD_FUNC_ARG when ctx is NULL but ctx length is greater than 0.
|
||||
* @return BAD_LENGTH_E when hashSz does not equal the digest size for
|
||||
* hashType.
|
||||
* @return MISSING_KEY when private key not set.
|
||||
* @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.
|
||||
*/
|
||||
int wc_SlhDsaKey_SignHash(SlhDsaKey* key, const byte* ctx, byte ctxSz,
|
||||
const byte* msg, word32 msgSz, enum wc_HashType hashType, byte* sig,
|
||||
const byte* hash, word32 hashSz, enum wc_HashType hashType, byte* sig,
|
||||
word32* sigSz, WC_RNG* rng)
|
||||
{
|
||||
int ret = 0;
|
||||
@@ -8036,7 +8107,7 @@ int wc_SlhDsaKey_SignHash(SlhDsaKey* key, const byte* ctx, byte ctxSz,
|
||||
|
||||
/* Validate parameters before generating random. */
|
||||
if ((key == NULL) || (key->params == NULL) ||
|
||||
((ctx == NULL) && (ctxSz > 0)) || (msg == NULL) || (sig == NULL) ||
|
||||
((ctx == NULL) && (ctxSz > 0)) || (hash == NULL) || (sig == NULL) ||
|
||||
(sigSz == NULL) || (rng == NULL)) {
|
||||
ret = BAD_FUNC_ARG;
|
||||
}
|
||||
@@ -8053,8 +8124,8 @@ int wc_SlhDsaKey_SignHash(SlhDsaKey* key, const byte* ctx, byte ctxSz,
|
||||
ret = wc_RNG_GenerateBlock(rng, addRnd, key->params->n);
|
||||
}
|
||||
if (ret == 0) {
|
||||
/* Pre-hash sign. */
|
||||
ret = wc_SlhDsaKey_SignHashWithRandom(key, ctx, ctxSz, msg, msgSz,
|
||||
/* HashSLH-DSA sign with caller-supplied digest. */
|
||||
ret = wc_SlhDsaKey_SignHashWithRandom(key, ctx, ctxSz, hash, hashSz,
|
||||
hashType, sig, sigSz, addRnd);
|
||||
}
|
||||
|
||||
@@ -8106,36 +8177,39 @@ int wc_SlhDsaKey_SignHash(SlhDsaKey* key, const byte* ctx, byte ctxSz,
|
||||
* 20: M' <- toByte(1, 1) || toByte(|ctx|, 1) || ctx || OID || PHM
|
||||
* 21: return slh_verify_internal(M', SIG, PK)
|
||||
*
|
||||
* The caller MUST pre-hash the application message with hashType before
|
||||
* calling and pass the digest as hash; hashSz must equal the digest size of
|
||||
* hashType (32 for SHAKE128, 64 for SHAKE256 per FIPS 205 Section 10.2.2).
|
||||
*
|
||||
* @param [in] key SLH-DSA key.
|
||||
* @param [in] ctx Context of signing.
|
||||
* @param [in] ctxSz Length of context in bytes.
|
||||
* @param [in] msg Message to sign.
|
||||
* @param [in] msgSz Length of message in bytes.
|
||||
* @param [in] hashType Hash algorithm to use in pre-hash.
|
||||
* @param [in] hash Pre-hashed message digest to verify against.
|
||||
* @param [in] hashSz Length of digest in bytes.
|
||||
* @param [in] hashType Hash algorithm used for pre-hash (selects OID).
|
||||
* @param [in] sig Signature data.
|
||||
* @param [in] sigSz Length of signature in bytes.
|
||||
* @return 0 on success.
|
||||
* @return BAD_FUNC_ARG when key, key's parameters, msg or sig is NULL.
|
||||
* @return BAD_FUNC_ARG when key, key's parameters, hash or sig is NULL.
|
||||
* @return BAD_FUNC_ARG when ctx is NULL but ctx length is greater than 0.
|
||||
* @return BAD_LENGTH_E when signature size does not match parameters.
|
||||
* @return BAD_LENGTH_E when signature size does not match parameters, or
|
||||
* when hashSz does not equal the digest size for hashType.
|
||||
* @return MISSING_KEY when public key not set.
|
||||
* @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.
|
||||
*/
|
||||
int wc_SlhDsaKey_VerifyHash(SlhDsaKey* key, const byte* ctx, byte ctxSz,
|
||||
const byte* msg, word32 msgSz, enum wc_HashType hashType, const byte* sig,
|
||||
const byte* hash, word32 hashSz, enum wc_HashType hashType, const byte* sig,
|
||||
word32 sigSz)
|
||||
{
|
||||
int ret = 0;
|
||||
byte ph[WC_MAX_DIGEST_SIZE];
|
||||
byte phLen = 0;
|
||||
const byte* oid = NULL;
|
||||
byte oidLen = 0;
|
||||
|
||||
/* Validate parameters. */
|
||||
if ((key == NULL) || (key->params == NULL) ||
|
||||
((ctx == NULL) && (ctxSz > 0)) || (msg == NULL) || (sig == NULL)) {
|
||||
((ctx == NULL) && (ctxSz > 0)) || (hash == NULL) || (sig == NULL)) {
|
||||
ret = BAD_FUNC_ARG;
|
||||
}
|
||||
/* Alg 20, Step 1: Check signature length is the expect length. */
|
||||
@@ -8148,10 +8222,9 @@ int wc_SlhDsaKey_VerifyHash(SlhDsaKey* key, const byte* ctx, byte ctxSz,
|
||||
ret = MISSING_KEY;
|
||||
}
|
||||
if (ret == 0) {
|
||||
/* Alg 24, Steps 4-19: Pre-hash message with hash algorithm specified.
|
||||
*/
|
||||
ret = slhdsakey_prehash_msg(msg, msgSz, hashType, ph, &phLen, &oid,
|
||||
&oidLen);
|
||||
/* Alg 24, 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);
|
||||
}
|
||||
if (ret == 0) {
|
||||
byte n = key->params->n;
|
||||
@@ -8164,12 +8237,12 @@ int wc_SlhDsaKey_VerifyHash(SlhDsaKey* key, const byte* ctx, byte ctxSz,
|
||||
|
||||
#ifdef WOLFSSL_SLHDSA_SHA2
|
||||
if (SLHDSA_IS_SHA2(key->params->param)) {
|
||||
/* SHA2: Build oid||ph as message for H_msg. */
|
||||
byte phMsg[80]; /* Max: 11 byte OID + 64 byte hash */
|
||||
word32 phMsgLen = (word32)oidLen + phLen;
|
||||
/* SHA2: Build oid||hash as message for H_msg. */
|
||||
byte phMsg[SLHDSA_PHMSG_MAX_LEN];
|
||||
word32 phMsgLen = (word32)oidLen + hashSz;
|
||||
|
||||
XMEMCPY(phMsg, oid, oidLen);
|
||||
XMEMCPY(phMsg + oidLen, ph, phLen);
|
||||
XMEMCPY(phMsg + oidLen, hash, hashSz);
|
||||
|
||||
ret = slhdsakey_h_msg_sha2(key, sig, hdr, ctx, ctxSz, phMsg,
|
||||
phMsgLen, md, (word32)key->params->dl1 + key->params->dl2 +
|
||||
@@ -8195,7 +8268,7 @@ int wc_SlhDsaKey_VerifyHash(SlhDsaKey* key, const byte* ctx, byte ctxSz,
|
||||
ret = slhdsakey_hash_update(&key->hash.shk.shake, oid, oidLen);
|
||||
}
|
||||
if (ret == 0) {
|
||||
ret = slhdsakey_hash_update(&key->hash.shk.shake, ph, phLen);
|
||||
ret = slhdsakey_hash_update(&key->hash.shk.shake, hash, hashSz);
|
||||
}
|
||||
if (ret == 0) {
|
||||
ret = slhdsakey_hash_final(&key->hash.shk.shake, md,
|
||||
|
||||
Reference in New Issue
Block a user