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