// Generated by tool/gen/fn/generate.py; do not edit.
// schema_sha256=787c413dea5e27098bec8d4778942ded65ed94c4cfffda39e20fac88581b05f1
// FIPS 204 Algorithms 4/5; no live C++ GPU prehash donor exists.
import mldsa_sign;
import mldsa_prehash_layout;
import mldsa_prehash_digest;
import mldsa_sign_workspace_layout;
import shake;
// Accept a precomputed public digest, not an arbitrary message. The fixed
// selector binds both digest length and DER OID; callers cannot supply an OID.
// SHAKE-128/256 lengths are fixed to 32/64 bytes, respectively.
bool mldsa_sign_prehashed_cached<T : IMldsaSignCache>(uint parameter_set, uint key[4896], uint rnd[32],
RWByteAddressBuffer digests, uint digest_base, uint digest_length,
RWByteAddressBuffer contexts, uint context_base, uint context_length,
uint algorithm, inout T cache, inout uint signature[4627], out uint attempts) {
attempts = 0u;
if (parameter_set != 44u && parameter_set != 65u && parameter_set != 87u) return false;
uint length = mldsa_prehash_bytes(algorithm);
if (length == 0u || digest_length != length || context_length > 255u) return false;
if (!pqc_buffer_range(digests, digest_base, length)
|| !pqc_buffer_range(contexts, context_base, context_length)) return false;
for (uint i = 64u; i < 128u; ++i) if (key[i] > 255u) return false;
PqcShake256 sponge;
pqc_shake256_init(sponge);
for (uint i = 64u; i < 128u; ++i) pqc_shake256_absorb_byte(sponge, key[i]);
mldsa_absorb_prehash_framing(sponge, digests, digest_base, length,
contexts, context_base, context_length, algorithm);
pqc_shake256_finalize(sponge);
uint mu[64];
for (uint i = 0u; i < 64u; ++i) mu[i] = pqc_shake256_squeeze_byte(sponge);
return mldsa_sign_mu_cached(parameter_set, key, mu, rnd, cache, signature, attempts);
}
// Existing fixture callers retain their local cache.
bool mldsa_sign_prehashed(uint parameter_set, uint key[4896], uint rnd[32],
RWByteAddressBuffer digests, uint digest_base, uint digest_length,
RWByteAddressBuffer contexts, uint context_base, uint context_length,
uint algorithm, inout uint signature[4627], out uint attempts) {
MldsaLocalSignCache cache;
return mldsa_sign_prehashed_cached(parameter_set, key, rnd,
digests, digest_base, digest_length, contexts, context_base, context_length,
algorithm, cache, signature, attempts);
}
// Workspace extent is checked before message hashing or cache access.
bool mldsa_sign_prehashed_buffer(uint parameter_set, uint key[4896], uint rnd[32],
RWByteAddressBuffer digests, uint digest_base, uint digest_length,
RWByteAddressBuffer contexts, uint context_base, uint context_length,
uint algorithm, RWByteAddressBuffer workspace, uint workspace_base,
inout uint signature[4627], out uint attempts) {
attempts = 0u;
if ((workspace_base & 3u) != 0u
|| !pqc_buffer_range(workspace, workspace_base, MLDSA_SIGN_CACHE_BYTES)) return false;
MldsaBufferSignCache cache;
cache.buffer = workspace;
cache.base = workspace_base;
return mldsa_sign_prehashed_cached(parameter_set, key, rnd,
digests, digest_base, digest_length, contexts, context_base, context_length,
algorithm, cache, signature, attempts);
}
// HashML-DSA accepts the original public message; digest words stay local.
// No secret-key bytes are transported through an ordinary digest buffer.
bool mldsa_sign_hash_message_cached<T : IMldsaSignCache>(
uint parameter_set, uint key[4896], uint rnd[32],
RWByteAddressBuffer messages, uint message_base, uint message_length,
RWByteAddressBuffer contexts, uint context_base, uint context_length,
uint algorithm, inout T cache, inout uint signature[4627], out uint attempts) {
attempts = 0u;
if (parameter_set != 44u && parameter_set != 65u && parameter_set != 87u) return false;
uint length = mldsa_prehash_bytes(algorithm);
if (length == 0u || context_length > 255u
|| !pqc_buffer_range(contexts, context_base, context_length)) return false;
for (uint i = 64u; i < 128u; ++i) if (key[i] > 255u) return false;
uint digest[16];
if (!mldsa_prehash_digest(messages, message_base, message_length, algorithm, digest)) return false;
PqcShake256 sponge;
pqc_shake256_init(sponge);
for (uint i = 64u; i < 128u; ++i) pqc_shake256_absorb_byte(sponge, key[i]);
mldsa_absorb_prehash_header(sponge, contexts, context_base, context_length, algorithm);
for (uint i = 0u; i < length; ++i)
pqc_shake256_absorb_byte(sponge, (digest[i >> 2u] >> ((i & 3u) * 8u)) & 255u);
pqc_shake256_finalize(sponge);
uint mu[64];
for (uint i = 0u; i < 64u; ++i) mu[i] = pqc_shake256_squeeze_byte(sponge);
return mldsa_sign_mu_cached(parameter_set, key, mu, rnd, cache, signature, attempts);
}
// Reject workspace extents before hashing or touching the signing cache.
bool mldsa_sign_hash_message_buffer(uint parameter_set, uint key[4896], uint rnd[32],
RWByteAddressBuffer messages, uint message_base, uint message_length,
RWByteAddressBuffer contexts, uint context_base, uint context_length,
uint algorithm, RWByteAddressBuffer workspace, uint workspace_base,
inout uint signature[4627], out uint attempts) {
attempts = 0u;
if ((workspace_base & 3u) != 0u
|| !pqc_buffer_range(workspace, workspace_base, MLDSA_SIGN_CACHE_BYTES)) return false;
MldsaBufferSignCache cache;
cache.buffer = workspace;
cache.base = workspace_base;
return mldsa_sign_hash_message_cached(parameter_set, key, rnd,
messages, message_base, message_length, contexts, context_base, context_length,
algorithm, cache, signature, attempts);
}