...

Source file src/crypto/tls/prf.go

Documentation: crypto/tls

		 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  	"fmt"
		16  	"hash"
		17  )
		18  
		19  // Split a premaster secret in two as specified in RFC 4346, Section 5.
		20  func splitPreMasterSecret(secret []byte) (s1, s2 []byte) {
		21  	s1 = secret[0 : (len(secret)+1)/2]
		22  	s2 = secret[len(secret)/2:]
		23  	return
		24  }
		25  
		26  // pHash implements the P_hash function, as defined in RFC 4346, Section 5.
		27  func pHash(result, secret, seed []byte, hash func() hash.Hash) {
		28  	h := hmac.New(hash, secret)
		29  	h.Write(seed)
		30  	a := h.Sum(nil)
		31  
		32  	j := 0
		33  	for j < len(result) {
		34  		h.Reset()
		35  		h.Write(a)
		36  		h.Write(seed)
		37  		b := h.Sum(nil)
		38  		copy(result[j:], b)
		39  		j += len(b)
		40  
		41  		h.Reset()
		42  		h.Write(a)
		43  		a = h.Sum(nil)
		44  	}
		45  }
		46  
		47  // prf10 implements the TLS 1.0 pseudo-random function, as defined in RFC 2246, Section 5.
		48  func prf10(result, secret, label, seed []byte) {
		49  	hashSHA1 := sha1.New
		50  	hashMD5 := md5.New
		51  
		52  	labelAndSeed := make([]byte, len(label)+len(seed))
		53  	copy(labelAndSeed, label)
		54  	copy(labelAndSeed[len(label):], seed)
		55  
		56  	s1, s2 := splitPreMasterSecret(secret)
		57  	pHash(result, s1, labelAndSeed, hashMD5)
		58  	result2 := make([]byte, len(result))
		59  	pHash(result2, s2, labelAndSeed, hashSHA1)
		60  
		61  	for i, b := range result2 {
		62  		result[i] ^= b
		63  	}
		64  }
		65  
		66  // prf12 implements the TLS 1.2 pseudo-random function, as defined in RFC 5246, Section 5.
		67  func prf12(hashFunc func() hash.Hash) func(result, secret, label, seed []byte) {
		68  	return func(result, secret, label, seed []byte) {
		69  		labelAndSeed := make([]byte, len(label)+len(seed))
		70  		copy(labelAndSeed, label)
		71  		copy(labelAndSeed[len(label):], seed)
		72  
		73  		pHash(result, secret, labelAndSeed, hashFunc)
		74  	}
		75  }
		76  
		77  const (
		78  	masterSecretLength	 = 48 // Length of a master secret in TLS 1.1.
		79  	finishedVerifyLength = 12 // Length of verify_data in a Finished message.
		80  )
		81  
		82  var masterSecretLabel = []byte("master secret")
		83  var keyExpansionLabel = []byte("key expansion")
		84  var clientFinishedLabel = []byte("client finished")
		85  var serverFinishedLabel = []byte("server finished")
		86  
		87  func prfAndHashForVersion(version uint16, suite *cipherSuite) (func(result, secret, label, seed []byte), crypto.Hash) {
		88  	switch version {
		89  	case VersionTLS10, VersionTLS11:
		90  		return prf10, crypto.Hash(0)
		91  	case VersionTLS12:
		92  		if suite.flags&suiteSHA384 != 0 {
		93  			return prf12(sha512.New384), crypto.SHA384
		94  		}
		95  		return prf12(sha256.New), crypto.SHA256
		96  	default:
		97  		panic("unknown version")
		98  	}
		99  }
	 100  
	 101  func prfForVersion(version uint16, suite *cipherSuite) func(result, secret, label, seed []byte) {
	 102  	prf, _ := prfAndHashForVersion(version, suite)
	 103  	return prf
	 104  }
	 105  
	 106  // masterFromPreMasterSecret generates the master secret from the pre-master
	 107  // secret. See RFC 5246, Section 8.1.
	 108  func masterFromPreMasterSecret(version uint16, suite *cipherSuite, preMasterSecret, clientRandom, serverRandom []byte) []byte {
	 109  	seed := make([]byte, 0, len(clientRandom)+len(serverRandom))
	 110  	seed = append(seed, clientRandom...)
	 111  	seed = append(seed, serverRandom...)
	 112  
	 113  	masterSecret := make([]byte, masterSecretLength)
	 114  	prfForVersion(version, suite)(masterSecret, preMasterSecret, masterSecretLabel, seed)
	 115  	return masterSecret
	 116  }
	 117  
	 118  // keysFromMasterSecret generates the connection keys from the master
	 119  // secret, given the lengths of the MAC key, cipher key and IV, as defined in
	 120  // RFC 2246, Section 6.3.
	 121  func keysFromMasterSecret(version uint16, suite *cipherSuite, masterSecret, clientRandom, serverRandom []byte, macLen, keyLen, ivLen int) (clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV []byte) {
	 122  	seed := make([]byte, 0, len(serverRandom)+len(clientRandom))
	 123  	seed = append(seed, serverRandom...)
	 124  	seed = append(seed, clientRandom...)
	 125  
	 126  	n := 2*macLen + 2*keyLen + 2*ivLen
	 127  	keyMaterial := make([]byte, n)
	 128  	prfForVersion(version, suite)(keyMaterial, masterSecret, keyExpansionLabel, seed)
	 129  	clientMAC = keyMaterial[:macLen]
	 130  	keyMaterial = keyMaterial[macLen:]
	 131  	serverMAC = keyMaterial[:macLen]
	 132  	keyMaterial = keyMaterial[macLen:]
	 133  	clientKey = keyMaterial[:keyLen]
	 134  	keyMaterial = keyMaterial[keyLen:]
	 135  	serverKey = keyMaterial[:keyLen]
	 136  	keyMaterial = keyMaterial[keyLen:]
	 137  	clientIV = keyMaterial[:ivLen]
	 138  	keyMaterial = keyMaterial[ivLen:]
	 139  	serverIV = keyMaterial[:ivLen]
	 140  	return
	 141  }
	 142  
	 143  func newFinishedHash(version uint16, cipherSuite *cipherSuite) finishedHash {
	 144  	var buffer []byte
	 145  	if version >= VersionTLS12 {
	 146  		buffer = []byte{}
	 147  	}
	 148  
	 149  	prf, hash := prfAndHashForVersion(version, cipherSuite)
	 150  	if hash != 0 {
	 151  		return finishedHash{hash.New(), hash.New(), nil, nil, buffer, version, prf}
	 152  	}
	 153  
	 154  	return finishedHash{sha1.New(), sha1.New(), md5.New(), md5.New(), buffer, version, prf}
	 155  }
	 156  
	 157  // A finishedHash calculates the hash of a set of handshake messages suitable
	 158  // for including in a Finished message.
	 159  type finishedHash struct {
	 160  	client hash.Hash
	 161  	server hash.Hash
	 162  
	 163  	// Prior to TLS 1.2, an additional MD5 hash is required.
	 164  	clientMD5 hash.Hash
	 165  	serverMD5 hash.Hash
	 166  
	 167  	// In TLS 1.2, a full buffer is sadly required.
	 168  	buffer []byte
	 169  
	 170  	version uint16
	 171  	prf		 func(result, secret, label, seed []byte)
	 172  }
	 173  
	 174  func (h *finishedHash) Write(msg []byte) (n int, err error) {
	 175  	h.client.Write(msg)
	 176  	h.server.Write(msg)
	 177  
	 178  	if h.version < VersionTLS12 {
	 179  		h.clientMD5.Write(msg)
	 180  		h.serverMD5.Write(msg)
	 181  	}
	 182  
	 183  	if h.buffer != nil {
	 184  		h.buffer = append(h.buffer, msg...)
	 185  	}
	 186  
	 187  	return len(msg), nil
	 188  }
	 189  
	 190  func (h finishedHash) Sum() []byte {
	 191  	if h.version >= VersionTLS12 {
	 192  		return h.client.Sum(nil)
	 193  	}
	 194  
	 195  	out := make([]byte, 0, md5.Size+sha1.Size)
	 196  	out = h.clientMD5.Sum(out)
	 197  	return h.client.Sum(out)
	 198  }
	 199  
	 200  // clientSum returns the contents of the verify_data member of a client's
	 201  // Finished message.
	 202  func (h finishedHash) clientSum(masterSecret []byte) []byte {
	 203  	out := make([]byte, finishedVerifyLength)
	 204  	h.prf(out, masterSecret, clientFinishedLabel, h.Sum())
	 205  	return out
	 206  }
	 207  
	 208  // serverSum returns the contents of the verify_data member of a server's
	 209  // Finished message.
	 210  func (h finishedHash) serverSum(masterSecret []byte) []byte {
	 211  	out := make([]byte, finishedVerifyLength)
	 212  	h.prf(out, masterSecret, serverFinishedLabel, h.Sum())
	 213  	return out
	 214  }
	 215  
	 216  // hashForClientCertificate returns the handshake messages so far, pre-hashed if
	 217  // necessary, suitable for signing by a TLS client certificate.
	 218  func (h finishedHash) hashForClientCertificate(sigType uint8, hashAlg crypto.Hash, masterSecret []byte) []byte {
	 219  	if (h.version >= VersionTLS12 || sigType == signatureEd25519) && h.buffer == nil {
	 220  		panic("tls: handshake hash for a client certificate requested after discarding the handshake buffer")
	 221  	}
	 222  
	 223  	if sigType == signatureEd25519 {
	 224  		return h.buffer
	 225  	}
	 226  
	 227  	if h.version >= VersionTLS12 {
	 228  		hash := hashAlg.New()
	 229  		hash.Write(h.buffer)
	 230  		return hash.Sum(nil)
	 231  	}
	 232  
	 233  	if sigType == signatureECDSA {
	 234  		return h.server.Sum(nil)
	 235  	}
	 236  
	 237  	return h.Sum()
	 238  }
	 239  
	 240  // discardHandshakeBuffer is called when there is no more need to
	 241  // buffer the entirety of the handshake messages.
	 242  func (h *finishedHash) discardHandshakeBuffer() {
	 243  	h.buffer = nil
	 244  }
	 245  
	 246  // noExportedKeyingMaterial is used as a value of
	 247  // ConnectionState.ekm when renegotiation is enabled and thus
	 248  // we wish to fail all key-material export requests.
	 249  func noExportedKeyingMaterial(label string, context []byte, length int) ([]byte, error) {
	 250  	return nil, errors.New("crypto/tls: ExportKeyingMaterial is unavailable when renegotiation is enabled")
	 251  }
	 252  
	 253  // ekmFromMasterSecret generates exported keying material as defined in RFC 5705.
	 254  func ekmFromMasterSecret(version uint16, suite *cipherSuite, masterSecret, clientRandom, serverRandom []byte) func(string, []byte, int) ([]byte, error) {
	 255  	return func(label string, context []byte, length int) ([]byte, error) {
	 256  		switch label {
	 257  		case "client finished", "server finished", "master secret", "key expansion":
	 258  			// These values are reserved and may not be used.
	 259  			return nil, fmt.Errorf("crypto/tls: reserved ExportKeyingMaterial label: %s", label)
	 260  		}
	 261  
	 262  		seedLen := len(serverRandom) + len(clientRandom)
	 263  		if context != nil {
	 264  			seedLen += 2 + len(context)
	 265  		}
	 266  		seed := make([]byte, 0, seedLen)
	 267  
	 268  		seed = append(seed, clientRandom...)
	 269  		seed = append(seed, serverRandom...)
	 270  
	 271  		if context != nil {
	 272  			if len(context) >= 1<<16 {
	 273  				return nil, fmt.Errorf("crypto/tls: ExportKeyingMaterial context too long")
	 274  			}
	 275  			seed = append(seed, byte(len(context)>>8), byte(len(context)))
	 276  			seed = append(seed, context...)
	 277  		}
	 278  
	 279  		keyMaterial := make([]byte, length)
	 280  		prfForVersion(version, suite)(keyMaterial, masterSecret, []byte(label), seed)
	 281  		return keyMaterial, nil
	 282  	}
	 283  }
	 284  

View as plain text