#ifndef __WPA_IMPL_H
#define __WPA_IMPL_H
#include <net/wpa.h>
#include <libdladm.h>
#include <libdllink.h>
#ifdef __cplusplus
extern "C" {
#endif
#define BIT(n) (1 << (n))
#define WPA_CIPHER_NONE BIT(0)
#define WPA_CIPHER_WEP40 BIT(1)
#define WPA_CIPHER_WEP104 BIT(2)
#define WPA_CIPHER_TKIP BIT(3)
#define WPA_CIPHER_CCMP BIT(4)
#define WPA_KEY_MGMT_IEEE8021X BIT(0)
#define WPA_KEY_MGMT_PSK BIT(1)
#define WPA_KEY_MGMT_NONE BIT(2)
#define WPA_KEY_MGMT_IEEE8021X_NO_WPA BIT(3)
#define WPA_PROTO_WPA BIT(0)
#define WPA_PROTO_RSN BIT(1)
#pragma pack(1)
struct ieee802_1x_hdr {
uint8_t version;
uint8_t type;
uint16_t length;
};
#pragma pack()
#define EAPOL_VERSION 2
enum { IEEE802_1X_TYPE_EAP_PACKET = 0,
IEEE802_1X_TYPE_EAPOL_START = 1,
IEEE802_1X_TYPE_EAPOL_LOGOFF = 2,
IEEE802_1X_TYPE_EAPOL_KEY = 3,
IEEE802_1X_TYPE_EAPOL_ENCAPSULATED_ASF_ALERT = 4
};
enum { EAPOL_KEY_TYPE_RC4 = 1,
EAPOL_KEY_TYPE_RSN = 2,
EAPOL_KEY_TYPE_WPA = 254
};
#define WPA_NONCE_LEN 32
#define WPA_REPLAY_COUNTER_LEN 8
#define MAX_PSK_LENGTH 64
#define WPA_PMK_LEN 32
#pragma pack(1)
struct wpa_eapol_key {
uint8_t type;
uint16_t key_info;
uint16_t key_length;
uint8_t replay_counter[WPA_REPLAY_COUNTER_LEN];
uint8_t key_nonce[WPA_NONCE_LEN];
uint8_t key_iv[16];
uint8_t key_rsc[8];
uint8_t key_id[8];
uint8_t key_mic[16];
uint16_t key_data_length;
};
#pragma pack()
#define WPA_KEY_INFO_TYPE_MASK (BIT(0) | BIT(1) | BIT(2))
#define WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 BIT(0)
#define WPA_KEY_INFO_TYPE_HMAC_SHA1_AES BIT(1)
#define WPA_KEY_INFO_KEY_TYPE BIT(3)
#define WPA_KEY_INFO_KEY_INDEX_MASK (BIT(4) | BIT(5))
#define WPA_KEY_INFO_KEY_INDEX_SHIFT 4
#define WPA_KEY_INFO_INSTALL BIT(6)
#define WPA_KEY_INFO_TXRX BIT(6)
#define WPA_KEY_INFO_ACK BIT(7)
#define WPA_KEY_INFO_MIC BIT(8)
#define WPA_KEY_INFO_SECURE BIT(9)
#define WPA_KEY_INFO_ERROR BIT(10)
#define WPA_KEY_INFO_REQUEST BIT(11)
#define WPA_KEY_INFO_ENCR_KEY_DATA BIT(12)
#define WPA_CAPABILITY_PREAUTH BIT(0)
#define GENERIC_INFO_ELEM 0xdd
#define RSN_INFO_ELEM 0x30
#define MAX_LOGBUF 4096
#define MAX_SCANRESULTS 64
enum {
REASON_UNSPECIFIED = 1,
REASON_DEAUTH_LEAVING = 3,
REASON_INVALID_IE = 13,
REASON_MICHAEL_MIC_FAILURE = 14,
REASON_4WAY_HANDSHAKE_TIMEOUT = 15,
REASON_GROUP_KEY_UPDATE_TIMEOUT = 16,
REASON_IE_IN_4WAY_DIFFERS = 17,
REASON_GROUP_CIPHER_NOT_VALID = 18,
REASON_PAIRWISE_CIPHER_NOT_VALID = 19,
REASON_AKMP_NOT_VALID = 20,
REASON_UNSUPPORTED_RSN_IE_VERSION = 21,
REASON_INVALID_RSN_IE_CAPAB = 22,
REASON_IEEE_802_1X_AUTH_FAILED = 23,
REASON_CIPHER_SUITE_REJECTED = 24
};
#define PMKID_LEN 16
#define PMK_LEN 32
#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
struct rsn_pmksa_cache {
struct rsn_pmksa_cache *next;
uint8_t pmkid[PMKID_LEN];
uint8_t pmk[PMK_LEN];
time_t expiration;
int akmp;
uint8_t aa[IEEE80211_ADDR_LEN];
};
struct rsn_pmksa_candidate {
struct rsn_pmksa_candidate *next;
uint8_t bssid[IEEE80211_ADDR_LEN];
};
#pragma pack(1)
struct wpa_ptk {
uint8_t mic_key[16];
uint8_t encr_key[16];
uint8_t tk1[16];
union {
uint8_t tk2[16];
struct {
uint8_t tx_mic_key[8];
uint8_t rx_mic_key[8];
} auth;
} u;
};
#pragma pack()
struct wpa_supplicant {
struct l2_packet_data *l2;
unsigned char own_addr[IEEE80211_ADDR_LEN];
dladm_handle_t handle;
datalink_id_t linkid;
char kname[DLADM_SECOBJ_NAME_MAX];
uint8_t pmk[PMK_LEN];
uint8_t snonce[WPA_NONCE_LEN];
uint8_t anonce[WPA_NONCE_LEN];
struct wpa_ptk ptk, tptk;
int ptk_set, tptk_set;
int renew_snonce;
struct wpa_config *conf;
uint8_t request_counter[WPA_REPLAY_COUNTER_LEN];
uint8_t rx_replay_counter[WPA_REPLAY_COUNTER_LEN];
int rx_replay_counter_set;
uint8_t bssid[IEEE80211_ADDR_LEN];
int reassociate;
uint8_t *ap_wpa_ie;
size_t ap_wpa_ie_len;
int proto;
int pairwise_cipher;
int group_cipher;
int key_mgmt;
struct wpa_driver_ops *driver;
enum {
WPA_DISCONNECTED,
WPA_SCANNING,
WPA_ASSOCIATING,
WPA_ASSOCIATED,
WPA_4WAY_HANDSHAKE,
WPA_GROUP_HANDSHAKE,
WPA_COMPLETED
} wpa_state;
struct rsn_pmksa_cache *pmksa;
int pmksa_count;
struct rsn_pmksa_cache *cur_pmksa;
struct rsn_pmksa_candidate *pmksa_candidates;
int eapol_received;
};
struct wpa_ie_data {
int proto;
int pairwise_cipher;
int group_cipher;
int key_mgmt;
int capabilities;
};
struct wpa_ssid {
uint8_t *ssid;
size_t ssid_len;
uint8_t bssid[IEEE80211_ADDR_LEN];
int bssid_set;
uint8_t psk[PMK_LEN];
int psk_set;
char *passphrase;
int pairwise_cipher;
int group_cipher;
int key_mgmt;
int proto;
};
struct wpa_config {
struct wpa_ssid *ssid;
int eapol_version;
};
struct wpa_config *wpa_config_read(void *);
void wpa_config_free(struct wpa_config *);
enum { MSG_MSGDUMP, MSG_DEBUG, MSG_INFO, MSG_WARNING, MSG_ERROR };
void wpa_printf(int, char *, ...);
void wpa_hexdump(int, const char *, const uint8_t *, size_t);
void wpa_event_handler(void *, wpa_event_type);
void wpa_supplicant_rx_eapol(void *, unsigned char *, unsigned char *, size_t);
void wpa_supplicant_scan(void *, void *);
void wpa_supplicant_req_scan(struct wpa_supplicant *, int, int);
void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *, int, int);
void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *);
void wpa_supplicant_disassociate(struct wpa_supplicant *, int);
void pmksa_cache_free(struct wpa_supplicant *);
void pmksa_candidate_free(struct wpa_supplicant *);
struct rsn_pmksa_cache *pmksa_cache_get(struct wpa_supplicant *,
uint8_t *, uint8_t *);
int wpa_parse_wpa_ie(struct wpa_supplicant *, uint8_t *,
size_t, struct wpa_ie_data *);
int wpa_gen_wpa_ie(struct wpa_supplicant *, uint8_t *);
#ifdef __cplusplus
}
#endif
#endif