blob: 0df3be323b43739017a182e7124251045e7a32bd [file] [log] [blame]
Adam Langley95c29f32014-06-20 12:00:00 -07001// Copyright 2009 The Go Authors. 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
Adam Langleydc7e9c42015-09-29 15:21:04 -07005package runner
Adam Langley95c29f32014-06-20 12:00:00 -07006
7import "bytes"
8
Nick Harper8dda5cc2016-06-30 18:51:11 -04009func writeLen(buf []byte, v, size int) {
10 for i := 0; i < size; i++ {
11 buf[size-i-1] = byte(v)
12 v >>= 8
13 }
14 if v != 0 {
15 panic("length is too long")
16 }
17}
18
19type byteBuilder struct {
20 buf *[]byte
21 start int
22 prefixLen int
23 child *byteBuilder
24}
25
26func newByteBuilder() *byteBuilder {
27 buf := make([]byte, 0, 32)
28 return &byteBuilder{buf: &buf}
29}
30
31func (bb *byteBuilder) len() int {
32 return len(*bb.buf) - bb.start - bb.prefixLen
33}
34
35func (bb *byteBuilder) flush() {
36 if bb.child == nil {
37 return
38 }
39 bb.child.flush()
40 writeLen((*bb.buf)[bb.child.start:], bb.child.len(), bb.child.prefixLen)
41 bb.child = nil
42 return
43}
44
45func (bb *byteBuilder) finish() []byte {
46 bb.flush()
47 return *bb.buf
48}
49
50func (bb *byteBuilder) addU8(u uint8) {
51 bb.flush()
52 *bb.buf = append(*bb.buf, u)
53}
54
55func (bb *byteBuilder) addU16(u uint16) {
56 bb.flush()
57 *bb.buf = append(*bb.buf, byte(u>>8), byte(u))
58}
59
60func (bb *byteBuilder) addU24(u int) {
61 bb.flush()
62 *bb.buf = append(*bb.buf, byte(u>>16), byte(u>>8), byte(u))
63}
64
65func (bb *byteBuilder) addU32(u uint32) {
66 bb.flush()
67 *bb.buf = append(*bb.buf, byte(u>>24), byte(u>>16), byte(u>>8), byte(u))
68}
69
70func (bb *byteBuilder) addU8LengthPrefixed() *byteBuilder {
71 return bb.createChild(1)
72}
73
74func (bb *byteBuilder) addU16LengthPrefixed() *byteBuilder {
75 return bb.createChild(2)
76}
77
78func (bb *byteBuilder) addU24LengthPrefixed() *byteBuilder {
79 return bb.createChild(3)
80}
81
82func (bb *byteBuilder) addBytes(b []byte) {
83 bb.flush()
84 *bb.buf = append(*bb.buf, b...)
85}
86
87func (bb *byteBuilder) createChild(lengthPrefixSize int) *byteBuilder {
88 bb.flush()
89 bb.child = &byteBuilder{
90 buf: bb.buf,
91 start: len(*bb.buf),
92 prefixLen: lengthPrefixSize,
93 }
94 for i := 0; i < lengthPrefixSize; i++ {
95 *bb.buf = append(*bb.buf, 0)
96 }
97 return bb.child
98}
99
100func (bb *byteBuilder) discardChild() {
101 if bb.child != nil {
102 return
103 }
104 bb.child = nil
105 *bb.buf = (*bb.buf)[:bb.start]
106}
107
Nick Harperf8b0e702016-06-30 19:59:01 -0400108type keyShareEntry struct {
109 group CurveID
110 keyExchange []byte
111}
112
Adam Langley95c29f32014-06-20 12:00:00 -0700113type clientHelloMsg struct {
Nick Harperb41d2e42016-07-01 17:50:32 -0400114 raw []byte
115 isDTLS bool
116 vers uint16
117 random []byte
118 sessionId []byte
119 // TODO(davidben): Add support for TLS 1.3 cookies which are larger and
120 // use an extension.
David Benjaminca6c8262014-11-15 19:06:08 -0500121 cookie []byte
122 cipherSuites []uint16
123 compressionMethods []uint8
124 nextProtoNeg bool
125 serverName string
126 ocspStapling bool
127 supportedCurves []CurveID
128 supportedPoints []uint8
Nick Harperf8b0e702016-06-30 19:59:01 -0400129 keyShares []keyShareEntry
130 pskIdentities [][]uint8
131 hasEarlyData bool
132 earlyDataContext []byte
David Benjaminca6c8262014-11-15 19:06:08 -0500133 ticketSupported bool
134 sessionTicket []uint8
Nick Harper60edffd2016-06-21 15:19:24 -0700135 signatureAlgorithms []signatureAlgorithm
David Benjaminca6c8262014-11-15 19:06:08 -0500136 secureRenegotiation []byte
137 alpnProtocols []string
138 duplicateExtension bool
139 channelIDSupported bool
140 npnLast bool
141 extendedMasterSecret bool
142 srtpProtectionProfiles []uint16
143 srtpMasterKeyIdentifier string
David Benjamin61f95272014-11-25 01:55:35 -0500144 sctListSupported bool
Adam Langley09505632015-07-30 18:10:13 -0700145 customExtension string
Adam Langley95c29f32014-06-20 12:00:00 -0700146}
147
148func (m *clientHelloMsg) equal(i interface{}) bool {
149 m1, ok := i.(*clientHelloMsg)
150 if !ok {
151 return false
152 }
153
154 return bytes.Equal(m.raw, m1.raw) &&
David Benjamin83c0bc92014-08-04 01:23:53 -0400155 m.isDTLS == m1.isDTLS &&
Adam Langley95c29f32014-06-20 12:00:00 -0700156 m.vers == m1.vers &&
157 bytes.Equal(m.random, m1.random) &&
158 bytes.Equal(m.sessionId, m1.sessionId) &&
David Benjamin83c0bc92014-08-04 01:23:53 -0400159 bytes.Equal(m.cookie, m1.cookie) &&
Adam Langley95c29f32014-06-20 12:00:00 -0700160 eqUint16s(m.cipherSuites, m1.cipherSuites) &&
161 bytes.Equal(m.compressionMethods, m1.compressionMethods) &&
162 m.nextProtoNeg == m1.nextProtoNeg &&
163 m.serverName == m1.serverName &&
164 m.ocspStapling == m1.ocspStapling &&
165 eqCurveIDs(m.supportedCurves, m1.supportedCurves) &&
166 bytes.Equal(m.supportedPoints, m1.supportedPoints) &&
Nick Harperf8b0e702016-06-30 19:59:01 -0400167 eqKeyShareEntryLists(m.keyShares, m1.keyShares) &&
168 eqByteSlices(m.pskIdentities, m1.pskIdentities) &&
169 m.hasEarlyData == m1.hasEarlyData &&
170 bytes.Equal(m.earlyDataContext, m1.earlyDataContext) &&
Adam Langley95c29f32014-06-20 12:00:00 -0700171 m.ticketSupported == m1.ticketSupported &&
172 bytes.Equal(m.sessionTicket, m1.sessionTicket) &&
Nick Harper60edffd2016-06-21 15:19:24 -0700173 eqSignatureAlgorithms(m.signatureAlgorithms, m1.signatureAlgorithms) &&
Adam Langley2ae77d22014-10-28 17:29:33 -0700174 bytes.Equal(m.secureRenegotiation, m1.secureRenegotiation) &&
175 (m.secureRenegotiation == nil) == (m1.secureRenegotiation == nil) &&
David Benjaminfa055a22014-09-15 16:51:51 -0400176 eqStrings(m.alpnProtocols, m1.alpnProtocols) &&
David Benjamind30a9902014-08-24 01:44:23 -0400177 m.duplicateExtension == m1.duplicateExtension &&
David Benjaminfc7b0862014-09-06 13:21:53 -0400178 m.channelIDSupported == m1.channelIDSupported &&
Adam Langley75712922014-10-10 16:23:43 -0700179 m.npnLast == m1.npnLast &&
David Benjaminca6c8262014-11-15 19:06:08 -0500180 m.extendedMasterSecret == m1.extendedMasterSecret &&
181 eqUint16s(m.srtpProtectionProfiles, m1.srtpProtectionProfiles) &&
David Benjamin61f95272014-11-25 01:55:35 -0500182 m.srtpMasterKeyIdentifier == m1.srtpMasterKeyIdentifier &&
Adam Langley09505632015-07-30 18:10:13 -0700183 m.sctListSupported == m1.sctListSupported &&
184 m.customExtension == m1.customExtension
Adam Langley95c29f32014-06-20 12:00:00 -0700185}
186
187func (m *clientHelloMsg) marshal() []byte {
188 if m.raw != nil {
189 return m.raw
190 }
191
Nick Harper8dda5cc2016-06-30 18:51:11 -0400192 handshakeMsg := newByteBuilder()
193 handshakeMsg.addU8(typeClientHello)
194 hello := handshakeMsg.addU24LengthPrefixed()
David Benjamin83c0bc92014-08-04 01:23:53 -0400195 vers := versionToWire(m.vers, m.isDTLS)
Nick Harper8dda5cc2016-06-30 18:51:11 -0400196 hello.addU16(vers)
197 hello.addBytes(m.random)
198 sessionId := hello.addU8LengthPrefixed()
199 sessionId.addBytes(m.sessionId)
David Benjamin83c0bc92014-08-04 01:23:53 -0400200 if m.isDTLS {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400201 cookie := hello.addU8LengthPrefixed()
202 cookie.addBytes(m.cookie)
David Benjamin83c0bc92014-08-04 01:23:53 -0400203 }
Nick Harper8dda5cc2016-06-30 18:51:11 -0400204 cipherSuites := hello.addU16LengthPrefixed()
205 for _, suite := range m.cipherSuites {
206 cipherSuites.addU16(suite)
Adam Langley95c29f32014-06-20 12:00:00 -0700207 }
Nick Harper8dda5cc2016-06-30 18:51:11 -0400208 compressionMethods := hello.addU8LengthPrefixed()
209 compressionMethods.addBytes(m.compressionMethods)
Adam Langley95c29f32014-06-20 12:00:00 -0700210
Nick Harper8dda5cc2016-06-30 18:51:11 -0400211 extensions := hello.addU16LengthPrefixed()
David Benjamin35a7a442014-07-05 00:23:20 -0400212 if m.duplicateExtension {
213 // Add a duplicate bogus extension at the beginning and end.
Nick Harper8dda5cc2016-06-30 18:51:11 -0400214 extensions.addU16(0xffff)
215 extensions.addU16(0) // 0-length for empty extension
David Benjamin35a7a442014-07-05 00:23:20 -0400216 }
David Benjaminfc7b0862014-09-06 13:21:53 -0400217 if m.nextProtoNeg && !m.npnLast {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400218 extensions.addU16(extensionNextProtoNeg)
219 extensions.addU16(0) // The length is always 0
Adam Langley95c29f32014-06-20 12:00:00 -0700220 }
221 if len(m.serverName) > 0 {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400222 extensions.addU16(extensionServerName)
223 serverNameList := extensions.addU16LengthPrefixed()
Adam Langley95c29f32014-06-20 12:00:00 -0700224
225 // RFC 3546, section 3.1
226 //
227 // struct {
228 // NameType name_type;
229 // select (name_type) {
230 // case host_name: HostName;
231 // } name;
232 // } ServerName;
233 //
234 // enum {
235 // host_name(0), (255)
236 // } NameType;
237 //
238 // opaque HostName<1..2^16-1>;
239 //
240 // struct {
241 // ServerName server_name_list<1..2^16-1>
242 // } ServerNameList;
243
Nick Harper8dda5cc2016-06-30 18:51:11 -0400244 serverName := serverNameList.addU16LengthPrefixed()
245 serverName.addU8(0) // NameType host_name(0)
246 hostName := serverName.addU16LengthPrefixed()
247 hostName.addBytes([]byte(m.serverName))
Adam Langley95c29f32014-06-20 12:00:00 -0700248 }
249 if m.ocspStapling {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400250 extensions.addU16(extensionStatusRequest)
251 certificateStatusRequest := extensions.addU16LengthPrefixed()
252
Adam Langley95c29f32014-06-20 12:00:00 -0700253 // RFC 4366, section 3.6
Nick Harper8dda5cc2016-06-30 18:51:11 -0400254 certificateStatusRequest.addU8(1) // OCSP type
Adam Langley95c29f32014-06-20 12:00:00 -0700255 // Two zero valued uint16s for the two lengths.
Nick Harper8dda5cc2016-06-30 18:51:11 -0400256 certificateStatusRequest.addU16(0) // ResponderID length
257 certificateStatusRequest.addU16(0) // Extensions length
Adam Langley95c29f32014-06-20 12:00:00 -0700258 }
259 if len(m.supportedCurves) > 0 {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400260 // http://tools.ietf.org/html/rfc4492#section-5.1.1
261 extensions.addU16(extensionSupportedCurves)
262 supportedCurvesList := extensions.addU16LengthPrefixed()
263 supportedCurves := supportedCurvesList.addU16LengthPrefixed()
Adam Langley95c29f32014-06-20 12:00:00 -0700264 for _, curve := range m.supportedCurves {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400265 supportedCurves.addU16(uint16(curve))
Adam Langley95c29f32014-06-20 12:00:00 -0700266 }
267 }
268 if len(m.supportedPoints) > 0 {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400269 // http://tools.ietf.org/html/rfc4492#section-5.1.2
270 extensions.addU16(extensionSupportedPoints)
271 supportedPointsList := extensions.addU16LengthPrefixed()
272 supportedPoints := supportedPointsList.addU8LengthPrefixed()
Adam Langley95c29f32014-06-20 12:00:00 -0700273 for _, pointFormat := range m.supportedPoints {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400274 supportedPoints.addU8(pointFormat)
Adam Langley95c29f32014-06-20 12:00:00 -0700275 }
276 }
Nick Harperf8b0e702016-06-30 19:59:01 -0400277 if len(m.keyShares) > 0 {
278 extensions.addU16(extensionKeyShare)
279 keyShareList := extensions.addU16LengthPrefixed()
280
281 keyShares := keyShareList.addU16LengthPrefixed()
282 for _, keyShare := range m.keyShares {
283 keyShares.addU16(uint16(keyShare.group))
284 keyExchange := keyShares.addU16LengthPrefixed()
285 keyExchange.addBytes(keyShare.keyExchange)
286 }
287 }
288 if len(m.pskIdentities) > 0 {
289 extensions.addU16(extensionPreSharedKey)
290 pskExtension := extensions.addU16LengthPrefixed()
291
292 pskIdentities := pskExtension.addU16LengthPrefixed()
293 for _, psk := range m.pskIdentities {
294 pskIdentity := pskIdentities.addU16LengthPrefixed()
295 pskIdentity.addBytes(psk)
296 }
297 }
298 if m.hasEarlyData {
299 extensions.addU16(extensionEarlyData)
300 earlyDataIndication := extensions.addU16LengthPrefixed()
301
302 context := earlyDataIndication.addU8LengthPrefixed()
303 context.addBytes(m.earlyDataContext)
304 }
Adam Langley95c29f32014-06-20 12:00:00 -0700305 if m.ticketSupported {
306 // http://tools.ietf.org/html/rfc5077#section-3.2
Nick Harper8dda5cc2016-06-30 18:51:11 -0400307 extensions.addU16(extensionSessionTicket)
308 sessionTicketExtension := extensions.addU16LengthPrefixed()
309 sessionTicketExtension.addBytes(m.sessionTicket)
Adam Langley95c29f32014-06-20 12:00:00 -0700310 }
Nick Harper60edffd2016-06-21 15:19:24 -0700311 if len(m.signatureAlgorithms) > 0 {
Adam Langley95c29f32014-06-20 12:00:00 -0700312 // https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
Nick Harper8dda5cc2016-06-30 18:51:11 -0400313 extensions.addU16(extensionSignatureAlgorithms)
314 signatureAlgorithmsExtension := extensions.addU16LengthPrefixed()
315 signatureAlgorithms := signatureAlgorithmsExtension.addU16LengthPrefixed()
Nick Harper60edffd2016-06-21 15:19:24 -0700316 for _, sigAlg := range m.signatureAlgorithms {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400317 signatureAlgorithms.addU16(uint16(sigAlg))
Adam Langley95c29f32014-06-20 12:00:00 -0700318 }
319 }
Adam Langley2ae77d22014-10-28 17:29:33 -0700320 if m.secureRenegotiation != nil {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400321 extensions.addU16(extensionRenegotiationInfo)
322 secureRenegoExt := extensions.addU16LengthPrefixed()
323 secureRenego := secureRenegoExt.addU8LengthPrefixed()
324 secureRenego.addBytes(m.secureRenegotiation)
Adam Langley95c29f32014-06-20 12:00:00 -0700325 }
David Benjaminfa055a22014-09-15 16:51:51 -0400326 if len(m.alpnProtocols) > 0 {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400327 // https://tools.ietf.org/html/rfc7301#section-3.1
328 extensions.addU16(extensionALPN)
329 alpnExtension := extensions.addU16LengthPrefixed()
David Benjaminfa055a22014-09-15 16:51:51 -0400330
Nick Harper8dda5cc2016-06-30 18:51:11 -0400331 protocolNameList := alpnExtension.addU16LengthPrefixed()
David Benjaminfa055a22014-09-15 16:51:51 -0400332 for _, s := range m.alpnProtocols {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400333 protocolName := protocolNameList.addU8LengthPrefixed()
334 protocolName.addBytes([]byte(s))
David Benjaminfa055a22014-09-15 16:51:51 -0400335 }
David Benjaminfa055a22014-09-15 16:51:51 -0400336 }
David Benjamind30a9902014-08-24 01:44:23 -0400337 if m.channelIDSupported {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400338 extensions.addU16(extensionChannelID)
339 extensions.addU16(0) // Length is always 0
David Benjamind30a9902014-08-24 01:44:23 -0400340 }
David Benjaminfc7b0862014-09-06 13:21:53 -0400341 if m.nextProtoNeg && m.npnLast {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400342 extensions.addU16(extensionNextProtoNeg)
343 extensions.addU16(0) // Length is always 0
David Benjaminfc7b0862014-09-06 13:21:53 -0400344 }
David Benjamin35a7a442014-07-05 00:23:20 -0400345 if m.duplicateExtension {
346 // Add a duplicate bogus extension at the beginning and end.
Nick Harper8dda5cc2016-06-30 18:51:11 -0400347 extensions.addU16(0xffff)
348 extensions.addU16(0)
David Benjamin35a7a442014-07-05 00:23:20 -0400349 }
Adam Langley75712922014-10-10 16:23:43 -0700350 if m.extendedMasterSecret {
David Benjamin43946d42016-02-01 08:42:19 -0500351 // https://tools.ietf.org/html/rfc7627
Nick Harper8dda5cc2016-06-30 18:51:11 -0400352 extensions.addU16(extensionExtendedMasterSecret)
353 extensions.addU16(0) // Length is always 0
Adam Langley75712922014-10-10 16:23:43 -0700354 }
David Benjaminca6c8262014-11-15 19:06:08 -0500355 if len(m.srtpProtectionProfiles) > 0 {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400356 // https://tools.ietf.org/html/rfc5764#section-4.1.1
357 extensions.addU16(extensionUseSRTP)
358 useSrtpExt := extensions.addU16LengthPrefixed()
David Benjaminca6c8262014-11-15 19:06:08 -0500359
Nick Harper8dda5cc2016-06-30 18:51:11 -0400360 srtpProtectionProfiles := useSrtpExt.addU16LengthPrefixed()
David Benjaminca6c8262014-11-15 19:06:08 -0500361 for _, p := range m.srtpProtectionProfiles {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400362 // An SRTPProtectionProfile is defined as uint8[2],
363 // not uint16. For some reason, we're storing it
364 // as a uint16.
365 srtpProtectionProfiles.addU8(byte(p >> 8))
366 srtpProtectionProfiles.addU8(byte(p))
David Benjaminca6c8262014-11-15 19:06:08 -0500367 }
Nick Harper8dda5cc2016-06-30 18:51:11 -0400368 srtpMki := useSrtpExt.addU8LengthPrefixed()
369 srtpMki.addBytes([]byte(m.srtpMasterKeyIdentifier))
David Benjaminca6c8262014-11-15 19:06:08 -0500370 }
David Benjamin61f95272014-11-25 01:55:35 -0500371 if m.sctListSupported {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400372 extensions.addU16(extensionSignedCertificateTimestamp)
373 extensions.addU16(0) // Length is always 0
David Benjamin61f95272014-11-25 01:55:35 -0500374 }
Adam Langley09505632015-07-30 18:10:13 -0700375 if l := len(m.customExtension); l > 0 {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400376 extensions.addU16(extensionCustom)
377 customExt := extensions.addU16LengthPrefixed()
378 customExt.addBytes([]byte(m.customExtension))
Adam Langley09505632015-07-30 18:10:13 -0700379 }
Adam Langley95c29f32014-06-20 12:00:00 -0700380
Nick Harper8dda5cc2016-06-30 18:51:11 -0400381 if extensions.len() == 0 {
382 hello.discardChild()
383 }
Adam Langley95c29f32014-06-20 12:00:00 -0700384
Nick Harper8dda5cc2016-06-30 18:51:11 -0400385 m.raw = handshakeMsg.finish()
386 return m.raw
Adam Langley95c29f32014-06-20 12:00:00 -0700387}
388
389func (m *clientHelloMsg) unmarshal(data []byte) bool {
390 if len(data) < 42 {
391 return false
392 }
393 m.raw = data
David Benjamin83c0bc92014-08-04 01:23:53 -0400394 m.vers = wireToVersion(uint16(data[4])<<8|uint16(data[5]), m.isDTLS)
Adam Langley95c29f32014-06-20 12:00:00 -0700395 m.random = data[6:38]
396 sessionIdLen := int(data[38])
397 if sessionIdLen > 32 || len(data) < 39+sessionIdLen {
398 return false
399 }
400 m.sessionId = data[39 : 39+sessionIdLen]
401 data = data[39+sessionIdLen:]
David Benjamin83c0bc92014-08-04 01:23:53 -0400402 if m.isDTLS {
403 if len(data) < 1 {
404 return false
405 }
406 cookieLen := int(data[0])
407 if cookieLen > 32 || len(data) < 1+cookieLen {
408 return false
409 }
410 m.cookie = data[1 : 1+cookieLen]
411 data = data[1+cookieLen:]
412 }
Adam Langley95c29f32014-06-20 12:00:00 -0700413 if len(data) < 2 {
414 return false
415 }
416 // cipherSuiteLen is the number of bytes of cipher suite numbers. Since
417 // they are uint16s, the number must be even.
418 cipherSuiteLen := int(data[0])<<8 | int(data[1])
419 if cipherSuiteLen%2 == 1 || len(data) < 2+cipherSuiteLen {
420 return false
421 }
422 numCipherSuites := cipherSuiteLen / 2
423 m.cipherSuites = make([]uint16, numCipherSuites)
424 for i := 0; i < numCipherSuites; i++ {
425 m.cipherSuites[i] = uint16(data[2+2*i])<<8 | uint16(data[3+2*i])
426 if m.cipherSuites[i] == scsvRenegotiation {
Adam Langley2ae77d22014-10-28 17:29:33 -0700427 m.secureRenegotiation = []byte{}
Adam Langley95c29f32014-06-20 12:00:00 -0700428 }
429 }
430 data = data[2+cipherSuiteLen:]
431 if len(data) < 1 {
432 return false
433 }
434 compressionMethodsLen := int(data[0])
435 if len(data) < 1+compressionMethodsLen {
436 return false
437 }
438 m.compressionMethods = data[1 : 1+compressionMethodsLen]
439
440 data = data[1+compressionMethodsLen:]
441
442 m.nextProtoNeg = false
443 m.serverName = ""
444 m.ocspStapling = false
Nick Harperf8b0e702016-06-30 19:59:01 -0400445 m.keyShares = nil
446 m.pskIdentities = nil
447 m.hasEarlyData = false
448 m.earlyDataContext = nil
Adam Langley95c29f32014-06-20 12:00:00 -0700449 m.ticketSupported = false
450 m.sessionTicket = nil
Nick Harper60edffd2016-06-21 15:19:24 -0700451 m.signatureAlgorithms = nil
David Benjaminfa055a22014-09-15 16:51:51 -0400452 m.alpnProtocols = nil
Adam Langley75712922014-10-10 16:23:43 -0700453 m.extendedMasterSecret = false
Adam Langley09505632015-07-30 18:10:13 -0700454 m.customExtension = ""
Adam Langley95c29f32014-06-20 12:00:00 -0700455
456 if len(data) == 0 {
457 // ClientHello is optionally followed by extension data
458 return true
459 }
460 if len(data) < 2 {
461 return false
462 }
463
464 extensionsLength := int(data[0])<<8 | int(data[1])
465 data = data[2:]
466 if extensionsLength != len(data) {
467 return false
468 }
469
470 for len(data) != 0 {
471 if len(data) < 4 {
472 return false
473 }
474 extension := uint16(data[0])<<8 | uint16(data[1])
475 length := int(data[2])<<8 | int(data[3])
476 data = data[4:]
477 if len(data) < length {
478 return false
479 }
480
481 switch extension {
482 case extensionServerName:
483 if length < 2 {
484 return false
485 }
486 numNames := int(data[0])<<8 | int(data[1])
487 d := data[2:]
488 for i := 0; i < numNames; i++ {
489 if len(d) < 3 {
490 return false
491 }
492 nameType := d[0]
493 nameLen := int(d[1])<<8 | int(d[2])
494 d = d[3:]
495 if len(d) < nameLen {
496 return false
497 }
498 if nameType == 0 {
499 m.serverName = string(d[0:nameLen])
500 break
501 }
502 d = d[nameLen:]
503 }
504 case extensionNextProtoNeg:
505 if length > 0 {
506 return false
507 }
508 m.nextProtoNeg = true
509 case extensionStatusRequest:
510 m.ocspStapling = length > 0 && data[0] == statusTypeOCSP
511 case extensionSupportedCurves:
512 // http://tools.ietf.org/html/rfc4492#section-5.5.1
513 if length < 2 {
514 return false
515 }
516 l := int(data[0])<<8 | int(data[1])
517 if l%2 == 1 || length != l+2 {
518 return false
519 }
520 numCurves := l / 2
521 m.supportedCurves = make([]CurveID, numCurves)
522 d := data[2:]
523 for i := 0; i < numCurves; i++ {
524 m.supportedCurves[i] = CurveID(d[0])<<8 | CurveID(d[1])
525 d = d[2:]
526 }
527 case extensionSupportedPoints:
528 // http://tools.ietf.org/html/rfc4492#section-5.5.2
529 if length < 1 {
530 return false
531 }
532 l := int(data[0])
533 if length != l+1 {
534 return false
535 }
536 m.supportedPoints = make([]uint8, l)
537 copy(m.supportedPoints, data[1:])
538 case extensionSessionTicket:
539 // http://tools.ietf.org/html/rfc5077#section-3.2
540 m.ticketSupported = true
541 m.sessionTicket = data[:length]
Nick Harperf8b0e702016-06-30 19:59:01 -0400542 case extensionKeyShare:
543 // draft-ietf-tls-tls13 section 6.3.2.3
544 if length < 2 {
545 return false
546 }
547 l := int(data[0])<<8 | int(data[1])
548 if l != length-2 {
549 return false
550 }
551 d := data[2:length]
552 for len(d) > 0 {
553 // The next KeyShareEntry contains a NamedGroup (2 bytes) and a
554 // key_exchange (2-byte length prefix with at least 1 byte of content).
555 if len(d) < 5 {
556 return false
557 }
558 entry := keyShareEntry{}
559 entry.group = CurveID(d[0])<<8 | CurveID(d[1])
560 keyExchLen := int(d[2])<<8 | int(d[3])
561 d = d[4:]
562 if len(d) < keyExchLen {
563 return false
564 }
565 entry.keyExchange = d[:keyExchLen]
566 d = d[keyExchLen:]
567 m.keyShares = append(m.keyShares, entry)
568 }
569 case extensionPreSharedKey:
570 // draft-ietf-tls-tls13 section 6.3.2.4
571 if length < 2 {
572 return false
573 }
574 l := int(data[0])<<8 | int(data[1])
575 if l != length-2 {
576 return false
577 }
578 d := data[2:length]
579 for len(d) > 0 {
580 if len(d) < 2 {
581 return false
582 }
583 pskLen := int(d[0])<<8 | int(d[1])
584 d = d[2:]
585 if len(d) < pskLen {
586 return false
587 }
588 psk := d[:pskLen]
589 m.pskIdentities = append(m.pskIdentities, psk)
590 d = d[pskLen:]
591 }
592 case extensionEarlyData:
593 // draft-ietf-tls-tls13 section 6.3.2.5
594 if length < 1 {
595 return false
596 }
597 l := int(data[0])
598 if length != l+1 {
599 return false
600 }
601 m.hasEarlyData = true
602 m.earlyDataContext = data[1:length]
Adam Langley95c29f32014-06-20 12:00:00 -0700603 case extensionSignatureAlgorithms:
604 // https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
605 if length < 2 || length&1 != 0 {
606 return false
607 }
608 l := int(data[0])<<8 | int(data[1])
609 if l != length-2 {
610 return false
611 }
612 n := l / 2
613 d := data[2:]
Nick Harper60edffd2016-06-21 15:19:24 -0700614 m.signatureAlgorithms = make([]signatureAlgorithm, n)
615 for i := range m.signatureAlgorithms {
616 m.signatureAlgorithms[i] = signatureAlgorithm(d[0])<<8 | signatureAlgorithm(d[1])
Adam Langley95c29f32014-06-20 12:00:00 -0700617 d = d[2:]
618 }
Adam Langley2ae77d22014-10-28 17:29:33 -0700619 case extensionRenegotiationInfo:
620 if length < 1 || length != int(data[0])+1 {
Adam Langley95c29f32014-06-20 12:00:00 -0700621 return false
622 }
Adam Langley2ae77d22014-10-28 17:29:33 -0700623 m.secureRenegotiation = data[1:length]
David Benjaminfa055a22014-09-15 16:51:51 -0400624 case extensionALPN:
625 if length < 2 {
626 return false
627 }
628 l := int(data[0])<<8 | int(data[1])
629 if l != length-2 {
630 return false
631 }
632 d := data[2:length]
633 for len(d) != 0 {
634 stringLen := int(d[0])
635 d = d[1:]
636 if stringLen == 0 || stringLen > len(d) {
637 return false
638 }
639 m.alpnProtocols = append(m.alpnProtocols, string(d[:stringLen]))
640 d = d[stringLen:]
641 }
David Benjamind30a9902014-08-24 01:44:23 -0400642 case extensionChannelID:
643 if length > 0 {
644 return false
645 }
646 m.channelIDSupported = true
Adam Langley75712922014-10-10 16:23:43 -0700647 case extensionExtendedMasterSecret:
648 if length != 0 {
649 return false
650 }
651 m.extendedMasterSecret = true
David Benjaminca6c8262014-11-15 19:06:08 -0500652 case extensionUseSRTP:
653 if length < 2 {
654 return false
655 }
656 l := int(data[0])<<8 | int(data[1])
657 if l > length-2 || l%2 != 0 {
658 return false
659 }
660 n := l / 2
661 m.srtpProtectionProfiles = make([]uint16, n)
662 d := data[2:length]
663 for i := 0; i < n; i++ {
664 m.srtpProtectionProfiles[i] = uint16(d[0])<<8 | uint16(d[1])
665 d = d[2:]
666 }
667 if len(d) < 1 || int(d[0]) != len(d)-1 {
668 return false
669 }
670 m.srtpMasterKeyIdentifier = string(d[1:])
David Benjamin61f95272014-11-25 01:55:35 -0500671 case extensionSignedCertificateTimestamp:
672 if length != 0 {
673 return false
674 }
675 m.sctListSupported = true
Adam Langley09505632015-07-30 18:10:13 -0700676 case extensionCustom:
677 m.customExtension = string(data[:length])
Adam Langley95c29f32014-06-20 12:00:00 -0700678 }
679 data = data[length:]
680 }
681
682 return true
683}
684
685type serverHelloMsg struct {
Nick Harperb41d2e42016-07-01 17:50:32 -0400686 raw []byte
687 isDTLS bool
688 vers uint16
689 random []byte
690 sessionId []byte
691 cipherSuite uint16
692 hasKeyShare bool
693 keyShare keyShareEntry
694 hasPSKIdentity bool
695 pskIdentity uint16
696 earlyDataIndication bool
697 compressionMethod uint8
698 extensions serverExtensions
Adam Langley95c29f32014-06-20 12:00:00 -0700699}
700
Adam Langley95c29f32014-06-20 12:00:00 -0700701func (m *serverHelloMsg) marshal() []byte {
702 if m.raw != nil {
703 return m.raw
704 }
705
Nick Harper5212ef82016-06-30 19:26:07 -0400706 handshakeMsg := newByteBuilder()
707 handshakeMsg.addU8(typeServerHello)
708 hello := handshakeMsg.addU24LengthPrefixed()
David Benjamin83c0bc92014-08-04 01:23:53 -0400709 vers := versionToWire(m.vers, m.isDTLS)
Nick Harper5212ef82016-06-30 19:26:07 -0400710 hello.addU16(vers)
711 hello.addBytes(m.random)
Nick Harperb41d2e42016-07-01 17:50:32 -0400712 if m.vers < VersionTLS13 || !enableTLS13Handshake {
713 sessionId := hello.addU8LengthPrefixed()
714 sessionId.addBytes(m.sessionId)
715 }
Nick Harper5212ef82016-06-30 19:26:07 -0400716 hello.addU16(m.cipherSuite)
Nick Harperb41d2e42016-07-01 17:50:32 -0400717 if m.vers < VersionTLS13 || !enableTLS13Handshake {
718 hello.addU8(m.compressionMethod)
719 }
Adam Langley95c29f32014-06-20 12:00:00 -0700720
Nick Harper5212ef82016-06-30 19:26:07 -0400721 extensions := hello.addU16LengthPrefixed()
Nick Harperb3d51be2016-07-01 11:43:18 -0400722
Nick Harperb41d2e42016-07-01 17:50:32 -0400723 if m.vers >= VersionTLS13 && enableTLS13Handshake {
724 if m.hasKeyShare {
725 extensions.addU16(extensionKeyShare)
726 keyShare := extensions.addU16LengthPrefixed()
727 keyShare.addU16(uint16(m.keyShare.group))
728 keyExchange := keyShare.addU16LengthPrefixed()
729 keyExchange.addBytes(m.keyShare.keyExchange)
730 }
731 if m.hasPSKIdentity {
732 extensions.addU16(extensionPreSharedKey)
733 extensions.addU16(2) // Length
734 extensions.addU16(m.pskIdentity)
735 }
736 if m.earlyDataIndication {
737 extensions.addU16(extensionEarlyData)
738 extensions.addU16(0) // Length
739 }
740 } else {
David Benjamin44b33bc2016-07-01 22:40:23 -0400741 m.extensions.marshal(extensions, m.vers)
Nick Harperb41d2e42016-07-01 17:50:32 -0400742 if extensions.len() == 0 {
743 hello.discardChild()
744 }
Nick Harperb3d51be2016-07-01 11:43:18 -0400745 }
746
747 m.raw = handshakeMsg.finish()
748 return m.raw
749}
750
751func (m *serverHelloMsg) unmarshal(data []byte) bool {
752 if len(data) < 42 {
753 return false
754 }
755 m.raw = data
756 m.vers = wireToVersion(uint16(data[4])<<8|uint16(data[5]), m.isDTLS)
757 m.random = data[6:38]
Nick Harperb41d2e42016-07-01 17:50:32 -0400758 data = data[38:]
759 if m.vers < VersionTLS13 || !enableTLS13Handshake {
760 sessionIdLen := int(data[0])
761 if sessionIdLen > 32 || len(data) < 1+sessionIdLen {
762 return false
763 }
764 m.sessionId = data[1 : 1+sessionIdLen]
765 data = data[1+sessionIdLen:]
Nick Harperb3d51be2016-07-01 11:43:18 -0400766 }
Nick Harperb41d2e42016-07-01 17:50:32 -0400767 if len(data) < 2 {
Nick Harperb3d51be2016-07-01 11:43:18 -0400768 return false
769 }
770 m.cipherSuite = uint16(data[0])<<8 | uint16(data[1])
Nick Harperb41d2e42016-07-01 17:50:32 -0400771 data = data[2:]
772 if m.vers < VersionTLS13 || !enableTLS13Handshake {
773 if len(data) < 1 {
774 return false
775 }
776 m.compressionMethod = data[0]
777 data = data[1:]
778 }
Nick Harperb3d51be2016-07-01 11:43:18 -0400779
Nick Harperb41d2e42016-07-01 17:50:32 -0400780 if len(data) == 0 && (m.vers < VersionTLS13 || enableTLS13Handshake) {
781 // Extension data is optional before TLS 1.3.
Nick Harperb3d51be2016-07-01 11:43:18 -0400782 m.extensions = serverExtensions{}
783 return true
784 }
785 if len(data) < 2 {
786 return false
787 }
788
789 extensionsLength := int(data[0])<<8 | int(data[1])
790 data = data[2:]
791 if len(data) != extensionsLength {
792 return false
793 }
794
Nick Harperb41d2e42016-07-01 17:50:32 -0400795 if m.vers >= VersionTLS13 && enableTLS13Handshake {
796 for len(data) != 0 {
797 if len(data) < 4 {
798 return false
799 }
800 extension := uint16(data[0])<<8 | uint16(data[1])
801 length := int(data[2])<<8 | int(data[3])
802 data = data[4:]
803
804 if len(data) < length {
805 return false
806 }
807 d := data[:length]
808 data = data[length:]
809
810 switch extension {
811 case extensionKeyShare:
812 m.hasKeyShare = true
813 if len(d) < 4 {
814 return false
815 }
816 m.keyShare.group = CurveID(uint16(d[0])<<8 | uint16(d[1]))
817 keyExchLen := int(d[2])<<8 | int(d[3])
818 if keyExchLen != len(d)-4 {
819 return false
820 }
821 m.keyShare.keyExchange = make([]byte, keyExchLen)
822 copy(m.keyShare.keyExchange, d[4:])
823 case extensionPreSharedKey:
824 if len(d) != 2 {
825 return false
826 }
827 m.pskIdentity = uint16(d[0])<<8 | uint16(d[1])
828 m.hasPSKIdentity = true
829 case extensionEarlyData:
830 if len(d) != 0 {
831 return false
832 }
833 m.earlyDataIndication = true
834 default:
835 // Only allow the 3 extensions that are sent in
836 // the clear in TLS 1.3.
837 return false
838 }
839 }
David Benjamin44b33bc2016-07-01 22:40:23 -0400840 } else if !m.extensions.unmarshal(data, m.vers) {
Nick Harperb3d51be2016-07-01 11:43:18 -0400841 return false
842 }
843
844 return true
845}
846
Nick Harperb41d2e42016-07-01 17:50:32 -0400847type encryptedExtensionsMsg struct {
848 raw []byte
849 extensions serverExtensions
850}
851
852func (m *encryptedExtensionsMsg) marshal() []byte {
853 if m.raw != nil {
854 return m.raw
855 }
856
857 encryptedExtensionsMsg := newByteBuilder()
858 encryptedExtensionsMsg.addU8(typeEncryptedExtensions)
859 encryptedExtensions := encryptedExtensionsMsg.addU24LengthPrefixed()
860 extensions := encryptedExtensions.addU16LengthPrefixed()
David Benjamin44b33bc2016-07-01 22:40:23 -0400861 m.extensions.marshal(extensions, VersionTLS13)
Nick Harperb41d2e42016-07-01 17:50:32 -0400862
863 m.raw = encryptedExtensionsMsg.finish()
864 return m.raw
865}
866
867func (m *encryptedExtensionsMsg) unmarshal(data []byte) bool {
868 if len(data) < 6 {
869 return false
870 }
871 if data[0] != typeEncryptedExtensions {
872 return false
873 }
874 msgLen := int(data[1])<<16 | int(data[2])<<8 | int(data[3])
875 data = data[4:]
876 if len(data) != msgLen {
877 return false
878 }
879 extLen := int(data[0])<<8 | int(data[1])
880 data = data[2:]
881 if extLen != len(data) {
882 return false
883 }
David Benjamin44b33bc2016-07-01 22:40:23 -0400884 return m.extensions.unmarshal(data, VersionTLS13)
Nick Harperb41d2e42016-07-01 17:50:32 -0400885}
886
Nick Harperb3d51be2016-07-01 11:43:18 -0400887type serverExtensions struct {
888 nextProtoNeg bool
889 nextProtos []string
890 ocspStapling bool
David Benjamin44b33bc2016-07-01 22:40:23 -0400891 ocspResponse []byte
Nick Harperb3d51be2016-07-01 11:43:18 -0400892 ticketSupported bool
893 secureRenegotiation []byte
894 alpnProtocol string
895 alpnProtocolEmpty bool
896 duplicateExtension bool
897 channelIDRequested bool
898 extendedMasterSecret bool
899 srtpProtectionProfile uint16
900 srtpMasterKeyIdentifier string
901 sctList []byte
902 customExtension string
903 npnLast bool
904}
905
David Benjamin44b33bc2016-07-01 22:40:23 -0400906func (m *serverExtensions) marshal(extensions *byteBuilder, version uint16) {
David Benjamin35a7a442014-07-05 00:23:20 -0400907 if m.duplicateExtension {
908 // Add a duplicate bogus extension at the beginning and end.
Nick Harper5212ef82016-06-30 19:26:07 -0400909 extensions.addU16(0xffff)
910 extensions.addU16(0) // length = 0 for empty extension
David Benjamin35a7a442014-07-05 00:23:20 -0400911 }
David Benjamin76c2efc2015-08-31 14:24:29 -0400912 if m.nextProtoNeg && !m.npnLast {
Nick Harper5212ef82016-06-30 19:26:07 -0400913 extensions.addU16(extensionNextProtoNeg)
914 extension := extensions.addU16LengthPrefixed()
Adam Langley95c29f32014-06-20 12:00:00 -0700915
916 for _, v := range m.nextProtos {
Nick Harper5212ef82016-06-30 19:26:07 -0400917 if len(v) > 255 {
918 v = v[:255]
Adam Langley95c29f32014-06-20 12:00:00 -0700919 }
Nick Harper5212ef82016-06-30 19:26:07 -0400920 npn := extension.addU8LengthPrefixed()
921 npn.addBytes([]byte(v))
Adam Langley95c29f32014-06-20 12:00:00 -0700922 }
923 }
David Benjamin44b33bc2016-07-01 22:40:23 -0400924 if version >= VersionTLS13 && enableTLS13Handshake {
925 if m.ocspResponse != nil {
926 extensions.addU16(extensionStatusRequest)
927 body := extensions.addU16LengthPrefixed()
928 body.addU8(statusTypeOCSP)
929 response := body.addU24LengthPrefixed()
930 response.addBytes(m.ocspResponse)
931 }
932 } else {
933 if m.ocspStapling {
934 extensions.addU16(extensionStatusRequest)
935 extensions.addU16(0)
936 }
Adam Langley95c29f32014-06-20 12:00:00 -0700937 }
938 if m.ticketSupported {
Nick Harper5212ef82016-06-30 19:26:07 -0400939 extensions.addU16(extensionSessionTicket)
940 extensions.addU16(0)
Adam Langley95c29f32014-06-20 12:00:00 -0700941 }
Adam Langley2ae77d22014-10-28 17:29:33 -0700942 if m.secureRenegotiation != nil {
Nick Harper5212ef82016-06-30 19:26:07 -0400943 extensions.addU16(extensionRenegotiationInfo)
944 extension := extensions.addU16LengthPrefixed()
945 secureRenego := extension.addU8LengthPrefixed()
946 secureRenego.addBytes(m.secureRenegotiation)
Adam Langley95c29f32014-06-20 12:00:00 -0700947 }
Nick Harper5212ef82016-06-30 19:26:07 -0400948 if len(m.alpnProtocol) > 0 || m.alpnProtocolEmpty {
949 extensions.addU16(extensionALPN)
950 extension := extensions.addU16LengthPrefixed()
951
952 protocolNameList := extension.addU16LengthPrefixed()
953 protocolName := protocolNameList.addU8LengthPrefixed()
954 protocolName.addBytes([]byte(m.alpnProtocol))
David Benjaminfa055a22014-09-15 16:51:51 -0400955 }
David Benjamind30a9902014-08-24 01:44:23 -0400956 if m.channelIDRequested {
Nick Harper5212ef82016-06-30 19:26:07 -0400957 extensions.addU16(extensionChannelID)
958 extensions.addU16(0)
David Benjamind30a9902014-08-24 01:44:23 -0400959 }
David Benjamin35a7a442014-07-05 00:23:20 -0400960 if m.duplicateExtension {
961 // Add a duplicate bogus extension at the beginning and end.
Nick Harper5212ef82016-06-30 19:26:07 -0400962 extensions.addU16(0xffff)
963 extensions.addU16(0)
David Benjamin35a7a442014-07-05 00:23:20 -0400964 }
Adam Langley75712922014-10-10 16:23:43 -0700965 if m.extendedMasterSecret {
Nick Harper5212ef82016-06-30 19:26:07 -0400966 extensions.addU16(extensionExtendedMasterSecret)
967 extensions.addU16(0)
Adam Langley75712922014-10-10 16:23:43 -0700968 }
David Benjaminca6c8262014-11-15 19:06:08 -0500969 if m.srtpProtectionProfile != 0 {
Nick Harper5212ef82016-06-30 19:26:07 -0400970 extensions.addU16(extensionUseSRTP)
971 extension := extensions.addU16LengthPrefixed()
972
973 srtpProtectionProfiles := extension.addU16LengthPrefixed()
974 srtpProtectionProfiles.addU8(byte(m.srtpProtectionProfile >> 8))
975 srtpProtectionProfiles.addU8(byte(m.srtpProtectionProfile))
976 srtpMki := extension.addU8LengthPrefixed()
977 srtpMki.addBytes([]byte(m.srtpMasterKeyIdentifier))
David Benjaminca6c8262014-11-15 19:06:08 -0500978 }
David Benjamin61f95272014-11-25 01:55:35 -0500979 if m.sctList != nil {
Nick Harper5212ef82016-06-30 19:26:07 -0400980 extensions.addU16(extensionSignedCertificateTimestamp)
981 extension := extensions.addU16LengthPrefixed()
982 extension.addBytes(m.sctList)
David Benjamin61f95272014-11-25 01:55:35 -0500983 }
Adam Langley09505632015-07-30 18:10:13 -0700984 if l := len(m.customExtension); l > 0 {
Nick Harper5212ef82016-06-30 19:26:07 -0400985 extensions.addU16(extensionCustom)
986 customExt := extensions.addU16LengthPrefixed()
987 customExt.addBytes([]byte(m.customExtension))
Adam Langley09505632015-07-30 18:10:13 -0700988 }
David Benjamin76c2efc2015-08-31 14:24:29 -0400989 if m.nextProtoNeg && m.npnLast {
Nick Harper5212ef82016-06-30 19:26:07 -0400990 extensions.addU16(extensionNextProtoNeg)
991 extension := extensions.addU16LengthPrefixed()
David Benjamin76c2efc2015-08-31 14:24:29 -0400992
993 for _, v := range m.nextProtos {
Nick Harper5212ef82016-06-30 19:26:07 -0400994 if len(v) > 255 {
995 v = v[0:255]
David Benjamin76c2efc2015-08-31 14:24:29 -0400996 }
Nick Harper5212ef82016-06-30 19:26:07 -0400997 npn := extension.addU8LengthPrefixed()
998 npn.addBytes([]byte(v))
David Benjamin76c2efc2015-08-31 14:24:29 -0400999 }
1000 }
Adam Langley95c29f32014-06-20 12:00:00 -07001001}
1002
David Benjamin44b33bc2016-07-01 22:40:23 -04001003func (m *serverExtensions) unmarshal(data []byte, version uint16) bool {
Nick Harperb3d51be2016-07-01 11:43:18 -04001004 // Reset all fields.
1005 *m = serverExtensions{}
Adam Langley95c29f32014-06-20 12:00:00 -07001006
1007 for len(data) != 0 {
1008 if len(data) < 4 {
1009 return false
1010 }
1011 extension := uint16(data[0])<<8 | uint16(data[1])
1012 length := int(data[2])<<8 | int(data[3])
1013 data = data[4:]
1014 if len(data) < length {
1015 return false
1016 }
1017
1018 switch extension {
1019 case extensionNextProtoNeg:
1020 m.nextProtoNeg = true
1021 d := data[:length]
1022 for len(d) > 0 {
1023 l := int(d[0])
1024 d = d[1:]
1025 if l == 0 || l > len(d) {
1026 return false
1027 }
1028 m.nextProtos = append(m.nextProtos, string(d[:l]))
1029 d = d[l:]
1030 }
1031 case extensionStatusRequest:
David Benjamin44b33bc2016-07-01 22:40:23 -04001032 if version >= VersionTLS13 && enableTLS13Handshake {
1033 if length < 4 {
1034 return false
1035 }
1036 d := data[:length]
1037 if d[0] != statusTypeOCSP {
1038 return false
1039 }
1040 respLen := int(d[1])<<16 | int(d[2])<<8 | int(d[3])
1041 if respLen+4 != len(d) || respLen == 0 {
1042 return false
1043 }
1044 m.ocspResponse = d[4:]
1045 } else {
1046 if length > 0 {
1047 return false
1048 }
1049 m.ocspStapling = true
Adam Langley95c29f32014-06-20 12:00:00 -07001050 }
Adam Langley95c29f32014-06-20 12:00:00 -07001051 case extensionSessionTicket:
1052 if length > 0 {
1053 return false
1054 }
1055 m.ticketSupported = true
1056 case extensionRenegotiationInfo:
Adam Langley2ae77d22014-10-28 17:29:33 -07001057 if length < 1 || length != int(data[0])+1 {
Adam Langley95c29f32014-06-20 12:00:00 -07001058 return false
1059 }
Adam Langley2ae77d22014-10-28 17:29:33 -07001060 m.secureRenegotiation = data[1:length]
David Benjaminfa055a22014-09-15 16:51:51 -04001061 case extensionALPN:
1062 d := data[:length]
1063 if len(d) < 3 {
1064 return false
1065 }
1066 l := int(d[0])<<8 | int(d[1])
1067 if l != len(d)-2 {
1068 return false
1069 }
1070 d = d[2:]
1071 l = int(d[0])
1072 if l != len(d)-1 {
1073 return false
1074 }
1075 d = d[1:]
1076 m.alpnProtocol = string(d)
Adam Langleyefb0e162015-07-09 11:35:04 -07001077 m.alpnProtocolEmpty = len(d) == 0
David Benjamind30a9902014-08-24 01:44:23 -04001078 case extensionChannelID:
1079 if length > 0 {
1080 return false
1081 }
1082 m.channelIDRequested = true
Adam Langley75712922014-10-10 16:23:43 -07001083 case extensionExtendedMasterSecret:
1084 if length != 0 {
1085 return false
1086 }
1087 m.extendedMasterSecret = true
David Benjaminca6c8262014-11-15 19:06:08 -05001088 case extensionUseSRTP:
1089 if length < 2+2+1 {
1090 return false
1091 }
1092 if data[0] != 0 || data[1] != 2 {
1093 return false
1094 }
1095 m.srtpProtectionProfile = uint16(data[2])<<8 | uint16(data[3])
1096 d := data[4:length]
1097 l := int(d[0])
1098 if l != len(d)-1 {
1099 return false
1100 }
1101 m.srtpMasterKeyIdentifier = string(d[1:])
David Benjamin61f95272014-11-25 01:55:35 -05001102 case extensionSignedCertificateTimestamp:
Paul Lietar4fac72e2015-09-09 13:44:55 +01001103 m.sctList = data[:length]
Adam Langley09505632015-07-30 18:10:13 -07001104 case extensionCustom:
1105 m.customExtension = string(data[:length])
Adam Langley95c29f32014-06-20 12:00:00 -07001106 }
1107 data = data[length:]
1108 }
1109
1110 return true
1111}
1112
1113type certificateMsg struct {
Nick Harperb41d2e42016-07-01 17:50:32 -04001114 raw []byte
1115 hasRequestContext bool
1116 requestContext []byte
1117 certificates [][]byte
Adam Langley95c29f32014-06-20 12:00:00 -07001118}
1119
Adam Langley95c29f32014-06-20 12:00:00 -07001120func (m *certificateMsg) marshal() (x []byte) {
1121 if m.raw != nil {
1122 return m.raw
1123 }
1124
Nick Harper7e0442a2016-07-01 17:40:09 -04001125 certMsg := newByteBuilder()
1126 certMsg.addU8(typeCertificate)
1127 certificate := certMsg.addU24LengthPrefixed()
Nick Harperb41d2e42016-07-01 17:50:32 -04001128 if m.hasRequestContext {
1129 context := certificate.addU8LengthPrefixed()
1130 context.addBytes(m.requestContext)
1131 }
Nick Harper7e0442a2016-07-01 17:40:09 -04001132 certificateList := certificate.addU24LengthPrefixed()
1133 for _, cert := range m.certificates {
1134 certEntry := certificateList.addU24LengthPrefixed()
1135 certEntry.addBytes(cert)
Adam Langley95c29f32014-06-20 12:00:00 -07001136 }
1137
Nick Harper7e0442a2016-07-01 17:40:09 -04001138 m.raw = certMsg.finish()
1139 return m.raw
Adam Langley95c29f32014-06-20 12:00:00 -07001140}
1141
1142func (m *certificateMsg) unmarshal(data []byte) bool {
Nick Harperb41d2e42016-07-01 17:50:32 -04001143 if len(data) < 4 {
Adam Langley95c29f32014-06-20 12:00:00 -07001144 return false
1145 }
1146
1147 m.raw = data
Nick Harperb41d2e42016-07-01 17:50:32 -04001148 data = data[4:]
1149
1150 if m.hasRequestContext {
1151 if len(data) == 0 {
1152 return false
1153 }
1154 contextLen := int(data[0])
1155 if len(data) < 1+contextLen {
1156 return false
1157 }
1158 m.requestContext = make([]byte, contextLen)
1159 copy(m.requestContext, data[1:])
1160 data = data[1+contextLen:]
1161 }
1162
1163 if len(data) < 3 {
1164 return false
1165 }
1166 certsLen := int(data[0])<<16 | int(data[1])<<8 | int(data[2])
1167 data = data[3:]
1168 if len(data) != certsLen {
Adam Langley95c29f32014-06-20 12:00:00 -07001169 return false
1170 }
1171
1172 numCerts := 0
Nick Harperb41d2e42016-07-01 17:50:32 -04001173 d := data
Adam Langley95c29f32014-06-20 12:00:00 -07001174 for certsLen > 0 {
1175 if len(d) < 4 {
1176 return false
1177 }
Nick Harperb41d2e42016-07-01 17:50:32 -04001178 certLen := int(d[0])<<16 | int(d[1])<<8 | int(d[2])
1179 if len(d) < 3+certLen {
Adam Langley95c29f32014-06-20 12:00:00 -07001180 return false
1181 }
1182 d = d[3+certLen:]
1183 certsLen -= 3 + certLen
1184 numCerts++
1185 }
1186
1187 m.certificates = make([][]byte, numCerts)
Nick Harperb41d2e42016-07-01 17:50:32 -04001188 d = data
Adam Langley95c29f32014-06-20 12:00:00 -07001189 for i := 0; i < numCerts; i++ {
1190 certLen := uint32(d[0])<<16 | uint32(d[1])<<8 | uint32(d[2])
1191 m.certificates[i] = d[3 : 3+certLen]
1192 d = d[3+certLen:]
1193 }
1194
1195 return true
1196}
1197
1198type serverKeyExchangeMsg struct {
1199 raw []byte
1200 key []byte
1201}
1202
Adam Langley95c29f32014-06-20 12:00:00 -07001203func (m *serverKeyExchangeMsg) marshal() []byte {
1204 if m.raw != nil {
1205 return m.raw
1206 }
1207 length := len(m.key)
1208 x := make([]byte, length+4)
1209 x[0] = typeServerKeyExchange
1210 x[1] = uint8(length >> 16)
1211 x[2] = uint8(length >> 8)
1212 x[3] = uint8(length)
1213 copy(x[4:], m.key)
1214
1215 m.raw = x
1216 return x
1217}
1218
1219func (m *serverKeyExchangeMsg) unmarshal(data []byte) bool {
1220 m.raw = data
1221 if len(data) < 4 {
1222 return false
1223 }
1224 m.key = data[4:]
1225 return true
1226}
1227
1228type certificateStatusMsg struct {
1229 raw []byte
1230 statusType uint8
1231 response []byte
1232}
1233
Adam Langley95c29f32014-06-20 12:00:00 -07001234func (m *certificateStatusMsg) marshal() []byte {
1235 if m.raw != nil {
1236 return m.raw
1237 }
1238
1239 var x []byte
1240 if m.statusType == statusTypeOCSP {
1241 x = make([]byte, 4+4+len(m.response))
1242 x[0] = typeCertificateStatus
1243 l := len(m.response) + 4
1244 x[1] = byte(l >> 16)
1245 x[2] = byte(l >> 8)
1246 x[3] = byte(l)
1247 x[4] = statusTypeOCSP
1248
1249 l -= 4
1250 x[5] = byte(l >> 16)
1251 x[6] = byte(l >> 8)
1252 x[7] = byte(l)
1253 copy(x[8:], m.response)
1254 } else {
1255 x = []byte{typeCertificateStatus, 0, 0, 1, m.statusType}
1256 }
1257
1258 m.raw = x
1259 return x
1260}
1261
1262func (m *certificateStatusMsg) unmarshal(data []byte) bool {
1263 m.raw = data
1264 if len(data) < 5 {
1265 return false
1266 }
1267 m.statusType = data[4]
1268
1269 m.response = nil
1270 if m.statusType == statusTypeOCSP {
1271 if len(data) < 8 {
1272 return false
1273 }
1274 respLen := uint32(data[5])<<16 | uint32(data[6])<<8 | uint32(data[7])
1275 if uint32(len(data)) != 4+4+respLen {
1276 return false
1277 }
1278 m.response = data[8:]
1279 }
1280 return true
1281}
1282
1283type serverHelloDoneMsg struct{}
1284
Adam Langley95c29f32014-06-20 12:00:00 -07001285func (m *serverHelloDoneMsg) marshal() []byte {
1286 x := make([]byte, 4)
1287 x[0] = typeServerHelloDone
1288 return x
1289}
1290
1291func (m *serverHelloDoneMsg) unmarshal(data []byte) bool {
1292 return len(data) == 4
1293}
1294
1295type clientKeyExchangeMsg struct {
1296 raw []byte
1297 ciphertext []byte
1298}
1299
Adam Langley95c29f32014-06-20 12:00:00 -07001300func (m *clientKeyExchangeMsg) marshal() []byte {
1301 if m.raw != nil {
1302 return m.raw
1303 }
1304 length := len(m.ciphertext)
1305 x := make([]byte, length+4)
1306 x[0] = typeClientKeyExchange
1307 x[1] = uint8(length >> 16)
1308 x[2] = uint8(length >> 8)
1309 x[3] = uint8(length)
1310 copy(x[4:], m.ciphertext)
1311
1312 m.raw = x
1313 return x
1314}
1315
1316func (m *clientKeyExchangeMsg) unmarshal(data []byte) bool {
1317 m.raw = data
1318 if len(data) < 4 {
1319 return false
1320 }
1321 l := int(data[1])<<16 | int(data[2])<<8 | int(data[3])
1322 if l != len(data)-4 {
1323 return false
1324 }
1325 m.ciphertext = data[4:]
1326 return true
1327}
1328
1329type finishedMsg struct {
1330 raw []byte
1331 verifyData []byte
1332}
1333
Adam Langley95c29f32014-06-20 12:00:00 -07001334func (m *finishedMsg) marshal() (x []byte) {
1335 if m.raw != nil {
1336 return m.raw
1337 }
1338
1339 x = make([]byte, 4+len(m.verifyData))
1340 x[0] = typeFinished
1341 x[3] = byte(len(m.verifyData))
1342 copy(x[4:], m.verifyData)
1343 m.raw = x
1344 return
1345}
1346
1347func (m *finishedMsg) unmarshal(data []byte) bool {
1348 m.raw = data
1349 if len(data) < 4 {
1350 return false
1351 }
1352 m.verifyData = data[4:]
1353 return true
1354}
1355
1356type nextProtoMsg struct {
1357 raw []byte
1358 proto string
1359}
1360
Adam Langley95c29f32014-06-20 12:00:00 -07001361func (m *nextProtoMsg) marshal() []byte {
1362 if m.raw != nil {
1363 return m.raw
1364 }
1365 l := len(m.proto)
1366 if l > 255 {
1367 l = 255
1368 }
1369
1370 padding := 32 - (l+2)%32
1371 length := l + padding + 2
1372 x := make([]byte, length+4)
1373 x[0] = typeNextProtocol
1374 x[1] = uint8(length >> 16)
1375 x[2] = uint8(length >> 8)
1376 x[3] = uint8(length)
1377
1378 y := x[4:]
1379 y[0] = byte(l)
1380 copy(y[1:], []byte(m.proto[0:l]))
1381 y = y[1+l:]
1382 y[0] = byte(padding)
1383
1384 m.raw = x
1385
1386 return x
1387}
1388
1389func (m *nextProtoMsg) unmarshal(data []byte) bool {
1390 m.raw = data
1391
1392 if len(data) < 5 {
1393 return false
1394 }
1395 data = data[4:]
1396 protoLen := int(data[0])
1397 data = data[1:]
1398 if len(data) < protoLen {
1399 return false
1400 }
1401 m.proto = string(data[0:protoLen])
1402 data = data[protoLen:]
1403
1404 if len(data) < 1 {
1405 return false
1406 }
1407 paddingLen := int(data[0])
1408 data = data[1:]
1409 if len(data) != paddingLen {
1410 return false
1411 }
1412
1413 return true
1414}
1415
1416type certificateRequestMsg struct {
1417 raw []byte
Nick Harper60edffd2016-06-21 15:19:24 -07001418 // hasSignatureAlgorithm indicates whether this message includes a list
Adam Langley95c29f32014-06-20 12:00:00 -07001419 // of signature and hash functions. This change was introduced with TLS
1420 // 1.2.
Nick Harper60edffd2016-06-21 15:19:24 -07001421 hasSignatureAlgorithm bool
Nick Harperb41d2e42016-07-01 17:50:32 -04001422 // hasRequestContext indicates whether this message includes a context
1423 // field instead of certificateTypes. This change was introduced with
1424 // TLS 1.3.
1425 hasRequestContext bool
Adam Langley95c29f32014-06-20 12:00:00 -07001426
1427 certificateTypes []byte
Nick Harperb41d2e42016-07-01 17:50:32 -04001428 requestContext []byte
Nick Harper60edffd2016-06-21 15:19:24 -07001429 signatureAlgorithms []signatureAlgorithm
Adam Langley95c29f32014-06-20 12:00:00 -07001430 certificateAuthorities [][]byte
1431}
1432
Nick Harper7e0442a2016-07-01 17:40:09 -04001433func (m *certificateRequestMsg) marshal() []byte {
Adam Langley95c29f32014-06-20 12:00:00 -07001434 if m.raw != nil {
1435 return m.raw
1436 }
1437
1438 // See http://tools.ietf.org/html/rfc4346#section-7.4.4
Nick Harper7e0442a2016-07-01 17:40:09 -04001439 builder := newByteBuilder()
1440 builder.addU8(typeCertificateRequest)
1441 body := builder.addU24LengthPrefixed()
1442
Nick Harperb41d2e42016-07-01 17:50:32 -04001443 if m.hasRequestContext {
1444 requestContext := body.addU8LengthPrefixed()
1445 requestContext.addBytes(m.requestContext)
1446 } else {
1447 certificateTypes := body.addU8LengthPrefixed()
1448 certificateTypes.addBytes(m.certificateTypes)
1449 }
Adam Langley95c29f32014-06-20 12:00:00 -07001450
Nick Harper60edffd2016-06-21 15:19:24 -07001451 if m.hasSignatureAlgorithm {
Nick Harper7e0442a2016-07-01 17:40:09 -04001452 signatureAlgorithms := body.addU16LengthPrefixed()
Nick Harper60edffd2016-06-21 15:19:24 -07001453 for _, sigAlg := range m.signatureAlgorithms {
Nick Harper7e0442a2016-07-01 17:40:09 -04001454 signatureAlgorithms.addU16(uint16(sigAlg))
Adam Langley95c29f32014-06-20 12:00:00 -07001455 }
1456 }
1457
Nick Harper7e0442a2016-07-01 17:40:09 -04001458 certificateAuthorities := body.addU16LengthPrefixed()
Adam Langley95c29f32014-06-20 12:00:00 -07001459 for _, ca := range m.certificateAuthorities {
Nick Harper7e0442a2016-07-01 17:40:09 -04001460 caEntry := certificateAuthorities.addU16LengthPrefixed()
1461 caEntry.addBytes(ca)
Adam Langley95c29f32014-06-20 12:00:00 -07001462 }
1463
David Benjamin8d343b42016-07-09 14:26:01 -07001464 if m.hasRequestContext {
1465 // Emit no certificate extensions.
1466 body.addU16(0)
1467 }
1468
Nick Harper7e0442a2016-07-01 17:40:09 -04001469 m.raw = builder.finish()
1470 return m.raw
Adam Langley95c29f32014-06-20 12:00:00 -07001471}
1472
1473func (m *certificateRequestMsg) unmarshal(data []byte) bool {
1474 m.raw = data
1475
1476 if len(data) < 5 {
1477 return false
1478 }
Nick Harperb41d2e42016-07-01 17:50:32 -04001479 data = data[4:]
Adam Langley95c29f32014-06-20 12:00:00 -07001480
Nick Harperb41d2e42016-07-01 17:50:32 -04001481 if m.hasRequestContext {
1482 contextLen := int(data[0])
1483 if len(data) < 1+contextLen {
1484 return false
1485 }
1486 m.requestContext = make([]byte, contextLen)
1487 copy(m.requestContext, data[1:])
1488 data = data[1+contextLen:]
1489 } else {
1490 numCertTypes := int(data[0])
1491 if len(data) < 1+numCertTypes {
1492 return false
1493 }
1494 m.certificateTypes = make([]byte, numCertTypes)
1495 copy(m.certificateTypes, data[1:])
1496 data = data[1+numCertTypes:]
Adam Langley95c29f32014-06-20 12:00:00 -07001497 }
1498
Nick Harper60edffd2016-06-21 15:19:24 -07001499 if m.hasSignatureAlgorithm {
Adam Langley95c29f32014-06-20 12:00:00 -07001500 if len(data) < 2 {
1501 return false
1502 }
Nick Harper60edffd2016-06-21 15:19:24 -07001503 sigAlgsLen := uint16(data[0])<<8 | uint16(data[1])
Adam Langley95c29f32014-06-20 12:00:00 -07001504 data = data[2:]
Nick Harper60edffd2016-06-21 15:19:24 -07001505 if sigAlgsLen&1 != 0 {
Adam Langley95c29f32014-06-20 12:00:00 -07001506 return false
1507 }
Nick Harper60edffd2016-06-21 15:19:24 -07001508 if len(data) < int(sigAlgsLen) {
Adam Langley95c29f32014-06-20 12:00:00 -07001509 return false
1510 }
Nick Harper60edffd2016-06-21 15:19:24 -07001511 numSigAlgs := sigAlgsLen / 2
1512 m.signatureAlgorithms = make([]signatureAlgorithm, numSigAlgs)
1513 for i := range m.signatureAlgorithms {
1514 m.signatureAlgorithms[i] = signatureAlgorithm(data[0])<<8 | signatureAlgorithm(data[1])
Adam Langley95c29f32014-06-20 12:00:00 -07001515 data = data[2:]
1516 }
1517 }
1518
1519 if len(data) < 2 {
1520 return false
1521 }
1522 casLength := uint16(data[0])<<8 | uint16(data[1])
1523 data = data[2:]
1524 if len(data) < int(casLength) {
1525 return false
1526 }
1527 cas := make([]byte, casLength)
1528 copy(cas, data)
1529 data = data[casLength:]
1530
1531 m.certificateAuthorities = nil
1532 for len(cas) > 0 {
1533 if len(cas) < 2 {
1534 return false
1535 }
1536 caLen := uint16(cas[0])<<8 | uint16(cas[1])
1537 cas = cas[2:]
1538
1539 if len(cas) < int(caLen) {
1540 return false
1541 }
1542
1543 m.certificateAuthorities = append(m.certificateAuthorities, cas[:caLen])
1544 cas = cas[caLen:]
1545 }
David Benjamin8d343b42016-07-09 14:26:01 -07001546
1547 if m.hasRequestContext {
1548 // Ignore certificate extensions.
1549 if len(data) < 2 {
1550 return false
1551 }
1552 extsLength := int(data[0])<<8 | int(data[1])
1553 if len(data) < 2+extsLength {
1554 return false
1555 }
1556 data = data[2+extsLength:]
1557 }
1558
Adam Langley95c29f32014-06-20 12:00:00 -07001559 if len(data) > 0 {
1560 return false
1561 }
1562
1563 return true
1564}
1565
1566type certificateVerifyMsg struct {
Nick Harper60edffd2016-06-21 15:19:24 -07001567 raw []byte
1568 hasSignatureAlgorithm bool
1569 signatureAlgorithm signatureAlgorithm
1570 signature []byte
Adam Langley95c29f32014-06-20 12:00:00 -07001571}
1572
Adam Langley95c29f32014-06-20 12:00:00 -07001573func (m *certificateVerifyMsg) marshal() (x []byte) {
1574 if m.raw != nil {
1575 return m.raw
1576 }
1577
1578 // See http://tools.ietf.org/html/rfc4346#section-7.4.8
1579 siglength := len(m.signature)
1580 length := 2 + siglength
Nick Harper60edffd2016-06-21 15:19:24 -07001581 if m.hasSignatureAlgorithm {
Adam Langley95c29f32014-06-20 12:00:00 -07001582 length += 2
1583 }
1584 x = make([]byte, 4+length)
1585 x[0] = typeCertificateVerify
1586 x[1] = uint8(length >> 16)
1587 x[2] = uint8(length >> 8)
1588 x[3] = uint8(length)
1589 y := x[4:]
Nick Harper60edffd2016-06-21 15:19:24 -07001590 if m.hasSignatureAlgorithm {
1591 y[0] = byte(m.signatureAlgorithm >> 8)
1592 y[1] = byte(m.signatureAlgorithm)
Adam Langley95c29f32014-06-20 12:00:00 -07001593 y = y[2:]
1594 }
1595 y[0] = uint8(siglength >> 8)
1596 y[1] = uint8(siglength)
1597 copy(y[2:], m.signature)
1598
1599 m.raw = x
1600
1601 return
1602}
1603
1604func (m *certificateVerifyMsg) unmarshal(data []byte) bool {
1605 m.raw = data
1606
1607 if len(data) < 6 {
1608 return false
1609 }
1610
1611 length := uint32(data[1])<<16 | uint32(data[2])<<8 | uint32(data[3])
1612 if uint32(len(data))-4 != length {
1613 return false
1614 }
1615
1616 data = data[4:]
Nick Harper60edffd2016-06-21 15:19:24 -07001617 if m.hasSignatureAlgorithm {
1618 m.signatureAlgorithm = signatureAlgorithm(data[0])<<8 | signatureAlgorithm(data[1])
Adam Langley95c29f32014-06-20 12:00:00 -07001619 data = data[2:]
1620 }
1621
1622 if len(data) < 2 {
1623 return false
1624 }
1625 siglength := int(data[0])<<8 + int(data[1])
1626 data = data[2:]
1627 if len(data) != siglength {
1628 return false
1629 }
1630
1631 m.signature = data
1632
1633 return true
1634}
1635
1636type newSessionTicketMsg struct {
1637 raw []byte
1638 ticket []byte
1639}
1640
Adam Langley95c29f32014-06-20 12:00:00 -07001641func (m *newSessionTicketMsg) marshal() (x []byte) {
1642 if m.raw != nil {
1643 return m.raw
1644 }
1645
1646 // See http://tools.ietf.org/html/rfc5077#section-3.3
1647 ticketLen := len(m.ticket)
1648 length := 2 + 4 + ticketLen
1649 x = make([]byte, 4+length)
1650 x[0] = typeNewSessionTicket
1651 x[1] = uint8(length >> 16)
1652 x[2] = uint8(length >> 8)
1653 x[3] = uint8(length)
1654 x[8] = uint8(ticketLen >> 8)
1655 x[9] = uint8(ticketLen)
1656 copy(x[10:], m.ticket)
1657
1658 m.raw = x
1659
1660 return
1661}
1662
1663func (m *newSessionTicketMsg) unmarshal(data []byte) bool {
1664 m.raw = data
1665
1666 if len(data) < 10 {
1667 return false
1668 }
1669
1670 length := uint32(data[1])<<16 | uint32(data[2])<<8 | uint32(data[3])
1671 if uint32(len(data))-4 != length {
1672 return false
1673 }
1674
1675 ticketLen := int(data[8])<<8 + int(data[9])
1676 if len(data)-10 != ticketLen {
1677 return false
1678 }
1679
1680 m.ticket = data[10:]
1681
1682 return true
1683}
1684
David Benjamind86c7672014-08-02 04:07:12 -04001685type v2ClientHelloMsg struct {
1686 raw []byte
1687 vers uint16
1688 cipherSuites []uint16
1689 sessionId []byte
1690 challenge []byte
1691}
1692
David Benjamind86c7672014-08-02 04:07:12 -04001693func (m *v2ClientHelloMsg) marshal() []byte {
1694 if m.raw != nil {
1695 return m.raw
1696 }
1697
1698 length := 1 + 2 + 2 + 2 + 2 + len(m.cipherSuites)*3 + len(m.sessionId) + len(m.challenge)
1699
1700 x := make([]byte, length)
1701 x[0] = 1
1702 x[1] = uint8(m.vers >> 8)
1703 x[2] = uint8(m.vers)
1704 x[3] = uint8((len(m.cipherSuites) * 3) >> 8)
1705 x[4] = uint8(len(m.cipherSuites) * 3)
1706 x[5] = uint8(len(m.sessionId) >> 8)
1707 x[6] = uint8(len(m.sessionId))
1708 x[7] = uint8(len(m.challenge) >> 8)
1709 x[8] = uint8(len(m.challenge))
1710 y := x[9:]
1711 for i, spec := range m.cipherSuites {
1712 y[i*3] = 0
1713 y[i*3+1] = uint8(spec >> 8)
1714 y[i*3+2] = uint8(spec)
1715 }
1716 y = y[len(m.cipherSuites)*3:]
1717 copy(y, m.sessionId)
1718 y = y[len(m.sessionId):]
1719 copy(y, m.challenge)
1720
1721 m.raw = x
1722
1723 return x
1724}
1725
David Benjamin83c0bc92014-08-04 01:23:53 -04001726type helloVerifyRequestMsg struct {
1727 raw []byte
1728 vers uint16
1729 cookie []byte
1730}
1731
David Benjamin83c0bc92014-08-04 01:23:53 -04001732func (m *helloVerifyRequestMsg) marshal() []byte {
1733 if m.raw != nil {
1734 return m.raw
1735 }
1736
1737 length := 2 + 1 + len(m.cookie)
1738
1739 x := make([]byte, 4+length)
1740 x[0] = typeHelloVerifyRequest
1741 x[1] = uint8(length >> 16)
1742 x[2] = uint8(length >> 8)
1743 x[3] = uint8(length)
1744 vers := versionToWire(m.vers, true)
1745 x[4] = uint8(vers >> 8)
1746 x[5] = uint8(vers)
1747 x[6] = uint8(len(m.cookie))
1748 copy(x[7:7+len(m.cookie)], m.cookie)
1749
1750 return x
1751}
1752
1753func (m *helloVerifyRequestMsg) unmarshal(data []byte) bool {
1754 if len(data) < 4+2+1 {
1755 return false
1756 }
1757 m.raw = data
1758 m.vers = wireToVersion(uint16(data[4])<<8|uint16(data[5]), true)
1759 cookieLen := int(data[6])
1760 if cookieLen > 32 || len(data) != 7+cookieLen {
1761 return false
1762 }
1763 m.cookie = data[7 : 7+cookieLen]
1764
1765 return true
1766}
1767
David Benjamin24599a82016-06-30 18:56:53 -04001768type channelIDMsg struct {
David Benjamind30a9902014-08-24 01:44:23 -04001769 raw []byte
1770 channelID []byte
1771}
1772
David Benjamin24599a82016-06-30 18:56:53 -04001773func (m *channelIDMsg) marshal() []byte {
David Benjamind30a9902014-08-24 01:44:23 -04001774 if m.raw != nil {
1775 return m.raw
1776 }
1777
1778 length := 2 + 2 + len(m.channelID)
1779
1780 x := make([]byte, 4+length)
David Benjamin24599a82016-06-30 18:56:53 -04001781 x[0] = typeChannelID
David Benjamind30a9902014-08-24 01:44:23 -04001782 x[1] = uint8(length >> 16)
1783 x[2] = uint8(length >> 8)
1784 x[3] = uint8(length)
1785 x[4] = uint8(extensionChannelID >> 8)
1786 x[5] = uint8(extensionChannelID & 0xff)
1787 x[6] = uint8(len(m.channelID) >> 8)
1788 x[7] = uint8(len(m.channelID) & 0xff)
1789 copy(x[8:], m.channelID)
1790
1791 return x
1792}
1793
David Benjamin24599a82016-06-30 18:56:53 -04001794func (m *channelIDMsg) unmarshal(data []byte) bool {
David Benjamind30a9902014-08-24 01:44:23 -04001795 if len(data) != 4+2+2+128 {
1796 return false
1797 }
1798 m.raw = data
1799 if (uint16(data[4])<<8)|uint16(data[5]) != extensionChannelID {
1800 return false
1801 }
1802 if int(data[6])<<8|int(data[7]) != 128 {
1803 return false
1804 }
1805 m.channelID = data[4+2+2:]
1806
1807 return true
1808}
1809
Adam Langley2ae77d22014-10-28 17:29:33 -07001810type helloRequestMsg struct {
1811}
1812
1813func (*helloRequestMsg) marshal() []byte {
1814 return []byte{typeHelloRequest, 0, 0, 0}
1815}
1816
1817func (*helloRequestMsg) unmarshal(data []byte) bool {
1818 return len(data) == 4
1819}
1820
Adam Langley95c29f32014-06-20 12:00:00 -07001821func eqUint16s(x, y []uint16) bool {
1822 if len(x) != len(y) {
1823 return false
1824 }
1825 for i, v := range x {
1826 if y[i] != v {
1827 return false
1828 }
1829 }
1830 return true
1831}
1832
1833func eqCurveIDs(x, y []CurveID) bool {
1834 if len(x) != len(y) {
1835 return false
1836 }
1837 for i, v := range x {
1838 if y[i] != v {
1839 return false
1840 }
1841 }
1842 return true
1843}
1844
1845func eqStrings(x, y []string) bool {
1846 if len(x) != len(y) {
1847 return false
1848 }
1849 for i, v := range x {
1850 if y[i] != v {
1851 return false
1852 }
1853 }
1854 return true
1855}
1856
1857func eqByteSlices(x, y [][]byte) bool {
1858 if len(x) != len(y) {
1859 return false
1860 }
1861 for i, v := range x {
1862 if !bytes.Equal(v, y[i]) {
1863 return false
1864 }
1865 }
1866 return true
1867}
1868
Nick Harper60edffd2016-06-21 15:19:24 -07001869func eqSignatureAlgorithms(x, y []signatureAlgorithm) bool {
Adam Langley95c29f32014-06-20 12:00:00 -07001870 if len(x) != len(y) {
1871 return false
1872 }
1873 for i, v := range x {
1874 v2 := y[i]
Nick Harper60edffd2016-06-21 15:19:24 -07001875 if v != v2 {
Adam Langley95c29f32014-06-20 12:00:00 -07001876 return false
1877 }
1878 }
1879 return true
1880}
Nick Harperf8b0e702016-06-30 19:59:01 -04001881
1882func eqKeyShareEntryLists(x, y []keyShareEntry) bool {
1883 if len(x) != len(y) {
1884 return false
1885 }
1886 for i, v := range x {
1887 if y[i].group != v.group || !bytes.Equal(y[i].keyExchange, v.keyExchange) {
1888 return false
1889 }
1890 }
1891 return true
1892
1893}