github.com/gopacket/gopacket@v1.1.0/layers/eapol.go (about)

     1  // Copyright 2012 Google, Inc. 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  	"fmt"
    12  
    13  	"github.com/gopacket/gopacket"
    14  )
    15  
    16  // EAPOL defines an EAP over LAN (802.1x) layer.
    17  type EAPOL struct {
    18  	BaseLayer
    19  	Version uint8
    20  	Type    EAPOLType
    21  	Length  uint16
    22  }
    23  
    24  // LayerType returns LayerTypeEAPOL.
    25  func (e *EAPOL) LayerType() gopacket.LayerType { return LayerTypeEAPOL }
    26  
    27  // DecodeFromBytes decodes the given bytes into this layer.
    28  func (e *EAPOL) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
    29  	if len(data) < 4 {
    30  		df.SetTruncated()
    31  		return fmt.Errorf("EAPOL length %d too short", len(data))
    32  	}
    33  	e.Version = data[0]
    34  	e.Type = EAPOLType(data[1])
    35  	e.Length = binary.BigEndian.Uint16(data[2:4])
    36  	e.BaseLayer = BaseLayer{data[:4], data[4:]}
    37  	return nil
    38  }
    39  
    40  // SerializeTo writes the serialized form of this layer into the
    41  // SerializationBuffer, implementing gopacket.SerializableLayer
    42  func (e *EAPOL) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
    43  	bytes, _ := b.PrependBytes(4)
    44  	bytes[0] = e.Version
    45  	bytes[1] = byte(e.Type)
    46  	binary.BigEndian.PutUint16(bytes[2:], e.Length)
    47  	return nil
    48  }
    49  
    50  // CanDecode returns the set of layer types that this DecodingLayer can decode.
    51  func (e *EAPOL) CanDecode() gopacket.LayerClass {
    52  	return LayerTypeEAPOL
    53  }
    54  
    55  // NextLayerType returns the layer type contained by this DecodingLayer.
    56  func (e *EAPOL) NextLayerType() gopacket.LayerType {
    57  	return e.Type.LayerType()
    58  }
    59  
    60  func decodeEAPOL(data []byte, p gopacket.PacketBuilder) error {
    61  	e := &EAPOL{}
    62  	return decodingLayerDecoder(e, data, p)
    63  }
    64  
    65  // EAPOLKeyDescriptorType is an enumeration of key descriptor types
    66  // as specified by 802.1x in the EAPOL-Key frame
    67  type EAPOLKeyDescriptorType uint8
    68  
    69  // Enumeration of EAPOLKeyDescriptorType
    70  const (
    71  	EAPOLKeyDescriptorTypeRC4   EAPOLKeyDescriptorType = 1
    72  	EAPOLKeyDescriptorTypeDot11 EAPOLKeyDescriptorType = 2
    73  	EAPOLKeyDescriptorTypeWPA   EAPOLKeyDescriptorType = 254
    74  )
    75  
    76  func (kdt EAPOLKeyDescriptorType) String() string {
    77  	switch kdt {
    78  	case EAPOLKeyDescriptorTypeRC4:
    79  		return "RC4"
    80  	case EAPOLKeyDescriptorTypeDot11:
    81  		return "802.11"
    82  	case EAPOLKeyDescriptorTypeWPA:
    83  		return "WPA"
    84  	default:
    85  		return fmt.Sprintf("unknown descriptor type %d", kdt)
    86  	}
    87  }
    88  
    89  // EAPOLKeyDescriptorVersion is an enumeration of versions specifying the
    90  // encryption algorithm for the key data and the authentication for the
    91  // message integrity code (MIC)
    92  type EAPOLKeyDescriptorVersion uint8
    93  
    94  // Enumeration of EAPOLKeyDescriptorVersion
    95  const (
    96  	EAPOLKeyDescriptorVersionOther       EAPOLKeyDescriptorVersion = 0
    97  	EAPOLKeyDescriptorVersionRC4HMACMD5  EAPOLKeyDescriptorVersion = 1
    98  	EAPOLKeyDescriptorVersionAESHMACSHA1 EAPOLKeyDescriptorVersion = 2
    99  	EAPOLKeyDescriptorVersionAES128CMAC  EAPOLKeyDescriptorVersion = 3
   100  )
   101  
   102  func (v EAPOLKeyDescriptorVersion) String() string {
   103  	switch v {
   104  	case EAPOLKeyDescriptorVersionOther:
   105  		return "Other"
   106  	case EAPOLKeyDescriptorVersionRC4HMACMD5:
   107  		return "RC4-HMAC-MD5"
   108  	case EAPOLKeyDescriptorVersionAESHMACSHA1:
   109  		return "AES-HMAC-SHA1-128"
   110  	case EAPOLKeyDescriptorVersionAES128CMAC:
   111  		return "AES-128-CMAC"
   112  	default:
   113  		return fmt.Sprintf("unknown version %d", v)
   114  	}
   115  }
   116  
   117  // EAPOLKeyType is an enumeration of key derivation types describing
   118  // the purpose of the keys being derived.
   119  type EAPOLKeyType uint8
   120  
   121  // Enumeration of EAPOLKeyType
   122  const (
   123  	EAPOLKeyTypeGroupSMK EAPOLKeyType = 0
   124  	EAPOLKeyTypePairwise EAPOLKeyType = 1
   125  )
   126  
   127  func (kt EAPOLKeyType) String() string {
   128  	switch kt {
   129  	case EAPOLKeyTypeGroupSMK:
   130  		return "Group/SMK"
   131  	case EAPOLKeyTypePairwise:
   132  		return "Pairwise"
   133  	default:
   134  		return fmt.Sprintf("unknown key type %d", kt)
   135  	}
   136  }
   137  
   138  // EAPOLKey defines an EAPOL-Key frame for 802.1x authentication
   139  type EAPOLKey struct {
   140  	BaseLayer
   141  	KeyDescriptorType    EAPOLKeyDescriptorType
   142  	KeyDescriptorVersion EAPOLKeyDescriptorVersion
   143  	KeyType              EAPOLKeyType
   144  	KeyIndex             uint8
   145  	Install              bool
   146  	KeyACK               bool
   147  	KeyMIC               bool
   148  	Secure               bool
   149  	MICError             bool
   150  	Request              bool
   151  	HasEncryptedKeyData  bool
   152  	SMKMessage           bool
   153  	KeyLength            uint16
   154  	ReplayCounter        uint64
   155  	Nonce                []byte
   156  	IV                   []byte
   157  	RSC                  uint64
   158  	ID                   uint64
   159  	MIC                  []byte
   160  	KeyDataLength        uint16
   161  	EncryptedKeyData     []byte
   162  }
   163  
   164  // LayerType returns LayerTypeEAPOLKey.
   165  func (ek *EAPOLKey) LayerType() gopacket.LayerType {
   166  	return LayerTypeEAPOLKey
   167  }
   168  
   169  // CanDecode returns the set of layer types that this DecodingLayer can decode.
   170  func (ek *EAPOLKey) CanDecode() gopacket.LayerType {
   171  	return LayerTypeEAPOLKey
   172  }
   173  
   174  // NextLayerType returns layers.LayerTypeDot11InformationElement if the key
   175  // data exists and is unencrypted, otherwise it does not expect a next layer.
   176  func (ek *EAPOLKey) NextLayerType() gopacket.LayerType {
   177  	if !ek.HasEncryptedKeyData && ek.KeyDataLength > 0 {
   178  		return LayerTypeDot11InformationElement
   179  	}
   180  	return gopacket.LayerTypePayload
   181  }
   182  
   183  const eapolKeyFrameLen = 95
   184  
   185  // DecodeFromBytes decodes the given bytes into this layer.
   186  func (ek *EAPOLKey) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
   187  	if len(data) < eapolKeyFrameLen {
   188  		df.SetTruncated()
   189  		return fmt.Errorf("EAPOLKey length %v too short, %v required",
   190  			len(data), eapolKeyFrameLen)
   191  	}
   192  
   193  	ek.KeyDescriptorType = EAPOLKeyDescriptorType(data[0])
   194  
   195  	info := binary.BigEndian.Uint16(data[1:3])
   196  	ek.KeyDescriptorVersion = EAPOLKeyDescriptorVersion(info & 0x0007)
   197  	ek.KeyType = EAPOLKeyType((info & 0x0008) >> 3)
   198  	ek.KeyIndex = uint8((info & 0x0030) >> 4)
   199  	ek.Install = (info & 0x0040) != 0
   200  	ek.KeyACK = (info & 0x0080) != 0
   201  	ek.KeyMIC = (info & 0x0100) != 0
   202  	ek.Secure = (info & 0x0200) != 0
   203  	ek.MICError = (info & 0x0400) != 0
   204  	ek.Request = (info & 0x0800) != 0
   205  	ek.HasEncryptedKeyData = (info & 0x1000) != 0
   206  	ek.SMKMessage = (info & 0x2000) != 0
   207  
   208  	ek.KeyLength = binary.BigEndian.Uint16(data[3:5])
   209  	ek.ReplayCounter = binary.BigEndian.Uint64(data[5:13])
   210  
   211  	ek.Nonce = data[13:45]
   212  	ek.IV = data[45:61]
   213  	ek.RSC = binary.BigEndian.Uint64(data[61:69])
   214  	ek.ID = binary.BigEndian.Uint64(data[69:77])
   215  	ek.MIC = data[77:93]
   216  
   217  	ek.KeyDataLength = binary.BigEndian.Uint16(data[93:95])
   218  
   219  	totalLength := eapolKeyFrameLen + int(ek.KeyDataLength)
   220  	if len(data) < totalLength {
   221  		df.SetTruncated()
   222  		return fmt.Errorf("EAPOLKey data length %d too short, %d required",
   223  			len(data)-eapolKeyFrameLen, ek.KeyDataLength)
   224  	}
   225  
   226  	if ek.HasEncryptedKeyData {
   227  		ek.EncryptedKeyData = data[eapolKeyFrameLen:totalLength]
   228  		ek.BaseLayer = BaseLayer{
   229  			Contents: data[:totalLength],
   230  			Payload:  data[totalLength:],
   231  		}
   232  	} else {
   233  		ek.BaseLayer = BaseLayer{
   234  			Contents: data[:eapolKeyFrameLen],
   235  			Payload:  data[eapolKeyFrameLen:],
   236  		}
   237  	}
   238  
   239  	return nil
   240  }
   241  
   242  // SerializeTo writes the serialized form of this layer into the
   243  // SerializationBuffer, implementing gopacket.SerializableLayer.
   244  // See the docs for gopacket.SerializableLayer for more info.
   245  func (ek *EAPOLKey) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
   246  	buf, err := b.PrependBytes(eapolKeyFrameLen + len(ek.EncryptedKeyData))
   247  	if err != nil {
   248  		return err
   249  	}
   250  
   251  	buf[0] = byte(ek.KeyDescriptorType)
   252  
   253  	var info uint16
   254  	info |= uint16(ek.KeyDescriptorVersion)
   255  	info |= uint16(ek.KeyType) << 3
   256  	info |= uint16(ek.KeyIndex) << 4
   257  	if ek.Install {
   258  		info |= 0x0040
   259  	}
   260  	if ek.KeyACK {
   261  		info |= 0x0080
   262  	}
   263  	if ek.KeyMIC {
   264  		info |= 0x0100
   265  	}
   266  	if ek.Secure {
   267  		info |= 0x0200
   268  	}
   269  	if ek.MICError {
   270  		info |= 0x0400
   271  	}
   272  	if ek.Request {
   273  		info |= 0x0800
   274  	}
   275  	if ek.HasEncryptedKeyData {
   276  		info |= 0x1000
   277  	}
   278  	if ek.SMKMessage {
   279  		info |= 0x2000
   280  	}
   281  	binary.BigEndian.PutUint16(buf[1:3], info)
   282  
   283  	binary.BigEndian.PutUint16(buf[3:5], ek.KeyLength)
   284  	binary.BigEndian.PutUint64(buf[5:13], ek.ReplayCounter)
   285  
   286  	copy(buf[13:45], ek.Nonce)
   287  	copy(buf[45:61], ek.IV)
   288  	binary.BigEndian.PutUint64(buf[61:69], ek.RSC)
   289  	binary.BigEndian.PutUint64(buf[69:77], ek.ID)
   290  	copy(buf[77:93], ek.MIC)
   291  
   292  	binary.BigEndian.PutUint16(buf[93:95], ek.KeyDataLength)
   293  	if len(ek.EncryptedKeyData) > 0 {
   294  		copy(buf[95:95+len(ek.EncryptedKeyData)], ek.EncryptedKeyData)
   295  	}
   296  
   297  	return nil
   298  }
   299  
   300  func decodeEAPOLKey(data []byte, p gopacket.PacketBuilder) error {
   301  	ek := &EAPOLKey{}
   302  	return decodingLayerDecoder(ek, data, p)
   303  }