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