summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoland Shoemaker <roland@golang.org>2023-01-31 09:14:16 -0800
committerGopher Robot <gobot@golang.org>2023-02-28 01:46:26 +0000
commitaaace6dda7cde2bebf13c64fb0d75536adb2b08b (patch)
tree7157ad0180a47d62ef711ba839c5906844c1e86c
parent0f4483cfdcf303ac5cbe4f4536e23750423137d9 (diff)
downloadgo-git-aaace6dda7cde2bebf13c64fb0d75536adb2b08b.tar.gz
[release-branch.go1.20] crypto/ecdh: explicitly reject mismatched curves in ECDH
Return an explicit error when PrivateKey.ECDH is called with a PublicKey which uses a different Curve. Also document this requirement, even though it is perhaps obvious. Updates #58131. Fixes #58498. Change-Id: I739181a3f1283bed14fb5ee7eb78658b854d28d8 Reviewed-on: https://go-review.googlesource.com/c/go/+/464335 Reviewed-by: Filippo Valsorda <filippo@golang.org> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Tatiana Bradley <tatianabradley@google.com> Auto-Submit: Roland Shoemaker <roland@golang.org> Run-TryBot: Roland Shoemaker <roland@golang.org> (cherry picked from commit 67d8916d551d22f5376e0be71d3922c9d63eaa6a) Reviewed-on: https://go-review.googlesource.com/c/go/+/471602 Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org> Auto-Submit: Dmitri Shuralyov <dmitshur@google.com> Reviewed-by: Roland Shoemaker <roland@golang.org>
-rw-r--r--src/crypto/ecdh/ecdh.go7
-rw-r--r--src/crypto/ecdh/ecdh_test.go36
2 files changed, 42 insertions, 1 deletions
diff --git a/src/crypto/ecdh/ecdh.go b/src/crypto/ecdh/ecdh.go
index d78b4d4432..74420559b5 100644
--- a/src/crypto/ecdh/ecdh.go
+++ b/src/crypto/ecdh/ecdh.go
@@ -10,6 +10,7 @@ import (
"crypto"
"crypto/internal/boring"
"crypto/subtle"
+ "errors"
"io"
"sync"
)
@@ -109,7 +110,8 @@ type PrivateKey struct {
publicKeyOnce sync.Once
}
-// ECDH performs a ECDH exchange and returns the shared secret.
+// ECDH performs a ECDH exchange and returns the shared secret. The PrivateKey
+// and PublicKey must use the same curve.
//
// For NIST curves, this performs ECDH as specified in SEC 1, Version 2.0,
// Section 3.3.1, and returns the x-coordinate encoded according to SEC 1,
@@ -118,6 +120,9 @@ type PrivateKey struct {
// For X25519, this performs ECDH as specified in RFC 7748, Section 6.1. If
// the result is the all-zero value, ECDH returns an error.
func (k *PrivateKey) ECDH(remote *PublicKey) ([]byte, error) {
+ if k.curve != remote.curve {
+ return nil, errors.New("crypto/ecdh: private key and public key curves do not match")
+ }
return k.curve.ecdh(k, remote)
}
diff --git a/src/crypto/ecdh/ecdh_test.go b/src/crypto/ecdh/ecdh_test.go
index 426850a146..10da95afbb 100644
--- a/src/crypto/ecdh/ecdh_test.go
+++ b/src/crypto/ecdh/ecdh_test.go
@@ -487,3 +487,39 @@ func TestLinker(t *testing.T) {
t.Error("no P384 symbols found in program using ecdh.P384, test is broken")
}
}
+
+func TestMismatchedCurves(t *testing.T) {
+ curves := []struct {
+ name string
+ curve ecdh.Curve
+ }{
+ {"P256", ecdh.P256()},
+ {"P384", ecdh.P384()},
+ {"P521", ecdh.P521()},
+ {"X25519", ecdh.X25519()},
+ }
+
+ for _, privCurve := range curves {
+ priv, err := privCurve.curve.GenerateKey(rand.Reader)
+ if err != nil {
+ t.Fatalf("failed to generate test key: %s", err)
+ }
+
+ for _, pubCurve := range curves {
+ if privCurve == pubCurve {
+ continue
+ }
+ t.Run(fmt.Sprintf("%s/%s", privCurve.name, pubCurve.name), func(t *testing.T) {
+ pub, err := pubCurve.curve.GenerateKey(rand.Reader)
+ if err != nil {
+ t.Fatalf("failed to generate test key: %s", err)
+ }
+ expected := "crypto/ecdh: private key and public key curves do not match"
+ _, err = priv.ECDH(pub.PublicKey())
+ if err.Error() != expected {
+ t.Fatalf("unexpected error: want %q, got %q", expected, err)
+ }
+ })
+ }
+ }
+}