diff options
author | Roland Shoemaker <roland@golang.org> | 2023-01-31 09:14:16 -0800 |
---|---|---|
committer | Gopher Robot <gobot@golang.org> | 2023-02-28 01:46:26 +0000 |
commit | aaace6dda7cde2bebf13c64fb0d75536adb2b08b (patch) | |
tree | 7157ad0180a47d62ef711ba839c5906844c1e86c | |
parent | 0f4483cfdcf303ac5cbe4f4536e23750423137d9 (diff) | |
download | go-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.go | 7 | ||||
-rw-r--r-- | src/crypto/ecdh/ecdh_test.go | 36 |
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) + } + }) + } + } +} |