tls13.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 tls13 implements the TLS 1.3 Key Schedule as specified in RFC 8446,
   6  // Section 7.1 and allowed by FIPS 140-3 IG 2.4.B Resolution 7.
   7  package tls13
   8  
   9  import (
  10  	"crypto/internal/fips140/hkdf"
  11  	"crypto/internal/fips140deps/byteorder"
  12  	"hash"
  13  )
  14  
  15  // We don't set the service indicator in this package but we delegate that to
  16  // the underlying functions because the TLS 1.3 KDF does not have a standard of
  17  // its own.
  18  
  19  // ExpandLabel implements HKDF-Expand-Label from RFC 8446, Section 7.1.
  20  func ExpandLabel[H hash.Hash](hash func() H, secret []byte, label []byte, context []byte, length int) []byte {
  21  	if len("tls13 ")+len(label) > 255 || len(context) > 255 {
  22  		// It should be impossible for this to panic: labels are fixed strings,
  23  		// and context is either a fixed-length computed hash, or parsed from a
  24  		// field which has the same length limitation.
  25  		//
  26  		// Another reasonable approach might be to return a randomized slice if
  27  		// we encounter an error, which would break the connection, but avoid
  28  		// panicking. This would perhaps be safer but significantly more
  29  		// confusing to users.
  30  		panic("tls13: label or context too long")
  31  	}
  32  	hkdfLabel := []byte{:0:2+1+len("tls13 ")+len(label)+1+len(context)}
  33  	hkdfLabel = byteorder.BEAppendUint16(hkdfLabel, uint16(length))
  34  	hkdfLabel = append(hkdfLabel, byte(len("tls13 ")+len(label)))
  35  	hkdfLabel = append(hkdfLabel, "tls13 "...)
  36  	hkdfLabel = append(hkdfLabel, label...)
  37  	hkdfLabel = append(hkdfLabel, byte(len(context)))
  38  	hkdfLabel = append(hkdfLabel, context...)
  39  	return hkdf.Expand(hash, secret, hkdfLabel, length)
  40  }
  41  
  42  func extract[H hash.Hash](hash func() H, newSecret, currentSecret []byte) []byte {
  43  	if newSecret == nil {
  44  		newSecret = []byte{:hash().Size()}
  45  	}
  46  	return hkdf.Extract(hash, newSecret, currentSecret)
  47  }
  48  
  49  func deriveSecret[H hash.Hash](hash func() H, secret []byte, label []byte, transcript hash.Hash) []byte {
  50  	if transcript == nil {
  51  		transcript = hash()
  52  	}
  53  	return ExpandLabel(hash, secret, label, transcript.Sum(nil), transcript.Size())
  54  }
  55  
  56  var (
  57  	resumptionBinderLabel         = []byte("res binder")
  58  	clientEarlyTrafficLabel       = []byte("c e traffic")
  59  	clientHandshakeTrafficLabel   = []byte("c hs traffic")
  60  	serverHandshakeTrafficLabel   = []byte("s hs traffic")
  61  	clientApplicationTrafficLabel = []byte("c ap traffic")
  62  	serverApplicationTrafficLabel = []byte("s ap traffic")
  63  	earlyExporterLabel            = []byte("e exp master")
  64  	exporterLabel                 = []byte("exp master")
  65  	resumptionLabel               = []byte("res master")
  66  )
  67  
  68  type EarlySecret struct {
  69  	secret []byte
  70  	hash   func() hash.Hash
  71  }
  72  
  73  func NewEarlySecret[H hash.Hash](h func() H, psk []byte) *EarlySecret {
  74  	return &EarlySecret{
  75  		secret: extract(h, psk, nil),
  76  		hash:   func() hash.Hash { return h() },
  77  	}
  78  }
  79  
  80  func (s *EarlySecret) ResumptionBinderKey() []byte {
  81  	return deriveSecret(s.hash, s.secret, resumptionBinderLabel, nil)
  82  }
  83  
  84  // ClientEarlyTrafficSecret derives the client_early_traffic_secret from the
  85  // early secret and the transcript up to the ClientHello.
  86  func (s *EarlySecret) ClientEarlyTrafficSecret(transcript hash.Hash) []byte {
  87  	return deriveSecret(s.hash, s.secret, clientEarlyTrafficLabel, transcript)
  88  }
  89  
  90  type HandshakeSecret struct {
  91  	secret []byte
  92  	hash   func() hash.Hash
  93  }
  94  
  95  func (s *EarlySecret) HandshakeSecret(sharedSecret []byte) *HandshakeSecret {
  96  	derived := deriveSecret(s.hash, s.secret, []byte("derived"), nil)
  97  	return &HandshakeSecret{
  98  		secret: extract(s.hash, sharedSecret, derived),
  99  		hash:   s.hash,
 100  	}
 101  }
 102  
 103  // ClientHandshakeTrafficSecret derives the client_handshake_traffic_secret from
 104  // the handshake secret and the transcript up to the ServerHello.
 105  func (s *HandshakeSecret) ClientHandshakeTrafficSecret(transcript hash.Hash) []byte {
 106  	return deriveSecret(s.hash, s.secret, clientHandshakeTrafficLabel, transcript)
 107  }
 108  
 109  // ServerHandshakeTrafficSecret derives the server_handshake_traffic_secret from
 110  // the handshake secret and the transcript up to the ServerHello.
 111  func (s *HandshakeSecret) ServerHandshakeTrafficSecret(transcript hash.Hash) []byte {
 112  	return deriveSecret(s.hash, s.secret, serverHandshakeTrafficLabel, transcript)
 113  }
 114  
 115  type MasterSecret struct {
 116  	secret []byte
 117  	hash   func() hash.Hash
 118  }
 119  
 120  func (s *HandshakeSecret) MasterSecret() *MasterSecret {
 121  	derived := deriveSecret(s.hash, s.secret, []byte("derived"), nil)
 122  	return &MasterSecret{
 123  		secret: extract(s.hash, nil, derived),
 124  		hash:   s.hash,
 125  	}
 126  }
 127  
 128  // ClientApplicationTrafficSecret derives the client_application_traffic_secret_0
 129  // from the master secret and the transcript up to the server Finished.
 130  func (s *MasterSecret) ClientApplicationTrafficSecret(transcript hash.Hash) []byte {
 131  	return deriveSecret(s.hash, s.secret, clientApplicationTrafficLabel, transcript)
 132  }
 133  
 134  // ServerApplicationTrafficSecret derives the server_application_traffic_secret_0
 135  // from the master secret and the transcript up to the server Finished.
 136  func (s *MasterSecret) ServerApplicationTrafficSecret(transcript hash.Hash) []byte {
 137  	return deriveSecret(s.hash, s.secret, serverApplicationTrafficLabel, transcript)
 138  }
 139  
 140  // ResumptionMasterSecret derives the resumption_master_secret from the master secret
 141  // and the transcript up to the client Finished.
 142  func (s *MasterSecret) ResumptionMasterSecret(transcript hash.Hash) []byte {
 143  	return deriveSecret(s.hash, s.secret, resumptionLabel, transcript)
 144  }
 145  
 146  type ExporterMasterSecret struct {
 147  	secret []byte
 148  	hash   func() hash.Hash
 149  }
 150  
 151  // ExporterMasterSecret derives the exporter_master_secret from the master secret
 152  // and the transcript up to the server Finished.
 153  func (s *MasterSecret) ExporterMasterSecret(transcript hash.Hash) *ExporterMasterSecret {
 154  	return &ExporterMasterSecret{
 155  		secret: deriveSecret(s.hash, s.secret, exporterLabel, transcript),
 156  		hash:   s.hash,
 157  	}
 158  }
 159  
 160  // EarlyExporterMasterSecret derives the exporter_master_secret from the early secret
 161  // and the transcript up to the ClientHello.
 162  func (s *EarlySecret) EarlyExporterMasterSecret(transcript hash.Hash) *ExporterMasterSecret {
 163  	return &ExporterMasterSecret{
 164  		secret: deriveSecret(s.hash, s.secret, earlyExporterLabel, transcript),
 165  		hash:   s.hash,
 166  	}
 167  }
 168  
 169  func (s *ExporterMasterSecret) Exporter(label []byte, context []byte, length int) []byte {
 170  	secret := deriveSecret(s.hash, s.secret, label, nil)
 171  	h := s.hash()
 172  	h.Write(context)
 173  	return ExpandLabel(s.hash, secret, []byte("exporter"), h.Sum(nil), length)
 174  }
 175  
 176  func TestingOnlyExporterSecret(s *ExporterMasterSecret) []byte {
 177  	return s.secret
 178  }
 179