github.com/gopacket/gopacket@v1.1.0/layers/tls_handshake.go (about) 1 // Copyright 2018 The GoPacket Authors. All rights reserved. 2 // 3 // Use of this source code is governed by a BSD-style license 4 // that can be found in the LICENSE file in the root of the source 5 // tree. 6 7 package layers 8 9 import ( 10 "encoding/binary" 11 "errors" 12 "fmt" 13 14 "github.com/gopacket/gopacket" 15 ) 16 17 /*refer to https://datatracker.ietf.org/doc/html/rfc5246#appendix-A.4*/ 18 const ( 19 TLSHandshakeHelloRequest = 0 20 TLSHandshakeClientHello = 1 21 TLSHandshakeServerHello = 2 22 TLSHandsharkHelloVerirfyRequest = 3 23 TLSHandshakeCertificate = 11 24 TLSHandshakeServerKeyExchange = 12 25 TLSHandshakeCertificateRequest = 13 26 TLSHandshakeServerHelloDone = 14 27 TLSHandshakeCertificateVerify = 15 28 TLSHandshakeClientKeyExchange = 16 29 TLSHandshakeFinished = 20 30 ) 31 32 var handShakeTypeMap = map[uint8]string{ 33 TLSHandshakeHelloRequest: "Hello Request", 34 TLSHandshakeClientHello: "Client Hello", 35 TLSHandshakeServerHello: "Server Hello", 36 TLSHandsharkHelloVerirfyRequest: "Hello Verify Request", 37 TLSHandshakeCertificate: "Certificate", 38 TLSHandshakeServerKeyExchange: "Server Key Exchange", 39 TLSHandshakeCertificateRequest: "Certificate Request", 40 TLSHandshakeServerHelloDone: "Server Hello Done", 41 TLSHandshakeCertificateVerify: "Certificate Verify", 42 TLSHandshakeClientKeyExchange: "Client Key Exchange", 43 TLSHandshakeFinished: "Finished", 44 } 45 46 type TLSHandshakeRecordClientHello struct { 47 HandshakeType uint8 48 Length uint32 49 ProtocolVersion TLSVersion 50 Random []uint8 51 SessionIDLength uint8 52 SessionID []uint8 53 CipherSuitsLength uint16 54 CipherSuits []uint8 55 CompressionMethodsLength uint8 56 CompressionMethods []uint8 57 ExtensionsLength uint16 58 Extensions []uint8 59 } 60 61 type TLSHandshakeRecordClientKeyChange struct { 62 } 63 64 // TLSHandshakeRecord defines the structure of a Handshare Record 65 type TLSHandshakeRecord struct { 66 TLSRecordHeader 67 ClientHello TLSHandshakeRecordClientHello 68 ClientKeyChange TLSHandshakeRecordClientKeyChange 69 } 70 71 func (t *TLSHandshakeRecordClientHello) decodeFromBytes(data []byte, df gopacket.DecodeFeedback) error { 72 t.HandshakeType = data[0] 73 d := make([]byte, 4) 74 for k, v := range data[1:4] { 75 d[k+1] = v 76 } 77 t.Length = binary.BigEndian.Uint32(d) 78 t.ProtocolVersion = TLSVersion(binary.BigEndian.Uint16(data[4:6])) 79 t.Random = data[6:38] 80 t.SessionIDLength = data[38] 81 t.SessionID = data[39 : 39+t.SessionIDLength] 82 t.CipherSuitsLength = binary.BigEndian.Uint16(data[39+t.SessionIDLength : 39+t.SessionIDLength+2]) 83 t.CipherSuits = data[39+t.SessionIDLength+2 : (39 + uint16(t.SessionIDLength) + 2 + t.CipherSuitsLength)] 84 t.CompressionMethodsLength = data[(39 + uint16(t.SessionIDLength) + 2 + t.CipherSuitsLength)] 85 t.CompressionMethods = data[(39+uint16(t.SessionIDLength)+2+t.CipherSuitsLength)+1 : (39+uint16(t.SessionIDLength)+2+t.CipherSuitsLength)+1+uint16(t.CompressionMethodsLength)] 86 t.ExtensionsLength = binary.BigEndian.Uint16(data[(39+uint16(t.SessionIDLength)+2+t.CipherSuitsLength)+1+uint16(t.CompressionMethodsLength) : (39+uint16(t.SessionIDLength)+2+t.CipherSuitsLength)+1+uint16(t.CompressionMethodsLength)+2]) 87 t.Extensions = data[((39 + uint16(t.SessionIDLength) + 2 + t.CipherSuitsLength) + 1 + uint16(t.CompressionMethodsLength) + 2) : ((39+uint16(t.SessionIDLength)+2+t.CipherSuitsLength)+1+uint16(t.CompressionMethodsLength)+2)+t.ExtensionsLength] 88 return nil 89 } 90 func (t *TLSHandshakeRecordClientKeyChange) decodeFromBytes(data []byte, df gopacket.DecodeFeedback) error { 91 /*TBD*/ 92 return nil 93 } 94 95 /** 96 * Checks whether a handshake message seems encrypted and cannot be dissected. 97 */ 98 func (t TLSHandshakeRecord) isEncryptedHandshakeMessage(h TLSRecordHeader, data []byte) bool { 99 if h.Length < 16 { 100 /* 101 * Encrypted data has additional overhead. For TLS 1.0/1.1 with stream 102 * and block ciphers, there is at least a MAC which is at minimum 16 103 * bytes for MD5. In TLS 1.2, AEAD adds an explicit nonce and auth tag. 104 * For AES-GCM/CCM the auth tag is 16 bytes. AES_CCM_8 (RFC 6655) uses 8 105 * byte auth tags, but the explicit nonce is also 8 (sums up to 16). 106 * 107 * So anything smaller than 16 bytes is assumed to be plaintext. 108 */ 109 return false 110 } 111 maybeType := data[0] 112 d := make([]byte, 4) 113 for k, v := range data[1:4] { 114 d[k+1] = v 115 } 116 if uint32(h.Length)-binary.BigEndian.Uint32(d) != 4 { 117 return true 118 } 119 if _, ok := handShakeTypeMap[maybeType]; !ok { 120 return true 121 } 122 return false 123 } 124 125 // DecodeFromBytes decodes the slice into the TLS struct. 126 func (t *TLSHandshakeRecord) decodeFromBytes(h TLSRecordHeader, data []byte, df gopacket.DecodeFeedback) error { 127 // TLS Record Header 128 t.ContentType = h.ContentType 129 t.Version = h.Version 130 t.Length = h.Length 131 132 if t.isEncryptedHandshakeMessage(h, data) { 133 fmt.Printf("encrypted message\n") 134 return nil 135 } 136 handshakeType := data[0] 137 switch handshakeType { 138 case TLSHandshakeClientHello: 139 t.ClientHello.decodeFromBytes(data, df) 140 case TLSHandshakeClientKeyExchange: 141 t.ClientKeyChange.decodeFromBytes(data, df) 142 default: 143 return errors.New("Unknown TLS handshake type") 144 // TODO 145 } 146 147 return nil 148 }