prf.mx raw

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