...
Run Format

Source file src/crypto/tls/prf.go

     1	// Copyright 2009 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/hmac"
    10		"crypto/md5"
    11		"crypto/sha1"
    12		"crypto/sha256"
    13		"crypto/sha512"
    14		"errors"
    15		"hash"
    16	)
    17	
    18	// Split a premaster secret in two as specified in RFC 4346, section 5.
    19	func splitPreMasterSecret(secret []byte) (s1, s2 []byte) {
    20		s1 = secret[0 : (len(secret)+1)/2]
    21		s2 = secret[len(secret)/2:]
    22		return
    23	}
    24	
    25	// pHash implements the P_hash function, as defined in RFC 4346, section 5.
    26	func pHash(result, secret, seed []byte, hash func() hash.Hash) {
    27		h := hmac.New(hash, secret)
    28		h.Write(seed)
    29		a := h.Sum(nil)
    30	
    31		j := 0
    32		for j < len(result) {
    33			h.Reset()
    34			h.Write(a)
    35			h.Write(seed)
    36			b := h.Sum(nil)
    37			todo := len(b)
    38			if j+todo > len(result) {
    39				todo = len(result) - j
    40			}
    41			copy(result[j:j+todo], b)
    42			j += todo
    43	
    44			h.Reset()
    45			h.Write(a)
    46			a = h.Sum(nil)
    47		}
    48	}
    49	
    50	// prf10 implements the TLS 1.0 pseudo-random function, as defined in RFC 2246, section 5.
    51	func prf10(result, secret, label, seed []byte) {
    52		hashSHA1 := sha1.New
    53		hashMD5 := md5.New
    54	
    55		labelAndSeed := make([]byte, len(label)+len(seed))
    56		copy(labelAndSeed, label)
    57		copy(labelAndSeed[len(label):], seed)
    58	
    59		s1, s2 := splitPreMasterSecret(secret)
    60		pHash(result, s1, labelAndSeed, hashMD5)
    61		result2 := make([]byte, len(result))
    62		pHash(result2, s2, labelAndSeed, hashSHA1)
    63	
    64		for i, b := range result2 {
    65			result[i] ^= b
    66		}
    67	}
    68	
    69	// prf12 implements the TLS 1.2 pseudo-random function, as defined in RFC 5246, section 5.
    70	func prf12(hashFunc func() hash.Hash) func(result, secret, label, seed []byte) {
    71		return func(result, secret, label, seed []byte) {
    72			labelAndSeed := make([]byte, len(label)+len(seed))
    73			copy(labelAndSeed, label)
    74			copy(labelAndSeed[len(label):], seed)
    75	
    76			pHash(result, secret, labelAndSeed, hashFunc)
    77		}
    78	}
    79	
    80	// prf30 implements the SSL 3.0 pseudo-random function, as defined in
    81	// www.mozilla.org/projects/security/pki/nss/ssl/draft302.txt section 6.
    82	func prf30(result, secret, label, seed []byte) {
    83		hashSHA1 := sha1.New()
    84		hashMD5 := md5.New()
    85	
    86		done := 0
    87		i := 0
    88		// RFC5246 section 6.3 says that the largest PRF output needed is 128
    89		// bytes. Since no more ciphersuites will be added to SSLv3, this will
    90		// remain true. Each iteration gives us 16 bytes so 10 iterations will
    91		// be sufficient.
    92		var b [11]byte
    93		for done < len(result) {
    94			for j := 0; j <= i; j++ {
    95				b[j] = 'A' + byte(i)
    96			}
    97	
    98			hashSHA1.Reset()
    99			hashSHA1.Write(b[:i+1])
   100			hashSHA1.Write(secret)
   101			hashSHA1.Write(seed)
   102			digest := hashSHA1.Sum(nil)
   103	
   104			hashMD5.Reset()
   105			hashMD5.Write(secret)
   106			hashMD5.Write(digest)
   107	
   108			done += copy(result[done:], hashMD5.Sum(nil))
   109			i++
   110		}
   111	}
   112	
   113	const (
   114		tlsRandomLength      = 32 // Length of a random nonce in TLS 1.1.
   115		masterSecretLength   = 48 // Length of a master secret in TLS 1.1.
   116		finishedVerifyLength = 12 // Length of verify_data in a Finished message.
   117	)
   118	
   119	var masterSecretLabel = []byte("master secret")
   120	var keyExpansionLabel = []byte("key expansion")
   121	var clientFinishedLabel = []byte("client finished")
   122	var serverFinishedLabel = []byte("server finished")
   123	
   124	func prfAndHashForVersion(version uint16, suite *cipherSuite) (func(result, secret, label, seed []byte), crypto.Hash) {
   125		switch version {
   126		case VersionSSL30:
   127			return prf30, crypto.Hash(0)
   128		case VersionTLS10, VersionTLS11:
   129			return prf10, crypto.Hash(0)
   130		case VersionTLS12:
   131			if suite.flags&suiteSHA384 != 0 {
   132				return prf12(sha512.New384), crypto.SHA384
   133			}
   134			return prf12(sha256.New), crypto.SHA256
   135		default:
   136			panic("unknown version")
   137		}
   138	}
   139	
   140	func prfForVersion(version uint16, suite *cipherSuite) func(result, secret, label, seed []byte) {
   141		prf, _ := prfAndHashForVersion(version, suite)
   142		return prf
   143	}
   144	
   145	// masterFromPreMasterSecret generates the master secret from the pre-master
   146	// secret. See http://tools.ietf.org/html/rfc5246#section-8.1
   147	func masterFromPreMasterSecret(version uint16, suite *cipherSuite, preMasterSecret, clientRandom, serverRandom []byte) []byte {
   148		seed := make([]byte, 0, len(clientRandom)+len(serverRandom))
   149		seed = append(seed, clientRandom...)
   150		seed = append(seed, serverRandom...)
   151	
   152		masterSecret := make([]byte, masterSecretLength)
   153		prfForVersion(version, suite)(masterSecret, preMasterSecret, masterSecretLabel, seed)
   154		return masterSecret
   155	}
   156	
   157	// keysFromMasterSecret generates the connection keys from the master
   158	// secret, given the lengths of the MAC key, cipher key and IV, as defined in
   159	// RFC 2246, section 6.3.
   160	func keysFromMasterSecret(version uint16, suite *cipherSuite, masterSecret, clientRandom, serverRandom []byte, macLen, keyLen, ivLen int) (clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV []byte) {
   161		seed := make([]byte, 0, len(serverRandom)+len(clientRandom))
   162		seed = append(seed, serverRandom...)
   163		seed = append(seed, clientRandom...)
   164	
   165		n := 2*macLen + 2*keyLen + 2*ivLen
   166		keyMaterial := make([]byte, n)
   167		prfForVersion(version, suite)(keyMaterial, masterSecret, keyExpansionLabel, seed)
   168		clientMAC = keyMaterial[:macLen]
   169		keyMaterial = keyMaterial[macLen:]
   170		serverMAC = keyMaterial[:macLen]
   171		keyMaterial = keyMaterial[macLen:]
   172		clientKey = keyMaterial[:keyLen]
   173		keyMaterial = keyMaterial[keyLen:]
   174		serverKey = keyMaterial[:keyLen]
   175		keyMaterial = keyMaterial[keyLen:]
   176		clientIV = keyMaterial[:ivLen]
   177		keyMaterial = keyMaterial[ivLen:]
   178		serverIV = keyMaterial[:ivLen]
   179		return
   180	}
   181	
   182	// lookupTLSHash looks up the corresponding crypto.Hash for a given
   183	// TLS hash identifier.
   184	func lookupTLSHash(hash uint8) (crypto.Hash, error) {
   185		switch hash {
   186		case hashSHA1:
   187			return crypto.SHA1, nil
   188		case hashSHA256:
   189			return crypto.SHA256, nil
   190		case hashSHA384:
   191			return crypto.SHA384, nil
   192		default:
   193			return 0, errors.New("tls: unsupported hash algorithm")
   194		}
   195	}
   196	
   197	func newFinishedHash(version uint16, cipherSuite *cipherSuite) finishedHash {
   198		var buffer []byte
   199		if version == VersionSSL30 || version >= VersionTLS12 {
   200			buffer = []byte{}
   201		}
   202	
   203		prf, hash := prfAndHashForVersion(version, cipherSuite)
   204		if hash != 0 {
   205			return finishedHash{hash.New(), hash.New(), nil, nil, buffer, version, prf}
   206		}
   207	
   208		return finishedHash{sha1.New(), sha1.New(), md5.New(), md5.New(), buffer, version, prf}
   209	}
   210	
   211	// A finishedHash calculates the hash of a set of handshake messages suitable
   212	// for including in a Finished message.
   213	type finishedHash struct {
   214		client hash.Hash
   215		server hash.Hash
   216	
   217		// Prior to TLS 1.2, an additional MD5 hash is required.
   218		clientMD5 hash.Hash
   219		serverMD5 hash.Hash
   220	
   221		// In TLS 1.2, a full buffer is sadly required.
   222		buffer []byte
   223	
   224		version uint16
   225		prf     func(result, secret, label, seed []byte)
   226	}
   227	
   228	func (h *finishedHash) Write(msg []byte) (n int, err error) {
   229		h.client.Write(msg)
   230		h.server.Write(msg)
   231	
   232		if h.version < VersionTLS12 {
   233			h.clientMD5.Write(msg)
   234			h.serverMD5.Write(msg)
   235		}
   236	
   237		if h.buffer != nil {
   238			h.buffer = append(h.buffer, msg...)
   239		}
   240	
   241		return len(msg), nil
   242	}
   243	
   244	func (h finishedHash) Sum() []byte {
   245		if h.version >= VersionTLS12 {
   246			return h.client.Sum(nil)
   247		}
   248	
   249		out := make([]byte, 0, md5.Size+sha1.Size)
   250		out = h.clientMD5.Sum(out)
   251		return h.client.Sum(out)
   252	}
   253	
   254	// finishedSum30 calculates the contents of the verify_data member of a SSLv3
   255	// Finished message given the MD5 and SHA1 hashes of a set of handshake
   256	// messages.
   257	func finishedSum30(md5, sha1 hash.Hash, masterSecret []byte, magic []byte) []byte {
   258		md5.Write(magic)
   259		md5.Write(masterSecret)
   260		md5.Write(ssl30Pad1[:])
   261		md5Digest := md5.Sum(nil)
   262	
   263		md5.Reset()
   264		md5.Write(masterSecret)
   265		md5.Write(ssl30Pad2[:])
   266		md5.Write(md5Digest)
   267		md5Digest = md5.Sum(nil)
   268	
   269		sha1.Write(magic)
   270		sha1.Write(masterSecret)
   271		sha1.Write(ssl30Pad1[:40])
   272		sha1Digest := sha1.Sum(nil)
   273	
   274		sha1.Reset()
   275		sha1.Write(masterSecret)
   276		sha1.Write(ssl30Pad2[:40])
   277		sha1.Write(sha1Digest)
   278		sha1Digest = sha1.Sum(nil)
   279	
   280		ret := make([]byte, len(md5Digest)+len(sha1Digest))
   281		copy(ret, md5Digest)
   282		copy(ret[len(md5Digest):], sha1Digest)
   283		return ret
   284	}
   285	
   286	var ssl3ClientFinishedMagic = [4]byte{0x43, 0x4c, 0x4e, 0x54}
   287	var ssl3ServerFinishedMagic = [4]byte{0x53, 0x52, 0x56, 0x52}
   288	
   289	// clientSum returns the contents of the verify_data member of a client's
   290	// Finished message.
   291	func (h finishedHash) clientSum(masterSecret []byte) []byte {
   292		if h.version == VersionSSL30 {
   293			return finishedSum30(h.clientMD5, h.client, masterSecret, ssl3ClientFinishedMagic[:])
   294		}
   295	
   296		out := make([]byte, finishedVerifyLength)
   297		h.prf(out, masterSecret, clientFinishedLabel, h.Sum())
   298		return out
   299	}
   300	
   301	// serverSum returns the contents of the verify_data member of a server's
   302	// Finished message.
   303	func (h finishedHash) serverSum(masterSecret []byte) []byte {
   304		if h.version == VersionSSL30 {
   305			return finishedSum30(h.serverMD5, h.server, masterSecret, ssl3ServerFinishedMagic[:])
   306		}
   307	
   308		out := make([]byte, finishedVerifyLength)
   309		h.prf(out, masterSecret, serverFinishedLabel, h.Sum())
   310		return out
   311	}
   312	
   313	// selectClientCertSignatureAlgorithm returns a signatureAndHash to sign a
   314	// client's CertificateVerify with, or an error if none can be found.
   315	func (h finishedHash) selectClientCertSignatureAlgorithm(serverList []signatureAndHash, sigType uint8) (signatureAndHash, error) {
   316		if h.version < VersionTLS12 {
   317			// Nothing to negotiate before TLS 1.2.
   318			return signatureAndHash{signature: sigType}, nil
   319		}
   320	
   321		for _, v := range serverList {
   322			if v.signature == sigType && isSupportedSignatureAndHash(v, supportedSignatureAlgorithms) {
   323				return v, nil
   324			}
   325		}
   326		return signatureAndHash{}, errors.New("tls: no supported signature algorithm found for signing client certificate")
   327	}
   328	
   329	// hashForClientCertificate returns a digest, hash function, and TLS 1.2 hash
   330	// id suitable for signing by a TLS client certificate.
   331	func (h finishedHash) hashForClientCertificate(signatureAndHash signatureAndHash, masterSecret []byte) ([]byte, crypto.Hash, error) {
   332		if (h.version == VersionSSL30 || h.version >= VersionTLS12) && h.buffer == nil {
   333			panic("a handshake hash for a client-certificate was requested after discarding the handshake buffer")
   334		}
   335	
   336		if h.version == VersionSSL30 {
   337			if signatureAndHash.signature != signatureRSA {
   338				return nil, 0, errors.New("tls: unsupported signature type for client certificate")
   339			}
   340	
   341			md5Hash := md5.New()
   342			md5Hash.Write(h.buffer)
   343			sha1Hash := sha1.New()
   344			sha1Hash.Write(h.buffer)
   345			return finishedSum30(md5Hash, sha1Hash, masterSecret, nil), crypto.MD5SHA1, nil
   346		}
   347		if h.version >= VersionTLS12 {
   348			hashAlg, err := lookupTLSHash(signatureAndHash.hash)
   349			if err != nil {
   350				return nil, 0, err
   351			}
   352			hash := hashAlg.New()
   353			hash.Write(h.buffer)
   354			return hash.Sum(nil), hashAlg, nil
   355		}
   356	
   357		if signatureAndHash.signature == signatureECDSA {
   358			return h.server.Sum(nil), crypto.SHA1, nil
   359		}
   360	
   361		return h.Sum(), crypto.MD5SHA1, nil
   362	}
   363	
   364	// discardHandshakeBuffer is called when there is no more need to
   365	// buffer the entirety of the handshake messages.
   366	func (h *finishedHash) discardHandshakeBuffer() {
   367		h.buffer = nil
   368	}
   369	

View as plain text