github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/pkg/crypto/tls/key_agreement.go (about)

     1  // Copyright 2010 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 tls
     6  
     7  import (
     8  	"crypto"
     9  	"crypto/elliptic"
    10  	"crypto/md5"
    11  	"crypto/rsa"
    12  	"crypto/sha1"
    13  	"crypto/x509"
    14  	"errors"
    15  	"io"
    16  	"math/big"
    17  )
    18  
    19  // rsaKeyAgreement implements the standard TLS key agreement where the client
    20  // encrypts the pre-master secret to the server's public key.
    21  type rsaKeyAgreement struct{}
    22  
    23  func (ka rsaKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
    24  	return nil, nil
    25  }
    26  
    27  func (ka rsaKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
    28  	preMasterSecret := make([]byte, 48)
    29  	_, err := io.ReadFull(config.rand(), preMasterSecret[2:])
    30  	if err != nil {
    31  		return nil, err
    32  	}
    33  
    34  	if len(ckx.ciphertext) < 2 {
    35  		return nil, errors.New("bad ClientKeyExchange")
    36  	}
    37  
    38  	ciphertext := ckx.ciphertext
    39  	if version != versionSSL30 {
    40  		ciphertextLen := int(ckx.ciphertext[0])<<8 | int(ckx.ciphertext[1])
    41  		if ciphertextLen != len(ckx.ciphertext)-2 {
    42  			return nil, errors.New("bad ClientKeyExchange")
    43  		}
    44  		ciphertext = ckx.ciphertext[2:]
    45  	}
    46  
    47  	err = rsa.DecryptPKCS1v15SessionKey(config.rand(), cert.PrivateKey.(*rsa.PrivateKey), ciphertext, preMasterSecret)
    48  	if err != nil {
    49  		return nil, err
    50  	}
    51  	// We don't check the version number in the premaster secret.  For one,
    52  	// by checking it, we would leak information about the validity of the
    53  	// encrypted pre-master secret. Secondly, it provides only a small
    54  	// benefit against a downgrade attack and some implementations send the
    55  	// wrong version anyway. See the discussion at the end of section
    56  	// 7.4.7.1 of RFC 4346.
    57  	return preMasterSecret, nil
    58  }
    59  
    60  func (ka rsaKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
    61  	return errors.New("unexpected ServerKeyExchange")
    62  }
    63  
    64  func (ka rsaKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
    65  	preMasterSecret := make([]byte, 48)
    66  	preMasterSecret[0] = byte(clientHello.vers >> 8)
    67  	preMasterSecret[1] = byte(clientHello.vers)
    68  	_, err := io.ReadFull(config.rand(), preMasterSecret[2:])
    69  	if err != nil {
    70  		return nil, nil, err
    71  	}
    72  
    73  	encrypted, err := rsa.EncryptPKCS1v15(config.rand(), cert.PublicKey.(*rsa.PublicKey), preMasterSecret)
    74  	if err != nil {
    75  		return nil, nil, err
    76  	}
    77  	ckx := new(clientKeyExchangeMsg)
    78  	ckx.ciphertext = make([]byte, len(encrypted)+2)
    79  	ckx.ciphertext[0] = byte(len(encrypted) >> 8)
    80  	ckx.ciphertext[1] = byte(len(encrypted))
    81  	copy(ckx.ciphertext[2:], encrypted)
    82  	return preMasterSecret, ckx, nil
    83  }
    84  
    85  // md5SHA1Hash implements TLS 1.0's hybrid hash function which consists of the
    86  // concatenation of an MD5 and SHA1 hash.
    87  func md5SHA1Hash(slices ...[]byte) []byte {
    88  	md5sha1 := make([]byte, md5.Size+sha1.Size)
    89  	hmd5 := md5.New()
    90  	for _, slice := range slices {
    91  		hmd5.Write(slice)
    92  	}
    93  	copy(md5sha1, hmd5.Sum(nil))
    94  
    95  	hsha1 := sha1.New()
    96  	for _, slice := range slices {
    97  		hsha1.Write(slice)
    98  	}
    99  	copy(md5sha1[md5.Size:], hsha1.Sum(nil))
   100  	return md5sha1
   101  }
   102  
   103  // ecdheRSAKeyAgreement implements a TLS key agreement where the server
   104  // generates a ephemeral EC public/private key pair and signs it. The
   105  // pre-master secret is then calculated using ECDH.
   106  type ecdheRSAKeyAgreement struct {
   107  	privateKey []byte
   108  	curve      elliptic.Curve
   109  	x, y       *big.Int
   110  }
   111  
   112  func (ka *ecdheRSAKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
   113  	var curveid uint16
   114  
   115  Curve:
   116  	for _, c := range clientHello.supportedCurves {
   117  		switch c {
   118  		case curveP256:
   119  			ka.curve = elliptic.P256()
   120  			curveid = c
   121  			break Curve
   122  		case curveP384:
   123  			ka.curve = elliptic.P384()
   124  			curveid = c
   125  			break Curve
   126  		case curveP521:
   127  			ka.curve = elliptic.P521()
   128  			curveid = c
   129  			break Curve
   130  		}
   131  	}
   132  
   133  	if curveid == 0 {
   134  		return nil, errors.New("tls: no supported elliptic curves offered")
   135  	}
   136  
   137  	var x, y *big.Int
   138  	var err error
   139  	ka.privateKey, x, y, err = elliptic.GenerateKey(ka.curve, config.rand())
   140  	if err != nil {
   141  		return nil, err
   142  	}
   143  	ecdhePublic := elliptic.Marshal(ka.curve, x, y)
   144  
   145  	// http://tools.ietf.org/html/rfc4492#section-5.4
   146  	serverECDHParams := make([]byte, 1+2+1+len(ecdhePublic))
   147  	serverECDHParams[0] = 3 // named curve
   148  	serverECDHParams[1] = byte(curveid >> 8)
   149  	serverECDHParams[2] = byte(curveid)
   150  	serverECDHParams[3] = byte(len(ecdhePublic))
   151  	copy(serverECDHParams[4:], ecdhePublic)
   152  
   153  	md5sha1 := md5SHA1Hash(clientHello.random, hello.random, serverECDHParams)
   154  	sig, err := rsa.SignPKCS1v15(config.rand(), cert.PrivateKey.(*rsa.PrivateKey), crypto.MD5SHA1, md5sha1)
   155  	if err != nil {
   156  		return nil, errors.New("failed to sign ECDHE parameters: " + err.Error())
   157  	}
   158  
   159  	skx := new(serverKeyExchangeMsg)
   160  	skx.key = make([]byte, len(serverECDHParams)+2+len(sig))
   161  	copy(skx.key, serverECDHParams)
   162  	k := skx.key[len(serverECDHParams):]
   163  	k[0] = byte(len(sig) >> 8)
   164  	k[1] = byte(len(sig))
   165  	copy(k[2:], sig)
   166  
   167  	return skx, nil
   168  }
   169  
   170  func (ka *ecdheRSAKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
   171  	if len(ckx.ciphertext) == 0 || int(ckx.ciphertext[0]) != len(ckx.ciphertext)-1 {
   172  		return nil, errors.New("bad ClientKeyExchange")
   173  	}
   174  	x, y := elliptic.Unmarshal(ka.curve, ckx.ciphertext[1:])
   175  	if x == nil {
   176  		return nil, errors.New("bad ClientKeyExchange")
   177  	}
   178  	x, _ = ka.curve.ScalarMult(x, y, ka.privateKey)
   179  	preMasterSecret := make([]byte, (ka.curve.Params().BitSize+7)>>3)
   180  	xBytes := x.Bytes()
   181  	copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes)
   182  
   183  	return preMasterSecret, nil
   184  }
   185  
   186  var errServerKeyExchange = errors.New("invalid ServerKeyExchange")
   187  
   188  func (ka *ecdheRSAKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
   189  	if len(skx.key) < 4 {
   190  		return errServerKeyExchange
   191  	}
   192  	if skx.key[0] != 3 { // named curve
   193  		return errors.New("server selected unsupported curve")
   194  	}
   195  	curveid := uint16(skx.key[1])<<8 | uint16(skx.key[2])
   196  
   197  	switch curveid {
   198  	case curveP256:
   199  		ka.curve = elliptic.P256()
   200  	case curveP384:
   201  		ka.curve = elliptic.P384()
   202  	case curveP521:
   203  		ka.curve = elliptic.P521()
   204  	default:
   205  		return errors.New("server selected unsupported curve")
   206  	}
   207  
   208  	publicLen := int(skx.key[3])
   209  	if publicLen+4 > len(skx.key) {
   210  		return errServerKeyExchange
   211  	}
   212  	ka.x, ka.y = elliptic.Unmarshal(ka.curve, skx.key[4:4+publicLen])
   213  	if ka.x == nil {
   214  		return errServerKeyExchange
   215  	}
   216  	serverECDHParams := skx.key[:4+publicLen]
   217  
   218  	sig := skx.key[4+publicLen:]
   219  	if len(sig) < 2 {
   220  		return errServerKeyExchange
   221  	}
   222  	sigLen := int(sig[0])<<8 | int(sig[1])
   223  	if sigLen+2 != len(sig) {
   224  		return errServerKeyExchange
   225  	}
   226  	sig = sig[2:]
   227  
   228  	md5sha1 := md5SHA1Hash(clientHello.random, serverHello.random, serverECDHParams)
   229  	return rsa.VerifyPKCS1v15(cert.PublicKey.(*rsa.PublicKey), crypto.MD5SHA1, md5sha1, sig)
   230  }
   231  
   232  func (ka *ecdheRSAKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
   233  	if ka.curve == nil {
   234  		return nil, nil, errors.New("missing ServerKeyExchange message")
   235  	}
   236  	priv, mx, my, err := elliptic.GenerateKey(ka.curve, config.rand())
   237  	if err != nil {
   238  		return nil, nil, err
   239  	}
   240  	x, _ := ka.curve.ScalarMult(ka.x, ka.y, priv)
   241  	preMasterSecret := make([]byte, (ka.curve.Params().BitSize+7)>>3)
   242  	xBytes := x.Bytes()
   243  	copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes)
   244  
   245  	serialized := elliptic.Marshal(ka.curve, mx, my)
   246  
   247  	ckx := new(clientKeyExchangeMsg)
   248  	ckx.ciphertext = make([]byte, 1+len(serialized))
   249  	ckx.ciphertext[0] = byte(len(serialized))
   250  	copy(ckx.ciphertext[1:], serialized)
   251  
   252  	return preMasterSecret, ckx, nil
   253  }