1
2
3
4
5 package fipstest
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 import (
22 "bufio"
23 "bytes"
24 "crypto/elliptic"
25 "crypto/internal/cryptotest"
26 entropy "crypto/internal/entropy/v1.0.0"
27 "crypto/internal/fips140"
28 "crypto/internal/fips140/aes"
29 "crypto/internal/fips140/aes/gcm"
30 "crypto/internal/fips140/bigmod"
31 "crypto/internal/fips140/drbg"
32 "crypto/internal/fips140/ecdh"
33 "crypto/internal/fips140/ecdsa"
34 "crypto/internal/fips140/ed25519"
35 "crypto/internal/fips140/edwards25519"
36 "crypto/internal/fips140/hkdf"
37 "crypto/internal/fips140/hmac"
38 "crypto/internal/fips140/mlkem"
39 "crypto/internal/fips140/pbkdf2"
40 "crypto/internal/fips140/rsa"
41 "crypto/internal/fips140/sha256"
42 "crypto/internal/fips140/sha3"
43 "crypto/internal/fips140/sha512"
44 "crypto/internal/fips140/ssh"
45 "crypto/internal/fips140/subtle"
46 "crypto/internal/fips140/tls12"
47 "crypto/internal/fips140/tls13"
48 "crypto/internal/impl"
49 "crypto/rand"
50 _ "embed"
51 "encoding/binary"
52 "errors"
53 "fmt"
54 "hash"
55 "internal/testenv"
56 "io"
57 "math/big"
58 "os"
59 "path/filepath"
60 "strings"
61 "testing"
62 )
63
64 var noPAAPAI = os.Getenv("GONOPAAPAI") == "1"
65
66
67
68
69 var entropyTesting = os.Getenv("GOENTROPYSOURCEACVP") == "1"
70
71 func TestMain(m *testing.M) {
72 if noPAAPAI {
73 for _, p := range impl.Packages() {
74 impl.Select(p, "")
75 }
76 }
77 if os.Getenv("ACVP_WRAPPER") == "1" {
78 wrapperMain()
79 } else {
80 os.Exit(m.Run())
81 }
82 }
83
84 func wrapperMain() {
85 if !fips140.Enabled {
86 fmt.Fprintln(os.Stderr, "ACVP wrapper must be run with GODEBUG=fips140=on")
87 os.Exit(2)
88 }
89 if err := processingLoop(bufio.NewReader(os.Stdin), os.Stdout); err != nil {
90 fmt.Fprintf(os.Stderr, "processing error: %v\n", err)
91 os.Exit(1)
92 }
93 }
94
95 type request struct {
96 name string
97 args [][]byte
98 }
99
100 type commandHandler func([][]byte) ([][]byte, error)
101
102 type command struct {
103
104 requiredArgs int
105 handler commandHandler
106 }
107
108 type ecdsaSigType int
109
110 const (
111 ecdsaSigTypeNormal ecdsaSigType = iota
112 ecdsaSigTypeDeterministic
113 )
114
115 type aesDirection int
116
117 const (
118 aesEncrypt aesDirection = iota
119 aesDecrypt
120 )
121
122 var (
123
124
125
126
127
128
129 entropyCapabilitiesJson []byte
130
131
132
133
134 commands = map[string]command{
135 "getConfig": cmdGetConfig(),
136
137 "SHA2-224": cmdHashAft(sha256.New224()),
138 "SHA2-224/MCT": cmdHashMct(sha256.New224()),
139 "SHA2-256": cmdHashAft(sha256.New()),
140 "SHA2-256/MCT": cmdHashMct(sha256.New()),
141 "SHA2-384": cmdHashAft(sha512.New384()),
142 "SHA2-384/MCT": cmdHashMct(sha512.New384()),
143 "SHA2-512": cmdHashAft(sha512.New()),
144 "SHA2-512/MCT": cmdHashMct(sha512.New()),
145 "SHA2-512/224": cmdHashAft(sha512.New512_224()),
146 "SHA2-512/224/MCT": cmdHashMct(sha512.New512_224()),
147 "SHA2-512/256": cmdHashAft(sha512.New512_256()),
148 "SHA2-512/256/MCT": cmdHashMct(sha512.New512_256()),
149
150 "SHA3-256": cmdHashAft(sha3.New256()),
151 "SHA3-256/MCT": cmdSha3Mct(sha3.New256()),
152 "SHA3-224": cmdHashAft(sha3.New224()),
153 "SHA3-224/MCT": cmdSha3Mct(sha3.New224()),
154 "SHA3-384": cmdHashAft(sha3.New384()),
155 "SHA3-384/MCT": cmdSha3Mct(sha3.New384()),
156 "SHA3-512": cmdHashAft(sha3.New512()),
157 "SHA3-512/MCT": cmdSha3Mct(sha3.New512()),
158
159
160
161
162
163
164 "SHA2-384/ENTROPY": cmdEntropyHashEntropySha384Aft(),
165 "SHA2-384/MCT/ENTROPY": cmdEntropyHashEntropySha384Mct(),
166
167
168
169
170
171 "SHAKE-128": cmdShakeAftVot(sha3.NewShake128()),
172 "SHAKE-128/VOT": cmdShakeAftVot(sha3.NewShake128()),
173 "SHAKE-128/MCT": cmdShakeMct(sha3.NewShake128()),
174 "SHAKE-256": cmdShakeAftVot(sha3.NewShake256()),
175 "SHAKE-256/VOT": cmdShakeAftVot(sha3.NewShake256()),
176 "SHAKE-256/MCT": cmdShakeMct(sha3.NewShake256()),
177
178 "cSHAKE-128": cmdCShakeAft(func(N, S []byte) *sha3.SHAKE { return sha3.NewCShake128(N, S) }),
179 "cSHAKE-128/MCT": cmdCShakeMct(func(N, S []byte) *sha3.SHAKE { return sha3.NewCShake128(N, S) }),
180 "cSHAKE-256": cmdCShakeAft(func(N, S []byte) *sha3.SHAKE { return sha3.NewCShake256(N, S) }),
181 "cSHAKE-256/MCT": cmdCShakeMct(func(N, S []byte) *sha3.SHAKE { return sha3.NewCShake256(N, S) }),
182
183 "HMAC-SHA2-224": cmdHmacAft(func() hash.Hash { return sha256.New224() }),
184 "HMAC-SHA2-256": cmdHmacAft(func() hash.Hash { return sha256.New() }),
185 "HMAC-SHA2-384": cmdHmacAft(func() hash.Hash { return sha512.New384() }),
186 "HMAC-SHA2-512": cmdHmacAft(func() hash.Hash { return sha512.New() }),
187 "HMAC-SHA2-512/224": cmdHmacAft(func() hash.Hash { return sha512.New512_224() }),
188 "HMAC-SHA2-512/256": cmdHmacAft(func() hash.Hash { return sha512.New512_256() }),
189 "HMAC-SHA3-224": cmdHmacAft(func() hash.Hash { return sha3.New224() }),
190 "HMAC-SHA3-256": cmdHmacAft(func() hash.Hash { return sha3.New256() }),
191 "HMAC-SHA3-384": cmdHmacAft(func() hash.Hash { return sha3.New384() }),
192 "HMAC-SHA3-512": cmdHmacAft(func() hash.Hash { return sha3.New512() }),
193
194 "HKDF/SHA2-224": cmdHkdfAft(func() hash.Hash { return sha256.New224() }),
195 "HKDF/SHA2-256": cmdHkdfAft(func() hash.Hash { return sha256.New() }),
196 "HKDF/SHA2-384": cmdHkdfAft(func() hash.Hash { return sha512.New384() }),
197 "HKDF/SHA2-512": cmdHkdfAft(func() hash.Hash { return sha512.New() }),
198 "HKDF/SHA2-512/224": cmdHkdfAft(func() hash.Hash { return sha512.New512_224() }),
199 "HKDF/SHA2-512/256": cmdHkdfAft(func() hash.Hash { return sha512.New512_256() }),
200 "HKDF/SHA3-224": cmdHkdfAft(func() hash.Hash { return sha3.New224() }),
201 "HKDF/SHA3-256": cmdHkdfAft(func() hash.Hash { return sha3.New256() }),
202 "HKDF/SHA3-384": cmdHkdfAft(func() hash.Hash { return sha3.New384() }),
203 "HKDF/SHA3-512": cmdHkdfAft(func() hash.Hash { return sha3.New512() }),
204
205 "HKDFExtract/SHA2-256": cmdHkdfExtractAft(func() hash.Hash { return sha256.New() }),
206 "HKDFExtract/SHA2-384": cmdHkdfExtractAft(func() hash.Hash { return sha512.New384() }),
207 "HKDFExpandLabel/SHA2-256": cmdHkdfExpandLabelAft(func() hash.Hash { return sha256.New() }),
208 "HKDFExpandLabel/SHA2-384": cmdHkdfExpandLabelAft(func() hash.Hash { return sha512.New384() }),
209
210 "PBKDF": cmdPbkdf(),
211
212 "ML-KEM-768/keyGen": cmdMlKem768KeyGenAft(),
213 "ML-KEM-768/encap": cmdMlKem768EncapAft(),
214 "ML-KEM-768/decap": cmdMlKem768DecapAft(),
215 "ML-KEM-1024/keyGen": cmdMlKem1024KeyGenAft(),
216 "ML-KEM-1024/encap": cmdMlKem1024EncapAft(),
217 "ML-KEM-1024/decap": cmdMlKem1024DecapAft(),
218
219 "hmacDRBG/SHA2-224": cmdHmacDrbgAft(func() hash.Hash { return sha256.New224() }),
220 "hmacDRBG/SHA2-256": cmdHmacDrbgAft(func() hash.Hash { return sha256.New() }),
221 "hmacDRBG/SHA2-384": cmdHmacDrbgAft(func() hash.Hash { return sha512.New384() }),
222 "hmacDRBG/SHA2-512": cmdHmacDrbgAft(func() hash.Hash { return sha512.New() }),
223 "hmacDRBG/SHA2-512/224": cmdHmacDrbgAft(func() hash.Hash { return sha512.New512_224() }),
224 "hmacDRBG/SHA2-512/256": cmdHmacDrbgAft(func() hash.Hash { return sha512.New512_256() }),
225 "hmacDRBG/SHA3-224": cmdHmacDrbgAft(func() hash.Hash { return sha3.New224() }),
226 "hmacDRBG/SHA3-256": cmdHmacDrbgAft(func() hash.Hash { return sha3.New256() }),
227 "hmacDRBG/SHA3-384": cmdHmacDrbgAft(func() hash.Hash { return sha3.New384() }),
228 "hmacDRBG/SHA3-512": cmdHmacDrbgAft(func() hash.Hash { return sha3.New512() }),
229
230 "EDDSA/keyGen": cmdEddsaKeyGenAft(),
231 "EDDSA/keyVer": cmdEddsaKeyVerAft(),
232 "EDDSA/sigGen": cmdEddsaSigGenAftBft(),
233 "EDDSA/sigVer": cmdEddsaSigVerAft(),
234
235 "ECDSA/keyGen": cmdEcdsaKeyGenAft(),
236 "ECDSA/keyVer": cmdEcdsaKeyVerAft(),
237 "ECDSA/sigGen": cmdEcdsaSigGenAft(ecdsaSigTypeNormal),
238 "ECDSA/sigVer": cmdEcdsaSigVerAft(),
239 "DetECDSA/sigGen": cmdEcdsaSigGenAft(ecdsaSigTypeDeterministic),
240
241 "AES-CBC/encrypt": cmdAesCbc(aesEncrypt),
242 "AES-CBC/decrypt": cmdAesCbc(aesDecrypt),
243 "AES-CTR/encrypt": cmdAesCtr(aesEncrypt),
244 "AES-CTR/decrypt": cmdAesCtr(aesDecrypt),
245 "AES-GCM/seal": cmdAesGcmSeal(false),
246 "AES-GCM/open": cmdAesGcmOpen(false),
247 "AES-GCM-randnonce/seal": cmdAesGcmSeal(true),
248 "AES-GCM-randnonce/open": cmdAesGcmOpen(true),
249
250 "CMAC-AES": cmdCmacAesAft(),
251 "CMAC-AES/verify": cmdCmacAesVerifyAft(),
252
253
254
255 "TLSKDF/1.2/SHA2-256": cmdTlsKdf12Aft(func() hash.Hash { return sha256.New() }),
256 "TLSKDF/1.2/SHA2-384": cmdTlsKdf12Aft(func() hash.Hash { return sha512.New384() }),
257 "TLSKDF/1.2/SHA2-512": cmdTlsKdf12Aft(func() hash.Hash { return sha512.New() }),
258
259
260
261 "SSHKDF/SHA2-224/client": cmdSshKdfAft(func() hash.Hash { return sha256.New224() }, ssh.ClientKeys),
262 "SSHKDF/SHA2-224/server": cmdSshKdfAft(func() hash.Hash { return sha256.New224() }, ssh.ServerKeys),
263 "SSHKDF/SHA2-256/client": cmdSshKdfAft(func() hash.Hash { return sha256.New() }, ssh.ClientKeys),
264 "SSHKDF/SHA2-256/server": cmdSshKdfAft(func() hash.Hash { return sha256.New() }, ssh.ServerKeys),
265 "SSHKDF/SHA2-384/client": cmdSshKdfAft(func() hash.Hash { return sha512.New384() }, ssh.ClientKeys),
266 "SSHKDF/SHA2-384/server": cmdSshKdfAft(func() hash.Hash { return sha512.New384() }, ssh.ServerKeys),
267 "SSHKDF/SHA2-512/client": cmdSshKdfAft(func() hash.Hash { return sha512.New() }, ssh.ClientKeys),
268 "SSHKDF/SHA2-512/server": cmdSshKdfAft(func() hash.Hash { return sha512.New() }, ssh.ServerKeys),
269
270 "ECDH/P-224": cmdEcdhAftVal(ecdh.P224()),
271 "ECDH/P-256": cmdEcdhAftVal(ecdh.P256()),
272 "ECDH/P-384": cmdEcdhAftVal(ecdh.P384()),
273 "ECDH/P-521": cmdEcdhAftVal(ecdh.P521()),
274
275 "ctrDRBG/AES-256": cmdCtrDrbgAft(),
276 "ctrDRBG-reseed/AES-256": cmdCtrDrbgReseedAft(),
277
278 "RSA/keyGen": cmdRsaKeyGenAft(),
279
280 "RSA/sigGen/SHA2-224/pkcs1v1.5": cmdRsaSigGenAft(func() hash.Hash { return sha256.New224() }, "SHA-224", false),
281 "RSA/sigGen/SHA2-256/pkcs1v1.5": cmdRsaSigGenAft(func() hash.Hash { return sha256.New() }, "SHA-256", false),
282 "RSA/sigGen/SHA2-384/pkcs1v1.5": cmdRsaSigGenAft(func() hash.Hash { return sha512.New384() }, "SHA-384", false),
283 "RSA/sigGen/SHA2-512/pkcs1v1.5": cmdRsaSigGenAft(func() hash.Hash { return sha512.New() }, "SHA-512", false),
284 "RSA/sigGen/SHA2-224/pss": cmdRsaSigGenAft(func() hash.Hash { return sha256.New224() }, "SHA-224", true),
285 "RSA/sigGen/SHA2-256/pss": cmdRsaSigGenAft(func() hash.Hash { return sha256.New() }, "SHA-256", true),
286 "RSA/sigGen/SHA2-384/pss": cmdRsaSigGenAft(func() hash.Hash { return sha512.New384() }, "SHA-384", true),
287 "RSA/sigGen/SHA2-512/pss": cmdRsaSigGenAft(func() hash.Hash { return sha512.New() }, "SHA-512", true),
288
289 "RSA/sigVer/SHA2-224/pkcs1v1.5": cmdRsaSigVerAft(func() hash.Hash { return sha256.New224() }, "SHA-224", false),
290 "RSA/sigVer/SHA2-256/pkcs1v1.5": cmdRsaSigVerAft(func() hash.Hash { return sha256.New() }, "SHA-256", false),
291 "RSA/sigVer/SHA2-384/pkcs1v1.5": cmdRsaSigVerAft(func() hash.Hash { return sha512.New384() }, "SHA-384", false),
292 "RSA/sigVer/SHA2-512/pkcs1v1.5": cmdRsaSigVerAft(func() hash.Hash { return sha512.New() }, "SHA-512", false),
293 "RSA/sigVer/SHA2-224/pss": cmdRsaSigVerAft(func() hash.Hash { return sha256.New224() }, "SHA-224", true),
294 "RSA/sigVer/SHA2-256/pss": cmdRsaSigVerAft(func() hash.Hash { return sha256.New() }, "SHA-256", true),
295 "RSA/sigVer/SHA2-384/pss": cmdRsaSigVerAft(func() hash.Hash { return sha512.New384() }, "SHA-384", true),
296 "RSA/sigVer/SHA2-512/pss": cmdRsaSigVerAft(func() hash.Hash { return sha512.New() }, "SHA-512", true),
297
298 "KDF-counter": cmdKdfCounterAft(),
299 "KDF-feedback": cmdKdfFeedbackAft(),
300
301 "OneStepNoCounter/HMAC-SHA2-224": cmdOneStepNoCounterHmacAft(func() hash.Hash { return sha256.New224() }),
302 "OneStepNoCounter/HMAC-SHA2-256": cmdOneStepNoCounterHmacAft(func() hash.Hash { return sha256.New() }),
303 "OneStepNoCounter/HMAC-SHA2-384": cmdOneStepNoCounterHmacAft(func() hash.Hash { return sha512.New384() }),
304 "OneStepNoCounter/HMAC-SHA2-512": cmdOneStepNoCounterHmacAft(func() hash.Hash { return sha512.New() }),
305 "OneStepNoCounter/HMAC-SHA2-512/224": cmdOneStepNoCounterHmacAft(func() hash.Hash { return sha512.New512_224() }),
306 "OneStepNoCounter/HMAC-SHA2-512/256": cmdOneStepNoCounterHmacAft(func() hash.Hash { return sha512.New512_256() }),
307 "OneStepNoCounter/HMAC-SHA3-224": cmdOneStepNoCounterHmacAft(func() hash.Hash { return sha3.New224() }),
308 "OneStepNoCounter/HMAC-SHA3-256": cmdOneStepNoCounterHmacAft(func() hash.Hash { return sha3.New256() }),
309 "OneStepNoCounter/HMAC-SHA3-384": cmdOneStepNoCounterHmacAft(func() hash.Hash { return sha3.New384() }),
310 "OneStepNoCounter/HMAC-SHA3-512": cmdOneStepNoCounterHmacAft(func() hash.Hash { return sha3.New512() }),
311
312 "KTS-IFC/SHA2-224/initiator": cmdKtsIfcInitiatorAft(func() hash.Hash { return sha256.New224() }),
313 "KTS-IFC/SHA2-224/responder": cmdKtsIfcResponderAft(func() hash.Hash { return sha256.New224() }),
314 "KTS-IFC/SHA2-256/initiator": cmdKtsIfcInitiatorAft(func() hash.Hash { return sha256.New() }),
315 "KTS-IFC/SHA2-256/responder": cmdKtsIfcResponderAft(func() hash.Hash { return sha256.New() }),
316 "KTS-IFC/SHA2-384/initiator": cmdKtsIfcInitiatorAft(func() hash.Hash { return sha512.New384() }),
317 "KTS-IFC/SHA2-384/responder": cmdKtsIfcResponderAft(func() hash.Hash { return sha512.New384() }),
318 "KTS-IFC/SHA2-512/initiator": cmdKtsIfcInitiatorAft(func() hash.Hash { return sha512.New() }),
319 "KTS-IFC/SHA2-512/responder": cmdKtsIfcResponderAft(func() hash.Hash { return sha512.New() }),
320 "KTS-IFC/SHA2-512/224/initiator": cmdKtsIfcInitiatorAft(func() hash.Hash { return sha512.New512_224() }),
321 "KTS-IFC/SHA2-512/224/responder": cmdKtsIfcResponderAft(func() hash.Hash { return sha512.New512_224() }),
322 "KTS-IFC/SHA2-512/256/initiator": cmdKtsIfcInitiatorAft(func() hash.Hash { return sha512.New512_256() }),
323 "KTS-IFC/SHA2-512/256/responder": cmdKtsIfcResponderAft(func() hash.Hash { return sha512.New512_256() }),
324 "KTS-IFC/SHA3-224/initiator": cmdKtsIfcInitiatorAft(func() hash.Hash { return sha3.New224() }),
325 "KTS-IFC/SHA3-224/responder": cmdKtsIfcResponderAft(func() hash.Hash { return sha3.New224() }),
326 "KTS-IFC/SHA3-256/initiator": cmdKtsIfcInitiatorAft(func() hash.Hash { return sha3.New256() }),
327 "KTS-IFC/SHA3-256/responder": cmdKtsIfcResponderAft(func() hash.Hash { return sha3.New256() }),
328 "KTS-IFC/SHA3-384/initiator": cmdKtsIfcInitiatorAft(func() hash.Hash { return sha3.New384() }),
329 "KTS-IFC/SHA3-384/responder": cmdKtsIfcResponderAft(func() hash.Hash { return sha3.New384() }),
330 "KTS-IFC/SHA3-512/initiator": cmdKtsIfcInitiatorAft(func() hash.Hash { return sha3.New512() }),
331 "KTS-IFC/SHA3-512/responder": cmdKtsIfcResponderAft(func() hash.Hash { return sha3.New512() }),
332 }
333 )
334
335 func processingLoop(reader io.Reader, writer io.Writer) error {
336
337
338
339 for {
340 req, err := readRequest(reader)
341 if errors.Is(err, io.EOF) {
342 break
343 } else if err != nil {
344 return fmt.Errorf("reading request: %w", err)
345 }
346
347 if entropyTesting && strings.HasPrefix(req.name, "SHA2-384") {
348 req.name = fmt.Sprintf("%s/ENTROPY", req.name)
349 }
350
351 cmd, exists := commands[req.name]
352 if !exists {
353 return fmt.Errorf("unknown command: %q", req.name)
354 }
355
356 if gotArgs := len(req.args); gotArgs != cmd.requiredArgs {
357 return fmt.Errorf("command %q expected %d args, got %d", req.name, cmd.requiredArgs, gotArgs)
358 }
359
360 response, err := cmd.handler(req.args)
361 if err != nil {
362 return fmt.Errorf("command %q failed: %w", req.name, err)
363 }
364
365 if err = writeResponse(writer, response); err != nil {
366 return fmt.Errorf("command %q response failed: %w", req.name, err)
367 }
368 }
369
370 return nil
371 }
372
373 func readRequest(reader io.Reader) (*request, error) {
374
375
376
377
378
379
380 var numArgs uint32
381 if err := binary.Read(reader, binary.LittleEndian, &numArgs); err != nil {
382 return nil, err
383 }
384 if numArgs == 0 {
385 return nil, errors.New("invalid request: zero args")
386 }
387
388 args, err := readArgs(reader, numArgs)
389 if err != nil {
390 return nil, err
391 }
392
393 return &request{
394 name: string(args[0]),
395 args: args[1:],
396 }, nil
397 }
398
399 func readArgs(reader io.Reader, requiredArgs uint32) ([][]byte, error) {
400 argLengths := make([]uint32, requiredArgs)
401 args := make([][]byte, requiredArgs)
402
403 for i := range argLengths {
404 if err := binary.Read(reader, binary.LittleEndian, &argLengths[i]); err != nil {
405 return nil, fmt.Errorf("invalid request: failed to read %d-th arg len: %w", i, err)
406 }
407 }
408
409 for i, length := range argLengths {
410 buf := make([]byte, length)
411 if _, err := io.ReadFull(reader, buf); err != nil {
412 return nil, fmt.Errorf("invalid request: failed to read %d-th arg data: %w", i, err)
413 }
414 args[i] = buf
415 }
416
417 return args, nil
418 }
419
420 func writeResponse(writer io.Writer, args [][]byte) error {
421
422
423
424 numArgs := uint32(len(args))
425 if err := binary.Write(writer, binary.LittleEndian, numArgs); err != nil {
426 return fmt.Errorf("writing arg count: %w", err)
427 }
428
429 for i, arg := range args {
430 if err := binary.Write(writer, binary.LittleEndian, uint32(len(arg))); err != nil {
431 return fmt.Errorf("writing %d-th arg length: %w", i, err)
432 }
433 }
434
435 for i, b := range args {
436 if _, err := writer.Write(b); err != nil {
437 return fmt.Errorf("writing %d-th arg data: %w", i, err)
438 }
439 }
440
441 return nil
442 }
443
444
445
446
447 func cmdGetConfig() command {
448
449
450 capabilities := [][]byte{capabilitiesJson}
451 if entropyTesting {
452 capabilities = [][]byte{entropyCapabilitiesJson}
453 }
454
455 return command{
456 handler: func(args [][]byte) ([][]byte, error) {
457 return capabilities, nil
458 },
459 }
460 }
461
462
463
464
465
466
467
468
469 func cmdHashAft(h hash.Hash) command {
470 return command{
471 requiredArgs: 1,
472 handler: func(args [][]byte) ([][]byte, error) {
473 h.Reset()
474 h.Write(args[0])
475 digest := make([]byte, 0, h.Size())
476 digest = h.Sum(digest)
477
478 return [][]byte{digest}, nil
479 },
480 }
481 }
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497 func cmdHashMct(h hash.Hash) command {
498 return command{
499 requiredArgs: 1,
500 handler: func(args [][]byte) ([][]byte, error) {
501 hSize := h.Size()
502 seed := args[0]
503
504 if seedLen := len(seed); seedLen != hSize {
505 return nil, fmt.Errorf("invalid seed size: expected %d got %d", hSize, seedLen)
506 }
507
508 digest := make([]byte, 0, hSize)
509 buf := make([]byte, 0, 3*hSize)
510 buf = append(buf, seed...)
511 buf = append(buf, seed...)
512 buf = append(buf, seed...)
513
514 for i := 0; i < 1000; i++ {
515 h.Reset()
516 h.Write(buf)
517 digest = h.Sum(digest[:0])
518
519 copy(buf, buf[hSize:])
520 copy(buf[2*hSize:], digest)
521 }
522
523 return [][]byte{buf[hSize*2:]}, nil
524 },
525 }
526 }
527
528
529
530 func cmdEntropyHashEntropySha384Aft() command {
531 return command{
532 requiredArgs: 1,
533 handler: func(args [][]byte) ([][]byte, error) {
534 digest := entropy.TestingOnlySHA384(args[0])
535 return [][]byte{digest[:]}, nil
536 },
537 }
538 }
539
540
541
542 func cmdEntropyHashEntropySha384Mct() command {
543 return command{
544 requiredArgs: 1,
545 handler: func(args [][]byte) ([][]byte, error) {
546 hSize := 48
547 seed := args[0]
548
549 digest := make([]byte, 0, hSize)
550 buf := make([]byte, 0, 3*hSize)
551 buf = append(buf, seed...)
552 buf = append(buf, seed...)
553 buf = append(buf, seed...)
554
555 for i := 0; i < 1000; i++ {
556 digestRaw := entropy.TestingOnlySHA384(buf)
557 digest = digestRaw[:hSize]
558
559 copy(buf, buf[hSize:])
560 copy(buf[2*hSize:], digest)
561 }
562
563 return [][]byte{buf[hSize*2:]}, nil
564 },
565 }
566 }
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581 func cmdSha3Mct(h hash.Hash) command {
582 return command{
583 requiredArgs: 1,
584 handler: func(args [][]byte) ([][]byte, error) {
585 seed := args[0]
586 md := make([][]byte, 1001)
587 md[0] = seed
588
589 for i := 1; i <= 1000; i++ {
590 h.Reset()
591 h.Write(md[i-1])
592 md[i] = h.Sum(nil)
593 }
594
595 return [][]byte{md[1000]}, nil
596 },
597 }
598 }
599
600 func cmdShakeAftVot(h *sha3.SHAKE) command {
601 return command{
602 requiredArgs: 2,
603 handler: func(args [][]byte) ([][]byte, error) {
604 msg := args[0]
605
606 outLenBytes := binary.LittleEndian.Uint32(args[1])
607 digest := make([]byte, outLenBytes)
608
609 h.Reset()
610 h.Write(msg)
611 h.Read(digest)
612
613 return [][]byte{digest}, nil
614 },
615 }
616 }
617
618 func cmdShakeMct(h *sha3.SHAKE) command {
619 return command{
620 requiredArgs: 4,
621 handler: func(args [][]byte) ([][]byte, error) {
622 md := args[0]
623 minOutBytes := binary.LittleEndian.Uint32(args[1])
624 maxOutBytes := binary.LittleEndian.Uint32(args[2])
625
626 outputLenBytes := binary.LittleEndian.Uint32(args[3])
627 if outputLenBytes < 2 {
628 return nil, fmt.Errorf("invalid output length: %d", outputLenBytes)
629 }
630
631 rangeBytes := maxOutBytes - minOutBytes + 1
632 if rangeBytes == 0 {
633 return nil, fmt.Errorf("invalid maxOutBytes and minOutBytes: %d, %d", maxOutBytes, minOutBytes)
634 }
635
636 for i := 0; i < 1000; i++ {
637
638
639 boundary := min(len(md), 16)
640 msg := make([]byte, 16)
641 copy(msg, md[:boundary])
642
643
644 h.Reset()
645 h.Write(msg)
646 digest := make([]byte, outputLenBytes)
647 h.Read(digest)
648 md = digest
649
650
651
652 rightmostOutput := uint32(md[outputLenBytes-2])<<8 | uint32(md[outputLenBytes-1])
653 outputLenBytes = minOutBytes + (rightmostOutput % rangeBytes)
654 }
655
656 encodedOutputLenBytes := make([]byte, 4)
657 binary.LittleEndian.PutUint32(encodedOutputLenBytes, outputLenBytes)
658
659 return [][]byte{md, encodedOutputLenBytes}, nil
660 },
661 }
662 }
663
664 func cmdCShakeAft(hFn func(N, S []byte) *sha3.SHAKE) command {
665 return command{
666 requiredArgs: 4,
667 handler: func(args [][]byte) ([][]byte, error) {
668 msg := args[0]
669 outLenBytes := binary.LittleEndian.Uint32(args[1])
670 functionName := args[2]
671 customization := args[3]
672
673 h := hFn(functionName, customization)
674 h.Write(msg)
675
676 out := make([]byte, outLenBytes)
677 h.Read(out)
678
679 return [][]byte{out}, nil
680 },
681 }
682 }
683
684 func cmdCShakeMct(hFn func(N, S []byte) *sha3.SHAKE) command {
685 return command{
686 requiredArgs: 6,
687 handler: func(args [][]byte) ([][]byte, error) {
688 message := args[0]
689 minOutLenBytes := binary.LittleEndian.Uint32(args[1])
690 maxOutLenBytes := binary.LittleEndian.Uint32(args[2])
691 outputLenBytes := binary.LittleEndian.Uint32(args[3])
692 incrementBytes := binary.LittleEndian.Uint32(args[4])
693 customization := args[5]
694
695 if outputLenBytes < 2 {
696 return nil, fmt.Errorf("invalid output length: %d", outputLenBytes)
697 }
698
699 rangeBits := (maxOutLenBytes*8 - minOutLenBytes*8) + 1
700 if rangeBits == 0 {
701 return nil, fmt.Errorf("invalid maxOutLenBytes and minOutLenBytes: %d, %d", maxOutLenBytes, minOutLenBytes)
702 }
703
704
705
706 for i := 0; i < 1000; i++ {
707
708 boundary := min(len(message), 16)
709 innerMsg := make([]byte, 16)
710 copy(innerMsg, message[:boundary])
711
712
713 h := hFn(nil, customization)
714 h.Write(innerMsg)
715 digest := make([]byte, outputLenBytes)
716 h.Read(digest)
717 message = digest
718
719
720 rightmostOutput := digest[outputLenBytes-2:]
721
722
723
724
725 rightmostOutputBE := binary.BigEndian.Uint16(rightmostOutput)
726
727
728 incrementBits := incrementBytes * 8
729 outputLenBits := (minOutLenBytes * 8) + (((uint32)(rightmostOutputBE)%rangeBits)/incrementBits)*incrementBits
730 outputLenBytes = outputLenBits / 8
731
732
733 msgWithBits := append(innerMsg, rightmostOutput...)
734 customization = make([]byte, len(msgWithBits))
735 for i, b := range msgWithBits {
736 customization[i] = (b % 26) + 65
737 }
738 }
739
740 encodedOutputLenBytes := make([]byte, 4)
741 binary.LittleEndian.PutUint32(encodedOutputLenBytes, outputLenBytes)
742
743 return [][]byte{message, encodedOutputLenBytes, customization}, nil
744 },
745 }
746 }
747
748 func cmdHmacAft(h func() hash.Hash) command {
749 return command{
750 requiredArgs: 2,
751 handler: func(args [][]byte) ([][]byte, error) {
752 msg := args[0]
753 key := args[1]
754 mac := hmac.New(h, key)
755 mac.Write(msg)
756 return [][]byte{mac.Sum(nil)}, nil
757 },
758 }
759 }
760
761 func cmdHkdfAft(h func() hash.Hash) command {
762 return command{
763 requiredArgs: 4,
764 handler: func(args [][]byte) ([][]byte, error) {
765 key := args[0]
766 salt := args[1]
767 info := args[2]
768 keyLen := int(binary.LittleEndian.Uint32(args[3]))
769
770 return [][]byte{hkdf.Key(h, key, salt, string(info), keyLen)}, nil
771 },
772 }
773 }
774
775 func cmdHkdfExtractAft(h func() hash.Hash) command {
776 return command{
777 requiredArgs: 2,
778 handler: func(args [][]byte) ([][]byte, error) {
779 secret := args[0]
780 salt := args[1]
781
782 return [][]byte{hkdf.Extract(h, secret, salt)}, nil
783 },
784 }
785 }
786
787 func cmdHkdfExpandLabelAft(h func() hash.Hash) command {
788 return command{
789 requiredArgs: 4,
790 handler: func(args [][]byte) ([][]byte, error) {
791 keyLen := int(binary.LittleEndian.Uint32(args[0]))
792 secret := args[1]
793 label := args[2]
794 transcriptHash := args[3]
795
796 return [][]byte{tls13.ExpandLabel(h, secret, string(label), transcriptHash, keyLen)}, nil
797 },
798 }
799 }
800
801 func cmdPbkdf() command {
802 return command{
803
804 requiredArgs: 5,
805 handler: func(args [][]byte) ([][]byte, error) {
806 h, err := lookupHash(string(args[0]))
807 if err != nil {
808 return nil, fmt.Errorf("PBKDF2 failed: %w", err)
809 }
810
811 keyLen := binary.LittleEndian.Uint32(args[1]) / 8
812 salt := args[2]
813 password := args[3]
814 iterationCount := binary.LittleEndian.Uint32(args[4])
815
816 derivedKey, err := pbkdf2.Key(h, string(password), salt, int(iterationCount), int(keyLen))
817 if err != nil {
818 return nil, fmt.Errorf("PBKDF2 failed: %w", err)
819 }
820
821 return [][]byte{derivedKey}, nil
822 },
823 }
824 }
825
826 func cmdEddsaKeyGenAft() command {
827 return command{
828 requiredArgs: 1,
829 handler: func(args [][]byte) ([][]byte, error) {
830 if string(args[0]) != "ED-25519" {
831 return nil, fmt.Errorf("unsupported EDDSA curve: %q", args[0])
832 }
833
834 sk, err := ed25519.GenerateKey()
835 if err != nil {
836 return nil, fmt.Errorf("generating EDDSA keypair: %w", err)
837 }
838
839
840
841
842
843
844
845
846
847
848 return [][]byte{sk.Seed(), sk.PublicKey()}, nil
849 },
850 }
851 }
852
853 func cmdEddsaKeyVerAft() command {
854 return command{
855 requiredArgs: 2,
856 handler: func(args [][]byte) ([][]byte, error) {
857 if string(args[0]) != "ED-25519" {
858 return nil, fmt.Errorf("unsupported EDDSA curve: %q", args[0])
859 }
860
861
862
863
864 if _, err := new(edwards25519.Point).SetBytes(args[1]); err != nil {
865 return [][]byte{{0}}, nil
866 }
867
868 return [][]byte{{1}}, nil
869 },
870 }
871 }
872
873 func cmdEddsaSigGenAftBft() command {
874 return command{
875 requiredArgs: 5,
876 handler: func(args [][]byte) ([][]byte, error) {
877 if string(args[0]) != "ED-25519" {
878 return nil, fmt.Errorf("unsupported EDDSA curve: %q", args[0])
879 }
880
881 sk, err := ed25519.NewPrivateKeyFromSeed(args[1])
882 if err != nil {
883 return nil, fmt.Errorf("error creating private key: %w", err)
884 }
885 msg := args[2]
886 prehash := args[3]
887 context := string(args[4])
888
889 var sig []byte
890 if prehash[0] == 1 {
891 h := sha512.New()
892 h.Write(msg)
893 msg = h.Sum(nil)
894
895
896
897 sig, err = ed25519.SignPH(sk, msg, context)
898 if err != nil {
899 return nil, fmt.Errorf("error signing message: %w", err)
900 }
901 } else {
902 sig = ed25519.Sign(sk, msg)
903 }
904
905 return [][]byte{sig}, nil
906 },
907 }
908 }
909
910 func cmdEddsaSigVerAft() command {
911 return command{
912 requiredArgs: 5,
913 handler: func(args [][]byte) ([][]byte, error) {
914 if string(args[0]) != "ED-25519" {
915 return nil, fmt.Errorf("unsupported EDDSA curve: %q", args[0])
916 }
917
918 msg := args[1]
919 pk, err := ed25519.NewPublicKey(args[2])
920 if err != nil {
921 return nil, fmt.Errorf("invalid public key: %w", err)
922 }
923 sig := args[3]
924 prehash := args[4]
925
926 if prehash[0] == 1 {
927 h := sha512.New()
928 h.Write(msg)
929 msg = h.Sum(nil)
930
931
932 err = ed25519.VerifyPH(pk, msg, sig, "")
933 } else {
934 err = ed25519.Verify(pk, msg, sig)
935 }
936
937 if err != nil {
938 return [][]byte{{0}}, nil
939 }
940
941 return [][]byte{{1}}, nil
942 },
943 }
944 }
945
946 func cmdEcdsaKeyGenAft() command {
947 return command{
948 requiredArgs: 1,
949 handler: func(args [][]byte) ([][]byte, error) {
950 curve, err := lookupCurve(string(args[0]))
951 if err != nil {
952 return nil, err
953 }
954
955 var sk *ecdsa.PrivateKey
956 switch curve.Params() {
957 case elliptic.P224().Params():
958 sk, err = ecdsa.GenerateKey(ecdsa.P224(), rand.Reader)
959 case elliptic.P256().Params():
960 sk, err = ecdsa.GenerateKey(ecdsa.P256(), rand.Reader)
961 case elliptic.P384().Params():
962 sk, err = ecdsa.GenerateKey(ecdsa.P384(), rand.Reader)
963 case elliptic.P521().Params():
964 sk, err = ecdsa.GenerateKey(ecdsa.P521(), rand.Reader)
965 default:
966 return nil, fmt.Errorf("unsupported curve: %v", curve)
967 }
968
969 if err != nil {
970 return nil, err
971 }
972
973 pubBytes := sk.PublicKey().Bytes()
974 byteLen := (curve.Params().BitSize + 7) / 8
975
976 return [][]byte{
977 sk.Bytes(),
978 pubBytes[1 : 1+byteLen],
979 pubBytes[1+byteLen:],
980 }, nil
981 },
982 }
983 }
984
985 func cmdEcdsaKeyVerAft() command {
986 return command{
987 requiredArgs: 3,
988 handler: func(args [][]byte) ([][]byte, error) {
989 curve, err := lookupCurve(string(args[0]))
990 if err != nil {
991 return nil, err
992 }
993
994 x := new(big.Int).SetBytes(args[1])
995 y := new(big.Int).SetBytes(args[2])
996
997 if curve.IsOnCurve(x, y) {
998 return [][]byte{{1}}, nil
999 }
1000
1001 return [][]byte{{0}}, nil
1002 },
1003 }
1004 }
1005
1006
1007
1008 func pointFromAffine(curve elliptic.Curve, x, y *big.Int) ([]byte, error) {
1009 bitSize := curve.Params().BitSize
1010
1011 if x.Sign() < 0 || y.Sign() < 0 {
1012 return nil, errors.New("negative coordinate")
1013 }
1014 if x.BitLen() > bitSize || y.BitLen() > bitSize {
1015 return nil, errors.New("overflowing coordinate")
1016 }
1017
1018 byteLen := (bitSize + 7) / 8
1019 buf := make([]byte, 1+2*byteLen)
1020 buf[0] = 4
1021 x.FillBytes(buf[1 : 1+byteLen])
1022 y.FillBytes(buf[1+byteLen : 1+2*byteLen])
1023 return buf, nil
1024 }
1025
1026 func signEcdsa[P ecdsa.Point[P], H hash.Hash](c *ecdsa.Curve[P], h func() H, sigType ecdsaSigType, q []byte, sk []byte, digest []byte) (*ecdsa.Signature, error) {
1027 priv, err := ecdsa.NewPrivateKey(c, sk, q)
1028 if err != nil {
1029 return nil, fmt.Errorf("invalid private key: %w", err)
1030 }
1031
1032 var sig *ecdsa.Signature
1033 switch sigType {
1034 case ecdsaSigTypeNormal:
1035 sig, err = ecdsa.Sign(c, h, priv, rand.Reader, digest)
1036 case ecdsaSigTypeDeterministic:
1037 sig, err = ecdsa.SignDeterministic(c, h, priv, digest)
1038 default:
1039 return nil, fmt.Errorf("unsupported signature type: %v", sigType)
1040 }
1041 if err != nil {
1042 return nil, fmt.Errorf("signing failed: %w", err)
1043 }
1044
1045 return sig, nil
1046 }
1047
1048 func cmdEcdsaSigGenAft(sigType ecdsaSigType) command {
1049 return command{
1050 requiredArgs: 4,
1051 handler: func(args [][]byte) ([][]byte, error) {
1052 curve, err := lookupCurve(string(args[0]))
1053 if err != nil {
1054 return nil, err
1055 }
1056
1057 sk := args[1]
1058
1059 newH, err := lookupHash(string(args[2]))
1060 if err != nil {
1061 return nil, err
1062 }
1063
1064 msg := args[3]
1065 hashFunc := newH()
1066 hashFunc.Write(msg)
1067 digest := hashFunc.Sum(nil)
1068
1069 d := new(big.Int).SetBytes(sk)
1070 x, y := curve.ScalarBaseMult(d.Bytes())
1071 q, err := pointFromAffine(curve, x, y)
1072 if err != nil {
1073 return nil, err
1074 }
1075
1076 var sig *ecdsa.Signature
1077 switch curve.Params() {
1078 case elliptic.P224().Params():
1079 sig, err = signEcdsa(ecdsa.P224(), newH, sigType, q, sk, digest)
1080 case elliptic.P256().Params():
1081 sig, err = signEcdsa(ecdsa.P256(), newH, sigType, q, sk, digest)
1082 case elliptic.P384().Params():
1083 sig, err = signEcdsa(ecdsa.P384(), newH, sigType, q, sk, digest)
1084 case elliptic.P521().Params():
1085 sig, err = signEcdsa(ecdsa.P521(), newH, sigType, q, sk, digest)
1086 default:
1087 return nil, fmt.Errorf("unsupported curve: %v", curve)
1088 }
1089 if err != nil {
1090 return nil, err
1091 }
1092
1093 return [][]byte{sig.R, sig.S}, nil
1094 },
1095 }
1096 }
1097
1098 func cmdEcdsaSigVerAft() command {
1099 return command{
1100 requiredArgs: 7,
1101 handler: func(args [][]byte) ([][]byte, error) {
1102 curve, err := lookupCurve(string(args[0]))
1103 if err != nil {
1104 return nil, err
1105 }
1106
1107 newH, err := lookupHash(string(args[1]))
1108 if err != nil {
1109 return nil, err
1110 }
1111
1112 msg := args[2]
1113 hashFunc := newH()
1114 hashFunc.Write(msg)
1115 digest := hashFunc.Sum(nil)
1116
1117 x, y := args[3], args[4]
1118 q, err := pointFromAffine(curve, new(big.Int).SetBytes(x), new(big.Int).SetBytes(y))
1119 if err != nil {
1120 return nil, fmt.Errorf("invalid x/y coordinates: %v", err)
1121 }
1122
1123 signature := &ecdsa.Signature{R: args[5], S: args[6]}
1124
1125 switch curve.Params() {
1126 case elliptic.P224().Params():
1127 err = verifyEcdsa(ecdsa.P224(), q, digest, signature)
1128 case elliptic.P256().Params():
1129 err = verifyEcdsa(ecdsa.P256(), q, digest, signature)
1130 case elliptic.P384().Params():
1131 err = verifyEcdsa(ecdsa.P384(), q, digest, signature)
1132 case elliptic.P521().Params():
1133 err = verifyEcdsa(ecdsa.P521(), q, digest, signature)
1134 default:
1135 return nil, fmt.Errorf("unsupported curve: %v", curve)
1136 }
1137
1138 if err == nil {
1139 return [][]byte{{1}}, nil
1140 }
1141
1142 return [][]byte{{0}}, nil
1143 },
1144 }
1145 }
1146
1147 func verifyEcdsa[P ecdsa.Point[P]](c *ecdsa.Curve[P], q []byte, digest []byte, sig *ecdsa.Signature) error {
1148 pub, err := ecdsa.NewPublicKey(c, q)
1149 if err != nil {
1150 return fmt.Errorf("invalid public key: %w", err)
1151 }
1152
1153 return ecdsa.Verify(c, pub, digest, sig)
1154 }
1155
1156 func lookupHash(name string) (func() hash.Hash, error) {
1157 var h func() hash.Hash
1158
1159 switch name {
1160 case "SHA2-224":
1161 h = func() hash.Hash { return sha256.New224() }
1162 case "SHA2-256":
1163 h = func() hash.Hash { return sha256.New() }
1164 case "SHA2-384":
1165 h = func() hash.Hash { return sha512.New384() }
1166 case "SHA2-512":
1167 h = func() hash.Hash { return sha512.New() }
1168 case "SHA2-512/224":
1169 h = func() hash.Hash { return sha512.New512_224() }
1170 case "SHA2-512/256":
1171 h = func() hash.Hash { return sha512.New512_256() }
1172 case "SHA3-224":
1173 h = func() hash.Hash { return sha3.New224() }
1174 case "SHA3-256":
1175 h = func() hash.Hash { return sha3.New256() }
1176 case "SHA3-384":
1177 h = func() hash.Hash { return sha3.New384() }
1178 case "SHA3-512":
1179 h = func() hash.Hash { return sha3.New512() }
1180 default:
1181 return nil, fmt.Errorf("unknown hash name: %q", name)
1182 }
1183
1184 return h, nil
1185 }
1186
1187 func cmdMlKem768KeyGenAft() command {
1188 return command{
1189 requiredArgs: 1,
1190 handler: func(args [][]byte) ([][]byte, error) {
1191 seed := args[0]
1192
1193 dk, err := mlkem.NewDecapsulationKey768(seed)
1194 if err != nil {
1195 return nil, fmt.Errorf("generating ML-KEM 768 decapsulation key: %w", err)
1196 }
1197
1198
1199 return [][]byte{dk.EncapsulationKey().Bytes(), mlkem.TestingOnlyExpandedBytes768(dk)}, nil
1200 },
1201 }
1202 }
1203
1204 func cmdMlKem768EncapAft() command {
1205 return command{
1206 requiredArgs: 2,
1207 handler: func(args [][]byte) ([][]byte, error) {
1208 pk := args[0]
1209 entropy := args[1]
1210
1211 ek, err := mlkem.NewEncapsulationKey768(pk)
1212 if err != nil {
1213 return nil, fmt.Errorf("generating ML-KEM 768 encapsulation key: %w", err)
1214 }
1215
1216 if len(entropy) != 32 {
1217 return nil, fmt.Errorf("wrong entropy length: got %d, want 32", len(entropy))
1218 }
1219
1220 sharedKey, ct := ek.EncapsulateInternal((*[32]byte)(entropy[:32]))
1221
1222 return [][]byte{ct, sharedKey}, nil
1223 },
1224 }
1225 }
1226
1227 func cmdMlKem768DecapAft() command {
1228 return command{
1229 requiredArgs: 2,
1230 handler: func(args [][]byte) ([][]byte, error) {
1231 pk := args[0]
1232 ct := args[1]
1233
1234 dk, err := mlkem.TestingOnlyNewDecapsulationKey768(pk)
1235 if err != nil {
1236 return nil, fmt.Errorf("generating ML-KEM 768 decapsulation key: %w", err)
1237 }
1238
1239 sharedKey, err := dk.Decapsulate(ct)
1240 if err != nil {
1241 return nil, fmt.Errorf("decapsulating ML-KEM 768 ciphertext: %w", err)
1242 }
1243
1244 return [][]byte{sharedKey}, nil
1245 },
1246 }
1247 }
1248
1249 func cmdMlKem1024KeyGenAft() command {
1250 return command{
1251 requiredArgs: 1,
1252 handler: func(args [][]byte) ([][]byte, error) {
1253 seed := args[0]
1254
1255 dk, err := mlkem.NewDecapsulationKey1024(seed)
1256 if err != nil {
1257 return nil, fmt.Errorf("generating ML-KEM 1024 decapsulation key: %w", err)
1258 }
1259
1260
1261 return [][]byte{dk.EncapsulationKey().Bytes(), mlkem.TestingOnlyExpandedBytes1024(dk)}, nil
1262 },
1263 }
1264 }
1265
1266 func cmdMlKem1024EncapAft() command {
1267 return command{
1268 requiredArgs: 2,
1269 handler: func(args [][]byte) ([][]byte, error) {
1270 pk := args[0]
1271 entropy := args[1]
1272
1273 ek, err := mlkem.NewEncapsulationKey1024(pk)
1274 if err != nil {
1275 return nil, fmt.Errorf("generating ML-KEM 1024 encapsulation key: %w", err)
1276 }
1277
1278 if len(entropy) != 32 {
1279 return nil, fmt.Errorf("wrong entropy length: got %d, want 32", len(entropy))
1280 }
1281
1282 sharedKey, ct := ek.EncapsulateInternal((*[32]byte)(entropy[:32]))
1283
1284 return [][]byte{ct, sharedKey}, nil
1285 },
1286 }
1287 }
1288
1289 func cmdMlKem1024DecapAft() command {
1290 return command{
1291 requiredArgs: 2,
1292 handler: func(args [][]byte) ([][]byte, error) {
1293 pk := args[0]
1294 ct := args[1]
1295
1296 dk, err := mlkem.TestingOnlyNewDecapsulationKey1024(pk)
1297 if err != nil {
1298 return nil, fmt.Errorf("generating ML-KEM 1024 decapsulation key: %w", err)
1299 }
1300
1301 sharedKey, err := dk.Decapsulate(ct)
1302 if err != nil {
1303 return nil, fmt.Errorf("decapsulating ML-KEM 1024 ciphertext: %w", err)
1304 }
1305
1306 return [][]byte{sharedKey}, nil
1307 },
1308 }
1309 }
1310
1311 func lookupCurve(name string) (elliptic.Curve, error) {
1312 var c elliptic.Curve
1313
1314 switch name {
1315 case "P-224":
1316 c = elliptic.P224()
1317 case "P-256":
1318 c = elliptic.P256()
1319 case "P-384":
1320 c = elliptic.P384()
1321 case "P-521":
1322 c = elliptic.P521()
1323 default:
1324 return nil, fmt.Errorf("unknown curve name: %q", name)
1325 }
1326
1327 return c, nil
1328 }
1329
1330 func cmdAesCbc(direction aesDirection) command {
1331 return command{
1332 requiredArgs: 4,
1333 handler: func(args [][]byte) ([][]byte, error) {
1334 if direction != aesEncrypt && direction != aesDecrypt {
1335 panic("invalid AES direction")
1336 }
1337
1338 key := args[0]
1339 input := args[1]
1340 iv := args[2]
1341 numIterations := binary.LittleEndian.Uint32(args[3])
1342
1343 blockCipher, err := aes.New(key)
1344 if err != nil {
1345 return nil, fmt.Errorf("creating AES block cipher with key len %d: %w", len(key), err)
1346 }
1347
1348 if len(input)%blockCipher.BlockSize() != 0 || len(input) == 0 {
1349 return nil, fmt.Errorf("invalid ciphertext/plaintext size %d: not a multiple of block size %d",
1350 len(input), blockCipher.BlockSize())
1351 }
1352
1353 if blockCipher.BlockSize() != len(iv) {
1354 return nil, fmt.Errorf("invalid IV size: expected %d, got %d", blockCipher.BlockSize(), len(iv))
1355 }
1356
1357 result := make([]byte, len(input))
1358 prevResult := make([]byte, len(input))
1359 prevInput := make([]byte, len(input))
1360
1361 for i := uint32(0); i < numIterations; i++ {
1362 copy(prevResult, result)
1363
1364 if i > 0 {
1365 if direction == aesEncrypt {
1366 copy(iv, result)
1367 } else {
1368 copy(iv, prevInput)
1369 }
1370 }
1371
1372 if direction == aesEncrypt {
1373 cbcEnc := aes.NewCBCEncrypter(blockCipher, [16]byte(iv))
1374 cbcEnc.CryptBlocks(result, input)
1375 } else {
1376 cbcDec := aes.NewCBCDecrypter(blockCipher, [16]byte(iv))
1377 cbcDec.CryptBlocks(result, input)
1378 }
1379
1380 if direction == aesDecrypt {
1381 copy(prevInput, input)
1382 }
1383
1384 if i == 0 {
1385 copy(input, iv)
1386 } else {
1387 copy(input, prevResult)
1388 }
1389 }
1390
1391 return [][]byte{result, prevResult}, nil
1392 },
1393 }
1394 }
1395
1396 func cmdAesCtr(direction aesDirection) command {
1397 return command{
1398 requiredArgs: 4,
1399 handler: func(args [][]byte) ([][]byte, error) {
1400 if direction != aesEncrypt && direction != aesDecrypt {
1401 panic("invalid AES direction")
1402 }
1403
1404 key := args[0]
1405 input := args[1]
1406 iv := args[2]
1407 numIterations := binary.LittleEndian.Uint32(args[3])
1408 if numIterations != 1 {
1409 return nil, fmt.Errorf("invalid num iterations: expected 1, got %d", numIterations)
1410 }
1411
1412 if len(iv) != aes.BlockSize {
1413 return nil, fmt.Errorf("invalid IV size: expected %d, got %d", aes.BlockSize, len(iv))
1414 }
1415
1416 blockCipher, err := aes.New(key)
1417 if err != nil {
1418 return nil, fmt.Errorf("creating AES block cipher with key len %d: %w", len(key), err)
1419 }
1420
1421 result := make([]byte, len(input))
1422 stream := aes.NewCTR(blockCipher, iv)
1423 stream.XORKeyStream(result, input)
1424
1425 return [][]byte{result}, nil
1426 },
1427 }
1428 }
1429
1430 func cmdAesGcmSeal(randNonce bool) command {
1431 return command{
1432 requiredArgs: 5,
1433 handler: func(args [][]byte) ([][]byte, error) {
1434 tagLen := binary.LittleEndian.Uint32(args[0])
1435 key := args[1]
1436 plaintext := args[2]
1437 nonce := args[3]
1438 additionalData := args[4]
1439
1440 blockCipher, err := aes.New(key)
1441 if err != nil {
1442 return nil, fmt.Errorf("creating AES block cipher with key len %d: %w", len(key), err)
1443 }
1444
1445 aesGCM, err := gcm.New(blockCipher, 12, int(tagLen))
1446 if err != nil {
1447 return nil, fmt.Errorf("creating AES-GCM with tag len %d: %w", tagLen, err)
1448 }
1449
1450 var ct []byte
1451 if !randNonce {
1452 ct = aesGCM.Seal(nil, nonce, plaintext, additionalData)
1453 } else {
1454 var internalNonce [12]byte
1455 ct = make([]byte, len(plaintext)+16)
1456 gcm.SealWithRandomNonce(aesGCM, internalNonce[:], ct, plaintext, additionalData)
1457
1458 ct = append(ct, internalNonce[:]...)
1459 }
1460
1461 return [][]byte{ct}, nil
1462 },
1463 }
1464 }
1465
1466 func cmdAesGcmOpen(randNonce bool) command {
1467 return command{
1468 requiredArgs: 5,
1469 handler: func(args [][]byte) ([][]byte, error) {
1470
1471 tagLen := binary.LittleEndian.Uint32(args[0])
1472 key := args[1]
1473 ciphertext := args[2]
1474 nonce := args[3]
1475 additionalData := args[4]
1476
1477 blockCipher, err := aes.New(key)
1478 if err != nil {
1479 return nil, fmt.Errorf("creating AES block cipher with key len %d: %w", len(key), err)
1480 }
1481
1482 aesGCM, err := gcm.New(blockCipher, 12, int(tagLen))
1483 if err != nil {
1484 return nil, fmt.Errorf("creating AES-GCM with tag len %d: %w", tagLen, err)
1485 }
1486
1487 if randNonce {
1488
1489 nonce = ciphertext[len(ciphertext)-12:]
1490 ciphertext = ciphertext[:len(ciphertext)-12]
1491 }
1492
1493 pt, err := aesGCM.Open(nil, nonce, ciphertext, additionalData)
1494 if err != nil {
1495 return [][]byte{{0}, nil}, nil
1496 }
1497
1498 return [][]byte{{1}, pt}, nil
1499 },
1500 }
1501 }
1502
1503 func cmdCmacAesAft() command {
1504 return command{
1505 requiredArgs: 3,
1506 handler: func(args [][]byte) ([][]byte, error) {
1507
1508 outputLen := int(binary.LittleEndian.Uint32(args[0]))
1509 key := args[1]
1510 message := args[2]
1511
1512 blockCipher, err := aes.New(key)
1513 if err != nil {
1514 return nil, fmt.Errorf("creating AES block cipher with key len %d: %w", len(key), err)
1515 }
1516
1517 cmac := gcm.NewCMAC(blockCipher)
1518 tag := cmac.MAC(message)
1519
1520 if outputLen > len(tag) {
1521 return nil, fmt.Errorf("invalid output length: expected %d, got %d", outputLen, len(tag))
1522 }
1523
1524 return [][]byte{tag[:outputLen]}, nil
1525 },
1526 }
1527 }
1528
1529 func cmdCmacAesVerifyAft() command {
1530 return command{
1531 requiredArgs: 3,
1532 handler: func(args [][]byte) ([][]byte, error) {
1533 key := args[0]
1534 message := args[1]
1535 claimedMAC := args[2]
1536
1537 blockCipher, err := aes.New(key)
1538 if err != nil {
1539 return nil, fmt.Errorf("creating AES block cipher with key len %d: %w", len(key), err)
1540 }
1541
1542 cmac := gcm.NewCMAC(blockCipher)
1543 tag := cmac.MAC(message)
1544
1545 if subtle.ConstantTimeCompare(tag[:len(claimedMAC)], claimedMAC) != 1 {
1546 return [][]byte{{0}}, nil
1547 }
1548
1549 return [][]byte{{1}}, nil
1550 },
1551 }
1552 }
1553
1554 func cmdTlsKdf12Aft(h func() hash.Hash) command {
1555 return command{
1556 requiredArgs: 5,
1557 handler: func(args [][]byte) ([][]byte, error) {
1558 outputLen := binary.LittleEndian.Uint32(args[0])
1559 secret := args[1]
1560 label := string(args[2])
1561 seed1 := args[3]
1562 seed2 := args[4]
1563
1564 return [][]byte{tls12.PRF(h, secret, label, append(seed1, seed2...), int(outputLen))}, nil
1565 },
1566 }
1567 }
1568
1569 func cmdSshKdfAft(hFunc func() hash.Hash, direction ssh.Direction) command {
1570 return command{
1571 requiredArgs: 4,
1572 handler: func(args [][]byte) ([][]byte, error) {
1573 k := args[0]
1574 h := args[1]
1575 sessionID := args[2]
1576 cipher := string(args[3])
1577
1578 var keyLen int
1579 switch cipher {
1580 case "AES-128":
1581 keyLen = 16
1582 case "AES-192":
1583 keyLen = 24
1584 case "AES-256":
1585 keyLen = 32
1586 default:
1587 return nil, fmt.Errorf("unsupported cipher: %q", cipher)
1588 }
1589
1590 ivKey, encKey, intKey := ssh.Keys(hFunc, direction, k, h, sessionID, 16, keyLen, hFunc().Size())
1591 return [][]byte{ivKey, encKey, intKey}, nil
1592 },
1593 }
1594 }
1595
1596 func cmdEcdhAftVal[P ecdh.Point[P]](curve *ecdh.Curve[P]) command {
1597 return command{
1598 requiredArgs: 3,
1599 handler: func(args [][]byte) ([][]byte, error) {
1600 peerX := args[0]
1601 peerY := args[1]
1602 rawSk := args[2]
1603
1604 uncompressedPk := append([]byte{4}, append(peerX, peerY...)...)
1605 pk, err := ecdh.NewPublicKey(curve, uncompressedPk)
1606 if err != nil {
1607 return nil, fmt.Errorf("invalid peer public key x,y: %v", err)
1608 }
1609
1610 var sk *ecdh.PrivateKey
1611 if len(rawSk) > 0 {
1612 sk, err = ecdh.NewPrivateKey(curve, rawSk)
1613 } else {
1614 sk, err = ecdh.GenerateKey(curve, rand.Reader)
1615 }
1616 if err != nil {
1617 return nil, fmt.Errorf("private key error: %v", err)
1618 }
1619
1620 pubBytes := sk.PublicKey().Bytes()
1621 coordLen := (len(pubBytes) - 1) / 2
1622 x := pubBytes[1 : 1+coordLen]
1623 y := pubBytes[1+coordLen:]
1624
1625 secret, err := ecdh.ECDH(curve, sk, pk)
1626 if err != nil {
1627 return nil, fmt.Errorf("key agreement failed: %v", err)
1628 }
1629
1630 return [][]byte{x, y, secret}, nil
1631 },
1632 }
1633 }
1634
1635 func cmdHmacDrbgAft(h func() hash.Hash) command {
1636 return command{
1637 requiredArgs: 6,
1638 handler: func(args [][]byte) ([][]byte, error) {
1639 outLen := binary.LittleEndian.Uint32(args[0])
1640 entropy := args[1]
1641 personalization := args[2]
1642 ad1 := args[3]
1643 ad2 := args[4]
1644 nonce := args[5]
1645
1646
1647 if len(ad1) != 0 || len(ad2) != 0 {
1648 return nil, errors.New("additional data not supported")
1649 }
1650
1651
1652
1653
1654
1655
1656
1657
1658 out := make([]byte, outLen)
1659 drbg := ecdsa.TestingOnlyNewDRBG(h, entropy, nonce, personalization)
1660 drbg.Generate(out)
1661 drbg.Generate(out)
1662
1663 return [][]byte{out}, nil
1664 },
1665 }
1666 }
1667
1668 func cmdCtrDrbgAft() command {
1669 return command{
1670 requiredArgs: 6,
1671 handler: func(args [][]byte) ([][]byte, error) {
1672 return acvpCtrDrbg{
1673 outLen: binary.LittleEndian.Uint32(args[0]),
1674 entropy: args[1],
1675 personalization: args[2],
1676 ad1: args[3],
1677 ad2: args[4],
1678 nonce: args[5],
1679 }.process()
1680 },
1681 }
1682 }
1683
1684 func cmdCtrDrbgReseedAft() command {
1685 return command{
1686 requiredArgs: 8,
1687 handler: func(args [][]byte) ([][]byte, error) {
1688 return acvpCtrDrbg{
1689 outLen: binary.LittleEndian.Uint32(args[0]),
1690 entropy: args[1],
1691 personalization: args[2],
1692 reseedAd: args[3],
1693 reseedEntropy: args[4],
1694 ad1: args[5],
1695 ad2: args[6],
1696 nonce: args[7],
1697 }.process()
1698 },
1699 }
1700 }
1701
1702 type acvpCtrDrbg struct {
1703 outLen uint32
1704 entropy []byte
1705 personalization []byte
1706 ad1 []byte
1707 ad2 []byte
1708 nonce []byte
1709 reseedAd []byte
1710 reseedEntropy []byte
1711 }
1712
1713 func (args acvpCtrDrbg) process() ([][]byte, error) {
1714
1715 if len(args.personalization) > 0 {
1716 return nil, errors.New("personalization string not supported")
1717 }
1718
1719
1720
1721 if len(args.nonce) > 0 {
1722 return nil, errors.New("unexpected nonce value")
1723 }
1724
1725
1726 entropy, err := require48Bytes(args.entropy)
1727 if err != nil {
1728 return nil, fmt.Errorf("entropy: %w", err)
1729 }
1730
1731
1732 ad1, err := require48Bytes(args.ad1)
1733 if err != nil {
1734 return nil, fmt.Errorf("AD1: %w", err)
1735 }
1736 ad2, err := require48Bytes(args.ad2)
1737 if err != nil {
1738 return nil, fmt.Errorf("AD2: %w", err)
1739 }
1740
1741 withReseed := len(args.reseedAd) > 0
1742 var reseedAd, reseedEntropy *[48]byte
1743 if withReseed {
1744
1745 if reseedAd, err = require48Bytes(args.reseedAd); err != nil {
1746 return nil, fmt.Errorf("reseed AD: %w", err)
1747 }
1748 if reseedEntropy, err = require48Bytes(args.reseedEntropy); err != nil {
1749 return nil, fmt.Errorf("reseed entropy: %w", err)
1750 }
1751 }
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761 out := make([]byte, args.outLen)
1762 ctrDrbg := drbg.NewCounter(entropy)
1763 if withReseed {
1764 ctrDrbg.Reseed(reseedEntropy, reseedAd)
1765 }
1766 ctrDrbg.Generate(out, ad1)
1767 ctrDrbg.Generate(out, ad2)
1768
1769 return [][]byte{out}, nil
1770 }
1771
1772
1773
1774 func require48Bytes(input []byte) (*[48]byte, error) {
1775 if inputLen := len(input); inputLen != 48 {
1776 return nil, fmt.Errorf("invalid length: %d", inputLen)
1777 }
1778 return (*[48]byte)(input), nil
1779 }
1780
1781 func cmdKdfCounterAft() command {
1782 return command{
1783 requiredArgs: 5,
1784 handler: func(args [][]byte) ([][]byte, error) {
1785 outputBytes := binary.LittleEndian.Uint32(args[0])
1786 prf := args[1]
1787 counterLocation := args[2]
1788 key := args[3]
1789 counterBits := binary.LittleEndian.Uint32(args[4])
1790
1791 if outputBytes != 32 {
1792 return nil, fmt.Errorf("KDF received unsupported output length %d bytes", outputBytes)
1793 }
1794 if !bytes.Equal(prf, []byte("CMAC-AES128")) && !bytes.Equal(prf, []byte("CMAC-AES192")) && !bytes.Equal(prf, []byte("CMAC-AES256")) {
1795 return nil, fmt.Errorf("KDF received unsupported PRF %q", string(prf))
1796 }
1797 if !bytes.Equal(counterLocation, []byte("before fixed data")) {
1798 return nil, fmt.Errorf("KDF received unsupported counter location %q", string(counterLocation))
1799 }
1800
1801
1802
1803
1804 if len(key) == 0 {
1805 return nil, errors.New("deferred test cases are not supported")
1806 }
1807 if counterBits != 16 {
1808 return nil, fmt.Errorf("KDF received unsupported counter length %d", counterBits)
1809 }
1810
1811 block, err := aes.New(key)
1812 if err != nil {
1813 return nil, fmt.Errorf("failed to create cipher: %v", err)
1814 }
1815 kdf := gcm.NewCounterKDF(block)
1816
1817 var label byte
1818 var context [12]byte
1819 rand.Reader.Read(context[:])
1820
1821 result := kdf.DeriveKey(label, context)
1822
1823 fixedData := make([]byte, 1+1+12)
1824 fixedData[0] = label
1825 copy(fixedData[2:], context[:])
1826
1827 return [][]byte{key, fixedData, result[:]}, nil
1828 },
1829 }
1830 }
1831
1832 func cmdKdfFeedbackAft() command {
1833 return command{
1834 requiredArgs: 5,
1835 handler: func(args [][]byte) ([][]byte, error) {
1836
1837
1838
1839 outputBytes := int(binary.LittleEndian.Uint32(args[0]))
1840 prf := string(args[1])
1841 counterLocation := args[2]
1842 key := args[3]
1843 counterBits := binary.LittleEndian.Uint32(args[4])
1844
1845 if !strings.HasPrefix(prf, "HMAC-") {
1846 return nil, fmt.Errorf("feedback KDF received unsupported PRF %q", prf)
1847 }
1848 prf = prf[len("HMAC-"):]
1849
1850 h, err := lookupHash(prf)
1851 if err != nil {
1852 return nil, fmt.Errorf("feedback KDF received unsupported PRF %q: %w", prf, err)
1853 }
1854
1855 if !bytes.Equal(counterLocation, []byte("after fixed data")) {
1856 return nil, fmt.Errorf("feedback KDF received unsupported counter location %q", string(counterLocation))
1857 }
1858
1859
1860
1861
1862
1863 if len(key) == 0 {
1864 return nil, errors.New("deferred test cases are not supported")
1865 }
1866
1867 if counterBits != 8 {
1868 return nil, fmt.Errorf("feedback KDF received unsupported counter length %d", counterBits)
1869 }
1870
1871 var context [12]byte
1872 rand.Reader.Read(context[:])
1873 fixedData := make([]byte, 1+1+12)
1874 copy(fixedData[2:], context[:])
1875
1876 result := hkdf.Expand(h, key, string(fixedData[:]), outputBytes)
1877
1878 return [][]byte{key, fixedData[:], result[:]}, nil
1879 },
1880 }
1881 }
1882
1883 func cmdRsaKeyGenAft() command {
1884 return command{
1885 requiredArgs: 1,
1886 handler: func(args [][]byte) ([][]byte, error) {
1887 bitSize := binary.LittleEndian.Uint32(args[0])
1888
1889 key, err := getRSAKey((int)(bitSize))
1890 if err != nil {
1891 return nil, fmt.Errorf("generating RSA key: %w", err)
1892 }
1893
1894 N, e, d, P, Q, _, _, _ := key.Export()
1895
1896 eBytes := make([]byte, 4)
1897 binary.BigEndian.PutUint32(eBytes, uint32(e))
1898
1899 return [][]byte{eBytes, P, Q, N, d}, nil
1900 },
1901 }
1902 }
1903
1904 func cmdRsaSigGenAft(hashFunc func() hash.Hash, hashName string, pss bool) command {
1905 return command{
1906 requiredArgs: 2,
1907 handler: func(args [][]byte) ([][]byte, error) {
1908 bitSize := binary.LittleEndian.Uint32(args[0])
1909 msg := args[1]
1910
1911 key, err := getRSAKey((int)(bitSize))
1912 if err != nil {
1913 return nil, fmt.Errorf("generating RSA key: %w", err)
1914 }
1915
1916 h := hashFunc()
1917 h.Write(msg)
1918 digest := h.Sum(nil)
1919
1920 var sig []byte
1921 if !pss {
1922 sig, err = rsa.SignPKCS1v15(key, hashName, digest)
1923 if err != nil {
1924 return nil, fmt.Errorf("signing RSA message: %w", err)
1925 }
1926 } else {
1927 sig, err = rsa.SignPSS(rand.Reader, key, hashFunc(), digest, h.Size())
1928 if err != nil {
1929 return nil, fmt.Errorf("signing RSA message: %w", err)
1930 }
1931 }
1932
1933 N, e, _, _, _, _, _, _ := key.Export()
1934 eBytes := make([]byte, 4)
1935 binary.BigEndian.PutUint32(eBytes, uint32(e))
1936
1937 return [][]byte{N, eBytes, sig}, nil
1938 },
1939 }
1940 }
1941
1942 func cmdRsaSigVerAft(hashFunc func() hash.Hash, hashName string, pss bool) command {
1943 return command{
1944 requiredArgs: 4,
1945 handler: func(args [][]byte) ([][]byte, error) {
1946 nBytes := args[0]
1947 eBytes := args[1]
1948 msg := args[2]
1949 sig := args[3]
1950
1951 paddedE := make([]byte, 4)
1952 copy(paddedE[4-len(eBytes):], eBytes)
1953 e := int(binary.BigEndian.Uint32(paddedE))
1954
1955 n, err := bigmod.NewModulus(nBytes)
1956 if err != nil {
1957 return nil, fmt.Errorf("invalid RSA modulus: %w", err)
1958 }
1959
1960 pub := &rsa.PublicKey{
1961 N: n,
1962 E: e,
1963 }
1964
1965 h := hashFunc()
1966 h.Write(msg)
1967 digest := h.Sum(nil)
1968
1969 if !pss {
1970 err = rsa.VerifyPKCS1v15(pub, hashName, digest, sig)
1971 } else {
1972 err = rsa.VerifyPSS(pub, hashFunc(), digest, sig)
1973 }
1974 if err != nil {
1975 return [][]byte{{0}}, nil
1976 }
1977
1978 return [][]byte{{1}}, nil
1979 },
1980 }
1981 }
1982
1983
1984 var rsaKeyCache = map[int]*rsa.PrivateKey{}
1985
1986
1987
1988 func getRSAKey(bits int) (*rsa.PrivateKey, error) {
1989 if key, exists := rsaKeyCache[bits]; exists {
1990 return key, nil
1991 }
1992
1993 key, err := rsa.GenerateKey(rand.Reader, bits)
1994 if err != nil {
1995 return nil, err
1996 }
1997
1998 rsaKeyCache[bits] = key
1999 return key, nil
2000 }
2001
2002 func cmdOneStepNoCounterHmacAft(h func() hash.Hash) command {
2003 return command{
2004 requiredArgs: 4,
2005 handler: func(args [][]byte) ([][]byte, error) {
2006 key := args[0]
2007 info := args[1]
2008 salt := args[2]
2009 outBytes := binary.LittleEndian.Uint32(args[3])
2010
2011 mac := hmac.New(h, salt)
2012 mac.Size()
2013
2014 if outBytes != uint32(mac.Size()) {
2015 return nil, fmt.Errorf("invalid output length: got %d, want %d", outBytes, mac.Size())
2016 }
2017
2018 data := make([]byte, 0, len(key)+len(info))
2019 data = append(data, key...)
2020 data = append(data, info...)
2021
2022 mac.Write(data)
2023 out := mac.Sum(nil)
2024
2025 return [][]byte{out}, nil
2026 },
2027 }
2028 }
2029
2030 func cmdKtsIfcInitiatorAft(h func() hash.Hash) command {
2031 return command{
2032 requiredArgs: 3,
2033 handler: func(args [][]byte) ([][]byte, error) {
2034 outputBytes := binary.LittleEndian.Uint32(args[0])
2035 nBytes := args[1]
2036 eBytes := args[2]
2037
2038 n, err := bigmod.NewModulus(nBytes)
2039 if err != nil {
2040 return nil, fmt.Errorf("invalid RSA modulus: %w", err)
2041 }
2042
2043 paddedE := make([]byte, 4)
2044 copy(paddedE[4-len(eBytes):], eBytes)
2045 e := int(binary.BigEndian.Uint32(paddedE))
2046 if e != 0x10001 {
2047 return nil, errors.New("e must be 0x10001")
2048 }
2049
2050 pub := &rsa.PublicKey{
2051 N: n,
2052 E: e,
2053 }
2054
2055 dkm := make([]byte, outputBytes)
2056 if _, err := rand.Read(dkm); err != nil {
2057 return nil, fmt.Errorf("failed to generate random DKM: %v", err)
2058 }
2059
2060 iutC, err := rsa.EncryptOAEP(h(), h(), rand.Reader, pub, dkm, nil)
2061 if err != nil {
2062 return nil, fmt.Errorf("OAEP encryption failed: %v", err)
2063 }
2064
2065 return [][]byte{iutC, dkm}, nil
2066 },
2067 }
2068 }
2069
2070 func cmdKtsIfcResponderAft(h func() hash.Hash) command {
2071 return command{
2072 requiredArgs: 6,
2073 handler: func(args [][]byte) ([][]byte, error) {
2074 nBytes := args[0]
2075 eBytes := args[1]
2076
2077 pBytes := args[2]
2078 qBytes := args[3]
2079 dBytes := args[4]
2080
2081 cBytes := args[5]
2082
2083 paddedE := make([]byte, 4)
2084 copy(paddedE[4-len(eBytes):], eBytes)
2085 e := int(binary.BigEndian.Uint32(paddedE))
2086 if e != 0x10001 {
2087 return nil, errors.New("e must be 0x10001")
2088 }
2089
2090 priv, err := rsa.NewPrivateKey(nBytes, int(e), dBytes, pBytes, qBytes)
2091 if err != nil {
2092 return nil, fmt.Errorf("failed to create private key: %v", err)
2093 }
2094
2095 dkm, err := rsa.DecryptOAEP(h(), h(), priv, cBytes, nil)
2096 if err != nil {
2097 return nil, fmt.Errorf("OAEP decryption failed: %v", err)
2098 }
2099
2100 return [][]byte{dkm}, nil
2101 },
2102 }
2103 }
2104
2105 func TestACVP(t *testing.T) {
2106 testenv.SkipIfShortAndSlow(t)
2107
2108 const (
2109 bsslModule = "boringssl.googlesource.com/boringssl.git"
2110 bsslVersion = "v0.0.0-20251111011041-baaf868e6e8f"
2111 goAcvpModule = "github.com/geomys/acvp-testdata"
2112 goAcvpVersion = "v0.0.0-20251201200548-d893de8b8b1c"
2113 )
2114
2115
2116
2117
2118
2119
2120 if _, err := os.Stat(testConfigFile); err != nil {
2121 t.Fatalf("failed to stat config file: %s", err)
2122 }
2123
2124
2125 bsslDir := cryptotest.FetchModule(t, bsslModule, bsslVersion)
2126
2127 t.Log("building acvptool")
2128
2129
2130 toolPath := filepath.Join(t.TempDir(), "acvptool.exe")
2131 cmd := testenv.Command(t, testenv.GoToolPath(t),
2132 "build",
2133 "-o", toolPath,
2134 "./util/fipstools/acvp/acvptool")
2135 cmd.Dir = bsslDir
2136 if out, err := cmd.CombinedOutput(); err != nil {
2137 t.Fatalf("failed to build acvptool: %s\n%s", err, out)
2138 }
2139
2140
2141 dataDir := cryptotest.FetchModule(t, goAcvpModule, goAcvpVersion)
2142
2143 cwd, err := os.Getwd()
2144 if err != nil {
2145 t.Fatalf("failed to fetch cwd: %s", err)
2146 }
2147 configPath := filepath.Join(cwd, testConfigFile)
2148 t.Logf("running check_expected.go\ncwd: %q\ndata_dir: %q\nconfig: %q\ntool: %q\nmodule-wrapper: %q\n",
2149 cwd, dataDir, configPath, toolPath, os.Args[0])
2150
2151
2152
2153
2154 args := []string{
2155 "run",
2156 filepath.Join(bsslDir, "util/fipstools/acvp/acvptool/test/check_expected.go"),
2157 "-tool",
2158 toolPath,
2159
2160 "-module-wrappers", "go:" + os.Args[0],
2161 "-tests", configPath,
2162 }
2163 cmd = testenv.Command(t, testenv.GoToolPath(t), args...)
2164 cmd.Dir = dataDir
2165 cmd.Env = append(os.Environ(),
2166 "ACVP_WRAPPER=1",
2167 "GODEBUG=fips140=on",
2168 )
2169 out, err := cmd.CombinedOutput()
2170 t.Logf("\n%s", out)
2171 if err != nil {
2172 t.Fatalf("failed to run acvp tests: %s", err)
2173 }
2174 }
2175
2176 func TestTooFewArgs(t *testing.T) {
2177 commands["test"] = command{
2178 requiredArgs: 1,
2179 handler: func(args [][]byte) ([][]byte, error) {
2180 if gotArgs := len(args); gotArgs != 1 {
2181 return nil, fmt.Errorf("expected 1 args, got %d", gotArgs)
2182 }
2183 return nil, nil
2184 },
2185 }
2186
2187 var output bytes.Buffer
2188 err := processingLoop(mockRequest(t, "test", nil), &output)
2189 if err == nil {
2190 t.Fatalf("expected error, got nil")
2191 }
2192 expectedErr := "expected 1 args, got 0"
2193 if !strings.Contains(err.Error(), expectedErr) {
2194 t.Errorf("expected error to contain %q, got %v", expectedErr, err)
2195 }
2196 }
2197
2198 func TestTooManyArgs(t *testing.T) {
2199 commands["test"] = command{
2200 requiredArgs: 1,
2201 handler: func(args [][]byte) ([][]byte, error) {
2202 if gotArgs := len(args); gotArgs != 1 {
2203 return nil, fmt.Errorf("expected 1 args, got %d", gotArgs)
2204 }
2205 return nil, nil
2206 },
2207 }
2208
2209 var output bytes.Buffer
2210 err := processingLoop(mockRequest(
2211 t, "test", [][]byte{[]byte("one"), []byte("two")}), &output)
2212 if err == nil {
2213 t.Fatalf("expected error, got nil")
2214 }
2215 expectedErr := "expected 1 args, got 2"
2216 if !strings.Contains(err.Error(), expectedErr) {
2217 t.Errorf("expected error to contain %q, got %v", expectedErr, err)
2218 }
2219 }
2220
2221 func TestGetConfig(t *testing.T) {
2222 var output bytes.Buffer
2223 err := processingLoop(mockRequest(t, "getConfig", nil), &output)
2224 if err != nil {
2225 t.Errorf("unexpected error: %v", err)
2226 }
2227
2228 respArgs := readResponse(t, &output)
2229 if len(respArgs) != 1 {
2230 t.Fatalf("expected 1 response arg, got %d", len(respArgs))
2231 }
2232
2233 if !bytes.Equal(respArgs[0], capabilitiesJson) {
2234 t.Errorf("expected config %q, got %q", string(capabilitiesJson), string(respArgs[0]))
2235 }
2236 }
2237
2238 func TestSha2256(t *testing.T) {
2239 testMessage := []byte("gophers eat grass")
2240 expectedDigest := []byte{
2241 188, 142, 10, 214, 48, 236, 72, 143, 70, 216, 223, 205, 219, 69, 53, 29,
2242 205, 207, 162, 6, 14, 70, 113, 60, 251, 170, 201, 236, 119, 39, 141, 172,
2243 }
2244
2245 var output bytes.Buffer
2246 err := processingLoop(mockRequest(t, "SHA2-256", [][]byte{testMessage}), &output)
2247 if err != nil {
2248 t.Errorf("unexpected error: %v", err)
2249 }
2250
2251 respArgs := readResponse(t, &output)
2252 if len(respArgs) != 1 {
2253 t.Fatalf("expected 1 response arg, got %d", len(respArgs))
2254 }
2255
2256 if !bytes.Equal(respArgs[0], expectedDigest) {
2257 t.Errorf("expected digest %v, got %v", expectedDigest, respArgs[0])
2258 }
2259 }
2260
2261 func mockRequest(t *testing.T, cmd string, args [][]byte) io.Reader {
2262 t.Helper()
2263
2264 msgData := append([][]byte{[]byte(cmd)}, args...)
2265
2266 var buf bytes.Buffer
2267 if err := writeResponse(&buf, msgData); err != nil {
2268 t.Fatalf("writeResponse error: %v", err)
2269 }
2270
2271 return &buf
2272 }
2273
2274 func readResponse(t *testing.T, reader io.Reader) [][]byte {
2275 var numArgs uint32
2276 if err := binary.Read(reader, binary.LittleEndian, &numArgs); err != nil {
2277 t.Fatalf("failed to read response args count: %v", err)
2278 }
2279
2280 args, err := readArgs(reader, numArgs)
2281 if err != nil {
2282 t.Fatalf("failed to read %d response args: %v", numArgs, err)
2283 }
2284
2285 return args
2286 }
2287
View as plain text