1
2
3
4
5 package tls
6
7 import (
8 "crypto/rand"
9 "crypto/rsa"
10 "crypto/x509"
11 "io"
12 "io/ioutil"
13 "sync"
14 "time"
15 )
16
17 const (
18 maxPlaintext = 16384
19 maxCiphertext = 16384 + 2048
20 recordHeaderLen = 5
21 maxHandshake = 65536
22
23 minVersion = 0x0301
24 maxVersion = 0x0301
25 )
26
27
28 type recordType uint8
29
30 const (
31 recordTypeChangeCipherSpec recordType = 20
32 recordTypeAlert recordType = 21
33 recordTypeHandshake recordType = 22
34 recordTypeApplicationData recordType = 23
35 )
36
37
38 const (
39 typeClientHello uint8 = 1
40 typeServerHello uint8 = 2
41 typeCertificate uint8 = 11
42 typeServerKeyExchange uint8 = 12
43 typeCertificateRequest uint8 = 13
44 typeServerHelloDone uint8 = 14
45 typeCertificateVerify uint8 = 15
46 typeClientKeyExchange uint8 = 16
47 typeFinished uint8 = 20
48 typeCertificateStatus uint8 = 22
49 typeNextProtocol uint8 = 67
50 )
51
52
53 const (
54 compressionNone uint8 = 0
55 )
56
57
58 var (
59 extensionServerName uint16 = 0
60 extensionStatusRequest uint16 = 5
61 extensionSupportedCurves uint16 = 10
62 extensionSupportedPoints uint16 = 11
63 extensionNextProtoNeg uint16 = 13172
64 )
65
66
67
68 var (
69 curveP256 uint16 = 23
70 curveP384 uint16 = 24
71 curveP521 uint16 = 25
72 )
73
74
75
76 var (
77 pointFormatUncompressed uint8 = 0
78 )
79
80
81 const (
82 statusTypeOCSP uint8 = 1
83 )
84
85
86 const (
87 certTypeRSASign = 1
88 certTypeDSSSign = 2
89 certTypeRSAFixedDH = 3
90 certTypeDSSFixedDH = 4
91
92 )
93
94
95 type ConnectionState struct {
96 HandshakeComplete bool
97 CipherSuite uint16
98 NegotiatedProtocol string
99 NegotiatedProtocolIsMutual bool
100
101
102 PeerCertificates []*x509.Certificate
103
104 VerifiedChains [][]*x509.Certificate
105 }
106
107
108
109 type Config struct {
110
111
112
113 Rand io.Reader
114
115
116
117 Time func() int64
118
119
120
121
122 Certificates []Certificate
123
124
125
126
127 RootCAs *x509.CertPool
128
129
130 NextProtos []string
131
132
133
134 ServerName string
135
136
137
138
139
140 AuthenticateClient bool
141
142
143
144 CipherSuites []uint16
145 }
146
147 func (c *Config) rand() io.Reader {
148 r := c.Rand
149 if r == nil {
150 return rand.Reader
151 }
152 return r
153 }
154
155 func (c *Config) time() int64 {
156 t := c.Time
157 if t == nil {
158 t = time.Seconds
159 }
160 return t()
161 }
162
163 func (c *Config) rootCAs() *x509.CertPool {
164 s := c.RootCAs
165 if s == nil {
166 s = defaultRoots()
167 }
168 return s
169 }
170
171 func (c *Config) cipherSuites() []uint16 {
172 s := c.CipherSuites
173 if s == nil {
174 s = defaultCipherSuites()
175 }
176 return s
177 }
178
179
180 type Certificate struct {
181 Certificate [][]byte
182 PrivateKey *rsa.PrivateKey
183
184
185 OCSPStaple []byte
186 }
187
188
189 type record struct {
190 contentType recordType
191 major, minor uint8
192 payload []byte
193 }
194
195 type handshakeMessage interface {
196 marshal() []byte
197 unmarshal([]byte) bool
198 }
199
200
201
202 func mutualVersion(vers uint16) (uint16, bool) {
203 if vers < minVersion {
204 return 0, false
205 }
206 if vers > maxVersion {
207 vers = maxVersion
208 }
209 return vers, true
210 }
211
212 var emptyConfig Config
213
214 func defaultConfig() *Config {
215 return &emptyConfig
216 }
217
218
219
220
221
222 var certFiles = []string{
223 "/etc/ssl/certs/ca-certificates.crt",
224 "/usr/share/curl/curl-ca-bundle.crt",
225 }
226
227 var once sync.Once
228
229 func defaultRoots() *x509.CertPool {
230 once.Do(initDefaults)
231 return varDefaultRoots
232 }
233
234 func defaultCipherSuites() []uint16 {
235 once.Do(initDefaults)
236 return varDefaultCipherSuites
237 }
238
239 func initDefaults() {
240 initDefaultRoots()
241 initDefaultCipherSuites()
242 }
243
244 var varDefaultRoots *x509.CertPool
245
246 func initDefaultRoots() {
247 roots := x509.NewCertPool()
248 for _, file := range certFiles {
249 data, err := ioutil.ReadFile(file)
250 if err == nil {
251 roots.AppendCertsFromPEM(data)
252 break
253 }
254 }
255 varDefaultRoots = roots
256 }
257
258 var varDefaultCipherSuites []uint16
259
260 func initDefaultCipherSuites() {
261 varDefaultCipherSuites = make([]uint16, len(cipherSuites))
262 i := 0
263 for id := range cipherSuites {
264 varDefaultCipherSuites[i] = id
265 i++
266 }
267 }