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 }