mirror of
https://github.com/slackhq/nebula.git
synced 2025-01-11 03:48:12 +00:00
e0185c4b01
* Support NIST curve P256 This change adds support for NIST curve P256. When you use `nebula-cert ca` or `nebula-cert keygen`, you can specify `-curve P256` to enable it. The curve to use is based on the curve defined in your CA certificate. Internally, we use ECDSA P256 to sign certificates, and ECDH P256 to do Noise handshakes. P256 is not supported natively in Noise Protocol, so we define `DHP256` in the `noiseutil` package to implement support for it. You cannot have a mixed network of Curve25519 and P256 certificates, since the Noise protocol will only attempt to parse using the Curve defined in the host's certificate. * verify the curves match in VerifyPrivateKey This would have failed anyways once we tried to actually use the bytes in the private key, but its better to detect the issue up front with a better error message. * add cert.Curve argument to Sign method * fix mismerge * use crypto/ecdh This is the preferred method for doing ECDH functions now, and also has a boringcrypto specific codepath. * remove other ecdh uses of crypto/elliptic use crypto/ecdh instead
68 lines
1.7 KiB
Go
68 lines
1.7 KiB
Go
package noiseutil
|
|
|
|
import (
|
|
"crypto/ecdh"
|
|
"crypto/rand"
|
|
"fmt"
|
|
"io"
|
|
|
|
"github.com/flynn/noise"
|
|
)
|
|
|
|
// DHP256 is the NIST P-256 ECDH function
|
|
var DHP256 noise.DHFunc = newNISTCurve("P256", ecdh.P256(), 32)
|
|
|
|
type nistCurve struct {
|
|
name string
|
|
curve ecdh.Curve
|
|
dhLen int
|
|
pubLen int
|
|
}
|
|
|
|
func newNISTCurve(name string, curve ecdh.Curve, byteLen int) nistCurve {
|
|
return nistCurve{
|
|
name: name,
|
|
curve: curve,
|
|
dhLen: byteLen,
|
|
// Standard uncompressed format, type (1 byte) plus both coordinates
|
|
pubLen: 1 + 2*byteLen,
|
|
}
|
|
}
|
|
|
|
func (c nistCurve) GenerateKeypair(rng io.Reader) (noise.DHKey, error) {
|
|
if rng == nil {
|
|
rng = rand.Reader
|
|
}
|
|
privkey, err := c.curve.GenerateKey(rng)
|
|
if err != nil {
|
|
return noise.DHKey{}, err
|
|
}
|
|
pubkey := privkey.PublicKey()
|
|
return noise.DHKey{Private: privkey.Bytes(), Public: pubkey.Bytes()}, nil
|
|
}
|
|
|
|
func (c nistCurve) DH(privkey, pubkey []byte) ([]byte, error) {
|
|
ecdhPubKey, err := c.curve.NewPublicKey(pubkey)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("unable to unmarshal pubkey: %w", err)
|
|
}
|
|
ecdhPrivKey, err := c.curve.NewPrivateKey(privkey)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("unable to unmarshal pubkey: %w", err)
|
|
}
|
|
|
|
return ecdhPrivKey.ECDH(ecdhPubKey)
|
|
}
|
|
|
|
func (c nistCurve) DHLen() int {
|
|
// NOTE: Noise Protocol specifies "DHLen" to represent two things:
|
|
// - The size of the public key
|
|
// - The return size of the DH() function
|
|
// But for standard NIST ECDH, the sizes of these are different.
|
|
// Luckily, the flynn/noise library actually only uses this DHLen()
|
|
// value to represent the public key size, so that is what we are
|
|
// returning here. The length of the DH() return bytes are unaffected by
|
|
// this value here.
|
|
return c.pubLen
|
|
}
|
|
func (c nistCurve) DHName() string { return c.name }
|