From: Filippo Valsorda Date: Wed, 20 Nov 2024 17:59:09 +0000 (+0100) Subject: crypto/ecdh: revamp FIPS ECDH API X-Git-Tag: go1.24rc1~100 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=fb432782f0017f59f6f2c5f620dfd8c67b5e35e3;p=gostls13.git crypto/ecdh: revamp FIPS ECDH API This makes it more similar to the ECDSA API, introducing proper key types that can correctly "cache" the key check. The new API also has a better compliance profile. Note how the old ECDHPnnn functions were not doing the PCT, instead delegating to the caller an invocation of ImportKeyPnnn. Change-Id: Ic6cf834427fd790324919b4d92bdaa2aac840016 Reviewed-on: https://go-review.googlesource.com/c/go/+/630098 Reviewed-by: Dmitri Shuralyov Auto-Submit: Filippo Valsorda Reviewed-by: Russ Cox LUCI-TryBot-Result: Go LUCI Reviewed-by: Daniel McCarney --- diff --git a/src/crypto/ecdh/ecdh.go b/src/crypto/ecdh/ecdh.go index e6bfe7c15c..231f1ea04c 100644 --- a/src/crypto/ecdh/ecdh.go +++ b/src/crypto/ecdh/ecdh.go @@ -9,6 +9,7 @@ package ecdh import ( "crypto" "crypto/internal/boring" + "crypto/internal/fips140/ecdh" "crypto/subtle" "errors" "io" @@ -60,6 +61,7 @@ type PublicKey struct { curve Curve publicKey []byte boring *boring.PublicKeyECDH + fips *ecdh.PublicKey } // Bytes returns a copy of the encoding of the public key. @@ -100,6 +102,7 @@ type PrivateKey struct { privateKey []byte publicKey *PublicKey boring *boring.PrivateKeyECDH + fips *ecdh.PrivateKey } // ECDH performs an ECDH exchange and returns the shared secret. The [PrivateKey] diff --git a/src/crypto/ecdh/nist.go b/src/crypto/ecdh/nist.go index 903aa26030..0f4a65e5af 100644 --- a/src/crypto/ecdh/nist.go +++ b/src/crypto/ecdh/nist.go @@ -13,11 +13,11 @@ import ( ) type nistCurve struct { - name string - generate func(io.Reader) (privateKey, publicKey []byte, err error) - importKey func([]byte) (publicKey []byte, err error) - checkPubkey func(publicKey []byte) error - sharedSecret func(privateKey, publicKey []byte) (sharedSecret []byte, err error) + name string + generate func(io.Reader) (*ecdh.PrivateKey, error) + newPrivateKey func([]byte) (*ecdh.PrivateKey, error) + newPublicKey func(publicKey []byte) (*ecdh.PublicKey, error) + sharedSecret func(*ecdh.PrivateKey, *ecdh.PublicKey) (sharedSecret []byte, err error) } func (c *nistCurve) String() string { @@ -43,15 +43,20 @@ func (c *nistCurve) GenerateKey(rand io.Reader) (*PrivateKey, error) { return k, nil } - privateKey, publicKey, err := c.generate(rand) + privateKey, err := c.generate(rand) if err != nil { return nil, err } k := &PrivateKey{ curve: c, - privateKey: privateKey, - publicKey: &PublicKey{curve: c, publicKey: publicKey}, + privateKey: privateKey.Bytes(), + fips: privateKey, + publicKey: &PublicKey{ + curve: c, + publicKey: privateKey.PublicKey().Bytes(), + fips: privateKey.PublicKey(), + }, } if boring.Enabled { bk, err := boring.NewPrivateKeyECDH(c.name, k.privateKey) @@ -87,15 +92,19 @@ func (c *nistCurve) NewPrivateKey(key []byte) (*PrivateKey, error) { return k, nil } - publicKey, err := c.importKey(key) + fk, err := c.newPrivateKey(key) if err != nil { return nil, err } - k := &PrivateKey{ curve: c, privateKey: bytes.Clone(key), - publicKey: &PublicKey{curve: c, publicKey: publicKey}, + fips: fk, + publicKey: &PublicKey{ + curve: c, + publicKey: fk.PublicKey().Bytes(), + fips: fk.PublicKey(), + }, } return k, nil } @@ -117,9 +126,11 @@ func (c *nistCurve) NewPublicKey(key []byte) (*PublicKey, error) { } k.boring = bk } else { - if err := c.checkPubkey(k.publicKey); err != nil { + fk, err := c.newPublicKey(key) + if err != nil { return nil, err } + k.fips = fk } return k, nil } @@ -135,7 +146,7 @@ func (c *nistCurve) ecdh(local *PrivateKey, remote *PublicKey) ([]byte, error) { if boring.Enabled { return boring.ECDH(local.boring, remote.boring) } - return c.sharedSecret(local.privateKey, remote.publicKey) + return c.sharedSecret(local.fips, remote.fips) } // P256 returns a [Curve] which implements NIST P-256 (FIPS 186-3, section D.2.3), @@ -146,11 +157,19 @@ func (c *nistCurve) ecdh(local *PrivateKey, remote *PublicKey) ([]byte, error) { func P256() Curve { return p256 } var p256 = &nistCurve{ - name: "P-256", - generate: ecdh.GenerateKeyP256, - importKey: ecdh.ImportKeyP256, - checkPubkey: ecdh.CheckPublicKeyP256, - sharedSecret: ecdh.ECDHP256, + name: "P-256", + generate: func(r io.Reader) (*ecdh.PrivateKey, error) { + return ecdh.GenerateKey(ecdh.P256(), r) + }, + newPrivateKey: func(b []byte) (*ecdh.PrivateKey, error) { + return ecdh.NewPrivateKey(ecdh.P256(), b) + }, + newPublicKey: func(publicKey []byte) (*ecdh.PublicKey, error) { + return ecdh.NewPublicKey(ecdh.P256(), publicKey) + }, + sharedSecret: func(priv *ecdh.PrivateKey, pub *ecdh.PublicKey) (sharedSecret []byte, err error) { + return ecdh.ECDH(ecdh.P256(), priv, pub) + }, } // P384 returns a [Curve] which implements NIST P-384 (FIPS 186-3, section D.2.4), @@ -161,11 +180,19 @@ var p256 = &nistCurve{ func P384() Curve { return p384 } var p384 = &nistCurve{ - name: "P-384", - generate: ecdh.GenerateKeyP384, - importKey: ecdh.ImportKeyP384, - checkPubkey: ecdh.CheckPublicKeyP384, - sharedSecret: ecdh.ECDHP384, + name: "P-384", + generate: func(r io.Reader) (*ecdh.PrivateKey, error) { + return ecdh.GenerateKey(ecdh.P384(), r) + }, + newPrivateKey: func(b []byte) (*ecdh.PrivateKey, error) { + return ecdh.NewPrivateKey(ecdh.P384(), b) + }, + newPublicKey: func(publicKey []byte) (*ecdh.PublicKey, error) { + return ecdh.NewPublicKey(ecdh.P384(), publicKey) + }, + sharedSecret: func(priv *ecdh.PrivateKey, pub *ecdh.PublicKey) (sharedSecret []byte, err error) { + return ecdh.ECDH(ecdh.P384(), priv, pub) + }, } // P521 returns a [Curve] which implements NIST P-521 (FIPS 186-3, section D.2.5), @@ -176,9 +203,17 @@ var p384 = &nistCurve{ func P521() Curve { return p521 } var p521 = &nistCurve{ - name: "P-521", - generate: ecdh.GenerateKeyP521, - importKey: ecdh.ImportKeyP521, - checkPubkey: ecdh.CheckPublicKeyP521, - sharedSecret: ecdh.ECDHP521, + name: "P-521", + generate: func(r io.Reader) (*ecdh.PrivateKey, error) { + return ecdh.GenerateKey(ecdh.P521(), r) + }, + newPrivateKey: func(b []byte) (*ecdh.PrivateKey, error) { + return ecdh.NewPrivateKey(ecdh.P521(), b) + }, + newPublicKey: func(publicKey []byte) (*ecdh.PublicKey, error) { + return ecdh.NewPublicKey(ecdh.P521(), publicKey) + }, + sharedSecret: func(priv *ecdh.PrivateKey, pub *ecdh.PublicKey) (sharedSecret []byte, err error) { + return ecdh.ECDH(ecdh.P521(), priv, pub) + }, } diff --git a/src/crypto/internal/fips140/ecdh/cast.go b/src/crypto/internal/fips140/ecdh/cast.go index b9b2def321..d63058fdab 100644 --- a/src/crypto/internal/fips140/ecdh/cast.go +++ b/src/crypto/internal/fips140/ecdh/cast.go @@ -8,7 +8,6 @@ import ( "bytes" "crypto/internal/fips140" _ "crypto/internal/fips140/check" - "crypto/internal/fips140/nistec" "errors" "sync" ) @@ -39,7 +38,9 @@ var fipsSelfTest = sync.OnceFunc(func() { 0x83, 0x48, 0x40, 0x56, 0x69, 0xa1, 0x95, 0xfa, 0xc5, 0x35, 0x04, 0x06, 0xba, 0x76, 0xbc, 0xce, } - got, err := ecdh(privateKey, publicKey, nistec.NewP256Point) + k := &PrivateKey{d: privateKey, pub: PublicKey{curve: p256}} + peer := &PublicKey{curve: p256, q: publicKey} + got, err := ecdh(P256(), k, peer) if err != nil { return err } diff --git a/src/crypto/internal/fips140/ecdh/ecdh.go b/src/crypto/internal/fips140/ecdh/ecdh.go index d2757bbf16..19a45c00db 100644 --- a/src/crypto/internal/fips140/ecdh/ecdh.go +++ b/src/crypto/internal/fips140/ecdh/ecdh.go @@ -16,72 +16,142 @@ import ( "math/bits" ) -// point is a generic constraint for the [nistec] point types. -type point[T any] interface { +// PrivateKey and PublicKey are not generic to make it possible to use them +// in other types without instantiating them with a specific point type. +// They are tied to one of the Curve types below through the curveID field. + +// All this is duplicated from crypto/internal/fips/ecdsa, but the standards are +// different and FIPS 140 does not allow reusing keys across them. + +type PrivateKey struct { + pub PublicKey + d []byte // bigmod.(*Nat).Bytes output (fixed length) +} + +func (priv *PrivateKey) Bytes() []byte { + return priv.d +} + +func (priv *PrivateKey) PublicKey() *PublicKey { + return &priv.pub +} + +type PublicKey struct { + curve curveID + q []byte // uncompressed nistec Point.Bytes output +} + +func (pub *PublicKey) Bytes() []byte { + return pub.q +} + +type curveID string + +const ( + p224 curveID = "P-224" + p256 curveID = "P-256" + p384 curveID = "P-384" + p521 curveID = "P-521" +) + +type Curve[P Point[P]] struct { + curve curveID + newPoint func() P + N []byte +} + +// Point is a generic constraint for the [nistec] Point types. +type Point[P any] interface { *nistec.P224Point | *nistec.P256Point | *nistec.P384Point | *nistec.P521Point Bytes() []byte BytesX() ([]byte, error) - SetBytes([]byte) (T, error) - ScalarMult(T, []byte) (T, error) - ScalarBaseMult([]byte) (T, error) + SetBytes([]byte) (P, error) + ScalarMult(P, []byte) (P, error) + ScalarBaseMult([]byte) (P, error) } -// GenerateKeyP224 generates a random P-224 private key for ECDH. -// -// If FIPS mode is disabled, privateKey is generated from rand. If FIPS mode is -// enabled, rand is ignored and the key pair is generated using the approved -// DRBG (and the function runs considerably slower). -func GenerateKeyP224(rand io.Reader) (privateKey, publicKey []byte, err error) { - fipsSelfTest() - fips140.RecordApproved() - return generateKey(rand, nistec.NewP224Point, p224Order) +func P224() *Curve[*nistec.P224Point] { + return &Curve[*nistec.P224Point]{ + curve: p224, + newPoint: nistec.NewP224Point, + N: p224Order, + } } -// GenerateKeyP256 generates a random P-256 private key for ECDH. -// -// If FIPS mode is disabled, privateKey is generated from rand. If FIPS mode is -// enabled, rand is ignored and the key pair is generated using the approved -// DRBG (and the function runs considerably slower). -func GenerateKeyP256(rand io.Reader) (privateKey, publicKey []byte, err error) { - fipsSelfTest() - fips140.RecordApproved() - return generateKey(rand, nistec.NewP256Point, p256Order) +var p224Order = []byte{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2, + 0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45, + 0x5c, 0x5c, 0x2a, 0x3d, } -// GenerateKeyP384 generates a random P-384 private key for ECDH. -// -// If FIPS mode is disabled, privateKey is generated from rand. If FIPS mode is -// enabled, rand is ignored and the key pair is generated using the approved -// DRBG (and the function runs considerably slower). -func GenerateKeyP384(rand io.Reader) (privateKey, publicKey []byte, err error) { - fipsSelfTest() - fips140.RecordApproved() - return generateKey(rand, nistec.NewP384Point, p384Order) +func P256() *Curve[*nistec.P256Point] { + return &Curve[*nistec.P256Point]{ + curve: p256, + newPoint: nistec.NewP256Point, + N: p256Order, + } } -// GenerateKeyP521 generates a random P-521 private key for ECDH. -// -// If FIPS mode is disabled, privateKey is generated from rand. If FIPS mode is -// enabled, rand is ignored and the key pair is generated using the approved -// DRBG (and the function runs considerably slower). -func GenerateKeyP521(rand io.Reader) (privateKey, publicKey []byte, err error) { - fipsSelfTest() - fips140.RecordApproved() - return generateKey(rand, nistec.NewP521Point, p521Order) +var p256Order = []byte{ + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xbc, 0xe6, 0xfa, 0xad, 0xa7, 0x17, 0x9e, 0x84, + 0xf3, 0xb9, 0xca, 0xc2, 0xfc, 0x63, 0x25, 0x51, +} + +func P384() *Curve[*nistec.P384Point] { + return &Curve[*nistec.P384Point]{ + curve: p384, + newPoint: nistec.NewP384Point, + N: p384Order, + } +} + +var p384Order = []byte{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xc7, 0x63, 0x4d, 0x81, 0xf4, 0x37, 0x2d, 0xdf, + 0x58, 0x1a, 0x0d, 0xb2, 0x48, 0xb0, 0xa7, 0x7a, + 0xec, 0xec, 0x19, 0x6a, 0xcc, 0xc5, 0x29, 0x73, } -func generateKey[P point[P]](rand io.Reader, newPoint func() P, scalarOrder []byte) (privateKey, publicKey []byte, err error) { +func P521() *Curve[*nistec.P521Point] { + return &Curve[*nistec.P521Point]{ + curve: p521, + newPoint: nistec.NewP521Point, + N: p521Order, + } +} + +var p521Order = []byte{0x01, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, + 0x51, 0x86, 0x87, 0x83, 0xbf, 0x2f, 0x96, 0x6b, + 0x7f, 0xcc, 0x01, 0x48, 0xf7, 0x09, 0xa5, 0xd0, + 0x3b, 0xb5, 0xc9, 0xb8, 0x89, 0x9c, 0x47, 0xae, + 0xbb, 0x6f, 0xb7, 0x1e, 0x91, 0x38, 0x64, 0x09, +} + +// GenerateKey generates a new ECDSA private key pair for the specified curve. +// +// In FIPS mode, rand is ignored. +func GenerateKey[P Point[P]](c *Curve[P], rand io.Reader) (*PrivateKey, error) { + fips140.RecordApproved() // This procedure is equivalent to Key Pair Generation by Testing // Candidates, specified in NIST SP 800-56A Rev. 3, Section 5.6.1.2.2. for { - key := make([]byte, len(scalarOrder)) + key := make([]byte, len(c.N)) if fips140.Enabled { drbg.Read(key) } else { randutil.MaybeReadByte(rand) if _, err := io.ReadFull(rand, key); err != nil { - return nil, nil, err + return nil, err } // In tests, rand will return all zeros and NewPrivateKey will reject // the zero key as it generates the identity as a public key. This also @@ -91,55 +161,34 @@ func generateKey[P point[P]](rand io.Reader, newPoint func() P, scalarOrder []by // Mask off any excess bits if the size of the underlying field is not a // whole number of bytes, which is only the case for P-521. - if len(scalarOrder) == len(p521Order) && scalarOrder[0]&0b1111_1110 == 0 { + if c.curve == p521 && c.N[0]&0b1111_1110 == 0 { key[0] &= 0b0000_0001 } - publicKey, err := checkKeyAndComputePublicKey(key, newPoint, scalarOrder) + privateKey, err := NewPrivateKey(c, key) if err != nil { continue } - - return key, publicKey, nil + return privateKey, nil } } -func ImportKeyP224(privateKey []byte) (publicKey []byte, err error) { - fips140.RecordNonApproved() - return checkKeyAndComputePublicKey(privateKey, nistec.NewP224Point, p224Order) -} - -func ImportKeyP256(privateKey []byte) (publicKey []byte, err error) { - fips140.RecordNonApproved() - return checkKeyAndComputePublicKey(privateKey, nistec.NewP256Point, p256Order) -} - -func ImportKeyP384(privateKey []byte) (publicKey []byte, err error) { - fips140.RecordNonApproved() - return checkKeyAndComputePublicKey(privateKey, nistec.NewP384Point, p384Order) -} - -func ImportKeyP521(privateKey []byte) (publicKey []byte, err error) { - fips140.RecordNonApproved() - return checkKeyAndComputePublicKey(privateKey, nistec.NewP521Point, p521Order) -} - -func checkKeyAndComputePublicKey[P point[P]](key []byte, newPoint func() P, scalarOrder []byte) (publicKey []byte, err error) { +func NewPrivateKey[P Point[P]](c *Curve[P], key []byte) (*PrivateKey, error) { // SP 800-56A Rev. 3, Section 5.6.1.2.2 checks that c <= n – 2 and then // returns d = c + 1. Note that it follows that 0 < d < n. Equivalently, // we check that 0 < d < n, and return d. - if len(key) != len(scalarOrder) || isZero(key) || !isLess(key, scalarOrder) { + if len(key) != len(c.N) || isZero(key) || !isLess(key, c.N) { return nil, errors.New("crypto/ecdh: invalid private key") } - p, err := newPoint().ScalarBaseMult(key) + p, err := c.newPoint().ScalarBaseMult(key) if err != nil { // This is unreachable because the only error condition of // ScalarBaseMult is if the input is not the right size. panic("crypto/ecdh: internal error: nistec ScalarBaseMult failed for a fixed-size input") } - publicKey = p.Bytes() + publicKey := p.Bytes() if len(publicKey) == 1 { // The encoding of the identity is a single 0x00 byte. This is // unreachable because the only scalar that generates the identity is @@ -157,7 +206,7 @@ func checkKeyAndComputePublicKey[P point[P]](key []byte, newPoint func() P, scal // consistent [...], even if the underlying standard does not require a // PCT". So we do it. And make ECDH nearly 50% slower (only) in FIPS mode. if err := fips140.PCT("ECDH PCT", func() error { - p1, err := newPoint().ScalarBaseMult(key) + p1, err := c.newPoint().ScalarBaseMult(key) if err != nil { return err } @@ -169,92 +218,58 @@ func checkKeyAndComputePublicKey[P point[P]](key []byte, newPoint func() P, scal panic(err) } - return publicKey, nil -} - -func CheckPublicKeyP224(publicKey []byte) error { - fipsSelfTest() - fips140.RecordApproved() - return checkPublicKey(publicKey, nistec.NewP224Point) -} - -func CheckPublicKeyP256(publicKey []byte) error { - fipsSelfTest() - fips140.RecordApproved() - return checkPublicKey(publicKey, nistec.NewP256Point) -} - -func CheckPublicKeyP384(publicKey []byte) error { - fipsSelfTest() - fips140.RecordApproved() - return checkPublicKey(publicKey, nistec.NewP384Point) + k := &PrivateKey{d: bytes.Clone(key), pub: PublicKey{curve: c.curve, q: publicKey}} + return k, nil } -func CheckPublicKeyP521(publicKey []byte) error { - fipsSelfTest() - fips140.RecordApproved() - return checkPublicKey(publicKey, nistec.NewP521Point) -} - -func checkPublicKey[P point[P]](key []byte, newPoint func() P) error { +func NewPublicKey[P Point[P]](c *Curve[P], key []byte) (*PublicKey, error) { // Reject the point at infinity and compressed encodings. if len(key) == 0 || key[0] != 4 { - return errors.New("crypto/ecdh: invalid public key") + return nil, errors.New("crypto/ecdh: invalid public key") } // SetBytes checks that x and y are in the interval [0, p - 1], and that // the point is on the curve. Along with the rejection of the point at // infinity (the identity element) above, this fulfills the requirements // of NIST SP 800-56A Rev. 3, Section 5.6.2.3.4. - if _, err := newPoint().SetBytes(key); err != nil { - return err + if _, err := c.newPoint().SetBytes(key); err != nil { + return nil, err } - return nil + return &PublicKey{curve: c.curve, q: bytes.Clone(key)}, nil } -func ECDHP224(privateKey, publicKey []byte) ([]byte, error) { +func ECDH[P Point[P]](c *Curve[P], k *PrivateKey, peer *PublicKey) ([]byte, error) { fipsSelfTest() fips140.RecordApproved() - return ecdh(privateKey, publicKey, nistec.NewP224Point) + return ecdh(c, k, peer) } -func ECDHP256(privateKey, publicKey []byte) ([]byte, error) { - fipsSelfTest() - fips140.RecordApproved() - return ecdh(privateKey, publicKey, nistec.NewP256Point) -} - -func ECDHP384(privateKey, publicKey []byte) ([]byte, error) { - fipsSelfTest() - fips140.RecordApproved() - return ecdh(privateKey, publicKey, nistec.NewP384Point) -} - -func ECDHP521(privateKey, publicKey []byte) ([]byte, error) { - fipsSelfTest() - fips140.RecordApproved() - return ecdh(privateKey, publicKey, nistec.NewP521Point) -} +func ecdh[P Point[P]](c *Curve[P], k *PrivateKey, peer *PublicKey) ([]byte, error) { + if c.curve != k.pub.curve { + return nil, errors.New("crypto/ecdh: mismatched curves") + } + if k.pub.curve != peer.curve { + return nil, errors.New("crypto/ecdh: mismatched curves") + } -func ecdh[P point[P]](privateKey, publicKey []byte, newPoint func() P) ([]byte, error) { // This applies the Shared Secret Computation of the Ephemeral Unified Model // scheme specified in NIST SP 800-56A Rev. 3, Section 6.1.2.2. // Per Section 5.6.2.3.4, Step 1, reject the identity element (0x00). - if len(publicKey) == 1 { + if len(k.pub.q) == 1 { return nil, errors.New("crypto/ecdh: public key is the identity element") } // SetBytes checks that (x, y) are reduced modulo p, and that they are on // the curve, performing Steps 2-3 of Section 5.6.2.3.4. - p, err := newPoint().SetBytes(publicKey) + p, err := c.newPoint().SetBytes(peer.q) if err != nil { return nil, err } // Compute P according to Section 5.7.1.2. - if _, err := p.ScalarMult(p, privateKey); err != nil { + if _, err := p.ScalarMult(p, k.d); err != nil { return nil, err } @@ -300,34 +315,3 @@ func isLess(a, b []byte) bool { // If there is a borrow at the end of the operation, then a < b. return borrow == 1 } - -var p224Order = []byte{ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2, - 0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45, - 0x5c, 0x5c, 0x2a, 0x3d, -} - -var p256Order = []byte{ - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xbc, 0xe6, 0xfa, 0xad, 0xa7, 0x17, 0x9e, 0x84, - 0xf3, 0xb9, 0xca, 0xc2, 0xfc, 0x63, 0x25, 0x51} - -var p384Order = []byte{ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xc7, 0x63, 0x4d, 0x81, 0xf4, 0x37, 0x2d, 0xdf, - 0x58, 0x1a, 0x0d, 0xb2, 0x48, 0xb0, 0xa7, 0x7a, - 0xec, 0xec, 0x19, 0x6a, 0xcc, 0xc5, 0x29, 0x73} - -var p521Order = []byte{0x01, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, - 0x51, 0x86, 0x87, 0x83, 0xbf, 0x2f, 0x96, 0x6b, - 0x7f, 0xcc, 0x01, 0x48, 0xf7, 0x09, 0xa5, 0xd0, - 0x3b, 0xb5, 0xc9, 0xb8, 0x89, 0x9c, 0x47, 0xae, - 0xbb, 0x6f, 0xb7, 0x1e, 0x91, 0x38, 0x64, 0x09} diff --git a/src/crypto/internal/fips140/ecdh/order_test.go b/src/crypto/internal/fips140/ecdh/order_test.go index 772c42c813..83453c5ac3 100644 --- a/src/crypto/internal/fips140/ecdh/order_test.go +++ b/src/crypto/internal/fips140/ecdh/order_test.go @@ -11,16 +11,16 @@ import ( ) func TestOrders(t *testing.T) { - if !bytes.Equal(elliptic.P224().Params().N.Bytes(), p224Order) { + if !bytes.Equal(elliptic.P224().Params().N.Bytes(), P224().N) { t.Errorf("P-224 order mismatch") } - if !bytes.Equal(elliptic.P256().Params().N.Bytes(), p256Order) { + if !bytes.Equal(elliptic.P256().Params().N.Bytes(), P256().N) { t.Errorf("P-256 order mismatch") } - if !bytes.Equal(elliptic.P384().Params().N.Bytes(), p384Order) { + if !bytes.Equal(elliptic.P384().Params().N.Bytes(), P384().N) { t.Errorf("P-384 order mismatch") } - if !bytes.Equal(elliptic.P521().Params().N.Bytes(), p521Order) { + if !bytes.Equal(elliptic.P521().Params().N.Bytes(), P521().N) { t.Errorf("P-521 order mismatch") } } diff --git a/src/crypto/internal/fips140test/cast_test.go b/src/crypto/internal/fips140test/cast_test.go index 0c5cc63e3f..0ef75afcbe 100644 --- a/src/crypto/internal/fips140test/cast_test.go +++ b/src/crypto/internal/fips140test/cast_test.go @@ -73,12 +73,16 @@ func findAllCASTs(t *testing.T) map[string]struct{} { // TestConditionals causes the conditional CASTs and PCTs to be invoked. func TestConditionals(t *testing.T) { mlkem.GenerateKey768() - ecdh.GenerateKeyP256(rand.Reader) - k, err := ecdsa.GenerateKey(ecdsa.P256(), rand.Reader) + k, err := ecdh.GenerateKey(ecdh.P256(), rand.Reader) if err != nil { t.Fatal(err) } - ecdsa.SignDeterministic(ecdsa.P256(), sha256.New, k, make([]byte, 32)) + ecdh.ECDH(ecdh.P256(), k, k.PublicKey()) + kDSA, err := ecdsa.GenerateKey(ecdsa.P256(), rand.Reader) + if err != nil { + t.Fatal(err) + } + ecdsa.SignDeterministic(ecdsa.P256(), sha256.New, kDSA, make([]byte, 32)) k25519, err := ed25519.GenerateKey(rand.Reader) if err != nil { t.Fatal(err)