aboutsummaryrefslogtreecommitdiff
path: root/src/crypto/internal
diff options
context:
space:
mode:
authorDaniel McCarney <daniel@binaryparadox.net>2024-12-19 14:02:05 -0500
committerGopher Robot <gobot@golang.org>2025-02-10 13:29:42 -0800
commitee8db080c8ca99bae0288f4cf19110cdfb179e35 (patch)
tree997151c20478078758959015cc0bfb944f01f030 /src/crypto/internal
parent86aca8778871c02eae6a7c4164ef1f004cd72814 (diff)
downloadgo-ee8db080c8ca99bae0288f4cf19110cdfb179e35.tar.xz
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 <roland@golang.org> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Auto-Submit: Filippo Valsorda <filippo@golang.org> Reviewed-by: Filippo Valsorda <filippo@golang.org> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Diffstat (limited to 'src/crypto/internal')
-rw-r--r--src/crypto/internal/fips140test/acvp_capabilities.json4
-rw-r--r--src/crypto/internal/fips140test/acvp_test.go47
2 files changed, 50 insertions, 1 deletions
diff --git a/src/crypto/internal/fips140test/acvp_capabilities.json b/src/crypto/internal/fips140test/acvp_capabilities.json
index 02940a2e6f..5b31850087 100644
--- a/src/crypto/internal/fips140test/acvp_capabilities.json
+++ b/src/crypto/internal/fips140test/acvp_capabilities.json
@@ -63,5 +63,7 @@
{"algorithm":"TLS-v1.2","mode":"KDF","revision":"RFC7627","hashAlg":["SHA2-256","SHA2-384","SHA2-512"]},
{"algorithm":"TLS-v1.3","mode":"KDF","revision":"RFC8446","hmacAlg":["SHA2-256","SHA2-384"],"runningMode":["DHE","PSK","PSK-DHE"]},
- {"algorithm":"kdf-components","mode":"ssh","revision":"1.0","hashAlg":["SHA2-224","SHA2-256","SHA2-384","SHA2-512"],"cipher":["AES-128","AES-192","AES-256"]}
+ {"algorithm":"kdf-components","mode":"ssh","revision":"1.0","hashAlg":["SHA2-224","SHA2-256","SHA2-384","SHA2-512"],"cipher":["AES-128","AES-192","AES-256"]},
+
+ {"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"]}
]
diff --git a/src/crypto/internal/fips140test/acvp_test.go b/src/crypto/internal/fips140test/acvp_test.go
index ded66b79ae..8c51538cab 100644
--- a/src/crypto/internal/fips140test/acvp_test.go
+++ b/src/crypto/internal/fips140test/acvp_test.go
@@ -26,6 +26,7 @@ import (
"crypto/internal/fips140"
"crypto/internal/fips140/aes"
"crypto/internal/fips140/aes/gcm"
+ "crypto/internal/fips140/ecdh"
"crypto/internal/fips140/ecdsa"
"crypto/internal/fips140/ed25519"
"crypto/internal/fips140/edwards25519"
@@ -123,6 +124,8 @@ var (
// https://pages.nist.gov/ACVP/draft-hammett-acvp-kdf-tls-v1.3.html#section-7.2
// SSH KDF algorithm capabilities:
// https://pages.nist.gov/ACVP/draft-celi-acvp-kdf-ssh.html#section-7.2
+ // ECDH algorithm capabilities:
+ // https://pages.nist.gov/ACVP/draft-hammett-acvp-kas-ssc-ecc.html
//go:embed acvp_capabilities.json
capabilitiesJson []byte
@@ -251,6 +254,11 @@ var (
"SSHKDF/SHA2-384/server": cmdSshKdfAft(func() fips140.Hash { return sha512.New384() }, ssh.ServerKeys),
"SSHKDF/SHA2-512/client": cmdSshKdfAft(func() fips140.Hash { return sha512.New() }, ssh.ClientKeys),
"SSHKDF/SHA2-512/server": cmdSshKdfAft(func() fips140.Hash { return sha512.New() }, ssh.ServerKeys),
+
+ "ECDH/P-224": cmdEcdhAftVal(ecdh.P224()),
+ "ECDH/P-256": cmdEcdhAftVal(ecdh.P256()),
+ "ECDH/P-384": cmdEcdhAftVal(ecdh.P384()),
+ "ECDH/P-521": cmdEcdhAftVal(ecdh.P521()),
}
)
@@ -1413,6 +1421,45 @@ func cmdSshKdfAft(hFunc func() fips140.Hash, direction ssh.Direction) command {
}
}
+func cmdEcdhAftVal[P ecdh.Point[P]](curve *ecdh.Curve[P]) command {
+ return command{
+ requiredArgs: 3, // X, Y, private key (empty for Val type tests)
+ handler: func(args [][]byte) ([][]byte, error) {
+ peerX := args[0]
+ peerY := args[1]
+ rawSk := args[2]
+
+ uncompressedPk := append([]byte{4}, append(peerX, peerY...)...) // 4 for uncompressed point format
+ pk, err := ecdh.NewPublicKey(curve, uncompressedPk)
+ if err != nil {
+ return nil, fmt.Errorf("invalid peer public key x,y: %v", err)
+ }
+
+ var sk *ecdh.PrivateKey
+ if len(rawSk) > 0 {
+ sk, err = ecdh.NewPrivateKey(curve, rawSk)
+ } else {
+ sk, err = ecdh.GenerateKey(curve, rand.Reader)
+ }
+ if err != nil {
+ return nil, fmt.Errorf("private key error: %v", err)
+ }
+
+ pubBytes := sk.PublicKey().Bytes()
+ coordLen := (len(pubBytes) - 1) / 2
+ x := pubBytes[1 : 1+coordLen]
+ y := pubBytes[1+coordLen:]
+
+ secret, err := ecdh.ECDH(curve, sk, pk)
+ if err != nil {
+ return nil, fmt.Errorf("key agreement failed: %v", err)
+ }
+
+ return [][]byte{x, y, secret}, nil
+ },
+ }
+}
+
func TestACVP(t *testing.T) {
testenv.SkipIfShortAndSlow(t)