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