src/pkg/crypto/tls/key_agreement.go - The Go Programming Language

Golang

Source file src/pkg/crypto/tls/key_agreement.go

     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	}