blob: 23b5c8ea99fda1aafe664e0dca49e9a3947000c2 [file] [log] [blame]
Adam Langley95c29f32014-06-20 12:00:00 -07001// Copyright 2009 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
Adam Langleydc7e9c42015-09-29 15:21:04 -07005package runner
Adam Langley95c29f32014-06-20 12:00:00 -07006
7import "bytes"
8
Nick Harper8dda5cc2016-06-30 18:51:11 -04009func writeLen(buf []byte, v, size int) {
10 for i := 0; i < size; i++ {
11 buf[size-i-1] = byte(v)
12 v >>= 8
13 }
14 if v != 0 {
15 panic("length is too long")
16 }
17}
18
19type byteBuilder struct {
20 buf *[]byte
21 start int
22 prefixLen int
23 child *byteBuilder
24}
25
26func newByteBuilder() *byteBuilder {
27 buf := make([]byte, 0, 32)
28 return &byteBuilder{buf: &buf}
29}
30
31func (bb *byteBuilder) len() int {
32 return len(*bb.buf) - bb.start - bb.prefixLen
33}
34
35func (bb *byteBuilder) flush() {
36 if bb.child == nil {
37 return
38 }
39 bb.child.flush()
40 writeLen((*bb.buf)[bb.child.start:], bb.child.len(), bb.child.prefixLen)
41 bb.child = nil
42 return
43}
44
45func (bb *byteBuilder) finish() []byte {
46 bb.flush()
47 return *bb.buf
48}
49
50func (bb *byteBuilder) addU8(u uint8) {
51 bb.flush()
52 *bb.buf = append(*bb.buf, u)
53}
54
55func (bb *byteBuilder) addU16(u uint16) {
56 bb.flush()
57 *bb.buf = append(*bb.buf, byte(u>>8), byte(u))
58}
59
60func (bb *byteBuilder) addU24(u int) {
61 bb.flush()
62 *bb.buf = append(*bb.buf, byte(u>>16), byte(u>>8), byte(u))
63}
64
65func (bb *byteBuilder) addU32(u uint32) {
66 bb.flush()
67 *bb.buf = append(*bb.buf, byte(u>>24), byte(u>>16), byte(u>>8), byte(u))
68}
69
70func (bb *byteBuilder) addU8LengthPrefixed() *byteBuilder {
71 return bb.createChild(1)
72}
73
74func (bb *byteBuilder) addU16LengthPrefixed() *byteBuilder {
75 return bb.createChild(2)
76}
77
78func (bb *byteBuilder) addU24LengthPrefixed() *byteBuilder {
79 return bb.createChild(3)
80}
81
82func (bb *byteBuilder) addBytes(b []byte) {
83 bb.flush()
84 *bb.buf = append(*bb.buf, b...)
85}
86
87func (bb *byteBuilder) createChild(lengthPrefixSize int) *byteBuilder {
88 bb.flush()
89 bb.child = &byteBuilder{
90 buf: bb.buf,
91 start: len(*bb.buf),
92 prefixLen: lengthPrefixSize,
93 }
94 for i := 0; i < lengthPrefixSize; i++ {
95 *bb.buf = append(*bb.buf, 0)
96 }
97 return bb.child
98}
99
100func (bb *byteBuilder) discardChild() {
101 if bb.child != nil {
102 return
103 }
104 bb.child = nil
105 *bb.buf = (*bb.buf)[:bb.start]
106}
107
Adam Langley95c29f32014-06-20 12:00:00 -0700108type clientHelloMsg struct {
David Benjaminca6c8262014-11-15 19:06:08 -0500109 raw []byte
110 isDTLS bool
111 vers uint16
112 random []byte
113 sessionId []byte
114 cookie []byte
115 cipherSuites []uint16
116 compressionMethods []uint8
117 nextProtoNeg bool
118 serverName string
119 ocspStapling bool
120 supportedCurves []CurveID
121 supportedPoints []uint8
122 ticketSupported bool
123 sessionTicket []uint8
Nick Harper60edffd2016-06-21 15:19:24 -0700124 signatureAlgorithms []signatureAlgorithm
David Benjaminca6c8262014-11-15 19:06:08 -0500125 secureRenegotiation []byte
126 alpnProtocols []string
127 duplicateExtension bool
128 channelIDSupported bool
129 npnLast bool
130 extendedMasterSecret bool
131 srtpProtectionProfiles []uint16
132 srtpMasterKeyIdentifier string
David Benjamin61f95272014-11-25 01:55:35 -0500133 sctListSupported bool
Adam Langley09505632015-07-30 18:10:13 -0700134 customExtension string
Adam Langley95c29f32014-06-20 12:00:00 -0700135}
136
137func (m *clientHelloMsg) equal(i interface{}) bool {
138 m1, ok := i.(*clientHelloMsg)
139 if !ok {
140 return false
141 }
142
143 return bytes.Equal(m.raw, m1.raw) &&
David Benjamin83c0bc92014-08-04 01:23:53 -0400144 m.isDTLS == m1.isDTLS &&
Adam Langley95c29f32014-06-20 12:00:00 -0700145 m.vers == m1.vers &&
146 bytes.Equal(m.random, m1.random) &&
147 bytes.Equal(m.sessionId, m1.sessionId) &&
David Benjamin83c0bc92014-08-04 01:23:53 -0400148 bytes.Equal(m.cookie, m1.cookie) &&
Adam Langley95c29f32014-06-20 12:00:00 -0700149 eqUint16s(m.cipherSuites, m1.cipherSuites) &&
150 bytes.Equal(m.compressionMethods, m1.compressionMethods) &&
151 m.nextProtoNeg == m1.nextProtoNeg &&
152 m.serverName == m1.serverName &&
153 m.ocspStapling == m1.ocspStapling &&
154 eqCurveIDs(m.supportedCurves, m1.supportedCurves) &&
155 bytes.Equal(m.supportedPoints, m1.supportedPoints) &&
156 m.ticketSupported == m1.ticketSupported &&
157 bytes.Equal(m.sessionTicket, m1.sessionTicket) &&
Nick Harper60edffd2016-06-21 15:19:24 -0700158 eqSignatureAlgorithms(m.signatureAlgorithms, m1.signatureAlgorithms) &&
Adam Langley2ae77d22014-10-28 17:29:33 -0700159 bytes.Equal(m.secureRenegotiation, m1.secureRenegotiation) &&
160 (m.secureRenegotiation == nil) == (m1.secureRenegotiation == nil) &&
David Benjaminfa055a22014-09-15 16:51:51 -0400161 eqStrings(m.alpnProtocols, m1.alpnProtocols) &&
David Benjamind30a9902014-08-24 01:44:23 -0400162 m.duplicateExtension == m1.duplicateExtension &&
David Benjaminfc7b0862014-09-06 13:21:53 -0400163 m.channelIDSupported == m1.channelIDSupported &&
Adam Langley75712922014-10-10 16:23:43 -0700164 m.npnLast == m1.npnLast &&
David Benjaminca6c8262014-11-15 19:06:08 -0500165 m.extendedMasterSecret == m1.extendedMasterSecret &&
166 eqUint16s(m.srtpProtectionProfiles, m1.srtpProtectionProfiles) &&
David Benjamin61f95272014-11-25 01:55:35 -0500167 m.srtpMasterKeyIdentifier == m1.srtpMasterKeyIdentifier &&
Adam Langley09505632015-07-30 18:10:13 -0700168 m.sctListSupported == m1.sctListSupported &&
169 m.customExtension == m1.customExtension
Adam Langley95c29f32014-06-20 12:00:00 -0700170}
171
172func (m *clientHelloMsg) marshal() []byte {
173 if m.raw != nil {
174 return m.raw
175 }
176
Nick Harper8dda5cc2016-06-30 18:51:11 -0400177 handshakeMsg := newByteBuilder()
178 handshakeMsg.addU8(typeClientHello)
179 hello := handshakeMsg.addU24LengthPrefixed()
David Benjamin83c0bc92014-08-04 01:23:53 -0400180 vers := versionToWire(m.vers, m.isDTLS)
Nick Harper8dda5cc2016-06-30 18:51:11 -0400181 hello.addU16(vers)
182 hello.addBytes(m.random)
183 sessionId := hello.addU8LengthPrefixed()
184 sessionId.addBytes(m.sessionId)
David Benjamin83c0bc92014-08-04 01:23:53 -0400185 if m.isDTLS {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400186 cookie := hello.addU8LengthPrefixed()
187 cookie.addBytes(m.cookie)
David Benjamin83c0bc92014-08-04 01:23:53 -0400188 }
Nick Harper8dda5cc2016-06-30 18:51:11 -0400189 cipherSuites := hello.addU16LengthPrefixed()
190 for _, suite := range m.cipherSuites {
191 cipherSuites.addU16(suite)
Adam Langley95c29f32014-06-20 12:00:00 -0700192 }
Nick Harper8dda5cc2016-06-30 18:51:11 -0400193 compressionMethods := hello.addU8LengthPrefixed()
194 compressionMethods.addBytes(m.compressionMethods)
Adam Langley95c29f32014-06-20 12:00:00 -0700195
Nick Harper8dda5cc2016-06-30 18:51:11 -0400196 extensions := hello.addU16LengthPrefixed()
David Benjamin35a7a442014-07-05 00:23:20 -0400197 if m.duplicateExtension {
198 // Add a duplicate bogus extension at the beginning and end.
Nick Harper8dda5cc2016-06-30 18:51:11 -0400199 extensions.addU16(0xffff)
200 extensions.addU16(0) // 0-length for empty extension
David Benjamin35a7a442014-07-05 00:23:20 -0400201 }
David Benjaminfc7b0862014-09-06 13:21:53 -0400202 if m.nextProtoNeg && !m.npnLast {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400203 extensions.addU16(extensionNextProtoNeg)
204 extensions.addU16(0) // The length is always 0
Adam Langley95c29f32014-06-20 12:00:00 -0700205 }
206 if len(m.serverName) > 0 {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400207 extensions.addU16(extensionServerName)
208 serverNameList := extensions.addU16LengthPrefixed()
Adam Langley95c29f32014-06-20 12:00:00 -0700209
210 // RFC 3546, section 3.1
211 //
212 // struct {
213 // NameType name_type;
214 // select (name_type) {
215 // case host_name: HostName;
216 // } name;
217 // } ServerName;
218 //
219 // enum {
220 // host_name(0), (255)
221 // } NameType;
222 //
223 // opaque HostName<1..2^16-1>;
224 //
225 // struct {
226 // ServerName server_name_list<1..2^16-1>
227 // } ServerNameList;
228
Nick Harper8dda5cc2016-06-30 18:51:11 -0400229 serverName := serverNameList.addU16LengthPrefixed()
230 serverName.addU8(0) // NameType host_name(0)
231 hostName := serverName.addU16LengthPrefixed()
232 hostName.addBytes([]byte(m.serverName))
Adam Langley95c29f32014-06-20 12:00:00 -0700233 }
234 if m.ocspStapling {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400235 extensions.addU16(extensionStatusRequest)
236 certificateStatusRequest := extensions.addU16LengthPrefixed()
237
Adam Langley95c29f32014-06-20 12:00:00 -0700238 // RFC 4366, section 3.6
Nick Harper8dda5cc2016-06-30 18:51:11 -0400239 certificateStatusRequest.addU8(1) // OCSP type
Adam Langley95c29f32014-06-20 12:00:00 -0700240 // Two zero valued uint16s for the two lengths.
Nick Harper8dda5cc2016-06-30 18:51:11 -0400241 certificateStatusRequest.addU16(0) // ResponderID length
242 certificateStatusRequest.addU16(0) // Extensions length
Adam Langley95c29f32014-06-20 12:00:00 -0700243 }
244 if len(m.supportedCurves) > 0 {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400245 // http://tools.ietf.org/html/rfc4492#section-5.1.1
246 extensions.addU16(extensionSupportedCurves)
247 supportedCurvesList := extensions.addU16LengthPrefixed()
248 supportedCurves := supportedCurvesList.addU16LengthPrefixed()
Adam Langley95c29f32014-06-20 12:00:00 -0700249 for _, curve := range m.supportedCurves {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400250 supportedCurves.addU16(uint16(curve))
Adam Langley95c29f32014-06-20 12:00:00 -0700251 }
252 }
253 if len(m.supportedPoints) > 0 {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400254 // http://tools.ietf.org/html/rfc4492#section-5.1.2
255 extensions.addU16(extensionSupportedPoints)
256 supportedPointsList := extensions.addU16LengthPrefixed()
257 supportedPoints := supportedPointsList.addU8LengthPrefixed()
Adam Langley95c29f32014-06-20 12:00:00 -0700258 for _, pointFormat := range m.supportedPoints {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400259 supportedPoints.addU8(pointFormat)
Adam Langley95c29f32014-06-20 12:00:00 -0700260 }
261 }
262 if m.ticketSupported {
263 // http://tools.ietf.org/html/rfc5077#section-3.2
Nick Harper8dda5cc2016-06-30 18:51:11 -0400264 extensions.addU16(extensionSessionTicket)
265 sessionTicketExtension := extensions.addU16LengthPrefixed()
266 sessionTicketExtension.addBytes(m.sessionTicket)
Adam Langley95c29f32014-06-20 12:00:00 -0700267 }
Nick Harper60edffd2016-06-21 15:19:24 -0700268 if len(m.signatureAlgorithms) > 0 {
Adam Langley95c29f32014-06-20 12:00:00 -0700269 // https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
Nick Harper8dda5cc2016-06-30 18:51:11 -0400270 extensions.addU16(extensionSignatureAlgorithms)
271 signatureAlgorithmsExtension := extensions.addU16LengthPrefixed()
272 signatureAlgorithms := signatureAlgorithmsExtension.addU16LengthPrefixed()
Nick Harper60edffd2016-06-21 15:19:24 -0700273 for _, sigAlg := range m.signatureAlgorithms {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400274 signatureAlgorithms.addU16(uint16(sigAlg))
Adam Langley95c29f32014-06-20 12:00:00 -0700275 }
276 }
Adam Langley2ae77d22014-10-28 17:29:33 -0700277 if m.secureRenegotiation != nil {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400278 extensions.addU16(extensionRenegotiationInfo)
279 secureRenegoExt := extensions.addU16LengthPrefixed()
280 secureRenego := secureRenegoExt.addU8LengthPrefixed()
281 secureRenego.addBytes(m.secureRenegotiation)
Adam Langley95c29f32014-06-20 12:00:00 -0700282 }
David Benjaminfa055a22014-09-15 16:51:51 -0400283 if len(m.alpnProtocols) > 0 {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400284 // https://tools.ietf.org/html/rfc7301#section-3.1
285 extensions.addU16(extensionALPN)
286 alpnExtension := extensions.addU16LengthPrefixed()
David Benjaminfa055a22014-09-15 16:51:51 -0400287
Nick Harper8dda5cc2016-06-30 18:51:11 -0400288 protocolNameList := alpnExtension.addU16LengthPrefixed()
David Benjaminfa055a22014-09-15 16:51:51 -0400289 for _, s := range m.alpnProtocols {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400290 protocolName := protocolNameList.addU8LengthPrefixed()
291 protocolName.addBytes([]byte(s))
David Benjaminfa055a22014-09-15 16:51:51 -0400292 }
David Benjaminfa055a22014-09-15 16:51:51 -0400293 }
David Benjamind30a9902014-08-24 01:44:23 -0400294 if m.channelIDSupported {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400295 extensions.addU16(extensionChannelID)
296 extensions.addU16(0) // Length is always 0
David Benjamind30a9902014-08-24 01:44:23 -0400297 }
David Benjaminfc7b0862014-09-06 13:21:53 -0400298 if m.nextProtoNeg && m.npnLast {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400299 extensions.addU16(extensionNextProtoNeg)
300 extensions.addU16(0) // Length is always 0
David Benjaminfc7b0862014-09-06 13:21:53 -0400301 }
David Benjamin35a7a442014-07-05 00:23:20 -0400302 if m.duplicateExtension {
303 // Add a duplicate bogus extension at the beginning and end.
Nick Harper8dda5cc2016-06-30 18:51:11 -0400304 extensions.addU16(0xffff)
305 extensions.addU16(0)
David Benjamin35a7a442014-07-05 00:23:20 -0400306 }
Adam Langley75712922014-10-10 16:23:43 -0700307 if m.extendedMasterSecret {
David Benjamin43946d42016-02-01 08:42:19 -0500308 // https://tools.ietf.org/html/rfc7627
Nick Harper8dda5cc2016-06-30 18:51:11 -0400309 extensions.addU16(extensionExtendedMasterSecret)
310 extensions.addU16(0) // Length is always 0
Adam Langley75712922014-10-10 16:23:43 -0700311 }
David Benjaminca6c8262014-11-15 19:06:08 -0500312 if len(m.srtpProtectionProfiles) > 0 {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400313 // https://tools.ietf.org/html/rfc5764#section-4.1.1
314 extensions.addU16(extensionUseSRTP)
315 useSrtpExt := extensions.addU16LengthPrefixed()
David Benjaminca6c8262014-11-15 19:06:08 -0500316
Nick Harper8dda5cc2016-06-30 18:51:11 -0400317 srtpProtectionProfiles := useSrtpExt.addU16LengthPrefixed()
David Benjaminca6c8262014-11-15 19:06:08 -0500318 for _, p := range m.srtpProtectionProfiles {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400319 // An SRTPProtectionProfile is defined as uint8[2],
320 // not uint16. For some reason, we're storing it
321 // as a uint16.
322 srtpProtectionProfiles.addU8(byte(p >> 8))
323 srtpProtectionProfiles.addU8(byte(p))
David Benjaminca6c8262014-11-15 19:06:08 -0500324 }
Nick Harper8dda5cc2016-06-30 18:51:11 -0400325 srtpMki := useSrtpExt.addU8LengthPrefixed()
326 srtpMki.addBytes([]byte(m.srtpMasterKeyIdentifier))
David Benjaminca6c8262014-11-15 19:06:08 -0500327 }
David Benjamin61f95272014-11-25 01:55:35 -0500328 if m.sctListSupported {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400329 extensions.addU16(extensionSignedCertificateTimestamp)
330 extensions.addU16(0) // Length is always 0
David Benjamin61f95272014-11-25 01:55:35 -0500331 }
Adam Langley09505632015-07-30 18:10:13 -0700332 if l := len(m.customExtension); l > 0 {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400333 extensions.addU16(extensionCustom)
334 customExt := extensions.addU16LengthPrefixed()
335 customExt.addBytes([]byte(m.customExtension))
Adam Langley09505632015-07-30 18:10:13 -0700336 }
Adam Langley95c29f32014-06-20 12:00:00 -0700337
Nick Harper8dda5cc2016-06-30 18:51:11 -0400338 if extensions.len() == 0 {
339 hello.discardChild()
340 }
Adam Langley95c29f32014-06-20 12:00:00 -0700341
Nick Harper8dda5cc2016-06-30 18:51:11 -0400342 m.raw = handshakeMsg.finish()
343 return m.raw
Adam Langley95c29f32014-06-20 12:00:00 -0700344}
345
346func (m *clientHelloMsg) unmarshal(data []byte) bool {
347 if len(data) < 42 {
348 return false
349 }
350 m.raw = data
David Benjamin83c0bc92014-08-04 01:23:53 -0400351 m.vers = wireToVersion(uint16(data[4])<<8|uint16(data[5]), m.isDTLS)
Adam Langley95c29f32014-06-20 12:00:00 -0700352 m.random = data[6:38]
353 sessionIdLen := int(data[38])
354 if sessionIdLen > 32 || len(data) < 39+sessionIdLen {
355 return false
356 }
357 m.sessionId = data[39 : 39+sessionIdLen]
358 data = data[39+sessionIdLen:]
David Benjamin83c0bc92014-08-04 01:23:53 -0400359 if m.isDTLS {
360 if len(data) < 1 {
361 return false
362 }
363 cookieLen := int(data[0])
364 if cookieLen > 32 || len(data) < 1+cookieLen {
365 return false
366 }
367 m.cookie = data[1 : 1+cookieLen]
368 data = data[1+cookieLen:]
369 }
Adam Langley95c29f32014-06-20 12:00:00 -0700370 if len(data) < 2 {
371 return false
372 }
373 // cipherSuiteLen is the number of bytes of cipher suite numbers. Since
374 // they are uint16s, the number must be even.
375 cipherSuiteLen := int(data[0])<<8 | int(data[1])
376 if cipherSuiteLen%2 == 1 || len(data) < 2+cipherSuiteLen {
377 return false
378 }
379 numCipherSuites := cipherSuiteLen / 2
380 m.cipherSuites = make([]uint16, numCipherSuites)
381 for i := 0; i < numCipherSuites; i++ {
382 m.cipherSuites[i] = uint16(data[2+2*i])<<8 | uint16(data[3+2*i])
383 if m.cipherSuites[i] == scsvRenegotiation {
Adam Langley2ae77d22014-10-28 17:29:33 -0700384 m.secureRenegotiation = []byte{}
Adam Langley95c29f32014-06-20 12:00:00 -0700385 }
386 }
387 data = data[2+cipherSuiteLen:]
388 if len(data) < 1 {
389 return false
390 }
391 compressionMethodsLen := int(data[0])
392 if len(data) < 1+compressionMethodsLen {
393 return false
394 }
395 m.compressionMethods = data[1 : 1+compressionMethodsLen]
396
397 data = data[1+compressionMethodsLen:]
398
399 m.nextProtoNeg = false
400 m.serverName = ""
401 m.ocspStapling = false
402 m.ticketSupported = false
403 m.sessionTicket = nil
Nick Harper60edffd2016-06-21 15:19:24 -0700404 m.signatureAlgorithms = nil
David Benjaminfa055a22014-09-15 16:51:51 -0400405 m.alpnProtocols = nil
Adam Langley75712922014-10-10 16:23:43 -0700406 m.extendedMasterSecret = false
Adam Langley09505632015-07-30 18:10:13 -0700407 m.customExtension = ""
Adam Langley95c29f32014-06-20 12:00:00 -0700408
409 if len(data) == 0 {
410 // ClientHello is optionally followed by extension data
411 return true
412 }
413 if len(data) < 2 {
414 return false
415 }
416
417 extensionsLength := int(data[0])<<8 | int(data[1])
418 data = data[2:]
419 if extensionsLength != len(data) {
420 return false
421 }
422
423 for len(data) != 0 {
424 if len(data) < 4 {
425 return false
426 }
427 extension := uint16(data[0])<<8 | uint16(data[1])
428 length := int(data[2])<<8 | int(data[3])
429 data = data[4:]
430 if len(data) < length {
431 return false
432 }
433
434 switch extension {
435 case extensionServerName:
436 if length < 2 {
437 return false
438 }
439 numNames := int(data[0])<<8 | int(data[1])
440 d := data[2:]
441 for i := 0; i < numNames; i++ {
442 if len(d) < 3 {
443 return false
444 }
445 nameType := d[0]
446 nameLen := int(d[1])<<8 | int(d[2])
447 d = d[3:]
448 if len(d) < nameLen {
449 return false
450 }
451 if nameType == 0 {
452 m.serverName = string(d[0:nameLen])
453 break
454 }
455 d = d[nameLen:]
456 }
457 case extensionNextProtoNeg:
458 if length > 0 {
459 return false
460 }
461 m.nextProtoNeg = true
462 case extensionStatusRequest:
463 m.ocspStapling = length > 0 && data[0] == statusTypeOCSP
464 case extensionSupportedCurves:
465 // http://tools.ietf.org/html/rfc4492#section-5.5.1
466 if length < 2 {
467 return false
468 }
469 l := int(data[0])<<8 | int(data[1])
470 if l%2 == 1 || length != l+2 {
471 return false
472 }
473 numCurves := l / 2
474 m.supportedCurves = make([]CurveID, numCurves)
475 d := data[2:]
476 for i := 0; i < numCurves; i++ {
477 m.supportedCurves[i] = CurveID(d[0])<<8 | CurveID(d[1])
478 d = d[2:]
479 }
480 case extensionSupportedPoints:
481 // http://tools.ietf.org/html/rfc4492#section-5.5.2
482 if length < 1 {
483 return false
484 }
485 l := int(data[0])
486 if length != l+1 {
487 return false
488 }
489 m.supportedPoints = make([]uint8, l)
490 copy(m.supportedPoints, data[1:])
491 case extensionSessionTicket:
492 // http://tools.ietf.org/html/rfc5077#section-3.2
493 m.ticketSupported = true
494 m.sessionTicket = data[:length]
495 case extensionSignatureAlgorithms:
496 // https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
497 if length < 2 || length&1 != 0 {
498 return false
499 }
500 l := int(data[0])<<8 | int(data[1])
501 if l != length-2 {
502 return false
503 }
504 n := l / 2
505 d := data[2:]
Nick Harper60edffd2016-06-21 15:19:24 -0700506 m.signatureAlgorithms = make([]signatureAlgorithm, n)
507 for i := range m.signatureAlgorithms {
508 m.signatureAlgorithms[i] = signatureAlgorithm(d[0])<<8 | signatureAlgorithm(d[1])
Adam Langley95c29f32014-06-20 12:00:00 -0700509 d = d[2:]
510 }
Adam Langley2ae77d22014-10-28 17:29:33 -0700511 case extensionRenegotiationInfo:
512 if length < 1 || length != int(data[0])+1 {
Adam Langley95c29f32014-06-20 12:00:00 -0700513 return false
514 }
Adam Langley2ae77d22014-10-28 17:29:33 -0700515 m.secureRenegotiation = data[1:length]
David Benjaminfa055a22014-09-15 16:51:51 -0400516 case extensionALPN:
517 if length < 2 {
518 return false
519 }
520 l := int(data[0])<<8 | int(data[1])
521 if l != length-2 {
522 return false
523 }
524 d := data[2:length]
525 for len(d) != 0 {
526 stringLen := int(d[0])
527 d = d[1:]
528 if stringLen == 0 || stringLen > len(d) {
529 return false
530 }
531 m.alpnProtocols = append(m.alpnProtocols, string(d[:stringLen]))
532 d = d[stringLen:]
533 }
David Benjamind30a9902014-08-24 01:44:23 -0400534 case extensionChannelID:
535 if length > 0 {
536 return false
537 }
538 m.channelIDSupported = true
Adam Langley75712922014-10-10 16:23:43 -0700539 case extensionExtendedMasterSecret:
540 if length != 0 {
541 return false
542 }
543 m.extendedMasterSecret = true
David Benjaminca6c8262014-11-15 19:06:08 -0500544 case extensionUseSRTP:
545 if length < 2 {
546 return false
547 }
548 l := int(data[0])<<8 | int(data[1])
549 if l > length-2 || l%2 != 0 {
550 return false
551 }
552 n := l / 2
553 m.srtpProtectionProfiles = make([]uint16, n)
554 d := data[2:length]
555 for i := 0; i < n; i++ {
556 m.srtpProtectionProfiles[i] = uint16(d[0])<<8 | uint16(d[1])
557 d = d[2:]
558 }
559 if len(d) < 1 || int(d[0]) != len(d)-1 {
560 return false
561 }
562 m.srtpMasterKeyIdentifier = string(d[1:])
David Benjamin61f95272014-11-25 01:55:35 -0500563 case extensionSignedCertificateTimestamp:
564 if length != 0 {
565 return false
566 }
567 m.sctListSupported = true
Adam Langley09505632015-07-30 18:10:13 -0700568 case extensionCustom:
569 m.customExtension = string(data[:length])
Adam Langley95c29f32014-06-20 12:00:00 -0700570 }
571 data = data[length:]
572 }
573
574 return true
575}
576
577type serverHelloMsg struct {
Nick Harperb3d51be2016-07-01 11:43:18 -0400578 raw []byte
579 isDTLS bool
580 vers uint16
581 random []byte
582 sessionId []byte
583 cipherSuite uint16
584 compressionMethod uint8
585 extensions serverExtensions
Adam Langley95c29f32014-06-20 12:00:00 -0700586}
587
Adam Langley95c29f32014-06-20 12:00:00 -0700588func (m *serverHelloMsg) marshal() []byte {
589 if m.raw != nil {
590 return m.raw
591 }
592
Nick Harper5212ef82016-06-30 19:26:07 -0400593 handshakeMsg := newByteBuilder()
594 handshakeMsg.addU8(typeServerHello)
595 hello := handshakeMsg.addU24LengthPrefixed()
David Benjamin83c0bc92014-08-04 01:23:53 -0400596 vers := versionToWire(m.vers, m.isDTLS)
Nick Harper5212ef82016-06-30 19:26:07 -0400597 hello.addU16(vers)
598 hello.addBytes(m.random)
599 sessionId := hello.addU8LengthPrefixed()
600 sessionId.addBytes(m.sessionId)
601 hello.addU16(m.cipherSuite)
602 hello.addU8(m.compressionMethod)
Adam Langley95c29f32014-06-20 12:00:00 -0700603
Nick Harper5212ef82016-06-30 19:26:07 -0400604 extensions := hello.addU16LengthPrefixed()
Nick Harperb3d51be2016-07-01 11:43:18 -0400605
606 m.extensions.marshal(extensions)
607
608 if extensions.len() == 0 {
609 hello.discardChild()
610 }
611
612 m.raw = handshakeMsg.finish()
613 return m.raw
614}
615
616func (m *serverHelloMsg) unmarshal(data []byte) bool {
617 if len(data) < 42 {
618 return false
619 }
620 m.raw = data
621 m.vers = wireToVersion(uint16(data[4])<<8|uint16(data[5]), m.isDTLS)
622 m.random = data[6:38]
623 sessionIdLen := int(data[38])
624 if sessionIdLen > 32 || len(data) < 39+sessionIdLen {
625 return false
626 }
627 m.sessionId = data[39 : 39+sessionIdLen]
628 data = data[39+sessionIdLen:]
629 if len(data) < 3 {
630 return false
631 }
632 m.cipherSuite = uint16(data[0])<<8 | uint16(data[1])
633 m.compressionMethod = data[2]
634 data = data[3:]
635
636 if len(data) == 0 {
637 // ServerHello is optionally followed by extension data
638 m.extensions = serverExtensions{}
639 return true
640 }
641 if len(data) < 2 {
642 return false
643 }
644
645 extensionsLength := int(data[0])<<8 | int(data[1])
646 data = data[2:]
647 if len(data) != extensionsLength {
648 return false
649 }
650
651 if !m.extensions.unmarshal(data) {
652 return false
653 }
654
655 return true
656}
657
658type serverExtensions struct {
659 nextProtoNeg bool
660 nextProtos []string
661 ocspStapling bool
662 ticketSupported bool
663 secureRenegotiation []byte
664 alpnProtocol string
665 alpnProtocolEmpty bool
666 duplicateExtension bool
667 channelIDRequested bool
668 extendedMasterSecret bool
669 srtpProtectionProfile uint16
670 srtpMasterKeyIdentifier string
671 sctList []byte
672 customExtension string
673 npnLast bool
674}
675
676func (m *serverExtensions) marshal(extensions *byteBuilder) {
David Benjamin35a7a442014-07-05 00:23:20 -0400677 if m.duplicateExtension {
678 // Add a duplicate bogus extension at the beginning and end.
Nick Harper5212ef82016-06-30 19:26:07 -0400679 extensions.addU16(0xffff)
680 extensions.addU16(0) // length = 0 for empty extension
David Benjamin35a7a442014-07-05 00:23:20 -0400681 }
David Benjamin76c2efc2015-08-31 14:24:29 -0400682 if m.nextProtoNeg && !m.npnLast {
Nick Harper5212ef82016-06-30 19:26:07 -0400683 extensions.addU16(extensionNextProtoNeg)
684 extension := extensions.addU16LengthPrefixed()
Adam Langley95c29f32014-06-20 12:00:00 -0700685
686 for _, v := range m.nextProtos {
Nick Harper5212ef82016-06-30 19:26:07 -0400687 if len(v) > 255 {
688 v = v[:255]
Adam Langley95c29f32014-06-20 12:00:00 -0700689 }
Nick Harper5212ef82016-06-30 19:26:07 -0400690 npn := extension.addU8LengthPrefixed()
691 npn.addBytes([]byte(v))
Adam Langley95c29f32014-06-20 12:00:00 -0700692 }
693 }
694 if m.ocspStapling {
Nick Harper5212ef82016-06-30 19:26:07 -0400695 extensions.addU16(extensionStatusRequest)
696 extensions.addU16(0)
Adam Langley95c29f32014-06-20 12:00:00 -0700697 }
698 if m.ticketSupported {
Nick Harper5212ef82016-06-30 19:26:07 -0400699 extensions.addU16(extensionSessionTicket)
700 extensions.addU16(0)
Adam Langley95c29f32014-06-20 12:00:00 -0700701 }
Adam Langley2ae77d22014-10-28 17:29:33 -0700702 if m.secureRenegotiation != nil {
Nick Harper5212ef82016-06-30 19:26:07 -0400703 extensions.addU16(extensionRenegotiationInfo)
704 extension := extensions.addU16LengthPrefixed()
705 secureRenego := extension.addU8LengthPrefixed()
706 secureRenego.addBytes(m.secureRenegotiation)
Adam Langley95c29f32014-06-20 12:00:00 -0700707 }
Nick Harper5212ef82016-06-30 19:26:07 -0400708 if len(m.alpnProtocol) > 0 || m.alpnProtocolEmpty {
709 extensions.addU16(extensionALPN)
710 extension := extensions.addU16LengthPrefixed()
711
712 protocolNameList := extension.addU16LengthPrefixed()
713 protocolName := protocolNameList.addU8LengthPrefixed()
714 protocolName.addBytes([]byte(m.alpnProtocol))
David Benjaminfa055a22014-09-15 16:51:51 -0400715 }
David Benjamind30a9902014-08-24 01:44:23 -0400716 if m.channelIDRequested {
Nick Harper5212ef82016-06-30 19:26:07 -0400717 extensions.addU16(extensionChannelID)
718 extensions.addU16(0)
David Benjamind30a9902014-08-24 01:44:23 -0400719 }
David Benjamin35a7a442014-07-05 00:23:20 -0400720 if m.duplicateExtension {
721 // Add a duplicate bogus extension at the beginning and end.
Nick Harper5212ef82016-06-30 19:26:07 -0400722 extensions.addU16(0xffff)
723 extensions.addU16(0)
David Benjamin35a7a442014-07-05 00:23:20 -0400724 }
Adam Langley75712922014-10-10 16:23:43 -0700725 if m.extendedMasterSecret {
Nick Harper5212ef82016-06-30 19:26:07 -0400726 extensions.addU16(extensionExtendedMasterSecret)
727 extensions.addU16(0)
Adam Langley75712922014-10-10 16:23:43 -0700728 }
David Benjaminca6c8262014-11-15 19:06:08 -0500729 if m.srtpProtectionProfile != 0 {
Nick Harper5212ef82016-06-30 19:26:07 -0400730 extensions.addU16(extensionUseSRTP)
731 extension := extensions.addU16LengthPrefixed()
732
733 srtpProtectionProfiles := extension.addU16LengthPrefixed()
734 srtpProtectionProfiles.addU8(byte(m.srtpProtectionProfile >> 8))
735 srtpProtectionProfiles.addU8(byte(m.srtpProtectionProfile))
736 srtpMki := extension.addU8LengthPrefixed()
737 srtpMki.addBytes([]byte(m.srtpMasterKeyIdentifier))
David Benjaminca6c8262014-11-15 19:06:08 -0500738 }
David Benjamin61f95272014-11-25 01:55:35 -0500739 if m.sctList != nil {
Nick Harper5212ef82016-06-30 19:26:07 -0400740 extensions.addU16(extensionSignedCertificateTimestamp)
741 extension := extensions.addU16LengthPrefixed()
742 extension.addBytes(m.sctList)
David Benjamin61f95272014-11-25 01:55:35 -0500743 }
Adam Langley09505632015-07-30 18:10:13 -0700744 if l := len(m.customExtension); l > 0 {
Nick Harper5212ef82016-06-30 19:26:07 -0400745 extensions.addU16(extensionCustom)
746 customExt := extensions.addU16LengthPrefixed()
747 customExt.addBytes([]byte(m.customExtension))
Adam Langley09505632015-07-30 18:10:13 -0700748 }
David Benjamin76c2efc2015-08-31 14:24:29 -0400749 if m.nextProtoNeg && m.npnLast {
Nick Harper5212ef82016-06-30 19:26:07 -0400750 extensions.addU16(extensionNextProtoNeg)
751 extension := extensions.addU16LengthPrefixed()
David Benjamin76c2efc2015-08-31 14:24:29 -0400752
753 for _, v := range m.nextProtos {
Nick Harper5212ef82016-06-30 19:26:07 -0400754 if len(v) > 255 {
755 v = v[0:255]
David Benjamin76c2efc2015-08-31 14:24:29 -0400756 }
Nick Harper5212ef82016-06-30 19:26:07 -0400757 npn := extension.addU8LengthPrefixed()
758 npn.addBytes([]byte(v))
David Benjamin76c2efc2015-08-31 14:24:29 -0400759 }
760 }
Adam Langley95c29f32014-06-20 12:00:00 -0700761}
762
Nick Harperb3d51be2016-07-01 11:43:18 -0400763func (m *serverExtensions) unmarshal(data []byte) bool {
764 // Reset all fields.
765 *m = serverExtensions{}
Adam Langley95c29f32014-06-20 12:00:00 -0700766
767 for len(data) != 0 {
768 if len(data) < 4 {
769 return false
770 }
771 extension := uint16(data[0])<<8 | uint16(data[1])
772 length := int(data[2])<<8 | int(data[3])
773 data = data[4:]
774 if len(data) < length {
775 return false
776 }
777
778 switch extension {
779 case extensionNextProtoNeg:
780 m.nextProtoNeg = true
781 d := data[:length]
782 for len(d) > 0 {
783 l := int(d[0])
784 d = d[1:]
785 if l == 0 || l > len(d) {
786 return false
787 }
788 m.nextProtos = append(m.nextProtos, string(d[:l]))
789 d = d[l:]
790 }
791 case extensionStatusRequest:
792 if length > 0 {
793 return false
794 }
795 m.ocspStapling = true
796 case extensionSessionTicket:
797 if length > 0 {
798 return false
799 }
800 m.ticketSupported = true
801 case extensionRenegotiationInfo:
Adam Langley2ae77d22014-10-28 17:29:33 -0700802 if length < 1 || length != int(data[0])+1 {
Adam Langley95c29f32014-06-20 12:00:00 -0700803 return false
804 }
Adam Langley2ae77d22014-10-28 17:29:33 -0700805 m.secureRenegotiation = data[1:length]
David Benjaminfa055a22014-09-15 16:51:51 -0400806 case extensionALPN:
807 d := data[:length]
808 if len(d) < 3 {
809 return false
810 }
811 l := int(d[0])<<8 | int(d[1])
812 if l != len(d)-2 {
813 return false
814 }
815 d = d[2:]
816 l = int(d[0])
817 if l != len(d)-1 {
818 return false
819 }
820 d = d[1:]
821 m.alpnProtocol = string(d)
Adam Langleyefb0e162015-07-09 11:35:04 -0700822 m.alpnProtocolEmpty = len(d) == 0
David Benjamind30a9902014-08-24 01:44:23 -0400823 case extensionChannelID:
824 if length > 0 {
825 return false
826 }
827 m.channelIDRequested = true
Adam Langley75712922014-10-10 16:23:43 -0700828 case extensionExtendedMasterSecret:
829 if length != 0 {
830 return false
831 }
832 m.extendedMasterSecret = true
David Benjaminca6c8262014-11-15 19:06:08 -0500833 case extensionUseSRTP:
834 if length < 2+2+1 {
835 return false
836 }
837 if data[0] != 0 || data[1] != 2 {
838 return false
839 }
840 m.srtpProtectionProfile = uint16(data[2])<<8 | uint16(data[3])
841 d := data[4:length]
842 l := int(d[0])
843 if l != len(d)-1 {
844 return false
845 }
846 m.srtpMasterKeyIdentifier = string(d[1:])
David Benjamin61f95272014-11-25 01:55:35 -0500847 case extensionSignedCertificateTimestamp:
Paul Lietar4fac72e2015-09-09 13:44:55 +0100848 m.sctList = data[:length]
Adam Langley09505632015-07-30 18:10:13 -0700849 case extensionCustom:
850 m.customExtension = string(data[:length])
Adam Langley95c29f32014-06-20 12:00:00 -0700851 }
852 data = data[length:]
853 }
854
855 return true
856}
857
858type certificateMsg struct {
859 raw []byte
860 certificates [][]byte
861}
862
Adam Langley95c29f32014-06-20 12:00:00 -0700863func (m *certificateMsg) marshal() (x []byte) {
864 if m.raw != nil {
865 return m.raw
866 }
867
Nick Harper7e0442a2016-07-01 17:40:09 -0400868 certMsg := newByteBuilder()
869 certMsg.addU8(typeCertificate)
870 certificate := certMsg.addU24LengthPrefixed()
871 certificateList := certificate.addU24LengthPrefixed()
872 for _, cert := range m.certificates {
873 certEntry := certificateList.addU24LengthPrefixed()
874 certEntry.addBytes(cert)
Adam Langley95c29f32014-06-20 12:00:00 -0700875 }
876
Nick Harper7e0442a2016-07-01 17:40:09 -0400877 m.raw = certMsg.finish()
878 return m.raw
Adam Langley95c29f32014-06-20 12:00:00 -0700879}
880
881func (m *certificateMsg) unmarshal(data []byte) bool {
882 if len(data) < 7 {
883 return false
884 }
885
886 m.raw = data
887 certsLen := uint32(data[4])<<16 | uint32(data[5])<<8 | uint32(data[6])
888 if uint32(len(data)) != certsLen+7 {
889 return false
890 }
891
892 numCerts := 0
893 d := data[7:]
894 for certsLen > 0 {
895 if len(d) < 4 {
896 return false
897 }
898 certLen := uint32(d[0])<<16 | uint32(d[1])<<8 | uint32(d[2])
899 if uint32(len(d)) < 3+certLen {
900 return false
901 }
902 d = d[3+certLen:]
903 certsLen -= 3 + certLen
904 numCerts++
905 }
906
907 m.certificates = make([][]byte, numCerts)
908 d = data[7:]
909 for i := 0; i < numCerts; i++ {
910 certLen := uint32(d[0])<<16 | uint32(d[1])<<8 | uint32(d[2])
911 m.certificates[i] = d[3 : 3+certLen]
912 d = d[3+certLen:]
913 }
914
915 return true
916}
917
918type serverKeyExchangeMsg struct {
919 raw []byte
920 key []byte
921}
922
Adam Langley95c29f32014-06-20 12:00:00 -0700923func (m *serverKeyExchangeMsg) marshal() []byte {
924 if m.raw != nil {
925 return m.raw
926 }
927 length := len(m.key)
928 x := make([]byte, length+4)
929 x[0] = typeServerKeyExchange
930 x[1] = uint8(length >> 16)
931 x[2] = uint8(length >> 8)
932 x[3] = uint8(length)
933 copy(x[4:], m.key)
934
935 m.raw = x
936 return x
937}
938
939func (m *serverKeyExchangeMsg) unmarshal(data []byte) bool {
940 m.raw = data
941 if len(data) < 4 {
942 return false
943 }
944 m.key = data[4:]
945 return true
946}
947
948type certificateStatusMsg struct {
949 raw []byte
950 statusType uint8
951 response []byte
952}
953
Adam Langley95c29f32014-06-20 12:00:00 -0700954func (m *certificateStatusMsg) marshal() []byte {
955 if m.raw != nil {
956 return m.raw
957 }
958
959 var x []byte
960 if m.statusType == statusTypeOCSP {
961 x = make([]byte, 4+4+len(m.response))
962 x[0] = typeCertificateStatus
963 l := len(m.response) + 4
964 x[1] = byte(l >> 16)
965 x[2] = byte(l >> 8)
966 x[3] = byte(l)
967 x[4] = statusTypeOCSP
968
969 l -= 4
970 x[5] = byte(l >> 16)
971 x[6] = byte(l >> 8)
972 x[7] = byte(l)
973 copy(x[8:], m.response)
974 } else {
975 x = []byte{typeCertificateStatus, 0, 0, 1, m.statusType}
976 }
977
978 m.raw = x
979 return x
980}
981
982func (m *certificateStatusMsg) unmarshal(data []byte) bool {
983 m.raw = data
984 if len(data) < 5 {
985 return false
986 }
987 m.statusType = data[4]
988
989 m.response = nil
990 if m.statusType == statusTypeOCSP {
991 if len(data) < 8 {
992 return false
993 }
994 respLen := uint32(data[5])<<16 | uint32(data[6])<<8 | uint32(data[7])
995 if uint32(len(data)) != 4+4+respLen {
996 return false
997 }
998 m.response = data[8:]
999 }
1000 return true
1001}
1002
1003type serverHelloDoneMsg struct{}
1004
Adam Langley95c29f32014-06-20 12:00:00 -07001005func (m *serverHelloDoneMsg) marshal() []byte {
1006 x := make([]byte, 4)
1007 x[0] = typeServerHelloDone
1008 return x
1009}
1010
1011func (m *serverHelloDoneMsg) unmarshal(data []byte) bool {
1012 return len(data) == 4
1013}
1014
1015type clientKeyExchangeMsg struct {
1016 raw []byte
1017 ciphertext []byte
1018}
1019
Adam Langley95c29f32014-06-20 12:00:00 -07001020func (m *clientKeyExchangeMsg) marshal() []byte {
1021 if m.raw != nil {
1022 return m.raw
1023 }
1024 length := len(m.ciphertext)
1025 x := make([]byte, length+4)
1026 x[0] = typeClientKeyExchange
1027 x[1] = uint8(length >> 16)
1028 x[2] = uint8(length >> 8)
1029 x[3] = uint8(length)
1030 copy(x[4:], m.ciphertext)
1031
1032 m.raw = x
1033 return x
1034}
1035
1036func (m *clientKeyExchangeMsg) unmarshal(data []byte) bool {
1037 m.raw = data
1038 if len(data) < 4 {
1039 return false
1040 }
1041 l := int(data[1])<<16 | int(data[2])<<8 | int(data[3])
1042 if l != len(data)-4 {
1043 return false
1044 }
1045 m.ciphertext = data[4:]
1046 return true
1047}
1048
1049type finishedMsg struct {
1050 raw []byte
1051 verifyData []byte
1052}
1053
Adam Langley95c29f32014-06-20 12:00:00 -07001054func (m *finishedMsg) marshal() (x []byte) {
1055 if m.raw != nil {
1056 return m.raw
1057 }
1058
1059 x = make([]byte, 4+len(m.verifyData))
1060 x[0] = typeFinished
1061 x[3] = byte(len(m.verifyData))
1062 copy(x[4:], m.verifyData)
1063 m.raw = x
1064 return
1065}
1066
1067func (m *finishedMsg) unmarshal(data []byte) bool {
1068 m.raw = data
1069 if len(data) < 4 {
1070 return false
1071 }
1072 m.verifyData = data[4:]
1073 return true
1074}
1075
1076type nextProtoMsg struct {
1077 raw []byte
1078 proto string
1079}
1080
Adam Langley95c29f32014-06-20 12:00:00 -07001081func (m *nextProtoMsg) marshal() []byte {
1082 if m.raw != nil {
1083 return m.raw
1084 }
1085 l := len(m.proto)
1086 if l > 255 {
1087 l = 255
1088 }
1089
1090 padding := 32 - (l+2)%32
1091 length := l + padding + 2
1092 x := make([]byte, length+4)
1093 x[0] = typeNextProtocol
1094 x[1] = uint8(length >> 16)
1095 x[2] = uint8(length >> 8)
1096 x[3] = uint8(length)
1097
1098 y := x[4:]
1099 y[0] = byte(l)
1100 copy(y[1:], []byte(m.proto[0:l]))
1101 y = y[1+l:]
1102 y[0] = byte(padding)
1103
1104 m.raw = x
1105
1106 return x
1107}
1108
1109func (m *nextProtoMsg) unmarshal(data []byte) bool {
1110 m.raw = data
1111
1112 if len(data) < 5 {
1113 return false
1114 }
1115 data = data[4:]
1116 protoLen := int(data[0])
1117 data = data[1:]
1118 if len(data) < protoLen {
1119 return false
1120 }
1121 m.proto = string(data[0:protoLen])
1122 data = data[protoLen:]
1123
1124 if len(data) < 1 {
1125 return false
1126 }
1127 paddingLen := int(data[0])
1128 data = data[1:]
1129 if len(data) != paddingLen {
1130 return false
1131 }
1132
1133 return true
1134}
1135
1136type certificateRequestMsg struct {
1137 raw []byte
Nick Harper60edffd2016-06-21 15:19:24 -07001138 // hasSignatureAlgorithm indicates whether this message includes a list
Adam Langley95c29f32014-06-20 12:00:00 -07001139 // of signature and hash functions. This change was introduced with TLS
1140 // 1.2.
Nick Harper60edffd2016-06-21 15:19:24 -07001141 hasSignatureAlgorithm bool
Adam Langley95c29f32014-06-20 12:00:00 -07001142
1143 certificateTypes []byte
Nick Harper60edffd2016-06-21 15:19:24 -07001144 signatureAlgorithms []signatureAlgorithm
Adam Langley95c29f32014-06-20 12:00:00 -07001145 certificateAuthorities [][]byte
1146}
1147
Nick Harper7e0442a2016-07-01 17:40:09 -04001148func (m *certificateRequestMsg) marshal() []byte {
Adam Langley95c29f32014-06-20 12:00:00 -07001149 if m.raw != nil {
1150 return m.raw
1151 }
1152
1153 // See http://tools.ietf.org/html/rfc4346#section-7.4.4
Nick Harper7e0442a2016-07-01 17:40:09 -04001154 builder := newByteBuilder()
1155 builder.addU8(typeCertificateRequest)
1156 body := builder.addU24LengthPrefixed()
1157
1158 certificateTypes := body.addU8LengthPrefixed()
1159 certificateTypes.addBytes(m.certificateTypes)
Adam Langley95c29f32014-06-20 12:00:00 -07001160
Nick Harper60edffd2016-06-21 15:19:24 -07001161 if m.hasSignatureAlgorithm {
Nick Harper7e0442a2016-07-01 17:40:09 -04001162 signatureAlgorithms := body.addU16LengthPrefixed()
Nick Harper60edffd2016-06-21 15:19:24 -07001163 for _, sigAlg := range m.signatureAlgorithms {
Nick Harper7e0442a2016-07-01 17:40:09 -04001164 signatureAlgorithms.addU16(uint16(sigAlg))
Adam Langley95c29f32014-06-20 12:00:00 -07001165 }
1166 }
1167
Nick Harper7e0442a2016-07-01 17:40:09 -04001168 certificateAuthorities := body.addU16LengthPrefixed()
Adam Langley95c29f32014-06-20 12:00:00 -07001169 for _, ca := range m.certificateAuthorities {
Nick Harper7e0442a2016-07-01 17:40:09 -04001170 caEntry := certificateAuthorities.addU16LengthPrefixed()
1171 caEntry.addBytes(ca)
Adam Langley95c29f32014-06-20 12:00:00 -07001172 }
1173
Nick Harper7e0442a2016-07-01 17:40:09 -04001174 m.raw = builder.finish()
1175 return m.raw
Adam Langley95c29f32014-06-20 12:00:00 -07001176}
1177
1178func (m *certificateRequestMsg) unmarshal(data []byte) bool {
1179 m.raw = data
1180
1181 if len(data) < 5 {
1182 return false
1183 }
1184
1185 length := uint32(data[1])<<16 | uint32(data[2])<<8 | uint32(data[3])
1186 if uint32(len(data))-4 != length {
1187 return false
1188 }
1189
1190 numCertTypes := int(data[4])
1191 data = data[5:]
1192 if numCertTypes == 0 || len(data) <= numCertTypes {
1193 return false
1194 }
1195
1196 m.certificateTypes = make([]byte, numCertTypes)
1197 if copy(m.certificateTypes, data) != numCertTypes {
1198 return false
1199 }
1200
1201 data = data[numCertTypes:]
1202
Nick Harper60edffd2016-06-21 15:19:24 -07001203 if m.hasSignatureAlgorithm {
Adam Langley95c29f32014-06-20 12:00:00 -07001204 if len(data) < 2 {
1205 return false
1206 }
Nick Harper60edffd2016-06-21 15:19:24 -07001207 sigAlgsLen := uint16(data[0])<<8 | uint16(data[1])
Adam Langley95c29f32014-06-20 12:00:00 -07001208 data = data[2:]
Nick Harper60edffd2016-06-21 15:19:24 -07001209 if sigAlgsLen&1 != 0 {
Adam Langley95c29f32014-06-20 12:00:00 -07001210 return false
1211 }
Nick Harper60edffd2016-06-21 15:19:24 -07001212 if len(data) < int(sigAlgsLen) {
Adam Langley95c29f32014-06-20 12:00:00 -07001213 return false
1214 }
Nick Harper60edffd2016-06-21 15:19:24 -07001215 numSigAlgs := sigAlgsLen / 2
1216 m.signatureAlgorithms = make([]signatureAlgorithm, numSigAlgs)
1217 for i := range m.signatureAlgorithms {
1218 m.signatureAlgorithms[i] = signatureAlgorithm(data[0])<<8 | signatureAlgorithm(data[1])
Adam Langley95c29f32014-06-20 12:00:00 -07001219 data = data[2:]
1220 }
1221 }
1222
1223 if len(data) < 2 {
1224 return false
1225 }
1226 casLength := uint16(data[0])<<8 | uint16(data[1])
1227 data = data[2:]
1228 if len(data) < int(casLength) {
1229 return false
1230 }
1231 cas := make([]byte, casLength)
1232 copy(cas, data)
1233 data = data[casLength:]
1234
1235 m.certificateAuthorities = nil
1236 for len(cas) > 0 {
1237 if len(cas) < 2 {
1238 return false
1239 }
1240 caLen := uint16(cas[0])<<8 | uint16(cas[1])
1241 cas = cas[2:]
1242
1243 if len(cas) < int(caLen) {
1244 return false
1245 }
1246
1247 m.certificateAuthorities = append(m.certificateAuthorities, cas[:caLen])
1248 cas = cas[caLen:]
1249 }
1250 if len(data) > 0 {
1251 return false
1252 }
1253
1254 return true
1255}
1256
1257type certificateVerifyMsg struct {
Nick Harper60edffd2016-06-21 15:19:24 -07001258 raw []byte
1259 hasSignatureAlgorithm bool
1260 signatureAlgorithm signatureAlgorithm
1261 signature []byte
Adam Langley95c29f32014-06-20 12:00:00 -07001262}
1263
Adam Langley95c29f32014-06-20 12:00:00 -07001264func (m *certificateVerifyMsg) marshal() (x []byte) {
1265 if m.raw != nil {
1266 return m.raw
1267 }
1268
1269 // See http://tools.ietf.org/html/rfc4346#section-7.4.8
1270 siglength := len(m.signature)
1271 length := 2 + siglength
Nick Harper60edffd2016-06-21 15:19:24 -07001272 if m.hasSignatureAlgorithm {
Adam Langley95c29f32014-06-20 12:00:00 -07001273 length += 2
1274 }
1275 x = make([]byte, 4+length)
1276 x[0] = typeCertificateVerify
1277 x[1] = uint8(length >> 16)
1278 x[2] = uint8(length >> 8)
1279 x[3] = uint8(length)
1280 y := x[4:]
Nick Harper60edffd2016-06-21 15:19:24 -07001281 if m.hasSignatureAlgorithm {
1282 y[0] = byte(m.signatureAlgorithm >> 8)
1283 y[1] = byte(m.signatureAlgorithm)
Adam Langley95c29f32014-06-20 12:00:00 -07001284 y = y[2:]
1285 }
1286 y[0] = uint8(siglength >> 8)
1287 y[1] = uint8(siglength)
1288 copy(y[2:], m.signature)
1289
1290 m.raw = x
1291
1292 return
1293}
1294
1295func (m *certificateVerifyMsg) unmarshal(data []byte) bool {
1296 m.raw = data
1297
1298 if len(data) < 6 {
1299 return false
1300 }
1301
1302 length := uint32(data[1])<<16 | uint32(data[2])<<8 | uint32(data[3])
1303 if uint32(len(data))-4 != length {
1304 return false
1305 }
1306
1307 data = data[4:]
Nick Harper60edffd2016-06-21 15:19:24 -07001308 if m.hasSignatureAlgorithm {
1309 m.signatureAlgorithm = signatureAlgorithm(data[0])<<8 | signatureAlgorithm(data[1])
Adam Langley95c29f32014-06-20 12:00:00 -07001310 data = data[2:]
1311 }
1312
1313 if len(data) < 2 {
1314 return false
1315 }
1316 siglength := int(data[0])<<8 + int(data[1])
1317 data = data[2:]
1318 if len(data) != siglength {
1319 return false
1320 }
1321
1322 m.signature = data
1323
1324 return true
1325}
1326
1327type newSessionTicketMsg struct {
1328 raw []byte
1329 ticket []byte
1330}
1331
Adam Langley95c29f32014-06-20 12:00:00 -07001332func (m *newSessionTicketMsg) marshal() (x []byte) {
1333 if m.raw != nil {
1334 return m.raw
1335 }
1336
1337 // See http://tools.ietf.org/html/rfc5077#section-3.3
1338 ticketLen := len(m.ticket)
1339 length := 2 + 4 + ticketLen
1340 x = make([]byte, 4+length)
1341 x[0] = typeNewSessionTicket
1342 x[1] = uint8(length >> 16)
1343 x[2] = uint8(length >> 8)
1344 x[3] = uint8(length)
1345 x[8] = uint8(ticketLen >> 8)
1346 x[9] = uint8(ticketLen)
1347 copy(x[10:], m.ticket)
1348
1349 m.raw = x
1350
1351 return
1352}
1353
1354func (m *newSessionTicketMsg) unmarshal(data []byte) bool {
1355 m.raw = data
1356
1357 if len(data) < 10 {
1358 return false
1359 }
1360
1361 length := uint32(data[1])<<16 | uint32(data[2])<<8 | uint32(data[3])
1362 if uint32(len(data))-4 != length {
1363 return false
1364 }
1365
1366 ticketLen := int(data[8])<<8 + int(data[9])
1367 if len(data)-10 != ticketLen {
1368 return false
1369 }
1370
1371 m.ticket = data[10:]
1372
1373 return true
1374}
1375
David Benjamind86c7672014-08-02 04:07:12 -04001376type v2ClientHelloMsg struct {
1377 raw []byte
1378 vers uint16
1379 cipherSuites []uint16
1380 sessionId []byte
1381 challenge []byte
1382}
1383
David Benjamind86c7672014-08-02 04:07:12 -04001384func (m *v2ClientHelloMsg) marshal() []byte {
1385 if m.raw != nil {
1386 return m.raw
1387 }
1388
1389 length := 1 + 2 + 2 + 2 + 2 + len(m.cipherSuites)*3 + len(m.sessionId) + len(m.challenge)
1390
1391 x := make([]byte, length)
1392 x[0] = 1
1393 x[1] = uint8(m.vers >> 8)
1394 x[2] = uint8(m.vers)
1395 x[3] = uint8((len(m.cipherSuites) * 3) >> 8)
1396 x[4] = uint8(len(m.cipherSuites) * 3)
1397 x[5] = uint8(len(m.sessionId) >> 8)
1398 x[6] = uint8(len(m.sessionId))
1399 x[7] = uint8(len(m.challenge) >> 8)
1400 x[8] = uint8(len(m.challenge))
1401 y := x[9:]
1402 for i, spec := range m.cipherSuites {
1403 y[i*3] = 0
1404 y[i*3+1] = uint8(spec >> 8)
1405 y[i*3+2] = uint8(spec)
1406 }
1407 y = y[len(m.cipherSuites)*3:]
1408 copy(y, m.sessionId)
1409 y = y[len(m.sessionId):]
1410 copy(y, m.challenge)
1411
1412 m.raw = x
1413
1414 return x
1415}
1416
David Benjamin83c0bc92014-08-04 01:23:53 -04001417type helloVerifyRequestMsg struct {
1418 raw []byte
1419 vers uint16
1420 cookie []byte
1421}
1422
David Benjamin83c0bc92014-08-04 01:23:53 -04001423func (m *helloVerifyRequestMsg) marshal() []byte {
1424 if m.raw != nil {
1425 return m.raw
1426 }
1427
1428 length := 2 + 1 + len(m.cookie)
1429
1430 x := make([]byte, 4+length)
1431 x[0] = typeHelloVerifyRequest
1432 x[1] = uint8(length >> 16)
1433 x[2] = uint8(length >> 8)
1434 x[3] = uint8(length)
1435 vers := versionToWire(m.vers, true)
1436 x[4] = uint8(vers >> 8)
1437 x[5] = uint8(vers)
1438 x[6] = uint8(len(m.cookie))
1439 copy(x[7:7+len(m.cookie)], m.cookie)
1440
1441 return x
1442}
1443
1444func (m *helloVerifyRequestMsg) unmarshal(data []byte) bool {
1445 if len(data) < 4+2+1 {
1446 return false
1447 }
1448 m.raw = data
1449 m.vers = wireToVersion(uint16(data[4])<<8|uint16(data[5]), true)
1450 cookieLen := int(data[6])
1451 if cookieLen > 32 || len(data) != 7+cookieLen {
1452 return false
1453 }
1454 m.cookie = data[7 : 7+cookieLen]
1455
1456 return true
1457}
1458
David Benjamin24599a82016-06-30 18:56:53 -04001459type channelIDMsg struct {
David Benjamind30a9902014-08-24 01:44:23 -04001460 raw []byte
1461 channelID []byte
1462}
1463
David Benjamin24599a82016-06-30 18:56:53 -04001464func (m *channelIDMsg) marshal() []byte {
David Benjamind30a9902014-08-24 01:44:23 -04001465 if m.raw != nil {
1466 return m.raw
1467 }
1468
1469 length := 2 + 2 + len(m.channelID)
1470
1471 x := make([]byte, 4+length)
David Benjamin24599a82016-06-30 18:56:53 -04001472 x[0] = typeChannelID
David Benjamind30a9902014-08-24 01:44:23 -04001473 x[1] = uint8(length >> 16)
1474 x[2] = uint8(length >> 8)
1475 x[3] = uint8(length)
1476 x[4] = uint8(extensionChannelID >> 8)
1477 x[5] = uint8(extensionChannelID & 0xff)
1478 x[6] = uint8(len(m.channelID) >> 8)
1479 x[7] = uint8(len(m.channelID) & 0xff)
1480 copy(x[8:], m.channelID)
1481
1482 return x
1483}
1484
David Benjamin24599a82016-06-30 18:56:53 -04001485func (m *channelIDMsg) unmarshal(data []byte) bool {
David Benjamind30a9902014-08-24 01:44:23 -04001486 if len(data) != 4+2+2+128 {
1487 return false
1488 }
1489 m.raw = data
1490 if (uint16(data[4])<<8)|uint16(data[5]) != extensionChannelID {
1491 return false
1492 }
1493 if int(data[6])<<8|int(data[7]) != 128 {
1494 return false
1495 }
1496 m.channelID = data[4+2+2:]
1497
1498 return true
1499}
1500
Adam Langley2ae77d22014-10-28 17:29:33 -07001501type helloRequestMsg struct {
1502}
1503
1504func (*helloRequestMsg) marshal() []byte {
1505 return []byte{typeHelloRequest, 0, 0, 0}
1506}
1507
1508func (*helloRequestMsg) unmarshal(data []byte) bool {
1509 return len(data) == 4
1510}
1511
Adam Langley95c29f32014-06-20 12:00:00 -07001512func eqUint16s(x, y []uint16) bool {
1513 if len(x) != len(y) {
1514 return false
1515 }
1516 for i, v := range x {
1517 if y[i] != v {
1518 return false
1519 }
1520 }
1521 return true
1522}
1523
1524func eqCurveIDs(x, y []CurveID) bool {
1525 if len(x) != len(y) {
1526 return false
1527 }
1528 for i, v := range x {
1529 if y[i] != v {
1530 return false
1531 }
1532 }
1533 return true
1534}
1535
1536func eqStrings(x, y []string) bool {
1537 if len(x) != len(y) {
1538 return false
1539 }
1540 for i, v := range x {
1541 if y[i] != v {
1542 return false
1543 }
1544 }
1545 return true
1546}
1547
1548func eqByteSlices(x, y [][]byte) bool {
1549 if len(x) != len(y) {
1550 return false
1551 }
1552 for i, v := range x {
1553 if !bytes.Equal(v, y[i]) {
1554 return false
1555 }
1556 }
1557 return true
1558}
1559
Nick Harper60edffd2016-06-21 15:19:24 -07001560func eqSignatureAlgorithms(x, y []signatureAlgorithm) bool {
Adam Langley95c29f32014-06-20 12:00:00 -07001561 if len(x) != len(y) {
1562 return false
1563 }
1564 for i, v := range x {
1565 v2 := y[i]
Nick Harper60edffd2016-06-21 15:19:24 -07001566 if v != v2 {
Adam Langley95c29f32014-06-20 12:00:00 -07001567 return false
1568 }
1569 }
1570 return true
1571}