blob: b92735e5806839e9c244debb22ac8b6ed336f0e2 [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
Nick Harper0b3625b2016-07-25 16:16:28 -07007import (
8 "bytes"
9 "encoding/binary"
10)
Adam Langley95c29f32014-06-20 12:00:00 -070011
Nick Harper8dda5cc2016-06-30 18:51:11 -040012func writeLen(buf []byte, v, size int) {
13 for i := 0; i < size; i++ {
14 buf[size-i-1] = byte(v)
15 v >>= 8
16 }
17 if v != 0 {
18 panic("length is too long")
19 }
20}
21
22type byteBuilder struct {
23 buf *[]byte
24 start int
25 prefixLen int
26 child *byteBuilder
27}
28
29func newByteBuilder() *byteBuilder {
30 buf := make([]byte, 0, 32)
31 return &byteBuilder{buf: &buf}
32}
33
34func (bb *byteBuilder) len() int {
35 return len(*bb.buf) - bb.start - bb.prefixLen
36}
37
38func (bb *byteBuilder) flush() {
39 if bb.child == nil {
40 return
41 }
42 bb.child.flush()
43 writeLen((*bb.buf)[bb.child.start:], bb.child.len(), bb.child.prefixLen)
44 bb.child = nil
45 return
46}
47
48func (bb *byteBuilder) finish() []byte {
49 bb.flush()
50 return *bb.buf
51}
52
53func (bb *byteBuilder) addU8(u uint8) {
54 bb.flush()
55 *bb.buf = append(*bb.buf, u)
56}
57
58func (bb *byteBuilder) addU16(u uint16) {
59 bb.flush()
60 *bb.buf = append(*bb.buf, byte(u>>8), byte(u))
61}
62
63func (bb *byteBuilder) addU24(u int) {
64 bb.flush()
65 *bb.buf = append(*bb.buf, byte(u>>16), byte(u>>8), byte(u))
66}
67
68func (bb *byteBuilder) addU32(u uint32) {
69 bb.flush()
70 *bb.buf = append(*bb.buf, byte(u>>24), byte(u>>16), byte(u>>8), byte(u))
71}
72
Nick Harper0b3625b2016-07-25 16:16:28 -070073func (bb *byteBuilder) addU64(u uint64) {
74 bb.flush()
75 var b [8]byte
76 binary.BigEndian.PutUint64(b[:], u)
77 *bb.buf = append(*bb.buf, b[:]...)
78}
79
Nick Harper8dda5cc2016-06-30 18:51:11 -040080func (bb *byteBuilder) addU8LengthPrefixed() *byteBuilder {
81 return bb.createChild(1)
82}
83
84func (bb *byteBuilder) addU16LengthPrefixed() *byteBuilder {
85 return bb.createChild(2)
86}
87
88func (bb *byteBuilder) addU24LengthPrefixed() *byteBuilder {
89 return bb.createChild(3)
90}
91
Nick Harper0b3625b2016-07-25 16:16:28 -070092func (bb *byteBuilder) addU32LengthPrefixed() *byteBuilder {
93 return bb.createChild(4)
94}
95
Nick Harper8dda5cc2016-06-30 18:51:11 -040096func (bb *byteBuilder) addBytes(b []byte) {
97 bb.flush()
98 *bb.buf = append(*bb.buf, b...)
99}
100
101func (bb *byteBuilder) createChild(lengthPrefixSize int) *byteBuilder {
102 bb.flush()
103 bb.child = &byteBuilder{
104 buf: bb.buf,
105 start: len(*bb.buf),
106 prefixLen: lengthPrefixSize,
107 }
108 for i := 0; i < lengthPrefixSize; i++ {
109 *bb.buf = append(*bb.buf, 0)
110 }
111 return bb.child
112}
113
114func (bb *byteBuilder) discardChild() {
115 if bb.child != nil {
116 return
117 }
118 bb.child = nil
119 *bb.buf = (*bb.buf)[:bb.start]
120}
121
Nick Harperf8b0e702016-06-30 19:59:01 -0400122type keyShareEntry struct {
123 group CurveID
124 keyExchange []byte
125}
126
Steven Valdez5b986082016-09-01 12:29:49 -0400127type pskIdentity struct {
128 keModes []byte
129 authModes []byte
130 ticket []uint8
131}
132
Adam Langley95c29f32014-06-20 12:00:00 -0700133type clientHelloMsg struct {
Nick Harperb41d2e42016-07-01 17:50:32 -0400134 raw []byte
135 isDTLS bool
136 vers uint16
137 random []byte
138 sessionId []byte
139 // TODO(davidben): Add support for TLS 1.3 cookies which are larger and
140 // use an extension.
David Benjaminca6c8262014-11-15 19:06:08 -0500141 cookie []byte
142 cipherSuites []uint16
143 compressionMethods []uint8
144 nextProtoNeg bool
145 serverName string
146 ocspStapling bool
147 supportedCurves []CurveID
148 supportedPoints []uint8
Nick Harperdcfbc672016-07-16 17:47:31 +0200149 hasKeyShares bool
Nick Harperf8b0e702016-06-30 19:59:01 -0400150 keyShares []keyShareEntry
David Benjamin7e1f9842016-09-20 19:24:40 -0400151 trailingKeyShareData bool
Steven Valdez5b986082016-09-01 12:29:49 -0400152 pskIdentities []pskIdentity
Nick Harperf8b0e702016-06-30 19:59:01 -0400153 hasEarlyData bool
154 earlyDataContext []byte
David Benjaminca6c8262014-11-15 19:06:08 -0500155 ticketSupported bool
156 sessionTicket []uint8
Nick Harper60edffd2016-06-21 15:19:24 -0700157 signatureAlgorithms []signatureAlgorithm
Steven Valdezfdd10992016-09-15 16:27:05 -0400158 supportedVersions []uint16
David Benjaminca6c8262014-11-15 19:06:08 -0500159 secureRenegotiation []byte
160 alpnProtocols []string
161 duplicateExtension bool
162 channelIDSupported bool
163 npnLast bool
164 extendedMasterSecret bool
165 srtpProtectionProfiles []uint16
166 srtpMasterKeyIdentifier string
David Benjamin61f95272014-11-25 01:55:35 -0500167 sctListSupported bool
Adam Langley09505632015-07-30 18:10:13 -0700168 customExtension string
David Benjamin65ac9972016-09-02 21:35:25 -0400169 hasGREASEExtension bool
Adam Langley95c29f32014-06-20 12:00:00 -0700170}
171
172func (m *clientHelloMsg) equal(i interface{}) bool {
173 m1, ok := i.(*clientHelloMsg)
174 if !ok {
175 return false
176 }
177
178 return bytes.Equal(m.raw, m1.raw) &&
David Benjamin83c0bc92014-08-04 01:23:53 -0400179 m.isDTLS == m1.isDTLS &&
Adam Langley95c29f32014-06-20 12:00:00 -0700180 m.vers == m1.vers &&
181 bytes.Equal(m.random, m1.random) &&
182 bytes.Equal(m.sessionId, m1.sessionId) &&
David Benjamin83c0bc92014-08-04 01:23:53 -0400183 bytes.Equal(m.cookie, m1.cookie) &&
Adam Langley95c29f32014-06-20 12:00:00 -0700184 eqUint16s(m.cipherSuites, m1.cipherSuites) &&
185 bytes.Equal(m.compressionMethods, m1.compressionMethods) &&
186 m.nextProtoNeg == m1.nextProtoNeg &&
187 m.serverName == m1.serverName &&
188 m.ocspStapling == m1.ocspStapling &&
189 eqCurveIDs(m.supportedCurves, m1.supportedCurves) &&
190 bytes.Equal(m.supportedPoints, m1.supportedPoints) &&
Nick Harperdcfbc672016-07-16 17:47:31 +0200191 m.hasKeyShares == m1.hasKeyShares &&
Nick Harperf8b0e702016-06-30 19:59:01 -0400192 eqKeyShareEntryLists(m.keyShares, m1.keyShares) &&
David Benjamin7e1f9842016-09-20 19:24:40 -0400193 m.trailingKeyShareData == m1.trailingKeyShareData &&
Steven Valdez5b986082016-09-01 12:29:49 -0400194 eqPSKIdentityLists(m.pskIdentities, m1.pskIdentities) &&
Nick Harperf8b0e702016-06-30 19:59:01 -0400195 m.hasEarlyData == m1.hasEarlyData &&
196 bytes.Equal(m.earlyDataContext, m1.earlyDataContext) &&
Adam Langley95c29f32014-06-20 12:00:00 -0700197 m.ticketSupported == m1.ticketSupported &&
198 bytes.Equal(m.sessionTicket, m1.sessionTicket) &&
Nick Harper60edffd2016-06-21 15:19:24 -0700199 eqSignatureAlgorithms(m.signatureAlgorithms, m1.signatureAlgorithms) &&
Steven Valdezfdd10992016-09-15 16:27:05 -0400200 eqUint16s(m.supportedVersions, m1.supportedVersions) &&
Adam Langley2ae77d22014-10-28 17:29:33 -0700201 bytes.Equal(m.secureRenegotiation, m1.secureRenegotiation) &&
202 (m.secureRenegotiation == nil) == (m1.secureRenegotiation == nil) &&
David Benjaminfa055a22014-09-15 16:51:51 -0400203 eqStrings(m.alpnProtocols, m1.alpnProtocols) &&
David Benjamind30a9902014-08-24 01:44:23 -0400204 m.duplicateExtension == m1.duplicateExtension &&
David Benjaminfc7b0862014-09-06 13:21:53 -0400205 m.channelIDSupported == m1.channelIDSupported &&
Adam Langley75712922014-10-10 16:23:43 -0700206 m.npnLast == m1.npnLast &&
David Benjaminca6c8262014-11-15 19:06:08 -0500207 m.extendedMasterSecret == m1.extendedMasterSecret &&
208 eqUint16s(m.srtpProtectionProfiles, m1.srtpProtectionProfiles) &&
David Benjamin61f95272014-11-25 01:55:35 -0500209 m.srtpMasterKeyIdentifier == m1.srtpMasterKeyIdentifier &&
Adam Langley09505632015-07-30 18:10:13 -0700210 m.sctListSupported == m1.sctListSupported &&
David Benjamin65ac9972016-09-02 21:35:25 -0400211 m.customExtension == m1.customExtension &&
212 m.hasGREASEExtension == m1.hasGREASEExtension
Adam Langley95c29f32014-06-20 12:00:00 -0700213}
214
215func (m *clientHelloMsg) marshal() []byte {
216 if m.raw != nil {
217 return m.raw
218 }
219
Nick Harper8dda5cc2016-06-30 18:51:11 -0400220 handshakeMsg := newByteBuilder()
221 handshakeMsg.addU8(typeClientHello)
222 hello := handshakeMsg.addU24LengthPrefixed()
David Benjamin3c6a1ea2016-09-26 18:30:05 -0400223 hello.addU16(m.vers)
Nick Harper8dda5cc2016-06-30 18:51:11 -0400224 hello.addBytes(m.random)
225 sessionId := hello.addU8LengthPrefixed()
226 sessionId.addBytes(m.sessionId)
David Benjamin83c0bc92014-08-04 01:23:53 -0400227 if m.isDTLS {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400228 cookie := hello.addU8LengthPrefixed()
229 cookie.addBytes(m.cookie)
David Benjamin83c0bc92014-08-04 01:23:53 -0400230 }
Nick Harper8dda5cc2016-06-30 18:51:11 -0400231 cipherSuites := hello.addU16LengthPrefixed()
232 for _, suite := range m.cipherSuites {
233 cipherSuites.addU16(suite)
Adam Langley95c29f32014-06-20 12:00:00 -0700234 }
Nick Harper8dda5cc2016-06-30 18:51:11 -0400235 compressionMethods := hello.addU8LengthPrefixed()
236 compressionMethods.addBytes(m.compressionMethods)
Adam Langley95c29f32014-06-20 12:00:00 -0700237
Nick Harper8dda5cc2016-06-30 18:51:11 -0400238 extensions := hello.addU16LengthPrefixed()
David Benjamin35a7a442014-07-05 00:23:20 -0400239 if m.duplicateExtension {
240 // Add a duplicate bogus extension at the beginning and end.
Nick Harper8dda5cc2016-06-30 18:51:11 -0400241 extensions.addU16(0xffff)
242 extensions.addU16(0) // 0-length for empty extension
David Benjamin35a7a442014-07-05 00:23:20 -0400243 }
David Benjaminfc7b0862014-09-06 13:21:53 -0400244 if m.nextProtoNeg && !m.npnLast {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400245 extensions.addU16(extensionNextProtoNeg)
246 extensions.addU16(0) // The length is always 0
Adam Langley95c29f32014-06-20 12:00:00 -0700247 }
248 if len(m.serverName) > 0 {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400249 extensions.addU16(extensionServerName)
250 serverNameList := extensions.addU16LengthPrefixed()
Adam Langley95c29f32014-06-20 12:00:00 -0700251
252 // RFC 3546, section 3.1
253 //
254 // struct {
255 // NameType name_type;
256 // select (name_type) {
257 // case host_name: HostName;
258 // } name;
259 // } ServerName;
260 //
261 // enum {
262 // host_name(0), (255)
263 // } NameType;
264 //
265 // opaque HostName<1..2^16-1>;
266 //
267 // struct {
268 // ServerName server_name_list<1..2^16-1>
269 // } ServerNameList;
270
Nick Harper8dda5cc2016-06-30 18:51:11 -0400271 serverName := serverNameList.addU16LengthPrefixed()
272 serverName.addU8(0) // NameType host_name(0)
273 hostName := serverName.addU16LengthPrefixed()
274 hostName.addBytes([]byte(m.serverName))
Adam Langley95c29f32014-06-20 12:00:00 -0700275 }
276 if m.ocspStapling {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400277 extensions.addU16(extensionStatusRequest)
278 certificateStatusRequest := extensions.addU16LengthPrefixed()
279
Adam Langley95c29f32014-06-20 12:00:00 -0700280 // RFC 4366, section 3.6
Nick Harper8dda5cc2016-06-30 18:51:11 -0400281 certificateStatusRequest.addU8(1) // OCSP type
Adam Langley95c29f32014-06-20 12:00:00 -0700282 // Two zero valued uint16s for the two lengths.
Nick Harper8dda5cc2016-06-30 18:51:11 -0400283 certificateStatusRequest.addU16(0) // ResponderID length
284 certificateStatusRequest.addU16(0) // Extensions length
Adam Langley95c29f32014-06-20 12:00:00 -0700285 }
286 if len(m.supportedCurves) > 0 {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400287 // http://tools.ietf.org/html/rfc4492#section-5.1.1
288 extensions.addU16(extensionSupportedCurves)
289 supportedCurvesList := extensions.addU16LengthPrefixed()
290 supportedCurves := supportedCurvesList.addU16LengthPrefixed()
Adam Langley95c29f32014-06-20 12:00:00 -0700291 for _, curve := range m.supportedCurves {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400292 supportedCurves.addU16(uint16(curve))
Adam Langley95c29f32014-06-20 12:00:00 -0700293 }
294 }
295 if len(m.supportedPoints) > 0 {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400296 // http://tools.ietf.org/html/rfc4492#section-5.1.2
297 extensions.addU16(extensionSupportedPoints)
298 supportedPointsList := extensions.addU16LengthPrefixed()
299 supportedPoints := supportedPointsList.addU8LengthPrefixed()
Adam Langley95c29f32014-06-20 12:00:00 -0700300 for _, pointFormat := range m.supportedPoints {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400301 supportedPoints.addU8(pointFormat)
Adam Langley95c29f32014-06-20 12:00:00 -0700302 }
303 }
Nick Harperdcfbc672016-07-16 17:47:31 +0200304 if m.hasKeyShares {
Nick Harperf8b0e702016-06-30 19:59:01 -0400305 extensions.addU16(extensionKeyShare)
306 keyShareList := extensions.addU16LengthPrefixed()
307
308 keyShares := keyShareList.addU16LengthPrefixed()
309 for _, keyShare := range m.keyShares {
310 keyShares.addU16(uint16(keyShare.group))
311 keyExchange := keyShares.addU16LengthPrefixed()
312 keyExchange.addBytes(keyShare.keyExchange)
313 }
David Benjamin7e1f9842016-09-20 19:24:40 -0400314
315 if m.trailingKeyShareData {
316 keyShares.addU8(0)
317 }
Nick Harperf8b0e702016-06-30 19:59:01 -0400318 }
319 if len(m.pskIdentities) > 0 {
320 extensions.addU16(extensionPreSharedKey)
321 pskExtension := extensions.addU16LengthPrefixed()
322
323 pskIdentities := pskExtension.addU16LengthPrefixed()
324 for _, psk := range m.pskIdentities {
Steven Valdez5b986082016-09-01 12:29:49 -0400325 pskIdentities.addU8LengthPrefixed().addBytes(psk.keModes)
326 pskIdentities.addU8LengthPrefixed().addBytes(psk.authModes)
327 pskIdentities.addU16LengthPrefixed().addBytes(psk.ticket)
Nick Harperf8b0e702016-06-30 19:59:01 -0400328 }
329 }
330 if m.hasEarlyData {
331 extensions.addU16(extensionEarlyData)
332 earlyDataIndication := extensions.addU16LengthPrefixed()
333
334 context := earlyDataIndication.addU8LengthPrefixed()
335 context.addBytes(m.earlyDataContext)
336 }
Adam Langley95c29f32014-06-20 12:00:00 -0700337 if m.ticketSupported {
338 // http://tools.ietf.org/html/rfc5077#section-3.2
Nick Harper8dda5cc2016-06-30 18:51:11 -0400339 extensions.addU16(extensionSessionTicket)
340 sessionTicketExtension := extensions.addU16LengthPrefixed()
341 sessionTicketExtension.addBytes(m.sessionTicket)
Adam Langley95c29f32014-06-20 12:00:00 -0700342 }
Nick Harper60edffd2016-06-21 15:19:24 -0700343 if len(m.signatureAlgorithms) > 0 {
Adam Langley95c29f32014-06-20 12:00:00 -0700344 // https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
Nick Harper8dda5cc2016-06-30 18:51:11 -0400345 extensions.addU16(extensionSignatureAlgorithms)
346 signatureAlgorithmsExtension := extensions.addU16LengthPrefixed()
347 signatureAlgorithms := signatureAlgorithmsExtension.addU16LengthPrefixed()
Nick Harper60edffd2016-06-21 15:19:24 -0700348 for _, sigAlg := range m.signatureAlgorithms {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400349 signatureAlgorithms.addU16(uint16(sigAlg))
Adam Langley95c29f32014-06-20 12:00:00 -0700350 }
351 }
Steven Valdezfdd10992016-09-15 16:27:05 -0400352 if len(m.supportedVersions) > 0 {
353 extensions.addU16(extensionSupportedVersions)
354 supportedVersionsExtension := extensions.addU16LengthPrefixed()
355 supportedVersions := supportedVersionsExtension.addU8LengthPrefixed()
356 for _, version := range m.supportedVersions {
357 supportedVersions.addU16(uint16(version))
358 }
359 }
Adam Langley2ae77d22014-10-28 17:29:33 -0700360 if m.secureRenegotiation != nil {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400361 extensions.addU16(extensionRenegotiationInfo)
362 secureRenegoExt := extensions.addU16LengthPrefixed()
363 secureRenego := secureRenegoExt.addU8LengthPrefixed()
364 secureRenego.addBytes(m.secureRenegotiation)
Adam Langley95c29f32014-06-20 12:00:00 -0700365 }
David Benjaminfa055a22014-09-15 16:51:51 -0400366 if len(m.alpnProtocols) > 0 {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400367 // https://tools.ietf.org/html/rfc7301#section-3.1
368 extensions.addU16(extensionALPN)
369 alpnExtension := extensions.addU16LengthPrefixed()
David Benjaminfa055a22014-09-15 16:51:51 -0400370
Nick Harper8dda5cc2016-06-30 18:51:11 -0400371 protocolNameList := alpnExtension.addU16LengthPrefixed()
David Benjaminfa055a22014-09-15 16:51:51 -0400372 for _, s := range m.alpnProtocols {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400373 protocolName := protocolNameList.addU8LengthPrefixed()
374 protocolName.addBytes([]byte(s))
David Benjaminfa055a22014-09-15 16:51:51 -0400375 }
David Benjaminfa055a22014-09-15 16:51:51 -0400376 }
David Benjamind30a9902014-08-24 01:44:23 -0400377 if m.channelIDSupported {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400378 extensions.addU16(extensionChannelID)
379 extensions.addU16(0) // Length is always 0
David Benjamind30a9902014-08-24 01:44:23 -0400380 }
David Benjaminfc7b0862014-09-06 13:21:53 -0400381 if m.nextProtoNeg && m.npnLast {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400382 extensions.addU16(extensionNextProtoNeg)
383 extensions.addU16(0) // Length is always 0
David Benjaminfc7b0862014-09-06 13:21:53 -0400384 }
David Benjamin35a7a442014-07-05 00:23:20 -0400385 if m.duplicateExtension {
386 // Add a duplicate bogus extension at the beginning and end.
Nick Harper8dda5cc2016-06-30 18:51:11 -0400387 extensions.addU16(0xffff)
388 extensions.addU16(0)
David Benjamin35a7a442014-07-05 00:23:20 -0400389 }
Adam Langley75712922014-10-10 16:23:43 -0700390 if m.extendedMasterSecret {
David Benjamin43946d42016-02-01 08:42:19 -0500391 // https://tools.ietf.org/html/rfc7627
Nick Harper8dda5cc2016-06-30 18:51:11 -0400392 extensions.addU16(extensionExtendedMasterSecret)
393 extensions.addU16(0) // Length is always 0
Adam Langley75712922014-10-10 16:23:43 -0700394 }
David Benjaminca6c8262014-11-15 19:06:08 -0500395 if len(m.srtpProtectionProfiles) > 0 {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400396 // https://tools.ietf.org/html/rfc5764#section-4.1.1
397 extensions.addU16(extensionUseSRTP)
398 useSrtpExt := extensions.addU16LengthPrefixed()
David Benjaminca6c8262014-11-15 19:06:08 -0500399
Nick Harper8dda5cc2016-06-30 18:51:11 -0400400 srtpProtectionProfiles := useSrtpExt.addU16LengthPrefixed()
David Benjaminca6c8262014-11-15 19:06:08 -0500401 for _, p := range m.srtpProtectionProfiles {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400402 // An SRTPProtectionProfile is defined as uint8[2],
403 // not uint16. For some reason, we're storing it
404 // as a uint16.
405 srtpProtectionProfiles.addU8(byte(p >> 8))
406 srtpProtectionProfiles.addU8(byte(p))
David Benjaminca6c8262014-11-15 19:06:08 -0500407 }
Nick Harper8dda5cc2016-06-30 18:51:11 -0400408 srtpMki := useSrtpExt.addU8LengthPrefixed()
409 srtpMki.addBytes([]byte(m.srtpMasterKeyIdentifier))
David Benjaminca6c8262014-11-15 19:06:08 -0500410 }
David Benjamin61f95272014-11-25 01:55:35 -0500411 if m.sctListSupported {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400412 extensions.addU16(extensionSignedCertificateTimestamp)
413 extensions.addU16(0) // Length is always 0
David Benjamin61f95272014-11-25 01:55:35 -0500414 }
Adam Langley09505632015-07-30 18:10:13 -0700415 if l := len(m.customExtension); l > 0 {
Nick Harper8dda5cc2016-06-30 18:51:11 -0400416 extensions.addU16(extensionCustom)
417 customExt := extensions.addU16LengthPrefixed()
418 customExt.addBytes([]byte(m.customExtension))
Adam Langley09505632015-07-30 18:10:13 -0700419 }
Adam Langley95c29f32014-06-20 12:00:00 -0700420
Nick Harper8dda5cc2016-06-30 18:51:11 -0400421 if extensions.len() == 0 {
422 hello.discardChild()
423 }
Adam Langley95c29f32014-06-20 12:00:00 -0700424
Nick Harper8dda5cc2016-06-30 18:51:11 -0400425 m.raw = handshakeMsg.finish()
426 return m.raw
Adam Langley95c29f32014-06-20 12:00:00 -0700427}
428
429func (m *clientHelloMsg) unmarshal(data []byte) bool {
430 if len(data) < 42 {
431 return false
432 }
433 m.raw = data
David Benjamin3c6a1ea2016-09-26 18:30:05 -0400434 m.vers = uint16(data[4])<<8 | uint16(data[5])
Adam Langley95c29f32014-06-20 12:00:00 -0700435 m.random = data[6:38]
436 sessionIdLen := int(data[38])
437 if sessionIdLen > 32 || len(data) < 39+sessionIdLen {
438 return false
439 }
440 m.sessionId = data[39 : 39+sessionIdLen]
441 data = data[39+sessionIdLen:]
David Benjamin83c0bc92014-08-04 01:23:53 -0400442 if m.isDTLS {
443 if len(data) < 1 {
444 return false
445 }
446 cookieLen := int(data[0])
447 if cookieLen > 32 || len(data) < 1+cookieLen {
448 return false
449 }
450 m.cookie = data[1 : 1+cookieLen]
451 data = data[1+cookieLen:]
452 }
Adam Langley95c29f32014-06-20 12:00:00 -0700453 if len(data) < 2 {
454 return false
455 }
456 // cipherSuiteLen is the number of bytes of cipher suite numbers. Since
457 // they are uint16s, the number must be even.
458 cipherSuiteLen := int(data[0])<<8 | int(data[1])
459 if cipherSuiteLen%2 == 1 || len(data) < 2+cipherSuiteLen {
460 return false
461 }
462 numCipherSuites := cipherSuiteLen / 2
463 m.cipherSuites = make([]uint16, numCipherSuites)
464 for i := 0; i < numCipherSuites; i++ {
465 m.cipherSuites[i] = uint16(data[2+2*i])<<8 | uint16(data[3+2*i])
466 if m.cipherSuites[i] == scsvRenegotiation {
Adam Langley2ae77d22014-10-28 17:29:33 -0700467 m.secureRenegotiation = []byte{}
Adam Langley95c29f32014-06-20 12:00:00 -0700468 }
469 }
470 data = data[2+cipherSuiteLen:]
471 if len(data) < 1 {
472 return false
473 }
474 compressionMethodsLen := int(data[0])
475 if len(data) < 1+compressionMethodsLen {
476 return false
477 }
478 m.compressionMethods = data[1 : 1+compressionMethodsLen]
479
480 data = data[1+compressionMethodsLen:]
481
482 m.nextProtoNeg = false
483 m.serverName = ""
484 m.ocspStapling = false
Nick Harperf8b0e702016-06-30 19:59:01 -0400485 m.keyShares = nil
486 m.pskIdentities = nil
487 m.hasEarlyData = false
488 m.earlyDataContext = nil
Adam Langley95c29f32014-06-20 12:00:00 -0700489 m.ticketSupported = false
490 m.sessionTicket = nil
Nick Harper60edffd2016-06-21 15:19:24 -0700491 m.signatureAlgorithms = nil
Steven Valdezfdd10992016-09-15 16:27:05 -0400492 m.supportedVersions = nil
David Benjaminfa055a22014-09-15 16:51:51 -0400493 m.alpnProtocols = nil
Adam Langley75712922014-10-10 16:23:43 -0700494 m.extendedMasterSecret = false
Adam Langley09505632015-07-30 18:10:13 -0700495 m.customExtension = ""
Adam Langley95c29f32014-06-20 12:00:00 -0700496
497 if len(data) == 0 {
498 // ClientHello is optionally followed by extension data
499 return true
500 }
501 if len(data) < 2 {
502 return false
503 }
504
505 extensionsLength := int(data[0])<<8 | int(data[1])
506 data = data[2:]
507 if extensionsLength != len(data) {
508 return false
509 }
510
511 for len(data) != 0 {
512 if len(data) < 4 {
513 return false
514 }
515 extension := uint16(data[0])<<8 | uint16(data[1])
516 length := int(data[2])<<8 | int(data[3])
517 data = data[4:]
518 if len(data) < length {
519 return false
520 }
521
522 switch extension {
523 case extensionServerName:
524 if length < 2 {
525 return false
526 }
527 numNames := int(data[0])<<8 | int(data[1])
528 d := data[2:]
529 for i := 0; i < numNames; i++ {
530 if len(d) < 3 {
531 return false
532 }
533 nameType := d[0]
534 nameLen := int(d[1])<<8 | int(d[2])
535 d = d[3:]
536 if len(d) < nameLen {
537 return false
538 }
539 if nameType == 0 {
540 m.serverName = string(d[0:nameLen])
541 break
542 }
543 d = d[nameLen:]
544 }
545 case extensionNextProtoNeg:
546 if length > 0 {
547 return false
548 }
549 m.nextProtoNeg = true
550 case extensionStatusRequest:
551 m.ocspStapling = length > 0 && data[0] == statusTypeOCSP
552 case extensionSupportedCurves:
553 // http://tools.ietf.org/html/rfc4492#section-5.5.1
554 if length < 2 {
555 return false
556 }
557 l := int(data[0])<<8 | int(data[1])
558 if l%2 == 1 || length != l+2 {
559 return false
560 }
561 numCurves := l / 2
562 m.supportedCurves = make([]CurveID, numCurves)
563 d := data[2:]
564 for i := 0; i < numCurves; i++ {
565 m.supportedCurves[i] = CurveID(d[0])<<8 | CurveID(d[1])
566 d = d[2:]
567 }
568 case extensionSupportedPoints:
569 // http://tools.ietf.org/html/rfc4492#section-5.5.2
570 if length < 1 {
571 return false
572 }
573 l := int(data[0])
574 if length != l+1 {
575 return false
576 }
577 m.supportedPoints = make([]uint8, l)
578 copy(m.supportedPoints, data[1:])
579 case extensionSessionTicket:
580 // http://tools.ietf.org/html/rfc5077#section-3.2
581 m.ticketSupported = true
582 m.sessionTicket = data[:length]
Nick Harperf8b0e702016-06-30 19:59:01 -0400583 case extensionKeyShare:
584 // draft-ietf-tls-tls13 section 6.3.2.3
585 if length < 2 {
586 return false
587 }
588 l := int(data[0])<<8 | int(data[1])
589 if l != length-2 {
590 return false
591 }
592 d := data[2:length]
Nick Harperdcfbc672016-07-16 17:47:31 +0200593 m.hasKeyShares = true
Nick Harperf8b0e702016-06-30 19:59:01 -0400594 for len(d) > 0 {
595 // The next KeyShareEntry contains a NamedGroup (2 bytes) and a
596 // key_exchange (2-byte length prefix with at least 1 byte of content).
597 if len(d) < 5 {
598 return false
599 }
600 entry := keyShareEntry{}
601 entry.group = CurveID(d[0])<<8 | CurveID(d[1])
602 keyExchLen := int(d[2])<<8 | int(d[3])
603 d = d[4:]
604 if len(d) < keyExchLen {
605 return false
606 }
607 entry.keyExchange = d[:keyExchLen]
608 d = d[keyExchLen:]
609 m.keyShares = append(m.keyShares, entry)
610 }
611 case extensionPreSharedKey:
612 // draft-ietf-tls-tls13 section 6.3.2.4
613 if length < 2 {
614 return false
615 }
616 l := int(data[0])<<8 | int(data[1])
617 if l != length-2 {
618 return false
619 }
620 d := data[2:length]
621 for len(d) > 0 {
Steven Valdez5b986082016-09-01 12:29:49 -0400622 var psk pskIdentity
623
624 if len(d) < 1 {
625 return false
626 }
627 keModesLen := int(d[0])
628 d = d[1:]
629 if len(d) < keModesLen {
630 return false
631 }
632 psk.keModes = d[:keModesLen]
633 d = d[keModesLen:]
634
635 if len(d) < 1 {
636 return false
637 }
638 authModesLen := int(d[0])
639 d = d[1:]
640 if len(d) < authModesLen {
641 return false
642 }
643 psk.authModes = d[:authModesLen]
644 d = d[authModesLen:]
Nick Harperf8b0e702016-06-30 19:59:01 -0400645 if len(d) < 2 {
646 return false
647 }
648 pskLen := int(d[0])<<8 | int(d[1])
649 d = d[2:]
Steven Valdez5b986082016-09-01 12:29:49 -0400650
Nick Harperf8b0e702016-06-30 19:59:01 -0400651 if len(d) < pskLen {
652 return false
653 }
Steven Valdez5b986082016-09-01 12:29:49 -0400654 psk.ticket = d[:pskLen]
Nick Harperf8b0e702016-06-30 19:59:01 -0400655 m.pskIdentities = append(m.pskIdentities, psk)
656 d = d[pskLen:]
657 }
658 case extensionEarlyData:
659 // draft-ietf-tls-tls13 section 6.3.2.5
660 if length < 1 {
661 return false
662 }
663 l := int(data[0])
664 if length != l+1 {
665 return false
666 }
667 m.hasEarlyData = true
668 m.earlyDataContext = data[1:length]
Adam Langley95c29f32014-06-20 12:00:00 -0700669 case extensionSignatureAlgorithms:
670 // https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
671 if length < 2 || length&1 != 0 {
672 return false
673 }
674 l := int(data[0])<<8 | int(data[1])
675 if l != length-2 {
676 return false
677 }
678 n := l / 2
679 d := data[2:]
Nick Harper60edffd2016-06-21 15:19:24 -0700680 m.signatureAlgorithms = make([]signatureAlgorithm, n)
681 for i := range m.signatureAlgorithms {
682 m.signatureAlgorithms[i] = signatureAlgorithm(d[0])<<8 | signatureAlgorithm(d[1])
Adam Langley95c29f32014-06-20 12:00:00 -0700683 d = d[2:]
684 }
Steven Valdezfdd10992016-09-15 16:27:05 -0400685 case extensionSupportedVersions:
686 if length < 1+2 {
687 return false
688 }
689 l := int(data[0])
690 if l != length-1 || l%2 == 1 || l < 2 {
691 return false
692 }
693 n := l / 2
694 d := data[1:]
695 m.supportedVersions = make([]uint16, n)
696 for i := range m.supportedVersions {
697 m.supportedVersions[i] = uint16(d[0])<<8 | uint16(d[1])
698 d = d[2:]
699 }
Adam Langley2ae77d22014-10-28 17:29:33 -0700700 case extensionRenegotiationInfo:
701 if length < 1 || length != int(data[0])+1 {
Adam Langley95c29f32014-06-20 12:00:00 -0700702 return false
703 }
Adam Langley2ae77d22014-10-28 17:29:33 -0700704 m.secureRenegotiation = data[1:length]
David Benjaminfa055a22014-09-15 16:51:51 -0400705 case extensionALPN:
706 if length < 2 {
707 return false
708 }
709 l := int(data[0])<<8 | int(data[1])
710 if l != length-2 {
711 return false
712 }
713 d := data[2:length]
714 for len(d) != 0 {
715 stringLen := int(d[0])
716 d = d[1:]
717 if stringLen == 0 || stringLen > len(d) {
718 return false
719 }
720 m.alpnProtocols = append(m.alpnProtocols, string(d[:stringLen]))
721 d = d[stringLen:]
722 }
David Benjamind30a9902014-08-24 01:44:23 -0400723 case extensionChannelID:
724 if length > 0 {
725 return false
726 }
727 m.channelIDSupported = true
Adam Langley75712922014-10-10 16:23:43 -0700728 case extensionExtendedMasterSecret:
729 if length != 0 {
730 return false
731 }
732 m.extendedMasterSecret = true
David Benjaminca6c8262014-11-15 19:06:08 -0500733 case extensionUseSRTP:
734 if length < 2 {
735 return false
736 }
737 l := int(data[0])<<8 | int(data[1])
738 if l > length-2 || l%2 != 0 {
739 return false
740 }
741 n := l / 2
742 m.srtpProtectionProfiles = make([]uint16, n)
743 d := data[2:length]
744 for i := 0; i < n; i++ {
745 m.srtpProtectionProfiles[i] = uint16(d[0])<<8 | uint16(d[1])
746 d = d[2:]
747 }
748 if len(d) < 1 || int(d[0]) != len(d)-1 {
749 return false
750 }
751 m.srtpMasterKeyIdentifier = string(d[1:])
David Benjamin61f95272014-11-25 01:55:35 -0500752 case extensionSignedCertificateTimestamp:
753 if length != 0 {
754 return false
755 }
756 m.sctListSupported = true
Adam Langley09505632015-07-30 18:10:13 -0700757 case extensionCustom:
758 m.customExtension = string(data[:length])
Adam Langley95c29f32014-06-20 12:00:00 -0700759 }
760 data = data[length:]
David Benjamin65ac9972016-09-02 21:35:25 -0400761
762 if isGREASEValue(extension) {
763 m.hasGREASEExtension = true
764 }
Adam Langley95c29f32014-06-20 12:00:00 -0700765 }
766
767 return true
768}
769
770type serverHelloMsg struct {
Nick Harperb41d2e42016-07-01 17:50:32 -0400771 raw []byte
772 isDTLS bool
773 vers uint16
David Benjaminb1dd8cd2016-09-26 19:20:48 -0400774 versOverride uint16
Nick Harperb41d2e42016-07-01 17:50:32 -0400775 random []byte
776 sessionId []byte
777 cipherSuite uint16
778 hasKeyShare bool
779 keyShare keyShareEntry
780 hasPSKIdentity bool
781 pskIdentity uint16
Steven Valdez803c77a2016-09-06 14:13:43 -0400782 useCertAuth bool
Nick Harperb41d2e42016-07-01 17:50:32 -0400783 earlyDataIndication bool
784 compressionMethod uint8
David Benjamin490469f2016-10-05 22:44:38 -0400785 customExtension string
786 unencryptedALPN string
Nick Harperb41d2e42016-07-01 17:50:32 -0400787 extensions serverExtensions
Adam Langley95c29f32014-06-20 12:00:00 -0700788}
789
Adam Langley95c29f32014-06-20 12:00:00 -0700790func (m *serverHelloMsg) marshal() []byte {
791 if m.raw != nil {
792 return m.raw
793 }
794
Nick Harper5212ef82016-06-30 19:26:07 -0400795 handshakeMsg := newByteBuilder()
796 handshakeMsg.addU8(typeServerHello)
797 hello := handshakeMsg.addU24LengthPrefixed()
David Benjaminb1dd8cd2016-09-26 19:20:48 -0400798
799 // m.vers is used both to determine the format of the rest of the
800 // ServerHello and to override the value, so include a second version
801 // field.
802 vers, ok := wireToVersion(m.vers, m.isDTLS)
803 if !ok {
804 panic("unknown version")
805 }
806 if m.versOverride != 0 {
807 hello.addU16(m.versOverride)
808 } else {
809 hello.addU16(m.vers)
810 }
811
Nick Harper5212ef82016-06-30 19:26:07 -0400812 hello.addBytes(m.random)
David Benjamin3c6a1ea2016-09-26 18:30:05 -0400813 if vers < VersionTLS13 {
Nick Harperb41d2e42016-07-01 17:50:32 -0400814 sessionId := hello.addU8LengthPrefixed()
815 sessionId.addBytes(m.sessionId)
816 }
Nick Harper5212ef82016-06-30 19:26:07 -0400817 hello.addU16(m.cipherSuite)
David Benjamin3c6a1ea2016-09-26 18:30:05 -0400818 if vers < VersionTLS13 {
Nick Harperb41d2e42016-07-01 17:50:32 -0400819 hello.addU8(m.compressionMethod)
820 }
Adam Langley95c29f32014-06-20 12:00:00 -0700821
Nick Harper5212ef82016-06-30 19:26:07 -0400822 extensions := hello.addU16LengthPrefixed()
Nick Harperb3d51be2016-07-01 11:43:18 -0400823
David Benjamin3c6a1ea2016-09-26 18:30:05 -0400824 if vers >= VersionTLS13 {
Nick Harperb41d2e42016-07-01 17:50:32 -0400825 if m.hasKeyShare {
826 extensions.addU16(extensionKeyShare)
827 keyShare := extensions.addU16LengthPrefixed()
828 keyShare.addU16(uint16(m.keyShare.group))
829 keyExchange := keyShare.addU16LengthPrefixed()
830 keyExchange.addBytes(m.keyShare.keyExchange)
831 }
832 if m.hasPSKIdentity {
833 extensions.addU16(extensionPreSharedKey)
834 extensions.addU16(2) // Length
835 extensions.addU16(m.pskIdentity)
836 }
Steven Valdez803c77a2016-09-06 14:13:43 -0400837 if m.useCertAuth {
838 extensions.addU16(extensionSignatureAlgorithms)
839 extensions.addU16(0) // Length
840 }
Nick Harperb41d2e42016-07-01 17:50:32 -0400841 if m.earlyDataIndication {
842 extensions.addU16(extensionEarlyData)
843 extensions.addU16(0) // Length
844 }
David Benjamin490469f2016-10-05 22:44:38 -0400845 if len(m.customExtension) > 0 {
846 extensions.addU16(extensionCustom)
847 customExt := extensions.addU16LengthPrefixed()
848 customExt.addBytes([]byte(m.customExtension))
849 }
850 if len(m.unencryptedALPN) > 0 {
851 extensions.addU16(extensionALPN)
852 extension := extensions.addU16LengthPrefixed()
853
854 protocolNameList := extension.addU16LengthPrefixed()
855 protocolName := protocolNameList.addU8LengthPrefixed()
856 protocolName.addBytes([]byte(m.unencryptedALPN))
857 }
Nick Harperb41d2e42016-07-01 17:50:32 -0400858 } else {
David Benjamin3c6a1ea2016-09-26 18:30:05 -0400859 m.extensions.marshal(extensions, vers)
Nick Harperb41d2e42016-07-01 17:50:32 -0400860 if extensions.len() == 0 {
861 hello.discardChild()
862 }
Nick Harperb3d51be2016-07-01 11:43:18 -0400863 }
864
865 m.raw = handshakeMsg.finish()
866 return m.raw
867}
868
869func (m *serverHelloMsg) unmarshal(data []byte) bool {
870 if len(data) < 42 {
871 return false
872 }
873 m.raw = data
David Benjamin3c6a1ea2016-09-26 18:30:05 -0400874 m.vers = uint16(data[4])<<8 | uint16(data[5])
David Benjaminb1dd8cd2016-09-26 19:20:48 -0400875 vers, ok := wireToVersion(m.vers, m.isDTLS)
876 if !ok {
877 return false
878 }
Nick Harperb3d51be2016-07-01 11:43:18 -0400879 m.random = data[6:38]
Nick Harperb41d2e42016-07-01 17:50:32 -0400880 data = data[38:]
David Benjamin3c6a1ea2016-09-26 18:30:05 -0400881 if vers < VersionTLS13 {
Nick Harperb41d2e42016-07-01 17:50:32 -0400882 sessionIdLen := int(data[0])
883 if sessionIdLen > 32 || len(data) < 1+sessionIdLen {
884 return false
885 }
886 m.sessionId = data[1 : 1+sessionIdLen]
887 data = data[1+sessionIdLen:]
Nick Harperb3d51be2016-07-01 11:43:18 -0400888 }
Nick Harperb41d2e42016-07-01 17:50:32 -0400889 if len(data) < 2 {
Nick Harperb3d51be2016-07-01 11:43:18 -0400890 return false
891 }
892 m.cipherSuite = uint16(data[0])<<8 | uint16(data[1])
Nick Harperb41d2e42016-07-01 17:50:32 -0400893 data = data[2:]
David Benjamin3c6a1ea2016-09-26 18:30:05 -0400894 if vers < VersionTLS13 {
Nick Harperb41d2e42016-07-01 17:50:32 -0400895 if len(data) < 1 {
896 return false
897 }
898 m.compressionMethod = data[0]
899 data = data[1:]
900 }
Nick Harperb3d51be2016-07-01 11:43:18 -0400901
David Benjamin8d315d72016-07-18 01:03:18 +0200902 if len(data) == 0 && m.vers < VersionTLS13 {
Nick Harperb41d2e42016-07-01 17:50:32 -0400903 // Extension data is optional before TLS 1.3.
Nick Harperb3d51be2016-07-01 11:43:18 -0400904 m.extensions = serverExtensions{}
905 return true
906 }
907 if len(data) < 2 {
908 return false
909 }
910
911 extensionsLength := int(data[0])<<8 | int(data[1])
912 data = data[2:]
913 if len(data) != extensionsLength {
914 return false
915 }
916
David Benjamin3c6a1ea2016-09-26 18:30:05 -0400917 if vers >= VersionTLS13 {
Nick Harperb41d2e42016-07-01 17:50:32 -0400918 for len(data) != 0 {
919 if len(data) < 4 {
920 return false
921 }
922 extension := uint16(data[0])<<8 | uint16(data[1])
923 length := int(data[2])<<8 | int(data[3])
924 data = data[4:]
925
926 if len(data) < length {
927 return false
928 }
929 d := data[:length]
930 data = data[length:]
931
932 switch extension {
933 case extensionKeyShare:
934 m.hasKeyShare = true
935 if len(d) < 4 {
936 return false
937 }
938 m.keyShare.group = CurveID(uint16(d[0])<<8 | uint16(d[1]))
939 keyExchLen := int(d[2])<<8 | int(d[3])
940 if keyExchLen != len(d)-4 {
941 return false
942 }
943 m.keyShare.keyExchange = make([]byte, keyExchLen)
944 copy(m.keyShare.keyExchange, d[4:])
945 case extensionPreSharedKey:
946 if len(d) != 2 {
947 return false
948 }
949 m.pskIdentity = uint16(d[0])<<8 | uint16(d[1])
950 m.hasPSKIdentity = true
Steven Valdez803c77a2016-09-06 14:13:43 -0400951 case extensionSignatureAlgorithms:
952 if len(d) != 0 {
953 return false
954 }
955 m.useCertAuth = true
Nick Harperb41d2e42016-07-01 17:50:32 -0400956 case extensionEarlyData:
957 if len(d) != 0 {
958 return false
959 }
960 m.earlyDataIndication = true
961 default:
962 // Only allow the 3 extensions that are sent in
963 // the clear in TLS 1.3.
964 return false
965 }
966 }
David Benjamin3c6a1ea2016-09-26 18:30:05 -0400967 } else if !m.extensions.unmarshal(data, vers) {
Nick Harperb3d51be2016-07-01 11:43:18 -0400968 return false
969 }
970
971 return true
972}
973
Nick Harperb41d2e42016-07-01 17:50:32 -0400974type encryptedExtensionsMsg struct {
975 raw []byte
976 extensions serverExtensions
Steven Valdez143e8b32016-07-11 13:19:03 -0400977 empty bool
Nick Harperb41d2e42016-07-01 17:50:32 -0400978}
979
980func (m *encryptedExtensionsMsg) marshal() []byte {
981 if m.raw != nil {
982 return m.raw
983 }
984
985 encryptedExtensionsMsg := newByteBuilder()
986 encryptedExtensionsMsg.addU8(typeEncryptedExtensions)
987 encryptedExtensions := encryptedExtensionsMsg.addU24LengthPrefixed()
Steven Valdez143e8b32016-07-11 13:19:03 -0400988 if !m.empty {
989 extensions := encryptedExtensions.addU16LengthPrefixed()
990 m.extensions.marshal(extensions, VersionTLS13)
991 }
Nick Harperb41d2e42016-07-01 17:50:32 -0400992
993 m.raw = encryptedExtensionsMsg.finish()
994 return m.raw
995}
996
997func (m *encryptedExtensionsMsg) unmarshal(data []byte) bool {
David Benjamin6f8f4de2016-07-13 16:42:36 -0400998 m.raw = data
Nick Harperb41d2e42016-07-01 17:50:32 -0400999 if len(data) < 6 {
1000 return false
1001 }
1002 if data[0] != typeEncryptedExtensions {
1003 return false
1004 }
1005 msgLen := int(data[1])<<16 | int(data[2])<<8 | int(data[3])
1006 data = data[4:]
1007 if len(data) != msgLen {
1008 return false
1009 }
1010 extLen := int(data[0])<<8 | int(data[1])
1011 data = data[2:]
1012 if extLen != len(data) {
1013 return false
1014 }
David Benjamin44b33bc2016-07-01 22:40:23 -04001015 return m.extensions.unmarshal(data, VersionTLS13)
Nick Harperb41d2e42016-07-01 17:50:32 -04001016}
1017
Nick Harperb3d51be2016-07-01 11:43:18 -04001018type serverExtensions struct {
1019 nextProtoNeg bool
1020 nextProtos []string
1021 ocspStapling bool
David Benjamin44b33bc2016-07-01 22:40:23 -04001022 ocspResponse []byte
Nick Harperb3d51be2016-07-01 11:43:18 -04001023 ticketSupported bool
1024 secureRenegotiation []byte
1025 alpnProtocol string
1026 alpnProtocolEmpty bool
1027 duplicateExtension bool
1028 channelIDRequested bool
1029 extendedMasterSecret bool
1030 srtpProtectionProfile uint16
1031 srtpMasterKeyIdentifier string
1032 sctList []byte
1033 customExtension string
1034 npnLast bool
Steven Valdez143e8b32016-07-11 13:19:03 -04001035 hasKeyShare bool
1036 keyShare keyShareEntry
Nick Harperb3d51be2016-07-01 11:43:18 -04001037}
1038
David Benjamin44b33bc2016-07-01 22:40:23 -04001039func (m *serverExtensions) marshal(extensions *byteBuilder, version uint16) {
David Benjamin35a7a442014-07-05 00:23:20 -04001040 if m.duplicateExtension {
1041 // Add a duplicate bogus extension at the beginning and end.
Nick Harper5212ef82016-06-30 19:26:07 -04001042 extensions.addU16(0xffff)
1043 extensions.addU16(0) // length = 0 for empty extension
David Benjamin35a7a442014-07-05 00:23:20 -04001044 }
David Benjamin76c2efc2015-08-31 14:24:29 -04001045 if m.nextProtoNeg && !m.npnLast {
Nick Harper5212ef82016-06-30 19:26:07 -04001046 extensions.addU16(extensionNextProtoNeg)
1047 extension := extensions.addU16LengthPrefixed()
Adam Langley95c29f32014-06-20 12:00:00 -07001048
1049 for _, v := range m.nextProtos {
Nick Harper5212ef82016-06-30 19:26:07 -04001050 if len(v) > 255 {
1051 v = v[:255]
Adam Langley95c29f32014-06-20 12:00:00 -07001052 }
Nick Harper5212ef82016-06-30 19:26:07 -04001053 npn := extension.addU8LengthPrefixed()
1054 npn.addBytes([]byte(v))
Adam Langley95c29f32014-06-20 12:00:00 -07001055 }
1056 }
David Benjamin8d315d72016-07-18 01:03:18 +02001057 if version >= VersionTLS13 {
David Benjamin44b33bc2016-07-01 22:40:23 -04001058 if m.ocspResponse != nil {
1059 extensions.addU16(extensionStatusRequest)
1060 body := extensions.addU16LengthPrefixed()
1061 body.addU8(statusTypeOCSP)
1062 response := body.addU24LengthPrefixed()
1063 response.addBytes(m.ocspResponse)
1064 }
1065 } else {
1066 if m.ocspStapling {
1067 extensions.addU16(extensionStatusRequest)
1068 extensions.addU16(0)
1069 }
Adam Langley95c29f32014-06-20 12:00:00 -07001070 }
1071 if m.ticketSupported {
Nick Harper5212ef82016-06-30 19:26:07 -04001072 extensions.addU16(extensionSessionTicket)
1073 extensions.addU16(0)
Adam Langley95c29f32014-06-20 12:00:00 -07001074 }
Adam Langley2ae77d22014-10-28 17:29:33 -07001075 if m.secureRenegotiation != nil {
Nick Harper5212ef82016-06-30 19:26:07 -04001076 extensions.addU16(extensionRenegotiationInfo)
1077 extension := extensions.addU16LengthPrefixed()
1078 secureRenego := extension.addU8LengthPrefixed()
1079 secureRenego.addBytes(m.secureRenegotiation)
Adam Langley95c29f32014-06-20 12:00:00 -07001080 }
Nick Harper5212ef82016-06-30 19:26:07 -04001081 if len(m.alpnProtocol) > 0 || m.alpnProtocolEmpty {
1082 extensions.addU16(extensionALPN)
1083 extension := extensions.addU16LengthPrefixed()
1084
1085 protocolNameList := extension.addU16LengthPrefixed()
1086 protocolName := protocolNameList.addU8LengthPrefixed()
1087 protocolName.addBytes([]byte(m.alpnProtocol))
David Benjaminfa055a22014-09-15 16:51:51 -04001088 }
David Benjamind30a9902014-08-24 01:44:23 -04001089 if m.channelIDRequested {
Nick Harper5212ef82016-06-30 19:26:07 -04001090 extensions.addU16(extensionChannelID)
1091 extensions.addU16(0)
David Benjamind30a9902014-08-24 01:44:23 -04001092 }
David Benjamin35a7a442014-07-05 00:23:20 -04001093 if m.duplicateExtension {
1094 // Add a duplicate bogus extension at the beginning and end.
Nick Harper5212ef82016-06-30 19:26:07 -04001095 extensions.addU16(0xffff)
1096 extensions.addU16(0)
David Benjamin35a7a442014-07-05 00:23:20 -04001097 }
Adam Langley75712922014-10-10 16:23:43 -07001098 if m.extendedMasterSecret {
Nick Harper5212ef82016-06-30 19:26:07 -04001099 extensions.addU16(extensionExtendedMasterSecret)
1100 extensions.addU16(0)
Adam Langley75712922014-10-10 16:23:43 -07001101 }
David Benjaminca6c8262014-11-15 19:06:08 -05001102 if m.srtpProtectionProfile != 0 {
Nick Harper5212ef82016-06-30 19:26:07 -04001103 extensions.addU16(extensionUseSRTP)
1104 extension := extensions.addU16LengthPrefixed()
1105
1106 srtpProtectionProfiles := extension.addU16LengthPrefixed()
1107 srtpProtectionProfiles.addU8(byte(m.srtpProtectionProfile >> 8))
1108 srtpProtectionProfiles.addU8(byte(m.srtpProtectionProfile))
1109 srtpMki := extension.addU8LengthPrefixed()
1110 srtpMki.addBytes([]byte(m.srtpMasterKeyIdentifier))
David Benjaminca6c8262014-11-15 19:06:08 -05001111 }
David Benjamin61f95272014-11-25 01:55:35 -05001112 if m.sctList != nil {
Nick Harper5212ef82016-06-30 19:26:07 -04001113 extensions.addU16(extensionSignedCertificateTimestamp)
1114 extension := extensions.addU16LengthPrefixed()
1115 extension.addBytes(m.sctList)
David Benjamin61f95272014-11-25 01:55:35 -05001116 }
Adam Langley09505632015-07-30 18:10:13 -07001117 if l := len(m.customExtension); l > 0 {
Nick Harper5212ef82016-06-30 19:26:07 -04001118 extensions.addU16(extensionCustom)
1119 customExt := extensions.addU16LengthPrefixed()
1120 customExt.addBytes([]byte(m.customExtension))
Adam Langley09505632015-07-30 18:10:13 -07001121 }
David Benjamin76c2efc2015-08-31 14:24:29 -04001122 if m.nextProtoNeg && m.npnLast {
Nick Harper5212ef82016-06-30 19:26:07 -04001123 extensions.addU16(extensionNextProtoNeg)
1124 extension := extensions.addU16LengthPrefixed()
David Benjamin76c2efc2015-08-31 14:24:29 -04001125
1126 for _, v := range m.nextProtos {
Nick Harper5212ef82016-06-30 19:26:07 -04001127 if len(v) > 255 {
1128 v = v[0:255]
David Benjamin76c2efc2015-08-31 14:24:29 -04001129 }
Nick Harper5212ef82016-06-30 19:26:07 -04001130 npn := extension.addU8LengthPrefixed()
1131 npn.addBytes([]byte(v))
David Benjamin76c2efc2015-08-31 14:24:29 -04001132 }
1133 }
Steven Valdez143e8b32016-07-11 13:19:03 -04001134 if m.hasKeyShare {
1135 extensions.addU16(extensionKeyShare)
1136 keyShare := extensions.addU16LengthPrefixed()
1137 keyShare.addU16(uint16(m.keyShare.group))
1138 keyExchange := keyShare.addU16LengthPrefixed()
1139 keyExchange.addBytes(m.keyShare.keyExchange)
1140 }
Adam Langley95c29f32014-06-20 12:00:00 -07001141}
1142
David Benjamin44b33bc2016-07-01 22:40:23 -04001143func (m *serverExtensions) unmarshal(data []byte, version uint16) bool {
Nick Harperb3d51be2016-07-01 11:43:18 -04001144 // Reset all fields.
1145 *m = serverExtensions{}
Adam Langley95c29f32014-06-20 12:00:00 -07001146
1147 for len(data) != 0 {
1148 if len(data) < 4 {
1149 return false
1150 }
1151 extension := uint16(data[0])<<8 | uint16(data[1])
1152 length := int(data[2])<<8 | int(data[3])
1153 data = data[4:]
1154 if len(data) < length {
1155 return false
1156 }
1157
1158 switch extension {
1159 case extensionNextProtoNeg:
1160 m.nextProtoNeg = true
1161 d := data[:length]
1162 for len(d) > 0 {
1163 l := int(d[0])
1164 d = d[1:]
1165 if l == 0 || l > len(d) {
1166 return false
1167 }
1168 m.nextProtos = append(m.nextProtos, string(d[:l]))
1169 d = d[l:]
1170 }
1171 case extensionStatusRequest:
David Benjamin8d315d72016-07-18 01:03:18 +02001172 if version >= VersionTLS13 {
David Benjamin44b33bc2016-07-01 22:40:23 -04001173 if length < 4 {
1174 return false
1175 }
1176 d := data[:length]
1177 if d[0] != statusTypeOCSP {
1178 return false
1179 }
1180 respLen := int(d[1])<<16 | int(d[2])<<8 | int(d[3])
1181 if respLen+4 != len(d) || respLen == 0 {
1182 return false
1183 }
1184 m.ocspResponse = d[4:]
1185 } else {
1186 if length > 0 {
1187 return false
1188 }
1189 m.ocspStapling = true
Adam Langley95c29f32014-06-20 12:00:00 -07001190 }
Adam Langley95c29f32014-06-20 12:00:00 -07001191 case extensionSessionTicket:
1192 if length > 0 {
1193 return false
1194 }
1195 m.ticketSupported = true
1196 case extensionRenegotiationInfo:
Adam Langley2ae77d22014-10-28 17:29:33 -07001197 if length < 1 || length != int(data[0])+1 {
Adam Langley95c29f32014-06-20 12:00:00 -07001198 return false
1199 }
Adam Langley2ae77d22014-10-28 17:29:33 -07001200 m.secureRenegotiation = data[1:length]
David Benjaminfa055a22014-09-15 16:51:51 -04001201 case extensionALPN:
1202 d := data[:length]
1203 if len(d) < 3 {
1204 return false
1205 }
1206 l := int(d[0])<<8 | int(d[1])
1207 if l != len(d)-2 {
1208 return false
1209 }
1210 d = d[2:]
1211 l = int(d[0])
1212 if l != len(d)-1 {
1213 return false
1214 }
1215 d = d[1:]
1216 m.alpnProtocol = string(d)
Adam Langleyefb0e162015-07-09 11:35:04 -07001217 m.alpnProtocolEmpty = len(d) == 0
David Benjamind30a9902014-08-24 01:44:23 -04001218 case extensionChannelID:
1219 if length > 0 {
1220 return false
1221 }
1222 m.channelIDRequested = true
Adam Langley75712922014-10-10 16:23:43 -07001223 case extensionExtendedMasterSecret:
1224 if length != 0 {
1225 return false
1226 }
1227 m.extendedMasterSecret = true
David Benjaminca6c8262014-11-15 19:06:08 -05001228 case extensionUseSRTP:
1229 if length < 2+2+1 {
1230 return false
1231 }
1232 if data[0] != 0 || data[1] != 2 {
1233 return false
1234 }
1235 m.srtpProtectionProfile = uint16(data[2])<<8 | uint16(data[3])
1236 d := data[4:length]
1237 l := int(d[0])
1238 if l != len(d)-1 {
1239 return false
1240 }
1241 m.srtpMasterKeyIdentifier = string(d[1:])
David Benjamin61f95272014-11-25 01:55:35 -05001242 case extensionSignedCertificateTimestamp:
Paul Lietar4fac72e2015-09-09 13:44:55 +01001243 m.sctList = data[:length]
Adam Langley09505632015-07-30 18:10:13 -07001244 case extensionCustom:
1245 m.customExtension = string(data[:length])
David Benjamin46f94bd2016-07-14 16:43:37 -04001246 case extensionServerName:
1247 if length != 0 {
1248 return false
1249 }
1250 // Ignore this extension from the server.
1251 case extensionSupportedPoints:
1252 // supported_points is illegal in TLS 1.3.
David Benjamin8d315d72016-07-18 01:03:18 +02001253 if version >= VersionTLS13 {
David Benjamin46f94bd2016-07-14 16:43:37 -04001254 return false
1255 }
1256 // Ignore this extension from the server.
David Benjamin4ee027f2016-07-17 12:34:41 +02001257 case extensionSupportedCurves:
1258 // The server can only send supported_curves in TLS 1.3.
David Benjamin8d315d72016-07-18 01:03:18 +02001259 if version < VersionTLS13 {
David Benjamin4ee027f2016-07-17 12:34:41 +02001260 return false
1261 }
David Benjamin46f94bd2016-07-14 16:43:37 -04001262 default:
1263 // Unknown extensions are illegal from the server.
1264 return false
Adam Langley95c29f32014-06-20 12:00:00 -07001265 }
1266 data = data[length:]
1267 }
1268
1269 return true
1270}
1271
Nick Harperdcfbc672016-07-16 17:47:31 +02001272type helloRetryRequestMsg struct {
1273 raw []byte
1274 vers uint16
1275 cipherSuite uint16
1276 selectedGroup CurveID
1277}
1278
1279func (m *helloRetryRequestMsg) marshal() []byte {
1280 if m.raw != nil {
1281 return m.raw
1282 }
1283
1284 retryRequestMsg := newByteBuilder()
1285 retryRequestMsg.addU8(typeHelloRetryRequest)
1286 retryRequest := retryRequestMsg.addU24LengthPrefixed()
1287 retryRequest.addU16(m.vers)
1288 retryRequest.addU16(m.cipherSuite)
1289 retryRequest.addU16(uint16(m.selectedGroup))
1290 // Extensions field. We have none to send.
1291 retryRequest.addU16(0)
1292
1293 m.raw = retryRequestMsg.finish()
1294 return m.raw
1295}
1296
1297func (m *helloRetryRequestMsg) unmarshal(data []byte) bool {
1298 m.raw = data
1299 if len(data) < 12 {
1300 return false
1301 }
1302 m.vers = uint16(data[4])<<8 | uint16(data[5])
1303 m.cipherSuite = uint16(data[6])<<8 | uint16(data[7])
1304 m.selectedGroup = CurveID(data[8])<<8 | CurveID(data[9])
1305 extLen := int(data[10])<<8 | int(data[11])
1306 data = data[12:]
1307 if len(data) != extLen {
1308 return false
1309 }
1310 return true
1311}
1312
Adam Langley95c29f32014-06-20 12:00:00 -07001313type certificateMsg struct {
Nick Harperb41d2e42016-07-01 17:50:32 -04001314 raw []byte
1315 hasRequestContext bool
1316 requestContext []byte
1317 certificates [][]byte
Adam Langley95c29f32014-06-20 12:00:00 -07001318}
1319
Adam Langley95c29f32014-06-20 12:00:00 -07001320func (m *certificateMsg) marshal() (x []byte) {
1321 if m.raw != nil {
1322 return m.raw
1323 }
1324
Nick Harper7e0442a2016-07-01 17:40:09 -04001325 certMsg := newByteBuilder()
1326 certMsg.addU8(typeCertificate)
1327 certificate := certMsg.addU24LengthPrefixed()
Nick Harperb41d2e42016-07-01 17:50:32 -04001328 if m.hasRequestContext {
1329 context := certificate.addU8LengthPrefixed()
1330 context.addBytes(m.requestContext)
1331 }
Nick Harper7e0442a2016-07-01 17:40:09 -04001332 certificateList := certificate.addU24LengthPrefixed()
1333 for _, cert := range m.certificates {
1334 certEntry := certificateList.addU24LengthPrefixed()
1335 certEntry.addBytes(cert)
Adam Langley95c29f32014-06-20 12:00:00 -07001336 }
1337
Nick Harper7e0442a2016-07-01 17:40:09 -04001338 m.raw = certMsg.finish()
1339 return m.raw
Adam Langley95c29f32014-06-20 12:00:00 -07001340}
1341
1342func (m *certificateMsg) unmarshal(data []byte) bool {
Nick Harperb41d2e42016-07-01 17:50:32 -04001343 if len(data) < 4 {
Adam Langley95c29f32014-06-20 12:00:00 -07001344 return false
1345 }
1346
1347 m.raw = data
Nick Harperb41d2e42016-07-01 17:50:32 -04001348 data = data[4:]
1349
1350 if m.hasRequestContext {
1351 if len(data) == 0 {
1352 return false
1353 }
1354 contextLen := int(data[0])
1355 if len(data) < 1+contextLen {
1356 return false
1357 }
1358 m.requestContext = make([]byte, contextLen)
1359 copy(m.requestContext, data[1:])
1360 data = data[1+contextLen:]
1361 }
1362
1363 if len(data) < 3 {
1364 return false
1365 }
1366 certsLen := int(data[0])<<16 | int(data[1])<<8 | int(data[2])
1367 data = data[3:]
1368 if len(data) != certsLen {
Adam Langley95c29f32014-06-20 12:00:00 -07001369 return false
1370 }
1371
1372 numCerts := 0
Nick Harperb41d2e42016-07-01 17:50:32 -04001373 d := data
Adam Langley95c29f32014-06-20 12:00:00 -07001374 for certsLen > 0 {
1375 if len(d) < 4 {
1376 return false
1377 }
Nick Harperb41d2e42016-07-01 17:50:32 -04001378 certLen := int(d[0])<<16 | int(d[1])<<8 | int(d[2])
1379 if len(d) < 3+certLen {
Adam Langley95c29f32014-06-20 12:00:00 -07001380 return false
1381 }
1382 d = d[3+certLen:]
1383 certsLen -= 3 + certLen
1384 numCerts++
1385 }
1386
1387 m.certificates = make([][]byte, numCerts)
Nick Harperb41d2e42016-07-01 17:50:32 -04001388 d = data
Adam Langley95c29f32014-06-20 12:00:00 -07001389 for i := 0; i < numCerts; i++ {
1390 certLen := uint32(d[0])<<16 | uint32(d[1])<<8 | uint32(d[2])
1391 m.certificates[i] = d[3 : 3+certLen]
1392 d = d[3+certLen:]
1393 }
1394
1395 return true
1396}
1397
1398type serverKeyExchangeMsg struct {
1399 raw []byte
1400 key []byte
1401}
1402
Adam Langley95c29f32014-06-20 12:00:00 -07001403func (m *serverKeyExchangeMsg) marshal() []byte {
1404 if m.raw != nil {
1405 return m.raw
1406 }
1407 length := len(m.key)
1408 x := make([]byte, length+4)
1409 x[0] = typeServerKeyExchange
1410 x[1] = uint8(length >> 16)
1411 x[2] = uint8(length >> 8)
1412 x[3] = uint8(length)
1413 copy(x[4:], m.key)
1414
1415 m.raw = x
1416 return x
1417}
1418
1419func (m *serverKeyExchangeMsg) unmarshal(data []byte) bool {
1420 m.raw = data
1421 if len(data) < 4 {
1422 return false
1423 }
1424 m.key = data[4:]
1425 return true
1426}
1427
1428type certificateStatusMsg struct {
1429 raw []byte
1430 statusType uint8
1431 response []byte
1432}
1433
Adam Langley95c29f32014-06-20 12:00:00 -07001434func (m *certificateStatusMsg) marshal() []byte {
1435 if m.raw != nil {
1436 return m.raw
1437 }
1438
1439 var x []byte
1440 if m.statusType == statusTypeOCSP {
1441 x = make([]byte, 4+4+len(m.response))
1442 x[0] = typeCertificateStatus
1443 l := len(m.response) + 4
1444 x[1] = byte(l >> 16)
1445 x[2] = byte(l >> 8)
1446 x[3] = byte(l)
1447 x[4] = statusTypeOCSP
1448
1449 l -= 4
1450 x[5] = byte(l >> 16)
1451 x[6] = byte(l >> 8)
1452 x[7] = byte(l)
1453 copy(x[8:], m.response)
1454 } else {
1455 x = []byte{typeCertificateStatus, 0, 0, 1, m.statusType}
1456 }
1457
1458 m.raw = x
1459 return x
1460}
1461
1462func (m *certificateStatusMsg) unmarshal(data []byte) bool {
1463 m.raw = data
1464 if len(data) < 5 {
1465 return false
1466 }
1467 m.statusType = data[4]
1468
1469 m.response = nil
1470 if m.statusType == statusTypeOCSP {
1471 if len(data) < 8 {
1472 return false
1473 }
1474 respLen := uint32(data[5])<<16 | uint32(data[6])<<8 | uint32(data[7])
1475 if uint32(len(data)) != 4+4+respLen {
1476 return false
1477 }
1478 m.response = data[8:]
1479 }
1480 return true
1481}
1482
1483type serverHelloDoneMsg struct{}
1484
Adam Langley95c29f32014-06-20 12:00:00 -07001485func (m *serverHelloDoneMsg) marshal() []byte {
1486 x := make([]byte, 4)
1487 x[0] = typeServerHelloDone
1488 return x
1489}
1490
1491func (m *serverHelloDoneMsg) unmarshal(data []byte) bool {
1492 return len(data) == 4
1493}
1494
1495type clientKeyExchangeMsg struct {
1496 raw []byte
1497 ciphertext []byte
1498}
1499
Adam Langley95c29f32014-06-20 12:00:00 -07001500func (m *clientKeyExchangeMsg) marshal() []byte {
1501 if m.raw != nil {
1502 return m.raw
1503 }
1504 length := len(m.ciphertext)
1505 x := make([]byte, length+4)
1506 x[0] = typeClientKeyExchange
1507 x[1] = uint8(length >> 16)
1508 x[2] = uint8(length >> 8)
1509 x[3] = uint8(length)
1510 copy(x[4:], m.ciphertext)
1511
1512 m.raw = x
1513 return x
1514}
1515
1516func (m *clientKeyExchangeMsg) unmarshal(data []byte) bool {
1517 m.raw = data
1518 if len(data) < 4 {
1519 return false
1520 }
1521 l := int(data[1])<<16 | int(data[2])<<8 | int(data[3])
1522 if l != len(data)-4 {
1523 return false
1524 }
1525 m.ciphertext = data[4:]
1526 return true
1527}
1528
1529type finishedMsg struct {
1530 raw []byte
1531 verifyData []byte
1532}
1533
Adam Langley95c29f32014-06-20 12:00:00 -07001534func (m *finishedMsg) marshal() (x []byte) {
1535 if m.raw != nil {
1536 return m.raw
1537 }
1538
1539 x = make([]byte, 4+len(m.verifyData))
1540 x[0] = typeFinished
1541 x[3] = byte(len(m.verifyData))
1542 copy(x[4:], m.verifyData)
1543 m.raw = x
1544 return
1545}
1546
1547func (m *finishedMsg) unmarshal(data []byte) bool {
1548 m.raw = data
1549 if len(data) < 4 {
1550 return false
1551 }
1552 m.verifyData = data[4:]
1553 return true
1554}
1555
1556type nextProtoMsg struct {
1557 raw []byte
1558 proto string
1559}
1560
Adam Langley95c29f32014-06-20 12:00:00 -07001561func (m *nextProtoMsg) marshal() []byte {
1562 if m.raw != nil {
1563 return m.raw
1564 }
1565 l := len(m.proto)
1566 if l > 255 {
1567 l = 255
1568 }
1569
1570 padding := 32 - (l+2)%32
1571 length := l + padding + 2
1572 x := make([]byte, length+4)
1573 x[0] = typeNextProtocol
1574 x[1] = uint8(length >> 16)
1575 x[2] = uint8(length >> 8)
1576 x[3] = uint8(length)
1577
1578 y := x[4:]
1579 y[0] = byte(l)
1580 copy(y[1:], []byte(m.proto[0:l]))
1581 y = y[1+l:]
1582 y[0] = byte(padding)
1583
1584 m.raw = x
1585
1586 return x
1587}
1588
1589func (m *nextProtoMsg) unmarshal(data []byte) bool {
1590 m.raw = data
1591
1592 if len(data) < 5 {
1593 return false
1594 }
1595 data = data[4:]
1596 protoLen := int(data[0])
1597 data = data[1:]
1598 if len(data) < protoLen {
1599 return false
1600 }
1601 m.proto = string(data[0:protoLen])
1602 data = data[protoLen:]
1603
1604 if len(data) < 1 {
1605 return false
1606 }
1607 paddingLen := int(data[0])
1608 data = data[1:]
1609 if len(data) != paddingLen {
1610 return false
1611 }
1612
1613 return true
1614}
1615
1616type certificateRequestMsg struct {
1617 raw []byte
Nick Harper60edffd2016-06-21 15:19:24 -07001618 // hasSignatureAlgorithm indicates whether this message includes a list
Adam Langley95c29f32014-06-20 12:00:00 -07001619 // of signature and hash functions. This change was introduced with TLS
1620 // 1.2.
Nick Harper60edffd2016-06-21 15:19:24 -07001621 hasSignatureAlgorithm bool
Nick Harperb41d2e42016-07-01 17:50:32 -04001622 // hasRequestContext indicates whether this message includes a context
1623 // field instead of certificateTypes. This change was introduced with
1624 // TLS 1.3.
1625 hasRequestContext bool
Adam Langley95c29f32014-06-20 12:00:00 -07001626
1627 certificateTypes []byte
Nick Harperb41d2e42016-07-01 17:50:32 -04001628 requestContext []byte
Nick Harper60edffd2016-06-21 15:19:24 -07001629 signatureAlgorithms []signatureAlgorithm
Adam Langley95c29f32014-06-20 12:00:00 -07001630 certificateAuthorities [][]byte
1631}
1632
Nick Harper7e0442a2016-07-01 17:40:09 -04001633func (m *certificateRequestMsg) marshal() []byte {
Adam Langley95c29f32014-06-20 12:00:00 -07001634 if m.raw != nil {
1635 return m.raw
1636 }
1637
1638 // See http://tools.ietf.org/html/rfc4346#section-7.4.4
Nick Harper7e0442a2016-07-01 17:40:09 -04001639 builder := newByteBuilder()
1640 builder.addU8(typeCertificateRequest)
1641 body := builder.addU24LengthPrefixed()
1642
Nick Harperb41d2e42016-07-01 17:50:32 -04001643 if m.hasRequestContext {
1644 requestContext := body.addU8LengthPrefixed()
1645 requestContext.addBytes(m.requestContext)
1646 } else {
1647 certificateTypes := body.addU8LengthPrefixed()
1648 certificateTypes.addBytes(m.certificateTypes)
1649 }
Adam Langley95c29f32014-06-20 12:00:00 -07001650
Nick Harper60edffd2016-06-21 15:19:24 -07001651 if m.hasSignatureAlgorithm {
Nick Harper7e0442a2016-07-01 17:40:09 -04001652 signatureAlgorithms := body.addU16LengthPrefixed()
Nick Harper60edffd2016-06-21 15:19:24 -07001653 for _, sigAlg := range m.signatureAlgorithms {
Nick Harper7e0442a2016-07-01 17:40:09 -04001654 signatureAlgorithms.addU16(uint16(sigAlg))
Adam Langley95c29f32014-06-20 12:00:00 -07001655 }
1656 }
1657
Nick Harper7e0442a2016-07-01 17:40:09 -04001658 certificateAuthorities := body.addU16LengthPrefixed()
Adam Langley95c29f32014-06-20 12:00:00 -07001659 for _, ca := range m.certificateAuthorities {
Nick Harper7e0442a2016-07-01 17:40:09 -04001660 caEntry := certificateAuthorities.addU16LengthPrefixed()
1661 caEntry.addBytes(ca)
Adam Langley95c29f32014-06-20 12:00:00 -07001662 }
1663
David Benjamin8d343b42016-07-09 14:26:01 -07001664 if m.hasRequestContext {
1665 // Emit no certificate extensions.
1666 body.addU16(0)
1667 }
1668
Nick Harper7e0442a2016-07-01 17:40:09 -04001669 m.raw = builder.finish()
1670 return m.raw
Adam Langley95c29f32014-06-20 12:00:00 -07001671}
1672
1673func (m *certificateRequestMsg) unmarshal(data []byte) bool {
1674 m.raw = data
1675
1676 if len(data) < 5 {
1677 return false
1678 }
Nick Harperb41d2e42016-07-01 17:50:32 -04001679 data = data[4:]
Adam Langley95c29f32014-06-20 12:00:00 -07001680
Nick Harperb41d2e42016-07-01 17:50:32 -04001681 if m.hasRequestContext {
1682 contextLen := int(data[0])
1683 if len(data) < 1+contextLen {
1684 return false
1685 }
1686 m.requestContext = make([]byte, contextLen)
1687 copy(m.requestContext, data[1:])
1688 data = data[1+contextLen:]
1689 } else {
1690 numCertTypes := int(data[0])
1691 if len(data) < 1+numCertTypes {
1692 return false
1693 }
1694 m.certificateTypes = make([]byte, numCertTypes)
1695 copy(m.certificateTypes, data[1:])
1696 data = data[1+numCertTypes:]
Adam Langley95c29f32014-06-20 12:00:00 -07001697 }
1698
Nick Harper60edffd2016-06-21 15:19:24 -07001699 if m.hasSignatureAlgorithm {
Adam Langley95c29f32014-06-20 12:00:00 -07001700 if len(data) < 2 {
1701 return false
1702 }
Nick Harper60edffd2016-06-21 15:19:24 -07001703 sigAlgsLen := uint16(data[0])<<8 | uint16(data[1])
Adam Langley95c29f32014-06-20 12:00:00 -07001704 data = data[2:]
Nick Harper60edffd2016-06-21 15:19:24 -07001705 if sigAlgsLen&1 != 0 {
Adam Langley95c29f32014-06-20 12:00:00 -07001706 return false
1707 }
Nick Harper60edffd2016-06-21 15:19:24 -07001708 if len(data) < int(sigAlgsLen) {
Adam Langley95c29f32014-06-20 12:00:00 -07001709 return false
1710 }
Nick Harper60edffd2016-06-21 15:19:24 -07001711 numSigAlgs := sigAlgsLen / 2
1712 m.signatureAlgorithms = make([]signatureAlgorithm, numSigAlgs)
1713 for i := range m.signatureAlgorithms {
1714 m.signatureAlgorithms[i] = signatureAlgorithm(data[0])<<8 | signatureAlgorithm(data[1])
Adam Langley95c29f32014-06-20 12:00:00 -07001715 data = data[2:]
1716 }
1717 }
1718
1719 if len(data) < 2 {
1720 return false
1721 }
1722 casLength := uint16(data[0])<<8 | uint16(data[1])
1723 data = data[2:]
1724 if len(data) < int(casLength) {
1725 return false
1726 }
1727 cas := make([]byte, casLength)
1728 copy(cas, data)
1729 data = data[casLength:]
1730
1731 m.certificateAuthorities = nil
1732 for len(cas) > 0 {
1733 if len(cas) < 2 {
1734 return false
1735 }
1736 caLen := uint16(cas[0])<<8 | uint16(cas[1])
1737 cas = cas[2:]
1738
1739 if len(cas) < int(caLen) {
1740 return false
1741 }
1742
1743 m.certificateAuthorities = append(m.certificateAuthorities, cas[:caLen])
1744 cas = cas[caLen:]
1745 }
David Benjamin8d343b42016-07-09 14:26:01 -07001746
1747 if m.hasRequestContext {
1748 // Ignore certificate extensions.
1749 if len(data) < 2 {
1750 return false
1751 }
1752 extsLength := int(data[0])<<8 | int(data[1])
1753 if len(data) < 2+extsLength {
1754 return false
1755 }
1756 data = data[2+extsLength:]
1757 }
1758
Adam Langley95c29f32014-06-20 12:00:00 -07001759 if len(data) > 0 {
1760 return false
1761 }
1762
1763 return true
1764}
1765
1766type certificateVerifyMsg struct {
Nick Harper60edffd2016-06-21 15:19:24 -07001767 raw []byte
1768 hasSignatureAlgorithm bool
1769 signatureAlgorithm signatureAlgorithm
1770 signature []byte
Adam Langley95c29f32014-06-20 12:00:00 -07001771}
1772
Adam Langley95c29f32014-06-20 12:00:00 -07001773func (m *certificateVerifyMsg) marshal() (x []byte) {
1774 if m.raw != nil {
1775 return m.raw
1776 }
1777
1778 // See http://tools.ietf.org/html/rfc4346#section-7.4.8
1779 siglength := len(m.signature)
1780 length := 2 + siglength
Nick Harper60edffd2016-06-21 15:19:24 -07001781 if m.hasSignatureAlgorithm {
Adam Langley95c29f32014-06-20 12:00:00 -07001782 length += 2
1783 }
1784 x = make([]byte, 4+length)
1785 x[0] = typeCertificateVerify
1786 x[1] = uint8(length >> 16)
1787 x[2] = uint8(length >> 8)
1788 x[3] = uint8(length)
1789 y := x[4:]
Nick Harper60edffd2016-06-21 15:19:24 -07001790 if m.hasSignatureAlgorithm {
1791 y[0] = byte(m.signatureAlgorithm >> 8)
1792 y[1] = byte(m.signatureAlgorithm)
Adam Langley95c29f32014-06-20 12:00:00 -07001793 y = y[2:]
1794 }
1795 y[0] = uint8(siglength >> 8)
1796 y[1] = uint8(siglength)
1797 copy(y[2:], m.signature)
1798
1799 m.raw = x
1800
1801 return
1802}
1803
1804func (m *certificateVerifyMsg) unmarshal(data []byte) bool {
1805 m.raw = data
1806
1807 if len(data) < 6 {
1808 return false
1809 }
1810
1811 length := uint32(data[1])<<16 | uint32(data[2])<<8 | uint32(data[3])
1812 if uint32(len(data))-4 != length {
1813 return false
1814 }
1815
1816 data = data[4:]
Nick Harper60edffd2016-06-21 15:19:24 -07001817 if m.hasSignatureAlgorithm {
1818 m.signatureAlgorithm = signatureAlgorithm(data[0])<<8 | signatureAlgorithm(data[1])
Adam Langley95c29f32014-06-20 12:00:00 -07001819 data = data[2:]
1820 }
1821
1822 if len(data) < 2 {
1823 return false
1824 }
1825 siglength := int(data[0])<<8 + int(data[1])
1826 data = data[2:]
1827 if len(data) != siglength {
1828 return false
1829 }
1830
1831 m.signature = data
1832
1833 return true
1834}
1835
1836type newSessionTicketMsg struct {
David Benjamin1a5e8ec2016-10-07 15:19:18 -04001837 raw []byte
1838 version uint16
1839 ticketLifetime uint32
1840 keModes []byte
1841 authModes []byte
1842 ticket []byte
David Benjamin1286bee2016-10-07 15:25:06 -04001843 customExtension string
David Benjamin1a5e8ec2016-10-07 15:19:18 -04001844 hasGREASEExtension bool
Adam Langley95c29f32014-06-20 12:00:00 -07001845}
1846
David Benjamin58104882016-07-18 01:25:41 +02001847func (m *newSessionTicketMsg) marshal() []byte {
Adam Langley95c29f32014-06-20 12:00:00 -07001848 if m.raw != nil {
1849 return m.raw
1850 }
1851
1852 // See http://tools.ietf.org/html/rfc5077#section-3.3
David Benjamin58104882016-07-18 01:25:41 +02001853 ticketMsg := newByteBuilder()
1854 ticketMsg.addU8(typeNewSessionTicket)
1855 body := ticketMsg.addU24LengthPrefixed()
1856 body.addU32(m.ticketLifetime)
1857 if m.version >= VersionTLS13 {
Steven Valdez5b986082016-09-01 12:29:49 -04001858 body.addU8LengthPrefixed().addBytes(m.keModes)
1859 body.addU8LengthPrefixed().addBytes(m.authModes)
1860 }
1861
1862 ticket := body.addU16LengthPrefixed()
1863 ticket.addBytes(m.ticket)
1864
1865 if m.version >= VersionTLS13 {
David Benjamin1286bee2016-10-07 15:25:06 -04001866 extensions := body.addU16LengthPrefixed()
1867 if len(m.customExtension) > 0 {
1868 extensions.addU16(ticketExtensionCustom)
1869 extensions.addU16LengthPrefixed().addBytes([]byte(m.customExtension))
1870 }
David Benjamin58104882016-07-18 01:25:41 +02001871 }
Adam Langley95c29f32014-06-20 12:00:00 -07001872
David Benjamin58104882016-07-18 01:25:41 +02001873 m.raw = ticketMsg.finish()
1874 return m.raw
Adam Langley95c29f32014-06-20 12:00:00 -07001875}
1876
1877func (m *newSessionTicketMsg) unmarshal(data []byte) bool {
1878 m.raw = data
1879
David Benjamin58104882016-07-18 01:25:41 +02001880 if len(data) < 8 {
1881 return false
1882 }
1883 m.ticketLifetime = uint32(data[4])<<24 | uint32(data[5])<<16 | uint32(data[6])<<8 | uint32(data[7])
1884 data = data[8:]
1885
1886 if m.version >= VersionTLS13 {
Steven Valdez5b986082016-09-01 12:29:49 -04001887 if len(data) < 1 {
David Benjamin58104882016-07-18 01:25:41 +02001888 return false
1889 }
Steven Valdez5b986082016-09-01 12:29:49 -04001890 keModesLength := int(data[0])
1891 if len(data)-1 < keModesLength {
David Benjamin58104882016-07-18 01:25:41 +02001892 return false
1893 }
Steven Valdez5b986082016-09-01 12:29:49 -04001894 m.keModes = data[1 : 1+keModesLength]
1895 data = data[1+keModesLength:]
1896
1897 if len(data) < 1 {
1898 return false
1899 }
1900 authModesLength := int(data[0])
1901 if len(data)-1 < authModesLength {
1902 return false
1903 }
1904 m.authModes = data[1 : 1+authModesLength]
1905 data = data[1+authModesLength:]
David Benjamin58104882016-07-18 01:25:41 +02001906 }
1907
1908 if len(data) < 2 {
1909 return false
1910 }
1911 ticketLen := int(data[0])<<8 + int(data[1])
Steven Valdez5b986082016-09-01 12:29:49 -04001912 data = data[2:]
1913 if len(data) < ticketLen {
David Benjamin58104882016-07-18 01:25:41 +02001914 return false
1915 }
Steven Valdez5b986082016-09-01 12:29:49 -04001916
David Benjamin58104882016-07-18 01:25:41 +02001917 if m.version >= VersionTLS13 && ticketLen == 0 {
Adam Langley95c29f32014-06-20 12:00:00 -07001918 return false
1919 }
1920
Steven Valdez5b986082016-09-01 12:29:49 -04001921 m.ticket = data[:ticketLen]
1922 data = data[ticketLen:]
1923
1924 if m.version >= VersionTLS13 {
1925 if len(data) < 2 {
1926 return false
1927 }
1928 extsLength := int(data[0])<<8 + int(data[1])
1929 data = data[2:]
1930 if len(data) < extsLength {
1931 return false
1932 }
David Benjamin1a5e8ec2016-10-07 15:19:18 -04001933 extensions := data[:extsLength]
Steven Valdez5b986082016-09-01 12:29:49 -04001934 data = data[extsLength:]
David Benjamin1a5e8ec2016-10-07 15:19:18 -04001935
1936 for len(extensions) > 0 {
1937 if len(extensions) < 4 {
1938 return false
1939 }
1940 extValue := uint16(extensions[0])<<8 | uint16(extensions[1])
1941 extLength := int(extensions[2])<<8 | int(extensions[3])
1942 if len(extensions) < 4+extLength {
1943 return false
1944 }
1945 extensions = extensions[4+extLength:]
1946
1947 if isGREASEValue(extValue) {
1948 m.hasGREASEExtension = true
1949 }
1950 }
Steven Valdez5b986082016-09-01 12:29:49 -04001951 }
1952
1953 if len(data) > 0 {
1954 return false
1955 }
Adam Langley95c29f32014-06-20 12:00:00 -07001956
1957 return true
1958}
1959
David Benjamind86c7672014-08-02 04:07:12 -04001960type v2ClientHelloMsg struct {
1961 raw []byte
1962 vers uint16
1963 cipherSuites []uint16
1964 sessionId []byte
1965 challenge []byte
1966}
1967
David Benjamind86c7672014-08-02 04:07:12 -04001968func (m *v2ClientHelloMsg) marshal() []byte {
1969 if m.raw != nil {
1970 return m.raw
1971 }
1972
1973 length := 1 + 2 + 2 + 2 + 2 + len(m.cipherSuites)*3 + len(m.sessionId) + len(m.challenge)
1974
1975 x := make([]byte, length)
1976 x[0] = 1
1977 x[1] = uint8(m.vers >> 8)
1978 x[2] = uint8(m.vers)
1979 x[3] = uint8((len(m.cipherSuites) * 3) >> 8)
1980 x[4] = uint8(len(m.cipherSuites) * 3)
1981 x[5] = uint8(len(m.sessionId) >> 8)
1982 x[6] = uint8(len(m.sessionId))
1983 x[7] = uint8(len(m.challenge) >> 8)
1984 x[8] = uint8(len(m.challenge))
1985 y := x[9:]
1986 for i, spec := range m.cipherSuites {
1987 y[i*3] = 0
1988 y[i*3+1] = uint8(spec >> 8)
1989 y[i*3+2] = uint8(spec)
1990 }
1991 y = y[len(m.cipherSuites)*3:]
1992 copy(y, m.sessionId)
1993 y = y[len(m.sessionId):]
1994 copy(y, m.challenge)
1995
1996 m.raw = x
1997
1998 return x
1999}
2000
David Benjamin83c0bc92014-08-04 01:23:53 -04002001type helloVerifyRequestMsg struct {
2002 raw []byte
2003 vers uint16
2004 cookie []byte
2005}
2006
David Benjamin83c0bc92014-08-04 01:23:53 -04002007func (m *helloVerifyRequestMsg) marshal() []byte {
2008 if m.raw != nil {
2009 return m.raw
2010 }
2011
2012 length := 2 + 1 + len(m.cookie)
2013
2014 x := make([]byte, 4+length)
2015 x[0] = typeHelloVerifyRequest
2016 x[1] = uint8(length >> 16)
2017 x[2] = uint8(length >> 8)
2018 x[3] = uint8(length)
David Benjamin3c6a1ea2016-09-26 18:30:05 -04002019 vers := m.vers
David Benjamin83c0bc92014-08-04 01:23:53 -04002020 x[4] = uint8(vers >> 8)
2021 x[5] = uint8(vers)
2022 x[6] = uint8(len(m.cookie))
2023 copy(x[7:7+len(m.cookie)], m.cookie)
2024
2025 return x
2026}
2027
2028func (m *helloVerifyRequestMsg) unmarshal(data []byte) bool {
2029 if len(data) < 4+2+1 {
2030 return false
2031 }
2032 m.raw = data
David Benjamin3c6a1ea2016-09-26 18:30:05 -04002033 m.vers = uint16(data[4])<<8 | uint16(data[5])
David Benjamin83c0bc92014-08-04 01:23:53 -04002034 cookieLen := int(data[6])
2035 if cookieLen > 32 || len(data) != 7+cookieLen {
2036 return false
2037 }
2038 m.cookie = data[7 : 7+cookieLen]
2039
2040 return true
2041}
2042
David Benjamin24599a82016-06-30 18:56:53 -04002043type channelIDMsg struct {
David Benjamind30a9902014-08-24 01:44:23 -04002044 raw []byte
2045 channelID []byte
2046}
2047
David Benjamin24599a82016-06-30 18:56:53 -04002048func (m *channelIDMsg) marshal() []byte {
David Benjamind30a9902014-08-24 01:44:23 -04002049 if m.raw != nil {
2050 return m.raw
2051 }
2052
2053 length := 2 + 2 + len(m.channelID)
2054
2055 x := make([]byte, 4+length)
David Benjamin24599a82016-06-30 18:56:53 -04002056 x[0] = typeChannelID
David Benjamind30a9902014-08-24 01:44:23 -04002057 x[1] = uint8(length >> 16)
2058 x[2] = uint8(length >> 8)
2059 x[3] = uint8(length)
2060 x[4] = uint8(extensionChannelID >> 8)
2061 x[5] = uint8(extensionChannelID & 0xff)
2062 x[6] = uint8(len(m.channelID) >> 8)
2063 x[7] = uint8(len(m.channelID) & 0xff)
2064 copy(x[8:], m.channelID)
2065
2066 return x
2067}
2068
David Benjamin24599a82016-06-30 18:56:53 -04002069func (m *channelIDMsg) unmarshal(data []byte) bool {
David Benjamind30a9902014-08-24 01:44:23 -04002070 if len(data) != 4+2+2+128 {
2071 return false
2072 }
2073 m.raw = data
2074 if (uint16(data[4])<<8)|uint16(data[5]) != extensionChannelID {
2075 return false
2076 }
2077 if int(data[6])<<8|int(data[7]) != 128 {
2078 return false
2079 }
2080 m.channelID = data[4+2+2:]
2081
2082 return true
2083}
2084
Adam Langley2ae77d22014-10-28 17:29:33 -07002085type helloRequestMsg struct {
2086}
2087
2088func (*helloRequestMsg) marshal() []byte {
2089 return []byte{typeHelloRequest, 0, 0, 0}
2090}
2091
2092func (*helloRequestMsg) unmarshal(data []byte) bool {
2093 return len(data) == 4
2094}
2095
David Benjamin21c00282016-07-18 21:56:23 +02002096type keyUpdateMsg struct {
Steven Valdezc4aa7272016-10-03 12:25:56 -04002097 raw []byte
2098 keyUpdateRequest byte
David Benjamin21c00282016-07-18 21:56:23 +02002099}
2100
Steven Valdezc4aa7272016-10-03 12:25:56 -04002101func (m *keyUpdateMsg) marshal() []byte {
2102 if m.raw != nil {
2103 return m.raw
2104 }
2105
2106 return []byte{typeKeyUpdate, 0, 0, 1, m.keyUpdateRequest}
David Benjamin21c00282016-07-18 21:56:23 +02002107}
2108
Steven Valdezc4aa7272016-10-03 12:25:56 -04002109func (m *keyUpdateMsg) unmarshal(data []byte) bool {
2110 m.raw = data
2111
2112 if len(data) != 5 {
2113 return false
2114 }
2115
2116 length := int(data[1])<<16 | int(data[2])<<8 | int(data[3])
2117 if len(data)-4 != length {
2118 return false
2119 }
2120
2121 m.keyUpdateRequest = data[4]
2122 return m.keyUpdateRequest == keyUpdateNotRequested || m.keyUpdateRequest == keyUpdateRequested
David Benjamin21c00282016-07-18 21:56:23 +02002123}
2124
Adam Langley95c29f32014-06-20 12:00:00 -07002125func eqUint16s(x, y []uint16) bool {
2126 if len(x) != len(y) {
2127 return false
2128 }
2129 for i, v := range x {
2130 if y[i] != v {
2131 return false
2132 }
2133 }
2134 return true
2135}
2136
2137func eqCurveIDs(x, y []CurveID) bool {
2138 if len(x) != len(y) {
2139 return false
2140 }
2141 for i, v := range x {
2142 if y[i] != v {
2143 return false
2144 }
2145 }
2146 return true
2147}
2148
2149func eqStrings(x, y []string) bool {
2150 if len(x) != len(y) {
2151 return false
2152 }
2153 for i, v := range x {
2154 if y[i] != v {
2155 return false
2156 }
2157 }
2158 return true
2159}
2160
2161func eqByteSlices(x, y [][]byte) bool {
2162 if len(x) != len(y) {
2163 return false
2164 }
2165 for i, v := range x {
2166 if !bytes.Equal(v, y[i]) {
2167 return false
2168 }
2169 }
2170 return true
2171}
2172
Nick Harper60edffd2016-06-21 15:19:24 -07002173func eqSignatureAlgorithms(x, y []signatureAlgorithm) bool {
Adam Langley95c29f32014-06-20 12:00:00 -07002174 if len(x) != len(y) {
2175 return false
2176 }
2177 for i, v := range x {
2178 v2 := y[i]
Nick Harper60edffd2016-06-21 15:19:24 -07002179 if v != v2 {
Adam Langley95c29f32014-06-20 12:00:00 -07002180 return false
2181 }
2182 }
2183 return true
2184}
Nick Harperf8b0e702016-06-30 19:59:01 -04002185
2186func eqKeyShareEntryLists(x, y []keyShareEntry) bool {
2187 if len(x) != len(y) {
2188 return false
2189 }
2190 for i, v := range x {
2191 if y[i].group != v.group || !bytes.Equal(y[i].keyExchange, v.keyExchange) {
2192 return false
2193 }
2194 }
2195 return true
2196
2197}
Steven Valdez5b986082016-09-01 12:29:49 -04002198
2199func eqPSKIdentityLists(x, y []pskIdentity) bool {
2200 if len(x) != len(y) {
2201 return false
2202 }
2203 for i, v := range x {
2204 if !bytes.Equal(y[i].keModes, v.keModes) || !bytes.Equal(y[i].authModes, v.authModes) || !bytes.Equal(y[i].ticket, v.ticket) {
2205 return false
2206 }
2207 }
2208 return true
2209
2210}