blob: da85e7ac4725936c43c75968e19cae6457ed56cd [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
5package main
6
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
25 signatureAndHashes []signatureAndHash
26 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) &&
59 eqSignatureAndHashes(m.signatureAndHashes, m1.signatureAndHashes) &&
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 }
107 if len(m.signatureAndHashes) > 0 {
108 extensionsLength += 2 + 2*len(m.signatureAndHashes)
109 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 }
284 if len(m.signatureAndHashes) > 0 {
285 // https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
286 z[0] = byte(extensionSignatureAlgorithms >> 8)
287 z[1] = byte(extensionSignatureAlgorithms)
288 l := 2 + 2*len(m.signatureAndHashes)
289 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:]
297 for _, sigAndHash := range m.signatureAndHashes {
298 z[0] = sigAndHash.hash
299 z[1] = sigAndHash.signature
300 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 {
352 // https://tools.ietf.org/html/draft-ietf-tls-session-hash-01
353 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
457 m.signatureAndHashes = 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:]
559 m.signatureAndHashes = make([]signatureAndHash, n)
560 for i := range m.signatureAndHashes {
561 m.signatureAndHashes[i].hash = d[0]
562 m.signatureAndHashes[i].signature = d[1]
563 d = d[2:]
564 }
Adam Langley2ae77d22014-10-28 17:29:33 -0700565 case extensionRenegotiationInfo:
566 if length < 1 || length != int(data[0])+1 {
Adam Langley95c29f32014-06-20 12:00:00 -0700567 return false
568 }
Adam Langley2ae77d22014-10-28 17:29:33 -0700569 m.secureRenegotiation = data[1:length]
David Benjaminfa055a22014-09-15 16:51:51 -0400570 case extensionALPN:
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 stringLen := int(d[0])
581 d = d[1:]
582 if stringLen == 0 || stringLen > len(d) {
583 return false
584 }
585 m.alpnProtocols = append(m.alpnProtocols, string(d[:stringLen]))
586 d = d[stringLen:]
587 }
David Benjamind30a9902014-08-24 01:44:23 -0400588 case extensionChannelID:
589 if length > 0 {
590 return false
591 }
592 m.channelIDSupported = true
Adam Langley75712922014-10-10 16:23:43 -0700593 case extensionExtendedMasterSecret:
594 if length != 0 {
595 return false
596 }
597 m.extendedMasterSecret = true
David Benjaminca6c8262014-11-15 19:06:08 -0500598 case extensionUseSRTP:
599 if length < 2 {
600 return false
601 }
602 l := int(data[0])<<8 | int(data[1])
603 if l > length-2 || l%2 != 0 {
604 return false
605 }
606 n := l / 2
607 m.srtpProtectionProfiles = make([]uint16, n)
608 d := data[2:length]
609 for i := 0; i < n; i++ {
610 m.srtpProtectionProfiles[i] = uint16(d[0])<<8 | uint16(d[1])
611 d = d[2:]
612 }
613 if len(d) < 1 || int(d[0]) != len(d)-1 {
614 return false
615 }
616 m.srtpMasterKeyIdentifier = string(d[1:])
David Benjamin61f95272014-11-25 01:55:35 -0500617 case extensionSignedCertificateTimestamp:
618 if length != 0 {
619 return false
620 }
621 m.sctListSupported = true
Adam Langley09505632015-07-30 18:10:13 -0700622 case extensionCustom:
623 m.customExtension = string(data[:length])
Adam Langley95c29f32014-06-20 12:00:00 -0700624 }
625 data = data[length:]
626 }
627
628 return true
629}
630
631type serverHelloMsg struct {
David Benjaminca6c8262014-11-15 19:06:08 -0500632 raw []byte
633 isDTLS bool
634 vers uint16
635 random []byte
636 sessionId []byte
637 cipherSuite uint16
638 compressionMethod uint8
639 nextProtoNeg bool
640 nextProtos []string
641 ocspStapling bool
642 ticketSupported bool
643 secureRenegotiation []byte
644 alpnProtocol string
Adam Langleyefb0e162015-07-09 11:35:04 -0700645 alpnProtocolEmpty bool
David Benjaminca6c8262014-11-15 19:06:08 -0500646 duplicateExtension bool
647 channelIDRequested bool
648 extendedMasterSecret bool
649 srtpProtectionProfile uint16
650 srtpMasterKeyIdentifier string
David Benjamin61f95272014-11-25 01:55:35 -0500651 sctList []byte
Adam Langley09505632015-07-30 18:10:13 -0700652 customExtension string
David Benjamin76c2efc2015-08-31 14:24:29 -0400653 npnLast bool
Adam Langley95c29f32014-06-20 12:00:00 -0700654}
655
Adam Langley95c29f32014-06-20 12:00:00 -0700656func (m *serverHelloMsg) marshal() []byte {
657 if m.raw != nil {
658 return m.raw
659 }
660
661 length := 38 + len(m.sessionId)
662 numExtensions := 0
663 extensionsLength := 0
664
665 nextProtoLen := 0
666 if m.nextProtoNeg {
667 numExtensions++
668 for _, v := range m.nextProtos {
669 nextProtoLen += len(v)
670 }
671 nextProtoLen += len(m.nextProtos)
672 extensionsLength += nextProtoLen
673 }
674 if m.ocspStapling {
675 numExtensions++
676 }
677 if m.ticketSupported {
678 numExtensions++
679 }
Adam Langley2ae77d22014-10-28 17:29:33 -0700680 if m.secureRenegotiation != nil {
681 extensionsLength += 1 + len(m.secureRenegotiation)
Adam Langley95c29f32014-06-20 12:00:00 -0700682 numExtensions++
683 }
David Benjamin35a7a442014-07-05 00:23:20 -0400684 if m.duplicateExtension {
685 numExtensions += 2
686 }
David Benjamind30a9902014-08-24 01:44:23 -0400687 if m.channelIDRequested {
688 numExtensions++
689 }
Adam Langleyefb0e162015-07-09 11:35:04 -0700690 if alpnLen := len(m.alpnProtocol); alpnLen > 0 || m.alpnProtocolEmpty {
David Benjaminfa055a22014-09-15 16:51:51 -0400691 if alpnLen >= 256 {
692 panic("invalid ALPN protocol")
693 }
694 extensionsLength += 2 + 1 + alpnLen
695 numExtensions++
696 }
Adam Langley75712922014-10-10 16:23:43 -0700697 if m.extendedMasterSecret {
698 numExtensions++
699 }
David Benjaminca6c8262014-11-15 19:06:08 -0500700 if m.srtpProtectionProfile != 0 {
701 extensionsLength += 2 + 2 + 1 + len(m.srtpMasterKeyIdentifier)
702 numExtensions++
703 }
David Benjamin61f95272014-11-25 01:55:35 -0500704 if m.sctList != nil {
705 extensionsLength += len(m.sctList)
706 numExtensions++
707 }
Adam Langley09505632015-07-30 18:10:13 -0700708 if l := len(m.customExtension); l > 0 {
709 extensionsLength += l
710 numExtensions++
711 }
David Benjaminfa055a22014-09-15 16:51:51 -0400712
Adam Langley95c29f32014-06-20 12:00:00 -0700713 if numExtensions > 0 {
714 extensionsLength += 4 * numExtensions
715 length += 2 + extensionsLength
716 }
717
718 x := make([]byte, 4+length)
719 x[0] = typeServerHello
720 x[1] = uint8(length >> 16)
721 x[2] = uint8(length >> 8)
722 x[3] = uint8(length)
David Benjamin83c0bc92014-08-04 01:23:53 -0400723 vers := versionToWire(m.vers, m.isDTLS)
724 x[4] = uint8(vers >> 8)
725 x[5] = uint8(vers)
Adam Langley95c29f32014-06-20 12:00:00 -0700726 copy(x[6:38], m.random)
727 x[38] = uint8(len(m.sessionId))
728 copy(x[39:39+len(m.sessionId)], m.sessionId)
729 z := x[39+len(m.sessionId):]
730 z[0] = uint8(m.cipherSuite >> 8)
731 z[1] = uint8(m.cipherSuite)
732 z[2] = uint8(m.compressionMethod)
733
734 z = z[3:]
735 if numExtensions > 0 {
736 z[0] = byte(extensionsLength >> 8)
737 z[1] = byte(extensionsLength)
738 z = z[2:]
739 }
David Benjamin35a7a442014-07-05 00:23:20 -0400740 if m.duplicateExtension {
741 // Add a duplicate bogus extension at the beginning and end.
742 z[0] = 0xff
743 z[1] = 0xff
744 z = z[4:]
745 }
David Benjamin76c2efc2015-08-31 14:24:29 -0400746 if m.nextProtoNeg && !m.npnLast {
Adam Langley95c29f32014-06-20 12:00:00 -0700747 z[0] = byte(extensionNextProtoNeg >> 8)
748 z[1] = byte(extensionNextProtoNeg & 0xff)
749 z[2] = byte(nextProtoLen >> 8)
750 z[3] = byte(nextProtoLen)
751 z = z[4:]
752
753 for _, v := range m.nextProtos {
754 l := len(v)
755 if l > 255 {
756 l = 255
757 }
758 z[0] = byte(l)
759 copy(z[1:], []byte(v[0:l]))
760 z = z[1+l:]
761 }
762 }
763 if m.ocspStapling {
764 z[0] = byte(extensionStatusRequest >> 8)
765 z[1] = byte(extensionStatusRequest)
766 z = z[4:]
767 }
768 if m.ticketSupported {
769 z[0] = byte(extensionSessionTicket >> 8)
770 z[1] = byte(extensionSessionTicket)
771 z = z[4:]
772 }
Adam Langley2ae77d22014-10-28 17:29:33 -0700773 if m.secureRenegotiation != nil {
Adam Langley95c29f32014-06-20 12:00:00 -0700774 z[0] = byte(extensionRenegotiationInfo >> 8)
775 z[1] = byte(extensionRenegotiationInfo & 0xff)
776 z[2] = 0
Adam Langley2ae77d22014-10-28 17:29:33 -0700777 z[3] = byte(1 + len(m.secureRenegotiation))
778 z[4] = byte(len(m.secureRenegotiation))
Adam Langley95c29f32014-06-20 12:00:00 -0700779 z = z[5:]
Adam Langley2ae77d22014-10-28 17:29:33 -0700780 copy(z, m.secureRenegotiation)
781 z = z[len(m.secureRenegotiation):]
Adam Langley95c29f32014-06-20 12:00:00 -0700782 }
Adam Langleyefb0e162015-07-09 11:35:04 -0700783 if alpnLen := len(m.alpnProtocol); alpnLen > 0 || m.alpnProtocolEmpty {
David Benjaminfa055a22014-09-15 16:51:51 -0400784 z[0] = byte(extensionALPN >> 8)
785 z[1] = byte(extensionALPN & 0xff)
786 l := 2 + 1 + alpnLen
787 z[2] = byte(l >> 8)
788 z[3] = byte(l)
789 l -= 2
790 z[4] = byte(l >> 8)
791 z[5] = byte(l)
792 l -= 1
793 z[6] = byte(l)
794 copy(z[7:], []byte(m.alpnProtocol))
795 z = z[7+alpnLen:]
796 }
David Benjamind30a9902014-08-24 01:44:23 -0400797 if m.channelIDRequested {
798 z[0] = byte(extensionChannelID >> 8)
799 z[1] = byte(extensionChannelID & 0xff)
800 z = z[4:]
801 }
David Benjamin35a7a442014-07-05 00:23:20 -0400802 if m.duplicateExtension {
803 // Add a duplicate bogus extension at the beginning and end.
804 z[0] = 0xff
805 z[1] = 0xff
806 z = z[4:]
807 }
Adam Langley75712922014-10-10 16:23:43 -0700808 if m.extendedMasterSecret {
809 z[0] = byte(extensionExtendedMasterSecret >> 8)
810 z[1] = byte(extensionExtendedMasterSecret & 0xff)
811 z = z[4:]
812 }
David Benjaminca6c8262014-11-15 19:06:08 -0500813 if m.srtpProtectionProfile != 0 {
814 z[0] = byte(extensionUseSRTP >> 8)
815 z[1] = byte(extensionUseSRTP & 0xff)
816 l := 2 + 2 + 1 + len(m.srtpMasterKeyIdentifier)
817 z[2] = byte(l >> 8)
818 z[3] = byte(l & 0xff)
819 z[4] = 0
820 z[5] = 2
821 z[6] = byte(m.srtpProtectionProfile >> 8)
822 z[7] = byte(m.srtpProtectionProfile & 0xff)
823 l = len(m.srtpMasterKeyIdentifier)
824 z[8] = byte(l)
825 copy(z[9:], []byte(m.srtpMasterKeyIdentifier))
826 z = z[9+l:]
827 }
David Benjamin61f95272014-11-25 01:55:35 -0500828 if m.sctList != nil {
829 z[0] = byte(extensionSignedCertificateTimestamp >> 8)
830 z[1] = byte(extensionSignedCertificateTimestamp & 0xff)
831 l := len(m.sctList)
832 z[2] = byte(l >> 8)
833 z[3] = byte(l & 0xff)
834 copy(z[4:], m.sctList)
835 z = z[4+l:]
836 }
Adam Langley09505632015-07-30 18:10:13 -0700837 if l := len(m.customExtension); l > 0 {
838 z[0] = byte(extensionCustom >> 8)
839 z[1] = byte(extensionCustom & 0xff)
840 z[2] = byte(l >> 8)
841 z[3] = byte(l & 0xff)
842 copy(z[4:], []byte(m.customExtension))
David Benjamin399e7c92015-07-30 23:01:27 -0400843 z = z[4+l:]
Adam Langley09505632015-07-30 18:10:13 -0700844 }
David Benjamin76c2efc2015-08-31 14:24:29 -0400845 if m.nextProtoNeg && m.npnLast {
846 z[0] = byte(extensionNextProtoNeg >> 8)
847 z[1] = byte(extensionNextProtoNeg & 0xff)
848 z[2] = byte(nextProtoLen >> 8)
849 z[3] = byte(nextProtoLen)
850 z = z[4:]
851
852 for _, v := range m.nextProtos {
853 l := len(v)
854 if l > 255 {
855 l = 255
856 }
857 z[0] = byte(l)
858 copy(z[1:], []byte(v[0:l]))
859 z = z[1+l:]
860 }
861 }
Adam Langley95c29f32014-06-20 12:00:00 -0700862
863 m.raw = x
864
865 return x
866}
867
868func (m *serverHelloMsg) unmarshal(data []byte) bool {
869 if len(data) < 42 {
870 return false
871 }
872 m.raw = data
David Benjamin83c0bc92014-08-04 01:23:53 -0400873 m.vers = wireToVersion(uint16(data[4])<<8|uint16(data[5]), m.isDTLS)
Adam Langley95c29f32014-06-20 12:00:00 -0700874 m.random = data[6:38]
875 sessionIdLen := int(data[38])
876 if sessionIdLen > 32 || len(data) < 39+sessionIdLen {
877 return false
878 }
879 m.sessionId = data[39 : 39+sessionIdLen]
880 data = data[39+sessionIdLen:]
881 if len(data) < 3 {
882 return false
883 }
884 m.cipherSuite = uint16(data[0])<<8 | uint16(data[1])
885 m.compressionMethod = data[2]
886 data = data[3:]
887
888 m.nextProtoNeg = false
889 m.nextProtos = nil
890 m.ocspStapling = false
891 m.ticketSupported = false
David Benjaminfa055a22014-09-15 16:51:51 -0400892 m.alpnProtocol = ""
Adam Langleyefb0e162015-07-09 11:35:04 -0700893 m.alpnProtocolEmpty = false
Adam Langley75712922014-10-10 16:23:43 -0700894 m.extendedMasterSecret = false
Adam Langley09505632015-07-30 18:10:13 -0700895 m.customExtension = ""
Adam Langley95c29f32014-06-20 12:00:00 -0700896
897 if len(data) == 0 {
898 // ServerHello is optionally followed by extension data
899 return true
900 }
901 if len(data) < 2 {
902 return false
903 }
904
905 extensionsLength := int(data[0])<<8 | int(data[1])
906 data = data[2:]
907 if len(data) != extensionsLength {
908 return false
909 }
910
911 for len(data) != 0 {
912 if len(data) < 4 {
913 return false
914 }
915 extension := uint16(data[0])<<8 | uint16(data[1])
916 length := int(data[2])<<8 | int(data[3])
917 data = data[4:]
918 if len(data) < length {
919 return false
920 }
921
922 switch extension {
923 case extensionNextProtoNeg:
924 m.nextProtoNeg = true
925 d := data[:length]
926 for len(d) > 0 {
927 l := int(d[0])
928 d = d[1:]
929 if l == 0 || l > len(d) {
930 return false
931 }
932 m.nextProtos = append(m.nextProtos, string(d[:l]))
933 d = d[l:]
934 }
935 case extensionStatusRequest:
936 if length > 0 {
937 return false
938 }
939 m.ocspStapling = true
940 case extensionSessionTicket:
941 if length > 0 {
942 return false
943 }
944 m.ticketSupported = true
945 case extensionRenegotiationInfo:
Adam Langley2ae77d22014-10-28 17:29:33 -0700946 if length < 1 || length != int(data[0])+1 {
Adam Langley95c29f32014-06-20 12:00:00 -0700947 return false
948 }
Adam Langley2ae77d22014-10-28 17:29:33 -0700949 m.secureRenegotiation = data[1:length]
David Benjaminfa055a22014-09-15 16:51:51 -0400950 case extensionALPN:
951 d := data[:length]
952 if len(d) < 3 {
953 return false
954 }
955 l := int(d[0])<<8 | int(d[1])
956 if l != len(d)-2 {
957 return false
958 }
959 d = d[2:]
960 l = int(d[0])
961 if l != len(d)-1 {
962 return false
963 }
964 d = d[1:]
965 m.alpnProtocol = string(d)
Adam Langleyefb0e162015-07-09 11:35:04 -0700966 m.alpnProtocolEmpty = len(d) == 0
David Benjamind30a9902014-08-24 01:44:23 -0400967 case extensionChannelID:
968 if length > 0 {
969 return false
970 }
971 m.channelIDRequested = true
Adam Langley75712922014-10-10 16:23:43 -0700972 case extensionExtendedMasterSecret:
973 if length != 0 {
974 return false
975 }
976 m.extendedMasterSecret = true
David Benjaminca6c8262014-11-15 19:06:08 -0500977 case extensionUseSRTP:
978 if length < 2+2+1 {
979 return false
980 }
981 if data[0] != 0 || data[1] != 2 {
982 return false
983 }
984 m.srtpProtectionProfile = uint16(data[2])<<8 | uint16(data[3])
985 d := data[4:length]
986 l := int(d[0])
987 if l != len(d)-1 {
988 return false
989 }
990 m.srtpMasterKeyIdentifier = string(d[1:])
David Benjamin61f95272014-11-25 01:55:35 -0500991 case extensionSignedCertificateTimestamp:
Paul Lietar4fac72e2015-09-09 13:44:55 +0100992 m.sctList = data[:length]
Adam Langley09505632015-07-30 18:10:13 -0700993 case extensionCustom:
994 m.customExtension = string(data[:length])
Adam Langley95c29f32014-06-20 12:00:00 -0700995 }
996 data = data[length:]
997 }
998
999 return true
1000}
1001
1002type certificateMsg struct {
1003 raw []byte
1004 certificates [][]byte
1005}
1006
Adam Langley95c29f32014-06-20 12:00:00 -07001007func (m *certificateMsg) marshal() (x []byte) {
1008 if m.raw != nil {
1009 return m.raw
1010 }
1011
1012 var i int
1013 for _, slice := range m.certificates {
1014 i += len(slice)
1015 }
1016
1017 length := 3 + 3*len(m.certificates) + i
1018 x = make([]byte, 4+length)
1019 x[0] = typeCertificate
1020 x[1] = uint8(length >> 16)
1021 x[2] = uint8(length >> 8)
1022 x[3] = uint8(length)
1023
1024 certificateOctets := length - 3
1025 x[4] = uint8(certificateOctets >> 16)
1026 x[5] = uint8(certificateOctets >> 8)
1027 x[6] = uint8(certificateOctets)
1028
1029 y := x[7:]
1030 for _, slice := range m.certificates {
1031 y[0] = uint8(len(slice) >> 16)
1032 y[1] = uint8(len(slice) >> 8)
1033 y[2] = uint8(len(slice))
1034 copy(y[3:], slice)
1035 y = y[3+len(slice):]
1036 }
1037
1038 m.raw = x
1039 return
1040}
1041
1042func (m *certificateMsg) unmarshal(data []byte) bool {
1043 if len(data) < 7 {
1044 return false
1045 }
1046
1047 m.raw = data
1048 certsLen := uint32(data[4])<<16 | uint32(data[5])<<8 | uint32(data[6])
1049 if uint32(len(data)) != certsLen+7 {
1050 return false
1051 }
1052
1053 numCerts := 0
1054 d := data[7:]
1055 for certsLen > 0 {
1056 if len(d) < 4 {
1057 return false
1058 }
1059 certLen := uint32(d[0])<<16 | uint32(d[1])<<8 | uint32(d[2])
1060 if uint32(len(d)) < 3+certLen {
1061 return false
1062 }
1063 d = d[3+certLen:]
1064 certsLen -= 3 + certLen
1065 numCerts++
1066 }
1067
1068 m.certificates = make([][]byte, numCerts)
1069 d = data[7:]
1070 for i := 0; i < numCerts; i++ {
1071 certLen := uint32(d[0])<<16 | uint32(d[1])<<8 | uint32(d[2])
1072 m.certificates[i] = d[3 : 3+certLen]
1073 d = d[3+certLen:]
1074 }
1075
1076 return true
1077}
1078
1079type serverKeyExchangeMsg struct {
1080 raw []byte
1081 key []byte
1082}
1083
Adam Langley95c29f32014-06-20 12:00:00 -07001084func (m *serverKeyExchangeMsg) marshal() []byte {
1085 if m.raw != nil {
1086 return m.raw
1087 }
1088 length := len(m.key)
1089 x := make([]byte, length+4)
1090 x[0] = typeServerKeyExchange
1091 x[1] = uint8(length >> 16)
1092 x[2] = uint8(length >> 8)
1093 x[3] = uint8(length)
1094 copy(x[4:], m.key)
1095
1096 m.raw = x
1097 return x
1098}
1099
1100func (m *serverKeyExchangeMsg) unmarshal(data []byte) bool {
1101 m.raw = data
1102 if len(data) < 4 {
1103 return false
1104 }
1105 m.key = data[4:]
1106 return true
1107}
1108
1109type certificateStatusMsg struct {
1110 raw []byte
1111 statusType uint8
1112 response []byte
1113}
1114
Adam Langley95c29f32014-06-20 12:00:00 -07001115func (m *certificateStatusMsg) marshal() []byte {
1116 if m.raw != nil {
1117 return m.raw
1118 }
1119
1120 var x []byte
1121 if m.statusType == statusTypeOCSP {
1122 x = make([]byte, 4+4+len(m.response))
1123 x[0] = typeCertificateStatus
1124 l := len(m.response) + 4
1125 x[1] = byte(l >> 16)
1126 x[2] = byte(l >> 8)
1127 x[3] = byte(l)
1128 x[4] = statusTypeOCSP
1129
1130 l -= 4
1131 x[5] = byte(l >> 16)
1132 x[6] = byte(l >> 8)
1133 x[7] = byte(l)
1134 copy(x[8:], m.response)
1135 } else {
1136 x = []byte{typeCertificateStatus, 0, 0, 1, m.statusType}
1137 }
1138
1139 m.raw = x
1140 return x
1141}
1142
1143func (m *certificateStatusMsg) unmarshal(data []byte) bool {
1144 m.raw = data
1145 if len(data) < 5 {
1146 return false
1147 }
1148 m.statusType = data[4]
1149
1150 m.response = nil
1151 if m.statusType == statusTypeOCSP {
1152 if len(data) < 8 {
1153 return false
1154 }
1155 respLen := uint32(data[5])<<16 | uint32(data[6])<<8 | uint32(data[7])
1156 if uint32(len(data)) != 4+4+respLen {
1157 return false
1158 }
1159 m.response = data[8:]
1160 }
1161 return true
1162}
1163
1164type serverHelloDoneMsg struct{}
1165
Adam Langley95c29f32014-06-20 12:00:00 -07001166func (m *serverHelloDoneMsg) marshal() []byte {
1167 x := make([]byte, 4)
1168 x[0] = typeServerHelloDone
1169 return x
1170}
1171
1172func (m *serverHelloDoneMsg) unmarshal(data []byte) bool {
1173 return len(data) == 4
1174}
1175
1176type clientKeyExchangeMsg struct {
1177 raw []byte
1178 ciphertext []byte
1179}
1180
Adam Langley95c29f32014-06-20 12:00:00 -07001181func (m *clientKeyExchangeMsg) marshal() []byte {
1182 if m.raw != nil {
1183 return m.raw
1184 }
1185 length := len(m.ciphertext)
1186 x := make([]byte, length+4)
1187 x[0] = typeClientKeyExchange
1188 x[1] = uint8(length >> 16)
1189 x[2] = uint8(length >> 8)
1190 x[3] = uint8(length)
1191 copy(x[4:], m.ciphertext)
1192
1193 m.raw = x
1194 return x
1195}
1196
1197func (m *clientKeyExchangeMsg) unmarshal(data []byte) bool {
1198 m.raw = data
1199 if len(data) < 4 {
1200 return false
1201 }
1202 l := int(data[1])<<16 | int(data[2])<<8 | int(data[3])
1203 if l != len(data)-4 {
1204 return false
1205 }
1206 m.ciphertext = data[4:]
1207 return true
1208}
1209
1210type finishedMsg struct {
1211 raw []byte
1212 verifyData []byte
1213}
1214
Adam Langley95c29f32014-06-20 12:00:00 -07001215func (m *finishedMsg) marshal() (x []byte) {
1216 if m.raw != nil {
1217 return m.raw
1218 }
1219
1220 x = make([]byte, 4+len(m.verifyData))
1221 x[0] = typeFinished
1222 x[3] = byte(len(m.verifyData))
1223 copy(x[4:], m.verifyData)
1224 m.raw = x
1225 return
1226}
1227
1228func (m *finishedMsg) unmarshal(data []byte) bool {
1229 m.raw = data
1230 if len(data) < 4 {
1231 return false
1232 }
1233 m.verifyData = data[4:]
1234 return true
1235}
1236
1237type nextProtoMsg struct {
1238 raw []byte
1239 proto string
1240}
1241
Adam Langley95c29f32014-06-20 12:00:00 -07001242func (m *nextProtoMsg) marshal() []byte {
1243 if m.raw != nil {
1244 return m.raw
1245 }
1246 l := len(m.proto)
1247 if l > 255 {
1248 l = 255
1249 }
1250
1251 padding := 32 - (l+2)%32
1252 length := l + padding + 2
1253 x := make([]byte, length+4)
1254 x[0] = typeNextProtocol
1255 x[1] = uint8(length >> 16)
1256 x[2] = uint8(length >> 8)
1257 x[3] = uint8(length)
1258
1259 y := x[4:]
1260 y[0] = byte(l)
1261 copy(y[1:], []byte(m.proto[0:l]))
1262 y = y[1+l:]
1263 y[0] = byte(padding)
1264
1265 m.raw = x
1266
1267 return x
1268}
1269
1270func (m *nextProtoMsg) unmarshal(data []byte) bool {
1271 m.raw = data
1272
1273 if len(data) < 5 {
1274 return false
1275 }
1276 data = data[4:]
1277 protoLen := int(data[0])
1278 data = data[1:]
1279 if len(data) < protoLen {
1280 return false
1281 }
1282 m.proto = string(data[0:protoLen])
1283 data = data[protoLen:]
1284
1285 if len(data) < 1 {
1286 return false
1287 }
1288 paddingLen := int(data[0])
1289 data = data[1:]
1290 if len(data) != paddingLen {
1291 return false
1292 }
1293
1294 return true
1295}
1296
1297type certificateRequestMsg struct {
1298 raw []byte
1299 // hasSignatureAndHash indicates whether this message includes a list
1300 // of signature and hash functions. This change was introduced with TLS
1301 // 1.2.
1302 hasSignatureAndHash bool
1303
1304 certificateTypes []byte
1305 signatureAndHashes []signatureAndHash
1306 certificateAuthorities [][]byte
1307}
1308
Adam Langley95c29f32014-06-20 12:00:00 -07001309func (m *certificateRequestMsg) marshal() (x []byte) {
1310 if m.raw != nil {
1311 return m.raw
1312 }
1313
1314 // See http://tools.ietf.org/html/rfc4346#section-7.4.4
1315 length := 1 + len(m.certificateTypes) + 2
1316 casLength := 0
1317 for _, ca := range m.certificateAuthorities {
1318 casLength += 2 + len(ca)
1319 }
1320 length += casLength
1321
1322 if m.hasSignatureAndHash {
1323 length += 2 + 2*len(m.signatureAndHashes)
1324 }
1325
1326 x = make([]byte, 4+length)
1327 x[0] = typeCertificateRequest
1328 x[1] = uint8(length >> 16)
1329 x[2] = uint8(length >> 8)
1330 x[3] = uint8(length)
1331
1332 x[4] = uint8(len(m.certificateTypes))
1333
1334 copy(x[5:], m.certificateTypes)
1335 y := x[5+len(m.certificateTypes):]
1336
1337 if m.hasSignatureAndHash {
1338 n := len(m.signatureAndHashes) * 2
1339 y[0] = uint8(n >> 8)
1340 y[1] = uint8(n)
1341 y = y[2:]
1342 for _, sigAndHash := range m.signatureAndHashes {
1343 y[0] = sigAndHash.hash
1344 y[1] = sigAndHash.signature
1345 y = y[2:]
1346 }
1347 }
1348
1349 y[0] = uint8(casLength >> 8)
1350 y[1] = uint8(casLength)
1351 y = y[2:]
1352 for _, ca := range m.certificateAuthorities {
1353 y[0] = uint8(len(ca) >> 8)
1354 y[1] = uint8(len(ca))
1355 y = y[2:]
1356 copy(y, ca)
1357 y = y[len(ca):]
1358 }
1359
1360 m.raw = x
1361 return
1362}
1363
1364func (m *certificateRequestMsg) unmarshal(data []byte) bool {
1365 m.raw = data
1366
1367 if len(data) < 5 {
1368 return false
1369 }
1370
1371 length := uint32(data[1])<<16 | uint32(data[2])<<8 | uint32(data[3])
1372 if uint32(len(data))-4 != length {
1373 return false
1374 }
1375
1376 numCertTypes := int(data[4])
1377 data = data[5:]
1378 if numCertTypes == 0 || len(data) <= numCertTypes {
1379 return false
1380 }
1381
1382 m.certificateTypes = make([]byte, numCertTypes)
1383 if copy(m.certificateTypes, data) != numCertTypes {
1384 return false
1385 }
1386
1387 data = data[numCertTypes:]
1388
1389 if m.hasSignatureAndHash {
1390 if len(data) < 2 {
1391 return false
1392 }
1393 sigAndHashLen := uint16(data[0])<<8 | uint16(data[1])
1394 data = data[2:]
1395 if sigAndHashLen&1 != 0 {
1396 return false
1397 }
1398 if len(data) < int(sigAndHashLen) {
1399 return false
1400 }
1401 numSigAndHash := sigAndHashLen / 2
1402 m.signatureAndHashes = make([]signatureAndHash, numSigAndHash)
1403 for i := range m.signatureAndHashes {
1404 m.signatureAndHashes[i].hash = data[0]
1405 m.signatureAndHashes[i].signature = data[1]
1406 data = data[2:]
1407 }
1408 }
1409
1410 if len(data) < 2 {
1411 return false
1412 }
1413 casLength := uint16(data[0])<<8 | uint16(data[1])
1414 data = data[2:]
1415 if len(data) < int(casLength) {
1416 return false
1417 }
1418 cas := make([]byte, casLength)
1419 copy(cas, data)
1420 data = data[casLength:]
1421
1422 m.certificateAuthorities = nil
1423 for len(cas) > 0 {
1424 if len(cas) < 2 {
1425 return false
1426 }
1427 caLen := uint16(cas[0])<<8 | uint16(cas[1])
1428 cas = cas[2:]
1429
1430 if len(cas) < int(caLen) {
1431 return false
1432 }
1433
1434 m.certificateAuthorities = append(m.certificateAuthorities, cas[:caLen])
1435 cas = cas[caLen:]
1436 }
1437 if len(data) > 0 {
1438 return false
1439 }
1440
1441 return true
1442}
1443
1444type certificateVerifyMsg struct {
1445 raw []byte
1446 hasSignatureAndHash bool
1447 signatureAndHash signatureAndHash
1448 signature []byte
1449}
1450
Adam Langley95c29f32014-06-20 12:00:00 -07001451func (m *certificateVerifyMsg) marshal() (x []byte) {
1452 if m.raw != nil {
1453 return m.raw
1454 }
1455
1456 // See http://tools.ietf.org/html/rfc4346#section-7.4.8
1457 siglength := len(m.signature)
1458 length := 2 + siglength
1459 if m.hasSignatureAndHash {
1460 length += 2
1461 }
1462 x = make([]byte, 4+length)
1463 x[0] = typeCertificateVerify
1464 x[1] = uint8(length >> 16)
1465 x[2] = uint8(length >> 8)
1466 x[3] = uint8(length)
1467 y := x[4:]
1468 if m.hasSignatureAndHash {
1469 y[0] = m.signatureAndHash.hash
1470 y[1] = m.signatureAndHash.signature
1471 y = y[2:]
1472 }
1473 y[0] = uint8(siglength >> 8)
1474 y[1] = uint8(siglength)
1475 copy(y[2:], m.signature)
1476
1477 m.raw = x
1478
1479 return
1480}
1481
1482func (m *certificateVerifyMsg) unmarshal(data []byte) bool {
1483 m.raw = data
1484
1485 if len(data) < 6 {
1486 return false
1487 }
1488
1489 length := uint32(data[1])<<16 | uint32(data[2])<<8 | uint32(data[3])
1490 if uint32(len(data))-4 != length {
1491 return false
1492 }
1493
1494 data = data[4:]
1495 if m.hasSignatureAndHash {
1496 m.signatureAndHash.hash = data[0]
1497 m.signatureAndHash.signature = data[1]
1498 data = data[2:]
1499 }
1500
1501 if len(data) < 2 {
1502 return false
1503 }
1504 siglength := int(data[0])<<8 + int(data[1])
1505 data = data[2:]
1506 if len(data) != siglength {
1507 return false
1508 }
1509
1510 m.signature = data
1511
1512 return true
1513}
1514
1515type newSessionTicketMsg struct {
1516 raw []byte
1517 ticket []byte
1518}
1519
Adam Langley95c29f32014-06-20 12:00:00 -07001520func (m *newSessionTicketMsg) marshal() (x []byte) {
1521 if m.raw != nil {
1522 return m.raw
1523 }
1524
1525 // See http://tools.ietf.org/html/rfc5077#section-3.3
1526 ticketLen := len(m.ticket)
1527 length := 2 + 4 + ticketLen
1528 x = make([]byte, 4+length)
1529 x[0] = typeNewSessionTicket
1530 x[1] = uint8(length >> 16)
1531 x[2] = uint8(length >> 8)
1532 x[3] = uint8(length)
1533 x[8] = uint8(ticketLen >> 8)
1534 x[9] = uint8(ticketLen)
1535 copy(x[10:], m.ticket)
1536
1537 m.raw = x
1538
1539 return
1540}
1541
1542func (m *newSessionTicketMsg) unmarshal(data []byte) bool {
1543 m.raw = data
1544
1545 if len(data) < 10 {
1546 return false
1547 }
1548
1549 length := uint32(data[1])<<16 | uint32(data[2])<<8 | uint32(data[3])
1550 if uint32(len(data))-4 != length {
1551 return false
1552 }
1553
1554 ticketLen := int(data[8])<<8 + int(data[9])
1555 if len(data)-10 != ticketLen {
1556 return false
1557 }
1558
1559 m.ticket = data[10:]
1560
1561 return true
1562}
1563
David Benjamind86c7672014-08-02 04:07:12 -04001564type v2ClientHelloMsg struct {
1565 raw []byte
1566 vers uint16
1567 cipherSuites []uint16
1568 sessionId []byte
1569 challenge []byte
1570}
1571
David Benjamind86c7672014-08-02 04:07:12 -04001572func (m *v2ClientHelloMsg) marshal() []byte {
1573 if m.raw != nil {
1574 return m.raw
1575 }
1576
1577 length := 1 + 2 + 2 + 2 + 2 + len(m.cipherSuites)*3 + len(m.sessionId) + len(m.challenge)
1578
1579 x := make([]byte, length)
1580 x[0] = 1
1581 x[1] = uint8(m.vers >> 8)
1582 x[2] = uint8(m.vers)
1583 x[3] = uint8((len(m.cipherSuites) * 3) >> 8)
1584 x[4] = uint8(len(m.cipherSuites) * 3)
1585 x[5] = uint8(len(m.sessionId) >> 8)
1586 x[6] = uint8(len(m.sessionId))
1587 x[7] = uint8(len(m.challenge) >> 8)
1588 x[8] = uint8(len(m.challenge))
1589 y := x[9:]
1590 for i, spec := range m.cipherSuites {
1591 y[i*3] = 0
1592 y[i*3+1] = uint8(spec >> 8)
1593 y[i*3+2] = uint8(spec)
1594 }
1595 y = y[len(m.cipherSuites)*3:]
1596 copy(y, m.sessionId)
1597 y = y[len(m.sessionId):]
1598 copy(y, m.challenge)
1599
1600 m.raw = x
1601
1602 return x
1603}
1604
David Benjamin83c0bc92014-08-04 01:23:53 -04001605type helloVerifyRequestMsg struct {
1606 raw []byte
1607 vers uint16
1608 cookie []byte
1609}
1610
David Benjamin83c0bc92014-08-04 01:23:53 -04001611func (m *helloVerifyRequestMsg) marshal() []byte {
1612 if m.raw != nil {
1613 return m.raw
1614 }
1615
1616 length := 2 + 1 + len(m.cookie)
1617
1618 x := make([]byte, 4+length)
1619 x[0] = typeHelloVerifyRequest
1620 x[1] = uint8(length >> 16)
1621 x[2] = uint8(length >> 8)
1622 x[3] = uint8(length)
1623 vers := versionToWire(m.vers, true)
1624 x[4] = uint8(vers >> 8)
1625 x[5] = uint8(vers)
1626 x[6] = uint8(len(m.cookie))
1627 copy(x[7:7+len(m.cookie)], m.cookie)
1628
1629 return x
1630}
1631
1632func (m *helloVerifyRequestMsg) unmarshal(data []byte) bool {
1633 if len(data) < 4+2+1 {
1634 return false
1635 }
1636 m.raw = data
1637 m.vers = wireToVersion(uint16(data[4])<<8|uint16(data[5]), true)
1638 cookieLen := int(data[6])
1639 if cookieLen > 32 || len(data) != 7+cookieLen {
1640 return false
1641 }
1642 m.cookie = data[7 : 7+cookieLen]
1643
1644 return true
1645}
1646
David Benjamind30a9902014-08-24 01:44:23 -04001647type encryptedExtensionsMsg struct {
1648 raw []byte
1649 channelID []byte
1650}
1651
David Benjamind30a9902014-08-24 01:44:23 -04001652func (m *encryptedExtensionsMsg) marshal() []byte {
1653 if m.raw != nil {
1654 return m.raw
1655 }
1656
1657 length := 2 + 2 + len(m.channelID)
1658
1659 x := make([]byte, 4+length)
1660 x[0] = typeEncryptedExtensions
1661 x[1] = uint8(length >> 16)
1662 x[2] = uint8(length >> 8)
1663 x[3] = uint8(length)
1664 x[4] = uint8(extensionChannelID >> 8)
1665 x[5] = uint8(extensionChannelID & 0xff)
1666 x[6] = uint8(len(m.channelID) >> 8)
1667 x[7] = uint8(len(m.channelID) & 0xff)
1668 copy(x[8:], m.channelID)
1669
1670 return x
1671}
1672
1673func (m *encryptedExtensionsMsg) unmarshal(data []byte) bool {
1674 if len(data) != 4+2+2+128 {
1675 return false
1676 }
1677 m.raw = data
1678 if (uint16(data[4])<<8)|uint16(data[5]) != extensionChannelID {
1679 return false
1680 }
1681 if int(data[6])<<8|int(data[7]) != 128 {
1682 return false
1683 }
1684 m.channelID = data[4+2+2:]
1685
1686 return true
1687}
1688
Adam Langley2ae77d22014-10-28 17:29:33 -07001689type helloRequestMsg struct {
1690}
1691
1692func (*helloRequestMsg) marshal() []byte {
1693 return []byte{typeHelloRequest, 0, 0, 0}
1694}
1695
1696func (*helloRequestMsg) unmarshal(data []byte) bool {
1697 return len(data) == 4
1698}
1699
Adam Langley95c29f32014-06-20 12:00:00 -07001700func eqUint16s(x, y []uint16) bool {
1701 if len(x) != len(y) {
1702 return false
1703 }
1704 for i, v := range x {
1705 if y[i] != v {
1706 return false
1707 }
1708 }
1709 return true
1710}
1711
1712func eqCurveIDs(x, y []CurveID) bool {
1713 if len(x) != len(y) {
1714 return false
1715 }
1716 for i, v := range x {
1717 if y[i] != v {
1718 return false
1719 }
1720 }
1721 return true
1722}
1723
1724func eqStrings(x, y []string) bool {
1725 if len(x) != len(y) {
1726 return false
1727 }
1728 for i, v := range x {
1729 if y[i] != v {
1730 return false
1731 }
1732 }
1733 return true
1734}
1735
1736func eqByteSlices(x, y [][]byte) bool {
1737 if len(x) != len(y) {
1738 return false
1739 }
1740 for i, v := range x {
1741 if !bytes.Equal(v, y[i]) {
1742 return false
1743 }
1744 }
1745 return true
1746}
1747
1748func eqSignatureAndHashes(x, y []signatureAndHash) bool {
1749 if len(x) != len(y) {
1750 return false
1751 }
1752 for i, v := range x {
1753 v2 := y[i]
1754 if v.hash != v2.hash || v.signature != v2.signature {
1755 return false
1756 }
1757 }
1758 return true
1759}