wireshark/epan/crypt/dot11decrypt_system.h
Mikael Kanstrup 9cf77ec5e1 ieee80211: Support decrypting WPA3-Personal / SAE captures
Add support for decrypting IEEE 802.11 WPA3-Personal / SAE traffic.

SAE uses AES encryption but a different key derivation function (KDF)
making Wireshark fail to decrypt such captures. Also both KDF and
decryption method is determined based only on EAPOL key description
version. This is not enough to figure out that SAE is being used.

Implement the alternative KDF needed to derive valid PTK. Also
implement a function to parse pairwise + group cipher suites and
auth key management type from RSNE tag. Using this new function
together with a number of new cipher and AKM lookup functions
correct KDF for SAE can be selected.

Bug: 15621
Change-Id: I8f6c917af1c9642c276a244943dd35f850ee3757
Reviewed-on: https://code.wireshark.org/review/32485
Petri-Dish: Anders Broman <a.broman58@gmail.com>
Tested-by: Petri Dish Buildbot
Reviewed-by: Anders Broman <a.broman58@gmail.com>
2019-03-21 12:13:58 +00:00

330 lines
12 KiB
C

/* dot11decrypt_system.h
*
* Copyright (c) 2006 CACE Technologies, Davis (California)
* All rights reserved.
*
* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0-only)
*/
#ifndef _DOT11DECRYPT_SYSTEM_H
#define _DOT11DECRYPT_SYSTEM_H
/************************************************************************/
/* Constant definitions */
/* General definitions */
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#define DOT11DECRYPT_RET_SUCCESS 0
#define DOT11DECRYPT_RET_UNSUCCESS 1
#define DOT11DECRYPT_RET_NO_DATA 1
#define DOT11DECRYPT_RET_WRONG_DATA_SIZE 2
#define DOT11DECRYPT_RET_REQ_DATA 3
#define DOT11DECRYPT_RET_NO_VALID_HANDSHAKE 4
#define DOT11DECRYPT_RET_NO_DATA_ENCRYPTED 5
#define DOT11DECRYPT_RET_SUCCESS_HANDSHAKE -1
#define DOT11DECRYPT_MAX_KEYS_NR 64
#define DOT11DECRYPT_MAX_SEC_ASSOCIATIONS_NR 256
/* Decryption algorithms fields size definition (bytes) */
#define DOT11DECRYPT_WPA_NONCE_LEN 32
#define DOT11DECRYPT_WPA_PTK_LEN 64 /* TKIP uses 48 bytes, CCMP uses 64 bytes */
#define DOT11DECRYPT_WPA_MICKEY_LEN 16
#define DOT11DECRYPT_WEP_128_KEY_LEN 16 /* 128 bits */
/* General 802.11 constants */
#define DOT11DECRYPT_MAC_LEN 6
#define DOT11DECRYPT_RADIOTAP_HEADER_LEN 24
#define DOT11DECRYPT_EAPOL_MAX_LEN 1024U
#define DOT11DECRYPT_TK_LEN 16
/* Max length of capture data */
#define DOT11DECRYPT_MAX_CAPLEN 8192
#define DOT11DECRYPT_WEP_IVLEN 3 /* 24bit */
#define DOT11DECRYPT_WEP_KIDLEN 1 /* 1 octet */
#define DOT11DECRYPT_WEP_ICV 4
#define DOT11DECRYPT_WEP_HEADER DOT11DECRYPT_WEP_IVLEN + DOT11DECRYPT_WEP_KIDLEN
#define DOT11DECRYPT_WEP_TRAILER DOT11DECRYPT_WEP_ICV
/*
* 802.11i defines an extended IV for use with non-WEP ciphers.
* When the EXTIV bit is set in the key id byte an additional
* 4 bytes immediately follow the IV for TKIP. For CCMP the
* EXTIV bit is likewise set but the 8 bytes represent the
* CCMP header rather than IV+extended-IV.
*/
#define DOT11DECRYPT_RSNA_EXTIV 0x20
#define DOT11DECRYPT_RSNA_EXTIVLEN 4 /* extended IV length */
#define DOT11DECRYPT_RSNA_MICLEN 8 /* trailing MIC */
#define DOT11DECRYPT_RSNA_HEADER DOT11DECRYPT_WEP_HEADER + DOT11DECRYPT_RSNA_EXTIVLEN
#define DOT11DECRYPT_CCMP_HEADER DOT11DECRYPT_RSNA_HEADER
#define DOT11DECRYPT_CCMP_TRAILER DOT11DECRYPT_RSNA_MICLEN
#define DOT11DECRYPT_TKIP_HEADER DOT11DECRYPT_RSNA_HEADER
#define DOT11DECRYPT_TKIP_TRAILER DOT11DECRYPT_RSNA_MICLEN + DOT11DECRYPT_WEP_ICV
#define DOT11DECRYPT_CRC_LEN 4
/************************************************************************/
/* File includes */
#include "dot11decrypt_interop.h"
#include "dot11decrypt_user.h"
#include "ws_symbol_export.h"
/************************************************************************/
/* Macro definitions */
/************************************************************************/
/* Type definitions */
typedef struct _DOT11DECRYPT_SEC_ASSOCIATION_ID {
UCHAR bssid[DOT11DECRYPT_MAC_LEN];
UCHAR sta[DOT11DECRYPT_MAC_LEN];
} DOT11DECRYPT_SEC_ASSOCIATION_ID, *PDOT11DECRYPT_SEC_ASSOCIATION_ID;
typedef struct _DOT11DECRYPT_SEC_ASSOCIATION {
/* This is for reassociations. A linked list of old security
* associations is kept. GCS
*/
struct _DOT11DECRYPT_SEC_ASSOCIATION* next;
/**
* This flag define whether this item is used or not. Accepted
* values are TRUE and FALSE
*/
UINT8 used;
DOT11DECRYPT_SEC_ASSOCIATION_ID saId;
DOT11DECRYPT_KEY_ITEM *key;
UINT8 handshake;
UINT8 validKey;
struct {
UINT8 key_ver; /* Key descriptor version */
UINT64 pn; /* only used with CCMP AES -if needed replay check- */
UCHAR nonce[DOT11DECRYPT_WPA_NONCE_LEN];
/* used to derive PTK, ANonce stored, SNonce taken */
/* the 2nd packet of the 4W handshake */
INT akm;
INT cipher;
UCHAR ptk[DOT11DECRYPT_WPA_PTK_LEN]; /* session key used in decryption algorithm */
} wpa;
} DOT11DECRYPT_SEC_ASSOCIATION, *PDOT11DECRYPT_SEC_ASSOCIATION;
typedef struct _DOT11DECRYPT_CONTEXT {
DOT11DECRYPT_SEC_ASSOCIATION sa[DOT11DECRYPT_MAX_SEC_ASSOCIATIONS_NR];
INT sa_index;
DOT11DECRYPT_KEY_ITEM keys[DOT11DECRYPT_MAX_KEYS_NR];
size_t keys_nr;
CHAR pkt_ssid[DOT11DECRYPT_WPA_SSID_MAX_LEN];
size_t pkt_ssid_len;
INT index;
INT first_free_index;
} DOT11DECRYPT_CONTEXT, *PDOT11DECRYPT_CONTEXT;
/************************************************************************/
/* Function prototype declarations */
#ifdef __cplusplus
extern "C" {
#endif
/**
* This will try to decrypt a 802.11 frame. If scanHandshake is
* true it will also check if it's a cleartext or encrypted eapol key
* frame which can be used to setup TK or GTK decryption keys.
* @param ctx [IN] Pointer to the current context
* @param data [IN] Pointer to a buffer with an 802.11 frame, including MAC
* header and payload
* @param data_off [IN] Payload offset (aka the MAC header length)
* @param data_len [IN] Total length of the MAC header and the payload
* @param decrypt_data [OUT] Pointer to a buffer that will contain
* decrypted data. Must have room for at least DOT11DECRYPT_MAX_CAPLEN bytes.
* @param decrypt_len [OUT] Length of decrypted data.
* @param key [OUT] Pointer to a preallocated key structure containing
* the key used during the decryption process (if done). If this parameter
* is set to NULL, the key will be not returned.
* @param scanHandshake [IN] If TRUE this function will additional check if
* the 802.11 frame data is pointing to has key information and if so use
* it to setup potential decryption keys. Enables handshake return codes.
* @return
* - DOT11DECRYPT_RET_SUCCESS: Decryption has been done (decrypt_data and
* decrypt_length will contain the packet data decrypted and the length of
* the new packet)
* - DOT11DECRYPT_RET_NO_DATA: The packet is not a data packet
* - DOT11DECRYPT_RET_WRONG_DATA_SIZE: The size of the packet is below the
* accepted minimum
* - DOT11DECRYPT_RET_REQ_DATA: Required data is not available and the
* processing must be interrupted (can also occur after decryption when
* scanHandshake is TRUE)
* - DOT11DECRYPT_RET_NO_DATA_ENCRYPTED: Not encrypted and no attempt to
* extract key information
* - DOT11DECRYPT_RET_UNSUCCESS: Generic unspecified error (decrypt_data
* and decrypt_length will be not modified).
* - DOT11DECRYPT_RET_SUCCESS_HANDSHAKE: An eapol handshake packet was successfuly parsed
* and key information extracted. The decrypted eapol keydata is copied to
* decrypt_data with keydata len in decrypt_len. key param will contain ptk
* used to decrypt eapol keydata.
* - DOT11DECRYPT_RET_NO_VALID_HANDSHAKE: The handshake is invalid or was not used
* for some reason. For encrypted packets decryption was still successful.
* @note
* The decrypted buffer should be allocated for a size equal or greater
* than the packet data buffer size. Before decryption process original
* data is copied in the buffer pointed by decrypt_data not to modify the
* original packet.
* @note
* The length of decrypted data will consider the entire 802.11 frame
* (thus the MAC header, the frame body and the recalculated FCS -if
* initially present-)
* @note
* This function is not thread-safe when used in parallel with context
* management functions on the same context.
*/
extern INT Dot11DecryptPacketProcess(
PDOT11DECRYPT_CONTEXT ctx,
const guint8 *data,
const guint data_off,
const guint data_len,
UCHAR *decrypt_data,
guint32 *decrypt_len,
PDOT11DECRYPT_KEY_ITEM key,
gboolean scanHandshake)
;
/**
* It sets a new keys collection to use during packet processing.
* Any key should be well-formed, thus: it should have a defined key
* type and the specified length should be conforming WEP or WPA/WPA2
* standards. A general WEP keys could be of any length (in the range
* defined in DOT11DECRYPT_KEY_ITEM), if a specific WEP key is used, the
* length of the key will be the one specified in 802.11i-2004 (40 bits or
* 104 bits).
* For WPA/WPA2 the password (passphrase and SSID), the PSK and the PMK
* are in alternative, as explain in the DOT11DECRYPT_KEY_ITEM structure
* description.
* @param ctx [IN] pointer to the current context
* @param keys [IN] an array of keys to set.
* @param keys_nr [IN] the size of the keys array
* @return The number of keys correctly inserted in the current database.
* @note Before inserting new keys, the current database will be cleaned.
* @note
* This function is not thread-safe when used in parallel with context
* management functions and the packet process function on the same
* context.
*/
extern INT Dot11DecryptSetKeys(
PDOT11DECRYPT_CONTEXT ctx,
DOT11DECRYPT_KEY_ITEM keys[],
const size_t keys_nr)
;
/**
* It gets the keys collection fom the specified context.
* @param ctx [IN] pointer to the current context
* @param keys [IN] a preallocated array of keys to be returned
* @param keys_nr [IN] the number of keys to return (the key array must
* be able to contain at least keys_nr keys)
* @return The number of keys returned
* @note
* Any key could be modified, as stated in the DOT11DECRYPT_KEY_ITEM description.
* @note
* This function is not thread-safe when used in parallel with context
* management functions and the packet process function on the same
* context.
*/
INT Dot11DecryptGetKeys(
const PDOT11DECRYPT_CONTEXT ctx,
DOT11DECRYPT_KEY_ITEM keys[],
const size_t keys_nr)
;
/**
* Sets the "last seen" SSID. This allows us to pick up previous
* SSIDs and use them when "wildcard" passphrases are specified
* in the preferences.
* @param ctx [IN|OUT] pointer to a preallocated context structure
* @param pkt_ssid [IN] pointer to the packet's SSID
* @param pkt_ssid_len [IN] length of the packet's SSID
* @return
* DOT11DECRYPT_RET_SUCCESS: The key has been set.
* DOT11DECRYPT_RET_UNSUCCESS: The has not been set, e.g. the length was
* too long.
*/
INT Dot11DecryptSetLastSSID(
PDOT11DECRYPT_CONTEXT ctx,
CHAR *pkt_ssid,
size_t pkt_ssid_len)
;
/**
* Initialize a context used to manage decryption and keys collection.
* @param ctx [IN|OUT] pointer to a preallocated context structure
* @return
* DOT11DECRYPT_RET_SUCCESS: the context has been successfully initialized
* DOT11DECRYPT_RET_UNSUCCESS: the context has not been initialized
* @note
* Only a correctly initialized context can be used to manage decryption
* processes and keys.
* @note
* This function is not thread-safe when used in parallel with context
* management functions and the packet process function on the same context.
*/
WS_DLL_PUBLIC
INT Dot11DecryptInitContext(
PDOT11DECRYPT_CONTEXT ctx)
;
/**
* Clean up the specified context. After the cleanup the pointer should
* not be used anymore.
* @param ctx [IN|OUT] pointer to the current context structure
* @return
* DOT11DECRYPT_RET_SUCCESS: the context has been successfully initialized
* DOT11DECRYPT_RET_UNSUCCESS: the context has not been initialized
* @note
* This function is not thread-safe when used in parallel with context
* management functions and the packet process function on the same
* context.
*/
WS_DLL_PUBLIC
INT Dot11DecryptDestroyContext(
PDOT11DECRYPT_CONTEXT ctx)
;
extern INT Dot11DecryptCcmpDecrypt(
UINT8 *m,
gint mac_header_len,
INT len,
UCHAR TK1[16])
;
extern INT Dot11DecryptTkipDecrypt(
UCHAR *tkip_mpdu,
size_t mpdu_len,
UCHAR TA[DOT11DECRYPT_MAC_LEN],
UCHAR TK[DOT11DECRYPT_TK_LEN])
;
#ifdef __cplusplus
}
#endif
#endif /* _DOT11DECRYPT_SYSTEM_H */