@@ -24,6 +24,8 @@ import (
24
24
"crypto/internal/cryptotest"
25
25
"crypto/internal/fips140"
26
26
"crypto/internal/fips140/ecdsa"
27
+ "crypto/internal/fips140/ed25519"
28
+ "crypto/internal/fips140/edwards25519"
27
29
"crypto/internal/fips140/hmac"
28
30
"crypto/internal/fips140/mlkem"
29
31
"crypto/internal/fips140/pbkdf2"
81
83
// https://pages.nist.gov/ACVP/draft-celi-acvp-ml-kem.html#section-7.3
82
84
// HMAC DRBG algorithm capabilities:
83
85
// https://pages.nist.gov/ACVP/draft-vassilev-acvp-drbg.html#section-7.2
86
+ // EDDSA algorithm capabilities:
87
+ // https://pages.nist.gov/ACVP/draft-celi-acvp-eddsa.html#section-7
84
88
//go:embed acvp_capabilities.json
85
89
capabilitiesJson []byte
86
90
@@ -142,6 +146,11 @@ var (
142
146
"hmacDRBG/SHA3-256" : cmdHmacDrbgAft (func () fips140.Hash { return sha3 .New256 () }),
143
147
"hmacDRBG/SHA3-384" : cmdHmacDrbgAft (func () fips140.Hash { return sha3 .New384 () }),
144
148
"hmacDRBG/SHA3-512" : cmdHmacDrbgAft (func () fips140.Hash { return sha3 .New512 () }),
149
+
150
+ "EDDSA/keyGen" : cmdEddsaKeyGenAft (),
151
+ "EDDSA/keyVer" : cmdEddsaKeyVerAft (),
152
+ "EDDSA/sigGen" : cmdEddsaSigGenAftBft (),
153
+ "EDDSA/sigVer" : cmdEddsaSigVerAft (),
145
154
}
146
155
)
147
156
@@ -397,6 +406,126 @@ func cmdPbkdf() command {
397
406
}
398
407
}
399
408
409
+ func cmdEddsaKeyGenAft () command {
410
+ return command {
411
+ requiredArgs : 1 , // Curve name
412
+ handler : func (args [][]byte ) ([][]byte , error ) {
413
+ if string (args [0 ]) != "ED-25519" {
414
+ return nil , fmt .Errorf ("unsupported EDDSA curve: %q" , args [0 ])
415
+ }
416
+
417
+ sk , err := ed25519 .GenerateKey ()
418
+ if err != nil {
419
+ return nil , fmt .Errorf ("generating EDDSA keypair: %w" , err )
420
+ }
421
+
422
+ // EDDSA/keyGen/AFT responses are d & q, described[0] as:
423
+ // d The encoded private key point
424
+ // q The encoded public key point
425
+ //
426
+ // Contrary to the description of a "point", d is the private key
427
+ // seed bytes per FIPS.186-5[1] A.2.3.
428
+ //
429
+ // [0]: https://pages.nist.gov/ACVP/draft-celi-acvp-eddsa.html#section-9.1
430
+ // [1]: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-5.pdf
431
+ return [][]byte {sk .Seed (), sk .PublicKey ()}, nil
432
+ },
433
+ }
434
+ }
435
+
436
+ func cmdEddsaKeyVerAft () command {
437
+ return command {
438
+ requiredArgs : 2 , // Curve name, Q
439
+ handler : func (args [][]byte ) ([][]byte , error ) {
440
+ if string (args [0 ]) != "ED-25519" {
441
+ return nil , fmt .Errorf ("unsupported EDDSA curve: %q" , args [0 ])
442
+ }
443
+
444
+ // Verify the point is on the curve. The higher-level ed25519 API does
445
+ // this at signature verification time so we have to use the lower-level
446
+ // edwards25519 package to do it here in absence of a signature to verify.
447
+ if _ , err := new (edwards25519.Point ).SetBytes (args [1 ]); err != nil {
448
+ return [][]byte {{0 }}, nil
449
+ }
450
+
451
+ return [][]byte {{1 }}, nil
452
+ },
453
+ }
454
+ }
455
+
456
+ func cmdEddsaSigGenAftBft () command {
457
+ return command {
458
+ requiredArgs : 5 , // Curve name, private key seed, message, prehash, context
459
+ handler : func (args [][]byte ) ([][]byte , error ) {
460
+ if string (args [0 ]) != "ED-25519" {
461
+ return nil , fmt .Errorf ("unsupported EDDSA curve: %q" , args [0 ])
462
+ }
463
+
464
+ sk , err := ed25519 .NewPrivateKeyFromSeed (args [1 ])
465
+ if err != nil {
466
+ return nil , fmt .Errorf ("error creating private key: %w" , err )
467
+ }
468
+ msg := args [2 ]
469
+ prehash := args [3 ]
470
+ context := string (args [4 ])
471
+
472
+ var sig []byte
473
+ if prehash [0 ] == 1 {
474
+ h := sha512 .New ()
475
+ h .Write (msg )
476
+ msg = h .Sum (nil )
477
+
478
+ // With ed25519 the context is only specified for sigGen tests when using prehashing.
479
+ // See https://pages.nist.gov/ACVP/draft-celi-acvp-eddsa.html#section-8.6
480
+ sig , err = ed25519 .SignPH (sk , msg , context )
481
+ if err != nil {
482
+ return nil , fmt .Errorf ("error signing message: %w" , err )
483
+ }
484
+ } else {
485
+ sig = ed25519 .Sign (sk , msg )
486
+ }
487
+
488
+ return [][]byte {sig }, nil
489
+ },
490
+ }
491
+ }
492
+
493
+ func cmdEddsaSigVerAft () command {
494
+ return command {
495
+ requiredArgs : 5 , // Curve name, message, public key, signature, prehash
496
+ handler : func (args [][]byte ) ([][]byte , error ) {
497
+ if string (args [0 ]) != "ED-25519" {
498
+ return nil , fmt .Errorf ("unsupported EDDSA curve: %q" , args [0 ])
499
+ }
500
+
501
+ msg := args [1 ]
502
+ pk , err := ed25519 .NewPublicKey (args [2 ])
503
+ if err != nil {
504
+ return nil , fmt .Errorf ("invalid public key: %w" , err )
505
+ }
506
+ sig := args [3 ]
507
+ prehash := args [4 ]
508
+
509
+ if prehash [0 ] == 1 {
510
+ h := sha512 .New ()
511
+ h .Write (msg )
512
+ msg = h .Sum (nil )
513
+ // Context is only specified for sigGen, not sigVer.
514
+ // See https://pages.nist.gov/ACVP/draft-celi-acvp-eddsa.html#section-8.6
515
+ err = ed25519 .VerifyPH (pk , msg , sig , "" )
516
+ } else {
517
+ err = ed25519 .Verify (pk , msg , sig )
518
+ }
519
+
520
+ if err != nil {
521
+ return [][]byte {{0 }}, nil
522
+ }
523
+
524
+ return [][]byte {{1 }}, nil
525
+ },
526
+ }
527
+ }
528
+
400
529
func lookupHash (name string ) (func () fips140.Hash , error ) {
401
530
var h func () fips140.Hash
402
531
0 commit comments