blob: d349ae727062087b7f64d7ff0bb9f0df73da113c [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 {
741 m.extensions.marshal(extensions)
742 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 }
840 } else if !m.extensions.unmarshal(data) {
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()
861 m.extensions.marshal(extensions)
862
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 }
884 return m.extensions.unmarshal(data)
885}
886
Nick Harperb3d51be2016-07-01 11:43:18 -0400887type serverExtensions struct {
888 nextProtoNeg bool
889 nextProtos []string
890 ocspStapling bool
891 ticketSupported bool
892 secureRenegotiation []byte
893 alpnProtocol string
894 alpnProtocolEmpty bool
895 duplicateExtension bool
896 channelIDRequested bool
897 extendedMasterSecret bool
898 srtpProtectionProfile uint16
899 srtpMasterKeyIdentifier string
900 sctList []byte
901 customExtension string
902 npnLast bool
903}
904
905func (m *serverExtensions) marshal(extensions *byteBuilder) {
David Benjamin35a7a442014-07-05 00:23:20 -0400906 if m.duplicateExtension {
907 // Add a duplicate bogus extension at the beginning and end.
Nick Harper5212ef82016-06-30 19:26:07 -0400908 extensions.addU16(0xffff)
909 extensions.addU16(0) // length = 0 for empty extension
David Benjamin35a7a442014-07-05 00:23:20 -0400910 }
David Benjamin76c2efc2015-08-31 14:24:29 -0400911 if m.nextProtoNeg && !m.npnLast {
Nick Harper5212ef82016-06-30 19:26:07 -0400912 extensions.addU16(extensionNextProtoNeg)
913 extension := extensions.addU16LengthPrefixed()
Adam Langley95c29f32014-06-20 12:00:00 -0700914
915 for _, v := range m.nextProtos {
Nick Harper5212ef82016-06-30 19:26:07 -0400916 if len(v) > 255 {
917 v = v[:255]
Adam Langley95c29f32014-06-20 12:00:00 -0700918 }
Nick Harper5212ef82016-06-30 19:26:07 -0400919 npn := extension.addU8LengthPrefixed()
920 npn.addBytes([]byte(v))
Adam Langley95c29f32014-06-20 12:00:00 -0700921 }
922 }
923 if m.ocspStapling {
Nick Harper5212ef82016-06-30 19:26:07 -0400924 extensions.addU16(extensionStatusRequest)
925 extensions.addU16(0)
Adam Langley95c29f32014-06-20 12:00:00 -0700926 }
927 if m.ticketSupported {
Nick Harper5212ef82016-06-30 19:26:07 -0400928 extensions.addU16(extensionSessionTicket)
929 extensions.addU16(0)
Adam Langley95c29f32014-06-20 12:00:00 -0700930 }
Adam Langley2ae77d22014-10-28 17:29:33 -0700931 if m.secureRenegotiation != nil {
Nick Harper5212ef82016-06-30 19:26:07 -0400932 extensions.addU16(extensionRenegotiationInfo)
933 extension := extensions.addU16LengthPrefixed()
934 secureRenego := extension.addU8LengthPrefixed()
935 secureRenego.addBytes(m.secureRenegotiation)
Adam Langley95c29f32014-06-20 12:00:00 -0700936 }
Nick Harper5212ef82016-06-30 19:26:07 -0400937 if len(m.alpnProtocol) > 0 || m.alpnProtocolEmpty {
938 extensions.addU16(extensionALPN)
939 extension := extensions.addU16LengthPrefixed()
940
941 protocolNameList := extension.addU16LengthPrefixed()
942 protocolName := protocolNameList.addU8LengthPrefixed()
943 protocolName.addBytes([]byte(m.alpnProtocol))
David Benjaminfa055a22014-09-15 16:51:51 -0400944 }
David Benjamind30a9902014-08-24 01:44:23 -0400945 if m.channelIDRequested {
Nick Harper5212ef82016-06-30 19:26:07 -0400946 extensions.addU16(extensionChannelID)
947 extensions.addU16(0)
David Benjamind30a9902014-08-24 01:44:23 -0400948 }
David Benjamin35a7a442014-07-05 00:23:20 -0400949 if m.duplicateExtension {
950 // Add a duplicate bogus extension at the beginning and end.
Nick Harper5212ef82016-06-30 19:26:07 -0400951 extensions.addU16(0xffff)
952 extensions.addU16(0)
David Benjamin35a7a442014-07-05 00:23:20 -0400953 }
Adam Langley75712922014-10-10 16:23:43 -0700954 if m.extendedMasterSecret {
Nick Harper5212ef82016-06-30 19:26:07 -0400955 extensions.addU16(extensionExtendedMasterSecret)
956 extensions.addU16(0)
Adam Langley75712922014-10-10 16:23:43 -0700957 }
David Benjaminca6c8262014-11-15 19:06:08 -0500958 if m.srtpProtectionProfile != 0 {
Nick Harper5212ef82016-06-30 19:26:07 -0400959 extensions.addU16(extensionUseSRTP)
960 extension := extensions.addU16LengthPrefixed()
961
962 srtpProtectionProfiles := extension.addU16LengthPrefixed()
963 srtpProtectionProfiles.addU8(byte(m.srtpProtectionProfile >> 8))
964 srtpProtectionProfiles.addU8(byte(m.srtpProtectionProfile))
965 srtpMki := extension.addU8LengthPrefixed()
966 srtpMki.addBytes([]byte(m.srtpMasterKeyIdentifier))
David Benjaminca6c8262014-11-15 19:06:08 -0500967 }
David Benjamin61f95272014-11-25 01:55:35 -0500968 if m.sctList != nil {
Nick Harper5212ef82016-06-30 19:26:07 -0400969 extensions.addU16(extensionSignedCertificateTimestamp)
970 extension := extensions.addU16LengthPrefixed()
971 extension.addBytes(m.sctList)
David Benjamin61f95272014-11-25 01:55:35 -0500972 }
Adam Langley09505632015-07-30 18:10:13 -0700973 if l := len(m.customExtension); l > 0 {
Nick Harper5212ef82016-06-30 19:26:07 -0400974 extensions.addU16(extensionCustom)
975 customExt := extensions.addU16LengthPrefixed()
976 customExt.addBytes([]byte(m.customExtension))
Adam Langley09505632015-07-30 18:10:13 -0700977 }
David Benjamin76c2efc2015-08-31 14:24:29 -0400978 if m.nextProtoNeg && m.npnLast {
Nick Harper5212ef82016-06-30 19:26:07 -0400979 extensions.addU16(extensionNextProtoNeg)
980 extension := extensions.addU16LengthPrefixed()
David Benjamin76c2efc2015-08-31 14:24:29 -0400981
982 for _, v := range m.nextProtos {
Nick Harper5212ef82016-06-30 19:26:07 -0400983 if len(v) > 255 {
984 v = v[0:255]
David Benjamin76c2efc2015-08-31 14:24:29 -0400985 }
Nick Harper5212ef82016-06-30 19:26:07 -0400986 npn := extension.addU8LengthPrefixed()
987 npn.addBytes([]byte(v))
David Benjamin76c2efc2015-08-31 14:24:29 -0400988 }
989 }
Adam Langley95c29f32014-06-20 12:00:00 -0700990}
991
Nick Harperb3d51be2016-07-01 11:43:18 -0400992func (m *serverExtensions) unmarshal(data []byte) bool {
993 // Reset all fields.
994 *m = serverExtensions{}
Adam Langley95c29f32014-06-20 12:00:00 -0700995
996 for len(data) != 0 {
997 if len(data) < 4 {
998 return false
999 }
1000 extension := uint16(data[0])<<8 | uint16(data[1])
1001 length := int(data[2])<<8 | int(data[3])
1002 data = data[4:]
1003 if len(data) < length {
1004 return false
1005 }
1006
1007 switch extension {
1008 case extensionNextProtoNeg:
1009 m.nextProtoNeg = true
1010 d := data[:length]
1011 for len(d) > 0 {
1012 l := int(d[0])
1013 d = d[1:]
1014 if l == 0 || l > len(d) {
1015 return false
1016 }
1017 m.nextProtos = append(m.nextProtos, string(d[:l]))
1018 d = d[l:]
1019 }
1020 case extensionStatusRequest:
1021 if length > 0 {
1022 return false
1023 }
1024 m.ocspStapling = true
1025 case extensionSessionTicket:
1026 if length > 0 {
1027 return false
1028 }
1029 m.ticketSupported = true
1030 case extensionRenegotiationInfo:
Adam Langley2ae77d22014-10-28 17:29:33 -07001031 if length < 1 || length != int(data[0])+1 {
Adam Langley95c29f32014-06-20 12:00:00 -07001032 return false
1033 }
Adam Langley2ae77d22014-10-28 17:29:33 -07001034 m.secureRenegotiation = data[1:length]
David Benjaminfa055a22014-09-15 16:51:51 -04001035 case extensionALPN:
1036 d := data[:length]
1037 if len(d) < 3 {
1038 return false
1039 }
1040 l := int(d[0])<<8 | int(d[1])
1041 if l != len(d)-2 {
1042 return false
1043 }
1044 d = d[2:]
1045 l = int(d[0])
1046 if l != len(d)-1 {
1047 return false
1048 }
1049 d = d[1:]
1050 m.alpnProtocol = string(d)
Adam Langleyefb0e162015-07-09 11:35:04 -07001051 m.alpnProtocolEmpty = len(d) == 0
David Benjamind30a9902014-08-24 01:44:23 -04001052 case extensionChannelID:
1053 if length > 0 {
1054 return false
1055 }
1056 m.channelIDRequested = true
Adam Langley75712922014-10-10 16:23:43 -07001057 case extensionExtendedMasterSecret:
1058 if length != 0 {
1059 return false
1060 }
1061 m.extendedMasterSecret = true
David Benjaminca6c8262014-11-15 19:06:08 -05001062 case extensionUseSRTP:
1063 if length < 2+2+1 {
1064 return false
1065 }
1066 if data[0] != 0 || data[1] != 2 {
1067 return false
1068 }
1069 m.srtpProtectionProfile = uint16(data[2])<<8 | uint16(data[3])
1070 d := data[4:length]
1071 l := int(d[0])
1072 if l != len(d)-1 {
1073 return false
1074 }
1075 m.srtpMasterKeyIdentifier = string(d[1:])
David Benjamin61f95272014-11-25 01:55:35 -05001076 case extensionSignedCertificateTimestamp:
Paul Lietar4fac72e2015-09-09 13:44:55 +01001077 m.sctList = data[:length]
Adam Langley09505632015-07-30 18:10:13 -07001078 case extensionCustom:
1079 m.customExtension = string(data[:length])
Adam Langley95c29f32014-06-20 12:00:00 -07001080 }
1081 data = data[length:]
1082 }
1083
1084 return true
1085}
1086
1087type certificateMsg struct {
Nick Harperb41d2e42016-07-01 17:50:32 -04001088 raw []byte
1089 hasRequestContext bool
1090 requestContext []byte
1091 certificates [][]byte
Adam Langley95c29f32014-06-20 12:00:00 -07001092}
1093
Adam Langley95c29f32014-06-20 12:00:00 -07001094func (m *certificateMsg) marshal() (x []byte) {
1095 if m.raw != nil {
1096 return m.raw
1097 }
1098
Nick Harper7e0442a2016-07-01 17:40:09 -04001099 certMsg := newByteBuilder()
1100 certMsg.addU8(typeCertificate)
1101 certificate := certMsg.addU24LengthPrefixed()
Nick Harperb41d2e42016-07-01 17:50:32 -04001102 if m.hasRequestContext {
1103 context := certificate.addU8LengthPrefixed()
1104 context.addBytes(m.requestContext)
1105 }
Nick Harper7e0442a2016-07-01 17:40:09 -04001106 certificateList := certificate.addU24LengthPrefixed()
1107 for _, cert := range m.certificates {
1108 certEntry := certificateList.addU24LengthPrefixed()
1109 certEntry.addBytes(cert)
Adam Langley95c29f32014-06-20 12:00:00 -07001110 }
1111
Nick Harper7e0442a2016-07-01 17:40:09 -04001112 m.raw = certMsg.finish()
1113 return m.raw
Adam Langley95c29f32014-06-20 12:00:00 -07001114}
1115
1116func (m *certificateMsg) unmarshal(data []byte) bool {
Nick Harperb41d2e42016-07-01 17:50:32 -04001117 if len(data) < 4 {
Adam Langley95c29f32014-06-20 12:00:00 -07001118 return false
1119 }
1120
1121 m.raw = data
Nick Harperb41d2e42016-07-01 17:50:32 -04001122 data = data[4:]
1123
1124 if m.hasRequestContext {
1125 if len(data) == 0 {
1126 return false
1127 }
1128 contextLen := int(data[0])
1129 if len(data) < 1+contextLen {
1130 return false
1131 }
1132 m.requestContext = make([]byte, contextLen)
1133 copy(m.requestContext, data[1:])
1134 data = data[1+contextLen:]
1135 }
1136
1137 if len(data) < 3 {
1138 return false
1139 }
1140 certsLen := int(data[0])<<16 | int(data[1])<<8 | int(data[2])
1141 data = data[3:]
1142 if len(data) != certsLen {
Adam Langley95c29f32014-06-20 12:00:00 -07001143 return false
1144 }
1145
1146 numCerts := 0
Nick Harperb41d2e42016-07-01 17:50:32 -04001147 d := data
Adam Langley95c29f32014-06-20 12:00:00 -07001148 for certsLen > 0 {
1149 if len(d) < 4 {
1150 return false
1151 }
Nick Harperb41d2e42016-07-01 17:50:32 -04001152 certLen := int(d[0])<<16 | int(d[1])<<8 | int(d[2])
1153 if len(d) < 3+certLen {
Adam Langley95c29f32014-06-20 12:00:00 -07001154 return false
1155 }
1156 d = d[3+certLen:]
1157 certsLen -= 3 + certLen
1158 numCerts++
1159 }
1160
1161 m.certificates = make([][]byte, numCerts)
Nick Harperb41d2e42016-07-01 17:50:32 -04001162 d = data
Adam Langley95c29f32014-06-20 12:00:00 -07001163 for i := 0; i < numCerts; i++ {
1164 certLen := uint32(d[0])<<16 | uint32(d[1])<<8 | uint32(d[2])
1165 m.certificates[i] = d[3 : 3+certLen]
1166 d = d[3+certLen:]
1167 }
1168
1169 return true
1170}
1171
1172type serverKeyExchangeMsg struct {
1173 raw []byte
1174 key []byte
1175}
1176
Adam Langley95c29f32014-06-20 12:00:00 -07001177func (m *serverKeyExchangeMsg) marshal() []byte {
1178 if m.raw != nil {
1179 return m.raw
1180 }
1181 length := len(m.key)
1182 x := make([]byte, length+4)
1183 x[0] = typeServerKeyExchange
1184 x[1] = uint8(length >> 16)
1185 x[2] = uint8(length >> 8)
1186 x[3] = uint8(length)
1187 copy(x[4:], m.key)
1188
1189 m.raw = x
1190 return x
1191}
1192
1193func (m *serverKeyExchangeMsg) unmarshal(data []byte) bool {
1194 m.raw = data
1195 if len(data) < 4 {
1196 return false
1197 }
1198 m.key = data[4:]
1199 return true
1200}
1201
1202type certificateStatusMsg struct {
1203 raw []byte
1204 statusType uint8
1205 response []byte
1206}
1207
Adam Langley95c29f32014-06-20 12:00:00 -07001208func (m *certificateStatusMsg) marshal() []byte {
1209 if m.raw != nil {
1210 return m.raw
1211 }
1212
1213 var x []byte
1214 if m.statusType == statusTypeOCSP {
1215 x = make([]byte, 4+4+len(m.response))
1216 x[0] = typeCertificateStatus
1217 l := len(m.response) + 4
1218 x[1] = byte(l >> 16)
1219 x[2] = byte(l >> 8)
1220 x[3] = byte(l)
1221 x[4] = statusTypeOCSP
1222
1223 l -= 4
1224 x[5] = byte(l >> 16)
1225 x[6] = byte(l >> 8)
1226 x[7] = byte(l)
1227 copy(x[8:], m.response)
1228 } else {
1229 x = []byte{typeCertificateStatus, 0, 0, 1, m.statusType}
1230 }
1231
1232 m.raw = x
1233 return x
1234}
1235
1236func (m *certificateStatusMsg) unmarshal(data []byte) bool {
1237 m.raw = data
1238 if len(data) < 5 {
1239 return false
1240 }
1241 m.statusType = data[4]
1242
1243 m.response = nil
1244 if m.statusType == statusTypeOCSP {
1245 if len(data) < 8 {
1246 return false
1247 }
1248 respLen := uint32(data[5])<<16 | uint32(data[6])<<8 | uint32(data[7])
1249 if uint32(len(data)) != 4+4+respLen {
1250 return false
1251 }
1252 m.response = data[8:]
1253 }
1254 return true
1255}
1256
1257type serverHelloDoneMsg struct{}
1258
Adam Langley95c29f32014-06-20 12:00:00 -07001259func (m *serverHelloDoneMsg) marshal() []byte {
1260 x := make([]byte, 4)
1261 x[0] = typeServerHelloDone
1262 return x
1263}
1264
1265func (m *serverHelloDoneMsg) unmarshal(data []byte) bool {
1266 return len(data) == 4
1267}
1268
1269type clientKeyExchangeMsg struct {
1270 raw []byte
1271 ciphertext []byte
1272}
1273
Adam Langley95c29f32014-06-20 12:00:00 -07001274func (m *clientKeyExchangeMsg) marshal() []byte {
1275 if m.raw != nil {
1276 return m.raw
1277 }
1278 length := len(m.ciphertext)
1279 x := make([]byte, length+4)
1280 x[0] = typeClientKeyExchange
1281 x[1] = uint8(length >> 16)
1282 x[2] = uint8(length >> 8)
1283 x[3] = uint8(length)
1284 copy(x[4:], m.ciphertext)
1285
1286 m.raw = x
1287 return x
1288}
1289
1290func (m *clientKeyExchangeMsg) unmarshal(data []byte) bool {
1291 m.raw = data
1292 if len(data) < 4 {
1293 return false
1294 }
1295 l := int(data[1])<<16 | int(data[2])<<8 | int(data[3])
1296 if l != len(data)-4 {
1297 return false
1298 }
1299 m.ciphertext = data[4:]
1300 return true
1301}
1302
1303type finishedMsg struct {
1304 raw []byte
1305 verifyData []byte
1306}
1307
Adam Langley95c29f32014-06-20 12:00:00 -07001308func (m *finishedMsg) marshal() (x []byte) {
1309 if m.raw != nil {
1310 return m.raw
1311 }
1312
1313 x = make([]byte, 4+len(m.verifyData))
1314 x[0] = typeFinished
1315 x[3] = byte(len(m.verifyData))
1316 copy(x[4:], m.verifyData)
1317 m.raw = x
1318 return
1319}
1320
1321func (m *finishedMsg) unmarshal(data []byte) bool {
1322 m.raw = data
1323 if len(data) < 4 {
1324 return false
1325 }
1326 m.verifyData = data[4:]
1327 return true
1328}
1329
1330type nextProtoMsg struct {
1331 raw []byte
1332 proto string
1333}
1334
Adam Langley95c29f32014-06-20 12:00:00 -07001335func (m *nextProtoMsg) marshal() []byte {
1336 if m.raw != nil {
1337 return m.raw
1338 }
1339 l := len(m.proto)
1340 if l > 255 {
1341 l = 255
1342 }
1343
1344 padding := 32 - (l+2)%32
1345 length := l + padding + 2
1346 x := make([]byte, length+4)
1347 x[0] = typeNextProtocol
1348 x[1] = uint8(length >> 16)
1349 x[2] = uint8(length >> 8)
1350 x[3] = uint8(length)
1351
1352 y := x[4:]
1353 y[0] = byte(l)
1354 copy(y[1:], []byte(m.proto[0:l]))
1355 y = y[1+l:]
1356 y[0] = byte(padding)
1357
1358 m.raw = x
1359
1360 return x
1361}
1362
1363func (m *nextProtoMsg) unmarshal(data []byte) bool {
1364 m.raw = data
1365
1366 if len(data) < 5 {
1367 return false
1368 }
1369 data = data[4:]
1370 protoLen := int(data[0])
1371 data = data[1:]
1372 if len(data) < protoLen {
1373 return false
1374 }
1375 m.proto = string(data[0:protoLen])
1376 data = data[protoLen:]
1377
1378 if len(data) < 1 {
1379 return false
1380 }
1381 paddingLen := int(data[0])
1382 data = data[1:]
1383 if len(data) != paddingLen {
1384 return false
1385 }
1386
1387 return true
1388}
1389
1390type certificateRequestMsg struct {
1391 raw []byte
Nick Harper60edffd2016-06-21 15:19:24 -07001392 // hasSignatureAlgorithm indicates whether this message includes a list
Adam Langley95c29f32014-06-20 12:00:00 -07001393 // of signature and hash functions. This change was introduced with TLS
1394 // 1.2.
Nick Harper60edffd2016-06-21 15:19:24 -07001395 hasSignatureAlgorithm bool
Nick Harperb41d2e42016-07-01 17:50:32 -04001396 // hasRequestContext indicates whether this message includes a context
1397 // field instead of certificateTypes. This change was introduced with
1398 // TLS 1.3.
1399 hasRequestContext bool
Adam Langley95c29f32014-06-20 12:00:00 -07001400
1401 certificateTypes []byte
Nick Harperb41d2e42016-07-01 17:50:32 -04001402 requestContext []byte
Nick Harper60edffd2016-06-21 15:19:24 -07001403 signatureAlgorithms []signatureAlgorithm
Adam Langley95c29f32014-06-20 12:00:00 -07001404 certificateAuthorities [][]byte
1405}
1406
Nick Harper7e0442a2016-07-01 17:40:09 -04001407func (m *certificateRequestMsg) marshal() []byte {
Adam Langley95c29f32014-06-20 12:00:00 -07001408 if m.raw != nil {
1409 return m.raw
1410 }
1411
1412 // See http://tools.ietf.org/html/rfc4346#section-7.4.4
Nick Harper7e0442a2016-07-01 17:40:09 -04001413 builder := newByteBuilder()
1414 builder.addU8(typeCertificateRequest)
1415 body := builder.addU24LengthPrefixed()
1416
Nick Harperb41d2e42016-07-01 17:50:32 -04001417 if m.hasRequestContext {
1418 requestContext := body.addU8LengthPrefixed()
1419 requestContext.addBytes(m.requestContext)
1420 } else {
1421 certificateTypes := body.addU8LengthPrefixed()
1422 certificateTypes.addBytes(m.certificateTypes)
1423 }
Adam Langley95c29f32014-06-20 12:00:00 -07001424
Nick Harper60edffd2016-06-21 15:19:24 -07001425 if m.hasSignatureAlgorithm {
Nick Harper7e0442a2016-07-01 17:40:09 -04001426 signatureAlgorithms := body.addU16LengthPrefixed()
Nick Harper60edffd2016-06-21 15:19:24 -07001427 for _, sigAlg := range m.signatureAlgorithms {
Nick Harper7e0442a2016-07-01 17:40:09 -04001428 signatureAlgorithms.addU16(uint16(sigAlg))
Adam Langley95c29f32014-06-20 12:00:00 -07001429 }
1430 }
1431
Nick Harper7e0442a2016-07-01 17:40:09 -04001432 certificateAuthorities := body.addU16LengthPrefixed()
Adam Langley95c29f32014-06-20 12:00:00 -07001433 for _, ca := range m.certificateAuthorities {
Nick Harper7e0442a2016-07-01 17:40:09 -04001434 caEntry := certificateAuthorities.addU16LengthPrefixed()
1435 caEntry.addBytes(ca)
Adam Langley95c29f32014-06-20 12:00:00 -07001436 }
1437
Nick Harper7e0442a2016-07-01 17:40:09 -04001438 m.raw = builder.finish()
1439 return m.raw
Adam Langley95c29f32014-06-20 12:00:00 -07001440}
1441
1442func (m *certificateRequestMsg) unmarshal(data []byte) bool {
1443 m.raw = data
1444
1445 if len(data) < 5 {
1446 return false
1447 }
Nick Harperb41d2e42016-07-01 17:50:32 -04001448 data = data[4:]
Adam Langley95c29f32014-06-20 12:00:00 -07001449
Nick Harperb41d2e42016-07-01 17:50:32 -04001450 if m.hasRequestContext {
1451 contextLen := int(data[0])
1452 if len(data) < 1+contextLen {
1453 return false
1454 }
1455 m.requestContext = make([]byte, contextLen)
1456 copy(m.requestContext, data[1:])
1457 data = data[1+contextLen:]
1458 } else {
1459 numCertTypes := int(data[0])
1460 if len(data) < 1+numCertTypes {
1461 return false
1462 }
1463 m.certificateTypes = make([]byte, numCertTypes)
1464 copy(m.certificateTypes, data[1:])
1465 data = data[1+numCertTypes:]
Adam Langley95c29f32014-06-20 12:00:00 -07001466 }
1467
Nick Harper60edffd2016-06-21 15:19:24 -07001468 if m.hasSignatureAlgorithm {
Adam Langley95c29f32014-06-20 12:00:00 -07001469 if len(data) < 2 {
1470 return false
1471 }
Nick Harper60edffd2016-06-21 15:19:24 -07001472 sigAlgsLen := uint16(data[0])<<8 | uint16(data[1])
Adam Langley95c29f32014-06-20 12:00:00 -07001473 data = data[2:]
Nick Harper60edffd2016-06-21 15:19:24 -07001474 if sigAlgsLen&1 != 0 {
Adam Langley95c29f32014-06-20 12:00:00 -07001475 return false
1476 }
Nick Harper60edffd2016-06-21 15:19:24 -07001477 if len(data) < int(sigAlgsLen) {
Adam Langley95c29f32014-06-20 12:00:00 -07001478 return false
1479 }
Nick Harper60edffd2016-06-21 15:19:24 -07001480 numSigAlgs := sigAlgsLen / 2
1481 m.signatureAlgorithms = make([]signatureAlgorithm, numSigAlgs)
1482 for i := range m.signatureAlgorithms {
1483 m.signatureAlgorithms[i] = signatureAlgorithm(data[0])<<8 | signatureAlgorithm(data[1])
Adam Langley95c29f32014-06-20 12:00:00 -07001484 data = data[2:]
1485 }
1486 }
1487
1488 if len(data) < 2 {
1489 return false
1490 }
1491 casLength := uint16(data[0])<<8 | uint16(data[1])
1492 data = data[2:]
1493 if len(data) < int(casLength) {
1494 return false
1495 }
1496 cas := make([]byte, casLength)
1497 copy(cas, data)
1498 data = data[casLength:]
1499
1500 m.certificateAuthorities = nil
1501 for len(cas) > 0 {
1502 if len(cas) < 2 {
1503 return false
1504 }
1505 caLen := uint16(cas[0])<<8 | uint16(cas[1])
1506 cas = cas[2:]
1507
1508 if len(cas) < int(caLen) {
1509 return false
1510 }
1511
1512 m.certificateAuthorities = append(m.certificateAuthorities, cas[:caLen])
1513 cas = cas[caLen:]
1514 }
1515 if len(data) > 0 {
1516 return false
1517 }
1518
1519 return true
1520}
1521
1522type certificateVerifyMsg struct {
Nick Harper60edffd2016-06-21 15:19:24 -07001523 raw []byte
1524 hasSignatureAlgorithm bool
1525 signatureAlgorithm signatureAlgorithm
1526 signature []byte
Adam Langley95c29f32014-06-20 12:00:00 -07001527}
1528
Adam Langley95c29f32014-06-20 12:00:00 -07001529func (m *certificateVerifyMsg) marshal() (x []byte) {
1530 if m.raw != nil {
1531 return m.raw
1532 }
1533
1534 // See http://tools.ietf.org/html/rfc4346#section-7.4.8
1535 siglength := len(m.signature)
1536 length := 2 + siglength
Nick Harper60edffd2016-06-21 15:19:24 -07001537 if m.hasSignatureAlgorithm {
Adam Langley95c29f32014-06-20 12:00:00 -07001538 length += 2
1539 }
1540 x = make([]byte, 4+length)
1541 x[0] = typeCertificateVerify
1542 x[1] = uint8(length >> 16)
1543 x[2] = uint8(length >> 8)
1544 x[3] = uint8(length)
1545 y := x[4:]
Nick Harper60edffd2016-06-21 15:19:24 -07001546 if m.hasSignatureAlgorithm {
1547 y[0] = byte(m.signatureAlgorithm >> 8)
1548 y[1] = byte(m.signatureAlgorithm)
Adam Langley95c29f32014-06-20 12:00:00 -07001549 y = y[2:]
1550 }
1551 y[0] = uint8(siglength >> 8)
1552 y[1] = uint8(siglength)
1553 copy(y[2:], m.signature)
1554
1555 m.raw = x
1556
1557 return
1558}
1559
1560func (m *certificateVerifyMsg) unmarshal(data []byte) bool {
1561 m.raw = data
1562
1563 if len(data) < 6 {
1564 return false
1565 }
1566
1567 length := uint32(data[1])<<16 | uint32(data[2])<<8 | uint32(data[3])
1568 if uint32(len(data))-4 != length {
1569 return false
1570 }
1571
1572 data = data[4:]
Nick Harper60edffd2016-06-21 15:19:24 -07001573 if m.hasSignatureAlgorithm {
1574 m.signatureAlgorithm = signatureAlgorithm(data[0])<<8 | signatureAlgorithm(data[1])
Adam Langley95c29f32014-06-20 12:00:00 -07001575 data = data[2:]
1576 }
1577
1578 if len(data) < 2 {
1579 return false
1580 }
1581 siglength := int(data[0])<<8 + int(data[1])
1582 data = data[2:]
1583 if len(data) != siglength {
1584 return false
1585 }
1586
1587 m.signature = data
1588
1589 return true
1590}
1591
1592type newSessionTicketMsg struct {
1593 raw []byte
1594 ticket []byte
1595}
1596
Adam Langley95c29f32014-06-20 12:00:00 -07001597func (m *newSessionTicketMsg) marshal() (x []byte) {
1598 if m.raw != nil {
1599 return m.raw
1600 }
1601
1602 // See http://tools.ietf.org/html/rfc5077#section-3.3
1603 ticketLen := len(m.ticket)
1604 length := 2 + 4 + ticketLen
1605 x = make([]byte, 4+length)
1606 x[0] = typeNewSessionTicket
1607 x[1] = uint8(length >> 16)
1608 x[2] = uint8(length >> 8)
1609 x[3] = uint8(length)
1610 x[8] = uint8(ticketLen >> 8)
1611 x[9] = uint8(ticketLen)
1612 copy(x[10:], m.ticket)
1613
1614 m.raw = x
1615
1616 return
1617}
1618
1619func (m *newSessionTicketMsg) unmarshal(data []byte) bool {
1620 m.raw = data
1621
1622 if len(data) < 10 {
1623 return false
1624 }
1625
1626 length := uint32(data[1])<<16 | uint32(data[2])<<8 | uint32(data[3])
1627 if uint32(len(data))-4 != length {
1628 return false
1629 }
1630
1631 ticketLen := int(data[8])<<8 + int(data[9])
1632 if len(data)-10 != ticketLen {
1633 return false
1634 }
1635
1636 m.ticket = data[10:]
1637
1638 return true
1639}
1640
David Benjamind86c7672014-08-02 04:07:12 -04001641type v2ClientHelloMsg struct {
1642 raw []byte
1643 vers uint16
1644 cipherSuites []uint16
1645 sessionId []byte
1646 challenge []byte
1647}
1648
David Benjamind86c7672014-08-02 04:07:12 -04001649func (m *v2ClientHelloMsg) marshal() []byte {
1650 if m.raw != nil {
1651 return m.raw
1652 }
1653
1654 length := 1 + 2 + 2 + 2 + 2 + len(m.cipherSuites)*3 + len(m.sessionId) + len(m.challenge)
1655
1656 x := make([]byte, length)
1657 x[0] = 1
1658 x[1] = uint8(m.vers >> 8)
1659 x[2] = uint8(m.vers)
1660 x[3] = uint8((len(m.cipherSuites) * 3) >> 8)
1661 x[4] = uint8(len(m.cipherSuites) * 3)
1662 x[5] = uint8(len(m.sessionId) >> 8)
1663 x[6] = uint8(len(m.sessionId))
1664 x[7] = uint8(len(m.challenge) >> 8)
1665 x[8] = uint8(len(m.challenge))
1666 y := x[9:]
1667 for i, spec := range m.cipherSuites {
1668 y[i*3] = 0
1669 y[i*3+1] = uint8(spec >> 8)
1670 y[i*3+2] = uint8(spec)
1671 }
1672 y = y[len(m.cipherSuites)*3:]
1673 copy(y, m.sessionId)
1674 y = y[len(m.sessionId):]
1675 copy(y, m.challenge)
1676
1677 m.raw = x
1678
1679 return x
1680}
1681
David Benjamin83c0bc92014-08-04 01:23:53 -04001682type helloVerifyRequestMsg struct {
1683 raw []byte
1684 vers uint16
1685 cookie []byte
1686}
1687
David Benjamin83c0bc92014-08-04 01:23:53 -04001688func (m *helloVerifyRequestMsg) marshal() []byte {
1689 if m.raw != nil {
1690 return m.raw
1691 }
1692
1693 length := 2 + 1 + len(m.cookie)
1694
1695 x := make([]byte, 4+length)
1696 x[0] = typeHelloVerifyRequest
1697 x[1] = uint8(length >> 16)
1698 x[2] = uint8(length >> 8)
1699 x[3] = uint8(length)
1700 vers := versionToWire(m.vers, true)
1701 x[4] = uint8(vers >> 8)
1702 x[5] = uint8(vers)
1703 x[6] = uint8(len(m.cookie))
1704 copy(x[7:7+len(m.cookie)], m.cookie)
1705
1706 return x
1707}
1708
1709func (m *helloVerifyRequestMsg) unmarshal(data []byte) bool {
1710 if len(data) < 4+2+1 {
1711 return false
1712 }
1713 m.raw = data
1714 m.vers = wireToVersion(uint16(data[4])<<8|uint16(data[5]), true)
1715 cookieLen := int(data[6])
1716 if cookieLen > 32 || len(data) != 7+cookieLen {
1717 return false
1718 }
1719 m.cookie = data[7 : 7+cookieLen]
1720
1721 return true
1722}
1723
David Benjamin24599a82016-06-30 18:56:53 -04001724type channelIDMsg struct {
David Benjamind30a9902014-08-24 01:44:23 -04001725 raw []byte
1726 channelID []byte
1727}
1728
David Benjamin24599a82016-06-30 18:56:53 -04001729func (m *channelIDMsg) marshal() []byte {
David Benjamind30a9902014-08-24 01:44:23 -04001730 if m.raw != nil {
1731 return m.raw
1732 }
1733
1734 length := 2 + 2 + len(m.channelID)
1735
1736 x := make([]byte, 4+length)
David Benjamin24599a82016-06-30 18:56:53 -04001737 x[0] = typeChannelID
David Benjamind30a9902014-08-24 01:44:23 -04001738 x[1] = uint8(length >> 16)
1739 x[2] = uint8(length >> 8)
1740 x[3] = uint8(length)
1741 x[4] = uint8(extensionChannelID >> 8)
1742 x[5] = uint8(extensionChannelID & 0xff)
1743 x[6] = uint8(len(m.channelID) >> 8)
1744 x[7] = uint8(len(m.channelID) & 0xff)
1745 copy(x[8:], m.channelID)
1746
1747 return x
1748}
1749
David Benjamin24599a82016-06-30 18:56:53 -04001750func (m *channelIDMsg) unmarshal(data []byte) bool {
David Benjamind30a9902014-08-24 01:44:23 -04001751 if len(data) != 4+2+2+128 {
1752 return false
1753 }
1754 m.raw = data
1755 if (uint16(data[4])<<8)|uint16(data[5]) != extensionChannelID {
1756 return false
1757 }
1758 if int(data[6])<<8|int(data[7]) != 128 {
1759 return false
1760 }
1761 m.channelID = data[4+2+2:]
1762
1763 return true
1764}
1765
Adam Langley2ae77d22014-10-28 17:29:33 -07001766type helloRequestMsg struct {
1767}
1768
1769func (*helloRequestMsg) marshal() []byte {
1770 return []byte{typeHelloRequest, 0, 0, 0}
1771}
1772
1773func (*helloRequestMsg) unmarshal(data []byte) bool {
1774 return len(data) == 4
1775}
1776
Adam Langley95c29f32014-06-20 12:00:00 -07001777func eqUint16s(x, y []uint16) bool {
1778 if len(x) != len(y) {
1779 return false
1780 }
1781 for i, v := range x {
1782 if y[i] != v {
1783 return false
1784 }
1785 }
1786 return true
1787}
1788
1789func eqCurveIDs(x, y []CurveID) bool {
1790 if len(x) != len(y) {
1791 return false
1792 }
1793 for i, v := range x {
1794 if y[i] != v {
1795 return false
1796 }
1797 }
1798 return true
1799}
1800
1801func eqStrings(x, y []string) bool {
1802 if len(x) != len(y) {
1803 return false
1804 }
1805 for i, v := range x {
1806 if y[i] != v {
1807 return false
1808 }
1809 }
1810 return true
1811}
1812
1813func eqByteSlices(x, y [][]byte) bool {
1814 if len(x) != len(y) {
1815 return false
1816 }
1817 for i, v := range x {
1818 if !bytes.Equal(v, y[i]) {
1819 return false
1820 }
1821 }
1822 return true
1823}
1824
Nick Harper60edffd2016-06-21 15:19:24 -07001825func eqSignatureAlgorithms(x, y []signatureAlgorithm) bool {
Adam Langley95c29f32014-06-20 12:00:00 -07001826 if len(x) != len(y) {
1827 return false
1828 }
1829 for i, v := range x {
1830 v2 := y[i]
Nick Harper60edffd2016-06-21 15:19:24 -07001831 if v != v2 {
Adam Langley95c29f32014-06-20 12:00:00 -07001832 return false
1833 }
1834 }
1835 return true
1836}
Nick Harperf8b0e702016-06-30 19:59:01 -04001837
1838func eqKeyShareEntryLists(x, y []keyShareEntry) bool {
1839 if len(x) != len(y) {
1840 return false
1841 }
1842 for i, v := range x {
1843 if y[i].group != v.group || !bytes.Equal(y[i].keyExchange, v.keyExchange) {
1844 return false
1845 }
1846 }
1847 return true
1848
1849}