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  }