[Midnightbsd-cvs] src: contrib/wpa_supplicant: merge changes

laffer1 at midnightbsd.org laffer1 at midnightbsd.org
Wed Nov 19 17:46:44 EST 2008


Log Message:
-----------
merge changes

Modified Files:
--------------
    src/contrib/wpa_supplicant:
        ChangeLog (r1.2 -> r1.3)
        FREEBSD-Xlist (r1.2 -> r1.3)
        Makefile (r1.2 -> r1.3)
        README (r1.2 -> r1.3)
        aes.c (r1.2 -> r1.3)
        aes_wrap.c (r1.2 -> r1.3)
        aes_wrap.h (r1.2 -> r1.3)
        base64.c (r1.1 -> r1.2)
        base64.h (r1.1 -> r1.2)
        common.c (r1.2 -> r1.3)
        common.h (r1.2 -> r1.3)
        config.c (r1.2 -> r1.3)
        config.h (r1.2 -> r1.3)
        config_file.c (r1.1 -> r1.2)
        config_ssid.h (r1.2 -> r1.3)
        config_types.h (r1.1 -> r1.2)
        crypto.c (r1.2 -> r1.3)
        crypto.h (r1.2 -> r1.3)
        crypto_gnutls.c (r1.1 -> r1.2)
        ctrl_iface.c (r1.2 -> r1.3)
        ctrl_iface.h (r1.2 -> r1.3)
        defconfig (r1.2 -> r1.3)
        defs.h (r1.2 -> r1.3)
        driver.h (r1.2 -> r1.3)
        driver_hostap.h (r1.1 -> r1.2)
        driver_ndis.c (r1.2 -> r1.3)
        driver_ndis.h (r1.2 -> r1.3)
        driver_wired.c (r1.1 -> r1.2)
        drivers.c (r1.2 -> r1.3)
        eap.c (r1.2 -> r1.3)
        eap.h (r1.2 -> r1.3)
        eap_aka.c (r1.2 -> r1.3)
        eap_defs.h (r1.2 -> r1.3)
        eap_fast.c (r1.2 -> r1.3)
        eap_gtc.c (r1.2 -> r1.3)
        eap_i.h (r1.2 -> r1.3)
        eap_leap.c (r1.2 -> r1.3)
        eap_md5.c (r1.2 -> r1.3)
        eap_mschapv2.c (r1.2 -> r1.3)
        eap_otp.c (r1.2 -> r1.3)
        eap_pax.c (r1.1 -> r1.2)
        eap_pax_common.c (r1.1 -> r1.2)
        eap_pax_common.h (r1.1 -> r1.2)
        eap_peap.c (r1.2 -> r1.3)
        eap_psk.c (r1.2 -> r1.3)
        eap_psk_common.c (r1.1 -> r1.2)
        eap_psk_common.h (r1.1 -> r1.2)
        eap_sim.c (r1.2 -> r1.3)
        eap_sim_common.c (r1.2 -> r1.3)
        eap_sim_common.h (r1.2 -> r1.3)
        eap_testing.txt (r1.2 -> r1.3)
        eap_tls.c (r1.2 -> r1.3)
        eap_tls_common.c (r1.2 -> r1.3)
        eap_tls_common.h (r1.2 -> r1.3)
        eap_tlv.c (r1.2 -> r1.3)
        eap_tlv.h (r1.2 -> r1.3)
        eap_ttls.c (r1.2 -> r1.3)
        eap_ttls.h (r1.2 -> r1.3)
        eapol_sm.c (r1.2 -> r1.3)
        eapol_sm.h (r1.2 -> r1.3)
        eapol_test.c (r1.2 -> r1.3)
        eloop.c (r1.2 -> r1.3)
        eloop.h (r1.2 -> r1.3)
        events.c (r1.1 -> r1.2)
        hostapd.h (r1.1 -> r1.2)
        l2_packet.h (r1.2 -> r1.3)
        main.c (r1.1 -> r1.2)
        md5.c (r1.2 -> r1.3)
        md5.h (r1.2 -> r1.3)
        ms_funcs.c (r1.2 -> r1.3)
        ms_funcs.h (r1.2 -> r1.3)
        pcsc_funcs.c (r1.2 -> r1.3)
        pcsc_funcs.h (r1.2 -> r1.3)
        preauth.c (r1.1 -> r1.2)
        preauth.h (r1.1 -> r1.2)
        preauth_test.c (r1.2 -> r1.3)
        radius.c (r1.2 -> r1.3)
        radius.h (r1.2 -> r1.3)
        radius_client.c (r1.2 -> r1.3)
        radius_client.h (r1.2 -> r1.3)
        rc4.c (r1.2 -> r1.3)
        rc4.h (r1.2 -> r1.3)
        sha1.c (r1.2 -> r1.3)
        sha1.h (r1.2 -> r1.3)
        tls.h (r1.2 -> r1.3)
        tls_gnutls.c (r1.1 -> r1.2)
        tls_none.c (r1.2 -> r1.3)
        tls_openssl.c (r1.2 -> r1.3)
        tls_schannel.c (r1.1 -> r1.2)
        todo.txt (r1.2 -> r1.3)
        version.h (r1.2 -> r1.3)
        wpa.c (r1.2 -> r1.3)
        wpa.h (r1.2 -> r1.3)
        wpa_cli.c (r1.2 -> r1.3)
        wpa_ctrl.c (r1.2 -> r1.3)
        wpa_ctrl.h (r1.2 -> r1.3)
        wpa_i.h (r1.1 -> r1.2)
        wpa_passphrase.c (r1.2 -> r1.3)
        wpa_supplicant.c (r1.2 -> r1.3)
        wpa_supplicant.conf (r1.2 -> r1.3)
        wpa_supplicant.h (r1.2 -> r1.3)
        wpa_supplicant_i.h (r1.2 -> r1.3)
    src/contrib/wpa_supplicant/doc:
        code_structure.doxygen (r1.1 -> r1.2)
        ctrl_iface.doxygen (r1.1 -> r1.2)
        doxygen.fast (r1.1 -> r1.2)
        doxygen.full (r1.1 -> r1.2)
        eap.doxygen (r1.1 -> r1.2)
        kerneldoc2doxygen.pl (r1.1 -> r1.2)
        mainpage.doxygen (r1.1 -> r1.2)
        porting.doxygen (r1.1 -> r1.2)
        testing_tools.doxygen (r1.1 -> r1.2)
    src/contrib/wpa_supplicant/doc/docbook:
        wpa_background.8 (r1.1 -> r1.2)
        wpa_background.sgml (r1.1 -> r1.2)
        wpa_cli.8 (r1.1 -> r1.2)
        wpa_cli.sgml (r1.1 -> r1.2)
        wpa_passphrase.8 (r1.1 -> r1.2)
        wpa_passphrase.sgml (r1.1 -> r1.2)
        wpa_supplicant.8 (r1.1 -> r1.2)
        wpa_supplicant.conf.5 (r1.1 -> r1.2)
        wpa_supplicant.conf.sgml (r1.1 -> r1.2)
        wpa_supplicant.sgml (r1.1 -> r1.2)

-------------- next part --------------
Index: wpa_i.h
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/wpa_i.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -L contrib/wpa_supplicant/wpa_i.h -L contrib/wpa_supplicant/wpa_i.h -u -r1.1 -r1.2
--- contrib/wpa_supplicant/wpa_i.h
+++ contrib/wpa_supplicant/wpa_i.h
@@ -1,6 +1,6 @@
 /*
  * wpa_supplicant - Internal WPA state machine definitions
- * Copyright (c) 2004-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2004-2006, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -15,12 +15,12 @@
 #ifndef WPA_I_H
 #define WPA_I_H
 
-#define WPA_NONCE_LEN 32
-#define WPA_REPLAY_COUNTER_LEN 8
-
-
 struct rsn_pmksa_candidate;
 
+#ifdef _MSC_VER
+#pragma pack(push, 1)
+#endif /* _MSC_VER */
+
 /**
  * struct wpa_ptk - WPA Pairwise Transient Key
  * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy
@@ -36,24 +36,40 @@
 			u8 rx_mic_key[8];
 		} auth;
 	} u;
-} __attribute__ ((packed));
+} STRUCT_PACKED;
 
+#ifdef _MSC_VER
+#pragma pack(pop)
+#endif /* _MSC_VER */
+
+
+#ifdef CONFIG_PEERKEY
+#define PEERKEY_MAX_IE_LEN 80
+struct wpa_peerkey {
+	struct wpa_peerkey *next;
+	int initiator; /* whether this end was initator for SMK handshake */
+	u8 addr[ETH_ALEN]; /* other end MAC address */
+	u8 inonce[WPA_NONCE_LEN]; /* Initiator Nonce */
+	u8 pnonce[WPA_NONCE_LEN]; /* Peer Nonce */
+	u8 rsnie_i[PEERKEY_MAX_IE_LEN]; /* Initiator RSN IE */
+	size_t rsnie_i_len;
+	u8 rsnie_p[PEERKEY_MAX_IE_LEN]; /* Peer RSN IE */
+	size_t rsnie_p_len;
+	u8 smk[PMK_LEN];
+	int smk_complete;
+	u8 smkid[PMKID_LEN];
+	u32 lifetime;
+	os_time_t expiration;
+	int cipher; /* Selected cipher (WPA_CIPHER_*) */
+	u8 replay_counter[WPA_REPLAY_COUNTER_LEN];
+	int replay_counter_set;
 
-/**
- * struct rsn_pmksa_cache - PMKSA cache entry
- */
-struct rsn_pmksa_cache {
-	struct rsn_pmksa_cache *next;
-	u8 pmkid[PMKID_LEN];
-	u8 pmk[PMK_LEN];
-	size_t pmk_len;
-	time_t expiration;
-	time_t reauth_time;
-	int akmp; /* WPA_KEY_MGMT_* */
-	u8 aa[ETH_ALEN];
-	struct wpa_ssid *ssid;
-	int opportunistic;
+	struct wpa_ptk stk, tstk;
+	int stk_set, tstk_set;
 };
+#else /* CONFIG_PEERKEY */
+struct wpa_peerkey;
+#endif /* CONFIG_PEERKEY */
 
 
 /**
@@ -74,11 +90,11 @@
 	struct eapol_sm *eapol; /* EAPOL state machine from upper level code */
 
 	struct rsn_pmksa_cache *pmksa; /* PMKSA cache */
-	struct rsn_pmksa_cache *cur_pmksa; /* current PMKSA entry */
-	int pmksa_count; /* number of entries in PMKSA cache */
+	struct rsn_pmksa_cache_entry *cur_pmksa; /* current PMKSA entry */
 	struct rsn_pmksa_candidate *pmksa_candidates;
 
 	struct l2_packet_data *l2_preauth;
+	struct l2_packet_data *l2_preauth_br;
 	u8 preauth_bssid[ETH_ALEN]; /* current RSN pre-auth peer or
 				     * 00:00:00:00:00:00 if no pre-auth is
 				     * in progress */
@@ -93,6 +109,7 @@
 
 	u8 own_addr[ETH_ALEN];
 	const char *ifname;
+	const char *bridge_ifname;
 	u8 bssid[ETH_ALEN];
 
 	unsigned int dot11RSNAConfigPMKLifetime;
@@ -106,11 +123,16 @@
 	unsigned int pairwise_cipher;
 	unsigned int group_cipher;
 	unsigned int key_mgmt;
+	unsigned int mgmt_group_cipher;
 
 	u8 *assoc_wpa_ie; /* Own WPA/RSN IE from (Re)AssocReq */
 	size_t assoc_wpa_ie_len;
 	u8 *ap_wpa_ie, *ap_rsn_ie;
 	size_t ap_wpa_ie_len, ap_rsn_ie_len;
+
+#ifdef CONFIG_PEERKEY
+	struct wpa_peerkey *peerkey;
+#endif /* CONFIG_PEERKEY */
 };
 
 
@@ -194,4 +216,11 @@
 	return sm->ctx->remove_pmkid(sm->ctx->ctx, bssid, pmkid);
 }
 
+static inline int wpa_sm_mlme_setprotection(struct wpa_sm *sm, const u8 *addr,
+					    int protect_type, int key_type)
+{
+	return sm->ctx->mlme_setprotection(sm->ctx->ctx, addr, protect_type,
+					   key_type);
+}
+
 #endif /* WPA_I_H */
Index: wpa_cli.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/wpa_cli.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/wpa_cli.c -L contrib/wpa_supplicant/wpa_cli.c -u -r1.2 -r1.3
--- contrib/wpa_supplicant/wpa_cli.c
+++ contrib/wpa_supplicant/wpa_cli.c
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant - command line interface for wpa_supplicant daemon
- * Copyright (c) 2004-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2004-2007, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -12,29 +12,26 @@
  * See README and COPYING for more details.
  */
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <signal.h>
-#include <unistd.h>
+#include "includes.h"
+
+#ifdef CONFIG_CTRL_IFACE
+
+#ifdef CONFIG_CTRL_IFACE_UNIX
 #include <dirent.h>
-#include <errno.h>
-#include <sys/time.h>
+#endif /* CONFIG_CTRL_IFACE_UNIX */
 #ifdef CONFIG_READLINE
 #include <readline/readline.h>
 #include <readline/history.h>
 #endif /* CONFIG_READLINE */
 
 #include "wpa_ctrl.h"
-#ifdef CONFIG_NATIVE_WINDOWS
 #include "common.h"
-#endif /* CONFIG_NATIVE_WINDOWS */
 #include "version.h"
 
 
 static const char *wpa_cli_version =
 "wpa_cli v" VERSION_STR "\n"
-"Copyright (c) 2004-2005, Jouni Malinen <jkmaline at cc.hut.fi> and contributors";
+"Copyright (c) 2004-2007, Jouni Malinen <j at w1.fi> and contributors";
 
 
 static const char *wpa_cli_license =
@@ -56,7 +53,7 @@
 "\n"
 "You should have received a copy of the GNU General Public License\n"
 "along with this program; if not, write to the Free Software\n"
-"Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n"
+"Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n"
 "\n"
 "Alternatively, this software may be distributed under the terms of the\n"
 "BSD license.\n"
@@ -129,12 +126,16 @@
 "  scan_results = get latest scan results\n"
 "  get_capability <eap/pairwise/group/key_mgmt/proto/auth_alg> = "
 "get capabilies\n"
+"  ap_scan <value> = set ap_scan parameter\n"
+"  stkstart <addr> = request STK negotiation with <addr>\n"
 "  terminate = terminate wpa_supplicant\n"
 "  quit = exit wpa_cli\n";
 
 static struct wpa_ctrl *ctrl_conn;
 static int wpa_cli_quit = 0;
 static int wpa_cli_attached = 0;
+static int wpa_cli_connected = 0;
+static int wpa_cli_last_id = 0;
 static const char *ctrl_iface_dir = "/var/run/wpa_supplicant";
 static char *ctrl_ifname = NULL;
 static const char *pid_file = NULL;
@@ -161,26 +162,26 @@
 
 static struct wpa_ctrl * wpa_cli_open_connection(const char *ifname)
 {
-#ifdef CONFIG_CTRL_IFACE_UDP
-	ctrl_conn = wpa_ctrl_open("");
+#if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE)
+	ctrl_conn = wpa_ctrl_open(ifname);
 	return ctrl_conn;
-#else /* CONFIG_CTRL_IFACE_UDP */
+#else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
 	char *cfile;
 	int flen;
 
 	if (ifname == NULL)
 		return NULL;
 
-	flen = strlen(ctrl_iface_dir) + strlen(ifname) + 2;
-	cfile = malloc(flen);
+	flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2;
+	cfile = os_malloc(flen);
 	if (cfile == NULL)
 		return NULL;
-	snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname);
+	os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname);
 
 	ctrl_conn = wpa_ctrl_open(cfile);
-	free(cfile);
+	os_free(cfile);
 	return ctrl_conn;
-#endif /* CONFIG_CTRL_IFACE_UDP */
+#endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
 }
 
 
@@ -215,7 +216,7 @@
 		return -1;
 	}
 	len = sizeof(buf) - 1;
-	ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
+	ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
 			       wpa_cli_msg_cb);
 	if (ret == -2) {
 		printf("'%s' command timed out.\n", cmd);
@@ -240,7 +241,7 @@
 
 static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
 {
-	int verbose = argc > 0 && strcmp(argv[0], "verbose") == 0;
+	int verbose = argc > 0 && os_strcmp(argv[0], "verbose") == 0;
 	return wpa_ctrl_command(ctrl, verbose ? "STATUS-VERBOSE" : "STATUS");
 }
 
@@ -307,6 +308,7 @@
 static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
 {
 	char cmd[256];
+	int res;
 
 	if (argc == 0) {
 		wpa_cli_show_variables();
@@ -319,8 +321,8 @@
 		return 0;
 	}
 
-	if (snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]) >=
-	    sizeof(cmd) - 1) {
+	res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]);
+	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
 		printf("Too long SET command.\n");
 		return 0;
 	}
@@ -351,6 +353,7 @@
 				       char *argv[])
 {
 	char cmd[256];
+	int res;
 
 	if (argc != 1) {
 		printf("Invalid PREAUTH command: needs one argument "
@@ -358,8 +361,8 @@
 		return 0;
 	}
 
-	if (snprintf(cmd, sizeof(cmd), "PREAUTH %s", argv[0]) >=
-	    sizeof(cmd) - 1) {
+	res = os_snprintf(cmd, sizeof(cmd), "PREAUTH %s", argv[0]);
+	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
 		printf("Too long PREAUTH command.\n");
 		return 0;
 	}
@@ -367,15 +370,61 @@
 }
 
 
+static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+	char cmd[256];
+	int res;
+
+	if (argc != 1) {
+		printf("Invalid AP_SCAN command: needs one argument (ap_scan "
+		       "value)\n");
+		return 0;
+	}
+	res = os_snprintf(cmd, sizeof(cmd), "AP_SCAN %s", argv[0]);
+	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
+		printf("Too long AP_SCAN command.\n");
+		return 0;
+	}
+	return wpa_ctrl_command(ctrl, cmd);
+}
+
+
+static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
+				char *argv[])
+{
+	char cmd[256];
+	int res;
+
+	if (argc != 1) {
+		printf("Invalid STKSTART command: needs one argument "
+		       "(Peer STA MAC address)\n");
+		return 0;
+	}
+
+	res = os_snprintf(cmd, sizeof(cmd), "STKSTART %s", argv[0]);
+	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
+		printf("Too long STKSTART command.\n");
+		return 0;
+	}
+	return wpa_ctrl_command(ctrl, cmd);
+}
+
+
 static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
 {
 	char cmd[256];
+	int res;
+
 	if (argc != 1) {
 		printf("Invalid LEVEL command: needs one argument (debug "
 		       "level)\n");
 		return 0;
 	}
-	snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
+	res = os_snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
+	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
+		printf("Too long LEVEL command.\n");
+		return 0;
+	}
 	return wpa_ctrl_command(ctrl, cmd);
 }
 
@@ -383,7 +432,7 @@
 static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
 {
 	char cmd[256], *pos, *end;
-	int i;
+	int i, ret;
 
 	if (argc < 2) {
 		printf("Invalid IDENTITY command: needs two arguments "
@@ -393,10 +442,21 @@
 
 	end = cmd + sizeof(cmd);
 	pos = cmd;
-	pos += snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
-		       argv[0], argv[1]);
-	for (i = 2; i < argc; i++)
-		pos += snprintf(pos, end - pos, " %s", argv[i]);
+	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
+			  argv[0], argv[1]);
+	if (ret < 0 || ret >= end - pos) {
+		printf("Too long IDENTITY command.\n");
+		return 0;
+	}
+	pos += ret;
+	for (i = 2; i < argc; i++) {
+		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
+		if (ret < 0 || ret >= end - pos) {
+			printf("Too long IDENTITY command.\n");
+			return 0;
+		}
+		pos += ret;
+	}
 
 	return wpa_ctrl_command(ctrl, cmd);
 }
@@ -405,7 +465,7 @@
 static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
 {
 	char cmd[256], *pos, *end;
-	int i;
+	int i, ret;
 
 	if (argc < 2) {
 		printf("Invalid PASSWORD command: needs two arguments "
@@ -415,10 +475,21 @@
 
 	end = cmd + sizeof(cmd);
 	pos = cmd;
-	pos += snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
-		       argv[0], argv[1]);
-	for (i = 2; i < argc; i++)
-		pos += snprintf(pos, end - pos, " %s", argv[i]);
+	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
+			  argv[0], argv[1]);
+	if (ret < 0 || ret >= end - pos) {
+		printf("Too long PASSWORD command.\n");
+		return 0;
+	}
+	pos += ret;
+	for (i = 2; i < argc; i++) {
+		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
+		if (ret < 0 || ret >= end - pos) {
+			printf("Too long PASSWORD command.\n");
+			return 0;
+		}
+		pos += ret;
+	}
 
 	return wpa_ctrl_command(ctrl, cmd);
 }
@@ -428,7 +499,7 @@
 				    char *argv[])
 {
 	char cmd[256], *pos, *end;
-	int i;
+	int i, ret;
 
 	if (argc < 2) {
 		printf("Invalid NEW_PASSWORD command: needs two arguments "
@@ -438,10 +509,21 @@
 
 	end = cmd + sizeof(cmd);
 	pos = cmd;
-	pos += snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
-		       argv[0], argv[1]);
-	for (i = 2; i < argc; i++)
-		pos += snprintf(pos, end - pos, " %s", argv[i]);
+	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
+			  argv[0], argv[1]);
+	if (ret < 0 || ret >= end - pos) {
+		printf("Too long NEW_PASSWORD command.\n");
+		return 0;
+	}
+	pos += ret;
+	for (i = 2; i < argc; i++) {
+		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
+		if (ret < 0 || ret >= end - pos) {
+			printf("Too long NEW_PASSWORD command.\n");
+			return 0;
+		}
+		pos += ret;
+	}
 
 	return wpa_ctrl_command(ctrl, cmd);
 }
@@ -450,7 +532,7 @@
 static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
 {
 	char cmd[256], *pos, *end;
-	int i;
+	int i, ret;
 
 	if (argc < 2) {
 		printf("Invalid PIN command: needs two arguments "
@@ -460,11 +542,21 @@
 
 	end = cmd + sizeof(cmd);
 	pos = cmd;
-	pos += snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
-			argv[0], argv[1]);
-	for (i = 2; i < argc; i++)
-		pos += snprintf(pos, end - pos, " %s", argv[i]);
-
+	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
+			  argv[0], argv[1]);
+	if (ret < 0 || ret >= end - pos) {
+		printf("Too long PIN command.\n");
+		return 0;
+	}
+	pos += ret;
+	for (i = 2; i < argc; i++) {
+		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
+		if (ret < 0 || ret >= end - pos) {
+			printf("Too long PIN command.\n");
+			return 0;
+		}
+		pos += ret;
+	}
 	return wpa_ctrl_command(ctrl, cmd);
 }
 
@@ -472,7 +564,7 @@
 static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
 {
 	char cmd[256], *pos, *end;
-	int i;
+	int i, ret;
 
 	if (argc < 2) {
 		printf("Invalid OTP command: needs two arguments (network "
@@ -482,10 +574,21 @@
 
 	end = cmd + sizeof(cmd);
 	pos = cmd;
-	pos += snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
-		       argv[0], argv[1]);
-	for (i = 2; i < argc; i++)
-		pos += snprintf(pos, end - pos, " %s", argv[i]);
+	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
+			  argv[0], argv[1]);
+	if (ret < 0 || ret >= end - pos) {
+		printf("Too long OTP command.\n");
+		return 0;
+	}
+	pos += ret;
+	for (i = 2; i < argc; i++) {
+		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
+		if (ret < 0 || ret >= end - pos) {
+			printf("Too long OTP command.\n");
+			return 0;
+		}
+		pos += ret;
+	}
 
 	return wpa_ctrl_command(ctrl, cmd);
 }
@@ -495,7 +598,7 @@
 				  char *argv[])
 {
 	char cmd[256], *pos, *end;
-	int i;
+	int i, ret;
 
 	if (argc < 2) {
 		printf("Invalid PASSPHRASE command: needs two arguments "
@@ -505,10 +608,21 @@
 
 	end = cmd + sizeof(cmd);
 	pos = cmd;
-	pos += snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
-		       argv[0], argv[1]);
-	for (i = 2; i < argc; i++)
-		pos += snprintf(pos, end - pos, " %s", argv[i]);
+	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
+			  argv[0], argv[1]);
+	if (ret < 0 || ret >= end - pos) {
+		printf("Too long PASSPHRASE command.\n");
+		return 0;
+	}
+	pos += ret;
+	for (i = 2; i < argc; i++) {
+		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
+		if (ret < 0 || ret >= end - pos) {
+			printf("Too long PASSPHRASE command.\n");
+			return 0;
+		}
+		pos += ret;
+	}
 
 	return wpa_ctrl_command(ctrl, cmd);
 }
@@ -517,7 +631,7 @@
 static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
 {
 	char cmd[256], *pos, *end;
-	int i;
+	int i, ret;
 
 	if (argc < 2) {
 		printf("Invalid BSSID command: needs two arguments (network "
@@ -527,9 +641,20 @@
 
 	end = cmd + sizeof(cmd);
 	pos = cmd;
-	pos += snprintf(pos, end - pos, "BSSID");
-	for (i = 0; i < argc; i++)
-		pos += snprintf(pos, end - pos, " %s", argv[i]);
+	ret = os_snprintf(pos, end - pos, "BSSID");
+	if (ret < 0 || ret >= end - pos) {
+		printf("Too long BSSID command.\n");
+		return 0;
+	}
+	pos += ret;
+	for (i = 0; i < argc; i++) {
+		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
+		if (ret < 0 || ret >= end - pos) {
+			printf("Too long BSSID command.\n");
+			return 0;
+		}
+		pos += ret;
+	}
 
 	return wpa_ctrl_command(ctrl, cmd);
 }
@@ -553,7 +678,8 @@
 		return 0;
 	}
 
-	snprintf(cmd, sizeof(cmd), "SELECT_NETWORK %s", argv[0]);
+	os_snprintf(cmd, sizeof(cmd), "SELECT_NETWORK %s", argv[0]);
+	cmd[sizeof(cmd) - 1] = '\0';
 
 	return wpa_ctrl_command(ctrl, cmd);
 }
@@ -570,7 +696,8 @@
 		return 0;
 	}
 
-	snprintf(cmd, sizeof(cmd), "ENABLE_NETWORK %s", argv[0]);
+	os_snprintf(cmd, sizeof(cmd), "ENABLE_NETWORK %s", argv[0]);
+	cmd[sizeof(cmd) - 1] = '\0';
 
 	return wpa_ctrl_command(ctrl, cmd);
 }
@@ -587,7 +714,8 @@
 		return 0;
 	}
 
-	snprintf(cmd, sizeof(cmd), "DISABLE_NETWORK %s", argv[0]);
+	os_snprintf(cmd, sizeof(cmd), "DISABLE_NETWORK %s", argv[0]);
+	cmd[sizeof(cmd) - 1] = '\0';
 
 	return wpa_ctrl_command(ctrl, cmd);
 }
@@ -611,7 +739,8 @@
 		return 0;
 	}
 
-	snprintf(cmd, sizeof(cmd), "REMOVE_NETWORK %s", argv[0]);
+	os_snprintf(cmd, sizeof(cmd), "REMOVE_NETWORK %s", argv[0]);
+	cmd[sizeof(cmd) - 1] = '\0';
 
 	return wpa_ctrl_command(ctrl, cmd);
 }
@@ -642,6 +771,7 @@
 				   char *argv[])
 {
 	char cmd[256];
+	int res;
 
 	if (argc == 0) {
 		wpa_cli_show_network_variables();
@@ -654,8 +784,9 @@
 		return 0;
 	}
 
-	if (snprintf(cmd, sizeof(cmd), "SET_NETWORK %s %s %s",
-		     argv[0], argv[1], argv[2]) >= sizeof(cmd) - 1) {
+	res = os_snprintf(cmd, sizeof(cmd), "SET_NETWORK %s %s %s",
+			  argv[0], argv[1], argv[2]);
+	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
 		printf("Too long SET_NETWORK command.\n");
 		return 0;
 	}
@@ -667,6 +798,7 @@
 				   char *argv[])
 {
 	char cmd[256];
+	int res;
 
 	if (argc == 0) {
 		wpa_cli_show_network_variables();
@@ -679,8 +811,9 @@
 		return 0;
 	}
 
-	if (snprintf(cmd, sizeof(cmd), "GET_NETWORK %s %s",
-		     argv[0], argv[1]) >= sizeof(cmd) - 1) {
+	res = os_snprintf(cmd, sizeof(cmd), "GET_NETWORK %s %s",
+			  argv[0], argv[1]);
+	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
 		printf("Too long GET_NETWORK command.\n");
 		return 0;
 	}
@@ -720,37 +853,30 @@
 {
 	char cmd[64];
 
-	if (argc != 1) {
-		printf("Invalid GET_CAPABILITY command: needs one argument\n");
+	if (argc < 1 || argc > 2) {
+		printf("Invalid GET_CAPABILITY command: need either one or "
+		       "two arguments\n");
 		return 0;
 	}
 
-	snprintf(cmd, sizeof(cmd), "GET_CAPABILITY %s", argv[0]);
+	if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
+		printf("Invalid GET_CAPABILITY command: second argument, "
+		       "if any, must be 'strict'\n");
+		return 0;
+	}
+
+	os_snprintf(cmd, sizeof(cmd), "GET_CAPABILITY %s%s", argv[0],
+		    (argc == 2) ? " strict" : "");
+	cmd[sizeof(cmd) - 1] = '\0';
 
 	return wpa_ctrl_command(ctrl, cmd);
 }
 
 
-static void wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
+static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
 {
-	struct dirent *dent;
-	DIR *dir;
-
-	dir = opendir(ctrl_iface_dir);
-	if (dir == NULL) {
-		printf("Control interface directory '%s' could not be "
-		       "openned.\n", ctrl_iface_dir);
-		return;
-	}
-
 	printf("Available interfaces:\n");
-	while ((dent = readdir(dir))) {
-		if (strcmp(dent->d_name, ".") == 0 ||
-		    strcmp(dent->d_name, "..") == 0)
-			continue;
-		printf("%s\n", dent->d_name);
-	}
-	closedir(dir);
+	return wpa_ctrl_command(ctrl, "INTERFACES");
 }
 
 
@@ -762,8 +888,8 @@
 	}
 
 	wpa_cli_close_connection();
-	free(ctrl_ifname);
-	ctrl_ifname = strdup(argv[0]);
+	os_free(ctrl_ifname);
+	ctrl_ifname = os_strdup(argv[0]);
 
 	if (wpa_cli_open_connection(ctrl_ifname)) {
 		printf("Connected to interface '%s.\n", ctrl_ifname);
@@ -804,17 +930,20 @@
 		printf("Invalid INTERFACE_ADD command: needs at least one "
 		       "argument (interface name)\n"
 			"All arguments: ifname confname driver ctrl_interface "
-			"driver_param\n");
+			"driver_param bridge_name\n");
 		return 0;
 	}
 
 	/*
 	 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
-	 * <driver_param>
+	 * <driver_param>TAB<bridge_name>
 	 */
-	snprintf(cmd, sizeof(cmd), "INTERFACE_ADD %s\t%s\t%s\t%s\t%s", argv[0],
-		 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
-		 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "");
+	os_snprintf(cmd, sizeof(cmd), "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
+		    argv[0],
+		    argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
+		    argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
+		    argc > 5 ? argv[5] : "");
+	cmd[sizeof(cmd) - 1] = '\0';
 	return wpa_ctrl_command(ctrl, cmd);
 }
 
@@ -830,7 +959,8 @@
 		return 0;
 	}
 
-	snprintf(cmd, sizeof(cmd), "INTERFACE_REMOVE %s", argv[0]);
+	os_snprintf(cmd, sizeof(cmd), "INTERFACE_REMOVE %s", argv[0]);
+	cmd[sizeof(cmd) - 1] = '\0';
 	return wpa_ctrl_command(ctrl, cmd);
 }
 
@@ -879,6 +1009,8 @@
 	{ "terminate", wpa_cli_cmd_terminate },
 	{ "interface_add", wpa_cli_cmd_interface_add },
 	{ "interface_remove", wpa_cli_cmd_interface_remove },
+	{ "ap_scan", wpa_cli_cmd_ap_scan },
+	{ "stkstart", wpa_cli_cmd_stkstart },
 	{ NULL, NULL }
 };
 
@@ -891,9 +1023,10 @@
 	count = 0;
 	cmd = wpa_cli_commands;
 	while (cmd->cmd) {
-		if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) == 0) {
+		if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
+		{
 			match = cmd;
-			if (strcasecmp(cmd->cmd, argv[0]) == 0) {
+			if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
 				/* we have an exact match */
 				count = 1;
 				break;
@@ -907,8 +1040,8 @@
 		printf("Ambiguous command '%s'; possible commands:", argv[0]);
 		cmd = wpa_cli_commands;
 		while (cmd->cmd) {
-			if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) ==
-			    0) {
+			if (os_strncasecmp(cmd->cmd, argv[0],
+					   os_strlen(argv[0])) == 0) {
 				printf(" %s", cmd->cmd);
 			}
 			cmd++;
@@ -924,7 +1057,7 @@
 
 static int str_match(const char *a, const char *b)
 {
-	return strncmp(a, b, strlen(b)) == 0;
+	return os_strncmp(a, b, os_strlen(b)) == 0;
 }
 
 
@@ -934,13 +1067,16 @@
 	char *cmd;
 	size_t len;
 
-	len = strlen(program) + strlen(arg1) + strlen(arg2) + 3;
-	cmd = malloc(len);
+	len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
+	cmd = os_malloc(len);
 	if (cmd == NULL)
 		return -1;
-	snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
+	os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
+	cmd[len - 1] = '\0';
+#ifndef _WIN32_WCE
 	system(cmd);
-	free(cmd);
+#endif /* _WIN32_WCE */
+	os_free(cmd);
 
 	return 0;
 }
@@ -949,11 +1085,12 @@
 static void wpa_cli_action_process(const char *msg)
 {
 	const char *pos;
+	char *copy = NULL, *id, *pos2;
 
 	pos = msg;
 	if (*pos == '<') {
 		/* skip priority */
-		pos = strchr(pos, '>');
+		pos = os_strchr(pos, '>');
 		if (pos)
 			pos++;
 		else
@@ -961,9 +1098,46 @@
 	}
 
 	if (str_match(pos, WPA_EVENT_CONNECTED)) {
-		wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
+		int new_id = -1;
+		os_unsetenv("WPA_ID");
+		os_unsetenv("WPA_ID_STR");
+		os_unsetenv("WPA_CTRL_DIR");
+
+		pos = os_strstr(pos, "[id=");
+		if (pos)
+			copy = os_strdup(pos + 4);
+
+		if (copy) {
+			pos2 = id = copy;
+			while (*pos2 && *pos2 != ' ')
+				pos2++;
+			*pos2++ = '\0';
+			new_id = atoi(id);
+			os_setenv("WPA_ID", id, 1);
+			while (*pos2 && *pos2 != '=')
+				pos2++;
+			if (*pos2 == '=')
+				pos2++;
+			id = pos2;
+			while (*pos2 && *pos2 != ']')
+				pos2++;
+			*pos2 = '\0';
+			os_setenv("WPA_ID_STR", id, 1);
+			os_free(copy);
+		}
+
+		os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
+
+		if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
+			wpa_cli_connected = 1;
+			wpa_cli_last_id = new_id;
+			wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
+		}
 	} else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
-		wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
+		if (wpa_cli_connected) {
+			wpa_cli_connected = 0;
+			wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
+		}
 	} else if (str_match(pos, WPA_EVENT_TERMINATING)) {
 		printf("wpa_supplicant is terminating - stop monitoring\n");
 		wpa_cli_quit = 1;
@@ -971,19 +1145,39 @@
 }
 
 
+#ifndef CONFIG_ANSI_C_EXTRA
 static void wpa_cli_action_cb(char *msg, size_t len)
 {
 	wpa_cli_action_process(msg);
 }
+#endif /* CONFIG_ANSI_C_EXTRA */
+
+
+static void wpa_cli_reconnect(void)
+{
+	wpa_cli_close_connection();
+	ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
+	if (ctrl_conn) {
+		printf("Connection to wpa_supplicant re-established\n");
+		if (wpa_ctrl_attach(ctrl_conn) == 0) {
+			wpa_cli_attached = 1;
+		} else {
+			printf("Warning: Failed to attach to "
+			       "wpa_supplicant.\n");
+		}
+	}
+}
 
 
 static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
 				 int action_monitor)
 {
 	int first = 1;
-	if (ctrl_conn == NULL)
+	if (ctrl_conn == NULL) {
+		wpa_cli_reconnect();
 		return;
-	while (wpa_ctrl_pending(ctrl)) {
+	}
+	while (wpa_ctrl_pending(ctrl) > 0) {
 		char buf[256];
 		size_t len = sizeof(buf) - 1;
 		if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
@@ -1001,6 +1195,12 @@
 			break;
 		}
 	}
+
+	if (wpa_ctrl_pending(ctrl) < 0) {
+		printf("Connection to wpa_supplicant lost - trying to "
+		       "reconnect\n");
+		wpa_cli_reconnect();
+	}
 }
 
 
@@ -1012,13 +1212,13 @@
 
 	if (state == 0) {
 		i = 0;
-		len = strlen(text);
+		len = os_strlen(text);
 	}
 
 	while ((cmd = wpa_cli_commands[i].cmd)) {
 		i++;
-		if (strncasecmp(cmd, text, len) == 0)
-			return strdup(cmd);
+		if (os_strncasecmp(cmd, text, len) == 0)
+			return os_strdup(cmd);
 	}
 
 	return NULL;
@@ -1055,10 +1255,11 @@
 	home = getenv("HOME");
 	if (home) {
 		const char *fname = ".wpa_cli_history";
-		int hfile_len = strlen(home) + 1 + strlen(fname) + 1;
-		hfile = malloc(hfile_len);
+		int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
+		hfile = os_malloc(hfile_len);
 		if (hfile) {
-			snprintf(hfile, hfile_len, "%s/%s", home, fname);
+			os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
+			hfile[hfile_len - 1] = '\0';
 			read_history(hfile);
 			stifle_history(100);
 		}
@@ -1077,7 +1278,7 @@
 			while (next_history())
 				;
 			h = previous_history();
-			if (h == NULL || strcmp(cmd, h->line) != 0)
+			if (h == NULL || os_strcmp(cmd, h->line) != 0)
 				add_history(cmd);
 			next_history();
 		}
@@ -1090,6 +1291,7 @@
 #endif /* CONFIG_NATIVE_WINDOWS */
 		if (cmd == NULL)
 			break;
+		wpa_cli_recv_pending(ctrl_conn, 0, 0);
 		pos = cmd;
 		while (*pos != '\0') {
 			if (*pos == '\n') {
@@ -1110,7 +1312,7 @@
 			if (argc == max_args)
 				break;
 			if (*pos == '"') {
-				char *pos2 = strrchr(pos, '"');
+				char *pos2 = os_strrchr(pos, '"');
 				if (pos2)
 					pos = pos2 + 1;
 			}
@@ -1123,7 +1325,7 @@
 			wpa_request(ctrl_conn, argc, argv);
 
 		if (cmd != cmdbuf)
-			free(cmd);
+			os_free(cmd);
 	} while (!wpa_cli_quit);
 
 #ifdef CONFIG_READLINE
@@ -1137,14 +1339,14 @@
 			char *p = h->line;
 			while (*p == ' ' || *p == '\t')
 				p++;
-			if (strncasecmp(p, "pa", 2) == 0 ||
-			    strncasecmp(p, "o", 1) == 0 ||
-			    strncasecmp(p, "n", 1)) {
+			if (os_strncasecmp(p, "pa", 2) == 0 ||
+			    os_strncasecmp(p, "o", 1) == 0 ||
+			    os_strncasecmp(p, "n", 1)) {
 				h = remove_history(where_history());
 				if (h) {
-					free(h->line);
-					free(h->data);
-					free(h);
+					os_free(h->line);
+					os_free(h->data);
+					os_free(h);
 				}
 				h = current_history();
 			} else {
@@ -1152,7 +1354,7 @@
 			}
 		}
 		write_history(hfile);
-		free(hfile);
+		os_free(hfile);
 	}
 #endif /* CONFIG_READLINE */
 }
@@ -1160,10 +1362,14 @@
 
 static void wpa_cli_action(struct wpa_ctrl *ctrl)
 {
+#ifdef CONFIG_ANSI_C_EXTRA
+	/* TODO: ANSI C version(?) */
+	printf("Action processing not supported in ANSI C build.\n");
+#else /* CONFIG_ANSI_C_EXTRA */
 	fd_set rfds;
 	int fd, res;
 	struct timeval tv;
-	char buf[16];
+	char buf[256]; /* note: large enough to fit in unsolicited messages */
 	size_t len;
 
 	fd = wpa_ctrl_get_fd(ctrl);
@@ -1186,13 +1392,14 @@
 			len = sizeof(buf) - 1;
 			if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
 					     wpa_cli_action_cb) < 0 ||
-			    len < 4 || memcmp(buf, "PONG", 4) != 0) {
+			    len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
 				printf("wpa_supplicant did not reply to PING "
 				       "command - exiting\n");
 				break;
 			}
 		}
 	}
+#endif /* CONFIG_ANSI_C_EXTRA */
 }
 
 
@@ -1200,11 +1407,9 @@
 {
 	wpa_cli_close_connection();
 	if (pid_file)
-		unlink(pid_file);
+		os_daemonize_terminate(pid_file);
 
-#ifdef CONFIG_NATIVE_WINDOWS
-	WSACleanup();
-#endif /* CONFIG_NATIVE_WINDOWS */
+	os_program_deinit();
 }
 
 static void wpa_cli_terminate(int sig)
@@ -1222,19 +1427,8 @@
 		       "reconnect\n");
 		wpa_cli_close_connection();
 	}
-	if (!ctrl_conn) {
-		ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
-		if (ctrl_conn) {
-			printf("Connection to wpa_supplicant "
-			       "re-established\n");
-			if (wpa_ctrl_attach(ctrl_conn) == 0) {
-				wpa_cli_attached = 1;
-			} else {
-				printf("Warning: Failed to attach to "
-				       "wpa_supplicant.\n");
-			}
-		}
-	}
+	if (!ctrl_conn)
+		wpa_cli_reconnect();
 	if (ctrl_conn)
 		wpa_cli_recv_pending(ctrl_conn, 1, 0);
 	alarm(1);
@@ -1242,22 +1436,71 @@
 #endif /* CONFIG_NATIVE_WINDOWS */
 
 
+static char * wpa_cli_get_default_ifname(void)
+{
+	char *ifname = NULL;
+
+#ifdef CONFIG_CTRL_IFACE_UNIX
+	struct dirent *dent;
+	DIR *dir = opendir(ctrl_iface_dir);
+	if (!dir)
+		return NULL;
+	while ((dent = readdir(dir))) {
+#ifdef _DIRENT_HAVE_D_TYPE
+		/*
+		 * Skip the file if it is not a socket. Also accept
+		 * DT_UNKNOWN (0) in case the C library or underlying
+		 * file system does not support d_type.
+		 */
+		if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
+			continue;
+#endif /* _DIRENT_HAVE_D_TYPE */
+		if (os_strcmp(dent->d_name, ".") == 0 ||
+		    os_strcmp(dent->d_name, "..") == 0)
+			continue;
+		printf("Selected interface '%s'\n", dent->d_name);
+		ifname = os_strdup(dent->d_name);
+		break;
+	}
+	closedir(dir);
+#endif /* CONFIG_CTRL_IFACE_UNIX */
+
+#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
+	char buf[2048], *pos;
+	size_t len;
+	struct wpa_ctrl *ctrl;
+	int ret;
+
+	ctrl = wpa_ctrl_open(NULL);
+	if (ctrl == NULL)
+		return NULL;
+
+	len = sizeof(buf) - 1;
+	ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
+	if (ret >= 0) {
+		buf[len] = '\0';
+		pos = os_strchr(buf, '\n');
+		if (pos)
+			*pos = '\0';
+		ifname = os_strdup(buf);
+	}
+	wpa_ctrl_close(ctrl);
+#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
+
+	return ifname;
+}
+
+
 int main(int argc, char *argv[])
 {
 	int interactive;
 	int warning_displayed = 0;
 	int c;
 	int daemonize = 0;
-	FILE *f;
 	const char *global = NULL;
 
-#ifdef CONFIG_NATIVE_WINDOWS
-	WSADATA wsaData;
-	if (WSAStartup(MAKEWORD(2, 0), &wsaData)) {
-		printf("Could not find a usable WinSock.dll\n");
+	if (os_program_init())
 		return -1;
-	}
-#endif /* CONFIG_NATIVE_WINDOWS */
 
 	for (;;) {
 		c = getopt(argc, argv, "a:Bg:hi:p:P:v");
@@ -1280,7 +1523,8 @@
 			printf("%s\n", wpa_cli_version);
 			return 0;
 		case 'i':
-			ctrl_ifname = strdup(optarg);
+			os_free(ctrl_ifname);
+			ctrl_ifname = os_strdup(optarg);
 			break;
 		case 'p':
 			ctrl_iface_dir = optarg;
@@ -1300,7 +1544,11 @@
 		printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
 
 	if (global) {
+#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
+		ctrl_conn = wpa_ctrl_open(NULL);
+#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
 		ctrl_conn = wpa_ctrl_open(global);
+#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
 		if (ctrl_conn == NULL) {
 			perror("Failed to connect to wpa_supplicant - "
 			       "wpa_ctrl_open");
@@ -1309,22 +1557,8 @@
 	}
 
 	for (; !global;) {
-		if (ctrl_ifname == NULL) {
-			struct dirent *dent;
-			DIR *dir = opendir(ctrl_iface_dir);
-			if (dir) {
-				while ((dent = readdir(dir))) {
-					if (strcmp(dent->d_name, ".") == 0 ||
-					    strcmp(dent->d_name, "..") == 0)
-						continue;
-					printf("Selected interface '%s'\n",
-					       dent->d_name);
-					ctrl_ifname = strdup(dent->d_name);
-					break;
-				}
-				closedir(dir);
-			}
-		}
+		if (ctrl_ifname == NULL)
+			ctrl_ifname = wpa_cli_get_default_ifname();
 		ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
 		if (ctrl_conn) {
 			if (warning_displayed)
@@ -1343,12 +1577,14 @@
 			       "re-trying\n");
 			warning_displayed = 1;
 		}
-		sleep(1);
+		os_sleep(1, 0);
 		continue;
 	}
 
+#ifndef _WIN32_WCE
 	signal(SIGINT, wpa_cli_terminate);
 	signal(SIGTERM, wpa_cli_terminate);
+#endif /* _WIN32_WCE */
 #ifndef CONFIG_NATIVE_WINDOWS
 	signal(SIGALRM, wpa_cli_alarm);
 #endif /* CONFIG_NATIVE_WINDOWS */
@@ -1364,18 +1600,8 @@
 		}
 	}
 
-	if (daemonize && daemon(0, 0)) {
-		perror("daemon");
+	if (daemonize && os_daemonize(pid_file))
 		return -1;
-	}
-
-	if (pid_file) {
-		f = fopen(pid_file, "w");
-		if (f) {
-			fprintf(f, "%u\n", getpid());
-			fclose(f);
-		}
-	}
 
 	if (interactive)
 		wpa_cli_interactive();
@@ -1384,8 +1610,16 @@
 	else
 		wpa_request(ctrl_conn, argc - optind, &argv[optind]);
 
-	free(ctrl_ifname);
+	os_free(ctrl_ifname);
 	wpa_cli_cleanup();
 
 	return 0;
 }
+
+#else /* CONFIG_CTRL_IFACE */
+int main(int argc, char *argv[])
+{
+	printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
+	return -1;
+}
+#endif /* CONFIG_CTRL_IFACE */
Index: hostapd.h
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/hostapd.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -L contrib/wpa_supplicant/hostapd.h -L contrib/wpa_supplicant/hostapd.h -u -r1.1 -r1.2
--- contrib/wpa_supplicant/hostapd.h
+++ contrib/wpa_supplicant/hostapd.h
@@ -3,18 +3,19 @@
 
 /*
  * Minimal version of hostapd header files for eapol_test to build
- * radiusclient.c.
+ * radius_client.c.
  */
 
 #include "common.h"
 
-void hostapd_logger(void *ctx, u8 *addr, unsigned int module, int level,
-		    char *fmt, ...) __attribute__ ((format (printf, 5, 6)));
+void hostapd_logger(void *ctx, const u8 *addr, unsigned int module, int level,
+		    char *fmt, ...) PRINTF_FORMAT(5, 6);
 
 struct hostapd_ip_addr;
 
 const char * hostapd_ip_txt(const struct hostapd_ip_addr *addr, char *buf,
-			    size_t buflen);;
+			    size_t buflen);
+int hostapd_ip_diff(struct hostapd_ip_addr *a, struct hostapd_ip_addr *b);
 
 enum {
 	HOSTAPD_LEVEL_DEBUG_VERBOSE = 0,
Index: eap_leap.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/eap_leap.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/eap_leap.c -L contrib/wpa_supplicant/eap_leap.c -u -r1.2 -r1.3
--- contrib/wpa_supplicant/eap_leap.c
+++ contrib/wpa_supplicant/eap_leap.c
@@ -1,6 +1,6 @@
 /*
- * WPA Supplicant / EAP-LEAP
- * Copyright (c) 2004-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * EAP peer method: LEAP
+ * Copyright (c) 2004-2006, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -12,14 +12,10 @@
  * See README and COPYING for more details.
  */
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
+#include "includes.h"
 
 #include "common.h"
 #include "eap_i.h"
-#include "wpa_supplicant.h"
-#include "config_ssid.h"
 #include "ms_funcs.h"
 #include "crypto.h"
 
@@ -49,10 +45,9 @@
 {
 	struct eap_leap_data *data;
 
-	data = malloc(sizeof(*data));
+	data = os_zalloc(sizeof(*data));
 	if (data == NULL)
 		return NULL;
-	memset(data, 0, sizeof(*data));
 	data->state = LEAP_WAIT_CHALLENGE;
 
 	sm->leap_done = FALSE;
@@ -62,7 +57,7 @@
 
 static void eap_leap_deinit(struct eap_sm *sm, void *priv)
 {
-	free(priv);
+	os_free(priv);
 }
 
 
@@ -72,14 +67,19 @@
 				     size_t *respDataLen)
 {
 	struct eap_leap_data *data = priv;
-	struct wpa_ssid *config = eap_get_config(sm);
 	const struct eap_hdr *req;
 	struct eap_hdr *resp;
-	const u8 *pos, *challenge;
+	const u8 *pos, *challenge, *identity, *password;
 	u8 challenge_len, *rpos;
+	size_t identity_len, password_len;
 
 	wpa_printf(MSG_DEBUG, "EAP-LEAP: Processing EAP-Request");
 
+	identity = eap_get_config_identity(sm, &identity_len);
+	password = eap_get_config_password(sm, &password_len);
+	if (identity == NULL || password == NULL)
+		return NULL;
+
 	req = (const struct eap_hdr *) reqData;
 	pos = (const u8 *) (req + 1);
 	if (reqDataLen < sizeof(*req) + 4 || *pos != EAP_TYPE_LEAP) {
@@ -103,38 +103,32 @@
 	if (challenge_len != LEAP_CHALLENGE_LEN ||
 	    challenge_len > reqDataLen - sizeof(*req) - 4) {
 		wpa_printf(MSG_INFO, "EAP-LEAP: Invalid challenge "
-			   "(challenge_len=%d reqDataLen=%lu",
+			   "(challenge_len=%d reqDataLen=%lu)",
 			   challenge_len, (unsigned long) reqDataLen);
 		ret->ignore = TRUE;
 		return NULL;
 	}
 	challenge = pos;
-	memcpy(data->peer_challenge, challenge, LEAP_CHALLENGE_LEN);
+	os_memcpy(data->peer_challenge, challenge, LEAP_CHALLENGE_LEN);
 	wpa_hexdump(MSG_MSGDUMP, "EAP-LEAP: Challenge from AP",
 		    challenge, LEAP_CHALLENGE_LEN);
 
 	wpa_printf(MSG_DEBUG, "EAP-LEAP: Generating Challenge Response");
 
-	*respDataLen = sizeof(struct eap_hdr) + 1 + 3 + LEAP_RESPONSE_LEN +
-		config->identity_len;
-	resp = malloc(*respDataLen);
+	resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_LEAP, respDataLen,
+			     3 + LEAP_RESPONSE_LEN + identity_len,
+			     EAP_CODE_RESPONSE, req->identifier, &rpos);
 	if (resp == NULL)
 		return NULL;
-	resp->code = EAP_CODE_RESPONSE;
-	resp->identifier = req->identifier;
-	resp->length = host_to_be16(*respDataLen);
-	rpos = (u8 *) (resp + 1);
-	*rpos++ = EAP_TYPE_LEAP;
 	*rpos++ = LEAP_VERSION;
 	*rpos++ = 0; /* unused */
 	*rpos++ = LEAP_RESPONSE_LEN;
-	nt_challenge_response(challenge,
-			      config->password, config->password_len, rpos);
-	memcpy(data->peer_response, rpos, LEAP_RESPONSE_LEN);
+	nt_challenge_response(challenge, password, password_len, rpos);
+	os_memcpy(data->peer_response, rpos, LEAP_RESPONSE_LEN);
 	wpa_hexdump(MSG_MSGDUMP, "EAP-LEAP: Response",
 		    rpos, LEAP_RESPONSE_LEN);
 	rpos += LEAP_RESPONSE_LEN;
-	memcpy(rpos, config->identity, config->identity_len);
+	os_memcpy(rpos, identity, identity_len);
 
 	data->state = LEAP_WAIT_SUCCESS;
 
@@ -144,17 +138,21 @@
 
 static u8 * eap_leap_process_success(struct eap_sm *sm, void *priv,
 				     struct eap_method_ret *ret,
-				     const u8 *reqData, size_t reqDataLen,
-				     size_t *respDataLen)
+				     const u8 *reqData, size_t *respDataLen)
 {
 	struct eap_leap_data *data = priv;
-	struct wpa_ssid *config = eap_get_config(sm);
 	const struct eap_hdr *req;
 	struct eap_hdr *resp;
 	u8 *pos;
+	const u8 *identity;
+	size_t identity_len;
 
 	wpa_printf(MSG_DEBUG, "EAP-LEAP: Processing EAP-Success");
 
+	identity = eap_get_config_identity(sm, &identity_len);
+	if (identity == NULL)
+		return NULL;
+
 	if (data->state != LEAP_WAIT_SUCCESS) {
 		wpa_printf(MSG_INFO, "EAP-LEAP: EAP-Success received in "
 			   "unexpected state (%d) - ignored", data->state);
@@ -164,31 +162,26 @@
 
 	req = (const struct eap_hdr *) reqData;
 
-	*respDataLen = sizeof(struct eap_hdr) + 1 + 3 + LEAP_CHALLENGE_LEN +
-		config->identity_len;
-	resp = malloc(*respDataLen);
+	resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_LEAP, respDataLen,
+			     3 + LEAP_CHALLENGE_LEN + identity_len,
+			     EAP_CODE_REQUEST, req->identifier, &pos);
 	if (resp == NULL)
 		return NULL;
-	resp->code = EAP_CODE_REQUEST;
-	resp->identifier = req->identifier;
-	resp->length = host_to_be16(*respDataLen);
-	pos = (u8 *) (resp + 1);
-	*pos++ = EAP_TYPE_LEAP;
 	*pos++ = LEAP_VERSION;
 	*pos++ = 0; /* unused */
 	*pos++ = LEAP_CHALLENGE_LEN;
 	if (hostapd_get_rand(pos, LEAP_CHALLENGE_LEN)) {
 		wpa_printf(MSG_WARNING, "EAP-LEAP: Failed to read random data "
 			   "for challenge");
-		free(resp);
+		os_free(resp);
 		ret->ignore = TRUE;
 		return NULL;
 	}
-	memcpy(data->ap_challenge, pos, LEAP_CHALLENGE_LEN);
+	os_memcpy(data->ap_challenge, pos, LEAP_CHALLENGE_LEN);
 	wpa_hexdump(MSG_MSGDUMP, "EAP-LEAP: Challenge to AP/AS", pos,
 		    LEAP_CHALLENGE_LEN);
 	pos += LEAP_CHALLENGE_LEN;
-	memcpy(pos, config->identity, config->identity_len);
+	os_memcpy(pos, identity, identity_len);
 
 	data->state = LEAP_WAIT_RESPONSE;
 
@@ -198,18 +191,21 @@
 
 static u8 * eap_leap_process_response(struct eap_sm *sm, void *priv,
 				      struct eap_method_ret *ret,
-				      const u8 *reqData, size_t reqDataLen,
-				      size_t *respDataLen)
+				      const u8 *reqData, size_t reqDataLen)
 {
 	struct eap_leap_data *data = priv;
-	struct wpa_ssid *config = eap_get_config(sm);
 	const struct eap_hdr *resp;
-	const u8 *pos;
+	const u8 *pos, *password;
 	u8 response_len, pw_hash[16], pw_hash_hash[16],
 		expected[LEAP_RESPONSE_LEN];
+	size_t password_len;
 
 	wpa_printf(MSG_DEBUG, "EAP-LEAP: Processing EAP-Response");
 
+	password = eap_get_config_password(sm, &password_len);
+	if (password == NULL)
+		return NULL;
+
 	resp = (const struct eap_hdr *) reqData;
 	pos = (const u8 *) (resp + 1);
 	if (reqDataLen < sizeof(*resp) + 4 || *pos != EAP_TYPE_LEAP) {
@@ -233,7 +229,7 @@
 	if (response_len != LEAP_RESPONSE_LEN ||
 	    response_len > reqDataLen - sizeof(*resp) - 4) {
 		wpa_printf(MSG_INFO, "EAP-LEAP: Invalid response "
-			   "(response_len=%d reqDataLen=%lu",
+			   "(response_len=%d reqDataLen=%lu)",
 			   response_len, (unsigned long) reqDataLen);
 		ret->ignore = TRUE;
 		return NULL;
@@ -241,16 +237,16 @@
 
 	wpa_hexdump(MSG_DEBUG, "EAP-LEAP: Response from AP",
 		    pos, LEAP_RESPONSE_LEN);
-	memcpy(data->ap_response, pos, LEAP_RESPONSE_LEN);
+	os_memcpy(data->ap_response, pos, LEAP_RESPONSE_LEN);
 
-	nt_password_hash(config->password, config->password_len, pw_hash);
+	nt_password_hash(password, password_len, pw_hash);
 	hash_nt_password_hash(pw_hash, pw_hash_hash);
 	challenge_response(data->ap_challenge, pw_hash_hash, expected);
 
 	ret->methodState = METHOD_DONE;
 	ret->allowNotifications = FALSE;
 
-	if (memcmp(pos, expected, LEAP_RESPONSE_LEN) != 0) {
+	if (os_memcmp(pos, expected, LEAP_RESPONSE_LEN) != 0) {
 		wpa_printf(MSG_WARNING, "EAP-LEAP: AP sent an invalid "
 			   "response - authentication failed");
 		wpa_hexdump(MSG_DEBUG, "EAP-LEAP: Expected response from AP",
@@ -278,13 +274,14 @@
 			     const u8 *reqData, size_t reqDataLen,
 			     size_t *respDataLen)
 {
-	struct wpa_ssid *config = eap_get_config(sm);
 	const struct eap_hdr *eap;
-	size_t len;
+	size_t len, password_len;
+	const u8 *password;
 
-	if (config == NULL || config->password == NULL) {
+	password = eap_get_config_password(sm, &password_len);
+	if (password == NULL) {
 		wpa_printf(MSG_INFO, "EAP-LEAP: Password not configured");
-		eap_sm_request_password(sm, config);
+		eap_sm_request_password(sm);
 		ret->ignore = TRUE;
 		return NULL;
 	}
@@ -310,11 +307,10 @@
 		return eap_leap_process_request(sm, priv, ret, reqData, len,
 						respDataLen);
 	case EAP_CODE_SUCCESS:
-		return eap_leap_process_success(sm, priv, ret, reqData, len,
+		return eap_leap_process_success(sm, priv, ret, reqData,
 						respDataLen);
 	case EAP_CODE_RESPONSE:
-		return eap_leap_process_response(sm, priv, ret, reqData, len,
-						 respDataLen);
+		return eap_leap_process_response(sm, priv, ret, reqData, len);
 	default:
 		wpa_printf(MSG_INFO, "EAP-LEAP: Unexpected EAP code (%d) - "
 			   "ignored", eap->code);
@@ -334,19 +330,22 @@
 static u8 * eap_leap_getKey(struct eap_sm *sm, void *priv, size_t *len)
 {
 	struct eap_leap_data *data = priv;
-	struct wpa_ssid *config = eap_get_config(sm);
 	u8 *key, pw_hash_hash[16], pw_hash[16];
-	const u8 *addr[5];
-	size_t elen[5];
+	const u8 *addr[5], *password;
+	size_t elen[5], password_len;
 
 	if (data->state != LEAP_DONE)
 		return NULL;
 
-	key = malloc(LEAP_KEY_LEN);
+	password = eap_get_config_password(sm, &password_len);
+	if (password == NULL)
+		return NULL;
+
+	key = os_malloc(LEAP_KEY_LEN);
 	if (key == NULL)
 		return NULL;
 
-	nt_password_hash(config->password, config->password_len, pw_hash);
+	nt_password_hash(password, password_len, pw_hash);
 	hash_nt_password_hash(pw_hash, pw_hash_hash);
 	wpa_hexdump_key(MSG_DEBUG, "EAP-LEAP: pw_hash_hash",
 			pw_hash_hash, 16);
@@ -377,13 +376,24 @@
 }
 
 
-const struct eap_method eap_method_leap =
+int eap_peer_leap_register(void)
 {
-	.method = EAP_TYPE_LEAP,
-	.name = "LEAP",
-	.init = eap_leap_init,
-	.deinit = eap_leap_deinit,
-	.process = eap_leap_process,
-	.isKeyAvailable = eap_leap_isKeyAvailable,
-	.getKey = eap_leap_getKey,
-};
+	struct eap_method *eap;
+	int ret;
+
+	eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
+				    EAP_VENDOR_IETF, EAP_TYPE_LEAP, "LEAP");
+	if (eap == NULL)
+		return -1;
+
+	eap->init = eap_leap_init;
+	eap->deinit = eap_leap_deinit;
+	eap->process = eap_leap_process;
+	eap->isKeyAvailable = eap_leap_isKeyAvailable;
+	eap->getKey = eap_leap_getKey;
+
+	ret = eap_peer_method_register(eap);
+	if (ret)
+		eap_peer_method_free(eap);
+	return ret;
+}
Index: eapol_sm.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/eapol_sm.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/eapol_sm.c -L contrib/wpa_supplicant/eapol_sm.c -u -r1.2 -r1.3
--- contrib/wpa_supplicant/eapol_sm.c
+++ contrib/wpa_supplicant/eapol_sm.c
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant / EAPOL state machines
- * Copyright (c) 2004-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2004-2005, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -12,9 +12,7 @@
  * See README and COPYING for more details.
  */
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
+#include "includes.h"
 
 #include "common.h"
 #include "eapol_sm.h"
@@ -24,6 +22,10 @@
 #include "wpa.h"
 #include "md5.h"
 #include "rc4.h"
+#include "state_machine.h"
+
+#define STATE_MACHINE_DATA struct eapol_sm
+#define STATE_MACHINE_DEBUG_PREFIX "EAPOL"
 
 
 /* IEEE 802.1X-2004 - Supplicant - EAPOL state machines */
@@ -150,6 +152,10 @@
 #define IEEE8021X_KEY_INDEX_FLAG 0x80
 #define IEEE8021X_KEY_INDEX_MASK 0x03
 
+#ifdef _MSC_VER
+#pragma pack(push, 1)
+#endif /* _MSC_VER */
+
 struct ieee802_1x_eapol_key {
 	u8 type;
 	/* Note: key_length is unaligned */
@@ -172,7 +178,11 @@
 	 * represents the number of least significant octets from
 	 * MS-MPPE-Send-Key attribute to be used as the keying material;
 	 * RC4 key used in encryption = Key-IV + MS-MPPE-Recv-Key */
-} __attribute__ ((packed));
+} STRUCT_PACKED;
+
+#ifdef _MSC_VER
+#pragma pack(pop)
+#endif /* _MSC_VER */
 
 
 static void eapol_sm_txLogoff(struct eapol_sm *sm);
@@ -185,29 +195,6 @@
 static void eapol_sm_step_timeout(void *eloop_ctx, void *timeout_ctx);
 
 
-/* Definitions for clarifying state machine implementation */
-#define SM_STATE(machine, state) \
-static void sm_ ## machine ## _ ## state ## _Enter(struct eapol_sm *sm, \
-	int global)
-
-#define SM_ENTRY(machine, state) \
-if (!global || sm->machine ## _state != machine ## _ ## state) { \
-	sm->changed = TRUE; \
-	wpa_printf(MSG_DEBUG, "EAPOL: " #machine " entering state " #state); \
-} \
-sm->machine ## _state = machine ## _ ## state;
-
-#define SM_ENTER(machine, state) \
-sm_ ## machine ## _ ## state ## _Enter(sm, 0)
-#define SM_ENTER_GLOBAL(machine, state) \
-sm_ ## machine ## _ ## state ## _Enter(sm, 1)
-
-#define SM_STEP(machine) \
-static void sm_ ## machine ## _Step(struct eapol_sm *sm)
-
-#define SM_STEP_RUN(machine) sm_ ## machine ## _Step(sm)
-
-
 /* Port Timers state machine - implemented as a function that will be called
  * once a second as a registered event loop timeout */
 static void eapol_port_timers_tick(void *eloop_ctx, void *timeout_ctx)
@@ -537,6 +524,20 @@
 	case SUPP_BE_UNKNOWN:
 		break;
 	case SUPP_BE_REQUEST:
+		/*
+		 * IEEE Std 802.1X-2004 has transitions from REQUEST to FAIL
+		 * and SUCCESS based on eapFail and eapSuccess, respectively.
+		 * However, IEEE Std 802.1X-2004 is also specifying that
+		 * eapNoResp should be set in conjuction with eapSuccess and
+		 * eapFail which would mean that more than one of the
+		 * transitions here would be activated at the same time.
+		 * Skipping RESPONSE and/or RECEIVE states in these cases can
+		 * cause problems and the direct transitions to do not seem
+		 * correct. Because of this, the conditions for these
+		 * transitions are verified only after eapNoResp. They are
+		 * unlikely to be used since eapNoResp should always be set if
+		 * either of eapSuccess or eapFail is set.
+		 */
 		if (sm->eapResp && sm->eapNoResp) {
 			wpa_printf(MSG_DEBUG, "EAPOL: SUPP_BE REQUEST: both "
 				   "eapResp and eapNoResp set?!");
@@ -545,6 +546,10 @@
 			SM_ENTER(SUPP_BE, RESPONSE);
 		else if (sm->eapNoResp)
 			SM_ENTER(SUPP_BE, RECEIVE);
+		else if (sm->eapFail)
+			SM_ENTER(SUPP_BE, FAIL);
+		else if (sm->eapSuccess)
+			SM_ENTER(SUPP_BE, SUCCESS);
 		break;
 	case SUPP_BE_RESPONSE:
 		SM_ENTER(SUPP_BE, RECEIVE);
@@ -664,7 +669,7 @@
 		}
 		sign_key_len = 16;
 		encr_key_len = 16;
-		memcpy(keydata.sign_key, keydata.encr_key, 16);
+		os_memcpy(keydata.sign_key, keydata.encr_key, 16);
 	} else if (res) {
 		wpa_printf(MSG_DEBUG, "EAPOL: Could not get enough master key "
 			   "data for decrypting EAPOL-Key keys (res=%d)", res);
@@ -673,8 +678,8 @@
 
 	/* The key replay_counter must increase when same master key */
 	if (sm->replay_counter_valid &&
-	    memcmp(sm->last_replay_counter, key->replay_counter,
-		   IEEE8021X_REPLAY_COUNTER_LEN) >= 0) {
+	    os_memcmp(sm->last_replay_counter, key->replay_counter,
+		      IEEE8021X_REPLAY_COUNTER_LEN) >= 0) {
 		wpa_printf(MSG_WARNING, "EAPOL: EAPOL-Key replay counter did "
 			   "not increase - ignoring key");
 		wpa_hexdump(MSG_DEBUG, "EAPOL: last replay counter",
@@ -686,17 +691,17 @@
 	}
 
 	/* Verify key signature (HMAC-MD5) */
-	memcpy(orig_key_sign, key->key_signature, IEEE8021X_KEY_SIGN_LEN);
-	memset(key->key_signature, 0, IEEE8021X_KEY_SIGN_LEN);
+	os_memcpy(orig_key_sign, key->key_signature, IEEE8021X_KEY_SIGN_LEN);
+	os_memset(key->key_signature, 0, IEEE8021X_KEY_SIGN_LEN);
 	hmac_md5(keydata.sign_key, sign_key_len,
 		 sm->last_rx_key, sizeof(*hdr) + be_to_host16(hdr->length),
 		 key->key_signature);
-	if (memcmp(orig_key_sign, key->key_signature, IEEE8021X_KEY_SIGN_LEN)
-	    != 0) {
+	if (os_memcmp(orig_key_sign, key->key_signature,
+		      IEEE8021X_KEY_SIGN_LEN) != 0) {
 		wpa_printf(MSG_DEBUG, "EAPOL: Invalid key signature in "
 			   "EAPOL-Key packet");
-		memcpy(key->key_signature, orig_key_sign,
-		       IEEE8021X_KEY_SIGN_LEN);
+		os_memcpy(key->key_signature, orig_key_sign,
+			  IEEE8021X_KEY_SIGN_LEN);
 		return;
 	}
 	wpa_printf(MSG_DEBUG, "EAPOL: EAPOL-Key key signature verified");
@@ -708,10 +713,10 @@
 		return;
 	}
 	if (key_len == rx_key_length) {
-		memcpy(ekey, key->key_iv, IEEE8021X_KEY_IV_LEN);
-		memcpy(ekey + IEEE8021X_KEY_IV_LEN, keydata.encr_key,
-		       encr_key_len);
-		memcpy(datakey, key + 1, key_len);
+		os_memcpy(ekey, key->key_iv, IEEE8021X_KEY_IV_LEN);
+		os_memcpy(ekey + IEEE8021X_KEY_IV_LEN, keydata.encr_key,
+			  encr_key_len);
+		os_memcpy(datakey, key + 1, key_len);
 		rc4(datakey, key_len, ekey,
 		    IEEE8021X_KEY_IV_LEN + encr_key_len);
 		wpa_hexdump_key(MSG_DEBUG, "EAPOL: Decrypted(RC4) key",
@@ -727,7 +732,7 @@
 		 * seems to interoperate with Authenticators.
 		 */
 		key_len = rx_key_length;
-		memcpy(datakey, keydata.encr_key, key_len);
+		os_memcpy(datakey, keydata.encr_key, key_len);
 		wpa_hexdump_key(MSG_DEBUG, "EAPOL: using part of EAP keying "
 				"material data encryption key",
 				datakey, key_len);
@@ -738,8 +743,8 @@
 	}
 
 	sm->replay_counter_valid = TRUE;
-	memcpy(sm->last_replay_counter, key->replay_counter,
-	       IEEE8021X_REPLAY_COUNTER_LEN);
+	os_memcpy(sm->last_replay_counter, key->replay_counter,
+		  IEEE8021X_REPLAY_COUNTER_LEN);
 
 	wpa_printf(MSG_DEBUG, "EAPOL: Setting dynamic WEP key: %s keyidx %d "
 		   "len %d",
@@ -803,7 +808,7 @@
 			    IEEE802_1X_TYPE_EAP_PACKET, resp, resp_len);
 
 	/* eapRespData is not used anymore, so free it here */
-	free(resp);
+	os_free(resp);
 
 	if (sm->initial_req)
 		sm->dot1xSuppEapolReqIdFramesRx++;
@@ -818,9 +823,9 @@
 {
 	/* release system resources that may have been allocated for the
 	 * authentication session */
-	free(sm->last_rx_key);
+	os_free(sm->last_rx_key);
 	sm->last_rx_key = NULL;
-	free(sm->eapReqData);
+	os_free(sm->eapReqData);
 	sm->eapReqData = NULL;
 	eap_sm_abort(sm->eap);
 }
@@ -855,6 +860,8 @@
 		SM_STEP_RUN(SUPP_BE);
 		if (eap_sm_step(sm->eap))
 			sm->changed = TRUE;
+		if (!sm->changed)
+			break;
 	}
 
 	if (sm->changed) {
@@ -872,6 +879,7 @@
 }
 
 
+#ifdef CONFIG_CTRL_IFACE
 static const char *eapol_supp_pae_state(int state)
 {
 	switch (state) {
@@ -927,8 +935,10 @@
 	else
 		return "Unauthorized";
 }
+#endif /* CONFIG_CTRL_IFACE */
 
 
+#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
 static const char * eapol_port_control(PortControl ctrl)
 {
 	switch (ctrl) {
@@ -942,6 +952,7 @@
 		return "Unknown";
 	}
 }
+#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
 
 
 /**
@@ -971,6 +982,7 @@
 }
 
 
+#ifdef CONFIG_CTRL_IFACE
 /**
  * eapol_sm_get_status - Get EAPOL state machine status
  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
@@ -987,30 +999,35 @@
 int eapol_sm_get_status(struct eapol_sm *sm, char *buf, size_t buflen,
 			int verbose)
 {
-	int len;
+	int len, ret;
 	if (sm == NULL)
 		return 0;
 
-	len = snprintf(buf, buflen,
-		       "Supplicant PAE state=%s\n"
-		       "suppPortStatus=%s\n",
-		       eapol_supp_pae_state(sm->SUPP_PAE_state),
-		       eapol_port_status(sm->suppPortStatus));
+	len = os_snprintf(buf, buflen,
+			  "Supplicant PAE state=%s\n"
+			  "suppPortStatus=%s\n",
+			  eapol_supp_pae_state(sm->SUPP_PAE_state),
+			  eapol_port_status(sm->suppPortStatus));
+	if (len < 0 || (size_t) len >= buflen)
+		return 0;
 
 	if (verbose) {
-		len += snprintf(buf + len, buflen - len,
-				"heldPeriod=%u\n"
-				"authPeriod=%u\n"
-				"startPeriod=%u\n"
-				"maxStart=%u\n"
-				"portControl=%s\n"
-				"Supplicant Backend state=%s\n",
-				sm->heldPeriod,
-				sm->authPeriod,
-				sm->startPeriod,
-				sm->maxStart,
-				eapol_port_control(sm->portControl),
-				eapol_supp_be_state(sm->SUPP_BE_state));
+		ret = os_snprintf(buf + len, buflen - len,
+				  "heldPeriod=%u\n"
+				  "authPeriod=%u\n"
+				  "startPeriod=%u\n"
+				  "maxStart=%u\n"
+				  "portControl=%s\n"
+				  "Supplicant Backend state=%s\n",
+				  sm->heldPeriod,
+				  sm->authPeriod,
+				  sm->startPeriod,
+				  sm->maxStart,
+				  eapol_port_control(sm->portControl),
+				  eapol_supp_be_state(sm->SUPP_BE_state));
+		if (ret < 0 || (size_t) ret >= buflen - len)
+			return len;
+		len += ret;
 	}
 
 	len += eap_sm_get_status(sm->eap, buf + len, buflen - len, verbose);
@@ -1033,49 +1050,63 @@
  */
 int eapol_sm_get_mib(struct eapol_sm *sm, char *buf, size_t buflen)
 {
-	int len;
+	size_t len;
+	int ret;
+
 	if (sm == NULL)
 		return 0;
-	len = snprintf(buf, buflen,
-		       "dot1xSuppPaeState=%d\n"
-		       "dot1xSuppHeldPeriod=%u\n"
-		       "dot1xSuppAuthPeriod=%u\n"
-		       "dot1xSuppStartPeriod=%u\n"
-		       "dot1xSuppMaxStart=%u\n"
-		       "dot1xSuppSuppControlledPortStatus=%s\n"
-		       "dot1xSuppBackendPaeState=%d\n"
-		       "dot1xSuppEapolFramesRx=%u\n"
-		       "dot1xSuppEapolFramesTx=%u\n"
-		       "dot1xSuppEapolStartFramesTx=%u\n"
-		       "dot1xSuppEapolLogoffFramesTx=%u\n"
-		       "dot1xSuppEapolRespFramesTx=%u\n"
-		       "dot1xSuppEapolReqIdFramesRx=%u\n"
-		       "dot1xSuppEapolReqFramesRx=%u\n"
-		       "dot1xSuppInvalidEapolFramesRx=%u\n"
-		       "dot1xSuppEapLengthErrorFramesRx=%u\n"
-		       "dot1xSuppLastEapolFrameVersion=%u\n"
-		       "dot1xSuppLastEapolFrameSource=" MACSTR "\n",
-		       sm->SUPP_PAE_state,
-		       sm->heldPeriod,
-		       sm->authPeriod,
-		       sm->startPeriod,
-		       sm->maxStart,
-		       sm->suppPortStatus == Authorized ?
-		       "Authorized" : "Unauthorized",
-		       sm->SUPP_BE_state,
-		       sm->dot1xSuppEapolFramesRx,
-		       sm->dot1xSuppEapolFramesTx,
-		       sm->dot1xSuppEapolStartFramesTx,
-		       sm->dot1xSuppEapolLogoffFramesTx,
-		       sm->dot1xSuppEapolRespFramesTx,
-		       sm->dot1xSuppEapolReqIdFramesRx,
-		       sm->dot1xSuppEapolReqFramesRx,
-		       sm->dot1xSuppInvalidEapolFramesRx,
-		       sm->dot1xSuppEapLengthErrorFramesRx,
-		       sm->dot1xSuppLastEapolFrameVersion,
-		       MAC2STR(sm->dot1xSuppLastEapolFrameSource));
+	ret = os_snprintf(buf, buflen,
+			  "dot1xSuppPaeState=%d\n"
+			  "dot1xSuppHeldPeriod=%u\n"
+			  "dot1xSuppAuthPeriod=%u\n"
+			  "dot1xSuppStartPeriod=%u\n"
+			  "dot1xSuppMaxStart=%u\n"
+			  "dot1xSuppSuppControlledPortStatus=%s\n"
+			  "dot1xSuppBackendPaeState=%d\n",
+			  sm->SUPP_PAE_state,
+			  sm->heldPeriod,
+			  sm->authPeriod,
+			  sm->startPeriod,
+			  sm->maxStart,
+			  sm->suppPortStatus == Authorized ?
+			  "Authorized" : "Unauthorized",
+			  sm->SUPP_BE_state);
+
+	if (ret < 0 || (size_t) ret >= buflen)
+		return 0;
+	len = ret;
+
+	ret = os_snprintf(buf + len, buflen - len,
+			  "dot1xSuppEapolFramesRx=%u\n"
+			  "dot1xSuppEapolFramesTx=%u\n"
+			  "dot1xSuppEapolStartFramesTx=%u\n"
+			  "dot1xSuppEapolLogoffFramesTx=%u\n"
+			  "dot1xSuppEapolRespFramesTx=%u\n"
+			  "dot1xSuppEapolReqIdFramesRx=%u\n"
+			  "dot1xSuppEapolReqFramesRx=%u\n"
+			  "dot1xSuppInvalidEapolFramesRx=%u\n"
+			  "dot1xSuppEapLengthErrorFramesRx=%u\n"
+			  "dot1xSuppLastEapolFrameVersion=%u\n"
+			  "dot1xSuppLastEapolFrameSource=" MACSTR "\n",
+			  sm->dot1xSuppEapolFramesRx,
+			  sm->dot1xSuppEapolFramesTx,
+			  sm->dot1xSuppEapolStartFramesTx,
+			  sm->dot1xSuppEapolLogoffFramesTx,
+			  sm->dot1xSuppEapolRespFramesTx,
+			  sm->dot1xSuppEapolReqIdFramesRx,
+			  sm->dot1xSuppEapolReqFramesRx,
+			  sm->dot1xSuppInvalidEapolFramesRx,
+			  sm->dot1xSuppEapLengthErrorFramesRx,
+			  sm->dot1xSuppLastEapolFrameVersion,
+			  MAC2STR(sm->dot1xSuppLastEapolFrameSource));
+
+	if (ret < 0 || (size_t) ret >= buflen - len)
+		return len;
+	len += ret;
+
 	return len;
 }
+#endif /* CONFIG_CTRL_IFACE */
 
 
 /**
@@ -1092,8 +1123,9 @@
 {
 	const struct ieee802_1x_hdr *hdr;
 	const struct ieee802_1x_eapol_key *key;
-	int plen, data_len;
+	int data_len;
 	int res = 1;
+	size_t plen;
 
 	if (sm == NULL)
 		return 0;
@@ -1104,7 +1136,7 @@
 	}
 	hdr = (const struct ieee802_1x_hdr *) buf;
 	sm->dot1xSuppLastEapolFrameVersion = hdr->version;
-	memcpy(sm->dot1xSuppLastEapolFrameSource, src, ETH_ALEN);
+	os_memcpy(sm->dot1xSuppLastEapolFrameSource, src, ETH_ALEN);
 	if (hdr->version < EAPOL_VERSION) {
 		/* TODO: backwards compatibility */
 	}
@@ -1124,14 +1156,14 @@
 			 */
 			eapol_sm_abort_cached(sm);
 		}
-		free(sm->eapReqData);
+		os_free(sm->eapReqData);
 		sm->eapReqDataLen = plen;
-		sm->eapReqData = malloc(sm->eapReqDataLen);
+		sm->eapReqData = os_malloc(sm->eapReqDataLen);
 		if (sm->eapReqData) {
 			wpa_printf(MSG_DEBUG, "EAPOL: Received EAP-Packet "
 				   "frame");
-			memcpy(sm->eapReqData, (u8 *) (hdr + 1),
-			       sm->eapReqDataLen);
+			os_memcpy(sm->eapReqData, (u8 *) (hdr + 1),
+				  sm->eapReqDataLen);
 			sm->eapolEap = TRUE;
 			eapol_sm_step(sm);
 		}
@@ -1156,12 +1188,12 @@
 				   "EAPOL-Key type %d", key->type);
 			break;
 		}
-		free(sm->last_rx_key);
-		sm->last_rx_key = malloc(data_len);
+		os_free(sm->last_rx_key);
+		sm->last_rx_key = os_malloc(data_len);
 		if (sm->last_rx_key) {
 			wpa_printf(MSG_DEBUG, "EAPOL: Received EAPOL-Key "
 				   "frame");
-			memcpy(sm->last_rx_key, buf, data_len);
+			os_memcpy(sm->last_rx_key, buf, data_len);
 			sm->last_rx_key_len = data_len;
 			sm->rxKey = TRUE;
 			eapol_sm_step(sm);
@@ -1330,7 +1362,7 @@
 		return -1;
 	if (len > eap_len)
 		return eap_len;
-	memcpy(key, eap_key, len);
+	os_memcpy(key, eap_key, len);
 	return 0;
 }
 
@@ -1398,7 +1430,13 @@
 	sm->cached_pmk = FALSE;
 	sm->SUPP_PAE_state = SUPP_PAE_CONNECTING;
 	sm->suppPortStatus = Unauthorized;
-	sm->eapRestart= TRUE;
+
+	/* Make sure we do not start sending EAPOL-Start frames first, but
+	 * instead move to RESTART state to start EAPOL authentication. */
+	sm->startWhen = 3;
+
+	if (sm->ctx->aborted_cached)
+		sm->ctx->aborted_cached(sm->ctx->ctx);
 }
 
 
@@ -1505,6 +1543,17 @@
 }
 
 
+/**
+ * eapol_sm_invalidate_cached_session - Mark cached EAP session data invalid
+ * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
+ */
+void eapol_sm_invalidate_cached_session(struct eapol_sm *sm)
+{
+	if (sm)
+		eap_invalidate_cached_session(sm->eap);
+}
+
+
 static struct wpa_ssid * eapol_sm_get_config(void *ctx)
 {
 	struct eapol_sm *sm = ctx;
@@ -1638,16 +1687,32 @@
 }
 
 
+static void eapol_sm_notify_pending(void *ctx)
+{
+	struct eapol_sm *sm = ctx;
+	if (sm == NULL)
+		return;
+	if (sm->eapReqData && !sm->eapReq) {
+		wpa_printf(MSG_DEBUG, "EAPOL: received notification from EAP "
+			   "state machine - retrying pending EAP Request");
+		sm->eapolEap = TRUE;
+		sm->eapReq = TRUE;
+		eapol_sm_step(sm);
+	}
+}
+
+
 static struct eapol_callbacks eapol_cb =
 {
-	.get_config = eapol_sm_get_config,
-	.get_bool = eapol_sm_get_bool,
-	.set_bool = eapol_sm_set_bool,
-	.get_int = eapol_sm_get_int,
-	.set_int = eapol_sm_set_int,
-	.get_eapReqData = eapol_sm_get_eapReqData,
-	.set_config_blob = eapol_sm_set_config_blob,
-	.get_config_blob = eapol_sm_get_config_blob,
+	eapol_sm_get_config,
+	eapol_sm_get_bool,
+	eapol_sm_set_bool,
+	eapol_sm_get_int,
+	eapol_sm_set_int,
+	eapol_sm_get_eapReqData,
+	eapol_sm_set_config_blob,
+	eapol_sm_get_config_blob,
+	eapol_sm_notify_pending
 };
 
 
@@ -1663,10 +1728,9 @@
 {
 	struct eapol_sm *sm;
 	struct eap_config conf;
-	sm = malloc(sizeof(*sm));
+	sm = os_zalloc(sizeof(*sm));
 	if (sm == NULL)
 		return NULL;
-	memset(sm, 0, sizeof(*sm));
 	sm->ctx = ctx;
 
 	sm->portControl = Auto;
@@ -1679,14 +1743,14 @@
 	/* Supplicant Backend state machine */
 	sm->authPeriod = 30;
 
-	memset(&conf, 0, sizeof(conf));
+	os_memset(&conf, 0, sizeof(conf));
 	conf.opensc_engine_path = ctx->opensc_engine_path;
 	conf.pkcs11_engine_path = ctx->pkcs11_engine_path;
 	conf.pkcs11_module_path = ctx->pkcs11_module_path;
 
 	sm->eap = eap_sm_init(sm, &eapol_cb, sm->ctx->msg_ctx, &conf);
 	if (sm->eap == NULL) {
-		free(sm);
+		os_free(sm);
 		return NULL;
 	}
 
@@ -1715,8 +1779,8 @@
 	eloop_cancel_timeout(eapol_sm_step_timeout, NULL, sm);
 	eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm);
 	eap_sm_deinit(sm->eap);
-	free(sm->last_rx_key);
-	free(sm->eapReqData);
-	free(sm->ctx);
-	free(sm);
+	os_free(sm->last_rx_key);
+	os_free(sm->eapReqData);
+	os_free(sm->ctx);
+	os_free(sm);
 }
Index: ctrl_iface.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/ctrl_iface.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/ctrl_iface.c -L contrib/wpa_supplicant/ctrl_iface.c -u -r1.2 -r1.3
--- contrib/wpa_supplicant/ctrl_iface.c
+++ contrib/wpa_supplicant/ctrl_iface.c
@@ -1,6 +1,6 @@
 /*
- * WPA Supplicant / UNIX domain and UDP socket -based control interface
- * Copyright (c) 2004-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * WPA Supplicant / Control interface (shared code for all backends)
+ * Copyright (c) 2004-2006, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -12,20 +12,7 @@
  * See README and COPYING for more details.
  */
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
-#ifndef CONFIG_NATIVE_WINDOWS
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <sys/un.h>
-#include <sys/uio.h>
-#endif /* CONFIG_NATIVE_WINDOWS */
+#include "includes.h"
 
 #include "common.h"
 #include "eloop.h"
@@ -37,31 +24,13 @@
 #include "ctrl_iface.h"
 #include "l2_packet.h"
 #include "preauth.h"
+#include "pmksa_cache.h"
 #include "wpa_ctrl.h"
 #include "eap.h"
 
 
-#ifdef CONFIG_CTRL_IFACE_UDP
-#define CTRL_IFACE_SOCK struct sockaddr_in
-#else /* CONFIG_CTRL_IFACE_UDP */
-#define CTRL_IFACE_SOCK struct sockaddr_un
-#endif /* CONFIG_CTRL_IFACE_UDP */
-
-
-/**
- * struct wpa_ctrl_dst - Internal data structure of control interface monitors
- *
- * This structure is used to store information about registered control
- * interface monitors into struct wpa_supplicant. This data is private to
- * ctrl_iface.c and should not be touched directly from other files.
- */
-struct wpa_ctrl_dst {
-	struct wpa_ctrl_dst *next;
-	CTRL_IFACE_SOCK addr;
-	socklen_t addrlen;
-	int debug_level;
-	int errors;
-};
+static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
+						  char *buf, int len);
 
 
 static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
@@ -70,33 +39,34 @@
 	char *value;
 	int ret = 0;
 
-	value = strchr(cmd, ' ');
+	value = os_strchr(cmd, ' ');
 	if (value == NULL)
 		return -1;
 	*value++ = '\0';
 
 	wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
-	if (strcasecmp(cmd, "EAPOL::heldPeriod") == 0) {
+	if (os_strcasecmp(cmd, "EAPOL::heldPeriod") == 0) {
 		eapol_sm_configure(wpa_s->eapol,
 				   atoi(value), -1, -1, -1);
-	} else if (strcasecmp(cmd, "EAPOL::authPeriod") == 0) {
+	} else if (os_strcasecmp(cmd, "EAPOL::authPeriod") == 0) {
 		eapol_sm_configure(wpa_s->eapol,
 				   -1, atoi(value), -1, -1);
-	} else if (strcasecmp(cmd, "EAPOL::startPeriod") == 0) {
+	} else if (os_strcasecmp(cmd, "EAPOL::startPeriod") == 0) {
 		eapol_sm_configure(wpa_s->eapol,
 				   -1, -1, atoi(value), -1);
-	} else if (strcasecmp(cmd, "EAPOL::maxStart") == 0) {
+	} else if (os_strcasecmp(cmd, "EAPOL::maxStart") == 0) {
 		eapol_sm_configure(wpa_s->eapol,
 				   -1, -1, -1, atoi(value));
-	} else if (strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) {
+	} else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) {
 		if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
 				     atoi(value)))
 			ret = -1;
-	} else if (strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") == 0) {
+	} else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") ==
+		   0) {
 		if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
 				     atoi(value)))
 			ret = -1;
-	} else if (strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) {
+	} else if (os_strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) {
 		if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, atoi(value)))
 			ret = -1;
 	} else
@@ -126,129 +96,48 @@
 }
 
 
-static int wpa_supplicant_ctrl_iface_attach(struct wpa_supplicant *wpa_s,
-					    CTRL_IFACE_SOCK *from,
-					    socklen_t fromlen)
-{
-	struct wpa_ctrl_dst *dst;
-
-	dst = malloc(sizeof(*dst));
-	if (dst == NULL)
-		return -1;
-	memset(dst, 0, sizeof(*dst));
-	memcpy(&dst->addr, from, sizeof(CTRL_IFACE_SOCK));
-	dst->addrlen = fromlen;
-	dst->debug_level = MSG_INFO;
-	dst->next = wpa_s->ctrl_dst;
-	wpa_s->ctrl_dst = dst;
-#ifdef CONFIG_CTRL_IFACE_UDP
-	wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor attached %s:%d",
-		   inet_ntoa(from->sin_addr), ntohs(from->sin_port));
-#else /* CONFIG_CTRL_IFACE_UDP */
-	wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached",
-		    (u8 *) from->sun_path, fromlen);
-#endif /* CONFIG_CTRL_IFACE_UDP */
-	return 0;
-}
-
+#ifdef CONFIG_PEERKEY
+/* MLME-STKSTART.request(peer) */
+static int wpa_supplicant_ctrl_iface_stkstart(
+	struct wpa_supplicant *wpa_s, char *addr)
+{
+	u8 peer[ETH_ALEN];
 
-static int wpa_supplicant_ctrl_iface_detach(struct wpa_supplicant *wpa_s,
-					    CTRL_IFACE_SOCK *from,
-					    socklen_t fromlen)
-{
-	struct wpa_ctrl_dst *dst, *prev = NULL;
-
-	dst = wpa_s->ctrl_dst;
-	while (dst) {
-#ifdef CONFIG_CTRL_IFACE_UDP
-		if (from->sin_addr.s_addr == dst->addr.sin_addr.s_addr &&
-		    from->sin_port == dst->addr.sin_port) {
-			if (prev == NULL)
-				wpa_s->ctrl_dst = dst->next;
-			else
-				prev->next = dst->next;
-			free(dst);
-			wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor detached "
-				   "%s:%d", inet_ntoa(from->sin_addr),
-				   ntohs(from->sin_port));
-			return 0;
-		}
-#else /* CONFIG_CTRL_IFACE_UDP */
-		if (fromlen == dst->addrlen &&
-		    memcmp(from->sun_path, dst->addr.sun_path, fromlen) == 0) {
-			if (prev == NULL)
-				wpa_s->ctrl_dst = dst->next;
-			else
-				prev->next = dst->next;
-			free(dst);
-			wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor detached",
-				    (u8 *) from->sun_path, fromlen);
-			return 0;
-		}
-#endif /* CONFIG_CTRL_IFACE_UDP */
-		prev = dst;
-		dst = dst->next;
+	if (hwaddr_aton(addr, peer)) {
+		wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART: invalid "
+			   "address '%s'", peer);
+		return -1;
 	}
-	return -1;
-}
 
+	wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART " MACSTR,
+		   MAC2STR(peer));
 
-static int wpa_supplicant_ctrl_iface_level(struct wpa_supplicant *wpa_s,
-					   CTRL_IFACE_SOCK *from,
-					   socklen_t fromlen,
-					   char *level)
-{
-	struct wpa_ctrl_dst *dst;
-
-	wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", level);
-
-	dst = wpa_s->ctrl_dst;
-	while (dst) {
-#ifdef CONFIG_CTRL_IFACE_UDP
-		if (from->sin_addr.s_addr == dst->addr.sin_addr.s_addr &&
-		    from->sin_port == dst->addr.sin_port) {
-			wpa_printf(MSG_DEBUG, "CTRL_IFACE changed monitor "
-				   "level %s:%d", inet_ntoa(from->sin_addr),
-				   ntohs(from->sin_port));
-			dst->debug_level = atoi(level);
-			return 0;
-		}
-#else /* CONFIG_CTRL_IFACE_UDP */
-		if (fromlen == dst->addrlen &&
-		    memcmp(from->sun_path, dst->addr.sun_path, fromlen) == 0) {
-			wpa_hexdump(MSG_DEBUG, "CTRL_IFACE changed monitor "
-				    "level", (u8 *) from->sun_path, fromlen);
-			dst->debug_level = atoi(level);
-			return 0;
-		}
-#endif /* CONFIG_CTRL_IFACE_UDP */
-		dst = dst->next;
-	}
-
-	return -1;
+	return wpa_sm_stkstart(wpa_s->wpa, peer);
 }
+#endif /* CONFIG_PEERKEY */
 
 
 static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s,
 					      char *rsp)
 {
+#ifdef IEEE8021X_EAPOL
 	char *pos, *id_pos;
 	int id;
 	struct wpa_ssid *ssid;
 
-	pos = strchr(rsp, '-');
+	pos = os_strchr(rsp, '-');
 	if (pos == NULL)
 		return -1;
 	*pos++ = '\0';
 	id_pos = pos;
-	pos = strchr(pos, ':');
+	pos = os_strchr(pos, ':');
 	if (pos == NULL)
 		return -1;
 	*pos++ = '\0';
 	id = atoi(id_pos);
 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id);
 	wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
-			      (u8 *) pos, strlen(pos));
+			      (u8 *) pos, os_strlen(pos));
 
 	ssid = wpa_config_get_network(wpa_s->conf, id);
 	if (ssid == NULL) {
@@ -257,43 +146,43 @@
 		return -1;
 	}
 
-	if (strcmp(rsp, "IDENTITY") == 0) {
-		free(ssid->identity);
-		ssid->identity = (u8 *) strdup(pos);
-		ssid->identity_len = strlen(pos);
+	if (os_strcmp(rsp, "IDENTITY") == 0) {
+		os_free(ssid->identity);
+		ssid->identity = (u8 *) os_strdup(pos);
+		ssid->identity_len = os_strlen(pos);
 		ssid->pending_req_identity = 0;
 		if (ssid == wpa_s->current_ssid)
 			wpa_s->reassociate = 1;
-	} else if (strcmp(rsp, "PASSWORD") == 0) {
-		free(ssid->password);
-		ssid->password = (u8 *) strdup(pos);
-		ssid->password_len = strlen(pos);
+	} else if (os_strcmp(rsp, "PASSWORD") == 0) {
+		os_free(ssid->password);
+		ssid->password = (u8 *) os_strdup(pos);
+		ssid->password_len = os_strlen(pos);
 		ssid->pending_req_password = 0;
 		if (ssid == wpa_s->current_ssid)
 			wpa_s->reassociate = 1;
-	} else if (strcmp(rsp, "NEW_PASSWORD") == 0) {
-		free(ssid->new_password);
-		ssid->new_password = (u8 *) strdup(pos);
-		ssid->new_password_len = strlen(pos);
+	} else if (os_strcmp(rsp, "NEW_PASSWORD") == 0) {
+		os_free(ssid->new_password);
+		ssid->new_password = (u8 *) os_strdup(pos);
+		ssid->new_password_len = os_strlen(pos);
 		ssid->pending_req_new_password = 0;
 		if (ssid == wpa_s->current_ssid)
 			wpa_s->reassociate = 1;
-	} else if (strcmp(rsp, "PIN") == 0) {
-		free(ssid->pin);
-		ssid->pin = strdup(pos);
+	} else if (os_strcmp(rsp, "PIN") == 0) {
+		os_free(ssid->pin);
+		ssid->pin = os_strdup(pos);
 		ssid->pending_req_pin = 0;
 		if (ssid == wpa_s->current_ssid)
 			wpa_s->reassociate = 1;
-	} else if (strcmp(rsp, "OTP") == 0) {
-		free(ssid->otp);
-		ssid->otp = (u8 *) strdup(pos);
-		ssid->otp_len = strlen(pos);
-		free(ssid->pending_req_otp);
+	} else if (os_strcmp(rsp, "OTP") == 0) {
+		os_free(ssid->otp);
+		ssid->otp = (u8 *) os_strdup(pos);
+		ssid->otp_len = os_strlen(pos);
+		os_free(ssid->pending_req_otp);
 		ssid->pending_req_otp = NULL;
 		ssid->pending_req_otp_len = 0;
-	} else if (strcmp(rsp, "PASSPHRASE") == 0) {
-		free(ssid->private_key_passwd);
-		ssid->private_key_passwd = (u8 *) strdup(pos);
+	} else if (os_strcmp(rsp, "PASSPHRASE") == 0) {
+		os_free(ssid->private_key_passwd);
+		ssid->private_key_passwd = (u8 *) os_strdup(pos);
 		ssid->pending_req_passphrase = 0;
 		if (ssid == wpa_s->current_ssid)
 			wpa_s->reassociate = 1;
@@ -303,6 +192,10 @@
 	}
 
 	return 0;
+#else /* IEEE8021X_EAPOL */
+	wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included");
+	return -1;
+#endif /* IEEE8021X_EAPOL */
 }
 
 
@@ -311,29 +204,62 @@
 					    char *buf, size_t buflen)
 {
 	char *pos, *end, tmp[30];
-	int res, verbose;
+	int res, verbose, ret;
 
-	verbose = strcmp(params, "-VERBOSE") == 0;
+	verbose = os_strcmp(params, "-VERBOSE") == 0;
 	pos = buf;
 	end = buf + buflen;
 	if (wpa_s->wpa_state >= WPA_ASSOCIATED) {
-		pos += snprintf(pos, end - pos, "bssid=" MACSTR "\n",
-				MAC2STR(wpa_s->bssid));
-		if (wpa_s->current_ssid) {
-			pos += snprintf(pos, end - pos, "ssid=%s\n",
-					wpa_ssid_txt(wpa_s->current_ssid->ssid,
-						     wpa_s->current_ssid->
-						     ssid_len));
+		struct wpa_ssid *ssid = wpa_s->current_ssid;
+		ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
+				  MAC2STR(wpa_s->bssid));
+		if (ret < 0 || ret >= end - pos)
+			return pos - buf;
+		pos += ret;
+		if (ssid) {
+			u8 *_ssid = ssid->ssid;
+			size_t ssid_len = ssid->ssid_len;
+			u8 ssid_buf[MAX_SSID_LEN];
+			if (ssid_len == 0) {
+				int _res = wpa_drv_get_ssid(wpa_s, ssid_buf);
+				if (_res < 0)
+					ssid_len = 0;
+				else
+					ssid_len = _res;
+				_ssid = ssid_buf;
+			}
+			ret = os_snprintf(pos, end - pos, "ssid=%s\nid=%d\n",
+					  wpa_ssid_txt(_ssid, ssid_len),
+					  ssid->id);
+			if (ret < 0 || ret >= end - pos)
+				return pos - buf;
+			pos += ret;
+
+			if (ssid->id_str) {
+				ret = os_snprintf(pos, end - pos,
+						  "id_str=%s\n",
+						  ssid->id_str);
+				if (ret < 0 || ret >= end - pos)
+					return pos - buf;
+				pos += ret;
+			}
 		}
 
 		pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose);
 	}
-	pos += snprintf(pos, end - pos, "wpa_state=%s\n",
-			wpa_supplicant_state_txt(wpa_s->wpa_state));
+	ret = os_snprintf(pos, end - pos, "wpa_state=%s\n",
+			  wpa_supplicant_state_txt(wpa_s->wpa_state));
+	if (ret < 0 || ret >= end - pos)
+		return pos - buf;
+	pos += ret;
 
 	if (wpa_s->l2 &&
-	    l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0)
-		pos += snprintf(pos, end - pos, "ip_address=%s\n", tmp);
+	    l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0) {
+		ret = os_snprintf(pos, end - pos, "ip_address=%s\n", tmp);
+		if (ret < 0 || ret >= end - pos)
+			return pos - buf;
+		pos += ret;
+	}
 
 	if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X ||
 	    wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
@@ -360,7 +286,7 @@
 	u8 bssid[ETH_ALEN];
 
 	/* cmd: "<network id> <BSSID>" */
-	pos = strchr(cmd, ' ');
+	pos = os_strchr(cmd, ' ');
 	if (pos == NULL)
 		return -1;
 	*pos++ = '\0';
@@ -378,9 +304,9 @@
 		return -1;
 	}
 
-	memcpy(ssid->bssid, bssid, ETH_ALEN);
+	os_memcpy(ssid->bssid, bssid, ETH_ALEN);
 	ssid->bssid_set =
-		memcmp(bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) != 0;
+		os_memcmp(bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) != 0;
 		
 
 	return 0;
@@ -392,26 +318,44 @@
 {
 	char *pos, *end;
 	struct wpa_ssid *ssid;
+	int ret;
 
 	pos = buf;
 	end = buf + buflen;
-	pos += snprintf(pos, end - pos, "network id / ssid / bssid / flags\n");
+	ret = os_snprintf(pos, end - pos,
+			  "network id / ssid / bssid / flags\n");
+	if (ret < 0 || ret >= end - pos)
+		return pos - buf;
+	pos += ret;
 
 	ssid = wpa_s->conf->ssid;
 	while (ssid) {
-		pos += snprintf(pos, end - pos, "%d\t%s",
-				ssid->id,
-				wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
+		ret = os_snprintf(pos, end - pos, "%d\t%s",
+				  ssid->id,
+				  wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
+		if (ret < 0 || ret >= end - pos)
+			return pos - buf;
+		pos += ret;
 		if (ssid->bssid_set) {
-			pos += snprintf(pos, end - pos, "\t" MACSTR,
-					MAC2STR(ssid->bssid));
+			ret = os_snprintf(pos, end - pos, "\t" MACSTR,
+					  MAC2STR(ssid->bssid));
 		} else {
-			pos += snprintf(pos, end - pos, "\tany");
+			ret = os_snprintf(pos, end - pos, "\tany");
 		}
-		pos += snprintf(pos, end - pos, "\t%s%s",
-				ssid == wpa_s->current_ssid ? "[CURRENT]" : "",
-				ssid->disabled ? "[DISABLED]" : "");
-		pos += snprintf(pos, end - pos, "\n");
+		if (ret < 0 || ret >= end - pos)
+			return pos - buf;
+		pos += ret;
+		ret = os_snprintf(pos, end - pos, "\t%s%s",
+				  ssid == wpa_s->current_ssid ?
+				  "[CURRENT]" : "",
+				  ssid->disabled ? "[DISABLED]" : "");
+		if (ret < 0 || ret >= end - pos)
+			return pos - buf;
+		pos += ret;
+		ret = os_snprintf(pos, end - pos, "\n");
+		if (ret < 0 || ret >= end - pos)
+			return pos - buf;
+		pos += ret;
 
 		ssid = ssid->next;
 	}
@@ -422,66 +366,106 @@
 
 static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher)
 {
-	int first = 1;
-	pos += snprintf(pos, end - pos, "-");
+	int first = 1, ret;
+	ret = os_snprintf(pos, end - pos, "-");
+	if (ret < 0 || ret >= end - pos)
+		return pos;
+	pos += ret;
 	if (cipher & WPA_CIPHER_NONE) {
-		pos += snprintf(pos, end - pos, "%sNONE", first ? "" : "+");
+		ret = os_snprintf(pos, end - pos, "%sNONE", first ? "" : "+");
+		if (ret < 0 || ret >= end - pos)
+			return pos;
+		pos += ret;
 		first = 0;
 	}
 	if (cipher & WPA_CIPHER_WEP40) {
-		pos += snprintf(pos, end - pos, "%sWEP40", first ? "" : "+");
+		ret = os_snprintf(pos, end - pos, "%sWEP40", first ? "" : "+");
+		if (ret < 0 || ret >= end - pos)
+			return pos;
+		pos += ret;
 		first = 0;
 	}
 	if (cipher & WPA_CIPHER_WEP104) {
-		pos += snprintf(pos, end - pos, "%sWEP104", first ? "" : "+");
+		ret = os_snprintf(pos, end - pos, "%sWEP104",
+				  first ? "" : "+");
+		if (ret < 0 || ret >= end - pos)
+			return pos;
+		pos += ret;
 		first = 0;
 	}
 	if (cipher & WPA_CIPHER_TKIP) {
-		pos += snprintf(pos, end - pos, "%sTKIP", first ? "" : "+");
+		ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : "+");
+		if (ret < 0 || ret >= end - pos)
+			return pos;
+		pos += ret;
 		first = 0;
 	}
 	if (cipher & WPA_CIPHER_CCMP) {
-		pos += snprintf(pos, end - pos, "%sCCMP", first ? "" : "+");
+		ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : "+");
+		if (ret < 0 || ret >= end - pos)
+			return pos;
+		pos += ret;
 		first = 0;
 	}
 	return pos;
 }
 
 
-static char * wpa_supplicant_ie_txt(struct wpa_supplicant *wpa_s,
-				    char *pos, char *end, const char *proto,
+static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto,
 				    const u8 *ie, size_t ie_len)
 {
 	struct wpa_ie_data data;
-	int first;
+	int first, ret;
 
-	pos += snprintf(pos, end - pos, "[%s-", proto);
+	ret = os_snprintf(pos, end - pos, "[%s-", proto);
+	if (ret < 0 || ret >= end - pos)
+		return pos;
+	pos += ret;
 
 	if (wpa_parse_wpa_ie(ie, ie_len, &data) < 0) {
-		pos += snprintf(pos, end - pos, "?]");
+		ret = os_snprintf(pos, end - pos, "?]");
+		if (ret < 0 || ret >= end - pos)
+			return pos;
+		pos += ret;
 		return pos;
 	}
 
 	first = 1;
 	if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
-		pos += snprintf(pos, end - pos, "%sEAP", first ? "" : "+");
+		ret = os_snprintf(pos, end - pos, "%sEAP", first ? "" : "+");
+		if (ret < 0 || ret >= end - pos)
+			return pos;
+		pos += ret;
 		first = 0;
 	}
 	if (data.key_mgmt & WPA_KEY_MGMT_PSK) {
-		pos += snprintf(pos, end - pos, "%sPSK", first ? "" : "+");
+		ret = os_snprintf(pos, end - pos, "%sPSK", first ? "" : "+");
+		if (ret < 0 || ret >= end - pos)
+			return pos;
+		pos += ret;
 		first = 0;
 	}
 	if (data.key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
-		pos += snprintf(pos, end - pos, "%sNone", first ? "" : "+");
+		ret = os_snprintf(pos, end - pos, "%sNone", first ? "" : "+");
+		if (ret < 0 || ret >= end - pos)
+			return pos;
+		pos += ret;
 		first = 0;
 	}
 
 	pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher);
 
-	if (data.capabilities & WPA_CAPABILITY_PREAUTH)
-		pos += snprintf(pos, end - pos, "-preauth");
+	if (data.capabilities & WPA_CAPABILITY_PREAUTH) {
+		ret = os_snprintf(pos, end - pos, "-preauth");
+		if (ret < 0 || ret >= end - pos)
+			return pos;
+		pos += ret;
+	}
 
-	pos += snprintf(pos, end - pos, "]");
+	ret = os_snprintf(pos, end - pos, "]");
+	if (ret < 0 || ret >= end - pos)
+		return pos;
+	pos += ret;
 
 	return pos;
 }
@@ -492,41 +476,63 @@
 {
 	char *pos, *end;
 	struct wpa_scan_result *res;
-	int i;
+	int i, ret;
 
 	if (wpa_s->scan_results == NULL &&
 	    wpa_supplicant_get_scan_results(wpa_s) < 0)
 		return 0;
+	if (wpa_s->scan_results == NULL)
+		return 0;
 
 	pos = buf;
 	end = buf + buflen;
-	pos += snprintf(pos, end - pos, "bssid / frequency / signal level / "
-			"flags / ssid\n");
+	ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / "
+			  "flags / ssid\n");
+	if (ret < 0 || ret >= end - pos)
+		return pos - buf;
+	pos += ret;
 
 	for (i = 0; i < wpa_s->num_scan_results; i++) {
 		res = &wpa_s->scan_results[i];
-		pos += snprintf(pos, end - pos, MACSTR "\t%d\t%d\t",
-				MAC2STR(res->bssid), res->freq, res->level);
+		ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t",
+				  MAC2STR(res->bssid), res->freq, res->level);
+		if (ret < 0 || ret >= end - pos)
+			return pos - buf;
+		pos += ret;
 		if (res->wpa_ie_len) {
-			pos = wpa_supplicant_ie_txt(wpa_s, pos, end, "WPA",
+			pos = wpa_supplicant_ie_txt(pos, end, "WPA",
 						    res->wpa_ie,
 						    res->wpa_ie_len);
 		}
 		if (res->rsn_ie_len) {
-			pos = wpa_supplicant_ie_txt(wpa_s, pos, end, "WPA2",
+			pos = wpa_supplicant_ie_txt(pos, end, "WPA2",
 						    res->rsn_ie,
 						    res->rsn_ie_len);
 		}
 		if (!res->wpa_ie_len && !res->rsn_ie_len &&
-		    res->caps & IEEE80211_CAP_PRIVACY)
-			pos += snprintf(pos, end - pos, "[WEP]");
-		if (res->caps & IEEE80211_CAP_IBSS)
-			pos += snprintf(pos, end - pos, "[IBSS]");
-
-		pos += snprintf(pos, end - pos, "\t%s",
-				wpa_ssid_txt(res->ssid, res->ssid_len));
-
-		pos += snprintf(pos, end - pos, "\n");
+		    res->caps & IEEE80211_CAP_PRIVACY) {
+			ret = os_snprintf(pos, end - pos, "[WEP]");
+			if (ret < 0 || ret >= end - pos)
+				return pos - buf;
+			pos += ret;
+		}
+		if (res->caps & IEEE80211_CAP_IBSS) {
+			ret = os_snprintf(pos, end - pos, "[IBSS]");
+			if (ret < 0 || ret >= end - pos)
+				return pos - buf;
+			pos += ret;
+		}
+
+		ret = os_snprintf(pos, end - pos, "\t%s",
+				  wpa_ssid_txt(res->ssid, res->ssid_len));
+		if (ret < 0 || ret >= end - pos)
+			return pos - buf;
+		pos += ret;
+
+		ret = os_snprintf(pos, end - pos, "\n");
+		if (ret < 0 || ret >= end - pos)
+			return pos - buf;
+		pos += ret;
 	}
 
 	return pos - buf;
@@ -540,7 +546,7 @@
 	struct wpa_ssid *ssid;
 
 	/* cmd: "<network id>" or "any" */
-	if (strcmp(cmd, "any") == 0) {
+	if (os_strcmp(cmd, "any") == 0) {
 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any");
 		ssid = wpa_s->conf->ssid;
 		while (ssid) {
@@ -637,6 +643,7 @@
 	struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
 {
 	struct wpa_ssid *ssid;
+	int ret;
 
 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK");
 
@@ -646,7 +653,10 @@
 	ssid->disabled = 1;
 	wpa_config_set_network_defaults(ssid);
 
-	return snprintf(buf, buflen, "%d\n", ssid->id);
+	ret = os_snprintf(buf, buflen, "%d\n", ssid->id);
+	if (ret < 0 || (size_t) ret >= buflen)
+		return -1;
+	return ret;
 }
 
 
@@ -668,8 +678,15 @@
 		return -1;
 	}
 
-	if (ssid == wpa_s->current_ssid)
+	if (ssid == wpa_s->current_ssid) {
+		/*
+		 * Invalidate the EAP session cache if the current network is
+		 * removed.
+		 */
+		eapol_sm_invalidate_cached_session(wpa_s->eapol);
+
 		wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING);
+	}
 
 	return 0;
 }
@@ -683,19 +700,21 @@
 	char *name, *value;
 
 	/* cmd: "<network id> <variable name> <value>" */
-	name = strchr(cmd, ' ');
+	name = os_strchr(cmd, ' ');
 	if (name == NULL)
 		return -1;
 	*name++ = '\0';
 
-	value = strchr(name, ' ');
+	value = os_strchr(name, ' ');
 	if (value == NULL)
 		return -1;
 	*value++ = '\0';
 
 	id = atoi(cmd);
-	wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s' "
-		   "value='%s'", id, name, value);
+	wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'",
+		   id, name);
+	wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
+			      (u8 *) value, os_strlen(value));
 
 	ssid = wpa_config_get_network(wpa_s->conf, id);
 	if (ssid == NULL) {
@@ -706,12 +725,21 @@
 
 	if (wpa_config_set(ssid, name, value, 0) < 0) {
 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network "
-			   "variable '%s' to '%s'", name, value);
+			   "variable '%s'", name);
 		return -1;
 	}
 
-	if ((strcmp(name, "psk") == 0 && value[0] == '"' && ssid->ssid_len) ||
-	    (strcmp(name, "ssid") == 0 && ssid->passphrase))
+	if (wpa_s->current_ssid == ssid) {
+		/*
+		 * Invalidate the EAP session cache if anything in the current
+		 * configuration changes.
+		 */
+		eapol_sm_invalidate_cached_session(wpa_s->eapol);
+	}
+
+	if ((os_strcmp(name, "psk") == 0 &&
+	     value[0] == '"' && ssid->ssid_len) ||
+	    (os_strcmp(name, "ssid") == 0 && ssid->passphrase))
 		wpa_config_update_psk(ssid);
 
 	return 0;
@@ -726,8 +754,8 @@
 	char *name, *value;
 
 	/* cmd: "<network id> <variable name>" */
-	name = strchr(cmd, ' ');
-	if (name == NULL)
+	name = os_strchr(cmd, ' ');
+	if (name == NULL || buflen == 0)
 		return -1;
 	*name++ = '\0';
 
@@ -742,18 +770,19 @@
 		return -1;
 	}
 
-	value = wpa_config_get(ssid, name);
+	value = wpa_config_get_no_key(ssid, name);
 	if (value == NULL) {
 		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network "
 			   "variable '%s'", name);
 		return -1;
 	}
 
-	snprintf(buf, buflen, "%s", value);
+	os_snprintf(buf, buflen, "%s", value);
+	buf[buflen - 1] = '\0';
 
-	free(value);
+	os_free(value);
 
-	return strlen(buf);
+	return os_strlen(buf);
 }
 
 
@@ -781,16 +810,28 @@
 
 
 static int wpa_supplicant_ctrl_iface_get_capability(
-	struct wpa_supplicant *wpa_s, const char *field, char *buf,
+	struct wpa_supplicant *wpa_s, const char *_field, char *buf,
 	size_t buflen)
 {
 	struct wpa_driver_capa capa;
-	int res, first = 1;
-	char *pos, *end;
+	int res, first = 1, ret;
+	char *pos, *end, *strict;
+	char field[30];
+
+	/* Determine whether or not strict checking was requested */
+	os_snprintf(field, sizeof(field), "%s", _field);
+	field[sizeof(field) - 1] = '\0';
+	strict = os_strchr(field, ' ');
+	if (strict != NULL) {
+		*strict++ = '\0';
+		if (os_strcmp(strict, "strict") != 0)
+			return -1;
+	}
 
-	wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s'", field);
+	wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s' %s",
+		field, strict ? strict : "");
 
-	if (strcmp(field, "eap") == 0) {
+	if (os_strcmp(field, "eap") == 0) {
 		return eap_get_names(buf, buflen);
 	}
 
@@ -799,124 +840,205 @@
 	pos = buf;
 	end = pos + buflen;
 
-	if (strcmp(field, "pairwise") == 0) {
-		if (res < 0)
-			return snprintf(buf, buflen, "CCMP TKIP NONE");
+	if (os_strcmp(field, "pairwise") == 0) {
+		if (res < 0) {
+			if (strict)
+				return 0;
+			ret = os_snprintf(buf, buflen, "CCMP TKIP NONE");
+			if (ret < 0 || (size_t) ret >= buflen)
+				return -1;
+			return ret;
+		}
 
 		if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
-			pos += snprintf(pos, end - pos, "%sCCMP",
-					first ? "" : " ");
+			ret = os_snprintf(pos, end - pos, "%sCCMP",
+					  first ? "" : " ");
+			if (ret < 0 || ret >= end - pos)
+				return pos - buf;
+			pos += ret;
 			first = 0;
 		}
 
 		if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
-			pos += snprintf(pos, end - pos, "%sTKIP",
-					first ? "" : " ");
+			ret = os_snprintf(pos, end - pos, "%sTKIP",
+					  first ? "" : " ");
+			if (ret < 0 || ret >= end - pos)
+				return pos - buf;
+			pos += ret;
 			first = 0;
 		}
 
 		if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
-			pos += snprintf(pos, end - pos, "%sNONE",
-					first ? "" : " ");
+			ret = os_snprintf(pos, end - pos, "%sNONE",
+					  first ? "" : " ");
+			if (ret < 0 || ret >= end - pos)
+				return pos - buf;
+			pos += ret;
 			first = 0;
 		}
 
 		return pos - buf;
 	}
 
-	if (strcmp(field, "group") == 0) {
-		if (res < 0)
-			return snprintf(buf, buflen, "CCMP TKIP WEP104 WEP40");
+	if (os_strcmp(field, "group") == 0) {
+		if (res < 0) {
+			if (strict)
+				return 0;
+			ret = os_snprintf(buf, buflen,
+					  "CCMP TKIP WEP104 WEP40");
+			if (ret < 0 || (size_t) ret >= buflen)
+				return -1;
+			return ret;
+		}
 
 		if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
-			pos += snprintf(pos, end - pos, "%sCCMP",
-					first ? "" : " ");
+			ret = os_snprintf(pos, end - pos, "%sCCMP",
+					  first ? "" : " ");
+			if (ret < 0 || ret >= end - pos)
+				return pos - buf;
+			pos += ret;
 			first = 0;
 		}
 
 		if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
-			pos += snprintf(pos, end - pos, "%sTKIP",
-					first ? "" : " ");
+			ret = os_snprintf(pos, end - pos, "%sTKIP",
+					  first ? "" : " ");
+			if (ret < 0 || ret >= end - pos)
+				return pos - buf;
+			pos += ret;
 			first = 0;
 		}
 
 		if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) {
-			pos += snprintf(pos, end - pos, "%sWEP104",
-					first ? "" : " ");
+			ret = os_snprintf(pos, end - pos, "%sWEP104",
+					  first ? "" : " ");
+			if (ret < 0 || ret >= end - pos)
+				return pos - buf;
+			pos += ret;
 			first = 0;
 		}
 
 		if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) {
-			pos += snprintf(pos, end - pos, "%sWEP40",
-					first ? "" : " ");
+			ret = os_snprintf(pos, end - pos, "%sWEP40",
+					  first ? "" : " ");
+			if (ret < 0 || ret >= end - pos)
+				return pos - buf;
+			pos += ret;
 			first = 0;
 		}
 
 		return pos - buf;
 	}
 
-	if (strcmp(field, "key_mgmt") == 0) {
+	if (os_strcmp(field, "key_mgmt") == 0) {
 		if (res < 0) {
-			return snprintf(buf, buflen, "WPA-PSK WPA-EAP "
-					"IEEE8021X WPA-NONE NONE");
+			if (strict)
+				return 0;
+			ret = os_snprintf(buf, buflen, "WPA-PSK WPA-EAP "
+					  "IEEE8021X WPA-NONE NONE");
+			if (ret < 0 || (size_t) ret >= buflen)
+				return -1;
+			return ret;
 		}
 
-		pos += snprintf(pos, end - pos, "NONE IEEE8021X");
+		ret = os_snprintf(pos, end - pos, "NONE IEEE8021X");
+		if (ret < 0 || ret >= end - pos)
+			return pos - buf;
+		pos += ret;
 
 		if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
-				     WPA_DRIVER_CAPA_KEY_MGMT_WPA2))
-			pos += snprintf(pos, end - pos, " WPA-EAP");
+				     WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
+			ret = os_snprintf(pos, end - pos, " WPA-EAP");
+			if (ret < 0 || ret >= end - pos)
+				return pos - buf;
+			pos += ret;
+		}
 
 		if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
-				     WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK))
-			pos += snprintf(pos, end - pos, " WPA-PSK");
+				     WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
+			ret = os_snprintf(pos, end - pos, " WPA-PSK");
+			if (ret < 0 || ret >= end - pos)
+				return pos - buf;
+			pos += ret;
+		}
 
-		if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE)
-			pos += snprintf(pos, end - pos, " WPA-NONE");
+		if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
+			ret = os_snprintf(pos, end - pos, " WPA-NONE");
+			if (ret < 0 || ret >= end - pos)
+				return pos - buf;
+			pos += ret;
+		}
 
 		return pos - buf;
 	}
 
-	if (strcmp(field, "proto") == 0) {
-		if (res < 0)
-			return snprintf(buf, buflen, "RSN WPA");
+	if (os_strcmp(field, "proto") == 0) {
+		if (res < 0) {
+			if (strict)
+				return 0;
+			ret = os_snprintf(buf, buflen, "RSN WPA");
+			if (ret < 0 || (size_t) ret >= buflen)
+				return -1;
+			return ret;
+		}
 
 		if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
 				     WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
-			pos += snprintf(pos, end - pos, "%sRSN",
-					first ? "" : " ");
+			ret = os_snprintf(pos, end - pos, "%sRSN",
+					  first ? "" : " ");
+			if (ret < 0 || ret >= end - pos)
+				return pos - buf;
+			pos += ret;
 			first = 0;
 		}
 
 		if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
 				     WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
-			pos += snprintf(pos, end - pos, "%sWPA",
-					first ? "" : " ");
+			ret = os_snprintf(pos, end - pos, "%sWPA",
+					  first ? "" : " ");
+			if (ret < 0 || ret >= end - pos)
+				return pos - buf;
+			pos += ret;
 			first = 0;
 		}
 
 		return pos - buf;
 	}
 
-	if (strcmp(field, "auth_alg") == 0) {
-		if (res < 0)
-			return snprintf(buf, buflen, "OPEN SHARED LEAP");
+	if (os_strcmp(field, "auth_alg") == 0) {
+		if (res < 0) {
+			if (strict)
+				return 0;
+			ret = os_snprintf(buf, buflen, "OPEN SHARED LEAP");
+			if (ret < 0 || (size_t) ret >= buflen)
+				return -1;
+			return ret;
+		}
 
 		if (capa.auth & (WPA_DRIVER_AUTH_OPEN)) {
-			pos += snprintf(pos, end - pos, "%sOPEN",
-					first ? "" : " ");
+			ret = os_snprintf(pos, end - pos, "%sOPEN",
+					  first ? "" : " ");
+			if (ret < 0 || ret >= end - pos)
+				return pos - buf;
+			pos += ret;
 			first = 0;
 		}
 
 		if (capa.auth & (WPA_DRIVER_AUTH_SHARED)) {
-			pos += snprintf(pos, end - pos, "%sSHARED",
-					first ? "" : " ");
+			ret = os_snprintf(pos, end - pos, "%sSHARED",
+					  first ? "" : " ");
+			if (ret < 0 || ret >= end - pos)
+				return pos - buf;
+			pos += ret;
 			first = 0;
 		}
 
 		if (capa.auth & (WPA_DRIVER_AUTH_LEAP)) {
-			pos += snprintf(pos, end - pos, "%sLEAP",
-					first ? "" : " ");
+			ret = os_snprintf(pos, end - pos, "%sLEAP",
+					  first ? "" : " ");
+			if (ret < 0 || ret >= end - pos)
+				return pos - buf;
+			pos += ret;
 			first = 0;
 		}
 
@@ -930,49 +1052,51 @@
 }
 
 
-static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx,
-					      void *sock_ctx)
+static int wpa_supplicant_ctrl_iface_ap_scan(
+	struct wpa_supplicant *wpa_s, char *cmd)
+{
+	int ap_scan = atoi(cmd);
+
+	if (ap_scan < 0 || ap_scan > 2)
+		return -1;
+	wpa_s->conf->ap_scan = ap_scan;
+	return 0;
+}
+
+
+char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
+					 char *buf, size_t *resp_len)
 {
-	struct wpa_supplicant *wpa_s = eloop_ctx;
-	char buf[256];
-	int res;
-	CTRL_IFACE_SOCK from;
-	socklen_t fromlen = sizeof(from);
 	char *reply;
 	const int reply_size = 2048;
+	int ctrl_rsp = 0;
 	int reply_len;
-	int new_attached = 0, ctrl_rsp = 0;
 
-	res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
-		       (struct sockaddr *) &from, &fromlen);
-	if (res < 0) {
-		perror("recvfrom(ctrl_iface)");
-		return;
-	}
-	buf[res] = '\0';
-	if (strncmp(buf, WPA_CTRL_RSP, strlen(WPA_CTRL_RSP)) == 0) {
+	if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 ||
+	    os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
 		wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface",
-				      (u8 *) buf, res);
+				      (const u8 *) buf, os_strlen(buf));
 	} else {
-		wpa_hexdump_ascii(MSG_DEBUG, "RX ctrl_iface", (u8 *) buf, res);
+		wpa_hexdump_ascii(MSG_DEBUG, "RX ctrl_iface",
+				  (const u8 *) buf, os_strlen(buf));
 	}
 
-	reply = malloc(reply_size);
+	reply = os_malloc(reply_size);
 	if (reply == NULL) {
-		sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
-		       fromlen);
-		return;
+		*resp_len = 1;
+		return NULL;
 	}
 
-	memcpy(reply, "OK\n", 3);
+	os_memcpy(reply, "OK\n", 3);
 	reply_len = 3;
 
-	if (strcmp(buf, "PING") == 0) {
-		memcpy(reply, "PONG\n", 5);
+	if (os_strcmp(buf, "PING") == 0) {
+		os_memcpy(reply, "PONG\n", 5);
 		reply_len = 5;
-	} else if (strcmp(buf, "MIB") == 0) {
+	} else if (os_strcmp(buf, "MIB") == 0) {
 		reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size);
 		if (reply_len >= 0) {
+			int res;
 			res = eapol_sm_get_mib(wpa_s->eapol, reply + reply_len,
 					       reply_size - reply_len);
 			if (res < 0)
@@ -980,452 +1104,105 @@
 			else
 				reply_len += res;
 		}
-	} else if (strncmp(buf, "STATUS", 6) == 0) {
+	} else if (os_strncmp(buf, "STATUS", 6) == 0) {
 		reply_len = wpa_supplicant_ctrl_iface_status(
 			wpa_s, buf + 6, reply, reply_size);
-	} else if (strcmp(buf, "PMKSA") == 0) {
+	} else if (os_strcmp(buf, "PMKSA") == 0) {
 		reply_len = pmksa_cache_list(wpa_s->wpa, reply, reply_size);
-	} else if (strncmp(buf, "SET ", 4) == 0) {
+	} else if (os_strncmp(buf, "SET ", 4) == 0) {
 		if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4))
 			reply_len = -1;
-	} else if (strcmp(buf, "LOGON") == 0) {
+	} else if (os_strcmp(buf, "LOGON") == 0) {
 		eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
-	} else if (strcmp(buf, "LOGOFF") == 0) {
+	} else if (os_strcmp(buf, "LOGOFF") == 0) {
 		eapol_sm_notify_logoff(wpa_s->eapol, TRUE);
-	} else if (strcmp(buf, "REASSOCIATE") == 0) {
+	} else if (os_strcmp(buf, "REASSOCIATE") == 0) {
 		wpa_s->disconnected = 0;
 		wpa_s->reassociate = 1;
 		wpa_supplicant_req_scan(wpa_s, 0, 0);
-	} else if (strncmp(buf, "PREAUTH ", 8) == 0) {
+	} else if (os_strncmp(buf, "PREAUTH ", 8) == 0) {
 		if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8))
 			reply_len = -1;
-	} else if (strcmp(buf, "ATTACH") == 0) {
-		if (wpa_supplicant_ctrl_iface_attach(wpa_s, &from, fromlen))
+#ifdef CONFIG_PEERKEY
+	} else if (os_strncmp(buf, "STKSTART ", 9) == 0) {
+		if (wpa_supplicant_ctrl_iface_stkstart(wpa_s, buf + 9))
 			reply_len = -1;
-		else
-			new_attached = 1;
-	} else if (strcmp(buf, "DETACH") == 0) {
-		if (wpa_supplicant_ctrl_iface_detach(wpa_s, &from, fromlen))
-			reply_len = -1;
-	} else if (strncmp(buf, "LEVEL ", 6) == 0) {
-		if (wpa_supplicant_ctrl_iface_level(wpa_s, &from, fromlen,
-						    buf + 6))
-			reply_len = -1;
-	} else if (strncmp(buf, WPA_CTRL_RSP, strlen(WPA_CTRL_RSP)) == 0) {
+#endif /* CONFIG_PEERKEY */
+	} else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0)
+	{
 		if (wpa_supplicant_ctrl_iface_ctrl_rsp(
-			    wpa_s, buf + strlen(WPA_CTRL_RSP)))
+			    wpa_s, buf + os_strlen(WPA_CTRL_RSP)))
 			reply_len = -1;
 		else
 			ctrl_rsp = 1;
-	} else if (strcmp(buf, "RECONFIGURE") == 0) {
+	} else if (os_strcmp(buf, "RECONFIGURE") == 0) {
 		if (wpa_supplicant_reload_configuration(wpa_s))
 			reply_len = -1;
-	} else if (strcmp(buf, "TERMINATE") == 0) {
+	} else if (os_strcmp(buf, "TERMINATE") == 0) {
 		eloop_terminate();
-	} else if (strncmp(buf, "BSSID ", 6) == 0) {
+	} else if (os_strncmp(buf, "BSSID ", 6) == 0) {
 		if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6))
 			reply_len = -1;
-	} else if (strcmp(buf, "LIST_NETWORKS") == 0) {
+	} else if (os_strcmp(buf, "LIST_NETWORKS") == 0) {
 		reply_len = wpa_supplicant_ctrl_iface_list_networks(
 			wpa_s, reply, reply_size);
-	} else if (strcmp(buf, "DISCONNECT") == 0) {
+	} else if (os_strcmp(buf, "DISCONNECT") == 0) {
 		wpa_s->disconnected = 1;
 		wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING);
-	} else if (strcmp(buf, "SCAN") == 0) {
+	} else if (os_strcmp(buf, "SCAN") == 0) {
 		wpa_s->scan_req = 2;
 		wpa_supplicant_req_scan(wpa_s, 0, 0);
-	} else if (strcmp(buf, "SCAN_RESULTS") == 0) {
+	} else if (os_strcmp(buf, "SCAN_RESULTS") == 0) {
 		reply_len = wpa_supplicant_ctrl_iface_scan_results(
 			wpa_s, reply, reply_size);
-	} else if (strncmp(buf, "SELECT_NETWORK ", 15) == 0) {
+	} else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) {
 		if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15))
 			reply_len = -1;
-	} else if (strncmp(buf, "ENABLE_NETWORK ", 15) == 0) {
+	} else if (os_strncmp(buf, "ENABLE_NETWORK ", 15) == 0) {
 		if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15))
 			reply_len = -1;
-	} else if (strncmp(buf, "DISABLE_NETWORK ", 16) == 0) {
+	} else if (os_strncmp(buf, "DISABLE_NETWORK ", 16) == 0) {
 		if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16))
 			reply_len = -1;
-	} else if (strcmp(buf, "ADD_NETWORK") == 0) {
+	} else if (os_strcmp(buf, "ADD_NETWORK") == 0) {
 		reply_len = wpa_supplicant_ctrl_iface_add_network(
 			wpa_s, reply, reply_size);
-	} else if (strncmp(buf, "REMOVE_NETWORK ", 15) == 0) {
+	} else if (os_strncmp(buf, "REMOVE_NETWORK ", 15) == 0) {
 		if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15))
 			reply_len = -1;
-	} else if (strncmp(buf, "SET_NETWORK ", 12) == 0) {
+	} else if (os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
 		if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12))
 			reply_len = -1;
-	} else if (strncmp(buf, "GET_NETWORK ", 12) == 0) {
+	} else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) {
 		reply_len = wpa_supplicant_ctrl_iface_get_network(
 			wpa_s, buf + 12, reply, reply_size);
-	} else if (strcmp(buf, "SAVE_CONFIG") == 0) {
+	} else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
 		if (wpa_supplicant_ctrl_iface_save_config(wpa_s))
 			reply_len = -1;
-	} else if (strncmp(buf, "GET_CAPABILITY ", 15) == 0) {
+	} else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) {
 		reply_len = wpa_supplicant_ctrl_iface_get_capability(
 			wpa_s, buf + 15, reply, reply_size);
+	} else if (os_strncmp(buf, "AP_SCAN ", 8) == 0) {
+		if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8))
+			reply_len = -1;
+	} else if (os_strcmp(buf, "INTERFACES") == 0) {
+		reply_len = wpa_supplicant_global_iface_interfaces(
+			wpa_s->global, reply, reply_size);
 	} else {
-		memcpy(reply, "UNKNOWN COMMAND\n", 16);
+		os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
 		reply_len = 16;
 	}
 
 	if (reply_len < 0) {
-		memcpy(reply, "FAIL\n", 5);
+		os_memcpy(reply, "FAIL\n", 5);
 		reply_len = 5;
 	}
-	sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen);
-	free(reply);
 
-	if (new_attached)
-		eapol_sm_notify_ctrl_attached(wpa_s->eapol);
 	if (ctrl_rsp)
 		eapol_sm_notify_ctrl_response(wpa_s->eapol);
-}
-
-
-#ifndef CONFIG_CTRL_IFACE_UDP
-static char * wpa_supplicant_ctrl_iface_path(struct wpa_supplicant *wpa_s)
-{
-	char *buf;
-	size_t len;
-
-	if (wpa_s->conf->ctrl_interface == NULL)
-		return NULL;
-
-	len = strlen(wpa_s->conf->ctrl_interface) + strlen(wpa_s->ifname) + 2;
-	buf = malloc(len);
-	if (buf == NULL)
-		return NULL;
-
-	snprintf(buf, len, "%s/%s",
-		 wpa_s->conf->ctrl_interface, wpa_s->ifname);
-#ifdef __CYGWIN__
-	{
-		/* Windows/WinPcap uses interface names that are not suitable
-		 * as a file name - convert invalid chars to underscores */
-		char *pos = buf;
-		while (*pos) {
-			if (*pos == '\\')
-				*pos = '_';
-			pos++;
-		}
-	}
-#endif /* __CYGWIN__ */
-	return buf;
-}
-#endif /* CONFIG_CTRL_IFACE_UDP */
-
-
-/**
- * wpa_supplicant_ctrl_iface_init - Initialize control interface
- * @wpa_s: Pointer to wpa_supplicant data
- * Returns: 0 on success, -1 on failure
- *
- * Initialize the control interface and start receiving commands from external
- * programs.
- */
-int wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s)
-{
-	CTRL_IFACE_SOCK addr;
-	int s = -1;
-#ifndef CONFIG_CTRL_IFACE_UDP
-	char *fname = NULL;
-#endif /* CONFIG_CTRL_IFACE_UDP */
-
-	wpa_s->ctrl_sock = -1;
 
-	if (wpa_s->conf->ctrl_interface == NULL)
-		return 0;
-
-#ifdef CONFIG_CTRL_IFACE_UDP
-	s = socket(PF_INET, SOCK_DGRAM, 0);
-	if (s < 0) {
-		perror("socket(PF_INET)");
-		goto fail;
-	}
-
-	memset(&addr, 0, sizeof(addr));
-	addr.sin_family = AF_INET;
-	addr.sin_addr.s_addr = htonl((127 << 24) | 1);
-	addr.sin_port = htons(WPA_CTRL_IFACE_PORT);
-	if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
-		perror("bind(AF_INET)");
-		goto fail;
-	}
-#else /* CONFIG_CTRL_IFACE_UDP */
-	if (mkdir(wpa_s->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
-		if (errno == EEXIST) {
-			wpa_printf(MSG_DEBUG, "Using existing control "
-				   "interface directory.");
-		} else {
-			perror("mkdir[ctrl_interface]");
-			goto fail;
-		}
-	}
-
-	if (wpa_s->conf->ctrl_interface_gid_set &&
-	    chown(wpa_s->conf->ctrl_interface, 0,
-		  wpa_s->conf->ctrl_interface_gid) < 0) {
-		perror("chown[ctrl_interface]");
-		return -1;
-	}
-
-	if (strlen(wpa_s->conf->ctrl_interface) + 1 + strlen(wpa_s->ifname) >=
-	    sizeof(addr.sun_path))
-		goto fail;
-
-	s = socket(PF_UNIX, SOCK_DGRAM, 0);
-	if (s < 0) {
-		perror("socket(PF_UNIX)");
-		goto fail;
-	}
-
-	memset(&addr, 0, sizeof(addr));
-	addr.sun_family = AF_UNIX;
-	fname = wpa_supplicant_ctrl_iface_path(wpa_s);
-	if (fname == NULL)
-		goto fail;
-	strncpy(addr.sun_path, fname, sizeof(addr.sun_path));
-	if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
-		perror("bind(PF_UNIX)");
-		if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
-			wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
-				   " allow connections - assuming it was left"
-				   "over from forced program termination");
-			if (unlink(fname) < 0) {
-				perror("unlink[ctrl_iface]");
-				wpa_printf(MSG_ERROR, "Could not unlink "
-					   "existing ctrl_iface socket '%s'",
-					   fname);
-				goto fail;
-			}
-			if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
-			    0) {
-				perror("bind(PF_UNIX)");
-				goto fail;
-			}
-			wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
-				   "ctrl_iface socket '%s'", fname);
-		} else {
-			wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
-				   "be in use - cannot override it");
-			wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
-				   "not used anymore", fname);
-			free(fname);
-			fname = NULL;
-			goto fail;
-		}
-	}
-
-	if (wpa_s->conf->ctrl_interface_gid_set &&
-	    chown(fname, 0, wpa_s->conf->ctrl_interface_gid) < 0) {
-		perror("chown[ctrl_interface/ifname]");
-		goto fail;
-	}
-
-	if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
-		perror("chmod[ctrl_interface/ifname]");
-		goto fail;
-	}
-	free(fname);
-#endif /* CONFIG_CTRL_IFACE_UDP */
-
-	wpa_s->ctrl_sock = s;
-	eloop_register_read_sock(s, wpa_supplicant_ctrl_iface_receive, wpa_s,
-				 NULL);
-
-	return 0;
-
-fail:
-	if (s >= 0)
-		close(s);
-#ifndef CONFIG_CTRL_IFACE_UDP
-	if (fname) {
-		unlink(fname);
-		free(fname);
-	}
-#endif /* CONFIG_CTRL_IFACE_UDP */
-	return -1;
-}
-
-
-/**
- * wpa_supplicant_ctrl_iface_deinit - Deinitialize control interface
- * @wpa_s: Pointer to wpa_supplicant data
- *
- * Deinitialize the control interface that was initialized with
- * wpa_supplicant_ctrl_iface_init().
- */
-void wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant *wpa_s)
-{
-	struct wpa_ctrl_dst *dst, *prev;
-
-	if (wpa_s->ctrl_sock > -1) {
-#ifndef CONFIG_CTRL_IFACE_UDP
-		char *fname;
-#endif /* CONFIG_CTRL_IFACE_UDP */
-		eloop_unregister_read_sock(wpa_s->ctrl_sock);
-		if (wpa_s->ctrl_dst) {
-			/*
-			 * Wait a second before closing the control socket if
-			 * there are any attached monitors in order to allow
-			 * them to receive any pending messages.
-			 */
-			wpa_printf(MSG_DEBUG, "CTRL_IFACE wait for attached "
-				   "monitors to receive messages");
-			sleep(1);
-		}
-		close(wpa_s->ctrl_sock);
-		wpa_s->ctrl_sock = -1;
-#ifndef CONFIG_CTRL_IFACE_UDP
-		fname = wpa_supplicant_ctrl_iface_path(wpa_s);
-		if (fname)
-			unlink(fname);
-		free(fname);
-
-		if (rmdir(wpa_s->conf->ctrl_interface) < 0) {
-			if (errno == ENOTEMPTY) {
-				wpa_printf(MSG_DEBUG, "Control interface "
-					   "directory not empty - leaving it "
-					   "behind");
-			} else {
-				perror("rmdir[ctrl_interface]");
-			}
-		}
-#endif /* CONFIG_CTRL_IFACE_UDP */
-	}
-
-	dst = wpa_s->ctrl_dst;
-	while (dst) {
-		prev = dst;
-		dst = dst->next;
-		free(prev);
-	}
-}
-
-
-/**
- * wpa_supplicant_ctrl_iface_send - Send a control interface packet to monitors
- * @wpa_s: Pointer to wpa_supplicant data
- * @level: Priority level of the message
- * @buf: Message data
- * @len: Message length
- *
- * Send a packet to all monitor programs attached to the control interface.
- */
-void wpa_supplicant_ctrl_iface_send(struct wpa_supplicant *wpa_s, int level,
-				    char *buf, size_t len)
-{
-	struct wpa_ctrl_dst *dst, *next;
-	char levelstr[10];
-	int idx;
-#ifdef CONFIG_CTRL_IFACE_UDP
-	char *sbuf;
-	int llen;
-
-	dst = wpa_s->ctrl_dst;
-	if (wpa_s->ctrl_sock < 0 || dst == NULL)
-		return;
-
-	snprintf(levelstr, sizeof(levelstr), "<%d>", level);
-
-	llen = strlen(levelstr);
-	sbuf = malloc(llen + len);
-	if (sbuf == NULL)
-		return;
-
-	memcpy(sbuf, levelstr, llen);
-	memcpy(sbuf + llen, buf, len);
-
-	idx = 0;
-	while (dst) {
-		next = dst->next;
-		if (level >= dst->debug_level) {
-			wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor send %s:%d",
-				   inet_ntoa(dst->addr.sin_addr),
-				   ntohs(dst->addr.sin_port));
-			if (sendto(wpa_s->ctrl_sock, sbuf, llen + len, 0,
-				   (struct sockaddr *) &dst->addr,
-				   sizeof(dst->addr)) < 0) {
-				perror("sendto(CTRL_IFACE monitor)");
-				dst->errors++;
-				if (dst->errors > 10) {
-					wpa_supplicant_ctrl_iface_detach(
-						wpa_s, &dst->addr,
-						dst->addrlen);
-				}
-			} else
-				dst->errors = 0;
-		}
-		idx++;
-		dst = next;
-	}
-	free(sbuf);
-#else /* CONFIG_CTRL_IFACE_UDP */
-	struct msghdr msg;
-	struct iovec io[2];
-
-	dst = wpa_s->ctrl_dst;
-	if (wpa_s->ctrl_sock < 0 || dst == NULL)
-		return;
-
-	snprintf(levelstr, sizeof(levelstr), "<%d>", level);
-	io[0].iov_base = levelstr;
-	io[0].iov_len = strlen(levelstr);
-	io[1].iov_base = buf;
-	io[1].iov_len = len;
-	memset(&msg, 0, sizeof(msg));
-	msg.msg_iov = io;
-	msg.msg_iovlen = 2;
-
-	idx = 0;
-	while (dst) {
-		next = dst->next;
-		if (level >= dst->debug_level) {
-			wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor send",
-				    (u8 *) dst->addr.sun_path, dst->addrlen);
-			msg.msg_name = &dst->addr;
-			msg.msg_namelen = dst->addrlen;
-			if (sendmsg(wpa_s->ctrl_sock, &msg, 0) < 0) {
-				perror("sendmsg(CTRL_IFACE monitor)");
-				dst->errors++;
-				if (dst->errors > 10) {
-					wpa_supplicant_ctrl_iface_detach(
-						wpa_s, &dst->addr,
-						dst->addrlen);
-				}
-			} else
-				dst->errors = 0;
-		}
-		idx++;
-		dst = next;
-	}
-#endif /* CONFIG_CTRL_IFACE_UDP */
-}
-
-
-/**
- * wpa_supplicant_ctrl_iface_wait - Wait for ctrl_iface monitor
- * @wpa_s: Pointer to wpa_supplicant data
- *
- * Wait until the first message from an external program using the control
- * interface is received. This function can be used to delay normal startup
- * processing to allow control interface programs to attach with
- * %wpa_supplicant before normal operations are started.
- */
-void wpa_supplicant_ctrl_iface_wait(struct wpa_supplicant *wpa_s)
-{
-	fd_set rfds;
-
-	if (wpa_s->ctrl_sock < 0)
-		return;
-
-	wpa_printf(MSG_DEBUG, "CTRL_IFACE - %s - wait for monitor",
-		   wpa_s->ifname);
-
-	FD_ZERO(&rfds);
-	FD_SET(wpa_s->ctrl_sock, &rfds);
-	select(wpa_s->ctrl_sock + 1, &rfds, NULL, NULL, NULL);
+	*resp_len = reply_len;
+	return reply;
 }
 
 
@@ -1437,14 +1214,15 @@
 
 	/*
 	 * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param>
+	 * TAB<bridge_ifname>
 	 */
 	wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd);
 
-	memset(&iface, 0, sizeof(iface));
+	os_memset(&iface, 0, sizeof(iface));
 
 	do {
 		iface.ifname = pos = cmd;
-		pos = strchr(pos, '\t');
+		pos = os_strchr(pos, '\t');
 		if (pos)
 			*pos++ = '\0';
 		if (iface.ifname[0] == '\0')
@@ -1453,7 +1231,7 @@
 			break;
 
 		iface.confname = pos;
-		pos = strchr(pos, '\t');
+		pos = os_strchr(pos, '\t');
 		if (pos)
 			*pos++ = '\0';
 		if (iface.confname[0] == '\0')
@@ -1462,7 +1240,7 @@
 			break;
 
 		iface.driver = pos;
-		pos = strchr(pos, '\t');
+		pos = os_strchr(pos, '\t');
 		if (pos)
 			*pos++ = '\0';
 		if (iface.driver[0] == '\0')
@@ -1471,7 +1249,7 @@
 			break;
 
 		iface.ctrl_interface = pos;
-		pos = strchr(pos, '\t');
+		pos = os_strchr(pos, '\t');
 		if (pos)
 			*pos++ = '\0';
 		if (iface.ctrl_interface[0] == '\0')
@@ -1480,13 +1258,22 @@
 			break;
 
 		iface.driver_param = pos;
-		pos = strchr(pos, '\t');
+		pos = os_strchr(pos, '\t');
 		if (pos)
 			*pos++ = '\0';
 		if (iface.driver_param[0] == '\0')
 			iface.driver_param = NULL;
 		if (pos == NULL)
 			break;
+
+		iface.bridge_ifname = pos;
+		pos = os_strchr(pos, '\t');
+		if (pos)
+			*pos++ = '\0';
+		if (iface.bridge_ifname[0] == '\0')
+			iface.bridge_ifname = NULL;
+		if (pos == NULL)
+			break;
 	} while (0);
 
 	if (wpa_supplicant_get_iface(global, iface.ifname))
@@ -1510,179 +1297,73 @@
 }
 
 
-static void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx,
-						     void *sock_ctx)
+static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
+						  char *buf, int len)
 {
-	struct wpa_global *global = eloop_ctx;
-	char buf[256];
 	int res;
-	CTRL_IFACE_SOCK from;
-	socklen_t fromlen = sizeof(from);
+	char *pos, *end;
+	struct wpa_supplicant *wpa_s;
+
+	wpa_s = global->ifaces;
+	pos = buf;
+	end = buf + len;
+
+	while (wpa_s) {
+		res = os_snprintf(pos, end - pos, "%s\n", wpa_s->ifname);
+		if (res < 0 || res >= end - pos) {
+			*pos = '\0';
+			break;
+		}
+		pos += res;
+		wpa_s = wpa_s->next;
+	}
+	return pos - buf;
+}
+
+
+char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global,
+						char *buf, size_t *resp_len)
+{
 	char *reply;
 	const int reply_size = 2048;
 	int reply_len;
 
-	res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
-		       (struct sockaddr *) &from, &fromlen);
-	if (res < 0) {
-		perror("recvfrom(ctrl_iface)");
-		return;
-	}
-	buf[res] = '\0';
-	wpa_hexdump_ascii(MSG_DEBUG, "RX global ctrl_iface", (u8 *) buf, res);
+	wpa_hexdump_ascii(MSG_DEBUG, "RX global ctrl_iface",
+			  (const u8 *) buf, os_strlen(buf));
 
-	reply = malloc(reply_size);
+	reply = os_malloc(reply_size);
 	if (reply == NULL) {
-		sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
-		       fromlen);
-		return;
+		*resp_len = 1;
+		return NULL;
 	}
 
-	memcpy(reply, "OK\n", 3);
+	os_memcpy(reply, "OK\n", 3);
 	reply_len = 3;
 
-	if (strcmp(buf, "PING") == 0) {
-		memcpy(reply, "PONG\n", 5);
+	if (os_strcmp(buf, "PING") == 0) {
+		os_memcpy(reply, "PONG\n", 5);
 		reply_len = 5;
-	} else if (strncmp(buf, "INTERFACE_ADD ", 14) == 0) {
+	} else if (os_strncmp(buf, "INTERFACE_ADD ", 14) == 0) {
 		if (wpa_supplicant_global_iface_add(global, buf + 14))
 			reply_len = -1;
-	} else if (strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) {
+	} else if (os_strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) {
 		if (wpa_supplicant_global_iface_remove(global, buf + 17))
 			reply_len = -1;
+	} else if (os_strcmp(buf, "INTERFACES") == 0) {
+		reply_len = wpa_supplicant_global_iface_interfaces(
+			global, reply, reply_size);
+	} else if (os_strcmp(buf, "TERMINATE") == 0) {
+		eloop_terminate();
 	} else {
-		memcpy(reply, "UNKNOWN COMMAND\n", 16);
+		os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
 		reply_len = 16;
 	}
 
 	if (reply_len < 0) {
-		memcpy(reply, "FAIL\n", 5);
+		os_memcpy(reply, "FAIL\n", 5);
 		reply_len = 5;
 	}
-	sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen);
-	free(reply);
-}
-
-
-/**
- * wpa_supplicant_global_ctrl_iface_init - Initialize global control interface
- * @global: Pointer to global data from wpa_supplicant_init()
- * Returns: 0 on success, -1 on failure
- *
- * Initialize the global control interface and start receiving commands from
- * external programs.
- */
-int wpa_supplicant_global_ctrl_iface_init(struct wpa_global *global)
-{
-	CTRL_IFACE_SOCK addr;
-	int s = -1;
-#ifndef CONFIG_CTRL_IFACE_UDP
-	char *fname = NULL;
-#endif /* CONFIG_CTRL_IFACE_UDP */
-
-	global->ctrl_sock = -1;
-
-	if (global->params.ctrl_interface == NULL)
-		return 0;
-
-	wpa_printf(MSG_DEBUG, "Global control interface '%s'",
-		   global->params.ctrl_interface);
-
-#ifdef CONFIG_CTRL_IFACE_UDP
-	s = socket(PF_INET, SOCK_DGRAM, 0);
-	if (s < 0) {
-		perror("socket(PF_INET)");
-		goto fail;
-	}
-
-	memset(&addr, 0, sizeof(addr));
-	addr.sin_family = AF_INET;
-	addr.sin_addr.s_addr = htonl((127 << 24) | 1);
-	addr.sin_port = htons(WPA_GLOBAL_CTRL_IFACE_PORT);
-	if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
-		perror("bind(AF_INET)");
-		goto fail;
-	}
-#else /* CONFIG_CTRL_IFACE_UDP */
-	s = socket(PF_UNIX, SOCK_DGRAM, 0);
-	if (s < 0) {
-		perror("socket(PF_UNIX)");
-		goto fail;
-	}
-
-	memset(&addr, 0, sizeof(addr));
-	addr.sun_family = AF_UNIX;
-	strncpy(addr.sun_path, global->params.ctrl_interface,
-		sizeof(addr.sun_path));
-	if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
-		perror("bind(PF_UNIX)");
-		if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
-			wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
-				   " allow connections - assuming it was left"
-				   "over from forced program termination");
-			if (unlink(global->params.ctrl_interface) < 0) {
-				perror("unlink[ctrl_iface]");
-				wpa_printf(MSG_ERROR, "Could not unlink "
-					   "existing ctrl_iface socket '%s'",
-					   global->params.ctrl_interface);
-				goto fail;
-			}
-			if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
-			    0) {
-				perror("bind(PF_UNIX)");
-				goto fail;
-			}
-			wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
-				   "ctrl_iface socket '%s'",
-				   global->params.ctrl_interface);
-		} else {
-			wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
-				   "be in use - cannot override it");
-			wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
-				   "not used anymore",
-				   global->params.ctrl_interface);
-			goto fail;
-		}
-	}
-#endif /* CONFIG_CTRL_IFACE_UDP */
-
-	global->ctrl_sock = s;
-	eloop_register_read_sock(s, wpa_supplicant_global_ctrl_iface_receive,
-				 global, NULL);
-
-	return 0;
-
-fail:
-	if (s >= 0)
-		close(s);
-#ifndef CONFIG_CTRL_IFACE_UDP
-	if (fname) {
-		unlink(fname);
-		free(fname);
-	}
-#endif /* CONFIG_CTRL_IFACE_UDP */
-	return -1;
-}
-
-
-/**
- * wpa_supplicant_global_ctrl_iface_deinit - Deinitialize global ctrl interface
- * @global: Pointer to global data from wpa_supplicant_init()
- *
- * Deinitialize the global control interface that was initialized with
- * wpa_supplicant_global_ctrl_iface_init().
- */
-void wpa_supplicant_global_ctrl_iface_deinit(struct wpa_global *global)
-{
-	if (global->ctrl_sock < 0)
-		return;
 
-	eloop_unregister_read_sock(global->ctrl_sock);
-	close(global->ctrl_sock);
-	global->ctrl_sock = -1;
-
-#ifndef CONFIG_CTRL_IFACE_UDP
-	if (global->params.ctrl_interface)
-		unlink(global->params.ctrl_interface);
-#endif /* CONFIG_CTRL_IFACE_UDP */
+	*resp_len = reply_len;
+	return reply;
 }
Index: radius.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/radius.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/radius.c -L contrib/wpa_supplicant/radius.c -u -r1.2 -r1.3
--- contrib/wpa_supplicant/radius.c
+++ contrib/wpa_supplicant/radius.c
@@ -1,7 +1,6 @@
 /*
- * Host AP (software wireless LAN access point) user space daemon for
- * Host AP kernel driver / RADIUS client
- * Copyright (c) 2002-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * hostapd / RADIUS message processing
+ * Copyright (c) 2002-2005, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -13,18 +12,7 @@
  * See README and COPYING for more details.
  */
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <signal.h>
-#include <sys/time.h>
-#ifndef CONFIG_NATIVE_WINDOWS
-#include <netinet/in.h>
-#include <sys/ioctl.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-#endif /* CONFIG_NATIVE_WINDOWS */
+#include "includes.h"
 
 #include "common.h"
 #include "radius.h"
@@ -36,12 +24,12 @@
 {
 	struct radius_msg *msg;
 
-	msg = (struct radius_msg *) malloc(sizeof(*msg));
+	msg = os_malloc(sizeof(*msg));
 	if (msg == NULL)
 		return NULL;
 
 	if (radius_msg_initialize(msg, RADIUS_DEFAULT_MSG_SIZE)) {
-		free(msg);
+		os_free(msg);
 		return NULL;
 	}
 
@@ -56,20 +44,19 @@
 	if (msg == NULL || init_len < sizeof(struct radius_hdr))
 		return -1;
 
-	memset(msg, 0, sizeof(*msg));
-	msg->buf = (unsigned char *) malloc(init_len);
+	os_memset(msg, 0, sizeof(*msg));
+	msg->buf = wpa_zalloc(init_len);
 	if (msg->buf == NULL)
 		return -1;
-	memset(msg->buf, 0, init_len);
 
 	msg->buf_size = init_len;
 	msg->hdr = (struct radius_hdr *) msg->buf;
 	msg->buf_used = sizeof(*msg->hdr);
 
-	msg->attrs = (struct radius_attr_hdr **)
-		malloc(RADIUS_DEFAULT_ATTR_COUNT * sizeof(*msg->attrs));
+	msg->attrs =
+		os_malloc(RADIUS_DEFAULT_ATTR_COUNT * sizeof(*msg->attrs));
 	if (msg->attrs == NULL) {
-		free(msg->buf);
+		os_free(msg->buf);
 		msg->buf = NULL;
 		msg->hdr = NULL;
 		return -1;
@@ -92,14 +79,14 @@
 void radius_msg_free(struct radius_msg *msg)
 {
 	if (msg->buf != NULL) {
-		free(msg->buf);
+		os_free(msg->buf);
 		msg->buf = NULL;
 		msg->hdr = NULL;
 	}
 	msg->buf_size = msg->buf_used = 0;
 
 	if (msg->attrs != NULL) {
-		free(msg->attrs);
+		os_free(msg->attrs);
 		msg->attrs = NULL;
 	}
 	msg->attr_size = msg->attr_used = 0;
@@ -178,10 +165,15 @@
 	{ RADIUS_ATTR_EVENT_TIMESTAMP, "Event-Timestamp",
 	  RADIUS_ATTR_INT32 },
 	{ RADIUS_ATTR_NAS_PORT_TYPE, "NAS-Port-Type", RADIUS_ATTR_INT32 },
+	{ RADIUS_ATTR_TUNNEL_TYPE, "Tunnel-Type", RADIUS_ATTR_HEXDUMP },
+	{ RADIUS_ATTR_TUNNEL_MEDIUM_TYPE, "Tunnel-Medium-Type",
+	  RADIUS_ATTR_HEXDUMP },
 	{ RADIUS_ATTR_CONNECT_INFO, "Connect-Info", RADIUS_ATTR_TEXT },
 	{ RADIUS_ATTR_EAP_MESSAGE, "EAP-Message", RADIUS_ATTR_UNDIST },
 	{ RADIUS_ATTR_MESSAGE_AUTHENTICATOR, "Message-Authenticator",
 	  RADIUS_ATTR_UNDIST },
+	{ RADIUS_ATTR_TUNNEL_PRIVATE_GROUP_ID, "Tunnel-Private-Group-Id",
+	  RADIUS_ATTR_HEXDUMP },
 	{ RADIUS_ATTR_ACCT_INTERIM_INTERVAL, "Acct-Interim-Interval",
 	  RADIUS_ATTR_INT32 },
 	{ RADIUS_ATTR_NAS_IPV6_ADDRESS, "NAS-IPv6-Address", RADIUS_ATTR_IPV6 },
@@ -191,7 +183,7 @@
 
 static struct radius_attr_type *radius_get_attr_type(u8 type)
 {
-	int i;
+	size_t i;
 
 	for (i = 0; i < RADIUS_ATTRS; i++) {
 		if (type == radius_attrs[i].type)
@@ -202,6 +194,15 @@
 }
 
 
+static void print_char(char c)
+{
+	if (c >= 32 && c < 127)
+		printf("%c", c);
+	else
+		printf("<%02x>", c);
+}
+
+
 static void radius_msg_dump_attr(struct radius_attr_hdr *hdr)
 {
 	struct radius_attr_type *attr;
@@ -257,11 +258,9 @@
 		break;
 
 	case RADIUS_ATTR_INT32:
-		if (len == 4) {
-			u32 *val = (u32 *) pos;
-			printf("      Value: %u\n",
-			       (unsigned int) ntohl(*val));
-		} else
+		if (len == 4)
+			printf("      Value: %u\n", WPA_GET_BE32(pos));
+		else
 			printf("      Invalid INT32 length %d\n", len);
 		break;
 
@@ -273,7 +272,7 @@
 
 void radius_msg_dump(struct radius_msg *msg)
 {
-	int i;
+	size_t i;
 
 	printf("RADIUS message: code=%d (%s) identifier=%d length=%d\n",
 	       msg->hdr->code, radius_code_string(msg->hdr->code),
@@ -291,7 +290,7 @@
 		u8 auth[MD5_MAC_LEN];
 		struct radius_attr_hdr *attr;
 
-		memset(auth, 0, MD5_MAC_LEN);
+		os_memset(auth, 0, MD5_MAC_LEN);
 		attr = radius_msg_add_attr(msg,
 					   RADIUS_ATTR_MESSAGE_AUTHENTICATOR,
 					   auth, MD5_MAC_LEN);
@@ -323,7 +322,7 @@
 	const u8 *addr[4];
 	size_t len[4];
 
-	memset(auth, 0, MD5_MAC_LEN);
+	os_memset(auth, 0, MD5_MAC_LEN);
 	attr = radius_msg_add_attr(msg, RADIUS_ATTR_MESSAGE_AUTHENTICATOR,
 				   auth, MD5_MAC_LEN);
 	if (attr == NULL) {
@@ -331,8 +330,8 @@
 		return -1;
 	}
 	msg->hdr->length = htons(msg->buf_used);
-	memcpy(msg->hdr->authenticator, req_authenticator,
-	       sizeof(msg->hdr->authenticator));
+	os_memcpy(msg->hdr->authenticator, req_authenticator,
+		  sizeof(msg->hdr->authenticator));
 	hmac_md5(secret, secret_len, msg->buf, msg->buf_used,
 		 (u8 *) (attr + 1));
 
@@ -363,7 +362,7 @@
 	size_t len[2];
 
 	msg->hdr->length = htons(msg->buf_used);
-	memset(msg->hdr->authenticator, 0, MD5_MAC_LEN);
+	os_memset(msg->hdr->authenticator, 0, MD5_MAC_LEN);
 	addr[0] = msg->buf;
 	len[0] = msg->buf_used;
 	addr[1] = secret;
@@ -384,9 +383,7 @@
 		struct radius_attr_hdr **nattrs;
 		int nlen = msg->attr_size * 2;
 
-		nattrs = (struct radius_attr_hdr **)
-			realloc(msg->attrs, nlen * sizeof(*msg->attrs));
-
+		nattrs = os_realloc(msg->attrs, nlen * sizeof(*msg->attrs));
 		if (nattrs == NULL)
 			return -1;
 
@@ -417,12 +414,12 @@
 	if (msg->buf_size < buf_needed) {
 		/* allocate more space for message buffer */
 		unsigned char *nbuf;
-		int nlen = msg->buf_size;
-		int diff, i;
+		size_t i, nlen = msg->buf_size;
+		int diff;
 
 		while (nlen < buf_needed)
 			nlen *= 2;
-		nbuf = (unsigned char *) realloc(msg->buf, nlen);
+		nbuf = os_realloc(msg->buf, nlen);
 		if (nbuf == NULL)
 			return NULL;
 		diff = nbuf - msg->buf;
@@ -432,7 +429,7 @@
 		for (i = 0; i < msg->attr_used; i++)
 			msg->attrs[i] = (struct radius_attr_hdr *)
 				(((u8 *) msg->attrs[i]) + diff);
-		memset(msg->buf + msg->buf_size, 0, nlen - msg->buf_size);
+		os_memset(msg->buf + msg->buf_size, 0, nlen - msg->buf_size);
 		msg->buf_size = nlen;
 	}
 
@@ -440,7 +437,7 @@
 	attr->type = type;
 	attr->length = sizeof(*attr) + data_len;
 	if (data_len > 0)
-		memcpy(attr + 1, data, data_len);
+		os_memcpy(attr + 1, data, data_len);
 
 	msg->buf_used += sizeof(*attr) + data_len;
 
@@ -475,23 +472,23 @@
 		       (unsigned long) len - msg_len);
 	}
 
-	msg = (struct radius_msg *) malloc(sizeof(*msg));
+	msg = os_malloc(sizeof(*msg));
 	if (msg == NULL)
 		return NULL;
 
 	if (radius_msg_initialize(msg, msg_len)) {
-		free(msg);
+		os_free(msg);
 		return NULL;
 	}
 
-	memcpy(msg->buf, data, msg_len);
+	os_memcpy(msg->buf, data, msg_len);
 	msg->buf_size = msg->buf_used = msg_len;
 
 	/* parse attributes */
 	pos = (unsigned char *) (msg->hdr + 1);
 	end = msg->buf + msg->buf_used;
 	while (pos < end) {
-		if (end - pos < sizeof(*attr))
+		if ((size_t) (end - pos) < sizeof(*attr))
 			goto fail;
 
 		attr = (struct radius_attr_hdr *) pos;
@@ -511,7 +508,7 @@
 
  fail:
 	radius_msg_free(msg);
-	free(msg);
+	os_free(msg);
 	return NULL;
 }
 
@@ -543,8 +540,7 @@
 u8 *radius_msg_get_eap(struct radius_msg *msg, size_t *eap_len)
 {
 	u8 *eap, *pos;
-	size_t len;
-	int i;
+	size_t len, i;
 
 	if (msg == NULL)
 		return NULL;
@@ -559,7 +555,7 @@
 	if (len == 0)
 		return NULL;
 
-	eap = malloc(len);
+	eap = os_malloc(len);
 	if (eap == NULL)
 		return NULL;
 
@@ -568,7 +564,7 @@
 		if (msg->attrs[i]->type == RADIUS_ATTR_EAP_MESSAGE) {
 			struct radius_attr_hdr *attr = msg->attrs[i];
 			int flen = attr->length - sizeof(*attr);
-			memcpy(pos, attr + 1, flen);
+			os_memcpy(pos, attr + 1, flen);
 			pos += flen;
 		}
 	}
@@ -586,7 +582,7 @@
 	u8 auth[MD5_MAC_LEN], orig[MD5_MAC_LEN];
 	u8 orig_authenticator[16];
 	struct radius_attr_hdr *attr = NULL;
-	int i;
+	size_t i;
 
 	for (i = 0; i < msg->attr_used; i++) {
 		if (msg->attrs[i]->type == RADIUS_ATTR_MESSAGE_AUTHENTICATOR) {
@@ -604,22 +600,22 @@
 		return 1;
 	}
 
-	memcpy(orig, attr + 1, MD5_MAC_LEN);
-	memset(attr + 1, 0, MD5_MAC_LEN);
+	os_memcpy(orig, attr + 1, MD5_MAC_LEN);
+	os_memset(attr + 1, 0, MD5_MAC_LEN);
 	if (req_auth) {
-		memcpy(orig_authenticator, msg->hdr->authenticator,
-		       sizeof(orig_authenticator));
-		memcpy(msg->hdr->authenticator, req_auth,
-		       sizeof(msg->hdr->authenticator));
+		os_memcpy(orig_authenticator, msg->hdr->authenticator,
+			  sizeof(orig_authenticator));
+		os_memcpy(msg->hdr->authenticator, req_auth,
+			  sizeof(msg->hdr->authenticator));
 	}
 	hmac_md5(secret, secret_len, msg->buf, msg->buf_used, auth);
-	memcpy(attr + 1, orig, MD5_MAC_LEN);
+	os_memcpy(attr + 1, orig, MD5_MAC_LEN);
 	if (req_auth) {
-		memcpy(msg->hdr->authenticator, orig_authenticator,
-		       sizeof(orig_authenticator));
+		os_memcpy(msg->hdr->authenticator, orig_authenticator,
+			  sizeof(orig_authenticator));
 	}
 
-	if (memcmp(orig, auth, MD5_MAC_LEN) != 0) {
+	if (os_memcmp(orig, auth, MD5_MAC_LEN) != 0) {
 		printf("Invalid Message-Authenticator!\n");
 		return 1;
 	}
@@ -656,13 +652,12 @@
 	addr[3] = secret;
 	len[3] = secret_len;
 	md5_vector(4, addr, len, hash);
-	if (memcmp(hash, msg->hdr->authenticator, MD5_MAC_LEN) != 0) {
+	if (os_memcmp(hash, msg->hdr->authenticator, MD5_MAC_LEN) != 0) {
 		printf("Response Authenticator invalid!\n");
 		return 1;
 	}
 
 	return 0;
-
 }
 
 
@@ -670,7 +665,7 @@
 			 u8 type)
 {
 	struct radius_attr_hdr *attr = NULL;
-	int i;
+	size_t i;
 
 	for (i = 0; i < src->attr_used; i++) {
 		if (src->attrs[i]->type == type) {
@@ -695,15 +690,15 @@
  * Use one-way MD5 hash calculated from current timestamp and some data given
  * by the caller. */
 void radius_msg_make_authenticator(struct radius_msg *msg,
-				   u8 *data, size_t len)
+				   const u8 *data, size_t len)
 {
-	struct timeval tv;
+	struct os_time tv;
 	long int l;
 	const u8 *addr[3];
 	size_t elen[3];
 
-	gettimeofday(&tv, NULL);
-	l = random();
+	os_get_time(&tv);
+	l = os_random();
 	addr[0] = (u8 *) &tv;
 	elen[0] = sizeof(tv);
 	addr[1] = data;
@@ -717,21 +712,21 @@
 /* Get Vendor-specific RADIUS Attribute from a parsed RADIUS message.
  * Returns the Attribute payload and sets alen to indicate the length of the
  * payload if a vendor attribute with subtype is found, otherwise returns NULL.
- * The returned payload is allocated with malloc() and caller must free it.
+ * The returned payload is allocated with os_malloc() and caller must free it
+ * by calling os_free().
  */
 static u8 *radius_msg_get_vendor_attr(struct radius_msg *msg, u32 vendor,
 				      u8 subtype, size_t *alen)
 {
 	u8 *data, *pos;
-	int i;
-	size_t len;
+	size_t i, len;
 
 	if (msg == NULL)
 		return NULL;
 
 	for (i = 0; i < msg->attr_used; i++) {
 		struct radius_attr_hdr *attr = msg->attrs[i];
-		int left;
+		size_t left;
 		u32 vendor_id;
 		struct radius_attr_vendor *vhdr;
 
@@ -744,7 +739,7 @@
 
 		pos = (u8 *) (attr + 1);
 
-		memcpy(&vendor_id, pos, 4);
+		os_memcpy(&vendor_id, pos, 4);
 		pos += 4;
 		left -= 4;
 
@@ -765,10 +760,10 @@
 			}
 
 			len = vhdr->vendor_length - sizeof(*vhdr);
-			data = malloc(len);
+			data = os_malloc(len);
 			if (data == NULL)
 				return NULL;
-			memcpy(data, pos + sizeof(*vhdr), len);
+			os_memcpy(data, pos + sizeof(*vhdr), len);
 			if (alen)
 				*alen = len;
 			return data;
@@ -804,7 +799,7 @@
 	}
 
 	plen = left;
-	ppos = plain = malloc(plen);
+	ppos = plain = os_malloc(plen);
 	if (plain == NULL)
 		return NULL;
 
@@ -833,19 +828,19 @@
 
 	if (plain[0] > plen - 1) {
 		printf("Failed to decrypt MPPE key\n");
-		free(plain);
+		os_free(plain);
 		return NULL;
 	}
 
-	res = malloc(plain[0]);
+	res = os_malloc(plain[0]);
 	if (res == NULL) {
-		free(plain);
+		os_free(plain);
 		return NULL;
 	}
-	memcpy(res, plain + 1, plain[0]);
+	os_memcpy(res, plain + 1, plain[0]);
 	if (reslen)
 		*reslen = plain[0];
-	free(plain);
+	os_free(plain);
 	return res;
 }
 
@@ -867,9 +862,9 @@
 	if (len & 0x0f) {
 		len = (len & 0xf0) + 16;
 	}
-	memset(ebuf, 0, len);
+	os_memset(ebuf, 0, len);
 	ebuf[0] = key_len;
-	memcpy(ebuf + 1, key, key_len);
+	os_memcpy(ebuf + 1, key, key_len);
 
 	*elen = len;
 
@@ -910,12 +905,10 @@
 	if (msg == NULL || sent_msg == NULL)
 		return NULL;
 
-	keys = (struct radius_ms_mppe_keys *) malloc(sizeof(*keys));
+	keys = wpa_zalloc(sizeof(*keys));
 	if (keys == NULL)
 		return NULL;
 
-	memset(keys, 0, sizeof(*keys));
-
 	key = radius_msg_get_vendor_attr(msg, RADIUS_VENDOR_ID_MICROSOFT,
 					 RADIUS_VENDOR_ATTR_MS_MPPE_SEND_KEY,
 					 &keylen);
@@ -924,7 +917,7 @@
 					    sent_msg->hdr->authenticator,
 					    secret, secret_len,
 					    &keys->send_len);
-		free(key);
+		os_free(key);
 	}
 
 	key = radius_msg_get_vendor_attr(msg, RADIUS_VENDOR_ID_MICROSOFT,
@@ -935,7 +928,7 @@
 					    sent_msg->hdr->authenticator,
 					    secret, secret_len,
 					    &keys->recv_len);
-		free(key);
+		os_free(key);
 	}
 
 	return keys;
@@ -953,21 +946,20 @@
 	if (msg == NULL || sent_msg == NULL)
 		return NULL;
 
-	keys = (struct radius_ms_mppe_keys *) malloc(sizeof(*keys));
+	keys = wpa_zalloc(sizeof(*keys));
 	if (keys == NULL)
 		return NULL;
 
-	memset(keys, 0, sizeof(*keys));
-
 	key = radius_msg_get_vendor_attr(msg, RADIUS_VENDOR_ID_CISCO,
 					 RADIUS_CISCO_AV_PAIR, &keylen);
-	if (key && keylen == 51 && memcmp(key, "leap:session-key=", 17) == 0) {
+	if (key && keylen == 51 &&
+	    os_memcmp(key, "leap:session-key=", 17) == 0) {
 		keys->recv = decrypt_ms_key(key + 17, keylen - 17,
 					    sent_msg->hdr->authenticator,
 					    secret, secret_len,
 					    &keys->recv_len);
-		free(key);
 	}
+	os_free(key);
 
 	return keys;
 }
@@ -991,17 +983,17 @@
 	hlen = sizeof(vendor_id) + sizeof(*vhdr) + 2;
 
 	/* MS-MPPE-Send-Key */
-	buf = malloc(hlen + send_key_len + 16);
+	buf = os_malloc(hlen + send_key_len + 16);
 	if (buf == NULL) {
 		return 0;
 	}
 	pos = buf;
-	memcpy(pos, &vendor_id, sizeof(vendor_id));
+	os_memcpy(pos, &vendor_id, sizeof(vendor_id));
 	pos += sizeof(vendor_id);
 	vhdr = (struct radius_attr_vendor *) pos;
 	vhdr->vendor_type = RADIUS_VENDOR_ATTR_MS_MPPE_SEND_KEY;
 	pos = (u8 *) (vhdr + 1);
-	salt = random() | 0x8000;
+	salt = os_random() | 0x8000;
 	*pos++ = salt >> 8;
 	*pos++ = salt;
 	encrypt_ms_key(send_key, send_key_len, salt, req_authenticator, secret,
@@ -1010,18 +1002,18 @@
 
 	attr = radius_msg_add_attr(msg, RADIUS_ATTR_VENDOR_SPECIFIC,
 				   buf, hlen + elen);
-	free(buf);
+	os_free(buf);
 	if (attr == NULL) {
 		return 0;
 	}
 
 	/* MS-MPPE-Recv-Key */
-	buf = malloc(hlen + send_key_len + 16);
+	buf = os_malloc(hlen + send_key_len + 16);
 	if (buf == NULL) {
 		return 0;
 	}
 	pos = buf;
-	memcpy(pos, &vendor_id, sizeof(vendor_id));
+	os_memcpy(pos, &vendor_id, sizeof(vendor_id));
 	pos += sizeof(vendor_id);
 	vhdr = (struct radius_attr_vendor *) pos;
 	vhdr->vendor_type = RADIUS_VENDOR_ATTR_MS_MPPE_RECV_KEY;
@@ -1035,7 +1027,7 @@
 
 	attr = radius_msg_add_attr(msg, RADIUS_ATTR_VENDOR_SPECIFIC,
 				   buf, hlen + elen);
-	free(buf);
+	os_free(buf);
 	if (attr == NULL) {
 		return 0;
 	}
@@ -1052,8 +1044,8 @@
 				  u8 *secret, size_t secret_len)
 {
 	u8 buf[128];
-	int padlen, i, pos;
-	size_t buf_len;
+	int padlen, i;
+	size_t buf_len, pos;
 	const u8 *addr[2];
 	size_t len[2];
 	u8 hash[16];
@@ -1061,13 +1053,13 @@
 	if (data_len > 128)
 		return NULL;
 
-	memcpy(buf, data, data_len);
+	os_memcpy(buf, data, data_len);
 	buf_len = data_len;
 
 	padlen = data_len % 16;
 	if (padlen) {
 		padlen = 16 - padlen;
-		memset(buf + data_len, 0, padlen);
+		os_memset(buf + data_len, 0, padlen);
 		buf_len += padlen;
 	}
 
@@ -1101,9 +1093,8 @@
 
 int radius_msg_get_attr(struct radius_msg *msg, u8 type, u8 *buf, size_t len)
 {
-	int i;
 	struct radius_attr_hdr *attr = NULL;
-	size_t dlen;
+	size_t i, dlen;
 
 	for (i = 0; i < msg->attr_used; i++) {
 		if (msg->attrs[i]->type == type) {
@@ -1117,7 +1108,7 @@
 
 	dlen = attr->length - sizeof(*attr);
 	if (buf)
-		memcpy(buf, (attr + 1), dlen > len ? len : dlen);
+		os_memcpy(buf, (attr + 1), dlen > len ? len : dlen);
 	return dlen;
 }
 
@@ -1125,7 +1116,7 @@
 int radius_msg_get_attr_ptr(struct radius_msg *msg, u8 type, u8 **buf,
 			    size_t *len, const u8 *start)
 {
-	int i;
+	size_t i;
 	struct radius_attr_hdr *attr = NULL;
 
 	for (i = 0; i < msg->attr_used; i++) {
@@ -1147,7 +1138,8 @@
 
 int radius_msg_count_attr(struct radius_msg *msg, u8 type, int min_len)
 {
-	int i, count;
+	size_t i;
+	int count;
 
 	for (count = 0, i = 0; i < msg->attr_used; i++) {
 		if (msg->attrs[i]->type == type &&
@@ -1158,3 +1150,80 @@
 
 	return count;
 }
+
+
+struct radius_tunnel_attrs {
+	int tag_used;
+	int type; /* Tunnel-Type */
+	int medium_type; /* Tunnel-Medium-Type */
+	int vlanid;
+};
+
+
+/**
+ * radius_msg_get_vlanid - Parse RADIUS attributes for VLAN tunnel information
+ * @msg: RADIUS message
+ * Returns: VLAN ID for the first tunnel configuration of -1 if none is found
+ */
+int radius_msg_get_vlanid(struct radius_msg *msg)
+{
+	struct radius_tunnel_attrs tunnel[RADIUS_TUNNEL_TAGS], *tun;
+	size_t i;
+	struct radius_attr_hdr *attr = NULL;
+	const u8 *data;
+	char buf[10];
+	size_t dlen;
+
+	os_memset(&tunnel, 0, sizeof(tunnel));
+
+	for (i = 0; i < msg->attr_used; i++) {
+		attr = msg->attrs[i];
+		data = (const u8 *) (attr + 1);
+		dlen = attr->length - sizeof(*attr);
+		if (attr->length < 3)
+			continue;
+		if (data[0] >= RADIUS_TUNNEL_TAGS)
+			tun = &tunnel[0];
+		else
+			tun = &tunnel[data[0]];
+
+		switch (attr->type) {
+		case RADIUS_ATTR_TUNNEL_TYPE:
+			if (attr->length != 6)
+				break;
+			tun->tag_used++;
+			tun->type = (data[1] << 16) | (data[2] << 8) | data[3];
+			break;
+		case RADIUS_ATTR_TUNNEL_MEDIUM_TYPE:
+			if (attr->length != 6)
+				break;
+			tun->tag_used++;
+			tun->medium_type =
+				(data[1] << 16) | (data[2] << 8) | data[3];
+			break;
+		case RADIUS_ATTR_TUNNEL_PRIVATE_GROUP_ID:
+			if (data[0] < RADIUS_TUNNEL_TAGS) {
+				data++;
+				dlen--;
+			}
+			if (dlen >= sizeof(buf))
+				break;
+			os_memcpy(buf, data, dlen);
+			buf[dlen] = '\0';
+			tun->tag_used++;
+			tun->vlanid = atoi(buf);
+			break;
+		}
+	}
+
+	for (i = 0; i < RADIUS_TUNNEL_TAGS; i++) {
+		tun = &tunnel[i];
+		if (tun->tag_used &&
+		    tun->type == RADIUS_TUNNEL_TYPE_VLAN &&
+		    tun->medium_type == RADIUS_TUNNEL_MEDIUM_TYPE_802 &&
+		    tun->vlanid > 0)
+			return tun->vlanid;
+	}
+
+	return -1;
+}
Index: main.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/main.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -L contrib/wpa_supplicant/main.c -L contrib/wpa_supplicant/main.c -u -r1.1 -r1.2
--- contrib/wpa_supplicant/main.c
+++ contrib/wpa_supplicant/main.c
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant / main() function for UNIX like OSes and MinGW
- * Copyright (c) 2003-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2003-2007, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -12,11 +12,10 @@
  * See README and COPYING for more details.
  */
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
+#include "includes.h"
+#ifdef __linux__
 #include <fcntl.h>
+#endif /* __linux__ */
 
 #include "common.h"
 #include "wpa_supplicant_i.h"
@@ -25,7 +24,11 @@
 extern const char *wpa_supplicant_version;
 extern const char *wpa_supplicant_license;
 #ifndef CONFIG_NO_STDOUT_DEBUG
-extern const char *wpa_supplicant_full_license;
+extern const char *wpa_supplicant_full_license1;
+extern const char *wpa_supplicant_full_license2;
+extern const char *wpa_supplicant_full_license3;
+extern const char *wpa_supplicant_full_license4;
+extern const char *wpa_supplicant_full_license5;
 #endif /* CONFIG_NO_STDOUT_DEBUG */
 
 extern struct wpa_driver_ops *wpa_supplicant_drivers[];
@@ -36,12 +39,13 @@
 	int i;
 	printf("%s\n\n%s\n"
 	       "usage:\n"
-	       "  wpa_supplicant [-BddehLqqvwW] [-P<pid file>] "
+	       "  wpa_supplicant [-BddehLqquvwW] [-P<pid file>] "
 	       "[-g<global ctrl>] \\\n"
 	       "        -i<ifname> -c<config file> [-C<ctrl>] [-D<driver>] "
 	       "[-p<driver_param>] \\\n"
-	       "        [-N -i<ifname> -c<conf> [-C<ctrl>] [-D<driver>] "
-	       "[-p<driver_param>] ...]\n"
+	       "        [-b<br_ifname> [-N -i<ifname> -c<conf> [-C<ctrl>] "
+	       "[-D<driver>] \\\n"
+	       "        [-p<driver_param>] [-b<br_ifname>] ...]\n"
 	       "\n"
 	       "drivers:\n",
 	       wpa_supplicant_version, wpa_supplicant_license);
@@ -54,6 +58,7 @@
 
 #ifndef CONFIG_NO_STDOUT_DEBUG
 	printf("options:\n"
+	       "  -b = optional bridge interface name\n"
 	       "  -B = run daemon in the background\n"
 	       "  -c = Configuration file\n"
 	       "  -C = ctrl_interface parameter (only used if -c is not)\n"
@@ -64,17 +69,20 @@
 	       "  -K = include keys (passwords, etc.) in debug output\n"
 	       "  -t = include timestamp in debug messages\n"
 	       "  -h = show this help text\n"
-	       "  -L = show license (GPL and BSD)\n"
-	       "  -p = driver parameters\n"
+	       "  -L = show license (GPL and BSD)\n");
+	printf("  -p = driver parameters\n"
 	       "  -P = PID file\n"
 	       "  -q = decrease debugging verbosity (-qq even less)\n"
+#ifdef CONFIG_CTRL_IFACE_DBUS
+	       "  -u = enable DBus control interface\n"
+#endif /* CONFIG_CTRL_IFACE_DBUS */
 	       "  -v = show version\n"
 	       "  -w = wait for interface to be added, if needed\n"
 	       "  -W = wait for a control interface monitor before starting\n"
 	       "  -N = start describing new interface\n");
 
 	printf("example:\n"
-	       "  wpa_supplicant -Dwext -iwlan0 -c/etc/wpa_supplicant.conf\n");
+	       "  wpa_supplicant -Dbsd -iwlan0 -c/etc/wpa_supplicant.conf\n");
 #endif /* CONFIG_NO_STDOUT_DEBUG */
 }
 
@@ -82,14 +90,20 @@
 static void license(void)
 {
 #ifndef CONFIG_NO_STDOUT_DEBUG
-	printf("%s\n\n%s\n",
-	       wpa_supplicant_version, wpa_supplicant_full_license);
+	printf("%s\n\n%s%s%s%s%s\n",
+	       wpa_supplicant_version,
+	       wpa_supplicant_full_license1,
+	       wpa_supplicant_full_license2,
+	       wpa_supplicant_full_license3,
+	       wpa_supplicant_full_license4,
+	       wpa_supplicant_full_license5);
 #endif /* CONFIG_NO_STDOUT_DEBUG */
 }
 
 
 static void wpa_supplicant_fd_workaround(void)
 {
+#ifdef __linux__
 	int s, i;
 	/* When started from pcmcia-cs scripts, wpa_supplicant might start with
 	 * fd 0, 1, and 2 closed. This will cause some issues because many
@@ -103,6 +117,7 @@
 			break;
 		}
 	}
+#endif /* __linux__ */
 }
 
 
@@ -110,34 +125,31 @@
 {
 	int c, i;
 	struct wpa_interface *ifaces, *iface;
-	int iface_count, exitcode;
+	int iface_count, exitcode = -1;
 	struct wpa_params params;
 	struct wpa_global *global;
 
-#ifdef CONFIG_NATIVE_WINDOWS
-	WSADATA wsaData;
-	if (WSAStartup(MAKEWORD(2, 0), &wsaData)) {
-		printf("Could not find a usable WinSock.dll\n");
+	if (os_program_init())
 		return -1;
-	}
-#endif /* CONFIG_NATIVE_WINDOWS */
 
-	memset(&params, 0, sizeof(params));
+	os_memset(&params, 0, sizeof(params));
 	params.wpa_debug_level = MSG_INFO;
 
-	iface = ifaces = malloc(sizeof(struct wpa_interface));
+	iface = ifaces = os_zalloc(sizeof(struct wpa_interface));
 	if (ifaces == NULL)
 		return -1;
-	memset(iface, 0, sizeof(*iface));
 	iface_count = 1;
 
 	wpa_supplicant_fd_workaround();
 
 	for (;;) {
-		c = getopt(argc, argv, "Bc:C:D:dg:hi:KLNp:P:qtvwW");
+		c = getopt(argc, argv, "b:Bc:C:D:dg:hi:KLNp:P:qtuvwW");
 		if (c < 0)
 			break;
 		switch (c) {
+		case 'b':
+			iface->bridge_ifname = optarg;
+			break;
 		case 'B':
 			params.daemonize++;
 			break;
@@ -155,7 +167,7 @@
 			printf("Debugging disabled with "
 			       "CONFIG_NO_STDOUT_DEBUG=y build time "
 			       "option.\n");
-			return -1;
+			goto out;
 #else /* CONFIG_NO_STDOUT_DEBUG */
 			params.wpa_debug_level--;
 			break;
@@ -165,7 +177,8 @@
 			break;
 		case 'h':
 			usage();
-			return -1;
+			exitcode = 0;
+			goto out;
 		case 'i':
 			iface->ifname = optarg;
 			break;
@@ -174,12 +187,14 @@
 			break;
 		case 'L':
 			license();
-			return -1;
+			exitcode = 0;
+			goto out;
 		case 'p':
 			iface->driver_param = optarg;
 			break;
 		case 'P':
-			params.pid_file = rel2abs_path(optarg);
+			os_free(params.pid_file);
+			params.pid_file = os_rel2abs_path(optarg);
 			break;
 		case 'q':
 			params.wpa_debug_level++;
@@ -187,9 +202,15 @@
 		case 't':
 			params.wpa_debug_timestamp++;
 			break;
+#ifdef CONFIG_CTRL_IFACE_DBUS
+		case 'u':
+			params.dbus_ctrl_interface = 1;
+			break;
+#endif /* CONFIG_CTRL_IFACE_DBUS */
 		case 'v':
 			printf("%s\n", wpa_supplicant_version);
-			return -1;
+			exitcode = 0;
+			goto out;
 		case 'w':
 			params.wait_for_interface++;
 			break;
@@ -198,19 +219,18 @@
 			break;
 		case 'N':
 			iface_count++;
-			iface = realloc(ifaces, iface_count *
-					sizeof(struct wpa_interface));
-			if (iface == NULL) {
-				free(ifaces);
-				return -1;
-			}
+			iface = os_realloc(ifaces, iface_count *
+					   sizeof(struct wpa_interface));
+			if (iface == NULL)
+				goto out;
 			ifaces = iface;
 			iface = &ifaces[iface_count - 1]; 
-			memset(iface, 0, sizeof(*iface));
+			os_memset(iface, 0, sizeof(*iface));
 			break;
 		default:
 			usage();
-			return -1;
+			exitcode = 0;
+			goto out;
 		}
 	}
 
@@ -219,16 +239,19 @@
 	if (global == NULL) {
 		printf("Failed to initialize wpa_supplicant\n");
 		exitcode = -1;
+		goto out;
 	}
 
 	for (i = 0; exitcode == 0 && i < iface_count; i++) {
 		if ((ifaces[i].confname == NULL &&
 		     ifaces[i].ctrl_interface == NULL) ||
 		    ifaces[i].ifname == NULL) {
-			if (iface_count == 1 && params.ctrl_interface)
+			if (iface_count == 1 && (params.ctrl_interface ||
+						 params.dbus_ctrl_interface))
 				break;
 			usage();
-			return -1;
+			exitcode = -1;
+			break;
 		}
 		if (wpa_supplicant_add_iface(global, &ifaces[i]) == NULL)
 			exitcode = -1;
@@ -239,12 +262,11 @@
 
 	wpa_supplicant_deinit(global);
 
-	free(ifaces);
-	free(params.pid_file);
+out:
+	os_free(ifaces);
+	os_free(params.pid_file);
 
-#ifdef CONFIG_NATIVE_WINDOWS
-	WSACleanup();
-#endif /* CONFIG_NATIVE_WINDOWS */
+	os_program_deinit();
 
 	return exitcode;
 }
Index: crypto.h
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/crypto.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/crypto.h -L contrib/wpa_supplicant/crypto.h -u -r1.2 -r1.3
--- contrib/wpa_supplicant/crypto.h
+++ contrib/wpa_supplicant/crypto.h
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant / wrapper functions for crypto libraries
- * Copyright (c) 2004-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2004-2005, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -56,16 +56,28 @@
 		 u8 *mac);
 
 /**
- * sha1_transform - Perform one SHA-1 transform step
- * @state: SHA-1 state
- * @data: Input data for the SHA-1 transform
- *
- * This function is used to implement random number generation specified in
- * NIST FIPS Publication 186-2 for EAP-SIM. This PRF uses a function that is
- * similar to SHA-1, but has different message padding and as such, access to
- * just part of the SHA-1 is needed.
+ * fips186_2-prf - NIST FIPS Publication 186-2 change notice 1 PRF
+ * @seed: Seed/key for the PRF
+ * @seed_len: Seed length in bytes
+ * @x: Buffer for PRF output
+ * @xlen: Output length in bytes
+ * Returns: 0 on success, -1 on failure
+ *
+ * This function implements random number generation specified in NIST FIPS
+ * Publication 186-2 for EAP-SIM. This PRF uses a function that is similar to
+ * SHA-1, but has different message padding.
+ */
+int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen);
+
+/**
+ * sha256_vector - SHA256 hash for data vector
+ * @num_elem: Number of elements in the data vector
+ * @addr: Pointers to the data areas
+ * @len: Lengths of the data blocks
+ * @mac: Buffer for the hash
  */
-void sha1_transform(u8 *state, const u8 data[64]);
+void sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len,
+		   u8 *mac);
 
 /**
  * des_encrypt - Encrypt one block with DES
@@ -120,4 +132,282 @@
 void aes_decrypt_deinit(void *ctx);
 
 
+enum crypto_hash_alg {
+	CRYPTO_HASH_ALG_MD5, CRYPTO_HASH_ALG_SHA1,
+	CRYPTO_HASH_ALG_HMAC_MD5, CRYPTO_HASH_ALG_HMAC_SHA1
+};
+
+struct crypto_hash;
+
+/**
+ * crypto_hash_init - Initialize hash/HMAC function
+ * @alg: Hash algorithm
+ * @key: Key for keyed hash (e.g., HMAC) or %NULL if not needed
+ * @key_len: Length of the key in bytes
+ * Returns: Pointer to hash context to use with other hash functions or %NULL
+ * on failure
+ *
+ * This function is only used with internal TLSv1 implementation
+ * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
+ * to implement this.
+ */
+struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
+				      size_t key_len);
+
+/**
+ * crypto_hash_update - Add data to hash calculation
+ * @ctx: Context pointer from crypto_hash_init()
+ * @data: Data buffer to add
+ * @len: Length of the buffer
+ *
+ * This function is only used with internal TLSv1 implementation
+ * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
+ * to implement this.
+ */
+void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len);
+
+/**
+ * crypto_hash_finish - Complete hash calculation
+ * @ctx: Context pointer from crypto_hash_init()
+ * @hash: Buffer for hash value or %NULL if caller is just freeing the hash
+ * context
+ * @len: Pointer to length of the buffer or %NULL if caller is just freeing the
+ * hash context; on return, this is set to the actual length of the hash value
+ * Returns: 0 on success, -1 if buffer is too small (len set to needed length),
+ * or -2 on other failures (including failed crypto_hash_update() operations)
+ *
+ * This function calculates the hash value and frees the context buffer that
+ * was used for hash calculation.
+ *
+ * This function is only used with internal TLSv1 implementation
+ * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
+ * to implement this.
+ */
+int crypto_hash_finish(struct crypto_hash *ctx, u8 *hash, size_t *len);
+
+
+enum crypto_cipher_alg {
+	CRYPTO_CIPHER_NULL = 0, CRYPTO_CIPHER_ALG_AES, CRYPTO_CIPHER_ALG_3DES,
+	CRYPTO_CIPHER_ALG_DES, CRYPTO_CIPHER_ALG_RC2, CRYPTO_CIPHER_ALG_RC4
+};
+
+struct crypto_cipher;
+
+/**
+ * crypto_cipher_init - Initialize block/stream cipher function
+ * @alg: Cipher algorithm
+ * @iv: Initialization vector for block ciphers or %NULL for stream ciphers
+ * @key: Cipher key
+ * @key_len: Length of key in bytes
+ * Returns: Pointer to cipher context to use with other cipher functions or
+ * %NULL on failure
+ *
+ * This function is only used with internal TLSv1 implementation
+ * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
+ * to implement this.
+ */
+struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
+					  const u8 *iv, const u8 *key,
+					  size_t key_len);
+
+/**
+ * crypto_cipher_encrypt - Cipher encrypt
+ * @ctx: Context pointer from crypto_cipher_init()
+ * @plain: Plaintext to cipher
+ * @crypt: Resulting ciphertext
+ * @len: Length of the plaintext
+ * Returns: 0 on success, -1 on failure
+ *
+ * This function is only used with internal TLSv1 implementation
+ * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
+ * to implement this.
+ */
+int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
+			  u8 *crypt, size_t len);
+
+/**
+ * crypto_cipher_decrypt - Cipher decrypt
+ * @ctx: Context pointer from crypto_cipher_init()
+ * @crypt: Ciphertext to decrypt
+ * @plain: Resulting plaintext
+ * @len: Length of the cipher text
+ * Returns: 0 on success, -1 on failure
+ *
+ * This function is only used with internal TLSv1 implementation
+ * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
+ * to implement this.
+ */
+int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
+			  u8 *plain, size_t len);
+
+/**
+ * crypto_cipher_decrypt - Free cipher context
+ * @ctx: Context pointer from crypto_cipher_init()
+ *
+ * This function is only used with internal TLSv1 implementation
+ * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
+ * to implement this.
+ */
+void crypto_cipher_deinit(struct crypto_cipher *ctx);
+
+
+struct crypto_public_key;
+struct crypto_private_key;
+
+/**
+ * crypto_public_key_import - Import an RSA public key
+ * @key: Key buffer (DER encoded RSA public key)
+ * @len: Key buffer length in bytes
+ * Returns: Pointer to the public key or %NULL on failure
+ *
+ * This function can just return %NULL if the crypto library supports X.509
+ * parsing. In that case, crypto_public_key_from_cert() is used to import the
+ * public key from a certificate.
+ *
+ * This function is only used with internal TLSv1 implementation
+ * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
+ * to implement this.
+ */
+struct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len);
+
+/**
+ * crypto_private_key_import - Import an RSA private key
+ * @key: Key buffer (DER encoded RSA private key)
+ * @len: Key buffer length in bytes
+ * Returns: Pointer to the private key or %NULL on failure
+ *
+ * This function is only used with internal TLSv1 implementation
+ * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
+ * to implement this.
+ */
+struct crypto_private_key * crypto_private_key_import(const u8 *key,
+						      size_t len);
+
+/**
+ * crypto_public_key_from_cert - Import an RSA public key from a certificate
+ * @buf: DER encoded X.509 certificate
+ * @len: Certificate buffer length in bytes
+ * Returns: Pointer to public key or %NULL on failure
+ *
+ * This function can just return %NULL if the crypto library does not support
+ * X.509 parsing. In that case, internal code will be used to parse the
+ * certificate and public key is imported using crypto_public_key_import().
+ *
+ * This function is only used with internal TLSv1 implementation
+ * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
+ * to implement this.
+ */
+struct crypto_public_key * crypto_public_key_from_cert(const u8 *buf,
+						       size_t len);
+
+/**
+ * crypto_public_key_encrypt_pkcs1_v15 - Public key encryption (PKCS #1 v1.5)
+ * @key: Public key
+ * @in: Plaintext buffer
+ * @inlen: Length of plaintext buffer in bytes
+ * @out: Output buffer for encrypted data
+ * @outlen: Length of output buffer in bytes; set to used length on success
+ * Returns: 0 on success, -1 on failure
+ *
+ * This function is only used with internal TLSv1 implementation
+ * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
+ * to implement this.
+ */
+int crypto_public_key_encrypt_pkcs1_v15(struct crypto_public_key *key,
+					const u8 *in, size_t inlen,
+					u8 *out, size_t *outlen);
+
+/**
+ * crypto_private_key_sign_pkcs1 - Sign with private key (PKCS #1)
+ * @key: Private key from crypto_private_key_import()
+ * @in: Plaintext buffer
+ * @inlen: Length of plaintext buffer in bytes
+ * @out: Output buffer for encrypted (signed) data
+ * @outlen: Length of output buffer in bytes; set to used length on success
+ * Returns: 0 on success, -1 on failure
+ *
+ * This function is only used with internal TLSv1 implementation
+ * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
+ * to implement this.
+ */
+int crypto_private_key_sign_pkcs1(struct crypto_private_key *key,
+				  const u8 *in, size_t inlen,
+				  u8 *out, size_t *outlen);
+
+/**
+ * crypto_public_key_free - Free public key
+ * @key: Public key
+ *
+ * This function is only used with internal TLSv1 implementation
+ * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
+ * to implement this.
+ */
+void crypto_public_key_free(struct crypto_public_key *key);
+
+/**
+ * crypto_private_key_free - Free private key
+ * @key: Private key from crypto_private_key_import()
+ *
+ * This function is only used with internal TLSv1 implementation
+ * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
+ * to implement this.
+ */
+void crypto_private_key_free(struct crypto_private_key *key);
+
+/**
+ * crypto_public_key_decrypt_pkcs1 - Decrypt PKCS #1 signature
+ * @key: Public key
+ * @crypt: Encrypted signature data (using the private key)
+ * @crypt_len: Encrypted signature data length
+ * @plain: Buffer for plaintext (at least crypt_len bytes)
+ * @plain_len: Plaintext length (max buffer size on input, real len on output);
+ * Returns: 0 on success, -1 on failure
+ */
+int crypto_public_key_decrypt_pkcs1(struct crypto_public_key *key,
+				    const u8 *crypt, size_t crypt_len,
+				    u8 *plain, size_t *plain_len);
+
+/**
+ * crypto_global_init - Initialize crypto wrapper
+ *
+ * This function is only used with internal TLSv1 implementation
+ * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
+ * to implement this.
+ */
+int crypto_global_init(void);
+
+/**
+ * crypto_global_deinit - Deinitialize crypto wrapper
+ *
+ * This function is only used with internal TLSv1 implementation
+ * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
+ * to implement this.
+ */
+void crypto_global_deinit(void);
+
+/**
+ * crypto_mod_exp - Modular exponentiation of large integers
+ * @base: Base integer (big endian byte array)
+ * @base_len: Length of base integer in bytes
+ * @power: Power integer (big endian byte array)
+ * @power_len: Length of power integer in bytes
+ * @modulus: Modulus integer (big endian byte array)
+ * @modulus_len: Length of modulus integer in bytes
+ * @result: Buffer for the result
+ * @result_len: Result length (max buffer size on input, real len on output)
+ * Returns: 0 on success, -1 on failure
+ *
+ * This function calculates result = base ^ power mod modulus. modules_len is
+ * used as the maximum size of modulus buffer. It is set to the used size on
+ * success.
+ *
+ * This function is only used with internal TLSv1 implementation
+ * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
+ * to implement this.
+ */
+int crypto_mod_exp(const u8 *base, size_t base_len,
+		   const u8 *power, size_t power_len,
+		   const u8 *modulus, size_t modulus_len,
+		   u8 *result, size_t *result_len);
+
 #endif /* CRYPTO_H */
Index: ctrl_iface.h
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/ctrl_iface.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/ctrl_iface.h -L contrib/wpa_supplicant/ctrl_iface.h -u -r1.2 -r1.3
--- contrib/wpa_supplicant/ctrl_iface.h
+++ contrib/wpa_supplicant/ctrl_iface.h
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant / UNIX domain socket -based control interface
- * Copyright (c) 2004-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2004-2005, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -17,45 +17,140 @@
 
 #ifdef CONFIG_CTRL_IFACE
 
-int wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s);
-void wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant *wpa_s);
-void wpa_supplicant_ctrl_iface_send(struct wpa_supplicant *wpa_s, int level,
-				    char *buf, size_t len);
-void wpa_supplicant_ctrl_iface_wait(struct wpa_supplicant *wpa_s);
-int wpa_supplicant_global_ctrl_iface_init(struct wpa_global *global);
-void wpa_supplicant_global_ctrl_iface_deinit(struct wpa_global *global);
+/* Shared functions from ctrl_iface.c; to be called by ctrl_iface backends */
+
+/**
+ * wpa_supplicant_ctrl_iface_process - Process ctrl_iface command
+ * @wpa_s: Pointer to wpa_supplicant data
+ * @buf: Received command buffer (nul terminated string)
+ * @resp_len: Variable to be set to the response length
+ * Returns: Response (*resp_len bytes) or %NULL on failure
+ *
+ * Control interface backends call this function when receiving a message that
+ * they do not process internally, i.e., anything else than ATTACH, DETACH,
+ * and LEVEL. The return response value is then sent to the external program
+ * that sent the command. Caller is responsible for freeing the buffer after
+ * this. If %NULL is returned, *resp_len can be set to two special values:
+ * 1 = send "FAIL\n" response, 2 = send "OK\n" response. If *resp_len has any
+ * other value, no response is sent.
+ */
+char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
+					 char *buf, size_t *resp_len);
+
+/**
+ * wpa_supplicant_ctrl_iface_process - Process global ctrl_iface command
+ * @global: Pointer to global data from wpa_supplicant_init()
+ * @buf: Received command buffer (nul terminated string)
+ * @resp_len: Variable to be set to the response length
+ * Returns: Response (*resp_len bytes) or %NULL on failure
+ *
+ * Control interface backends call this function when receiving a message from
+ * the global ctrl_iface connection. The return response value is then sent to
+ * the external program that sent the command. Caller is responsible for
+ * freeing the buffer after this. If %NULL is returned, *resp_len can be set to
+ * two special values: 1 = send "FAIL\n" response, 2 = send "OK\n" response. If
+ * *resp_len has any other value, no response is sent.
+ */
+char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global,
+						char *buf, size_t *resp_len);
+
+
+/* Functions that each ctrl_iface backend must implement */
+
+/**
+ * wpa_supplicant_ctrl_iface_init - Initialize control interface
+ * @wpa_s: Pointer to wpa_supplicant data
+ * Returns: Pointer to private data on success, %NULL on failure
+ *
+ * Initialize the control interface and start receiving commands from external
+ * programs.
+ *
+ * Required to be implemented in each control interface backend.
+ */
+struct ctrl_iface_priv *
+wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s);
+
+/**
+ * wpa_supplicant_ctrl_iface_deinit - Deinitialize control interface
+ * @priv: Pointer to private data from wpa_supplicant_ctrl_iface_init()
+ *
+ * Deinitialize the control interface that was initialized with
+ * wpa_supplicant_ctrl_iface_init().
+ *
+ * Required to be implemented in each control interface backend.
+ */
+void wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv);
+
+/**
+ * wpa_supplicant_ctrl_iface_wait - Wait for ctrl_iface monitor
+ * @priv: Pointer to private data from wpa_supplicant_ctrl_iface_init()
+ *
+ * Wait until the first message from an external program using the control
+ * interface is received. This function can be used to delay normal startup
+ * processing to allow control interface programs to attach with
+ * %wpa_supplicant before normal operations are started.
+ *
+ * Required to be implemented in each control interface backend.
+ */
+void wpa_supplicant_ctrl_iface_wait(struct ctrl_iface_priv *priv);
+
+/**
+ * wpa_supplicant_global_ctrl_iface_init - Initialize global control interface
+ * @global: Pointer to global data from wpa_supplicant_init()
+ * Returns: Pointer to private data on success, %NULL on failure
+ *
+ * Initialize the global control interface and start receiving commands from
+ * external programs.
+ *
+ * Required to be implemented in each control interface backend.
+ */
+struct ctrl_iface_global_priv *
+wpa_supplicant_global_ctrl_iface_init(struct wpa_global *global);
+
+/**
+ * wpa_supplicant_global_ctrl_iface_deinit - Deinitialize global ctrl interface
+ * @priv: Pointer to private data from wpa_supplicant_global_ctrl_iface_init()
+ *
+ * Deinitialize the global control interface that was initialized with
+ * wpa_supplicant_global_ctrl_iface_init().
+ *
+ * Required to be implemented in each control interface backend.
+ */
+void wpa_supplicant_global_ctrl_iface_deinit(
+	struct ctrl_iface_global_priv *priv);
 
 #else /* CONFIG_CTRL_IFACE */
 
-static inline int wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s)
+static inline struct ctrl_iface_priv *
+wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s)
 {
-	return 0;
+	return (void *) -1;
 }
 
 static inline void
-wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant *wpa_s)
+wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv)
 {
 }
 
 static inline void
-wpa_supplicant_ctrl_iface_send(struct wpa_supplicant *wpa_s, int level,
+wpa_supplicant_ctrl_iface_send(struct ctrl_iface_priv *priv, int level,
 			       char *buf, size_t len)
 {
 }
 
 static inline void
-wpa_supplicant_ctrl_iface_wait(struct wpa_supplicant *wpa_s)
+wpa_supplicant_ctrl_iface_wait(struct ctrl_iface_priv *priv)
 {
 }
 
-static inline int
+static inline struct ctrl_iface_global_priv *
 wpa_supplicant_global_ctrl_iface_init(struct wpa_global *global)
 {
-	return 0;
+	return (void *) 1;
 }
 
 static inline void
-wpa_supplicant_global_ctrl_iface_deinit(struct wpa_global *global)
+wpa_supplicant_global_ctrl_iface_deinit(struct ctrl_iface_global_priv *priv)
 {
 }
 
Index: eap_i.h
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/eap_i.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/eap_i.h -L contrib/wpa_supplicant/eap_i.h -u -r1.2 -r1.3
--- contrib/wpa_supplicant/eap_i.h
+++ contrib/wpa_supplicant/eap_i.h
@@ -1,6 +1,6 @@
 /*
- * WPA Supplicant / EAP state machines internal structures (RFC 4137)
- * Copyright (c) 2004-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * EAP peer state machines internal structures (RFC 4137)
+ * Copyright (c) 2004-2006, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -66,6 +66,11 @@
  */
 struct eap_method {
 	/**
+	 * vendor - EAP Vendor-ID (EAP_VENDOR_*) (0 = IETF)
+	 */
+	int vendor;
+
+	/**
 	 * method - EAP type number (EAP_TYPE_*)
 	 */
 	EapType method;
@@ -205,6 +210,64 @@
 	 * that use method specific identity need to implement.
 	 */
 	const u8 * (*get_identity)(struct eap_sm *sm, void *priv, size_t *len);
+
+	/**
+	 * free - Free EAP method data
+	 * @method: Pointer to the method data registered with
+	 * eap_peer_method_register().
+	 *
+	 * This function will be called when the EAP method is being
+	 * unregistered. If the EAP method allocated resources during
+	 * registration (e.g., allocated struct eap_method), they should be
+	 * freed in this function. No other method functions will be called
+	 * after this call. If this function is not defined (i.e., function
+	 * pointer is %NULL), a default handler is used to release the method
+	 * data with free(method). This is suitable for most cases.
+	 */
+	void (*free)(struct eap_method *method);
+
+#define EAP_PEER_METHOD_INTERFACE_VERSION 1
+	/**
+	 * version - Version of the EAP peer method interface
+	 *
+	 * The EAP peer method implementation should set this variable to
+	 * EAP_PEER_METHOD_INTERFACE_VERSION. This is used to verify that the
+	 * EAP method is using supported API version when using dynamically
+	 * loadable EAP methods.
+	 */
+	int version;
+
+	/**
+	 * next - Pointer to the next EAP method
+	 *
+	 * This variable is used internally in the EAP method registration code
+	 * to create a linked list of registered EAP methods.
+	 */
+	struct eap_method *next;
+
+#ifdef CONFIG_DYNAMIC_EAP_METHODS
+	/**
+	 * dl_handle - Handle for the dynamic library
+	 *
+	 * This variable is used internally in the EAP method registration code
+	 * to store a handle for the dynamic library. If the method is linked
+	 * in statically, this is %NULL.
+	 */
+	void *dl_handle;
+#endif /* CONFIG_DYNAMIC_EAP_METHODS */
+
+	/**
+	 * get_emsk - Get EAP method specific keying extended material (EMSK)
+	 * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+	 * @priv: Pointer to private EAP method data from eap_method::init()
+	 * @len: Pointer to a variable to store EMSK length
+	 * Returns: EMSK or %NULL if not available
+	 *
+	 * This function can be used to get the extended keying material from
+	 * the EAP method. The key may already be stored in the method-specific
+	 * private data or this function may derive the key.
+	 */
+	u8 * (*get_emsk)(struct eap_sm *sm, void *priv, size_t *len);
 };
 
 
@@ -231,6 +294,8 @@
 	Boolean rxFailure;
 	int reqId;
 	EapType reqMethod;
+	int reqVendor;
+	u32 reqVendorMethod;
 	Boolean ignore;
 	/* Constants */
 	int ClientTimeout;
@@ -266,15 +331,26 @@
 
 	/* Optional challenges generated in Phase 1 (EAP-FAST) */
 	u8 *peer_challenge, *auth_challenge;
+	int mschapv2_full_key; /* Request full MSCHAPv2 key */
 
 	int num_rounds;
 	int force_disabled;
 };
 
-const u8 * eap_hdr_validate(EapType eap_type, const u8 *msg, size_t msglen,
-			    size_t *plen);
+const u8 * eap_hdr_validate(int vendor, EapType eap_type,
+			    const u8 *msg, size_t msglen, size_t *plen);
+const u8 * eap_get_config_identity(struct eap_sm *sm, size_t *len);
+const u8 * eap_get_config_password(struct eap_sm *sm, size_t *len);
+const u8 * eap_get_config_new_password(struct eap_sm *sm, size_t *len);
+const u8 * eap_get_config_otp(struct eap_sm *sm, size_t *len);
+void eap_clear_config_otp(struct eap_sm *sm);
+struct wpa_ssid * eap_get_config(struct eap_sm *sm);
 void eap_set_config_blob(struct eap_sm *sm, struct wpa_config_blob *blob);
 const struct wpa_config_blob *
 eap_get_config_blob(struct eap_sm *sm, const char *name);
+struct eap_hdr * eap_msg_alloc(int vendor, EapType type, size_t *len,
+			       size_t payload_len, u8 code, u8 identifier,
+			       u8 **payload);
+void eap_notify_pending(struct eap_sm *sm);
 
 #endif /* EAP_I_H */
Index: defs.h
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/defs.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/defs.h -L contrib/wpa_supplicant/defs.h -u -r1.2 -r1.3
--- contrib/wpa_supplicant/defs.h
+++ contrib/wpa_supplicant/defs.h
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant - Common definitions
- * Copyright (c) 2004-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2004-2006, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -24,7 +24,8 @@
 typedef enum { FALSE = 0, TRUE = 1 } Boolean;
 
 
-typedef enum { WPA_ALG_NONE, WPA_ALG_WEP, WPA_ALG_TKIP, WPA_ALG_CCMP } wpa_alg;
+typedef enum { WPA_ALG_NONE, WPA_ALG_WEP, WPA_ALG_TKIP, WPA_ALG_CCMP,
+	       WPA_ALG_IGTK, WPA_ALG_DHV } wpa_alg;
 typedef enum { CIPHER_NONE, CIPHER_WEP40, CIPHER_TKIP, CIPHER_CCMP,
 	       CIPHER_WEP104 } wpa_cipher;
 typedef enum { KEY_MGMT_802_1X, KEY_MGMT_PSK, KEY_MGMT_NONE,
@@ -128,4 +129,12 @@
 	WPA_COMPLETED
 } wpa_states;
 
+#define MLME_SETPROTECTION_PROTECT_TYPE_NONE 0
+#define MLME_SETPROTECTION_PROTECT_TYPE_RX 1
+#define MLME_SETPROTECTION_PROTECT_TYPE_TX 2
+#define MLME_SETPROTECTION_PROTECT_TYPE_RX_TX 3
+
+#define MLME_SETPROTECTION_KEY_TYPE_GROUP 0
+#define MLME_SETPROTECTION_KEY_TYPE_PAIRWISE 1
+
 #endif /* DEFS_H */
Index: eloop.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/eloop.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/eloop.c -L contrib/wpa_supplicant/eloop.c -u -r1.2 -r1.3
--- contrib/wpa_supplicant/eloop.c
+++ contrib/wpa_supplicant/eloop.c
@@ -1,6 +1,6 @@
 /*
  * Event loop based on select() loop
- * Copyright (c) 2002-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2002-2005, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -12,19 +12,9 @@
  * See README and COPYING for more details.
  */
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <errno.h>
-#include <signal.h>
+#include "includes.h"
 
-#ifdef CONFIG_NATIVE_WINDOWS
 #include "common.h"
-#endif /* CONFIG_NATIVE_WINDOWS */
-
 #include "eloop.h"
 
 
@@ -32,29 +22,38 @@
 	int sock;
 	void *eloop_data;
 	void *user_data;
-	void (*handler)(int sock, void *eloop_ctx, void *sock_ctx);
+	eloop_sock_handler handler;
 };
 
 struct eloop_timeout {
-	struct timeval time;
+	struct os_time time;
 	void *eloop_data;
 	void *user_data;
-	void (*handler)(void *eloop_ctx, void *sock_ctx);
+	eloop_timeout_handler handler;
 	struct eloop_timeout *next;
 };
 
 struct eloop_signal {
 	int sig;
 	void *user_data;
-	void (*handler)(int sig, void *eloop_ctx, void *signal_ctx);
+	eloop_signal_handler handler;
 	int signaled;
 };
 
+struct eloop_sock_table {
+	int count;
+	struct eloop_sock *table;
+	int changed;
+};
+
 struct eloop_data {
 	void *user_data;
 
-	int max_sock, reader_count;
-	struct eloop_sock *readers;
+	int max_sock;
+
+	struct eloop_sock_table readers;
+	struct eloop_sock_table writers;
+	struct eloop_sock_table exceptions;
 
 	struct eloop_timeout *timeout;
 
@@ -64,81 +63,181 @@
 	int pending_terminate;
 
 	int terminate;
+	int reader_table_changed;
 };
 
 static struct eloop_data eloop;
 
 
-void eloop_init(void *user_data)
+int eloop_init(void *user_data)
 {
-	memset(&eloop, 0, sizeof(eloop));
+	os_memset(&eloop, 0, sizeof(eloop));
 	eloop.user_data = user_data;
+	return 0;
 }
 
 
-int eloop_register_read_sock(int sock,
-			     void (*handler)(int sock, void *eloop_ctx,
-					     void *sock_ctx),
-			     void *eloop_data, void *user_data)
+static int eloop_sock_table_add_sock(struct eloop_sock_table *table,
+                                     int sock, eloop_sock_handler handler,
+                                     void *eloop_data, void *user_data)
 {
 	struct eloop_sock *tmp;
 
+	if (table == NULL)
+		return -1;
+
 	tmp = (struct eloop_sock *)
-		realloc(eloop.readers,
-			(eloop.reader_count + 1) * sizeof(struct eloop_sock));
+		os_realloc(table->table,
+			   (table->count + 1) * sizeof(struct eloop_sock));
 	if (tmp == NULL)
 		return -1;
 
-	tmp[eloop.reader_count].sock = sock;
-	tmp[eloop.reader_count].eloop_data = eloop_data;
-	tmp[eloop.reader_count].user_data = user_data;
-	tmp[eloop.reader_count].handler = handler;
-	eloop.reader_count++;
-	eloop.readers = tmp;
+	tmp[table->count].sock = sock;
+	tmp[table->count].eloop_data = eloop_data;
+	tmp[table->count].user_data = user_data;
+	tmp[table->count].handler = handler;
+	table->count++;
+	table->table = tmp;
 	if (sock > eloop.max_sock)
 		eloop.max_sock = sock;
+	table->changed = 1;
 
 	return 0;
 }
 
 
-void eloop_unregister_read_sock(int sock)
+static void eloop_sock_table_remove_sock(struct eloop_sock_table *table,
+                                         int sock)
 {
 	int i;
 
-	if (eloop.readers == NULL || eloop.reader_count == 0)
+	if (table == NULL || table->table == NULL || table->count == 0)
 		return;
 
-	for (i = 0; i < eloop.reader_count; i++) {
-		if (eloop.readers[i].sock == sock)
+	for (i = 0; i < table->count; i++) {
+		if (table->table[i].sock == sock)
 			break;
 	}
-	if (i == eloop.reader_count)
+	if (i == table->count)
 		return;
-	if (i != eloop.reader_count - 1) {
-		memmove(&eloop.readers[i], &eloop.readers[i + 1],
-			(eloop.reader_count - i - 1) *
-			sizeof(struct eloop_sock));
+	if (i != table->count - 1) {
+		os_memmove(&table->table[i], &table->table[i + 1],
+			   (table->count - i - 1) *
+			   sizeof(struct eloop_sock));
+	}
+	table->count--;
+	table->changed = 1;
+}
+
+
+static void eloop_sock_table_set_fds(struct eloop_sock_table *table,
+				     fd_set *fds)
+{
+	int i;
+
+	FD_ZERO(fds);
+
+	if (table->table == NULL)
+		return;
+
+	for (i = 0; i < table->count; i++)
+		FD_SET(table->table[i].sock, fds);
+}
+
+
+static void eloop_sock_table_dispatch(struct eloop_sock_table *table,
+				      fd_set *fds)
+{
+	int i;
+
+	if (table == NULL || table->table == NULL)
+		return;
+
+	table->changed = 0;
+	for (i = 0; i < table->count; i++) {
+		if (FD_ISSET(table->table[i].sock, fds)) {
+			table->table[i].handler(table->table[i].sock,
+						table->table[i].eloop_data,
+						table->table[i].user_data);
+			if (table->changed)
+				break;
+		}
+	}
+}
+
+
+static void eloop_sock_table_destroy(struct eloop_sock_table *table)
+{
+	if (table)
+		os_free(table->table);
+}
+
+
+int eloop_register_read_sock(int sock, eloop_sock_handler handler,
+			     void *eloop_data, void *user_data)
+{
+	return eloop_register_sock(sock, EVENT_TYPE_READ, handler,
+				   eloop_data, user_data);
+}
+
+
+void eloop_unregister_read_sock(int sock)
+{
+	eloop_unregister_sock(sock, EVENT_TYPE_READ);
+}
+
+
+static struct eloop_sock_table *eloop_get_sock_table(eloop_event_type type)
+{
+	switch (type) {
+	case EVENT_TYPE_READ:
+		return &eloop.readers;
+	case EVENT_TYPE_WRITE:
+		return &eloop.writers;
+	case EVENT_TYPE_EXCEPTION:
+		return &eloop.exceptions;
 	}
-	eloop.reader_count--;
+
+	return NULL;
+}
+
+
+int eloop_register_sock(int sock, eloop_event_type type,
+			eloop_sock_handler handler,
+			void *eloop_data, void *user_data)
+{
+	struct eloop_sock_table *table;
+
+	table = eloop_get_sock_table(type);
+	return eloop_sock_table_add_sock(table, sock, handler,
+					 eloop_data, user_data);
+}
+
+
+void eloop_unregister_sock(int sock, eloop_event_type type)
+{
+	struct eloop_sock_table *table;
+
+	table = eloop_get_sock_table(type);
+	eloop_sock_table_remove_sock(table, sock);
 }
 
 
 int eloop_register_timeout(unsigned int secs, unsigned int usecs,
-			   void (*handler)(void *eloop_ctx, void *timeout_ctx),
+			   eloop_timeout_handler handler,
 			   void *eloop_data, void *user_data)
 {
 	struct eloop_timeout *timeout, *tmp, *prev;
 
-	timeout = (struct eloop_timeout *) malloc(sizeof(*timeout));
+	timeout = os_malloc(sizeof(*timeout));
 	if (timeout == NULL)
 		return -1;
-	gettimeofday(&timeout->time, NULL);
-	timeout->time.tv_sec += secs;
-	timeout->time.tv_usec += usecs;
-	while (timeout->time.tv_usec >= 1000000) {
-		timeout->time.tv_sec++;
-		timeout->time.tv_usec -= 1000000;
+	os_get_time(&timeout->time);
+	timeout->time.sec += secs;
+	timeout->time.usec += usecs;
+	while (timeout->time.usec >= 1000000) {
+		timeout->time.sec++;
+		timeout->time.usec -= 1000000;
 	}
 	timeout->eloop_data = eloop_data;
 	timeout->user_data = user_data;
@@ -153,7 +252,7 @@
 	prev = NULL;
 	tmp = eloop.timeout;
 	while (tmp != NULL) {
-		if (timercmp(&timeout->time, &tmp->time, <))
+		if (os_time_before(&timeout->time, &tmp->time))
 			break;
 		prev = tmp;
 		tmp = tmp->next;
@@ -171,7 +270,7 @@
 }
 
 
-int eloop_cancel_timeout(void (*handler)(void *eloop_ctx, void *sock_ctx),
+int eloop_cancel_timeout(eloop_timeout_handler handler,
 			 void *eloop_data, void *user_data)
 {
 	struct eloop_timeout *timeout, *prev, *next;
@@ -191,7 +290,7 @@
 				eloop.timeout = next;
 			else
 				prev->next = next;
-			free(timeout);
+			os_free(timeout);
 			removed++;
 		} else
 			prev = timeout;
@@ -266,17 +365,15 @@
 }
 
 
-int eloop_register_signal(int sig,
-			  void (*handler)(int sig, void *eloop_ctx,
-					  void *signal_ctx),
+int eloop_register_signal(int sig, eloop_signal_handler handler,
 			  void *user_data)
 {
 	struct eloop_signal *tmp;
 
 	tmp = (struct eloop_signal *)
-		realloc(eloop.signals,
-			(eloop.signal_count + 1) *
-			sizeof(struct eloop_signal));
+		os_realloc(eloop.signals,
+			   (eloop.signal_count + 1) *
+			   sizeof(struct eloop_signal));
 	if (tmp == NULL)
 		return -1;
 
@@ -292,41 +389,67 @@
 }
 
 
-void eloop_run(void)
+int eloop_register_signal_terminate(eloop_signal_handler handler,
+				    void *user_data)
 {
-	fd_set *rfds;
-	int i, res;
-	struct timeval tv, now;
+	int ret = eloop_register_signal(SIGINT, handler, user_data);
+	if (ret == 0)
+		ret = eloop_register_signal(SIGTERM, handler, user_data);
+	return ret;
+}
+
 
-	rfds = malloc(sizeof(*rfds));
-	if (rfds == NULL) {
+int eloop_register_signal_reconfig(eloop_signal_handler handler,
+				   void *user_data)
+{
+#ifdef CONFIG_NATIVE_WINDOWS
+	return 0;
+#else /* CONFIG_NATIVE_WINDOWS */
+	return eloop_register_signal(SIGHUP, handler, user_data);
+#endif /* CONFIG_NATIVE_WINDOWS */
+}
+
+
+void eloop_run(void)
+{
+	fd_set *rfds, *wfds, *efds;
+	int res;
+	struct timeval _tv;
+	struct os_time tv, now;
+
+	rfds = os_malloc(sizeof(*rfds));
+	wfds = os_malloc(sizeof(*wfds));
+	efds = os_malloc(sizeof(*efds));
+	if (rfds == NULL || wfds == NULL || efds == NULL) {
 		printf("eloop_run - malloc failed\n");
-		return;
+		goto out;
 	}
 
 	while (!eloop.terminate &&
-		(eloop.timeout || eloop.reader_count > 0)) {
+	       (eloop.timeout || eloop.readers.count > 0 ||
+		eloop.writers.count > 0 || eloop.exceptions.count > 0)) {
 		if (eloop.timeout) {
-			gettimeofday(&now, NULL);
-			if (timercmp(&now, &eloop.timeout->time, <))
-				timersub(&eloop.timeout->time, &now, &tv);
+			os_get_time(&now);
+			if (os_time_before(&now, &eloop.timeout->time))
+				os_time_sub(&eloop.timeout->time, &now, &tv);
 			else
-				tv.tv_sec = tv.tv_usec = 0;
+				tv.sec = tv.usec = 0;
 #if 0
 			printf("next timeout in %lu.%06lu sec\n",
-			       tv.tv_sec, tv.tv_usec);
+			       tv.sec, tv.usec);
 #endif
+			_tv.tv_sec = tv.sec;
+			_tv.tv_usec = tv.usec;
 		}
 
-		FD_ZERO(rfds);
-		for (i = 0; i < eloop.reader_count; i++)
-			FD_SET(eloop.readers[i].sock, rfds);
-		res = select(eloop.max_sock + 1, rfds, NULL, NULL,
-			     eloop.timeout ? &tv : NULL);
-		if (res < 0 && errno != EINTR) {
+		eloop_sock_table_set_fds(&eloop.readers, rfds);
+		eloop_sock_table_set_fds(&eloop.writers, wfds);
+		eloop_sock_table_set_fds(&eloop.exceptions, efds);
+		res = select(eloop.max_sock + 1, rfds, wfds, efds,
+			     eloop.timeout ? &_tv : NULL);
+		if (res < 0 && errno != EINTR && errno != 0) {
 			perror("select");
-			free(rfds);
-			return;
+			goto out;
 		}
 		eloop_process_pending_signals();
 
@@ -334,13 +457,13 @@
 		if (eloop.timeout) {
 			struct eloop_timeout *tmp;
 
-			gettimeofday(&now, NULL);
-			if (!timercmp(&now, &eloop.timeout->time, <)) {
+			os_get_time(&now);
+			if (!os_time_before(&now, &eloop.timeout->time)) {
 				tmp = eloop.timeout;
 				eloop.timeout = eloop.timeout->next;
 				tmp->handler(tmp->eloop_data,
 					     tmp->user_data);
-				free(tmp);
+				os_free(tmp);
 			}
 
 		}
@@ -348,17 +471,15 @@
 		if (res <= 0)
 			continue;
 
-		for (i = 0; i < eloop.reader_count; i++) {
-			if (FD_ISSET(eloop.readers[i].sock, rfds)) {
-				eloop.readers[i].handler(
-					eloop.readers[i].sock,
-					eloop.readers[i].eloop_data,
-					eloop.readers[i].user_data);
-			}
-		}
+		eloop_sock_table_dispatch(&eloop.readers, rfds);
+		eloop_sock_table_dispatch(&eloop.writers, wfds);
+		eloop_sock_table_dispatch(&eloop.exceptions, efds);
 	}
 
-	free(rfds);
+out:
+	os_free(rfds);
+	os_free(wfds);
+	os_free(efds);
 }
 
 
@@ -376,10 +497,12 @@
 	while (timeout != NULL) {
 		prev = timeout;
 		timeout = timeout->next;
-		free(prev);
+		os_free(prev);
 	}
-	free(eloop.readers);
-	free(eloop.signals);
+	eloop_sock_table_destroy(&eloop.readers);
+	eloop_sock_table_destroy(&eloop.writers);
+	eloop_sock_table_destroy(&eloop.exceptions);
+	os_free(eloop.signals);
 }
 
 
@@ -387,3 +510,22 @@
 {
 	return eloop.terminate;
 }
+
+
+void eloop_wait_for_read_sock(int sock)
+{
+	fd_set rfds;
+
+	if (sock < 0)
+		return;
+
+	FD_ZERO(&rfds);
+	FD_SET(sock, &rfds);
+	select(sock + 1, &rfds, NULL, NULL, NULL);
+}
+
+
+void * eloop_get_user_data(void)
+{
+	return eloop.user_data;
+}
Index: radius_client.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/radius_client.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/radius_client.c -L contrib/wpa_supplicant/radius_client.c -u -r1.2 -r1.3
--- contrib/wpa_supplicant/radius_client.c
+++ contrib/wpa_supplicant/radius_client.c
@@ -1,7 +1,6 @@
 /*
- * Host AP (software wireless LAN access point) user space daemon for
- * Host AP kernel driver / RADIUS client
- * Copyright (c) 2002-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * hostapd / RADIUS client
+ * Copyright (c) 2002-2005, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -13,19 +12,7 @@
  * See README and COPYING for more details.
  */
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <time.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <errno.h>
-#ifndef CONFIG_NATIVE_WINDOWS
-#include <netinet/in.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-#endif /* CONFIG_NATIVE_WINDOWS */
+#include "includes.h"
 
 #include "hostapd.h"
 #include "radius.h"
@@ -60,11 +47,11 @@
 			    * for the same STA. */
 	struct radius_msg *msg;
 	RadiusType msg_type;
-	time_t first_try;
-	time_t next_try;
+	os_time_t first_try;
+	os_time_t next_try;
 	int attempts;
 	int next_wait;
-	struct timeval last_attempt;
+	struct os_time last_attempt;
 
 	u8 *shared_secret;
 	size_t shared_secret_len;
@@ -110,8 +97,8 @@
 static void radius_client_msg_free(struct radius_msg_list *req)
 {
 	radius_msg_free(req->msg);
-	free(req->msg);
-	free(req);
+	os_free(req->msg);
+	os_free(req);
 }
 
 
@@ -135,9 +122,8 @@
 		num = &radius->num_auth_handlers;
 	}
 
-	newh = (struct radius_rx_handler *)
-		realloc(*handlers,
-			(*num + 1) * sizeof(struct radius_rx_handler));
+	newh = os_realloc(*handlers,
+			  (*num + 1) * sizeof(struct radius_rx_handler));
 	if (newh == NULL)
 		return -1;
 
@@ -173,7 +159,8 @@
 
 
 static int radius_client_retransmit(struct radius_client_data *radius,
-				    struct radius_msg_list *entry, time_t now)
+				    struct radius_msg_list *entry,
+				    os_time_t now)
 {
 	struct hostapd_radius_servers *conf = radius->conf;
 	int s;
@@ -203,7 +190,7 @@
 		       HOSTAPD_LEVEL_DEBUG, "Resending RADIUS message (id=%d)",
 		       entry->msg->hdr->identifier);
 
-	gettimeofday(&entry->last_attempt, NULL);
+	os_get_time(&entry->last_attempt);
 	if (send(s, entry->msg->buf, entry->msg->buf_used, 0) < 0)
 		radius_client_handle_send_error(radius, s, entry->msg_type);
 
@@ -225,7 +212,8 @@
 {
 	struct radius_client_data *radius = eloop_ctx;
 	struct hostapd_radius_servers *conf = radius->conf;
-	time_t now, first;
+	struct os_time now;
+	os_time_t first;
 	struct radius_msg_list *entry, *prev, *tmp;
 	int auth_failover = 0, acct_failover = 0;
 	char abuf[50];
@@ -234,13 +222,13 @@
 	if (!entry)
 		return;
 
-	time(&now);
+	os_get_time(&now);
 	first = 0;
 
 	prev = NULL;
 	while (entry) {
-		if (now >= entry->next_try &&
-		    radius_client_retransmit(radius, entry, now)) {
+		if (now.sec >= entry->next_try &&
+		    radius_client_retransmit(radius, entry, now.sec)) {
 			if (prev)
 				prev->next = entry->next;
 			else
@@ -269,14 +257,14 @@
 	}
 
 	if (radius->msgs) {
-		if (first < now)
-			first = now;
-		eloop_register_timeout(first - now, 0,
+		if (first < now.sec)
+			first = now.sec;
+		eloop_register_timeout(first - now.sec, 0,
 				       radius_client_timer, radius, NULL);
 		hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
 			       HOSTAPD_LEVEL_DEBUG, "Next RADIUS client "
 			       "retransmit in %ld seconds",
-			       (long int) (first - now));
+			       (long int) (first - now.sec));
 	}
 
 	if (auth_failover && conf->num_auth_servers > 1) {
@@ -332,7 +320,8 @@
 
 static void radius_client_update_timeout(struct radius_client_data *radius)
 {
-	time_t now, first;
+	struct os_time now;
+	os_time_t first;
 	struct radius_msg_list *entry;
 
 	eloop_cancel_timeout(radius_client_timer, radius, NULL);
@@ -347,21 +336,21 @@
 			first = entry->next_try;
 	}
 
-	time(&now);
-	if (first < now)
-		first = now;
-	eloop_register_timeout(first - now, 0, radius_client_timer, radius,
+	os_get_time(&now);
+	if (first < now.sec)
+		first = now.sec;
+	eloop_register_timeout(first - now.sec, 0, radius_client_timer, radius,
 			       NULL);
 	hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
 		       HOSTAPD_LEVEL_DEBUG, "Next RADIUS client retransmit in"
-		       " %ld seconds\n", (long int) (first - now));
+		       " %ld seconds\n", (long int) (first - now.sec));
 }
 
 
 static void radius_client_list_add(struct radius_client_data *radius,
 				   struct radius_msg *msg,
 				   RadiusType msg_type, u8 *shared_secret,
-				   size_t shared_secret_len, u8 *addr)
+				   size_t shared_secret_len, const u8 *addr)
 {
 	struct radius_msg_list *entry, *prev;
 
@@ -369,29 +358,28 @@
 		/* No point in adding entries to retransmit queue since event
 		 * loop has already been terminated. */
 		radius_msg_free(msg);
-		free(msg);
+		os_free(msg);
 		return;
 	}
 
-	entry = malloc(sizeof(*entry));
+	entry = wpa_zalloc(sizeof(*entry));
 	if (entry == NULL) {
 		printf("Failed to add RADIUS packet into retransmit list\n");
 		radius_msg_free(msg);
-		free(msg);
+		os_free(msg);
 		return;
 	}
 
-	memset(entry, 0, sizeof(*entry));
 	if (addr)
-		memcpy(entry->addr, addr, ETH_ALEN);
+		os_memcpy(entry->addr, addr, ETH_ALEN);
 	entry->msg = msg;
 	entry->msg_type = msg_type;
 	entry->shared_secret = shared_secret;
 	entry->shared_secret_len = shared_secret_len;
-	time(&entry->first_try);
+	os_get_time(&entry->last_attempt);
+	entry->first_try = entry->last_attempt.sec;
 	entry->next_try = entry->first_try + RADIUS_CLIENT_FIRST_WAIT;
 	entry->attempts = 1;
-	gettimeofday(&entry->last_attempt, NULL);
 	entry->next_wait = RADIUS_CLIENT_FIRST_WAIT * 2;
 	entry->next = radius->msgs;
 	radius->msgs = entry;
@@ -415,7 +403,7 @@
 
 
 static void radius_client_list_del(struct radius_client_data *radius,
-				   RadiusType msg_type, u8 *addr)
+				   RadiusType msg_type, const u8 *addr)
 {
 	struct radius_msg_list *entry, *prev, *tmp;
 
@@ -426,7 +414,7 @@
 	prev = NULL;
 	while (entry) {
 		if (entry->msg_type == msg_type &&
-		    memcmp(entry->addr, addr, ETH_ALEN) == 0) {
+		    os_memcmp(entry->addr, addr, ETH_ALEN) == 0) {
 			if (prev)
 				prev->next = entry->next;
 			else
@@ -448,7 +436,8 @@
 
 
 int radius_client_send(struct radius_client_data *radius,
-		       struct radius_msg *msg, RadiusType msg_type, u8 *addr)
+		       struct radius_msg *msg, RadiusType msg_type,
+		       const u8 *addr)
 {
 	struct hostapd_radius_servers *conf = radius->conf;
 	u8 *shared_secret;
@@ -499,13 +488,13 @@
 	struct radius_client_data *radius = eloop_ctx;
 	struct hostapd_radius_servers *conf = radius->conf;
 	RadiusType msg_type = (RadiusType) sock_ctx;
-	int len, i, roundtrip;
+	int len, roundtrip;
 	unsigned char buf[3000];
 	struct radius_msg *msg;
 	struct radius_rx_handler *handlers;
-	size_t num_handlers;
+	size_t num_handlers, i;
 	struct radius_msg_list *req, *prev_req;
-	struct timeval tv;
+	struct os_time now;
 	struct hostapd_radius_server *rconf;
 	int invalid_authenticator = 0;
 
@@ -584,9 +573,9 @@
 		goto fail;
 	}
 
-	gettimeofday(&tv, NULL);
-	roundtrip = (tv.tv_sec - req->last_attempt.tv_sec) * 100 +
-		(tv.tv_usec - req->last_attempt.tv_usec) / 10000;
+	os_get_time(&now);
+	roundtrip = (now.sec - req->last_attempt.sec) * 100 +
+		(now.usec - req->last_attempt.usec) / 10000;
 	hostapd_logger(radius->ctx, req->addr, HOSTAPD_MODULE_RADIUS,
 		       HOSTAPD_LEVEL_DEBUG,
 		       "Received RADIUS packet matched with a pending "
@@ -609,7 +598,7 @@
 		switch (res) {
 		case RADIUS_RX_PROCESSED:
 			radius_msg_free(msg);
-			free(msg);
+			os_free(msg);
 			/* continue */
 		case RADIUS_RX_QUEUED:
 			radius_client_msg_free(req);
@@ -637,13 +626,13 @@
 
  fail:
 	radius_msg_free(msg);
-	free(msg);
+	os_free(msg);
 }
 
 
 u8 radius_client_get_id(struct radius_client_data *radius)
 {
-	struct radius_msg_list *entry, *prev, *remove;
+	struct radius_msg_list *entry, *prev, *_remove;
 	u8 id = radius->next_radius_identifier++;
 
 	/* remove entries with matching id from retransmit list to avoid
@@ -661,36 +650,69 @@
 				prev->next = entry->next;
 			else
 				radius->msgs = entry->next;
-			remove = entry;
-		} else
-			remove = NULL;
-		prev = entry;
+			_remove = entry;
+		} else {
+			_remove = NULL;
+			prev = entry;
+		}
 		entry = entry->next;
 
-		if (remove)
-			radius_client_msg_free(remove);
+		if (_remove)
+			radius_client_msg_free(_remove);
 	}
 
 	return id;
 }
 
 
-void radius_client_flush(struct radius_client_data *radius)
+void radius_client_flush(struct radius_client_data *radius, int only_auth)
 {
-	struct radius_msg_list *entry, *prev;
+	struct radius_msg_list *entry, *prev, *tmp;
 
 	if (!radius)
 		return;
 
-	eloop_cancel_timeout(radius_client_timer, radius, NULL);
-
+	prev = NULL;
 	entry = radius->msgs;
-	radius->msgs = NULL;
-	radius->num_msgs = 0;
+
 	while (entry) {
-		prev = entry;
-		entry = entry->next;
-		radius_client_msg_free(prev);
+		if (!only_auth || entry->msg_type == RADIUS_AUTH) {
+			if (prev)
+				prev->next = entry->next;
+			else
+				radius->msgs = entry->next;
+
+			tmp = entry;
+			entry = entry->next;
+			radius_client_msg_free(tmp);
+			radius->num_msgs--;
+		} else {
+			prev = entry;
+			entry = entry->next;
+		}
+	}
+
+	if (radius->msgs == NULL)
+		eloop_cancel_timeout(radius_client_timer, radius, NULL);
+}
+
+
+void radius_client_update_acct_msgs(struct radius_client_data *radius,
+				    u8 *shared_secret,
+				    size_t shared_secret_len)
+{
+	struct radius_msg_list *entry;
+
+	if (!radius)
+		return;
+
+	for (entry = radius->msgs; entry; entry = entry->next) {
+		if (entry->msg_type == RADIUS_ACCT) {
+			entry->shared_secret = shared_secret;
+			entry->shared_secret_len = shared_secret_len;
+			radius_msg_finish_acct(entry->msg, shared_secret,
+					       shared_secret_len);
+		}
 	}
 }
 
@@ -709,6 +731,7 @@
 	socklen_t addrlen;
 	char abuf[50];
 	int sel_sock;
+	struct radius_msg_list *entry;
 
 	hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
 		       HOSTAPD_LEVEL_INFO,
@@ -718,37 +741,43 @@
 		       nserv->port);
 
 	if (!oserv || nserv->shared_secret_len != oserv->shared_secret_len ||
-	    memcmp(nserv->shared_secret, oserv->shared_secret,
-		   nserv->shared_secret_len) != 0) {
-		/* Pending RADIUS packets used different shared
-		 * secret, so they would need to be modified. Could
-		 * update all message authenticators and
-		 * User-Passwords, etc. and retry with new server. For
-		 * now, just drop all pending packets. */
-		radius_client_flush(radius);
-	} else {
-		/* Reset retry counters for the new server */
-		struct radius_msg_list *entry;
-		entry = radius->msgs;
-		while (entry) {
-			entry->next_try = entry->first_try +
-				RADIUS_CLIENT_FIRST_WAIT;
-			entry->attempts = 0;
-			entry->next_wait = RADIUS_CLIENT_FIRST_WAIT * 2;
-			entry = entry->next;
-		}
-		if (radius->msgs) {
-			eloop_cancel_timeout(radius_client_timer, radius,
-					     NULL);
-			eloop_register_timeout(RADIUS_CLIENT_FIRST_WAIT, 0,
-					       radius_client_timer, radius,
-					       NULL);
+	    os_memcmp(nserv->shared_secret, oserv->shared_secret,
+		      nserv->shared_secret_len) != 0) {
+		/* Pending RADIUS packets used different shared secret, so
+		 * they need to be modified. Update accounting message
+		 * authenticators here. Authentication messages are removed
+		 * since they would require more changes and the new RADIUS
+		 * server may not be prepared to receive them anyway due to
+		 * missing state information. Client will likely retry
+		 * authentication, so this should not be an issue. */
+		if (auth)
+			radius_client_flush(radius, 1);
+		else {
+			radius_client_update_acct_msgs(
+				radius, nserv->shared_secret,
+				nserv->shared_secret_len);
 		}
 	}
 
+	/* Reset retry counters for the new server */
+	for (entry = radius->msgs; entry; entry = entry->next) {
+		if ((auth && entry->msg_type != RADIUS_AUTH) ||
+		    (!auth && entry->msg_type != RADIUS_ACCT))
+			continue;
+		entry->next_try = entry->first_try + RADIUS_CLIENT_FIRST_WAIT;
+		entry->attempts = 0;
+		entry->next_wait = RADIUS_CLIENT_FIRST_WAIT * 2;
+	}
+
+	if (radius->msgs) {
+		eloop_cancel_timeout(radius_client_timer, radius, NULL);
+		eloop_register_timeout(RADIUS_CLIENT_FIRST_WAIT, 0,
+				       radius_client_timer, radius, NULL);
+	}
+
 	switch (nserv->addr.af) {
 	case AF_INET:
-		memset(&serv, 0, sizeof(serv));
+		os_memset(&serv, 0, sizeof(serv));
 		serv.sin_family = AF_INET;
 		serv.sin_addr.s_addr = nserv->addr.u.v4.s_addr;
 		serv.sin_port = htons(nserv->port);
@@ -758,10 +787,10 @@
 		break;
 #ifdef CONFIG_IPV6
 	case AF_INET6:
-		memset(&serv6, 0, sizeof(serv6));
+		os_memset(&serv6, 0, sizeof(serv6));
 		serv6.sin6_family = AF_INET6;
-		memcpy(&serv6.sin6_addr, &nserv->addr.u.v6,
-		       sizeof(struct in6_addr));
+		os_memcpy(&serv6.sin6_addr, &nserv->addr.u.v6,
+			  sizeof(struct in6_addr));
 		serv6.sin6_port = htons(nserv->port);
 		addr = (struct sockaddr *) &serv6;
 		addrlen = sizeof(serv6);
@@ -878,6 +907,17 @@
 	else
 		ok++;
 
+#ifdef CONFIG_IPV6
+	radius->acct_serv_sock6 = socket(PF_INET6, SOCK_DGRAM, 0);
+	if (radius->acct_serv_sock6 < 0)
+		perror("socket[PF_INET6,SOCK_DGRAM]");
+	else
+		ok++;
+#endif /* CONFIG_IPV6 */
+
+	if (ok == 0)
+		return -1;
+
 	radius_change_server(radius, conf->acct_server, NULL,
 			     radius->acct_serv_sock, radius->acct_serv_sock6,
 			     0);
@@ -911,11 +951,10 @@
 {
 	struct radius_client_data *radius;
 
-	radius = malloc(sizeof(struct radius_client_data));
+	radius = wpa_zalloc(sizeof(struct radius_client_data));
 	if (radius == NULL)
 		return NULL;
 
-	memset(radius, 0, sizeof(struct radius_client_data));
 	radius->ctx = ctx;
 	radius->conf = conf;
 	radius->auth_serv_sock = radius->acct_serv_sock =
@@ -946,12 +985,17 @@
 	if (!radius)
 		return;
 
+	if (radius->auth_serv_sock >= 0)
+		eloop_unregister_read_sock(radius->auth_serv_sock);
+	if (radius->acct_serv_sock >= 0)
+		eloop_unregister_read_sock(radius->acct_serv_sock);
+
 	eloop_cancel_timeout(radius_retry_primary_timer, radius, NULL);
 
-	radius_client_flush(radius);
-	free(radius->auth_handlers);
-	free(radius->acct_handlers);
-	free(radius);
+	radius_client_flush(radius, 0);
+	os_free(radius->auth_handlers);
+	os_free(radius->acct_handlers);
+	os_free(radius);
 }
 
 
@@ -963,7 +1007,7 @@
 	entry = radius->msgs;
 	while (entry) {
 		if (entry->msg_type == RADIUS_AUTH &&
-		    memcmp(entry->addr, addr, ETH_ALEN) == 0) {
+		    os_memcmp(entry->addr, addr, ETH_ALEN) == 0) {
 			hostapd_logger(radius->ctx, addr,
 				       HOSTAPD_MODULE_RADIUS,
 				       HOSTAPD_LEVEL_DEBUG,
@@ -1003,37 +1047,37 @@
 		}
 	}
 
-	return snprintf(buf, buflen,
-			"radiusAuthServerIndex=%d\n"
-			"radiusAuthServerAddress=%s\n"
-			"radiusAuthClientServerPortNumber=%d\n"
-			"radiusAuthClientRoundTripTime=%d\n"
-			"radiusAuthClientAccessRequests=%u\n"
-			"radiusAuthClientAccessRetransmissions=%u\n"
-			"radiusAuthClientAccessAccepts=%u\n"
-			"radiusAuthClientAccessRejects=%u\n"
-			"radiusAuthClientAccessChallenges=%u\n"
-			"radiusAuthClientMalformedAccessResponses=%u\n"
-			"radiusAuthClientBadAuthenticators=%u\n"
-			"radiusAuthClientPendingRequests=%u\n"
-			"radiusAuthClientTimeouts=%u\n"
-			"radiusAuthClientUnknownTypes=%u\n"
-			"radiusAuthClientPacketsDropped=%u\n",
-			serv->index,
-			hostapd_ip_txt(&serv->addr, abuf, sizeof(abuf)),
-			serv->port,
-			serv->round_trip_time,
-			serv->requests,
-			serv->retransmissions,
-			serv->access_accepts,
-			serv->access_rejects,
-			serv->access_challenges,
-			serv->malformed_responses,
-			serv->bad_authenticators,
-			pending,
-			serv->timeouts,
-			serv->unknown_types,
-			serv->packets_dropped);
+	return os_snprintf(buf, buflen,
+			   "radiusAuthServerIndex=%d\n"
+			   "radiusAuthServerAddress=%s\n"
+			   "radiusAuthClientServerPortNumber=%d\n"
+			   "radiusAuthClientRoundTripTime=%d\n"
+			   "radiusAuthClientAccessRequests=%u\n"
+			   "radiusAuthClientAccessRetransmissions=%u\n"
+			   "radiusAuthClientAccessAccepts=%u\n"
+			   "radiusAuthClientAccessRejects=%u\n"
+			   "radiusAuthClientAccessChallenges=%u\n"
+			   "radiusAuthClientMalformedAccessResponses=%u\n"
+			   "radiusAuthClientBadAuthenticators=%u\n"
+			   "radiusAuthClientPendingRequests=%u\n"
+			   "radiusAuthClientTimeouts=%u\n"
+			   "radiusAuthClientUnknownTypes=%u\n"
+			   "radiusAuthClientPacketsDropped=%u\n",
+			   serv->index,
+			   hostapd_ip_txt(&serv->addr, abuf, sizeof(abuf)),
+			   serv->port,
+			   serv->round_trip_time,
+			   serv->requests,
+			   serv->retransmissions,
+			   serv->access_accepts,
+			   serv->access_rejects,
+			   serv->access_challenges,
+			   serv->malformed_responses,
+			   serv->bad_authenticators,
+			   pending,
+			   serv->timeouts,
+			   serv->unknown_types,
+			   serv->packets_dropped);
 }
 
 
@@ -1053,33 +1097,33 @@
 		}
 	}
 
-	return snprintf(buf, buflen,
-			"radiusAccServerIndex=%d\n"
-			"radiusAccServerAddress=%s\n"
-			"radiusAccClientServerPortNumber=%d\n"
-			"radiusAccClientRoundTripTime=%d\n"
-			"radiusAccClientRequests=%u\n"
-			"radiusAccClientRetransmissions=%u\n"
-			"radiusAccClientResponses=%u\n"
-			"radiusAccClientMalformedResponses=%u\n"
-			"radiusAccClientBadAuthenticators=%u\n"
-			"radiusAccClientPendingRequests=%u\n"
-			"radiusAccClientTimeouts=%u\n"
-			"radiusAccClientUnknownTypes=%u\n"
-			"radiusAccClientPacketsDropped=%u\n",
-			serv->index,
-			hostapd_ip_txt(&serv->addr, abuf, sizeof(abuf)),
-			serv->port,
-			serv->round_trip_time,
-			serv->requests,
-			serv->retransmissions,
-			serv->responses,
-			serv->malformed_responses,
-			serv->bad_authenticators,
-			pending,
-			serv->timeouts,
-			serv->unknown_types,
-			serv->packets_dropped);
+	return os_snprintf(buf, buflen,
+			   "radiusAccServerIndex=%d\n"
+			   "radiusAccServerAddress=%s\n"
+			   "radiusAccClientServerPortNumber=%d\n"
+			   "radiusAccClientRoundTripTime=%d\n"
+			   "radiusAccClientRequests=%u\n"
+			   "radiusAccClientRetransmissions=%u\n"
+			   "radiusAccClientResponses=%u\n"
+			   "radiusAccClientMalformedResponses=%u\n"
+			   "radiusAccClientBadAuthenticators=%u\n"
+			   "radiusAccClientPendingRequests=%u\n"
+			   "radiusAccClientTimeouts=%u\n"
+			   "radiusAccClientUnknownTypes=%u\n"
+			   "radiusAccClientPacketsDropped=%u\n",
+			   serv->index,
+			   hostapd_ip_txt(&serv->addr, abuf, sizeof(abuf)),
+			   serv->port,
+			   serv->round_trip_time,
+			   serv->requests,
+			   serv->retransmissions,
+			   serv->responses,
+			   serv->malformed_responses,
+			   serv->bad_authenticators,
+			   pending,
+			   serv->timeouts,
+			   serv->unknown_types,
+			   serv->packets_dropped);
 }
 
 
@@ -1113,3 +1157,48 @@
 
 	return count;
 }
+
+
+static int radius_servers_diff(struct hostapd_radius_server *nserv,
+			       struct hostapd_radius_server *oserv,
+			       int num)
+{
+	int i;
+
+	for (i = 0; i < num; i++) {
+		if (hostapd_ip_diff(&nserv[i].addr, &oserv[i].addr) ||
+		    nserv[i].port != oserv[i].port ||
+		    nserv[i].shared_secret_len != oserv[i].shared_secret_len ||
+		    memcmp(nserv[i].shared_secret, oserv[i].shared_secret,
+			   nserv[i].shared_secret_len) != 0)
+			return 1;
+	}
+
+	return 0;
+}
+
+
+struct radius_client_data *
+radius_client_reconfig(struct radius_client_data *old, void *ctx,
+		       struct hostapd_radius_servers *oldconf,
+		       struct hostapd_radius_servers *newconf)
+{
+	radius_client_flush(old, 0);
+
+	if (newconf->retry_primary_interval !=
+	    oldconf->retry_primary_interval ||
+	    newconf->num_auth_servers != oldconf->num_auth_servers ||
+	    newconf->num_acct_servers != oldconf->num_acct_servers ||
+	    radius_servers_diff(newconf->auth_servers, oldconf->auth_servers,
+				newconf->num_auth_servers) ||
+	    radius_servers_diff(newconf->acct_servers, oldconf->acct_servers,
+				newconf->num_acct_servers)) {
+		hostapd_logger(ctx, NULL, HOSTAPD_MODULE_RADIUS,
+			       HOSTAPD_LEVEL_DEBUG,
+			       "Reconfiguring RADIUS client");
+		radius_client_deinit(old);
+		return radius_client_init(ctx, newconf);
+	}
+
+	return old;
+}
Index: wpa_supplicant.h
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/wpa_supplicant.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/wpa_supplicant.h -L contrib/wpa_supplicant/wpa_supplicant.h -u -r1.2 -r1.3
--- contrib/wpa_supplicant/wpa_supplicant.h
+++ contrib/wpa_supplicant/wpa_supplicant.h
@@ -1,6 +1,6 @@
 /*
  * wpa_supplicant - Exported functions for wpa_supplicant modules
- * Copyright (c) 2003-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2003-2005, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -121,7 +121,18 @@
 	 * Driver will be notified about successful pre-authentication with
 	 * struct wpa_driver_ops::add_pmkid() calls.
 	 */
-	EVENT_PMKID_CANDIDATE
+	EVENT_PMKID_CANDIDATE,
+
+	/**
+	 * EVENT_STKSTART - Request STK handshake (MLME-STKSTART.request)
+	 *
+	 * This event can be used to inform wpa_supplicant about desire to set
+	 * up secure direct link connection between two stations as defined in
+	 * IEEE 802.11e with a new PeerKey mechanism that replaced the original
+	 * STAKey negotiation. The caller will need to set peer address for the
+	 * event.
+	 */
+	EVENT_STKSTART
 } wpa_event_type;
 
 
@@ -208,7 +219,7 @@
 	 * struct interface_status - Data for EVENT_INTERFACE_STATUS
 	 */
 	struct interface_status {
-		char ifname[20];
+		char ifname[100];
 		enum {
 			EVENT_INTERFACE_ADDED, EVENT_INTERFACE_REMOVED
 		} ievent;
@@ -225,6 +236,13 @@
 		/** Whether RSN IE includes pre-authenticate flag */
 		int preauth;
 	} pmkid_candidate;
+
+	/**
+	 * struct stkstart - Data for EVENT_STKSTART
+	 */
+	struct stkstart {
+		u8 peer[ETH_ALEN];
+	} stkstart;
 };
 
 /**
@@ -241,25 +259,6 @@
 			  union wpa_event_data *data);
 
 /**
- * wpa_msg - Conditional printf for default target and ctrl_iface monitors
- * @wpa_s: pointer to wpa_supplicant data; this is the ctx variable registered
- *	with struct wpa_driver_ops::init()
- * @level: priority level (MSG_*) of the message
- * @fmt: printf format string, followed by optional arguments
- *
- * This function is used to print conditional debugging and error messages. The
- * output may be directed to stdout, stderr, and/or syslog based on
- * configuration. This function is like wpa_printf(), but it also sends the
- * same message to all attached ctrl_iface monitors.
- *
- * Note: New line '\n' is added to the end of the text when printing to stdout.
- */
-void wpa_msg(struct wpa_supplicant *wpa_s, int level, char *fmt, ...)
-__attribute__ ((format (printf, 3, 4)));
-
-const char * wpa_ssid_txt(u8 *ssid, size_t ssid_len);
-
-/**
  * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
  * @ctx: Context pointer (wpa_s)
  * @src_addr: Source address of the EAPOL frame
Index: eap.h
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/eap.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/eap.h -L contrib/wpa_supplicant/eap.h -u -r1.2 -r1.3
--- contrib/wpa_supplicant/eap.h
+++ contrib/wpa_supplicant/eap.h
@@ -1,6 +1,6 @@
 /*
- * WPA Supplicant / EAP state machine functions (RFC 4137)
- * Copyright (c) 2004-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * EAP peer state machine functions (RFC 4137)
+ * Copyright (c) 2004-2006, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -17,11 +17,16 @@
 
 #include "defs.h"
 #include "eap_defs.h"
+#include "eap_methods.h"
 
 struct eap_sm;
 struct wpa_ssid;
 struct wpa_config_blob;
 
+struct eap_method_type {
+	int vendor;
+	u32 method;
+};
 
 #ifdef IEEE8021X_EAPOL
 
@@ -194,6 +199,18 @@
 	 */
 	const struct wpa_config_blob * (*get_config_blob)(void *ctx,
 							  const char *name);
+
+	/**
+	 * notify_pending - Notify that a pending request can be retried
+	 * @ctx: eapol_ctx from eap_sm_init() call
+	 *
+	 * An EAP method can perform a pending operation (e.g., to get a
+	 * response from an external process). Once the response is available,
+	 * this callback function can be used to request EAPOL state machine to
+	 * retry delivering the previously received (and still unanswered) EAP
+	 * request to EAP state machine.
+	 */
+	void (*notify_pending)(void *ctx);
 };
 
 /**
@@ -229,47 +246,26 @@
 		      int verbose);
 u8 * eap_sm_buildIdentity(struct eap_sm *sm, int id, size_t *len,
 			  int encrypted);
-const struct eap_method * eap_sm_get_eap_methods(int method);
-void eap_sm_request_identity(struct eap_sm *sm, struct wpa_ssid *config);
-void eap_sm_request_password(struct eap_sm *sm, struct wpa_ssid *config);
-void eap_sm_request_new_password(struct eap_sm *sm, struct wpa_ssid *config);
-void eap_sm_request_pin(struct eap_sm *sm, struct wpa_ssid *config);
-void eap_sm_request_otp(struct eap_sm *sm, struct wpa_ssid *config,
-			const char *msg, size_t msg_len);
-void eap_sm_request_passphrase(struct eap_sm *sm, struct wpa_ssid *config);
+void eap_sm_request_identity(struct eap_sm *sm);
+void eap_sm_request_password(struct eap_sm *sm);
+void eap_sm_request_new_password(struct eap_sm *sm);
+void eap_sm_request_pin(struct eap_sm *sm);
+void eap_sm_request_otp(struct eap_sm *sm, const char *msg, size_t msg_len);
+void eap_sm_request_passphrase(struct eap_sm *sm);
 void eap_sm_notify_ctrl_attached(struct eap_sm *sm);
-u8 eap_get_type(const char *name);
-const char * eap_get_name(EapType type);
-size_t eap_get_names(char *buf, size_t buflen);
-u8 eap_get_phase2_type(const char *name);
-u8 *eap_get_phase2_types(struct wpa_ssid *config, size_t *count);
+u32 eap_get_phase2_type(const char *name, int *vendor);
+struct eap_method_type * eap_get_phase2_types(struct wpa_ssid *config,
+					      size_t *count);
 void eap_set_fast_reauth(struct eap_sm *sm, int enabled);
 void eap_set_workaround(struct eap_sm *sm, unsigned int workaround);
 void eap_set_force_disabled(struct eap_sm *sm, int disabled);
-struct wpa_ssid * eap_get_config(struct eap_sm *sm);
 int eap_key_available(struct eap_sm *sm);
 void eap_notify_success(struct eap_sm *sm);
 void eap_notify_lower_layer_success(struct eap_sm *sm);
 const u8 * eap_get_eapKeyData(struct eap_sm *sm, size_t *len);
 u8 * eap_get_eapRespData(struct eap_sm *sm, size_t *len);
 void eap_register_scard_ctx(struct eap_sm *sm, void *ctx);
-
-#else /* IEEE8021X_EAPOL */
-
-static inline u8 eap_get_type(const char *name)
-{
-	return EAP_TYPE_NONE;
-}
-
-static inline const char * eap_get_name(EapType type)
-{
-	return NULL;
-}
-
-static inline size_t eap_get_names(char *buf, size_t buflen)
-{
-	return 0;
-}
+void eap_invalidate_cached_session(struct eap_sm *sm);
 
 #endif /* IEEE8021X_EAPOL */
 
Index: wpa_passphrase.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/wpa_passphrase.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/wpa_passphrase.c -L contrib/wpa_supplicant/wpa_passphrase.c -u -r1.2 -r1.3
--- contrib/wpa_supplicant/wpa_passphrase.c
+++ contrib/wpa_supplicant/wpa_passphrase.c
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant - ASCII passphrase to WPA PSK tool
- * Copyright (c) 2003-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2003-2005, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -12,8 +12,7 @@
  * See README and COPYING for more details.
  */
 
-#include <stdio.h>
-#include <string.h>
+#include "includes.h"
 
 #include "common.h"
 #include "sha1.h"
@@ -54,12 +53,12 @@
 		passphrase = buf;
 	}
 
-	if (strlen(passphrase) < 8 || strlen(passphrase) > 63) {
+	if (os_strlen(passphrase) < 8 || os_strlen(passphrase) > 63) {
 		printf("Passphrase must be 8..63 characters\n");
 		return 1;
 	}
 
-	pbkdf2_sha1(passphrase, ssid, strlen(ssid), 4096, psk, 32);
+	pbkdf2_sha1(passphrase, ssid, os_strlen(ssid), 4096, psk, 32);
 
 	printf("network={\n");
 	printf("\tssid=\"%s\"\n", ssid);
Index: driver_hostap.h
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/driver_hostap.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -L contrib/wpa_supplicant/driver_hostap.h -L contrib/wpa_supplicant/driver_hostap.h -u -r1.1 -r1.2
--- contrib/wpa_supplicant/driver_hostap.h
+++ contrib/wpa_supplicant/driver_hostap.h
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant - driver interaction with Linux Host AP driver
- * Copyright (c) 2003-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2003-2005, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
Index: common.h
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/common.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/common.h -L contrib/wpa_supplicant/common.h -u -r1.2 -r1.3
--- contrib/wpa_supplicant/common.h
+++ contrib/wpa_supplicant/common.h
@@ -1,6 +1,6 @@
 /*
  * wpa_supplicant/hostapd / common helper functions, etc.
- * Copyright (c) 2002-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2002-2006, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -11,18 +11,20 @@
  *
  * See README and COPYING for more details.
  *
- * $FreeBSD: src/contrib/wpa_supplicant/common.h,v 1.2.2.1 2006/03/24 01:41:06 sam Exp $
+ * $FreeBSD: src/contrib/wpa_supplicant/common.h,v 1.4 2007/07/11 15:58:51 sam Exp $
  */
 
 #ifndef COMMON_H
 #define COMMON_H
 
+#include "os.h"
+
 #ifdef __linux__
 #include <endian.h>
 #include <byteswap.h>
 #endif /* __linux__ */
 
-#if defined(__FreeBSD__) || defined(__NetBSD__)
+#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
 #include <sys/types.h>
 #include <sys/endian.h>
 #define __BYTE_ORDER	_BYTE_ORDER
@@ -31,51 +33,22 @@
 #define bswap_16 bswap16
 #define bswap_32 bswap32
 #define bswap_64 bswap64
-#endif /* defined(__FreeBSD__) || defined(__NetBSD__) */
-
-#ifdef CONFIG_NATIVE_WINDOWS
-#include <winsock2.h>
-
-static inline int daemon(int nochdir, int noclose)
-{
-	printf("Windows - daemon() not supported yet\n");
-	return -1;
-}
-
-static inline void sleep(int seconds)
-{
-	Sleep(seconds * 1000);
-}
-
-static inline void usleep(unsigned long usec)
-{
-	Sleep(usec / 1000);
-}
-
-#ifndef timersub
-#define timersub(a, b, res) do { \
-	(res)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
-	(res)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
-	if ((res)->tv_usec < 0) { \
-		(res)->tv_sec--; \
-		(res)->tv_usec += 1000000; \
-	} \
-} while (0)
-#endif
-
-struct timezone {
-	int  tz_minuteswest;
-	int  tz_dsttime;
-};
+#endif /* defined(__FreeBSD__) || defined(__NetBSD__) ||
+	* defined(__DragonFly__) */
 
-int gettimeofday(struct timeval *tv, struct timezone *tz);
+#ifdef CONFIG_TI_COMPILER
+#define __BIG_ENDIAN 4321
+#define __LITTLE_ENDIAN 1234
+#ifdef __big_endian__
+#define __BYTE_ORDER __BIG_ENDIAN
+#else
+#define __BYTE_ORDER __LITTLE_ENDIAN
+#endif
+#endif /* CONFIG_TI_COMPILER */
 
-static inline long int random(void)
-{
-	return rand();
-}
+#ifdef CONFIG_NATIVE_WINDOWS
+#include <winsock.h>
 
-typedef int gid_t;
 typedef int socklen_t;
 
 #ifndef MSG_DONTWAIT
@@ -86,6 +59,10 @@
 
 #if defined(__CYGWIN__) || defined(CONFIG_NATIVE_WINDOWS)
 
+#ifdef _MSC_VER
+#define inline __inline
+#endif /* _MSC_VER */
+
 static inline unsigned short wpa_swap_16(unsigned short v)
 {
 	return ((v & 0xff) << 8) | (v >> 8);
@@ -107,6 +84,18 @@
 
 #else /* __CYGWIN__ */
 
+#ifndef __BYTE_ORDER
+#ifndef __LITTLE_ENDIAN
+#ifndef __BIG_ENDIAN
+#define __LITTLE_ENDIAN 1234
+#define __BIG_ENDIAN 4321
+#if defined(sparc)
+#define __BYTE_ORDER __BIG_ENDIAN
+#endif
+#endif /* __BIG_ENDIAN */
+#endif /* __LITTLE_ENDIAN */
+#endif /* __BYTE_ORDER */
+
 #if __BYTE_ORDER == __LITTLE_ENDIAN
 #define le_to_host16(n) (n)
 #define host_to_le16(n) (n)
@@ -115,6 +104,10 @@
 #define le_to_host32(n) (n)
 #define be_to_host32(n) bswap_32(n)
 #define host_to_be32(n) bswap_32(n)
+#define le_to_host64(n) (n)
+#define host_to_le64(n) (n)
+#define be_to_host64(n) bswap_64(n)
+#define host_to_be64(n) bswap_64(n)
 #elif __BYTE_ORDER == __BIG_ENDIAN
 #define le_to_host16(n) bswap_16(n)
 #define host_to_le16(n) bswap_16(n)
@@ -123,6 +116,10 @@
 #define le_to_host32(n) bswap_32(n)
 #define be_to_host32(n) (n)
 #define host_to_be32(n) (n)
+#define le_to_host64(n) bswap_64(n)
+#define host_to_le64(n) bswap_64(n)
+#define be_to_host64(n) (n)
+#define host_to_be64(n) (n)
 #ifndef WORDS_BIGENDIAN
 #define WORDS_BIGENDIAN
 #endif
@@ -147,12 +144,88 @@
 		(a)[0] = ((u16) (val)) & 0xff;	\
 	} while (0)
 
+#define WPA_GET_BE24(a) ((((u32) (a)[0]) << 16) | (((u32) (a)[1]) << 8) | \
+			 ((u32) (a)[2]))
+#define WPA_PUT_BE24(a, val)				\
+	do {						\
+		(a)[0] = (u8) (((u32) (val)) >> 16);	\
+		(a)[1] = (u8) (((u32) (val)) >> 8);	\
+		(a)[2] = (u8) (((u32) (val)) & 0xff);	\
+	} while (0)
+
+#define WPA_GET_BE32(a) ((((u32) (a)[0]) << 24) | (((u32) (a)[1]) << 16) | \
+			 (((u32) (a)[2]) << 8) | ((u32) (a)[3]))
+#define WPA_PUT_BE32(a, val)				\
+	do {						\
+		(a)[0] = (u8) (((u32) (val)) >> 24);	\
+		(a)[1] = (u8) (((u32) (val)) >> 16);	\
+		(a)[2] = (u8) (((u32) (val)) >> 8);	\
+		(a)[3] = (u8) (((u32) (val)) & 0xff);	\
+	} while (0)
+
+#define WPA_PUT_BE64(a, val)				\
+	do {						\
+		(a)[0] = (u8) (((u64) (val)) >> 56);	\
+		(a)[1] = (u8) (((u64) (val)) >> 48);	\
+		(a)[2] = (u8) (((u64) (val)) >> 40);	\
+		(a)[3] = (u8) (((u64) (val)) >> 32);	\
+		(a)[4] = (u8) (((u64) (val)) >> 24);	\
+		(a)[5] = (u8) (((u64) (val)) >> 16);	\
+		(a)[6] = (u8) (((u64) (val)) >> 8);	\
+		(a)[7] = (u8) (((u64) (val)) & 0xff);	\
+	} while (0)
+
 
 #ifndef ETH_ALEN
 #define ETH_ALEN 6
 #endif
 
+#ifdef _MSC_VER
+typedef UINT64 u64;
+typedef UINT32 u32;
+typedef UINT16 u16;
+typedef UINT8 u8;
+typedef INT64 s64;
+typedef INT32 s32;
+typedef INT16 s16;
+typedef INT8 s8;
+#define WPA_TYPES_DEFINED
+#endif /* _MSC_VER */
+
+#ifdef __vxworks
+typedef unsigned long long u64;
+typedef UINT32 u32;
+typedef UINT16 u16;
+typedef UINT8 u8;
+typedef long long s64;
+typedef INT32 s32;
+typedef INT16 s16;
+typedef INT8 s8;
+#define WPA_TYPES_DEFINED
+#endif /* __vxworks */
+
+#ifdef CONFIG_TI_COMPILER
+#ifdef _LLONG_AVAILABLE
+typedef unsigned long long u64;
+#else
+/*
+ * TODO: 64-bit variable not available. Using long as a workaround to test the
+ * build, but this will likely not work for all operations.
+ */
+typedef unsigned long u64;
+#endif
+typedef unsigned int u32;
+typedef unsigned short u16;
+typedef unsigned char u8;
+#define WPA_TYPES_DEFINED
+#endif /* CONFIG_TI_COMPILER */
+
+#ifndef WPA_TYPES_DEFINED
+#ifdef CONFIG_USE_INTTYPES_H
+#include <inttypes.h>
+#else
 #include <stdint.h>
+#endif
 typedef uint64_t u64;
 typedef uint32_t u32;
 typedef uint16_t u16;
@@ -161,19 +234,27 @@
 typedef int32_t s32;
 typedef int16_t s16;
 typedef int8_t s8;
+#define WPA_TYPES_DEFINED
+#endif /* !WPA_TYPES_DEFINED */
 
-int hostapd_get_rand(u8 *buf, size_t len);
-void hostapd_hexdump(const char *title, const u8 *buf, size_t len);
+#define hostapd_get_rand os_get_random
 int hwaddr_aton(const char *txt, u8 *addr);
 int hexstr2bin(const char *hex, u8 *buf, size_t len);
-char * rel2abs_path(const char *rel_path);
 void inc_byte_array(u8 *counter, size_t len);
-void print_char(char c);
-void fprint_char(FILE *f, char c);
+void wpa_get_ntp_timestamp(u8 *buf);
+
+
+#ifdef __GNUC__
+#define PRINTF_FORMAT(a,b) __attribute__ ((format (printf, (a), (b))))
+#define STRUCT_PACKED __attribute__ ((packed))
+#else
+#define PRINTF_FORMAT(a,b)
+#define STRUCT_PACKED
+#endif
 
 
 /* Debugging function - conditional printf and hex dump. Driver wrappers can
- *  use these for debugging purposes. */
+ * use these for debugging purposes. */
 
 enum { MSG_MSGDUMP, MSG_DEBUG, MSG_INFO, MSG_WARNING, MSG_ERROR };
 
@@ -181,13 +262,18 @@
 
 #define wpa_debug_print_timestamp() do { } while (0)
 #define wpa_printf(args...) do { } while (0)
-#define wpa_hexdump(args...) do { } while (0)
-#define wpa_hexdump_key(args...) do { } while (0)
-#define wpa_hexdump_ascii(args...) do { } while (0)
-#define wpa_hexdump_ascii_key(args...) do { } while (0)
+#define wpa_hexdump(l,t,b,le) do { } while (0)
+#define wpa_hexdump_key(l,t,b,le) do { } while (0)
+#define wpa_hexdump_ascii(l,t,b,le) do { } while (0)
+#define wpa_hexdump_ascii_key(l,t,b,le) do { } while (0)
+#define wpa_debug_open_file() do { } while (0)
+#define wpa_debug_close_file() do { } while (0)
 
 #else /* CONFIG_NO_STDOUT_DEBUG */
 
+int wpa_debug_open_file(void);
+void wpa_debug_close_file(void);
+
 /**
  * wpa_debug_printf_timestamp - Print timestamp for debug output
  *
@@ -209,7 +295,7 @@
  * Note: New line '\n' is added to the end of the text when printing to stdout.
  */
 void wpa_printf(int level, char *fmt, ...)
-__attribute__ ((format (printf, 2, 3)));
+PRINTF_FORMAT(2, 3);
 
 /**
  * wpa_hexdump - conditional hex dump
@@ -275,6 +361,42 @@
 #endif /* CONFIG_NO_STDOUT_DEBUG */
 
 
+#ifdef CONFIG_NO_WPA_MSG
+#define wpa_msg(args...) do { } while (0)
+#define wpa_msg_register_cb(f) do { } while (0)
+#else /* CONFIG_NO_WPA_MSG */
+/**
+ * wpa_msg - Conditional printf for default target and ctrl_iface monitors
+ * @ctx: Pointer to context data; this is the ctx variable registered
+ *	with struct wpa_driver_ops::init()
+ * @level: priority level (MSG_*) of the message
+ * @fmt: printf format string, followed by optional arguments
+ *
+ * This function is used to print conditional debugging and error messages. The
+ * output may be directed to stdout, stderr, and/or syslog based on
+ * configuration. This function is like wpa_printf(), but it also sends the
+ * same message to all attached ctrl_iface monitors.
+ *
+ * Note: New line '\n' is added to the end of the text when printing to stdout.
+ */
+void wpa_msg(void *ctx, int level, char *fmt, ...) PRINTF_FORMAT(3, 4);
+
+typedef void (*wpa_msg_cb_func)(void *ctx, int level, const char *txt,
+				size_t len);
+
+/**
+ * wpa_msg_register_cb - Register callback function for wpa_msg() messages
+ * @func: Callback function (%NULL to unregister)
+ */
+void wpa_msg_register_cb(wpa_msg_cb_func func);
+#endif /* CONFIG_NO_WPA_MSG */
+
+
+int wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len);
+int wpa_snprintf_hex_uppercase(char *buf, size_t buf_size, const u8 *data,
+			       size_t len);
+
+
 #ifdef EAPOL_TEST
 #define WPA_ASSERT(a)						       \
 	do {							       \
@@ -289,4 +411,84 @@
 #define WPA_ASSERT(a) do { } while (0)
 #endif
 
+
+#ifdef _MSC_VER
+#undef vsnprintf
+#define vsnprintf _vsnprintf
+#undef close
+#define close closesocket
+#endif /* _MSC_VER */
+
+
+#ifdef CONFIG_ANSI_C_EXTRA
+
+#if !defined(_MSC_VER) || _MSC_VER < 1400
+/* snprintf - used in number of places; sprintf() is _not_ a good replacement
+ * due to possible buffer overflow; see, e.g.,
+ * http://www.ijs.si/software/snprintf/ for portable implementation of
+ * snprintf. */
+int snprintf(char *str, size_t size, const char *format, ...);
+
+/* vsnprintf - only used for wpa_msg() in wpa_supplicant.c */
+int vsnprintf(char *str, size_t size, const char *format, va_list ap);
+#endif /* !defined(_MSC_VER) || _MSC_VER < 1400 */
+
+/* getopt - only used in main.c */
+int getopt(int argc, char *const argv[], const char *optstring);
+extern char *optarg;
+extern int optind;
+
+#ifndef CONFIG_NO_SOCKLEN_T_TYPEDEF
+#ifndef __socklen_t_defined
+typedef int socklen_t;
+#endif
+#endif
+
+/* inline - define as __inline or just define it to be empty, if needed */
+#ifdef CONFIG_NO_INLINE
+#define inline
+#else
+#define inline __inline
+#endif
+
+#ifndef __func__
+#define __func__ "__func__ not defined"
+#endif
+
+#ifndef bswap_16
+#define bswap_16(a) ((((u16) (a) << 8) & 0xff00) | (((u16) (a) >> 8) & 0xff))
+#endif
+
+#ifndef bswap_32
+#define bswap_32(a) ((((u32) (a) << 24) & 0xff000000) | \
+		     (((u32) (a) << 8) & 0xff0000) | \
+     		     (((u32) (a) >> 8) & 0xff00) | \
+     		     (((u32) (a) >> 24) & 0xff))
+#endif
+
+#ifndef MSG_DONTWAIT
+#define MSG_DONTWAIT 0
+#endif
+
+#ifdef _WIN32_WCE
+void perror(const char *s);
+#endif /* _WIN32_WCE */
+
+#endif /* CONFIG_ANSI_C_EXTRA */
+
+#define wpa_zalloc(s) os_zalloc((s))
+
+#ifdef CONFIG_NATIVE_WINDOWS
+void wpa_unicode2ascii_inplace(TCHAR *str);
+TCHAR * wpa_strdup_tchar(const char *str);
+#else /* CONFIG_NATIVE_WINDOWS */
+#define wpa_unicode2ascii_inplace(s) do { } while (0)
+#define wpa_strdup_tchar(s) strdup((s))
+#endif /* CONFIG_NATIVE_WINDOWS */
+
+const char * wpa_ssid_txt(u8 *ssid, size_t ssid_len);
+
+typedef u32 __be32;
+typedef u64 __be64;
+
 #endif /* COMMON_H */
Index: eloop.h
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/eloop.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/eloop.h -L contrib/wpa_supplicant/eloop.h -u -r1.2 -r1.3
--- contrib/wpa_supplicant/eloop.h
+++ contrib/wpa_supplicant/eloop.h
@@ -1,6 +1,6 @@
 /*
  * Event loop
- * Copyright (c) 2002-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2002-2006, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -23,18 +23,67 @@
 #ifndef ELOOP_H
 #define ELOOP_H
 
-/* Magic number for eloop_cancel_timeout() */
+/**
+ * ELOOP_ALL_CTX - eloop_cancel_timeout() magic number to match all timeouts
+ */
 #define ELOOP_ALL_CTX (void *) -1
 
 /**
+ * eloop_event_type - eloop socket event type for eloop_register_sock()
+ * @EVENT_TYPE_READ: Socket has data available for reading
+ * @EVENT_TYPE_WRITE: Socket has room for new data to be written
+ * @EVENT_TYPE_EXCEPTION: An exception has been reported
+ */
+typedef enum {
+	EVENT_TYPE_READ = 0,
+	EVENT_TYPE_WRITE,
+	EVENT_TYPE_EXCEPTION
+} eloop_event_type;
+
+/**
+ * eloop_sock_handler - eloop socket event callback type
+ * @sock: File descriptor number for the socket
+ * @eloop_ctx: Registered callback context data (eloop_data)
+ * @sock_ctx: Registered callback context data (user_data)
+ */
+typedef void (*eloop_sock_handler)(int sock, void *eloop_ctx, void *sock_ctx);
+
+/**
+ * eloop_event_handler - eloop generic event callback type
+ * @eloop_ctx: Registered callback context data (eloop_data)
+ * @sock_ctx: Registered callback context data (user_data)
+ */
+typedef void (*eloop_event_handler)(void *eloop_data, void *user_ctx);
+
+/**
+ * eloop_timeout_handler - eloop timeout event callback type
+ * @eloop_ctx: Registered callback context data (eloop_data)
+ * @sock_ctx: Registered callback context data (user_data)
+ */
+typedef void (*eloop_timeout_handler)(void *eloop_data, void *user_ctx);
+
+/**
+ * eloop_signal_handler - eloop signal event callback type
+ * @sig: Signal number
+ * @eloop_ctx: Registered callback context data (global user_data from
+ * eloop_init() call)
+ * @signal_ctx: Registered callback context data (user_data from
+ * eloop_register_signal(), eloop_register_signal_terminate(), or
+ * eloop_register_signal_reconfig() call)
+ */
+typedef void (*eloop_signal_handler)(int sig, void *eloop_ctx,
+				     void *signal_ctx);
+
+/**
  * eloop_init() - Initialize global event loop data
  * @user_data: Pointer to global data passed as eloop_ctx to signal handlers
+ * Returns: 0 on success, -1 on failure
  *
  * This function must be called before any other eloop_* function. user_data
  * can be used to configure a global (to the process) pointer that will be
  * passed as eloop_ctx parameter to signal handlers.
  */
-void eloop_init(void *user_data);
+int eloop_init(void *user_data);
 
 /**
  * eloop_register_read_sock - Register handler for read events
@@ -46,11 +95,11 @@
  *
  * Register a read socket notifier for the given file descriptor. The handler
  * function will be called whenever data is available for reading from the
- * socket.
+ * socket. The handler function is responsible for clearing the event after
+ * having processed it in order to avoid eloop from calling the handler again
+ * for the same event.
  */
-int eloop_register_read_sock(int sock,
-			     void (*handler)(int sock, void *eloop_ctx,
-					     void *sock_ctx),
+int eloop_register_read_sock(int sock, eloop_sock_handler handler,
 			     void *eloop_data, void *user_data);
 
 /**
@@ -63,6 +112,71 @@
 void eloop_unregister_read_sock(int sock);
 
 /**
+ * eloop_register_sock - Register handler for socket events
+ * @sock: File descriptor number for the socket
+ * @type: Type of event to wait for
+ * @handler: Callback function to be called when the event is triggered
+ * @eloop_data: Callback context data (eloop_ctx)
+ * @user_data: Callback context data (sock_ctx)
+ * Returns: 0 on success, -1 on failure
+ *
+ * Register an event notifier for the given socket's file descriptor. The
+ * handler function will be called whenever the that event is triggered for the
+ * socket. The handler function is responsible for clearing the event after
+ * having processed it in order to avoid eloop from calling the handler again
+ * for the same event.
+ */
+int eloop_register_sock(int sock, eloop_event_type type,
+			eloop_sock_handler handler,
+			void *eloop_data, void *user_data);
+
+/**
+ * eloop_unregister_sock - Unregister handler for socket events
+ * @sock: File descriptor number for the socket
+ * @type: Type of event for which sock was registered
+ *
+ * Unregister a socket event notifier that was previously registered with
+ * eloop_register_sock().
+ */
+void eloop_unregister_sock(int sock, eloop_event_type type);
+
+/**
+ * eloop_register_event - Register handler for generic events
+ * @event: Event to wait (eloop implementation specific)
+ * @event_size: Size of event data
+ * @handler: Callback function to be called when event is triggered
+ * @eloop_data: Callback context data (eloop_data)
+ * @user_data: Callback context data (user_data)
+ * Returns: 0 on success, -1 on failure
+ *
+ * Register an event handler for the given event. This function is used to
+ * register eloop implementation specific events which are mainly targetted for
+ * operating system specific code (driver interface and l2_packet) since the
+ * portable code will not be able to use such an OS-specific call. The handler
+ * function will be called whenever the event is triggered. The handler
+ * function is responsible for clearing the event after having processed it in
+ * order to avoid eloop from calling the handler again for the same event.
+ *
+ * In case of Windows implementation (eloop_win.c), event pointer is of HANDLE
+ * type, i.e., void*. The callers are likely to have 'HANDLE h' type variable,
+ * and they would call this function with eloop_register_event(h, sizeof(h),
+ * ...).
+ */
+int eloop_register_event(void *event, size_t event_size,
+			 eloop_event_handler handler,
+			 void *eloop_data, void *user_data);
+
+/**
+ * eloop_unregister_event - Unregister handler for a generic event
+ * @event: Event to cancel (eloop implementation specific)
+ * @event_size: Size of event data
+ *
+ * Unregister a generic event notifier that was previously registered with
+ * eloop_register_event().
+ */
+void eloop_unregister_event(void *event, size_t event_size);
+
+/**
  * eloop_register_timeout - Register timeout
  * @secs: Number of seconds to the timeout
  * @usecs: Number of microseconds to the timeout
@@ -75,7 +189,7 @@
  * given time.
  */
 int eloop_register_timeout(unsigned int secs, unsigned int usecs,
-			   void (*handler)(void *eloop_ctx, void *timeout_ctx),
+			   eloop_timeout_handler handler,
 			   void *eloop_data, void *user_data);
 
 /**
@@ -89,7 +203,7 @@
  * eloop_register_timeout(). ELOOP_ALL_CTX can be used as a wildcard for
  * cancelling all timeouts regardless of eloop_data/user_data.
  */
-int eloop_cancel_timeout(void (*handler)(void *eloop_ctx, void *sock_ctx),
+int eloop_cancel_timeout(eloop_timeout_handler handler,
 			 void *eloop_data, void *user_data);
 
 /**
@@ -100,20 +214,67 @@
  * Returns: 0 on success, -1 on failure
  *
  * Register a callback function that will be called when a signal is received.
- * The calback function is actually called only after the system signal handler
- * has returned. This means that the normal limits for sighandlers (i.e., only
- * "safe functions" allowed) do not apply for the registered callback.
+ * The callback function is actually called only after the system signal
+ * handler has returned. This means that the normal limits for sighandlers
+ * (i.e., only "safe functions" allowed) do not apply for the registered
+ * callback.
  *
  * Signals are 'global' events and there is no local eloop_data pointer like
  * with other handlers. The global user_data pointer registered with
  * eloop_init() will be used as eloop_ctx for signal handlers.
  */
-int eloop_register_signal(int sig,
-			  void (*handler)(int sig, void *eloop_ctx,
-					  void *signal_ctx),
+int eloop_register_signal(int sig, eloop_signal_handler handler,
 			  void *user_data);
 
 /**
+ * eloop_register_signal_terminate - Register handler for terminate signals
+ * @handler: Callback function to be called when the signal is received
+ * @user_data: Callback context data (signal_ctx)
+ * Returns: 0 on success, -1 on failure
+ *
+ * Register a callback function that will be called when a process termination
+ * signal is received. The callback function is actually called only after the
+ * system signal handler has returned. This means that the normal limits for
+ * sighandlers (i.e., only "safe functions" allowed) do not apply for the
+ * registered callback.
+ *
+ * Signals are 'global' events and there is no local eloop_data pointer like
+ * with other handlers. The global user_data pointer registered with
+ * eloop_init() will be used as eloop_ctx for signal handlers.
+ *
+ * This function is a more portable version of eloop_register_signal() since
+ * the knowledge of exact details of the signals is hidden in eloop
+ * implementation. In case of operating systems using signal(), this function
+ * registers handlers for SIGINT and SIGTERM.
+ */
+int eloop_register_signal_terminate(eloop_signal_handler handler,
+				    void *user_data);
+
+/**
+ * eloop_register_signal_reconfig - Register handler for reconfig signals
+ * @handler: Callback function to be called when the signal is received
+ * @user_data: Callback context data (signal_ctx)
+ * Returns: 0 on success, -1 on failure
+ *
+ * Register a callback function that will be called when a reconfiguration /
+ * hangup signal is received. The callback function is actually called only
+ * after the system signal handler has returned. This means that the normal
+ * limits for sighandlers (i.e., only "safe functions" allowed) do not apply
+ * for the registered callback.
+ *
+ * Signals are 'global' events and there is no local eloop_data pointer like
+ * with other handlers. The global user_data pointer registered with
+ * eloop_init() will be used as eloop_ctx for signal handlers.
+ *
+ * This function is a more portable version of eloop_register_signal() since
+ * the knowledge of exact details of the signals is hidden in eloop
+ * implementation. In case of operating systems using signal(), this function
+ * registers a handler for SIGHUP.
+ */
+int eloop_register_signal_reconfig(eloop_signal_handler handler,
+				   void *user_data);
+
+/**
  * eloop_run - Start the event loop
  *
  * Start the event loop and continue running as long as there are any
@@ -133,7 +294,7 @@
 /**
  * eloop_destroy - Free any resources allocated for the event loop
  *
- * After calling eloop_destoy(), other eloop_* functions must not be called
+ * After calling eloop_destroy(), other eloop_* functions must not be called
  * before re-running eloop_init().
  */
 void eloop_destroy(void);
@@ -149,4 +310,18 @@
  */
 int eloop_terminated(void);
 
+/**
+ * eloop_wait_for_read_sock - Wait for a single reader
+ * @sock: File descriptor number for the socket
+ *
+ * Do a blocking wait for a single read socket.
+ */
+void eloop_wait_for_read_sock(int sock);
+
+/**
+ * eloop_get_user_data - Get global user data
+ * Returns: user_data pointer that was registered with eloop_init()
+ */
+void * eloop_get_user_data(void);
+
 #endif /* ELOOP_H */
Index: rc4.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/rc4.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/rc4.c -L contrib/wpa_supplicant/rc4.c -u -r1.2 -r1.3
--- contrib/wpa_supplicant/rc4.c
+++ contrib/wpa_supplicant/rc4.c
@@ -1,6 +1,6 @@
 /*
  * RC4 stream cipher
- * Copyright (c) 2002-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2002-2005, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -12,7 +12,8 @@
  * See README and COPYING for more details.
  */
 
-#include <stdio.h>
+#include "includes.h"
+
 #include "common.h"
 #include "rc4.h"
 
@@ -35,7 +36,7 @@
 {
 	u32 i, j, k;
 	u8 S[256], *pos;
-	int kpos;
+	size_t kpos;
 
 	/* Setup RC4 state */
 	for (i = 0; i < 256; i++)
Index: eap_pax_common.h
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/eap_pax_common.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -L contrib/wpa_supplicant/eap_pax_common.h -L contrib/wpa_supplicant/eap_pax_common.h -u -r1.1 -r1.2
--- contrib/wpa_supplicant/eap_pax_common.h
+++ contrib/wpa_supplicant/eap_pax_common.h
@@ -1,6 +1,6 @@
 /*
- * WPA Supplicant / EAP-PAX shared routines
- * Copyright (c) 2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * EAP server/peer: EAP-PAX shared routines
+ * Copyright (c) 2005-2006, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -15,6 +15,10 @@
 #ifndef EAP_PAX_COMMON_H
 #define EAP_PAX_COMMON_H
 
+#ifdef _MSC_VER
+#pragma pack(push, 1)
+#endif /* _MSC_VER */
+
 struct eap_pax_hdr {
 	u8 code;
 	u8 identifier;
@@ -26,7 +30,11 @@
 	u8 dh_group_id;
 	u8 public_key_id;
 	/* Followed by variable length payload and ICV */
-} __attribute__ ((packed));
+} STRUCT_PACKED;
+
+#ifdef _MSC_VER
+#pragma pack(pop)
+#endif /* _MSC_VER */
 
 
 /* op_code: */
@@ -45,22 +53,31 @@
 /* flags: */
 #define EAP_PAX_FLAGS_MF			0x01
 #define EAP_PAX_FLAGS_CE			0x02
+#define EAP_PAX_FLAGS_AI			0x04
 
 /* mac_id: */
 #define EAP_PAX_MAC_HMAC_SHA1_128		0x01
-#define EAP_PAX_MAC_AES_CBC_MAC_128		0x02
+#define EAP_PAX_HMAC_SHA256_128			0x02
 
 /* dh_group_id: */
 #define EAP_PAX_DH_GROUP_NONE			0x00
-#define EAP_PAX_DH_GROUP_3072_MODP		0x01
+#define EAP_PAX_DH_GROUP_2048_MODP		0x01
+#define EAP_PAX_DH_GROUP_3072_MODP		0x02
+#define EAP_PAX_DH_GROUP_NIST_ECC_P_256		0x03
 
 /* public_key_id: */
 #define EAP_PAX_PUBLIC_KEY_NONE			0x00
-#define EAP_PAX_PUBLIC_KEY_RSA_OAEP_2048	0x01
+#define EAP_PAX_PUBLIC_KEY_RSAES_OAEP		0x01
+#define EAP_PAX_PUBLIC_KEY_RSA_PKCS1_V1_5	0x02
+#define EAP_PAX_PUBLIC_KEY_EL_GAMAL_NIST_ECC	0x03
+
+/* ADE type: */
+#define EAP_PAX_ADE_VENDOR_SPECIFIC		0x01
+#define EAP_PAX_ADE_CLIENT_CHANNEL_BINDING	0x02
+#define EAP_PAX_ADE_SERVER_CHANNEL_BINDING	0x03
 
 
 #define EAP_PAX_RAND_LEN 32
-#define EAP_PAX_MSK_LEN 64
 #define EAP_PAX_MAC_LEN 16
 #define EAP_PAX_ICV_LEN 16
 #define EAP_PAX_AK_LEN 16
Index: eap_pax_common.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/eap_pax_common.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -L contrib/wpa_supplicant/eap_pax_common.c -L contrib/wpa_supplicant/eap_pax_common.c -u -r1.1 -r1.2
--- contrib/wpa_supplicant/eap_pax_common.c
+++ contrib/wpa_supplicant/eap_pax_common.c
@@ -1,6 +1,6 @@
 /*
- * WPA Supplicant / EAP-PAX shared routines
- * Copyright (c) 2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * EAP server/peer: EAP-PAX shared routines
+ * Copyright (c) 2005, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -12,9 +12,7 @@
  * See README and COPYING for more details.
  */
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
+#include "includes.h"
 
 #include "common.h"
 #include "sha1.h"
@@ -33,7 +31,7 @@
  * @output: Buffer for the derived key
  * Returns: 0 on success, -1 failed
  *
- * draft-clancy-eap-pax-04.txt, chap. 2.5: PAX-KDF-W(X, Y, Z)
+ * RFC 4746, Section 2.6: PAX-KDF-W(X, Y, Z)
  */
 int eap_pax_kdf(u8 mac_id, const u8 *key, size_t key_len,
 		const char *identifier,
@@ -50,12 +48,12 @@
 	if (identifier == NULL || num_blocks >= 255)
 		return -1;
 
-	/* TODO: add support for EAP_PAX_MAC_AES_CBC_MAC_128 */
+	/* TODO: add support for EAP_PAX_HMAC_SHA256_128 */
 	if (mac_id != EAP_PAX_MAC_HMAC_SHA1_128)
 		return -1;
 
 	addr[0] = (const u8 *) identifier;
-	len[0] = strlen(identifier);
+	len[0] = os_strlen(identifier);
 	addr[1] = entropy;
 	len[1] = entropy_len;
 	addr[2] = &counter;
@@ -66,7 +64,7 @@
 	for (counter = 1; counter <= (u8) num_blocks; counter++) {
 		size_t clen = left > EAP_PAX_MAC_LEN ? EAP_PAX_MAC_LEN : left;
 		hmac_sha1_vector(key, key_len, 3, addr, len, mac);
-		memcpy(pos, mac, clen);
+		os_memcpy(pos, mac, clen);
 		pos += clen;
 		left -= clen;
 	}
@@ -102,7 +100,7 @@
 	size_t len[3];
 	size_t count;
 
-	/* TODO: add support for EAP_PAX_MAC_AES_CBC_MAC_128 */
+	/* TODO: add support for EAP_PAX_HMAC_SHA256_128 */
 	if (mac_id != EAP_PAX_MAC_HMAC_SHA1_128)
 		return -1;
 
@@ -115,7 +113,7 @@
 
 	count = (data1 ? 1 : 0) + (data2 ? 1 : 0) + (data3 ? 1 : 0);
 	hmac_sha1_vector(key, key_len, count, addr, len, hash);
-	memcpy(mac, hash, EAP_PAX_MAC_LEN);
+	os_memcpy(mac, hash, EAP_PAX_MAC_LEN);
 
 	return 0;
 }
Index: wpa_supplicant_i.h
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/wpa_supplicant_i.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/wpa_supplicant_i.h -L contrib/wpa_supplicant/wpa_supplicant_i.h -u -r1.2 -r1.3
--- contrib/wpa_supplicant/wpa_supplicant_i.h
+++ contrib/wpa_supplicant/wpa_supplicant_i.h
@@ -1,6 +1,6 @@
 /*
  * wpa_supplicant - Internal definitions
- * Copyright (c) 2003-2006, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2003-2006, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -28,6 +28,15 @@
 struct wpa_sm;
 struct wpa_supplicant;
 
+/*
+ * Forward declarations of private structures used within the ctrl_iface
+ * backends. Other parts of wpa_supplicant do not have access to data stored in
+ * these structures.
+ */
+struct ctrl_iface_priv;
+struct ctrl_iface_global_priv;
+struct ctrl_iface_dbus_priv;
+
 /**
  * struct wpa_interface - Parameters for wpa_supplicant_add_iface()
  */
@@ -72,6 +81,16 @@
 	 * ifname - Interface name
 	 */
 	const char *ifname;
+
+	/**
+	 * bridge_ifname - Optional bridge interface name
+	 *
+	 * If the driver interface (ifname) is included in a Linux bridge
+	 * device, the bridge interface may need to be used for receiving EAPOL
+	 * frames. This can be enabled by setting this variable to enable
+	 * receiving of EAPOL frames from an additional interface.
+	 */
+	const char *bridge_ifname;
 };
 
 /**
@@ -132,6 +151,16 @@
 	 * ctrl_interface - Global ctrl_iface path/parameter
 	 */
 	char *ctrl_interface;
+
+	/**
+	 * dbus_ctrl_interface - Enable the DBus control interface
+	 */
+	int dbus_ctrl_interface;
+
+	/**
+	 * wpa_debug_use_file - Write debug to a file (instead of stdout)
+	 */
+	int wpa_debug_use_file;
 };
 
 /**
@@ -143,7 +172,91 @@
 struct wpa_global {
 	struct wpa_supplicant *ifaces;
 	struct wpa_params params;
-	int ctrl_sock;
+	struct ctrl_iface_global_priv *ctrl_iface;
+	struct ctrl_iface_dbus_priv *dbus_ctrl_iface;
+};
+
+
+struct wpa_client_mlme {
+#ifdef CONFIG_CLIENT_MLME
+	enum {
+		IEEE80211_DISABLED, IEEE80211_AUTHENTICATE,
+		IEEE80211_ASSOCIATE, IEEE80211_ASSOCIATED,
+		IEEE80211_IBSS_SEARCH, IEEE80211_IBSS_JOINED
+	} state;
+	u8 prev_bssid[ETH_ALEN];
+	u8 ssid[32];
+	size_t ssid_len;
+	u16 aid;
+	u16 ap_capab, capab;
+	u8 *extra_ie; /* to be added to the end of AssocReq */
+	size_t extra_ie_len;
+	wpa_key_mgmt key_mgmt;
+
+	/* The last AssocReq/Resp IEs */
+	u8 *assocreq_ies, *assocresp_ies;
+	size_t assocreq_ies_len, assocresp_ies_len;
+
+	int auth_tries, assoc_tries;
+
+	unsigned int ssid_set:1;
+	unsigned int bssid_set:1;
+	unsigned int prev_bssid_set:1;
+	unsigned int authenticated:1;
+	unsigned int associated:1;
+	unsigned int probereq_poll:1;
+	unsigned int use_protection:1;
+	unsigned int create_ibss:1;
+	unsigned int mixed_cell:1;
+	unsigned int wmm_enabled:1;
+
+	struct os_time last_probe;
+
+#define IEEE80211_AUTH_ALG_OPEN BIT(0)
+#define IEEE80211_AUTH_ALG_SHARED_KEY BIT(1)
+#define IEEE80211_AUTH_ALG_LEAP BIT(2)
+	unsigned int auth_algs; /* bitfield of allowed auth algs */
+	int auth_alg; /* currently used IEEE 802.11 authentication algorithm */
+	int auth_transaction;
+
+	struct os_time ibss_join_req;
+	u8 *probe_resp; /* ProbeResp template for IBSS */
+	size_t probe_resp_len;
+	u32 supp_rates_bits;
+
+	int wmm_last_param_set;
+
+	int sta_scanning;
+	int scan_hw_mode_idx;
+	int scan_channel_idx;
+	enum { SCAN_SET_CHANNEL, SCAN_SEND_PROBE } scan_state;
+	struct os_time last_scan_completed;
+	int scan_oper_channel;
+	int scan_oper_freq;
+	int scan_oper_phymode;
+	u8 scan_ssid[32];
+	size_t scan_ssid_len;
+	int scan_skip_11b;
+
+	struct ieee80211_sta_bss *sta_bss_list;
+#define STA_HASH_SIZE 256
+#define STA_HASH(sta) (sta[5])
+	struct ieee80211_sta_bss *sta_bss_hash[STA_HASH_SIZE];
+
+	int cts_protect_erp_frames;
+
+	int phymode; /* current mode; WPA_MODE_IEEE80211A, .. */
+	struct wpa_hw_modes *modes;
+	size_t num_modes;
+	unsigned int hw_modes; /* bitfield of allowed hardware modes;
+				* (1 << MODE_*) */
+	int num_curr_rates;
+	struct wpa_rate_data *curr_rates;
+	int freq; /* The current frequency in MHz */
+	int channel; /* The current IEEE 802.11 channel number */
+#else /* CONFIG_CLIENT_MLME */
+	int dummy; /* to keep MSVC happy */
+#endif /* CONFIG_CLIENT_MLME */
 };
 
 /**
@@ -158,14 +271,21 @@
 	struct wpa_global *global;
 	struct wpa_supplicant *next;
 	struct l2_packet_data *l2;
+	struct l2_packet_data *l2_br;
 	unsigned char own_addr[ETH_ALEN];
 	char ifname[100];
+#ifdef CONFIG_CTRL_IFACE_DBUS
+	char *dbus_path;
+#endif /* CONFIG_CTRL_IFACE_DBUS */
+	char bridge_ifname[16];
 
 	char *confname;
 	struct wpa_config *conf;
 	int countermeasures;
-	time_t last_michael_mic_error;
+	os_time_t last_michael_mic_error;
 	u8 bssid[ETH_ALEN];
+	u8 pending_bssid[ETH_ALEN]; /* If wpa_state == WPA_ASSOCIATING, this
+				     * field contains the targer BSSID. */
 	int reassociate; /* reassociation requested */
 	int disconnected; /* all connections disabled; i.e., do no reassociate
 			   * before this has been cleared */
@@ -175,6 +295,7 @@
 	int pairwise_cipher;
 	int group_cipher;
 	int key_mgmt;
+	int mgmt_group_cipher;
 
 	void *drv_priv; /* private data used by driver_ops */
 
@@ -195,9 +316,7 @@
 	struct wpa_sm *wpa;
 	struct eapol_sm *eapol;
 
-	int ctrl_sock; /* UNIX domain socket for control interface or -1 if
-			* not used */
-	struct wpa_ctrl_dst *ctrl_dst;
+	struct ctrl_iface_priv *ctrl_iface;
 
 	wpa_states wpa_state;
 	int new_connection;
@@ -216,6 +335,13 @@
 
 	int scan_req; /* manual scan request; this forces a scan even if there
 		       * are no enabled networks in the configuration */
+	int scan_res_tried; /* whether ap_scan=1 mode has tried to fetch scan
+			     * results without a new scan request; this is used
+			     * to speed up the first association if the driver
+			     * has already available scan results. */
+
+	struct wpa_client_mlme mlme;
+	int use_client_mlme;
 };
 
 
@@ -230,7 +356,6 @@
 struct wpa_blacklist * wpa_blacklist_get(struct wpa_supplicant *wpa_s,
 					 const u8 *bssid);
 int wpa_blacklist_add(struct wpa_supplicant *wpa_s, const u8 *bssid);
-int wpa_blacklist_del(struct wpa_supplicant *wpa_s, const u8 *bssid);
 void wpa_blacklist_clear(struct wpa_supplicant *wpa_s);
 int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
 			      struct wpa_scan_result *bss,
@@ -270,6 +395,8 @@
 int wpa_supplicant_scard_init(struct wpa_supplicant *wpa_s,
 			      struct wpa_ssid *ssid);
 
+/* events.c */
+void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s);
 
 /* driver_ops */
 static inline void * wpa_drv_init(struct wpa_supplicant *wpa_s,
@@ -481,4 +608,89 @@
 	return -1;
 }
 
+static inline int wpa_drv_set_operstate(struct wpa_supplicant *wpa_s,
+					int state)
+{
+	if (wpa_s->driver->set_operstate)
+		return wpa_s->driver->set_operstate(wpa_s->drv_priv, state);
+	return 0;
+}
+
+static inline int wpa_drv_mlme_setprotection(struct wpa_supplicant *wpa_s,
+					     const u8 *addr, int protect_type,
+					     int key_type)
+{
+	if (wpa_s->driver->mlme_setprotection)
+		return wpa_s->driver->mlme_setprotection(wpa_s->drv_priv, addr,
+							 protect_type,
+							 key_type);
+	return 0;
+}
+
+static inline struct wpa_hw_modes *
+wpa_drv_get_hw_feature_data(struct wpa_supplicant *wpa_s, u16 *num_modes,
+			    u16 *flags)
+{
+	if (wpa_s->driver->get_hw_feature_data)
+		return wpa_s->driver->get_hw_feature_data(wpa_s->drv_priv,
+							  num_modes, flags);
+	return NULL;
+}
+
+static inline int wpa_drv_set_channel(struct wpa_supplicant *wpa_s,
+				      wpa_hw_mode phymode, int chan,
+				      int freq)
+{
+	if (wpa_s->driver->set_channel)
+		return wpa_s->driver->set_channel(wpa_s->drv_priv, phymode,
+						  chan, freq);
+	return -1;
+}
+
+static inline int wpa_drv_set_ssid(struct wpa_supplicant *wpa_s,
+				   const u8 *ssid, size_t ssid_len)
+{
+	if (wpa_s->driver->set_ssid) {
+		return wpa_s->driver->set_ssid(wpa_s->drv_priv, ssid,
+					       ssid_len);
+	}
+	return -1;
+}
+
+static inline int wpa_drv_set_bssid(struct wpa_supplicant *wpa_s,
+				    const u8 *bssid)
+{
+	if (wpa_s->driver->set_bssid) {
+		return wpa_s->driver->set_bssid(wpa_s->drv_priv, bssid);
+	}
+	return -1;
+}
+
+static inline int wpa_drv_send_mlme(struct wpa_supplicant *wpa_s,
+				    const u8 *data, size_t data_len)
+{
+	if (wpa_s->driver->send_mlme)
+		return wpa_s->driver->send_mlme(wpa_s->drv_priv,
+						data, data_len);
+	return -1;
+}
+
+static inline int wpa_drv_mlme_add_sta(struct wpa_supplicant *wpa_s,
+				       const u8 *addr, const u8 *supp_rates,
+				       size_t supp_rates_len)
+{
+	if (wpa_s->driver->mlme_add_sta)
+		return wpa_s->driver->mlme_add_sta(wpa_s->drv_priv, addr,
+						   supp_rates, supp_rates_len);
+	return -1;
+}
+
+static inline int wpa_drv_mlme_remove_sta(struct wpa_supplicant *wpa_s,
+					  const u8 *addr)
+{
+	if (wpa_s->driver->mlme_remove_sta)
+		return wpa_s->driver->mlme_remove_sta(wpa_s->drv_priv, addr);
+	return -1;
+}
+
 #endif /* WPA_SUPPLICANT_I_H */
Index: eap_tlv.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/eap_tlv.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/eap_tlv.c -L contrib/wpa_supplicant/eap_tlv.c -u -r1.2 -r1.3
--- contrib/wpa_supplicant/eap_tlv.c
+++ contrib/wpa_supplicant/eap_tlv.c
@@ -1,6 +1,6 @@
 /*
- * WPA Supplicant / EAP-TLV (draft-josefsson-pppext-eap-tls-eap-07.txt)
- * Copyright (c) 2004-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * EAP peer method: EAP-TLV (draft-josefsson-pppext-eap-tls-eap-07.txt)
+ * Copyright (c) 2004-2006, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -12,31 +12,33 @@
  * See README and COPYING for more details.
  */
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
+#include "includes.h"
 
 #include "common.h"
-#include "wpa_supplicant.h"
 #include "eap_i.h"
 #include "eap_tlv.h"
 
 
+/**
+ * eap_tlv_build_nak - Build EAP-TLV NAK message
+ * @id: EAP identifier for the header
+ * @nak_type: TLV type (EAP_TLV_*)
+ * @resp_len: Buffer for returning the response length
+ * Returns: Buffer to the allocated EAP-TLV NAK message or %NULL on failure
+ *
+ * This funtion builds an EAP-TLV NAK message. The caller is responsible for
+ * freeing the returned buffer.
+ */
 u8 * eap_tlv_build_nak(int id, u16 nak_type, size_t *resp_len)
 {
 	struct eap_hdr *hdr;
 	u8 *pos;
 
-	*resp_len = sizeof(struct eap_hdr) + 1 + 10;
-	hdr = malloc(*resp_len);
+	hdr = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLV, resp_len,
+			    10, EAP_CODE_RESPONSE, id, &pos);
 	if (hdr == NULL)
 		return NULL;
 
-	hdr->code = EAP_CODE_RESPONSE;
-	hdr->identifier = id;
-	hdr->length = host_to_be16(*resp_len);
-	pos = (u8 *) (hdr + 1);
-	*pos++ = EAP_TYPE_TLV;
 	*pos++ = 0x80; /* Mandatory */
 	*pos++ = EAP_TLV_NAK_TLV;
 	/* Length */
@@ -54,21 +56,26 @@
 }
 
 
+/**
+ * eap_tlv_build_result - Build EAP-TLV Result message
+ * @id: EAP identifier for the header
+ * @status: Status (EAP_TLV_RESULT_SUCCESS or EAP_TLV_RESULT_FAILURE)
+ * @resp_len: Buffer for returning the response length
+ * Returns: Buffer to the allocated EAP-TLV Result message or %NULL on failure
+ *
+ * This funtion builds an EAP-TLV Result message. The caller is responsible for
+ * freeing the returned buffer.
+ */
 u8 * eap_tlv_build_result(int id, u16 status, size_t *resp_len)
 {
 	struct eap_hdr *hdr;
 	u8 *pos;
 
-	*resp_len = sizeof(struct eap_hdr) + 1 + 6;
-	hdr = malloc(*resp_len);
+	hdr = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLV, resp_len,
+			    6, EAP_CODE_RESPONSE, id, &pos);
 	if (hdr == NULL)
 		return NULL;
 
-	hdr->code = EAP_CODE_RESPONSE;
-	hdr->identifier = id;
-	hdr->length = host_to_be16(*resp_len);
-	pos = (u8 *) (hdr + 1);
-	*pos++ = EAP_TYPE_TLV;
 	*pos++ = 0x80; /* Mandatory */
 	*pos++ = EAP_TLV_RESULT_TLV;
 	/* Length */
@@ -81,14 +88,28 @@
 }
 
 
+/**
+ * eap_tlv_process - Process a received EAP-TLV message and generate a response
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ * @ret: Return values from EAP request validation and processing
+ * @hdr: EAP-TLV request to be processed. The caller must have validated that
+ * the buffer is large enough to contain full request (hdr->length bytes) and
+ * that the EAP type is EAP_TYPE_TLV.
+ * @resp: Buffer to return a pointer to the allocated response message. This
+ * field should be initialized to %NULL before the call. The value will be
+ * updated if a response message is generated. The caller is responsible for
+ * freeing the allocated message.
+ * @resp_len: Buffer for returning the response length
+ * Returns: 0 on success, -1 on failure
+ */
 int eap_tlv_process(struct eap_sm *sm, struct eap_method_ret *ret,
 		    const struct eap_hdr *hdr, u8 **resp, size_t *resp_len)
 {
-	size_t left;
+	size_t left, tlv_len;
 	const u8 *pos;
 	const u8 *result_tlv = NULL;
 	size_t result_tlv_len = 0;
-	int tlv_type, mandatory, tlv_len;
+	int tlv_type, mandatory;
 
 	/* Parse TLVs */
 	left = be_to_host16(hdr->length) - sizeof(struct eap_hdr) - 1;
@@ -104,7 +125,8 @@
 		left -= 4;
 		if (tlv_len > left) {
 			wpa_printf(MSG_DEBUG, "EAP-TLV: TLV underrun "
-				   "(tlv_len=%d left=%lu)", tlv_len,
+				   "(tlv_len=%lu left=%lu)",
+				   (unsigned long) tlv_len,
 				   (unsigned long) left);
 			return -1;
 		}
Index: tls_gnutls.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/tls_gnutls.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -L contrib/wpa_supplicant/tls_gnutls.c -L contrib/wpa_supplicant/tls_gnutls.c -u -r1.1 -r1.2
--- contrib/wpa_supplicant/tls_gnutls.c
+++ contrib/wpa_supplicant/tls_gnutls.c
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant / SSL/TLS interface functions for openssl
- * Copyright (c) 2004-2006, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2004-2007, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -12,17 +12,43 @@
  * See README and COPYING for more details.
  */
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
+#include "includes.h"
 #include <gnutls/gnutls.h>
 #include <gnutls/x509.h>
+#ifdef PKCS12_FUNCS
+#include <gnutls/pkcs12.h>
+#endif /* PKCS12_FUNCS */
+
+#ifdef CONFIG_GNUTLS_EXTRA
+#if LIBGNUTLS_VERSION_NUMBER >= 0x010302
+#define GNUTLS_IA
+#include <gnutls/extra.h>
+#if LIBGNUTLS_VERSION_NUMBER == 0x010302
+/* This function is not included in the current gnutls/extra.h even though it
+ * should be, so define it here as a workaround for the time being. */
+int gnutls_ia_verify_endphase(gnutls_session_t session, char *checksum);
+#endif /* LIBGNUTLS_VERSION_NUMBER == 0x010302 */
+#endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */
+#endif /* CONFIG_GNUTLS_EXTRA */
 
 #include "common.h"
 #include "tls.h"
 
 
+#define TLS_RANDOM_SIZE 32
+#define TLS_MASTER_SIZE 48
+
+
+#if LIBGNUTLS_VERSION_NUMBER < 0x010302
+/* GnuTLS 1.3.2 added functions for using master secret. Older versions require
+ * use of internal structures to get the master_secret and
+ * {server,client}_random.
+ */
+#define GNUTLS_INTERNAL_STRUCTURE_HACK
+#endif /* LIBGNUTLS_VERSION_NUMBER < 0x010302 */
+
+
+#ifdef GNUTLS_INTERNAL_STRUCTURE_HACK
 /*
  * It looks like gnutls does not provide access to client/server_random and
  * master_key. This is somewhat unfortunate since these are needed for key
@@ -32,8 +58,6 @@
  */
 
 typedef u8 uint8;
-#define TLS_RANDOM_SIZE 32
-#define TLS_MASTER_SIZE 48
 typedef unsigned char opaque;
 typedef struct {
     uint8 suite[2];
@@ -59,9 +83,21 @@
 	security_parameters_st security_parameters;
 	/* followed by things we are not interested in */
 };
+#endif /* LIBGNUTLS_VERSION_NUMBER < 0x010302 */
 
 static int tls_gnutls_ref_count = 0;
 
+struct tls_global {
+	/* Data for session resumption */
+	void *session_data;
+	size_t session_data_size;
+
+	int server;
+
+	int params_set;
+	gnutls_certificate_credentials_t xcred;
+};
+
 struct tls_connection {
 	gnutls_session session;
 	char *subject_match, *altsubject_match;
@@ -75,7 +111,23 @@
 	u8 *push_buf, *pull_buf, *pull_buf_offset;
 	size_t push_buf_len, pull_buf_len;
 
+	int params_set;
 	gnutls_certificate_credentials_t xcred;
+
+	int tls_ia;
+	int final_phase_finished;
+
+#ifdef GNUTLS_IA
+	gnutls_ia_server_credentials_t iacred_srv;
+	gnutls_ia_client_credentials_t iacred_cli;
+
+	/* Session keys generated in the current phase for inner secret
+	 * permutation before generating/verifying PhaseFinished. */
+	u8 *session_keys;
+	size_t session_keys_len;
+
+	u8 inner_secret[TLS_MASTER_SIZE];
+#endif /* GNUTLS_IA */
 };
 
 
@@ -87,7 +139,7 @@
 		return;
 	}
 
-	s = strdup(msg);
+	s = os_strdup(msg);
 	if (s == NULL)
 		return;
 
@@ -101,7 +153,7 @@
 	}
 	wpa_printf(level > 3 ? MSG_MSGDUMP : MSG_DEBUG,
 		   "gnutls<%d> %s", level, s);
-	free(s);
+	os_free(s);
 }
 
 
@@ -109,21 +161,36 @@
 
 void * tls_init(const struct tls_config *conf)
 {
+	struct tls_global *global;
+
+#ifdef GNUTLS_INTERNAL_STRUCTURE_HACK
 	/* Because of the horrible hack to get master_secret and client/server
 	 * random, we need to make sure that the gnutls version is something
 	 * that is expected to have same structure definition for the session
 	 * data.. */
 	const char *ver;
-	const char *ok_ver[] = { "1.2.3", "1.2.4", "1.2.5", "1.2.6", NULL };
+	const char *ok_ver[] = { "1.2.3", "1.2.4", "1.2.5", "1.2.6", "1.2.9",
+				 "1.3.2",
+				 NULL };
 	int i;
+#endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */
+
+	global = os_zalloc(sizeof(*global));
+	if (global == NULL)
+		return NULL;
 
-	if (tls_gnutls_ref_count == 0 && gnutls_global_init() < 0)
+	if (tls_gnutls_ref_count == 0 && gnutls_global_init() < 0) {
+		os_free(global);
 		return NULL;
+	}
 	tls_gnutls_ref_count++;
 
+#ifdef GNUTLS_INTERNAL_STRUCTURE_HACK
 	ver = gnutls_check_version(NULL);
-	if (ver == NULL)
+	if (ver == NULL) {
+		tls_deinit(global);
 		return NULL;
+	}
 	wpa_printf(MSG_DEBUG, "%s - gnutls version %s", __func__, ver);
 	for (i = 0; ok_ver[i]; i++) {
 		if (strcmp(ok_ver[i], ver) == 0)
@@ -132,18 +199,28 @@
 	if (ok_ver[i] == NULL) {
 		wpa_printf(MSG_INFO, "Untested gnutls version %s - this needs "
 			   "to be tested and enabled in tls_gnutls.c", ver);
+		tls_deinit(global);
 		return NULL;
 	}
+#endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */
 
 	gnutls_global_set_log_function(tls_log_func);
 	if (wpa_debug_show_keys)
 		gnutls_global_set_log_level(11);
-	return (void *) 1;
+	return global;
 }
 
 
 void tls_deinit(void *ssl_ctx)
 {
+	struct tls_global *global = ssl_ctx;
+	if (global) {
+		if (global->params_set)
+			gnutls_certificate_free_credentials(global->xcred);
+		os_free(global->session_data);
+		os_free(global);
+	}
+
 	tls_gnutls_ref_count--;
 	if (tls_gnutls_ref_count == 0)
 		gnutls_global_deinit();
@@ -167,13 +244,13 @@
 	}
 
 	end = conn->pull_buf + conn->pull_buf_len;
-	if (end - conn->pull_buf_offset < len)
+	if ((size_t) (end - conn->pull_buf_offset) < len)
 		len = end - conn->pull_buf_offset;
-	memcpy(buf, conn->pull_buf_offset, len);
+	os_memcpy(buf, conn->pull_buf_offset, len);
 	conn->pull_buf_offset += len;
 	if (conn->pull_buf_offset == end) {
 		wpa_printf(MSG_DEBUG, "%s - pull_buf consumed", __func__);
-		free(conn->pull_buf);
+		os_free(conn->pull_buf);
 		conn->pull_buf = conn->pull_buf_offset = NULL;
 		conn->pull_buf_len = 0;
 	} else {
@@ -190,12 +267,12 @@
 	struct tls_connection *conn = (struct tls_connection *) ptr;
 	u8 *nbuf;
 
-	nbuf = realloc(conn->push_buf, conn->push_buf_len + len);
+	nbuf = os_realloc(conn->push_buf, conn->push_buf_len + len);
 	if (nbuf == NULL) {
 		errno = ENOMEM;
 		return -1;
 	}
-	memcpy(nbuf + conn->push_buf_len, buf, len);
+	os_memcpy(nbuf + conn->push_buf_len, buf, len);
 	conn->push_buf = nbuf;
 	conn->push_buf_len += len;
 
@@ -203,33 +280,78 @@
 }
 
 
-struct tls_connection * tls_connection_init(void *ssl_ctx)
+static int tls_gnutls_init_session(struct tls_global *global,
+				   struct tls_connection *conn)
 {
-	struct tls_connection *conn;
 	const int cert_types[2] = { GNUTLS_CRT_X509, 0 };
 	const int protos[2] = { GNUTLS_TLS1, 0 };
+	int ret;
 
-
-	conn = malloc(sizeof(*conn));
-	if (conn == NULL)
-		return NULL;
-	memset(conn, 0, sizeof(*conn));
-	if (gnutls_init(&conn->session, GNUTLS_CLIENT) < 0) {
+	ret = gnutls_init(&conn->session,
+			  global->server ? GNUTLS_SERVER : GNUTLS_CLIENT);
+	if (ret < 0) {
 		wpa_printf(MSG_INFO, "TLS: Failed to initialize new TLS "
-			   "connection");
-		free(conn);
-		return NULL;
+			   "connection: %s", gnutls_strerror(ret));
+		return -1;
 	}
 
-	gnutls_set_default_priority(conn->session);
-	gnutls_certificate_type_set_priority(conn->session, cert_types);
-	gnutls_protocol_set_priority(conn->session, protos);
+	ret = gnutls_set_default_priority(conn->session);
+	if (ret < 0)
+		goto fail;
+
+	ret = gnutls_certificate_type_set_priority(conn->session, cert_types);
+	if (ret < 0)
+		goto fail;
+
+	ret = gnutls_protocol_set_priority(conn->session, protos);
+	if (ret < 0)
+		goto fail;
 
 	gnutls_transport_set_pull_function(conn->session, tls_pull_func);
 	gnutls_transport_set_push_function(conn->session, tls_push_func);
 	gnutls_transport_set_ptr(conn->session, (gnutls_transport_ptr) conn);
 
-	gnutls_certificate_allocate_credentials(&conn->xcred);
+	return 0;
+
+fail:
+	wpa_printf(MSG_INFO, "TLS: Failed to setup new TLS connection: %s",
+		   gnutls_strerror(ret));
+	gnutls_deinit(conn->session);
+	return -1;
+}
+
+
+struct tls_connection * tls_connection_init(void *ssl_ctx)
+{
+	struct tls_global *global = ssl_ctx;
+	struct tls_connection *conn;
+	int ret;
+
+	conn = os_zalloc(sizeof(*conn));
+	if (conn == NULL)
+		return NULL;
+
+	if (tls_gnutls_init_session(global, conn)) {
+		os_free(conn);
+		return NULL;
+	}
+
+	if (global->params_set) {
+		ret = gnutls_credentials_set(conn->session,
+					     GNUTLS_CRD_CERTIFICATE,
+					     global->xcred);
+		if (ret < 0) {
+			wpa_printf(MSG_INFO, "Failed to configure "
+				   "credentials: %s", gnutls_strerror(ret));
+			os_free(conn);
+			return NULL;
+		}
+	}
+
+	if (gnutls_certificate_allocate_credentials(&conn->xcred)) {
+		os_free(conn);
+		return NULL;
+	}
 
 	return conn;
 }
@@ -239,14 +361,26 @@
 {
 	if (conn == NULL)
 		return;
+
+#ifdef GNUTLS_IA
+	if (conn->iacred_srv)
+		gnutls_ia_free_server_credentials(conn->iacred_srv);
+	if (conn->iacred_cli)
+		gnutls_ia_free_client_credentials(conn->iacred_cli);
+	if (conn->session_keys) {
+		os_memset(conn->session_keys, 0, conn->session_keys_len);
+		os_free(conn->session_keys);
+	}
+#endif /* GNUTLS_IA */
+
 	gnutls_certificate_free_credentials(conn->xcred);
 	gnutls_deinit(conn->session);
-	free(conn->pre_shared_secret);
-	free(conn->subject_match);
-	free(conn->altsubject_match);
-	free(conn->push_buf);
-	free(conn->pull_buf);
-	free(conn);
+	os_free(conn->pre_shared_secret);
+	os_free(conn->subject_match);
+	os_free(conn->altsubject_match);
+	os_free(conn->push_buf);
+	os_free(conn->pull_buf);
+	os_free(conn);
 }
 
 
@@ -258,6 +392,9 @@
 
 int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn)
 {
+	struct tls_global *global = ssl_ctx;
+	int ret;
+
 	if (conn == NULL)
 		return -1;
 
@@ -265,11 +402,46 @@
 	 * because the connection was already terminated in practice
 	 * and "close notify" shutdown alert would confuse AS. */
 	gnutls_bye(conn->session, GNUTLS_SHUT_RDWR);
-	free(conn->push_buf);
+	os_free(conn->push_buf);
 	conn->push_buf = NULL;
 	conn->push_buf_len = 0;
 	conn->established = 0;
-	/* TODO: what to do trigger new handshake for re-auth? */
+	conn->final_phase_finished = 0;
+#ifdef GNUTLS_IA
+	if (conn->session_keys) {
+		os_memset(conn->session_keys, 0, conn->session_keys_len);
+		os_free(conn->session_keys);
+	}
+	conn->session_keys_len = 0;
+#endif /* GNUTLS_IA */
+
+	gnutls_deinit(conn->session);
+	if (tls_gnutls_init_session(global, conn)) {
+		wpa_printf(MSG_INFO, "GnuTLS: Failed to preparare new session "
+			   "for session resumption use");
+		return -1;
+	}
+
+	ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE,
+				     conn->params_set ? conn->xcred :
+				     global->xcred);
+	if (ret < 0) {
+		wpa_printf(MSG_INFO, "GnuTLS: Failed to configure credentials "
+			   "for session resumption: %s", gnutls_strerror(ret));
+		return -1;
+	}
+
+	if (global->session_data) {
+		ret = gnutls_session_set_data(conn->session,
+					      global->session_data,
+					      global->session_data_size);
+		if (ret < 0) {
+			wpa_printf(MSG_INFO, "GnuTLS: Failed to set session "
+				   "data: %s", gnutls_strerror(ret));
+			return -1;
+		}
+	}
+
 	return 0;
 }
 
@@ -309,15 +481,15 @@
 
 		wpa_printf(MSG_DEBUG, "TLS: altSubjectName: %s:%s",
 			   field, gen->d.ia5->data);
-		len = strlen(field) + 1 + strlen((char *) gen->d.ia5->data) +
-			1;
-		tmp = malloc(len);
+		len = os_strlen(field) + 1 +
+			strlen((char *) gen->d.ia5->data) + 1;
+		tmp = os_malloc(len);
 		if (tmp == NULL)
 			continue;
 		snprintf(tmp, len, "%s:%s", field, gen->d.ia5->data);
 		if (strstr(tmp, match))
 			found++;
-		free(tmp);
+		os_free(tmp);
 	}
 
 	return found;
@@ -380,18 +552,18 @@
 	if (conn == NULL || params == NULL)
 		return -1;
 
-	free(conn->subject_match);
+	os_free(conn->subject_match);
 	conn->subject_match = NULL;
 	if (params->subject_match) {
-		conn->subject_match = strdup(params->subject_match);
+		conn->subject_match = os_strdup(params->subject_match);
 		if (conn->subject_match == NULL)
 			return -1;
 	}
 
-	free(conn->altsubject_match);
+	os_free(conn->altsubject_match);
 	conn->altsubject_match = NULL;
 	if (params->altsubject_match) {
-		conn->altsubject_match = strdup(params->altsubject_match);
+		conn->altsubject_match = os_strdup(params->altsubject_match);
 		if (conn->altsubject_match == NULL)
 			return -1;
 	}
@@ -415,6 +587,7 @@
 					   "'%s' in DER format: %s",
 					   params->ca_cert,
 					   gnutls_strerror(ret));
+				return -1;
 			}
 		}
 	}
@@ -437,8 +610,33 @@
 				return ret;
 			}
 		}
+	} else if (params->private_key) {
+		int pkcs12_ok = 0;
+#ifdef PKCS12_FUNCS
+		/* Try to load in PKCS#12 format */
+#if LIBGNUTLS_VERSION_NUMBER >= 0x010302
+		ret = gnutls_certificate_set_x509_simple_pkcs12_file(
+			conn->xcred, params->private_key, GNUTLS_X509_FMT_DER,
+			params->private_key_passwd);
+		if (ret != 0) {
+			wpa_printf(MSG_DEBUG, "Failed to load private_key in "
+				   "PKCS#12 format: %s", gnutls_strerror(ret));
+			return -1;
+		} else
+			pkcs12_ok = 1;
+#endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */
+#endif /* PKCS12_FUNCS */
+
+		if (!pkcs12_ok) {
+			wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not "
+				   "included");
+			return -1;
+		}
 	}
 
+	conn->tls_ia = params->tls_ia;
+	conn->params_set = 1;
+
 	ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE,
 				     conn->xcred);
 	if (ret < 0) {
@@ -446,13 +644,122 @@
 			   gnutls_strerror(ret));
 	}
 
+#ifdef GNUTLS_IA
+	if (conn->iacred_cli)
+		gnutls_ia_free_client_credentials(conn->iacred_cli);
+
+	ret = gnutls_ia_allocate_client_credentials(&conn->iacred_cli);
+	if (ret) {
+		wpa_printf(MSG_DEBUG, "Failed to allocate IA credentials: %s",
+			   gnutls_strerror(ret));
+		return -1;
+	}
+
+	ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_IA,
+				     conn->iacred_cli);
+	if (ret) {
+		wpa_printf(MSG_DEBUG, "Failed to configure IA credentials: %s",
+			   gnutls_strerror(ret));
+		gnutls_ia_free_client_credentials(conn->iacred_cli);
+		conn->iacred_cli = NULL;
+		return -1;
+	}
+#endif /* GNUTLS_IE */
+
 	return ret;
 }
 
 
-int tls_global_ca_cert(void *_ssl_ctx, const char *ca_cert)
+int tls_global_set_params(void *tls_ctx,
+			  const struct tls_connection_params *params)
 {
-	/* TODO */
+	struct tls_global *global = tls_ctx;
+	int ret;
+
+	/* Currently, global parameters are only set when running in server
+	 * mode. */
+	global->server = 1;
+
+	if (global->params_set) {
+		gnutls_certificate_free_credentials(global->xcred);
+		global->params_set = 0;
+	}
+
+	ret = gnutls_certificate_allocate_credentials(&global->xcred);
+	if (ret) {
+		wpa_printf(MSG_DEBUG, "Failed to allocate global credentials "
+			   "%s", gnutls_strerror(ret));
+		return -1;
+	}
+
+	if (params->ca_cert) {
+		ret = gnutls_certificate_set_x509_trust_file(
+			global->xcred, params->ca_cert, GNUTLS_X509_FMT_PEM);
+		if (ret < 0) {
+			wpa_printf(MSG_DEBUG, "Failed to read CA cert '%s' "
+				   "in PEM format: %s", params->ca_cert,
+				   gnutls_strerror(ret));
+			ret = gnutls_certificate_set_x509_trust_file(
+				global->xcred, params->ca_cert,
+				GNUTLS_X509_FMT_DER);
+			if (ret < 0) {
+				wpa_printf(MSG_DEBUG, "Failed to read CA cert "
+					   "'%s' in DER format: %s",
+					   params->ca_cert,
+					   gnutls_strerror(ret));
+				goto fail;
+			}
+		}
+	}
+
+	if (params->client_cert && params->private_key) {
+		/* TODO: private_key_passwd? */
+		ret = gnutls_certificate_set_x509_key_file(
+			global->xcred, params->client_cert,
+			params->private_key, GNUTLS_X509_FMT_PEM);
+		if (ret < 0) {
+			wpa_printf(MSG_DEBUG, "Failed to read client cert/key "
+				   "in PEM format: %s", gnutls_strerror(ret));
+			ret = gnutls_certificate_set_x509_key_file(
+				global->xcred, params->client_cert,
+				params->private_key, GNUTLS_X509_FMT_DER);
+			if (ret < 0) {
+				wpa_printf(MSG_DEBUG, "Failed to read client "
+					   "cert/key in DER format: %s",
+					   gnutls_strerror(ret));
+				goto fail;
+			}
+		}
+	} else if (params->private_key) {
+		int pkcs12_ok = 0;
+#ifdef PKCS12_FUNCS
+		/* Try to load in PKCS#12 format */
+#if LIBGNUTLS_VERSION_NUMBER >= 0x010302
+		ret = gnutls_certificate_set_x509_simple_pkcs12_file(
+			global->xcred, params->private_key,
+			GNUTLS_X509_FMT_DER, params->private_key_passwd);
+		if (ret != 0) {
+			wpa_printf(MSG_DEBUG, "Failed to load private_key in "
+				   "PKCS#12 format: %s", gnutls_strerror(ret));
+			goto fail;
+		} else
+			pkcs12_ok = 1;
+#endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */
+#endif /* PKCS12_FUNCS */
+
+		if (!pkcs12_ok) {
+			wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not "
+				   "included");
+			goto fail;
+		}
+	}
+
+	global->params_set = 1;
+
+	return 0;
+
+fail:
+	gnutls_certificate_free_credentials(global->xcred);
 	return -1;
 }
 
@@ -460,62 +767,85 @@
 int tls_global_set_verify(void *ssl_ctx, int check_crl)
 {
 	/* TODO */
-	return -1;
+	return 0;
 }
 
 
 int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn,
 			      int verify_peer)
 {
-	if (conn == NULL)
+	if (conn == NULL || conn->session == NULL)
 		return -1;
 
-	/* TODO */
-
-	return 1;
-}
-
+	conn->verify_peer = verify_peer;
+	gnutls_certificate_server_set_request(conn->session,
+					      verify_peer ? GNUTLS_CERT_REQUIRE
+					      : GNUTLS_CERT_REQUEST);
 
-int tls_global_client_cert(void *_ssl_ctx, const char *client_cert)
-{
-	/* TODO */
-	return -1;
-}
-
-
-int tls_global_private_key(void *_ssl_ctx, const char *private_key,
-			   const char *private_key_passwd)
-{
-	/* TODO */
-	return -1;
+	return 0;
 }
 
 
 int tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn,
 			    struct tls_keys *keys)
 {
+#ifdef GNUTLS_INTERNAL_STRUCTURE_HACK
 	security_parameters_st *sec;
+#endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */
 
 	if (conn == NULL || conn->session == NULL || keys == NULL)
 		return -1;
 
-	memset(keys, 0, sizeof(*keys));
+	os_memset(keys, 0, sizeof(*keys));
+
+#ifdef GNUTLS_INTERNAL_STRUCTURE_HACK
 	sec = &conn->session->security_parameters;
 	keys->master_key = sec->master_secret;
 	keys->master_key_len = TLS_MASTER_SIZE;
 	keys->client_random = sec->client_random;
-	keys->client_random_len = TLS_RANDOM_SIZE;
 	keys->server_random = sec->server_random;
+#else /* GNUTLS_INTERNAL_STRUCTURE_HACK */
+	keys->client_random =
+		(u8 *) gnutls_session_get_client_random(conn->session);
+	keys->server_random =
+		(u8 *) gnutls_session_get_server_random(conn->session);
+	/* No access to master_secret */
+#endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */
+
+#ifdef GNUTLS_IA
+	gnutls_ia_extract_inner_secret(conn->session,
+				       (char *) conn->inner_secret);
+	keys->inner_secret = conn->inner_secret;
+	keys->inner_secret_len = TLS_MASTER_SIZE;
+#endif /* GNUTLS_IA */
+
+	keys->client_random_len = TLS_RANDOM_SIZE;
 	keys->server_random_len = TLS_RANDOM_SIZE;
 
 	return 0;
 }
 
 
+int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
+		       const char *label, int server_random_first,
+		       u8 *out, size_t out_len)
+{
+#if LIBGNUTLS_VERSION_NUMBER >= 0x010302
+	if (conn == NULL || conn->session == NULL)
+		return -1;
+
+	return gnutls_prf(conn->session, os_strlen(label), label,
+			  server_random_first, 0, NULL, out_len, (char *) out);
+#else /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */
+	return -1;
+#endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */
+}
+
+
 static int tls_connection_verify_peer(struct tls_connection *conn)
 {
 	unsigned int status, num_certs, i;
-	time_t now;
+	struct os_time now;
 	const gnutls_datum_t *certs;
 	gnutls_x509_crt_t cert;
 
@@ -541,7 +871,7 @@
 		return -1;
 	}
 
-	now = time(NULL);
+	os_get_time(&now);
 
 	certs = gnutls_certificate_get_peers(conn->session, &num_certs);
 	if (certs == NULL) {
@@ -569,7 +899,7 @@
 
 		gnutls_x509_crt_get_dn(cert, NULL, &len);
 		len++;
-		buf = malloc(len + 1);
+		buf = os_malloc(len + 1);
 		if (buf) {
 			buf[0] = buf[len] = '\0';
 			gnutls_x509_crt_get_dn(cert, buf, &len);
@@ -581,10 +911,10 @@
 			/* TODO: validate subject_match and altsubject_match */
 		}
 
-		free(buf);
+		os_free(buf);
 
-		if (gnutls_x509_crt_get_expiration_time(cert) < now ||
-		    gnutls_x509_crt_get_activation_time(cert) > now) {
+		if (gnutls_x509_crt_get_expiration_time(cert) < now.sec ||
+		    gnutls_x509_crt_get_activation_time(cert) > now.sec) {
 			wpa_printf(MSG_INFO, "TLS: Peer certificate %d/%d is "
 				   "not valid at this time",
 				   i + 1, num_certs);
@@ -601,21 +931,26 @@
 
 u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
 			      const u8 *in_data, size_t in_len,
-			      size_t *out_len)
+			      size_t *out_len, u8 **appl_data,
+			      size_t *appl_data_len)
 {
+	struct tls_global *global = ssl_ctx;
 	u8 *out_data;
 	int ret;
 
+	if (appl_data)
+		*appl_data = NULL;
+
 	if (in_data && in_len) {
 		if (conn->pull_buf) {
 			wpa_printf(MSG_DEBUG, "%s - %d bytes remaining in "
 				   "pull_buf", __func__, conn->pull_buf_len);
-			free(conn->pull_buf);
+			os_free(conn->pull_buf);
 		}
-		conn->pull_buf = malloc(in_len);
+		conn->pull_buf = os_malloc(in_len);
 		if (conn->pull_buf == NULL)
 			return NULL;
-		memcpy(conn->pull_buf, in_data, in_len);
+		os_memcpy(conn->pull_buf, in_data, in_len);
 		conn->pull_buf_offset = conn->pull_buf;
 		conn->pull_buf_len = in_len;
 	}
@@ -624,6 +959,12 @@
 	if (ret < 0) {
 		switch (ret) {
 		case GNUTLS_E_AGAIN:
+			if (global->server && conn->established &&
+			    conn->push_buf == NULL) {
+				/* Need to return something to trigger
+				 * completion of EAP-TLS. */
+				conn->push_buf = os_malloc(1);
+			}
 			break;
 		case GNUTLS_E_FATAL_ALERT_RECEIVED:
 			wpa_printf(MSG_DEBUG, "%s - received fatal '%s' alert",
@@ -637,17 +978,44 @@
 			conn->failed++;
 		}
 	} else {
-		wpa_printf(MSG_DEBUG, "TLS: Handshake completed successfully");
+		size_t size;
+
 		if (conn->verify_peer && tls_connection_verify_peer(conn)) {
 			wpa_printf(MSG_INFO, "TLS: Peer certificate chain "
 				   "failed validation");
 			conn->failed++;
 			return NULL;
 		}
+
+		if (conn->tls_ia && !gnutls_ia_handshake_p(conn->session)) {
+			wpa_printf(MSG_INFO, "TLS: No TLS/IA negotiation");
+			conn->failed++;
+			return NULL;
+		}
+
+		if (conn->tls_ia)
+			wpa_printf(MSG_DEBUG, "TLS: Start TLS/IA handshake");
+		else {
+			wpa_printf(MSG_DEBUG, "TLS: Handshake completed "
+				   "successfully");
+		}
 		conn->established = 1;
 		if (conn->push_buf == NULL) {
 			/* Need to return something to get final TLS ACK. */
-			conn->push_buf = malloc(1);
+			conn->push_buf = os_malloc(1);
+		}
+
+		gnutls_session_get_data(conn->session, NULL, &size);
+		if (global->session_data == NULL ||
+		    global->session_data_size < size) {
+			os_free(global->session_data);
+			global->session_data = os_malloc(size);
+		}
+		if (global->session_data) {
+			global->session_data_size = size;
+			gnutls_session_get_data(conn->session,
+						global->session_data,
+						&global->session_data_size);
 		}
 	}
 
@@ -664,8 +1032,8 @@
 				     const u8 *in_data, size_t in_len,
 				     size_t *out_len)
 {
-	/* TODO */
-	return NULL;
+	return tls_connection_handshake(ssl_ctx, conn, in_data, in_len,
+					out_len, NULL, NULL);
 }
 
 
@@ -674,13 +1042,24 @@
 			   u8 *out_data, size_t out_len)
 {
 	ssize_t res;
+
+#ifdef GNUTLS_IA
+	if (conn->tls_ia)
+		res = gnutls_ia_send(conn->session, (char *) in_data, in_len);
+	else
+#endif /* GNUTLS_IA */
 	res = gnutls_record_send(conn->session, in_data, in_len);
+	if (res < 0) {
+		wpa_printf(MSG_INFO, "%s: Encryption failed: %s",
+			   __func__, gnutls_strerror(res));
+		return -1;
+	}
 	if (conn->push_buf == NULL)
 		return -1;
 	if (conn->push_buf_len < out_len)
 		out_len = conn->push_buf_len;
-	memcpy(out_data, conn->push_buf, out_len);
-	free(conn->push_buf);
+	os_memcpy(out_data, conn->push_buf, out_len);
+	os_free(conn->push_buf);
 	conn->push_buf = NULL;
 	conn->push_buf_len = 0;
 	return out_len;
@@ -696,15 +1075,70 @@
 	if (conn->pull_buf) {
 		wpa_printf(MSG_DEBUG, "%s - %d bytes remaining in "
 			   "pull_buf", __func__, conn->pull_buf_len);
-		free(conn->pull_buf);
+		os_free(conn->pull_buf);
 	}
-	conn->pull_buf = malloc(in_len);
+	conn->pull_buf = os_malloc(in_len);
 	if (conn->pull_buf == NULL)
 		return -1;
-	memcpy(conn->pull_buf, in_data, in_len);
+	os_memcpy(conn->pull_buf, in_data, in_len);
 	conn->pull_buf_offset = conn->pull_buf;
 	conn->pull_buf_len = in_len;
 
+#ifdef GNUTLS_IA
+	if (conn->tls_ia) {
+		res = gnutls_ia_recv(conn->session, (char *) out_data,
+				     out_len);
+		if (out_len >= 12 &&
+		    (res == GNUTLS_E_WARNING_IA_IPHF_RECEIVED ||
+		     res == GNUTLS_E_WARNING_IA_FPHF_RECEIVED)) {
+			int final = res == GNUTLS_E_WARNING_IA_FPHF_RECEIVED;
+			wpa_printf(MSG_DEBUG, "%s: Received %sPhaseFinished",
+				   __func__, final ? "Final" : "Intermediate");
+
+			res = gnutls_ia_permute_inner_secret(
+				conn->session, conn->session_keys_len,
+				(char *) conn->session_keys);
+			if (conn->session_keys) {
+				os_memset(conn->session_keys, 0,
+					  conn->session_keys_len);
+				os_free(conn->session_keys);
+			}
+			conn->session_keys = NULL;
+			conn->session_keys_len = 0;
+			if (res) {
+				wpa_printf(MSG_DEBUG, "%s: Failed to permute "
+					   "inner secret: %s",
+					   __func__, gnutls_strerror(res));
+				return -1;
+			}
+
+			res = gnutls_ia_verify_endphase(conn->session,
+							(char *) out_data);
+			if (res == 0) {
+				wpa_printf(MSG_DEBUG, "%s: Correct endphase "
+					   "checksum", __func__);
+			} else {
+				wpa_printf(MSG_INFO, "%s: Endphase "
+					   "verification failed: %s",
+					   __func__, gnutls_strerror(res));
+				return -1;
+			}
+
+			if (final)
+				conn->final_phase_finished = 1;
+
+			return 0;
+		}
+
+		if (res < 0) {
+			wpa_printf(MSG_DEBUG, "%s - gnutls_ia_recv failed: %d "
+				   "(%s)", __func__, res,
+				   gnutls_strerror(res));
+		}
+		return res;
+	}
+#endif /* GNUTLS_IA */
+
 	res = gnutls_record_recv(conn->session, out_data, out_len);
 	if (res < 0) {
 		wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d "
@@ -723,19 +1157,18 @@
 }
 
 
-#ifdef EAP_FAST
 int tls_connection_set_master_key(void *ssl_ctx, struct tls_connection *conn,
 				  const u8 *key, size_t key_len)
 {
 	/* TODO */
 	return -1;
 }
-#endif /* EAP_FAST */
 
 
-int tls_connection_set_anon_dh(void *ssl_ctx, struct tls_connection *conn)
+int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
+				   u8 *ciphers)
 {
-	/* TODO: set ADH-AES128-SHA cipher */
+	/* TODO */
 	return -1;
 }
 
@@ -757,7 +1190,6 @@
 }
 
 
-#ifdef EAP_FAST
 int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn,
 				    int ext_type, const u8 *data,
 				    size_t data_len)
@@ -765,7 +1197,6 @@
 	/* TODO */
 	return -1;
 }
-#endif /* EAP_FAST */
 
 
 int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn)
@@ -790,3 +1221,150 @@
 		return -1;
 	return conn->write_alerts;
 }
+
+
+int tls_connection_get_keyblock_size(void *tls_ctx,
+				     struct tls_connection *conn)
+{
+	/* TODO */
+	return -1;
+}
+
+
+unsigned int tls_capabilities(void *tls_ctx)
+{
+	unsigned int capa = 0;
+
+#ifdef GNUTLS_IA
+	capa |= TLS_CAPABILITY_IA;
+#endif /* GNUTLS_IA */
+
+	return capa;
+}
+
+
+int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn,
+			  int tls_ia)
+{
+#ifdef GNUTLS_IA
+	int ret;
+
+	if (conn == NULL)
+		return -1;
+
+	conn->tls_ia = tls_ia;
+	if (!tls_ia)
+		return 0;
+
+	ret = gnutls_ia_allocate_server_credentials(&conn->iacred_srv);
+	if (ret) {
+		wpa_printf(MSG_DEBUG, "Failed to allocate IA credentials: %s",
+			   gnutls_strerror(ret));
+		return -1;
+	}
+
+	ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_IA,
+				     conn->iacred_srv);
+	if (ret) {
+		wpa_printf(MSG_DEBUG, "Failed to configure IA credentials: %s",
+			   gnutls_strerror(ret));
+		gnutls_ia_free_server_credentials(conn->iacred_srv);
+		conn->iacred_srv = NULL;
+		return -1;
+	}
+
+	return 0;
+#else /* GNUTLS_IA */
+	return -1;
+#endif /* GNUTLS_IA */
+}
+
+
+int tls_connection_ia_send_phase_finished(void *tls_ctx,
+					  struct tls_connection *conn,
+					  int final,
+					  u8 *out_data, size_t out_len)
+{
+#ifdef GNUTLS_IA
+	int ret;
+
+	if (conn == NULL || conn->session == NULL || !conn->tls_ia)
+		return -1;
+
+	ret = gnutls_ia_permute_inner_secret(conn->session,
+					     conn->session_keys_len,
+					     (char *) conn->session_keys);
+	if (conn->session_keys) {
+		os_memset(conn->session_keys, 0, conn->session_keys_len);
+		os_free(conn->session_keys);
+	}
+	conn->session_keys = NULL;
+	conn->session_keys_len = 0;
+	if (ret) {
+		wpa_printf(MSG_DEBUG, "%s: Failed to permute inner secret: %s",
+			   __func__, gnutls_strerror(ret));
+		return -1;
+	}
+
+	ret = gnutls_ia_endphase_send(conn->session, final);
+	if (ret) {
+		wpa_printf(MSG_DEBUG, "%s: Failed to send endphase: %s",
+			   __func__, gnutls_strerror(ret));
+		return -1;
+	}
+
+	if (conn->push_buf == NULL)
+		return -1;
+	if (conn->push_buf_len < out_len)
+		out_len = conn->push_buf_len;
+	os_memcpy(out_data, conn->push_buf, out_len);
+	os_free(conn->push_buf);
+	conn->push_buf = NULL;
+	conn->push_buf_len = 0;
+	return out_len;
+#else /* GNUTLS_IA */
+	return -1;
+#endif /* GNUTLS_IA */
+}
+
+
+int tls_connection_ia_final_phase_finished(void *tls_ctx,
+					   struct tls_connection *conn)
+{
+	if (conn == NULL)
+		return -1;
+
+	return conn->final_phase_finished;
+}
+
+
+int tls_connection_ia_permute_inner_secret(void *tls_ctx,
+					   struct tls_connection *conn,
+					   const u8 *key, size_t key_len)
+{
+#ifdef GNUTLS_IA
+	if (conn == NULL || !conn->tls_ia)
+		return -1;
+
+	if (conn->session_keys) {
+		os_memset(conn->session_keys, 0, conn->session_keys_len);
+		os_free(conn->session_keys);
+	}
+	conn->session_keys_len = 0;
+
+	if (key) {
+		conn->session_keys = os_malloc(key_len);
+		if (conn->session_keys == NULL)
+			return -1;
+		os_memcpy(conn->session_keys, key, key_len);
+		conn->session_keys_len = key_len;
+	} else {
+		conn->session_keys = NULL;
+		conn->session_keys_len = 0;
+	}
+
+	return 0;
+#else /* GNUTLS_IA */
+	return -1;
+#endif /* GNUTLS_IA */
+}
Index: config.h
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/config.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/config.h -L contrib/wpa_supplicant/config.h -u -r1.2 -r1.3
--- contrib/wpa_supplicant/config.h
+++ contrib/wpa_supplicant/config.h
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant / Configuration file structures
- * Copyright (c) 2003-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2003-2005, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -15,12 +15,6 @@
 #ifndef CONFIG_H
 #define CONFIG_H
 
-#ifdef CONFIG_CTRL_IFACE
-#ifndef CONFIG_CTRL_IFACE_UDP
-#include <grp.h>
-#endif /* CONFIG_CTRL_IFACE_UDP */
-#endif /* CONFIG_CTRL_IFACE */
-
 #define DEFAULT_EAPOL_VERSION 1
 #define DEFAULT_AP_SCAN 1
 #define DEFAULT_FAST_REAUTH 1
@@ -128,45 +122,67 @@
 	int ap_scan;
 
 	/**
-	 * ctrl_interface - Directory for UNIX domain sockets
+	 * ctrl_interface - Parameters for the control interface
 	 *
-	 * This variable is used to configure where the UNIX domain sockets
-	 * for the control interface are created. If UDP-based ctrl_iface is
-	 * used, this variable can be set to any string (i.e., %NULL is not
-	 * allowed).
-	 */
-	char *ctrl_interface;
-
-#ifdef CONFIG_CTRL_IFACE
-#ifndef CONFIG_CTRL_IFACE_UDP
-	/**
-	 * ctrl_interface_gid - Group identity for the UNIX domain sockets
+	 * If this is specified, %wpa_supplicant will open a control interface
+	 * that is available for external programs to manage %wpa_supplicant.
+	 * The meaning of this string depends on which control interface
+	 * mechanism is used. For all cases, the existance of this parameter
+	 * in configuration is used to determine whether the control interface
+	 * is enabled.
+	 *
+	 * For UNIX domain sockets (default on Linux and BSD): This is a
+	 * directory that will be created for UNIX domain sockets for listening
+	 * to requests from external programs (CLI/GUI, etc.) for status
+	 * information and configuration. The socket file will be named based
+	 * on the interface name, so multiple %wpa_supplicant processes can be
+	 * run at the same time if more than one interface is used.
+	 * /var/run/wpa_supplicant is the recommended directory for sockets and
+	 * by default, wpa_cli will use it when trying to connect with
+	 * %wpa_supplicant.
 	 *
 	 * Access control for the control interface can be configured
 	 * by setting the directory to allow only members of a group
 	 * to use sockets. This way, it is possible to run
-	 * wpa_supplicant as root (since it needs to change network
+	 * %wpa_supplicant as root (since it needs to change network
 	 * configuration and open raw sockets) and still allow GUI/CLI
 	 * components to be run as non-root users. However, since the
 	 * control interface can be used to change the network
 	 * configuration, this access needs to be protected in many
-	 * cases. By default, wpa_supplicant is configured to use gid
+	 * cases. By default, %wpa_supplicant is configured to use gid
 	 * 0 (root). If you want to allow non-root users to use the
 	 * control interface, add a new group and change this value to
 	 * match with that group. Add users that should have control
 	 * interface access to this group.
+	 *
+	 * When configuring both the directory and group, use following format:
+	 * DIR=/var/run/wpa_supplicant GROUP=wheel
+	 * DIR=/var/run/wpa_supplicant GROUP=0
+	 * (group can be either group name or gid)
+	 *
+	 * For UDP connections (default on Windows): The value will be ignored.
+	 * This variable is just used to select that the control interface is
+	 * to be created. The value can be set to, e.g., udp
+	 * (ctrl_interface=udp).
+	 *
+	 * For Windows Named Pipe: This value can be used to set the security
+	 * descriptor for controlling access to the control interface. Security
+	 * descriptor can be set using Security Descriptor String Format (see
+	 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/secauthz/security/security_descriptor_string_format.asp).
+	 * The descriptor string needs to be prefixed with SDDL=. For example,
+	 * ctrl_interface=SDDL=D: would set an empty DACL (which will reject
+	 * all connections).
 	 */
-	gid_t ctrl_interface_gid;
-#endif /* CONFIG_CTRL_IFACE_UDP */
+	char *ctrl_interface;
+
 	/**
-	 * ctrl_interface_gid_set - Whether ctrl_interface_gid is used
+	 * ctrl_interface_group - Control interface group (DEPRECATED)
 	 *
-	 * If this variable is zero, ctrl_interface_gid value is not used and
-	 * group will not be changed from the value it got by default
-	 * when the directory or socket was created.
+	 * This variable is only used for backwards compatibility. Group for
+	 * UNIX domain sockets should now be specified using GROUP=<group> in
+	 * ctrl_interface variable.
 	 */
-	int ctrl_interface_gid_set;
-#endif /* CONFIG_CTRL_IFACE */
+	char *ctrl_interface_group;
 
 	/**
 	 * fast_reauth - EAP fast re-authentication (session resumption)
@@ -257,7 +273,7 @@
 };
 
 
-/* Protypes for common functions from config.c */
+/* Prototypes for common functions from config.c */
 
 void wpa_config_free(struct wpa_config *ssid);
 void wpa_config_free_ssid(struct wpa_ssid *ssid);
@@ -268,6 +284,7 @@
 int wpa_config_set(struct wpa_ssid *ssid, const char *var, const char *value,
 		   int line);
 char * wpa_config_get(struct wpa_ssid *ssid, const char *var);
+char * wpa_config_get_no_key(struct wpa_ssid *ssid, const char *var);
 void wpa_config_update_psk(struct wpa_ssid *ssid);
 int wpa_config_add_prio_network(struct wpa_config *config,
 				struct wpa_ssid *ssid);
@@ -280,6 +297,11 @@
 int wpa_config_remove_blob(struct wpa_config *config, const char *name);
 struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface,
 					   const char *driver_param);
+#ifndef CONFIG_NO_STDOUT_DEBUG
+void wpa_config_debug_dump_networks(struct wpa_config *config);
+#else /* CONFIG_NO_STDOUT_DEBUG */
+#define wpa_config_debug_dump_networks(c) do { } while (0)
+#endif /* CONFIG_NO_STDOUT_DEBUG */
 
 
 /* Prototypes for backend specific functions from the selected config_*.c */
Index: preauth_test.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/preauth_test.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/preauth_test.c -L contrib/wpa_supplicant/preauth_test.c -u -r1.2 -r1.3
--- contrib/wpa_supplicant/preauth_test.c
+++ contrib/wpa_supplicant/preauth_test.c
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant - test code for pre-authentication
- * Copyright (c) 2003-2006, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2003-2006, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -15,15 +15,8 @@
  * Not used in production version.
  */
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <ctype.h>
-#include <string.h>
-#include <signal.h>
-#include <netinet/in.h>
+#include "includes.h"
 #include <assert.h>
-#include <arpa/inet.h>
 
 #include "common.h"
 #include "config.h"
@@ -37,12 +30,13 @@
 #include "ctrl_iface.h"
 #include "pcsc_funcs.h"
 #include "preauth.h"
+#include "pmksa_cache.h"
 
 
 extern int wpa_debug_level;
 extern int wpa_debug_show_keys;
 
-struct wpa_driver_ops *wpa_supplicant_drivers[] = { };
+struct wpa_driver_ops *wpa_supplicant_drivers[] = { NULL };
 
 
 struct preauth_test_data {
@@ -75,7 +69,7 @@
 	struct ieee802_1x_hdr *hdr;
 
 	*msg_len = sizeof(*hdr) + data_len;
-	hdr = malloc(*msg_len);
+	hdr = os_malloc(*msg_len);
 	if (hdr == NULL)
 		return NULL;
 
@@ -84,9 +78,9 @@
 	hdr->length = htons(data_len);
 
 	if (data)
-		memcpy(hdr + 1, data, data_len);
+		os_memcpy(hdr + 1, data, data_len);
 	else
-		memset(hdr + 1, 0, data_len);
+		os_memset(hdr + 1, 0, data_len);
 
 	if (data_pos)
 		*data_pos = hdr + 1;
@@ -167,6 +161,15 @@
 }
 
 
+static int wpa_supplicant_mlme_setprotection(void *wpa_s, const u8 *addr,
+					     int protection_type,
+					     int key_type)
+{
+	printf("%s - not implemented\n", __func__);
+	return -1;
+}
+
+
 static int wpa_supplicant_add_pmkid(void *wpa_s,
 				    const u8 *bssid, const u8 *pmkid)
 {
@@ -203,10 +206,12 @@
 {
 	rsn_preauth_deinit(wpa_s->wpa);
 	pmksa_candidate_free(wpa_s->wpa);
-	pmksa_cache_free(wpa_s->wpa);
 	wpa_sm_deinit(wpa_s->wpa);
 	scard_deinit(wpa_s->scard);
-	wpa_supplicant_ctrl_iface_deinit(wpa_s);
+	if (wpa_s->ctrl_iface) {
+		wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
+		wpa_s->ctrl_iface = NULL;
+	}
 	wpa_config_free(wpa_s->conf);
 }
 
@@ -240,13 +245,12 @@
 	struct l2_packet_data *l2;
 	struct wpa_sm_ctx *ctx;
 
-	memset(&dummy_driver, 0, sizeof(dummy_driver));
+	os_memset(&dummy_driver, 0, sizeof(dummy_driver));
 	wpa_s->driver = &dummy_driver;
 
-	ctx = malloc(sizeof(*ctx));
+	ctx = os_zalloc(sizeof(*ctx));
 	assert(ctx != NULL);
 
-	memset(ctx, 0, sizeof(*ctx));
 	ctx->ctx = wpa_s;
 	ctx->set_state = _wpa_supplicant_set_state;
 	ctx->get_state = _wpa_supplicant_get_state;
@@ -265,13 +269,14 @@
 	ctx->remove_pmkid = wpa_supplicant_remove_pmkid;
 	ctx->set_config_blob = wpa_supplicant_set_config_blob;
 	ctx->get_config_blob = wpa_supplicant_get_config_blob;
+	ctx->mlme_setprotection = wpa_supplicant_mlme_setprotection;
 
 	wpa_s->wpa = wpa_sm_init(ctx);
 	assert(wpa_s->wpa != NULL);
 	wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, WPA_PROTO_RSN);
 
-	strncpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
-	wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname);
+	os_strncpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
+	wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname, NULL);
 
 	l2 = l2_packet_init(wpa_s->ifname, NULL, ETH_P_RSN_PREAUTH, NULL,
 			    NULL, 0);
@@ -301,7 +306,10 @@
 	u8 bssid[ETH_ALEN];
 	struct preauth_test_data preauth_test;
 
-	memset(&preauth_test, 0, sizeof(preauth_test));
+	if (os_program_init())
+		return -1;
+
+	os_memset(&preauth_test, 0, sizeof(preauth_test));
 
 	wpa_debug_level = 0;
 	wpa_debug_show_keys = 1;
@@ -317,9 +325,17 @@
 		return -1;
 	}
 
-	eloop_init(&wpa_s);
+	if (eap_peer_register_methods()) {
+		wpa_printf(MSG_ERROR, "Failed to register EAP methods");
+		return -1;
+	}
+
+	if (eloop_init(&wpa_s)) {
+		wpa_printf(MSG_ERROR, "Failed to initialize event loop");
+		return -1;
+	}
 
-	memset(&wpa_s, 0, sizeof(wpa_s));
+	os_memset(&wpa_s, 0, sizeof(wpa_s));
 	wpa_s.conf = wpa_config_read(argv[1]);
 	if (wpa_s.conf == NULL) {
 		printf("Failed to parse configuration file '%s'.\n", argv[1]);
@@ -331,7 +347,8 @@
 	}
 
 	wpa_init_conf(&wpa_s, argv[3]);
-	if (wpa_supplicant_ctrl_iface_init(&wpa_s)) {
+	wpa_s.ctrl_iface = wpa_supplicant_ctrl_iface_init(&wpa_s);
+	if (wpa_s.ctrl_iface == NULL) {
 		printf("Failed to initialize control interface '%s'.\n"
 		       "You may have another preauth_test process already "
 		       "running or the file was\n"
@@ -350,20 +367,24 @@
 
 	eloop_register_timeout(30, 0, eapol_test_timeout, &preauth_test, NULL);
 	eloop_register_timeout(0, 100000, eapol_test_poll, &wpa_s, NULL);
-	eloop_register_signal(SIGINT, eapol_test_terminate, NULL);
-	eloop_register_signal(SIGTERM, eapol_test_terminate, NULL);
-	eloop_register_signal(SIGHUP, eapol_test_terminate, NULL);
+	eloop_register_signal_terminate(eapol_test_terminate, NULL);
+	eloop_register_signal_reconfig(eapol_test_terminate, NULL);
 	eloop_run();
 
 	if (preauth_test.auth_timed_out)
 		ret = -2;
 	else {
-		ret = pmksa_cache_get(wpa_s.wpa, bssid, NULL) ? 0 : -3;
+		ret = pmksa_cache_set_current(wpa_s.wpa, NULL, bssid, NULL, 0)
+			? 0 : -3;
 	}
 
 	test_eapol_clean(&wpa_s);
 
+	eap_peer_unregister_methods();
+
 	eloop_destroy();
 
+	os_program_deinit();
+
 	return ret;
 }
Index: eap_psk_common.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/eap_psk_common.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -L contrib/wpa_supplicant/eap_psk_common.c -L contrib/wpa_supplicant/eap_psk_common.c -u -r1.1 -r1.2
--- contrib/wpa_supplicant/eap_psk_common.c
+++ contrib/wpa_supplicant/eap_psk_common.c
@@ -1,6 +1,6 @@
 /*
- * WPA Supplicant / EAP-PSK shared routines
- * Copyright (c) 2004-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * EAP server/peer: EAP-PSK shared routines
+ * Copyright (c) 2004-2006, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -12,12 +12,11 @@
  * See README and COPYING for more details.
  */
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
+#include "includes.h"
 
 #include "common.h"
 #include "aes_wrap.h"
+#include "eap_defs.h"
 #include "eap_psk_common.h"
 
 #define aes_block_size 16
@@ -25,9 +24,9 @@
 
 void eap_psk_key_setup(const u8 *psk, u8 *ak, u8 *kdk)
 {
-	memset(ak, 0, aes_block_size);
+	os_memset(ak, 0, aes_block_size);
 	aes_128_encrypt_block(psk, ak, ak);
-	memcpy(kdk, ak, aes_block_size);
+	os_memcpy(kdk, ak, aes_block_size);
 	ak[aes_block_size - 1] ^= 0x01;
 	kdk[aes_block_size - 1] ^= 0x02;
 	aes_128_encrypt_block(psk, ak, ak);
@@ -35,7 +34,8 @@
 }
 
 
-void eap_psk_derive_keys(const u8 *kdk, const u8 *rand_p, u8 *tek, u8 *msk)
+void eap_psk_derive_keys(const u8 *kdk, const u8 *rand_p, u8 *tek, u8 *msk,
+			 u8 *emsk)
 {
 	u8 hash[aes_block_size];
 	u8 counter = 1;
@@ -48,10 +48,17 @@
 	hash[aes_block_size - 1] ^= counter;
 	counter++;
 
-	for (i = 0; i < EAP_PSK_MSK_LEN / aes_block_size; i++) {
+	for (i = 0; i < EAP_MSK_LEN / aes_block_size; i++) {
 		hash[aes_block_size - 1] ^= counter;
 		aes_128_encrypt_block(kdk, hash, &msk[i * aes_block_size]);
 		hash[aes_block_size - 1] ^= counter;
 		counter++;
 	}
+
+	for (i = 0; i < EAP_EMSK_LEN / aes_block_size; i++) {
+		hash[aes_block_size - 1] ^= counter;
+		aes_128_encrypt_block(kdk, hash, &emsk[i * aes_block_size]);
+		hash[aes_block_size - 1] ^= counter;
+		counter++;
+	}
 }
Index: common.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/common.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/common.c -L contrib/wpa_supplicant/common.c -u -r1.2 -r1.3
--- contrib/wpa_supplicant/common.c
+++ contrib/wpa_supplicant/common.c
@@ -1,6 +1,6 @@
 /*
  * wpa_supplicant/hostapd / common helper functions, etc.
- * Copyright (c) 2002-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2002-2006, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -12,70 +12,20 @@
  * See README and COPYING for more details.
  */
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#include <stdarg.h>
-#include <ctype.h>
-#include <time.h>
-#include <sys/time.h>
-#ifdef CONFIG_NATIVE_WINDOWS
-#include <winsock2.h>
-#include <wincrypt.h>
-#endif /* CONFIG_NATIVE_WINDOWS */
+#include "includes.h"
 
 #include "common.h"
 
 
+#ifdef CONFIG_DEBUG_FILE
+static FILE *out_file = NULL;
+#endif /* CONFIG_DEBUG_FILE */
+int wpa_debug_use_file = 0;
 int wpa_debug_level = MSG_INFO;
 int wpa_debug_show_keys = 0;
 int wpa_debug_timestamp = 0;
 
 
-int hostapd_get_rand(u8 *buf, size_t len)
-{
-#ifdef CONFIG_NATIVE_WINDOWS
-	HCRYPTPROV prov;
-	BOOL ret;
-
-	if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL,
-				 CRYPT_VERIFYCONTEXT))
-		return -1;
-
-	ret = CryptGenRandom(prov, len, buf);
-	CryptReleaseContext(prov, 0);
-
-	return ret ? 0 : -1;
-#else /* CONFIG_NATIVE_WINDOWS */
-	FILE *f;
-	size_t rc;
-
-	f = fopen("/dev/urandom", "r");
-	if (f == NULL) {
-		printf("Could not open /dev/urandom.\n");
-		return -1;
-	}
-
-	rc = fread(buf, 1, len, f);
-	fclose(f);
-
-	return rc != len ? -1 : 0;
-#endif /* CONFIG_NATIVE_WINDOWS */
-}
-
-
-void hostapd_hexdump(const char *title, const u8 *buf, size_t len)
-{
-	size_t i;
-	printf("%s - hexdump(len=%lu):", title, (unsigned long) len);
-	for (i = 0; i < len; i++)
-		printf(" %02x", buf[i]);
-	printf("\n");
-}
-
-
 static int hex2num(char c)
 {
 	if (c >= '0' && c <= '9')
@@ -139,7 +89,8 @@
  */
 int hexstr2bin(const char *hex, u8 *buf, size_t len)
 {
-	int i, a;
+	size_t i;
+	int a;
 	const char *ipos = hex;
 	u8 *opos = buf;
 
@@ -154,45 +105,6 @@
 }
 
 
-char * rel2abs_path(const char *rel_path)
-{
-	char *buf = NULL, *cwd, *ret;
-	size_t len = 128, cwd_len, rel_len, ret_len;
-
-	if (rel_path[0] == '/')
-		return strdup(rel_path);
-
-	for (;;) {
-		buf = malloc(len);
-		if (buf == NULL)
-			return NULL;
-		cwd = getcwd(buf, len);
-		if (cwd == NULL) {
-			free(buf);
-			if (errno != ERANGE) {
-				return NULL;
-			}
-			len *= 2;
-		} else {
-			break;
-		}
-	}
-
-	cwd_len = strlen(cwd);
-	rel_len = strlen(rel_path);
-	ret_len = cwd_len + 1 + rel_len + 1;
-	ret = malloc(ret_len);
-	if (ret) {
-		memcpy(ret, cwd, cwd_len);
-		ret[cwd_len] = '/';
-		memcpy(ret + cwd_len + 1, rel_path, rel_len);
-		ret[ret_len - 1] = '\0';
-	}
-	free(buf);
-	return ret;
-}
-
-
 /**
  * inc_byte_array - Increment arbitrary length byte array by one
  * @counter: Pointer to byte array
@@ -214,40 +126,40 @@
 }
 
 
-void print_char(char c)
+void wpa_get_ntp_timestamp(u8 *buf)
 {
-	if (c >= 32 && c < 127)
-		printf("%c", c);
-	else
-		printf("<%02x>", c);
-}
-
+	struct os_time now;
+	u32 sec, usec;
 
-void fprint_char(FILE *f, char c)
-{
-	if (c >= 32 && c < 127)
-		fprintf(f, "%c", c);
-	else
-		fprintf(f, "<%02x>", c);
+	/* 64-bit NTP timestamp (time from 1900-01-01 00:00:00) */
+	os_get_time(&now);
+	sec = host_to_be32(now.sec + 2208988800U); /* Epoch to 1900 */
+	/* Estimate 2^32/10^6 = 4295 - 1/32 - 1/512 */
+	usec = now.usec;
+	usec = host_to_be32(4295 * usec - (usec >> 5) - (usec >> 9));
+	os_memcpy(buf, (u8 *) &sec, 4);
+	os_memcpy(buf + 4, (u8 *) &usec, 4);
 }
 
 
+
 #ifndef CONFIG_NO_STDOUT_DEBUG
 
 void wpa_debug_print_timestamp(void)
 {
-	struct timeval tv;
-	char buf[16];
+	struct os_time tv;
 
 	if (!wpa_debug_timestamp)
 		return;
 
-	gettimeofday(&tv, NULL);
-	if (strftime(buf, sizeof(buf), "%b %d %H:%M:%S",
-		     localtime((const time_t *) &tv.tv_sec)) <= 0) {
-		snprintf(buf, sizeof(buf), "%u", (int) tv.tv_sec);
-	}
-	printf("%s.%06u: ", buf, (unsigned int) tv.tv_usec);
+	os_get_time(&tv);
+#ifdef CONFIG_DEBUG_FILE
+	if (out_file) {
+		fprintf(out_file, "%ld.%06u: ", (long) tv.sec,
+			(unsigned int) tv.usec);
+	} else
+#endif /* CONFIG_DEBUG_FILE */
+	printf("%ld.%06u: ", (long) tv.sec, (unsigned int) tv.usec);
 }
 
 
@@ -269,8 +181,17 @@
 	va_start(ap, fmt);
 	if (level >= wpa_debug_level) {
 		wpa_debug_print_timestamp();
+#ifdef CONFIG_DEBUG_FILE
+		if (out_file) {
+			vfprintf(out_file, fmt, ap);
+			fprintf(out_file, "\n");
+		} else {
+#endif /* CONFIG_DEBUG_FILE */
 		vprintf(fmt, ap);
 		printf("\n");
+#ifdef CONFIG_DEBUG_FILE
+		}
+#endif /* CONFIG_DEBUG_FILE */
 	}
 	va_end(ap);
 }
@@ -283,6 +204,21 @@
 	if (level < wpa_debug_level)
 		return;
 	wpa_debug_print_timestamp();
+#ifdef CONFIG_DEBUG_FILE
+	if (out_file) {
+		fprintf(out_file, "%s - hexdump(len=%lu):",
+			title, (unsigned long) len);
+		if (buf == NULL) {
+			fprintf(out_file, " [NULL]");
+		} else if (show) {
+			for (i = 0; i < len; i++)
+				fprintf(out_file, " %02x", buf[i]);
+		} else {
+			fprintf(out_file, " [REMOVED]");
+		}
+		fprintf(out_file, "\n");
+	} else {
+#endif /* CONFIG_DEBUG_FILE */
 	printf("%s - hexdump(len=%lu):", title, (unsigned long) len);
 	if (buf == NULL) {
 		printf(" [NULL]");
@@ -293,6 +229,9 @@
 		printf(" [REMOVED]");
 	}
 	printf("\n");
+#ifdef CONFIG_DEBUG_FILE
+	}
+#endif /* CONFIG_DEBUG_FILE */
 }
 
 void wpa_hexdump(int level, const char *title, const u8 *buf, size_t len)
@@ -310,13 +249,51 @@
 static void _wpa_hexdump_ascii(int level, const char *title, const u8 *buf,
 			       size_t len, int show)
 {
-	int i, llen;
+	size_t i, llen;
 	const u8 *pos = buf;
-	const int line_len = 16;
+	const size_t line_len = 16;
 
 	if (level < wpa_debug_level)
 		return;
 	wpa_debug_print_timestamp();
+#ifdef CONFIG_DEBUG_FILE
+	if (out_file) {
+		if (!show) {
+			fprintf(out_file,
+				"%s - hexdump_ascii(len=%lu): [REMOVED]\n",
+				title, (unsigned long) len);
+			return;
+		}
+		if (buf == NULL) {
+			fprintf(out_file,
+				"%s - hexdump_ascii(len=%lu): [NULL]\n",
+				title, (unsigned long) len);
+			return;
+		}
+		fprintf(out_file, "%s - hexdump_ascii(len=%lu):\n",
+			title, (unsigned long) len);
+		while (len) {
+			llen = len > line_len ? line_len : len;
+			fprintf(out_file, "    ");
+			for (i = 0; i < llen; i++)
+				fprintf(out_file, " %02x", pos[i]);
+			for (i = llen; i < line_len; i++)
+				fprintf(out_file, "   ");
+			fprintf(out_file, "   ");
+			for (i = 0; i < llen; i++) {
+				if (isprint(pos[i]))
+					fprintf(out_file, "%c", pos[i]);
+				else
+					fprintf(out_file, "_");
+			}
+			for (i = llen; i < line_len; i++)
+				fprintf(out_file, " ");
+			fprintf(out_file, "\n");
+			pos += llen;
+			len -= llen;
+		}
+	} else {
+#endif /* CONFIG_DEBUG_FILE */
 	if (!show) {
 		printf("%s - hexdump_ascii(len=%lu): [REMOVED]\n",
 		       title, (unsigned long) len);
@@ -348,6 +325,9 @@
 		pos += llen;
 		len -= llen;
 	}
+#ifdef CONFIG_DEBUG_FILE
+	}
+#endif /* CONFIG_DEBUG_FILE */
 }
 
 
@@ -363,26 +343,261 @@
 	_wpa_hexdump_ascii(level, title, buf, len, wpa_debug_show_keys);
 }
 
+
+int wpa_debug_open_file(void)
+{
+#ifdef CONFIG_DEBUG_FILE
+	static int count = 0;
+	char fname[64];
+	if (!wpa_debug_use_file)
+		return 0;
+#ifdef _WIN32
+	os_snprintf(fname, sizeof(fname), "\\Temp\\wpa_supplicant-log-%d.txt",
+		    count++);
+#else /* _WIN32 */
+	os_snprintf(fname, sizeof(fname), "/tmp/wpa_supplicant-log-%d.txt",
+		    count++);
+#endif /* _WIN32 */
+	out_file = fopen(fname, "w");
+	return out_file == NULL ? -1 : 0;
+#else /* CONFIG_DEBUG_FILE */
+	return 0;
+#endif /* CONFIG_DEBUG_FILE */
+}
+
+
+void wpa_debug_close_file(void)
+{
+#ifdef CONFIG_DEBUG_FILE
+	if (!wpa_debug_use_file)
+		return;
+	fclose(out_file);
+	out_file = NULL;
+#endif /* CONFIG_DEBUG_FILE */
+}
+
 #endif /* CONFIG_NO_STDOUT_DEBUG */
 
 
-#ifdef CONFIG_NATIVE_WINDOWS
+#ifndef CONFIG_NO_WPA_MSG
+static wpa_msg_cb_func wpa_msg_cb = NULL;
+
+void wpa_msg_register_cb(wpa_msg_cb_func func)
+{
+	wpa_msg_cb = func;
+}
 
-#define EPOCHFILETIME (116444736000000000ULL)
 
-int gettimeofday(struct timeval *tv, struct timezone *tz)
+void wpa_msg(void *ctx, int level, char *fmt, ...)
 {
-	FILETIME ft;
-	LARGE_INTEGER li;
-	ULONGLONG t;
-
-	GetSystemTimeAsFileTime(&ft);
-	li.LowPart = ft.dwLowDateTime;
-	li.HighPart = ft.dwHighDateTime;
-	t = (li.QuadPart - EPOCHFILETIME) / 10;
-	tv->tv_sec = (long) (t / 1000000);
-	tv->tv_usec = (long) (t % 1000000);
+	va_list ap;
+	char *buf;
+	const int buflen = 2048;
+	int len;
 
-	return 0;
+	buf = os_malloc(buflen);
+	if (buf == NULL) {
+		wpa_printf(MSG_ERROR, "wpa_msg: Failed to allocate message "
+			   "buffer");
+		return;
+	}
+	va_start(ap, fmt);
+	len = vsnprintf(buf, buflen, fmt, ap);
+	va_end(ap);
+	wpa_printf(level, "%s", buf);
+	if (wpa_msg_cb)
+		wpa_msg_cb(ctx, level, buf, len);
+	os_free(buf);
+}
+#endif /* CONFIG_NO_WPA_MSG */
+
+
+static inline int _wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data,
+				    size_t len, int uppercase)
+{
+	size_t i;
+	char *pos = buf, *end = buf + buf_size;
+	int ret;
+	if (buf_size == 0)
+		return 0;
+	for (i = 0; i < len; i++) {
+		ret = os_snprintf(pos, end - pos, uppercase ? "%02X" : "%02x",
+				  data[i]);
+		if (ret < 0 || ret >= end - pos) {
+			end[-1] = '\0';
+			return pos - buf;
+		}
+		pos += ret;
+	}
+	end[-1] = '\0';
+	return pos - buf;
+}
+
+/**
+ * wpa_snprintf_hex - Print data as a hex string into a buffer
+ * @buf: Memory area to use as the output buffer
+ * @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1)
+ * @data: Data to be printed
+ * @len: Length of data in bytes
+ * Returns: Number of bytes written
+ */
+int wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len)
+{
+	return _wpa_snprintf_hex(buf, buf_size, data, len, 0);
+}
+
+
+/**
+ * wpa_snprintf_hex_uppercase - Print data as a upper case hex string into buf
+ * @buf: Memory area to use as the output buffer
+ * @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1)
+ * @data: Data to be printed
+ * @len: Length of data in bytes
+ * Returns: Number of bytes written
+ */
+int wpa_snprintf_hex_uppercase(char *buf, size_t buf_size, const u8 *data,
+			       size_t len)
+{
+	return _wpa_snprintf_hex(buf, buf_size, data, len, 1);
+}
+
+
+#ifdef CONFIG_ANSI_C_EXTRA
+
+#ifdef _WIN32_WCE
+void perror(const char *s)
+{
+	wpa_printf(MSG_ERROR, "%s: GetLastError: %d",
+		   s, (int) GetLastError());
+}
+#endif /* _WIN32_WCE */
+
+
+int optind = 1;
+int optopt;
+char *optarg;
+
+int getopt(int argc, char *const argv[], const char *optstring)
+{
+	static int optchr = 1;
+	char *cp;
+
+	if (optchr == 1) {
+		if (optind >= argc) {
+			/* all arguments processed */
+			return EOF;
+		}
+
+		if (argv[optind][0] != '-' || argv[optind][1] == '\0') {
+			/* no option characters */
+			return EOF;
+		}
+	}
+
+	if (os_strcmp(argv[optind], "--") == 0) {
+		/* no more options */
+		optind++;
+		return EOF;
+	}
+
+	optopt = argv[optind][optchr];
+	cp = os_strchr(optstring, optopt);
+	if (cp == NULL || optopt == ':') {
+		if (argv[optind][++optchr] == '\0') {
+			optchr = 1;
+			optind++;
+		}
+		return '?';
+	}
+
+	if (cp[1] == ':') {
+		/* Argument required */
+		optchr = 1;
+		if (argv[optind][optchr + 1]) {
+			/* No space between option and argument */
+			optarg = &argv[optind++][optchr + 1];
+		} else if (++optind >= argc) {
+			/* option requires an argument */
+			return '?';
+		} else {
+			/* Argument in the next argv */
+			optarg = argv[optind++];
+		}
+	} else {
+		/* No argument */
+		if (argv[optind][++optchr] == '\0') {
+			optchr = 1;
+			optind++;
+		}
+		optarg = NULL;
+	}
+	return *cp;
+}
+#endif /* CONFIG_ANSI_C_EXTRA */
+
+
+#ifdef CONFIG_NATIVE_WINDOWS
+/**
+ * wpa_unicode2ascii_inplace - Convert unicode string into ASCII
+ * @str: Pointer to string to convert
+ *
+ * This function converts a unicode string to ASCII using the same
+ * buffer for output. If UNICODE is not set, the buffer is not
+ * modified.
+ */
+void wpa_unicode2ascii_inplace(TCHAR *str)
+{
+#ifdef UNICODE
+	char *dst = (char *) str;
+	while (*str)
+		*dst++ = (char) *str++;
+	*dst = '\0';
+#endif /* UNICODE */
+}
+
+
+TCHAR * wpa_strdup_tchar(const char *str)
+{
+#ifdef UNICODE
+	TCHAR *buf;
+	buf = os_malloc((strlen(str) + 1) * sizeof(TCHAR));
+	if (buf == NULL)
+		return NULL;
+	wsprintf(buf, L"%S", str);
+	return buf;
+#else /* UNICODE */
+	return os_strdup(str);
+#endif /* UNICODE */
 }
 #endif /* CONFIG_NATIVE_WINDOWS */
+
+
+/**
+ * wpa_ssid_txt - Convert SSID to a printable string
+ * @ssid: SSID (32-octet string)
+ * @ssid_len: Length of ssid in octets
+ * Returns: Pointer to a printable string
+ *
+ * This function can be used to convert SSIDs into printable form. In most
+ * cases, SSIDs do not use unprintable characters, but IEEE 802.11 standard
+ * does not limit the used character set, so anything could be used in an SSID.
+ *
+ * This function uses a static buffer, so only one call can be used at the
+ * time, i.e., this is not re-entrant and the returned buffer must be used
+ * before calling this again.
+ */
+const char * wpa_ssid_txt(u8 *ssid, size_t ssid_len)
+{
+	static char ssid_txt[33];
+	char *pos;
+
+	if (ssid_len > 32)
+		ssid_len = 32;
+	os_memcpy(ssid_txt, ssid, ssid_len);
+	ssid_txt[ssid_len] = '\0';
+	for (pos = ssid_txt; *pos != '\0'; pos++) {
+		if ((u8) *pos < 32 || (u8) *pos >= 127)
+			*pos = '_';
+	}
+	return ssid_txt;
+}
Index: wpa.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/wpa.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/wpa.c -L contrib/wpa_supplicant/wpa.c -u -r1.2 -r1.3
--- contrib/wpa_supplicant/wpa.c
+++ contrib/wpa_supplicant/wpa.c
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant - WPA state machine and EAPOL-Key processing
- * Copyright (c) 2003-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2003-2006, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -12,12 +12,7 @@
  * See README and COPYING for more details.
  */
 
-#include <stdlib.h>
-#include <stdio.h>
-#ifndef CONFIG_NATIVE_WINDOWS
-#include <netinet/in.h>
-#endif /* CONFIG_NATIVE_WINDOWS */
-#include <string.h>
+#include "includes.h"
 
 #include "common.h"
 #include "md5.h"
@@ -26,11 +21,11 @@
 #include "aes_wrap.h"
 #include "wpa.h"
 #include "eloop.h"
-#include "wpa_supplicant.h"
 #include "config.h"
 #include "l2_packet.h"
 #include "eapol_sm.h"
 #include "preauth.h"
+#include "pmksa_cache.h"
 #include "wpa_i.h"
 
 
@@ -43,7 +38,9 @@
 static const u8 WPA_CIPHER_SUITE_NONE[] = { 0x00, 0x50, 0xf2, 0 };
 static const u8 WPA_CIPHER_SUITE_WEP40[] = { 0x00, 0x50, 0xf2, 1 };
 static const u8 WPA_CIPHER_SUITE_TKIP[] = { 0x00, 0x50, 0xf2, 2 };
+#if 0
 static const u8 WPA_CIPHER_SUITE_WRAP[] = { 0x00, 0x50, 0xf2, 3 };
+#endif
 static const u8 WPA_CIPHER_SUITE_CCMP[] = { 0x00, 0x50, 0xf2, 4 };
 static const u8 WPA_CIPHER_SUITE_WEP104[] = { 0x00, 0x50, 0xf2, 5 };
 
@@ -61,13 +58,21 @@
  * WPA Capabilities (2 octets, little endian) (default: 0)
  */
 
+#ifdef _MSC_VER
+#pragma pack(push, 1)
+#endif /* _MSC_VER */
+
 struct wpa_ie_hdr {
 	u8 elem_id;
 	u8 len;
 	u8 oui[3];
 	u8 oui_type;
 	u8 version[2];
-} __attribute__ ((packed));
+} STRUCT_PACKED;
+
+#ifdef _MSC_VER
+#pragma pack(pop)
+#endif /* _MSC_VER */
 
 
 static const int RSN_SELECTOR_LEN = 4;
@@ -77,17 +82,53 @@
 static const u8 RSN_CIPHER_SUITE_NONE[] = { 0x00, 0x0f, 0xac, 0 };
 static const u8 RSN_CIPHER_SUITE_WEP40[] = { 0x00, 0x0f, 0xac, 1 };
 static const u8 RSN_CIPHER_SUITE_TKIP[] = { 0x00, 0x0f, 0xac, 2 };
+#if 0
 static const u8 RSN_CIPHER_SUITE_WRAP[] = { 0x00, 0x0f, 0xac, 3 };
+#endif
 static const u8 RSN_CIPHER_SUITE_CCMP[] = { 0x00, 0x0f, 0xac, 4 };
 static const u8 RSN_CIPHER_SUITE_WEP104[] = { 0x00, 0x0f, 0xac, 5 };
+#ifdef CONFIG_IEEE80211W
+static const u8 RSN_CIPHER_SUITE_AES_128_CMAC[] = { 0x00, 0x0f, 0xac, 6 };
+#endif /* CONFIG_IEEE80211W */
 
 /* EAPOL-Key Key Data Encapsulation
- * GroupKey and STAKey require encryption, otherwise, encryption is optional.
+ * GroupKey and PeerKey require encryption, otherwise, encryption is optional.
  */
 static const u8 RSN_KEY_DATA_GROUPKEY[] = { 0x00, 0x0f, 0xac, 1 };
+#if 0
 static const u8 RSN_KEY_DATA_STAKEY[] = { 0x00, 0x0f, 0xac, 2 };
+#endif
 static const u8 RSN_KEY_DATA_MAC_ADDR[] = { 0x00, 0x0f, 0xac, 3 };
 static const u8 RSN_KEY_DATA_PMKID[] = { 0x00, 0x0f, 0xac, 4 };
+#ifdef CONFIG_PEERKEY
+static const u8 RSN_KEY_DATA_SMK[] = { 0x00, 0x0f, 0xac, 5 };
+static const u8 RSN_KEY_DATA_NONCE[] = { 0x00, 0x0f, 0xac, 6 };
+static const u8 RSN_KEY_DATA_LIFETIME[] = { 0x00, 0x0f, 0xac, 7 };
+static const u8 RSN_KEY_DATA_ERROR[] = { 0x00, 0x0f, 0xac, 8 };
+#endif /* CONFIG_PEERKEY */
+#ifdef CONFIG_IEEE80211W
+/* FIX: IEEE 802.11w/D1.0 is using subtypes 5 and 6 for these, but they were
+ * already taken by 802.11ma (PeerKey). Need to update the values here once
+ * IEEE 802.11w fixes these. */
+static const u8 RSN_KEY_DATA_DHV[] = { 0x00, 0x0f, 0xac, 9 };
+static const u8 RSN_KEY_DATA_IGTK[] = { 0x00, 0x0f, 0xac, 10 };
+#endif /* CONFIG_IEEE80211W */
+
+#ifdef CONFIG_PEERKEY
+enum {
+	STK_MUI_4WAY_STA_AP = 1,
+	STK_MUI_4WAY_STAT_STA = 2,
+	STK_MUI_GTK = 3,
+	STK_MUI_SMK = 4
+};
+
+enum {
+	STK_ERR_STA_NR = 1,
+	STK_ERR_STA_NRSN = 2,
+	STK_ERR_CPHR_NS = 3,
+	STK_ERR_NO_STSL = 4
+};
+#endif /* CONFIG_PEERKEY */
 
 /* 1/4: PMKID
  * 2/4: RSN IE
@@ -110,13 +151,18 @@
  * RSN Capabilities (2 octets, little endian) (default: 0)
  * PMKID Count (2 octets) (default: 0)
  * PMKID List (16 * n octets)
+ * Management Group Cipher Suite (4 octets) (default: AES-128-CMAC)
  */
 
+#ifdef _MSC_VER
+#pragma pack(push, 1)
+#endif /* _MSC_VER */
+
 struct rsn_ie_hdr {
 	u8 elem_id; /* WLAN_EID_RSN */
 	u8 len;
 	u8 version[2];
-} __attribute__ ((packed));
+} STRUCT_PACKED;
 
 
 struct wpa_eapol_key {
@@ -132,9 +178,31 @@
 	u8 key_mic[16];
 	u8 key_data_length[2];
 	/* followed by key_data_length bytes of key_data */
-} __attribute__ ((packed));
+} STRUCT_PACKED;
+
+
+struct rsn_error_kde {
+	u16 mui;
+	u16 error_type;
+} STRUCT_PACKED;
+
+#ifdef CONFIG_IEEE80211W
+struct wpa_dhv_kde {
+	u8 dhv[WPA_DHV_LEN];
+} STRUCT_PACKED;
+
+struct wpa_igtk_kde {
+	u8 keyid[2];
+	u8 pn[6];
+	u8 igtk[WPA_IGTK_LEN];
+} STRUCT_PACKED;
+#endif /* CONFIG_IEEE80211W */
+
+#ifdef _MSC_VER
+#pragma pack(pop)
+#endif /* _MSC_VER */
 
-#define WPA_KEY_INFO_TYPE_MASK (BIT(0) | BIT(1) | BIT(2))
+#define WPA_KEY_INFO_TYPE_MASK ((u16) (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 */
@@ -149,8 +217,14 @@
 #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_KEY_INFO_SMK_MESSAGE BIT(13)
 
 
+#ifdef CONFIG_PEERKEY
+static void wpa_supplicant_peerkey_free(struct wpa_sm *sm,
+					struct wpa_peerkey *peerkey);
+#endif /* CONFIG_PEERKEY */
+
 
 /**
  * wpa_cipher_txt - Convert cipher suite to a text string
@@ -203,15 +277,15 @@
 
 static int wpa_selector_to_bitfield(const u8 *s)
 {
-	if (memcmp(s, WPA_CIPHER_SUITE_NONE, WPA_SELECTOR_LEN) == 0)
+	if (os_memcmp(s, WPA_CIPHER_SUITE_NONE, WPA_SELECTOR_LEN) == 0)
 		return WPA_CIPHER_NONE;
-	if (memcmp(s, WPA_CIPHER_SUITE_WEP40, WPA_SELECTOR_LEN) == 0)
+	if (os_memcmp(s, WPA_CIPHER_SUITE_WEP40, WPA_SELECTOR_LEN) == 0)
 		return WPA_CIPHER_WEP40;
-	if (memcmp(s, WPA_CIPHER_SUITE_TKIP, WPA_SELECTOR_LEN) == 0)
+	if (os_memcmp(s, WPA_CIPHER_SUITE_TKIP, WPA_SELECTOR_LEN) == 0)
 		return WPA_CIPHER_TKIP;
-	if (memcmp(s, WPA_CIPHER_SUITE_CCMP, WPA_SELECTOR_LEN) == 0)
+	if (os_memcmp(s, WPA_CIPHER_SUITE_CCMP, WPA_SELECTOR_LEN) == 0)
 		return WPA_CIPHER_CCMP;
-	if (memcmp(s, WPA_CIPHER_SUITE_WEP104, WPA_SELECTOR_LEN) == 0)
+	if (os_memcmp(s, WPA_CIPHER_SUITE_WEP104, WPA_SELECTOR_LEN) == 0)
 		return WPA_CIPHER_WEP104;
 	return 0;
 }
@@ -219,42 +293,72 @@
 
 static int wpa_key_mgmt_to_bitfield(const u8 *s)
 {
-	if (memcmp(s, WPA_AUTH_KEY_MGMT_UNSPEC_802_1X, WPA_SELECTOR_LEN) == 0)
-		return WPA_KEY_MGMT_IEEE8021X;
-	if (memcmp(s, WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X, WPA_SELECTOR_LEN) ==
+	if (os_memcmp(s, WPA_AUTH_KEY_MGMT_UNSPEC_802_1X, WPA_SELECTOR_LEN) ==
 	    0)
+		return WPA_KEY_MGMT_IEEE8021X;
+	if (os_memcmp(s, WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X, WPA_SELECTOR_LEN)
+	    == 0)
 		return WPA_KEY_MGMT_PSK;
-	if (memcmp(s, WPA_AUTH_KEY_MGMT_NONE, WPA_SELECTOR_LEN) == 0)
+	if (os_memcmp(s, WPA_AUTH_KEY_MGMT_NONE, WPA_SELECTOR_LEN) == 0)
 		return WPA_KEY_MGMT_WPA_NONE;
 	return 0;
 }
 
 
+#ifndef CONFIG_NO_WPA2
 static int rsn_selector_to_bitfield(const u8 *s)
 {
-	if (memcmp(s, RSN_CIPHER_SUITE_NONE, RSN_SELECTOR_LEN) == 0)
+	if (os_memcmp(s, RSN_CIPHER_SUITE_NONE, RSN_SELECTOR_LEN) == 0)
 		return WPA_CIPHER_NONE;
-	if (memcmp(s, RSN_CIPHER_SUITE_WEP40, RSN_SELECTOR_LEN) == 0)
+	if (os_memcmp(s, RSN_CIPHER_SUITE_WEP40, RSN_SELECTOR_LEN) == 0)
 		return WPA_CIPHER_WEP40;
-	if (memcmp(s, RSN_CIPHER_SUITE_TKIP, RSN_SELECTOR_LEN) == 0)
+	if (os_memcmp(s, RSN_CIPHER_SUITE_TKIP, RSN_SELECTOR_LEN) == 0)
 		return WPA_CIPHER_TKIP;
-	if (memcmp(s, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN) == 0)
+	if (os_memcmp(s, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN) == 0)
 		return WPA_CIPHER_CCMP;
-	if (memcmp(s, RSN_CIPHER_SUITE_WEP104, RSN_SELECTOR_LEN) == 0)
+	if (os_memcmp(s, RSN_CIPHER_SUITE_WEP104, RSN_SELECTOR_LEN) == 0)
 		return WPA_CIPHER_WEP104;
+#ifdef CONFIG_IEEE80211W
+	if (os_memcmp(s, RSN_CIPHER_SUITE_AES_128_CMAC, RSN_SELECTOR_LEN) == 0)
+		return WPA_CIPHER_AES_128_CMAC;
+#endif /* CONFIG_IEEE80211W */
 	return 0;
 }
 
 
 static int rsn_key_mgmt_to_bitfield(const u8 *s)
 {
-	if (memcmp(s, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X, RSN_SELECTOR_LEN) == 0)
-		return WPA_KEY_MGMT_IEEE8021X;
-	if (memcmp(s, RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X, RSN_SELECTOR_LEN) ==
+	if (os_memcmp(s, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X, RSN_SELECTOR_LEN) ==
 	    0)
+		return WPA_KEY_MGMT_IEEE8021X;
+	if (os_memcmp(s, RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X, RSN_SELECTOR_LEN)
+	    == 0)
 		return WPA_KEY_MGMT_PSK;
 	return 0;
 }
+#endif /* CONFIG_NO_WPA2 */
+
+
+#ifdef CONFIG_PEERKEY
+static u8 * wpa_add_ie(u8 *pos, const u8 *ie, size_t ie_len)
+{
+	os_memcpy(pos, ie, ie_len);
+	return pos + ie_len;
+}
+
+
+static u8 * wpa_add_kde(u8 *pos, const u8 *kde, const u8 *data,
+			size_t data_len)
+{
+	*pos++ = GENERIC_INFO_ELEM;
+	*pos++ = RSN_SELECTOR_LEN + data_len;
+	os_memcpy(pos, kde, RSN_SELECTOR_LEN);
+	pos += RSN_SELECTOR_LEN;
+	os_memcpy(pos, data, data_len);
+	pos += data_len;
+	return pos;
+}
+#endif /* CONFIG_PEERKEY */
 
 
 static int wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len,
@@ -272,6 +376,7 @@
 	data->capabilities = 0;
 	data->pmkid = NULL;
 	data->num_pmkid = 0;
+	data->mgmt_group_cipher = 0;
 
 	if (wpa_ie_len == 0) {
 		/* No WPA IE - fail silently */
@@ -288,7 +393,7 @@
 
 	if (hdr->elem_id != GENERIC_INFO_ELEM ||
 	    hdr->len != wpa_ie_len - 2 ||
-	    memcmp(&hdr->oui, WPA_OUI_TYPE, WPA_SELECTOR_LEN) != 0 ||
+	    os_memcmp(hdr->oui, WPA_OUI_TYPE, WPA_SELECTOR_LEN) != 0 ||
 	    WPA_GET_LE16(hdr->version) != WPA_VERSION) {
 		wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version",
 			   __func__);
@@ -357,9 +462,8 @@
 	}
 
 	if (left > 0) {
-		wpa_printf(MSG_DEBUG, "%s: ie has %u trailing bytes",
+		wpa_printf(MSG_DEBUG, "%s: ie has %u trailing bytes - ignored",
 			   __func__, left);
-		return -1;
 	}
 
 	return 0;
@@ -369,6 +473,7 @@
 static int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
 				struct wpa_ie_data *data)
 {
+#ifndef CONFIG_NO_WPA2
 	const struct rsn_ie_hdr *hdr;
 	const u8 *pos;
 	int left;
@@ -381,6 +486,12 @@
 	data->capabilities = 0;
 	data->pmkid = NULL;
 	data->num_pmkid = 0;
+#ifdef CONFIG_IEEE80211W
+	data->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
+#else /* CONFIG_IEEE80211W */
+	data->mgmt_group_cipher = 0;
+#endif /* CONFIG_IEEE80211W */
+
 
 	if (rsn_ie_len == 0) {
 		/* No RSN IE - fail silently */
@@ -408,6 +519,13 @@
 
 	if (left >= RSN_SELECTOR_LEN) {
 		data->group_cipher = rsn_selector_to_bitfield(pos);
+#ifdef CONFIG_IEEE80211W
+		if (data->group_cipher == WPA_CIPHER_AES_128_CMAC) {
+			wpa_printf(MSG_DEBUG, "%s: AES-128-CMAC used as group "
+				   "cipher", __func__);
+			return -1;
+		}
+#endif /* CONFIG_IEEE80211W */
 		pos += RSN_SELECTOR_LEN;
 		left -= RSN_SELECTOR_LEN;
 	} else if (left > 0) {
@@ -431,6 +549,13 @@
 			pos += RSN_SELECTOR_LEN;
 			left -= RSN_SELECTOR_LEN;
 		}
+#ifdef CONFIG_IEEE80211W
+		if (data->pairwise_cipher & WPA_CIPHER_AES_128_CMAC) {
+			wpa_printf(MSG_DEBUG, "%s: AES-128-CMAC used as "
+				   "pairwise cipher", __func__);
+			return -1;
+		}
+#endif /* CONFIG_IEEE80211W */
 	} else if (left == 1) {
 		wpa_printf(MSG_DEBUG, "%s: ie too short (for key mgmt)",
 			   __func__);
@@ -480,12 +605,29 @@
 		}
 	}
 
+#ifdef CONFIG_IEEE80211W
+	if (left >= 4) {
+		data->mgmt_group_cipher = rsn_selector_to_bitfield(pos);
+		if (data->mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC) {
+			wpa_printf(MSG_DEBUG, "%s: Unsupported management "
+				   "group cipher 0x%x", __func__,
+				   data->mgmt_group_cipher);
+			return -1;
+		}
+		pos += RSN_SELECTOR_LEN;
+		left -= RSN_SELECTOR_LEN;
+	}
+#endif /* CONFIG_IEEE80211W */
+
 	if (left > 0) {
 		wpa_printf(MSG_DEBUG, "%s: ie has %u trailing bytes - ignored",
 			   __func__, left);
 	}
 
 	return 0;
+#else /* CONFIG_NO_WPA2 */
+	return -1;
+#endif /* CONFIG_NO_WPA2 */
 }
 
 
@@ -521,18 +663,18 @@
 
 	hdr = (struct wpa_ie_hdr *) wpa_ie;
 	hdr->elem_id = GENERIC_INFO_ELEM;
-	memcpy(&hdr->oui, WPA_OUI_TYPE, WPA_SELECTOR_LEN);
+	os_memcpy(hdr->oui, WPA_OUI_TYPE, WPA_SELECTOR_LEN);
 	WPA_PUT_LE16(hdr->version, WPA_VERSION);
 	pos = (u8 *) (hdr + 1);
 
 	if (group_cipher == WPA_CIPHER_CCMP) {
-		memcpy(pos, WPA_CIPHER_SUITE_CCMP, WPA_SELECTOR_LEN);
+		os_memcpy(pos, WPA_CIPHER_SUITE_CCMP, WPA_SELECTOR_LEN);
 	} else if (group_cipher == WPA_CIPHER_TKIP) {
-		memcpy(pos, WPA_CIPHER_SUITE_TKIP, WPA_SELECTOR_LEN);
+		os_memcpy(pos, WPA_CIPHER_SUITE_TKIP, WPA_SELECTOR_LEN);
 	} else if (group_cipher == WPA_CIPHER_WEP104) {
-		memcpy(pos, WPA_CIPHER_SUITE_WEP104, WPA_SELECTOR_LEN);
+		os_memcpy(pos, WPA_CIPHER_SUITE_WEP104, WPA_SELECTOR_LEN);
 	} else if (group_cipher == WPA_CIPHER_WEP40) {
-		memcpy(pos, WPA_CIPHER_SUITE_WEP40, WPA_SELECTOR_LEN);
+		os_memcpy(pos, WPA_CIPHER_SUITE_WEP40, WPA_SELECTOR_LEN);
 	} else {
 		wpa_printf(MSG_WARNING, "Invalid group cipher (%d).",
 			   group_cipher);
@@ -543,11 +685,11 @@
 	*pos++ = 1;
 	*pos++ = 0;
 	if (pairwise_cipher == WPA_CIPHER_CCMP) {
-		memcpy(pos, WPA_CIPHER_SUITE_CCMP, WPA_SELECTOR_LEN);
+		os_memcpy(pos, WPA_CIPHER_SUITE_CCMP, WPA_SELECTOR_LEN);
 	} else if (pairwise_cipher == WPA_CIPHER_TKIP) {
-		memcpy(pos, WPA_CIPHER_SUITE_TKIP, WPA_SELECTOR_LEN);
+		os_memcpy(pos, WPA_CIPHER_SUITE_TKIP, WPA_SELECTOR_LEN);
 	} else if (pairwise_cipher == WPA_CIPHER_NONE) {
-		memcpy(pos, WPA_CIPHER_SUITE_NONE, WPA_SELECTOR_LEN);
+		os_memcpy(pos, WPA_CIPHER_SUITE_NONE, WPA_SELECTOR_LEN);
 	} else {
 		wpa_printf(MSG_WARNING, "Invalid pairwise cipher (%d).",
 			   pairwise_cipher);
@@ -558,12 +700,13 @@
 	*pos++ = 1;
 	*pos++ = 0;
 	if (key_mgmt == WPA_KEY_MGMT_IEEE8021X) {
-		memcpy(pos, WPA_AUTH_KEY_MGMT_UNSPEC_802_1X, WPA_SELECTOR_LEN);
+		os_memcpy(pos, WPA_AUTH_KEY_MGMT_UNSPEC_802_1X,
+			  WPA_SELECTOR_LEN);
 	} else if (key_mgmt == WPA_KEY_MGMT_PSK) {
-		memcpy(pos, WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X,
-		       WPA_SELECTOR_LEN);
+		os_memcpy(pos, WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X,
+			  WPA_SELECTOR_LEN);
 	} else if (key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
-		memcpy(pos, WPA_AUTH_KEY_MGMT_NONE, WPA_SELECTOR_LEN);
+		os_memcpy(pos, WPA_AUTH_KEY_MGMT_NONE, WPA_SELECTOR_LEN);
 	} else {
 		wpa_printf(MSG_WARNING, "Invalid key management type (%d).",
 			   key_mgmt);
@@ -575,7 +718,7 @@
 
 	hdr->len = (pos - wpa_ie) - 2;
 
-	WPA_ASSERT(pos - wpa_ie <= wpa_ie_len);
+	WPA_ASSERT((size_t) (pos - wpa_ie) <= wpa_ie_len);
 
 	return pos - wpa_ie;
 }
@@ -583,10 +726,13 @@
 
 static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len,
 			      int pairwise_cipher, int group_cipher,
-			      int key_mgmt, struct wpa_sm *sm)
+			      int key_mgmt, int mgmt_group_cipher,
+			      struct wpa_sm *sm)
 {
+#ifndef CONFIG_NO_WPA2
 	u8 *pos;
 	struct rsn_ie_hdr *hdr;
+	u16 capab;
 
 	if (rsn_ie_len < sizeof(*hdr) + RSN_SELECTOR_LEN +
 	    2 + RSN_SELECTOR_LEN + 2 + RSN_SELECTOR_LEN + 2 +
@@ -599,13 +745,13 @@
 	pos = (u8 *) (hdr + 1);
 
 	if (group_cipher == WPA_CIPHER_CCMP) {
-		memcpy(pos, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN);
+		os_memcpy(pos, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN);
 	} else if (group_cipher == WPA_CIPHER_TKIP) {
-		memcpy(pos, RSN_CIPHER_SUITE_TKIP, RSN_SELECTOR_LEN);
+		os_memcpy(pos, RSN_CIPHER_SUITE_TKIP, RSN_SELECTOR_LEN);
 	} else if (group_cipher == WPA_CIPHER_WEP104) {
-		memcpy(pos, RSN_CIPHER_SUITE_WEP104, RSN_SELECTOR_LEN);
+		os_memcpy(pos, RSN_CIPHER_SUITE_WEP104, RSN_SELECTOR_LEN);
 	} else if (group_cipher == WPA_CIPHER_WEP40) {
-		memcpy(pos, RSN_CIPHER_SUITE_WEP40, RSN_SELECTOR_LEN);
+		os_memcpy(pos, RSN_CIPHER_SUITE_WEP40, RSN_SELECTOR_LEN);
 	} else {
 		wpa_printf(MSG_WARNING, "Invalid group cipher (%d).",
 			   group_cipher);
@@ -616,11 +762,11 @@
 	*pos++ = 1;
 	*pos++ = 0;
 	if (pairwise_cipher == WPA_CIPHER_CCMP) {
-		memcpy(pos, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN);
+		os_memcpy(pos, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN);
 	} else if (pairwise_cipher == WPA_CIPHER_TKIP) {
-		memcpy(pos, RSN_CIPHER_SUITE_TKIP, RSN_SELECTOR_LEN);
+		os_memcpy(pos, RSN_CIPHER_SUITE_TKIP, RSN_SELECTOR_LEN);
 	} else if (pairwise_cipher == WPA_CIPHER_NONE) {
-		memcpy(pos, RSN_CIPHER_SUITE_NONE, RSN_SELECTOR_LEN);
+		os_memcpy(pos, RSN_CIPHER_SUITE_NONE, RSN_SELECTOR_LEN);
 	} else {
 		wpa_printf(MSG_WARNING, "Invalid pairwise cipher (%d).",
 			   pairwise_cipher);
@@ -631,10 +777,11 @@
 	*pos++ = 1;
 	*pos++ = 0;
 	if (key_mgmt == WPA_KEY_MGMT_IEEE8021X) {
-		memcpy(pos, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X, RSN_SELECTOR_LEN);
+		os_memcpy(pos, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X,
+			  RSN_SELECTOR_LEN);
 	} else if (key_mgmt == WPA_KEY_MGMT_PSK) {
-		memcpy(pos, RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X,
-		       RSN_SELECTOR_LEN);
+		os_memcpy(pos, RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X,
+			  RSN_SELECTOR_LEN);
 	} else {
 		wpa_printf(MSG_WARNING, "Invalid key management type (%d).",
 			   key_mgmt);
@@ -643,23 +790,46 @@
 	pos += RSN_SELECTOR_LEN;
 
 	/* RSN Capabilities */
-	*pos++ = 0;
-	*pos++ = 0;
+	capab = 0;
+#ifdef CONFIG_IEEE80211W
+	if (mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC)
+		capab |= WPA_CAPABILITY_MGMT_FRAME_PROTECTION;
+#endif /* CONFIG_IEEE80211W */
+	WPA_PUT_LE16(pos, capab);
+	pos += 2;
 
 	if (sm->cur_pmksa) {
 		/* PMKID Count (2 octets, little endian) */
 		*pos++ = 1;
 		*pos++ = 0;
 		/* PMKID */
-		memcpy(pos, sm->cur_pmksa->pmkid, PMKID_LEN);
+		os_memcpy(pos, sm->cur_pmksa->pmkid, PMKID_LEN);
 		pos += PMKID_LEN;
 	}
 
+#ifdef CONFIG_IEEE80211W
+	if (mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC) {
+		if (!sm->cur_pmksa) {
+			/* PMKID Count */
+			WPA_PUT_LE16(pos, 0);
+			pos += 2;
+
+			/* Management Group Cipher Suite */
+			memcpy(pos, RSN_CIPHER_SUITE_AES_128_CMAC,
+			       RSN_SELECTOR_LEN);
+			pos += RSN_SELECTOR_LEN;
+		}
+	}
+#endif /* CONFIG_IEEE80211W */
+
 	hdr->len = (pos - rsn_ie) - 2;
 
-	WPA_ASSERT(pos - rsn_ie <= rsn_ie_len);
+	WPA_ASSERT((size_t) (pos - rsn_ie) <= rsn_ie_len);
 
 	return pos - rsn_ie;
+#else /* CONFIG_NO_WPA2 */
+	return -1;
+#endif /* CONFIG_NO_WPA2 */
 }
 
 
@@ -676,7 +846,8 @@
 		return wpa_gen_wpa_ie_rsn(wpa_ie, wpa_ie_len,
 					  sm->pairwise_cipher,
 					  sm->group_cipher,
-					  sm->key_mgmt, sm);
+					  sm->key_mgmt, sm->mgmt_group_cipher,
+					  sm);
 	else
 		return wpa_gen_wpa_ie_wpa(wpa_ie, wpa_ie_len,
 					  sm->pairwise_cipher,
@@ -688,6 +859,8 @@
 /**
  * wpa_pmk_to_ptk - Calculate PTK from PMK, addresses, and nonces
  * @pmk: Pairwise master key
+ * @pmk_len: Length of PMK
+ * @label: Label to use in derivation
  * @addr1: AA or SA
  * @addr2: SA or AA
  * @nonce1: ANonce or SNonce
@@ -699,32 +872,36 @@
  * PTK = PRF-X(PMK, "Pairwise key expansion",
  *             Min(AA, SA) || Max(AA, SA) ||
  *             Min(ANonce, SNonce) || Max(ANonce, SNonce))
+ *
+ * STK = PRF-X(SMK, "Peer key expansion",
+ *             Min(MAC_I, MAC_P) || Max(MAC_I, MAC_P) ||
+ *             Min(INonce, PNonce) || Max(INonce, PNonce))
  */
 static void wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len,
+			   const char *label,
 			   const u8 *addr1, const u8 *addr2,
 			   const u8 *nonce1, const u8 *nonce2,
 			   u8 *ptk, size_t ptk_len)
 {
 	u8 data[2 * ETH_ALEN + 2 * 32];
 
-	if (memcmp(addr1, addr2, ETH_ALEN) < 0) {
-		memcpy(data, addr1, ETH_ALEN);
-		memcpy(data + ETH_ALEN, addr2, ETH_ALEN);
+	if (os_memcmp(addr1, addr2, ETH_ALEN) < 0) {
+		os_memcpy(data, addr1, ETH_ALEN);
+		os_memcpy(data + ETH_ALEN, addr2, ETH_ALEN);
 	} else {
-		memcpy(data, addr2, ETH_ALEN);
-		memcpy(data + ETH_ALEN, addr1, ETH_ALEN);
+		os_memcpy(data, addr2, ETH_ALEN);
+		os_memcpy(data + ETH_ALEN, addr1, ETH_ALEN);
 	}
 
-	if (memcmp(nonce1, nonce2, 32) < 0) {
-		memcpy(data + 2 * ETH_ALEN, nonce1, 32);
-		memcpy(data + 2 * ETH_ALEN + 32, nonce2, 32);
+	if (os_memcmp(nonce1, nonce2, 32) < 0) {
+		os_memcpy(data + 2 * ETH_ALEN, nonce1, 32);
+		os_memcpy(data + 2 * ETH_ALEN + 32, nonce2, 32);
 	} else {
-		memcpy(data + 2 * ETH_ALEN, nonce2, 32);
-		memcpy(data + 2 * ETH_ALEN + 32, nonce1, 32);
+		os_memcpy(data + 2 * ETH_ALEN, nonce2, 32);
+		os_memcpy(data + 2 * ETH_ALEN + 32, nonce1, 32);
 	}
 
-	sha1_prf(pmk, pmk_len, "Pairwise key expansion", data, sizeof(data),
-		 ptk, ptk_len);
+	sha1_prf(pmk, pmk_len, label, data, sizeof(data), ptk, ptk_len);
 
 	wpa_hexdump_key(MSG_DEBUG, "WPA: PMK", pmk, pmk_len);
 	wpa_hexdump_key(MSG_DEBUG, "WPA: PTK", ptk, ptk_len);
@@ -756,7 +933,7 @@
 	} else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
 		u8 hash[SHA1_MAC_LEN];
 		hmac_sha1(key, 16, buf, len, hash);
-		memcpy(mic, hash, MD5_MAC_LEN);
+		os_memcpy(mic, hash, MD5_MAC_LEN);
 	}
 }
 
@@ -765,13 +942,29 @@
 			       int ver, const u8 *dest, u16 proto,
 			       u8 *msg, size_t msg_len, u8 *key_mic)
 {
+	if (os_memcmp(dest, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) == 0 &&
+	    os_memcmp(sm->bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) == 0) {
+		/*
+		 * Association event was not yet received; try to fetch
+		 * BSSID from the driver.
+		 */
+		if (wpa_sm_get_bssid(sm, sm->bssid) < 0) {
+			wpa_printf(MSG_DEBUG, "WPA: Failed to read BSSID for "
+				   "EAPOL-Key destination address");
+		} else {
+			dest = sm->bssid;
+			wpa_printf(MSG_DEBUG, "WPA: Use BSSID (" MACSTR
+				   ") as the destination for EAPOL-Key",
+				   MAC2STR(dest));
+		}
+	}
 	if (key_mic) {
 		wpa_eapol_key_mic(kck, ver, msg, msg_len, key_mic);
 	}
 	wpa_hexdump(MSG_MSGDUMP, "WPA: TX EAPOL-Key", msg, msg_len);
 	wpa_sm_ether_send(sm, dest, proto, msg, msg_len);
 	eapol_sm_notify_tx_eapol_key(sm->eapol);
-	free(msg);
+	os_free(msg);
 }
 
 
@@ -820,8 +1013,8 @@
 		key_info |= WPA_KEY_INFO_KEY_TYPE;
 	WPA_PUT_BE16(reply->key_info, key_info);
 	WPA_PUT_BE16(reply->key_length, 0);
-	memcpy(reply->replay_counter, sm->request_counter,
-	       WPA_REPLAY_COUNTER_LEN);
+	os_memcpy(reply->replay_counter, sm->request_counter,
+		  WPA_REPLAY_COUNTER_LEN);
 	inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN);
 
 	WPA_PUT_BE16(reply->key_data_length, 0);
@@ -835,6 +1028,149 @@
 }
 
 
+/**
+ * wpa_sm_stkstart - Send EAPOL-Key Request for STK handshake (STK M1)
+ * @sm: Pointer to WPA state machine data from wpa_sm_init()
+ * @peer: MAC address of the peer STA
+ * Returns: 0 on success, or -1 on failure
+ *
+ * Send an EAPOL-Key Request to the current authenticator to start STK
+ * handshake with the peer.
+ */
+int wpa_sm_stkstart(struct wpa_sm *sm, const u8 *peer)
+{
+#ifdef CONFIG_PEERKEY
+	size_t rlen, kde_len;
+	struct wpa_eapol_key *req;
+	int key_info, ver;
+	u8 bssid[ETH_ALEN], *rbuf, *pos, *count_pos;
+	u16 count;
+	struct wpa_ssid *ssid = sm->cur_ssid;
+	struct rsn_ie_hdr *hdr;
+	struct wpa_peerkey *peerkey;
+	struct wpa_ie_data ie;
+
+	if (sm->proto != WPA_PROTO_RSN || !sm->ptk_set ||
+	    ssid == NULL || !ssid->peerkey)
+		return -1;
+
+	if (sm->ap_rsn_ie &&
+	    wpa_parse_wpa_ie_rsn(sm->ap_rsn_ie, sm->ap_rsn_ie_len, &ie) == 0 &&
+	    !(ie.capabilities & WPA_CAPABILITY_PEERKEY_ENABLED)) {
+		wpa_printf(MSG_DEBUG, "RSN: Current AP does not support STK");
+		return -1;
+	}
+
+	if (sm->pairwise_cipher == WPA_CIPHER_CCMP)
+		ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES;
+	else
+		ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4;
+
+	if (wpa_sm_get_bssid(sm, bssid) < 0) {
+		wpa_printf(MSG_WARNING, "Failed to read BSSID for EAPOL-Key "
+			   "SMK M1");
+		return -1;
+	}
+
+	/* TODO: find existing entry and if found, use that instead of adding
+	 * a new one */
+	peerkey = os_malloc(sizeof(*peerkey));
+	if (peerkey == NULL)
+		return -1;
+	os_memset(peerkey, 0, sizeof(*peerkey));
+	peerkey->initiator = 1;
+	os_memcpy(peerkey->addr, peer, ETH_ALEN);
+
+	/* SMK M1:
+	 * EAPOL-Key(S=1, M=1, A=0, I=0, K=0, SM=1, KeyRSC=0, Nonce=INonce,
+	 *           MIC=MIC, DataKDs=(RSNIE_I, MAC_P KDE))
+	 */
+
+	hdr = (struct rsn_ie_hdr *) peerkey->rsnie_i;
+	hdr->elem_id = RSN_INFO_ELEM;
+	WPA_PUT_LE16(hdr->version, RSN_VERSION);
+	pos = (u8 *) (hdr + 1);
+	/* Group Suite can be anything for SMK RSN IE; receiver will just
+	 * ignore it. */
+	os_memcpy(pos, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN);
+	pos += RSN_SELECTOR_LEN;
+	count_pos = pos;
+	pos += 2;
+
+	count = 0;
+	if (ssid->pairwise_cipher & WPA_CIPHER_CCMP) {
+		os_memcpy(pos, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN);
+		pos += RSN_SELECTOR_LEN;
+		count++;
+	}
+	if (ssid->pairwise_cipher & WPA_CIPHER_TKIP) {
+		os_memcpy(pos, RSN_CIPHER_SUITE_TKIP, RSN_SELECTOR_LEN);
+		pos += RSN_SELECTOR_LEN;
+		count++;
+	}
+	WPA_PUT_LE16(count_pos, count);
+
+	hdr->len = (pos - peerkey->rsnie_i) - 2;
+	peerkey->rsnie_i_len = pos - peerkey->rsnie_i;
+	wpa_hexdump(MSG_DEBUG, "WPA: RSN IE for SMK handshake",
+		    peerkey->rsnie_i, peerkey->rsnie_i_len);
+
+	kde_len = peerkey->rsnie_i_len + 2 + RSN_SELECTOR_LEN + ETH_ALEN;
+
+	rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,
+				  sizeof(*req) + kde_len, &rlen,
+				  (void *) &req);
+	if (rbuf == NULL) {
+		wpa_supplicant_peerkey_free(sm, peerkey);
+		return -1;
+	}
+
+	req->type = EAPOL_KEY_TYPE_RSN;
+	key_info = WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_MIC |
+		WPA_KEY_INFO_SECURE | WPA_KEY_INFO_REQUEST | ver;
+	WPA_PUT_BE16(req->key_info, key_info);
+	WPA_PUT_BE16(req->key_length, 0);
+	os_memcpy(req->replay_counter, sm->request_counter,
+		  WPA_REPLAY_COUNTER_LEN);
+	inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN);
+
+	if (hostapd_get_rand(peerkey->inonce, WPA_NONCE_LEN)) {
+		wpa_msg(sm->ctx->ctx, MSG_WARNING,
+			"WPA: Failed to get random data for INonce");
+		os_free(rbuf);
+		wpa_supplicant_peerkey_free(sm, peerkey);
+		return -1;
+	}
+	os_memcpy(req->key_nonce, peerkey->inonce, WPA_NONCE_LEN);
+	wpa_hexdump(MSG_DEBUG, "WPA: INonce for SMK handshake",
+		    req->key_nonce, WPA_NONCE_LEN);
+
+	WPA_PUT_BE16(req->key_data_length, (u16) kde_len);
+	pos = (u8 *) (req + 1);
+
+	/* Initiator RSN IE */
+	pos = wpa_add_ie(pos, peerkey->rsnie_i, peerkey->rsnie_i_len);
+	/* Peer MAC address KDE */
+	pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN);
+
+	wpa_printf(MSG_INFO, "RSN: Sending EAPOL-Key SMK M1 Request (peer "
+		   MACSTR ")", MAC2STR(peer));
+	wpa_eapol_key_send(sm, sm->ptk.kck, ver, bssid, ETH_P_EAPOL,
+			   rbuf, rlen, req->key_mic);
+
+	peerkey->next = sm->peerkey;
+	sm->peerkey = peerkey;
+
+	return 0;
+
+#else /* CONFIG_PEERKEY */
+
+	return -1;
+
+#endif /* CONFIG_PEERKEY */
+}
+
+
 struct wpa_eapol_ie_parse {
 	const u8 *wpa_ie;
 	size_t wpa_ie_len;
@@ -843,6 +1179,24 @@
 	const u8 *pmkid;
 	const u8 *gtk;
 	size_t gtk_len;
+	const u8 *mac_addr;
+	size_t mac_addr_len;
+#ifdef CONFIG_PEERKEY
+	const u8 *smk;
+	size_t smk_len;
+	const u8 *nonce;
+	size_t nonce_len;
+	const u8 *lifetime;
+	size_t lifetime_len;
+	const u8 *error;
+	size_t error_len;
+#endif /* CONFIG_PEERKEY */
+#ifdef CONFIG_IEEE80211W
+	const u8 *dhv;
+	size_t dhv_len;
+	const u8 *igtk;
+	size_t igtk_len;
+#endif /* CONFIG_IEEE80211W */
 };
 
 
@@ -860,7 +1214,7 @@
 		return 1;
 
 	if (pos[1] >= 6 &&
-	    memcmp(pos + 2, WPA_OUI_TYPE, WPA_SELECTOR_LEN) == 0 &&
+	    os_memcmp(pos + 2, WPA_OUI_TYPE, WPA_SELECTOR_LEN) == 0 &&
 	    pos[2 + WPA_SELECTOR_LEN] == 1 &&
 	    pos[2 + WPA_SELECTOR_LEN + 1] == 0) {
 		ie->wpa_ie = pos;
@@ -870,16 +1224,70 @@
 
 	if (pos + 1 + RSN_SELECTOR_LEN < end &&
 	    pos[1] >= RSN_SELECTOR_LEN + PMKID_LEN &&
-	    memcmp(pos + 2, RSN_KEY_DATA_PMKID, RSN_SELECTOR_LEN) == 0) {
+	    os_memcmp(pos + 2, RSN_KEY_DATA_PMKID, RSN_SELECTOR_LEN) == 0) {
 		ie->pmkid = pos + 2 + RSN_SELECTOR_LEN;
 		return 0;
 	}
 
 	if (pos[1] > RSN_SELECTOR_LEN + 2 &&
-	    memcmp(pos + 2, RSN_KEY_DATA_GROUPKEY, RSN_SELECTOR_LEN) == 0) {
+	    os_memcmp(pos + 2, RSN_KEY_DATA_GROUPKEY, RSN_SELECTOR_LEN) == 0) {
 		ie->gtk = pos + 2 + RSN_SELECTOR_LEN;
 		ie->gtk_len = pos[1] - RSN_SELECTOR_LEN;
+		return 0;
+	}
+
+	if (pos[1] > RSN_SELECTOR_LEN + 2 &&
+	    os_memcmp(pos + 2, RSN_KEY_DATA_MAC_ADDR, RSN_SELECTOR_LEN) == 0) {
+		ie->mac_addr = pos + 2 + RSN_SELECTOR_LEN;
+		ie->mac_addr_len = pos[1] - RSN_SELECTOR_LEN;
+		return 0;
+	}
+
+#ifdef CONFIG_PEERKEY
+	if (pos[1] > RSN_SELECTOR_LEN + 2 &&
+	    os_memcmp(pos + 2, RSN_KEY_DATA_SMK, RSN_SELECTOR_LEN) == 0) {
+		ie->smk = pos + 2 + RSN_SELECTOR_LEN;
+		ie->smk_len = pos[1] - RSN_SELECTOR_LEN;
+		return 0;
+	}
+
+	if (pos[1] > RSN_SELECTOR_LEN + 2 &&
+	    os_memcmp(pos + 2, RSN_KEY_DATA_NONCE, RSN_SELECTOR_LEN) == 0) {
+		ie->nonce = pos + 2 + RSN_SELECTOR_LEN;
+		ie->nonce_len = pos[1] - RSN_SELECTOR_LEN;
+		return 0;
+	}
+
+	if (pos[1] > RSN_SELECTOR_LEN + 2 &&
+	    os_memcmp(pos + 2, RSN_KEY_DATA_LIFETIME, RSN_SELECTOR_LEN) == 0) {
+		ie->lifetime = pos + 2 + RSN_SELECTOR_LEN;
+		ie->lifetime_len = pos[1] - RSN_SELECTOR_LEN;
+		return 0;
+	}
+
+	if (pos[1] > RSN_SELECTOR_LEN + 2 &&
+	    os_memcmp(pos + 2, RSN_KEY_DATA_ERROR, RSN_SELECTOR_LEN) == 0) {
+		ie->error = pos + 2 + RSN_SELECTOR_LEN;
+		ie->error_len = pos[1] - RSN_SELECTOR_LEN;
+		return 0;
+	}
+#endif /* CONFIG_PEERKEY */
+
+#ifdef CONFIG_IEEE80211W
+	if (pos[1] > RSN_SELECTOR_LEN + 2 &&
+	    os_memcmp(pos + 2, RSN_KEY_DATA_DHV, RSN_SELECTOR_LEN) == 0) {
+		ie->dhv = pos + 2 + RSN_SELECTOR_LEN;
+		ie->dhv_len = pos[1] - RSN_SELECTOR_LEN;
+		return 0;
+	}
+
+	if (pos[1] > RSN_SELECTOR_LEN + 2 &&
+	    os_memcmp(pos + 2, RSN_KEY_DATA_IGTK, RSN_SELECTOR_LEN) == 0) {
+		ie->igtk = pos + 2 + RSN_SELECTOR_LEN;
+		ie->igtk_len = pos[1] - RSN_SELECTOR_LEN;
+		return 0;
 	}
+#endif /* CONFIG_IEEE80211W */
 
 	return 0;
 }
@@ -898,11 +1306,19 @@
 	const u8 *pos, *end;
 	int ret = 0;
 
-	memset(ie, 0, sizeof(*ie));
+	os_memset(ie, 0, sizeof(*ie));
 	for (pos = buf, end = pos + len; pos + 1 < end; pos += 2 + pos[1]) {
+		if (pos[0] == 0xdd &&
+		    ((pos == buf + len - 1) || pos[1] == 0)) {
+			/* Ignore padding */
+			break;
+		}
 		if (pos + 2 + pos[1] > end) {
 			wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key Key Data "
-				   "underflow (ie=%d len=%d)", pos[0], pos[1]);
+				   "underflow (ie=%d len=%d pos=%d)",
+				   pos[0], pos[1], (int) (pos - buf));
+			wpa_hexdump_key(MSG_DEBUG, "WPA: Key Data",
+					buf, len);
 			ret = -1;
 			break;
 		}
@@ -938,7 +1354,7 @@
 		 * not have enough time to get the association information
 		 * event before receiving this 1/4 message, so try to find a
 		 * matching PMKSA cache entry here. */
-		sm->cur_pmksa = pmksa_cache_get(sm, src_addr, pmkid);
+		sm->cur_pmksa = pmksa_cache_get(sm->pmksa, src_addr, pmkid);
 		if (sm->cur_pmksa) {
 			wpa_printf(MSG_DEBUG, "RSN: found matching PMKID from "
 				   "PMKSA cache");
@@ -949,7 +1365,7 @@
 	}
 
 	if (pmkid && sm->cur_pmksa &&
-	    memcmp(pmkid, sm->cur_pmksa->pmkid, PMKID_LEN) == 0) {
+	    os_memcmp(pmkid, sm->cur_pmksa->pmkid, PMKID_LEN) == 0) {
 		wpa_hexdump(MSG_DEBUG, "RSN: matched PMKID", pmkid, PMKID_LEN);
 		wpa_sm_set_pmk_from_pmksa(sm);
 		wpa_hexdump_key(MSG_DEBUG, "RSN: PMK from PMKSA cache",
@@ -959,20 +1375,22 @@
 		int res, pmk_len;
 		pmk_len = PMK_LEN;
 		res = eapol_sm_get_key(sm->eapol, sm->pmk, PMK_LEN);
-#ifdef EAP_LEAP
 		if (res) {
+			/*
+			 * EAP-LEAP is an exception from other EAP methods: it
+			 * uses only 16-byte PMK.
+			 */
 			res = eapol_sm_get_key(sm->eapol, sm->pmk, 16);
 			pmk_len = 16;
 		}
-#endif /* EAP_LEAP */
 		if (res == 0) {
 			wpa_hexdump_key(MSG_DEBUG, "WPA: PMK from EAPOL state "
 					"machines", sm->pmk, pmk_len);
 			sm->pmk_len = pmk_len;
-			pmksa_cache_add(sm, sm->pmk, pmk_len, src_addr,
+			pmksa_cache_add(sm->pmksa, sm->pmk, pmk_len, src_addr,
 					sm->own_addr, sm->cur_ssid);
 			if (!sm->cur_pmksa && pmkid &&
-			    pmksa_cache_get(sm, src_addr, pmkid)) {
+			    pmksa_cache_get(sm->pmksa, src_addr, pmkid)) {
 				wpa_printf(MSG_DEBUG, "RSN: the new PMK "
 					   "matches with the PMKID");
 				abort_cached = 0;
@@ -1006,7 +1424,7 @@
 		if (buf) {
 			wpa_sm_ether_send(sm, sm->bssid, ETH_P_EAPOL,
 					  buf, buflen);
-			free(buf);
+			os_free(buf);
 		}
 
 		return -1;
@@ -1017,24 +1435,22 @@
 
 
 static int wpa_supplicant_send_2_of_4(struct wpa_sm *sm,
-				      const unsigned char *src_addr,
+				      const unsigned char *dst,
 				      const struct wpa_eapol_key *key,
-				      int ver)
+				      int ver, const u8 *nonce,
+				      const u8 *wpa_ie, size_t wpa_ie_len,
+				      struct wpa_ptk *ptk)
 {
 	size_t rlen;
 	struct wpa_eapol_key *reply;
-	struct wpa_ptk *ptk;
-	u8 buf[8], *rbuf, *wpa_ie;
-	int wpa_ie_len;
+	u8 *rbuf;
 
-	if (sm->assoc_wpa_ie == NULL) {
-		wpa_printf(MSG_WARNING, "WPA: No assoc_wpa_ie set - cannot "
+	if (wpa_ie == NULL) {
+		wpa_printf(MSG_WARNING, "WPA: No wpa_ie set - cannot "
 			   "generate msg 2/4");
 		return -1;
 	}
 
-	wpa_ie = sm->assoc_wpa_ie;
-	wpa_ie_len = sm->assoc_wpa_ie_len;
 	wpa_hexdump(MSG_DEBUG, "WPA: WPA IE for msg 2/4", wpa_ie, wpa_ie_len);
 
 	rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY,
@@ -1050,40 +1466,17 @@
 	if (sm->proto == WPA_PROTO_RSN)
 		WPA_PUT_BE16(reply->key_length, 0);
 	else
-		memcpy(reply->key_length, key->key_length, 2);
-	memcpy(reply->replay_counter, key->replay_counter,
-	       WPA_REPLAY_COUNTER_LEN);
+		os_memcpy(reply->key_length, key->key_length, 2);
+	os_memcpy(reply->replay_counter, key->replay_counter,
+		  WPA_REPLAY_COUNTER_LEN);
 
 	WPA_PUT_BE16(reply->key_data_length, wpa_ie_len);
-	memcpy(reply + 1, wpa_ie, wpa_ie_len);
-
-	if (sm->renew_snonce) {
-		if (hostapd_get_rand(sm->snonce, WPA_NONCE_LEN)) {
-			wpa_msg(sm->ctx->ctx, MSG_WARNING,
-				"WPA: Failed to get random data for SNonce");
-			free(rbuf);
-			return -1;
-		}
-		sm->renew_snonce = 0;
-		wpa_hexdump(MSG_DEBUG, "WPA: Renewed SNonce",
-			    sm->snonce, WPA_NONCE_LEN);
-	}
-	memcpy(reply->key_nonce, sm->snonce, WPA_NONCE_LEN);
+	os_memcpy(reply + 1, wpa_ie, wpa_ie_len);
 
-	/* Calculate PTK which will be stored as a temporary PTK until it has
-	 * been verified when processing message 3/4. */
-	ptk = &sm->tptk;
-	wpa_pmk_to_ptk(sm->pmk, sm->pmk_len, sm->own_addr, src_addr,
-		       sm->snonce, key->key_nonce,
-		       (u8 *) ptk, sizeof(*ptk));
-	/* Supplicant: swap tx/rx Mic keys */
-	memcpy(buf, ptk->u.auth.tx_mic_key, 8);
-	memcpy(ptk->u.auth.tx_mic_key, ptk->u.auth.rx_mic_key, 8);
-	memcpy(ptk->u.auth.rx_mic_key, buf, 8);
-	sm->tptk_set = 1;
+	os_memcpy(reply->key_nonce, nonce, WPA_NONCE_LEN);
 
 	wpa_printf(MSG_DEBUG, "WPA: Sending EAPOL-Key 2/4");
-	wpa_eapol_key_send(sm, ptk->kck, ver, src_addr, ETH_P_EAPOL,
+	wpa_eapol_key_send(sm, ptk->kck, ver, dst, ETH_P_EAPOL,
 			   rbuf, rlen, reply->key_mic);
 
 	return 0;
@@ -1096,6 +1489,8 @@
 					  u16 ver)
 {
 	struct wpa_eapol_ie_parse ie;
+	struct wpa_ptk *ptk;
+	u8 buf[8];
 
 	if (wpa_sm_get_ssid(sm) == NULL) {
 		wpa_printf(MSG_WARNING, "WPA: No SSID info found (msg 1 of "
@@ -1107,27 +1502,54 @@
 	wpa_printf(MSG_DEBUG, "WPA: RX message 1 of 4-Way Handshake from "
 		   MACSTR " (ver=%d)", MAC2STR(src_addr), ver);
 
-	memset(&ie, 0, sizeof(ie));
+	os_memset(&ie, 0, sizeof(ie));
 
+#ifndef CONFIG_NO_WPA2
 	if (sm->proto == WPA_PROTO_RSN) {
 		/* RSN: msg 1/4 should contain PMKID for the selected PMK */
-		const u8 *buf = (const u8 *) (key + 1);
+		const u8 *_buf = (const u8 *) (key + 1);
 		size_t len = WPA_GET_BE16(key->key_data_length);
-		wpa_hexdump(MSG_DEBUG, "RSN: msg 1/4 key data", buf, len);
-		wpa_supplicant_parse_ies(buf, len, &ie);
+		wpa_hexdump(MSG_DEBUG, "RSN: msg 1/4 key data", _buf, len);
+		wpa_supplicant_parse_ies(_buf, len, &ie);
 		if (ie.pmkid) {
 			wpa_hexdump(MSG_DEBUG, "RSN: PMKID from "
 				    "Authenticator", ie.pmkid, PMKID_LEN);
 		}
 	}
+#endif /* CONFIG_NO_WPA2 */
 
 	if (wpa_supplicant_get_pmk(sm, src_addr, ie.pmkid))
 		return;
 
-	if (wpa_supplicant_send_2_of_4(sm, src_addr, key, ver))
+	if (sm->renew_snonce) {
+		if (hostapd_get_rand(sm->snonce, WPA_NONCE_LEN)) {
+			wpa_msg(sm->ctx->ctx, MSG_WARNING,
+				"WPA: Failed to get random data for SNonce");
+			return;
+		}
+		sm->renew_snonce = 0;
+		wpa_hexdump(MSG_DEBUG, "WPA: Renewed SNonce",
+			    sm->snonce, WPA_NONCE_LEN);
+	}
+
+	/* Calculate PTK which will be stored as a temporary PTK until it has
+	 * been verified when processing message 3/4. */
+	ptk = &sm->tptk;
+	wpa_pmk_to_ptk(sm->pmk, sm->pmk_len, "Pairwise key expansion",
+		       sm->own_addr, sm->bssid, sm->snonce, key->key_nonce,
+		       (u8 *) ptk, sizeof(*ptk));
+	/* Supplicant: swap tx/rx Mic keys */
+	os_memcpy(buf, ptk->u.auth.tx_mic_key, 8);
+	os_memcpy(ptk->u.auth.tx_mic_key, ptk->u.auth.rx_mic_key, 8);
+	os_memcpy(ptk->u.auth.rx_mic_key, buf, 8);
+	sm->tptk_set = 1;
+
+	if (wpa_supplicant_send_2_of_4(sm, sm->bssid, key, ver, sm->snonce,
+				       sm->assoc_wpa_ie, sm->assoc_wpa_ie_len,
+				       ptk))
 		return;
 
-	memcpy(sm->anonce, key->key_nonce, WPA_NONCE_LEN);
+	os_memcpy(sm->anonce, key->key_nonce, WPA_NONCE_LEN);
 }
 
 
@@ -1150,7 +1572,9 @@
 	wpa_sm_set_state(sm, WPA_COMPLETED);
 
 	if (secure) {
-		/* MLME.SETPROTECTION.request(TA, Tx_Rx) */
+		wpa_sm_mlme_setprotection(
+			sm, addr, MLME_SETPROTECTION_PROTECT_TYPE_RX_TX,
+			MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
 		eapol_sm_notify_portValid(sm->eapol, TRUE);
 		if (sm->key_mgmt == WPA_KEY_MGMT_PSK)
 			eapol_sm_notify_eap_success(sm->eapol, TRUE);
@@ -1173,10 +1597,10 @@
 
 
 static int wpa_supplicant_install_ptk(struct wpa_sm *sm,
-				      const unsigned char *src_addr,
 				      const struct wpa_eapol_key *key)
 {
-	int alg, keylen, rsclen;
+	int keylen, rsclen;
+	wpa_alg alg;
 	const u8 *key_rsc;
 	u8 null_rsc[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
 
@@ -1210,8 +1634,8 @@
 		wpa_hexdump(MSG_DEBUG, "WPA: RSC", key_rsc, rsclen);
 	}
 
-	if (wpa_sm_set_key(sm, alg, src_addr, 0, 1, key_rsc, rsclen,
-			   (u8 *) &sm->ptk.tk1, keylen) < 0) {
+	if (wpa_sm_set_key(sm, alg, sm->bssid, 0, 1, key_rsc, rsclen,
+			   (u8 *) sm->ptk.tk1, keylen) < 0) {
 		wpa_printf(MSG_WARNING, "WPA: Failed to set PTK to the "
 			   "driver.");
 		return -1;
@@ -1222,7 +1646,7 @@
 
 static int wpa_supplicant_check_group_cipher(int group_cipher,
 					     int keylen, int maxkeylen,
-					     int *key_rsc_len, int *alg)
+					     int *key_rsc_len, wpa_alg *alg)
 {
 	int ret = 0;
 
@@ -1276,7 +1700,8 @@
 
 
 struct wpa_gtk_data {
-	int alg, tx, key_rsc_len, keyidx;
+	wpa_alg alg;
+	int tx, key_rsc_len, keyidx;
 	u8 gtk[32];
 	int gtk_len;
 };
@@ -1295,9 +1720,9 @@
 	wpa_hexdump(MSG_DEBUG, "WPA: RSC", key_rsc, gd->key_rsc_len);
 	if (sm->group_cipher == WPA_CIPHER_TKIP) {
 		/* Swap Tx/Rx keys for Michael MIC */
-		memcpy(gtk_buf, gd->gtk, 16);
-		memcpy(gtk_buf + 16, gd->gtk + 24, 8);
-		memcpy(gtk_buf + 24, gd->gtk + 16, 8);
+		os_memcpy(gtk_buf, gd->gtk, 16);
+		os_memcpy(gtk_buf + 16, gd->gtk + 24, 8);
+		os_memcpy(gtk_buf + 24, gd->gtk + 16, 8);
 		_gtk = gtk_buf;
 	}
 	if (sm->pairwise_cipher == WPA_CIPHER_NONE) {
@@ -1340,11 +1765,11 @@
 
 
 static int wpa_supplicant_pairwise_gtk(struct wpa_sm *sm,
-				       const unsigned char *src_addr,
 				       const struct wpa_eapol_key *key,
-				       const u8 *gtk, int gtk_len,
+				       const u8 *gtk, size_t gtk_len,
 				       int key_info)
 {
+#ifndef CONFIG_NO_WPA2
 	struct wpa_gtk_data gd;
 
 	/*
@@ -1355,7 +1780,7 @@
 	 * GTK
 	 */
 
-	memset(&gd, 0, sizeof(gd));
+	os_memset(&gd, 0, sizeof(gd));
 	wpa_hexdump_key(MSG_DEBUG, "RSN: received GTK in pairwise handshake",
 			gtk, gtk_len);
 
@@ -1368,7 +1793,7 @@
 	gtk += 2;
 	gtk_len -= 2;
 
-	memcpy(gd.gtk, gtk, gtk_len);
+	os_memcpy(gd.gtk, gtk, gtk_len);
 	gd.gtk_len = gtk_len;
 
 	if (wpa_supplicant_check_group_cipher(sm->group_cipher,
@@ -1379,9 +1804,68 @@
 		return -1;
 	}
 
-	wpa_supplicant_key_neg_complete(sm, src_addr,
+	wpa_supplicant_key_neg_complete(sm, sm->bssid,
 					key_info & WPA_KEY_INFO_SECURE);
 	return 0;
+#else /* CONFIG_NO_WPA2 */
+	return -1;
+#endif /* CONFIG_NO_WPA2 */
+}
+
+
+static int ieee80211w_set_keys(struct wpa_sm *sm,
+			       struct wpa_eapol_ie_parse *ie)
+{
+#ifdef CONFIG_IEEE80211W
+	if (sm->mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC)
+		return 0;
+
+	if (ie->igtk) {
+		const struct wpa_igtk_kde *igtk;
+		u16 keyidx;
+		if (ie->igtk_len != sizeof(*igtk))
+			return -1;
+		igtk = (const struct wpa_igtk_kde *) ie->igtk;
+		keyidx = WPA_GET_LE16(igtk->keyid);
+		wpa_printf(MSG_DEBUG, "WPA: IGTK keyid %d "
+			   "pn %02x%02x%02x%02x%02x%02x",
+			   keyidx, MAC2STR(igtk->pn));
+		wpa_hexdump_key(MSG_DEBUG, "WPA: IGTK",
+				igtk->igtk, WPA_IGTK_LEN);
+		if (keyidx > 4095) {
+			wpa_printf(MSG_WARNING, "WPA: Invalid IGTK KeyID %d",
+				   keyidx);
+			return -1;
+		}
+		if (wpa_sm_set_key(sm, WPA_ALG_IGTK,
+				   (u8 *) "\xff\xff\xff\xff\xff\xff",
+				   keyidx, 0, igtk->pn, sizeof(igtk->pn),
+				   igtk->igtk, WPA_IGTK_LEN) < 0) {
+			wpa_printf(MSG_WARNING, "WPA: Failed to configure IGTK"
+				   " to the driver");
+			return -1;
+		}
+	}
+
+	if (ie->dhv) {
+		const struct wpa_dhv_kde *dhv;
+		if (ie->dhv_len != sizeof(*dhv))
+			return -1;
+		dhv = (const struct wpa_dhv_kde *) ie->dhv;
+		wpa_hexdump_key(MSG_DEBUG, "WPA: DHV", dhv->dhv, WPA_DHV_LEN);
+		if (wpa_sm_set_key(sm, WPA_ALG_DHV,
+				   (u8 *) "\xff\xff\xff\xff\xff\xff", 0, 0,
+				   NULL, 0, dhv->dhv, WPA_DHV_LEN) < 0) {
+			wpa_printf(MSG_WARNING, "WPA: Failed to configure DHV "
+				   "to the driver");
+			return -1;
+		}
+	}
+
+	return 0;
+#else /* CONFIG_IEEE80211W */
+	return 0;
+#endif /* CONFIG_IEEE80211W */
 }
 
 
@@ -1442,12 +1926,21 @@
 		}
 	}
 
+	if (ie->wpa_ie == NULL && ie->rsn_ie == NULL &&
+	    (sm->ap_wpa_ie || sm->ap_rsn_ie)) {
+		wpa_report_ie_mismatch(sm, "IE in 3/4 msg does not match "
+				       "with IE in Beacon/ProbeResp (no IE?)",
+				       src_addr, ie->wpa_ie, ie->wpa_ie_len,
+				       ie->rsn_ie, ie->rsn_ie_len);
+		return -1;
+	}
+
 	if ((ie->wpa_ie && sm->ap_wpa_ie &&
 	     (ie->wpa_ie_len != sm->ap_wpa_ie_len ||
-	      memcmp(ie->wpa_ie, sm->ap_wpa_ie, ie->wpa_ie_len) != 0)) ||
+	      os_memcmp(ie->wpa_ie, sm->ap_wpa_ie, ie->wpa_ie_len) != 0)) ||
 	    (ie->rsn_ie && sm->ap_rsn_ie &&
 	     (ie->rsn_ie_len != sm->ap_rsn_ie_len ||
-	      memcmp(ie->rsn_ie, sm->ap_rsn_ie, ie->rsn_ie_len) != 0))) {
+	      os_memcmp(ie->rsn_ie, sm->ap_rsn_ie, ie->rsn_ie_len) != 0))) {
 		wpa_report_ie_mismatch(sm, "IE in 3/4 msg does not match "
 				       "with IE in Beacon/ProbeResp",
 				       src_addr, ie->wpa_ie, ie->wpa_ie_len,
@@ -1472,16 +1965,22 @@
 
 
 static int wpa_supplicant_send_4_of_4(struct wpa_sm *sm,
-				      const unsigned char *src_addr,
+				      const unsigned char *dst,
 				      const struct wpa_eapol_key *key,
-				      u16 ver, u16 key_info)
+				      u16 ver, u16 key_info,
+				      const u8 *kde, size_t kde_len,
+				      struct wpa_ptk *ptk)
 {
 	size_t rlen;
 	struct wpa_eapol_key *reply;
 	u8 *rbuf;
 
+	if (kde)
+		wpa_hexdump(MSG_DEBUG, "WPA: KDE for msg 4/4", kde, kde_len);
+
 	rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,
-				  sizeof(*reply), &rlen, (void *) &reply);
+				  sizeof(*reply) + kde_len,
+				  &rlen, (void *) &reply);
 	if (rbuf == NULL)
 		return -1;
 
@@ -1493,14 +1992,16 @@
 	if (sm->proto == WPA_PROTO_RSN)
 		WPA_PUT_BE16(reply->key_length, 0);
 	else
-		memcpy(reply->key_length, key->key_length, 2);
-	memcpy(reply->replay_counter, key->replay_counter,
-	       WPA_REPLAY_COUNTER_LEN);
-
-	WPA_PUT_BE16(reply->key_data_length, 0);
+		os_memcpy(reply->key_length, key->key_length, 2);
+	os_memcpy(reply->replay_counter, key->replay_counter,
+		  WPA_REPLAY_COUNTER_LEN);
+
+	WPA_PUT_BE16(reply->key_data_length, kde_len);
+	if (kde)
+		os_memcpy(reply + 1, kde, kde_len);
 
 	wpa_printf(MSG_DEBUG, "WPA: Sending EAPOL-Key 4/4");
-	wpa_eapol_key_send(sm, sm->ptk.kck, ver, src_addr, ETH_P_EAPOL,
+	wpa_eapol_key_send(sm, ptk->kck, ver, dst, ETH_P_EAPOL,
 			   rbuf, rlen, reply->key_mic);
 
 	return 0;
@@ -1508,9 +2009,8 @@
 
 
 static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm,
-					  const unsigned char *src_addr,
 					  const struct wpa_eapol_key *key,
-					  int extra_len, u16 ver)
+					  u16 ver)
 {
 	u16 key_info, keylen, len;
 	const u8 *pos;
@@ -1518,7 +2018,7 @@
 
 	wpa_sm_set_state(sm, WPA_4WAY_HANDSHAKE);
 	wpa_printf(MSG_DEBUG, "WPA: RX message 3 of 4-Way Handshake from "
-		   MACSTR " (ver=%d)", MAC2STR(src_addr), ver);
+		   MACSTR " (ver=%d)", MAC2STR(sm->bssid), ver);
 
 	key_info = WPA_GET_BE16(key->key_info);
 
@@ -1530,14 +2030,33 @@
 		wpa_printf(MSG_WARNING, "WPA: GTK IE in unencrypted key data");
 		return;
 	}
+#ifdef CONFIG_IEEE80211W
+	if ((ie.dhv || ie.igtk) && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
+		wpa_printf(MSG_WARNING, "WPA: DHV/IGTK KDE in unencrypted key "
+			   "data");
+		return;
+	}
 
-	if (wpa_supplicant_validate_ie(sm, src_addr, &ie) < 0)
+	if (ie.dhv && ie.dhv_len != sizeof(struct wpa_dhv_kde)) {
+		wpa_printf(MSG_WARNING, "WPA: Invalid DHV KDE length %lu",
+			   (unsigned long) ie.dhv_len);
 		return;
+	}
+
+	if (ie.igtk && ie.igtk_len != sizeof(struct wpa_igtk_kde)) {
+		wpa_printf(MSG_WARNING, "WPA: Invalid IGTK KDE length %lu",
+			   (unsigned long) ie.igtk_len);
+		return;
+	}
+#endif /* CONFIG_IEEE80211W */
 
-	if (memcmp(sm->anonce, key->key_nonce, WPA_NONCE_LEN) != 0) {
+	if (wpa_supplicant_validate_ie(sm, sm->bssid, &ie) < 0)
+		return;
+
+	if (os_memcmp(sm->anonce, key->key_nonce, WPA_NONCE_LEN) != 0) {
 		wpa_printf(MSG_WARNING, "WPA: ANonce from message 1 of 4-Way "
 			   "Handshake differs from 3 of 4-Way Handshake - drop"
-			   " packet (src=" MACSTR ")", MAC2STR(src_addr));
+			   " packet (src=" MACSTR ")", MAC2STR(sm->bssid));
 		return;
 	}
 
@@ -1547,7 +2066,7 @@
 		if (keylen != 16) {
 			wpa_printf(MSG_WARNING, "WPA: Invalid CCMP key length "
 				   "%d (src=" MACSTR ")",
-				   keylen, MAC2STR(src_addr));
+				   keylen, MAC2STR(sm->bssid));
 			return;
 		}
 		break;
@@ -1555,13 +2074,14 @@
 		if (keylen != 32) {
 			wpa_printf(MSG_WARNING, "WPA: Invalid TKIP key length "
 				   "%d (src=" MACSTR ")",
-				   keylen, MAC2STR(src_addr));
+				   keylen, MAC2STR(sm->bssid));
 			return;
 		}
 		break;
 	}
 
-	if (wpa_supplicant_send_4_of_4(sm, src_addr, key, ver, key_info))
+	if (wpa_supplicant_send_4_of_4(sm, sm->bssid, key, ver, key_info,
+				       NULL, 0, &sm->ptk))
 		return;
 
 	/* SNonce was successfully used in msg 3/4, so mark it to be renewed
@@ -1570,51 +2090,905 @@
 	sm->renew_snonce = 1;
 
 	if (key_info & WPA_KEY_INFO_INSTALL) {
-		wpa_supplicant_install_ptk(sm, src_addr, key);
+		wpa_supplicant_install_ptk(sm, key);
 	}
 
 	if (key_info & WPA_KEY_INFO_SECURE) {
-		/* MLME.SETPROTECTION.request(TA, Tx_Rx) */
+		wpa_sm_mlme_setprotection(
+			sm, sm->bssid, MLME_SETPROTECTION_PROTECT_TYPE_RX,
+			MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
 		eapol_sm_notify_portValid(sm->eapol, TRUE);
 	}
 	wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE);
 
 	if (ie.gtk &&
-	    wpa_supplicant_pairwise_gtk(sm, src_addr, key,
+	    wpa_supplicant_pairwise_gtk(sm, key,
 					ie.gtk, ie.gtk_len, key_info) < 0) {
 		wpa_printf(MSG_INFO, "RSN: Failed to configure GTK");
 	}
+
+	if (ieee80211w_set_keys(sm, &ie) < 0)
+		wpa_printf(MSG_INFO, "RSN: Failed to configure DHV/IGTK");
 }
 
 
-static int wpa_supplicant_process_1_of_2_rsn(struct wpa_sm *sm,
-					     const u8 *keydata,
-					     size_t keydatalen,
-					     int key_info,
-					     struct wpa_gtk_data *gd)
+#ifdef CONFIG_PEERKEY
+static void wpa_supplicant_smk_timeout(void *eloop_ctx, void *timeout_ctx)
 {
-	int maxkeylen;
-	struct wpa_eapol_ie_parse ie;
+#if 0
+	struct wpa_sm *sm = eloop_ctx;
+	struct wpa_peerkey *peerkey = timeout_ctx;
+#endif
+	/* TODO: time out SMK and any STK that was generated using this SMK */
+}
 
-	wpa_hexdump(MSG_DEBUG, "RSN: msg 1/2 key data", keydata, keydatalen);
-	wpa_supplicant_parse_ies(keydata, keydatalen, &ie);
-	if (ie.gtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
-		wpa_printf(MSG_WARNING, "WPA: GTK IE in unencrypted key data");
-		return -1;
-	}
-	if (ie.gtk == NULL) {
-		wpa_printf(MSG_INFO, "WPA: No GTK IE in Group Key msg 1/2");
-		return -1;
-	}
-	maxkeylen = gd->gtk_len = ie.gtk_len - 2;
 
-	if (wpa_supplicant_check_group_cipher(sm->group_cipher,
-					      gd->gtk_len, maxkeylen,
-					      &gd->key_rsc_len, &gd->alg))
+static void wpa_supplicant_peerkey_free(struct wpa_sm *sm,
+					struct wpa_peerkey *peerkey)
+{
+	eloop_cancel_timeout(wpa_supplicant_smk_timeout, sm, peerkey);
+	os_free(peerkey);
+}
+
+
+static int wpa_supplicant_send_smk_error(struct wpa_sm *sm, const u8 *dst,
+					 const u8 *peer,
+					 u16 mui, u16 error_type, int ver)
+{
+#ifndef CONFIG_NO_WPA2
+	size_t rlen;
+	struct wpa_eapol_key *err;
+	struct rsn_error_kde error;
+	u8 *rbuf, *pos;
+	size_t kde_len;
+	u16 key_info;
+
+	kde_len = 2 + RSN_SELECTOR_LEN + sizeof(error);
+	if (peer)
+		kde_len += 2 + RSN_SELECTOR_LEN + ETH_ALEN;
+
+	rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY,
+				  NULL, sizeof(*err) + kde_len, &rlen,
+				  (void *) &err);
+	if (rbuf == NULL)
 		return -1;
 
-	wpa_hexdump(MSG_DEBUG, "RSN: received GTK in group key handshake",
-		    ie.gtk, ie.gtk_len);
+	err->type = EAPOL_KEY_TYPE_RSN;
+	key_info = ver | WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_MIC |
+		WPA_KEY_INFO_SECURE | WPA_KEY_INFO_ERROR |
+		WPA_KEY_INFO_REQUEST;
+	WPA_PUT_BE16(err->key_info, key_info);
+	WPA_PUT_BE16(err->key_length, 0);
+	os_memcpy(err->replay_counter, sm->request_counter,
+		  WPA_REPLAY_COUNTER_LEN);
+	inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN);
+
+	WPA_PUT_BE16(err->key_data_length, (u16) kde_len);
+	pos = (u8 *) (err + 1);
+
+	if (peer) {
+		/* Peer MAC Address KDE */
+		pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN);
+	}
+
+	/* Error KDE */
+	error.mui = host_to_be16(mui);
+	error.error_type = host_to_be16(error_type);
+	pos = wpa_add_kde(pos, RSN_KEY_DATA_ERROR,
+			  (u8 *) &error, sizeof(error));
+
+	if (peer) {
+		wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key SMK Error (peer "
+			   MACSTR " mui %d error_type %d)",
+			   MAC2STR(peer), mui, error_type);
+	} else {
+		wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key SMK Error "
+			   "(mui %d error_type %d)", mui, error_type);
+	}
+
+	wpa_eapol_key_send(sm, sm->ptk.kck, ver, dst, ETH_P_EAPOL,
+			   rbuf, rlen, err->key_mic);
+
+	return 0;
+#else /* CONFIG_NO_WPA2 */
+	return -1;
+#endif /* CONFIG_NO_WPA2 */
+}
+
+
+static int wpa_supplicant_send_smk_m3(struct wpa_sm *sm,
+				      const unsigned char *src_addr,
+				      const struct wpa_eapol_key *key,
+				      int ver, struct wpa_peerkey *peerkey)
+{
+	size_t rlen;
+	struct wpa_eapol_key *reply;
+	u8 *rbuf, *pos;
+	size_t kde_len;
+	u16 key_info;
+
+	/* KDEs: Peer RSN IE, Initiator MAC Address, Initiator Nonce */
+	kde_len = peerkey->rsnie_p_len +
+		2 + RSN_SELECTOR_LEN + ETH_ALEN +
+		2 + RSN_SELECTOR_LEN + WPA_NONCE_LEN;
+
+	rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY,
+				  NULL, sizeof(*reply) + kde_len, &rlen,
+				  (void *) &reply);
+	if (rbuf == NULL)
+		return -1;
+
+	reply->type = EAPOL_KEY_TYPE_RSN;
+	key_info = ver | WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_MIC |
+		WPA_KEY_INFO_SECURE;
+	WPA_PUT_BE16(reply->key_info, key_info);
+	WPA_PUT_BE16(reply->key_length, 0);
+	os_memcpy(reply->replay_counter, key->replay_counter,
+		  WPA_REPLAY_COUNTER_LEN);
+
+	os_memcpy(reply->key_nonce, peerkey->pnonce, WPA_NONCE_LEN);
+
+	WPA_PUT_BE16(reply->key_data_length, (u16) kde_len);
+	pos = (u8 *) (reply + 1);
+
+	/* Peer RSN IE */
+	pos = wpa_add_ie(pos, peerkey->rsnie_p, peerkey->rsnie_p_len);
+
+	/* Initiator MAC Address KDE */
+	pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peerkey->addr, ETH_ALEN);
+
+	/* Initiator Nonce */
+	pos = wpa_add_kde(pos, RSN_KEY_DATA_NONCE,
+			  peerkey->inonce, WPA_NONCE_LEN);
+
+	wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key SMK M3");
+	wpa_eapol_key_send(sm, sm->ptk.kck, ver, src_addr, ETH_P_EAPOL,
+			   rbuf, rlen, reply->key_mic);
+
+	return 0;
+}
+
+
+static int wpa_supplicant_process_smk_m2(
+	struct wpa_sm *sm, const unsigned char *src_addr,
+	const struct wpa_eapol_key *key, size_t extra_len, int ver)
+{
+	struct wpa_ssid *ssid = sm->cur_ssid;
+	struct wpa_peerkey *peerkey;
+	struct wpa_eapol_ie_parse kde;
+	struct wpa_ie_data ie;
+	int cipher;
+	struct rsn_ie_hdr *hdr;
+	u8 *pos;
+
+	wpa_printf(MSG_DEBUG, "RSN: Received SMK M2");
+
+	if (ssid == NULL || !ssid->peerkey || sm->proto != WPA_PROTO_RSN) {
+		wpa_printf(MSG_INFO, "RSN: SMK handshake not allowed for "
+			   "the current network");
+		return -1;
+	}
+
+	if (wpa_supplicant_parse_ies((const u8 *) (key + 1), extra_len, &kde) <
+	    0) {
+		wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M2");
+		return -1;
+	}
+
+	if (kde.rsn_ie == NULL || kde.mac_addr == NULL ||
+	    kde.mac_addr_len < ETH_ALEN) {
+		wpa_printf(MSG_INFO, "RSN: No RSN IE or MAC address KDE in "
+			   "SMK M2");
+		return -1;
+	}
+
+	wpa_printf(MSG_DEBUG, "RSN: SMK M2 - SMK initiator " MACSTR,
+		   MAC2STR(kde.mac_addr));
+
+	if (kde.rsn_ie_len > PEERKEY_MAX_IE_LEN) {
+		wpa_printf(MSG_INFO, "RSN: Too long Initiator RSN IE in SMK "
+			   "M2");
+		return -1;
+	}
+
+	if (wpa_parse_wpa_ie_rsn(kde.rsn_ie, kde.rsn_ie_len, &ie) < 0) {
+		wpa_printf(MSG_INFO, "RSN: Failed to parse RSN IE in SMK M2");
+		return -1;
+	}
+
+	cipher = ie.pairwise_cipher & ssid->pairwise_cipher;
+	if (cipher & WPA_CIPHER_CCMP) {
+		wpa_printf(MSG_DEBUG, "RSN: Using CCMP for PeerKey");
+		cipher = WPA_CIPHER_CCMP;
+	} else if (cipher & WPA_CIPHER_TKIP) {
+		wpa_printf(MSG_DEBUG, "RSN: Using TKIP for PeerKey");
+		cipher = WPA_CIPHER_TKIP;
+	} else {
+		wpa_printf(MSG_INFO, "RSN: No acceptable cipher in SMK M2");
+		wpa_supplicant_send_smk_error(sm, src_addr, kde.mac_addr,
+					      STK_MUI_SMK, STK_ERR_CPHR_NS,
+					      ver);
+		return -1;
+	}
+
+	/* TODO: find existing entry and if found, use that instead of adding
+	 * a new one; how to handle the case where both ends initiate at the
+	 * same time? */
+	peerkey = os_malloc(sizeof(*peerkey));
+	if (peerkey == NULL)
+		return -1;
+	os_memset(peerkey, 0, sizeof(*peerkey));
+	os_memcpy(peerkey->addr, kde.mac_addr, ETH_ALEN);
+	os_memcpy(peerkey->inonce, key->key_nonce, WPA_NONCE_LEN);
+	os_memcpy(peerkey->rsnie_i, kde.rsn_ie, kde.rsn_ie_len);
+	peerkey->rsnie_i_len = kde.rsn_ie_len;
+	peerkey->cipher = cipher;
+
+	if (hostapd_get_rand(peerkey->pnonce, WPA_NONCE_LEN)) {
+		wpa_msg(sm->ctx->ctx, MSG_WARNING,
+			"WPA: Failed to get random data for PNonce");
+		wpa_supplicant_peerkey_free(sm, peerkey);
+		return -1;
+	}
+
+	hdr = (struct rsn_ie_hdr *) peerkey->rsnie_p;
+	hdr->elem_id = RSN_INFO_ELEM;
+	WPA_PUT_LE16(hdr->version, RSN_VERSION);
+	pos = (u8 *) (hdr + 1);
+	/* Group Suite can be anything for SMK RSN IE; receiver will just
+	 * ignore it. */
+	os_memcpy(pos, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN);
+	pos += RSN_SELECTOR_LEN;
+	/* Include only the selected cipher in pairwise cipher suite */
+	WPA_PUT_LE16(pos, 1);
+	pos += 2;
+	if (cipher == WPA_CIPHER_CCMP)
+		os_memcpy(pos, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN);
+	else if (cipher == WPA_CIPHER_TKIP)
+		os_memcpy(pos, RSN_CIPHER_SUITE_TKIP, RSN_SELECTOR_LEN);
+	pos += RSN_SELECTOR_LEN;
+
+	hdr->len = (pos - peerkey->rsnie_p) - 2;
+	peerkey->rsnie_p_len = pos - peerkey->rsnie_p;
+	wpa_hexdump(MSG_DEBUG, "WPA: RSN IE for SMK handshake",
+		    peerkey->rsnie_p, peerkey->rsnie_p_len);
+
+	wpa_supplicant_send_smk_m3(sm, src_addr, key, ver, peerkey);
+
+	peerkey->next = sm->peerkey;
+	sm->peerkey = peerkey;
+
+	return 0;
+}
+
+
+/**
+ * rsn_smkid - Derive SMK identifier
+ * @smk: Station master key (32 bytes)
+ * @pnonce: Peer Nonce
+ * @mac_p: Peer MAC address
+ * @inonce: Initiator Nonce
+ * @mac_i: Initiator MAC address
+ *
+ * 8.5.1.4 Station to station (STK) key hierarchy
+ * SMKID = HMAC-SHA1-128(SMK, "SMK Name" || PNonce || MAC_P || INonce || MAC_I)
+ */
+static void rsn_smkid(const u8 *smk, const u8 *pnonce, const u8 *mac_p,
+		      const u8 *inonce, const u8 *mac_i, u8 *smkid)
+{
+	char *title = "SMK Name";
+	const u8 *addr[5];
+	const size_t len[5] = { 8, WPA_NONCE_LEN, ETH_ALEN, WPA_NONCE_LEN,
+				ETH_ALEN };
+	unsigned char hash[SHA1_MAC_LEN];
+
+	addr[0] = (u8 *) title;
+	addr[1] = pnonce;
+	addr[2] = mac_p;
+	addr[3] = inonce;
+	addr[4] = mac_i;
+
+	hmac_sha1_vector(smk, PMK_LEN, 5, addr, len, hash);
+	os_memcpy(smkid, hash, PMKID_LEN);
+}
+
+
+static void wpa_supplicant_send_stk_1_of_4(struct wpa_sm *sm,
+					   struct wpa_peerkey *peerkey)
+{
+	size_t mlen;
+	struct wpa_eapol_key *msg;
+	u8 *mbuf;
+	size_t kde_len;
+	u16 key_info, ver;
+
+	kde_len = 2 + RSN_SELECTOR_LEN + PMKID_LEN;
+
+	mbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,
+				  sizeof(*msg) + kde_len, &mlen,
+				  (void *) &msg);
+	if (mbuf == NULL)
+		return;
+
+	msg->type = EAPOL_KEY_TYPE_RSN;
+
+	if (peerkey->cipher == WPA_CIPHER_CCMP)
+		ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES;
+	else
+		ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4;
+
+	key_info = ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_ACK;
+	WPA_PUT_BE16(msg->key_info, key_info);
+
+	if (peerkey->cipher == WPA_CIPHER_CCMP)
+		WPA_PUT_BE16(msg->key_length, 16);
+	else
+		WPA_PUT_BE16(msg->key_length, 32);
+
+	os_memcpy(msg->replay_counter, peerkey->replay_counter,
+		  WPA_REPLAY_COUNTER_LEN);
+	inc_byte_array(peerkey->replay_counter, WPA_REPLAY_COUNTER_LEN);
+
+	WPA_PUT_BE16(msg->key_data_length, kde_len);
+	wpa_add_kde((u8 *) (msg + 1), RSN_KEY_DATA_PMKID,
+		    peerkey->smkid, PMKID_LEN);
+
+	if (hostapd_get_rand(peerkey->inonce, WPA_NONCE_LEN)) {
+		wpa_msg(sm->ctx->ctx, MSG_WARNING,
+			"RSN: Failed to get random data for INonce (STK)");
+		os_free(mbuf);
+		return;
+	}
+	wpa_hexdump(MSG_DEBUG, "RSN: INonce for STK 4-Way Handshake",
+		    peerkey->inonce, WPA_NONCE_LEN);
+	os_memcpy(msg->key_nonce, peerkey->inonce, WPA_NONCE_LEN);
+
+	wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key STK 1/4 to " MACSTR,
+		   MAC2STR(peerkey->addr));
+	wpa_eapol_key_send(sm, NULL, ver, peerkey->addr, ETH_P_EAPOL,
+			   mbuf, mlen, NULL);
+}
+
+
+static void wpa_supplicant_send_stk_3_of_4(struct wpa_sm *sm,
+					   struct wpa_peerkey *peerkey)
+{
+	size_t mlen;
+	struct wpa_eapol_key *msg;
+	u8 *mbuf, *pos;
+	size_t kde_len;
+	u16 key_info, ver;
+	u32 lifetime;
+
+	kde_len = peerkey->rsnie_i_len +
+		2 + RSN_SELECTOR_LEN + sizeof(lifetime);
+
+	mbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,
+				  sizeof(*msg) + kde_len, &mlen,
+				  (void *) &msg);
+	if (mbuf == NULL)
+		return;
+
+	msg->type = EAPOL_KEY_TYPE_RSN;
+
+	if (peerkey->cipher == WPA_CIPHER_CCMP)
+		ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES;
+	else
+		ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4;
+
+	key_info = ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_ACK |
+		WPA_KEY_INFO_MIC | WPA_KEY_INFO_SECURE;
+	WPA_PUT_BE16(msg->key_info, key_info);
+
+	if (peerkey->cipher == WPA_CIPHER_CCMP)
+		WPA_PUT_BE16(msg->key_length, 16);
+	else
+		WPA_PUT_BE16(msg->key_length, 32);
+
+	os_memcpy(msg->replay_counter, peerkey->replay_counter,
+		  WPA_REPLAY_COUNTER_LEN);
+	inc_byte_array(peerkey->replay_counter, WPA_REPLAY_COUNTER_LEN);
+
+	WPA_PUT_BE16(msg->key_data_length, kde_len);
+	pos = (u8 *) (msg + 1);
+	pos = wpa_add_ie(pos, peerkey->rsnie_i, peerkey->rsnie_i_len);
+	lifetime = host_to_be32(peerkey->lifetime);
+	pos = wpa_add_kde(pos, RSN_KEY_DATA_LIFETIME,
+			  (u8 *) &lifetime, sizeof(lifetime));
+
+	os_memcpy(msg->key_nonce, peerkey->inonce, WPA_NONCE_LEN);
+
+	wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key STK 3/4 to " MACSTR,
+		   MAC2STR(peerkey->addr));
+	wpa_eapol_key_send(sm, peerkey->stk.kck, ver, peerkey->addr,
+			   ETH_P_EAPOL, mbuf, mlen, msg->key_mic);
+}
+
+
+static int wpa_supplicant_process_smk_m45(
+	struct wpa_sm *sm, const unsigned char *src_addr,
+	const struct wpa_eapol_key *key, size_t extra_len, int ver)
+{
+	struct wpa_ssid *ssid = sm->cur_ssid;
+	struct wpa_peerkey *peerkey;
+	struct wpa_eapol_ie_parse kde;
+	u32 lifetime;
+	struct os_time now;
+	struct wpa_ie_data ie;
+
+	if (ssid == NULL || !ssid->peerkey || sm->proto != WPA_PROTO_RSN) {
+		wpa_printf(MSG_DEBUG, "RSN: SMK handshake not allowed for "
+			   "the current network");
+		return -1;
+	}
+
+	if (wpa_supplicant_parse_ies((const u8 *) (key + 1), extra_len, &kde) <
+	    0) {
+		wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M4/M5");
+		return -1;
+	}
+
+	if (kde.mac_addr == NULL || kde.mac_addr_len < ETH_ALEN ||
+	    kde.nonce == NULL || kde.nonce_len < WPA_NONCE_LEN ||
+	    kde.smk == NULL || kde.smk_len < PMK_LEN + WPA_NONCE_LEN ||
+	    kde.lifetime == NULL || kde.lifetime_len < 4) {
+		wpa_printf(MSG_INFO, "RSN: No MAC Address, Nonce, SMK, or "
+			   "Lifetime KDE in SMK M4/M5");
+		return -1;
+	}
+
+	for (peerkey = sm->peerkey; peerkey; peerkey = peerkey->next) {
+		if (os_memcmp(peerkey->addr, kde.mac_addr, ETH_ALEN) == 0 &&
+		    os_memcmp(peerkey->initiator ? peerkey->inonce :
+			   peerkey->pnonce,
+			   key->key_nonce, WPA_NONCE_LEN) == 0)
+			break;
+	}
+	if (peerkey == NULL) {
+		wpa_printf(MSG_INFO, "RSN: No matching SMK handshake found "
+			   "for SMK M4/M5: peer " MACSTR,
+			   MAC2STR(kde.mac_addr));
+		return -1;
+	}
+
+	if (peerkey->initiator) {
+		int cipher;
+		wpa_printf(MSG_DEBUG, "RSN: Received SMK M5 (Peer " MACSTR ")",
+			   MAC2STR(kde.mac_addr));
+		if (kde.rsn_ie == NULL || kde.rsn_ie_len > PEERKEY_MAX_IE_LEN
+		    || wpa_parse_wpa_ie_rsn(kde.rsn_ie, kde.rsn_ie_len, &ie) <
+		    0) {
+			wpa_printf(MSG_INFO, "RSN: No RSN IE in SMK M5");
+			/* TODO: abort negotiation */
+			return -1;
+		}
+
+		if (os_memcmp(key->key_nonce, peerkey->inonce, WPA_NONCE_LEN)
+		    != 0) {
+			wpa_printf(MSG_INFO, "RSN: Key Nonce in SMK M5 does "
+				   "not match with INonce used in SMK M1");
+			return -1;
+		}
+
+		if (os_memcmp(kde.smk + PMK_LEN, peerkey->inonce,
+			      WPA_NONCE_LEN) != 0) {
+			wpa_printf(MSG_INFO, "RSN: INonce in SMK KDE does not "
+				   "match with the one used in SMK M1");
+			return -1;
+		}
+
+		os_memcpy(peerkey->rsnie_p, kde.rsn_ie, kde.rsn_ie_len);
+		peerkey->rsnie_p_len = kde.rsn_ie_len;
+		os_memcpy(peerkey->pnonce, kde.nonce, WPA_NONCE_LEN);
+
+		cipher = ie.pairwise_cipher & ssid->pairwise_cipher;
+		if (cipher & WPA_CIPHER_CCMP) {
+			wpa_printf(MSG_DEBUG, "RSN: Using CCMP for PeerKey");
+			peerkey->cipher = WPA_CIPHER_CCMP;
+		} else if (cipher & WPA_CIPHER_TKIP) {
+			wpa_printf(MSG_DEBUG, "RSN: Using TKIP for PeerKey");
+			peerkey->cipher = WPA_CIPHER_TKIP;
+		} else {
+			wpa_printf(MSG_INFO, "RSN: SMK Peer STA " MACSTR
+				   " selected unacceptable cipher",
+				   MAC2STR(kde.mac_addr));
+			wpa_supplicant_send_smk_error(
+				sm, src_addr, kde.mac_addr,
+				STK_MUI_SMK, STK_ERR_CPHR_NS, ver);
+			/* TODO: abort negotiation */
+			return -1;
+		}
+	} else {
+		wpa_printf(MSG_DEBUG, "RSN: Received SMK M4 (Initiator "
+			   MACSTR ")", MAC2STR(kde.mac_addr));
+
+		if (os_memcmp(kde.smk + PMK_LEN, peerkey->pnonce,
+			      WPA_NONCE_LEN) != 0) {
+			wpa_printf(MSG_INFO, "RSN: PNonce in SMK KDE does not "
+				   "match with the one used in SMK M3");
+			return -1;
+		}
+
+		if (os_memcmp(kde.nonce, peerkey->inonce, WPA_NONCE_LEN) != 0)
+		{
+			wpa_printf(MSG_INFO, "RSN: INonce in SMK M5 did not "
+				   "match with the one received in SMK M2");
+			return -1;
+		}
+	}
+
+	os_memcpy(peerkey->smk, kde.smk, PMK_LEN);
+	peerkey->smk_complete = 1;
+	wpa_hexdump_key(MSG_DEBUG, "RSN: SMK", peerkey->smk, PMK_LEN);
+	lifetime = WPA_GET_BE32(kde.lifetime);
+	wpa_printf(MSG_DEBUG, "RSN: SMK lifetime %u seconds", lifetime);
+	if (lifetime > 1000000000)
+		lifetime = 1000000000; /* avoid overflowing expiration time */
+	peerkey->lifetime = lifetime;
+	os_get_time(&now);
+	peerkey->expiration = now.sec + lifetime;
+	eloop_register_timeout(lifetime, 0, wpa_supplicant_smk_timeout,
+			       sm, peerkey);
+
+	if (peerkey->initiator) {
+		rsn_smkid(peerkey->smk, peerkey->pnonce, peerkey->addr,
+			  peerkey->inonce, sm->own_addr, peerkey->smkid);
+		wpa_supplicant_send_stk_1_of_4(sm, peerkey);
+	} else {
+		rsn_smkid(peerkey->smk, peerkey->pnonce, sm->own_addr,
+			  peerkey->inonce, peerkey->addr, peerkey->smkid);
+	}
+	wpa_hexdump(MSG_DEBUG, "RSN: SMKID", peerkey->smkid, PMKID_LEN);
+
+	return 0;
+}
+
+
+static int wpa_supplicant_process_smk_error(
+	struct wpa_sm *sm, const unsigned char *src_addr,
+	const struct wpa_eapol_key *key, size_t extra_len)
+{
+	struct wpa_ssid *ssid = sm->cur_ssid;
+	struct wpa_eapol_ie_parse kde;
+	struct rsn_error_kde error;
+	u8 peer[ETH_ALEN];
+	u16 error_type;
+
+	wpa_printf(MSG_DEBUG, "RSN: Received SMK Error");
+
+	if (ssid == NULL || !ssid->peerkey || sm->proto != WPA_PROTO_RSN) {
+		wpa_printf(MSG_DEBUG, "RSN: SMK handshake not allowed for "
+			   "the current network");
+		return -1;
+	}
+
+	if (wpa_supplicant_parse_ies((const u8 *) (key + 1), extra_len, &kde) <
+	    0) {
+		wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK Error");
+		return -1;
+	}
+
+	if (kde.error == NULL || kde.error_len < sizeof(error)) {
+		wpa_printf(MSG_INFO, "RSN: No Error KDE in SMK Error");
+		return -1;
+	}
+
+	if (kde.mac_addr && kde.mac_addr_len >= ETH_ALEN)
+		os_memcpy(peer, kde.mac_addr, ETH_ALEN);
+	os_memcpy(&error, kde.error, sizeof(error));
+	error_type = be_to_host16(error.error_type);
+	wpa_msg(sm->ctx->ctx, MSG_INFO,
+		"RSN: SMK Error KDE received: MUI %d error_type %d peer "
+		MACSTR,
+		be_to_host16(error.mui), error_type,
+		MAC2STR(peer));
+
+	if (kde.mac_addr &&
+	    (error_type == STK_ERR_STA_NR || error_type == STK_ERR_STA_NRSN ||
+	     error_type == STK_ERR_CPHR_NS)) {
+		struct wpa_peerkey *peerkey;
+
+		for (peerkey = sm->peerkey; peerkey; peerkey = peerkey->next) {
+			if (os_memcmp(peerkey->addr, kde.mac_addr, ETH_ALEN) ==
+			    0)
+				break;
+		}
+		if (peerkey == NULL) {
+			wpa_printf(MSG_DEBUG, "RSN: No matching SMK handshake "
+				   "found for SMK Error");
+			return -1;
+		}
+		/* TODO: abort SMK/STK handshake and remove all related keys */
+	}
+
+	return 0;
+}
+
+
+static void wpa_supplicant_process_stk_1_of_4(struct wpa_sm *sm,
+					      struct wpa_peerkey *peerkey,
+					      const struct wpa_eapol_key *key,
+					      u16 ver)
+{
+	struct wpa_eapol_ie_parse ie;
+	const u8 *kde;
+	size_t len, kde_buf_len;
+	struct wpa_ptk *stk;
+	u8 buf[8], *kde_buf, *pos;
+	u32 lifetime;
+
+	wpa_printf(MSG_DEBUG, "RSN: RX message 1 of STK 4-Way Handshake from "
+		   MACSTR " (ver=%d)", MAC2STR(peerkey->addr), ver);
+
+	os_memset(&ie, 0, sizeof(ie));
+
+	/* RSN: msg 1/4 should contain SMKID for the selected SMK */
+	kde = (const u8 *) (key + 1);
+	len = WPA_GET_BE16(key->key_data_length);
+	wpa_hexdump(MSG_DEBUG, "RSN: msg 1/4 key data", kde, len);
+	if (wpa_supplicant_parse_ies(kde, len, &ie) < 0 || ie.pmkid == NULL) {
+		wpa_printf(MSG_DEBUG, "RSN: No SMKID in STK 1/4");
+		return;
+	}
+	if (os_memcmp(ie.pmkid, peerkey->smkid, PMKID_LEN) != 0) {
+		wpa_hexdump(MSG_DEBUG, "RSN: Unknown SMKID in STK 1/4",
+			    ie.pmkid, PMKID_LEN);
+		return;
+	}
+
+	if (hostapd_get_rand(peerkey->pnonce, WPA_NONCE_LEN)) {
+		wpa_msg(sm->ctx->ctx, MSG_WARNING,
+			"RSN: Failed to get random data for PNonce");
+		return;
+	}
+	wpa_hexdump(MSG_DEBUG, "WPA: Renewed PNonce",
+		    peerkey->pnonce, WPA_NONCE_LEN);
+
+	/* Calculate STK which will be stored as a temporary STK until it has
+	 * been verified when processing message 3/4. */
+	stk = &peerkey->tstk;
+	wpa_pmk_to_ptk(peerkey->smk, PMK_LEN, "Peer key expansion",
+		       sm->own_addr, peerkey->addr,
+		       peerkey->pnonce, key->key_nonce,
+		       (u8 *) stk, sizeof(*stk));
+	/* Supplicant: swap tx/rx Mic keys */
+	os_memcpy(buf, stk->u.auth.tx_mic_key, 8);
+	os_memcpy(stk->u.auth.tx_mic_key, stk->u.auth.rx_mic_key, 8);
+	os_memcpy(stk->u.auth.rx_mic_key, buf, 8);
+	peerkey->tstk_set = 1;
+
+	kde_buf_len = peerkey->rsnie_p_len +
+		2 + RSN_SELECTOR_LEN + sizeof(lifetime) +
+		2 + RSN_SELECTOR_LEN + PMKID_LEN;
+	kde_buf = os_malloc(kde_buf_len);
+	if (kde_buf == NULL)
+		return;
+	pos = kde_buf;
+	pos = wpa_add_ie(pos, peerkey->rsnie_p, peerkey->rsnie_p_len);
+	lifetime = host_to_be32(peerkey->lifetime);
+	pos = wpa_add_kde(pos, RSN_KEY_DATA_LIFETIME,
+			  (u8 *) &lifetime, sizeof(lifetime));
+	pos = wpa_add_kde(pos, RSN_KEY_DATA_PMKID, peerkey->smkid, PMKID_LEN);
+
+	if (wpa_supplicant_send_2_of_4(sm, peerkey->addr, key, ver,
+				       peerkey->pnonce, kde_buf, kde_buf_len,
+				       stk)) {
+		os_free(kde_buf);
+		return;
+	}
+	os_free(kde_buf);
+
+	os_memcpy(peerkey->inonce, key->key_nonce, WPA_NONCE_LEN);
+}
+
+
+static void wpa_supplicant_update_smk_lifetime(struct wpa_sm *sm,
+					       struct wpa_peerkey *peerkey,
+					       struct wpa_eapol_ie_parse *kde)
+{
+	u32 lifetime;
+	struct os_time now;
+
+	if (kde->lifetime == NULL || kde->lifetime_len < sizeof(lifetime))
+		return;
+
+	lifetime = WPA_GET_BE32(kde->lifetime);
+
+	if (lifetime >= peerkey->lifetime) {
+		wpa_printf(MSG_DEBUG, "RSN: Peer used SMK lifetime %u seconds "
+			   "which is larger than or equal to own value %u "
+			   "seconds - ignored", lifetime, peerkey->lifetime);
+		return;
+	}
+
+	wpa_printf(MSG_DEBUG, "RSN: Peer used shorter SMK lifetime %u seconds "
+		   "(own was %u seconds) - updated",
+		   lifetime, peerkey->lifetime);
+	peerkey->lifetime = lifetime;
+
+	os_get_time(&now);
+	peerkey->expiration = now.sec + lifetime;
+	eloop_cancel_timeout(wpa_supplicant_smk_timeout, sm, peerkey);
+	eloop_register_timeout(lifetime, 0, wpa_supplicant_smk_timeout,
+			       sm, peerkey);
+}
+
+
+static void wpa_supplicant_process_stk_2_of_4(struct wpa_sm *sm,
+					      struct wpa_peerkey *peerkey,
+					      const struct wpa_eapol_key *key,
+					      u16 ver)
+{
+	struct wpa_eapol_ie_parse kde;
+	const u8 *keydata;
+	size_t len;
+
+	wpa_printf(MSG_DEBUG, "RSN: RX message 2 of STK 4-Way Handshake from "
+		   MACSTR " (ver=%d)", MAC2STR(peerkey->addr), ver);
+
+	os_memset(&kde, 0, sizeof(kde));
+
+	/* RSN: msg 2/4 should contain SMKID for the selected SMK and RSN IE
+	 * from the peer. It may also include Lifetime KDE. */
+	keydata = (const u8 *) (key + 1);
+	len = WPA_GET_BE16(key->key_data_length);
+	wpa_hexdump(MSG_DEBUG, "RSN: msg 2/4 key data", keydata, len);
+	if (wpa_supplicant_parse_ies(keydata, len, &kde) < 0 ||
+	    kde.pmkid == NULL || kde.rsn_ie == NULL) {
+		wpa_printf(MSG_DEBUG, "RSN: No SMKID or RSN IE in STK 2/4");
+		return;
+	}
+
+	if (os_memcmp(kde.pmkid, peerkey->smkid, PMKID_LEN) != 0) {
+		wpa_hexdump(MSG_DEBUG, "RSN: Unknown SMKID in STK 2/4",
+			    kde.pmkid, PMKID_LEN);
+		return;
+	}
+
+	if (kde.rsn_ie_len != peerkey->rsnie_p_len ||
+	    os_memcmp(kde.rsn_ie, peerkey->rsnie_p, kde.rsn_ie_len) != 0) {
+		wpa_printf(MSG_INFO, "RSN: Peer RSN IE in SMK and STK "
+			   "handshakes did not match");
+		wpa_hexdump(MSG_DEBUG, "RSN: Peer RSN IE in SMK handshake",
+			    peerkey->rsnie_p, peerkey->rsnie_p_len);
+		wpa_hexdump(MSG_DEBUG, "RSN: Peer RSN IE in STK handshake",
+			    kde.rsn_ie, kde.rsn_ie_len);
+		return;
+	}
+
+	wpa_supplicant_update_smk_lifetime(sm, peerkey, &kde);
+
+	wpa_supplicant_send_stk_3_of_4(sm, peerkey);
+	os_memcpy(peerkey->pnonce, key->key_nonce, WPA_NONCE_LEN);
+}
+
+
+static void wpa_supplicant_process_stk_3_of_4(struct wpa_sm *sm,
+					      struct wpa_peerkey *peerkey,
+					      const struct wpa_eapol_key *key,
+					      u16 ver)
+{
+	struct wpa_eapol_ie_parse kde;
+	const u8 *keydata;
+	size_t len, key_len;
+	const u8 *_key;
+	u8 key_buf[32], rsc[6];
+
+	wpa_printf(MSG_DEBUG, "RSN: RX message 3 of STK 4-Way Handshake from "
+		   MACSTR " (ver=%d)", MAC2STR(peerkey->addr), ver);
+
+	os_memset(&kde, 0, sizeof(kde));
+
+	/* RSN: msg 3/4 should contain Initiator RSN IE. It may also include
+	 * Lifetime KDE. */
+	keydata = (const u8 *) (key + 1);
+	len = WPA_GET_BE16(key->key_data_length);
+	wpa_hexdump(MSG_DEBUG, "RSN: msg 3/4 key data", keydata, len);
+	if (wpa_supplicant_parse_ies(keydata, len, &kde) < 0) {
+		wpa_printf(MSG_DEBUG, "RSN: Failed to parse key data in "
+			   "STK 3/4");
+		return;
+	}
+
+	if (kde.rsn_ie_len != peerkey->rsnie_i_len ||
+	    os_memcmp(kde.rsn_ie, peerkey->rsnie_i, kde.rsn_ie_len) != 0) {
+		wpa_printf(MSG_INFO, "RSN: Initiator RSN IE in SMK and STK "
+			   "handshakes did not match");
+		wpa_hexdump(MSG_DEBUG, "RSN: Initiator RSN IE in SMK "
+			    "handshake",
+			    peerkey->rsnie_i, peerkey->rsnie_i_len);
+		wpa_hexdump(MSG_DEBUG, "RSN: Initiator RSN IE in STK "
+			    "handshake",
+			    kde.rsn_ie, kde.rsn_ie_len);
+		return;
+	}
+
+	if (os_memcmp(peerkey->inonce, key->key_nonce, WPA_NONCE_LEN) != 0) {
+		wpa_printf(MSG_WARNING, "RSN: INonce from message 1 of STK "
+			   "4-Way Handshake differs from 3 of STK 4-Way "
+			   "Handshake - drop packet (src=" MACSTR ")",
+			   MAC2STR(peerkey->addr));
+		return;
+	}
+
+	wpa_supplicant_update_smk_lifetime(sm, peerkey, &kde);
+
+	if (wpa_supplicant_send_4_of_4(sm, peerkey->addr, key, ver,
+				       WPA_GET_BE16(key->key_info),
+				       NULL, 0, &peerkey->stk))
+		return;
+
+	_key = (u8 *) peerkey->stk.tk1;
+	if (peerkey->cipher == WPA_CIPHER_TKIP) {
+		/* Swap Tx/Rx keys for Michael MIC */
+		os_memcpy(key_buf, _key, 16);
+		os_memcpy(key_buf + 16, _key + 24, 8);
+		os_memcpy(key_buf + 24, _key + 16, 8);
+		_key = key_buf;
+		key_len = 32;
+	} else
+		key_len = 16;
+
+	os_memset(rsc, 0, 6);
+	if (wpa_sm_set_key(sm, peerkey->cipher, peerkey->addr, 0, 1,
+			   rsc, sizeof(rsc), _key, key_len) < 0) {
+		wpa_printf(MSG_WARNING, "RSN: Failed to set STK to the "
+			   "driver.");
+		return;
+	}
+}
+
+
+static void wpa_supplicant_process_stk_4_of_4(struct wpa_sm *sm,
+					      struct wpa_peerkey *peerkey,
+					      const struct wpa_eapol_key *key,
+					      u16 ver)
+{
+	u8 rsc[6];
+
+	wpa_printf(MSG_DEBUG, "RSN: RX message 4 of STK 4-Way Handshake from "
+		   MACSTR " (ver=%d)", MAC2STR(peerkey->addr), ver);
+
+	os_memset(rsc, 0, 6);
+	if (wpa_sm_set_key(sm, peerkey->cipher, peerkey->addr, 0, 1,
+			   rsc, sizeof(rsc), (u8 *) peerkey->stk.tk1,
+			   peerkey->cipher == WPA_CIPHER_TKIP ? 32 : 16) < 0) {
+		wpa_printf(MSG_WARNING, "RSN: Failed to set STK to the "
+			   "driver.");
+		return;
+	}
+}
+#endif /* CONFIG_PEERKEY */
+
+
+static int wpa_supplicant_process_1_of_2_rsn(struct wpa_sm *sm,
+					     const u8 *keydata,
+					     size_t keydatalen,
+					     u16 key_info,
+					     struct wpa_gtk_data *gd)
+{
+	int maxkeylen;
+	struct wpa_eapol_ie_parse ie;
+
+	wpa_hexdump(MSG_DEBUG, "RSN: msg 1/2 key data", keydata, keydatalen);
+	wpa_supplicant_parse_ies(keydata, keydatalen, &ie);
+	if (ie.gtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
+		wpa_printf(MSG_WARNING, "WPA: GTK IE in unencrypted key data");
+		return -1;
+	}
+	if (ie.gtk == NULL) {
+		wpa_printf(MSG_INFO, "WPA: No GTK IE in Group Key msg 1/2");
+		return -1;
+	}
+	maxkeylen = gd->gtk_len = ie.gtk_len - 2;
+
+	if (wpa_supplicant_check_group_cipher(sm->group_cipher,
+					      gd->gtk_len, maxkeylen,
+					      &gd->key_rsc_len, &gd->alg))
+		return -1;
+
+	wpa_hexdump(MSG_DEBUG, "RSN: received GTK in group key handshake",
+		    ie.gtk, ie.gtk_len);
 	gd->keyidx = ie.gtk[0] & 0x3;
 	gd->tx = wpa_supplicant_gtk_tx_bit_workaround(sm,
 						      !!(ie.gtk[0] & BIT(2)));
@@ -1623,7 +2997,10 @@
 			   "(len=%lu)", (unsigned long) ie.gtk_len - 2);
 		return -1;
 	}
-	memcpy(gd->gtk, ie.gtk + 2, ie.gtk_len - 2);
+	os_memcpy(gd->gtk, ie.gtk + 2, ie.gtk_len - 2);
+
+	if (ieee80211w_set_keys(sm, &ie) < 0)
+		wpa_printf(MSG_INFO, "RSN: Failed to configure DHV/IGTK");
 
 	return 0;
 }
@@ -1632,22 +3009,29 @@
 static int wpa_supplicant_process_1_of_2_wpa(struct wpa_sm *sm,
 					     const struct wpa_eapol_key *key,
 					     size_t keydatalen, int key_info,
-					     int extra_len, u16 ver,
+					     size_t extra_len, u16 ver,
 					     struct wpa_gtk_data *gd)
 {
-	int maxkeylen;
+	size_t maxkeylen;
 	u8 ek[32];
 
 	gd->gtk_len = WPA_GET_BE16(key->key_length);
 	maxkeylen = keydatalen;
 	if (keydatalen > extra_len) {
 		wpa_printf(MSG_INFO, "WPA: Truncated EAPOL-Key packet:"
-			   " key_data_length=%lu > extra_len=%d",
-			   (unsigned long) keydatalen, extra_len);
+			   " key_data_length=%lu > extra_len=%lu",
+			   (unsigned long) keydatalen,
+			   (unsigned long) extra_len);
 		return -1;
 	}
-	if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES)
+	if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
+		if (maxkeylen < 8) {
+			wpa_printf(MSG_INFO, "WPA: Too short maxkeylen (%lu)",
+				   (unsigned long) maxkeylen);
+			return -1;
+		}
 		maxkeylen -= 8;
+	}
 
 	if (wpa_supplicant_check_group_cipher(sm->group_cipher,
 					      gd->gtk_len, maxkeylen,
@@ -1657,15 +3041,15 @@
 	gd->keyidx = (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) >>
 		WPA_KEY_INFO_KEY_INDEX_SHIFT;
 	if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4) {
-		memcpy(ek, key->key_iv, 16);
-		memcpy(ek + 16, sm->ptk.kek, 16);
+		os_memcpy(ek, key->key_iv, 16);
+		os_memcpy(ek + 16, sm->ptk.kek, 16);
 		if (keydatalen > sizeof(gd->gtk)) {
 			wpa_printf(MSG_WARNING, "WPA: RC4 key data "
 				   "too long (%lu)",
 				   (unsigned long) keydatalen);
 			return -1;
 		}
-		memcpy(gd->gtk, key + 1, keydatalen);
+		os_memcpy(gd->gtk, key + 1, keydatalen);
 		rc4_skip(ek, 32, 256, gd->gtk, keydatalen);
 	} else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
 		if (keydatalen % 8) {
@@ -1694,7 +3078,6 @@
 
 
 static int wpa_supplicant_send_2_of_2(struct wpa_sm *sm,
-				      const unsigned char *src_addr,
 				      const struct wpa_eapol_key *key,
 				      int ver, u16 key_info)
 {
@@ -1715,14 +3098,14 @@
 	if (sm->proto == WPA_PROTO_RSN)
 		WPA_PUT_BE16(reply->key_length, 0);
 	else
-		memcpy(reply->key_length, key->key_length, 2);
-	memcpy(reply->replay_counter, key->replay_counter,
-	       WPA_REPLAY_COUNTER_LEN);
+		os_memcpy(reply->key_length, key->key_length, 2);
+	os_memcpy(reply->replay_counter, key->replay_counter,
+		  WPA_REPLAY_COUNTER_LEN);
 
 	WPA_PUT_BE16(reply->key_data_length, 0);
 
 	wpa_printf(MSG_DEBUG, "WPA: Sending EAPOL-Key 2/2");
-	wpa_eapol_key_send(sm, sm->ptk.kck, ver, src_addr, ETH_P_EAPOL,
+	wpa_eapol_key_send(sm, sm->ptk.kck, ver, sm->bssid, ETH_P_EAPOL,
 			   rbuf, rlen, reply->key_mic);
 
 	return 0;
@@ -1735,13 +3118,12 @@
 					  int extra_len, u16 ver)
 {
 	u16 key_info, keydatalen;
-	int rekey;
+	int rekey, ret;
 	struct wpa_gtk_data gd;
 
-	memset(&gd, 0, sizeof(gd));
+	os_memset(&gd, 0, sizeof(gd));
 
 	rekey = wpa_sm_get_state(sm) == WPA_COMPLETED;
-	wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE);
 	wpa_printf(MSG_DEBUG, "WPA: RX message 1 of Group Key Handshake from "
 		   MACSTR " (ver=%d)", MAC2STR(src_addr), ver);
 
@@ -1749,29 +3131,32 @@
 	keydatalen = WPA_GET_BE16(key->key_data_length);
 
 	if (sm->proto == WPA_PROTO_RSN) {
-		if (wpa_supplicant_process_1_of_2_rsn(sm,
-						      (const u8 *) (key + 1),
-						      keydatalen, key_info,
-						      &gd))
-			return;
+		ret = wpa_supplicant_process_1_of_2_rsn(sm,
+							(const u8 *) (key + 1),
+							keydatalen, key_info,
+							&gd);
 	} else {
-		if (wpa_supplicant_process_1_of_2_wpa(sm, key, keydatalen,
-						      key_info, extra_len,
-						      ver, &gd))
-			return;
+		ret = wpa_supplicant_process_1_of_2_wpa(sm, key, keydatalen,
+							key_info, extra_len,
+							ver, &gd);
 	}
 
+	wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE);
+
+	if (ret)
+		return;
+
 	if (wpa_supplicant_install_gtk(sm, &gd, key->key_rsc) ||
-	    wpa_supplicant_send_2_of_2(sm, src_addr, key, ver, key_info))
+	    wpa_supplicant_send_2_of_2(sm, key, ver, key_info))
 		return;
 
 	if (rekey) {
 		wpa_msg(sm->ctx->ctx, MSG_INFO, "WPA: Group rekeying "
 			"completed with " MACSTR " [GTK=%s]",
-			MAC2STR(src_addr), wpa_cipher_txt(sm->group_cipher));
+			MAC2STR(sm->bssid), wpa_cipher_txt(sm->group_cipher));
 		wpa_sm_set_state(sm, WPA_COMPLETED);
 	} else {
-		wpa_supplicant_key_neg_complete(sm, src_addr,
+		wpa_supplicant_key_neg_complete(sm, sm->bssid,
 						key_info &
 						WPA_KEY_INFO_SECURE);
 	}
@@ -1786,27 +3171,27 @@
 	u8 mic[16];
 	int ok = 0;
 
-	memcpy(mic, key->key_mic, 16);
+	os_memcpy(mic, key->key_mic, 16);
 	if (sm->tptk_set) {
-		memset(key->key_mic, 0, 16);
+		os_memset(key->key_mic, 0, 16);
 		wpa_eapol_key_mic(sm->tptk.kck, ver, buf, len,
 				  key->key_mic);
-		if (memcmp(mic, key->key_mic, 16) != 0) {
+		if (os_memcmp(mic, key->key_mic, 16) != 0) {
 			wpa_printf(MSG_WARNING, "WPA: Invalid EAPOL-Key MIC "
 				   "when using TPTK - ignoring TPTK");
 		} else {
 			ok = 1;
 			sm->tptk_set = 0;
 			sm->ptk_set = 1;
-			memcpy(&sm->ptk, &sm->tptk, sizeof(sm->ptk));
+			os_memcpy(&sm->ptk, &sm->tptk, sizeof(sm->ptk));
 		}
 	}
 
 	if (!ok && sm->ptk_set) {
-		memset(key->key_mic, 0, 16);
+		os_memset(key->key_mic, 0, 16);
 		wpa_eapol_key_mic(sm->ptk.kck, ver, buf, len,
 				  key->key_mic);
-		if (memcmp(mic, key->key_mic, 16) != 0) {
+		if (os_memcmp(mic, key->key_mic, 16) != 0) {
 			wpa_printf(MSG_WARNING, "WPA: Invalid EAPOL-Key MIC "
 				   "- dropping packet");
 			return -1;
@@ -1820,13 +3205,72 @@
 		return -1;
 	}
 
-	memcpy(sm->rx_replay_counter, key->replay_counter,
-	       WPA_REPLAY_COUNTER_LEN);
+	os_memcpy(sm->rx_replay_counter, key->replay_counter,
+		  WPA_REPLAY_COUNTER_LEN);
 	sm->rx_replay_counter_set = 1;
 	return 0;
 }
 
 
+#ifdef CONFIG_PEERKEY
+static int wpa_supplicant_verify_eapol_key_mic_peerkey(
+	struct wpa_sm *sm, struct wpa_peerkey *peerkey,
+	struct wpa_eapol_key *key, u16 ver, const u8 *buf, size_t len)
+{
+	u8 mic[16];
+	int ok = 0;
+
+	if (peerkey->initiator && !peerkey->stk_set) {
+		wpa_pmk_to_ptk(peerkey->smk, PMK_LEN, "Peer key expansion",
+			       sm->own_addr, peerkey->addr,
+			       peerkey->inonce, key->key_nonce,
+			       (u8 *) &peerkey->stk, sizeof(peerkey->stk));
+		peerkey->stk_set = 1;
+	}
+
+	os_memcpy(mic, key->key_mic, 16);
+	if (peerkey->tstk_set) {
+		os_memset(key->key_mic, 0, 16);
+		wpa_eapol_key_mic(peerkey->tstk.kck, ver, buf, len,
+				  key->key_mic);
+		if (os_memcmp(mic, key->key_mic, 16) != 0) {
+			wpa_printf(MSG_WARNING, "RSN: Invalid EAPOL-Key MIC "
+				   "when using TSTK - ignoring TSTK");
+		} else {
+			ok = 1;
+			peerkey->tstk_set = 0;
+			peerkey->stk_set = 1;
+			os_memcpy(&peerkey->stk, &peerkey->tstk,
+				  sizeof(peerkey->stk));
+		}
+	}
+
+	if (!ok && peerkey->stk_set) {
+		os_memset(key->key_mic, 0, 16);
+		wpa_eapol_key_mic(peerkey->stk.kck, ver, buf, len,
+				  key->key_mic);
+		if (os_memcmp(mic, key->key_mic, 16) != 0) {
+			wpa_printf(MSG_WARNING, "RSN: Invalid EAPOL-Key MIC "
+				   "- dropping packet");
+			return -1;
+		}
+		ok = 1;
+	}
+
+	if (!ok) {
+		wpa_printf(MSG_WARNING, "RSN: Could not verify EAPOL-Key MIC "
+			   "- dropping packet");
+		return -1;
+	}
+
+	os_memcpy(peerkey->replay_counter, key->replay_counter,
+		  WPA_REPLAY_COUNTER_LEN);
+	peerkey->replay_counter_set = 1;
+	return 0;
+}
+#endif /* CONFIG_PEERKEY */
+
+
 /* Decrypt RSN EAPOL-Key key data (RC4 or AES-WRAP) */
 static int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm,
 					   struct wpa_eapol_key *key, u16 ver)
@@ -1845,8 +3289,8 @@
 	 * to be implemented separately for each message type. */
 	if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4) {
 		u8 ek[32];
-		memcpy(ek, key->key_iv, 16);
-		memcpy(ek + 16, sm->ptk.kek, 16);
+		os_memcpy(ek, key->key_iv, 16);
+		os_memcpy(ek + 16, sm->ptk.kek, 16);
 		rc4_skip(ek, 32, 256, (u8 *) (key + 1), keydatalen);
 	} else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
 		u8 *buf;
@@ -1856,7 +3300,7 @@
 			return -1;
 		}
 		keydatalen -= 8; /* AES-WRAP adds 8 bytes */
-		buf = malloc(keydatalen);
+		buf = os_malloc(keydatalen);
 		if (buf == NULL) {
 			wpa_printf(MSG_WARNING, "WPA: No memory for "
 				   "AES-UNWRAP buffer");
@@ -1864,13 +3308,13 @@
 		}
 		if (aes_unwrap(sm->ptk.kek, keydatalen / 8,
 			       (u8 *) (key + 1), buf)) {
-			free(buf);
+			os_free(buf);
 			wpa_printf(MSG_WARNING, "WPA: AES unwrap failed - "
 				   "could not decrypt EAPOL-Key key data");
 			return -1;
 		}
-		memcpy(key + 1, buf, keydatalen);
-		free(buf);
+		os_memcpy(key + 1, buf, keydatalen);
+		os_free(buf);
 		WPA_PUT_BE16(key->key_data_length, keydatalen);
 	}
 	wpa_hexdump_key(MSG_DEBUG, "WPA: decrypted EAPOL-Key key data",
@@ -1880,6 +3324,53 @@
 
 
 /**
+ * wpa_sm_aborted_cached - Notify WPA that PMKSA caching was aborted
+ * @sm: Pointer to WPA state machine data from wpa_sm_init()
+ */
+void wpa_sm_aborted_cached(struct wpa_sm *sm)
+{
+	if (sm && sm->cur_pmksa) {
+		wpa_printf(MSG_DEBUG, "RSN: Cancelling PMKSA caching attempt");
+		sm->cur_pmksa = NULL;
+	}
+}
+
+
+static void wpa_eapol_key_dump(const struct wpa_eapol_key *key)
+{
+#ifndef CONFIG_NO_STDOUT_DEBUG
+	u16 key_info = WPA_GET_BE16(key->key_info);
+
+	wpa_printf(MSG_DEBUG, "  EAPOL-Key type=%d", key->type);
+	wpa_printf(MSG_DEBUG, "  key_info 0x%x (ver=%d keyidx=%d rsvd=%d %s"
+		   "%s%s%s%s%s%s%s)",
+		   key_info, key_info & WPA_KEY_INFO_TYPE_MASK,
+		   (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) >>
+		   WPA_KEY_INFO_KEY_INDEX_SHIFT,
+		   (key_info & (BIT(13) | BIT(14) | BIT(15))) >> 13,
+		   key_info & WPA_KEY_INFO_KEY_TYPE ? "Pairwise" : "Group",
+		   key_info & WPA_KEY_INFO_INSTALL ? " Install" : "",
+		   key_info & WPA_KEY_INFO_ACK ? " Ack" : "",
+		   key_info & WPA_KEY_INFO_MIC ? " MIC" : "",
+		   key_info & WPA_KEY_INFO_SECURE ? " Secure" : "",
+		   key_info & WPA_KEY_INFO_ERROR ? " Error" : "",
+		   key_info & WPA_KEY_INFO_REQUEST ? " Request" : "",
+		   key_info & WPA_KEY_INFO_ENCR_KEY_DATA ? " Encr" : "");
+	wpa_printf(MSG_DEBUG, "  key_length=%u key_data_length=%u",
+		   WPA_GET_BE16(key->key_length),
+		   WPA_GET_BE16(key->key_data_length));
+	wpa_hexdump(MSG_DEBUG, "  replay_counter",
+		    key->replay_counter, WPA_REPLAY_COUNTER_LEN);
+	wpa_hexdump(MSG_DEBUG, "  key_nonce", key->key_nonce, WPA_NONCE_LEN);
+	wpa_hexdump(MSG_DEBUG, "  key_iv", key->key_iv, 16);
+	wpa_hexdump(MSG_DEBUG, "  key_rsc", key->key_rsc, 8);
+	wpa_hexdump(MSG_DEBUG, "  key_id (reserved)", key->key_id, 8);
+	wpa_hexdump(MSG_DEBUG, "  key_mic", key->key_mic, 16);
+#endif /* CONFIG_NO_STDOUT_DEBUG */
+}
+
+
+/**
  * wpa_sm_rx_eapol - Process received WPA EAPOL frames
  * @sm: Pointer to WPA state machine data from wpa_sm_init()
  * @src_addr: Source MAC address of the EAPOL packet
@@ -1904,6 +3395,7 @@
 	u16 key_info, ver;
 	u8 *tmp;
 	int ret = -1;
+	struct wpa_peerkey *peerkey = NULL;
 
 	if (len < sizeof(*hdr) + sizeof(*key)) {
 		wpa_printf(MSG_DEBUG, "WPA: EAPOL frame too short to be a WPA "
@@ -1913,14 +3405,14 @@
 		return 0;
 	}
 
-	tmp = malloc(len);
+	tmp = os_malloc(len);
 	if (tmp == NULL)
 		return -1;
-	memcpy(tmp, buf, len);
+	os_memcpy(tmp, buf, len);
 
 	hdr = (struct ieee802_1x_hdr *) tmp;
 	key = (struct wpa_eapol_key *) (hdr + 1);
-	plen = ntohs(hdr->length);
+	plen = be_to_host16(hdr->length);
 	data_len = plen + sizeof(*hdr);
 	wpa_printf(MSG_DEBUG, "IEEE 802.1X RX: version=%d type=%d length=%lu",
 		   hdr->version, hdr->type, (unsigned long) plen);
@@ -1931,12 +3423,6 @@
 	if (hdr->type != IEEE802_1X_TYPE_EAPOL_KEY) {
 		wpa_printf(MSG_DEBUG, "WPA: EAPOL frame (type %u) discarded, "
 			"not a Key frame", hdr->type);
-		if (sm->cur_pmksa) {
-			wpa_printf(MSG_DEBUG, "WPA: Cancelling PMKSA caching "
-				   "attempt - attempt full EAP "
-				   "authentication");
-			eapol_sm_notify_pmkid_attempt(sm->eapol, 0);
-		}
 		ret = 0;
 		goto out;
 	}
@@ -1948,7 +3434,6 @@
 		goto out;
 	}
 
-	wpa_printf(MSG_DEBUG, "  EAPOL-Key type=%d", key->type);
 	if (key->type != EAPOL_KEY_TYPE_WPA && key->type != EAPOL_KEY_TYPE_RSN)
 	{
 		wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key type (%d) unknown, "
@@ -1956,6 +3441,7 @@
 		ret = 0;
 		goto out;
 	}
+	wpa_eapol_key_dump(key);
 
 	eapol_sm_notify_lower_layer_success(sm->eapol);
 	wpa_hexdump(MSG_MSGDUMP, "WPA: RX EAPOL-Key", tmp, len);
@@ -1989,15 +3475,54 @@
 			goto out;
 	}
 
-	if (sm->rx_replay_counter_set &&
-	    memcmp(key->replay_counter, sm->rx_replay_counter,
-		   WPA_REPLAY_COUNTER_LEN) <= 0) {
+#ifdef CONFIG_PEERKEY
+	for (peerkey = sm->peerkey; peerkey; peerkey = peerkey->next) {
+		if (os_memcmp(peerkey->addr, src_addr, ETH_ALEN) == 0)
+			break;
+	}
+
+	if (!(key_info & WPA_KEY_INFO_SMK_MESSAGE) && peerkey) {
+		if (!peerkey->initiator && peerkey->replay_counter_set &&
+		    os_memcmp(key->replay_counter, peerkey->replay_counter,
+			      WPA_REPLAY_COUNTER_LEN) <= 0) {
+			wpa_printf(MSG_WARNING, "RSN: EAPOL-Key Replay "
+				   "Counter did not increase (STK) - dropping "
+				   "packet");
+			goto out;
+		} else if (peerkey->initiator) {
+			u8 _tmp[WPA_REPLAY_COUNTER_LEN];
+			os_memcpy(_tmp, key->replay_counter,
+				  WPA_REPLAY_COUNTER_LEN);
+			inc_byte_array(_tmp, WPA_REPLAY_COUNTER_LEN);
+			if (os_memcmp(_tmp, peerkey->replay_counter,
+				      WPA_REPLAY_COUNTER_LEN) != 0) {
+				wpa_printf(MSG_DEBUG, "RSN: EAPOL-Key Replay "
+					   "Counter did not match (STK) - "
+					   "dropping packet");
+				goto out;
+			}
+		}
+	}
+
+	if (peerkey && peerkey->initiator && (key_info & WPA_KEY_INFO_ACK)) {
+		wpa_printf(MSG_INFO, "RSN: Ack bit in key_info from STK peer");
+		goto out;
+	}
+#endif /* CONFIG_PEERKEY */
+
+	if (!peerkey && sm->rx_replay_counter_set &&
+	    os_memcmp(key->replay_counter, sm->rx_replay_counter,
+		      WPA_REPLAY_COUNTER_LEN) <= 0) {
 		wpa_printf(MSG_WARNING, "WPA: EAPOL-Key Replay Counter did not"
 			   " increase - dropping packet");
 		goto out;
 	}
 
-	if (!(key_info & WPA_KEY_INFO_ACK)) {
+	if (!(key_info & (WPA_KEY_INFO_ACK | WPA_KEY_INFO_SMK_MESSAGE))
+#ifdef CONFIG_PEERKEY
+	    && (peerkey == NULL || !peerkey->initiator)
+#endif /* CONFIG_PEERKEY */
+		) {
 		wpa_printf(MSG_INFO, "WPA: No Ack bit in key_info");
 		goto out;
 	}
@@ -2008,10 +3533,17 @@
 		goto out;
 	}
 
-	if ((key_info & WPA_KEY_INFO_MIC) &&
+	if ((key_info & WPA_KEY_INFO_MIC) && !peerkey &&
 	    wpa_supplicant_verify_eapol_key_mic(sm, key, ver, tmp, data_len))
 		goto out;
 
+#ifdef CONFIG_PEERKEY
+	if ((key_info & WPA_KEY_INFO_MIC) && peerkey &&
+	    wpa_supplicant_verify_eapol_key_mic_peerkey(
+		    sm, peerkey, key, ver, tmp, data_len))
+		goto out;
+#endif /* CONFIG_PEERKEY */
+
 	extra_len = data_len - sizeof(*hdr) - sizeof(*key);
 
 	if (WPA_GET_BE16(key->key_data_length) > extra_len) {
@@ -2021,11 +3553,14 @@
 			(unsigned long) extra_len);
 		goto out;
 	}
+	extra_len = WPA_GET_BE16(key->key_data_length);
 
 	if (sm->proto == WPA_PROTO_RSN &&
-	    (key_info & WPA_KEY_INFO_ENCR_KEY_DATA) &&
-	    wpa_supplicant_decrypt_key_data(sm, key, ver))
-		goto out;
+	    (key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
+		if (wpa_supplicant_decrypt_key_data(sm, key, ver))
+			goto out;
+		extra_len = WPA_GET_BE16(key->key_data_length);
+	}
 
 	if (key_info & WPA_KEY_INFO_KEY_TYPE) {
 		if (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) {
@@ -2033,15 +3568,52 @@
 				   "(Pairwise) with non-zero key index");
 			goto out;
 		}
+#ifdef CONFIG_PEERKEY
+		if (peerkey) {
+			if ((key_info & (WPA_KEY_INFO_MIC | WPA_KEY_INFO_ACK))
+			    == (WPA_KEY_INFO_MIC | WPA_KEY_INFO_ACK)) {
+				/* 3/4 STK 4-Way Handshake */
+				wpa_supplicant_process_stk_3_of_4(sm, peerkey,
+								  key, ver);
+			} else if (key_info & WPA_KEY_INFO_ACK) {
+				/* 1/4 STK 4-Way Handshake */
+				wpa_supplicant_process_stk_1_of_4(sm, peerkey,
+								  key, ver);
+			} else if (key_info & WPA_KEY_INFO_SECURE) {
+				/* 4/4 STK 4-Way Handshake */
+				wpa_supplicant_process_stk_4_of_4(sm, peerkey,
+								  key, ver);
+			} else {
+				/* 2/4 STK 4-Way Handshake */
+				wpa_supplicant_process_stk_2_of_4(sm, peerkey,
+								  key, ver);
+			}
+		} else
+#endif /* CONFIG_PEERKEY */
 		if (key_info & WPA_KEY_INFO_MIC) {
 			/* 3/4 4-Way Handshake */
-			wpa_supplicant_process_3_of_4(sm, src_addr, key,
-						      extra_len, ver);
+			wpa_supplicant_process_3_of_4(sm, key, ver);
 		} else {
 			/* 1/4 4-Way Handshake */
 			wpa_supplicant_process_1_of_4(sm, src_addr, key,
 						      ver);
 		}
+	} else if (key_info & WPA_KEY_INFO_SMK_MESSAGE) {
+#ifdef CONFIG_PEERKEY
+		if (key_info & WPA_KEY_INFO_ERROR) {
+			/* SMK Error */
+			wpa_supplicant_process_smk_error(sm, src_addr, key,
+							 extra_len);
+		} else if (key_info & WPA_KEY_INFO_ACK) {
+			/* SMK M2 */
+			wpa_supplicant_process_smk_m2(sm, src_addr, key,
+						      extra_len, ver);
+		} else {
+			/* SMK M4 or M5 */
+			wpa_supplicant_process_smk_m45(sm, src_addr, key,
+						       extra_len, ver);
+		}
+#endif /* CONFIG_PEERKEY */
 	} else {
 		if (key_info & WPA_KEY_INFO_MIC) {
 			/* 1/2 Group Key Handshake */
@@ -2056,11 +3628,12 @@
 	ret = 1;
 
 out:
-	free(tmp);
+	os_free(tmp);
 	return ret;
 }
 
 
+#ifdef CONFIG_CTRL_IFACE
 static int wpa_cipher_bits(int cipher)
 {
 	switch (cipher) {
@@ -2137,15 +3710,13 @@
  */
 int wpa_sm_get_mib(struct wpa_sm *sm, char *buf, size_t buflen)
 {
-	int len, i;
 	char pmkid_txt[PMKID_LEN * 2 + 1];
-	int rsna;
+	int rsna, ret;
+	size_t len;
 
 	if (sm->cur_pmksa) {
-		char *pos = pmkid_txt;
-		for (i = 0; i < PMKID_LEN; i++) {
-			pos += sprintf(pos, "%02x", sm->cur_pmksa->pmkid[i]);
-		}
+		wpa_snprintf_hex(pmkid_txt, sizeof(pmkid_txt),
+				 sm->cur_pmksa->pmkid, PMKID_LEN);
 	} else
 		pmkid_txt[0] = '\0';
 
@@ -2156,51 +3727,85 @@
 	else
 		rsna = 0;
 
-	len = snprintf(buf, buflen,
-		       "dot11RSNAOptionImplemented=TRUE\n"
-		       "dot11RSNAPreauthenticationImplemented=TRUE\n"
-		       "dot11RSNAEnabled=%s\n"
-		       "dot11RSNAPreauthenticationEnabled=%s\n"
-		       "dot11RSNAConfigVersion=%d\n"
-		       "dot11RSNAConfigPairwiseKeysSupported=5\n"
-		       "dot11RSNAConfigGroupCipherSize=%d\n"
-		       "dot11RSNAConfigPMKLifetime=%d\n"
-		       "dot11RSNAConfigPMKReauthThreshold=%d\n"
-		       "dot11RSNAConfigNumberOfPTKSAReplayCounters=1\n"
-		       "dot11RSNAConfigSATimeout=%d\n"
-		       "dot11RSNAAuthenticationSuiteSelected=" RSN_SUITE "\n"
-		       "dot11RSNAPairwiseCipherSelected=" RSN_SUITE "\n"
-		       "dot11RSNAGroupCipherSelected=" RSN_SUITE "\n"
-		       "dot11RSNAPMKIDUsed=%s\n"
-		       "dot11RSNAAuthenticationSuiteRequested=" RSN_SUITE "\n"
-		       "dot11RSNAPairwiseCipherRequested=" RSN_SUITE "\n"
-		       "dot11RSNAGroupCipherRequested=" RSN_SUITE "\n"
-		       "dot11RSNAConfigNumberOfGTKSAReplayCounters=0\n"
-		       "dot11RSNA4WayHandshakeFailures=%u\n",
-		       rsna ? "TRUE" : "FALSE",
-		       rsna ? "TRUE" : "FALSE",
-		       RSN_VERSION,
-		       wpa_cipher_bits(sm->group_cipher),
-		       sm->dot11RSNAConfigPMKLifetime,
-		       sm->dot11RSNAConfigPMKReauthThreshold,
-		       sm->dot11RSNAConfigSATimeout,
-		       RSN_SUITE_ARG(wpa_key_mgmt_suite(sm)),
-		       RSN_SUITE_ARG(wpa_cipher_suite(sm,
-						      sm->pairwise_cipher)),
-		       RSN_SUITE_ARG(wpa_cipher_suite(sm, sm->group_cipher)),
-		       pmkid_txt,
-		       RSN_SUITE_ARG(wpa_key_mgmt_suite(sm)),
-		       RSN_SUITE_ARG(wpa_cipher_suite(sm,
-						      sm->pairwise_cipher)),
-		       RSN_SUITE_ARG(wpa_cipher_suite(sm, sm->group_cipher)),
-		       sm->dot11RSNA4WayHandshakeFailures);
-	return len;
+	ret = os_snprintf(buf, buflen,
+			  "dot11RSNAOptionImplemented=TRUE\n"
+			  "dot11RSNAPreauthenticationImplemented=TRUE\n"
+			  "dot11RSNAEnabled=%s\n"
+			  "dot11RSNAPreauthenticationEnabled=%s\n"
+			  "dot11RSNAConfigVersion=%d\n"
+			  "dot11RSNAConfigPairwiseKeysSupported=5\n"
+			  "dot11RSNAConfigGroupCipherSize=%d\n"
+			  "dot11RSNAConfigPMKLifetime=%d\n"
+			  "dot11RSNAConfigPMKReauthThreshold=%d\n"
+			  "dot11RSNAConfigNumberOfPTKSAReplayCounters=1\n"
+			  "dot11RSNAConfigSATimeout=%d\n",
+			  rsna ? "TRUE" : "FALSE",
+			  rsna ? "TRUE" : "FALSE",
+			  RSN_VERSION,
+			  wpa_cipher_bits(sm->group_cipher),
+			  sm->dot11RSNAConfigPMKLifetime,
+			  sm->dot11RSNAConfigPMKReauthThreshold,
+			  sm->dot11RSNAConfigSATimeout);
+	if (ret < 0 || (size_t) ret >= buflen)
+		return 0;
+	len = ret;
+
+	ret = os_snprintf(
+		buf + len, buflen - len,
+		"dot11RSNAAuthenticationSuiteSelected=" RSN_SUITE "\n"
+		"dot11RSNAPairwiseCipherSelected=" RSN_SUITE "\n"
+		"dot11RSNAGroupCipherSelected=" RSN_SUITE "\n"
+		"dot11RSNAPMKIDUsed=%s\n"
+		"dot11RSNAAuthenticationSuiteRequested=" RSN_SUITE "\n"
+		"dot11RSNAPairwiseCipherRequested=" RSN_SUITE "\n"
+		"dot11RSNAGroupCipherRequested=" RSN_SUITE "\n"
+		"dot11RSNAConfigNumberOfGTKSAReplayCounters=0\n"
+		"dot11RSNA4WayHandshakeFailures=%u\n",
+		RSN_SUITE_ARG(wpa_key_mgmt_suite(sm)),
+		RSN_SUITE_ARG(wpa_cipher_suite(sm, sm->pairwise_cipher)),
+		RSN_SUITE_ARG(wpa_cipher_suite(sm, sm->group_cipher)),
+		pmkid_txt,
+		RSN_SUITE_ARG(wpa_key_mgmt_suite(sm)),
+		RSN_SUITE_ARG(wpa_cipher_suite(sm, sm->pairwise_cipher)),
+		RSN_SUITE_ARG(wpa_cipher_suite(sm, sm->group_cipher)),
+		sm->dot11RSNA4WayHandshakeFailures);
+	if (ret >= 0 && (size_t) ret < buflen)
+		len += ret;
+
+	return (int) len;
+}
+#endif /* CONFIG_CTRL_IFACE */
+
+
+static void wpa_sm_pmksa_free_cb(struct rsn_pmksa_cache_entry *entry,
+				 void *ctx, int replace)
+{
+	struct wpa_sm *sm = ctx;
+
+	if (sm->cur_pmksa == entry ||
+	    (sm->pmk_len == entry->pmk_len &&
+	     os_memcmp(sm->pmk, entry->pmk, sm->pmk_len) == 0)) {
+		wpa_printf(MSG_DEBUG, "RSN: removed current PMKSA entry");
+		sm->cur_pmksa = NULL;
+
+		if (replace) {
+			/* A new entry is being added, so no need to
+			 * deauthenticate in this case. This happens when EAP
+			 * authentication is completed again (reauth or failed
+			 * PMKSA caching attempt). */
+			return;
+		}
+
+		os_memset(sm->pmk, 0, sizeof(sm->pmk));
+		wpa_sm_deauthenticate(sm, REASON_UNSPECIFIED);
+		wpa_sm_req_scan(sm, 0, 0);
+	}
 }
 
 
 /**
  * wpa_sm_init - Initialize WPA state machine
- * @ctx: Context pointer for callbacks
+ * @ctx: Context pointer for callbacks; this needs to be an allocated buffer
  * Returns: Pointer to the allocated WPA state machine data
  *
  * This function is used to allocate a new WPA state machine and the returned
@@ -2210,10 +3815,9 @@
 {
 	struct wpa_sm *sm;
 
-	sm = malloc(sizeof(*sm));
+	sm = os_zalloc(sizeof(*sm));
 	if (sm == NULL)
 		return NULL;
-	memset(sm, 0, sizeof(*sm));
 	sm->renew_snonce = 1;
 	sm->ctx = ctx;
 
@@ -2221,6 +3825,14 @@
 	sm->dot11RSNAConfigPMKReauthThreshold = 70;
 	sm->dot11RSNAConfigSATimeout = 60;
 
+	sm->pmksa = pmksa_cache_init(wpa_sm_pmksa_free_cb, sm, sm);
+	if (sm->pmksa == NULL) {
+		wpa_printf(MSG_ERROR, "RSN: PMKSA cache initialization "
+			   "failed");
+		os_free(sm);
+		return NULL;
+	}
+
 	return sm;
 }
 
@@ -2233,12 +3845,23 @@
 {
 	if (sm == NULL)
 		return;
-	eloop_cancel_timeout(wpa_sm_start_preauth, sm, 0);
-	free(sm->assoc_wpa_ie);
-	free(sm->ap_wpa_ie);
-	free(sm->ap_rsn_ie);
-	free(sm->ctx);
-	free(sm);
+	pmksa_cache_deinit(sm->pmksa);
+	eloop_cancel_timeout(wpa_sm_start_preauth, sm, NULL);
+	os_free(sm->assoc_wpa_ie);
+	os_free(sm->ap_wpa_ie);
+	os_free(sm->ap_rsn_ie);
+	os_free(sm->ctx);
+#ifdef CONFIG_PEERKEY
+	{
+		struct wpa_peerkey *prev, *peerkey = sm->peerkey;
+		while (peerkey) {
+			prev = peerkey;
+			peerkey = peerkey->next;
+			os_free(prev);
+		}
+	}
+#endif /* CONFIG_PEERKEY */
+	os_free(sm);
 }
 
 
@@ -2256,11 +3879,11 @@
 		return;
 
 	wpa_printf(MSG_DEBUG, "WPA: Association event - clear replay counter");
-	memcpy(sm->bssid, bssid, ETH_ALEN);
-	memset(sm->rx_replay_counter, 0, WPA_REPLAY_COUNTER_LEN);
+	os_memcpy(sm->bssid, bssid, ETH_ALEN);
+	os_memset(sm->rx_replay_counter, 0, WPA_REPLAY_COUNTER_LEN);
 	sm->rx_replay_counter_set = 0;
 	sm->renew_snonce = 1;
-	if (memcmp(sm->preauth_bssid, bssid, ETH_ALEN) == 0)
+	if (os_memcmp(sm->preauth_bssid, bssid, ETH_ALEN) == 0)
 		rsn_preauth_deinit(sm);
 }
 
@@ -2294,7 +3917,7 @@
 		return;
 
 	sm->pmk_len = pmk_len;
-	memcpy(sm->pmk, pmk, pmk_len);
+	os_memcpy(sm->pmk, pmk, pmk_len);
 }
 
 
@@ -2312,10 +3935,10 @@
 
 	if (sm->cur_pmksa) {
 		sm->pmk_len = sm->cur_pmksa->pmk_len;
-		memcpy(sm->pmk, sm->cur_pmksa->pmk, sm->pmk_len);
+		os_memcpy(sm->pmk, sm->cur_pmksa->pmk, sm->pmk_len);
 	} else {
 		sm->pmk_len = PMK_LEN;
-		memset(sm->pmk, 0, PMK_LEN);
+		os_memset(sm->pmk, 0, PMK_LEN);
 	}
 }
 
@@ -2358,8 +3981,10 @@
  */
 void wpa_sm_set_config(struct wpa_sm *sm, struct wpa_ssid *config)
 {
-	if (sm)
+	if (sm) {
 		sm->cur_ssid = config;
+		pmksa_cache_notify_reconfig(sm->pmksa);
+	}
 }
 
 
@@ -2371,7 +3996,7 @@
 void wpa_sm_set_own_addr(struct wpa_sm *sm, const u8 *addr)
 {
 	if (sm)
-		memcpy(sm->own_addr, addr, ETH_ALEN);
+		os_memcpy(sm->own_addr, addr, ETH_ALEN);
 }
 
 
@@ -2379,11 +4004,15 @@
  * wpa_sm_set_ifname - Set network interface name
  * @sm: Pointer to WPA state machine data from wpa_sm_init()
  * @ifname: Interface name
+ * @bridge_ifname: Optional bridge interface name (for pre-auth)
  */
-void wpa_sm_set_ifname(struct wpa_sm *sm, const char *ifname)
+void wpa_sm_set_ifname(struct wpa_sm *sm, const char *ifname,
+		       const char *bridge_ifname)
 {
-	if (sm)
+	if (sm) {
 		sm->ifname = ifname;
+		sm->bridge_ifname = bridge_ifname;
+	}
 }
 
 
@@ -2445,6 +4074,13 @@
 	case WPA_PARAM_KEY_MGMT:
 		sm->key_mgmt = value;
 		break;
+#ifdef CONFIG_IEEE80211W
+	case WPA_PARAM_MGMT_GROUP:
+		sm->mgmt_group_cipher = value;
+		break;
+#endif /* CONFIG_IEEE80211W */
+	default:
+		break;
 	}
 
 	return ret;
@@ -2477,6 +4113,10 @@
 		return sm->group_cipher;
 	case WPA_PARAM_KEY_MGMT:
 		return sm->key_mgmt;
+#ifdef CONFIG_IEEE80211W
+	case WPA_PARAM_MGMT_GROUP:
+		return sm->mgmt_group_cipher;
+#endif /* CONFIG_IEEE80211W */
 	default:
 		return 0;
 	}
@@ -2499,14 +4139,18 @@
 		      int verbose)
 {
 	char *pos = buf, *end = buf + buflen;
+	int ret;
 
-	pos += snprintf(pos, end - pos,
-			"pairwise_cipher=%s\n"
-			"group_cipher=%s\n"
-			"key_mgmt=%s\n",
-			wpa_cipher_txt(sm->pairwise_cipher),
-			wpa_cipher_txt(sm->group_cipher),
-			wpa_key_mgmt_txt(sm->key_mgmt, sm->proto));
+	ret = os_snprintf(pos, end - pos,
+			  "pairwise_cipher=%s\n"
+			  "group_cipher=%s\n"
+			  "key_mgmt=%s\n",
+			  wpa_cipher_txt(sm->pairwise_cipher),
+			  wpa_cipher_txt(sm->group_cipher),
+			  wpa_key_mgmt_txt(sm->key_mgmt, sm->proto));
+	if (ret < 0 || ret >= end - pos)
+		return pos - buf;
+	pos += ret;
 	return pos - buf;
 }
 
@@ -2525,12 +4169,15 @@
 int wpa_sm_set_assoc_wpa_ie_default(struct wpa_sm *sm, u8 *wpa_ie,
 				    size_t *wpa_ie_len)
 {
+	int res;
+
 	if (sm == NULL)
 		return -1;
 
-	*wpa_ie_len = wpa_gen_wpa_ie(sm, wpa_ie, *wpa_ie_len);
-	if (*wpa_ie_len < 0)
+	res = wpa_gen_wpa_ie(sm, wpa_ie, *wpa_ie_len);
+	if (res < 0)
 		return -1;
+	*wpa_ie_len = res;
 
 	wpa_hexdump(MSG_DEBUG, "WPA: Set own WPA IE default",
 		    wpa_ie, *wpa_ie_len);
@@ -2541,11 +4188,11 @@
 		 * the correct version of the IE even if PMKSA caching is
 		 * aborted (which would remove PMKID from IE generation).
 		 */
-		sm->assoc_wpa_ie = malloc(*wpa_ie_len);
+		sm->assoc_wpa_ie = os_malloc(*wpa_ie_len);
 		if (sm->assoc_wpa_ie == NULL)
 			return -1;
 
-		memcpy(sm->assoc_wpa_ie, wpa_ie, *wpa_ie_len);
+		os_memcpy(sm->assoc_wpa_ie, wpa_ie, *wpa_ie_len);
 		sm->assoc_wpa_ie_len = *wpa_ie_len;
 	}
 
@@ -2569,18 +4216,18 @@
 	if (sm == NULL)
 		return -1;
 
-	free(sm->assoc_wpa_ie);
+	os_free(sm->assoc_wpa_ie);
 	if (ie == NULL || len == 0) {
 		wpa_printf(MSG_DEBUG, "WPA: clearing own WPA/RSN IE");
 		sm->assoc_wpa_ie = NULL;
 		sm->assoc_wpa_ie_len = 0;
 	} else {
 		wpa_hexdump(MSG_DEBUG, "WPA: set own WPA/RSN IE", ie, len);
-		sm->assoc_wpa_ie = malloc(len);
+		sm->assoc_wpa_ie = os_malloc(len);
 		if (sm->assoc_wpa_ie == NULL)
 			return -1;
 
-		memcpy(sm->assoc_wpa_ie, ie, len);
+		os_memcpy(sm->assoc_wpa_ie, ie, len);
 		sm->assoc_wpa_ie_len = len;
 	}
 
@@ -2603,18 +4250,18 @@
 	if (sm == NULL)
 		return -1;
 
-	free(sm->ap_wpa_ie);
+	os_free(sm->ap_wpa_ie);
 	if (ie == NULL || len == 0) {
 		wpa_printf(MSG_DEBUG, "WPA: clearing AP WPA IE");
 		sm->ap_wpa_ie = NULL;
 		sm->ap_wpa_ie_len = 0;
 	} else {
 		wpa_hexdump(MSG_DEBUG, "WPA: set AP WPA IE", ie, len);
-		sm->ap_wpa_ie = malloc(len);
+		sm->ap_wpa_ie = os_malloc(len);
 		if (sm->ap_wpa_ie == NULL)
 			return -1;
 
-		memcpy(sm->ap_wpa_ie, ie, len);
+		os_memcpy(sm->ap_wpa_ie, ie, len);
 		sm->ap_wpa_ie_len = len;
 	}
 
@@ -2637,18 +4284,18 @@
 	if (sm == NULL)
 		return -1;
 
-	free(sm->ap_rsn_ie);
+	os_free(sm->ap_rsn_ie);
 	if (ie == NULL || len == 0) {
 		wpa_printf(MSG_DEBUG, "WPA: clearing AP RSN IE");
 		sm->ap_rsn_ie = NULL;
 		sm->ap_rsn_ie_len = 0;
 	} else {
 		wpa_hexdump(MSG_DEBUG, "WPA: set AP RSN IE", ie, len);
-		sm->ap_rsn_ie = malloc(len);
+		sm->ap_rsn_ie = os_malloc(len);
 		if (sm->ap_rsn_ie == NULL)
 			return -1;
 
-		memcpy(sm->ap_rsn_ie, ie, len);
+		os_memcpy(sm->ap_rsn_ie, ie, len);
 		sm->ap_rsn_ie_len = len;
 	}
 
Index: md5.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/md5.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/md5.c -L contrib/wpa_supplicant/md5.c -u -r1.2 -r1.3
--- contrib/wpa_supplicant/md5.c
+++ contrib/wpa_supplicant/md5.c
@@ -1,6 +1,6 @@
 /*
  * MD5 hash implementation and interface functions
- * Copyright (c) 2003-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2003-2005, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -12,9 +12,7 @@
  * See README and COPYING for more details.
  */
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
+#include "includes.h"
 
 #include "common.h"
 #include "md5.h"
@@ -35,9 +33,8 @@
 {
 	u8 k_pad[64]; /* padding - key XORd with ipad/opad */
 	u8 tk[16];
-	int i;
 	const u8 *_addr[6];
-	size_t _len[6];
+	size_t i, _len[6];
 
 	if (num_elem > 5) {
 		/*
@@ -64,8 +61,8 @@
 	 * and text is the data being protected */
 
 	/* start out by storing key in ipad */
-	memset(k_pad, 0, sizeof(k_pad));
-	memcpy(k_pad, key, key_len);
+	os_memset(k_pad, 0, sizeof(k_pad));
+	os_memcpy(k_pad, key, key_len);
 
 	/* XOR key with ipad values */
 	for (i = 0; i < 64; i++)
@@ -80,8 +77,8 @@
 	}
 	md5_vector(1 + num_elem, _addr, _len, mac);
 
-	memset(k_pad, 0, sizeof(k_pad));
-	memcpy(k_pad, key, key_len);
+	os_memset(k_pad, 0, sizeof(k_pad));
+	os_memcpy(k_pad, key, key_len);
 	/* XOR key with opad values */
 	for (i = 0; i < 64; i++)
 		k_pad[i] ^= 0x5c;
@@ -110,7 +107,7 @@
 }
 
 
-#ifndef EAP_TLS_FUNCS
+#ifdef INTERNAL_MD5
 
 struct MD5Context {
 	u32 buf[4];
@@ -118,12 +115,15 @@
 	u8 in[64];
 };
 
+#ifndef CONFIG_CRYPTO_INTERNAL
 static void MD5Init(struct MD5Context *context);
 static void MD5Update(struct MD5Context *context, unsigned char const *buf,
-		      unsigned len);
+			  unsigned len);
 static void MD5Final(unsigned char digest[16], struct MD5Context *context);
+#endif /* CONFIG_CRYPTO_INTERNAL */
 static void MD5Transform(u32 buf[4], u32 const in[16]);
 
+
 typedef struct MD5Context MD5_CTX;
 
 
@@ -137,7 +137,7 @@
 void md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
 {
 	MD5_CTX ctx;
-	int i;
+	size_t i;
 
 	MD5Init(&ctx);
 	for (i = 0; i < num_elem; i++)
@@ -186,7 +186,7 @@
  * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
  * initialization constants.
  */
-static void MD5Init(struct MD5Context *ctx)
+void MD5Init(struct MD5Context *ctx)
 {
     ctx->buf[0] = 0x67452301;
     ctx->buf[1] = 0xefcdab89;
@@ -201,8 +201,7 @@
  * Update context to reflect the concatenation of another buffer full
  * of bytes.
  */
-static void MD5Update(struct MD5Context *ctx, unsigned char const *buf,
-		      unsigned len)
+void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len)
 {
     u32 t;
 
@@ -222,10 +221,10 @@
 
 	t = 64 - t;
 	if (len < t) {
-	    memcpy(p, buf, len);
+	    os_memcpy(p, buf, len);
 	    return;
 	}
-	memcpy(p, buf, t);
+	os_memcpy(p, buf, t);
 	byteReverse(ctx->in, 16);
 	MD5Transform(ctx->buf, (u32 *) ctx->in);
 	buf += t;
@@ -234,7 +233,7 @@
     /* Process data in 64-byte chunks */
 
     while (len >= 64) {
-	memcpy(ctx->in, buf, 64);
+	os_memcpy(ctx->in, buf, 64);
 	byteReverse(ctx->in, 16);
 	MD5Transform(ctx->buf, (u32 *) ctx->in);
 	buf += 64;
@@ -243,14 +242,14 @@
 
     /* Handle any remaining bytes of data. */
 
-    memcpy(ctx->in, buf, len);
+    os_memcpy(ctx->in, buf, len);
 }
 
 /*
  * Final wrapup - pad to 64-byte boundary with the bit pattern
  * 1 0* (64-bit count of bits processed, MSB-first)
  */
-static void MD5Final(unsigned char digest[16], struct MD5Context *ctx)
+void MD5Final(unsigned char digest[16], struct MD5Context *ctx)
 {
     unsigned count;
     unsigned char *p;
@@ -269,15 +268,15 @@
     /* Pad out to 56 mod 64 */
     if (count < 8) {
 	/* Two lots of padding:  Pad the first block to 64 bytes */
-	memset(p, 0, count);
+	os_memset(p, 0, count);
 	byteReverse(ctx->in, 16);
 	MD5Transform(ctx->buf, (u32 *) ctx->in);
 
 	/* Now fill the next block with 56 bytes */
-	memset(ctx->in, 0, 56);
+	os_memset(ctx->in, 0, 56);
     } else {
 	/* Pad block to 56 bytes */
-	memset(p, 0, count - 8);
+	os_memset(p, 0, count - 8);
     }
     byteReverse(ctx->in, 14);
 
@@ -287,8 +286,8 @@
 
     MD5Transform(ctx->buf, (u32 *) ctx->in);
     byteReverse((unsigned char *) ctx->buf, 4);
-    memcpy(digest, ctx->buf, 16);
-    memset(ctx, 0, sizeof(ctx));	/* In case it's sensitive */
+    os_memcpy(digest, ctx->buf, 16);
+    os_memset(ctx, 0, sizeof(ctx));	/* In case it's sensitive */
 }
 
 /* The four core functions - F1 is optimized somewhat */
@@ -392,4 +391,4 @@
 }
 /* ===== end - public domain MD5 implementation ===== */
 
-#endif /* !EAP_TLS_FUNCS */
+#endif /* INTERNAL_MD5 */
Index: driver_wired.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/driver_wired.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -L contrib/wpa_supplicant/driver_wired.c -L contrib/wpa_supplicant/driver_wired.c -u -r1.1 -r1.2
--- contrib/wpa_supplicant/driver_wired.c
+++ contrib/wpa_supplicant/driver_wired.c
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant - wired Ethernet driver interface
- * Copyright (c) 2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2005-2007, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -12,15 +12,15 @@
  * See README and COPYING for more details.
  */
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
+#include "includes.h"
 #include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netpacket/packet.h>
 #include <net/if.h>
+#ifdef __linux__
+#include <netpacket/packet.h>
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+#include <net/if_dl.h>
+#endif /* __FreeBSD__ */
 
 #include "common.h"
 #include "driver.h"
@@ -39,12 +39,6 @@
 };
 
 
-static int wpa_driver_wired_set_wpa(void *priv, int enabled)
-{
-	return 0;
-}
-
-
 static int wpa_driver_wired_get_ssid(void *priv, u8 *ssid)
 {
 	ssid[0] = 0;
@@ -55,7 +49,7 @@
 static int wpa_driver_wired_get_bssid(void *priv, u8 *bssid)
 {
 	/* Report PAE group address as the "BSSID" for wired connection. */
-	memcpy(bssid, pae_group_addr, ETH_ALEN);
+	os_memcpy(bssid, pae_group_addr, ETH_ALEN);
 	return 0;
 }
 
@@ -71,8 +65,8 @@
 		return -1;
 	}
 
-	memset(&ifr, 0, sizeof(ifr));
-	strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
+	os_memset(&ifr, 0, sizeof(ifr));
+	os_strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
 	if (ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
 		perror("ioctl[SIOCGIFFLAGS]");
 		close(s);
@@ -95,8 +89,8 @@
 		return -1;
 	}
 
-	memset(&ifr, 0, sizeof(ifr));
-	strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
+	os_memset(&ifr, 0, sizeof(ifr));
+	os_strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
 	ifr.ifr_flags = flags & 0xffff;
 	if (ioctl(s, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
 		perror("ioctl[SIOCSIFFLAGS]");
@@ -119,10 +113,25 @@
 		return -1;
 	}
 
-	memset(&ifr, 0, sizeof(ifr));
-	strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
+	os_memset(&ifr, 0, sizeof(ifr));
+	os_strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
+#ifdef __linux__
 	ifr.ifr_hwaddr.sa_family = AF_UNSPEC;
-	memcpy(ifr.ifr_hwaddr.sa_data, addr, ETH_ALEN);
+	os_memcpy(ifr.ifr_hwaddr.sa_data, addr, ETH_ALEN);
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+	{
+		struct sockaddr_dl *dlp;
+		dlp = (struct sockaddr_dl *) &ifr.ifr_addr;
+		dlp->sdl_len = sizeof(struct sockaddr_dl);
+		dlp->sdl_family = AF_LINK;
+		dlp->sdl_index = 0;
+		dlp->sdl_nlen = 0;
+		dlp->sdl_alen = ETH_ALEN;
+		dlp->sdl_slen = 0;
+		os_memcpy(LLADDR(dlp), addr, ETH_ALEN); 
+	}
+#endif /* __FreeBSD__ */
 
 	if (ioctl(s, add ? SIOCADDMULTI : SIOCDELMULTI, (caddr_t) &ifr) < 0) {
 		perror("ioctl[SIOC{ADD/DEL}MULTI]");
@@ -143,11 +152,11 @@
 	if (drv->pf_sock == -1)
 		return -1;
 
-	memset(&mreq, 0, sizeof(mreq));
+	os_memset(&mreq, 0, sizeof(mreq));
 	mreq.mr_ifindex = if_nametoindex(drv->ifname);
 	mreq.mr_type = PACKET_MR_MULTICAST;
 	mreq.mr_alen = ETH_ALEN;
-	memcpy(mreq.mr_address, addr, ETH_ALEN);
+	os_memcpy(mreq.mr_address, addr, ETH_ALEN);
 
 	if (setsockopt(drv->pf_sock, SOL_PACKET,
 		       add ? PACKET_ADD_MEMBERSHIP : PACKET_DROP_MEMBERSHIP,
@@ -167,20 +176,19 @@
 	struct wpa_driver_wired_data *drv;
 	int flags;
 
-	drv = malloc(sizeof(*drv));
+	drv = os_zalloc(sizeof(*drv));
 	if (drv == NULL)
 		return NULL;
-	memset(drv, 0, sizeof(*drv));
-	strncpy(drv->ifname, ifname, sizeof(drv->ifname));
+	os_strncpy(drv->ifname, ifname, sizeof(drv->ifname));
 	drv->ctx = ctx;
 
 #ifdef __linux__
 	drv->pf_sock = socket(PF_PACKET, SOCK_DGRAM, 0);
 	if (drv->pf_sock < 0)
 		perror("socket(PF_PACKET)");
-#else
+#else /* __linux__ */
 	drv->pf_sock = -1;       
-#endif
+#endif /* __linux__ */
 	
 	if (wpa_driver_wired_get_ifflags(ifname, &flags) == 0 &&
 	    !(flags & IFF_UP) &&
@@ -199,7 +207,7 @@
 	} else if (wpa_driver_wired_get_ifflags(ifname, &flags) < 0) {
 		wpa_printf(MSG_INFO, "%s: Could not get interface "
 			   "flags", __func__);
-		free(drv);
+		os_free(drv);
 		return NULL;
 	} else if (flags & IFF_ALLMULTI) {
 		wpa_printf(MSG_DEBUG, "%s: Interface is already configured "
@@ -208,7 +216,7 @@
 						flags | IFF_ALLMULTI) < 0) {
 		wpa_printf(MSG_INFO, "%s: Failed to enable allmulti",
 			   __func__);
-		free(drv);
+		os_free(drv);
 		return NULL;
 	} else {
 		wpa_printf(MSG_DEBUG, "%s: Enabled allmulti mode",
@@ -256,14 +264,13 @@
 	if (drv->pf_sock != -1)
 		close(drv->pf_sock);
 	
-	free(drv);
+	os_free(drv);
 }
 
 
 const struct wpa_driver_ops wpa_driver_wired_ops = {
 	.name = "wired",
 	.desc = "wpa_supplicant wired Ethernet driver",
-	.set_wpa = wpa_driver_wired_set_wpa,
 	.get_ssid = wpa_driver_wired_get_ssid,
 	.get_bssid = wpa_driver_wired_get_bssid,
 	.init = wpa_driver_wired_init,
Index: eap_peap.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/eap_peap.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/eap_peap.c -L contrib/wpa_supplicant/eap_peap.c -u -r1.2 -r1.3
--- contrib/wpa_supplicant/eap_peap.c
+++ contrib/wpa_supplicant/eap_peap.c
@@ -1,6 +1,6 @@
 /*
- * WPA Supplicant / EAP-PEAP (draft-josefsson-pppext-eap-tls-eap-07.txt)
- * Copyright (c) 2004-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * EAP peer method: EAP-PEAP (draft-josefsson-pppext-eap-tls-eap-07.txt)
+ * Copyright (c) 2004-2006, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -12,14 +12,11 @@
  * See README and COPYING for more details.
  */
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
+#include "includes.h"
 
 #include "common.h"
 #include "eap_i.h"
 #include "eap_tls_common.h"
-#include "wpa_supplicant.h"
 #include "config_ssid.h"
 #include "tls.h"
 #include "eap_tlv.h"
@@ -45,8 +42,8 @@
 	void *phase2_priv;
 	int phase2_success;
 
-	u8 phase2_type;
-	u8 *phase2_types;
+	struct eap_method_type phase2_type;
+	struct eap_method_type *phase2_types;
 	size_t num_phase2_types;
 
 	int peap_outer_success; /* 0 = PEAP terminated on Phase 2 inner
@@ -70,17 +67,16 @@
 	struct eap_peap_data *data;
 	struct wpa_ssid *config = eap_get_config(sm);
 
-	data = malloc(sizeof(*data));
+	data = os_zalloc(sizeof(*data));
 	if (data == NULL)
 		return NULL;
 	sm->peap_done = FALSE;
-	memset(data, 0, sizeof(*data));
 	data->peap_version = EAP_PEAP_VERSION;
 	data->force_peap_version = -1;
 	data->peap_outer_success = 2;
 
 	if (config && config->phase1) {
-		char *pos = strstr(config->phase1, "peapver=");
+		char *pos = os_strstr(config->phase1, "peapver=");
 		if (pos) {
 			data->force_peap_version = atoi(pos + 8);
 			data->peap_version = data->force_peap_version;
@@ -88,22 +84,22 @@
 				   "%d", data->force_peap_version);
 		}
 
-		if (strstr(config->phase1, "peaplabel=1")) {
+		if (os_strstr(config->phase1, "peaplabel=1")) {
 			data->force_new_label = 1;
 			wpa_printf(MSG_DEBUG, "EAP-PEAP: Force new label for "
 				   "key derivation");
 		}
 
-		if (strstr(config->phase1, "peap_outer_success=0")) {
+		if (os_strstr(config->phase1, "peap_outer_success=0")) {
 			data->peap_outer_success = 0;
 			wpa_printf(MSG_DEBUG, "EAP-PEAP: terminate "
 				   "authentication on tunneled EAP-Success");
-		} else if (strstr(config->phase1, "peap_outer_success=1")) {
+		} else if (os_strstr(config->phase1, "peap_outer_success=1")) {
 			data->peap_outer_success = 1;
 			wpa_printf(MSG_DEBUG, "EAP-PEAP: send tunneled "
 				   "EAP-Success after receiving tunneled "
 				   "EAP-Success");
-		} else if (strstr(config->phase1, "peap_outer_success=2")) {
+		} else if (os_strstr(config->phase1, "peap_outer_success=2")) {
 			data->peap_outer_success = 2;
 			wpa_printf(MSG_DEBUG, "EAP-PEAP: send PEAP/TLS ACK "
 				   "after receiving tunneled EAP-Success");
@@ -112,15 +108,17 @@
 
 	if (config && config->phase2) {
 		char *start, *pos, *buf;
-		u8 method, *methods = NULL, *_methods;
+		struct eap_method_type *methods = NULL, *_methods;
+		u8 method;
 		size_t num_methods = 0;
-		start = buf = strdup(config->phase2);
+		start = buf = os_strdup(config->phase2);
 		if (buf == NULL) {
 			eap_peap_deinit(sm, data);
 			return NULL;
 		}
 		while (start && *start != '\0') {
-			pos = strstr(start, "auth=");
+			int vendor;
+			pos = os_strstr(start, "auth=");
 			if (pos == NULL)
 				break;
 			if (start != pos && *(pos - 1) != ' ') {
@@ -129,28 +127,33 @@
 			}
 
 			start = pos + 5;
-			pos = strchr(start, ' ');
+			pos = os_strchr(start, ' ');
 			if (pos)
 				*pos++ = '\0';
-			method = eap_get_phase2_type(start);
-			if (method == EAP_TYPE_NONE) {
+			method = eap_get_phase2_type(start, &vendor);
+			if (vendor == EAP_VENDOR_IETF &&
+			    method == EAP_TYPE_NONE) {
 				wpa_printf(MSG_ERROR, "EAP-PEAP: Unsupported "
 					   "Phase2 method '%s'", start);
 			} else {
 				num_methods++;
-				_methods = realloc(methods, num_methods);
+				_methods = os_realloc(
+					methods,
+					num_methods * sizeof(*methods));
 				if (_methods == NULL) {
-					free(methods);
+					os_free(methods);
+					os_free(buf);
 					eap_peap_deinit(sm, data);
 					return NULL;
 				}
 				methods = _methods;
-				methods[num_methods - 1] = method;
+				methods[num_methods - 1].vendor = vendor;
+				methods[num_methods - 1].method = method;
 			}
 
 			start = pos;
 		}
-		free(buf);
+		os_free(buf);
 		data->phase2_types = methods;
 		data->num_phase2_types = num_methods;
 	}
@@ -164,8 +167,10 @@
 		return NULL;
 	}
 	wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Phase2 EAP types",
-		    data->phase2_types, data->num_phase2_types);
-	data->phase2_type = EAP_TYPE_NONE;
+		    (u8 *) data->phase2_types,
+		    data->num_phase2_types * sizeof(struct eap_method_type));
+	data->phase2_type.vendor = EAP_VENDOR_IETF;
+	data->phase2_type.method = EAP_TYPE_NONE;
 
 	if (eap_tls_ssl_init(sm, &data->ssl, config)) {
 		wpa_printf(MSG_INFO, "EAP-PEAP: Failed to initialize SSL.");
@@ -184,11 +189,11 @@
 		return;
 	if (data->phase2_priv && data->phase2_method)
 		data->phase2_method->deinit(sm, data->phase2_priv);
-	free(data->phase2_types);
+	os_free(data->phase2_types);
 	eap_tls_ssl_deinit(sm, &data->ssl);
-	free(data->key_data);
-	free(data->pending_phase2_req);
-	free(data);
+	os_free(data->key_data);
+	os_free(data->pending_phase2_req);
+	os_free(data);
 }
 
 
@@ -204,7 +209,7 @@
 	 * add TLS Message Length field, if the frame is fragmented.
 	 * Note: Microsoft IAS did not seem to like TLS Message Length with
 	 * PEAP/MSCHAPv2. */
-	resp = malloc(sizeof(struct eap_hdr) + 2 + data->ssl.tls_out_limit);
+	resp = os_malloc(sizeof(struct eap_hdr) + 2 + data->ssl.tls_out_limit);
 	if (resp == NULL)
 		return -1;
 
@@ -221,7 +226,7 @@
 	if (res < 0) {
 		wpa_printf(MSG_INFO, "EAP-PEAP: Failed to encrypt Phase 2 "
 			   "data");
-		free(resp);
+		os_free(resp);
 		return -1;
 	}
 
@@ -232,29 +237,36 @@
 }
 
 
-static int eap_peap_phase2_nak(struct eap_sm *sm,
-			       struct eap_peap_data *data,
-			       struct eap_hdr *hdr,
+static int eap_peap_phase2_nak(struct eap_peap_data *data, struct eap_hdr *hdr,
 			       u8 **resp, size_t *resp_len)
 {
 	struct eap_hdr *resp_hdr;
 	u8 *pos = (u8 *) (hdr + 1);
+	size_t i;
 
+	/* TODO: add support for expanded Nak */
 	wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Request: Nak type=%d", *pos);
 	wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Allowed Phase2 EAP types",
-		    data->phase2_types, data->num_phase2_types);
-	*resp_len = sizeof(struct eap_hdr) + 1 + data->num_phase2_types;
-	*resp = malloc(*resp_len);
+		    (u8 *) data->phase2_types,
+		    data->num_phase2_types * sizeof(struct eap_method_type));
+	*resp_len = sizeof(struct eap_hdr) + 1;
+	*resp = os_malloc(*resp_len + data->num_phase2_types);
 	if (*resp == NULL)
 		return -1;
 
 	resp_hdr = (struct eap_hdr *) (*resp);
 	resp_hdr->code = EAP_CODE_RESPONSE;
 	resp_hdr->identifier = hdr->identifier;
-	resp_hdr->length = host_to_be16(*resp_len);
 	pos = (u8 *) (resp_hdr + 1);
 	*pos++ = EAP_TYPE_NAK;
-	memcpy(pos, data->phase2_types, data->num_phase2_types);
+	for (i = 0; i < data->num_phase2_types; i++) {
+		if (data->phase2_types[i].vendor == EAP_VENDOR_IETF &&
+		    data->phase2_types[i].method < 256) {
+			(*resp_len)++;
+			*pos++ = data->phase2_types[i].method;
+		}
+	}
+	resp_hdr->length = host_to_be16(*resp_len);
 
 	return 0;
 }
@@ -263,7 +275,6 @@
 static int eap_peap_phase2_request(struct eap_sm *sm,
 				   struct eap_peap_data *data,
 				   struct eap_method_ret *ret,
-				   const struct eap_hdr *req,
 				   struct eap_hdr *hdr,
 				   u8 **resp, size_t *resp_len)
 {
@@ -281,10 +292,10 @@
 	wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Request: type=%d", *pos);
 	switch (*pos) {
 	case EAP_TYPE_IDENTITY:
-		*resp = eap_sm_buildIdentity(sm, req->identifier, resp_len, 1);
+		*resp = eap_sm_buildIdentity(sm, hdr->identifier, resp_len, 1);
 		break;
 	case EAP_TYPE_TLV:
-		memset(&iret, 0, sizeof(iret));
+		os_memset(&iret, 0, sizeof(iret));
 		if (eap_tlv_process(sm, &iret, hdr, resp, resp_len)) {
 			ret->methodState = METHOD_DONE;
 			ret->decision = DECISION_FAIL;
@@ -298,27 +309,37 @@
 		}
 		break;
 	default:
-		if (data->phase2_type == EAP_TYPE_NONE) {
-			int i;
+		if (data->phase2_type.vendor == EAP_VENDOR_IETF &&
+		    data->phase2_type.method == EAP_TYPE_NONE) {
+			size_t i;
 			for (i = 0; i < data->num_phase2_types; i++) {
-				if (data->phase2_types[i] != *pos)
+				if (data->phase2_types[i].vendor !=
+				    EAP_VENDOR_IETF ||
+				    data->phase2_types[i].method != *pos)
 					continue;
 
-				data->phase2_type = *pos;
+				data->phase2_type.vendor =
+					data->phase2_types[i].vendor;
+				data->phase2_type.method =
+					data->phase2_types[i].method;
 				wpa_printf(MSG_DEBUG, "EAP-PEAP: Selected "
-					   "Phase 2 EAP method %d",
-					   data->phase2_type);
+					   "Phase 2 EAP vendor %d method %d",
+					   data->phase2_type.vendor,
+					   data->phase2_type.method);
 				break;
 			}
 		}
-		if (*pos != data->phase2_type || *pos == EAP_TYPE_NONE) {
-			if (eap_peap_phase2_nak(sm, data, hdr, resp, resp_len))
+		if (*pos != data->phase2_type.method ||
+		    *pos == EAP_TYPE_NONE) {
+			if (eap_peap_phase2_nak(data, hdr, resp, resp_len))
 				return -1;
 			return 0;
 		}
 
 		if (data->phase2_priv == NULL) {
-			data->phase2_method = eap_sm_get_eap_methods(*pos);
+			data->phase2_method = eap_sm_get_eap_methods(
+				data->phase2_type.vendor,
+				data->phase2_type.method);
 			if (data->phase2_method) {
 				sm->init_phase2 = 1;
 				data->phase2_priv =
@@ -333,7 +354,7 @@
 			ret->decision = DECISION_FAIL;
 			return -1;
 		}
-		memset(&iret, 0, sizeof(iret));
+		os_memset(&iret, 0, sizeof(iret));
 		*resp = data->phase2_method->process(sm, data->phase2_priv,
 						     &iret, (u8 *) hdr, len,
 						     resp_len);
@@ -349,10 +370,10 @@
 	if (*resp == NULL &&
 	    (config->pending_req_identity || config->pending_req_password ||
 	     config->pending_req_otp || config->pending_req_new_password)) {
-		free(data->pending_phase2_req);
-		data->pending_phase2_req = malloc(len);
+		os_free(data->pending_phase2_req);
+		data->pending_phase2_req = os_malloc(len);
 		if (data->pending_phase2_req) {
-			memcpy(data->pending_phase2_req, hdr, len);
+			os_memcpy(data->pending_phase2_req, hdr, len);
 			data->pending_phase2_req_len = len;
 		}
 	}
@@ -368,10 +389,10 @@
 			    u8 **out_data, size_t *out_len)
 {
 	u8 *in_decrypted;
-	int buf_len, len_decrypted, len, skip_change = 0;
+	int res, skip_change = 0;
 	struct eap_hdr *hdr, *rhdr;
 	u8 *resp = NULL;
-	size_t resp_len;
+	size_t resp_len, len_decrypted, len, buf_len;
 	const u8 *msg;
 	size_t msg_len;
 	int need_more_input;
@@ -383,7 +404,7 @@
 		wpa_printf(MSG_DEBUG, "EAP-PEAP: Pending Phase 2 request - "
 			   "skip decryption and use old data");
 		/* Clear TLS reassembly state. */
-		free(data->ssl.tls_in);
+		os_free(data->ssl.tls_in);
 		data->ssl.tls_in = NULL;
 		data->ssl.tls_in_len = 0;
 		data->ssl.tls_in_left = 0;
@@ -416,9 +437,9 @@
 	buf_len = in_len;
 	if (data->ssl.tls_in_total > buf_len)
 		buf_len = data->ssl.tls_in_total;
-	in_decrypted = malloc(buf_len);
+	in_decrypted = os_malloc(buf_len);
 	if (in_decrypted == NULL) {
-		free(data->ssl.tls_in);
+		os_free(data->ssl.tls_in);
 		data->ssl.tls_in = NULL;
 		data->ssl.tls_in_len = 0;
 		wpa_printf(MSG_WARNING, "EAP-PEAP: failed to allocate memory "
@@ -426,18 +447,18 @@
 		return -1;
 	}
 
-	len_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,
-					       msg, msg_len,
-					       in_decrypted, buf_len);
-	free(data->ssl.tls_in);
+	res = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,
+				     msg, msg_len, in_decrypted, buf_len);
+	os_free(data->ssl.tls_in);
 	data->ssl.tls_in = NULL;
 	data->ssl.tls_in_len = 0;
-	if (len_decrypted < 0) {
+	if (res < 0) {
 		wpa_printf(MSG_INFO, "EAP-PEAP: Failed to decrypt Phase 2 "
 			   "data");
-		free(in_decrypted);
+		os_free(in_decrypted);
 		return 0;
 	}
+	len_decrypted = res;
 
 continue_req:
 	wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Decrypted Phase 2 EAP", in_decrypted,
@@ -457,14 +478,14 @@
 	}
 
 	if (data->peap_version == 0 && !skip_change) {
-		struct eap_hdr *nhdr = malloc(sizeof(struct eap_hdr) +
-					      len_decrypted);
+		struct eap_hdr *nhdr = os_malloc(sizeof(struct eap_hdr) +
+						 len_decrypted);
 		if (nhdr == NULL) {
-			free(in_decrypted);
+			os_free(in_decrypted);
 			return 0;
 		}
-		memcpy((u8 *) (nhdr + 1), in_decrypted, len_decrypted);
-		free(in_decrypted);
+		os_memcpy((u8 *) (nhdr + 1), in_decrypted, len_decrypted);
+		os_free(in_decrypted);
 		nhdr->code = req->code;
 		nhdr->identifier = req->identifier;
 		nhdr->length = host_to_be16(sizeof(struct eap_hdr) +
@@ -475,23 +496,25 @@
 	}
 	hdr = (struct eap_hdr *) in_decrypted;
 	if (len_decrypted < sizeof(*hdr)) {
-		free(in_decrypted);
+		os_free(in_decrypted);
 		wpa_printf(MSG_INFO, "EAP-PEAP: Too short Phase 2 "
-			   "EAP frame (len=%d)", len_decrypted);
+			   "EAP frame (len=%lu)",
+			   (unsigned long) len_decrypted);
 		return 0;
 	}
 	len = be_to_host16(hdr->length);
 	if (len > len_decrypted) {
-		free(in_decrypted);
+		os_free(in_decrypted);
 		wpa_printf(MSG_INFO, "EAP-PEAP: Length mismatch in "
-			   "Phase 2 EAP frame (len=%d hdr->length=%d)",
-			   len_decrypted, len);
+			   "Phase 2 EAP frame (len=%lu hdr->length=%lu)",
+			   (unsigned long) len_decrypted, (unsigned long) len);
 		return 0;
 	}
 	if (len < len_decrypted) {
 		wpa_printf(MSG_INFO, "EAP-PEAP: Odd.. Phase 2 EAP header has "
-			   "shorter length than full decrypted data (%d < %d)",
-			   len, len_decrypted);
+			   "shorter length than full decrypted data "
+			   "(%lu < %lu)",
+			   (unsigned long) len, (unsigned long) len_decrypted);
 		if (sm->workaround && len == 4 && len_decrypted == 5 &&
 		    in_decrypted[4] == EAP_TYPE_IDENTITY) {
 			/* Radiator 3.9 seems to set Phase 2 EAP header to use
@@ -500,19 +523,22 @@
 			 * This was fixed in 2004-06-23 patch for Radiator and
 			 * this workaround can be removed at some point. */
 			wpa_printf(MSG_INFO, "EAP-PEAP: workaround -> replace "
-				   "Phase 2 EAP header len (%d) with real "
-				   "decrypted len (%d)", len, len_decrypted);
+				   "Phase 2 EAP header len (%lu) with real "
+				   "decrypted len (%lu)",
+				   (unsigned long) len,
+				   (unsigned long) len_decrypted);
 			len = len_decrypted;
 			hdr->length = host_to_be16(len);
 		}
 	}
 	wpa_printf(MSG_DEBUG, "EAP-PEAP: received Phase 2: code=%d "
-		   "identifier=%d length=%d", hdr->code, hdr->identifier, len);
+		   "identifier=%d length=%lu", hdr->code, hdr->identifier,
+		   (unsigned long) len);
 	switch (hdr->code) {
 	case EAP_CODE_REQUEST:
-		if (eap_peap_phase2_request(sm, data, ret, req, hdr,
+		if (eap_peap_phase2_request(sm, data, ret, hdr,
 					    &resp, &resp_len)) {
-			free(in_decrypted);
+			os_free(in_decrypted);
 			wpa_printf(MSG_INFO, "EAP-PEAP: Phase2 Request "
 				   "processing failed");
 			return 0;
@@ -531,7 +557,7 @@
 			ret->methodState = METHOD_DONE;
 			data->phase2_success = 1;
 			if (data->peap_outer_success == 2) {
-				free(in_decrypted);
+				os_free(in_decrypted);
 				wpa_printf(MSG_DEBUG, "EAP-PEAP: Use TLS ACK "
 					   "to finish authentication");
 				return 1;
@@ -539,9 +565,8 @@
 				/* Reply with EAP-Success within the TLS
 				 * channel to complete the authentication. */
 				resp_len = sizeof(struct eap_hdr);
-				resp = malloc(resp_len);
+				resp = os_zalloc(resp_len);
 				if (resp) {
-					memset(resp, 0, resp_len);
 					rhdr = (struct eap_hdr *) resp;
 					rhdr->code = EAP_CODE_SUCCESS;
 					rhdr->identifier = hdr->identifier;
@@ -565,9 +590,8 @@
 		/* Reply with EAP-Failure within the TLS channel to complete
 		 * failure reporting. */
 		resp_len = sizeof(struct eap_hdr);
-		resp = malloc(resp_len);
+		resp = os_zalloc(resp_len);
 		if (resp) {
-			memset(resp, 0, resp_len);
 			rhdr = (struct eap_hdr *) resp;
 			rhdr->code = EAP_CODE_FAILURE;
 			rhdr->identifier = hdr->identifier;
@@ -580,20 +604,20 @@
 		break;
 	}
 
-	free(in_decrypted);
+	os_free(in_decrypted);
 
 	if (resp) {
 		u8 *resp_pos;
 		size_t resp_send_len;
-		int skip_change = 0;
+		int skip_change2 = 0;
 
 		wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 data",
 				resp, resp_len);
 		/* PEAP version changes */
 		if (resp_len >= 5 && resp[0] == EAP_CODE_RESPONSE &&
 		    resp[4] == EAP_TYPE_TLV)
-			skip_change = 1;
-		if (data->peap_version == 0 && !skip_change) {
+			skip_change2 = 1;
+		if (data->peap_version == 0 && !skip_change2) {
 			resp_pos = resp + sizeof(struct eap_hdr);
 			resp_send_len = resp_len - sizeof(struct eap_hdr);
 		} else {
@@ -607,7 +631,7 @@
 			wpa_printf(MSG_INFO, "EAP-PEAP: Failed to encrypt "
 				   "a Phase 2 frame");
 		}
-		free(resp);
+		os_free(resp);
 	}
 
 	return 0;
@@ -669,7 +693,7 @@
 			char *label;
 			wpa_printf(MSG_DEBUG,
 				   "EAP-PEAP: TLS done, proceed to Phase 2");
-			free(data->key_data);
+			os_free(data->key_data);
 			/* draft-josefsson-ppext-eap-tls-eap-05.txt
 			 * specifies that PEAPv1 would use "client PEAP
 			 * encryption" as the label. However, most existing
@@ -716,6 +740,19 @@
 
 			data->resuming = 0;
 		}
+
+		if (res == 2) {
+			/*
+			 * Application data included in the handshake message.
+			 */
+			os_free(data->pending_phase2_req);
+			data->pending_phase2_req = resp;
+			data->pending_phase2_req_len = *respDataLen;
+			resp = NULL;
+			*respDataLen = 0;
+			res = eap_peap_decrypt(sm, data, ret, req, pos, left,
+					       &resp, respDataLen);
+		}
 	}
 
 	if (ret->methodState == METHOD_DONE) {
@@ -742,7 +779,7 @@
 static void eap_peap_deinit_for_reauth(struct eap_sm *sm, void *priv)
 {
 	struct eap_peap_data *data = priv;
-	free(data->pending_phase2_req);
+	os_free(data->pending_phase2_req);
 	data->pending_phase2_req = NULL;
 }
 
@@ -750,12 +787,15 @@
 static void * eap_peap_init_for_reauth(struct eap_sm *sm, void *priv)
 {
 	struct eap_peap_data *data = priv;
-	free(data->key_data);
+	os_free(data->key_data);
 	data->key_data = NULL;
 	if (eap_tls_reauth_init(sm, &data->ssl)) {
-		free(data);
+		os_free(data);
 		return NULL;
 	}
+	if (data->phase2_priv && data->phase2_method &&
+	    data->phase2_method->init_for_reauth)
+		data->phase2_method->init_for_reauth(sm, data->phase2_priv);
 	data->phase2_success = 0;
 	data->resuming = 1;
 	sm->peap_done = FALSE;
@@ -767,13 +807,17 @@
 			       size_t buflen, int verbose)
 {
 	struct eap_peap_data *data = priv;
-	int len;
+	int len, ret;
 
 	len = eap_tls_status(sm, &data->ssl, buf, buflen, verbose);
 	if (data->phase2_method) {
-		len += snprintf(buf + len, buflen - len,
-				"EAP-PEAPv%d Phase2 method=%s\n",
-				data->peap_version, data->phase2_method->name);
+		ret = os_snprintf(buf + len, buflen - len,
+				  "EAP-PEAPv%d Phase2 method=%s\n",
+				  data->peap_version,
+				  data->phase2_method->name);
+		if (ret < 0 || (size_t) ret >= buflen - len)
+			return len;
+		len += ret;
 	}
 	return len;
 }
@@ -794,28 +838,39 @@
 	if (data->key_data == NULL || !data->phase2_success)
 		return NULL;
 
-	key = malloc(EAP_TLS_KEY_LEN);
+	key = os_malloc(EAP_TLS_KEY_LEN);
 	if (key == NULL)
 		return NULL;
 
 	*len = EAP_TLS_KEY_LEN;
-	memcpy(key, data->key_data, EAP_TLS_KEY_LEN);
+	os_memcpy(key, data->key_data, EAP_TLS_KEY_LEN);
 
 	return key;
 }
 
 
-const struct eap_method eap_method_peap =
+int eap_peer_peap_register(void)
 {
-	.method = EAP_TYPE_PEAP,
-	.name = "PEAP",
-	.init = eap_peap_init,
-	.deinit = eap_peap_deinit,
-	.process = eap_peap_process,
-	.isKeyAvailable = eap_peap_isKeyAvailable,
-	.getKey = eap_peap_getKey,
-	.get_status = eap_peap_get_status,
-	.has_reauth_data = eap_peap_has_reauth_data,
-	.deinit_for_reauth = eap_peap_deinit_for_reauth,
-	.init_for_reauth = eap_peap_init_for_reauth,
-};
+	struct eap_method *eap;
+	int ret;
+
+	eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
+				    EAP_VENDOR_IETF, EAP_TYPE_PEAP, "PEAP");
+	if (eap == NULL)
+		return -1;
+
+	eap->init = eap_peap_init;
+	eap->deinit = eap_peap_deinit;
+	eap->process = eap_peap_process;
+	eap->isKeyAvailable = eap_peap_isKeyAvailable;
+	eap->getKey = eap_peap_getKey;
+	eap->get_status = eap_peap_get_status;
+	eap->has_reauth_data = eap_peap_has_reauth_data;
+	eap->deinit_for_reauth = eap_peap_deinit_for_reauth;
+	eap->init_for_reauth = eap_peap_init_for_reauth;
+
+	ret = eap_peer_method_register(eap);
+	if (ret)
+		eap_peer_method_free(eap);
+	return ret;
+}
Index: radius_client.h
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/radius_client.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/radius_client.h -L contrib/wpa_supplicant/radius_client.h -u -r1.2 -r1.3
--- contrib/wpa_supplicant/radius_client.h
+++ contrib/wpa_supplicant/radius_client.h
@@ -1,3 +1,17 @@
+/*
+ * hostapd / RADIUS client
+ * Copyright (c) 2002-2005, Jouni Malinen <j at w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
 #ifndef RADIUS_CLIENT_H
 #define RADIUS_CLIENT_H
 
@@ -73,15 +87,19 @@
 			   void *data);
 int radius_client_send(struct radius_client_data *radius,
 		       struct radius_msg *msg,
-		       RadiusType msg_type, u8 *addr);
+		       RadiusType msg_type, const u8 *addr);
 u8 radius_client_get_id(struct radius_client_data *radius);
 
-void radius_client_flush(struct radius_client_data *radius);
+void radius_client_flush(struct radius_client_data *radius, int only_auth);
 struct radius_client_data *
 radius_client_init(void *ctx, struct hostapd_radius_servers *conf);
 void radius_client_deinit(struct radius_client_data *radius);
 void radius_client_flush_auth(struct radius_client_data *radius, u8 *addr);
 int radius_client_get_mib(struct radius_client_data *radius, char *buf,
 			  size_t buflen);
+struct radius_client_data *
+radius_client_reconfig(struct radius_client_data *old, void *ctx,
+		       struct hostapd_radius_servers *oldconf,
+		       struct hostapd_radius_servers *newconf);
 
 #endif /* RADIUS_CLIENT_H */
Index: config_file.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/config_file.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -L contrib/wpa_supplicant/config_file.c -L contrib/wpa_supplicant/config_file.c -u -r1.1 -r1.2
--- contrib/wpa_supplicant/config_file.c
+++ contrib/wpa_supplicant/config_file.c
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant / Configuration backend: text file
- * Copyright (c) 2003-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2003-2006, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -16,18 +16,30 @@
  * described in the sample configuration file, wpa_supplicant.conf.
  */
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
+#include "includes.h"
 
 #include "common.h"
-#include "wpa.h"
-#include "wpa_supplicant.h"
 #include "config.h"
 #include "base64.h"
+#include "eap_methods.h"
 
 
-static char * wpa_config_get_line(char *s, int size, FILE *stream, int *line)
+/**
+ * wpa_config_get_line - Read the next configuration file line
+ * @s: Buffer for the line
+ * @size: The buffer length
+ * @stream: File stream to read from
+ * @line: Pointer to a variable storing the file line number
+ * @_pos: Buffer for the pointer to the beginning of data on the text line or
+ * %NULL if not needed (returned value used instead)
+ * Returns: Pointer to the beginning of data on the text line or %NULL if no
+ * more text lines are available.
+ *
+ * This function reads the next non-empty line from the configuration file and
+ * removes comments. The returned string is guaranteed to be null-terminated.
+ */
+static char * wpa_config_get_line(char *s, int size, FILE *stream, int *line,
+				  char **_pos)
 {
 	char *pos, *end, *sstart;
 
@@ -36,39 +48,82 @@
 		s[size - 1] = '\0';
 		pos = s;
 
+		/* Skip white space from the beginning of line. */
 		while (*pos == ' ' || *pos == '\t' || *pos == '\r')
 			pos++;
-		if (*pos == '#' || *pos == '\n' || *pos == '\0' ||
-		    *pos == '\r')
+
+		/* Skip comment lines and empty lines */
+		if (*pos == '#' || *pos == '\n' || *pos == '\0')
 			continue;
 
-		/* Remove # comments unless they are within a double quoted
-		 * string. Remove trailing white space. */
-		sstart = strchr(pos, '"');
+		/*
+		 * Remove # comments unless they are within a double quoted
+		 * string.
+		 */
+		sstart = os_strchr(pos, '"');
 		if (sstart)
-			sstart = strrchr(sstart + 1, '"');
+			sstart = os_strrchr(sstart + 1, '"');
 		if (!sstart)
 			sstart = pos;
-		end = strchr(sstart, '#');
+		end = os_strchr(sstart, '#');
 		if (end)
 			*end-- = '\0';
 		else
-			end = pos + strlen(pos) - 1;
+			end = pos + os_strlen(pos) - 1;
+
+		/* Remove trailing white space. */
 		while (end > pos &&
 		       (*end == '\n' || *end == ' ' || *end == '\t' ||
-			*end == '\r')) {
+			*end == '\r'))
 			*end-- = '\0';
-		}
+
 		if (*pos == '\0')
 			continue;
 
+		if (_pos)
+			*_pos = pos;
 		return pos;
 	}
 
+	if (_pos)
+		*_pos = NULL;
 	return NULL;
 }
 
 
+static int wpa_config_validate_network(struct wpa_ssid *ssid, int line)
+{
+	int errors = 0;
+
+	if (ssid->passphrase) {
+		if (ssid->psk_set) {
+			wpa_printf(MSG_ERROR, "Line %d: both PSK and "
+				   "passphrase configured.", line);
+			errors++;
+		}
+		wpa_config_update_psk(ssid);
+	}
+
+	if ((ssid->key_mgmt & WPA_KEY_MGMT_PSK) && !ssid->psk_set) {
+		wpa_printf(MSG_ERROR, "Line %d: WPA-PSK accepted for key "
+			   "management, but no PSK configured.", line);
+		errors++;
+	}
+
+	if ((ssid->group_cipher & WPA_CIPHER_CCMP) &&
+	    !(ssid->pairwise_cipher & WPA_CIPHER_CCMP) &&
+	    !(ssid->pairwise_cipher & WPA_CIPHER_NONE)) {
+		/* Group cipher cannot be stronger than the pairwise cipher. */
+		wpa_printf(MSG_DEBUG, "Line %d: removed CCMP from group cipher"
+			   " list since it was not allowed for pairwise "
+			   "cipher", line);
+		ssid->group_cipher &= ~WPA_CIPHER_CCMP;
+	}
+
+	return errors;
+}
+
+
 static struct wpa_ssid * wpa_config_read_network(FILE *f, int *line, int id)
 {
 	struct wpa_ssid *ssid;
@@ -77,21 +132,20 @@
 
 	wpa_printf(MSG_MSGDUMP, "Line: %d - start of a new network block",
 		   *line);
-	ssid = (struct wpa_ssid *) malloc(sizeof(*ssid));
+	ssid = os_zalloc(sizeof(*ssid));
 	if (ssid == NULL)
 		return NULL;
-	memset(ssid, 0, sizeof(*ssid));
 	ssid->id = id;
 
 	wpa_config_set_network_defaults(ssid);
 
-	while ((pos = wpa_config_get_line(buf, sizeof(buf), f, line))) {
-		if (strcmp(pos, "}") == 0) {
+	while (wpa_config_get_line(buf, sizeof(buf), f, line, &pos)) {
+		if (os_strcmp(pos, "}") == 0) {
 			end = 1;
 			break;
 		}
 
-		pos2 = strchr(pos, '=');
+		pos2 = os_strchr(pos, '=');
 		if (pos2 == NULL) {
 			wpa_printf(MSG_ERROR, "Line %d: Invalid SSID line "
 				   "'%s'.", *line, pos);
@@ -101,7 +155,7 @@
 
 		*pos2++ = '\0';
 		if (*pos2 == '"') {
-			if (strchr(pos2 + 1, '"') == NULL) {
+			if (os_strchr(pos2 + 1, '"') == NULL) {
 				wpa_printf(MSG_ERROR, "Line %d: invalid "
 					   "quotation '%s'.", *line, pos2);
 				errors++;
@@ -119,32 +173,10 @@
 		errors++;
 	}
 
-	if (ssid->passphrase) {
-		if (ssid->psk_set) {
-			wpa_printf(MSG_ERROR, "Line %d: both PSK and "
-				   "passphrase configured.", *line);
-			errors++;
-		}
-		wpa_config_update_psk(ssid);
-	}
-
-	if ((ssid->key_mgmt & WPA_KEY_MGMT_PSK) && !ssid->psk_set) {
-		wpa_printf(MSG_ERROR, "Line %d: WPA-PSK accepted for key "
-			   "management, but no PSK configured.", *line);
-		errors++;
-	}
-
-	if ((ssid->group_cipher & WPA_CIPHER_CCMP) &&
-	    !(ssid->pairwise_cipher & WPA_CIPHER_CCMP)) {
-		/* Group cipher cannot be stronger than the pairwise cipher. */
-		wpa_printf(MSG_DEBUG, "Line %d: removed CCMP from group cipher"
-			   " list since it was not allowed for pairwise "
-			   "cipher", *line);
-		ssid->group_cipher &= ~WPA_CIPHER_CCMP;
-	}
+	errors += wpa_config_validate_network(ssid, *line);
 
 	if (errors) {
-		free(ssid);
+		wpa_config_free_ssid(ssid);
 		ssid = NULL;
 	}
 
@@ -164,41 +196,40 @@
 	wpa_printf(MSG_MSGDUMP, "Line: %d - start of a new named blob '%s'",
 		   *line, name);
 
-	while ((pos = wpa_config_get_line(buf, sizeof(buf), f, line))) {
-		if (strcmp(pos, "}") == 0) {
+	while (wpa_config_get_line(buf, sizeof(buf), f, line, &pos)) {
+		if (os_strcmp(pos, "}") == 0) {
 			end = 1;
 			break;
 		}
 
-		len = strlen(pos);
-		nencoded = realloc(encoded, encoded_len + len);
+		len = os_strlen(pos);
+		nencoded = os_realloc(encoded, encoded_len + len);
 		if (nencoded == NULL) {
 			wpa_printf(MSG_ERROR, "Line %d: not enough memory for "
 				   "blob", *line);
-			free(encoded);
+			os_free(encoded);
 			return NULL;
 		}
 		encoded = nencoded;
-		memcpy(encoded + encoded_len, pos, len);
+		os_memcpy(encoded + encoded_len, pos, len);
 		encoded_len += len;
 	}
 
 	if (!end) {
 		wpa_printf(MSG_ERROR, "Line %d: blob was not terminated "
 			   "properly", *line);
-		free(encoded);
+		os_free(encoded);
 		return NULL;
 	}
 
-	blob = malloc(sizeof(*blob));
+	blob = os_zalloc(sizeof(*blob));
 	if (blob == NULL) {
-		free(encoded);
+		os_free(encoded);
 		return NULL;
 	}
-	memset(blob, 0, sizeof(*blob));
-	blob->name = strdup(name);
+	blob->name = os_strdup(name);
 	blob->data = base64_decode(encoded, encoded_len, &blob->len);
-	free(encoded);
+	os_free(encoded);
 
 	if (blob->name == NULL || blob->data == NULL) {
 		wpa_config_free_blob(blob);
@@ -216,7 +247,7 @@
 	int errors = 0, line = 0;
 	struct wpa_ssid *ssid, *tail = NULL, *head = NULL;
 	struct wpa_config *config;
-	int id = 0, prio;
+	int id = 0;
 
 	config = wpa_config_alloc_empty(NULL, NULL);
 	if (config == NULL)
@@ -224,12 +255,12 @@
 	wpa_printf(MSG_DEBUG, "Reading configuration file '%s'", name);
 	f = fopen(name, "r");
 	if (f == NULL) {
-		free(config);
+		os_free(config);
 		return NULL;
 	}
 
-	while ((pos = wpa_config_get_line(buf, sizeof(buf), f, &line))) {
-		if (strcmp(pos, "network={") == 0) {
+	while (wpa_config_get_line(buf, sizeof(buf), f, &line, &pos)) {
+		if (os_strcmp(pos, "network={") == 0) {
 			ssid = wpa_config_read_network(f, &line, id++);
 			if (ssid == NULL) {
 				wpa_printf(MSG_ERROR, "Line %d: failed to "
@@ -250,11 +281,11 @@
 				errors++;
 				continue;
 			}
-		} else if (strncmp(pos, "blob-base64-", 12) == 0) {
-			char *name = pos + 12, *name_end;
+		} else if (os_strncmp(pos, "blob-base64-", 12) == 0) {
+			char *bname = pos + 12, *name_end;
 			struct wpa_config_blob *blob;
 
-			name_end = strchr(name, '=');
+			name_end = os_strchr(bname, '=');
 			if (name_end == NULL) {
 				wpa_printf(MSG_ERROR, "Line %d: no blob name "
 					   "terminator", line);
@@ -263,51 +294,28 @@
 			}
 			*name_end = '\0';
 
-			blob = wpa_config_read_blob(f, &line, name);
+			blob = wpa_config_read_blob(f, &line, bname);
 			if (blob == NULL) {
 				wpa_printf(MSG_ERROR, "Line %d: failed to read"
-					   " blob %s", line, name);
+					   " blob %s", line, bname);
 				errors++;
 				continue;
 			}
 			wpa_config_set_blob(config, blob);
 #ifdef CONFIG_CTRL_IFACE
-		} else if (strncmp(pos, "ctrl_interface=", 15) == 0) {
-			free(config->ctrl_interface);
-			config->ctrl_interface = strdup(pos + 15);
+		} else if (os_strncmp(pos, "ctrl_interface=", 15) == 0) {
+			os_free(config->ctrl_interface);
+			config->ctrl_interface = os_strdup(pos + 15);
 			wpa_printf(MSG_DEBUG, "ctrl_interface='%s'",
 				   config->ctrl_interface);
-#ifndef CONFIG_CTRL_IFACE_UDP
-		} else if (strncmp(pos, "ctrl_interface_group=", 21) == 0) {
-			struct group *grp;
-			char *endp;
-			const char *group = pos + 21;
-
-			grp = getgrnam(group);
-			if (grp) {
-				config->ctrl_interface_gid = grp->gr_gid;
-				config->ctrl_interface_gid_set = 1;
-				wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d"
-					   " (from group name '%s')",
-					   (int) config->ctrl_interface_gid,
-					   group);
-				continue;
-			}
-
-			/* Group name not found - try to parse this as gid */
-			config->ctrl_interface_gid = strtol(group, &endp, 10);
-			if (*group == '\0' || *endp != '\0') {
-				wpa_printf(MSG_DEBUG, "Line %d: Invalid group "
-					   "'%s'", line, group);
-				errors++;
-				continue;
-			}
-			config->ctrl_interface_gid_set = 1;
-			wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d",
-				   (int) config->ctrl_interface_gid);
-#endif /* CONFIG_CTRL_IFACE_UDP */
+		} else if (os_strncmp(pos, "ctrl_interface_group=", 21) == 0) {
+			os_free(config->ctrl_interface_group);
+			config->ctrl_interface_group = os_strdup(pos + 21);
+			wpa_printf(MSG_DEBUG, "ctrl_interface_group='%s' "
+				   "(DEPRECATED)",
+				   config->ctrl_interface_group);
 #endif /* CONFIG_CTRL_IFACE */
-		} else if (strncmp(pos, "eapol_version=", 14) == 0) {
+		} else if (os_strncmp(pos, "eapol_version=", 14) == 0) {
 			config->eapol_version = atoi(pos + 14);
 			if (config->eapol_version < 1 ||
 			    config->eapol_version > 2) {
@@ -319,55 +327,69 @@
 			}
 			wpa_printf(MSG_DEBUG, "eapol_version=%d",
 				   config->eapol_version);
-		} else if (strncmp(pos, "ap_scan=", 8) == 0) {
+		} else if (os_strncmp(pos, "ap_scan=", 8) == 0) {
 			config->ap_scan = atoi(pos + 8);
 			wpa_printf(MSG_DEBUG, "ap_scan=%d", config->ap_scan);
-		} else if (strncmp(pos, "fast_reauth=", 12) == 0) {
+		} else if (os_strncmp(pos, "fast_reauth=", 12) == 0) {
 			config->fast_reauth = atoi(pos + 12);
 			wpa_printf(MSG_DEBUG, "fast_reauth=%d",
 				   config->fast_reauth);
-		} else if (strncmp(pos, "opensc_engine_path=", 19) == 0) {
-			free(config->opensc_engine_path);
-			config->opensc_engine_path = strdup(pos + 19);
+		} else if (os_strncmp(pos, "opensc_engine_path=", 19) == 0) {
+			os_free(config->opensc_engine_path);
+			config->opensc_engine_path = os_strdup(pos + 19);
 			wpa_printf(MSG_DEBUG, "opensc_engine_path='%s'",
 				   config->opensc_engine_path);
-		} else if (strncmp(pos, "pkcs11_engine_path=", 19) == 0) {
-			free(config->pkcs11_engine_path);
-			config->pkcs11_engine_path = strdup(pos + 19);
+		} else if (os_strncmp(pos, "pkcs11_engine_path=", 19) == 0) {
+			os_free(config->pkcs11_engine_path);
+			config->pkcs11_engine_path = os_strdup(pos + 19);
 			wpa_printf(MSG_DEBUG, "pkcs11_engine_path='%s'",
 				   config->pkcs11_engine_path);
-		} else if (strncmp(pos, "pkcs11_module_path=", 19) == 0) {
-			free(config->pkcs11_module_path);
-			config->pkcs11_module_path = strdup(pos + 19);
+		} else if (os_strncmp(pos, "pkcs11_module_path=", 19) == 0) {
+			os_free(config->pkcs11_module_path);
+			config->pkcs11_module_path = os_strdup(pos + 19);
 			wpa_printf(MSG_DEBUG, "pkcs11_module_path='%s'",
 				   config->pkcs11_module_path);
-		} else if (strncmp(pos, "driver_param=", 13) == 0) {
-			free(config->driver_param);
-			config->driver_param = strdup(pos + 13);
+		} else if (os_strncmp(pos, "driver_param=", 13) == 0) {
+			os_free(config->driver_param);
+			config->driver_param = os_strdup(pos + 13);
 			wpa_printf(MSG_DEBUG, "driver_param='%s'",
 				   config->driver_param);
-		} else if (strncmp(pos, "dot11RSNAConfigPMKLifetime=", 27) ==
-			   0) {
+		} else if (os_strncmp(pos, "dot11RSNAConfigPMKLifetime=", 27)
+			   == 0) {
 			config->dot11RSNAConfigPMKLifetime = atoi(pos + 27);
 			wpa_printf(MSG_DEBUG, "dot11RSNAConfigPMKLifetime=%d",
 				   config->dot11RSNAConfigPMKLifetime);
-		} else if (strncmp(pos, "dot11RSNAConfigPMKReauthThreshold=",
-				   34) ==
-			   0) {
+		} else if (os_strncmp(pos,
+				      "dot11RSNAConfigPMKReauthThreshold=", 34)
+			   == 0) {
 			config->dot11RSNAConfigPMKReauthThreshold =
 				atoi(pos + 34);
 			wpa_printf(MSG_DEBUG,
 				   "dot11RSNAConfigPMKReauthThreshold=%d",
 				   config->dot11RSNAConfigPMKReauthThreshold);
-		} else if (strncmp(pos, "dot11RSNAConfigSATimeout=", 25) ==
+		} else if (os_strncmp(pos, "dot11RSNAConfigSATimeout=", 25) ==
 			   0) {
 			config->dot11RSNAConfigSATimeout = atoi(pos + 25);
 			wpa_printf(MSG_DEBUG, "dot11RSNAConfigSATimeout=%d",
 				   config->dot11RSNAConfigSATimeout);
-		} else if (strncmp(pos, "update_config=", 14) == 0) {
+		} else if (os_strncmp(pos, "update_config=", 14) == 0) {
 			config->update_config = atoi(pos + 14);
 			wpa_printf(MSG_DEBUG, "update_config=%d",
 				   config->update_config);
+		} else if (os_strncmp(pos, "load_dynamic_eap=", 17) == 0) {
+			char *so = pos + 17;
+			int ret;
+			wpa_printf(MSG_DEBUG, "load_dynamic_eap=%s", so);
+			ret = eap_peer_method_load(so);
+			if (ret == -2) {
+				wpa_printf(MSG_DEBUG, "This EAP type was "
+					   "already loaded - not reloading.");
+			} else if (ret) {
+				wpa_printf(MSG_ERROR, "Line %d: Failed to "
+					   "load dynamic EAP method '%s'.",
+					   line, so);
+				errors++;
+			}
 		} else {
 			wpa_printf(MSG_ERROR, "Line %d: Invalid configuration "
 				   "line '%s'.", line, pos);
@@ -379,17 +401,8 @@
 	fclose(f);
 
 	config->ssid = head;
-	for (prio = 0; prio < config->num_prio; prio++) {
-		ssid = config->pssid[prio];
-		wpa_printf(MSG_DEBUG, "Priority group %d",
-			   ssid->priority);
-		while (ssid) {
-			wpa_printf(MSG_DEBUG, "   id=%d ssid='%s'",
-				   ssid->id,
-				   wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
-			ssid = ssid->pnext;
-		}
-	}
+	wpa_config_debug_dump_networks(config);
+
 	if (errors) {
 		wpa_config_free(config);
 		config = NULL;
@@ -406,7 +419,7 @@
 	if (value == NULL)
 		return;
 	fprintf(f, "\t%s=%s\n", field, value);
-	free(value);
+	os_free(value);
 }
 
 
@@ -424,7 +437,7 @@
 	if (value == NULL)
 		return;
 	fprintf(f, "\tbssid=%s\n", value);
-	free(value);
+	os_free(value);
 }
 
 
@@ -434,7 +447,7 @@
 	if (value == NULL)
 		return;
 	fprintf(f, "\tpsk=%s\n", value);
-	free(value);
+	os_free(value);
 }
 
 
@@ -450,7 +463,7 @@
 		return;
 	if (value[0])
 		fprintf(f, "\tproto=%s\n", value);
-	free(value);
+	os_free(value);
 }
 
 
@@ -466,7 +479,7 @@
 		return;
 	if (value[0])
 		fprintf(f, "\tkey_mgmt=%s\n", value);
-	free(value);
+	os_free(value);
 }
 
 
@@ -482,7 +495,7 @@
 		return;
 	if (value[0])
 		fprintf(f, "\tpairwise=%s\n", value);
-	free(value);
+	os_free(value);
 }
 
 
@@ -498,7 +511,7 @@
 		return;
 	if (value[0])
 		fprintf(f, "\tgroup=%s\n", value);
-	free(value);
+	os_free(value);
 }
 
 
@@ -514,10 +527,11 @@
 		return;
 	if (value[0])
 		fprintf(f, "\tauth_alg=%s\n", value);
-	free(value);
+	os_free(value);
 }
 
 
+#ifdef IEEE8021X_EAPOL
 static void write_eap(FILE *f, struct wpa_ssid *ssid)
 {
 	char *value;
@@ -528,19 +542,20 @@
 
 	if (value[0])
 		fprintf(f, "\teap=%s\n", value);
-	free(value);
+	os_free(value);
 }
+#endif /* IEEE8021X_EAPOL */
 
 
 static void write_wep_key(FILE *f, int idx, struct wpa_ssid *ssid)
 {
 	char field[20], *value;
 
-	snprintf(field, sizeof(field), "wep_key%d", idx);
+	os_snprintf(field, sizeof(field), "wep_key%d", idx);
 	value = wpa_config_get(ssid, field);
 	if (value) {
 		fprintf(f, "\t%s=%s\n", field, value);
-		free(value);
+		os_free(value);
 	}
 }
 
@@ -562,6 +577,7 @@
 	write_pairwise(f, ssid);
 	write_group(f, ssid);
 	write_auth_alg(f, ssid);
+#ifdef IEEE8021X_EAPOL
 	write_eap(f, ssid);
 	STR(identity);
 	STR(anonymous_identity);
@@ -569,6 +585,7 @@
 	STR(nai);
 	STR(password);
 	STR(ca_cert);
+	STR(ca_path);
 	STR(client_cert);
 	STR(private_key);
 	STR(private_key_passwd);
@@ -576,6 +593,7 @@
 	STR(subject_match);
 	STR(altsubject_match);
 	STR(ca_cert2);
+	STR(ca_path2);
 	STR(client_cert2);
 	STR(private_key2);
 	STR(private_key2_passwd);
@@ -590,15 +608,24 @@
 	STR(key_id);
 	INT(engine);
 	INT_DEF(eapol_flags, DEFAULT_EAPOL_FLAGS);
+#endif /* IEEE8021X_EAPOL */
 	for (i = 0; i < 4; i++)
 		write_wep_key(f, i, ssid);
 	INT(wep_tx_keyidx);
 	INT(priority);
+#ifdef IEEE8021X_EAPOL
 	INT_DEF(eap_workaround, DEFAULT_EAP_WORKAROUND);
 	STR(pac_file);
+	INT_DEF(fragment_size, DEFAULT_FRAGMENT_SIZE);
+#endif /* IEEE8021X_EAPOL */
 	INT(mode);
 	INT(proactive_key_caching);
 	INT(disabled);
+	INT(peerkey);
+#ifdef CONFIG_IEEE80211W
+	INT(ieee80211w);
+#endif /* CONFIG_IEEE80211W */
+	STR(id_str);
 
 #undef STR
 #undef INT
@@ -615,36 +642,19 @@
 		return -1;
 
 	fprintf(f, "\nblob-base64-%s={\n%s}\n", blob->name, encoded);
-	free(encoded);
+	os_free(encoded);
 	return 0;
 }
 
 
-int wpa_config_write(const char *name, struct wpa_config *config)
+static void wpa_config_write_global(FILE *f, struct wpa_config *config)
 {
-	FILE *f;
-	struct wpa_ssid *ssid;
-	struct wpa_config_blob *blob;
-	int ret = 0;
-
-	wpa_printf(MSG_DEBUG, "Writing configuration file '%s'", name);
-
-
-	f = fopen(name, "w");
-	if (f == NULL) {
-		wpa_printf(MSG_DEBUG, "Failed to open '%s' for writing", name);
-		return -1;
-	}
-
 #ifdef CONFIG_CTRL_IFACE
 	if (config->ctrl_interface)
 		fprintf(f, "ctrl_interface=%s\n", config->ctrl_interface);
-#ifndef CONFIG_CTRL_IFACE_UDP
-	if (config->ctrl_interface_gid_set) {
-		fprintf(f, "ctrl_interface_group=%d\n",
-			(int) config->ctrl_interface_gid);
-	}
-#endif /* CONFIG_CTRL_IFACE_UDP */
+	if (config->ctrl_interface_group)
+		fprintf(f, "ctrl_interface_group=%s\n",
+			config->ctrl_interface_group);
 #endif /* CONFIG_CTRL_IFACE */
 	if (config->eapol_version != DEFAULT_EAPOL_VERSION)
 		fprintf(f, "eapol_version=%d\n", config->eapol_version);
@@ -674,6 +684,25 @@
 			config->dot11RSNAConfigSATimeout);
 	if (config->update_config)
 		fprintf(f, "update_config=%d\n", config->update_config);
+}
+
+
+int wpa_config_write(const char *name, struct wpa_config *config)
+{
+	FILE *f;
+	struct wpa_ssid *ssid;
+	struct wpa_config_blob *blob;
+	int ret = 0;
+
+	wpa_printf(MSG_DEBUG, "Writing configuration file '%s'", name);
+
+	f = fopen(name, "w");
+	if (f == NULL) {
+		wpa_printf(MSG_DEBUG, "Failed to open '%s' for writing", name);
+		return -1;
+	}
+
+	wpa_config_write_global(f, config);
 
 	for (ssid = config->ssid; ssid; ssid = ssid->next) {
 		fprintf(f, "\nnetwork={\n");
Index: tls_openssl.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/tls_openssl.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/tls_openssl.c -L contrib/wpa_supplicant/tls_openssl.c -u -r1.2 -r1.3
--- contrib/wpa_supplicant/tls_openssl.c
+++ contrib/wpa_supplicant/tls_openssl.c
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant / SSL/TLS interface functions for openssl
- * Copyright (c) 2004-2006, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2004-2006, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -12,9 +12,7 @@
  * See README and COPYING for more details.
  */
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
+#include "includes.h"
 
 #ifndef CONFIG_SMARTCARD
 #ifndef OPENSSL_NO_ENGINE
@@ -235,7 +233,7 @@
 		goto err;
 	}
 
-	if (hash_size != flen) {
+	if ((int) hash_size != flen) {
 		wpa_printf(MSG_INFO, "CryptoAPI: Invalid hash size (%u != %d)",
 			   (unsigned) hash_size, flen);
 		RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT,
@@ -248,7 +246,7 @@
 	}
 
 	len = RSA_size(rsa);
-	buf = malloc(len);
+	buf = os_malloc(len);
 	if (buf == NULL) {
 		RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, ERR_R_MALLOC_FAILURE);
 		goto err;
@@ -264,7 +262,7 @@
 	ret = len;
 
 err:
-	free(buf);
+	os_free(buf);
 	CryptDestroyHash(hash);
 
 	return ret;
@@ -287,14 +285,14 @@
 		CryptReleaseContext(priv->crypt_prov, 0);
 	if (priv->cert)
 		CertFreeCertificateContext(priv->cert);
-	free(priv);
+	os_free(priv);
 }
 
 
 static int cryptoapi_finish(RSA *rsa)
 {
 	cryptoapi_free_data((struct cryptoapi_rsa_data *) rsa->meth->app_data);
-	free((void *) rsa->meth);
+	os_free((void *) rsa->meth);
 	rsa->meth = NULL;
 	return 1;
 }
@@ -315,8 +313,7 @@
 
 	if (strncmp(name, "cert://", 7) == 0) {
 		unsigned short wbuf[255];
-		MultiByteToWideChar(CP_ACP, 0, name + 7, -1,
-				    wbuf, sizeof(wbuf));
+		MultiByteToWideChar(CP_ACP, 0, name + 7, -1, wbuf, 255);
 		ret = CertFindCertificateInStore(cs, X509_ASN_ENCODING |
 						 PKCS_7_ASN_ENCODING,
 						 0, CERT_FIND_SUBJECT_STR,
@@ -327,8 +324,8 @@
 		const char *hash = name + 7;
 		unsigned char *buf;
 
-		len = strlen(hash) / 2;
-		buf = malloc(len);
+		len = os_strlen(hash) / 2;
+		buf = os_malloc(len);
 		if (buf && hexstr2bin(hash, buf, len) == 0) {
 			blob.cbData = len;
 			blob.pbData = buf;
@@ -338,7 +335,7 @@
 							 0, CERT_FIND_HASH,
 							 &blob, NULL);
 		}
-		free(buf);
+		os_free(buf);
 	}
 
 	CertCloseStore(cs, 0);
@@ -359,17 +356,15 @@
 	     strncmp(name, "hash://", 7) != 0))
 		return -1;
 
-	priv = malloc(sizeof(*priv));
-	rsa_meth = malloc(sizeof(*rsa_meth));
+	priv = os_zalloc(sizeof(*priv));
+	rsa_meth = os_zalloc(sizeof(*rsa_meth));
 	if (priv == NULL || rsa_meth == NULL) {
 		wpa_printf(MSG_WARNING, "CryptoAPI: Failed to allocate memory "
 			   "for CryptoAPI RSA method");
-		free(priv);
-		free(rsa_meth);
+		os_free(priv);
+		os_free(rsa_meth);
 		return -1;
 	}
-	memset(priv, 0, sizeof(*priv));
-	memset(rsa_meth, 0, sizeof(*rsa_meth));
 
 	priv->cert = cryptoapi_find_cert(name, CERT_SYSTEM_STORE_CURRENT_USER);
 	if (priv->cert == NULL) {
@@ -419,8 +414,11 @@
 		goto err;
 	}
 
-	if (!SSL_use_certificate(ssl, cert))
+	if (!SSL_use_certificate(ssl, cert)) {
+		RSA_free(rsa);
+		rsa = NULL;
 		goto err;
+	}
 	pub_rsa = cert->cert_info->key->pkey->pkey.rsa;
 	X509_free(cert);
 	cert = NULL;
@@ -442,7 +440,7 @@
 	if (rsa)
 		RSA_free(rsa);
 	else {
-		free(rsa_meth);
+		os_free(rsa_meth);
 		cryptoapi_free_data(priv);
 	}
 	return -1;
@@ -455,6 +453,10 @@
 	PCCERT_CONTEXT ctx = NULL;
 	X509 *cert;
 	char buf[128];
+	const char *store;
+#ifdef UNICODE
+	WCHAR *wstore;
+#endif /* UNICODE */
 
 	if (mingw_load_crypto_func())
 		return -1;
@@ -462,10 +464,20 @@
 	if (name == NULL || strncmp(name, "cert_store://", 13) != 0)
 		return -1;
 
-	cs = CertOpenSystemStore(0, name + 13);
+	store = name + 13;
+#ifdef UNICODE
+	wstore = os_malloc((os_strlen(store) + 1) * sizeof(WCHAR));
+	if (wstore == NULL)
+		return -1;
+	wsprintf(wstore, L"%S", store);
+	cs = CertOpenSystemStore(0, wstore);
+	os_free(wstore);
+#else /* UNICODE */
+	cs = CertOpenSystemStore(0, store);
+#endif /* UNICODE */
 	if (cs == NULL) {
 		wpa_printf(MSG_DEBUG, "%s: failed to open system cert store "
-			   "'%s': error=%d", __func__, name + 13,
+			   "'%s': error=%d", __func__, store,
 			   (int) GetLastError());
 		return -1;
 	}
@@ -643,21 +655,25 @@
 {
 	char *engine_id = "pkcs11";
 	const char *pre_cmd[] = {
-		"SO_PATH", pkcs11_so_path,
-		"ID", engine_id,
+		"SO_PATH", NULL /* pkcs11_so_path */,
+		"ID", NULL /* engine_id */,
 		"LIST_ADD", "1",
 		/* "NO_VCHECK", "1", */
 		"LOAD", NULL,
 		NULL, NULL
 	};
 	const char *post_cmd[] = {
-		"MODULE_PATH", pkcs11_module_path,
+		"MODULE_PATH", NULL /* pkcs11_module_path */,
 		NULL, NULL
 	};
 
 	if (!pkcs11_so_path || !pkcs11_module_path)
 		return 0;
 
+	pre_cmd[1] = pkcs11_so_path;
+	pre_cmd[3] = engine_id;
+	post_cmd[1] = pkcs11_module_path;
+
 	wpa_printf(MSG_DEBUG, "ENGINE: Loading pkcs11 Engine from %s",
 		   pkcs11_so_path);
 
@@ -673,8 +689,8 @@
 {
 	char *engine_id = "opensc";
 	const char *pre_cmd[] = {
-		"SO_PATH", opensc_so_path,
-		"ID", engine_id,
+		"SO_PATH", NULL /* opensc_so_path */,
+		"ID", NULL /* engine_id */,
 		"LIST_ADD", "1",
 		"LOAD", NULL,
 		NULL, NULL
@@ -683,6 +699,9 @@
 	if (!opensc_so_path)
 		return 0;
 
+	pre_cmd[1] = opensc_so_path;
+	pre_cmd[3] = engine_id;
+
 	wpa_printf(MSG_DEBUG, "ENGINE: Loading OpenSC Engine from %s",
 		   opensc_so_path);
 
@@ -853,15 +872,14 @@
 	SSL_CTX *ssl = ssl_ctx;
 	struct tls_connection *conn;
 
-	conn = malloc(sizeof(*conn));
+	conn = os_zalloc(sizeof(*conn));
 	if (conn == NULL)
 		return NULL;
-	memset(conn, 0, sizeof(*conn));
 	conn->ssl = SSL_new(ssl);
 	if (conn->ssl == NULL) {
 		tls_show_errors(MSG_INFO, __func__,
 				"Failed to initialize new SSL connection");
-		free(conn);
+		os_free(conn);
 		return NULL;
 	}
 
@@ -875,7 +893,7 @@
 		tls_show_errors(MSG_INFO, __func__,
 				"Failed to create a new BIO for ssl_in");
 		SSL_free(conn->ssl);
-		free(conn);
+		os_free(conn);
 		return NULL;
 	}
 
@@ -885,7 +903,7 @@
 				"Failed to create a new BIO for ssl_out");
 		SSL_free(conn->ssl);
 		BIO_free(conn->ssl_in);
-		free(conn);
+		os_free(conn);
 		return NULL;
 	}
 
@@ -899,12 +917,12 @@
 {
 	if (conn == NULL)
 		return;
-	free(conn->pre_shared_secret);
+	os_free(conn->pre_shared_secret);
 	SSL_free(conn->ssl);
 	tls_engine_deinit(conn);
-	free(conn->subject_match);
-	free(conn->altsubject_match);
-	free(conn);
+	os_free(conn->subject_match);
+	os_free(conn->altsubject_match);
+	os_free(conn);
 }
 
 
@@ -928,55 +946,71 @@
 }
 
 
-static int tls_match_altsubject(X509 *cert, const char *match)
+static int tls_match_altsubject_component(X509 *cert, int type,
+					  const char *value, size_t len)
 {
 	GENERAL_NAME *gen;
-	char *field, *tmp;
 	void *ext;
 	int i, found = 0;
-	size_t len;
 
 	ext = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
 
 	for (i = 0; ext && i < sk_GENERAL_NAME_num(ext); i++) {
 		gen = sk_GENERAL_NAME_value(ext, i);
-		switch (gen->type) {
-		case GEN_EMAIL:
-			field = "EMAIL";
-			break;
-		case GEN_DNS:
-			field = "DNS";
-			break;
-		case GEN_URI:
-			field = "URI";
-			break;
-		default:
-			field = NULL;
-			wpa_printf(MSG_DEBUG, "TLS: altSubjectName: "
-				   "unsupported type=%d", gen->type);
-			break;
-		}
-
-		if (!field)
+		if (gen->type != type)
 			continue;
-
-		wpa_printf(MSG_DEBUG, "TLS: altSubjectName: %s:%s",
-			   field, gen->d.ia5->data);
-		len = strlen(field) + 1 + strlen((char *) gen->d.ia5->data) +
-			1;
-		tmp = malloc(len);
-		if (tmp == NULL)
-			continue;
-		snprintf(tmp, len, "%s:%s", field, gen->d.ia5->data);
-		if (strstr(tmp, match))
+		if (os_strlen((char *) gen->d.ia5->data) == len &&
+		    os_memcmp(value, gen->d.ia5->data, len) == 0)
 			found++;
-		free(tmp);
 	}
 
 	return found;
 }
 
 
+static int tls_match_altsubject(X509 *cert, const char *match)
+{
+	int type;
+	const char *pos, *end;
+	size_t len;
+
+	pos = match;
+	do {
+		if (os_strncmp(pos, "EMAIL:", 6) == 0) {
+			type = GEN_EMAIL;
+			pos += 6;
+		} else if (os_strncmp(pos, "DNS:", 4) == 0) {
+			type = GEN_DNS;
+			pos += 4;
+		} else if (os_strncmp(pos, "URI:", 4) == 0) {
+			type = GEN_URI;
+			pos += 4;
+		} else {
+			wpa_printf(MSG_INFO, "TLS: Invalid altSubjectName "
+				   "match '%s'", pos);
+			return 0;
+		}
+		end = os_strchr(pos, ';');
+		while (end) {
+			if (os_strncmp(end + 1, "EMAIL:", 6) == 0 ||
+			    os_strncmp(end + 1, "DNS:", 4) == 0 ||
+			    os_strncmp(end + 1, "URI:", 4) == 0)
+				break;
+			end = os_strchr(end + 1, ';');
+		}
+		if (end)
+			len = end - pos;
+		else
+			len = os_strlen(pos);
+		if (tls_match_altsubject_component(cert, type, pos, len) > 0)
+			return 1;
+		pos = end + 1;
+	} while (end);
+
+	return 0;
+}
+
+
 static int tls_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
 {
 	char buf[256];
@@ -1006,7 +1040,7 @@
 			   "preverify_ok=%d err=%d (%s) depth=%d buf='%s'",
 			   preverify_ok, err,
 			   X509_verify_cert_error_string(err), depth, buf);
-		if (depth == 0 && match && strstr(buf, match) == NULL) {
+		if (depth == 0 && match && os_strstr(buf, match) == NULL) {
 			wpa_printf(MSG_WARNING, "TLS: Subject '%s' did not "
 				   "match with '%s'", buf, match);
 			preverify_ok = 0;
@@ -1071,11 +1105,20 @@
 		}
 
 		if (!X509_STORE_add_cert(ssl_ctx->cert_store, cert)) {
+			unsigned long err = ERR_peek_error();
 			tls_show_errors(MSG_WARNING, __func__,
 					"Failed to add ca_cert_blob to "
 					"certificate store");
-			X509_free(cert);
-			return -1;
+			if (ERR_GET_LIB(err) == ERR_LIB_X509 &&
+			    ERR_GET_REASON(err) ==
+			    X509_R_CERT_ALREADY_IN_HASH_TABLE) {
+				wpa_printf(MSG_DEBUG, "OpenSSL: %s - ignoring "
+					   "cert already in hash table error",
+					   __func__);
+			} else {
+				X509_free(cert);
+				return -1;
+			}
 		}
 		X509_free(cert);
 		wpa_printf(MSG_DEBUG, "OpenSSL: %s - added ca_cert_blob "
@@ -1128,9 +1171,8 @@
 }
 
 
-int tls_global_ca_cert(void *_ssl_ctx, const char *ca_cert)
+static int tls_global_ca_cert(SSL_CTX *ssl_ctx, const char *ca_cert)
 {
-	SSL_CTX *ssl_ctx = _ssl_ctx;
 	if (ca_cert) {
 		if (SSL_CTX_load_verify_locations(ssl_ctx, ca_cert, NULL) != 1)
 		{
@@ -1174,23 +1216,22 @@
 }
 
 
-static int tls_connection_set_subject_match(void *ssl_ctx,
-					    struct tls_connection *conn,
+static int tls_connection_set_subject_match(struct tls_connection *conn,
 					    const char *subject_match,
 					    const char *altsubject_match)
 {
-	free(conn->subject_match);
+	os_free(conn->subject_match);
 	conn->subject_match = NULL;
 	if (subject_match) {
-		conn->subject_match = strdup(subject_match);
+		conn->subject_match = os_strdup(subject_match);
 		if (conn->subject_match == NULL)
 			return -1;
 	}
 
-	free(conn->altsubject_match);
+	os_free(conn->altsubject_match);
 	conn->altsubject_match = NULL;
 	if (altsubject_match) {
-		conn->altsubject_match = strdup(altsubject_match);
+		conn->altsubject_match = os_strdup(altsubject_match);
 		if (conn->altsubject_match == NULL)
 			return -1;
 	}
@@ -1219,8 +1260,7 @@
 }
 
 
-static int tls_connection_client_cert(void *ssl_ctx,
-				      struct tls_connection *conn,
+static int tls_connection_client_cert(struct tls_connection *conn,
 				      const char *client_cert,
 				      const u8 *client_cert_blob,
 				      size_t client_cert_blob_len)
@@ -1270,10 +1310,9 @@
 }
 
 
-int tls_global_client_cert(void *_ssl_ctx, const char *client_cert)
+static int tls_global_client_cert(SSL_CTX *ssl_ctx, const char *client_cert)
 {
 #ifndef OPENSSL_NO_STDIO
-	SSL_CTX *ssl_ctx = _ssl_ctx;
 	if (client_cert == NULL)
 		return 0;
 
@@ -1300,9 +1339,9 @@
 	if (password == NULL) {
 		return 0;
 	}
-	strncpy(buf, (char *) password, size);
+	os_strncpy(buf, (char *) password, size);
 	buf[size - 1] = '\0';
-	return strlen(buf);
+	return os_strlen(buf);
 }
 
 
@@ -1322,6 +1361,7 @@
 	if (!PKCS12_parse(p12, passwd, &pkey, &cert, &certs)) {
 		tls_show_errors(MSG_DEBUG, __func__,
 				"Failed to parse PKCS12 file");
+		PKCS12_free(p12);
 		return -1;
 	}
 	wpa_printf(MSG_DEBUG, "TLS: Successfully parsed PKCS12 data");
@@ -1388,7 +1428,7 @@
 	FILE *f;
 	PKCS12 *p12;
 
-	f = fopen(private_key, "r");
+	f = fopen(private_key, "rb");
 	if (f == NULL)
 		return -1;
 
@@ -1434,8 +1474,7 @@
 }
 
 
-static int tls_connection_engine_private_key(void *_ssl_ctx,
-					     struct tls_connection *conn)
+static int tls_connection_engine_private_key(struct tls_connection *conn)
 {
 #ifndef OPENSSL_NO_ENGINE
 	if (SSL_use_PrivateKey(conn->ssl, conn->private_key) != 1) {
@@ -1472,7 +1511,7 @@
 		return 0;
 
 	if (private_key_passwd) {
-		passwd = strdup(private_key_passwd);
+		passwd = os_strdup(private_key_passwd);
 		if (passwd == NULL)
 			return -1;
 	} else
@@ -1582,13 +1621,13 @@
 
 	if (!ok) {
 		wpa_printf(MSG_INFO, "OpenSSL: Failed to load private key");
-		free(passwd);
+		os_free(passwd);
 		ERR_clear_error();
 		return -1;
 	}
 	ERR_clear_error();
 	SSL_CTX_set_default_passwd_cb(ssl_ctx, NULL);
-	free(passwd);
+	os_free(passwd);
 	
 	if (!SSL_check_private_key(conn->ssl)) {
 		tls_show_errors(MSG_INFO, __func__, "Private key failed "
@@ -1601,17 +1640,16 @@
 }
 
 
-int tls_global_private_key(void *_ssl_ctx, const char *private_key,
-			   const char *private_key_passwd)
+static int tls_global_private_key(SSL_CTX *ssl_ctx, const char *private_key,
+				  const char *private_key_passwd)
 {
-	SSL_CTX *ssl_ctx = _ssl_ctx;
 	char *passwd;
 
 	if (private_key == NULL)
 		return 0;
 
 	if (private_key_passwd) {
-		passwd = strdup(private_key_passwd);
+		passwd = os_strdup(private_key_passwd);
 		if (passwd == NULL)
 			return -1;
 	} else
@@ -1629,11 +1667,11 @@
 	    tls_read_pkcs12(ssl_ctx, NULL, private_key, passwd)) {
 		tls_show_errors(MSG_INFO, __func__,
 				"Failed to load private key");
-		free(passwd);
+		os_free(passwd);
 		ERR_clear_error();
 		return -1;
 	}
-	free(passwd);
+	os_free(passwd);
 	ERR_clear_error();
 	SSL_CTX_set_default_passwd_cb(ssl_ctx, NULL);
 	
@@ -1647,8 +1685,7 @@
 }
 
 
-static int tls_connection_dh(void *ssl_ctx, struct tls_connection *conn,
-		      const char *dh_file)
+static int tls_connection_dh(struct tls_connection *conn, const char *dh_file)
 {
 #ifdef OPENSSL_NO_DH
 	if (dh_file == NULL)
@@ -1733,7 +1770,7 @@
 	if (ssl == NULL || ssl->s3 == NULL || ssl->session == NULL)
 		return -1;
 
-	memset(keys, 0, sizeof(*keys));
+	os_memset(keys, 0, sizeof(*keys));
 	keys->master_key = ssl->session->master_key;
 	keys->master_key_len = ssl->session->master_key_length;
 	keys->client_random = ssl->s3->client_random;
@@ -1745,13 +1782,25 @@
 }
 
 
+int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
+		       const char *label, int server_random_first,
+		       u8 *out, size_t out_len)
+{
+	return -1;
+}
+
+
 u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
 			      const u8 *in_data, size_t in_len,
-			      size_t *out_len)
+			      size_t *out_len, u8 **appl_data,
+			      size_t *appl_data_len)
 {
 	int res;
 	u8 *out_data;
 
+	if (appl_data)
+		*appl_data = NULL;
+
 	/*
 	 * Give TLS handshake data from the server (if available) to OpenSSL
 	 * for processing.
@@ -1782,7 +1831,7 @@
 	/* Get the TLS handshake data to be sent to the server */
 	res = BIO_ctrl_pending(conn->ssl_out);
 	wpa_printf(MSG_DEBUG, "SSL: %d bytes pending from ssl_out", res);
-	out_data = malloc(res == 0 ? 1 : res);
+	out_data = os_malloc(res == 0 ? 1 : res);
 	if (out_data == NULL) {
 		wpa_printf(MSG_DEBUG, "SSL: Failed to allocate memory for "
 			   "handshake output (%d bytes)", res);
@@ -1805,6 +1854,26 @@
 		return NULL;
 	}
 	*out_len = res;
+
+	if (SSL_is_init_finished(conn->ssl) && appl_data) {
+		*appl_data = os_malloc(in_len);
+		if (*appl_data) {
+			res = SSL_read(conn->ssl, *appl_data, in_len);
+			if (res < 0) {
+				tls_show_errors(MSG_INFO, __func__,
+						"Failed to read possible "
+						"Application Data");
+				os_free(*appl_data);
+				*appl_data = NULL;
+			} else {
+				*appl_data_len = res;
+				wpa_hexdump_key(MSG_MSGDUMP, "SSL: Application"
+						" Data in Finish message",
+						*appl_data, *appl_data_len);
+			}
+		}
+	}
+
 	return out_data;
 }
 
@@ -1833,7 +1902,7 @@
 
 	res = BIO_ctrl_pending(conn->ssl_out);
 	wpa_printf(MSG_DEBUG, "SSL: %d bytes pending from ssl_out", res);
-	out_data = malloc(res == 0 ? 1 : res);
+	out_data = os_malloc(res == 0 ? 1 : res);
 	if (out_data == NULL) {
 		wpa_printf(MSG_DEBUG, "SSL: Failed to allocate memory for "
 			   "handshake output (%d bytes)", res);
@@ -1930,7 +1999,7 @@
 }
 
 
-#ifdef EAP_FAST
+#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC)
 /* Pre-shared secred requires a patch to openssl, so this function is
  * commented out unless explicitly needed for EAP-FAST in order to be able to
  * build this file with unmodified openssl. */
@@ -1944,7 +2013,8 @@
 	if (conn == NULL || conn->pre_shared_secret == 0)
 		return 0;
 
-	memcpy(secret, conn->pre_shared_secret, conn->pre_shared_secret_len);
+	os_memcpy(secret, conn->pre_shared_secret,
+		  conn->pre_shared_secret_len);
 	*secret_len = conn->pre_shared_secret_len;
 
 	return 1;
@@ -1957,14 +2027,14 @@
 	if (conn == NULL || key_len > SSL_MAX_MASTER_KEY_LENGTH)
 		return -1;
 
-	free(conn->pre_shared_secret);
+	os_free(conn->pre_shared_secret);
 	conn->pre_shared_secret = NULL;
 	conn->pre_shared_secret_len = 0;
 
 	if (key) {
-		conn->pre_shared_secret = malloc(key_len);
+		conn->pre_shared_secret = os_malloc(key_len);
 		if (conn->pre_shared_secret) {
-			memcpy(conn->pre_shared_secret, key, key_len);
+			os_memcpy(conn->pre_shared_secret, key, key_len);
 			conn->pre_shared_secret_len = key_len;
 		}
 		if (SSL_set_session_secret_cb(conn->ssl, tls_sess_sec_cb,
@@ -1977,17 +2047,58 @@
 
 	return 0;
 }
-#endif /* EAP_FAST */
+#endif /* EAP_FAST || EAP_FAST_DYNAMIC */
 
 
-int tls_connection_set_anon_dh(void *ssl_ctx, struct tls_connection *conn)
+int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
+				   u8 *ciphers)
 {
-	if (conn == NULL || conn->ssl == NULL)
+	char buf[100], *pos, *end;
+	u8 *c;
+	int ret;
+
+	if (conn == NULL || conn->ssl == NULL || ciphers == NULL)
 		return -1;
 
-	if (SSL_set_cipher_list(conn->ssl, "ADH-AES128-SHA") != 1) {
+	buf[0] = '\0';
+	pos = buf;
+	end = pos + sizeof(buf);
+
+	c = ciphers;
+	while (*c != TLS_CIPHER_NONE) {
+		const char *suite;
+
+		switch (*c) {
+		case TLS_CIPHER_RC4_SHA:
+			suite = "RC4-SHA";
+			break;
+		case TLS_CIPHER_AES128_SHA:
+			suite = "AES128-SHA";
+			break;
+		case TLS_CIPHER_RSA_DHE_AES128_SHA:
+			suite = "DHE-RSA-AES128-SHA";
+			break;
+		case TLS_CIPHER_ANON_DH_AES128_SHA:
+			suite = "ADH-AES128-SHA";
+			break;
+		default:
+			wpa_printf(MSG_DEBUG, "TLS: Unsupported "
+				   "cipher selection: %d", *c);
+			return -1;
+		}
+		ret = os_snprintf(pos, end - pos, ":%s", suite);
+		if (ret < 0 || ret >= end - pos)
+			break;
+		pos += ret;
+
+		c++;
+	}
+
+	wpa_printf(MSG_DEBUG, "OpenSSL: cipher suites: %s", buf + 1);
+
+	if (SSL_set_cipher_list(conn->ssl, buf + 1) != 1) {
 		tls_show_errors(MSG_INFO, __func__,
-				"Anon DH configuration failed");
+				"Cipher suite configuration failed");
 		return -1;
 	}
 
@@ -2006,7 +2117,8 @@
 	if (name == NULL)
 		return -1;
 
-	snprintf(buf, buflen, "%s", name);
+	os_snprintf(buf, buflen, "%s", name);
+	buf[buflen - 1] = '\0';
 	return 0;
 }
 
@@ -2020,7 +2132,7 @@
 }
 
 
-#ifdef EAP_FAST
+#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC)
 /* ClientHello TLS extensions require a patch to openssl, so this function is
  * commented out unless explicitly needed for EAP-FAST in order to be able to
  * build this file with unmodified openssl. */
@@ -2037,7 +2149,7 @@
 
 	return 0;
 }
-#endif /* EAP_FAST */
+#endif /* EAP_FAST || EAP_FAST_DYNAMIC */
 
 
 int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn)
@@ -2078,7 +2190,7 @@
 			   __func__, ERR_error_string(err, NULL));
 	}
 
-	if (tls_connection_set_subject_match(tls_ctx, conn,
+	if (tls_connection_set_subject_match(conn,
 					     params->subject_match,
 					     params->altsubject_match))
 		return -1;
@@ -2087,7 +2199,7 @@
 				   params->ca_cert_blob_len,
 				   params->ca_path))
 		return -1;
-	if (tls_connection_client_cert(tls_ctx, conn, params->client_cert,
+	if (tls_connection_client_cert(conn, params->client_cert,
 				       params->client_cert_blob,
 				       params->client_cert_blob_len))
 		return -1;
@@ -2098,7 +2210,7 @@
 				      params->key_id);
 		if (ret)
 			return ret;
-		if (tls_connection_engine_private_key(tls_ctx, conn))
+		if (tls_connection_engine_private_key(conn))
 			return TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED;
 	} else if (tls_connection_private_key(tls_ctx, conn,
 					      params->private_key,
@@ -2110,7 +2222,7 @@
 		return -1;
 	}
 
-	if (tls_connection_dh(tls_ctx, conn, params->dh_file)) {
+	if (tls_connection_dh(conn, params->dh_file)) {
 		wpa_printf(MSG_INFO, "TLS: Failed to load DH file '%s'",
 			   params->dh_file);
 		return -1;
@@ -2122,6 +2234,31 @@
 }
 
 
+int tls_global_set_params(void *tls_ctx,
+			  const struct tls_connection_params *params)
+{
+	SSL_CTX *ssl_ctx = tls_ctx;
+	unsigned long err;
+
+	while ((err = ERR_get_error())) {
+		wpa_printf(MSG_INFO, "%s: Clearing pending SSL error: %s",
+			   __func__, ERR_error_string(err, NULL));
+	}
+
+	if (tls_global_ca_cert(ssl_ctx, params->ca_cert))
+		return -1;
+
+	if (tls_global_client_cert(ssl_ctx, params->client_cert))
+		return -1;
+
+	if (tls_global_private_key(ssl_ctx, params->private_key,
+				   params->private_key_passwd))
+		return -1;
+
+	return 0;
+}
+
+
 int tls_connection_get_keyblock_size(void *tls_ctx,
 				     struct tls_connection *conn)
 {
@@ -2141,3 +2278,40 @@
 		    EVP_MD_size(h) +
 		    EVP_CIPHER_iv_length(c));
 }
+
+
+unsigned int tls_capabilities(void *tls_ctx)
+{
+	return 0;
+}
+
+
+int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn,
+			  int tls_ia)
+{
+	return -1;
+}
+
+
+int tls_connection_ia_send_phase_finished(void *tls_ctx,
+					  struct tls_connection *conn,
+					  int final,
+					  u8 *out_data, size_t out_len)
+{
+	return -1;
+}
+
+
+int tls_connection_ia_final_phase_finished(void *tls_ctx,
+					   struct tls_connection *conn)
+{
+	return -1;
+}
+
+
+int tls_connection_ia_permute_inner_secret(void *tls_ctx,
+					   struct tls_connection *conn,
+					   const u8 *key, size_t key_len)
+{
+	return -1;
+}
Index: eap_tlv.h
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/eap_tlv.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/eap_tlv.h -L contrib/wpa_supplicant/eap_tlv.h -u -r1.2 -r1.3
--- contrib/wpa_supplicant/eap_tlv.h
+++ contrib/wpa_supplicant/eap_tlv.h
@@ -1,6 +1,6 @@
 /*
- * WPA Supplicant / EAP-TLV (draft-josefsson-pppext-eap-tls-eap-07.txt)
- * Copyright (c) 2004-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * EAP peer method: EAP-TLV (draft-josefsson-pppext-eap-tls-eap-07.txt)
+ * Copyright (c) 2004-2005, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -32,29 +32,33 @@
 
 #define EAP_TLV_TYPE_MANDATORY 0x8000
 
+#ifdef _MSC_VER
+#pragma pack(push, 1)
+#endif /* _MSC_VER */
+
 struct eap_tlv_hdr {
 	u16 tlv_type;
 	u16 length;
-};
+} STRUCT_PACKED;
 
 struct eap_tlv_nak_tlv {
 	u16 tlv_type;
 	u16 length;
 	u32 vendor_id;
 	u16 nak_type;
-} __attribute__((packed));
+} STRUCT_PACKED;
 
 struct eap_tlv_result_tlv {
 	u16 tlv_type;
 	u16 length;
 	u16 status;
-} __attribute__((packed));
+} STRUCT_PACKED;
 
 struct eap_tlv_intermediate_result_tlv {
 	u16 tlv_type;
 	u16 length;
 	u16 status;
-} __attribute__((packed));
+} STRUCT_PACKED;
 
 struct eap_tlv_crypto_binding__tlv {
 	u16 tlv_type;
@@ -65,7 +69,7 @@
 	u8 subtype;
 	u8 nonce[32];
 	u8 compound_mac[20];
-} __attribute__((packed));
+} STRUCT_PACKED;
 
 struct eap_tlv_pac_ack_tlv {
 	u16 tlv_type;
@@ -73,7 +77,11 @@
 	u16 pac_type;
 	u16 pac_len;
 	u16 result;
-} __attribute__((packed));
+} STRUCT_PACKED;
+
+#ifdef _MSC_VER
+#pragma pack(pop)
+#endif /* _MSC_VER */
 
 #define EAP_TLV_CRYPTO_BINDING_SUBTYPE_REQUEST 0
 #define EAP_TLV_CRYPTO_BINDING_SUBTYPE_RESPONSE 1
Index: eap_tls_common.h
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/eap_tls_common.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/eap_tls_common.h -L contrib/wpa_supplicant/eap_tls_common.h -u -r1.2 -r1.3
--- contrib/wpa_supplicant/eap_tls_common.h
+++ contrib/wpa_supplicant/eap_tls_common.h
@@ -1,6 +1,6 @@
 /*
- * WPA Supplicant / EAP-TLS/PEAP/TTLS/FAST common functions
- * Copyright (c) 2004-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * EAP peer: EAP-TLS/PEAP/TTLS/FAST common functions
+ * Copyright (c) 2004-2005, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -30,6 +30,7 @@
 	int phase2;
 	int include_tls_length; /* include TLS length field even if the TLS
 				 * data is not fragmented */
+	int tls_ia; /* Enable TLS/IA */
 
 	struct eap_sm *eap;
 };
@@ -49,16 +50,16 @@
 		     struct wpa_ssid *config);
 void eap_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data);
 u8 * eap_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
-			char *label, size_t len);
+			const char *label, size_t len);
 const u8 * eap_tls_data_reassemble(
 	struct eap_sm *sm, struct eap_ssl_data *data, const u8 *in_data,
 	size_t in_len, size_t *out_len, int *need_more_input);
 int eap_tls_process_helper(struct eap_sm *sm, struct eap_ssl_data *data,
-			   int eap_type, int peap_version,
+			   EapType eap_type, int peap_version,
 			   u8 id, const u8 *in_data, size_t in_len,
 			   u8 **out_data, size_t *out_len);
 u8 * eap_tls_build_ack(struct eap_ssl_data *data, size_t *respDataLen, u8 id,
-		       int eap_type, int peap_version);
+		       EapType eap_type, int peap_version);
 int eap_tls_reauth_init(struct eap_sm *sm, struct eap_ssl_data *data);
 int eap_tls_status(struct eap_sm *sm, struct eap_ssl_data *data, char *buf,
 		   size_t buflen, int verbose);
Index: eap_defs.h
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/eap_defs.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/eap_defs.h -L contrib/wpa_supplicant/eap_defs.h -u -r1.2 -r1.3
--- contrib/wpa_supplicant/eap_defs.h
+++ contrib/wpa_supplicant/eap_defs.h
@@ -1,6 +1,6 @@
 /*
- * WPA Supplicant/hostapd / Shared EAP definitions
- * Copyright (c) 2004-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * EAP server/peer: Shared EAP definitions
+ * Copyright (c) 2004-2006, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -17,12 +17,20 @@
 
 /* RFC 3748 - Extensible Authentication Protocol (EAP) */
 
+#ifdef _MSC_VER
+#pragma pack(push, 1)
+#endif /* _MSC_VER */
+
 struct eap_hdr {
 	u8 code;
 	u8 identifier;
 	u16 length; /* including code and identifier; network byte order */
 	/* followed by length-4 octets of data */
-} __attribute__ ((packed));
+} STRUCT_PACKED;
+
+#ifdef _MSC_VER
+#pragma pack(pop)
+#endif /* _MSC_VER */
 
 enum { EAP_CODE_REQUEST = 1, EAP_CODE_RESPONSE = 2, EAP_CODE_SUCCESS = 3,
        EAP_CODE_FAILURE = 4 };
@@ -40,17 +48,28 @@
 	EAP_TYPE_GTC = 6, /* RFC 3748 */
 	EAP_TYPE_TLS = 13 /* RFC 2716 */,
 	EAP_TYPE_LEAP = 17 /* Cisco proprietary */,
-	EAP_TYPE_SIM = 18 /* draft-haverinen-pppext-eap-sim-12.txt */,
+	EAP_TYPE_SIM = 18 /* RFC 4186 */,
 	EAP_TYPE_TTLS = 21 /* draft-ietf-pppext-eap-ttls-02.txt */,
-	EAP_TYPE_AKA = 23 /* draft-arkko-pppext-eap-aka-12.txt */,
+	EAP_TYPE_AKA = 23 /* RFC 4187 */,
 	EAP_TYPE_PEAP = 25 /* draft-josefsson-pppext-eap-tls-eap-06.txt */,
 	EAP_TYPE_MSCHAPV2 = 26 /* draft-kamath-pppext-eap-mschapv2-00.txt */,
 	EAP_TYPE_TLV = 33 /* draft-josefsson-pppext-eap-tls-eap-07.txt */,
-	EAP_TYPE_FAST = 43 /* draft-cam-winget-eap-fast-00.txt */,
-	EAP_TYPE_PAX = 46, /* draft-clancy-eap-pax-04.txt */
-	EAP_TYPE_EXPANDED_NAK = 254 /* RFC 3748 */,
-	EAP_TYPE_PSK = 255 /* EXPERIMENTAL - type not yet allocated
-			    * draft-bersani-eap-psk-09 */
+	EAP_TYPE_FAST = 43 /* draft-cam-winget-eap-fast-05.txt */,
+	EAP_TYPE_PAX = 46 /* RFC 4746 */,
+	EAP_TYPE_PSK = 47 /* RFC 4764 */,
+	EAP_TYPE_SAKE = 48 /* RFC 4763 */,
+	EAP_TYPE_EXPANDED = 254 /* RFC 3748 */,
+	EAP_TYPE_GPSK = 255 /* EXPERIMENTAL - type not yet allocated
+			     * draft-ietf-emu-eap-gpsk-01.txt */
 } EapType;
 
+
+/* SMI Network Management Private Enterprise Code for vendor specific types */
+enum {
+	EAP_VENDOR_IETF = 0
+};
+
+#define EAP_MSK_LEN 64
+#define EAP_EMSK_LEN 64
+
 #endif /* EAP_DEFS_H */
Index: config_ssid.h
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/config_ssid.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/config_ssid.h -L contrib/wpa_supplicant/config_ssid.h -u -r1.2 -r1.3
--- contrib/wpa_supplicant/config_ssid.h
+++ contrib/wpa_supplicant/config_ssid.h
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant / Network configuration structures
- * Copyright (c) 2003-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2003-2006, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -15,11 +15,18 @@
 #ifndef CONFIG_SSID_H
 #define CONFIG_SSID_H
 
+#ifndef BIT
+#define BIT(n) (1 << (n))
+#endif
+
 #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)
+#ifdef CONFIG_IEEE80211W
+#define WPA_CIPHER_AES_128_CMAC BIT(5)
+#endif /* CONFIG_IEEE80211W */
 
 #define WPA_KEY_MGMT_IEEE8021X BIT(0)
 #define WPA_KEY_MGMT_PSK BIT(1)
@@ -36,7 +43,8 @@
 
 #define MAX_SSID_LEN 32
 #define PMK_LEN 32
-#define EAP_PSK_LEN 16
+#define EAP_PSK_LEN_MIN 16
+#define EAP_PSK_LEN_MAX 32
 
 
 #define DEFAULT_EAP_WORKAROUND ((unsigned int) -1)
@@ -47,6 +55,7 @@
 #define DEFAULT_PAIRWISE (WPA_CIPHER_CCMP | WPA_CIPHER_TKIP)
 #define DEFAULT_GROUP (WPA_CIPHER_CCMP | WPA_CIPHER_TKIP | \
 		       WPA_CIPHER_WEP104 | WPA_CIPHER_WEP40)
+#define DEFAULT_FRAGMENT_SIZE 1398
 
 /**
  * struct wpa_ssid - Network configuration data
@@ -191,6 +200,8 @@
 	 */
 	int scan_ssid;
 
+#ifdef IEEE8021X_EAPOL
+
 	/**
 	 * identity - EAP Identity
 	 */
@@ -216,19 +227,20 @@
 	size_t anonymous_identity_len;
 
 	/**
-	 * eappsk - EAP-PSK pre-shared key
+	 * eappsk - EAP-PSK/PAX/SAKE pre-shared key
 	 */
 	u8 *eappsk;
 
 	/**
-	 * eappsk_len - EAP-PSK pre-shared key length
+	 * eappsk_len - EAP-PSK/PAX/SAKE pre-shared key length
 	 *
-	 * This field is always 16 for the current version of EAP-PSK.
+	 * This field is always 16 for the current version of EAP-PSK/PAX and
+	 * 32 for EAP-SAKE.
 	 */
 	size_t eappsk_len;
 
 	/**
-	 * nai - User NAI (for EAP-PSK)
+	 * nai - User NAI (for EAP-PSK/PAX/SAKE)
 	 */
 	u8 *nai;
 
@@ -263,6 +275,9 @@
 	 * On Windows, trusted CA certificates can be loaded from the system
 	 * certificate store by setting this to cert_store://<name>, e.g.,
 	 * ca_cert="cert_store://CA" or ca_cert="cert_store://ROOT".
+	 * Note that when running wpa_supplicant as an application, the user
+	 * certificate store (My user account) is used, whereas computer store
+	 * (Computer account) is used when running wpasvc as a service.
 	 */
 	u8 *ca_cert;
 
@@ -309,6 +324,10 @@
 	 *
 	 * For example: private_key="hash://63093aa9c47f56ae88334c7b65a4"
 	 *
+	 * Note that when running wpa_supplicant as an application, the user
+	 * certificate store (My user account) is used, whereas computer store
+	 * (Computer account) is used when running wpasvc as a service.
+	 *
 	 * Alternatively, a named configuration blob can be used by setting
 	 * this to blob://<blob name>.
 	 */
@@ -354,14 +373,16 @@
 	/**
 	 * altsubject_match - Constraint for server certificate alt. subject
 	 *
-	 * This substring is matched against the alternative subject name of
-	 * the authentication server certificate. If this string is set, the
-	 * server sertificate is only accepted if it contains this string in an
-	 * alternative subject name extension.
+	 * Semicolon separated string of entries to be matched against the
+	 * alternative subject name of the authentication server certificate.
+	 * If this string is set, the server sertificate is only accepted if it
+	 * contains one of the entries in an alternative subject name
+	 * extension.
 	 *
 	 * altSubjectName string is in following format: TYPE:VALUE
 	 *
-	 * Example: DNS:server.example.com
+	 * Example: EMAIL:server at example.com
+	 * Example: DNS:server.example.com;DNS:server2.example.com
 	 *
 	 * Following types are supported: EMAIL, DNS, URI
 	 */
@@ -465,10 +486,10 @@
 	/**
 	 * eap_methods - Allowed EAP methods
 	 *
-	 * Zero (EAP_TYPE_NONE) terminated list of allowed EAP methods or %NULL
-	 * if all methods are accepted.
+	 * (vendor=EAP_VENDOR_IETF,method=EAP_TYPE_NONE) terminated list of
+	 * allowed EAP methods or %NULL if all methods are accepted.
 	 */
-	u8 *eap_methods;
+	struct eap_method_type *eap_methods;
 
 	/**
 	 * phase1 - Phase 1 (outer authentication) parameters
@@ -569,6 +590,8 @@
 	 */
 	int eapol_flags;
 
+#endif /* IEEE8021X_EAPOL */
+
 #define NUM_WEP_KEYS 4
 #define MAX_WEP_KEY_LEN 16
 	/**
@@ -602,6 +625,18 @@
 	int proactive_key_caching;
 
 	/**
+	 * mixed_cell - Whether mixed cells are allowed
+	 *
+	 * This option can be used to configure whether so called mixed cells,
+	 * i.e., networks that use both plaintext and encryption in the same
+	 * SSID, are allowed. This is disabled (0) by default. Enable by
+	 * setting this to 1.
+	 */
+	int mixed_cell;
+
+#ifdef IEEE8021X_EAPOL
+
+	/**
 	 * otp - One-time-password
 	 *
 	 * This field should not be set in configuration step. It is only used
@@ -715,6 +750,8 @@
 	 */
 	char *pac_file;
 
+#endif /* IEEE8021X_EAPOL */
+
 	/**
 	 * mode - IEEE 802.11 operation mode (Infrastucture/IBSS)
 	 *
@@ -731,6 +768,8 @@
 	 */
 	int mode;
 
+#ifdef IEEE8021X_EAPOL
+
 	/**
 	 * mschapv2_retry - MSCHAPv2 retry in progress
 	 *
@@ -753,6 +792,8 @@
 	 */
 	size_t new_password_len;
 
+#endif /* IEEE8021X_EAPOL */
+
 	/**
 	 * disabled - Whether this network is currently disabled
 	 *
@@ -761,8 +802,58 @@
 	 * ctrl_iface, e.g., with wpa_cli or wpa_gui).
 	 */
 	int disabled;
+
+	/**
+	 * peerkey -  Whether PeerKey handshake for direct links is allowed
+	 *
+	 * This is only used when both RSN/WPA2 and IEEE 802.11e (QoS) are
+	 * enabled.
+	 *
+	 * 0 = disabled (default)
+	 * 1 = enabled
+	 */
+	int peerkey;
+
+#ifdef IEEE8021X_EAPOL
+
+	/**
+	 * fragment_size - Maximum EAP fragment size in bytes (default 1398)
+	 *
+	 * This value limits the fragment size for EAP methods that support
+	 * fragmentation (e.g., EAP-TLS and EAP-PEAP). This value should be set
+	 * small enough to make the EAP messages fit in MTU of the network
+	 * interface used for EAPOL. The default value is suitable for most
+	 * cases.
+	 */
+	int fragment_size;
+
+#endif /* IEEE8021X_EAPOL */
+
+	/**
+	 * id_str - Network identifier string for external scripts
+	 *
+	 * This value is passed to external ctrl_iface monitors in
+	 * WPA_EVENT_CONNECTED event and wpa_cli sets this as WPA_ID_STR
+	 * environment variable for action scripts.
+	 */
+	char *id_str;
+
+#ifdef CONFIG_IEEE80211W
+	/**
+	 * ieee80211w - Whether management frame protection is enabled
+	 *
+	 * This value is used to configure policy for management frame
+	 * protection (IEEE 802.11w). 0 = disabled, 1 = optional, 2 = required.
+	 */
+	enum {
+		NO_IEEE80211W = 0,
+		IEEE80211W_OPTIONAL = 1,
+		IEEE80211W_REQUIRED = 2
+	} ieee80211w;
+#endif /* CONFIG_IEEE80211W */
 };
 
-int wpa_config_allowed_eap_method(struct wpa_ssid *ssid, int method);
+int wpa_config_allowed_eap_method(struct wpa_ssid *ssid, int vendor,
+				  u32 method);
 
 #endif /* CONFIG_SSID_H */
Index: eap_sim.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/eap_sim.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/eap_sim.c -L contrib/wpa_supplicant/eap_sim.c -u -r1.2 -r1.3
--- contrib/wpa_supplicant/eap_sim.c
+++ contrib/wpa_supplicant/eap_sim.c
@@ -1,6 +1,6 @@
 /*
- * WPA Supplicant / EAP-SIM (draft-haverinen-pppext-eap-sim-13.txt)
- * Copyright (c) 2004-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * EAP peer method: EAP-SIM (RFC 4186)
+ * Copyright (c) 2004-2006, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -12,50 +12,30 @@
  * See README and COPYING for more details.
  */
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
+#include "includes.h"
 
 #include "common.h"
 #include "eap_i.h"
-#include "wpa_supplicant.h"
 #include "config_ssid.h"
 #include "crypto.h"
 #include "pcsc_funcs.h"
 #include "eap_sim_common.h"
 
-#define EAP_SIM_VERSION 1
-
-/* EAP-SIM Subtypes */
-#define EAP_SIM_SUBTYPE_START 10
-#define EAP_SIM_SUBTYPE_CHALLENGE 11
-#define EAP_SIM_SUBTYPE_NOTIFICATION 12
-#define EAP_SIM_SUBTYPE_REAUTHENTICATION 13
-#define EAP_SIM_SUBTYPE_CLIENT_ERROR 14
-
-/* AT_CLIENT_ERROR_CODE error codes */
-#define EAP_SIM_UNABLE_TO_PROCESS_PACKET 0
-#define EAP_SIM_UNSUPPORTED_VERSION 1
-#define EAP_SIM_INSUFFICIENT_NUM_OF_CHAL 2
-#define EAP_SIM_RAND_NOT_FRESH 3
-
-#define KC_LEN 8
-#define SRES_LEN 4
-#define EAP_SIM_MAX_FAST_REAUTHS 1000
 
 struct eap_sim_data {
 	u8 *ver_list;
 	size_t ver_list_len;
 	int selected_version;
-	int min_num_chal, num_chal;
+	size_t min_num_chal, num_chal;
 
-	u8 kc[3][KC_LEN];
-	u8 sres[3][SRES_LEN];
+	u8 kc[3][EAP_SIM_KC_LEN];
+	u8 sres[3][EAP_SIM_SRES_LEN];
 	u8 nonce_mt[EAP_SIM_NONCE_MT_LEN], nonce_s[EAP_SIM_NONCE_S_LEN];
 	u8 mk[EAP_SIM_MK_LEN];
 	u8 k_aut[EAP_SIM_K_AUT_LEN];
 	u8 k_encr[EAP_SIM_K_ENCR_LEN];
 	u8 msk[EAP_SIM_KEYING_DATA_LEN];
+	u8 emsk[EAP_EMSK_LEN];
 	u8 rand[3][GSM_RAND_LEN];
 
 	int num_id_req, num_notification;
@@ -76,33 +56,33 @@
 	struct eap_sim_data *data;
 	struct wpa_ssid *config = eap_get_config(sm);
 
-	data = malloc(sizeof(*data));
+	data = os_zalloc(sizeof(*data));
 	if (data == NULL)
 		return NULL;
-	memset(data, 0, sizeof(*data));
 
 	if (hostapd_get_rand(data->nonce_mt, EAP_SIM_NONCE_MT_LEN)) {
 		wpa_printf(MSG_WARNING, "EAP-SIM: Failed to get random data "
 			   "for NONCE_MT");
-		free(data);
+		os_free(data);
 		return NULL;
 	}
 
 	data->min_num_chal = 2;
 	if (config && config->phase1) {
-		char *pos = strstr(config->phase1, "sim_min_num_chal=");
+		char *pos = os_strstr(config->phase1, "sim_min_num_chal=");
 		if (pos) {
 			data->min_num_chal = atoi(pos + 17);
 			if (data->min_num_chal < 2 || data->min_num_chal > 3) {
 				wpa_printf(MSG_WARNING, "EAP-SIM: Invalid "
 					   "sim_min_num_chal configuration "
-					   "(%d, expected 2 or 3)",
-					   data->min_num_chal);
-				free(data);
+					   "(%lu, expected 2 or 3)",
+					   (unsigned long) data->min_num_chal);
+				os_free(data);
 				return NULL;
 			}
 			wpa_printf(MSG_DEBUG, "EAP-SIM: Set minimum number of "
-				   "challenges to %d", data->min_num_chal);
+				   "challenges to %lu",
+				   (unsigned long) data->min_num_chal);
 		}
 	}
 
@@ -116,11 +96,11 @@
 {
 	struct eap_sim_data *data = priv;
 	if (data) {
-		free(data->ver_list);
-		free(data->pseudonym);
-		free(data->reauth_id);
-		free(data->last_eap_identity);
-		free(data);
+		os_free(data->ver_list);
+		os_free(data->pseudonym);
+		os_free(data->reauth_id);
+		os_free(data->last_eap_identity);
+		os_free(data);
 	}
 }
 
@@ -146,26 +126,26 @@
 	 * concerned, but it is quite useful for cases where the AS is rotating
 	 * the order of pre-configured values. */
 	{
-		int i;
+		size_t i;
 		for (i = 0; i < data->num_chal; i++) {
 			if (data->rand[i][0] == 0xaa) {
-				memcpy(data->kc[i],
-				       "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7",
-				       KC_LEN);
-				memcpy(data->sres[i], "\xd1\xd2\xd3\xd4",
-				       SRES_LEN);
+				os_memcpy(data->kc[i],
+					  "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7",
+					  EAP_SIM_KC_LEN);
+				os_memcpy(data->sres[i], "\xd1\xd2\xd3\xd4",
+					  EAP_SIM_SRES_LEN);
 			} else if (data->rand[i][0] == 0xbb) {
-				memcpy(data->kc[i],
-				       "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7",
-				       KC_LEN);
-				memcpy(data->sres[i], "\xe1\xe2\xe3\xe4",
-				       SRES_LEN);
+				os_memcpy(data->kc[i],
+					  "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7",
+					  EAP_SIM_KC_LEN);
+				os_memcpy(data->sres[i], "\xe1\xe2\xe3\xe4",
+					  EAP_SIM_SRES_LEN);
 			} else {
-				memcpy(data->kc[i],
-				       "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7",
-				       KC_LEN);
-				memcpy(data->sres[i], "\xf1\xf2\xf3\xf4",
-				       SRES_LEN);
+				os_memcpy(data->kc[i],
+					  "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7",
+					  EAP_SIM_KC_LEN);
+				os_memcpy(data->sres[i], "\xf1\xf2\xf3\xf4",
+					  EAP_SIM_SRES_LEN);
 			}
 		}
 	}
@@ -174,38 +154,12 @@
 }
 
 
-static int eap_sim_supported_ver(struct eap_sim_data *data, int version)
+static int eap_sim_supported_ver(int version)
 {
 	return version == EAP_SIM_VERSION;
 }
 
 
-static void eap_sim_derive_mk(struct eap_sim_data *data,
-			      const u8 *identity, size_t identity_len)
-{
-	u8 sel_ver[2];
-	const unsigned char *addr[5];
-	size_t len[5];
-
-	addr[0] = identity;
-	len[0] = identity_len;
-	addr[1] = (u8 *) data->kc;
-	len[1] = data->num_chal * KC_LEN;
-	addr[2] = data->nonce_mt;
-	len[2] = EAP_SIM_NONCE_MT_LEN;
-	addr[3] = data->ver_list;
-	len[3] = data->ver_list_len;
-	addr[4] = sel_ver;
-	len[4] = 2;
-
-	WPA_PUT_BE16(sel_ver, data->selected_version);
-
-	/* MK = SHA1(Identity|n*Kc|NONCE_MT|Version List|Selected Version) */
-	sha1_vector(5, addr, len, data->mk);
-	wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: MK", data->mk, EAP_SIM_MK_LEN);
-}
-
-
 #define CLEAR_PSEUDONYM	0x01
 #define CLEAR_REAUTH_ID	0x02
 #define CLEAR_EAP_ID	0x04
@@ -217,17 +171,17 @@
 		   id & CLEAR_REAUTH_ID ? " reauth_id" : "",
 		   id & CLEAR_EAP_ID ? " eap_id" : "");
 	if (id & CLEAR_PSEUDONYM) {
-		free(data->pseudonym);
+		os_free(data->pseudonym);
 		data->pseudonym = NULL;
 		data->pseudonym_len = 0;
 	}
 	if (id & CLEAR_REAUTH_ID) {
-		free(data->reauth_id);
+		os_free(data->reauth_id);
 		data->reauth_id = NULL;
 		data->reauth_id_len = 0;
 	}
 	if (id & CLEAR_EAP_ID) {
-		free(data->last_eap_identity);
+		os_free(data->last_eap_identity);
 		data->last_eap_identity = NULL;
 		data->last_eap_identity_len = 0;
 	}
@@ -238,15 +192,15 @@
 			     struct eap_sim_attrs *attr)
 {
 	if (attr->next_pseudonym) {
-		free(data->pseudonym);
-		data->pseudonym = malloc(attr->next_pseudonym_len);
+		os_free(data->pseudonym);
+		data->pseudonym = os_malloc(attr->next_pseudonym_len);
 		if (data->pseudonym == NULL) {
 			wpa_printf(MSG_INFO, "EAP-SIM: (encr) No memory for "
 				   "next pseudonym");
 			return -1;
 		}
-		memcpy(data->pseudonym, attr->next_pseudonym,
-		       attr->next_pseudonym_len);
+		os_memcpy(data->pseudonym, attr->next_pseudonym,
+			  attr->next_pseudonym_len);
 		data->pseudonym_len = attr->next_pseudonym_len;
 		wpa_hexdump_ascii(MSG_DEBUG,
 				  "EAP-SIM: (encr) AT_NEXT_PSEUDONYM",
@@ -255,15 +209,15 @@
 	}
 
 	if (attr->next_reauth_id) {
-		free(data->reauth_id);
-		data->reauth_id = malloc(attr->next_reauth_id_len);
+		os_free(data->reauth_id);
+		data->reauth_id = os_malloc(attr->next_reauth_id_len);
 		if (data->reauth_id == NULL) {
 			wpa_printf(MSG_INFO, "EAP-SIM: (encr) No memory for "
 				   "next reauth_id");
 			return -1;
 		}
-		memcpy(data->reauth_id, attr->next_reauth_id,
-		       attr->next_reauth_id_len);
+		os_memcpy(data->reauth_id, attr->next_reauth_id,
+			  attr->next_reauth_id_len);
 		data->reauth_id_len = attr->next_reauth_id_len;
 		wpa_hexdump_ascii(MSG_DEBUG,
 				  "EAP-SIM: (encr) AT_NEXT_REAUTH_ID",
@@ -275,7 +229,7 @@
 }
 
 
-static u8 * eap_sim_client_error(struct eap_sm *sm, struct eap_sim_data *data,
+static u8 * eap_sim_client_error(struct eap_sim_data *data,
 				 const struct eap_hdr *req,
 				 size_t *respDataLen, int err)
 {
@@ -298,8 +252,7 @@
 				   size_t *respDataLen,
 				   enum eap_sim_id_req id_req)
 {
-	struct wpa_ssid *config = eap_get_config(sm);
-	u8 *identity = NULL;
+	const u8 *identity = NULL;
 	size_t identity_len = 0;
 	struct eap_sim_msg *msg;
 
@@ -313,11 +266,12 @@
 		identity = data->pseudonym;
 		identity_len = data->pseudonym_len;
 		eap_sim_clear_identities(data, CLEAR_REAUTH_ID);
-	} else if (id_req != NO_ID_REQ && config && config->identity) {
-		identity = config->identity;
-		identity_len = config->identity_len;
-		eap_sim_clear_identities(data,
-					 CLEAR_PSEUDONYM | CLEAR_REAUTH_ID);
+	} else if (id_req != NO_ID_REQ) {
+		identity = eap_get_config_identity(sm, &identity_len);
+		if (identity) {
+			eap_sim_clear_identities(data, CLEAR_PSEUDONYM |
+						 CLEAR_REAUTH_ID);
+		}
 	}
 	if (id_req != NO_ID_REQ)
 		eap_sim_clear_identities(data, CLEAR_EAP_ID);
@@ -346,8 +300,7 @@
 }
 
 
-static u8 * eap_sim_response_challenge(struct eap_sm *sm,
-				       struct eap_sim_data *data,
+static u8 * eap_sim_response_challenge(struct eap_sim_data *data,
 				       const struct eap_hdr *req,
 				       size_t *respDataLen)
 {
@@ -361,12 +314,11 @@
 	eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
 	return eap_sim_msg_finish(msg, respDataLen, data->k_aut,
 				  (u8 *) data->sres,
-				  data->num_chal * SRES_LEN);
+				  data->num_chal * EAP_SIM_SRES_LEN);
 }
 
 
-static u8 * eap_sim_response_reauth(struct eap_sm *sm,
-				    struct eap_sim_data *data,
+static u8 * eap_sim_response_reauth(struct eap_sim_data *data,
 				    const struct eap_hdr *req,
 				    size_t *respDataLen, int counter_too_small)
 {
@@ -405,8 +357,7 @@
 }
 
 
-static u8 * eap_sim_response_notification(struct eap_sm *sm,
-					  struct eap_sim_data *data,
+static u8 * eap_sim_response_notification(struct eap_sim_data *data,
 					  const struct eap_hdr *req,
 					  size_t *respDataLen,
 					  u16 notification)
@@ -445,36 +396,37 @@
 
 
 static u8 * eap_sim_process_start(struct eap_sm *sm, struct eap_sim_data *data,
-				  const struct eap_hdr *req, size_t reqDataLen,
+				  const struct eap_hdr *req,
 				  size_t *respDataLen,
 				  struct eap_sim_attrs *attr)
 {
-	int i, selected_version = -1, id_error;
+	int selected_version = -1, id_error;
+	size_t i;
 	u8 *pos;
 
 	wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Start");
 	if (attr->version_list == NULL) {
 		wpa_printf(MSG_INFO, "EAP-SIM: No AT_VERSION_LIST in "
 			   "SIM/Start");
-		return eap_sim_client_error(sm, data, req, respDataLen,
+		return eap_sim_client_error(data, req, respDataLen,
 					    EAP_SIM_UNSUPPORTED_VERSION);
 	}
 
-	free(data->ver_list);
-	data->ver_list = malloc(attr->version_list_len);
+	os_free(data->ver_list);
+	data->ver_list = os_malloc(attr->version_list_len);
 	if (data->ver_list == NULL) {
 		wpa_printf(MSG_DEBUG, "EAP-SIM: Failed to allocate "
 			   "memory for version list");
-		return eap_sim_client_error(sm, data, req, respDataLen,
+		return eap_sim_client_error(data, req, respDataLen,
 					    EAP_SIM_UNABLE_TO_PROCESS_PACKET);
 	}
-	memcpy(data->ver_list, attr->version_list, attr->version_list_len);
+	os_memcpy(data->ver_list, attr->version_list, attr->version_list_len);
 	data->ver_list_len = attr->version_list_len;
 	pos = data->ver_list;
 	for (i = 0; i < data->ver_list_len / 2; i++) {
 		int ver = pos[0] * 256 + pos[1];
 		pos += 2;
-		if (eap_sim_supported_ver(data, ver)) {
+		if (eap_sim_supported_ver(ver)) {
 			selected_version = ver;
 			break;
 		}
@@ -482,7 +434,7 @@
 	if (selected_version < 0) {
 		wpa_printf(MSG_INFO, "EAP-SIM: Could not find a supported "
 			   "version");
-		return eap_sim_client_error(sm, data, req, respDataLen,
+		return eap_sim_client_error(data, req, respDataLen,
 					    EAP_SIM_UNSUPPORTED_VERSION);
 	}
 	wpa_printf(MSG_DEBUG, "EAP-SIM: Selected Version %d",
@@ -512,7 +464,7 @@
 	if (id_error) {
 		wpa_printf(MSG_INFO, "EAP-SIM: Too many ID requests "
 			   "used within one authentication");
-		return eap_sim_client_error(sm, data, req, respDataLen,
+		return eap_sim_client_error(data, req, respDataLen,
 					    EAP_SIM_UNABLE_TO_PROCESS_PACKET);
 	}
 
@@ -528,8 +480,7 @@
 				      size_t *respDataLen,
 				      struct eap_sim_attrs *attr)
 {
-	struct wpa_ssid *config = eap_get_config(sm);
-	u8 *identity;
+	const u8 *identity;
 	size_t identity_len;
 	struct eap_sim_attrs eattr;
 
@@ -540,7 +491,7 @@
 			   "did not include%s%s",
 			   !attr->mac ? " AT_MAC" : "",
 			   !attr->rand ? " AT_RAND" : "");
-		return eap_sim_client_error(sm, data, req, respDataLen,
+		return eap_sim_client_error(data, req, respDataLen,
 					    EAP_SIM_UNABLE_TO_PROCESS_PACKET);
 	}
 
@@ -549,36 +500,36 @@
 	if (attr->num_chal < data->min_num_chal) {
 		wpa_printf(MSG_INFO, "EAP-SIM: Insufficient number of "
 			   "challenges (%lu)", (unsigned long) attr->num_chal);
-		return eap_sim_client_error(sm, data, req, respDataLen,
+		return eap_sim_client_error(data, req, respDataLen,
 					    EAP_SIM_INSUFFICIENT_NUM_OF_CHAL);
 	}
 	if (attr->num_chal > 3) {
 		wpa_printf(MSG_INFO, "EAP-SIM: Too many challenges "
 			   "(%lu)", (unsigned long) attr->num_chal);
-		return eap_sim_client_error(sm, data, req, respDataLen,
+		return eap_sim_client_error(data, req, respDataLen,
 					    EAP_SIM_UNABLE_TO_PROCESS_PACKET);
 	}
 
 	/* Verify that RANDs are different */
-	if (memcmp(attr->rand, attr->rand + GSM_RAND_LEN,
+	if (os_memcmp(attr->rand, attr->rand + GSM_RAND_LEN,
 		   GSM_RAND_LEN) == 0 ||
 	    (attr->num_chal > 2 &&
-	     (memcmp(attr->rand, attr->rand + 2 * GSM_RAND_LEN,
-		     GSM_RAND_LEN) == 0 ||
-	      memcmp(attr->rand + GSM_RAND_LEN,
-		     attr->rand + 2 * GSM_RAND_LEN,
-		     GSM_RAND_LEN) == 0))) {
+	     (os_memcmp(attr->rand, attr->rand + 2 * GSM_RAND_LEN,
+			GSM_RAND_LEN) == 0 ||
+	      os_memcmp(attr->rand + GSM_RAND_LEN,
+			attr->rand + 2 * GSM_RAND_LEN,
+			GSM_RAND_LEN) == 0))) {
 		wpa_printf(MSG_INFO, "EAP-SIM: Same RAND used multiple times");
-		return eap_sim_client_error(sm, data, req, respDataLen,
+		return eap_sim_client_error(data, req, respDataLen,
 					    EAP_SIM_RAND_NOT_FRESH);
 	}
 
-	memcpy(data->rand, attr->rand, attr->num_chal * GSM_RAND_LEN);
+	os_memcpy(data->rand, attr->rand, attr->num_chal * GSM_RAND_LEN);
 	data->num_chal = attr->num_chal;
 		
 	if (eap_sim_gsm_auth(sm, data)) {
 		wpa_printf(MSG_WARNING, "EAP-SIM: GSM authentication failed");
-		return eap_sim_client_error(sm, data, req, respDataLen,
+		return eap_sim_client_error(data, req, respDataLen,
 					    EAP_SIM_UNABLE_TO_PROCESS_PACKET);
 	}
 	if (data->last_eap_identity) {
@@ -587,20 +538,22 @@
 	} else if (data->pseudonym) {
 		identity = data->pseudonym;
 		identity_len = data->pseudonym_len;
-	} else {
-		identity = config->identity;
-		identity_len = config->identity_len;
-	}
+	} else
+		identity = eap_get_config_identity(sm, &identity_len);
 	wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Selected identity for MK "
 			  "derivation", identity, identity_len);
-	eap_sim_derive_mk(data, identity, identity_len);
-	eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk);
+	eap_sim_derive_mk(identity, identity_len, data->nonce_mt,
+			  data->selected_version, data->ver_list,
+			  data->ver_list_len, data->num_chal,
+			  (const u8 *) data->kc, data->mk);
+	eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk,
+			    data->emsk);
 	if (eap_sim_verify_mac(data->k_aut, (const u8 *) req, reqDataLen,
 			       attr->mac, data->nonce_mt,
 			       EAP_SIM_NONCE_MT_LEN)) {
 		wpa_printf(MSG_WARNING, "EAP-SIM: Challenge message "
 			   "used invalid AT_MAC");
-		return eap_sim_client_error(sm, data, req, respDataLen,
+		return eap_sim_client_error(data, req, respDataLen,
 					    EAP_SIM_UNABLE_TO_PROCESS_PACKET);
 	}
 
@@ -617,11 +570,11 @@
 					       &eattr, 0);
 		if (decrypted == NULL) {
 			return eap_sim_client_error(
-				sm, data, req, respDataLen,
+				data, req, respDataLen,
 				EAP_SIM_UNABLE_TO_PROCESS_PACKET);
 		}
 		eap_sim_learn_ids(data, &eattr);
-		free(decrypted);
+		os_free(decrypted);
 	}
 
 	if (data->state != FAILURE)
@@ -629,17 +582,15 @@
 
 	data->num_id_req = 0;
 	data->num_notification = 0;
-	/* draft-haverinen-pppext-eap-sim-13.txt specifies that counter
-	 * is initialized to one after fullauth, but initializing it to
-	 * zero makes it easier to implement reauth verification. */
+	/* RFC 4186 specifies that counter is initialized to one after
+	 * fullauth, but initializing it to zero makes it easier to implement
+	 * reauth verification. */
 	data->counter = 0;
-	return eap_sim_response_challenge(sm, data, req, respDataLen);
+	return eap_sim_response_challenge(data, req, respDataLen);
 }
 
 
 static int eap_sim_process_notification_reauth(struct eap_sim_data *data,
-					       const struct eap_hdr *req,
-					       size_t reqDataLen,
 					       struct eap_sim_attrs *attr)
 {
 	struct eap_sim_attrs eattr;
@@ -660,15 +611,15 @@
 		return -1;
 	}
 
-	if (eattr.counter != data->counter) {
+	if (eattr.counter < 0 || (size_t) eattr.counter != data->counter) {
 		wpa_printf(MSG_WARNING, "EAP-SIM: Counter in notification "
 			   "message does not match with counter in reauth "
 			   "message");
-		free(decrypted);
+		os_free(decrypted);
 		return -1;
 	}
 
-	free(decrypted);
+	os_free(decrypted);
 	return 0;
 }
 
@@ -692,7 +643,7 @@
 	}
 
 	if (data->reauth &&
-	    eap_sim_process_notification_reauth(data, req, reqDataLen, attr)) {
+	    eap_sim_process_notification_reauth(data, attr)) {
 		wpa_printf(MSG_WARNING, "EAP-SIM: Invalid notification "
 			   "message after reauth");
 		return -1;
@@ -713,20 +664,20 @@
 	if (data->num_notification > 0) {
 		wpa_printf(MSG_INFO, "EAP-SIM: too many notification "
 			   "rounds (only one allowed)");
-		return eap_sim_client_error(sm, data, req, respDataLen,
+		return eap_sim_client_error(data, req, respDataLen,
 					    EAP_SIM_UNABLE_TO_PROCESS_PACKET);
 	}
 	data->num_notification++;
 	if (attr->notification == -1) {
 		wpa_printf(MSG_INFO, "EAP-SIM: no AT_NOTIFICATION in "
 			   "Notification message");
-		return eap_sim_client_error(sm, data, req, respDataLen,
+		return eap_sim_client_error(data, req, respDataLen,
 					    EAP_SIM_UNABLE_TO_PROCESS_PACKET);
 	}
 
 	if ((attr->notification & 0x4000) == 0 &&
 	    eap_sim_process_notification_auth(data, req, reqDataLen, attr)) {
-		return eap_sim_client_error(sm, data, req, respDataLen,
+		return eap_sim_client_error(data, req, respDataLen,
 					    EAP_SIM_UNABLE_TO_PROCESS_PACKET);
 	}
 
@@ -734,7 +685,7 @@
 	if (attr->notification >= 0 && attr->notification < 32768) {
 		data->state = FAILURE;
 	}
-	return eap_sim_response_notification(sm, data, req, respDataLen,
+	return eap_sim_response_notification(data, req, respDataLen,
 					     attr->notification);
 }
 
@@ -754,7 +705,7 @@
 	if (data->reauth_id == NULL) {
 		wpa_printf(MSG_WARNING, "EAP-SIM: Server is trying "
 			   "reauthentication, but no reauth_id available");
-		return eap_sim_client_error(sm, data, req, respDataLen,
+		return eap_sim_client_error(data, req, respDataLen,
 					    EAP_SIM_UNABLE_TO_PROCESS_PACKET);
 	}
 
@@ -763,14 +714,14 @@
 			       attr->mac, (u8 *) "", 0)) {
 		wpa_printf(MSG_WARNING, "EAP-SIM: Reauthentication "
 			   "did not have valid AT_MAC");
-		return eap_sim_client_error(sm, data, req, respDataLen,
+		return eap_sim_client_error(data, req, respDataLen,
 					    EAP_SIM_UNABLE_TO_PROCESS_PACKET);
 	}
 
 	if (attr->encr_data == NULL || attr->iv == NULL) {
 		wpa_printf(MSG_WARNING, "EAP-SIM: Reauthentication "
 			   "message did not include encrypted data");
-		return eap_sim_client_error(sm, data, req, respDataLen,
+		return eap_sim_client_error(data, req, respDataLen,
 					    EAP_SIM_UNABLE_TO_PROCESS_PACKET);
 	}
 
@@ -780,7 +731,7 @@
 	if (decrypted == NULL) {
 		wpa_printf(MSG_WARNING, "EAP-SIM: Failed to parse encrypted "
 			   "data from reauthentication message");
-		return eap_sim_client_error(sm, data, req, respDataLen,
+		return eap_sim_client_error(data, req, respDataLen,
 					    EAP_SIM_UNABLE_TO_PROCESS_PACKET);
 	}
 
@@ -788,12 +739,12 @@
 		wpa_printf(MSG_INFO, "EAP-SIM: (encr) No%s%s in reauth packet",
 			   !eattr.nonce_s ? " AT_NONCE_S" : "",
 			   eattr.counter < 0 ? " AT_COUNTER" : "");
-		free(decrypted);
-		return eap_sim_client_error(sm, data, req, respDataLen,
+		os_free(decrypted);
+		return eap_sim_client_error(data, req, respDataLen,
 					    EAP_SIM_UNABLE_TO_PROCESS_PACKET);
 	}
 
-	if (eattr.counter <= data->counter) {
+	if (eattr.counter < 0 || (size_t) eattr.counter <= data->counter) {
 		wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid counter "
 			   "(%d <= %d)", eattr.counter, data->counter);
 		data->counter_too_small = eattr.counter;
@@ -802,23 +753,24 @@
 		 * However, since it was used in the last EAP-Response-Identity
 		 * packet, it has to saved for the following fullauth to be
 		 * used in MK derivation. */
-		free(data->last_eap_identity);
+		os_free(data->last_eap_identity);
 		data->last_eap_identity = data->reauth_id;
 		data->last_eap_identity_len = data->reauth_id_len;
 		data->reauth_id = NULL;
 		data->reauth_id_len = 0;
-		free(decrypted);
-		return eap_sim_response_reauth(sm, data, req, respDataLen, 1);
+		os_free(decrypted);
+		return eap_sim_response_reauth(data, req, respDataLen, 1);
 	}
 	data->counter = eattr.counter;
 
-	memcpy(data->nonce_s, eattr.nonce_s, EAP_SIM_NONCE_S_LEN);
+	os_memcpy(data->nonce_s, eattr.nonce_s, EAP_SIM_NONCE_S_LEN);
 	wpa_hexdump(MSG_DEBUG, "EAP-SIM: (encr) AT_NONCE_S",
 		    data->nonce_s, EAP_SIM_NONCE_S_LEN);
 
 	eap_sim_derive_keys_reauth(data->counter,
 				   data->reauth_id, data->reauth_id_len,
-				   data->nonce_s, data->mk, data->msk);
+				   data->nonce_s, data->mk, data->msk,
+				   data->emsk);
 	eap_sim_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID);
 	eap_sim_learn_ids(data, &eattr);
 
@@ -832,8 +784,8 @@
 			   "fast reauths performed - force fullauth");
 		eap_sim_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID);
 	}
-	free(decrypted);
-	return eap_sim_response_reauth(sm, data, req, respDataLen, 0);
+	os_free(decrypted);
+	return eap_sim_response_reauth(data, req, respDataLen, 0);
 }
 
 
@@ -843,7 +795,6 @@
 			    size_t *respDataLen)
 {
 	struct eap_sim_data *data = priv;
-	struct wpa_ssid *config = eap_get_config(sm);
 	const struct eap_hdr *req;
 	u8 subtype, *res;
 	const u8 *pos;
@@ -851,14 +802,15 @@
 	size_t len;
 
 	wpa_hexdump(MSG_DEBUG, "EAP-SIM: EAP data", reqData, reqDataLen);
-	if (config == NULL || config->identity == NULL) {
+	if (eap_get_config_identity(sm, &len) == NULL) {
 		wpa_printf(MSG_INFO, "EAP-SIM: Identity not configured");
-		eap_sm_request_identity(sm, config);
+		eap_sm_request_identity(sm);
 		ret->ignore = TRUE;
 		return NULL;
 	}
 
-	pos = eap_hdr_validate(EAP_TYPE_SIM, reqData, reqDataLen, &len);
+	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SIM,
+			       reqData, reqDataLen, &len);
 	if (pos == NULL || len < 1) {
 		ret->ignore = TRUE;
 		return NULL;
@@ -876,14 +828,14 @@
 	pos += 2; /* Reserved */
 
 	if (eap_sim_parse_attr(pos, reqData + len, &attr, 0, 0)) {
-		res = eap_sim_client_error(sm, data, req, respDataLen,
+		res = eap_sim_client_error(data, req, respDataLen,
 					   EAP_SIM_UNABLE_TO_PROCESS_PACKET);
 		goto done;
 	}
 
 	switch (subtype) {
 	case EAP_SIM_SUBTYPE_START:
-		res = eap_sim_process_start(sm, data, req, len,
+		res = eap_sim_process_start(sm, data, req,
 					    respDataLen, &attr);
 		break;
 	case EAP_SIM_SUBTYPE_CHALLENGE:
@@ -900,12 +852,12 @@
 		break;
 	case EAP_SIM_SUBTYPE_CLIENT_ERROR:
 		wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Client-Error");
-		res = eap_sim_client_error(sm, data, req, respDataLen,
+		res = eap_sim_client_error(data, req, respDataLen,
 					   EAP_SIM_UNABLE_TO_PROCESS_PACKET);
 		break;
 	default:
 		wpa_printf(MSG_DEBUG, "EAP-SIM: Unknown subtype=%d", subtype);
-		res = eap_sim_client_error(sm, data, req, respDataLen,
+		res = eap_sim_client_error(data, req, respDataLen,
 					   EAP_SIM_UNABLE_TO_PROCESS_PACKET);
 		break;
 	}
@@ -947,7 +899,7 @@
 	if (hostapd_get_rand(data->nonce_mt, EAP_SIM_NONCE_MT_LEN)) {
 		wpa_printf(MSG_WARNING, "EAP-SIM: Failed to get random data "
 			   "for NONCE_MT");
-		free(data);
+		os_free(data);
 		return NULL;
 	}
 	data->num_id_req = 0;
@@ -991,28 +943,59 @@
 	if (data->state != SUCCESS)
 		return NULL;
 
-	key = malloc(EAP_SIM_KEYING_DATA_LEN);
+	key = os_malloc(EAP_SIM_KEYING_DATA_LEN);
 	if (key == NULL)
 		return NULL;
 
 	*len = EAP_SIM_KEYING_DATA_LEN;
-	memcpy(key, data->msk, EAP_SIM_KEYING_DATA_LEN);
+	os_memcpy(key, data->msk, EAP_SIM_KEYING_DATA_LEN);
 
 	return key;
 }
 
 
-const struct eap_method eap_method_sim =
+static u8 * eap_sim_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
 {
-	.method = EAP_TYPE_SIM,
-	.name = "SIM",
-	.init = eap_sim_init,
-	.deinit = eap_sim_deinit,
-	.process = eap_sim_process,
-	.isKeyAvailable = eap_sim_isKeyAvailable,
-	.getKey = eap_sim_getKey,
-	.has_reauth_data = eap_sim_has_reauth_data,
-	.deinit_for_reauth = eap_sim_deinit_for_reauth,
-	.init_for_reauth = eap_sim_init_for_reauth,
-	.get_identity = eap_sim_get_identity,
-};
+	struct eap_sim_data *data = priv;
+	u8 *key;
+
+	if (data->state != SUCCESS)
+		return NULL;
+
+	key = os_malloc(EAP_EMSK_LEN);
+	if (key == NULL)
+		return NULL;
+
+	*len = EAP_EMSK_LEN;
+	os_memcpy(key, data->emsk, EAP_EMSK_LEN);
+
+	return key;
+}
+
+
+int eap_peer_sim_register(void)
+{
+	struct eap_method *eap;
+	int ret;
+
+	eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
+				    EAP_VENDOR_IETF, EAP_TYPE_SIM, "SIM");
+	if (eap == NULL)
+		return -1;
+
+	eap->init = eap_sim_init;
+	eap->deinit = eap_sim_deinit;
+	eap->process = eap_sim_process;
+	eap->isKeyAvailable = eap_sim_isKeyAvailable;
+	eap->getKey = eap_sim_getKey;
+	eap->has_reauth_data = eap_sim_has_reauth_data;
+	eap->deinit_for_reauth = eap_sim_deinit_for_reauth;
+	eap->init_for_reauth = eap_sim_init_for_reauth;
+	eap->get_identity = eap_sim_get_identity;
+	eap->get_emsk = eap_sim_get_emsk;
+
+	ret = eap_peer_method_register(eap);
+	if (ret)
+		eap_peer_method_free(eap);
+	return ret;
+}
Index: eap_fast.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/eap_fast.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/eap_fast.c -L contrib/wpa_supplicant/eap_fast.c -u -r1.2 -r1.3
--- contrib/wpa_supplicant/eap_fast.c
+++ contrib/wpa_supplicant/eap_fast.c
@@ -1,6 +1,6 @@
 /*
- * WPA Supplicant / EAP-FAST (draft-cam-winget-eap-fast-00.txt)
- * Copyright (c) 2004-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * EAP peer method: EAP-FAST (draft-cam-winget-eap-fast-03.txt)
+ * Copyright (c) 2004-2006, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -12,14 +12,11 @@
  * See README and COPYING for more details.
  */
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
+#include "includes.h"
 
 #include "common.h"
 #include "eap_i.h"
 #include "eap_tls_common.h"
-#include "wpa_supplicant.h"
 #include "config_ssid.h"
 #include "tls.h"
 #include "eap_tlv.h"
@@ -35,6 +32,8 @@
 #define EAP_FAST_VERSION 1
 #define EAP_FAST_KEY_LEN 64
 #define EAP_FAST_PAC_KEY_LEN 32
+#define EAP_FAST_SIMCK_LEN 40
+#define EAP_FAST_SKS_LEN 40
 
 #define TLS_EXT_PAC_OPAQUE 35
 
@@ -61,19 +60,11 @@
 };
 
 
-/* draft-cam-winget-eap-fast-02.txt:
- * 6.2 EAP-FAST Authentication Phase 1: Key Derivations */
-struct eap_fast_key_block_auth {
-	/* Extra key material after TLS key_block */
-	u8 session_key_seed[40];
-};
-
-
 /* draft-cam-winget-eap-fast-provisioning-01.txt:
  * 3.4 Key Derivations Used in the EAP-FAST Provisioning Exchange */
 struct eap_fast_key_block_provisioning {
 	/* Extra key material after TLS key_block */
-	u8 session_key_seed[40];
+	u8 session_key_seed[EAP_FAST_SKS_LEN];
 	u8 server_challenge[16];
 	u8 client_challenge[16];
 };
@@ -105,33 +96,36 @@
 	void *phase2_priv;
 	int phase2_success;
 
-	u8 phase2_type;
-	u8 *phase2_types;
+	struct eap_method_type phase2_type;
+	struct eap_method_type *phase2_types;
 	size_t num_phase2_types;
 	int resuming; /* starting a resumed session */
-	struct eap_fast_key_block_auth *key_block_a;
 	struct eap_fast_key_block_provisioning *key_block_p;
 	int provisioning_allowed; /* is PAC provisioning allowed */
 	int provisioning; /* doing PAC provisioning (not the normal auth) */
 
 	u8 key_data[EAP_FAST_KEY_LEN];
+	u8 emsk[EAP_EMSK_LEN];
 	int success;
 
 	struct eap_fast_pac *pac;
 	struct eap_fast_pac *current_pac;
 
 	int tls_master_secret_set;
+
+	u8 simck[EAP_FAST_SIMCK_LEN];
+	int simck_idx;
 };
 
 
 static void eap_fast_free_pac(struct eap_fast_pac *pac)
 {
-	free(pac->pac_opaque);
-	free(pac->pac_info);
-	free(pac->a_id);
-	free(pac->i_id);
-	free(pac->a_id_info);
-	free(pac);
+	os_free(pac->pac_opaque);
+	os_free(pac->pac_info);
+	os_free(pac->a_id);
+	os_free(pac->i_id);
+	os_free(pac->a_id_info);
+	os_free(pac);
 }
 
 
@@ -142,7 +136,7 @@
 
 	while (pac) {
 		if (pac->a_id_len == a_id_len &&
-		    memcmp(pac->a_id, a_id, a_id_len) == 0) {
+		    os_memcmp(pac->a_id, a_id, a_id_len) == 0) {
 			return pac;
 		}
 		pac = pac->next;
@@ -164,7 +158,7 @@
 	prev = NULL;
 	while (pac) {
 		if (pac->a_id_len == entry->a_id_len &&
-		    memcmp(pac->a_id, entry->a_id, pac->a_id_len) == 0) {
+		    os_memcmp(pac->a_id, entry->a_id, pac->a_id_len) == 0) {
 			if (prev == NULL) {
 				data->pac = pac->next;
 			} else {
@@ -180,60 +174,59 @@
 	}
 
 	/* Allocate a new entry and add it to the list of PACs. */
-	pac = malloc(sizeof(*pac));
+	pac = os_zalloc(sizeof(*pac));
 	if (pac == NULL)
 		return -1;
 
-	memset(pac, 0, sizeof(*pac));
-	memcpy(pac->pac_key, entry->pac_key, EAP_FAST_PAC_KEY_LEN);
+	os_memcpy(pac->pac_key, entry->pac_key, EAP_FAST_PAC_KEY_LEN);
 	if (entry->pac_opaque) {
-		pac->pac_opaque = malloc(entry->pac_opaque_len);
+		pac->pac_opaque = os_malloc(entry->pac_opaque_len);
 		if (pac->pac_opaque == NULL) {
 			eap_fast_free_pac(pac);
 			return -1;
 		}
-		memcpy(pac->pac_opaque, entry->pac_opaque,
-		       entry->pac_opaque_len);
+		os_memcpy(pac->pac_opaque, entry->pac_opaque,
+			  entry->pac_opaque_len);
 		pac->pac_opaque_len = entry->pac_opaque_len;
 	}
 	if (entry->pac_info) {
-		pac->pac_info = malloc(entry->pac_info_len);
+		pac->pac_info = os_malloc(entry->pac_info_len);
 		if (pac->pac_info == NULL) {
 			eap_fast_free_pac(pac);
 			return -1;
 		}
-		memcpy(pac->pac_info, entry->pac_info,
-		       entry->pac_info_len);
+		os_memcpy(pac->pac_info, entry->pac_info,
+			  entry->pac_info_len);
 		pac->pac_info_len = entry->pac_info_len;
 	}
 	if (entry->a_id) {
-		pac->a_id = malloc(entry->a_id_len);
+		pac->a_id = os_malloc(entry->a_id_len);
 		if (pac->a_id == NULL) {
 			eap_fast_free_pac(pac);
 			return -1;
 		}
-		memcpy(pac->a_id, entry->a_id,
-		       entry->a_id_len);
+		os_memcpy(pac->a_id, entry->a_id,
+			  entry->a_id_len);
 		pac->a_id_len = entry->a_id_len;
 	}
 	if (entry->i_id) {
-		pac->i_id = malloc(entry->i_id_len);
+		pac->i_id = os_malloc(entry->i_id_len);
 		if (pac->i_id == NULL) {
 			eap_fast_free_pac(pac);
 			return -1;
 		}
-		memcpy(pac->i_id, entry->i_id,
-		       entry->i_id_len);
+		os_memcpy(pac->i_id, entry->i_id,
+			  entry->i_id_len);
 		pac->i_id_len = entry->i_id_len;
 	}
 	if (entry->a_id_info) {
-		pac->a_id_info = malloc(entry->a_id_info_len);
+		pac->a_id_info = os_malloc(entry->a_id_info_len);
 		if (pac->a_id_info == NULL) {
 			eap_fast_free_pac(pac);
 			return -1;
 		}
-		memcpy(pac->a_id_info, entry->a_id_info,
-		       entry->a_id_info_len);
+		os_memcpy(pac->a_id_info, entry->a_id_info,
+			  entry->a_id_info_len);
 		pac->a_id_info_len = entry->a_id_info_len;
 	}
 	pac->next = data->pac;
@@ -267,7 +260,7 @@
 		len = l_end - rc->pos;
 		if (len >= buf_len)
 			len = buf_len - 1;
-		memcpy(buf, rc->pos, len);
+		os_memcpy(buf, rc->pos, len);
 		buf[len] = '\0';
 		rc->pos = l_end + 1;
 	}
@@ -293,15 +286,15 @@
 
 	if (value == NULL)
 		return NULL;
-	hlen = strlen(value);
+	hlen = os_strlen(value);
 	if (hlen & 1)
 		return NULL;
 	*len = hlen / 2;
-	buf = malloc(*len);
+	buf = os_malloc(*len);
 	if (buf == NULL)
 		return NULL;
 	if (hexstr2bin(value, buf, *len)) {
-		free(buf);
+		os_free(buf);
 		return NULL;
 	}
 	return buf;
@@ -321,9 +314,9 @@
 	if (pac_file == NULL)
 		return -1;
 
-	memset(&rc, 0, sizeof(rc));
+	os_memset(&rc, 0, sizeof(rc));
 
-	if (strncmp(pac_file, "blob://", 7) == 0) {
+	if (os_strncmp(pac_file, "blob://", 7) == 0) {
 		const struct wpa_config_blob *blob;
 		blob = eap_get_config_blob(sm, pac_file + 7);
 		if (blob == NULL) {
@@ -344,17 +337,17 @@
 		}
 	}
 
-	buf = malloc(buf_len);
+	buf = os_malloc(buf_len);
 	if (buf == NULL) {
 		return -1;
 	}
 
 	line++;
 	if (eap_fast_read_line(&rc, buf, buf_len) < 0 ||
-	    strcmp(pac_file_hdr, buf) != 0) {
+	    os_strcmp(pac_file_hdr, buf) != 0) {
 		wpa_printf(MSG_INFO, "EAP-FAST: Unrecognized header line in "
 			   "PAC file '%s'", pac_file);
-		free(buf);
+		os_free(buf);
 		if (rc.f)
 			fclose(rc.f);
 		return -1;
@@ -362,12 +355,12 @@
 
 	while (eap_fast_read_line(&rc, buf, buf_len) == 0) {
 		line++;
-		pos = strchr(buf, '=');
+		pos = os_strchr(buf, '=');
 		if (pos) {
 			*pos++ = '\0';
 		}
 
-		if (strcmp(buf, "START") == 0) {
+		if (os_strcmp(buf, "START") == 0) {
 			if (pac) {
 				wpa_printf(MSG_INFO, "EAP-FAST: START line "
 					   "without END in '%s:%d'",
@@ -375,15 +368,14 @@
 				ret = -1;
 				break;
 			}
-			pac = malloc(sizeof(*pac));
+			pac = os_zalloc(sizeof(*pac));
 			if (pac == NULL) {
 				wpa_printf(MSG_INFO, "EAP-FAST: No memory for "
 					   "PAC entry");
 				ret = -1;
 				break;
 			}
-			memset(pac, 0, sizeof(*pac));
-		} else if (strcmp(buf, "END") == 0) {
+		} else if (os_strcmp(buf, "END") == 0) {
 			if (pac == NULL) {
 				wpa_printf(MSG_INFO, "EAP-FAST: END line "
 					   "without START in '%s:%d'",
@@ -395,7 +387,7 @@
 			data->pac = pac;
 			pac = NULL;
 			count++;
-		} else if (pac && strcmp(buf, "PAC-Key") == 0) {
+		} else if (pac && os_strcmp(buf, "PAC-Key") == 0) {
 			u8 *key;
 			size_t key_len;
 			key = eap_fast_parse_hex(pos, &key_len);
@@ -403,13 +395,14 @@
 				wpa_printf(MSG_INFO, "EAP-FAST: Invalid "
 					   "PAC-Key '%s:%d'", pac_file, line);
 				ret = -1;
-				free(key);
+				os_free(key);
 				break;
 			}
 
-			memcpy(pac->pac_key, key, EAP_FAST_PAC_KEY_LEN);
-			free(key);
-		} else if (pac && strcmp(buf, "PAC-Opaque") == 0) {
+			os_memcpy(pac->pac_key, key, EAP_FAST_PAC_KEY_LEN);
+			os_free(key);
+		} else if (pac && os_strcmp(buf, "PAC-Opaque") == 0) {
+			os_free(pac->pac_opaque);
 			pac->pac_opaque =
 				eap_fast_parse_hex(pos, &pac->pac_opaque_len);
 			if (pac->pac_opaque == NULL) {
@@ -419,7 +412,8 @@
 				ret = -1;
 				break;
 			}
-		} else if (pac && strcmp(buf, "A-ID") == 0) {
+		} else if (pac && os_strcmp(buf, "A-ID") == 0) {
+			os_free(pac->a_id);
 			pac->a_id = eap_fast_parse_hex(pos, &pac->a_id_len);
 			if (pac->a_id == NULL) {
 				wpa_printf(MSG_INFO, "EAP-FAST: Invalid "
@@ -427,7 +421,8 @@
 				ret = -1;
 				break;
 			}
-		} else if (pac && strcmp(buf, "I-ID") == 0) {
+		} else if (pac && os_strcmp(buf, "I-ID") == 0) {
+			os_free(pac->i_id);
 			pac->i_id = eap_fast_parse_hex(pos, &pac->i_id_len);
 			if (pac->i_id == NULL) {
 				wpa_printf(MSG_INFO, "EAP-FAST: Invalid "
@@ -435,7 +430,8 @@
 				ret = -1;
 				break;
 			}
-		} else if (pac && strcmp(buf, "A-ID-Info") == 0) {
+		} else if (pac && os_strcmp(buf, "A-ID-Info") == 0) {
+			os_free(pac->a_id_info);
 			pac->a_id_info =
 				eap_fast_parse_hex(pos, &pac->a_id_info_len);
 			if (pac->a_id_info == NULL) {
@@ -455,7 +451,7 @@
 		ret = -1;
 	}
 
-	free(buf);
+	os_free(buf);
 	if (rc.f)
 		fclose(rc.f);
 
@@ -472,20 +468,20 @@
 			   const char *field, const u8 *data,
 			   size_t len, int txt)
 {
-	int i;
-	size_t need;
+	size_t i, need;
+	int ret;
 
 	if (data == NULL || *buf == NULL)
 		return;
 
-	need = strlen(field) + len * 2 + 30;
+	need = os_strlen(field) + len * 2 + 30;
 	if (txt)
-		need += strlen(field) + len + 20;
+		need += os_strlen(field) + len + 20;
 
 	if (*pos - *buf + need > *buf_len) {
-		char *nbuf = realloc(*buf, *buf_len + need);
+		char *nbuf = os_realloc(*buf, *buf_len + need);
 		if (nbuf == NULL) {
-			free(*buf);
+			os_free(*buf);
 			*buf = NULL;
 			return;
 		}
@@ -493,21 +489,33 @@
 		*buf_len += need;
 	}
 
-	*pos += snprintf(*pos, *buf + *buf_len - *pos, "%s=", field);
-	for (i = 0; i < len; i++) {
-		*pos += snprintf(*pos, *buf + *buf_len - *pos,
-				 "%02x", data[i]);
-	}
-	*pos += snprintf(*pos, *buf + *buf_len - *pos, "\n");
+	ret = os_snprintf(*pos, *buf + *buf_len - *pos, "%s=", field);
+	if (ret < 0 || ret >= *buf + *buf_len - *pos)
+		return;
+	*pos += ret;
+	*pos += wpa_snprintf_hex(*pos, *buf + *buf_len - *pos, data, len);
+	ret = os_snprintf(*pos, *buf + *buf_len - *pos, "\n");
+	if (ret < 0 || ret >= *buf + *buf_len - *pos)
+		return;
+	*pos += ret;
 
 	if (txt) {
-		*pos += snprintf(*pos, *buf + *buf_len - *pos,
-				 "%s-txt=", field);
+		ret = os_snprintf(*pos, *buf + *buf_len - *pos,
+				  "%s-txt=", field);
+		if (ret < 0 || ret >= *buf + *buf_len - *pos)
+			return;
+		*pos += ret;
 		for (i = 0; i < len; i++) {
-			*pos += snprintf(*pos, *buf + *buf_len - *pos,
-					 "%c", data[i]);
+			ret = os_snprintf(*pos, *buf + *buf_len - *pos,
+					  "%c", data[i]);
+			if (ret < 0 || ret >= *buf + *buf_len - *pos)
+				return;
+			*pos += ret;
 		}
-		*pos += snprintf(*pos, *buf + *buf_len - *pos, "\n");
+		ret = os_snprintf(*pos, *buf + *buf_len - *pos, "\n");
+		if (ret < 0 || ret >= *buf + *buf_len - *pos)
+			return;
+		*pos += ret;
 	}
 }
 
@@ -517,7 +525,7 @@
 {
 	FILE *f;
 	struct eap_fast_pac *pac;
-	int count = 0;
+	int count = 0, ret;
 	char *buf, *pos;
 	size_t buf_len;
 
@@ -525,15 +533,25 @@
 		return -1;
 
 	buf_len = 1024;
-	pos = buf = malloc(buf_len);
+	pos = buf = os_malloc(buf_len);
 	if (buf == NULL)
 		return -1;
 
-	pos += snprintf(pos, buf + buf_len - pos, "%s\n", pac_file_hdr);
+	ret = os_snprintf(pos, buf + buf_len - pos, "%s\n", pac_file_hdr);
+	if (ret < 0 || ret >= buf + buf_len - pos) {
+		os_free(buf);
+		return -1;
+	}
+	pos += ret;
 
 	pac = data->pac;
 	while (pac) {
-		pos += snprintf(pos, buf + buf_len - pos, "START\n");
+		ret = os_snprintf(pos, buf + buf_len - pos, "START\n");
+		if (ret < 0 || ret >= buf + buf_len - pos) {
+			os_free(buf);
+			return -1;
+		}
+		pos += ret;
 		eap_fast_write(&buf, &pos, &buf_len, "PAC-Key", pac->pac_key,
 			       EAP_FAST_PAC_KEY_LEN, 0);
 		eap_fast_write(&buf, &pos, &buf_len, "PAC-Opaque",
@@ -546,31 +564,35 @@
 			       pac->i_id_len, 1);
 		eap_fast_write(&buf, &pos, &buf_len, "A-ID-Info",
 			       pac->a_id_info, pac->a_id_info_len, 1);
-		pos += snprintf(pos, buf + buf_len - pos, "END\n");
-		count++;
-		pac = pac->next;
-
 		if (buf == NULL) {
 			wpa_printf(MSG_DEBUG, "EAP-FAST: No memory for PAC "
 				   "data");
 			return -1;
 		}
+		ret = os_snprintf(pos, buf + buf_len - pos, "END\n");
+		if (ret < 0 || ret >= buf + buf_len - pos) {
+			os_free(buf);
+			return -1;
+		}
+		pos += ret;
+		count++;
+		pac = pac->next;
 	}
 
-	if (strncmp(pac_file, "blob://", 7) == 0) {
+	if (os_strncmp(pac_file, "blob://", 7) == 0) {
 		struct wpa_config_blob *blob;
-		blob = malloc(sizeof(*blob));
+		blob = os_zalloc(sizeof(*blob));
 		if (blob == NULL) {
-			free(buf);
+			os_free(buf);
 			return -1;
 		}
-		memset(blob, 0, sizeof(*blob));
 		blob->data = (u8 *) buf;
 		blob->len = pos - buf;
 		buf = NULL;
-		blob->name = strdup(pac_file + 7);
+		blob->name = os_strdup(pac_file + 7);
 		if (blob->name == NULL) {
-			wpa_config_free_blob(blob);
+			os_free(blob->data);
+			os_free(blob);
 			return -1;
 		}
 		eap_set_config_blob(sm, blob);
@@ -579,11 +601,11 @@
 		if (f == NULL) {
 			wpa_printf(MSG_INFO, "EAP-FAST: Failed to open PAC "
 				   "file '%s' for writing", pac_file);
-			free(buf);
+			os_free(buf);
 			return -1;
 		}
 		fprintf(f, "%s", buf);
-		free(buf);
+		os_free(buf);
 		fclose(f);
 	}
 
@@ -599,14 +621,13 @@
 	struct eap_fast_data *data;
 	struct wpa_ssid *config = eap_get_config(sm);
 
-	data = malloc(sizeof(*data));
+	data = os_zalloc(sizeof(*data));
 	if (data == NULL)
 		return NULL;
-	memset(data, 0, sizeof(*data));
 	data->fast_version = EAP_FAST_VERSION;
 
 	if (config && config->phase1) {
-		if (strstr(config->phase1, "fast_provisioning=1")) {
+		if (os_strstr(config->phase1, "fast_provisioning=1")) {
 			data->provisioning_allowed = 1;
 			wpa_printf(MSG_DEBUG, "EAP-FAST: Automatic PAC "
 				   "provisioning is allowed");
@@ -615,15 +636,17 @@
 
 	if (config && config->phase2) {
 		char *start, *pos, *buf;
-		u8 method, *methods = NULL, *_methods;
+		struct eap_method_type *methods = NULL, *_methods;
+		u8 method;
 		size_t num_methods = 0;
-		start = buf = strdup(config->phase2);
+		start = buf = os_strdup(config->phase2);
 		if (buf == NULL) {
 			eap_fast_deinit(sm, data);
 			return NULL;
 		}
 		while (start && *start != '\0') {
-			pos = strstr(start, "auth=");
+			int vendor;
+			pos = os_strstr(start, "auth=");
 			if (pos == NULL)
 				break;
 			if (start != pos && *(pos - 1) != ' ') {
@@ -632,28 +655,33 @@
 			}
 
 			start = pos + 5;
-			pos = strchr(start, ' ');
+			pos = os_strchr(start, ' ');
 			if (pos)
 				*pos++ = '\0';
-			method = eap_get_phase2_type(start);
-			if (method == EAP_TYPE_NONE) {
+			method = eap_get_phase2_type(start, &vendor);
+			if (vendor == EAP_VENDOR_IETF &&
+			    method == EAP_TYPE_NONE) {
 				wpa_printf(MSG_ERROR, "EAP-FAST: Unsupported "
 					   "Phase2 method '%s'", start);
 			} else {
 				num_methods++;
-				_methods = realloc(methods, num_methods);
+				_methods = os_realloc(
+					methods,
+					num_methods * sizeof(*methods));
 				if (_methods == NULL) {
-					free(methods);
+					os_free(methods);
+					os_free(buf);
 					eap_fast_deinit(sm, data);
 					return NULL;
 				}
 				methods = _methods;
-				methods[num_methods - 1] = method;
+				methods[num_methods - 1].vendor = vendor;
+				methods[num_methods - 1].method = method;
 			}
 
 			start = pos;
 		}
-		free(buf);
+		os_free(buf);
 		data->phase2_types = methods;
 		data->num_phase2_types = num_methods;
 	}
@@ -667,8 +695,10 @@
 		return NULL;
 	}
 	wpa_hexdump(MSG_DEBUG, "EAP-FAST: Phase2 EAP types",
-		    data->phase2_types, data->num_phase2_types);
-	data->phase2_type = EAP_TYPE_NONE;
+		    (u8 *) data->phase2_types,
+		    data->num_phase2_types * sizeof(struct eap_method_type));
+	data->phase2_type.vendor = EAP_VENDOR_IETF;
+	data->phase2_type.method = EAP_TYPE_NONE;
 
 	if (eap_tls_ssl_init(sm, &data->ssl, config)) {
 		wpa_printf(MSG_INFO, "EAP-FAST: Failed to initialize SSL.");
@@ -706,9 +736,8 @@
 		return;
 	if (data->phase2_priv && data->phase2_method)
 		data->phase2_method->deinit(sm, data->phase2_priv);
-	free(data->phase2_types);
-	free(data->key_block_a);
-	free(data->key_block_p);
+	os_free(data->phase2_types);
+	os_free(data->key_block_p);
 	eap_tls_ssl_deinit(sm, &data->ssl);
 
 	pac = data->pac;
@@ -718,7 +747,7 @@
 		pac = pac->next;
 		eap_fast_free_pac(prev);
 	}
-	free(data);
+	os_free(data);
 }
 
 
@@ -732,7 +761,7 @@
 
 	/* TODO: add support for fragmentation, if needed. This will need to
 	 * add TLS Message Length field, if the frame is fragmented. */
-	resp = malloc(sizeof(struct eap_hdr) + 2 + data->ssl.tls_out_limit);
+	resp = os_malloc(sizeof(struct eap_hdr) + 2 + data->ssl.tls_out_limit);
 	if (resp == NULL)
 		return 0;
 
@@ -749,7 +778,7 @@
 	if (res < 0) {
 		wpa_printf(MSG_INFO, "EAP-FAST: Failed to encrypt Phase 2 "
 			   "data");
-		free(resp);
+		os_free(resp);
 		return 0;
 	}
 
@@ -760,53 +789,57 @@
 }
 
 
-static int eap_fast_phase2_nak(struct eap_sm *sm,
-			       struct eap_fast_data *data,
+static int eap_fast_phase2_nak(struct eap_fast_data *data,
 			       struct eap_hdr *hdr,
 			       u8 **resp, size_t *resp_len)
 {
 	struct eap_hdr *resp_hdr;
 	u8 *pos = (u8 *) (hdr + 1);
+	size_t i;
 
+	/* TODO: add support for expanded Nak */
 	wpa_printf(MSG_DEBUG, "EAP-FAST: Phase 2 Request: Nak type=%d", *pos);
 	wpa_hexdump(MSG_DEBUG, "EAP-FAST: Allowed Phase2 EAP types",
-		    data->phase2_types, data->num_phase2_types);
-	*resp_len = sizeof(struct eap_hdr) + 1 + data->num_phase2_types;
-	*resp = malloc(*resp_len);
+		    (u8 *) data->phase2_types,
+		    data->num_phase2_types * sizeof(struct eap_method_type));
+	*resp_len = sizeof(struct eap_hdr) + 1;
+	*resp = os_malloc(*resp_len + data->num_phase2_types);
 	if (*resp == NULL)
 		return -1;
 
 	resp_hdr = (struct eap_hdr *) (*resp);
 	resp_hdr->code = EAP_CODE_RESPONSE;
 	resp_hdr->identifier = hdr->identifier;
-	resp_hdr->length = host_to_be16(*resp_len);
 	pos = (u8 *) (resp_hdr + 1);
 	*pos++ = EAP_TYPE_NAK;
-	memcpy(pos, data->phase2_types, data->num_phase2_types);
+	for (i = 0; i < data->num_phase2_types; i++) {
+		if (data->phase2_types[i].vendor == EAP_VENDOR_IETF &&
+		    data->phase2_types[i].method < 256) {
+			(*resp_len)++;
+			*pos++ = data->phase2_types[i].method;
+		}
+	}
+	resp_hdr->length = host_to_be16(*resp_len);
 
 	return 0;
 }
 
 
-static int eap_fast_derive_msk(struct eap_sm *sm, struct eap_fast_data *data)
+static int eap_fast_derive_msk(struct eap_fast_data *data)
 {
-	u8 isk[32];
-	u8 imck[60];
-
-	if (data->key_block_a == NULL)
-		return -1;
-
-	memset(isk, 0, sizeof(isk));
-	sha1_t_prf(data->key_block_a->session_key_seed,
-		   sizeof(data->key_block_a->session_key_seed),
-		   "Inner Methods Compound Keys",
-		   isk, sizeof(isk), imck, sizeof(imck));
-	sha1_t_prf(imck, 40, "Session Key Generating Function", (u8 *) "", 0,
+	/* Derive EAP Master Session Keys (section 5.4) */
+	sha1_t_prf(data->simck, EAP_FAST_SIMCK_LEN,
+		   "Session Key Generating Function", (u8 *) "", 0,
 		   data->key_data, EAP_FAST_KEY_LEN);
-
 	wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: Derived key (MSK)",
 			data->key_data, EAP_FAST_KEY_LEN);
 
+	sha1_t_prf(data->simck, EAP_FAST_SIMCK_LEN,
+		   "Extended Session Key Generating Function",
+		   (u8 *) "", 0, data->emsk, EAP_EMSK_LEN);
+	wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: Derived key (EMSK)",
+			data->emsk, EAP_EMSK_LEN);
+
 	data->success = 1;
 
 	return 0;
@@ -823,7 +856,8 @@
 	size_t seed_len, server_random_len;
 
 	if (data->tls_master_secret_set || !data->current_pac ||
-	    tls_connection_get_keys(sm->ssl_ctx, data->ssl.conn, &keys)) {
+	    tls_connection_get_keys(sm->ssl_ctx, data->ssl.conn, &keys) ||
+	    keys.client_random == NULL) {
 		return 0;
 	}
 
@@ -857,14 +891,13 @@
 	wpa_hexdump(MSG_DEBUG, "EAP-FAST: server_random",
 		    server_random, server_random_len);
 
-
 	seed_len = keys.client_random_len + server_random_len;
-	seed = malloc(seed_len);
+	seed = os_malloc(seed_len);
 	if (seed == NULL)
 		return -1;
-	memcpy(seed, server_random, server_random_len);
-	memcpy(seed + server_random_len,
-	       keys.client_random, keys.client_random_len);
+	os_memcpy(seed, server_random, server_random_len);
+	os_memcpy(seed + server_random_len,
+		  keys.client_random, keys.client_random_len);
 
 	wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: T-PRF seed", seed, seed_len);
 	wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: PAC-Key",
@@ -874,7 +907,7 @@
 	sha1_t_prf(data->current_pac->pac_key, EAP_FAST_PAC_KEY_LEN,
 		   "PAC to master secret label hash",
 		   seed, seed_len, master_secret, sizeof(master_secret));
-	free(seed);
+	os_free(seed);
 	wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: TLS pre-master-secret",
 			master_secret, sizeof(master_secret));
 
@@ -890,63 +923,86 @@
 				char *label, size_t len)
 {
 	struct tls_keys keys;
-	u8 *rnd;
-	u8 *out;
+	u8 *rnd = NULL, *out;
 	int block_size;
 
-	if (tls_connection_get_keys(sm->ssl_ctx, data->conn, &keys))
-		return NULL;
 	block_size = tls_connection_get_keyblock_size(sm->ssl_ctx, data->conn);
 	if (block_size < 0)
 		return NULL;
-	out = malloc(block_size + len);
-	rnd = malloc(keys.client_random_len + keys.server_random_len);
-	if (out == NULL || rnd == NULL) {
-		free(out);
-		free(rnd);
+
+	out = os_malloc(block_size + len);
+	if (out == NULL)
 		return NULL;
+
+	if (tls_connection_prf(sm->ssl_ctx, data->conn, label, 1, out,
+			       block_size + len) == 0) {
+		os_memmove(out, out + block_size, len);
+		return out;
 	}
-	memcpy(rnd, keys.server_random, keys.server_random_len);
-	memcpy(rnd + keys.server_random_len, keys.client_random,
-	       keys.client_random_len);
+
+	if (tls_connection_get_keys(sm->ssl_ctx, data->conn, &keys))
+		goto fail;
+
+	rnd = os_malloc(keys.client_random_len + keys.server_random_len);
+	if (rnd == NULL)
+		goto fail;
+
+	os_memcpy(rnd, keys.server_random, keys.server_random_len);
+	os_memcpy(rnd + keys.server_random_len, keys.client_random,
+		  keys.client_random_len);
 
 	wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: master_secret for key "
 			"expansion", keys.master_key, keys.master_key_len);
 	if (tls_prf(keys.master_key, keys.master_key_len,
 		    label, rnd, keys.client_random_len +
-		    keys.server_random_len, out, block_size + len)) {
-		free(rnd);
-		free(out);
-		return NULL;
-	}
-	free(rnd);
-	memmove(out, out + block_size, len);
+		    keys.server_random_len, out, block_size + len))
+		goto fail;
+	os_free(rnd);
+	os_memmove(out, out + block_size, len);
 	return out;
+
+fail:
+	os_free(rnd);
+	os_free(out);
+	return NULL;
 }
 
 
 static void eap_fast_derive_key_auth(struct eap_sm *sm,
 				     struct eap_fast_data *data)
 {
-	free(data->key_block_a);
-	data->key_block_a = (struct eap_fast_key_block_auth *)
-		eap_fast_derive_key(sm, &data->ssl, "key expansion",
-				    sizeof(*data->key_block_a));
-	if (data->key_block_a == NULL) {
+	u8 *sks;
+
+	/* draft-cam-winget-eap-fast-05.txt:
+	 * 5.1 EAP-FAST Authentication Phase 1: Key Derivations
+	 * Extra key material after TLS key_block: session_ket_seed[40]
+	 */
+
+	sks = eap_fast_derive_key(sm, &data->ssl, "key expansion",
+				  EAP_FAST_SKS_LEN);
+	if (sks == NULL) {
 		wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to derive "
 			   "session_key_seed");
 		return;
 	}
-	wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: session_key_seed",
-			data->key_block_a->session_key_seed,
-			sizeof(data->key_block_a->session_key_seed));
+
+	/*
+	 * draft-cam-winget-eap-fast-05.txt, 5.2:
+	 * S-IMCK[0] = session_key_seed
+	 */
+	wpa_hexdump_key(MSG_DEBUG,
+			"EAP-FAST: session_key_seed (SKS = S-IMCK[0])",
+			sks, EAP_FAST_SKS_LEN);
+	data->simck_idx = 0;
+	os_memcpy(data->simck, sks, EAP_FAST_SIMCK_LEN);
+	os_free(sks);
 }
 
 
 static void eap_fast_derive_key_provisioning(struct eap_sm *sm,
 					     struct eap_fast_data *data)
 {
-	free(data->key_block_p);
+	os_free(data->key_block_p);
 	data->key_block_p = (struct eap_fast_key_block_provisioning *)
 		eap_fast_derive_key(sm, &data->ssl, "key expansion",
 				    sizeof(*data->key_block_p));
@@ -954,9 +1010,17 @@
 		wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to derive key block");
 		return;
 	}
-	wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: session_key_seed",
+	/*
+	 * draft-cam-winget-eap-fast-05.txt, 5.2:
+	 * S-IMCK[0] = session_key_seed
+	 */
+	wpa_hexdump_key(MSG_DEBUG,
+			"EAP-FAST: session_key_seed (SKS = S-IMCK[0])",
 			data->key_block_p->session_key_seed,
 			sizeof(data->key_block_p->session_key_seed));
+	data->simck_idx = 0;
+	os_memcpy(data->simck, data->key_block_p->session_key_seed,
+		  EAP_FAST_SIMCK_LEN);
 	wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: server_challenge",
 			data->key_block_p->server_challenge,
 			sizeof(data->key_block_p->server_challenge));
@@ -979,7 +1043,6 @@
 static int eap_fast_phase2_request(struct eap_sm *sm,
 				   struct eap_fast_data *data,
 				   struct eap_method_ret *ret,
-				   const struct eap_hdr *req,
 				   struct eap_hdr *hdr,
 				   u8 **resp, size_t *resp_len)
 {
@@ -996,30 +1059,40 @@
 	wpa_printf(MSG_DEBUG, "EAP-FAST: Phase 2 Request: type=%d", *pos);
 	switch (*pos) {
 	case EAP_TYPE_IDENTITY:
-		*resp = eap_sm_buildIdentity(sm, req->identifier, resp_len, 1);
+		*resp = eap_sm_buildIdentity(sm, hdr->identifier, resp_len, 1);
 		break;
 	default:
-		if (data->phase2_type == EAP_TYPE_NONE) {
-			int i;
+		if (data->phase2_type.vendor == EAP_VENDOR_IETF &&
+		    data->phase2_type.method == EAP_TYPE_NONE) {
+			size_t i;
 			for (i = 0; i < data->num_phase2_types; i++) {
-				if (data->phase2_types[i] != *pos)
+				if (data->phase2_types[i].vendor !=
+				    EAP_VENDOR_IETF ||
+				    data->phase2_types[i].method != *pos)
 					continue;
 
-				data->phase2_type = *pos;
+				data->phase2_type.vendor =
+					data->phase2_types[i].vendor;
+				data->phase2_type.method =
+					data->phase2_types[i].method;
 				wpa_printf(MSG_DEBUG, "EAP-FAST: Selected "
-					   "Phase 2 EAP method %d",
-					   data->phase2_type);
+					   "Phase 2 EAP vendor %d method %d",
+					   data->phase2_type.vendor,
+					   data->phase2_type.method);
 				break;
 			}
 		}
-		if (*pos != data->phase2_type || *pos == EAP_TYPE_NONE) {
-			if (eap_fast_phase2_nak(sm, data, hdr, resp, resp_len))
+		if (*pos != data->phase2_type.method ||
+		    *pos == EAP_TYPE_NONE) {
+			if (eap_fast_phase2_nak(data, hdr, resp, resp_len))
 				return -1;
 			return 0;
 		}
 
 		if (data->phase2_priv == NULL) {
-			data->phase2_method = eap_sm_get_eap_methods(*pos);
+			data->phase2_method = eap_sm_get_eap_methods(
+				data->phase2_type.vendor,
+				data->phase2_type.method);
 			if (data->phase2_method) {
 				if (data->key_block_p) {
 					sm->auth_challenge =
@@ -1030,9 +1103,11 @@
 						client_challenge;
 				}
 				sm->init_phase2 = 1;
+				sm->mschapv2_full_key = 1;
 				data->phase2_priv =
 					data->phase2_method->init(sm);
 				sm->init_phase2 = 0;
+				sm->mschapv2_full_key = 0;
 				sm->auth_challenge = NULL;
 				sm->peer_challenge = NULL;
 			}
@@ -1044,7 +1119,7 @@
 			ret->decision = DECISION_FAIL;
 			return -1;
 		}
-		memset(&iret, 0, sizeof(iret));
+		os_memset(&iret, 0, sizeof(iret));
 		*resp = data->phase2_method->process(sm, data->phase2_priv,
 						     &iret, (u8 *) hdr, len,
 						     resp_len);
@@ -1071,7 +1146,7 @@
 {
 	struct eap_tlv_nak_tlv *nak;
 	*len = sizeof(*nak);
-	nak = malloc(*len);
+	nak = os_malloc(*len);
 	if (nak == NULL)
 		return NULL;
 	nak->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY | EAP_TLV_NAK_TLV);
@@ -1086,7 +1161,7 @@
 {
 	struct eap_tlv_intermediate_result_tlv *result;
 	*len = sizeof(*result);
-	result = malloc(*len);
+	result = os_malloc(*len);
 	if (result == NULL)
 		return NULL;
 	result->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY |
@@ -1105,11 +1180,10 @@
 	struct eap_tlv_pac_ack_tlv *ack;
 
 	*len = sizeof(*res) + sizeof(*ack);
-	res = malloc(*len);
+	res = os_zalloc(*len);
 	if (res == NULL)
 		return NULL;
 
-	memset(res, 0, *len);
 	res->tlv_type = host_to_be16(EAP_TLV_RESULT_TLV |
 				     EAP_TLV_TYPE_MANDATORY);
 	res->length = host_to_be16(sizeof(*res) - sizeof(struct eap_tlv_hdr));
@@ -1132,19 +1206,19 @@
 	struct eap_tlv_hdr *tlv;
 
 	/* Encapsulate EAP packet in EAP Payload TLV */
-	tlv = malloc(sizeof(*tlv) + *len);
+	tlv = os_malloc(sizeof(*tlv) + *len);
 	if (tlv == NULL) {
 		wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to "
 			   "allocate memory for TLV "
 			   "encapsulation");
-		free(buf);
+		os_free(buf);
 		return NULL;
 	}
 	tlv->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY |
 				     EAP_TLV_EAP_PAYLOAD_TLV);
 	tlv->length = host_to_be16(*len);
-	memcpy(tlv + 1, buf, *len);
-	free(buf);
+	os_memcpy(tlv + 1, buf, *len);
+	os_free(buf);
 	*len += sizeof(*tlv);
 	return (u8 *) tlv;
 }
@@ -1153,10 +1227,10 @@
 static u8 * eap_fast_process_crypto_binding(
 	struct eap_sm *sm, struct eap_fast_data *data,
 	struct eap_method_ret *ret,
-	struct eap_tlv_crypto_binding__tlv *bind, size_t bind_len,
+	struct eap_tlv_crypto_binding__tlv *_bind, size_t bind_len,
 	size_t *resp_len, int final)
 {
-	u8 *resp, *sks = NULL;
+	u8 *resp;
 	struct eap_tlv_intermediate_result_tlv *rresult;
 	struct eap_tlv_crypto_binding__tlv *rbind;
 	u8 isk[32], imck[60], *cmk, cmac[20], *key;
@@ -1165,46 +1239,37 @@
 
 	wpa_printf(MSG_DEBUG, "EAP-FAST: Crypto-Binding TLV: Version %d "
 		   "Received Version %d SubType %d",
-		   bind->version, bind->received_version, bind->subtype);
+		   _bind->version, _bind->received_version, _bind->subtype);
 	wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: NONCE",
-		    bind->nonce, sizeof(bind->nonce));
+		    _bind->nonce, sizeof(_bind->nonce));
 	wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Compound MAC",
-		    bind->compound_mac, sizeof(bind->compound_mac));
+		    _bind->compound_mac, sizeof(_bind->compound_mac));
 
-	if (bind->version != EAP_FAST_VERSION ||
-	    bind->received_version != EAP_FAST_VERSION ||
-	    bind->subtype != EAP_TLV_CRYPTO_BINDING_SUBTYPE_REQUEST) {
+	if (_bind->version != EAP_FAST_VERSION ||
+	    _bind->received_version != EAP_FAST_VERSION ||
+	    _bind->subtype != EAP_TLV_CRYPTO_BINDING_SUBTYPE_REQUEST) {
 		wpa_printf(MSG_INFO, "EAP-FAST: Invalid version/subtype in "
 			   "Crypto-Binding TLV: Version %d "
 			   "Received Version %d SubType %d",
-			   bind->version, bind->received_version,
-			   bind->subtype);
+			   _bind->version, _bind->received_version,
+			   _bind->subtype);
 		resp = eap_fast_tlv_result(EAP_TLV_RESULT_FAILURE, 1,
 					   resp_len);
 		return resp;
 	}
 
+	wpa_printf(MSG_DEBUG, "EAP-FAST: Determining CMK[%d] for Compound MIC "
+		   "calculation", data->simck_idx + 1);
 
-	if (data->provisioning) {
-		if (data->key_block_p) {
-			sks = data->key_block_p->session_key_seed;
-		}
-	} else {
-		if (data->key_block_a) {
-			sks = data->key_block_a->session_key_seed;
-		}
-	}
-	if (sks == NULL) {
-		wpa_printf(MSG_INFO, "EAP-FAST: No Session Key Seed available "
-			   "for processing Crypto-Binding TLV");
-		return NULL;
-	}
-
-	wpa_printf(MSG_DEBUG, "EAP-FAST: Determining CMK for Compound MIC "
-		   "calculation");
-	wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: S-IMCK[0] = SKS", sks, 40);
+	/*
+	 * draft-cam-winget-eap-fast-05.txt, 5.2:
+	 * IMCK[j] = T-PRF(S-IMCK[j-1], "Inner Methods Compound Keys",
+	 *                 MSK[j], 60)
+	 * S-IMCK[j] = first 40 octets of IMCK[j]
+	 * CMK[j] = last 20 octets of IMCK[j]
+	 */
 
-	memset(isk, 0, sizeof(isk));
+	os_memset(isk, 0, sizeof(isk));
 	if (data->phase2_method == NULL || data->phase2_priv == NULL) {
 		wpa_printf(MSG_DEBUG, "EAP-FAST: Phase 2 method not "
 			   "available");
@@ -1222,45 +1287,42 @@
 		}
 		if (key_len > sizeof(isk))
 			key_len = sizeof(isk);
-		/* FIX: which end is being padded? */
-#if 0
-		memcpy(isk + (sizeof(isk) - key_len), key, key_len);
-#else
-		memcpy(isk, key, key_len);
-#endif
-		free(key);
+		os_memcpy(isk, key, key_len);
+		os_free(key);
 	}
-	wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: ISK[0]", isk, sizeof(isk));
-	sha1_t_prf(sks, 40, "Inner Methods Compound Keys",
+	wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: ISK[j]", isk, sizeof(isk));
+	sha1_t_prf(data->simck, EAP_FAST_SIMCK_LEN,
+		   "Inner Methods Compound Keys",
 		   isk, sizeof(isk), imck, sizeof(imck));
-	/* S-IMCK[1] = imkc[0..39] */
-	wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: S-IMCK[1]", imck, 40);
-	cmk = imck + 40;
-	wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: CMK", cmk, 20);
+	data->simck_idx++;
+	os_memcpy(data->simck, imck, EAP_FAST_SIMCK_LEN);
+	wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: S-IMCK[j]",
+			data->simck, EAP_FAST_SIMCK_LEN);
+	cmk = imck + EAP_FAST_SIMCK_LEN;
+	wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: CMK[j]", cmk, 20);
 
-	memcpy(cmac, bind->compound_mac, sizeof(cmac));
-	memset(bind->compound_mac, 0, sizeof(cmac));
+	os_memcpy(cmac, _bind->compound_mac, sizeof(cmac));
+	os_memset(_bind->compound_mac, 0, sizeof(cmac));
 	wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Crypto-Binding TLV for Compound "
-		    "MAC calculation", (u8 *) bind, bind_len);
-	hmac_sha1(cmk, 20, (u8 *) bind, bind_len, bind->compound_mac);
-	res = memcmp(cmac, bind->compound_mac, sizeof(cmac));
+		    "MAC calculation", (u8 *) _bind, bind_len);
+	hmac_sha1(cmk, 20, (u8 *) _bind, bind_len, _bind->compound_mac);
+	res = os_memcmp(cmac, _bind->compound_mac, sizeof(cmac));
 	wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Received Compound MAC",
 		    cmac, sizeof(cmac));
 	wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Calculated Compound MAC",
-		    bind->compound_mac, sizeof(cmac));
+		    _bind->compound_mac, sizeof(cmac));
 	if (res != 0) {
 		wpa_printf(MSG_INFO, "EAP-FAST: Compound MAC did not match");
 		resp = eap_fast_tlv_result(EAP_TLV_RESULT_FAILURE, 1,
 					   resp_len);
-		memcpy(bind->compound_mac, cmac, sizeof(cmac));
+		os_memcpy(_bind->compound_mac, cmac, sizeof(cmac));
 		return resp;
 	}
 
 	*resp_len = sizeof(*rresult) + sizeof(*rbind);
-	resp = malloc(*resp_len);
+	resp = os_zalloc(*resp_len);
 	if (resp == NULL)
 		return NULL;
-	memset(resp, 0, *resp_len);
 
 	/* Both intermediate and final Result TLVs are identical, so ok to use
 	 * the same structure definition for them. */
@@ -1272,7 +1334,7 @@
 	rresult->status = host_to_be16(EAP_TLV_RESULT_SUCCESS);
 
 	if (!data->provisioning && data->phase2_success &&
-	    eap_fast_derive_msk(sm, data) < 0) {
+	    eap_fast_derive_msk(data) < 0) {
 		wpa_printf(MSG_INFO, "EAP-FAST: Failed to generate MSK");
 		ret->methodState = METHOD_DONE;
 		ret->decision = DECISION_FAIL;
@@ -1286,10 +1348,10 @@
 	rbind->length = host_to_be16(sizeof(*rbind) -
 				     sizeof(struct eap_tlv_hdr));
 	rbind->version = EAP_FAST_VERSION;
-	rbind->received_version = bind->version;
+	rbind->received_version = _bind->version;
 	rbind->subtype = EAP_TLV_CRYPTO_BINDING_SUBTYPE_RESPONSE;
-	memcpy(rbind->nonce, bind->nonce, sizeof(bind->nonce));
-	inc_byte_array(rbind->nonce, sizeof(bind->nonce));
+	os_memcpy(rbind->nonce, _bind->nonce, sizeof(_bind->nonce));
+	inc_byte_array(rbind->nonce, sizeof(rbind->nonce));
 	hmac_sha1(cmk, 20, (u8 *) rbind, sizeof(*rbind), rbind->compound_mac);
 
 	wpa_printf(MSG_DEBUG, "EAP-FAST: Reply Crypto-Binding TLV: Version %d "
@@ -1322,7 +1384,7 @@
 	int type, pac_key_found = 0;
 	struct eap_fast_pac entry;
 
-	memset(&entry, 0, sizeof(entry));
+	os_memset(&entry, 0, sizeof(entry));
 	pos = pac;
 	left = pac_len;
 	while (left > sizeof(*hdr)) {
@@ -1350,7 +1412,7 @@
 				break;
 			}
 			pac_key_found = 1;
-			memcpy(entry.pac_key, pos, len);
+			os_memcpy(entry.pac_key, pos, len);
 			break;
 		case PAC_TYPE_PAC_OPAQUE:
 			wpa_hexdump(MSG_DEBUG, "EAP-FAST: PAC-Opaque",
@@ -1463,10 +1525,10 @@
 			    u8 **out_data, size_t *out_len)
 {
 	u8 *in_decrypted, *pos, *end;
-	int buf_len, len_decrypted, len;
+	int len_decrypted, len;
 	struct eap_hdr *hdr;
 	u8 *resp = NULL;
-	size_t resp_len;
+	size_t buf_len, resp_len;
 	int mandatory, tlv_type;
 	u8 *eap_payload_tlv = NULL, *pac = NULL;
 	size_t eap_payload_tlv_len = 0, pac_len = 0;
@@ -1475,7 +1537,7 @@
 	size_t crypto_binding_len = 0;
 	const u8 *msg;
 	size_t msg_len;
-	int need_more_input;
+	int need_more_input, stop;
 
 	wpa_printf(MSG_DEBUG, "EAP-FAST: received %lu bytes encrypted data for"
 		   " Phase 2", (unsigned long) in_len);
@@ -1488,9 +1550,9 @@
 	buf_len = in_len;
 	if (data->ssl.tls_in_total > buf_len)
 		buf_len = data->ssl.tls_in_total;
-	in_decrypted = malloc(buf_len);
+	in_decrypted = os_malloc(buf_len);
 	if (in_decrypted == NULL) {
-		free(data->ssl.tls_in);
+		os_free(data->ssl.tls_in);
 		data->ssl.tls_in = NULL;
 		data->ssl.tls_in_len = 0;
 		wpa_printf(MSG_WARNING, "EAP-FAST: failed to allocate memory "
@@ -1501,13 +1563,13 @@
 	len_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,
 					       msg, msg_len,
 					       in_decrypted, buf_len);
-	free(data->ssl.tls_in);
+	os_free(data->ssl.tls_in);
 	data->ssl.tls_in = NULL;
 	data->ssl.tls_in_len = 0;
 	if (len_decrypted < 0) {
 		wpa_printf(MSG_INFO, "EAP-FAST: Failed to decrypt Phase 2 "
 			   "data");
-		free(in_decrypted);
+		os_free(in_decrypted);
 		return -1;
 	}
 
@@ -1515,7 +1577,7 @@
 		    in_decrypted, len_decrypted);
 
 	if (len_decrypted < 4) {
-		free(in_decrypted);
+		os_free(in_decrypted);
 		wpa_printf(MSG_INFO, "EAP-FAST: Too short Phase 2 "
 			   "TLV frame (len=%d)", len_decrypted);
 		return -1;
@@ -1523,14 +1585,15 @@
 
 	pos = in_decrypted;
 	end = in_decrypted + len_decrypted;
-	while (pos + 4 < end) {
+	stop = 0;
+	while (pos + 4 < end && !stop) {
 		mandatory = pos[0] & 0x80;
 		tlv_type = WPA_GET_BE16(pos) & 0x3fff;
 		pos += 2;
 		len = WPA_GET_BE16(pos);
 		pos += 2;
 		if (pos + len > end) {
-			free(in_decrypted);
+			os_free(in_decrypted);
 			wpa_printf(MSG_INFO, "EAP-FAST: TLV overflow");
 			return 0;
 		}
@@ -1613,7 +1676,7 @@
 					   "mandatory TLV type %d", tlv_type);
 				resp = eap_fast_tlv_nak(0, tlv_type,
 							&resp_len);
-				pos = end;
+				stop = 1;
 			} else {
 				wpa_printf(MSG_DEBUG, "EAP-FAST: ignored "
 					   "unknown optional TLV type %d",
@@ -1629,7 +1692,7 @@
 		resp = eap_fast_tlv_result(EAP_TLV_RESULT_FAILURE, 0,
 					   &resp_len);
 		if (!resp) {
-			free(in_decrypted);
+			os_free(in_decrypted);
 			return 0;
 		}
 	}
@@ -1638,7 +1701,7 @@
 		resp = eap_fast_tlv_result(EAP_TLV_RESULT_FAILURE, 1,
 					   &resp_len);
 		if (!resp) {
-			free(in_decrypted);
+			os_free(in_decrypted);
 			return 0;
 		}
 	}
@@ -1648,31 +1711,33 @@
 			wpa_printf(MSG_DEBUG, "EAP-FAST: too short EAP "
 				   "Payload TLV (len=%lu)",
 				   (unsigned long) eap_payload_tlv_len);
-			free(in_decrypted);
+			os_free(in_decrypted);
 			return 0;
 		}
 		hdr = (struct eap_hdr *) eap_payload_tlv;
 		if (be_to_host16(hdr->length) > eap_payload_tlv_len) {
 			wpa_printf(MSG_DEBUG, "EAP-FAST: EAP packet overflow "
 				   "in EAP Payload TLV");
+			os_free(in_decrypted);
+			return 0;
 		}
 		if (hdr->code == EAP_CODE_REQUEST) {
-			if (eap_fast_phase2_request(sm, data, ret, req, hdr,
+			if (eap_fast_phase2_request(sm, data, ret, hdr,
 						    &resp, &resp_len)) {
-				free(in_decrypted);
+				os_free(in_decrypted);
 				wpa_printf(MSG_INFO, "EAP-FAST: Phase2 "
 					   "Request processing failed");
 				return 0;
 			}
 			resp = eap_fast_tlv_eap_payload(resp, &resp_len);
 			if (resp == NULL) {
-				free(in_decrypted);
+				os_free(in_decrypted);
 				return 0;
 			}
 		} else {
 			wpa_printf(MSG_INFO, "EAP-FAST: Unexpected code=%d in "
 				   "Phase 2 EAP header", hdr->code);
-			free(in_decrypted);
+			os_free(in_decrypted);
 			return 0;
 		}
 	}
@@ -1684,7 +1749,7 @@
 						       crypto_binding_len,
 						       &resp_len, final);
 		if (!resp) {
-			free(in_decrypted);
+			os_free(in_decrypted);
 			return 0;
 		}
 	}
@@ -1695,7 +1760,7 @@
 		resp = eap_fast_tlv_result(EAP_TLV_RESULT_FAILURE, 0,
 					   &resp_len);
 		if (!resp) {
-			free(in_decrypted);
+			os_free(in_decrypted);
 			return 0;
 		}
 	}
@@ -1704,17 +1769,17 @@
 		resp = eap_fast_process_pac(sm, data, ret, pac, pac_len,
 					    &resp_len);
 		if (!resp) {
-			free(in_decrypted);
+			os_free(in_decrypted);
 			return 0;
 		}
 	}
 
-	free(in_decrypted);
+	os_free(in_decrypted);
 
 	if (resp == NULL) {
 		wpa_printf(MSG_DEBUG, "EAP-FAST: No recognized TLVs - send "
 			   "empty response packet");
-		resp = malloc(1);
+		resp = os_malloc(1);
 		if (resp == NULL)
 			return 0;
 		resp_len = 0;
@@ -1727,7 +1792,7 @@
 		wpa_printf(MSG_INFO, "EAP-FAST: Failed to encrypt a Phase 2 "
 			   "frame");
 	}
-	free(resp);
+	os_free(resp);
 
 	return 0;
 }
@@ -1803,17 +1868,17 @@
 		} else if (data->current_pac) {
 			u8 *tlv;
 			size_t tlv_len, olen;
-			struct eap_tlv_hdr *hdr;
+			struct eap_tlv_hdr *ehdr;
 			olen = data->current_pac->pac_opaque_len;
-			tlv_len = sizeof(*hdr) + olen;
-			tlv = malloc(tlv_len);
+			tlv_len = sizeof(*ehdr) + olen;
+			tlv = os_malloc(tlv_len);
 			if (tlv) {
-				hdr = (struct eap_tlv_hdr *) tlv;
-				hdr->tlv_type =
+				ehdr = (struct eap_tlv_hdr *) tlv;
+				ehdr->tlv_type =
 					host_to_be16(PAC_TYPE_PAC_OPAQUE);
-				hdr->length = host_to_be16(olen);
-				memcpy(hdr + 1, data->current_pac->pac_opaque,
-				       olen);
+				ehdr->length = host_to_be16(olen);
+				os_memcpy(ehdr + 1,
+					  data->current_pac->pac_opaque, olen);
 			}
 			if (tlv == NULL ||
 			    tls_connection_client_hello_ext(
@@ -1821,11 +1886,12 @@
 				    TLS_EXT_PAC_OPAQUE, tlv, tlv_len) < 0) {
 				wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to "
 					   "add PAC-Opaque TLS extension");
-				free(tlv);
+				os_free(tlv);
 				return NULL;
 			}
-			free(tlv);
+			os_free(tlv);
 		} else {
+			u8 ciphers[2];
 			if (!data->provisioning_allowed) {
 				wpa_printf(MSG_DEBUG, "EAP-FAST: No PAC found "
 					   "and provisioning disabled");
@@ -1833,8 +1899,11 @@
 			}
 			wpa_printf(MSG_DEBUG, "EAP-FAST: No PAC found - "
 				   "starting provisioning");
-			if (tls_connection_set_anon_dh(sm->ssl_ctx,
-						       data->ssl.conn)) {
+			ciphers[0] = TLS_CIPHER_ANON_DH_AES128_SHA;
+			ciphers[1] = TLS_CIPHER_NONE;
+			if (tls_connection_set_cipher_list(sm->ssl_ctx,
+							   data->ssl.conn,
+							   ciphers)) {
 				wpa_printf(MSG_INFO, "EAP-FAST: Could not "
 					   "configure anonymous DH for TLS "
 					   "connection");
@@ -1903,6 +1972,9 @@
 
 static void eap_fast_deinit_for_reauth(struct eap_sm *sm, void *priv)
 {
+	struct eap_fast_data *data = priv;
+	os_free(data->key_block_p);
+	data->key_block_p = NULL;
 }
 
 
@@ -1910,12 +1982,16 @@
 {
 	struct eap_fast_data *data = priv;
 	if (eap_tls_reauth_init(sm, &data->ssl)) {
-		free(data);
+		os_free(data);
 		return NULL;
 	}
+	if (data->phase2_priv && data->phase2_method &&
+	    data->phase2_method->init_for_reauth)
+		data->phase2_method->init_for_reauth(sm, data->phase2_priv);
 	data->phase2_success = 0;
 	data->resuming = 1;
 	data->provisioning = 0;
+	data->simck_idx = 0;
 	return priv;
 }
 #endif
@@ -1925,7 +2001,18 @@
 			       size_t buflen, int verbose)
 {
 	struct eap_fast_data *data = priv;
-	return eap_tls_status(sm, &data->ssl, buf, buflen, verbose);
+	int len, ret;
+
+	len = eap_tls_status(sm, &data->ssl, buf, buflen, verbose);
+	if (data->phase2_method) {
+		ret = os_snprintf(buf + len, buflen - len,
+				  "EAP-FAST Phase2 method=%s\n",
+				  data->phase2_method->name);
+		if (ret < 0 || (size_t) ret >= buflen - len)
+			return len;
+		len += ret;
+	}
+	return len;
 }
 
 
@@ -1944,30 +2031,61 @@
 	if (!data->success)
 		return NULL;
 
-	key = malloc(EAP_FAST_KEY_LEN);
+	key = os_malloc(EAP_FAST_KEY_LEN);
 	if (key == NULL)
 		return NULL;
 
 	*len = EAP_FAST_KEY_LEN;
-	memcpy(key, data->key_data, EAP_FAST_KEY_LEN);
+	os_memcpy(key, data->key_data, EAP_FAST_KEY_LEN);
 
 	return key;
 }
 
 
-const struct eap_method eap_method_fast =
+static u8 * eap_fast_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
 {
-	.method = EAP_TYPE_FAST,
-	.name = "FAST",
-	.init = eap_fast_init,
-	.deinit = eap_fast_deinit,
-	.process = eap_fast_process,
-	.isKeyAvailable = eap_fast_isKeyAvailable,
-	.getKey = eap_fast_getKey,
-	.get_status = eap_fast_get_status,
+	struct eap_fast_data *data = priv;
+	u8 *key;
+
+	if (!data->success)
+		return NULL;
+
+	key = os_malloc(EAP_EMSK_LEN);
+	if (key == NULL)
+		return NULL;
+
+	*len = EAP_EMSK_LEN;
+	os_memcpy(key, data->emsk, EAP_EMSK_LEN);
+
+	return key;
+}
+
+
+int eap_peer_fast_register(void)
+{
+	struct eap_method *eap;
+	int ret;
+
+	eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
+				    EAP_VENDOR_IETF, EAP_TYPE_FAST, "FAST");
+	if (eap == NULL)
+		return -1;
+
+	eap->init = eap_fast_init;
+	eap->deinit = eap_fast_deinit;
+	eap->process = eap_fast_process;
+	eap->isKeyAvailable = eap_fast_isKeyAvailable;
+	eap->getKey = eap_fast_getKey;
+	eap->get_status = eap_fast_get_status;
 #if 0
-	.has_reauth_data = eap_fast_has_reauth_data,
-	.deinit_for_reauth = eap_fast_deinit_for_reauth,
-	.init_for_reauth = eap_fast_init_for_reauth,
+	eap->has_reauth_data = eap_fast_has_reauth_data;
+	eap->deinit_for_reauth = eap_fast_deinit_for_reauth;
+	eap->init_for_reauth = eap_fast_init_for_reauth;
 #endif
-};
+	eap->get_emsk = eap_fast_get_emsk;
+
+	ret = eap_peer_method_register(eap);
+	if (ret)
+		eap_peer_method_free(eap);
+	return ret;
+}
Index: eapol_sm.h
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/eapol_sm.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/eapol_sm.h -L contrib/wpa_supplicant/eapol_sm.h -u -r1.2 -r1.3
--- contrib/wpa_supplicant/eapol_sm.h
+++ contrib/wpa_supplicant/eapol_sm.h
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant / EAPOL state machines
- * Copyright (c) 2004-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2004-2005, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -168,6 +168,12 @@
 							  const char *name);
 
 	/**
+	 * aborted_cached - Notify that cached PMK attempt was aborted
+	 * @ctx: Callback context (ctx)
+	 */
+	void (*aborted_cached)(void *ctx);
+
+	/**
 	 * opensc_engine_path - Path to the OpenSSL engine for opensc
 	 *
 	 * This is an OpenSSL specific configuration option for loading OpenSC
@@ -224,6 +230,7 @@
 void eapol_sm_notify_ctrl_response(struct eapol_sm *sm);
 void eapol_sm_request_reauth(struct eapol_sm *sm);
 void eapol_sm_notify_lower_layer_success(struct eapol_sm *sm);
+void eapol_sm_invalidate_cached_session(struct eapol_sm *sm);
 #else /* IEEE8021X_EAPOL */
 static inline struct eapol_sm *eapol_sm_init(struct eapol_ctx *ctx)
 {
@@ -307,6 +314,9 @@
 static inline void eapol_sm_notify_lower_layer_success(struct eapol_sm *sm)
 {
 }
+static inline void eapol_sm_invalidate_cached_session(struct eapol_sm *sm)
+{
+}
 #endif /* IEEE8021X_EAPOL */
 
 #endif /* EAPOL_SM_H */
Index: wpa_ctrl.h
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/wpa_ctrl.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/wpa_ctrl.h -L contrib/wpa_supplicant/wpa_ctrl.h -u -r1.2 -r1.3
--- contrib/wpa_supplicant/wpa_ctrl.h
+++ contrib/wpa_supplicant/wpa_ctrl.h
@@ -1,6 +1,6 @@
 /*
  * wpa_supplicant/hostapd control interface library
- * Copyright (c) 2004-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2004-2006, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -147,7 +147,7 @@
 /**
  * wpa_ctrl_pending - Check whether there are pending event messages
  * @ctrl: Control interface data from wpa_ctrl_open()
- * Returns: Non-zero if there are pending messages
+ * Returns: 1 if there are pending messages, 0 if no, or -1 on error
  *
  * This function will check whether there are any pending control interface
  * message available to be received with wpa_ctrl_recv(). wpa_ctrl_pending() is
Index: tls_schannel.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/tls_schannel.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -L contrib/wpa_supplicant/tls_schannel.c -L contrib/wpa_supplicant/tls_schannel.c -u -r1.1 -r1.2
--- contrib/wpa_supplicant/tls_schannel.c
+++ contrib/wpa_supplicant/tls_schannel.c
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant / SSL/TLS interface functions for Microsoft Schannel
- * Copyright (c) 2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2005, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -20,9 +20,7 @@
  * TODO: add support for EAP-TLS (client cert/key conf)
  */
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
+#include "includes.h"
 #include <windows.h>
 #include <wincrypt.h>
 #include <schannel.h>
@@ -57,7 +55,7 @@
 {
 	INIT_SECURITY_INTERFACE pInitSecurityInterface;
 
-	global->hsecurity = LoadLibrary("Secur32.dll");
+	global->hsecurity = LoadLibrary(TEXT("Secur32.dll"));
 	if (global->hsecurity == NULL) {
 		wpa_printf(MSG_ERROR, "%s: Could not load Secur32.dll - 0x%x",
 			   __func__, (unsigned int) GetLastError());
@@ -93,12 +91,11 @@
 {
 	struct tls_global *global;
 
-	global = malloc(sizeof(*global));
+	global = os_zalloc(sizeof(*global));
 	if (global == NULL)
 		return NULL;
-	memset(global, 0, sizeof(*global));
 	if (schannel_load_lib(global)) {
-		free(global);
+		os_free(global);
 		return NULL;
 	}
 	return global;
@@ -112,7 +109,7 @@
 	if (global->my_cert_store)
 		CertCloseStore(global->my_cert_store, 0);
 	FreeLibrary(global->hsecurity);
-	free(global);
+	os_free(global);
 }
 
 
@@ -126,10 +123,9 @@
 {
 	struct tls_connection *conn;
 
-	conn = malloc(sizeof(*conn));
+	conn = os_zalloc(sizeof(*conn));
 	if (conn == NULL)
 		return NULL;
-	memset(conn, 0, sizeof(*conn));
 	conn->start = 1;
 
 	return conn;
@@ -141,7 +137,7 @@
 	if (conn == NULL)
 		return;
 
-	free(conn);
+	os_free(conn);
 }
 
 
@@ -167,7 +163,8 @@
 }
 
 
-int tls_global_ca_cert(void *_ssl_ctx, const char *ca_cert)
+int tls_global_set_params(void *tls_ctx,
+			  const struct tls_connection_params *params)
 {
 	return -1;
 }
@@ -186,27 +183,18 @@
 }
 
 
-int tls_global_client_cert(void *_ssl_ctx, const char *client_cert)
-{
-	return -1;
-}
-
-
-int tls_global_private_key(void *_ssl_ctx, const char *private_key,
-			   const char *private_key_passwd)
+int tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn,
+			    struct tls_keys *keys)
 {
+	/* Schannel does not export master secret or client/server random. */
 	return -1;
 }
 
 
-int tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn,
-			    struct tls_keys *keys)
+int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
+		       const char *label, int server_random_first,
+		       u8 *out, size_t out_len)
 {
-	if (conn == NULL || keys == NULL || !conn->eap_tls_prf_set)
-		return -1;
-
-	memset(keys, 0, sizeof(*keys));
-
 	/*
 	 * Cannot get master_key from Schannel, but EapKeyBlock can be used to
 	 * generate session keys for EAP-TLS and EAP-PEAPv0. EAP-PEAPv2 and
@@ -215,8 +203,13 @@
 	 * and just use Schannel or CryptoAPI for low-level crypto
 	 * functionality..
 	 */
-	keys->eap_tls_prf = conn->eap_tls_prf;
-	keys->eap_tls_prf_len = sizeof(conn->eap_tls_prf);
+
+	if (conn == NULL || !conn->eap_tls_prf_set || server_random_first ||
+	    os_strcmp(label, "client EAP encryption") != 0 ||
+	    out_len > sizeof(conn->eap_tls_prf))
+		return -1;
+
+	os_memcpy(out, conn->eap_tls_prf, out_len);
 
 	return 0;
 }
@@ -248,10 +241,17 @@
 	outbuf.pBuffers = outbufs;
 	outbuf.ulVersion = SECBUFFER_VERSION;
 
+#ifdef UNICODE
+	status = global->sspi->InitializeSecurityContextW(
+		&conn->creds, NULL, NULL /* server name */, sspi_flags, 0,
+		SECURITY_NATIVE_DREP, NULL, 0, &conn->context,
+		&outbuf, &sspi_flags_out, &ts_expiry);
+#else /* UNICODE */
 	status = global->sspi->InitializeSecurityContextA(
 		&conn->creds, NULL, NULL /* server name */, sspi_flags, 0,
 		SECURITY_NATIVE_DREP, NULL, 0, &conn->context,
 		&outbuf, &sspi_flags_out, &ts_expiry);
+#endif /* UNICODE */
 	if (status != SEC_I_CONTINUE_NEEDED) {
 		wpa_printf(MSG_ERROR, "%s: InitializeSecurityContextA "
 			   "failed - 0x%x",
@@ -265,10 +265,10 @@
 			    outbufs[0].pvBuffer, outbufs[0].cbBuffer);
 		conn->start = 0;
 		*out_len = outbufs[0].cbBuffer;
-		buf = malloc(*out_len);
+		buf = os_malloc(*out_len);
 		if (buf == NULL)
 			return NULL;
-		memcpy(buf, outbufs[0].pvBuffer, *out_len);
+		os_memcpy(buf, outbufs[0].pvBuffer, *out_len);
 		global->sspi->FreeContextBuffer(outbufs[0].pvBuffer);
 		return buf;
 	}
@@ -310,14 +310,16 @@
 	wpa_hexdump_key(MSG_MSGDUMP, "Schannel - EapKeyBlock - rgbIVs",
 			kb.rgbIVs, sizeof(kb.rgbIVs));
 
-	memcpy(conn->eap_tls_prf, kb.rgbKeys, sizeof(kb.rgbKeys));
+	os_memcpy(conn->eap_tls_prf, kb.rgbKeys, sizeof(kb.rgbKeys));
 	conn->eap_tls_prf_set = 1;
+	return 0;
 }
 
 
 u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
 			      const u8 *in_data, size_t in_len,
-			      size_t *out_len)
+			      size_t *out_len, u8 **appl_data,
+			      size_t *appl_data_len)
 {
 	struct tls_global *global = ssl_ctx;
 	DWORD sspi_flags, sspi_flags_out;
@@ -327,6 +329,9 @@
 	TimeStamp ts_expiry;
 	u8 *out_buf = NULL;
 
+	if (appl_data)
+		*appl_data = NULL;
+
 	if (conn->start) {
 		return tls_conn_hs_clienthello(global, conn, out_len);
 	}
@@ -363,12 +368,19 @@
 	outbuf.pBuffers = outbufs;
 	outbuf.ulVersion = SECBUFFER_VERSION;
 
+#ifdef UNICODE
+	status = global->sspi->InitializeSecurityContextW(
+		&conn->creds, &conn->context, NULL, sspi_flags, 0,
+		SECURITY_NATIVE_DREP, &inbuf, 0, NULL,
+		&outbuf, &sspi_flags_out, &ts_expiry);
+#else /* UNICODE */
 	status = global->sspi->InitializeSecurityContextA(
 		&conn->creds, &conn->context, NULL, sspi_flags, 0,
 		SECURITY_NATIVE_DREP, &inbuf, 0, NULL,
 		&outbuf, &sspi_flags_out, &ts_expiry);
+#endif /* UNICODE */
 
-	wpa_printf(MSG_MSGDUMP, "Schannel: InitializeSecurityContextA -> "
+	wpa_printf(MSG_MSGDUMP, "Schannel: InitializeSecurityContext -> "
 		   "status=%d inlen[0]=%d intype[0]=%d inlen[1]=%d "
 		   "intype[1]=%d outlen[0]=%d",
 		   (int) status, (int) inbufs[0].cbBuffer,
@@ -381,12 +393,14 @@
 			wpa_hexdump(MSG_MSGDUMP, "SChannel - output",
 				    outbufs[0].pvBuffer, outbufs[0].cbBuffer);
 			*out_len = outbufs[0].cbBuffer;
-			out_buf = malloc(*out_len);
-			if (out_buf == NULL)
-				return NULL;
-			memcpy(out_buf, outbufs[0].pvBuffer, *out_len);
+			out_buf = os_malloc(*out_len);
+			if (out_buf)
+				os_memcpy(out_buf, outbufs[0].pvBuffer,
+					  *out_len);
 			global->sspi->FreeContextBuffer(outbufs[0].pvBuffer);
 			outbufs[0].pvBuffer = NULL;
+			if (out_buf == NULL)
+				return NULL;
 		}
 	}
 
@@ -406,14 +420,20 @@
 
 		/* Need to return something to get final TLS ACK. */
 		if (out_buf == NULL)
-			out_buf = malloc(1);
+			out_buf = os_malloc(1);
 
 		if (inbufs[1].BufferType == SECBUFFER_EXTRA) {
 			wpa_hexdump(MSG_MSGDUMP, "SChannel - Encrypted "
 				    "application data",
 				    inbufs[1].pvBuffer, inbufs[1].cbBuffer);
-			/* FIX: need to fix TLS API to allow this data to be
-			 * passed to the caller */
+			if (appl_data) {
+				*appl_data_len = outbufs[1].cbBuffer;
+				appl_data = os_malloc(*appl_data_len);
+				if (appl_data)
+					os_memcpy(appl_data,
+						  outbufs[1].pvBuffer,
+						  *appl_data_len);
+			}
 			global->sspi->FreeContextBuffer(inbufs[1].pvBuffer);
 			inbufs[1].pvBuffer = NULL;
 		}
@@ -494,12 +514,12 @@
 		return -1;
 	}
 
-	memset(&bufs, 0, sizeof(bufs));
+	os_memset(&bufs, 0, sizeof(bufs));
 	bufs[0].pvBuffer = out_data;
 	bufs[0].cbBuffer = sizes.cbHeader;
 	bufs[0].BufferType = SECBUFFER_STREAM_HEADER;
 
-	memcpy(out_data + sizes.cbHeader, in_data, in_len);
+	os_memcpy(out_data + sizes.cbHeader, in_data, in_len);
 	bufs[1].pvBuffer = out_data + sizes.cbHeader;
 	bufs[1].cbBuffer = in_len;
 	bufs[1].BufferType = SECBUFFER_DATA;
@@ -565,8 +585,8 @@
 
 	wpa_hexdump(MSG_MSGDUMP, "Schannel: Encrypted data to DecryptMessage",
 		    in_data, in_len);
-	memset(&bufs, 0, sizeof(bufs));
-	memcpy(out_data, in_data, in_len);
+	os_memset(&bufs, 0, sizeof(bufs));
+	os_memcpy(out_data, in_data, in_len);
 	bufs[0].pvBuffer = out_data;
 	bufs[0].cbBuffer = in_len;
 	bufs[0].BufferType = SECBUFFER_DATA;
@@ -618,7 +638,7 @@
 				   __func__);
 			return -1;
 		}
-		memmove(out_data, bufs[i].pvBuffer, bufs[i].cbBuffer);
+		os_memmove(out_data, bufs[i].pvBuffer, bufs[i].cbBuffer);
 		return bufs[i].cbBuffer;
 	}
 
@@ -634,16 +654,15 @@
 }
 
 
-#ifdef EAP_FAST
 int tls_connection_set_master_key(void *ssl_ctx, struct tls_connection *conn,
 				  const u8 *key, size_t key_len)
 {
 	return -1;
 }
-#endif /* EAP_FAST */
 
 
-int tls_connection_set_anon_dh(void *ssl_ctx, struct tls_connection *conn)
+int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
+				   u8 *ciphers)
 {
 	return -1;
 }
@@ -663,17 +682,12 @@
 }
 
 
-#ifdef EAP_FAST
-/* ClientHello TLS extensions require a patch to openssl, so this function is
- * commented out unless explicitly needed for EAP-FAST in order to be able to
- * build this file with unmodified openssl. */
 int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn,
 				    int ext_type, const u8 *data,
 				    size_t data_len)
 {
 	return -1;
 }
-#endif /* EAP_FAST */
 
 
 int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn)
@@ -712,22 +726,29 @@
 		return -1;
 
 	if (global->my_cert_store == NULL &&
-	    (global->my_cert_store = CertOpenSystemStore(0, "MY")) == NULL) {
+	    (global->my_cert_store = CertOpenSystemStore(0, TEXT("MY"))) ==
+	    NULL) {
 		wpa_printf(MSG_ERROR, "%s: CertOpenSystemStore failed - 0x%x",
 			   __func__, (unsigned int) GetLastError());
 		return -1;
 	}
 
-	memset(&conn->schannel_cred, 0, sizeof(conn->schannel_cred));
+	os_memset(&conn->schannel_cred, 0, sizeof(conn->schannel_cred));
 	conn->schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
 	conn->schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1;
 	algs[0] = CALG_RSA_KEYX;
 	conn->schannel_cred.cSupportedAlgs = 1;
 	conn->schannel_cred.palgSupportedAlgs = algs;
 	conn->schannel_cred.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS;
+#ifdef UNICODE
+	status = global->sspi->AcquireCredentialsHandleW(
+		NULL, UNISP_NAME_W, SECPKG_CRED_OUTBOUND, NULL,
+		&conn->schannel_cred, NULL, NULL, &conn->creds, &ts_expiry);
+#else /* UNICODE */
 	status = global->sspi->AcquireCredentialsHandleA(
 		NULL, UNISP_NAME_A, SECPKG_CRED_OUTBOUND, NULL,
 		&conn->schannel_cred, NULL, NULL, &conn->creds, &ts_expiry);
+#endif /* UNICODE */
 	if (status != SEC_E_OK) {
 		wpa_printf(MSG_DEBUG, "%s: AcquireCredentialsHandleA failed - "
 			   "0x%x", __func__, (unsigned int) status);
@@ -736,3 +757,40 @@
 
 	return 0;
 }
+
+
+unsigned int tls_capabilities(void *tls_ctx)
+{
+	return 0;
+}
+
+
+int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn,
+			  int tls_ia)
+{
+	return -1;
+}
+
+
+int tls_connection_ia_send_phase_finished(void *tls_ctx,
+					  struct tls_connection *conn,
+					  int final,
+					  u8 *out_data, size_t out_len)
+{
+	return -1;
+}
+
+
+int tls_connection_ia_final_phase_finished(void *tls_ctx,
+					   struct tls_connection *conn)
+{
+	return -1;
+}
+
+
+int tls_connection_ia_permute_inner_secret(void *tls_ctx,
+					   struct tls_connection *conn,
+					   const u8 *key, size_t key_len)
+{
+	return -1;
+}
Index: eap_md5.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/eap_md5.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/eap_md5.c -L contrib/wpa_supplicant/eap_md5.c -u -r1.2 -r1.3
--- contrib/wpa_supplicant/eap_md5.c
+++ contrib/wpa_supplicant/eap_md5.c
@@ -1,6 +1,6 @@
 /*
- * WPA Supplicant / EAP-MD5
- * Copyright (c) 2004-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * EAP peer method: EAP-MD5 (RFC 3748 and RFC 1994)
+ * Copyright (c) 2004-2006, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -12,19 +12,18 @@
  * See README and COPYING for more details.
  */
 
-#include <stdlib.h>
-#include <stdio.h>
+#include "includes.h"
 
 #include "common.h"
 #include "eap_i.h"
-#include "wpa_supplicant.h"
-#include "config_ssid.h"
 #include "md5.h"
 #include "crypto.h"
 
 
 static void * eap_md5_init(struct eap_sm *sm)
 {
+	/* No need for private data. However, must return non-NULL to indicate
+	 * success. */
 	return (void *) 1;
 }
 
@@ -39,35 +38,41 @@
 			    const u8 *reqData, size_t reqDataLen,
 			    size_t *respDataLen)
 {
-	struct wpa_ssid *config = eap_get_config(sm);
 	const struct eap_hdr *req;
 	struct eap_hdr *resp;
-	const u8 *pos, *challenge;
+	const u8 *pos, *challenge, *password;
 	u8 *rpos;
-	int challenge_len;
-	size_t len;
+	size_t len, challenge_len, password_len;
 	const u8 *addr[3];
 	size_t elen[3];
 
-	if (config == NULL || config->password == NULL) {
+	password = eap_get_config_password(sm, &password_len);
+	if (password == NULL) {
 		wpa_printf(MSG_INFO, "EAP-MD5: Password not configured");
-		eap_sm_request_password(sm, config);
+		eap_sm_request_password(sm);
 		ret->ignore = TRUE;
 		return NULL;
 	}
 
-	pos = eap_hdr_validate(EAP_TYPE_MD5, reqData, reqDataLen, &len);
-	if (pos == NULL) {
+	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MD5,
+			       reqData, reqDataLen, &len);
+	if (pos == NULL || len == 0) {
+		wpa_printf(MSG_INFO, "EAP-MD5: Invalid frame (pos=%p len=%lu)",
+			   pos, (unsigned long) len);
 		ret->ignore = TRUE;
 		return NULL;
 	}
+
+	/*
+	 * CHAP Challenge:
+	 * Value-Size (1 octet) | Value(Challenge) | Name(optional)
+	 */
 	req = (const struct eap_hdr *) reqData;
 	challenge_len = *pos++;
-	if (challenge_len == 0 ||
-	    challenge_len > len - 1) {
+	if (challenge_len == 0 || challenge_len > len - 1) {
 		wpa_printf(MSG_INFO, "EAP-MD5: Invalid challenge "
-			   "(challenge_len=%d len=%lu",
-			   challenge_len, (unsigned long) len);
+			   "(challenge_len=%lu len=%lu)",
+			   (unsigned long) challenge_len, (unsigned long) len);
 		ret->ignore = TRUE;
 		return NULL;
 	}
@@ -76,26 +81,27 @@
 	wpa_hexdump(MSG_MSGDUMP, "EAP-MD5: Challenge",
 		    challenge, challenge_len);
 
-	wpa_printf(MSG_DEBUG, "EAP-MD5: generating Challenge Response");
+	wpa_printf(MSG_DEBUG, "EAP-MD5: Generating Challenge Response");
 	ret->methodState = METHOD_DONE;
 	ret->decision = DECISION_UNCOND_SUCC;
 	ret->allowNotifications = TRUE;
 
-	*respDataLen = sizeof(struct eap_hdr) + 1 + 1 + MD5_MAC_LEN;
-	resp = malloc(*respDataLen);
+	resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MD5, respDataLen,
+			     1 + MD5_MAC_LEN, EAP_CODE_RESPONSE,
+			     req->identifier, &rpos);
 	if (resp == NULL)
 		return NULL;
-	resp->code = EAP_CODE_RESPONSE;
-	resp->identifier = req->identifier;
-	resp->length = host_to_be16(*respDataLen);
-	rpos = (u8 *) (resp + 1);
-	*rpos++ = EAP_TYPE_MD5;
-	*rpos++ = MD5_MAC_LEN; /* Value-Size */
+
+	/*
+	 * CHAP Response:
+	 * Value-Size (1 octet) | Value(Response) | Name(optional)
+	 */
+	*rpos++ = MD5_MAC_LEN;
 
 	addr[0] = &resp->identifier;
 	elen[0] = 1;
-	addr[1] = config->password;
-	elen[1] = config->password_len;
+	addr[1] = password;
+	elen[1] = password_len;
 	addr[2] = challenge;
 	elen[2] = challenge_len;
 	md5_vector(3, addr, elen, rpos);
@@ -105,11 +111,22 @@
 }
 
 
-const struct eap_method eap_method_md5 =
+int eap_peer_md5_register(void)
 {
-	.method = EAP_TYPE_MD5,
-	.name = "MD5",
-	.init = eap_md5_init,
-	.deinit = eap_md5_deinit,
-	.process = eap_md5_process,
-};
+	struct eap_method *eap;
+	int ret;
+
+	eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
+				    EAP_VENDOR_IETF, EAP_TYPE_MD5, "MD5");
+	if (eap == NULL)
+		return -1;
+
+	eap->init = eap_md5_init;
+	eap->deinit = eap_md5_deinit;
+	eap->process = eap_md5_process;
+
+	ret = eap_peer_method_register(eap);
+	if (ret)
+		eap_peer_method_free(eap);
+	return ret;
+}
Index: events.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/events.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -L contrib/wpa_supplicant/events.c -L contrib/wpa_supplicant/events.c -u -r1.1 -r1.2
--- contrib/wpa_supplicant/events.c
+++ contrib/wpa_supplicant/events.c
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant - Driver event processing
- * Copyright (c) 2003-2006, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2003-2006, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -11,14 +11,10 @@
  *
  * See README and COPYING for more details.
  *
- * $FreeBSD: src/contrib/wpa_supplicant/events.c,v 1.2.2.1 2006/03/24 01:41:06 sam Exp $
+ * $FreeBSD: src/contrib/wpa_supplicant/events.c,v 1.3 2007/07/11 15:58:51 sam Exp $
  */
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <time.h>
+#include "includes.h"
 
 #include "common.h"
 #include "eapol_sm.h"
@@ -30,8 +26,10 @@
 #include "wpa_supplicant_i.h"
 #include "pcsc_funcs.h"
 #include "preauth.h"
+#include "pmksa_cache.h"
 #include "wpa_ctrl.h"
 #include "eap.h"
+#include "ctrl_iface_dbus.h"
 
 
 static int wpa_supplicant_select_config(struct wpa_supplicant *wpa_s)
@@ -65,6 +63,8 @@
 		wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
 	}
 
+	if (wpa_s->current_ssid && wpa_s->current_ssid != ssid)
+		eapol_sm_invalidate_cached_session(wpa_s->eapol);
 	wpa_s->current_ssid = ssid;
 	wpa_sm_set_config(wpa_s->wpa, wpa_s->current_ssid);
 	wpa_supplicant_initiate_eapol(wpa_s);
@@ -87,10 +87,11 @@
 }
 
 
-static void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s)
+void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s)
 {
 	wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
-	memset(wpa_s->bssid, 0, ETH_ALEN);
+	os_memset(wpa_s->bssid, 0, ETH_ALEN);
+	os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
 	eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
 	eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
 	if (wpa_s->key_mgmt == WPA_KEY_MGMT_PSK)
@@ -147,6 +148,7 @@
 	    wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE)
 		return 0;
 
+#ifdef IEEE8021X_EAPOL
 	if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
 	    wpa_s->current_ssid &&
 	    !(wpa_s->current_ssid->eapol_flags &
@@ -156,6 +158,7 @@
 		 * plaintext or static WEP keys). */
 		return 0;
 	}
+#endif /* IEEE8021X_EAPOL */
 
 	return 1;
 }
@@ -173,6 +176,7 @@
 int wpa_supplicant_scard_init(struct wpa_supplicant *wpa_s,
 			      struct wpa_ssid *ssid)
 {
+#ifdef IEEE8021X_EAPOL
 	int aka = 0, sim = 0, type;
 
 	if (ssid->pcsc == NULL || wpa_s->scard != NULL)
@@ -182,22 +186,23 @@
 		sim = 1;
 		aka = 1;
 	} else {
-		u8 *eap = ssid->eap_methods;
-		while (*eap != EAP_TYPE_NONE) {
-			if (*eap == EAP_TYPE_SIM)
-				sim = 1;
-			else if (*eap == EAP_TYPE_AKA)
-				aka = 1;
+		struct eap_method_type *eap = ssid->eap_methods;
+		while (eap->vendor != EAP_VENDOR_IETF ||
+		       eap->method != EAP_TYPE_NONE) {
+			if (eap->vendor == EAP_VENDOR_IETF) {
+				if (eap->method == EAP_TYPE_SIM)
+					sim = 1;
+				else if (eap->method == EAP_TYPE_AKA)
+					aka = 1;
+			}
 			eap++;
 		}
 	}
 
-#ifndef EAP_SIM
-	sim = 0;
-#endif /* EAP_SIM */
-#ifndef EAP_AKA
-	aka = 0;
-#endif /* EAP_AKA */
+	if (eap_sm_get_eap_methods(EAP_VENDOR_IETF, EAP_TYPE_SIM) == NULL)
+		sim = 0;
+	if (eap_sm_get_eap_methods(EAP_VENDOR_IETF, EAP_TYPE_AKA) == NULL)
+		aka = 0;
 
 	if (!sim && !aka) {
 		wpa_printf(MSG_DEBUG, "Selected network is configured to use "
@@ -222,6 +227,7 @@
 	}
 	wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
 	eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
+#endif /* IEEE8021X_EAPOL */
 
 	return 0;
 }
@@ -232,16 +238,21 @@
 {
 	int i, privacy = 0;
 
+	if (ssid->mixed_cell)
+		return 1;
+
 	for (i = 0; i < NUM_WEP_KEYS; i++) {
 		if (ssid->wep_key_len[i]) {
 			privacy = 1;
 			break;
 		}
 	}
+#ifdef IEEE8021X_EAPOL
 	if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) &&
 	    ssid->eapol_flags & (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
 				 EAPOL_FLAG_REQUIRE_KEY_BROADCAST))
 		privacy = 1;
+#endif /* IEEE8021X_EAPOL */
 
 	if (bss->caps & IEEE80211_CAP_PRIVACY)
 		return privacy;
@@ -286,6 +297,15 @@
 			break;
 		}
 
+#ifdef CONFIG_IEEE80211W
+		if (!(ie.capabilities & WPA_CAPABILITY_MGMT_FRAME_PROTECTION)
+		    && ssid->ieee80211w == IEEE80211W_REQUIRED) {
+			wpa_printf(MSG_DEBUG, "   skip RSN IE - no mgmt frame "
+				   "protection");
+			break;
+		}
+#endif /* CONFIG_IEEE80211W */
+
 		wpa_printf(MSG_DEBUG, "   selected based on RSN IE");
 		return 1;
 	}
@@ -348,6 +368,7 @@
 	bss = NULL;
 	ssid = NULL;
 	/* First, try to find WPA-enabled AP */
+	wpa_printf(MSG_DEBUG, "Try to find WPA-enabled AP");
 	for (i = 0; i < num && !selected; i++) {
 		bss = &results[i];
 		wpa_printf(MSG_DEBUG, "%d: " MACSTR " ssid='%s' "
@@ -356,8 +377,8 @@
 			   wpa_ssid_txt(bss->ssid, bss->ssid_len),
 			   (unsigned long) bss->wpa_ie_len,
 			   (unsigned long) bss->rsn_ie_len, bss->caps);
-		if ((e = wpa_blacklist_get(wpa_s, bss->bssid)) &&
-		    e->count > 1) {
+		e = wpa_blacklist_get(wpa_s, bss->bssid);
+		if (e && e->count > 1) {
 			wpa_printf(MSG_DEBUG, "   skip - blacklisted");
 			continue;
 		}
@@ -368,17 +389,20 @@
 		}
 
 		for (ssid = group; ssid; ssid = ssid->pnext) {
-			if (ssid->disabled)
+			if (ssid->disabled) {
+				wpa_printf(MSG_DEBUG, "   skip - disabled");
 				continue;
+			}
 			if (bss->ssid_len != ssid->ssid_len ||
-			    memcmp(bss->ssid, ssid->ssid,
-				   bss->ssid_len) != 0) {
+			    os_memcmp(bss->ssid, ssid->ssid,
+				      bss->ssid_len) != 0) {
 				wpa_printf(MSG_DEBUG, "   skip - "
 					   "SSID mismatch");
 				continue;
 			}
 			if (ssid->bssid_set &&
-			    memcmp(bss->bssid, ssid->bssid, ETH_ALEN) != 0) {
+			    os_memcmp(bss->bssid, ssid->bssid, ETH_ALEN) != 0)
+			{
 				wpa_printf(MSG_DEBUG, "   skip - "
 					   "BSSID mismatch");
 				continue;
@@ -386,6 +410,11 @@
 			if (wpa_supplicant_ssid_bss_match(ssid, bss)) {
 				selected = bss;
 				*selected_ssid = ssid;
+				wpa_printf(MSG_DEBUG, "   selected WPA AP "
+					   MACSTR " ssid='%s'",
+					   MAC2STR(bss->bssid),
+					   wpa_ssid_txt(bss->ssid,
+							bss->ssid_len));
 				break;
 			}
 		}
@@ -393,35 +422,76 @@
 
 	/* If no WPA-enabled AP found, try to find non-WPA AP, if configuration
 	 * allows this. */
+	wpa_printf(MSG_DEBUG, "Try to find non-WPA AP");
 	for (i = 0; i < num && !selected; i++) {
 		bss = &results[i];
-		if ((e = wpa_blacklist_get(wpa_s, bss->bssid)) &&
-		    e->count > 1) {
+		wpa_printf(MSG_DEBUG, "%d: " MACSTR " ssid='%s' "
+			   "wpa_ie_len=%lu rsn_ie_len=%lu caps=0x%x",
+			   i, MAC2STR(bss->bssid),
+			   wpa_ssid_txt(bss->ssid, bss->ssid_len),
+			   (unsigned long) bss->wpa_ie_len,
+			   (unsigned long) bss->rsn_ie_len, bss->caps);
+		e = wpa_blacklist_get(wpa_s, bss->bssid);
+		if (e && e->count > 1) {
+			wpa_printf(MSG_DEBUG, "   skip - blacklisted");
 			continue;
 		}
 		for (ssid = group; ssid; ssid = ssid->pnext) {
-			if (!ssid->disabled &&
-			    (ssid->ssid_len == 0 ||
-			     (bss->ssid_len == ssid->ssid_len &&
-			      memcmp(bss->ssid, ssid->ssid, bss->ssid_len) ==
-			      0)) &&
-			    (!ssid->bssid_set ||
-			     memcmp(bss->bssid, ssid->bssid, ETH_ALEN) == 0) &&
-			    ((ssid->key_mgmt & WPA_KEY_MGMT_NONE) ||
-			     (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA))
-			    && bss->wpa_ie_len == 0 && bss->rsn_ie_len == 0 &&
-			    wpa_supplicant_match_privacy(bss, ssid) &&
-			    !(bss->caps & IEEE80211_CAP_IBSS))
+			if (ssid->disabled) {
+				wpa_printf(MSG_DEBUG, "   skip - disabled");
+				continue;
+			}
+			if (bss->ssid_len != ssid->ssid_len ||
+			    os_memcmp(bss->ssid, ssid->ssid,
+				      bss->ssid_len) != 0) {
+				wpa_printf(MSG_DEBUG, "   skip - "
+					   "SSID mismatch");
+				continue;
+			}
+
+			if (ssid->bssid_set &&
+			    os_memcmp(bss->bssid, ssid->bssid, ETH_ALEN) != 0)
 			{
-				selected = bss;
-				*selected_ssid = ssid;
-				wpa_printf(MSG_DEBUG, "   selected non-WPA AP "
-					   MACSTR " ssid='%s'",
-					   MAC2STR(bss->bssid),
-					   wpa_ssid_txt(bss->ssid,
-							bss->ssid_len));
-				break;
+				wpa_printf(MSG_DEBUG, "   skip - "
+					   "BSSID mismatch");
+				continue;
+			}
+			
+			if (!(ssid->key_mgmt & WPA_KEY_MGMT_NONE) &&
+			    !(ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA))
+			{
+				wpa_printf(MSG_DEBUG, "   skip - "
+					   "non-WPA network not allowed");
+				continue;
 			}
+
+			if ((ssid->key_mgmt & 
+			     (WPA_KEY_MGMT_IEEE8021X | WPA_KEY_MGMT_PSK)) ||
+			    bss->wpa_ie_len != 0 || bss->rsn_ie_len != 0) {
+				wpa_printf(MSG_DEBUG, "   skip - "
+					   "WPA network");
+				continue;
+			}
+
+			if (!wpa_supplicant_match_privacy(bss, ssid)) {
+				wpa_printf(MSG_DEBUG, "   skip - "
+					   "privacy mismatch");
+				continue;
+			}
+
+			if (bss->caps & IEEE80211_CAP_IBSS) {
+				wpa_printf(MSG_DEBUG, "   skip - "
+					   "IBSS (adhoc) network");
+				continue;
+			}
+
+			selected = bss;
+			*selected_ssid = ssid;
+			wpa_printf(MSG_DEBUG, "   selected non-WPA AP "
+				   MACSTR " ssid='%s'",
+				   MAC2STR(bss->bssid),
+				   wpa_ssid_txt(bss->ssid, bss->ssid_len));
+			break;
 		}
 	}
 
@@ -431,7 +501,7 @@
 
 static void wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s)
 {
-	int num, prio;
+	int num, prio, timeout;
 	struct wpa_scan_result *selected = NULL;
 	struct wpa_ssid *ssid = NULL;
 	struct wpa_scan_result *results;
@@ -441,9 +511,12 @@
 			return;
 		wpa_printf(MSG_DEBUG, "Failed to get scan results - try "
 			   "scanning again");
-		wpa_supplicant_req_scan(wpa_s, 1, 0);
-		return;
+		timeout = 1;
+		goto req_scan;
 	}
+
+	wpa_supplicant_dbus_notify_scan_results(wpa_s);
+
 	if (wpa_s->conf->ap_scan == 2)
 		return;
 	results = wpa_s->scan_results;
@@ -468,8 +541,15 @@
 	}
 
 	if (selected) {
+		/* Do not trigger new association unless the BSSID has changed
+		 * or if reassociation is requested. If we are in process of
+		 * associating with the selected BSSID, do not trigger new
+		 * attempt. */
 		if (wpa_s->reassociate ||
-		    memcmp(selected->bssid, wpa_s->bssid, ETH_ALEN) != 0) {
+		    (os_memcmp(selected->bssid, wpa_s->bssid, ETH_ALEN) != 0 &&
+		     (wpa_s->wpa_state != WPA_ASSOCIATING ||
+		      os_memcmp(selected->bssid, wpa_s->pending_bssid,
+				ETH_ALEN) != 0))) {
 			if (wpa_supplicant_scard_init(wpa_s, ssid)) {
 				wpa_supplicant_req_scan(wpa_s, 10, 0);
 				return;
@@ -482,8 +562,22 @@
 		rsn_preauth_scan_results(wpa_s->wpa, results, num);
 	} else {
 		wpa_printf(MSG_DEBUG, "No suitable AP found.");
-		wpa_supplicant_req_scan(wpa_s, 5, 0);
+		timeout = 5;
+		goto req_scan;
 	}
+
+	return;
+
+req_scan:
+	if (wpa_s->scan_res_tried == 1 && wpa_s->conf->ap_scan == 1) {
+		/*
+		 * Quick recovery if the initial scan results were not
+		 * complete when fetched before the first scan request.
+		 */
+		wpa_s->scan_res_tried++;
+		timeout = 0;
+	}
+	wpa_supplicant_req_scan(wpa_s, timeout, 0);
 }
 
 
@@ -517,7 +611,7 @@
 			break;
 		}
 		if ((p[0] == GENERIC_INFO_ELEM && p[1] >= 6 &&
-		     (memcmp(&p[2], "\x00\x50\xF2\x01\x01\x00", 6) == 0)) ||
+		     (os_memcmp(&p[2], "\x00\x50\xF2\x01\x01\x00", 6) == 0)) ||
 		    (p[0] == RSN_INFO_ELEM && p[1] >= 2)) {
 			if (wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, p, len))
 				break;
@@ -547,7 +641,7 @@
 		}
 		if (!wpa_found &&
 		    p[0] == GENERIC_INFO_ELEM && p[1] >= 6 &&
-		    memcmp(&p[2], "\x00\x50\xF2\x01\x01\x00", 6) == 0) {
+		    os_memcmp(&p[2], "\x00\x50\xF2\x01\x01\x00", 6) == 0) {
 			wpa_found = 1;
 			wpa_sm_set_ap_wpa_ie(wpa_s->wpa, p, len);
 		}
@@ -578,11 +672,15 @@
 		wpa_supplicant_event_associnfo(wpa_s, data);
 
 	wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATED);
-	if (wpa_drv_get_bssid(wpa_s, bssid) >= 0 &&
-	    memcmp(bssid, wpa_s->bssid, ETH_ALEN) != 0) {
+	if (wpa_s->use_client_mlme)
+		os_memcpy(bssid, wpa_s->bssid, ETH_ALEN);
+	if (wpa_s->use_client_mlme ||
+	    (wpa_drv_get_bssid(wpa_s, bssid) >= 0 &&
+	     os_memcmp(bssid, wpa_s->bssid, ETH_ALEN) != 0)) {
 		wpa_msg(wpa_s, MSG_DEBUG, "Associated to a new BSS: BSSID="
 			MACSTR, MAC2STR(bssid));
-		memcpy(wpa_s->bssid, bssid, ETH_ALEN);
+		os_memcpy(wpa_s->bssid, bssid, ETH_ALEN);
+		os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
 		if (wpa_supplicant_dynamic_keys(wpa_s)) {
 			wpa_clear_keys(wpa_s, bssid);
 		}
@@ -627,11 +725,14 @@
 		/* Timeout for receiving the first EAPOL packet */
 		wpa_supplicant_req_auth_timeout(wpa_s, 10, 0);
 	}
+	wpa_supplicant_cancel_scan(wpa_s);
 }
 
 
 static void wpa_supplicant_event_disassoc(struct wpa_supplicant *wpa_s)
 {
+	const u8 *bssid;
+
 	if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
 		/*
 		 * At least Host AP driver and a Prism3 card seemed to be
@@ -650,15 +751,18 @@
 	}
 	if (wpa_s->wpa_state >= WPA_ASSOCIATED)
 		wpa_supplicant_req_scan(wpa_s, 0, 100000);
-	wpa_blacklist_add(wpa_s, wpa_s->bssid);
+	bssid = wpa_s->bssid;
+	if (os_memcmp(bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) == 0)
+		bssid = wpa_s->pending_bssid;
+	wpa_blacklist_add(wpa_s, bssid);
 	wpa_sm_notify_disassoc(wpa_s->wpa);
-	wpa_supplicant_mark_disassoc(wpa_s);
 	wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "- Disconnect event - "
 		"remove keys");
 	if (wpa_supplicant_dynamic_keys(wpa_s)) {
 		wpa_s->keys_cleared = 0;
 		wpa_clear_keys(wpa_s, wpa_s->bssid);
 	}
+	wpa_supplicant_mark_disassoc(wpa_s);
 }
 
 
@@ -667,14 +771,14 @@
 					 union wpa_event_data *data)
 {
 	int pairwise;
-	time_t now;
+	struct os_time t;
 
 	wpa_msg(wpa_s, MSG_WARNING, "Michael MIC failure detected");
 	pairwise = (data && data->michael_mic_failure.unicast);
 	wpa_sm_key_request(wpa_s->wpa, 1, pairwise);
-	time(&now);
+	os_get_time(&t);
 	if (wpa_s->last_michael_mic_error &&
-	    now - wpa_s->last_michael_mic_error <= 60) {
+	    t.sec - wpa_s->last_michael_mic_error <= 60) {
 		/* initialize countermeasures */
 		wpa_s->countermeasures = 1;
 		wpa_msg(wpa_s, MSG_WARNING, "TKIP countermeasures started");
@@ -683,7 +787,7 @@
 		 * Need to wait for completion of request frame. We do not get
 		 * any callback for the message completion, so just wait a
 		 * short while and hope for the best. */
-		usleep(10000);
+		os_sleep(0, 10000);
 
 		wpa_drv_set_countermeasures(wpa_s, 1);
 		wpa_supplicant_deauthenticate(wpa_s,
@@ -696,10 +800,11 @@
 		/* TODO: mark the AP rejected for 60 second. STA is
 		 * allowed to associate with another AP.. */
 	}
-	wpa_s->last_michael_mic_error = now;
+	wpa_s->last_michael_mic_error = t.sec;
 }
 
 
+#ifdef CONFIG_TERMINATE_ONLASTIF
 static int any_interfaces(struct wpa_supplicant *head)
 {
 	struct wpa_supplicant *wpa_s;
@@ -709,12 +814,13 @@
 			return 1;
 	return 0;
 }
+#endif /* CONFIG_TERMINATE_ONLASTIF */
 
 static void
 wpa_supplicant_event_interface_status(struct wpa_supplicant *wpa_s,
 				      union wpa_event_data *data)
 {
-	if (strcmp(wpa_s->ifname, data->interface_status.ifname) != 0)
+	if (os_strcmp(wpa_s->ifname, data->interface_status.ifname) != 0)
 		return;
 
 	switch (data->interface_status.ievent) {
@@ -734,14 +840,28 @@
 		wpa_supplicant_mark_disassoc(wpa_s);
 		l2_packet_deinit(wpa_s->l2);
 		wpa_s->l2 = NULL;
+#ifdef CONFIG_TERMINATE_ONLASTIF
 		/* check if last interface */
 		if (!any_interfaces(wpa_s->global->ifaces))
 			eloop_terminate();
+#endif /* CONFIG_TERMINATE_ONLASTIF */
 		break;
 	}
 }
 
 
+#ifdef CONFIG_PEERKEY
+static void
+wpa_supplicant_event_stkstart(struct wpa_supplicant *wpa_s,
+			      union wpa_event_data *data)
+{
+	if (data == NULL)
+		return;
+	wpa_sm_stkstart(wpa_s->wpa, data->stkstart.peer);
+}
+#endif /* CONFIG_PEERKEY */
+
+
 void wpa_supplicant_event(struct wpa_supplicant *wpa_s, wpa_event_type event,
 			  union wpa_event_data *data)
 {
@@ -767,6 +887,11 @@
 	case EVENT_PMKID_CANDIDATE:
 		wpa_supplicant_event_pmkid_candidate(wpa_s, data);
 		break;
+#ifdef CONFIG_PEERKEY
+	case EVENT_STKSTART:
+		wpa_supplicant_event_stkstart(wpa_s, data);
+		break;
+#endif /* CONFIG_PEERKEY */
 	default:
 		wpa_printf(MSG_INFO, "Unknown event %d", event);
 		break;
Index: eap_psk_common.h
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/eap_psk_common.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -L contrib/wpa_supplicant/eap_psk_common.h -L contrib/wpa_supplicant/eap_psk_common.h -u -r1.1 -r1.2
--- contrib/wpa_supplicant/eap_psk_common.h
+++ contrib/wpa_supplicant/eap_psk_common.h
@@ -1,6 +1,6 @@
 /*
- * WPA Supplicant / EAP-PSK shared routines
- * Copyright (c) 2004-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * EAP server/peer: EAP-PSK shared routines
+ * Copyright (c) 2004-2006, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -19,7 +19,6 @@
 #define EAP_PSK_RAND_LEN 16
 #define EAP_PSK_MAC_LEN 16
 #define EAP_PSK_TEK_LEN 16
-#define EAP_PSK_MSK_LEN 64
 #define EAP_PSK_PSK_LEN 16
 #define EAP_PSK_AK_LEN 16
 #define EAP_PSK_KDK_LEN 16
@@ -29,6 +28,13 @@
 #define EAP_PSK_R_FLAG_DONE_FAILURE 3
 #define EAP_PSK_E_FLAG 0x20
 
+#define EAP_PSK_FLAGS_GET_T(flags) (((flags) & 0xc0) >> 6)
+#define EAP_PSK_FLAGS_SET_T(t) ((u8) (t) << 6)
+
+#ifdef _MSC_VER
+#pragma pack(push, 1)
+#endif /* _MSC_VER */
+
 /* Shared prefix for all EAP-PSK frames */
 struct eap_psk_hdr {
 	u8 code;
@@ -36,7 +42,7 @@
 	u16 length; /* including code, identifier, and length */
 	u8 type; /* EAP_TYPE_PSK */
 	u8 flags;
-} __attribute__ ((packed));
+} STRUCT_PACKED;
 
 /* EAP-PSK First Message (AS -> Supplicant) */
 struct eap_psk_hdr_1 {
@@ -47,7 +53,7 @@
 	u8 flags;
 	u8 rand_s[EAP_PSK_RAND_LEN];
 	/* Followed by variable length ID_S */
-} __attribute__ ((packed));
+} STRUCT_PACKED;
 
 /* EAP-PSK Second Message (Supplicant -> AS) */
 struct eap_psk_hdr_2 {
@@ -60,7 +66,7 @@
 	u8 rand_p[EAP_PSK_RAND_LEN];
 	u8 mac_p[EAP_PSK_MAC_LEN];
 	/* Followed by variable length ID_P */
-} __attribute__ ((packed));
+} STRUCT_PACKED;
 
 /* EAP-PSK Third Message (AS -> Supplicant) */
 struct eap_psk_hdr_3 {
@@ -72,7 +78,7 @@
 	u8 rand_s[EAP_PSK_RAND_LEN];
 	u8 mac_s[EAP_PSK_MAC_LEN];
 	/* Followed by variable length PCHANNEL */
-} __attribute__ ((packed));
+} STRUCT_PACKED;
 
 /* EAP-PSK Fourth Message (Supplicant -> AS) */
 struct eap_psk_hdr_4 {
@@ -83,10 +89,15 @@
 	u8 flags;
 	u8 rand_s[EAP_PSK_RAND_LEN];
 	/* Followed by variable length PCHANNEL */
-} __attribute__ ((packed));
+} STRUCT_PACKED;
+
+#ifdef _MSC_VER
+#pragma pack(pop)
+#endif /* _MSC_VER */
 
 
 void eap_psk_key_setup(const u8 *psk, u8 *ak, u8 *kdk);
-void eap_psk_derive_keys(const u8 *kdk, const u8 *rand_p, u8 *tek, u8 *msk);
+void eap_psk_derive_keys(const u8 *kdk, const u8 *rand_p, u8 *tek, u8 *msk,
+			 u8 *emsk);
 
 #endif /* EAP_PSK_COMMON_H */
Index: README
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/README,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/README -L contrib/wpa_supplicant/README -u -r1.2 -r1.3
--- contrib/wpa_supplicant/README
+++ contrib/wpa_supplicant/README
@@ -1,8 +1,7 @@
 WPA Supplicant
 ==============
 
-Copyright (c) 2003-2006, Jouni Malinen <jkmaline at cc.hut.fi> and
-contributors
+Copyright (c) 2003-2007, Jouni Malinen <j at w1.fi> and contributors
 All Rights Reserved.
 
 This program is dual-licensed under both the GPL version 2 and BSD
@@ -26,13 +25,13 @@
 
 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
 (this copy of the license is in COPYING file)
 
 
-Alternatively, this software may be distributed under the terms of BSD
-license:
+Alternatively, this software may be distributed, used, and modified
+under the terms of BSD license:
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are
@@ -90,6 +89,8 @@
   * EAP-AKA
   * EAP-PSK
   * EAP-PAX
+  * EAP-SAKE
+  * EAP-GPSK
   * LEAP (note: requires special support from the driver for IEEE 802.11
 	  authentication)
   (following methods are supported, but since they do not generate keying
@@ -103,6 +104,20 @@
   * pre-authentication
   * PMKSA caching
 
+Supported TLS/crypto libraries:
+- OpenSSL (default)
+- GnuTLS
+
+Internal TLS/crypto implementation (optional):
+- can be used in place of an external TLS/crypto library
+- TLSv1
+- X.509 certificate processing
+- PKCS #1
+- ASN.1
+- RSA
+- bignum
+- minimal size (ca. 50 kB binary, parts of which are already needed for WPA;
+  TLSv1/X.509/ASN.1/RSA/bignum parts are about 25 kB on x86)
 
 
 Requirements
@@ -114,6 +129,14 @@
 - NetBSD-current
 - Microsoft Windows with WinPcap (at least WinXP, may work with other versions)
 - drivers:
+	Linux drivers that support WPA/WPA2 configuration with the generic
+	Linux wireless extensions (WE-18 or newer). Even though there are
+	number of driver specific interface included in wpa_supplicant, please
+	note that Linux drivers are moving to use generic wireless extensions
+	and driver_wext (-Dwext on wpa_supplicant command line) should be the
+	default option to start with before falling back to driver specific
+	interface.
+
 	Host AP driver for Prism2/2.5/3 (development snapshot/v0.2.x)
 	(http://hostap.epitest.fi/)
 	Driver need to be set in Managed mode ('iwconfig wlan0 mode managed').
@@ -191,18 +214,27 @@
 
 These libraries are _not_ used in the default Linux build. Instead,
 internal Linux specific implementation is used. libpcap/libdnet are
-more portable and they can be used by adding CONFIG_DNET_PCAP=y into
+more portable and they can be used by adding CONFIG_L2_PACKET=pcap into
 .config. They may also be selected automatically for other operating
-systems.
+systems. In case of Windows builds, WinPcap is used by default
+(CONFIG_L2_PACKET=winpcap).
 
 
 Optional libraries for EAP-TLS, EAP-PEAP, and EAP-TTLS:
-- openssl (tested with 0.9.7c and 0.9.7d, assumed to work with most
-  relatively recent versions; this is likely to be available with most
-  distributions, http://www.openssl.org/)
+- OpenSSL (tested with 0.9.7c and 0.9.7d, and 0.9.8 versions; assumed to
+  work with most relatively recent versions; this is likely to be
+  available with most distributions, http://www.openssl.org/)
+- GnuTLS
+- internal TLSv1 implementation
+
+TLS options for EAP-FAST:
+- OpenSSL 0.9.8d _with_ openssl-0.9.8d-tls-extensions.patch applied
+  (i.e., the default OpenSSL package does not include support for
+  extensions needed for EAP-FAST)
+- internal TLSv1 implementation
 
-This library is only needed when EAP-TLS, EAP-PEAP, or EAP-TTLS
-support is enabled. WPA-PSK mode does not require this or EAPOL/EAP
+One of these libraries is needed when EAP-TLS, EAP-PEAP, EAP-TTLS, or
+EAP-FAST support is enabled. WPA-PSK mode does not require this or EAPOL/EAP
 implementation. A configuration file, .config, for compilation is
 needed to enable IEEE 802.1X/EAPOL and EAP methods. Note that EAP-MD5,
 EAP-GTC, EAP-OTP, and EAP-MSCHAPV2 cannot be used alone with WPA, so
@@ -321,8 +353,8 @@
 build time configuration file, .config, in the wpa_supplicant root
 directory. Configuration options are text lines using following
 format: CONFIG_<option>=y. Lines starting with # are considered
-comments and are ignored. See defconfig file for example configuration
-and list of available option.
+comments and are ignored. See defconfig file for an example configuration
+and a list of available options and additional notes.
 
 The build time configuration can be used to select only the needed
 features and limit the binary size and requirements for external
@@ -332,8 +364,9 @@
 
 Following build time configuration options are used to control IEEE
 802.1X/EAPOL and EAP state machines and all EAP methods. Including
-TLS, PEAP, or TTLS will require linking wpa_supplicant with openssl
-library for TLS implementation.
+TLS, PEAP, or TTLS will require linking wpa_supplicant with OpenSSL
+library for TLS implementation. Alternatively, GnuTLS or the internal
+TLSv1 implementation can be used for TLS functionaly.
 
 CONFIG_IEEE8021X_EAPOL=y
 CONFIG_EAP_MD5=y
@@ -346,6 +379,8 @@
 CONFIG_EAP_SIM=y
 CONFIG_EAP_AKA=y
 CONFIG_EAP_PSK=y
+CONFIG_EAP_SAKE=y
+CONFIG_EAP_GPSK=y
 CONFIG_EAP_PAX=y
 CONFIG_EAP_LEAP=y
 
@@ -355,11 +390,6 @@
 
 CONFIG_PCSC=y
 
-Following option can be used to replace the native Linux packet socket
-interface with libpcap/libdnet.
-
-CONFIG_DNET_PCAP=y
-
 Following options can be added to .config to select which driver
 interfaces are included. Hermes driver interface needs to be downloaded
 from Agere (see above). CONFIG_WIRELESS_EXTENSION will be used
@@ -402,6 +432,8 @@
 CONFIG_EAP_SIM=y
 CONFIG_EAP_AKA=y
 CONFIG_EAP_PSK=y
+CONFIG_EAP_SAKE=y
+CONFIG_EAP_GPSK=y
 CONFIG_EAP_PAX=y
 CONFIG_EAP_LEAP=y
 CONFIG_PCSC=y
@@ -449,19 +481,30 @@
 --------------------
 
 usage:
-  wpa_supplicant [-BddehLqqvw] -i<ifname> -c<config file> [-D<driver>] \
-      [-N -i<ifname> -c<conf> [-D<driver>] ...]
+  wpa_supplicant [-BddehLqqvwW] [-P<pid file>] [-g<global ctrl>] \
+        -i<ifname> -c<config file> [-C<ctrl>] [-D<driver>] [-p<driver_param>] \
+        [-b<br_ifname> [-N -i<ifname> -c<conf> [-C<ctrl>] [-D<driver>] \
+        [-p<driver_param>] [-b<br_ifname>] ...]
 
 options:
+  -b = optional bridge interface name
   -B = run daemon in the background
+  -c = Configuration file
+  -C = ctrl_interface parameter (only used if -c is not)
+  -i = interface name
   -d = increase debugging verbosity (-dd even more)
+  -D = driver name
+  -g = global ctrl_interface
   -K = include keys (passwords, etc.) in debug output
   -t = include timestamp in debug messages
   -h = show this help text
   -L = show license (GPL and BSD)
+  -p = driver parameters
+  -P = PID file
   -q = decrease debugging verbosity (-qq even less)
   -v = show version
   -w = wait for interface to be added, if needed
+  -W = wait for a control interface monitor before starting
   -N = start describing new interface
 
 drivers:
@@ -473,7 +516,7 @@
   wext = Linux wireless extensions (generic)
   ndiswrapper = Linux ndiswrapper
   broadcom = Broadcom wl.o driver
-  ipw = Intel ipw2100/2200 driver
+  ipw = Intel ipw2100/2200 driver (old; use wext with Linux 2.6.13 or newer)
   wired = wpa_supplicant wired Ethernet driver
   bsd = BSD 802.11 support (Atheros, etc.)
   ndis = Windows NDIS driver
@@ -503,6 +546,13 @@
 	-c wpa2.conf -i ath0 -D madwifi
 
 
+If the interface is added in a Linux bridge (e.g., br0), the bridge
+interface needs to be configured to wpa_supplicant in addition to the
+main interface:
+
+wpa_supplicant -cw.conf -Dmadwifi -iath0 -bbr0
+
+
 Configuration file
 ------------------
 
@@ -518,7 +568,7 @@
 Configuration file can include one or more network blocks, e.g., one
 for each used SSID. wpa_supplicant will automatically select the best
 betwork based on the order of network blocks in the configuration
-file, network security level (WPA/WPA2 is prefered), and signal
+file, network security level (WPA/WPA2 is preferred), and signal
 strength.
 
 Example configuration files for some common configurations:
Index: FREEBSD-Xlist
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/FREEBSD-Xlist,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/FREEBSD-Xlist -L contrib/wpa_supplicant/FREEBSD-Xlist -u -r1.2 -r1.3
--- contrib/wpa_supplicant/FREEBSD-Xlist
+++ contrib/wpa_supplicant/FREEBSD-Xlist
@@ -1,4 +1,4 @@
-$FreeBSD: src/contrib/wpa_supplicant/FREEBSD-Xlist,v 1.1.2.1 2006/03/24 01:41:06 sam Exp $
+$FreeBSD: src/contrib/wpa_supplicant/FREEBSD-Xlist,v 1.4 2007/07/11 15:59:42 sam Exp $
 .cvsignore
 README-Windows.txt
 driver_atmel.c
@@ -8,14 +8,26 @@
 driver_ipw.c
 driver_madwifi.c
 driver_ndiswrapper.c
+driver_ndis_.c
 driver_prism54.c
 driver_test.c
 driver_wext.c
 driver_wext.h
 l2_packet_freebsd.c
 l2_packet_linux.c
+l2_packet_ndis.c
+l2_packet_none.c
 l2_packet_pcap.c
+l2_packet_winpcap.c
+main_none.c
+main_winmain.c
+main_winsvc.c
+ndis_events.c
 ndis_events.cpp
+nmake.mk
+os_win32.c
 priv_netlink.h
+vs2005
+win_example.reg
 win_if_list.c
 wireless_copy.h
Index: tls_none.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/tls_none.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/tls_none.c -L contrib/wpa_supplicant/tls_none.c -u -r1.2 -r1.3
--- contrib/wpa_supplicant/tls_none.c
+++ contrib/wpa_supplicant/tls_none.c
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant / SSL/TLS interface functions for no TLS case
- * Copyright (c) 2004, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2004, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -12,8 +12,7 @@
  * See README and COPYING for more details.
  */
 
-#include <stdlib.h>
-#include <stdio.h>
+#include "includes.h"
 
 #include "common.h"
 #include "tls.h"
@@ -26,3 +25,217 @@
 void tls_deinit(void *ssl_ctx)
 {
 }
+
+
+#ifdef EAP_TLS_NONE
+
+int tls_get_errors(void *tls_ctx)
+{
+	return 0;
+}
+
+
+struct tls_connection * tls_connection_init(void *tls_ctx)
+{
+	return NULL;
+}
+
+
+void tls_connection_deinit(void *tls_ctx, struct tls_connection *conn)
+{
+}
+
+
+int tls_connection_established(void *tls_ctx, struct tls_connection *conn)
+{
+	return -1;
+}
+
+
+int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn)
+{
+	return -1;
+}
+
+
+int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
+			      const struct tls_connection_params *params)
+{
+	return -1;
+}
+
+
+int tls_global_set_params(void *tls_ctx,
+			  const struct tls_connection_params *params)
+{
+	return -1;
+}
+
+
+int tls_global_set_verify(void *tls_ctx, int check_crl)
+{
+	return -1;
+}
+
+
+int tls_connection_set_verify(void *tls_ctx, struct tls_connection *conn,
+			      int verify_peer)
+{
+	return -1;
+}
+
+
+int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn,
+			  int tls_ia)
+{
+	return -1;
+}
+
+
+int tls_connection_get_keys(void *tls_ctx, struct tls_connection *conn,
+			    struct tls_keys *keys)
+{
+	return -1;
+}
+
+
+int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
+		       const char *label, int server_random_first,
+		       u8 *out, size_t out_len)
+{
+	return -1;
+}
+
+
+u8 * tls_connection_handshake(void *tls_ctx, struct tls_connection *conn,
+			      const u8 *in_data, size_t in_len,
+			      size_t *out_len, u8 **appl_data,
+			      size_t *appl_data_len)
+{
+	return NULL;
+}
+
+
+u8 * tls_connection_server_handshake(void *tls_ctx,
+				     struct tls_connection *conn,
+				     const u8 *in_data, size_t in_len,
+				     size_t *out_len)
+{
+	return NULL;
+}
+
+
+int tls_connection_encrypt(void *tls_ctx, struct tls_connection *conn,
+			   const u8 *in_data, size_t in_len,
+			   u8 *out_data, size_t out_len)
+{
+	return -1;
+}
+
+
+int tls_connection_decrypt(void *tls_ctx, struct tls_connection *conn,
+			   const u8 *in_data, size_t in_len,
+			   u8 *out_data, size_t out_len)
+{
+	return -1;
+}
+
+
+int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn)
+{
+	return 0;
+}
+
+
+int tls_connection_set_master_key(void *tls_ctx, struct tls_connection *conn,
+				  const u8 *key, size_t key_len)
+{
+	return -1;
+}
+
+
+int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
+				   u8 *ciphers)
+{
+	return -1;
+}
+
+
+int tls_get_cipher(void *tls_ctx, struct tls_connection *conn,
+		   char *buf, size_t buflen)
+{
+	return -1;
+}
+
+
+int tls_connection_enable_workaround(void *tls_ctx,
+				     struct tls_connection *conn)
+{
+	return -1;
+}
+
+
+int tls_connection_client_hello_ext(void *tls_ctx, struct tls_connection *conn,
+				    int ext_type, const u8 *data,
+				    size_t data_len)
+{
+	return -1;
+}
+
+
+int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn)
+{
+	return 0;
+}
+
+
+int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn)
+{
+	return 0;
+}
+
+
+int tls_connection_get_write_alerts(void *tls_ctx,
+				    struct tls_connection *conn)
+{
+	return 0;
+}
+
+
+int tls_connection_get_keyblock_size(void *tls_ctx,
+				     struct tls_connection *conn)
+{
+	return -1;
+}
+
+
+unsigned int tls_capabilities(void *tls_ctx)
+{
+	return 0;
+}
+
+
+int tls_connection_ia_send_phase_finished(void *tls_ctx,
+					  struct tls_connection *conn,
+					  int final,
+					  u8 *out_data, size_t out_len)
+{
+	return -1;
+}
+
+
+int tls_connection_ia_final_phase_finished(void *tls_ctx,
+					   struct tls_connection *conn)
+{
+	return -1;
+}
+
+
+int tls_connection_ia_permute_inner_secret(void *tls_ctx,
+					   struct tls_connection *conn,
+					   const u8 *key, size_t key_len)
+{
+	return -1;
+}
+
+#endif /* EAP_TLS_NONE */
Index: driver.h
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/driver.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/driver.h -L contrib/wpa_supplicant/driver.h -u -r1.2 -r1.3
--- contrib/wpa_supplicant/driver.h
+++ contrib/wpa_supplicant/driver.h
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant - driver interface definition
- * Copyright (c) 2003-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2003-2006, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -128,6 +128,30 @@
 	 * mode - Operation mode (infra/ibss) IEEE80211_MODE_*
 	 */
 	int mode;
+
+	/**
+	 * wep_key - WEP keys for static WEP configuration
+	 */
+	const u8 *wep_key[4];
+
+	/**
+	 * wep_key_len - WEP key length for static WEP configuration
+	 */
+	size_t wep_key_len[4];
+
+	/**
+	 * wep_tx_keyidx - WEP TX key index for static WEP configuration
+	 */
+	int wep_tx_keyidx;
+
+	/**
+	 * mgmt_frame_protection - IEEE 802.11w management frame protection
+	 */
+	enum {
+		NO_MGMT_FRAME_PROTECTION,
+		MGMT_FRAME_PROTECTION_OPTIONAL,
+		MGMT_FRAME_PROTECTION_REQUIRED
+	} mgmt_frame_protection;
 };
 
 /**
@@ -155,10 +179,56 @@
 /* Driver generated WPA/RSN IE */
 #define WPA_DRIVER_FLAGS_DRIVER_IE	0x00000001
 #define WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC 0x00000002
+#define WPA_DRIVER_FLAGS_USER_SPACE_MLME 0x00000004
 	unsigned int flags;
 };
 
 
+#define WPA_CHAN_W_SCAN 0x00000001
+#define WPA_CHAN_W_ACTIVE_SCAN 0x00000002
+#define WPA_CHAN_W_IBSS 0x00000004
+
+struct wpa_channel_data {
+	short chan; /* channel number (IEEE 802.11) */
+	short freq; /* frequency in MHz */
+	int flag; /* flag for user space use (WPA_CHAN_*) */
+};
+
+#define WPA_RATE_ERP 0x00000001
+#define WPA_RATE_BASIC 0x00000002
+#define WPA_RATE_PREAMBLE2 0x00000004
+#define WPA_RATE_SUPPORTED 0x00000010
+#define WPA_RATE_OFDM 0x00000020
+#define WPA_RATE_CCK 0x00000040
+#define WPA_RATE_MANDATORY 0x00000100
+
+struct wpa_rate_data {
+	int rate; /* rate in 100 kbps */
+	int flags; /* WPA_RATE_ flags */
+};
+
+typedef enum {
+	WPA_MODE_IEEE80211B,
+	WPA_MODE_IEEE80211G,
+	WPA_MODE_IEEE80211A,
+	NUM_WPA_MODES
+} wpa_hw_mode;
+
+struct wpa_hw_modes {
+	wpa_hw_mode mode;
+	int num_channels;
+	struct wpa_channel_data *channels;
+	int num_rates;
+	struct wpa_rate_data *rates;
+};
+
+
+struct ieee80211_rx_status {
+        int channel;
+        int ssi;
+};
+
+
 /**
  * struct wpa_driver_ops - Driver interface API definition
  *
@@ -230,10 +300,12 @@
 	 * set_key - Configure encryption key
 	 * @priv: private driver interface data
 	 * @alg: encryption algorithm (%WPA_ALG_NONE, %WPA_ALG_WEP,
-	 *	%WPA_ALG_TKIP, %WPA_ALG_CCMP); %WPA_ALG_NONE clears the key.
+	 *	%WPA_ALG_TKIP, %WPA_ALG_CCMP, %WPA_ALG_IGTK, %WPA_ALG_DHV);
+	 *	%WPA_ALG_NONE clears the key.
 	 * @addr: address of the peer STA or ff:ff:ff:ff:ff:ff for
 	 *	broadcast/default keys
-	 * @key_idx: key index (0..3), usually 0 for unicast keys
+	 * @key_idx: key index (0..3), usually 0 for unicast keys; 0..4095 for
+	 *	IGTK
 	 * @set_tx: configure this key as the default Tx key (only used when
 	 *	driver does not support separate unicast/individual key
 	 * @seq: sequence number/packet number, seq_len octets, the next
@@ -241,11 +313,11 @@
 	 *	for Rx keys (in most cases, this is only used with broadcast
 	 *	keys and set to zero for unicast keys)
 	 * @seq_len: length of the seq, depends on the algorithm:
-	 *	TKIP: 6 octets, CCMP: 6 octets
+	 *	TKIP: 6 octets, CCMP: 6 octets, IGTK: 6 octets
 	 * @key: key buffer; TKIP: 16-byte temporal key, 8-byte Tx Mic key,
 	 *	8-byte Rx Mic Key
 	 * @key_len: length of the key buffer in octets (WEP: 5 or 13,
-	 *	TKIP: 32, CCMP: 16)
+	 *	TKIP: 32, CCMP: 16, IGTK: 16, DHV: 16)
 	 *
 	 * Returns: 0 on success, -1 on failure
 	 *
@@ -554,6 +626,132 @@
 	 */
 	int (*send_eapol)(void *priv, const u8 *dest, u16 proto,
 			  const u8 *data, size_t data_len);
+
+	/**
+	 * set_operstate - Sets device operating state to DORMANT or UP
+	 * @priv: private driver interface data
+	 * @state: 0 = dormant, 1 = up
+	 * Returns: 0 on success, -1 on failure
+	 *
+	 * This is an optional function that can be used on operating systems
+	 * that support a concept of controlling network device state from user
+	 * space applications. This function, if set, gets called with
+	 * state = 1 when authentication has been completed and with state = 0
+	 * when connection is lost.
+	 */
+	int (*set_operstate)(void *priv, int state);
+
+	/**
+	 * mlme_setprotection - MLME-SETPROTECTION.request primitive
+	 * @priv: Private driver interface data
+	 * @addr: Address of the station for which to set protection (may be
+	 * %NULL for group keys)
+	 * @protect_type: MLME_SETPROTECTION_PROTECT_TYPE_*
+	 * @key_type: MLME_SETPROTECTION_KEY_TYPE_*
+	 * Returns: 0 on success, -1 on failure
+	 *
+	 * This is an optional function that can be used to set the driver to
+	 * require protection for Tx and/or Rx frames. This uses the layer
+	 * interface defined in IEEE 802.11i-2004 clause 10.3.22.1
+	 * (MLME-SETPROTECTION.request). Many drivers do not use explicit
+	 * set protection operation; instead, they set protection implicitly
+	 * based on configured keys.
+	 */
+	int (*mlme_setprotection)(void *priv, const u8 *addr, int protect_type,
+				  int key_type);
+
+	/**
+	 * get_hw_feature_data - Get hardware support data (channels and rates)
+	 * @priv: Private driver interface data
+	 * @num_modes: Variable for returning the number of returned modes
+	 * flags: Variable for returning hardware feature flags
+	 * Returns: Pointer to allocated hardware data on success or %NULL on
+	 * failure. Caller is responsible for freeing this.
+	 *
+	 * This function is only needed for drivers that export MLME
+	 * (management frame processing) to wpa_supplicant.
+	 */
+	struct wpa_hw_modes * (*get_hw_feature_data)(void *priv,
+						     u16 *num_modes,
+						     u16 *flags);
+
+	/**
+	 * set_channel - Set channel
+	 * @priv: Private driver interface data
+	 * @phymode: WPA_MODE_IEEE80211B, ..
+	 * @chan: IEEE 802.11 channel number
+	 * @freq: Frequency of the channel in MHz
+	 * Returns: 0 on success, -1 on failure
+	 *
+	 * This function is only needed for drivers that export MLME
+	 * (management frame processing) to wpa_supplicant.
+	 */
+	int (*set_channel)(void *priv, wpa_hw_mode phymode, int chan,
+			   int freq);
+
+	/**
+	 * set_ssid - Set SSID
+	 * @priv: Private driver interface data
+	 * @ssid: SSID
+	 * @ssid_len: SSID length
+	 * Returns: 0 on success, -1 on failure
+	 *
+	 * This function is only needed for drivers that export MLME
+	 * (management frame processing) to wpa_supplicant.
+	 */
+	int (*set_ssid)(void *priv, const u8 *ssid, size_t ssid_len);
+
+	/**
+	 * set_bssid - Set BSSID
+	 * @priv: Private driver interface data
+	 * @bssid: BSSID
+	 * Returns: 0 on success, -1 on failure
+	 *
+	 * This function is only needed for drivers that export MLME
+	 * (management frame processing) to wpa_supplicant.
+	 */
+	int (*set_bssid)(void *priv, const u8 *bssid);
+
+	/**
+	 * send_mlme - Send management frame from MLME
+	 * @priv: Private driver interface data
+	 * @data: IEEE 802.11 management frame with IEEE 802.11 header
+	 * @data_len: Size of the management frame
+	 * Returns: 0 on success, -1 on failure
+	 *
+	 * This function is only needed for drivers that export MLME
+	 * (management frame processing) to wpa_supplicant.
+	 */
+	int (*send_mlme)(void *priv, const u8 *data, size_t data_len);
+
+	/**
+	 * mlme_add_sta - Add a STA entry into the driver/netstack
+	 * @priv: Private driver interface data
+	 * @addr: MAC address of the STA (e.g., BSSID of the AP)
+	 * @supp_rates: Supported rate set (from (Re)AssocResp); in IEEE 802.11
+	 * format (one octet per rate, 1 = 0.5 Mbps)
+	 * @supp_rates_len: Number of entries in supp_rates
+	 * Returns: 0 on success, -1 on failure
+	 *
+	 * This function is only needed for drivers that export MLME
+	 * (management frame processing) to wpa_supplicant. When the MLME code
+	 * completes association with an AP, this function is called to
+	 * configure the driver/netstack with a STA entry for data frame
+	 * processing (TX rate control, encryption/decryption).
+	 */
+	 int (*mlme_add_sta)(void *priv, const u8 *addr, const u8 *supp_rates,
+			     size_t supp_rates_len);
+
+	/**
+	 * mlme_remove_sta - Remove a STA entry from the driver/netstack
+	 * @priv: Private driver interface data
+	 * @addr: MAC address of the STA (e.g., BSSID of the AP)
+	 * Returns: 0 on success, -1 on failure
+	 *
+	 * This function is only needed for drivers that export MLME
+	 * (management frame processing) to wpa_supplicant.
+	 */
+	 int (*mlme_remove_sta)(void *priv, const u8 *addr);
 };
 
 #endif /* DRIVER_H */
Index: eap_pax.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/eap_pax.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -L contrib/wpa_supplicant/eap_pax.c -L contrib/wpa_supplicant/eap_pax.c -u -r1.1 -r1.2
--- contrib/wpa_supplicant/eap_pax.c
+++ contrib/wpa_supplicant/eap_pax.c
@@ -1,6 +1,6 @@
 /*
- * WPA Supplicant / EAP-PAX (draft-clancy-eap-pax-04.txt)
- * Copyright (c) 2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * EAP peer method: EAP-PAX (RFC 4746)
+ * Copyright (c) 2005-2006, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -12,13 +12,10 @@
  * See README and COPYING for more details.
  */
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
+#include "includes.h"
 
 #include "common.h"
 #include "eap_i.h"
-#include "wpa_supplicant.h"
 #include "config_ssid.h"
 #include "eap_pax_common.h"
 #include "sha1.h"
@@ -26,6 +23,11 @@
 
 /*
  * Note: only PAX_STD subprotocol is currently supported
+ *
+ * TODO: Add support with PAX_SEC with the mandatory to implement ciphersuite
+ * (HMAC_SHA1_128, IANA DH Group 14 (2048 bits), RSA-PKCS1-V1_5) and
+ * recommended ciphersuite (HMAC_SHA256_128, IANA DH Group 15 (3072 bits),
+ * RSAES-OAEP).
  */
 
 struct eap_pax_data {
@@ -68,22 +70,21 @@
 		return NULL;
 	}
 
-	data = malloc(sizeof(*data));
+	data = os_zalloc(sizeof(*data));
 	if (data == NULL)
 		return NULL;
-	memset(data, 0, sizeof(*data));
 	data->state = PAX_INIT;
 
-	data->cid = malloc(config->nai_len);
+	data->cid = os_malloc(config->nai_len);
 	if (data->cid == NULL) {
 		eap_pax_deinit(sm, data);
 		return NULL;
 	}
-	memcpy(data->cid, config->nai, config->nai_len);
+	os_memcpy(data->cid, config->nai, config->nai_len);
 	data->cid_len = config->nai_len;
 
 	if (config->eappsk) {
-		memcpy(data->ak, config->eappsk, EAP_PAX_AK_LEN);
+		os_memcpy(data->ak, config->eappsk, EAP_PAX_AK_LEN);
 	} else {
 		u8 hash[SHA1_MAC_LEN];
 		const unsigned char *addr[1];
@@ -91,7 +92,7 @@
 		addr[0] = config->password;
 		len[0] = config->password_len;
 		sha1_vector(1, addr, len, hash);
-		memcpy(data->ak, hash, EAP_PAX_AK_LEN);
+		os_memcpy(data->ak, hash, EAP_PAX_AK_LEN);
 	}
 
 	return data;
@@ -101,8 +102,8 @@
 static void eap_pax_deinit(struct eap_sm *sm, void *priv)
 {
 	struct eap_pax_data *data = priv;
-	free(data->cid);
-	free(data);
+	os_free(data->cid);
+	os_free(data);
 }
 
 
@@ -111,7 +112,7 @@
 {
 	struct eap_pax_hdr *resp;
 
-	resp = malloc(resp_len);
+	resp = os_malloc(resp_len);
 	if (resp == NULL)
 		return NULL;
 	resp->code = EAP_CODE_RESPONSE;
@@ -127,7 +128,7 @@
 }
 
 
-static u8 * eap_pax_process_std_1(struct eap_sm *sm, struct eap_pax_data *data,
+static u8 * eap_pax_process_std_1(struct eap_pax_data *data,
 				  struct eap_method_ret *ret,
 				  const u8 *reqData, size_t reqDataLen,
 				  size_t *respDataLen)
@@ -175,7 +176,7 @@
 
 	pos += 2;
 	left -= 2;
-	memcpy(data->rand.r.x, pos, EAP_PAX_RAND_LEN);
+	os_memcpy(data->rand.r.x, pos, EAP_PAX_RAND_LEN);
 	wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: X (server rand)",
 		    data->rand.r.x, EAP_PAX_RAND_LEN);
 	pos += EAP_PAX_RAND_LEN;
@@ -212,14 +213,14 @@
 	rpos = (u8 *) (resp + 1);
 	*rpos++ = 0;
 	*rpos++ = EAP_PAX_RAND_LEN;
-	memcpy(rpos, data->rand.r.y, EAP_PAX_RAND_LEN);
+	os_memcpy(rpos, data->rand.r.y, EAP_PAX_RAND_LEN);
 	wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: B = Y (client rand)",
 		    rpos, EAP_PAX_RAND_LEN);
 	rpos += EAP_PAX_RAND_LEN;
 
 	WPA_PUT_BE16(rpos, data->cid_len);
 	rpos += 2;
-	memcpy(rpos, data->cid, data->cid_len);
+	os_memcpy(rpos, data->cid, data->cid_len);
 	wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-PAX: CID", rpos, data->cid_len);
 	rpos += data->cid_len;
 
@@ -233,6 +234,8 @@
 		    rpos, EAP_PAX_MAC_LEN);
 	rpos += EAP_PAX_MAC_LEN;
 
+	/* Optional ADE could be added here, if needed */
+
 	eap_pax_mac(req->mac_id, data->ick, EAP_PAX_ICK_LEN,
 		    (u8 *) resp, *respDataLen - EAP_PAX_ICV_LEN,
 		    NULL, 0, NULL, 0, rpos);
@@ -248,7 +251,7 @@
 }
 
 
-static u8 * eap_pax_process_std_3(struct eap_sm *sm, struct eap_pax_data *data,
+static u8 * eap_pax_process_std_3(struct eap_pax_data *data,
 				  struct eap_method_ret *ret,
 				  const u8 *reqData, size_t reqDataLen,
 				  size_t *respDataLen)
@@ -300,7 +303,7 @@
 	eap_pax_mac(data->mac_id, data->ck, EAP_PAX_CK_LEN,
 		    data->rand.r.y, EAP_PAX_RAND_LEN,
 		    (u8 *) data->cid, data->cid_len, NULL, 0, mac);
-	if (memcmp(pos, mac, EAP_PAX_MAC_LEN) != 0) {
+	if (os_memcmp(pos, mac, EAP_PAX_MAC_LEN) != 0) {
 		wpa_printf(MSG_INFO, "EAP-PAX: Invalid MAC_CK(B, CID) "
 			   "received");
 		wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: expected MAC_CK(B, CID)",
@@ -326,6 +329,9 @@
 		return NULL;
 
 	rpos = (u8 *) (resp + 1);
+
+	/* Optional ADE could be added here, if needed */
+
 	eap_pax_mac(data->mac_id, data->ick, EAP_PAX_ICK_LEN,
 		    (u8 *) resp, *respDataLen - EAP_PAX_ICV_LEN,
 		    NULL, 0, NULL, 0, rpos);
@@ -352,7 +358,8 @@
 	size_t len;
 	u16 flen;
 
-	pos = eap_hdr_validate(EAP_TYPE_PAX, reqData, reqDataLen, &len);
+	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PAX,
+			       reqData, reqDataLen, &len);
 	if (pos == NULL || len < EAP_PAX_ICV_LEN) {
 		ret->ignore = TRUE;
 		return NULL;
@@ -393,7 +400,7 @@
 		return NULL;
 	}
 
-	/* TODO: add support for EAP_PAX_MAC_AES_CBC_MAC_128 */
+	/* TODO: add support EAP_PAX_HMAC_SHA256_128 */
 	if (req->mac_id != EAP_PAX_MAC_HMAC_SHA1_128) {
 		wpa_printf(MSG_INFO, "EAP-PAX: Unsupported MAC ID 0x%x",
 			   req->mac_id);
@@ -432,7 +439,7 @@
 		eap_pax_mac(req->mac_id, data->ick, EAP_PAX_ICK_LEN,
 			    reqData, flen, NULL, 0, NULL, 0, icvbuf);
 	}
-	if (memcmp(icv, icvbuf, EAP_PAX_ICV_LEN) != 0) {
+	if (os_memcmp(icv, icvbuf, EAP_PAX_ICV_LEN) != 0) {
 		wpa_printf(MSG_DEBUG, "EAP-PAX: invalid ICV - ignoring the "
 			   "message");
 		wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: expected ICV",
@@ -448,11 +455,11 @@
 
 	switch (req->op_code) {
 	case EAP_PAX_OP_STD_1:
-		resp = eap_pax_process_std_1(sm, data, ret, reqData, flen,
+		resp = eap_pax_process_std_1(data, ret, reqData, flen,
 					     respDataLen);
 		break;
 	case EAP_PAX_OP_STD_3:
-		resp = eap_pax_process_std_3(sm, data, ret, reqData, flen,
+		resp = eap_pax_process_std_3(data, ret, reqData, flen,
 					     respDataLen);
 		break;
 	default:
@@ -485,26 +492,60 @@
 	if (data->state != PAX_DONE)
 		return NULL;
 
-	key = malloc(EAP_PAX_MSK_LEN);
+	key = os_malloc(EAP_MSK_LEN);
 	if (key == NULL)
 		return NULL;
 
-	*len = EAP_PAX_MSK_LEN;
+	*len = EAP_MSK_LEN;
 	eap_pax_kdf(data->mac_id, data->mk, EAP_PAX_MK_LEN,
 		    "Master Session Key", data->rand.e, 2 * EAP_PAX_RAND_LEN,
-		    EAP_PAX_MSK_LEN, key);
+		    EAP_MSK_LEN, key);
 
 	return key;
 }
 
 
-const struct eap_method eap_method_pax =
+static u8 * eap_pax_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
 {
-	.method = EAP_TYPE_PAX,
-	.name = "PAX",
-	.init = eap_pax_init,
-	.deinit = eap_pax_deinit,
-	.process = eap_pax_process,
-	.isKeyAvailable = eap_pax_isKeyAvailable,
-	.getKey = eap_pax_getKey,
-};
+	struct eap_pax_data *data = priv;
+	u8 *key;
+
+	if (data->state != PAX_DONE)
+		return NULL;
+
+	key = os_malloc(EAP_EMSK_LEN);
+	if (key == NULL)
+		return NULL;
+
+	*len = EAP_EMSK_LEN;
+	eap_pax_kdf(data->mac_id, data->mk, EAP_PAX_MK_LEN,
+		    "Extended Master Session Key",
+		    data->rand.e, 2 * EAP_PAX_RAND_LEN,
+		    EAP_EMSK_LEN, key);
+
+	return key;
+}
+
+
+int eap_peer_pax_register(void)
+{
+	struct eap_method *eap;
+	int ret;
+
+	eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
+				    EAP_VENDOR_IETF, EAP_TYPE_PAX, "PAX");
+	if (eap == NULL)
+		return -1;
+
+	eap->init = eap_pax_init;
+	eap->deinit = eap_pax_deinit;
+	eap->process = eap_pax_process;
+	eap->isKeyAvailable = eap_pax_isKeyAvailable;
+	eap->getKey = eap_pax_getKey;
+	eap->get_emsk = eap_pax_get_emsk;
+
+	ret = eap_peer_method_register(eap);
+	if (ret)
+		eap_peer_method_free(eap);
+	return ret;
+}
Index: preauth.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/preauth.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -L contrib/wpa_supplicant/preauth.c -L contrib/wpa_supplicant/preauth.c -u -r1.1 -r1.2
--- contrib/wpa_supplicant/preauth.c
+++ contrib/wpa_supplicant/preauth.c
@@ -1,6 +1,6 @@
 /*
- * WPA Supplicant - RSN pre-authentication and PMKSA caching
- * Copyright (c) 2003-2006, Jouni Malinen <jkmaline at cc.hut.fi>
+ * WPA Supplicant - RSN pre-authentication
+ * Copyright (c) 2003-2006, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -12,30 +12,21 @@
  * See README and COPYING for more details.
  */
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <sys/time.h>
-#ifndef CONFIG_NATIVE_WINDOWS
-#include <netinet/in.h>
-#endif /* CONFIG_NATIVE_WINDOWS */
-#include <string.h>
-#include <time.h>
+#include "includes.h"
 
 #include "common.h"
-#include "sha1.h"
 #include "wpa.h"
 #include "driver.h"
 #include "eloop.h"
-#include "wpa_supplicant.h"
 #include "config.h"
 #include "l2_packet.h"
 #include "eapol_sm.h"
 #include "preauth.h"
+#include "pmksa_cache.h"
 #include "wpa_i.h"
 
 
 #define PMKID_CANDIDATE_PRIO_SCAN 1000
-static const int pmksa_cache_max_entries = 32;
 
 
 struct rsn_pmksa_candidate {
@@ -46,429 +37,6 @@
 
 
 /**
- * rsn_pmkid - Calculate PMK identifier
- * @pmk: Pairwise master key
- * @aa: Authenticator address
- * @spa: Supplicant address
- *
- * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy
- * PMKID = HMAC-SHA1-128(PMK, "PMK Name" || AA || SPA)
- */
-static void rsn_pmkid(const u8 *pmk, const u8 *aa, const u8 *spa, u8 *pmkid)
-{
-	char *title = "PMK Name";
-	const unsigned char *addr[3];
-	const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN };
-	unsigned char hash[SHA1_MAC_LEN];
-
-	addr[0] = (unsigned char *) title;
-	addr[1] = aa;
-	addr[2] = spa;
-
-	hmac_sha1_vector(pmk, PMK_LEN, 3, addr, len, hash);
-	memcpy(pmkid, hash, PMKID_LEN);
-}
-
-
-static void pmksa_cache_set_expiration(struct wpa_sm *sm);
-
-
-static void pmksa_cache_free_entry(struct wpa_sm *sm,
-				   struct rsn_pmksa_cache *entry, int replace)
-{
-	int current;
-
-	current = sm->cur_pmksa == entry ||
-		(sm->pmk_len == entry->pmk_len &&
-		 memcmp(sm->pmk, entry->pmk, sm->pmk_len) == 0);
-
-	free(entry);
-	sm->pmksa_count--;
-
-	if (current) {
-		wpa_printf(MSG_DEBUG, "RSN: removed current PMKSA entry");
-		sm->cur_pmksa = NULL;
-
-		if (replace) {
-			/* A new entry is being added, so no need to
-			 * deauthenticate in this case. This happens when EAP
-			 * authentication is completed again (reauth or failed
-			 * PMKSA caching attempt). */
-			return;
-		}
-
-		memset(sm->pmk, 0, sizeof(sm->pmk));
-		wpa_sm_deauthenticate(sm, REASON_UNSPECIFIED);
-		wpa_sm_req_scan(sm, 0, 0);
-	}
-}
-
-
-static void pmksa_cache_expire(void *eloop_ctx, void *timeout_ctx)
-{
-	struct wpa_sm *sm = eloop_ctx;
-	time_t now;
-
-	time(&now);
-	while (sm->pmksa && sm->pmksa->expiration <= now) {
-		struct rsn_pmksa_cache *entry = sm->pmksa;
-		sm->pmksa = entry->next;
-		wpa_printf(MSG_DEBUG, "RSN: expired PMKSA cache entry for "
-			   MACSTR, MAC2STR(entry->aa));
-		pmksa_cache_free_entry(sm, entry, 0);
-	}
-
-	pmksa_cache_set_expiration(sm);
-}
-
-
-static void pmksa_cache_reauth(void *eloop_ctx, void *timeout_ctx)
-{
-	struct wpa_sm *sm = eloop_ctx;
-	sm->cur_pmksa = NULL;
-	eapol_sm_request_reauth(sm->eapol);
-}
-
-
-static void pmksa_cache_set_expiration(struct wpa_sm *sm)
-{
-	int sec;
-	struct rsn_pmksa_cache *entry;
-
-	eloop_cancel_timeout(pmksa_cache_expire, sm, NULL);
-	eloop_cancel_timeout(pmksa_cache_reauth, sm, NULL);
-	if (sm->pmksa == NULL)
-		return;
-	sec = sm->pmksa->expiration - time(NULL);
-	if (sec < 0)
-		sec = 0;
-	eloop_register_timeout(sec + 1, 0, pmksa_cache_expire, sm, NULL);
-
-	entry = sm->cur_pmksa ? sm->cur_pmksa :
-		pmksa_cache_get(sm, sm->bssid, NULL);
-	if (entry) {
-		sec = sm->pmksa->reauth_time - time(NULL);
-		if (sec < 0)
-			sec = 0;
-		eloop_register_timeout(sec, 0, pmksa_cache_reauth, sm, NULL);
-	}
-}
-
-
-/**
- * pmksa_cache_add - Add a PMKSA cache entry
- * @sm: Pointer to WPA state machine data from wpa_sm_init()
- * @pmk: The new pairwise master key
- * @pmk_len: PMK length in bytes, usually PMK_LEN (32)
- * @aa: Authenticator address
- * @spa: Supplicant address
- * @ssid: The network configuration for which this PMK is being added
- * Returns: Pointer to the added PMKSA cache entry or %NULL on error
- *
- * This function create a PMKSA entry for a new PMK and adds it to the PMKSA
- * cache. If an old entry is already in the cache for the same Authenticator,
- * this entry will be replaced with the new entry. PMKID will be calculated
- * based on the PMK and the driver interface is notified of the new PMKID.
- */
-struct rsn_pmksa_cache *
-pmksa_cache_add(struct wpa_sm *sm, const u8 *pmk,
-		size_t pmk_len, const u8 *aa, const u8 *spa,
-		struct wpa_ssid *ssid)
-{
-	struct rsn_pmksa_cache *entry, *pos, *prev;
-	time_t now;
-
-	if (sm->proto != WPA_PROTO_RSN || pmk_len > PMK_LEN)
-		return NULL;
-
-	entry = malloc(sizeof(*entry));
-	if (entry == NULL)
-		return NULL;
-	memset(entry, 0, sizeof(*entry));
-	memcpy(entry->pmk, pmk, pmk_len);
-	entry->pmk_len = pmk_len;
-	rsn_pmkid(pmk, aa, spa, entry->pmkid);
-	now = time(NULL);
-	entry->expiration = now + sm->dot11RSNAConfigPMKLifetime;
-	entry->reauth_time = now + sm->dot11RSNAConfigPMKLifetime *
-		sm->dot11RSNAConfigPMKReauthThreshold / 100;
-	entry->akmp = WPA_KEY_MGMT_IEEE8021X;
-	memcpy(entry->aa, aa, ETH_ALEN);
-	entry->ssid = ssid;
-
-	/* Replace an old entry for the same Authenticator (if found) with the
-	 * new entry */
-	pos = sm->pmksa;
-	prev = NULL;
-	while (pos) {
-		if (memcmp(aa, pos->aa, ETH_ALEN) == 0) {
-			if (pos->pmk_len == pmk_len &&
-			    memcmp(pos->pmk, pmk, pmk_len) == 0 &&
-			    memcmp(pos->pmkid, entry->pmkid, PMKID_LEN) == 0) {
-				wpa_printf(MSG_DEBUG, "WPA: reusing previous "
-					   "PMKSA entry");
-				free(entry);
-				return pos;
-			}
-			if (prev == NULL)
-				sm->pmksa = pos->next;
-			else
-				prev->next = pos->next;
-			wpa_printf(MSG_DEBUG, "RSN: Replace PMKSA entry for "
-				   "the current AP");
-			pmksa_cache_free_entry(sm, pos, 1);
-			break;
-		}
-		prev = pos;
-		pos = pos->next;
-	}
-
-	if (sm->pmksa_count >= pmksa_cache_max_entries && sm->pmksa) {
-		/* Remove the oldest entry to make room for the new entry */
-		pos = sm->pmksa;
-		sm->pmksa = pos->next;
-		wpa_printf(MSG_DEBUG, "RSN: removed the oldest PMKSA cache "
-			   "entry (for " MACSTR ") to make room for new one",
-			   MAC2STR(pos->aa));
-		wpa_sm_remove_pmkid(sm, pos->aa, pos->pmkid);
-		pmksa_cache_free_entry(sm, pos, 0);
-	}
-
-	/* Add the new entry; order by expiration time */
-	pos = sm->pmksa;
-	prev = NULL;
-	while (pos) {
-		if (pos->expiration > entry->expiration)
-			break;
-		prev = pos;
-		pos = pos->next;
-	}
-	if (prev == NULL) {
-		entry->next = sm->pmksa;
-		sm->pmksa = entry;
-		pmksa_cache_set_expiration(sm);
-	} else {
-		entry->next = prev->next;
-		prev->next = entry;
-	}
-	sm->pmksa_count++;
-	wpa_printf(MSG_DEBUG, "RSN: added PMKSA cache entry for " MACSTR,
-		   MAC2STR(entry->aa));
-	wpa_sm_add_pmkid(sm, entry->aa, entry->pmkid);
-
-	return entry;
-}
-
-
-/**
- * pmksa_cache_free - Free all entries in PMKSA cache
- * @sm: Pointer to WPA state machine data from wpa_sm_init()
- */
-void pmksa_cache_free(struct wpa_sm *sm)
-{
-	struct rsn_pmksa_cache *entry, *prev;
-
-	if (sm == NULL)
-		return;
-
-	entry = sm->pmksa;
-	sm->pmksa = NULL;
-	while (entry) {
-		prev = entry;
-		entry = entry->next;
-		free(prev);
-	}
-	pmksa_cache_set_expiration(sm);
-	sm->cur_pmksa = NULL;
-}
-
-
-/**
- * pmksa_cache_get - Fetch a PMKSA cache entry
- * @sm: Pointer to WPA state machine data from wpa_sm_init()
- * @aa: Authenticator address or %NULL to match any
- * @pmkid: PMKID or %NULL to match any
- * Returns: Pointer to PMKSA cache entry or %NULL if no match was found
- */
-struct rsn_pmksa_cache * pmksa_cache_get(struct wpa_sm *sm,
-					 const u8 *aa, const u8 *pmkid)
-{
-	struct rsn_pmksa_cache *entry = sm->pmksa;
-	while (entry) {
-		if ((aa == NULL || memcmp(entry->aa, aa, ETH_ALEN) == 0) &&
-		    (pmkid == NULL ||
-		     memcmp(entry->pmkid, pmkid, PMKID_LEN) == 0))
-			return entry;
-		entry = entry->next;
-	}
-	return NULL;
-}
-
-
-/**
- * pmksa_cache_notify_reconfig - Reconfiguration notification for PMKSA cache
- * @sm: Pointer to WPA state machine data from wpa_sm_init()
- *
- * Clear references to old data structures when wpa_supplicant is reconfigured.
- */
-void pmksa_cache_notify_reconfig(struct wpa_sm *sm)
-{
-	struct rsn_pmksa_cache *entry = sm->pmksa;
-	while (entry) {
-		entry->ssid = NULL;
-		entry = entry->next;
-	}
-}
-
-
-static struct rsn_pmksa_cache *
-pmksa_cache_clone_entry(struct wpa_sm *sm,
-			const struct rsn_pmksa_cache *old_entry, const u8 *aa)
-{
-	struct rsn_pmksa_cache *new_entry;
-
-	new_entry = pmksa_cache_add(sm, old_entry->pmk, old_entry->pmk_len,
-				    aa, sm->own_addr, old_entry->ssid);
-	if (new_entry == NULL)
-		return NULL;
-
-	/* TODO: reorder entries based on expiration time? */
-	new_entry->expiration = old_entry->expiration;
-	new_entry->opportunistic = 1;
-
-	return new_entry;
-}
-
-
-/**
- * pmksa_cache_get_opportunistic - Try to get an opportunistic PMKSA entry
- * @sm: Pointer to WPA state machine data from wpa_sm_init()
- * @ssid: Pointer to the current network configuration
- * @aa: Authenticator address for the new AP
- * Returns: Pointer to a new PMKSA cache entry or %NULL if not available
- *
- * Try to create a new PMKSA cache entry opportunistically by guessing that the
- * new AP is sharing the same PMK as another AP that has the same SSID and has
- * already an entry in PMKSA cache.
- */
-static struct rsn_pmksa_cache *
-pmksa_cache_get_opportunistic(struct wpa_sm *sm,
-			      struct wpa_ssid *ssid, const u8 *aa)
-{
-	struct rsn_pmksa_cache *entry = sm->pmksa;
-
-	if (ssid == NULL)
-		return NULL;
-	while (entry) {
-		if (entry->ssid == ssid) {
-			entry = pmksa_cache_clone_entry(sm, entry, aa);
-			if (entry) {
-				wpa_printf(MSG_DEBUG, "RSN: added "
-					   "opportunistic PMKSA cache entry "
-					   "for " MACSTR, MAC2STR(aa));
-			}
-			return entry;
-		}
-		entry = entry->next;
-	}
-	return NULL;
-}
-
-
-/**
- * pmksa_cache_get_current - Get the current used PMKSA entry
- * @sm: Pointer to WPA state machine data from wpa_sm_init()
- * Returns: Pointer to the current PMKSA cache entry or %NULL if not available
- */
-struct rsn_pmksa_cache * pmksa_cache_get_current(struct wpa_sm *sm)
-{
-	if (sm == NULL)
-		return NULL;
-	return sm->cur_pmksa;
-}
-
-
-/**
- * pmksa_cache_clear_current - Clear the current PMKSA entry selection
- * @sm: Pointer to WPA state machine data from wpa_sm_init()
- */
-void pmksa_cache_clear_current(struct wpa_sm *sm)
-{
-	if (sm == NULL)
-		return;
-	sm->cur_pmksa = NULL;
-}
-
-
-/**
- * pmksa_cache_set_current - Set the current PMKSA entry selection
- * @sm: Pointer to WPA state machine data from wpa_sm_init()
- * @pmkid: PMKID for selecting PMKSA or %NULL if not used
- * @bssid: BSSID for PMKSA  or %NULL if not used
- * @ssid: The network configuration for the current network
- * @try_opportunistic: Whether to allow opportunistic PMKSA caching
- * Returns: 0 if PMKSA was found or -1 if no matching entry was found
- */
-int pmksa_cache_set_current(struct wpa_sm *sm, const u8 *pmkid,
-			    const u8 *bssid, struct wpa_ssid *ssid,
-			    int try_opportunistic)
-{
-	sm->cur_pmksa = NULL;
-	if (pmkid)
-		sm->cur_pmksa = pmksa_cache_get(sm, NULL, pmkid);
-	if (sm->cur_pmksa == NULL && bssid)
-		sm->cur_pmksa = pmksa_cache_get(sm, bssid, NULL);
-	if (sm->cur_pmksa == NULL && try_opportunistic)
-		sm->cur_pmksa = pmksa_cache_get_opportunistic(sm, ssid, bssid);
-	if (sm->cur_pmksa) {
-		wpa_hexdump(MSG_DEBUG, "RSN: PMKID",
-			    sm->cur_pmksa->pmkid, PMKID_LEN);
-		return 0;
-	}
-	return -1;
-}
-
-
-/**
- * pmksa_cache_list - Dump text list of entries in PMKSA cache
- * @sm: Pointer to WPA state machine data from wpa_sm_init()
- * @buf: Buffer for the list
- * @len: Length of the buffer
- * Returns: number of bytes written to buffer
- *
- * This function is used to generate a text format representation of the
- * current PMKSA cache contents for the ctrl_iface PMKSA command.
- */
-int pmksa_cache_list(struct wpa_sm *sm, char *buf, size_t len)
-{
-	int i, j;
-	char *pos = buf;
-	struct rsn_pmksa_cache *entry;
-	time_t now;
-
-	time(&now);
-	pos += snprintf(pos, buf + len - pos,
-			"Index / AA / PMKID / expiration (in seconds) / "
-			"opportunistic\n");
-	i = 0;
-	entry = sm->pmksa;
-	while (entry) {
-		i++;
-		pos += snprintf(pos, buf + len - pos, "%d " MACSTR " ",
-				i, MAC2STR(entry->aa));
-		for (j = 0; j < PMKID_LEN; j++)
-			pos += snprintf(pos, buf + len - pos, "%02x",
-					entry->pmkid[j]);
-		pos += snprintf(pos, buf + len - pos, " %d %d\n",
-				(int) (entry->expiration - now),
-				entry->opportunistic);
-		entry = entry->next;
-	}
-	return pos - buf;
-}
-
-
-/**
  * pmksa_candidate_free - Free all entries in PMKSA candidate list
  * @sm: Pointer to WPA state machine data from wpa_sm_init()
  */
@@ -484,12 +52,12 @@
 	while (entry) {
 		prev = entry;
 		entry = entry->next;
-		free(prev);
+		os_free(prev);
 	}
 }
 
 
-#ifdef IEEE8021X_EAPOL
+#if defined(IEEE8021X_EAPOL) && !defined(CONFIG_NO_WPA2)
 
 static void rsn_preauth_receive(void *ctx, const u8 *src_addr,
 				const u8 *buf, size_t len)
@@ -500,9 +68,9 @@
 	wpa_hexdump(MSG_MSGDUMP, "RX pre-auth", buf, len);
 
 	if (sm->preauth_eapol == NULL ||
-	    memcmp(sm->preauth_bssid, "\x00\x00\x00\x00\x00\x00",
-		   ETH_ALEN) == 0 ||
-	    memcmp(sm->preauth_bssid, src_addr, ETH_ALEN) != 0) {
+	    os_memcmp(sm->preauth_bssid, "\x00\x00\x00\x00\x00\x00",
+		      ETH_ALEN) == 0 ||
+	    os_memcmp(sm->preauth_bssid, src_addr, ETH_ALEN) != 0) {
 		wpa_printf(MSG_WARNING, "RSN pre-auth frame received from "
 			   "unexpected source " MACSTR " - dropped",
 			   MAC2STR(src_addr));
@@ -523,17 +91,19 @@
 		int res, pmk_len;
 		pmk_len = PMK_LEN;
 		res = eapol_sm_get_key(eapol, pmk, PMK_LEN);
-#ifdef EAP_LEAP
 		if (res) {
+			/*
+			 * EAP-LEAP is an exception from other EAP methods: it
+			 * uses only 16-byte PMK.
+			 */
 			res = eapol_sm_get_key(eapol, pmk, 16);
 			pmk_len = 16;
 		}
-#endif /* EAP_LEAP */
 		if (res == 0) {
 			wpa_hexdump_key(MSG_DEBUG, "RSN: PMK from pre-auth",
 					pmk, pmk_len);
 			sm->pmk_len = pmk_len;
-			pmksa_cache_add(sm, pmk, pmk_len,
+			pmksa_cache_add(sm->pmksa, pmk, pmk_len,
 					sm->preauth_bssid, sm->own_addr,
 					sm->cur_ssid);
 		} else {
@@ -585,7 +155,7 @@
 	wpa_hexdump(MSG_MSGDUMP, "TX EAPOL (preauth)", msg, msglen);
 	res = l2_packet_send(sm->l2_preauth, sm->preauth_bssid,
 			     ETH_P_RSN_PREAUTH, msg, msglen);
-	free(msg);
+	os_free(msg);
 	return res;
 }
 
@@ -624,12 +194,24 @@
 		return -2;
 	}
 
-	ctx = malloc(sizeof(*ctx));
+	if (sm->bridge_ifname) {
+		sm->l2_preauth_br = l2_packet_init(sm->bridge_ifname,
+						   sm->own_addr,
+						   ETH_P_RSN_PREAUTH,
+						   rsn_preauth_receive, sm, 0);
+		if (sm->l2_preauth_br == NULL) {
+			wpa_printf(MSG_WARNING, "RSN: Failed to initialize L2 "
+				   "packet processing (bridge) for "
+				   "pre-authentication");
+			return -2;
+		}
+	}
+
+	ctx = os_zalloc(sizeof(*ctx));
 	if (ctx == NULL) {
 		wpa_printf(MSG_WARNING, "Failed to allocate EAPOL context.");
 		return -4;
 	}
-	memset(ctx, 0, sizeof(*ctx));
 	ctx->ctx = sm->ctx->ctx;
 	ctx->msg_ctx = sm->ctx->ctx;
 	ctx->preauth = 1;
@@ -643,12 +225,12 @@
 
 	sm->preauth_eapol = eapol_sm_init(ctx);
 	if (sm->preauth_eapol == NULL) {
-		free(ctx);
+		os_free(ctx);
 		wpa_printf(MSG_WARNING, "RSN: Failed to initialize EAPOL "
 			   "state machines for pre-authentication");
 		return -3;
 	}
-	memset(&eapol_conf, 0, sizeof(eapol_conf));
+	os_memset(&eapol_conf, 0, sizeof(eapol_conf));
 	eapol_conf.accept_802_1x_keys = 0;
 	eapol_conf.required_keys = 0;
 	eapol_conf.fast_reauth = sm->fast_reauth;
@@ -662,7 +244,7 @@
 	 * after the 4-Way Handshake.
 	 */
 	eapol_sm_configure(sm->preauth_eapol, -1, -1, 5, 6);
-	memcpy(sm->preauth_bssid, dst, ETH_ALEN);
+	os_memcpy(sm->preauth_bssid, dst, ETH_ALEN);
 
 	eapol_sm_notify_portValid(sm->preauth_eapol, TRUE);
 	/* 802.1X::portControl = Auto */
@@ -690,10 +272,14 @@
 	eloop_cancel_timeout(rsn_preauth_timeout, sm, NULL);
 	eapol_sm_deinit(sm->preauth_eapol);
 	sm->preauth_eapol = NULL;
-	memset(sm->preauth_bssid, 0, ETH_ALEN);
+	os_memset(sm->preauth_bssid, 0, ETH_ALEN);
 
 	l2_packet_deinit(sm->l2_preauth);
 	sm->l2_preauth = NULL;
+	if (sm->l2_preauth_br) {
+		l2_packet_deinit(sm->l2_preauth_br);
+		sm->l2_preauth_br = NULL;
+	}
 }
 
 
@@ -726,10 +312,10 @@
 	}
 
 	while (sm->pmksa_candidates) {
-		struct rsn_pmksa_cache *p = NULL;
+		struct rsn_pmksa_cache_entry *p = NULL;
 		candidate = sm->pmksa_candidates;
-		p = pmksa_cache_get(sm, candidate->bssid, NULL);
-		if (memcmp(sm->bssid, candidate->bssid, ETH_ALEN) != 0 &&
+		p = pmksa_cache_get(sm->pmksa, candidate->bssid, NULL);
+		if (os_memcmp(sm->bssid, candidate->bssid, ETH_ALEN) != 0 &&
 		    (p == NULL || p->opportunistic)) {
 			wpa_msg(sm->ctx->ctx, MSG_DEBUG, "RSN: PMKSA "
 				"candidate " MACSTR
@@ -737,7 +323,7 @@
 				MAC2STR(candidate->bssid));
 			sm->pmksa_candidates = candidate->next;
 			rsn_preauth_init(sm, candidate->bssid, sm->cur_ssid);
-			free(candidate);
+			os_free(candidate);
 			return;
 		}
 		wpa_msg(sm->ctx->ctx, MSG_DEBUG, "RSN: PMKSA candidate "
@@ -750,7 +336,7 @@
 		}
 
 		sm->pmksa_candidates = candidate->next;
-		free(candidate);
+		os_free(candidate);
 	}
 	wpa_msg(sm->ctx->ctx, MSG_DEBUG, "RSN: no more pending PMKSA "
 		"candidates");
@@ -774,7 +360,7 @@
 	struct rsn_pmksa_candidate *cand, *prev, *pos;
 
 	if (sm->cur_ssid && sm->cur_ssid->proactive_key_caching)
-		pmksa_cache_get_opportunistic(sm, sm->cur_ssid, bssid);
+		pmksa_cache_get_opportunistic(sm->pmksa, sm->cur_ssid, bssid);
 
 	if (!preauth) {
 		wpa_printf(MSG_DEBUG, "RSN: Ignored PMKID candidate without "
@@ -787,7 +373,7 @@
 	prev = NULL;
 	cand = sm->pmksa_candidates;
 	while (cand) {
-		if (memcmp(cand->bssid, bssid, ETH_ALEN) == 0) {
+		if (os_memcmp(cand->bssid, bssid, ETH_ALEN) == 0) {
 			if (prev)
 				prev->next = cand->next;
 			else
@@ -802,11 +388,10 @@
 		if (prio < PMKID_CANDIDATE_PRIO_SCAN)
 			cand->priority = prio;
 	} else {
-		cand = malloc(sizeof(*cand));
+		cand = os_zalloc(sizeof(*cand));
 		if (cand == NULL)
 			return;
-		memset(cand, 0, sizeof(*cand));
-		memcpy(cand->bssid, bssid, ETH_ALEN);
+		os_memcpy(cand->bssid, bssid, ETH_ALEN);
 		cand->priority = prio;
 	}
 
@@ -849,7 +434,7 @@
 	struct wpa_scan_result *r;
 	struct wpa_ie_data ie;
 	int i;
-	struct rsn_pmksa_cache *pmksa;
+	struct rsn_pmksa_cache_entry *pmksa;
 
 	if (sm->cur_ssid == NULL)
 		return;
@@ -863,18 +448,18 @@
 	for (i = count - 1; i >= 0; i--) {
 		r = &results[i];
 		if (r->ssid_len != sm->cur_ssid->ssid_len ||
-		    memcmp(r->ssid, sm->cur_ssid->ssid,
-			   r->ssid_len) != 0)
+		    os_memcmp(r->ssid, sm->cur_ssid->ssid,
+			      r->ssid_len) != 0)
 			continue;
 
-		if (memcmp(r->bssid, sm->bssid, ETH_ALEN) == 0)
+		if (os_memcmp(r->bssid, sm->bssid, ETH_ALEN) == 0)
 			continue;
 
 		if (r->rsn_ie_len == 0 ||
 		    wpa_parse_wpa_ie(r->rsn_ie, r->rsn_ie_len, &ie))
 			continue;
 
-		pmksa = pmksa_cache_get(sm, r->bssid, NULL);
+		pmksa = pmksa_cache_get(sm->pmksa, r->bssid, NULL);
 		if (pmksa &&
 		    (!pmksa->opportunistic ||
 		     !(ie.capabilities & WPA_CAPABILITY_PREAUTH)))
@@ -891,6 +476,7 @@
 }
 
 
+#ifdef CONFIG_CTRL_IFACE
 /**
  * rsn_preauth_get_status - Get pre-authentication status
  * @sm: Pointer to WPA state machine data from wpa_sm_init()
@@ -907,11 +493,14 @@
 			   int verbose)
 {
 	char *pos = buf, *end = buf + buflen;
-	int res;
+	int res, ret;
 
 	if (sm->preauth_eapol) {
-		pos += snprintf(pos, end - pos, "Pre-authentication "
-				"EAPOL state machines:\n");
+		ret = os_snprintf(pos, end - pos, "Pre-authentication "
+				  "EAPOL state machines:\n");
+		if (ret < 0 || ret >= end - pos)
+			return pos - buf;
+		pos += ret;
 		res = eapol_sm_get_status(sm->preauth_eapol,
 					  pos, end - pos, verbose);
 		if (res >= 0)
@@ -920,6 +509,7 @@
 
 	return pos - buf;
 }
+#endif /* CONFIG_CTRL_IFACE */
 
 
 /**
@@ -931,4 +521,4 @@
 	return sm->preauth_eapol != NULL;
 }
 
-#endif /* IEEE8021X_EAPOL */
+#endif /* IEEE8021X_EAPOL and !CONFIG_NO_WPA2 */
Index: l2_packet.h
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/l2_packet.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/l2_packet.h -L contrib/wpa_supplicant/l2_packet.h -u -r1.2 -r1.3
--- contrib/wpa_supplicant/l2_packet.h
+++ contrib/wpa_supplicant/l2_packet.h
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant - Layer2 packet interface definition
- * Copyright (c) 2003-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2003-2005, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -42,11 +42,19 @@
  */
 struct l2_packet_data;
 
+#ifdef _MSC_VER
+#pragma pack(push, 1)
+#endif /* _MSC_VER */
+
 struct l2_ethhdr {
 	u8 h_dest[ETH_ALEN];
 	u8 h_source[ETH_ALEN];
 	u16 h_proto;
-} __attribute__ ((packed));
+} STRUCT_PACKED;
+
+#ifdef _MSC_VER
+#pragma pack(pop)
+#endif /* _MSC_VER */
 
 /**
  * l2_packet_init - Initialize l2_packet interface
Index: base64.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/base64.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -L contrib/wpa_supplicant/base64.c -L contrib/wpa_supplicant/base64.c -u -r1.1 -r1.2
--- contrib/wpa_supplicant/base64.c
+++ contrib/wpa_supplicant/base64.c
@@ -1,6 +1,6 @@
 /*
  * Base64 encoding/decoding (RFC1341)
- * Copyright (c) 2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2005, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -12,12 +12,12 @@
  * See README and COPYING for more details.
  */
 
-#include <stdlib.h>
-#include <string.h>
+#include "includes.h"
 
+#include "os.h"
 #include "base64.h"
 
-static const unsigned char base64_table[64] =
+static const unsigned char base64_table[65] =
 	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 
 /**
@@ -43,7 +43,7 @@
 	olen = len * 4 / 3 + 4; /* 3-byte blocks to 4-byte */
 	olen += olen / 72; /* line feeds */
 	olen++; /* nul termination */
-	out = malloc(olen);
+	out = os_malloc(olen);
 	if (out == NULL)
 		return NULL;
 
@@ -104,9 +104,9 @@
 	unsigned char dtable[256], *out, *pos, in[4], block[4], tmp;
 	size_t i, count, olen;
 
-	memset(dtable, 0x80, 256);
-	for (i = 0; i < sizeof(base64_table); i++)
-		dtable[base64_table[i]] = i;
+	os_memset(dtable, 0x80, 256);
+	for (i = 0; i < sizeof(base64_table) - 1; i++)
+		dtable[base64_table[i]] = (unsigned char) i;
 	dtable['='] = 0;
 
 	count = 0;
@@ -119,7 +119,7 @@
 		return NULL;
 
 	olen = count / 4 * 3;
-	pos = out = malloc(count);
+	pos = out = os_malloc(olen);
 	if (out == NULL)
 		return NULL;
 
@@ -166,19 +166,9 @@
 		return -1;
 	}
 
-	f = fopen(argv[2], "r");
-	if (f == NULL)
-		return -1;
-	fseek(f, 0, SEEK_END);
-	len = ftell(f);
-	fseek(f, 0, SEEK_SET);
-	buf = malloc(len);
-	if (buf == NULL) {
-		fclose(f);
+	buf = os_readfile(argv[2], &len);
+	if (buf == NULL)
 		return -1;
-	}
-	fread(buf, 1, len, f);
-	fclose(f);
 
 	if (strcmp(argv[1], "encode") == 0)
 		e = base64_encode(buf, len, &elen);
Index: eap_tls_common.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/eap_tls_common.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/eap_tls_common.c -L contrib/wpa_supplicant/eap_tls_common.c -u -r1.2 -r1.3
--- contrib/wpa_supplicant/eap_tls_common.c
+++ contrib/wpa_supplicant/eap_tls_common.c
@@ -1,6 +1,6 @@
 /*
- * WPA Supplicant / EAP-TLS/PEAP/TTLS/FAST common functions
- * Copyright (c) 2004-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * EAP peer: EAP-TLS/PEAP/TTLS/FAST common functions
+ * Copyright (c) 2004-2006, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -12,14 +12,11 @@
  * See README and COPYING for more details.
  */
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
+#include "includes.h"
 
 #include "common.h"
 #include "eap_i.h"
 #include "eap_tls_common.h"
-#include "wpa_supplicant.h"
 #include "config_ssid.h"
 #include "md5.h"
 #include "sha1.h"
@@ -32,7 +29,7 @@
 {
 	const struct wpa_config_blob *blob;
 
-	if (*name == NULL || strncmp(*name, "blob://", 7) != 0)
+	if (*name == NULL || os_strncmp(*name, "blob://", 7) != 0)
 		return 0;
 
 	blob = eap_get_config_blob(sm, *name + 7);
@@ -50,87 +47,138 @@
 }
 
 
-int eap_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data,
-		     struct wpa_ssid *config)
+static void eap_tls_params_from_conf1(struct tls_connection_params *params,
+				      struct wpa_ssid *config)
 {
-	int ret = -1, res;
-	struct tls_connection_params params;
+	params->ca_cert = (char *) config->ca_cert;
+	params->ca_path = (char *) config->ca_path;
+	params->client_cert = (char *) config->client_cert;
+	params->private_key = (char *) config->private_key;
+	params->private_key_passwd = (char *) config->private_key_passwd;
+	params->dh_file = (char *) config->dh_file;
+	params->subject_match = (char *) config->subject_match;
+	params->altsubject_match = (char *) config->altsubject_match;
+	params->engine_id = config->engine_id;
+	params->pin = config->pin;
+	params->key_id = config->key_id;
+}
 
-	data->eap = sm;
-	data->phase2 = sm->init_phase2;
-	memset(&params, 0, sizeof(params));
-	params.engine = config->engine;
-	if (config == NULL) {
-	} else if (data->phase2) {
-		params.ca_cert = (char *) config->ca_cert2;
-		params.ca_path = (char *) config->ca_path2;
-		params.client_cert = (char *) config->client_cert2;
-		params.private_key = (char *) config->private_key2;
-		params.private_key_passwd =
-			(char *) config->private_key2_passwd;
-		params.dh_file = (char *) config->dh_file2;
-		params.subject_match = (char *) config->subject_match2;
-		params.altsubject_match = (char *) config->altsubject_match2;
-	} else {
-		params.ca_cert = (char *) config->ca_cert;
-		params.ca_path = (char *) config->ca_path;
-		params.client_cert = (char *) config->client_cert;
-		params.private_key = (char *) config->private_key;
-		params.private_key_passwd =
-			(char *) config->private_key_passwd;
-		params.dh_file = (char *) config->dh_file;
-		params.subject_match = (char *) config->subject_match;
-		params.altsubject_match = (char *) config->altsubject_match;
-		params.engine_id = config->engine_id;
-		params.pin = config->pin;
-		params.key_id = config->key_id;
-	}
-
-	if (eap_tls_check_blob(sm, &params.ca_cert, &params.ca_cert_blob,
-			       &params.ca_cert_blob_len) ||
-	    eap_tls_check_blob(sm, &params.client_cert,
-			       &params.client_cert_blob,
-			       &params.client_cert_blob_len) ||
-	    eap_tls_check_blob(sm, &params.private_key,
-			       &params.private_key_blob,
-			       &params.private_key_blob_len) ||
-	    eap_tls_check_blob(sm, &params.dh_file, &params.dh_blob,
-			       &params.dh_blob_len)) {
+
+static void eap_tls_params_from_conf2(struct tls_connection_params *params,
+				      struct wpa_ssid *config)
+{
+	params->ca_cert = (char *) config->ca_cert2;
+	params->ca_path = (char *) config->ca_path2;
+	params->client_cert = (char *) config->client_cert2;
+	params->private_key = (char *) config->private_key2;
+	params->private_key_passwd = (char *) config->private_key2_passwd;
+	params->dh_file = (char *) config->dh_file2;
+	params->subject_match = (char *) config->subject_match2;
+	params->altsubject_match = (char *) config->altsubject_match2;
+}
+
+
+static int eap_tls_params_from_conf(struct eap_sm *sm,
+				    struct eap_ssl_data *data,
+				    struct tls_connection_params *params,
+				    struct wpa_ssid *config, int phase2)
+{
+	os_memset(params, 0, sizeof(*params));
+	params->engine = config->engine;
+	if (phase2)
+		eap_tls_params_from_conf2(params, config);
+	else
+		eap_tls_params_from_conf1(params, config);
+	params->tls_ia = data->tls_ia;
+
+
+	if (eap_tls_check_blob(sm, &params->ca_cert, &params->ca_cert_blob,
+			       &params->ca_cert_blob_len) ||
+	    eap_tls_check_blob(sm, &params->client_cert,
+			       &params->client_cert_blob,
+			       &params->client_cert_blob_len) ||
+	    eap_tls_check_blob(sm, &params->private_key,
+			       &params->private_key_blob,
+			       &params->private_key_blob_len) ||
+	    eap_tls_check_blob(sm, &params->dh_file, &params->dh_blob,
+			       &params->dh_blob_len)) {
 		wpa_printf(MSG_INFO, "SSL: Failed to get configuration blobs");
-		goto done;
+		return -1;
 	}
 
+	return 0;
+}
+
+
+static int eap_tls_init_connection(struct eap_sm *sm,
+				   struct eap_ssl_data *data,
+				   struct wpa_ssid *config,
+				   struct tls_connection_params *params)
+{
+	int res;
+
 	data->conn = tls_connection_init(sm->ssl_ctx);
 	if (data->conn == NULL) {
 		wpa_printf(MSG_INFO, "SSL: Failed to initialize new TLS "
 			   "connection");
-		goto done;
+		return -1;
 	}
 
-	res = tls_connection_set_params(sm->ssl_ctx, data->conn, &params);
+	res = tls_connection_set_params(sm->ssl_ctx, data->conn, params);
 	if (res == TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED) {
 		/* At this point with the pkcs11 engine the PIN might be wrong.
 		 * We reset the PIN in the configuration to be sure to not use
 		 * it again and the calling function must request a new one */
-		free(config->pin);
+		os_free(config->pin);
 		config->pin = NULL;
 	} else if (res == TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED) {
-		wpa_printf(MSG_INFO,"TLS: Failed to load private key");
+		wpa_printf(MSG_INFO, "TLS: Failed to load private key");
 		/* We don't know exactly but maybe the PIN was wrong,
 		 * so ask for a new one. */
-		free(config->pin);
+		os_free(config->pin);
 		config->pin = NULL;
-		eap_sm_request_pin(sm, config);
+		eap_sm_request_pin(sm);
 		sm->ignore = TRUE;
-		goto done;
+		return -1;
 	} else if (res) {
 		wpa_printf(MSG_INFO, "TLS: Failed to set TLS connection "
 			   "parameters");
-		goto done;
+		return -1;
 	}
 
-	/* TODO: make this configurable */
-	data->tls_out_limit = 1398;
+	return 0;
+}
+
+
+/**
+ * eap_tls_ssl_init - Initialize shared TLS functionality
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ * @data: Data for TLS processing
+ * @config: Pointer to the network configuration
+ * Returns: 0 on success, -1 on failure
+ *
+ * This function is used to initialize shared TLS functionality for EAP-TLS,
+ * EAP-PEAP, EAP-TTLS, and EAP-FAST.
+ */
+int eap_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data,
+		     struct wpa_ssid *config)
+{
+	int ret = -1;
+	struct tls_connection_params params;
+
+	if (config == NULL)
+		return -1;
+
+	data->eap = sm;
+	data->phase2 = sm->init_phase2;
+	if (eap_tls_params_from_conf(sm, data, &params, config, data->phase2) <
+	    0)
+		goto done;
+
+	if (eap_tls_init_connection(sm, data, config, &params) < 0)
+		goto done;
+
+	data->tls_out_limit = config->fragment_size;
 	if (data->phase2) {
 		/* Limit the fragment size in the inner TLS authentication
 		 * since the outer authentication with EAP-PEAP does not yet
@@ -139,8 +187,8 @@
 			data->tls_out_limit -= 100;
 	}
 
-	if (config && config->phase1 &&
-	    strstr(config->phase1, "include_tls_length=1")) {
+	if (config->phase1 &&
+	    os_strstr(config->phase1, "include_tls_length=1")) {
 		wpa_printf(MSG_DEBUG, "TLS: Include TLS Message Length in "
 			   "unfragmented packets");
 		data->include_tls_length = 1;
@@ -153,58 +201,82 @@
 }
 
 
+/**
+ * eap_tls_ssl_deinit - Deinitialize shared TLS functionality
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ * @data: Data for TLS processing
+ *
+ * This function deinitializes shared TLS functionality that was initialized
+ * with eap_tls_ssl_init().
+ */
 void eap_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data)
 {
 	tls_connection_deinit(sm->ssl_ctx, data->conn);
-	free(data->tls_in);
-	free(data->tls_out);
+	os_free(data->tls_in);
+	os_free(data->tls_out);
 }
 
 
+/**
+ * eap_tls_derive_key - Derive a key based on TLS session data
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ * @data: Data for TLS processing
+ * @label: Label string for deriving the keys, e.g., "client EAP encryption"
+ * @len: Length of the key material to generate (usually 64 for MSK)
+ * Returns: Pointer to allocated key on success or %NULL on failure
+ *
+ * This function uses TLS-PRF to generate pseudo-random data based on the TLS
+ * session data (client/server random and master key). Each key type may use a
+ * different label to bind the key usage into the generated material.
+ *
+ * The caller is responsible for freeing the returned buffer.
+ */
 u8 * eap_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
-			char *label, size_t len)
+			const char *label, size_t len)
 {
 	struct tls_keys keys;
-	u8 *rnd;
-	u8 *out;
+	u8 *rnd = NULL, *out;
 
-	if (tls_connection_get_keys(sm->ssl_ctx, data->conn, &keys))
+	out = os_malloc(len);
+	if (out == NULL)
 		return NULL;
 
-	if (keys.eap_tls_prf && strcmp(label, "client EAP encryption") == 0) {
-		if (len > keys.eap_tls_prf_len)
-			return NULL;
-		out = malloc(len);
-		if (out == NULL)
-			return NULL;
-		memcpy(out, keys.eap_tls_prf, len);
+	/* First, try to use TLS library function for PRF, if available. */
+	if (tls_connection_prf(sm->ssl_ctx, data->conn, label, 0, out, len) ==
+	    0)
 		return out;
-	}
+
+	/*
+	 * TLS library did not support key generation, so get the needed TLS
+	 * session parameters and use an internal implementation of TLS PRF to
+	 * derive the key.
+	 */
+	if (tls_connection_get_keys(sm->ssl_ctx, data->conn, &keys))
+		goto fail;
 
 	if (keys.client_random == NULL || keys.server_random == NULL ||
 	    keys.master_key == NULL)
-		return NULL;
+		goto fail;
 
-	out = malloc(len);
-	rnd = malloc(keys.client_random_len + keys.server_random_len);
-	if (out == NULL || rnd == NULL) {
-		free(out);
-		free(rnd);
-		return NULL;
-	}
-	memcpy(rnd, keys.client_random, keys.client_random_len);
-	memcpy(rnd + keys.client_random_len, keys.server_random,
-	       keys.server_random_len);
+	rnd = os_malloc(keys.client_random_len + keys.server_random_len);
+	if (rnd == NULL)
+		goto fail;
+	os_memcpy(rnd, keys.client_random, keys.client_random_len);
+	os_memcpy(rnd + keys.client_random_len, keys.server_random,
+		  keys.server_random_len);
 
 	if (tls_prf(keys.master_key, keys.master_key_len,
 		    label, rnd, keys.client_random_len +
-		    keys.server_random_len, out, len)) {
-		free(rnd);
-		free(out);
-		return NULL;
-	}
-	free(rnd);
+		    keys.server_random_len, out, len))
+		goto fail;
+
+	os_free(rnd);
 	return out;
+
+fail:
+	os_free(out);
+	os_free(rnd);
+	return NULL;
 }
 
 
@@ -217,9 +289,11 @@
  * @out_len: Variable for returning output data length
  * @need_more_input: Variable for returning whether more input data is needed
  * to reassemble this TLS packet
- * Returns: Pointer to output data or %NULL on error
+ * Returns: Pointer to output data, %NULL on error or when more data is needed
+ * for the full message (in which case, *need_more_input is also set to 1).
  *
- * This function reassembles TLS fragments.
+ * This function reassembles TLS fragments. Caller must not free the returned
+ * data buffer since an internal pointer to it is maintained.
  */
 const u8 * eap_tls_data_reassemble(
 	struct eap_sm *sm, struct eap_ssl_data *data, const u8 *in_data,
@@ -231,7 +305,7 @@
 
 	if (data->tls_in_left > in_len || data->tls_in) {
 		if (data->tls_in_len + in_len == 0) {
-			free(data->tls_in);
+			os_free(data->tls_in);
 			data->tls_in = NULL;
 			data->tls_in_len = 0;
 			wpa_printf(MSG_WARNING, "SSL: Invalid reassembly "
@@ -242,16 +316,26 @@
 				   (unsigned long) in_len);
 			return NULL;
 		}
-		buf = realloc(data->tls_in, data->tls_in_len + in_len);
+		if (data->tls_in_len + in_len > 65536) {
+			/* Limit length to avoid rogue servers from causing
+			 * large memory allocations. */
+			os_free(data->tls_in);
+			data->tls_in = NULL;
+			data->tls_in_len = 0;
+			wpa_printf(MSG_INFO, "SSL: Too long TLS fragment (size"
+				   " over 64 kB)");
+			return NULL;
+		}
+		buf = os_realloc(data->tls_in, data->tls_in_len + in_len);
 		if (buf == NULL) {
-			free(data->tls_in);
+			os_free(data->tls_in);
 			data->tls_in = NULL;
 			data->tls_in_len = 0;
 			wpa_printf(MSG_INFO, "SSL: Could not allocate memory "
 				   "for TLS data");
 			return NULL;
 		}
-		memcpy(buf + data->tls_in_len, in_data, in_len);
+		os_memcpy(buf + data->tls_in_len, in_data, in_len);
 		data->tls_in = buf;
 		data->tls_in_len += in_len;
 		if (in_len > data->tls_in_left) {
@@ -269,10 +353,10 @@
 		}
 	} else {
 		data->tls_in_left = 0;
-		data->tls_in = malloc(in_len);
+		data->tls_in = os_malloc(in_len ? in_len : 1);
 		if (data->tls_in == NULL)
 			return NULL;
-		memcpy(data->tls_in, in_data, in_len);
+		os_memcpy(data->tls_in, in_data, in_len);
 		data->tls_in_len = in_len;
 	}
 
@@ -281,56 +365,161 @@
 }
 
 
+static int eap_tls_process_input(struct eap_sm *sm, struct eap_ssl_data *data,
+				 const u8 *in_data, size_t in_len,
+				 u8 **out_data, size_t *out_len)
+{
+	const u8 *msg;
+	size_t msg_len;
+	int need_more_input;
+	u8 *appl_data;
+	size_t appl_data_len;
+
+	msg = eap_tls_data_reassemble(sm, data, in_data, in_len,
+				      &msg_len, &need_more_input);
+	if (msg == NULL)
+		return need_more_input ? 1 : -1;
+
+	/* Full TLS message reassembled - continue handshake processing */
+	if (data->tls_out) {
+		/* This should not happen.. */
+		wpa_printf(MSG_INFO, "SSL: eap_tls_process_helper - pending "
+			   "tls_out data even though tls_out_len = 0");
+		os_free(data->tls_out);
+		WPA_ASSERT(data->tls_out == NULL);
+	}
+	appl_data = NULL;
+	data->tls_out = tls_connection_handshake(sm->ssl_ctx, data->conn,
+						 msg, msg_len,
+						 &data->tls_out_len,
+						 &appl_data, &appl_data_len);
+
+	/* Clear reassembled input data (if the buffer was needed). */
+	data->tls_in_left = data->tls_in_total = data->tls_in_len = 0;
+	os_free(data->tls_in);
+	data->tls_in = NULL;
+
+	if (appl_data &&
+	    tls_connection_established(sm->ssl_ctx, data->conn) &&
+	    !tls_connection_get_failed(sm->ssl_ctx, data->conn)) {
+		wpa_hexdump_key(MSG_MSGDUMP, "SSL: Application data",
+				appl_data, appl_data_len);
+		*out_data = appl_data;
+		*out_len = appl_data_len;
+		return 2;
+	}
+
+	os_free(appl_data);
+
+	return 0;
+}
+
+
+static int eap_tls_process_output(struct eap_ssl_data *data, EapType eap_type,
+				  int peap_version, u8 id, int ret,
+				  u8 **out_data, size_t *out_len)
+{
+	size_t len;
+	u8 *pos, *flags;
+	int more_fragments, length_included;
+	
+	wpa_printf(MSG_DEBUG, "SSL: %lu bytes left to be sent out (of total "
+		   "%lu bytes)",
+		   (unsigned long) data->tls_out_len - data->tls_out_pos,
+		   (unsigned long) data->tls_out_len);
+
+	len = data->tls_out_len - data->tls_out_pos;
+	if (len > data->tls_out_limit) {
+		more_fragments = 1;
+		len = data->tls_out_limit;
+		wpa_printf(MSG_DEBUG, "SSL: sending %lu bytes, more fragments "
+			   "will follow", (unsigned long) len);
+	} else
+		more_fragments = 0;
+
+	length_included = data->tls_out_pos == 0 &&
+		(data->tls_out_len > data->tls_out_limit ||
+		 data->include_tls_length);
+
+	*out_data = (u8 *)
+		eap_msg_alloc(EAP_VENDOR_IETF, eap_type, out_len,
+			      1 + length_included * 4 + len, EAP_CODE_RESPONSE,
+			      id, &pos);
+	if (*out_data == NULL)
+		return -1;
+
+	flags = pos++;
+	*flags = peap_version;
+	if (more_fragments)
+		*flags |= EAP_TLS_FLAGS_MORE_FRAGMENTS;
+	if (length_included) {
+		*flags |= EAP_TLS_FLAGS_LENGTH_INCLUDED;
+		WPA_PUT_BE32(pos, data->tls_out_len);
+		pos += 4;
+	}
+
+	os_memcpy(pos, &data->tls_out[data->tls_out_pos], len);
+	data->tls_out_pos += len;
+
+	if (!more_fragments) {
+		data->tls_out_len = 0;
+		data->tls_out_pos = 0;
+		os_free(data->tls_out);
+		data->tls_out = NULL;
+	}
+
+	return ret;
+}
+
+
+/**
+ * eap_tls_process_helper - Process TLS handshake message
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ * @data: Data for TLS processing
+ * @eap_type: EAP type (EAP_TYPE_TLS, EAP_TYPE_PEAP, ...)
+ * @peap_version: Version number for EAP-PEAP/TTLS
+ * @id: EAP identifier for the response
+ * @in_data: Message received from the server
+ * @in_len: Length of in_data
+ * @out_data: Buffer for returning a pointer to the response message
+ * @out_len: Buffer for returning the length of the response message
+ * Returns: 0 on success, 1 if more input data is needed, or -1 on failure
+ *
+ * This function can be used to process TLS handshake messages. It reassembles
+ * the received fragments and uses a TLS library to process the messages. The
+ * response data from the TLS library is fragmented to suitable output messages
+ * that the caller can send out.
+ *
+ * out_data is used to return the response message if the return value of this
+ * function is 0 or -1. In case of failure, the message is likely a TLS alarm
+ * message. The caller is responsible for freeing the allocated buffer if
+ * *out_data is not %NULL.
+ */
 int eap_tls_process_helper(struct eap_sm *sm, struct eap_ssl_data *data,
-			   int eap_type, int peap_version,
+			   EapType eap_type, int peap_version,
 			   u8 id, const u8 *in_data, size_t in_len,
 			   u8 **out_data, size_t *out_len)
 {
-	size_t len;
-	u8 *pos, *flags;
-	struct eap_hdr *resp;
 	int ret = 0;
 
 	WPA_ASSERT(data->tls_out_len == 0 || in_len == 0);
 	*out_len = 0;
+	*out_data = NULL;
 
 	if (data->tls_out_len == 0) {
 		/* No more data to send out - expect to receive more data from
 		 * the AS. */
-		const u8 *msg;
-		size_t msg_len;
-		int need_more_input;
-
-		msg = eap_tls_data_reassemble(sm, data, in_data, in_len,
-					      &msg_len, &need_more_input);
-		if (msg == NULL)
-			return need_more_input ? 1 : -1;
-
-		/* Full TLS message reassembled - continue handshake processing
-		 */
-		if (data->tls_out) {
-			/* This should not happen.. */
-			wpa_printf(MSG_INFO, "SSL: eap_tls_process_helper - "
-				   "pending tls_out data even though "
-				   "tls_out_len = 0");
-			free(data->tls_out);
-			WPA_ASSERT(data->tls_out == NULL);
-		}
-		data->tls_out = tls_connection_handshake(sm->ssl_ctx,
-							 data->conn,
-							 msg, msg_len,
-							 &data->tls_out_len);
-
-		/* Clear reassembled input data (if the buffer was needed). */
-		data->tls_in_left = data->tls_in_total = data->tls_in_len = 0;
-		free(data->tls_in);
-		data->tls_in = NULL;
+		int res = eap_tls_process_input(sm, data, in_data, in_len,
+						out_data, out_len);
+		if (res)
+			return res;
 	}
 
 	if (data->tls_out == NULL) {
 		data->tls_out_len = 0;
 		return -1;
 	}
+
 	if (tls_connection_get_failed(sm->ssl_ctx, data->conn)) {
 		wpa_printf(MSG_DEBUG, "SSL: Failed - tls_out available to "
 			   "report error");
@@ -340,90 +529,56 @@
 
 	if (data->tls_out_len == 0) {
 		/* TLS negotiation should now be complete since all other cases
-		 * needing more that should have been catched above based on
+		 * needing more data should have been caught above based on
 		 * the TLS Message Length field. */
 		wpa_printf(MSG_DEBUG, "SSL: No data to be sent out");
-		free(data->tls_out);
+		os_free(data->tls_out);
 		data->tls_out = NULL;
 		return 1;
 	}
 
-	wpa_printf(MSG_DEBUG, "SSL: %lu bytes left to be sent out (of total "
-		   "%lu bytes)",
-		   (unsigned long) data->tls_out_len - data->tls_out_pos,
-		   (unsigned long) data->tls_out_len);
-	resp = malloc(sizeof(struct eap_hdr) + 2 + 4 + data->tls_out_limit);
-	if (resp == NULL) {
-		*out_data = NULL;
-		return -1;
-	}
-	resp->code = EAP_CODE_RESPONSE;
-	resp->identifier = id;
-	pos = (u8 *) (resp + 1);
-	*pos++ = eap_type;
-	flags = pos++;
-	*flags = peap_version;
-	if (data->tls_out_pos == 0 &&
-	    (data->tls_out_len > data->tls_out_limit ||
-	     data->include_tls_length)) {
-		*flags |= EAP_TLS_FLAGS_LENGTH_INCLUDED;
-		*pos++ = (data->tls_out_len >> 24) & 0xff;
-		*pos++ = (data->tls_out_len >> 16) & 0xff;
-		*pos++ = (data->tls_out_len >> 8) & 0xff;
-		*pos++ = data->tls_out_len & 0xff;
-	}
-
-	len = data->tls_out_len - data->tls_out_pos;
-	if (len > data->tls_out_limit) {
-		*flags |= EAP_TLS_FLAGS_MORE_FRAGMENTS;
-		len = data->tls_out_limit;
-		wpa_printf(MSG_DEBUG, "SSL: sending %lu bytes, more fragments "
-			   "will follow", (unsigned long) len);
-	}
-	memcpy(pos, &data->tls_out[data->tls_out_pos], len);
-	data->tls_out_pos += len;
-	*out_len = (pos - (u8 *) resp) + len;
-	resp->length = host_to_be16(*out_len);
-	*out_data = (u8 *) resp;
-
-	if (!(*flags & EAP_TLS_FLAGS_MORE_FRAGMENTS)) {
-		data->tls_out_len = 0;
-		data->tls_out_pos = 0;
-		free(data->tls_out);
-		data->tls_out = NULL;
-	}
-
-	return ret;
+	return eap_tls_process_output(data, eap_type, peap_version, id, ret,
+				      out_data, out_len);
 }
 
 
+/**
+ * eap_tls_build_ack - Build a TLS ACK frames
+ * @data: Data for TLS processing
+ * @respDataLen: Buffer for returning the length of the response message
+ * @id: EAP identifier for the response
+ * @eap_type: EAP type (EAP_TYPE_TLS, EAP_TYPE_PEAP, ...)
+ * @peap_version: Version number for EAP-PEAP/TTLS
+ * Returns: Pointer to allocated ACK frames or %NULL on failure
+ */
 u8 * eap_tls_build_ack(struct eap_ssl_data *data, size_t *respDataLen, u8 id,
-		       int eap_type, int peap_version)
+		       EapType eap_type, int peap_version)
 {
 	struct eap_hdr *resp;
 	u8 *pos;
 
-	*respDataLen = sizeof(struct eap_hdr) + 2;
-	resp = malloc(*respDataLen);
+	resp = eap_msg_alloc(EAP_VENDOR_IETF, eap_type, respDataLen,
+			     1, EAP_CODE_RESPONSE, id, &pos);
 	if (resp == NULL)
 		return NULL;
 	wpa_printf(MSG_DEBUG, "SSL: Building ACK");
-	resp->code = EAP_CODE_RESPONSE;
-	resp->identifier = id;
-	resp->length = host_to_be16(*respDataLen);
-	pos = (u8 *) (resp + 1);
-	*pos++ = eap_type; /* Type */
 	*pos = peap_version; /* Flags */
 	return (u8 *) resp;
 }
 
 
+/**
+ * eap_tls_reauth_init - Re-initialize shared TLS for session resumption
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ * @data: Data for TLS processing
+ * Returns: 0 on success, -1 on failure
+ */
 int eap_tls_reauth_init(struct eap_sm *sm, struct eap_ssl_data *data)
 {
-	free(data->tls_in);
+	os_free(data->tls_in);
 	data->tls_in = NULL;
 	data->tls_in_len = data->tls_in_left = data->tls_in_total = 0;
-	free(data->tls_out);
+	os_free(data->tls_out);
 	data->tls_out = NULL;
 	data->tls_out_len = data->tls_out_pos = 0;
 
@@ -431,27 +586,50 @@
 }
 
 
+/**
+ * eap_tls_status - Get TLS status
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ * @data: Data for TLS processing
+ * @buf: Buffer for status information
+ * @buflen: Maximum buffer length
+ * @verbose: Whether to include verbose status information
+ * Returns: Number of bytes written to buf.
+ */
 int eap_tls_status(struct eap_sm *sm, struct eap_ssl_data *data, char *buf,
 		   size_t buflen, int verbose)
 {
 	char name[128];
-	int len = 0;
+	int len = 0, ret;
 
 	if (tls_get_cipher(sm->ssl_ctx, data->conn, name, sizeof(name)) == 0) {
-		len += snprintf(buf + len, buflen - len,
-				"EAP TLS cipher=%s\n", name);
+		ret = os_snprintf(buf + len, buflen - len,
+				  "EAP TLS cipher=%s\n", name);
+		if (ret < 0 || (size_t) ret >= buflen - len)
+			return len;
+		len += ret;
 	}
 
 	return len;
 }
 
 
+/**
+ * eap_tls_process_init - Initial validation and processing of EAP requests
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ * @data: Data for TLS processing
+ * @eap_type: EAP type (EAP_TYPE_TLS, EAP_TYPE_PEAP, ...)
+ * @ret: Return values from EAP request validation and processing
+ * @reqData: EAP request to be processed (eapReqData)
+ * @reqDataLen: Length of the EAP request
+ * @len: Buffer for returning length of the remaining payload
+ * @flags: Buffer for returning TLS flags
+ * Returns: Buffer to payload after TLS flags and length or %NULL on failure
+ */
 const u8 * eap_tls_process_init(struct eap_sm *sm, struct eap_ssl_data *data,
 				EapType eap_type, struct eap_method_ret *ret,
 				const u8 *reqData, size_t reqDataLen,
 				size_t *len, u8 *flags)
 {
-	const struct eap_hdr *req;
 	const u8 *pos;
 	size_t left;
 	unsigned int tls_msg_len;
@@ -462,12 +640,12 @@
 		return NULL;
 	}
 
-	pos = eap_hdr_validate(eap_type, reqData, reqDataLen, &left);
+	pos = eap_hdr_validate(EAP_VENDOR_IETF, eap_type, reqData, reqDataLen,
+			       &left);
 	if (pos == NULL) {
 		ret->ignore = TRUE;
 		return NULL;
 	}
-	req = (const struct eap_hdr *) reqData;
 	*flags = *pos++;
 	left--;
 	wpa_printf(MSG_DEBUG, "SSL: Received packet(len=%lu) - "
@@ -479,14 +657,13 @@
 			ret->ignore = TRUE;
 			return NULL;
 		}
-		tls_msg_len = (pos[0] << 24) | (pos[1] << 16) | (pos[2] << 8) |
-			pos[3];
+		tls_msg_len = WPA_GET_BE32(pos);
 		wpa_printf(MSG_DEBUG, "SSL: TLS Message Length: %d",
 			   tls_msg_len);
 		if (data->tls_in_left == 0) {
 			data->tls_in_total = tls_msg_len;
 			data->tls_in_left = tls_msg_len;
-			free(data->tls_in);
+			os_free(data->tls_in);
 			data->tls_in = NULL;
 			data->tls_in_len = 0;
 		}
Index: config_types.h
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/config_types.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -L contrib/wpa_supplicant/config_types.h -L contrib/wpa_supplicant/config_types.h -u -r1.1 -r1.2
--- contrib/wpa_supplicant/config_types.h
+++ contrib/wpa_supplicant/config_types.h
@@ -1,3 +1,17 @@
+/*
+ * hostapd / Shared configuration file defines
+ * Copyright (c) 2003-2005, Jouni Malinen <j at w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
 #ifndef CONFIG_TYPES_H
 #define CONFIG_TYPES_H
 
Index: crypto.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/crypto.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/crypto.c -L contrib/wpa_supplicant/crypto.c -u -r1.2 -r1.3
--- contrib/wpa_supplicant/crypto.c
+++ contrib/wpa_supplicant/crypto.c
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant / wrapper functions for libcrypto
- * Copyright (c) 2004-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2004-2005, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -12,9 +12,8 @@
  * See README and COPYING for more details.
  */
 
-#include <string.h>
-#include <sys/types.h>
-
+#include "includes.h"
+#include <openssl/opensslv.h>
 #include <openssl/md4.h>
 #include <openssl/md5.h>
 #include <openssl/sha.h>
@@ -36,7 +35,7 @@
 void md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
 {
 	MD4_CTX ctx;
-	int i;
+	size_t i;
 
 	MD4_Init(&ctx);
 	for (i = 0; i < num_elem; i++)
@@ -70,7 +69,7 @@
 void md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
 {
 	MD5_CTX ctx;
-	int i;
+	size_t i;
 
 	MD5_Init(&ctx);
 	for (i = 0; i < num_elem; i++)
@@ -82,7 +81,7 @@
 void sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
 {
 	SHA_CTX ctx;
-	int i;
+	size_t i;
 
 	SHA1_Init(&ctx);
 	for (i = 0; i < num_elem; i++)
@@ -91,24 +90,78 @@
 }
 
 
-void sha1_transform(u8 *state, const u8 data[64])
+static void sha1_transform(u8 *state, const u8 data[64])
 {
 	SHA_CTX context;
-	memset(&context, 0, sizeof(context));
-	memcpy(&context.h0, state, 5 * 4);
+	os_memset(&context, 0, sizeof(context));
+	os_memcpy(&context.h0, state, 5 * 4);
 	SHA1_Transform(&context, data);
-	memcpy(state, &context.h0, 5 * 4);
+	os_memcpy(state, &context.h0, 5 * 4);
+}
+
+
+int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen)
+{
+	u8 xkey[64];
+	u32 t[5], _t[5];
+	int i, j, m, k;
+	u8 *xpos = x;
+	u32 carry;
+
+	if (seed_len > sizeof(xkey))
+		seed_len = sizeof(xkey);
+
+	/* FIPS 186-2 + change notice 1 */
+
+	os_memcpy(xkey, seed, seed_len);
+	os_memset(xkey + seed_len, 0, 64 - seed_len);
+	t[0] = 0x67452301;
+	t[1] = 0xEFCDAB89;
+	t[2] = 0x98BADCFE;
+	t[3] = 0x10325476;
+	t[4] = 0xC3D2E1F0;
+
+	m = xlen / 40;
+	for (j = 0; j < m; j++) {
+		/* XSEED_j = 0 */
+		for (i = 0; i < 2; i++) {
+			/* XVAL = (XKEY + XSEED_j) mod 2^b */
+
+			/* w_i = G(t, XVAL) */
+			os_memcpy(_t, t, 20);
+			sha1_transform((u8 *) _t, xkey);
+			_t[0] = host_to_be32(_t[0]);
+			_t[1] = host_to_be32(_t[1]);
+			_t[2] = host_to_be32(_t[2]);
+			_t[3] = host_to_be32(_t[3]);
+			_t[4] = host_to_be32(_t[4]);
+			os_memcpy(xpos, _t, 20);
+
+			/* XKEY = (1 + XKEY + w_i) mod 2^b */
+			carry = 1;
+			for (k = 19; k >= 0; k--) {
+				carry += xkey[k] + xpos[k];
+				xkey[k] = carry & 0xff;
+				carry >>= 8;
+			}
+
+			xpos += 20;
+		}
+		/* x_j = w_0|w_1 */
+	}
+
+	return 0;
 }
 
 
 void * aes_encrypt_init(const u8 *key, size_t len)
 {
 	AES_KEY *ak;
-	ak = malloc(sizeof(*ak));
+	ak = os_malloc(sizeof(*ak));
 	if (ak == NULL)
 		return NULL;
 	if (AES_set_encrypt_key(key, 8 * len, ak) < 0) {
-		free(ak);
+		os_free(ak);
 		return NULL;
 	}
 	return ak;
@@ -123,18 +176,18 @@
 
 void aes_encrypt_deinit(void *ctx)
 {
-	free(ctx);
+	os_free(ctx);
 }
 
 
 void * aes_decrypt_init(const u8 *key, size_t len)
 {
 	AES_KEY *ak;
-	ak = malloc(sizeof(*ak));
+	ak = os_malloc(sizeof(*ak));
 	if (ak == NULL)
 		return NULL;
 	if (AES_set_decrypt_key(key, 8 * len, ak) < 0) {
-		free(ak);
+		os_free(ak);
 		return NULL;
 	}
 	return ak;
@@ -149,6 +202,6 @@
 
 void aes_decrypt_deinit(void *ctx)
 {
-	free(ctx);
+	os_free(ctx);
 }
 #endif /* EAP_TLS_FUNCS */
Index: crypto_gnutls.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/crypto_gnutls.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -L contrib/wpa_supplicant/crypto_gnutls.c -L contrib/wpa_supplicant/crypto_gnutls.c -u -r1.1 -r1.2
--- contrib/wpa_supplicant/crypto_gnutls.c
+++ contrib/wpa_supplicant/crypto_gnutls.c
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant / wrapper functions for libgcrypt
- * Copyright (c) 2004-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2004-2005, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -12,8 +12,7 @@
  * See README and COPYING for more details.
  */
 
-#include <stdio.h>
-#include <sys/types.h>
+#include "includes.h"
 #include <gcrypt.h>
 
 #include "common.h"
@@ -23,7 +22,7 @@
 {
 	gcry_md_hd_t hd;
 	unsigned char *p;
-	int i;
+	size_t i;
 
 	if (gcry_md_open(&hd, GCRY_MD_MD4, 0) != GPG_ERR_NO_ERROR)
 		return;
@@ -63,7 +62,7 @@
 {
 	gcry_md_hd_t hd;
 	unsigned char *p;
-	int i;
+	size_t i;
 
 	if (gcry_md_open(&hd, GCRY_MD_MD5, 0) != GPG_ERR_NO_ERROR)
 		return;
@@ -80,7 +79,7 @@
 {
 	gcry_md_hd_t hd;
 	unsigned char *p;
-	int i;
+	size_t i;
 
 	if (gcry_md_open(&hd, GCRY_MD_SHA1, 0) != GPG_ERR_NO_ERROR)
 		return;
@@ -93,9 +92,10 @@
 }
 
 
-void sha1_transform(u8 *state, const u8 data[64])
+int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen)
 {
 	/* FIX: how to do this with libgcrypt? */
+	return -1;
 }
 
 
Index: eapol_test.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/eapol_test.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/eapol_test.c -L contrib/wpa_supplicant/eapol_test.c -u -r1.2 -r1.3
--- contrib/wpa_supplicant/eapol_test.c
+++ contrib/wpa_supplicant/eapol_test.c
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant - test code
- * Copyright (c) 2003-2006, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2003-2006, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -15,22 +15,13 @@
  * Not used in production version.
  */
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <unistd.h>
-#include <ctype.h>
-#include <string.h>
-#include <signal.h>
-#ifndef CONFIG_NATIVE_WINDOWS
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#endif /* CONFIG_NATIVE_WINDOWS */
+#include "includes.h"
 #include <assert.h>
 
 #include "common.h"
 #include "config.h"
 #include "eapol_sm.h"
+#include "eap.h"
 #include "eloop.h"
 #include "wpa.h"
 #include "eap_i.h"
@@ -46,7 +37,7 @@
 extern int wpa_debug_level;
 extern int wpa_debug_show_keys;
 
-struct wpa_driver_ops *wpa_supplicant_drivers[] = { };
+struct wpa_driver_ops *wpa_supplicant_drivers[] = { NULL };
 
 
 struct eapol_test_data {
@@ -74,6 +65,9 @@
 
 	u8 *eap_identity;
 	size_t eap_identity_len;
+
+	char *connect_info;
+	u8 own_addr[ETH_ALEN];
 };
 
 static struct eapol_test_data eapol_test;
@@ -82,15 +76,15 @@
 static void send_eap_request_identity(void *eloop_ctx, void *timeout_ctx);
 
 
-void hostapd_logger(void *ctx, u8 *addr, unsigned int module, int level,
+void hostapd_logger(void *ctx, const u8 *addr, unsigned int module, int level,
 		    char *fmt, ...)
 {
 	char *format;
 	int maxlen;
 	va_list ap;
 
-	maxlen = strlen(fmt) + 100;
-	format = malloc(maxlen);
+	maxlen = os_strlen(fmt) + 100;
+	format = os_malloc(maxlen);
 	if (!format)
 		return;
 
@@ -98,15 +92,15 @@
 
 
 	if (addr)
-		snprintf(format, maxlen, "STA " MACSTR ": %s",
-			 MAC2STR(addr), fmt);
+		os_snprintf(format, maxlen, "STA " MACSTR ": %s",
+			    MAC2STR(addr), fmt);
 	else
-		snprintf(format, maxlen, "%s", fmt);
+		os_snprintf(format, maxlen, "%s", fmt);
 
 	vprintf(format, ap);
 	printf("\n");
 
-	free(format);
+	os_free(format);
 
 	va_end(ap);
 }
@@ -119,7 +113,7 @@
 		return NULL;
 
 	if (addr->af == AF_INET) {
-		snprintf(buf, buflen, "%s", inet_ntoa(addr->u.v4));
+		os_snprintf(buf, buflen, "%s", inet_ntoa(addr->u.v4));
 	} else {
 		buf[0] = '\0';
 	}
@@ -134,6 +128,12 @@
 }
 
 
+int hostapd_ip_diff(struct hostapd_ip_addr *a, struct hostapd_ip_addr *b)
+{
+	return 0;
+}
+
+
 static void ieee802_1x_encapsulate_radius(struct eapol_test_data *e,
 					  const u8 *eap, size_t len)
 {
@@ -160,11 +160,11 @@
 	if (len > sizeof(*hdr) && hdr->code == EAP_CODE_RESPONSE &&
 	    pos[0] == EAP_TYPE_IDENTITY) {
 		pos++;
-		free(e->eap_identity);
+		os_free(e->eap_identity);
 		e->eap_identity_len = len - sizeof(*hdr) - 1;
-		e->eap_identity = malloc(e->eap_identity_len);
+		e->eap_identity = os_malloc(e->eap_identity_len);
 		if (e->eap_identity) {
-			memcpy(e->eap_identity, pos, e->eap_identity_len);
+			os_memcpy(e->eap_identity, pos, e->eap_identity_len);
 			wpa_hexdump(MSG_DEBUG, "Learned identity from "
 				    "EAP-Response-Identity",
 				    e->eap_identity, e->eap_identity_len);
@@ -184,10 +184,10 @@
 		goto fail;
 	}
 
-	snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT,
-		 MAC2STR(e->wpa_s->own_addr));
+	os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT,
+		    MAC2STR(e->wpa_s->own_addr));
 	if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLING_STATION_ID,
-				 (u8 *) buf, strlen(buf))) {
+				 (u8 *) buf, os_strlen(buf))) {
 		printf("Could not add Calling-Station-Id\n");
 		goto fail;
 	}
@@ -206,9 +206,9 @@
 		goto fail;
 	}
 
-	snprintf(buf, sizeof(buf), "CONNECT 11Mbps 802.11b");
+	os_snprintf(buf, sizeof(buf), "%s", e->connect_info);
 	if (!radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO,
-				 (u8 *) buf, strlen(buf))) {
+				 (u8 *) buf, os_strlen(buf))) {
 		printf("Could not add Connect-Info\n");
 		goto fail;
 	}
@@ -240,7 +240,7 @@
 
  fail:
 	radius_msg_free(msg);
-	free(msg);
+	os_free(msg);
 }
 
 
@@ -295,23 +295,27 @@
 
 	if (eapol_sm_get_key(e->wpa_s->eapol, pmk, PMK_LEN) == 0) {
 		wpa_hexdump(MSG_DEBUG, "PMK from EAPOL", pmk, PMK_LEN);
-		if (memcmp(pmk, e->authenticator_pmk, PMK_LEN) != 0)
+		if (os_memcmp(pmk, e->authenticator_pmk, PMK_LEN) != 0) {
 			printf("WARNING: PMK mismatch\n");
-		else if (e->radius_access_accept_received)
+			wpa_hexdump(MSG_DEBUG, "PMK from AS",
+				    e->authenticator_pmk, PMK_LEN);
+		} else if (e->radius_access_accept_received)
 			ret = 0;
 	} else if (e->authenticator_pmk_len == 16 &&
 		   eapol_sm_get_key(e->wpa_s->eapol, pmk, 16) == 0) {
 		wpa_hexdump(MSG_DEBUG, "LEAP PMK from EAPOL", pmk, 16);
-		if (memcmp(pmk, e->authenticator_pmk, 16) != 0)
+		if (os_memcmp(pmk, e->authenticator_pmk, 16) != 0) {
 			printf("WARNING: PMK mismatch\n");
-		else if (e->radius_access_accept_received)
+			wpa_hexdump(MSG_DEBUG, "PMK from AS",
+				    e->authenticator_pmk, 16);
+		} else if (e->radius_access_accept_received)
 			ret = 0;
 	} else if (e->radius_access_accept_received && e->no_mppe_keys) {
 		/* No keying material expected */
 		ret = 0;
 	}
 
-	if (ret)
+	if (ret && !e->no_mppe_keys)
 		e->num_mppe_mismatch++;
 	else if (!e->no_mppe_keys)
 		e->num_mppe_ok++;
@@ -340,12 +344,11 @@
 	struct eapol_config eapol_conf;
 	struct eapol_ctx *ctx;
 
-	ctx = malloc(sizeof(*ctx));
+	ctx = os_zalloc(sizeof(*ctx));
 	if (ctx == NULL) {
 		printf("Failed to allocate EAPOL context.\n");
 		return -1;
 	}
-	memset(ctx, 0, sizeof(*ctx));
 	ctx->ctx = wpa_s;
 	ctx->msg_ctx = wpa_s;
 	ctx->scard_ctx = wpa_s->scard;
@@ -363,13 +366,13 @@
 
 	wpa_s->eapol = eapol_sm_init(ctx);
 	if (wpa_s->eapol == NULL) {
-		free(ctx);
+		os_free(ctx);
 		printf("Failed to initialize EAPOL state machines.\n");
 		return -1;
 	}
 
 	wpa_s->current_ssid = ssid;
-	memset(&eapol_conf, 0, sizeof(eapol_conf));
+	os_memset(&eapol_conf, 0, sizeof(eapol_conf));
 	eapol_conf.accept_802_1x_keys = 1;
 	eapol_conf.required_keys = 0;
 	eapol_conf.fast_reauth = wpa_s->conf->fast_reauth;
@@ -390,23 +393,26 @@
 			     struct wpa_supplicant *wpa_s)
 {
 	radius_client_deinit(e->radius);
-	free(e->last_eap_radius);
+	os_free(e->last_eap_radius);
 	if (e->last_recv_radius) {
 		radius_msg_free(e->last_recv_radius);
-		free(e->last_recv_radius);
+		os_free(e->last_recv_radius);
 	}
-	free(e->eap_identity);
+	os_free(e->eap_identity);
 	e->eap_identity = NULL;
 	eapol_sm_deinit(wpa_s->eapol);
 	wpa_s->eapol = NULL;
 	if (e->radius_conf && e->radius_conf->auth_server) {
-		free(e->radius_conf->auth_server->shared_secret);
-		free(e->radius_conf->auth_server);
+		os_free(e->radius_conf->auth_server->shared_secret);
+		os_free(e->radius_conf->auth_server);
 	}
-	free(e->radius_conf);
+	os_free(e->radius_conf);
 	e->radius_conf = NULL;
 	scard_deinit(wpa_s->scard);
-	wpa_supplicant_ctrl_iface_deinit(wpa_s);
+	if (wpa_s->ctrl_iface) {
+		wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
+		wpa_s->ctrl_iface = NULL;
+	}
 	wpa_config_free(wpa_s->conf);
 }
 
@@ -458,6 +464,9 @@
 	case EAP_TYPE_GTC: return "GTC";
 	case EAP_TYPE_MD5: return "MD5";
 	case EAP_TYPE_OTP: return "OTP";
+	case EAP_TYPE_FAST: return "FAST";
+	case EAP_TYPE_SAKE: return "SAKE";
+	case EAP_TYPE_PSK: return "PSK";
 	default: return "Unknown";
 	}
 }
@@ -484,7 +493,7 @@
 		 * attribute */
 		wpa_printf(MSG_DEBUG, "could not extract "
 			       "EAP-Message from RADIUS message");
-		free(e->last_eap_radius);
+		os_free(e->last_eap_radius);
 		e->last_eap_radius = NULL;
 		e->last_eap_radius_len = 0;
 		return;
@@ -493,7 +502,7 @@
 	if (len < sizeof(*hdr)) {
 		wpa_printf(MSG_DEBUG, "too short EAP packet "
 			       "received from authentication server");
-		free(eap);
+		os_free(eap);
 		return;
 	}
 
@@ -503,26 +512,26 @@
 	hdr = (struct eap_hdr *) eap;
 	switch (hdr->code) {
 	case EAP_CODE_REQUEST:
-		snprintf(buf, sizeof(buf), "EAP-Request-%s (%d)",
-			 eap_type >= 0 ? eap_type_text(eap_type) : "??",
-			 eap_type);
+		os_snprintf(buf, sizeof(buf), "EAP-Request-%s (%d)",
+			    eap_type >= 0 ? eap_type_text(eap_type) : "??",
+			    eap_type);
 		break;
 	case EAP_CODE_RESPONSE:
-		snprintf(buf, sizeof(buf), "EAP Response-%s (%d)",
-			 eap_type >= 0 ? eap_type_text(eap_type) : "??",
-			 eap_type);
+		os_snprintf(buf, sizeof(buf), "EAP Response-%s (%d)",
+			    eap_type >= 0 ? eap_type_text(eap_type) : "??",
+			    eap_type);
 		break;
 	case EAP_CODE_SUCCESS:
-		snprintf(buf, sizeof(buf), "EAP Success");
+		os_snprintf(buf, sizeof(buf), "EAP Success");
 		/* LEAP uses EAP Success within an authentication, so must not
 		 * stop here with eloop_terminate(); */
 		break;
 	case EAP_CODE_FAILURE:
-		snprintf(buf, sizeof(buf), "EAP Failure");
+		os_snprintf(buf, sizeof(buf), "EAP Failure");
 		eloop_terminate();
 		break;
 	default:
-		snprintf(buf, sizeof(buf), "unknown EAP code");
+		os_snprintf(buf, sizeof(buf), "unknown EAP code");
 		wpa_hexdump(MSG_DEBUG, "Decapsulated EAP packet", eap, len);
 		break;
 	}
@@ -532,21 +541,21 @@
 
 	/* sta->eapol_sm->be_auth.idFromServer = hdr->identifier; */
 
-	free(e->last_eap_radius);
+	os_free(e->last_eap_radius);
 	e->last_eap_radius = eap;
 	e->last_eap_radius_len = len;
 
 	{
-		struct ieee802_1x_hdr *hdr;
-		hdr = malloc(sizeof(*hdr) + len);
-		assert(hdr != NULL);
-		hdr->version = EAPOL_VERSION;
-		hdr->type = IEEE802_1X_TYPE_EAP_PACKET;
-		hdr->length = htons(len);
-		memcpy((u8 *) (hdr + 1), eap, len);
+		struct ieee802_1x_hdr *dot1x;
+		dot1x = os_malloc(sizeof(*dot1x) + len);
+		assert(dot1x != NULL);
+		dot1x->version = EAPOL_VERSION;
+		dot1x->type = IEEE802_1X_TYPE_EAP_PACKET;
+		dot1x->length = htons(len);
+		os_memcpy((u8 *) (dot1x + 1), eap, len);
 		eapol_sm_rx_eapol(e->wpa_s->eapol, e->wpa_s->bssid,
-				  (u8 *) hdr, sizeof(*hdr) + len);
-		free(hdr);
+				  (u8 *) dot1x, sizeof(*dot1x) + len);
+		os_free(dot1x);
 	}
 }
 
@@ -560,7 +569,7 @@
 	keys = radius_msg_get_ms_keys(msg, req, shared_secret,
 				      shared_secret_len);
 	if (keys && keys->send == NULL && keys->recv == NULL) {
-		free(keys);
+		os_free(keys);
 		keys = radius_msg_get_cisco_keys(msg, req, shared_secret,
 						 shared_secret_len);
 	}
@@ -576,13 +585,13 @@
 			e->authenticator_pmk_len =
 				keys->recv_len > PMK_LEN ? PMK_LEN :
 				keys->recv_len;
-			memcpy(e->authenticator_pmk, keys->recv,
-			       e->authenticator_pmk_len);
+			os_memcpy(e->authenticator_pmk, keys->recv,
+				  e->authenticator_pmk_len);
 		}
 
-		free(keys->send);
-		free(keys->recv);
-		free(keys);
+		os_free(keys->send);
+		os_free(keys->recv);
+		os_free(keys);
 	}
 }
 
@@ -623,7 +632,7 @@
 
 	if (e->last_recv_radius) {
 		radius_msg_free(e->last_recv_radius);
-		free(e->last_recv_radius);
+		os_free(e->last_recv_radius);
 	}
 
 	e->last_recv_radius = msg;
@@ -659,18 +668,16 @@
 	int res;
 
 	wpa_s->bssid[5] = 1;
-	wpa_s->own_addr[5] = 2;
+	os_memcpy(wpa_s->own_addr, e->own_addr, ETH_ALEN);
 	e->own_ip_addr.s_addr = htonl((127 << 24) | 1);
-	strncpy(wpa_s->ifname, "test", sizeof(wpa_s->ifname));
+	os_strncpy(wpa_s->ifname, "test", sizeof(wpa_s->ifname));
 
-	e->radius_conf = malloc(sizeof(struct hostapd_radius_servers));
+	e->radius_conf = os_zalloc(sizeof(struct hostapd_radius_servers));
 	assert(e->radius_conf != NULL);
-	memset(e->radius_conf, 0, sizeof(struct hostapd_radius_servers));
 	e->radius_conf->num_auth_servers = 1;
-	as = malloc(sizeof(struct hostapd_radius_server));
+	as = os_zalloc(sizeof(struct hostapd_radius_server));
 	assert(as != NULL);
-	memset(as, 0, sizeof(*as));
-#ifdef CONFIG_NATIVE_WINDOWS
+#if defined(CONFIG_NATIVE_WINDOWS) || defined(CONFIG_ANSI_C_EXTRA)
 	{
 		int a[4];
 		u8 *pos;
@@ -681,13 +688,13 @@
 		*pos++ = a[2];
 		*pos++ = a[3];
 	}
-#else /* CONFIG_NATIVE_WINDOWS */
+#else /* CONFIG_NATIVE_WINDOWS or CONFIG_ANSI_C_EXTRA */
 	inet_aton(authsrv, &as->addr.u.v4);
-#endif /* CONFIG_NATIVE_WINDOWS */
+#endif /* CONFIG_NATIVE_WINDOWS or CONFIG_ANSI_C_EXTRA */
 	as->addr.af = AF_INET;
 	as->port = port;
-	as->shared_secret = (u8 *) strdup(secret);
-	as->shared_secret_len = strlen(secret);
+	as->shared_secret = (u8 *) os_strdup(secret);
+	as->shared_secret_len = os_strlen(secret);
 	e->radius_conf->auth_server = as;
 	e->radius_conf->auth_servers = as;
 	e->radius_conf->msg_dumps = 1;
@@ -706,7 +713,7 @@
 	struct scard_data *scard;
 	size_t len;
 	char imsi[20];
-	unsigned char rand[16];
+	unsigned char _rand[16];
 #ifdef PCSC_FUNCS
 	unsigned char sres[4];
 	unsigned char kc[8];
@@ -715,7 +722,8 @@
 	unsigned char rand_[num_triplets][16];
 	unsigned char sres_[num_triplets][4];
 	unsigned char kc_[num_triplets][8];
-	int i, j, res;
+	int i, res;
+	size_t j;
 
 #define AKA_RAND_LEN 16
 #define AKA_AUTN_LEN 16
@@ -746,16 +754,16 @@
 	wpa_hexdump_ascii(MSG_DEBUG, "SCARD: IMSI", (u8 *) imsi, len);
 	/* NOTE: Permanent Username: 1 | IMSI */
 
-	memset(rand, 0, sizeof(rand));
-	if (scard_gsm_auth(scard, rand, sres, kc))
+	os_memset(_rand, 0, sizeof(_rand));
+	if (scard_gsm_auth(scard, _rand, sres, kc))
 		goto failed;
 
-	memset(rand, 0xff, sizeof(rand));
-	if (scard_gsm_auth(scard, rand, sres, kc))
+	os_memset(_rand, 0xff, sizeof(_rand));
+	if (scard_gsm_auth(scard, _rand, sres, kc))
 		goto failed;
 
 	for (i = 0; i < num_triplets; i++) {
-		memset(rand_[i], i, sizeof(rand_[i]));
+		os_memset(rand_[i], i, sizeof(rand_[i]));
 		if (scard_gsm_auth(scard, rand_[i], sres_[i], kc_[i]))
 			goto failed;
 	}
@@ -779,9 +787,9 @@
 	wpa_printf(MSG_DEBUG, "Trying to use UMTS authentication");
 
 	/* seq 39 (0x28) */
-	memset(aka_rand, 0xaa, 16);
-	memcpy(aka_autn, "\x86\x71\x31\xcb\xa2\xfc\x61\xdf"
-	       "\xa3\xb3\x97\x9d\x07\x32\xa2\x12", 16);
+	os_memset(aka_rand, 0xaa, 16);
+	os_memcpy(aka_autn, "\x86\x71\x31\xcb\xa2\xfc\x61\xdf"
+		  "\xa3\xb3\x97\x9d\x07\x32\xa2\x12", 16);
 
 	res = scard_umts_auth(scard, aka_rand, aka_autn, aka_res, &aka_res_len,
 			      aka_ik, aka_ck, aka_auts);
@@ -811,18 +819,19 @@
 	struct scard_data *scard;
 	size_t len;
 	char imsi[20];
-	unsigned char rand[16];
+	unsigned char _rand[16];
 	unsigned char sres[4];
 	unsigned char kc[8];
 	int num_triplets;
-	int i, j;
+	int i;
+	size_t j;
 
 	if (argc < 2 || ((num_triplets = atoi(argv[1])) <= 0)) {
 		printf("invalid parameters for sim command\n");
 		return -1;
 	}
 
-	if (argc <= 2 || strcmp(argv[2], "debug") != 0) {
+	if (argc <= 2 || os_strcmp(argv[2], "debug") != 0) {
 		/* disable debug output */
 		wpa_debug_level = 99;
 	}
@@ -845,8 +854,8 @@
 	}
 
 	for (i = 0; i < num_triplets; i++) {
-		memset(rand, i, sizeof(rand));
-		if (scard_gsm_auth(scard, rand, sres, kc))
+		os_memset(_rand, i, sizeof(_rand));
+		if (scard_gsm_auth(scard, _rand, sres, kc))
 			break;
 
 		/* IMSI:Kc:SRES:RAND */
@@ -860,7 +869,7 @@
 			printf("%02X", sres[j]);
 		printf(":");
 		for (j = 0; j < 16; j++)
-			printf("%02X", rand[j]);
+			printf("%02X", _rand[j]);
 		printf("\n");
 	}
 
@@ -883,11 +892,13 @@
 {
 	printf("usage:\n"
 	       "eapol_test [-nWS] -c<conf> [-a<AS IP>] [-p<AS port>] "
-	       "[-s<AS secret>] [-r<count>]\n"
+	       "[-s<AS secret>] \\\n"
+	       "           [-r<count>] [-t<timeout>] [-C<Connect-Info>] \\\n"
+	       "           [-M<client MAC address>]\n"
 	       "eapol_test scard\n"
 	       "eapol_test sim <PIN> <num triplets> [debug]\n"
-	       "\n"
-	       "options:\n"
+	       "\n");
+	printf("options:\n"
 	       "  -c<conf> = configuration file\n"
 	       "  -a<AS IP> = IP address of the authentication server, "
 	       "default 127.0.0.1\n"
@@ -898,7 +909,13 @@
 	       "  -r<count> = number of re-authentications\n"
 	       "  -W = wait for a control interface monitor before starting\n"
 	       "  -S = save configuration after authentiation\n"
-	       "  -n = no MPPE keys expected\n");
+	       "  -n = no MPPE keys expected\n"
+	       "  -t<timeout> = sets timeout in seconds (default: 30 s)\n"
+	       "  -C<Connect-Info> = RADIUS Connect-Info (default: "
+	       "CONNECT 11Mbps 802.11b)\n"
+	       "  -M<client MAC address> = Set own MAC address "
+	       "(Calling-Station-Id,\n"
+	       "                           default: 02:00:00:00:00:01)\n");
 }
 
 
@@ -910,22 +927,20 @@
 	int as_port = 1812;
 	char *as_secret = "radius";
 	char *conf = NULL;
+	int timeout = 30;
 
-#ifdef CONFIG_NATIVE_WINDOWS
-	WSADATA wsaData;
-	if (WSAStartup(MAKEWORD(2, 0), &wsaData)) {
-		printf("Could not find a usable WinSock.dll\n");
+	if (os_program_init())
 		return -1;
-	}
-#endif /* CONFIG_NATIVE_WINDOWS */
 
-	memset(&eapol_test, 0, sizeof(eapol_test));
+	os_memset(&eapol_test, 0, sizeof(eapol_test));
+	eapol_test.connect_info = "CONNECT 11Mbps 802.11b";
+	os_memcpy(eapol_test.own_addr, "\x02\x00\x00\x00\x00\x01", ETH_ALEN);
 
 	wpa_debug_level = 0;
 	wpa_debug_show_keys = 1;
 
 	for (;;) {
-		c = getopt(argc, argv, "a:c:np:r:s:SW");
+		c = getopt(argc, argv, "a:c:C:M:np:r:s:St:W");
 		if (c < 0)
 			break;
 		switch (c) {
@@ -935,6 +950,15 @@
 		case 'c':
 			conf = optarg;
 			break;
+		case 'C':
+			eapol_test.connect_info = optarg;
+			break;
+		case 'M':
+			if (hwaddr_aton(optarg, eapol_test.own_addr)) {
+				usage();
+				return -1;
+			}
+			break;
 		case 'n':
 			eapol_test.no_mppe_keys++;
 			break;
@@ -950,6 +974,9 @@
 		case 'S':
 			save_config++;
 			break;
+		case 't':
+			timeout = atoi(optarg);
+			break;
 		case 'W':
 			wait_for_monitor++;
 			break;
@@ -959,11 +986,11 @@
 		}
 	}
 
-	if (argc > optind && strcmp(argv[optind], "scard") == 0) {
+	if (argc > optind && os_strcmp(argv[optind], "scard") == 0) {
 		return scard_test();
 	}
 
-	if (argc > optind && strcmp(argv[optind], "sim") == 0) {
+	if (argc > optind && os_strcmp(argv[optind], "sim") == 0) {
 		return scard_get_triplets(argc - optind - 1,
 					  &argv[optind + 1]);
 	}
@@ -974,9 +1001,17 @@
 		return -1;
 	}
 
-	eloop_init(&wpa_s);
+	if (eap_peer_register_methods()) {
+		wpa_printf(MSG_ERROR, "Failed to register EAP methods");
+		return -1;
+	}
 
-	memset(&wpa_s, 0, sizeof(wpa_s));
+	if (eloop_init(&wpa_s)) {
+		wpa_printf(MSG_ERROR, "Failed to initialize event loop");
+		return -1;
+	}
+
+	os_memset(&wpa_s, 0, sizeof(wpa_s));
 	eapol_test.wpa_s = &wpa_s;
 	wpa_s.conf = wpa_config_read(conf);
 	if (wpa_s.conf == NULL) {
@@ -989,7 +1024,8 @@
 	}
 
 	wpa_init_conf(&eapol_test, &wpa_s, as_addr, as_port, as_secret);
-	if (wpa_supplicant_ctrl_iface_init(&wpa_s)) {
+	wpa_s.ctrl_iface = wpa_supplicant_ctrl_iface_init(&wpa_s);
+	if (wpa_s.ctrl_iface == NULL) {
 		printf("Failed to initialize control interface '%s'.\n"
 		       "You may have another eapol_test process already "
 		       "running or the file was\n"
@@ -1007,18 +1043,17 @@
 		return -1;
 
 	if (wait_for_monitor)
-		wpa_supplicant_ctrl_iface_wait(&wpa_s);
+		wpa_supplicant_ctrl_iface_wait(wpa_s.ctrl_iface);
 
-	eloop_register_timeout(30, 0, eapol_test_timeout, &eapol_test, NULL);
+	eloop_register_timeout(timeout, 0, eapol_test_timeout, &eapol_test,
+			       NULL);
 	eloop_register_timeout(0, 0, send_eap_request_identity, &wpa_s, NULL);
-	eloop_register_signal(SIGINT, eapol_test_terminate, NULL);
-	eloop_register_signal(SIGTERM, eapol_test_terminate, NULL);
-#ifndef CONFIG_NATIVE_WINDOWS
-	eloop_register_signal(SIGHUP, eapol_test_terminate, NULL);
-#endif /* CONFIG_NATIVE_WINDOWS */
+	eloop_register_signal_terminate(eapol_test_terminate, NULL);
+	eloop_register_signal_reconfig(eapol_test_terminate, NULL);
 	eloop_run();
 
-	if (eapol_test_compare_pmk(&eapol_test) == 0)
+	if (eapol_test_compare_pmk(&eapol_test) == 0 ||
+	    eapol_test.no_mppe_keys)
 		ret = 0;
 	if (eapol_test.auth_timed_out)
 		ret = -2;
@@ -1030,6 +1065,8 @@
 
 	test_eapol_clean(&eapol_test, &wpa_s);
 
+	eap_peer_unregister_methods();
+
 	eloop_destroy();
 
 	printf("MPPE keys OK: %d  mismatch: %d\n",
@@ -1041,9 +1078,7 @@
 	else
 		printf("SUCCESS\n");
 
-#ifdef CONFIG_NATIVE_WINDOWS
-	WSACleanup();
-#endif /* CONFIG_NATIVE_WINDOWS */
+	os_program_deinit();
 
 	return ret;
 }
Index: driver_ndis.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/driver_ndis.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/driver_ndis.c -L contrib/wpa_supplicant/driver_ndis.c -u -r1.2 -r1.3
--- contrib/wpa_supplicant/driver_ndis.c
+++ contrib/wpa_supplicant/driver_ndis.c
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant - Windows/NDIS driver interface
- * Copyright (c) 2004-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2004-2006, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -12,13 +12,27 @@
  * See README and COPYING for more details.
  */
 
-#include <stdlib.h>
+#ifdef __CYGWIN__
+/* Avoid some header file conflicts by not including standard headers for
+ * cygwin builds when Packet32.h is included. */
+#include "build_config.h"
+int close(int fd);
+#else /* __CYGWIN__ */
+#include "includes.h"
+#endif /* __CYGWIN__ */
+#ifdef CONFIG_USE_NDISUIO
+#include <winsock2.h>
+#else /* CONFIG_USE_NDISUIO */
 #include <Packet32.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/unistd.h>
+#endif /* CONFIG_USE_NDISUIO */
 #include <ntddndis.h>
 
+#ifdef _WIN32_WCE
+#include <winioctl.h>
+#include <nuiouser.h>
+#include <devload.h>
+#endif /* _WIN32_WCE */
+
 #include "common.h"
 #include "driver.h"
 #include "wpa_supplicant.h"
@@ -28,8 +42,14 @@
 #include "driver_ndis.h"
 
 int wpa_driver_register_event_cb(struct wpa_driver_ndis_data *drv);
+void wpa_driver_ndis_event_pipe_cb(void *eloop_data, void *user_data);
 
+static void wpa_driver_ndis_deinit(void *priv);
 static void wpa_driver_ndis_poll(void *drv);
+static void wpa_driver_ndis_poll_timeout(void *eloop_ctx, void *timeout_ctx);
+static int wpa_driver_ndis_adapter_init(struct wpa_driver_ndis_data *drv);
+static int wpa_driver_ndis_adapter_open(struct wpa_driver_ndis_data *drv);
+static void wpa_driver_ndis_adapter_close(struct wpa_driver_ndis_data *drv);
 
 
 /* FIX: to be removed once this can be compiled with the complete NDIS
@@ -216,7 +236,7 @@
 	ULONG Length;
 	ULONG Version;
 	ULONG NoOfPMKIDs;
-	ULONG NoOfAuthEncryptPairSupported;
+	ULONG NoOfAuthEncryptPairsSupported;
 	NDIS_802_11_AUTHENTICATION_ENCRYPTION
 		AuthenticationEncryptionSupported[1];
 } NDIS_802_11_CAPABILITY;
@@ -268,20 +288,173 @@
 #define NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR		0x06
 #define NDIS_802_11_AUTH_REQUEST_GROUP_ERROR		0x0E
 
-#endif
+#endif /* OID_802_11_BSSID */
+
+
+#ifndef OID_802_11_PMKID
+/* Platform SDK for XP did not include WPA2, so add needed definitions */
+
+#define OID_802_11_CAPABILITY 			0x0d010122
+#define OID_802_11_PMKID 			0x0d010123
+
+#define Ndis802_11AuthModeWPA2 6
+#define Ndis802_11AuthModeWPA2PSK 7
+
+#define Ndis802_11StatusType_PMKID_CandidateList 2
+
+typedef struct NDIS_802_11_AUTHENTICATION_ENCRYPTION {
+	NDIS_802_11_AUTHENTICATION_MODE AuthModeSupported;
+	NDIS_802_11_ENCRYPTION_STATUS EncryptStatusSupported;
+} NDIS_802_11_AUTHENTICATION_ENCRYPTION;
+
+typedef struct NDIS_802_11_CAPABILITY {
+	ULONG Length;
+	ULONG Version;
+	ULONG NoOfPMKIDs;
+	ULONG NoOfAuthEncryptPairsSupported;
+	NDIS_802_11_AUTHENTICATION_ENCRYPTION
+		AuthenticationEncryptionSupported[1];
+} NDIS_802_11_CAPABILITY;
+
+typedef UCHAR NDIS_802_11_PMKID_VALUE[16];
+
+typedef struct BSSID_INFO {
+	NDIS_802_11_MAC_ADDRESS BSSID;
+	NDIS_802_11_PMKID_VALUE PMKID;
+} BSSID_INFO;
+
+typedef struct NDIS_802_11_PMKID {
+	ULONG Length;
+	ULONG BSSIDInfoCount;
+	BSSID_INFO BSSIDInfo[1];
+} NDIS_802_11_PMKID;
+
+typedef struct PMKID_CANDIDATE {
+	NDIS_802_11_MAC_ADDRESS BSSID;
+	ULONG Flags;
+} PMKID_CANDIDATE;
+
+#define NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED 0x01
+
+typedef struct NDIS_802_11_PMKID_CANDIDATE_LIST {
+	ULONG Version;
+	ULONG NumCandidates;
+	PMKID_CANDIDATE CandidateList[1];
+} NDIS_802_11_PMKID_CANDIDATE_LIST;
+
+#endif /* OID_802_11_CAPABILITY */
+
+
+#ifdef CONFIG_USE_NDISUIO
+#ifndef _WIN32_WCE
+#ifdef __MINGW32_VERSION
+typedef ULONG NDIS_OID;
+#endif /* __MINGW32_VERSION */
+/* from nuiouser.h */
+#define FSCTL_NDISUIO_BASE      FILE_DEVICE_NETWORK
+
+#define _NDISUIO_CTL_CODE(_Function, _Method, _Access) \
+	CTL_CODE(FSCTL_NDISUIO_BASE, _Function, _Method, _Access)
+
+#define IOCTL_NDISUIO_OPEN_DEVICE \
+	_NDISUIO_CTL_CODE(0x200, METHOD_BUFFERED, \
+			  FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+
+#define IOCTL_NDISUIO_QUERY_OID_VALUE \
+	_NDISUIO_CTL_CODE(0x201, METHOD_BUFFERED, \
+			  FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+
+#define IOCTL_NDISUIO_SET_OID_VALUE \
+	_NDISUIO_CTL_CODE(0x205, METHOD_BUFFERED, \
+			  FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+
+#define IOCTL_NDISUIO_SET_ETHER_TYPE \
+	_NDISUIO_CTL_CODE(0x202, METHOD_BUFFERED, \
+			  FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+
+#define IOCTL_NDISUIO_QUERY_BINDING \
+	_NDISUIO_CTL_CODE(0x203, METHOD_BUFFERED, \
+			  FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+
+#define IOCTL_NDISUIO_BIND_WAIT \
+	_NDISUIO_CTL_CODE(0x204, METHOD_BUFFERED, \
+			  FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+
+typedef struct _NDISUIO_QUERY_OID
+{
+    NDIS_OID Oid;
+    UCHAR Data[sizeof(ULONG)];
+} NDISUIO_QUERY_OID, *PNDISUIO_QUERY_OID;
+
+typedef struct _NDISUIO_SET_OID
+{
+    NDIS_OID Oid;
+    UCHAR Data[sizeof(ULONG)];
+} NDISUIO_SET_OID, *PNDISUIO_SET_OID;
+
+typedef struct _NDISUIO_QUERY_BINDING
+{
+	ULONG BindingIndex;
+	ULONG DeviceNameOffset;
+	ULONG DeviceNameLength;
+	ULONG DeviceDescrOffset;
+	ULONG DeviceDescrLength;
+} NDISUIO_QUERY_BINDING, *PNDISUIO_QUERY_BINDING;
+#endif /* _WIN32_WCE */
+#endif /* CONFIG_USE_NDISUIO */
 
 
 static int ndis_get_oid(struct wpa_driver_ndis_data *drv, unsigned int oid,
-			char *data, int len)
+			char *data, size_t len)
 {
+#ifdef CONFIG_USE_NDISUIO
+	NDISUIO_QUERY_OID *o;
+	size_t buflen = sizeof(*o) + len;
+	DWORD written;
+	int ret;
+	size_t hdrlen;
+
+	o = os_zalloc(buflen);
+	if (o == NULL)
+		return -1;
+	o->Oid = oid;
+#ifdef _WIN32_WCE
+	o->ptcDeviceName = drv->adapter_name;
+#endif /* _WIN32_WCE */
+	if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_QUERY_OID_VALUE,
+			     o, sizeof(NDISUIO_QUERY_OID), o, buflen, &written,
+			     NULL)) {
+		wpa_printf(MSG_DEBUG, "NDIS: IOCTL_NDISUIO_QUERY_OID_VALUE "
+			   "failed (oid=%08x): %d", oid, (int) GetLastError());
+		os_free(o);
+		return -1;
+	}
+	hdrlen = sizeof(NDISUIO_QUERY_OID) - sizeof(o->Data);
+	if (written < hdrlen) {
+		wpa_printf(MSG_DEBUG, "NDIS: query oid=%08x written (%d); "
+			   "too short", oid, (unsigned int) written);
+		os_free(o);
+		return -1;
+	}
+	written -= hdrlen;
+	if (written > len) {
+		wpa_printf(MSG_DEBUG, "NDIS: query oid=%08x written (%d) > "
+			   "len (%d)",oid, (unsigned int) written, len);
+		os_free(o);
+		return -1;
+	}
+	os_memcpy(data, o->Data, written);
+	ret = written;
+	os_free(o);
+	return ret;
+#else /* CONFIG_USE_NDISUIO */
 	char *buf;
 	PACKET_OID_DATA *o;
 	int ret;
 
-	buf = malloc(sizeof(*o) + len);
+	buf = os_zalloc(sizeof(*o) + len);
 	if (buf == NULL)
 		return -1;
-	memset(buf, 0, sizeof(*o) + len);
 	o = (PACKET_OID_DATA *) buf;
 	o->Oid = oid;
 	o->Length = len;
@@ -289,46 +462,81 @@
 	if (!PacketRequest(drv->adapter, FALSE, o)) {
 		wpa_printf(MSG_DEBUG, "%s: oid=0x%x len (%d) failed",
 			   __func__, oid, len);
-		free(buf);
+		os_free(buf);
 		return -1;
 	}
 	if (o->Length > len) {
 		wpa_printf(MSG_DEBUG, "%s: oid=0x%x Length (%d) > len (%d)",
 			   __func__, oid, (unsigned int) o->Length, len);
-		free(buf);
+		os_free(buf);
 		return -1;
 	}
-	memcpy(data, o->Data, o->Length);
+	os_memcpy(data, o->Data, o->Length);
 	ret = o->Length;
-	free(buf);
+	os_free(buf);
 	return ret;
+#endif /* CONFIG_USE_NDISUIO */
 }
 
 
 static int ndis_set_oid(struct wpa_driver_ndis_data *drv, unsigned int oid,
-			char *data, int len)
+			const char *data, size_t len)
 {
+#ifdef CONFIG_USE_NDISUIO
+	NDISUIO_SET_OID *o;
+	size_t buflen, reallen;
+	DWORD written;
+	char txt[50];
+
+	os_snprintf(txt, sizeof(txt), "NDIS: Set OID %08x", oid);
+	wpa_hexdump_key(MSG_MSGDUMP, txt, data, len);
+
+	buflen = sizeof(*o) + len;
+	reallen = buflen - sizeof(o->Data);
+	o = os_zalloc(buflen);
+	if (o == NULL)
+		return -1;
+	o->Oid = oid;
+#ifdef _WIN32_WCE
+	o->ptcDeviceName = drv->adapter_name;
+#endif /* _WIN32_WCE */
+	if (data)
+		os_memcpy(o->Data, data, len);
+	if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_SET_OID_VALUE,
+			     o, reallen, NULL, 0, &written, NULL)) {
+		wpa_printf(MSG_DEBUG, "NDIS: IOCTL_NDISUIO_SET_OID_VALUE "
+			   "(oid=%08x) failed: %d", oid, (int) GetLastError());
+		os_free(o);
+		return -1;
+	}
+	os_free(o);
+	return 0;
+#else /* CONFIG_USE_NDISUIO */
 	char *buf;
 	PACKET_OID_DATA *o;
+	char txt[50];
 
-	buf = malloc(sizeof(*o) + len);
+	os_snprintf(txt, sizeof(txt), "NDIS: Set OID %08x", oid);
+	wpa_hexdump_key(MSG_MSGDUMP, txt, data, len);
+
+	buf = os_zalloc(sizeof(*o) + len);
 	if (buf == NULL)
 		return -1;
-	memset(buf, 0, sizeof(*o) + len);
 	o = (PACKET_OID_DATA *) buf;
 	o->Oid = oid;
 	o->Length = len;
 	if (data)
-		memcpy(o->Data, data, len);
+		os_memcpy(o->Data, data, len);
 
 	if (!PacketRequest(drv->adapter, TRUE, o)) {
 		wpa_printf(MSG_DEBUG, "%s: oid=0x%x len (%d) failed",
 			   __func__, oid, len);
-		free(buf);
+		os_free(buf);
 		return -1;
 	}
-	free(buf);
+	os_free(buf);
 	return 0;
+#endif /* CONFIG_USE_NDISUIO */
 }
 
 
@@ -429,7 +637,7 @@
 		}
 		return -1;
 	}
-	memcpy(ssid, buf.Ssid, buf.SsidLength);
+	os_memcpy(ssid, buf.Ssid, buf.SsidLength);
 	return buf.SsidLength;
 }
 
@@ -439,9 +647,9 @@
 {
 	NDIS_802_11_SSID buf;
 
-	memset(&buf, 0, sizeof(buf));
+	os_memset(&buf, 0, sizeof(buf));
 	buf.SsidLength = ssid_len;
-	memcpy(buf.Ssid, ssid, ssid_len);
+	os_memcpy(buf.Ssid, ssid, ssid_len);
 	/*
 	 * Make sure radio is marked enabled here so that scan request will not
 	 * force SSID to be changed to a random one in order to enable radio at
@@ -517,7 +725,7 @@
 	}
 
 	res = ndis_set_oid(drv, OID_802_11_BSSID_LIST_SCAN, "    ", 4);
-	eloop_register_timeout(3, 0, wpa_driver_ndis_scan_timeout, drv,
+	eloop_register_timeout(7, 0, wpa_driver_ndis_scan_timeout, drv,
 			       drv->ctx);
 	return res;
 }
@@ -541,11 +749,11 @@
 			continue;
 		}
 		if (pos[0] == GENERIC_INFO_ELEM && pos[1] >= 4 &&
-		    memcmp(pos + 2, "\x00\x50\xf2\x01", 4) == 0) {
-			memcpy(res->wpa_ie, pos, ielen);
+		    os_memcmp(pos + 2, "\x00\x50\xf2\x01", 4) == 0) {
+			os_memcpy(res->wpa_ie, pos, ielen);
 			res->wpa_ie_len = ielen;
 		} else if (pos[0] == RSN_INFO_ELEM) {
-			memcpy(res->rsn_ie, pos, ielen);
+			os_memcpy(res->rsn_ie, pos, ielen);
 			res->rsn_ie_len = ielen;
 		}
 		pos += ielen;
@@ -559,19 +767,18 @@
 {
 	struct wpa_driver_ndis_data *drv = priv;
 	NDIS_802_11_BSSID_LIST_EX *b;
-	size_t blen;
-	int len, count, i, j;
+	size_t blen, count, i;
+	int len, j;
 	char *pos;
 
 	blen = 65535;
-	b = malloc(blen);
+	b = os_zalloc(blen);
 	if (b == NULL)
 		return -1;
-	memset(b, 0, blen);
 	len = ndis_get_oid(drv, OID_802_11_BSSID_LIST, (char *) b, blen);
 	if (len < 0) {
 		wpa_printf(MSG_DEBUG, "NDIS: failed to get scan results");
-		free(b);
+		os_free(b);
 		return -1;
 	}
 	count = b->NumberOfItems;
@@ -579,15 +786,20 @@
 	if (count > max_size)
 		count = max_size;
 
-	memset(results, 0, max_size * sizeof(struct wpa_scan_result));
+	os_memset(results, 0, max_size * sizeof(struct wpa_scan_result));
 	pos = (char *) &b->Bssid[0];
 	for (i = 0; i < count; i++) {
 		NDIS_WLAN_BSSID_EX *bss = (NDIS_WLAN_BSSID_EX *) pos;
-		memcpy(results[i].bssid, bss->MacAddress, ETH_ALEN);
-		memcpy(results[i].ssid, bss->Ssid.Ssid, bss->Ssid.SsidLength);
+		os_memcpy(results[i].bssid, bss->MacAddress, ETH_ALEN);
+		os_memcpy(results[i].ssid, bss->Ssid.Ssid,
+			  bss->Ssid.SsidLength);
 		results[i].ssid_len = bss->Ssid.SsidLength;
 		if (bss->Privacy)
 			results[i].caps |= IEEE80211_CAP_PRIVACY;
+		if (bss->InfrastructureMode == Ndis802_11IBSS)
+			results[i].caps |= IEEE80211_CAP_IBSS;
+		else if (bss->InfrastructureMode == Ndis802_11Infrastructure)
+			results[i].caps |= IEEE80211_CAP_ESS;
 		results[i].level = (int) bss->Rssi;
 		results[i].freq = bss->Configuration.DSConfig / 1000;
 		for (j = 0; j < sizeof(bss->SupportedRates); j++) {
@@ -597,14 +809,27 @@
 					bss->SupportedRates[j] & 0x7f;
 			}
 		}
+		if (((char *) bss->IEs) + bss->IELength  > (char *) b + blen) {
+			/*
+			 * Some NDIS drivers have been reported to include an
+			 * entry with an invalid IELength in scan results and
+			 * this has crashed wpa_supplicant, so validate the
+			 * returned value before using it.
+			 */
+			wpa_printf(MSG_DEBUG, "NDIS: skipped invalid scan "
+				   "result IE (BSSID=" MACSTR ") IELength=%d",
+				   MAC2STR(results[i].bssid),
+				   (int) bss->IELength);
+			break;
+		}
 		wpa_driver_ndis_get_ies(&results[i], bss->IEs, bss->IELength);
 		pos += bss->Length;
 		if (pos > (char *) b + blen)
 			break;
 	}
 
-	free(b);
-	return count;
+	os_free(b);
+	return (int) count;
 }
 
 
@@ -616,24 +841,25 @@
 	NDIS_802_11_KEY_INDEX index;
 	int res, res2;
 
-	memset(&rkey, 0, sizeof(rkey));
+	os_memset(&rkey, 0, sizeof(rkey));
 
 	rkey.Length = sizeof(rkey);
 	rkey.KeyIndex = key_idx;
 	if (pairwise)
 		rkey.KeyIndex |= 1 << 30;
-	memcpy(rkey.BSSID, bssid, ETH_ALEN);
+	os_memcpy(rkey.BSSID, bssid, ETH_ALEN);
 
 	res = ndis_set_oid(drv, OID_802_11_REMOVE_KEY, (char *) &rkey,
 			   sizeof(rkey));
 	if (!pairwise) {
+		index = key_idx;
 		res2 = ndis_set_oid(drv, OID_802_11_REMOVE_WEP,
 				    (char *) &index, sizeof(index));
 	} else
 		res2 = 0;
 
 	if (res < 0 && res2 < 0)
-		return res;
+		return -1;
 	return 0;
 }
 
@@ -647,10 +873,9 @@
 	int res;
 
 	len = 12 + key_len;
-	wep = malloc(len);
+	wep = os_zalloc(len);
 	if (wep == NULL)
 		return -1;
-	memset(wep, 0, len);
 	wep->Length = len;
 	wep->KeyIndex = key_idx;
 	if (set_tx)
@@ -660,13 +885,13 @@
 		wep->KeyIndex |= 1 << 30;
 #endif
 	wep->KeyLength = key_len;
-	memcpy(wep->KeyMaterial, key, key_len);
+	os_memcpy(wep->KeyMaterial, key, key_len);
 
-	wpa_hexdump_key(MSG_MSGDUMP, "NDIS: OIS_802_11_ADD_WEP",
+	wpa_hexdump_key(MSG_MSGDUMP, "NDIS: OID_802_11_ADD_WEP",
 			(char *) wep, len);
 	res = ndis_set_oid(drv, OID_802_11_ADD_WEP, (char *) wep, len);
 
-	free(wep);
+	os_free(wep);
 
 	return res;
 }
@@ -677,20 +902,21 @@
 				   const u8 *key, size_t key_len)
 {
 	struct wpa_driver_ndis_data *drv = priv;
-	size_t len;
+	size_t len, i;
 	NDIS_802_11_KEY *nkey;
-	int i, res, pairwise;
+	int res, pairwise;
 	u8 bssid[ETH_ALEN];
 
-	if (addr == NULL || memcmp(addr, "\xff\xff\xff\xff\xff\xff",
-				   ETH_ALEN) == 0) {
+	if (addr == NULL || os_memcmp(addr, "\xff\xff\xff\xff\xff\xff",
+				      ETH_ALEN) == 0) {
 		/* Group Key */
 		pairwise = 0;
-		wpa_driver_ndis_get_bssid(drv, bssid);
+		if (wpa_driver_ndis_get_bssid(drv, bssid) < 0)
+			os_memset(bssid, 0xff, ETH_ALEN);
 	} else {
 		/* Pairwise Key */
 		pairwise = 1;
-		memcpy(bssid, addr, ETH_ALEN);
+		os_memcpy(bssid, addr, ETH_ALEN);
 	}
 
 	if (alg == WPA_ALG_NONE || key_len == 0) {
@@ -705,10 +931,9 @@
 
 	len = 12 + 6 + 6 + 8 + key_len;
 
-	nkey = malloc(len);
+	nkey = os_zalloc(len);
 	if (nkey == NULL)
 		return -1;
-	memset(nkey, 0, len);
 
 	nkey->Length = len;
 	nkey->KeyIndex = key_idx;
@@ -719,23 +944,23 @@
 	if (seq && seq_len)
 		nkey->KeyIndex |= 1 << 29;
 	nkey->KeyLength = key_len;
-	memcpy(nkey->BSSID, bssid, ETH_ALEN);
+	os_memcpy(nkey->BSSID, bssid, ETH_ALEN);
 	if (seq && seq_len) {
 		for (i = 0; i < seq_len; i++)
-			nkey->KeyRSC |= seq[i] << (i * 8);
+			nkey->KeyRSC |= (ULONGLONG) seq[i] << (i * 8);
 	}
 	if (alg == WPA_ALG_TKIP && key_len == 32) {
-		memcpy(nkey->KeyMaterial, key, 16);
-		memcpy(nkey->KeyMaterial + 16, key + 24, 8);
-		memcpy(nkey->KeyMaterial + 24, key + 16, 8);
+		os_memcpy(nkey->KeyMaterial, key, 16);
+		os_memcpy(nkey->KeyMaterial + 16, key + 24, 8);
+		os_memcpy(nkey->KeyMaterial + 24, key + 16, 8);
 	} else {
-		memcpy(nkey->KeyMaterial, key, key_len);
+		os_memcpy(nkey->KeyMaterial, key, key_len);
 	}
 
-	wpa_hexdump_key(MSG_MSGDUMP, "NDIS: OIS_802_11_ADD_KEY",
+	wpa_hexdump_key(MSG_MSGDUMP, "NDIS: OID_802_11_ADD_KEY",
 			(char *) nkey, len);
 	res = ndis_set_oid(drv, OID_802_11_ADD_KEY, (char *) nkey, len);
-	free(nkey);
+	os_free(nkey);
 
 	return res;
 }
@@ -748,11 +973,18 @@
 	struct wpa_driver_ndis_data *drv = priv;
 	u32 auth_mode, encr, priv_mode, mode;
 
+	drv->mode = params->mode;
+
 	/* Note: Setting OID_802_11_INFRASTRUCTURE_MODE clears current keys,
 	 * so static WEP keys needs to be set again after this. */
-	if (params->mode == IEEE80211_MODE_IBSS)
+	if (params->mode == IEEE80211_MODE_IBSS) {
 		mode = Ndis802_11IBSS;
-	else
+		/* Need to make sure that BSSID polling is enabled for
+		 * IBSS mode. */
+		eloop_cancel_timeout(wpa_driver_ndis_poll_timeout, drv, NULL);
+		eloop_register_timeout(1, 0, wpa_driver_ndis_poll_timeout,
+				       drv, NULL);
+	} else
 		mode = Ndis802_11Infrastructure;
 	if (ndis_set_oid(drv, OID_802_11_INFRASTRUCTURE_MODE,
 			 (char *) &mode, sizeof(mode)) < 0) {
@@ -762,6 +994,23 @@
 		/* Try to continue anyway */
 	}
 
+	if (params->key_mgmt_suite == KEY_MGMT_NONE ||
+	    params->key_mgmt_suite == KEY_MGMT_802_1X_NO_WPA) {
+		/* Re-set WEP keys if static WEP configuration is used. */
+		u8 bcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+		int i;
+		for (i = 0; i < 4; i++) {
+			if (!params->wep_key[i])
+				continue;
+			wpa_printf(MSG_DEBUG, "NDIS: Re-setting static WEP "
+				   "key %d", i);
+			wpa_driver_ndis_set_key(drv, WPA_ALG_WEP, bcast, i,
+						i == params->wep_tx_keyidx,
+						NULL, 0, params->wep_key[i],
+						params->wep_key_len[i]);
+		}
+	}
+
 	if (params->wpa_ie == NULL || params->wpa_ie_len == 0) {
 		if (params->auth_alg & AUTH_ALG_SHARED_KEY) {
 			if (params->auth_alg & AUTH_ALG_OPEN_SYSTEM)
@@ -801,8 +1050,10 @@
 	case CIPHER_NONE:
 		if (params->group_suite == CIPHER_CCMP)
 			encr = Ndis802_11Encryption3Enabled;
-		else
+		else if (params->group_suite == CIPHER_TKIP)
 			encr = Ndis802_11Encryption2Enabled;
+		else
+			encr = Ndis802_11EncryptionDisabled;
 		break;
 	default:
 		encr = Ndis802_11EncryptionDisabled;
@@ -819,6 +1070,15 @@
 	ndis_set_auth_mode(drv, auth_mode);
 	ndis_set_encr_status(drv, encr);
 
+	if (params->bssid) {
+		ndis_set_oid(drv, OID_802_11_BSSID, params->bssid, ETH_ALEN);
+		drv->oid_bssid_set = 1;
+	} else if (drv->oid_bssid_set) {
+		ndis_set_oid(drv, OID_802_11_BSSID, "\xff\xff\xff\xff\xff\xff",
+			     ETH_ALEN);
+		drv->oid_bssid_set = 0;
+	}
+
 	return wpa_driver_ndis_set_ssid(drv, params->ssid, params->ssid_len);
 }
 
@@ -838,21 +1098,21 @@
 		entry = entry->next;
 	}
 	len = 8 + count * sizeof(BSSID_INFO);
-	p = malloc(len);
+	p = os_zalloc(len);
 	if (p == NULL)
 		return -1;
-	memset(p, 0, len);
+
 	p->Length = len;
 	p->BSSIDInfoCount = count;
 	entry = drv->pmkid;
 	for (i = 0; i < count; i++) {
-		memcpy(&p->BSSIDInfo[i].BSSID, entry->bssid, ETH_ALEN);
-		memcpy(&p->BSSIDInfo[i].PMKID, entry->pmkid, 16);
+		os_memcpy(&p->BSSIDInfo[i].BSSID, entry->bssid, ETH_ALEN);
+		os_memcpy(&p->BSSIDInfo[i].PMKID, entry->pmkid, 16);
 		entry = entry->next;
 	}
 	wpa_hexdump(MSG_MSGDUMP, "NDIS: OID_802_11_PMKID", (char *) p, len);
 	ret = ndis_set_oid(drv, OID_802_11_PMKID, (char *) p, len);
-	free(p);
+	os_free(p);
 	return ret;
 }
 
@@ -869,7 +1129,7 @@
 	prev = NULL;
 	entry = drv->pmkid;
 	while (entry) {
-		if (memcmp(entry->bssid, bssid, ETH_ALEN) == 0)
+		if (os_memcmp(entry->bssid, bssid, ETH_ALEN) == 0)
 			break;
 		prev = entry;
 		entry = entry->next;
@@ -878,17 +1138,17 @@
 	if (entry) {
 		/* Replace existing entry for this BSSID and move it into the
 		 * beginning of the list. */
-		memcpy(entry->pmkid, pmkid, 16);
+		os_memcpy(entry->pmkid, pmkid, 16);
 		if (prev) {
 			prev->next = entry->next;
 			entry->next = drv->pmkid;
 			drv->pmkid = entry;
 		}
 	} else {
-		entry = malloc(sizeof(*entry));
+		entry = os_malloc(sizeof(*entry));
 		if (entry) {
-			memcpy(entry->bssid, bssid, ETH_ALEN);
-			memcpy(entry->pmkid, pmkid, 16);
+			os_memcpy(entry->bssid, bssid, ETH_ALEN);
+			os_memcpy(entry->pmkid, pmkid, 16);
 			entry->next = drv->pmkid;
 			drv->pmkid = entry;
 		}
@@ -911,13 +1171,13 @@
 	prev = NULL;
 	drv->pmkid = NULL;
 	while (entry) {
-		if (memcmp(entry->bssid, bssid, ETH_ALEN) == 0 &&
-		    memcmp(entry->pmkid, pmkid, 16) == 0) {
+		if (os_memcmp(entry->bssid, bssid, ETH_ALEN) == 0 &&
+		    os_memcmp(entry->pmkid, pmkid, 16) == 0) {
 			if (prev)
 				prev->next = entry->next;
 			else
 				drv->pmkid = entry->next;
-			free(entry);
+			os_free(entry);
 			break;
 		}
 		prev = entry;
@@ -941,10 +1201,10 @@
 	while (pmkid) {
 		prev = pmkid;
 		pmkid = pmkid->next;
-		free(prev);
+		os_free(prev);
 	}
 
-	memset(&p, 0, sizeof(p));
+	os_memset(&p, 0, sizeof(p));
 	p.Length = 8;
 	p.BSSIDInfoCount = 0;
 	wpa_hexdump(MSG_MSGDUMP, "NDIS: OID_802_11_PMKID (flush)",
@@ -957,10 +1217,10 @@
 {
 	char buf[512], *pos;
 	NDIS_802_11_ASSOCIATION_INFORMATION *ai;
-	int len, i;
+	int len;
 	union wpa_event_data data;
 	NDIS_802_11_BSSID_LIST_EX *b;
-	size_t blen;
+	size_t blen, i;
 
 	len = ndis_get_oid(drv, OID_802_11_ASSOCIATION_INFORMATION, buf,
 			   sizeof(buf));
@@ -1002,33 +1262,32 @@
 		   (int) ai->OffsetRequestIEs, (int) ai->OffsetResponseIEs,
 		   (int) ai->RequestIELength, (int) ai->ResponseIELength);
 
-	if (ai->OffsetRequestIEs + ai->RequestIELength > len ||
-	    ai->OffsetResponseIEs + ai->ResponseIELength > len) {
+	if (ai->OffsetRequestIEs + ai->RequestIELength > (unsigned) len ||
+	    ai->OffsetResponseIEs + ai->ResponseIELength > (unsigned) len) {
 		wpa_printf(MSG_DEBUG, "NDIS: association information - "
 			   "IE overflow");
 		return -1;
 	}
 
-	wpa_hexdump(MSG_MSGDUMP, "NDIS: Request IEs", 
+	wpa_hexdump(MSG_MSGDUMP, "NDIS: Request IEs",
 		    buf + ai->OffsetRequestIEs, ai->RequestIELength);
-	wpa_hexdump(MSG_MSGDUMP, "NDIS: Response IEs", 
+	wpa_hexdump(MSG_MSGDUMP, "NDIS: Response IEs",
 		    buf + ai->OffsetResponseIEs, ai->ResponseIELength);
 
-	memset(&data, 0, sizeof(data));
+	os_memset(&data, 0, sizeof(data));
 	data.assoc_info.req_ies = buf + ai->OffsetRequestIEs;
 	data.assoc_info.req_ies_len = ai->RequestIELength;
 	data.assoc_info.resp_ies = buf + ai->OffsetResponseIEs;
 	data.assoc_info.resp_ies_len = ai->ResponseIELength;
 
 	blen = 65535;
-	b = malloc(blen);
+	b = os_zalloc(blen);
 	if (b == NULL)
 		goto skip_scan_results;
-	memset(b, 0, blen);
 	len = ndis_get_oid(drv, OID_802_11_BSSID_LIST, (char *) b, blen);
 	if (len < 0) {
 		wpa_printf(MSG_DEBUG, "NDIS: failed to get scan results");
-		free(b);
+		os_free(b);
 		b = NULL;
 		goto skip_scan_results;
 	}
@@ -1038,7 +1297,7 @@
 	pos = (char *) &b->Bssid[0];
 	for (i = 0; i < b->NumberOfItems; i++) {
 		NDIS_WLAN_BSSID_EX *bss = (NDIS_WLAN_BSSID_EX *) pos;
-		if (memcmp(drv->bssid, bss->MacAddress, ETH_ALEN) == 0 &&
+		if (os_memcmp(drv->bssid, bss->MacAddress, ETH_ALEN) == 0 &&
 		    bss->IELength > sizeof(NDIS_802_11_FIXED_IEs)) {
 			data.assoc_info.beacon_ies =
 				((u8 *) bss->IEs) +
@@ -1058,7 +1317,7 @@
 skip_scan_results:
 	wpa_supplicant_event(drv->ctx, EVENT_ASSOCINFO, &data);
 
-	free(b);
+	os_free(b);
 
 	return 0;
 }
@@ -1068,26 +1327,44 @@
 {
 	struct wpa_driver_ndis_data *drv = eloop_ctx;
 	u8 bssid[ETH_ALEN];
+	int poll;
 
 	if (drv->wired)
 		return;
 
 	if (wpa_driver_ndis_get_bssid(drv, bssid)) {
 		/* Disconnected */
-		if (memcmp(drv->bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN)
+		if (os_memcmp(drv->bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN)
 		    != 0) {
-			memset(drv->bssid, 0, ETH_ALEN);
+			os_memset(drv->bssid, 0, ETH_ALEN);
 			wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL);
 		}
 	} else {
 		/* Connected */
-		if (memcmp(drv->bssid, bssid, ETH_ALEN) != 0) {
-			memcpy(drv->bssid, bssid, ETH_ALEN);
+		if (os_memcmp(drv->bssid, bssid, ETH_ALEN) != 0) {
+			os_memcpy(drv->bssid, bssid, ETH_ALEN);
 			wpa_driver_ndis_get_associnfo(drv);
 			wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL);
 		}
 	}
-	eloop_register_timeout(1, 0, wpa_driver_ndis_poll_timeout, drv, NULL);
+
+	/* When using integrated NDIS event receiver, we can skip BSSID
+	 * polling when using infrastructure network. However, when using
+	 * IBSS mode, many driver do not seem to generate connection event,
+	 * so we need to enable BSSID polling to figure out when IBSS network
+	 * has been formed.
+	 */
+	poll = drv->mode == IEEE80211_MODE_IBSS;
+#ifndef CONFIG_NDIS_EVENTS_INTEGRATED
+#ifndef _WIN32_WCE
+	poll = 1;
+#endif /* _WIN32_WCE */
+#endif /* CONFIG_NDIS_EVENTS_INTEGRATED */
+
+	if (poll) {
+		eloop_register_timeout(1, 0, wpa_driver_ndis_poll_timeout,
+					drv, NULL);
+	}
 }
 
 
@@ -1116,7 +1393,7 @@
 void wpa_driver_ndis_event_disconnect(struct wpa_driver_ndis_data *drv)
 {
 	wpa_printf(MSG_DEBUG, "NDIS: Media Disconnect Event");
-	memset(drv->bssid, 0, ETH_ALEN);
+	os_memset(drv->bssid, 0, ETH_ALEN);
 	wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL);
 }
 
@@ -1147,7 +1424,7 @@
 		group = 1;
 
 	if (pairwise || group) {
-		memset(&event, 0, sizeof(event));
+		os_memset(&event, 0, sizeof(event));
 		event.michael_mic_failure.unicast = pairwise;
 		wpa_supplicant_event(drv->ctx, EVENT_MICHAEL_MIC_FAILURE,
 				     &event);
@@ -1159,7 +1436,7 @@
 					const u8 *data, size_t data_len)
 {
 	NDIS_802_11_PMKID_CANDIDATE_LIST *pmkid;
-	int i;
+	size_t i;
 	union wpa_event_data event;
 
 	if (data_len < 8) {
@@ -1183,12 +1460,12 @@
 		return;
 	}
 
-	memset(&event, 0, sizeof(event));
+	os_memset(&event, 0, sizeof(event));
 	for (i = 0; i < pmkid->NumCandidates; i++) {
 		PMKID_CANDIDATE *p = &pmkid->CandidateList[i];
 		wpa_printf(MSG_DEBUG, "NDIS: %d: " MACSTR " Flags 0x%x",
 			   i, MAC2STR(p->BSSID), (int) p->Flags);
-		memcpy(event.pmkid_candidate.bssid, p->BSSID, ETH_ALEN);
+		os_memcpy(event.pmkid_candidate.bssid, p->BSSID, ETH_ALEN);
 		event.pmkid_candidate.index = i;
 		event.pmkid_candidate.preauth =
 			p->Flags & NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED;
@@ -1230,6 +1507,50 @@
 }
 
 
+/* Called when an adapter is added */
+void wpa_driver_ndis_event_adapter_arrival(struct wpa_driver_ndis_data *drv)
+{
+	union wpa_event_data event;
+	int i;
+
+	wpa_printf(MSG_DEBUG, "NDIS: Notify Adapter Arrival");
+
+	for (i = 0; i < 30; i++) {
+		/* Re-open Packet32/NDISUIO connection */
+		wpa_driver_ndis_adapter_close(drv);
+		if (wpa_driver_ndis_adapter_init(drv) < 0 ||
+		    wpa_driver_ndis_adapter_open(drv) < 0) {
+			wpa_printf(MSG_DEBUG, "NDIS: Driver re-initialization "
+				   "(%d) failed", i);
+			os_sleep(1, 0);
+		} else {
+			wpa_printf(MSG_DEBUG, "NDIS: Driver re-initialized");
+			break;
+		}
+	}
+
+	os_memset(&event, 0, sizeof(event));
+	os_snprintf(event.interface_status.ifname,
+		    sizeof(event.interface_status.ifname), "%s", drv->ifname);
+	event.interface_status.ievent = EVENT_INTERFACE_ADDED;
+	wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event);
+}
+
+
+/* Called when an adapter is removed */
+void wpa_driver_ndis_event_adapter_removal(struct wpa_driver_ndis_data *drv)
+{
+	union wpa_event_data event;
+
+	wpa_printf(MSG_DEBUG, "NDIS: Notify Adapter Removal");
+	os_memset(&event, 0, sizeof(event));
+	os_snprintf(event.interface_status.ifname,
+		    sizeof(event.interface_status.ifname), "%s", drv->ifname);
+	event.interface_status.ievent = EVENT_INTERFACE_REMOVED;
+	wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event);
+}
+
+
 static void
 wpa_driver_ndis_get_wpa_capability(struct wpa_driver_ndis_data *drv)
 {
@@ -1300,11 +1621,11 @@
 static void wpa_driver_ndis_get_capability(struct wpa_driver_ndis_data *drv)
 {
 	char buf[512];
-	int len, i;
+	int len;
+	size_t i;
 	NDIS_802_11_CAPABILITY *c;
 
-	drv->capa.flags = WPA_DRIVER_FLAGS_DRIVER_IE |
-		WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC;
+	drv->capa.flags = WPA_DRIVER_FLAGS_DRIVER_IE;
 
 	len = ndis_get_oid(drv, OID_802_11_CAPABILITY, buf, sizeof(buf));
 	if (len < 0) {
@@ -1321,10 +1642,11 @@
 	}
 	wpa_printf(MSG_DEBUG, "NDIS: Driver supports OID_802_11_CAPABILITY - "
 		   "NoOfPMKIDs %d NoOfAuthEncrPairs %d",
-		   (int) c->NoOfPMKIDs, (int) c->NoOfAuthEncryptPairSupported);
+		   (int) c->NoOfPMKIDs,
+		   (int) c->NoOfAuthEncryptPairsSupported);
 	drv->has_capability = 1;
 	drv->no_of_pmkid = c->NoOfPMKIDs;
-	for (i = 0; i < c->NoOfAuthEncryptPairSupported; i++) {
+	for (i = 0; i < c->NoOfAuthEncryptPairsSupported; i++) {
 		NDIS_802_11_AUTHENTICATION_ENCRYPTION *ae;
 		ae = &c->AuthenticationEncryptionSupported[i];
 		if ((char *) (ae + 1) > buf + len) {
@@ -1389,7 +1711,7 @@
 	struct wpa_driver_ndis_data *drv = priv;
 	if (!drv->has_capability)
 		return -1;
-	memcpy(capa, &drv->capa, sizeof(*capa));
+	os_memcpy(capa, &drv->capa, sizeof(*capa));
 	return 0;
 }
 
@@ -1408,12 +1730,279 @@
 }
 
 
+#ifdef _WIN32_WCE
+
+#define NDISUIO_MSG_SIZE (sizeof(NDISUIO_DEVICE_NOTIFICATION) + 512)
+
+static void ndisuio_notification_receive(void *eloop_data, void *user_ctx)
+{
+	struct wpa_driver_ndis_data *drv = eloop_data;
+	NDISUIO_DEVICE_NOTIFICATION *hdr;
+	u8 buf[NDISUIO_MSG_SIZE];
+	DWORD len, flags;
+
+	if (!ReadMsgQueue(drv->event_queue, buf, NDISUIO_MSG_SIZE, &len, 0,
+			  &flags)) {
+		wpa_printf(MSG_DEBUG, "ndisuio_notification_receive: "
+			   "ReadMsgQueue failed: %d", (int) GetLastError());
+		return;
+	}
+
+	if (len < sizeof(NDISUIO_DEVICE_NOTIFICATION)) {
+		wpa_printf(MSG_DEBUG, "ndisuio_notification_receive: "
+			   "Too short message (len=%d)", (int) len);
+		return;
+	}
+
+	hdr = (NDISUIO_DEVICE_NOTIFICATION *) buf;
+	wpa_printf(MSG_DEBUG, "NDIS: Notification received: len=%d type=0x%x",
+		   (int) len, hdr->dwNotificationType);
+
+	switch (hdr->dwNotificationType) {
+#ifdef NDISUIO_NOTIFICATION_ADAPTER_ARRIVAL
+	case NDISUIO_NOTIFICATION_ADAPTER_ARRIVAL:
+		wpa_printf(MSG_DEBUG, "NDIS: ADAPTER_ARRIVAL");
+		wpa_driver_ndis_event_adapter_arrival(drv);
+		break;
+#endif
+#ifdef NDISUIO_NOTIFICATION_ADAPTER_REMOVAL
+	case NDISUIO_NOTIFICATION_ADAPTER_REMOVAL:
+		wpa_printf(MSG_DEBUG, "NDIS: ADAPTER_REMOVAL");
+		wpa_driver_ndis_event_adapter_removal(drv);
+		break;
+#endif
+	case NDISUIO_NOTIFICATION_MEDIA_CONNECT:
+		wpa_printf(MSG_DEBUG, "NDIS: MEDIA_CONNECT");
+		SetEvent(drv->connected_event);
+		wpa_driver_ndis_event_connect(drv);
+		break;
+	case NDISUIO_NOTIFICATION_MEDIA_DISCONNECT:
+		ResetEvent(drv->connected_event);
+		wpa_printf(MSG_DEBUG, "NDIS: MEDIA_DISCONNECT");
+		wpa_driver_ndis_event_disconnect(drv);
+		break;
+	case NDISUIO_NOTIFICATION_MEDIA_SPECIFIC_NOTIFICATION:
+		wpa_printf(MSG_DEBUG, "NDIS: MEDIA_SPECIFIC_NOTIFICATION");
+#if _WIN32_WCE == 420 || _WIN32_WCE == 0x420
+		wpa_driver_ndis_event_media_specific(
+			drv, hdr->pvStatusBuffer, hdr->uiStatusBufferSize);
+#else
+		wpa_driver_ndis_event_media_specific(
+			drv, ((const u8 *) hdr) + hdr->uiOffsetToStatusBuffer,
+			(size_t) hdr->uiStatusBufferSize);
+#endif
+		break;
+	default:
+		wpa_printf(MSG_DEBUG, "NDIS: Unknown notification type 0x%x",
+			   hdr->dwNotificationType);
+		break;
+	}
+}
+
+
+static void ndisuio_notification_deinit(struct wpa_driver_ndis_data *drv)
+{
+	NDISUIO_REQUEST_NOTIFICATION req;
+
+	memset(&req, 0, sizeof(req));
+	req.hMsgQueue = drv->event_queue;
+	req.dwNotificationTypes = 0;
+
+	if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_REQUEST_NOTIFICATION,
+			     &req, sizeof(req), NULL, 0, NULL, NULL)) {
+		wpa_printf(MSG_INFO, "ndisuio_notification_deinit: "
+			   "IOCTL_NDISUIO_REQUEST_NOTIFICATION failed: %d",
+			   (int) GetLastError());
+	}
+
+	if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_CANCEL_NOTIFICATION,
+			     NULL, 0, NULL, 0, NULL, NULL)) {
+		wpa_printf(MSG_INFO, "ndisuio_notification_deinit: "
+			   "IOCTL_NDISUIO_CANCEL_NOTIFICATION failed: %d",
+			   (int) GetLastError());
+	}
+
+	if (drv->event_queue) {
+		eloop_unregister_event(drv->event_queue,
+				       sizeof(drv->event_queue));
+		CloseHandle(drv->event_queue);
+		drv->event_queue = NULL;
+	}
+
+	if (drv->connected_event) {
+		CloseHandle(drv->connected_event);
+		drv->connected_event = NULL;
+	}
+}
+
+
+static int ndisuio_notification_init(struct wpa_driver_ndis_data *drv)
+{
+	MSGQUEUEOPTIONS opt;
+	NDISUIO_REQUEST_NOTIFICATION req;
+
+	drv->connected_event =
+		CreateEvent(NULL, TRUE, FALSE, TEXT("WpaSupplicantConnected"));
+	if (drv->connected_event == NULL) {
+		wpa_printf(MSG_INFO, "ndisuio_notification_init: "
+			   "CreateEvent failed: %d",
+			   (int) GetLastError());
+		return -1;
+	}
+
+	memset(&opt, 0, sizeof(opt));
+	opt.dwSize = sizeof(opt);
+	opt.dwMaxMessages = 5;
+	opt.cbMaxMessage = NDISUIO_MSG_SIZE;
+	opt.bReadAccess = TRUE;
+
+	drv->event_queue = CreateMsgQueue(NULL, &opt);
+	if (drv->event_queue == NULL) {
+		wpa_printf(MSG_INFO, "ndisuio_notification_init: "
+			   "CreateMsgQueue failed: %d",
+			   (int) GetLastError());
+		ndisuio_notification_deinit(drv);
+		return -1;
+	}
+
+	memset(&req, 0, sizeof(req));
+	req.hMsgQueue = drv->event_queue;
+	req.dwNotificationTypes =
+#ifdef NDISUIO_NOTIFICATION_ADAPTER_ARRIVAL
+		NDISUIO_NOTIFICATION_ADAPTER_ARRIVAL |
+#endif
+#ifdef NDISUIO_NOTIFICATION_ADAPTER_REMOVAL
+		NDISUIO_NOTIFICATION_ADAPTER_REMOVAL |
+#endif
+		NDISUIO_NOTIFICATION_MEDIA_CONNECT |
+		NDISUIO_NOTIFICATION_MEDIA_DISCONNECT |
+		NDISUIO_NOTIFICATION_MEDIA_SPECIFIC_NOTIFICATION;
+
+	if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_REQUEST_NOTIFICATION,
+			     &req, sizeof(req), NULL, 0, NULL, NULL)) {
+		wpa_printf(MSG_INFO, "ndisuio_notification_init: "
+			   "IOCTL_NDISUIO_REQUEST_NOTIFICATION failed: %d",
+			   (int) GetLastError());
+		ndisuio_notification_deinit(drv);
+		return -1;
+	}
+
+	eloop_register_event(drv->event_queue, sizeof(drv->event_queue),
+			     ndisuio_notification_receive, drv, NULL);
+
+	return 0;
+}
+#endif /* _WIN32_WCE */
+
+
 static int wpa_driver_ndis_get_names(struct wpa_driver_ndis_data *drv)
 {
-	PTSTR names, pos, pos2;
+#ifdef CONFIG_USE_NDISUIO
+	NDISUIO_QUERY_BINDING *b;
+	size_t blen = sizeof(*b) + 1024;
+	int i, error, found = 0;
+	DWORD written;
+	char name[256], desc[256], *dpos;
+	WCHAR *pos;
+	size_t j, len, dlen;
+
+	b = os_malloc(blen);
+	if (b == NULL)
+		return -1;
+
+	for (i = 0; ; i++) {
+		os_memset(b, 0, blen);
+		b->BindingIndex = i;
+		if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_QUERY_BINDING,
+				     b, sizeof(NDISUIO_QUERY_BINDING), b, blen,
+				     &written, NULL)) {
+			error = (int) GetLastError();
+			if (error == ERROR_NO_MORE_ITEMS)
+				break;
+			wpa_printf(MSG_DEBUG, "IOCTL_NDISUIO_QUERY_BINDING "
+				   "failed: %d", error);
+			break;
+		}
+
+		pos = (WCHAR *) ((char *) b + b->DeviceNameOffset);
+		len = b->DeviceNameLength;
+		if (len >= sizeof(name))
+			len = sizeof(name) - 1;
+		for (j = 0; j < len; j++)
+			name[j] = (char) pos[j];
+		name[len] = '\0';
+
+		pos = (WCHAR *) ((char *) b + b->DeviceDescrOffset);
+		len = b->DeviceDescrLength;
+		if (len >= sizeof(desc))
+			len = sizeof(desc) - 1;
+		for (j = 0; j < len; j++)
+			desc[j] = (char) pos[j];
+		desc[len] = '\0';
+
+		wpa_printf(MSG_DEBUG, "NDIS: %d - %s - %s", i, name, desc);
+
+		if (os_strstr(name, drv->ifname)) {
+			wpa_printf(MSG_DEBUG, "NDIS: Interface name match");
+			found = 1;
+			break;
+		}
+
+		if (os_strncmp(desc, drv->ifname, os_strlen(drv->ifname)) == 0)
+		{
+			wpa_printf(MSG_DEBUG, "NDIS: Interface description "
+				   "match");
+			found = 1;
+			break;
+		}
+	}
+
+	if (!found) {
+		wpa_printf(MSG_DEBUG, "NDIS: Could not find interface '%s'",
+			   drv->ifname);
+		os_free(b);
+		return -1;
+	}
+
+	os_strncpy(drv->ifname,
+		   os_strncmp(name, "\\DEVICE\\", 8) == 0 ? name + 8 : name,
+		   sizeof(drv->ifname));
+#ifdef _WIN32_WCE
+	drv->adapter_name = wpa_strdup_tchar(drv->ifname);
+	if (drv->adapter_name == NULL) {
+		wpa_printf(MSG_ERROR, "NDIS: Failed to allocate memory for "
+			   "adapter name");
+		os_free(b);
+		return -1;
+	}
+#endif /* _WIN32_WCE */
+
+	dpos = os_strstr(desc, " - ");
+	if (dpos)
+		dlen = dpos - desc;
+	else
+		dlen = os_strlen(desc);
+	drv->adapter_desc = os_malloc(dlen + 1);
+	if (drv->adapter_desc) {
+		os_memcpy(drv->adapter_desc, desc, dlen);
+		drv->adapter_desc[dlen] = '\0';
+	}
+
+	os_free(b);
+
+	if (drv->adapter_desc == NULL)
+		return -1;
+
+	wpa_printf(MSG_DEBUG, "NDIS: Adapter description prefix '%s'",
+		   drv->adapter_desc);
+
+	return 0;
+#else /* CONFIG_USE_NDISUIO */
+	PTSTR _names;
+	char *names, *pos, *pos2;
 	ULONG len;
 	BOOLEAN res;
-	const int MAX_ADAPTERS = 32;
+#define MAX_ADAPTERS 32
 	char *name[MAX_ADAPTERS];
 	char *desc[MAX_ADAPTERS];
 	int num_name, num_desc, i, found_name, found_desc;
@@ -1423,30 +2012,27 @@
 		   PacketGetVersion());
 
 	len = 8192;
-	names = malloc(len);
-	if (names == NULL)
+	_names = os_zalloc(len);
+	if (_names == NULL)
 		return -1;
-	memset(names, 0, len);
 
-	res = PacketGetAdapterNames(names, &len);
+	res = PacketGetAdapterNames(_names, &len);
 	if (!res && len > 8192) {
-		free(names);
-		names = malloc(len);
-		if (names == NULL)
+		os_free(_names);
+		_names = os_zalloc(len);
+		if (_names == NULL)
 			return -1;
-		memset(names, 0, len);
-		res = PacketGetAdapterNames(names, &len);
+		res = PacketGetAdapterNames(_names, &len);
 	}
 
 	if (!res) {
 		wpa_printf(MSG_ERROR, "NDIS: Failed to get adapter list "
 			   "(PacketGetAdapterNames)");
-		free(names);
+		os_free(_names);
 		return -1;
 	}
 
-	/* wpa_hexdump_ascii(MSG_DEBUG, "NDIS: AdapterNames", names, len); */
-
+	names = (char *) _names;
 	if (names[0] && names[1] == '\0' && names[2] && names[3] == '\0') {
 		wpa_printf(MSG_DEBUG, "NDIS: Looks like adapter names are in "
 			   "UNICODE");
@@ -1461,7 +2047,7 @@
 			*pos++ = pos2[0];
 			pos2 += 2;
 		}
-		memcpy(pos + 2, names, pos - names);
+		os_memcpy(pos + 2, names, pos - names);
 		pos += 2;
 	} else
 		pos = names;
@@ -1472,14 +2058,14 @@
 		while (*pos && pos < names + len)
 			pos++;
 		if (pos + 1 >= names + len) {
-			free(names);
+			os_free(names);
 			return -1;
 		}
 		pos++;
 		num_name++;
 		if (num_name >= MAX_ADAPTERS) {
 			wpa_printf(MSG_DEBUG, "NDIS: Too many adapters");
-			free(names);
+			os_free(names);
 			return -1;
 		}
 		if (*pos == '\0') {
@@ -1496,7 +2082,7 @@
 		while (*pos && pos < names + len)
 			pos++;
 		if (pos + 1 >= names + len) {
-			free(names);
+			os_free(names);
 			return -1;
 		}
 		pos++;
@@ -1504,7 +2090,7 @@
 		if (num_desc >= MAX_ADAPTERS) {
 			wpa_printf(MSG_DEBUG, "NDIS: Too many adapter "
 				   "descriptions");
-			free(names);
+			os_free(names);
 			return -1;
 		}
 		if (*pos == '\0') {
@@ -1526,7 +2112,7 @@
 		wpa_printf(MSG_DEBUG, "NDIS: mismatch in adapter name and "
 			   "description counts (%d != %d)",
 			   num_name, num_desc);
-		free(names);
+		os_free(names);
 		return -1;
 	}
 
@@ -1534,13 +2120,12 @@
 	for (i = 0; i < num_name; i++) {
 		wpa_printf(MSG_DEBUG, "NDIS: %d - %s - %s",
 			   i, name[i], desc[i]);
-		if (found_name == -1 && strcmp(name[i], drv->ifname) == 0) {
+		if (found_name == -1 && os_strstr(name[i], drv->ifname))
 			found_name = i;
-		}
 		if (found_desc == -1 &&
-		    strncmp(desc[i], drv->ifname, strlen(drv->ifname)) == 0) {
+		    os_strncmp(desc[i], drv->ifname, os_strlen(drv->ifname)) ==
+		    0)
 			found_desc = i;
-		}
 	}
 
 	if (found_name < 0 && found_desc >= 0) {
@@ -1548,33 +2133,36 @@
 			   "description '%s'",
 			   name[found_desc], desc[found_desc]);
 		found_name = found_desc;
-		strncpy(drv->ifname, name[found_desc], sizeof(drv->ifname));
+		os_strncpy(drv->ifname,
+			   os_strncmp(name[found_desc], "\\Device\\NPF_", 12)
+			   == 0 ? name[found_desc] + 12 : name[found_desc],
+			   sizeof(drv->ifname));
 	}
 
 	if (found_name < 0) {
 		wpa_printf(MSG_DEBUG, "NDIS: Could not find interface '%s'",
 			   drv->ifname);
-		free(names);
+		os_free(names);
 		return -1;
 	}
 
 	i = found_name;
-	pos = strchr(desc[i], '(');
+	pos = os_strrchr(desc[i], '(');
 	if (pos) {
 		dlen = pos - desc[i];
 		pos--;
 		if (pos > desc[i] && *pos == ' ')
 			dlen--;
 	} else {
-		dlen = strlen(desc[i]);
+		dlen = os_strlen(desc[i]);
 	}
-	drv->adapter_desc = malloc(dlen + 1);
+	drv->adapter_desc = os_malloc(dlen + 1);
 	if (drv->adapter_desc) {
-		memcpy(drv->adapter_desc, desc[i], dlen);
+		os_memcpy(drv->adapter_desc, desc[i], dlen);
 		drv->adapter_desc[dlen] = '\0';
 	}
 
-	free(names);
+	os_free(names);
 
 	if (drv->adapter_desc == NULL)
 		return -1;
@@ -1583,6 +2171,500 @@
 		   drv->adapter_desc);
 
 	return 0;
+#endif /* CONFIG_USE_NDISUIO */
+}
+
+
+#if defined(CONFIG_NATIVE_WINDOWS) || defined(__CYGWIN__)
+#ifndef _WIN32_WCE
+/*
+ * These structures are undocumented for WinXP; only WinCE version is
+ * documented. These would be included wzcsapi.h if it were available. Some
+ * changes here have been needed to make the structures match with WinXP SP2.
+ * It is unclear whether these work with any other version.
+ */
+
+typedef struct {
+	LPWSTR wszGuid;
+} INTF_KEY_ENTRY, *PINTF_KEY_ENTRY;
+
+typedef struct {
+	DWORD dwNumIntfs;
+	PINTF_KEY_ENTRY pIntfs;
+} INTFS_KEY_TABLE, *PINTFS_KEY_TABLE;
+
+typedef struct {
+	DWORD dwDataLen;
+	LPBYTE pData;
+} RAW_DATA, *PRAW_DATA;
+
+typedef struct {
+	LPWSTR wszGuid;
+	LPWSTR wszDescr;
+	ULONG ulMediaState;
+	ULONG ulMediaType;
+	ULONG ulPhysicalMediaType;
+	INT nInfraMode;
+	INT nAuthMode;
+	INT nWepStatus;
+#ifndef _WIN32_WCE
+	u8 pad[2]; /* why is this needed? */
+#endif /* _WIN32_WCE */
+	DWORD dwCtlFlags;
+	DWORD dwCapabilities; /* something added for WinXP SP2(?) */
+	RAW_DATA rdSSID;
+	RAW_DATA rdBSSID;
+	RAW_DATA rdBSSIDList;
+	RAW_DATA rdStSSIDList;
+	RAW_DATA rdCtrlData;
+#ifdef UNDER_CE
+	BOOL bInitialized;
+#endif
+	DWORD nWPAMCastCipher;
+	/* add some extra buffer for later additions since this interface is
+	 * far from stable */
+	u8 later_additions[100];
+} INTF_ENTRY, *PINTF_ENTRY;
+
+#define INTF_ALL 0xffffffff
+#define INTF_ALL_FLAGS 0x0000ffff
+#define INTF_CTLFLAGS 0x00000010
+#define INTFCTL_ENABLED 0x8000
+#endif /* _WIN32_WCE */
+
+
+#ifdef _WIN32_WCE
+static int wpa_driver_ndis_rebind_adapter(struct wpa_driver_ndis_data *drv)
+{
+	HANDLE ndis;
+	TCHAR multi[100];
+	int len;
+
+	len = _tcslen(drv->adapter_name);
+	if (len > 80)
+		return -1;
+
+	ndis = CreateFile(DD_NDIS_DEVICE_NAME, GENERIC_READ | GENERIC_WRITE,
+			  0, NULL, OPEN_EXISTING, 0, NULL);
+	if (ndis == INVALID_HANDLE_VALUE) {
+		wpa_printf(MSG_DEBUG, "NDIS: Failed to open file to NDIS "
+			   "device: %d", (int) GetLastError());
+		return -1;
+	}
+
+	len++;
+	memcpy(multi, drv->adapter_name, len * sizeof(TCHAR));
+	memcpy(&multi[len], TEXT("NDISUIO\0"), 9 * sizeof(TCHAR));
+	len += 9;
+
+	if (!DeviceIoControl(ndis, IOCTL_NDIS_REBIND_ADAPTER,
+			     multi, len * sizeof(TCHAR), NULL, 0, NULL, NULL))
+	{
+		wpa_printf(MSG_DEBUG, "NDIS: IOCTL_NDIS_REBIND_ADAPTER "
+			   "failed: 0x%x", (int) GetLastError());
+		wpa_hexdump_ascii(MSG_DEBUG, "NDIS: rebind multi_sz",
+				  (u8 *) multi, len * sizeof(TCHAR));
+		CloseHandle(ndis);
+		return -1;
+	}
+
+	CloseHandle(ndis);
+
+	wpa_printf(MSG_DEBUG, "NDIS: Requested NDIS rebind of NDISUIO "
+		   "protocol");
+
+	return 0;
+}
+#endif /* _WIN32_WCE */
+
+
+static int wpa_driver_ndis_set_wzc(struct wpa_driver_ndis_data *drv,
+				   int enable)
+{
+#ifdef _WIN32_WCE
+	HKEY hk, hk2;
+	LONG ret;
+	DWORD i, hnd, len;
+	TCHAR keyname[256], devname[256];
+
+#define WZC_DRIVER TEXT("Drivers\\BuiltIn\\ZeroConfig")
+
+	if (enable) {
+		HANDLE h;
+		h = ActivateDeviceEx(WZC_DRIVER, NULL, 0, NULL);
+		if (h == INVALID_HANDLE_VALUE || h == 0) {
+			wpa_printf(MSG_DEBUG, "NDIS: Failed to re-enable WZC "
+				   "- ActivateDeviceEx failed: %d",
+				   (int) GetLastError());
+			return -1;
+		}
+
+		wpa_printf(MSG_DEBUG, "NDIS: WZC re-enabled");
+		return wpa_driver_ndis_rebind_adapter(drv);
+	}
+
+	/*
+	 * Unfortunately, just disabling the WZC for an interface is not enough
+	 * to free NDISUIO for us, so need to disable and unload WZC completely
+	 * for now when using WinCE with NDISUIO. In addition, must request
+	 * NDISUIO protocol to be rebound to the adapter in order to free the
+	 * NDISUIO binding that WZC hold before us.
+	 */
+
+	/* Enumerate HKLM\Drivers\Active\* to find a handle to WZC. */
+	ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, DEVLOAD_ACTIVE_KEY, 0, 0, &hk);
+	if (ret != ERROR_SUCCESS) {
+		wpa_printf(MSG_DEBUG, "NDIS: RegOpenKeyEx(DEVLOAD_ACTIVE_KEY) "
+			   "failed: %d %d", (int) ret, (int) GetLastError());
+		return -1;
+	}
+
+	for (i = 0; ; i++) {
+		len = sizeof(keyname);
+		ret = RegEnumKeyEx(hk, i, keyname, &len, NULL, NULL, NULL,
+				   NULL);
+		if (ret != ERROR_SUCCESS) {
+			wpa_printf(MSG_DEBUG, "NDIS: Could not find active "
+				   "WZC - assuming it is not running.");
+			RegCloseKey(hk);
+			return -1;
+		}
+
+		ret = RegOpenKeyEx(hk, keyname, 0, 0, &hk2);
+		if (ret != ERROR_SUCCESS) {
+			wpa_printf(MSG_DEBUG, "NDIS: RegOpenKeyEx(active dev) "
+				   "failed: %d %d",
+				   (int) ret, (int) GetLastError());
+			continue;
+		}
+
+		len = sizeof(devname);
+		ret = RegQueryValueEx(hk2, DEVLOAD_DEVKEY_VALNAME, NULL, NULL,
+				      (LPBYTE) devname, &len);
+		if (ret != ERROR_SUCCESS) {
+			wpa_printf(MSG_DEBUG, "NDIS: RegQueryValueEx("
+				   "DEVKEY_VALNAME) failed: %d %d",
+				   (int) ret, (int) GetLastError());
+			RegCloseKey(hk2);
+			continue;
+		}
+
+		if (_tcscmp(devname, WZC_DRIVER) == 0)
+			break;
+
+		RegCloseKey(hk2);
+	}
+
+	RegCloseKey(hk);
+
+	/* Found WZC - get handle to it. */
+	len = sizeof(hnd);
+	ret = RegQueryValueEx(hk2, DEVLOAD_HANDLE_VALNAME, NULL, NULL,
+			      (PUCHAR) &hnd, &len);
+	if (ret != ERROR_SUCCESS) {
+		wpa_printf(MSG_DEBUG, "NDIS: RegQueryValueEx(HANDLE_VALNAME) "
+			   "failed: %d %d", (int) ret, (int) GetLastError());
+		RegCloseKey(hk2);
+		return -1;
+	}
+
+	RegCloseKey(hk2);
+
+	/* Deactivate WZC */
+	if (!DeactivateDevice((HANDLE) hnd)) {
+		wpa_printf(MSG_DEBUG, "NDIS: DeactivateDevice failed: %d",
+			   (int) GetLastError());
+		return -1;
+	}
+
+	wpa_printf(MSG_DEBUG, "NDIS: Disabled WZC temporarily");
+	drv->wzc_disabled = 1;
+	return wpa_driver_ndis_rebind_adapter(drv);
+
+#else /* _WIN32_WCE */
+
+	HMODULE hm;
+	DWORD (WINAPI *wzc_enum_interf)(LPWSTR pSrvAddr,
+					PINTFS_KEY_TABLE pIntfs);
+	DWORD (WINAPI *wzc_query_interf)(LPWSTR pSrvAddr, DWORD dwInFlags,
+					 PINTF_ENTRY pIntf,
+					 LPDWORD pdwOutFlags);
+	DWORD (WINAPI *wzc_set_interf)(LPWSTR pSrvAddr, DWORD dwInFlags,
+				       PINTF_ENTRY pIntf, LPDWORD pdwOutFlags);
+	int ret = -1, j;
+	DWORD res;
+	INTFS_KEY_TABLE guids;
+	INTF_ENTRY intf;
+	char guid[128];
+	WCHAR *pos;
+	DWORD flags, i;
+
+	hm = LoadLibrary(TEXT("wzcsapi.dll"));
+	if (hm == NULL) {
+		wpa_printf(MSG_DEBUG, "NDIS: Failed to load wzcsapi.dll (%u) "
+			   "- WZC probably not running",
+			   (unsigned int) GetLastError());
+		return -1;
+	}
+
+#ifdef _WIN32_WCE
+	wzc_enum_interf = (void *) GetProcAddressA(hm, "WZCEnumInterfaces");
+	wzc_query_interf = (void *) GetProcAddressA(hm, "WZCQueryInterface");
+	wzc_set_interf = (void *) GetProcAddressA(hm, "WZCSetInterface");
+#else /* _WIN32_WCE */
+	wzc_enum_interf = (void *) GetProcAddress(hm, "WZCEnumInterfaces");
+	wzc_query_interf = (void *) GetProcAddress(hm, "WZCQueryInterface");
+	wzc_set_interf = (void *) GetProcAddress(hm, "WZCSetInterface");
+#endif /* _WIN32_WCE */
+
+	if (wzc_enum_interf == NULL || wzc_query_interf == NULL ||
+	    wzc_set_interf == NULL) {
+		wpa_printf(MSG_DEBUG, "NDIS: WZCEnumInterfaces, "
+			   "WZCQueryInterface, or WZCSetInterface not found "
+			   "in wzcsapi.dll");
+		goto fail;
+	}
+
+	os_memset(&guids, 0, sizeof(guids));
+	res = wzc_enum_interf(NULL, &guids);
+	if (res != 0) {
+		wpa_printf(MSG_DEBUG, "NDIS: WZCEnumInterfaces failed: %d; "
+			   "WZC service is apparently not running",
+			   (int) res);
+		goto fail;
+	}
+
+	wpa_printf(MSG_DEBUG, "NDIS: WZCEnumInterfaces: %d interfaces",
+		   (int) guids.dwNumIntfs);
+
+	for (i = 0; i < guids.dwNumIntfs; i++) {
+		pos = guids.pIntfs[i].wszGuid;
+		for (j = 0; j < sizeof(guid); j++) {
+			guid[j] = (char) *pos;
+			if (*pos == 0)
+				break;
+			pos++;
+		}
+		guid[sizeof(guid) - 1] = '\0';
+		wpa_printf(MSG_DEBUG, "NDIS: intfs %d GUID '%s'",
+			   (int) i, guid);
+		if (os_strstr(drv->ifname, guid) == NULL)
+			continue;
+
+		wpa_printf(MSG_DEBUG, "NDIS: Current interface found from "
+			   "WZC");
+		break;
+	}
+
+	if (i >= guids.dwNumIntfs) {
+		wpa_printf(MSG_DEBUG, "NDIS: Current interface not found from "
+			   "WZC");
+		goto fail;
+	}
+
+	os_memset(&intf, 0, sizeof(intf));
+	intf.wszGuid = guids.pIntfs[i].wszGuid;
+	/* Set flags to verify that the structure has not changed. */
+	intf.dwCtlFlags = -1;
+	flags = 0;
+	res = wzc_query_interf(NULL, INTFCTL_ENABLED, &intf, &flags);
+	if (res != 0) {
+		wpa_printf(MSG_DEBUG, "NDIS: Could not query flags for the "
+			   "WZC interface: %d (0x%x)",
+			   (int) res, (int) res);
+		wpa_printf(MSG_DEBUG, "NDIS: GetLastError: %u",
+			   (unsigned int) GetLastError());
+		goto fail;
+	}
+
+	wpa_printf(MSG_DEBUG, "NDIS: WZC interface flags 0x%x dwCtlFlags 0x%x",
+		   (int) flags, (int) intf.dwCtlFlags);
+
+	if (intf.dwCtlFlags == -1) {
+		wpa_printf(MSG_DEBUG, "NDIS: Looks like wzcsapi has changed "
+			   "again - could not disable WZC");
+		wpa_hexdump(MSG_MSGDUMP, "NDIS: intf",
+			    (u8 *) &intf, sizeof(intf));
+		goto fail;
+	}
+
+	if (enable) {
+		if (!(intf.dwCtlFlags & INTFCTL_ENABLED)) {
+			wpa_printf(MSG_DEBUG, "NDIS: Enabling WZC for this "
+				   "interface");
+			intf.dwCtlFlags |= INTFCTL_ENABLED;
+			res = wzc_set_interf(NULL, INTFCTL_ENABLED, &intf,
+					     &flags);
+			if (res != 0) {
+				wpa_printf(MSG_DEBUG, "NDIS: Failed to enable "
+					   "WZC: %d (0x%x)",
+					   (int) res, (int) res);
+				wpa_printf(MSG_DEBUG, "NDIS: GetLastError: %u",
+					   (unsigned int) GetLastError());
+				goto fail;
+			}
+			wpa_printf(MSG_DEBUG, "NDIS: Re-enabled WZC for this "
+				   "interface");
+			drv->wzc_disabled = 0;
+		}
+	} else {
+		if (intf.dwCtlFlags & INTFCTL_ENABLED) {
+			wpa_printf(MSG_DEBUG, "NDIS: Disabling WZC for this "
+				   "interface");
+			intf.dwCtlFlags &= ~INTFCTL_ENABLED;
+			res = wzc_set_interf(NULL, INTFCTL_ENABLED, &intf,
+					     &flags);
+			if (res != 0) {
+				wpa_printf(MSG_DEBUG, "NDIS: Failed to "
+					   "disable WZC: %d (0x%x)",
+					   (int) res, (int) res);
+				wpa_printf(MSG_DEBUG, "NDIS: GetLastError: %u",
+					   (unsigned int) GetLastError());
+				goto fail;
+			}
+			wpa_printf(MSG_DEBUG, "NDIS: Disabled WZC temporarily "
+				   "for this interface");
+			drv->wzc_disabled = 1;
+		} else {
+			wpa_printf(MSG_DEBUG, "NDIS: WZC was not enabled for "
+				   "this interface");
+		}
+	}
+
+	ret = 0;
+
+fail:
+	FreeLibrary(hm);
+
+	return ret;
+#endif /* _WIN32_WCE */
+}
+
+#else /* CONFIG_NATIVE_WINDOWS || __CYGWIN__ */
+
+static int wpa_driver_ndis_set_wzc(struct wpa_driver_ndis_data *drv,
+				   int enable)
+{
+	return 0;
+}
+
+#endif /* CONFIG_NATIVE_WINDOWS || __CYGWIN__ */
+
+
+#ifdef CONFIG_USE_NDISUIO
+/*
+ * l2_packet_ndis.c is sharing the same handle to NDISUIO, so we must be able
+ * to export this handle. This is somewhat ugly, but there is no better
+ * mechanism available to pass data from driver interface to l2_packet wrapper.
+ */
+static HANDLE driver_ndis_ndisuio_handle = INVALID_HANDLE_VALUE;
+
+HANDLE driver_ndis_get_ndisuio_handle(void)
+{
+	return driver_ndis_ndisuio_handle;
+}
+#endif /* CONFIG_USE_NDISUIO */
+
+
+static int wpa_driver_ndis_adapter_init(struct wpa_driver_ndis_data *drv)
+{
+#ifdef CONFIG_USE_NDISUIO
+#ifndef _WIN32_WCE
+#define NDISUIO_DEVICE_NAME TEXT("\\\\.\\\\Ndisuio")
+	DWORD written;
+#endif /* _WIN32_WCE */
+	drv->ndisuio = CreateFile(NDISUIO_DEVICE_NAME,
+				  GENERIC_READ | GENERIC_WRITE, 0, NULL,
+				  OPEN_EXISTING,
+				  FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
+				  INVALID_HANDLE_VALUE);
+	if (drv->ndisuio == INVALID_HANDLE_VALUE) {
+		wpa_printf(MSG_ERROR, "NDIS: Failed to open connection to "
+			   "NDISUIO: %d", (int) GetLastError());
+		return -1;
+	}
+	driver_ndis_ndisuio_handle = drv->ndisuio;
+
+#ifndef _WIN32_WCE
+	if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_BIND_WAIT, NULL, 0,
+			     NULL, 0, &written, NULL)) {
+		wpa_printf(MSG_ERROR, "NDIS: IOCTL_NDISUIO_BIND_WAIT failed: "
+			   "%d", (int) GetLastError());
+		CloseHandle(drv->ndisuio);
+		drv->ndisuio = INVALID_HANDLE_VALUE;
+		return -1;
+	}
+#endif /* _WIN32_WCE */
+
+	return 0;
+#else /* CONFIG_USE_NDISUIO */
+	return 0;
+#endif /* CONFIG_USE_NDISUIO */
+}
+
+
+static int wpa_driver_ndis_adapter_open(struct wpa_driver_ndis_data *drv)
+{
+#ifdef CONFIG_USE_NDISUIO
+	DWORD written;
+#define MAX_NDIS_DEVICE_NAME_LEN 256
+	WCHAR ifname[MAX_NDIS_DEVICE_NAME_LEN];
+	size_t len, i, pos;
+	const char *prefix = "\\DEVICE\\";
+
+#ifdef _WIN32_WCE
+	pos = 0;
+#else /* _WIN32_WCE */
+	pos = 8;
+#endif /* _WIN32_WCE */
+	len = pos + os_strlen(drv->ifname);
+	if (len >= MAX_NDIS_DEVICE_NAME_LEN)
+		return -1;
+	for (i = 0; i < pos; i++)
+		ifname[i] = (WCHAR) prefix[i];
+	for (i = pos; i < len; i++)
+		ifname[i] = (WCHAR) drv->ifname[i - pos];
+	ifname[i] = L'\0';
+
+	if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_OPEN_DEVICE,
+			     ifname, len * sizeof(WCHAR), NULL, 0, &written,
+			     NULL)) {
+		wpa_printf(MSG_ERROR, "NDIS: IOCTL_NDISUIO_OPEN_DEVICE "
+			   "failed: %d", (int) GetLastError());
+		wpa_hexdump_ascii(MSG_DEBUG, "NDIS: ifname",
+				  (const u8 *) ifname, len * sizeof(WCHAR));
+		CloseHandle(drv->ndisuio);
+		drv->ndisuio = INVALID_HANDLE_VALUE;
+		return -1;
+	}
+
+	wpa_printf(MSG_DEBUG, "NDIS: Opened NDISUIO device successfully");
+
+	return 0;
+#else /* CONFIG_USE_NDISUIO */
+	char ifname[128];
+	os_snprintf(ifname, sizeof(ifname), "\\Device\\NPF_%s", drv->ifname);
+	drv->adapter = PacketOpenAdapter(ifname);
+	if (drv->adapter == NULL) {
+		wpa_printf(MSG_DEBUG, "NDIS: PacketOpenAdapter failed for "
+			   "'%s'", ifname);
+		return -1;
+	}
+	return 0;
+#endif /* CONFIG_USE_NDISUIO */
+}
+
+
+static void wpa_driver_ndis_adapter_close(struct wpa_driver_ndis_data *drv)
+{
+#ifdef CONFIG_USE_NDISUIO
+	driver_ndis_ndisuio_handle = INVALID_HANDLE_VALUE;
+	if (drv->ndisuio != INVALID_HANDLE_VALUE)
+		CloseHandle(drv->ndisuio);
+#else /* CONFIG_USE_NDISUIO */
+	if (drv->adapter)
+		PacketCloseAdapter(drv->adapter);
+#endif /* CONFIG_USE_NDISUIO */
 }
 
 
@@ -1591,24 +2673,38 @@
 	struct wpa_driver_ndis_data *drv;
 	u32 mode;
 
-	drv = malloc(sizeof(*drv));
+	drv = os_zalloc(sizeof(*drv));
 	if (drv == NULL)
 		return NULL;
-	memset(drv, 0, sizeof(*drv));
 	drv->ctx = ctx;
-	strncpy(drv->ifname, ifname, sizeof(drv->ifname));
-	drv->event_sock = -1;
+	/*
+	 * Compatibility code to strip possible prefix from the GUID. Previous
+	 * versions include \Device\NPF_ prefix for all names, but the internal
+	 * interface name is now only the GUI. Both Packet32 and NDISUIO
+	 * prefixes are supported.
+	 */
+	if (os_strncmp(ifname, "\\Device\\NPF_", 12) == 0)
+		ifname += 12;
+	else if (os_strncmp(ifname, "\\DEVICE\\", 8) == 0)
+		ifname += 8;
+	os_strncpy(drv->ifname, ifname, sizeof(drv->ifname));
+
+	if (wpa_driver_ndis_adapter_init(drv) < 0) {
+		os_free(drv);
+		return NULL;
+	}
 
 	if (wpa_driver_ndis_get_names(drv) < 0) {
-		free(drv);
+		wpa_driver_ndis_adapter_close(drv);
+		os_free(drv);
 		return NULL;
 	}
 
-	drv->adapter = PacketOpenAdapter(drv->ifname);
-	if (drv->adapter == NULL) {
-		wpa_printf(MSG_DEBUG, "NDIS: PacketOpenAdapter failed for "
-			   "'%s'", drv->ifname);
-		free(drv);
+	wpa_driver_ndis_set_wzc(drv, 0);
+
+	if (wpa_driver_ndis_adapter_open(drv) < 0) {
+		wpa_driver_ndis_adapter_close(drv);
+		os_free(drv);
 		return NULL;
 	}
 
@@ -1616,8 +2712,8 @@
 			 drv->own_addr, ETH_ALEN) < 0) {
 		wpa_printf(MSG_DEBUG, "NDIS: Get OID_802_3_CURRENT_ADDRESS "
 			   "failed");
-		PacketCloseAdapter(drv->adapter);
-		free(drv);
+		wpa_driver_ndis_adapter_close(drv);
+		os_free(drv);
 		return NULL;
 	}
 	wpa_driver_ndis_get_capability(drv);
@@ -1628,7 +2724,23 @@
 
 	eloop_register_timeout(1, 0, wpa_driver_ndis_poll_timeout, drv, NULL);
 
-	wpa_driver_register_event_cb(drv);
+#ifdef CONFIG_NDIS_EVENTS_INTEGRATED
+	drv->events = ndis_events_init(&drv->events_pipe, &drv->event_avail,
+				       drv->ifname, drv->adapter_desc);
+	if (drv->events == NULL) {
+		wpa_driver_ndis_deinit(drv);
+		return NULL;
+	}
+	eloop_register_event(drv->event_avail, sizeof(drv->event_avail),
+			     wpa_driver_ndis_event_pipe_cb, drv, NULL);
+#endif /* CONFIG_NDIS_EVENTS_INTEGRATED */
+
+#ifdef _WIN32_WCE
+	if (ndisuio_notification_init(drv) < 0) {
+		wpa_driver_ndis_deinit(drv);
+		return NULL;
+	}
+#endif /* _WIN32_WCE */
 
 	/* Set mode here in case card was configured for ad-hoc mode
 	 * previously. */
@@ -1655,6 +2767,20 @@
 static void wpa_driver_ndis_deinit(void *priv)
 {
 	struct wpa_driver_ndis_data *drv = priv;
+
+#ifdef CONFIG_NDIS_EVENTS_INTEGRATED
+	if (drv->events) {
+		eloop_unregister_event(drv->event_avail,
+				       sizeof(drv->event_avail));
+		ndis_events_deinit(drv->events);
+	}
+#endif /* CONFIG_NDIS_EVENTS_INTEGRATED */
+
+#ifdef _WIN32_WCE
+	ndisuio_notification_deinit(drv);
+#endif /* _WIN32_WCE */
+
+	eloop_cancel_timeout(wpa_driver_ndis_scan_timeout, drv, drv->ctx);
 	eloop_cancel_timeout(wpa_driver_ndis_poll_timeout, drv, NULL);
 	wpa_driver_ndis_flush_pmkid(drv);
 	wpa_driver_ndis_disconnect(drv);
@@ -1662,37 +2788,53 @@
 		wpa_printf(MSG_DEBUG, "NDIS: failed to disassociate and turn "
 			   "radio off");
 	}
-	if (drv->event_sock >= 0) {
-		eloop_unregister_read_sock(drv->event_sock);
-		close(drv->event_sock);
-	}
-	if (drv->adapter)
-		PacketCloseAdapter(drv->adapter);
 
-	free(drv->adapter_desc);
-	free(drv);
+	wpa_driver_ndis_adapter_close(drv);
+
+	if (drv->wzc_disabled)
+		wpa_driver_ndis_set_wzc(drv, 1);
+
+#ifdef _WIN32_WCE
+	os_free(drv->adapter_name);
+#endif /* _WIN32_WCE */
+	os_free(drv->adapter_desc);
+	os_free(drv);
 }
 
 
 const struct wpa_driver_ops wpa_driver_ndis_ops = {
-	.name = "ndis",
-	.desc = "Windows NDIS driver",
-	.init = wpa_driver_ndis_init,
-	.deinit = wpa_driver_ndis_deinit,
-	.set_wpa = wpa_driver_ndis_set_wpa,
-	.scan = wpa_driver_ndis_scan,
-	.get_scan_results = wpa_driver_ndis_get_scan_results,
-	.get_bssid = wpa_driver_ndis_get_bssid,
-	.get_ssid = wpa_driver_ndis_get_ssid,
-	.set_key = wpa_driver_ndis_set_key,
-	.associate = wpa_driver_ndis_associate,
-	.deauthenticate = wpa_driver_ndis_deauthenticate,
-	.disassociate = wpa_driver_ndis_disassociate,
-	.poll = wpa_driver_ndis_poll,
-	.add_pmkid = wpa_driver_ndis_add_pmkid,
-	.remove_pmkid = wpa_driver_ndis_remove_pmkid,
-	.flush_pmkid = wpa_driver_ndis_flush_pmkid,
-	.get_capa = wpa_driver_ndis_get_capa,
-	.get_ifname = wpa_driver_ndis_get_ifname,
-	.get_mac_addr = wpa_driver_ndis_get_mac_addr,
+	"ndis",
+	"Windows NDIS driver",
+	wpa_driver_ndis_get_bssid,
+	wpa_driver_ndis_get_ssid,
+	wpa_driver_ndis_set_wpa,
+	wpa_driver_ndis_set_key,
+	wpa_driver_ndis_init,
+	wpa_driver_ndis_deinit,
+	NULL /* set_param */,
+	NULL /* set_countermeasures */,
+	NULL /* set_drop_unencrypted */,
+	wpa_driver_ndis_scan,
+	wpa_driver_ndis_get_scan_results,
+	wpa_driver_ndis_deauthenticate,
+	wpa_driver_ndis_disassociate,
+	wpa_driver_ndis_associate,
+	NULL /* set_auth_alg */,
+	wpa_driver_ndis_add_pmkid,
+	wpa_driver_ndis_remove_pmkid,
+	wpa_driver_ndis_flush_pmkid,
+	wpa_driver_ndis_get_capa,
+	wpa_driver_ndis_poll,
+	wpa_driver_ndis_get_ifname,
+	wpa_driver_ndis_get_mac_addr,
+	NULL /* send_eapol */,
+	NULL /* set_operstate */,
+	NULL /* mlme_setprotection */,
+	NULL /* get_hw_feature_data */,
+	NULL /* set_channel */,
+	NULL /* set_ssid */,
+	NULL /* set_bssid */,
+	NULL /* send_mlme */,
+	NULL /* mlme_add_sta */,
+	NULL /* mlme_remove_sta */
 };
Index: wpa.h
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/wpa.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/wpa.h -L contrib/wpa_supplicant/wpa.h -u -r1.2 -r1.3
--- contrib/wpa_supplicant/wpa.h
+++ contrib/wpa_supplicant/wpa.h
@@ -1,6 +1,6 @@
 /*
  * wpa_supplicant - WPA definitions
- * Copyright (c) 2003-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2003-2006, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -16,30 +16,15 @@
 #define WPA_H
 
 #include "defs.h"
+#include "wpa_common.h"
 
+#ifndef BIT
 #define BIT(n) (1 << (n))
-
-struct ieee802_1x_hdr {
-	u8 version;
-	u8 type;
-	u16 length;
-	/* followed by length octets of data */
-} __attribute__ ((packed));
-
-#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 };
-
+#endif
 
 #define WPA_CAPABILITY_PREAUTH BIT(0)
+#define WPA_CAPABILITY_MGMT_FRAME_PROTECTION BIT(6)
+#define WPA_CAPABILITY_PEERKEY_ENABLED BIT(9)
 
 #define GENERIC_INFO_ELEM 0xdd
 #define RSN_INFO_ELEM 0x30
@@ -95,6 +80,8 @@
 	void (*set_config_blob)(void *ctx, struct wpa_config_blob *blob);
 	const struct wpa_config_blob * (*get_config_blob)(void *ctx,
 							  const char *name);
+	int (*mlme_setprotection)(void *ctx, const u8 *addr,
+				  int protection_type, int key_type);
 };
 
 
@@ -105,7 +92,8 @@
 	WPA_PARAM_PROTO,
 	WPA_PARAM_PAIRWISE,
 	WPA_PARAM_GROUP,
-	WPA_PARAM_KEY_MGMT
+	WPA_PARAM_KEY_MGMT,
+	WPA_PARAM_MGMT_GROUP
 };
 
 struct wpa_ie_data {
@@ -116,6 +104,7 @@
 	int capabilities;
 	int num_pmkid;
 	const u8 *pmkid;
+	int mgmt_group_cipher;
 };
 
 #ifndef CONFIG_NO_WPA
@@ -130,7 +119,8 @@
 void wpa_sm_set_scard_ctx(struct wpa_sm *sm, void *scard_ctx);
 void wpa_sm_set_config(struct wpa_sm *sm, struct wpa_ssid *config);
 void wpa_sm_set_own_addr(struct wpa_sm *sm, const u8 *addr);
-void wpa_sm_set_ifname(struct wpa_sm *sm, const char *ifname);
+void wpa_sm_set_ifname(struct wpa_sm *sm, const char *ifname,
+		       const char *bridge_ifname);
 void wpa_sm_set_eapol(struct wpa_sm *sm, struct eapol_sm *eapol);
 int wpa_sm_set_assoc_wpa_ie(struct wpa_sm *sm, const u8 *ie, size_t len);
 int wpa_sm_set_assoc_wpa_ie_default(struct wpa_sm *sm, u8 *wpa_ie,
@@ -149,9 +139,12 @@
 
 void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise);
 
+int wpa_sm_stkstart(struct wpa_sm *sm, const u8 *peer);
+
 int wpa_parse_wpa_ie(const u8 *wpa_ie, size_t wpa_ie_len,
 		     struct wpa_ie_data *data);
 
+void wpa_sm_aborted_cached(struct wpa_sm *sm);
 int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
 		    const u8 *buf, size_t len);
 int wpa_sm_parse_own_wpa_ie(struct wpa_sm *sm, struct wpa_ie_data *data);
@@ -201,7 +194,8 @@
 {
 }
 
-static inline void wpa_sm_set_ifname(struct wpa_sm *sm, const char *ifname)
+static inline void wpa_sm_set_ifname(struct wpa_sm *sm, const char *ifname,
+				     const char *bridge_ifname)
 {
 }
 
@@ -263,12 +257,21 @@
 {
 }
 
+static inline int wpa_sm_stkstart(struct wpa_sm *sm, const u8 *peer)
+{
+	return -1;
+}
+
 static inline int wpa_parse_wpa_ie(const u8 *wpa_ie, size_t wpa_ie_len,
 				   struct wpa_ie_data *data)
 {
 	return -1;
 }
 
+static inline void wpa_sm_aborted_cached(struct wpa_sm *sm)
+{
+}
+
 static inline int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
 				  const u8 *buf, size_t len)
 {
Index: Makefile
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/Makefile,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/Makefile -L contrib/wpa_supplicant/Makefile -u -r1.2 -r1.3
--- contrib/wpa_supplicant/Makefile
+++ contrib/wpa_supplicant/Makefile
@@ -11,7 +11,7 @@
 
 ALL=wpa_supplicant wpa_passphrase wpa_cli
 
-all: verify_config $(ALL)
+all: verify_config $(ALL) dynamic_eap_methods
 
 verify_config:
 	@if [ ! -r .config ]; then \
@@ -36,13 +36,36 @@
 	for i in $(ALL); do cp $$i $(DESTDIR)/usr/local/sbin/$$i; done
 
 OBJS = config.o \
-	eloop.o common.o md5.o \
-	rc4.o sha1.o
-OBJS_p = wpa_passphrase.o sha1.o md5.o
+	common.o md5.o md4.o \
+	rc4.o sha1.o des.o
+OBJS_p = wpa_passphrase.o sha1.o md5.o md4.o \
+	common.o des.o
 OBJS_c = wpa_cli.o wpa_ctrl.o
 
 -include .config
 
+ifndef CONFIG_OS
+ifdef CONFIG_NATIVE_WINDOWS
+CONFIG_OS=win32
+else
+CONFIG_OS=unix
+endif
+endif
+
+ifeq ($(CONFIG_OS), internal)
+CFLAGS += -DOS_NO_C_LIB_DEFINES
+endif
+
+OBJS += os_$(CONFIG_OS).o
+OBJS_p += os_$(CONFIG_OS).o
+OBJS_c += os_$(CONFIG_OS).o
+
+ifndef CONFIG_ELOOP
+CONFIG_ELOOP=eloop
+endif
+OBJS += $(CONFIG_ELOOP).o
+
+
 ifdef CONFIG_EAPOL_TEST
 CFLAGS += -Werror -DEAPOL_TEST
 endif
@@ -56,6 +79,14 @@
 CFLAGS += -DCONFIG_BACKEND_FILE
 endif
 
+ifeq ($(CONFIG_BACKEND), winreg)
+OBJS += config_winreg.o
+endif
+
+ifeq ($(CONFIG_BACKEND), none)
+OBJS += config_none.o
+endif
+
 ifdef CONFIG_DRIVER_HOSTAP
 CFLAGS += -DCONFIG_DRIVER_HOSTAP
 OBJS_d += driver_hostap.o
@@ -111,15 +142,21 @@
 ifdef CONFIG_DRIVER_BSD
 CFLAGS += -DCONFIG_DRIVER_BSD
 OBJS_d += driver_bsd.o
-CONFIG_DNET_PCAP=y
-CONFIG_L2_FREEBSD=y
+ifndef CONFIG_L2_PACKET
+CONFIG_L2_PACKET=freebsd
+endif
 endif
 
 ifdef CONFIG_DRIVER_NDIS
 CFLAGS += -DCONFIG_DRIVER_NDIS
 OBJS_d += driver_ndis.o driver_ndis_.o
-CONFIG_DNET_PCAP=y
+ifndef CONFIG_L2_PACKET
+CONFIG_L2_PACKET=pcap
+endif
 CONFIG_WINPCAP=y
+ifdef CONFIG_USE_NDISUIO
+CFLAGS += -DCONFIG_USE_NDISUIO
+endif
 endif
 
 ifdef CONFIG_DRIVER_WIRED
@@ -132,116 +169,176 @@
 OBJS_d += driver_test.o
 endif
 
-ifdef CONFIG_DNET_PCAP
-CFLAGS += -DUSE_DNET_PCAP
+ifndef CONFIG_L2_PACKET
+CONFIG_L2_PACKET=linux
+endif
+
+OBJS += l2_packet_$(CONFIG_L2_PACKET).o
+
+ifeq ($(CONFIG_L2_PACKET), pcap)
 ifdef CONFIG_WINPCAP
-OBJS += l2_packet_pcap.o
 CFLAGS += -DCONFIG_WINPCAP
 LIBS += -lwpcap -lpacket
 LIBS_w += -lwpcap
 else
-ifdef CONFIG_L2_FREEBSD
-OBJS += l2_packet_freebsd.o
-LIBS += -lpcap
-else
-OBJS += l2_packet_pcap.o
 LIBS += -ldnet -lpcap
 endif
 endif
-else
-OBJS += l2_packet_linux.o
+
+ifeq ($(CONFIG_L2_PACKET), winpcap)
+LIBS += -lwpcap -lpacket
+LIBS_w += -lwpcap
+endif
+
+ifeq ($(CONFIG_L2_PACKET), freebsd)
+LIBS += -lpcap
 endif
 
 ifdef CONFIG_EAP_TLS
 # EAP-TLS
+ifeq ($(CONFIG_EAP_TLS), dyn)
+CFLAGS += -DEAP_TLS_DYNAMIC
+EAPDYN += eap_tls.so
+else
 CFLAGS += -DEAP_TLS
 OBJS += eap_tls.o
+endif
 TLS_FUNCS=y
 CONFIG_IEEE8021X_EAPOL=y
 endif
 
 ifdef CONFIG_EAP_PEAP
 # EAP-PEAP
+ifeq ($(CONFIG_EAP_PEAP), dyn)
+CFLAGS += -DEAP_PEAP_DYNAMIC
+EAPDYN += eap_peap.so
+else
 CFLAGS += -DEAP_PEAP
 OBJS += eap_peap.o
+endif
 TLS_FUNCS=y
-CONFIG_EAP_MSCHAPV2=y
 CONFIG_IEEE8021X_EAPOL=y
 CONFIG_EAP_TLV=y
 endif
 
 ifdef CONFIG_EAP_TTLS
 # EAP-TTLS
+ifeq ($(CONFIG_EAP_TTLS), dyn)
+CFLAGS += -DEAP_TTLS_DYNAMIC
+EAPDYN += eap_ttls.so
+else
 CFLAGS += -DEAP_TTLS
 OBJS += eap_ttls.o
+endif
 MS_FUNCS=y
 TLS_FUNCS=y
-CONFIG_EAP_MD5=y
 CONFIG_IEEE8021X_EAPOL=y
 endif
 
 ifdef CONFIG_EAP_MD5
-# EAP-MD5 (also used by EAP-TTLS)
+# EAP-MD5
+ifeq ($(CONFIG_EAP_MD5), dyn)
+CFLAGS += -DEAP_MD5_DYNAMIC
+EAPDYN += eap_md5.so
+else
 CFLAGS += -DEAP_MD5
 OBJS += eap_md5.o
+endif
 CONFIG_IEEE8021X_EAPOL=y
 endif
 
 # backwards compatibility for old spelling
 ifdef CONFIG_MSCHAPV2
+ifndef CONFIG_EAP_MSCHAPV2
 CONFIG_EAP_MSCHAPV2=y
 endif
+endif
 
 ifdef CONFIG_EAP_MSCHAPV2
-# EAP-MSCHAPv2 (also used by EAP-PEAP)
+# EAP-MSCHAPv2
+ifeq ($(CONFIG_EAP_MSCHAPV2), dyn)
+CFLAGS += -DEAP_MSCHAPv2_DYNAMIC
+EAPDYN += eap_mschapv2.so
+else
 CFLAGS += -DEAP_MSCHAPv2
 OBJS += eap_mschapv2.o
+endif
 MS_FUNCS=y
 CONFIG_IEEE8021X_EAPOL=y
 endif
 
 ifdef CONFIG_EAP_GTC
-# EAP-GTC (also used by EAP-PEAP)
+# EAP-GTC
+ifeq ($(CONFIG_EAP_GTC), dyn)
+CFLAGS += -DEAP_GTC_DYNAMIC
+EAPDYN += eap_gtc.so
+else
 CFLAGS += -DEAP_GTC
 OBJS += eap_gtc.o
+endif
 CONFIG_IEEE8021X_EAPOL=y
 endif
 
 ifdef CONFIG_EAP_OTP
 # EAP-OTP
+ifeq ($(CONFIG_EAP_OTP), dyn)
+CFLAGS += -DEAP_OTP_DYNAMIC
+EAPDYN += eap_otp.so
+else
 CFLAGS += -DEAP_OTP
 OBJS += eap_otp.o
+endif
 CONFIG_IEEE8021X_EAPOL=y
 endif
 
 ifdef CONFIG_EAP_SIM
 # EAP-SIM
+ifeq ($(CONFIG_EAP_SIM), dyn)
+CFLAGS += -DEAP_SIM_DYNAMIC
+EAPDYN += eap_sim.so
+else
 CFLAGS += -DEAP_SIM
 OBJS += eap_sim.o
+endif
 CONFIG_IEEE8021X_EAPOL=y
 CONFIG_EAP_SIM_COMMON=y
 endif
 
 ifdef CONFIG_EAP_LEAP
 # EAP-LEAP
+ifeq ($(CONFIG_EAP_LEAP), dyn)
+CFLAGS += -DEAP_LEAP_DYNAMIC
+EAPDYN += eap_leap.so
+else
 CFLAGS += -DEAP_LEAP
 OBJS += eap_leap.o
+endif
 MS_FUNCS=y
 CONFIG_IEEE8021X_EAPOL=y
 endif
 
 ifdef CONFIG_EAP_PSK
 # EAP-PSK
+ifeq ($(CONFIG_EAP_PSK), dyn)
+CFLAGS += -DEAP_PSK_DYNAMIC
+EAPDYN += eap_psk.so
+else
 CFLAGS += -DEAP_PSK
 OBJS += eap_psk.o eap_psk_common.o
+endif
 CONFIG_IEEE8021X_EAPOL=y
 NEED_AES=y
 endif
 
 ifdef CONFIG_EAP_AKA
 # EAP-AKA
+ifeq ($(CONFIG_EAP_AKA), dyn)
+CFLAGS += -DEAP_AKA_DYNAMIC
+EAPDYN += eap_aka.so
+else
 CFLAGS += -DEAP_AKA
 OBJS += eap_aka.o
+endif
 CONFIG_IEEE8021X_EAPOL=y
 CONFIG_EAP_SIM_COMMON=y
 endif
@@ -259,22 +356,75 @@
 
 ifdef CONFIG_EAP_FAST
 # EAP-FAST
+ifeq ($(CONFIG_EAP_FAST), dyn)
+CFLAGS += -DEAP_FAST_DYNAMIC
+EAPDYN += eap_fast.so
+else
 CFLAGS += -DEAP_FAST
 OBJS += eap_fast.o
+endif
 TLS_FUNCS=y
 endif
 
 ifdef CONFIG_EAP_PAX
 # EAP-PAX
+ifeq ($(CONFIG_EAP_PAX), dyn)
+CFLAGS += -DEAP_PAX_DYNAMIC
+EAPDYN += eap_pax.so
+else
 CFLAGS += -DEAP_PAX
 OBJS += eap_pax.o eap_pax_common.o
+endif
+CONFIG_IEEE8021X_EAPOL=y
+endif
+
+ifdef CONFIG_EAP_SAKE
+# EAP-SAKE
+ifeq ($(CONFIG_EAP_SAKE), dyn)
+CFLAGS += -DEAP_SAKE_DYNAMIC
+EAPDYN += eap_sake.so
+else
+CFLAGS += -DEAP_SAKE
+OBJS += eap_sake.o eap_sake_common.o
+endif
+CONFIG_IEEE8021X_EAPOL=y
+endif
+
+ifdef CONFIG_EAP_GPSK
+# EAP-GPSK
+ifeq ($(CONFIG_EAP_GPSK), dyn)
+CFLAGS += -DEAP_GPSK_DYNAMIC
+EAPDYN += eap_gpsk.so
+else
+CFLAGS += -DEAP_GPSK
+OBJS += eap_gpsk.o eap_gpsk_common.o
+endif
+CONFIG_IEEE8021X_EAPOL=y
+ifdef CONFIG_EAP_GPSK_SHA256
+CFLAGS += -DEAP_GPSK_SHA256
+NEED_SHA256=y
+endif
+endif
+
+ifdef CONFIG_EAP_VENDOR_TEST
+ifeq ($(CONFIG_EAP_VENDOR_TEST), dyn)
+CFLAGS += -DEAP_VENDOR_TEST_DYNAMIC
+EAPDYN += eap_vendor_test.so
+else
+CFLAGS += -DEAP_VENDOR_TEST
+OBJS += eap_vendor_test.o
+endif
 CONFIG_IEEE8021X_EAPOL=y
 endif
 
 ifdef CONFIG_IEEE8021X_EAPOL
 # IEEE 802.1X/EAPOL state machines (e.g., for RADIUS authentication)
 CFLAGS += -DIEEE8021X_EAPOL
-OBJS += eapol_sm.o eap.o
+OBJS += eapol_sm.o eap.o eap_methods.o
+ifdef CONFIG_DYNAMIC_EAP_METHODS
+CFLAGS += -DCONFIG_DYNAMIC_EAP_METHODS
+LIBS += -ldl -rdynamic
+endif
 endif
 
 ifdef CONFIG_PCSC
@@ -282,18 +432,38 @@
 CFLAGS += -DPCSC_FUNCS -I/usr/include/PCSC
 OBJS += pcsc_funcs.o
 # -lpthread may not be needed depending on how pcsc-lite was configured
+ifdef CONFIG_NATIVE_WINDOWS
+#Once MinGW gets support for WinScard, -lwinscard could be used instead of the
+#dynamic symbol loading that is now used in pcsc_funcs.c
+#LIBS += -lwinscard
+else
 LIBS += -lpcsclite -lpthread
 endif
+endif
 
 ifndef CONFIG_TLS
 CONFIG_TLS=openssl
 endif
 
+ifeq ($(CONFIG_TLS), internal)
+ifndef CONFIG_CRYPTO
+CONFIG_CRYPTO=internal
+endif
+endif
+ifeq ($(CONFIG_CRYPTO), libtomcrypt)
+CFLAGS += -DCONFIG_INTERNAL_X509
+endif
+ifeq ($(CONFIG_CRYPTO), internal)
+CFLAGS += -DCONFIG_INTERNAL_X509
+endif
+
+
 ifdef TLS_FUNCS
 # Shared TLS functions (needed for EAP_TLS, EAP_PEAP, EAP_TTLS, and EAP_FAST)
 CFLAGS += -DEAP_TLS_FUNCS
 OBJS += eap_tls_common.o
 ifeq ($(CONFIG_TLS), openssl)
+CFLAGS += -DEAP_TLS_OPENSSL
 OBJS += tls_openssl.o
 LIBS += -lssl -lcrypto
 LIBS_p += -lcrypto
@@ -302,16 +472,45 @@
 OBJS += tls_gnutls.o
 LIBS += -lgnutls -lgcrypt -lgpg-error
 LIBS_p += -lgcrypt
+ifdef CONFIG_GNUTLS_EXTRA
+CFLAGS += -DCONFIG_GNUTLS_EXTRA
+LIBS += -lgnutls-extra
+endif
 endif
 ifeq ($(CONFIG_TLS), schannel)
 OBJS += tls_schannel.o
-# Using OpenSSL for crypto at the moment; to be replaced
-LIBS += -lcrypto
-LIBS_p += -lcrypto
+endif
+ifeq ($(CONFIG_TLS), internal)
+OBJS += tls_internal.o tlsv1_common.o tlsv1_client.o asn1.o x509v3.o
+OBJS_p += asn1.o rc4.o aes_wrap.o
+ifneq ($(CONFIG_BACKEND), file)
+OBJS += base64.o
+endif
+CFLAGS += -DCONFIG_TLS_INTERNAL
+ifeq ($(CONFIG_CRYPTO), internal)
+ifdef CONFIG_INTERNAL_LIBTOMMATH
+CFLAGS += -DCONFIG_INTERNAL_LIBTOMMATH
+else
+LIBS += -ltommath
+LIBS_p += -ltommath
+endif
+endif
+ifeq ($(CONFIG_CRYPTO), libtomcrypt)
+LIBS += -ltomcrypt -ltfm
+LIBS_p += -ltomcrypt -ltfm
+endif
+endif
+ifeq ($(CONFIG_TLS), none)
+OBJS += tls_none.o
+CFLAGS += -DEAP_TLS_NONE
+CONFIG_INTERNAL_AES=y
+CONFIG_INTERNAL_SHA1=y
+CONFIG_INTERNAL_MD5=y
+CONFIG_INTERNAL_SHA256=y
 endif
 ifdef CONFIG_SMARTCARD
 ifndef CONFIG_NATIVE_WINDOWS
-ifndef CONFIG_L2_FREEBSD
+ifneq ($(CONFIG_L2_PACKET), freebsd)
 LIBS += -ldl
 endif
 endif
@@ -345,24 +544,85 @@
 LIBS_p += -lgcrypt
 endif
 ifeq ($(CONFIG_TLS), schannel)
-# Using OpenSSL for crypto at the moment; to be replaced
-LIBS += -lcrypto
-LIBS_p += -lcrypto
+endif
+ifeq ($(CONFIG_TLS), internal)
+ifeq ($(CONFIG_CRYPTO), libtomcrypt)
+LIBS += -ltomcrypt -ltfm
+LIBS_p += -ltomcrypt -ltfm
+endif
 endif
 endif
 ifeq ($(CONFIG_TLS), openssl)
 OBJS += crypto.o
 OBJS_p += crypto.o
+CONFIG_INTERNAL_SHA256=y
 endif
 ifeq ($(CONFIG_TLS), gnutls)
 OBJS += crypto_gnutls.o
 OBJS_p += crypto_gnutls.o
+CONFIG_INTERNAL_SHA256=y
 endif
 ifeq ($(CONFIG_TLS), schannel)
-# Using OpenSSL for crypto at the moment; to be replaced
-OBJS += crypto.o
-OBJS_p += crypto.o
+OBJS += crypto_cryptoapi.o
+OBJS_p += crypto_cryptoapi.o
+CONFIG_INTERNAL_SHA256=y
+endif
+ifeq ($(CONFIG_TLS), internal)
+ifeq ($(CONFIG_CRYPTO), libtomcrypt)
+OBJS += crypto_libtomcrypt.o
+OBJS_p += crypto_libtomcrypt.o
+CONFIG_INTERNAL_SHA256=y
+endif
+ifeq ($(CONFIG_CRYPTO), internal)
+OBJS += crypto_internal.o rsa.o bignum.o
+OBJS_p += crypto_internal.o rsa.o bignum.o
+CFLAGS += -DCONFIG_CRYPTO_INTERNAL
+CONFIG_INTERNAL_AES=y
+CONFIG_INTERNAL_DES=y
+CONFIG_INTERNAL_SHA1=y
+CONFIG_INTERNAL_MD4=y
+CONFIG_INTERNAL_MD5=y
+CONFIG_INTERNAL_SHA256=y
+endif
+ifeq ($(CONFIG_CRYPTO), cryptoapi)
+OBJS += crypto_cryptoapi.o
+OBJS_p += crypto_cryptoapi.o
+CFLAGS += -DCONFIG_CRYPTO_CRYPTOAPI
+CONFIG_INTERNAL_SHA256=y
+endif
+endif
+ifeq ($(CONFIG_TLS), none)
+OBJS += crypto_none.o
+OBJS_p += crypto_none.o
+CONFIG_INTERNAL_SHA256=y
+endif
+else
+CONFIG_INTERNAL_AES=y
+CONFIG_INTERNAL_SHA1=y
+CONFIG_INTERNAL_MD5=y
+endif
+
+ifdef CONFIG_INTERNAL_AES
+CFLAGS += -DINTERNAL_AES
+endif
+ifdef CONFIG_INTERNAL_SHA1
+CFLAGS += -DINTERNAL_SHA1
+endif
+ifdef CONFIG_INTERNAL_SHA256
+CFLAGS += -DINTERNAL_SHA256
+endif
+ifdef CONFIG_INTERNAL_MD5
+CFLAGS += -DINTERNAL_MD5
+endif
+ifdef CONFIG_INTERNAL_MD4
+CFLAGS += -DINTERNAL_MD4
 endif
+ifdef CONFIG_INTERNAL_DES
+CFLAGS += -DINTERNAL_DES
+endif
+
+ifdef NEED_SHA256
+OBJS += sha256.o
 endif
 
 ifdef CONFIG_WIRELESS_EXTENSION
@@ -371,8 +631,31 @@
 endif
 
 ifdef CONFIG_CTRL_IFACE
+ifeq ($(CONFIG_CTRL_IFACE), y)
+ifdef CONFIG_NATIVE_WINDOWS
+CONFIG_CTRL_IFACE=named_pipe
+else
+CONFIG_CTRL_IFACE=unix
+endif
+endif
 CFLAGS += -DCONFIG_CTRL_IFACE
-OBJS += ctrl_iface.o
+ifeq ($(CONFIG_CTRL_IFACE), unix)
+CFLAGS += -DCONFIG_CTRL_IFACE_UNIX
+endif
+ifeq ($(CONFIG_CTRL_IFACE), udp)
+CFLAGS += -DCONFIG_CTRL_IFACE_UDP
+endif
+ifeq ($(CONFIG_CTRL_IFACE), named_pipe)
+CFLAGS += -DCONFIG_CTRL_IFACE_NAMED_PIPE
+endif
+OBJS += ctrl_iface.o ctrl_iface_$(CONFIG_CTRL_IFACE).o
+endif
+
+ifdef CONFIG_CTRL_IFACE_DBUS
+CFLAGS += -DCONFIG_CTRL_IFACE_DBUS -DDBUS_API_SUBJECT_TO_CHANGE
+OBJS += ctrl_iface_dbus.o ctrl_iface_dbus_handlers.o dbus_dict_helpers.o
+LIBS += `pkg-config --libs dbus-1`
+CFLAGS += `pkg-config --cflags dbus-1`
 endif
 
 ifdef CONFIG_READLINE
@@ -381,13 +664,20 @@
 endif
 
 ifdef CONFIG_NATIVE_WINDOWS
-CFLAGS += -DCONFIG_NATIVE_WINDOWS -DCONFIG_CTRL_IFACE_UDP
+CFLAGS += -DCONFIG_NATIVE_WINDOWS
 LIBS += -lws2_32 -lgdi32 -lcrypt32
 LIBS_c += -lws2_32
+LIBS_p += -lws2_32
+ifeq ($(CONFIG_CRYPTO), cryptoapi)
+LIBS_p += -lcrypt32
+endif
 endif
 
 ifdef CONFIG_NO_STDOUT_DEBUG
 CFLAGS += -DCONFIG_NO_STDOUT_DEBUG
+ifndef CONFIG_CTRL_IFACE
+CFLAGS += -DCONFIG_NO_WPA_MSG
+endif
 endif
 
 ifdef CONFIG_IPV6
@@ -395,53 +685,117 @@
 CFLAGS += -DCONFIG_IPV6
 endif
 
+ifdef CONFIG_PEERKEY
+CFLAGS += -DCONFIG_PEERKEY
+endif
+
+ifdef CONFIG_IEEE80211W
+CFLAGS += -DCONFIG_IEEE80211W
+NEED_SHA256=y
+endif
+
 ifndef CONFIG_NO_WPA
-OBJS += wpa.o preauth.o
+OBJS += wpa.o preauth.o pmksa_cache.o
 NEED_AES=y
 else
-CFLAGS += -DCONFIG_NO_WPA
+CFLAGS += -DCONFIG_NO_WPA -DCONFIG_NO_WPA2
+endif
+
+ifdef CONFIG_NO_WPA2
+CFLAGS += -DCONFIG_NO_WPA2
+endif
+
+ifdef CONFIG_NO_AES_EXTRAS
+CFLAGS += -DCONFIG_NO_AES_WRAP
+CFLAGS += -DCONFIG_NO_AES_CTR -DCONFIG_NO_AES_OMAC1
+CFLAGS += -DCONFIG_NO_AES_EAX -DCONFIG_NO_AES_CBC
 endif
 
 ifdef NEED_AES
 OBJS += aes_wrap.o
 endif
 
+ifdef CONFIG_CLIENT_MLME
+OBJS += mlme.o
+CFLAGS += -DCONFIG_CLIENT_MLME
+endif
+
+ifndef CONFIG_MAIN
+CONFIG_MAIN=main
+endif
+
 OBJS += wpa_supplicant.o events.o
 OBJS_t := $(OBJS) eapol_test.o radius.o radius_client.o
 OBJS_t2 := $(OBJS) preauth_test.o
-OBJS += main.o drivers.o $(OBJS_d)
+OBJS += $(CONFIG_MAIN).o drivers.o $(OBJS_d)
+
+ifdef CONFIG_NDIS_EVENTS_INTEGRATED
+CFLAGS += -DCONFIG_NDIS_EVENTS_INTEGRATED
+OBJS += ndis_events.o
+EXTRALIBS += -loleaut32 -lole32 -luuid
+ifdef PLATFORMSDKLIB
+EXTRALIBS += $(PLATFORMSDKLIB)/WbemUuid.Lib
+else
+EXTRALIBS += WbemUuid.Lib
+endif
+endif
+
+ifndef LDO
+LDO=$(CC)
+endif
+
+dynamic_eap_methods: $(EAPDYN)
 
 wpa_supplicant: .config $(OBJS)
-	$(CC) -o wpa_supplicant $(OBJS) $(LIBS)
+	$(LDO) $(LDFLAGS) -o wpa_supplicant $(OBJS) $(LIBS) $(EXTRALIBS)
 
 eapol_test: .config $(OBJS_t)
-	$(CC) -o eapol_test $(OBJS_t) $(LIBS)
+	$(LDO) $(LDFLAGS) -o eapol_test $(OBJS_t) $(LIBS)
 
 preauth_test: .config $(OBJS_t2) 
-	$(CC) -o preauth_test $(OBJS_t2) $(LIBS)
+	$(LDO) $(LDFLAGS) -o preauth_test $(OBJS_t2) $(LIBS)
 
 wpa_passphrase: $(OBJS_p)
-	$(CC) -o wpa_passphrase $(OBJS_p) $(LIBS_p)
+	$(LDO) $(LDFLAGS) -o wpa_passphrase $(OBJS_p) $(LIBS_p)
 
 wpa_cli: $(OBJS_c)
-	$(CC) -o wpa_cli $(OBJS_c) $(LIBS_c)
+	$(LDO) $(LDFLAGS) -o wpa_cli $(OBJS_c) $(LIBS_c)
+
+OBJSa=asn1_test.o asn1.o x509v3.o common.o os_unix.o \
+	crypto_$(CONFIG_CRYPTO).o md5.o sha1.o \
+	rc4.o des.o aes_wrap.o \
+	bignum.o rsa.o
+asn1_test: $(OBJSa)
+	$(LDO) $(LDFLAGS) -o asn1_test $(OBJSa)
+
+OBJSx=tests/test_x509v3.o asn1.o x509v3.o \
+	common.o os_unix.o \
+	crypto_$(CONFIG_CRYPTO).o \
+	md5.o sha1.o \
+	rc4.o des.o aes_wrap.o \
+	bignum.o rsa.o
+test_x509v3: $(OBJSx)
+	$(LDO) $(LDFLAGS) -o test_x509v3 $(OBJSx)
 
 win_if_list: win_if_list.c
-	$(CC) -o $@ win_if_list.c $(CFLAGS) $(LIBS_w)
+	$(LDO) $(LDFLAGS) -o $@ win_if_list.c $(CFLAGS) $(LIBS_w)
+
+eap_psk.so: eap_psk.c eap_psk_common.c
+	$(CC) -o $@ $(CFLAGS) -shared -rdynamic -fPIC $^ \
+		-Deap_peer_psk_register=eap_peer_method_dynamic_init
+
+eap_pax.so: eap_pax.c eap_pax_common.c
+	$(CC) -o $@ $(CFLAGS) -shared -rdynamic -fPIC $^ \
+		-Deap_peer_pax_register=eap_peer_method_dynamic_init
+
+eap_sake.so: eap_sake.c eap_sake_common.c
+	$(CC) -o $@ $(CFLAGS) -shared -rdynamic -fPIC $^ \
+		-Deap_peer_sake_register=eap_peer_method_dynamic_init
+
+%.so: %.c
+	$(CC) -o $@ $(CFLAGS) -shared -rdynamic -fPIC $< \
+		-D$(*:eap_%=eap_peer_%)_register=eap_peer_method_dynamic_init
 
-# parameters for Microsoft Visual C++ Toolkit 2003 compiler
-CL=cl
-CLDIR=C:\Program Files\Microsoft Visual C++ Toolkit 2003
-PSDKDIR=C:\Program Files\Microsoft Platform SDK for Windows XP SP2
-CLFLAGS=-O
-CLLIBS=wbemuuid.lib libcmt.lib kernel32.lib uuid.lib ole32.lib oleaut32.lib \
-	ws2_32.lib
-
-ndis_events: ndis_events.cpp
-	INCLUDE="$(CLDIR)\include;$(PSDKDIR)\Include" \
-	LIB="$(CLDIR)\lib;$(PSDKDIR)\Lib" \
-	$(CL) $(CLFLAGS) -o ndis_events.exe ndis_events.cpp \
-		/link -nodefaultlib $(CLLIBS)
 
 wpa_supplicant.exe: wpa_supplicant
 	mv -f $< $@
@@ -465,39 +819,55 @@
 wpa_gui: wpa_gui/Makefile
 	$(MAKE) -C wpa_gui
 
-TEST_SRC_MS_FUNCS = ms_funcs.c crypto.c sha1.c md5.c
-test-ms_funcs: $(TEST_SRC_MS_FUNCS)
-	$(CC) -o test-ms_funcs -Wall -Werror $(TEST_SRC_MS_FUNCS) \
-		-DTEST_MAIN_MS_FUNCS -lcrypto -I../hostapd -I.
+TEST_MS_FUNCS_OBJS = crypto.o sha1.o md5.o \
+	os_unix.o rc4.o tests/test_ms_funcs.o
+test-ms_funcs: $(TEST_MS_FUNCS_OBJS)
+	$(LDO) $(LDFLAGS) -o $@ $(TEST_MS_FUNCS_OBJS) $(LIBS) -lcrypto
 	./test-ms_funcs
 	rm test-ms_funcs
 
-TEST_SRC_SHA1 = sha1.c
-test-sha1: $(TEST_SRC_SHA1)
-	$(CC) -o test-sha1 -Wall -Werror $(TEST_SRC_SHA1) \
-		-DTEST_MAIN -I../hostad -I.
+TEST_SHA1_OBJS = sha1.o md5.o tests/test_sha1.o #crypto.o
+test-sha1: $(TEST_SHA1_OBJS)
+	$(LDO) $(LDFLAGS) -o $@ $(TEST_SHA1_OBJS) $(LIBS)
 	./test-sha1
 	rm test-sha1
 
-TEST_SRC_AES_WRAP = aes_wrap.c
-test-aes_wrap: $(TEST_SRC_AES_WRAP)
-	$(CC) -o test-aes_wrap -Wall -Werror $(TEST_SRC_AES_WRAP) \
-		-DTEST_MAIN -I../hostad -I.
-	./test-aes_wrap
-	rm test-aes_wrap
-
-TEST_SRC_EAP_SIM_COMMON = eap_sim_common.c sha1.c md5.c \
-	aes_wrap.c common.c
-test-eap_sim_common: $(TEST_SRC_EAP_SIM_COMMON)
-	$(CC) -o test-eap_sim_common -Wall -Werror $(TEST_SRC_EAP_SIM_COMMON) \
-		-DTEST_MAIN_EAP_SIM_COMMON -I../hostapd -I.
+TEST_SHA256_OBJS = sha256.o md5.o tests/test_sha256.o crypto.o
+test-sha256: $(TEST_SHA256_OBJS)
+	$(LDO) $(LDFLAGS) -o $@ $(TEST_SHA256_OBJS) $(LIBS)
+	./test-sha256
+	rm test-sha256
+
+TEST_AES_OBJS = aes_wrap.o tests/test_aes.o # crypto.o
+test-aes: $(TEST_AES_OBJS)
+	$(LDO) $(LDFLAGS) -o $@ $(TEST_AES_OBJS) $(LIBS)
+	./test-aes
+	rm test-aes
+
+TEST_EAP_SIM_COMMON_OBJS = sha1.o md5.o \
+	aes_wrap.o common.o os_unix.o \
+	tests/test_eap_sim_common.o
+test-eap_sim_common: $(TEST_EAP_SIM_COMMON_OBJS)
+	$(LDO) $(LDFLAGS) -o $@ $(TEST_AES_OBJS) $(LIBS)
 	./test-eap_sim_common
 	rm test-eap_sim_common
 
-tests: test-ms_funcs test-sha1 test-aes_wrap test-eap_sim_common
+TEST_MD4_OBJS = md4.o tests/test_md4.o #crypto.o
+test-md4: $(TEST_MD4_OBJS)
+	$(LDO) $(LDFLAGS) -o $@ $(TEST_MD4_OBJS) $(LIBS)
+	./test-md4
+	rm test-md4
+
+TEST_MD5_OBJS = md5.o tests/test_md5.o #crypto.o
+test-md5: $(TEST_MD5_OBJS)
+	$(LDO) $(LDFLAGS) -o $@ $(TEST_MD5_OBJS) $(LIBS)
+	./test-md5
+	rm test-md5
+
+tests: test-ms_funcs test-sha1 test-aes test-eap_sim_common test-md4 test-md5
 
 clean:
-	rm -f core *~ *.o *.d $(ALL) $(WINALL)
+	rm -f core *~ *.o *.d eap_*.so $(ALL) $(WINALL)
 
 %.eps: %.fig
 	fig2dev -L eps $*.fig $*.eps
Index: eap_sim_common.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/eap_sim_common.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/eap_sim_common.c -L contrib/wpa_supplicant/eap_sim_common.c -u -r1.2 -r1.3
--- contrib/wpa_supplicant/eap_sim_common.c
+++ contrib/wpa_supplicant/eap_sim_common.c
@@ -1,6 +1,6 @@
 /*
- * WPA Supplicant / EAP-SIM/AKA shared routines
- * Copyright (c) 2004-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * EAP peer: EAP-SIM/AKA shared routines
+ * Copyright (c) 2004-2006, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -12,9 +12,7 @@
  * See README and COPYING for more details.
  */
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
+#include "includes.h"
 
 #include "common.h"
 #include "eap_i.h"
@@ -24,80 +22,98 @@
 #include "eap_sim_common.h"
 
 
-static void eap_sim_prf(const u8 *key, u8 *x, size_t xlen)
+static int eap_sim_prf(const u8 *key, u8 *x, size_t xlen)
 {
-	u8 xkey[64];
-	u32 t[5], _t[5];
-	int i, j, m, k;
-	u8 *xpos = x;
-	u32 carry;
-
-	/* FIPS 186-2 + change notice 1 */
-
-	memcpy(xkey, key, EAP_SIM_MK_LEN);
-	memset(xkey + EAP_SIM_MK_LEN, 0, 64 - EAP_SIM_MK_LEN);
-	t[0] = 0x67452301;
-	t[1] = 0xEFCDAB89;
-	t[2] = 0x98BADCFE;
-	t[3] = 0x10325476;
-	t[4] = 0xC3D2E1F0;
-
-	m = xlen / 40;
-	for (j = 0; j < m; j++) {
-		/* XSEED_j = 0 */
-		for (i = 0; i < 2; i++) {
-			/* XVAL = (XKEY + XSEED_j) mod 2^b */
-
-			/* w_i = G(t, XVAL) */
-			memcpy(_t, t, 20);
-			sha1_transform((u8 *) _t, xkey);
-			_t[0] = host_to_be32(_t[0]);
-			_t[1] = host_to_be32(_t[1]);
-			_t[2] = host_to_be32(_t[2]);
-			_t[3] = host_to_be32(_t[3]);
-			_t[4] = host_to_be32(_t[4]);
-			memcpy(xpos, _t, 20);
-
-			/* XKEY = (1 + XKEY + w_i) mod 2^b */
-			carry = 1;
-			for (k = 19; k >= 0; k--) {
-				carry += xkey[k] + xpos[k];
-				xkey[k] = carry & 0xff;
-				carry >>= 8;
-			}
+	return fips186_2_prf(key, EAP_SIM_MK_LEN, x, xlen);
+}
 
-			xpos += SHA1_MAC_LEN;
-		}
-		/* x_j = w_0|w_1 */
-	}
+
+void eap_sim_derive_mk(const u8 *identity, size_t identity_len,
+		       const u8 *nonce_mt, u16 selected_version,
+		       const u8 *ver_list, size_t ver_list_len,
+		       int num_chal, const u8 *kc, u8 *mk)
+{
+	u8 sel_ver[2];
+	const unsigned char *addr[5];
+	size_t len[5];
+
+	addr[0] = identity;
+	len[0] = identity_len;
+	addr[1] = kc;
+	len[1] = num_chal * EAP_SIM_KC_LEN;
+	addr[2] = nonce_mt;
+	len[2] = EAP_SIM_NONCE_MT_LEN;
+	addr[3] = ver_list;
+	len[3] = ver_list_len;
+	addr[4] = sel_ver;
+	len[4] = 2;
+
+	WPA_PUT_BE16(sel_ver, selected_version);
+
+	/* MK = SHA1(Identity|n*Kc|NONCE_MT|Version List|Selected Version) */
+	sha1_vector(5, addr, len, mk);
+	wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: MK", mk, EAP_SIM_MK_LEN);
+}
+
+
+void eap_aka_derive_mk(const u8 *identity, size_t identity_len,
+		       const u8 *ik, const u8 *ck, u8 *mk)
+{
+	const u8 *addr[3];
+	size_t len[3];
+
+	addr[0] = identity;
+	len[0] = identity_len;
+	addr[1] = ik;
+	len[1] = EAP_AKA_IK_LEN;
+	addr[2] = ck;
+	len[2] = EAP_AKA_CK_LEN;
+
+	/* MK = SHA1(Identity|IK|CK) */
+	sha1_vector(3, addr, len, mk);
+	wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: IK", ik, EAP_AKA_IK_LEN);
+	wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: CK", ck, EAP_AKA_CK_LEN);
+	wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: MK", mk, EAP_SIM_MK_LEN);
 }
 
 
-void eap_sim_derive_keys(const u8 *mk, u8 *k_encr, u8 *k_aut, u8 *msk)
+int eap_sim_derive_keys(const u8 *mk, u8 *k_encr, u8 *k_aut, u8 *msk, u8 *emsk)
 {
-	u8 buf[120], *pos;
-	eap_sim_prf(mk, buf, 120);
+	u8 buf[EAP_SIM_K_ENCR_LEN + EAP_SIM_K_AUT_LEN +
+	       EAP_SIM_KEYING_DATA_LEN + EAP_EMSK_LEN], *pos;
+	if (eap_sim_prf(mk, buf, sizeof(buf)) < 0) {
+		wpa_printf(MSG_ERROR, "EAP-SIM: Failed to derive keys");
+		return -1;
+	}
 	pos = buf;
-	memcpy(k_encr, pos, EAP_SIM_K_ENCR_LEN);
+	os_memcpy(k_encr, pos, EAP_SIM_K_ENCR_LEN);
 	pos += EAP_SIM_K_ENCR_LEN;
-	memcpy(k_aut, pos, EAP_SIM_K_AUT_LEN);
+	os_memcpy(k_aut, pos, EAP_SIM_K_AUT_LEN);
 	pos += EAP_SIM_K_AUT_LEN;
-	memcpy(msk, pos, EAP_SIM_KEYING_DATA_LEN);
+	os_memcpy(msk, pos, EAP_SIM_KEYING_DATA_LEN);
+	pos += EAP_SIM_KEYING_DATA_LEN;
+	os_memcpy(emsk, pos, EAP_EMSK_LEN);
 
 	wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: K_encr",
 			k_encr, EAP_SIM_K_ENCR_LEN);
 	wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: K_aut",
-			k_aut, EAP_SIM_K_ENCR_LEN);
-	wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: keying material",
+			k_aut, EAP_SIM_K_AUT_LEN);
+	wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: keying material (MSK)",
 			msk, EAP_SIM_KEYING_DATA_LEN);
+	wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: EMSK", emsk, EAP_EMSK_LEN);
+	os_memset(buf, 0, sizeof(buf));
+
+	return 0;
 }
 
 
-void eap_sim_derive_keys_reauth(u16 _counter,
-				const u8 *identity, size_t identity_len,
-				const u8 *nonce_s, const u8 *mk, u8 *msk)
+int eap_sim_derive_keys_reauth(u16 _counter,
+			       const u8 *identity, size_t identity_len,
+			       const u8 *nonce_s, const u8 *mk, u8 *msk,
+			       u8 *emsk)
 {
 	u8 xkey[SHA1_MAC_LEN];
+	u8 buf[EAP_SIM_KEYING_DATA_LEN + EAP_EMSK_LEN + 32];
 	u8 counter[2];
 	const u8 *addr[4];
 	size_t len[4];
@@ -125,9 +141,22 @@
 	sha1_vector(4, addr, len, xkey);
 	wpa_hexdump(MSG_DEBUG, "EAP-SIM: XKEY'", xkey, SHA1_MAC_LEN);
 
-	eap_sim_prf(xkey, msk, EAP_SIM_KEYING_DATA_LEN);
-	wpa_hexdump(MSG_DEBUG, "EAP-SIM: keying material",
-		    msk, EAP_SIM_KEYING_DATA_LEN);
+	if (eap_sim_prf(xkey, buf, sizeof(buf)) < 0) {
+		wpa_printf(MSG_ERROR, "EAP-SIM: Failed to derive keys");
+		return -1;
+	}
+	if (msk) {
+		os_memcpy(msk, buf, EAP_SIM_KEYING_DATA_LEN);
+		wpa_hexdump(MSG_DEBUG, "EAP-SIM: keying material (MSK)",
+			    msk, EAP_SIM_KEYING_DATA_LEN);
+	}
+	if (emsk) {
+		os_memcpy(emsk, buf + EAP_SIM_KEYING_DATA_LEN, EAP_EMSK_LEN);
+		wpa_hexdump(MSG_DEBUG, "EAP-SIM: EMSK", emsk, EAP_EMSK_LEN);
+	}
+	os_memset(buf, 0, sizeof(buf));
+
+	return 0;
 }
 
 
@@ -143,7 +172,7 @@
 	    mac > req + req_len - EAP_SIM_MAC_LEN)
 		return -1;
 
-	tmp = malloc(req_len);
+	tmp = os_malloc(req_len);
 	if (tmp == NULL)
 		return -1;
 
@@ -153,12 +182,19 @@
 	len[1] = extra_len;
 
 	/* HMAC-SHA1-128 */
-	memcpy(tmp, req, req_len);
-	memset(tmp + (mac - req), 0, EAP_SIM_MAC_LEN);
+	os_memcpy(tmp, req, req_len);
+	os_memset(tmp + (mac - req), 0, EAP_SIM_MAC_LEN);
+	wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Verify MAC - msg", tmp, req_len);
+	wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Verify MAC - extra data",
+		    extra, extra_len);
+	wpa_hexdump_key(MSG_MSGDUMP, "EAP-SIM: Verify MAC - K_aut",
+			k_aut, EAP_SIM_K_AUT_LEN);
 	hmac_sha1_vector(k_aut, EAP_SIM_K_AUT_LEN, 2, addr, len, hmac);
-	free(tmp);
+	wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Verify MAC: MAC",
+		    hmac, EAP_SIM_MAC_LEN);
+	os_free(tmp);
 
-	return (memcmp(hmac, mac, EAP_SIM_MAC_LEN) == 0) ? 0 : 1;
+	return (os_memcmp(hmac, mac, EAP_SIM_MAC_LEN) == 0) ? 0 : 1;
 }
 
 
@@ -175,9 +211,16 @@
 	len[1] = extra_len;
 
 	/* HMAC-SHA1-128 */
-	memset(mac, 0, EAP_SIM_MAC_LEN);
+	os_memset(mac, 0, EAP_SIM_MAC_LEN);
+	wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Add MAC - msg", msg, msg_len);
+	wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Add MAC - extra data",
+		    extra, extra_len);
+	wpa_hexdump_key(MSG_MSGDUMP, "EAP-SIM: Add MAC - K_aut",
+			k_aut, EAP_SIM_K_AUT_LEN);
 	hmac_sha1_vector(k_aut, EAP_SIM_K_AUT_LEN, 2, addr, len, hmac);
-	memcpy(mac, hmac, EAP_SIM_MAC_LEN);
+	os_memcpy(mac, hmac, EAP_SIM_MAC_LEN);
+	wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Add MAC: MAC",
+		    mac, EAP_SIM_MAC_LEN);
 }
 
 
@@ -185,10 +228,9 @@
 		       struct eap_sim_attrs *attr, int aka, int encr)
 {
 	const u8 *pos = start, *apos;
-	size_t alen, plen;
-	int list_len, i;
+	size_t alen, plen, i, list_len;
 
-	memset(attr, 0, sizeof(*attr));
+	os_memset(attr, 0, sizeof(*attr));
 	attr->id_req = NO_ID_REQ;
 	attr->notification = -1;
 	attr->counter = -1;
@@ -219,7 +261,7 @@
 			apos += 2;
 			alen -= 2;
 			if ((!aka && (alen % GSM_RAND_LEN)) ||
-			    (aka && alen != AKA_RAND_LEN)) {
+			    (aka && alen != EAP_AKA_RAND_LEN)) {
 				wpa_printf(MSG_INFO, "EAP-SIM: Invalid AT_RAND"
 					   " (len %lu)",
 					   (unsigned long) alen);
@@ -237,7 +279,7 @@
 			}
 			apos += 2;
 			alen -= 2;
-			if (alen != AKA_AUTN_LEN) {
+			if (alen != EAP_AKA_AUTN_LEN) {
 				wpa_printf(MSG_INFO, "EAP-AKA: Invalid AT_AUTN"
 					   " (len %lu)",
 					   (unsigned long) alen);
@@ -316,8 +358,9 @@
 			wpa_printf(MSG_DEBUG, "EAP-SIM: AT_VERSION_LIST");
 			if (list_len < 2 || list_len > alen - 2) {
 				wpa_printf(MSG_WARNING, "EAP-SIM: Invalid "
-					   "AT_VERSION_LIST (list_len=%d "
-					   "attr_len=%lu)", list_len,
+					   "AT_VERSION_LIST (list_len=%lu "
+					   "attr_len=%lu)",
+					   (unsigned long) list_len,
 					   (unsigned long) alen);
 				return -1;
 			}
@@ -356,6 +399,22 @@
 			wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) AT_COUNTER %d",
 				   attr->counter);
 			break;
+		case EAP_SIM_AT_COUNTER_TOO_SMALL:
+			if (!encr) {
+				wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted "
+					   "AT_COUNTER_TOO_SMALL");
+				return -1;
+			}
+			if (alen != 2) {
+				wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid "
+					   "AT_COUNTER_TOO_SMALL (alen=%lu)",
+					   (unsigned long) alen);
+				return -1;
+			}
+			wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) "
+				   "AT_COUNTER_TOO_SMALL");
+			attr->counter_too_small = 1;
+			break;
 		case EAP_SIM_AT_NONCE_S:
 			if (!encr) {
 				wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted "
@@ -444,6 +503,35 @@
 			attr->next_reauth_id = pos + 4;
 			attr->next_reauth_id_len = plen;
 			break;
+		case EAP_SIM_AT_RES:
+			wpa_printf(MSG_DEBUG, "EAP-SIM: AT_RES");
+			apos += 2;
+			alen -= 2;
+			if (!aka || alen < EAP_AKA_MIN_RES_LEN ||
+			    alen > EAP_AKA_MAX_RES_LEN) {
+				wpa_printf(MSG_INFO, "EAP-SIM: Invalid AT_RES "
+					   "(len %lu)",
+					   (unsigned long) alen);
+				return -1;
+			}
+			attr->res = apos;
+			attr->res_len = alen;
+			break;
+		case EAP_SIM_AT_AUTS:
+			wpa_printf(MSG_DEBUG, "EAP-AKA: AT_AUTS");
+			if (!aka) {
+				wpa_printf(MSG_DEBUG, "EAP-SIM: "
+					   "Unexpected AT_AUTS");
+				return -1;
+			}
+			if (alen != EAP_AKA_AUTS_LEN) {
+				wpa_printf(MSG_INFO, "EAP-AKA: Invalid AT_AUTS"
+					   " (len %lu)",
+					   (unsigned long) alen);
+				return -1;
+			}
+			attr->auts = apos;
+			break;
 		default:
 			if (pos[0] < 128) {
 				wpa_printf(MSG_INFO, "EAP-SIM: Unrecognized "
@@ -478,10 +566,10 @@
 		return NULL;
 	}
 
-	decrypted = malloc(encr_data_len);
+	decrypted = os_malloc(encr_data_len);
 	if (decrypted == NULL)
 		return NULL;
-	memcpy(decrypted, encr_data, encr_data_len);
+	os_memcpy(decrypted, encr_data, encr_data_len);
 
 	aes_128_cbc_decrypt(k_encr, iv, decrypted, encr_data_len);
 	wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Decrypted AT_ENCR_DATA",
@@ -491,7 +579,7 @@
 			       aka, 1)) {
 		wpa_printf(MSG_INFO, "EAP-SIM: (encr) Failed to parse "
 			   "decrypted AT_ENCR_DATA");
-		free(decrypted);
+		os_free(decrypted);
 		return NULL;
 	}
 
@@ -514,17 +602,15 @@
 	struct eap_hdr *eap;
 	u8 *pos;
 
-	msg = malloc(sizeof(*msg));
+	msg = os_zalloc(sizeof(*msg));
 	if (msg == NULL)
 		return NULL;
-	memset(msg, 0, sizeof(*msg));
 
-	msg->buf = malloc(EAP_SIM_INIT_LEN);
+	msg->buf = os_zalloc(EAP_SIM_INIT_LEN);
 	if (msg->buf == NULL) {
-		free(msg);
+		os_free(msg);
 		return NULL;
 	}
-	memset(msg->buf, 0, EAP_SIM_INIT_LEN);
 	msg->buf_len = EAP_SIM_INIT_LEN;
 	eap = (struct eap_hdr *) msg->buf;
 	eap->code = code;
@@ -561,7 +647,7 @@
 
 	*len = msg->used;
 	buf = msg->buf;
-	free(msg);
+	os_free(msg);
 	return buf;
 }
 
@@ -569,8 +655,8 @@
 void eap_sim_msg_free(struct eap_sim_msg *msg)
 {
 	if (msg) {
-		free(msg->buf);
-		free(msg);
+		os_free(msg->buf);
+		os_free(msg);
 	}
 }
 
@@ -578,7 +664,7 @@
 static int eap_sim_msg_resize(struct eap_sim_msg *msg, size_t add_len)
 {
 	if (msg->used + add_len > msg->buf_len) {
-		u8 *nbuf = realloc(msg->buf, msg->used + add_len);
+		u8 *nbuf = os_realloc(msg->buf, msg->used + add_len);
 		if (nbuf == NULL)
 			return -1;
 		msg->buf = nbuf;
@@ -605,10 +691,10 @@
 	start = pos = msg->buf + msg->used;
 	*pos++ = attr;
 	*pos++ = attr_len / 4;
-	memcpy(pos, data, len);
+	os_memcpy(pos, data, len);
 	if (pad_len) {
 		pos += len;
-		memset(pos, 0, pad_len);
+		os_memset(pos, 0, pad_len);
 	}
 	msg->used += attr_len;
 	return start;
@@ -635,10 +721,10 @@
 	WPA_PUT_BE16(pos, value);
 	pos += 2;
 	if (data)
-		memcpy(pos, data, len);
+		os_memcpy(pos, data, len);
 	if (pad_len) {
 		pos += len;
-		memset(pos, 0, pad_len);
+		os_memset(pos, 0, pad_len);
 	}
 	msg->used += attr_len;
 	return start;
@@ -681,7 +767,7 @@
 {
 	size_t encr_len;
 
-	if (k_encr == NULL || msg->iv == 0 || msg->encr == 0)
+	if (msg == NULL || k_encr == NULL || msg->iv == 0 || msg->encr == 0)
 		return -1;
 
 	encr_len = msg->used - msg->encr - 4;
@@ -698,7 +784,7 @@
 		pos = eap_sim_msg_add(msg, attr_pad, 0, NULL, pad_len - 4);
 		if (pos == NULL)
 			return -1;
-		memset(pos + 4, 0, pad_len - 4);
+		os_memset(pos + 4, 0, pad_len - 4);
 		encr_len += pad_len;
 	}
 	wpa_printf(MSG_DEBUG, "   (AT_ENCR_DATA data len %lu)",
@@ -752,43 +838,3 @@
 		}
 	}
 }
-
-
-#ifdef TEST_MAIN_EAP_SIM_COMMON
-static int test_eap_sim_prf(void)
-{
-	/* http://csrc.nist.gov/encryption/dss/Examples-1024bit.pdf */
-	u8 xkey[] = {
-		0xbd, 0x02, 0x9b, 0xbe, 0x7f, 0x51, 0x96, 0x0b,
-		0xcf, 0x9e, 0xdb, 0x2b, 0x61, 0xf0, 0x6f, 0x0f,
-		0xeb, 0x5a, 0x38, 0xb6
-	};
-	u8 w[] = {
-		0x20, 0x70, 0xb3, 0x22, 0x3d, 0xba, 0x37, 0x2f,
-		0xde, 0x1c, 0x0f, 0xfc, 0x7b, 0x2e, 0x3b, 0x49,
-		0x8b, 0x26, 0x06, 0x14, 0x3c, 0x6c, 0x18, 0xba,
-		0xcb, 0x0f, 0x6c, 0x55, 0xba, 0xbb, 0x13, 0x78,
-		0x8e, 0x20, 0xd7, 0x37, 0xa3, 0x27, 0x51, 0x16
-	};
-	u8 buf[40];
-
-	printf("Testing EAP-SIM PRF (FIPS 186-2 + change notice 1)\n");
-	eap_sim_prf(xkey, buf, sizeof(buf));
-	if (memcmp(w, buf, sizeof(w) != 0)) {
-		printf("eap_sim_prf failed\n");
-		return 1;
-	}
-
-	return 0;
-}
-
-
-int main(int argc, char *argv[])
-{
-	int errors = 0;
-
-	errors += test_eap_sim_prf();
-
-	return errors;
-}
-#endif /* TEST_MAIN_EAP_SIM_COMMON */
Index: wpa_supplicant.conf
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/wpa_supplicant.conf,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/wpa_supplicant.conf -L contrib/wpa_supplicant/wpa_supplicant.conf -u -r1.2 -r1.3
--- contrib/wpa_supplicant/wpa_supplicant.conf
+++ contrib/wpa_supplicant/wpa_supplicant.conf
@@ -25,16 +25,22 @@
 
 # global configuration (shared by all network blocks)
 #
-# Interface for separate control program. If this is specified, wpa_supplicant
-# will create this directory and a UNIX domain socket for listening to requests
-# from external programs (CLI/GUI, etc.) for status information and
-# configuration. The socket file will be named based on the interface name, so
-# multiple wpa_supplicant processes can be run at the same time if more than
-# one interface is used.
+# Parameters for the control interface. If this is specified, wpa_supplicant
+# will open a control interface that is available for external programs to
+# manage wpa_supplicant. The meaning of this string depends on which control
+# interface mechanism is used. For all cases, the existance of this parameter
+# in configuration is used to determine whether the control interface is
+# enabled.
+#
+# For UNIX domain sockets (default on Linux and BSD): This is a directory that
+# will be created for UNIX domain sockets for listening to requests from
+# external programs (CLI/GUI, etc.) for status information and configuration.
+# The socket file will be named based on the interface name, so multiple
+# wpa_supplicant processes can be run at the same time if more than one
+# interface is used.
 # /var/run/wpa_supplicant is the recommended directory for sockets and by
 # default, wpa_cli will use it when trying to connect with wpa_supplicant.
-ctrl_interface=/var/run/wpa_supplicant
-
+#
 # Access control for the control interface can be configured by setting the
 # directory to allow only members of a group to use sockets. This way, it is
 # possible to run wpa_supplicant as root (since it needs to change network
@@ -48,12 +54,28 @@
 # not included in the configuration file, group will not be changed from the
 # value it got by default when the directory or socket was created.
 #
-# This variable can be a group name or gid.
-#ctrl_interface_group=wheel
-ctrl_interface_group=0
+# When configuring both the directory and group, use following format:
+# DIR=/var/run/wpa_supplicant GROUP=wheel
+# DIR=/var/run/wpa_supplicant GROUP=0
+# (group can be either group name or gid)
+#
+# For UDP connections (default on Windows): The value will be ignored. This
+# variable is just used to select that the control interface is to be created.
+# The value can be set to, e.g., udp (ctrl_interface=udp)
+#
+# For Windows Named Pipe: This value can be used to set the security descriptor
+# for controlling access to the control interface. Security descriptor can be
+# set using Security Descriptor String Format (see http://msdn.microsoft.com/
+# library/default.asp?url=/library/en-us/secauthz/security/
+# security_descriptor_string_format.asp). The descriptor string needs to be
+# prefixed with SDDL=. For example, ctrl_interface=SDDL=D: would set an empty
+# DACL (which will reject all connections). See README-Windows.txt for more
+# information about SDDL string format.
+#
+ctrl_interface=/var/run/wpa_supplicant
 
 # IEEE 802.1X/EAPOL version
-# wpa_supplicant was implemented based on IEEE 802-1X-REV-d8 which defines
+# wpa_supplicant is implemented based on IEEE Std 802.1X-2004 which defines
 # EAPOL version 2. However, there are many APs that do not handle the new
 # version number correctly (they seem to drop the frames completely). In order
 # to make wpa_supplicant interoperate with these APs, the version number is set
@@ -94,11 +116,18 @@
 # They are both from the opensc project (http://www.opensc.org/)
 # By default no engines are loaded.
 # make the opensc engine available
-opensc_engine_path=/usr/lib/opensc/engine_opensc.so
+#opensc_engine_path=/usr/lib/opensc/engine_opensc.so
 # make the pkcs11 engine available
-pkcs11_engine_path=/usr/lib/opensc/engine_pkcs11.so
+#pkcs11_engine_path=/usr/lib/opensc/engine_pkcs11.so
 # configure the path to the pkcs11 module required by the pkcs11 engine
-pkcs11_module_path=/usr/lib/pkcs11/opensc-pkcs11.so
+#pkcs11_module_path=/usr/lib/pkcs11/opensc-pkcs11.so
+
+# Dynamic EAP methods
+# If EAP methods were built dynamically as shared object files, they need to be
+# loaded here before being used in the network blocks. By default, EAP methods
+# are included statically in the build, so these lines are not needed
+#load_dynamic_eap=/usr/lib/wpa_supplicant/eap_tls.so
+#load_dynamic_eap=/usr/lib/wpa_supplicant/eap_md5.so
 
 # Driver interface parameters
 # This field can be used to configure arbitrary driver interace parameters. The
@@ -126,6 +155,10 @@
 #	1 = this network block is disabled (can be enabled through ctrl_iface,
 #	    e.g., with wpa_cli or wpa_gui)
 #
+# id_str: Network identifier string for external scripts. This value is passed
+#	to external action script through wpa_cli as WPA_ID_STR environment
+#	variable to make it easier to do network specific configuration.
+#
 # ssid: SSID (mandatory); either as an ASCII string with double quotation or
 #	as hex string; network name
 #
@@ -213,6 +246,12 @@
 # Note: When using wired authentication, eapol_flags must be set to 0 for the
 # authentication to be completed successfully.
 #
+# mixed_cell: This option can be used to configure whether so called mixed
+# cells, i.e., networks that use both plaintext and encryption in the same
+# SSID, are allowed when selecting a BSS form scan results.
+# 0 = disabled (default)
+# 1 = enabled
+#
 # proactive_key_caching:
 # Enable/disable opportunistic PMKSA caching for WPA2.
 # 0 = disabled (default)
@@ -222,6 +261,12 @@
 # hex without quotation, e.g., 0102030405)
 # wep_tx_keyidx: Default WEP key index (TX) (0..3)
 #
+# peerkey: Whether PeerKey negotiation for direct links (IEEE 802.11e DLS) is
+# allowed. This is only used with RSN/WPA2.
+# 0 = disabled (default)
+# 1 = enabled
+#peerkey=1
+#
 # Following fields are only used with internal EAP implementation.
 # eap: space-separated list of accepted EAP methods
 #	MD5 = EAP-MD5 (unsecure and does not generate keying material ->
@@ -253,6 +298,9 @@
 #	On Windows, trusted CA certificates can be loaded from the system
 #	certificate store by setting this to cert_store://<name>, e.g.,
 #	ca_cert="cert_store://CA" or ca_cert="cert_store://ROOT".
+#	Note that when running wpa_supplicant as an application, the user
+#	certificate store (My user account) is used, whereas computer store
+#	(Computer account) is used when running wpasvc as a service.
 # ca_path: Directory path for CA certificate files (PEM). This path may
 #	contain multiple CA certificates in OpenSSL format. Common use for this
 #	is to point to system trusted CA list which is often installed into
@@ -274,6 +322,9 @@
 #	cert://substring_to_match
 #	hash://certificate_thumbprint_in_hex
 #	for example: private_key="hash://63093aa9c47f56ae88334c7b65a4"
+#	Note that when running wpa_supplicant as an application, the user
+#	certificate store (My user account) is used, whereas computer store
+#	(Computer account) is used when running wpasvc as a service.
 #	Alternatively, a named configuration blob can be used by setting this
 #	to blob://<blob name>.
 # private_key_passwd: Password for private key file (if left out, this will be
@@ -291,12 +342,13 @@
 #	sertificate is only accepted if it contains this string in the subject.
 #	The subject string is in following format:
 #	/C=US/ST=CA/L=San Francisco/CN=Test AS/emailAddress=as at example.com
-# altsubject_match: Substring to be matched against the alternative subject
-#	name of the authentication server certificate. If this string is set,
-#	the server sertificate is only accepted if it contains this string in
-#	an alternative subject name extension.
+# altsubject_match: Semicolon separated string of entries to be matched against
+#	the alternative subject name of the authentication server certificate.
+#	If this string is set, the server sertificate is only accepted if it
+#	contains one of the entries in an alternative subject name extension.
 #	altSubjectName string is in following format: TYPE:VALUE
-#	Example: DNS:server.example.com
+#	Example: EMAIL:server at example.com
+#	Example: DNS:server.example.com;DNS:server2.example.com
 #	Following types are supported: EMAIL, DNS, URI
 # phase1: Phase1 (outer authentication, i.e., TLS tunnel) parameters
 #	(string with field-value pairs, e.g., "peapver=0" or
@@ -336,10 +388,29 @@
 # altsubject_match2: Substring to be matched against the alternative subject
 #	name of the authentication server certificate.
 #
+# fragment_size: Maximum EAP fragment size in bytes (default 1398).
+#	This value limits the fragment size for EAP methods that support
+#	fragmentation (e.g., EAP-TLS and EAP-PEAP). This value should be set
+#	small enough to make the EAP messages fit in MTU of the network
+#	interface used for EAPOL. The default value is suitable for most
+#	cases.
+#
 # EAP-PSK variables:
 # eappsk: 16-byte (128-bit, 32 hex digits) pre-shared key in hex format
 # nai: user NAI
 #
+# EAP-PAX variables:
+# eappsk: 16-byte (128-bit, 32 hex digits) pre-shared key in hex format
+#
+# EAP-SAKE variables:
+# eappsk: 32-byte (256-bit, 64 hex digits) pre-shared key in hex format
+#	(this is concatenation of Root-Secret-A and Root-Secret-B)
+# nai: user NAI (PEERID)
+#
+# EAP-GPSK variables:
+# eappsk: Pre-shared key in hex format (at least 128 bits, i.e., 32 hex digits)
+# nai: user NAI (ID_Client)
+#
 # EAP-FAST variables:
 # pac_file: File path for the PAC entries. wpa_supplicant will need to be able
 #	to create this file and write updates to it when PAC is being
@@ -660,3 +731,10 @@
 blob-base64-exampleblob={
 SGVsbG8gV29ybGQhCg==
 }
+
+
+# Wildcard match for SSID (plaintext APs only). This example select any
+# open AP regardless of its SSID.
+network={
+	key_mgmt=NONE
+}
Index: aes.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/aes.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/aes.c -L contrib/wpa_supplicant/aes.c -u -r1.2 -r1.3
--- contrib/wpa_supplicant/aes.c
+++ contrib/wpa_supplicant/aes.c
@@ -9,7 +9,7 @@
  *   cost of reduced throughput (quite small difference on Pentium 4,
  *   10-25% when using -O1 or -O2 optimization)
  *
- * Copyright (c) 2003-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2003-2005, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -21,6 +21,8 @@
  * See README and COPYING for more details.
  */
 
+#include "includes.h"
+
 /*
  * rijndael-alg-fst.c
  *
@@ -1060,7 +1062,7 @@
 	u32 *rk;
 	if (len != 16)
 		return NULL;
-	rk = malloc(4 * 44);
+	rk = os_malloc(4 * 44);
 	if (rk == NULL)
 		return NULL;
 	rijndaelKeySetupEnc(rk, key);
@@ -1076,7 +1078,7 @@
 
 void aes_encrypt_deinit(void *ctx)
 {
-	free(ctx);
+	os_free(ctx);
 }
 
 
@@ -1085,7 +1087,7 @@
 	u32 *rk;
 	if (len != 16)
 		return NULL;
-	rk = malloc(4 * 44);
+	rk = os_malloc(4 * 44);
 	if (rk == NULL)
 		return NULL;
 	rijndaelKeySetupDec(rk, key);
@@ -1101,5 +1103,5 @@
 
 void aes_decrypt_deinit(void *ctx)
 {
-	free(ctx);
+	os_free(ctx);
 }
Index: driver_ndis.h
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/driver_ndis.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/driver_ndis.h -L contrib/wpa_supplicant/driver_ndis.h -u -r1.2 -r1.3
--- contrib/wpa_supplicant/driver_ndis.h
+++ contrib/wpa_supplicant/driver_ndis.h
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant - Windows/NDIS driver interface
- * Copyright (c) 2004-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2004-2006, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -15,6 +15,14 @@
 #ifndef DRIVER_NDIS_H
 #define DRIVER_NDIS_H
 
+#ifdef CONFIG_NDIS_EVENTS_INTEGRATED
+struct ndis_events_data;
+struct ndis_events_data * ndis_events_init(HANDLE *read_pipe, HANDLE *event,
+					   const char *ifname,
+					   const char *desc);
+void ndis_events_deinit(struct ndis_events_data *events);
+#endif /* CONFIG_NDIS_EVENTS_INTEGRATED */
+
 struct ndis_pmkid_entry {
 	struct ndis_pmkid_entry *next;
 	u8 bssid[ETH_ALEN];
@@ -23,9 +31,18 @@
 
 struct wpa_driver_ndis_data {
 	void *ctx;
-	char ifname[100];
+	char ifname[100]; /* GUID: {7EE3EFE5-C165-472F-986D-F6FBEDFE8C8D} */
+#ifdef _WIN32_WCE
+	TCHAR *adapter_name;
+	HANDLE event_queue; /* NDISUIO notifier MsgQueue */
+	HANDLE connected_event; /* WpaSupplicantConnected event */
+#endif /* _WIN32_WCE */
 	u8 own_addr[ETH_ALEN];
+#ifdef CONFIG_USE_NDISUIO
+	HANDLE ndisuio;
+#else /* CONFIG_USE_NDISUIO */
 	LPADAPTER adapter;
+#endif /* CONFIG_USE_NDISUIO */
 	u8 bssid[ETH_ALEN];
 
 	int has_capability;
@@ -33,9 +50,15 @@
 	int radio_enabled;
 	struct wpa_driver_capa capa;
 	struct ndis_pmkid_entry *pmkid;
-	int event_sock;
 	char *adapter_desc;
 	int wired;
+	int mode;
+	int wzc_disabled;
+	int oid_bssid_set;
+#ifdef CONFIG_NDIS_EVENTS_INTEGRATED
+	HANDLE events_pipe, event_avail;
+	struct ndis_events_data *events;
+#endif /* CONFIG_NDIS_EVENTS_INTEGRATED */
 };
 
 #endif /* DRIVER_NDIS_H */
Index: eap_psk.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/eap_psk.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/eap_psk.c -L contrib/wpa_supplicant/eap_psk.c -u -r1.2 -r1.3
--- contrib/wpa_supplicant/eap_psk.c
+++ contrib/wpa_supplicant/eap_psk.c
@@ -1,6 +1,6 @@
 /*
- * WPA Supplicant / EAP-PSK (draft-bersani-eap-psk-09.txt)
- * Copyright (c) 2004-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * EAP peer method: EAP-PSK (RFC 4764)
+ * Copyright (c) 2004-2007, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -15,13 +15,10 @@
  * different from WPA-PSK. This file is not needed for WPA-PSK functionality.
  */
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
+#include "includes.h"
 
 #include "common.h"
 #include "eap_i.h"
-#include "wpa_supplicant.h"
 #include "config_ssid.h"
 #include "md5.h"
 #include "aes_wrap.h"
@@ -34,7 +31,8 @@
 	u8 ak[EAP_PSK_AK_LEN], kdk[EAP_PSK_KDK_LEN], tek[EAP_PSK_TEK_LEN];
 	u8 *id_s, *id_p;
 	size_t id_s_len, id_p_len;
-	u8 key_data[EAP_PSK_MSK_LEN];
+	u8 msk[EAP_MSK_LEN];
+	u8 emsk[EAP_EMSK_LEN];
 };
 
 
@@ -48,24 +46,23 @@
 		return NULL;
 	}
 
-	data = malloc(sizeof(*data));
+	data = os_zalloc(sizeof(*data));
 	if (data == NULL)
 		return NULL;
-	memset(data, 0, sizeof(*data));
 	eap_psk_key_setup(config->eappsk, data->ak, data->kdk);
 	wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: AK", data->ak, EAP_PSK_AK_LEN);
 	wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: KDK", data->kdk, EAP_PSK_KDK_LEN);
 	data->state = PSK_INIT;
 
 	if (config->nai) {
-		data->id_p = malloc(config->nai_len);
+		data->id_p = os_malloc(config->nai_len);
 		if (data->id_p)
-			memcpy(data->id_p, config->nai, config->nai_len);
+			os_memcpy(data->id_p, config->nai, config->nai_len);
 		data->id_p_len = config->nai_len;
 	}
 	if (data->id_p == NULL) {
 		wpa_printf(MSG_INFO, "EAP-PSK: could not get own identity");
-		free(data);
+		os_free(data);
 		return NULL;
 	}
 
@@ -76,13 +73,13 @@
 static void eap_psk_deinit(struct eap_sm *sm, void *priv)
 {
 	struct eap_psk_data *data = priv;
-	free(data->id_s);
-	free(data->id_p);
-	free(data);
+	os_free(data->id_s);
+	os_free(data->id_p);
+	os_free(data);
 }
 
 
-static u8 * eap_psk_process_1(struct eap_sm *sm, struct eap_psk_data *data,
+static u8 * eap_psk_process_1(struct eap_psk_data *data,
 			      struct eap_method_ret *ret,
 			      const u8 *reqData, size_t reqDataLen,
 			      size_t *respDataLen)
@@ -107,25 +104,25 @@
 		return NULL;
 	}
 	wpa_printf(MSG_DEBUG, "EAP-PSK: Flags=0x%x", hdr1->flags);
-	if ((hdr1->flags & 0x03) != 0) {
+	if (EAP_PSK_FLAGS_GET_T(hdr1->flags) != 0) {
 		wpa_printf(MSG_INFO, "EAP-PSK: Unexpected T=%d (expected 0)",
-			   hdr1->flags & 0x03);
+			   EAP_PSK_FLAGS_GET_T(hdr1->flags));
 		ret->methodState = METHOD_DONE;
 		ret->decision = DECISION_FAIL;
 		return NULL;
 	}
 	wpa_hexdump(MSG_DEBUG, "EAP-PSK: RAND_S", hdr1->rand_s,
 		    EAP_PSK_RAND_LEN);
-	free(data->id_s);
+	os_free(data->id_s);
 	data->id_s_len = be_to_host16(hdr1->length) - sizeof(*hdr1);
-	data->id_s = malloc(data->id_s_len);
+	data->id_s = os_malloc(data->id_s_len);
 	if (data->id_s == NULL) {
 		wpa_printf(MSG_ERROR, "EAP-PSK: Failed to allocate memory for "
 			   "ID_S (len=%lu)", (unsigned long) data->id_s_len);
 		ret->ignore = TRUE;
 		return NULL;
 	}
-	memcpy(data->id_s, (u8 *) (hdr1 + 1), data->id_s_len);
+	os_memcpy(data->id_s, (u8 *) (hdr1 + 1), data->id_s_len);
 	wpa_hexdump_ascii(MSG_DEBUG, "EAP-PSK: ID_S",
 			  data->id_s, data->id_s_len);
 
@@ -136,7 +133,7 @@
 	}
 
 	*respDataLen = sizeof(*hdr2) + data->id_p_len;
-	resp = malloc(*respDataLen);
+	resp = os_malloc(*respDataLen);
 	if (resp == NULL)
 		return NULL;
 	hdr2 = (struct eap_psk_hdr_2 *) resp;
@@ -144,26 +141,26 @@
 	hdr2->identifier = hdr1->identifier;
 	hdr2->length = host_to_be16(*respDataLen);
 	hdr2->type = EAP_TYPE_PSK;
-	hdr2->flags = 1; /* T=1 */
-	memcpy(hdr2->rand_s, hdr1->rand_s, EAP_PSK_RAND_LEN);
-	memcpy(hdr2->rand_p, data->rand_p, EAP_PSK_RAND_LEN);
-	memcpy((u8 *) (hdr2 + 1), data->id_p, data->id_p_len);
+	hdr2->flags = EAP_PSK_FLAGS_SET_T(1); /* T=1 */
+	os_memcpy(hdr2->rand_s, hdr1->rand_s, EAP_PSK_RAND_LEN);
+	os_memcpy(hdr2->rand_p, data->rand_p, EAP_PSK_RAND_LEN);
+	os_memcpy((u8 *) (hdr2 + 1), data->id_p, data->id_p_len);
 	/* MAC_P = OMAC1-AES-128(AK, ID_P||ID_S||RAND_S||RAND_P) */
 	buflen = data->id_p_len + data->id_s_len + 2 * EAP_PSK_RAND_LEN;
-	buf = malloc(buflen);
+	buf = os_malloc(buflen);
 	if (buf == NULL) {
-		free(resp);
+		os_free(resp);
 		return NULL;
 	}
-	memcpy(buf, data->id_p, data->id_p_len);
+	os_memcpy(buf, data->id_p, data->id_p_len);
 	pos = buf + data->id_p_len;
-	memcpy(pos, data->id_s, data->id_s_len);
+	os_memcpy(pos, data->id_s, data->id_s_len);
 	pos += data->id_s_len;
-	memcpy(pos, hdr1->rand_s, EAP_PSK_RAND_LEN);
+	os_memcpy(pos, hdr1->rand_s, EAP_PSK_RAND_LEN);
 	pos += EAP_PSK_RAND_LEN;
-	memcpy(pos, data->rand_p, EAP_PSK_RAND_LEN);
+	os_memcpy(pos, data->rand_p, EAP_PSK_RAND_LEN);
 	omac1_aes_128(data->ak, buf, buflen, hdr2->mac_p);
-	free(buf);
+	os_free(buf);
 	wpa_hexdump(MSG_DEBUG, "EAP-PSK: RAND_P", hdr2->rand_p,
 		    EAP_PSK_RAND_LEN);
 	wpa_hexdump(MSG_DEBUG, "EAP-PSK: MAC_P", hdr2->mac_p, EAP_PSK_MAC_LEN);
@@ -176,7 +173,7 @@
 }
 
 
-static u8 * eap_psk_process_3(struct eap_sm *sm, struct eap_psk_data *data,
+static u8 * eap_psk_process_3(struct eap_psk_data *data,
 			      struct eap_method_ret *ret,
 			      const u8 *reqData, size_t reqDataLen,
 			      size_t *respDataLen)
@@ -205,9 +202,9 @@
 	left -= sizeof(*hdr3);
 	pchannel = (const u8 *) (hdr3 + 1);
 	wpa_printf(MSG_DEBUG, "EAP-PSK: Flags=0x%x", hdr3->flags);
-	if ((hdr3->flags & 0x03) != 2) {
+	if (EAP_PSK_FLAGS_GET_T(hdr3->flags) != 2) {
 		wpa_printf(MSG_INFO, "EAP-PSK: Unexpected T=%d (expected 2)",
-			   hdr3->flags & 0x03);
+			   EAP_PSK_FLAGS_GET_T(hdr3->flags));
 		ret->methodState = METHOD_DONE;
 		ret->decision = DECISION_FAIL;
 		return NULL;
@@ -227,14 +224,14 @@
 
 	/* MAC_S = OMAC1-AES-128(AK, ID_S||RAND_P) */
 	buflen = data->id_s_len + EAP_PSK_RAND_LEN;
-	buf = malloc(buflen);
+	buf = os_malloc(buflen);
 	if (buf == NULL)
 		return NULL;
-	memcpy(buf, data->id_s, data->id_s_len);
-	memcpy(buf + data->id_s_len, data->rand_p, EAP_PSK_RAND_LEN);
+	os_memcpy(buf, data->id_s, data->id_s_len);
+	os_memcpy(buf + data->id_s_len, data->rand_p, EAP_PSK_RAND_LEN);
 	omac1_aes_128(data->ak, buf, buflen, mac);
-	free(buf);
-	if (memcmp(mac, hdr3->mac_s, EAP_PSK_MAC_LEN) != 0) {
+	os_free(buf);
+	if (os_memcmp(mac, hdr3->mac_s, EAP_PSK_MAC_LEN) != 0) {
 		wpa_printf(MSG_WARNING, "EAP-PSK: Invalid MAC_S in third "
 			   "message");
 		ret->methodState = METHOD_DONE;
@@ -244,13 +241,13 @@
 	wpa_printf(MSG_DEBUG, "EAP-PSK: MAC_S verified successfully");
 
 	eap_psk_derive_keys(data->kdk, data->rand_p, data->tek,
-			    data->key_data);
+			    data->msk, data->emsk);
 	wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: TEK", data->tek, EAP_PSK_TEK_LEN);
-	wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: MSK", data->key_data,
-			EAP_PSK_MSK_LEN);
+	wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: MSK", data->msk, EAP_MSK_LEN);
+	wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: EMSK", data->emsk, EAP_EMSK_LEN);
 
-	memset(nonce, 0, 12);
-	memcpy(nonce + 12, pchannel, 4);
+	os_memset(nonce, 0, 12);
+	os_memcpy(nonce + 12, pchannel, 4);
 	pchannel += 4;
 	left -= 4;
 
@@ -265,18 +262,18 @@
 	wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: PCHANNEL - hdr", reqData, 5);
 	wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: PCHANNEL - cipher msg", msg, left);
 
-	decrypted = malloc(left);
+	decrypted = os_malloc(left);
 	if (decrypted == NULL) {
 		ret->methodState = METHOD_DONE;
 		ret->decision = DECISION_FAIL;
 		return NULL;
 	}
-	memcpy(decrypted, msg, left);
+	os_memcpy(decrypted, msg, left);
 
 	if (aes_128_eax_decrypt(data->tek, nonce, sizeof(nonce),
 				reqData, 22, decrypted, left, tag)) {
 		wpa_printf(MSG_WARNING, "EAP-PSK: PCHANNEL decryption failed");
-		free(decrypted);
+		os_free(decrypted);
 		return NULL;
 	}
 	wpa_hexdump(MSG_DEBUG, "EAP-PSK: Decrypted PCHANNEL message",
@@ -300,9 +297,9 @@
 	}
 
 	*respDataLen = sizeof(*hdr4) + 4 + 16 + 1;
-	resp = malloc(*respDataLen + 1);
+	resp = os_malloc(*respDataLen + 1);
 	if (resp == NULL) {
-		free(decrypted);
+		os_free(decrypted);
 		return NULL;
 	}
 	hdr4 = (struct eap_psk_hdr_4 *) resp;
@@ -310,13 +307,13 @@
 	hdr4->identifier = hdr3->identifier;
 	hdr4->length = host_to_be16(*respDataLen);
 	hdr4->type = EAP_TYPE_PSK;
-	hdr4->flags = 3; /* T=3 */
-	memcpy(hdr4->rand_s, hdr3->rand_s, EAP_PSK_RAND_LEN);
+	hdr4->flags = EAP_PSK_FLAGS_SET_T(3); /* T=3 */
+	os_memcpy(hdr4->rand_s, hdr3->rand_s, EAP_PSK_RAND_LEN);
 	rpchannel = (u8 *) (hdr4 + 1);
 
 	/* nonce++ */
 	inc_byte_array(nonce, sizeof(nonce));
-	memcpy(rpchannel, nonce + 12, 4);
+	os_memcpy(rpchannel, nonce + 12, 4);
 
 	data_len = 1;
 	if (decrypted[0] & EAP_PSK_E_FLAG) {
@@ -349,7 +346,7 @@
 	ret->methodState = METHOD_DONE;
 	ret->decision = failed ? DECISION_FAIL : DECISION_UNCOND_SUCC;
 
-	free(decrypted);
+	os_free(decrypted);
 
 	return resp;
 }
@@ -365,7 +362,8 @@
 	u8 *resp = NULL;
 	size_t len;
 
-	pos = eap_hdr_validate(EAP_TYPE_PSK, reqData, reqDataLen, &len);
+	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PSK,
+			       reqData, reqDataLen, &len);
 	if (pos == NULL) {
 		ret->ignore = TRUE;
 		return NULL;
@@ -379,11 +377,11 @@
 
 	switch (data->state) {
 	case PSK_INIT:
-		resp = eap_psk_process_1(sm, data, ret, reqData, len,
+		resp = eap_psk_process_1(data, ret, reqData, len,
 					 respDataLen);
 		break;
 	case PSK_MAC_SENT:
-		resp = eap_psk_process_3(sm, data, ret, reqData, len,
+		resp = eap_psk_process_3(data, ret, reqData, len,
 					 respDataLen);
 		break;
 	case PSK_DONE:
@@ -416,24 +414,55 @@
 	if (data->state != PSK_DONE)
 		return NULL;
 
-	key = malloc(EAP_PSK_MSK_LEN);
+	key = os_malloc(EAP_MSK_LEN);
 	if (key == NULL)
 		return NULL;
 
-	*len = EAP_PSK_MSK_LEN;
-	memcpy(key, data->key_data, EAP_PSK_MSK_LEN);
+	*len = EAP_MSK_LEN;
+	os_memcpy(key, data->msk, EAP_MSK_LEN);
 
 	return key;
 }
 
 
-const struct eap_method eap_method_psk =
+static u8 * eap_psk_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
 {
-	.method = EAP_TYPE_PSK,
-	.name = "PSK",
-	.init = eap_psk_init,
-	.deinit = eap_psk_deinit,
-	.process = eap_psk_process,
-	.isKeyAvailable = eap_psk_isKeyAvailable,
-	.getKey = eap_psk_getKey,
-};
+	struct eap_psk_data *data = priv;
+	u8 *key;
+
+	if (data->state != PSK_DONE)
+		return NULL;
+
+	key = os_malloc(EAP_EMSK_LEN);
+	if (key == NULL)
+		return NULL;
+
+	*len = EAP_EMSK_LEN;
+	os_memcpy(key, data->emsk, EAP_EMSK_LEN);
+
+	return key;
+}
+
+
+int eap_peer_psk_register(void)
+{
+	struct eap_method *eap;
+	int ret;
+
+	eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
+				    EAP_VENDOR_IETF, EAP_TYPE_PSK, "PSK");
+	if (eap == NULL)
+		return -1;
+
+	eap->init = eap_psk_init;
+	eap->deinit = eap_psk_deinit;
+	eap->process = eap_psk_process;
+	eap->isKeyAvailable = eap_psk_isKeyAvailable;
+	eap->getKey = eap_psk_getKey;
+	eap->get_emsk = eap_psk_get_emsk;
+
+	ret = eap_peer_method_register(eap);
+	if (ret)
+		eap_peer_method_free(eap);
+	return ret;
+}
Index: eap_ttls.h
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/eap_ttls.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/eap_ttls.h -L contrib/wpa_supplicant/eap_ttls.h -u -r1.2 -r1.3
--- contrib/wpa_supplicant/eap_ttls.h
+++ contrib/wpa_supplicant/eap_ttls.h
@@ -1,6 +1,6 @@
 /*
- * WPA Supplicant / EAP-TTLS (draft-ietf-pppext-eap-ttls-03.txt)
- * Copyright (c) 2004-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * EAP server/peer: EAP-TTLS (draft-ietf-pppext-eap-ttls-03.txt)
+ * Copyright (c) 2004-2005, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -36,11 +36,11 @@
 
 #define AVP_PAD(start, pos) \
 do { \
-	int pad; \
-	pad = (4 - (((pos) - (start)) & 3)) & 3; \
-	memset((pos), 0, pad); \
-	pos += pad; \
-} while(0)
+	int __pad; \
+	__pad = (4 - (((pos) - (start)) & 3)) & 3; \
+	os_memset((pos), 0, __pad); \
+	pos += __pad; \
+} while (0)
 
 
 /* RFC 2865 */
Index: rc4.h
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/rc4.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/rc4.h -L contrib/wpa_supplicant/rc4.h -u -r1.2 -r1.3
--- contrib/wpa_supplicant/rc4.h
+++ contrib/wpa_supplicant/rc4.h
@@ -1,6 +1,6 @@
 /*
  * RC4 stream cipher
- * Copyright (c) 2002-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2002-2005, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
Index: pcsc_funcs.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/pcsc_funcs.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/pcsc_funcs.c -L contrib/wpa_supplicant/pcsc_funcs.c -u -r1.2 -r1.3
--- contrib/wpa_supplicant/pcsc_funcs.c
+++ contrib/wpa_supplicant/pcsc_funcs.c
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant / PC/SC smartcard interface for USIM, GSM SIM
- * Copyright (c) 2004-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2004-2007, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -10,15 +10,16 @@
  * license.
  *
  * See README and COPYING for more details.
+ *
+ * This file implements wrapper functions for accessing GSM SIM and 3GPP USIM
+ * cards through PC/SC smartcard library. These functions are used to implement
+ * authentication routines for EAP-SIM and EAP-AKA.
  */
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
+#include "includes.h"
 #include <winscard.h>
 
 #include "common.h"
-#include "wpa_supplicant.h"
 #include "pcsc_funcs.h"
 
 
@@ -38,6 +39,9 @@
  *	P1 = ID of alg in card
  *	P2 = ID of secret key
  *   READ BINARY: B0 <offset high> <offset low> <len>
+ *   READ RECORD: B2 <record number> <mode> <len>
+ *	P2 (mode) = '02' (next record), '03' (previous record),
+ *		    '04' (absolute mode)
  *   VERIFY CHV: 20 00 <CHV number> 08
  *   CHANGE CHV: 24 00 <CHV number> 10
  *   DISABLE CHV: 26 00 01 08
@@ -51,6 +55,7 @@
 #define SIM_CMD_RUN_GSM_ALG		0xa0, 0x88, 0x00, 0x00, 0x10
 #define SIM_CMD_GET_RESPONSE		0xa0, 0xc0, 0x00, 0x00
 #define SIM_CMD_READ_BIN		0xa0, 0xb0, 0x00, 0x00
+#define SIM_CMD_READ_RECORD		0xa0, 0xb2, 0x00, 0x00
 #define SIM_CMD_VERIFY_CHV1		0xa0, 0x20, 0x00, 0x01, 0x08
 
 /* USIM commands */
@@ -58,6 +63,8 @@
 #define USIM_CMD_RUN_UMTS_ALG		0x00, 0x88, 0x00, 0x81, 0x22
 #define USIM_CMD_GET_RESPONSE		0x00, 0xc0, 0x00, 0x00
 
+#define SIM_RECORD_MODE_ABSOLUTE 0x04
+
 #define USIM_FSP_TEMPL_TAG		0x62
 
 #define USIM_TLV_FILE_DESC		0x82
@@ -83,20 +90,151 @@
 typedef enum { SCARD_GSM_SIM, SCARD_USIM } sim_types;
 
 struct scard_data {
-	long ctx;
-	long card;
-	unsigned long protocol;
+	SCARDCONTEXT ctx;
+	SCARDHANDLE card;
+	DWORD protocol;
 	sim_types sim_type;
 	int pin1_required;
 };
 
+#ifdef __MINGW32_VERSION
+/* MinGW does not yet support WinScard, so load the needed functions
+ * dynamically from winscard.dll for now. */
+
+static HINSTANCE dll = NULL; /* winscard.dll */
+
+static const SCARD_IO_REQUEST *dll_g_rgSCardT0Pci, *dll_g_rgSCardT1Pci;
+#undef SCARD_PCI_T0
+#define SCARD_PCI_T0 (dll_g_rgSCardT0Pci)
+#undef SCARD_PCI_T1
+#define SCARD_PCI_T1 (dll_g_rgSCardT1Pci)
+
+
+static WINSCARDAPI LONG WINAPI
+(*dll_SCardEstablishContext)(IN DWORD dwScope,
+			     IN LPCVOID pvReserved1,
+			     IN LPCVOID pvReserved2,
+			     OUT LPSCARDCONTEXT phContext);
+#define SCardEstablishContext dll_SCardEstablishContext
+
+static long (*dll_SCardReleaseContext)(long hContext);
+#define SCardReleaseContext dll_SCardReleaseContext
+
+static WINSCARDAPI LONG WINAPI
+(*dll_SCardListReadersA)(IN SCARDCONTEXT hContext,
+			 IN LPCSTR mszGroups,
+			 OUT LPSTR mszReaders,
+			 IN OUT LPDWORD pcchReaders);
+#undef SCardListReaders
+#define SCardListReaders dll_SCardListReadersA
+
+static WINSCARDAPI LONG WINAPI
+(*dll_SCardConnectA)(IN SCARDCONTEXT hContext,
+		     IN LPCSTR szReader,
+		     IN DWORD dwShareMode,
+		     IN DWORD dwPreferredProtocols,
+		     OUT LPSCARDHANDLE phCard,
+		     OUT LPDWORD pdwActiveProtocol);
+#undef SCardConnect
+#define SCardConnect dll_SCardConnectA
+
+static WINSCARDAPI LONG WINAPI
+(*dll_SCardDisconnect)(IN SCARDHANDLE hCard,
+		       IN DWORD dwDisposition);
+#define SCardDisconnect dll_SCardDisconnect
+
+static WINSCARDAPI LONG WINAPI
+(*dll_SCardTransmit)(IN SCARDHANDLE hCard,
+		     IN LPCSCARD_IO_REQUEST pioSendPci,
+		     IN LPCBYTE pbSendBuffer,
+		     IN DWORD cbSendLength,
+		     IN OUT LPSCARD_IO_REQUEST pioRecvPci,
+		     OUT LPBYTE pbRecvBuffer,
+		     IN OUT LPDWORD pcbRecvLength);
+#define SCardTransmit dll_SCardTransmit
+
+static WINSCARDAPI LONG WINAPI
+(*dll_SCardBeginTransaction)(IN SCARDHANDLE hCard);
+#define SCardBeginTransaction dll_SCardBeginTransaction
+
+static WINSCARDAPI LONG WINAPI
+(*dll_SCardEndTransaction)(IN SCARDHANDLE hCard, IN DWORD dwDisposition);
+#define SCardEndTransaction dll_SCardEndTransaction
+
+
+static int mingw_load_symbols(void)
+{
+	char *sym;
+
+	if (dll)
+		return 0;
+
+	dll = LoadLibrary("winscard");
+	if (dll == NULL) {
+		wpa_printf(MSG_DEBUG, "WinSCard: Could not load winscard.dll "
+			   "library");
+		return -1;
+	}
+
+#define LOADSYM(s) \
+	sym = #s; \
+	dll_ ## s = (void *) GetProcAddress(dll, sym); \
+	if (dll_ ## s == NULL) \
+		goto fail;
+
+	LOADSYM(SCardEstablishContext);
+	LOADSYM(SCardReleaseContext);
+	LOADSYM(SCardListReadersA);
+	LOADSYM(SCardConnectA);
+	LOADSYM(SCardDisconnect);
+	LOADSYM(SCardTransmit);
+	LOADSYM(SCardBeginTransaction);
+	LOADSYM(SCardEndTransaction);
+	LOADSYM(g_rgSCardT0Pci);
+	LOADSYM(g_rgSCardT1Pci);
+
+#undef LOADSYM
+
+	return 0;
+
+fail:
+	wpa_printf(MSG_DEBUG, "WinSCard: Could not get address for %s from "
+		   "winscard.dll", sym);
+	FreeLibrary(dll);
+	dll = NULL;
+	return -1;
+}
+
+
+static void mingw_unload_symbols(void)
+{
+	if (dll == NULL)
+		return;
+
+	FreeLibrary(dll);
+	dll = NULL;
+}
+
+#else /* __MINGW32_VERSION */
+
+#define mingw_load_symbols() 0
+#define mingw_unload_symbols() do { } while (0)
+
+#endif /* __MINGW32_VERSION */
+
 
 static int _scard_select_file(struct scard_data *scard, unsigned short file_id,
 			      unsigned char *buf, size_t *buf_len,
-			      sim_types sim_type, unsigned char *aid);
+			      sim_types sim_type, unsigned char *aid,
+			      size_t aidlen);
 static int scard_select_file(struct scard_data *scard, unsigned short file_id,
 			     unsigned char *buf, size_t *buf_len);
 static int scard_verify_pin(struct scard_data *scard, const char *pin);
+static int scard_get_record_len(struct scard_data *scard,
+				unsigned char recnum, unsigned char mode);
+static int scard_read_record(struct scard_data *scard,
+			     unsigned char *data, size_t len,
+			     unsigned char recnum, unsigned char mode);
 
 
 static int scard_parse_fsp_templ(unsigned char *buf, size_t buf_len,
@@ -175,27 +313,145 @@
 			return -1;
 		/* TODO: there could be more than one PS_DO entry because of
 		 * multiple PINs in key reference.. */
-		if (ps_do)
+		if (ps_do > 0 && (ps_do & 0x80))
 			return 1;
+		return 0;
 	}
 
 	return -1;
 }
 
 
+static int scard_get_aid(struct scard_data *scard, unsigned char *aid,
+			 size_t maxlen)
+{
+	int rlen, rec;
+	struct efdir {
+		unsigned char appl_template_tag; /* 0x61 */
+		unsigned char appl_template_len;
+		unsigned char appl_id_tag; /* 0x4f */
+		unsigned char aid_len;
+		unsigned char rid[5];
+		unsigned char appl_code[2]; /* 0x1002 for 3G USIM */
+	} *efdir;
+	unsigned char buf[100];
+	size_t blen;
+
+	efdir = (struct efdir *) buf;
+	blen = sizeof(buf);
+	if (scard_select_file(scard, SCARD_FILE_EF_DIR, buf, &blen)) {
+		wpa_printf(MSG_DEBUG, "SCARD: Failed to read EF_DIR");
+		return -1;
+	}
+	wpa_hexdump(MSG_DEBUG, "SCARD: EF_DIR select", buf, blen);
+
+	for (rec = 1; rec < 10; rec++) {
+		rlen = scard_get_record_len(scard, rec,
+					    SIM_RECORD_MODE_ABSOLUTE);
+		if (rlen < 0) {
+			wpa_printf(MSG_DEBUG, "SCARD: Failed to get EF_DIR "
+				   "record length");
+			return -1;
+		}
+		blen = sizeof(buf);
+		if (rlen > (int) blen) {
+			wpa_printf(MSG_DEBUG, "SCARD: Too long EF_DIR record");
+			return -1;
+		}
+		if (scard_read_record(scard, buf, rlen, rec,
+				      SIM_RECORD_MODE_ABSOLUTE) < 0) {
+			wpa_printf(MSG_DEBUG, "SCARD: Failed to read "
+				   "EF_DIR record %d", rec);
+			return -1;
+		}
+		wpa_hexdump(MSG_DEBUG, "SCARD: EF_DIR record", buf, rlen);
+
+		if (efdir->appl_template_tag != 0x61) {
+			wpa_printf(MSG_DEBUG, "SCARD: Unexpected application "
+				   "template tag 0x%x",
+				   efdir->appl_template_tag);
+			continue;
+		}
+
+		if (efdir->appl_template_len > rlen - 2) {
+			wpa_printf(MSG_DEBUG, "SCARD: Too long application "
+				   "template (len=%d rlen=%d)",
+				   efdir->appl_template_len, rlen);
+			continue;
+		}
+
+		if (efdir->appl_id_tag != 0x4f) {
+			wpa_printf(MSG_DEBUG, "SCARD: Unexpected application "
+				   "identifier tag 0x%x", efdir->appl_id_tag);
+			continue;
+		}
+
+		if (efdir->aid_len < 1 || efdir->aid_len > 16) {
+			wpa_printf(MSG_DEBUG, "SCARD: Invalid AID length %d",
+				   efdir->aid_len);
+			continue;
+		}
+
+		wpa_hexdump(MSG_DEBUG, "SCARD: AID from EF_DIR record",
+			    efdir->rid, efdir->aid_len);
+
+		if (efdir->appl_code[0] == 0x10 &&
+		    efdir->appl_code[1] == 0x02) {
+			wpa_printf(MSG_DEBUG, "SCARD: 3G USIM app found from "
+				   "EF_DIR record %d", rec);
+			break;
+		}
+	}
+
+	if (rec >= 10) {
+		wpa_printf(MSG_DEBUG, "SCARD: 3G USIM app not found "
+			   "from EF_DIR records");
+		return -1;
+	}
+
+	if (efdir->aid_len > maxlen) {
+		wpa_printf(MSG_DEBUG, "SCARD: Too long AID");
+		return -1;
+	}
+
+	os_memcpy(aid, efdir->rid, efdir->aid_len);
+
+	return efdir->aid_len;
+}
+
+
+/**
+ * scard_init - Initialize SIM/USIM connection using PC/SC
+ * @sim_type: Allowed SIM types (SIM, USIM, or both)
+ * Returns: Pointer to private data structure, or %NULL on failure
+ *
+ * This function is used to initialize SIM/USIM connection. PC/SC is used to
+ * open connection to the SIM/USIM card and the card is verified to support the
+ * selected sim_type. In addition, local flag is set if a PIN is needed to
+ * access some of the card functions. Once the connection is not needed
+ * anymore, scard_deinit() can be used to close it.
+ */
 struct scard_data * scard_init(scard_sim_type sim_type)
 {
-	long ret, len;
+	long ret;
+	unsigned long len;
 	struct scard_data *scard;
+#ifdef CONFIG_NATIVE_WINDOWS
+	TCHAR *readers = NULL;
+#else /* CONFIG_NATIVE_WINDOWS */
 	char *readers = NULL;
-	char buf[100];
+#endif /* CONFIG_NATIVE_WINDOWS */
+	unsigned char buf[100];
 	size_t blen;
+	int transaction = 0;
+	int pin_needed;
 
 	wpa_printf(MSG_DEBUG, "SCARD: initializing smart card interface");
-	scard = malloc(sizeof(*scard));
+	if (mingw_load_symbols())
+		return NULL;
+	scard = os_zalloc(sizeof(*scard));
 	if (scard == NULL)
 		return NULL;
-	memset(scard, 0, sizeof(*scard));
 
 	ret = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL,
 				    &scard->ctx);
@@ -212,9 +468,12 @@
 		goto failed;
 	}
 
-	readers = malloc(len);
+#ifdef UNICODE
+	len *= 2;
+#endif /* UNICODE */
+	readers = os_malloc(len);
 	if (readers == NULL) {
-		printf("malloc failed\n");
+		wpa_printf(MSG_INFO, "SCARD: malloc failed\n");
 		goto failed;
 	}
 
@@ -233,23 +492,36 @@
 	 * double NUL.
 	 * TODO: add support for selecting the reader; now just use the first
 	 * one.. */
+#ifdef UNICODE
+	wpa_printf(MSG_DEBUG, "SCARD: Selected reader='%S'", readers);
+#else /* UNICODE */
 	wpa_printf(MSG_DEBUG, "SCARD: Selected reader='%s'", readers);
+#endif /* UNICODE */
 
 	ret = SCardConnect(scard->ctx, readers, SCARD_SHARE_SHARED,
 			   SCARD_PROTOCOL_T0, &scard->card, &scard->protocol);
 	if (ret != SCARD_S_SUCCESS) {
-		if (ret == SCARD_E_NO_SMARTCARD)
+		if (ret == (long) SCARD_E_NO_SMARTCARD)
 			wpa_printf(MSG_INFO, "No smart card inserted.");
 		else
 			wpa_printf(MSG_WARNING, "SCardConnect err=%lx", ret);
 		goto failed;
 	}
 
-	free(readers);
+	os_free(readers);
 	readers = NULL;
 
-	wpa_printf(MSG_DEBUG, "SCARD: card=%ld active_protocol=%lu",
-		   scard->card, scard->protocol);
+	wpa_printf(MSG_DEBUG, "SCARD: card=0x%x active_protocol=%lu (%s)",
+		   (unsigned int) scard->card, scard->protocol,
+		   scard->protocol == SCARD_PROTOCOL_T0 ? "T0" : "T1");
+
+	ret = SCardBeginTransaction(scard->card);
+	if (ret != SCARD_S_SUCCESS) {
+		wpa_printf(MSG_DEBUG, "SCARD: Could not begin transaction: "
+			   "0x%x", (unsigned int) ret);
+		goto failed;
+	}
+	transaction = 1;
 
 	blen = sizeof(buf);
 
@@ -257,7 +529,7 @@
 	if (sim_type == SCARD_USIM_ONLY || sim_type == SCARD_TRY_BOTH) {
 		wpa_printf(MSG_DEBUG, "SCARD: verifying USIM support");
 		if (_scard_select_file(scard, SCARD_FILE_MF, buf, &blen,
-				       SCARD_USIM, NULL)) {
+				       SCARD_USIM, NULL, 0)) {
 			wpa_printf(MSG_DEBUG, "SCARD: USIM is not supported");
 			if (sim_type == SCARD_USIM_ONLY)
 				goto failed;
@@ -282,31 +554,66 @@
 			goto failed;
 		}
 	} else {
-		/* Select based on AID = 3G RID */
+		unsigned char aid[32];
+		int aid_len;
+
+		aid_len = scard_get_aid(scard, aid, sizeof(aid));
+		if (aid_len < 0) {
+			wpa_printf(MSG_DEBUG, "SCARD: Failed to find AID for "
+				   "3G USIM app - try to use standard 3G RID");
+			os_memcpy(aid, "\xa0\x00\x00\x00\x87", 5);
+			aid_len = 5;
+		}
+		wpa_hexdump(MSG_DEBUG, "SCARD: 3G USIM AID", aid, aid_len);
+
+		/* Select based on AID = 3G RID from EF_DIR. This is usually
+		 * starting with A0 00 00 00 87. */
 		blen = sizeof(buf);
 		if (_scard_select_file(scard, 0, buf, &blen, scard->sim_type,
-				       "\xA0\x00\x00\x00\x87")) {
-			wpa_printf(MSG_DEBUG, "SCARD: Failed to read 3G RID "
-				   "AID");
+				       aid, aid_len)) {
+			wpa_printf(MSG_INFO, "SCARD: Failed to read 3G USIM "
+				   "app");
+			wpa_hexdump(MSG_INFO, "SCARD: 3G USIM AID",
+				    aid, aid_len);
 			goto failed;
 		}
 	}
 
 	/* Verify whether CHV1 (PIN1) is needed to access the card. */
-	if (scard_pin_needed(scard, buf, blen)) {
+	pin_needed = scard_pin_needed(scard, buf, blen);
+	if (pin_needed < 0) {
+		wpa_printf(MSG_DEBUG, "SCARD: Failed to determine whether PIN "
+			   "is needed");
+		goto failed;
+	}
+	if (pin_needed) {
 		scard->pin1_required = 1;
 		wpa_printf(MSG_DEBUG, "PIN1 needed for SIM access");
 	}
 
+	ret = SCardEndTransaction(scard->card, SCARD_LEAVE_CARD);
+	if (ret != SCARD_S_SUCCESS) {
+		wpa_printf(MSG_DEBUG, "SCARD: Could not end transaction: "
+			   "0x%x", (unsigned int) ret);
+	}
+
 	return scard;
 
 failed:
-	free(readers);
+	if (transaction)
+		SCardEndTransaction(scard->card, SCARD_LEAVE_CARD);
+	os_free(readers);
 	scard_deinit(scard);
 	return NULL;
 }
 
 
+/**
+ * scard_set_pin - Set PIN (CHV1/PIN1) code for accessing SIM/USIM commands
+ * @scard: Pointer to private data from scard_init()
+ * pin: PIN code as an ASCII string (e.g., "1234")
+ * Returns: 0 on success, -1 on failure
+ */
 int scard_set_pin(struct scard_data *scard, const char *pin)
 {
 	if (scard == NULL)
@@ -330,6 +637,12 @@
 }
 
 
+/**
+ * scard_deinit - Deinitialize SIM/USIM connection
+ * @scard: Pointer to private data from scard_init()
+ *
+ * This function closes the SIM/USIM connect opened with scard_init().
+ */
 void scard_deinit(struct scard_data *scard)
 {
 	long ret;
@@ -353,29 +666,30 @@
 				   "context (err=%ld)", ret);
 		}
 	}
-	free(scard);
+	os_free(scard);
+	mingw_unload_symbols();
 }
 
 
 static long scard_transmit(struct scard_data *scard,
-			   unsigned char *send, size_t send_len,
-			   unsigned char *recv, size_t *recv_len)
+			   unsigned char *_send, size_t send_len,
+			   unsigned char *_recv, size_t *recv_len)
 {
 	long ret;
 	unsigned long rlen;
 
 	wpa_hexdump_key(MSG_DEBUG, "SCARD: scard_transmit: send",
-			send, send_len);
+			_send, send_len);
 	rlen = *recv_len;
 	ret = SCardTransmit(scard->card,
 			    scard->protocol == SCARD_PROTOCOL_T1 ?
 			    SCARD_PCI_T1 : SCARD_PCI_T0,
-			    send, (unsigned long) send_len,
-			    NULL, recv, &rlen);
+			    _send, (unsigned long) send_len,
+			    NULL, _recv, &rlen);
 	*recv_len = rlen;
 	if (ret == SCARD_S_SUCCESS) {
 		wpa_hexdump(MSG_DEBUG, "SCARD: scard_transmit: recv",
-			    recv, rlen);
+			    _recv, rlen);
 	} else {
 		wpa_printf(MSG_WARNING, "SCARD: SCardTransmit failed "
 			   "(err=0x%lx)", ret);
@@ -386,11 +700,12 @@
 
 static int _scard_select_file(struct scard_data *scard, unsigned short file_id,
 			      unsigned char *buf, size_t *buf_len,
-			      sim_types sim_type, unsigned char *aid)
+			      sim_types sim_type, unsigned char *aid,
+			      size_t aidlen)
 {
 	long ret;
 	unsigned char resp[3];
-	unsigned char cmd[10] = { SIM_CMD_SELECT };
+	unsigned char cmd[50] = { SIM_CMD_SELECT };
 	int cmdlen;
 	unsigned char get_resp[5] = { SIM_CMD_GET_RESPONSE };
 	size_t len, rlen;
@@ -403,10 +718,14 @@
 
 	wpa_printf(MSG_DEBUG, "SCARD: select file %04x", file_id);
 	if (aid) {
+		wpa_hexdump(MSG_DEBUG, "SCARD: select file by AID",
+			    aid, aidlen);
+		if (5 + aidlen > sizeof(cmd))
+			return -1;
 		cmd[2] = 0x04; /* Select by AID */
-		cmd[4] = 5; /* len */
-		memcpy(cmd + 5, aid, 5);
-		cmdlen = 10;
+		cmd[4] = aidlen; /* len */
+		os_memcpy(cmd + 5, aid, aidlen);
+		cmdlen = 5 + aidlen;
 	} else {
 		cmd[5] = file_id >> 8;
 		cmd[6] = file_id & 0xff;
@@ -464,19 +783,102 @@
 			     unsigned char *buf, size_t *buf_len)
 {
 	return _scard_select_file(scard, file_id, buf, buf_len,
-				  scard->sim_type, NULL);
+				  scard->sim_type, NULL, 0);
+}
+
+
+static int scard_get_record_len(struct scard_data *scard, unsigned char recnum,
+				unsigned char mode)
+{
+	unsigned char buf[255];
+	unsigned char cmd[5] = { SIM_CMD_READ_RECORD /* , len */ };
+	size_t blen;
+	long ret;
+
+	if (scard->sim_type == SCARD_USIM)
+		cmd[0] = USIM_CLA;
+	cmd[2] = recnum;
+	cmd[3] = mode;
+	cmd[4] = sizeof(buf);
+
+	blen = sizeof(buf);
+	ret = scard_transmit(scard, cmd, sizeof(cmd), buf, &blen);
+	if (ret != SCARD_S_SUCCESS) {
+		wpa_printf(MSG_DEBUG, "SCARD: failed to determine file "
+			   "length for record %d", recnum);
+		return -1;
+	}
+
+	wpa_hexdump(MSG_DEBUG, "SCARD: file length determination response",
+		    buf, blen);
+
+	if (blen < 2 || buf[0] != 0x6c) {
+		wpa_printf(MSG_DEBUG, "SCARD: unexpected response to file "
+			   "length determination");
+		return -1;
+	}
+
+	return buf[1];
+}
+
+
+static int scard_read_record(struct scard_data *scard,
+			     unsigned char *data, size_t len,
+			     unsigned char recnum, unsigned char mode)
+{
+	unsigned char cmd[5] = { SIM_CMD_READ_RECORD /* , len */ };
+	size_t blen = len + 3;
+	unsigned char *buf;
+	long ret;
+
+	if (scard->sim_type == SCARD_USIM)
+		cmd[0] = USIM_CLA;
+	cmd[2] = recnum;
+	cmd[3] = mode;
+	cmd[4] = len;
+
+	buf = os_malloc(blen);
+	if (buf == NULL)
+		return -1;
+
+	ret = scard_transmit(scard, cmd, sizeof(cmd), buf, &blen);
+	if (ret != SCARD_S_SUCCESS) {
+		os_free(buf);
+		return -2;
+	}
+	if (blen != len + 2) {
+		wpa_printf(MSG_DEBUG, "SCARD: record read returned unexpected "
+			   "length %d (expected %d)", blen, len + 2);
+		os_free(buf);
+		return -3;
+	}
+
+	if (buf[len] != 0x90 || buf[len + 1] != 0x00) {
+		wpa_printf(MSG_DEBUG, "SCARD: record read returned unexpected "
+			   "status %02x %02x (expected 90 00)",
+			   buf[len], buf[len + 1]);
+		os_free(buf);
+		return -4;
+	}
+
+	os_memcpy(data, buf, len);
+	os_free(buf);
+
+	return 0;
 }
 
 
 static int scard_read_file(struct scard_data *scard,
 			   unsigned char *data, size_t len)
 {
-	char cmd[5] = { SIM_CMD_READ_BIN, len };
+	unsigned char cmd[5] = { SIM_CMD_READ_BIN /* , len */ };
 	size_t blen = len + 3;
 	unsigned char *buf;
 	long ret;
 
-	buf = malloc(blen);
+	cmd[4] = len;
+
+	buf = os_malloc(blen);
 	if (buf == NULL)
 		return -1;
 
@@ -484,13 +886,13 @@
 		cmd[0] = USIM_CLA;
 	ret = scard_transmit(scard, cmd, sizeof(cmd), buf, &blen);
 	if (ret != SCARD_S_SUCCESS) {
-		free(buf);
+		os_free(buf);
 		return -2;
 	}
 	if (blen != len + 2) {
 		wpa_printf(MSG_DEBUG, "SCARD: file read returned unexpected "
 			   "length %d (expected %d)", blen, len + 2);
-		free(buf);
+		os_free(buf);
 		return -3;
 	}
 
@@ -498,12 +900,12 @@
 		wpa_printf(MSG_DEBUG, "SCARD: file read returned unexpected "
 			   "status %02x %02x (expected 90 00)",
 			   buf[len], buf[len + 1]);
-		free(buf);
+		os_free(buf);
 		return -4;
 	}
 
-	memcpy(data, buf, len);
-	free(buf);
+	os_memcpy(data, buf, len);
+	os_free(buf);
 
 	return 0;
 }
@@ -513,18 +915,18 @@
 {
 	long ret;
 	unsigned char resp[3];
-	char cmd[5 + 8] = { SIM_CMD_VERIFY_CHV1 };
+	unsigned char cmd[5 + 8] = { SIM_CMD_VERIFY_CHV1 };
 	size_t len;
 
 	wpa_printf(MSG_DEBUG, "SCARD: verifying PIN");
 
-	if (pin == NULL || strlen(pin) > 8)
+	if (pin == NULL || os_strlen(pin) > 8)
 		return -1;
 
 	if (scard->sim_type == SCARD_USIM)
 		cmd[0] = USIM_CLA;
-	memcpy(cmd + 5, pin, strlen(pin));
-	memset(cmd + 5 + strlen(pin), 0xff, 8 - strlen(pin));
+	os_memcpy(cmd + 5, pin, os_strlen(pin));
+	os_memset(cmd + 5 + os_strlen(pin), 0xff, 8 - os_strlen(pin));
 
 	len = sizeof(resp);
 	ret = scard_transmit(scard, cmd, sizeof(cmd), resp, &len);
@@ -541,12 +943,25 @@
 }
 
 
+/**
+ * scard_get_imsi - Read IMSI from SIM/USIM card
+ * @scard: Pointer to private data from scard_init()
+ * @imsi: Buffer for IMSI
+ * @len: Length of imsi buffer; set to IMSI length on success
+ * Returns: 0 on success, -1 if IMSI file cannot be selected, -2 if IMSI file
+ * selection returns invalid result code, -3 if parsing FSP template file fails
+ * (USIM only), -4 if IMSI does not fit in the provided imsi buffer (len is set
+ * to needed length), -5 if reading IMSI file fails.
+ *
+ * This function can be used to read IMSI from the SIM/USIM card. If the IMSI
+ * file is PIN protected, scard_set_pin() must have been used to set the
+ * correct PIN code before calling scard_get_imsi().
+ */
 int scard_get_imsi(struct scard_data *scard, char *imsi, size_t *len)
 {
-	char buf[100];
-	size_t blen, imsilen;
+	unsigned char buf[100];
+	size_t blen, imsilen, i;
 	char *pos;
-	int i;
 
 	wpa_printf(MSG_DEBUG, "SCARD: reading IMSI from (GSM) EF-IMSI");
 	blen = sizeof(buf);
@@ -606,7 +1021,22 @@
 }
 
 
-int scard_gsm_auth(struct scard_data *scard, unsigned char *rand,
+/**
+ * scard_gsm_auth - Run GSM authentication command on SIM card
+ * @scard: Pointer to private data from scard_init()
+ * @_rand: 16-byte RAND value from HLR/AuC
+ * @sres: 4-byte buffer for SRES
+ * @kc: 8-byte buffer for Kc
+ * Returns: 0 on success, -1 if SIM/USIM connection has not been initialized,
+ * -2 if authentication command execution fails, -3 if unknown response code
+ * for authentication command is received, -4 if reading of response fails,
+ * -5 if if response data is of unexpected length
+ *
+ * This function performs GSM authentication using SIM/USIM card and the
+ * provided RAND value from HLR/AuC. If authentication command can be completed
+ * successfully, SRES and Kc values will be written into sres and kc buffers.
+ */
+int scard_gsm_auth(struct scard_data *scard, const unsigned char *_rand,
 		   unsigned char *sres, unsigned char *kc)
 {
 	unsigned char cmd[5 + 1 + 16] = { SIM_CMD_RUN_GSM_ALG };
@@ -619,17 +1049,17 @@
 	if (scard == NULL)
 		return -1;
 
-	wpa_hexdump(MSG_DEBUG, "SCARD: GSM auth - RAND", rand, 16);
+	wpa_hexdump(MSG_DEBUG, "SCARD: GSM auth - RAND", _rand, 16);
 	if (scard->sim_type == SCARD_GSM_SIM) {
 		cmdlen = 5 + 16;
-		memcpy(cmd + 5, rand, 16);
+		os_memcpy(cmd + 5, _rand, 16);
 	} else {
 		cmdlen = 5 + 1 + 16;
 		cmd[0] = USIM_CLA;
 		cmd[3] = 0x80;
 		cmd[4] = 17;
 		cmd[5] = 16;
-		memcpy(cmd + 6, rand, 16);
+		os_memcpy(cmd + 6, _rand, 16);
 	}
 	len = sizeof(resp);
 	ret = scard_transmit(scard, cmd, cmdlen, resp, &len);
@@ -659,8 +1089,8 @@
 				   len);
 			return -5;
 		}
-		memcpy(sres, buf, 4);
-		memcpy(kc, buf + 4, 8);
+		os_memcpy(sres, buf, 4);
+		os_memcpy(kc, buf + 4, 8);
 	} else {
 		if (len != 1 + 4 + 1 + 8 + 2) {
 			wpa_printf(MSG_WARNING, "SCARD: unexpected data "
@@ -673,8 +1103,8 @@
 				   "length (%d %d, expected 4 8)",
 				   buf[0], buf[5]);
 		}
-		memcpy(sres, buf + 1, 4);
-		memcpy(kc, buf + 6, 8);
+		os_memcpy(sres, buf + 1, 4);
+		os_memcpy(kc, buf + 6, 8);
 	}
 
 	wpa_hexdump(MSG_DEBUG, "SCARD: GSM auth - SRES", sres, 4);
@@ -684,13 +1114,33 @@
 }
 
 
-int scard_umts_auth(struct scard_data *scard, unsigned char *rand,
-		    unsigned char *autn, unsigned char *res, size_t *res_len,
+/**
+ * scard_umts_auth - Run UMTS authentication command on USIM card
+ * @scard: Pointer to private data from scard_init()
+ * @_rand: 16-byte RAND value from HLR/AuC
+ * @autn: 16-byte AUTN value from HLR/AuC
+ * @res: 16-byte buffer for RES
+ * @res_len: Variable that will be set to RES length
+ * @ik: 16-byte buffer for IK
+ * @ck: 16-byte buffer for CK
+ * @auts: 14-byte buffer for AUTS
+ * Returns: 0 on success, -1 on failure, or -2 if USIM reports synchronization
+ * failure
+ *
+ * This function performs AKA authentication using USIM card and the provided
+ * RAND and AUTN values from HLR/AuC. If authentication command can be
+ * completed successfully, RES, IK, and CK values will be written into provided
+ * buffers and res_len is set to length of received RES value. If USIM reports
+ * synchronization failure, the received AUTS value will be written into auts
+ * buffer. In this case, RES, IK, and CK are not valid.
+ */
+int scard_umts_auth(struct scard_data *scard, const unsigned char *_rand,
+		    const unsigned char *autn,
+		    unsigned char *res, size_t *res_len,
 		    unsigned char *ik, unsigned char *ck, unsigned char *auts)
 {
 	unsigned char cmd[5 + 1 + AKA_RAND_LEN + 1 + AKA_AUTN_LEN] =
 		{ USIM_CMD_RUN_UMTS_ALG };
-	int cmdlen;
 	unsigned char get_resp[5] = { USIM_CMD_GET_RESPONSE };
 	unsigned char resp[3], buf[64], *pos, *end;
 	size_t len;
@@ -705,20 +1155,19 @@
 		return -1;
 	}
 
-	wpa_hexdump(MSG_DEBUG, "SCARD: UMTS auth - RAND", rand, AKA_RAND_LEN);
+	wpa_hexdump(MSG_DEBUG, "SCARD: UMTS auth - RAND", _rand, AKA_RAND_LEN);
 	wpa_hexdump(MSG_DEBUG, "SCARD: UMTS auth - AUTN", autn, AKA_AUTN_LEN);
-	cmdlen = 5 + 1 + AKA_RAND_LEN + 1 + AKA_AUTN_LEN;
 	cmd[5] = AKA_RAND_LEN;
-	memcpy(cmd + 6, rand, AKA_RAND_LEN);
+	os_memcpy(cmd + 6, _rand, AKA_RAND_LEN);
 	cmd[6 + AKA_RAND_LEN] = AKA_AUTN_LEN;
-	memcpy(cmd + 6 + AKA_RAND_LEN + 1, autn, AKA_AUTN_LEN);
+	os_memcpy(cmd + 6 + AKA_RAND_LEN + 1, autn, AKA_AUTN_LEN);
 
 	len = sizeof(resp);
 	ret = scard_transmit(scard, cmd, sizeof(cmd), resp, &len);
 	if (ret != SCARD_S_SUCCESS)
 		return -1;
 
-	if (len >= 0 && len <= sizeof(resp))
+	if (len <= sizeof(resp))
 		wpa_hexdump(MSG_DEBUG, "SCARD: UMTS alg response", resp, len);
 
 	if (len == 2 && resp[0] == 0x98 && resp[1] == 0x62) {
@@ -735,14 +1184,14 @@
 
 	len = sizeof(buf);
 	ret = scard_transmit(scard, get_resp, sizeof(get_resp), buf, &len);
-	if (ret != SCARD_S_SUCCESS || len < 0 || len > sizeof(buf))
+	if (ret != SCARD_S_SUCCESS || len > sizeof(buf))
 		return -1;
 
 	wpa_hexdump(MSG_DEBUG, "SCARD: UMTS get response result", buf, len);
 	if (len >= 2 + AKA_AUTS_LEN && buf[0] == 0xdc &&
 	    buf[1] == AKA_AUTS_LEN) {
 		wpa_printf(MSG_DEBUG, "SCARD: UMTS Synchronization-Failure");
-		memcpy(auts, buf + 2, AKA_AUTS_LEN);
+		os_memcpy(auts, buf + 2, AKA_AUTS_LEN);
 		wpa_hexdump(MSG_DEBUG, "SCARD: AUTS", auts, AKA_AUTS_LEN);
 		return -2;
 	} else if (len >= 6 + IK_LEN + CK_LEN && buf[0] == 0xdb) {
@@ -755,7 +1204,7 @@
 			return -1;
 		}
 		*res_len = *pos++;
-		memcpy(res, pos, *res_len);
+		os_memcpy(res, pos, *res_len);
 		pos += *res_len;
 		wpa_hexdump(MSG_DEBUG, "SCARD: RES", res, *res_len);
 
@@ -765,7 +1214,7 @@
 			return -1;
 		}
 		pos++;
-		memcpy(ck, pos, CK_LEN);
+		os_memcpy(ck, pos, CK_LEN);
 		pos += CK_LEN;
 		wpa_hexdump(MSG_DEBUG, "SCARD: CK", ck, CK_LEN);
 
@@ -775,7 +1224,7 @@
 			return -1;
 		}
 		pos++;
-		memcpy(ik, pos, IK_LEN);
+		os_memcpy(ik, pos, IK_LEN);
 		pos += IK_LEN;
 		wpa_hexdump(MSG_DEBUG, "SCARD: IK", ik, IK_LEN);
 
Index: eap_otp.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/eap_otp.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/eap_otp.c -L contrib/wpa_supplicant/eap_otp.c -u -r1.2 -r1.3
--- contrib/wpa_supplicant/eap_otp.c
+++ contrib/wpa_supplicant/eap_otp.c
@@ -1,6 +1,6 @@
 /*
- * WPA Supplicant / EAP-OTP (RFC 3748)
- * Copyright (c) 2004-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * EAP peer method: EAP-OTP (RFC 3748)
+ * Copyright (c) 2004-2006, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -12,18 +12,17 @@
  * See README and COPYING for more details.
  */
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
+#include "includes.h"
 
 #include "common.h"
 #include "eap_i.h"
-#include "wpa_supplicant.h"
 #include "config_ssid.h"
 
 
 static void * eap_otp_init(struct eap_sm *sm)
 {
+	/* No need for private data. However, must return non-NULL to indicate
+	 * success. */
 	return (void *) 1;
 }
 
@@ -38,14 +37,15 @@
 			    const u8 *reqData, size_t reqDataLen,
 			    size_t *respDataLen)
 {
-	struct wpa_ssid *config = eap_get_config(sm);
 	const struct eap_hdr *req;
 	struct eap_hdr *resp;
 	const u8 *pos, *password;
 	u8 *rpos;
 	size_t password_len, len;
+	int otp;
 
-	pos = eap_hdr_validate(EAP_TYPE_OTP, reqData, reqDataLen, &len);
+	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_OTP,
+			       reqData, reqDataLen, &len);
 	if (pos == NULL) {
 		ret->ignore = TRUE;
 		return NULL;
@@ -54,58 +54,61 @@
 	wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-OTP: Request message",
 			  pos, len);
 
-	if (config == NULL ||
-	    (config->password == NULL && config->otp == NULL)) {
+	password = eap_get_config_otp(sm, &password_len);
+	if (password)
+		otp = 1;
+	else {
+		password = eap_get_config_password(sm, &password_len);
+		otp = 0;
+	}
+
+	if (password == NULL) {
 		wpa_printf(MSG_INFO, "EAP-OTP: Password not configured");
-		eap_sm_request_otp(sm, config, (const char *) pos, len);
+		eap_sm_request_otp(sm, (const char *) pos, len);
 		ret->ignore = TRUE;
 		return NULL;
 	}
 
-	if (config->otp) {
-		password = config->otp;
-		password_len = config->otp_len;
-	} else {
-		password = config->password;
-		password_len = config->password_len;
-	}
-
 	ret->ignore = FALSE;
 
 	ret->methodState = METHOD_DONE;
 	ret->decision = DECISION_COND_SUCC;
 	ret->allowNotifications = FALSE;
 
-	*respDataLen = sizeof(struct eap_hdr) + 1 + password_len;
-	resp = malloc(*respDataLen);
+	resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_OTP, respDataLen,
+			     password_len, EAP_CODE_RESPONSE, req->identifier,
+			     &rpos);
 	if (resp == NULL)
 		return NULL;
-	resp->code = EAP_CODE_RESPONSE;
-	resp->identifier = req->identifier;
-	resp->length = host_to_be16(*respDataLen);
-	rpos = (u8 *) (resp + 1);
-	*rpos++ = EAP_TYPE_OTP;
-	memcpy(rpos, password, password_len);
+	os_memcpy(rpos, password, password_len);
 	wpa_hexdump_ascii_key(MSG_MSGDUMP, "EAP-OTP: Response",
 			      password, password_len);
 
-	if (config->otp) {
+	if (otp) {
 		wpa_printf(MSG_DEBUG, "EAP-OTP: Forgetting used password");
-		memset(config->otp, 0, config->otp_len);
-		free(config->otp);
-		config->otp = NULL;
-		config->otp_len = 0;
+		eap_clear_config_otp(sm);
 	}
 
 	return (u8 *) resp;
 }
 
 
-const struct eap_method eap_method_otp =
+int eap_peer_otp_register(void)
 {
-	.method = EAP_TYPE_OTP,
-	.name = "OTP",
-	.init = eap_otp_init,
-	.deinit = eap_otp_deinit,
-	.process = eap_otp_process,
-};
+	struct eap_method *eap;
+	int ret;
+
+	eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
+				    EAP_VENDOR_IETF, EAP_TYPE_OTP, "OTP");
+	if (eap == NULL)
+		return -1;
+
+	eap->init = eap_otp_init;
+	eap->deinit = eap_otp_deinit;
+	eap->process = eap_otp_process;
+
+	ret = eap_peer_method_register(eap);
+	if (ret)
+		eap_peer_method_free(eap);
+	return ret;
+}
Index: eap_tls.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/eap_tls.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/eap_tls.c -L contrib/wpa_supplicant/eap_tls.c -u -r1.2 -r1.3
--- contrib/wpa_supplicant/eap_tls.c
+++ contrib/wpa_supplicant/eap_tls.c
@@ -1,6 +1,6 @@
 /*
- * WPA Supplicant / EAP-TLS (RFC 2716)
- * Copyright (c) 2004-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * EAP peer method: EAP-TLS (RFC 2716)
+ * Copyright (c) 2004-2006, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -12,14 +12,11 @@
  * See README and COPYING for more details.
  */
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
+#include "includes.h"
 
 #include "common.h"
 #include "eap_i.h"
 #include "eap_tls_common.h"
-#include "wpa_supplicant.h"
 #include "config_ssid.h"
 #include "tls.h"
 
@@ -44,10 +41,9 @@
 		return NULL;
 	}
 
-	data = malloc(sizeof(*data));
+	data = os_zalloc(sizeof(*data));
 	if (data == NULL)
 		return NULL;
-	memset(data, 0, sizeof(*data));
 
 	if (eap_tls_ssl_init(sm, &data->ssl, config)) {
 		wpa_printf(MSG_INFO, "EAP-TLS: Failed to initialize SSL.");
@@ -55,13 +51,13 @@
 		if (config->engine) {
 			wpa_printf(MSG_DEBUG, "EAP-TLS: Requesting Smartcard "
 				   "PIN");
-			eap_sm_request_pin(sm, config);
+			eap_sm_request_pin(sm);
 			sm->ignore = TRUE;
 		} else if (config->private_key && !config->private_key_passwd)
 		{
 			wpa_printf(MSG_DEBUG, "EAP-TLS: Requesting private "
 				   "key passphrase");
-			eap_sm_request_passphrase(sm, config);
+			eap_sm_request_passphrase(sm);
 			sm->ignore = TRUE;
 		}
 		return NULL;
@@ -77,8 +73,67 @@
 	if (data == NULL)
 		return;
 	eap_tls_ssl_deinit(sm, &data->ssl);
-	free(data->key_data);
-	free(data);
+	os_free(data->key_data);
+	os_free(data);
+}
+
+
+static u8 * eap_tls_failure(struct eap_sm *sm, struct eap_tls_data *data,
+			    struct eap_method_ret *ret, int res, u8 *resp,
+			    u8 id, size_t *respDataLen)
+{
+	wpa_printf(MSG_DEBUG, "EAP-TLS: TLS processing failed");
+
+	ret->methodState = METHOD_DONE;
+	ret->decision = DECISION_FAIL;
+
+	if (res == -1) {
+		struct wpa_ssid *config = eap_get_config(sm);
+		if (config) {
+			/*
+			 * The TLS handshake failed. So better forget the old
+			 * PIN. It may be wrong, we cannot be sure but trying
+			 * the wrong one again might block it on the card--so
+			 * better ask the user again.
+			 */
+			os_free(config->pin);
+			config->pin = NULL;
+		}
+	}
+
+	if (resp) {
+		/*
+		 * This is likely an alert message, so send it instead of just
+		 * ACKing the error.
+		 */
+		return resp;
+	}
+
+	return eap_tls_build_ack(&data->ssl, respDataLen, id, EAP_TYPE_TLS, 0);
+}
+
+
+static void eap_tls_success(struct eap_sm *sm, struct eap_tls_data *data,
+			    struct eap_method_ret *ret)
+{
+	wpa_printf(MSG_DEBUG, "EAP-TLS: Done");
+
+	ret->methodState = METHOD_DONE;
+	ret->decision = DECISION_UNCOND_SUCC;
+
+	os_free(data->key_data);
+	data->key_data = eap_tls_derive_key(sm, &data->ssl,
+					    "client EAP encryption",
+					    EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
+	if (data->key_data) {
+		wpa_hexdump_key(MSG_DEBUG, "EAP-TLS: Derived key",
+				data->key_data, EAP_TLS_KEY_LEN);
+		wpa_hexdump_key(MSG_DEBUG, "EAP-TLS: Derived EMSK",
+				data->key_data + EAP_TLS_KEY_LEN,
+				EAP_EMSK_LEN);
+	} else {
+		wpa_printf(MSG_INFO, "EAP-TLS: Failed to derive key");
+	}
 }
 
 
@@ -87,7 +142,6 @@
 			    const u8 *reqData, size_t reqDataLen,
 			    size_t *respDataLen)
 {
-	struct wpa_ssid *config = eap_get_config(sm);
 	const struct eap_hdr *req;
 	size_t left;
 	int res;
@@ -113,48 +167,18 @@
 				     left, &resp, respDataLen);
 
 	if (res < 0) {
-		wpa_printf(MSG_DEBUG, "EAP-TLS: TLS processing failed");
-		ret->methodState = METHOD_MAY_CONT;
-		ret->decision = DECISION_FAIL;
-		if (resp) {
-			/* This is likely an alert message, so send it instead
-			 * of just ACKing the error. */
-			return resp;
-		}
-		return eap_tls_build_ack(&data->ssl, respDataLen, id,
-					 EAP_TYPE_TLS, 0);
+		return eap_tls_failure(sm, data, ret, res, resp, id,
+				       respDataLen);
 	}
 
-	if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
-		wpa_printf(MSG_DEBUG, "EAP-TLS: Done");
-		ret->methodState = METHOD_DONE;
-		ret->decision = DECISION_UNCOND_SUCC;
-		free(data->key_data);
-		data->key_data = eap_tls_derive_key(sm, &data->ssl,
-						    "client EAP encryption",
-						    EAP_TLS_KEY_LEN);
-		if (data->key_data) {
-			wpa_hexdump_key(MSG_DEBUG, "EAP-TLS: Derived key",
-					data->key_data, EAP_TLS_KEY_LEN);
-		} else {
-			wpa_printf(MSG_DEBUG, "EAP-TLS: Failed to derive key");
-		}
-	}
+	if (tls_connection_established(sm->ssl_ctx, data->ssl.conn))
+		eap_tls_success(sm, data, ret);
 
 	if (res == 1) {
 		return eap_tls_build_ack(&data->ssl, respDataLen, id,
 					 EAP_TYPE_TLS, 0);
 	}
 
-	if (res == -1) {
-		/* The TLS handshake failed. So better forget the old PIN.
-		 * It may be wrong, we can't be sure but trying the wrong one
-		 * again might block it on the card - so better ask the user
-		 * again */
-		free(config->pin);
-		config->pin = NULL;
-	}
-
 	return resp;
 }
 
@@ -174,10 +198,10 @@
 static void * eap_tls_init_for_reauth(struct eap_sm *sm, void *priv)
 {
 	struct eap_tls_data *data = priv;
-	free(data->key_data);
+	os_free(data->key_data);
 	data->key_data = NULL;
 	if (eap_tls_reauth_init(sm, &data->ssl)) {
-		free(data);
+		os_free(data);
 		return NULL;
 	}
 	return priv;
@@ -207,28 +231,59 @@
 	if (data->key_data == NULL)
 		return NULL;
 
-	key = malloc(EAP_TLS_KEY_LEN);
+	key = os_malloc(EAP_TLS_KEY_LEN);
 	if (key == NULL)
 		return NULL;
 
 	*len = EAP_TLS_KEY_LEN;
-	memcpy(key, data->key_data, EAP_TLS_KEY_LEN);
+	os_memcpy(key, data->key_data, EAP_TLS_KEY_LEN);
 
 	return key;
 }
 
 
-const struct eap_method eap_method_tls =
+static u8 * eap_tls_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
 {
-	.method = EAP_TYPE_TLS,
-	.name = "TLS",
-	.init = eap_tls_init,
-	.deinit = eap_tls_deinit,
-	.process = eap_tls_process,
-	.isKeyAvailable = eap_tls_isKeyAvailable,
-	.getKey = eap_tls_getKey,
-	.get_status = eap_tls_get_status,
-	.has_reauth_data = eap_tls_has_reauth_data,
-	.deinit_for_reauth = eap_tls_deinit_for_reauth,
-	.init_for_reauth = eap_tls_init_for_reauth,
-};
+	struct eap_tls_data *data = priv;
+	u8 *key;
+
+	if (data->key_data == NULL)
+		return NULL;
+
+	key = os_malloc(EAP_EMSK_LEN);
+	if (key == NULL)
+		return NULL;
+
+	*len = EAP_EMSK_LEN;
+	os_memcpy(key, data->key_data + EAP_TLS_KEY_LEN, EAP_EMSK_LEN);
+
+	return key;
+}
+
+
+int eap_peer_tls_register(void)
+{
+	struct eap_method *eap;
+	int ret;
+
+	eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
+				    EAP_VENDOR_IETF, EAP_TYPE_TLS, "TLS");
+	if (eap == NULL)
+		return -1;
+
+	eap->init = eap_tls_init;
+	eap->deinit = eap_tls_deinit;
+	eap->process = eap_tls_process;
+	eap->isKeyAvailable = eap_tls_isKeyAvailable;
+	eap->getKey = eap_tls_getKey;
+	eap->get_status = eap_tls_get_status;
+	eap->has_reauth_data = eap_tls_has_reauth_data;
+	eap->deinit_for_reauth = eap_tls_deinit_for_reauth;
+	eap->init_for_reauth = eap_tls_init_for_reauth;
+	eap->get_emsk = eap_tls_get_emsk;
+
+	ret = eap_peer_method_register(eap);
+	if (ret)
+		eap_peer_method_free(eap);
+	return ret;
+}
Index: eap_ttls.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/eap_ttls.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/eap_ttls.c -L contrib/wpa_supplicant/eap_ttls.c -u -r1.2 -r1.3
--- contrib/wpa_supplicant/eap_ttls.c
+++ contrib/wpa_supplicant/eap_ttls.c
@@ -1,6 +1,6 @@
 /*
- * WPA Supplicant / EAP-TTLS (draft-ietf-pppext-eap-ttls-03.txt)
- * Copyright (c) 2004-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * EAP peer method: EAP-TTLS (draft-ietf-pppext-eap-ttls-03.txt)
+ * Copyright (c) 2004-2006, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -12,26 +12,37 @@
  * See README and COPYING for more details.
  */
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
+#include "includes.h"
 
 #include "common.h"
 #include "eap_i.h"
 #include "eap_tls_common.h"
-#include "wpa_supplicant.h"
 #include "config_ssid.h"
 #include "ms_funcs.h"
+#include "sha1.h"
 #include "crypto.h"
 #include "tls.h"
 #include "eap_ttls.h"
 
 
+/* Maximum supported PEAP version
+ * 0 = draft-ietf-pppext-eap-ttls-03.txt / draft-funk-eap-ttls-v0-00.txt
+ * 1 = draft-funk-eap-ttls-v1-00.txt
+ */
+#define EAP_TTLS_VERSION 0 /* TTLSv1 implementation is not yet complete */
+
+
+#define MSCHAPV2_KEY_LEN 16
+
+
 static void eap_ttls_deinit(struct eap_sm *sm, void *priv);
 
 
 struct eap_ttls_data {
 	struct eap_ssl_data ssl;
+	int ssl_initialized;
+
+	int ttls_version, force_ttls_version;
 
 	const struct eap_method *phase2_method;
 	void *phase2_priv;
@@ -45,8 +56,8 @@
 		EAP_TTLS_PHASE2_PAP,
 		EAP_TTLS_PHASE2_CHAP
 	} phase2_type;
-	u8 phase2_eap_type;
-	u8 *phase2_eap_types;
+	struct eap_method_type phase2_eap_type;
+	struct eap_method_type *phase2_eap_types;
 	size_t num_phase2_eap_types;
 
 	u8 auth_response[20];
@@ -67,26 +78,38 @@
 	struct wpa_ssid *config = eap_get_config(sm);
 	char *selected;
 
-	data = malloc(sizeof(*data));
+	data = os_zalloc(sizeof(*data));
 	if (data == NULL)
 		return NULL;
-	memset(data, 0, sizeof(*data));
+	data->ttls_version = EAP_TTLS_VERSION;
+	data->force_ttls_version = -1;
 	selected = "EAP";
 	data->phase2_type = EAP_TTLS_PHASE2_EAP;
+
+	if (config && config->phase1) {
+		char *pos = os_strstr(config->phase1, "ttlsver=");
+		if (pos) {
+			data->force_ttls_version = atoi(pos + 8);
+			data->ttls_version = data->force_ttls_version;
+			wpa_printf(MSG_DEBUG, "EAP-TTLS: Forced TTLS version "
+				   "%d", data->force_ttls_version);
+		}
+	}
+
 	if (config && config->phase2) {
-		if (strstr(config->phase2, "autheap=")) {
+		if (os_strstr(config->phase2, "autheap=")) {
 			selected = "EAP";
 			data->phase2_type = EAP_TTLS_PHASE2_EAP;
-		} else if (strstr(config->phase2, "auth=MSCHAPV2")) {
+		} else if (os_strstr(config->phase2, "auth=MSCHAPV2")) {
 			selected = "MSCHAPV2";
 			data->phase2_type = EAP_TTLS_PHASE2_MSCHAPV2;
-		} else if (strstr(config->phase2, "auth=MSCHAP")) {
+		} else if (os_strstr(config->phase2, "auth=MSCHAP")) {
 			selected = "MSCHAP";
 			data->phase2_type = EAP_TTLS_PHASE2_MSCHAP;
-		} else if (strstr(config->phase2, "auth=PAP")) {
+		} else if (os_strstr(config->phase2, "auth=PAP")) {
 			selected = "PAP";
 			data->phase2_type = EAP_TTLS_PHASE2_PAP;
-		} else if (strstr(config->phase2, "auth=CHAP")) {
+		} else if (os_strstr(config->phase2, "auth=CHAP")) {
 			selected = "CHAP";
 			data->phase2_type = EAP_TTLS_PHASE2_CHAP;
 		}
@@ -96,15 +119,17 @@
 	if (data->phase2_type == EAP_TTLS_PHASE2_EAP) {
 		if (config && config->phase2) {
 			char *start, *pos, *buf;
-			u8 method, *methods = NULL, *_methods;
+			struct eap_method_type *methods = NULL, *_methods;
+			u8 method;
 			size_t num_methods = 0;
-			start = buf = strdup(config->phase2);
+			start = buf = os_strdup(config->phase2);
 			if (buf == NULL) {
 				eap_ttls_deinit(sm, data);
 				return NULL;
 			}
 			while (start && *start != '\0') {
-				pos = strstr(start, "autheap=");
+				int vendor;
+				pos = os_strstr(start, "autheap=");
 				if (pos == NULL)
 					break;
 				if (start != pos && *(pos - 1) != ' ') {
@@ -113,30 +138,36 @@
 				}
 
 				start = pos + 8;
-				pos = strchr(start, ' ');
+				pos = os_strchr(start, ' ');
 				if (pos)
 					*pos++ = '\0';
-				method = eap_get_phase2_type(start);
-				if (method == EAP_TYPE_NONE) {
+				method = eap_get_phase2_type(start, &vendor);
+				if (vendor == EAP_VENDOR_IETF &&
+				    method == EAP_TYPE_NONE) {
 					wpa_printf(MSG_ERROR, "EAP-TTLS: "
 						   "Unsupported Phase2 EAP "
 						   "method '%s'", start);
 				} else {
 					num_methods++;
-					_methods = realloc(methods,
-							   num_methods);
+					_methods = os_realloc(
+						methods, num_methods *
+						sizeof(*methods));
 					if (_methods == NULL) {
-						free(methods);
+						os_free(methods);
+						os_free(buf);
 						eap_ttls_deinit(sm, data);
 						return NULL;
 					}
 					methods = _methods;
-					methods[num_methods - 1] = method;
+					methods[num_methods - 1].vendor =
+						vendor;
+					methods[num_methods - 1].method =
+						method;
 				}
 
 				start = pos;
 			}
-			free(buf);
+			os_free(buf);
 			data->phase2_eap_types = methods;
 			data->num_phase2_eap_types = num_methods;
 		}
@@ -151,16 +182,23 @@
 			return NULL;
 		}
 		wpa_hexdump(MSG_DEBUG, "EAP-TTLS: Phase2 EAP types",
-			    data->phase2_eap_types,
-			    data->num_phase2_eap_types);
-		data->phase2_eap_type = EAP_TYPE_NONE;
+			    (u8 *) data->phase2_eap_types,
+			    data->num_phase2_eap_types *
+			    sizeof(struct eap_method_type));
+		data->phase2_eap_type.vendor = EAP_VENDOR_IETF;
+		data->phase2_eap_type.method = EAP_TYPE_NONE;
 	}
 
-
-	if (eap_tls_ssl_init(sm, &data->ssl, config)) {
-		wpa_printf(MSG_INFO, "EAP-TTLS: Failed to initialize SSL.");
-		eap_ttls_deinit(sm, data);
-		return NULL;
+	if (!(tls_capabilities(sm->ssl_ctx) & TLS_CAPABILITY_IA) &&
+	    data->ttls_version > 0) {
+		if (data->force_ttls_version > 0) {
+			wpa_printf(MSG_INFO, "EAP-TTLS: Forced TTLSv%d and "
+				   "TLS library does not support TLS/IA.",
+				   data->force_ttls_version);
+			eap_ttls_deinit(sm, data);
+			return NULL;
+		}
+		data->ttls_version = 0;
 	}
 
 	return data;
@@ -174,11 +212,12 @@
 		return;
 	if (data->phase2_priv && data->phase2_method)
 		data->phase2_method->deinit(sm, data->phase2_priv);
-	free(data->phase2_eap_types);
-	eap_tls_ssl_deinit(sm, &data->ssl);
-	free(data->key_data);
-	free(data->pending_phase2_req);
-	free(data);
+	os_free(data->phase2_eap_types);
+	if (data->ssl_initialized)
+		eap_tls_ssl_deinit(sm, &data->ssl);
+	os_free(data->key_data);
+	os_free(data->pending_phase2_req);
+	os_free(data);
 }
 
 
@@ -192,7 +231,7 @@
 
 	/* TODO: add support for fragmentation, if needed. This will need to
 	 * add TLS Message Length field, if the frame is fragmented. */
-	resp = malloc(sizeof(struct eap_hdr) + 2 + data->ssl.tls_out_limit);
+	resp = os_malloc(sizeof(struct eap_hdr) + 2 + data->ssl.tls_out_limit);
 	if (resp == NULL)
 		return -1;
 
@@ -201,7 +240,7 @@
 
 	pos = (u8 *) (resp + 1);
 	*pos++ = EAP_TYPE_TTLS;
-	*pos++ = 0;
+	*pos++ = data->ttls_version;
 
 	res = tls_connection_encrypt(sm->ssl_ctx, data->ssl.conn,
 				     plain, plain_len,
@@ -209,7 +248,7 @@
 	if (res < 0) {
 		wpa_printf(MSG_INFO, "EAP-TTLS: Failed to encrypt Phase 2 "
 			   "data");
-		free(resp);
+		os_free(resp);
 		return -1;
 	}
 
@@ -250,7 +289,7 @@
 {
 	u8 *pos;
 	pos = eap_ttls_avp_hdr(avphdr, avp_code, vendor_id, mandatory, len);
-	memcpy(pos, data, len);
+	os_memcpy(pos, data, len);
 	pos += len;
 	AVP_PAD(start, pos);
 	return pos;
@@ -262,48 +301,215 @@
 {
 	u8 *avp, *pos;
 
-	avp = malloc(sizeof(struct ttls_avp) + *resp_len + 4);
+	avp = os_malloc(sizeof(struct ttls_avp) + *resp_len + 4);
 	if (avp == NULL) {
-		free(*resp);
+		os_free(*resp);
 		*resp = NULL;
 		*resp_len = 0;
 		return -1;
 	}
 
 	pos = eap_ttls_avp_hdr(avp, avp_code, 0, mandatory, *resp_len);
-	memcpy(pos, *resp, *resp_len);
+	os_memcpy(pos, *resp, *resp_len);
 	pos += *resp_len;
 	AVP_PAD(avp, pos);
-	free(*resp);
+	os_free(*resp);
 	*resp = avp;
 	*resp_len = pos - avp;
 	return 0;
 }
 
 
-static int eap_ttls_phase2_nak(struct eap_sm *sm,
-			       struct eap_ttls_data *data,
-			       struct eap_hdr *hdr,
+static int eap_ttls_ia_permute_inner_secret(struct eap_sm *sm,
+					    struct eap_ttls_data *data,
+					    const u8 *key, size_t key_len)
+{
+	u8 *buf;
+	size_t buf_len;
+	int ret;
+
+	if (key) {
+		buf_len = 2 + key_len;
+		buf = os_malloc(buf_len);
+		if (buf == NULL)
+			return -1;
+		WPA_PUT_BE16(buf, key_len);
+		os_memcpy(buf + 2, key, key_len);
+	} else {
+		buf = NULL;
+		buf_len = 0;
+	}
+
+	wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Session keys for TLS/IA inner "
+			"secret permutation", buf, buf_len);
+	ret = tls_connection_ia_permute_inner_secret(sm->ssl_ctx,
+						     data->ssl.conn,
+						     buf, buf_len);
+	os_free(buf);
+
+	return ret;
+}
+
+
+static int eap_ttls_v0_derive_key(struct eap_sm *sm,
+				  struct eap_ttls_data *data)
+{
+	os_free(data->key_data);
+	data->key_data = eap_tls_derive_key(sm, &data->ssl,
+					    "ttls keying material",
+					    EAP_TLS_KEY_LEN);
+	if (!data->key_data) {
+		wpa_printf(MSG_INFO, "EAP-TTLS: Failed to derive key");
+		return -1;
+	}
+
+	wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Derived key",
+			data->key_data, EAP_TLS_KEY_LEN);
+
+	return 0;
+}
+
+
+static int eap_ttls_v1_derive_key(struct eap_sm *sm,
+				  struct eap_ttls_data *data)
+{
+	struct tls_keys keys;
+	u8 *rnd;
+
+	os_free(data->key_data);
+	data->key_data = NULL;
+
+	os_memset(&keys, 0, sizeof(keys));
+	if (tls_connection_get_keys(sm->ssl_ctx, data->ssl.conn, &keys) ||
+	    keys.client_random == NULL || keys.server_random == NULL ||
+	    keys.inner_secret == NULL) {
+		wpa_printf(MSG_INFO, "EAP-TTLS: Could not get inner secret, "
+			   "client random, or server random to derive keying "
+			   "material");
+		return -1;
+	}
+
+	rnd = os_malloc(keys.client_random_len + keys.server_random_len);
+	data->key_data = os_malloc(EAP_TLS_KEY_LEN);
+	if (rnd == NULL || data->key_data == NULL) {
+		wpa_printf(MSG_INFO, "EAP-TTLS: No memory for key derivation");
+		os_free(rnd);
+		os_free(data->key_data);
+		data->key_data = NULL;
+		return -1;
+	}
+	os_memcpy(rnd, keys.client_random, keys.client_random_len);
+	os_memcpy(rnd + keys.client_random_len, keys.server_random,
+		  keys.server_random_len);
+
+	if (tls_prf(keys.inner_secret, keys.inner_secret_len,
+		    "ttls v1 keying material", rnd, keys.client_random_len +
+		    keys.server_random_len, data->key_data, EAP_TLS_KEY_LEN)) {
+		wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to derive key");
+		os_free(rnd);
+		os_free(data->key_data);
+		data->key_data = NULL;
+		return -1;
+	}
+
+	wpa_hexdump(MSG_DEBUG, "EAP-TTLS: client/server random",
+		    rnd, keys.client_random_len + keys.server_random_len);
+	wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: TLS/IA inner secret",
+			keys.inner_secret, keys.inner_secret_len);
+
+	os_free(rnd);
+
+	wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Derived key",
+			data->key_data, EAP_TLS_KEY_LEN);
+
+	return 0;
+}
+
+
+static u8 * eap_ttls_implicit_challenge(struct eap_sm *sm,
+					struct eap_ttls_data *data, size_t len)
+{
+	struct tls_keys keys;
+	u8 *challenge, *rnd;
+
+	if (data->ttls_version == 0) {
+		return eap_tls_derive_key(sm, &data->ssl, "ttls challenge",
+					  len);
+	}
+
+	os_memset(&keys, 0, sizeof(keys));
+	if (tls_connection_get_keys(sm->ssl_ctx, data->ssl.conn, &keys) ||
+	    keys.client_random == NULL || keys.server_random == NULL ||
+	    keys.inner_secret == NULL) {
+		wpa_printf(MSG_INFO, "EAP-TTLS: Could not get inner secret, "
+			   "client random, or server random to derive "
+			   "implicit challenge");
+		return NULL;
+	}
+
+	rnd = os_malloc(keys.client_random_len + keys.server_random_len);
+	challenge = os_malloc(len);
+	if (rnd == NULL || challenge == NULL) {
+		wpa_printf(MSG_INFO, "EAP-TTLS: No memory for implicit "
+			   "challenge derivation");
+		os_free(rnd);
+		os_free(challenge);
+		return NULL;
+	}
+	os_memcpy(rnd, keys.server_random, keys.server_random_len);
+	os_memcpy(rnd + keys.server_random_len, keys.client_random,
+		  keys.client_random_len);
+
+	if (tls_prf(keys.inner_secret, keys.inner_secret_len,
+		    "inner application challenge", rnd,
+		    keys.client_random_len + keys.server_random_len,
+		    challenge, len)) {
+		wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to derive implicit "
+			   "challenge");
+		os_free(rnd);
+		os_free(challenge);
+		return NULL;
+	}
+
+	os_free(rnd);
+
+	wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Derived implicit challenge",
+			challenge, len);
+
+	return challenge;
+}
+
+
+static int eap_ttls_phase2_nak(struct eap_ttls_data *data, struct eap_hdr *hdr,
 			       u8 **resp, size_t *resp_len)
 {
 	struct eap_hdr *resp_hdr;
 	u8 *pos = (u8 *) (hdr + 1);
+	size_t i;
 
+	/* TODO: add support for expanded Nak */
 	wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 Request: Nak type=%d", *pos);
 	wpa_hexdump(MSG_DEBUG, "EAP-TTLS: Allowed Phase2 EAP types",
-		    data->phase2_eap_types, data->num_phase2_eap_types);
-	*resp_len = sizeof(struct eap_hdr) + 1 + data->num_phase2_eap_types;
-	*resp = malloc(*resp_len);
+		    (u8 *) data->phase2_eap_types, data->num_phase2_eap_types *
+		    sizeof(struct eap_method_type));
+	*resp_len = sizeof(struct eap_hdr) + 1;
+	*resp = os_malloc(*resp_len + data->num_phase2_eap_types);
 	if (*resp == NULL)
 		return -1;
 
 	resp_hdr = (struct eap_hdr *) (*resp);
 	resp_hdr->code = EAP_CODE_RESPONSE;
 	resp_hdr->identifier = hdr->identifier;
-	resp_hdr->length = host_to_be16(*resp_len);
 	pos = (u8 *) (resp_hdr + 1);
 	*pos++ = EAP_TYPE_NAK;
-	memcpy(pos, data->phase2_eap_types, data->num_phase2_eap_types);
+	for (i = 0; i < data->num_phase2_eap_types; i++) {
+		if (data->phase2_eap_types[i].vendor == EAP_VENDOR_IETF &&
+		    data->phase2_eap_types[i].method < 256) {
+			(*resp_len)++;
+			*pos++ = data->phase2_eap_types[i].method;
+		}
+	}
+	resp_hdr->length = host_to_be16(*resp_len);
 
 	return 0;
 }
@@ -312,7 +518,6 @@
 static int eap_ttls_phase2_request_eap(struct eap_sm *sm,
 				       struct eap_ttls_data *data,
 				       struct eap_method_ret *ret,
-				       const struct eap_hdr *req,
 				       struct eap_hdr *hdr,
 				       u8 **resp, size_t *resp_len)
 {
@@ -330,35 +535,46 @@
 	wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 EAP Request: type=%d", *pos);
 	switch (*pos) {
 	case EAP_TYPE_IDENTITY:
-		*resp = eap_sm_buildIdentity(sm, req->identifier, resp_len, 1);
+		*resp = eap_sm_buildIdentity(sm, hdr->identifier, resp_len, 1);
 		break;
 	default:
-		if (data->phase2_eap_type == EAP_TYPE_NONE) {
-			int i;
+		if (data->phase2_eap_type.vendor == EAP_VENDOR_IETF &&
+		    data->phase2_eap_type.method == EAP_TYPE_NONE) {
+			size_t i;
 			for (i = 0; i < data->num_phase2_eap_types; i++) {
-				if (data->phase2_eap_types[i] != *pos)
+				if (data->phase2_eap_types[i].vendor !=
+				    EAP_VENDOR_IETF ||
+				    data->phase2_eap_types[i].method != *pos)
 					continue;
 
-				data->phase2_eap_type = *pos;
+				data->phase2_eap_type.vendor =
+					data->phase2_eap_types[i].vendor;
+				data->phase2_eap_type.method =
+					data->phase2_eap_types[i].method;
 				wpa_printf(MSG_DEBUG, "EAP-TTLS: Selected "
-					   "Phase 2 EAP method %d",
-					   data->phase2_eap_type);
+					   "Phase 2 EAP vendor %d method %d",
+					   data->phase2_eap_type.vendor,
+					   data->phase2_eap_type.method);
 				break;
 			}
 		}
-		if (*pos != data->phase2_eap_type || *pos == EAP_TYPE_NONE) {
-			if (eap_ttls_phase2_nak(sm, data, hdr, resp, resp_len))
+		if (*pos != data->phase2_eap_type.method ||
+		    *pos == EAP_TYPE_NONE) {
+			if (eap_ttls_phase2_nak(data, hdr, resp, resp_len))
 				return -1;
 			break;
 		}
 
 		if (data->phase2_priv == NULL) {
-			data->phase2_method = eap_sm_get_eap_methods(*pos);
+			data->phase2_method = eap_sm_get_eap_methods(
+				EAP_VENDOR_IETF, *pos);
 			if (data->phase2_method) {
 				sm->init_phase2 = 1;
+				sm->mschapv2_full_key = 1;
 				data->phase2_priv =
 					data->phase2_method->init(sm);
 				sm->init_phase2 = 0;
+				sm->mschapv2_full_key = 0;
 			}
 		}
 		if (data->phase2_priv == NULL || data->phase2_method == NULL) {
@@ -366,7 +582,7 @@
 				   "Phase 2 EAP method %d", *pos);
 			return -1;
 		}
-		memset(&iret, 0, sizeof(iret));
+		os_memset(&iret, 0, sizeof(iret));
 		*resp = data->phase2_method->process(sm, data->phase2_priv,
 						     &iret, (u8 *) hdr, len,
 						     resp_len);
@@ -378,6 +594,28 @@
 			ret->methodState = iret.methodState;
 			ret->decision = iret.decision;
 		}
+		if (data->ttls_version > 0) {
+			const struct eap_method *m = data->phase2_method;
+			void *priv = data->phase2_priv;
+
+			/* TTLSv1 requires TLS/IA FinalPhaseFinished */
+			if (ret->decision == DECISION_UNCOND_SUCC)
+				ret->decision = DECISION_COND_SUCC;
+			ret->methodState = METHOD_CONT;
+
+			if (ret->decision == DECISION_COND_SUCC &&
+			    m->isKeyAvailable && m->getKey &&
+			    m->isKeyAvailable(sm, priv)) {
+				u8 *key;
+				size_t key_len;
+				key = m->getKey(sm, priv, &key_len);
+				if (key) {
+					eap_ttls_ia_permute_inner_secret(
+						sm, data, key, key_len);
+					os_free(key);
+				}
+			}
+		}
 		break;
 	}
 
@@ -400,14 +638,11 @@
 static int eap_ttls_phase2_request_mschapv2(struct eap_sm *sm,
 					    struct eap_ttls_data *data,
 					    struct eap_method_ret *ret,
-					    const struct eap_hdr *req,
-					    struct eap_hdr *hdr,
 					    u8 **resp, size_t *resp_len)
 {
 	struct wpa_ssid *config = eap_get_config(sm);
 	u8 *buf, *pos, *challenge, *username, *peer_challenge;
-	size_t username_len;
-	int i;
+	size_t username_len, i;
 
 	wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 MSCHAPV2 Request");
 
@@ -425,7 +660,7 @@
 		}
 	}
 
-	pos = buf = malloc(config->identity_len + 1000);
+	pos = buf = os_malloc(config->identity_len + 1000);
 	if (buf == NULL) {
 		wpa_printf(MSG_ERROR,
 			   "EAP-TTLS/MSCHAPV2: Failed to allocate memory");
@@ -437,11 +672,10 @@
 			       config->identity, config->identity_len);
 
 	/* MS-CHAP-Challenge */
-	challenge = eap_tls_derive_key(sm, &data->ssl, "ttls challenge",
-				       EAP_TTLS_MSCHAPV2_CHALLENGE_LEN * 2 +
-				       1);
+	challenge = eap_ttls_implicit_challenge(
+		sm, data, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN * 2 + 1);
 	if (challenge == NULL) {
-		free(buf);
+		os_free(buf);
 		wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAPV2: Failed to derive "
 			   "implicit challenge");
 		return -1;
@@ -459,9 +693,9 @@
 	data->ident = challenge[EAP_TTLS_MSCHAPV2_CHALLENGE_LEN];
 	*pos++ = data->ident;
 	*pos++ = 0; /* Flags */
-	memcpy(pos, peer_challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN);
+	os_memcpy(pos, peer_challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN);
 	pos += EAP_TTLS_MSCHAPV2_CHALLENGE_LEN;
-	memset(pos, 0, 8); /* Reserved, must be zero */
+	os_memset(pos, 0, 8); /* Reserved, must be zero */
 	pos += 8;
 	wpa_hexdump(MSG_DEBUG, "EAP-TTLS: MSCHAPV2: implicit auth_challenge",
 		    challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN);
@@ -482,14 +716,32 @@
 					pos, data->auth_response);
 	data->auth_response_valid = 1;
 
+	if (data->ttls_version > 0) {
+		u8 pw_hash[16], pw_hash_hash[16], master_key[16];
+		u8 session_key[2 * MSCHAPV2_KEY_LEN];
+		nt_password_hash(config->password, config->password_len,
+				 pw_hash);
+		hash_nt_password_hash(pw_hash, pw_hash_hash);
+		get_master_key(pw_hash_hash, pos /* nt_response */,
+			       master_key);
+		get_asymetric_start_key(master_key, session_key,
+					MSCHAPV2_KEY_LEN, 0, 0);
+		get_asymetric_start_key(master_key,
+					session_key + MSCHAPV2_KEY_LEN,
+					MSCHAPV2_KEY_LEN, 1, 0);
+		eap_ttls_ia_permute_inner_secret(sm, data,
+						 session_key,
+						 sizeof(session_key));
+	}
+
 	pos += 24;
-	free(challenge);
+	os_free(challenge);
 	AVP_PAD(buf, pos);
 
 	*resp = buf;
 	*resp_len = pos - buf;
 
-	if (sm->workaround) {
+	if (sm->workaround && data->ttls_version == 0) {
 		/* At least FreeRADIUS seems to be terminating
 		 * EAP-TTLS/MSHCAPV2 without the expected MS-CHAP-v2 Success
 		 * packet. */
@@ -506,8 +758,6 @@
 static int eap_ttls_phase2_request_mschap(struct eap_sm *sm,
 					  struct eap_ttls_data *data,
 					  struct eap_method_ret *ret,
-					  const struct eap_hdr *req,
-					  struct eap_hdr *hdr,
 					  u8 **resp, size_t *resp_len)
 {
 	struct wpa_ssid *config = eap_get_config(sm);
@@ -515,7 +765,7 @@
 
 	wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 MSCHAP Request");
 
-	pos = buf = malloc(config->identity_len + 1000);
+	pos = buf = os_malloc(config->identity_len + 1000);
 	if (buf == NULL) {
 		wpa_printf(MSG_ERROR,
 			   "EAP-TTLS/MSCHAP: Failed to allocate memory");
@@ -527,10 +777,9 @@
 			       config->identity, config->identity_len);
 
 	/* MS-CHAP-Challenge */
-	challenge = eap_tls_derive_key(sm, &data->ssl, "ttls challenge",
-				       EAP_TLS_KEY_LEN);
+	challenge = eap_ttls_implicit_challenge(sm, data, EAP_TLS_KEY_LEN);
 	if (challenge == NULL) {
-		free(buf);
+		os_free(buf);
 		wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAP: Failed to derive "
 			   "implicit challenge");
 		return -1;
@@ -547,7 +796,7 @@
 	data->ident = challenge[EAP_TTLS_MSCHAP_CHALLENGE_LEN];
 	*pos++ = data->ident;
 	*pos++ = 1; /* Flags: Use NT style passwords */
-	memset(pos, 0, 24); /* LM-Response */
+	os_memset(pos, 0, 24); /* LM-Response */
 	pos += 24;
 	nt_challenge_response(challenge,
 			      config->password, config->password_len,
@@ -558,16 +807,23 @@
 		    challenge, EAP_TTLS_MSCHAP_CHALLENGE_LEN);
 	wpa_hexdump(MSG_DEBUG, "EAP-TTLS: MSCHAP response", pos, 24);
 	pos += 24;
-	free(challenge);
+	os_free(challenge);
 	AVP_PAD(buf, pos);
 
 	*resp = buf;
 	*resp_len = pos - buf;
 
-	/* EAP-TTLS/MSCHAP does not provide tunneled success notification, so
-	 * assume that Phase2 succeeds. */
-	ret->methodState = METHOD_DONE;
-	ret->decision = DECISION_COND_SUCC;
+	if (data->ttls_version > 0) {
+		/* EAP-TTLSv1 uses TLS/IA FinalPhaseFinished to report success,
+		 * so do not allow connection to be terminated yet. */
+		ret->methodState = METHOD_CONT;
+		ret->decision = DECISION_COND_SUCC;
+	} else {
+		/* EAP-TTLS/MSCHAP does not provide tunneled success
+		 * notification, so assume that Phase2 succeeds. */
+		ret->methodState = METHOD_DONE;
+		ret->decision = DECISION_COND_SUCC;
+	}
 
 	return 0;
 }
@@ -576,8 +832,6 @@
 static int eap_ttls_phase2_request_pap(struct eap_sm *sm,
 				       struct eap_ttls_data *data,
 				       struct eap_method_ret *ret,
-				       const struct eap_hdr *req,
-				       struct eap_hdr *hdr,
 				       u8 **resp, size_t *resp_len)
 {
 	struct wpa_ssid *config = eap_get_config(sm);
@@ -586,7 +840,8 @@
 
 	wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 PAP Request");
 
-	pos = buf = malloc(config->identity_len + config->password_len + 100);
+	pos = buf = os_malloc(config->identity_len + config->password_len +
+			      100);
 	if (buf == NULL) {
 		wpa_printf(MSG_ERROR,
 			   "EAP-TTLS/PAP: Failed to allocate memory");
@@ -603,19 +858,26 @@
 	pad = (16 - (config->password_len & 15)) & 15;
 	pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_USER_PASSWORD, 0, 1,
 			       config->password_len + pad);
-	memcpy(pos, config->password, config->password_len);
+	os_memcpy(pos, config->password, config->password_len);
 	pos += config->password_len;
-	memset(pos, 0, pad);
+	os_memset(pos, 0, pad);
 	pos += pad;
 	AVP_PAD(buf, pos);
 
 	*resp = buf;
 	*resp_len = pos - buf;
 
-	/* EAP-TTLS/PAP does not provide tunneled success notification, so
-	 * assume that Phase2 succeeds. */
-	ret->methodState = METHOD_DONE;
-	ret->decision = DECISION_COND_SUCC;
+	if (data->ttls_version > 0) {
+		/* EAP-TTLSv1 uses TLS/IA FinalPhaseFinished to report success,
+		 * so do not allow connection to be terminated yet. */
+		ret->methodState = METHOD_CONT;
+		ret->decision = DECISION_COND_SUCC;
+	} else {
+		/* EAP-TTLS/PAP does not provide tunneled success notification,
+		 * so assume that Phase2 succeeds. */
+		ret->methodState = METHOD_DONE;
+		ret->decision = DECISION_COND_SUCC;
+	}
 
 	return 0;
 }
@@ -624,8 +886,6 @@
 static int eap_ttls_phase2_request_chap(struct eap_sm *sm,
 					struct eap_ttls_data *data,
 					struct eap_method_ret *ret,
-					const struct eap_hdr *req,
-					struct eap_hdr *hdr,
 					u8 **resp, size_t *resp_len)
 {
 	struct wpa_ssid *config = eap_get_config(sm);
@@ -635,7 +895,7 @@
 
 	wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 CHAP Request");
 
-	pos = buf = malloc(config->identity_len + 1000);
+	pos = buf = os_malloc(config->identity_len + 1000);
 	if (buf == NULL) {
 		wpa_printf(MSG_ERROR,
 			   "EAP-TTLS/CHAP: Failed to allocate memory");
@@ -647,10 +907,9 @@
 			       config->identity, config->identity_len);
 
 	/* CHAP-Challenge */
-	challenge = eap_tls_derive_key(sm, &data->ssl, "ttls challenge",
-				       EAP_TLS_KEY_LEN);
+	challenge = eap_ttls_implicit_challenge(sm, data, EAP_TLS_KEY_LEN);
 	if (challenge == NULL) {
-		free(buf);
+		os_free(buf);
 		wpa_printf(MSG_ERROR, "EAP-TTLS/CHAP: Failed to derive "
 			   "implicit challenge");
 		return -1;
@@ -683,16 +942,23 @@
 	wpa_hexdump(MSG_DEBUG, "EAP-TTLS: CHAP password",
 		    pos, EAP_TTLS_CHAP_PASSWORD_LEN);
 	pos += EAP_TTLS_CHAP_PASSWORD_LEN;
-	free(challenge);
+	os_free(challenge);
 	AVP_PAD(buf, pos);
 
 	*resp = buf;
 	*resp_len = pos - buf;
 
-	/* EAP-TTLS/CHAP does not provide tunneled success notification, so
-	 * assume that Phase2 succeeds. */
-	ret->methodState = METHOD_DONE;
-	ret->decision = DECISION_COND_SUCC;
+	if (data->ttls_version > 0) {
+		/* EAP-TTLSv1 uses TLS/IA FinalPhaseFinished to report success,
+		 * so do not allow connection to be terminated yet. */
+		ret->methodState = METHOD_CONT;
+		ret->decision = DECISION_COND_SUCC;
+	} else {
+		/* EAP-TTLS/CHAP does not provide tunneled success
+		 * notification, so assume that Phase2 succeeds. */
+		ret->methodState = METHOD_DONE;
+		ret->decision = DECISION_COND_SUCC;
+	}
 
 	return 0;
 }
@@ -705,49 +971,49 @@
 				   struct eap_hdr *hdr,
 				   u8 **resp, size_t *resp_len)
 {
-	struct wpa_ssid *config = eap_get_config(sm);
 	int res = 0;
+	size_t len;
 
 	if (data->phase2_type == EAP_TTLS_PHASE2_MSCHAPV2 ||
 	    data->phase2_type == EAP_TTLS_PHASE2_MSCHAP ||
 	    data->phase2_type == EAP_TTLS_PHASE2_PAP ||
 	    data->phase2_type == EAP_TTLS_PHASE2_CHAP) {
-		if (config == NULL || config->identity == NULL) {
+		if (eap_get_config_identity(sm, &len) == NULL) {
 			wpa_printf(MSG_INFO,
 				   "EAP-TTLS: Identity not configured");
-			eap_sm_request_identity(sm, config);
-			if (config->password == NULL)
-				eap_sm_request_password(sm, config);
+			eap_sm_request_identity(sm);
+			if (eap_get_config_password(sm, &len) == NULL)
+				eap_sm_request_password(sm);
 			return 0;
 		}
 
-		if (config->password == NULL) {
+		if (eap_get_config_password(sm, &len) == NULL) {
 			wpa_printf(MSG_INFO,
 				   "EAP-TTLS: Password not configured");
-			eap_sm_request_password(sm, config);
+			eap_sm_request_password(sm);
 			return 0;
 		}
 	}
 
 	switch (data->phase2_type) {
 	case EAP_TTLS_PHASE2_EAP:
-		res = eap_ttls_phase2_request_eap(sm, data, ret, req, hdr,
+		res = eap_ttls_phase2_request_eap(sm, data, ret, hdr,
 						  resp, resp_len);
 		break;
 	case EAP_TTLS_PHASE2_MSCHAPV2:
-		res = eap_ttls_phase2_request_mschapv2(sm, data, ret, req, hdr,
+		res = eap_ttls_phase2_request_mschapv2(sm, data, ret,
 						       resp, resp_len);
 		break;
 	case EAP_TTLS_PHASE2_MSCHAP:
-		res = eap_ttls_phase2_request_mschap(sm, data, ret, req, hdr,
+		res = eap_ttls_phase2_request_mschap(sm, data, ret,
 						     resp, resp_len);
 		break;
 	case EAP_TTLS_PHASE2_PAP:
-		res = eap_ttls_phase2_request_pap(sm, data, ret, req, hdr,
+		res = eap_ttls_phase2_request_pap(sm, data, ret,
 						  resp, resp_len);
 		break;
 	case EAP_TTLS_PHASE2_CHAP:
-		res = eap_ttls_phase2_request_chap(sm, data, ret, req, hdr,
+		res = eap_ttls_phase2_request_chap(sm, data, ret,
 						   resp, resp_len);
 		break;
 	default:
@@ -765,6 +1031,43 @@
 }
 
 
+static u8 * eap_ttls_build_phase_finished(struct eap_sm *sm,
+					  struct eap_ttls_data *data,
+					  int id, int final,
+					  size_t *reqDataLen)
+{
+	int len;
+	struct eap_hdr *req;
+	u8 *pos;
+	const int max_len = 300;
+
+	len = sizeof(struct eap_hdr) + 2 + max_len;
+	req = os_malloc(len);
+	if (req == NULL)
+		return NULL;
+
+	req->code = EAP_CODE_RESPONSE;
+	req->identifier = id;
+
+	pos = (u8 *) (req + 1);
+	*pos++ = EAP_TYPE_TTLS;
+	*pos++ = data->ttls_version;
+
+	len = tls_connection_ia_send_phase_finished(sm->ssl_ctx,
+						    data->ssl.conn,
+						    final, pos, max_len);
+	if (len < 0) {
+		os_free(req);
+		return NULL;
+	}
+
+	*reqDataLen = sizeof(struct eap_hdr) + 2 + len;
+	req->length = host_to_be16(*reqDataLen);
+
+	return (u8 *) req;
+}
+
+
 static int eap_ttls_decrypt(struct eap_sm *sm, struct eap_ttls_data *data,
 			    struct eap_method_ret *ret,
 			    const struct eap_hdr *req,
@@ -772,10 +1075,10 @@
 			    u8 **out_data, size_t *out_len)
 {
 	u8 *in_decrypted = NULL, *pos;
-	int buf_len, len_decrypted = 0, len, left, retval = 0;
+	int res, retval = 0;
 	struct eap_hdr *hdr = NULL;
 	u8 *resp = NULL, *mschapv2 = NULL, *eapdata = NULL;
-	size_t resp_len, eap_len = 0;
+	size_t resp_len, eap_len = 0, len_decrypted = 0, len, buf_len, left;
 	struct ttls_avp *avp;
 	u8 recv_response[20];
 	int mschapv2_error = 0;
@@ -791,7 +1094,7 @@
 		wpa_printf(MSG_DEBUG, "EAP-TTLS: Pending Phase 2 request - "
 			   "skip decryption and use old data");
 		/* Clear TLS reassembly state. */
-		free(data->ssl.tls_in);
+		os_free(data->ssl.tls_in);
 		data->ssl.tls_in = NULL;
 		data->ssl.tls_in_len = 0;
 		data->ssl.tls_in_left = 0;
@@ -801,7 +1104,7 @@
 		data->pending_phase2_req = NULL;
 		len_decrypted = data->pending_phase2_req_len;
 		if (data->pending_phase2_req_len == 0) {
-			free(in_decrypted);
+			os_free(in_decrypted);
 			in_decrypted = NULL;
 			goto fake_req_identity;
 		}
@@ -831,7 +1134,7 @@
 		wpa_printf(MSG_DEBUG, "EAP-TTLS: empty data in beginning of "
 			   "Phase 2 - use fake EAP-Request Identity");
 		buf_len = sizeof(*hdr) + 1;
-		in_decrypted = malloc(buf_len);
+		in_decrypted = os_malloc(buf_len);
 		if (in_decrypted == NULL) {
 			wpa_printf(MSG_WARNING, "EAP-TTLS: failed to allocate "
 				   "memory for fake EAP-Identity Request");
@@ -854,9 +1157,9 @@
 	buf_len = in_len;
 	if (data->ssl.tls_in_total > buf_len)
 		buf_len = data->ssl.tls_in_total;
-	in_decrypted = malloc(buf_len);
+	in_decrypted = os_malloc(buf_len);
 	if (in_decrypted == NULL) {
-		free(data->ssl.tls_in);
+		os_free(data->ssl.tls_in);
 		data->ssl.tls_in = NULL;
 		data->ssl.tls_in_len = 0;
 		wpa_printf(MSG_WARNING, "EAP-TTLS: failed to allocate memory "
@@ -865,18 +1168,34 @@
 		goto done;
 	}
 
-	len_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,
-					       msg, msg_len,
-					       in_decrypted, buf_len);
-	free(data->ssl.tls_in);
+	res = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,
+				     msg, msg_len, in_decrypted, buf_len);
+	os_free(data->ssl.tls_in);
 	data->ssl.tls_in = NULL;
 	data->ssl.tls_in_len = 0;
-	if (len_decrypted < 0) {
+	if (res < 0) {
 		wpa_printf(MSG_INFO, "EAP-TTLS: Failed to decrypt Phase 2 "
 			   "data");
 		retval = -1;
 		goto done;
 	}
+	len_decrypted = res;
+
+	if (data->ttls_version > 0 && len_decrypted == 0 &&
+	    tls_connection_ia_final_phase_finished(sm->ssl_ctx,
+						   data->ssl.conn)) {
+		wpa_printf(MSG_DEBUG, "EAP-TTLS: FinalPhaseFinished received");
+		wpa_printf(MSG_INFO, "EAP-TTLS: TLS/IA authentication "
+			   "succeeded");
+		ret->methodState = METHOD_DONE;
+		ret->decision = DECISION_UNCOND_SUCC;
+		data->phase2_success = 1;
+		*out_data = eap_ttls_build_phase_finished(sm, data,
+							  req->identifier, 1,
+							  out_len);
+		eap_ttls_v1_derive_key(sm, data);
+		goto done;
+	}
 
 continue_req:
 	data->phase2_start = 0;
@@ -885,8 +1204,8 @@
 		    in_decrypted, len_decrypted);
 	if (len_decrypted < sizeof(struct ttls_avp)) {
 		wpa_printf(MSG_WARNING, "EAP-TTLS: Too short Phase 2 AVP frame"
-			   " len=%d expected %lu or more - dropped",
-			   len_decrypted,
+			   " len=%lu expected %lu or more - dropped",
+			   (unsigned long) len_decrypted,
 			   (unsigned long) sizeof(struct ttls_avp));
 		retval = -1;
 		goto done;
@@ -911,8 +1230,14 @@
 			   (int) avp_length);
 		if (avp_length > left) {
 			wpa_printf(MSG_WARNING, "EAP-TTLS: AVP overflow "
-				   "(len=%d, left=%d) - dropped",
-				   (int) avp_length, left);
+				   "(len=%d, left=%lu) - dropped",
+				   (int) avp_length, (unsigned long) left);
+			retval = -1;
+			goto done;
+		}
+		if (avp_length < sizeof(*avp)) {
+			wpa_printf(MSG_WARNING, "EAP-TTLS: Invalid AVP length "
+				   "%d", avp_length);
 			retval = -1;
 			goto done;
 		}
@@ -937,7 +1262,7 @@
 		if (vendor_id == 0 && avp_code == RADIUS_ATTR_EAP_MESSAGE) {
 			wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP - EAP Message");
 			if (eapdata == NULL) {
-				eapdata = malloc(dlen);
+				eapdata = os_malloc(dlen);
 				if (eapdata == NULL) {
 					retval = -1;
 					wpa_printf(MSG_WARNING, "EAP-TTLS: "
@@ -945,10 +1270,11 @@
 						   "for Phase 2 EAP data");
 					goto done;
 				}
-				memcpy(eapdata, dpos, dlen);
+				os_memcpy(eapdata, dpos, dlen);
 				eap_len = dlen;
 			} else {
-				u8 *neweap = realloc(eapdata, eap_len + dlen);
+				u8 *neweap = os_realloc(eapdata,
+							eap_len + dlen);
 				if (neweap == NULL) {
 					retval = -1;
 					wpa_printf(MSG_WARNING, "EAP-TTLS: "
@@ -956,7 +1282,7 @@
 						   "for Phase 2 EAP data");
 					goto done;
 				}
-				memcpy(neweap + eap_len, dpos, dlen);
+				os_memcpy(neweap + eap_len, dpos, dlen);
 				eapdata = neweap;
 				eap_len += dlen;
 			}
@@ -999,7 +1325,10 @@
 
 		pad = (4 - (avp_length & 3)) & 3;
 		pos += avp_length + pad;
-		left -= avp_length + pad;
+		if (left < avp_length + pad)
+			left = 0;
+		else
+			left -= avp_length + pad;
 	}
 
 	switch (data->phase2_type) {
@@ -1026,15 +1355,16 @@
 		len = be_to_host16(hdr->length);
 		if (len > eap_len) {
 			wpa_printf(MSG_INFO, "EAP-TTLS: Length mismatch in "
-				   "Phase 2 EAP frame (EAP hdr len=%d, EAP "
-				   "data len in AVP=%lu)", len,
+				   "Phase 2 EAP frame (EAP hdr len=%lu, EAP "
+				   "data len in AVP=%lu)",
+				   (unsigned long) len,
 				   (unsigned long) eap_len);
 			retval = -1;
 			goto done;
 		}
 		wpa_printf(MSG_DEBUG, "EAP-TTLS: received Phase 2: code=%d "
-			   "identifier=%d length=%d",
-			   hdr->code, hdr->identifier, len);
+			   "identifier=%d length=%lu",
+			   hdr->code, hdr->identifier, (unsigned long) len);
 	process_eap:
 		switch (hdr->code) {
 		case EAP_CODE_REQUEST:
@@ -1082,7 +1412,7 @@
 		if (!data->auth_response_valid ||
 		    mschapv2[1] != 'S' || mschapv2[2] != '=' ||
 		    hexstr2bin((char *) (mschapv2 + 3), recv_response, 20) ||
-		    memcmp(data->auth_response, recv_response, 20) != 0) {
+		    os_memcmp(data->auth_response, recv_response, 20) != 0) {
 			wpa_printf(MSG_WARNING, "EAP-TTLS: Invalid "
 				   "authenticator response in Phase 2 "
 				   "MSCHAPV2 success request");
@@ -1092,9 +1422,17 @@
 
 		wpa_printf(MSG_INFO, "EAP-TTLS: Phase 2 MSCHAPV2 "
 			   "authentication succeeded");
-		ret->methodState = METHOD_DONE;
-		ret->decision = DECISION_UNCOND_SUCC;
-		data->phase2_success = 1;
+		if (data->ttls_version > 0) {
+			/* EAP-TTLSv1 uses TLS/IA FinalPhaseFinished to report
+			 * success, so do not allow connection to be terminated
+			 * yet. */
+			ret->methodState = METHOD_CONT;
+			ret->decision = DECISION_COND_SUCC;
+		} else {
+			ret->methodState = METHOD_DONE;
+			ret->decision = DECISION_UNCOND_SUCC;
+			data->phase2_success = 1;
+		}
 
 		/* Reply with empty data; authentication server will reply
 		 * with EAP-Success after this. */
@@ -1120,23 +1458,23 @@
 			wpa_printf(MSG_INFO, "EAP-TTLS: Failed to encrypt "
 				   "a Phase 2 frame");
 		}
-		free(resp);
+		os_free(resp);
 	} else if (config->pending_req_identity ||
 		   config->pending_req_password ||
 		   config->pending_req_otp ||
 		   config->pending_req_new_password) {
-		free(data->pending_phase2_req);
-		data->pending_phase2_req = malloc(len_decrypted);
+		os_free(data->pending_phase2_req);
+		data->pending_phase2_req = os_malloc(len_decrypted);
 		if (data->pending_phase2_req) {
-			memcpy(data->pending_phase2_req, in_decrypted,
-			       len_decrypted);
+			os_memcpy(data->pending_phase2_req, in_decrypted,
+				  len_decrypted);
 			data->pending_phase2_req_len = len_decrypted;
 		}
 	}
 
 done:
-	free(in_decrypted);
-	free(eapdata);
+	os_free(in_decrypted);
+	os_free(eapdata);
 
 	if (retval < 0) {
 		ret->methodState = METHOD_DONE;
@@ -1158,6 +1496,7 @@
 	u8 flags, *resp, id;
 	const u8 *pos;
 	struct eap_ttls_data *data = priv;
+	struct wpa_ssid *config = eap_get_config(sm);
 
 	pos = eap_tls_process_init(sm, &data->ssl, EAP_TYPE_TTLS, ret,
 				   reqData, reqDataLen, &left, &flags);
@@ -1167,6 +1506,34 @@
 	id = req->identifier;
 
 	if (flags & EAP_TLS_FLAGS_START) {
+		wpa_printf(MSG_DEBUG, "EAP-TTLS: Start (server ver=%d, own "
+			   "ver=%d)", flags & EAP_PEAP_VERSION_MASK,
+			   data->ttls_version);
+		if ((flags & EAP_PEAP_VERSION_MASK) < data->ttls_version)
+			data->ttls_version = flags & EAP_PEAP_VERSION_MASK;
+		if (data->force_ttls_version >= 0 &&
+		    data->force_ttls_version != data->ttls_version) {
+			wpa_printf(MSG_WARNING, "EAP-TTLS: Failed to select "
+				   "forced TTLS version %d",
+				   data->force_ttls_version);
+			ret->methodState = METHOD_DONE;
+			ret->decision = DECISION_FAIL;
+			ret->allowNotifications = FALSE;
+			return NULL;
+		}
+		wpa_printf(MSG_DEBUG, "EAP-TTLS: Using TTLS version %d",
+			   data->ttls_version);
+
+		if (data->ttls_version > 0)
+			data->ssl.tls_ia = 1;
+		if (!data->ssl_initialized &&
+		    eap_tls_ssl_init(sm, &data->ssl, config)) {
+			wpa_printf(MSG_INFO, "EAP-TTLS: Failed to initialize "
+				   "SSL.");
+			return NULL;
+		}
+		data->ssl_initialized = 1;
+
 		wpa_printf(MSG_DEBUG, "EAP-TTLS: Start");
 		/* draft-ietf-pppext-eap-ttls-03.txt, Ch. 8.1:
 		 * EAP-TTLS Start packet may, in a future specification, be
@@ -1174,6 +1541,13 @@
 		 * must ignore such data but must not reject the Start packet.
 		 */
 		left = 0;
+	} else if (!data->ssl_initialized) {
+		wpa_printf(MSG_DEBUG, "EAP-TTLS: First message did not "
+			   "include Start flag");
+		ret->methodState = METHOD_DONE;
+		ret->decision = DECISION_FAIL;
+		ret->allowNotifications = FALSE;
+		return NULL;
 	}
 
 	resp = NULL;
@@ -1182,8 +1556,8 @@
 		res = eap_ttls_decrypt(sm, data, ret, req, pos, left,
 				       &resp, respDataLen);
 	} else {
-		res = eap_tls_process_helper(sm, &data->ssl, EAP_TYPE_TTLS, 0,
-					     id, pos, left,
+		res = eap_tls_process_helper(sm, &data->ssl, EAP_TYPE_TTLS,
+					     data->ttls_version, id, pos, left,
 					     &resp, respDataLen);
 
 		if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
@@ -1196,20 +1570,8 @@
 				ret->methodState = METHOD_MAY_CONT;
 			}
 			data->phase2_start = 1;
-			free(data->key_data);
-			data->key_data =
-				eap_tls_derive_key(sm, &data->ssl,
-						   "ttls keying material",
-						   EAP_TLS_KEY_LEN);
-			if (data->key_data) {
-				wpa_hexdump_key(MSG_DEBUG,
-						"EAP-TTLS: Derived key",
-						data->key_data,
-						EAP_TLS_KEY_LEN);
-			} else {
-				wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to "
-					   "derive key");
-			}
+			if (data->ttls_version == 0)
+				eap_ttls_v0_derive_key(sm, data);
 
 			if (*respDataLen == 0) {
 				if (eap_ttls_decrypt(sm, data, ret, req, NULL,
@@ -1222,9 +1584,22 @@
 			}
 			data->resuming = 0;
 		}
+
+		if (res == 2) {
+			/*
+			 * Application data included in the handshake message.
+			 */
+			os_free(data->pending_phase2_req);
+			data->pending_phase2_req = resp;
+			data->pending_phase2_req_len = *respDataLen;
+			resp = NULL;
+			*respDataLen = 0;
+			res = eap_ttls_decrypt(sm, data, ret, req, pos, left,
+					       &resp, respDataLen);
+		}
 	}
 
-	if (ret->methodState == METHOD_DONE) {
+	if (data->ttls_version == 0 && ret->methodState == METHOD_DONE) {
 		ret->allowNotifications = FALSE;
 		if (ret->decision == DECISION_UNCOND_SUCC ||
 		    ret->decision == DECISION_COND_SUCC) {
@@ -1232,7 +1607,8 @@
 				   "completed successfully");
 			data->phase2_success = 1;
 		}
-	} else if (sm->workaround && ret->methodState == METHOD_MAY_CONT &&
+	} else if (data->ttls_version == 0 && sm->workaround &&
+		   ret->methodState == METHOD_MAY_CONT &&
 		   (ret->decision == DECISION_UNCOND_SUCC ||
 		    ret->decision == DECISION_COND_SUCC)) {
 			wpa_printf(MSG_DEBUG, "EAP-TTLS: Authentication "
@@ -1242,7 +1618,7 @@
 
 	if (res == 1) {
 		return eap_tls_build_ack(&data->ssl, respDataLen, id,
-					 EAP_TYPE_TTLS, 0);
+					 EAP_TYPE_TTLS, data->ttls_version);
 	}
 	return resp;
 }
@@ -1259,7 +1635,7 @@
 static void eap_ttls_deinit_for_reauth(struct eap_sm *sm, void *priv)
 {
 	struct eap_ttls_data *data = priv;
-	free(data->pending_phase2_req);
+	os_free(data->pending_phase2_req);
 	data->pending_phase2_req = NULL;
 }
 
@@ -1267,12 +1643,15 @@
 static void * eap_ttls_init_for_reauth(struct eap_sm *sm, void *priv)
 {
 	struct eap_ttls_data *data = priv;
-	free(data->key_data);
+	os_free(data->key_data);
 	data->key_data = NULL;
 	if (eap_tls_reauth_init(sm, &data->ssl)) {
-		free(data);
+		os_free(data);
 		return NULL;
 	}
+	if (data->phase2_priv && data->phase2_method &&
+	    data->phase2_method->init_for_reauth)
+		data->phase2_method->init_for_reauth(sm, data->phase2_priv);
 	data->phase2_start = 0;
 	data->phase2_success = 0;
 	data->resuming = 1;
@@ -1285,33 +1664,40 @@
 			       size_t buflen, int verbose)
 {
 	struct eap_ttls_data *data = priv;
-	int len;
+	int len, ret;
 
 	len = eap_tls_status(sm, &data->ssl, buf, buflen, verbose);
+	ret = os_snprintf(buf + len, buflen - len,
+			  "EAP-TTLSv%d Phase2 method=",
+			  data->ttls_version);
+	if (ret < 0 || (size_t) ret >= buflen - len)
+		return len;
+	len += ret;
 	switch (data->phase2_type) {
 	case EAP_TTLS_PHASE2_EAP:
-		len += snprintf(buf + len, buflen - len,
-				"EAP-TTLS Phase2 method=EAP-%s\n",
-				data->phase2_method ? data->phase2_method->name
-				: "?");
+		ret = os_snprintf(buf + len, buflen - len, "EAP-%s\n",
+				  data->phase2_method ?
+				  data->phase2_method->name : "?");
 		break;
 	case EAP_TTLS_PHASE2_MSCHAPV2:
-		len += snprintf(buf + len, buflen - len,
-				"EAP-TTLS Phase2 method=MSCHAPV2\n");
+		ret = os_snprintf(buf + len, buflen - len, "MSCHAPV2\n");
 		break;
 	case EAP_TTLS_PHASE2_MSCHAP:
-		len += snprintf(buf + len, buflen - len,
-				"EAP-TTLS Phase2 method=MSCHAP\n");
+		ret = os_snprintf(buf + len, buflen - len, "MSCHAP\n");
 		break;
 	case EAP_TTLS_PHASE2_PAP:
-		len += snprintf(buf + len, buflen - len,
-				"EAP-TTLS Phase2 method=PAP\n");
+		ret = os_snprintf(buf + len, buflen - len, "PAP\n");
 		break;
 	case EAP_TTLS_PHASE2_CHAP:
-		len += snprintf(buf + len, buflen - len,
-				"EAP-TTLS Phase2 method=CHAP\n");
+		ret = os_snprintf(buf + len, buflen - len, "CHAP\n");
+		break;
+	default:
+		ret = 0;
 		break;
 	}
+	if (ret < 0 || (size_t) ret >= buflen - len)
+		return len;
+	len += ret;
 
 	return len;
 }
@@ -1332,28 +1718,39 @@
 	if (data->key_data == NULL || !data->phase2_success)
 		return NULL;
 
-	key = malloc(EAP_TLS_KEY_LEN);
+	key = os_malloc(EAP_TLS_KEY_LEN);
 	if (key == NULL)
 		return NULL;
 
 	*len = EAP_TLS_KEY_LEN;
-	memcpy(key, data->key_data, EAP_TLS_KEY_LEN);
+	os_memcpy(key, data->key_data, EAP_TLS_KEY_LEN);
 
 	return key;
 }
 
 
-const struct eap_method eap_method_ttls =
+int eap_peer_ttls_register(void)
 {
-	.method = EAP_TYPE_TTLS,
-	.name = "TTLS",
-	.init = eap_ttls_init,
-	.deinit = eap_ttls_deinit,
-	.process = eap_ttls_process,
-	.isKeyAvailable = eap_ttls_isKeyAvailable,
-	.getKey = eap_ttls_getKey,
-	.get_status = eap_ttls_get_status,
-	.has_reauth_data = eap_ttls_has_reauth_data,
-	.deinit_for_reauth = eap_ttls_deinit_for_reauth,
-	.init_for_reauth = eap_ttls_init_for_reauth,
-};
+	struct eap_method *eap;
+	int ret;
+
+	eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
+				    EAP_VENDOR_IETF, EAP_TYPE_TTLS, "TTLS");
+	if (eap == NULL)
+		return -1;
+
+	eap->init = eap_ttls_init;
+	eap->deinit = eap_ttls_deinit;
+	eap->process = eap_ttls_process;
+	eap->isKeyAvailable = eap_ttls_isKeyAvailable;
+	eap->getKey = eap_ttls_getKey;
+	eap->get_status = eap_ttls_get_status;
+	eap->has_reauth_data = eap_ttls_has_reauth_data;
+	eap->deinit_for_reauth = eap_ttls_deinit_for_reauth;
+	eap->init_for_reauth = eap_ttls_init_for_reauth;
+
+	ret = eap_peer_method_register(eap);
+	if (ret)
+		eap_peer_method_free(eap);
+	return ret;
+}
Index: ChangeLog
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/ChangeLog,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/ChangeLog -L contrib/wpa_supplicant/ChangeLog -u -r1.2 -r1.3
--- contrib/wpa_supplicant/ChangeLog
+++ contrib/wpa_supplicant/ChangeLog
@@ -1,32 +1,334 @@
 ChangeLog for wpa_supplicant
 
-2006-02-08 - v0.4.8
+2007-05-28 - v0.5.8
+	* updated driver_wext.c to build with the current wireless-dev.git tree
+	  and net/d80211 changes
+	* updated EAP Generalized Pre-Shared Key (EAP-GPSK) to use the latest
+	  draft (draft-ietf-emu-eap-gpsk-03.txt)
+	* fixed 'make install'
+	* fixed EAP-TTLS implementation not to crash on use of freed memory
+	  if TLS library initialization fails
+	* fixed EAP-AKA Notification processing to allow Notification to be
+	  processed after AKA Challenge response has been sent
+
+2006-12-31 - v0.5.7
+	* updated EAP-SAKE to RFC 4763 and the IANA-allocated EAP type 48
+	* updated EAP-PSK to use the IANA-allocated EAP type 47
+	* fixed EAP-PAX key derivation
+	* fixed EAP-PSK bit ordering of the Flags field
+	* fixed EAP-PEAP/TTLS/FAST to use the correct EAP identifier in
+	  tunnelled identity request (previously, the identifier from the outer
+	  method was used, not the tunnelled identifier which could be
+	  different)
+	* fixed EAP-TTLS AVP parser processing for too short AVP lengths
+	* added support for EAP-FAST authentication with inner methods that
+	  generate MSK (e.g., EAP-MSCHAPv2 that was previously only supported
+	  for PAC provisioning)
+	* fixed dbus ctrl_iface to validate message interface before
+	  dispatching to avoid a possible segfault [Bug 190]
+	* fixed PeerKey key derivation to use the correct PRF label
+	* updated Windows binary build to link against OpenSSL 0.9.8d and
+	  added support for EAP-FAST
+
+2006-11-24 - v0.5.6
+	* added experimental, integrated TLSv1 client implementation with the
+	  needed X.509/ASN.1/RSA/bignum processing (this can be enabled by
+	  setting CONFIG_TLS=internal and CONFIG_INTERNAL_LIBTOMMATH=y in
+	  .config); this can be useful, e.g., if the target system does not
+	  have a suitable TLS library and a minimal code size is required
+	  (total size of this internal TLS/crypto code is bit under 50 kB on
+	  x86 and the crypto code is shared by rest of the supplicant so some
+	  of it was already required; TLSv1/X.509/ASN.1/RSA added about 25 kB)
+	* removed STAKey handshake since PeerKey handshake has replaced it in
+	  IEEE 802.11ma and there are no known deployments of STAKey
+	* updated EAP Generalized Pre-Shared Key (EAP-GPSK) to use the latest
+	  draft (draft-ietf-emu-eap-gpsk-01.txt)
+	* added preliminary implementation of IEEE 802.11w/D1.0 (management
+	  frame protection)
+	  (Note: this requires driver support to work properly.)
+	  (Note2: IEEE 802.11w is an unapproved draft and subject to change.)
+	* fixed Windows named pipes ctrl_iface to not stop listening for
+	  commands if client program opens a named pipe and closes it
+	  immediately without sending a command
+	* fixed USIM PIN status determination for the case that PIN is not
+	  needed (this allows EAP-AKA to be used with USIM cards that do not
+	  use PIN)
+	* added support for reading 3G USIM AID from EF_DIR to allow EAP-AKA to
+	  be used with cards that do not support file selection based on
+	  partial AID
+	* added support for matching the subjectAltName of the authentication
+	  server certificate against multiple name components (e.g.,
+	  altsubject_match="DNS:server.example.com;DNS:server2.example.com")
+	* fixed EAP-SIM/AKA key derivation for re-authentication case (only
+	  affects IEEE 802.1X with dynamic WEP keys)
+	* changed ctrl_iface network configuration 'get' operations to not
+	  return password/key material; if these fields are requested, "*"
+	  will be returned if the password/key is set, but the value of the
+	  parameter is not exposed
+
+2006-08-27 - v0.5.5
+	* added support for building Windows version with UNICODE defined
+	  (wide-char functions)
+	* driver_ndis: fixed static WEP configuration to avoid race condition
+	  issues with some NDIS drivers between association and setting WEP
+	  keys
+	* driver_ndis: added validation for IELength value in scan results to
+	  avoid crashes when using buggy NDIS drivers [Bug 165]
+	* fixed Release|Win32 target in the Visual Studio project files
+	  (previously, only Debug|Win32 target was set properly)
+	* changed control interface API call wpa_ctrl_pending() to allow it to
+	  return -1 on error (e.g., connection lost); control interface clients
+	  will need to make sure that they verify that the value is indeed >0
+	  when determining whether there are pending messages
+	* added an alternative control interface backend for Windows targets:
+	  Named Pipe (CONFIG_CTRL_IFACE=named_pipe); this is now the default
+	  control interface mechanism for Windows builds (previously, UDP to
+	  localhost was used)
+	* changed ctrl_interface configuration for UNIX domain sockets:
+	  - deprecated ctrl_interface_group variable (it may be removed in
+	    future versions)
+	  - allow both directory and group be configured with ctrl_interface
+	    in following format: DIR=/var/run/wpa_supplicant GROUP=wheel
+	  - ctrl_interface=/var/run/wpa_supplicant is still supported for the
+	    case when group is not changed
+	* added support for controlling more than one interface per process in
+	  Windows version
+	* added a workaround for a case where the AP is using unknown address
+	  (e.g., MAC address of the wired interface) as the source address for
+	  EAPOL-Key frames; previously, that source address was used as the
+	  destination for EAPOL-Key frames and in key derivation; now, BSSID is
+	  used even if the source address does not match with it
+	  (this resolves an interoperability issue with Thomson SpeedTouch 580)
+	* added a workaround for UDP-based control interface (which was used in
+	  Windows builds before this release) to prevent packets with forged
+	  addresses from being accepted as local control requests
+	* removed ndis_events.cpp and possibility of using external
+	  ndis_events.exe; C version (ndis_events.c) is fully functional and
+	  there is no desire to maintain two separate versions of this
+	  implementation
+	* ndis_events: Changed NDIS event notification design to use WMI to
+	  learn the adapter description through Win32_PnPEntity class; this
+	  should fix some cases where the adapter name was not recognized
+	  correctly (e.g., with some USB WLAN adapters, e.g., Ralink RT2500
+	  USB) [Bug 113]
+	* fixed selection of the first network in ap_scan=2 mode; previously,
+	  wpa_supplicant could get stuck in SCANNING state when only the first
+	  network for enabled (e.g., after 'wpa_cli select_network 0')
+	* winsvc: added support for configuring ctrl_interface parameters in
+	  registry (ctrl_interface string value in
+	  HKLM\SOFTWARE\wpa_supplicant\interfaces\0000 key); this new value is
+	  required to enable control interface (previously, this was hardcoded
+	  to be enabled)
+	* allow wpa_gui subdirectory to be built with both Qt3 and Qt4
+	* converted wpa_gui-qt4 subdirectory to use Qt4 specific project format
+
+2006-06-20 - v0.5.4
+	* fixed build with CONFIG_STAKEY=y [Bug 143]
+	* added support for doing MLME (IEEE 802.11 management frame
+	  processing) in wpa_supplicant when using Devicescape IEEE 802.11
+	  stack (wireless-dev.git tree)
+	* added a new network block configuration option, fragment_size, to
+	  configure the maximum EAP fragment size
+	* driver_ndis: Disable WZC automatically for the selected interface to
+	  avoid conflicts with two programs trying to control the radio; WZC
+	  will be re-enabled (if it was enabled originally) when wpa_supplicant
+	  is terminated
+	* added an experimental TLSv1 client implementation
+	  (CONFIG_TLS=internal) that can be used instead of an external TLS
+	  library, e.g., to reduce total size requirement on systems that do
+	  not include any TLS library by default (this is not yet complete;
+	  basic functionality is there, but certificate validation is not yet
+	  included)
+	* added PeerKey handshake implementation for IEEE 802.11e
+	  direct link setup (DLS) to replace STAKey handshake
+	* fixed WPA PSK update through ctrl_iface for the case where the old
+	  PSK was derived from an ASCII passphrase and the new PSK is set as
+	  a raw PSK (hex string)
+	* added new configuration option for identifying which network block
+	  was used (id_str in wpa_supplicant.conf; included on
+	  WPA_EVENT_CONNECT monitor event and as WPA_ID_STR environmental
+	  variable in wpa_cli action scripts; in addition WPA_ID variable is
+	  set to the current unique identifier that wpa_supplicant assigned
+	  automatically for the network and that can be used with
+	  GET_NETWORK/SET_NETWORK ctrl_iface commands)
+	* wpa_cli action script is now called only when the connect/disconnect
+	  status changes or when associating with a different network
+	* fixed configuration parser not to remove CCMP from group cipher list
+	  if WPA-None (adhoc) is used (pairwise=NONE in that case)
+	* fixed integrated NDIS events processing not to hang the process due
+	  to a missed change in eloop_win.c API in v0.5.3 [Bug 155]
+	* added support for EAP Generalized Pre-Shared Key (EAP-GPSK,
+	  draft-clancy-emu-eap-shared-secret-00.txt)
+	* added Microsoft Visual Studio 2005 solution and project files for
+	  build wpa_supplicant for Windows (see vs2005 subdirectory)
+	* eloop_win: fixed unregistration of Windows events
+	* l2_packet_winpcap: fixed a deadlock in deinitializing l2_packet
+	  at the end of RSN pre-authentication and added unregistration of
+	  a Windows event to avoid getting eloop_win stuck with an invalid
+	  handle
+	* driver_ndis: added support for selecting AP based on BSSID
+	* added new environmental variable for wpa_cli action scripts:
+	  WPA_CTRL_DIR is the current control interface directory
+	* driver_ndis: added support for using NDISUIO instead of WinPcap for
+	  OID set/query operations (CONFIG_USE_NDISUIO=y in .config); with new
+	  l2_packet_ndis (CONFIG_L2_PACKET=ndis), this can be used to build
+	  wpa_supplicant without requiring WinPcap; note that using NDISUIO
+	  requires that WZC is disabled (net stop wzcsvc) since NDISUIO allows
+	  only one application to open the device
+	* changed NDIS driver naming to only include device GUID, e.g.,
+	  {7EE3EFE5-C165-472F-986D-F6FBEDFE8C8D}, instead of including WinPcap
+	  specific \Device\NPF_ prefix before the GUID; the prefix is still
+	  allowed for backwards compatibility, but it is not required anymore
+	  when specifying the interface
+	* driver_ndis: re-initialize driver interface is the adapter is removed
+	  and re-inserted [Bug 159]
+	* driver_madwifi: fixed TKIP and CCMP sequence number configuration on
+	  big endian hosts [Bug 146]
+
+2006-04-27 - v0.5.3
+	* fixed EAP-GTC response to include correct user identity when run as
+	  phase 2 method of EAP-FAST (i.e., EAP-FAST did not work in v0.5.2)
+	* driver_ndis: Fixed encryption mode configuration for unencrypted
+	  networks (some NDIS drivers ignored this, but others, e.g., Broadcom,
+	  refused to associate with open networks) [Bug 106]
+	* driver_ndis: use BSSID OID polling to detect when IBSS network is
+	  formed even when ndis_events code is included since some NDIS drivers
+	  do not generate media connect events in IBSS mode
+	* config_winreg: allow global ctrl_interface parameter to be configured
+	  in Windows registry
+	* config_winreg: added support for saving configuration data into
+	  Windows registry
+	* added support for controlling network device operational state
+	  (dormant/up) for Linux 2.6.17 to improve DHCP processing (see
+	  http://www.flamewarmaster.de/software/dhcpclient/ for a DHCP client
+	  that can use this information)
+	* driver_wext: added support for WE-21 change to SSID configuration
+	* driver_wext: fixed privacy configuration for static WEP keys mode
+	  [Bug 140]
+	* added an optional driver_ops callback for MLME-SETPROTECTION.request
+	  primitive
+	* added support for EAP-SAKE (no EAP method number allocated yet, so
+	  this is using the same experimental type 255 as EAP-PSK)
+	* added support for dynamically loading EAP methods (.so files) instead
+	  of requiring them to be statically linked in; this is disabled by
+	  default (see CONFIG_DYNAMIC_EAP_METHODS in defconfig for information
+	  on how to use this)
+
+2006-03-19 - v0.5.2
+	* do not try to use USIM APDUs when initializing PC/SC for SIM card
+	  access for a network that has not enabled EAP-AKA
+	* fixed EAP phase 2 Nak for EAP-{PEAP,TTLS,FAST} (this was broken in
+	  v0.5.1 due to the new support for expanded EAP types)
+	* added support for generating EAP Expanded Nak
+	* try to fetch scan results once before requesting new scan when
+	  starting up in ap_scan=1 mode (this can speed up initial association
+	  a lot with, e.g., madwifi-ng driver)
+	* added support for receiving EAPOL frames from a Linux bridge
+	  interface (-bbr0 on command line)
+	* fixed EAPOL re-authentication for sessions that used PMKSA caching
+	* changed EAP method registration to use a dynamic list of methods
+	  instead of a static list generated at build time
+	* fixed PMKSA cache deinitialization not to use freed memory when
+	  removing PMKSA entries
+	* fixed a memory leak in EAP-TTLS re-authentication
+	* reject WPA/WPA2 message 3/4 if it does not include any valid
+	  WPA/RSN IE
+	* driver_wext: added fallback to use SIOCSIWENCODE for setting auth_alg
+	  if the driver does not support SIOCSIWAUTH
+
+2006-01-29 - v0.5.1
+	* driver_test: added better support for multiple APs and STAs by using
+	  a directory with sockets that include MAC address for each device in
+	  the name (driver_param=test_dir=/tmp/test)
+	* added support for EAP expanded type (vendor specific EAP methods)
+	* added AP_SCAN command into ctrl_iface so that ap_scan configuration
+	  option can be changed if needed
+	* wpa_cli/wpa_gui: skip non-socket files in control directory when
+	  using UNIX domain sockets; this avoids selecting an incorrect
+	  interface (e.g., a PID file could be in this directory, even though
+	  use of this directory for something else than socket files is not
+	  recommended)
+	* fixed TLS library deinitialization after RSN pre-authentication not
+	  to disable TLS library for normal authentication
+	* driver_wext: Remove null-termination from SSID length if the driver
+	  used it; some Linux drivers do this and they were causing problems in
+	  wpa_supplicant not finding matching configuration block. This change
+	  would break a case where the SSID actually ends in '\0', but that is
+	  not likely to happen in real use.
+	* fixed PMKSA cache processing not to trigger deauthentication if the
+	  current PMKSA cache entry is replaced with a valid new entry
+	* fixed PC/SC initialization for ap_scan != 1 modes (this fixes
+	  EAP-SIM and EAP-AKA with real SIM/USIM card when using ap_scan=0 or
+	  ap_scan=2)
+
+2005-12-18 - v0.5.0 (beginning of 0.5.x development releases)
+	* added experimental STAKey handshake implementation for IEEE 802.11e
+	  direct link setup (DLS); note: this is disabled by default in both
+	  build and runtime configuration (can be enabled with CONFIG_STAKEY=y
+	  and stakey=1)
+	* fixed EAP-SIM and EAP-AKA pseudonym and fast re-authentication to
+	  decrypt AT_ENCR_DATA attributes correctly
+	* fixed EAP-AKA to allow resynchronization within the same session
+	* made code closer to ANSI C89 standard to make it easier to port to
+	  other C libraries and compilers
+	* started moving operating system or C library specific functions into
+	  wrapper functions defined in os.h and implemented in os_*.c to make
+	  code more portable
+	* wpa_supplicant can now be built with Microsoft Visual C++
+	  (e.g., with the freely available Toolkit 2003 version or Visual
+	  C++ 2005 Express Edition and Platform SDK); see nmake.mak for an
+	  example makefile for nmake
+	* added support for using Windows registry for command line parameters
+	  (CONFIG_MAIN=main_winsvc) and configuration data
+	  (CONFIG_BACKEND=winreg); see win_example.reg for an example registry
+	  contents; this version can be run both as a Windows service and as a
+	  normal application; 'wpasvc.exe app' to start as applicant,
+	  'wpasvc.exe reg <full path to wpasvc.exe>' to register a service,
+	  'net start wpasvc' to start the service, 'wpasvc.exe unreg' to
+	  unregister a service
+	* made it possible to link ndis_events.exe functionality into
+	  wpa_supplicant.exe by defining CONFIG_NDIS_EVENTS_INTEGRATED
+	* added better support for multiple control interface backends
+	  (CONFIG_CTRL_IFACE option); currently, 'unix' and 'udp' are supported
 	* fixed PC/SC code to use correct length for GSM AUTH command buffer
 	  and to not use pioRecvPci with SCardTransmit() calls; these were not
 	  causing visible problems with pcsc-lite, but Windows Winscard.dll
 	  refused the previously used parameters; this fixes EAP-SIM and
 	  EAP-AKA authentication using SIM/USIM card under Windows
+	* added new event loop implementation for Windows using
+	  WaitForMultipleObject() instead of select() in order to allow waiting
+	  for non-socket objects; this can be selected with
+	  CONFIG_ELOOP=eloop_win in .config
+	* added support for selecting l2_packet implementation in .config
+	  (CONFIG_L2_PACKET; following options are available now: linux, pcap,
+	  winpcap, freebsd, none)
+	* added new l2_packet implementation for WinPcap
+	  (CONFIG_L2_PACKET=winpcap) that uses a separate receive thread to
+	  reduce latency in EAPOL receive processing from about 100 ms to about
+	  3 ms
 	* added support for EAP-FAST key derivation using other ciphers than
 	  RC4-128-SHA for authentication and AES128-SHA for provisioning
-	* fixed EAP-SIM and EAP-AKA pseudonym and fast re-authentication to
-	  decrypt AT_ENCR_DATA attributes correctly
 	* added support for configuring CA certificate as DER file and as a
 	  configuration blob
 	* fixed private key configuration as configuration blob and added
 	  support for using PKCS#12 as a blob
-	* fixed cygwin build
+	* tls_gnutls: added support for using PKCS#12 files; added support for
+	  session resumption
 	* added support for loading trusted CA certificates from Windows
 	  certificate store: ca_cert="cert_store://<name>", where <name> is
 	  likely CA (Intermediate CA certificates) or ROOT (root certificates)
-	* fixed TLS library deinitialization after RSN pre-authentication not
-	  to disable TLS library for normal authentication
-	* fixed PMKSA cache processing not to trigger deauthentication if the
-	  current PMKSA cache entry is replaced with a valid new entry
-	* fixed PC/SC initialization for ap_scan != 1 modes (this fixes
-	  EAP-SIM and EAP-AKA with real SIM/USIM card when using ap_scan=0 or
-	  ap_scan=2)
-	* do not try to use USIM APDUs when initializing PC/SC for SIM card
-	  access for a network that has not enabled EAP-AKA
+	* added C version of ndis_events.cpp and made it possible to build this
+	  with MinGW so that CONFIG_NDIS_EVENTS_INTEGRATED can be used more
+	  easily on cross-compilation builds
+	* added wpasvc.exe into Windows binary release; this is an alternative
+	  version of wpa_supplicant.exe with configuration backend using
+	  Windows registry and with the entry point designed to run as a
+	  Windows service
+	* integrated ndis_events.exe functionality into wpa_supplicant.exe and
+	  wpasvc.exe and removed this additional tool from the Windows binary
+	  release since it is not needed anymore
+	* load winscard.dll functions dynamically when building with MinGW
+	  since MinGW does not yet include winscard library
 
 2005-11-20 - v0.4.7 (beginning of 0.4.x stable releases)
 	* l2_packet_pcap: fixed wired IEEE 802.1X authentication with libpcap
Index: todo.txt
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/todo.txt,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/todo.txt -L contrib/wpa_supplicant/todo.txt -u -r1.2 -r1.3
--- contrib/wpa_supplicant/todo.txt
+++ contrib/wpa_supplicant/todo.txt
@@ -19,33 +19,23 @@
 - EAP-SIM/AKA: AT_RESULT_IND
 - on disconnect event, could try to associate with another AP if one is
   present in scan results; would need to update scan results periodically..
-- add flag scan_requested and only try to re-associate if this is set when
-  new scan results are received; this would allow background scans without
-  triggering re-assoc..
 - if driver/hw is not WPA2 capable, must remove WPA_PROTO_RSN flag from
   ssid->proto fields to avoid detecting downgrade attacks when the driver
   is not reporting RSN IE, but msg 3/4 has one
-- EAP-SIM/AKA: if SIM reader initialization fails, do not start authentication
 - Cisco AP and non-zero keyidx for unicast -> map to broadcast
   (actually, this already works with driver_ndis; so maybe just change
   driver_*.c to do the mapping for drivers that cannot handle non-zero keyidx
   for unicast); worked also with Host AP driver and madwifi
 - IEEE 802.1X and key update with driver_ndis?? wpa_supplicant did not seem
   to see unencrypted EAPOL-Key frames at all..
-- -Dwired: if ssid is set in network block, authentication gets "stuck" since
-  driver_wired.c only reports empty SSID and association is not assumed to be
-  ok
 - EAP-PAX with PAX_SEC
-- EAP: extended nak, vendor method; go through rfc
-  RFC 3748
-  * Expanded Type (Sect. 5.7)
-  * Experimental Type
-  * Expanded Nak (Sect. 5.3.2)
+- EAP (RFC 3748)
   * OTP Extended Responses (Sect. 5.5)
 - test what happens if authenticator sends EAP-Success before real EAP
   authentication ("canned" Success); this should be ignored based on
   RFC 3748 Sect. 4.2
 - test compilation with gcc -W options (more warnings?)
+  (Done once; number of unused function arguments still present)
 - add proper support for using dot11RSNAConfigSATimeout
 - ctrl_iface: get/set/remove blob
 - use doc/docbook/*.sgml and docbook2{txt,html,pdf} to replace README and
@@ -53,3 +43,82 @@
   in one page; how to build a PDF file with all the SGML included?
 - test wait-for-interface and daemonize combinations with number of driver
   interfaces
+  * 'test' worked with WPA-PSK
+- EAP-POTP/RSA SecurID profile (draft-nystrom-eap-potp-03.txt)
+- document wpa_gui build and consider adding it to 'make install'
+- test madwifi with pairwise=TKIP group=WEP104
+- possibility to link in WPA Authenticator state machine to wpa_supplicant
+  (new STAKey handshake, WPA2 IBSS)
+- consider merging hostapd and wpa_supplicant PMKSA cache implementations
+- add support for configuring password for MSCHAPv2 as NtPasswordHash in
+  the same way as was added to hostapd (hash:<hex value>)
+- test_driver: configure directory and create AP-<mac> and STA-<mac> files
+  there to allow scanning multiple APs (e.g., for testing pre-auth and PMKSA
+  caching testing) and to exchange STA-STA EAPOL frames
+- consider adding generic buffer functionality that could be used in number
+  of places
+  * allocate buffer (with default max size), allow reserving head room to
+    make it possible to add a header without having to reallocate buffer
+  * reallocate buffer (add head and/or tail room)
+  * ref count and free when count=0 ?
+  * add data (to tail): re-alloc more tailroom if needed and copy new data
+  * error flag so that caller can do multiple add()s and only in the end
+    check whether something has failed; this should make error handling
+    simpler
+- consider redesigning pending EAP requests (identity/password/otp from
+  ctrl_iface) by moving the retrying of the previous request into EAP
+  state machine so that EAPOL state machine is not needed for this
+- rfc4284.txt (network selection for eap)
+- www pages about configuring wpa_supplicant:
+  * global options (ap_scan, ctrl_interfaces) based on OS/driver
+  * network block
+  * key_mgmt selection
+  * WPA parameters
+  * EAP options (one page for each method)
+  * "configuration wizard" (step 1: select OS, step 2: select driver, ...) to
+    generate example configuration
+- error path in rsn_preauth_init: should probably deinit l2_packet handlers
+  if something fails; does something else need deinit?
+- consider moving SIM card functionality (IMSI fetching) away from eap.c;
+  this should likely happen before EAP is initialized for authentication;
+  now IMSI is read only after receiving EAP-Identity/Request, but since it is
+  really needed for all cases, reading IMSI and generating Identity string
+  could very well be done before EAP has been started
+- test all allowed EAP Phase 2 methods (i.e., anything else than PEAP, TTLS,
+  FAST): SIM AKA PAX PSK LEAP; if these work, include in eap_testing.txt; if
+  not, either fix or make eap_allowed_phase2_type reject
+- try to work around race in receiving association event and first EAPOL
+  message
+- helper function to do memcmp(addr, "\x00\x00\x00\x00\x00\x00", ETH_ALEN)
+- add wpa_secure_memzero() macro and secure implementation (volatile u8*) to
+  clear memory; this would be used to clear temporary buffers containing
+  private data (e.g., keys); the macro can be defined to NOP in order to save
+  space (i.e., no code should depend on the macro doing something)
+- make sure that TLS session cache is not shared between EAP types or if it
+  is, that the cache entries are bound to only one EAP type; e.g., cache entry
+  created with EAP-TLS must not be allowed to do fast re-auth with EAP-TTLS
+- consider moving eap_tls_build_ack() call into eap_tls_process_helper()
+  (it seems to be called always if helper returns 1)
+  * could need to modify eap_{ttls,peap,fast}_decrypt to do same
+- add support for fetching full user cert chain from Windows certificate
+  stores even when there are intermediate CA certs that are not in the
+  configured ca_cert store (e.g., ROOT) (they could be, e.g., in CA store)
+
+
+0.6.x branch:
+- clean up common.[ch]
+- change TLS/crypto library interface to use a structure of function
+  pointers and helper inline functions (like driver_ops) instead of
+  requiring every TLS wrapper to implement all functions
+- move from CVS to git (0.3.x, 0.4.x, 0.5.x releases will continue
+  to be updated only on CVS)
+- move files into subdirectories and combine wpa_supplicant and hostapd
+  into a repository that matches in directory structure with the release
+  tarballs
+  (subdirs: eap_common, eap_peer, eap_server, driver, driver_ap, ...)
+- make it clearer that EAP server/peer can be used as a separate library
+  for other programs
+- add support for encrypted configuration fields (e.g., password, psk,
+  passphrase, pin)
+- wpa_gui: add support for setting and showing priority, id_str, auth_alg
+  (open/shared for static WEP)
Index: base64.h
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/base64.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -L contrib/wpa_supplicant/base64.h -L contrib/wpa_supplicant/base64.h -u -r1.1 -r1.2
--- contrib/wpa_supplicant/base64.h
+++ contrib/wpa_supplicant/base64.h
@@ -1,6 +1,6 @@
 /*
  * Base64 encoding/decoding (RFC1341)
- * Copyright (c) 2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2005, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
Index: eap_sim_common.h
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/eap_sim_common.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/eap_sim_common.h -L contrib/wpa_supplicant/eap_sim_common.h -u -r1.2 -r1.3
--- contrib/wpa_supplicant/eap_sim_common.h
+++ contrib/wpa_supplicant/eap_sim_common.h
@@ -1,6 +1,6 @@
 /*
- * WPA Supplicant / EAP-SIM/AKA shared routines
- * Copyright (c) 2004-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * EAP peer: EAP-SIM/AKA shared routines
+ * Copyright (c) 2004-2006, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -23,16 +23,65 @@
 #define EAP_SIM_K_ENCR_LEN 16
 #define EAP_SIM_KEYING_DATA_LEN 64
 #define EAP_SIM_IV_LEN 16
+#define EAP_SIM_KC_LEN 8
+#define EAP_SIM_SRES_LEN 4
 
 #define GSM_RAND_LEN 16
 
-#define AKA_RAND_LEN 16
-#define AKA_AUTN_LEN 16
+#define EAP_SIM_VERSION 1
 
-void eap_sim_derive_keys(const u8 *mk, u8 *k_encr, u8 *k_aut, u8 *msk);
-void eap_sim_derive_keys_reauth(u16 _counter,
-				const u8 *identity, size_t identity_len,
-				const u8 *nonce_s, const u8 *mk, u8 *msk);
+/* EAP-SIM Subtypes */
+#define EAP_SIM_SUBTYPE_START 10
+#define EAP_SIM_SUBTYPE_CHALLENGE 11
+#define EAP_SIM_SUBTYPE_NOTIFICATION 12
+#define EAP_SIM_SUBTYPE_REAUTHENTICATION 13
+#define EAP_SIM_SUBTYPE_CLIENT_ERROR 14
+
+/* AT_CLIENT_ERROR_CODE error codes */
+#define EAP_SIM_UNABLE_TO_PROCESS_PACKET 0
+#define EAP_SIM_UNSUPPORTED_VERSION 1
+#define EAP_SIM_INSUFFICIENT_NUM_OF_CHAL 2
+#define EAP_SIM_RAND_NOT_FRESH 3
+
+#define EAP_SIM_MAX_FAST_REAUTHS 1000
+
+#define EAP_SIM_MAX_CHAL 3
+
+
+/* EAP-AKA Subtypes */
+#define EAP_AKA_SUBTYPE_CHALLENGE 1
+#define EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT 2
+#define EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE 4
+#define EAP_AKA_SUBTYPE_IDENTITY 5
+#define EAP_AKA_SUBTYPE_NOTIFICATION 12
+#define EAP_AKA_SUBTYPE_REAUTHENTICATION 13
+#define EAP_AKA_SUBTYPE_CLIENT_ERROR 14
+
+/* AT_CLIENT_ERROR_CODE error codes */
+#define EAP_AKA_UNABLE_TO_PROCESS_PACKET 0
+
+#define EAP_AKA_RAND_LEN 16
+#define EAP_AKA_AUTN_LEN 16
+#define EAP_AKA_AUTS_LEN 14
+#define EAP_AKA_RES_MAX_LEN 16
+#define EAP_AKA_IK_LEN 16
+#define EAP_AKA_CK_LEN 16
+#define EAP_AKA_MAX_FAST_REAUTHS 1000
+#define EAP_AKA_MIN_RES_LEN 4
+#define EAP_AKA_MAX_RES_LEN 16
+
+void eap_sim_derive_mk(const u8 *identity, size_t identity_len,
+		       const u8 *nonce_mt, u16 selected_version,
+		       const u8 *ver_list, size_t ver_list_len,
+		       int num_chal, const u8 *kc, u8 *mk);
+void eap_aka_derive_mk(const u8 *identity, size_t identity_len,
+		       const u8 *ik, const u8 *ck, u8 *mk);
+int eap_sim_derive_keys(const u8 *mk, u8 *k_encr, u8 *k_aut, u8 *msk,
+			u8 *emsk);
+int eap_sim_derive_keys_reauth(u16 _counter,
+			       const u8 *identity, size_t identity_len,
+			       const u8 *nonce_s, const u8 *mk, u8 *msk,
+			       u8 *emsk);
 int eap_sim_verify_mac(const u8 *k_aut, const u8 *req, size_t req_len,
 		       const u8 *mac, const u8 *extra, size_t extra_len);
 void eap_sim_add_mac(const u8 *k_aut, u8 *msg, size_t msg_len, u8 *mac,
@@ -42,8 +91,8 @@
 /* EAP-SIM/AKA Attributes (0..127 non-skippable) */
 #define EAP_SIM_AT_RAND 1
 #define EAP_SIM_AT_AUTN 2 /* only AKA */
-#define EAP_SIM_AT_RES 3 /* only AKA, only send */
-#define EAP_SIM_AT_AUTS 4 /* only AKA, only send */
+#define EAP_SIM_AT_RES 3 /* only AKA, only peer->server */
+#define EAP_SIM_AT_AUTS 4 /* only AKA, only peer->server */
 #define EAP_SIM_AT_PADDING 6 /* only encrypted */
 #define EAP_SIM_AT_NONCE_MT 7 /* only SIM, only send */
 #define EAP_SIM_AT_PERMANENT_ID_REQ 10
@@ -81,11 +130,12 @@
 struct eap_sim_attrs {
 	const u8 *rand, *autn, *mac, *iv, *encr_data, *version_list, *nonce_s;
 	const u8 *next_pseudonym, *next_reauth_id;
-	const u8 *nonce_mt, *identity;
+	const u8 *nonce_mt, *identity, *res, *auts;
 	size_t num_chal, version_list_len, encr_data_len;
-	size_t next_pseudonym_len, next_reauth_id_len, identity_len;
+	size_t next_pseudonym_len, next_reauth_id_len, identity_len, res_len;
 	enum eap_sim_id_req id_req;
 	int notification, counter, selected_version, client_error_code;
+	int counter_too_small;
 };
 
 int eap_sim_parse_attr(const u8 *start, const u8 *end,
Index: sha1.h
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/sha1.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/sha1.h -L contrib/wpa_supplicant/sha1.h -u -r1.2 -r1.3
--- contrib/wpa_supplicant/sha1.h
+++ contrib/wpa_supplicant/sha1.h
@@ -1,6 +1,6 @@
 /*
  * SHA1 hash implementation and interface functions
- * Copyright (c) 2003-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2003-2005, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -30,4 +30,12 @@
 void pbkdf2_sha1(const char *passphrase, const char *ssid, size_t ssid_len,
 		 int iterations, u8 *buf, size_t buflen);
 
+#ifdef CONFIG_CRYPTO_INTERNAL
+struct SHA1Context;
+
+void SHA1Init(struct SHA1Context *context);
+void SHA1Update(struct SHA1Context *context, const void *data, u32 len);
+void SHA1Final(unsigned char digest[20], struct SHA1Context *context);
+#endif /* CONFIG_CRYPTO_INTERNAL */
+
 #endif /* SHA1_H */
Index: wpa_supplicant.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/wpa_supplicant.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/wpa_supplicant.c -L contrib/wpa_supplicant/wpa_supplicant.c -u -r1.2 -r1.3
--- contrib/wpa_supplicant/wpa_supplicant.c
+++ contrib/wpa_supplicant/wpa_supplicant.c
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant
- * Copyright (c) 2003-2006, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2003-2007, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -11,19 +11,14 @@
  *
  * See README and COPYING for more details.
  *
- * $FreeBSD: src/contrib/wpa_supplicant/wpa_supplicant.c,v 1.1.1.3.2.2 2006/03/24 01:41:07 sam Exp $
+ * This file implements functions for registering and unregistering
+ * %wpa_supplicant interfaces. In addition, this file contains number of
+ * functions for managing network connections.
+ *
+ * $FreeBSD: src/contrib/wpa_supplicant/wpa_supplicant.c,v 1.4 2007/07/11 15:58:51 sam Exp $
  */
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <unistd.h>
-#include <string.h>
-#include <time.h>
-#include <signal.h>
-#ifndef CONFIG_NATIVE_WINDOWS
-#include <netinet/in.h>
-#endif /* CONFIG_NATIVE_WINDOWS */
+#include "includes.h"
 
 #include "common.h"
 #include "eapol_sm.h"
@@ -35,14 +30,17 @@
 #include "l2_packet.h"
 #include "wpa_supplicant_i.h"
 #include "ctrl_iface.h"
+#include "ctrl_iface_dbus.h"
 #include "pcsc_funcs.h"
 #include "version.h"
 #include "preauth.h"
+#include "pmksa_cache.h"
 #include "wpa_ctrl.h"
+#include "mlme.h"
 
 const char *wpa_supplicant_version =
 "wpa_supplicant v" VERSION_STR "\n"
-"Copyright (c) 2003-2006, Jouni Malinen <jkmaline at cc.hut.fi> and contributors";
+"Copyright (c) 2003-2007, Jouni Malinen <j at w1.fi> and contributors";
 
 const char *wpa_supplicant_license =
 "This program is free software. You can distribute it and/or modify it\n"
@@ -50,14 +48,15 @@
 "\n"
 "Alternatively, this software may be distributed under the terms of the\n"
 "BSD license. See README and COPYING for more details.\n"
-#ifdef EAP_TLS_FUNCS
+#ifdef EAP_TLS_OPENSSL
 "\nThis product includes software developed by the OpenSSL Project\n"
 "for use in the OpenSSL Toolkit (http://www.openssl.org/)\n"
-#endif /* EAP_TLS_FUNCS */
+#endif /* EAP_TLS_OPENSSL */
 ;
 
 #ifndef CONFIG_NO_STDOUT_DEBUG
-const char *wpa_supplicant_full_license =
+/* Long text divided into parts in order to fit in C89 strings size limits. */
+const char *wpa_supplicant_full_license1 =
 "This program is free software; you can redistribute it and/or modify\n"
 "it under the terms of the GNU General Public License version 2 as\n"
 "published by the Free Software Foundation.\n"
@@ -66,10 +65,11 @@
 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
 "GNU General Public License for more details.\n"
-"\n"
+"\n";
+const char *wpa_supplicant_full_license2 =
 "You should have received a copy of the GNU General Public License\n"
 "along with this program; if not, write to the Free Software\n"
-"Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n"
+"Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n"
 "\n"
 "Alternatively, this software may be distributed under the terms of the\n"
 "BSD license.\n"
@@ -77,14 +77,16 @@
 "Redistribution and use in source and binary forms, with or without\n"
 "modification, are permitted provided that the following conditions are\n"
 "met:\n"
-"\n"
+"\n";
+const char *wpa_supplicant_full_license3 =
 "1. Redistributions of source code must retain the above copyright\n"
 "   notice, this list of conditions and the following disclaimer.\n"
 "\n"
 "2. Redistributions in binary form must reproduce the above copyright\n"
 "   notice, this list of conditions and the following disclaimer in the\n"
 "   documentation and/or other materials provided with the distribution.\n"
-"\n"
+"\n";
+const char *wpa_supplicant_full_license4 =
 "3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
 "   names of its contributors may be used to endorse or promote products\n"
 "   derived from this software without specific prior written permission.\n"
@@ -92,7 +94,8 @@
 "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
 "\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
 "LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
-"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
+"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n";
+const char *wpa_supplicant_full_license5 =
 "OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
 "SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
 "LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
@@ -105,37 +108,14 @@
 
 extern struct wpa_driver_ops *wpa_supplicant_drivers[];
 
+extern int wpa_debug_use_file;
 extern int wpa_debug_level;
 extern int wpa_debug_show_keys;
 extern int wpa_debug_timestamp;
 
 static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx);
 
-void wpa_msg(struct wpa_supplicant *wpa_s, int level, char *fmt, ...)
-{
-	va_list ap;
-	char *buf;
-	const int buflen = 2048;
-	int len;
-
-	buf = malloc(buflen);
-	if (buf == NULL) {
-		printf("Failed to allocate message buffer for:\n");
-		va_start(ap, fmt);
-		vprintf(fmt, ap);
-		printf("\n");
-		va_end(ap);
-		return;
-	}
-	va_start(ap, fmt);
-	len = vsnprintf(buf, buflen, fmt, ap);
-	va_end(ap);
-	wpa_printf(level, "%s", buf);
-	wpa_supplicant_ctrl_iface_send(wpa_s, level, buf, len);
-	free(buf);
-}
-
-
+#if defined(IEEE8021X_EAPOL) || !defined(CONFIG_NO_WPA)
 static u8 * wpa_alloc_eapol(const struct wpa_supplicant *wpa_s, u8 type,
 			    const void *data, u16 data_len,
 			    size_t *msg_len, void **data_pos)
@@ -143,18 +123,18 @@
 	struct ieee802_1x_hdr *hdr;
 
 	*msg_len = sizeof(*hdr) + data_len;
-	hdr = malloc(*msg_len);
+	hdr = os_malloc(*msg_len);
 	if (hdr == NULL)
 		return NULL;
 
 	hdr->version = wpa_s->conf->eapol_version;
 	hdr->type = type;
-	hdr->length = htons(data_len);
+	hdr->length = host_to_be16(data_len);
 
 	if (data)
-		memcpy(hdr + 1, data, data_len);
+		os_memcpy(hdr + 1, data, data_len);
 	else
-		memset(hdr + 1, 0, data_len);
+		os_memset(hdr + 1, 0, data_len);
 
 	if (data_pos)
 		*data_pos = hdr + 1;
@@ -165,14 +145,15 @@
 
 /**
  * wpa_ether_send - Send Ethernet frame
- * @wpa_s: pointer to wpa_supplicant data
+ * @wpa_s: Pointer to wpa_supplicant data
  * @dest: Destination MAC address
- * @proto: Ethertype
+ * @proto: Ethertype in host byte order
  * @buf: Frame payload starting from IEEE 802.1X header
  * @len: Frame payload length
+ * Returns: >=0 on success, <0 on failure
  */
-int wpa_ether_send(struct wpa_supplicant *wpa_s, const u8 *dest, u16 proto,
-		   const u8 *buf, size_t len)
+static int wpa_ether_send(struct wpa_supplicant *wpa_s, const u8 *dest,
+			  u16 proto, const u8 *buf, size_t len)
 {
 	if (wpa_s->l2) {
 		return l2_packet_send(wpa_s->l2, dest, proto, buf, len);
@@ -180,15 +161,17 @@
 
 	return wpa_drv_send_eapol(wpa_s, dest, proto, buf, len);
 }
+#endif /* IEEE8021X_EAPOL || !CONFIG_NO_WPA */
 
 
 #ifdef IEEE8021X_EAPOL
 /**
  * wpa_supplicant_eapol_send - Send IEEE 802.1X EAPOL packet to Authenticator
- * @ctx: pointer to wpa_supplicant data
+ * @ctx: Pointer to wpa_supplicant data (wpa_s)
  * @type: IEEE 802.1X packet type (IEEE802_1X_TYPE_*)
  * @buf: EAPOL payload (after IEEE 802.1X header)
  * @len: EAPOL payload length
+ * Returns: >=0 on success, <0 on failure
  *
  * This function adds Ethernet and IEEE 802.1X header and sends the EAPOL frame
  * to the current Authenticator.
@@ -224,11 +207,13 @@
 		return -1;
 	}
 
-	if (memcmp(wpa_s->bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) == 0) {
+	if (os_memcmp(wpa_s->bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) == 0)
+	{
 		wpa_printf(MSG_DEBUG, "BSSID not set when trying to send an "
 			   "EAPOL frame");
 		if (wpa_drv_get_bssid(wpa_s, bssid) == 0 &&
-		    memcmp(bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) != 0) {
+		    os_memcmp(bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) !=
+		    0) {
 			dst = bssid;
 			wpa_printf(MSG_DEBUG, "Using current BSSID " MACSTR
 				   " from the driver as the EAPOL destination",
@@ -252,30 +237,45 @@
 
 	wpa_hexdump(MSG_MSGDUMP, "TX EAPOL", msg, msglen);
 	res = wpa_ether_send(wpa_s, dst, ETH_P_EAPOL, msg, msglen);
-	free(msg);
+	os_free(msg);
 	return res;
 }
 
 
 /**
  * wpa_eapol_set_wep_key - set WEP key for the driver
- * @ctx: pointer to wpa_supplicant data
+ * @ctx: Pointer to wpa_supplicant data (wpa_s)
  * @unicast: 1 = individual unicast key, 0 = broadcast key
  * @keyidx: WEP key index (0..3)
- * @key: pointer to key data
- * @keylen: key length in bytes
- *
- * Returns 0 on success or < 0 on error.
+ * @key: Pointer to key data
+ * @keylen: Key length in bytes
+ * Returns: 0 on success or < 0 on error.
  */
 static int wpa_eapol_set_wep_key(void *ctx, int unicast, int keyidx,
 				 const u8 *key, size_t keylen)
 {
 	struct wpa_supplicant *wpa_s = ctx;
+	if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
+		int cipher = (keylen == 5) ? WPA_CIPHER_WEP40 :
+			WPA_CIPHER_WEP104;
+		if (unicast)
+			wpa_s->pairwise_cipher = cipher;
+		else
+			wpa_s->group_cipher = cipher;
+	}
 	return wpa_drv_set_key(wpa_s, WPA_ALG_WEP,
 			       unicast ? wpa_s->bssid :
 			       (u8 *) "\xff\xff\xff\xff\xff\xff",
 			       keyidx, unicast, (u8 *) "", 0, key, keylen);
 }
+
+
+static void wpa_supplicant_aborted_cached(void *ctx)
+{
+	struct wpa_supplicant *wpa_s = ctx;
+	wpa_sm_aborted_cached(wpa_s->wpa);
+}
+
 #endif /* IEEE8021X_EAPOL */
 
 
@@ -332,14 +332,14 @@
 
 	switch (wpa_s->group_cipher) {
 	case WPA_CIPHER_CCMP:
-		memcpy(key, ssid->psk, 16);
+		os_memcpy(key, ssid->psk, 16);
 		keylen = 16;
 		alg = WPA_ALG_CCMP;
 		break;
 	case WPA_CIPHER_TKIP:
 		/* WPA-None uses the same Michael MIC key for both TX and RX */
-		memcpy(key, ssid->psk, 16 + 8);
-		memcpy(key + 16 + 8, ssid->psk + 16, 8);
+		os_memcpy(key, ssid->psk, 16 + 8);
+		os_memcpy(key + 16 + 8, ssid->psk + 16, 8);
 		keylen = 32;
 		alg = WPA_ALG_TKIP;
 		break;
@@ -373,6 +373,12 @@
 #endif /* IEEE8021X_EAPOL */
 
 
+/**
+ * wpa_blacklist_get - Get the blacklist entry for a BSSID
+ * @wpa_s: Pointer to wpa_supplicant data
+ * @bssid: BSSID
+ * Returns: Matching blacklist entry for the BSSID or %NULL if not found
+ */
 struct wpa_blacklist * wpa_blacklist_get(struct wpa_supplicant *wpa_s,
 					 const u8 *bssid)
 {
@@ -380,7 +386,7 @@
 
 	e = wpa_s->blacklist;
 	while (e) {
-		if (memcmp(e->bssid, bssid, ETH_ALEN) == 0)
+		if (os_memcmp(e->bssid, bssid, ETH_ALEN) == 0)
 			return e;
 		e = e->next;
 	}
@@ -389,6 +395,22 @@
 }
 
 
+/**
+ * wpa_blacklist_add - Add an BSSID to the blacklist
+ * @wpa_s: Pointer to wpa_supplicant data
+ * @bssid: BSSID to be added to the blacklist
+ * Returns: 0 on success, -1 on failure
+ *
+ * This function adds the specified BSSID to the blacklist or increases the
+ * blacklist count if the BSSID was already listed. It should be called when
+ * an association attempt fails either due to the selected BSS rejecting
+ * association or due to timeout.
+ *
+ * This blacklist is used to force %wpa_supplicant to go through all available
+ * BSSes before retrying to associate with an BSS that rejected or timed out
+ * association. It does not prevent the listed BSS from being used; it only
+ * changes the order in which they are tried.
+ */
 int wpa_blacklist_add(struct wpa_supplicant *wpa_s, const u8 *bssid)
 {
 	struct wpa_blacklist *e;
@@ -402,11 +424,10 @@
 		return 0;
 	}
 
-	e = malloc(sizeof(*e));
+	e = os_zalloc(sizeof(*e));
 	if (e == NULL)
 		return -1;
-	memset(e, 0, sizeof(*e));
-	memcpy(e->bssid, bssid, ETH_ALEN);
+	os_memcpy(e->bssid, bssid, ETH_ALEN);
 	e->count = 1;
 	e->next = wpa_s->blacklist;
 	wpa_s->blacklist = e;
@@ -417,13 +438,13 @@
 }
 
 
-int wpa_blacklist_del(struct wpa_supplicant *wpa_s, const u8 *bssid)
+static int wpa_blacklist_del(struct wpa_supplicant *wpa_s, const u8 *bssid)
 {
 	struct wpa_blacklist *e, *prev = NULL;
 
 	e = wpa_s->blacklist;
 	while (e) {
-		if (memcmp(e->bssid, bssid, ETH_ALEN) == 0) {
+		if (os_memcmp(e->bssid, bssid, ETH_ALEN) == 0) {
 			if (prev == NULL) {
 				wpa_s->blacklist = e->next;
 			} else {
@@ -431,7 +452,7 @@
 			}
 			wpa_printf(MSG_DEBUG, "Removed BSSID " MACSTR " from "
 				   "blacklist", MAC2STR(bssid));
-			free(e);
+			os_free(e);
 			return 0;
 		}
 		prev = e;
@@ -441,6 +462,10 @@
 }
 
 
+/**
+ * wpa_blacklist_clear - Clear the blacklist of all entries
+ * @wpa_s: Pointer to wpa_supplicant data
+ */
 void wpa_blacklist_clear(struct wpa_supplicant *wpa_s)
 {
 	struct wpa_blacklist *e, *prev;
@@ -452,28 +477,20 @@
 		e = e->next;
 		wpa_printf(MSG_DEBUG, "Removed BSSID " MACSTR " from "
 			   "blacklist (clear)", MAC2STR(prev->bssid));
-		free(prev);
+		os_free(prev);
 	}
 }
 
 
-const char * wpa_ssid_txt(u8 *ssid, size_t ssid_len)
-{
-	static char ssid_txt[MAX_SSID_LEN + 1];
-	char *pos;
-
-	if (ssid_len > MAX_SSID_LEN)
-		ssid_len = MAX_SSID_LEN;
-	memcpy(ssid_txt, ssid, ssid_len);
-	ssid_txt[ssid_len] = '\0';
-	for (pos = ssid_txt; *pos != '\0'; pos++) {
-		if ((u8) *pos < 32 || (u8) *pos >= 127)
-			*pos = '_';
-	}
-	return ssid_txt;
-}
-
-
+/**
+ * wpa_supplicant_req_scan - Schedule a scan for neighboring access points
+ * @wpa_s: Pointer to wpa_supplicant data
+ * @sec: Number of seconds after which to scan
+ * @usec: Number of microseconds after which to scan
+ *
+ * This function is used to schedule a scan for neighboring access points after
+ * the specified time.
+ */
 void wpa_supplicant_req_scan(struct wpa_supplicant *wpa_s, int sec, int usec)
 {
 	wpa_msg(wpa_s, MSG_DEBUG, "Setting scan request: %d sec %d usec",
@@ -483,6 +500,13 @@
 }
 
 
+/**
+ * wpa_supplicant_cancel_scan - Cancel a scheduled scan request
+ * @wpa_s: Pointer to wpa_supplicant data
+ *
+ * This function is used to cancel a scan request scheduled with
+ * wpa_supplicant_req_scan().
+ */
 void wpa_supplicant_cancel_scan(struct wpa_supplicant *wpa_s)
 {
 	wpa_msg(wpa_s, MSG_DEBUG, "Cancelling scan request");
@@ -493,9 +517,12 @@
 static void wpa_supplicant_timeout(void *eloop_ctx, void *timeout_ctx)
 {
 	struct wpa_supplicant *wpa_s = eloop_ctx;
+	const u8 *bssid = wpa_s->bssid;
+	if (os_memcmp(bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) == 0)
+		bssid = wpa_s->pending_bssid;
 	wpa_msg(wpa_s, MSG_INFO, "Authentication with " MACSTR " timed out.",
 		MAC2STR(wpa_s->bssid));
-	wpa_blacklist_add(wpa_s, wpa_s->bssid);
+	wpa_blacklist_add(wpa_s, bssid);
 	wpa_sm_notify_disassoc(wpa_s->wpa);
 	wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING);
 	wpa_s->reassociate = 1;
@@ -503,11 +530,20 @@
 }
 
 
+/**
+ * wpa_supplicant_req_auth_timeout - Schedule a timeout for authentication
+ * @wpa_s: Pointer to wpa_supplicant data
+ * @sec: Number of seconds after which to time out authentication
+ * @usec: Number of microseconds after which to time out authentication
+ *
+ * This function is used to schedule a timeout for the current authentication
+ * attempt.
+ */
 void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s,
 				     int sec, int usec)
 {
 	if (wpa_s->conf && wpa_s->conf->ap_scan == 0 &&
-	    wpa_s->driver && strcmp(wpa_s->driver->name, "wired") == 0)
+	    wpa_s->driver && os_strcmp(wpa_s->driver->name, "wired") == 0)
 		return;
 
 	wpa_msg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec "
@@ -517,6 +553,14 @@
 }
 
 
+/**
+ * wpa_supplicant_cancel_auth_timeout - Cancel authentication timeout
+ * @wpa_s: Pointer to wpa_supplicant data
+ *
+ * This function is used to cancel authentication timeout scheduled with
+ * wpa_supplicant_req_auth_timeout() and it is called when authentication has
+ * been completed.
+ */
 void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s)
 {
 	wpa_msg(wpa_s, MSG_DEBUG, "Cancelling authentication timeout");
@@ -525,8 +569,16 @@
 }
 
 
+/**
+ * wpa_supplicant_initiate_eapol - Configure EAPOL state machine
+ * @wpa_s: Pointer to wpa_supplicant data
+ *
+ * This function is used to configure EAPOL state machine based on the selected
+ * authentication mode.
+ */
 void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s)
 {
+#ifdef IEEE8021X_EAPOL
 	struct eapol_config eapol_conf;
 	struct wpa_ssid *ssid = wpa_s->current_ssid;
 
@@ -540,7 +592,7 @@
 	else
 		eapol_sm_notify_portControl(wpa_s->eapol, Auto);
 
-	memset(&eapol_conf, 0, sizeof(eapol_conf));
+	os_memset(&eapol_conf, 0, sizeof(eapol_conf));
 	if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
 		eapol_conf.accept_802_1x_keys = 1;
 		eapol_conf.required_keys = 0;
@@ -553,18 +605,29 @@
 		}
 
 		if (wpa_s->conf && wpa_s->driver &&
-		    strcmp(wpa_s->driver->name, "wired") == 0) {
+		    os_strcmp(wpa_s->driver->name, "wired") == 0) {
 			eapol_conf.required_keys = 0;
 		}
 	}
-	eapol_conf.fast_reauth = wpa_s->conf->fast_reauth;
+	if (wpa_s->conf)
+		eapol_conf.fast_reauth = wpa_s->conf->fast_reauth;
 	eapol_conf.workaround = ssid->eap_workaround;
 	eapol_conf.eap_disabled = wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X &&
 		wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA;
 	eapol_sm_notify_config(wpa_s->eapol, ssid, &eapol_conf);
+#endif /* IEEE8021X_EAPOL */
 }
 
 
+/**
+ * wpa_supplicant_set_non_wpa_policy - Set WPA parameters to non-WPA mode
+ * @wpa_s: Pointer to wpa_supplicant data
+ * @ssid: Configuration data for the network
+ *
+ * This function is used to configure WPA state machine and related parameters
+ * to a mode where WPA is not enabled. This is called as part of the
+ * authentication configuration when the selected network does not use WPA.
+ */
 void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
 				       struct wpa_ssid *ssid)
 {
@@ -579,6 +642,7 @@
 	wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
 	wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
 	wpa_s->group_cipher = WPA_CIPHER_NONE;
+	wpa_s->mgmt_group_cipher = 0;
 
 	for (i = 0; i < NUM_WEP_KEYS; i++) {
 		if (ssid->wep_key_len[i] > 5) {
@@ -596,6 +660,10 @@
 	wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
 			 wpa_s->pairwise_cipher);
 	wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
+#ifdef CONFIG_IEEE80211W
+	wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
+			 wpa_s->mgmt_group_cipher);
+#endif /* CONFIG_IEEE80211W */
 
 	pmksa_cache_clear_current(wpa_s->wpa);
 }
@@ -609,14 +677,21 @@
 	eapol_sm_register_scard_ctx(wpa_s->eapol, NULL);
 	l2_packet_deinit(wpa_s->l2);
 	wpa_s->l2 = NULL;
+	if (wpa_s->l2_br) {
+		l2_packet_deinit(wpa_s->l2_br);
+		wpa_s->l2_br = NULL;
+	}
 
-	wpa_supplicant_ctrl_iface_deinit(wpa_s);
+	if (wpa_s->ctrl_iface) {
+		wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
+		wpa_s->ctrl_iface = NULL;
+	}
 	if (wpa_s->conf != NULL) {
 		wpa_config_free(wpa_s->conf);
 		wpa_s->conf = NULL;
 	}
 
-	free(wpa_s->confname);
+	os_free(wpa_s->confname);
 	wpa_s->confname = NULL;
 
 	wpa_sm_set_eapol(wpa_s->wpa, NULL);
@@ -626,19 +701,29 @@
 	rsn_preauth_deinit(wpa_s->wpa);
 
 	pmksa_candidate_free(wpa_s->wpa);
-	pmksa_cache_free(wpa_s->wpa);
 	wpa_sm_deinit(wpa_s->wpa);
 	wpa_s->wpa = NULL;
 	wpa_blacklist_clear(wpa_s);
 
-	free(wpa_s->scan_results);
+	os_free(wpa_s->scan_results);
 	wpa_s->scan_results = NULL;
 	wpa_s->num_scan_results = 0;
 
 	wpa_supplicant_cancel_scan(wpa_s);
+	wpa_supplicant_cancel_auth_timeout(wpa_s);
+
+	ieee80211_sta_deinit(wpa_s);
 }
 
 
+/**
+ * wpa_clear_keys - Clear keys configured for the driver
+ * @wpa_s: Pointer to wpa_supplicant data
+ * @addr: Previously used BSSID or %NULL if not available
+ *
+ * This function clears the encryption keys that has been previously configured
+ * for the driver.
+ */
 void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
 {
 	u8 *bcast = (u8 *) "\xff\xff\xff\xff\xff\xff";
@@ -656,6 +741,7 @@
 		return;
 	}
 
+	/* MLME-DELETEKEYS.request */
 	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, bcast, 0, 0, NULL, 0, NULL, 0);
 	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, bcast, 1, 0, NULL, 0, NULL, 0);
 	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, bcast, 2, 0, NULL, 0, NULL, 0);
@@ -663,11 +749,21 @@
 	if (addr) {
 		wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL, 0, NULL,
 				0);
+		/* MLME-SETPROTECTION.request(None) */
+		wpa_drv_mlme_setprotection(
+			wpa_s, addr,
+			MLME_SETPROTECTION_PROTECT_TYPE_NONE,
+			MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
 	}
 	wpa_s->keys_cleared = 1;
 }
 
 
+/**
+ * wpa_supplicant_state_txt - Get the connection state name as a text string
+ * @state: State (wpa_state; WPA_*)
+ * Returns: The state name as a printable text string
+ */
 const char * wpa_supplicant_state_txt(int state)
 {
 	switch (state) {
@@ -693,26 +789,50 @@
 }
 
 
+/**
+ * wpa_supplicant_set_state - Set current connection state
+ * @wpa_s: Pointer to wpa_supplicant data
+ * @state: The new connection state
+ *
+ * This function is called whenever the connection state changes, e.g.,
+ * association is completed for WPA/WPA2 4-Way Handshake is started.
+ */
 void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s, wpa_states state)
 {
 	wpa_printf(MSG_DEBUG, "State: %s -> %s",
 		   wpa_supplicant_state_txt(wpa_s->wpa_state),
 		   wpa_supplicant_state_txt(state));
+
+	wpa_supplicant_dbus_notify_state_change(wpa_s, state,
+						wpa_s->wpa_state);
+
 	if (state == WPA_COMPLETED && wpa_s->new_connection) {
-		wpa_s->new_connection = 0;
+#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
+		struct wpa_ssid *ssid = wpa_s->current_ssid;
 		wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
-			MACSTR " completed %s",
+			MACSTR " completed %s [id=%d id_str=%s]",
 			MAC2STR(wpa_s->bssid), wpa_s->reassociated_connection ?
-			"(reauth)" : "(auth)");
+			"(reauth)" : "(auth)",
+			ssid ? ssid->id : -1,
+			ssid && ssid->id_str ? ssid->id_str : "");
+#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
+		wpa_s->new_connection = 0;
 		wpa_s->reassociated_connection = 1;
+		wpa_drv_set_operstate(wpa_s, 1);
 	} else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
 		   state == WPA_ASSOCIATED) {
 		wpa_s->new_connection = 1;
+		wpa_drv_set_operstate(wpa_s, 0);
 	}
 	wpa_s->wpa_state = state;
 }
 
 
+/**
+ * wpa_supplicant_get_state - Get the connection state
+ * @wpa_s: Pointer to wpa_supplicant data
+ * Returns: The current connection state (WPA_*)
+ */
 wpa_states wpa_supplicant_get_state(struct wpa_supplicant *wpa_s)
 {
 	return wpa_s->wpa_state;
@@ -732,6 +852,27 @@
 }
 
 
+static void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
+{
+	wpa_s->pairwise_cipher = 0;
+	wpa_s->group_cipher = 0;
+	wpa_s->mgmt_group_cipher = 0;
+	wpa_s->key_mgmt = 0;
+	wpa_s->wpa_state = WPA_DISCONNECTED;
+}
+
+
+/**
+ * wpa_supplicant_reload_configuration - Reload configuration data
+ * @wpa_s: Pointer to wpa_supplicant data
+ * Returns: 0 on success or -1 if configuration parsing failed
+ *
+ * This function can be used to request that the configuration data is reloaded
+ * (e.g., after configuration file change). This function is reloading
+ * configuration only for one interface, so this may need to be called multiple
+ * times if %wpa_supplicant is controlling multiple interfaces and all
+ * interfaces need reconfiguration.
+ */
 int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
 {
 	struct wpa_config *conf;
@@ -747,26 +888,30 @@
 
 	reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
 		|| (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
-		    strcmp(conf->ctrl_interface, wpa_s->conf->ctrl_interface)
-		    != 0);
+		    os_strcmp(conf->ctrl_interface,
+			      wpa_s->conf->ctrl_interface) != 0);
 
-	if (reconf_ctrl)
-		wpa_supplicant_ctrl_iface_deinit(wpa_s);
+	if (reconf_ctrl && wpa_s->ctrl_iface) {
+		wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
+		wpa_s->ctrl_iface = NULL;
+	}
 
+	eapol_sm_invalidate_cached_session(wpa_s->eapol);
 	wpa_s->current_ssid = NULL;
 	/*
 	 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
 	 * pkcs11_engine_path, pkcs11_module_path.
-	 */ 
+	 */
 	eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
 	wpa_sm_set_config(wpa_s->wpa, NULL);
 	wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
-	pmksa_cache_notify_reconfig(wpa_s->wpa);
 	rsn_preauth_deinit(wpa_s->wpa);
 	wpa_config_free(wpa_s->conf);
 	wpa_s->conf = conf;
 	if (reconf_ctrl)
-		wpa_supplicant_ctrl_iface_init(wpa_s);
+		wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
+
+	wpa_supplicant_clear_status(wpa_s);
 	wpa_s->reassociate = 1;
 	wpa_supplicant_req_scan(wpa_s, 0, 0);
 	wpa_msg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
@@ -774,7 +919,6 @@
 }
 
 
-#ifndef CONFIG_NATIVE_WINDOWS
 static void wpa_supplicant_reconfig(int sig, void *eloop_ctx,
 				    void *signal_ctx)
 {
@@ -787,7 +931,6 @@
 		}
 	}
 }
-#endif /* CONFIG_NATIVE_WINDOWS */
 
 
 static void wpa_supplicant_gen_assoc_event(struct wpa_supplicant *wpa_s)
@@ -804,7 +947,7 @@
 	wpa_supplicant_initiate_eapol(wpa_s);
 	wpa_printf(MSG_DEBUG, "Already associated with a configured network - "
 		   "generating associated event");
-	memset(&data, 0, sizeof(data));
+	os_memset(&data, 0, sizeof(data));
 	wpa_supplicant_event(wpa_s, EVENT_ASSOC, &data);
 }
 
@@ -813,7 +956,7 @@
 {
 	struct wpa_supplicant *wpa_s = eloop_ctx;
 	struct wpa_ssid *ssid;
-	int enabled, scan_req = 0;
+	int enabled, scan_req = 0, ret;
 
 	if (wpa_s->disconnected)
 		return;
@@ -835,6 +978,13 @@
 	scan_req = wpa_s->scan_req;
 	wpa_s->scan_req = 0;
 
+	if (wpa_s->conf->ap_scan != 0 &&
+	    wpa_s->driver && os_strcmp(wpa_s->driver->name, "wired") == 0) {
+		wpa_printf(MSG_DEBUG, "Using wired driver - overriding "
+			   "ap_scan configuration");
+		wpa_s->conf->ap_scan = 0;
+	}
+
 	if (wpa_s->conf->ap_scan == 0) {
 		wpa_supplicant_gen_assoc_event(wpa_s);
 		return;
@@ -866,8 +1016,13 @@
 		 * ap_scan=2 mode - try to associate with each SSID instead of
 		 * scanning for each scan_ssid=1 network.
 		 */
-		if (ssid == NULL)
+		if (ssid == NULL) {
+			wpa_printf(MSG_DEBUG, "wpa_supplicant_scan: Reached "
+				   "end of scan list - go back to beginning");
+			wpa_s->prev_scan_ssid = BROADCAST_SSID_SCAN;
+			wpa_supplicant_req_scan(wpa_s, 0, 0);
 			return;
+		}
 		if (ssid->next) {
 			/* Continue from the next SSID on the next attempt. */
 			wpa_s->prev_scan_ssid = ssid;
@@ -888,8 +1043,23 @@
 	} else
 		wpa_s->prev_scan_ssid = BROADCAST_SSID_SCAN;
 
-	if (wpa_drv_scan(wpa_s, ssid ? ssid->ssid : NULL,
-			 ssid ? ssid->ssid_len : 0)) {
+	if (wpa_s->scan_res_tried == 0 && wpa_s->conf->ap_scan == 1) {
+		wpa_s->scan_res_tried++;
+		wpa_printf(MSG_DEBUG, "Trying to get current scan results "
+			   "first without requesting a new scan to speed up "
+			   "initial association");
+		wpa_supplicant_event(wpa_s, EVENT_SCAN_RESULTS, NULL);
+		return;
+	}
+
+	if (wpa_s->use_client_mlme) {
+		ret = ieee80211_sta_req_scan(wpa_s, ssid ? ssid->ssid : NULL,
+					     ssid ? ssid->ssid_len : 0);
+	} else {
+		ret = wpa_drv_scan(wpa_s, ssid ? ssid->ssid : NULL,
+				   ssid ? ssid->ssid_len : 0);
+	}
+	if (ret) {
 		wpa_printf(MSG_WARNING, "Failed to initiate AP scan.");
 		wpa_supplicant_req_scan(wpa_s, 10, 0);
 	}
@@ -966,10 +1136,34 @@
 		return -1;
 	}
 
+#ifdef CONFIG_IEEE80211W
+	if (!(ie->capabilities & WPA_CAPABILITY_MGMT_FRAME_PROTECTION) &&
+	    ssid->ieee80211w == IEEE80211W_REQUIRED) {
+		wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
+			"that does not support management frame protection - "
+			"reject");
+		return -1;
+	}
+#endif /* CONFIG_IEEE80211W */
+
 	return 0;
 }
 
 
+/**
+ * wpa_supplicant_set_suites - Set authentication and encryption parameters
+ * @wpa_s: Pointer to wpa_supplicant data
+ * @bss: Scan results for the selected BSS, or %NULL if not available
+ * @ssid: Configuration data for the selected network
+ * @wpa_ie: Buffer for the WPA/RSN IE
+ * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
+ * used buffer length in case the functions returns success.
+ * Returns: 0 on success or -1 on failure
+ *
+ * This function is used to configure authentication and encryption parameters
+ * based on the network configuration and scan result for the selected BSS (if
+ * available).
+ */
 int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
 			      struct wpa_scan_result *bss,
 			      struct wpa_ssid *ssid,
@@ -1001,18 +1195,30 @@
 		else
 			proto = WPA_PROTO_WPA;
 		if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
-			memset(&ie, 0, sizeof(ie));
+			os_memset(&ie, 0, sizeof(ie));
 			ie.group_cipher = ssid->group_cipher;
 			ie.pairwise_cipher = ssid->pairwise_cipher;
 			ie.key_mgmt = ssid->key_mgmt;
+#ifdef CONFIG_IEEE80211W
+			ie.mgmt_group_cipher =
+				ssid->ieee80211w != NO_IEEE80211W ?
+				WPA_CIPHER_AES_128_CMAC : 0;
+#endif /* CONFIG_IEEE80211W */
 			wpa_printf(MSG_DEBUG, "WPA: Set cipher suites based "
 				   "on configuration");
-		}
+		} else
+			proto = ie.proto;
 	}
 
 	wpa_printf(MSG_DEBUG, "WPA: Selected cipher suites: group %d "
-		   "pairwise %d key_mgmt %d",
-		   ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt);
+		   "pairwise %d key_mgmt %d proto %d",
+		   ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
+#ifdef CONFIG_IEEE80211W
+	if (ssid->ieee80211w) {
+		wpa_printf(MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
+			   ie.mgmt_group_cipher);
+	}
+#endif /* CONFIG_IEEE80211W */
 
 	wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
 
@@ -1077,6 +1283,23 @@
 			 wpa_s->pairwise_cipher);
 	wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
 
+#ifdef CONFIG_IEEE80211W
+	sel = ie.mgmt_group_cipher;
+	if (ssid->ieee80211w == NO_IEEE80211W ||
+	    !(ie.capabilities & WPA_CAPABILITY_MGMT_FRAME_PROTECTION))
+		sel = 0;
+	if (sel & WPA_CIPHER_AES_128_CMAC) {
+		wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
+		wpa_msg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
+			"AES-128-CMAC");
+	} else {
+		wpa_s->mgmt_group_cipher = 0;
+		wpa_msg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
+	}
+	wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
+			 wpa_s->mgmt_group_cipher);
+#endif /* CONFIG_IEEE80211W */
+
 	if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
 		wpa_printf(MSG_WARNING, "WPA: Failed to generate WPA IE.");
 		return -1;
@@ -1091,15 +1314,23 @@
 }
 
 
+/**
+ * wpa_supplicant_associate - Request association
+ * @wpa_s: Pointer to wpa_supplicant data
+ * @bss: Scan results for the selected BSS, or %NULL if not available
+ * @ssid: Configuration data for the selected network
+ *
+ * This function is used to request %wpa_supplicant to associate with a BSS.
+ */
 void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
 			      struct wpa_scan_result *bss,
 			      struct wpa_ssid *ssid)
 {
 	u8 wpa_ie[80];
 	size_t wpa_ie_len;
-	int use_crypt;
+	int use_crypt, ret, i;
 	int algs = AUTH_ALG_OPEN_SYSTEM;
-	int cipher_pairwise, cipher_group;
+	wpa_cipher cipher_pairwise, cipher_group;
 	struct wpa_driver_associate_params params;
 	int wep_keys_set = 0;
 	struct wpa_driver_capa capa;
@@ -1110,10 +1341,12 @@
 		wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
 			" (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
 			wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
-		memset(wpa_s->bssid, 0, ETH_ALEN);
+		os_memset(wpa_s->bssid, 0, ETH_ALEN);
+		os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
 	} else {
 		wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
 			wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
+		os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
 	}
 	wpa_supplicant_cancel_scan(wpa_s);
 
@@ -1121,6 +1354,7 @@
 	 * previous association. */
 	wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
 
+#ifdef IEEE8021X_EAPOL
 	if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
 		if (ssid->leap) {
 			if (ssid->non_leap == 0)
@@ -1129,6 +1363,7 @@
 				algs |= AUTH_ALG_LEAP;
 		}
 	}
+#endif /* IEEE8021X_EAPOL */
 	wpa_printf(MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
 	if (ssid->auth_alg) {
 		algs = 0;
@@ -1181,7 +1416,6 @@
 	cipher_group = cipher_suite2driver(wpa_s->group_cipher);
 	if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
 	    wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
-		int i;
 		if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
 			use_crypt = 0;
 		for (i = 0; i < NUM_WEP_KEYS; i++) {
@@ -1196,6 +1430,7 @@
 		}
 	}
 
+#ifdef IEEE8021X_EAPOL
 	if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
 		if ((ssid->eapol_flags &
 		     (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
@@ -1209,6 +1444,7 @@
 			cipher_pairwise = cipher_group = CIPHER_WEP104;
 		}
 	}
+#endif /* IEEE8021X_EAPOL */
 
 	if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
 		/* Set the key before (and later after) association */
@@ -1217,7 +1453,7 @@
 
 	wpa_drv_set_drop_unencrypted(wpa_s, use_crypt);
 	wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
-	memset(&params, 0, sizeof(params));
+	os_memset(&params, 0, sizeof(params));
 	if (bss) {
 		params.bssid = bss->bssid;
 		params.ssid = bss->ssid;
@@ -1234,7 +1470,32 @@
 	params.key_mgmt_suite = key_mgmt2driver(wpa_s->key_mgmt);
 	params.auth_alg = algs;
 	params.mode = ssid->mode;
-	if (wpa_drv_associate(wpa_s, &params) < 0) {
+	for (i = 0; i < NUM_WEP_KEYS; i++) {
+		if (ssid->wep_key_len[i])
+			params.wep_key[i] = ssid->wep_key[i];
+		params.wep_key_len[i] = ssid->wep_key_len[i];
+	}
+	params.wep_tx_keyidx = ssid->wep_tx_keyidx;
+
+#ifdef CONFIG_IEEE80211W
+	switch (ssid->ieee80211w) {
+	case NO_IEEE80211W:
+		params.mgmt_frame_protection = NO_MGMT_FRAME_PROTECTION;
+		break;
+	case IEEE80211W_OPTIONAL:
+		params.mgmt_frame_protection = MGMT_FRAME_PROTECTION_OPTIONAL;
+		break;
+	case IEEE80211W_REQUIRED:
+		params.mgmt_frame_protection = MGMT_FRAME_PROTECTION_REQUIRED;
+		break;
+	}
+#endif /* CONFIG_IEEE80211W */
+
+	if (wpa_s->use_client_mlme)
+		ret = ieee80211_sta_associate(wpa_s, &params);
+	else
+		ret = wpa_drv_associate(wpa_s, &params);
+	if (ret < 0) {
 		wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
 			"failed");
 		/* try to continue anyway; new association will be tried again
@@ -1265,48 +1526,78 @@
 	if (wep_keys_set && wpa_drv_get_capa(wpa_s, &capa) == 0 &&
 	    capa.flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC) {
 		/* Set static WEP keys again */
-		int i;
-		for (i = 0; i < NUM_WEP_KEYS; i++) {
-			if (ssid->wep_key_len[i]) {
+		int j;
+		for (j = 0; j < NUM_WEP_KEYS; j++) {
+			if (ssid->wep_key_len[j]) {
 				wpa_set_wep_key(wpa_s,
-						i == ssid->wep_tx_keyidx,
-						i, ssid->wep_key[i],
-						ssid->wep_key_len[i]);
+						j == ssid->wep_tx_keyidx,
+						j, ssid->wep_key[j],
+						ssid->wep_key_len[j]);
 			}
 		}
 	}
 
+	if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
+		/*
+		 * Do not allow EAP session resumption between different
+		 * network configurations.
+		 */
+		eapol_sm_invalidate_cached_session(wpa_s->eapol);
+	}
 	wpa_s->current_ssid = ssid;
 	wpa_sm_set_config(wpa_s->wpa, wpa_s->current_ssid);
 	wpa_supplicant_initiate_eapol(wpa_s);
 }
 
 
+/**
+ * wpa_supplicant_disassociate - Disassociate the current connection
+ * @wpa_s: Pointer to wpa_supplicant data
+ * @reason_code: IEEE 802.11 reason code for the disassociate frame
+ *
+ * This function is used to request %wpa_supplicant to disassociate with the
+ * current AP.
+ */
 void wpa_supplicant_disassociate(struct wpa_supplicant *wpa_s,
 				 int reason_code)
 {
 	u8 *addr = NULL;
-	wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
-	if (memcmp(wpa_s->bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) != 0) {
-		wpa_drv_disassociate(wpa_s, wpa_s->bssid, reason_code);
+	if (os_memcmp(wpa_s->bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) != 0)
+	{
+		if (wpa_s->use_client_mlme)
+			ieee80211_sta_disassociate(wpa_s, reason_code);
+		else
+			wpa_drv_disassociate(wpa_s, wpa_s->bssid, reason_code);
 		addr = wpa_s->bssid;
 	}
 	wpa_clear_keys(wpa_s, addr);
+	wpa_supplicant_mark_disassoc(wpa_s);
 	wpa_s->current_ssid = NULL;
 	wpa_sm_set_config(wpa_s->wpa, NULL);
 	eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
-	eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
-	eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
 }
 
 
+/**
+ * wpa_supplicant_deauthenticate - Deauthenticate the current connection
+ * @wpa_s: Pointer to wpa_supplicant data
+ * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
+ *
+ * This function is used to request %wpa_supplicant to disassociate with the
+ * current AP.
+ */
 void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
 				   int reason_code)
 {
 	u8 *addr = NULL;
 	wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
-	if (memcmp(wpa_s->bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) != 0) {
-		wpa_drv_deauthenticate(wpa_s, wpa_s->bssid, reason_code);
+	if (os_memcmp(wpa_s->bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) != 0)
+	{
+		if (wpa_s->use_client_mlme)
+			ieee80211_sta_deauthenticate(wpa_s, reason_code);
+		else
+			wpa_drv_deauthenticate(wpa_s, wpa_s->bssid,
+					       reason_code);
 		addr = wpa_s->bssid;
 	}
 	wpa_clear_keys(wpa_s, addr);
@@ -1318,24 +1609,36 @@
 }
 
 
+/**
+ * wpa_supplicant_get_scan_results - Get scan results
+ * @wpa_s: Pointer to wpa_supplicant data
+ * Returns: 0 on success, -1 on failure
+ *
+ * This function is request the current scan results from the driver and stores
+ * a local copy of the results in wpa_s->scan_results.
+ */
 int wpa_supplicant_get_scan_results(struct wpa_supplicant *wpa_s)
 {
 #define SCAN_AP_LIMIT 128
 	struct wpa_scan_result *results, *tmp;
 	int num;
 
-	results = malloc(SCAN_AP_LIMIT * sizeof(struct wpa_scan_result));
+	results = os_malloc(SCAN_AP_LIMIT * sizeof(struct wpa_scan_result));
 	if (results == NULL) {
 		wpa_printf(MSG_WARNING, "Failed to allocate memory for scan "
 			   "results");
 		return -1;
 	}
 
-	num = wpa_drv_get_scan_results(wpa_s, results, SCAN_AP_LIMIT);
+	if (wpa_s->use_client_mlme) {
+		num = ieee80211_sta_get_scan_results(wpa_s, results,
+						     SCAN_AP_LIMIT);
+	} else
+		num = wpa_drv_get_scan_results(wpa_s, results, SCAN_AP_LIMIT);
 	wpa_printf(MSG_DEBUG, "Scan results: %d", num);
 	if (num < 0) {
 		wpa_printf(MSG_DEBUG, "Failed to get scan results");
-		free(results);
+		os_free(results);
 		return -1;
 	}
 	if (num > SCAN_AP_LIMIT) {
@@ -1345,12 +1648,12 @@
 	}
 
 	/* Free unneeded memory for unused scan result entries */
-	tmp = realloc(results, num * sizeof(struct wpa_scan_result));
+	tmp = os_realloc(results, num * sizeof(struct wpa_scan_result));
 	if (tmp || num == 0) {
 		results = tmp;
 	}
 
-	free(wpa_s->scan_results);
+	os_free(wpa_s->scan_results);
 	wpa_s->scan_results = results;
 	wpa_s->num_scan_results = num;
 
@@ -1370,7 +1673,14 @@
 	}
 
 	for (i = 0; i < wpa_s->num_scan_results; i++) {
-		if (memcmp(results[i].bssid, wpa_s->bssid, ETH_ALEN) == 0) {
+		struct wpa_ssid *ssid = wpa_s->current_ssid;
+		if (os_memcmp(results[i].bssid, wpa_s->bssid, ETH_ALEN) != 0)
+			continue;
+		if (ssid == NULL ||
+		    ((results[i].ssid_len == ssid->ssid_len &&
+		      os_memcmp(results[i].ssid, ssid->ssid, ssid->ssid_len)
+		      == 0) ||
+		     ssid->ssid_len == 0)) {
 			curr = &results[i];
 			break;
 		}
@@ -1409,36 +1719,52 @@
 
 
 /**
- * wpa_supplicant_get_ssid - get a pointer to the current network structure
- * @wpa_s: pointer to wpa_supplicant data
- *
- * Returns: a pointer to the current network structure or %NULL on failure
+ * wpa_supplicant_get_ssid - Get a pointer to the current network structure
+ * @wpa_s: Pointer to wpa_supplicant data
+ * Returns: A pointer to the current network structure or %NULL on failure
  */
 struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
 {
 	struct wpa_ssid *entry;
 	u8 ssid[MAX_SSID_LEN];
-	int ssid_len;
+	int res;
+	size_t ssid_len;
 	u8 bssid[ETH_ALEN];
+	int wired;
 
-	ssid_len = wpa_drv_get_ssid(wpa_s, ssid);
-	if (ssid_len < 0) {
-		wpa_printf(MSG_WARNING, "Could not read SSID from driver.");
-		return NULL;
+	if (wpa_s->use_client_mlme) {
+		if (ieee80211_sta_get_ssid(wpa_s, ssid, &ssid_len)) {
+			wpa_printf(MSG_WARNING, "Could not read SSID from "
+				   "MLME.");
+			return NULL;
+		}
+	} else {
+		res = wpa_drv_get_ssid(wpa_s, ssid);
+		if (res < 0) {
+			wpa_printf(MSG_WARNING, "Could not read SSID from "
+				   "driver.");
+			return NULL;
+		}
+		ssid_len = res;
 	}
 
-	if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
+	if (wpa_s->use_client_mlme)
+		os_memcpy(bssid, wpa_s->bssid, ETH_ALEN);
+	else if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
 		wpa_printf(MSG_WARNING, "Could not read BSSID from driver.");
 		return NULL;
 	}
 
+	wired = wpa_s->conf->ap_scan == 0 && wpa_s->driver &&
+		os_strcmp(wpa_s->driver->name, "wired") == 0;
+
 	entry = wpa_s->conf->ssid;
 	while (entry) {
 		if (!entry->disabled &&
-		    ssid_len == entry->ssid_len &&
-		    memcmp(ssid, entry->ssid, ssid_len) == 0 &&
+		    ((ssid_len == entry->ssid_len &&
+		      os_memcmp(ssid, entry->ssid, ssid_len) == 0) || wired) &&
 		    (!entry->bssid_set ||
-		     memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
+		     os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
 			return entry;
 		entry = entry->next;
 	}
@@ -1505,8 +1831,13 @@
 }
 
 
-static int wpa_supplicant_get_bssid(void *wpa_s, u8 *bssid)
+static int wpa_supplicant_get_bssid(void *ctx, u8 *bssid)
 {
+	struct wpa_supplicant *wpa_s = ctx;
+	if (wpa_s->use_client_mlme) {
+		os_memcpy(bssid, wpa_s->bssid, ETH_ALEN);
+		return 0;
+	}
 	return wpa_drv_get_bssid(wpa_s, bssid);
 }
 
@@ -1521,6 +1852,15 @@
 }
 
 
+static int wpa_supplicant_mlme_setprotection(void *wpa_s, const u8 *addr,
+					     int protection_type,
+					     int key_type)
+{
+	return wpa_drv_mlme_setprotection(wpa_s, addr, protection_type,
+					  key_type);
+}
+
+
 static int wpa_supplicant_add_pmkid(void *wpa_s,
 				    const u8 *bssid, const u8 *pmkid)
 {
@@ -1557,13 +1897,13 @@
 	}
 
 	for (i = 0; wpa_supplicant_drivers[i]; i++) {
-		if (strcmp(name, wpa_supplicant_drivers[i]->name) == 0) {
+		if (os_strcmp(name, wpa_supplicant_drivers[i]->name) == 0) {
 			wpa_s->driver = wpa_supplicant_drivers[i];
 			return 0;
 		}
 	}
 
-	printf("Unsupported driver '%s'.\n", name);
+	wpa_printf(MSG_ERROR, "Unsupported driver '%s'.\n", name);
 	return -1;
 }
 
@@ -1604,7 +1944,7 @@
 	 * an AP, so just allow any address to be used for now. The replies are
 	 * still sent to the current BSSID (if available), though. */
 
-	memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
+	os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
 	if (wpa_s->key_mgmt != WPA_KEY_MGMT_PSK &&
 	    eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
 		return;
@@ -1613,6 +1953,17 @@
 }
 
 
+/**
+ * wpa_supplicant_driver_init - Initialize driver interface parameters
+ * @wpa_s: Pointer to wpa_supplicant data
+ * @wait_for_interface: 0 = do not wait for the interface (reports a failure if
+ * the interface is not present), 1 = wait until the interface is available
+ * Returns: 0 on success, -1 on failure
+ *
+ * This function is called to initialize driver interface parameters.
+ * wpa_drv_init() must have been called before this function to initialize the
+ * driver interface.
+ */
 int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s,
 			       int wait_for_interface)
 {
@@ -1622,7 +1973,7 @@
 		if (wpa_s->driver->send_eapol) {
 			const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
 			if (addr)
-				memcpy(wpa_s->own_addr, addr, ETH_ALEN);
+				os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
 			break;
 		}
 		wpa_s->l2 = l2_packet_init(wpa_s->ifname,
@@ -1633,18 +1984,34 @@
 			break;
 		else if (!wait_for_interface)
 			return -1;
-		printf("Waiting for interface..\n");
-		sleep(5);
+		wpa_printf(MSG_DEBUG, "Waiting for interface..");
+		os_sleep(5, 0);
 	}
 
 	if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
-		fprintf(stderr, "Failed to get own L2 address\n");
+		wpa_printf(MSG_ERROR, "Failed to get own L2 address");
 		return -1;
 	}
 
 	wpa_printf(MSG_DEBUG, "Own MAC address: " MACSTR,
 		   MAC2STR(wpa_s->own_addr));
 
+	if (wpa_s->bridge_ifname[0]) {
+		wpa_printf(MSG_DEBUG, "Receiving packets from bridge interface"
+			   " '%s'", wpa_s->bridge_ifname);
+		wpa_s->l2_br = l2_packet_init(wpa_s->bridge_ifname,
+					      wpa_s->own_addr,
+					      ETH_P_EAPOL,
+					      wpa_supplicant_rx_eapol, wpa_s,
+					      0);
+		if (wpa_s->l2_br == NULL) {
+			wpa_printf(MSG_ERROR, "Failed to open l2_packet "
+				   "connection for the bridge interface '%s'",
+				   wpa_s->bridge_ifname);
+			return -1;
+		}
+	}
+
 	/* Backwards compatibility call to set_wpa() handler. This is called
 	 * only just after init and just before deinit, so these handler can be
 	 * used to implement same functionality. */
@@ -1656,8 +2023,8 @@
 			wpa_printf(MSG_DEBUG, "Driver does not support WPA.");
 			/* Continue to allow non-WPA modes to be used. */
 		} else {
-			fprintf(stderr, "Failed to enable WPA in the "
-				"driver.\n");
+			wpa_printf(MSG_ERROR, "Failed to enable WPA in the "
+				"driver.");
 			return -1;
 		}
 	}
@@ -1681,20 +2048,7 @@
 static int wpa_supplicant_daemon(const char *pid_file)
 {
 	wpa_printf(MSG_DEBUG, "Daemonize..");
-	if (daemon(0, 0)) {
-		perror("daemon");
-		return -1;
-	}
-
-	if (pid_file) {
-		FILE *f = fopen(pid_file, "w");
-		if (f) {
-			fprintf(f, "%u\n", getpid());
-			fclose(f);
-		}
-	}
-
-	return 0;
+	return os_daemonize(pid_file);
 }
 
 
@@ -1702,11 +2056,9 @@
 {
 	struct wpa_supplicant *wpa_s;
 
-	wpa_s = malloc(sizeof(*wpa_s));
+	wpa_s = os_zalloc(sizeof(*wpa_s));
 	if (wpa_s == NULL)
 		return NULL;
-	memset(wpa_s, 0, sizeof(*wpa_s));
-	wpa_s->ctrl_sock = -1;
 	wpa_s->scan_req = 1;
 
 	return wpa_s;
@@ -1717,10 +2069,11 @@
 				     struct wpa_interface *iface)
 {
 	wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
-		   "'%s' ctrl_interface '%s'", iface->ifname,
+		   "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
 		   iface->confname ? iface->confname : "N/A",
 		   iface->driver ? iface->driver : "default",
-		   iface->ctrl_interface ? iface->ctrl_interface : "N/A");
+		   iface->ctrl_interface ? iface->ctrl_interface : "N/A",
+		   iface->bridge_ifname ? iface->bridge_ifname : "N/A");
 
 	if (wpa_supplicant_set_driver(wpa_s, iface->driver) < 0) {
 		return -1;
@@ -1728,7 +2081,7 @@
 
 	if (iface->confname) {
 #ifdef CONFIG_BACKEND_FILE
-		wpa_s->confname = rel2abs_path(iface->confname);
+		wpa_s->confname = os_rel2abs_path(iface->confname);
 		if (wpa_s->confname == NULL) {
 			wpa_printf(MSG_ERROR, "Failed to get absolute path "
 				   "for configuration file '%s'.",
@@ -1738,12 +2091,12 @@
 		wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
 			   iface->confname, wpa_s->confname);
 #else /* CONFIG_BACKEND_FILE */
-		wpa_s->confname = strdup(iface->confname);
+		wpa_s->confname = os_strdup(iface->confname);
 #endif /* CONFIG_BACKEND_FILE */
 		wpa_s->conf = wpa_config_read(wpa_s->confname);
 		if (wpa_s->conf == NULL) {
-			printf("Failed to read read or parse configuration "
-			       "'%s'.\n", wpa_s->confname);
+			wpa_printf(MSG_ERROR, "Failed to read or parse "
+				   "configuration '%s'.", wpa_s->confname);
 			return -1;
 		}
 
@@ -1752,34 +2105,46 @@
 		 * line.
 		 */
 		if (iface->ctrl_interface) {
-			free(wpa_s->conf->ctrl_interface);
+			os_free(wpa_s->conf->ctrl_interface);
 			wpa_s->conf->ctrl_interface =
-				strdup(iface->ctrl_interface);
+				os_strdup(iface->ctrl_interface);
 		}
 
 		if (iface->driver_param) {
-			free(wpa_s->conf->driver_param);
+			os_free(wpa_s->conf->driver_param);
 			wpa_s->conf->driver_param =
-				strdup(iface->driver_param);
+				os_strdup(iface->driver_param);
 		}
 	} else
 		wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
 						     iface->driver_param);
 
 	if (wpa_s->conf == NULL) {
-		printf("\nNo configuration found.\n");
+		wpa_printf(MSG_ERROR, "\nNo configuration found.");
 		return -1;
 	}
 
 	if (iface->ifname == NULL) {
-		printf("\nInterface name is required.\n");
+		wpa_printf(MSG_ERROR, "\nInterface name is required.");
 		return -1;
 	}
-	if (strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
-		printf("Too long interface name '%s'.\n", iface->ifname);
+	if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
+		wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
+			   iface->ifname);
 		return -1;
 	}
-	strncpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
+	os_strncpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
+
+	if (iface->bridge_ifname) {
+		if (os_strlen(iface->bridge_ifname) >=
+		    sizeof(wpa_s->bridge_ifname)) {
+			wpa_printf(MSG_ERROR, "\nToo long bridge interface "
+				   "name '%s'.", iface->bridge_ifname);
+			return -1;
+		}
+		os_strncpy(wpa_s->bridge_ifname, iface->bridge_ifname,
+			   sizeof(wpa_s->bridge_ifname));
+	}
 
 	return 0;
 }
@@ -1789,13 +2154,12 @@
 {
 #ifdef IEEE8021X_EAPOL
 	struct eapol_ctx *ctx;
-	ctx = malloc(sizeof(*ctx));
+	ctx = os_zalloc(sizeof(*ctx));
 	if (ctx == NULL) {
-		printf("Failed to allocate EAPOL context.\n");
+		wpa_printf(MSG_ERROR, "Failed to allocate EAPOL context.");
 		return -1;
 	}
 
-	memset(ctx, 0, sizeof(*ctx));
 	ctx->ctx = wpa_s;
 	ctx->msg_ctx = wpa_s;
 	ctx->eapol_send_ctx = wpa_s;
@@ -1805,13 +2169,15 @@
 	ctx->set_wep_key = wpa_eapol_set_wep_key;
 	ctx->set_config_blob = wpa_supplicant_set_config_blob;
 	ctx->get_config_blob = wpa_supplicant_get_config_blob;
+	ctx->aborted_cached = wpa_supplicant_aborted_cached;
 	ctx->opensc_engine_path = wpa_s->conf->opensc_engine_path;
 	ctx->pkcs11_engine_path = wpa_s->conf->pkcs11_engine_path;
 	ctx->pkcs11_module_path = wpa_s->conf->pkcs11_module_path;
 	wpa_s->eapol = eapol_sm_init(ctx);
 	if (wpa_s->eapol == NULL) {
-		free(ctx);
-		printf("Failed to initialize EAPOL state machines.\n");
+		os_free(ctx);
+		wpa_printf(MSG_ERROR, "Failed to initialize EAPOL state "
+			   "machines.");
 		return -1;
 	}
 #endif /* IEEE8021X_EAPOL */
@@ -1824,13 +2190,12 @@
 {
 #ifndef CONFIG_NO_WPA
 	struct wpa_sm_ctx *ctx;
-	ctx = malloc(sizeof(*ctx));
+	ctx = os_zalloc(sizeof(*ctx));
 	if (ctx == NULL) {
-		printf("Failed to allocate WPA context.\n");
+		wpa_printf(MSG_ERROR, "Failed to allocate WPA context.");
 		return -1;
 	}
 
-	memset(ctx, 0, sizeof(*ctx));
 	ctx->ctx = wpa_s;
 	ctx->set_state = _wpa_supplicant_set_state;
 	ctx->get_state = _wpa_supplicant_get_state;
@@ -1849,10 +2214,12 @@
 	ctx->remove_pmkid = wpa_supplicant_remove_pmkid;
 	ctx->set_config_blob = wpa_supplicant_set_config_blob;
 	ctx->get_config_blob = wpa_supplicant_get_config_blob;
+	ctx->mlme_setprotection = wpa_supplicant_mlme_setprotection;
 
 	wpa_s->wpa = wpa_sm_init(ctx);
 	if (wpa_s->wpa == NULL) {
-		fprintf(stderr, "Failed to initialize WPA state machine\n");
+		wpa_printf(MSG_ERROR, "Failed to initialize WPA state "
+			   "machine");
 		return -1;
 	}
 #endif /* CONFIG_NO_WPA */
@@ -1865,6 +2232,7 @@
 				      int wait_for_interface)
 {
 	const char *ifname;
+	struct wpa_driver_capa capa;
 
 	wpa_printf(MSG_DEBUG, "Initializing interface (2) '%s'",
 		   wpa_s->ifname);
@@ -1882,50 +2250,52 @@
 	 * call. */
 	wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
 	if (wpa_s->drv_priv == NULL) {
-		fprintf(stderr, "Failed to initialize driver interface\n");
+		wpa_printf(MSG_ERROR, "Failed to initialize driver interface");
 		return -1;
 	}
 	if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
-		fprintf(stderr, "Driver interface rejected driver_param "
-			"'%s'\n", wpa_s->conf->driver_param);
+		wpa_printf(MSG_ERROR, "Driver interface rejected "
+			   "driver_param '%s'", wpa_s->conf->driver_param);
 		return -1;
 	}
 
 	ifname = wpa_drv_get_ifname(wpa_s);
-	if (ifname && strcmp(ifname, wpa_s->ifname) != 0) {
+	if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
 		wpa_printf(MSG_DEBUG, "Driver interface replaced interface "
 			   "name with '%s'", ifname);
-		strncpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
+		os_strncpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
 	}
 
 	if (wpa_supplicant_init_wpa(wpa_s) < 0)
 		return -1;
 
-	wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname);
+	wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
+			  wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
+			  NULL);
 	wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
 	wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
 
 	if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
 	    wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
 			     wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
-		fprintf(stderr, "Invalid WPA parameter value for "
-			"dot11RSNAConfigPMKLifetime\n");
+		wpa_printf(MSG_ERROR, "Invalid WPA parameter value for "
+			   "dot11RSNAConfigPMKLifetime");
 		return -1;
 	}
 
 	if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
 	    wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
 			     wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
-		fprintf(stderr, "Invalid WPA parameter value for "
-			"dot11RSNAConfigPMKReauthThreshold\n");
+		wpa_printf(MSG_ERROR, "Invalid WPA parameter value for "
+			"dot11RSNAConfigPMKReauthThreshold");
 		return -1;
 	}
 
 	if (wpa_s->conf->dot11RSNAConfigSATimeout &&
 	    wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
 			     wpa_s->conf->dot11RSNAConfigSATimeout)) {
-		fprintf(stderr, "Invalid WPA parameter value for "
-			"dot11RSNAConfigSATimeout\n");
+		wpa_printf(MSG_ERROR, "Invalid WPA parameter value for "
+			   "dot11RSNAConfigSATimeout");
 		return -1;
 	}
 
@@ -1934,18 +2304,27 @@
 	}
 	wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
 
-	if (wpa_supplicant_ctrl_iface_init(wpa_s)) {
-		printf("Failed to initialize control interface '%s'.\n"
-		       "You may have another wpa_supplicant process already "
-		       "running or the file was\n"
-		       "left by an unclean termination of wpa_supplicant in "
-		       "which case you will need\n"
-		       "to manually remove this file before starting "
-		       "wpa_supplicant again.\n",
-		       wpa_s->conf->ctrl_interface);
+	wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
+	if (wpa_s->ctrl_iface == NULL) {
+		wpa_printf(MSG_ERROR,
+			   "Failed to initialize control interface '%s'.\n"
+			   "You may have another wpa_supplicant process "
+			   "already running or the file was\n"
+			   "left by an unclean termination of wpa_supplicant "
+			   "in which case you will need\n"
+			   "to manually remove this file before starting "
+			   "wpa_supplicant again.\n",
+			   wpa_s->conf->ctrl_interface);
 		return -1;
 	}
 
+	if (wpa_drv_get_capa(wpa_s, &capa) == 0 &&
+	    capa.flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME) {
+		wpa_s->use_client_mlme = 1;
+		if (ieee80211_sta_init(wpa_s))
+			return -1;
+	}
+
 	return 0;
 }
 
@@ -1959,17 +2338,21 @@
 		 * called only just after init and just before deinit, so these
 		 * handler can be used to implement same functionality. */
 		if (wpa_drv_set_wpa(wpa_s, 0) < 0) {
-			fprintf(stderr, "Failed to disable WPA in the "
-				"driver.\n");
+			wpa_printf(MSG_ERROR, "Failed to disable WPA in the "
+				   "driver.");
 		}
 
 		wpa_drv_set_drop_unencrypted(wpa_s, 0);
 		wpa_drv_set_countermeasures(wpa_s, 0);
 		wpa_clear_keys(wpa_s, NULL);
-
-		wpa_drv_deinit(wpa_s);
 	}
+
+	wpas_dbus_unregister_iface(wpa_s);
+
 	wpa_supplicant_cleanup(wpa_s);
+
+	if (wpa_s->drv_priv)
+		wpa_drv_deinit(wpa_s);
 }
 
 
@@ -2003,11 +2386,19 @@
 		wpa_printf(MSG_DEBUG, "Failed to add interface %s",
 			   iface->ifname);
 		wpa_supplicant_deinit_iface(wpa_s);
-		free(wpa_s);
+		os_free(wpa_s);
 		return NULL;
 	}
 
 	wpa_s->global = global;
+
+	/* Register the interface with the dbus control interface */
+	if (wpas_dbus_register_iface(wpa_s)) {
+		wpa_supplicant_deinit_iface(wpa_s);
+		os_free(wpa_s);
+		return NULL;
+	}
+		
 	wpa_s->next = global->ifaces;
 	global->ifaces = wpa_s;
 
@@ -2048,7 +2439,7 @@
 	wpa_printf(MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
 
 	wpa_supplicant_deinit_iface(wpa_s);
-	free(wpa_s);
+	os_free(wpa_s);
 
 	return 0;
 }
@@ -2066,7 +2457,7 @@
 	struct wpa_supplicant *wpa_s;
 
 	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
-		if (strcmp(wpa_s->ifname, ifname) == 0)
+		if (os_strcmp(wpa_s->ifname, ifname) == 0)
 			return wpa_s;
 	}
 	return NULL;
@@ -2085,37 +2476,68 @@
 struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
 {
 	struct wpa_global *global;
+	int ret;
 
 	if (params == NULL)
 		return NULL;
-	global = malloc(sizeof(*global));
+
+	wpa_debug_use_file = params->wpa_debug_use_file;
+	wpa_debug_open_file();
+
+	ret = eap_peer_register_methods();
+	if (ret) {
+		wpa_printf(MSG_ERROR, "Failed to register EAP methods");
+		if (ret == -2)
+			wpa_printf(MSG_ERROR, "Two or more EAP methods used "
+				   "the same EAP type.");
+		return NULL;
+	}
+
+	global = os_zalloc(sizeof(*global));
 	if (global == NULL)
 		return NULL;
-	memset(global, 0, sizeof(*global));
 	global->params.daemonize = params->daemonize;
 	global->params.wait_for_interface = params->wait_for_interface;
 	global->params.wait_for_monitor = params->wait_for_monitor;
+	global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
 	if (params->pid_file)
-		global->params.pid_file = strdup(params->pid_file);
+		global->params.pid_file = os_strdup(params->pid_file);
 	if (params->ctrl_interface)
-		global->params.ctrl_interface = strdup(params->ctrl_interface);
+		global->params.ctrl_interface =
+			os_strdup(params->ctrl_interface);
 	wpa_debug_level = global->params.wpa_debug_level =
 		params->wpa_debug_level;
 	wpa_debug_show_keys = global->params.wpa_debug_show_keys =
 		params->wpa_debug_show_keys;
 	wpa_debug_timestamp = global->params.wpa_debug_timestamp =
 		params->wpa_debug_timestamp;
+	wpa_debug_use_file = global->params.wpa_debug_use_file =
+		params->wpa_debug_use_file;
 
-	eloop_init(global);
+	if (eloop_init(global)) {
+		wpa_printf(MSG_ERROR, "Failed to initialize event loop");
+		wpa_supplicant_deinit(global);
+		return NULL;
+	}
 
-	if (wpa_supplicant_global_ctrl_iface_init(global)) {
-		eloop_destroy();
+	global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
+	if (global->ctrl_iface == NULL) {
+		wpa_supplicant_deinit(global);
 		return NULL;
 	}
 
+	if (global->params.dbus_ctrl_interface) {
+		global->dbus_ctrl_iface =
+			wpa_supplicant_dbus_ctrl_iface_init(global);
+		if (global->dbus_ctrl_iface == NULL) {
+			wpa_supplicant_deinit(global);
+			return NULL;
+		}
+	}
+
 	if (global->params.wait_for_interface && global->params.daemonize &&
 	    wpa_supplicant_daemon(global->params.pid_file)) {
-		eloop_destroy();
+		wpa_supplicant_deinit(global);
 		return NULL;
 	}
 
@@ -2142,14 +2564,13 @@
 
 	if (global->params.wait_for_monitor) {
 		for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
-			wpa_supplicant_ctrl_iface_wait(wpa_s);
+			if (wpa_s->ctrl_iface)
+				wpa_supplicant_ctrl_iface_wait(
+					wpa_s->ctrl_iface);
 	}
 
-	eloop_register_signal(SIGINT, wpa_supplicant_terminate, NULL);
-	eloop_register_signal(SIGTERM, wpa_supplicant_terminate, NULL);
-#ifndef CONFIG_NATIVE_WINDOWS
-	eloop_register_signal(SIGHUP, wpa_supplicant_reconfig, NULL);
-#endif /* CONFIG_NATIVE_WINDOWS */
+	eloop_register_signal_terminate(wpa_supplicant_terminate, NULL);
+	eloop_register_signal_reconfig(wpa_supplicant_reconfig, NULL);
 
 	eloop_run();
 
@@ -2172,15 +2593,21 @@
 	while (global->ifaces)
 		wpa_supplicant_remove_iface(global, global->ifaces);
 
-	wpa_supplicant_global_ctrl_iface_deinit(global);
+	if (global->ctrl_iface)
+		wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
+	if (global->dbus_ctrl_iface)
+		wpa_supplicant_dbus_ctrl_iface_deinit(global->dbus_ctrl_iface);
+
+	eap_peer_unregister_methods();
 
 	eloop_destroy();
 
 	if (global->params.pid_file) {
-		unlink(global->params.pid_file);
-		free(global->params.pid_file);
+		os_daemonize_terminate(global->params.pid_file);
+		os_free(global->params.pid_file);
 	}
-	free(global->params.ctrl_interface);
+	os_free(global->params.ctrl_interface);
 
-	free(global);
+	os_free(global);
+	wpa_debug_close_file();
 }
Index: pcsc_funcs.h
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/pcsc_funcs.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/pcsc_funcs.h -L contrib/wpa_supplicant/pcsc_funcs.h -u -r1.2 -r1.3
--- contrib/wpa_supplicant/pcsc_funcs.h
+++ contrib/wpa_supplicant/pcsc_funcs.h
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant / PC/SC smartcard interface for USIM, GSM SIM
- * Copyright (c) 2004-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2004-2006, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -26,6 +26,7 @@
 #define SCARD_FILE_GSM_DF	0x7F20
 #define SCARD_FILE_UMTS_DF	0x7F50
 #define SCARD_FILE_GSM_EF_IMSI	0x6F07
+#define SCARD_FILE_EF_DIR	0x2F00
 #define SCARD_FILE_EF_ICCID	0x2FE2
 #define SCARD_FILE_EF_CK	0x6FE1
 #define SCARD_FILE_EF_IK	0x6FE2
@@ -46,10 +47,11 @@
 
 int scard_set_pin(struct scard_data *scard, const char *pin);
 int scard_get_imsi(struct scard_data *scard, char *imsi, size_t *len);
-int scard_gsm_auth(struct scard_data *scard, unsigned char *rand,
+int scard_gsm_auth(struct scard_data *scard, const unsigned char *_rand,
 		   unsigned char *sres, unsigned char *kc);
-int scard_umts_auth(struct scard_data *scard, unsigned char *rand,
-		    unsigned char *autn, unsigned char *res, size_t *res_len,
+int scard_umts_auth(struct scard_data *scard, const unsigned char *_rand,
+		    const unsigned char *autn,
+		    unsigned char *res, size_t *res_len,
 		    unsigned char *ik, unsigned char *ck, unsigned char *auts);
 
 #else /* PCSC_FUNCS */
Index: eap.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/eap.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/eap.c -L contrib/wpa_supplicant/eap.c -u -r1.2 -r1.3
--- contrib/wpa_supplicant/eap.c
+++ contrib/wpa_supplicant/eap.c
@@ -1,6 +1,6 @@
 /*
- * WPA Supplicant / EAP state machines (RFC 4137)
- * Copyright (c) 2004-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * EAP peer state machines (RFC 4137)
+ * Copyright (c) 2004-2006, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -10,160 +10,47 @@
  * license.
  *
  * See README and COPYING for more details.
+ *
+ * This file implements the Peer State Machine as defined in RFC 4137. The used
+ * states and state transitions match mostly with the RFC. However, there are
+ * couple of additional transitions for working around small issues noticed
+ * during testing. These exceptions are explained in comments within the
+ * functions in this file. The method functions, m.func(), are similar to the
+ * ones used in RFC 4137, but some small changes have used here to optimize
+ * operations and to add functionality needed for fast re-authentication
+ * (session resumption).
  */
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
+#include "includes.h"
 
 #include "common.h"
 #include "eap_i.h"
-#include "wpa_supplicant.h"
 #include "config_ssid.h"
 #include "tls.h"
 #include "crypto.h"
 #include "pcsc_funcs.h"
 #include "wpa_ctrl.h"
+#include "state_machine.h"
 
+#define STATE_MACHINE_DATA struct eap_sm
+#define STATE_MACHINE_DEBUG_PREFIX "EAP"
 
 #define EAP_MAX_AUTH_ROUNDS 50
 
 
-#ifdef EAP_MD5
-extern const struct eap_method eap_method_md5;
-#endif
-#ifdef EAP_TLS
-extern const struct eap_method eap_method_tls;
-#endif
-#ifdef EAP_MSCHAPv2
-extern const struct eap_method eap_method_mschapv2;
-#endif
-#ifdef EAP_PEAP
-extern const struct eap_method eap_method_peap;
-#endif
-#ifdef EAP_TTLS
-extern const struct eap_method eap_method_ttls;
-#endif
-#ifdef EAP_GTC
-extern const struct eap_method eap_method_gtc;
-#endif
-#ifdef EAP_OTP
-extern const struct eap_method eap_method_otp;
-#endif
-#ifdef EAP_SIM
-extern const struct eap_method eap_method_sim;
-#endif
-#ifdef EAP_LEAP
-extern const struct eap_method eap_method_leap;
-#endif
-#ifdef EAP_PSK
-extern const struct eap_method eap_method_psk;
-#endif
-#ifdef EAP_AKA
-extern const struct eap_method eap_method_aka;
-#endif
-#ifdef EAP_FAST
-extern const struct eap_method eap_method_fast;
-#endif
-#ifdef EAP_PAX
-extern const struct eap_method eap_method_pax;
-#endif
-
-static const struct eap_method *eap_methods[] =
-{
-#ifdef EAP_MD5
-	&eap_method_md5,
-#endif
-#ifdef EAP_TLS
-	&eap_method_tls,
-#endif
-#ifdef EAP_MSCHAPv2
-	&eap_method_mschapv2,
-#endif
-#ifdef EAP_PEAP
-	&eap_method_peap,
-#endif
-#ifdef EAP_TTLS
-	&eap_method_ttls,
-#endif
-#ifdef EAP_GTC
-	&eap_method_gtc,
-#endif
-#ifdef EAP_OTP
-	&eap_method_otp,
-#endif
-#ifdef EAP_SIM
-	&eap_method_sim,
-#endif
-#ifdef EAP_LEAP
-	&eap_method_leap,
-#endif
-#ifdef EAP_PSK
-	&eap_method_psk,
-#endif
-#ifdef EAP_AKA
-	&eap_method_aka,
-#endif
-#ifdef EAP_FAST
-	&eap_method_fast,
-#endif
-#ifdef EAP_PAX
-	&eap_method_pax,
-#endif
-};
-#define NUM_EAP_METHODS (sizeof(eap_methods) / sizeof(eap_methods[0]))
-
-
-/**
- * eap_sm_get_eap_methods - Get EAP method based on type number
- * @method: EAP type number
- * Returns: Pointer to EAP method of %NULL if not found
- */
-const struct eap_method * eap_sm_get_eap_methods(int method)
-{
-	int i;
-	for (i = 0; i < NUM_EAP_METHODS; i++) {
-		if (eap_methods[i]->method == method)
-			return eap_methods[i];
-	}
-	return NULL;
-}
-
-
-static Boolean eap_sm_allowMethod(struct eap_sm *sm, EapType method);
+static Boolean eap_sm_allowMethod(struct eap_sm *sm, int vendor,
+				  EapType method);
 static u8 * eap_sm_buildNak(struct eap_sm *sm, int id, size_t *len);
-static void eap_sm_processIdentity(struct eap_sm *sm, const u8 *req,
-				   size_t len);
-static void eap_sm_processNotify(struct eap_sm *sm, const u8 *req, size_t len);
-static u8 * eap_sm_buildNotify(struct eap_sm *sm, int id, size_t *len);
+static void eap_sm_processIdentity(struct eap_sm *sm, const u8 *req);
+static void eap_sm_processNotify(struct eap_sm *sm, const u8 *req);
+static u8 * eap_sm_buildNotify(int id, size_t *len);
 static void eap_sm_parseEapReq(struct eap_sm *sm, const u8 *req, size_t len);
-static const char * eap_sm_method_state_txt(int state);
-static const char * eap_sm_decision_txt(int decision);
+#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
+static const char * eap_sm_method_state_txt(EapMethodState state);
+static const char * eap_sm_decision_txt(EapDecision decision);
+#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
 
 
-/* Definitions for clarifying state machine implementation */
-#define SM_STATE(machine, state) \
-static void sm_ ## machine ## _ ## state ## _Enter(struct eap_sm *sm, \
-	int global)
-
-#define SM_ENTRY(machine, state) \
-if (!global || sm->machine ## _state != machine ## _ ## state) { \
-	sm->changed = TRUE; \
-	wpa_printf(MSG_DEBUG, "EAP: " #machine " entering state " #state); \
-} \
-sm->machine ## _state = machine ## _ ## state;
-
-#define SM_ENTER(machine, state) \
-sm_ ## machine ## _ ## state ## _Enter(sm, 0)
-#define SM_ENTER_GLOBAL(machine, state) \
-sm_ ## machine ## _ ## state ## _Enter(sm, 1)
-
-#define SM_STEP(machine) \
-static void sm_ ## machine ## _Step(struct eap_sm *sm)
-
-#define SM_STEP_RUN(machine) sm_ ## machine ## _Step(sm)
-
 
 static Boolean eapol_get_bool(struct eap_sm *sm, enum eapol_bool_var var)
 {
@@ -210,6 +97,11 @@
 }
 
 
+/*
+ * This state initializes state machine variables when the machine is
+ * activated (portEnabled = TRUE). This is also used when re-starting
+ * authentication (eapRestart == TRUE).
+ */
 SM_STATE(EAP, INITIALIZE)
 {
 	SM_ENTRY(EAP, INITIALIZE);
@@ -228,7 +120,7 @@
 	eapol_set_int(sm, EAPOL_idleWhile, sm->ClientTimeout);
 	eapol_set_bool(sm, EAPOL_eapSuccess, FALSE);
 	eapol_set_bool(sm, EAPOL_eapFail, FALSE);
-	free(sm->eapKeyData);
+	os_free(sm->eapKeyData);
 	sm->eapKeyData = NULL;
 	sm->eapKeyAvailable = FALSE;
 	eapol_set_bool(sm, EAPOL_eapRestart, FALSE);
@@ -248,6 +140,11 @@
 }
 
 
+/*
+ * This state is reached whenever service from the lower layer is interrupted
+ * or unavailable (portEnabled == FALSE). Immediate transition to INITIALIZE
+ * occurs when the port becomes enabled.
+ */
 SM_STATE(EAP, DISABLED)
 {
 	SM_ENTRY(EAP, DISABLED);
@@ -255,12 +152,21 @@
 }
 
 
+/*
+ * The state machine spends most of its time here, waiting for something to
+ * happen. This state is entered unconditionally from INITIALIZE, DISCARD, and
+ * SEND_RESPONSE states.
+ */
 SM_STATE(EAP, IDLE)
 {
 	SM_ENTRY(EAP, IDLE);
 }
 
 
+/*
+ * This state is entered when an EAP packet is received (eapReq == TRUE) to
+ * parse the packet header.
+ */
 SM_STATE(EAP, RECEIVED)
 {
 	const u8 *eapReqData;
@@ -274,72 +180,110 @@
 }
 
 
+/*
+ * This state is entered when a request for a new type comes in. Either the
+ * correct method is started, or a Nak response is built.
+ */
 SM_STATE(EAP, GET_METHOD)
 {
+	int reinit;
+	EapType method;
+
 	SM_ENTRY(EAP, GET_METHOD);
-	if (eap_sm_allowMethod(sm, sm->reqMethod)) {
-		int reinit = 0;
-		if (sm->fast_reauth &&
-		    sm->m && sm->m->method == sm->reqMethod &&
-		    sm->m->has_reauth_data &&
-		    sm->m->has_reauth_data(sm, sm->eap_method_priv)) {
-			wpa_printf(MSG_DEBUG, "EAP: using previous method data"
-				   " for fast re-authentication");
-			reinit = 1;
-		} else
-			eap_deinit_prev_method(sm, "GET_METHOD");
-		sm->selectedMethod = sm->reqMethod;
-		if (sm->m == NULL)
-			sm->m = eap_sm_get_eap_methods(sm->selectedMethod);
-		if (sm->m) {
-			wpa_printf(MSG_DEBUG, "EAP: initialize selected EAP "
-				   "method (%d, %s)",
-				   sm->selectedMethod, sm->m->name);
-			if (reinit)
-				sm->eap_method_priv = sm->m->init_for_reauth(
-					sm, sm->eap_method_priv);
-			else
-				sm->eap_method_priv = sm->m->init(sm);
-			if (sm->eap_method_priv == NULL) {
-				struct wpa_ssid *config = eap_get_config(sm);
-				wpa_msg(sm->msg_ctx, MSG_INFO,
-					"EAP: Failed to initialize EAP method "
-					"%d (%s)",
-					sm->selectedMethod, sm->m->name);
-				sm->m = NULL;
-				sm->methodState = METHOD_NONE;
-				sm->selectedMethod = EAP_TYPE_NONE;
-				if (sm->reqMethod == EAP_TYPE_TLS &&
-				    config &&
-				    (config->pending_req_pin ||
-				     config->pending_req_passphrase)) {
-					/*
-					 * Return without generating Nak in
-					 * order to allow entering of PIN code
-					 * or passphrase to retry the current
-					 * EAP packet.
-					 */
-					wpa_printf(MSG_DEBUG, "EAP: Pending "
-						   "PIN/passphrase request - "
-						   "skip Nak");
-					return;
-				}
-			} else {
-				sm->methodState = METHOD_INIT;
-				wpa_msg(sm->msg_ctx, MSG_INFO,
-					WPA_EVENT_EAP_METHOD
-					"EAP method %d (%s) selected",
-					sm->selectedMethod, sm->m->name);
-				return;
-			}
+
+	if (sm->reqMethod == EAP_TYPE_EXPANDED)
+		method = sm->reqVendorMethod;
+	else
+		method = sm->reqMethod;
+
+	if (!eap_sm_allowMethod(sm, sm->reqVendor, method)) {
+		wpa_printf(MSG_DEBUG, "EAP: vendor %u method %u not allowed",
+			   sm->reqVendor, method);
+		goto nak;
+	}
+
+	/*
+	 * RFC 4137 does not define specific operation for fast
+	 * re-authentication (session resumption). The design here is to allow
+	 * the previously used method data to be maintained for
+	 * re-authentication if the method support session resumption.
+	 * Otherwise, the previously used method data is freed and a new method
+	 * is allocated here.
+	 */
+	if (sm->fast_reauth &&
+	    sm->m && sm->m->vendor == sm->reqVendor &&
+	    sm->m->method == method &&
+	    sm->m->has_reauth_data &&
+	    sm->m->has_reauth_data(sm, sm->eap_method_priv)) {
+		wpa_printf(MSG_DEBUG, "EAP: Using previous method data"
+			   " for fast re-authentication");
+		reinit = 1;
+	} else {
+		eap_deinit_prev_method(sm, "GET_METHOD");
+		reinit = 0;
+	}
+
+	sm->selectedMethod = sm->reqMethod;
+	if (sm->m == NULL)
+		sm->m = eap_sm_get_eap_methods(sm->reqVendor, method);
+	if (!sm->m) {
+		wpa_printf(MSG_DEBUG, "EAP: Could not find selected method: "
+			   "vendor %d method %d",
+			   sm->reqVendor, method);
+		goto nak;
+	}
+
+	wpa_printf(MSG_DEBUG, "EAP: Initialize selected EAP method: "
+		   "vendor %u method %u (%s)",
+		   sm->reqVendor, method, sm->m->name);
+	if (reinit)
+		sm->eap_method_priv = sm->m->init_for_reauth(
+			sm, sm->eap_method_priv);
+	else
+		sm->eap_method_priv = sm->m->init(sm);
+
+	if (sm->eap_method_priv == NULL) {
+		struct wpa_ssid *config = eap_get_config(sm);
+		wpa_msg(sm->msg_ctx, MSG_INFO,
+			"EAP: Failed to initialize EAP method: vendor %u "
+			"method %u (%s)",
+			sm->reqVendor, method, sm->m->name);
+		sm->m = NULL;
+		sm->methodState = METHOD_NONE;
+		sm->selectedMethod = EAP_TYPE_NONE;
+		if (sm->reqMethod == EAP_TYPE_TLS && config &&
+		    (config->pending_req_pin ||
+		     config->pending_req_passphrase)) {
+			/*
+			 * Return without generating Nak in order to allow
+			 * entering of PIN code or passphrase to retry the
+			 * current EAP packet.
+			 */
+			wpa_printf(MSG_DEBUG, "EAP: Pending PIN/passphrase "
+				   "request - skip Nak");
+			return;
 		}
+
+		goto nak;
 	}
 
-	free(sm->eapRespData);
+	sm->methodState = METHOD_INIT;
+	wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_METHOD
+		"EAP vendor %u method %u (%s) selected",
+		sm->reqVendor, method, sm->m->name);
+	return;
+
+nak:
+	os_free(sm->eapRespData);
+	sm->eapRespData = NULL;
 	sm->eapRespData = eap_sm_buildNak(sm, sm->reqId, &sm->eapRespDataLen);
 }
 
 
+/*
+ * The method processing happens here. The request from the authenticator is
+ * processed, and an appropriate response packet is built.
+ */
 SM_STATE(EAP, METHOD)
 {
 	u8 *eapReqData;
@@ -354,14 +298,27 @@
 
 	eapReqData = eapol_get_eapReqData(sm, &eapReqDataLen);
 
-	/* Get ignore, methodState, decision, allowNotifications, and
-	 * eapRespData. */
-	memset(&ret, 0, sizeof(ret));
+	/*
+	 * Get ignore, methodState, decision, allowNotifications, and
+	 * eapRespData. RFC 4137 uses three separate method procedure (check,
+	 * process, and buildResp) in this state. These have been combined into
+	 * a single function call to m->process() in order to optimize EAP
+	 * method implementation interface a bit. These procedures are only
+	 * used from within this METHOD state, so there is no need to keep
+	 * these as separate C functions.
+	 *
+	 * The RFC 4137 procedures return values as follows:
+	 * ignore = m.check(eapReqData)
+	 * (methodState, decision, allowNotifications) = m.process(eapReqData)
+	 * eapRespData = m.buildResp(reqId)
+	 */
+	os_memset(&ret, 0, sizeof(ret));
 	ret.ignore = sm->ignore;
 	ret.methodState = sm->methodState;
 	ret.decision = sm->decision;
 	ret.allowNotifications = sm->allowNotifications;
-	free(sm->eapRespData);
+	os_free(sm->eapRespData);
+	sm->eapRespData = NULL;
 	sm->eapRespData = sm->m->process(sm, sm->eap_method_priv, &ret,
 					 eapReqData, eapReqDataLen,
 					 &sm->eapRespDataLen);
@@ -380,25 +337,29 @@
 
 	if (sm->m->isKeyAvailable && sm->m->getKey &&
 	    sm->m->isKeyAvailable(sm, sm->eap_method_priv)) {
-		free(sm->eapKeyData);
+		os_free(sm->eapKeyData);
 		sm->eapKeyData = sm->m->getKey(sm, sm->eap_method_priv,
 					       &sm->eapKeyDataLen);
 	}
 }
 
 
+/*
+ * This state signals the lower layer that a response packet is ready to be
+ * sent.
+ */
 SM_STATE(EAP, SEND_RESPONSE)
 {
 	SM_ENTRY(EAP, SEND_RESPONSE);
-	free(sm->lastRespData);
+	os_free(sm->lastRespData);
 	if (sm->eapRespData) {
 		if (sm->workaround)
-			memcpy(sm->last_md5, sm->req_md5, 16);
+			os_memcpy(sm->last_md5, sm->req_md5, 16);
 		sm->lastId = sm->reqId;
-		sm->lastRespData = malloc(sm->eapRespDataLen);
+		sm->lastRespData = os_malloc(sm->eapRespDataLen);
 		if (sm->lastRespData) {
-			memcpy(sm->lastRespData, sm->eapRespData,
-			       sm->eapRespDataLen);
+			os_memcpy(sm->lastRespData, sm->eapRespData,
+				  sm->eapRespDataLen);
 			sm->lastRespDataLen = sm->eapRespDataLen;
 		}
 		eapol_set_bool(sm, EAPOL_eapResp, TRUE);
@@ -409,6 +370,10 @@
 }
 
 
+/*
+ * This state signals the lower layer that the request was discarded, and no
+ * response packet will be sent at this time.
+ */
 SM_STATE(EAP, DISCARD)
 {
 	SM_ENTRY(EAP, DISCARD);
@@ -417,6 +382,9 @@
 }
 
 
+/*
+ * Handles requests for Identity method and builds a response.
+ */
 SM_STATE(EAP, IDENTITY)
 {
 	const u8 *eapReqData;
@@ -424,13 +392,17 @@
 
 	SM_ENTRY(EAP, IDENTITY);
 	eapReqData = eapol_get_eapReqData(sm, &eapReqDataLen);
-	eap_sm_processIdentity(sm, eapReqData, eapReqDataLen);
-	free(sm->eapRespData);
+	eap_sm_processIdentity(sm, eapReqData);
+	os_free(sm->eapRespData);
+	sm->eapRespData = NULL;
 	sm->eapRespData = eap_sm_buildIdentity(sm, sm->reqId,
 					       &sm->eapRespDataLen, 0);
 }
 
 
+/*
+ * Handles requests for Notification method and builds a response.
+ */
 SM_STATE(EAP, NOTIFICATION)
 {
 	const u8 *eapReqData;
@@ -438,22 +410,25 @@
 
 	SM_ENTRY(EAP, NOTIFICATION);
 	eapReqData = eapol_get_eapReqData(sm, &eapReqDataLen);
-	eap_sm_processNotify(sm, eapReqData, eapReqDataLen);
-	free(sm->eapRespData);
-	sm->eapRespData = eap_sm_buildNotify(sm, sm->reqId,
-					     &sm->eapRespDataLen);
+	eap_sm_processNotify(sm, eapReqData);
+	os_free(sm->eapRespData);
+	sm->eapRespData = NULL;
+	sm->eapRespData = eap_sm_buildNotify(sm->reqId, &sm->eapRespDataLen);
 }
 
 
+/*
+ * This state retransmits the previous response packet.
+ */
 SM_STATE(EAP, RETRANSMIT)
 {
 	SM_ENTRY(EAP, RETRANSMIT);
-	free(sm->eapRespData);
+	os_free(sm->eapRespData);
 	if (sm->lastRespData) {
-		sm->eapRespData = malloc(sm->lastRespDataLen);
+		sm->eapRespData = os_malloc(sm->lastRespDataLen);
 		if (sm->eapRespData) {
-			memcpy(sm->eapRespData, sm->lastRespData,
-			       sm->lastRespDataLen);
+			os_memcpy(sm->eapRespData, sm->lastRespData,
+				  sm->lastRespDataLen);
 			sm->eapRespDataLen = sm->lastRespDataLen;
 		}
 	} else
@@ -461,6 +436,11 @@
 }
 
 
+/*
+ * This state is entered in case of a successful completion of authentication
+ * and state machine waits here until port is disabled or EAP authentication is
+ * restarted.
+ */
 SM_STATE(EAP, SUCCESS)
 {
 	SM_ENTRY(EAP, SUCCESS);
@@ -488,6 +468,10 @@
 }
 
 
+/*
+ * This state is entered in case of a failure and state machine waits here
+ * until port is disabled or EAP authentication is restarted.
+ */
 SM_STATE(EAP, FAILURE)
 {
 	SM_ENTRY(EAP, FAILURE);
@@ -538,6 +522,9 @@
 }
 
 
+/*
+ * RFC 4137 - Appendix A.1: EAP Peer State Machine - State transitions
+ */
 SM_STEP(EAP)
 {
 	int duplicate;
@@ -548,6 +535,14 @@
 	else if (!eapol_get_bool(sm, EAPOL_portEnabled) || sm->force_disabled)
 		SM_ENTER_GLOBAL(EAP, DISABLED);
 	else if (sm->num_rounds > EAP_MAX_AUTH_ROUNDS) {
+		/* RFC 4137 does not place any limit on number of EAP messages
+		 * in an authentication session. However, some error cases have
+		 * ended up in a state were EAP messages were sent between the
+		 * peer and server in a loop (e.g., TLS ACK frame in both
+		 * direction). Since this is quite undesired outcome, limit the
+		 * total number of EAP round-trips and abort authentication if
+		 * this limit is exceeded.
+		 */
 		if (sm->num_rounds == EAP_MAX_AUTH_ROUNDS + 1) {
 			wpa_msg(sm->msg_ctx, MSG_INFO, "EAP: more than %d "
 				"authentication rounds - abort",
@@ -565,6 +560,11 @@
 			SM_ENTER(EAP, INITIALIZE);
 		break;
 	case EAP_IDLE:
+		/*
+		 * The first three transitions are from RFC 4137. The last two
+		 * are local additions to handle special cases with LEAP and
+		 * PEAP server not sending EAP-Success in some cases.
+		 */
 		if (eapol_get_bool(sm, EAPOL_eapReq))
 			SM_ENTER(EAP, RECEIVED);
 		else if ((eapol_get_bool(sm, EAPOL_altAccept) &&
@@ -591,7 +591,7 @@
 	case EAP_RECEIVED:
 		duplicate = (sm->reqId == sm->lastId) && sm->rxReq;
 		if (sm->workaround && duplicate &&
-		    memcmp(sm->req_md5, sm->last_md5, 16) != 0) {
+		    os_memcmp(sm->req_md5, sm->last_md5, 16) != 0) {
 			/*
 			 * RFC 4137 uses (reqId == lastId) as the only
 			 * verification for duplicate EAP requests. However,
@@ -608,10 +608,15 @@
 			duplicate = 0;
 		}
 
-		if (sm->rxSuccess &&
+		/*
+		 * Two special cases below for LEAP are local additions to work
+		 * around odd LEAP behavior (EAP-Success in the middle of
+		 * authentication and then swapped roles). Other transitions
+		 * are based on RFC 4137.
+		 */
+		if (sm->rxSuccess && sm->decision != DECISION_FAIL &&
 		    (sm->reqId == sm->lastId ||
-		     eap_success_workaround(sm, sm->reqId, sm->lastId)) &&
-		    sm->decision != DECISION_FAIL)
+		     eap_success_workaround(sm, sm->reqId, sm->lastId)))
 			SM_ENTER(EAP, SUCCESS);
 		else if (sm->methodState != METHOD_CONT &&
 			 ((sm->rxFailure &&
@@ -682,32 +687,108 @@
 }
 
 
-static Boolean eap_sm_allowMethod(struct eap_sm *sm, EapType method)
+static Boolean eap_sm_allowMethod(struct eap_sm *sm, int vendor,
+				  EapType method)
 {
 	struct wpa_ssid *config = eap_get_config(sm);
-	int i;
 
-	if (!wpa_config_allowed_eap_method(config, method))
+	if (!wpa_config_allowed_eap_method(config, vendor, method)) {
+		wpa_printf(MSG_DEBUG, "EAP: configuration does not allow: "
+			   "vendor %u method %u", vendor, method);
 		return FALSE;
-	for (i = 0; i < NUM_EAP_METHODS; i++) {
-		if (eap_methods[i]->method == method)
-			return TRUE;
 	}
+	if (eap_sm_get_eap_methods(vendor, method))
+		return TRUE;
+	wpa_printf(MSG_DEBUG, "EAP: not included in build: "
+		   "vendor %u method %u", vendor, method);
 	return FALSE;
 }
 
 
-static u8 *eap_sm_buildNak(struct eap_sm *sm, int id, size_t *len)
+static u8 * eap_sm_build_expanded_nak(struct eap_sm *sm, int id, size_t *len,
+				      const struct eap_method *methods,
+				      size_t count)
 {
 	struct wpa_ssid *config = eap_get_config(sm);
 	struct eap_hdr *resp;
 	u8 *pos;
-	int i, found = 0;
+	int found = 0;
+	const struct eap_method *m;
 
-	wpa_printf(MSG_DEBUG, "EAP: Building EAP-Nak (requested type %d not "
-		   "allowed)", sm->reqMethod);
+	wpa_printf(MSG_DEBUG, "EAP: Building expanded EAP-Nak");
+
+	/* RFC 3748 - 5.3.2: Expanded Nak */
+	*len = sizeof(struct eap_hdr) + 8;
+	resp = os_malloc(*len + 8 * (count + 1));
+	if (resp == NULL)
+		return NULL;
+
+	resp->code = EAP_CODE_RESPONSE;
+	resp->identifier = id;
+	pos = (u8 *) (resp + 1);
+	*pos++ = EAP_TYPE_EXPANDED;
+	WPA_PUT_BE24(pos, EAP_VENDOR_IETF);
+	pos += 3;
+	WPA_PUT_BE32(pos, EAP_TYPE_NAK);
+	pos += 4;
+
+	for (m = methods; m; m = m->next) {
+		if (sm->reqVendor == m->vendor &&
+		    sm->reqVendorMethod == m->method)
+			continue; /* do not allow the current method again */
+		if (wpa_config_allowed_eap_method(config, m->vendor,
+						  m->method)) {
+			wpa_printf(MSG_DEBUG, "EAP: allowed type: "
+				   "vendor=%u method=%u",
+				   m->vendor, m->method);
+			*pos++ = EAP_TYPE_EXPANDED;
+			WPA_PUT_BE24(pos, m->vendor);
+			pos += 3;
+			WPA_PUT_BE32(pos, m->method);
+			pos += 4;
+
+			(*len) += 8;
+			found++;
+		}
+	}
+	if (!found) {
+		wpa_printf(MSG_DEBUG, "EAP: no more allowed methods");
+		*pos++ = EAP_TYPE_EXPANDED;
+		WPA_PUT_BE24(pos, EAP_VENDOR_IETF);
+		pos += 3;
+		WPA_PUT_BE32(pos, EAP_TYPE_NONE);
+		pos += 4;
+
+		(*len) += 8;
+	}
+
+	resp->length = host_to_be16(*len);
+
+	return (u8 *) resp;
+}
+
+
+static u8 * eap_sm_buildNak(struct eap_sm *sm, int id, size_t *len)
+{
+	struct wpa_ssid *config = eap_get_config(sm);
+	struct eap_hdr *resp;
+	u8 *pos;
+	int found = 0, expanded_found = 0;
+	size_t count;
+	const struct eap_method *methods, *m;
+
+	wpa_printf(MSG_DEBUG, "EAP: Building EAP-Nak (requested type %u "
+		   "vendor=%u method=%u not allowed)", sm->reqMethod,
+		   sm->reqVendor, sm->reqVendorMethod);
+	methods = eap_peer_get_methods(&count);
+	if (methods == NULL)
+		return NULL;
+	if (sm->reqMethod == EAP_TYPE_EXPANDED)
+		return eap_sm_build_expanded_nak(sm, id, len, methods, count);
+
+	/* RFC 3748 - 5.3.1: Legacy Nak */
 	*len = sizeof(struct eap_hdr) + 1;
-	resp = malloc(*len + NUM_EAP_METHODS);
+	resp = os_malloc(*len + count + 1);
 	if (resp == NULL)
 		return NULL;
 
@@ -716,11 +797,18 @@
 	pos = (u8 *) (resp + 1);
 	*pos++ = EAP_TYPE_NAK;
 
-	for (i = 0; i < NUM_EAP_METHODS; i++) {
-		if (eap_methods[i]->method != sm->reqMethod &&
-		    wpa_config_allowed_eap_method(config,
-						  eap_methods[i]->method)) {
-			*pos++ = eap_methods[i]->method;
+	for (m = methods; m; m = m->next) {
+		if (m->vendor == EAP_VENDOR_IETF && m->method == sm->reqMethod)
+			continue; /* do not allow the current method again */
+		if (wpa_config_allowed_eap_method(config, m->vendor,
+						  m->method)) {
+			if (m->vendor != EAP_VENDOR_IETF) {
+				if (expanded_found)
+					continue;
+				expanded_found = 1;
+				*pos++ = EAP_TYPE_EXPANDED;
+			} else
+				*pos++ = m->method;
 			(*len)++;
 			found++;
 		}
@@ -738,8 +826,7 @@
 }
 
 
-static void eap_sm_processIdentity(struct eap_sm *sm, const u8 *req,
-				   size_t len)
+static void eap_sm_processIdentity(struct eap_sm *sm, const u8 *req)
 {
 	const struct eap_hdr *hdr = (const struct eap_hdr *) req;
 	const u8 *pos = (const u8 *) (hdr + 1);
@@ -748,6 +835,13 @@
 	wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_STARTED
 		"EAP authentication started");
 
+	/*
+	 * RFC 3748 - 5.1: Identity
+	 * Data field may contain a displayable message in UTF-8. If this
+	 * includes NUL-character, only the data before that should be
+	 * displayed. Some EAP implementasitons may piggy-back additional
+	 * options after the NUL.
+	 */
 	/* TODO: could save displayable message so that it can be shown to the
 	 * user in case of interaction is required */
 	wpa_hexdump_ascii(MSG_DEBUG, "EAP: EAP-Request Identity data",
@@ -755,12 +849,14 @@
 }
 
 
+#ifdef PCSC_FUNCS
 static int eap_sm_imsi_identity(struct eap_sm *sm, struct wpa_ssid *ssid)
 {
 	int aka = 0;
 	char imsi[100];
 	size_t imsi_len;
-	u8 *pos = ssid->eap_methods;
+	struct eap_method_type *m = ssid->eap_methods;
+	int i;
 
 	imsi_len = sizeof(imsi);
 	if (scard_get_imsi(sm->scard_ctx, imsi, &imsi_len)) {
@@ -770,16 +866,17 @@
 
 	wpa_hexdump_ascii(MSG_DEBUG, "IMSI", (u8 *) imsi, imsi_len);
 
-	while (pos && *pos != EAP_TYPE_NONE) {
-		if (*pos == EAP_TYPE_AKA) {
+	for (i = 0; m && (m[i].vendor != EAP_VENDOR_IETF ||
+			  m[i].method != EAP_TYPE_NONE); i++) {
+		if (m[i].vendor == EAP_VENDOR_IETF &&
+		    m[i].method == EAP_TYPE_AKA) {
 			aka = 1;
 			break;
 		}
-		pos++;
 	}
 
-	free(ssid->identity);
-	ssid->identity = malloc(1 + imsi_len);
+	os_free(ssid->identity);
+	ssid->identity = os_malloc(1 + imsi_len);
 	if (ssid->identity == NULL) {
 		wpa_printf(MSG_WARNING, "Failed to allocate buffer for "
 			   "IMSI-based identity");
@@ -787,28 +884,34 @@
 	}
 
 	ssid->identity[0] = aka ? '0' : '1';
-	memcpy(ssid->identity + 1, imsi, imsi_len);
+	os_memcpy(ssid->identity + 1, imsi, imsi_len);
 	ssid->identity_len = 1 + imsi_len;
+
 	return 0;
 }
+#endif /* PCSC_FUNCS */
 
 
 static int eap_sm_get_scard_identity(struct eap_sm *sm, struct wpa_ssid *ssid)
 {
+#ifdef PCSC_FUNCS
 	if (scard_set_pin(sm->scard_ctx, ssid->pin)) {
 		/*
 		 * Make sure the same PIN is not tried again in order to avoid
 		 * blocking SIM.
 		 */
-		free(ssid->pin);
+		os_free(ssid->pin);
 		ssid->pin = NULL;
 
 		wpa_printf(MSG_WARNING, "PIN validation failed");
-		eap_sm_request_pin(sm, ssid);
+		eap_sm_request_pin(sm);
 		return -1;
 	}
 
 	return eap_sm_imsi_identity(sm, ssid);
+#else /* PCSC_FUNCS */
+	return -1;
+#endif /* PCSC_FUNCS */
 }
 
 
@@ -816,8 +919,8 @@
  * eap_sm_buildIdentity - Build EAP-Identity/Response for the current network
  * @sm: Pointer to EAP state machine allocated with eap_sm_init()
  * @id: EAP identifier for the packet
- * @len: Pointer to variable that will be set to the length of the response
- * @encrypted: Whether the packet is for enrypted tunnel (EAP phase 2)
+ * @len: Pointer to a variable that will be set to the length of the response
+ * @encrypted: Whether the packet is for encrypted tunnel (EAP phase 2)
  * Returns: Pointer to the allocated EAP-Identity/Response packet or %NULL on
  * failure
  *
@@ -867,14 +970,13 @@
 			wpa_hexdump_ascii(MSG_DEBUG, "permanent identity from "
 					  "IMSI", identity, identity_len);
 		} else {
-			eap_sm_request_identity(sm, config);
+			eap_sm_request_identity(sm);
 			return NULL;
 		}
 	}
 
-
 	*len = sizeof(struct eap_hdr) + 1 + identity_len;
-	resp = malloc(*len);
+	resp = os_malloc(*len);
 	if (resp == NULL)
 		return NULL;
 
@@ -883,19 +985,18 @@
 	resp->length = host_to_be16(*len);
 	pos = (u8 *) (resp + 1);
 	*pos++ = EAP_TYPE_IDENTITY;
-	memcpy(pos, identity, identity_len);
+	os_memcpy(pos, identity, identity_len);
 
 	return (u8 *) resp;
 }
 
 
-static void eap_sm_processNotify(struct eap_sm *sm, const u8 *req, size_t len)
+static void eap_sm_processNotify(struct eap_sm *sm, const u8 *req)
 {
 	const struct eap_hdr *hdr = (const struct eap_hdr *) req;
 	const u8 *pos;
 	char *msg;
-	size_t msg_len;
-	int i;
+	size_t i, msg_len;
 
 	pos = (const u8 *) (hdr + 1);
 	pos++;
@@ -907,7 +1008,7 @@
 	wpa_hexdump_ascii(MSG_DEBUG, "EAP: EAP-Request Notification data",
 			  pos, msg_len);
 
-	msg = malloc(msg_len + 1);
+	msg = os_malloc(msg_len + 1);
 	if (msg == NULL)
 		return;
 	for (i = 0; i < msg_len; i++)
@@ -915,18 +1016,18 @@
 	msg[msg_len] = '\0';
 	wpa_msg(sm->msg_ctx, MSG_INFO, "%s%s",
 		WPA_EVENT_EAP_NOTIFICATION, msg);
-	free(msg);
+	os_free(msg);
 }
 
 
-static u8 *eap_sm_buildNotify(struct eap_sm *sm, int id, size_t *len)
+static u8 * eap_sm_buildNotify(int id, size_t *len)
 {
 	struct eap_hdr *resp;
 	u8 *pos;
 
 	wpa_printf(MSG_DEBUG, "EAP: Generating EAP-Response Notification");
 	*len = sizeof(struct eap_hdr) + 1;
-	resp = malloc(*len);
+	resp = os_malloc(*len);
 	if (resp == NULL)
 		return NULL;
 
@@ -944,10 +1045,13 @@
 {
 	const struct eap_hdr *hdr;
 	size_t plen;
+	const u8 *pos;
 
-	sm->rxReq = sm->rxSuccess = sm->rxFailure = FALSE;
+	sm->rxReq = sm->rxResp = sm->rxSuccess = sm->rxFailure = FALSE;
 	sm->reqId = 0;
 	sm->reqMethod = EAP_TYPE_NONE;
+	sm->reqVendor = EAP_VENDOR_IETF;
+	sm->reqVendorMethod = EAP_TYPE_NONE;
 
 	if (req == NULL || len < sizeof(*hdr))
 		return;
@@ -964,22 +1068,50 @@
 	sm->reqId = hdr->identifier;
 
 	if (sm->workaround) {
-		md5_vector(1, (const u8 **) &req, &len, sm->req_md5);
+		md5_vector(1, (const u8 **) &req, &plen, sm->req_md5);
 	}
 
 	switch (hdr->code) {
 	case EAP_CODE_REQUEST:
+		if (plen < sizeof(*hdr) + 1) {
+			wpa_printf(MSG_DEBUG, "EAP: Too short EAP-Request - "
+				   "no Type field");
+			return;
+		}
 		sm->rxReq = TRUE;
-		if (plen > sizeof(*hdr))
-			sm->reqMethod = *((u8 *) (hdr + 1));
-		wpa_printf(MSG_DEBUG, "EAP: Received EAP-Request method=%d "
-			   "id=%d", sm->reqMethod, sm->reqId);
+		pos = (const u8 *) (hdr + 1);
+		sm->reqMethod = *pos++;
+		if (sm->reqMethod == EAP_TYPE_EXPANDED) {
+			if (plen < sizeof(*hdr) + 8) {
+				wpa_printf(MSG_DEBUG, "EAP: Ignored truncated "
+					   "expanded EAP-Packet (plen=%lu)",
+					   (unsigned long) plen);
+				return;
+			}
+			sm->reqVendor = WPA_GET_BE24(pos);
+			pos += 3;
+			sm->reqVendorMethod = WPA_GET_BE32(pos);
+		}
+		wpa_printf(MSG_DEBUG, "EAP: Received EAP-Request id=%d "
+			   "method=%u vendor=%u vendorMethod=%u",
+			   sm->reqId, sm->reqMethod, sm->reqVendor,
+			   sm->reqVendorMethod);
 		break;
 	case EAP_CODE_RESPONSE:
 		if (sm->selectedMethod == EAP_TYPE_LEAP) {
+			/*
+			 * LEAP differs from RFC 4137 by using reversed roles
+			 * for mutual authentication and because of this, we
+			 * need to accept EAP-Response frames if LEAP is used.
+			 */
+			if (plen < sizeof(*hdr) + 1) {
+				wpa_printf(MSG_DEBUG, "EAP: Too short "
+					   "EAP-Response - no Type field");
+				return;
+			}
 			sm->rxResp = TRUE;
-			if (plen > sizeof(*hdr))
-				sm->reqMethod = *((u8 *) (hdr + 1));
+			pos = (const u8 *) (hdr + 1);
+			sm->reqMethod = *pos;
 			wpa_printf(MSG_DEBUG, "EAP: Received EAP-Response for "
 				   "LEAP method=%d id=%d",
 				   sm->reqMethod, sm->reqId);
@@ -1012,7 +1144,10 @@
  * Returns: Pointer to the allocated EAP state machine or %NULL on failure
  *
  * This function allocates and initializes an EAP state machine. In addition,
- * this initializes TLS library for the new EAP state machine.
+ * this initializes TLS library for the new EAP state machine. eapol_cb pointer
+ * will be in use until eap_sm_deinit() is used to deinitialize this EAP state
+ * machine. Consequently, the caller must make sure that this data structure
+ * remains alive while the EAP state machine is active.
  */
 struct eap_sm * eap_sm_init(void *eapol_ctx, struct eapol_callbacks *eapol_cb,
 			    void *msg_ctx, struct eap_config *conf)
@@ -1020,16 +1155,15 @@
 	struct eap_sm *sm;
 	struct tls_config tlsconf;
 
-	sm = malloc(sizeof(*sm));
+	sm = os_zalloc(sizeof(*sm));
 	if (sm == NULL)
 		return NULL;
-	memset(sm, 0, sizeof(*sm));
 	sm->eapol_ctx = eapol_ctx;
 	sm->eapol_cb = eapol_cb;
 	sm->msg_ctx = msg_ctx;
 	sm->ClientTimeout = 60;
 
-	memset(&tlsconf, 0, sizeof(tlsconf));
+	os_memset(&tlsconf, 0, sizeof(tlsconf));
 	tlsconf.opensc_engine_path = conf->opensc_engine_path;
 	tlsconf.pkcs11_engine_path = conf->pkcs11_engine_path;
 	tlsconf.pkcs11_module_path = conf->pkcs11_module_path;
@@ -1037,7 +1171,7 @@
 	if (sm->ssl_ctx == NULL) {
 		wpa_printf(MSG_WARNING, "SSL: Failed to initialize TLS "
 			   "context.");
-		free(sm);
+		os_free(sm);
 		return NULL;
 	}
 
@@ -1057,11 +1191,9 @@
 	if (sm == NULL)
 		return;
 	eap_deinit_prev_method(sm, "EAP deinit");
-	free(sm->lastRespData);
-	free(sm->eapRespData);
-	free(sm->eapKeyData);
+	eap_sm_abort(sm);
 	tls_deinit(sm->ssl_ctx);
-	free(sm);
+	os_free(sm);
 }
 
 
@@ -1096,13 +1228,21 @@
  */
 void eap_sm_abort(struct eap_sm *sm)
 {
-	free(sm->eapRespData);
+	os_free(sm->lastRespData);
+	sm->lastRespData = NULL;
+	os_free(sm->eapRespData);
 	sm->eapRespData = NULL;
-	free(sm->eapKeyData);
+	os_free(sm->eapKeyData);
 	sm->eapKeyData = NULL;
+
+	/* This is not clearly specified in the EAP statemachines draft, but
+	 * it seems necessary to make sure that some of the EAPOL variables get
+	 * cleared for the next authentication. */
+	eapol_set_bool(sm, EAPOL_eapSuccess, FALSE);
 }
 
 
+#ifdef CONFIG_CTRL_IFACE
 static const char * eap_sm_state_txt(int state)
 {
 	switch (state) {
@@ -1136,9 +1276,11 @@
 		return "UNKNOWN";
 	}
 }
+#endif /* CONFIG_CTRL_IFACE */
 
 
-static const char * eap_sm_method_state_txt(int state)
+#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
+static const char * eap_sm_method_state_txt(EapMethodState state)
 {
 	switch (state) {
 	case METHOD_NONE:
@@ -1157,7 +1299,7 @@
 }
 
 
-static const char * eap_sm_decision_txt(int decision)
+static const char * eap_sm_decision_txt(EapDecision decision)
 {
 	switch (decision) {
 	case DECISION_FAIL:
@@ -1170,15 +1312,18 @@
 		return "UNKNOWN";
 	}
 }
+#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
+
 
+#ifdef CONFIG_CTRL_IFACE
 
 /**
  * eap_sm_get_status - Get EAP state machine status
  * @sm: Pointer to EAP state machine allocated with eap_sm_init()
- * @buf: buffer for status information
- * @buflen: maximum buffer length
- * @verbose: whether to include verbose status information
- * Returns: number of bytes written to buf.
+ * @buf: Buffer for status information
+ * @buflen: Maximum buffer length
+ * @verbose: Whether to include verbose status information
+ * Returns: Number of bytes written to buf.
  *
  * Query EAP state machine for status information. This function fills in a
  * text area with current status information from the EAPOL state machine. If
@@ -1187,14 +1332,16 @@
  */
 int eap_sm_get_status(struct eap_sm *sm, char *buf, size_t buflen, int verbose)
 {
-	int len;
+	int len, ret;
 
 	if (sm == NULL)
 		return 0;
 
-	len = snprintf(buf, buflen,
-		       "EAP state=%s\n",
-		       eap_sm_state_txt(sm->EAP_state));
+	len = os_snprintf(buf, buflen,
+			  "EAP state=%s\n",
+			  eap_sm_state_txt(sm->EAP_state));
+	if (len < 0 || (size_t) len >= buflen)
+		return 0;
 
 	if (sm->selectedMethod != EAP_TYPE_NONE) {
 		const char *name;
@@ -1202,15 +1349,19 @@
 			name = sm->m->name;
 		} else {
 			const struct eap_method *m =
-				eap_sm_get_eap_methods(sm->selectedMethod);
+				eap_sm_get_eap_methods(EAP_VENDOR_IETF,
+						       sm->selectedMethod);
 			if (m)
 				name = m->name;
 			else
 				name = "?";
 		}
-		len += snprintf(buf + len, buflen - len,
-				"selectedMethod=%d (EAP-%s)\n",
-				sm->selectedMethod, name);
+		ret = os_snprintf(buf + len, buflen - len,
+				  "selectedMethod=%d (EAP-%s)\n",
+				  sm->selectedMethod, name);
+		if (ret < 0 || (size_t) ret >= buflen - len)
+			return len;
+		len += ret;
 
 		if (sm->m && sm->m->get_status) {
 			len += sm->m->get_status(sm, sm->eap_method_priv,
@@ -1220,37 +1371,45 @@
 	}
 
 	if (verbose) {
-		len += snprintf(buf + len, buflen - len,
-				"reqMethod=%d\n"
-				"methodState=%s\n"
-				"decision=%s\n"
-				"ClientTimeout=%d\n",
-				sm->reqMethod,
-				eap_sm_method_state_txt(sm->methodState),
-				eap_sm_decision_txt(sm->decision),
-				sm->ClientTimeout);
+		ret = os_snprintf(buf + len, buflen - len,
+				  "reqMethod=%d\n"
+				  "methodState=%s\n"
+				  "decision=%s\n"
+				  "ClientTimeout=%d\n",
+				  sm->reqMethod,
+				  eap_sm_method_state_txt(sm->methodState),
+				  eap_sm_decision_txt(sm->decision),
+				  sm->ClientTimeout);
+		if (ret < 0 || (size_t) ret >= buflen - len)
+			return len;
+		len += ret;
 	}
 
 	return len;
 }
+#endif /* CONFIG_CTRL_IFACE */
 
 
+#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
 typedef enum {
 	TYPE_IDENTITY, TYPE_PASSWORD, TYPE_OTP, TYPE_PIN, TYPE_NEW_PASSWORD,
 	TYPE_PASSPHRASE
 } eap_ctrl_req_type;
 
-static void eap_sm_request(struct eap_sm *sm, struct wpa_ssid *config,
-			   eap_ctrl_req_type type, const char *msg,
-			   size_t msglen)
+static void eap_sm_request(struct eap_sm *sm, eap_ctrl_req_type type,
+			   const char *msg, size_t msglen)
 {
+	struct wpa_ssid *config;
 	char *buf;
 	size_t buflen;
 	int len;
 	char *field;
 	char *txt, *tmp;
 
-	if (config == NULL || sm == NULL)
+	if (sm == NULL)
+		return;
+	config = eap_get_config(sm);
+	if (config == NULL)
 		return;
 
 	switch (type) {
@@ -1277,15 +1436,15 @@
 	case TYPE_OTP:
 		field = "OTP";
 		if (msg) {
-			tmp = malloc(msglen + 3);
+			tmp = os_malloc(msglen + 3);
 			if (tmp == NULL)
 				return;
 			tmp[0] = '[';
-			memcpy(tmp + 1, msg, msglen);
+			os_memcpy(tmp + 1, msg, msglen);
 			tmp[msglen + 1] = ']';
 			tmp[msglen + 2] = '\0';
 			txt = tmp;
-			free(config->pending_req_otp);
+			os_free(config->pending_req_otp);
 			config->pending_req_otp = tmp;
 			config->pending_req_otp_len = msglen + 3;
 		} else {
@@ -1303,90 +1462,94 @@
 		return;
 	}
 
-	buflen = 100 + strlen(txt) + config->ssid_len;
-	buf = malloc(buflen);
+	buflen = 100 + os_strlen(txt) + config->ssid_len;
+	buf = os_malloc(buflen);
 	if (buf == NULL)
 		return;
-	len = snprintf(buf, buflen, WPA_CTRL_REQ "%s-%d:%s needed for SSID ",
-		       field, config->id, txt);
+	len = os_snprintf(buf, buflen,
+			  WPA_CTRL_REQ "%s-%d:%s needed for SSID ",
+			  field, config->id, txt);
+	if (len < 0 || (size_t) len >= buflen) {
+		os_free(buf);
+		return;
+	}
 	if (config->ssid && buflen > len + config->ssid_len) {
-		memcpy(buf + len, config->ssid, config->ssid_len);
+		os_memcpy(buf + len, config->ssid, config->ssid_len);
 		len += config->ssid_len;
 		buf[len] = '\0';
 	}
+	buf[buflen - 1] = '\0';
 	wpa_msg(sm->msg_ctx, MSG_INFO, "%s", buf);
-	free(buf);
+	os_free(buf);
 }
+#else /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
+#define eap_sm_request(sm, type, msg, msglen) do { } while (0)
+#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
 
 
 /**
  * eap_sm_request_identity - Request identity from user (ctrl_iface)
  * @sm: Pointer to EAP state machine allocated with eap_sm_init()
- * @config: Pointer to the current network configuration
  *
  * EAP methods can call this function to request identity information for the
  * current network. This is normally called when the identity is not included
  * in the network configuration. The request will be sent to monitor programs
  * through the control interface.
  */
-void eap_sm_request_identity(struct eap_sm *sm, struct wpa_ssid *config)
+void eap_sm_request_identity(struct eap_sm *sm)
 {
-	eap_sm_request(sm, config, TYPE_IDENTITY, NULL, 0);
+	eap_sm_request(sm, TYPE_IDENTITY, NULL, 0);
 }
 
 
 /**
  * eap_sm_request_password - Request password from user (ctrl_iface)
  * @sm: Pointer to EAP state machine allocated with eap_sm_init()
- * @config: Pointer to the current network configuration
  *
  * EAP methods can call this function to request password information for the
  * current network. This is normally called when the password is not included
  * in the network configuration. The request will be sent to monitor programs
  * through the control interface.
  */
-void eap_sm_request_password(struct eap_sm *sm, struct wpa_ssid *config)
+void eap_sm_request_password(struct eap_sm *sm)
 {
-	eap_sm_request(sm, config, TYPE_PASSWORD, NULL, 0);
+	eap_sm_request(sm, TYPE_PASSWORD, NULL, 0);
 }
 
 
 /**
  * eap_sm_request_new_password - Request new password from user (ctrl_iface)
  * @sm: Pointer to EAP state machine allocated with eap_sm_init()
- * @config: Pointer to the current network configuration
  *
  * EAP methods can call this function to request new password information for
  * the current network. This is normally called when the EAP method indicates
  * that the current password has expired and password change is required. The
  * request will be sent to monitor programs through the control interface.
  */
-void eap_sm_request_new_password(struct eap_sm *sm, struct wpa_ssid *config)
+void eap_sm_request_new_password(struct eap_sm *sm)
 {
-	eap_sm_request(sm, config, TYPE_NEW_PASSWORD, NULL, 0);
+	eap_sm_request(sm, TYPE_NEW_PASSWORD, NULL, 0);
 }
 
 
 /**
  * eap_sm_request_pin - Request SIM or smart card PIN from user (ctrl_iface)
  * @sm: Pointer to EAP state machine allocated with eap_sm_init()
- * @config: Pointer to the current network configuration
  *
  * EAP methods can call this function to request SIM or smart card PIN
  * information for the current network. This is normally called when the PIN is
  * not included in the network configuration. The request will be sent to
  * monitor programs through the control interface.
  */
-void eap_sm_request_pin(struct eap_sm *sm, struct wpa_ssid *config)
+void eap_sm_request_pin(struct eap_sm *sm)
 {
-	eap_sm_request(sm, config, TYPE_PIN, NULL, 0);
+	eap_sm_request(sm, TYPE_PIN, NULL, 0);
 }
 
 
 /**
  * eap_sm_request_otp - Request one time password from user (ctrl_iface)
  * @sm: Pointer to EAP state machine allocated with eap_sm_init()
- * @config: Pointer to the current network configuration
  * @msg: Message to be displayed to the user when asking for OTP
  * @msg_len: Length of the user displayable message
  *
@@ -1394,26 +1557,24 @@
  * the current network. The request will be sent to monitor programs through
  * the control interface.
  */
-void eap_sm_request_otp(struct eap_sm *sm, struct wpa_ssid *config,
-			const char *msg, size_t msg_len)
+void eap_sm_request_otp(struct eap_sm *sm, const char *msg, size_t msg_len)
 {
-	eap_sm_request(sm, config, TYPE_OTP, msg, msg_len);
+	eap_sm_request(sm, TYPE_OTP, msg, msg_len);
 }
 
 
 /**
  * eap_sm_request_passphrase - Request passphrase from user (ctrl_iface)
  * @sm: Pointer to EAP state machine allocated with eap_sm_init()
- * @config: Pointer to the current network configuration
  *
  * EAP methods can call this function to request passphrase for a private key
  * for the current network. This is normally called when the passphrase is not
  * included in the network configuration. The request will be sent to monitor
  * programs through the control interface.
  */
-void eap_sm_request_passphrase(struct eap_sm *sm, struct wpa_ssid *config)
+void eap_sm_request_passphrase(struct eap_sm *sm)
 {
-	eap_sm_request(sm, config, TYPE_PASSPHRASE, NULL, 0);
+	eap_sm_request(sm, TYPE_PASSPHRASE, NULL, 0);
 }
 
 
@@ -1436,84 +1597,24 @@
 	 * starts immediately after system startup when the user interface is
 	 * not yet running. */
 	if (config->pending_req_identity)
-		eap_sm_request_identity(sm, config);
+		eap_sm_request_identity(sm);
 	if (config->pending_req_password)
-		eap_sm_request_password(sm, config);
+		eap_sm_request_password(sm);
 	if (config->pending_req_new_password)
-		eap_sm_request_new_password(sm, config);
+		eap_sm_request_new_password(sm);
 	if (config->pending_req_otp)
-		eap_sm_request_otp(sm, config, NULL, 0);
+		eap_sm_request_otp(sm, NULL, 0);
 	if (config->pending_req_pin)
-		eap_sm_request_pin(sm, config);
+		eap_sm_request_pin(sm);
 	if (config->pending_req_passphrase)
-		eap_sm_request_passphrase(sm, config);
+		eap_sm_request_passphrase(sm);
 }
 
 
-/**
- * eap_get_type - Get EAP type for the given EAP method name
- * @name: EAP method name, e.g., TLS
- * Returns: EAP method type or %EAP_TYPE_NONE if not found
- *
- * This function maps EAP type names into EAP type numbers based on the list of
- * EAP methods included in the build.
- */
-u8 eap_get_type(const char *name)
-{
-	int i;
-	for (i = 0; i < NUM_EAP_METHODS; i++) {
-		if (strcmp(eap_methods[i]->name, name) == 0)
-			return eap_methods[i]->method;
-	}
-	return EAP_TYPE_NONE;
-}
-
-
-/**
- * eap_get_name - Get EAP method name for the given EAP type
- * @type: EAP method type
- * Returns: EAP method name, e.g., TLS, or %NULL if not found
- *
- * This function maps EAP type numbers into EAP type names based on the list of
- * EAP methods included in the build.
- */
-const char * eap_get_name(EapType type)
-{
-	int i;
-	for (i = 0; i < NUM_EAP_METHODS; i++) {
-		if (eap_methods[i]->method == type)
-			return eap_methods[i]->name;
-	}
-	return NULL;
-}
-
-
-/**
- * eap_get_names - Get space separated list of names for supported EAP methods
- * @buf: Buffer for names
- * @buflen: Buffer length
- * Returns: Number of characters written into buf (not including nul
- * termination)
- */
-size_t eap_get_names(char *buf, size_t buflen)
-{
-	char *pos, *end;
-	int i;
-
-	pos = buf;
-	end = pos + buflen;
-
-	for (i = 0; i < NUM_EAP_METHODS; i++) {
-		pos += snprintf(pos, end - pos, "%s%s",
-				i == 0 ? "" : " ", eap_methods[i]->name);
-	}
-
-	return pos - buf;
-}
-
-
-static int eap_allowed_phase2_type(int type)
+static int eap_allowed_phase2_type(int vendor, int type)
 {
+	if (vendor != EAP_VENDOR_IETF)
+		return 0;
 	return type != EAP_TYPE_PEAP && type != EAP_TYPE_TTLS &&
 		type != EAP_TYPE_FAST;
 }
@@ -1522,17 +1623,22 @@
 /**
  * eap_get_phase2_type - Get EAP type for the given EAP phase 2 method name
  * @name: EAP method name, e.g., MD5
+ * @vendor: Buffer for returning EAP Vendor-Id
  * Returns: EAP method type or %EAP_TYPE_NONE if not found
  *
  * This function maps EAP type names into EAP type numbers that are allowed for
  * Phase 2, i.e., for tunneled authentication. Phase 2 is used, e.g., with
  * EAP-PEAP, EAP-TTLS, and EAP-FAST.
  */
-u8 eap_get_phase2_type(const char *name)
+u32 eap_get_phase2_type(const char *name, int *vendor)
 {
-	u8 type = eap_get_type(name);
-	if (eap_allowed_phase2_type(type))
+	int v;
+	u8 type = eap_get_type(name, &v);
+	if (eap_allowed_phase2_type(v, type)) {
+		*vendor = v;
 		return type;
+	}
+	*vendor = EAP_VENDOR_IETF;
 	return EAP_TYPE_NONE;
 }
 
@@ -1540,29 +1646,39 @@
 /**
  * eap_get_phase2_types - Get list of allowed EAP phase 2 types
  * @config: Pointer to a network configuration
- * @count: Pointer to variable filled with number of returned EAP types
+ * @count: Pointer to a variable to be filled with number of returned EAP types
  * Returns: Pointer to allocated type list or %NULL on failure
  *
  * This function generates an array of allowed EAP phase 2 (tunneled) types for
  * the given network configuration.
  */
-u8 *eap_get_phase2_types(struct wpa_ssid *config, size_t *count)
+struct eap_method_type * eap_get_phase2_types(struct wpa_ssid *config,
+					      size_t *count)
 {
-	u8 *buf, method;
-	int i;
+	struct eap_method_type *buf;
+	u32 method;
+	int vendor;
+	size_t mcount;
+	const struct eap_method *methods, *m;
 
+	methods = eap_peer_get_methods(&mcount);
+	if (methods == NULL)
+		return NULL;
 	*count = 0;
-	buf = malloc(NUM_EAP_METHODS);
+	buf = os_malloc(mcount * sizeof(struct eap_method_type));
 	if (buf == NULL)
 		return NULL;
 
-	for (i = 0; i < NUM_EAP_METHODS; i++) {
-		method = eap_methods[i]->method;
-		if (eap_allowed_phase2_type(method)) {
-			if (method == EAP_TYPE_TLS && config &&
+	for (m = methods; m; m = m->next) {
+		vendor = m->vendor;
+		method = m->method;
+		if (eap_allowed_phase2_type(vendor, method)) {
+			if (vendor == EAP_VENDOR_IETF &&
+			    method == EAP_TYPE_TLS && config &&
 			    config->private_key2 == NULL)
 				continue;
-			buf[*count] = method;
+			buf[*count].vendor = vendor;
+			buf[*count].method = method;
 			(*count)++;
 		}
 	}
@@ -1574,7 +1690,7 @@
 /**
  * eap_set_fast_reauth - Update fast_reauth setting
  * @sm: Pointer to EAP state machine allocated with eap_sm_init()
- * @enabled: 1 = fast reauthentication is enabled, 0 = disabled
+ * @enabled: 1 = Fast reauthentication is enabled, 0 = Disabled
  */
 void eap_set_fast_reauth(struct eap_sm *sm, int enabled)
 {
@@ -1597,6 +1713,11 @@
  * eap_get_config - Get current network configuration
  * @sm: Pointer to EAP state machine allocated with eap_sm_init()
  * Returns: Pointer to the current network configuration or %NULL if not found
+ *
+ * EAP peer methods should avoid using this function if they can use other
+ * access functions, like eap_get_config_identity() and
+ * eap_get_config_password(), that do not require direct access to
+ * struct wpa_ssid.
  */
 struct wpa_ssid * eap_get_config(struct eap_sm *sm)
 {
@@ -1605,6 +1726,90 @@
 
 
 /**
+ * eap_get_config_password - Get identity from the network configuration
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ * @len: Buffer for the length of the identity
+ * Returns: Pointer to the identity or %NULL if not found
+ */
+const u8 * eap_get_config_identity(struct eap_sm *sm, size_t *len)
+{
+	struct wpa_ssid *config = eap_get_config(sm);
+	if (config == NULL)
+		return NULL;
+	*len = config->identity_len;
+	return config->identity;
+}
+
+
+/**
+ * eap_get_config_password - Get password from the network configuration
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ * @len: Buffer for the length of the password
+ * Returns: Pointer to the password or %NULL if not found
+ */
+const u8 * eap_get_config_password(struct eap_sm *sm, size_t *len)
+{
+	struct wpa_ssid *config = eap_get_config(sm);
+	if (config == NULL)
+		return NULL;
+	*len = config->password_len;
+	return config->password;
+}
+
+
+/**
+ * eap_get_config_new_password - Get new password from network configuration
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ * @len: Buffer for the length of the new password
+ * Returns: Pointer to the new password or %NULL if not found
+ */
+const u8 * eap_get_config_new_password(struct eap_sm *sm, size_t *len)
+{
+	struct wpa_ssid *config = eap_get_config(sm);
+	if (config == NULL)
+		return NULL;
+	*len = config->new_password_len;
+	return config->new_password;
+}
+
+
+/**
+ * eap_get_config_otp - Get one-time password from the network configuration
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ * @len: Buffer for the length of the one-time password
+ * Returns: Pointer to the one-time password or %NULL if not found
+ */
+const u8 * eap_get_config_otp(struct eap_sm *sm, size_t *len)
+{
+	struct wpa_ssid *config = eap_get_config(sm);
+	if (config == NULL)
+		return NULL;
+	*len = config->otp_len;
+	return config->otp;
+}
+
+
+/**
+ * eap_clear_config_otp - Clear used one-time password
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ *
+ * This function clears a used one-time password (OTP) from the current network
+ * configuration. This should be called when the OTP has been used and is not
+ * needed anymore.
+ */
+void eap_clear_config_otp(struct eap_sm *sm)
+{
+	struct wpa_ssid *config = eap_get_config(sm);
+	if (config == NULL)
+		return;
+	os_memset(config->otp, 0, config->otp_len);
+	os_free(config->otp);
+	config->otp = NULL;
+	config->otp_len = 0;
+}
+
+
+/**
  * eap_key_available - Get key availability (eapKeyAvailable variable)
  * @sm: Pointer to EAP state machine allocated with eap_sm_init()
  * Returns: 1 if EAP keying material is available, 0 if not
@@ -1631,6 +1836,8 @@
 		sm->EAP_state = EAP_SUCCESS;
 	}
 }
+
+
 /**
  * eap_notify_lower_layer_success - Notification of lower layer success
  * @sm: Pointer to EAP state machine allocated with eap_sm_init()
@@ -1713,7 +1920,7 @@
 /**
  * eap_sm_register_scard_ctx - Notification of smart card context
  * @sm: Pointer to EAP state machine allocated with eap_sm_init()
- * @ctx: context data for smart card operations
+ * @ctx: Context data for smart card operations
  *
  * Notify EAP state machines of context data for smart card operations. This
  * context data will be used as a parameter for scard_*() functions.
@@ -1727,35 +1934,72 @@
 
 /**
  * eap_hdr_validate - Validate EAP header
+ * @vendor: Expected EAP Vendor-Id (0 = IETF)
  * @eap_type: Expected EAP type number
  * @msg: EAP frame (starting with EAP header)
  * @msglen: Length of msg
- * @plen: Pointer for return payload length
+ * @plen: Pointer to variable to contain the returned payload length
  * Returns: Pointer to EAP payload (after type field), or %NULL on failure
  *
  * This is a helper function for EAP method implementations. This is usually
- * called in the beginning of struct eap_method::process() function.
+ * called in the beginning of struct eap_method::process() function to verify
+ * that the received EAP request packet has a valid header. This function is
+ * able to process both legacy and expanded EAP headers and in most cases, the
+ * caller can just use the returned payload pointer (into *plen) for processing
+ * the payload regardless of whether the packet used the expanded EAP header or
+ * not.
  */
-const u8 * eap_hdr_validate(EapType eap_type, const u8 *msg, size_t msglen,
-			    size_t *plen)
+const u8 * eap_hdr_validate(int vendor, EapType eap_type,
+			    const u8 *msg, size_t msglen, size_t *plen)
 {
 	const struct eap_hdr *hdr;
 	const u8 *pos;
 	size_t len;
 
 	hdr = (const struct eap_hdr *) msg;
-	pos = (const u8 *) (hdr + 1);
-	if (msglen < sizeof(*hdr) + 1 || *pos != eap_type) {
-		wpa_printf(MSG_INFO, "EAP: Invalid frame type");
+
+	if (msglen < sizeof(*hdr)) {
+		wpa_printf(MSG_INFO, "EAP: Too short EAP frame");
 		return NULL;
 	}
+
 	len = be_to_host16(hdr->length);
 	if (len < sizeof(*hdr) + 1 || len > msglen) {
 		wpa_printf(MSG_INFO, "EAP: Invalid EAP length");
 		return NULL;
 	}
-	*plen = len - sizeof(*hdr) - 1;
-	return pos + 1;
+
+	pos = (const u8 *) (hdr + 1);
+
+	if (*pos == EAP_TYPE_EXPANDED) {
+		int exp_vendor;
+		u32 exp_type;
+		if (len < sizeof(*hdr) + 8) {
+			wpa_printf(MSG_INFO, "EAP: Invalid expanded EAP "
+				   "length");
+			return NULL;
+		}
+		pos++;
+		exp_vendor = WPA_GET_BE24(pos);
+		pos += 3;
+		exp_type = WPA_GET_BE32(pos);
+		pos += 4;
+		if (exp_vendor != vendor || exp_type != (u32) eap_type) {
+			wpa_printf(MSG_INFO, "EAP: Invalid expanded frame "
+				   "type");
+			return NULL;
+		}
+
+		*plen = len - sizeof(*hdr) - 8;
+		return pos;
+	} else {
+		if (vendor != EAP_VENDOR_IETF || *pos != eap_type) {
+			wpa_printf(MSG_INFO, "EAP: Invalid frame type");
+			return NULL;
+		}
+		*plen = len - sizeof(*hdr) - 1;
+		return pos + 1;
+	}
 }
 
 
@@ -1798,3 +2042,79 @@
 {
 	sm->force_disabled = disabled;
 }
+
+
+/**
+ * eap_msg_alloc - Allocate a buffer for an EAP message
+ * @vendor: Vendor-Id (0 = IETF)
+ * @type: EAP type
+ * @len: Buffer for returning message length
+ * @payload_len: Payload length in bytes (data after Type)
+ * @code: Message Code (EAP_CODE_*)
+ * @identifier: Identifier
+ * @payload: Pointer to payload pointer that will be set to point to the
+ * beginning of the payload or %NULL if payload pointer is not needed
+ * Returns: Pointer to the allocated message buffer or %NULL on error
+ *
+ * This function can be used to allocate a buffer for an EAP message and fill
+ * in the EAP header. This function is automatically using expanded EAP header
+ * if the selected Vendor-Id is not IETF. In other words, most EAP methods do
+ * not need to separately select which header type to use when using this
+ * function to allocate the message buffers.
+ */
+struct eap_hdr * eap_msg_alloc(int vendor, EapType type, size_t *len,
+			       size_t payload_len, u8 code, u8 identifier,
+			       u8 **payload)
+{
+	struct eap_hdr *hdr;
+	u8 *pos;
+
+	*len = sizeof(struct eap_hdr) + (vendor == EAP_VENDOR_IETF ? 1 : 8) +
+		payload_len;
+	hdr = os_malloc(*len);
+	if (hdr) {
+		hdr->code = code;
+		hdr->identifier = identifier;
+		hdr->length = host_to_be16(*len);
+		pos = (u8 *) (hdr + 1);
+		if (vendor == EAP_VENDOR_IETF) {
+			*pos++ = type;
+		} else {
+			*pos++ = EAP_TYPE_EXPANDED;
+			WPA_PUT_BE24(pos, vendor);
+			pos += 3;
+			WPA_PUT_BE32(pos, type);
+			pos += 4;
+		}
+		if (payload)
+			*payload = pos;
+	}
+
+	return hdr;
+}
+
+
+ /**
+ * eap_notify_pending - Notify that EAP method is ready to re-process a request
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ *
+ * An EAP method can perform a pending operation (e.g., to get a response from
+ * an external process). Once the response is available, this function can be
+ * used to request EAPOL state machine to retry delivering the previously
+ * received (and still unanswered) EAP request to EAP state machine.
+ */
+void eap_notify_pending(struct eap_sm *sm)
+{
+	sm->eapol_cb->notify_pending(sm->eapol_ctx);
+}
+
+
+/**
+ * eap_invalidate_cached_session - Mark cached session data invalid
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ */
+void eap_invalidate_cached_session(struct eap_sm *sm)
+{
+	if (sm)
+		eap_deinit_prev_method(sm, "invalidate");
+}
Index: eap_mschapv2.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/eap_mschapv2.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/eap_mschapv2.c -L contrib/wpa_supplicant/eap_mschapv2.c -u -r1.2 -r1.3
--- contrib/wpa_supplicant/eap_mschapv2.c
+++ contrib/wpa_supplicant/eap_mschapv2.c
@@ -1,6 +1,6 @@
 /*
- * WPA Supplicant / EAP-MSCHAPV2 (draft-kamath-pppext-eap-mschapv2-00.txt)
- * Copyright (c) 2004-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * EAP peer method: EAP-MSCHAPV2 (draft-kamath-pppext-eap-mschapv2-00.txt)
+ * Copyright (c) 2004-2006, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -10,30 +10,60 @@
  * license.
  *
  * See README and COPYING for more details.
+ *
+ * This file implements EAP peer part of EAP-MSCHAPV2 method (EAP type 26).
+ * draft-kamath-pppext-eap-mschapv2-00.txt defines the Microsoft EAP CHAP
+ * Extensions Protocol, Version 2, for mutual authentication and key
+ * derivation. This encapsulates MS-CHAP-v2 protocol which is defined in
+ * RFC 2759. Use of EAP-MSCHAPV2 derived keys with MPPE cipher is described in
+ * RFC 3079.
  */
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
+#include "includes.h"
 
 #include "common.h"
 #include "eap_i.h"
-#include "wpa_supplicant.h"
 #include "config_ssid.h"
 #include "ms_funcs.h"
 #include "wpa_ctrl.h"
 
 
+#define MSCHAPV2_CHAL_LEN 16
+#define MSCHAPV2_NT_RESPONSE_LEN 24
+
+#ifdef _MSC_VER
+#pragma pack(push, 1)
+#endif /* _MSC_VER */
+
 struct eap_mschapv2_hdr {
-	u8 code;
-	u8 identifier;
-	u16 length; /* including code, identifier, and length */
-	u8 type; /* EAP_TYPE_MSCHAPV2 */
 	u8 op_code; /* MSCHAPV2_OP_* */
-	u8 mschapv2_id; /* usually same as identifier */
+	u8 mschapv2_id; /* usually same as EAP identifier; must be changed
+			 * for challenges, but not for success/failure */
 	u8 ms_length[2]; /* Note: misaligned; length - 5 */
 	/* followed by data */
-} __attribute__ ((packed));
+} STRUCT_PACKED;
+
+/* Response Data field */
+struct ms_response {
+	u8 peer_challenge[MSCHAPV2_CHAL_LEN];
+	u8 reserved[8];
+	u8 nt_response[MSCHAPV2_NT_RESPONSE_LEN];
+	u8 flags;
+} STRUCT_PACKED;
+
+/* Change-Password Data field */
+struct ms_change_password {
+	u8 encr_password[516];
+	u8 encr_hash[16];
+	u8 peer_challenge[MSCHAPV2_CHAL_LEN];
+	u8 reserved[8];
+	u8 nt_response[MSCHAPV2_NT_RESPONSE_LEN];
+	u8 flags[2];
+} STRUCT_PACKED;
+
+#ifdef _MSC_VER
+#pragma pack(pop)
+#endif /* _MSC_VER */
 
 #define MSCHAPV2_OP_CHALLENGE 1
 #define MSCHAPV2_OP_RESPONSE 2
@@ -41,8 +71,6 @@
 #define MSCHAPV2_OP_FAILURE 4
 #define MSCHAPV2_OP_CHANGE_PASSWORD 7
 
-#define MSCHAPV2_RESP_LEN 49
-
 #define ERROR_RESTRICTED_LOGON_HOURS 646
 #define ERROR_ACCT_DISABLED 647
 #define ERROR_PASSWD_EXPIRED 648
@@ -67,6 +95,7 @@
 	 */
 	u8 *peer_challenge;
 	u8 *auth_challenge;
+	int full_key;
 
 	int phase2;
 	u8 master_key[16];
@@ -84,27 +113,31 @@
 static void * eap_mschapv2_init(struct eap_sm *sm)
 {
 	struct eap_mschapv2_data *data;
-	data = malloc(sizeof(*data));
+	data = os_zalloc(sizeof(*data));
 	if (data == NULL)
 		return NULL;
-	memset(data, 0, sizeof(*data));
+
+	data->full_key = sm->mschapv2_full_key;
 
 	if (sm->peer_challenge) {
-		data->peer_challenge = malloc(16);
+		data->full_key = 1;
+		data->peer_challenge = os_malloc(MSCHAPV2_CHAL_LEN);
 		if (data->peer_challenge == NULL) {
 			eap_mschapv2_deinit(sm, data);
 			return NULL;
 		}
-		memcpy(data->peer_challenge, sm->peer_challenge, 16);
+		os_memcpy(data->peer_challenge, sm->peer_challenge,
+			  MSCHAPV2_CHAL_LEN);
 	}
 
 	if (sm->auth_challenge) {
-		data->auth_challenge = malloc(16);
+		data->auth_challenge = os_malloc(MSCHAPV2_CHAL_LEN);
 		if (data->auth_challenge == NULL) {
 			eap_mschapv2_deinit(sm, data);
 			return NULL;
 		}
-		memcpy(data->auth_challenge, sm->auth_challenge, 16);
+		os_memcpy(data->auth_challenge, sm->auth_challenge,
+			  MSCHAPV2_CHAL_LEN);
 	}
 
 	data->phase2 = sm->init_phase2;
@@ -116,54 +149,194 @@
 static void eap_mschapv2_deinit(struct eap_sm *sm, void *priv)
 {
 	struct eap_mschapv2_data *data = priv;
-	free(data->peer_challenge);
-	free(data->auth_challenge);
-	free(data->prev_challenge);
-	free(data);
+	os_free(data->peer_challenge);
+	os_free(data->auth_challenge);
+	os_free(data->prev_challenge);
+	os_free(data);
+}
+
+
+static const u8 * eap_mschapv2_remove_domain(const u8 *username, size_t *len)
+{
+	size_t i;
+
+	/*
+	 * MSCHAPv2 does not include optional domain name in the
+	 * challenge-response calculation, so remove domain prefix
+	 * (if present).
+	 */
+
+	for (i = 0; i < *len; i++) {
+		if (username[i] == '\\') {
+			*len -= i + 1;
+			return username + i + 1;
+		}
+	}
+
+	return username;
+}
+
+
+static void eap_mschapv2_derive_response(
+	struct eap_mschapv2_data *data,
+	const u8 *username, size_t username_len,
+	const u8 *password, size_t password_len,
+	const u8 *auth_challenge, const u8 *peer_challenge,
+	u8 *nt_response)
+{
+	u8 password_hash[16], password_hash_hash[16];
+
+	wpa_hexdump(MSG_DEBUG, "EAP-MSCHAPV2: auth_challenge",
+		    auth_challenge, MSCHAPV2_CHAL_LEN);
+	wpa_hexdump(MSG_DEBUG, "EAP-MSCHAPV2: peer_challenge",
+		    peer_challenge, MSCHAPV2_CHAL_LEN);
+	wpa_hexdump_ascii(MSG_DEBUG, "EAP-MSCHAPV2: username",
+			  username, username_len);
+	wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-MSCHAPV2: password",
+			      password, password_len);
+	generate_nt_response(auth_challenge, peer_challenge,
+			     username, username_len,
+			     password, password_len, nt_response);
+	wpa_hexdump(MSG_DEBUG, "EAP-MSCHAPV2: response", nt_response,
+		    MSCHAPV2_NT_RESPONSE_LEN);
+	/* Authenticator response is not really needed yet, but calculate it
+	 * here so that challenges need not be saved. */
+	generate_authenticator_response(password, password_len,
+					peer_challenge, auth_challenge,
+					username, username_len, nt_response,
+					data->auth_response);
+	data->auth_response_valid = 1;
+
+	/* Likewise, generate master_key here since we have the needed data
+	 * available. */
+	nt_password_hash(password, password_len, password_hash);
+	hash_nt_password_hash(password_hash, password_hash_hash);
+	get_master_key(password_hash_hash, nt_response, data->master_key);
+	data->master_key_valid = 1;
 }
 
 
+static u8 * eap_mschapv2_challenge_reply(struct eap_sm *sm,
+					 struct eap_mschapv2_data *data, u8 id,
+					 u8 mschapv2_id,
+					 const u8 *auth_challenge,
+					 size_t *respDataLen)
+{
+	struct eap_hdr *resp;
+	struct eap_mschapv2_hdr *ms;
+	u8 *rpos, *peer_challenge;
+	int ms_len;
+	struct ms_response *r;
+	size_t username_len, identity_len, password_len;
+	const u8 *username, *identity, *password;
+
+	wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Generating Challenge Response");
+
+	identity = eap_get_config_identity(sm, &identity_len);
+	password = eap_get_config_password(sm, &password_len);
+	if (identity == NULL || password == NULL)
+		return NULL;
+
+	username_len = identity_len;
+	username = eap_mschapv2_remove_domain(identity, &username_len);
+
+	ms_len = sizeof(*ms) + 1 + sizeof(*r) + identity_len;
+	resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, respDataLen,
+			     ms_len, EAP_CODE_RESPONSE, id, &rpos);
+	if (resp == NULL)
+		return NULL;
+
+	ms = (struct eap_mschapv2_hdr *) rpos;
+	ms->op_code = MSCHAPV2_OP_RESPONSE;
+	ms->mschapv2_id = mschapv2_id;
+	if (data->prev_error) {
+		/*
+		 * TODO: this does not seem to be enough when processing two
+		 * or more failure messages. IAS did not increment mschapv2_id
+		 * in its own packets, but it seemed to expect the peer to
+		 * increment this for all packets(?).
+		 */
+		ms->mschapv2_id++;
+	}
+	WPA_PUT_BE16(ms->ms_length, ms_len);
+	rpos = (u8 *) (ms + 1);
+	*rpos++ = sizeof(*r); /* Value-Size */
+
+	/* Response */
+	r = (struct ms_response *) rpos;
+	peer_challenge = r->peer_challenge;
+	if (data->peer_challenge) {
+		wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: peer_challenge generated "
+			   "in Phase 1");
+		peer_challenge = data->peer_challenge;
+		os_memset(r->peer_challenge, 0, MSCHAPV2_CHAL_LEN);
+	} else if (os_get_random(peer_challenge, MSCHAPV2_CHAL_LEN)) {
+		os_free(resp);
+		return NULL;
+	}
+	os_memset(r->reserved, 0, 8);
+	if (data->auth_challenge) {
+		wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: auth_challenge generated "
+			   "in Phase 1");
+		auth_challenge = data->auth_challenge;
+	}
+	eap_mschapv2_derive_response(data, username, username_len,
+				     password, password_len,
+				     auth_challenge, peer_challenge,
+				     r->nt_response);
+
+	r->flags = 0; /* reserved, must be zero */
+
+	os_memcpy((u8 *) (r + 1), identity, identity_len);
+	wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: TX identifier %d mschapv2_id %d "
+		   "(response)", resp->identifier, ms->mschapv2_id);
+	return (u8 *) resp;
+}
+
+
+/**
+ * eap_mschapv2_process - Process an EAP-MSCHAPv2 challenge message
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ * @data: Pointer to private EAP method data from eap_mschapv2_init()
+ * @ret: Return values from EAP request validation and processing
+ * @req: Pointer to EAP-MSCHAPv2 header from the request
+ * @req_len: Length of the EAP-MSCHAPv2 data
+ * @id: EAP identifier used in th erequest
+ * @respDataLen: Length of the returned EAP response
+ * Returns: Pointer to allocated EAP response packet (eapRespData) or %NULL if
+ * no reply available
+ */
 static u8 * eap_mschapv2_challenge(struct eap_sm *sm,
 				   struct eap_mschapv2_data *data,
 				   struct eap_method_ret *ret,
 				   const struct eap_mschapv2_hdr *req,
-				   size_t *respDataLen)
+				   size_t req_len, u8 id, size_t *respDataLen)
 {
-	struct wpa_ssid *config = eap_get_config(sm);
-	u8 *challenge, *peer_challenge, *username, *pos;
-	int i, ms_len;
-	size_t len, challenge_len, username_len;
-	struct eap_mschapv2_hdr *resp;
-	u8 password_hash[16], password_hash_hash[16];
+	size_t len, challenge_len;
+	const u8 *pos, *challenge;
 
-	if (config == NULL)
+	if (eap_get_config_identity(sm, &len) == NULL ||
+	    eap_get_config_password(sm, &len) == NULL)
 		return NULL;
 
-	/* MSCHAPv2 does not include optional domain name in the
-	 * challenge-response calculation, so remove domain prefix
-	 * (if present). */
-	username = config->identity;
-	username_len = config->identity_len;
-	for (i = 0; i < username_len; i++) {
-		if (username[i] == '\\') {
-			username_len -= i + 1;
-			username += i + 1;
-			break;
-		}
-	}
-
 	wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Received challenge");
-	len = be_to_host16(req->length);
-	pos = (u8 *) (req + 1);
+	if (req_len < sizeof(*req) + 1) {
+		wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Too short challenge data "
+			   "(len %lu)", (unsigned long) req_len);
+		ret->ignore = TRUE;
+		return NULL;
+	}
+	pos = (const u8 *) (req + 1);
 	challenge_len = *pos++;
-	if (challenge_len != 16) {
+	len = req_len - sizeof(*req) - 1;
+	if (challenge_len != MSCHAPV2_CHAL_LEN) {
 		wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Invalid challenge length "
 			   "%lu", (unsigned long) challenge_len);
 		ret->ignore = TRUE;
 		return NULL;
 	}
 
-	if (len < 10 || len - 10 < challenge_len) {
+	if (len < challenge_len) {
 		wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Too short challenge"
 			   " packet: len=%lu challenge_len=%lu",
 			   (unsigned long) len, (unsigned long) challenge_len);
@@ -178,116 +351,70 @@
 	} else
 		challenge = pos;
 	pos += challenge_len;
+	len -= challenge_len;
 	wpa_hexdump_ascii(MSG_DEBUG, "EAP-MSCHAPV2: Authentication Servername",
-		    pos, len - challenge_len - 10);
+		    pos, len);
 
 	ret->ignore = FALSE;
 	ret->methodState = METHOD_MAY_CONT;
 	ret->decision = DECISION_FAIL;
 	ret->allowNotifications = TRUE;
 
-	wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Generating Challenge Response");
+	return eap_mschapv2_challenge_reply(sm, data, id, req->mschapv2_id,
+					    challenge, respDataLen);
+}
 
-	*respDataLen = sizeof(*resp) + 1 + MSCHAPV2_RESP_LEN +
-		config->identity_len;
-	resp = malloc(*respDataLen);
-	if (resp == NULL)
-		return NULL;
-	memset(resp, 0, *respDataLen);
-	resp->code = EAP_CODE_RESPONSE;
-	resp->identifier = req->identifier;
-	resp->length = host_to_be16(*respDataLen);
-	resp->type = EAP_TYPE_MSCHAPV2;
-	resp->op_code = MSCHAPV2_OP_RESPONSE;
-	resp->mschapv2_id = req->mschapv2_id;
-	if (data->prev_error) {
-		/*
-		 * TODO: this does not seem to be enough when processing two
-		 * or more failure messages. IAS did not increment mschapv2_id
-		 * in its own packets, but it seemed to expect the peer to
-		 * increment this for all packets(?).
-		 */
-		resp->mschapv2_id++;
-	}
-	ms_len = *respDataLen - 5;
-	WPA_PUT_BE16(resp->ms_length, ms_len);
-	pos = (u8 *) (resp + 1);
-	*pos++ = MSCHAPV2_RESP_LEN; /* Value-Size */
 
-	/* Response */
-	peer_challenge = pos;
-	if (data->peer_challenge) {
-		wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: peer_challenge generated "
-			   "in Phase 1");
-		peer_challenge = data->peer_challenge;
-	} else if (hostapd_get_rand(peer_challenge, 16)) {
-		free(resp);
-		return NULL;
-	}
-	pos += 16;
-	pos += 8; /* Reserved, must be zero */
-	if (data->auth_challenge) {
-		wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: auth_challenge generated "
-			   "in Phase 1");
-		challenge = data->auth_challenge;
+static void eap_mschapv2_password_changed(struct eap_sm *sm,
+					  struct eap_mschapv2_data *data)
+{
+	struct wpa_ssid *config = eap_get_config(sm);
+	if (config && config->new_password) {
+		wpa_msg(sm->msg_ctx, MSG_INFO,
+			WPA_EVENT_PASSWORD_CHANGED
+			"EAP-MSCHAPV2: Password changed successfully");
+		data->prev_error = 0;
+		os_free(config->password);
+		config->password = config->new_password;
+		config->new_password = NULL;
+		config->password_len = config->new_password_len;
+		config->new_password_len = 0;
 	}
-	wpa_hexdump(MSG_DEBUG, "EAP-MSCHAPV2: auth_challenge", challenge, 16);
-	wpa_hexdump(MSG_DEBUG, "EAP-MSCHAPV2: peer_challenge",
-		    peer_challenge, 16);
-	wpa_hexdump_ascii(MSG_DEBUG, "EAP-MSCHAPV2: username",
-			  username, username_len);
-	wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-MSCHAPV2: password",
-			      config->password, config->password_len);
-	generate_nt_response(challenge, peer_challenge,
-			     username, username_len,
-			     config->password, config->password_len,
-			     pos);
-	wpa_hexdump(MSG_DEBUG, "EAP-MSCHAPV2: response", pos, 24);
-	/* Authenticator response is not really needed yet, but calculate it
-	 * here so that challenges need not be saved. */
-	generate_authenticator_response(config->password, config->password_len,
-					peer_challenge, challenge,
-					username, username_len, pos,
-					data->auth_response);
-	data->auth_response_valid = 1;
-
-	/* Likewise, generate master_key here since we have the needed data
-	 * available. */
-	nt_password_hash(config->password, config->password_len,
-			 password_hash);
-	hash_nt_password_hash(password_hash, password_hash_hash);
-	get_master_key(password_hash_hash, pos /* nt_response */,
-		       data->master_key);
-	data->master_key_valid = 1;
-
-	pos += 24;
-	pos++; /* Flag / reserved, must be zero */
-
-	memcpy(pos, config->identity, config->identity_len);
-	wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: TX identifier %d mschapv2_id %d "
-		   "(response)", resp->identifier, resp->mschapv2_id);
-	return (u8 *) resp;
 }
 
 
+/**
+ * eap_mschapv2_process - Process an EAP-MSCHAPv2 success message
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ * @data: Pointer to private EAP method data from eap_mschapv2_init()
+ * @ret: Return values from EAP request validation and processing
+ * @req: Pointer to EAP-MSCHAPv2 header from the request
+ * @req_len: Length of the EAP-MSCHAPv2 data
+ * @id: EAP identifier used in th erequest
+ * @respDataLen: Length of the returned EAP response
+ * Returns: Pointer to allocated EAP response packet (eapRespData) or %NULL if
+ * no reply available
+ */
 static u8 * eap_mschapv2_success(struct eap_sm *sm,
 				 struct eap_mschapv2_data *data,
 				 struct eap_method_ret *ret,
 				 const struct eap_mschapv2_hdr *req,
-				 size_t *respDataLen)
+				 size_t req_len, u8 id, size_t *respDataLen)
 {
-	struct eap_mschapv2_hdr *resp;
+	struct eap_hdr *resp;
+	struct eap_mschapv2_hdr *ms;
 	const u8 *pos;
 	u8 recv_response[20];
-	int len, left;
+	size_t len;
+	u8 *rpos;
 
 	wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Received success");
-	len = be_to_host16(req->length);
+	len = req_len - sizeof(*req);
 	pos = (const u8 *) (req + 1);
-	if (!data->auth_response_valid || len < sizeof(*req) + 42 ||
+	if (!data->auth_response_valid || len < 42 ||
 	    pos[0] != 'S' || pos[1] != '=' ||
 	    hexstr2bin((char *) (pos + 2), recv_response, 20) ||
-	    memcmp(data->auth_response, recv_response, 20) != 0) {
+	    os_memcmp(data->auth_response, recv_response, 20) != 0) {
 		wpa_printf(MSG_WARNING, "EAP-MSCHAPV2: Invalid authenticator "
 			   "response in success request");
 		ret->methodState = METHOD_DONE;
@@ -295,16 +422,19 @@
 		return NULL;
 	}
 	pos += 42;
-	left = len - sizeof(*req) - 42;
-	while (left > 0 && *pos == ' ') {
+	len -= 42;
+	while (len > 0 && *pos == ' ') {
 		pos++;
-		left--;
+		len--;
 	}
 	wpa_hexdump_ascii(MSG_DEBUG, "EAP-MSCHAPV2: Success message",
-			  pos, left);
+			  pos, len);
 	wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Authentication succeeded");
-	*respDataLen = 6;
-	resp = malloc(6);
+
+	/* Note: Only op_code of the EAP-MSCHAPV2 header is included in success
+	 * message. */
+	resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, respDataLen,
+			     1, EAP_CODE_RESPONSE, id, &rpos);
 	if (resp == NULL) {
 		wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Failed to allocate "
 			   "buffer for success response");
@@ -312,31 +442,16 @@
 		return NULL;
 	}
 
-	resp->code = EAP_CODE_RESPONSE;
-	resp->identifier = req->identifier;
-	resp->length = host_to_be16(6);
-	resp->type = EAP_TYPE_MSCHAPV2;
-	resp->op_code = MSCHAPV2_OP_SUCCESS;
+	ms = (struct eap_mschapv2_hdr *) rpos;
+	ms->op_code = MSCHAPV2_OP_SUCCESS;
 
 	ret->methodState = METHOD_DONE;
 	ret->decision = DECISION_UNCOND_SUCC;
 	ret->allowNotifications = FALSE;
 	data->success = 1;
 
-	if (data->prev_error == ERROR_PASSWD_EXPIRED) {
-		struct wpa_ssid *config = eap_get_config(sm);
-		if (config && config->new_password) {
-			wpa_msg(sm->msg_ctx, MSG_INFO,
-				WPA_EVENT_PASSWORD_CHANGED
-				"EAP-MSCHAPV2: Password changed successfully");
-			data->prev_error = 0;
-			free(config->password);
-			config->password = config->new_password;
-			config->new_password = NULL;
-			config->password_len = config->new_password_len;
-			config->new_password_len = 0;
-		}
-	}
+	if (data->prev_error == ERROR_PASSWD_EXPIRED)
+		eap_mschapv2_password_changed(sm, data);
 
 	return (u8 *) resp;
 }
@@ -355,30 +470,30 @@
 
 	pos = txt;
 
-	if (pos && strncmp(pos, "E=", 2) == 0) {
+	if (pos && os_strncmp(pos, "E=", 2) == 0) {
 		pos += 2;
 		data->prev_error = atoi(pos);
 		wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: error %d",
 			   data->prev_error);
-		pos = strchr(pos, ' ');
+		pos = os_strchr(pos, ' ');
 		if (pos)
 			pos++;
 	}
 
-	if (pos && strncmp(pos, "R=", 2) == 0) {
+	if (pos && os_strncmp(pos, "R=", 2) == 0) {
 		pos += 2;
 		retry = atoi(pos);
 		wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: retry is %sallowed",
 			   retry == 1 ? "" : "not ");
-		pos = strchr(pos, ' ');
+		pos = os_strchr(pos, ' ');
 		if (pos)
 			pos++;
 	}
 
-	if (pos && strncmp(pos, "C=", 2) == 0) {
+	if (pos && os_strncmp(pos, "C=", 2) == 0) {
 		int hex_len;
 		pos += 2;
-		hex_len = strchr(pos, ' ') - (char *) pos;
+		hex_len = os_strchr(pos, ' ') - (char *) pos;
 		if (hex_len == PASSWD_CHANGE_CHAL_LEN * 2) {
 			if (hexstr2bin(pos, data->passwd_change_challenge,
 				       PASSWD_CHANGE_CHAL_LEN)) {
@@ -395,7 +510,7 @@
 			wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: invalid failure "
 				   "challenge len %d", hex_len);
 		}
-		pos = strchr(pos, ' ');
+		pos = os_strchr(pos, ' ');
 		if (pos)
 			pos++;
 	} else {
@@ -403,17 +518,17 @@
 			   "was not present in failure message");
 	}
 
-	if (pos && strncmp(pos, "V=", 2) == 0) {
+	if (pos && os_strncmp(pos, "V=", 2) == 0) {
 		pos += 2;
 		data->passwd_change_version = atoi(pos);
 		wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: password changing "
 			   "protocol version %d", data->passwd_change_version);
-		pos = strchr(pos, ' ');
+		pos = os_strchr(pos, ' ');
 		if (pos)
 			pos++;
 	}
 
-	if (pos && strncmp(pos, "M=", 2) == 0) {
+	if (pos && os_strncmp(pos, "M=", 2) == 0) {
 		pos += 2;
 		msg = pos;
 	}
@@ -427,14 +542,14 @@
 			wpa_msg(sm->msg_ctx, MSG_INFO,
 				"EAP-MSCHAPV2: Password expired - password "
 				"change required");
-			eap_sm_request_new_password(sm, config);
+			eap_sm_request_new_password(sm);
 		}
 	} else if (retry == 1 && config) {
 		/* TODO: could prevent the current password from being used
 		 * again at least for some period of time */
 		if (!config->mschapv2_retry)
-			eap_sm_request_identity(sm, config);
-		eap_sm_request_password(sm, config);
+			eap_sm_request_identity(sm);
+		eap_sm_request_password(sm);
 		config->mschapv2_retry = 1;
 	} else if (config) {
 		/* TODO: prevent retries using same username/password */
@@ -449,137 +564,135 @@
 					 struct eap_mschapv2_data *data,
 					 struct eap_method_ret *ret,
 					 const struct eap_mschapv2_hdr *req,
-					 size_t *respDataLen)
+					 u8 id, size_t *respDataLen)
 {
-	struct eap_mschapv2_hdr *resp;
-	int ms_len, i;
-	u8 *peer_challenge, *username, *pos;
-	size_t username_len;
-	struct wpa_ssid *config = eap_get_config(sm);
-
-	if (config == NULL || config->identity == NULL ||
-	    config->new_password == NULL || config->password == NULL)
+	struct eap_hdr *resp;
+	int ms_len;
+	const u8 *username, *password, *new_password;
+	u8 *pos;
+	size_t username_len, password_len, new_password_len;
+	struct eap_mschapv2_hdr *ms;
+	struct ms_change_password *cp;
+
+	username = eap_get_config_identity(sm, &username_len);
+	password = eap_get_config_password(sm, &password_len);
+	new_password = eap_get_config_new_password(sm, &new_password_len);
+	if (username == NULL || password == NULL || new_password == NULL)
 		return NULL;
 
-	/*
-	 * MSCHAPv2 does not include optional domain name in the
-	 * challenge-response calculation, so remove domain prefix
-	 * (if present).
-	 */
-	username = config->identity;
-	username_len = config->identity_len;
-	for (i = 0; i < username_len; i++) {
-		if (username[i] == '\\') {
-			username_len -= i + 1;
-			username += i + 1;
-			break;
-		}
-	}
+	username = eap_mschapv2_remove_domain(username, &username_len);
 
 	ret->ignore = FALSE;
 	ret->methodState = METHOD_MAY_CONT;
 	ret->decision = DECISION_COND_SUCC;
 	ret->allowNotifications = TRUE;
 
-	*respDataLen = 591;
-	resp = malloc(*respDataLen);
-	if (resp == NULL) {
+	ms_len = sizeof(*ms) + sizeof(*cp);
+	resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, respDataLen,
+			     ms_len, EAP_CODE_RESPONSE, id, &pos);
+	if (resp == NULL)
 		return NULL;
-	}
 
-	resp->code = EAP_CODE_RESPONSE;
-	resp->identifier = req->identifier;
-	resp->length = host_to_be16((u16) *respDataLen);
-	resp->type = EAP_TYPE_MSCHAPV2;
-	resp->op_code = MSCHAPV2_OP_CHANGE_PASSWORD;
-	resp->mschapv2_id = req->mschapv2_id + 1;
-	ms_len = *respDataLen - 5;
-	WPA_PUT_BE16(resp->ms_length, ms_len);
-	pos = (u8 *) (resp + 1);
+	ms = (struct eap_mschapv2_hdr *) pos;
+	ms->op_code = MSCHAPV2_OP_CHANGE_PASSWORD;
+	ms->mschapv2_id = req->mschapv2_id + 1;
+	WPA_PUT_BE16(ms->ms_length, ms_len);
+	cp = (struct ms_change_password *) (ms + 1);
 
 	/* Encrypted-Password */
 	new_password_encrypted_with_old_nt_password_hash(
-		config->new_password, config->new_password_len,
-		config->password, config->password_len, pos);
-	pos += 516;
+		new_password, new_password_len,
+		password, password_len, cp->encr_password);
 
 	/* Encrypted-Hash */
 	old_nt_password_hash_encrypted_with_new_nt_password_hash(
-		config->new_password, config->new_password_len,
-		config->password, config->password_len, pos);
-	pos += 16;
+		new_password, new_password_len,
+		password, password_len, cp->encr_hash);
 
 	/* Peer-Challenge */
-	peer_challenge = pos;
-	if (hostapd_get_rand(peer_challenge, 16)) {
-		free(resp);
+	if (os_get_random(cp->peer_challenge, MSCHAPV2_CHAL_LEN)) {
+		os_free(resp);
 		return NULL;
 	}
-	pos += 16;
 
 	/* Reserved, must be zero */
-	memset(pos, 0, 8);
-	pos += 8;
+	os_memset(cp->reserved, 0, 8);
 
 	/* NT-Response */
 	wpa_hexdump(MSG_DEBUG, "EAP-MSCHAPV2: auth_challenge",
 		    data->passwd_change_challenge, PASSWD_CHANGE_CHAL_LEN);
 	wpa_hexdump(MSG_DEBUG, "EAP-MSCHAPV2: peer_challenge",
-		    peer_challenge, 16);
+		    cp->peer_challenge, MSCHAPV2_CHAL_LEN);
 	wpa_hexdump_ascii(MSG_DEBUG, "EAP-MSCHAPV2: username",
 			  username, username_len);
 	wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-MSCHAPV2: new password",
-			      config->new_password, config->new_password_len);
-	generate_nt_response(data->passwd_change_challenge, peer_challenge,
+			      new_password, new_password_len);
+	generate_nt_response(data->passwd_change_challenge, cp->peer_challenge,
 			     username, username_len,
-			     config->new_password, config->new_password_len,
-			     pos);
-	wpa_hexdump(MSG_DEBUG, "EAP-MSCHAPV2: NT-Response", pos, 24);
+			     new_password, new_password_len,
+			     cp->nt_response);
+	wpa_hexdump(MSG_DEBUG, "EAP-MSCHAPV2: NT-Response",
+		    cp->nt_response, MSCHAPV2_NT_RESPONSE_LEN);
 
 	/* Authenticator response is not really needed yet, but calculate it
 	 * here so that challenges need not be saved. */
-	generate_authenticator_response(config->new_password,
-					config->new_password_len,
-					peer_challenge,
+	generate_authenticator_response(new_password, new_password_len,
+					cp->peer_challenge,
 					data->passwd_change_challenge,
-					username, username_len, pos,
-					data->auth_response);
+					username, username_len,
+					cp->nt_response, data->auth_response);
 	data->auth_response_valid = 1;
 
-	pos += 24;
-
 	/* Flags */
-	*pos++ = 0;
-	*pos++ = 0;
+	os_memset(cp->flags, 0, 2);
 
 	wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: TX identifier %d mschapv2_id %d "
-		   "(change pw)", resp->identifier, resp->mschapv2_id);
+		   "(change pw)", resp->identifier, ms->mschapv2_id);
 
 	return (u8 *) resp;
 }
 
 
+/**
+ * eap_mschapv2_process - Process an EAP-MSCHAPv2 failure message
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ * @data: Pointer to private EAP method data from eap_mschapv2_init()
+ * @ret: Return values from EAP request validation and processing
+ * @req: Pointer to EAP-MSCHAPv2 header from the request
+ * @req_len: Length of the EAP-MSCHAPv2 data
+ * @id: EAP identifier used in th erequest
+ * @respDataLen: Length of the returned EAP response
+ * Returns: Pointer to allocated EAP response packet (eapRespData) or %NULL if
+ * no reply available
+ */
 static u8 * eap_mschapv2_failure(struct eap_sm *sm,
 				 struct eap_mschapv2_data *data,
 				 struct eap_method_ret *ret,
 				 const struct eap_mschapv2_hdr *req,
-				 size_t *respDataLen)
+				 size_t req_len, u8 id, size_t *respDataLen)
 {
-	struct eap_mschapv2_hdr *resp;
+	struct eap_hdr *resp;
 	const u8 *msdata = (const u8 *) (req + 1);
 	char *buf;
-	int len = be_to_host16(req->length) - sizeof(*req);
+	size_t len = req_len - sizeof(*req);
 	int retry = 0;
+	struct eap_mschapv2_hdr *ms;
+	u8 *pos;
 
 	wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Received failure");
 	wpa_hexdump_ascii(MSG_DEBUG, "EAP-MSCHAPV2: Failure data",
 			  msdata, len);
-	buf = malloc(len + 1);
+	/*
+	 * eap_mschapv2_failure_txt() expects a nul terminated string, so we
+	 * must allocate a large enough temporary buffer to create that since
+	 * the received message does not include nul termination.
+	 */
+	buf = os_malloc(len + 1);
 	if (buf) {
-		memcpy(buf, msdata, len);
+		os_memcpy(buf, msdata, len);
 		buf[len] = '\0';
 		retry = eap_mschapv2_failure_txt(sm, data, buf);
-		free(buf);
+		os_free(buf);
 	}
 
 	ret->ignore = FALSE;
@@ -592,7 +705,7 @@
 		struct wpa_ssid *config = eap_get_config(sm);
 		if (config && config->new_password)
 			return eap_mschapv2_change_password(sm, data, ret, req,
-							    respDataLen);
+							    id, respDataLen);
 		if (config && config->pending_req_new_password)
 			return NULL;
 	} else if (retry && data->prev_error == ERROR_AUTHENTICATION_FAILURE) {
@@ -602,22 +715,91 @@
 		return NULL;
 	}
 
-	*respDataLen = 6;
-	resp = malloc(6);
-	if (resp == NULL) {
+	/* Note: Only op_code of the EAP-MSCHAPV2 header is included in failure
+	 * message. */
+	resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, respDataLen,
+			     1, EAP_CODE_RESPONSE, id, &pos);
+	if (resp == NULL)
 		return NULL;
-	}
 
-	resp->code = EAP_CODE_RESPONSE;
-	resp->identifier = req->identifier;
-	resp->length = host_to_be16(6);
-	resp->type = EAP_TYPE_MSCHAPV2;
-	resp->op_code = MSCHAPV2_OP_FAILURE;
+	ms = (struct eap_mschapv2_hdr *) pos;
+	ms->op_code = MSCHAPV2_OP_FAILURE;
 
 	return (u8 *) resp;
 }
 
 
+static int eap_mschapv2_check_config(struct eap_sm *sm)
+{
+	size_t len;
+
+	if (eap_get_config_identity(sm, &len) == NULL) {
+		wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Identity not configured");
+		eap_sm_request_identity(sm);
+		return -1;
+	}
+
+	if (eap_get_config_password(sm, &len) == NULL) {
+		wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Password not configured");
+		eap_sm_request_password(sm);
+		return -1;
+	}
+
+	return 0;
+}
+
+
+static int eap_mschapv2_check_mslen(struct eap_sm *sm, size_t len,
+				    const struct eap_mschapv2_hdr *ms)
+{
+	size_t ms_len = WPA_GET_BE16(ms->ms_length);
+
+	if (ms_len == len)
+		return 0;
+
+	wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Invalid header: len=%lu "
+		   "ms_len=%lu", (unsigned long) len, (unsigned long) ms_len);
+	if (sm->workaround) {
+		/* Some authentication servers use invalid ms_len,
+		 * ignore it for interoperability. */
+		wpa_printf(MSG_INFO, "EAP-MSCHAPV2: workaround, ignore"
+			   " invalid ms_len %lu (len %lu)",
+			   (unsigned long) ms_len,
+			   (unsigned long) len);
+		return 0;
+	}
+
+	return -1;
+}
+
+
+static void eap_mschapv2_copy_challenge(struct eap_mschapv2_data *data,
+					const u8 *reqData, size_t reqDataLen)
+{
+	/*
+	 * Store a copy of the challenge message, so that it can be processed
+	 * again in case retry is allowed after a possible failure.
+	 */
+	os_free(data->prev_challenge);
+	data->prev_challenge = os_malloc(reqDataLen);
+	if (data->prev_challenge) {
+		data->prev_challenge_len = reqDataLen;
+		os_memcpy(data->prev_challenge, reqData, reqDataLen);
+	}
+}
+
+
+/**
+ * eap_mschapv2_process - Process an EAP-MSCHAPv2 request
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ * @priv: Pointer to private EAP method data from eap_mschapv2_init()
+ * @ret: Return values from EAP request validation and processing
+ * @reqData: EAP request to be processed (eapReqData)
+ * @reqDataLen: Length of the EAP request
+ * @respDataLen: Length of the returned EAP response
+ * Returns: Pointer to allocated EAP response packet (eapRespData) or %NULL if
+ * no reply available
+ */
 static u8 * eap_mschapv2_process(struct eap_sm *sm, void *priv,
 				 struct eap_method_ret *ret,
 				 const u8 *reqData, size_t reqDataLen,
@@ -625,21 +807,13 @@
 {
 	struct eap_mschapv2_data *data = priv;
 	struct wpa_ssid *config = eap_get_config(sm);
-	const struct eap_mschapv2_hdr *req;
-	int ms_len, using_prev_challenge = 0;
+	const struct eap_hdr *req;
+	const struct eap_mschapv2_hdr *ms;
+	int using_prev_challenge = 0;
 	const u8 *pos;
 	size_t len;
 
-	if (config == NULL || config->identity == NULL) {
-		wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Identity not configured");
-		eap_sm_request_identity(sm, config);
-		ret->ignore = TRUE;
-		return NULL;
-	}
-
-	if (config->password == NULL) {
-		wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Password not configured");
-		eap_sm_request_password(sm, config);
+	if (eap_mschapv2_check_config(sm)) {
 		ret->ignore = TRUE;
 		return NULL;
 	}
@@ -655,49 +829,38 @@
 		config->mschapv2_retry = 0;
 	}
 
-	pos = eap_hdr_validate(EAP_TYPE_MSCHAPV2, reqData, reqDataLen, &len);
-	if (pos == NULL || len < 5) {
+	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2,
+			       reqData, reqDataLen, &len);
+	if (pos == NULL || len < sizeof(*ms) + 1) {
 		ret->ignore = TRUE;
 		return NULL;
 	}
-	req = (const struct eap_mschapv2_hdr *) reqData;
-	len = be_to_host16(req->length);
-	ms_len = WPA_GET_BE16(req->ms_length);
-	if (ms_len != len - 5) {
-		wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Invalid header: len=%lu "
-			   "ms_len=%d", (unsigned long) len, ms_len);
-		if (sm->workaround) {
-			/* Some authentication servers use invalid ms_len,
-			 * ignore it for interoperability. */
-			wpa_printf(MSG_INFO, "EAP-MSCHAPV2: workaround, ignore"
-				   " invalid ms_len");
-		} else {
-			ret->ignore = TRUE;
-			return NULL;
-		}
+
+	ms = (const struct eap_mschapv2_hdr *) pos;
+	if (eap_mschapv2_check_mslen(sm, len, ms)) {
+		ret->ignore = TRUE;
+		return NULL;
 	}
 
+	req = (const struct eap_hdr *) reqData;
 	wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: RX identifier %d mschapv2_id %d",
-		   req->identifier, req->mschapv2_id);
+		   req->identifier, ms->mschapv2_id);
 
-	switch (req->op_code) {
+	switch (ms->op_code) {
 	case MSCHAPV2_OP_CHALLENGE:
-		if (!using_prev_challenge) {
-			free(data->prev_challenge);
-			data->prev_challenge = malloc(len);
-			if (data->prev_challenge) {
-				data->prev_challenge_len = len;
-				memcpy(data->prev_challenge, reqData, len);
-			}
-		}
-		return eap_mschapv2_challenge(sm, data, ret, req, respDataLen);
+		if (!using_prev_challenge)
+			eap_mschapv2_copy_challenge(data, reqData, reqDataLen);
+		return eap_mschapv2_challenge(sm, data, ret, ms, len,
+					      req->identifier, respDataLen);
 	case MSCHAPV2_OP_SUCCESS:
-		return eap_mschapv2_success(sm, data, ret, req, respDataLen);
+		return eap_mschapv2_success(sm, data, ret, ms, len,
+					    req->identifier, respDataLen);
 	case MSCHAPV2_OP_FAILURE:
-		return eap_mschapv2_failure(sm, data, ret, req, respDataLen);
+		return eap_mschapv2_failure(sm, data, ret, ms, len,
+					    req->identifier, respDataLen);
 	default:
 		wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Unknown op %d - ignored",
-			   req->op_code);
+			   ms->op_code);
 		ret->ignore = TRUE;
 		return NULL;
 	}
@@ -720,18 +883,18 @@
 	if (!data->master_key_valid || !data->success)
 		return NULL;
 
-	if (data->peer_challenge) {
+	if (data->full_key) {
 		/* EAP-FAST needs both send and receive keys */
 		key_len = 2 * MSCHAPV2_KEY_LEN;
 	} else {
 		key_len = MSCHAPV2_KEY_LEN;
 	}
 
-	key = malloc(key_len);
+	key = os_malloc(key_len);
 	if (key == NULL)
 		return NULL;
 
-	if (data->peer_challenge) {
+	if (data->full_key) {
 		get_asymetric_start_key(data->master_key, key,
 					MSCHAPV2_KEY_LEN, 0, 0);
 		get_asymetric_start_key(data->master_key,
@@ -750,13 +913,32 @@
 }
 
 
-const struct eap_method eap_method_mschapv2 =
+/**
+ * eap_peer_mschapv2_register - Register EAP-MSCHAPv2 peer method
+ * Returns: 0 on success, -1 on failure
+ *
+ * This function is used to register EAP-MSCHAPv2 peer method into the EAP
+ * method list.
+ */
+int eap_peer_mschapv2_register(void)
 {
-	.method = EAP_TYPE_MSCHAPV2,
-	.name = "MSCHAPV2",
-	.init = eap_mschapv2_init,
-	.deinit = eap_mschapv2_deinit,
-	.process = eap_mschapv2_process,
-	.isKeyAvailable = eap_mschapv2_isKeyAvailable,
-	.getKey = eap_mschapv2_getKey,
-};
+	struct eap_method *eap;
+	int ret;
+
+	eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
+				    EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2,
+				    "MSCHAPV2");
+	if (eap == NULL)
+		return -1;
+
+	eap->init = eap_mschapv2_init;
+	eap->deinit = eap_mschapv2_deinit;
+	eap->process = eap_mschapv2_process;
+	eap->isKeyAvailable = eap_mschapv2_isKeyAvailable;
+	eap->getKey = eap_mschapv2_getKey;
+
+	ret = eap_peer_method_register(eap);
+	if (ret)
+		eap_peer_method_free(eap);
+	return ret;
+}
Index: sha1.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/sha1.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/sha1.c -L contrib/wpa_supplicant/sha1.c -u -r1.2 -r1.3
--- contrib/wpa_supplicant/sha1.c
+++ contrib/wpa_supplicant/sha1.c
@@ -1,6 +1,6 @@
 /*
  * SHA1 hash implementation and interface functions
- * Copyright (c) 2003-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2003-2005, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -12,9 +12,7 @@
  * See README and COPYING for more details.
  */
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
+#include "includes.h"
 
 #include "common.h"
 #include "sha1.h"
@@ -36,9 +34,8 @@
 {
 	unsigned char k_pad[64]; /* padding - key XORd with ipad/opad */
 	unsigned char tk[20];
-	int i;
 	const u8 *_addr[6];
-	size_t _len[6];
+	size_t _len[6], i;
 
 	if (num_elem > 5) {
 		/*
@@ -65,8 +62,8 @@
 	 * and text is the data being protected */
 
 	/* start out by storing key in ipad */
-	memset(k_pad, 0, sizeof(k_pad));
-	memcpy(k_pad, key, key_len);
+	os_memset(k_pad, 0, sizeof(k_pad));
+	os_memcpy(k_pad, key, key_len);
 	/* XOR key with ipad values */
 	for (i = 0; i < 64; i++)
 		k_pad[i] ^= 0x36;
@@ -80,8 +77,8 @@
 	}
 	sha1_vector(1 + num_elem, _addr, _len, mac);
 
-	memset(k_pad, 0, sizeof(k_pad));
-	memcpy(k_pad, key, key_len);
+	os_memset(k_pad, 0, sizeof(k_pad));
+	os_memcpy(k_pad, key, key_len);
 	/* XOR key with opad values */
 	for (i = 0; i < 64; i++)
 		k_pad[i] ^= 0x5c;
@@ -129,7 +126,7 @@
 	u8 zero = 0, counter = 0;
 	size_t pos, plen;
 	u8 hash[SHA1_MAC_LEN];
-	size_t label_len = strlen(label);
+	size_t label_len = os_strlen(label);
 	const unsigned char *addr[4];
 	size_t len[4];
 
@@ -152,7 +149,7 @@
 		} else {
 			hmac_sha1_vector(key, key_len, 4, addr, len,
 					 hash);
-			memcpy(&buf[pos], hash, plen);
+			os_memcpy(&buf[pos], hash, plen);
 			break;
 		}
 		counter++;
@@ -180,7 +177,7 @@
 	unsigned char counter = 0;
 	size_t pos, plen;
 	u8 hash[SHA1_MAC_LEN];
-	size_t label_len = strlen(label);
+	size_t label_len = os_strlen(label);
 	u8 output_len[2];
 	const unsigned char *addr[5];
 	size_t len[5];
@@ -204,10 +201,10 @@
 		plen = buf_len - pos;
 		hmac_sha1_vector(key, key_len, 5, addr, len, hash);
 		if (plen >= SHA1_MAC_LEN) {
-			memcpy(&buf[pos], hash, SHA1_MAC_LEN);
+			os_memcpy(&buf[pos], hash, SHA1_MAC_LEN);
 			pos += SHA1_MAC_LEN;
 		} else {
-			memcpy(&buf[pos], hash, plen);
+			os_memcpy(&buf[pos], hash, plen);
 			break;
 		}
 		len[0] = SHA1_MAC_LEN;
@@ -224,18 +221,19 @@
  * @seed_len: Length of the seed
  * @out: Buffer for the generated pseudo-random key
  * @outlen: Number of bytes of key to generate
-*
+ * Returns: 0 on success, -1 on failure.
+ *
  * This function is used to derive new, cryptographically separate keys from a
  * given key in TLS. This PRF is defined in RFC 2246, Chapter 5.
  */
 int tls_prf(const u8 *secret, size_t secret_len, const char *label,
 	    const u8 *seed, size_t seed_len, u8 *out, size_t outlen)
 {
-	size_t L_S1, L_S2;
+	size_t L_S1, L_S2, i;
 	const u8 *S1, *S2;
 	u8 A_MD5[MD5_MAC_LEN], A_SHA1[SHA1_MAC_LEN];
 	u8 P_MD5[MD5_MAC_LEN], P_SHA1[SHA1_MAC_LEN];
-	int i, MD5_pos, SHA1_pos;
+	int MD5_pos, SHA1_pos;
 	const u8 *MD5_addr[3];
 	size_t MD5_len[3];
 	const unsigned char *SHA1_addr[3];
@@ -247,14 +245,14 @@
 	MD5_addr[0] = A_MD5;
 	MD5_len[0] = MD5_MAC_LEN;
 	MD5_addr[1] = (unsigned char *) label;
-	MD5_len[1] = strlen(label);
+	MD5_len[1] = os_strlen(label);
 	MD5_addr[2] = seed;
 	MD5_len[2] = seed_len;
 
 	SHA1_addr[0] = A_SHA1;
 	SHA1_len[0] = SHA1_MAC_LEN;
 	SHA1_addr[1] = (unsigned char *) label;
-	SHA1_len[1] = strlen(label);
+	SHA1_len[1] = os_strlen(label);
 	SHA1_addr[2] = seed;
 	SHA1_len[2] = seed_len;
 
@@ -297,7 +295,7 @@
 
 
 static void pbkdf2_sha1_f(const char *passphrase, const char *ssid,
-			  size_t ssid_len, int iterations, int count,
+			  size_t ssid_len, int iterations, unsigned int count,
 			  u8 *digest)
 {
 	unsigned char tmp[SHA1_MAC_LEN], tmp2[SHA1_MAC_LEN];
@@ -305,7 +303,7 @@
 	unsigned char count_buf[4];
 	const u8 *addr[2];
 	size_t len[2];
-	size_t passphrase_len = strlen(passphrase);
+	size_t passphrase_len = os_strlen(passphrase);
 
 	addr[0] = (u8 *) ssid;
 	len[0] = ssid_len;
@@ -323,12 +321,12 @@
 	count_buf[2] = (count >> 8) & 0xff;
 	count_buf[3] = count & 0xff;
 	hmac_sha1_vector((u8 *) passphrase, passphrase_len, 2, addr, len, tmp);
-	memcpy(digest, tmp, SHA1_MAC_LEN);
+	os_memcpy(digest, tmp, SHA1_MAC_LEN);
 
 	for (i = 1; i < iterations; i++) {
 		hmac_sha1((u8 *) passphrase, passphrase_len, tmp, SHA1_MAC_LEN,
 			  tmp2);
-		memcpy(tmp, tmp2, SHA1_MAC_LEN);
+		os_memcpy(tmp, tmp2, SHA1_MAC_LEN);
 		for (j = 0; j < SHA1_MAC_LEN; j++)
 			digest[j] ^= tmp2[j];
 	}
@@ -351,7 +349,7 @@
 void pbkdf2_sha1(const char *passphrase, const char *ssid, size_t ssid_len,
 		 int iterations, u8 *buf, size_t buflen)
 {
-	int count = 0;
+	unsigned int count = 0;
 	unsigned char *pos = buf;
 	size_t left = buflen, plen;
 	unsigned char digest[SHA1_MAC_LEN];
@@ -361,24 +359,28 @@
 		pbkdf2_sha1_f(passphrase, ssid, ssid_len, iterations, count,
 			      digest);
 		plen = left > SHA1_MAC_LEN ? SHA1_MAC_LEN : left;
-		memcpy(pos, digest, plen);
+		os_memcpy(pos, digest, plen);
 		pos += plen;
 		left -= plen;
 	}
 }
 
 
-#ifndef EAP_TLS_FUNCS
+#ifdef INTERNAL_SHA1
 
-typedef struct {
+struct SHA1Context {
 	u32 state[5];
 	u32 count[2];
 	unsigned char buffer[64];
-} SHA1_CTX;
+};
+
+typedef struct SHA1Context SHA1_CTX;
 
-static void SHA1Init(SHA1_CTX *context);
-static void SHA1Update(SHA1_CTX *context, const void *data, u32 len);
-static void SHA1Final(unsigned char digest[20], SHA1_CTX* context);
+#ifndef CONFIG_CRYPTO_INTERNAL
+static void SHA1Init(struct SHA1Context *context);
+static void SHA1Update(struct SHA1Context *context, const void *data, u32 len);
+static void SHA1Final(unsigned char digest[20], struct SHA1Context *context);
+#endif /* CONFIG_CRYPTO_INTERNAL */
 static void SHA1Transform(u32 state[5], const unsigned char buffer[64]);
 
 
@@ -393,7 +395,7 @@
 		 u8 *mac)
 {
 	SHA1_CTX ctx;
-	int i;
+	size_t i;
 
 	SHA1Init(&ctx);
 	for (i = 0; i < num_elem; i++)
@@ -402,19 +404,57 @@
 }
 
 
-/**
- * sha1_transform - Perform one SHA-1 transform step
- * @state: SHA-1 state
- * @data: Input data for the SHA-1 transform
- *
- * This function is used to implement random number generation specified in
- * NIST FIPS Publication 186-2 for EAP-SIM. This PRF uses a function that is
- * similar to SHA-1, but has different message padding and as such, access to
- * just part of the SHA-1 is needed.
- */
-void sha1_transform(u8 *state, const u8 data[64])
+int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen)
 {
-	SHA1Transform((u32 *) state, data);
+	u8 xkey[64];
+	u32 t[5], _t[5];
+	int i, j, m, k;
+	u8 *xpos = x;
+	u32 carry;
+
+	if (seed_len > sizeof(xkey))
+		seed_len = sizeof(xkey);
+
+	/* FIPS 186-2 + change notice 1 */
+
+	os_memcpy(xkey, seed, seed_len);
+	os_memset(xkey + seed_len, 0, 64 - seed_len);
+	t[0] = 0x67452301;
+	t[1] = 0xEFCDAB89;
+	t[2] = 0x98BADCFE;
+	t[3] = 0x10325476;
+	t[4] = 0xC3D2E1F0;
+
+	m = xlen / 40;
+	for (j = 0; j < m; j++) {
+		/* XSEED_j = 0 */
+		for (i = 0; i < 2; i++) {
+			/* XVAL = (XKEY + XSEED_j) mod 2^b */
+
+			/* w_i = G(t, XVAL) */
+			os_memcpy(_t, t, 20);
+			SHA1Transform(_t, xkey);
+			_t[0] = host_to_be32(_t[0]);
+			_t[1] = host_to_be32(_t[1]);
+			_t[2] = host_to_be32(_t[2]);
+			_t[3] = host_to_be32(_t[3]);
+			_t[4] = host_to_be32(_t[4]);
+			os_memcpy(xpos, _t, 20);
+
+			/* XKEY = (1 + XKEY + w_i) mod 2^b */
+			carry = 1;
+			for (k = 19; k >= 0; k--) {
+				carry += xkey[k] + xpos[k];
+				xkey[k] = carry & 0xff;
+				carry >>= 8;
+			}
+
+			xpos += SHA1_MAC_LEN;
+		}
+		/* x_j = w_0|w_1 */
+	}
+
+	return 0;
 }
 
 
@@ -479,11 +519,11 @@
 
 -----------------
 Modified 4/01
-By Jouni Malinen <jkmaline at cc.hut.fi>
+By Jouni Malinen <j at w1.fi>
 Minor changes to match the coding style used in Dynamics.
 
 Modified September 24, 2004
-By Jouni Malinen <jkmaline at cc.hut.fi>
+By Jouni Malinen <j at w1.fi>
 Fixed alignment issue in SHA1Transform when SHA1HANDSOFF is defined.
 
 */
@@ -557,7 +597,7 @@
 #ifdef SHA1HANDSOFF
 	u32 workspace[16];
 	block = (CHAR64LONG16 *) workspace;
-	memcpy(block, buffer, 64);
+	os_memcpy(block, buffer, 64);
 #else
 	block = (CHAR64LONG16 *) buffer;
 #endif
@@ -597,14 +637,14 @@
 	/* Wipe variables */
 	a = b = c = d = e = 0;
 #ifdef SHA1HANDSOFF
-	memset(block, 0, 64);
+	os_memset(block, 0, 64);
 #endif
 }
 
 
 /* SHA1Init - Initialize new context */
 
-static void SHA1Init(SHA1_CTX* context)
+void SHA1Init(SHA1_CTX* context)
 {
 	/* SHA1 initialization constants */
 	context->state[0] = 0x67452301;
@@ -618,7 +658,7 @@
 
 /* Run your data through this. */
 
-static void SHA1Update(SHA1_CTX* context, const void *_data, u32 len)
+void SHA1Update(SHA1_CTX* context, const void *_data, u32 len)
 {
 	u32 i, j;
 	const unsigned char *data = _data;
@@ -631,7 +671,7 @@
 		context->count[1]++;
 	context->count[1] += (len >> 29);
 	if ((j + len) > 63) {
-		memcpy(&context->buffer[j], data, (i = 64-j));
+		os_memcpy(&context->buffer[j], data, (i = 64-j));
 		SHA1Transform(context->state, context->buffer);
 		for ( ; i + 63 < len; i += 64) {
 			SHA1Transform(context->state, &data[i]);
@@ -639,7 +679,7 @@
 		j = 0;
 	}
 	else i = 0;
-	memcpy(&context->buffer[j], &data[i], len - i);
+	os_memcpy(&context->buffer[j], &data[i], len - i);
 #ifdef VERBOSE
 	SHAPrintContext(context, "after ");
 #endif
@@ -648,7 +688,7 @@
 
 /* Add padding and return the message digest. */
 
-static void SHA1Final(unsigned char digest[20], SHA1_CTX* context)
+void SHA1Final(unsigned char digest[20], SHA1_CTX* context)
 {
 	u32 i;
 	unsigned char finalcount[8];
@@ -671,324 +711,12 @@
 	}
 	/* Wipe variables */
 	i = 0;
-	memset(context->buffer, 0, 64);
-	memset(context->state, 0, 20);
-	memset(context->count, 0, 8);
-	memset(finalcount, 0, 8);
+	os_memset(context->buffer, 0, 64);
+	os_memset(context->state, 0, 20);
+	os_memset(context->count, 0, 8);
+	os_memset(finalcount, 0, 8);
 }
 
 /* ===== end - public domain SHA1 implementation ===== */
 
-#endif /* EAP_TLS_FUNCS */
-
-
-#ifdef TEST_MAIN
-
-#include "md5.c"
-
-static int test_eap_fast(void)
-{
-	/* draft-cam-winget-eap-fast-01.txt */
-	const u8 pac_key[] = {
-		0x0B, 0x97, 0x39, 0x0F, 0x37, 0x51, 0x78, 0x09,
-		0x81, 0x1E, 0xFD, 0x9C, 0x6E, 0x65, 0x94, 0x2B,
-		0x63, 0x2C, 0xE9, 0x53, 0x89, 0x38, 0x08, 0xBA,
-		0x36, 0x0B, 0x03, 0x7C, 0xD1, 0x85, 0xE4, 0x14
-	};
-	const u8 seed[] = {
-		0x3F, 0xFB, 0x11, 0xC4, 0x6C, 0xBF, 0xA5, 0x7A,
-		0x54, 0x40, 0xDA, 0xE8, 0x22, 0xD3, 0x11, 0xD3,
-		0xF7, 0x6D, 0xE4, 0x1D, 0xD9, 0x33, 0xE5, 0x93,
-		0x70, 0x97, 0xEB, 0xA9, 0xB3, 0x66, 0xF4, 0x2A,
-		0x00, 0x00, 0x00, 0x02, 0x6A, 0x66, 0x43, 0x2A,
-		0x8D, 0x14, 0x43, 0x2C, 0xEC, 0x58, 0x2D, 0x2F,
-		0xC7, 0x9C, 0x33, 0x64, 0xBA, 0x04, 0xAD, 0x3A,
-		0x52, 0x54, 0xD6, 0xA5, 0x79, 0xAD, 0x1E, 0x00
-	};
-	const u8 master_secret[] = {
-		0x4A, 0x1A, 0x51, 0x2C, 0x01, 0x60, 0xBC, 0x02,
-		0x3C, 0xCF, 0xBC, 0x83, 0x3F, 0x03, 0xBC, 0x64,
-		0x88, 0xC1, 0x31, 0x2F, 0x0B, 0xA9, 0xA2, 0x77,
-		0x16, 0xA8, 0xD8, 0xE8, 0xBD, 0xC9, 0xD2, 0x29,
-		0x38, 0x4B, 0x7A, 0x85, 0xBE, 0x16, 0x4D, 0x27,
-		0x33, 0xD5, 0x24, 0x79, 0x87, 0xB1, 0xC5, 0xA2  
-	};
-	const u8 key_block[] = {
-		0x59, 0x59, 0xBE, 0x8E, 0x41, 0x3A, 0x77, 0x74,
-		0x8B, 0xB2, 0xE5, 0xD3, 0x60, 0xAC, 0x4D, 0x35,
-		0xDF, 0xFB, 0xC8, 0x1E, 0x9C, 0x24, 0x9C, 0x8B,
-		0x0E, 0xC3, 0x1D, 0x72, 0xC8, 0x84, 0x9D, 0x57,
-		0x48, 0x51, 0x2E, 0x45, 0x97, 0x6C, 0x88, 0x70,
-		0xBE, 0x5F, 0x01, 0xD3, 0x64, 0xE7, 0x4C, 0xBB,
-		0x11, 0x24, 0xE3, 0x49, 0xE2, 0x3B, 0xCD, 0xEF,
-		0x7A, 0xB3, 0x05, 0x39, 0x5D, 0x64, 0x8A, 0x44,
-		0x11, 0xB6, 0x69, 0x88, 0x34, 0x2E, 0x8E, 0x29,
-		0xD6, 0x4B, 0x7D, 0x72, 0x17, 0x59, 0x28, 0x05,
-		0xAF, 0xF9, 0xB7, 0xFF, 0x66, 0x6D, 0xA1, 0x96,
-		0x8F, 0x0B, 0x5E, 0x06, 0x46, 0x7A, 0x44, 0x84,
-		0x64, 0xC1, 0xC8, 0x0C, 0x96, 0x44, 0x09, 0x98,
-		0xFF, 0x92, 0xA8, 0xB4, 0xC6, 0x42, 0x28, 0x71
-	};
-	const u8 sks[] = {
-		0xD6, 0x4B, 0x7D, 0x72, 0x17, 0x59, 0x28, 0x05,
-		0xAF, 0xF9, 0xB7, 0xFF, 0x66, 0x6D, 0xA1, 0x96,
-		0x8F, 0x0B, 0x5E, 0x06, 0x46, 0x7A, 0x44, 0x84,
-		0x64, 0xC1, 0xC8, 0x0C, 0x96, 0x44, 0x09, 0x98,
-		0xFF, 0x92, 0xA8, 0xB4, 0xC6, 0x42, 0x28, 0x71
-	};
-	const u8 isk[] = {
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-	};
-	const u8 imck[] = {
-		0x16, 0x15, 0x3C, 0x3F, 0x21, 0x55, 0xEF, 0xD9,
-		0x7F, 0x34, 0xAE, 0xC8, 0x1A, 0x4E, 0x66, 0x80,
-		0x4C, 0xC3, 0x76, 0xF2, 0x8A, 0xA9, 0x6F, 0x96,
-		0xC2, 0x54, 0x5F, 0x8C, 0xAB, 0x65, 0x02, 0xE1,
-		0x18, 0x40, 0x7B, 0x56, 0xBE, 0xEA, 0xA7, 0xC5,
-		0x76, 0x5D, 0x8F, 0x0B, 0xC5, 0x07, 0xC6, 0xB9,
-		0x04, 0xD0, 0x69, 0x56, 0x72, 0x8B, 0x6B, 0xB8,
-		0x15, 0xEC, 0x57, 0x7B
-	};
-	const u8 msk[] = {
-		0x4D, 0x83, 0xA9, 0xBE, 0x6F, 0x8A, 0x74, 0xED,
-		0x6A, 0x02, 0x66, 0x0A, 0x63, 0x4D, 0x2C, 0x33,
-		0xC2, 0xDA, 0x60, 0x15, 0xC6, 0x37, 0x04, 0x51,
-		0x90, 0x38, 0x63, 0xDA, 0x54, 0x3E, 0x14, 0xB9,
-		0x27, 0x99, 0x18, 0x1E, 0x07, 0xBF, 0x0F, 0x5A,
-		0x5E, 0x3C, 0x32, 0x93, 0x80, 0x8C, 0x6C, 0x49,
-		0x67, 0xED, 0x24, 0xFE, 0x45, 0x40, 0xA0, 0x59,
-		0x5E, 0x37, 0xC2, 0xE9, 0xD0, 0x5D, 0x0A, 0xE3
-	};
-	u8 tlv[] = {
-		0x80, 0x0C, 0x00, 0x38, 0x00, 0x01, 0x01, 0x00,
-		0xD8, 0x6A, 0x8C, 0x68, 0x3C, 0x32, 0x31, 0xA8,
-		0x56, 0x63, 0xB6, 0x40, 0x21, 0xFE, 0x21, 0x14,
-		0x4E, 0xE7, 0x54, 0x20, 0x79, 0x2D, 0x42, 0x62,
-		0xC9, 0xBF, 0x53, 0x7F, 0x54, 0xFD, 0xAC, 0x58,
-		0x43, 0x24, 0x6E, 0x30, 0x92, 0x17, 0x6D, 0xCF,
-		0xE6, 0xE0, 0x69, 0xEB, 0x33, 0x61, 0x6A, 0xCC,
-		0x05, 0xC5, 0x5B, 0xB7
-	};
-	const u8 compound_mac[] = {
-		0x43, 0x24, 0x6E, 0x30, 0x92, 0x17, 0x6D, 0xCF,
-		0xE6, 0xE0, 0x69, 0xEB, 0x33, 0x61, 0x6A, 0xCC,
-		0x05, 0xC5, 0x5B, 0xB7
-	};
-	u8 buf[512];
-	const u8 *simck, *cmk;
-	int errors = 0;
-
-	printf("EAP-FAST test cases\n");
-
-	printf("- T-PRF (SHA1) test case / master_secret\n");
-	sha1_t_prf(pac_key, sizeof(pac_key), "PAC to master secret label hash",
-		   seed, sizeof(seed), buf, sizeof(master_secret));
-	if (memcmp(master_secret, buf, sizeof(master_secret)) != 0) {
-		printf("T-PRF test - FAILED!\n");
-		errors++;
-	}
-
-	printf("- PRF (TLS, SHA1/MD5) test case / key_block\n");
-	tls_prf(master_secret, sizeof(master_secret), "key expansion",
-		seed, sizeof(seed), buf, sizeof(key_block));
-	if (memcmp(key_block, buf, sizeof(key_block)) != 0) {
-		printf("PRF test - FAILED!\n");
-		errors++;
-	}
-
-	printf("- T-PRF (SHA1) test case / IMCK\n");
-	sha1_t_prf(sks, sizeof(sks), "Inner Methods Compound Keys",
-		   isk, sizeof(isk), buf, sizeof(imck));
-	if (memcmp(imck, buf, sizeof(imck)) != 0) {
-		printf("T-PRF test - FAILED!\n");
-		errors++;
-	}
-
-	simck = imck;
-	cmk = imck + 40;
-
-	printf("- T-PRF (SHA1) test case / MSK\n");
-	sha1_t_prf(simck, 40, "Session Key Generating Function",
-		   "", 0, buf, sizeof(msk));
-	if (memcmp(msk, buf, sizeof(msk)) != 0) {
-		printf("T-PRF test - FAILED!\n");
-		errors++;
-	}
-
-	printf("- Compound MAC test case\n");
-	memset(tlv + sizeof(tlv) - 20, 0, 20);
-	hmac_sha1(cmk, 20, tlv, sizeof(tlv), tlv + sizeof(tlv) - 20);
-	if (memcmp(tlv + sizeof(tlv) - 20, compound_mac, sizeof(compound_mac))
-	    != 0) {
-		printf("Compound MAC test - FAILED!\n");
-		errors++;
-	}
-
-	return errors;
-}
-
-
-static u8 key0[] =
-{
-	0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
-	0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
-	0x0b, 0x0b, 0x0b, 0x0b
-};
-static u8 data0[] = "Hi There";
-static u8 prf0[] =
-{
-	0xbc, 0xd4, 0xc6, 0x50, 0xb3, 0x0b, 0x96, 0x84,
-	0x95, 0x18, 0x29, 0xe0, 0xd7, 0x5f, 0x9d, 0x54,
-	0xb8, 0x62, 0x17, 0x5e, 0xd9, 0xf0, 0x06, 0x06,
-	0xe1, 0x7d, 0x8d, 0xa3, 0x54, 0x02, 0xff, 0xee,
-	0x75, 0xdf, 0x78, 0xc3, 0xd3, 0x1e, 0x0f, 0x88,
-	0x9f, 0x01, 0x21, 0x20, 0xc0, 0x86, 0x2b, 0xeb,
-	0x67, 0x75, 0x3e, 0x74, 0x39, 0xae, 0x24, 0x2e,
-	0xdb, 0x83, 0x73, 0x69, 0x83, 0x56, 0xcf, 0x5a
-};
-
-static u8 key1[] = "Jefe";
-static u8 data1[] = "what do ya want for nothing?";
-static u8 prf1[] =
-{
-	0x51, 0xf4, 0xde, 0x5b, 0x33, 0xf2, 0x49, 0xad,
-	0xf8, 0x1a, 0xeb, 0x71, 0x3a, 0x3c, 0x20, 0xf4,
-	0xfe, 0x63, 0x14, 0x46, 0xfa, 0xbd, 0xfa, 0x58,
-	0x24, 0x47, 0x59, 0xae, 0x58, 0xef, 0x90, 0x09,
-	0xa9, 0x9a, 0xbf, 0x4e, 0xac, 0x2c, 0xa5, 0xfa,
-	0x87, 0xe6, 0x92, 0xc4, 0x40, 0xeb, 0x40, 0x02,
-	0x3e, 0x7b, 0xab, 0xb2, 0x06, 0xd6, 0x1d, 0xe7,
-	0xb9, 0x2f, 0x41, 0x52, 0x90, 0x92, 0xb8, 0xfc
-};
-
-
-static u8 key2[] =
-{
-	0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-	0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-	0xaa, 0xaa, 0xaa, 0xaa
-};
-static u8 data2[] =
-{
-	0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
-	0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
-	0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
-	0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
-	0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
-	0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
-	0xdd, 0xdd
-};
-static u8 prf2[] =
-{
-	0xe1, 0xac, 0x54, 0x6e, 0xc4, 0xcb, 0x63, 0x6f,
-	0x99, 0x76, 0x48, 0x7b, 0xe5, 0xc8, 0x6b, 0xe1,
-	0x7a, 0x02, 0x52, 0xca, 0x5d, 0x8d, 0x8d, 0xf1,
-	0x2c, 0xfb, 0x04, 0x73, 0x52, 0x52, 0x49, 0xce,
-	0x9d, 0xd8, 0xd1, 0x77, 0xea, 0xd7, 0x10, 0xbc,
-	0x9b, 0x59, 0x05, 0x47, 0x23, 0x91, 0x07, 0xae,
-	0xf7, 0xb4, 0xab, 0xd4, 0x3d, 0x87, 0xf0, 0xa6,
-	0x8f, 0x1c, 0xbd, 0x9e, 0x2b, 0x6f, 0x76, 0x07
-};
-
-
-struct passphrase_test {
-	char *passphrase;
-	char *ssid;
-	char psk[32];
-};
-
-static struct passphrase_test passphrase_tests[] =
-{
-	{
-		"password",
-		"IEEE",
-		{
-			0xf4, 0x2c, 0x6f, 0xc5, 0x2d, 0xf0, 0xeb, 0xef,
-			0x9e, 0xbb, 0x4b, 0x90, 0xb3, 0x8a, 0x5f, 0x90,
-			0x2e, 0x83, 0xfe, 0x1b, 0x13, 0x5a, 0x70, 0xe2,
-			0x3a, 0xed, 0x76, 0x2e, 0x97, 0x10, 0xa1, 0x2e
-		}
-	},
-	{
-		"ThisIsAPassword",
-		"ThisIsASSID",
-		{
-			0x0d, 0xc0, 0xd6, 0xeb, 0x90, 0x55, 0x5e, 0xd6,
-			0x41, 0x97, 0x56, 0xb9, 0xa1, 0x5e, 0xc3, 0xe3,
-			0x20, 0x9b, 0x63, 0xdf, 0x70, 0x7d, 0xd5, 0x08,
-			0xd1, 0x45, 0x81, 0xf8, 0x98, 0x27, 0x21, 0xaf
-		}
-	},
-	{
-		"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
-		"ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ",
-		{
-			0xbe, 0xcb, 0x93, 0x86, 0x6b, 0xb8, 0xc3, 0x83,
-			0x2c, 0xb7, 0x77, 0xc2, 0xf5, 0x59, 0x80, 0x7c,
-			0x8c, 0x59, 0xaf, 0xcb, 0x6e, 0xae, 0x73, 0x48,
-			0x85, 0x00, 0x13, 0x00, 0xa9, 0x81, 0xcc, 0x62
-		}
-	},
-};
-
-#define NUM_PASSPHRASE_TESTS \
-(sizeof(passphrase_tests) / sizeof(passphrase_tests[0]))
-
-
-int main(int argc, char *argv[])
-{
-	u8 res[512];
-	int ret = 0, i;
-
-	printf("PRF-SHA1 test cases:\n");
-
-	sha1_prf(key0, sizeof(key0), "prefix", data0, sizeof(data0) - 1,
-		 res, sizeof(prf0));
-	if (memcmp(res, prf0, sizeof(prf0)) == 0)
-		printf("Test case 0 - OK\n");
-	else {
-		printf("Test case 0 - FAILED!\n");
-		ret++;
-	}
-
-	sha1_prf(key1, sizeof(key1) - 1, "prefix", data1, sizeof(data1) - 1,
-		 res, sizeof(prf1));
-	if (memcmp(res, prf1, sizeof(prf1)) == 0)
-		printf("Test case 1 - OK\n");
-	else {
-		printf("Test case 1 - FAILED!\n");
-		ret++;
-	}
-
-	sha1_prf(key2, sizeof(key2), "prefix", data2, sizeof(data2),
-		 res, sizeof(prf2));
-	if (memcmp(res, prf2, sizeof(prf2)) == 0)
-		printf("Test case 2 - OK\n");
-	else {
-		printf("Test case 2 - FAILED!\n");
-		ret++;
-	}
-
-	ret += test_eap_fast();
-
-	printf("PBKDF2-SHA1 Passphrase test cases:\n");
-	for (i = 0; i < NUM_PASSPHRASE_TESTS; i++) {
-		u8 psk[32];
-		struct passphrase_test *test = &passphrase_tests[i];
-		pbkdf2_sha1(test->passphrase,
-			    test->ssid, strlen(test->ssid),
-			    4096, psk, 32);
-		if (memcmp(psk, test->psk, 32) == 0)
-			printf("Test case %d - OK\n", i);
-		else {
-			printf("Test case %d - FAILED!\n", i);
-			ret++;
-		}
-	}
-
-	return ret;
-}
-#endif /* TEST_MAIN */
+#endif /* INTERNAL_SHA1 */
Index: aes_wrap.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/aes_wrap.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/aes_wrap.c -L contrib/wpa_supplicant/aes_wrap.c -u -r1.2 -r1.3
--- contrib/wpa_supplicant/aes_wrap.c
+++ contrib/wpa_supplicant/aes_wrap.c
@@ -7,7 +7,7 @@
  * - AES-128 EAX mode encryption/decryption
  * - AES-128 CBC
  *
- * Copyright (c) 2003-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2003-2005, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -19,17 +19,18 @@
  * See README and COPYING for more details.
  */
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
+#include "includes.h"
+
 #include "common.h"
 #include "aes_wrap.h"
 #include "crypto.h"
 
-#ifndef EAP_TLS_FUNCS
+#ifdef INTERNAL_AES
 #include "aes.c"
-#endif /* EAP_TLS_FUNCS */
+#endif /* INTERNAL_AES */
+
 
+#ifndef CONFIG_NO_AES_WRAP
 
 /**
  * aes_wrap - Wrap keys with AES Key Wrap Algorithm (128-bit KEK) (RFC3394)
@@ -49,8 +50,8 @@
 	r = cipher + 8;
 
 	/* 1) Initialize variables. */
-	memset(a, 0xa6, 8);
-	memcpy(r, plain, 8 * n);
+	os_memset(a, 0xa6, 8);
+	os_memcpy(r, plain, 8 * n);
 
 	ctx = aes_encrypt_init(kek, 16);
 	if (ctx == NULL)
@@ -66,12 +67,12 @@
 	for (j = 0; j <= 5; j++) {
 		r = cipher + 8;
 		for (i = 1; i <= n; i++) {
-			memcpy(b, a, 8);
-			memcpy(b + 8, r, 8);
+			os_memcpy(b, a, 8);
+			os_memcpy(b + 8, r, 8);
 			aes_encrypt(ctx, b, b);
-			memcpy(a, b, 8);
+			os_memcpy(a, b, 8);
 			a[7] ^= n * j + i;
-			memcpy(r, b + 8, 8);
+			os_memcpy(r, b + 8, 8);
 			r += 8;
 		}
 	}
@@ -86,6 +87,8 @@
 	return 0;
 }
 
+#endif /* CONFIG_NO_AES_WRAP */
+
 
 /**
  * aes_unwrap - Unwrap key with AES Key Wrap Algorithm (128-bit KEK) (RFC3394)
@@ -102,9 +105,9 @@
 	void *ctx;
 
 	/* 1) Initialize variables. */
-	memcpy(a, cipher, 8);
+	os_memcpy(a, cipher, 8);
 	r = plain;
-	memcpy(r, cipher + 8, 8 * n);
+	os_memcpy(r, cipher + 8, 8 * n);
 
 	ctx = aes_decrypt_init(kek, 16);
 	if (ctx == NULL)
@@ -120,13 +123,13 @@
 	for (j = 5; j >= 0; j--) {
 		r = plain + (n - 1) * 8;
 		for (i = n; i >= 1; i--) {
-			memcpy(b, a, 8);
+			os_memcpy(b, a, 8);
 			b[7] ^= n * j + i;
 
-			memcpy(b + 8, r, 8);
+			os_memcpy(b + 8, r, 8);
 			aes_decrypt(ctx, b, b);
-			memcpy(a, b, 8);
-			memcpy(r, b + 8, 8);
+			os_memcpy(a, b, 8);
+			os_memcpy(r, b + 8, 8);
 			r -= 8;
 		}
 	}
@@ -148,6 +151,8 @@
 
 #define BLOCK_SIZE 16
 
+#ifndef CONFIG_NO_AES_OMAC1
+
 static void gf_mulx(u8 *pad)
 {
 	int i, carry;
@@ -162,8 +167,8 @@
 
 
 /**
- * omac1_aes_128 - One-Key CBC MAC (OMAC1) hash with AES-128
- * @key: Key for the hash operation
+ * omac1_aes_128 - One-Key CBC MAC (OMAC1) hash with AES-128 (aka AES-CMAC)
+ * @key: 128-bit key for the hash operation
  * @data: Data buffer for which a MAC is determined
  * @data: Length of data buffer in bytes
  * @mac: Buffer for MAC (128 bits, i.e., 16 bytes)
@@ -174,13 +179,12 @@
 	void *ctx;
 	u8 cbc[BLOCK_SIZE], pad[BLOCK_SIZE];
 	const u8 *pos = data;
-	int i;
-	size_t left = data_len;
+	size_t i, left = data_len;
 
 	ctx = aes_encrypt_init(key, 16);
 	if (ctx == NULL)
 		return -1;
-	memset(cbc, 0, BLOCK_SIZE);
+	os_memset(cbc, 0, BLOCK_SIZE);
 
 	while (left >= BLOCK_SIZE) {
 		for (i = 0; i < BLOCK_SIZE; i++)
@@ -190,7 +194,7 @@
 		left -= BLOCK_SIZE;
 	}
 
-	memset(pad, 0, BLOCK_SIZE);
+	os_memset(pad, 0, BLOCK_SIZE);
 	aes_encrypt(ctx, pad, pad);
 	gf_mulx(pad);
 
@@ -208,6 +212,8 @@
 	return 0;
 }
 
+#endif /* CONFIG_NO_AES_OMAC1 */
+
 
 /**
  * aes_128_encrypt_block - Perform one AES 128-bit block operation
@@ -228,6 +234,8 @@
 }
 
 
+#ifndef CONFIG_NO_AES_CTR
+
 /**
  * aes_128_ctr_encrypt - AES-128 CTR mode encryption
  * @key: Key for encryption (16 bytes)
@@ -240,7 +248,7 @@
 			u8 *data, size_t data_len)
 {
 	void *ctx;
-	size_t len, left = data_len;
+	size_t j, len, left = data_len;
 	int i;
 	u8 *pos = data;
 	u8 counter[BLOCK_SIZE], buf[BLOCK_SIZE];
@@ -248,14 +256,14 @@
 	ctx = aes_encrypt_init(key, 16);
 	if (ctx == NULL)
 		return -1;
-	memcpy(counter, nonce, BLOCK_SIZE);
+	os_memcpy(counter, nonce, BLOCK_SIZE);
 
 	while (left > 0) {
 		aes_encrypt(ctx, counter, buf);
 
 		len = (left < BLOCK_SIZE) ? left : BLOCK_SIZE;
-		for (i = 0; i < len; i++)
-			pos[i] ^= buf[i];
+		for (j = 0; j < len; j++)
+			pos[j] ^= buf[j];
 		pos += len;
 		left -= len;
 
@@ -269,6 +277,10 @@
 	return 0;
 }
 
+#endif /* CONFIG_NO_AES_CTR */
+
+
+#ifndef CONFIG_NO_AES_EAX
 
 /**
  * aes_128_eax_encrypt - AES-128 EAX mode encryption
@@ -299,26 +311,26 @@
 		buf_len = hdr_len;
 	buf_len += 16;
 
-	buf = malloc(buf_len);
+	buf = os_malloc(buf_len);
 	if (buf == NULL)
 		return -1;
 
-	memset(buf, 0, 15);
+	os_memset(buf, 0, 15);
 
 	buf[15] = 0;
-	memcpy(buf + 16, nonce, nonce_len);
+	os_memcpy(buf + 16, nonce, nonce_len);
 	omac1_aes_128(key, buf, 16 + nonce_len, nonce_mac);
 
 	buf[15] = 1;
-	memcpy(buf + 16, hdr, hdr_len);
+	os_memcpy(buf + 16, hdr, hdr_len);
 	omac1_aes_128(key, buf, 16 + hdr_len, hdr_mac);
 
 	aes_128_ctr_encrypt(key, nonce_mac, data, data_len);
 	buf[15] = 2;
-	memcpy(buf + 16, data, data_len);
+	os_memcpy(buf + 16, data, data_len);
 	omac1_aes_128(key, buf, 16 + data_len, data_mac);
 
-	free(buf);
+	os_free(buf);
 
 	for (i = 0; i < BLOCK_SIZE; i++)
 		tag[i] = nonce_mac[i] ^ data_mac[i] ^ hdr_mac[i];
@@ -356,25 +368,25 @@
 		buf_len = hdr_len;
 	buf_len += 16;
 
-	buf = malloc(buf_len);
+	buf = os_malloc(buf_len);
 	if (buf == NULL)
 		return -1;
 
-	memset(buf, 0, 15);
+	os_memset(buf, 0, 15);
 
 	buf[15] = 0;
-	memcpy(buf + 16, nonce, nonce_len);
+	os_memcpy(buf + 16, nonce, nonce_len);
 	omac1_aes_128(key, buf, 16 + nonce_len, nonce_mac);
 
 	buf[15] = 1;
-	memcpy(buf + 16, hdr, hdr_len);
+	os_memcpy(buf + 16, hdr, hdr_len);
 	omac1_aes_128(key, buf, 16 + hdr_len, hdr_mac);
 
 	buf[15] = 2;
-	memcpy(buf + 16, data, data_len);
+	os_memcpy(buf + 16, data, data_len);
 	omac1_aes_128(key, buf, 16 + data_len, data_mac);
 
-	free(buf);
+	os_free(buf);
 
 	for (i = 0; i < BLOCK_SIZE; i++) {
 		if (tag[i] != (nonce_mac[i] ^ data_mac[i] ^ hdr_mac[i]))
@@ -386,6 +398,10 @@
 	return 0;
 }
 
+#endif /* CONFIG_NO_AES_EAX */
+
+
+#ifndef CONFIG_NO_AES_CBC
 
 /**
  * aes_128_cbc_encrypt - AES-128 CBC encryption
@@ -405,14 +421,14 @@
 	ctx = aes_encrypt_init(key, 16);
 	if (ctx == NULL)
 		return -1;
-	memcpy(cbc, iv, BLOCK_SIZE);
+	os_memcpy(cbc, iv, BLOCK_SIZE);
 
 	blocks = data_len / BLOCK_SIZE;
 	for (i = 0; i < blocks; i++) {
 		for (j = 0; j < BLOCK_SIZE; j++)
 			cbc[j] ^= pos[j];
 		aes_encrypt(ctx, cbc, cbc);
-		memcpy(pos, cbc, BLOCK_SIZE);
+		os_memcpy(pos, cbc, BLOCK_SIZE);
 		pos += BLOCK_SIZE;
 	}
 	aes_encrypt_deinit(ctx);
@@ -438,288 +454,19 @@
 	ctx = aes_decrypt_init(key, 16);
 	if (ctx == NULL)
 		return -1;
-	memcpy(cbc, iv, BLOCK_SIZE);
+	os_memcpy(cbc, iv, BLOCK_SIZE);
 
 	blocks = data_len / BLOCK_SIZE;
 	for (i = 0; i < blocks; i++) {
-		memcpy(tmp, pos, BLOCK_SIZE);
+		os_memcpy(tmp, pos, BLOCK_SIZE);
 		aes_decrypt(ctx, pos, pos);
 		for (j = 0; j < BLOCK_SIZE; j++)
 			pos[j] ^= cbc[j];
-		memcpy(cbc, tmp, BLOCK_SIZE);
+		os_memcpy(cbc, tmp, BLOCK_SIZE);
 		pos += BLOCK_SIZE;
 	}
 	aes_decrypt_deinit(ctx);
 	return 0;
 }
 
-
-#ifdef TEST_MAIN
-
-#ifdef __i386__
-#define rdtscll(val) \
-     __asm__ __volatile__("rdtsc" : "=A" (val))
-
-static void test_aes_perf(void)
-{
-	const int num_iters = 10;
-	int i;
-	unsigned int start, end;
-	u8 key[16], pt[16], ct[16];
-	void *ctx;
-
-	printf("keySetupEnc:");
-	for (i = 0; i < num_iters; i++) {
-		rdtscll(start);
-		ctx = aes_encrypt_init(key, 16);
-		rdtscll(end);
-		aes_encrypt_deinit(ctx);
-		printf(" %d", end - start);
-	}
-	printf("\n");
-
-	printf("Encrypt:");
-	ctx = aes_encrypt_init(key, 16);
-	for (i = 0; i < num_iters; i++) {
-		rdtscll(start);
-		aes_encrypt(ctx, pt, ct);
-		rdtscll(end);
-		printf(" %d", end - start);
-	}
-	aes_encrypt_deinit(ctx);
-	printf("\n");
-}
-#endif /* __i386__ */
-
-
-static int test_eax(void)
-{
-	u8 msg[] = { 0xF7, 0xFB };
-	u8 key[] = { 0x91, 0x94, 0x5D, 0x3F, 0x4D, 0xCB, 0xEE, 0x0B,
-		     0xF4, 0x5E, 0xF5, 0x22, 0x55, 0xF0, 0x95, 0xA4 };
-	u8 nonce[] = { 0xBE, 0xCA, 0xF0, 0x43, 0xB0, 0xA2, 0x3D, 0x84,
-		       0x31, 0x94, 0xBA, 0x97, 0x2C, 0x66, 0xDE, 0xBD };
-	u8 hdr[] = { 0xFA, 0x3B, 0xFD, 0x48, 0x06, 0xEB, 0x53, 0xFA };
-	u8 cipher[] = { 0x19, 0xDD, 0x5C, 0x4C, 0x93, 0x31, 0x04, 0x9D,
-			0x0B, 0xDA, 0xB0, 0x27, 0x74, 0x08, 0xF6, 0x79,
-			0x67, 0xE5 };
-	u8 data[sizeof(msg)], tag[BLOCK_SIZE];
-
-	memcpy(data, msg, sizeof(msg));
-	if (aes_128_eax_encrypt(key, nonce, sizeof(nonce), hdr, sizeof(hdr),
-				data, sizeof(data), tag)) {
-		printf("AES-128 EAX mode encryption failed\n");
-		return 1;
-	}
-	if (memcmp(data, cipher, sizeof(data)) != 0) {
-		printf("AES-128 EAX mode encryption returned invalid cipher "
-		       "text\n");
-		return 1;
-	}
-	if (memcmp(tag, cipher + sizeof(data), BLOCK_SIZE) != 0) {
-		printf("AES-128 EAX mode encryption returned invalid tag\n");
-		return 1;
-	}
-
-	if (aes_128_eax_decrypt(key, nonce, sizeof(nonce), hdr, sizeof(hdr),
-				data, sizeof(data), tag)) {
-		printf("AES-128 EAX mode decryption failed\n");
-		return 1;
-	}
-	if (memcmp(data, msg, sizeof(data)) != 0) {
-		printf("AES-128 EAX mode decryption returned invalid plain "
-		       "text\n");
-		return 1;
-	}
-
-	return 0;
-}
-
-
-static int test_cbc(void)
-{
-	struct cbc_test_vector {
-		u8 key[16];
-		u8 iv[16];
-		u8 plain[32];
-		u8 cipher[32];
-		size_t len;
-	} vectors[] = {
-		{
-			{ 0x06, 0xa9, 0x21, 0x40, 0x36, 0xb8, 0xa1, 0x5b,
-			  0x51, 0x2e, 0x03, 0xd5, 0x34, 0x12, 0x00, 0x06 },
-			{ 0x3d, 0xaf, 0xba, 0x42, 0x9d, 0x9e, 0xb4, 0x30,
-			  0xb4, 0x22, 0xda, 0x80, 0x2c, 0x9f, 0xac, 0x41 },
-			"Single block msg",
-			{ 0xe3, 0x53, 0x77, 0x9c, 0x10, 0x79, 0xae, 0xb8,
-			  0x27, 0x08, 0x94, 0x2d, 0xbe, 0x77, 0x18, 0x1a },
-			16
-		},
-		{
-			{ 0xc2, 0x86, 0x69, 0x6d, 0x88, 0x7c, 0x9a, 0xa0,
-			  0x61, 0x1b, 0xbb, 0x3e, 0x20, 0x25, 0xa4, 0x5a },
-			{ 0x56, 0x2e, 0x17, 0x99, 0x6d, 0x09, 0x3d, 0x28,
-			  0xdd, 0xb3, 0xba, 0x69, 0x5a, 0x2e, 0x6f, 0x58 },
-			{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-			  0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-			  0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-			  0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
-			{ 0xd2, 0x96, 0xcd, 0x94, 0xc2, 0xcc, 0xcf, 0x8a,
-			  0x3a, 0x86, 0x30, 0x28, 0xb5, 0xe1, 0xdc, 0x0a,
-			  0x75, 0x86, 0x60, 0x2d, 0x25, 0x3c, 0xff, 0xf9,
-			  0x1b, 0x82, 0x66, 0xbe, 0xa6, 0xd6, 0x1a, 0xb1 },
-			32
-		}
-	};
-	int i, ret = 0;
-	u8 *buf;
-
-	for (i = 0; i < sizeof(vectors) / sizeof(vectors[0]); i++) {
-		struct cbc_test_vector *tv = &vectors[i];
-		buf = malloc(tv->len);
-		if (buf == NULL) {
-			ret++;
-			break;
-		}
-		memcpy(buf, tv->plain, tv->len);
-		aes_128_cbc_encrypt(tv->key, tv->iv, buf, tv->len);
-		if (memcmp(buf, tv->cipher, tv->len) != 0) {
-			printf("AES-CBC encrypt %d failed\n", i);
-			ret++;
-		}
-		memcpy(buf, tv->cipher, tv->len);
-		aes_128_cbc_decrypt(tv->key, tv->iv, buf, tv->len);
-		if (memcmp(buf, tv->plain, tv->len) != 0) {
-			printf("AES-CBC decrypt %d failed\n", i);
-			ret++;
-		}
-		free(buf);
-	}
-
-	return ret;
-}
-
-
-/* OMAC1 AES-128 test vectors from
- * http://csrc.nist.gov/CryptoToolkit/modes/proposedmodes/omac/omac-ad.pdf
- */
-
-struct omac1_test_vector {
-	u8 k[16];
-	u8 msg[64];
-	int msg_len;
-	u8 tag[16];
-};
-
-static struct omac1_test_vector test_vectors[] =
-{
-	{
-		{ 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
-		  0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c },
-		{ },
-		0,
-		{ 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28,
-		  0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46 }
-	},
-	{
-		{ 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
-		  0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c },
-		{ 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
-		  0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a},
-		16,
-		{ 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44,
-		  0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c }
-	},
-	{
-		{ 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
-		  0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c },
-		{ 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
-		  0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
-		  0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
-		  0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
-		  0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11 },
-		40,
-		{ 0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30,
-		  0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27 }
-	},
-	{
-		{ 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
-		  0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c },
-		{ 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
-		  0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
-		  0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
-		  0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
-		  0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
-		  0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
-		  0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
-		  0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 },
-		64,
-		{ 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92,
-		  0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe }
-	},
-};
-
-
-int main(int argc, char *argv[])
-{
-	u8 kek[] = {
-		0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-		0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
-	};
-	u8 plain[] = {
-		0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
-		0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff
-	};
-	u8 crypt[] = {
-		0x1F, 0xA6, 0x8B, 0x0A, 0x81, 0x12, 0xB4, 0x47,
-		0xAE, 0xF3, 0x4B, 0xD8, 0xFB, 0x5A, 0x7B, 0x82,
-		0x9D, 0x3E, 0x86, 0x23, 0x71, 0xD2, 0xCF, 0xE5
-	};
-	u8 result[24];
-	int ret = 0, i;
-	struct omac1_test_vector *tv;
-
-	if (aes_wrap(kek, 2, plain, result)) {
-		printf("AES-WRAP-128-128 reported failure\n");
-		ret++;
-	}
-	if (memcmp(result, crypt, 24) != 0) {
-		printf("AES-WRAP-128-128 failed\n");
-		ret++;
-	}
-	if (aes_unwrap(kek, 2, crypt, result)) {
-		printf("AES-UNWRAP-128-128 reported failure\n");
-		ret++;
-	}
-	if (memcmp(result, plain, 16) != 0) {
-		int i;
-		printf("AES-UNWRAP-128-128 failed\n");
-		ret++;
-		for (i = 0; i < 16; i++)
-			printf(" %02x", result[i]);
-		printf("\n");
-	}
-
-#ifdef __i386__
-	test_aes_perf();
-#endif /* __i386__ */
-
-	for (i = 0; i < sizeof(test_vectors) / sizeof(test_vectors[0]); i++) {
-		tv = &test_vectors[i];
-		omac1_aes_128(tv->k, tv->msg, tv->msg_len, result);
-		if (memcmp(result, tv->tag, 16) != 0) {
-			printf("OMAC1-AES-128 test vector %d failed\n", i);
-			ret++;
-		}
-	}
-
-	ret += test_eax();
-
-	ret += test_cbc();
-
-	if (ret)
-		printf("FAILED!\n");
-
-	return ret;
-}
-#endif /* TEST_MAIN */
+#endif /* CONFIG_NO_AES_CBC */
Index: preauth.h
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/preauth.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -L contrib/wpa_supplicant/preauth.h -L contrib/wpa_supplicant/preauth.h -u -r1.1 -r1.2
--- contrib/wpa_supplicant/preauth.h
+++ contrib/wpa_supplicant/preauth.h
@@ -1,6 +1,6 @@
 /*
  * wpa_supplicant - WPA2/RSN pre-authentication functions
- * Copyright (c) 2003-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2003-2005, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -19,63 +19,18 @@
 
 #ifndef CONFIG_NO_WPA
 
-void pmksa_cache_free(struct wpa_sm *sm);
-struct rsn_pmksa_cache * pmksa_cache_get(struct wpa_sm *sm,
-					 const u8 *aa, const u8 *pmkid);
-int pmksa_cache_list(struct wpa_sm *sm, char *buf, size_t len);
 void pmksa_candidate_free(struct wpa_sm *sm);
-struct rsn_pmksa_cache *
-pmksa_cache_add(struct wpa_sm *sm, const u8 *pmk,
-		size_t pmk_len, const u8 *aa, const u8 *spa,
-		struct wpa_ssid *ssid);
-void pmksa_cache_notify_reconfig(struct wpa_sm *sm);
-struct rsn_pmksa_cache * pmksa_cache_get_current(struct wpa_sm *sm);
-void pmksa_cache_clear_current(struct wpa_sm *sm);
-int pmksa_cache_set_current(struct wpa_sm *sm, const u8 *pmkid,
-			    const u8 *bssid, struct wpa_ssid *ssid,
-			    int try_opportunistic);
 
 #else /* CONFIG_NO_WPA */
 
-static inline void pmksa_cache_free(struct wpa_sm *sm)
-{
-}
-
 static inline void pmksa_candidate_free(struct wpa_sm *sm)
 {
 }
 
-static inline void pmksa_cache_notify_reconfig(struct wpa_sm *sm)
-{
-}
-
-static inline struct rsn_pmksa_cache *
-pmksa_cache_get_current(struct wpa_sm *sm)
-{
-	return NULL;
-}
-
-static inline int pmksa_cache_list(struct wpa_sm *sm, char *buf, size_t len)
-{
-	return -1;
-}
-
-static inline void pmksa_cache_clear_current(struct wpa_sm *sm)
-{
-}
-
-static inline int pmksa_cache_set_current(struct wpa_sm *sm, const u8 *pmkid,
-					  const u8 *bssid,
-					  struct wpa_ssid *ssid,
-					  int try_opportunistic)
-{
-	return -1;
-}
-
 #endif /* CONFIG_NO_WPA */
 
 
-#if defined(IEEE8021X_EAPOL) && !defined(CONFIG_NO_WPA)
+#if defined(IEEE8021X_EAPOL) && !defined(CONFIG_NO_WPA2)
 
 int rsn_preauth_init(struct wpa_sm *sm, const u8 *dst,
 		     struct wpa_ssid *config);
@@ -89,7 +44,7 @@
 			   int verbose);
 int rsn_preauth_in_progress(struct wpa_sm *sm);
 
-#else /* IEEE8021X_EAPOL and !CONFIG_NO_WPA */
+#else /* IEEE8021X_EAPOL and !CONFIG_NO_WPA2 */
 
 static inline void rsn_preauth_candidate_process(struct wpa_sm *sm)
 {
@@ -127,6 +82,6 @@
 	return 0;
 }
 
-#endif /* IEEE8021X_EAPOL and !CONFIG_NO_WPA */
+#endif /* IEEE8021X_EAPOL and !CONFIG_NO_WPA2 */
 
 #endif /* PREAUTH_H */
Index: defconfig
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/defconfig,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/defconfig -L contrib/wpa_supplicant/defconfig -u -r1.2 -r1.3
--- contrib/wpa_supplicant/defconfig
+++ contrib/wpa_supplicant/defconfig
@@ -6,15 +6,20 @@
 # just setting VARIABLE=n is not disabling that variable.
 #
 # This file is included in Makefile, so variables like CFLAGS and LIBS can also
-# be modified from here. In most cass, these lines should use += in order not
+# be modified from here. In most cases, these lines should use += in order not
 # to override previous values of the variables.
 
 
-# Uncomment following two lines and fix the paths if you have installed openssl
-# in non-default location
+# Uncomment following two lines and fix the paths if you have installed OpenSSL
+# or GnuTLS in non-default location
 #CFLAGS += -I/usr/local/openssl/include
 #LIBS += -L/usr/local/openssl/lib
 
+# Some Red Hat versions seem to include kerberos header files from OpenSSL, but
+# the kerberos files are not in the default include path. Following line can be
+# used to fix build issues on such systems (krb5.h not found).
+#CFLAGS += -I/usr/include/kerberos
+
 # Example configuration for various cross-compilation platforms
 
 #### sveasoft (e.g., for Linksys WRT54G) ######################################
@@ -86,6 +91,11 @@
 #CFLAGS += -I/opt/mingw/mingw32/include/ddk
 #LIBS += -L/opt/mingw/mingw32/lib
 #CC=mingw32-gcc
+# By default, driver_ndis uses WinPcap for low-level operations. This can be
+# replaced with the following option which replaces WinPcap calls with NDISUIO.
+# However, this requires that WZC is disabled (net stop wzcsvc) before starting
+# wpa_supplicant.
+# CONFIG_USE_NDISUIO=y
 
 # Driver interface for development testing
 #CONFIG_DRIVER_TEST=y
@@ -97,10 +107,10 @@
 # included)
 CONFIG_IEEE8021X_EAPOL=y
 
-# EAP-MD5 (automatically included if EAP-TTLS is enabled)
+# EAP-MD5
 CONFIG_EAP_MD5=y
 
-# EAP-MSCHAPv2 (automatically included if EAP-PEAP is enabled)
+# EAP-MSCHAPv2
 CONFIG_EAP_MSCHAPV2=y
 
 # EAP-TLS
@@ -112,6 +122,13 @@
 # EAP-TTLS
 CONFIG_EAP_TTLS=y
 
+# EAP-FAST
+# Note: Default OpenSSL package does not include support for all the
+# functionality needed for EAP-FAST. If EAP-FAST is enabled with OpenSSL,
+# the OpenSSL library must be patched (openssl-0.9.8d-tls-extensions.patch)
+# to add the needed functions.
+#CONFIG_EAP_FAST=y
+
 # EAP-GTC
 CONFIG_EAP_GTC=y
 
@@ -133,6 +150,14 @@
 # EAP-AKA (enable CONFIG_PCSC, if EAP-AKA is used)
 #CONFIG_EAP_AKA=y
 
+# EAP-SAKE
+#CONFIG_EAP_SAKE=y
+
+# EAP-GPSK
+#CONFIG_EAP_GPSK=y
+# Include support for optional SHA256 cipher suite in EAP-GPSK
+#CONFIG_EAP_GPSK_SHA256=y
+
 # PKCS#12 (PFX) support (used to read private key and certificate file from
 # a file that usually has extension .p12 or .pfx)
 CONFIG_PKCS12=y
@@ -148,11 +173,13 @@
 # Development testing
 #CONFIG_EAPOL_TEST=y
 
-# Replace native Linux implementation of packet sockets with libdnet/libpcap.
-# This will be automatically set for non-Linux OS.
-#CONFIG_DNET_PCAP=y
-
-# Include control interface for external programs, e.g, wpa_cli
+# Select control interface backend for external programs, e.g, wpa_cli:
+# unix = UNIX domain sockets (default for Linux/*BSD)
+# udp = UDP sockets using localhost (127.0.0.1)
+# named_pipe = Windows Named Pipe (default for Windows)
+# y = use default (backwards compatibility)
+# If this option is commented out, control interface is not included in the
+# build.
 CONFIG_CTRL_IFACE=y
 
 # Include support for GNU Readline and History Libraries in wpa_cli.
@@ -171,6 +198,121 @@
 # 35-50 kB in code size.
 #CONFIG_NO_WPA=y
 
+# Remove WPA2 support. This allows WPA to be used, but removes WPA2 code to
+# save about 1 kB in code size when building only WPA-Personal (no EAP support)
+# or 6 kB if building for WPA-Enterprise.
+#CONFIG_NO_WPA2=y
+
+# Remove AES extra functions. This can be used to reduce code size by about
+# 1.5 kB by removing extra AES modes that are not needed for commonly used
+# client configurations (they are needed for some EAP types).
+#CONFIG_NO_AES_EXTRAS=y
+
 # Select configuration backend:
 # file = text file (e.g., wpa_supplicant.conf)
+# winreg = Windows registry (see win_example.reg for an example)
 CONFIG_BACKEND=file
+
+# Select program entry point implementation:
+# main = UNIX/POSIX like main() function (default)
+# main_winsvc = Windows service (read parameters from registry)
+# main_none = Very basic example (development use only)
+#CONFIG_MAIN=main
+
+# Select wrapper for operatins system and C library specific functions
+# unix = UNIX/POSIX like systems (default)
+# win32 = Windows systems
+# none = Empty template
+#CONFIG_OS=unix
+
+# Select event loop implementation
+# eloop = select() loop (default)
+# eloop_win = Windows events and WaitForMultipleObject() loop
+# eloop_none = Empty template
+#CONFIG_ELOOP=eloop
+
+# Select layer 2 packet implementation
+# linux = Linux packet socket (default)
+# pcap = libpcap/libdnet/WinPcap
+# freebsd = FreeBSD libpcap
+# winpcap = WinPcap with receive thread
+# ndis = Windows NDISUIO (note: requires CONFIG_USE_NDISUIO=y)
+# none = Empty template
+#CONFIG_L2_PACKET=linux
+
+# PeerKey handshake for Station to Station Link (IEEE 802.11e DLS)
+CONFIG_PEERKEY=y
+
+# IEEE 802.11w (management frame protection)
+# This version is an experimental implementation based on IEEE 802.11w/D1.0
+# draft and is subject to change since the standard has not yet been finalized.
+# Driver support is also needed for IEEE 802.11w.
+#CONFIG_IEEE80211W=y
+
+# Select TLS implementation
+# openssl = OpenSSL (default)
+# gnutls = GnuTLS (needed for TLS/IA, see also CONFIG_GNUTLS_EXTRA)
+# internal = Internal TLSv1 implementation (experimental)
+# none = Empty template
+#CONFIG_TLS=openssl
+
+# Whether to enable TLS/IA support, which is required for EAP-TTLSv1.
+# You need CONFIG_TLS=gnutls for this to have any effect. Please note that
+# even though the core GnuTLS library is released under LGPL, this extra
+# library uses GPL and as such, the terms of GPL apply to the combination
+# of wpa_supplicant and GnuTLS if this option is enabled. BSD license may not
+# apply for distribution of the resulting binary.
+#CONFIG_GNUTLS_EXTRA=y
+
+# If CONFIG_TLS=internal is used, additional library and include paths are
+# needed for LibTomMath. Alternatively, an integrated, minimal version of
+# LibTomMath can be used. See beginning of libtommath.c for details on benefits
+# and drawbacks of this option.
+#CONFIG_INTERNAL_LIBTOMMATH=y
+#ifndef CONFIG_INTERNAL_LIBTOMMATH
+#LTM_PATH=/usr/src/libtommath-0.39
+#CFLAGS += -I$(LTM_PATH)
+#LIBS += -L$(LTM_PATH)
+#LIBS_p += -L$(LTM_PATH)
+#endif
+
+# Include NDIS event processing through WMI into wpa_supplicant/wpasvc.
+# This is only for Windows builds and requires WMI-related header files and
+# WbemUuid.Lib from Platform SDK even when building with MinGW.
+#CONFIG_NDIS_EVENTS_INTEGRATED=y
+#PLATFORMSDKLIB="/opt/Program Files/Microsoft Platform SDK/Lib"
+
+# Add support for DBus control interface
+#CONFIG_CTRL_IFACE_DBUS=y
+
+# Add support for loading EAP methods dynamically as shared libraries.
+# When this option is enabled, each EAP method can be either included
+# statically (CONFIG_EAP_<method>=y) or dynamically (CONFIG_EAP_<method>=dyn).
+# Dynamic EAP methods are build as shared objects (eap_*.so) and they need to
+# be loaded in the beginning of the wpa_supplicant configuration file
+# (see load_dynamic_eap parameter in the example file) before being used in
+# the network blocks.
+#
+# Note that some shared parts of EAP methods are included in the main program
+# and in order to be able to use dynamic EAP methods using these parts, the
+# main program must have been build with the EAP method enabled (=y or =dyn).
+# This means that EAP-TLS/PEAP/TTLS/FAST cannot be added as dynamic libraries
+# unless at least one of them was included in the main build to force inclusion
+# of the shared code. Similarly, at least one of EAP-SIM/AKA must be included
+# in the main build to be able to load these methods dynamically.
+#
+# Please also note that using dynamic libraries will increase the total binary
+# size. Thus, it may not be the best option for targets that have limited
+# amount of memory/flash.
+#CONFIG_DYNAMIC_EAP_METHODS=y
+
+# Include client MLME (management frame processing).
+# This can be used to move MLME processing of Devicescape IEEE 802.11 stack
+# into user space.
+#CONFIG_CLIENT_MLME=y
+# Currently, driver_devicescape.c build requires some additional parameters
+# to be able to include some of the kernel header files. Following lines can
+# be used to set these (WIRELESS_DEV must point to the root directory of the
+# wireless-dev.git tree).
+#WIRELESS_DEV=/usr/src/wireless-dev
+#CFLAGS += -I$(WIRELESS_DEV)/net/mac80211
Index: ms_funcs.h
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/ms_funcs.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/ms_funcs.h -L contrib/wpa_supplicant/ms_funcs.h -u -r1.2 -r1.3
--- contrib/wpa_supplicant/ms_funcs.h
+++ contrib/wpa_supplicant/ms_funcs.h
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant / shared MSCHAPV2 helper functions / RFC 2433 / RFC 2759
- * Copyright (c) 2004-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2004-2005, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -19,11 +19,21 @@
 			  const u8 *username, size_t username_len,
 			  const u8 *password, size_t password_len,
 			  u8 *response);
+void generate_nt_response_pwhash(const u8 *auth_challenge,
+				 const u8 *peer_challenge,
+				 const u8 *username, size_t username_len,
+				 const u8 *password_hash,
+				 u8 *response);
 void generate_authenticator_response(const u8 *password, size_t password_len,
 				     const u8 *peer_challenge,
 				     const u8 *auth_challenge,
 				     const u8 *username, size_t username_len,
 				     const u8 *nt_response, u8 *response);
+void generate_authenticator_response_pwhash(
+	const u8 *password_hash,
+	const u8 *peer_challenge, const u8 *auth_challenge,
+	const u8 *username, size_t username_len,
+	const u8 *nt_response, u8 *response);
 void nt_challenge_response(const u8 *challenge, const u8 *password,
 			   size_t password_len, u8 *response);
 
@@ -46,5 +56,4 @@
 	const u8 *old_password, size_t old_password_len,
 	u8 *encrypted_password_hash);
 
-
 #endif /* MS_FUNCS_H */
Index: eap_testing.txt
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/eap_testing.txt,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/eap_testing.txt -L contrib/wpa_supplicant/eap_testing.txt -u -r1.2 -r1.3
--- contrib/wpa_supplicant/eap_testing.txt
+++ contrib/wpa_supplicant/eap_testing.txt
@@ -25,7 +25,7 @@
 would be to get an evaluation version of the server so that I can
 install it on my own test setup. If you are interested in providing
 either server access or evaluation version, please contact me
-(jkmaline at cc.hut.fi).
+(j at w1.fi).
 
 
 Test matrix
@@ -38,7 +38,7 @@
 Cisco ACS ----------------------------------------------------------.
 hostapd --------------------------------------------------------.   |
 Cisco Aironet 1200 AP (local RADIUS server) ----------------.   |   |
-Corriente Elektron -------------------------------------.   |   |   |
+Periodik Labs Elektron ---------------------------------.   |   |   |
 Lucent NavisRadius ---------------------------------.   |   |   |   |
 Interlink RAD-Series ---------------------------.   |   |   |   |   |
 Radiator -----------------------------------.   |   |   |   |   |   |
@@ -60,7 +60,7 @@
 EAP-PEAPv0/MD5		+   -   -   +   +   +   +   +   -   -   +   -
 EAP-PEAPv0/TLS		-   +   -   +   +   +   F   +   -   -   -   -
 EAP-PEAPv1/MSCHAPv2	-   -   +   +   +   +1  +   +5  +8  -   +   +
-EAP-PEAPv1/GTC		-   -   +   +   +   +1  +   +5  -   -   +   +
+EAP-PEAPv1/GTC		-   -   +   +   +   +1  +   +5  +8  -   +   +
 EAP-PEAPv1/OTP		-   -   -   -   -   +1  -   -   -   -   -   -
 EAP-PEAPv1/MD5		-   -   -   +   +   +1  +   +5  -   -   +   -
 EAP-PEAPv1/TLS		-   -   -   +   +   +1  F   +5  -   -   -   -
@@ -68,16 +68,18 @@
 EAP-TTLS/MSCHAP		+   -   +   +   +   +   +   +   +   -   +   -
 EAP-TTLS/MSCHAPv2	+   -   +   +   +   +   +   +   +   -   +   -
 EAP-TTLS/PAP		+   -   +   +   +   +   +   +   +   -   +   -
-EAP-TTLS/EAP-MD5	+   -   +2  +   +   +   +   +   -   -   +   -
+EAP-TTLS/EAP-MD5	+   -   +2  +   +   +   +   +   +   -   +   -
 EAP-TTLS/EAP-GTC	+   -   +2  ?   +   +   +   +   -   -   +   -
 EAP-TTLS/EAP-OTP	-   -   -   -   -   +   -   -   -   -   -   -
 EAP-TTLS/EAP-MSCHAPv2	+   -   +2  +   +   +   +   +   +   -   +   -
 EAP-TTLS/EAP-TLS	-   -   +2  +   F   +   +   +   -   -   -   -
 EAP-SIM			+3  -   -   ?   -   +   -   ?   -   -   +   -
-EAP-AKA			-   -   -   -   -   +   -   -   -   -   -   -
+EAP-AKA			-   -   -   -   -   +   -   -   -   -   +   -
 EAP-PSK			+7  -   -   -   -   -   -   -   -   -   +   -
 EAP-PAX			-   -   -   -   -   -   -   -   -   -   +   -
-EAP-FAST		-   -   -   -   -   -   -   -   -   +   -   +
+EAP-SAKE		-   -   -   -   -   -   -   -   -   -   +   -
+EAP-GPSK		-   -   -   -   -   -   -   -   -   -   +   -
+EAP-FAST		-   -   -   +   -   -   -   -   -   +   -   +
 LEAP			+   -   +   +   +   +   F   +6  -   +   -   +
 
 1) PEAPv1 required new label, "client PEAP encryption" instead of "client EAP
Index: md5.h
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/md5.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/md5.h -L contrib/wpa_supplicant/md5.h -u -r1.2 -r1.3
--- contrib/wpa_supplicant/md5.h
+++ contrib/wpa_supplicant/md5.h
@@ -1,6 +1,6 @@
 /*
  * MD5 hash implementation and interface functions
- * Copyright (c) 2003-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2003-2005, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -22,4 +22,13 @@
 void hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
 	      u8 *mac);
 
+#ifdef CONFIG_CRYPTO_INTERNAL
+struct MD5Context;
+
+void MD5Init(struct MD5Context *context);
+void MD5Update(struct MD5Context *context, unsigned char const *buf,
+	       unsigned len);
+void MD5Final(unsigned char digest[16], struct MD5Context *context);
+#endif /* CONFIG_CRYPTO_INTERNAL */
+
 #endif /* MD5_H */
Index: eap_gtc.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/eap_gtc.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/eap_gtc.c -L contrib/wpa_supplicant/eap_gtc.c -u -r1.2 -r1.3
--- contrib/wpa_supplicant/eap_gtc.c
+++ contrib/wpa_supplicant/eap_gtc.c
@@ -1,6 +1,6 @@
 /*
- * WPA Supplicant / EAP-GTC (RFC 2284)
- * Copyright (c) 2004-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * EAP peer method: EAP-GTC (RFC 3748)
+ * Copyright (c) 2004-2006, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -12,14 +12,10 @@
  * See README and COPYING for more details.
  */
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
+#include "includes.h"
 
 #include "common.h"
 #include "eap_i.h"
-#include "wpa_supplicant.h"
-#include "config_ssid.h"
 
 
 struct eap_gtc_data {
@@ -30,10 +26,9 @@
 static void * eap_gtc_init(struct eap_sm *sm)
 {
 	struct eap_gtc_data *data;
-	data = malloc(sizeof(*data));
+	data = os_zalloc(sizeof(*data));
 	if (data == NULL)
 		return NULL;
-	memset(data, 0, sizeof(*data));
 
 	if (sm->m && sm->m->method == EAP_TYPE_FAST) {
 		wpa_printf(MSG_DEBUG, "EAP-GTC: EAP-FAST tunnel - use prefix "
@@ -47,7 +42,7 @@
 static void eap_gtc_deinit(struct eap_sm *sm, void *priv)
 {
 	struct eap_gtc_data *data = priv;
-	free(data);
+	os_free(data);
 }
 
 
@@ -57,14 +52,15 @@
 			    size_t *respDataLen)
 {
 	struct eap_gtc_data *data = priv;
-	struct wpa_ssid *config = eap_get_config(sm);
 	const struct eap_hdr *req;
 	struct eap_hdr *resp;
-	const u8 *pos, *password;
+	const u8 *pos, *password, *identity;
 	u8 *rpos;
-	size_t password_len, len;
+	size_t password_len, identity_len, len, plen;
+	int otp;
 
-	pos = eap_hdr_validate(EAP_TYPE_GTC, reqData, reqDataLen, &len);
+	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GTC,
+			       reqData, reqDataLen, &len);
 	if (pos == NULL) {
 		ret->ignore = TRUE;
 		return NULL;
@@ -73,7 +69,7 @@
 
 	wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-GTC: Request message", pos, len);
 	if (data->prefix &&
-	    (len < 10 || memcmp(pos, "CHALLENGE=", 10) != 0)) {
+	    (len < 10 || os_memcmp(pos, "CHALLENGE=", 10) != 0)) {
 		wpa_printf(MSG_DEBUG, "EAP-GTC: Challenge did not start with "
 			   "expected prefix");
 
@@ -81,81 +77,79 @@
 		 * acknowledgement of the failure. This will also cover the
 		 * error case which seems to use EAP-MSCHAPv2 like error
 		 * reporting with EAP-GTC inside EAP-FAST tunnel. */
-		*respDataLen = sizeof(struct eap_hdr) + 1;
-		resp = malloc(*respDataLen);
-		if (resp == NULL)
-			return NULL;
-		resp->code = EAP_CODE_RESPONSE;
-		resp->identifier = req->identifier;
-		resp->length = host_to_be16(*respDataLen);
-		rpos = (u8 *) (resp + 1);
-		*rpos++ = EAP_TYPE_GTC;
+		resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GTC,
+				     respDataLen, 0, EAP_CODE_RESPONSE,
+				     req->identifier, NULL);
 		return (u8 *) resp;
 	}
 
-	if (config == NULL ||
-	    (config->password == NULL && config->otp == NULL)) {
+	password = eap_get_config_otp(sm, &password_len);
+	if (password)
+		otp = 1;
+	else {
+		password = eap_get_config_password(sm, &password_len);
+		otp = 0;
+	}
+
+	if (password == NULL) {
 		wpa_printf(MSG_INFO, "EAP-GTC: Password not configured");
-		eap_sm_request_otp(sm, config, (const char *) pos, len);
+		eap_sm_request_otp(sm, (const char *) pos, len);
 		ret->ignore = TRUE;
 		return NULL;
 	}
 
-	if (config->otp) {
-		password = config->otp;
-		password_len = config->otp_len;
-	} else {
-		password = config->password;
-		password_len = config->password_len;
-	}
-
 	ret->ignore = FALSE;
 
 	ret->methodState = data->prefix ? METHOD_MAY_CONT : METHOD_DONE;
 	ret->decision = DECISION_COND_SUCC;
 	ret->allowNotifications = FALSE;
 
-	*respDataLen = sizeof(struct eap_hdr) + 1 + password_len;
-	if (data->prefix) {
-		*respDataLen += 9 + config->identity_len + 1;
-	}
-	resp = malloc(*respDataLen);
+	plen = password_len;
+	identity = eap_get_config_identity(sm, &identity_len);
+	if (identity == NULL)
+		return NULL;
+	if (data->prefix)
+		plen += 9 + identity_len + 1;
+	resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GTC, respDataLen,
+			     plen, EAP_CODE_RESPONSE, req->identifier, &rpos);
 	if (resp == NULL)
 		return NULL;
-	resp->code = EAP_CODE_RESPONSE;
-	resp->identifier = req->identifier;
-	resp->length = host_to_be16(*respDataLen);
-	rpos = (u8 *) (resp + 1);
-	*rpos++ = EAP_TYPE_GTC;
 	if (data->prefix) {
-		memcpy(rpos, "RESPONSE=", 9);
+		os_memcpy(rpos, "RESPONSE=", 9);
 		rpos += 9;
-		memcpy(rpos, config->identity, config->identity_len);
-		rpos += config->identity_len;
+		os_memcpy(rpos, identity, identity_len);
+		rpos += identity_len;
 		*rpos++ = '\0';
 	}
-	memcpy(rpos, password, password_len);
+	os_memcpy(rpos, password, password_len);
 	wpa_hexdump_ascii_key(MSG_MSGDUMP, "EAP-GTC: Response",
-			      (u8 *) (resp + 1) + 1,
-			      *respDataLen - sizeof(struct eap_hdr) - 1);
+			      (u8 *) (resp + 1) + 1, plen);
 
-	if (config->otp) {
+	if (otp) {
 		wpa_printf(MSG_DEBUG, "EAP-GTC: Forgetting used password");
-		memset(config->otp, 0, config->otp_len);
-		free(config->otp);
-		config->otp = NULL;
-		config->otp_len = 0;
+		eap_clear_config_otp(sm);
 	}
 
 	return (u8 *) resp;
 }
 
 
-const struct eap_method eap_method_gtc =
+int eap_peer_gtc_register(void)
 {
-	.method = EAP_TYPE_GTC,
-	.name = "GTC",
-	.init = eap_gtc_init,
-	.deinit = eap_gtc_deinit,
-	.process = eap_gtc_process,
-};
+	struct eap_method *eap;
+	int ret;
+
+	eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
+				    EAP_VENDOR_IETF, EAP_TYPE_GTC, "GTC");
+	if (eap == NULL)
+		return -1;
+
+	eap->init = eap_gtc_init;
+	eap->deinit = eap_gtc_deinit;
+	eap->process = eap_gtc_process;
+
+	ret = eap_peer_method_register(eap);
+	if (ret)
+		eap_peer_method_free(eap);
+	return ret;
+}
Index: wpa_ctrl.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/wpa_ctrl.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/wpa_ctrl.c -L contrib/wpa_supplicant/wpa_ctrl.c -u -r1.2 -r1.3
--- contrib/wpa_supplicant/wpa_ctrl.c
+++ contrib/wpa_supplicant/wpa_ctrl.c
@@ -1,6 +1,6 @@
 /*
  * wpa_supplicant/hostapd control interface library
- * Copyright (c) 2004-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2004-2007, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -11,25 +11,24 @@
  *
  * See README and COPYING for more details.
  *
- * $FreeBSD: src/contrib/wpa_supplicant/wpa_ctrl.c,v 1.3.2.1 2006/03/24 01:41:07 sam Exp $
+ * $FreeBSD: src/contrib/wpa_supplicant/wpa_ctrl.c,v 1.5 2007/07/11 15:58:51 sam Exp $
  */
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#ifndef CONFIG_NATIVE_WINDOWS
-#include <sys/socket.h>
-#include <netinet/in.h>
+#include "includes.h"
+
+#ifdef CONFIG_CTRL_IFACE
+
+#ifdef CONFIG_CTRL_IFACE_UNIX
 #include <sys/un.h>
-#endif /* CONFIG_NATIVE_WINDOWS */
+#endif /* CONFIG_CTRL_IFACE_UNIX */
 
 #include "wpa_ctrl.h"
-#ifdef CONFIG_NATIVE_WINDOWS
 #include "common.h"
-#endif /* CONFIG_NATIVE_WINDOWS */
+
+
+#if defined(CONFIG_CTRL_IFACE_UNIX) || defined(CONFIG_CTRL_IFACE_UDP)
+#define CTRL_IFACE_SOCKET
+#endif /* CONFIG_CTRL_IFACE_UNIX || CONFIG_CTRL_IFACE_UDP */
 
 
 /**
@@ -42,83 +41,121 @@
  * the arguments for most of the control interface library functions.
  */
 struct wpa_ctrl {
-	int s;
 #ifdef CONFIG_CTRL_IFACE_UDP
+	int s;
 	struct sockaddr_in local;
 	struct sockaddr_in dest;
-#else /* CONFIG_CTRL_IFACE_UDP */
+	char *cookie;
+#endif /* CONFIG_CTRL_IFACE_UDP */
+#ifdef CONFIG_CTRL_IFACE_UNIX
+	int s;
 	struct sockaddr_un local;
 	struct sockaddr_un dest;
-#endif /* CONFIG_CTRL_IFACE_UDP */
+#endif /* CONFIG_CTRL_IFACE_UNIX */
+#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
+	HANDLE pipe;
+#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
 };
 
 
+#ifdef CONFIG_CTRL_IFACE_UNIX
+
 struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
 {
 	struct wpa_ctrl *ctrl;
-#ifndef CONFIG_CTRL_IFACE_UDP
 	static int counter = 0;
-#endif /* CONFIG_CTRL_IFACE_UDP */
 
-	ctrl = malloc(sizeof(*ctrl));
+	ctrl = os_malloc(sizeof(*ctrl));
 	if (ctrl == NULL)
 		return NULL;
-	memset(ctrl, 0, sizeof(*ctrl));
+	os_memset(ctrl, 0, sizeof(*ctrl));
 
-#ifdef CONFIG_CTRL_IFACE_UDP
-	ctrl->s = socket(PF_INET, SOCK_DGRAM, 0);
+	ctrl->s = socket(PF_UNIX, SOCK_DGRAM, 0);
 	if (ctrl->s < 0) {
-		perror("socket");
-		free(ctrl);
+		os_free(ctrl);
 		return NULL;
 	}
 
-	ctrl->local.sin_family = AF_INET;
-	ctrl->local.sin_addr.s_addr = htonl((127 << 24) | 1);
+	ctrl->local.sun_family = AF_UNIX;
+	os_snprintf(ctrl->local.sun_path, sizeof(ctrl->local.sun_path),
+		    "/tmp/wpa_ctrl_%d-%d", getpid(), counter++);
 	if (bind(ctrl->s, (struct sockaddr *) &ctrl->local,
-		 sizeof(ctrl->local)) < 0) {
+		    sizeof(ctrl->local)) < 0) {
 		close(ctrl->s);
-		free(ctrl);
+		os_free(ctrl);
 		return NULL;
 	}
 
-	ctrl->dest.sin_family = AF_INET;
-	ctrl->dest.sin_addr.s_addr = htonl((127 << 24) | 1);
-	ctrl->dest.sin_port = htons(WPA_CTRL_IFACE_PORT);
+	ctrl->dest.sun_family = AF_UNIX;
+	os_snprintf(ctrl->dest.sun_path, sizeof(ctrl->dest.sun_path), "%s",
+		    ctrl_path);
 	if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest,
 		    sizeof(ctrl->dest)) < 0) {
-		perror("connect");
 		close(ctrl->s);
-		free(ctrl);
+		unlink(ctrl->local.sun_path);
+		os_free(ctrl);
 		return NULL;
 	}
-#else /* CONFIG_CTRL_IFACE_UDP */
-	ctrl->s = socket(PF_UNIX, SOCK_DGRAM, 0);
+
+	return ctrl;
+}
+
+
+void wpa_ctrl_close(struct wpa_ctrl *ctrl)
+{
+	unlink(ctrl->local.sun_path);
+	close(ctrl->s);
+	os_free(ctrl);
+}
+
+#endif /* CONFIG_CTRL_IFACE_UNIX */
+
+
+#ifdef CONFIG_CTRL_IFACE_UDP
+
+struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
+{
+	struct wpa_ctrl *ctrl;
+	char buf[128];
+	size_t len;
+
+	ctrl = os_malloc(sizeof(*ctrl));
+	if (ctrl == NULL)
+		return NULL;
+	os_memset(ctrl, 0, sizeof(*ctrl));
+
+	ctrl->s = socket(PF_INET, SOCK_DGRAM, 0);
 	if (ctrl->s < 0) {
-		free(ctrl);
+		perror("socket");
+		os_free(ctrl);
 		return NULL;
 	}
 
-	ctrl->local.sun_family = AF_UNIX;
-	snprintf(ctrl->local.sun_path, sizeof(ctrl->local.sun_path) - 1,
-		 "/tmp/wpa_ctrl_%d-%d", getpid(), counter++);
+	ctrl->local.sin_family = AF_INET;
+	ctrl->local.sin_addr.s_addr = htonl((127 << 24) | 1);
 	if (bind(ctrl->s, (struct sockaddr *) &ctrl->local,
-		    sizeof(ctrl->local)) < 0) {
+		 sizeof(ctrl->local)) < 0) {
 		close(ctrl->s);
-		free(ctrl);
+		os_free(ctrl);
 		return NULL;
 	}
 
-	ctrl->dest.sun_family = AF_UNIX;
-	strncpy(ctrl->dest.sun_path, ctrl_path, sizeof(ctrl->dest.sun_path) - 1);
+	ctrl->dest.sin_family = AF_INET;
+	ctrl->dest.sin_addr.s_addr = htonl((127 << 24) | 1);
+	ctrl->dest.sin_port = htons(WPA_CTRL_IFACE_PORT);
 	if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest,
 		    sizeof(ctrl->dest)) < 0) {
+		perror("connect");
 		close(ctrl->s);
-		unlink(ctrl->local.sun_path);
-		free(ctrl);
+		os_free(ctrl);
 		return NULL;
 	}
-#endif /* CONFIG_CTRL_IFACE_UDP */
+
+	len = sizeof(buf) - 1;
+	if (wpa_ctrl_request(ctrl, "GET_COOKIE", 10, buf, &len, NULL) == 0) {
+		buf[len] = '\0';
+		ctrl->cookie = strdup(buf);
+	}
 
 	return ctrl;
 }
@@ -126,14 +163,15 @@
 
 void wpa_ctrl_close(struct wpa_ctrl *ctrl)
 {
-#ifndef CONFIG_CTRL_IFACE_UDP
-	unlink(ctrl->local.sun_path);
-#endif /* CONFIG_CTRL_IFACE_UDP */
 	close(ctrl->s);
-	free(ctrl);
+	os_free(ctrl->cookie);
+	os_free(ctrl);
 }
 
+#endif /* CONFIG_CTRL_IFACE_UDP */
+
 
+#ifdef CTRL_IFACE_SOCKET
 int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
 		     char *reply, size_t *reply_len,
 		     void (*msg_cb)(char *msg, size_t len))
@@ -141,9 +179,35 @@
 	struct timeval tv;
 	int res;
 	fd_set rfds;
+	const char *_cmd;
+	char *cmd_buf = NULL;
+	size_t _cmd_len;
 
-	if (send(ctrl->s, cmd, cmd_len, 0) < 0)
+#ifdef CONFIG_CTRL_IFACE_UDP
+	if (ctrl->cookie) {
+		char *pos;
+		_cmd_len = strlen(ctrl->cookie) + 1 + cmd_len;
+		cmd_buf = os_malloc(_cmd_len );
+		if (cmd_buf == NULL)
+			return -1;
+		_cmd = cmd_buf;
+		pos = cmd_buf;
+		strcpy(pos, ctrl->cookie);
+		pos += strlen(ctrl->cookie);
+		*pos++ = ' ';
+		memcpy(pos, cmd, cmd_len);
+	} else
+#endif /* CONFIG_CTRL_IFACE_UDP */
+	{
+		_cmd = cmd;
+		_cmd_len = cmd_len;
+	}
+
+	if (send(ctrl->s, _cmd, _cmd_len, 0) < 0) {
+		os_free(cmd_buf);
 		return -1;
+	}
+	os_free(cmd_buf);
 
 	for (;;) {
 		tv.tv_sec = 2;
@@ -178,6 +242,7 @@
 	}
 	return 0;
 }
+#endif /* CTRL_IFACE_SOCKET */
 
 
 static int wpa_ctrl_attach_helper(struct wpa_ctrl *ctrl, int attach)
@@ -190,7 +255,7 @@
 			       buf, &len, NULL);
 	if (ret < 0)
 		return ret;
-	if (len == 3 && memcmp(buf, "OK\n", 3) == 0)
+	if (len == 3 && os_memcmp(buf, "OK\n", 3) == 0)
 		return 0;
 	return -1;
 }
@@ -208,6 +273,8 @@
 }
 
 
+#ifdef CTRL_IFACE_SOCKET
+
 int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len)
 {
 	int res;
@@ -223,13 +290,12 @@
 int wpa_ctrl_pending(struct wpa_ctrl *ctrl)
 {
 	struct timeval tv;
-	int res;
 	fd_set rfds;
 	tv.tv_sec = 0;
 	tv.tv_usec = 0;
 	FD_ZERO(&rfds);
 	FD_SET(ctrl->s, &rfds);
-	res = select(ctrl->s + 1, &rfds, NULL, NULL, &tv);
+	select(ctrl->s + 1, &rfds, NULL, NULL, &tv);
 	return FD_ISSET(ctrl->s, &rfds);
 }
 
@@ -238,3 +304,124 @@
 {
 	return ctrl->s;
 }
+
+#endif /* CTRL_IFACE_SOCKET */
+
+
+#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
+
+#ifndef WPA_SUPPLICANT_NAMED_PIPE
+#define WPA_SUPPLICANT_NAMED_PIPE "WpaSupplicant"
+#endif
+#define NAMED_PIPE_PREFIX TEXT("\\\\.\\pipe\\") TEXT(WPA_SUPPLICANT_NAMED_PIPE)
+
+struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
+{
+	struct wpa_ctrl *ctrl;
+	DWORD mode;
+	TCHAR name[256];
+	int i;
+
+	ctrl = os_malloc(sizeof(*ctrl));
+	if (ctrl == NULL)
+		return NULL;
+	os_memset(ctrl, 0, sizeof(*ctrl));
+
+#ifdef UNICODE
+	if (ctrl_path == NULL)
+		_snwprintf(name, 256, NAMED_PIPE_PREFIX);
+	else
+		_snwprintf(name, 256, NAMED_PIPE_PREFIX TEXT("-%S"),
+			   ctrl_path);
+#else /* UNICODE */
+	if (ctrl_path == NULL)
+		os_snprintf(name, 256, NAMED_PIPE_PREFIX);
+	else
+		os_snprintf(name, 256, NAMED_PIPE_PREFIX "-%s",
+			    ctrl_path);
+#endif /* UNICODE */
+
+	for (i = 0; i < 10; i++) {
+		ctrl->pipe = CreateFile(name, GENERIC_READ | GENERIC_WRITE, 0,
+					NULL, OPEN_EXISTING, 0, NULL);
+		/*
+		 * Current named pipe server side in wpa_supplicant is
+		 * re-opening the pipe for new clients only after the previous
+		 * one is taken into use. This leaves a small window for race
+		 * conditions when two connections are being opened at almost
+		 * the same time. Retry if that was the case.
+		 */
+		if (ctrl->pipe != INVALID_HANDLE_VALUE ||
+		    GetLastError() != ERROR_PIPE_BUSY)
+			break;
+		WaitNamedPipe(name, 1000);
+	}
+	if (ctrl->pipe == INVALID_HANDLE_VALUE) {
+		os_free(ctrl);
+		return NULL;
+	}
+
+	mode = PIPE_READMODE_MESSAGE;
+	if (!SetNamedPipeHandleState(ctrl->pipe, &mode, NULL, NULL)) {
+		CloseHandle(ctrl->pipe);
+		os_free(ctrl);
+		return NULL;
+	}
+
+	return ctrl;
+}
+
+
+void wpa_ctrl_close(struct wpa_ctrl *ctrl)
+{
+	CloseHandle(ctrl->pipe);
+	os_free(ctrl);
+}
+
+
+int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
+		     char *reply, size_t *reply_len,
+		     void (*msg_cb)(char *msg, size_t len))
+{
+	DWORD written;
+	DWORD readlen = *reply_len;
+
+	if (!WriteFile(ctrl->pipe, cmd, cmd_len, &written, NULL))
+		return -1;
+
+	if (!ReadFile(ctrl->pipe, reply, *reply_len, &readlen, NULL))
+		return -1;
+	*reply_len = readlen;
+
+	return 0;
+}
+
+
+int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len)
+{
+	DWORD len = *reply_len;
+	if (!ReadFile(ctrl->pipe, reply, *reply_len, &len, NULL))
+		return -1;
+	*reply_len = len;
+	return 0;
+}
+
+
+int wpa_ctrl_pending(struct wpa_ctrl *ctrl)
+{
+	DWORD left;
+
+	if (!PeekNamedPipe(ctrl->pipe, NULL, 0, NULL, &left, NULL))
+		return -1;
+	return left ? 1 : 0;
+}
+
+
+int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl)
+{
+	return -1;
+}
+
+#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
+
+#endif /* CONFIG_CTRL_IFACE */
Index: version.h
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/version.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/version.h -L contrib/wpa_supplicant/version.h -u -r1.2 -r1.3
--- contrib/wpa_supplicant/version.h
+++ contrib/wpa_supplicant/version.h
@@ -1,6 +1,6 @@
 #ifndef VERSION_H
 #define VERSION_H
 
-#define VERSION_STR "0.4.8"
+#define VERSION_STR "0.5.8"
 
 #endif /* VERSION_H */
Index: tls.h
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/tls.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/tls.h -L contrib/wpa_supplicant/tls.h -u -r1.2 -r1.3
--- contrib/wpa_supplicant/tls.h
+++ contrib/wpa_supplicant/tls.h
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant / SSL/TLS interface definition
- * Copyright (c) 2004-2006, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2004-2006, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -18,21 +18,14 @@
 struct tls_connection;
 
 struct tls_keys {
-	const u8 *master_key;
+	const u8 *master_key; /* TLS master secret */
 	size_t master_key_len;
 	const u8 *client_random;
 	size_t client_random_len;
 	const u8 *server_random;
 	size_t server_random_len;
-
-	/*
-	 * If TLS library does not provide access to master_key, but only to
-	 * EAP key block, this pointer can be set to point to the result of
-	 * PRF(master_secret, "client EAP encryption",
-	 * client_random + server_random).
-	 */
-	const u8 *eap_tls_prf;
-	size_t eap_tls_prf_len;
+	const u8 *inner_secret; /* TLS/IA inner secret */
+	size_t inner_secret_len;
 };
 
 struct tls_config {
@@ -71,8 +64,10 @@
  * @ppin: pointer to the pin variable in the configuration
  * (this is OpenSSL specific for now)
  * @key_id: the private key's key id (this is OpenSSL specific for now)
+ * @tls_ia: Whether to enable TLS/IA (for EAP-TTLSv1)
  *
- * TLS connection parameters to be configured with tls_connection_set_params().
+ * TLS connection parameters to be configured with tls_connection_set_params()
+ * and tls_global_set_params().
  *
  * Certificates and private key can be configured either as a reference name
  * (file path or reference to certificate store) or by providing the same data
@@ -96,6 +91,7 @@
 	const char *dh_file;
 	const u8 *dh_blob;
 	size_t dh_blob_len;
+	int tls_ia;
 
 	/* OpenSSL specific variables */
 	int engine;
@@ -134,7 +130,6 @@
 /**
  * tls_get_errors - Process pending errors
  * @tls_ctx: TLS context data from tls_init()
- *
  * Returns: Number of found error, 0 if no errors detected.
  *
  * Process all pending TLS errors.
@@ -144,7 +139,6 @@
 /**
  * tls_connection_init - Initialize a new TLS connection
  * @tls_ctx: TLS context data from tls_init()
- *
  * Returns: Connection context data, conn for other function calls
  */
 struct tls_connection * tls_connection_init(void *tls_ctx);
@@ -162,16 +156,14 @@
  * tls_connection_established - Has the TLS connection been completed?
  * @tls_ctx: TLS context data from tls_init()
  * @conn: Connection context data from tls_connection_init()
- *
  * Returns: 1 if TLS connection has been completed, 0 if not.
  */
 int tls_connection_established(void *tls_ctx, struct tls_connection *conn);
 
 /**
- * tls_connection_shutdown - Shutdown TLS connection data.
+ * tls_connection_shutdown - Shutdown TLS connection
  * @tls_ctx: TLS context data from tls_init()
  * @conn: Connection context data from tls_connection_init()
- *
  * Returns: 0 on success, -1 on failure
  *
  * Shutdown current TLS connection without releasing all resources. New
@@ -185,12 +177,12 @@
 	TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED = -3,
 	TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED = -2
 };
+
 /**
  * tls_connection_set_params - Set TLS connection parameters
  * @tls_ctx: TLS context data from tls_init()
  * @conn: Connection context data from tls_connection_init()
  * @params: Connection parameters
- *
  * Returns: 0 on success, -1 on failure,
  * TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED (-2) on possible PIN error causing
  * PKCS#11 engine failure, or
@@ -201,21 +193,23 @@
 			      const struct tls_connection_params *params);
 
 /**
- * tls_global_ca_cert - Set trusted CA certificate for all TLS connections
+ * tls_global_set_params - Set TLS parameters for all TLS connection
  * @tls_ctx: TLS context data from tls_init()
- * @ca_cert: File name for CA certificate in PEM or DER format
- * %NULL to allow all subjects
- *
- * Returns: 0 on success, -1 on failure
+ * @params: Global TLS parameters
+ * Returns: 0 on success, -1 on failure,
+ * TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED (-2) on possible PIN error causing
+ * PKCS#11 engine failure, or
+ * TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED (-3) on failure to verify the
+ * PKCS#11 engine private key.
  */
-int tls_global_ca_cert(void *tls_ctx, const char *ca_cert);
+int tls_global_set_params(void *tls_ctx,
+			  const struct tls_connection_params *params);
 
 /**
  * tls_global_set_verify - Set global certificate verification options
  * @tls_ctx: TLS context data from tls_init()
  * @check_crl: 0 = do not verify CRLs, 1 = verify CRL for the user certificate,
  * 2 = verify CRL for all certificates
- *
  * Returns: 0 on success, -1 on failure
  */
 int tls_global_set_verify(void *tls_ctx, int check_crl);
@@ -225,55 +219,73 @@
  * @tls_ctx: TLS context data from tls_init()
  * @conn: Connection context data from tls_connection_init()
  * @verify_peer: 1 = verify peer certificate
- *
  * Returns: 0 on success, -1 on failure
  */
 int tls_connection_set_verify(void *tls_ctx, struct tls_connection *conn,
 			      int verify_peer);
 
 /**
- * tls_global_client_cert - Set client certificate for all TLS connections
+ * tls_connection_set_ia - Set TLS/IA parameters
  * @tls_ctx: TLS context data from tls_init()
- * @client_cert: File name for client certificate in PEM or DER format
- *
+ * @conn: Connection context data from tls_connection_init()
+ * @tls_ia: 1 = enable TLS/IA
  * Returns: 0 on success, -1 on failure
- */
-int tls_global_client_cert(void *tls_ctx, const char *client_cert);
-
-/**
- * tls_global_private_key - Set private key for all TLS connections
- * @tls_ctx: TLS context data from tls_init()
- * @private_key: File name for client private key in PEM or DER format
- * @private_key_passwd: Passphrase for decrypted private key, %NULL if no
- * passphrase is used.
  *
- * Returns: 0 on success, -1 on failure
+ * This function is used to configure TLS/IA in server mode where
+ * tls_connection_set_params() is not used.
  */
-int tls_global_private_key(void *tls_ctx, const char *private_key,
-			   const char *private_key_passwd);
+int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn,
+			  int tls_ia);
 
 /**
  * tls_connection_get_keys - Get master key and random data from TLS connection
  * @tls_ctx: TLS context data from tls_init()
  * @conn: Connection context data from tls_connection_init()
  * @keys: Structure of key/random data (filled on success)
- *
  * Returns: 0 on success, -1 on failure
  */
 int tls_connection_get_keys(void *tls_ctx, struct tls_connection *conn,
 			    struct tls_keys *keys);
 
 /**
+ * tls_connection_prf - Use TLS-PRF to derive keying material
+ * @tls_ctx: TLS context data from tls_init()
+ * @conn: Connection context data from tls_connection_init()
+ * @label: Label (e.g., description of the key) for PRF
+ * @server_random_first: seed is 0 = client_random|server_random,
+ * 1 = server_random|client_random
+ * @out: Buffer for output data from TLS-PRF
+ * @out_len: Length of the output buffer
+ * Returns: 0 on success, -1 on failure
+ *
+ * This function is optional to implement if tls_connection_get_keys() provides
+ * access to master secret and server/client random values. If these values are
+ * not exported from the TLS library, tls_connection_prf() is required so that
+ * further keying material can be derived from the master secret. If not
+ * implemented, the function will still need to be defined, but it can just
+ * return -1. Example implementation of this function is in tls_prf() function
+ * when it is called with seed set to client_random|server_random (or
+ * server_random|client_random).
+ */
+int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
+		       const char *label, int server_random_first,
+		       u8 *out, size_t out_len);
+
+/**
  * tls_connection_handshake - Process TLS handshake (client side)
  * @tls_ctx: TLS context data from tls_init()
  * @conn: Connection context data from tls_connection_init()
  * @in_data: Input data from TLS peer
  * @in_len: Input data length
  * @out_len: Length of the output buffer.
- *
+ * @appl_data: Pointer to application data pointer, or %NULL if dropped
+ * @appl_data_len: Pointer to variable that is set to appl_data length
  * Returns: Pointer to output data, %NULL on failure
  *
- * Caller is responsible for freeing returned output data.
+ * Caller is responsible for freeing returned output data. If the final
+ * handshake message includes application data, this is decrypted and
+ * appl_data (if not %NULL) is set to point this data. Caller is responsible
+ * for freeing appl_data.
  *
  * This function is used during TLS handshake. The first call is done with
  * in_data == %NULL and the library is expected to return ClientHello packet.
@@ -291,7 +303,8 @@
  */
 u8 * tls_connection_handshake(void *tls_ctx, struct tls_connection *conn,
 			      const u8 *in_data, size_t in_len,
-			      size_t *out_len);
+			      size_t *out_len, u8 **appl_data,
+			      size_t *appl_data_len);
 
 /**
  * tls_connection_server_handshake - Process TLS handshake (server side)
@@ -300,7 +313,6 @@
  * @in_data: Input data from TLS peer
  * @in_len: Input data length
  * @out_len: Length of the output buffer.
- *
  * Returns: pointer to output data, %NULL on failure
  *
  * Caller is responsible for freeing returned output data.
@@ -318,7 +330,6 @@
  * @in_len: Input buffer length
  * @out_data: Pointer to output buffer (encrypted TLS data)
  * @out_len: Maximum out_data length 
- *
  * Returns: Number of bytes written to out_data, -1 on failure
  *
  * This function is used after TLS handshake has been completed successfully to
@@ -336,7 +347,6 @@
  * @in_len: Input buffer length
  * @out_data: Pointer to output buffer (decrypted data from TLS tunnel)
  * @out_len: Maximum out_data length
- *
  * Returns: Number of bytes written to out_data, -1 on failure
  *
  * This function is used after TLS handshake has been completed successfully to
@@ -350,7 +360,6 @@
  * tls_connection_resumed - Was session resumption used
  * @tls_ctx: TLS context data from tls_init()
  * @conn: Connection context data from tls_connection_init()
- *
  * Returns: 1 if current session used session resumption, 0 if not
  */
 int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn);
@@ -361,23 +370,29 @@
  * @conn: Connection context data from tls_connection_init()
  * @key: TLS pre-master-secret
  * @key_len: length of key in bytes
- *
  * Returns: 0 on success, -1 on failure
  */
 int tls_connection_set_master_key(void *tls_ctx, struct tls_connection *conn,
 				  const u8 *key, size_t key_len);
 
+enum {
+	TLS_CIPHER_NONE,
+	TLS_CIPHER_RC4_SHA /* 0x0005 */,
+	TLS_CIPHER_AES128_SHA /* 0x002f */,
+	TLS_CIPHER_RSA_DHE_AES128_SHA /* 0x0031 */,
+	TLS_CIPHER_ANON_DH_AES128_SHA /* 0x0034 */
+};
+
 /**
- * tls_connection_set_anon_dh - Configure TLS connection to use anonymous DH
+ * tls_connection_set_cipher_list - Configure acceptable cipher suites
  * @tls_ctx: TLS context data from tls_init()
  * @conn: Connection context data from tls_connection_init()
- *
+ * @ciphers: Zero (TLS_CIPHER_NONE) terminated list of allowed ciphers
+ * (TLS_CIPHER_*).
  * Returns: 0 on success, -1 on failure
- *
- * TODO: consider changing this to more generic routine for configuring allowed
- * ciphers
  */
-int tls_connection_set_anon_dh(void *tls_ctx, struct tls_connection *conn);
+int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
+				   u8 *ciphers);
 
 /**
  * tls_get_cipher - Get current cipher name
@@ -385,7 +400,6 @@
  * @conn: Connection context data from tls_connection_init()
  * @buf: Buffer for the cipher name
  * @buflen: buf size
- *
  * Returns: 0 on success, -1 on failure
  *
  * Get the name of the currently used cipher.
@@ -397,7 +411,6 @@
  * tls_connection_enable_workaround - Enable TLS workaround options
  * @tls_ctx: TLS context data from tls_init()
  * @conn: Connection context data from tls_connection_init()
- *
  * Returns: 0 on success, -1 on failure
  *
  * This function is used to enable connection-specific workaround options for
@@ -411,9 +424,8 @@
  * @tls_ctx: TLS context data from tls_init()
  * @conn: Connection context data from tls_connection_init()
  * @ext_type: Extension type
- * @data: Extension payload (NULL to remove extension)
+ * @data: Extension payload (%NULL to remove extension)
  * @data_len: Extension payload length
- *
  * Returns: 0 on success, -1 on failure
  */
 int tls_connection_client_hello_ext(void *tls_ctx, struct tls_connection *conn,
@@ -433,7 +445,6 @@
  * tls_connection_get_read_alerts - Get connection read alert status
  * @tls_ctx: TLS context data from tls_init()
  * @conn: Connection context data from tls_connection_init()
- *
  * Returns: Number of times a fatal read (remote end reported error) has
  * happened during this connection.
  */
@@ -443,7 +454,6 @@
  * tls_connection_get_write_alerts - Get connection write alert status
  * @tls_ctx: TLS context data from tls_init()
  * @conn: Connection context data from tls_connection_init()
- *
  * Returns: Number of times a fatal write (locally detected error) has happened
  * during this connection.
  */
@@ -460,4 +470,52 @@
 int tls_connection_get_keyblock_size(void *tls_ctx,
 				     struct tls_connection *conn);
 
+#define TLS_CAPABILITY_IA 0x0001 /* TLS Inner Application (TLS/IA) */
+/**
+ * tls_capabilities - Get supported TLS capabilities
+ * @tls_ctx: TLS context data from tls_init()
+ * Returns: Bit field of supported TLS capabilities (TLS_CAPABILITY_*)
+ */
+unsigned int tls_capabilities(void *tls_ctx);
+
+/**
+ * tls_connection_ia_send_phase_finished - Send a TLS/IA PhaseFinished message
+ * @tls_ctx: TLS context data from tls_init()
+ * @conn: Connection context data from tls_connection_init()
+ * @final: 1 = FinalPhaseFinished, 0 = IntermediatePhaseFinished
+ * @out_data: Pointer to output buffer (encrypted TLS/IA data)
+ * @out_len: Maximum out_data length 
+ * Returns: Number of bytes written to out_data on success, -1 on failure
+ *
+ * This function is used to send the TLS/IA end phase message, e.g., when the
+ * EAP server completes EAP-TTLSv1.
+ */
+int tls_connection_ia_send_phase_finished(void *tls_ctx,
+					  struct tls_connection *conn,
+					  int final,
+					  u8 *out_data, size_t out_len);
+
+/**
+ * tls_connection_ia_final_phase_finished - Has final phase been completed
+ * @tls_ctx: TLS context data from tls_init()
+ * @conn: Connection context data from tls_connection_init()
+ * Returns: 1 if valid FinalPhaseFinished has been received, 0 if not, or -1
+ * on failure
+ */
+int tls_connection_ia_final_phase_finished(void *tls_ctx,
+					   struct tls_connection *conn);
+
+/**
+ * tls_connection_ia_permute_inner_secret - Permute TLS/IA inner secret
+ * @tls_ctx: TLS context data from tls_init()
+ * @conn: Connection context data from tls_connection_init()
+ * @key: Session key material (session_key vectors with 2-octet length), or
+ * %NULL if no session key was generating in the current phase
+ * @key_len: Length of session key material
+ * Returns: 0 on success, -1 on failure
+ */
+int tls_connection_ia_permute_inner_secret(void *tls_ctx,
+					   struct tls_connection *conn,
+					   const u8 *key, size_t key_len);
+
 #endif /* TLS_H */
Index: config.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/config.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/config.c -L contrib/wpa_supplicant/config.c -u -r1.2 -r1.3
--- contrib/wpa_supplicant/config.c
+++ contrib/wpa_supplicant/config.c
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant / Configuration parser and common functions
- * Copyright (c) 2003-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2003-2006, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -12,14 +12,11 @@
  * See README and COPYING for more details.
  */
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
+#include "includes.h"
 
 #include "common.h"
 #include "wpa.h"
 #include "sha1.h"
-#include "wpa_supplicant.h"
 #include "eapol_sm.h"
 #include "eap.h"
 #include "l2_packet.h"
@@ -46,9 +43,11 @@
 	/* Variable specific parameters for the parser. */
 	void *param1, *param2, *param3, *param4;
 
-	/* 0 = this variable can be included in debug output
+	/* 0 = this variable can be included in debug output and ctrl_iface
 	 * 1 = this variable contains key/private data and it must not be
-	 *     included in debug output unless explicitly requested
+	 *     included in debug output unless explicitly requested. In
+	 *     addition, this variable will not be readable through the
+	 *     ctrl_iface.
 	 */
 	int key_data;
 };
@@ -59,23 +58,23 @@
 	if (*value == '"') {
 		char *pos;
 		value++;
-		pos = strchr(value, '"');
+		pos = os_strrchr(value, '"');
 		if (pos == NULL || pos[1] != '\0')
 			return NULL;
 		*pos = '\0';
-		*len = strlen(value);
-		return strdup(value);
+		*len = os_strlen(value);
+		return os_strdup(value);
 	} else {
 		u8 *str;
-		size_t hlen = strlen(value);
-		if (hlen % 1)
+		size_t hlen = os_strlen(value);
+		if (hlen & 1)
 			return NULL;
 		*len = hlen / 2;
-		str = malloc(*len);
+		str = os_malloc(*len);
 		if (str == NULL)
 			return NULL;
 		if (hexstr2bin(value, str, *len)) {
-			free(str);
+			os_free(str);
 			return NULL;
 		}
 		return (char *) str;
@@ -88,35 +87,29 @@
 				int line, const char *value)
 {
 	size_t res_len, *dst_len;
-	char **dst;
+	char **dst, *tmp;
 
-	dst = (char **) (((u8 *) ssid) + (long) data->param1);
-	dst_len = (size_t *) (((u8 *) ssid) + (long) data->param2);
-
-	free(*dst);
-	*dst = wpa_config_parse_string(value, &res_len);
-	if (*dst == NULL) {
+	tmp = wpa_config_parse_string(value, &res_len);
+	if (tmp == NULL) {
 		wpa_printf(MSG_ERROR, "Line %d: failed to parse %s '%s'.",
-			   line, data->name, value);
+			   line, data->name,
+			   data->key_data ? "[KEY DATA REMOVED]" : value);
 		return -1;
 	}
-	if (data->param2)
-		*dst_len = res_len;
 
 	if (data->key_data) {
 		wpa_hexdump_ascii_key(MSG_MSGDUMP, data->name,
-				      (u8 *) *dst, res_len);
+				      (u8 *) tmp, res_len);
 	} else {
 		wpa_hexdump_ascii(MSG_MSGDUMP, data->name,
-				  (u8 *) *dst, res_len);
+				  (u8 *) tmp, res_len);
 	}
 
 	if (data->param3 && res_len < (size_t) data->param3) {
 		wpa_printf(MSG_ERROR, "Line %d: too short %s (len=%lu "
 			   "min_len=%ld)", line, data->name,
 			   (unsigned long) res_len, (long) data->param3);
-		free(*dst);
-		*dst = NULL;
+		os_free(tmp);
 		return -1;
 	}
 
@@ -124,18 +117,24 @@
 		wpa_printf(MSG_ERROR, "Line %d: too long %s (len=%lu "
 			   "max_len=%ld)", line, data->name,
 			   (unsigned long) res_len, (long) data->param4);
-		free(*dst);
-		*dst = NULL;
+		os_free(tmp);
 		return -1;
 	}
 
+	dst = (char **) (((u8 *) ssid) + (long) data->param1);
+	dst_len = (size_t *) (((u8 *) ssid) + (long) data->param2);
+	os_free(*dst);
+	*dst = tmp;
+	if (data->param2)
+		*dst_len = res_len;
+
 	return 0;
 }
 
 
 static int is_hex(const u8 *data, size_t len)
 {
-	int i;
+	size_t i;
 
 	for (i = 0; i < len; i++) {
 		if (data[i] < 32 || data[i] >= 127)
@@ -147,17 +146,15 @@
 
 static char * wpa_config_write_string_ascii(const u8 *value, size_t len)
 {
-	int i;
-	char *buf, *pos, *end;
+	char *buf;
 
-	pos = buf = malloc(len + 3);
+	buf = os_malloc(len + 3);
 	if (buf == NULL)
 		return NULL;
-	end = buf + len + 3;
-	pos += snprintf(pos, end - pos, "\"");
-	for (i = 0; i < len; i++)
-		pos += snprintf(pos, end - pos, "%c", value[i]);
-	pos += snprintf(pos, end - pos, "\"");
+	buf[0] = '"';
+	os_memcpy(buf + 1, value, len);
+	buf[len + 1] = '"';
+	buf[len + 2] = '\0';
 
 	return buf;
 }
@@ -165,16 +162,12 @@
 
 static char * wpa_config_write_string_hex(const u8 *value, size_t len)
 {
-	int i;
-	char *buf, *pos, *end;
+	char *buf;
 
-	pos = buf = malloc(2 * len + 1);
+	buf = os_zalloc(2 * len + 1);
 	if (buf == NULL)
 		return NULL;
-	memset(buf, 0, 2 * len + 1);
-	end = buf + 2 * len + 1;
-	for (i = 0; i < len; i++)
-		pos += snprintf(pos, end - pos, "%02x", value[i]);
+	wpa_snprintf_hex(buf, 2 * len + 1, value, len);
 
 	return buf;
 }
@@ -205,7 +198,7 @@
 	if (data->param2)
 		len = *((size_t *) (((u8 *) ssid) + (long) data->param2));
 	else
-		len = strlen(*src);
+		len = os_strlen(*src);
 
 	return wpa_config_write_string((const u8 *) *src, len);
 }
@@ -249,10 +242,11 @@
 
 	src = (int *) (((u8 *) ssid) + (long) data->param1);
 
-	value = malloc(20);
+	value = os_malloc(20);
 	if (value == NULL)
 		return NULL;
-	snprintf(value, 20, "%d", *src);
+	os_snprintf(value, 20, "%d", *src);
+	value[20 - 1] = '\0';
 	return value;
 }
 
@@ -280,10 +274,11 @@
 	if (!ssid->bssid_set)
 		return NULL;
 
-	value = malloc(20);
+	value = os_malloc(20);
 	if (value == NULL)
 		return NULL;
-	snprintf(value, 20, MACSTR, MAC2STR(ssid->bssid));
+	os_snprintf(value, 20, MACSTR, MAC2STR(ssid->bssid));
+	value[20 - 1] = '\0';
 	return value;
 }
 
@@ -293,14 +288,15 @@
 				const char *value)
 {
 	if (*value == '"') {
-		char *pos;
+		const char *pos;
 		size_t len;
 
 		value++;
-		pos = strrchr(value, '"');
+		pos = os_strrchr(value, '"');
 		if (pos)
-			*pos = '\0';
-		len = strlen(value);
+			len = pos - value;
+		else
+			len = os_strlen(value);
 		if (len < 8 || len > 63) {
 			wpa_printf(MSG_ERROR, "Line %d: Invalid passphrase "
 				   "length %lu (expected: 8..63) '%s'.",
@@ -309,8 +305,17 @@
 		}
 		wpa_hexdump_ascii_key(MSG_MSGDUMP, "PSK (ASCII passphrase)",
 				      (u8 *) value, len);
-		ssid->passphrase = strdup(value);
-		return ssid->passphrase == NULL ? -1 : 0;
+		if (ssid->passphrase && os_strlen(ssid->passphrase) == len &&
+		    os_memcmp(ssid->passphrase, value, len) == 0)
+			return 0;
+		ssid->psk_set = 0;
+		os_free(ssid->passphrase);
+		ssid->passphrase = os_malloc(len + 1);
+		if (ssid->passphrase == NULL)
+			return -1;
+		os_memcpy(ssid->passphrase, value, len);
+		ssid->passphrase[len] = '\0';
+		return 0;
 	}
 
 	if (hexstr2bin(value, ssid->psk, PMK_LEN) ||
@@ -319,6 +324,10 @@
 			   line, value);
 		return -1;
 	}
+
+	os_free(ssid->passphrase);
+	ssid->passphrase = NULL;
+
 	ssid->psk_set = 1;
 	wpa_hexdump_key(MSG_MSGDUMP, "PSK", ssid->psk, PMK_LEN);
 	return 0;
@@ -331,7 +340,7 @@
 	if (ssid->passphrase)
 		return wpa_config_write_string_ascii(
 			(const u8 *) ssid->passphrase,
-			strlen(ssid->passphrase));
+			os_strlen(ssid->passphrase));
 
 	if (ssid->psk_set)
 		return wpa_config_write_string_hex(ssid->psk, PMK_LEN);
@@ -347,7 +356,7 @@
 	int val = 0, last, errors = 0;
 	char *start, *end, *buf;
 
-	buf = strdup(value);
+	buf = os_strdup(value);
 	if (buf == NULL)
 		return -1;
 	start = buf;
@@ -362,10 +371,10 @@
 			end++;
 		last = *end == '\0';
 		*end = '\0';
-		if (strcmp(start, "WPA") == 0)
+		if (os_strcmp(start, "WPA") == 0)
 			val |= WPA_PROTO_WPA;
-		else if (strcmp(start, "RSN") == 0 ||
-			 strcmp(start, "WPA2") == 0)
+		else if (os_strcmp(start, "RSN") == 0 ||
+			 os_strcmp(start, "WPA2") == 0)
 			val |= WPA_PROTO_RSN;
 		else {
 			wpa_printf(MSG_ERROR, "Line %d: invalid proto '%s'",
@@ -377,7 +386,7 @@
 			break;
 		start = end + 1;
 	}
-	free(buf);
+	os_free(buf);
 
 	if (val == 0) {
 		wpa_printf(MSG_ERROR,
@@ -394,22 +403,27 @@
 static char * wpa_config_write_proto(const struct parse_data *data,
 				     struct wpa_ssid *ssid)
 {
-	int first = 1;
+	int first = 1, ret;
 	char *buf, *pos, *end;
 
-	pos = buf = malloc(10);
+	pos = buf = os_zalloc(10);
 	if (buf == NULL)
 		return NULL;
-	memset(buf, 0, 10);
 	end = buf + 10;
 
 	if (ssid->proto & WPA_PROTO_WPA) {
-		pos += snprintf(pos, end - pos, "%sWPA", first ? "" : " ");
+		ret = os_snprintf(pos, end - pos, "%sWPA", first ? "" : " ");
+		if (ret < 0 || ret >= end - pos)
+			return buf;
+		pos += ret;
 		first = 0;
 	}
 
 	if (ssid->proto & WPA_PROTO_RSN) {
-		pos += snprintf(pos, end - pos, "%sRSN", first ? "" : " ");
+		ret = os_snprintf(pos, end - pos, "%sRSN", first ? "" : " ");
+		if (ret < 0 || ret >= end - pos)
+			return buf;
+		pos += ret;
 		first = 0;
 	}
 
@@ -424,7 +438,7 @@
 	int val = 0, last, errors = 0;
 	char *start, *end, *buf;
 
-	buf = strdup(value);
+	buf = os_strdup(value);
 	if (buf == NULL)
 		return -1;
 	start = buf;
@@ -439,15 +453,15 @@
 			end++;
 		last = *end == '\0';
 		*end = '\0';
-		if (strcmp(start, "WPA-PSK") == 0)
+		if (os_strcmp(start, "WPA-PSK") == 0)
 			val |= WPA_KEY_MGMT_PSK;
-		else if (strcmp(start, "WPA-EAP") == 0)
+		else if (os_strcmp(start, "WPA-EAP") == 0)
 			val |= WPA_KEY_MGMT_IEEE8021X;
-		else if (strcmp(start, "IEEE8021X") == 0)
+		else if (os_strcmp(start, "IEEE8021X") == 0)
 			val |= WPA_KEY_MGMT_IEEE8021X_NO_WPA;
-		else if (strcmp(start, "NONE") == 0)
+		else if (os_strcmp(start, "NONE") == 0)
 			val |= WPA_KEY_MGMT_NONE;
-		else if (strcmp(start, "WPA-NONE") == 0)
+		else if (os_strcmp(start, "WPA-NONE") == 0)
 			val |= WPA_KEY_MGMT_WPA_NONE;
 		else {
 			wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'",
@@ -459,7 +473,7 @@
 			break;
 		start = end + 1;
 	}
-	free(buf);
+	os_free(buf);
 
 	if (val == 0) {
 		wpa_printf(MSG_ERROR,
@@ -476,40 +490,62 @@
 static char * wpa_config_write_key_mgmt(const struct parse_data *data,
 					struct wpa_ssid *ssid)
 {
-	int first = 1;
 	char *buf, *pos, *end;
+	int ret;
 
-	pos = buf = malloc(50);
+	pos = buf = os_zalloc(50);
 	if (buf == NULL)
 		return NULL;
-	memset(buf, 0, 50);
 	end = buf + 50;
 
 	if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) {
-		pos += snprintf(pos, end - pos, "%sWPA-PSK", first ? "" : " ");
-		first = 0;
+		ret = os_snprintf(pos, end - pos, "%sWPA-PSK",
+				  pos == buf ? "" : " ");
+		if (ret < 0 || ret >= end - pos) {
+			end[-1] = '\0';
+			return buf;
+		}
+		pos += ret;
 	}
 
 	if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
-		pos += snprintf(pos, end - pos, "%sWPA-EAP", first ? "" : " ");
-		first = 0;
+		ret = os_snprintf(pos, end - pos, "%sWPA-EAP",
+				  pos == buf ? "" : " ");
+		if (ret < 0 || ret >= end - pos) {
+			end[-1] = '\0';
+			return buf;
+		}
+		pos += ret;
 	}
 
 	if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
-		pos += snprintf(pos, end - pos, "%sIEEE8021X",
-				first ? "" : " ");
-		first = 0;
+		ret = os_snprintf(pos, end - pos, "%sIEEE8021X",
+				  pos == buf ? "" : " ");
+		if (ret < 0 || ret >= end - pos) {
+			end[-1] = '\0';
+			return buf;
+		}
+		pos += ret;
 	}
 
 	if (ssid->key_mgmt & WPA_KEY_MGMT_NONE) {
-		pos += snprintf(pos, end - pos, "%sNONE", first ? "" : " ");
-		first = 0;
+		ret = os_snprintf(pos, end - pos, "%sNONE",
+				  pos == buf ? "" : " ");
+		if (ret < 0 || ret >= end - pos) {
+			end[-1] = '\0';
+			return buf;
+		}
+		pos += ret;
 	}
 
 	if (ssid->key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
-		pos += snprintf(pos, end - pos, "%sWPA-NONE",
-				first ? "" : " ");
-		first = 0;
+		ret = os_snprintf(pos, end - pos, "%sWPA-NONE",
+				  pos == buf ? "" : " ");
+		if (ret < 0 || ret >= end - pos) {
+			end[-1] = '\0';
+			return buf;
+		}
+		pos += ret;
 	}
 
 	return buf;
@@ -521,7 +557,7 @@
 	int val = 0, last;
 	char *start, *end, *buf;
 
-	buf = strdup(value);
+	buf = os_strdup(value);
 	if (buf == NULL)
 		return -1;
 	start = buf;
@@ -536,20 +572,20 @@
 			end++;
 		last = *end == '\0';
 		*end = '\0';
-		if (strcmp(start, "CCMP") == 0)
+		if (os_strcmp(start, "CCMP") == 0)
 			val |= WPA_CIPHER_CCMP;
-		else if (strcmp(start, "TKIP") == 0)
+		else if (os_strcmp(start, "TKIP") == 0)
 			val |= WPA_CIPHER_TKIP;
-		else if (strcmp(start, "WEP104") == 0)
+		else if (os_strcmp(start, "WEP104") == 0)
 			val |= WPA_CIPHER_WEP104;
-		else if (strcmp(start, "WEP40") == 0)
+		else if (os_strcmp(start, "WEP40") == 0)
 			val |= WPA_CIPHER_WEP40;
-		else if (strcmp(start, "NONE") == 0)
+		else if (os_strcmp(start, "NONE") == 0)
 			val |= WPA_CIPHER_NONE;
 		else {
 			wpa_printf(MSG_ERROR, "Line %d: invalid cipher '%s'.",
 				   line, start);
-			free(buf);
+			os_free(buf);
 			return -1;
 		}
 
@@ -557,7 +593,7 @@
 			break;
 		start = end + 1;
 	}
-	free(buf);
+	os_free(buf);
 
 	if (val == 0) {
 		wpa_printf(MSG_ERROR, "Line %d: no cipher values configured.",
@@ -570,38 +606,62 @@
 
 static char * wpa_config_write_cipher(int cipher)
 {
-	int first = 1;
 	char *buf, *pos, *end;
+	int ret;
 
-	pos = buf = malloc(50);
+	pos = buf = os_zalloc(50);
 	if (buf == NULL)
 		return NULL;
-	memset(buf, 0, 50);
 	end = buf + 50;
 
 	if (cipher & WPA_CIPHER_CCMP) {
-		pos += snprintf(pos, end - pos, "%sCCMP", first ? "" : " ");
-		first = 0;
+		ret = os_snprintf(pos, end - pos, "%sCCMP",
+				  pos == buf ? "" : " ");
+		if (ret < 0 || ret >= end - pos) {
+			end[-1] = '\0';
+			return buf;
+		}
+		pos += ret;
 	}
 
 	if (cipher & WPA_CIPHER_TKIP) {
-		pos += snprintf(pos, end - pos, "%sTKIP", first ? "" : " ");
-		first = 0;
+		ret = os_snprintf(pos, end - pos, "%sTKIP",
+				  pos == buf ? "" : " ");
+		if (ret < 0 || ret >= end - pos) {
+			end[-1] = '\0';
+			return buf;
+		}
+		pos += ret;
 	}
 
 	if (cipher & WPA_CIPHER_WEP104) {
-		pos += snprintf(pos, end - pos, "%sWEP104", first ? "" : " ");
-		first = 0;
+		ret = os_snprintf(pos, end - pos, "%sWEP104",
+				  pos == buf ? "" : " ");
+		if (ret < 0 || ret >= end - pos) {
+			end[-1] = '\0';
+			return buf;
+		}
+		pos += ret;
 	}
 
 	if (cipher & WPA_CIPHER_WEP40) {
-		pos += snprintf(pos, end - pos, "%sWEP40", first ? "" : " ");
-		first = 0;
+		ret = os_snprintf(pos, end - pos, "%sWEP40",
+				  pos == buf ? "" : " ");
+		if (ret < 0 || ret >= end - pos) {
+			end[-1] = '\0';
+			return buf;
+		}
+		pos += ret;
 	}
 
 	if (cipher & WPA_CIPHER_NONE) {
-		pos += snprintf(pos, end - pos, "%sNONE", first ? "" : " ");
-		first = 0;
+		ret = os_snprintf(pos, end - pos, "%sNONE",
+				  pos == buf ? "" : " ");
+		if (ret < 0 || ret >= end - pos) {
+			end[-1] = '\0';
+			return buf;
+		}
+		pos += ret;
 	}
 
 	return buf;
@@ -670,7 +730,7 @@
 	int val = 0, last, errors = 0;
 	char *start, *end, *buf;
 
-	buf = strdup(value);
+	buf = os_strdup(value);
 	if (buf == NULL)
 		return -1;
 	start = buf;
@@ -685,11 +745,11 @@
 			end++;
 		last = *end == '\0';
 		*end = '\0';
-		if (strcmp(start, "OPEN") == 0)
+		if (os_strcmp(start, "OPEN") == 0)
 			val |= WPA_AUTH_ALG_OPEN;
-		else if (strcmp(start, "SHARED") == 0)
+		else if (os_strcmp(start, "SHARED") == 0)
 			val |= WPA_AUTH_ALG_SHARED;
-		else if (strcmp(start, "LEAP") == 0)
+		else if (os_strcmp(start, "LEAP") == 0)
 			val |= WPA_AUTH_ALG_LEAP;
 		else {
 			wpa_printf(MSG_ERROR, "Line %d: invalid auth_alg '%s'",
@@ -701,7 +761,7 @@
 			break;
 		start = end + 1;
 	}
-	free(buf);
+	os_free(buf);
 
 	if (val == 0) {
 		wpa_printf(MSG_ERROR,
@@ -718,44 +778,59 @@
 static char * wpa_config_write_auth_alg(const struct parse_data *data,
 					struct wpa_ssid *ssid)
 {
-	int first = 1;
 	char *buf, *pos, *end;
+	int ret;
 
-	pos = buf = malloc(30);
+	pos = buf = os_zalloc(30);
 	if (buf == NULL)
 		return NULL;
-	memset(buf, 0, 30);
 	end = buf + 30;
 
 	if (ssid->auth_alg & WPA_AUTH_ALG_OPEN) {
-		pos += snprintf(pos, end - pos, "%sOPEN", first ? "" : " ");
-		first = 0;
+		ret = os_snprintf(pos, end - pos, "%sOPEN",
+				  pos == buf ? "" : " ");
+		if (ret < 0 || ret >= end - pos) {
+			end[-1] = '\0';
+			return buf;
+		}
+		pos += ret;
 	}
 
 	if (ssid->auth_alg & WPA_AUTH_ALG_SHARED) {
-		pos += snprintf(pos, end - pos, "%sSHARED", first ? "" : " ");
-		first = 0;
+		ret = os_snprintf(pos, end - pos, "%sSHARED",
+				  pos == buf ? "" : " ");
+		if (ret < 0 || ret >= end - pos) {
+			end[-1] = '\0';
+			return buf;
+		}
+		pos += ret;
 	}
 
 	if (ssid->auth_alg & WPA_AUTH_ALG_LEAP) {
-		pos += snprintf(pos, end - pos, "%sLEAP", first ? "" : " ");
-		first = 0;
+		ret = os_snprintf(pos, end - pos, "%sLEAP",
+				  pos == buf ? "" : " ");
+		if (ret < 0 || ret >= end - pos) {
+			end[-1] = '\0';
+			return buf;
+		}
+		pos += ret;
 	}
 
 	return buf;
 }
 
 
+#ifdef IEEE8021X_EAPOL
 static int wpa_config_parse_eap(const struct parse_data *data,
 				struct wpa_ssid *ssid, int line,
 				const char *value)
 {
 	int last, errors = 0;
 	char *start, *end, *buf;
-	u8 *methods = NULL, *tmp;
+	struct eap_method_type *methods = NULL, *tmp;
 	size_t num_methods = 0;
 
-	buf = strdup(value);
+	buf = os_strdup(value);
 	if (buf == NULL)
 		return -1;
 	start = buf;
@@ -771,13 +846,17 @@
 		last = *end == '\0';
 		*end = '\0';
 		tmp = methods;
-		methods = realloc(methods, num_methods + 1);
+		methods = os_realloc(methods,
+				     (num_methods + 1) * sizeof(*methods));
 		if (methods == NULL) {
-			free(tmp);
+			os_free(tmp);
+			os_free(buf);
 			return -1;
 		}
-		methods[num_methods] = eap_get_type(start);
-		if (methods[num_methods] == EAP_TYPE_NONE) {
+		methods[num_methods].method = eap_get_type(
+			start, &methods[num_methods].vendor);
+		if (methods[num_methods].vendor == EAP_VENDOR_IETF &&
+		    methods[num_methods].method == EAP_TYPE_NONE) {
 			wpa_printf(MSG_ERROR, "Line %d: unknown EAP method "
 				   "'%s'", line, start);
 			wpa_printf(MSG_ERROR, "You may need to add support for"
@@ -785,7 +864,8 @@
 				   "build time configuration.\n"
 				   "See README for more information.");
 			errors++;
-		} else if (methods[num_methods] == EAP_TYPE_LEAP)
+		} else if (methods[num_methods].vendor == EAP_VENDOR_IETF &&
+			   methods[num_methods].method == EAP_TYPE_LEAP)
 			ssid->leap++;
 		else
 			ssid->non_leap++;
@@ -794,18 +874,20 @@
 			break;
 		start = end + 1;
 	}
-	free(buf);
+	os_free(buf);
 
 	tmp = methods;
-	methods = realloc(methods, num_methods + 1);
+	methods = os_realloc(methods, (num_methods + 1) * sizeof(*methods));
 	if (methods == NULL) {
-		free(tmp);
+		os_free(tmp);
 		return -1;
 	}
-	methods[num_methods] = EAP_TYPE_NONE;
+	methods[num_methods].vendor = EAP_VENDOR_IETF;
+	methods[num_methods].method = EAP_TYPE_NONE;
 	num_methods++;
 
-	wpa_hexdump(MSG_MSGDUMP, "eap methods", methods, num_methods);
+	wpa_hexdump(MSG_MSGDUMP, "eap methods",
+		    (u8 *) methods, num_methods * sizeof(*methods));
 	ssid->eap_methods = methods;
 	return errors ? -1 : 0;
 }
@@ -814,31 +896,37 @@
 static char * wpa_config_write_eap(const struct parse_data *data,
 				   struct wpa_ssid *ssid)
 {
-	int first = 1;
+	int i, ret;
 	char *buf, *pos, *end;
-	const u8 *eap_methods = ssid->eap_methods;
+	const struct eap_method_type *eap_methods = ssid->eap_methods;
 	const char *name;
 
 	if (eap_methods == NULL)
 		return NULL;
 
-	pos = buf = malloc(100);
+	pos = buf = os_zalloc(100);
 	if (buf == NULL)
 		return NULL;
-	memset(buf, 0, 100);
 	end = buf + 100;
 
-	while (*eap_methods != EAP_TYPE_NONE) {
-		name = eap_get_name(*eap_methods);
-		if (name)
-			pos += snprintf(pos, end - pos, "%s%s",
-					first ? "" : " ", name);
-		first = 0;
-		eap_methods++;
+	for (i = 0; eap_methods[i].vendor != EAP_VENDOR_IETF ||
+		     eap_methods[i].method != EAP_TYPE_NONE; i++) {
+		name = eap_get_name(eap_methods[i].vendor,
+				    eap_methods[i].method);
+		if (name) {
+			ret = os_snprintf(pos, end - pos, "%s%s",
+					  pos == buf ? "" : " ", name);
+			if (ret < 0 || ret >= end - pos)
+				break;
+			pos += ret;
+		}
 	}
 
+	end[-1] = '\0';
+
 	return buf;
 }
+#endif /* IEEE8021X_EAPOL */
 
 
 static int wpa_config_parse_wep_key(u8 *key, size_t *len, int line,
@@ -855,12 +943,12 @@
 	if (*len > MAX_WEP_KEY_LEN) {
 		wpa_printf(MSG_ERROR, "Line %d: Too long WEP key %d '%s'.",
 			   line, idx, value);
-		free(buf);
+		os_free(buf);
 		return -1;
 	}
-	memcpy(key, buf, *len);
-	free(buf);
-	snprintf(title, sizeof(title), "wep_key%d", idx);
+	os_memcpy(key, buf, *len);
+	os_free(buf);
+	os_snprintf(title, sizeof(title), "wep_key%d", idx);
 	wpa_hexdump_key(MSG_MSGDUMP, title, key, *len);
 	return 0;
 }
@@ -945,42 +1033,50 @@
 
 /* Helper macros for network block parser */
 
+#ifdef OFFSET
+#undef OFFSET
+#endif /* OFFSET */
 /* OFFSET: Get offset of a variable within the wpa_ssid structure */
 #define OFFSET(v) ((void *) &((struct wpa_ssid *) 0)->v)
 
 /* STR: Define a string variable for an ASCII string; f = field name */
-#define STR(f) .name = #f, .parser = wpa_config_parse_str, \
-	.writer = wpa_config_write_str, .param1 = OFFSET(f)
+#define _STR(f) #f, wpa_config_parse_str, wpa_config_write_str, OFFSET(f)
+#define STR(f) _STR(f), NULL, NULL, NULL, 0
+#define STR_KEY(f) _STR(f), NULL, NULL, NULL, 1
 
 /* STR_LEN: Define a string variable with a separate variable for storing the
  * data length. Unlike STR(), this can be used to store arbitrary binary data
  * (i.e., even nul termination character). */
-#define STR_LEN(f) STR(f), .param2 = OFFSET(f ## _len)
+#define _STR_LEN(f) _STR(f), OFFSET(f ## _len)
+#define STR_LEN(f) _STR_LEN(f), NULL, NULL, 0
+#define STR_LEN_KEY(f) _STR_LEN(f), NULL, NULL, 1
 
 /* STR_RANGE: Like STR_LEN(), but with minimum and maximum allowed length
  * explicitly specified. */
-#define STR_RANGE(f, min, max) STR_LEN(f), .param3 = (void *) (min), \
-	.param4 = (void *) (max)
+#define _STR_RANGE(f, min, max) _STR_LEN(f), (void *) (min), (void *) (max)
+#define STR_RANGE(f, min, max) _STR_RANGE(f, min, max), 0
+#define STR_RANGE_KEY(f, min, max) _STR_RANGE(f, min, max), 1
 
+#define _INT(f) #f, wpa_config_parse_int, wpa_config_write_int, \
+	OFFSET(f), (void *) 0
 
 /* INT: Define an integer variable */
-#define INT(f) .name = #f, .parser = wpa_config_parse_int, \
-	.writer = wpa_config_write_int, \
-	.param1 = OFFSET(f), .param2 = (void *) 0
-
-/* INT: Define an integer variable with allowed value range */
-#define INT_RANGE(f, min, max) INT(f), .param3 = (void *) (min), \
-	.param4 = (void *) (max)
+#define INT(f) _INT(f), NULL, NULL, 0
+
+/* INT_RANGE: Define an integer variable with allowed value range */
+#define INT_RANGE(f, min, max) _INT(f), (void *) (min), (void *) (max), 0
 
 /* FUNC: Define a configuration variable that uses a custom function for
  * parsing and writing the value. */
-#define FUNC(f) .name = #f, .parser = wpa_config_parse_ ## f, \
-		.writer = wpa_config_write_ ## f
+#define _FUNC(f) #f, wpa_config_parse_ ## f, wpa_config_write_ ## f, \
+	NULL, NULL, NULL, NULL
+#define FUNC(f) _FUNC(f), 0
+#define FUNC_KEY(f) _FUNC(f), 1
 
 /*
  * Table of network configuration variables. This table is used to parse each
  * network configuration variable, e.g., each line in wpa_supplicant.conf file
- * that is insider a network block.
+ * that is inside a network block.
  *
  * This table is generated using the helper macros defined above and with
  * generous help from the C pre-processor. The field name is stored as a string
@@ -995,31 +1091,33 @@
  * function (.parser) is then called to parse the actual value of the field.
  *
  * This kind of mechanism makes it easy to add new configuration parameters,
- * since only one line needs to be added into this table and in struct wpa_ssid
- * definitions if the new variable is either a string or integer. More complex
- * types will need to use their own parser and writer functions.
+ * since only one line needs to be added into this table and into the
+ * struct wpa_ssid definition if the new variable is either a string or
+ * integer. More complex types will need to use their own parser and writer
+ * functions.
  */
 static const struct parse_data ssid_fields[] = {
 	{ STR_RANGE(ssid, 0, MAX_SSID_LEN) },
 	{ INT_RANGE(scan_ssid, 0, 1) },
 	{ FUNC(bssid) },
-	{ FUNC(psk), .key_data = 1 },
+	{ FUNC_KEY(psk) },
 	{ FUNC(proto) },
 	{ FUNC(key_mgmt) },
 	{ FUNC(pairwise) },
 	{ FUNC(group) },
 	{ FUNC(auth_alg) },
+#ifdef IEEE8021X_EAPOL
 	{ FUNC(eap) },
 	{ STR_LEN(identity) },
 	{ STR_LEN(anonymous_identity) },
-	{ STR_RANGE(eappsk, EAP_PSK_LEN, EAP_PSK_LEN), .key_data = 1 },
+	{ STR_RANGE_KEY(eappsk, EAP_PSK_LEN_MIN, EAP_PSK_LEN_MAX) },
 	{ STR_LEN(nai) },
-	{ STR_LEN(password), .key_data = 1 },
+	{ STR_LEN_KEY(password) },
 	{ STR(ca_cert) },
 	{ STR(ca_path) },
 	{ STR(client_cert) },
 	{ STR(private_key) },
-	{ STR(private_key_passwd), .key_data = 1 },
+	{ STR_KEY(private_key_passwd) },
 	{ STR(dh_file) },
 	{ STR(subject_match) },
 	{ STR(altsubject_match) },
@@ -1027,44 +1125,64 @@
 	{ STR(ca_path2) },
 	{ STR(client_cert2) },
 	{ STR(private_key2) },
-	{ STR(private_key2_passwd), .key_data = 1 },
+	{ STR_KEY(private_key2_passwd) },
 	{ STR(dh_file2) },
 	{ STR(subject_match2) },
 	{ STR(altsubject_match2) },
 	{ STR(phase1) },
 	{ STR(phase2) },
 	{ STR(pcsc) },
-	{ STR(pin), .key_data = 1 },
+	{ STR_KEY(pin) },
 	{ STR(engine_id) },
 	{ STR(key_id) },
 	{ INT(engine) },
 	{ INT(eapol_flags) },
-	{ FUNC(wep_key0), .key_data = 1 },
-	{ FUNC(wep_key1), .key_data = 1 },
-	{ FUNC(wep_key2), .key_data = 1 },
-	{ FUNC(wep_key3), .key_data = 1 },
+#endif /* IEEE8021X_EAPOL */
+	{ FUNC_KEY(wep_key0) },
+	{ FUNC_KEY(wep_key1) },
+	{ FUNC_KEY(wep_key2) },
+	{ FUNC_KEY(wep_key3) },
 	{ INT(wep_tx_keyidx) },
 	{ INT(priority) },
+#ifdef IEEE8021X_EAPOL
 	{ INT(eap_workaround) },
 	{ STR(pac_file) },
+	{ INT(fragment_size) },
+#endif /* IEEE8021X_EAPOL */
 	{ INT_RANGE(mode, 0, 1) },
 	{ INT_RANGE(proactive_key_caching, 0, 1) },
 	{ INT_RANGE(disabled, 0, 1) },
+	{ STR(id_str) },
+#ifdef CONFIG_IEEE80211W
+	{ INT_RANGE(ieee80211w, 0, 2) },
+#endif /* CONFIG_IEEE80211W */
+	{ INT_RANGE(peerkey, 0, 1) },
+	{ INT_RANGE(mixed_cell, 0, 1) }
 };
 
 #undef OFFSET
+#undef _STR
 #undef STR
+#undef STR_KEY
+#undef _STR_LEN
 #undef STR_LEN
+#undef STR_LEN_KEY
+#undef _STR_RANGE
 #undef STR_RANGE
+#undef STR_RANGE_KEY
+#undef _INT
 #undef INT
 #undef INT_RANGE
+#undef _FUNC
 #undef FUNC
+#undef FUNC_KEY
 #define NUM_SSID_FIELDS (sizeof(ssid_fields) / sizeof(ssid_fields[0]))
 
 
 /**
  * wpa_config_add_prio_network - Add a network to priority lists
  * @config: Configuration data from wpa_config_read()
+ * @ssid: Pointer to the network configuration to be added to the list
  * Returns: 0 on success, -1 on failure
  *
  * This function is used to add a network block to the priority list of
@@ -1078,6 +1196,10 @@
 	int prio;
 	struct wpa_ssid *prev, **nlist;
 
+	/*
+	 * Add to an existing priority list if one is available for the
+	 * configured priority level for this network.
+	 */
 	for (prio = 0; prio < config->num_prio; prio++) {
 		prev = config->pssid[prio];
 		if (prev->priority == ssid->priority) {
@@ -1088,9 +1210,9 @@
 		}
 	}
 
-	/* First network for this priority - add new priority list */
-	nlist = realloc(config->pssid,
-			(config->num_prio + 1) * sizeof(struct wpa_ssid *));
+	/* First network for this priority - add a new priority list */
+	nlist = os_realloc(config->pssid,
+			   (config->num_prio + 1) * sizeof(struct wpa_ssid *));
 	if (nlist == NULL)
 		return -1;
 
@@ -1099,8 +1221,8 @@
 			break;
 	}
 
-	memmove(&nlist[prio + 1], &nlist[prio],
-		(config->num_prio - prio) * sizeof(struct wpa_ssid *));
+	os_memmove(&nlist[prio + 1], &nlist[prio],
+		   (config->num_prio - prio) * sizeof(struct wpa_ssid *));
 
 	nlist[prio] = ssid;
 	config->num_prio++;
@@ -1124,7 +1246,7 @@
 	struct wpa_ssid *ssid;
 	int ret = 0;
 
-	free(config->pssid);
+	os_free(config->pssid);
 	config->pssid = NULL;
 	config->num_prio = 0;
 
@@ -1144,46 +1266,49 @@
  * wpa_config_free_ssid - Free network/ssid configuration data
  * @ssid: Configuration data for the network
  *
- * This function frees all resources allocated for the netowkr configuration
+ * This function frees all resources allocated for the network configuration
  * data.
  */
 void wpa_config_free_ssid(struct wpa_ssid *ssid)
 {
-	free(ssid->ssid);
-	free(ssid->passphrase);
-	free(ssid->eap_methods);
-	free(ssid->identity);
-	free(ssid->anonymous_identity);
-	free(ssid->eappsk);
-	free(ssid->nai);
-	free(ssid->password);
-	free(ssid->ca_cert);
-	free(ssid->ca_path);
-	free(ssid->client_cert);
-	free(ssid->private_key);
-	free(ssid->private_key_passwd);
-	free(ssid->dh_file);
-	free(ssid->subject_match);
-	free(ssid->altsubject_match);
-	free(ssid->ca_cert2);
-	free(ssid->ca_path2);
-	free(ssid->client_cert2);
-	free(ssid->private_key2);
-	free(ssid->private_key2_passwd);
-	free(ssid->dh_file2);
-	free(ssid->subject_match2);
-	free(ssid->altsubject_match2);
-	free(ssid->phase1);
-	free(ssid->phase2);
-	free(ssid->pcsc);
-	free(ssid->pin);
-	free(ssid->engine_id);
-	free(ssid->key_id);
-	free(ssid->otp);
-	free(ssid->pending_req_otp);
-	free(ssid->pac_file);
-	free(ssid->new_password);
-	free(ssid);
+	os_free(ssid->ssid);
+	os_free(ssid->passphrase);
+#ifdef IEEE8021X_EAPOL
+	os_free(ssid->eap_methods);
+	os_free(ssid->identity);
+	os_free(ssid->anonymous_identity);
+	os_free(ssid->eappsk);
+	os_free(ssid->nai);
+	os_free(ssid->password);
+	os_free(ssid->ca_cert);
+	os_free(ssid->ca_path);
+	os_free(ssid->client_cert);
+	os_free(ssid->private_key);
+	os_free(ssid->private_key_passwd);
+	os_free(ssid->dh_file);
+	os_free(ssid->subject_match);
+	os_free(ssid->altsubject_match);
+	os_free(ssid->ca_cert2);
+	os_free(ssid->ca_path2);
+	os_free(ssid->client_cert2);
+	os_free(ssid->private_key2);
+	os_free(ssid->private_key2_passwd);
+	os_free(ssid->dh_file2);
+	os_free(ssid->subject_match2);
+	os_free(ssid->altsubject_match2);
+	os_free(ssid->phase1);
+	os_free(ssid->phase2);
+	os_free(ssid->pcsc);
+	os_free(ssid->pin);
+	os_free(ssid->engine_id);
+	os_free(ssid->key_id);
+	os_free(ssid->otp);
+	os_free(ssid->pending_req_otp);
+	os_free(ssid->pac_file);
+	os_free(ssid->new_password);
+#endif /* IEEE8021X_EAPOL */
+	os_free(ssid->id_str);
+	os_free(ssid);
 }
 
 
@@ -1213,37 +1338,43 @@
 		wpa_config_free_blob(prevblob);
 	}
 
-	free(config->ctrl_interface);
-	free(config->opensc_engine_path);
-	free(config->pkcs11_engine_path);
-	free(config->pkcs11_module_path);
-	free(config->driver_param);
-	free(config->pssid);
-	free(config);
+	os_free(config->ctrl_interface);
+	os_free(config->ctrl_interface_group);
+	os_free(config->opensc_engine_path);
+	os_free(config->pkcs11_engine_path);
+	os_free(config->pkcs11_module_path);
+	os_free(config->driver_param);
+	os_free(config->pssid);
+	os_free(config);
 }
 
 
+#ifdef IEEE8021X_EAPOL
 /**
  * wpa_config_allowed_eap_method - Check whether EAP method is allowed
- * @ssid: Pointer to a configuration data
+ * @ssid: Pointer to configuration data
+ * @vendor: Vendor-Id for expanded types or 0 = IETF for legacy types
  * @method: EAP type
  * Returns: 1 = allowed EAP method, 0 = not allowed
  */
-int wpa_config_allowed_eap_method(struct wpa_ssid *ssid, int method)
+int wpa_config_allowed_eap_method(struct wpa_ssid *ssid, int vendor,
+				  u32 method)
 {
-	u8 *pos;
+	int i;
+	struct eap_method_type *m;
 
 	if (ssid == NULL || ssid->eap_methods == NULL)
 		return 1;
 
-	pos = ssid->eap_methods;
-	while (*pos != EAP_TYPE_NONE) {
-		if (*pos == method)
+	m = ssid->eap_methods;
+	for (i = 0; m[i].vendor != EAP_VENDOR_IETF ||
+		     m[i].method != EAP_TYPE_NONE; i++) {
+		if (m[i].vendor == vendor && m[i].method == method)
 			return 1;
-		pos++;
 	}
 	return 0;
 }
+#endif /* IEEE8021X_EAPOL */
 
 
 /**
@@ -1287,10 +1418,9 @@
 	}
 	id++;
 
-	ssid = malloc(sizeof(*ssid));
+	ssid = os_zalloc(sizeof(*ssid));
 	if (ssid == NULL)
 		return NULL;
-	memset(ssid, 0, sizeof(*ssid));
 	ssid->id = id;
 	if (last)
 		last->next = ssid;
@@ -1337,7 +1467,7 @@
 
 /**
  * wpa_config_set_network_defaults - Set network default values
- * @ssid: Pointer to a network configuration data
+ * @ssid: Pointer to network configuration data
  */
 void wpa_config_set_network_defaults(struct wpa_ssid *ssid)
 {
@@ -1345,14 +1475,17 @@
 	ssid->pairwise_cipher = DEFAULT_PAIRWISE;
 	ssid->group_cipher = DEFAULT_GROUP;
 	ssid->key_mgmt = DEFAULT_KEY_MGMT;
+#ifdef IEEE8021X_EAPOL
 	ssid->eapol_flags = DEFAULT_EAPOL_FLAGS;
 	ssid->eap_workaround = DEFAULT_EAP_WORKAROUND;
+	ssid->fragment_size = DEFAULT_FRAGMENT_SIZE;
+#endif /* IEEE8021X_EAPOL */
 }
 
 
 /**
  * wpa_config_set - Set a variable in network configuration
- * @ssid: Pointer to a network configuration data
+ * @ssid: Pointer to network configuration data
  * @var: Variable name, e.g., "ssid"
  * @value: Variable value
  * @line: Line number in configuration file or 0 if not used
@@ -1366,14 +1499,15 @@
 int wpa_config_set(struct wpa_ssid *ssid, const char *var, const char *value,
 		   int line)
 {
-	int i, ret = 0;
+	size_t i;
+	int ret = 0;
 
 	if (ssid == NULL || var == NULL || value == NULL)
 		return -1;
 
 	for (i = 0; i < NUM_SSID_FIELDS; i++) {
 		const struct parse_data *field = &ssid_fields[i];
-		if (strcmp(var, field->name) != 0)
+		if (os_strcmp(var, field->name) != 0)
 			continue;
 
 		if (field->parser(field, ssid, line, value)) {
@@ -1399,7 +1533,7 @@
 
 /**
  * wpa_config_get - Get a variable in network configuration
- * @ssid: Pointer to a network configuration data
+ * @ssid: Pointer to network configuration data
  * @var: Variable name, e.g., "ssid"
  * Returns: Value of the variable or %NULL on failure
  *
@@ -1411,14 +1545,14 @@
  */
 char * wpa_config_get(struct wpa_ssid *ssid, const char *var)
 {
-	int i;
+	size_t i;
 
 	if (ssid == NULL || var == NULL)
 		return NULL;
 
 	for (i = 0; i < NUM_SSID_FIELDS; i++) {
 		const struct parse_data *field = &ssid_fields[i];
-		if (strcmp(var, field->name) == 0)
+		if (os_strcmp(var, field->name) == 0)
 			return field->writer(field, ssid);
 	}
 
@@ -1427,8 +1561,55 @@
 
 
 /**
+ * wpa_config_get_no_key - Get a variable in network configuration (no keys)
+ * @ssid: Pointer to network configuration data
+ * @var: Variable name, e.g., "ssid"
+ * Returns: Value of the variable or %NULL on failure
+ *
+ * This function can be used to get network configuration variable like
+ * wpa_config_get(). The only difference is that this functions does not expose
+ * key/password material from the configuration. In case a key/password field
+ * is requested, the returned value is an empty string or %NULL if the variable
+ * is not set or "*" if the variable is set (regardless of its value). The
+ * returned value is a copy of the configuration variable in text format, i.e,.
+ * the same format that the text-based configuration file and wpa_config_set()
+ * are using for the value. The caller is responsible for freeing the returned
+ * value.
+ */
+char * wpa_config_get_no_key(struct wpa_ssid *ssid, const char *var)
+{
+	size_t i;
+
+	if (ssid == NULL || var == NULL)
+		return NULL;
+
+	for (i = 0; i < NUM_SSID_FIELDS; i++) {
+		const struct parse_data *field = &ssid_fields[i];
+		if (os_strcmp(var, field->name) == 0) {
+			char *res = field->writer(field, ssid);
+			if (field->key_data) {
+				if (res && res[0]) {
+					wpa_printf(MSG_DEBUG, "Do not allow "
+						   "key_data field to be "
+						   "exposed");
+					os_free(res);
+					return os_strdup("*");
+				}
+
+				os_free(res);
+				return NULL;
+			}
+			return res;
+		}
+	}
+
+	return NULL;
+}
+
+
+/**
  * wpa_config_update_psk - Update WPA PSK based on passphrase and SSID
- * @ssid: Pointer to a network configuration data
+ * @ssid: Pointer to network configuration data
  *
  * This function must be called to update WPA PSK when either SSID or the
  * passphrase has changed for the network configuration.
@@ -1456,7 +1637,7 @@
 	struct wpa_config_blob *blob = config->blobs;
 
 	while (blob) {
-		if (strcmp(blob->name, name) == 0)
+		if (os_strcmp(blob->name, name) == 0)
 			return blob;
 		blob = blob->next;
 	}
@@ -1488,9 +1669,9 @@
 void wpa_config_free_blob(struct wpa_config_blob *blob)
 {
 	if (blob) {
-		free(blob->name);
-		free(blob->data);
-		free(blob);
+		os_free(blob->name);
+		os_free(blob->data);
+		os_free(blob);
 	}
 }
 
@@ -1506,7 +1687,7 @@
 	struct wpa_config_blob *pos = config->blobs, *prev = NULL;
 
 	while (pos) {
-		if (strcmp(pos->name, name) == 0) {
+		if (os_strcmp(pos->name, name) == 0) {
 			if (prev)
 				prev->next = pos->next;
 			else
@@ -1534,18 +1715,42 @@
 {
 	struct wpa_config *config;
 
-	config = malloc(sizeof(*config));
+	config = os_zalloc(sizeof(*config));
 	if (config == NULL)
 		return NULL;
-	memset(config, 0, sizeof(*config));
 	config->eapol_version = DEFAULT_EAPOL_VERSION;
 	config->ap_scan = DEFAULT_AP_SCAN;
 	config->fast_reauth = DEFAULT_FAST_REAUTH;
 
 	if (ctrl_interface)
-		config->ctrl_interface = strdup(ctrl_interface);
+		config->ctrl_interface = os_strdup(ctrl_interface);
 	if (driver_param)
-		config->driver_param = strdup(driver_param);
+		config->driver_param = os_strdup(driver_param);
 
 	return config;
 }
+
+
+#ifndef CONFIG_NO_STDOUT_DEBUG
+/**
+ * wpa_config_debug_dump_networks - Debug dump of configured networks
+ * @config: Configuration data from wpa_config_read()
+ */
+void wpa_config_debug_dump_networks(struct wpa_config *config)
+{
+	int prio;
+	struct wpa_ssid *ssid;
+
+	for (prio = 0; prio < config->num_prio; prio++) {
+		ssid = config->pssid[prio];
+		wpa_printf(MSG_DEBUG, "Priority group %d",
+			   ssid->priority);
+		while (ssid) {
+			wpa_printf(MSG_DEBUG, "   id=%d ssid='%s'",
+				   ssid->id,
+				   wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
+			ssid = ssid->pnext;
+		}
+	}
+}
+#endif /* CONFIG_NO_STDOUT_DEBUG */
Index: drivers.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/drivers.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/drivers.c -L contrib/wpa_supplicant/drivers.c -u -r1.2 -r1.3
--- contrib/wpa_supplicant/drivers.c
+++ contrib/wpa_supplicant/drivers.c
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant / driver interface list
- * Copyright (c) 2004-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2004-2005, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -12,9 +12,12 @@
  * See README and COPYING for more details.
  */
 
-#include <stdlib.h>
+#include "includes.h"
 
 
+#ifdef CONFIG_DRIVER_WEXT
+extern struct wpa_driver_ops wpa_driver_wext_ops; /* driver_wext.c */
+#endif /* CONFIG_DRIVER_WEXT */
 #ifdef CONFIG_DRIVER_HOSTAP
 extern struct wpa_driver_ops wpa_driver_hostap_ops; /* driver_hostap.c */
 #endif /* CONFIG_DRIVER_HOSTAP */
@@ -30,9 +33,6 @@
 #ifdef CONFIG_DRIVER_ATMEL
 extern struct wpa_driver_ops wpa_driver_atmel_ops; /* driver_atmel.c */
 #endif /* CONFIG_DRIVER_ATMEL */
-#ifdef CONFIG_DRIVER_WEXT
-extern struct wpa_driver_ops wpa_driver_wext_ops; /* driver_wext.c */
-#endif /* CONFIG_DRIVER_WEXT */
 #ifdef CONFIG_DRIVER_NDISWRAPPER
 /* driver_ndiswrapper.c */
 extern struct wpa_driver_ops wpa_driver_ndiswrapper_ops;
@@ -59,6 +59,9 @@
 
 struct wpa_driver_ops *wpa_supplicant_drivers[] =
 {
+#ifdef CONFIG_DRIVER_WEXT
+	&wpa_driver_wext_ops,
+#endif /* CONFIG_DRIVER_WEXT */
 #ifdef CONFIG_DRIVER_HOSTAP
 	&wpa_driver_hostap_ops,
 #endif /* CONFIG_DRIVER_HOSTAP */
@@ -74,9 +77,6 @@
 #ifdef CONFIG_DRIVER_ATMEL
 	&wpa_driver_atmel_ops,
 #endif /* CONFIG_DRIVER_ATMEL */
-#ifdef CONFIG_DRIVER_WEXT
-	&wpa_driver_wext_ops,
-#endif /* CONFIG_DRIVER_WEXT */
 #ifdef CONFIG_DRIVER_NDISWRAPPER
 	&wpa_driver_ndiswrapper_ops,
 #endif /* CONFIG_DRIVER_NDISWRAPPER */
Index: ms_funcs.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/ms_funcs.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/ms_funcs.c -L contrib/wpa_supplicant/ms_funcs.c -u -r1.2 -r1.3
--- contrib/wpa_supplicant/ms_funcs.c
+++ contrib/wpa_supplicant/ms_funcs.c
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant / shared MSCHAPV2 helper functions / RFC 2433 / RFC 2759
- * Copyright (c) 2004-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2004-2006, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -12,9 +12,7 @@
  * See README and COPYING for more details.
  */
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
+#include "includes.h"
 
 #include "common.h"
 #include "sha1.h"
@@ -26,7 +24,7 @@
 /**
  * challenge_hash - ChallengeHash() - RFC 2759, Sect. 8.2
  * @peer_challenge: 16-octet PeerChallenge (IN)
- * @auth_challenge: 16-octet AuthChallenge (IN)
+ * @auth_challenge: 16-octet AuthenticatorChallenge (IN)
  * @username: 0-to-256-char UserName (IN)
  * @username_len: Length of username
  * @challenge: 8-octet Challenge (OUT)
@@ -47,41 +45,41 @@
 	len[2] = username_len;
 
 	sha1_vector(3, addr, len, hash);
-	memcpy(challenge, hash, 8);
+	os_memcpy(challenge, hash, 8);
 }
 
 
 /**
  * nt_password_hash - NtPasswordHash() - RFC 2759, Sect. 8.3
- * @password: 0-to-256-unicode-char Password (IN)
+ * @password: 0-to-256-unicode-char Password (IN; ASCII)
  * @password_len: Length of password
  * @password_hash: 16-octet PasswordHash (OUT)
  */
 void nt_password_hash(const u8 *password, size_t password_len,
 		      u8 *password_hash)
 {
-	u8 *buf;
-	int i;
-	size_t len;
+	u8 buf[512], *pos;
+	size_t i, len;
 
-	/* Convert password into unicode */
-	buf = malloc(password_len * 2);
-	if (buf == NULL)
+	if (password_len > 256)
 		return;
-	memset(buf, 0, password_len * 2);
-	for (i = 0; i < password_len; i++)
+
+	/* Convert password into unicode */
+	for (i = 0; i < password_len; i++) {
 		buf[2 * i] = password[i];
+		buf[2 * i + 1] = 0;
+	}
 
 	len = password_len * 2;
-	md4_vector(1, (const u8 **) &buf, &len, password_hash);
-	free(buf);
+	pos = buf;
+	md4_vector(1, (const u8 **) &pos, &len, password_hash);
 }
 
 
 /**
  * hash_nt_password_hash - HashNtPasswordHash() - RFC 2759, Sect. 8.4
  * @password_hash: 16-octet PasswordHash (IN)
- * @password_hash_hash: 16-octet PaswordHashHash (OUT)
+ * @password_hash_hash: 16-octet PasswordHashHash (OUT)
  */
 void hash_nt_password_hash(const u8 *password_hash, u8 *password_hash_hash)
 {
@@ -104,7 +102,7 @@
 	des_encrypt(challenge, password_hash + 7, response + 8);
 	zpwd[0] = password_hash[14];
 	zpwd[1] = password_hash[15];
-	memset(zpwd + 2, 0, 5);
+	os_memset(zpwd + 2, 0, 5);
 	des_encrypt(challenge, zpwd, response + 16);
 }
 
@@ -115,7 +113,7 @@
  * @peer_hallenge: 16-octet PeerChallenge (IN)
  * @username: 0-to-256-char UserName (IN)
  * @username_len: Length of username
- * @password: 0-to-256-unicode-char Password (IN)
+ * @password: 0-to-256-unicode-char Password (IN; ASCII)
  * @password_len: Length of password
  * @response: 24-octet Response (OUT)
  */
@@ -135,21 +133,44 @@
 
 
 /**
- * generate_authenticator_response - GenerateAuthenticatorResponse() - RFC 2759, Sect. 8.7
- * @password: 0-to-256-unicode-char Password (IN)
- * @password_len: Length of password
+ * generate_nt_response_pwhash - GenerateNTResponse() - RFC 2759, Sect. 8.1
+ * @auth_challenge: 16-octet AuthenticatorChallenge (IN)
+ * @peer_hallenge: 16-octet PeerChallenge (IN)
+ * @username: 0-to-256-char UserName (IN)
+ * @username_len: Length of username
+ * @password_hash: 16-octet PasswordHash (IN)
+ * @response: 24-octet Response (OUT)
+ */
+void generate_nt_response_pwhash(const u8 *auth_challenge,
+				 const u8 *peer_challenge,
+				 const u8 *username, size_t username_len,
+				 const u8 *password_hash,
+				 u8 *response)
+{
+	u8 challenge[8];
+
+	challenge_hash(peer_challenge, auth_challenge, username, username_len,
+		       challenge);
+	challenge_response(challenge, password_hash, response);
+}
+
+
+/**
+ * generate_authenticator_response_pwhash - GenerateAuthenticatorResponse() - RFC 2759, Sect. 8.7
+ * @password_hash: 16-octet PasswordHash (IN)
  * @nt_response: 24-octet NT-Response (IN)
  * @peer_challenge: 16-octet PeerChallenge (IN)
  * @auth_challenge: 16-octet AuthenticatorChallenge (IN)
  * @username: 0-to-256-char UserName (IN)
  * @username_len: Length of username
- * @response: 42-octet AuthenticatorResponse (OUT)
+ * @response: 20-octet AuthenticatorResponse (OUT) (note: this value is usually
+ * encoded as a 42-octet ASCII string (S=<hexdump of response>)
  */
-void generate_authenticator_response(const u8 *password, size_t password_len,
-				     const u8 *peer_challenge,
-				     const u8 *auth_challenge,
-				     const u8 *username, size_t username_len,
-				     const u8 *nt_response, u8 *response)
+void generate_authenticator_response_pwhash(
+	const u8 *password_hash,
+	const u8 *peer_challenge, const u8 *auth_challenge,
+	const u8 *username, size_t username_len,
+	const u8 *nt_response, u8 *response)
 {
 	static const u8 magic1[39] = {
 		0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76,
@@ -165,7 +186,7 @@
 		0x6E
 	};
 
-	u8 password_hash[16], password_hash_hash[16], challenge[8];
+	u8 password_hash_hash[16], challenge[8];
 	const unsigned char *addr1[3];
 	const size_t len1[3] = { 16, 24, sizeof(magic1) };
 	const unsigned char *addr2[3];
@@ -179,7 +200,6 @@
 	addr2[1] = challenge;
 	addr2[2] = magic2;
 
-	nt_password_hash(password, password_len, password_hash);
 	hash_nt_password_hash(password_hash, password_hash_hash);
 	sha1_vector(3, addr1, len1, response);
 
@@ -190,9 +210,36 @@
 
 
 /**
+ * generate_authenticator_response - GenerateAuthenticatorResponse() - RFC 2759, Sect. 8.7
+ * @password: 0-to-256-unicode-char Password (IN; ASCII)
+ * @password_len: Length of password
+ * @nt_response: 24-octet NT-Response (IN)
+ * @peer_challenge: 16-octet PeerChallenge (IN)
+ * @auth_challenge: 16-octet AuthenticatorChallenge (IN)
+ * @username: 0-to-256-char UserName (IN)
+ * @username_len: Length of username
+ * @response: 20-octet AuthenticatorResponse (OUT) (note: this value is usually
+ * encoded as a 42-octet ASCII string (S=<hexdump of response>)
+ */
+void generate_authenticator_response(const u8 *password, size_t password_len,
+				     const u8 *peer_challenge,
+				     const u8 *auth_challenge,
+				     const u8 *username, size_t username_len,
+				     const u8 *nt_response, u8 *response)
+{
+	u8 password_hash[16];
+	nt_password_hash(password, password_len, password_hash);
+	generate_authenticator_response_pwhash(password_hash,
+					       peer_challenge, auth_challenge,
+					       username, username_len,
+					       nt_response, response);
+}
+
+
+/**
  * nt_challenge_response - NtChallengeResponse() - RFC 2433, Sect. A.5
  * @challenge: 8-octet Challenge (IN)
- * @password: 0-to-256-unicode-char Password (IN)
+ * @password: 0-to-256-unicode-char Password (IN; ASCII)
  * @password_len: Length of password
  * @response: 24-octet Response (OUT)
  */
@@ -228,7 +275,7 @@
 	addr[2] = magic1;
 
 	sha1_vector(3, addr, len, hash);
-	memcpy(master_key, hash, 16);
+	os_memcpy(master_key, hash, 16);
 }
 
 
@@ -236,7 +283,7 @@
  * get_asymetric_start_key - GetAsymetricStartKey() - RFC 3079, Sect. 3.4
  * @master_key: 16-octet MasterKey (IN)
  * @session_key: 8-to-16 octet SessionKey (OUT)
- * @session_key_len: SessionKeyLength (Length of session_key)
+ * @session_key_len: SessionKeyLength (Length of session_key) (IN)
  * @is_send: IsSend (IN, BOOLEAN)
  * @is_server: IsServer (IN, BOOLEAN)
  */
@@ -296,15 +343,15 @@
 
 	if (session_key_len > SHA1_MAC_LEN)
 		session_key_len = SHA1_MAC_LEN;
-	memcpy(session_key, digest, session_key_len);
+	os_memcpy(session_key, digest, session_key_len);
 }
 
 
 #define PWBLOCK_LEN 516
 
 /**
- * encrypt_pw_block_with_password_hash - EncryptPwBlobkWithPasswordHash() - RFC 2759, Sect. 8.10
- * @password: 0-to-256-unicode-char Password (IN)
+ * encrypt_pw_block_with_password_hash - EncryptPwBlockWithPasswordHash() - RFC 2759, Sect. 8.10
+ * @password: 0-to-256-unicode-char Password (IN; ASCII)
  * @password_len: Length of password
  * @password_hash: 16-octet PasswordHash (IN)
  * @pw_block: 516-byte PwBlock (OUT)
@@ -319,10 +366,15 @@
 	if (password_len > 256)
 		return;
 
-	memset(pw_block, 0, PWBLOCK_LEN);
+	os_memset(pw_block, 0, PWBLOCK_LEN);
 	offset = (256 - password_len) * 2;
+	os_get_random(pw_block, offset);
 	for (i = 0; i < password_len; i++)
 		pw_block[offset + i * 2] = password[i];
+	/*
+	 * PasswordLength is 4 octets, but since the maximum password length is
+	 * 256, only first two (in little endian byte order) can be non-zero.
+	 */
 	pos = &pw_block[2 * 256];
 	WPA_PUT_LE16(pos, password_len * 2);
 	rc4(pw_block, PWBLOCK_LEN, password_hash, 16);
@@ -331,9 +383,9 @@
 
 /**
  * new_password_encrypted_with_old_nt_password_hash - NewPasswordEncryptedWithOldNtPasswordHash() - RFC 2759, Sect. 8.9
- * @new_password: 0-to-256-unicode-char NewPassword (IN)
+ * @new_password: 0-to-256-unicode-char NewPassword (IN; ASCII)
  * @new_password_len: Length of new_password
- * @old_password: 0-to-256-unicode-char OldPassword (IN)
+ * @old_password: 0-to-256-unicode-char OldPassword (IN; ASCII)
  * @old_password_len: Length of old_password
  * @encrypted_pw_block: 516-octet EncryptedPwBlock (OUT)
  */
@@ -367,9 +419,9 @@
 
 /**
  * old_nt_password_hash_encrypted_with_new_nt_password_hash - OldNtPasswordHashEncryptedWithNewNtPasswordHash() - RFC 2759, Sect. 8.12
- * @new_password: 0-to-256-unicode-char NewPassword (IN)
+ * @new_password: 0-to-256-unicode-char NewPassword (IN; ASCII)
  * @new_password_len: Length of new_password
- * @old_password: 0-to-256-unicode-char OldPassword (IN)
+ * @old_password: 0-to-256-unicode-char OldPassword (IN; ASCII)
  * @old_password_len: Length of old_password
  * @encrypted_password_ash: 16-octet EncryptedPasswordHash (OUT)
  */
@@ -386,112 +438,3 @@
 					      new_password_hash,
 					      encrypted_password_hash);
 }
-
-
-#ifdef TEST_MAIN_MS_FUNCS
-
-#include "rc4.c"
-
-int main(int argc, char *argv[])
-{
-	/* Test vector from RFC2759 example */
-	u8 *username = "User";
-	u8 *password = "clientPass";
-	u8 auth_challenge[] = {
-		0x5B, 0x5D, 0x7C, 0x7D, 0x7B, 0x3F, 0x2F, 0x3E,
-		0x3C, 0x2C, 0x60, 0x21, 0x32, 0x26, 0x26, 0x28
-	};
-	u8 peer_challenge[] = {
-		0x21, 0x40, 0x23, 0x24, 0x25, 0x5E, 0x26, 0x2A,
-		0x28, 0x29, 0x5F, 0x2B, 0x3A, 0x33, 0x7C, 0x7E
-	};
-	u8 challenge[] = { 0xD0, 0x2E, 0x43, 0x86, 0xBC, 0xE9, 0x12, 0x26 };
-	u8 password_hash[] = {
-		0x44, 0xEB, 0xBA, 0x8D, 0x53, 0x12, 0xB8, 0xD6,
-		0x11, 0x47, 0x44, 0x11, 0xF5, 0x69, 0x89, 0xAE
-	};
-	u8 nt_response[] = {
-		0x82, 0x30, 0x9E, 0xCD, 0x8D, 0x70, 0x8B, 0x5E,
-		0xA0, 0x8F, 0xAA, 0x39, 0x81, 0xCD, 0x83, 0x54,
-		0x42, 0x33, 0x11, 0x4A, 0x3D, 0x85, 0xD6, 0xDF
-	};
-	u8 password_hash_hash[] = {
-		0x41, 0xC0, 0x0C, 0x58, 0x4B, 0xD2, 0xD9, 0x1C,
-		0x40, 0x17, 0xA2, 0xA1, 0x2F, 0xA5, 0x9F, 0x3F
-	};
-	u8 authenticator_response[] = {
-		0x40, 0x7A, 0x55, 0x89, 0x11, 0x5F, 0xD0, 0xD6,
-		0x20, 0x9F, 0x51, 0x0F, 0xE9, 0xC0, 0x45, 0x66,
-		0x93, 0x2C, 0xDA, 0x56
-	};
-	u8 master_key[] = {
-		0xFD, 0xEC, 0xE3, 0x71, 0x7A, 0x8C, 0x83, 0x8C,
-		0xB3, 0x88, 0xE5, 0x27, 0xAE, 0x3C, 0xDD, 0x31
-	};
-	u8 send_start_key[] = {
-		0x8B, 0x7C, 0xDC, 0x14, 0x9B, 0x99, 0x3A, 0x1B,
-		0xA1, 0x18, 0xCB, 0x15, 0x3F, 0x56, 0xDC, 0xCB
-	};
-	u8 buf[32];
-
-	int errors = 0;
-
-	printf("Testing ms_funcs.c\n");
-
-	challenge_hash(peer_challenge, auth_challenge,
-		       username, strlen(username),
-		       buf);
-	if (memcmp(challenge, buf, sizeof(challenge)) != 0) {
-		printf("challenge_hash failed\n");
-		errors++;
-	}
-
-	nt_password_hash(password, strlen(password), buf);
-	if (memcmp(password_hash, buf, sizeof(password_hash)) != 0) {
-		printf("nt_password_hash failed\n");
-		errors++;
-	}
-
-	generate_nt_response(auth_challenge, peer_challenge,
-			     username, strlen(username),
-			     password, strlen(password),
-			     buf);
-	if (memcmp(nt_response, buf, sizeof(nt_response)) != 0) {
-		printf("generate_nt_response failed\n");
-		errors++;
-	}
-
-	hash_nt_password_hash(password_hash, buf);
-	if (memcmp(password_hash_hash, buf, sizeof(password_hash_hash)) != 0) {
-		printf("hash_nt_password_hash failed\n");
-		errors++;
-	}
-
-	generate_authenticator_response(password, strlen(password),
-					peer_challenge, auth_challenge,
-					username, strlen(username),
-					nt_response, buf);
-	if (memcmp(authenticator_response, buf, sizeof(authenticator_response))
-	    != 0) {
-		printf("generate_authenticator_response failed\n");
-		errors++;
-	}
-
-	get_master_key(password_hash_hash, nt_response, buf);
-	if (memcmp(master_key, buf, sizeof(master_key)) != 0) {
-		printf("get_master_key failed\n");
-		errors++;
-	}
-
-	get_asymetric_start_key(master_key, buf, sizeof(send_start_key), 1, 1);
-	if (memcmp(send_start_key, buf, sizeof(send_start_key)) != 0) {
-		printf("get_asymetric_start_key failed\n");
-		errors++;
-	}
-
-	if (errors)
-		printf("FAILED! %d errors\n", errors);
-
-	return errors;
-}
-#endif /* TEST_MAIN_MS_FUNCS */
Index: aes_wrap.h
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/aes_wrap.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/aes_wrap.h -L contrib/wpa_supplicant/aes_wrap.h -u -r1.2 -r1.3
--- contrib/wpa_supplicant/aes_wrap.h
+++ contrib/wpa_supplicant/aes_wrap.h
@@ -7,7 +7,7 @@
  * - AES-128 EAX mode encryption/decryption
  * - AES-128 CBC
  *
- * Copyright (c) 2003-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * Copyright (c) 2003-2005, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
Index: eap_aka.c
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/eap_aka.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/eap_aka.c -L contrib/wpa_supplicant/eap_aka.c -u -r1.2 -r1.3
--- contrib/wpa_supplicant/eap_aka.c
+++ contrib/wpa_supplicant/eap_aka.c
@@ -1,6 +1,6 @@
 /*
- * WPA Supplicant / EAP-AKA (draft-arkko-pppext-eap-aka-12.txt)
- * Copyright (c) 2004-2005, Jouni Malinen <jkmaline at cc.hut.fi>
+ * EAP peer method: EAP-AKA (RFC 4187)
+ * Copyright (c) 2004-2006, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -12,46 +12,26 @@
  * See README and COPYING for more details.
  */
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
+#include "includes.h"
 
 #include "common.h"
 #include "eap_i.h"
-#include "wpa_supplicant.h"
-#include "config_ssid.h"
 #include "crypto.h"
 #include "pcsc_funcs.h"
 #include "eap_sim_common.h"
 
-/* EAP-AKA Subtypes */
-#define EAP_AKA_SUBTYPE_CHALLENGE 1
-#define EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT 2
-#define EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE 4
-#define EAP_AKA_SUBTYPE_IDENTITY 5
-#define EAP_AKA_SUBTYPE_NOTIFICATION 12
-#define EAP_AKA_SUBTYPE_REAUTHENTICATION 13
-#define EAP_AKA_SUBTYPE_CLIENT_ERROR 14
-
-/* AT_CLIENT_ERROR_CODE error codes */
-#define EAP_AKA_UNABLE_TO_PROCESS_PACKET 0
-
-#define AKA_AUTS_LEN 14
-#define RES_MAX_LEN 16
-#define IK_LEN 16
-#define CK_LEN 16
-#define EAP_AKA_MAX_FAST_REAUTHS 1000
 
 struct eap_aka_data {
-	u8 ik[IK_LEN], ck[CK_LEN], res[RES_MAX_LEN];
+	u8 ik[EAP_AKA_IK_LEN], ck[EAP_AKA_CK_LEN], res[EAP_AKA_RES_MAX_LEN];
 	size_t res_len;
 	u8 nonce_s[EAP_SIM_NONCE_S_LEN];
 	u8 mk[EAP_SIM_MK_LEN];
 	u8 k_aut[EAP_SIM_K_AUT_LEN];
 	u8 k_encr[EAP_SIM_K_ENCR_LEN];
 	u8 msk[EAP_SIM_KEYING_DATA_LEN];
-	u8 rand[AKA_RAND_LEN], autn[AKA_AUTN_LEN];
-	u8 auts[AKA_AUTS_LEN];
+	u8 emsk[EAP_EMSK_LEN];
+	u8 rand[EAP_AKA_RAND_LEN], autn[EAP_AKA_AUTN_LEN];
+	u8 auts[EAP_AKA_AUTS_LEN];
 
 	int num_id_req, num_notification;
 	u8 *pseudonym;
@@ -69,10 +49,9 @@
 static void * eap_aka_init(struct eap_sm *sm)
 {
 	struct eap_aka_data *data;
-	data = malloc(sizeof(*data));
+	data = os_zalloc(sizeof(*data));
 	if (data == NULL)
 		return NULL;
-	memset(data, 0, sizeof(*data));
 
 	data->state = CONTINUE;
 
@@ -84,10 +63,10 @@
 {
 	struct eap_aka_data *data = priv;
 	if (data) {
-		free(data->pseudonym);
-		free(data->reauth_id);
-		free(data->last_eap_identity);
-		free(data);
+		os_free(data->pseudonym);
+		os_free(data->reauth_id);
+		os_free(data->last_eap_identity);
+		os_free(data);
 	}
 }
 
@@ -102,45 +81,34 @@
 #else /* PCSC_FUNCS */
 	/* These hardcoded Kc and SRES values are used for testing.
 	 * Could consider making them configurable. */
-	memset(data->res, '2', RES_MAX_LEN);
-	data->res_len = 16;
-	memset(data->ik, '3', IK_LEN);
-	memset(data->ck, '4', CK_LEN);
+	os_memset(data->res, '2', EAP_AKA_RES_MAX_LEN);
+	data->res_len = EAP_AKA_RES_MAX_LEN;
+	os_memset(data->ik, '3', EAP_AKA_IK_LEN);
+	os_memset(data->ck, '4', EAP_AKA_CK_LEN);
 	{
-		u8 autn[AKA_AUTN_LEN];
-		memset(autn, '1', AKA_AUTN_LEN);
-		if (memcmp(autn, data->autn, AKA_AUTN_LEN) != 0) {
+		u8 autn[EAP_AKA_AUTN_LEN];
+		os_memset(autn, '1', EAP_AKA_AUTN_LEN);
+		if (os_memcmp(autn, data->autn, EAP_AKA_AUTN_LEN) != 0) {
 			wpa_printf(MSG_WARNING, "EAP-AKA: AUTN did not match "
 				   "with expected value");
 			return -1;
 		}
 	}
+#if 0
+	{
+		static int test_resync = 1;
+		if (test_resync) {
+			/* Test Resynchronization */
+			test_resync = 0;
+			return -2;
+		}
+	}
+#endif
 	return 0;
 #endif /* PCSC_FUNCS */
 }
 
 
-static void eap_aka_derive_mk(struct eap_aka_data *data,
-			      const u8 *identity, size_t identity_len)
-{
-	const u8 *addr[3];
-	size_t len[3];
-
-	addr[0] = identity;
-	len[0] = identity_len;
-	addr[1] = data->ik;
-	len[1] = IK_LEN;
-	addr[2] = data->ck;
-	len[2] = CK_LEN;
-
-	/* MK = SHA1(Identity|IK|CK) */
-	sha1_vector(3, addr, len, data->mk);
-	wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: IK", data->ik, IK_LEN);
-	wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: CK", data->ck, CK_LEN);
-	wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: MK", data->mk, EAP_SIM_MK_LEN);
-}
-
-
 #define CLEAR_PSEUDONYM	0x01
 #define CLEAR_REAUTH_ID	0x02
 #define CLEAR_EAP_ID	0x04
@@ -152,17 +120,17 @@
 		   id & CLEAR_REAUTH_ID ? " reauth_id" : "",
 		   id & CLEAR_EAP_ID ? " eap_id" : "");
 	if (id & CLEAR_PSEUDONYM) {
-		free(data->pseudonym);
+		os_free(data->pseudonym);
 		data->pseudonym = NULL;
 		data->pseudonym_len = 0;
 	}
 	if (id & CLEAR_REAUTH_ID) {
-		free(data->reauth_id);
+		os_free(data->reauth_id);
 		data->reauth_id = NULL;
 		data->reauth_id_len = 0;
 	}
 	if (id & CLEAR_EAP_ID) {
-		free(data->last_eap_identity);
+		os_free(data->last_eap_identity);
 		data->last_eap_identity = NULL;
 		data->last_eap_identity_len = 0;
 	}
@@ -173,15 +141,15 @@
 			     struct eap_sim_attrs *attr)
 {
 	if (attr->next_pseudonym) {
-		free(data->pseudonym);
-		data->pseudonym = malloc(attr->next_pseudonym_len);
+		os_free(data->pseudonym);
+		data->pseudonym = os_malloc(attr->next_pseudonym_len);
 		if (data->pseudonym == NULL) {
 			wpa_printf(MSG_INFO, "EAP-AKA: (encr) No memory for "
 				   "next pseudonym");
 			return -1;
 		}
-		memcpy(data->pseudonym, attr->next_pseudonym,
-		       attr->next_pseudonym_len);
+		os_memcpy(data->pseudonym, attr->next_pseudonym,
+			  attr->next_pseudonym_len);
 		data->pseudonym_len = attr->next_pseudonym_len;
 		wpa_hexdump_ascii(MSG_DEBUG,
 				  "EAP-AKA: (encr) AT_NEXT_PSEUDONYM",
@@ -190,15 +158,15 @@
 	}
 
 	if (attr->next_reauth_id) {
-		free(data->reauth_id);
-		data->reauth_id = malloc(attr->next_reauth_id_len);
+		os_free(data->reauth_id);
+		data->reauth_id = os_malloc(attr->next_reauth_id_len);
 		if (data->reauth_id == NULL) {
 			wpa_printf(MSG_INFO, "EAP-AKA: (encr) No memory for "
 				   "next reauth_id");
 			return -1;
 		}
-		memcpy(data->reauth_id, attr->next_reauth_id,
-		       attr->next_reauth_id_len);
+		os_memcpy(data->reauth_id, attr->next_reauth_id,
+			  attr->next_reauth_id_len);
 		data->reauth_id_len = attr->next_reauth_id_len;
 		wpa_hexdump_ascii(MSG_DEBUG,
 				  "EAP-AKA: (encr) AT_NEXT_REAUTH_ID",
@@ -210,7 +178,7 @@
 }
 
 
-static u8 * eap_aka_client_error(struct eap_sm *sm, struct eap_aka_data *data,
+static u8 * eap_aka_client_error(struct eap_aka_data *data,
 				 const struct eap_hdr *req,
 				 size_t *respDataLen, int err)
 {
@@ -227,8 +195,7 @@
 }
 
 
-static u8 * eap_aka_authentication_reject(struct eap_sm *sm,
-					  struct eap_aka_data *data,
+static u8 * eap_aka_authentication_reject(struct eap_aka_data *data,
 					  const struct eap_hdr *req,
 					  size_t *respDataLen)
 {
@@ -247,14 +214,12 @@
 }
 
 
-static u8 * eap_aka_synchronization_failure(struct eap_sm *sm,
-					    struct eap_aka_data *data,
+static u8 * eap_aka_synchronization_failure(struct eap_aka_data *data,
 					    const struct eap_hdr *req,
 					    size_t *respDataLen)
 {
 	struct eap_sim_msg *msg;
 
-	data->state = FAILURE;
 	data->num_id_req = 0;
 	data->num_notification = 0;
 
@@ -264,7 +229,8 @@
 			       EAP_TYPE_AKA,
 			       EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE);
 	wpa_printf(MSG_DEBUG, "   AT_AUTS");
-	eap_sim_msg_add_full(msg, EAP_SIM_AT_AUTS, data->auts, AKA_AUTS_LEN);
+	eap_sim_msg_add_full(msg, EAP_SIM_AT_AUTS, data->auts,
+			     EAP_AKA_AUTS_LEN);
 	return eap_sim_msg_finish(msg, respDataLen, NULL, NULL, 0);
 }
 
@@ -275,8 +241,7 @@
 				      size_t *respDataLen,
 				      enum eap_sim_id_req id_req)
 {
-	struct wpa_ssid *config = eap_get_config(sm);
-	u8 *identity = NULL;
+	const u8 *identity = NULL;
 	size_t identity_len = 0;
 	struct eap_sim_msg *msg;
 
@@ -290,11 +255,12 @@
 		identity = data->pseudonym;
 		identity_len = data->pseudonym_len;
 		eap_aka_clear_identities(data, CLEAR_REAUTH_ID);
-	} else if (id_req != NO_ID_REQ && config && config->identity) {
-		identity = config->identity;
-		identity_len = config->identity_len;
-		eap_aka_clear_identities(data,
-					 CLEAR_PSEUDONYM | CLEAR_REAUTH_ID);
+	} else if (id_req != NO_ID_REQ) {
+		identity = eap_get_config_identity(sm, &identity_len);
+		if (identity) {
+			eap_aka_clear_identities(data, CLEAR_PSEUDONYM |
+						 CLEAR_REAUTH_ID);
+		}
 	}
 	if (id_req != NO_ID_REQ)
 		eap_aka_clear_identities(data, CLEAR_EAP_ID);
@@ -315,8 +281,7 @@
 }
 
 
-static u8 * eap_aka_response_challenge(struct eap_sm *sm,
-				       struct eap_aka_data *data,
+static u8 * eap_aka_response_challenge(struct eap_aka_data *data,
 				       const struct eap_hdr *req,
 				       size_t *respDataLen)
 {
@@ -335,10 +300,10 @@
 }
 
 
-static u8 * eap_aka_response_reauth(struct eap_sm *sm,
-				    struct eap_aka_data *data,
+static u8 * eap_aka_response_reauth(struct eap_aka_data *data,
 				    const struct eap_hdr *req,
-				    size_t *respDataLen, int counter_too_small)
+				    size_t *respDataLen, int counter_too_small,
+				    const u8 *nonce_s)
 {
 	struct eap_sim_msg *msg;
 	unsigned int counter;
@@ -370,13 +335,12 @@
 	}
 	wpa_printf(MSG_DEBUG, "   AT_MAC");
 	eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
-	return eap_sim_msg_finish(msg, respDataLen, data->k_aut, data->nonce_s,
+	return eap_sim_msg_finish(msg, respDataLen, data->k_aut, nonce_s,
 				  EAP_SIM_NONCE_S_LEN);
 }
 
 
-static u8 * eap_aka_response_notification(struct eap_sm *sm,
-					  struct eap_aka_data *data,
+static u8 * eap_aka_response_notification(struct eap_aka_data *data,
 					  const struct eap_hdr *req,
 					  size_t *respDataLen,
 					  u16 notification)
@@ -388,8 +352,6 @@
 		   req->identifier);
 	msg = eap_sim_msg_init(EAP_CODE_RESPONSE, req->identifier,
 			       EAP_TYPE_AKA, EAP_AKA_SUBTYPE_NOTIFICATION);
-	wpa_printf(MSG_DEBUG, "   AT_NOTIFICATION");
-	eap_sim_msg_add(msg, EAP_SIM_AT_NOTIFICATION, notification, NULL, 0);
 	if (k_aut && data->reauth) {
 		wpa_printf(MSG_DEBUG, "   AT_IV");
 		wpa_printf(MSG_DEBUG, "   AT_ENCR_DATA");
@@ -417,7 +379,6 @@
 static u8 * eap_aka_process_identity(struct eap_sm *sm,
 				     struct eap_aka_data *data,
 				     const struct eap_hdr *req,
-				     size_t reqDataLen,
 				     size_t *respDataLen,
 				     struct eap_sim_attrs *attr)
 {
@@ -448,7 +409,7 @@
 	if (id_error) {
 		wpa_printf(MSG_INFO, "EAP-AKA: Too many ID requests "
 			   "used within one authentication");
-		return eap_aka_client_error(sm, data, req, respDataLen,
+		return eap_aka_client_error(data, req, respDataLen,
 					    EAP_AKA_UNABLE_TO_PROCESS_PACKET);
 	}
 
@@ -464,8 +425,7 @@
 				      size_t *respDataLen,
 				      struct eap_sim_attrs *attr)
 {
-	struct wpa_ssid *config = eap_get_config(sm);
-	u8 *identity;
+	const u8 *identity;
 	size_t identity_len;
 	int res;
 	struct eap_sim_attrs eattr;
@@ -478,26 +438,24 @@
 			   !attr->mac ? " AT_MAC" : "",
 			   !attr->rand ? " AT_RAND" : "",
 			   !attr->autn ? " AT_AUTN" : "");
-		return eap_aka_client_error(sm, data, req, respDataLen,
+		return eap_aka_client_error(data, req, respDataLen,
 					    EAP_AKA_UNABLE_TO_PROCESS_PACKET);
 	}
-	memcpy(data->rand, attr->rand, AKA_RAND_LEN);
-	memcpy(data->autn, attr->autn, AKA_AUTN_LEN);
+	os_memcpy(data->rand, attr->rand, EAP_AKA_RAND_LEN);
+	os_memcpy(data->autn, attr->autn, EAP_AKA_AUTN_LEN);
 
 	res = eap_aka_umts_auth(sm, data);
 	if (res == -1) {
 		wpa_printf(MSG_WARNING, "EAP-AKA: UMTS authentication "
 			   "failed (AUTN)");
-		return eap_aka_authentication_reject(sm, data, req,
-						     respDataLen);
+		return eap_aka_authentication_reject(data, req, respDataLen);
 	} else if (res == -2) {
 		wpa_printf(MSG_WARNING, "EAP-AKA: UMTS authentication "
 			   "failed (AUTN seq# -> AUTS)");
-		return eap_aka_synchronization_failure(sm, data, req,
-						       respDataLen);
+		return eap_aka_synchronization_failure(data, req, respDataLen);
 	} else if (res) {
 		wpa_printf(MSG_WARNING, "EAP-AKA: UMTS authentication failed");
-		return eap_aka_client_error(sm, data, req, respDataLen,
+		return eap_aka_client_error(data, req, respDataLen,
 					    EAP_AKA_UNABLE_TO_PROCESS_PACKET);
 	}
 	if (data->last_eap_identity) {
@@ -506,19 +464,19 @@
 	} else if (data->pseudonym) {
 		identity = data->pseudonym;
 		identity_len = data->pseudonym_len;
-	} else {
-		identity = config->identity;
-		identity_len = config->identity_len;
-	}
+	} else
+		identity = eap_get_config_identity(sm, &identity_len);
 	wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Selected identity for MK "
 			  "derivation", identity, identity_len);
-	eap_aka_derive_mk(data, identity, identity_len);
-	eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk);
+	eap_aka_derive_mk(identity, identity_len, data->ik, data->ck,
+			  data->mk);
+	eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk,
+			    data->emsk);
 	if (eap_sim_verify_mac(data->k_aut, (const u8 *) req, reqDataLen,
 			       attr->mac, (u8 *) "", 0)) {
 		wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message "
 			   "used invalid AT_MAC");
-		return eap_aka_client_error(sm, data, req, respDataLen,
+		return eap_aka_client_error(data, req, respDataLen,
 					    EAP_AKA_UNABLE_TO_PROCESS_PACKET);
 	}
 
@@ -535,11 +493,11 @@
 					       &eattr, 0);
 		if (decrypted == NULL) {
 			return eap_aka_client_error(
-				sm, data, req, respDataLen,
+				data, req, respDataLen,
 				EAP_AKA_UNABLE_TO_PROCESS_PACKET);
 		}
 		eap_aka_learn_ids(data, &eattr);
-		free(decrypted);
+		os_free(decrypted);
 	}
 
 	if (data->state != FAILURE)
@@ -547,17 +505,15 @@
 
 	data->num_id_req = 0;
 	data->num_notification = 0;
-	/* draft-arkko-pppext-eap-aka-12.txt specifies that counter
-	 * is initialized to one after fullauth, but initializing it to
-	 * zero makes it easier to implement reauth verification. */
+	/* RFC 4187 specifies that counter is initialized to one after
+	 * fullauth, but initializing it to zero makes it easier to implement
+	 * reauth verification. */
 	data->counter = 0;
-	return eap_aka_response_challenge(sm, data, req, respDataLen);
+	return eap_aka_response_challenge(data, req, respDataLen);
 }
 
 
 static int eap_aka_process_notification_reauth(struct eap_aka_data *data,
-					       const struct eap_hdr *req,
-					       size_t reqDataLen,
 					       struct eap_sim_attrs *attr)
 {
 	struct eap_sim_attrs eattr;
@@ -578,15 +534,15 @@
 		return -1;
 	}
 
-	if (eattr.counter != data->counter) {
+	if (eattr.counter < 0 || (size_t) eattr.counter != data->counter) {
 		wpa_printf(MSG_WARNING, "EAP-AKA: Counter in notification "
 			   "message does not match with counter in reauth "
 			   "message");
-		free(decrypted);
+		os_free(decrypted);
 		return -1;
 	}
 
-	free(decrypted);
+	os_free(decrypted);
 	return 0;
 }
 
@@ -610,7 +566,7 @@
 	}
 
 	if (data->reauth &&
-	    eap_aka_process_notification_reauth(data, req, reqDataLen, attr)) {
+	    eap_aka_process_notification_reauth(data, attr)) {
 		wpa_printf(MSG_WARNING, "EAP-AKA: Invalid notification "
 			   "message after reauth");
 		return -1;
@@ -631,20 +587,20 @@
 	if (data->num_notification > 0) {
 		wpa_printf(MSG_INFO, "EAP-AKA: too many notification "
 			   "rounds (only one allowed)");
-		return eap_aka_client_error(sm, data, req, respDataLen,
+		return eap_aka_client_error(data, req, respDataLen,
 					    EAP_AKA_UNABLE_TO_PROCESS_PACKET);
 	}
 	data->num_notification++;
 	if (attr->notification == -1) {
 		wpa_printf(MSG_INFO, "EAP-AKA: no AT_NOTIFICATION in "
 			   "Notification message");
-		return eap_aka_client_error(sm, data, req, respDataLen,
+		return eap_aka_client_error(data, req, respDataLen,
 					    EAP_AKA_UNABLE_TO_PROCESS_PACKET);
 	}
 
 	if ((attr->notification & 0x4000) == 0 &&
 	    eap_aka_process_notification_auth(data, req, reqDataLen, attr)) {
-		return eap_aka_client_error(sm, data, req, respDataLen,
+		return eap_aka_client_error(data, req, respDataLen,
 					    EAP_AKA_UNABLE_TO_PROCESS_PACKET);
 	}
 
@@ -652,7 +608,7 @@
 	if (attr->notification >= 0 && attr->notification < 32768) {
 		data->state = FAILURE;
 	}
-	return eap_aka_response_notification(sm, data, req, respDataLen,
+	return eap_aka_response_notification(data, req, respDataLen,
 					     attr->notification);
 }
 
@@ -672,7 +628,7 @@
 	if (data->reauth_id == NULL) {
 		wpa_printf(MSG_WARNING, "EAP-AKA: Server is trying "
 			   "reauthentication, but no reauth_id available");
-		return eap_aka_client_error(sm, data, req, respDataLen,
+		return eap_aka_client_error(data, req, respDataLen,
 					    EAP_AKA_UNABLE_TO_PROCESS_PACKET);
 	}
 
@@ -681,14 +637,14 @@
 			       attr->mac, (u8 *) "", 0)) {
 		wpa_printf(MSG_WARNING, "EAP-AKA: Reauthentication "
 			   "did not have valid AT_MAC");
-		return eap_aka_client_error(sm, data, req, respDataLen,
+		return eap_aka_client_error(data, req, respDataLen,
 					    EAP_AKA_UNABLE_TO_PROCESS_PACKET);
 	}
 
 	if (attr->encr_data == NULL || attr->iv == NULL) {
 		wpa_printf(MSG_WARNING, "EAP-AKA: Reauthentication "
 			   "message did not include encrypted data");
-		return eap_aka_client_error(sm, data, req, respDataLen,
+		return eap_aka_client_error(data, req, respDataLen,
 					    EAP_AKA_UNABLE_TO_PROCESS_PACKET);
 	}
 
@@ -698,7 +654,7 @@
 	if (decrypted == NULL) {
 		wpa_printf(MSG_WARNING, "EAP-AKA: Failed to parse encrypted "
 			   "data from reauthentication message");
-		return eap_aka_client_error(sm, data, req, respDataLen,
+		return eap_aka_client_error(data, req, respDataLen,
 					    EAP_AKA_UNABLE_TO_PROCESS_PACKET);
 	}
 
@@ -706,37 +662,48 @@
 		wpa_printf(MSG_INFO, "EAP-AKA: (encr) No%s%s in reauth packet",
 			   !eattr.nonce_s ? " AT_NONCE_S" : "",
 			   eattr.counter < 0 ? " AT_COUNTER" : "");
-		free(decrypted);
-		return eap_aka_client_error(sm, data, req, respDataLen,
+		os_free(decrypted);
+		return eap_aka_client_error(data, req, respDataLen,
 					    EAP_AKA_UNABLE_TO_PROCESS_PACKET);
 	}
 
-	if (eattr.counter <= data->counter) {
+	if (eattr.counter < 0 || (size_t) eattr.counter <= data->counter) {
+		u8 *res;
 		wpa_printf(MSG_INFO, "EAP-AKA: (encr) Invalid counter "
 			   "(%d <= %d)", eattr.counter, data->counter);
 		data->counter_too_small = eattr.counter;
+
+		eap_sim_derive_keys_reauth(eattr.counter, data->reauth_id,
+					   data->reauth_id_len, eattr.nonce_s,
+					   data->mk, NULL, NULL);
+
 		/* Reply using Re-auth w/ AT_COUNTER_TOO_SMALL. The current
 		 * reauth_id must not be used to start a new reauthentication.
 		 * However, since it was used in the last EAP-Response-Identity
 		 * packet, it has to saved for the following fullauth to be
 		 * used in MK derivation. */
-		free(data->last_eap_identity);
+		os_free(data->last_eap_identity);
 		data->last_eap_identity = data->reauth_id;
 		data->last_eap_identity_len = data->reauth_id_len;
 		data->reauth_id = NULL;
 		data->reauth_id_len = 0;
-		free(decrypted);
-		return eap_aka_response_reauth(sm, data, req, respDataLen, 1);
+
+		res = eap_aka_response_reauth(data, req, respDataLen, 1,
+					      eattr.nonce_s);
+		os_free(decrypted);
+
+		return res;
 	}
 	data->counter = eattr.counter;
 
-	memcpy(data->nonce_s, eattr.nonce_s, EAP_SIM_NONCE_S_LEN);
+	os_memcpy(data->nonce_s, eattr.nonce_s, EAP_SIM_NONCE_S_LEN);
 	wpa_hexdump(MSG_DEBUG, "EAP-AKA: (encr) AT_NONCE_S",
 		    data->nonce_s, EAP_SIM_NONCE_S_LEN);
 
 	eap_sim_derive_keys_reauth(data->counter,
 				   data->reauth_id, data->reauth_id_len,
-				   data->nonce_s, data->mk, data->msk);
+				   data->nonce_s, data->mk, data->msk,
+				   data->emsk);
 	eap_aka_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID);
 	eap_aka_learn_ids(data, &eattr);
 
@@ -750,8 +717,9 @@
 			   "fast reauths performed - force fullauth");
 		eap_aka_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID);
 	}
-	free(decrypted);
-	return eap_aka_response_reauth(sm, data, req, respDataLen, 0);
+	os_free(decrypted);
+	return eap_aka_response_reauth(data, req, respDataLen, 0,
+				       data->nonce_s);
 }
 
 
@@ -761,7 +729,6 @@
 			    size_t *respDataLen)
 {
 	struct eap_aka_data *data = priv;
-	struct wpa_ssid *config = eap_get_config(sm);
 	const struct eap_hdr *req;
 	u8 subtype, *res;
 	const u8 *pos;
@@ -769,14 +736,15 @@
 	size_t len;
 
 	wpa_hexdump(MSG_DEBUG, "EAP-AKA: EAP data", reqData, reqDataLen);
-	if (config == NULL || config->identity == NULL) {
+	if (eap_get_config_identity(sm, &len) == NULL) {
 		wpa_printf(MSG_INFO, "EAP-AKA: Identity not configured");
-		eap_sm_request_identity(sm, config);
+		eap_sm_request_identity(sm);
 		ret->ignore = TRUE;
 		return NULL;
 	}
 
-	pos = eap_hdr_validate(EAP_TYPE_AKA, reqData, reqDataLen, &len);
+	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_AKA,
+			       reqData, reqDataLen, &len);
 	if (pos == NULL || len < 1) {
 		ret->ignore = TRUE;
 		return NULL;
@@ -794,14 +762,14 @@
 	pos += 2; /* Reserved */
 
 	if (eap_sim_parse_attr(pos, reqData + len, &attr, 1, 0)) {
-		res = eap_aka_client_error(sm, data, req, respDataLen,
+		res = eap_aka_client_error(data, req, respDataLen,
 					   EAP_AKA_UNABLE_TO_PROCESS_PACKET);
 		goto done;
 	}
 
 	switch (subtype) {
 	case EAP_AKA_SUBTYPE_IDENTITY:
-		res = eap_aka_process_identity(sm, data, req, len,
+		res = eap_aka_process_identity(sm, data, req,
 					       respDataLen, &attr);
 		break;
 	case EAP_AKA_SUBTYPE_CHALLENGE:
@@ -818,12 +786,12 @@
 		break;
 	case EAP_AKA_SUBTYPE_CLIENT_ERROR:
 		wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Client-Error");
-		res = eap_aka_client_error(sm, data, req, respDataLen,
+		res = eap_aka_client_error(data, req, respDataLen,
 					   EAP_AKA_UNABLE_TO_PROCESS_PACKET);
 		break;
 	default:
 		wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown subtype=%d", subtype);
-		res = eap_aka_client_error(sm, data, req, respDataLen,
+		res = eap_aka_client_error(data, req, respDataLen,
 					   EAP_AKA_UNABLE_TO_PROCESS_PACKET);
 		break;
 	}
@@ -834,7 +802,12 @@
 		ret->methodState = METHOD_DONE;
 	} else if (data->state == SUCCESS) {
 		ret->decision = DECISION_COND_SUCC;
-		ret->methodState = METHOD_DONE;
+		/*
+		 * It is possible for the server to reply with AKA
+		 * Notification, so we must allow the method to continue and
+		 * not only accept EAP-Success at this point.
+		 */
+		ret->methodState = METHOD_MAY_CONT;
 	}
 
 	if (ret->methodState == METHOD_DONE) {
@@ -903,28 +876,59 @@
 	if (data->state != SUCCESS)
 		return NULL;
 
-	key = malloc(EAP_SIM_KEYING_DATA_LEN);
+	key = os_malloc(EAP_SIM_KEYING_DATA_LEN);
 	if (key == NULL)
 		return NULL;
 
 	*len = EAP_SIM_KEYING_DATA_LEN;
-	memcpy(key, data->msk, EAP_SIM_KEYING_DATA_LEN);
+	os_memcpy(key, data->msk, EAP_SIM_KEYING_DATA_LEN);
 
 	return key;
 }
 
 
-const struct eap_method eap_method_aka =
+static u8 * eap_aka_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
 {
-	.method = EAP_TYPE_AKA,
-	.name = "AKA",
-	.init = eap_aka_init,
-	.deinit = eap_aka_deinit,
-	.process = eap_aka_process,
-	.isKeyAvailable = eap_aka_isKeyAvailable,
-	.getKey = eap_aka_getKey,
-	.has_reauth_data = eap_aka_has_reauth_data,
-	.deinit_for_reauth = eap_aka_deinit_for_reauth,
-	.init_for_reauth = eap_aka_init_for_reauth,
-	.get_identity = eap_aka_get_identity,
-};
+	struct eap_aka_data *data = priv;
+	u8 *key;
+
+	if (data->state != SUCCESS)
+		return NULL;
+
+	key = os_malloc(EAP_EMSK_LEN);
+	if (key == NULL)
+		return NULL;
+
+	*len = EAP_EMSK_LEN;
+	os_memcpy(key, data->emsk, EAP_EMSK_LEN);
+
+	return key;
+}
+
+
+int eap_peer_aka_register(void)
+{
+	struct eap_method *eap;
+	int ret;
+
+	eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
+				    EAP_VENDOR_IETF, EAP_TYPE_AKA, "AKA");
+	if (eap == NULL)
+		return -1;
+
+	eap->init = eap_aka_init;
+	eap->deinit = eap_aka_deinit;
+	eap->process = eap_aka_process;
+	eap->isKeyAvailable = eap_aka_isKeyAvailable;
+	eap->getKey = eap_aka_getKey;
+	eap->has_reauth_data = eap_aka_has_reauth_data;
+	eap->deinit_for_reauth = eap_aka_deinit_for_reauth;
+	eap->init_for_reauth = eap_aka_init_for_reauth;
+	eap->get_identity = eap_aka_get_identity;
+	eap->get_emsk = eap_aka_get_emsk;
+
+	ret = eap_peer_method_register(eap);
+	if (ret)
+		eap_peer_method_free(eap);
+	return ret;
+}
Index: radius.h
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/radius.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/wpa_supplicant/radius.h -L contrib/wpa_supplicant/radius.h -u -r1.2 -r1.3
--- contrib/wpa_supplicant/radius.h
+++ contrib/wpa_supplicant/radius.h
@@ -1,15 +1,33 @@
+/*
+ * hostapd / RADIUS message processing
+ * Copyright (c) 2002-2005, Jouni Malinen <j at w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
 #ifndef RADIUS_H
 #define RADIUS_H
 
 /* RFC 2865 - RADIUS */
 
+#ifdef _MSC_VER
+#pragma pack(push, 1)
+#endif /* _MSC_VER */
+
 struct radius_hdr {
 	u8 code;
 	u8 identifier;
 	u16 length; /* including this header */
 	u8 authenticator[16];
 	/* followed by length-20 octets of attributes */
-} __attribute__ ((packed));
+} STRUCT_PACKED;
 
 enum { RADIUS_CODE_ACCESS_REQUEST = 1,
        RADIUS_CODE_ACCESS_ACCEPT = 2,
@@ -26,7 +44,7 @@
 	u8 type;
 	u8 length; /* including this header */
 	/* followed by length-2 octets of attribute value */
-} __attribute__ ((packed));
+} STRUCT_PACKED;
 
 #define RADIUS_MAX_ATTR_LEN (255 - sizeof(struct radius_attr_hdr))
 
@@ -60,9 +78,12 @@
        RADIUS_ATTR_ACCT_OUTPUT_GIGAWORDS = 53,
        RADIUS_ATTR_EVENT_TIMESTAMP = 55,
        RADIUS_ATTR_NAS_PORT_TYPE = 61,
+       RADIUS_ATTR_TUNNEL_TYPE = 64,
+       RADIUS_ATTR_TUNNEL_MEDIUM_TYPE = 65,
        RADIUS_ATTR_CONNECT_INFO = 77,
        RADIUS_ATTR_EAP_MESSAGE = 79,
        RADIUS_ATTR_MESSAGE_AUTHENTICATOR = 80,
+       RADIUS_ATTR_TUNNEL_PRIVATE_GROUP_ID = 81,
        RADIUS_ATTR_ACCT_INTERIM_INTERVAL = 85,
        RADIUS_ATTR_NAS_IPV6_ADDRESS = 95
 };
@@ -107,11 +128,25 @@
 #define RADIUS_ACCT_TERMINATE_CAUSE_USER_ERROR 17
 #define RADIUS_ACCT_TERMINATE_CAUSE_HOST_REQUEST 18
 
+#define RADIUS_TUNNEL_TAGS 32
+
+/* Tunnel-Type */
+#define RADIUS_TUNNEL_TYPE_PPTP 1
+#define RADIUS_TUNNEL_TYPE_L2TP 3
+#define RADIUS_TUNNEL_TYPE_IPIP 7
+#define RADIUS_TUNNEL_TYPE_GRE 10
+#define RADIUS_TUNNEL_TYPE_VLAN 13
+
+/* Tunnel-Medium-Type */
+#define RADIUS_TUNNEL_MEDIUM_TYPE_IPV4 1
+#define RADIUS_TUNNEL_MEDIUM_TYPE_IPV6 2
+#define RADIUS_TUNNEL_MEDIUM_TYPE_802 6
+
 
 struct radius_attr_vendor {
 	u8 vendor_type;
 	u8 vendor_length;
-} __attribute__ ((packed));
+} STRUCT_PACKED;
 
 #define RADIUS_VENDOR_ID_CISCO 9
 #define RADIUS_CISCO_AV_PAIR 1
@@ -123,6 +158,10 @@
        RADIUS_VENDOR_ATTR_MS_MPPE_RECV_KEY = 17
 };
 
+#ifdef _MSC_VER
+#pragma pack(pop)
+#endif /* _MSC_VER */
+
 struct radius_ms_mppe_keys {
 	u8 *send;
 	size_t send_len;
@@ -182,7 +221,7 @@
 int radius_msg_copy_attr(struct radius_msg *dst, struct radius_msg *src,
 			 u8 type);
 void radius_msg_make_authenticator(struct radius_msg *msg,
-				   u8 *data, size_t len);
+				   const u8 *data, size_t len);
 struct radius_ms_mppe_keys *
 radius_msg_get_ms_keys(struct radius_msg *msg, struct radius_msg *sent_msg,
 		       u8 *secret, size_t secret_len);
@@ -199,6 +238,7 @@
 				  u8 *data, size_t data_len,
 				  u8 *secret, size_t secret_len);
 int radius_msg_get_attr(struct radius_msg *msg, u8 type, u8 *buf, size_t len);
+int radius_msg_get_vlanid(struct radius_msg *msg);
 
 static inline int radius_msg_add_attr_int32(struct radius_msg *msg, u8 type,
 					    u32 value)
Index: code_structure.doxygen
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/doc/code_structure.doxygen,v
retrieving revision 1.1
retrieving revision 1.2
diff -L contrib/wpa_supplicant/doc/code_structure.doxygen -L contrib/wpa_supplicant/doc/code_structure.doxygen -u -r1.1 -r1.2
--- contrib/wpa_supplicant/doc/code_structure.doxygen
+++ contrib/wpa_supplicant/doc/code_structure.doxygen
@@ -219,6 +219,12 @@
 eap_psk.c, eap_psk_common.h, eap_psk_common.c
 	EAP-PSK (note: this is not needed for WPA-PSK)
 
+eap_sake.c, eap_sake_common.h, eap_sake_common.c
+	EAP-SAKE
+
+eap_gpsk.c, eap_gpsk_common.h, eap_gpsk_common.c
+	EAP-GPSK
+
 eap_aka.c, eap_fast.c, eap_gtc.c, eap_leap.c, eap_md5.c, eap_mschapv2.c,
 eap_otp.c, eap_peap.c, eap_sim.c, eap_tls.c
 	Other EAP method implementations
Index: porting.doxygen
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/doc/porting.doxygen,v
retrieving revision 1.1
retrieving revision 1.2
diff -L contrib/wpa_supplicant/doc/porting.doxygen -L contrib/wpa_supplicant/doc/porting.doxygen -u -r1.1 -r1.2
--- contrib/wpa_supplicant/doc/porting.doxygen
+++ contrib/wpa_supplicant/doc/porting.doxygen
@@ -5,14 +5,62 @@
 hardware (board, CPU) and software (OS, drivers) targets. It is
 already used with number of operating systems and numerous wireless
 card models and drivers. The main %wpa_supplicant repository includes
-support for Linux, FreeBSD, and Windows. In addition, at least VxWorks
-and PalmOS are supported in separate repositories. On the hardware
+support for Linux, FreeBSD, and Windows. In addition, at least VxWorks,
+PalmOS, Windows CE, and Windows Mobile are supported in separate
+repositories. On the hardware
 side, %wpa_supplicant is used on various systems: desktops, laptops,
 PDAs, and embedded devices with CPUs including x86, PowerPC,
 arm/xscale, and MIPS. Both big and little endian configurations are
 supported.
 
 
+\section ansi_c_extra Extra functions on top of ANSI C
+
+%wpa_supplicant is mostly using ANSI C functions that are available on
+most targets. However, couple of additional functions that are common
+on modern UNIX systems are used. Number of these are listed with
+prototypes in common.h (the #ifdef CONFIG_ANSI_C_EXTRA block). These
+functions may need to be implemented or at least defined as macros to
+native functions in the target OS or C library.
+
+Many of the common ANSI C functions are used through a wrapper
+definitions in os.h to allow these to be replaced easily with a
+platform specific version in case standard C libraries are not
+available. In addition, os.h defines couple of common platform
+specific functions that are implemented in os_unix.c for UNIX like
+targets and in os_win32.c for Win32 API. If the target platform does
+not support either of these examples, a new os_*.c file may need to be
+added.
+
+Unless OS_NO_C_LIB_DEFINES is defined, the standard ANSI C and POSIX
+functions are used by defining the os_*() wrappers to use them
+directly in order to avoid extra cost in size and speed. If the target
+platform needs different versions of the functions, os.h can be
+modified to define the suitable macros or alternatively,
+OS_NO_C_LIB_DEFINES may be defined for the build and the wrapper
+functions can then be implemented in a new os_*.c wrapper file.
+
+common.h defines number of helper macros for handling integers of
+different size and byte order. Suitable version of these definitions
+may need to be added for the target platform.
+
+
+\section configuration_backend Configuration backend
+
+%wpa_supplicant implements a configuration interface that allows the
+backend to be easily replaced in order to read configuration data from
+a suitable source depending on the target platform. config.c
+implements the generic code that can be shared with all configuration
+backends. Each backend is implemented in its own config_*.c file.
+
+The included config_file.c backend uses a text file for configuration
+and config_winreg.c uses Windows registry. These files can be used as
+an example for a new configuration backend if the target platform uses
+different mechanism for configuration parameters. In addition,
+config_none.c can be used as an empty starting point for building a
+new configuration backend.
+
+
 \section driver_iface_porting Driver interface
 
 Unless the target OS and driver is already supported, most porting
@@ -118,4 +166,43 @@
 enabled/disabled if it is desirable that %wpa_supplicant processing
 for the interface is fully enabled/disabled at the same time.
 
+
+\section simple_build Simple build example
+
+One way to start a porting project is to begin with a very simple
+build of %wpa_supplicant with WPA-PSK support and once that is
+building correctly, start adding features.
+
+Following command can be used to build very simple version of
+%wpa_supplicant:
+
+\verbatim
+cc -o wpa_supplicant config.c eloop.c common.c md5.c rc4.c sha1.c \
+	config_none.c l2_packet_none.c tls_none.c wpa.c preauth.c \
+	aes_wrap.c wpa_supplicant.c events.c main_none.c drivers.c
+\endverbatim
+
+The end result is not really very useful since it uses empty functions
+for configuration parsing and layer 2 packet access and does not
+include a driver interface. However, this is a good starting point
+since the build is complete in the sense that all functions are
+present and this is easy to configure to a build system by just
+including the listed C files.
+
+Once this version can be build successfully, the end result can be
+made functional by adding a proper program entry point (main*.c),
+driver interface (driver_*.c and matching CONFIG_DRIVER_* define for
+registration in drivers.c), configuration parser/writer (config_*.c),
+and layer 2 packet access implementation (l2_packet_*.c). After these
+components have been added, the end result should be a working
+WPA/WPA2-PSK enabled supplicant.
+
+After the basic functionality has been verified to work, more features
+can be added by linking in more files and defining C pre-processor
+defines. Currently, the best source of information for what options
+are available and which files needs to be included is in the Makefile
+used for building the supplicant with make. Similar configuration will
+be needed for build systems that either use different type of make
+tool or a GUI-based project configuration.
+
 */
Index: mainpage.doxygen
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/doc/mainpage.doxygen,v
retrieving revision 1.1
retrieving revision 1.2
diff -L contrib/wpa_supplicant/doc/mainpage.doxygen -L contrib/wpa_supplicant/doc/mainpage.doxygen -u -r1.1 -r1.2
--- contrib/wpa_supplicant/doc/mainpage.doxygen
+++ contrib/wpa_supplicant/doc/mainpage.doxygen
@@ -13,7 +13,7 @@
 %wpa_supplicant has been implemented, how it can be modified, how new
 drivers can be supported, and how %wpa_supplicant can be ported to
 other operating systems. If any information is missing, feel free to
-contact Jouni Malinen <jkmaline at cc.hut.fi> for more
+contact Jouni Malinen <j at w1.fi> for more
 information. Contributions as patch files are also very welcome at the
 same address. Please note that %wpa_supplicant is licensed under dual
 license, GPLv2 or BSD at user's choice. All contributions to
Index: eap.doxygen
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/doc/eap.doxygen,v
retrieving revision 1.1
retrieving revision 1.2
diff -L contrib/wpa_supplicant/doc/eap.doxygen -L contrib/wpa_supplicant/doc/eap.doxygen -u -r1.1 -r1.2
--- contrib/wpa_supplicant/doc/eap.doxygen
+++ contrib/wpa_supplicant/doc/eap.doxygen
@@ -1,9 +1,10 @@
 /**
 \page eap_module EAP peer implementation
 
-%wpa_supplicant uses a separate code module for EAP peer
-implementation. This module was designed to use only a minimal set of
-direct function calls (mainly, to debug/event functions) in order for
+Extensible Authentication Protocol (EAP) is an authentication framework
+defined in RFC 3748. %wpa_supplicant uses a separate code module for EAP
+peer implementation. This module was designed to use only a minimal set
+of direct function calls (mainly, to debug/event functions) in order for
 it to be usable in other programs. The design of the EAP
 implementation is based loosely on RFC 4137. The state machine is
 defined in this RFC and so is the interface between the peer state
@@ -25,8 +26,9 @@
 method specific functions. This allows new EAP methods to be added
 without modifying the core EAP state machine implementation.
 
-New EAP methods need to be registered by adding them into build
-(Makefile) and EAP method table in the beginning of eap.c. Each EAP
+New EAP methods need to be registered by adding them into the build
+(Makefile) and the EAP method registration list in the
+eap_peer_register_methods() function of eap_methods.c. Each EAP
 method should use a build-time configuration option, e.g., EAP_TLS, in
 order to make it possible to select which of the methods are included
 in the build.
@@ -35,4 +37,20 @@
 eap_method defines the needed function pointers that each EAP method
 must provide. In addition, the EAP type and name are registered using
 this structure. This interface is based on section 4.4 of RFC 4137.
+
+It is recommended that the EAP methods would use generic helper
+functions, eap_msg_alloc() and eap_hdr_validate() when processing
+messages. This allows code sharing and can avoid missing some of the
+needed validation steps for received packets. In addition, these
+functions make it easier to change between expanded and legacy EAP
+header, if needed.
+
+When adding an EAP method that uses a vendor specific EAP type
+(Expanded Type as defined in RFC 3748, Chapter 5.7), the new method
+must be registered by passing vendor id instead of EAP_VENDOR_IETF to
+eap_peer_method_alloc(). These methods must not try to emulate
+expanded types by registering a legacy EAP method for type 254. See
+eap_vendor_test.c for an example of an EAP method implementation that
+is implemented as an expanded type.
+
 */
Index: doxygen.fast
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/doc/doxygen.fast,v
retrieving revision 1.1
retrieving revision 1.2
diff -L contrib/wpa_supplicant/doc/doxygen.fast -L contrib/wpa_supplicant/doc/doxygen.fast -u -r1.1 -r1.2
--- contrib/wpa_supplicant/doc/doxygen.fast
+++ contrib/wpa_supplicant/doc/doxygen.fast
@@ -4,7 +4,7 @@
 # Project related configuration options
 #---------------------------------------------------------------------------
 PROJECT_NAME           = wpa_supplicant
-PROJECT_NUMBER         = 0.4.x
+PROJECT_NUMBER         = 0.5.x
 OUTPUT_DIRECTORY       = doc
 CREATE_SUBDIRS         = NO
 OUTPUT_LANGUAGE        = English
Index: testing_tools.doxygen
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/doc/testing_tools.doxygen,v
retrieving revision 1.1
retrieving revision 1.2
diff -L contrib/wpa_supplicant/doc/testing_tools.doxygen -L contrib/wpa_supplicant/doc/testing_tools.doxygen -u -r1.1 -r1.2
--- contrib/wpa_supplicant/doc/testing_tools.doxygen
+++ contrib/wpa_supplicant/doc/testing_tools.doxygen
@@ -47,7 +47,9 @@
 
 \verbatim
 usage:
-eapol_test [-nW] -c<conf> [-a<AS IP>] [-p<AS port>] [-s<AS secret>] [-r<count>]
+eapol_test [-nWS] -c<conf> [-a<AS IP>] [-p<AS port>] [-s<AS secret>] \
+           [-r<count>] [-t<timeout>] [-C<Connect-Info>] \
+           [-M<client MAC address>]
 eapol_test scard
 eapol_test sim <PIN> <num triplets> [debug]
 
@@ -58,7 +60,12 @@
   -s<AS secret> = shared secret with the authentication server, default 'radius'
   -r<count> = number of re-authentications
   -W = wait for a control interface monitor before starting
+  -S = save configuration after authentiation
   -n = no MPPE keys expected
+  -t<timeout> = sets timeout in seconds (default: 30 s)
+  -C<Connect-Info> = RADIUS Connect-Info (default: CONNECT 11Mbps 802.11b)
+  -M<client MAC address> = Set own MAC address (Calling-Station-Id,
+                           default: 02:00:00:00:00:01)
 \endverbatim
 
 
Index: kerneldoc2doxygen.pl
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/doc/kerneldoc2doxygen.pl,v
retrieving revision 1.1
retrieving revision 1.2
diff -L contrib/wpa_supplicant/doc/kerneldoc2doxygen.pl -L contrib/wpa_supplicant/doc/kerneldoc2doxygen.pl -u -r1.1 -r1.2
--- contrib/wpa_supplicant/doc/kerneldoc2doxygen.pl
+++ contrib/wpa_supplicant/doc/kerneldoc2doxygen.pl
@@ -20,7 +20,7 @@
 #
 ##########################################################################
 # Copyright (C) 2003 Jonathan Foster <jon at jon-foster.co.uk>
-# Copyright (C) 2005 Jouni Malinen <jkmaline at cc.hut.fi>
+# Copyright (C) 2005 Jouni Malinen <j at w1.fi>
 # (modified for kerneldoc format used in wpa_supplicant)
 #
 # This program is free software; you can redistribute it and/or modify
@@ -34,7 +34,7 @@
 #
 # You should have received a copy of the GNU General Public License
 # along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 # or look at http://www.gnu.org/licenses/gpl.html
 ##########################################################################
 
Index: doxygen.full
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/doc/doxygen.full,v
retrieving revision 1.1
retrieving revision 1.2
diff -L contrib/wpa_supplicant/doc/doxygen.full -L contrib/wpa_supplicant/doc/doxygen.full -u -r1.1 -r1.2
--- contrib/wpa_supplicant/doc/doxygen.full
+++ contrib/wpa_supplicant/doc/doxygen.full
@@ -4,7 +4,7 @@
 # Project related configuration options
 #---------------------------------------------------------------------------
 PROJECT_NAME           = wpa_supplicant
-PROJECT_NUMBER         = 0.4.x
+PROJECT_NUMBER         = 0.5.x
 OUTPUT_DIRECTORY       = doc
 CREATE_SUBDIRS         = NO
 OUTPUT_LANGUAGE        = English
@@ -187,7 +187,7 @@
 SEARCH_INCLUDES        = YES
 INCLUDE_PATH           = 
 INCLUDE_FILE_PATTERNS  = 
-PREDEFINED             = IEEE8021X_EAPOL
+PREDEFINED             = IEEE8021X_EAPOL CONFIG_CTRL_IFACE
 EXPAND_AS_DEFINED      = 
 SKIP_FUNCTION_MACROS   = YES
 #---------------------------------------------------------------------------
Index: ctrl_iface.doxygen
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/doc/ctrl_iface.doxygen,v
retrieving revision 1.1
retrieving revision 1.2
diff -L contrib/wpa_supplicant/doc/ctrl_iface.doxygen -L contrib/wpa_supplicant/doc/ctrl_iface.doxygen -u -r1.1 -r1.2
--- contrib/wpa_supplicant/doc/ctrl_iface.doxygen
+++ contrib/wpa_supplicant/doc/ctrl_iface.doxygen
@@ -138,6 +138,7 @@
 \verbatim
 bssid=02:00:01:02:03:04
 ssid=test network
+id=0
 pairwise_cipher=CCMP
 group_cipher=CCMP
 key_mgmt=WPA-PSK
@@ -368,11 +369,15 @@
 \endverbatim
 
 
-\subsection ctrl_iface_GET_CAPABILITY GET_CAPABILITY <option>
+\subsection ctrl_iface_GET_CAPABILITY GET_CAPABILITY <option> [strict]
 
 Get list of supported functionality (eap, pairwise, group,
 proto). Supported functionality is shown as space separate lists of
 values used in the same format as in %wpa_supplicant configuration.
+If optional argument, 'strict', is added, only the values that the
+driver claims to explicitly support are included. Without this, all
+available capabilities are included if the driver does not provide
+a mechanism for querying capabilities.
 
 Example request/reply pairs:
 
@@ -387,6 +392,10 @@
 \endverbatim
 
 \verbatim
+GET_CAPABILITY pairwise strict
+\endverbatim
+
+\verbatim
 GET_CAPABILITY group
 CCMP TKIP WEP104 WEP40
 \endverbatim
@@ -406,4 +415,23 @@
 OPEN SHARED LEAP
 \endverbatim
 
+
+\subsection ctrl_iface_AP_SCAN AP_SCAN <ap_scan value>
+
+Change ap_scan value:
+0 = no scanning,
+1 = %wpa_supplicant requests scans and uses scan results to select the AP,
+2 = %wpa_supplicant does not use scanning and just requests driver to
+associate and take care of AP selection
+
+
+\subsection ctrl_iface_INTERFACES INTERFACES
+
+List configured interfaces.
+
+\verbatim
+wlan0
+eth0
+\endverbatim
+
 */
Index: wpa_background.8
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/doc/docbook/wpa_background.8,v
retrieving revision 1.1
retrieving revision 1.2
diff -L contrib/wpa_supplicant/doc/docbook/wpa_background.8 -L contrib/wpa_supplicant/doc/docbook/wpa_background.8 -u -r1.1 -r1.2
--- contrib/wpa_supplicant/doc/docbook/wpa_background.8
+++ contrib/wpa_supplicant/doc/docbook/wpa_background.8
@@ -3,7 +3,7 @@
 .\" <http://shell.ipoline.com/~elmert/comp/docbook2X/> 
 .\" Please send any bug reports, improvements, comments, patches, 
 .\" etc. to Steve Cheng <steve at ggi-project.org>.
-.TH "WPA_BACKGROUND" "8" "08 February 2006" "" ""
+.TH "WPA_BACKGROUND" "8" "28 May 2007" "" ""
 
 .SH NAME
 wpa_background \- Background information on Wi-Fi Protected Access and IEEE 802.11i
@@ -76,7 +76,7 @@
 .SH "LEGAL"
 .PP
 wpa_supplicant is copyright (c) 2003-2005,
-Jouni Malinen <jkmaline at cc.hut.fi> and
+Jouni Malinen <j at w1.fi> and
 contributors.
 All Rights Reserved.
 .PP
Index: wpa_passphrase.8
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/doc/docbook/wpa_passphrase.8,v
retrieving revision 1.1
retrieving revision 1.2
diff -L contrib/wpa_supplicant/doc/docbook/wpa_passphrase.8 -L contrib/wpa_supplicant/doc/docbook/wpa_passphrase.8 -u -r1.1 -r1.2
--- contrib/wpa_supplicant/doc/docbook/wpa_passphrase.8
+++ contrib/wpa_supplicant/doc/docbook/wpa_passphrase.8
@@ -3,10 +3,10 @@
 .\" <http://shell.ipoline.com/~elmert/comp/docbook2X/> 
 .\" Please send any bug reports, improvements, comments, patches, 
 .\" etc. to Steve Cheng <steve at ggi-project.org>.
-.TH "WPA_PASSPHRASE" "8" "08 February 2006" "" ""
+.TH "WPA_PASSPHRASE" "8" "28 May 2007" "" ""
 
 .SH NAME
-wpa_passphrase \- Set WPA passphrase for a SSID
+wpa_passphrase \- Generate a WPA PSK from an ASCII passphrase for a SSID
 .SH SYNOPSIS
 
 \fBwpa_passphrase\fR [ \fB\fIssid\fB\fR ] [ \fB\fIpassphrase\fB\fR ]
@@ -15,7 +15,8 @@
 .PP
 \fBwpa_passphrase\fR pre-computes PSK entries for
 network configuration blocks of a
-\fIwpa_supplicant.conf\fR file.
+\fIwpa_supplicant.conf\fR file. An ASCII passphrase
+and SSID are used to generate a 256-bit PSK.
 .SH "OPTIONS"
 .TP
 \fBssid\fR
@@ -31,7 +32,7 @@
 .SH "LEGAL"
 .PP
 wpa_supplicant is copyright (c) 2003-2005,
-Jouni Malinen <jkmaline at cc.hut.fi> and
+Jouni Malinen <j at w1.fi> and
 contributors.
 All Rights Reserved.
 .PP
Index: wpa_cli.8
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/doc/docbook/wpa_cli.8,v
retrieving revision 1.1
retrieving revision 1.2
diff -L contrib/wpa_supplicant/doc/docbook/wpa_cli.8 -L contrib/wpa_supplicant/doc/docbook/wpa_cli.8 -u -r1.1 -r1.2
--- contrib/wpa_supplicant/doc/docbook/wpa_cli.8
+++ contrib/wpa_supplicant/doc/docbook/wpa_cli.8
@@ -3,7 +3,7 @@
 .\" <http://shell.ipoline.com/~elmert/comp/docbook2X/> 
 .\" Please send any bug reports, improvements, comments, patches, 
 .\" etc. to Steve Cheng <steve at ggi-project.org>.
-.TH "WPA_CLI" "8" "08 February 2006" "" ""
+.TH "WPA_CLI" "8" "28 May 2007" "" ""
 
 .SH NAME
 wpa_cli \- WPA command line client
@@ -113,7 +113,14 @@
 based on events from wpa_supplicant.  The specified file will
 be executed with the first argument set to interface name and
 second to "CONNECT" or "DISCONNECT" depending on the event.
-This can be used 
+This can be used to execute networking tools required to configure
+the interface.
+
+Additionally, three environmental variables are available to
+the file: WPA_CTRL_DIR, WPA_ID, and WPA_ID_STR. WPA_CTRL_DIR
+contains the absolute path to the ctrl_interface socket. WPA_ID
+contains the unique network_id identifier assigned to the active
+network, and WPA_ID_STR contains the content of the id_str option.
 .TP
 \fB-P file\fR
 Set the location of the PID
@@ -177,7 +184,7 @@
 \fBotp <network id> <password>\fR
 configure one-time-password for an SSID
 .TP
-\fBbssid *lt;network id> <BSSID>\fR
+\fBbssid <network id> <BSSID>\fR
 set preferred BSSID for an SSID
 .TP
 \fBlist_networks\fR
@@ -194,7 +201,7 @@
 .SH "LEGAL"
 .PP
 wpa_supplicant is copyright (c) 2003-2005,
-Jouni Malinen <jkmaline at cc.hut.fi> and
+Jouni Malinen <j at w1.fi> and
 contributors.
 All Rights Reserved.
 .PP
Index: wpa_supplicant.conf.5
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/doc/docbook/wpa_supplicant.conf.5,v
retrieving revision 1.1
retrieving revision 1.2
diff -L contrib/wpa_supplicant/doc/docbook/wpa_supplicant.conf.5 -L contrib/wpa_supplicant/doc/docbook/wpa_supplicant.conf.5 -u -r1.1 -r1.2
--- contrib/wpa_supplicant/doc/docbook/wpa_supplicant.conf.5
+++ contrib/wpa_supplicant/doc/docbook/wpa_supplicant.conf.5
@@ -3,7 +3,7 @@
 .\" <http://shell.ipoline.com/~elmert/comp/docbook2X/> 
 .\" Please send any bug reports, improvements, comments, patches, 
 .\" etc. to Steve Cheng <steve at ggi-project.org>.
-.TH "WPA_SUPPLICANT.CONF" "5" "08 February 2006" "" ""
+.TH "WPA_SUPPLICANT.CONF" "5" "28 May 2007" "" ""
 
 .SH NAME
 wpa_supplicant.conf \- configuration file for wpa_supplicant
@@ -24,13 +24,13 @@
 Changes to configuration file can be reloaded be sending
 SIGHUP signal to \fBwpa_supplicant\fR ('killall -HUP
 wpa_supplicant'). Similarly, reloading can be triggered with
-'wpa_cli reconfigure' command.
+the 'wpa_cli reconfigure' command.
 .PP
 Configuration file can include one or more network blocks,
 e.g., one for each used SSID. wpa_supplicant will automatically
-select the best betwork based on the order of network blocks in
+select the best network based on the order of network blocks in
 the configuration file, network security level (WPA/WPA2 is
-prefered), and signal strength.
+preferred), and signal strength.
 .SH "QUICK EXAMPLES"
 .TP 3
 1. 
Index: wpa_passphrase.sgml
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/doc/docbook/wpa_passphrase.sgml,v
retrieving revision 1.1
retrieving revision 1.2
diff -L contrib/wpa_supplicant/doc/docbook/wpa_passphrase.sgml -L contrib/wpa_supplicant/doc/docbook/wpa_passphrase.sgml -u -r1.1 -r1.2
--- contrib/wpa_supplicant/doc/docbook/wpa_passphrase.sgml
+++ contrib/wpa_supplicant/doc/docbook/wpa_passphrase.sgml
@@ -7,7 +7,7 @@
   </refmeta>
   <refnamediv>
     <refname>wpa_passphrase</refname>
-    <refpurpose>Set WPA passphrase for a SSID</refpurpose>
+    <refpurpose>Generate a WPA PSK from an ASCII passphrase for a SSID</refpurpose>
   </refnamediv>
   <refsynopsisdiv>
     <cmdsynopsis>
@@ -22,7 +22,8 @@
 
     <para><command>wpa_passphrase</command> pre-computes PSK entries for
     network configuration blocks of a
-    <filename>wpa_supplicant.conf</filename> file.</para>
+    <filename>wpa_supplicant.conf</filename> file. An ASCII passphrase
+    and SSID are used to generate a 256-bit PSK.</para>
   </refsect1>
 
   <refsect1>
@@ -62,7 +63,7 @@
   <refsect1>
     <title>Legal</title>
     <para>wpa_supplicant is copyright (c) 2003-2005,
-    Jouni Malinen <email>jkmaline at cc.hut.fi</email> and
+    Jouni Malinen <email>j at w1.fi</email> and
     contributors.
     All Rights Reserved.</para>
 
Index: wpa_supplicant.conf.sgml
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/doc/docbook/wpa_supplicant.conf.sgml,v
retrieving revision 1.1
retrieving revision 1.2
diff -L contrib/wpa_supplicant/doc/docbook/wpa_supplicant.conf.sgml -L contrib/wpa_supplicant/doc/docbook/wpa_supplicant.conf.sgml -u -r1.1 -r1.2
--- contrib/wpa_supplicant/doc/docbook/wpa_supplicant.conf.sgml
+++ contrib/wpa_supplicant/doc/docbook/wpa_supplicant.conf.sgml
@@ -26,13 +26,13 @@
     <para>Changes to configuration file can be reloaded be sending
     SIGHUP signal to <command>wpa_supplicant</command> ('killall -HUP
     wpa_supplicant'). Similarly, reloading can be triggered with
-    'wpa_cli reconfigure' command.</para>
+    the 'wpa_cli reconfigure' command.</para>
 
     <para>Configuration file can include one or more network blocks,
     e.g., one for each used SSID. wpa_supplicant will automatically
-    select the best betwork based on the order of network blocks in
+    select the best network based on the order of network blocks in
     the configuration file, network security level (WPA/WPA2 is
-    prefered), and signal strength.</para>
+    preferred), and signal strength.</para>
   </refsect1>
 
   <refsect1>
Index: wpa_cli.sgml
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/doc/docbook/wpa_cli.sgml,v
retrieving revision 1.1
retrieving revision 1.2
diff -L contrib/wpa_supplicant/doc/docbook/wpa_cli.sgml -L contrib/wpa_supplicant/doc/docbook/wpa_cli.sgml -u -r1.1 -r1.2
--- contrib/wpa_supplicant/doc/docbook/wpa_cli.sgml
+++ contrib/wpa_supplicant/doc/docbook/wpa_cli.sgml
@@ -141,7 +141,15 @@
         based on events from wpa_supplicant.  The specified file will
 	be executed with the first argument set to interface name and
 	second to "CONNECT" or "DISCONNECT" depending on the event.
-	This can be used </para></listitem>
+	This can be used to execute networking tools required to configure
+	the interface.</para>
+
+	<para>Additionally, three environmental variables are available to
+	the file: WPA_CTRL_DIR, WPA_ID, and WPA_ID_STR. WPA_CTRL_DIR
+	contains the absolute path to the ctrl_interface socket. WPA_ID
+	contains the unique network_id identifier assigned to the active
+	network, and WPA_ID_STR contains the content of the id_str option.
+	</para></listitem>
       </varlistentry>
 
       <varlistentry>
@@ -282,7 +290,7 @@
       </varlistentry>
 
       <varlistentry>
-	<term>bssid *lt;network id> <BSSID></term>
+	<term>bssid <network id> <BSSID></term>
 	<listitem>
 	  <para>set preferred BSSID for an SSID</para>
 	</listitem>
@@ -320,7 +328,7 @@
   <refsect1>
     <title>Legal</title>
     <para>wpa_supplicant is copyright (c) 2003-2005,
-    Jouni Malinen <email>jkmaline at cc.hut.fi</email> and
+    Jouni Malinen <email>j at w1.fi</email> and
     contributors.
     All Rights Reserved.</para>
 
Index: wpa_background.sgml
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/doc/docbook/wpa_background.sgml,v
retrieving revision 1.1
retrieving revision 1.2
diff -L contrib/wpa_supplicant/doc/docbook/wpa_background.sgml -L contrib/wpa_supplicant/doc/docbook/wpa_background.sgml -u -r1.1 -r1.2
--- contrib/wpa_supplicant/doc/docbook/wpa_background.sgml
+++ contrib/wpa_supplicant/doc/docbook/wpa_background.sgml
@@ -91,7 +91,7 @@
   <refsect1>
     <title>Legal</title>
     <para>wpa_supplicant is copyright (c) 2003-2005,
-    Jouni Malinen <email>jkmaline at cc.hut.fi</email> and
+    Jouni Malinen <email>j at w1.fi</email> and
     contributors.
     All Rights Reserved.</para>
 
Index: wpa_supplicant.8
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/doc/docbook/wpa_supplicant.8,v
retrieving revision 1.1
retrieving revision 1.2
diff -L contrib/wpa_supplicant/doc/docbook/wpa_supplicant.8 -L contrib/wpa_supplicant/doc/docbook/wpa_supplicant.8 -u -r1.1 -r1.2
--- contrib/wpa_supplicant/doc/docbook/wpa_supplicant.8
+++ contrib/wpa_supplicant/doc/docbook/wpa_supplicant.8
@@ -3,13 +3,13 @@
 .\" <http://shell.ipoline.com/~elmert/comp/docbook2X/> 
 .\" Please send any bug reports, improvements, comments, patches, 
 .\" etc. to Steve Cheng <steve at ggi-project.org>.
-.TH "WPA_SUPPLICANT" "8" "08 February 2006" "" ""
+.TH "WPA_SUPPLICANT" "8" "28 May 2007" "" ""
 
 .SH NAME
 wpa_supplicant \- Wi-Fi Protected Access client and IEEE 802.1X supplicant
 .SH SYNOPSIS
 
-\fBwpa_supplicant\fR [ \fB-BddehLqqvw\fR ] [ \fB-i\fIifname\fB\fR ] [ \fB-c\fIconfig file\fB\fR ] [ \fB-D\fIdriver\fB\fR ]
+\fBwpa_supplicant\fR [ \fB-BddehLqqvw\fR ] [ \fB-i\fIifname\fB\fR ] [ \fB-c\fIconfig file\fB\fR ] [ \fB-D\fIdriver\fB\fR ] [ \fB-P\fIPID_file\fB\fR ]
 
 .SH "OVERVIEW"
 .PP
@@ -260,6 +260,15 @@
 \fB-c filename\fR
 Path to configuration file.
 .TP
+\fB-P PID_file\fR
+Path to PID file.
+.TP
+\fB-C ctrl_interface\fR
+Path to ctrl_interface socket (only used if -c is not).
+.TP
+\fB-g global ctrl_interface\fR
+Path to global ctrl_interface socket.
+.TP
 \fB-D driver\fR
 Driver to use.  See the available options below.
 .TP
@@ -454,7 +463,7 @@
 .PP
 First, make a configuration file, e.g.
 \fI/etc/wpa_supplicant.conf\fR, that describes the networks
-you are interested in.  See \fBwpa_supplicant\fR(5)
+you are interested in.  See \fBwpa_supplicant.conf\fR(5)
 for details.
 .PP
 Once the configuration is ready, you can test whether the
@@ -536,7 +545,7 @@
 .SH "LEGAL"
 .PP
 wpa_supplicant is copyright (c) 2003-2005,
-Jouni Malinen <jkmaline at cc.hut.fi> and
+Jouni Malinen <j at w1.fi> and
 contributors.
 All Rights Reserved.
 .PP
Index: wpa_supplicant.sgml
===================================================================
RCS file: /home/cvs/src/contrib/wpa_supplicant/doc/docbook/wpa_supplicant.sgml,v
retrieving revision 1.1
retrieving revision 1.2
diff -L contrib/wpa_supplicant/doc/docbook/wpa_supplicant.sgml -L contrib/wpa_supplicant/doc/docbook/wpa_supplicant.sgml -u -r1.1 -r1.2
--- contrib/wpa_supplicant/doc/docbook/wpa_supplicant.sgml
+++ contrib/wpa_supplicant/doc/docbook/wpa_supplicant.sgml
@@ -16,6 +16,7 @@
       <arg>-i<replaceable>ifname</replaceable></arg>
       <arg>-c<replaceable>config file</replaceable></arg>
       <arg>-D<replaceable>driver</replaceable></arg>
+      <arg>-P<replaceable>PID_file</replaceable></arg>
     </cmdsynopsis>
   </refsynopsisdiv>
   <refsect1>
@@ -347,6 +348,27 @@
       </varlistentry>
 
       <varlistentry>
+	<term>-P PID_file</term>
+	<listitem>
+	  <para>Path to PID file.</para>
+	</listitem>
+      </varlistentry>
+
+      <varlistentry>
+	<term>-C ctrl_interface</term>
+	<listitem>
+	  <para>Path to ctrl_interface socket (only used if -c is not).</para>
+	</listitem>
+      </varlistentry>
+
+      <varlistentry>
+	<term>-g global ctrl_interface</term>
+	<listitem>
+	  <para>Path to global ctrl_interface socket.</para>
+	</listitem>
+      </varlistentry>
+
+      <varlistentry>
 	<term>-D driver</term>
 	<listitem>
 	  <para>Driver to use.  See the available options below.</para>
@@ -657,7 +679,7 @@
     <para>First, make a configuration file, e.g.
     <filename>/etc/wpa_supplicant.conf</filename>, that describes the networks
     you are interested in.  See <citerefentry>
-	<refentrytitle>wpa_supplicant</refentrytitle>
+	<refentrytitle>wpa_supplicant.conf</refentrytitle>
 	<manvolnum>5</manvolnum>
       </citerefentry>
     for details.</para>
@@ -751,7 +773,7 @@
   <refsect1>
     <title>Legal</title>
     <para>wpa_supplicant is copyright (c) 2003-2005,
-    Jouni Malinen <email>jkmaline at cc.hut.fi</email> and
+    Jouni Malinen <email>j at w1.fi</email> and
     contributors.
     All Rights Reserved.</para>
 


More information about the Midnightbsd-cvs mailing list