nist.mx raw

   1  // Copyright 2022 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 ecdh
   6  
   7  import (
   8  	"bytes"
   9  	"crypto/internal/boring"
  10  	"crypto/internal/fips140/ecdh"
  11  	"crypto/internal/fips140only"
  12  	"errors"
  13  	"io"
  14  )
  15  
  16  type nistCurve struct {
  17  	name          []byte
  18  	generate      func(io.Reader) (*ecdh.PrivateKey, error)
  19  	newPrivateKey func([]byte) (*ecdh.PrivateKey, error)
  20  	newPublicKey  func(publicKey []byte) (*ecdh.PublicKey, error)
  21  	sharedSecret  func(*ecdh.PrivateKey, *ecdh.PublicKey) (sharedSecret []byte, err error)
  22  }
  23  
  24  func (c *nistCurve) String() string {
  25  	return c.name
  26  }
  27  
  28  func (c *nistCurve) GenerateKey(rand io.Reader) (*PrivateKey, error) {
  29  	if boring.Enabled && rand == boring.RandReader {
  30  		key, bytes, err := boring.GenerateKeyECDH(c.name)
  31  		if err != nil {
  32  			return nil, err
  33  		}
  34  		pub, err := key.PublicKey()
  35  		if err != nil {
  36  			return nil, err
  37  		}
  38  		k := &PrivateKey{
  39  			curve:      c,
  40  			privateKey: bytes,
  41  			publicKey:  &PublicKey{curve: c, publicKey: pub.Bytes(), boring: pub},
  42  			boring:     key,
  43  		}
  44  		return k, nil
  45  	}
  46  
  47  	if fips140only.Enabled && !fips140only.ApprovedRandomReader(rand) {
  48  		return nil, errors.New("crypto/ecdh: only crypto/rand.Reader is allowed in FIPS 140-only mode")
  49  	}
  50  
  51  	privateKey, err := c.generate(rand)
  52  	if err != nil {
  53  		return nil, err
  54  	}
  55  
  56  	k := &PrivateKey{
  57  		curve:      c,
  58  		privateKey: privateKey.Bytes(),
  59  		fips:       privateKey,
  60  		publicKey: &PublicKey{
  61  			curve:     c,
  62  			publicKey: privateKey.PublicKey().Bytes(),
  63  			fips:      privateKey.PublicKey(),
  64  		},
  65  	}
  66  	if boring.Enabled {
  67  		bk, err := boring.NewPrivateKeyECDH(c.name, k.privateKey)
  68  		if err != nil {
  69  			return nil, err
  70  		}
  71  		pub, err := bk.PublicKey()
  72  		if err != nil {
  73  			return nil, err
  74  		}
  75  		k.boring = bk
  76  		k.publicKey.boring = pub
  77  	}
  78  	return k, nil
  79  }
  80  
  81  func (c *nistCurve) NewPrivateKey(key []byte) (*PrivateKey, error) {
  82  	if boring.Enabled {
  83  		bk, err := boring.NewPrivateKeyECDH(c.name, key)
  84  		if err != nil {
  85  			return nil, errors.New("crypto/ecdh: invalid private key")
  86  		}
  87  		pub, err := bk.PublicKey()
  88  		if err != nil {
  89  			return nil, errors.New("crypto/ecdh: invalid private key")
  90  		}
  91  		k := &PrivateKey{
  92  			curve:      c,
  93  			privateKey: bytes.Clone(key),
  94  			publicKey:  &PublicKey{curve: c, publicKey: pub.Bytes(), boring: pub},
  95  			boring:     bk,
  96  		}
  97  		return k, nil
  98  	}
  99  
 100  	fk, err := c.newPrivateKey(key)
 101  	if err != nil {
 102  		return nil, err
 103  	}
 104  	k := &PrivateKey{
 105  		curve:      c,
 106  		privateKey: bytes.Clone(key),
 107  		fips:       fk,
 108  		publicKey: &PublicKey{
 109  			curve:     c,
 110  			publicKey: fk.PublicKey().Bytes(),
 111  			fips:      fk.PublicKey(),
 112  		},
 113  	}
 114  	return k, nil
 115  }
 116  
 117  func (c *nistCurve) NewPublicKey(key []byte) (*PublicKey, error) {
 118  	// Reject the point at infinity and compressed encodings.
 119  	// Note that boring.NewPublicKeyECDH would accept them.
 120  	if len(key) == 0 || key[0] != 4 {
 121  		return nil, errors.New("crypto/ecdh: invalid public key")
 122  	}
 123  	k := &PublicKey{
 124  		curve:     c,
 125  		publicKey: bytes.Clone(key),
 126  	}
 127  	if boring.Enabled {
 128  		bk, err := boring.NewPublicKeyECDH(c.name, k.publicKey)
 129  		if err != nil {
 130  			return nil, errors.New("crypto/ecdh: invalid public key")
 131  		}
 132  		k.boring = bk
 133  	} else {
 134  		fk, err := c.newPublicKey(key)
 135  		if err != nil {
 136  			return nil, err
 137  		}
 138  		k.fips = fk
 139  	}
 140  	return k, nil
 141  }
 142  
 143  func (c *nistCurve) ecdh(local *PrivateKey, remote *PublicKey) ([]byte, error) {
 144  	// Note that this function can't return an error, as NewPublicKey rejects
 145  	// invalid points and the point at infinity, and NewPrivateKey rejects
 146  	// invalid scalars and the zero value. BytesX returns an error for the point
 147  	// at infinity, but in a prime order group such as the NIST curves that can
 148  	// only be the result of a scalar multiplication if one of the inputs is the
 149  	// zero scalar or the point at infinity.
 150  
 151  	if boring.Enabled {
 152  		return boring.ECDH(local.boring, remote.boring)
 153  	}
 154  	return c.sharedSecret(local.fips, remote.fips)
 155  }
 156  
 157  // P256 returns a [Curve] which implements NIST P-256 (FIPS 186-3, section D.2.3),
 158  // also known as secp256r1 or prime256v1.
 159  //
 160  // Multiple invocations of this function will return the same value, which can
 161  // be used for equality checks and switch statements.
 162  func P256() Curve { return p256 }
 163  
 164  var p256 = &nistCurve{
 165  	name: "P-256",
 166  	generate: func(r io.Reader) (*ecdh.PrivateKey, error) {
 167  		return ecdh.GenerateKey(ecdh.P256(), r)
 168  	},
 169  	newPrivateKey: func(b []byte) (*ecdh.PrivateKey, error) {
 170  		return ecdh.NewPrivateKey(ecdh.P256(), b)
 171  	},
 172  	newPublicKey: func(publicKey []byte) (*ecdh.PublicKey, error) {
 173  		return ecdh.NewPublicKey(ecdh.P256(), publicKey)
 174  	},
 175  	sharedSecret: func(priv *ecdh.PrivateKey, pub *ecdh.PublicKey) (sharedSecret []byte, err error) {
 176  		return ecdh.ECDH(ecdh.P256(), priv, pub)
 177  	},
 178  }
 179  
 180  // P384 returns a [Curve] which implements NIST P-384 (FIPS 186-3, section D.2.4),
 181  // also known as secp384r1.
 182  //
 183  // Multiple invocations of this function will return the same value, which can
 184  // be used for equality checks and switch statements.
 185  func P384() Curve { return p384 }
 186  
 187  var p384 = &nistCurve{
 188  	name: "P-384",
 189  	generate: func(r io.Reader) (*ecdh.PrivateKey, error) {
 190  		return ecdh.GenerateKey(ecdh.P384(), r)
 191  	},
 192  	newPrivateKey: func(b []byte) (*ecdh.PrivateKey, error) {
 193  		return ecdh.NewPrivateKey(ecdh.P384(), b)
 194  	},
 195  	newPublicKey: func(publicKey []byte) (*ecdh.PublicKey, error) {
 196  		return ecdh.NewPublicKey(ecdh.P384(), publicKey)
 197  	},
 198  	sharedSecret: func(priv *ecdh.PrivateKey, pub *ecdh.PublicKey) (sharedSecret []byte, err error) {
 199  		return ecdh.ECDH(ecdh.P384(), priv, pub)
 200  	},
 201  }
 202  
 203  // P521 returns a [Curve] which implements NIST P-521 (FIPS 186-3, section D.2.5),
 204  // also known as secp521r1.
 205  //
 206  // Multiple invocations of this function will return the same value, which can
 207  // be used for equality checks and switch statements.
 208  func P521() Curve { return p521 }
 209  
 210  var p521 = &nistCurve{
 211  	name: "P-521",
 212  	generate: func(r io.Reader) (*ecdh.PrivateKey, error) {
 213  		return ecdh.GenerateKey(ecdh.P521(), r)
 214  	},
 215  	newPrivateKey: func(b []byte) (*ecdh.PrivateKey, error) {
 216  		return ecdh.NewPrivateKey(ecdh.P521(), b)
 217  	},
 218  	newPublicKey: func(publicKey []byte) (*ecdh.PublicKey, error) {
 219  		return ecdh.NewPublicKey(ecdh.P521(), publicKey)
 220  	},
 221  	sharedSecret: func(priv *ecdh.PrivateKey, pub *ecdh.PublicKey) (sharedSecret []byte, err error) {
 222  		return ecdh.ECDH(ecdh.P521(), priv, pub)
 223  	},
 224  }
 225