blob: 0bae1aac059ae89265b8fc89e2b2600d88d3ce29 [file] [log] [blame] [edit]
package subprocess
import (
"encoding/hex"
"encoding/json"
"fmt"
"strings"
)
// Common top-level structure to parse mode
type slhdsaTestVectorSet struct {
Algorithm string `json:"algorithm"`
Mode string `json:"mode"`
Revision string `json:"revision"`
}
type slhdsaKeyGenTestVectorSet struct {
Algorithm string `json:"algorithm"`
Mode string `json:"mode"`
Revision string `json:"revision"`
Groups []slhdsaKeyGenTestGroup `json:"testGroups"`
}
type slhdsaKeyGenTestGroup struct {
ID uint64 `json:"tgId"`
TestType string `json:"testType"`
ParameterSet string `json:"parameterSet"`
Tests []slhdsaKeyGenTest `json:"tests"`
}
type slhdsaKeyGenTest struct {
ID uint64 `json:"tcId"`
SKSeed string `json:"skSeed"`
SKPrf string `json:"skPrf"`
PKSeed string `json:"pkSeed"`
}
type slhdsaKeyGenTestGroupResponse struct {
ID uint64 `json:"tgId"`
Tests []slhdsaKeyGenTestResponse `json:"tests"`
}
type slhdsaKeyGenTestResponse struct {
ID uint64 `json:"tcId"`
PublicKey string `json:"pk"`
PrivateKey string `json:"sk"`
}
type slhdsaSigGenTestVectorSet struct {
Algorithm string `json:"algorithm"`
Mode string `json:"mode"`
Revision string `json:"revision"`
Groups []slhdsaSigGenTestGroup `json:"testGroups"`
}
type slhdsaSigGenTestGroup struct {
ID uint64 `json:"tgId"`
TestType string `json:"testType"`
ParameterSet string `json:"parameterSet"`
Deterministic bool `json:"deterministic"`
Tests []slhdsaSigGenTest `json:"tests"`
}
type slhdsaSigGenTest struct {
ID uint64 `json:"tcId"`
Message string `json:"message"`
PrivateKey string `json:"sk"`
AdditionalRandomness string `json:"additionalRandomness,omitempty"`
}
type slhdsaSigGenTestGroupResponse struct {
ID uint64 `json:"tgId"`
Tests []slhdsaSigGenTestResponse `json:"tests"`
}
type slhdsaSigGenTestResponse struct {
ID uint64 `json:"tcId"`
Signature string `json:"signature"`
}
type slhdsaSigVerTestVectorSet struct {
Algorithm string `json:"algorithm"`
Mode string `json:"mode"`
Revision string `json:"revision"`
Groups []slhdsaSigVerTestGroup `json:"testGroups"`
}
type slhdsaSigVerTestGroup struct {
ID uint64 `json:"tgId"`
TestType string `json:"testType"`
ParameterSet string `json:"parameterSet"`
Tests []slhdsaSigVerTest `json:"tests"`
}
type slhdsaSigVerTest struct {
ID uint64 `json:"tcId"`
Message string `json:"message"`
Signature string `json:"signature"`
PublicKey string `json:"pk"`
}
type slhdsaSigVerTestGroupResponse struct {
ID uint64 `json:"tgId"`
Tests []slhdsaSigVerTestResponse `json:"tests"`
}
type slhdsaSigVerTestResponse struct {
ID uint64 `json:"tcId"`
TestPassed bool `json:"testPassed"`
}
type slhdsa struct{}
func (s *slhdsa) Process(vectorSet []byte, t Transactable) (any, error) {
var common slhdsaTestVectorSet
if err := json.Unmarshal(vectorSet, &common); err != nil {
return nil, fmt.Errorf("failed to unmarshal vector set: %v", err)
}
switch common.Mode {
case "keyGen":
return s.processKeyGen(vectorSet, t)
case "sigGen":
return s.processSigGen(vectorSet, t)
case "sigVer":
return s.processSigVer(vectorSet, t)
default:
return nil, fmt.Errorf("unsupported SLH-DSA mode: %s", common.Mode)
}
}
func (s *slhdsa) processKeyGen(vectorSet []byte, t Transactable) (any, error) {
var parsed slhdsaKeyGenTestVectorSet
if err := json.Unmarshal(vectorSet, &parsed); err != nil {
return nil, fmt.Errorf("failed to unmarshal keyGen vector set: %v", err)
}
var ret []slhdsaKeyGenTestGroupResponse
for _, group := range parsed.Groups {
response := slhdsaKeyGenTestGroupResponse{
ID: group.ID,
}
if !strings.HasPrefix(group.ParameterSet, "SLH-DSA-") {
return nil, fmt.Errorf("invalid parameter set: %s", group.ParameterSet)
}
cmdName := group.ParameterSet + "/keyGen"
for _, test := range group.Tests {
skSeed, err := hex.DecodeString(test.SKSeed)
if err != nil {
return nil, fmt.Errorf("failed to decode skSeed in test case %d/%d: %s",
group.ID, test.ID, err)
}
skPrf, err := hex.DecodeString(test.SKPrf)
if err != nil {
return nil, fmt.Errorf("failed to decode skPrf in test case %d/%d: %s",
group.ID, test.ID, err)
}
pkSeed, err := hex.DecodeString(test.PKSeed)
if err != nil {
return nil, fmt.Errorf("failed to decode pkSeed in test case %d/%d: %s",
group.ID, test.ID, err)
}
var seed []byte
seed = append(seed, skSeed...)
seed = append(seed, skPrf...)
seed = append(seed, pkSeed...)
result, err := t.Transact(cmdName, 2, seed)
if err != nil {
return nil, fmt.Errorf("key generation failed for test case %d/%d: %s",
group.ID, test.ID, err)
}
response.Tests = append(response.Tests, slhdsaKeyGenTestResponse{
ID: test.ID,
PrivateKey: hex.EncodeToString(result[0]),
PublicKey: hex.EncodeToString(result[1]),
})
}
ret = append(ret, response)
}
return ret, nil
}
func (s *slhdsa) processSigGen(vectorSet []byte, t Transactable) (any, error) {
var parsed slhdsaSigGenTestVectorSet
if err := json.Unmarshal(vectorSet, &parsed); err != nil {
return nil, fmt.Errorf("failed to unmarshal sigGen vector set: %v", err)
}
var ret []slhdsaSigGenTestGroupResponse
for _, group := range parsed.Groups {
response := slhdsaSigGenTestGroupResponse{
ID: group.ID,
}
if !strings.HasPrefix(group.ParameterSet, "SLH-DSA-") {
return nil, fmt.Errorf("invalid parameter set: %s", group.ParameterSet)
}
cmdName := group.ParameterSet + "/sigGen"
for _, test := range group.Tests {
sk, err := hex.DecodeString(test.PrivateKey)
if err != nil {
return nil, fmt.Errorf("failed to decode private key in test case %d/%d: %s",
group.ID, test.ID, err)
}
msg, err := hex.DecodeString(test.Message)
if err != nil {
return nil, fmt.Errorf("failed to decode message in test case %d/%d: %s",
group.ID, test.ID, err)
}
var randomness []byte
if !group.Deterministic {
randomness, err = hex.DecodeString(test.AdditionalRandomness)
if err != nil {
return nil, fmt.Errorf("failed to decode randomness in test case %d/%d: %s",
group.ID, test.ID, err)
}
}
result, err := t.Transact(cmdName, 1, sk, msg, randomness)
if err != nil {
return nil, fmt.Errorf("signature generation failed for test case %d/%d: %s",
group.ID, test.ID, err)
}
response.Tests = append(response.Tests, slhdsaSigGenTestResponse{
ID: test.ID,
Signature: hex.EncodeToString(result[0]),
})
}
ret = append(ret, response)
}
return ret, nil
}
func (s *slhdsa) processSigVer(vectorSet []byte, t Transactable) (any, error) {
var parsed slhdsaSigVerTestVectorSet
if err := json.Unmarshal(vectorSet, &parsed); err != nil {
return nil, fmt.Errorf("failed to unmarshal sigVer vector set: %v", err)
}
var ret []slhdsaSigVerTestGroupResponse
for _, group := range parsed.Groups {
response := slhdsaSigVerTestGroupResponse{
ID: group.ID,
}
if !strings.HasPrefix(group.ParameterSet, "SLH-DSA-") {
return nil, fmt.Errorf("invalid parameter set: %s", group.ParameterSet)
}
cmdName := group.ParameterSet + "/sigVer"
for _, test := range group.Tests {
pk, err := hex.DecodeString(test.PublicKey)
if err != nil {
return nil, fmt.Errorf("failed to decode public key in test case %d/%d: %s",
group.ID, test.ID, err)
}
msg, err := hex.DecodeString(test.Message)
if err != nil {
return nil, fmt.Errorf("failed to decode message in test case %d/%d: %s",
group.ID, test.ID, err)
}
sig, err := hex.DecodeString(test.Signature)
if err != nil {
return nil, fmt.Errorf("failed to decode signature in test case %d/%d: %s",
group.ID, test.ID, err)
}
result, err := t.Transact(cmdName, 1, pk, msg, sig)
if err != nil {
return nil, fmt.Errorf("signature verification failed for test case %d/%d: %s",
group.ID, test.ID, err)
}
testPassed := result[0][0] != 0
response.Tests = append(response.Tests, slhdsaSigVerTestResponse{
ID: test.ID,
TestPassed: testPassed,
})
}
ret = append(ret, response)
}
return ret, nil
}