shadowTLS/shadow/tls_util.go

110 lines
2.4 KiB
Go

package shadow
import (
"encoding/binary"
)
const (
RecordHeaderLen = 5
ChangeCipherSpec = 0x14
EncryptedAlert = 0x15
Handshake = 0x16
AppData = 0x17
VersionTLS10 = 0x0301
VersionTLS11 = 0x0302
VersionTLS12 = 0x0303
VersionTLS13 = 0x0304
ServerHello = 2
ClientHello = 1
Certificate = 11
ServerKeyExchange = 12
ServerHelloDone = 14
EncryptedHandshake = 99
)
type TLSHeader struct {
Type uint8
Version uint16
Length int
HandshakeType uint8
ChangeCipherSpecNext uint8
Rand []byte
}
func (t *TLSHeader) toString() string {
if t == nil {
return "nul"
}
desc := ""
switch t.Type {
case Handshake:
desc += "Type=handshake;"
switch t.HandshakeType {
case ClientHello:
desc += "HandshakeType=ClientHello;"
break
case ServerHello:
desc += "HandshakeType=ServerHello;"
break
}
break
case ChangeCipherSpec:
desc += "Type=ChangeCipherSpec;"
switch t.ChangeCipherSpecNext {
case Handshake:
desc += "ChangeCipherSpecNext=Handshake;"
break
case AppData:
desc += "ChangeCipherSpecNext=AppData;"
break
}
break
case EncryptedAlert:
desc += "Type=EncryptedAlert;"
break
case AppData:
desc += "Type=AppData;"
break
}
return desc
}
func ParseAndVerifyTLSHeader(data []byte) *TLSHeader {
if len(data) < RecordHeaderLen {
return nil
}
header := &TLSHeader{
Type: data[0],
Version: binary.BigEndian.Uint16(data[1:3]),
Length: int(binary.BigEndian.Uint16(data[3:5])),
}
//Check type
if header.Type != Handshake && header.Type != AppData && header.Type != EncryptedAlert && header.Type != ChangeCipherSpec {
return nil
}
//Check version
if header.Version != VersionTLS10 && header.Version != VersionTLS11 && header.Version != VersionTLS12 && header.Version != VersionTLS13 {
return nil
}
if header.Type == Handshake {
header.HandshakeType = data[5]
//Check Handshake type
if header.HandshakeType != ServerHello && header.HandshakeType != ClientHello && header.HandshakeType != Certificate && header.HandshakeType != ServerKeyExchange && header.HandshakeType != ServerHelloDone {
header.HandshakeType = EncryptedHandshake
}
if header.HandshakeType == ClientHello {
header.Rand = data[11:43]
}
}
if header.Type == ChangeCipherSpec {
if len(data) > 6 {
header.ChangeCipherSpecNext = data[6]
}
}
return header
}