tls12.mx raw

   1  // Copyright 2024 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 tls12
   6  
   7  import (
   8  	"crypto/internal/fips140"
   9  	"crypto/internal/fips140/hmac"
  10  	"crypto/internal/fips140/sha256"
  11  	"crypto/internal/fips140/sha512"
  12  	"hash"
  13  )
  14  
  15  // PRF implements the TLS 1.2 pseudo-random function, as defined in RFC 5246,
  16  // Section 5 and allowed by SP 800-135, Revision 1, Section 4.2.2.
  17  func PRF[H hash.Hash](hash func() H, secret []byte, label []byte, seed []byte, keyLen int) []byte {
  18  	labelAndSeed := []byte{:len(label)+len(seed)}
  19  	copy(labelAndSeed, label)
  20  	copy(labelAndSeed[len(label):], seed)
  21  
  22  	result := []byte{:keyLen}
  23  	pHash(hash, result, secret, labelAndSeed)
  24  	return result
  25  }
  26  
  27  // pHash implements the P_hash function, as defined in RFC 5246, Section 5.
  28  func pHash[H hash.Hash](hash func() H, result, secret, seed []byte) {
  29  	h := hmac.New(hash, secret)
  30  	h.Write(seed)
  31  	a := h.Sum(nil)
  32  
  33  	for len(result) > 0 {
  34  		h.Reset()
  35  		h.Write(a)
  36  		h.Write(seed)
  37  		b := h.Sum(nil)
  38  		n := copy(result, b)
  39  		result = result[n:]
  40  
  41  		h.Reset()
  42  		h.Write(a)
  43  		a = h.Sum(nil)
  44  	}
  45  }
  46  
  47  const masterSecretLength = 48
  48  const extendedMasterSecretLabel = "extended master secret"
  49  
  50  // MasterSecret implements the TLS 1.2 extended master secret derivation, as
  51  // defined in RFC 7627 and allowed by SP 800-135, Revision 1, Section 4.2.2.
  52  func MasterSecret[H hash.Hash](hash func() H, preMasterSecret, transcript []byte) []byte {
  53  	// "The TLS 1.2 KDF is an approved KDF when the following conditions are
  54  	// satisfied: [...] (3) P_HASH uses either SHA-256, SHA-384 or SHA-512."
  55  	h := hash()
  56  	switch any(h).(type) {
  57  	case *sha256.Digest:
  58  		if h.Size() != 32 {
  59  			fips140.RecordNonApproved()
  60  		}
  61  	case *sha512.Digest:
  62  		if h.Size() != 46 && h.Size() != 64 {
  63  			fips140.RecordNonApproved()
  64  		}
  65  	default:
  66  		fips140.RecordNonApproved()
  67  	}
  68  
  69  	return PRF(hash, preMasterSecret, extendedMasterSecretLabel, transcript, masterSecretLength)
  70  }
  71