2009-11-04 01:25:13 +00:00
|
|
|
// 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
|
|
|
|
|
|
|
|
type clientHelloMsg struct {
|
2009-12-15 23:33:31 +00:00
|
|
|
raw []byte
|
|
|
|
major, minor uint8
|
|
|
|
random []byte
|
|
|
|
sessionId []byte
|
|
|
|
cipherSuites []uint16
|
|
|
|
compressionMethods []uint8
|
2009-12-23 19:13:09 +00:00
|
|
|
nextProtoNeg bool
|
|
|
|
serverName string
|
2009-11-04 01:25:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (m *clientHelloMsg) marshal() []byte {
|
|
|
|
if m.raw != nil {
|
2009-11-09 20:07:39 +00:00
|
|
|
return m.raw
|
2009-11-04 01:25:13 +00:00
|
|
|
}
|
|
|
|
|
2009-12-15 23:33:31 +00:00
|
|
|
length := 2 + 32 + 1 + len(m.sessionId) + 2 + len(m.cipherSuites)*2 + 1 + len(m.compressionMethods)
|
2009-12-23 19:13:09 +00:00
|
|
|
numExtensions := 0
|
|
|
|
extensionsLength := 0
|
|
|
|
if m.nextProtoNeg {
|
|
|
|
numExtensions++
|
|
|
|
}
|
|
|
|
if len(m.serverName) > 0 {
|
|
|
|
extensionsLength += 5 + len(m.serverName)
|
|
|
|
numExtensions++
|
|
|
|
}
|
|
|
|
if numExtensions > 0 {
|
|
|
|
extensionsLength += 4 * numExtensions
|
|
|
|
length += 2 + extensionsLength
|
|
|
|
}
|
|
|
|
|
2009-12-15 23:33:31 +00:00
|
|
|
x := make([]byte, 4+length)
|
|
|
|
x[0] = typeClientHello
|
|
|
|
x[1] = uint8(length >> 16)
|
|
|
|
x[2] = uint8(length >> 8)
|
|
|
|
x[3] = uint8(length)
|
|
|
|
x[4] = m.major
|
|
|
|
x[5] = m.minor
|
|
|
|
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)
|
2009-11-04 01:25:13 +00:00
|
|
|
for i, suite := range m.cipherSuites {
|
2009-12-15 23:33:31 +00:00
|
|
|
y[2+i*2] = uint8(suite >> 8)
|
|
|
|
y[3+i*2] = uint8(suite)
|
2009-11-04 01:25:13 +00:00
|
|
|
}
|
2009-12-15 23:33:31 +00:00
|
|
|
z := y[2+len(m.cipherSuites)*2:]
|
|
|
|
z[0] = uint8(len(m.compressionMethods))
|
|
|
|
copy(z[1:], m.compressionMethods)
|
2009-12-23 19:13:09 +00:00
|
|
|
|
|
|
|
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)
|
|
|
|
// The length is always 0
|
|
|
|
z = z[4:]
|
|
|
|
}
|
|
|
|
if len(m.serverName) > 0 {
|
|
|
|
z[0] = byte(extensionServerName >> 8)
|
|
|
|
z[1] = byte(extensionServerName)
|
|
|
|
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[1] = 1
|
|
|
|
z[3] = byte(len(m.serverName) >> 8)
|
|
|
|
z[4] = byte(len(m.serverName))
|
2010-02-26 00:01:29 +00:00
|
|
|
copy(z[5:], []byte(m.serverName))
|
2009-12-23 19:13:09 +00:00
|
|
|
z = z[l:]
|
|
|
|
}
|
|
|
|
|
2009-12-15 23:33:31 +00:00
|
|
|
m.raw = x
|
2009-11-04 01:25:13 +00:00
|
|
|
|
2009-12-15 23:33:31 +00:00
|
|
|
return x
|
2009-11-04 01:25:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (m *clientHelloMsg) unmarshal(data []byte) bool {
|
2009-11-21 23:53:03 +00:00
|
|
|
if len(data) < 43 {
|
2009-11-09 20:07:39 +00:00
|
|
|
return false
|
2009-11-04 01:25:13 +00:00
|
|
|
}
|
2009-12-15 23:33:31 +00:00
|
|
|
m.raw = data
|
|
|
|
m.major = data[4]
|
|
|
|
m.minor = data[5]
|
|
|
|
m.random = data[6:38]
|
|
|
|
sessionIdLen := int(data[38])
|
2009-11-10 05:13:17 +00:00
|
|
|
if sessionIdLen > 32 || len(data) < 39+sessionIdLen {
|
2009-11-09 20:07:39 +00:00
|
|
|
return false
|
2009-11-04 01:25:13 +00:00
|
|
|
}
|
2009-12-15 23:33:31 +00:00
|
|
|
m.sessionId = data[39 : 39+sessionIdLen]
|
|
|
|
data = data[39+sessionIdLen:]
|
2009-11-04 01:25:13 +00:00
|
|
|
if len(data) < 2 {
|
2009-11-09 20:07:39 +00:00
|
|
|
return false
|
2009-11-04 01:25:13 +00:00
|
|
|
}
|
|
|
|
// cipherSuiteLen is the number of bytes of cipher suite numbers. Since
|
|
|
|
// they are uint16s, the number must be even.
|
2009-12-15 23:33:31 +00:00
|
|
|
cipherSuiteLen := int(data[0])<<8 | int(data[1])
|
2009-11-10 05:13:17 +00:00
|
|
|
if cipherSuiteLen%2 == 1 || len(data) < 2+cipherSuiteLen {
|
2009-11-09 20:07:39 +00:00
|
|
|
return false
|
2009-11-04 01:25:13 +00:00
|
|
|
}
|
2009-12-15 23:33:31 +00:00
|
|
|
numCipherSuites := cipherSuiteLen / 2
|
|
|
|
m.cipherSuites = make([]uint16, numCipherSuites)
|
2009-11-04 01:25:13 +00:00
|
|
|
for i := 0; i < numCipherSuites; i++ {
|
2009-11-10 05:13:17 +00:00
|
|
|
m.cipherSuites[i] = uint16(data[2+2*i])<<8 | uint16(data[3+2*i])
|
2009-11-04 01:25:13 +00:00
|
|
|
}
|
2009-12-15 23:33:31 +00:00
|
|
|
data = data[2+cipherSuiteLen:]
|
2009-11-04 01:25:13 +00:00
|
|
|
if len(data) < 2 {
|
2009-11-09 20:07:39 +00:00
|
|
|
return false
|
2009-11-04 01:25:13 +00:00
|
|
|
}
|
2009-12-15 23:33:31 +00:00
|
|
|
compressionMethodsLen := int(data[0])
|
2009-11-10 05:13:17 +00:00
|
|
|
if len(data) < 1+compressionMethodsLen {
|
2009-11-09 20:07:39 +00:00
|
|
|
return false
|
2009-11-04 01:25:13 +00:00
|
|
|
}
|
2009-12-15 23:33:31 +00:00
|
|
|
m.compressionMethods = data[1 : 1+compressionMethodsLen]
|
2009-11-04 01:25:13 +00:00
|
|
|
|
2009-12-23 19:13:09 +00:00
|
|
|
data = data[1+compressionMethodsLen:]
|
|
|
|
|
|
|
|
m.nextProtoNeg = false
|
|
|
|
m.serverName = ""
|
|
|
|
|
|
|
|
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:
|
|
|
|
if length < 2 {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
numNames := int(data[0])<<8 | int(data[1])
|
|
|
|
d := data[2:]
|
|
|
|
for i := 0; i < numNames; i++ {
|
|
|
|
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[0:nameLen])
|
|
|
|
break
|
|
|
|
}
|
|
|
|
d = d[nameLen:]
|
|
|
|
}
|
|
|
|
case extensionNextProtoNeg:
|
|
|
|
if length > 0 {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
m.nextProtoNeg = true
|
|
|
|
}
|
|
|
|
data = data[length:]
|
|
|
|
}
|
|
|
|
|
2009-12-15 23:33:31 +00:00
|
|
|
return true
|
2009-11-04 01:25:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type serverHelloMsg struct {
|
2009-12-15 23:33:31 +00:00
|
|
|
raw []byte
|
|
|
|
major, minor uint8
|
|
|
|
random []byte
|
|
|
|
sessionId []byte
|
|
|
|
cipherSuite uint16
|
|
|
|
compressionMethod uint8
|
2009-12-23 19:13:09 +00:00
|
|
|
nextProtoNeg bool
|
|
|
|
nextProtos []string
|
2009-11-04 01:25:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (m *serverHelloMsg) marshal() []byte {
|
|
|
|
if m.raw != nil {
|
2009-11-09 20:07:39 +00:00
|
|
|
return m.raw
|
2009-11-04 01:25:13 +00:00
|
|
|
}
|
|
|
|
|
2009-12-15 23:33:31 +00:00
|
|
|
length := 38 + len(m.sessionId)
|
2009-12-23 19:13:09 +00:00
|
|
|
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 numExtensions > 0 {
|
|
|
|
extensionsLength += 4 * numExtensions
|
|
|
|
length += 2 + extensionsLength
|
|
|
|
}
|
|
|
|
|
2009-12-15 23:33:31 +00:00
|
|
|
x := make([]byte, 4+length)
|
|
|
|
x[0] = typeServerHello
|
|
|
|
x[1] = uint8(length >> 16)
|
|
|
|
x[2] = uint8(length >> 8)
|
|
|
|
x[3] = uint8(length)
|
|
|
|
x[4] = m.major
|
|
|
|
x[5] = m.minor
|
|
|
|
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] = uint8(m.compressionMethod)
|
2009-12-23 19:13:09 +00:00
|
|
|
|
|
|
|
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)
|
|
|
|
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)
|
2010-02-26 00:01:29 +00:00
|
|
|
copy(z[1:], []byte(v[0:l]))
|
2009-12-23 19:13:09 +00:00
|
|
|
z = z[1+l:]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-12-15 23:33:31 +00:00
|
|
|
m.raw = x
|
|
|
|
|
|
|
|
return x
|
2009-11-04 01:25:13 +00:00
|
|
|
}
|
|
|
|
|
2009-12-23 19:13:09 +00:00
|
|
|
func append(slice []string, elem string) []string {
|
|
|
|
if len(slice) < cap(slice) {
|
|
|
|
slice = slice[0 : len(slice)+1]
|
|
|
|
slice[len(slice)-1] = elem
|
|
|
|
return slice
|
|
|
|
}
|
|
|
|
|
|
|
|
fresh := make([]string, len(slice)+1, cap(slice)*2+1)
|
|
|
|
copy(fresh, slice)
|
|
|
|
fresh[len(slice)] = elem
|
|
|
|
return fresh
|
|
|
|
}
|
|
|
|
|
2009-11-21 23:53:03 +00:00
|
|
|
func (m *serverHelloMsg) unmarshal(data []byte) bool {
|
|
|
|
if len(data) < 42 {
|
|
|
|
return false
|
|
|
|
}
|
2009-12-15 23:33:31 +00:00
|
|
|
m.raw = data
|
|
|
|
m.major = data[4]
|
|
|
|
m.minor = data[5]
|
|
|
|
m.random = data[6:38]
|
|
|
|
sessionIdLen := int(data[38])
|
2009-11-21 23:53:03 +00:00
|
|
|
if sessionIdLen > 32 || len(data) < 39+sessionIdLen {
|
|
|
|
return false
|
|
|
|
}
|
2009-12-15 23:33:31 +00:00
|
|
|
m.sessionId = data[39 : 39+sessionIdLen]
|
|
|
|
data = data[39+sessionIdLen:]
|
2009-11-21 23:53:03 +00:00
|
|
|
if len(data) < 3 {
|
|
|
|
return false
|
|
|
|
}
|
2009-12-15 23:33:31 +00:00
|
|
|
m.cipherSuite = uint16(data[0])<<8 | uint16(data[1])
|
|
|
|
m.compressionMethod = data[2]
|
2009-12-23 19:13:09 +00:00
|
|
|
data = data[3:]
|
|
|
|
|
|
|
|
m.nextProtoNeg = false
|
|
|
|
m.nextProtos = nil
|
|
|
|
|
|
|
|
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
|
|
|
|
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[0:l]))
|
|
|
|
d = d[l:]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
data = data[length:]
|
|
|
|
}
|
2009-11-21 23:53:03 +00:00
|
|
|
|
2009-12-15 23:33:31 +00:00
|
|
|
return true
|
2009-11-21 23:53:03 +00:00
|
|
|
}
|
|
|
|
|
2009-11-04 01:25:13 +00:00
|
|
|
type certificateMsg struct {
|
2009-12-15 23:33:31 +00:00
|
|
|
raw []byte
|
|
|
|
certificates [][]byte
|
2009-11-04 01:25:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (m *certificateMsg) marshal() (x []byte) {
|
|
|
|
if m.raw != nil {
|
2009-11-09 20:07:39 +00:00
|
|
|
return m.raw
|
2009-11-04 01:25:13 +00:00
|
|
|
}
|
|
|
|
|
2009-12-15 23:33:31 +00:00
|
|
|
var i int
|
2009-11-04 01:25:13 +00:00
|
|
|
for _, slice := range m.certificates {
|
2009-11-09 20:07:39 +00:00
|
|
|
i += len(slice)
|
2009-11-04 01:25:13 +00:00
|
|
|
}
|
|
|
|
|
2009-12-15 23:33:31 +00:00
|
|
|
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)
|
2009-11-04 01:25:13 +00:00
|
|
|
|
2009-12-15 23:33:31 +00:00
|
|
|
certificateOctets := length - 3
|
|
|
|
x[4] = uint8(certificateOctets >> 16)
|
|
|
|
x[5] = uint8(certificateOctets >> 8)
|
|
|
|
x[6] = uint8(certificateOctets)
|
2009-11-04 01:25:13 +00:00
|
|
|
|
2009-12-15 23:33:31 +00:00
|
|
|
y := x[7:]
|
2009-11-04 01:25:13 +00:00
|
|
|
for _, slice := range m.certificates {
|
2009-12-15 23:33:31 +00:00
|
|
|
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):]
|
2009-11-04 01:25:13 +00:00
|
|
|
}
|
|
|
|
|
2009-12-15 23:33:31 +00:00
|
|
|
m.raw = x
|
|
|
|
return
|
2009-11-04 01:25:13 +00:00
|
|
|
}
|
|
|
|
|
2009-11-21 23:53:03 +00:00
|
|
|
func (m *certificateMsg) unmarshal(data []byte) bool {
|
|
|
|
if len(data) < 7 {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2009-12-15 23:33:31 +00:00
|
|
|
m.raw = data
|
|
|
|
certsLen := uint32(data[4])<<16 | uint32(data[5])<<8 | uint32(data[6])
|
2009-11-21 23:53:03 +00:00
|
|
|
if uint32(len(data)) != certsLen+7 {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2009-12-15 23:33:31 +00:00
|
|
|
numCerts := 0
|
|
|
|
d := data[7:]
|
2009-11-21 23:53:03 +00:00
|
|
|
for certsLen > 0 {
|
|
|
|
if len(d) < 4 {
|
|
|
|
return false
|
|
|
|
}
|
2009-12-15 23:33:31 +00:00
|
|
|
certLen := uint32(d[0])<<24 | uint32(d[1])<<8 | uint32(d[2])
|
2009-11-21 23:53:03 +00:00
|
|
|
if uint32(len(d)) < 3+certLen {
|
|
|
|
return false
|
|
|
|
}
|
2009-12-15 23:33:31 +00:00
|
|
|
d = d[3+certLen:]
|
|
|
|
certsLen -= 3 + certLen
|
|
|
|
numCerts++
|
2009-11-21 23:53:03 +00:00
|
|
|
}
|
|
|
|
|
2009-12-15 23:33:31 +00:00
|
|
|
m.certificates = make([][]byte, numCerts)
|
|
|
|
d = data[7:]
|
2009-11-21 23:53:03 +00:00
|
|
|
for i := 0; i < numCerts; i++ {
|
2009-12-15 23:33:31 +00:00
|
|
|
certLen := uint32(d[0])<<24 | uint32(d[1])<<8 | uint32(d[2])
|
|
|
|
m.certificates[i] = d[3 : 3+certLen]
|
|
|
|
d = d[3+certLen:]
|
2009-11-21 23:53:03 +00:00
|
|
|
}
|
|
|
|
|
2009-12-15 23:33:31 +00:00
|
|
|
return true
|
2009-11-21 23:53:03 +00:00
|
|
|
}
|
|
|
|
|
2009-11-04 01:25:13 +00:00
|
|
|
type serverHelloDoneMsg struct{}
|
|
|
|
|
|
|
|
func (m *serverHelloDoneMsg) marshal() []byte {
|
2009-12-15 23:33:31 +00:00
|
|
|
x := make([]byte, 4)
|
|
|
|
x[0] = typeServerHelloDone
|
|
|
|
return x
|
2009-11-04 01:25:13 +00:00
|
|
|
}
|
|
|
|
|
2009-11-21 23:53:03 +00:00
|
|
|
func (m *serverHelloDoneMsg) unmarshal(data []byte) bool {
|
|
|
|
return len(data) == 4
|
|
|
|
}
|
|
|
|
|
2009-11-04 01:25:13 +00:00
|
|
|
type clientKeyExchangeMsg struct {
|
2009-12-15 23:33:31 +00:00
|
|
|
raw []byte
|
|
|
|
ciphertext []byte
|
2009-11-04 01:25:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (m *clientKeyExchangeMsg) marshal() []byte {
|
|
|
|
if m.raw != nil {
|
2009-11-09 20:07:39 +00:00
|
|
|
return m.raw
|
2009-11-04 01:25:13 +00:00
|
|
|
}
|
2009-12-15 23:33:31 +00:00
|
|
|
length := len(m.ciphertext) + 2
|
|
|
|
x := make([]byte, length+4)
|
|
|
|
x[0] = typeClientKeyExchange
|
|
|
|
x[1] = uint8(length >> 16)
|
|
|
|
x[2] = uint8(length >> 8)
|
|
|
|
x[3] = uint8(length)
|
|
|
|
x[4] = uint8(len(m.ciphertext) >> 8)
|
|
|
|
x[5] = uint8(len(m.ciphertext))
|
|
|
|
copy(x[6:], m.ciphertext)
|
|
|
|
|
|
|
|
m.raw = x
|
|
|
|
return x
|
2009-11-04 01:25:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (m *clientKeyExchangeMsg) unmarshal(data []byte) bool {
|
2009-12-15 23:33:31 +00:00
|
|
|
m.raw = data
|
2009-11-04 01:25:13 +00:00
|
|
|
if len(data) < 7 {
|
2009-11-09 20:07:39 +00:00
|
|
|
return false
|
2009-11-04 01:25:13 +00:00
|
|
|
}
|
2009-12-15 23:33:31 +00:00
|
|
|
cipherTextLen := int(data[4])<<8 | int(data[5])
|
2009-11-10 05:13:17 +00:00
|
|
|
if len(data) != 6+cipherTextLen {
|
2009-11-09 20:07:39 +00:00
|
|
|
return false
|
2009-11-04 01:25:13 +00:00
|
|
|
}
|
2009-12-15 23:33:31 +00:00
|
|
|
m.ciphertext = data[6:]
|
|
|
|
return true
|
2009-11-04 01:25:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type finishedMsg struct {
|
2009-12-15 23:33:31 +00:00
|
|
|
raw []byte
|
|
|
|
verifyData []byte
|
2009-11-04 01:25:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (m *finishedMsg) marshal() (x []byte) {
|
|
|
|
if m.raw != nil {
|
2009-11-09 20:07:39 +00:00
|
|
|
return m.raw
|
2009-11-04 01:25:13 +00:00
|
|
|
}
|
|
|
|
|
2009-12-15 23:33:31 +00:00
|
|
|
x = make([]byte, 16)
|
|
|
|
x[0] = typeFinished
|
|
|
|
x[3] = 12
|
|
|
|
copy(x[4:], m.verifyData)
|
|
|
|
m.raw = x
|
|
|
|
return
|
2009-11-04 01:25:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (m *finishedMsg) unmarshal(data []byte) bool {
|
2009-12-15 23:33:31 +00:00
|
|
|
m.raw = data
|
2009-11-04 01:25:13 +00:00
|
|
|
if len(data) != 4+12 {
|
2009-11-09 20:07:39 +00:00
|
|
|
return false
|
2009-11-04 01:25:13 +00:00
|
|
|
}
|
2009-12-15 23:33:31 +00:00
|
|
|
m.verifyData = data[4:]
|
|
|
|
return true
|
2009-11-04 01:25:13 +00:00
|
|
|
}
|
2009-12-23 19:13:09 +00:00
|
|
|
|
|
|
|
type nextProtoMsg struct {
|
|
|
|
raw []byte
|
|
|
|
proto string
|
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
2010-02-26 00:01:29 +00:00
|
|
|
copy(y[1:], []byte(m.proto[0:l]))
|
2009-12-23 19:13:09 +00:00
|
|
|
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
|
|
|
|
}
|