Source file src/pkg/crypto/tls/common.go
1
2
3
4
5 package tls
6
7 import (
8 "crypto"
9 "crypto/rand"
10 "crypto/x509"
11 "io"
12 "strings"
13 "sync"
14 "time"
15 )
16
17 const (
18 maxPlaintext = 16384
19 maxCiphertext = 16384 + 2048
20 recordHeaderLen = 5
21 maxHandshake = 65536
22
23 versionSSL30 = 0x0300
24 versionTLS10 = 0x0301
25
26 minVersion = versionSSL30
27 maxVersion = versionTLS10
28 )
29
30
31 type recordType uint8
32
33 const (
34 recordTypeChangeCipherSpec recordType = 20
35 recordTypeAlert recordType = 21
36 recordTypeHandshake recordType = 22
37 recordTypeApplicationData recordType = 23
38 )
39
40
41 const (
42 typeClientHello uint8 = 1
43 typeServerHello uint8 = 2
44 typeNewSessionTicket uint8 = 4
45 typeCertificate uint8 = 11
46 typeServerKeyExchange uint8 = 12
47 typeCertificateRequest uint8 = 13
48 typeServerHelloDone uint8 = 14
49 typeCertificateVerify uint8 = 15
50 typeClientKeyExchange uint8 = 16
51 typeFinished uint8 = 20
52 typeCertificateStatus uint8 = 22
53 typeNextProtocol uint8 = 67
54 )
55
56
57 const (
58 compressionNone uint8 = 0
59 )
60
61
62 var (
63 extensionServerName uint16 = 0
64 extensionStatusRequest uint16 = 5
65 extensionSupportedCurves uint16 = 10
66 extensionSupportedPoints uint16 = 11
67 extensionSessionTicket uint16 = 35
68 extensionNextProtoNeg uint16 = 13172
69 )
70
71
72
73 var (
74 curveP256 uint16 = 23
75 curveP384 uint16 = 24
76 curveP521 uint16 = 25
77 )
78
79
80
81 var (
82 pointFormatUncompressed uint8 = 0
83 )
84
85
86 const (
87 statusTypeOCSP uint8 = 1
88 )
89
90
91 const (
92 certTypeRSASign = 1
93 certTypeDSSSign = 2
94 certTypeRSAFixedDH = 3
95 certTypeDSSFixedDH = 4
96
97 )
98
99
100 type ConnectionState struct {
101 HandshakeComplete bool
102 DidResume bool
103 CipherSuite uint16
104 NegotiatedProtocol string
105 NegotiatedProtocolIsMutual bool
106
107
108
109 ServerName string
110
111
112 PeerCertificates []*x509.Certificate
113
114 VerifiedChains [][]*x509.Certificate
115 }
116
117
118
119 type ClientAuthType int
120
121 const (
122 NoClientCert ClientAuthType = iota
123 RequestClientCert
124 RequireAnyClientCert
125 VerifyClientCertIfGiven
126 RequireAndVerifyClientCert
127 )
128
129
130
131 type Config struct {
132
133
134
135 Rand io.Reader
136
137
138
139 Time func() time.Time
140
141
142
143
144 Certificates []Certificate
145
146
147
148
149
150
151
152 NameToCertificate map[string]*Certificate
153
154
155
156
157 RootCAs *x509.CertPool
158
159
160 NextProtos []string
161
162
163
164 ServerName string
165
166
167
168 ClientAuth ClientAuthType
169
170
171
172
173 ClientCAs *x509.CertPool
174
175
176
177
178
179
180
181 InsecureSkipVerify bool
182
183
184
185 CipherSuites []uint16
186
187
188
189
190
191 PreferServerCipherSuites bool
192
193
194
195 SessionTicketsDisabled bool
196
197
198
199
200
201
202
203
204
205 SessionTicketKey [32]byte
206
207 serverInitOnce sync.Once
208 }
209
210 func (c *Config) serverInit() {
211 if c.SessionTicketsDisabled {
212 return
213 }
214
215
216 for _, b := range c.SessionTicketKey {
217 if b != 0 {
218 return
219 }
220 }
221
222 if _, err := io.ReadFull(c.rand(), c.SessionTicketKey[:]); err != nil {
223 c.SessionTicketsDisabled = true
224 }
225 }
226
227 func (c *Config) rand() io.Reader {
228 r := c.Rand
229 if r == nil {
230 return rand.Reader
231 }
232 return r
233 }
234
235 func (c *Config) time() time.Time {
236 t := c.Time
237 if t == nil {
238 t = time.Now
239 }
240 return t()
241 }
242
243 func (c *Config) cipherSuites() []uint16 {
244 s := c.CipherSuites
245 if s == nil {
246 s = defaultCipherSuites()
247 }
248 return s
249 }
250
251
252
253
254 func (c *Config) getCertificateForName(name string) *Certificate {
255 if len(c.Certificates) == 1 || c.NameToCertificate == nil {
256
257 return &c.Certificates[0]
258 }
259
260 name = strings.ToLower(name)
261 for len(name) > 0 && name[len(name)-1] == '.' {
262 name = name[:len(name)-1]
263 }
264
265 if cert, ok := c.NameToCertificate[name]; ok {
266 return cert
267 }
268
269
270
271 labels := strings.Split(name, ".")
272 for i := range labels {
273 labels[i] = "*"
274 candidate := strings.Join(labels, ".")
275 if cert, ok := c.NameToCertificate[candidate]; ok {
276 return cert
277 }
278 }
279
280
281 return &c.Certificates[0]
282 }
283
284
285
286
287 func (c *Config) BuildNameToCertificate() {
288 c.NameToCertificate = make(map[string]*Certificate)
289 for i := range c.Certificates {
290 cert := &c.Certificates[i]
291 x509Cert, err := x509.ParseCertificate(cert.Certificate[0])
292 if err != nil {
293 continue
294 }
295 if len(x509Cert.Subject.CommonName) > 0 {
296 c.NameToCertificate[x509Cert.Subject.CommonName] = cert
297 }
298 for _, san := range x509Cert.DNSNames {
299 c.NameToCertificate[san] = cert
300 }
301 }
302 }
303
304
305 type Certificate struct {
306 Certificate [][]byte
307 PrivateKey crypto.PrivateKey
308
309
310 OCSPStaple []byte
311
312
313
314
315 Leaf *x509.Certificate
316 }
317
318
319 type record struct {
320 contentType recordType
321 major, minor uint8
322 payload []byte
323 }
324
325 type handshakeMessage interface {
326 marshal() []byte
327 unmarshal([]byte) bool
328 }
329
330
331
332 func mutualVersion(vers uint16) (uint16, bool) {
333 if vers < minVersion {
334 return 0, false
335 }
336 if vers > maxVersion {
337 vers = maxVersion
338 }
339 return vers, true
340 }
341
342 var emptyConfig Config
343
344 func defaultConfig() *Config {
345 return &emptyConfig
346 }
347
348 var (
349 once sync.Once
350 varDefaultCipherSuites []uint16
351 )
352
353 func defaultCipherSuites() []uint16 {
354 once.Do(initDefaultCipherSuites)
355 return varDefaultCipherSuites
356 }
357
358 func initDefaultCipherSuites() {
359 varDefaultCipherSuites = make([]uint16, len(cipherSuites))
360 for i, suite := range cipherSuites {
361 varDefaultCipherSuites[i] = suite.id
362 }
363 }
View as plain text