summaryrefslogtreecommitdiff
path: root/src/pkg/crypto/tls/handshake_messages.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/crypto/tls/handshake_messages.go')
-rw-r--r--src/pkg/crypto/tls/handshake_messages.go367
1 files changed, 345 insertions, 22 deletions
diff --git a/src/pkg/crypto/tls/handshake_messages.go b/src/pkg/crypto/tls/handshake_messages.go
index f0a48c863..e5e856271 100644
--- a/src/pkg/crypto/tls/handshake_messages.go
+++ b/src/pkg/crypto/tls/handshake_messages.go
@@ -13,6 +13,9 @@ type clientHelloMsg struct {
compressionMethods []uint8
nextProtoNeg bool
serverName string
+ ocspStapling bool
+ supportedCurves []uint16
+ supportedPoints []uint8
}
func (m *clientHelloMsg) marshal() []byte {
@@ -26,10 +29,22 @@ func (m *clientHelloMsg) marshal() []byte {
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 numExtensions > 0 {
extensionsLength += 4 * numExtensions
length += 2 + extensionsLength
@@ -95,12 +110,55 @@ func (m *clientHelloMsg) marshal() []byte {
// ServerName server_name_list<1..2^16-1>
// } ServerNameList;
- z[1] = 1
+ 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] = byte(pointFormat)
+ z = z[1:]
+ }
+ }
m.raw = x
@@ -148,6 +206,7 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool {
m.nextProtoNeg = false
m.serverName = ""
+ m.ocspStapling = false
if len(data) == 0 {
// ClientHello is optionally followed by extension data
@@ -202,6 +261,35 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool {
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([]uint16, numCurves)
+ d := data[2:]
+ for i := 0; i < numCurves; i++ {
+ m.supportedCurves[i] = uint16(d[0])<<8 | uint16(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:])
}
data = data[length:]
}
@@ -218,6 +306,7 @@ type serverHelloMsg struct {
compressionMethod uint8
nextProtoNeg bool
nextProtos []string
+ certStatus bool
}
func (m *serverHelloMsg) marshal() []byte {
@@ -238,6 +327,9 @@ func (m *serverHelloMsg) marshal() []byte {
nextProtoLen += len(m.nextProtos)
extensionsLength += nextProtoLen
}
+ if m.certStatus {
+ numExtensions++
+ }
if numExtensions > 0 {
extensionsLength += 4 * numExtensions
length += 2 + extensionsLength
@@ -281,25 +373,17 @@ func (m *serverHelloMsg) marshal() []byte {
z = z[1+l:]
}
}
+ if m.certStatus {
+ z[0] = byte(extensionStatusRequest >> 8)
+ z[1] = byte(extensionStatusRequest)
+ z = z[4:]
+ }
m.raw = x
return x
}
-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
-}
-
func (m *serverHelloMsg) unmarshal(data []byte) bool {
if len(data) < 42 {
return false
@@ -322,6 +406,7 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool {
m.nextProtoNeg = false
m.nextProtos = nil
+ m.certStatus = false
if len(data) == 0 {
// ServerHello is optionally followed by extension data
@@ -361,6 +446,11 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool {
m.nextProtos = append(m.nextProtos, string(d[0:l]))
d = d[l:]
}
+ case extensionStatusRequest:
+ if length > 0 {
+ return false
+ }
+ m.certStatus = true
}
data = data[length:]
}
@@ -445,6 +535,91 @@ func (m *certificateMsg) unmarshal(data []byte) bool {
return true
}
+type serverKeyExchangeMsg struct {
+ raw []byte
+ key []byte
+}
+
+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) 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) marshal() []byte {
@@ -466,15 +641,13 @@ func (m *clientKeyExchangeMsg) marshal() []byte {
if m.raw != nil {
return m.raw
}
- length := len(m.ciphertext) + 2
+ 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)
- x[4] = uint8(len(m.ciphertext) >> 8)
- x[5] = uint8(len(m.ciphertext))
- copy(x[6:], m.ciphertext)
+ copy(x[4:], m.ciphertext)
m.raw = x
return x
@@ -482,14 +655,14 @@ func (m *clientKeyExchangeMsg) marshal() []byte {
func (m *clientKeyExchangeMsg) unmarshal(data []byte) bool {
m.raw = data
- if len(data) < 7 {
+ if len(data) < 4 {
return false
}
- cipherTextLen := int(data[4])<<8 | int(data[5])
- if len(data) != 6+cipherTextLen {
+ l := int(data[1])<<16 | int(data[2])<<8 | int(data[3])
+ if l != len(data)-4 {
return false
}
- m.ciphertext = data[6:]
+ m.ciphertext = data[4:]
return true
}
@@ -579,3 +752,153 @@ func (m *nextProtoMsg) unmarshal(data []byte) bool {
return true
}
+
+type certificateRequestMsg struct {
+ raw []byte
+ certificateTypes []byte
+ certificateAuthorities [][]byte
+}
+
+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
+ for _, ca := range m.certificateAuthorities {
+ length += 2 + len(ca)
+ }
+
+ 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):]
+
+ numCA := len(m.certificateAuthorities)
+ y[0] = uint8(numCA >> 8)
+ y[1] = uint8(numCA)
+ 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 len(data) < 2 {
+ return false
+ }
+
+ numCAs := uint16(data[0])<<16 | uint16(data[1])
+ data = data[2:]
+
+ m.certificateAuthorities = make([][]byte, numCAs)
+ for i := uint16(0); i < numCAs; i++ {
+ if len(data) < 2 {
+ return false
+ }
+ caLen := uint16(data[0])<<16 | uint16(data[1])
+
+ data = data[2:]
+ if len(data) < int(caLen) {
+ return false
+ }
+
+ ca := make([]byte, caLen)
+ copy(ca, data)
+ m.certificateAuthorities[i] = ca
+ data = data[caLen:]
+ }
+
+ if len(data) > 0 {
+ return false
+ }
+
+ return true
+}
+
+type certificateVerifyMsg struct {
+ raw []byte
+ signature []byte
+}
+
+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
+ x = make([]byte, 4+length)
+ x[0] = typeCertificateVerify
+ x[1] = uint8(length >> 16)
+ x[2] = uint8(length >> 8)
+ x[3] = uint8(length)
+ x[4] = uint8(siglength >> 8)
+ x[5] = uint8(siglength)
+ copy(x[6:], 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
+ }
+
+ siglength := int(data[4])<<8 + int(data[5])
+ if len(data)-6 != siglength {
+ return false
+ }
+
+ m.signature = data[6:]
+
+ return true
+}