Skip to content

Commit 67d8916

Browse files
rolandshoemakergopherbot
authored andcommitted
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. Fixes #58131 Change-Id: I739181a3f1283bed14fb5ee7eb78658b854d28d8 Reviewed-on: https://go-review.googlesource.com/c/go/+/464335 Reviewed-by: Filippo Valsorda <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Tatiana Bradley <[email protected]> Auto-Submit: Roland Shoemaker <[email protected]> Run-TryBot: Roland Shoemaker <[email protected]>
1 parent e2ca417 commit 67d8916

File tree

2 files changed

+42
-1
lines changed

2 files changed

+42
-1
lines changed

src/crypto/ecdh/ecdh.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"crypto"
1111
"crypto/internal/boring"
1212
"crypto/subtle"
13+
"errors"
1314
"io"
1415
"sync"
1516
)
@@ -109,7 +110,8 @@ type PrivateKey struct {
109110
publicKeyOnce sync.Once
110111
}
111112

112-
// ECDH performs a ECDH exchange and returns the shared secret.
113+
// ECDH performs a ECDH exchange and returns the shared secret. The PrivateKey
114+
// and PublicKey must use the same curve.
113115
//
114116
// For NIST curves, this performs ECDH as specified in SEC 1, Version 2.0,
115117
// Section 3.3.1, and returns the x-coordinate encoded according to SEC 1,
@@ -118,6 +120,9 @@ type PrivateKey struct {
118120
// For X25519, this performs ECDH as specified in RFC 7748, Section 6.1. If
119121
// the result is the all-zero value, ECDH returns an error.
120122
func (k *PrivateKey) ECDH(remote *PublicKey) ([]byte, error) {
123+
if k.curve != remote.curve {
124+
return nil, errors.New("crypto/ecdh: private key and public key curves do not match")
125+
}
121126
return k.curve.ecdh(k, remote)
122127
}
123128

src/crypto/ecdh/ecdh_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,3 +487,39 @@ func TestLinker(t *testing.T) {
487487
t.Error("no P384 symbols found in program using ecdh.P384, test is broken")
488488
}
489489
}
490+
491+
func TestMismatchedCurves(t *testing.T) {
492+
curves := []struct {
493+
name string
494+
curve ecdh.Curve
495+
}{
496+
{"P256", ecdh.P256()},
497+
{"P384", ecdh.P384()},
498+
{"P521", ecdh.P521()},
499+
{"X25519", ecdh.X25519()},
500+
}
501+
502+
for _, privCurve := range curves {
503+
priv, err := privCurve.curve.GenerateKey(rand.Reader)
504+
if err != nil {
505+
t.Fatalf("failed to generate test key: %s", err)
506+
}
507+
508+
for _, pubCurve := range curves {
509+
if privCurve == pubCurve {
510+
continue
511+
}
512+
t.Run(fmt.Sprintf("%s/%s", privCurve.name, pubCurve.name), func(t *testing.T) {
513+
pub, err := pubCurve.curve.GenerateKey(rand.Reader)
514+
if err != nil {
515+
t.Fatalf("failed to generate test key: %s", err)
516+
}
517+
expected := "crypto/ecdh: private key and public key curves do not match"
518+
_, err = priv.ECDH(pub.PublicKey())
519+
if err.Error() != expected {
520+
t.Fatalf("unexpected error: want %q, got %q", expected, err)
521+
}
522+
})
523+
}
524+
}
525+
}

0 commit comments

Comments
 (0)