/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi>
* Sun elects to license this software under the BSD license.
* See README for more details.
*/
#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;
/* followed by length octets of data */
};
#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]; /* Reserved in IEEE 802.11i/RSN */
uint8_t key_mic[16];
uint16_t key_data_length;
/* followed by key_data_length bytes of key_data */
};
#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) /* 1: Pairwise, 0: Group key */
/* bit4..5 is used in WPA, but is reserved in IEEE 802.11i/RSN */
#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) /* pairwise */
#define WPA_KEY_INFO_TXRX BIT(6) /* group */
#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) /* IEEE 802.11i/RSN only */
#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
};
/*
* wpa_supplicant
*/
#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; /* WPA_KEY_MGMT_* */
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]; /* EAPOL-Key MIC Key (MK) */
uint8_t encr_key[16]; /* EAPOL-Key Encryption Key (EK) */
uint8_t tk1[16]; /* Temporal Key 1 (TK1) */
union {
uint8_t tk2[16]; /* Temporal Key 2 (TK2) */
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];
/* The handle required for libdladm calls */
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];
/* ANonce from the last 1/4 msg */
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; /* reassociation requested */
uint8_t *ap_wpa_ie;
size_t ap_wpa_ie_len;
/*
* Selected configuration
* based on Beacon/ProbeResp WPA IE
*/
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; /* PMKSA cache */
int pmksa_count; /* number of entries in PMKSA cache */
struct rsn_pmksa_cache *cur_pmksa; /* current PMKSA entry */
struct rsn_pmksa_candidate *pmksa_candidates;
/*
* number of EAPOL packets received after the
* previous association event
*/
int eapol_received;
};
struct wpa_ie_data {
int proto;
int pairwise_cipher;
int group_cipher;
int key_mgmt;
int capabilities;
};
/* WPA configuration */
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;
/* Bitfields of allowed Pairwise/Group Ciphers, WPA_CIPHER_* */
int pairwise_cipher;
int group_cipher;
int key_mgmt;
int proto; /* Bitfield of allowed protocols (WPA_PROTO_*) */
};
struct wpa_config {
struct wpa_ssid *ssid; /* global network list */
int eapol_version;
/* int ap_scan; */
};
struct wpa_config *wpa_config_read(void *);
void wpa_config_free(struct wpa_config *);
/*
* Debugging function - conditional printf and hex dump.
* Driver wrappers can use these for debugging purposes.
*/
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 /* __WPA_IMPL_H */