1// Copyright 2017 Google Inc. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package tls
6
7import (
8	"errors"
9	"io"
10)
11
12type TLSExtension interface {
13	writeToUConn(*UConn) error
14
15	Len() int // includes header
16
17	// Read reads up to len(p) bytes into p.
18	// It returns the number of bytes read (0 <= n <= len(p)) and any error encountered.
19	Read(p []byte) (n int, err error) // implements io.Reader
20}
21
22type NPNExtension struct {
23	NextProtos []string
24}
25
26func (e *NPNExtension) writeToUConn(uc *UConn) error {
27	uc.config.NextProtos = e.NextProtos
28	uc.HandshakeState.Hello.NextProtoNeg = true
29	return nil
30}
31
32func (e *NPNExtension) Len() int {
33	return 4
34}
35
36func (e *NPNExtension) Read(b []byte) (int, error) {
37	if len(b) < e.Len() {
38		return 0, io.ErrShortBuffer
39	}
40	b[0] = byte(extensionNextProtoNeg >> 8)
41	b[1] = byte(extensionNextProtoNeg & 0xff)
42	// The length is always 0
43	return e.Len(), io.EOF
44}
45
46type SNIExtension struct {
47	ServerName string // not an array because go crypto/tls doesn't support multiple SNIs
48}
49
50func (e *SNIExtension) writeToUConn(uc *UConn) error {
51	uc.config.ServerName = e.ServerName
52	uc.HandshakeState.Hello.ServerName = e.ServerName
53	return nil
54}
55
56func (e *SNIExtension) Len() int {
57	return 4 + 2 + 1 + 2 + len(e.ServerName)
58}
59
60func (e *SNIExtension) Read(b []byte) (int, error) {
61	if len(b) < e.Len() {
62		return 0, io.ErrShortBuffer
63	}
64	// RFC 3546, section 3.1
65	b[0] = byte(extensionServerName >> 8)
66	b[1] = byte(extensionServerName)
67	b[2] = byte((len(e.ServerName) + 5) >> 8)
68	b[3] = byte((len(e.ServerName) + 5))
69	b[4] = byte((len(e.ServerName) + 3) >> 8)
70	b[5] = byte(len(e.ServerName) + 3)
71	// b[6] Server Name Type: host_name (0)
72	b[7] = byte(len(e.ServerName) >> 8)
73	b[8] = byte(len(e.ServerName))
74	copy(b[9:], []byte(e.ServerName))
75	return e.Len(), io.EOF
76}
77
78type StatusRequestExtension struct {
79}
80
81func (e *StatusRequestExtension) writeToUConn(uc *UConn) error {
82	uc.HandshakeState.Hello.OcspStapling = true
83	return nil
84}
85
86func (e *StatusRequestExtension) Len() int {
87	return 9
88}
89
90func (e *StatusRequestExtension) Read(b []byte) (int, error) {
91	if len(b) < e.Len() {
92		return 0, io.ErrShortBuffer
93	}
94	// RFC 4366, section 3.6
95	b[0] = byte(extensionStatusRequest >> 8)
96	b[1] = byte(extensionStatusRequest)
97	b[2] = 0
98	b[3] = 5
99	b[4] = 1 // OCSP type
100	// Two zero valued uint16s for the two lengths.
101	return e.Len(), io.EOF
102}
103
104type SupportedCurvesExtension struct {
105	Curves []CurveID
106}
107
108func (e *SupportedCurvesExtension) writeToUConn(uc *UConn) error {
109	uc.config.CurvePreferences = e.Curves
110	uc.HandshakeState.Hello.SupportedCurves = e.Curves
111	return nil
112}
113
114func (e *SupportedCurvesExtension) Len() int {
115	return 6 + 2*len(e.Curves)
116}
117
118func (e *SupportedCurvesExtension) Read(b []byte) (int, error) {
119	if len(b) < e.Len() {
120		return 0, io.ErrShortBuffer
121	}
122	// http://tools.ietf.org/html/rfc4492#section-5.5.1
123	b[0] = byte(extensionSupportedCurves >> 8)
124	b[1] = byte(extensionSupportedCurves)
125	b[2] = byte((2 + 2*len(e.Curves)) >> 8)
126	b[3] = byte((2 + 2*len(e.Curves)))
127	b[4] = byte((2 * len(e.Curves)) >> 8)
128	b[5] = byte((2 * len(e.Curves)))
129	for i, curve := range e.Curves {
130		b[6+2*i] = byte(curve >> 8)
131		b[7+2*i] = byte(curve)
132	}
133	return e.Len(), io.EOF
134}
135
136type SupportedPointsExtension struct {
137	SupportedPoints []uint8
138}
139
140func (e *SupportedPointsExtension) writeToUConn(uc *UConn) error {
141	uc.HandshakeState.Hello.SupportedPoints = e.SupportedPoints
142	return nil
143}
144
145func (e *SupportedPointsExtension) Len() int {
146	return 5 + len(e.SupportedPoints)
147}
148
149func (e *SupportedPointsExtension) Read(b []byte) (int, error) {
150	if len(b) < e.Len() {
151		return 0, io.ErrShortBuffer
152	}
153	// http://tools.ietf.org/html/rfc4492#section-5.5.2
154	b[0] = byte(extensionSupportedPoints >> 8)
155	b[1] = byte(extensionSupportedPoints)
156	b[2] = byte((1 + len(e.SupportedPoints)) >> 8)
157	b[3] = byte((1 + len(e.SupportedPoints)))
158	b[4] = byte((len(e.SupportedPoints)))
159	for i, pointFormat := range e.SupportedPoints {
160		b[5+i] = pointFormat
161	}
162	return e.Len(), io.EOF
163}
164
165type SignatureAlgorithmsExtension struct {
166	SupportedSignatureAlgorithms []SignatureScheme
167}
168
169func (e *SignatureAlgorithmsExtension) writeToUConn(uc *UConn) error {
170	uc.HandshakeState.Hello.SupportedSignatureAlgorithms = e.SupportedSignatureAlgorithms
171	return nil
172}
173
174func (e *SignatureAlgorithmsExtension) Len() int {
175	return 6 + 2*len(e.SupportedSignatureAlgorithms)
176}
177
178func (e *SignatureAlgorithmsExtension) Read(b []byte) (int, error) {
179	if len(b) < e.Len() {
180		return 0, io.ErrShortBuffer
181	}
182	// https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
183	b[0] = byte(extensionSignatureAlgorithms >> 8)
184	b[1] = byte(extensionSignatureAlgorithms)
185	b[2] = byte((2 + 2*len(e.SupportedSignatureAlgorithms)) >> 8)
186	b[3] = byte((2 + 2*len(e.SupportedSignatureAlgorithms)))
187	b[4] = byte((2 * len(e.SupportedSignatureAlgorithms)) >> 8)
188	b[5] = byte((2 * len(e.SupportedSignatureAlgorithms)))
189	for i, sigAndHash := range e.SupportedSignatureAlgorithms {
190		b[6+2*i] = byte(sigAndHash >> 8)
191		b[7+2*i] = byte(sigAndHash)
192	}
193	return e.Len(), io.EOF
194}
195
196type RenegotiationInfoExtension struct {
197	renegotiation       RenegotiationSupport
198	SecureRenegotiation []byte // if empty, default []byte{0} is assumed
199}
200
201func (e *RenegotiationInfoExtension) writeToUConn(uc *UConn) error {
202	uc.config.Renegotiation = e.renegotiation
203	switch e.renegotiation {
204	case RenegotiateOnceAsClient:
205		fallthrough
206	case RenegotiateFreelyAsClient:
207		uc.HandshakeState.Hello.SecureRenegotiationSupported = true
208		// Note that if we manage to use this in renegotiation(currently only in initial handshake), we'd have to point
209		// uc.ClientHelloMsg.SecureRenegotiation = chs.C.clientFinished
210		// and probably do something else. It's a mess.
211	case RenegotiateNever:
212	default:
213	}
214	return nil
215}
216
217func (e *RenegotiationInfoExtension) Len() int {
218	switch e.renegotiation {
219	case RenegotiateOnceAsClient:
220		fallthrough
221	case RenegotiateFreelyAsClient:
222		extBodyLen := len(e.SecureRenegotiation)
223		if extBodyLen == 0 {
224			extBodyLen = 1
225		}
226		return 4 + extBodyLen
227	case RenegotiateNever:
228	default:
229	}
230	return 0
231}
232
233func (e *RenegotiationInfoExtension) Read(b []byte) (int, error) {
234	if len(b) < e.Len() {
235		return 0, io.ErrShortBuffer
236	}
237	switch e.renegotiation {
238	case RenegotiateOnceAsClient:
239		fallthrough
240	case RenegotiateFreelyAsClient:
241		secureRenegBody := e.SecureRenegotiation
242		if len(secureRenegBody) == 0 {
243			secureRenegBody = []byte{0}
244		}
245		extBodyLen := len(secureRenegBody)
246
247		b[0] = byte(extensionRenegotiationInfo >> 8)
248		b[1] = byte(extensionRenegotiationInfo & 0xff)
249		b[2] = byte(extBodyLen >> 8)
250		b[3] = byte(extBodyLen)
251		copy(b[4:], secureRenegBody)
252
253		if len(e.SecureRenegotiation) != 0 {
254			copy(b[5:], e.SecureRenegotiation)
255		}
256	case RenegotiateNever:
257	default:
258	}
259	return e.Len(), io.EOF
260}
261
262type ALPNExtension struct {
263	AlpnProtocols []string
264}
265
266func (e *ALPNExtension) writeToUConn(uc *UConn) error {
267	uc.config.NextProtos = e.AlpnProtocols
268	uc.HandshakeState.Hello.AlpnProtocols = e.AlpnProtocols
269	return nil
270}
271
272func (e *ALPNExtension) Len() int {
273	bLen := 2 + 2 + 2
274	for _, s := range e.AlpnProtocols {
275		bLen += 1 + len(s)
276	}
277	return bLen
278}
279
280func (e *ALPNExtension) Read(b []byte) (int, error) {
281	if len(b) < e.Len() {
282		return 0, io.ErrShortBuffer
283	}
284
285	b[0] = byte(extensionALPN >> 8)
286	b[1] = byte(extensionALPN & 0xff)
287	lengths := b[2:]
288	b = b[6:]
289
290	stringsLength := 0
291	for _, s := range e.AlpnProtocols {
292		l := len(s)
293		b[0] = byte(l)
294		copy(b[1:], s)
295		b = b[1+l:]
296		stringsLength += 1 + l
297	}
298
299	lengths[2] = byte(stringsLength >> 8)
300	lengths[3] = byte(stringsLength)
301	stringsLength += 2
302	lengths[0] = byte(stringsLength >> 8)
303	lengths[1] = byte(stringsLength)
304
305	return e.Len(), io.EOF
306}
307
308type SCTExtension struct {
309}
310
311func (e *SCTExtension) writeToUConn(uc *UConn) error {
312	uc.HandshakeState.Hello.Scts = true
313	return nil
314}
315
316func (e *SCTExtension) Len() int {
317	return 4
318}
319
320func (e *SCTExtension) Read(b []byte) (int, error) {
321	if len(b) < e.Len() {
322		return 0, io.ErrShortBuffer
323	}
324	// https://tools.ietf.org/html/rfc6962#section-3.3.1
325	b[0] = byte(extensionSCT >> 8)
326	b[1] = byte(extensionSCT)
327	// zero uint16 for the zero-length extension_data
328	return e.Len(), io.EOF
329}
330
331type SessionTicketExtension struct {
332	Session *ClientSessionState
333}
334
335func (e *SessionTicketExtension) writeToUConn(uc *UConn) error {
336	if e.Session != nil {
337		uc.HandshakeState.Session = e.Session
338		uc.HandshakeState.Hello.SessionTicket = e.Session.sessionTicket
339	}
340	return nil
341}
342
343func (e *SessionTicketExtension) Len() int {
344	if e.Session != nil {
345		return 4 + len(e.Session.sessionTicket)
346	}
347	return 4
348}
349
350func (e *SessionTicketExtension) Read(b []byte) (int, error) {
351	if len(b) < e.Len() {
352		return 0, io.ErrShortBuffer
353	}
354
355	extBodyLen := e.Len() - 4
356
357	b[0] = byte(extensionSessionTicket >> 8)
358	b[1] = byte(extensionSessionTicket)
359	b[2] = byte(extBodyLen >> 8)
360	b[3] = byte(extBodyLen)
361	if extBodyLen > 0 {
362		copy(b[4:], e.Session.sessionTicket)
363	}
364	return e.Len(), io.EOF
365}
366
367type GenericExtension struct {
368	id   uint16
369	data []byte
370}
371
372func (e *GenericExtension) writeToUConn(uc *UConn) error {
373	return nil
374}
375
376func (e *GenericExtension) Len() int {
377	return 4 + len(e.data)
378}
379
380func (e *GenericExtension) Read(b []byte) (int, error) {
381	if len(b) < e.Len() {
382		return 0, io.ErrShortBuffer
383	}
384
385	b[0] = byte(e.id >> 8)
386	b[1] = byte(e.id)
387	b[2] = byte(len(e.data) >> 8)
388	b[3] = byte(len(e.data))
389	if len(e.data) > 0 {
390		copy(b[4:], e.data)
391	}
392	return e.Len(), io.EOF
393}
394
395type UtlsExtendedMasterSecretExtension struct {
396}
397
398// TODO: update when this extension is implemented in crypto/tls
399// but we probably won't have to enable it in Config
400func (e *UtlsExtendedMasterSecretExtension) writeToUConn(uc *UConn) error {
401	uc.HandshakeState.Hello.Ems = true
402	return nil
403}
404
405func (e *UtlsExtendedMasterSecretExtension) Len() int {
406	return 4
407}
408
409func (e *UtlsExtendedMasterSecretExtension) Read(b []byte) (int, error) {
410	if len(b) < e.Len() {
411		return 0, io.ErrShortBuffer
412	}
413	// https://tools.ietf.org/html/rfc7627
414	b[0] = byte(utlsExtensionExtendedMasterSecret >> 8)
415	b[1] = byte(utlsExtensionExtendedMasterSecret)
416	// The length is 0
417	return e.Len(), io.EOF
418}
419
420var extendedMasterSecretLabel = []byte("extended master secret")
421
422// extendedMasterFromPreMasterSecret generates the master secret from the pre-master
423// secret and session hash. See https://tools.ietf.org/html/rfc7627#section-4
424func extendedMasterFromPreMasterSecret(version uint16, suite *cipherSuite, preMasterSecret []byte, fh finishedHash) []byte {
425	sessionHash := fh.Sum()
426	masterSecret := make([]byte, masterSecretLength)
427	prfForVersion(version, suite)(masterSecret, preMasterSecret, extendedMasterSecretLabel, sessionHash)
428	return masterSecret
429}
430
431// GREASE stinks with dead parrots, have to be super careful, and, if possible, not include GREASE
432// https://github.com/google/boringssl/blob/1c68fa2350936ca5897a66b430ebaf333a0e43f5/ssl/internal.h
433const (
434	ssl_grease_cipher = iota
435	ssl_grease_group
436	ssl_grease_extension1
437	ssl_grease_extension2
438	ssl_grease_version
439	ssl_grease_ticket_extension
440	ssl_grease_last_index = ssl_grease_ticket_extension
441)
442
443// it is responsibility of user not to generate multiple grease extensions with same value
444type UtlsGREASEExtension struct {
445	Value uint16
446	Body  []byte // in Chrome first grease has empty body, second grease has a single zero byte
447}
448
449func (e *UtlsGREASEExtension) writeToUConn(uc *UConn) error {
450	return nil
451}
452
453// will panic if ssl_grease_last_index[index] is out of bounds.
454func GetBoringGREASEValue(greaseSeed [ssl_grease_last_index]uint16, index int) uint16 {
455	// GREASE value is back from deterministic to random.
456	// https://github.com/google/boringssl/blob/a365138ac60f38b64bfc608b493e0f879845cb88/ssl/handshake_client.c#L530
457	ret := uint16(greaseSeed[index])
458	/* This generates a random value of the form 0xωaωa, for all 0 ≤ ω < 16. */
459	ret = (ret & 0xf0) | 0x0a
460	ret |= ret << 8
461	return ret
462}
463
464func (e *UtlsGREASEExtension) Len() int {
465	return 4 + len(e.Body)
466}
467
468func (e *UtlsGREASEExtension) Read(b []byte) (int, error) {
469	if len(b) < e.Len() {
470		return 0, io.ErrShortBuffer
471	}
472
473	b[0] = byte(e.Value >> 8)
474	b[1] = byte(e.Value)
475	b[2] = byte(len(e.Body) >> 8)
476	b[3] = byte(len(e.Body))
477	if len(e.Body) > 0 {
478		copy(b[4:], e.Body)
479	}
480	return e.Len(), io.EOF
481}
482
483type UtlsPaddingExtension struct {
484	PaddingLen int
485	WillPad    bool // set to false to disable extension
486
487	// Functor for deciding on padding length based on unpadded ClientHello length.
488	// If willPad is false, then this extension should not be included.
489	GetPaddingLen func(clientHelloUnpaddedLen int) (paddingLen int, willPad bool)
490}
491
492func (e *UtlsPaddingExtension) writeToUConn(uc *UConn) error {
493	return nil
494}
495
496func (e *UtlsPaddingExtension) Len() int {
497	if e.WillPad {
498		return 4 + e.PaddingLen
499	} else {
500		return 0
501	}
502}
503
504func (e *UtlsPaddingExtension) Update(clientHelloUnpaddedLen int) {
505	if e.GetPaddingLen != nil {
506		e.PaddingLen, e.WillPad = e.GetPaddingLen(clientHelloUnpaddedLen)
507	}
508}
509
510func (e *UtlsPaddingExtension) Read(b []byte) (int, error) {
511	if !e.WillPad {
512		return 0, io.EOF
513	}
514	if len(b) < e.Len() {
515		return 0, io.ErrShortBuffer
516	}
517	// https://tools.ietf.org/html/rfc7627
518	b[0] = byte(utlsExtensionPadding >> 8)
519	b[1] = byte(utlsExtensionPadding)
520	b[2] = byte(e.PaddingLen >> 8)
521	b[3] = byte(e.PaddingLen)
522	return e.Len(), io.EOF
523}
524
525// https://github.com/google/boringssl/blob/7d7554b6b3c79e707e25521e61e066ce2b996e4c/ssl/t1_lib.c#L2803
526func BoringPaddingStyle(unpaddedLen int) (int, bool) {
527	if unpaddedLen > 0xff && unpaddedLen < 0x200 {
528		paddingLen := 0x200 - unpaddedLen
529		if paddingLen >= 4+1 {
530			paddingLen -= 4
531		} else {
532			paddingLen = 1
533		}
534		return paddingLen, true
535	}
536	return 0, false
537}
538
539/* TLS 1.3 */
540type KeyShareExtension struct {
541	KeyShares []KeyShare
542}
543
544func (e *KeyShareExtension) Len() int {
545	return 4 + 2 + e.keySharesLen()
546}
547
548func (e *KeyShareExtension) keySharesLen() int {
549	extLen := 0
550	for _, ks := range e.KeyShares {
551		extLen += 4 + len(ks.Data)
552	}
553	return extLen
554}
555
556func (e *KeyShareExtension) Read(b []byte) (int, error) {
557	if len(b) < e.Len() {
558		return 0, io.ErrShortBuffer
559	}
560
561	b[0] = byte(extensionKeyShare >> 8)
562	b[1] = byte(extensionKeyShare)
563	keySharesLen := e.keySharesLen()
564	b[2] = byte((keySharesLen + 2) >> 8)
565	b[3] = byte((keySharesLen + 2))
566	b[4] = byte((keySharesLen) >> 8)
567	b[5] = byte((keySharesLen))
568
569	i := 6
570	for _, ks := range e.KeyShares {
571		b[i] = byte(ks.Group >> 8)
572		b[i+1] = byte(ks.Group)
573		b[i+2] = byte(len(ks.Data) >> 8)
574		b[i+3] = byte(len(ks.Data))
575		copy(b[i+4:], ks.Data)
576		i += 4 + len(ks.Data)
577	}
578
579	return e.Len(), io.EOF
580}
581
582func (e *KeyShareExtension) writeToUConn(uc *UConn) error {
583	uc.HandshakeState.Hello.KeyShares = e.KeyShares
584	return nil
585}
586
587type PSKKeyExchangeModesExtension struct {
588	Modes []uint8
589}
590
591func (e *PSKKeyExchangeModesExtension) Len() int {
592	return 4 + 1 + len(e.Modes)
593}
594
595func (e *PSKKeyExchangeModesExtension) Read(b []byte) (int, error) {
596	if len(b) < e.Len() {
597		return 0, io.ErrShortBuffer
598	}
599
600	if len(e.Modes) > 255 {
601		return 0, errors.New("too many PSK Key Exchange modes")
602	}
603
604	b[0] = byte(extensionPSKModes >> 8)
605	b[1] = byte(extensionPSKModes)
606
607	modesLen := len(e.Modes)
608	b[2] = byte((modesLen + 1) >> 8)
609	b[3] = byte((modesLen + 1))
610	b[4] = byte(modesLen)
611
612	if len(e.Modes) > 0 {
613		copy(b[5:], e.Modes)
614	}
615
616	return e.Len(), io.EOF
617}
618
619func (e *PSKKeyExchangeModesExtension) writeToUConn(uc *UConn) error {
620	uc.HandshakeState.Hello.PskModes = e.Modes
621	return nil
622}
623
624type SupportedVersionsExtension struct {
625	Versions []uint16
626}
627
628func (e *SupportedVersionsExtension) writeToUConn(uc *UConn) error {
629	uc.HandshakeState.Hello.SupportedVersions = e.Versions
630	return nil
631}
632
633func (e *SupportedVersionsExtension) Len() int {
634	return 4 + 1 + (2 * len(e.Versions))
635}
636
637func (e *SupportedVersionsExtension) Read(b []byte) (int, error) {
638	if len(b) < e.Len() {
639		return 0, io.ErrShortBuffer
640	}
641	extLen := 2 * len(e.Versions)
642	if extLen > 255 {
643		return 0, errors.New("too many supported versions")
644	}
645
646	b[0] = byte(extensionSupportedVersions >> 8)
647	b[1] = byte(extensionSupportedVersions)
648	b[2] = byte((extLen + 1) >> 8)
649	b[3] = byte((extLen + 1))
650	b[4] = byte(extLen)
651
652	i := 5
653	for _, sv := range e.Versions {
654		b[i] = byte(sv >> 8)
655		b[i+1] = byte(sv)
656		i += 2
657	}
658	return e.Len(), io.EOF
659}
660
661// MUST NOT be part of initial ClientHello
662type CookieExtension struct {
663	Cookie []byte
664}
665
666func (e *CookieExtension) writeToUConn(uc *UConn) error {
667	return nil
668}
669
670func (e *CookieExtension) Len() int {
671	return 4 + len(e.Cookie)
672}
673
674func (e *CookieExtension) Read(b []byte) (int, error) {
675	if len(b) < e.Len() {
676		return 0, io.ErrShortBuffer
677	}
678
679	b[0] = byte(extensionCookie >> 8)
680	b[1] = byte(extensionCookie)
681	b[2] = byte(len(e.Cookie) >> 8)
682	b[3] = byte(len(e.Cookie))
683	if len(e.Cookie) > 0 {
684		copy(b[4:], e.Cookie)
685	}
686	return e.Len(), io.EOF
687}
688
689/*
690FAKE EXTENSIONS
691*/
692
693type FakeChannelIDExtension struct {
694}
695
696func (e *FakeChannelIDExtension) writeToUConn(uc *UConn) error {
697	return nil
698}
699
700func (e *FakeChannelIDExtension) Len() int {
701	return 4
702}
703
704func (e *FakeChannelIDExtension) Read(b []byte) (int, error) {
705	if len(b) < e.Len() {
706		return 0, io.ErrShortBuffer
707	}
708	// https://tools.ietf.org/html/draft-balfanz-tls-channelid-00
709	b[0] = byte(fakeExtensionChannelID >> 8)
710	b[1] = byte(fakeExtensionChannelID & 0xff)
711	// The length is 0
712	return e.Len(), io.EOF
713}
714
715type FakeRecordSizeLimitExtension struct {
716	Limit uint16
717}
718
719func (e *FakeRecordSizeLimitExtension) writeToUConn(uc *UConn) error {
720	return nil
721}
722
723func (e *FakeRecordSizeLimitExtension) Len() int {
724	return 6
725}
726
727func (e *FakeRecordSizeLimitExtension) Read(b []byte) (int, error) {
728	if len(b) < e.Len() {
729		return 0, io.ErrShortBuffer
730	}
731	// https://tools.ietf.org/html/draft-balfanz-tls-channelid-00
732	b[0] = byte(fakeRecordSizeLimit >> 8)
733	b[1] = byte(fakeRecordSizeLimit & 0xff)
734
735	b[2] = byte(0)
736	b[3] = byte(2)
737
738	b[4] = byte(e.Limit >> 8)
739	b[5] = byte(e.Limit & 0xff)
740	return e.Len(), io.EOF
741}
742