...

Source file src/pkg/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		"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	// prf30 implements the SSL 3.0 pseudo-random function, as defined in
    78	// www.mozilla.org/projects/security/pki/nss/ssl/draft302.txt section 6.
    79	func prf30(result, secret, label, seed []byte) {
    80		hashSHA1 := sha1.New()
    81		hashMD5 := md5.New()
    82	
    83		done := 0
    84		i := 0
    85		// RFC 5246 section 6.3 says that the largest PRF output needed is 128
    86		// bytes. Since no more ciphersuites will be added to SSLv3, this will
    87		// remain true. Each iteration gives us 16 bytes so 10 iterations will
    88		// be sufficient.
    89		var b [11]byte
    90		for done < len(result) {
    91			for j := 0; j <= i; j++ {
    92				b[j] = 'A' + byte(i)
    93			}
    94	
    95			hashSHA1.Reset()
    96			hashSHA1.Write(b[:i+1])
    97			hashSHA1.Write(secret)
    98			hashSHA1.Write(seed)
    99			digest := hashSHA1.Sum(nil)
   100	
   101			hashMD5.Reset()
   102			hashMD5.Write(secret)
   103			hashMD5.Write(digest)
   104	
   105			done += copy(result[done:], hashMD5.Sum(nil))
   106			i++
   107		}
   108	}
   109	
   110	const (
   111		masterSecretLength   = 48 // Length of a master secret in TLS 1.1.
   112		finishedVerifyLength = 12 // Length of verify_data in a Finished message.
   113	)
   114	
   115	var masterSecretLabel = []byte("master secret")
   116	var keyExpansionLabel = []byte("key expansion")
   117	var clientFinishedLabel = []byte("client finished")
   118	var serverFinishedLabel = []byte("server finished")
   119	
   120	func prfAndHashForVersion(version uint16, suite *cipherSuite) (func(result, secret, label, seed []byte), crypto.Hash) {
   121		switch version {
   122		case VersionSSL30:
   123			return prf30, crypto.Hash(0)
   124		case VersionTLS10, VersionTLS11:
   125			return prf10, crypto.Hash(0)
   126		case VersionTLS12:
   127			if suite.flags&suiteSHA384 != 0 {
   128				return prf12(sha512.New384), crypto.SHA384
   129			}
   130			return prf12(sha256.New), crypto.SHA256
   131		default:
   132			panic("unknown version")
   133		}
   134	}
   135	
   136	func prfForVersion(version uint16, suite *cipherSuite) func(result, secret, label, seed []byte) {
   137		prf, _ := prfAndHashForVersion(version, suite)
   138		return prf
   139	}
   140	
   141	// masterFromPreMasterSecret generates the master secret from the pre-master
   142	// secret. See RFC 5246, Section 8.1.
   143	func masterFromPreMasterSecret(version uint16, suite *cipherSuite, preMasterSecret, clientRandom, serverRandom []byte) []byte {
   144		seed := make([]byte, 0, len(clientRandom)+len(serverRandom))
   145		seed = append(seed, clientRandom...)
   146		seed = append(seed, serverRandom...)
   147	
   148		masterSecret := make([]byte, masterSecretLength)
   149		prfForVersion(version, suite)(masterSecret, preMasterSecret, masterSecretLabel, seed)
   150		return masterSecret
   151	}
   152	
   153	// keysFromMasterSecret generates the connection keys from the master
   154	// secret, given the lengths of the MAC key, cipher key and IV, as defined in
   155	// RFC 2246, Section 6.3.
   156	func keysFromMasterSecret(version uint16, suite *cipherSuite, masterSecret, clientRandom, serverRandom []byte, macLen, keyLen, ivLen int) (clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV []byte) {
   157		seed := make([]byte, 0, len(serverRandom)+len(clientRandom))
   158		seed = append(seed, serverRandom...)
   159		seed = append(seed, clientRandom...)
   160	
   161		n := 2*macLen + 2*keyLen + 2*ivLen
   162		keyMaterial := make([]byte, n)
   163		prfForVersion(version, suite)(keyMaterial, masterSecret, keyExpansionLabel, seed)
   164		clientMAC = keyMaterial[:macLen]
   165		keyMaterial = keyMaterial[macLen:]
   166		serverMAC = keyMaterial[:macLen]
   167		keyMaterial = keyMaterial[macLen:]
   168		clientKey = keyMaterial[:keyLen]
   169		keyMaterial = keyMaterial[keyLen:]
   170		serverKey = keyMaterial[:keyLen]
   171		keyMaterial = keyMaterial[keyLen:]
   172		clientIV = keyMaterial[:ivLen]
   173		keyMaterial = keyMaterial[ivLen:]
   174		serverIV = keyMaterial[:ivLen]
   175		return
   176	}
   177	
   178	// hashFromSignatureScheme returns the corresponding crypto.Hash for a given
   179	// hash from a TLS SignatureScheme.
   180	func hashFromSignatureScheme(signatureAlgorithm SignatureScheme) (crypto.Hash, error) {
   181		switch signatureAlgorithm {
   182		case PKCS1WithSHA1, ECDSAWithSHA1:
   183			return crypto.SHA1, nil
   184		case PKCS1WithSHA256, PSSWithSHA256, ECDSAWithP256AndSHA256:
   185			return crypto.SHA256, nil
   186		case PKCS1WithSHA384, PSSWithSHA384, ECDSAWithP384AndSHA384:
   187			return crypto.SHA384, nil
   188		case PKCS1WithSHA512, PSSWithSHA512, ECDSAWithP521AndSHA512:
   189			return crypto.SHA512, nil
   190		case Ed25519:
   191			return directSigning, nil
   192		default:
   193			return 0, fmt.Errorf("tls: unsupported signature algorithm: %#04x", signatureAlgorithm)
   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	// hashForClientCertificate returns the handshake messages so far, pre-hashed if
   314	// necessary, suitable for signing by a TLS client certificate.
   315	func (h finishedHash) hashForClientCertificate(sigType uint8, hashAlg crypto.Hash, masterSecret []byte) ([]byte, error) {
   316		if (h.version == VersionSSL30 || h.version >= VersionTLS12 || sigType == signatureEd25519) && h.buffer == nil {
   317			panic("tls: handshake hash for a client certificate requested after discarding the handshake buffer")
   318		}
   319	
   320		if h.version == VersionSSL30 {
   321			if sigType != signaturePKCS1v15 {
   322				return nil, errors.New("tls: unsupported signature type for client certificate")
   323			}
   324	
   325			md5Hash := md5.New()
   326			md5Hash.Write(h.buffer)
   327			sha1Hash := sha1.New()
   328			sha1Hash.Write(h.buffer)
   329			return finishedSum30(md5Hash, sha1Hash, masterSecret, nil), nil
   330		}
   331	
   332		if sigType == signatureEd25519 {
   333			return h.buffer, nil
   334		}
   335	
   336		if h.version >= VersionTLS12 {
   337			hash := hashAlg.New()
   338			hash.Write(h.buffer)
   339			return hash.Sum(nil), nil
   340		}
   341	
   342		if sigType == signatureECDSA {
   343			return h.server.Sum(nil), nil
   344		}
   345	
   346		return h.Sum(), nil
   347	}
   348	
   349	// discardHandshakeBuffer is called when there is no more need to
   350	// buffer the entirety of the handshake messages.
   351	func (h *finishedHash) discardHandshakeBuffer() {
   352		h.buffer = nil
   353	}
   354	
   355	// noExportedKeyingMaterial is used as a value of
   356	// ConnectionState.ekm when renegotation is enabled and thus
   357	// we wish to fail all key-material export requests.
   358	func noExportedKeyingMaterial(label string, context []byte, length int) ([]byte, error) {
   359		return nil, errors.New("crypto/tls: ExportKeyingMaterial is unavailable when renegotiation is enabled")
   360	}
   361	
   362	// ekmFromMasterSecret generates exported keying material as defined in RFC 5705.
   363	func ekmFromMasterSecret(version uint16, suite *cipherSuite, masterSecret, clientRandom, serverRandom []byte) func(string, []byte, int) ([]byte, error) {
   364		return func(label string, context []byte, length int) ([]byte, error) {
   365			switch label {
   366			case "client finished", "server finished", "master secret", "key expansion":
   367				// These values are reserved and may not be used.
   368				return nil, fmt.Errorf("crypto/tls: reserved ExportKeyingMaterial label: %s", label)
   369			}
   370	
   371			seedLen := len(serverRandom) + len(clientRandom)
   372			if context != nil {
   373				seedLen += 2 + len(context)
   374			}
   375			seed := make([]byte, 0, seedLen)
   376	
   377			seed = append(seed, clientRandom...)
   378			seed = append(seed, serverRandom...)
   379	
   380			if context != nil {
   381				if len(context) >= 1<<16 {
   382					return nil, fmt.Errorf("crypto/tls: ExportKeyingMaterial context too long")
   383				}
   384				seed = append(seed, byte(len(context)>>8), byte(len(context)))
   385				seed = append(seed, context...)
   386			}
   387	
   388			keyMaterial := make([]byte, length)
   389			prfForVersion(version, suite)(keyMaterial, masterSecret, []byte(label), seed)
   390			return keyMaterial, nil
   391		}
   392	}
   393	

View as plain text