1
2
3
4
5
6
7 package tls13
8
9 import (
10 "crypto/internal/fips140"
11 "crypto/internal/fips140/hkdf"
12 "crypto/internal/fips140deps/byteorder"
13 )
14
15
16
17
18
19
20 func ExpandLabel[H fips140.Hash](hash func() H, secret []byte, label string, context []byte, length int) []byte {
21 if len("tls13 ")+len(label) > 255 || len(context) > 255 {
22
23
24
25
26
27
28
29
30 panic("tls13: label or context too long")
31 }
32 hkdfLabel := make([]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, string(hkdfLabel), length)
40 }
41
42 func extract[H fips140.Hash](hash func() H, newSecret, currentSecret []byte) []byte {
43 if newSecret == nil {
44 newSecret = make([]byte, hash().Size())
45 }
46 return hkdf.Extract(hash, newSecret, currentSecret)
47 }
48
49 func deriveSecret[H fips140.Hash](hash func() H, secret []byte, label string, transcript fips140.Hash) []byte {
50 if transcript == nil {
51 transcript = hash()
52 }
53 return ExpandLabel(hash, secret, label, transcript.Sum(nil), transcript.Size())
54 }
55
56 const (
57 resumptionBinderLabel = "res binder"
58 clientEarlyTrafficLabel = "c e traffic"
59 clientHandshakeTrafficLabel = "c hs traffic"
60 serverHandshakeTrafficLabel = "s hs traffic"
61 clientApplicationTrafficLabel = "c ap traffic"
62 serverApplicationTrafficLabel = "s ap traffic"
63 earlyExporterLabel = "e exp master"
64 exporterLabel = "exp master"
65 resumptionLabel = "res master"
66 )
67
68 type EarlySecret struct {
69 secret []byte
70 hash func() fips140.Hash
71 }
72
73 func NewEarlySecret[H fips140.Hash](hash func() H, psk []byte) *EarlySecret {
74 return &EarlySecret{
75 secret: extract(hash, psk, nil),
76 hash: func() fips140.Hash { return hash() },
77 }
78 }
79
80 func (s *EarlySecret) ResumptionBinderKey() []byte {
81 return deriveSecret(s.hash, s.secret, resumptionBinderLabel, nil)
82 }
83
84
85
86 func (s *EarlySecret) ClientEarlyTrafficSecret(transcript fips140.Hash) []byte {
87 return deriveSecret(s.hash, s.secret, clientEarlyTrafficLabel, transcript)
88 }
89
90 type HandshakeSecret struct {
91 secret []byte
92 hash func() fips140.Hash
93 }
94
95 func (s *EarlySecret) HandshakeSecret(sharedSecret []byte) *HandshakeSecret {
96 derived := deriveSecret(s.hash, s.secret, "derived", nil)
97 return &HandshakeSecret{
98 secret: extract(s.hash, sharedSecret, derived),
99 hash: s.hash,
100 }
101 }
102
103
104
105 func (s *HandshakeSecret) ClientHandshakeTrafficSecret(transcript fips140.Hash) []byte {
106 return deriveSecret(s.hash, s.secret, clientHandshakeTrafficLabel, transcript)
107 }
108
109
110
111 func (s *HandshakeSecret) ServerHandshakeTrafficSecret(transcript fips140.Hash) []byte {
112 return deriveSecret(s.hash, s.secret, serverHandshakeTrafficLabel, transcript)
113 }
114
115 type MasterSecret struct {
116 secret []byte
117 hash func() fips140.Hash
118 }
119
120 func (s *HandshakeSecret) MasterSecret() *MasterSecret {
121 derived := deriveSecret(s.hash, s.secret, "derived", nil)
122 return &MasterSecret{
123 secret: extract(s.hash, nil, derived),
124 hash: s.hash,
125 }
126 }
127
128
129
130 func (s *MasterSecret) ClientApplicationTrafficSecret(transcript fips140.Hash) []byte {
131 return deriveSecret(s.hash, s.secret, clientApplicationTrafficLabel, transcript)
132 }
133
134
135
136 func (s *MasterSecret) ServerApplicationTrafficSecret(transcript fips140.Hash) []byte {
137 return deriveSecret(s.hash, s.secret, serverApplicationTrafficLabel, transcript)
138 }
139
140
141
142 func (s *MasterSecret) ResumptionMasterSecret(transcript fips140.Hash) []byte {
143 return deriveSecret(s.hash, s.secret, resumptionLabel, transcript)
144 }
145
146 type ExporterMasterSecret struct {
147 secret []byte
148 hash func() fips140.Hash
149 }
150
151
152
153 func (s *MasterSecret) ExporterMasterSecret(transcript fips140.Hash) *ExporterMasterSecret {
154 return &ExporterMasterSecret{
155 secret: deriveSecret(s.hash, s.secret, exporterLabel, transcript),
156 hash: s.hash,
157 }
158 }
159
160
161
162 func (s *EarlySecret) EarlyExporterMasterSecret(transcript fips140.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 string, 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, "exporter", h.Sum(nil), length)
174 }
175
176 func TestingOnlyExporterSecret(s *ExporterMasterSecret) []byte {
177 return s.secret
178 }
179
View as plain text