...

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/md5"
    10		"crypto/rsa"
    11		"crypto/sha1"
    12		"crypto/x509"
    13		"errors"
    14		"io"
    15	)
    16	
    17	var errClientKeyExchange = errors.New("tls: invalid ClientKeyExchange message")
    18	var errServerKeyExchange = errors.New("tls: invalid ServerKeyExchange message")
    19	
    20	// rsaKeyAgreement implements the standard TLS key agreement where the client
    21	// encrypts the pre-master secret to the server's public key.
    22	type rsaKeyAgreement struct{}
    23	
    24	func (ka rsaKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
    25		return nil, nil
    26	}
    27	
    28	func (ka rsaKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
    29		if len(ckx.ciphertext) < 2 {
    30			return nil, errClientKeyExchange
    31		}
    32	
    33		ciphertext := ckx.ciphertext
    34		if version != VersionSSL30 {
    35			ciphertextLen := int(ckx.ciphertext[0])<<8 | int(ckx.ciphertext[1])
    36			if ciphertextLen != len(ckx.ciphertext)-2 {
    37				return nil, errClientKeyExchange
    38			}
    39			ciphertext = ckx.ciphertext[2:]
    40		}
    41		priv, ok := cert.PrivateKey.(crypto.Decrypter)
    42		if !ok {
    43			return nil, errors.New("tls: certificate private key does not implement crypto.Decrypter")
    44		}
    45		// Perform constant time RSA PKCS#1 v1.5 decryption
    46		preMasterSecret, err := priv.Decrypt(config.rand(), ciphertext, &rsa.PKCS1v15DecryptOptions{SessionKeyLen: 48})
    47		if err != nil {
    48			return nil, err
    49		}
    50		// We don't check the version number in the premaster secret. For one,
    51		// by checking it, we would leak information about the validity of the
    52		// encrypted pre-master secret. Secondly, it provides only a small
    53		// benefit against a downgrade attack and some implementations send the
    54		// wrong version anyway. See the discussion at the end of section
    55		// 7.4.7.1 of RFC 4346.
    56		return preMasterSecret, nil
    57	}
    58	
    59	func (ka rsaKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
    60		return errors.New("tls: unexpected ServerKeyExchange")
    61	}
    62	
    63	func (ka rsaKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
    64		preMasterSecret := make([]byte, 48)
    65		preMasterSecret[0] = byte(clientHello.vers >> 8)
    66		preMasterSecret[1] = byte(clientHello.vers)
    67		_, err := io.ReadFull(config.rand(), preMasterSecret[2:])
    68		if err != nil {
    69			return nil, nil, err
    70		}
    71	
    72		encrypted, err := rsa.EncryptPKCS1v15(config.rand(), cert.PublicKey.(*rsa.PublicKey), preMasterSecret)
    73		if err != nil {
    74			return nil, nil, err
    75		}
    76		ckx := new(clientKeyExchangeMsg)
    77		ckx.ciphertext = make([]byte, len(encrypted)+2)
    78		ckx.ciphertext[0] = byte(len(encrypted) >> 8)
    79		ckx.ciphertext[1] = byte(len(encrypted))
    80		copy(ckx.ciphertext[2:], encrypted)
    81		return preMasterSecret, ckx, nil
    82	}
    83	
    84	// sha1Hash calculates a SHA1 hash over the given byte slices.
    85	func sha1Hash(slices [][]byte) []byte {
    86		hsha1 := sha1.New()
    87		for _, slice := range slices {
    88			hsha1.Write(slice)
    89		}
    90		return hsha1.Sum(nil)
    91	}
    92	
    93	// md5SHA1Hash implements TLS 1.0's hybrid hash function which consists of the
    94	// concatenation of an MD5 and SHA1 hash.
    95	func md5SHA1Hash(slices [][]byte) []byte {
    96		md5sha1 := make([]byte, md5.Size+sha1.Size)
    97		hmd5 := md5.New()
    98		for _, slice := range slices {
    99			hmd5.Write(slice)
   100		}
   101		copy(md5sha1, hmd5.Sum(nil))
   102		copy(md5sha1[md5.Size:], sha1Hash(slices))
   103		return md5sha1
   104	}
   105	
   106	// hashForServerKeyExchange hashes the given slices and returns their digest
   107	// using the given hash function (for >= TLS 1.2) or using a default based on
   108	// the sigType (for earlier TLS versions). For Ed25519 signatures, which don't
   109	// do pre-hashing, it returns the concatenation of the slices.
   110	func hashForServerKeyExchange(sigType uint8, hashFunc crypto.Hash, version uint16, slices ...[]byte) []byte {
   111		if sigType == signatureEd25519 {
   112			var signed []byte
   113			for _, slice := range slices {
   114				signed = append(signed, slice...)
   115			}
   116			return signed
   117		}
   118		if version >= VersionTLS12 {
   119			h := hashFunc.New()
   120			for _, slice := range slices {
   121				h.Write(slice)
   122			}
   123			digest := h.Sum(nil)
   124			return digest
   125		}
   126		if sigType == signatureECDSA {
   127			return sha1Hash(slices)
   128		}
   129		return md5SHA1Hash(slices)
   130	}
   131	
   132	// ecdheKeyAgreement implements a TLS key agreement where the server
   133	// generates an ephemeral EC public/private key pair and signs it. The
   134	// pre-master secret is then calculated using ECDH. The signature may
   135	// be ECDSA, Ed25519 or RSA.
   136	type ecdheKeyAgreement struct {
   137		version uint16
   138		isRSA   bool
   139		params  ecdheParameters
   140	
   141		// ckx and preMasterSecret are generated in processServerKeyExchange
   142		// and returned in generateClientKeyExchange.
   143		ckx             *clientKeyExchangeMsg
   144		preMasterSecret []byte
   145	}
   146	
   147	func (ka *ecdheKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
   148		preferredCurves := config.curvePreferences()
   149	
   150		var curveID CurveID
   151	NextCandidate:
   152		for _, candidate := range preferredCurves {
   153			for _, c := range clientHello.supportedCurves {
   154				if candidate == c {
   155					curveID = c
   156					break NextCandidate
   157				}
   158			}
   159		}
   160	
   161		if curveID == 0 {
   162			return nil, errors.New("tls: no supported elliptic curves offered")
   163		}
   164		if _, ok := curveForCurveID(curveID); curveID != X25519 && !ok {
   165			return nil, errors.New("tls: CurvePreferences includes unsupported curve")
   166		}
   167	
   168		params, err := generateECDHEParameters(config.rand(), curveID)
   169		if err != nil {
   170			return nil, err
   171		}
   172		ka.params = params
   173	
   174		// See RFC 4492, Section 5.4.
   175		ecdhePublic := params.PublicKey()
   176		serverECDHParams := make([]byte, 1+2+1+len(ecdhePublic))
   177		serverECDHParams[0] = 3 // named curve
   178		serverECDHParams[1] = byte(curveID >> 8)
   179		serverECDHParams[2] = byte(curveID)
   180		serverECDHParams[3] = byte(len(ecdhePublic))
   181		copy(serverECDHParams[4:], ecdhePublic)
   182	
   183		priv, ok := cert.PrivateKey.(crypto.Signer)
   184		if !ok {
   185			return nil, errors.New("tls: certificate private key does not implement crypto.Signer")
   186		}
   187	
   188		signatureAlgorithm, sigType, hashFunc, err := pickSignatureAlgorithm(priv.Public(), clientHello.supportedSignatureAlgorithms, supportedSignatureAlgorithmsTLS12, ka.version)
   189		if err != nil {
   190			return nil, err
   191		}
   192		if (sigType == signaturePKCS1v15 || sigType == signatureRSAPSS) != ka.isRSA {
   193			return nil, errors.New("tls: certificate cannot be used with the selected cipher suite")
   194		}
   195	
   196		signed := hashForServerKeyExchange(sigType, hashFunc, ka.version, clientHello.random, hello.random, serverECDHParams)
   197	
   198		signOpts := crypto.SignerOpts(hashFunc)
   199		if sigType == signatureRSAPSS {
   200			signOpts = &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash, Hash: hashFunc}
   201		}
   202		sig, err := priv.Sign(config.rand(), signed, signOpts)
   203		if err != nil {
   204			return nil, errors.New("tls: failed to sign ECDHE parameters: " + err.Error())
   205		}
   206	
   207		skx := new(serverKeyExchangeMsg)
   208		sigAndHashLen := 0
   209		if ka.version >= VersionTLS12 {
   210			sigAndHashLen = 2
   211		}
   212		skx.key = make([]byte, len(serverECDHParams)+sigAndHashLen+2+len(sig))
   213		copy(skx.key, serverECDHParams)
   214		k := skx.key[len(serverECDHParams):]
   215		if ka.version >= VersionTLS12 {
   216			k[0] = byte(signatureAlgorithm >> 8)
   217			k[1] = byte(signatureAlgorithm)
   218			k = k[2:]
   219		}
   220		k[0] = byte(len(sig) >> 8)
   221		k[1] = byte(len(sig))
   222		copy(k[2:], sig)
   223	
   224		return skx, nil
   225	}
   226	
   227	func (ka *ecdheKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
   228		if len(ckx.ciphertext) == 0 || int(ckx.ciphertext[0]) != len(ckx.ciphertext)-1 {
   229			return nil, errClientKeyExchange
   230		}
   231	
   232		preMasterSecret := ka.params.SharedKey(ckx.ciphertext[1:])
   233		if preMasterSecret == nil {
   234			return nil, errClientKeyExchange
   235		}
   236	
   237		return preMasterSecret, nil
   238	}
   239	
   240	func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
   241		if len(skx.key) < 4 {
   242			return errServerKeyExchange
   243		}
   244		if skx.key[0] != 3 { // named curve
   245			return errors.New("tls: server selected unsupported curve")
   246		}
   247		curveID := CurveID(skx.key[1])<<8 | CurveID(skx.key[2])
   248	
   249		publicLen := int(skx.key[3])
   250		if publicLen+4 > len(skx.key) {
   251			return errServerKeyExchange
   252		}
   253		serverECDHParams := skx.key[:4+publicLen]
   254		publicKey := serverECDHParams[4:]
   255	
   256		sig := skx.key[4+publicLen:]
   257		if len(sig) < 2 {
   258			return errServerKeyExchange
   259		}
   260	
   261		if _, ok := curveForCurveID(curveID); curveID != X25519 && !ok {
   262			return errors.New("tls: server selected unsupported curve")
   263		}
   264	
   265		params, err := generateECDHEParameters(config.rand(), curveID)
   266		if err != nil {
   267			return err
   268		}
   269		ka.params = params
   270	
   271		ka.preMasterSecret = params.SharedKey(publicKey)
   272		if ka.preMasterSecret == nil {
   273			return errServerKeyExchange
   274		}
   275	
   276		ourPublicKey := params.PublicKey()
   277		ka.ckx = new(clientKeyExchangeMsg)
   278		ka.ckx.ciphertext = make([]byte, 1+len(ourPublicKey))
   279		ka.ckx.ciphertext[0] = byte(len(ourPublicKey))
   280		copy(ka.ckx.ciphertext[1:], ourPublicKey)
   281	
   282		var signatureAlgorithm SignatureScheme
   283		if ka.version >= VersionTLS12 {
   284			// handle SignatureAndHashAlgorithm
   285			signatureAlgorithm = SignatureScheme(sig[0])<<8 | SignatureScheme(sig[1])
   286			sig = sig[2:]
   287			if len(sig) < 2 {
   288				return errServerKeyExchange
   289			}
   290		}
   291		_, sigType, hashFunc, err := pickSignatureAlgorithm(cert.PublicKey, []SignatureScheme{signatureAlgorithm}, clientHello.supportedSignatureAlgorithms, ka.version)
   292		if err != nil {
   293			return err
   294		}
   295		if (sigType == signaturePKCS1v15 || sigType == signatureRSAPSS) != ka.isRSA {
   296			return errServerKeyExchange
   297		}
   298	
   299		sigLen := int(sig[0])<<8 | int(sig[1])
   300		if sigLen+2 != len(sig) {
   301			return errServerKeyExchange
   302		}
   303		sig = sig[2:]
   304	
   305		signed := hashForServerKeyExchange(sigType, hashFunc, ka.version, clientHello.random, serverHello.random, serverECDHParams)
   306		return verifyHandshakeSignature(sigType, cert.PublicKey, hashFunc, signed, sig)
   307	}
   308	
   309	func (ka *ecdheKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
   310		if ka.ckx == nil {
   311			return nil, nil, errors.New("tls: missing ServerKeyExchange message")
   312		}
   313	
   314		return ka.preMasterSecret, ka.ckx, nil
   315	}
   316	

View as plain text