Index: uspace/lib/ieee80211/include/ieee80211.h
===================================================================
--- uspace/lib/ieee80211/include/ieee80211.h	(revision 59fa7ab26f7b4336f753dcd52b89d6cac0dfca97)
+++ uspace/lib/ieee80211/include/ieee80211.h	(revision d7dadcb4162ebe9a54c5014f67b20ba124ddd307)
@@ -57,4 +57,15 @@
 #define IEEE80211_CHANNEL_GAP 5
 
+/* Max AMPDU factor. */
+#define IEEE80211_MAX_AMPDU_FACTOR 13
+
+/* Max passphrase length in WPA/WPA2 protocols. */
+#define IEEE80211_WPA_MAX_PASSWORD_LENGTH 64
+
+/** IEEE 802.11 b/g supported data rates in units of 500 kb/s. */
+static const uint8_t ieee80211bg_data_rates[] = {
+	2, 4, 11, 12, 18, 22, 24, 36, 48, 72, 96, 108
+};
+
 /** Device operating modes. */
 typedef enum {
@@ -65,4 +76,18 @@
 } ieee80211_operating_mode_t;
 
+/** Key flags. */
+typedef enum {
+	IEEE80211_KEY_FLAG_TYPE_PAIRWISE = 0x01,
+	IEEE80211_KEY_FLAG_TYPE_GROUP = 0x02
+} ieee80211_key_flags_t;
+
+/** Key config structure. */
+typedef struct {
+	uint8_t id;
+	uint8_t flags;
+	ieee80211_security_suite_t suite;
+	uint8_t data[32];
+} ieee80211_key_config_t;
+
 /** IEEE 802.11 callback functions. */
 typedef struct {
@@ -109,4 +134,25 @@
 	 */
 	int (*set_freq)(struct ieee80211_dev *, uint16_t);
+	
+	/**
+	 * Callback to inform device about BSSID change.
+	 * 
+	 * @param ieee80211_dev Pointer to IEEE 802.11 device structure.
+	 * 
+	 * @return EOK if succeed, negative error code otherwise.
+	 */
+	int (*bssid_change)(struct ieee80211_dev *);
+	
+	/**
+	 * Callback to setup encryption key in IEEE 802.11 device.
+	 * 
+	 * @param ieee80211_dev Pointer to IEEE 802.11 device structure.
+	 * @param key_conf Key config structure.
+	 * @param insert True to insert this key to device, false to remove it.
+	 * 
+	 * @return EOK if succeed, negative error code otherwise.
+	 */
+	int (*key_config)(struct ieee80211_dev *, 
+		ieee80211_key_config_t *key_conf, bool);
 } ieee80211_ops_t;
 
@@ -124,10 +170,21 @@
 	void *specific);
 extern ddf_dev_t *ieee80211_get_ddf_dev(ieee80211_dev_t* ieee80211_dev);
-extern ieee80211_operating_mode_t ieee80211_query_current_op_mode(ieee80211_dev_t *ieee80211_dev);
+extern ieee80211_operating_mode_t 
+	ieee80211_query_current_op_mode(ieee80211_dev_t *ieee80211_dev);
 extern uint16_t ieee80211_query_current_freq(ieee80211_dev_t *ieee80211_dev);
+extern void ieee80211_query_bssid(ieee80211_dev_t* ieee80211_dev, 
+	nic_address_t *bssid);
+extern bool ieee80211_is_connected(ieee80211_dev_t* ieee80211_dev);
 extern void ieee80211_report_current_op_mode(ieee80211_dev_t *ieee80211_dev,
 	ieee80211_operating_mode_t op_mode);
 extern void ieee80211_report_current_freq(ieee80211_dev_t *ieee80211_dev,
 	uint16_t freq);
+extern uint16_t ieee80211_get_aid(ieee80211_dev_t* ieee80211_dev);
+extern int ieee80211_get_security_suite(ieee80211_dev_t* ieee80211_dev);
+extern bool ieee80211_is_ready(ieee80211_dev_t* ieee80211_dev);
+extern void ieee80211_set_ready(ieee80211_dev_t* ieee80211_dev, bool ready);
+extern bool ieee80211_query_using_key(ieee80211_dev_t* ieee80211_dev);
+extern void ieee80211_setup_key_confirm(ieee80211_dev_t* ieee80211_dev, 
+	bool using_key);
 
 extern bool ieee80211_is_data_frame(uint16_t frame_ctrl);
@@ -135,4 +192,6 @@
 extern bool ieee80211_is_beacon_frame(uint16_t frame_ctrl);
 extern bool ieee80211_is_probe_response_frame(uint16_t frame_ctrl);
+extern bool ieee80211_is_auth_frame(uint16_t frame_ctrl);
+extern bool ieee80211_is_assoc_response_frame(uint16_t frame_ctrl);
 
 /* Worker functions. */
Index: uspace/lib/ieee80211/include/ieee80211_iface_impl.h
===================================================================
--- uspace/lib/ieee80211/include/ieee80211_iface_impl.h	(revision 59fa7ab26f7b4336f753dcd52b89d6cac0dfca97)
+++ uspace/lib/ieee80211/include/ieee80211_iface_impl.h	(revision d7dadcb4162ebe9a54c5014f67b20ba124ddd307)
@@ -45,6 +45,8 @@
 
 extern int ieee80211_get_scan_results_impl(ddf_fun_t *fun, 
-	ieee80211_scan_results_t *results);
-extern int ieee80211_connect_impl(ddf_fun_t *fun, char *ssid, char *password);
+	ieee80211_scan_results_t *results, bool now);
+extern int ieee80211_connect_impl(ddf_fun_t *fun, char *ssid_start, 
+	char *password);
+extern int ieee80211_disconnect_impl(ddf_fun_t *fun);
 
 #endif	/* LIB_IEEE80211_IFACE_IMPL_H */
Index: uspace/lib/ieee80211/include/ieee80211_impl.h
===================================================================
--- uspace/lib/ieee80211/include/ieee80211_impl.h	(revision 59fa7ab26f7b4336f753dcd52b89d6cac0dfca97)
+++ uspace/lib/ieee80211/include/ieee80211_impl.h	(revision d7dadcb4162ebe9a54c5014f67b20ba124ddd307)
@@ -43,8 +43,19 @@
 
 extern int ieee80211_start_impl(ieee80211_dev_t *ieee80211_dev);
-extern int ieee80211_tx_handler_impl(ieee80211_dev_t *ieee80211_dev, void *buffer, 
-	size_t buffer_size);
-extern int ieee80211_set_freq_impl(ieee80211_dev_t *ieee80211_dev, uint16_t freq);
+extern int ieee80211_tx_handler_impl(ieee80211_dev_t *ieee80211_dev, 
+	void *buffer, size_t buffer_size);
+extern int ieee80211_set_freq_impl(ieee80211_dev_t *ieee80211_dev, 
+	uint16_t freq);
+extern int ieee80211_bssid_change_impl(ieee80211_dev_t *ieee80211_dev);
+extern int ieee80211_key_config_impl(ieee80211_dev_t *ieee80211_dev,
+	ieee80211_key_config_t *key_conf, bool insert);
 extern int ieee80211_scan_impl(ieee80211_dev_t *ieee80211_dev);
+extern int ieee80211_prf(uint8_t *key, uint8_t *data, uint8_t *hash, 
+	hash_func_t hash_sel);
+extern int ieee80211_aes_key_unwrap(uint8_t *kek, uint8_t *data, 
+	size_t data_size, uint8_t *output);
+extern int rnd_sequence(uint8_t *sequence, size_t length);
+extern uint8_t *min_sequence(uint8_t *seq1, uint8_t *seq2, size_t size);
+extern uint8_t *max_sequence(uint8_t *seq1, uint8_t *seq2, size_t size);
 
 #endif	/* LIB_IEEE80211_IMPL_H */
Index: uspace/lib/ieee80211/include/ieee80211_private.h
===================================================================
--- uspace/lib/ieee80211/include/ieee80211_private.h	(revision 59fa7ab26f7b4336f753dcd52b89d6cac0dfca97)
+++ uspace/lib/ieee80211/include/ieee80211_private.h	(revision d7dadcb4162ebe9a54c5014f67b20ba124ddd307)
@@ -40,4 +40,5 @@
 #define LIBNET_IEEE80211_PRIVATE_H
 
+#include <fibril_synch.h>
 #include <byteorder.h>
 #include <ddf/driver.h>
@@ -46,4 +47,61 @@
 #include <ieee80211/ieee80211.h>
 #include "ieee80211.h"
+
+/* Timeout in us for waiting to authentication/association response. */
+#define AUTH_TIMEOUT 200000
+
+/* Timeout in us for waiting to finish 4-way handshake process. */
+#define HANDSHAKE_TIMEOUT 3000000
+
+/* Max period to rerun scan. */
+#define MAX_SCAN_SPAN_SEC 30
+
+/* Max time to keep scan result. */
+#define MAX_KEEP_SCAN_SPAN_SEC 120
+
+/* Security bit in capability info field. */
+#define CAP_SECURITY 0x10
+
+/* Protocol type used in EAPOL frames. */
+#define ETH_TYPE_PAE 0x888E
+
+/* WPA OUI used in vendor specific IE. */
+#define WPA_OUI 0x0050F201
+
+/* GTK OUI used in vendor specific IE. */
+#define GTK_OUI 0x000FAC01
+
+/* Max PTK key length. */
+#define MAX_PTK_LENGTH 64
+
+/* Max GTK key length. */
+#define MAX_GTK_LENGTH 64
+
+/* KEK offset inside PTK. */
+#define KEK_OFFSET 16
+
+/* TK offset inside PTK. */
+#define TK_OFFSET 32
+
+/* Length of CCMP header we need to reserve. */
+#define IEEE80211_CCMP_HEADER_LENGTH 8
+
+/* 
+ * Length of data to be encrypted by PRF function:
+ * NONCE + SNONCE (2 * 32) + DEST_MAC + SOURCE_MAC (2 * ETH_ADDR) 
+ */
+#define PRF_CRYPT_DATA_LENGTH 2*32 + 2*ETH_ADDR
+
+/** IEEE 802.11 PTK key length. */
+typedef enum {
+	IEEE80211_PTK_CCMP_LENGTH = 48,
+	IEEE80211_PTK_TKIP_LENGTH = 64
+} ieee80211_ptk_length_t;
+
+/** IEEE 802.11 GTK key length. */
+typedef enum {
+	IEEE80211_GTK_CCMP_LENGTH = 16,
+	IEEE80211_GTK_TKIP_LENGTH = 32
+} ieee80211_gtk_length_t;
 
 /** IEEE 802.11 frame types. */
@@ -55,5 +113,5 @@
 } ieee80211_frame_type_t;
 
-/** IEEE 802.11 frame subtypes. */
+/** IEEE 802.11 management frame subtypes. */
 typedef enum {
 	IEEE80211_MGMT_ASSOC_REQ_FRAME = 0x00,
@@ -64,8 +122,14 @@
 	IEEE80211_MGMT_PROBE_RESP_FRAME = 0x50,
 	IEEE80211_MGMT_BEACON_FRAME = 0x80,
-	IEEE80211_MGMT_DIASSOC_FRAME = 0xA0,
+	IEEE80211_MGMT_DISASSOC_FRAME = 0xA0,
 	IEEE80211_MGMT_AUTH_FRAME = 0xB0,
 	IEEE80211_MGMT_DEAUTH_FRAME = 0xC0,
-} ieee80211_frame_subtype_t;
+} ieee80211_frame_mgmt_subtype_t;
+
+/** IEEE 802.11 data frame subtypes. */
+typedef enum {
+	IEEE80211_DATA_DATA_FRAME = 0x0000,
+	IEEE80211_DATA_QOS_FRAME = 0x0080
+} ieee80211_frame_data_subtype_t;
 
 /** IEEE 802.11 frame control value masks. */
@@ -73,5 +137,38 @@
 	IEEE80211_FRAME_CTRL_FRAME_TYPE = 0x000C,
 	IEEE80211_FRAME_CTRL_FRAME_SUBTYPE = 0x00F0,
-} ieee80211_frame_control_mask_t;
+	IEEE80211_FRAME_CTRL_PROTECTED = 0x4000
+} ieee80211_frame_ctrl_mask_t;
+
+/** IEEE 802.11 frame control DS field values. */
+typedef enum {
+	IEEE80211_FRAME_CTRL_TODS = 0x0100,
+	IEEE80211_FRAME_CTRL_FROMDS = 0x0200
+} ieee80211_frame_ctrl_ds_t;
+
+/** IEEE 802.11 authentication cipher suites values. */
+typedef enum {
+	IEEE80211_AUTH_CIPHER_TKIP = 0x02,
+	IEEE80211_AUTH_CIPHER_CCMP = 0x04
+} ieee80211_auth_cipher_type_t;
+
+/** IEEE 802.11 AKM suites values. */
+typedef enum {
+	IEEE80211_AUTH_AKM_8021X = 0x01,
+	IEEE80211_AUTH_AKM_PSK = 0x02
+} ieee80211_auth_akm_type_t;
+
+typedef enum {
+	IEEE80211_EAPOL_START = 0x1,
+	IEEE80211_EAPOL_KEY = 0x3
+} ieee80211_eapol_frame_type_t;
+
+typedef enum {
+	IEEE80211_EAPOL_KEY_KEYINFO_KEYTYPE = 0x0008,
+	IEEE80211_EAPOL_KEY_KEYINFO_INSTALL = 0x0040,
+	IEEE80211_EAPOL_KEY_KEYINFO_ACK = 0x0080,
+	IEEE80211_EAPOL_KEY_KEYINFO_MIC = 0x0100,
+	IEEE80211_EAPOL_KEY_KEYINFO_SECURE = 0x0200,
+	IEEE80211_EAPOL_KEY_KEYINFO_ENCDATA = 0x1000
+} ieee80211_eapol_key_keyinfo_t;
 
 /** IEEE 802.11 information element types. */
@@ -80,6 +177,42 @@
 	IEEE80211_RATES_IE = 1,		/**< Supported data rates. */
 	IEEE80211_CHANNEL_IE = 3,	/**< Current channel number. */
-	IEEE80211_EXT_RATES_IE = 50	/**< Extended data rates. */
+	IEEE80211_CHALLENGE_IE = 16,	/**< Challenge text. */
+	IEEE80211_RSN_IE = 48,		/**< RSN. */
+	IEEE80211_EXT_RATES_IE = 50,	/**< Extended data rates. */
+	IEEE80211_VENDOR_IE = 221	/**< Vendor specific IE. */
 } ieee80211_ie_type_t;
+
+/** IEEE 802.11 authentication phases. */
+typedef enum {
+	IEEE80211_AUTH_DISCONNECTED,
+	IEEE80211_AUTH_AUTHENTICATED,
+	IEEE80211_AUTH_ASSOCIATED
+} ieee80211_auth_phase_t;
+
+/** Link with scan result info. */
+typedef struct {
+	link_t link;
+	time_t last_beacon;
+	ieee80211_scan_result_t scan_result;
+	uint8_t rsn_copy[256];
+	size_t rsn_copy_len;
+} ieee80211_scan_result_link_t;
+
+/** List of scan results info. */
+typedef struct {
+	list_t list;
+	time_t last_scan;
+	fibril_mutex_t scan_mutex;
+	size_t size;
+} ieee80211_scan_result_list_t;
+
+/** BSSID info. */
+typedef struct {
+	uint16_t aid;
+	char password[IEEE80211_WPA_MAX_PASSWORD_LENGTH];
+	uint8_t ptk[MAX_PTK_LENGTH];
+	uint8_t gtk[MAX_GTK_LENGTH];
+	ieee80211_scan_result_link_t *res_link;
+} ieee80211_bssid_info_t;
 
 /** IEEE 802.11 WiFi device structure. */
@@ -103,16 +236,45 @@
 	ieee80211_operating_mode_t current_op_mode;
 	
+	/** Info about BSSID we are connected to. */
+	ieee80211_bssid_info_t bssid_info;
+	
+	/** 
+	 * Flag indicating that data traffic is encrypted by HW key
+	 * that is set up in device. 
+	 */
+	bool using_hw_key;
+	
 	/** BSSIDs we listen to. */
 	nic_address_t bssid_mask;
 	
 	/** List of APs in neighborhood. */
-	ieee80211_scan_results_t ap_list;
-	
-	/* TODO: Probably to be removed later - nic.open function is now 
-	 * executed multiple times, have to find out reason and fix it. 
-	 */
+	ieee80211_scan_result_list_t ap_list;
+	
+	/** Current sequence number used in data frames. */
+	uint16_t sequence_number;
+	
+	/** Current authentication phase. */
+	ieee80211_auth_phase_t current_auth_phase;
+	
+	/** General purpose guard. */
+	fibril_mutex_t gen_mutex;
+	
+	/** General purpose condition variable. */
+	fibril_condvar_t gen_cond;
+	
+	/** Indicates whether device is fully initialized. */
+	bool ready;
+	
 	/** Indicates whether driver has already started. */
 	bool started;
 };
+
+/** IEEE 802.3 (ethernet) header. */
+typedef struct {
+	uint8_t dest_addr[ETH_ADDR];
+	uint8_t src_addr[ETH_ADDR];
+	uint16_t proto;			/**< Big Endian value! */
+} __attribute__((packed)) __attribute__ ((aligned(2))) 
+	eth_header_t;
 
 /** IEEE 802.11 management header structure. */
@@ -124,5 +286,6 @@
 	uint8_t bssid[ETH_ADDR];
 	uint16_t seq_ctrl;		/**< Little Endian value! */
-} __attribute__((packed)) __attribute__ ((aligned(2))) ieee80211_mgmt_header_t;
+} __attribute__((packed)) __attribute__ ((aligned(2))) 
+	ieee80211_mgmt_header_t;
 
 /** IEEE 802.11 data header structure. */
@@ -134,7 +297,6 @@
 	uint8_t address3[ETH_ADDR];
 	uint16_t seq_ctrl;		/**< Little Endian value! */
-	uint8_t address4[ETH_ADDR];
-	uint16_t qos_ctrl;		/**< Little Endian value! */
-} __attribute__((packed)) __attribute__ ((aligned(2))) ieee80211_data_header_t;
+} __attribute__((packed)) __attribute__ ((aligned(2))) 
+	ieee80211_data_header_t;
 
 /** IEEE 802.11 information element header. */
@@ -142,5 +304,6 @@
 	uint8_t element_id;
 	uint8_t length;
-} __attribute__((packed)) __attribute__ ((aligned(2))) ieee80211_ie_header_t;
+} __attribute__((packed)) __attribute__ ((aligned(2))) 
+	ieee80211_ie_header_t;
 
 /** IEEE 802.11 authentication frame body. */
@@ -149,15 +312,85 @@
 	uint16_t auth_trans_no;		/**< Little Endian value! */
 	uint16_t status;		/**< Little Endian value! */
-} __attribute__((packed)) __attribute__ ((aligned(2))) ieee80211_auth_body_t;
+} __attribute__((packed)) __attribute__ ((aligned(2))) 
+	ieee80211_auth_body_t;
+
+/** IEEE 802.11 deauthentication frame body. */
+typedef struct {
+	uint16_t reason;		/**< Little Endian value! */
+} __attribute__((packed)) __attribute__ ((aligned(2))) 
+	ieee80211_deauth_body_t;
+
+/** IEEE 802.11 association request frame body. */
+typedef struct {
+	uint16_t capability;		/**< Little Endian value! */
+	uint16_t listen_interval;	/**< Little Endian value! */
+} __attribute__((packed)) __attribute__ ((aligned(2))) 
+	ieee80211_assoc_req_body_t;
+
+/** IEEE 802.11 association response frame body. */
+typedef struct {
+	uint16_t capability;		/**< Little Endian value! */
+	uint16_t status;		/**< Little Endian value! */
+	uint16_t aid;			/**< Little Endian value! */
+} __attribute__((packed)) __attribute__ ((aligned(2))) 
+	ieee80211_assoc_resp_body_t;
 
 /** IEEE 802.11 beacon frame body start. */
 typedef struct {
 	uint8_t timestamp[8];
-	uint16_t beacon_interval;
-	uint16_t capability;
-} __attribute__((packed)) __attribute__ ((aligned(2))) ieee80211_beacon_start_t;
-
-extern int ieee80211_probe_request(ieee80211_dev_t *ieee80211_dev);
-extern int ieee80211_probe_auth(ieee80211_dev_t *ieee80211_dev);
+	uint16_t beacon_interval;	/**< Little Endian value! */
+	uint16_t capability;		/**< Little Endian value! */
+} __attribute__((packed)) __attribute__ ((aligned(2))) 
+	ieee80211_beacon_start_t;
+
+/** IEEE 802.11i EAPOL-Key frame format. */
+typedef struct {
+	uint8_t proto_version;
+	uint8_t packet_type;
+	uint16_t body_length;		/**< Big Endian value! */
+	uint8_t descriptor_type;
+	uint16_t key_info;		/**< Big Endian value! */
+	uint16_t key_length;		/**< Big Endian value! */
+	uint8_t key_replay_counter[8];
+	uint8_t key_nonce[32];
+	uint8_t eapol_key_iv[16];
+	uint8_t key_rsc[8];
+	uint8_t reserved[8];
+	uint8_t key_mic[16];
+	uint16_t key_data_length;	/**< Big Endian value! */
+} __attribute__((packed)) ieee80211_eapol_key_frame_t;
+
+#define ieee80211_scan_result_list_foreach(results, iter) \
+    list_foreach((results).list, link, ieee80211_scan_result_link_t, (iter))
+
+static inline void ieee80211_scan_result_list_init(
+	ieee80211_scan_result_list_t *results) 
+{
+	list_initialize(&results->list);
+	fibril_mutex_initialize(&results->scan_mutex);
+}
+
+static inline void ieee80211_scan_result_list_remove(
+	ieee80211_scan_result_list_t *results,
+	ieee80211_scan_result_link_t *result)
+{
+	list_remove(&result->link);
+	results->size--;
+}
+
+static inline void ieee80211_scan_result_list_append(
+	ieee80211_scan_result_list_t *results,
+	ieee80211_scan_result_link_t *result)
+{
+	list_append(&result->link, &results->list);
+	results->size++;
+}
+
+extern int ieee80211_probe_request(ieee80211_dev_t *ieee80211_dev, 
+	char *ssid);
+extern int ieee80211_authenticate(ieee80211_dev_t *ieee80211_dev);
+extern int ieee80211_associate(ieee80211_dev_t *ieee80211_dev, 
+	char *password);
+extern int ieee80211_deauthenticate(ieee80211_dev_t *ieee80211_dev);
 
 #endif /* LIBN_IEEE80211_H */
