ecdsa.mx raw

   1  // Copyright 2011 The Go Authors. All rights reserved.
   2  // Use of this source code is governed by a BSD-style
   3  // license that can be found in the LICENSE file.
   4  
   5  // Package ecdsa implements the Elliptic Curve Digital Signature Algorithm, as
   6  // defined in [FIPS 186-5].
   7  //
   8  // Signatures generated by this package are not deterministic, but entropy is
   9  // mixed with the private key and the message, achieving the same level of
  10  // security in case of randomness source failure.
  11  //
  12  // Operations involving private keys are implemented using constant-time
  13  // algorithms, as long as an [elliptic.Curve] returned by [elliptic.P224],
  14  // [elliptic.P256], [elliptic.P384], or [elliptic.P521] is used.
  15  //
  16  // [FIPS 186-5]: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-5.pdf
  17  package ecdsa
  18  
  19  import (
  20  	"crypto"
  21  	"crypto/ecdh"
  22  	"crypto/elliptic"
  23  	"crypto/internal/boring"
  24  	"crypto/internal/boring/bbig"
  25  	"crypto/internal/fips140/ecdsa"
  26  	"crypto/internal/fips140/nistec"
  27  	"crypto/internal/fips140cache"
  28  	"crypto/internal/fips140hash"
  29  	"crypto/internal/fips140only"
  30  	"crypto/internal/randutil"
  31  	"crypto/sha512"
  32  	"crypto/subtle"
  33  	"errors"
  34  	"io"
  35  	"math/big"
  36  
  37  	"golang.org/x/crypto/cryptobyte"
  38  	"golang.org/x/crypto/cryptobyte/asn1"
  39  )
  40  
  41  // PublicKey represents an ECDSA public key.
  42  type PublicKey struct {
  43  	elliptic.Curve
  44  
  45  	// X, Y are the coordinates of the public key point.
  46  	//
  47  	// Modifying the raw coordinates can produce invalid keys, and may
  48  	// invalidate internal optimizations; moreover, [big.Int] methods are not
  49  	// suitable for operating on cryptographic values. To encode and decode
  50  	// PublicKey values, use [PublicKey.Bytes] and [ParseUncompressedPublicKey]
  51  	// or [crypto/x509.MarshalPKIXPublicKey] and [crypto/x509.ParsePKIXPublicKey].
  52  	// For ECDH, use [crypto/ecdh]. For lower-level elliptic curve operations,
  53  	// use a third-party module like filippo.io/nistec.
  54  	//
  55  	// These fields will be deprecated in Go 1.26.
  56  	X, Y *big.Int
  57  }
  58  
  59  // Any methods implemented on PublicKey might need to also be implemented on
  60  // PrivateKey, as the latter embeds the former and will expose its methods.
  61  
  62  // ECDH returns k as a [ecdh.PublicKey]. It returns an error if the key is
  63  // invalid according to the definition of [ecdh.Curve.NewPublicKey], or if the
  64  // Curve is not supported by crypto/ecdh.
  65  func (k *PublicKey) ECDH() (*ecdh.PublicKey, error) {
  66  	c := curveToECDH(k.Curve)
  67  	if c == nil {
  68  		return nil, errors.New("ecdsa: unsupported curve by crypto/ecdh")
  69  	}
  70  	if !k.Curve.IsOnCurve(k.X, k.Y) {
  71  		return nil, errors.New("ecdsa: invalid public key")
  72  	}
  73  	return c.NewPublicKey(elliptic.Marshal(k.Curve, k.X, k.Y))
  74  }
  75  
  76  // Equal reports whether pub and x have the same value.
  77  //
  78  // Two keys are only considered to have the same value if they have the same Curve value.
  79  // Note that for example [elliptic.P256] and elliptic.P256().Params() are different
  80  // values, as the latter is a generic not constant time implementation.
  81  func (pub *PublicKey) Equal(x crypto.PublicKey) bool {
  82  	xx, ok := x.(*PublicKey)
  83  	if !ok {
  84  		return false
  85  	}
  86  	return bigIntEqual(pub.X, xx.X) && bigIntEqual(pub.Y, xx.Y) &&
  87  		// Standard library Curve implementations are singletons, so this check
  88  		// will work for those. Other Curves might be equivalent even if not
  89  		// singletons, but there is no definitive way to check for that, and
  90  		// better to err on the side of safety.
  91  		pub.Curve == xx.Curve
  92  }
  93  
  94  // ParseUncompressedPublicKey parses a public key encoded as an uncompressed
  95  // point according to SEC 1, Version 2.0, Section 2.3.3 (also known as the X9.62
  96  // uncompressed format). It returns an error if the point is not in uncompressed
  97  // form, is not on the curve, or is the point at infinity.
  98  //
  99  // curve must be one of [elliptic.P224], [elliptic.P256], [elliptic.P384], or
 100  // [elliptic.P521], or ParseUncompressedPublicKey returns an error.
 101  //
 102  // ParseUncompressedPublicKey accepts the same format as
 103  // [ecdh.Curve.NewPublicKey] does for NIST curves, but returns a [PublicKey]
 104  // instead of an [ecdh.PublicKey].
 105  //
 106  // Note that public keys are more commonly encoded in DER (or PEM) format, which
 107  // can be parsed with [crypto/x509.ParsePKIXPublicKey] (and [encoding/pem]).
 108  func ParseUncompressedPublicKey(curve elliptic.Curve, data []byte) (*PublicKey, error) {
 109  	if len(data) < 1 || data[0] != 4 {
 110  		return nil, errors.New("ecdsa: invalid uncompressed public key")
 111  	}
 112  	switch curve {
 113  	case elliptic.P224():
 114  		return parseUncompressedPublicKey(ecdsa.P224(), curve, data)
 115  	case elliptic.P256():
 116  		return parseUncompressedPublicKey(ecdsa.P256(), curve, data)
 117  	case elliptic.P384():
 118  		return parseUncompressedPublicKey(ecdsa.P384(), curve, data)
 119  	case elliptic.P521():
 120  		return parseUncompressedPublicKey(ecdsa.P521(), curve, data)
 121  	default:
 122  		return nil, errors.New("ecdsa: curve not supported by ParseUncompressedPublicKey")
 123  	}
 124  }
 125  
 126  func parseUncompressedPublicKey[P ecdsa.Point[P]](c *ecdsa.Curve[P], curve elliptic.Curve, data []byte) (*PublicKey, error) {
 127  	k, err := ecdsa.NewPublicKey(c, data)
 128  	if err != nil {
 129  		return nil, err
 130  	}
 131  	return publicKeyFromFIPS(curve, k)
 132  }
 133  
 134  // Bytes encodes the public key as an uncompressed point according to SEC 1,
 135  // Version 2.0, Section 2.3.3 (also known as the X9.62 uncompressed format).
 136  // It returns an error if the public key is invalid.
 137  //
 138  // PublicKey.Curve must be one of [elliptic.P224], [elliptic.P256],
 139  // [elliptic.P384], or [elliptic.P521], or Bytes returns an error.
 140  //
 141  // Bytes returns the same format as [ecdh.PublicKey.Bytes] does for NIST curves.
 142  //
 143  // Note that public keys are more commonly encoded in DER (or PEM) format, which
 144  // can be generated with [crypto/x509.MarshalPKIXPublicKey] (and [encoding/pem]).
 145  func (pub *PublicKey) Bytes() ([]byte, error) {
 146  	switch pub.Curve {
 147  	case elliptic.P224():
 148  		return publicKeyBytes(ecdsa.P224(), pub)
 149  	case elliptic.P256():
 150  		return publicKeyBytes(ecdsa.P256(), pub)
 151  	case elliptic.P384():
 152  		return publicKeyBytes(ecdsa.P384(), pub)
 153  	case elliptic.P521():
 154  		return publicKeyBytes(ecdsa.P521(), pub)
 155  	default:
 156  		return nil, errors.New("ecdsa: curve not supported by PublicKey.Bytes")
 157  	}
 158  }
 159  
 160  func publicKeyBytes[P ecdsa.Point[P]](c *ecdsa.Curve[P], pub *PublicKey) ([]byte, error) {
 161  	k, err := publicKeyToFIPS(c, pub)
 162  	if err != nil {
 163  		return nil, err
 164  	}
 165  	return k.Bytes(), nil
 166  }
 167  
 168  // PrivateKey represents an ECDSA private key.
 169  type PrivateKey struct {
 170  	PublicKey
 171  
 172  	// D is the private scalar value.
 173  	//
 174  	// Modifying the raw value can produce invalid keys, and may
 175  	// invalidate internal optimizations; moreover, [big.Int] methods are not
 176  	// suitable for operating on cryptographic values. To encode and decode
 177  	// PrivateKey values, use [PrivateKey.Bytes] and [ParseRawPrivateKey] or
 178  	// [crypto/x509.MarshalPKCS8PrivateKey] and [crypto/x509.ParsePKCS8PrivateKey].
 179  	// For ECDH, use [crypto/ecdh].
 180  	//
 181  	// This field will be deprecated in Go 1.26.
 182  	D *big.Int
 183  }
 184  
 185  // ECDH returns k as a [ecdh.PrivateKey]. It returns an error if the key is
 186  // invalid according to the definition of [ecdh.Curve.NewPrivateKey], or if the
 187  // Curve is not supported by [crypto/ecdh].
 188  func (k *PrivateKey) ECDH() (*ecdh.PrivateKey, error) {
 189  	c := curveToECDH(k.Curve)
 190  	if c == nil {
 191  		return nil, errors.New("ecdsa: unsupported curve by crypto/ecdh")
 192  	}
 193  	size := (k.Curve.Params().N.BitLen() + 7) / 8
 194  	if k.D.BitLen() > size*8 {
 195  		return nil, errors.New("ecdsa: invalid private key")
 196  	}
 197  	return c.NewPrivateKey(k.D.FillBytes([]byte{:size}))
 198  }
 199  
 200  func curveToECDH(c elliptic.Curve) ecdh.Curve {
 201  	switch c {
 202  	case elliptic.P256():
 203  		return ecdh.P256()
 204  	case elliptic.P384():
 205  		return ecdh.P384()
 206  	case elliptic.P521():
 207  		return ecdh.P521()
 208  	default:
 209  		return nil
 210  	}
 211  }
 212  
 213  // Public returns the public key corresponding to priv.
 214  func (priv *PrivateKey) Public() crypto.PublicKey {
 215  	return &priv.PublicKey
 216  }
 217  
 218  // Equal reports whether priv and x have the same value.
 219  //
 220  // See [PublicKey.Equal] for details on how Curve is compared.
 221  func (priv *PrivateKey) Equal(x crypto.PrivateKey) bool {
 222  	xx, ok := x.(*PrivateKey)
 223  	if !ok {
 224  		return false
 225  	}
 226  	return priv.PublicKey.Equal(&xx.PublicKey) && bigIntEqual(priv.D, xx.D)
 227  }
 228  
 229  // bigIntEqual reports whether a and b are equal leaking only their bit length
 230  // through timing side-channels.
 231  func bigIntEqual(a, b *big.Int) bool {
 232  	return subtle.ConstantTimeCompare(a.Bytes(), b.Bytes()) == 1
 233  }
 234  
 235  // ParseRawPrivateKey parses a private key encoded as a fixed-length big-endian
 236  // integer, according to SEC 1, Version 2.0, Section 2.3.6 (sometimes referred
 237  // to as the raw format). It returns an error if the value is not reduced modulo
 238  // the curve's order, or if it's zero.
 239  //
 240  // curve must be one of [elliptic.P224], [elliptic.P256], [elliptic.P384], or
 241  // [elliptic.P521], or ParseRawPrivateKey returns an error.
 242  //
 243  // ParseRawPrivateKey accepts the same format as [ecdh.Curve.NewPrivateKey] does
 244  // for NIST curves, but returns a [PrivateKey] instead of an [ecdh.PrivateKey].
 245  //
 246  // Note that private keys are more commonly encoded in ASN.1 or PKCS#8 format,
 247  // which can be parsed with [crypto/x509.ParseECPrivateKey] or
 248  // [crypto/x509.ParsePKCS8PrivateKey] (and [encoding/pem]).
 249  func ParseRawPrivateKey(curve elliptic.Curve, data []byte) (*PrivateKey, error) {
 250  	switch curve {
 251  	case elliptic.P224():
 252  		return parseRawPrivateKey(ecdsa.P224(), nistec.NewP224Point, curve, data)
 253  	case elliptic.P256():
 254  		return parseRawPrivateKey(ecdsa.P256(), nistec.NewP256Point, curve, data)
 255  	case elliptic.P384():
 256  		return parseRawPrivateKey(ecdsa.P384(), nistec.NewP384Point, curve, data)
 257  	case elliptic.P521():
 258  		return parseRawPrivateKey(ecdsa.P521(), nistec.NewP521Point, curve, data)
 259  	default:
 260  		return nil, errors.New("ecdsa: curve not supported by ParseRawPrivateKey")
 261  	}
 262  }
 263  
 264  func parseRawPrivateKey[P ecdsa.Point[P]](c *ecdsa.Curve[P], newPoint func() P, curve elliptic.Curve, data []byte) (*PrivateKey, error) {
 265  	q, err := newPoint().ScalarBaseMult(data)
 266  	if err != nil {
 267  		return nil, err
 268  	}
 269  	k, err := ecdsa.NewPrivateKey(c, data, q.Bytes())
 270  	if err != nil {
 271  		return nil, err
 272  	}
 273  	return privateKeyFromFIPS(curve, k)
 274  }
 275  
 276  // Bytes encodes the private key as a fixed-length big-endian integer according
 277  // to SEC 1, Version 2.0, Section 2.3.6 (sometimes referred to as the raw
 278  // format). It returns an error if the private key is invalid.
 279  //
 280  // PrivateKey.Curve must be one of [elliptic.P224], [elliptic.P256],
 281  // [elliptic.P384], or [elliptic.P521], or Bytes returns an error.
 282  //
 283  // Bytes returns the same format as [ecdh.PrivateKey.Bytes] does for NIST curves.
 284  //
 285  // Note that private keys are more commonly encoded in ASN.1 or PKCS#8 format,
 286  // which can be generated with [crypto/x509.MarshalECPrivateKey] or
 287  // [crypto/x509.MarshalPKCS8PrivateKey] (and [encoding/pem]).
 288  func (priv *PrivateKey) Bytes() ([]byte, error) {
 289  	switch priv.Curve {
 290  	case elliptic.P224():
 291  		return privateKeyBytes(ecdsa.P224(), priv)
 292  	case elliptic.P256():
 293  		return privateKeyBytes(ecdsa.P256(), priv)
 294  	case elliptic.P384():
 295  		return privateKeyBytes(ecdsa.P384(), priv)
 296  	case elliptic.P521():
 297  		return privateKeyBytes(ecdsa.P521(), priv)
 298  	default:
 299  		return nil, errors.New("ecdsa: curve not supported by PrivateKey.Bytes")
 300  	}
 301  }
 302  
 303  func privateKeyBytes[P ecdsa.Point[P]](c *ecdsa.Curve[P], priv *PrivateKey) ([]byte, error) {
 304  	k, err := privateKeyToFIPS(c, priv)
 305  	if err != nil {
 306  		return nil, err
 307  	}
 308  	return k.Bytes(), nil
 309  }
 310  
 311  // Sign signs a hash (which should be the result of hashing a larger message
 312  // with opts.HashFunc()) using the private key, priv. If the hash is longer than
 313  // the bit-length of the private key's curve order, the hash will be truncated
 314  // to that length. It returns the ASN.1 encoded signature, like [SignASN1].
 315  //
 316  // If rand is not nil, the signature is randomized. Most applications should use
 317  // [crypto/rand.Reader] as rand. Note that the returned signature does not
 318  // depend deterministically on the bytes read from rand, and may change between
 319  // calls and/or between versions.
 320  //
 321  // If rand is nil, Sign will produce a deterministic signature according to RFC
 322  // 6979. When producing a deterministic signature, opts.HashFunc() must be the
 323  // function used to produce digest and priv.Curve must be one of
 324  // [elliptic.P224], [elliptic.P256], [elliptic.P384], or [elliptic.P521].
 325  func (priv *PrivateKey) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) ([]byte, error) {
 326  	if rand == nil {
 327  		return signRFC6979(priv, digest, opts)
 328  	}
 329  	return SignASN1(rand, priv, digest)
 330  }
 331  
 332  // GenerateKey generates a new ECDSA private key for the specified curve.
 333  //
 334  // Most applications should use [crypto/rand.Reader] as rand. Note that the
 335  // returned key does not depend deterministically on the bytes read from rand,
 336  // and may change between calls and/or between versions.
 337  func GenerateKey(c elliptic.Curve, rand io.Reader) (*PrivateKey, error) {
 338  	randutil.MaybeReadByte(rand)
 339  
 340  	if boring.Enabled && rand == boring.RandReader {
 341  		x, y, d, err := boring.GenerateKeyECDSA(c.Params().Name)
 342  		if err != nil {
 343  			return nil, err
 344  		}
 345  		return &PrivateKey{PublicKey: PublicKey{Curve: c, X: bbig.Dec(x), Y: bbig.Dec(y)}, D: bbig.Dec(d)}, nil
 346  	}
 347  	boring.UnreachableExceptTests()
 348  
 349  	switch c.Params() {
 350  	case elliptic.P224().Params():
 351  		return generateFIPS(c, ecdsa.P224(), rand)
 352  	case elliptic.P256().Params():
 353  		return generateFIPS(c, ecdsa.P256(), rand)
 354  	case elliptic.P384().Params():
 355  		return generateFIPS(c, ecdsa.P384(), rand)
 356  	case elliptic.P521().Params():
 357  		return generateFIPS(c, ecdsa.P521(), rand)
 358  	default:
 359  		return generateLegacy(c, rand)
 360  	}
 361  }
 362  
 363  func generateFIPS[P ecdsa.Point[P]](curve elliptic.Curve, c *ecdsa.Curve[P], rand io.Reader) (*PrivateKey, error) {
 364  	if fips140only.Enabled && !fips140only.ApprovedRandomReader(rand) {
 365  		return nil, errors.New("crypto/ecdsa: only crypto/rand.Reader is allowed in FIPS 140-only mode")
 366  	}
 367  	privateKey, err := ecdsa.GenerateKey(c, rand)
 368  	if err != nil {
 369  		return nil, err
 370  	}
 371  	return privateKeyFromFIPS(curve, privateKey)
 372  }
 373  
 374  // errNoAsm is returned by signAsm and verifyAsm when the assembly
 375  // implementation is not available.
 376  var errNoAsm = errors.New("no assembly implementation available")
 377  
 378  // SignASN1 signs a hash (which should be the result of hashing a larger message)
 379  // using the private key, priv. If the hash is longer than the bit-length of the
 380  // private key's curve order, the hash will be truncated to that length. It
 381  // returns the ASN.1 encoded signature.
 382  //
 383  // The signature is randomized. Most applications should use [crypto/rand.Reader]
 384  // as rand. Note that the returned signature does not depend deterministically on
 385  // the bytes read from rand, and may change between calls and/or between versions.
 386  func SignASN1(rand io.Reader, priv *PrivateKey, hash []byte) ([]byte, error) {
 387  	randutil.MaybeReadByte(rand)
 388  
 389  	if boring.Enabled && rand == boring.RandReader {
 390  		b, err := boringPrivateKey(priv)
 391  		if err != nil {
 392  			return nil, err
 393  		}
 394  		return boring.SignMarshalECDSA(b, hash)
 395  	}
 396  	boring.UnreachableExceptTests()
 397  
 398  	switch priv.Curve.Params() {
 399  	case elliptic.P224().Params():
 400  		return signFIPS(ecdsa.P224(), priv, rand, hash)
 401  	case elliptic.P256().Params():
 402  		return signFIPS(ecdsa.P256(), priv, rand, hash)
 403  	case elliptic.P384().Params():
 404  		return signFIPS(ecdsa.P384(), priv, rand, hash)
 405  	case elliptic.P521().Params():
 406  		return signFIPS(ecdsa.P521(), priv, rand, hash)
 407  	default:
 408  		return signLegacy(priv, rand, hash)
 409  	}
 410  }
 411  
 412  func signFIPS[P ecdsa.Point[P]](c *ecdsa.Curve[P], priv *PrivateKey, rand io.Reader, hash []byte) ([]byte, error) {
 413  	if fips140only.Enabled && !fips140only.ApprovedRandomReader(rand) {
 414  		return nil, errors.New("crypto/ecdsa: only crypto/rand.Reader is allowed in FIPS 140-only mode")
 415  	}
 416  	k, err := privateKeyToFIPS(c, priv)
 417  	if err != nil {
 418  		return nil, err
 419  	}
 420  	// Always using SHA-512 instead of the hash that computed hash is
 421  	// technically a violation of draft-irtf-cfrg-det-sigs-with-noise-04 but in
 422  	// our API we don't get to know what it was, and this has no security impact.
 423  	sig, err := ecdsa.Sign(c, sha512.New, k, rand, hash)
 424  	if err != nil {
 425  		return nil, err
 426  	}
 427  	return encodeSignature(sig.R, sig.S)
 428  }
 429  
 430  func signRFC6979(priv *PrivateKey, hash []byte, opts crypto.SignerOpts) ([]byte, error) {
 431  	if opts == nil {
 432  		return nil, errors.New("ecdsa: Sign called with nil opts")
 433  	}
 434  	h := opts.HashFunc()
 435  	if h.Size() != len(hash) {
 436  		return nil, errors.New("ecdsa: hash length does not match hash function")
 437  	}
 438  	switch priv.Curve.Params() {
 439  	case elliptic.P224().Params():
 440  		return signFIPSDeterministic(ecdsa.P224(), h, priv, hash)
 441  	case elliptic.P256().Params():
 442  		return signFIPSDeterministic(ecdsa.P256(), h, priv, hash)
 443  	case elliptic.P384().Params():
 444  		return signFIPSDeterministic(ecdsa.P384(), h, priv, hash)
 445  	case elliptic.P521().Params():
 446  		return signFIPSDeterministic(ecdsa.P521(), h, priv, hash)
 447  	default:
 448  		return nil, errors.New("ecdsa: curve not supported by deterministic signatures")
 449  	}
 450  }
 451  
 452  func signFIPSDeterministic[P ecdsa.Point[P]](c *ecdsa.Curve[P], hashFunc crypto.Hash, priv *PrivateKey, hash []byte) ([]byte, error) {
 453  	k, err := privateKeyToFIPS(c, priv)
 454  	if err != nil {
 455  		return nil, err
 456  	}
 457  	h := fips140hash.UnwrapNew(hashFunc.New)
 458  	if fips140only.Enabled && !fips140only.ApprovedHash(h()) {
 459  		return nil, errors.New("crypto/ecdsa: use of hash functions other than SHA-2 or SHA-3 is not allowed in FIPS 140-only mode")
 460  	}
 461  	sig, err := ecdsa.SignDeterministic(c, h, k, hash)
 462  	if err != nil {
 463  		return nil, err
 464  	}
 465  	return encodeSignature(sig.R, sig.S)
 466  }
 467  
 468  func encodeSignature(r, s []byte) ([]byte, error) {
 469  	var b cryptobyte.Builder
 470  	b.AddASN1(asn1.SEQUENCE, func(b *cryptobyte.Builder) {
 471  		addASN1IntBytes(b, r)
 472  		addASN1IntBytes(b, s)
 473  	})
 474  	return b.Bytes()
 475  }
 476  
 477  // addASN1IntBytes encodes in ASN.1 a positive integer represented as
 478  // a big-endian byte slice with zero or more leading zeroes.
 479  func addASN1IntBytes(b *cryptobyte.Builder, bytes []byte) {
 480  	for len(bytes) > 0 && bytes[0] == 0 {
 481  		bytes = bytes[1:]
 482  	}
 483  	if len(bytes) == 0 {
 484  		b.SetError(errors.New("invalid integer"))
 485  		return
 486  	}
 487  	b.AddASN1(asn1.INTEGER, func(c *cryptobyte.Builder) {
 488  		if bytes[0]&0x80 != 0 {
 489  			c.AddUint8(0)
 490  		}
 491  		c.AddBytes(bytes)
 492  	})
 493  }
 494  
 495  // VerifyASN1 verifies the ASN.1 encoded signature, sig, of hash using the
 496  // public key, pub. Its return value records whether the signature is valid.
 497  //
 498  // The inputs are not considered confidential, and may leak through timing side
 499  // channels, or if an attacker has control of part of the inputs.
 500  func VerifyASN1(pub *PublicKey, hash, sig []byte) bool {
 501  	if boring.Enabled {
 502  		key, err := boringPublicKey(pub)
 503  		if err != nil {
 504  			return false
 505  		}
 506  		return boring.VerifyECDSA(key, hash, sig)
 507  	}
 508  	boring.UnreachableExceptTests()
 509  
 510  	switch pub.Curve.Params() {
 511  	case elliptic.P224().Params():
 512  		return verifyFIPS(ecdsa.P224(), pub, hash, sig)
 513  	case elliptic.P256().Params():
 514  		return verifyFIPS(ecdsa.P256(), pub, hash, sig)
 515  	case elliptic.P384().Params():
 516  		return verifyFIPS(ecdsa.P384(), pub, hash, sig)
 517  	case elliptic.P521().Params():
 518  		return verifyFIPS(ecdsa.P521(), pub, hash, sig)
 519  	default:
 520  		return verifyLegacy(pub, hash, sig)
 521  	}
 522  }
 523  
 524  func verifyFIPS[P ecdsa.Point[P]](c *ecdsa.Curve[P], pub *PublicKey, hash, sig []byte) bool {
 525  	r, s, err := parseSignature(sig)
 526  	if err != nil {
 527  		return false
 528  	}
 529  	k, err := publicKeyToFIPS(c, pub)
 530  	if err != nil {
 531  		return false
 532  	}
 533  	if err := ecdsa.Verify(c, k, hash, &ecdsa.Signature{R: r, S: s}); err != nil {
 534  		return false
 535  	}
 536  	return true
 537  }
 538  
 539  func parseSignature(sig []byte) (r, s []byte, err error) {
 540  	var inner cryptobyte.String
 541  	input := cryptobyte.String(sig)
 542  	if !input.ReadASN1(&inner, asn1.SEQUENCE) ||
 543  		!input.Empty() ||
 544  		!inner.ReadASN1Integer(&r) ||
 545  		!inner.ReadASN1Integer(&s) ||
 546  		!inner.Empty() {
 547  		return nil, nil, errors.New("invalid ASN.1")
 548  	}
 549  	return r, s, nil
 550  }
 551  
 552  func publicKeyFromFIPS(curve elliptic.Curve, pub *ecdsa.PublicKey) (*PublicKey, error) {
 553  	x, y, err := pointToAffine(curve, pub.Bytes())
 554  	if err != nil {
 555  		return nil, err
 556  	}
 557  	return &PublicKey{Curve: curve, X: x, Y: y}, nil
 558  }
 559  
 560  func privateKeyFromFIPS(curve elliptic.Curve, priv *ecdsa.PrivateKey) (*PrivateKey, error) {
 561  	pub, err := publicKeyFromFIPS(curve, priv.PublicKey())
 562  	if err != nil {
 563  		return nil, err
 564  	}
 565  	return &PrivateKey{PublicKey: *pub, D: (&big.Int{}).SetBytes(priv.Bytes())}, nil
 566  }
 567  
 568  func publicKeyToFIPS[P ecdsa.Point[P]](c *ecdsa.Curve[P], pub *PublicKey) (*ecdsa.PublicKey, error) {
 569  	Q, err := pointFromAffine(pub.Curve, pub.X, pub.Y)
 570  	if err != nil {
 571  		return nil, err
 572  	}
 573  	return ecdsa.NewPublicKey(c, Q)
 574  }
 575  
 576  var privateKeyCache fips140cache.Cache[PrivateKey, ecdsa.PrivateKey]
 577  
 578  func privateKeyToFIPS[P ecdsa.Point[P]](c *ecdsa.Curve[P], priv *PrivateKey) (*ecdsa.PrivateKey, error) {
 579  	Q, err := pointFromAffine(priv.Curve, priv.X, priv.Y)
 580  	if err != nil {
 581  		return nil, err
 582  	}
 583  	return privateKeyCache.Get(priv, func() (*ecdsa.PrivateKey, error) {
 584  		return ecdsa.NewPrivateKey(c, priv.D.Bytes(), Q)
 585  	}, func(k *ecdsa.PrivateKey) bool {
 586  		return subtle.ConstantTimeCompare(k.PublicKey().Bytes(), Q) == 1 &&
 587  			leftPadBytesEqual(k.Bytes(), priv.D.Bytes())
 588  	})
 589  }
 590  
 591  func leftPadBytesEqual(a, b []byte) bool {
 592  	if len(a) < len(b) {
 593  		a, b = b, a
 594  	}
 595  	if len(a) > len(b) {
 596  		x := []byte{:0:66 /* enough for a P-521 private key */}
 597  		x = append(x, []byte{:len(a)-len(b)}...)
 598  		x = append(x, b...)
 599  		b = x
 600  	}
 601  	return subtle.ConstantTimeCompare(a, b) == 1
 602  }
 603  
 604  // pointFromAffine is used to convert the PublicKey to a nistec SetBytes input.
 605  func pointFromAffine(curve elliptic.Curve, x, y *big.Int) ([]byte, error) {
 606  	bitSize := curve.Params().BitSize
 607  	// Reject values that would not get correctly encoded.
 608  	if x.Sign() < 0 || y.Sign() < 0 {
 609  		return nil, errors.New("negative coordinate")
 610  	}
 611  	if x.BitLen() > bitSize || y.BitLen() > bitSize {
 612  		return nil, errors.New("overflowing coordinate")
 613  	}
 614  	// Encode the coordinates and let SetBytes reject invalid points.
 615  	byteLen := (bitSize + 7) / 8
 616  	buf := []byte{:1+2*byteLen}
 617  	buf[0] = 4 // uncompressed point
 618  	x.FillBytes(buf[1 : 1+byteLen])
 619  	y.FillBytes(buf[1+byteLen : 1+2*byteLen])
 620  	return buf, nil
 621  }
 622  
 623  // pointToAffine is used to convert a nistec Bytes encoding to a PublicKey.
 624  func pointToAffine(curve elliptic.Curve, p []byte) (x, y *big.Int, err error) {
 625  	if len(p) == 1 && p[0] == 0 {
 626  		// This is the encoding of the point at infinity.
 627  		return nil, nil, errors.New("ecdsa: public key point is the infinity")
 628  	}
 629  	byteLen := (curve.Params().BitSize + 7) / 8
 630  	x = (&big.Int{}).SetBytes(p[1 : 1+byteLen])
 631  	y = (&big.Int{}).SetBytes(p[1+byteLen:])
 632  	return x, y, nil
 633  }
 634