blob: 907ae9cbe6c760daae6ffb160e44acbf1a86b6b6 [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
9type clientHelloMsg struct {
David Benjaminca6c8262014-11-15 19:06:08 -050010 raw []byte
11 isDTLS bool
12 vers uint16
13 random []byte
14 sessionId []byte
15 cookie []byte
16 cipherSuites []uint16
17 compressionMethods []uint8
18 nextProtoNeg bool
19 serverName string
20 ocspStapling bool
21 supportedCurves []CurveID
22 supportedPoints []uint8
23 ticketSupported bool
24 sessionTicket []uint8
Nick Harper60edffd2016-06-21 15:19:24 -070025 signatureAlgorithms []signatureAlgorithm
David Benjaminca6c8262014-11-15 19:06:08 -050026 secureRenegotiation []byte
27 alpnProtocols []string
28 duplicateExtension bool
29 channelIDSupported bool
30 npnLast bool
31 extendedMasterSecret bool
32 srtpProtectionProfiles []uint16
33 srtpMasterKeyIdentifier string
David Benjamin61f95272014-11-25 01:55:35 -050034 sctListSupported bool
Adam Langley09505632015-07-30 18:10:13 -070035 customExtension string
Adam Langley95c29f32014-06-20 12:00:00 -070036}
37
38func (m *clientHelloMsg) equal(i interface{}) bool {
39 m1, ok := i.(*clientHelloMsg)
40 if !ok {
41 return false
42 }
43
44 return bytes.Equal(m.raw, m1.raw) &&
David Benjamin83c0bc92014-08-04 01:23:53 -040045 m.isDTLS == m1.isDTLS &&
Adam Langley95c29f32014-06-20 12:00:00 -070046 m.vers == m1.vers &&
47 bytes.Equal(m.random, m1.random) &&
48 bytes.Equal(m.sessionId, m1.sessionId) &&
David Benjamin83c0bc92014-08-04 01:23:53 -040049 bytes.Equal(m.cookie, m1.cookie) &&
Adam Langley95c29f32014-06-20 12:00:00 -070050 eqUint16s(m.cipherSuites, m1.cipherSuites) &&
51 bytes.Equal(m.compressionMethods, m1.compressionMethods) &&
52 m.nextProtoNeg == m1.nextProtoNeg &&
53 m.serverName == m1.serverName &&
54 m.ocspStapling == m1.ocspStapling &&
55 eqCurveIDs(m.supportedCurves, m1.supportedCurves) &&
56 bytes.Equal(m.supportedPoints, m1.supportedPoints) &&
57 m.ticketSupported == m1.ticketSupported &&
58 bytes.Equal(m.sessionTicket, m1.sessionTicket) &&
Nick Harper60edffd2016-06-21 15:19:24 -070059 eqSignatureAlgorithms(m.signatureAlgorithms, m1.signatureAlgorithms) &&
Adam Langley2ae77d22014-10-28 17:29:33 -070060 bytes.Equal(m.secureRenegotiation, m1.secureRenegotiation) &&
61 (m.secureRenegotiation == nil) == (m1.secureRenegotiation == nil) &&
David Benjaminfa055a22014-09-15 16:51:51 -040062 eqStrings(m.alpnProtocols, m1.alpnProtocols) &&
David Benjamind30a9902014-08-24 01:44:23 -040063 m.duplicateExtension == m1.duplicateExtension &&
David Benjaminfc7b0862014-09-06 13:21:53 -040064 m.channelIDSupported == m1.channelIDSupported &&
Adam Langley75712922014-10-10 16:23:43 -070065 m.npnLast == m1.npnLast &&
David Benjaminca6c8262014-11-15 19:06:08 -050066 m.extendedMasterSecret == m1.extendedMasterSecret &&
67 eqUint16s(m.srtpProtectionProfiles, m1.srtpProtectionProfiles) &&
David Benjamin61f95272014-11-25 01:55:35 -050068 m.srtpMasterKeyIdentifier == m1.srtpMasterKeyIdentifier &&
Adam Langley09505632015-07-30 18:10:13 -070069 m.sctListSupported == m1.sctListSupported &&
70 m.customExtension == m1.customExtension
Adam Langley95c29f32014-06-20 12:00:00 -070071}
72
73func (m *clientHelloMsg) marshal() []byte {
74 if m.raw != nil {
75 return m.raw
76 }
77
78 length := 2 + 32 + 1 + len(m.sessionId) + 2 + len(m.cipherSuites)*2 + 1 + len(m.compressionMethods)
David Benjamin83c0bc92014-08-04 01:23:53 -040079 if m.isDTLS {
80 length += 1 + len(m.cookie)
81 }
Adam Langley95c29f32014-06-20 12:00:00 -070082 numExtensions := 0
83 extensionsLength := 0
84 if m.nextProtoNeg {
85 numExtensions++
86 }
87 if m.ocspStapling {
88 extensionsLength += 1 + 2 + 2
89 numExtensions++
90 }
91 if len(m.serverName) > 0 {
92 extensionsLength += 5 + len(m.serverName)
93 numExtensions++
94 }
95 if len(m.supportedCurves) > 0 {
96 extensionsLength += 2 + 2*len(m.supportedCurves)
97 numExtensions++
98 }
99 if len(m.supportedPoints) > 0 {
100 extensionsLength += 1 + len(m.supportedPoints)
101 numExtensions++
102 }
103 if m.ticketSupported {
104 extensionsLength += len(m.sessionTicket)
105 numExtensions++
106 }
Nick Harper60edffd2016-06-21 15:19:24 -0700107 if len(m.signatureAlgorithms) > 0 {
108 extensionsLength += 2 + 2*len(m.signatureAlgorithms)
Adam Langley95c29f32014-06-20 12:00:00 -0700109 numExtensions++
110 }
Adam Langley2ae77d22014-10-28 17:29:33 -0700111 if m.secureRenegotiation != nil {
112 extensionsLength += 1 + len(m.secureRenegotiation)
Adam Langley95c29f32014-06-20 12:00:00 -0700113 numExtensions++
114 }
David Benjamin35a7a442014-07-05 00:23:20 -0400115 if m.duplicateExtension {
116 numExtensions += 2
117 }
David Benjamind30a9902014-08-24 01:44:23 -0400118 if m.channelIDSupported {
119 numExtensions++
120 }
David Benjaminfa055a22014-09-15 16:51:51 -0400121 if len(m.alpnProtocols) > 0 {
122 extensionsLength += 2
123 for _, s := range m.alpnProtocols {
Adam Langleyefb0e162015-07-09 11:35:04 -0700124 if l := len(s); l > 255 {
David Benjaminfa055a22014-09-15 16:51:51 -0400125 panic("invalid ALPN protocol")
126 }
127 extensionsLength++
128 extensionsLength += len(s)
129 }
130 numExtensions++
131 }
Adam Langley75712922014-10-10 16:23:43 -0700132 if m.extendedMasterSecret {
133 numExtensions++
134 }
David Benjaminca6c8262014-11-15 19:06:08 -0500135 if len(m.srtpProtectionProfiles) > 0 {
136 extensionsLength += 2 + 2*len(m.srtpProtectionProfiles)
137 extensionsLength += 1 + len(m.srtpMasterKeyIdentifier)
138 numExtensions++
139 }
David Benjamin61f95272014-11-25 01:55:35 -0500140 if m.sctListSupported {
141 numExtensions++
142 }
Adam Langley09505632015-07-30 18:10:13 -0700143 if l := len(m.customExtension); l > 0 {
144 extensionsLength += l
145 numExtensions++
146 }
Adam Langley95c29f32014-06-20 12:00:00 -0700147 if numExtensions > 0 {
148 extensionsLength += 4 * numExtensions
149 length += 2 + extensionsLength
150 }
151
152 x := make([]byte, 4+length)
153 x[0] = typeClientHello
154 x[1] = uint8(length >> 16)
155 x[2] = uint8(length >> 8)
156 x[3] = uint8(length)
David Benjamin83c0bc92014-08-04 01:23:53 -0400157 vers := versionToWire(m.vers, m.isDTLS)
158 x[4] = uint8(vers >> 8)
159 x[5] = uint8(vers)
Adam Langley95c29f32014-06-20 12:00:00 -0700160 copy(x[6:38], m.random)
161 x[38] = uint8(len(m.sessionId))
162 copy(x[39:39+len(m.sessionId)], m.sessionId)
163 y := x[39+len(m.sessionId):]
David Benjamin83c0bc92014-08-04 01:23:53 -0400164 if m.isDTLS {
165 y[0] = uint8(len(m.cookie))
166 copy(y[1:], m.cookie)
167 y = y[1+len(m.cookie):]
168 }
Adam Langley95c29f32014-06-20 12:00:00 -0700169 y[0] = uint8(len(m.cipherSuites) >> 7)
170 y[1] = uint8(len(m.cipherSuites) << 1)
171 for i, suite := range m.cipherSuites {
172 y[2+i*2] = uint8(suite >> 8)
173 y[3+i*2] = uint8(suite)
174 }
175 z := y[2+len(m.cipherSuites)*2:]
176 z[0] = uint8(len(m.compressionMethods))
177 copy(z[1:], m.compressionMethods)
178
179 z = z[1+len(m.compressionMethods):]
180 if numExtensions > 0 {
181 z[0] = byte(extensionsLength >> 8)
182 z[1] = byte(extensionsLength)
183 z = z[2:]
184 }
David Benjamin35a7a442014-07-05 00:23:20 -0400185 if m.duplicateExtension {
186 // Add a duplicate bogus extension at the beginning and end.
187 z[0] = 0xff
188 z[1] = 0xff
189 z = z[4:]
190 }
David Benjaminfc7b0862014-09-06 13:21:53 -0400191 if m.nextProtoNeg && !m.npnLast {
Adam Langley95c29f32014-06-20 12:00:00 -0700192 z[0] = byte(extensionNextProtoNeg >> 8)
193 z[1] = byte(extensionNextProtoNeg & 0xff)
194 // The length is always 0
195 z = z[4:]
196 }
197 if len(m.serverName) > 0 {
198 z[0] = byte(extensionServerName >> 8)
199 z[1] = byte(extensionServerName & 0xff)
200 l := len(m.serverName) + 5
201 z[2] = byte(l >> 8)
202 z[3] = byte(l)
203 z = z[4:]
204
205 // RFC 3546, section 3.1
206 //
207 // struct {
208 // NameType name_type;
209 // select (name_type) {
210 // case host_name: HostName;
211 // } name;
212 // } ServerName;
213 //
214 // enum {
215 // host_name(0), (255)
216 // } NameType;
217 //
218 // opaque HostName<1..2^16-1>;
219 //
220 // struct {
221 // ServerName server_name_list<1..2^16-1>
222 // } ServerNameList;
223
224 z[0] = byte((len(m.serverName) + 3) >> 8)
225 z[1] = byte(len(m.serverName) + 3)
226 z[3] = byte(len(m.serverName) >> 8)
227 z[4] = byte(len(m.serverName))
228 copy(z[5:], []byte(m.serverName))
229 z = z[l:]
230 }
231 if m.ocspStapling {
232 // RFC 4366, section 3.6
233 z[0] = byte(extensionStatusRequest >> 8)
234 z[1] = byte(extensionStatusRequest)
235 z[2] = 0
236 z[3] = 5
237 z[4] = 1 // OCSP type
238 // Two zero valued uint16s for the two lengths.
239 z = z[9:]
240 }
241 if len(m.supportedCurves) > 0 {
242 // http://tools.ietf.org/html/rfc4492#section-5.5.1
243 z[0] = byte(extensionSupportedCurves >> 8)
244 z[1] = byte(extensionSupportedCurves)
245 l := 2 + 2*len(m.supportedCurves)
246 z[2] = byte(l >> 8)
247 z[3] = byte(l)
248 l -= 2
249 z[4] = byte(l >> 8)
250 z[5] = byte(l)
251 z = z[6:]
252 for _, curve := range m.supportedCurves {
253 z[0] = byte(curve >> 8)
254 z[1] = byte(curve)
255 z = z[2:]
256 }
257 }
258 if len(m.supportedPoints) > 0 {
259 // http://tools.ietf.org/html/rfc4492#section-5.5.2
260 z[0] = byte(extensionSupportedPoints >> 8)
261 z[1] = byte(extensionSupportedPoints)
262 l := 1 + len(m.supportedPoints)
263 z[2] = byte(l >> 8)
264 z[3] = byte(l)
265 l--
266 z[4] = byte(l)
267 z = z[5:]
268 for _, pointFormat := range m.supportedPoints {
269 z[0] = byte(pointFormat)
270 z = z[1:]
271 }
272 }
273 if m.ticketSupported {
274 // http://tools.ietf.org/html/rfc5077#section-3.2
275 z[0] = byte(extensionSessionTicket >> 8)
276 z[1] = byte(extensionSessionTicket)
277 l := len(m.sessionTicket)
278 z[2] = byte(l >> 8)
279 z[3] = byte(l)
280 z = z[4:]
281 copy(z, m.sessionTicket)
282 z = z[len(m.sessionTicket):]
283 }
Nick Harper60edffd2016-06-21 15:19:24 -0700284 if len(m.signatureAlgorithms) > 0 {
Adam Langley95c29f32014-06-20 12:00:00 -0700285 // https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
286 z[0] = byte(extensionSignatureAlgorithms >> 8)
287 z[1] = byte(extensionSignatureAlgorithms)
Nick Harper60edffd2016-06-21 15:19:24 -0700288 l := 2 + 2*len(m.signatureAlgorithms)
Adam Langley95c29f32014-06-20 12:00:00 -0700289 z[2] = byte(l >> 8)
290 z[3] = byte(l)
291 z = z[4:]
292
293 l -= 2
294 z[0] = byte(l >> 8)
295 z[1] = byte(l)
296 z = z[2:]
Nick Harper60edffd2016-06-21 15:19:24 -0700297 for _, sigAlg := range m.signatureAlgorithms {
298 z[0] = byte(sigAlg >> 8)
299 z[1] = byte(sigAlg)
Adam Langley95c29f32014-06-20 12:00:00 -0700300 z = z[2:]
301 }
302 }
Adam Langley2ae77d22014-10-28 17:29:33 -0700303 if m.secureRenegotiation != nil {
Adam Langley95c29f32014-06-20 12:00:00 -0700304 z[0] = byte(extensionRenegotiationInfo >> 8)
305 z[1] = byte(extensionRenegotiationInfo & 0xff)
306 z[2] = 0
Adam Langley2ae77d22014-10-28 17:29:33 -0700307 z[3] = byte(1 + len(m.secureRenegotiation))
308 z[4] = byte(len(m.secureRenegotiation))
Adam Langley95c29f32014-06-20 12:00:00 -0700309 z = z[5:]
Adam Langley2ae77d22014-10-28 17:29:33 -0700310 copy(z, m.secureRenegotiation)
311 z = z[len(m.secureRenegotiation):]
Adam Langley95c29f32014-06-20 12:00:00 -0700312 }
David Benjaminfa055a22014-09-15 16:51:51 -0400313 if len(m.alpnProtocols) > 0 {
314 z[0] = byte(extensionALPN >> 8)
315 z[1] = byte(extensionALPN & 0xff)
316 lengths := z[2:]
317 z = z[6:]
318
319 stringsLength := 0
320 for _, s := range m.alpnProtocols {
321 l := len(s)
322 z[0] = byte(l)
323 copy(z[1:], s)
324 z = z[1+l:]
325 stringsLength += 1 + l
326 }
327
328 lengths[2] = byte(stringsLength >> 8)
329 lengths[3] = byte(stringsLength)
330 stringsLength += 2
331 lengths[0] = byte(stringsLength >> 8)
332 lengths[1] = byte(stringsLength)
333 }
David Benjamind30a9902014-08-24 01:44:23 -0400334 if m.channelIDSupported {
335 z[0] = byte(extensionChannelID >> 8)
336 z[1] = byte(extensionChannelID & 0xff)
337 z = z[4:]
338 }
David Benjaminfc7b0862014-09-06 13:21:53 -0400339 if m.nextProtoNeg && m.npnLast {
340 z[0] = byte(extensionNextProtoNeg >> 8)
341 z[1] = byte(extensionNextProtoNeg & 0xff)
342 // The length is always 0
343 z = z[4:]
344 }
David Benjamin35a7a442014-07-05 00:23:20 -0400345 if m.duplicateExtension {
346 // Add a duplicate bogus extension at the beginning and end.
347 z[0] = 0xff
348 z[1] = 0xff
349 z = z[4:]
350 }
Adam Langley75712922014-10-10 16:23:43 -0700351 if m.extendedMasterSecret {
David Benjamin43946d42016-02-01 08:42:19 -0500352 // https://tools.ietf.org/html/rfc7627
Adam Langley75712922014-10-10 16:23:43 -0700353 z[0] = byte(extensionExtendedMasterSecret >> 8)
354 z[1] = byte(extensionExtendedMasterSecret & 0xff)
355 z = z[4:]
356 }
David Benjaminca6c8262014-11-15 19:06:08 -0500357 if len(m.srtpProtectionProfiles) > 0 {
358 z[0] = byte(extensionUseSRTP >> 8)
359 z[1] = byte(extensionUseSRTP & 0xff)
360
361 profilesLen := 2 * len(m.srtpProtectionProfiles)
362 mkiLen := len(m.srtpMasterKeyIdentifier)
363 l := 2 + profilesLen + 1 + mkiLen
364 z[2] = byte(l >> 8)
365 z[3] = byte(l & 0xff)
366
367 z[4] = byte(profilesLen >> 8)
368 z[5] = byte(profilesLen & 0xff)
369 z = z[6:]
370 for _, p := range m.srtpProtectionProfiles {
371 z[0] = byte(p >> 8)
372 z[1] = byte(p & 0xff)
373 z = z[2:]
374 }
375
376 z[0] = byte(mkiLen)
377 copy(z[1:], []byte(m.srtpMasterKeyIdentifier))
378 z = z[1+mkiLen:]
379 }
David Benjamin61f95272014-11-25 01:55:35 -0500380 if m.sctListSupported {
381 z[0] = byte(extensionSignedCertificateTimestamp >> 8)
382 z[1] = byte(extensionSignedCertificateTimestamp & 0xff)
383 z = z[4:]
384 }
Adam Langley09505632015-07-30 18:10:13 -0700385 if l := len(m.customExtension); l > 0 {
386 z[0] = byte(extensionCustom >> 8)
387 z[1] = byte(extensionCustom & 0xff)
388 z[2] = byte(l >> 8)
389 z[3] = byte(l & 0xff)
390 copy(z[4:], []byte(m.customExtension))
David Benjamin399e7c92015-07-30 23:01:27 -0400391 z = z[4+l:]
Adam Langley09505632015-07-30 18:10:13 -0700392 }
Adam Langley95c29f32014-06-20 12:00:00 -0700393
394 m.raw = x
395
396 return x
397}
398
399func (m *clientHelloMsg) unmarshal(data []byte) bool {
400 if len(data) < 42 {
401 return false
402 }
403 m.raw = data
David Benjamin83c0bc92014-08-04 01:23:53 -0400404 m.vers = wireToVersion(uint16(data[4])<<8|uint16(data[5]), m.isDTLS)
Adam Langley95c29f32014-06-20 12:00:00 -0700405 m.random = data[6:38]
406 sessionIdLen := int(data[38])
407 if sessionIdLen > 32 || len(data) < 39+sessionIdLen {
408 return false
409 }
410 m.sessionId = data[39 : 39+sessionIdLen]
411 data = data[39+sessionIdLen:]
David Benjamin83c0bc92014-08-04 01:23:53 -0400412 if m.isDTLS {
413 if len(data) < 1 {
414 return false
415 }
416 cookieLen := int(data[0])
417 if cookieLen > 32 || len(data) < 1+cookieLen {
418 return false
419 }
420 m.cookie = data[1 : 1+cookieLen]
421 data = data[1+cookieLen:]
422 }
Adam Langley95c29f32014-06-20 12:00:00 -0700423 if len(data) < 2 {
424 return false
425 }
426 // cipherSuiteLen is the number of bytes of cipher suite numbers. Since
427 // they are uint16s, the number must be even.
428 cipherSuiteLen := int(data[0])<<8 | int(data[1])
429 if cipherSuiteLen%2 == 1 || len(data) < 2+cipherSuiteLen {
430 return false
431 }
432 numCipherSuites := cipherSuiteLen / 2
433 m.cipherSuites = make([]uint16, numCipherSuites)
434 for i := 0; i < numCipherSuites; i++ {
435 m.cipherSuites[i] = uint16(data[2+2*i])<<8 | uint16(data[3+2*i])
436 if m.cipherSuites[i] == scsvRenegotiation {
Adam Langley2ae77d22014-10-28 17:29:33 -0700437 m.secureRenegotiation = []byte{}
Adam Langley95c29f32014-06-20 12:00:00 -0700438 }
439 }
440 data = data[2+cipherSuiteLen:]
441 if len(data) < 1 {
442 return false
443 }
444 compressionMethodsLen := int(data[0])
445 if len(data) < 1+compressionMethodsLen {
446 return false
447 }
448 m.compressionMethods = data[1 : 1+compressionMethodsLen]
449
450 data = data[1+compressionMethodsLen:]
451
452 m.nextProtoNeg = false
453 m.serverName = ""
454 m.ocspStapling = false
455 m.ticketSupported = false
456 m.sessionTicket = nil
Nick Harper60edffd2016-06-21 15:19:24 -0700457 m.signatureAlgorithms = nil
David Benjaminfa055a22014-09-15 16:51:51 -0400458 m.alpnProtocols = nil
Adam Langley75712922014-10-10 16:23:43 -0700459 m.extendedMasterSecret = false
Adam Langley09505632015-07-30 18:10:13 -0700460 m.customExtension = ""
Adam Langley95c29f32014-06-20 12:00:00 -0700461
462 if len(data) == 0 {
463 // ClientHello is optionally followed by extension data
464 return true
465 }
466 if len(data) < 2 {
467 return false
468 }
469
470 extensionsLength := int(data[0])<<8 | int(data[1])
471 data = data[2:]
472 if extensionsLength != len(data) {
473 return false
474 }
475
476 for len(data) != 0 {
477 if len(data) < 4 {
478 return false
479 }
480 extension := uint16(data[0])<<8 | uint16(data[1])
481 length := int(data[2])<<8 | int(data[3])
482 data = data[4:]
483 if len(data) < length {
484 return false
485 }
486
487 switch extension {
488 case extensionServerName:
489 if length < 2 {
490 return false
491 }
492 numNames := int(data[0])<<8 | int(data[1])
493 d := data[2:]
494 for i := 0; i < numNames; i++ {
495 if len(d) < 3 {
496 return false
497 }
498 nameType := d[0]
499 nameLen := int(d[1])<<8 | int(d[2])
500 d = d[3:]
501 if len(d) < nameLen {
502 return false
503 }
504 if nameType == 0 {
505 m.serverName = string(d[0:nameLen])
506 break
507 }
508 d = d[nameLen:]
509 }
510 case extensionNextProtoNeg:
511 if length > 0 {
512 return false
513 }
514 m.nextProtoNeg = true
515 case extensionStatusRequest:
516 m.ocspStapling = length > 0 && data[0] == statusTypeOCSP
517 case extensionSupportedCurves:
518 // http://tools.ietf.org/html/rfc4492#section-5.5.1
519 if length < 2 {
520 return false
521 }
522 l := int(data[0])<<8 | int(data[1])
523 if l%2 == 1 || length != l+2 {
524 return false
525 }
526 numCurves := l / 2
527 m.supportedCurves = make([]CurveID, numCurves)
528 d := data[2:]
529 for i := 0; i < numCurves; i++ {
530 m.supportedCurves[i] = CurveID(d[0])<<8 | CurveID(d[1])
531 d = d[2:]
532 }
533 case extensionSupportedPoints:
534 // http://tools.ietf.org/html/rfc4492#section-5.5.2
535 if length < 1 {
536 return false
537 }
538 l := int(data[0])
539 if length != l+1 {
540 return false
541 }
542 m.supportedPoints = make([]uint8, l)
543 copy(m.supportedPoints, data[1:])
544 case extensionSessionTicket:
545 // http://tools.ietf.org/html/rfc5077#section-3.2
546 m.ticketSupported = true
547 m.sessionTicket = data[:length]
548 case extensionSignatureAlgorithms:
549 // https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
550 if length < 2 || length&1 != 0 {
551 return false
552 }
553 l := int(data[0])<<8 | int(data[1])
554 if l != length-2 {
555 return false
556 }
557 n := l / 2
558 d := data[2:]
Nick Harper60edffd2016-06-21 15:19:24 -0700559 m.signatureAlgorithms = make([]signatureAlgorithm, n)
560 for i := range m.signatureAlgorithms {
561 m.signatureAlgorithms[i] = signatureAlgorithm(d[0])<<8 | signatureAlgorithm(d[1])
Adam Langley95c29f32014-06-20 12:00:00 -0700562 d = d[2:]
563 }
Adam Langley2ae77d22014-10-28 17:29:33 -0700564 case extensionRenegotiationInfo:
565 if length < 1 || length != int(data[0])+1 {
Adam Langley95c29f32014-06-20 12:00:00 -0700566 return false
567 }
Adam Langley2ae77d22014-10-28 17:29:33 -0700568 m.secureRenegotiation = data[1:length]
David Benjaminfa055a22014-09-15 16:51:51 -0400569 case extensionALPN:
570 if length < 2 {
571 return false
572 }
573 l := int(data[0])<<8 | int(data[1])
574 if l != length-2 {
575 return false
576 }
577 d := data[2:length]
578 for len(d) != 0 {
579 stringLen := int(d[0])
580 d = d[1:]
581 if stringLen == 0 || stringLen > len(d) {
582 return false
583 }
584 m.alpnProtocols = append(m.alpnProtocols, string(d[:stringLen]))
585 d = d[stringLen:]
586 }
David Benjamind30a9902014-08-24 01:44:23 -0400587 case extensionChannelID:
588 if length > 0 {
589 return false
590 }
591 m.channelIDSupported = true
Adam Langley75712922014-10-10 16:23:43 -0700592 case extensionExtendedMasterSecret:
593 if length != 0 {
594 return false
595 }
596 m.extendedMasterSecret = true
David Benjaminca6c8262014-11-15 19:06:08 -0500597 case extensionUseSRTP:
598 if length < 2 {
599 return false
600 }
601 l := int(data[0])<<8 | int(data[1])
602 if l > length-2 || l%2 != 0 {
603 return false
604 }
605 n := l / 2
606 m.srtpProtectionProfiles = make([]uint16, n)
607 d := data[2:length]
608 for i := 0; i < n; i++ {
609 m.srtpProtectionProfiles[i] = uint16(d[0])<<8 | uint16(d[1])
610 d = d[2:]
611 }
612 if len(d) < 1 || int(d[0]) != len(d)-1 {
613 return false
614 }
615 m.srtpMasterKeyIdentifier = string(d[1:])
David Benjamin61f95272014-11-25 01:55:35 -0500616 case extensionSignedCertificateTimestamp:
617 if length != 0 {
618 return false
619 }
620 m.sctListSupported = true
Adam Langley09505632015-07-30 18:10:13 -0700621 case extensionCustom:
622 m.customExtension = string(data[:length])
Adam Langley95c29f32014-06-20 12:00:00 -0700623 }
624 data = data[length:]
625 }
626
627 return true
628}
629
630type serverHelloMsg struct {
David Benjaminca6c8262014-11-15 19:06:08 -0500631 raw []byte
632 isDTLS bool
633 vers uint16
634 random []byte
635 sessionId []byte
636 cipherSuite uint16
637 compressionMethod uint8
638 nextProtoNeg bool
639 nextProtos []string
640 ocspStapling bool
641 ticketSupported bool
642 secureRenegotiation []byte
643 alpnProtocol string
Adam Langleyefb0e162015-07-09 11:35:04 -0700644 alpnProtocolEmpty bool
David Benjaminca6c8262014-11-15 19:06:08 -0500645 duplicateExtension bool
646 channelIDRequested bool
647 extendedMasterSecret bool
648 srtpProtectionProfile uint16
649 srtpMasterKeyIdentifier string
David Benjamin61f95272014-11-25 01:55:35 -0500650 sctList []byte
Adam Langley09505632015-07-30 18:10:13 -0700651 customExtension string
David Benjamin76c2efc2015-08-31 14:24:29 -0400652 npnLast bool
Adam Langley95c29f32014-06-20 12:00:00 -0700653}
654
Adam Langley95c29f32014-06-20 12:00:00 -0700655func (m *serverHelloMsg) marshal() []byte {
656 if m.raw != nil {
657 return m.raw
658 }
659
660 length := 38 + len(m.sessionId)
661 numExtensions := 0
662 extensionsLength := 0
663
664 nextProtoLen := 0
665 if m.nextProtoNeg {
666 numExtensions++
667 for _, v := range m.nextProtos {
668 nextProtoLen += len(v)
669 }
670 nextProtoLen += len(m.nextProtos)
671 extensionsLength += nextProtoLen
672 }
673 if m.ocspStapling {
674 numExtensions++
675 }
676 if m.ticketSupported {
677 numExtensions++
678 }
Adam Langley2ae77d22014-10-28 17:29:33 -0700679 if m.secureRenegotiation != nil {
680 extensionsLength += 1 + len(m.secureRenegotiation)
Adam Langley95c29f32014-06-20 12:00:00 -0700681 numExtensions++
682 }
David Benjamin35a7a442014-07-05 00:23:20 -0400683 if m.duplicateExtension {
684 numExtensions += 2
685 }
David Benjamind30a9902014-08-24 01:44:23 -0400686 if m.channelIDRequested {
687 numExtensions++
688 }
Adam Langleyefb0e162015-07-09 11:35:04 -0700689 if alpnLen := len(m.alpnProtocol); alpnLen > 0 || m.alpnProtocolEmpty {
David Benjaminfa055a22014-09-15 16:51:51 -0400690 if alpnLen >= 256 {
691 panic("invalid ALPN protocol")
692 }
693 extensionsLength += 2 + 1 + alpnLen
694 numExtensions++
695 }
Adam Langley75712922014-10-10 16:23:43 -0700696 if m.extendedMasterSecret {
697 numExtensions++
698 }
David Benjaminca6c8262014-11-15 19:06:08 -0500699 if m.srtpProtectionProfile != 0 {
700 extensionsLength += 2 + 2 + 1 + len(m.srtpMasterKeyIdentifier)
701 numExtensions++
702 }
David Benjamin61f95272014-11-25 01:55:35 -0500703 if m.sctList != nil {
704 extensionsLength += len(m.sctList)
705 numExtensions++
706 }
Adam Langley09505632015-07-30 18:10:13 -0700707 if l := len(m.customExtension); l > 0 {
708 extensionsLength += l
709 numExtensions++
710 }
David Benjaminfa055a22014-09-15 16:51:51 -0400711
Adam Langley95c29f32014-06-20 12:00:00 -0700712 if numExtensions > 0 {
713 extensionsLength += 4 * numExtensions
714 length += 2 + extensionsLength
715 }
716
717 x := make([]byte, 4+length)
718 x[0] = typeServerHello
719 x[1] = uint8(length >> 16)
720 x[2] = uint8(length >> 8)
721 x[3] = uint8(length)
David Benjamin83c0bc92014-08-04 01:23:53 -0400722 vers := versionToWire(m.vers, m.isDTLS)
723 x[4] = uint8(vers >> 8)
724 x[5] = uint8(vers)
Adam Langley95c29f32014-06-20 12:00:00 -0700725 copy(x[6:38], m.random)
726 x[38] = uint8(len(m.sessionId))
727 copy(x[39:39+len(m.sessionId)], m.sessionId)
728 z := x[39+len(m.sessionId):]
729 z[0] = uint8(m.cipherSuite >> 8)
730 z[1] = uint8(m.cipherSuite)
731 z[2] = uint8(m.compressionMethod)
732
733 z = z[3:]
734 if numExtensions > 0 {
735 z[0] = byte(extensionsLength >> 8)
736 z[1] = byte(extensionsLength)
737 z = z[2:]
738 }
David Benjamin35a7a442014-07-05 00:23:20 -0400739 if m.duplicateExtension {
740 // Add a duplicate bogus extension at the beginning and end.
741 z[0] = 0xff
742 z[1] = 0xff
743 z = z[4:]
744 }
David Benjamin76c2efc2015-08-31 14:24:29 -0400745 if m.nextProtoNeg && !m.npnLast {
Adam Langley95c29f32014-06-20 12:00:00 -0700746 z[0] = byte(extensionNextProtoNeg >> 8)
747 z[1] = byte(extensionNextProtoNeg & 0xff)
748 z[2] = byte(nextProtoLen >> 8)
749 z[3] = byte(nextProtoLen)
750 z = z[4:]
751
752 for _, v := range m.nextProtos {
753 l := len(v)
754 if l > 255 {
755 l = 255
756 }
757 z[0] = byte(l)
758 copy(z[1:], []byte(v[0:l]))
759 z = z[1+l:]
760 }
761 }
762 if m.ocspStapling {
763 z[0] = byte(extensionStatusRequest >> 8)
764 z[1] = byte(extensionStatusRequest)
765 z = z[4:]
766 }
767 if m.ticketSupported {
768 z[0] = byte(extensionSessionTicket >> 8)
769 z[1] = byte(extensionSessionTicket)
770 z = z[4:]
771 }
Adam Langley2ae77d22014-10-28 17:29:33 -0700772 if m.secureRenegotiation != nil {
Adam Langley95c29f32014-06-20 12:00:00 -0700773 z[0] = byte(extensionRenegotiationInfo >> 8)
774 z[1] = byte(extensionRenegotiationInfo & 0xff)
775 z[2] = 0
Adam Langley2ae77d22014-10-28 17:29:33 -0700776 z[3] = byte(1 + len(m.secureRenegotiation))
777 z[4] = byte(len(m.secureRenegotiation))
Adam Langley95c29f32014-06-20 12:00:00 -0700778 z = z[5:]
Adam Langley2ae77d22014-10-28 17:29:33 -0700779 copy(z, m.secureRenegotiation)
780 z = z[len(m.secureRenegotiation):]
Adam Langley95c29f32014-06-20 12:00:00 -0700781 }
Adam Langleyefb0e162015-07-09 11:35:04 -0700782 if alpnLen := len(m.alpnProtocol); alpnLen > 0 || m.alpnProtocolEmpty {
David Benjaminfa055a22014-09-15 16:51:51 -0400783 z[0] = byte(extensionALPN >> 8)
784 z[1] = byte(extensionALPN & 0xff)
785 l := 2 + 1 + alpnLen
786 z[2] = byte(l >> 8)
787 z[3] = byte(l)
788 l -= 2
789 z[4] = byte(l >> 8)
790 z[5] = byte(l)
791 l -= 1
792 z[6] = byte(l)
793 copy(z[7:], []byte(m.alpnProtocol))
794 z = z[7+alpnLen:]
795 }
David Benjamind30a9902014-08-24 01:44:23 -0400796 if m.channelIDRequested {
797 z[0] = byte(extensionChannelID >> 8)
798 z[1] = byte(extensionChannelID & 0xff)
799 z = z[4:]
800 }
David Benjamin35a7a442014-07-05 00:23:20 -0400801 if m.duplicateExtension {
802 // Add a duplicate bogus extension at the beginning and end.
803 z[0] = 0xff
804 z[1] = 0xff
805 z = z[4:]
806 }
Adam Langley75712922014-10-10 16:23:43 -0700807 if m.extendedMasterSecret {
808 z[0] = byte(extensionExtendedMasterSecret >> 8)
809 z[1] = byte(extensionExtendedMasterSecret & 0xff)
810 z = z[4:]
811 }
David Benjaminca6c8262014-11-15 19:06:08 -0500812 if m.srtpProtectionProfile != 0 {
813 z[0] = byte(extensionUseSRTP >> 8)
814 z[1] = byte(extensionUseSRTP & 0xff)
815 l := 2 + 2 + 1 + len(m.srtpMasterKeyIdentifier)
816 z[2] = byte(l >> 8)
817 z[3] = byte(l & 0xff)
818 z[4] = 0
819 z[5] = 2
820 z[6] = byte(m.srtpProtectionProfile >> 8)
821 z[7] = byte(m.srtpProtectionProfile & 0xff)
822 l = len(m.srtpMasterKeyIdentifier)
823 z[8] = byte(l)
824 copy(z[9:], []byte(m.srtpMasterKeyIdentifier))
825 z = z[9+l:]
826 }
David Benjamin61f95272014-11-25 01:55:35 -0500827 if m.sctList != nil {
828 z[0] = byte(extensionSignedCertificateTimestamp >> 8)
829 z[1] = byte(extensionSignedCertificateTimestamp & 0xff)
830 l := len(m.sctList)
831 z[2] = byte(l >> 8)
832 z[3] = byte(l & 0xff)
833 copy(z[4:], m.sctList)
834 z = z[4+l:]
835 }
Adam Langley09505632015-07-30 18:10:13 -0700836 if l := len(m.customExtension); l > 0 {
837 z[0] = byte(extensionCustom >> 8)
838 z[1] = byte(extensionCustom & 0xff)
839 z[2] = byte(l >> 8)
840 z[3] = byte(l & 0xff)
841 copy(z[4:], []byte(m.customExtension))
David Benjamin399e7c92015-07-30 23:01:27 -0400842 z = z[4+l:]
Adam Langley09505632015-07-30 18:10:13 -0700843 }
David Benjamin76c2efc2015-08-31 14:24:29 -0400844 if m.nextProtoNeg && m.npnLast {
845 z[0] = byte(extensionNextProtoNeg >> 8)
846 z[1] = byte(extensionNextProtoNeg & 0xff)
847 z[2] = byte(nextProtoLen >> 8)
848 z[3] = byte(nextProtoLen)
849 z = z[4:]
850
851 for _, v := range m.nextProtos {
852 l := len(v)
853 if l > 255 {
854 l = 255
855 }
856 z[0] = byte(l)
857 copy(z[1:], []byte(v[0:l]))
858 z = z[1+l:]
859 }
860 }
Adam Langley95c29f32014-06-20 12:00:00 -0700861
862 m.raw = x
863
864 return x
865}
866
867func (m *serverHelloMsg) unmarshal(data []byte) bool {
868 if len(data) < 42 {
869 return false
870 }
871 m.raw = data
David Benjamin83c0bc92014-08-04 01:23:53 -0400872 m.vers = wireToVersion(uint16(data[4])<<8|uint16(data[5]), m.isDTLS)
Adam Langley95c29f32014-06-20 12:00:00 -0700873 m.random = data[6:38]
874 sessionIdLen := int(data[38])
875 if sessionIdLen > 32 || len(data) < 39+sessionIdLen {
876 return false
877 }
878 m.sessionId = data[39 : 39+sessionIdLen]
879 data = data[39+sessionIdLen:]
880 if len(data) < 3 {
881 return false
882 }
883 m.cipherSuite = uint16(data[0])<<8 | uint16(data[1])
884 m.compressionMethod = data[2]
885 data = data[3:]
886
887 m.nextProtoNeg = false
888 m.nextProtos = nil
889 m.ocspStapling = false
890 m.ticketSupported = false
David Benjaminfa055a22014-09-15 16:51:51 -0400891 m.alpnProtocol = ""
Adam Langleyefb0e162015-07-09 11:35:04 -0700892 m.alpnProtocolEmpty = false
Adam Langley75712922014-10-10 16:23:43 -0700893 m.extendedMasterSecret = false
Adam Langley09505632015-07-30 18:10:13 -0700894 m.customExtension = ""
Adam Langley95c29f32014-06-20 12:00:00 -0700895
896 if len(data) == 0 {
897 // ServerHello is optionally followed by extension data
898 return true
899 }
900 if len(data) < 2 {
901 return false
902 }
903
904 extensionsLength := int(data[0])<<8 | int(data[1])
905 data = data[2:]
906 if len(data) != extensionsLength {
907 return false
908 }
909
910 for len(data) != 0 {
911 if len(data) < 4 {
912 return false
913 }
914 extension := uint16(data[0])<<8 | uint16(data[1])
915 length := int(data[2])<<8 | int(data[3])
916 data = data[4:]
917 if len(data) < length {
918 return false
919 }
920
921 switch extension {
922 case extensionNextProtoNeg:
923 m.nextProtoNeg = true
924 d := data[:length]
925 for len(d) > 0 {
926 l := int(d[0])
927 d = d[1:]
928 if l == 0 || l > len(d) {
929 return false
930 }
931 m.nextProtos = append(m.nextProtos, string(d[:l]))
932 d = d[l:]
933 }
934 case extensionStatusRequest:
935 if length > 0 {
936 return false
937 }
938 m.ocspStapling = true
939 case extensionSessionTicket:
940 if length > 0 {
941 return false
942 }
943 m.ticketSupported = true
944 case extensionRenegotiationInfo:
Adam Langley2ae77d22014-10-28 17:29:33 -0700945 if length < 1 || length != int(data[0])+1 {
Adam Langley95c29f32014-06-20 12:00:00 -0700946 return false
947 }
Adam Langley2ae77d22014-10-28 17:29:33 -0700948 m.secureRenegotiation = data[1:length]
David Benjaminfa055a22014-09-15 16:51:51 -0400949 case extensionALPN:
950 d := data[:length]
951 if len(d) < 3 {
952 return false
953 }
954 l := int(d[0])<<8 | int(d[1])
955 if l != len(d)-2 {
956 return false
957 }
958 d = d[2:]
959 l = int(d[0])
960 if l != len(d)-1 {
961 return false
962 }
963 d = d[1:]
964 m.alpnProtocol = string(d)
Adam Langleyefb0e162015-07-09 11:35:04 -0700965 m.alpnProtocolEmpty = len(d) == 0
David Benjamind30a9902014-08-24 01:44:23 -0400966 case extensionChannelID:
967 if length > 0 {
968 return false
969 }
970 m.channelIDRequested = true
Adam Langley75712922014-10-10 16:23:43 -0700971 case extensionExtendedMasterSecret:
972 if length != 0 {
973 return false
974 }
975 m.extendedMasterSecret = true
David Benjaminca6c8262014-11-15 19:06:08 -0500976 case extensionUseSRTP:
977 if length < 2+2+1 {
978 return false
979 }
980 if data[0] != 0 || data[1] != 2 {
981 return false
982 }
983 m.srtpProtectionProfile = uint16(data[2])<<8 | uint16(data[3])
984 d := data[4:length]
985 l := int(d[0])
986 if l != len(d)-1 {
987 return false
988 }
989 m.srtpMasterKeyIdentifier = string(d[1:])
David Benjamin61f95272014-11-25 01:55:35 -0500990 case extensionSignedCertificateTimestamp:
Paul Lietar4fac72e2015-09-09 13:44:55 +0100991 m.sctList = data[:length]
Adam Langley09505632015-07-30 18:10:13 -0700992 case extensionCustom:
993 m.customExtension = string(data[:length])
Adam Langley95c29f32014-06-20 12:00:00 -0700994 }
995 data = data[length:]
996 }
997
998 return true
999}
1000
1001type certificateMsg struct {
1002 raw []byte
1003 certificates [][]byte
1004}
1005
Adam Langley95c29f32014-06-20 12:00:00 -07001006func (m *certificateMsg) marshal() (x []byte) {
1007 if m.raw != nil {
1008 return m.raw
1009 }
1010
1011 var i int
1012 for _, slice := range m.certificates {
1013 i += len(slice)
1014 }
1015
1016 length := 3 + 3*len(m.certificates) + i
1017 x = make([]byte, 4+length)
1018 x[0] = typeCertificate
1019 x[1] = uint8(length >> 16)
1020 x[2] = uint8(length >> 8)
1021 x[3] = uint8(length)
1022
1023 certificateOctets := length - 3
1024 x[4] = uint8(certificateOctets >> 16)
1025 x[5] = uint8(certificateOctets >> 8)
1026 x[6] = uint8(certificateOctets)
1027
1028 y := x[7:]
1029 for _, slice := range m.certificates {
1030 y[0] = uint8(len(slice) >> 16)
1031 y[1] = uint8(len(slice) >> 8)
1032 y[2] = uint8(len(slice))
1033 copy(y[3:], slice)
1034 y = y[3+len(slice):]
1035 }
1036
1037 m.raw = x
1038 return
1039}
1040
1041func (m *certificateMsg) unmarshal(data []byte) bool {
1042 if len(data) < 7 {
1043 return false
1044 }
1045
1046 m.raw = data
1047 certsLen := uint32(data[4])<<16 | uint32(data[5])<<8 | uint32(data[6])
1048 if uint32(len(data)) != certsLen+7 {
1049 return false
1050 }
1051
1052 numCerts := 0
1053 d := data[7:]
1054 for certsLen > 0 {
1055 if len(d) < 4 {
1056 return false
1057 }
1058 certLen := uint32(d[0])<<16 | uint32(d[1])<<8 | uint32(d[2])
1059 if uint32(len(d)) < 3+certLen {
1060 return false
1061 }
1062 d = d[3+certLen:]
1063 certsLen -= 3 + certLen
1064 numCerts++
1065 }
1066
1067 m.certificates = make([][]byte, numCerts)
1068 d = data[7:]
1069 for i := 0; i < numCerts; i++ {
1070 certLen := uint32(d[0])<<16 | uint32(d[1])<<8 | uint32(d[2])
1071 m.certificates[i] = d[3 : 3+certLen]
1072 d = d[3+certLen:]
1073 }
1074
1075 return true
1076}
1077
1078type serverKeyExchangeMsg struct {
1079 raw []byte
1080 key []byte
1081}
1082
Adam Langley95c29f32014-06-20 12:00:00 -07001083func (m *serverKeyExchangeMsg) marshal() []byte {
1084 if m.raw != nil {
1085 return m.raw
1086 }
1087 length := len(m.key)
1088 x := make([]byte, length+4)
1089 x[0] = typeServerKeyExchange
1090 x[1] = uint8(length >> 16)
1091 x[2] = uint8(length >> 8)
1092 x[3] = uint8(length)
1093 copy(x[4:], m.key)
1094
1095 m.raw = x
1096 return x
1097}
1098
1099func (m *serverKeyExchangeMsg) unmarshal(data []byte) bool {
1100 m.raw = data
1101 if len(data) < 4 {
1102 return false
1103 }
1104 m.key = data[4:]
1105 return true
1106}
1107
1108type certificateStatusMsg struct {
1109 raw []byte
1110 statusType uint8
1111 response []byte
1112}
1113
Adam Langley95c29f32014-06-20 12:00:00 -07001114func (m *certificateStatusMsg) marshal() []byte {
1115 if m.raw != nil {
1116 return m.raw
1117 }
1118
1119 var x []byte
1120 if m.statusType == statusTypeOCSP {
1121 x = make([]byte, 4+4+len(m.response))
1122 x[0] = typeCertificateStatus
1123 l := len(m.response) + 4
1124 x[1] = byte(l >> 16)
1125 x[2] = byte(l >> 8)
1126 x[3] = byte(l)
1127 x[4] = statusTypeOCSP
1128
1129 l -= 4
1130 x[5] = byte(l >> 16)
1131 x[6] = byte(l >> 8)
1132 x[7] = byte(l)
1133 copy(x[8:], m.response)
1134 } else {
1135 x = []byte{typeCertificateStatus, 0, 0, 1, m.statusType}
1136 }
1137
1138 m.raw = x
1139 return x
1140}
1141
1142func (m *certificateStatusMsg) unmarshal(data []byte) bool {
1143 m.raw = data
1144 if len(data) < 5 {
1145 return false
1146 }
1147 m.statusType = data[4]
1148
1149 m.response = nil
1150 if m.statusType == statusTypeOCSP {
1151 if len(data) < 8 {
1152 return false
1153 }
1154 respLen := uint32(data[5])<<16 | uint32(data[6])<<8 | uint32(data[7])
1155 if uint32(len(data)) != 4+4+respLen {
1156 return false
1157 }
1158 m.response = data[8:]
1159 }
1160 return true
1161}
1162
1163type serverHelloDoneMsg struct{}
1164
Adam Langley95c29f32014-06-20 12:00:00 -07001165func (m *serverHelloDoneMsg) marshal() []byte {
1166 x := make([]byte, 4)
1167 x[0] = typeServerHelloDone
1168 return x
1169}
1170
1171func (m *serverHelloDoneMsg) unmarshal(data []byte) bool {
1172 return len(data) == 4
1173}
1174
1175type clientKeyExchangeMsg struct {
1176 raw []byte
1177 ciphertext []byte
1178}
1179
Adam Langley95c29f32014-06-20 12:00:00 -07001180func (m *clientKeyExchangeMsg) marshal() []byte {
1181 if m.raw != nil {
1182 return m.raw
1183 }
1184 length := len(m.ciphertext)
1185 x := make([]byte, length+4)
1186 x[0] = typeClientKeyExchange
1187 x[1] = uint8(length >> 16)
1188 x[2] = uint8(length >> 8)
1189 x[3] = uint8(length)
1190 copy(x[4:], m.ciphertext)
1191
1192 m.raw = x
1193 return x
1194}
1195
1196func (m *clientKeyExchangeMsg) unmarshal(data []byte) bool {
1197 m.raw = data
1198 if len(data) < 4 {
1199 return false
1200 }
1201 l := int(data[1])<<16 | int(data[2])<<8 | int(data[3])
1202 if l != len(data)-4 {
1203 return false
1204 }
1205 m.ciphertext = data[4:]
1206 return true
1207}
1208
1209type finishedMsg struct {
1210 raw []byte
1211 verifyData []byte
1212}
1213
Adam Langley95c29f32014-06-20 12:00:00 -07001214func (m *finishedMsg) marshal() (x []byte) {
1215 if m.raw != nil {
1216 return m.raw
1217 }
1218
1219 x = make([]byte, 4+len(m.verifyData))
1220 x[0] = typeFinished
1221 x[3] = byte(len(m.verifyData))
1222 copy(x[4:], m.verifyData)
1223 m.raw = x
1224 return
1225}
1226
1227func (m *finishedMsg) unmarshal(data []byte) bool {
1228 m.raw = data
1229 if len(data) < 4 {
1230 return false
1231 }
1232 m.verifyData = data[4:]
1233 return true
1234}
1235
1236type nextProtoMsg struct {
1237 raw []byte
1238 proto string
1239}
1240
Adam Langley95c29f32014-06-20 12:00:00 -07001241func (m *nextProtoMsg) marshal() []byte {
1242 if m.raw != nil {
1243 return m.raw
1244 }
1245 l := len(m.proto)
1246 if l > 255 {
1247 l = 255
1248 }
1249
1250 padding := 32 - (l+2)%32
1251 length := l + padding + 2
1252 x := make([]byte, length+4)
1253 x[0] = typeNextProtocol
1254 x[1] = uint8(length >> 16)
1255 x[2] = uint8(length >> 8)
1256 x[3] = uint8(length)
1257
1258 y := x[4:]
1259 y[0] = byte(l)
1260 copy(y[1:], []byte(m.proto[0:l]))
1261 y = y[1+l:]
1262 y[0] = byte(padding)
1263
1264 m.raw = x
1265
1266 return x
1267}
1268
1269func (m *nextProtoMsg) unmarshal(data []byte) bool {
1270 m.raw = data
1271
1272 if len(data) < 5 {
1273 return false
1274 }
1275 data = data[4:]
1276 protoLen := int(data[0])
1277 data = data[1:]
1278 if len(data) < protoLen {
1279 return false
1280 }
1281 m.proto = string(data[0:protoLen])
1282 data = data[protoLen:]
1283
1284 if len(data) < 1 {
1285 return false
1286 }
1287 paddingLen := int(data[0])
1288 data = data[1:]
1289 if len(data) != paddingLen {
1290 return false
1291 }
1292
1293 return true
1294}
1295
1296type certificateRequestMsg struct {
1297 raw []byte
Nick Harper60edffd2016-06-21 15:19:24 -07001298 // hasSignatureAlgorithm indicates whether this message includes a list
Adam Langley95c29f32014-06-20 12:00:00 -07001299 // of signature and hash functions. This change was introduced with TLS
1300 // 1.2.
Nick Harper60edffd2016-06-21 15:19:24 -07001301 hasSignatureAlgorithm bool
Adam Langley95c29f32014-06-20 12:00:00 -07001302
1303 certificateTypes []byte
Nick Harper60edffd2016-06-21 15:19:24 -07001304 signatureAlgorithms []signatureAlgorithm
Adam Langley95c29f32014-06-20 12:00:00 -07001305 certificateAuthorities [][]byte
1306}
1307
Adam Langley95c29f32014-06-20 12:00:00 -07001308func (m *certificateRequestMsg) marshal() (x []byte) {
1309 if m.raw != nil {
1310 return m.raw
1311 }
1312
1313 // See http://tools.ietf.org/html/rfc4346#section-7.4.4
1314 length := 1 + len(m.certificateTypes) + 2
1315 casLength := 0
1316 for _, ca := range m.certificateAuthorities {
1317 casLength += 2 + len(ca)
1318 }
1319 length += casLength
1320
Nick Harper60edffd2016-06-21 15:19:24 -07001321 if m.hasSignatureAlgorithm {
1322 length += 2 + 2*len(m.signatureAlgorithms)
Adam Langley95c29f32014-06-20 12:00:00 -07001323 }
1324
1325 x = make([]byte, 4+length)
1326 x[0] = typeCertificateRequest
1327 x[1] = uint8(length >> 16)
1328 x[2] = uint8(length >> 8)
1329 x[3] = uint8(length)
1330
1331 x[4] = uint8(len(m.certificateTypes))
1332
1333 copy(x[5:], m.certificateTypes)
1334 y := x[5+len(m.certificateTypes):]
1335
Nick Harper60edffd2016-06-21 15:19:24 -07001336 if m.hasSignatureAlgorithm {
1337 n := len(m.signatureAlgorithms) * 2
Adam Langley95c29f32014-06-20 12:00:00 -07001338 y[0] = uint8(n >> 8)
1339 y[1] = uint8(n)
1340 y = y[2:]
Nick Harper60edffd2016-06-21 15:19:24 -07001341 for _, sigAlg := range m.signatureAlgorithms {
1342 y[0] = byte(sigAlg >> 8)
1343 y[1] = byte(sigAlg)
Adam Langley95c29f32014-06-20 12:00:00 -07001344 y = y[2:]
1345 }
1346 }
1347
1348 y[0] = uint8(casLength >> 8)
1349 y[1] = uint8(casLength)
1350 y = y[2:]
1351 for _, ca := range m.certificateAuthorities {
1352 y[0] = uint8(len(ca) >> 8)
1353 y[1] = uint8(len(ca))
1354 y = y[2:]
1355 copy(y, ca)
1356 y = y[len(ca):]
1357 }
1358
1359 m.raw = x
1360 return
1361}
1362
1363func (m *certificateRequestMsg) unmarshal(data []byte) bool {
1364 m.raw = data
1365
1366 if len(data) < 5 {
1367 return false
1368 }
1369
1370 length := uint32(data[1])<<16 | uint32(data[2])<<8 | uint32(data[3])
1371 if uint32(len(data))-4 != length {
1372 return false
1373 }
1374
1375 numCertTypes := int(data[4])
1376 data = data[5:]
1377 if numCertTypes == 0 || len(data) <= numCertTypes {
1378 return false
1379 }
1380
1381 m.certificateTypes = make([]byte, numCertTypes)
1382 if copy(m.certificateTypes, data) != numCertTypes {
1383 return false
1384 }
1385
1386 data = data[numCertTypes:]
1387
Nick Harper60edffd2016-06-21 15:19:24 -07001388 if m.hasSignatureAlgorithm {
Adam Langley95c29f32014-06-20 12:00:00 -07001389 if len(data) < 2 {
1390 return false
1391 }
Nick Harper60edffd2016-06-21 15:19:24 -07001392 sigAlgsLen := uint16(data[0])<<8 | uint16(data[1])
Adam Langley95c29f32014-06-20 12:00:00 -07001393 data = data[2:]
Nick Harper60edffd2016-06-21 15:19:24 -07001394 if sigAlgsLen&1 != 0 {
Adam Langley95c29f32014-06-20 12:00:00 -07001395 return false
1396 }
Nick Harper60edffd2016-06-21 15:19:24 -07001397 if len(data) < int(sigAlgsLen) {
Adam Langley95c29f32014-06-20 12:00:00 -07001398 return false
1399 }
Nick Harper60edffd2016-06-21 15:19:24 -07001400 numSigAlgs := sigAlgsLen / 2
1401 m.signatureAlgorithms = make([]signatureAlgorithm, numSigAlgs)
1402 for i := range m.signatureAlgorithms {
1403 m.signatureAlgorithms[i] = signatureAlgorithm(data[0])<<8 | signatureAlgorithm(data[1])
Adam Langley95c29f32014-06-20 12:00:00 -07001404 data = data[2:]
1405 }
1406 }
1407
1408 if len(data) < 2 {
1409 return false
1410 }
1411 casLength := uint16(data[0])<<8 | uint16(data[1])
1412 data = data[2:]
1413 if len(data) < int(casLength) {
1414 return false
1415 }
1416 cas := make([]byte, casLength)
1417 copy(cas, data)
1418 data = data[casLength:]
1419
1420 m.certificateAuthorities = nil
1421 for len(cas) > 0 {
1422 if len(cas) < 2 {
1423 return false
1424 }
1425 caLen := uint16(cas[0])<<8 | uint16(cas[1])
1426 cas = cas[2:]
1427
1428 if len(cas) < int(caLen) {
1429 return false
1430 }
1431
1432 m.certificateAuthorities = append(m.certificateAuthorities, cas[:caLen])
1433 cas = cas[caLen:]
1434 }
1435 if len(data) > 0 {
1436 return false
1437 }
1438
1439 return true
1440}
1441
1442type certificateVerifyMsg struct {
Nick Harper60edffd2016-06-21 15:19:24 -07001443 raw []byte
1444 hasSignatureAlgorithm bool
1445 signatureAlgorithm signatureAlgorithm
1446 signature []byte
Adam Langley95c29f32014-06-20 12:00:00 -07001447}
1448
Adam Langley95c29f32014-06-20 12:00:00 -07001449func (m *certificateVerifyMsg) marshal() (x []byte) {
1450 if m.raw != nil {
1451 return m.raw
1452 }
1453
1454 // See http://tools.ietf.org/html/rfc4346#section-7.4.8
1455 siglength := len(m.signature)
1456 length := 2 + siglength
Nick Harper60edffd2016-06-21 15:19:24 -07001457 if m.hasSignatureAlgorithm {
Adam Langley95c29f32014-06-20 12:00:00 -07001458 length += 2
1459 }
1460 x = make([]byte, 4+length)
1461 x[0] = typeCertificateVerify
1462 x[1] = uint8(length >> 16)
1463 x[2] = uint8(length >> 8)
1464 x[3] = uint8(length)
1465 y := x[4:]
Nick Harper60edffd2016-06-21 15:19:24 -07001466 if m.hasSignatureAlgorithm {
1467 y[0] = byte(m.signatureAlgorithm >> 8)
1468 y[1] = byte(m.signatureAlgorithm)
Adam Langley95c29f32014-06-20 12:00:00 -07001469 y = y[2:]
1470 }
1471 y[0] = uint8(siglength >> 8)
1472 y[1] = uint8(siglength)
1473 copy(y[2:], m.signature)
1474
1475 m.raw = x
1476
1477 return
1478}
1479
1480func (m *certificateVerifyMsg) unmarshal(data []byte) bool {
1481 m.raw = data
1482
1483 if len(data) < 6 {
1484 return false
1485 }
1486
1487 length := uint32(data[1])<<16 | uint32(data[2])<<8 | uint32(data[3])
1488 if uint32(len(data))-4 != length {
1489 return false
1490 }
1491
1492 data = data[4:]
Nick Harper60edffd2016-06-21 15:19:24 -07001493 if m.hasSignatureAlgorithm {
1494 m.signatureAlgorithm = signatureAlgorithm(data[0])<<8 | signatureAlgorithm(data[1])
Adam Langley95c29f32014-06-20 12:00:00 -07001495 data = data[2:]
1496 }
1497
1498 if len(data) < 2 {
1499 return false
1500 }
1501 siglength := int(data[0])<<8 + int(data[1])
1502 data = data[2:]
1503 if len(data) != siglength {
1504 return false
1505 }
1506
1507 m.signature = data
1508
1509 return true
1510}
1511
1512type newSessionTicketMsg struct {
1513 raw []byte
1514 ticket []byte
1515}
1516
Adam Langley95c29f32014-06-20 12:00:00 -07001517func (m *newSessionTicketMsg) marshal() (x []byte) {
1518 if m.raw != nil {
1519 return m.raw
1520 }
1521
1522 // See http://tools.ietf.org/html/rfc5077#section-3.3
1523 ticketLen := len(m.ticket)
1524 length := 2 + 4 + ticketLen
1525 x = make([]byte, 4+length)
1526 x[0] = typeNewSessionTicket
1527 x[1] = uint8(length >> 16)
1528 x[2] = uint8(length >> 8)
1529 x[3] = uint8(length)
1530 x[8] = uint8(ticketLen >> 8)
1531 x[9] = uint8(ticketLen)
1532 copy(x[10:], m.ticket)
1533
1534 m.raw = x
1535
1536 return
1537}
1538
1539func (m *newSessionTicketMsg) unmarshal(data []byte) bool {
1540 m.raw = data
1541
1542 if len(data) < 10 {
1543 return false
1544 }
1545
1546 length := uint32(data[1])<<16 | uint32(data[2])<<8 | uint32(data[3])
1547 if uint32(len(data))-4 != length {
1548 return false
1549 }
1550
1551 ticketLen := int(data[8])<<8 + int(data[9])
1552 if len(data)-10 != ticketLen {
1553 return false
1554 }
1555
1556 m.ticket = data[10:]
1557
1558 return true
1559}
1560
David Benjamind86c7672014-08-02 04:07:12 -04001561type v2ClientHelloMsg struct {
1562 raw []byte
1563 vers uint16
1564 cipherSuites []uint16
1565 sessionId []byte
1566 challenge []byte
1567}
1568
David Benjamind86c7672014-08-02 04:07:12 -04001569func (m *v2ClientHelloMsg) marshal() []byte {
1570 if m.raw != nil {
1571 return m.raw
1572 }
1573
1574 length := 1 + 2 + 2 + 2 + 2 + len(m.cipherSuites)*3 + len(m.sessionId) + len(m.challenge)
1575
1576 x := make([]byte, length)
1577 x[0] = 1
1578 x[1] = uint8(m.vers >> 8)
1579 x[2] = uint8(m.vers)
1580 x[3] = uint8((len(m.cipherSuites) * 3) >> 8)
1581 x[4] = uint8(len(m.cipherSuites) * 3)
1582 x[5] = uint8(len(m.sessionId) >> 8)
1583 x[6] = uint8(len(m.sessionId))
1584 x[7] = uint8(len(m.challenge) >> 8)
1585 x[8] = uint8(len(m.challenge))
1586 y := x[9:]
1587 for i, spec := range m.cipherSuites {
1588 y[i*3] = 0
1589 y[i*3+1] = uint8(spec >> 8)
1590 y[i*3+2] = uint8(spec)
1591 }
1592 y = y[len(m.cipherSuites)*3:]
1593 copy(y, m.sessionId)
1594 y = y[len(m.sessionId):]
1595 copy(y, m.challenge)
1596
1597 m.raw = x
1598
1599 return x
1600}
1601
David Benjamin83c0bc92014-08-04 01:23:53 -04001602type helloVerifyRequestMsg struct {
1603 raw []byte
1604 vers uint16
1605 cookie []byte
1606}
1607
David Benjamin83c0bc92014-08-04 01:23:53 -04001608func (m *helloVerifyRequestMsg) marshal() []byte {
1609 if m.raw != nil {
1610 return m.raw
1611 }
1612
1613 length := 2 + 1 + len(m.cookie)
1614
1615 x := make([]byte, 4+length)
1616 x[0] = typeHelloVerifyRequest
1617 x[1] = uint8(length >> 16)
1618 x[2] = uint8(length >> 8)
1619 x[3] = uint8(length)
1620 vers := versionToWire(m.vers, true)
1621 x[4] = uint8(vers >> 8)
1622 x[5] = uint8(vers)
1623 x[6] = uint8(len(m.cookie))
1624 copy(x[7:7+len(m.cookie)], m.cookie)
1625
1626 return x
1627}
1628
1629func (m *helloVerifyRequestMsg) unmarshal(data []byte) bool {
1630 if len(data) < 4+2+1 {
1631 return false
1632 }
1633 m.raw = data
1634 m.vers = wireToVersion(uint16(data[4])<<8|uint16(data[5]), true)
1635 cookieLen := int(data[6])
1636 if cookieLen > 32 || len(data) != 7+cookieLen {
1637 return false
1638 }
1639 m.cookie = data[7 : 7+cookieLen]
1640
1641 return true
1642}
1643
David Benjamin24599a82016-06-30 18:56:53 -04001644type channelIDMsg struct {
David Benjamind30a9902014-08-24 01:44:23 -04001645 raw []byte
1646 channelID []byte
1647}
1648
David Benjamin24599a82016-06-30 18:56:53 -04001649func (m *channelIDMsg) marshal() []byte {
David Benjamind30a9902014-08-24 01:44:23 -04001650 if m.raw != nil {
1651 return m.raw
1652 }
1653
1654 length := 2 + 2 + len(m.channelID)
1655
1656 x := make([]byte, 4+length)
David Benjamin24599a82016-06-30 18:56:53 -04001657 x[0] = typeChannelID
David Benjamind30a9902014-08-24 01:44:23 -04001658 x[1] = uint8(length >> 16)
1659 x[2] = uint8(length >> 8)
1660 x[3] = uint8(length)
1661 x[4] = uint8(extensionChannelID >> 8)
1662 x[5] = uint8(extensionChannelID & 0xff)
1663 x[6] = uint8(len(m.channelID) >> 8)
1664 x[7] = uint8(len(m.channelID) & 0xff)
1665 copy(x[8:], m.channelID)
1666
1667 return x
1668}
1669
David Benjamin24599a82016-06-30 18:56:53 -04001670func (m *channelIDMsg) unmarshal(data []byte) bool {
David Benjamind30a9902014-08-24 01:44:23 -04001671 if len(data) != 4+2+2+128 {
1672 return false
1673 }
1674 m.raw = data
1675 if (uint16(data[4])<<8)|uint16(data[5]) != extensionChannelID {
1676 return false
1677 }
1678 if int(data[6])<<8|int(data[7]) != 128 {
1679 return false
1680 }
1681 m.channelID = data[4+2+2:]
1682
1683 return true
1684}
1685
Adam Langley2ae77d22014-10-28 17:29:33 -07001686type helloRequestMsg struct {
1687}
1688
1689func (*helloRequestMsg) marshal() []byte {
1690 return []byte{typeHelloRequest, 0, 0, 0}
1691}
1692
1693func (*helloRequestMsg) unmarshal(data []byte) bool {
1694 return len(data) == 4
1695}
1696
Adam Langley95c29f32014-06-20 12:00:00 -07001697func eqUint16s(x, y []uint16) bool {
1698 if len(x) != len(y) {
1699 return false
1700 }
1701 for i, v := range x {
1702 if y[i] != v {
1703 return false
1704 }
1705 }
1706 return true
1707}
1708
1709func eqCurveIDs(x, y []CurveID) bool {
1710 if len(x) != len(y) {
1711 return false
1712 }
1713 for i, v := range x {
1714 if y[i] != v {
1715 return false
1716 }
1717 }
1718 return true
1719}
1720
1721func eqStrings(x, y []string) bool {
1722 if len(x) != len(y) {
1723 return false
1724 }
1725 for i, v := range x {
1726 if y[i] != v {
1727 return false
1728 }
1729 }
1730 return true
1731}
1732
1733func eqByteSlices(x, y [][]byte) bool {
1734 if len(x) != len(y) {
1735 return false
1736 }
1737 for i, v := range x {
1738 if !bytes.Equal(v, y[i]) {
1739 return false
1740 }
1741 }
1742 return true
1743}
1744
Nick Harper60edffd2016-06-21 15:19:24 -07001745func eqSignatureAlgorithms(x, y []signatureAlgorithm) bool {
Adam Langley95c29f32014-06-20 12:00:00 -07001746 if len(x) != len(y) {
1747 return false
1748 }
1749 for i, v := range x {
1750 v2 := y[i]
Nick Harper60edffd2016-06-21 15:19:24 -07001751 if v != v2 {
Adam Langley95c29f32014-06-20 12:00:00 -07001752 return false
1753 }
1754 }
1755 return true
1756}