1
18
19 package record
20
21 import (
22 "bytes"
23 "errors"
24 "net"
25 "reflect"
26 "testing"
27
28 "github.com/google/go-cmp/cmp"
29 "google.golang.org/protobuf/testing/protocmp"
30
31 commonpb "github.com/google/s2a-go/internal/proto/common_go_proto"
32 "github.com/google/s2a-go/internal/record/internal/aeadcrypter/testutil"
33 )
34
35 var errFakeConnEOF = errors.New("fakeConn is out of bounds")
36
37
38 type fakeConn struct {
39 net.Conn
40
41 bufCount int
42 buf [][]byte
43
44
45 additionalBuf [][]byte
46 closed bool
47 }
48
49
50
51 func (c *fakeConn) Read(b []byte) (n int, err error) {
52 if c.bufCount >= len(c.buf) {
53 return 0, errFakeConnEOF
54 }
55 n = copy(b, c.buf[c.bufCount])
56 if n < len(c.buf[c.bufCount]) {
57 c.buf[c.bufCount] = c.buf[c.bufCount][n:]
58 } else {
59 c.bufCount++
60 }
61 return n, nil
62 }
63
64
65
66 func (c *fakeConn) Write(b []byte) (n int, err error) {
67 buf := make([]byte, len(b))
68 n = copy(buf, b)
69 c.additionalBuf = append(c.additionalBuf, buf)
70 return n, nil
71 }
72
73 func (c *fakeConn) Close() error {
74 c.closed = true
75 return nil
76 }
77
78 type fakeTicketSender struct {
79 sessionTickets [][]byte
80 }
81
82 func (f *fakeTicketSender) sendTicketsToS2A(sessionTickets [][]byte, callComplete chan bool) {
83 f.sessionTickets = sessionTickets
84 go func() {
85 callComplete <- true
86 close(callComplete)
87 }()
88 }
89
90 func TestNewS2ARecordConn(t *testing.T) {
91 for _, tc := range []struct {
92 desc string
93 options *ConnParameters
94 outUnusedBytesBuf []byte
95 outOverheadSize int
96 outHandshakerServiceAddr string
97 outConnectionID uint64
98 outLocalIdentity *commonpb.Identity
99 outErr bool
100 }{
101 {
102 desc: "nil conn options",
103 outErr: true,
104 },
105 {
106 desc: "invalid input traffic secret size",
107 options: &ConnParameters{
108 NetConn: &fakeConn{},
109 Ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384,
110 TLSVersion: commonpb.TLSVersion_TLS1_3,
111 InTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
112 OutTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
113 HSAddr: "test handshaker address",
114 },
115 outErr: true,
116 },
117 {
118 desc: "invalid output traffic secret size",
119 options: &ConnParameters{
120 NetConn: &fakeConn{},
121 Ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384,
122 TLSVersion: commonpb.TLSVersion_TLS1_3,
123 InTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
124 OutTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
125 HSAddr: "test handshaker address",
126 },
127 outErr: true,
128 },
129 {
130 desc: "invalid tls version",
131 options: &ConnParameters{
132 NetConn: &fakeConn{},
133 Ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256,
134 TLSVersion: commonpb.TLSVersion_TLS1_2,
135 InTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
136 OutTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
137 HSAddr: "test handshaker address",
138 },
139 outErr: true,
140 },
141 {
142 desc: "basic with AES-128-GCM-SHA256",
143 options: &ConnParameters{
144 NetConn: &fakeConn{},
145 Ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256,
146 TLSVersion: commonpb.TLSVersion_TLS1_3,
147 InTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
148 OutTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
149 HSAddr: "test handshaker address",
150 ConnectionID: 1,
151 LocalIdentity: &commonpb.Identity{
152 IdentityOneof: &commonpb.Identity_SpiffeId{
153 SpiffeId: "test_spiffe_id",
154 },
155 },
156 },
157
158
159 outOverheadSize: 22,
160 outHandshakerServiceAddr: "test handshaker address",
161 outConnectionID: 1,
162 outLocalIdentity: &commonpb.Identity{
163 IdentityOneof: &commonpb.Identity_SpiffeId{
164 SpiffeId: "test_spiffe_id",
165 },
166 },
167 },
168 {
169 desc: "basic with AES-256-GCM-SHA384",
170 options: &ConnParameters{
171 NetConn: &fakeConn{},
172 Ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384,
173 TLSVersion: commonpb.TLSVersion_TLS1_3,
174 InTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
175 OutTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
176 HSAddr: "test handshaker address",
177 ConnectionID: 1,
178 LocalIdentity: &commonpb.Identity{
179 IdentityOneof: &commonpb.Identity_SpiffeId{
180 SpiffeId: "test_spiffe_id",
181 },
182 },
183 },
184
185
186 outOverheadSize: 22,
187 outHandshakerServiceAddr: "test handshaker address",
188 outConnectionID: 1,
189 outLocalIdentity: &commonpb.Identity{
190 IdentityOneof: &commonpb.Identity_SpiffeId{
191 SpiffeId: "test_spiffe_id",
192 },
193 },
194 },
195 {
196 desc: "basic with CHACHA20-POLY1305-SHA256",
197 options: &ConnParameters{
198 NetConn: &fakeConn{},
199 Ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256,
200 TLSVersion: commonpb.TLSVersion_TLS1_3,
201 InTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
202 OutTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
203 HSAddr: "test handshaker address",
204 ConnectionID: 1,
205 LocalIdentity: &commonpb.Identity{
206 IdentityOneof: &commonpb.Identity_SpiffeId{
207 SpiffeId: "test_spiffe_id",
208 },
209 },
210 },
211
212
213 outOverheadSize: 22,
214 outHandshakerServiceAddr: "test handshaker address",
215 outConnectionID: 1,
216 outLocalIdentity: &commonpb.Identity{
217 IdentityOneof: &commonpb.Identity_SpiffeId{
218 SpiffeId: "test_spiffe_id",
219 },
220 },
221 },
222 {
223 desc: "basic with unusedBytes",
224 options: &ConnParameters{
225 NetConn: &fakeConn{},
226 Ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256,
227 TLSVersion: commonpb.TLSVersion_TLS1_3,
228 InTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
229 OutTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
230 UnusedBuf: testutil.Dehex("ffffffff"),
231 HSAddr: "test handshaker address",
232 },
233 outUnusedBytesBuf: testutil.Dehex("ffffffff"),
234
235
236 outOverheadSize: 22,
237 outHandshakerServiceAddr: "test handshaker address",
238 },
239 } {
240 t.Run(tc.desc, func(t *testing.T) {
241 NetConn, err := NewConn(tc.options)
242 if got, want := err == nil, !tc.outErr; got != want {
243 t.Errorf("NewConn(%v) = (err=nil) = %v, want %v", *tc.options, got, want)
244 }
245 if err != nil {
246 return
247 }
248 conn := NetConn.(*conn)
249 if got, want := conn.unusedBuf, tc.outUnusedBytesBuf; !bytes.Equal(got, want) {
250 t.Errorf("conn.unusedBytes = %v, want %v", got, want)
251 }
252 if got, want := conn.overheadSize, tc.outOverheadSize; got != want {
253 t.Errorf("conn.overheadSize = %v, want %v", got, want)
254 }
255 ticketSender := conn.ticketSender.(*ticketSender)
256 if got, want := ticketSender.hsAddr, tc.outHandshakerServiceAddr; got != want {
257 t.Errorf("ticketSender.hsAddr = %v, want %v", got, want)
258 }
259 if got, want := ticketSender.connectionID, tc.outConnectionID; got != want {
260 t.Errorf("ticketSender.connectionID = %v, want %v", got, want)
261 }
262 if got, want := ticketSender.localIdentity, tc.outLocalIdentity; !cmp.Equal(got, want, protocmp.Transform()) {
263 t.Errorf("ticketSender.localIdentity = %v, want %v", got, want)
264 }
265 })
266 }
267 }
268
269 func TestStripPaddingAndType(t *testing.T) {
270 for _, tc := range []struct {
271 desc string
272 pendingApplicationData, outPendingApplicationData []byte
273 outContentType recordType
274 }{
275 {
276 desc: "no padding",
277 pendingApplicationData: []byte{byte(alert)},
278 outContentType: alert,
279 },
280 {
281 desc: "single padding",
282 pendingApplicationData: []byte{byte(applicationData), 0x00},
283 outContentType: applicationData,
284 },
285 {
286 desc: "multi padding",
287 pendingApplicationData: []byte{byte(handshake), 0x00, 0x00},
288 outContentType: handshake,
289 },
290 {
291 desc: "app data with no padding",
292 pendingApplicationData: []byte{0xff, byte(handshake)},
293 outPendingApplicationData: []byte{0xff},
294 outContentType: handshake,
295 },
296 {
297 desc: "app data with padding",
298 pendingApplicationData: []byte{0xff, byte(handshake), 0x00},
299 outPendingApplicationData: []byte{0xff},
300 outContentType: handshake,
301 },
302 } {
303 t.Run(tc.desc, func(t *testing.T) {
304 c := conn{pendingApplicationData: tc.pendingApplicationData}
305 ct, err := c.stripPaddingAndType()
306 if err != nil {
307 t.Errorf("c.stripPaddingAndType() failed: %v", err)
308 }
309 if got, want := c.pendingApplicationData, tc.outPendingApplicationData; !bytes.Equal(got, want) {
310 t.Errorf("c.pendingApplicationData = %v, want %v", got, want)
311 }
312 if got, want := ct, tc.outContentType; got != want {
313 t.Errorf("ct = %v, want %v", got, want)
314 }
315 })
316 }
317 }
318
319 func TestParseRecord(t *testing.T) {
320 for _, tc := range []struct {
321 desc string
322 b []byte
323 maxLen uint16
324 outCompletedRecord, outRemaining []byte
325 outErr bool
326 }{
327 {
328 desc: "buffer smaller than header size",
329 b: make([]byte, 1),
330 outRemaining: make([]byte, 1),
331 },
332 {
333 desc: "header payload size larger than maxLen",
334 b: testutil.Dehex("000000ffff"),
335 maxLen: 1,
336 outRemaining: testutil.Dehex("000000ffff"),
337 outErr: true,
338 },
339 {
340 desc: "header payload size same as maxLen",
341 b: testutil.Dehex("0000000003ffffff"),
342 maxLen: 3,
343 outCompletedRecord: testutil.Dehex("0000000003ffffff"),
344 },
345 {
346 desc: "incomplete record",
347 b: testutil.Dehex("0000000001"),
348 maxLen: 10,
349 outRemaining: testutil.Dehex("0000000001"),
350 },
351 {
352 desc: "complete record",
353 b: testutil.Dehex("0000000001ff"),
354 maxLen: 10,
355 outCompletedRecord: testutil.Dehex("0000000001ff"),
356 },
357 } {
358 t.Run(tc.desc, func(t *testing.T) {
359 completedRecord, remaining, err := parseReadBuffer(tc.b, tc.maxLen)
360 if got, want := err == nil, !tc.outErr; got != want {
361 t.Errorf("parseReadBuffer(%v, %v) = (err=nil) = %v, want %v", tc.b, tc.maxLen, got, want)
362 }
363 if err != nil {
364 return
365 }
366 if got, want := completedRecord, tc.outCompletedRecord; !bytes.Equal(got, want) {
367 t.Errorf("completedRecord = %v, want %v", got, want)
368 }
369 if got, want := remaining, tc.outRemaining; !bytes.Equal(got, want) {
370 t.Errorf("remaining = %v, want %v", got, want)
371 }
372 })
373 }
374 }
375
376 func TestReadCompletedRecord(t *testing.T) {
377 for _, tc := range []struct {
378 desc string
379 connBufs [][]byte
380 nextRecord, unusedBuf []byte
381 outCompletedRecords [][]byte
382 outErr bool
383 }{
384 {
385 desc: "invalid record header size",
386 nextRecord: testutil.Dehex("170303ffff"),
387 outErr: true,
388 },
389 {
390 desc: "complete record in single read",
391 connBufs: [][]byte{
392 testutil.Dehex("1703030001ff"),
393 },
394 outCompletedRecords: [][]byte{
395 testutil.Dehex("1703030001ff"),
396 },
397 },
398 {
399 desc: "complete record in single read from leftover buffer",
400 nextRecord: testutil.Dehex("1703030001ff"),
401 outCompletedRecords: [][]byte{
402 testutil.Dehex("1703030001ff"),
403 },
404 },
405 {
406 desc: "complete record split in header",
407 connBufs: [][]byte{
408 testutil.Dehex("170303"),
409 testutil.Dehex("0001ff"),
410 },
411 unusedBuf: make([]byte, tlsRecordMaxPlaintextSize),
412 outCompletedRecords: [][]byte{
413 testutil.Dehex("1703030001ff"),
414 },
415 },
416 {
417 desc: "complete record split in ciphertext",
418 connBufs: [][]byte{
419 testutil.Dehex("1703030002ff"),
420 testutil.Dehex("ff"),
421 },
422 unusedBuf: make([]byte, tlsRecordMaxPlaintextSize),
423 outCompletedRecords: [][]byte{
424 testutil.Dehex("1703030002ffff"),
425 },
426 },
427 {
428 desc: "two complete records split in header",
429 connBufs: [][]byte{
430 testutil.Dehex("170303"),
431 testutil.Dehex("0002ffff1703030001ff"),
432 },
433 unusedBuf: make([]byte, tlsRecordMaxPlaintextSize),
434 outCompletedRecords: [][]byte{
435 testutil.Dehex("1703030002ffff"),
436 testutil.Dehex("1703030001ff"),
437 },
438 },
439 {
440 desc: "two complete records split in second header",
441 connBufs: [][]byte{
442 testutil.Dehex("1703030002ffff1703"),
443 testutil.Dehex("030001ff"),
444 },
445 unusedBuf: make([]byte, tlsRecordMaxPlaintextSize),
446 outCompletedRecords: [][]byte{
447 testutil.Dehex("1703030002ffff"),
448 testutil.Dehex("1703030001ff"),
449 },
450 },
451 {
452 desc: "two complete records split in ciphertext",
453 connBufs: [][]byte{
454 testutil.Dehex("1703030002ff"),
455 testutil.Dehex("ff1703030001ff"),
456 },
457 unusedBuf: make([]byte, tlsRecordMaxPlaintextSize),
458 outCompletedRecords: [][]byte{
459 testutil.Dehex("1703030002ffff"),
460 testutil.Dehex("1703030001ff"),
461 },
462 },
463 {
464 desc: "two complete records split in second ciphertext",
465 connBufs: [][]byte{
466 testutil.Dehex("1703030002ffff1703030002ff"),
467 testutil.Dehex("ff"),
468 },
469 unusedBuf: make([]byte, tlsRecordMaxPlaintextSize),
470 outCompletedRecords: [][]byte{
471 testutil.Dehex("1703030002ffff"),
472 testutil.Dehex("1703030002ffff"),
473 },
474 },
475 {
476 desc: "complete record split by each byte",
477 connBufs: [][]byte{
478 {0x17}, {0x03}, {0x03}, {0x00}, {0x01}, {0xff},
479 },
480 unusedBuf: make([]byte, tlsRecordMaxPlaintextSize),
481 outCompletedRecords: [][]byte{
482 testutil.Dehex("1703030001ff"),
483 },
484 },
485 } {
486 t.Run(tc.desc, func(t *testing.T) {
487 fConn := &fakeConn{buf: tc.connBufs}
488 c := &conn{Conn: fConn, nextRecord: tc.nextRecord, unusedBuf: tc.unusedBuf}
489 for _, outCompletedRecord := range tc.outCompletedRecords {
490 completedRecord, err := c.readFullRecord()
491 if got, want := err == nil, !tc.outErr; got != want {
492 t.Errorf("c.readCompletecRecord() = (err=nil) = %v, want %v", got, want)
493 }
494 if err != nil {
495 return
496 }
497 if got, want := completedRecord, outCompletedRecord; !bytes.Equal(got, want) {
498 t.Errorf("c.readFullRecord() = %v, want %v", got, want)
499 }
500 }
501 })
502 }
503 }
504
505 func TestSplitAndValidateHeader(t *testing.T) {
506 for _, tc := range []struct {
507 desc string
508 completedRecord []byte
509 outHeader, outCiphertext []byte
510 outErr bool
511 }{
512 {
513 desc: "invalid header type",
514 completedRecord: make([]byte, tlsRecordHeaderSize),
515 outErr: true,
516 },
517 {
518 desc: "invalid legacy record version",
519 completedRecord: []byte{byte(tlsApplicationData), 0x00, 0x00, 0x00, 0x00},
520 outErr: true,
521 },
522 {
523 desc: "basic with no ciphertext",
524 completedRecord: []byte{byte(tlsApplicationData), 0x03, 0x03, 0x00, 0x00},
525 outHeader: []byte{byte(tlsApplicationData), 0x03, 0x03, 0x00, 0x00},
526 },
527 {
528 desc: "basic with ciphertext",
529 completedRecord: []byte{byte(tlsApplicationData), 0x03, 0x03, 0x00, 0x01, 0xff},
530 outHeader: []byte{byte(tlsApplicationData), 0x03, 0x03, 0x00, 0x01},
531 outCiphertext: []byte{0xff},
532 },
533 } {
534 t.Run(tc.desc, func(t *testing.T) {
535 header, ciphertext, err := splitAndValidateHeader(tc.completedRecord)
536 if got, want := err == nil, !tc.outErr; got != want {
537 t.Errorf("splitAndValidateHeader(%v) = (err=nil) = %v, want %v", tc.completedRecord, got, want)
538 }
539 if err != nil {
540 return
541 }
542 if got, want := header, tc.outHeader; !bytes.Equal(got, want) {
543 t.Errorf("header = %v, want %v", got, want)
544 }
545 if got, want := ciphertext, tc.outCiphertext; !bytes.Equal(got, want) {
546 t.Errorf("ciphertext = %v, want %v", got, want)
547 }
548 })
549 }
550 }
551
552 func TestConnReadApplicationData(t *testing.T) {
553 for _, tc := range []struct {
554 desc string
555 ciphersuite commonpb.Ciphersuite
556 trafficSecret []byte
557 completedRecords [][]byte
558 outPlaintexts [][]byte
559 outErr bool
560 }{
561
562
563
564 {
565 desc: "AES-128-GCM-SHA256 with no padding",
566 ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256,
567 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
568 completedRecords: [][]byte{
569 testutil.Dehex("1703030017f2e4e411ac6760e4e3f074a36574c45ee4c1906103db0d"),
570 testutil.Dehex("170303001ad7853afd6d7ceaabab950a0b6707905d2b908894871c7c62021f"),
571 },
572 outPlaintexts: [][]byte{
573 []byte("123456"),
574 []byte("789123456"),
575 },
576 },
577 {
578 desc: "AES-128-GCM-SHA256 with padding",
579 ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256,
580 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
581 completedRecords: [][]byte{
582 testutil.Dehex("1703030021f2e4e411ac6760e84726e4886d7432e39b34f0fccfc1f4558303c68a19535c0ff5"),
583 },
584 outPlaintexts: [][]byte{
585 []byte("123456"),
586 },
587 },
588 {
589 desc: "AES-128-GCM-SHA256 empty",
590 ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256,
591 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
592 completedRecords: [][]byte{
593 testutil.Dehex("1703030011d47cb2ec040f26cc8989330339c669dd4e"),
594 },
595 outPlaintexts: [][]byte{
596 []byte(""),
597 },
598 },
599 {
600 desc: "AES-256-GCM-SHA384 with no padding",
601 ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384,
602 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
603 completedRecords: [][]byte{
604 testutil.Dehex("170303001724efee5af1a62170ad5a95f899d038b965386a1a7daed9"),
605 testutil.Dehex("170303001a832a5fd271b6442e74bc02111a8e8b52a74b14dd3eca8598b293"),
606 },
607 outPlaintexts: [][]byte{
608 []byte("123456"),
609 []byte("789123456"),
610 },
611 },
612 {
613 desc: "AES-256-GCM-SHA384 with padding",
614 ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384,
615 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
616 completedRecords: [][]byte{
617 testutil.Dehex("170303002124efee5af1a621e8a4d1f269930e7835cfdd05e2d0bec5b01a67decfa6372c2af7"),
618 },
619 outPlaintexts: [][]byte{
620 []byte("123456"),
621 },
622 },
623 {
624 desc: "AES-256-GCM-SHA384 empty",
625 ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384,
626 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
627 completedRecords: [][]byte{
628 testutil.Dehex("170303001102a04134d38c1118f36b01d177c5d2dcf7"),
629 },
630 outPlaintexts: [][]byte{
631 []byte(""),
632 },
633 },
634 {
635 desc: "CHACHA20-POLY1305-SHA256 with no padding",
636 ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256,
637 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
638 completedRecords: [][]byte{
639 testutil.Dehex("1703030017c947ffa470304370338bb07ce468e6b8a0944a338ba402"),
640 testutil.Dehex("170303001a0cedeb922170c110c172262542c67916b78fa0d1c1261709cd00"),
641 },
642 outPlaintexts: [][]byte{
643 []byte("123456"),
644 []byte("789123456"),
645 },
646 },
647 {
648 desc: "CHACHA20-POLY1305-SHA256 with padding",
649 ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256,
650 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
651 completedRecords: [][]byte{
652 testutil.Dehex("1703030021c947ffa4703043f063e7b6a0519fbd0956cf3a7c9730c13597eec17ec7e700f140"),
653 },
654 outPlaintexts: [][]byte{
655 []byte("123456"),
656 },
657 },
658 {
659 desc: "CHACHA20-POLY1305-SHA256 empty",
660 ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256,
661 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
662 completedRecords: [][]byte{
663 testutil.Dehex("1703030011ef8f7a428ddc84ee5968cd6306bf1d2d1b"),
664 },
665 outPlaintexts: [][]byte{
666 []byte(""),
667 },
668 },
669 {
670 desc: "AES-128-GCM-SHA256 split in first record",
671 ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256,
672 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
673 completedRecords: [][]byte{
674 testutil.Dehex("1703030017f2e4e411ac6760"),
675 testutil.Dehex("e4e3f074a36574c45ee4c1906103db0d"),
676 },
677 outPlaintexts: [][]byte{
678 []byte("123456"),
679 },
680 },
681 {
682 desc: "AES-256-GCM-SHA384 split in first record",
683 ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384,
684 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
685 completedRecords: [][]byte{
686 testutil.Dehex("170303001724efee5af1a6"),
687 testutil.Dehex("2170ad5a95f899d038b965386a1a7daed9"),
688 },
689 outPlaintexts: [][]byte{
690 []byte("123456"),
691 },
692 },
693 {
694 desc: "CHACHA20-POLY1305-SHA256 split in first record",
695 ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256,
696 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
697 completedRecords: [][]byte{
698 testutil.Dehex("1703030017c947ffa470"),
699 testutil.Dehex("304370338bb07ce468e6b8a0944a338ba402"),
700 },
701 outPlaintexts: [][]byte{
702 []byte("123456"),
703 },
704 },
705 {
706 desc: "AES-128-GCM-SHA256 split in first record header",
707 ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256,
708 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
709 completedRecords: [][]byte{
710 testutil.Dehex("17"),
711 testutil.Dehex("03030017f2e4e411ac6760e4e3f074a36574c45ee4c1906103db0d"),
712 },
713 outPlaintexts: [][]byte{
714 []byte("123456"),
715 },
716 },
717 {
718 desc: "AES-256-GCM-SHA384 split in first record header",
719 ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384,
720 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
721 completedRecords: [][]byte{
722 testutil.Dehex("17"),
723 testutil.Dehex("0303001724efee5af1a62170ad5a95f899d038b965386a1a7daed9"),
724 },
725 outPlaintexts: [][]byte{
726 []byte("123456"),
727 },
728 },
729 {
730 desc: "CHACHA20-POLY1305-SHA256 split in first record header",
731 ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256,
732 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
733 completedRecords: [][]byte{
734 testutil.Dehex("17"),
735 testutil.Dehex("03030017c947ffa470304370338bb07ce468e6b8a0944a338ba402"),
736 },
737 outPlaintexts: [][]byte{
738 []byte("123456"),
739 },
740 },
741 {
742 desc: "AES-128-GCM-SHA256 split in second record",
743 ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256,
744 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
745 completedRecords: [][]byte{
746 testutil.Dehex("1703030017f2e4e411ac6760e4e3f074a36574c45ee4c1906103db0d170303001ad7"),
747 testutil.Dehex("853afd6d7ceaabab950a0b6707905d2b908894871c7c62021f"),
748 },
749 outPlaintexts: [][]byte{
750 []byte("123456"),
751 []byte("789123456"),
752 },
753 },
754 {
755 desc: "AES-256-GCM-SHA384 split in second record",
756 ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384,
757 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
758 completedRecords: [][]byte{
759 testutil.Dehex("170303001724efee5af1a62170ad5a95f899d038b965386a1a7daed9170303001a83"),
760 testutil.Dehex("2a5fd271b6442e74bc02111a8e8b52a74b14dd3eca8598b293"),
761 },
762 outPlaintexts: [][]byte{
763 []byte("123456"),
764 []byte("789123456"),
765 },
766 },
767 {
768 desc: "CHACHA20-POLY1305-SHA256 split in second record",
769 ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256,
770 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
771 completedRecords: [][]byte{
772 testutil.Dehex("1703030017c947ffa470304370338bb07ce468e6b8a0944a338ba402170303001a0c"),
773 testutil.Dehex("edeb922170c110c172262542c67916b78fa0d1c1261709cd00"),
774 },
775 outPlaintexts: [][]byte{
776 []byte("123456"),
777 []byte("789123456"),
778 },
779 },
780 {
781 desc: "AES-128-GCM-SHA256 split in second record header",
782 ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256,
783 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
784 completedRecords: [][]byte{
785 testutil.Dehex("1703030017f2e4e411ac6760e4e3f074a36574c45ee4c1906103db0d17"),
786 testutil.Dehex("0303001ad7853afd6d7ceaabab950a0b6707905d2b908894871c7c62021f"),
787 },
788 outPlaintexts: [][]byte{
789 []byte("123456"),
790 []byte("789123456"),
791 },
792 },
793 {
794 desc: "AES-256-GCM-SHA384 split in second record header",
795 ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384,
796 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
797 completedRecords: [][]byte{
798 testutil.Dehex("170303001724efee5af1a62170ad5a95f899d038b965386a1a7daed917"),
799 testutil.Dehex("0303001a832a5fd271b6442e74bc02111a8e8b52a74b14dd3eca8598b293"),
800 },
801 outPlaintexts: [][]byte{
802 []byte("123456"),
803 []byte("789123456"),
804 },
805 },
806 {
807 desc: "CHACHA20-POLY1305-SHA256 split in second record header",
808 ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256,
809 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
810 completedRecords: [][]byte{
811 testutil.Dehex("1703030017c947ffa470304370338bb07ce468e6b8a0944a338ba40217"),
812 testutil.Dehex("0303001a0cedeb922170c110c172262542c67916b78fa0d1c1261709cd00"),
813 },
814 outPlaintexts: [][]byte{
815 []byte("123456"),
816 []byte("789123456"),
817 },
818 },
819 {
820 desc: "AES-128-GCM-SHA256 split randomly",
821 ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256,
822 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
823 completedRecords: [][]byte{
824 testutil.Dehex("1703030017f2e4e411ac6760e4"),
825 testutil.Dehex("e3f074a36574c45ee4c1906103db0d17"),
826 testutil.Dehex("0303001ad7853afd6d7ceaab"),
827 testutil.Dehex("ab950a0b6707905d2b908894871c7c62021f"),
828 },
829 outPlaintexts: [][]byte{
830 []byte("123456"),
831 []byte("789123456"),
832 },
833 },
834 {
835 desc: "AES-256-GCM-SHA384 split randomly",
836 ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384,
837 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
838 completedRecords: [][]byte{
839 testutil.Dehex("170303001724efee"),
840 testutil.Dehex("5af1a62170ad5a95f899d038b965386a1a7daed917"),
841 testutil.Dehex("03"),
842 testutil.Dehex("03001a832a5fd271b6442e74bc02111a8e8b52a74b14dd3eca8598b293"),
843 },
844 outPlaintexts: [][]byte{
845 []byte("123456"),
846 []byte("789123456"),
847 },
848 },
849 {
850 desc: "CHACHA20-POLY1305-SHA256 split randomly",
851 ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256,
852 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
853 completedRecords: [][]byte{
854 testutil.Dehex("17"),
855 testutil.Dehex("03030017c947ffa470304370338bb07ce468e6b8a0944a338ba40217"),
856 testutil.Dehex("0303001a0cedeb922170"),
857 testutil.Dehex("c110c172262542c67916b78fa0d1c1261709cd00"),
858 },
859 outPlaintexts: [][]byte{
860 []byte("123456"),
861 []byte("789123456"),
862 },
863 },
864 } {
865 t.Run(tc.desc, func(t *testing.T) {
866 c, err := NewConn(&ConnParameters{
867 NetConn: &fakeConn{buf: tc.completedRecords},
868 Ciphersuite: tc.ciphersuite,
869 TLSVersion: commonpb.TLSVersion_TLS1_3,
870 InTrafficSecret: tc.trafficSecret,
871 OutTrafficSecret: tc.trafficSecret,
872 })
873 if err != nil {
874 t.Fatalf("NewConn() failed: %v", err)
875 }
876 for _, outPlaintext := range tc.outPlaintexts {
877 plaintext := make([]byte, tlsRecordMaxPlaintextSize)
878 n, err := c.Read(plaintext)
879 if got, want := err == nil, !tc.outErr; got != want {
880 t.Errorf("c.Read(plaintext) = (err=nil) = %v, want %v", got, want)
881 }
882 if err != nil {
883 return
884 }
885 plaintext = plaintext[:n]
886 if got, want := plaintext, outPlaintext; !bytes.Equal(got, want) {
887 t.Errorf("c.Read(plaintext) = %v, want %v", got, want)
888 }
889 }
890 })
891 }
892 }
893
894 func TestConnReadAlert(t *testing.T) {
895 for _, tc := range []struct {
896 desc string
897 ciphersuite commonpb.Ciphersuite
898 trafficSecret []byte
899 completedRecord []byte
900 }{
901
902
903
904
905 {
906 desc: "AES-128-GCM-SHA256 with no padding",
907 ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256,
908 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
909 completedRecord: testutil.Dehex("1703030013c2d6c245fb80969de1dd9d14499261b67735b0"),
910 },
911 {
912 desc: "AES-128-GCM-SHA256 with padding",
913 ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256,
914 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
915 completedRecord: testutil.Dehex("170303001dc2d6c225995177e84726e4886d5ea79383e5d529cd8339fbbfcafe2418"),
916 },
917 {
918 desc: "AES-256-GCM-SHA384 with no padding",
919 ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384,
920 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
921 completedRecord: testutil.Dehex("170303001314ddc8f3b3856660bb5ac81533c157582f8b4c"),
922 },
923 {
924 desc: "AES-256-GCM-SHA384 with padding",
925 ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384,
926 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
927 completedRecord: testutil.Dehex("170303001d14ddc86ec49036e8a4d1f269933545f03b0fe9ffd8b02acd1e41f7139e"),
928 },
929 {
930 desc: "CHACHA20-POLY1305-SHA256 with no padding",
931 ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256,
932 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
933 completedRecord: testutil.Dehex("1703030013f975d9cb2f116d85d4e3859f5288a9b013d778"),
934 },
935 {
936 desc: "CHACHA20-POLY1305-SHA256 with padding",
937 ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256,
938 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
939 completedRecord: testutil.Dehex("170303001df975d990450654f063e7b6a0514c2714c9827e796071389802f451585a"),
940 },
941
942
943
944 {
945 desc: "AES-128-GCM-SHA256 other alert",
946 ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256,
947 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
948 completedRecord: testutil.Dehex("1703030013c2fac23f995cbe79a8d1e4c8f0353afefeaac9"),
949 },
950 {
951 desc: "AES-256-GCM-SHA384 other alert",
952 ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384,
953 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
954 completedRecord: testutil.Dehex("170303001314f1c80add85193c9598219ae9dc26f2479ccf"),
955 },
956 {
957 desc: "CHACHA20-POLY1305-SHA256 other alert",
958 ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256,
959 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
960 completedRecord: testutil.Dehex("1703030013f959d96fed92bdc7e85e04e86c19eaf154b052"),
961 },
962
963
964
965
966
967 {
968 desc: "AES-128-GCM-SHA256 invalid",
969 ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256,
970 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
971 completedRecord: testutil.Dehex("1703030012c2c351fc48d9ac84fa165adcc9a26ffbc3c7"),
972 },
973 {
974 desc: "AES-256-GCM-SHA384 invalid",
975 ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384,
976 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
977 completedRecord: testutil.Dehex("170303001214c8476102a460b5cf9e9ba59e1726215ca9"),
978 },
979 {
980 desc: "CHACHA20-POLY1305-SHA256 invalid",
981 ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256,
982 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
983 completedRecord: testutil.Dehex("1703030012f9606a83ac17b165a51f3fe764da8560c706"),
984 },
985 } {
986 t.Run(tc.desc, func(t *testing.T) {
987 f := &fakeConn{buf: [][]byte{tc.completedRecord}}
988 c, err := NewConn(&ConnParameters{
989 NetConn: f,
990 Ciphersuite: tc.ciphersuite,
991 TLSVersion: commonpb.TLSVersion_TLS1_3,
992 InTrafficSecret: tc.trafficSecret,
993 OutTrafficSecret: tc.trafficSecret,
994 })
995 if err != nil {
996 t.Fatalf("NewConn() failed: %v", err)
997 }
998 plaintext := make([]byte, tlsRecordMaxPlaintextSize)
999 _, err = c.Read(plaintext)
1000 if got, want := err == nil, false; got != want {
1001 t.Errorf("c.Read(plaintext) = (err=nil) = %v, want %v", got, want)
1002 }
1003 })
1004 }
1005 }
1006
1007 func TestConnReadKeyUpdate(t *testing.T) {
1008 for _, tc := range []struct {
1009 desc string
1010 ciphersuite commonpb.Ciphersuite
1011 trafficSecret []byte
1012 completedRecords [][]byte
1013 plaintexts [][]byte
1014 outPlaintexts [][]byte
1015 outWriteBuf [][]byte
1016 }{
1017 {
1018 desc: "AES-128-GCM-SHA256",
1019 ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256,
1020 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
1021 completedRecords: [][]byte{
1022 testutil.Dehex("1703030020dbd6d724994777e84726e4886d7432e311a73b42d0073f28ea60e30e8eb498fd"),
1023 testutil.Dehex("1703030017dd99ebef48292cd4c372a000740372d2ae9aad31cfd274"),
1024 },
1025 plaintexts: [][]byte{
1026 []byte("123456"),
1027 },
1028 outPlaintexts: [][]byte{
1029 []byte(""),
1030 []byte("123456"),
1031 },
1032 outWriteBuf: [][]byte{
1033 testutil.Dehex("1703030017f2e4e411ac6760e4e3f074a36574c45ee4c1906103db0d"),
1034 },
1035 },
1036 {
1037 desc: "AES-256-GCM-SHA384",
1038 ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384,
1039 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
1040 completedRecords: [][]byte{
1041 testutil.Dehex("17030300200ddddd6fc48636e8a4d1f269930e7835adc07e732ba7fd617ff9a65a51c36b6d"),
1042 testutil.Dehex("17030300179cd5972e76baf56af644c92235460301c0a013ad35be00"),
1043 },
1044 plaintexts: [][]byte{
1045 []byte("123456"),
1046 },
1047 outPlaintexts: [][]byte{
1048 []byte(""),
1049 []byte("123456"),
1050 },
1051 outWriteBuf: [][]byte{
1052 testutil.Dehex("170303001724efee5af1a62170ad5a95f899d038b965386a1a7daed9"),
1053 },
1054 },
1055 {
1056 desc: "CHACHA20-POLY1305-SHA256",
1057 ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256,
1058 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
1059 completedRecords: [][]byte{
1060 testutil.Dehex("1703030020e075cc91451054f063e7b6a0519fbd098e83bda4b515bea5196cccc008556ad0"),
1061 testutil.Dehex("1703030017c4e48ccaf036bd9bc146bbc6192404f9a2d2da5d1afe78"),
1062 },
1063 plaintexts: [][]byte{
1064 []byte("123456"),
1065 },
1066 outPlaintexts: [][]byte{
1067 []byte(""),
1068 []byte("123456"),
1069 },
1070 outWriteBuf: [][]byte{
1071 testutil.Dehex("1703030017c947ffa470304370338bb07ce468e6b8a0944a338ba402"),
1072 },
1073 },
1074 {
1075 desc: "AES-128-GCM-SHA256 send key update request",
1076 ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256,
1077 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
1078 completedRecords: [][]byte{
1079 testutil.Dehex("1703030016dbd6d724984756cc7bd50502b024f94b489f1a943df5"),
1080 testutil.Dehex("1703030017dd99ebef48292cd4c372a000740372d2ae9aad31cfd274"),
1081 },
1082 plaintexts: [][]byte{
1083 []byte("123456"),
1084 },
1085 outPlaintexts: [][]byte{
1086 []byte(""),
1087 []byte("123456"),
1088 },
1089 outWriteBuf: [][]byte{
1090 testutil.Dehex("1703030016dbd6d7249947cdda08655a3c2622891c1758fb0c0d0e"),
1091 testutil.Dehex("1703030017dd99ebef48292cd4c372a000740372d2ae9aad31cfd274"),
1092 },
1093 },
1094 {
1095 desc: "AES-256-GCM-SHA384 send key update request",
1096 ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384,
1097 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
1098 completedRecords: [][]byte{
1099 testutil.Dehex("17030300160ddddd6fc5862e8275a95a35a9a43502a1da78f8a416"),
1100 testutil.Dehex("17030300179cd5972e76baf56af644c92235460301c0a013ad35be00"),
1101 },
1102 plaintexts: [][]byte{
1103 []byte("123456"),
1104 },
1105 outPlaintexts: [][]byte{
1106 []byte(""),
1107 []byte("123456"),
1108 },
1109 outWriteBuf: [][]byte{
1110 testutil.Dehex("17030300160ddddd6fc486a82b55d4457e3dc846f77b6d3f24de45"),
1111 testutil.Dehex("17030300179cd5972e76baf56af644c92235460301c0a013ad35be00"),
1112 },
1113 },
1114 {
1115 desc: "CHACHA20-POLY1305-SHA256 send key update request",
1116 ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256,
1117 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
1118 completedRecords: [][]byte{
1119 testutil.Dehex("1703030016e075cc914410ffeb7e4d960f8e3b1e830c137cc69692"),
1120 testutil.Dehex("1703030017c4e48ccaf036bd9bc146bbc6192404f9a2d2da5d1afe78"),
1121 },
1122 plaintexts: [][]byte{
1123 []byte("123456"),
1124 },
1125 outPlaintexts: [][]byte{
1126 []byte(""),
1127 []byte("123456"),
1128 },
1129 outWriteBuf: [][]byte{
1130 testutil.Dehex("1703030016e075cc914510bc0dbc87cfc12f394b235147042f42d0"),
1131 testutil.Dehex("1703030017c4e48ccaf036bd9bc146bbc6192404f9a2d2da5d1afe78"),
1132 },
1133 },
1134 } {
1135 t.Run(tc.desc, func(t *testing.T) {
1136 fConn := &fakeConn{buf: tc.completedRecords}
1137 c, err := NewConn(&ConnParameters{
1138 NetConn: fConn,
1139 Ciphersuite: tc.ciphersuite,
1140 TLSVersion: commonpb.TLSVersion_TLS1_3,
1141 InTrafficSecret: tc.trafficSecret,
1142 OutTrafficSecret: tc.trafficSecret,
1143 })
1144 if err != nil {
1145 t.Fatalf("NewConn() failed: %v", err)
1146 }
1147 for _, outPlaintext := range tc.outPlaintexts {
1148 plaintext := make([]byte, tlsRecordMaxPlaintextSize)
1149 n, err := c.Read(plaintext)
1150 if err != nil {
1151 t.Fatalf("c.Read(plaintext) failed: %v", err)
1152 }
1153 plaintext = plaintext[:n]
1154 if got, want := plaintext, outPlaintext; !bytes.Equal(got, want) {
1155 t.Errorf("c.Read(plaintext) = %v, want %v", got, want)
1156 }
1157 }
1158
1159
1160
1161 for _, plaintext := range tc.plaintexts {
1162 n, err := c.Write(plaintext)
1163 if err != nil {
1164 t.Fatalf("c.Write(plaintext) failed: %v", err)
1165 }
1166 if got, want := n, len(plaintext); got != want {
1167 t.Fatalf("c.Write(plaintext) = %v, want %v", got, want)
1168 }
1169 }
1170 if got, want := fConn.additionalBuf, tc.outWriteBuf; !cmp.Equal(fConn.additionalBuf, tc.outWriteBuf) {
1171 t.Errorf("fConn.additionalBuf = %x, want %x", got, want)
1172 }
1173 if got, want := len(c.(*conn).pendingApplicationData), 0; got != want {
1174 t.Errorf("len(c.(*conn).pendingApplicationData) = %v, want %v", got, want)
1175 }
1176
1177
1178
1179
1180 fConn2 := &fakeConn{buf: tc.outWriteBuf}
1181 c2, err := NewConn(&ConnParameters{
1182 NetConn: fConn2,
1183 Ciphersuite: tc.ciphersuite,
1184 TLSVersion: commonpb.TLSVersion_TLS1_3,
1185 InTrafficSecret: tc.trafficSecret,
1186 OutTrafficSecret: tc.trafficSecret,
1187 })
1188 if err != nil {
1189 t.Fatalf("NewConn() failed: %v", err)
1190 }
1191 for range tc.outWriteBuf {
1192 plaintext := make([]byte, tlsRecordMaxPlaintextSize)
1193 _, err := c2.Read(plaintext)
1194 if err != nil {
1195 t.Fatalf("c.Read(plaintext) failed: %v", err)
1196 }
1197 }
1198 })
1199 }
1200 }
1201
1202
1203 func buildSessionTicket(msg []byte) []byte {
1204 b := make([]byte, tlsHandshakePrefixSize+len(msg))
1205 b[0] = tlsHandshakeNewSessionTicketType
1206 v := len(msg)
1207 b[1] = byte(v >> 16)
1208 b[2] = byte(v >> 8)
1209 b[3] = byte(v)
1210 copy(b[4:], msg)
1211 return b
1212 }
1213
1214 func TestConnNewSessionTicket(t *testing.T) {
1215 emptyTicket := []byte{4, 0, 0, 1, 0}
1216 for _, tc := range []struct {
1217 desc string
1218 ciphersuite commonpb.Ciphersuite
1219 trafficSecret []byte
1220 completedRecords [][]byte
1221 outPlaintexts [][]byte
1222 finalTicketState sessionTicketState
1223 outSessionTickets [][]byte
1224 ticketsSent bool
1225 }{
1226
1227
1228
1229 {
1230 desc: "AES-128-GCM-SHA256 new session ticket",
1231 ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256,
1232 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
1233 completedRecords: [][]byte{
1234 testutil.Dehex("1703030016c7d6d72499478b3d80281cae5b7c1a3e5cd553aae716"),
1235 },
1236 outPlaintexts: [][]byte{
1237 []byte(""),
1238 },
1239 finalTicketState: receivingTickets,
1240 outSessionTickets: [][]byte{
1241 emptyTicket,
1242 },
1243 },
1244 {
1245 desc: "AES-256-GCM-SHA384 new session ticket",
1246 ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384,
1247 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
1248 completedRecords: [][]byte{
1249 testutil.Dehex("170303001611dddd6fc4869be0e1c12a5a29db1aa2e5814e5894e5"),
1250 },
1251 outPlaintexts: [][]byte{
1252 []byte(""),
1253 },
1254 finalTicketState: receivingTickets,
1255 outSessionTickets: [][]byte{
1256 emptyTicket,
1257 },
1258 },
1259 {
1260 desc: "CHACHA20-POLY1305-SHA256 new session ticket",
1261 ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256,
1262 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
1263 completedRecords: [][]byte{
1264 testutil.Dehex("1703030016fc75cc914510008c6B45bb46b1f030921006c3556882"),
1265 },
1266 outPlaintexts: [][]byte{
1267 []byte(""),
1268 },
1269 finalTicketState: receivingTickets,
1270 outSessionTickets: [][]byte{
1271 emptyTicket,
1272 },
1273 },
1274 {
1275 desc: "AES-128-GCM-SHA256 new session ticket followed by application data",
1276 ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256,
1277 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
1278 completedRecords: [][]byte{
1279 testutil.Dehex("1703030016c7d6d72499478b3d80281cae5b7c1a3e5cd553aae716"),
1280 testutil.Dehex("170303001ad7853afd6d7ceaabab950a0b6707905d2b908894871c7c62021f"),
1281 },
1282 outPlaintexts: [][]byte{
1283 []byte(""),
1284 []byte("789123456"),
1285 },
1286 finalTicketState: notReceivingTickets,
1287 outSessionTickets: [][]byte{
1288 emptyTicket,
1289 },
1290 ticketsSent: true,
1291 },
1292 {
1293 desc: "AES-256-GCM-SHA384 new session ticket followed by application data",
1294 ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384,
1295 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
1296 completedRecords: [][]byte{
1297 testutil.Dehex("170303001611dddd6fc4869be0e1c12a5a29db1aa2e5814e5894e5"),
1298 testutil.Dehex("170303001a832a5fd271b6442e74bc02111a8e8b52a74b14dd3eca8598b293"),
1299 },
1300 outPlaintexts: [][]byte{
1301 []byte(""),
1302 []byte("789123456"),
1303 },
1304 finalTicketState: notReceivingTickets,
1305 outSessionTickets: [][]byte{
1306 emptyTicket,
1307 },
1308 ticketsSent: true,
1309 },
1310 {
1311 desc: "CHACHA20-POLY1305-SHA256 new session ticket followed by application data",
1312 ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256,
1313 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
1314 completedRecords: [][]byte{
1315 testutil.Dehex("1703030016fc75cc914510008c6B45bb46b1f030921006c3556882"),
1316 testutil.Dehex("170303001a0cedeb922170c110c172262542c67916b78fa0d1c1261709cd00"),
1317 },
1318 outPlaintexts: [][]byte{
1319 []byte(""),
1320 []byte("789123456"),
1321 },
1322 finalTicketState: notReceivingTickets,
1323 outSessionTickets: [][]byte{
1324 emptyTicket,
1325 },
1326 ticketsSent: true,
1327 },
1328 {
1329 desc: "AES-128-GCM-SHA256 ticket, application data, then another ticket",
1330 ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256,
1331 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
1332 completedRecords: [][]byte{
1333 testutil.Dehex("1703030016c7d6d72499478b3d80281cae5b7c1a3e5cd553aae716"),
1334 testutil.Dehex("170303001ad7853afd6d7ceaabab950a0b6707905d2b908894871c7c62021f"),
1335 testutil.Dehex("17030300169c4fb23ec187cec7a8443ae3cd6f45e9dca53023e952"),
1336 },
1337 outPlaintexts: [][]byte{
1338 []byte(""),
1339 []byte("789123456"),
1340 []byte(""),
1341 },
1342 finalTicketState: notReceivingTickets,
1343 outSessionTickets: [][]byte{
1344 emptyTicket,
1345 },
1346 ticketsSent: true,
1347 },
1348 {
1349 desc: "AES-256-GCM-SHA384 ticket, application data, then another ticket",
1350 ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384,
1351 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
1352 completedRecords: [][]byte{
1353 testutil.Dehex("170303001611dddd6fc4869be0e1c12a5a29db1aa2e5814e5894e5"),
1354 testutil.Dehex("170303001a832a5fd271b6442e74bc02111a8e8b52a74b14dd3eca8598b293"),
1355 testutil.Dehex("1703030016a5f3bdfc4ab1cb73dca49bc86a7fde6396e83d9eb6ac"),
1356 },
1357 outPlaintexts: [][]byte{
1358 []byte(""),
1359 []byte("789123456"),
1360 []byte(""),
1361 },
1362 finalTicketState: notReceivingTickets,
1363 outSessionTickets: [][]byte{
1364 emptyTicket,
1365 },
1366 ticketsSent: true,
1367 },
1368 {
1369 desc: "CHACHA20-POLY1305-SHA256 ticket, application data, then another ticket",
1370 ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256,
1371 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
1372 completedRecords: [][]byte{
1373 testutil.Dehex("1703030016fc75cc914510008c6B45bb46b1f030921006c3556882"),
1374 testutil.Dehex("170303001a0cedeb922170c110c172262542c67916b78fa0d1c1261709cd00"),
1375 testutil.Dehex("1703030016a1726a73d83b83e97018b7d4b9d33ec9528d7f10e8f2"),
1376 },
1377 outPlaintexts: [][]byte{
1378 []byte(""),
1379 []byte("789123456"),
1380 []byte(""),
1381 },
1382 finalTicketState: notReceivingTickets,
1383 outSessionTickets: [][]byte{
1384 emptyTicket,
1385 },
1386 ticketsSent: true,
1387 },
1388 } {
1389 t.Run(tc.desc, func(t *testing.T) {
1390 c, err := NewConn(&ConnParameters{
1391 NetConn: &fakeConn{buf: tc.completedRecords},
1392 Ciphersuite: tc.ciphersuite,
1393 TLSVersion: commonpb.TLSVersion_TLS1_3,
1394 InTrafficSecret: tc.trafficSecret,
1395 OutTrafficSecret: tc.trafficSecret,
1396 })
1397 if err != nil {
1398 t.Fatalf("NewConn() failed: %v", err)
1399 }
1400 newConn := c.(*conn)
1401
1402 fakeTicketSender := &fakeTicketSender{}
1403 newConn.ticketSender = fakeTicketSender
1404 for _, outPlaintext := range tc.outPlaintexts {
1405 plaintext := make([]byte, tlsRecordMaxPlaintextSize)
1406 n, err := c.Read(plaintext)
1407 if err != nil {
1408 t.Fatalf("c.Read(plaintext) failed: %v", err)
1409 }
1410 plaintext = plaintext[:n]
1411 if got, want := plaintext, outPlaintext; !bytes.Equal(got, want) {
1412 t.Errorf("c.Read(plaintext) = %v, want %v", got, want)
1413 }
1414 if got, want := len(c.(*conn).pendingApplicationData), 0; got != want {
1415 t.Errorf("len(c.(*conn).pendingApplicationData) = %v, want %v", got, want)
1416 }
1417 }
1418 newConn.Close()
1419 if got, want := newConn.ticketState, tc.finalTicketState; got != want {
1420 t.Errorf("newConn.ticketState = %v, want %v", got, want)
1421 }
1422 if got, want := newConn.handshakeBuf, make([]byte, 0); !bytes.Equal(got, want) {
1423 t.Errorf("newConn.handshakeBuf = %v, want %v", got, want)
1424 }
1425 if got, want := newConn.sessionTickets, tc.outSessionTickets; !cmp.Equal(got, want) {
1426 t.Errorf("newConn.sessionTickets = %v, want %v", got, want)
1427 }
1428 if tc.ticketsSent {
1429 if got, want := fakeTicketSender.sessionTickets, tc.outSessionTickets; !cmp.Equal(got, want) {
1430 t.Errorf("fakeTicketSender.sessionTickets = %v, want %v", got, want)
1431 }
1432 }
1433 })
1434 }
1435 }
1436
1437 type handshakeMsg struct {
1438 msg []byte
1439 isKeyUpdate bool
1440 }
1441
1442 func TestConnHandshakeWithHandshakeBuilder(t *testing.T) {
1443 dummyTicket := buildSessionTicket([]byte("abc"))
1444 dummyTicketFragment1 := buildSessionTicket(make([]byte, tlsRecordMaxPlaintextSize/2))
1445 dummyTicketFragment2 := buildSessionTicket(make([]byte, tlsRecordMaxPlaintextSize))
1446 dummyLargeTicket := buildSessionTicket(make([]byte, tlsRecordMaxPlaintextSize*2))
1447 dummyTicketSplitHeader1 := buildSessionTicket([]byte("abc"))[:2]
1448 dummyTicketSplitHeader2 := buildSessionTicket([]byte("abc"))[2:]
1449
1450 for _, tc := range []struct {
1451 desc string
1452 ciphersuite commonpb.Ciphersuite
1453 trafficSecret []byte
1454 handshakeMsgs []handshakeMsg
1455 finalTicketState sessionTicketState
1456 outSessionTickets [][]byte
1457 ticketsSent bool
1458 outErr bool
1459 }{
1460 {
1461 desc: "AES-128-GCM-SHA256 consecutive tickets",
1462 ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256,
1463 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
1464 handshakeMsgs: []handshakeMsg{
1465 {
1466 msg: dummyTicket,
1467 },
1468 {
1469 msg: dummyTicket,
1470 },
1471 },
1472 finalTicketState: receivingTickets,
1473 outSessionTickets: [][]byte{
1474 dummyTicket,
1475 dummyTicket,
1476 },
1477 },
1478 {
1479 desc: "AES-256-GCM-SHA384 consecutive tickets",
1480 ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384,
1481 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
1482 handshakeMsgs: []handshakeMsg{
1483 {
1484 msg: dummyTicket,
1485 },
1486 {
1487 msg: dummyTicket,
1488 },
1489 },
1490 finalTicketState: receivingTickets,
1491 outSessionTickets: [][]byte{
1492 dummyTicket,
1493 dummyTicket,
1494 },
1495 },
1496 {
1497 desc: "CHACHA20-POLY1305-SHA256 consecutive tickets",
1498 ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256,
1499 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
1500 handshakeMsgs: []handshakeMsg{
1501 {
1502 msg: dummyTicket,
1503 },
1504 {
1505 msg: dummyTicket,
1506 },
1507 },
1508 finalTicketState: receivingTickets,
1509 outSessionTickets: [][]byte{
1510 dummyTicket,
1511 dummyTicket,
1512 },
1513 },
1514 {
1515 desc: "AES-128-GCM-SHA256 multiple tickets in one record",
1516 ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256,
1517 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
1518 handshakeMsgs: []handshakeMsg{
1519 {
1520 msg: append(dummyTicket, dummyTicket...),
1521 },
1522 },
1523 finalTicketState: receivingTickets,
1524 outSessionTickets: [][]byte{
1525 dummyTicket,
1526 dummyTicket,
1527 },
1528 },
1529 {
1530 desc: "AES-256-GCM-SHA384 multiple tickets in one record",
1531 ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384,
1532 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
1533 handshakeMsgs: []handshakeMsg{
1534 {
1535 msg: append(dummyTicket, dummyTicket...),
1536 },
1537 },
1538 finalTicketState: receivingTickets,
1539 outSessionTickets: [][]byte{
1540 dummyTicket,
1541 dummyTicket,
1542 },
1543 },
1544 {
1545 desc: "CHACHA20-POLY1305-SHA256 multiple tickets in one record",
1546 ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256,
1547 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
1548 handshakeMsgs: []handshakeMsg{
1549 {
1550 msg: append(dummyTicket, dummyTicket...),
1551 },
1552 },
1553 finalTicketState: receivingTickets,
1554 outSessionTickets: [][]byte{
1555 dummyTicket,
1556 dummyTicket,
1557 },
1558 },
1559 {
1560 desc: "AES-128-GCM-SHA256 fragmented tickets",
1561 ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256,
1562 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
1563 handshakeMsgs: []handshakeMsg{
1564 {
1565 msg: append(dummyTicketFragment1, dummyTicketFragment2...),
1566 },
1567 },
1568 finalTicketState: receivingTickets,
1569 outSessionTickets: [][]byte{
1570 dummyTicketFragment1,
1571 dummyTicketFragment2,
1572 },
1573 },
1574 {
1575 desc: "AES-256-GCM-SHA384 fragmented tickets",
1576 ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384,
1577 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
1578 handshakeMsgs: []handshakeMsg{
1579 {
1580 msg: append(dummyTicketFragment1, dummyTicketFragment2...),
1581 },
1582 },
1583 finalTicketState: receivingTickets,
1584 outSessionTickets: [][]byte{
1585 dummyTicketFragment1,
1586 dummyTicketFragment2,
1587 },
1588 },
1589 {
1590 desc: "CHACHA20-POLY1305-SHA256 fragmented tickets",
1591 ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256,
1592 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
1593 handshakeMsgs: []handshakeMsg{
1594 {
1595 msg: append(dummyTicketFragment1, dummyTicketFragment2...),
1596 },
1597 },
1598 finalTicketState: receivingTickets,
1599 outSessionTickets: [][]byte{
1600 dummyTicketFragment1,
1601 dummyTicketFragment2,
1602 },
1603 },
1604 {
1605 desc: "AES-128-GCM-SHA256 large ticket",
1606 ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256,
1607 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
1608 handshakeMsgs: []handshakeMsg{
1609 {
1610 msg: dummyLargeTicket,
1611 },
1612 },
1613 finalTicketState: receivingTickets,
1614 outSessionTickets: [][]byte{
1615 dummyLargeTicket,
1616 },
1617 },
1618 {
1619 desc: "AES-256-GCM-SHA384 large ticket",
1620 ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384,
1621 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
1622 handshakeMsgs: []handshakeMsg{
1623 {
1624 msg: dummyLargeTicket,
1625 },
1626 },
1627 finalTicketState: receivingTickets,
1628 outSessionTickets: [][]byte{
1629 dummyLargeTicket,
1630 },
1631 },
1632 {
1633 desc: "CHACHA20-POLY1305-SHA256 large ticket",
1634 ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256,
1635 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
1636 handshakeMsgs: []handshakeMsg{
1637 {
1638 msg: dummyLargeTicket,
1639 },
1640 },
1641 finalTicketState: receivingTickets,
1642 outSessionTickets: [][]byte{
1643 dummyLargeTicket,
1644 },
1645 },
1646 {
1647 desc: "AES-128-GCM-SHA256 split in header",
1648 ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256,
1649 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
1650 handshakeMsgs: []handshakeMsg{
1651 {
1652 msg: dummyTicketSplitHeader1,
1653 },
1654 {
1655 msg: dummyTicketSplitHeader2,
1656 },
1657 },
1658 finalTicketState: receivingTickets,
1659 outSessionTickets: [][]byte{
1660 dummyTicket,
1661 },
1662 },
1663 {
1664 desc: "AES-256-GCM-SHA384 split in header",
1665 ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384,
1666 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
1667 handshakeMsgs: []handshakeMsg{
1668 {
1669 msg: dummyTicketSplitHeader1,
1670 },
1671 {
1672 msg: dummyTicketSplitHeader2,
1673 },
1674 },
1675 finalTicketState: receivingTickets,
1676 outSessionTickets: [][]byte{
1677 dummyTicket,
1678 },
1679 },
1680 {
1681 desc: "CHACHA20-POLY1305-SHA256 split in header",
1682 ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256,
1683 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
1684 handshakeMsgs: []handshakeMsg{
1685 {
1686 msg: dummyTicketSplitHeader1,
1687 },
1688 {
1689 msg: dummyTicketSplitHeader2,
1690 },
1691 },
1692 finalTicketState: receivingTickets,
1693 outSessionTickets: [][]byte{
1694 dummyTicket,
1695 },
1696 },
1697 {
1698 desc: "AES-128-GCM-SHA256 past max limit",
1699 ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256,
1700 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
1701 handshakeMsgs: []handshakeMsg{
1702 {
1703 msg: dummyTicket,
1704 },
1705 {
1706 msg: dummyTicket,
1707 },
1708 {
1709 msg: dummyTicket,
1710 },
1711 {
1712 msg: dummyTicket,
1713 },
1714 {
1715 msg: dummyTicket,
1716 },
1717 {
1718 msg: dummyTicket,
1719 },
1720 },
1721 finalTicketState: notReceivingTickets,
1722 outSessionTickets: [][]byte{
1723 dummyTicket,
1724 dummyTicket,
1725 dummyTicket,
1726 dummyTicket,
1727 dummyTicket,
1728 },
1729 ticketsSent: true,
1730 },
1731 {
1732 desc: "AES-256-GCM-SHA384 past max limit",
1733 ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384,
1734 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
1735 handshakeMsgs: []handshakeMsg{
1736 {
1737 msg: dummyTicket,
1738 },
1739 {
1740 msg: dummyTicket,
1741 },
1742 {
1743 msg: dummyTicket,
1744 },
1745 {
1746 msg: dummyTicket,
1747 },
1748 {
1749 msg: dummyTicket,
1750 },
1751 {
1752 msg: dummyTicket,
1753 },
1754 },
1755 finalTicketState: notReceivingTickets,
1756 outSessionTickets: [][]byte{
1757 dummyTicket,
1758 dummyTicket,
1759 dummyTicket,
1760 dummyTicket,
1761 dummyTicket,
1762 },
1763 ticketsSent: true,
1764 },
1765 {
1766 desc: "CHACHA20-POLY1305-SHA256 past max limit",
1767 ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256,
1768 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
1769 handshakeMsgs: []handshakeMsg{
1770 {
1771 msg: dummyTicket,
1772 },
1773 {
1774 msg: dummyTicket,
1775 },
1776 {
1777 msg: dummyTicket,
1778 },
1779 {
1780 msg: dummyTicket,
1781 },
1782 {
1783 msg: dummyTicket,
1784 },
1785 {
1786 msg: dummyTicket,
1787 },
1788 },
1789 finalTicketState: notReceivingTickets,
1790 outSessionTickets: [][]byte{
1791 dummyTicket,
1792 dummyTicket,
1793 dummyTicket,
1794 dummyTicket,
1795 dummyTicket,
1796 },
1797 ticketsSent: true,
1798 },
1799 {
1800 desc: "AES-128-GCM-SHA256 consecutive key updates",
1801 ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256,
1802 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
1803 handshakeMsgs: []handshakeMsg{
1804 {
1805 msg: buildKeyUpdateRequest(),
1806 isKeyUpdate: true,
1807 },
1808 {
1809 msg: buildKeyUpdateRequest(),
1810 isKeyUpdate: true,
1811 },
1812 },
1813 },
1814 {
1815 desc: "AES-256-GCM-SHA384 consecutive key updates",
1816 ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384,
1817 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
1818 handshakeMsgs: []handshakeMsg{
1819 {
1820 msg: buildKeyUpdateRequest(),
1821 isKeyUpdate: true,
1822 },
1823 {
1824 msg: buildKeyUpdateRequest(),
1825 isKeyUpdate: true,
1826 },
1827 },
1828 },
1829 {
1830 desc: "CHACHA20-POLY1305-SHA256 consecutive key updates",
1831 ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256,
1832 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
1833 handshakeMsgs: []handshakeMsg{
1834 {
1835 msg: buildKeyUpdateRequest(),
1836 isKeyUpdate: true,
1837 },
1838 {
1839 msg: buildKeyUpdateRequest(),
1840 isKeyUpdate: true,
1841 },
1842 },
1843 },
1844 {
1845 desc: "AES-128-GCM-SHA256 consecutive key updates in single record",
1846 ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256,
1847 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
1848 handshakeMsgs: []handshakeMsg{
1849 {
1850 msg: append(buildKeyUpdateRequest(), buildKeyUpdateRequest()...),
1851 isKeyUpdate: true,
1852 },
1853 },
1854 outErr: true,
1855 },
1856 {
1857 desc: "AES-256-GCM-SHA384 consecutive key updates in single record",
1858 ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384,
1859 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
1860 handshakeMsgs: []handshakeMsg{
1861 {
1862 msg: append(buildKeyUpdateRequest(), buildKeyUpdateRequest()...),
1863 isKeyUpdate: true,
1864 },
1865 },
1866 outErr: true,
1867 },
1868 {
1869 desc: "CHACHA20-POLY1305-SHA256 consecutive key updates in single record",
1870 ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256,
1871 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
1872 handshakeMsgs: []handshakeMsg{
1873 {
1874 msg: append(buildKeyUpdateRequest(), buildKeyUpdateRequest()...),
1875 isKeyUpdate: true,
1876 },
1877 },
1878 outErr: true,
1879 },
1880 {
1881 desc: "AES-128-GCM-SHA256 fragmented key update",
1882 ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256,
1883 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
1884 handshakeMsgs: []handshakeMsg{
1885 {
1886 msg: buildKeyUpdateRequest()[:2],
1887 },
1888 {
1889 msg: buildKeyUpdateRequest()[2:],
1890 isKeyUpdate: true,
1891 },
1892 },
1893 },
1894 {
1895 desc: "AES-256-GCM-SHA384 fragmented key update",
1896 ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384,
1897 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
1898 handshakeMsgs: []handshakeMsg{
1899 {
1900 msg: buildKeyUpdateRequest()[:2],
1901 },
1902 {
1903 msg: buildKeyUpdateRequest()[2:],
1904 isKeyUpdate: true,
1905 },
1906 },
1907 },
1908 {
1909 desc: "CHACHA20-POLY1305-SHA256 fragmented key update",
1910 ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256,
1911 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
1912 handshakeMsgs: []handshakeMsg{
1913 {
1914 msg: buildKeyUpdateRequest()[:2],
1915 },
1916 {
1917 msg: buildKeyUpdateRequest()[2:],
1918 isKeyUpdate: true,
1919 },
1920 },
1921 },
1922 {
1923 desc: "AES-128-GCM-SHA256 key update between session tickets",
1924 ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256,
1925 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
1926 handshakeMsgs: []handshakeMsg{
1927 {
1928 msg: dummyTicket,
1929 },
1930 {
1931 msg: buildKeyUpdateRequest(),
1932 isKeyUpdate: true,
1933 },
1934 {
1935 msg: dummyTicket,
1936 },
1937 },
1938 finalTicketState: receivingTickets,
1939 outSessionTickets: [][]byte{
1940 dummyTicket,
1941 dummyTicket,
1942 },
1943 },
1944 {
1945 desc: "AES-256-GCM-SHA384 key update between session tickets",
1946 ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384,
1947 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
1948 handshakeMsgs: []handshakeMsg{
1949 {
1950 msg: dummyTicket,
1951 },
1952 {
1953 msg: buildKeyUpdateRequest(),
1954 isKeyUpdate: true,
1955 },
1956 {
1957 msg: dummyTicket,
1958 },
1959 },
1960 finalTicketState: receivingTickets,
1961 outSessionTickets: [][]byte{
1962 dummyTicket,
1963 dummyTicket,
1964 },
1965 },
1966 {
1967 desc: "CHACHA20-POLY1305-SHA256 key update between session tickets",
1968 ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256,
1969 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
1970 handshakeMsgs: []handshakeMsg{
1971 {
1972 msg: dummyTicket,
1973 },
1974 {
1975 msg: buildKeyUpdateRequest(),
1976 isKeyUpdate: true,
1977 },
1978 {
1979 msg: dummyTicket,
1980 },
1981 },
1982 finalTicketState: receivingTickets,
1983 outSessionTickets: [][]byte{
1984 dummyTicket,
1985 dummyTicket,
1986 },
1987 },
1988 {
1989 desc: "AES-128-GCM-SHA256 key update between session tickets in a single record",
1990 ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256,
1991 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
1992 handshakeMsgs: []handshakeMsg{
1993 {
1994 msg: append(append(dummyTicket, buildKeyUpdateRequest()...), dummyTicket...),
1995 },
1996 },
1997 outErr: true,
1998 },
1999 {
2000 desc: "AES-256-GCM-SHA384 key update between session tickets in a single record",
2001 ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384,
2002 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
2003 handshakeMsgs: []handshakeMsg{
2004 {
2005 msg: append(append(dummyTicket, buildKeyUpdateRequest()...), dummyTicket...),
2006 },
2007 },
2008 outErr: true,
2009 },
2010 {
2011 desc: "CHACHA20-POLY1305-SHA256 key update between session tickets in a single record",
2012 ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256,
2013 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
2014 handshakeMsgs: []handshakeMsg{
2015 {
2016 msg: append(append(dummyTicket, buildKeyUpdateRequest()...), dummyTicket...),
2017 },
2018 },
2019 outErr: true,
2020 },
2021 } {
2022 t.Run(tc.desc, func(t *testing.T) {
2023 fc := &fakeConn{}
2024 netConn, err := NewConn(&ConnParameters{
2025 NetConn: fc,
2026 Ciphersuite: tc.ciphersuite,
2027 TLSVersion: commonpb.TLSVersion_TLS1_3,
2028 InTrafficSecret: tc.trafficSecret,
2029 OutTrafficSecret: tc.trafficSecret,
2030 })
2031 if err != nil {
2032 t.Fatalf("NewConn() failed: %v", err)
2033 }
2034 c := netConn.(*conn)
2035
2036 fakeTicketSender := &fakeTicketSender{}
2037 c.ticketSender = fakeTicketSender
2038 for _, handshakeMsg := range tc.handshakeMsgs {
2039 _, err = c.writeTLSRecord(handshakeMsg.msg, byte(handshake))
2040 if err != nil {
2041 t.Fatalf("c.writeTLSRecord(hanshakeMsg, byte(handshake)) failed: %v", err)
2042 }
2043 if handshakeMsg.isKeyUpdate {
2044 if err := c.outConn.UpdateKey(); err != nil {
2045 t.Fatalf("c.outConn.UpdateKey() failed: %v", err)
2046 }
2047 }
2048 }
2049 fc.buf = fc.additionalBuf
2050
2051 for {
2052 plaintext := make([]byte, tlsRecordMaxPlaintextSize)
2053 n, err := c.Read(plaintext)
2054 if err != nil {
2055 if err == errFakeConnEOF {
2056 break
2057 }
2058 if !tc.outErr {
2059 t.Fatalf("c.Read(plaintext) failed: %v", err)
2060 }
2061 return
2062 }
2063 if got, want := n, 0; got != want {
2064 t.Errorf("c.Read(plaintext) = %v, want %v,", got, want)
2065 }
2066 if got, want := len(c.pendingApplicationData), 0; got != want {
2067 t.Errorf("len(c.(*conn).pendingApplicationData) = %v, want %v", got, want)
2068 }
2069 }
2070 netConn.Close()
2071 if got, want := c.ticketState, tc.finalTicketState; got != want {
2072 t.Errorf("newConn.ticketState = %v, want %v", got, want)
2073 }
2074 if got, want := c.handshakeBuf, make([]byte, 0); !bytes.Equal(got, want) {
2075 t.Errorf("newConn.handshakeBuf = %v, want %v", got, want)
2076 }
2077 if got, want := c.sessionTickets, tc.outSessionTickets; !cmp.Equal(got, want) {
2078 t.Errorf("newConn.sessionTickets = %v, want %v", got, want)
2079 }
2080 if tc.ticketsSent {
2081 if got, want := fakeTicketSender.sessionTickets, tc.outSessionTickets; !cmp.Equal(got, want) {
2082 t.Errorf("fakeTicketSender.sessionTickets = %v, want %v", got, want)
2083 }
2084 }
2085 })
2086 }
2087 }
2088
2089 func TestWrite(t *testing.T) {
2090 for _, tc := range []struct {
2091 desc string
2092 ciphersuite commonpb.Ciphersuite
2093 trafficSecret []byte
2094 plaintexts [][]byte
2095 outRecords [][]byte
2096 outBytesWritten []int
2097 outErr bool
2098 }{
2099
2100
2101
2102
2103 {
2104 desc: "AES-128-GCM-SHA256",
2105 ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256,
2106 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
2107 plaintexts: [][]byte{
2108 []byte("123456"),
2109 []byte("789123456"),
2110 },
2111 outRecords: [][]byte{
2112 testutil.Dehex("1703030017f2e4e411ac6760e4e3f074a36574c45ee4c1906103db0d"),
2113 testutil.Dehex("170303001ad7853afd6d7ceaabab950a0b6707905d2b908894871c7c62021f"),
2114 },
2115 outBytesWritten: []int{6, 9},
2116 },
2117 {
2118 desc: "AES-128-GCM-SHA256 empty",
2119 ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256,
2120 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
2121 plaintexts: [][]byte{
2122 []byte(""),
2123 },
2124 outRecords: [][]byte{
2125 testutil.Dehex("1703030011d47cb2ec040f26cc8989330339c669dd4e"),
2126 },
2127 outBytesWritten: []int{0},
2128 },
2129 {
2130 desc: "AES-256-GCM-SHA384",
2131 ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384,
2132 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
2133 plaintexts: [][]byte{
2134 []byte("123456"),
2135 []byte("789123456"),
2136 },
2137 outRecords: [][]byte{
2138 testutil.Dehex("170303001724efee5af1a62170ad5a95f899d038b965386a1a7daed9"),
2139 testutil.Dehex("170303001a832a5fd271b6442e74bc02111a8e8b52a74b14dd3eca8598b293"),
2140 },
2141 outBytesWritten: []int{6, 9},
2142 },
2143 {
2144 desc: "AES-256-GCM-SHA384 empty",
2145 ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384,
2146 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
2147 plaintexts: [][]byte{
2148 []byte(""),
2149 },
2150 outRecords: [][]byte{
2151 testutil.Dehex("170303001102a04134d38c1118f36b01d177c5d2dcf7"),
2152 },
2153 outBytesWritten: []int{0},
2154 },
2155 {
2156 desc: "CHACHA20-POLY1305-SHA256",
2157 ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256,
2158 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
2159 plaintexts: [][]byte{
2160 []byte("123456"),
2161 []byte("789123456"),
2162 },
2163 outRecords: [][]byte{
2164 testutil.Dehex("1703030017c947ffa470304370338bb07ce468e6b8a0944a338ba402"),
2165 testutil.Dehex("170303001a0cedeb922170c110c172262542c67916b78fa0d1c1261709cd00"),
2166 },
2167 outBytesWritten: []int{6, 9},
2168 },
2169 {
2170 desc: "CHACHA20-POLY1305-SHA256 empty",
2171 ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256,
2172 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
2173 plaintexts: [][]byte{
2174 []byte(""),
2175 },
2176 outRecords: [][]byte{
2177 testutil.Dehex("1703030011ef8f7a428ddc84ee5968cd6306bf1d2d1b"),
2178 },
2179 outBytesWritten: []int{0},
2180 },
2181 } {
2182 t.Run(tc.desc, func(t *testing.T) {
2183 fConn := &fakeConn{}
2184 newConn, err := NewConn(&ConnParameters{
2185 NetConn: fConn,
2186 Ciphersuite: tc.ciphersuite,
2187 TLSVersion: commonpb.TLSVersion_TLS1_3,
2188 InTrafficSecret: tc.trafficSecret,
2189 OutTrafficSecret: tc.trafficSecret,
2190 })
2191 c := newConn.(*conn)
2192 if err != nil {
2193 t.Fatalf("NewConn() failed: %v", err)
2194 }
2195 for i, plaintext := range tc.plaintexts {
2196 bytesWritten, err := c.writeTLSRecord(plaintext, tlsApplicationData)
2197 if got, want := err == nil, !tc.outErr; got != want {
2198 t.Errorf("c.Write(plaintext) = (err=nil) = %v, want %v", got, want)
2199 }
2200 if bytesWritten != tc.outBytesWritten[i] {
2201 t.Errorf("Incorrect number of bytes written: got: %v, want: %v", bytesWritten, tc.outBytesWritten[i])
2202 }
2203 }
2204 if !reflect.DeepEqual(fConn.additionalBuf, tc.outRecords) {
2205 t.Errorf("Incorrect Record: got: %v, want: %v", fConn.additionalBuf, tc.outRecords)
2206 }
2207 })
2208 }
2209 }
2210
2211 func TestWriteTwoRecords(t *testing.T) {
2212 for _, tc := range []struct {
2213 desc string
2214 ciphersuite commonpb.Ciphersuite
2215 trafficSecret []byte
2216 plaintext []byte
2217 numRecordBytes int
2218 outBytesWritten int
2219 outErr bool
2220 }{
2221
2222
2223
2224
2225
2226 {
2227 desc: "AES-128-GCM-SHA256",
2228 ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256,
2229 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
2230 plaintext: make([]byte, 1+tlsRecordMaxPlaintextSize),
2231 numRecordBytes: 23 + tlsRecordMaxSize,
2232 outBytesWritten: 1 + tlsRecordMaxPlaintextSize,
2233 },
2234 {
2235 desc: "AES-256-GCM-SHA384",
2236 ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384,
2237 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
2238 plaintext: make([]byte, 1+tlsRecordMaxPlaintextSize),
2239 numRecordBytes: 23 + tlsRecordMaxSize,
2240 outBytesWritten: 1 + tlsRecordMaxPlaintextSize,
2241 },
2242 {
2243 desc: "CHACHA20-POLY1305-SHA256",
2244 ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256,
2245 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
2246 plaintext: make([]byte, 1+tlsRecordMaxPlaintextSize),
2247 numRecordBytes: 23 + tlsRecordMaxSize,
2248 outBytesWritten: 1 + tlsRecordMaxPlaintextSize,
2249 },
2250 } {
2251 t.Run(tc.desc, func(t *testing.T) {
2252 fConn := &fakeConn{}
2253 newConn, err := NewConn(&ConnParameters{
2254 NetConn: fConn,
2255 Ciphersuite: tc.ciphersuite,
2256 TLSVersion: commonpb.TLSVersion_TLS1_3,
2257 InTrafficSecret: tc.trafficSecret,
2258 OutTrafficSecret: tc.trafficSecret,
2259 })
2260 c := newConn.(*conn)
2261 if err != nil {
2262 t.Fatalf("NewConn() failed: %v", err)
2263 }
2264 bytesWritten, err := c.writeTLSRecord(tc.plaintext, tlsApplicationData)
2265 if got, want := err == nil, !tc.outErr; got != want {
2266 t.Errorf("c.Write(plaintext) = (err=nil) = %v, want %v", got, want)
2267 }
2268 if bytesWritten != tc.outBytesWritten {
2269 t.Errorf("Incorrect number of bytes written: got: %v, want: %v", bytesWritten, tc.outBytesWritten)
2270 }
2271 if len(fConn.additionalBuf[0]) != tc.numRecordBytes {
2272 t.Errorf("Incorrect number of bytes prepared: got: %v, want: %v", len(fConn.additionalBuf[0]), tc.numRecordBytes)
2273 }
2274 })
2275 }
2276 }
2277
2278 func TestExceedBufferSize(t *testing.T) {
2279 for _, tc := range []struct {
2280 desc string
2281 ciphersuite commonpb.Ciphersuite
2282 trafficSecret []byte
2283 plaintext []byte
2284 expectedOutRecordBufSize int
2285 expectedNumWrites int
2286 outErr bool
2287 }{
2288
2289
2290
2291
2292 {
2293 desc: "AES-128-GCM-SHA256",
2294 ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256,
2295 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
2296 plaintext: make([]byte, 1+tlsRecordMaxPlaintextSize*outBufMaxRecords),
2297 expectedOutRecordBufSize: outBufMaxSize,
2298 expectedNumWrites: 2,
2299 },
2300 {
2301 desc: "AES-256-GCM-SHA384",
2302 ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384,
2303 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
2304 plaintext: make([]byte, 1+tlsRecordMaxPlaintextSize*outBufMaxRecords),
2305 expectedOutRecordBufSize: outBufMaxSize,
2306 expectedNumWrites: 2,
2307 },
2308 {
2309 desc: "CHACHA20-POLY1305-SHA256",
2310 ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256,
2311 trafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
2312 plaintext: make([]byte, 1+tlsRecordMaxPlaintextSize*outBufMaxRecords),
2313 expectedOutRecordBufSize: outBufMaxSize,
2314 expectedNumWrites: 2,
2315 },
2316 } {
2317 t.Run(tc.desc, func(t *testing.T) {
2318 fConn := &fakeConn{}
2319 newConn, err := NewConn(&ConnParameters{
2320 NetConn: fConn,
2321 Ciphersuite: tc.ciphersuite,
2322 TLSVersion: commonpb.TLSVersion_TLS1_3,
2323 InTrafficSecret: tc.trafficSecret,
2324 OutTrafficSecret: tc.trafficSecret,
2325 })
2326 c := newConn.(*conn)
2327 if err != nil {
2328 t.Fatalf("NewConn() failed: %v", err)
2329 }
2330 bytesWritten, err := c.writeTLSRecord(tc.plaintext, tlsApplicationData)
2331 if got, want := err == nil, !tc.outErr; got != want {
2332 t.Errorf("c.Write(plaintext) = (err=nil) = %v, want %v", err, want)
2333 }
2334 if bytesWritten != len(tc.plaintext) {
2335 t.Errorf("Incorrect number of bytes written: got: %v, want: %v", bytesWritten, len(tc.plaintext))
2336 }
2337 if len(c.outRecordsBuf) != tc.expectedOutRecordBufSize {
2338 t.Errorf("Incorrect buf size: got: %v, want: %v", len(c.outRecordsBuf), tc.expectedOutRecordBufSize)
2339 }
2340 if len(fConn.additionalBuf) != tc.expectedNumWrites {
2341 t.Errorf("Inforrect number of records: got: %v, want: %v,", len(fConn.additionalBuf), tc.expectedNumWrites)
2342 }
2343 })
2344 }
2345 }
2346
2347 func TestRoundtrip(t *testing.T) {
2348 for _, tc := range []struct {
2349 desc string
2350 ciphersuite commonpb.Ciphersuite
2351 inTrafficSecret []byte
2352 outTrafficSecret []byte
2353 plaintexts [][]byte
2354 plaintextBytesWritten []int
2355 numRecordBytes []int
2356 }{
2357
2358
2359 {
2360 desc: "AES-128-GCM-SHA256",
2361 ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256,
2362 inTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
2363 outTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
2364 plaintexts: [][]byte{
2365 []byte("123456"),
2366 []byte("789123456"),
2367 },
2368 plaintextBytesWritten: []int{6, 9},
2369 numRecordBytes: []int{28, 31},
2370 },
2371 {
2372 desc: "AES-128-GCM-SHA256 different traffic secrets",
2373 ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256,
2374 inTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
2375 outTrafficSecret: testutil.Dehex("1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b"),
2376 plaintexts: [][]byte{
2377 []byte("123456"),
2378 []byte("789123456"),
2379 },
2380 plaintextBytesWritten: []int{6, 9},
2381 numRecordBytes: []int{28, 31},
2382 },
2383 {
2384 desc: "AES-128-GCM-SHA256 empty",
2385 ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256,
2386 inTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
2387 outTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
2388 plaintexts: [][]byte{
2389 []byte(""),
2390 },
2391 plaintextBytesWritten: []int{0},
2392 numRecordBytes: []int{22},
2393 },
2394 {
2395 desc: "AES-128-GCM-SHA256 max buffer size",
2396 ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256,
2397 inTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
2398 outTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
2399 plaintexts: [][]byte{
2400 make([]byte, tlsRecordMaxPlaintextSize*outBufMaxRecords),
2401 },
2402 plaintextBytesWritten: []int{tlsRecordMaxPlaintextSize * outBufMaxRecords},
2403 numRecordBytes: []int{outBufMaxSize},
2404 },
2405 {
2406 desc: "AES-128-GCM-SHA256 exceed buffer size",
2407 ciphersuite: commonpb.Ciphersuite_AES_128_GCM_SHA256,
2408 inTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
2409 outTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
2410 plaintexts: [][]byte{
2411 make([]byte, 1+tlsRecordMaxPlaintextSize*outBufMaxRecords),
2412 },
2413 plaintextBytesWritten: []int{1 + tlsRecordMaxPlaintextSize*outBufMaxRecords},
2414 numRecordBytes: []int{outBufMaxSize, 23},
2415 },
2416 {
2417 desc: "AES-256-GCM-SHA384",
2418 ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384,
2419 inTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
2420 outTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
2421 plaintexts: [][]byte{
2422 []byte("123456"),
2423 []byte("789123456"),
2424 },
2425 plaintextBytesWritten: []int{6, 9},
2426 numRecordBytes: []int{28, 31},
2427 },
2428 {
2429 desc: "AES-256-GCM-SHA384 different traffic secrets",
2430 ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384,
2431 inTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
2432 outTrafficSecret: testutil.Dehex("1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b"),
2433 plaintexts: [][]byte{
2434 []byte("123456"),
2435 []byte("789123456"),
2436 },
2437 plaintextBytesWritten: []int{6, 9},
2438 numRecordBytes: []int{28, 31},
2439 },
2440 {
2441 desc: "AES-256-GCM-SHA384 empty",
2442 ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384,
2443 inTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
2444 outTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
2445 plaintexts: [][]byte{
2446 []byte(""),
2447 },
2448 plaintextBytesWritten: []int{0},
2449 numRecordBytes: []int{22},
2450 },
2451 {
2452 desc: "AES-256-GCM-SHA384 max buffer size",
2453 ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384,
2454 inTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
2455 outTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
2456 plaintexts: [][]byte{
2457 make([]byte, tlsRecordMaxPlaintextSize*outBufMaxRecords),
2458 },
2459 plaintextBytesWritten: []int{tlsRecordMaxPlaintextSize * outBufMaxRecords},
2460 numRecordBytes: []int{outBufMaxSize},
2461 },
2462 {
2463 desc: "AES-256-GCM-SHA384 exceed buffer size",
2464 ciphersuite: commonpb.Ciphersuite_AES_256_GCM_SHA384,
2465 inTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
2466 outTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
2467 plaintexts: [][]byte{
2468 make([]byte, 1+tlsRecordMaxPlaintextSize*outBufMaxRecords),
2469 },
2470 plaintextBytesWritten: []int{1 + tlsRecordMaxPlaintextSize*outBufMaxRecords},
2471 numRecordBytes: []int{outBufMaxSize, 23},
2472 },
2473 {
2474 desc: "CHACHA20-POLY1305-SHA256",
2475 ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256,
2476 inTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
2477 outTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
2478 plaintexts: [][]byte{
2479 []byte("123456"),
2480 []byte("789123456"),
2481 },
2482 plaintextBytesWritten: []int{6, 9},
2483 numRecordBytes: []int{28, 31},
2484 },
2485 {
2486 desc: "CHACHA20-POLY1305-SHA256 different traffic secrets",
2487 ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256,
2488 inTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
2489 outTrafficSecret: testutil.Dehex("1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b"),
2490 plaintexts: [][]byte{
2491 []byte("123456"),
2492 []byte("789123456"),
2493 },
2494 plaintextBytesWritten: []int{6, 9},
2495 numRecordBytes: []int{28, 31},
2496 },
2497 {
2498 desc: "CHACHA20-POLY1305-SHA256 empty",
2499 ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256,
2500 inTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
2501 outTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
2502 plaintexts: [][]byte{
2503 []byte(""),
2504 },
2505 plaintextBytesWritten: []int{0},
2506 numRecordBytes: []int{22},
2507 },
2508 {
2509 desc: "CHACHA20-POLY1305-SHA256 max buffer size",
2510 ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256,
2511 inTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
2512 outTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
2513 plaintexts: [][]byte{
2514 make([]byte, tlsRecordMaxPlaintextSize*outBufMaxRecords),
2515 },
2516 plaintextBytesWritten: []int{tlsRecordMaxPlaintextSize * outBufMaxRecords},
2517 numRecordBytes: []int{outBufMaxSize},
2518 },
2519 {
2520 desc: "CHACHA20-POLY1305-SHA256 max buffer size",
2521 ciphersuite: commonpb.Ciphersuite_CHACHA20_POLY1305_SHA256,
2522 inTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
2523 outTrafficSecret: testutil.Dehex("6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b"),
2524 plaintexts: [][]byte{
2525 make([]byte, 1+tlsRecordMaxPlaintextSize*outBufMaxRecords),
2526 },
2527 plaintextBytesWritten: []int{1 + tlsRecordMaxPlaintextSize*outBufMaxRecords},
2528 numRecordBytes: []int{outBufMaxSize, 23},
2529 },
2530 } {
2531 t.Run(tc.desc, func(t *testing.T) {
2532 fConnClient := &fakeConn{}
2533 client, err := NewConn(&ConnParameters{
2534 NetConn: fConnClient,
2535 Ciphersuite: tc.ciphersuite,
2536 TLSVersion: commonpb.TLSVersion_TLS1_3,
2537 InTrafficSecret: tc.inTrafficSecret,
2538 OutTrafficSecret: tc.outTrafficSecret,
2539 })
2540 if err != nil {
2541 t.Fatalf("NewConn() failed: %v", err)
2542 }
2543 fConnServer := &fakeConn{}
2544 server, err := NewConn(&ConnParameters{
2545 NetConn: fConnServer,
2546 Ciphersuite: tc.ciphersuite,
2547 TLSVersion: commonpb.TLSVersion_TLS1_3,
2548 InTrafficSecret: tc.outTrafficSecret,
2549 OutTrafficSecret: tc.inTrafficSecret,
2550 })
2551 if err != nil {
2552 t.Fatalf("NewConn() failed: %v", err)
2553 }
2554 err = sendRecordsRoundtrip(t, client, server, fConnClient, fConnServer, tc.plaintexts, tc.plaintextBytesWritten, tc.numRecordBytes)
2555 if err != nil {
2556 return
2557 }
2558 sendRecordsRoundtrip(t, server, client, fConnServer, fConnClient, tc.plaintexts, tc.plaintextBytesWritten, tc.numRecordBytes)
2559
2560 })
2561 }
2562 }
2563
2564 func sendRecordsRoundtrip(t *testing.T, src net.Conn, dst net.Conn, fConnSrc *fakeConn, fConnDst *fakeConn, plaintexts [][]byte, plaintextBytesWritten []int, recordBytes []int) error {
2565 for i, plaintext := range plaintexts {
2566 bytesWritten, err := src.Write(plaintext)
2567 if got, want := err == nil, true; got != want {
2568 t.Errorf("c.Write(plaintext) = (err=nil) = %v, want %v", err, want)
2569 return errors.New("Write returned unexpected output")
2570 }
2571
2572 if bytesWritten != plaintextBytesWritten[i] {
2573 t.Errorf("Incorrect number of bytes written: got: %v, want: %v", bytesWritten, plaintextBytesWritten[i])
2574 return errors.New("Write returned unexpected output")
2575 }
2576
2577 if len(fConnSrc.additionalBuf[i]) != recordBytes[i] {
2578 t.Errorf("Incorrect number of bytes prepared: got: %v, want: %v", len(fConnSrc.additionalBuf[i]), recordBytes[i])
2579 return errors.New("Write returned unexpected output")
2580 }
2581 }
2582 fConnDst.buf = fConnSrc.additionalBuf
2583 for _, outPlaintext := range plaintexts {
2584 n := 0
2585 for n < len(outPlaintext) {
2586 plaintext := make([]byte, tlsRecordMaxPlaintextSize)
2587 dn, err := dst.Read(plaintext)
2588 if got, want := err == nil, true; got != want {
2589 t.Errorf("c.Read(plaintext) = (err=nil) = %v, want %v", err, want)
2590 return errors.New("Read returned unexpected output")
2591 }
2592 if got, want := plaintext[:dn], outPlaintext[n:n+dn]; !bytes.Equal(got, want) {
2593 t.Errorf("c.Read(plaintext) = %v, want %v", len(got), len(want))
2594 return errors.New("Read returned unexpected output")
2595 }
2596 n += dn
2597 }
2598 }
2599 return nil
2600 }
2601
View as plain text