github.com/Hyperledger-TWGC/tjfoc-gm@v1.4.0/gmtls/prf.go (about)

     1  /*
     2  Copyright Suzhou Tongji Fintech Research Institute 2017 All Rights Reserved.
     3  Licensed under the Apache License, Version 2.0 (the "License");
     4  you may not use this file except in compliance with the License.
     5  You may obtain a copy of the License at
     6  
     7  	http://www.apache.org/licenses/LICENSE-2.0
     8  
     9  Unless required by applicable law or agreed to in writing, software
    10  distributed under the License is distributed on an "AS IS" BASIS,
    11  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  See the License for the specific language governing permissions and
    13  limitations under the License.
    14  */
    15  
    16  package gmtls
    17  
    18  import (
    19  	"crypto"
    20  	"crypto/hmac"
    21  	"crypto/md5"
    22  	"crypto/sha1"
    23  	"crypto/sha256"
    24  	"crypto/sha512"
    25  	"errors"
    26  	"fmt"
    27  	"github.com/Hyperledger-TWGC/tjfoc-gm/sm3"
    28  	"hash"
    29  )
    30  
    31  // Split a premaster secret in two as specified in RFC 4346, section 5.
    32  func splitPreMasterSecret(secret []byte) (s1, s2 []byte) {
    33  	s1 = secret[0 : (len(secret)+1)/2]
    34  	s2 = secret[len(secret)/2:]
    35  	return
    36  }
    37  
    38  // pHash implements the P_hash function, as defined in RFC 4346, section 5.
    39  func pHash(result, secret, seed []byte, hash func() hash.Hash) {
    40  	h := hmac.New(hash, secret)
    41  	h.Write(seed)
    42  	a := h.Sum(nil)
    43  
    44  	j := 0
    45  	for j < len(result) {
    46  		h.Reset()
    47  		h.Write(a)
    48  		h.Write(seed)
    49  		b := h.Sum(nil)
    50  		todo := len(b)
    51  		if j+todo > len(result) {
    52  			todo = len(result) - j
    53  		}
    54  		copy(result[j:j+todo], b)
    55  		j += todo
    56  
    57  		h.Reset()
    58  		h.Write(a)
    59  		a = h.Sum(nil)
    60  	}
    61  }
    62  
    63  // prf10 implements the TLS 1.0 pseudo-random function, as defined in RFC 2246, section 5.
    64  func prf10(result, secret, label, seed []byte) {
    65  	hashSHA1 := sha1.New
    66  	hashMD5 := md5.New
    67  
    68  	labelAndSeed := make([]byte, len(label)+len(seed))
    69  	copy(labelAndSeed, label)
    70  	copy(labelAndSeed[len(label):], seed)
    71  
    72  	s1, s2 := splitPreMasterSecret(secret)
    73  	pHash(result, s1, labelAndSeed, hashMD5)
    74  	result2 := make([]byte, len(result))
    75  	pHash(result2, s2, labelAndSeed, hashSHA1)
    76  
    77  	for i, b := range result2 {
    78  		result[i] ^= b
    79  	}
    80  }
    81  
    82  // prf12 implements the TLS 1.2 pseudo-random function, as defined in RFC 5246, section 5.
    83  func prf12(hashFunc func() hash.Hash) func(result, secret, label, seed []byte) {
    84  	return func(result, secret, label, seed []byte) {
    85  		labelAndSeed := make([]byte, len(label)+len(seed))
    86  		copy(labelAndSeed, label)
    87  		copy(labelAndSeed[len(label):], seed)
    88  
    89  		pHash(result, secret, labelAndSeed, hashFunc)
    90  	}
    91  }
    92  
    93  // prf30 implements the SSL 3.0 pseudo-random function, as defined in
    94  // www.mozilla.org/projects/security/pki/nss/ssl/draft302.txt section 6.
    95  func prf30(result, secret, label, seed []byte) {
    96  	hashSHA1 := sha1.New()
    97  	hashMD5 := md5.New()
    98  
    99  	done := 0
   100  	i := 0
   101  	// RFC 5246 section 6.3 says that the largest PRF output needed is 128
   102  	// bytes. Since no more ciphersuites will be added to SSLv3, this will
   103  	// remain true. Each iteration gives us 16 bytes so 10 iterations will
   104  	// be sufficient.
   105  	var b [11]byte
   106  	for done < len(result) {
   107  		for j := 0; j <= i; j++ {
   108  			b[j] = 'A' + byte(i)
   109  		}
   110  
   111  		hashSHA1.Reset()
   112  		hashSHA1.Write(b[:i+1])
   113  		hashSHA1.Write(secret)
   114  		hashSHA1.Write(seed)
   115  		digest := hashSHA1.Sum(nil)
   116  
   117  		hashMD5.Reset()
   118  		hashMD5.Write(secret)
   119  		hashMD5.Write(digest)
   120  
   121  		done += copy(result[done:], hashMD5.Sum(nil))
   122  		i++
   123  	}
   124  }
   125  
   126  const (
   127  	tlsRandomLength      = 32 // Length of a random nonce in TLS 1.1.
   128  	masterSecretLength   = 48 // Length of a master secret in TLS 1.1.
   129  	finishedVerifyLength = 12 // Length of verify_data in a Finished message.
   130  )
   131  
   132  var masterSecretLabel = []byte("master secret")
   133  var keyExpansionLabel = []byte("key expansion")
   134  var clientFinishedLabel = []byte("client finished")
   135  var serverFinishedLabel = []byte("server finished")
   136  
   137  func prfAndHashForGM() func(result, secret, label, seed []byte) {
   138  	return prf12(sm3.New)
   139  }
   140  
   141  func prfAndHashForVersion(version uint16, suite *cipherSuite) (func(result, secret, label, seed []byte), crypto.Hash) {
   142  	switch version {
   143  	case VersionSSL30:
   144  		return prf30, crypto.Hash(0)
   145  	case VersionTLS10, VersionTLS11:
   146  		return prf10, crypto.Hash(0)
   147  	case VersionTLS12:
   148  		if suite.flags&suiteSHA384 != 0 {
   149  			return prf12(sha512.New384), crypto.SHA384
   150  		}
   151  		return prf12(sha256.New), crypto.SHA256
   152  	default:
   153  		panic("unknown version")
   154  	}
   155  }
   156  
   157  func prfForVersion(version uint16, suite *cipherSuite) func(result, secret, label, seed []byte) {
   158  	var prf func(result, secret, label, seed []byte)
   159  	if version == VersionGMSSL {
   160  		prf = prfAndHashForGM()
   161  	} else {
   162  		prf, _ = prfAndHashForVersion(version, suite)
   163  	}
   164  	return prf
   165  }
   166  
   167  // masterFromPreMasterSecret generates the master secret from the pre-master
   168  // secret. See http://tools.ietf.org/html/rfc5246#section-8.1
   169  func masterFromPreMasterSecret(version uint16, suite *cipherSuite, preMasterSecret, clientRandom, serverRandom []byte) []byte {
   170  	seed := make([]byte, 0, len(clientRandom)+len(serverRandom))
   171  	seed = append(seed, clientRandom...)
   172  	seed = append(seed, serverRandom...)
   173  
   174  	masterSecret := make([]byte, masterSecretLength)
   175  	prfForVersion(version, suite)(masterSecret, preMasterSecret, masterSecretLabel, seed)
   176  	return masterSecret
   177  }
   178  
   179  // keysFromMasterSecret generates the connection keys from the master
   180  // secret, given the lengths of the MAC key, cipher key and IV, as defined in
   181  // RFC 2246, section 6.3.
   182  func keysFromMasterSecret(version uint16, suite *cipherSuite, masterSecret, clientRandom, serverRandom []byte, macLen, keyLen, ivLen int) (clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV []byte) {
   183  	seed := make([]byte, 0, len(serverRandom)+len(clientRandom))
   184  	seed = append(seed, serverRandom...)
   185  	seed = append(seed, clientRandom...)
   186  
   187  	n := 2*macLen + 2*keyLen + 2*ivLen
   188  	keyMaterial := make([]byte, n)
   189  	prfForVersion(version, suite)(keyMaterial, masterSecret, keyExpansionLabel, seed)
   190  	clientMAC = keyMaterial[:macLen]
   191  	keyMaterial = keyMaterial[macLen:]
   192  	serverMAC = keyMaterial[:macLen]
   193  	keyMaterial = keyMaterial[macLen:]
   194  	clientKey = keyMaterial[:keyLen]
   195  	keyMaterial = keyMaterial[keyLen:]
   196  	serverKey = keyMaterial[:keyLen]
   197  	keyMaterial = keyMaterial[keyLen:]
   198  	clientIV = keyMaterial[:ivLen]
   199  	keyMaterial = keyMaterial[ivLen:]
   200  	serverIV = keyMaterial[:ivLen]
   201  	return
   202  }
   203  
   204  // lookupTLSHash looks up the corresponding crypto.Hash for a given
   205  // TLS hash identifier.
   206  func lookupTLSHash(signatureAlgorithm SignatureScheme) (crypto.Hash, error) {
   207  	switch signatureAlgorithm {
   208  	case PKCS1WithSHA1, ECDSAWithSHA1:
   209  		return crypto.SHA1, nil
   210  	case PKCS1WithSHA256, PSSWithSHA256, ECDSAWithP256AndSHA256:
   211  		return crypto.SHA256, nil
   212  	case PKCS1WithSHA384, PSSWithSHA384, ECDSAWithP384AndSHA384:
   213  		return crypto.SHA384, nil
   214  	case PKCS1WithSHA512, PSSWithSHA512, ECDSAWithP521AndSHA512:
   215  		return crypto.SHA512, nil
   216  	default:
   217  		return 0, fmt.Errorf("tls: unsupported signature algorithm: %#04x", signatureAlgorithm)
   218  	}
   219  }
   220  func newFinishedHash(version uint16, cipherSuite *cipherSuite) finishedHash {
   221  	var buffer []byte
   222  	if version == VersionSSL30 || version >= VersionTLS12 {
   223  		buffer = []byte{}
   224  	}
   225  
   226  	var prf func(result, secret, label, seed []byte)
   227  
   228  	if version == VersionGMSSL {
   229  		prf = prfAndHashForGM()
   230  		return finishedHash{sm3.New(), sm3.New(), nil, nil, buffer, version, prf}
   231  	} else {
   232  		prf, hash := prfAndHashForVersion(version, cipherSuite)
   233  		if hash != 0 {
   234  			return finishedHash{hash.New(), hash.New(), nil, nil, buffer, version, prf}
   235  		}
   236  	}
   237  
   238  	return finishedHash{sha1.New(), sha1.New(), md5.New(), md5.New(), buffer, version, prf}
   239  }
   240  
   241  // A finishedHash calculates the hash of a set of handshake messages suitable
   242  // for including in a Finished message.
   243  type finishedHash struct {
   244  	client hash.Hash
   245  	server hash.Hash
   246  
   247  	// Prior to TLS 1.2, an additional MD5 hash is required.
   248  	clientMD5 hash.Hash
   249  	serverMD5 hash.Hash
   250  
   251  	// In TLS 1.2, a full buffer is sadly required.
   252  	buffer []byte
   253  
   254  	version uint16
   255  	prf     func(result, secret, label, seed []byte)
   256  }
   257  
   258  func (h *finishedHash) Write(msg []byte) (n int, err error) {
   259  	h.client.Write(msg)
   260  	h.server.Write(msg)
   261  
   262  	if h.version < VersionTLS12 {
   263  		h.clientMD5.Write(msg)
   264  		h.serverMD5.Write(msg)
   265  	}
   266  
   267  	if h.buffer != nil {
   268  		h.buffer = append(h.buffer, msg...)
   269  	}
   270  
   271  	return len(msg), nil
   272  }
   273  
   274  func (h finishedHash) Sum() []byte {
   275  	if h.version >= VersionTLS12 || h.version == VersionGMSSL {
   276  		return h.client.Sum(nil)
   277  	}
   278  
   279  	out := make([]byte, 0, md5.Size+sha1.Size)
   280  	out = h.clientMD5.Sum(out)
   281  	return h.client.Sum(out)
   282  }
   283  
   284  // finishedSum30 calculates the contents of the verify_data member of a SSLv3
   285  // Finished message given the MD5 and SHA1 hashes of a set of handshake
   286  // messages.
   287  func finishedSum30(md5, sha1 hash.Hash, masterSecret []byte, magic []byte) []byte {
   288  	md5.Write(magic)
   289  	md5.Write(masterSecret)
   290  	md5.Write(ssl30Pad1[:])
   291  	md5Digest := md5.Sum(nil)
   292  
   293  	md5.Reset()
   294  	md5.Write(masterSecret)
   295  	md5.Write(ssl30Pad2[:])
   296  	md5.Write(md5Digest)
   297  	md5Digest = md5.Sum(nil)
   298  
   299  	sha1.Write(magic)
   300  	sha1.Write(masterSecret)
   301  	sha1.Write(ssl30Pad1[:40])
   302  	sha1Digest := sha1.Sum(nil)
   303  
   304  	sha1.Reset()
   305  	sha1.Write(masterSecret)
   306  	sha1.Write(ssl30Pad2[:40])
   307  	sha1.Write(sha1Digest)
   308  	sha1Digest = sha1.Sum(nil)
   309  
   310  	ret := make([]byte, len(md5Digest)+len(sha1Digest))
   311  	copy(ret, md5Digest)
   312  	copy(ret[len(md5Digest):], sha1Digest)
   313  	return ret
   314  }
   315  
   316  var ssl3ClientFinishedMagic = [4]byte{0x43, 0x4c, 0x4e, 0x54}
   317  var ssl3ServerFinishedMagic = [4]byte{0x53, 0x52, 0x56, 0x52}
   318  
   319  // clientSum returns the contents of the verify_data member of a client's
   320  // Finished message.
   321  func (h finishedHash) clientSum(masterSecret []byte) []byte {
   322  	if h.version == VersionSSL30 {
   323  		return finishedSum30(h.clientMD5, h.client, masterSecret, ssl3ClientFinishedMagic[:])
   324  	}
   325  
   326  	out := make([]byte, finishedVerifyLength)
   327  	h.prf(out, masterSecret, clientFinishedLabel, h.Sum())
   328  	return out
   329  }
   330  
   331  // serverSum returns the contents of the verify_data member of a server's
   332  // Finished message.
   333  func (h finishedHash) serverSum(masterSecret []byte) []byte {
   334  	if h.version == VersionSSL30 {
   335  		return finishedSum30(h.serverMD5, h.server, masterSecret, ssl3ServerFinishedMagic[:])
   336  	}
   337  
   338  	out := make([]byte, finishedVerifyLength)
   339  	h.prf(out, masterSecret, serverFinishedLabel, h.Sum())
   340  	return out
   341  }
   342  
   343  // hashForClientCertificate returns a digest, hash function, and TLS 1.2 hash
   344  // id suitable for signing by a TLS client certificate.
   345  func (h finishedHash) hashForClientCertificate(sigType uint8, hashAlg crypto.Hash, masterSecret []byte) ([]byte, error) {
   346  	if (h.version == VersionSSL30 || h.version >= VersionTLS12) && h.buffer == nil {
   347  		panic("a handshake hash for a client-certificate was requested after discarding the handshake buffer")
   348  	}
   349  
   350  	if h.version == VersionSSL30 {
   351  		if sigType != signaturePKCS1v15 {
   352  			return nil, errors.New("tls: unsupported signature type for client certificate")
   353  		}
   354  
   355  		md5Hash := md5.New()
   356  		md5Hash.Write(h.buffer)
   357  		sha1Hash := sha1.New()
   358  		sha1Hash.Write(h.buffer)
   359  		return finishedSum30(md5Hash, sha1Hash, masterSecret, nil), nil
   360  	}
   361  	if h.version >= VersionTLS12 {
   362  		hash := hashAlg.New()
   363  		hash.Write(h.buffer)
   364  		return hash.Sum(nil), nil
   365  	}
   366  
   367  	if sigType == signatureECDSA {
   368  		return h.server.Sum(nil), nil
   369  	}
   370  
   371  	return h.Sum(), nil
   372  }
   373  
   374  // discardHandshakeBuffer is called when there is no more need to
   375  // buffer the entirety of the handshake messages.
   376  func (h *finishedHash) discardHandshakeBuffer() {
   377  	h.buffer = nil
   378  }
   379  
   380  // noExportedKeyingMaterial is used as a value of
   381  // ConnectionState.ekm when renegotation is enabled and thus
   382  // we wish to fail all key-material export requests.
   383  func noExportedKeyingMaterial(label string, context []byte, length int) ([]byte, error) {
   384  	return nil, errors.New("crypto/tls: ExportKeyingMaterial is unavailable when renegotiation is enabled")
   385  }
   386  
   387  // ekmFromMasterSecret generates exported keying material as defined in
   388  // https://tools.ietf.org/html/rfc5705.
   389  func ekmFromMasterSecret(version uint16, suite *cipherSuite, masterSecret, clientRandom, serverRandom []byte) func(string, []byte, int) ([]byte, error) {
   390  	return func(label string, context []byte, length int) ([]byte, error) {
   391  		switch label {
   392  		case "client finished", "server finished", "master secret", "key expansion":
   393  			// These values are reserved and may not be used.
   394  			return nil, fmt.Errorf("crypto/tls: reserved ExportKeyingMaterial label: %s", label)
   395  		}
   396  
   397  		seedLen := len(serverRandom) + len(clientRandom)
   398  		if context != nil {
   399  			seedLen += 2 + len(context)
   400  		}
   401  		seed := make([]byte, 0, seedLen)
   402  
   403  		seed = append(seed, clientRandom...)
   404  		seed = append(seed, serverRandom...)
   405  
   406  		if context != nil {
   407  			if len(context) >= 1<<16 {
   408  				return nil, fmt.Errorf("crypto/tls: ExportKeyingMaterial context too long")
   409  			}
   410  			seed = append(seed, byte(len(context)>>8), byte(len(context)))
   411  			seed = append(seed, context...)
   412  		}
   413  
   414  		keyMaterial := make([]byte, length)
   415  		prfForVersion(version, suite)(keyMaterial, masterSecret, []byte(label), seed)
   416  		return keyMaterial, nil
   417  	}
   418  }