github.com/gopacket/gopacket@v1.1.0/layers/tls.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  
    13  	"github.com/gopacket/gopacket"
    14  )
    15  
    16  // TLSType defines the type of data after the TLS Record
    17  type TLSType uint8
    18  
    19  // TLSType known values.
    20  const (
    21  	TLSChangeCipherSpec TLSType = 20
    22  	TLSAlert            TLSType = 21
    23  	TLSHandshake        TLSType = 22
    24  	TLSApplicationData  TLSType = 23
    25  	TLSUnknown          TLSType = 255
    26  )
    27  
    28  // String shows the register type nicely formatted
    29  func (tt TLSType) String() string {
    30  	switch tt {
    31  	default:
    32  		return "Unknown"
    33  	case TLSChangeCipherSpec:
    34  		return "Change Cipher Spec"
    35  	case TLSAlert:
    36  		return "Alert"
    37  	case TLSHandshake:
    38  		return "Handshake"
    39  	case TLSApplicationData:
    40  		return "Application Data"
    41  	}
    42  }
    43  
    44  // TLSVersion represents the TLS version in numeric format
    45  type TLSVersion uint16
    46  
    47  // Strings shows the TLS version nicely formatted
    48  func (tv TLSVersion) String() string {
    49  	switch tv {
    50  	default:
    51  		return "Unknown"
    52  	case 0x0200:
    53  		return "SSL 2.0"
    54  	case 0x0300:
    55  		return "SSL 3.0"
    56  	case 0x0301:
    57  		return "TLS 1.0"
    58  	case 0x0302:
    59  		return "TLS 1.1"
    60  	case 0x0303:
    61  		return "TLS 1.2"
    62  	case 0x0304:
    63  		return "TLS 1.3"
    64  	}
    65  }
    66  
    67  // TLS is specified in RFC 5246
    68  //
    69  //  TLS Record Protocol
    70  //  0  1  2  3  4  5  6  7  8
    71  //  +--+--+--+--+--+--+--+--+
    72  //  |     Content Type      |
    73  //  +--+--+--+--+--+--+--+--+
    74  //  |    Version (major)    |
    75  //  +--+--+--+--+--+--+--+--+
    76  //  |    Version (minor)    |
    77  //  +--+--+--+--+--+--+--+--+
    78  //  |        Length         |
    79  //  +--+--+--+--+--+--+--+--+
    80  //  |        Length         |
    81  //  +--+--+--+--+--+--+--+--+
    82  
    83  // TLS is actually a slide of TLSrecord structures
    84  type TLS struct {
    85  	BaseLayer
    86  
    87  	// TLS Records
    88  	ChangeCipherSpec []TLSChangeCipherSpecRecord
    89  	Handshake        []TLSHandshakeRecord
    90  	AppData          []TLSAppDataRecord
    91  	Alert            []TLSAlertRecord
    92  }
    93  
    94  // TLSRecordHeader contains all the information that each TLS Record types should have
    95  type TLSRecordHeader struct {
    96  	ContentType TLSType
    97  	Version     TLSVersion
    98  	Length      uint16
    99  }
   100  
   101  // LayerType returns gopacket.LayerTypeTLS.
   102  func (t *TLS) LayerType() gopacket.LayerType { return LayerTypeTLS }
   103  
   104  // decodeTLS decodes the byte slice into a TLS type. It also
   105  // setups the application Layer in PacketBuilder.
   106  func decodeTLS(data []byte, p gopacket.PacketBuilder) error {
   107  	t := &TLS{}
   108  	err := t.DecodeFromBytes(data, p)
   109  	if err != nil {
   110  		return err
   111  	}
   112  	p.AddLayer(t)
   113  	p.SetApplicationLayer(t)
   114  	return nil
   115  }
   116  
   117  // DecodeFromBytes decodes the slice into the TLS struct.
   118  func (t *TLS) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
   119  	t.BaseLayer.Contents = data
   120  	t.BaseLayer.Payload = nil
   121  
   122  	t.ChangeCipherSpec = t.ChangeCipherSpec[:0]
   123  	t.Handshake = t.Handshake[:0]
   124  	t.AppData = t.AppData[:0]
   125  	t.Alert = t.Alert[:0]
   126  
   127  	return t.decodeTLSRecords(data, df)
   128  }
   129  
   130  func (t *TLS) decodeTLSRecords(data []byte, df gopacket.DecodeFeedback) error {
   131  	if len(data) < 5 {
   132  		df.SetTruncated()
   133  		return errors.New("TLS record too short")
   134  	}
   135  
   136  	// since there are no further layers, the baselayer's content is
   137  	// pointing to this layer
   138  	// TODO: Consider removing this
   139  	t.BaseLayer = BaseLayer{Contents: data[:len(data)]}
   140  
   141  	var h TLSRecordHeader
   142  	h.ContentType = TLSType(data[0])
   143  	h.Version = TLSVersion(binary.BigEndian.Uint16(data[1:3]))
   144  	h.Length = binary.BigEndian.Uint16(data[3:5])
   145  
   146  	if h.ContentType.String() == "Unknown" {
   147  		return errors.New("Unknown TLS record type")
   148  	}
   149  
   150  	hl := 5 // header length
   151  	tl := hl + int(h.Length)
   152  	if len(data) < tl {
   153  		df.SetTruncated()
   154  		return errors.New("TLS packet length mismatch")
   155  	}
   156  
   157  	switch h.ContentType {
   158  	default:
   159  		return errors.New("Unknown TLS record type")
   160  	case TLSChangeCipherSpec:
   161  		var r TLSChangeCipherSpecRecord
   162  		e := r.decodeFromBytes(h, data[hl:tl], df)
   163  		if e != nil {
   164  			return e
   165  		}
   166  		t.ChangeCipherSpec = append(t.ChangeCipherSpec, r)
   167  	case TLSAlert:
   168  		var r TLSAlertRecord
   169  		e := r.decodeFromBytes(h, data[hl:tl], df)
   170  		if e != nil {
   171  			return e
   172  		}
   173  		t.Alert = append(t.Alert, r)
   174  	case TLSHandshake:
   175  		var r TLSHandshakeRecord
   176  		e := r.decodeFromBytes(h, data[hl:tl], df)
   177  		if e != nil {
   178  			return e
   179  		}
   180  		t.Handshake = append(t.Handshake, r)
   181  	case TLSApplicationData:
   182  		var r TLSAppDataRecord
   183  		e := r.decodeFromBytes(h, data[hl:tl], df)
   184  		if e != nil {
   185  			return e
   186  		}
   187  		t.AppData = append(t.AppData, r)
   188  	}
   189  
   190  	if len(data) == tl {
   191  		return nil
   192  	}
   193  	return t.decodeTLSRecords(data[tl:len(data)], df)
   194  }
   195  
   196  // CanDecode implements gopacket.DecodingLayer.
   197  func (t *TLS) CanDecode() gopacket.LayerClass {
   198  	return LayerTypeTLS
   199  }
   200  
   201  // NextLayerType implements gopacket.DecodingLayer.
   202  func (t *TLS) NextLayerType() gopacket.LayerType {
   203  	return gopacket.LayerTypeZero
   204  }
   205  
   206  // Payload returns nil, since TLS encrypted payload is inside TLSAppDataRecord
   207  func (t *TLS) Payload() []byte {
   208  	return nil
   209  }
   210  
   211  // SerializeTo writes the serialized form of this layer into the
   212  // SerializationBuffer, implementing gopacket.SerializableLayer.
   213  func (t *TLS) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
   214  	totalLength := 0
   215  	for _, record := range t.ChangeCipherSpec {
   216  		if opts.FixLengths {
   217  			record.Length = 1
   218  		}
   219  		totalLength += 5 + 1 // length of header + record
   220  	}
   221  	for range t.Handshake {
   222  		totalLength += 5
   223  		// TODO
   224  	}
   225  	for _, record := range t.AppData {
   226  		if opts.FixLengths {
   227  			record.Length = uint16(len(record.Payload))
   228  		}
   229  		totalLength += 5 + len(record.Payload)
   230  	}
   231  	for _, record := range t.Alert {
   232  		if len(record.EncryptedMsg) == 0 {
   233  			if opts.FixLengths {
   234  				record.Length = 2
   235  			}
   236  			totalLength += 5 + 2
   237  		} else {
   238  			if opts.FixLengths {
   239  				record.Length = uint16(len(record.EncryptedMsg))
   240  			}
   241  			totalLength += 5 + len(record.EncryptedMsg)
   242  		}
   243  	}
   244  	data, err := b.PrependBytes(totalLength)
   245  	if err != nil {
   246  		return err
   247  	}
   248  	off := 0
   249  	for _, record := range t.ChangeCipherSpec {
   250  		off = encodeHeader(record.TLSRecordHeader, data, off)
   251  		data[off] = byte(record.Message)
   252  		off++
   253  	}
   254  	for _, record := range t.Handshake {
   255  		off = encodeHeader(record.TLSRecordHeader, data, off)
   256  		// TODO
   257  	}
   258  	for _, record := range t.AppData {
   259  		off = encodeHeader(record.TLSRecordHeader, data, off)
   260  		copy(data[off:], record.Payload)
   261  		off += len(record.Payload)
   262  	}
   263  	for _, record := range t.Alert {
   264  		off = encodeHeader(record.TLSRecordHeader, data, off)
   265  		if len(record.EncryptedMsg) == 0 {
   266  			data[off] = byte(record.Level)
   267  			data[off+1] = byte(record.Description)
   268  			off += 2
   269  		} else {
   270  			copy(data[off:], record.EncryptedMsg)
   271  			off += len(record.EncryptedMsg)
   272  		}
   273  	}
   274  	return nil
   275  }
   276  
   277  func encodeHeader(header TLSRecordHeader, data []byte, offset int) int {
   278  	data[offset] = byte(header.ContentType)
   279  	binary.BigEndian.PutUint16(data[offset+1:], uint16(header.Version))
   280  	binary.BigEndian.PutUint16(data[offset+3:], header.Length)
   281  
   282  	return offset + 5
   283  }