• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1package subprocess
2
3import (
4	"encoding/hex"
5	"encoding/json"
6	"fmt"
7	"strings"
8)
9
10// Common top-level structure to parse mode
11type slhdsaTestVectorSet struct {
12	Algorithm string `json:"algorithm"`
13	Mode      string `json:"mode"`
14	Revision  string `json:"revision"`
15}
16
17type slhdsaKeyGenTestVectorSet struct {
18	Algorithm string                  `json:"algorithm"`
19	Mode      string                  `json:"mode"`
20	Revision  string                  `json:"revision"`
21	Groups    []slhdsaKeyGenTestGroup `json:"testGroups"`
22}
23
24type slhdsaKeyGenTestGroup struct {
25	ID           uint64             `json:"tgId"`
26	TestType     string             `json:"testType"`
27	ParameterSet string             `json:"parameterSet"`
28	Tests        []slhdsaKeyGenTest `json:"tests"`
29}
30
31type slhdsaKeyGenTest struct {
32	ID     uint64 `json:"tcId"`
33	SKSeed string `json:"skSeed"`
34	SKPrf  string `json:"skPrf"`
35	PKSeed string `json:"pkSeed"`
36}
37
38type slhdsaKeyGenTestGroupResponse struct {
39	ID    uint64                     `json:"tgId"`
40	Tests []slhdsaKeyGenTestResponse `json:"tests"`
41}
42
43type slhdsaKeyGenTestResponse struct {
44	ID         uint64 `json:"tcId"`
45	PublicKey  string `json:"pk"`
46	PrivateKey string `json:"sk"`
47}
48
49type slhdsaSigGenTestVectorSet struct {
50	Algorithm string                  `json:"algorithm"`
51	Mode      string                  `json:"mode"`
52	Revision  string                  `json:"revision"`
53	Groups    []slhdsaSigGenTestGroup `json:"testGroups"`
54}
55
56type slhdsaSigGenTestGroup struct {
57	ID            uint64             `json:"tgId"`
58	TestType      string             `json:"testType"`
59	ParameterSet  string             `json:"parameterSet"`
60	Deterministic bool               `json:"deterministic"`
61	Tests         []slhdsaSigGenTest `json:"tests"`
62}
63
64type slhdsaSigGenTest struct {
65	ID                   uint64 `json:"tcId"`
66	Message              string `json:"message"`
67	PrivateKey           string `json:"sk"`
68	AdditionalRandomness string `json:"additionalRandomness,omitempty"`
69}
70
71type slhdsaSigGenTestGroupResponse struct {
72	ID    uint64                     `json:"tgId"`
73	Tests []slhdsaSigGenTestResponse `json:"tests"`
74}
75
76type slhdsaSigGenTestResponse struct {
77	ID        uint64 `json:"tcId"`
78	Signature string `json:"signature"`
79}
80
81type slhdsaSigVerTestVectorSet struct {
82	Algorithm string                  `json:"algorithm"`
83	Mode      string                  `json:"mode"`
84	Revision  string                  `json:"revision"`
85	Groups    []slhdsaSigVerTestGroup `json:"testGroups"`
86}
87
88type slhdsaSigVerTestGroup struct {
89	ID           uint64             `json:"tgId"`
90	TestType     string             `json:"testType"`
91	ParameterSet string             `json:"parameterSet"`
92	Tests        []slhdsaSigVerTest `json:"tests"`
93}
94
95type slhdsaSigVerTest struct {
96	ID        uint64 `json:"tcId"`
97	Message   string `json:"message"`
98	Signature string `json:"signature"`
99	PublicKey string `json:"pk"`
100}
101
102type slhdsaSigVerTestGroupResponse struct {
103	ID    uint64                     `json:"tgId"`
104	Tests []slhdsaSigVerTestResponse `json:"tests"`
105}
106
107type slhdsaSigVerTestResponse struct {
108	ID         uint64 `json:"tcId"`
109	TestPassed bool   `json:"testPassed"`
110}
111
112type slhdsa struct{}
113
114func (s *slhdsa) Process(vectorSet []byte, t Transactable) (any, error) {
115	var common slhdsaTestVectorSet
116	if err := json.Unmarshal(vectorSet, &common); err != nil {
117		return nil, fmt.Errorf("failed to unmarshal vector set: %v", err)
118	}
119
120	switch common.Mode {
121	case "keyGen":
122		return s.processKeyGen(vectorSet, t)
123	case "sigGen":
124		return s.processSigGen(vectorSet, t)
125	case "sigVer":
126		return s.processSigVer(vectorSet, t)
127	default:
128		return nil, fmt.Errorf("unsupported SLH-DSA mode: %s", common.Mode)
129	}
130}
131
132func (s *slhdsa) processKeyGen(vectorSet []byte, t Transactable) (any, error) {
133	var parsed slhdsaKeyGenTestVectorSet
134	if err := json.Unmarshal(vectorSet, &parsed); err != nil {
135		return nil, fmt.Errorf("failed to unmarshal keyGen vector set: %v", err)
136	}
137
138	var ret []slhdsaKeyGenTestGroupResponse
139
140	for _, group := range parsed.Groups {
141		response := slhdsaKeyGenTestGroupResponse{
142			ID: group.ID,
143		}
144
145		if !strings.HasPrefix(group.ParameterSet, "SLH-DSA-") {
146			return nil, fmt.Errorf("invalid parameter set: %s", group.ParameterSet)
147		}
148		cmdName := group.ParameterSet + "/keyGen"
149
150		for _, test := range group.Tests {
151			skSeed, err := hex.DecodeString(test.SKSeed)
152			if err != nil {
153				return nil, fmt.Errorf("failed to decode skSeed in test case %d/%d: %s",
154					group.ID, test.ID, err)
155			}
156
157			skPrf, err := hex.DecodeString(test.SKPrf)
158			if err != nil {
159				return nil, fmt.Errorf("failed to decode skPrf in test case %d/%d: %s",
160					group.ID, test.ID, err)
161			}
162
163			pkSeed, err := hex.DecodeString(test.PKSeed)
164			if err != nil {
165				return nil, fmt.Errorf("failed to decode pkSeed in test case %d/%d: %s",
166					group.ID, test.ID, err)
167			}
168
169			var seed []byte
170			seed = append(seed, skSeed...)
171			seed = append(seed, skPrf...)
172			seed = append(seed, pkSeed...)
173
174			result, err := t.Transact(cmdName, 2, seed)
175			if err != nil {
176				return nil, fmt.Errorf("key generation failed for test case %d/%d: %s",
177					group.ID, test.ID, err)
178			}
179
180			response.Tests = append(response.Tests, slhdsaKeyGenTestResponse{
181				ID:         test.ID,
182				PrivateKey: hex.EncodeToString(result[0]),
183				PublicKey:  hex.EncodeToString(result[1]),
184			})
185		}
186
187		ret = append(ret, response)
188	}
189
190	return ret, nil
191}
192
193func (s *slhdsa) processSigGen(vectorSet []byte, t Transactable) (any, error) {
194	var parsed slhdsaSigGenTestVectorSet
195	if err := json.Unmarshal(vectorSet, &parsed); err != nil {
196		return nil, fmt.Errorf("failed to unmarshal sigGen vector set: %v", err)
197	}
198
199	var ret []slhdsaSigGenTestGroupResponse
200
201	for _, group := range parsed.Groups {
202		response := slhdsaSigGenTestGroupResponse{
203			ID: group.ID,
204		}
205
206		if !strings.HasPrefix(group.ParameterSet, "SLH-DSA-") {
207			return nil, fmt.Errorf("invalid parameter set: %s", group.ParameterSet)
208		}
209		cmdName := group.ParameterSet + "/sigGen"
210
211		for _, test := range group.Tests {
212			sk, err := hex.DecodeString(test.PrivateKey)
213			if err != nil {
214				return nil, fmt.Errorf("failed to decode private key in test case %d/%d: %s",
215					group.ID, test.ID, err)
216			}
217
218			msg, err := hex.DecodeString(test.Message)
219			if err != nil {
220				return nil, fmt.Errorf("failed to decode message in test case %d/%d: %s",
221					group.ID, test.ID, err)
222			}
223
224			var randomness []byte
225			if !group.Deterministic {
226				randomness, err = hex.DecodeString(test.AdditionalRandomness)
227				if err != nil {
228					return nil, fmt.Errorf("failed to decode randomness in test case %d/%d: %s",
229						group.ID, test.ID, err)
230				}
231			}
232
233			result, err := t.Transact(cmdName, 1, sk, msg, randomness)
234			if err != nil {
235				return nil, fmt.Errorf("signature generation failed for test case %d/%d: %s",
236					group.ID, test.ID, err)
237			}
238
239			response.Tests = append(response.Tests, slhdsaSigGenTestResponse{
240				ID:        test.ID,
241				Signature: hex.EncodeToString(result[0]),
242			})
243		}
244
245		ret = append(ret, response)
246	}
247
248	return ret, nil
249}
250
251func (s *slhdsa) processSigVer(vectorSet []byte, t Transactable) (any, error) {
252	var parsed slhdsaSigVerTestVectorSet
253	if err := json.Unmarshal(vectorSet, &parsed); err != nil {
254		return nil, fmt.Errorf("failed to unmarshal sigVer vector set: %v", err)
255	}
256
257	var ret []slhdsaSigVerTestGroupResponse
258
259	for _, group := range parsed.Groups {
260		response := slhdsaSigVerTestGroupResponse{
261			ID: group.ID,
262		}
263
264		if !strings.HasPrefix(group.ParameterSet, "SLH-DSA-") {
265			return nil, fmt.Errorf("invalid parameter set: %s", group.ParameterSet)
266		}
267		cmdName := group.ParameterSet + "/sigVer"
268
269		for _, test := range group.Tests {
270			pk, err := hex.DecodeString(test.PublicKey)
271			if err != nil {
272				return nil, fmt.Errorf("failed to decode public key in test case %d/%d: %s",
273					group.ID, test.ID, err)
274			}
275
276			msg, err := hex.DecodeString(test.Message)
277			if err != nil {
278				return nil, fmt.Errorf("failed to decode message in test case %d/%d: %s",
279					group.ID, test.ID, err)
280			}
281
282			sig, err := hex.DecodeString(test.Signature)
283			if err != nil {
284				return nil, fmt.Errorf("failed to decode signature in test case %d/%d: %s",
285					group.ID, test.ID, err)
286			}
287
288			result, err := t.Transact(cmdName, 1, pk, msg, sig)
289			if err != nil {
290				return nil, fmt.Errorf("signature verification failed for test case %d/%d: %s",
291					group.ID, test.ID, err)
292			}
293
294			testPassed := result[0][0] != 0
295			response.Tests = append(response.Tests, slhdsaSigVerTestResponse{
296				ID:         test.ID,
297				TestPassed: testPassed,
298			})
299		}
300
301		ret = append(ret, response)
302	}
303
304	return ret, nil
305}
306