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