blob: 10a44f1492bbf1d95ddacfc44430dab6dde147e0 [file] [log] [blame]
// Copyright 2025 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build !fips140v1.0
package fipstest
import (
"crypto/internal/fips140/mldsa"
_ "embed"
"fmt"
)
//go:embed acvp_capabilities_fips140v1.26.json
var capabilitiesJson []byte
var testConfigFile = "acvp_test_fips140v1.26.config.json"
func init() {
commands["ML-DSA-44/keyGen"] = cmdMlDsaKeyGenAft(mldsa.NewPrivateKey44)
commands["ML-DSA-65/keyGen"] = cmdMlDsaKeyGenAft(mldsa.NewPrivateKey65)
commands["ML-DSA-87/keyGen"] = cmdMlDsaKeyGenAft(mldsa.NewPrivateKey87)
commands["ML-DSA-44/sigGen"] = cmdMlDsaSigGenAft()
commands["ML-DSA-65/sigGen"] = cmdMlDsaSigGenAft()
commands["ML-DSA-87/sigGen"] = cmdMlDsaSigGenAft()
commands["ML-DSA-44/sigVer"] = cmdMlDsaSigVerAft(mldsa.NewPublicKey44)
commands["ML-DSA-65/sigVer"] = cmdMlDsaSigVerAft(mldsa.NewPublicKey65)
commands["ML-DSA-87/sigVer"] = cmdMlDsaSigVerAft(mldsa.NewPublicKey87)
}
func cmdMlDsaKeyGenAft(keyGen func([]byte) (*mldsa.PrivateKey, error)) command {
return command{
requiredArgs: 1, // Seed
handler: func(args [][]byte) ([][]byte, error) {
seed := args[0]
sk, err := keyGen(seed)
if err != nil {
return nil, fmt.Errorf("generating ML-DSA 44 private key: %w", err)
}
// Important: we must return the full encoding of sk, not the seed.
return [][]byte{sk.PublicKey().Bytes(), mldsa.TestingOnlyPrivateKeySemiExpandedBytes(sk)}, nil
},
}
}
func cmdMlDsaSigGenAft() command {
return command{
requiredArgs: 5, // secret key, message, randomizer, mu, context
handler: func(args [][]byte) ([][]byte, error) {
skSmiExpanded := args[0]
message := args[1] // Optional, exclusive with mu
randomizer := args[2] // Optional
context := string(args[3]) // Optional
mu := args[4] // Optional, exclusive with message
sk, err := mldsa.TestingOnlyNewPrivateKeyFromSemiExpanded(skSmiExpanded)
if err != nil {
return nil, fmt.Errorf("making ML-DSA private key from semi-expanded form: %w", err)
}
haveMessage := len(message) != 0
haveRandomizer := len(randomizer) != 0
haveMu := len(mu) != 0
var sig []byte
if haveMessage && !haveRandomizer && !haveMu {
sig, err = mldsa.SignDeterministic(sk, message, context)
} else if haveMessage && haveRandomizer && !haveMu {
sig, err = mldsa.TestingOnlySignWithRandom(sk, message, context, randomizer)
} else if !haveMessage && !haveRandomizer && haveMu {
sig, err = mldsa.SignExternalMuDeterministic(sk, mu)
} else if !haveMessage && haveRandomizer && haveMu {
sig, err = mldsa.TestingOnlySignExternalMuWithRandom(sk, mu, randomizer)
} else {
return nil, fmt.Errorf(
"unsupported ML-DSA sigGen args: have message=%v have randomizer=%v haveMu=%v haveContext=%v",
haveMessage, haveRandomizer, haveMu, len(context) != 0)
}
if err != nil {
return nil, fmt.Errorf("creating deterministic ML-DSA signature: %w", err)
}
return [][]byte{sig}, nil
},
}
}
func cmdMlDsaSigVerAft(pubKey func([]byte) (*mldsa.PublicKey, error)) command {
return command{
requiredArgs: 5, // public key, message, signature, context, mu
handler: func(args [][]byte) ([][]byte, error) {
pkRaw := args[0]
message := args[1] // Optional, exclusive with mu
signature := args[2]
context := string(args[3]) // Optional
mu := args[4] // Optional, exclusive with message
pk, err := pubKey(pkRaw)
if err != nil {
return nil, fmt.Errorf("loading ML-DSA public key: %w", err)
}
haveMessage := len(message) != 0
haveMu := len(mu) != 0
if haveMessage && !haveMu {
err = mldsa.Verify(pk, message, signature, context)
} else if !haveMessage && haveMu {
err = mldsa.VerifyExternalMu(pk, mu, signature)
} else {
return nil, fmt.Errorf(
"unsupported ML-DSA sigVer args: have message=%v haveMu=%v haveContext=%v",
haveMessage, haveMu, len(context) != 0)
}
if err != nil {
return [][]byte{{0}}, nil
}
return [][]byte{{1}}, nil
},
}
}