...
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		var seed [tlsRandomLength * 2]byte
   149		copy(seed[0:len(clientRandom)], clientRandom)
   150		copy(seed[len(clientRandom):], serverRandom)
   151		masterSecret := make([]byte, masterSecretLength)
   152		prfForVersion(version, suite)(masterSecret, preMasterSecret, masterSecretLabel, seed[0:])
   153		return masterSecret
   154	}
   155	
   156	// keysFromMasterSecret generates the connection keys from the master
   157	// secret, given the lengths of the MAC key, cipher key and IV, as defined in
   158	// RFC 2246, section 6.3.
   159	func keysFromMasterSecret(version uint16, suite *cipherSuite, masterSecret, clientRandom, serverRandom []byte, macLen, keyLen, ivLen int) (clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV []byte) {
   160		var seed [tlsRandomLength * 2]byte
   161		copy(seed[0:len(clientRandom)], serverRandom)
   162		copy(seed[len(serverRandom):], clientRandom)
   163	
   164		n := 2*macLen + 2*keyLen + 2*ivLen
   165		keyMaterial := make([]byte, n)
   166		prfForVersion(version, suite)(keyMaterial, masterSecret, keyExpansionLabel, seed[0:])
   167		clientMAC = keyMaterial[:macLen]
   168		keyMaterial = keyMaterial[macLen:]
   169		serverMAC = keyMaterial[:macLen]
   170		keyMaterial = keyMaterial[macLen:]
   171		clientKey = keyMaterial[:keyLen]
   172		keyMaterial = keyMaterial[keyLen:]
   173		serverKey = keyMaterial[:keyLen]
   174		keyMaterial = keyMaterial[keyLen:]
   175		clientIV = keyMaterial[:ivLen]
   176		keyMaterial = keyMaterial[ivLen:]
   177		serverIV = keyMaterial[:ivLen]
   178		return
   179	}
   180	
   181	// lookupTLSHash looks up the corresponding crypto.Hash for a given
   182	// TLS hash identifier.
   183	func lookupTLSHash(hash uint8) (crypto.Hash, error) {
   184		switch hash {
   185		case hashSHA1:
   186			return crypto.SHA1, nil
   187		case hashSHA256:
   188			return crypto.SHA256, nil
   189		case hashSHA384:
   190			return crypto.SHA384, nil
   191		default:
   192			return 0, errors.New("tls: unsupported hash algorithm")
   193		}
   194	}
   195	
   196	func newFinishedHash(version uint16, cipherSuite *cipherSuite) finishedHash {
   197		var buffer []byte
   198		if version == VersionSSL30 || version >= VersionTLS12 {
   199			buffer = []byte{}
   200		}
   201	
   202		prf, hash := prfAndHashForVersion(version, cipherSuite)
   203		if hash != 0 {
   204			return finishedHash{hash.New(), hash.New(), nil, nil, buffer, version, prf}
   205		}
   206	
   207		return finishedHash{sha1.New(), sha1.New(), md5.New(), md5.New(), buffer, version, prf}
   208	}
   209	
   210	// A finishedHash calculates the hash of a set of handshake messages suitable
   211	// for including in a Finished message.
   212	type finishedHash struct {
   213		client hash.Hash
   214		server hash.Hash
   215	
   216		// Prior to TLS 1.2, an additional MD5 hash is required.
   217		clientMD5 hash.Hash
   218		serverMD5 hash.Hash
   219	
   220		// In TLS 1.2, a full buffer is sadly required.
   221		buffer []byte
   222	
   223		version uint16
   224		prf     func(result, secret, label, seed []byte)
   225	}
   226	
   227	func (h *finishedHash) Write(msg []byte) (n int, err error) {
   228		h.client.Write(msg)
   229		h.server.Write(msg)
   230	
   231		if h.version < VersionTLS12 {
   232			h.clientMD5.Write(msg)
   233			h.serverMD5.Write(msg)
   234		}
   235	
   236		if h.buffer != nil {
   237			h.buffer = append(h.buffer, msg...)
   238		}
   239	
   240		return len(msg), nil
   241	}
   242	
   243	func (h finishedHash) Sum() []byte {
   244		if h.version >= VersionTLS12 {
   245			return h.client.Sum(nil)
   246		}
   247	
   248		out := make([]byte, 0, md5.Size+sha1.Size)
   249		out = h.clientMD5.Sum(out)
   250		return h.client.Sum(out)
   251	}
   252	
   253	// finishedSum30 calculates the contents of the verify_data member of a SSLv3
   254	// Finished message given the MD5 and SHA1 hashes of a set of handshake
   255	// messages.
   256	func finishedSum30(md5, sha1 hash.Hash, masterSecret []byte, magic []byte) []byte {
   257		md5.Write(magic)
   258		md5.Write(masterSecret)
   259		md5.Write(ssl30Pad1[:])
   260		md5Digest := md5.Sum(nil)
   261	
   262		md5.Reset()
   263		md5.Write(masterSecret)
   264		md5.Write(ssl30Pad2[:])
   265		md5.Write(md5Digest)
   266		md5Digest = md5.Sum(nil)
   267	
   268		sha1.Write(magic)
   269		sha1.Write(masterSecret)
   270		sha1.Write(ssl30Pad1[:40])
   271		sha1Digest := sha1.Sum(nil)
   272	
   273		sha1.Reset()
   274		sha1.Write(masterSecret)
   275		sha1.Write(ssl30Pad2[:40])
   276		sha1.Write(sha1Digest)
   277		sha1Digest = sha1.Sum(nil)
   278	
   279		ret := make([]byte, len(md5Digest)+len(sha1Digest))
   280		copy(ret, md5Digest)
   281		copy(ret[len(md5Digest):], sha1Digest)
   282		return ret
   283	}
   284	
   285	var ssl3ClientFinishedMagic = [4]byte{0x43, 0x4c, 0x4e, 0x54}
   286	var ssl3ServerFinishedMagic = [4]byte{0x53, 0x52, 0x56, 0x52}
   287	
   288	// clientSum returns the contents of the verify_data member of a client's
   289	// Finished message.
   290	func (h finishedHash) clientSum(masterSecret []byte) []byte {
   291		if h.version == VersionSSL30 {
   292			return finishedSum30(h.clientMD5, h.client, masterSecret, ssl3ClientFinishedMagic[:])
   293		}
   294	
   295		out := make([]byte, finishedVerifyLength)
   296		h.prf(out, masterSecret, clientFinishedLabel, h.Sum())
   297		return out
   298	}
   299	
   300	// serverSum returns the contents of the verify_data member of a server's
   301	// Finished message.
   302	func (h finishedHash) serverSum(masterSecret []byte) []byte {
   303		if h.version == VersionSSL30 {
   304			return finishedSum30(h.serverMD5, h.server, masterSecret, ssl3ServerFinishedMagic[:])
   305		}
   306	
   307		out := make([]byte, finishedVerifyLength)
   308		h.prf(out, masterSecret, serverFinishedLabel, h.Sum())
   309		return out
   310	}
   311	
   312	// selectClientCertSignatureAlgorithm returns a signatureAndHash to sign a
   313	// client's CertificateVerify with, or an error if none can be found.
   314	func (h finishedHash) selectClientCertSignatureAlgorithm(serverList []signatureAndHash, sigType uint8) (signatureAndHash, error) {
   315		if h.version < VersionTLS12 {
   316			// Nothing to negotiate before TLS 1.2.
   317			return signatureAndHash{signature: sigType}, nil
   318		}
   319	
   320		for _, v := range serverList {
   321			if v.signature == sigType && isSupportedSignatureAndHash(v, supportedSignatureAlgorithms) {
   322				return v, nil
   323			}
   324		}
   325		return signatureAndHash{}, errors.New("tls: no supported signature algorithm found for signing client certificate")
   326	}
   327	
   328	// hashForClientCertificate returns a digest, hash function, and TLS 1.2 hash
   329	// id suitable for signing by a TLS client certificate.
   330	func (h finishedHash) hashForClientCertificate(signatureAndHash signatureAndHash, masterSecret []byte) ([]byte, crypto.Hash, error) {
   331		if (h.version == VersionSSL30 || h.version >= VersionTLS12) && h.buffer == nil {
   332			panic("a handshake hash for a client-certificate was requested after discarding the handshake buffer")
   333		}
   334	
   335		if h.version == VersionSSL30 {
   336			if signatureAndHash.signature != signatureRSA {
   337				return nil, 0, errors.New("tls: unsupported signature type for client certificate")
   338			}
   339	
   340			md5Hash := md5.New()
   341			md5Hash.Write(h.buffer)
   342			sha1Hash := sha1.New()
   343			sha1Hash.Write(h.buffer)
   344			return finishedSum30(md5Hash, sha1Hash, masterSecret, nil), crypto.MD5SHA1, nil
   345		}
   346		if h.version >= VersionTLS12 {
   347			hashAlg, err := lookupTLSHash(signatureAndHash.hash)
   348			if err != nil {
   349				return nil, 0, err
   350			}
   351			hash := hashAlg.New()
   352			hash.Write(h.buffer)
   353			return hash.Sum(nil), hashAlg, nil
   354		}
   355	
   356		if signatureAndHash.signature == signatureECDSA {
   357			return h.server.Sum(nil), crypto.SHA1, nil
   358		}
   359	
   360		return h.Sum(), crypto.MD5SHA1, nil
   361	}
   362	
   363	// discardHandshakeBuffer is called when there is no more need to
   364	// buffer the entirety of the handshake messages.
   365	func (h *finishedHash) discardHandshakeBuffer() {
   366		h.buffer = nil
   367	}
   368	

View as plain text