Skip to content

Commit ee8db08

Browse files
cpugopherbot
authored andcommitted
crypto/internal/fips140test: add KAS-ECC-SSC ACVP tests
Adds ACVP test coverage for the Sp800-56Ar3 KAS-ECC-SSC algorithm based on the NIST spec: https://pages.nist.gov/ACVP/draft-hammett-acvp-kas-ssc-ecc.html There's no acvp_test.config.json update for this algorithm as one test type type requires random key generation and can't be separated from the test type that doesn't, making it a bad fit for static data testing. Updates #69642 Change-Id: I3b6538fad1c1e5c8b14b638ff3b933f11e98f75a Reviewed-on: https://go-review.googlesource.com/c/go/+/637916 Reviewed-by: Roland Shoemaker <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> Auto-Submit: Filippo Valsorda <[email protected]> Reviewed-by: Filippo Valsorda <[email protected]> Reviewed-by: Dmitri Shuralyov <[email protected]>
1 parent 86aca87 commit ee8db08

File tree

2 files changed

+50
-1
lines changed

2 files changed

+50
-1
lines changed

src/crypto/internal/fips140test/acvp_capabilities.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,5 +63,7 @@
6363

6464
{"algorithm":"TLS-v1.2","mode":"KDF","revision":"RFC7627","hashAlg":["SHA2-256","SHA2-384","SHA2-512"]},
6565
{"algorithm":"TLS-v1.3","mode":"KDF","revision":"RFC8446","hmacAlg":["SHA2-256","SHA2-384"],"runningMode":["DHE","PSK","PSK-DHE"]},
66-
{"algorithm":"kdf-components","mode":"ssh","revision":"1.0","hashAlg":["SHA2-224","SHA2-256","SHA2-384","SHA2-512"],"cipher":["AES-128","AES-192","AES-256"]}
66+
{"algorithm":"kdf-components","mode":"ssh","revision":"1.0","hashAlg":["SHA2-224","SHA2-256","SHA2-384","SHA2-512"],"cipher":["AES-128","AES-192","AES-256"]},
67+
68+
{"algorithm":"KAS-ECC-SSC","revision":"Sp800-56Ar3","scheme":{"ephemeralUnified":{"kasRole":["initiator","responder"]},"staticUnified":{"kasRole":["initiator","responder"]}},"domainParameterGenerationMethods":["P-224","P-256","P-384","P-521"]}
6769
]

src/crypto/internal/fips140test/acvp_test.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"crypto/internal/fips140"
2727
"crypto/internal/fips140/aes"
2828
"crypto/internal/fips140/aes/gcm"
29+
"crypto/internal/fips140/ecdh"
2930
"crypto/internal/fips140/ecdsa"
3031
"crypto/internal/fips140/ed25519"
3132
"crypto/internal/fips140/edwards25519"
@@ -123,6 +124,8 @@ var (
123124
// https://pages.nist.gov/ACVP/draft-hammett-acvp-kdf-tls-v1.3.html#section-7.2
124125
// SSH KDF algorithm capabilities:
125126
// https://pages.nist.gov/ACVP/draft-celi-acvp-kdf-ssh.html#section-7.2
127+
// ECDH algorithm capabilities:
128+
// https://pages.nist.gov/ACVP/draft-hammett-acvp-kas-ssc-ecc.html
126129
//go:embed acvp_capabilities.json
127130
capabilitiesJson []byte
128131

@@ -251,6 +254,11 @@ var (
251254
"SSHKDF/SHA2-384/server": cmdSshKdfAft(func() fips140.Hash { return sha512.New384() }, ssh.ServerKeys),
252255
"SSHKDF/SHA2-512/client": cmdSshKdfAft(func() fips140.Hash { return sha512.New() }, ssh.ClientKeys),
253256
"SSHKDF/SHA2-512/server": cmdSshKdfAft(func() fips140.Hash { return sha512.New() }, ssh.ServerKeys),
257+
258+
"ECDH/P-224": cmdEcdhAftVal(ecdh.P224()),
259+
"ECDH/P-256": cmdEcdhAftVal(ecdh.P256()),
260+
"ECDH/P-384": cmdEcdhAftVal(ecdh.P384()),
261+
"ECDH/P-521": cmdEcdhAftVal(ecdh.P521()),
254262
}
255263
)
256264

@@ -1413,6 +1421,45 @@ func cmdSshKdfAft(hFunc func() fips140.Hash, direction ssh.Direction) command {
14131421
}
14141422
}
14151423

1424+
func cmdEcdhAftVal[P ecdh.Point[P]](curve *ecdh.Curve[P]) command {
1425+
return command{
1426+
requiredArgs: 3, // X, Y, private key (empty for Val type tests)
1427+
handler: func(args [][]byte) ([][]byte, error) {
1428+
peerX := args[0]
1429+
peerY := args[1]
1430+
rawSk := args[2]
1431+
1432+
uncompressedPk := append([]byte{4}, append(peerX, peerY...)...) // 4 for uncompressed point format
1433+
pk, err := ecdh.NewPublicKey(curve, uncompressedPk)
1434+
if err != nil {
1435+
return nil, fmt.Errorf("invalid peer public key x,y: %v", err)
1436+
}
1437+
1438+
var sk *ecdh.PrivateKey
1439+
if len(rawSk) > 0 {
1440+
sk, err = ecdh.NewPrivateKey(curve, rawSk)
1441+
} else {
1442+
sk, err = ecdh.GenerateKey(curve, rand.Reader)
1443+
}
1444+
if err != nil {
1445+
return nil, fmt.Errorf("private key error: %v", err)
1446+
}
1447+
1448+
pubBytes := sk.PublicKey().Bytes()
1449+
coordLen := (len(pubBytes) - 1) / 2
1450+
x := pubBytes[1 : 1+coordLen]
1451+
y := pubBytes[1+coordLen:]
1452+
1453+
secret, err := ecdh.ECDH(curve, sk, pk)
1454+
if err != nil {
1455+
return nil, fmt.Errorf("key agreement failed: %v", err)
1456+
}
1457+
1458+
return [][]byte{x, y, secret}, nil
1459+
},
1460+
}
1461+
}
1462+
14161463
func TestACVP(t *testing.T) {
14171464
testenv.SkipIfShortAndSlow(t)
14181465

0 commit comments

Comments
 (0)