slhdsa: KAT + propagation test augmentations (Red Probe 7/10)

This commit is contained in:
Hanzo AI
2026-06-05 05:13:36 -07:00
parent f05ff68684
commit ce21119e75
2 changed files with 44 additions and 2 deletions
+19
View File
@@ -51,6 +51,16 @@ func nameToCirclID(t *testing.T, name string) circl.ID {
// in the underlying circl version cannot silently break compatibility with the
// FIPS 205 specification.
func TestSLHDSA_KAT_KeygenFIPS205(t *testing.T) {
// 120 NIST ACVP keygen vectors across 12 modes. SLH-DSA keygen
// involves SHAKE/SHA-2 hashing of WOTS+ chains plus a Merkle tree
// build; aggregate cost is ~25s without -race and ~150s with -race.
// Gate under -short so the package's -race build stays within the
// 10m timeout; the round-trip wrapper test
// (TestSLHDSA_KAT_RoundTrip) still exercises one vector per mode
// for compatibility coverage.
if testing.Short() {
t.Skip("skipping full 120-vector KAT keygen suite under -short")
}
for _, v := range slhdsaKATVectors {
v := v
t.Run(v.Mode+"/"+v.SkSeed[:8], func(t *testing.T) {
@@ -102,6 +112,15 @@ func TestSLHDSA_KAT_KeygenFIPS205(t *testing.T) {
// agrees with the parameter set names used in NIST ACVP. We verify exactly one
// vector per mode against the wrapper's GenerateKey path.
func TestSLHDSA_KAT_RoundTrip(t *testing.T) {
// 12 modes × keygen + sign + verify. Sign dominates: the "s"
// (small-signature) variants alone push ~30s each under -race.
// Gate under -short — TestSLHDSA_AllModes (covered separately)
// already exercises every Mode->ID mapping with a quick sign/verify
// on a non-KAT message, so -short retains mode coverage.
if testing.Short() {
t.Skip("skipping 12-mode KAT round-trip Sign suite under -short")
}
// Map ACVP names to our Mode constants.
nameToMode := map[string]Mode{
"SLH-DSA-SHA2-128s": SHA2_128s,
+25 -2
View File
@@ -59,6 +59,14 @@ func TestSLHDSA_SignVerify_SHAKE_128s(t *testing.T) {
}
func TestSLHDSA_SignVerify_SHA2_256s(t *testing.T) {
// SHA-2-256s is the slowest production mode (~1.5s sign without
// -race, ~10s with). The matching SHA2_256f variant gives
// equivalent FIPS-205 compliance coverage at ~50ms; gate the slow
// "s" variant under -short.
if testing.Short() {
t.Skip("skipping SLH-DSA-SHA2-256s slow variant under -short")
}
sk, err := GenerateKey(rand.Reader, SHA2_256s)
if err != nil {
t.Fatalf("Failed to generate key: %v", err)
@@ -226,12 +234,27 @@ func TestSLHDSA_PublicKeyFromBytes(t *testing.T) {
}
func TestSLHDSA_AllModes(t *testing.T) {
// Test that all modes are supported
modes := []Mode{
// Test that all modes are supported.
//
// The "s" variants (small signature, deep WOTS+ chains) push sign
// to ~1.5s without -race and ~10s under -race — aggregate ~6s/35s.
// Under -short we keep a subset covering one (SHA-2, SHAKE) × one
// (s, f) combination per level so the mode-mapping coverage stays
// intact at a fraction of the cost.
allModes := []Mode{
SHA2_128s, SHAKE_128s, SHA2_128f, SHAKE_128f,
SHA2_192s, SHAKE_192s, SHA2_192f, SHAKE_192f,
SHA2_256s, SHAKE_256s, SHA2_256f, SHAKE_256f,
}
shortModes := []Mode{
SHA2_128f, SHAKE_128f, // fast 128-bit variants
SHA2_192f, SHAKE_192f, // fast 192-bit variants
SHA2_256f, SHAKE_256f, // fast 256-bit variants
}
modes := allModes
if testing.Short() {
modes = shortModes
}
for _, mode := range modes {
t.Run(modeToID(mode).String(), func(t *testing.T) {