Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/boringssl.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'ssl/test/runner/key_agreement.go')
-rw-r--r--ssl/test/runner/key_agreement.go215
1 files changed, 198 insertions, 17 deletions
diff --git a/ssl/test/runner/key_agreement.go b/ssl/test/runner/key_agreement.go
index 9ecd2e56..5e5d976d 100644
--- a/ssl/test/runner/key_agreement.go
+++ b/ssl/test/runner/key_agreement.go
@@ -21,6 +21,7 @@ import (
"math/big"
"./curve25519"
+ "./newhope"
)
var errClientKeyExchange = errors.New("tls: invalid ClientKeyExchange message")
@@ -252,13 +253,16 @@ func pickTLS12HashForSignature(sigType uint8, clientList, serverList []signature
// A ecdhCurve is an instance of ECDH-style key agreement for TLS.
type ecdhCurve interface {
- // generateKeypair generates a keypair using rand. It returns the
- // encoded public key.
- generateKeypair(rand io.Reader) (publicKey []byte, err error)
+ // offer generates a keypair using rand. It returns the encoded |publicKey|.
+ offer(rand io.Reader) (publicKey []byte, err error)
- // computeSecret performs a key exchange against peerKey and returns
- // the resulting shared secret.
- computeSecret(peerKey []byte) (preMasterSecret []byte, err error)
+ // accept responds to the |peerKey| generated by |offer| with the acceptor's
+ // |publicKey|, and returns agreed-upon |preMasterSecret| to the acceptor.
+ accept(rand io.Reader, peerKey []byte) (publicKey []byte, preMasterSecret []byte, err error)
+
+ // finish returns the computed |preMasterSecret|, given the |peerKey|
+ // generated by |accept|.
+ finish(peerKey []byte) (preMasterSecret []byte, err error)
}
// ellipticECDHCurve implements ecdhCurve with an elliptic.Curve.
@@ -267,7 +271,7 @@ type ellipticECDHCurve struct {
privateKey []byte
}
-func (e *ellipticECDHCurve) generateKeypair(rand io.Reader) (publicKey []byte, err error) {
+func (e *ellipticECDHCurve) offer(rand io.Reader) (publicKey []byte, err error) {
var x, y *big.Int
e.privateKey, x, y, err = elliptic.GenerateKey(e.curve, rand)
if err != nil {
@@ -276,7 +280,19 @@ func (e *ellipticECDHCurve) generateKeypair(rand io.Reader) (publicKey []byte, e
return elliptic.Marshal(e.curve, x, y), nil
}
-func (e *ellipticECDHCurve) computeSecret(peerKey []byte) (preMasterSecret []byte, err error) {
+func (e *ellipticECDHCurve) accept(rand io.Reader, peerKey []byte) (publicKey []byte, preMasterSecret []byte, err error) {
+ publicKey, err = e.offer(rand)
+ if err != nil {
+ return nil, nil, err
+ }
+ preMasterSecret, err = e.finish(peerKey)
+ if err != nil {
+ return nil, nil, err
+ }
+ return
+}
+
+func (e *ellipticECDHCurve) finish(peerKey []byte) (preMasterSecret []byte, err error) {
x, y := elliptic.Unmarshal(e.curve, peerKey)
if x == nil {
return nil, errors.New("tls: invalid peer key")
@@ -294,7 +310,7 @@ type x25519ECDHCurve struct {
privateKey [32]byte
}
-func (e *x25519ECDHCurve) generateKeypair(rand io.Reader) (publicKey []byte, err error) {
+func (e *x25519ECDHCurve) offer(rand io.Reader) (publicKey []byte, err error) {
_, err = io.ReadFull(rand, e.privateKey[:])
if err != nil {
return
@@ -304,7 +320,19 @@ func (e *x25519ECDHCurve) generateKeypair(rand io.Reader) (publicKey []byte, err
return out[:], nil
}
-func (e *x25519ECDHCurve) computeSecret(peerKey []byte) (preMasterSecret []byte, err error) {
+func (e *x25519ECDHCurve) accept(rand io.Reader, peerKey []byte) (publicKey []byte, preMasterSecret []byte, err error) {
+ publicKey, err = e.offer(rand)
+ if err != nil {
+ return nil, nil, err
+ }
+ preMasterSecret, err = e.finish(peerKey)
+ if err != nil {
+ return nil, nil, err
+ }
+ return
+}
+
+func (e *x25519ECDHCurve) finish(peerKey []byte) (preMasterSecret []byte, err error) {
if len(peerKey) != 32 {
return nil, errors.New("tls: invalid peer key")
}
@@ -321,6 +349,66 @@ func (e *x25519ECDHCurve) computeSecret(peerKey []byte) (preMasterSecret []byte,
return out[:], nil
}
+// cecpq1Curve is combined elliptic curve (X25519) and post-quantum (new hope) key
+// agreement.
+type cecpq1Curve struct {
+ x25519 *x25519ECDHCurve
+ newhope *newhope.Poly
+}
+
+func (e *cecpq1Curve) offer(rand io.Reader) (publicKey []byte, err error) {
+ var x25519OfferMsg, newhopeOfferMsg []byte
+
+ e.x25519 = new(x25519ECDHCurve)
+ if x25519OfferMsg, err = e.x25519.offer(rand); err != nil {
+ return nil, err
+ }
+
+ newhopeOfferMsg, e.newhope = newhope.Offer(rand)
+
+ return append(x25519OfferMsg, newhopeOfferMsg[:]...), nil
+}
+
+func (e *cecpq1Curve) accept(rand io.Reader, peerKey []byte) (publicKey []byte, preMasterSecret []byte, err error) {
+ if len(peerKey) != 32+newhope.OfferMsgLen {
+ return nil, nil, errors.New("cecpq1: invalid offer message")
+ }
+
+ var x25519AcceptMsg, newhopeAcceptMsg []byte
+ var x25519Secret []byte
+ var newhopeSecret newhope.Key
+
+ x25519 := new(x25519ECDHCurve)
+ if x25519AcceptMsg, x25519Secret, err = x25519.accept(rand, peerKey[:32]); err != nil {
+ return nil, nil, err
+ }
+
+ if newhopeSecret, newhopeAcceptMsg, err = newhope.Accept(rand, peerKey[32:]); err != nil {
+ return nil, nil, err
+ }
+
+ return append(x25519AcceptMsg, newhopeAcceptMsg[:]...), append(x25519Secret, newhopeSecret[:]...), nil
+}
+
+func (e *cecpq1Curve) finish(peerKey []byte) (preMasterSecret []byte, err error) {
+ if len(peerKey) != 32+newhope.AcceptMsgLen {
+ return nil, errors.New("cecpq1: invalid accept message")
+ }
+
+ var x25519Secret []byte
+ var newhopeSecret newhope.Key
+
+ if x25519Secret, err = e.x25519.finish(peerKey[:32]); err != nil {
+ return nil, err
+ }
+
+ if newhopeSecret, err = e.newhope.Finish(peerKey[32:]); err != nil {
+ return nil, err
+ }
+
+ return append(x25519Secret, newhopeSecret[:]...), nil
+}
+
func curveForCurveID(id CurveID) (ecdhCurve, bool) {
switch id {
case CurveP224:
@@ -551,7 +639,7 @@ NextCandidate:
return nil, errors.New("tls: preferredCurves includes unsupported curve")
}
- publicKey, err := ka.curve.generateKeypair(config.rand())
+ publicKey, err := ka.curve.offer(config.rand())
if err != nil {
return nil, err
}
@@ -566,6 +654,9 @@ NextCandidate:
}
serverECDHParams[3] = byte(len(publicKey))
copy(serverECDHParams[4:], publicKey)
+ if config.Bugs.InvalidECDHPoint {
+ serverECDHParams[4] ^= 0xff
+ }
return ka.auth.signParameters(config, cert, clientHello, hello, serverECDHParams)
}
@@ -574,7 +665,7 @@ func (ka *ecdheKeyAgreement) processClientKeyExchange(config *Config, cert *Cert
if len(ckx.ciphertext) == 0 || int(ckx.ciphertext[0]) != len(ckx.ciphertext)-1 {
return nil, errClientKeyExchange
}
- return ka.curve.computeSecret(ckx.ciphertext[1:])
+ return ka.curve.finish(ckx.ciphertext[1:])
}
func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
@@ -609,11 +700,7 @@ func (ka *ecdheKeyAgreement) generateClientKeyExchange(config *Config, clientHel
return nil, nil, errors.New("missing ServerKeyExchange message")
}
- publicKey, err := ka.curve.generateKeypair(config.rand())
- if err != nil {
- return nil, nil, err
- }
- preMasterSecret, err := ka.curve.computeSecret(ka.peerKey)
+ publicKey, preMasterSecret, err := ka.curve.accept(config.rand(), ka.peerKey)
if err != nil {
return nil, nil, err
}
@@ -622,6 +709,100 @@ func (ka *ecdheKeyAgreement) generateClientKeyExchange(config *Config, clientHel
ckx.ciphertext = make([]byte, 1+len(publicKey))
ckx.ciphertext[0] = byte(len(publicKey))
copy(ckx.ciphertext[1:], publicKey)
+ if config.Bugs.InvalidECDHPoint {
+ ckx.ciphertext[1] ^= 0xff
+ }
+
+ return preMasterSecret, ckx, nil
+}
+
+// cecpq1RSAKeyAgreement is like an ecdheKeyAgreement, but using the cecpq1Curve
+// pseudo-curve, and without any parameters (e.g. curve name) other than the
+// keys being exchanged. The signature may either be ECDSA or RSA.
+type cecpq1KeyAgreement struct {
+ auth keyAgreementAuthentication
+ curve ecdhCurve
+ peerKey []byte
+}
+
+func (ka *cecpq1KeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
+ ka.curve = &cecpq1Curve{}
+ publicKey, err := ka.curve.offer(config.rand())
+ if err != nil {
+ return nil, err
+ }
+
+ if config.Bugs.CECPQ1BadX25519Part {
+ publicKey[0] ^= 1
+ }
+ if config.Bugs.CECPQ1BadNewhopePart {
+ publicKey[32] ^= 1
+ publicKey[33] ^= 1
+ publicKey[34] ^= 1
+ publicKey[35] ^= 1
+ }
+
+ var params []byte
+ params = append(params, byte(len(publicKey)>>8))
+ params = append(params, byte(len(publicKey)&0xff))
+ params = append(params, publicKey[:]...)
+
+ return ka.auth.signParameters(config, cert, clientHello, hello, params)
+}
+
+func (ka *cecpq1KeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
+ if len(ckx.ciphertext) < 2 {
+ return nil, errClientKeyExchange
+ }
+ peerKeyLen := int(ckx.ciphertext[0])<<8 + int(ckx.ciphertext[1])
+ peerKey := ckx.ciphertext[2:]
+ if peerKeyLen != len(peerKey) {
+ return nil, errClientKeyExchange
+ }
+ return ka.curve.finish(peerKey)
+}
+
+func (ka *cecpq1KeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
+ if len(skx.key) < 2 {
+ return errServerKeyExchange
+ }
+ peerKeyLen := int(skx.key[0])<<8 + int(skx.key[1])
+ // Save the peer key for later.
+ if len(skx.key) < 2+peerKeyLen {
+ return errServerKeyExchange
+ }
+ ka.peerKey = skx.key[2 : 2+peerKeyLen]
+ if peerKeyLen != len(ka.peerKey) {
+ return errServerKeyExchange
+ }
+
+ // Check the signature.
+ params := skx.key[:2+peerKeyLen]
+ sig := skx.key[2+peerKeyLen:]
+ return ka.auth.verifyParameters(config, clientHello, serverHello, cert, params, sig)
+}
+
+func (ka *cecpq1KeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
+ curve := &cecpq1Curve{}
+ publicKey, preMasterSecret, err := curve.accept(config.rand(), ka.peerKey)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ if config.Bugs.CECPQ1BadX25519Part {
+ publicKey[0] ^= 1
+ }
+ if config.Bugs.CECPQ1BadNewhopePart {
+ publicKey[32] ^= 1
+ publicKey[33] ^= 1
+ publicKey[34] ^= 1
+ publicKey[35] ^= 1
+ }
+
+ ckx := new(clientKeyExchangeMsg)
+ ckx.ciphertext = append(ckx.ciphertext, byte(len(publicKey)>>8))
+ ckx.ciphertext = append(ckx.ciphertext, byte(len(publicKey)&0xff))
+ ckx.ciphertext = append(ckx.ciphertext, publicKey[:]...)
return preMasterSecret, ckx, nil
}