...
Run Format

Source file src/crypto/tls/handshake_messages.go

  // Copyright 2009 The Go Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style
  // license that can be found in the LICENSE file.
  
  package tls
  
  import "bytes"
  
  type clientHelloMsg struct {
  	raw                          []byte
  	vers                         uint16
  	random                       []byte
  	sessionId                    []byte
  	cipherSuites                 []uint16
  	compressionMethods           []uint8
  	nextProtoNeg                 bool
  	serverName                   string
  	ocspStapling                 bool
  	scts                         bool
  	supportedCurves              []CurveID
  	supportedPoints              []uint8
  	ticketSupported              bool
  	sessionTicket                []uint8
  	signatureAndHashes           []signatureAndHash
  	secureRenegotiation          []byte
  	secureRenegotiationSupported bool
  	alpnProtocols                []string
  }
  
  func (m *clientHelloMsg) equal(i interface{}) bool {
  	m1, ok := i.(*clientHelloMsg)
  	if !ok {
  		return false
  	}
  
  	return bytes.Equal(m.raw, m1.raw) &&
  		m.vers == m1.vers &&
  		bytes.Equal(m.random, m1.random) &&
  		bytes.Equal(m.sessionId, m1.sessionId) &&
  		eqUint16s(m.cipherSuites, m1.cipherSuites) &&
  		bytes.Equal(m.compressionMethods, m1.compressionMethods) &&
  		m.nextProtoNeg == m1.nextProtoNeg &&
  		m.serverName == m1.serverName &&
  		m.ocspStapling == m1.ocspStapling &&
  		m.scts == m1.scts &&
  		eqCurveIDs(m.supportedCurves, m1.supportedCurves) &&
  		bytes.Equal(m.supportedPoints, m1.supportedPoints) &&
  		m.ticketSupported == m1.ticketSupported &&
  		bytes.Equal(m.sessionTicket, m1.sessionTicket) &&
  		eqSignatureAndHashes(m.signatureAndHashes, m1.signatureAndHashes) &&
  		m.secureRenegotiationSupported == m1.secureRenegotiationSupported &&
  		bytes.Equal(m.secureRenegotiation, m1.secureRenegotiation) &&
  		eqStrings(m.alpnProtocols, m1.alpnProtocols)
  }
  
  func (m *clientHelloMsg) marshal() []byte {
  	if m.raw != nil {
  		return m.raw
  	}
  
  	length := 2 + 32 + 1 + len(m.sessionId) + 2 + len(m.cipherSuites)*2 + 1 + len(m.compressionMethods)
  	numExtensions := 0
  	extensionsLength := 0
  	if m.nextProtoNeg {
  		numExtensions++
  	}
  	if m.ocspStapling {
  		extensionsLength += 1 + 2 + 2
  		numExtensions++
  	}
  	if len(m.serverName) > 0 {
  		extensionsLength += 5 + len(m.serverName)
  		numExtensions++
  	}
  	if len(m.supportedCurves) > 0 {
  		extensionsLength += 2 + 2*len(m.supportedCurves)
  		numExtensions++
  	}
  	if len(m.supportedPoints) > 0 {
  		extensionsLength += 1 + len(m.supportedPoints)
  		numExtensions++
  	}
  	if m.ticketSupported {
  		extensionsLength += len(m.sessionTicket)
  		numExtensions++
  	}
  	if len(m.signatureAndHashes) > 0 {
  		extensionsLength += 2 + 2*len(m.signatureAndHashes)
  		numExtensions++
  	}
  	if m.secureRenegotiationSupported {
  		extensionsLength += 1 + len(m.secureRenegotiation)
  		numExtensions++
  	}
  	if len(m.alpnProtocols) > 0 {
  		extensionsLength += 2
  		for _, s := range m.alpnProtocols {
  			if l := len(s); l == 0 || l > 255 {
  				panic("invalid ALPN protocol")
  			}
  			extensionsLength++
  			extensionsLength += len(s)
  		}
  		numExtensions++
  	}
  	if m.scts {
  		numExtensions++
  	}
  	if numExtensions > 0 {
  		extensionsLength += 4 * numExtensions
  		length += 2 + extensionsLength
  	}
  
  	x := make([]byte, 4+length)
  	x[0] = typeClientHello
  	x[1] = uint8(length >> 16)
  	x[2] = uint8(length >> 8)
  	x[3] = uint8(length)
  	x[4] = uint8(m.vers >> 8)
  	x[5] = uint8(m.vers)
  	copy(x[6:38], m.random)
  	x[38] = uint8(len(m.sessionId))
  	copy(x[39:39+len(m.sessionId)], m.sessionId)
  	y := x[39+len(m.sessionId):]
  	y[0] = uint8(len(m.cipherSuites) >> 7)
  	y[1] = uint8(len(m.cipherSuites) << 1)
  	for i, suite := range m.cipherSuites {
  		y[2+i*2] = uint8(suite >> 8)
  		y[3+i*2] = uint8(suite)
  	}
  	z := y[2+len(m.cipherSuites)*2:]
  	z[0] = uint8(len(m.compressionMethods))
  	copy(z[1:], m.compressionMethods)
  
  	z = z[1+len(m.compressionMethods):]
  	if numExtensions > 0 {
  		z[0] = byte(extensionsLength >> 8)
  		z[1] = byte(extensionsLength)
  		z = z[2:]
  	}
  	if m.nextProtoNeg {
  		z[0] = byte(extensionNextProtoNeg >> 8)
  		z[1] = byte(extensionNextProtoNeg & 0xff)
  		// The length is always 0
  		z = z[4:]
  	}
  	if len(m.serverName) > 0 {
  		z[0] = byte(extensionServerName >> 8)
  		z[1] = byte(extensionServerName & 0xff)
  		l := len(m.serverName) + 5
  		z[2] = byte(l >> 8)
  		z[3] = byte(l)
  		z = z[4:]
  
  		// RFC 3546, section 3.1
  		//
  		// struct {
  		//     NameType name_type;
  		//     select (name_type) {
  		//         case host_name: HostName;
  		//     } name;
  		// } ServerName;
  		//
  		// enum {
  		//     host_name(0), (255)
  		// } NameType;
  		//
  		// opaque HostName<1..2^16-1>;
  		//
  		// struct {
  		//     ServerName server_name_list<1..2^16-1>
  		// } ServerNameList;
  
  		z[0] = byte((len(m.serverName) + 3) >> 8)
  		z[1] = byte(len(m.serverName) + 3)
  		z[3] = byte(len(m.serverName) >> 8)
  		z[4] = byte(len(m.serverName))
  		copy(z[5:], []byte(m.serverName))
  		z = z[l:]
  	}
  	if m.ocspStapling {
  		// RFC 4366, section 3.6
  		z[0] = byte(extensionStatusRequest >> 8)
  		z[1] = byte(extensionStatusRequest)
  		z[2] = 0
  		z[3] = 5
  		z[4] = 1 // OCSP type
  		// Two zero valued uint16s for the two lengths.
  		z = z[9:]
  	}
  	if len(m.supportedCurves) > 0 {
  		// http://tools.ietf.org/html/rfc4492#section-5.5.1
  		z[0] = byte(extensionSupportedCurves >> 8)
  		z[1] = byte(extensionSupportedCurves)
  		l := 2 + 2*len(m.supportedCurves)
  		z[2] = byte(l >> 8)
  		z[3] = byte(l)
  		l -= 2
  		z[4] = byte(l >> 8)
  		z[5] = byte(l)
  		z = z[6:]
  		for _, curve := range m.supportedCurves {
  			z[0] = byte(curve >> 8)
  			z[1] = byte(curve)
  			z = z[2:]
  		}
  	}
  	if len(m.supportedPoints) > 0 {
  		// http://tools.ietf.org/html/rfc4492#section-5.5.2
  		z[0] = byte(extensionSupportedPoints >> 8)
  		z[1] = byte(extensionSupportedPoints)
  		l := 1 + len(m.supportedPoints)
  		z[2] = byte(l >> 8)
  		z[3] = byte(l)
  		l--
  		z[4] = byte(l)
  		z = z[5:]
  		for _, pointFormat := range m.supportedPoints {
  			z[0] = pointFormat
  			z = z[1:]
  		}
  	}
  	if m.ticketSupported {
  		// http://tools.ietf.org/html/rfc5077#section-3.2
  		z[0] = byte(extensionSessionTicket >> 8)
  		z[1] = byte(extensionSessionTicket)
  		l := len(m.sessionTicket)
  		z[2] = byte(l >> 8)
  		z[3] = byte(l)
  		z = z[4:]
  		copy(z, m.sessionTicket)
  		z = z[len(m.sessionTicket):]
  	}
  	if len(m.signatureAndHashes) > 0 {
  		// https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
  		z[0] = byte(extensionSignatureAlgorithms >> 8)
  		z[1] = byte(extensionSignatureAlgorithms)
  		l := 2 + 2*len(m.signatureAndHashes)
  		z[2] = byte(l >> 8)
  		z[3] = byte(l)
  		z = z[4:]
  
  		l -= 2
  		z[0] = byte(l >> 8)
  		z[1] = byte(l)
  		z = z[2:]
  		for _, sigAndHash := range m.signatureAndHashes {
  			z[0] = sigAndHash.hash
  			z[1] = sigAndHash.signature
  			z = z[2:]
  		}
  	}
  	if m.secureRenegotiationSupported {
  		z[0] = byte(extensionRenegotiationInfo >> 8)
  		z[1] = byte(extensionRenegotiationInfo & 0xff)
  		z[2] = 0
  		z[3] = byte(len(m.secureRenegotiation) + 1)
  		z[4] = byte(len(m.secureRenegotiation))
  		z = z[5:]
  		copy(z, m.secureRenegotiation)
  		z = z[len(m.secureRenegotiation):]
  	}
  	if len(m.alpnProtocols) > 0 {
  		z[0] = byte(extensionALPN >> 8)
  		z[1] = byte(extensionALPN & 0xff)
  		lengths := z[2:]
  		z = z[6:]
  
  		stringsLength := 0
  		for _, s := range m.alpnProtocols {
  			l := len(s)
  			z[0] = byte(l)
  			copy(z[1:], s)
  			z = z[1+l:]
  			stringsLength += 1 + l
  		}
  
  		lengths[2] = byte(stringsLength >> 8)
  		lengths[3] = byte(stringsLength)
  		stringsLength += 2
  		lengths[0] = byte(stringsLength >> 8)
  		lengths[1] = byte(stringsLength)
  	}
  	if m.scts {
  		// https://tools.ietf.org/html/rfc6962#section-3.3.1
  		z[0] = byte(extensionSCT >> 8)
  		z[1] = byte(extensionSCT)
  		// zero uint16 for the zero-length extension_data
  		z = z[4:]
  	}
  
  	m.raw = x
  
  	return x
  }
  
  func (m *clientHelloMsg) unmarshal(data []byte) bool {
  	if len(data) < 42 {
  		return false
  	}
  	m.raw = data
  	m.vers = uint16(data[4])<<8 | uint16(data[5])
  	m.random = data[6:38]
  	sessionIdLen := int(data[38])
  	if sessionIdLen > 32 || len(data) < 39+sessionIdLen {
  		return false
  	}
  	m.sessionId = data[39 : 39+sessionIdLen]
  	data = data[39+sessionIdLen:]
  	if len(data) < 2 {
  		return false
  	}
  	// cipherSuiteLen is the number of bytes of cipher suite numbers. Since
  	// they are uint16s, the number must be even.
  	cipherSuiteLen := int(data[0])<<8 | int(data[1])
  	if cipherSuiteLen%2 == 1 || len(data) < 2+cipherSuiteLen {
  		return false
  	}
  	numCipherSuites := cipherSuiteLen / 2
  	m.cipherSuites = make([]uint16, numCipherSuites)
  	for i := 0; i < numCipherSuites; i++ {
  		m.cipherSuites[i] = uint16(data[2+2*i])<<8 | uint16(data[3+2*i])
  		if m.cipherSuites[i] == scsvRenegotiation {
  			m.secureRenegotiationSupported = true
  		}
  	}
  	data = data[2+cipherSuiteLen:]
  	if len(data) < 1 {
  		return false
  	}
  	compressionMethodsLen := int(data[0])
  	if len(data) < 1+compressionMethodsLen {
  		return false
  	}
  	m.compressionMethods = data[1 : 1+compressionMethodsLen]
  
  	data = data[1+compressionMethodsLen:]
  
  	m.nextProtoNeg = false
  	m.serverName = ""
  	m.ocspStapling = false
  	m.ticketSupported = false
  	m.sessionTicket = nil
  	m.signatureAndHashes = nil
  	m.alpnProtocols = nil
  	m.scts = false
  
  	if len(data) == 0 {
  		// ClientHello is optionally followed by extension data
  		return true
  	}
  	if len(data) < 2 {
  		return false
  	}
  
  	extensionsLength := int(data[0])<<8 | int(data[1])
  	data = data[2:]
  	if extensionsLength != len(data) {
  		return false
  	}
  
  	for len(data) != 0 {
  		if len(data) < 4 {
  			return false
  		}
  		extension := uint16(data[0])<<8 | uint16(data[1])
  		length := int(data[2])<<8 | int(data[3])
  		data = data[4:]
  		if len(data) < length {
  			return false
  		}
  
  		switch extension {
  		case extensionServerName:
  			d := data[:length]
  			if len(d) < 2 {
  				return false
  			}
  			namesLen := int(d[0])<<8 | int(d[1])
  			d = d[2:]
  			if len(d) != namesLen {
  				return false
  			}
  			for len(d) > 0 {
  				if len(d) < 3 {
  					return false
  				}
  				nameType := d[0]
  				nameLen := int(d[1])<<8 | int(d[2])
  				d = d[3:]
  				if len(d) < nameLen {
  					return false
  				}
  				if nameType == 0 {
  					m.serverName = string(d[:nameLen])
  					break
  				}
  				d = d[nameLen:]
  			}
  		case extensionNextProtoNeg:
  			if length > 0 {
  				return false
  			}
  			m.nextProtoNeg = true
  		case extensionStatusRequest:
  			m.ocspStapling = length > 0 && data[0] == statusTypeOCSP
  		case extensionSupportedCurves:
  			// http://tools.ietf.org/html/rfc4492#section-5.5.1
  			if length < 2 {
  				return false
  			}
  			l := int(data[0])<<8 | int(data[1])
  			if l%2 == 1 || length != l+2 {
  				return false
  			}
  			numCurves := l / 2
  			m.supportedCurves = make([]CurveID, numCurves)
  			d := data[2:]
  			for i := 0; i < numCurves; i++ {
  				m.supportedCurves[i] = CurveID(d[0])<<8 | CurveID(d[1])
  				d = d[2:]
  			}
  		case extensionSupportedPoints:
  			// http://tools.ietf.org/html/rfc4492#section-5.5.2
  			if length < 1 {
  				return false
  			}
  			l := int(data[0])
  			if length != l+1 {
  				return false
  			}
  			m.supportedPoints = make([]uint8, l)
  			copy(m.supportedPoints, data[1:])
  		case extensionSessionTicket:
  			// http://tools.ietf.org/html/rfc5077#section-3.2
  			m.ticketSupported = true
  			m.sessionTicket = data[:length]
  		case extensionSignatureAlgorithms:
  			// https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
  			if length < 2 || length&1 != 0 {
  				return false
  			}
  			l := int(data[0])<<8 | int(data[1])
  			if l != length-2 {
  				return false
  			}
  			n := l / 2
  			d := data[2:]
  			m.signatureAndHashes = make([]signatureAndHash, n)
  			for i := range m.signatureAndHashes {
  				m.signatureAndHashes[i].hash = d[0]
  				m.signatureAndHashes[i].signature = d[1]
  				d = d[2:]
  			}
  		case extensionRenegotiationInfo:
  			if length == 0 {
  				return false
  			}
  			d := data[:length]
  			l := int(d[0])
  			d = d[1:]
  			if l != len(d) {
  				return false
  			}
  
  			m.secureRenegotiation = d
  			m.secureRenegotiationSupported = true
  		case extensionALPN:
  			if length < 2 {
  				return false
  			}
  			l := int(data[0])<<8 | int(data[1])
  			if l != length-2 {
  				return false
  			}
  			d := data[2:length]
  			for len(d) != 0 {
  				stringLen := int(d[0])
  				d = d[1:]
  				if stringLen == 0 || stringLen > len(d) {
  					return false
  				}
  				m.alpnProtocols = append(m.alpnProtocols, string(d[:stringLen]))
  				d = d[stringLen:]
  			}
  		case extensionSCT:
  			m.scts = true
  			if length != 0 {
  				return false
  			}
  		}
  		data = data[length:]
  	}
  
  	return true
  }
  
  type serverHelloMsg struct {
  	raw                          []byte
  	vers                         uint16
  	random                       []byte
  	sessionId                    []byte
  	cipherSuite                  uint16
  	compressionMethod            uint8
  	nextProtoNeg                 bool
  	nextProtos                   []string
  	ocspStapling                 bool
  	scts                         [][]byte
  	ticketSupported              bool
  	secureRenegotiation          []byte
  	secureRenegotiationSupported bool
  	alpnProtocol                 string
  }
  
  func (m *serverHelloMsg) equal(i interface{}) bool {
  	m1, ok := i.(*serverHelloMsg)
  	if !ok {
  		return false
  	}
  
  	if len(m.scts) != len(m1.scts) {
  		return false
  	}
  	for i, sct := range m.scts {
  		if !bytes.Equal(sct, m1.scts[i]) {
  			return false
  		}
  	}
  
  	return bytes.Equal(m.raw, m1.raw) &&
  		m.vers == m1.vers &&
  		bytes.Equal(m.random, m1.random) &&
  		bytes.Equal(m.sessionId, m1.sessionId) &&
  		m.cipherSuite == m1.cipherSuite &&
  		m.compressionMethod == m1.compressionMethod &&
  		m.nextProtoNeg == m1.nextProtoNeg &&
  		eqStrings(m.nextProtos, m1.nextProtos) &&
  		m.ocspStapling == m1.ocspStapling &&
  		m.ticketSupported == m1.ticketSupported &&
  		m.secureRenegotiationSupported == m1.secureRenegotiationSupported &&
  		bytes.Equal(m.secureRenegotiation, m1.secureRenegotiation) &&
  		m.alpnProtocol == m1.alpnProtocol
  }
  
  func (m *serverHelloMsg) marshal() []byte {
  	if m.raw != nil {
  		return m.raw
  	}
  
  	length := 38 + len(m.sessionId)
  	numExtensions := 0
  	extensionsLength := 0
  
  	nextProtoLen := 0
  	if m.nextProtoNeg {
  		numExtensions++
  		for _, v := range m.nextProtos {
  			nextProtoLen += len(v)
  		}
  		nextProtoLen += len(m.nextProtos)
  		extensionsLength += nextProtoLen
  	}
  	if m.ocspStapling {
  		numExtensions++
  	}
  	if m.ticketSupported {
  		numExtensions++
  	}
  	if m.secureRenegotiationSupported {
  		extensionsLength += 1 + len(m.secureRenegotiation)
  		numExtensions++
  	}
  	if alpnLen := len(m.alpnProtocol); alpnLen > 0 {
  		if alpnLen >= 256 {
  			panic("invalid ALPN protocol")
  		}
  		extensionsLength += 2 + 1 + alpnLen
  		numExtensions++
  	}
  	sctLen := 0
  	if len(m.scts) > 0 {
  		for _, sct := range m.scts {
  			sctLen += len(sct) + 2
  		}
  		extensionsLength += 2 + sctLen
  		numExtensions++
  	}
  
  	if numExtensions > 0 {
  		extensionsLength += 4 * numExtensions
  		length += 2 + extensionsLength
  	}
  
  	x := make([]byte, 4+length)
  	x[0] = typeServerHello
  	x[1] = uint8(length >> 16)
  	x[2] = uint8(length >> 8)
  	x[3] = uint8(length)
  	x[4] = uint8(m.vers >> 8)
  	x[5] = uint8(m.vers)
  	copy(x[6:38], m.random)
  	x[38] = uint8(len(m.sessionId))
  	copy(x[39:39+len(m.sessionId)], m.sessionId)
  	z := x[39+len(m.sessionId):]
  	z[0] = uint8(m.cipherSuite >> 8)
  	z[1] = uint8(m.cipherSuite)
  	z[2] = m.compressionMethod
  
  	z = z[3:]
  	if numExtensions > 0 {
  		z[0] = byte(extensionsLength >> 8)
  		z[1] = byte(extensionsLength)
  		z = z[2:]
  	}
  	if m.nextProtoNeg {
  		z[0] = byte(extensionNextProtoNeg >> 8)
  		z[1] = byte(extensionNextProtoNeg & 0xff)
  		z[2] = byte(nextProtoLen >> 8)
  		z[3] = byte(nextProtoLen)
  		z = z[4:]
  
  		for _, v := range m.nextProtos {
  			l := len(v)
  			if l > 255 {
  				l = 255
  			}
  			z[0] = byte(l)
  			copy(z[1:], []byte(v[0:l]))
  			z = z[1+l:]
  		}
  	}
  	if m.ocspStapling {
  		z[0] = byte(extensionStatusRequest >> 8)
  		z[1] = byte(extensionStatusRequest)
  		z = z[4:]
  	}
  	if m.ticketSupported {
  		z[0] = byte(extensionSessionTicket >> 8)
  		z[1] = byte(extensionSessionTicket)
  		z = z[4:]
  	}
  	if m.secureRenegotiationSupported {
  		z[0] = byte(extensionRenegotiationInfo >> 8)
  		z[1] = byte(extensionRenegotiationInfo & 0xff)
  		z[2] = 0
  		z[3] = byte(len(m.secureRenegotiation) + 1)
  		z[4] = byte(len(m.secureRenegotiation))
  		z = z[5:]
  		copy(z, m.secureRenegotiation)
  		z = z[len(m.secureRenegotiation):]
  	}
  	if alpnLen := len(m.alpnProtocol); alpnLen > 0 {
  		z[0] = byte(extensionALPN >> 8)
  		z[1] = byte(extensionALPN & 0xff)
  		l := 2 + 1 + alpnLen
  		z[2] = byte(l >> 8)
  		z[3] = byte(l)
  		l -= 2
  		z[4] = byte(l >> 8)
  		z[5] = byte(l)
  		l -= 1
  		z[6] = byte(l)
  		copy(z[7:], []byte(m.alpnProtocol))
  		z = z[7+alpnLen:]
  	}
  	if sctLen > 0 {
  		z[0] = byte(extensionSCT >> 8)
  		z[1] = byte(extensionSCT)
  		l := sctLen + 2
  		z[2] = byte(l >> 8)
  		z[3] = byte(l)
  		z[4] = byte(sctLen >> 8)
  		z[5] = byte(sctLen)
  
  		z = z[6:]
  		for _, sct := range m.scts {
  			z[0] = byte(len(sct) >> 8)
  			z[1] = byte(len(sct))
  			copy(z[2:], sct)
  			z = z[len(sct)+2:]
  		}
  	}
  
  	m.raw = x
  
  	return x
  }
  
  func (m *serverHelloMsg) unmarshal(data []byte) bool {
  	if len(data) < 42 {
  		return false
  	}
  	m.raw = data
  	m.vers = uint16(data[4])<<8 | uint16(data[5])
  	m.random = data[6:38]
  	sessionIdLen := int(data[38])
  	if sessionIdLen > 32 || len(data) < 39+sessionIdLen {
  		return false
  	}
  	m.sessionId = data[39 : 39+sessionIdLen]
  	data = data[39+sessionIdLen:]
  	if len(data) < 3 {
  		return false
  	}
  	m.cipherSuite = uint16(data[0])<<8 | uint16(data[1])
  	m.compressionMethod = data[2]
  	data = data[3:]
  
  	m.nextProtoNeg = false
  	m.nextProtos = nil
  	m.ocspStapling = false
  	m.scts = nil
  	m.ticketSupported = false
  	m.alpnProtocol = ""
  
  	if len(data) == 0 {
  		// ServerHello is optionally followed by extension data
  		return true
  	}
  	if len(data) < 2 {
  		return false
  	}
  
  	extensionsLength := int(data[0])<<8 | int(data[1])
  	data = data[2:]
  	if len(data) != extensionsLength {
  		return false
  	}
  
  	for len(data) != 0 {
  		if len(data) < 4 {
  			return false
  		}
  		extension := uint16(data[0])<<8 | uint16(data[1])
  		length := int(data[2])<<8 | int(data[3])
  		data = data[4:]
  		if len(data) < length {
  			return false
  		}
  
  		switch extension {
  		case extensionNextProtoNeg:
  			m.nextProtoNeg = true
  			d := data[:length]
  			for len(d) > 0 {
  				l := int(d[0])
  				d = d[1:]
  				if l == 0 || l > len(d) {
  					return false
  				}
  				m.nextProtos = append(m.nextProtos, string(d[:l]))
  				d = d[l:]
  			}
  		case extensionStatusRequest:
  			if length > 0 {
  				return false
  			}
  			m.ocspStapling = true
  		case extensionSessionTicket:
  			if length > 0 {
  				return false
  			}
  			m.ticketSupported = true
  		case extensionRenegotiationInfo:
  			if length == 0 {
  				return false
  			}
  			d := data[:length]
  			l := int(d[0])
  			d = d[1:]
  			if l != len(d) {
  				return false
  			}
  
  			m.secureRenegotiation = d
  			m.secureRenegotiationSupported = true
  		case extensionALPN:
  			d := data[:length]
  			if len(d) < 3 {
  				return false
  			}
  			l := int(d[0])<<8 | int(d[1])
  			if l != len(d)-2 {
  				return false
  			}
  			d = d[2:]
  			l = int(d[0])
  			if l != len(d)-1 {
  				return false
  			}
  			d = d[1:]
  			if len(d) == 0 {
  				// ALPN protocols must not be empty.
  				return false
  			}
  			m.alpnProtocol = string(d)
  		case extensionSCT:
  			d := data[:length]
  
  			if len(d) < 2 {
  				return false
  			}
  			l := int(d[0])<<8 | int(d[1])
  			d = d[2:]
  			if len(d) != l || l == 0 {
  				return false
  			}
  
  			m.scts = make([][]byte, 0, 3)
  			for len(d) != 0 {
  				if len(d) < 2 {
  					return false
  				}
  				sctLen := int(d[0])<<8 | int(d[1])
  				d = d[2:]
  				if sctLen == 0 || len(d) < sctLen {
  					return false
  				}
  				m.scts = append(m.scts, d[:sctLen])
  				d = d[sctLen:]
  			}
  		}
  		data = data[length:]
  	}
  
  	return true
  }
  
  type certificateMsg struct {
  	raw          []byte
  	certificates [][]byte
  }
  
  func (m *certificateMsg) equal(i interface{}) bool {
  	m1, ok := i.(*certificateMsg)
  	if !ok {
  		return false
  	}
  
  	return bytes.Equal(m.raw, m1.raw) &&
  		eqByteSlices(m.certificates, m1.certificates)
  }
  
  func (m *certificateMsg) marshal() (x []byte) {
  	if m.raw != nil {
  		return m.raw
  	}
  
  	var i int
  	for _, slice := range m.certificates {
  		i += len(slice)
  	}
  
  	length := 3 + 3*len(m.certificates) + i
  	x = make([]byte, 4+length)
  	x[0] = typeCertificate
  	x[1] = uint8(length >> 16)
  	x[2] = uint8(length >> 8)
  	x[3] = uint8(length)
  
  	certificateOctets := length - 3
  	x[4] = uint8(certificateOctets >> 16)
  	x[5] = uint8(certificateOctets >> 8)
  	x[6] = uint8(certificateOctets)
  
  	y := x[7:]
  	for _, slice := range m.certificates {
  		y[0] = uint8(len(slice) >> 16)
  		y[1] = uint8(len(slice) >> 8)
  		y[2] = uint8(len(slice))
  		copy(y[3:], slice)
  		y = y[3+len(slice):]
  	}
  
  	m.raw = x
  	return
  }
  
  func (m *certificateMsg) unmarshal(data []byte) bool {
  	if len(data) < 7 {
  		return false
  	}
  
  	m.raw = data
  	certsLen := uint32(data[4])<<16 | uint32(data[5])<<8 | uint32(data[6])
  	if uint32(len(data)) != certsLen+7 {
  		return false
  	}
  
  	numCerts := 0
  	d := data[7:]
  	for certsLen > 0 {
  		if len(d) < 4 {
  			return false
  		}
  		certLen := uint32(d[0])<<16 | uint32(d[1])<<8 | uint32(d[2])
  		if uint32(len(d)) < 3+certLen {
  			return false
  		}
  		d = d[3+certLen:]
  		certsLen -= 3 + certLen
  		numCerts++
  	}
  
  	m.certificates = make([][]byte, numCerts)
  	d = data[7:]
  	for i := 0; i < numCerts; i++ {
  		certLen := uint32(d[0])<<16 | uint32(d[1])<<8 | uint32(d[2])
  		m.certificates[i] = d[3 : 3+certLen]
  		d = d[3+certLen:]
  	}
  
  	return true
  }
  
  type serverKeyExchangeMsg struct {
  	raw []byte
  	key []byte
  }
  
  func (m *serverKeyExchangeMsg) equal(i interface{}) bool {
  	m1, ok := i.(*serverKeyExchangeMsg)
  	if !ok {
  		return false
  	}
  
  	return bytes.Equal(m.raw, m1.raw) &&
  		bytes.Equal(m.key, m1.key)
  }
  
  func (m *serverKeyExchangeMsg) marshal() []byte {
  	if m.raw != nil {
  		return m.raw
  	}
  	length := len(m.key)
  	x := make([]byte, length+4)
  	x[0] = typeServerKeyExchange
  	x[1] = uint8(length >> 16)
  	x[2] = uint8(length >> 8)
  	x[3] = uint8(length)
  	copy(x[4:], m.key)
  
  	m.raw = x
  	return x
  }
  
  func (m *serverKeyExchangeMsg) unmarshal(data []byte) bool {
  	m.raw = data
  	if len(data) < 4 {
  		return false
  	}
  	m.key = data[4:]
  	return true
  }
  
  type certificateStatusMsg struct {
  	raw        []byte
  	statusType uint8
  	response   []byte
  }
  
  func (m *certificateStatusMsg) equal(i interface{}) bool {
  	m1, ok := i.(*certificateStatusMsg)
  	if !ok {
  		return false
  	}
  
  	return bytes.Equal(m.raw, m1.raw) &&
  		m.statusType == m1.statusType &&
  		bytes.Equal(m.response, m1.response)
  }
  
  func (m *certificateStatusMsg) marshal() []byte {
  	if m.raw != nil {
  		return m.raw
  	}
  
  	var x []byte
  	if m.statusType == statusTypeOCSP {
  		x = make([]byte, 4+4+len(m.response))
  		x[0] = typeCertificateStatus
  		l := len(m.response) + 4
  		x[1] = byte(l >> 16)
  		x[2] = byte(l >> 8)
  		x[3] = byte(l)
  		x[4] = statusTypeOCSP
  
  		l -= 4
  		x[5] = byte(l >> 16)
  		x[6] = byte(l >> 8)
  		x[7] = byte(l)
  		copy(x[8:], m.response)
  	} else {
  		x = []byte{typeCertificateStatus, 0, 0, 1, m.statusType}
  	}
  
  	m.raw = x
  	return x
  }
  
  func (m *certificateStatusMsg) unmarshal(data []byte) bool {
  	m.raw = data
  	if len(data) < 5 {
  		return false
  	}
  	m.statusType = data[4]
  
  	m.response = nil
  	if m.statusType == statusTypeOCSP {
  		if len(data) < 8 {
  			return false
  		}
  		respLen := uint32(data[5])<<16 | uint32(data[6])<<8 | uint32(data[7])
  		if uint32(len(data)) != 4+4+respLen {
  			return false
  		}
  		m.response = data[8:]
  	}
  	return true
  }
  
  type serverHelloDoneMsg struct{}
  
  func (m *serverHelloDoneMsg) equal(i interface{}) bool {
  	_, ok := i.(*serverHelloDoneMsg)
  	return ok
  }
  
  func (m *serverHelloDoneMsg) marshal() []byte {
  	x := make([]byte, 4)
  	x[0] = typeServerHelloDone
  	return x
  }
  
  func (m *serverHelloDoneMsg) unmarshal(data []byte) bool {
  	return len(data) == 4
  }
  
  type clientKeyExchangeMsg struct {
  	raw        []byte
  	ciphertext []byte
  }
  
  func (m *clientKeyExchangeMsg) equal(i interface{}) bool {
  	m1, ok := i.(*clientKeyExchangeMsg)
  	if !ok {
  		return false
  	}
  
  	return bytes.Equal(m.raw, m1.raw) &&
  		bytes.Equal(m.ciphertext, m1.ciphertext)
  }
  
  func (m *clientKeyExchangeMsg) marshal() []byte {
  	if m.raw != nil {
  		return m.raw
  	}
  	length := len(m.ciphertext)
  	x := make([]byte, length+4)
  	x[0] = typeClientKeyExchange
  	x[1] = uint8(length >> 16)
  	x[2] = uint8(length >> 8)
  	x[3] = uint8(length)
  	copy(x[4:], m.ciphertext)
  
  	m.raw = x
  	return x
  }
  
  func (m *clientKeyExchangeMsg) unmarshal(data []byte) bool {
  	m.raw = data
  	if len(data) < 4 {
  		return false
  	}
  	l := int(data[1])<<16 | int(data[2])<<8 | int(data[3])
  	if l != len(data)-4 {
  		return false
  	}
  	m.ciphertext = data[4:]
  	return true
  }
  
  type finishedMsg struct {
  	raw        []byte
  	verifyData []byte
  }
  
  func (m *finishedMsg) equal(i interface{}) bool {
  	m1, ok := i.(*finishedMsg)
  	if !ok {
  		return false
  	}
  
  	return bytes.Equal(m.raw, m1.raw) &&
  		bytes.Equal(m.verifyData, m1.verifyData)
  }
  
  func (m *finishedMsg) marshal() (x []byte) {
  	if m.raw != nil {
  		return m.raw
  	}
  
  	x = make([]byte, 4+len(m.verifyData))
  	x[0] = typeFinished
  	x[3] = byte(len(m.verifyData))
  	copy(x[4:], m.verifyData)
  	m.raw = x
  	return
  }
  
  func (m *finishedMsg) unmarshal(data []byte) bool {
  	m.raw = data
  	if len(data) < 4 {
  		return false
  	}
  	m.verifyData = data[4:]
  	return true
  }
  
  type nextProtoMsg struct {
  	raw   []byte
  	proto string
  }
  
  func (m *nextProtoMsg) equal(i interface{}) bool {
  	m1, ok := i.(*nextProtoMsg)
  	if !ok {
  		return false
  	}
  
  	return bytes.Equal(m.raw, m1.raw) &&
  		m.proto == m1.proto
  }
  
  func (m *nextProtoMsg) marshal() []byte {
  	if m.raw != nil {
  		return m.raw
  	}
  	l := len(m.proto)
  	if l > 255 {
  		l = 255
  	}
  
  	padding := 32 - (l+2)%32
  	length := l + padding + 2
  	x := make([]byte, length+4)
  	x[0] = typeNextProtocol
  	x[1] = uint8(length >> 16)
  	x[2] = uint8(length >> 8)
  	x[3] = uint8(length)
  
  	y := x[4:]
  	y[0] = byte(l)
  	copy(y[1:], []byte(m.proto[0:l]))
  	y = y[1+l:]
  	y[0] = byte(padding)
  
  	m.raw = x
  
  	return x
  }
  
  func (m *nextProtoMsg) unmarshal(data []byte) bool {
  	m.raw = data
  
  	if len(data) < 5 {
  		return false
  	}
  	data = data[4:]
  	protoLen := int(data[0])
  	data = data[1:]
  	if len(data) < protoLen {
  		return false
  	}
  	m.proto = string(data[0:protoLen])
  	data = data[protoLen:]
  
  	if len(data) < 1 {
  		return false
  	}
  	paddingLen := int(data[0])
  	data = data[1:]
  	if len(data) != paddingLen {
  		return false
  	}
  
  	return true
  }
  
  type certificateRequestMsg struct {
  	raw []byte
  	// hasSignatureAndHash indicates whether this message includes a list
  	// of signature and hash functions. This change was introduced with TLS
  	// 1.2.
  	hasSignatureAndHash bool
  
  	certificateTypes       []byte
  	signatureAndHashes     []signatureAndHash
  	certificateAuthorities [][]byte
  }
  
  func (m *certificateRequestMsg) equal(i interface{}) bool {
  	m1, ok := i.(*certificateRequestMsg)
  	if !ok {
  		return false
  	}
  
  	return bytes.Equal(m.raw, m1.raw) &&
  		bytes.Equal(m.certificateTypes, m1.certificateTypes) &&
  		eqByteSlices(m.certificateAuthorities, m1.certificateAuthorities) &&
  		eqSignatureAndHashes(m.signatureAndHashes, m1.signatureAndHashes)
  }
  
  func (m *certificateRequestMsg) marshal() (x []byte) {
  	if m.raw != nil {
  		return m.raw
  	}
  
  	// See http://tools.ietf.org/html/rfc4346#section-7.4.4
  	length := 1 + len(m.certificateTypes) + 2
  	casLength := 0
  	for _, ca := range m.certificateAuthorities {
  		casLength += 2 + len(ca)
  	}
  	length += casLength
  
  	if m.hasSignatureAndHash {
  		length += 2 + 2*len(m.signatureAndHashes)
  	}
  
  	x = make([]byte, 4+length)
  	x[0] = typeCertificateRequest
  	x[1] = uint8(length >> 16)
  	x[2] = uint8(length >> 8)
  	x[3] = uint8(length)
  
  	x[4] = uint8(len(m.certificateTypes))
  
  	copy(x[5:], m.certificateTypes)
  	y := x[5+len(m.certificateTypes):]
  
  	if m.hasSignatureAndHash {
  		n := len(m.signatureAndHashes) * 2
  		y[0] = uint8(n >> 8)
  		y[1] = uint8(n)
  		y = y[2:]
  		for _, sigAndHash := range m.signatureAndHashes {
  			y[0] = sigAndHash.hash
  			y[1] = sigAndHash.signature
  			y = y[2:]
  		}
  	}
  
  	y[0] = uint8(casLength >> 8)
  	y[1] = uint8(casLength)
  	y = y[2:]
  	for _, ca := range m.certificateAuthorities {
  		y[0] = uint8(len(ca) >> 8)
  		y[1] = uint8(len(ca))
  		y = y[2:]
  		copy(y, ca)
  		y = y[len(ca):]
  	}
  
  	m.raw = x
  	return
  }
  
  func (m *certificateRequestMsg) unmarshal(data []byte) bool {
  	m.raw = data
  
  	if len(data) < 5 {
  		return false
  	}
  
  	length := uint32(data[1])<<16 | uint32(data[2])<<8 | uint32(data[3])
  	if uint32(len(data))-4 != length {
  		return false
  	}
  
  	numCertTypes := int(data[4])
  	data = data[5:]
  	if numCertTypes == 0 || len(data) <= numCertTypes {
  		return false
  	}
  
  	m.certificateTypes = make([]byte, numCertTypes)
  	if copy(m.certificateTypes, data) != numCertTypes {
  		return false
  	}
  
  	data = data[numCertTypes:]
  
  	if m.hasSignatureAndHash {
  		if len(data) < 2 {
  			return false
  		}
  		sigAndHashLen := uint16(data[0])<<8 | uint16(data[1])
  		data = data[2:]
  		if sigAndHashLen&1 != 0 {
  			return false
  		}
  		if len(data) < int(sigAndHashLen) {
  			return false
  		}
  		numSigAndHash := sigAndHashLen / 2
  		m.signatureAndHashes = make([]signatureAndHash, numSigAndHash)
  		for i := range m.signatureAndHashes {
  			m.signatureAndHashes[i].hash = data[0]
  			m.signatureAndHashes[i].signature = data[1]
  			data = data[2:]
  		}
  	}
  
  	if len(data) < 2 {
  		return false
  	}
  	casLength := uint16(data[0])<<8 | uint16(data[1])
  	data = data[2:]
  	if len(data) < int(casLength) {
  		return false
  	}
  	cas := make([]byte, casLength)
  	copy(cas, data)
  	data = data[casLength:]
  
  	m.certificateAuthorities = nil
  	for len(cas) > 0 {
  		if len(cas) < 2 {
  			return false
  		}
  		caLen := uint16(cas[0])<<8 | uint16(cas[1])
  		cas = cas[2:]
  
  		if len(cas) < int(caLen) {
  			return false
  		}
  
  		m.certificateAuthorities = append(m.certificateAuthorities, cas[:caLen])
  		cas = cas[caLen:]
  	}
  
  	return len(data) == 0
  }
  
  type certificateVerifyMsg struct {
  	raw                 []byte
  	hasSignatureAndHash bool
  	signatureAndHash    signatureAndHash
  	signature           []byte
  }
  
  func (m *certificateVerifyMsg) equal(i interface{}) bool {
  	m1, ok := i.(*certificateVerifyMsg)
  	if !ok {
  		return false
  	}
  
  	return bytes.Equal(m.raw, m1.raw) &&
  		m.hasSignatureAndHash == m1.hasSignatureAndHash &&
  		m.signatureAndHash.hash == m1.signatureAndHash.hash &&
  		m.signatureAndHash.signature == m1.signatureAndHash.signature &&
  		bytes.Equal(m.signature, m1.signature)
  }
  
  func (m *certificateVerifyMsg) marshal() (x []byte) {
  	if m.raw != nil {
  		return m.raw
  	}
  
  	// See http://tools.ietf.org/html/rfc4346#section-7.4.8
  	siglength := len(m.signature)
  	length := 2 + siglength
  	if m.hasSignatureAndHash {
  		length += 2
  	}
  	x = make([]byte, 4+length)
  	x[0] = typeCertificateVerify
  	x[1] = uint8(length >> 16)
  	x[2] = uint8(length >> 8)
  	x[3] = uint8(length)
  	y := x[4:]
  	if m.hasSignatureAndHash {
  		y[0] = m.signatureAndHash.hash
  		y[1] = m.signatureAndHash.signature
  		y = y[2:]
  	}
  	y[0] = uint8(siglength >> 8)
  	y[1] = uint8(siglength)
  	copy(y[2:], m.signature)
  
  	m.raw = x
  
  	return
  }
  
  func (m *certificateVerifyMsg) unmarshal(data []byte) bool {
  	m.raw = data
  
  	if len(data) < 6 {
  		return false
  	}
  
  	length := uint32(data[1])<<16 | uint32(data[2])<<8 | uint32(data[3])
  	if uint32(len(data))-4 != length {
  		return false
  	}
  
  	data = data[4:]
  	if m.hasSignatureAndHash {
  		m.signatureAndHash.hash = data[0]
  		m.signatureAndHash.signature = data[1]
  		data = data[2:]
  	}
  
  	if len(data) < 2 {
  		return false
  	}
  	siglength := int(data[0])<<8 + int(data[1])
  	data = data[2:]
  	if len(data) != siglength {
  		return false
  	}
  
  	m.signature = data
  
  	return true
  }
  
  type newSessionTicketMsg struct {
  	raw    []byte
  	ticket []byte
  }
  
  func (m *newSessionTicketMsg) equal(i interface{}) bool {
  	m1, ok := i.(*newSessionTicketMsg)
  	if !ok {
  		return false
  	}
  
  	return bytes.Equal(m.raw, m1.raw) &&
  		bytes.Equal(m.ticket, m1.ticket)
  }
  
  func (m *newSessionTicketMsg) marshal() (x []byte) {
  	if m.raw != nil {
  		return m.raw
  	}
  
  	// See http://tools.ietf.org/html/rfc5077#section-3.3
  	ticketLen := len(m.ticket)
  	length := 2 + 4 + ticketLen
  	x = make([]byte, 4+length)
  	x[0] = typeNewSessionTicket
  	x[1] = uint8(length >> 16)
  	x[2] = uint8(length >> 8)
  	x[3] = uint8(length)
  	x[8] = uint8(ticketLen >> 8)
  	x[9] = uint8(ticketLen)
  	copy(x[10:], m.ticket)
  
  	m.raw = x
  
  	return
  }
  
  func (m *newSessionTicketMsg) unmarshal(data []byte) bool {
  	m.raw = data
  
  	if len(data) < 10 {
  		return false
  	}
  
  	length := uint32(data[1])<<16 | uint32(data[2])<<8 | uint32(data[3])
  	if uint32(len(data))-4 != length {
  		return false
  	}
  
  	ticketLen := int(data[8])<<8 + int(data[9])
  	if len(data)-10 != ticketLen {
  		return false
  	}
  
  	m.ticket = data[10:]
  
  	return true
  }
  
  type helloRequestMsg struct {
  }
  
  func (*helloRequestMsg) marshal() []byte {
  	return []byte{typeHelloRequest, 0, 0, 0}
  }
  
  func (*helloRequestMsg) unmarshal(data []byte) bool {
  	return len(data) == 4
  }
  
  func eqUint16s(x, y []uint16) bool {
  	if len(x) != len(y) {
  		return false
  	}
  	for i, v := range x {
  		if y[i] != v {
  			return false
  		}
  	}
  	return true
  }
  
  func eqCurveIDs(x, y []CurveID) bool {
  	if len(x) != len(y) {
  		return false
  	}
  	for i, v := range x {
  		if y[i] != v {
  			return false
  		}
  	}
  	return true
  }
  
  func eqStrings(x, y []string) bool {
  	if len(x) != len(y) {
  		return false
  	}
  	for i, v := range x {
  		if y[i] != v {
  			return false
  		}
  	}
  	return true
  }
  
  func eqByteSlices(x, y [][]byte) bool {
  	if len(x) != len(y) {
  		return false
  	}
  	for i, v := range x {
  		if !bytes.Equal(v, y[i]) {
  			return false
  		}
  	}
  	return true
  }
  
  func eqSignatureAndHashes(x, y []signatureAndHash) bool {
  	if len(x) != len(y) {
  		return false
  	}
  	for i, v := range x {
  		v2 := y[i]
  		if v.hash != v2.hash || v.signature != v2.signature {
  			return false
  		}
  	}
  	return true
  }
  

View as plain text