Source file
src/crypto/tls/conn_test.go
1
2
3
4
5 package tls
6
7 import (
8 "bytes"
9 "io"
10 "net"
11 "testing"
12 )
13
14 func TestRoundUp(t *testing.T) {
15 if roundUp(0, 16) != 0 ||
16 roundUp(1, 16) != 16 ||
17 roundUp(15, 16) != 16 ||
18 roundUp(16, 16) != 16 ||
19 roundUp(17, 16) != 32 {
20 t.Error("roundUp broken")
21 }
22 }
23
24
25 var padding255Bad = [256]byte{}
26
27
28 var padding255Good = [256]byte{255}
29
30 var paddingTests = []struct {
31 in []byte
32 good bool
33 expectedLen int
34 }{
35 {[]byte{1, 2, 3, 4, 0}, true, 4},
36 {[]byte{1, 2, 3, 4, 0, 1}, false, 0},
37 {[]byte{1, 2, 3, 4, 99, 99}, false, 0},
38 {[]byte{1, 2, 3, 4, 1, 1}, true, 4},
39 {[]byte{1, 2, 3, 2, 2, 2}, true, 3},
40 {[]byte{1, 2, 3, 3, 3, 3}, true, 2},
41 {[]byte{1, 2, 3, 4, 3, 3}, false, 0},
42 {[]byte{1, 4, 4, 4, 4, 4}, true, 1},
43 {[]byte{5, 5, 5, 5, 5, 5}, true, 0},
44 {[]byte{6, 6, 6, 6, 6, 6}, false, 0},
45 {padding255Bad[:], false, 0},
46 {padding255Good[:], true, 0},
47 }
48
49 func TestRemovePadding(t *testing.T) {
50 for i := 1; i < len(padding255Bad); i++ {
51 padding255Bad[i] = 255
52 padding255Good[i] = 255
53 }
54 for i, test := range paddingTests {
55 paddingLen, good := extractPadding(test.in)
56 expectedGood := byte(255)
57 if !test.good {
58 expectedGood = 0
59 }
60 if good != expectedGood {
61 t.Errorf("#%d: wrong validity, want:%d got:%d", i, expectedGood, good)
62 }
63 if good == 255 && len(test.in)-paddingLen != test.expectedLen {
64 t.Errorf("#%d: got %d, want %d", i, len(test.in)-paddingLen, test.expectedLen)
65 }
66 }
67 }
68
69 var certExampleCom = `308201713082011ba003020102021005a75ddf21014d5f417083b7a010ba2e300d06092a864886f70d01010b050030123110300e060355040a130741636d6520436f301e170d3136303831373231343135335a170d3137303831373231343135335a30123110300e060355040a130741636d6520436f305c300d06092a864886f70d0101010500034b003048024100b37f0fdd67e715bf532046ac34acbd8fdc4dabe2b598588f3f58b1f12e6219a16cbfe54d2b4b665396013589262360b6721efa27d546854f17cc9aeec6751db10203010001a34d304b300e0603551d0f0101ff0404030205a030130603551d25040c300a06082b06010505070301300c0603551d130101ff0402300030160603551d11040f300d820b6578616d706c652e636f6d300d06092a864886f70d01010b050003410059fc487866d3d855503c8e064ca32aac5e9babcece89ec597f8b2b24c17867f4a5d3b4ece06e795bfc5448ccbd2ffca1b3433171ebf3557a4737b020565350a0`
70
71 var certWildcardExampleCom = `308201743082011ea003020102021100a7aa6297c9416a4633af8bec2958c607300d06092a864886f70d01010b050030123110300e060355040a130741636d6520436f301e170d3136303831373231343231395a170d3137303831373231343231395a30123110300e060355040a130741636d6520436f305c300d06092a864886f70d0101010500034b003048024100b105afc859a711ee864114e7d2d46c2dcbe392d3506249f6c2285b0eb342cc4bf2d803677c61c0abde443f084745c1a6d62080e5664ef2cc8f50ad8a0ab8870b0203010001a34f304d300e0603551d0f0101ff0404030205a030130603551d25040c300a06082b06010505070301300c0603551d130101ff0402300030180603551d110411300f820d2a2e6578616d706c652e636f6d300d06092a864886f70d01010b0500034100af26088584d266e3f6566360cf862c7fecc441484b098b107439543144a2b93f20781988281e108c6d7656934e56950e1e5f2bcf38796b814ccb729445856c34`
72
73 var certFooExampleCom = `308201753082011fa00302010202101bbdb6070b0aeffc49008cde74deef29300d06092a864886f70d01010b050030123110300e060355040a130741636d6520436f301e170d3136303831373231343234345a170d3137303831373231343234345a30123110300e060355040a130741636d6520436f305c300d06092a864886f70d0101010500034b003048024100f00ac69d8ca2829f26216c7b50f1d4bbabad58d447706476cd89a2f3e1859943748aa42c15eedc93ac7c49e40d3b05ed645cb6b81c4efba60d961f44211a54eb0203010001a351304f300e0603551d0f0101ff0404030205a030130603551d25040c300a06082b06010505070301300c0603551d130101ff04023000301a0603551d1104133011820f666f6f2e6578616d706c652e636f6d300d06092a864886f70d01010b0500034100a0957fca6d1e0f1ef4b247348c7a8ca092c29c9c0ecc1898ea6b8065d23af6d922a410dd2335a0ea15edd1394cef9f62c9e876a21e35250a0b4fe1ddceba0f36`
74
75 func TestCertificateSelection(t *testing.T) {
76 config := Config{
77 Certificates: []Certificate{
78 {
79 Certificate: [][]byte{fromHex(certExampleCom)},
80 },
81 {
82 Certificate: [][]byte{fromHex(certWildcardExampleCom)},
83 },
84 {
85 Certificate: [][]byte{fromHex(certFooExampleCom)},
86 },
87 },
88 }
89
90 config.BuildNameToCertificate()
91
92 pointerToIndex := func(c *Certificate) int {
93 for i := range config.Certificates {
94 if c == &config.Certificates[i] {
95 return i
96 }
97 }
98 return -1
99 }
100
101 certificateForName := func(name string) *Certificate {
102 clientHello := &ClientHelloInfo{
103 ServerName: name,
104 }
105 if cert, err := config.getCertificate(clientHello); err != nil {
106 t.Errorf("unable to get certificate for name '%s': %s", name, err)
107 return nil
108 } else {
109 return cert
110 }
111 }
112
113 if n := pointerToIndex(certificateForName("example.com")); n != 0 {
114 t.Errorf("example.com returned certificate %d, not 0", n)
115 }
116 if n := pointerToIndex(certificateForName("bar.example.com")); n != 1 {
117 t.Errorf("bar.example.com returned certificate %d, not 1", n)
118 }
119 if n := pointerToIndex(certificateForName("foo.example.com")); n != 2 {
120 t.Errorf("foo.example.com returned certificate %d, not 2", n)
121 }
122 if n := pointerToIndex(certificateForName("foo.bar.example.com")); n != 0 {
123 t.Errorf("foo.bar.example.com returned certificate %d, not 0", n)
124 }
125 }
126
127
128 func runDynamicRecordSizingTest(t *testing.T, config *Config) {
129 clientConn, serverConn := localPipe(t)
130
131 serverConfig := config.Clone()
132 serverConfig.DynamicRecordSizingDisabled = false
133 tlsConn := Server(serverConn, serverConfig)
134
135 handshakeDone := make(chan struct{})
136 recordSizesChan := make(chan []int, 1)
137 defer func() { <-recordSizesChan }()
138 go func() {
139
140
141
142 defer close(recordSizesChan)
143 defer clientConn.Close()
144
145 tlsConn := Client(clientConn, config)
146 if err := tlsConn.Handshake(); err != nil {
147 t.Errorf("Error from client handshake: %v", err)
148 return
149 }
150 close(handshakeDone)
151
152 var recordHeader [recordHeaderLen]byte
153 var record []byte
154 var recordSizes []int
155
156 for {
157 n, err := io.ReadFull(clientConn, recordHeader[:])
158 if err == io.EOF {
159 break
160 }
161 if err != nil || n != len(recordHeader) {
162 t.Errorf("io.ReadFull = %d, %v", n, err)
163 return
164 }
165
166 length := int(recordHeader[3])<<8 | int(recordHeader[4])
167 if len(record) < length {
168 record = make([]byte, length)
169 }
170
171 n, err = io.ReadFull(clientConn, record[:length])
172 if err != nil || n != length {
173 t.Errorf("io.ReadFull = %d, %v", n, err)
174 return
175 }
176
177 recordSizes = append(recordSizes, recordHeaderLen+length)
178 }
179
180 recordSizesChan <- recordSizes
181 }()
182
183 if err := tlsConn.Handshake(); err != nil {
184 t.Fatalf("Error from server handshake: %s", err)
185 }
186 <-handshakeDone
187
188
189 plaintext := bytes.Join([][]byte{
190 bytes.Repeat([]byte("x"), recordSizeBoostThreshold),
191 bytes.Repeat([]byte("y"), maxPlaintext*2),
192 bytes.Repeat([]byte("z"), maxPlaintext),
193 }, nil)
194
195 if _, err := tlsConn.Write(plaintext); err != nil {
196 t.Fatalf("Error from server write: %s", err)
197 }
198 if err := tlsConn.Close(); err != nil {
199 t.Fatalf("Error from server close: %s", err)
200 }
201
202 recordSizes := <-recordSizesChan
203 if recordSizes == nil {
204 t.Fatalf("Client encountered an error")
205 }
206
207
208
209 recordSizes = recordSizes[:len(recordSizes)-2]
210
211
212
213 seenLargeRecord := false
214 for i, size := range recordSizes {
215 if !seenLargeRecord {
216 if size > (i+1)*tcpMSSEstimate {
217 t.Fatalf("Record #%d has size %d, which is too large too soon", i, size)
218 }
219 if size >= maxPlaintext {
220 seenLargeRecord = true
221 }
222 } else if size <= maxPlaintext {
223 t.Fatalf("Record #%d has size %d but should be full sized", i, size)
224 }
225 }
226
227 if !seenLargeRecord {
228 t.Fatalf("No large records observed")
229 }
230 }
231
232 func TestDynamicRecordSizingWithStreamCipher(t *testing.T) {
233 config := testConfig.Clone()
234 config.MaxVersion = VersionTLS12
235 config.CipherSuites = []uint16{TLS_RSA_WITH_RC4_128_SHA}
236 runDynamicRecordSizingTest(t, config)
237 }
238
239 func TestDynamicRecordSizingWithCBC(t *testing.T) {
240 config := testConfig.Clone()
241 config.MaxVersion = VersionTLS12
242 config.CipherSuites = []uint16{TLS_RSA_WITH_AES_256_CBC_SHA}
243 runDynamicRecordSizingTest(t, config)
244 }
245
246 func TestDynamicRecordSizingWithAEAD(t *testing.T) {
247 config := testConfig.Clone()
248 config.MaxVersion = VersionTLS12
249 config.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}
250 runDynamicRecordSizingTest(t, config)
251 }
252
253 func TestDynamicRecordSizingWithTLSv13(t *testing.T) {
254 config := testConfig.Clone()
255 runDynamicRecordSizingTest(t, config)
256 }
257
258
259
260 type hairpinConn struct {
261 net.Conn
262 tlsConn *Conn
263 }
264
265 func (conn *hairpinConn) Close() error {
266 conn.tlsConn.ConnectionState()
267 return nil
268 }
269
270 func TestHairpinInClose(t *testing.T) {
271
272
273 client, server := localPipe(t)
274 defer server.Close()
275 defer client.Close()
276
277 conn := &hairpinConn{client, nil}
278 tlsConn := Server(conn, &Config{
279 GetCertificate: func(*ClientHelloInfo) (*Certificate, error) {
280 panic("unreachable")
281 },
282 })
283 conn.tlsConn = tlsConn
284
285
286 tlsConn.Close()
287 }
288
View as plain text