[pkg-wpa-devel] r880 - in /wpasupplicant/trunk: debian/ debian/patches/ patches/ src/common/ src/crypto/ src/drivers/ src/eap_common/ src/eap_peer/ src/eap_server/ src/l2_packet/ src/radius/ src/rsn_supp/ src/tls/ src/utils/ wpa_supplicant/ wpa_supplicant/doc/ wpa_supplicant/doc/docbook/ wpa_supplicant/tests/

kelmo-guest at users.alioth.debian.org kelmo-guest at users.alioth.debian.org
Sat Nov 3 11:46:49 UTC 2007


Author: kelmo-guest
Date: Sat Nov  3 11:46:49 2007
New Revision: 880

URL: http://svn.debian.org/wsvn/pkg-wpa/?sc=1&rev=880
Log:
* New upstream git snapshot.
* Build depend on docbook and docbook-utils to generate upstream manpages
  from sgml source.a
* Upstream wpa_cli(8) is no longer incorrect with regard to CONNECTED and
  DISCONNECTED signal events. (Closes: #432904)

Added:
    wpasupplicant/trunk/patches/openssl-0.9.8g-tls-extensions.patch
      - copied unchanged from r879, wpasupplicant/branches/upstream/current/patches/openssl-0.9.8g-tls-extensions.patch
    wpasupplicant/trunk/patches/openssl-0.9.9-session-ticket.patch
      - copied unchanged from r879, wpasupplicant/branches/upstream/current/patches/openssl-0.9.9-session-ticket.patch
    wpasupplicant/trunk/src/drivers/Apple80211.h
      - copied unchanged from r879, wpasupplicant/branches/upstream/current/src/drivers/Apple80211.h
    wpasupplicant/trunk/src/drivers/MobileApple80211.c
      - copied unchanged from r879, wpasupplicant/branches/upstream/current/src/drivers/MobileApple80211.c
    wpasupplicant/trunk/src/drivers/MobileApple80211.h
      - copied unchanged from r879, wpasupplicant/branches/upstream/current/src/drivers/MobileApple80211.h
    wpasupplicant/trunk/src/drivers/driver_iphone.m
      - copied unchanged from r879, wpasupplicant/branches/upstream/current/src/drivers/driver_iphone.m
    wpasupplicant/trunk/src/drivers/driver_osx.m
      - copied unchanged from r879, wpasupplicant/branches/upstream/current/src/drivers/driver_osx.m
    wpasupplicant/trunk/src/eap_common/eap_fast_common.h
      - copied unchanged from r879, wpasupplicant/branches/upstream/current/src/eap_common/eap_fast_common.h
    wpasupplicant/trunk/src/eap_common/eap_tlv_common.h
      - copied unchanged from r879, wpasupplicant/branches/upstream/current/src/eap_common/eap_tlv_common.h
    wpasupplicant/trunk/src/eap_server/eap_fast.c
      - copied unchanged from r879, wpasupplicant/branches/upstream/current/src/eap_server/eap_fast.c
    wpasupplicant/trunk/src/tls/tlsv1_client_i.h
      - copied unchanged from r879, wpasupplicant/branches/upstream/current/src/tls/tlsv1_client_i.h
    wpasupplicant/trunk/src/tls/tlsv1_client_read.c
      - copied unchanged from r879, wpasupplicant/branches/upstream/current/src/tls/tlsv1_client_read.c
    wpasupplicant/trunk/src/tls/tlsv1_client_write.c
      - copied unchanged from r879, wpasupplicant/branches/upstream/current/src/tls/tlsv1_client_write.c
    wpasupplicant/trunk/src/tls/tlsv1_cred.c
      - copied unchanged from r879, wpasupplicant/branches/upstream/current/src/tls/tlsv1_cred.c
    wpasupplicant/trunk/src/tls/tlsv1_cred.h
      - copied unchanged from r879, wpasupplicant/branches/upstream/current/src/tls/tlsv1_cred.h
    wpasupplicant/trunk/src/tls/tlsv1_record.c
      - copied unchanged from r879, wpasupplicant/branches/upstream/current/src/tls/tlsv1_record.c
    wpasupplicant/trunk/src/tls/tlsv1_record.h
      - copied unchanged from r879, wpasupplicant/branches/upstream/current/src/tls/tlsv1_record.h
    wpasupplicant/trunk/src/tls/tlsv1_server.c
      - copied unchanged from r879, wpasupplicant/branches/upstream/current/src/tls/tlsv1_server.c
    wpasupplicant/trunk/src/tls/tlsv1_server.h
      - copied unchanged from r879, wpasupplicant/branches/upstream/current/src/tls/tlsv1_server.h
    wpasupplicant/trunk/src/tls/tlsv1_server_i.h
      - copied unchanged from r879, wpasupplicant/branches/upstream/current/src/tls/tlsv1_server_i.h
    wpasupplicant/trunk/src/tls/tlsv1_server_read.c
      - copied unchanged from r879, wpasupplicant/branches/upstream/current/src/tls/tlsv1_server_read.c
    wpasupplicant/trunk/src/tls/tlsv1_server_write.c
      - copied unchanged from r879, wpasupplicant/branches/upstream/current/src/tls/tlsv1_server_write.c
    wpasupplicant/trunk/wpa_supplicant/tests/test_x509v3_nist.sh
      - copied unchanged from r879, wpasupplicant/branches/upstream/current/wpa_supplicant/tests/test_x509v3_nist.sh
    wpasupplicant/trunk/wpa_supplicant/tests/test_x509v3_nist2.sh
      - copied unchanged from r879, wpasupplicant/branches/upstream/current/wpa_supplicant/tests/test_x509v3_nist2.sh
Removed:
    wpasupplicant/trunk/wpa_supplicant/doc/docbook/wpa_background.8
    wpasupplicant/trunk/wpa_supplicant/doc/docbook/wpa_cli.8
    wpasupplicant/trunk/wpa_supplicant/doc/docbook/wpa_passphrase.8
    wpasupplicant/trunk/wpa_supplicant/doc/docbook/wpa_supplicant.8
    wpasupplicant/trunk/wpa_supplicant/doc/docbook/wpa_supplicant.conf.5
Modified:
    wpasupplicant/trunk/debian/changelog
    wpasupplicant/trunk/debian/control
    wpasupplicant/trunk/debian/patches/00list
    wpasupplicant/trunk/debian/rules
    wpasupplicant/trunk/src/common/defs.h
    wpasupplicant/trunk/src/common/wpa_common.c
    wpasupplicant/trunk/src/common/wpa_common.h
    wpasupplicant/trunk/src/crypto/aes_wrap.c
    wpasupplicant/trunk/src/crypto/aes_wrap.h
    wpasupplicant/trunk/src/crypto/crypto.h
    wpasupplicant/trunk/src/crypto/crypto_internal.c
    wpasupplicant/trunk/src/crypto/ms_funcs.c
    wpasupplicant/trunk/src/crypto/ms_funcs.h
    wpasupplicant/trunk/src/crypto/sha256.c
    wpasupplicant/trunk/src/crypto/tls.h
    wpasupplicant/trunk/src/crypto/tls_gnutls.c
    wpasupplicant/trunk/src/crypto/tls_internal.c
    wpasupplicant/trunk/src/crypto/tls_none.c
    wpasupplicant/trunk/src/crypto/tls_openssl.c
    wpasupplicant/trunk/src/crypto/tls_schannel.c
    wpasupplicant/trunk/src/drivers/driver.h
    wpasupplicant/trunk/src/drivers/driver_wext.c
    wpasupplicant/trunk/src/drivers/drivers.c
    wpasupplicant/trunk/src/eap_common/eap_gpsk_common.c
    wpasupplicant/trunk/src/eap_common/eap_gpsk_common.h
    wpasupplicant/trunk/src/eap_peer/eap.c
    wpasupplicant/trunk/src/eap_peer/eap_fast.c
    wpasupplicant/trunk/src/eap_peer/eap_fast_pac.h
    wpasupplicant/trunk/src/eap_peer/eap_gpsk.c
    wpasupplicant/trunk/src/eap_peer/eap_gtc.c
    wpasupplicant/trunk/src/eap_peer/eap_i.h
    wpasupplicant/trunk/src/eap_peer/eap_leap.c
    wpasupplicant/trunk/src/eap_peer/eap_mschapv2.c
    wpasupplicant/trunk/src/eap_peer/eap_tlv.h
    wpasupplicant/trunk/src/eap_peer/eap_ttls.c
    wpasupplicant/trunk/src/eap_peer/tncc.c
    wpasupplicant/trunk/src/eap_server/eap.c
    wpasupplicant/trunk/src/eap_server/eap.h
    wpasupplicant/trunk/src/eap_server/eap_gpsk.c
    wpasupplicant/trunk/src/eap_server/eap_gtc.c
    wpasupplicant/trunk/src/eap_server/eap_i.h
    wpasupplicant/trunk/src/eap_server/eap_methods.c
    wpasupplicant/trunk/src/eap_server/eap_mschapv2.c
    wpasupplicant/trunk/src/eap_server/eap_tlv.c
    wpasupplicant/trunk/src/l2_packet/l2_packet_freebsd.c
    wpasupplicant/trunk/src/radius/radius_client.c
    wpasupplicant/trunk/src/radius/radius_server.c
    wpasupplicant/trunk/src/radius/radius_server.h
    wpasupplicant/trunk/src/rsn_supp/wpa_ft.c
    wpasupplicant/trunk/src/tls/asn1.c
    wpasupplicant/trunk/src/tls/tlsv1_client.c
    wpasupplicant/trunk/src/tls/tlsv1_client.h
    wpasupplicant/trunk/src/tls/tlsv1_common.c
    wpasupplicant/trunk/src/tls/tlsv1_common.h
    wpasupplicant/trunk/src/tls/x509v3.c
    wpasupplicant/trunk/src/utils/common.h
    wpasupplicant/trunk/src/utils/os_unix.c
    wpasupplicant/trunk/wpa_supplicant/ChangeLog
    wpasupplicant/trunk/wpa_supplicant/Makefile
    wpasupplicant/trunk/wpa_supplicant/config.c
    wpasupplicant/trunk/wpa_supplicant/config_ssid.h
    wpasupplicant/trunk/wpa_supplicant/ctrl_iface.c
    wpasupplicant/trunk/wpa_supplicant/doc/ctrl_iface.doxygen
    wpasupplicant/trunk/wpa_supplicant/doc/docbook/wpa_cli.sgml
    wpasupplicant/trunk/wpa_supplicant/eap_testing.txt
    wpasupplicant/trunk/wpa_supplicant/eapol_test.c
    wpasupplicant/trunk/wpa_supplicant/events.c
    wpasupplicant/trunk/wpa_supplicant/mlme.c
    wpasupplicant/trunk/wpa_supplicant/tests/test_aes.c
    wpasupplicant/trunk/wpa_supplicant/tests/test_x509v3.c
    wpasupplicant/trunk/wpa_supplicant/todo.txt
    wpasupplicant/trunk/wpa_supplicant/wpa_cli.c
    wpasupplicant/trunk/wpa_supplicant/wpa_supplicant.c
    wpasupplicant/trunk/wpa_supplicant/wpa_supplicant.conf
    wpasupplicant/trunk/wpa_supplicant/wpa_supplicant_i.h

Modified: wpasupplicant/trunk/debian/changelog
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/debian/changelog?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/debian/changelog (original)
+++ wpasupplicant/trunk/debian/changelog Sat Nov  3 11:46:49 2007
@@ -1,5 +1,6 @@
-wpasupplicant (0.6.0-5) UNRELEASED; urgency=low
-
+wpasupplicant (0.6.1~git20071103-1) UNRELEASED; urgency=low
+
+  * New upstream git snapshot.
   * Convert to non-cdbs traditional debhelper-centric debian/rules and remove
     build dependency on cdbs. This converges with style of hostapd package.
   * Correct poorly formatted debian/NEWS entry that was causing lintian to
@@ -23,8 +24,12 @@
     /usr/share/dbus-1/system-service/. The filename reflects the service bus
     name of "fi.epitest.hostap.WPASupplicant". In addition, the service must
     be started by root user. Thanks to Michael Biebl. (Closes: #412179)
-
- -- Kel Modderman <kel at otaku42.de>  Sat, 03 Nov 2007 17:03:52 +1000
+  * Build depend on docbook and docbook-utils to generate upstream manpages
+    from sgml source.a
+  * Upstream wpa_cli(8) is no longer incorrect with regard to CONNECTED and
+    DISCONNECTED signal events. (Closes: #432904)
+
+ -- Kel Modderman <kel at otaku42.de>  Sat, 03 Nov 2007 20:39:25 +1000
 
 wpasupplicant (0.6.0-4) unstable; urgency=low
 

Modified: wpasupplicant/trunk/debian/control
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/debian/control?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/debian/control (original)
+++ wpasupplicant/trunk/debian/control Sat Nov  3 11:46:49 2007
@@ -4,7 +4,7 @@
 Maintainer: Debian/Ubuntu wpasupplicant Maintainers <pkg-wpa-devel at lists.alioth.debian.org>
 Uploaders: Kyle McMartin <kyle at debian.org>, Reinhard Tartler <siretart at tauware.de>, Kel Modderman <kel at otaku42.de>
 Standards-Version: 3.7.2
-Build-Depends: debhelper (>= 5), dpatch, libssl-dev, libreadline5-dev, libqt4-dev, libdbus-1-dev (>= 1.1.1-1)
+Build-Depends: debhelper (>= 5), dpatch, libssl-dev, libreadline5-dev, libqt4-dev, libdbus-1-dev (>= 1.1.1-1), docbook, docbook-utils
 Vcs-Svn: svn://svn.debian.org/pkg-wpa/wpasupplicant/trunk
 Vcs-Browser: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/
 Homepage: http://w1.fi/wpa_supplicant/

Modified: wpasupplicant/trunk/debian/patches/00list
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/debian/patches/00list?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/debian/patches/00list (original)
+++ wpasupplicant/trunk/debian/patches/00list Sat Nov  3 11:46:49 2007
@@ -1,7 +1,4 @@
-10_fix_non_wpa_zero_len_ssid
 20_madwifi_headers
 30_dbus_policy
-40_debian_doc_examples
-50_fix_wext_tsf_stack_overflow
 60_dbus_deprecated_get_fd
 70_fix_deprecated_conversion_of_string_constant

Modified: wpasupplicant/trunk/debian/rules
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/debian/rules?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/debian/rules (original)
+++ wpasupplicant/trunk/debian/rules Sat Nov  3 11:46:49 2007
@@ -27,6 +27,9 @@
 	$(MAKE) -f debian/defconfig.mk DOTCONFIG=wpa_supplicant/.config
 	$(MAKE) -C wpa_supplicant
 	
+	# manpages - docbook2man
+	$(MAKE) -C wpa_supplicant/doc/docbook man
+	
 	# sanitise the example configuration
 	sed 's/^\([^#]\+=.*\|}\)/#\1/' < wpa_supplicant/wpa_supplicant.conf \
 		> README.wpa_supplicant.conf
@@ -43,6 +46,8 @@
 	rm -f build-stamp
 	
 	$(MAKE) -C wpa_supplicant clean
+	
+	$(MAKE) -C wpa_supplicant/doc/docbook clean
 	
 	if [ -f wpa_supplicant/$(WPAGUI)/Makefile ]; then \
 		$(MAKE) -C wpa_supplicant/$(WPAGUI) distclean ; \

Modified: wpasupplicant/trunk/src/common/defs.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/common/defs.h?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/src/common/defs.h (original)
+++ wpasupplicant/trunk/src/common/defs.h Sat Nov  3 11:46:49 2007
@@ -50,7 +50,7 @@
 
 
 typedef enum { WPA_ALG_NONE, WPA_ALG_WEP, WPA_ALG_TKIP, WPA_ALG_CCMP,
-	       WPA_ALG_IGTK } wpa_alg;
+	       WPA_ALG_IGTK, WPA_ALG_PMK } 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,

Modified: wpasupplicant/trunk/src/common/wpa_common.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/common/wpa_common.c?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/src/common/wpa_common.c (original)
+++ wpasupplicant/trunk/src/common/wpa_common.c Sat Nov  3 11:46:49 2007
@@ -396,7 +396,7 @@
 /**
  * wpa_derive_pmk_r0 - Derive PMK-R0 and PMKR0Name
  *
- * IEEE 802.11r/D5.0 - 8.5.1.5.3
+ * IEEE 802.11r/D8.0 - 8.5.1.5.3
  */
 void wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len,
 		       const u8 *ssid, size_t ssid_len,
@@ -410,7 +410,7 @@
 	size_t len[2];
 
 	/*
-	 * R0-Key-Data = KDF-384(XXKey, "R0 Key Derivation",
+	 * R0-Key-Data = KDF-384(XXKey, "FT-R0",
 	 *                       SSIDlength || SSID || MDID || R0KHlength ||
 	 *                       R0KH-ID || S0KH-ID)
 	 * XXKey is either the second 256 bits of MSK or PSK.
@@ -431,15 +431,15 @@
 	os_memcpy(pos, s0kh_id, ETH_ALEN);
 	pos += ETH_ALEN;
 
-	sha256_prf(xxkey, xxkey_len, "R0 Key Derivation", buf, pos - buf,
+	sha256_prf(xxkey, xxkey_len, "FT-R0", buf, pos - buf,
 		   r0_key_data, sizeof(r0_key_data));
 	os_memcpy(pmk_r0, r0_key_data, PMK_LEN);
 
 	/*
-	 * PMKR0Name = Truncate-128(SHA-256("R0 Key Name" || PMK-R0Name-Salt)
+	 * PMKR0Name = Truncate-128(SHA-256("FT-R0" || PMK-R0Name-Salt)
 	 */
-	addr[0] = (const u8 *) "R0 Key Name";
-	len[0] = 11;
+	addr[0] = (const u8 *) "FT-R0";
+	len[0] = 5;
 	addr[1] = r0_key_data + PMK_LEN;
 	len[1] = 16;
 
@@ -451,7 +451,7 @@
 /**
  * wpa_derive_pmk_r1_name - Derive PMKR1Name
  *
- * IEEE 802.11r/D5.0 - 8.5.1.5.4
+ * IEEE 802.11r/D8.0 - 8.5.1.5.4
  */
 void wpa_derive_pmk_r1_name(const u8 *pmk_r0_name, const u8 *r1kh_id,
 			    const u8 *s1kh_id, u8 *pmk_r1_name)
@@ -461,11 +461,11 @@
 	size_t len[4];
 
 	/*
-	 * PMKR1Name = Truncate-128(SHA-256("R1 Key Name" || PMKR0Name ||
+	 * PMKR1Name = Truncate-128(SHA-256("FT-R1" || PMKR0Name ||
 	 *                                  R1KH-ID || S1KH-ID))
 	 */
-	addr[0] = (const u8 *) "R1 Key Name";
-	len[0] = 11;
+	addr[0] = (const u8 *) "FT-R1";
+	len[0] = 5;
 	addr[1] = pmk_r0_name;
 	len[1] = WPA_PMK_NAME_LEN;
 	addr[2] = r1kh_id;
@@ -481,7 +481,7 @@
 /**
  * wpa_derive_pmk_r1 - Derive PMK-R1 and PMKR1Name from PMK-R0
  *
- * IEEE 802.11r/D5.0 - 8.5.1.5.4
+ * IEEE 802.11r/D8.0 - 8.5.1.5.4
  */
 void wpa_derive_pmk_r1(const u8 *pmk_r0, const u8 *pmk_r0_name,
 		       const u8 *r1kh_id, const u8 *s1kh_id,
@@ -490,15 +490,14 @@
 	u8 buf[FT_R1KH_ID_LEN + ETH_ALEN];
 	u8 *pos;
 
-	/* PMK-R1 = KDF-256(PMK-R0, "R1 Key Derivation", R1KH-ID || S1KH-ID) */
+	/* PMK-R1 = KDF-256(PMK-R0, "FT-R1", R1KH-ID || S1KH-ID) */
 	pos = buf;
 	os_memcpy(pos, r1kh_id, FT_R1KH_ID_LEN);
 	pos += FT_R1KH_ID_LEN;
 	os_memcpy(pos, s1kh_id, ETH_ALEN);
 	pos += ETH_ALEN;
 
-	sha256_prf(pmk_r0, PMK_LEN, "R1 Key Derivation", buf, pos - buf,
-		   pmk_r1, PMK_LEN);
+	sha256_prf(pmk_r0, PMK_LEN, "FT-R1", buf, pos - buf, pmk_r1, PMK_LEN);
 
 	wpa_derive_pmk_r1_name(pmk_r0_name, r1kh_id, s1kh_id, pmk_r1_name);
 }
@@ -507,7 +506,7 @@
 /**
  * wpa_pmk_r1_to_ptk - Derive PTK and PTKName from PMK-R1
  *
- * IEEE 802.11r/D5.0 - 8.5.1.5.5
+ * IEEE 802.11r/D8.0 - 8.5.1.5.5
  */
 void wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce,
 		       const u8 *sta_addr, const u8 *bssid,
@@ -520,7 +519,7 @@
 	size_t len[6];
 
 	/*
-	 * PTK = KDF-PTKLen(PMK-R1, "PTK Key derivation", SNonce || ANonce ||
+	 * PTK = KDF-PTKLen(PMK-R1, "FT-PTK", SNonce || ANonce ||
 	 *                  BSSID || STA-ADDR)
 	 */
 	pos = buf;
@@ -533,17 +532,16 @@
 	os_memcpy(pos, sta_addr, ETH_ALEN);
 	pos += ETH_ALEN;
 
-	sha256_prf(pmk_r1, PMK_LEN, "PTK Key derivation", buf, pos - buf,
-		   ptk, ptk_len);
+	sha256_prf(pmk_r1, PMK_LEN, "FT-PTK", buf, pos - buf, ptk, ptk_len);
 
 	/*
-	 * PTKName = Truncate-128(SHA-256(PMKR1Name || "PTK Name" || SNonce ||
+	 * PTKName = Truncate-128(SHA-256(PMKR1Name || "FT-PTK" || SNonce ||
 	 *                                ANonce || BSSID || STA-ADDR))
 	 */
 	addr[0] = pmk_r1_name;
 	len[0] = WPA_PMK_NAME_LEN;
-	addr[1] = (const u8 *) "PTK Name";
-	len[1] = 8;
+	addr[1] = (const u8 *) "FT-PTK";
+	len[1] = 6;
 	addr[2] = snonce;
 	len[2] = WPA_NONCE_LEN;
 	addr[3] = anonce;

Modified: wpasupplicant/trunk/src/common/wpa_common.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/common/wpa_common.h?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/src/common/wpa_common.h (original)
+++ wpasupplicant/trunk/src/common/wpa_common.h Sat Nov  3 11:46:49 2007
@@ -281,9 +281,8 @@
 	u8 ft_capab;
 } STRUCT_PACKED;
 
-#define RSN_FT_CAPAB_FT_OVER_AIR BIT(0)
-#define RSN_FT_CAPAB_FT_OVER_DS BIT(1)
-#define RSN_FT_CAPAB_FT_RESOURCE_REQ_SUPP BIT(2)
+#define RSN_FT_CAPAB_FT_OVER_DS BIT(0)
+#define RSN_FT_CAPAB_FT_RESOURCE_REQ_SUPP BIT(1)
 
 struct rsn_ftie {
 	u8 mic_control[2];

Modified: wpasupplicant/trunk/src/crypto/aes_wrap.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/crypto/aes_wrap.c?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/src/crypto/aes_wrap.c (original)
+++ wpasupplicant/trunk/src/crypto/aes_wrap.c Sat Nov  3 11:46:49 2007
@@ -7,7 +7,7 @@
  * - AES-128 EAX mode encryption/decryption
  * - AES-128 CBC
  *
- * Copyright (c) 2003-2006, Jouni Malinen <j at w1.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
@@ -29,10 +29,11 @@
 
 /**
  * aes_wrap - Wrap keys with AES Key Wrap Algorithm (128-bit KEK) (RFC3394)
- * @kek: Key encryption key (KEK)
- * @n: Length of the wrapped key in 64-bit units; e.g., 2 = 128-bit = 16 bytes
- * @plain: Plaintext key to be wrapped, n * 64 bit
- * @cipher: Wrapped key, (n + 1) * 64 bit
+ * @kek: 16-octet Key encryption key (KEK)
+ * @n: Length of the plaintext key in 64-bit units; e.g., 2 = 128-bit = 16
+ * bytes
+ * @plain: Plaintext key to be wrapped, n * 64 bits
+ * @cipher: Wrapped key, (n + 1) * 64 bits
  * Returns: 0 on success, -1 on failure
  */
 int aes_wrap(const u8 *kek, int n, const u8 *plain, u8 *cipher)
@@ -88,9 +89,10 @@
 /**
  * aes_unwrap - Unwrap key with AES Key Wrap Algorithm (128-bit KEK) (RFC3394)
  * @kek: Key encryption key (KEK)
- * @n: Length of the wrapped key in 64-bit units; e.g., 2 = 128-bit = 16 bytes
- * @cipher: Wrapped key to be unwrapped, (n + 1) * 64 bit
- * @plain: Plaintext key, n * 64 bit
+ * @n: Length of the plaintext key in 64-bit units; e.g., 2 = 128-bit = 16
+ * bytes
+ * @cipher: Wrapped key to be unwrapped, (n + 1) * 64 bits
+ * @plain: Plaintext key, n * 64 bits
  * Returns: 0 on success, -1 on failure (e.g., integrity verification failed)
  */
 int aes_unwrap(const u8 *kek, int n, const u8 *cipher, u8 *plain)
@@ -162,10 +164,11 @@
 
 
 /**
- * omac1_aes_128 - One-Key CBC MAC (OMAC1) hash with AES-128 (aka AES-CMAC)
+ * omac1_aes_128_vector - One-Key CBC MAC (OMAC1) hash with AES-128
  * @key: 128-bit key for the hash operation
- * @data: Data buffer for which a MAC is determined
- * @data: Length of data buffer in bytes
+ * @num_elem: Number of elements in the data vector
+ * @addr: Pointers to the data areas
+ * @len: Lengths of the data blocks
  * @mac: Buffer for MAC (128 bits, i.e., 16 bytes)
  * Returns: 0 on success, -1 on failure
  *
@@ -173,21 +176,37 @@
  * OMAC1 was standardized with the name CMAC by NIST in a Special Publication
  * (SP) 800-38B.
  */
-int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
+int omac1_aes_128_vector(const u8 *key, size_t num_elem,
+			 const u8 *addr[], const size_t *len, u8 *mac)
 {
 	void *ctx;
 	u8 cbc[BLOCK_SIZE], pad[BLOCK_SIZE];
-	const u8 *pos = data;
-	size_t i, left = data_len;
+	const u8 *pos, *end;
+	size_t i, e, left, total_len;
 
 	ctx = aes_encrypt_init(key, 16);
 	if (ctx == NULL)
 		return -1;
 	os_memset(cbc, 0, BLOCK_SIZE);
 
+	total_len = 0;
+	for (e = 0; e < num_elem; e++)
+		total_len += len[e];
+	left = total_len;
+
+	e = 0;
+	pos = addr[0];
+	end = pos + len[0];
+
 	while (left >= BLOCK_SIZE) {
-		for (i = 0; i < BLOCK_SIZE; i++)
+		for (i = 0; i < BLOCK_SIZE; i++) {
 			cbc[i] ^= *pos++;
+			if (pos >= end) {
+				e++;
+				pos = addr[e];
+				end = pos + len[e];
+			}
+		}
 		if (left > BLOCK_SIZE)
 			aes_encrypt(ctx, cbc, cbc);
 		left -= BLOCK_SIZE;
@@ -197,9 +216,15 @@
 	aes_encrypt(ctx, pad, pad);
 	gf_mulx(pad);
 
-	if (left || data_len == 0) {
-		for (i = 0; i < left; i++)
+	if (left || total_len == 0) {
+		for (i = 0; i < left; i++) {
 			cbc[i] ^= *pos++;
+			if (pos >= end) {
+				e++;
+				pos = addr[e];
+				end = pos + len[e];
+			}
+		}
 		cbc[left] ^= 0x80;
 		gf_mulx(pad);
 	}
@@ -209,6 +234,24 @@
 	aes_encrypt(ctx, pad, mac);
 	aes_encrypt_deinit(ctx);
 	return 0;
+}
+
+
+/**
+ * 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_len: Length of data buffer in bytes
+ * @mac: Buffer for MAC (128 bits, i.e., 16 bytes)
+ * Returns: 0 on success, -1 on failure
+ *
+ * This is a mode for using block cipher (AES in this case) for authentication.
+ * OMAC1 was standardized with the name CMAC by NIST in a Special Publication
+ * (SP) 800-38B.
+ */
+int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
+{
+	return omac1_aes_128_vector(key, 1, &data, &data_len, mac);
 }
 
 #endif /* CONFIG_NO_AES_OMAC1 */

Modified: wpasupplicant/trunk/src/crypto/aes_wrap.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/crypto/aes_wrap.h?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/src/crypto/aes_wrap.h (original)
+++ wpasupplicant/trunk/src/crypto/aes_wrap.h Sat Nov  3 11:46:49 2007
@@ -7,7 +7,7 @@
  * - AES-128 EAX mode encryption/decryption
  * - AES-128 CBC
  *
- * Copyright (c) 2003-2005, Jouni Malinen <j at w1.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
@@ -24,6 +24,8 @@
 
 int aes_wrap(const u8 *kek, int n, const u8 *plain, u8 *cipher);
 int aes_unwrap(const u8 *kek, int n, const u8 *cipher, u8 *plain);
+int omac1_aes_128_vector(const u8 *key, size_t num_elem,
+			 const u8 *addr[], const size_t *len, u8 *mac);
 int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac);
 int aes_128_encrypt_block(const u8 *key, const u8 *in, u8 *out);
 int aes_128_ctr_encrypt(const u8 *key, const u8 *nonce,

Modified: wpasupplicant/trunk/src/crypto/crypto.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/crypto/crypto.h?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/src/crypto/crypto.h (original)
+++ wpasupplicant/trunk/src/crypto/crypto.h Sat Nov  3 11:46:49 2007
@@ -316,6 +316,23 @@
 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_decrypt_pkcs1_v15 - Private key decryption (PKCS #1 v1.5)
+ * @key: Private key
+ * @in: Encrypted buffer
+ * @inlen: Length of encrypted 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_private_key_decrypt_pkcs1_v15(struct crypto_private_key *key,
+					 const u8 *in, size_t inlen,
+					 u8 *out, size_t *outlen);
 
 /**
  * crypto_private_key_sign_pkcs1 - Sign with private key (PKCS #1)

Modified: wpasupplicant/trunk/src/crypto/crypto_internal.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/crypto/crypto_internal.c?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/src/crypto/crypto_internal.c (original)
+++ wpasupplicant/trunk/src/crypto/crypto_internal.c Sat Nov  3 11:46:49 2007
@@ -539,6 +539,39 @@
 }
 
 
+int crypto_private_key_decrypt_pkcs1_v15(struct crypto_private_key *key,
+					 const u8 *in, size_t inlen,
+					 u8 *out, size_t *outlen)
+{
+	struct crypto_rsa_key *rkey = (struct crypto_rsa_key *) key;
+	int res;
+	u8 *pos, *end;
+
+	res = crypto_rsa_exptmod(in, inlen, out, outlen, rkey, 1);
+	if (res)
+		return res;
+
+	if (*outlen < 2 || out[0] != 0 || out[1] != 2)
+		return -1;
+
+	/* Skip PS (pseudorandom non-zero octets) */
+	pos = out + 2;
+	end = out + *outlen;
+	while (*pos && pos < end)
+		pos++;
+	if (pos == end)
+		return -1;
+	pos++;
+
+	*outlen -= pos - out;
+
+	/* Strip PKCS #1 header */
+	os_memmove(out, pos, *outlen);
+
+	return 0;
+}
+
+
 int crypto_private_key_sign_pkcs1(struct crypto_private_key *key,
 				  const u8 *in, size_t inlen,
 				  u8 *out, size_t *outlen)
@@ -576,21 +609,39 @@
 	 * PKCS #1 v1.5, 8.1:
 	 *
 	 * EB = 00 || BT || PS || 00 || D
-	 * BT = 01
-	 * PS = k-3-||D|| times FF
+	 * BT = 00 or 01
+	 * PS = k-3-||D|| times (00 if BT=00) or (FF if BT=01)
 	 * k = length of modulus in octets
 	 */
 
 	if (len < 3 + 8 + 16 /* min hash len */ ||
-	    plain[0] != 0x00 || plain[1] != 0x01 || plain[2] != 0xff) {
+	    plain[0] != 0x00 || (plain[1] != 0x00 && plain[1] != 0x01)) {
 		wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB "
 			   "structure");
 		return -1;
 	}
 
 	pos = plain + 3;
-	while (pos < plain + len && *pos == 0xff)
-		pos++;
+	if (plain[1] == 0x00) {
+		/* BT = 00 */
+		if (plain[2] != 0x00) {
+			wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature "
+				   "PS (BT=00)");
+			return -1;
+		}
+		while (pos + 1 < plain + len && *pos == 0x00 && pos[1] == 0x00)
+			pos++;
+	} else {
+		/* BT = 01 */
+		if (plain[2] != 0xff) {
+			wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature "
+				   "PS (BT=01)");
+			return -1;
+		}
+		while (pos < plain + len && *pos == 0xff)
+			pos++;
+	}
+
 	if (pos - plain - 2 < 8) {
 		/* PKCS #1 v1.5, 8.1: At least eight octets long PS */
 		wpa_printf(MSG_INFO, "LibTomCrypt: Too short signature "

Modified: wpasupplicant/trunk/src/crypto/ms_funcs.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/crypto/ms_funcs.c?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/src/crypto/ms_funcs.c (original)
+++ wpasupplicant/trunk/src/crypto/ms_funcs.c Sat Nov  3 11:46:49 2007
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant / shared MSCHAPV2 helper functions / RFC 2433 / RFC 2759
- * Copyright (c) 2004-2006, Jouni Malinen <j at w1.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
@@ -411,9 +411,8 @@
  * @block: 16-octet Block (IN)
  * @cypher: 16-octer Cypher (OUT)
  */
-static void nt_password_hash_encrypted_with_block(const u8 *password_hash,
-						  const u8 *block,
-						  u8 *cypher)
+void nt_password_hash_encrypted_with_block(const u8 *password_hash,
+					   const u8 *block, u8 *cypher)
 {
 	des_encrypt(password_hash, block, cypher);
 	des_encrypt(password_hash + 8, block + 7, cypher + 8);

Modified: wpasupplicant/trunk/src/crypto/ms_funcs.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/crypto/ms_funcs.h?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/src/crypto/ms_funcs.h (original)
+++ wpasupplicant/trunk/src/crypto/ms_funcs.h Sat Nov  3 11:46:49 2007
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant / shared MSCHAPV2 helper functions / RFC 2433 / RFC 2759
- * Copyright (c) 2004-2005, Jouni Malinen <j at w1.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
@@ -47,10 +47,15 @@
 void get_asymetric_start_key(const u8 *master_key, u8 *session_key,
 			     size_t session_key_len, int is_send,
 			     int is_server);
+int encrypt_pw_block_with_password_hash(
+	const u8 *password, size_t password_len,
+	const u8 *password_hash, u8 *pw_block);
 void new_password_encrypted_with_old_nt_password_hash(
 	const u8 *new_password, size_t new_password_len,
 	const u8 *old_password, size_t old_password_len,
 	u8 *encrypted_pw_block);
+void nt_password_hash_encrypted_with_block(const u8 *password_hash,
+					   const u8 *block, u8 *cypher);
 void old_nt_password_hash_encrypted_with_new_nt_password_hash(
 	const u8 *new_password, size_t new_password_len,
 	const u8 *old_password, size_t old_password_len,

Modified: wpasupplicant/trunk/src/crypto/sha256.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/crypto/sha256.c?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/src/crypto/sha256.c (original)
+++ wpasupplicant/trunk/src/crypto/sha256.c Sat Nov  3 11:46:49 2007
@@ -107,7 +107,7 @@
 
 
 /**
- * sha256_prf - SHA256-based Pseudo-Random Function (IEEE 802.11r, 8.5a.3)
+ * sha256_prf - SHA256-based Pseudo-Random Function (IEEE 802.11r, 8.5.1.5.2)
  * @key: Key for PRF
  * @key_len: Length of the key in bytes
  * @label: A unique label for each purpose of the PRF
@@ -132,7 +132,7 @@
 	addr[0] = counter_le;
 	len[0] = 2;
 	addr[1] = (u8 *) label;
-	len[1] = os_strlen(label) + 1;
+	len[1] = os_strlen(label);
 	addr[2] = data;
 	len[2] = data_len;
 	addr[3] = length_le;

Modified: wpasupplicant/trunk/src/crypto/tls.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/crypto/tls.h?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/src/crypto/tls.h (original)
+++ wpasupplicant/trunk/src/crypto/tls.h Sat Nov  3 11:46:49 2007
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant / SSL/TLS interface definition
- * Copyright (c) 2004-2006, Jouni Malinen <j at w1.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
@@ -364,17 +364,6 @@
  */
 int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn);
 
-/**
- * tls_connection_set_master_key - Configure master secret for TLS connection
- * @tls_ctx: TLS context data from tls_init()
- * @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 */,
@@ -518,4 +507,13 @@
 					   struct tls_connection *conn,
 					   const u8 *key, size_t key_len);
 
+typedef int (*tls_session_ticket_cb)
+(void *ctx, const u8 *ticket, size_t len, const u8 *client_random,
+ const u8 *server_random, u8 *master_secret);
+
+int tls_connection_set_session_ticket_cb(void *tls_ctx,
+					 struct tls_connection *conn,
+					 tls_session_ticket_cb cb,
+					 void *ctx);
+
 #endif /* TLS_H */

Modified: wpasupplicant/trunk/src/crypto/tls_gnutls.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/crypto/tls_gnutls.c?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/src/crypto/tls_gnutls.c (original)
+++ wpasupplicant/trunk/src/crypto/tls_gnutls.c Sat Nov  3 11:46:49 2007
@@ -1157,14 +1157,6 @@
 }
 
 
-int tls_connection_set_master_key(void *ssl_ctx, struct tls_connection *conn,
-				  const u8 *key, size_t key_len)
-{
-	/* TODO */
-	return -1;
-}
-
-
 int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
 				   u8 *ciphers)
 {

Modified: wpasupplicant/trunk/src/crypto/tls_internal.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/crypto/tls_internal.c?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/src/crypto/tls_internal.c (original)
+++ wpasupplicant/trunk/src/crypto/tls_internal.c Sat Nov  3 11:46:49 2007
@@ -20,16 +20,20 @@
 #include "common.h"
 #include "tls.h"
 #include "tls/tlsv1_client.h"
+#include "tls/tlsv1_server.h"
 
 
 static int tls_ref_count = 0;
 
 struct tls_global {
-	int dummy;
+	int server;
+	struct tlsv1_credentials *server_cred;
+	int check_crl;
 };
 
 struct tls_connection {
 	struct tlsv1_client *client;
+	struct tlsv1_server *server;
 };
 
 
@@ -38,8 +42,14 @@
 	struct tls_global *global;
 
 	if (tls_ref_count == 0) {
+#ifdef CONFIG_TLS_INTERNAL_CLIENT
 		if (tlsv1_client_global_init())
 			return NULL;
+#endif /* CONFIG_TLS_INTERNAL_CLIENT */
+#ifdef CONFIG_TLS_INTERNAL_SERVER
+		if (tlsv1_server_global_init())
+			return NULL;
+#endif /* CONFIG_TLS_INTERNAL_SERVER */
 	}
 	tls_ref_count++;
 
@@ -55,7 +65,13 @@
 	struct tls_global *global = ssl_ctx;
 	tls_ref_count--;
 	if (tls_ref_count == 0) {
+#ifdef CONFIG_TLS_INTERNAL_CLIENT
 		tlsv1_client_global_deinit();
+#endif /* CONFIG_TLS_INTERNAL_CLIENT */
+#ifdef CONFIG_TLS_INTERNAL_SERVER
+		tlsv1_cred_free(global->server_cred);
+		tlsv1_server_global_deinit();
+#endif /* CONFIG_TLS_INTERNAL_SERVER */
 	}
 	os_free(global);
 }
@@ -70,16 +86,30 @@
 struct tls_connection * tls_connection_init(void *tls_ctx)
 {
 	struct tls_connection *conn;
+	struct tls_global *global = tls_ctx;
 
 	conn = os_zalloc(sizeof(*conn));
 	if (conn == NULL)
 		return NULL;
 
-	conn->client = tlsv1_client_init();
-	if (conn->client == NULL) {
-		os_free(conn);
-		return NULL;
-	}
+#ifdef CONFIG_TLS_INTERNAL_CLIENT
+	if (!global->server) {
+		conn->client = tlsv1_client_init();
+		if (conn->client == NULL) {
+			os_free(conn);
+			return NULL;
+		}
+	}
+#endif /* CONFIG_TLS_INTERNAL_CLIENT */
+#ifdef CONFIG_TLS_INTERNAL_SERVER
+	if (global->server) {
+		conn->server = tlsv1_server_init(global->server_cred);
+		if (conn->server == NULL) {
+			os_free(conn);
+			return NULL;
+		}
+	}
+#endif /* CONFIG_TLS_INTERNAL_SERVER */
 
 	return conn;
 }
@@ -89,74 +119,170 @@
 {
 	if (conn == NULL)
 		return;
-	tlsv1_client_deinit(conn->client);
+#ifdef CONFIG_TLS_INTERNAL_CLIENT
+	if (conn->client)
+		tlsv1_client_deinit(conn->client);
+#endif /* CONFIG_TLS_INTERNAL_CLIENT */
+#ifdef CONFIG_TLS_INTERNAL_SERVER
+	if (conn->server)
+		tlsv1_server_deinit(conn->server);
+#endif /* CONFIG_TLS_INTERNAL_SERVER */
 	os_free(conn);
 }
 
 
 int tls_connection_established(void *tls_ctx, struct tls_connection *conn)
 {
-	return tlsv1_client_established(conn->client);
+#ifdef CONFIG_TLS_INTERNAL_CLIENT
+	if (conn->client)
+		return tlsv1_client_established(conn->client);
+#endif /* CONFIG_TLS_INTERNAL_CLIENT */
+#ifdef CONFIG_TLS_INTERNAL_SERVER
+	if (conn->server)
+		return tlsv1_server_established(conn->server);
+#endif /* CONFIG_TLS_INTERNAL_SERVER */
+	return 0;
 }
 
 
 int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn)
 {
-	return tlsv1_client_shutdown(conn->client);
+#ifdef CONFIG_TLS_INTERNAL_CLIENT
+	if (conn->client)
+		return tlsv1_client_shutdown(conn->client);
+#endif /* CONFIG_TLS_INTERNAL_CLIENT */
+#ifdef CONFIG_TLS_INTERNAL_SERVER
+	if (conn->server)
+		return tlsv1_server_shutdown(conn->server);
+#endif /* CONFIG_TLS_INTERNAL_SERVER */
+	return -1;
 }
 
 
 int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
 			      const struct tls_connection_params *params)
 {
-	if (tlsv1_client_set_ca_cert(conn->client, params->ca_cert,
-				     params->ca_cert_blob,
-				     params->ca_cert_blob_len,
-				     params->ca_path)) {
+#ifdef CONFIG_TLS_INTERNAL_CLIENT
+	struct tlsv1_credentials *cred;
+
+	if (conn->client == NULL)
+		return -1;
+
+	cred = tlsv1_cred_alloc();
+	if (cred == NULL)
+		return -1;
+
+	if (tlsv1_set_ca_cert(cred, params->ca_cert,
+			      params->ca_cert_blob, params->ca_cert_blob_len,
+			      params->ca_path)) {
 		wpa_printf(MSG_INFO, "TLS: Failed to configure trusted CA "
 			   "certificates");
-		return -1;
-	}
-
-	if (tlsv1_client_set_client_cert(conn->client, params->client_cert,
-					 params->client_cert_blob,
-					 params->client_cert_blob_len)) {
+		tlsv1_cred_free(cred);
+		return -1;
+	}
+
+	if (tlsv1_set_cert(cred, params->client_cert,
+			   params->client_cert_blob,
+			   params->client_cert_blob_len)) {
 		wpa_printf(MSG_INFO, "TLS: Failed to configure client "
 			   "certificate");
-		return -1;
-	}
-
-	if (tlsv1_client_set_private_key(conn->client,
-					 params->private_key,
-					 params->private_key_passwd,
-					 params->private_key_blob,
-					 params->private_key_blob_len)) {
+		tlsv1_cred_free(cred);
+		return -1;
+	}
+
+	if (tlsv1_set_private_key(cred, params->private_key,
+				  params->private_key_passwd,
+				  params->private_key_blob,
+				  params->private_key_blob_len)) {
 		wpa_printf(MSG_INFO, "TLS: Failed to load private key");
-		return -1;
-	}
-
-	return 0;
+		tlsv1_cred_free(cred);
+		return -1;
+	}
+
+	if (tlsv1_set_dhparams(cred, params->dh_file, params->dh_blob,
+			       params->dh_blob_len)) {
+		wpa_printf(MSG_INFO, "TLS: Failed to load DH parameters");
+		tlsv1_cred_free(cred);
+		return -1;
+	}
+
+	if (tlsv1_client_set_cred(conn->client, cred) < 0) {
+		tlsv1_cred_free(cred);
+		return -1;
+	}
+
+	return 0;
+#else /* CONFIG_TLS_INTERNAL_CLIENT */
+	return -1;
+#endif /* CONFIG_TLS_INTERNAL_CLIENT */
 }
 
 
 int tls_global_set_params(void *tls_ctx,
 			  const struct tls_connection_params *params)
 {
-	wpa_printf(MSG_INFO, "TLS: not implemented - %s", __func__);
-	return -1;
+#ifdef CONFIG_TLS_INTERNAL_SERVER
+	struct tls_global *global = tls_ctx;
+	struct tlsv1_credentials *cred;
+
+	/* Currently, global parameters are only set when running in server
+	 * mode. */
+	global->server = 1;
+	tlsv1_cred_free(global->server_cred);
+	global->server_cred = cred = tlsv1_cred_alloc();
+	if (cred == NULL)
+		return -1;
+
+	if (tlsv1_set_ca_cert(cred, params->ca_cert, params->ca_cert_blob,
+			      params->ca_cert_blob_len, params->ca_path)) {
+		wpa_printf(MSG_INFO, "TLS: Failed to configure trusted CA "
+			   "certificates");
+		return -1;
+	}
+
+	if (tlsv1_set_cert(cred, params->client_cert, params->client_cert_blob,
+			   params->client_cert_blob_len)) {
+		wpa_printf(MSG_INFO, "TLS: Failed to configure server "
+			   "certificate");
+		return -1;
+	}
+
+	if (tlsv1_set_private_key(cred, params->private_key,
+				  params->private_key_passwd,
+				  params->private_key_blob,
+				  params->private_key_blob_len)) {
+		wpa_printf(MSG_INFO, "TLS: Failed to load private key");
+		return -1;
+	}
+
+	if (tlsv1_set_dhparams(cred, params->dh_file, params->dh_blob,
+			       params->dh_blob_len)) {
+		wpa_printf(MSG_INFO, "TLS: Failed to load DH parameters");
+		return -1;
+	}
+
+	return 0;
+#else /* CONFIG_TLS_INTERNAL_SERVER */
+	return -1;
+#endif /* CONFIG_TLS_INTERNAL_SERVER */
 }
 
 
 int tls_global_set_verify(void *tls_ctx, int check_crl)
 {
-	wpa_printf(MSG_INFO, "TLS: not implemented - %s", __func__);
-	return -1;
+	struct tls_global *global = tls_ctx;
+	global->check_crl = check_crl;
+	return 0;
 }
 
 
 int tls_connection_set_verify(void *tls_ctx, struct tls_connection *conn,
 			      int verify_peer)
 {
+#ifdef CONFIG_TLS_INTERNAL_SERVER
+	if (conn->server)
+		return tlsv1_server_set_verify(conn->server, verify_peer);
+#endif /* CONFIG_TLS_INTERNAL_SERVER */
 	return -1;
 }
 
@@ -171,7 +297,15 @@
 int tls_connection_get_keys(void *tls_ctx, struct tls_connection *conn,
 			    struct tls_keys *keys)
 {
-	return tlsv1_client_get_keys(conn->client, keys);
+#ifdef CONFIG_TLS_INTERNAL_CLIENT
+	if (conn->client)
+		return tlsv1_client_get_keys(conn->client, keys);
+#endif /* CONFIG_TLS_INTERNAL_CLIENT */
+#ifdef CONFIG_TLS_INTERNAL_SERVER
+	if (conn->server)
+		return tlsv1_server_get_keys(conn->server, keys);
+#endif /* CONFIG_TLS_INTERNAL_SERVER */
+	return -1;
 }
 
 
@@ -179,8 +313,21 @@
 		       const char *label, int server_random_first,
 		       u8 *out, size_t out_len)
 {
-	return tlsv1_client_prf(conn->client, label, server_random_first,
-				out, out_len);
+#ifdef CONFIG_TLS_INTERNAL_CLIENT
+	if (conn->client) {
+		return tlsv1_client_prf(conn->client, label,
+					server_random_first,
+					out, out_len);
+	}
+#endif /* CONFIG_TLS_INTERNAL_CLIENT */
+#ifdef CONFIG_TLS_INTERNAL_SERVER
+	if (conn->server) {
+		return tlsv1_server_prf(conn->server, label,
+					server_random_first,
+					out, out_len);
+	}
+#endif /* CONFIG_TLS_INTERNAL_SERVER */
+	return -1;
 }
 
 
@@ -189,6 +336,10 @@
 			      size_t *out_len, u8 **appl_data,
 			      size_t *appl_data_len)
 {
+#ifdef CONFIG_TLS_INTERNAL_CLIENT
+	if (conn->client == NULL)
+		return NULL;
+
 	if (appl_data)
 		*appl_data = NULL;
 
@@ -196,6 +347,9 @@
 		   __func__, in_data, (unsigned long) in_len);
 	return tlsv1_client_handshake(conn->client, in_data, in_len, out_len,
 				      appl_data, appl_data_len);
+#else /* CONFIG_TLS_INTERNAL_CLIENT */
+	return NULL;
+#endif /* CONFIG_TLS_INTERNAL_CLIENT */
 }
 
 
@@ -204,8 +358,20 @@
 				     const u8 *in_data, size_t in_len,
 				     size_t *out_len)
 {
-	wpa_printf(MSG_INFO, "TLS: not implemented - %s", __func__);
+#ifdef CONFIG_TLS_INTERNAL_SERVER
+	u8 *out;
+	if (conn->server == NULL)
+		return NULL;
+
+	wpa_printf(MSG_DEBUG, "TLS: %s(in_data=%p in_len=%lu)",
+		   __func__, in_data, (unsigned long) in_len);
+	out = tlsv1_server_handshake(conn->server, in_data, in_len, out_len);
+	if (out == NULL && tlsv1_server_established(conn->server))
+		out = os_malloc(1);
+	return out;
+#else /* CONFIG_TLS_INTERNAL_SERVER */
 	return NULL;
+#endif /* CONFIG_TLS_INTERNAL_SERVER */
 }
 
 
@@ -213,8 +379,19 @@
 			   const u8 *in_data, size_t in_len,
 			   u8 *out_data, size_t out_len)
 {
-	return tlsv1_client_encrypt(conn->client, in_data, in_len, out_data,
-				    out_len);
+#ifdef CONFIG_TLS_INTERNAL_CLIENT
+	if (conn->client) {
+		return tlsv1_client_encrypt(conn->client, in_data, in_len,
+					    out_data, out_len);
+	}
+#endif /* CONFIG_TLS_INTERNAL_CLIENT */
+#ifdef CONFIG_TLS_INTERNAL_SERVER
+	if (conn->server) {
+		return tlsv1_server_encrypt(conn->server, in_data, in_len,
+					    out_data, out_len);
+	}
+#endif /* CONFIG_TLS_INTERNAL_SERVER */
+	return -1;
 }
 
 
@@ -222,28 +399,48 @@
 			   const u8 *in_data, size_t in_len,
 			   u8 *out_data, size_t out_len)
 {
-	return tlsv1_client_decrypt(conn->client, in_data, in_len, out_data,
-				    out_len);
+#ifdef CONFIG_TLS_INTERNAL_CLIENT
+	if (conn->client) {
+		return tlsv1_client_decrypt(conn->client, in_data, in_len,
+					    out_data, out_len);
+	}
+#endif /* CONFIG_TLS_INTERNAL_CLIENT */
+#ifdef CONFIG_TLS_INTERNAL_SERVER
+	if (conn->server) {
+		return tlsv1_server_decrypt(conn->server, in_data, in_len,
+					    out_data, out_len);
+	}
+#endif /* CONFIG_TLS_INTERNAL_SERVER */
+	return -1;
 }
 
 
 int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn)
 {
-	return tlsv1_client_resumed(conn->client);
-}
-
-
-int tls_connection_set_master_key(void *tls_ctx, struct tls_connection *conn,
-				  const u8 *key, size_t key_len)
-{
-	return tlsv1_client_set_master_key(conn->client, key, key_len);
+#ifdef CONFIG_TLS_INTERNAL_CLIENT
+	if (conn->client)
+		return tlsv1_client_resumed(conn->client);
+#endif /* CONFIG_TLS_INTERNAL_CLIENT */
+#ifdef CONFIG_TLS_INTERNAL_SERVER
+	if (conn->server)
+		return tlsv1_server_resumed(conn->server);
+#endif /* CONFIG_TLS_INTERNAL_SERVER */
+	return -1;
 }
 
 
 int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
 				   u8 *ciphers)
 {
-	return tlsv1_client_set_cipher_list(conn->client, ciphers);
+#ifdef CONFIG_TLS_INTERNAL_CLIENT
+	if (conn->client)
+		return tlsv1_client_set_cipher_list(conn->client, ciphers);
+#endif /* CONFIG_TLS_INTERNAL_CLIENT */
+#ifdef CONFIG_TLS_INTERNAL_SERVER
+	if (conn->server)
+		return tlsv1_server_set_cipher_list(conn->server, ciphers);
+#endif /* CONFIG_TLS_INTERNAL_SERVER */
+	return -1;
 }
 
 
@@ -252,7 +449,15 @@
 {
 	if (conn == NULL)
 		return -1;
-	return tlsv1_client_get_cipher(conn->client, buf, buflen);
+#ifdef CONFIG_TLS_INTERNAL_CLIENT
+	if (conn->client)
+		return tlsv1_client_get_cipher(conn->client, buf, buflen);
+#endif /* CONFIG_TLS_INTERNAL_CLIENT */
+#ifdef CONFIG_TLS_INTERNAL_SERVER
+	if (conn->server)
+		return tlsv1_server_get_cipher(conn->server, buf, buflen);
+#endif /* CONFIG_TLS_INTERNAL_SERVER */
+	return -1;
 }
 
 
@@ -267,7 +472,13 @@
 				    int ext_type, const u8 *data,
 				    size_t data_len)
 {
-	return tlsv1_client_hello_ext(conn->client, ext_type, data, data_len);
+#ifdef CONFIG_TLS_INTERNAL_CLIENT
+	if (conn->client) {
+		return tlsv1_client_hello_ext(conn->client, ext_type,
+					      data, data_len);
+	}
+#endif /* CONFIG_TLS_INTERNAL_CLIENT */
+	return -1;
 }
 
 
@@ -293,7 +504,15 @@
 int tls_connection_get_keyblock_size(void *tls_ctx,
 				     struct tls_connection *conn)
 {
-	return tlsv1_client_get_keyblock_size(conn->client);
+#ifdef CONFIG_TLS_INTERNAL_CLIENT
+	if (conn->client)
+		return tlsv1_client_get_keyblock_size(conn->client);
+#endif /* CONFIG_TLS_INTERNAL_CLIENT */
+#ifdef CONFIG_TLS_INTERNAL_SERVER
+	if (conn->server)
+		return tlsv1_server_get_keyblock_size(conn->server);
+#endif /* CONFIG_TLS_INTERNAL_SERVER */
+	return -1;
 }
 
 
@@ -325,3 +544,24 @@
 {
 	return -1;
 }
+
+
+int tls_connection_set_session_ticket_cb(void *tls_ctx,
+					 struct tls_connection *conn,
+					 tls_session_ticket_cb cb,
+					 void *ctx)
+{
+#ifdef CONFIG_TLS_INTERNAL_CLIENT
+	if (conn->client) {
+		tlsv1_client_set_session_ticket_cb(conn->client, cb, ctx);
+		return 0;
+	}
+#endif /* CONFIG_TLS_INTERNAL_CLIENT */
+#ifdef CONFIG_TLS_INTERNAL_SERVER
+	if (conn->server) {
+		tlsv1_server_set_session_ticket_cb(conn->server, cb, ctx);
+		return 0;
+	}
+#endif /* CONFIG_TLS_INTERNAL_SERVER */
+	return -1;
+}

Modified: wpasupplicant/trunk/src/crypto/tls_none.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/crypto/tls_none.c?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/src/crypto/tls_none.c (original)
+++ wpasupplicant/trunk/src/crypto/tls_none.c Sat Nov  3 11:46:49 2007
@@ -147,13 +147,6 @@
 }
 
 
-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)
 {

Modified: wpasupplicant/trunk/src/crypto/tls_openssl.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/crypto/tls_openssl.c?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/src/crypto/tls_openssl.c (original)
+++ wpasupplicant/trunk/src/crypto/tls_openssl.c Sat Nov  3 11:46:49 2007
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant / SSL/TLS interface functions for openssl
- * Copyright (c) 2004-2006, Jouni Malinen <j at w1.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
@@ -49,8 +49,12 @@
 	char *subject_match, *altsubject_match;
 	int read_alerts, write_alerts, failed;
 
-	u8 *pre_shared_secret;
-	size_t pre_shared_secret_len;
+	tls_session_ticket_cb session_ticket_cb;
+	void *session_ticket_cb_ctx;
+
+	/* SessionTicket received from OpenSSL hello_extension_cb (server) */
+	u8 *session_ticket;
+	size_t session_ticket_len;
 };
 
 
@@ -919,11 +923,11 @@
 {
 	if (conn == NULL)
 		return;
-	os_free(conn->pre_shared_secret);
 	SSL_free(conn->ssl);
 	tls_engine_deinit(conn);
 	os_free(conn->subject_match);
 	os_free(conn->altsubject_match);
+	os_free(conn->session_ticket);
 	os_free(conn);
 }
 
@@ -1760,6 +1764,80 @@
 }
 
 
+static int tls_global_dh(SSL_CTX *ssl_ctx, const char *dh_file)
+{
+#ifdef OPENSSL_NO_DH
+	if (dh_file == NULL)
+		return 0;
+	wpa_printf(MSG_ERROR, "TLS: openssl does not include DH support, but "
+		   "dh_file specified");
+	return -1;
+#else /* OPENSSL_NO_DH */
+	DH *dh;
+	BIO *bio;
+
+	/* TODO: add support for dh_blob */
+	if (dh_file == NULL)
+		return 0;
+	if (ssl_ctx == NULL)
+		return -1;
+
+	bio = BIO_new_file(dh_file, "r");
+	if (bio == NULL) {
+		wpa_printf(MSG_INFO, "TLS: Failed to open DH file '%s': %s",
+			   dh_file, ERR_error_string(ERR_get_error(), NULL));
+		return -1;
+	}
+	dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
+	BIO_free(bio);
+#ifndef OPENSSL_NO_DSA
+	while (dh == NULL) {
+		DSA *dsa;
+		wpa_printf(MSG_DEBUG, "TLS: Failed to parse DH file '%s': %s -"
+			   " trying to parse as DSA params", dh_file,
+			   ERR_error_string(ERR_get_error(), NULL));
+		bio = BIO_new_file(dh_file, "r");
+		if (bio == NULL)
+			break;
+		dsa = PEM_read_bio_DSAparams(bio, NULL, NULL, NULL);
+		BIO_free(bio);
+		if (!dsa) {
+			wpa_printf(MSG_DEBUG, "TLS: Failed to parse DSA file "
+				   "'%s': %s", dh_file,
+				   ERR_error_string(ERR_get_error(), NULL));
+			break;
+		}
+
+		wpa_printf(MSG_DEBUG, "TLS: DH file in DSA param format");
+		dh = DSA_dup_DH(dsa);
+		DSA_free(dsa);
+		if (dh == NULL) {
+			wpa_printf(MSG_INFO, "TLS: Failed to convert DSA "
+				   "params into DH params");
+			break;
+		}
+		break;
+	}
+#endif /* !OPENSSL_NO_DSA */
+	if (dh == NULL) {
+		wpa_printf(MSG_INFO, "TLS: Failed to read/parse DH/DSA file "
+			   "'%s'", dh_file);
+		return -1;
+	}
+
+	if (SSL_CTX_set_tmp_dh(ssl_ctx, dh) != 1) {
+		wpa_printf(MSG_INFO, "TLS: Failed to set DH params from '%s': "
+			   "%s", dh_file,
+			   ERR_error_string(ERR_get_error(), NULL));
+		DH_free(dh);
+		return -1;
+	}
+	DH_free(dh);
+	return 0;
+#endif /* OPENSSL_NO_DH */
+}
+
+
 int tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn,
 			    struct tls_keys *keys)
 {
@@ -1998,57 +2076,6 @@
 {
 	return conn ? conn->ssl->hit : 0;
 }
-
-
-#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. */
-
-static int tls_sess_sec_cb(SSL *s, void *secret, int *secret_len,
-			   STACK_OF(SSL_CIPHER) *peer_ciphers,
-			   SSL_CIPHER **cipher, void *arg)
-{
-	struct tls_connection *conn = arg;
-
-	if (conn == NULL || conn->pre_shared_secret == 0)
-		return 0;
-
-	os_memcpy(secret, conn->pre_shared_secret,
-		  conn->pre_shared_secret_len);
-	*secret_len = conn->pre_shared_secret_len;
-
-	return 1;
-}
-
-
-int tls_connection_set_master_key(void *ssl_ctx, struct tls_connection *conn,
-				  const u8 *key, size_t key_len)
-{
-	if (conn == NULL || key_len > SSL_MAX_MASTER_KEY_LENGTH)
-		return -1;
-
-	os_free(conn->pre_shared_secret);
-	conn->pre_shared_secret = NULL;
-	conn->pre_shared_secret_len = 0;
-
-	if (key) {
-		conn->pre_shared_secret = os_malloc(key_len);
-		if (conn->pre_shared_secret) {
-			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,
-					      conn) != 1)
-			return -1;
-	} else {
-		if (SSL_set_session_secret_cb(conn->ssl, NULL, NULL) != 1)
-			return -1;
-	}
-
-	return 0;
-}
-#endif /* EAP_FAST || EAP_FAST_DYNAMIC */
 
 
 int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
@@ -2255,6 +2282,12 @@
 				   params->private_key_passwd))
 		return -1;
 
+	if (tls_global_dh(ssl_ctx, params->dh_file)) {
+		wpa_printf(MSG_INFO, "TLS: Failed to load DH file '%s'",
+			   params->dh_file);
+		return -1;
+	}
+
 	return 0;
 }
 
@@ -2272,7 +2305,11 @@
 		return -1;
 
 	c = conn->ssl->enc_read_ctx->cipher;
+#if OPENSSL_VERSION_NUMBER >= 0x00909000L
+	h = EVP_MD_CTX_md(conn->ssl->read_hash);
+#else
 	h = conn->ssl->read_hash;
+#endif
 
 	return 2 * (EVP_CIPHER_key_length(c) +
 		    EVP_MD_size(h) +
@@ -2315,3 +2352,131 @@
 {
 	return -1;
 }
+
+
+#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. */
+
+static int tls_sess_sec_cb(SSL *s, void *secret, int *secret_len,
+			   STACK_OF(SSL_CIPHER) *peer_ciphers,
+			   SSL_CIPHER **cipher, void *arg)
+{
+	struct tls_connection *conn = arg;
+	int ret;
+
+	if (conn == NULL || conn->session_ticket_cb == NULL)
+		return 0;
+
+	ret = conn->session_ticket_cb(conn->session_ticket_cb_ctx,
+				      conn->session_ticket,
+				      conn->session_ticket_len,
+				      s->s3->client_random,
+				      s->s3->server_random, secret);
+	os_free(conn->session_ticket);
+	conn->session_ticket = NULL;
+
+	if (ret <= 0)
+		return 0;
+
+	*secret_len = SSL_MAX_MASTER_KEY_LENGTH;
+	return 1;
+}
+
+
+#ifdef SSL_OP_NO_TICKET
+static void tls_hello_ext_cb(SSL *s, int client_server, int type,
+			     unsigned char *data, int len, void *arg)
+{
+	struct tls_connection *conn = arg;
+
+	if (conn == NULL || conn->session_ticket_cb == NULL)
+		return;
+
+	wpa_printf(MSG_DEBUG, "OpenSSL: %s: type=%d length=%d", __func__,
+		   type, len);
+
+	if (type == TLSEXT_TYPE_session_ticket && !client_server) {
+		os_free(conn->session_ticket);
+		conn->session_ticket = NULL;
+
+		wpa_hexdump(MSG_DEBUG, "OpenSSL: ClientHello SessionTicket "
+			    "extension", data, len);
+		conn->session_ticket = os_malloc(len);
+		if (conn->session_ticket == NULL)
+			return;
+
+		os_memcpy(conn->session_ticket, data, len);
+		conn->session_ticket_len = len;
+	}
+}
+#else /* SSL_OP_NO_TICKET */
+static int tls_hello_ext_cb(SSL *s, TLS_EXTENSION *ext, void *arg)
+{
+	struct tls_connection *conn = arg;
+
+	if (conn == NULL || conn->session_ticket_cb == NULL)
+		return 0;
+
+	wpa_printf(MSG_DEBUG, "OpenSSL: %s: type=%d length=%d", __func__,
+		   ext->type, ext->length);
+
+	os_free(conn->session_ticket);
+	conn->session_ticket = NULL;
+
+	if (ext->type == 35) {
+		wpa_hexdump(MSG_DEBUG, "OpenSSL: ClientHello SessionTicket "
+			    "extension", ext->data, ext->length);
+		conn->session_ticket = os_malloc(ext->length);
+		if (conn->session_ticket == NULL)
+			return SSL_AD_INTERNAL_ERROR;
+
+		os_memcpy(conn->session_ticket, ext->data, ext->length);
+		conn->session_ticket_len = ext->length;
+	}
+
+	return 0;
+}
+#endif /* SSL_OP_NO_TICKET */
+#endif /* EAP_FAST || EAP_FAST_DYNAMIC */
+
+
+int tls_connection_set_session_ticket_cb(void *tls_ctx,
+					 struct tls_connection *conn,
+					 tls_session_ticket_cb cb,
+					 void *ctx)
+{
+#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC)
+	conn->session_ticket_cb = cb;
+	conn->session_ticket_cb_ctx = ctx;
+
+	if (cb) {
+		if (SSL_set_session_secret_cb(conn->ssl, tls_sess_sec_cb,
+					      conn) != 1)
+			return -1;
+#ifdef SSL_OP_NO_TICKET
+		SSL_set_tlsext_debug_callback(conn->ssl, tls_hello_ext_cb);
+		SSL_set_tlsext_debug_arg(conn->ssl, conn);
+#else /* SSL_OP_NO_TICKET */
+		if (SSL_set_hello_extension_cb(conn->ssl, tls_hello_ext_cb,
+					       conn) != 1)
+			return -1;
+#endif /* SSL_OP_NO_TICKET */
+	} else {
+		if (SSL_set_session_secret_cb(conn->ssl, NULL, NULL) != 1)
+			return -1;
+#ifdef SSL_OP_NO_TICKET
+		SSL_set_tlsext_debug_callback(conn->ssl, NULL);
+		SSL_set_tlsext_debug_arg(conn->ssl, conn);
+#else /* SSL_OP_NO_TICKET */
+		if (SSL_set_hello_extension_cb(conn->ssl, NULL, NULL) != 1)
+			return -1;
+#endif /* SSL_OP_NO_TICKET */
+	}
+
+	return 0;
+#else /* EAP_FAST || EAP_FAST_DYNAMIC */
+	return -1;
+#endif /* EAP_FAST || EAP_FAST_DYNAMIC */
+}

Modified: wpasupplicant/trunk/src/crypto/tls_schannel.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/crypto/tls_schannel.c?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/src/crypto/tls_schannel.c (original)
+++ wpasupplicant/trunk/src/crypto/tls_schannel.c Sat Nov  3 11:46:49 2007
@@ -654,13 +654,6 @@
 }
 
 
-int tls_connection_set_master_key(void *ssl_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)
 {

Modified: wpasupplicant/trunk/src/drivers/driver.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/drivers/driver.h?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/src/drivers/driver.h (original)
+++ wpasupplicant/trunk/src/drivers/driver.h Sat Nov  3 11:46:49 2007
@@ -197,6 +197,14 @@
 	 * mobility domain is currently active.
 	 */
 	const u8 *ft_md;
+
+	/**
+	 * passphrase - RSN passphrase for PSK
+	 *
+	 * This value is made available only for WPA/WPA2-Personal (PSK) and
+	 * only for drivers that set WPA_DRIVER_FLAGS_4WAY_HANDSHAKE.
+	 */
+	const char *passphrase;
 };
 
 /**
@@ -227,6 +235,9 @@
 #define WPA_DRIVER_FLAGS_DRIVER_IE	0x00000001
 #define WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC 0x00000002
 #define WPA_DRIVER_FLAGS_USER_SPACE_MLME 0x00000004
+/* Driver takes care of RSN 4-way handshake internally; PMK is configured with
+ * struct wpa_driver_ops::set_key using alg = WPA_ALG_PMK */
+#define WPA_DRIVER_FLAGS_4WAY_HANDSHAKE 0x00000008
 	unsigned int flags;
 };
 
@@ -347,7 +358,8 @@
 	 * 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_IGTK, %WPA_ALG_DHV);
+	 *	%WPA_ALG_TKIP, %WPA_ALG_CCMP, %WPA_ALG_IGTK, %WPA_ALG_DHV,
+	 *	%WPA_ALG_PMK);
 	 *	%WPA_ALG_NONE clears the key.
 	 * @addr: address of the peer STA or ff:ff:ff:ff:ff:ff for
 	 *	broadcast/default keys

Modified: wpasupplicant/trunk/src/drivers/driver_wext.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/drivers/driver_wext.c?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/src/drivers/driver_wext.c (original)
+++ wpasupplicant/trunk/src/drivers/driver_wext.c Sat Nov  3 11:46:49 2007
@@ -1380,6 +1380,7 @@
 			wpa_printf(MSG_INFO, "Invalid TSF length (%d)", bytes);
 			return;
 		}
+		bytes /= 2;
 		hexstr2bin(spos, bin, bytes);
 		res->tsf += WPA_GET_BE64(bin);
 	}

Modified: wpasupplicant/trunk/src/drivers/drivers.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/drivers/drivers.c?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/src/drivers/drivers.c (original)
+++ wpasupplicant/trunk/src/drivers/drivers.c Sat Nov  3 11:46:49 2007
@@ -58,6 +58,12 @@
 #ifdef CONFIG_DRIVER_RALINK
 extern struct wpa_driver_ops wpa_driver_ralink_ops; /* driver_ralink.c */
 #endif /* CONFIG_DRIVER_RALINK */
+#ifdef CONFIG_DRIVER_OSX
+extern struct wpa_driver_ops wpa_driver_osx_ops; /* driver_osx.m */
+#endif /* CONFIG_DRIVER_OSX */
+#ifdef CONFIG_DRIVER_IPHONE
+extern struct wpa_driver_ops wpa_driver_iphone_ops; /* driver_iphone.m */
+#endif /* CONFIG_DRIVER_IPHONE */
 
 
 struct wpa_driver_ops *wpa_supplicant_drivers[] =
@@ -104,5 +110,11 @@
 #ifdef CONFIG_DRIVER_RALINK
 	&wpa_driver_ralink_ops,
 #endif /* CONFIG_DRIVER_RALINK */
+#ifdef CONFIG_DRIVER_OSX
+	&wpa_driver_osx_ops,
+#endif /* CONFIG_DRIVER_OSX */
+#ifdef CONFIG_DRIVER_IPHONE
+	&wpa_driver_iphone_ops,
+#endif /* CONFIG_DRIVER_IPHONE */
 	NULL
 };

Modified: wpasupplicant/trunk/src/eap_common/eap_gpsk_common.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/eap_common/eap_gpsk_common.c?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/src/eap_common/eap_gpsk_common.c (original)
+++ wpasupplicant/trunk/src/eap_common/eap_gpsk_common.c Sat Nov  3 11:46:49 2007
@@ -18,7 +18,9 @@
 #include "eap_defs.h"
 #include "aes_wrap.h"
 #include "crypto.h"
+#ifdef EAP_GPSK_SHA256
 #include "sha256.h"
+#endif /* EAP_GPSK_SHA256 */
 #include "eap_gpsk_common.h"
 
 
@@ -42,31 +44,29 @@
 }
 
 
-static int eap_gpsk_gkdf(const u8 *psk /* Y */, size_t psk_len,
-			 const u8 *data /* Z */, size_t data_len,
-			 u8 *buf, size_t len /* X */)
+static int eap_gpsk_gkdf_cmac(const u8 *psk /* Y */,
+			      const u8 *data /* Z */, size_t data_len,
+			      u8 *buf, size_t len /* X */)
 {
 	u8 *opos;
 	size_t i, n, hashlen, left, clen;
-	u8 ibuf[2], hash[SHA256_MAC_LEN];
-	const u8 *addr[3];
-	size_t vlen[3];
-
-	hashlen = SHA256_MAC_LEN;
-	/* M_i = Hash-Function (i || Y || Z); */
+	u8 ibuf[2], hash[16];
+	const u8 *addr[2];
+	size_t vlen[2];
+
+	hashlen = sizeof(hash);
+	/* M_i = MAC_Y (i || Z); (MAC = AES-CMAC-128) */
 	addr[0] = ibuf;
 	vlen[0] = sizeof(ibuf);
-	addr[1] = psk;
-	vlen[1] = psk_len;
-	addr[2] = data;
-	vlen[2] = data_len;
+	addr[1] = data;
+	vlen[1] = data_len;
 
 	opos = buf;
 	left = len;
 	n = (len + hashlen - 1) / hashlen;
 	for (i = 1; i <= n; i++) {
 		WPA_PUT_BE16(ibuf, i);
-		sha256_vector(3, addr, vlen, hash);
+		omac1_aes_128_vector(psk, 2, addr, vlen, hash);
 		clen = left > hashlen ? hashlen : left;
 		os_memcpy(opos, hash, clen);
 		opos += clen;
@@ -77,7 +77,42 @@
 }
 
 
-static int eap_gpsk_derive_keys_helper(u32 csuite_specified,
+#ifdef EAP_GPSK_SHA256
+static int eap_gpsk_gkdf_sha256(const u8 *psk /* Y */,
+				const u8 *data /* Z */, size_t data_len,
+				u8 *buf, size_t len /* X */)
+{
+	u8 *opos;
+	size_t i, n, hashlen, left, clen;
+	u8 ibuf[2], hash[SHA256_MAC_LEN];
+	const u8 *addr[2];
+	size_t vlen[2];
+
+	hashlen = SHA256_MAC_LEN;
+	/* M_i = MAC_Y (i || Z); (MAC = HMAC-SHA256) */
+	addr[0] = ibuf;
+	vlen[0] = sizeof(ibuf);
+	addr[1] = data;
+	vlen[1] = data_len;
+
+	opos = buf;
+	left = len;
+	n = (len + hashlen - 1) / hashlen;
+	for (i = 1; i <= n; i++) {
+		WPA_PUT_BE16(ibuf, i);
+		hmac_sha256_vector(psk, 32, 2, addr, vlen, hash);
+		clen = left > hashlen ? hashlen : left;
+		os_memcpy(opos, hash, clen);
+		opos += clen;
+		left -= clen;
+	}
+
+	return 0;
+}
+#endif /* EAP_GPSK_SHA256 */
+
+
+static int eap_gpsk_derive_keys_helper(u32 csuite_specifier,
 				       u8 *kdf_out, size_t kdf_out_len,
 				       const u8 *psk, size_t psk_len,
 				       const u8 *seed, size_t seed_len,
@@ -85,10 +120,28 @@
 				       u8 *sk, size_t sk_len,
 				       u8 *pk, size_t pk_len)
 {
-	u8 zero, mk[32], *pos, *data;
-	size_t data_len;
-
-	zero = 0;
+	u8 zero[32], mk[32], *pos, *data;
+	size_t data_len, mk_len;
+	int (*gkdf)(const u8 *psk, const u8 *data, size_t data_len,
+		    u8 *buf, size_t len);
+
+	gkdf = NULL;
+	switch (csuite_specifier) {
+	case EAP_GPSK_CIPHER_AES:
+		gkdf = eap_gpsk_gkdf_cmac;
+		mk_len = 16;
+		break;
+#ifdef EAP_GPSK_SHA256
+	case EAP_GPSK_CIPHER_SHA256:
+		gkdf = eap_gpsk_gkdf_sha256;
+		mk_len = SHA256_MAC_LEN;
+		break;
+#endif /* EAP_GPSK_SHA256 */
+	default:
+		return -1;
+	}
+
+	os_memset(zero, 0, sizeof(zero));
 
 	data_len = 2 + psk_len + 6 + seed_len;
 	data = os_malloc(data_len);
@@ -99,23 +152,22 @@
 	pos += 2;
 	os_memcpy(pos, psk, psk_len);
 	pos += psk_len;
-	WPA_PUT_BE24(pos, 0); /* CSuite/Vendor = IETF */
-	pos += 3;
-	WPA_PUT_BE24(pos, csuite_specified); /* CSuite/Specifier */
-	pos += 3;
+	WPA_PUT_BE32(pos, EAP_GPSK_VENDOR_IETF); /* CSuite/Vendor = IETF */
+	pos += 4;
+	WPA_PUT_BE16(pos, csuite_specifier); /* CSuite/Specifier */
+	pos += 2;
 	os_memcpy(pos, seed, seed_len); /* inputString */
 	wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: Data to MK derivation",
 			data, data_len);
 
-	if (eap_gpsk_gkdf(&zero, 1, data, data_len, mk, sizeof(mk)) < 0) {
+	if (gkdf(zero, data, data_len, mk, mk_len) < 0) {
 		os_free(data);
 		return -1;
 	}
 	os_free(data);
-	wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: MK", mk, sizeof(mk));
-
-	if (eap_gpsk_gkdf(mk, sizeof(mk), seed, seed_len,
-			  kdf_out, kdf_out_len) < 0)
+	wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: MK", mk, mk_len);
+
+	if (gkdf(mk, seed, seed_len, kdf_out, kdf_out_len) < 0)
 		return -1;
 
 	pos = kdf_out;
@@ -153,16 +205,15 @@
 	/*
 	 * inputString = RAND_Peer || ID_Peer || RAND_Server || ID_Server
 	 *            (= seed)
-	 * KS = 16, PL = psk_len, CSuite_Sel = 0x000000 0x000001
-	 * MK = GKDF-32 (0x00, PL || PSK || CSuite_Sel || inputString)
+	 * KS = 16, PL = psk_len, CSuite_Sel = 0x00000000 0x0001
+	 * zero = 0x00 || 0x00 || ... || 0x00 (16 times)
+	 * MK = GKDF-16 (zero, PL || PSK || CSuite_Sel || inputString)
 	 * MSK = GKDF-160 (MK, inputString)[0..63]
 	 * EMSK = GKDF-160 (MK, inputString)[64..127]
 	 * SK = GKDF-160 (MK, inputString)[128..143]
 	 * PK = GKDF-160 (MK, inputString)[144..159]
-	 * MID = GKDF-16(0x00, "Method ID" || EAP_Method_Type || CSuite_Sel ||
-	 *               inputString)
-	 * Hash-Function = SHA256 (see [RFC4634])
-	 * hashlen = 32 octets (256 bits)
+	 * Method-ID = GKDF-16 (zero, "Method ID" || EAP_Method_Type ||
+	 *                      CSuite_Sel || inputString)
 	 */
 
 	*sk_len = EAP_GPSK_SK_LEN_AES;
@@ -190,15 +241,14 @@
 	/*
 	 * inputString = RAND_Peer || ID_Peer || RAND_Server || ID_Server
 	 *            (= seed)
-	 * KS = 32, PL = psk_len, CSuite_Sel = 0x000000 0x000002
-	 * MK = GKDF-32 (0x00, PL || PSK || CSuite_Sel || inputString)
-	 * MSK = GKDF-192 (MK, inputString)[0..63]
-	 * EMSK = GKDF-192 (MK, inputString)[64..127]
-	 * SK = GKDF-192 (MK, inputString)[128..159]
-	 * MID = GKDF-16(0x00, "Method ID" || EAP_Method_Type || CSuite_Sel ||
-	 *               inputString)
-	 * Hash-Function = SHA256 (see [RFC4634])
-	 * hashlen = 32 octets (256 bits)
+	 * KS = 32, PL = psk_len, CSuite_Sel = 0x00000000 0x0002
+	 * zero = 0x00 || 0x00 || ... || 0x00 (32 times)
+	 * MK = GKDF-32 (zero, PL || PSK || CSuite_Sel || inputString)
+	 * MSK = GKDF-160 (MK, inputString)[0..63]
+	 * EMSK = GKDF-160 (MK, inputString)[64..127]
+	 * SK = GKDF-160 (MK, inputString)[128..159]
+	 * Method-ID = GKDF-16 (zero, "Method ID" || EAP_Method_Type ||
+	 *                      CSuite_Sel || inputString)
 	 */
 
 	*sk_len = EAP_GPSK_SK_LEN_SHA256;

Modified: wpasupplicant/trunk/src/eap_common/eap_gpsk_common.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/eap_common/eap_gpsk_common.h?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/src/eap_common/eap_gpsk_common.h (original)
+++ wpasupplicant/trunk/src/eap_common/eap_gpsk_common.h Sat Nov  3 11:46:49 2007
@@ -32,7 +32,7 @@
 #define EAP_GPSK_MAX_PK_LEN 32
 #define EAP_GPSK_MAX_MIC_LEN 32
 
-#define EAP_GPSK_VENDOR_IETF		0x000000
+#define EAP_GPSK_VENDOR_IETF		0x00000000
 #define EAP_GPSK_CIPHER_RESERVED	0x000000
 #define EAP_GPSK_CIPHER_AES		0x000001
 #define EAP_GPSK_CIPHER_SHA256		0x000002
@@ -43,8 +43,8 @@
 #endif /* _MSC_VER */
 
 struct eap_gpsk_csuite {
-	u8 vendor[3];
-	u8 specifier[3];
+	u8 vendor[4];
+	u8 specifier[2];
 } STRUCT_PACKED;
 
 #ifdef _MSC_VER

Modified: wpasupplicant/trunk/src/eap_peer/eap.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/eap_peer/eap.c?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/src/eap_peer/eap.c (original)
+++ wpasupplicant/trunk/src/eap_peer/eap.c Sat Nov  3 11:46:49 2007
@@ -1,6 +1,6 @@
 /*
  * EAP peer state machines (RFC 4137)
- * Copyright (c) 2004-2006, Jouni Malinen <j at w1.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
@@ -1788,6 +1788,27 @@
 
 
 /**
+ * eap_get_config_password2 - Get password from the network configuration
+ * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
+ * @len: Buffer for the length of the password
+ * @hash: Buffer for returning whether the password is stored as a
+ * NtPasswordHash instead of plaintext password; can be %NULL if this
+ * information is not needed
+ * Returns: Pointer to the password or %NULL if not found
+ */
+const u8 * eap_get_config_password2(struct eap_sm *sm, size_t *len, int *hash)
+{
+	struct wpa_ssid *config = eap_get_config(sm);
+	if (config == NULL)
+		return NULL;
+	*len = config->password_len;
+	if (hash)
+		*hash = !!(config->flags & WPA_CONFIG_FLAGS_PASSWORD_NTHASH);
+	return config->password;
+}
+
+
+/**
  * eap_get_config_new_password - Get new password from network configuration
  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
  * @len: Buffer for the length of the new password

Modified: wpasupplicant/trunk/src/eap_peer/eap_fast.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/eap_peer/eap_fast.c?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/src/eap_peer/eap_fast.c (original)
+++ wpasupplicant/trunk/src/eap_peer/eap_fast.c Sat Nov  3 11:46:49 2007
@@ -32,27 +32,8 @@
  * - password change (pending mschapv2 packet; replay decrypted packet)
  */
 
-#define EAP_FAST_VERSION 1
-#define EAP_FAST_KEY_LEN 64
-#define EAP_FAST_SIMCK_LEN 40
-#define EAP_FAST_SKS_LEN 40
-
-#define TLS_EXT_PAC_OPAQUE 35
-
 
 static void eap_fast_deinit(struct eap_sm *sm, void *priv);
-
-
-/*
- * draft-cam-winget-eap-fast-provisioning-04.txt:
- * Section 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[EAP_FAST_SKS_LEN];
-	u8 server_challenge[16]; /* MSCHAPv2 ServerChallenge */
-	u8 client_challenge[16]; /* MSCHAPv2 ClientChallenge */
-};
 
 
 struct eap_fast_data {
@@ -75,6 +56,7 @@
 	int provisioning; /* doing PAC provisioning (not the normal auth) */
 	int anon_provisioning; /* doing anonymous (unauthenticated)
 				* provisioning */
+	int session_ticket_used;
 
 	u8 key_data[EAP_FAST_KEY_LEN];
 	u8 emsk[EAP_EMSK_LEN];
@@ -85,14 +67,71 @@
 	size_t max_pac_list_len;
 	int use_pac_binary_format;
 
-	int tls_master_secret_set;
-
 	u8 simck[EAP_FAST_SIMCK_LEN];
 	int simck_idx;
 
 	u8 *pending_phase2_req;
 	size_t pending_phase2_req_len;
 };
+
+
+static int eap_fast_session_ticket_cb(void *ctx, const u8 *ticket, size_t len,
+				      const u8 *client_random,
+				      const u8 *server_random,
+				      u8 *master_secret)
+{
+	struct eap_fast_data *data = ctx;
+#define TLS_RANDOM_LEN 32
+#define TLS_MASTER_SECRET_LEN 48
+	u8 seed[2 * TLS_RANDOM_LEN];
+
+	wpa_printf(MSG_DEBUG, "EAP-FAST: SessionTicket callback");
+
+	if (client_random == NULL || server_random == NULL ||
+	    master_secret == NULL) {
+		wpa_printf(MSG_DEBUG, "EAP-FAST: SessionTicket failed - fall "
+			   "back to full TLS handshake");
+		data->session_ticket_used = 0;
+		if (data->provisioning_allowed) {
+			wpa_printf(MSG_DEBUG, "EAP-FAST: Try to provision a "
+				   "new PAC-Key");
+			data->provisioning = 1;
+			data->current_pac = NULL;
+		}
+		return 0;
+	}
+
+	wpa_hexdump(MSG_DEBUG, "EAP-FAST: SessionTicket", ticket, len);
+	wpa_hexdump(MSG_DEBUG, "EAP-FAST: client_random",
+		    client_random, TLS_RANDOM_LEN);
+	wpa_hexdump(MSG_DEBUG, "EAP-FAST: server_random",
+		    server_random, TLS_RANDOM_LEN);
+
+	if (data->current_pac == NULL) {
+		wpa_printf(MSG_DEBUG, "EAP-FAST: No PAC-Key available for "
+			   "using SessionTicket");
+		data->session_ticket_used = 0;
+		return 0;
+	}
+
+	/*
+	 * RFC 4851, Section 5.1:
+	 * master_secret = T-PRF(PAC-Key, "PAC to master secret label hash", 
+	 *                       server_random + client_random, 48)
+	 */
+	os_memcpy(seed, server_random, TLS_RANDOM_LEN);
+	os_memcpy(seed + TLS_RANDOM_LEN, client_random, TLS_RANDOM_LEN);
+	sha1_t_prf(data->current_pac->pac_key, EAP_FAST_PAC_KEY_LEN,
+		   "PAC to master secret label hash",
+		   seed, sizeof(seed), master_secret, TLS_MASTER_SECRET_LEN);
+
+	wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: master_secret",
+			master_secret, TLS_MASTER_SECRET_LEN);
+
+	data->session_ticket_used = 1;
+
+	return 1;
+}
 
 
 static int eap_fast_parse_phase1(struct eap_fast_data *data,
@@ -160,6 +199,15 @@
 		return NULL;
 	}
 
+	if (tls_connection_set_session_ticket_cb(sm->ssl_ctx, data->ssl.conn,
+						 eap_fast_session_ticket_cb,
+						 data) < 0) {
+		wpa_printf(MSG_INFO, "EAP-FAST: Failed to set SessionTicket "
+			   "callback");
+		eap_fast_deinit(sm, data);
+		return NULL;
+	}
+
 	/*
 	 * The local RADIUS server in a Cisco AP does not seem to like empty
 	 * fragments before data, so disable that workaround for CBC.
@@ -234,83 +282,6 @@
 	data->success = 1;
 
 	return 0;
-}
-
-
-static int eap_fast_set_tls_master_secret(struct eap_sm *sm,
-					  struct eap_fast_data *data,
-					  const u8 *tls, size_t tls_len)
-{
-	struct tls_keys keys;
-	u8 master_secret[48], *seed;
-	const u8 *server_random;
-	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) ||
-	    keys.client_random == NULL) {
-		return 0;
-	}
-
-	wpa_hexdump(MSG_DEBUG, "EAP-FAST: client_random",
-		    keys.client_random, keys.client_random_len);
-
-	/*
-	 * TLS master secret is needed before TLS library has processed this
-	 * message which includes both ServerHello and an encrypted handshake
-	 * message, so we need to parse server_random from this message before
-	 * passing it to TLS library.
-	 *
-	 * Example TLS packet header:
-	 * (16 03 01 00 2a 02 00 00 26 03 01 <32 bytes server_random>)
-	 * Content Type: Handshake: 0x16
-	 * Version: TLS 1.0 (0x0301)
-	 * Lenghth: 42 (0x002a)
-	 * Handshake Type: Server Hello: 0x02
-	 * Length: 38 (0x000026)
-	 * Version TLS 1.0 (0x0301)
-	 * Random: 32 bytes
-	 */
-	if (tls_len < 43 || tls[0] != 0x16 ||
-	    tls[1] != 0x03 || tls[2] != 0x01 ||
-	    tls[5] != 0x02 || tls[9] != 0x03 || tls[10] != 0x01) {
-		wpa_hexdump(MSG_DEBUG, "EAP-FAST: unrecognized TLS "
-			    "ServerHello", tls, tls_len);
-		return -1;
-	}
-	server_random = tls + 11;
-	server_random_len = 32;
-	wpa_hexdump(MSG_DEBUG, "EAP-FAST: server_random",
-		    server_random, server_random_len);
-
-	seed_len = keys.client_random_len + server_random_len;
-	seed = os_malloc(seed_len);
-	if (seed == NULL)
-		return -1;
-	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",
-			data->current_pac->pac_key, EAP_FAST_PAC_KEY_LEN);
-	/*
-	 * RFC 4851, Section 5.1:
-	 * master_secret = T-PRF(PAC-Key, "PAC to master secret label hash", 
-	 *                       server_random + client_random, 48)
-	 */
-	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));
-	os_free(seed);
-	wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: TLS pre-master-secret",
-			master_secret, sizeof(master_secret));
-
-	data->tls_master_secret_set = 1;
-
-	return tls_connection_set_master_key(sm->ssl_ctx, data->ssl.conn,
-					     master_secret,
-					     sizeof(master_secret));
 }
 
 
@@ -1719,21 +1690,6 @@
 			res = 1;
 		}
 	} else {
-		/*
-		 * Try to configure the TLS master secret based on PAC-Key
-		 * and server/client random values. If the needed values are
-		 * not yet available, the function returns 0, so we only abort
-		 * on failure case when configuring the TLS library fails, not
-		 * if the key material is not yet available.
-		 */
-		if (eap_fast_set_tls_master_secret(sm, data, pos, left) < 0) {
-			wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to configure "
-				   "TLS master secret");
-			ret->methodState = METHOD_DONE;
-			ret->decision = DECISION_FAIL;
-			return NULL;
-		}
-
 		/* Continue processing TLS handshake (phase 1). */
 		res = eap_peer_tls_process_helper(sm, &data->ssl,
 						  EAP_TYPE_FAST,

Modified: wpasupplicant/trunk/src/eap_peer/eap_fast_pac.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/eap_peer/eap_fast_pac.h?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/src/eap_peer/eap_fast_pac.h (original)
+++ wpasupplicant/trunk/src/eap_peer/eap_fast_pac.h Sat Nov  3 11:46:49 2007
@@ -15,54 +15,7 @@
 #ifndef EAP_FAST_PAC_H
 #define EAP_FAST_PAC_H
 
-/*
- * draft-cam-winget-eap-fast-provisioning-04.txt:
- * Section 4.2.1 - Formats for PAC TLV Attributes / Type Field
- * Note: bit 0x8000 (Mandatory) and bit 0x4000 (Reserved) are also defined
- * in the general PAC TLV format (Section 4.2).
- */
-#define PAC_TYPE_PAC_KEY 1
-#define PAC_TYPE_PAC_OPAQUE 2
-#define PAC_TYPE_CRED_LIFETIME 3
-#define PAC_TYPE_A_ID 4
-#define PAC_TYPE_I_ID 5
-/*
- * 6 was previous assigned for SERVER_PROTECTED_DATA, but
- * draft-cam-winget-eap-fast-provisioning-02.txt changed this to Reserved.
- */
-#define PAC_TYPE_A_ID_INFO 7
-#define PAC_TYPE_PAC_ACKNOWLEDGEMENT 8
-#define PAC_TYPE_PAC_INFO 9
-#define PAC_TYPE_PAC_TYPE 10
-
-#ifdef _MSC_VER
-#pragma pack(push, 1)
-#endif /* _MSC_VER */
-
-struct pac_tlv_hdr {
-	be16 type;
-	be16 len;
-} STRUCT_PACKED;
-
-#ifdef _MSC_VER
-#pragma pack(pop)
-#endif /* _MSC_VER */
-
-
-#define EAP_FAST_PAC_KEY_LEN 32
-
-/* draft-cam-winget-eap-fast-provisioning-04.txt: 4.2.6 PAC-Type TLV
- * Note: Machine Authentication PAC and User Authorization PAC were removed in
- * draft-cam-winget-eap-fast-provisioning-03.txt
- */
-#define PAC_TYPE_TUNNEL_PAC 1
-/* Application Specific Short Lived PACs (only in volatile storage) */
-/* User Authorization PAC */
-#define PAC_TYPE_USER_AUTHORIZATION 3
-/* Application Specific Long Lived PACs */
-/* Machine Authentication PAC */
-#define PAC_TYPE_MACHINE_AUTHENTICATION 2
-
+#include "eap_common/eap_fast_common.h"
 
 struct eap_fast_pac {
 	struct eap_fast_pac *next;

Modified: wpasupplicant/trunk/src/eap_peer/eap_gpsk.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/eap_peer/eap_gpsk.c?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/src/eap_peer/eap_gpsk.c (original)
+++ wpasupplicant/trunk/src/eap_peer/eap_gpsk.c Sat Nov  3 11:46:49 2007
@@ -1,5 +1,5 @@
 /*
- * EAP peer method: EAP-GPSK (draft-ietf-emu-eap-gpsk-04.txt)
+ * EAP peer method: EAP-GPSK (draft-ietf-emu-eap-gpsk-06.txt)
  * Copyright (c) 2006-2007, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -196,8 +196,8 @@
 	csuite = (struct eap_gpsk_csuite *) csuite_list;
 	for (i = 0; i < count; i++) {
 		int vendor, specifier;
-		vendor = WPA_GET_BE24(csuite->vendor);
-		specifier = WPA_GET_BE24(csuite->specifier);
+		vendor = WPA_GET_BE32(csuite->vendor);
+		specifier = WPA_GET_BE16(csuite->specifier);
 		wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite[%d]: %d:%d",
 			   i, vendor, specifier);
 		if (data->vendor == EAP_GPSK_VENDOR_IETF &&
@@ -356,8 +356,8 @@
 	rpos += csuite_list_len;
 
 	csuite = (struct eap_gpsk_csuite *) rpos;
-	WPA_PUT_BE24(csuite->vendor, data->vendor);
-	WPA_PUT_BE24(csuite->specifier, data->specifier);
+	WPA_PUT_BE32(csuite->vendor, data->vendor);
+	WPA_PUT_BE16(csuite->specifier, data->specifier);
 	rpos = (u8 *) (csuite + 1);
 
 	if (eap_gpsk_derive_keys(data->psk, data->psk_len,
@@ -444,8 +444,8 @@
 		return NULL;
 	}
 	csuite = (const struct eap_gpsk_csuite *) pos;
-	vendor = WPA_GET_BE24(csuite->vendor);
-	specifier = WPA_GET_BE24(csuite->specifier);
+	vendor = WPA_GET_BE32(csuite->vendor);
+	specifier = WPA_GET_BE16(csuite->specifier);
 	pos += sizeof(*csuite);
 	if (vendor != data->vendor || specifier != data->specifier) {
 		wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite_Sel (%d:%d) does not "

Modified: wpasupplicant/trunk/src/eap_peer/eap_gtc.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/eap_peer/eap_gtc.c?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/src/eap_peer/eap_gtc.c (original)
+++ wpasupplicant/trunk/src/eap_peer/eap_gtc.c Sat Nov  3 11:46:49 2007
@@ -30,7 +30,8 @@
 	if (data == NULL)
 		return NULL;
 
-	if (sm->m && sm->m->method == EAP_TYPE_FAST) {
+	if (sm->m && sm->m->vendor == EAP_VENDOR_IETF &&
+	    sm->m->method == EAP_TYPE_FAST) {
 		wpa_printf(MSG_DEBUG, "EAP-GTC: EAP-FAST tunnel - use prefix "
 			   "with challenge/response");
 		data->prefix = 1;

Modified: wpasupplicant/trunk/src/eap_peer/eap_i.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/eap_peer/eap_i.h?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/src/eap_peer/eap_i.h (original)
+++ wpasupplicant/trunk/src/eap_peer/eap_i.h Sat Nov  3 11:46:49 2007
@@ -340,6 +340,7 @@
 
 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_password2(struct eap_sm *sm, size_t *len, int *hash);
 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);

Modified: wpasupplicant/trunk/src/eap_peer/eap_leap.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/eap_peer/eap_leap.c?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/src/eap_peer/eap_leap.c (original)
+++ wpasupplicant/trunk/src/eap_peer/eap_leap.c Sat Nov  3 11:46:49 2007
@@ -1,6 +1,6 @@
 /*
  * EAP peer method: LEAP
- * Copyright (c) 2004-2006, Jouni Malinen <j at w1.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
@@ -72,11 +72,12 @@
 	const u8 *pos, *challenge, *identity, *password;
 	u8 challenge_len, *rpos;
 	size_t identity_len, password_len;
+	int pwhash;
 
 	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);
+	password = eap_get_config_password2(sm, &password_len, &pwhash);
 	if (identity == NULL || password == NULL)
 		return NULL;
 
@@ -123,7 +124,10 @@
 	*rpos++ = LEAP_VERSION;
 	*rpos++ = 0; /* unused */
 	*rpos++ = LEAP_RESPONSE_LEN;
-	nt_challenge_response(challenge, password, password_len, rpos);
+	if (pwhash)
+		challenge_response(challenge, password, rpos);
+	else
+		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);
@@ -199,10 +203,11 @@
 	u8 response_len, pw_hash[16], pw_hash_hash[16],
 		expected[LEAP_RESPONSE_LEN];
 	size_t password_len;
+	int pwhash;
 
 	wpa_printf(MSG_DEBUG, "EAP-LEAP: Processing EAP-Response");
 
-	password = eap_get_config_password(sm, &password_len);
+	password = eap_get_config_password2(sm, &password_len, &pwhash);
 	if (password == NULL)
 		return NULL;
 
@@ -239,8 +244,12 @@
 		    pos, LEAP_RESPONSE_LEN);
 	os_memcpy(data->ap_response, pos, LEAP_RESPONSE_LEN);
 
-	nt_password_hash(password, password_len, pw_hash);
-	hash_nt_password_hash(pw_hash, pw_hash_hash);
+	if (pwhash) {
+		hash_nt_password_hash(password, pw_hash_hash);
+	} else {
+		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;
@@ -333,11 +342,12 @@
 	u8 *key, pw_hash_hash[16], pw_hash[16];
 	const u8 *addr[5], *password;
 	size_t elen[5], password_len;
+	int pwhash;
 
 	if (data->state != LEAP_DONE)
 		return NULL;
 
-	password = eap_get_config_password(sm, &password_len);
+	password = eap_get_config_password2(sm, &password_len, &pwhash);
 	if (password == NULL)
 		return NULL;
 
@@ -345,8 +355,12 @@
 	if (key == NULL)
 		return NULL;
 
-	nt_password_hash(password, password_len, pw_hash);
-	hash_nt_password_hash(pw_hash, pw_hash_hash);
+	if (pwhash)
+		hash_nt_password_hash(password, pw_hash_hash);
+	else {
+		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);
 	wpa_hexdump(MSG_DEBUG, "EAP-LEAP: peer_challenge",

Modified: wpasupplicant/trunk/src/eap_peer/eap_mschapv2.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/eap_peer/eap_mschapv2.c?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/src/eap_peer/eap_mschapv2.c (original)
+++ wpasupplicant/trunk/src/eap_peer/eap_mschapv2.c Sat Nov  3 11:46:49 2007
@@ -1,6 +1,6 @@
 /*
  * EAP peer method: EAP-MSCHAPV2 (draft-kamath-pppext-eap-mschapv2-00.txt)
- * Copyright (c) 2004-2006, Jouni Malinen <j at w1.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
@@ -180,7 +180,7 @@
 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 *password, size_t password_len, int pwhash,
 	const u8 *auth_challenge, const u8 *peer_challenge,
 	u8 *nt_response)
 {
@@ -192,25 +192,45 @@
 		    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);
+	if (pwhash) {
+		wpa_hexdump_key(MSG_DEBUG, "EAP-MSCHAPV2: password hash",
+				password, password_len);
+		generate_nt_response_pwhash(auth_challenge, peer_challenge,
+					    username, username_len,
+					    password, nt_response);
+	} else {
+		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);
+	if (pwhash) {
+		generate_authenticator_response_pwhash(
+			password, peer_challenge, auth_challenge,
+			username, username_len, nt_response,
+			data->auth_response);
+	} else {
+		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);
+	if (pwhash) {
+		hash_nt_password_hash(password, password_hash_hash);
+	} else {
+		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;
 }
@@ -229,11 +249,12 @@
 	struct ms_response *r;
 	size_t username_len, identity_len, password_len;
 	const u8 *username, *identity, *password;
+	int pwhash;
 
 	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);
+	password = eap_get_config_password2(sm, &password_len, &pwhash);
 	if (identity == NULL || password == NULL)
 		return NULL;
 
@@ -281,7 +302,7 @@
 		auth_challenge = data->auth_challenge;
 	}
 	eap_mschapv2_derive_response(data, username, username_len,
-				     password, password_len,
+				     password, password_len, pwhash,
 				     auth_challenge, peer_challenge,
 				     r->nt_response);
 
@@ -375,9 +396,20 @@
 			"EAP-MSCHAPV2: Password changed successfully");
 		data->prev_error = 0;
 		os_free(config->password);
-		config->password = config->new_password;
+		if (config->flags & WPA_CONFIG_FLAGS_PASSWORD_NTHASH) {
+			config->password = os_malloc(16);
+			config->password_len = 16;
+			if (config->password) {
+				nt_password_hash(config->new_password,
+						 config->new_password_len,
+						 config->password);
+			}
+			os_free(config->new_password);
+		} else {
+			config->password = config->new_password;
+			config->password_len = config->new_password_len;
+		}
 		config->new_password = NULL;
-		config->password_len = config->new_password_len;
 		config->new_password_len = 0;
 	}
 }
@@ -574,9 +606,10 @@
 	struct eap_mschapv2_hdr *ms;
 	struct ms_change_password *cp;
 	u8 password_hash[16], password_hash_hash[16];
+	int pwhash;
 
 	username = eap_get_config_identity(sm, &username_len);
-	password = eap_get_config_password(sm, &password_len);
+	password = eap_get_config_password2(sm, &password_len, &pwhash);
 	new_password = eap_get_config_new_password(sm, &new_password_len);
 	if (username == NULL || password == NULL || new_password == NULL)
 		return NULL;
@@ -601,14 +634,29 @@
 	cp = (struct ms_change_password *) (ms + 1);
 
 	/* Encrypted-Password */
-	new_password_encrypted_with_old_nt_password_hash(
-		new_password, new_password_len,
-		password, password_len, cp->encr_password);
+	if (pwhash) {
+		encrypt_pw_block_with_password_hash(
+			new_password, new_password_len,
+			password, cp->encr_password);
+	} else {
+		new_password_encrypted_with_old_nt_password_hash(
+			new_password, new_password_len,
+			password, password_len, cp->encr_password);
+	}
 
 	/* Encrypted-Hash */
-	old_nt_password_hash_encrypted_with_new_nt_password_hash(
-		new_password, new_password_len,
-		password, password_len, cp->encr_hash);
+	if (pwhash) {
+		u8 new_password_hash[16];
+		nt_password_hash(new_password, new_password_len,
+				 new_password_hash);
+		nt_password_hash_encrypted_with_block(password,
+						      new_password_hash,
+						      cp->encr_hash);
+	} else {
+		old_nt_password_hash_encrypted_with_new_nt_password_hash(
+			new_password, new_password_len,
+			password, password_len, cp->encr_hash);
+	}
 
 	/* Peer-Challenge */
 	if (os_get_random(cp->peer_challenge, MSCHAPV2_CHAL_LEN)) {

Modified: wpasupplicant/trunk/src/eap_peer/eap_tlv.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/eap_peer/eap_tlv.h?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/src/eap_peer/eap_tlv.h (original)
+++ wpasupplicant/trunk/src/eap_peer/eap_tlv.h Sat Nov  3 11:46:49 2007
@@ -15,104 +15,7 @@
 #ifndef EAP_TLV_H
 #define EAP_TLV_H
 
-/* EAP-TLV TLVs (draft-josefsson-ppext-eap-tls-eap-07.txt) */
-#define EAP_TLV_RESULT_TLV 3 /* Acknowledged Result */
-#define EAP_TLV_NAK_TLV 4
-/* Note: RFC 4851, Section 4.2.4 defines 5 as Error TLV */
-#define EAP_TLV_CRYPTO_BINDING_TLV 5
-#define EAP_TLV_CONNECTION_BINDING_TLV 6
-#define EAP_TLV_VENDOR_SPECIFIC_TLV 7
-#define EAP_TLV_URI_TLV 8
-#define EAP_TLV_EAP_PAYLOAD_TLV 9
-#define EAP_TLV_INTERMEDIATE_RESULT_TLV 10
-#define EAP_TLV_PAC_TLV 11 /* draft-cam-winget-eap-fast-provisioning-04.txt,
-			    * Section 4.2 */
-#define EAP_TLV_CRYPTO_BINDING_TLV_ 12 /* RFC 4851, Section 4.2.8 */
-/* draft-cam-winget-eap-fast-provisiong-04.txt, Section 4.3.1 */
-#define EAP_TLV_SERVER_TRUSTED_ROOT_TLV 18
-#define EAP_TLV_REQUEST_ACTION_TLV 19 /* RFC 4851, Section 4.2.9 */
-/* draft-cam-winget-eap-fast-provisiong-04.txt, Section 4.3.2 */
-#define EAP_TLV_PKCS7_TLV 20
-
-#define EAP_TLV_RESULT_SUCCESS 1
-#define EAP_TLV_RESULT_FAILURE 2
-
-#define EAP_TLV_TYPE_MANDATORY 0x8000
-
-#ifdef _MSC_VER
-#pragma pack(push, 1)
-#endif /* _MSC_VER */
-
-struct eap_tlv_hdr {
-	be16 tlv_type;
-	be16 length;
-} STRUCT_PACKED;
-
-struct eap_tlv_nak_tlv {
-	be16 tlv_type;
-	be16 length;
-	be32 vendor_id;
-	be16 nak_type;
-} STRUCT_PACKED;
-
-struct eap_tlv_result_tlv {
-	be16 tlv_type;
-	be16 length;
-	be16 status;
-} STRUCT_PACKED;
-
-/* RFC 4851, Section 4.2.7 - Intermediate-Result TLV */
-struct eap_tlv_intermediate_result_tlv {
-	be16 tlv_type;
-	be16 length;
-	be16 status;
-	/* Followed by optional TLVs */
-} STRUCT_PACKED;
-
-/* RFC 4851, Section 4.2.8 - Crypto-Binding TLV */
-struct eap_tlv_crypto_binding__tlv {
-	be16 tlv_type;
-	be16 length;
-	u8 reserved;
-	u8 version;
-	u8 received_version;
-	u8 subtype;
-	u8 nonce[32];
-	u8 compound_mac[20];
-} STRUCT_PACKED;
-
-struct eap_tlv_pac_ack_tlv {
-	be16 tlv_type;
-	be16 length;
-	be16 pac_type;
-	be16 pac_len;
-	be16 result;
-} STRUCT_PACKED;
-
-/* RFC 4851, Section 4.2.9 - Request-Action TLV */
-struct eap_tlv_request_action_tlv {
-	be16 tlv_type;
-	be16 length;
-	be16 action;
-} STRUCT_PACKED;
-
-/* draft-cam-winget-eap-fast-provisiong-04.txt, Section 4.2.6 - PAC-Type TLV */
-struct eap_tlv_pac_type_tlv {
-	be16 tlv_type; /* PAC_TYPE_PAC_TYPE */
-	be16 length;
-	be16 pac_type;
-} 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
-
-#define EAP_TLV_ACTION_PROCESS_TLV 1
-#define EAP_TLV_ACTION_NEGOTIATE_EAP 2
-
+#include "eap_common/eap_tlv_common.h"
 
 u8 * eap_tlv_build_nak(int id, u16 nak_type, size_t *resp_len);
 u8 * eap_tlv_build_result(int id, u16 status, size_t *resp_len);

Modified: wpasupplicant/trunk/src/eap_peer/eap_ttls.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/eap_peer/eap_ttls.c?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/src/eap_peer/eap_ttls.c (original)
+++ wpasupplicant/trunk/src/eap_peer/eap_ttls.c Sat Nov  3 11:46:49 2007
@@ -198,7 +198,7 @@
 
 static u8 * eap_ttls_avp_add(u8 *start, u8 *avphdr, u32 avp_code,
 			     u32 vendor_id, int mandatory,
-			     u8 *data, size_t len)
+			     const u8 *data, size_t len)
 {
 	u8 *pos;
 	pos = eap_ttls_avp_hdr(avphdr, avp_code, vendor_id, mandatory, len);
@@ -615,13 +615,23 @@
 #if EAP_TTLS_VERSION > 0
 	u8 pw_hash[16], pw_hash_hash[16], master_key[16];
 	u8 session_key[2 * MSCHAPV2_KEY_LEN];
-	struct wpa_ssid *config = eap_get_config(sm);
+	const u8 *password;
+	size_t password_len;
+	int pwhash;
 
 	if (data->ttls_version == 0)
 		return;
 
-	nt_password_hash(config->password, config->password_len, pw_hash);
-	hash_nt_password_hash(pw_hash, pw_hash_hash);
+	password = eap_get_config_password2(sm, &password_len, &pwhash);
+	if (password == NULL)
+		return;
+
+	if (pwhash)
+		hash_nt_password_hash(password, pw_hash_hash);
+	else {
+		nt_password_hash(password, password_len, pw_hash);
+		hash_nt_password_hash(pw_hash, pw_hash_hash);
+	}
 	get_master_key(pw_hash_hash, nt_response, master_key);
 	get_asymetric_start_key(master_key, session_key,
 				MSCHAPV2_KEY_LEN, 0, 0);
@@ -638,18 +648,22 @@
 					    struct eap_method_ret *ret,
 					    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, i;
+	u8 *buf, *pos, *challenge, *peer_challenge;
+	const u8 *identity, *username, *password;
+	size_t identity_len, password_len, username_len, i;
+	int pwhash;
 
 	wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 MSCHAPV2 Request");
 
 	/* 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;
-	pos = username;
+	identity = eap_get_config_identity(sm, &identity_len);
+	password = eap_get_config_password2(sm, &password_len, &pwhash);
+	if (identity == NULL || password == NULL)
+		return -1;
+	username = identity;
+	username_len = identity_len;
 	for (i = 0; i < username_len; i++) {
 		if (username[i] == '\\') {
 			username_len -= i + 1;
@@ -658,7 +672,7 @@
 		}
 	}
 
-	pos = buf = os_malloc(config->identity_len + 1000);
+	pos = buf = os_malloc(identity_len + 1000);
 	if (buf == NULL) {
 		wpa_printf(MSG_ERROR,
 			   "EAP-TTLS/MSCHAPV2: Failed to allocate memory");
@@ -667,7 +681,7 @@
 
 	/* User-Name */
 	pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1,
-			       config->identity, config->identity_len);
+			       identity, identity_len);
 
 	/* MS-CHAP-Challenge */
 	challenge = eap_ttls_implicit_challenge(
@@ -701,17 +715,28 @@
 		    peer_challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN);
 	wpa_hexdump_ascii(MSG_DEBUG, "EAP-TTLS: MSCHAPV2 username",
 			  username, username_len);
-	wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-TTLS: 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-TTLS: MSCHAPV2 response", pos, 24);
-	generate_authenticator_response(config->password, config->password_len,
-					peer_challenge, challenge,
-					username, username_len,
-					pos, data->auth_response);
+	if (pwhash) {
+		wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: MSCHAPV2 password hash",
+				password, 16);
+		generate_nt_response_pwhash(challenge, peer_challenge,
+					    username, username_len,
+					    password, pos);
+		wpa_hexdump(MSG_DEBUG, "EAP-TTLS: MSCHAPV2 response", pos, 24);
+		generate_authenticator_response_pwhash(
+			password, peer_challenge, challenge,
+			username, username_len, pos, data->auth_response);
+	} else {
+		wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-TTLS: MSCHAPV2 password",
+				      password, password_len);
+		generate_nt_response(challenge, peer_challenge,
+				     username, username_len,
+				     password, password_len, pos);
+		wpa_hexdump(MSG_DEBUG, "EAP-TTLS: MSCHAPV2 response", pos, 24);
+		generate_authenticator_response(password, password_len,
+						peer_challenge, challenge,
+						username, username_len,
+						pos, data->auth_response);
+	}
 	data->auth_response_valid = 1;
 
 	eap_ttlsv1_permute_inner(sm, data, pos);
@@ -742,12 +767,19 @@
 					  struct eap_method_ret *ret,
 					  u8 **resp, size_t *resp_len)
 {
-	struct wpa_ssid *config = eap_get_config(sm);
 	u8 *buf, *pos, *challenge;
+	const u8 *identity, *password;
+	size_t identity_len, password_len;
+	int pwhash;
 
 	wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 MSCHAP Request");
 
-	pos = buf = os_malloc(config->identity_len + 1000);
+	identity = eap_get_config_identity(sm, &identity_len);
+	password = eap_get_config_password2(sm, &password_len, &pwhash);
+	if (identity == NULL || password == NULL)
+		return -1;
+
+	pos = buf = os_malloc(identity_len + 1000);
 	if (buf == NULL) {
 		wpa_printf(MSG_ERROR,
 			   "EAP-TTLS/MSCHAP: Failed to allocate memory");
@@ -756,7 +788,7 @@
 
 	/* User-Name */
 	pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1,
-			       config->identity, config->identity_len);
+			       identity, identity_len);
 
 	/* MS-CHAP-Challenge */
 	challenge = eap_ttls_implicit_challenge(sm, data, EAP_TLS_KEY_LEN);
@@ -780,11 +812,16 @@
 	*pos++ = 1; /* Flags: Use NT style passwords */
 	os_memset(pos, 0, 24); /* LM-Response */
 	pos += 24;
-	nt_challenge_response(challenge,
-			      config->password, config->password_len,
-			      pos); /* NT-Response */
-	wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-TTLS: MSCHAP password",
-			      config->password, config->password_len);
+	if (pwhash) {
+		challenge_response(challenge, password, pos); /* NT-Response */
+		wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: MSCHAP password hash",
+				password, 16);
+	} else {
+		nt_challenge_response(challenge, password, password_len,
+				      pos); /* NT-Response */
+		wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-TTLS: MSCHAP password",
+				      password, password_len);
+	}
 	wpa_hexdump(MSG_DEBUG, "EAP-TTLS: MSCHAP implicit challenge",
 		    challenge, EAP_TTLS_MSCHAP_CHALLENGE_LEN);
 	wpa_hexdump(MSG_DEBUG, "EAP-TTLS: MSCHAP response", pos, 24);
@@ -816,14 +853,19 @@
 				       struct eap_method_ret *ret,
 				       u8 **resp, size_t *resp_len)
 {
-	struct wpa_ssid *config = eap_get_config(sm);
 	u8 *buf, *pos;
 	size_t pad;
+	const u8 *identity, *password;
+	size_t identity_len, password_len;
 
 	wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 PAP Request");
 
-	pos = buf = os_malloc(config->identity_len + config->password_len +
-			      100);
+	identity = eap_get_config_identity(sm, &identity_len);
+	password = eap_get_config_password(sm, &password_len);
+	if (identity == NULL || password == NULL)
+		return -1;
+
+	pos = buf = os_malloc(identity_len + password_len + 100);
 	if (buf == NULL) {
 		wpa_printf(MSG_ERROR,
 			   "EAP-TTLS/PAP: Failed to allocate memory");
@@ -832,16 +874,16 @@
 
 	/* User-Name */
 	pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1,
-			       config->identity, config->identity_len);
+			       identity, identity_len);
 
 	/* User-Password; in RADIUS, this is encrypted, but EAP-TTLS encrypts
 	 * the data, so no separate encryption is used in the AVP itself.
 	 * However, the password is padded to obfuscate its length. */
-	pad = (16 - (config->password_len & 15)) & 15;
+	pad = (16 - (password_len & 15)) & 15;
 	pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_USER_PASSWORD, 0, 1,
-			       config->password_len + pad);
-	os_memcpy(pos, config->password, config->password_len);
-	pos += config->password_len;
+			       password_len + pad);
+	os_memcpy(pos, password, password_len);
+	pos += password_len;
 	os_memset(pos, 0, pad);
 	pos += pad;
 	AVP_PAD(buf, pos);
@@ -870,14 +912,20 @@
 					struct eap_method_ret *ret,
 					u8 **resp, size_t *resp_len)
 {
-	struct wpa_ssid *config = eap_get_config(sm);
 	u8 *buf, *pos, *challenge;
 	const u8 *addr[3];
 	size_t len[3];
+	const u8 *identity, *password;
+	size_t identity_len, password_len;
 
 	wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 CHAP Request");
 
-	pos = buf = os_malloc(config->identity_len + 1000);
+	identity = eap_get_config_identity(sm, &identity_len);
+	password = eap_get_config_password(sm, &password_len);
+	if (identity == NULL || password == NULL)
+		return -1;
+
+	pos = buf = os_malloc(identity_len + 1000);
 	if (buf == NULL) {
 		wpa_printf(MSG_ERROR,
 			   "EAP-TTLS/CHAP: Failed to allocate memory");
@@ -886,7 +934,7 @@
 
 	/* User-Name */
 	pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1,
-			       config->identity, config->identity_len);
+			       identity, identity_len);
 
 	/* CHAP-Challenge */
 	challenge = eap_ttls_implicit_challenge(sm, data, EAP_TLS_KEY_LEN);
@@ -909,16 +957,16 @@
 	/* MD5(Ident + Password + Challenge) */
 	addr[0] = &data->ident;
 	len[0] = 1;
-	addr[1] = config->password;
-	len[1] = config->password_len;
+	addr[1] = password;
+	len[1] = password_len;
 	addr[2] = challenge;
 	len[2] = EAP_TTLS_CHAP_CHALLENGE_LEN;
 	md5_vector(3, addr, len, pos);
 
 	wpa_hexdump_ascii(MSG_DEBUG, "EAP-TTLS: CHAP username",
-			  config->identity, config->identity_len);
+			  identity, identity_len);
 	wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-TTLS: CHAP password",
-			      config->password, config->password_len);
+			      password, password_len);
 	wpa_hexdump(MSG_DEBUG, "EAP-TTLS: CHAP implicit challenge",
 		    challenge, EAP_TTLS_CHAP_CHALLENGE_LEN);
 	wpa_hexdump(MSG_DEBUG, "EAP-TTLS: CHAP password",

Modified: wpasupplicant/trunk/src/eap_peer/tncc.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/eap_peer/tncc.c?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/src/eap_peer/tncc.c (original)
+++ wpasupplicant/trunk/src/eap_peer/tncc.c Sat Nov  3 11:46:49 2007
@@ -684,9 +684,7 @@
 		}
 
 		pos += 6;
-		while (*pos == ' ')
-			pos++;
-		type = atoi(pos);
+		type = strtoul(pos, NULL, 16);
 		wpa_printf(MSG_DEBUG, "TNC: IMC-IMV-Message Type 0x%x", type);
 
 		pos = os_strstr(start, "<Base64>");

Modified: wpasupplicant/trunk/src/eap_server/eap.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/eap_server/eap.c?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/src/eap_server/eap.c (original)
+++ wpasupplicant/trunk/src/eap_server/eap.c Sat Nov  3 11:46:49 2007
@@ -941,6 +941,15 @@
 	sm->ssl_ctx = conf->ssl_ctx;
 	sm->eap_sim_db_priv = conf->eap_sim_db_priv;
 	sm->backend_auth = conf->backend_auth;
+	if (conf->pac_opaque_encr_key) {
+		sm->pac_opaque_encr_key = os_malloc(16);
+		if (sm->pac_opaque_encr_key) {
+			os_memcpy(sm->pac_opaque_encr_key,
+				  conf->pac_opaque_encr_key, 16);
+		}
+	}
+	if (conf->eap_fast_a_id)
+		sm->eap_fast_a_id = strdup(conf->eap_fast_a_id);
 
 	wpa_printf(MSG_DEBUG, "EAP: Server state machine created");
 
@@ -967,6 +976,8 @@
 	free(sm->lastReqData);
 	free(sm->eapRespData);
 	free(sm->identity);
+	free(sm->pac_opaque_encr_key);
+	free(sm->eap_fast_a_id);
 	eap_user_free(sm->user);
 	free(sm);
 }

Modified: wpasupplicant/trunk/src/eap_server/eap.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/eap_server/eap.h?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/src/eap_server/eap.h (original)
+++ wpasupplicant/trunk/src/eap_server/eap.h Sat Nov  3 11:46:49 2007
@@ -57,6 +57,8 @@
 	void *ssl_ctx;
 	void *eap_sim_db_priv;
 	Boolean backend_auth;
+	u8 *pac_opaque_encr_key;
+	char *eap_fast_a_id;
 };
 
 

Modified: wpasupplicant/trunk/src/eap_server/eap_gpsk.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/eap_server/eap_gpsk.c?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/src/eap_server/eap_gpsk.c (original)
+++ wpasupplicant/trunk/src/eap_server/eap_gpsk.c Sat Nov  3 11:46:49 2007
@@ -1,5 +1,5 @@
 /*
- * hostapd / EAP-GPSK (draft-ietf-emu-eap-gpsk-04.txt) server
+ * hostapd / EAP-GPSK (draft-ietf-emu-eap-gpsk-06.txt) server
  * Copyright (c) 2006-2007, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -84,17 +84,17 @@
 	data->csuite_count = 0;
 	if (eap_gpsk_supported_ciphersuite(EAP_GPSK_VENDOR_IETF,
 					   EAP_GPSK_CIPHER_AES)) {
-		WPA_PUT_BE24(data->csuite_list[data->csuite_count].vendor,
+		WPA_PUT_BE32(data->csuite_list[data->csuite_count].vendor,
 			     EAP_GPSK_VENDOR_IETF);
-		WPA_PUT_BE24(data->csuite_list[data->csuite_count].specifier,
+		WPA_PUT_BE16(data->csuite_list[data->csuite_count].specifier,
 			     EAP_GPSK_CIPHER_AES);
 		data->csuite_count++;
 	}
 	if (eap_gpsk_supported_ciphersuite(EAP_GPSK_VENDOR_IETF,
 					   EAP_GPSK_CIPHER_SHA256)) {
-		WPA_PUT_BE24(data->csuite_list[data->csuite_count].vendor,
+		WPA_PUT_BE32(data->csuite_list[data->csuite_count].vendor,
 			     EAP_GPSK_VENDOR_IETF);
-		WPA_PUT_BE24(data->csuite_list[data->csuite_count].specifier,
+		WPA_PUT_BE16(data->csuite_list[data->csuite_count].specifier,
 			     EAP_GPSK_CIPHER_SHA256);
 		data->csuite_count++;
 	}
@@ -192,8 +192,8 @@
 	memcpy(pos, data->rand_server, EAP_GPSK_RAND_LEN);
 	pos += EAP_GPSK_RAND_LEN;
 	csuite = (struct eap_gpsk_csuite *) pos;
-	WPA_PUT_BE24(csuite->vendor, data->vendor);
-	WPA_PUT_BE24(csuite->specifier, data->specifier);
+	WPA_PUT_BE32(csuite->vendor, data->vendor);
+	WPA_PUT_BE16(csuite->specifier, data->specifier);
 	pos += sizeof(*csuite);
 
 	/* no PD_Payload_2 */
@@ -396,13 +396,13 @@
 	if (i == data->csuite_count) {
 		wpa_printf(MSG_DEBUG, "EAP-GPSK: Peer selected unsupported "
 			   "ciphersuite %d:%d",
-			   WPA_GET_BE24(csuite->vendor),
-			   WPA_GET_BE24(csuite->specifier));
-		eap_gpsk_state(data, FAILURE);
-		return;
-	}
-	data->vendor = WPA_GET_BE24(csuite->vendor);
-	data->specifier = WPA_GET_BE24(csuite->specifier);
+			   WPA_GET_BE32(csuite->vendor),
+			   WPA_GET_BE16(csuite->specifier));
+		eap_gpsk_state(data, FAILURE);
+		return;
+	}
+	data->vendor = WPA_GET_BE32(csuite->vendor);
+	data->specifier = WPA_GET_BE16(csuite->specifier);
 	wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite_Sel %d:%d",
 		   data->vendor, data->specifier);
 	pos += sizeof(*csuite);	

Modified: wpasupplicant/trunk/src/eap_server/eap_gtc.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/eap_server/eap_gtc.c?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/src/eap_server/eap_gtc.c (original)
+++ wpasupplicant/trunk/src/eap_server/eap_gtc.c Sat Nov  3 11:46:49 2007
@@ -20,6 +20,7 @@
 
 struct eap_gtc_data {
 	enum { CONTINUE, SUCCESS, FAILURE } state;
+	int prefix;
 };
 
 
@@ -32,6 +33,15 @@
 		return NULL;
 	data->state = CONTINUE;
 
+#ifdef EAP_FAST
+	if (sm->m && sm->m->vendor == EAP_VENDOR_IETF &&
+	    sm->m->method == EAP_TYPE_FAST) {
+		wpa_printf(MSG_DEBUG, "EAP-GTC: EAP-FAST tunnel - use prefix "
+			   "with challenge/response");
+		data->prefix = 1;
+	}
+#endif /* EAP_FAST */
+
 	return data;
 }
 
@@ -49,8 +59,10 @@
 	struct eap_gtc_data *data = priv;
 	struct eap_hdr *req;
 	u8 *pos;
-	char *msg = "Password";
+	char *msg;
 	size_t msg_len;
+
+	msg = data->prefix ? "CHALLENGE=Password" : "Password";
 
 	msg_len = strlen(msg);
 	req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GTC, reqDataLen,
@@ -94,6 +106,64 @@
 	const u8 *pos;
 	size_t rlen;
 
+	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GTC,
+			       respData, respDataLen, &rlen);
+	if (pos == NULL || rlen < 1)
+		return; /* Should not happen - frame already validated */
+
+	wpa_hexdump_ascii_key(MSG_MSGDUMP, "EAP-GTC: Response", pos, rlen);
+
+#ifdef EAP_FAST
+	if (data->prefix) {
+		const u8 *pos2, *end;
+		/* "RESPONSE=<user>\0<password>" */
+		if (rlen < 10) {
+			wpa_printf(MSG_DEBUG, "EAP-GTC: Too short response "
+				   "for EAP-FAST prefix");
+			data->state = FAILURE;
+			return;
+		}
+
+		end = pos + rlen;
+		pos += 9;
+		pos2 = pos;
+		while (pos2 < end && *pos2)
+			pos2++;
+		if (pos2 == end) {
+			wpa_printf(MSG_DEBUG, "EAP-GTC: No password in "
+				   "response to EAP-FAST prefix");
+			data->state = FAILURE;
+			return;
+		}
+
+		wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-GTC: Response user",
+				  pos, pos2 - pos);
+		os_free(sm->identity);
+		sm->identity_len = pos2 - pos;
+		sm->identity = os_malloc(sm->identity_len);
+		if (sm->identity == NULL) {
+			data->state = FAILURE;
+			return;
+		}
+		os_memcpy(sm->identity, pos, sm->identity_len);
+
+		if (eap_user_get(sm, sm->identity, sm->identity_len, 1) != 0) {
+			wpa_hexdump_ascii(MSG_DEBUG, "EAP-GTC: Phase2 "
+					  "Identity not found in the user "
+					  "database",
+					  sm->identity, sm->identity_len);
+			data->state = FAILURE;
+			return;
+		}
+
+		pos = pos2 + 1;
+		rlen = end - pos;
+		wpa_hexdump_ascii_key(MSG_MSGDUMP,
+				      "EAP-GTC: Response password",
+				      pos, rlen);
+	}
+#endif /* EAP_FAST */
+
 	if (sm->user == NULL || sm->user->password == NULL ||
 	    sm->user->password_hash) {
 		wpa_printf(MSG_INFO, "EAP-GTC: Plaintext password not "
@@ -101,13 +171,6 @@
 		data->state = FAILURE;
 		return;
 	}
-
-	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GTC,
-			       respData, respDataLen, &rlen);
-	if (pos == NULL || rlen < 1)
-		return; /* Should not happen - frame already validated */
-
-	wpa_hexdump_key(MSG_MSGDUMP, "EAP-GTC: Response", pos, rlen);
 
 	if (rlen != sm->user->password_len ||
 	    memcmp(pos, sm->user->password, rlen) != 0) {

Modified: wpasupplicant/trunk/src/eap_server/eap_i.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/eap_server/eap_i.h?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/src/eap_server/eap_i.h (original)
+++ wpasupplicant/trunk/src/eap_server/eap_i.h Sat Nov  3 11:46:49 2007
@@ -179,6 +179,12 @@
 	enum {
 		METHOD_PENDING_NONE, METHOD_PENDING_WAIT, METHOD_PENDING_CONT
 	} method_pending;
+
+	u8 *auth_challenge;
+	u8 *peer_challenge;
+
+	u8 *pac_opaque_encr_key;
+	char *eap_fast_a_id;
 };
 
 int eap_user_get(struct eap_sm *sm, const u8 *identity, size_t identity_len,

Modified: wpasupplicant/trunk/src/eap_server/eap_methods.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/eap_server/eap_methods.c?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/src/eap_server/eap_methods.c (original)
+++ wpasupplicant/trunk/src/eap_server/eap_methods.c Sat Nov  3 11:46:49 2007
@@ -247,6 +247,13 @@
 	}
 #endif /* EAP_VENDOR_TEST */
 
+#ifdef EAP_FAST
+	if (ret == 0) {
+		int eap_server_fast_register(void);
+		ret = eap_server_fast_register();
+	}
+#endif /* EAP_FAST */
+
 	return ret;
 }
 

Modified: wpasupplicant/trunk/src/eap_server/eap_mschapv2.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/eap_server/eap_mschapv2.c?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/src/eap_server/eap_mschapv2.c (original)
+++ wpasupplicant/trunk/src/eap_server/eap_mschapv2.c Sat Nov  3 11:46:49 2007
@@ -50,6 +50,8 @@
 
 struct eap_mschapv2_data {
 	u8 auth_challenge[CHALLENGE_LEN];
+	int auth_challenge_from_tls;
+	u8 *peer_challenge;
 	u8 auth_response[20];
 	enum { CHALLENGE, SUCCESS_REQ, FAILURE_REQ, SUCCESS, FAILURE } state;
 	u8 resp_mschapv2_id;
@@ -67,6 +69,22 @@
 		return NULL;
 	data->state = CHALLENGE;
 
+	if (sm->auth_challenge) {
+		os_memcpy(data->auth_challenge, sm->auth_challenge,
+			  CHALLENGE_LEN);
+		data->auth_challenge_from_tls = 1;
+	}
+
+	if (sm->peer_challenge) {
+		data->peer_challenge = os_malloc(CHALLENGE_LEN);
+		if (data->peer_challenge == NULL) {
+			os_free(data);
+			return NULL;
+		}
+		os_memcpy(data->peer_challenge, sm->peer_challenge,
+			  CHALLENGE_LEN);
+	}
+
 	return data;
 }
 
@@ -74,6 +92,10 @@
 static void eap_mschapv2_reset(struct eap_sm *sm, void *priv)
 {
 	struct eap_mschapv2_data *data = priv;
+	if (data == NULL)
+		return;
+
+	free(data->peer_challenge);
 	free(data);
 }
 
@@ -88,7 +110,8 @@
 	char *name = "hostapd"; /* TODO: make this configurable */
 	size_t ms_len;
 
-	if (hostapd_get_rand(data->auth_challenge, CHALLENGE_LEN)) {
+	if (!data->auth_challenge_from_tls &&
+	    hostapd_get_rand(data->auth_challenge, CHALLENGE_LEN)) {
 		wpa_printf(MSG_ERROR, "EAP-MSCHAPV2: Failed to get random "
 			   "data");
 		data->state = FAILURE;
@@ -112,7 +135,8 @@
 
 	pos = (u8 *) (ms + 1);
 	*pos++ = CHALLENGE_LEN;
-	memcpy(pos, data->auth_challenge, CHALLENGE_LEN);
+	if (!data->auth_challenge_from_tls)
+		memcpy(pos, data->auth_challenge, CHALLENGE_LEN);
 	wpa_hexdump(MSG_MSGDUMP, "EAP-MSCHAPV2: Challenge", pos,
 		    CHALLENGE_LEN);
 	pos += CHALLENGE_LEN;
@@ -306,6 +330,11 @@
 	name = pos;
 	name_len = end - name;
 
+	if (data->peer_challenge) {
+		wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Using pre-configured "
+			   "Peer-Challenge");
+		peer_challenge = data->peer_challenge;
+	}
 	wpa_hexdump(MSG_MSGDUMP, "EAP-MSCHAPV2: Peer-Challenge",
 		    peer_challenge, 16);
 	wpa_hexdump(MSG_MSGDUMP, "EAP-MSCHAPV2: NT-Response", nt_response, 24);

Modified: wpasupplicant/trunk/src/eap_server/eap_tlv.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/eap_server/eap_tlv.c?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/src/eap_server/eap_tlv.c (original)
+++ wpasupplicant/trunk/src/eap_server/eap_tlv.c Sat Nov  3 11:46:49 2007
@@ -16,20 +16,7 @@
 
 #include "common.h"
 #include "eap_i.h"
-
-
-/* EAP-TLV TLVs (draft-josefsson-ppext-eap-tls-eap-07.txt) */
-#define EAP_TLV_RESULT_TLV 3 /* Acknowledged Result */
-#define EAP_TLV_NAK_TLV 4
-#define EAP_TLV_CRYPTO_BINDING_TLV 5
-#define EAP_TLV_CONNECTION_BINDING_TLV 6
-#define EAP_TLV_VENDOR_SPECIFIC_TLV 7
-#define EAP_TLV_URI_TLV 8
-#define EAP_TLV_EAP_PAYLOAD_TLV 9
-#define EAP_TLV_INTERMEDIATE_RESULT_TLV 10
-
-#define EAP_TLV_RESULT_SUCCESS 1
-#define EAP_TLV_RESULT_FAILURE 2
+#include "eap_common/eap_tlv_common.h"
 
 
 struct eap_tlv_data {

Modified: wpasupplicant/trunk/src/l2_packet/l2_packet_freebsd.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/l2_packet/l2_packet_freebsd.c?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/src/l2_packet/l2_packet_freebsd.c (original)
+++ wpasupplicant/trunk/src/l2_packet/l2_packet_freebsd.c Sat Nov  3 11:46:49 2007
@@ -14,6 +14,9 @@
  */
 
 #include "includes.h"
+#ifdef __APPLE__
+#include <net/bpf.h>
+#endif /* __APPLE__ */
 #include <pcap.h>
 
 #include <sys/ioctl.h>
@@ -231,8 +234,11 @@
 void l2_packet_deinit(struct l2_packet_data *l2)
 {
 	if (l2 != NULL) {
-		if (l2->pcap)
+		if (l2->pcap) {
+			eloop_unregister_read_sock(
+				pcap_get_selectable_fd(l2->pcap));
 			pcap_close(l2->pcap);
+		}
 		os_free(l2);
 	}
 }

Modified: wpasupplicant/trunk/src/radius/radius_client.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/radius/radius_client.c?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/src/radius/radius_client.c (original)
+++ wpasupplicant/trunk/src/radius/radius_client.c Sat Nov  3 11:46:49 2007
@@ -142,7 +142,8 @@
 #ifndef CONFIG_NATIVE_WINDOWS
 	int _errno = errno;
 	perror("send[RADIUS]");
-	if (_errno == ENOTCONN || _errno == EDESTADDRREQ || _errno == EINVAL) {
+	if (_errno == ENOTCONN || _errno == EDESTADDRREQ || _errno == EINVAL ||
+	    _errno == EBADF) {
 		hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
 			       HOSTAPD_LEVEL_INFO,
 			       "Send failed - maybe interface status changed -"

Modified: wpasupplicant/trunk/src/radius/radius_server.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/radius/radius_server.c?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/src/radius/radius_server.c (original)
+++ wpasupplicant/trunk/src/radius/radius_server.c Sat Nov  3 11:46:49 2007
@@ -87,6 +87,8 @@
 	int num_sess;
 	void *eap_sim_db_priv;
 	void *ssl_ctx;
+	u8 *pac_opaque_encr_key;
+	char *eap_fast_a_id;
 	int ipv6;
 	struct os_time start_time;
 	struct radius_server_counters counters;
@@ -309,6 +311,8 @@
 	eap_conf.ssl_ctx = data->ssl_ctx;
 	eap_conf.eap_sim_db_priv = data->eap_sim_db_priv;
 	eap_conf.backend_auth = TRUE;
+	eap_conf.pac_opaque_encr_key = data->pac_opaque_encr_key;
+	eap_conf.eap_fast_a_id = data->eap_fast_a_id;
 	sess->eap = eap_server_sm_init(sess, &radius_server_eapol_cb,
 				       &eap_conf);
 	if (sess->eap == NULL) {
@@ -999,6 +1003,13 @@
 	data->eap_sim_db_priv = conf->eap_sim_db_priv;
 	data->ssl_ctx = conf->ssl_ctx;
 	data->ipv6 = conf->ipv6;
+	if (conf->pac_opaque_encr_key) {
+		data->pac_opaque_encr_key = os_malloc(16);
+		os_memcpy(data->pac_opaque_encr_key, conf->pac_opaque_encr_key,
+			  16);
+	}
+	if (conf->eap_fast_a_id)
+		data->eap_fast_a_id = os_strdup(conf->eap_fast_a_id);
 	data->get_eap_user = conf->get_eap_user;
 
 	data->clients = radius_server_read_clients(conf->client_file,

Modified: wpasupplicant/trunk/src/radius/radius_server.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/radius/radius_server.h?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/src/radius/radius_server.h (original)
+++ wpasupplicant/trunk/src/radius/radius_server.h Sat Nov  3 11:46:49 2007
@@ -24,6 +24,8 @@
 	void *conf_ctx;
 	void *eap_sim_db_priv;
 	void *ssl_ctx;
+	u8 *pac_opaque_encr_key;
+	char *eap_fast_a_id;
 	int ipv6;
 	int (*get_eap_user)(void *ctx, const u8 *identity, size_t identity_len,
 			    int phase2, struct eap_user *user);

Modified: wpasupplicant/trunk/src/rsn_supp/wpa_ft.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/rsn_supp/wpa_ft.c?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/src/rsn_supp/wpa_ft.c (original)
+++ wpasupplicant/trunk/src/rsn_supp/wpa_ft.c Sat Nov  3 11:46:49 2007
@@ -229,7 +229,7 @@
 	pos += sizeof(*mdie);
 	os_memcpy(mdie->mobility_domain, sm->mobility_domain,
 		  MOBILITY_DOMAIN_ID_LEN);
-	mdie->ft_capab = RSN_FT_CAPAB_FT_OVER_AIR;
+	mdie->ft_capab = 0; /* FIX: copy from the target AP's MDIE */
 
 	/* FTIE[SNonce, R0KH-ID] */
 	*pos++ = WLAN_EID_FAST_BSS_TRANSITION;
@@ -747,7 +747,8 @@
 
 	if (parse.gtk[1] != keylen) {
 		wpa_printf(MSG_DEBUG, "FT: GTK length mismatch: received %d "
-			   "negotiated %d", parse.gtk[1], keylen);
+			   "negotiated %lu",
+			   parse.gtk[1], (unsigned long) keylen);
 		return -1;
 	}
 

Modified: wpasupplicant/trunk/src/tls/asn1.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/tls/asn1.c?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/src/tls/asn1.c (original)
+++ wpasupplicant/trunk/src/tls/asn1.c Sat Nov  3 11:46:49 2007
@@ -58,6 +58,10 @@
 		}
 		tmp &= 0x7f; /* number of subsequent octets */
 		hdr->length = 0;
+		if (tmp > 4) {
+			wpa_printf(MSG_DEBUG, "ASN.1: Too long length field");
+			return -1;
+		}
 		while (tmp--) {
 			if (pos >= end) {
 				wpa_printf(MSG_DEBUG, "ASN.1: Length "
@@ -71,7 +75,7 @@
 		hdr->length = tmp;
 	}
 
-	if (pos + hdr->length > end) {
+	if (end < pos || hdr->length > (unsigned int) (end - pos)) {
 		wpa_printf(MSG_DEBUG, "ASN.1: Contents underflow");
 		return -1;
 	}

Modified: wpasupplicant/trunk/src/tls/tlsv1_client.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/tls/tlsv1_client.c?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/src/tls/tlsv1_client.c (original)
+++ wpasupplicant/trunk/src/tls/tlsv1_client.c Sat Nov  3 11:46:49 2007
@@ -1,6 +1,6 @@
 /*
- * wpa_supplicant: TLSv1 client (RFC 2246)
- * Copyright (c) 2006, Jouni Malinen <j at w1.fi>
+ * TLSv1 client (RFC 2246)
+ * Copyright (c) 2006-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,614 +15,26 @@
 #include "includes.h"
 
 #include "common.h"
-#include "base64.h"
-#include "md5.h"
 #include "sha1.h"
-#include "crypto.h"
 #include "tls.h"
 #include "tlsv1_common.h"
+#include "tlsv1_record.h"
 #include "tlsv1_client.h"
-#include "x509v3.h"
+#include "tlsv1_client_i.h"
 
 /* TODO:
  * Support for a message fragmented across several records (RFC 2246, 6.2.1)
  */
 
-struct tlsv1_client {
-	enum {
-		CLIENT_HELLO, SERVER_HELLO, SERVER_CERTIFICATE,
-		SERVER_KEY_EXCHANGE, SERVER_CERTIFICATE_REQUEST,
-		SERVER_HELLO_DONE, CLIENT_KEY_EXCHANGE, CHANGE_CIPHER_SPEC,
-		SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, ACK_FINISHED,
-		ESTABLISHED, FAILED
-	} state;
-
-	struct tlsv1_record_layer rl;
-
-	u8 session_id[TLS_SESSION_ID_MAX_LEN];
-	size_t session_id_len;
-	u8 client_random[TLS_RANDOM_LEN];
-	u8 server_random[TLS_RANDOM_LEN];
-	u8 master_secret[TLS_MASTER_SECRET_LEN];
-
-	u8 alert_level;
-	u8 alert_description;
-
-	unsigned int certificate_requested:1;
-	unsigned int session_resumed:1;
-	unsigned int ticket:1;
-	unsigned int ticket_key:1;
-
-	struct crypto_public_key *server_rsa_key;
-
-	struct crypto_hash *verify_md5_client;
-	struct crypto_hash *verify_sha1_client;
-	struct crypto_hash *verify_md5_server;
-	struct crypto_hash *verify_sha1_server;
-	struct crypto_hash *verify_md5_cert;
-	struct crypto_hash *verify_sha1_cert;
-
-#define MAX_CIPHER_COUNT 30
-	u16 cipher_suites[MAX_CIPHER_COUNT];
-	size_t num_cipher_suites;
-
-	u16 prev_cipher_suite;
-
-	u8 *client_hello_ext;
-	size_t client_hello_ext_len;
-
-	/* The prime modulus used for Diffie-Hellman */
-	u8 *dh_p;
-	size_t dh_p_len;
-	/* The generator used for Diffie-Hellman */
-	u8 *dh_g;
-	size_t dh_g_len;
-	/* The server's Diffie-Hellman public value */
-	u8 *dh_ys;
-	size_t dh_ys_len;
-
-	struct x509_certificate *trusted_certs;
-	struct x509_certificate *client_cert;
-	struct crypto_private_key *client_key;
-};
-
-
-static int tls_derive_keys(struct tlsv1_client *conn,
-			   const u8 *pre_master_secret,
-			   size_t pre_master_secret_len);
-static int tls_process_server_key_exchange(struct tlsv1_client *conn, u8 ct,
-					   const u8 *in_data, size_t *in_len);
-static int tls_process_certificate_request(struct tlsv1_client *conn, u8 ct,
-					   const u8 *in_data, size_t *in_len);
-static int tls_process_server_hello_done(struct tlsv1_client *conn, u8 ct,
-					 const u8 *in_data, size_t *in_len);
-
-
-static void tls_alert(struct tlsv1_client *conn, u8 level, u8 description)
+
+void tls_alert(struct tlsv1_client *conn, u8 level, u8 description)
 {
 	conn->alert_level = level;
 	conn->alert_description = description;
 }
 
 
-static void tls_verify_hash_add(struct tlsv1_client *conn, const u8 *buf,
-				size_t len)
-{
-	if (conn->verify_md5_client && conn->verify_sha1_client) {
-		crypto_hash_update(conn->verify_md5_client, buf, len);
-		crypto_hash_update(conn->verify_sha1_client, buf, len);
-	}
-	if (conn->verify_md5_server && conn->verify_sha1_server) {
-		crypto_hash_update(conn->verify_md5_server, buf, len);
-		crypto_hash_update(conn->verify_sha1_server, buf, len);
-	}
-	if (conn->verify_md5_cert && conn->verify_sha1_cert) {
-		crypto_hash_update(conn->verify_md5_cert, buf, len);
-		crypto_hash_update(conn->verify_sha1_cert, buf, len);
-	}
-}
-
-
-static u8 * tls_send_alert(struct tlsv1_client *conn,
-			   u8 level, u8 description,
-			   size_t *out_len)
-{
-	u8 *alert, *pos, *length;
-
-	wpa_printf(MSG_DEBUG, "TLSv1: Send Alert(%d:%d)", level, description);
-	*out_len = 0;
-
-	alert = os_malloc(10);
-	if (alert == NULL)
-		return NULL;
-
-	pos = alert;
-
-	/* TLSPlaintext */
-	/* ContentType type */
-	*pos++ = TLS_CONTENT_TYPE_ALERT;
-	/* ProtocolVersion version */
-	WPA_PUT_BE16(pos, TLS_VERSION);
-	pos += 2;
-	/* uint16 length (to be filled) */
-	length = pos;
-	pos += 2;
-	/* opaque fragment[TLSPlaintext.length] */
-
-	/* Alert */
-	/* AlertLevel level */
-	*pos++ = level;
-	/* AlertDescription description */
-	*pos++ = description;
-
-	WPA_PUT_BE16(length, pos - length - 2);
-	*out_len = pos - alert;
-
-	return alert;
-}
-
-
-static u8 * tls_send_client_hello(struct tlsv1_client *conn,
-				  size_t *out_len)
-{
-	u8 *hello, *end, *pos, *hs_length, *hs_start, *rhdr;
-	struct os_time now;
-	size_t len, i;
-
-	wpa_printf(MSG_DEBUG, "TLSv1: Send ClientHello");
-	*out_len = 0;
-
-	os_get_time(&now);
-	WPA_PUT_BE32(conn->client_random, now.sec);
-	if (os_get_random(conn->client_random + 4, TLS_RANDOM_LEN - 4)) {
-		wpa_printf(MSG_ERROR, "TLSv1: Could not generate "
-			   "client_random");
-		return NULL;
-	}
-	wpa_hexdump(MSG_MSGDUMP, "TLSv1: client_random",
-		    conn->client_random, TLS_RANDOM_LEN);
-
-	len = 100 + conn->num_cipher_suites * 2 + conn->client_hello_ext_len;
-	hello = os_malloc(len);
-	if (hello == NULL)
-		return NULL;
-	end = hello + len;
-
-	rhdr = hello;
-	pos = rhdr + TLS_RECORD_HEADER_LEN;
-
-	/* opaque fragment[TLSPlaintext.length] */
-
-	/* Handshake */
-	hs_start = pos;
-	/* HandshakeType msg_type */
-	*pos++ = TLS_HANDSHAKE_TYPE_CLIENT_HELLO;
-	/* uint24 length (to be filled) */
-	hs_length = pos;
-	pos += 3;
-	/* body - ClientHello */
-	/* ProtocolVersion client_version */
-	WPA_PUT_BE16(pos, TLS_VERSION);
-	pos += 2;
-	/* Random random: uint32 gmt_unix_time, opaque random_bytes */
-	os_memcpy(pos, conn->client_random, TLS_RANDOM_LEN);
-	pos += TLS_RANDOM_LEN;
-	/* SessionID session_id */
-	*pos++ = conn->session_id_len;
-	os_memcpy(pos, conn->session_id, conn->session_id_len);
-	pos += conn->session_id_len;
-	/* CipherSuite cipher_suites<2..2^16-1> */
-	WPA_PUT_BE16(pos, 2 * conn->num_cipher_suites);
-	pos += 2;
-	for (i = 0; i < conn->num_cipher_suites; i++) {
-		WPA_PUT_BE16(pos, conn->cipher_suites[i]);
-		pos += 2;
-	}
-	/* CompressionMethod compression_methods<1..2^8-1> */
-	*pos++ = 1;
-	*pos++ = TLS_COMPRESSION_NULL;
-
-	if (conn->client_hello_ext) {
-		os_memcpy(pos, conn->client_hello_ext,
-			  conn->client_hello_ext_len);
-		pos += conn->client_hello_ext_len;
-	}
-
-	WPA_PUT_BE24(hs_length, pos - hs_length - 3);
-	tls_verify_hash_add(conn, hs_start, pos - hs_start);
-
-	if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE,
-			      rhdr, end - rhdr, pos - hs_start, out_len) < 0) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Failed to create TLS record");
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-			  TLS_ALERT_INTERNAL_ERROR);
-		os_free(hello);
-		return NULL;
-	}
-
-	conn->state = SERVER_HELLO;
-
-	return hello;
-}
-
-
-static int tls_process_server_hello(struct tlsv1_client *conn, u8 ct,
-				    const u8 *in_data, size_t *in_len)
-{
-	const u8 *pos, *end;
-	size_t left, len, i;
-	u16 cipher_suite;
-
-	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; "
-			   "received content type 0x%x", ct);
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-			  TLS_ALERT_UNEXPECTED_MESSAGE);
-		return -1;
-	}
-
-	pos = in_data;
-	left = *in_len;
-
-	if (left < 4)
-		goto decode_error;
-
-	/* HandshakeType msg_type */
-	if (*pos != TLS_HANDSHAKE_TYPE_SERVER_HELLO) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake "
-			   "message %d (expected ServerHello)", *pos);
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-			  TLS_ALERT_UNEXPECTED_MESSAGE);
-		return -1;
-	}
-	wpa_printf(MSG_DEBUG, "TLSv1: Received ServerHello");
-	pos++;
-	/* uint24 length */
-	len = WPA_GET_BE24(pos);
-	pos += 3;
-	left -= 4;
-
-	if (len > left)
-		goto decode_error;
-
-	/* body - ServerHello */
-
-	wpa_hexdump(MSG_MSGDUMP, "TLSv1: ServerHello", pos, len);
-	end = pos + len;
-
-	/* ProtocolVersion server_version */
-	if (end - pos < 2)
-		goto decode_error;
-	if (WPA_GET_BE16(pos) != TLS_VERSION) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Unexpected protocol version in "
-			   "ServerHello");
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-			  TLS_ALERT_PROTOCOL_VERSION);
-		return -1;
-	}
-	pos += 2;
-
-	/* Random random */
-	if (end - pos < TLS_RANDOM_LEN)
-		goto decode_error;
-
-	os_memcpy(conn->server_random, pos, TLS_RANDOM_LEN);
-	pos += TLS_RANDOM_LEN;
-	wpa_hexdump(MSG_MSGDUMP, "TLSv1: server_random",
-		    conn->server_random, TLS_RANDOM_LEN);
-
-	/* SessionID session_id */
-	if (end - pos < 1)
-		goto decode_error;
-	if (end - pos < 1 + *pos || *pos > TLS_SESSION_ID_MAX_LEN)
-		goto decode_error;
-	if (conn->session_id_len && conn->session_id_len == *pos &&
-	    os_memcmp(conn->session_id, pos + 1, conn->session_id_len) == 0) {
-		pos += 1 + conn->session_id_len;
-		wpa_printf(MSG_DEBUG, "TLSv1: Resuming old session");
-		conn->session_resumed = 1;
-	} else {
-		conn->session_id_len = *pos;
-		pos++;
-		os_memcpy(conn->session_id, pos, conn->session_id_len);
-		pos += conn->session_id_len;
-	}
-	wpa_hexdump(MSG_MSGDUMP, "TLSv1: session_id",
-		    conn->session_id, conn->session_id_len);
-
-	/* CipherSuite cipher_suite */
-	if (end - pos < 2)
-		goto decode_error;
-	cipher_suite = WPA_GET_BE16(pos);
-	pos += 2;
-	for (i = 0; i < conn->num_cipher_suites; i++) {
-		if (cipher_suite == conn->cipher_suites[i])
-			break;
-	}
-	if (i == conn->num_cipher_suites) {
-		wpa_printf(MSG_INFO, "TLSv1: Server selected unexpected "
-			   "cipher suite 0x%04x", cipher_suite);
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-			  TLS_ALERT_ILLEGAL_PARAMETER);
-		return -1;
-	}
-
-	if (conn->session_resumed && cipher_suite != conn->prev_cipher_suite) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Server selected a different "
-			   "cipher suite for a resumed connection (0x%04x != "
-			   "0x%04x)", cipher_suite, conn->prev_cipher_suite);
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-			  TLS_ALERT_ILLEGAL_PARAMETER);
-		return -1;
-	}
-
-	if (tlsv1_record_set_cipher_suite(&conn->rl, cipher_suite) < 0) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Failed to set CipherSuite for "
-			   "record layer");
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-			  TLS_ALERT_INTERNAL_ERROR);
-		return -1;
-	}
-
-	conn->prev_cipher_suite = cipher_suite;
-
-	if (conn->session_resumed || conn->ticket_key)
-		tls_derive_keys(conn, NULL, 0);
-
-	/* CompressionMethod compression_method */
-	if (end - pos < 1)
-		goto decode_error;
-	if (*pos != TLS_COMPRESSION_NULL) {
-		wpa_printf(MSG_INFO, "TLSv1: Server selected unexpected "
-			   "compression 0x%02x", *pos);
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-			  TLS_ALERT_ILLEGAL_PARAMETER);
-		return -1;
-	}
-	pos++;
-
-	if (end != pos) {
-		wpa_hexdump(MSG_DEBUG, "TLSv1: Unexpected extra data in the "
-			    "end of ServerHello", pos, end - pos);
-		goto decode_error;
-	}
-
-	*in_len = end - in_data;
-
-	conn->state = (conn->session_resumed || conn->ticket) ?
-		SERVER_CHANGE_CIPHER_SPEC : SERVER_CERTIFICATE;
-
-	return 0;
-
-decode_error:
-	wpa_printf(MSG_DEBUG, "TLSv1: Failed to decode ServerHello");
-	tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
-	return -1;
-}
-
-
-static int tls_server_key_exchange_allowed(struct tlsv1_client *conn)
-{
-	const struct tls_cipher_suite *suite;
-
-	/* RFC 2246, Section 7.4.3 */
-	suite = tls_get_cipher_suite(conn->rl.cipher_suite);
-	if (suite == NULL)
-		return 0;
-
-	switch (suite->key_exchange) {
-	case TLS_KEY_X_DHE_DSS:
-	case TLS_KEY_X_DHE_DSS_EXPORT:
-	case TLS_KEY_X_DHE_RSA:
-	case TLS_KEY_X_DHE_RSA_EXPORT:
-	case TLS_KEY_X_DH_anon_EXPORT:
-	case TLS_KEY_X_DH_anon:
-		return 1;
-	case TLS_KEY_X_RSA_EXPORT:
-		return 1 /* FIX: public key len > 512 bits */;
-	default:
-		return 0;
-	}
-}
-
-
-static int tls_process_certificate(struct tlsv1_client *conn, u8 ct,
-				   const u8 *in_data, size_t *in_len)
-{
-	const u8 *pos, *end;
-	size_t left, len, list_len, cert_len, idx;
-	u8 type;
-	struct x509_certificate *chain = NULL, *last = NULL, *cert;
-	int reason;
-
-	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; "
-			   "received content type 0x%x", ct);
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-			  TLS_ALERT_UNEXPECTED_MESSAGE);
-		return -1;
-	}
-
-	pos = in_data;
-	left = *in_len;
-
-	if (left < 4) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Too short Certificate message "
-			   "(len=%lu)", (unsigned long) left);
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
-		return -1;
-	}
-
-	type = *pos++;
-	len = WPA_GET_BE24(pos);
-	pos += 3;
-	left -= 4;
-
-	if (len > left) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Unexpected Certificate message "
-			   "length (len=%lu != left=%lu)",
-			   (unsigned long) len, (unsigned long) left);
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
-		return -1;
-	}
-
-	if (type == TLS_HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE)
-		return tls_process_server_key_exchange(conn, ct, in_data,
-						       in_len);
-	if (type == TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST)
-		return tls_process_certificate_request(conn, ct, in_data,
-						       in_len);
-	if (type == TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE)
-		return tls_process_server_hello_done(conn, ct, in_data,
-						     in_len);
-	if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake "
-			   "message %d (expected Certificate/"
-			   "ServerKeyExchange/CertificateRequest/"
-			   "ServerHelloDone)", type);
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-			  TLS_ALERT_UNEXPECTED_MESSAGE);
-		return -1;
-	}
-
-	wpa_printf(MSG_DEBUG,
-		   "TLSv1: Received Certificate (certificate_list len %lu)",
-		   (unsigned long) len);
-
-	/*
-	 * opaque ASN.1Cert<2^24-1>;
-	 *
-	 * struct {
-	 *     ASN.1Cert certificate_list<1..2^24-1>;
-	 * } Certificate;
-	 */
-
-	end = pos + len;
-
-	if (end - pos < 3) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Too short Certificate "
-			   "(left=%lu)", (unsigned long) left);
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
-		return -1;
-	}
-
-	list_len = WPA_GET_BE24(pos);
-	pos += 3;
-
-	if ((size_t) (end - pos) != list_len) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Unexpected certificate_list "
-			   "length (len=%lu left=%lu)",
-			   (unsigned long) list_len,
-			   (unsigned long) (end - pos));
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
-		return -1;
-	}
-
-	idx = 0;
-	while (pos < end) {
-		if (end - pos < 3) {
-			wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse "
-				   "certificate_list");
-			tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-				  TLS_ALERT_DECODE_ERROR);
-			x509_certificate_chain_free(chain);
-			return -1;
-		}
-
-		cert_len = WPA_GET_BE24(pos);
-		pos += 3;
-
-		if ((size_t) (end - pos) < cert_len) {
-			wpa_printf(MSG_DEBUG, "TLSv1: Unexpected certificate "
-				   "length (len=%lu left=%lu)",
-				   (unsigned long) cert_len,
-				   (unsigned long) (end - pos));
-			tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-				  TLS_ALERT_DECODE_ERROR);
-			x509_certificate_chain_free(chain);
-			return -1;
-		}
-
-		wpa_printf(MSG_DEBUG, "TLSv1: Certificate %lu (len %lu)",
-			   (unsigned long) idx, (unsigned long) cert_len);
-
-		if (idx == 0) {
-			crypto_public_key_free(conn->server_rsa_key);
-			if (tls_parse_cert(pos, cert_len,
-					   &conn->server_rsa_key)) {
-				wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse "
-					   "the certificate");
-				tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-					  TLS_ALERT_BAD_CERTIFICATE);
-				x509_certificate_chain_free(chain);
-				return -1;
-			}
-		}
-
-		cert = x509_certificate_parse(pos, cert_len);
-		if (cert == NULL) {
-			wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse "
-				   "the certificate");
-			tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-				  TLS_ALERT_BAD_CERTIFICATE);
-			x509_certificate_chain_free(chain);
-			return -1;
-		}
-
-		if (last == NULL)
-			chain = cert;
-		else
-			last->next = cert;
-		last = cert;
-
-		idx++;
-		pos += cert_len;
-	}
-
-	if (x509_certificate_chain_validate(conn->trusted_certs, chain,
-					    &reason) < 0) {
-		int tls_reason;
-		wpa_printf(MSG_DEBUG, "TLSv1: Server certificate chain "
-			   "validation failed (reason=%d)", reason);
-		switch (reason) {
-		case X509_VALIDATE_BAD_CERTIFICATE:
-			tls_reason = TLS_ALERT_BAD_CERTIFICATE;
-			break;
-		case X509_VALIDATE_UNSUPPORTED_CERTIFICATE:
-			tls_reason = TLS_ALERT_UNSUPPORTED_CERTIFICATE;
-			break;
-		case X509_VALIDATE_CERTIFICATE_REVOKED:
-			tls_reason = TLS_ALERT_CERTIFICATE_REVOKED;
-			break;
-		case X509_VALIDATE_CERTIFICATE_EXPIRED:
-			tls_reason = TLS_ALERT_CERTIFICATE_EXPIRED;
-			break;
-		case X509_VALIDATE_CERTIFICATE_UNKNOWN:
-			tls_reason = TLS_ALERT_CERTIFICATE_UNKNOWN;
-			break;
-		case X509_VALIDATE_UNKNOWN_CA:
-			tls_reason = TLS_ALERT_UNKNOWN_CA;
-			break;
-		default:
-			tls_reason = TLS_ALERT_BAD_CERTIFICATE;
-			break;
-		}
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, tls_reason);
-		x509_certificate_chain_free(chain);
-		return -1;
-	}
-
-	x509_certificate_chain_free(chain);
-
-	*in_len = end - in_data;
-
-	conn->state = SERVER_KEY_EXCHANGE;
-
-	return 0;
-}
-
-
-static void tlsv1_client_free_dh(struct tlsv1_client *conn)
+void tlsv1_client_free_dh(struct tlsv1_client *conn)
 {
 	os_free(conn->dh_p);
 	os_free(conn->dh_g);
@@ -631,438 +43,7 @@
 }
 
 
-static int tlsv1_process_diffie_hellman(struct tlsv1_client *conn,
-					const u8 *buf, size_t len)
-{
-	const u8 *pos, *end;
-
-	tlsv1_client_free_dh(conn);
-
-	pos = buf;
-	end = buf + len;
-
-	if (end - pos < 3)
-		goto fail;
-	conn->dh_p_len = WPA_GET_BE16(pos);
-	pos += 2;
-	if (conn->dh_p_len == 0 || end - pos < (int) conn->dh_p_len)
-		goto fail;
-	conn->dh_p = os_malloc(conn->dh_p_len);
-	if (conn->dh_p == NULL)
-		goto fail;
-	os_memcpy(conn->dh_p, pos, conn->dh_p_len);
-	pos += conn->dh_p_len;
-	wpa_hexdump(MSG_DEBUG, "TLSv1: DH p (prime)",
-		    conn->dh_p, conn->dh_p_len);
-
-	if (end - pos < 3)
-		goto fail;
-	conn->dh_g_len = WPA_GET_BE16(pos);
-	pos += 2;
-	if (conn->dh_g_len == 0 || end - pos < (int) conn->dh_g_len)
-		goto fail;
-	conn->dh_g = os_malloc(conn->dh_g_len);
-	if (conn->dh_g == NULL)
-		goto fail;
-	os_memcpy(conn->dh_g, pos, conn->dh_g_len);
-	pos += conn->dh_g_len;
-	wpa_hexdump(MSG_DEBUG, "TLSv1: DH g (generator)",
-		    conn->dh_g, conn->dh_g_len);
-	if (conn->dh_g_len == 1 && conn->dh_g[0] < 2)
-		goto fail;
-
-	if (end - pos < 3)
-		goto fail;
-	conn->dh_ys_len = WPA_GET_BE16(pos);
-	pos += 2;
-	if (conn->dh_ys_len == 0 || end - pos < (int) conn->dh_ys_len)
-		goto fail;
-	conn->dh_ys = os_malloc(conn->dh_ys_len);
-	if (conn->dh_ys == NULL)
-		goto fail;
-	os_memcpy(conn->dh_ys, pos, conn->dh_ys_len);
-	pos += conn->dh_ys_len;
-	wpa_hexdump(MSG_DEBUG, "TLSv1: DH Ys (server's public value)",
-		    conn->dh_ys, conn->dh_ys_len);
-
-	return 0;
-
-fail:
-	tlsv1_client_free_dh(conn);
-	return -1;
-}
-
-
-static int tls_process_server_key_exchange(struct tlsv1_client *conn, u8 ct,
-					   const u8 *in_data, size_t *in_len)
-{
-	const u8 *pos, *end;
-	size_t left, len;
-	u8 type;
-	const struct tls_cipher_suite *suite;
-
-	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; "
-			   "received content type 0x%x", ct);
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-			  TLS_ALERT_UNEXPECTED_MESSAGE);
-		return -1;
-	}
-
-	pos = in_data;
-	left = *in_len;
-
-	if (left < 4) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Too short ServerKeyExchange "
-			   "(Left=%lu)", (unsigned long) left);
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
-		return -1;
-	}
-
-	type = *pos++;
-	len = WPA_GET_BE24(pos);
-	pos += 3;
-	left -= 4;
-
-	if (len > left) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in ServerKeyExchange "
-			   "length (len=%lu != left=%lu)",
-			   (unsigned long) len, (unsigned long) left);
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
-		return -1;
-	}
-
-	end = pos + len;
-
-	if (type == TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST)
-		return tls_process_certificate_request(conn, ct, in_data,
-						       in_len);
-	if (type == TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE)
-		return tls_process_server_hello_done(conn, ct, in_data,
-						     in_len);
-	if (type != TLS_HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake "
-			   "message %d (expected ServerKeyExchange/"
-			   "CertificateRequest/ServerHelloDone)", type);
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-			  TLS_ALERT_UNEXPECTED_MESSAGE);
-		return -1;
-	}
-
-	wpa_printf(MSG_DEBUG, "TLSv1: Received ServerKeyExchange");
-
-	if (!tls_server_key_exchange_allowed(conn)) {
-		wpa_printf(MSG_DEBUG, "TLSv1: ServerKeyExchange not allowed "
-			   "with the selected cipher suite");
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-			  TLS_ALERT_UNEXPECTED_MESSAGE);
-		return -1;
-	}
-
-	wpa_hexdump(MSG_DEBUG, "TLSv1: ServerKeyExchange", pos, len);
-	suite = tls_get_cipher_suite(conn->rl.cipher_suite);
-	if (suite && suite->key_exchange == TLS_KEY_X_DH_anon) {
-		if (tlsv1_process_diffie_hellman(conn, pos, len) < 0) {
-			tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-				  TLS_ALERT_DECODE_ERROR);
-			return -1;
-		}
-	} else {
-		wpa_printf(MSG_DEBUG, "TLSv1: UnexpectedServerKeyExchange");
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-			  TLS_ALERT_UNEXPECTED_MESSAGE);
-		return -1;
-	}
-
-	*in_len = end - in_data;
-
-	conn->state = SERVER_CERTIFICATE_REQUEST;
-
-	return 0;
-}
-
-
-static int tls_process_certificate_request(struct tlsv1_client *conn, u8 ct,
-					   const u8 *in_data, size_t *in_len)
-{
-	const u8 *pos, *end;
-	size_t left, len;
-	u8 type;
-
-	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; "
-			   "received content type 0x%x", ct);
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-			  TLS_ALERT_UNEXPECTED_MESSAGE);
-		return -1;
-	}
-
-	pos = in_data;
-	left = *in_len;
-
-	if (left < 4) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Too short CertificateRequest "
-			   "(left=%lu)", (unsigned long) left);
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
-		return -1;
-	}
-
-	type = *pos++;
-	len = WPA_GET_BE24(pos);
-	pos += 3;
-	left -= 4;
-
-	if (len > left) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in CertificateRequest "
-			   "length (len=%lu != left=%lu)",
-			   (unsigned long) len, (unsigned long) left);
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
-		return -1;
-	}
-
-	end = pos + len;
-
-	if (type == TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE)
-		return tls_process_server_hello_done(conn, ct, in_data,
-						     in_len);
-	if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake "
-			   "message %d (expected CertificateRequest/"
-			   "ServerHelloDone)", type);
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-			  TLS_ALERT_UNEXPECTED_MESSAGE);
-		return -1;
-	}
-
-	wpa_printf(MSG_DEBUG, "TLSv1: Received CertificateRequest");
-
-	conn->certificate_requested = 1;
-
-	*in_len = end - in_data;
-
-	conn->state = SERVER_HELLO_DONE;
-
-	return 0;
-}
-
-
-static int tls_process_server_hello_done(struct tlsv1_client *conn, u8 ct,
-					 const u8 *in_data, size_t *in_len)
-{
-	const u8 *pos, *end;
-	size_t left, len;
-	u8 type;
-
-	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; "
-			   "received content type 0x%x", ct);
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-			  TLS_ALERT_UNEXPECTED_MESSAGE);
-		return -1;
-	}
-
-	pos = in_data;
-	left = *in_len;
-
-	if (left < 4) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Too short ServerHelloDone "
-			   "(left=%lu)", (unsigned long) left);
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
-		return -1;
-	}
-
-	type = *pos++;
-	len = WPA_GET_BE24(pos);
-	pos += 3;
-	left -= 4;
-
-	if (len > left) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in ServerHelloDone "
-			   "length (len=%lu != left=%lu)",
-			   (unsigned long) len, (unsigned long) left);
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
-		return -1;
-	}
-	end = pos + len;
-
-	if (type != TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake "
-			   "message %d (expected ServerHelloDone)", type);
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-			  TLS_ALERT_UNEXPECTED_MESSAGE);
-		return -1;
-	}
-
-	wpa_printf(MSG_DEBUG, "TLSv1: Received ServerHelloDone");
-
-	*in_len = end - in_data;
-
-	conn->state = CLIENT_KEY_EXCHANGE;
-
-	return 0;
-}
-
-
-static int tls_process_server_change_cipher_spec(struct tlsv1_client *conn,
-						 u8 ct, const u8 *in_data,
-						 size_t *in_len)
-{
-	const u8 *pos;
-	size_t left;
-
-	if (ct != TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Expected ChangeCipherSpec; "
-			   "received content type 0x%x", ct);
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-			  TLS_ALERT_UNEXPECTED_MESSAGE);
-		return -1;
-	}
-
-	pos = in_data;
-	left = *in_len;
-
-	if (left < 1) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Too short ChangeCipherSpec");
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
-		return -1;
-	}
-
-	if (*pos != TLS_CHANGE_CIPHER_SPEC) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Expected ChangeCipherSpec; "
-			   "received data 0x%x", *pos);
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-			  TLS_ALERT_UNEXPECTED_MESSAGE);
-		return -1;
-	}
-
-	wpa_printf(MSG_DEBUG, "TLSv1: Received ChangeCipherSpec");
-	if (tlsv1_record_change_read_cipher(&conn->rl) < 0) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Failed to change read cipher "
-			   "for record layer");
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-			  TLS_ALERT_INTERNAL_ERROR);
-		return -1;
-	}
-
-	*in_len = pos + 1 - in_data;
-
-	conn->state = SERVER_FINISHED;
-
-	return 0;
-}
-
-
-static int tls_process_server_finished(struct tlsv1_client *conn, u8 ct,
-				       const u8 *in_data, size_t *in_len)
-{
-	const u8 *pos, *end;
-	size_t left, len, hlen;
-	u8 verify_data[TLS_VERIFY_DATA_LEN];
-	u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN];
-
-	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Expected Finished; "
-			   "received content type 0x%x", ct);
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-			  TLS_ALERT_UNEXPECTED_MESSAGE);
-		return -1;
-	}
-
-	pos = in_data;
-	left = *in_len;
-
-	if (left < 4) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Too short record (left=%lu) for "
-			   "Finished",
-			   (unsigned long) left);
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-			  TLS_ALERT_DECODE_ERROR);
-		return -1;
-	}
-
-	if (pos[0] != TLS_HANDSHAKE_TYPE_FINISHED) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Expected Finished; received "
-			   "type 0x%x", pos[0]);
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-			  TLS_ALERT_UNEXPECTED_MESSAGE);
-		return -1;
-	}
-
-	len = WPA_GET_BE24(pos + 1);
-
-	pos += 4;
-	left -= 4;
-
-	if (len > left) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Too short buffer for Finished "
-			   "(len=%lu > left=%lu)",
-			   (unsigned long) len, (unsigned long) left);
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-			  TLS_ALERT_DECODE_ERROR);
-		return -1;
-	}
-	end = pos + len;
-	if (len != TLS_VERIFY_DATA_LEN) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Unexpected verify_data length "
-			   "in Finished: %lu (expected %d)",
-			   (unsigned long) len, TLS_VERIFY_DATA_LEN);
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-			  TLS_ALERT_DECODE_ERROR);
-		return -1;
-	}
-	wpa_hexdump(MSG_MSGDUMP, "TLSv1: verify_data in Finished",
-		    pos, TLS_VERIFY_DATA_LEN);
-
-	hlen = MD5_MAC_LEN;
-	if (conn->verify_md5_server == NULL ||
-	    crypto_hash_finish(conn->verify_md5_server, hash, &hlen) < 0) {
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-			  TLS_ALERT_INTERNAL_ERROR);
-		conn->verify_md5_server = NULL;
-		crypto_hash_finish(conn->verify_sha1_server, NULL, NULL);
-		conn->verify_sha1_server = NULL;
-		return -1;
-	}
-	conn->verify_md5_server = NULL;
-	hlen = SHA1_MAC_LEN;
-	if (conn->verify_sha1_server == NULL ||
-	    crypto_hash_finish(conn->verify_sha1_server, hash + MD5_MAC_LEN,
-			       &hlen) < 0) {
-		conn->verify_sha1_server = NULL;
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-			  TLS_ALERT_INTERNAL_ERROR);
-		return -1;
-	}
-	conn->verify_sha1_server = NULL;
-
-	if (tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN,
-		    "server finished", hash, MD5_MAC_LEN + SHA1_MAC_LEN,
-		    verify_data, TLS_VERIFY_DATA_LEN)) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive verify_data");
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-			  TLS_ALERT_DECRYPT_ERROR);
-		return -1;
-	}
-	wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (server)",
-			verify_data, TLS_VERIFY_DATA_LEN);
-
-	if (os_memcmp(pos, verify_data, TLS_VERIFY_DATA_LEN) != 0) {
-		wpa_printf(MSG_INFO, "TLSv1: Mismatch in verify_data");
-		return -1;
-	}
-
-	wpa_printf(MSG_DEBUG, "TLSv1: Received Finished");
-
-	*in_len = end - in_data;
-
-	conn->state = (conn->session_resumed || conn->ticket) ?
-		CHANGE_CIPHER_SPEC : ACK_FINISHED;
-
-	return 0;
-}
-
-
-static int tls_derive_pre_master_secret(u8 *pre_master_secret)
+int tls_derive_pre_master_secret(u8 *pre_master_secret)
 {
 	WPA_PUT_BE16(pre_master_secret, TLS_VERSION);
 	if (os_get_random(pre_master_secret + 2,
@@ -1072,9 +53,8 @@
 }
 
 
-static int tls_derive_keys(struct tlsv1_client *conn,
-			   const u8 *pre_master_secret,
-			   size_t pre_master_secret_len)
+int tls_derive_keys(struct tlsv1_client *conn,
+		    const u8 *pre_master_secret, size_t pre_master_secret_len)
 {
 	u8 seed[2 * TLS_RANDOM_LEN];
 	u8 key_block[TLS_MAX_KEY_BLOCK_LEN];
@@ -1138,718 +118,6 @@
 }
 
 
-static int tls_write_client_certificate(struct tlsv1_client *conn,
-					u8 **msgpos, u8 *end)
-{
-	u8 *pos, *rhdr, *hs_start, *hs_length, *cert_start;
-	size_t rlen;
-	struct x509_certificate *cert;
-
-	pos = *msgpos;
-
-	wpa_printf(MSG_DEBUG, "TLSv1: Send Certificate");
-	rhdr = pos;
-	pos += TLS_RECORD_HEADER_LEN;
-
-	/* opaque fragment[TLSPlaintext.length] */
-
-	/* Handshake */
-	hs_start = pos;
-	/* HandshakeType msg_type */
-	*pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE;
-	/* uint24 length (to be filled) */
-	hs_length = pos;
-	pos += 3;
-	/* body - Certificate */
-	/* uint24 length (to be filled) */
-	cert_start = pos;
-	pos += 3;
-	cert = conn->client_cert;
-	while (cert) {
-		if (pos + 3 + cert->cert_len > end) {
-			wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space "
-				   "for Certificate (cert_len=%lu left=%lu)",
-				   (unsigned long) cert->cert_len,
-				   (unsigned long) (end - pos));
-			tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-				  TLS_ALERT_INTERNAL_ERROR);
-			return -1;
-		}
-		WPA_PUT_BE24(pos, cert->cert_len);
-		pos += 3;
-		os_memcpy(pos, cert->cert_start, cert->cert_len);
-		pos += cert->cert_len;
-
-		if (x509_certificate_self_signed(cert))
-			break;
-		cert = x509_certificate_get_subject(conn->trusted_certs,
-						    &cert->issuer);
-	}
-	if (cert == conn->client_cert || cert == NULL) {
-		/*
-		 * Client was not configured with all the needed certificates
-		 * to form a full certificate chain. The server may fail to
-		 * validate the chain unless it is configured with all the
-		 * missing CA certificates.
-		 */
-		wpa_printf(MSG_DEBUG, "TLSv1: Full client certificate chain "
-			   "not configured - validation may fail");
-	}
-	WPA_PUT_BE24(cert_start, pos - cert_start - 3);
-
-	WPA_PUT_BE24(hs_length, pos - hs_length - 3);
-
-	if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE,
-			      rhdr, end - rhdr, pos - hs_start, &rlen) < 0) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record");
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-			  TLS_ALERT_INTERNAL_ERROR);
-		return -1;
-	}
-	pos = rhdr + rlen;
-
-	tls_verify_hash_add(conn, hs_start, pos - hs_start);
-
-	*msgpos = pos;
-
-	return 0;
-}
-
-
-static int tlsv1_key_x_anon_dh(struct tlsv1_client *conn, u8 **pos, u8 *end)
-{
-#ifdef EAP_FAST
-	/* ClientDiffieHellmanPublic */
-	u8 *csecret, *csecret_start, *dh_yc, *shared;
-	size_t csecret_len, dh_yc_len, shared_len;
-
-	csecret_len = conn->dh_p_len;
-	csecret = os_malloc(csecret_len);
-	if (csecret == NULL) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate "
-			   "memory for Yc (Diffie-Hellman)");
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-			  TLS_ALERT_INTERNAL_ERROR);
-		return -1;
-	}
-	if (os_get_random(csecret, csecret_len)) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Failed to get random "
-			   "data for Diffie-Hellman");
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-			  TLS_ALERT_INTERNAL_ERROR);
-		os_free(csecret);
-		return -1;
-	}
-
-	if (os_memcmp(csecret, conn->dh_p, csecret_len) > 0)
-		csecret[0] = 0; /* make sure Yc < p */
-
-	csecret_start = csecret;
-	while (csecret_len > 1 && *csecret_start == 0) {
-		csecret_start++;
-		csecret_len--;
-	}
-	wpa_hexdump_key(MSG_DEBUG, "TLSv1: DH client's secret value",
-			csecret_start, csecret_len);
-
-	/* Yc = g^csecret mod p */
-	dh_yc_len = conn->dh_p_len;
-	dh_yc = os_malloc(dh_yc_len);
-	if (dh_yc == NULL) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate "
-			   "memory for Diffie-Hellman");
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-			  TLS_ALERT_INTERNAL_ERROR);
-		os_free(csecret);
-		return -1;
-	}
-	crypto_mod_exp(conn->dh_g, conn->dh_g_len,
-		       csecret_start, csecret_len,
-		       conn->dh_p, conn->dh_p_len,
-		       dh_yc, &dh_yc_len);
-
-	wpa_hexdump(MSG_DEBUG, "TLSv1: DH Yc (client's public value)",
-		    dh_yc, dh_yc_len);
-
-	WPA_PUT_BE16(*pos, dh_yc_len);
-	*pos += 2;
-	if (*pos + dh_yc_len > end) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Not enough room in the "
-			   "message buffer for Yc");
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-			  TLS_ALERT_INTERNAL_ERROR);
-		os_free(csecret);
-		os_free(dh_yc);
-		return -1;
-	}
-	os_memcpy(*pos, dh_yc, dh_yc_len);
-	*pos += dh_yc_len;
-	os_free(dh_yc);
-
-	shared_len = conn->dh_p_len;
-	shared = os_malloc(shared_len);
-	if (shared == NULL) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Could not allocate memory for "
-			   "DH");
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-			  TLS_ALERT_INTERNAL_ERROR);
-		os_free(csecret);
-		return -1;
-	}
-
-	/* shared = Ys^csecret mod p */
-	crypto_mod_exp(conn->dh_ys, conn->dh_ys_len,
-		       csecret_start, csecret_len,
-		       conn->dh_p, conn->dh_p_len,
-		       shared, &shared_len);
-	wpa_hexdump_key(MSG_DEBUG, "TLSv1: Shared secret from DH key exchange",
-			shared, shared_len);
-
-	os_memset(csecret_start, 0, csecret_len);
-	os_free(csecret);
-	if (tls_derive_keys(conn, shared, shared_len)) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys");
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-			  TLS_ALERT_INTERNAL_ERROR);
-		os_free(shared);
-		return -1;
-	}
-	os_memset(shared, 0, shared_len);
-	os_free(shared);
-	tlsv1_client_free_dh(conn);
-	return 0;
-#else /* EAP_FAST */
-	tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR);
-	return -1;
-#endif /* EAP_FAST */
-}
-
-
-static int tlsv1_key_x_rsa(struct tlsv1_client *conn, u8 **pos, u8 *end)
-{
-	u8 pre_master_secret[TLS_PRE_MASTER_SECRET_LEN];
-	size_t clen;
-	int res;
-
-	if (tls_derive_pre_master_secret(pre_master_secret) < 0 ||
-	    tls_derive_keys(conn, pre_master_secret,
-			    TLS_PRE_MASTER_SECRET_LEN)) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys");
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-			  TLS_ALERT_INTERNAL_ERROR);
-		return -1;
-	}
-
-	/* EncryptedPreMasterSecret */
-	if (conn->server_rsa_key == NULL) {
-		wpa_printf(MSG_DEBUG, "TLSv1: No server RSA key to "
-			   "use for encrypting pre-master secret");
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-			  TLS_ALERT_INTERNAL_ERROR);
-		return -1;
-	}
-
-	/* RSA encrypted value is encoded with PKCS #1 v1.5 block type 2. */
-	*pos += 2;
-	clen = end - *pos;
-	res = crypto_public_key_encrypt_pkcs1_v15(
-		conn->server_rsa_key,
-		pre_master_secret, TLS_PRE_MASTER_SECRET_LEN,
-		*pos, &clen);
-	os_memset(pre_master_secret, 0, TLS_PRE_MASTER_SECRET_LEN);
-	if (res < 0) {
-		wpa_printf(MSG_DEBUG, "TLSv1: RSA encryption failed");
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-			  TLS_ALERT_INTERNAL_ERROR);
-		return -1;
-	}
-	WPA_PUT_BE16(*pos - 2, clen);
-	wpa_hexdump(MSG_MSGDUMP, "TLSv1: Encrypted pre_master_secret",
-		    *pos, clen);
-	*pos += clen;
-
-	return 0;
-}
-
-
-static int tls_write_client_key_exchange(struct tlsv1_client *conn,
-					 u8 **msgpos, u8 *end)
-{
-	u8 *pos, *rhdr, *hs_start, *hs_length;
-	size_t rlen;
-	tls_key_exchange keyx;
-	const struct tls_cipher_suite *suite;
-
-	suite = tls_get_cipher_suite(conn->rl.cipher_suite);
-	if (suite == NULL)
-		keyx = TLS_KEY_X_NULL;
-	else
-		keyx = suite->key_exchange;
-
-	pos = *msgpos;
-
-	wpa_printf(MSG_DEBUG, "TLSv1: Send ClientKeyExchange");
-
-	rhdr = pos;
-	pos += TLS_RECORD_HEADER_LEN;
-
-	/* opaque fragment[TLSPlaintext.length] */
-
-	/* Handshake */
-	hs_start = pos;
-	/* HandshakeType msg_type */
-	*pos++ = TLS_HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE;
-	/* uint24 length (to be filled) */
-	hs_length = pos;
-	pos += 3;
-	/* body - ClientKeyExchange */
-	if (keyx == TLS_KEY_X_DH_anon) {
-		if (tlsv1_key_x_anon_dh(conn, &pos, end) < 0)
-			return -1;
-	} else {
-		if (tlsv1_key_x_rsa(conn, &pos, end) < 0)
-			return -1;
-	}
-
-	WPA_PUT_BE24(hs_length, pos - hs_length - 3);
-
-	if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE,
-			      rhdr, end - rhdr, pos - hs_start, &rlen) < 0) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record");
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-			  TLS_ALERT_INTERNAL_ERROR);
-		return -1;
-	}
-	pos = rhdr + rlen;
-	tls_verify_hash_add(conn, hs_start, pos - hs_start);
-
-	*msgpos = pos;
-
-	return 0;
-}
-
-
-static int tls_write_client_certificate_verify(struct tlsv1_client *conn,
-					       u8 **msgpos, u8 *end)
-{
-	u8 *pos, *rhdr, *hs_start, *hs_length, *signed_start;
-	size_t rlen, hlen, clen;
-	u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN], *hpos;
-	enum { SIGN_ALG_RSA, SIGN_ALG_DSA } alg = SIGN_ALG_RSA;
-
-	pos = *msgpos;
-
-	wpa_printf(MSG_DEBUG, "TLSv1: Send CertificateVerify");
-	rhdr = pos;
-	pos += TLS_RECORD_HEADER_LEN;
-
-	/* Handshake */
-	hs_start = pos;
-	/* HandshakeType msg_type */
-	*pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE_VERIFY;
-	/* uint24 length (to be filled) */
-	hs_length = pos;
-	pos += 3;
-
-	/*
-	 * RFC 2246: 7.4.3 and 7.4.8:
-	 * Signature signature
-	 *
-	 * RSA:
-	 * digitally-signed struct {
-	 *     opaque md5_hash[16];
-	 *     opaque sha_hash[20];
-	 * };
-	 *
-	 * DSA:
-	 * digitally-signed struct {
-	 *     opaque sha_hash[20];
-	 * };
-	 *
-	 * The hash values are calculated over all handshake messages sent or
-	 * received starting at ClientHello up to, but not including, this
-	 * CertificateVerify message, including the type and length fields of
-	 * the handshake messages.
-	 */
-
-	hpos = hash;
-
-	if (alg == SIGN_ALG_RSA) {
-		hlen = MD5_MAC_LEN;
-		if (conn->verify_md5_cert == NULL ||
-		    crypto_hash_finish(conn->verify_md5_cert, hpos, &hlen) < 0)
-		{
-			tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-				  TLS_ALERT_INTERNAL_ERROR);
-			conn->verify_md5_cert = NULL;
-			crypto_hash_finish(conn->verify_sha1_cert, NULL, NULL);
-			conn->verify_sha1_cert = NULL;
-			return -1;
-		}
-		hpos += MD5_MAC_LEN;
-	} else
-		crypto_hash_finish(conn->verify_md5_cert, NULL, NULL);
-
-	conn->verify_md5_cert = NULL;
-	hlen = SHA1_MAC_LEN;
-	if (conn->verify_sha1_cert == NULL ||
-	    crypto_hash_finish(conn->verify_sha1_cert, hpos, &hlen) < 0) {
-		conn->verify_sha1_cert = NULL;
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-			  TLS_ALERT_INTERNAL_ERROR);
-		return -1;
-	}
-	conn->verify_sha1_cert = NULL;
-
-	if (alg == SIGN_ALG_RSA)
-		hlen += MD5_MAC_LEN;
-
-	wpa_hexdump(MSG_MSGDUMP, "TLSv1: CertificateVerify hash", hash, hlen);
-
-	/*
-	 * RFC 2246, 4.7:
-	 * In digital signing, one-way hash functions are used as input for a
-	 * signing algorithm. A digitally-signed element is encoded as an
-	 * opaque vector <0..2^16-1>, where the length is specified by the
-	 * signing algorithm and key.
-	 *
-	 * In RSA signing, a 36-byte structure of two hashes (one SHA and one
-	 * MD5) is signed (encrypted with the private key). It is encoded with
-	 * PKCS #1 block type 0 or type 1 as described in [PKCS1].
-	 */
-	signed_start = pos; /* length to be filled */
-	pos += 2;
-	clen = end - pos;
-	if (crypto_private_key_sign_pkcs1(conn->client_key, hash, hlen,
-					  pos, &clen) < 0) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Failed to sign hash (PKCS #1)");
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-			  TLS_ALERT_INTERNAL_ERROR);
-		return -1;
-	}
-	WPA_PUT_BE16(signed_start, clen);
-
-	pos += clen;
-
-	WPA_PUT_BE24(hs_length, pos - hs_length - 3);
-
-	if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE,
-			      rhdr, end - rhdr, pos - hs_start, &rlen) < 0) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record");
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-			  TLS_ALERT_INTERNAL_ERROR);
-		return -1;
-	}
-	pos = rhdr + rlen;
-
-	tls_verify_hash_add(conn, hs_start, pos - hs_start);
-
-	*msgpos = pos;
-
-	return 0;
-}
-
-
-static int tls_write_client_change_cipher_spec(struct tlsv1_client *conn,
-					       u8 **msgpos, u8 *end)
-{
-	u8 *pos, *rhdr;
-	size_t rlen;
-
-	pos = *msgpos;
-
-	wpa_printf(MSG_DEBUG, "TLSv1: Send ChangeCipherSpec");
-	rhdr = pos;
-	pos += TLS_RECORD_HEADER_LEN;
-	*pos = TLS_CHANGE_CIPHER_SPEC;
-	if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC,
-			      rhdr, end - rhdr, 1, &rlen) < 0) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record");
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-			  TLS_ALERT_INTERNAL_ERROR);
-		return -1;
-	}
-
-	if (tlsv1_record_change_write_cipher(&conn->rl) < 0) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Failed to set write cipher for "
-			   "record layer");
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-			  TLS_ALERT_INTERNAL_ERROR);
-		return -1;
-	}
-
-	*msgpos = rhdr + rlen;
-
-	return 0;
-}
-
-
-static int tls_write_client_finished(struct tlsv1_client *conn,
-				     u8 **msgpos, u8 *end)
-{
-	u8 *pos, *rhdr, *hs_start, *hs_length;
-	size_t rlen, hlen;
-	u8 verify_data[TLS_VERIFY_DATA_LEN];
-	u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN];
-
-	pos = *msgpos;
-
-	wpa_printf(MSG_DEBUG, "TLSv1: Send Finished");
-
-	/* Encrypted Handshake Message: Finished */
-
-	hlen = MD5_MAC_LEN;
-	if (conn->verify_md5_client == NULL ||
-	    crypto_hash_finish(conn->verify_md5_client, hash, &hlen) < 0) {
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-			  TLS_ALERT_INTERNAL_ERROR);
-		conn->verify_md5_client = NULL;
-		crypto_hash_finish(conn->verify_sha1_client, NULL, NULL);
-		conn->verify_sha1_client = NULL;
-		return -1;
-	}
-	conn->verify_md5_client = NULL;
-	hlen = SHA1_MAC_LEN;
-	if (conn->verify_sha1_client == NULL ||
-	    crypto_hash_finish(conn->verify_sha1_client, hash + MD5_MAC_LEN,
-			       &hlen) < 0) {
-		conn->verify_sha1_client = NULL;
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-			  TLS_ALERT_INTERNAL_ERROR);
-		return -1;
-	}
-	conn->verify_sha1_client = NULL;
-
-	if (tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN,
-		    "client finished", hash, MD5_MAC_LEN + SHA1_MAC_LEN,
-		    verify_data, TLS_VERIFY_DATA_LEN)) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate verify_data");
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-			  TLS_ALERT_INTERNAL_ERROR);
-		return -1;
-	}
-	wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (client)",
-			verify_data, TLS_VERIFY_DATA_LEN);
-
-	rhdr = pos;
-	pos += TLS_RECORD_HEADER_LEN;
-	/* Handshake */
-	hs_start = pos;
-	/* HandshakeType msg_type */
-	*pos++ = TLS_HANDSHAKE_TYPE_FINISHED;
-	/* uint24 length (to be filled) */
-	hs_length = pos;
-	pos += 3;
-	os_memcpy(pos, verify_data, TLS_VERIFY_DATA_LEN);
-	pos += TLS_VERIFY_DATA_LEN;
-	WPA_PUT_BE24(hs_length, pos - hs_length - 3);
-	tls_verify_hash_add(conn, hs_start, pos - hs_start);
-
-	if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE,
-			      rhdr, end - rhdr, pos - hs_start, &rlen) < 0) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record");
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-			  TLS_ALERT_INTERNAL_ERROR);
-		return -1;
-	}
-
-	pos = rhdr + rlen;
-
-	*msgpos = pos;
-
-	return 0;
-}
-
-
-static size_t tls_client_cert_chain_der_len(struct tlsv1_client *conn)
-{
-	size_t len = 0;
-	struct x509_certificate *cert;
-
-	cert = conn->client_cert;
-	while (cert) {
-		len += 3 + cert->cert_len;
-		if (x509_certificate_self_signed(cert))
-			break;
-		cert = x509_certificate_get_subject(conn->trusted_certs,
-						    &cert->issuer);
-	}
-
-	return len;
-}
-
-
-static u8 * tls_send_client_key_exchange(struct tlsv1_client *conn,
-					 size_t *out_len)
-{
-	u8 *msg, *end, *pos;
-	size_t msglen;
-
-	*out_len = 0;
-
-	msglen = 1000;
-	if (conn->certificate_requested)
-		msglen += tls_client_cert_chain_der_len(conn);
-
-	msg = os_malloc(msglen);
-	if (msg == NULL)
-		return NULL;
-
-	pos = msg;
-	end = msg + msglen;
-
-	if (conn->certificate_requested) {
-		if (tls_write_client_certificate(conn, &pos, end) < 0) {
-			os_free(msg);
-			return NULL;
-		}
-	}
-
-	if (tls_write_client_key_exchange(conn, &pos, end) < 0 ||
-	    (conn->certificate_requested && conn->client_key &&
-	     tls_write_client_certificate_verify(conn, &pos, end) < 0) ||
-	    tls_write_client_change_cipher_spec(conn, &pos, end) < 0 ||
-	    tls_write_client_finished(conn, &pos, end) < 0) {
-		os_free(msg);
-		return NULL;
-	}
-
-	*out_len = pos - msg;
-
-	conn->state = SERVER_CHANGE_CIPHER_SPEC;
-
-	return msg;
-}
-
-
-static u8 * tls_send_change_cipher_spec(struct tlsv1_client *conn,
-					size_t *out_len)
-{
-	u8 *msg, *end, *pos;
-
-	*out_len = 0;
-
-	msg = os_malloc(1000);
-	if (msg == NULL)
-		return NULL;
-
-	pos = msg;
-	end = msg + 1000;
-
-	if (tls_write_client_change_cipher_spec(conn, &pos, end) < 0 ||
-	    tls_write_client_finished(conn, &pos, end) < 0) {
-		os_free(msg);
-		return NULL;
-	}
-
-	*out_len = pos - msg;
-
-	wpa_printf(MSG_DEBUG, "TLSv1: Session resumption completed "
-		   "successfully");
-	conn->state = ESTABLISHED;
-
-	return msg;
-}
-
-
-static int tls_process_application_data(struct tlsv1_client *conn, u8 ct,
-					const u8 *in_data, size_t *in_len,
-					u8 **out_data, size_t *out_len)
-{
-	const u8 *pos;
-	size_t left;
-
-	if (ct != TLS_CONTENT_TYPE_APPLICATION_DATA) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Expected Application Data; "
-			   "received content type 0x%x", ct);
-		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-			  TLS_ALERT_UNEXPECTED_MESSAGE);
-		return -1;
-	}
-
-	pos = in_data;
-	left = *in_len;
-
-	wpa_hexdump(MSG_DEBUG, "TLSv1: Application Data included in Handshake",
-		    pos, left);
-
-	*out_data = os_malloc(left);
-	if (*out_data) {
-		os_memcpy(*out_data, pos, left);
-		*out_len = left;
-	}
-
-	return 0;
-}
-
-
-static int tlsv1_client_process_handshake(struct tlsv1_client *conn, u8 ct,
-					  const u8 *buf, size_t *len,
-					  u8 **out_data, size_t *out_len)
-{
-	if (ct == TLS_CONTENT_TYPE_HANDSHAKE && *len >= 4 &&
-	    buf[0] == TLS_HANDSHAKE_TYPE_HELLO_REQUEST) {
-		size_t hr_len = WPA_GET_BE24(buf + 1);
-		if (hr_len > *len - 4) {
-			wpa_printf(MSG_DEBUG, "TLSv1: HelloRequest underflow");
-			tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
-				  TLS_ALERT_DECODE_ERROR);
-			return -1;
-		}
-		wpa_printf(MSG_DEBUG, "TLSv1: Ignored HelloRequest");
-		*len = 4 + hr_len;
-		return 0;
-	}
-
-	switch (conn->state) {
-	case SERVER_HELLO:
-		if (tls_process_server_hello(conn, ct, buf, len))
-			return -1;
-		break;
-	case SERVER_CERTIFICATE:
-		if (tls_process_certificate(conn, ct, buf, len))
-			return -1;
-		break;
-	case SERVER_KEY_EXCHANGE:
-		if (tls_process_server_key_exchange(conn, ct, buf, len))
-			return -1;
-		break;
-	case SERVER_CERTIFICATE_REQUEST:
-		if (tls_process_certificate_request(conn, ct, buf, len))
-			return -1;
-		break;
-	case SERVER_HELLO_DONE:
-		if (tls_process_server_hello_done(conn, ct, buf, len))
-			return -1;
-		break;
-	case SERVER_CHANGE_CIPHER_SPEC:
-		if (tls_process_server_change_cipher_spec(conn, ct, buf, len))
-			return -1;
-		break;
-	case SERVER_FINISHED:
-		if (tls_process_server_finished(conn, ct, buf, len))
-			return -1;
-		break;
-	case ACK_FINISHED:
-		if (out_data &&
-		    tls_process_application_data(conn, ct, buf, len, out_data,
-						 out_len))
-			return -1;
-		break;
-	default:
-		wpa_printf(MSG_DEBUG, "TLSv1: Unexpected state %d "
-			   "while processing received message",
-			   conn->state);
-		return -1;
-	}
-
-	if (ct == TLS_CONTENT_TYPE_HANDSHAKE)
-		tls_verify_hash_add(conn, buf, *len);
-
-	return 0;
-}
-
-
 /**
  * tlsv1_client_handshake - Process TLS handshake
  * @conn: TLSv1 client connection data from tlsv1_client_init()
@@ -1866,6 +134,7 @@
 	const u8 *pos, *end;
 	u8 *msg = NULL, *in_msg, *in_pos, *in_end, alert, ct;
 	size_t in_msg_len;
+	int no_appl_data;
 
 	if (conn->state == CLIENT_HELLO) {
 		if (in_len)
@@ -1915,36 +184,20 @@
 	os_free(in_msg);
 	in_msg = NULL;
 
-	switch (conn->state) {
-	case CLIENT_KEY_EXCHANGE:
-		msg = tls_send_client_key_exchange(conn, out_len);
-		break;
-	case CHANGE_CIPHER_SPEC:
-		msg = tls_send_change_cipher_spec(conn, out_len);
-		break;
-	case ACK_FINISHED:
-		wpa_printf(MSG_DEBUG, "TLSv1: Handshake completed "
-			   "successfully");
-		conn->state = ESTABLISHED;
-		if (appl_data == NULL || *appl_data == NULL) {
-			/* Need to return something to get final TLS ACK. */
-			msg = os_malloc(1);
-		}
-		*out_len = 0;
-		break;
-	default:
-		wpa_printf(MSG_DEBUG, "TLSv1: Unexpected state %d while "
-			   "generating reply", conn->state);
-		break;
-	}
+	no_appl_data = appl_data == NULL || *appl_data == NULL;
+	msg = tlsv1_client_handshake_write(conn, out_len, no_appl_data);
 
 failed:
 	os_free(in_msg);
 	if (conn->alert_level) {
 		conn->state = FAILED;
 		os_free(msg);
-		msg = tls_send_alert(conn, conn->alert_level,
-				     conn->alert_description, out_len);
+		msg = tlsv1_client_send_alert(conn, conn->alert_level,
+					      conn->alert_description,
+					      out_len);
+	} else if (msg == NULL) {
+		msg = os_zalloc(1);
+		*out_len = 0;
 	}
 
 	return msg;
@@ -2071,49 +324,6 @@
 }
 
 
-static void tlsv1_client_free_verify_hashes(struct tlsv1_client *conn)
-{
-	crypto_hash_finish(conn->verify_md5_client, NULL, NULL);
-	crypto_hash_finish(conn->verify_md5_server, NULL, NULL);
-	crypto_hash_finish(conn->verify_md5_cert, NULL, NULL);
-	crypto_hash_finish(conn->verify_sha1_client, NULL, NULL);
-	crypto_hash_finish(conn->verify_sha1_server, NULL, NULL);
-	crypto_hash_finish(conn->verify_sha1_cert, NULL, NULL);
-	conn->verify_md5_client = NULL;
-	conn->verify_md5_server = NULL;
-	conn->verify_md5_cert = NULL;
-	conn->verify_sha1_client = NULL;
-	conn->verify_sha1_server = NULL;
-	conn->verify_sha1_cert = NULL;
-}
-
-
-static int tlsv1_client_init_verify_hashes(struct tlsv1_client *conn)
-{
-	conn->verify_md5_client = crypto_hash_init(CRYPTO_HASH_ALG_MD5, NULL,
-						   0);
-	conn->verify_md5_server = crypto_hash_init(CRYPTO_HASH_ALG_MD5, NULL,
-						   0);
-	conn->verify_md5_cert = crypto_hash_init(CRYPTO_HASH_ALG_MD5, NULL, 0);
-	conn->verify_sha1_client = crypto_hash_init(CRYPTO_HASH_ALG_SHA1, NULL,
-						    0);
-	conn->verify_sha1_server = crypto_hash_init(CRYPTO_HASH_ALG_SHA1, NULL,
-						    0);
-	conn->verify_sha1_cert = crypto_hash_init(CRYPTO_HASH_ALG_SHA1, NULL,
-						  0);
-	if (conn->verify_md5_client == NULL ||
-	    conn->verify_md5_server == NULL ||
-	    conn->verify_md5_cert == NULL ||
-	    conn->verify_sha1_client == NULL ||
-	    conn->verify_sha1_server == NULL ||
-	    conn->verify_sha1_cert == NULL) {
-		tlsv1_client_free_verify_hashes(conn);
-		return -1;
-	}
-	return 0;
-}
-
-
 /**
  * tlsv1_client_init - Initialize TLSv1 client connection
  * Returns: Pointer to TLSv1 client connection data or %NULL on failure
@@ -2130,7 +340,7 @@
 
 	conn->state = CLIENT_HELLO;
 
-	if (tlsv1_client_init_verify_hashes(conn) < 0) {
+	if (tls_verify_hash_init(&conn->verify) < 0) {
 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to initialize verify "
 			   "hash");
 		os_free(conn);
@@ -2162,12 +372,10 @@
 	tlsv1_record_set_cipher_suite(&conn->rl, TLS_NULL_WITH_NULL_NULL);
 	tlsv1_record_change_write_cipher(&conn->rl);
 	tlsv1_record_change_read_cipher(&conn->rl);
-	tlsv1_client_free_verify_hashes(conn);
+	tls_verify_hash_free(&conn->verify);
 	os_free(conn->client_hello_ext);
 	tlsv1_client_free_dh(conn);
-	x509_certificate_chain_free(conn->trusted_certs);
-	x509_certificate_chain_free(conn->client_cert);
-	crypto_private_key_free(conn->client_key);
+	tlsv1_cred_free(conn->cred);
 	os_free(conn);
 }
 
@@ -2271,8 +479,7 @@
 {
 	conn->state = CLIENT_HELLO;
 
-	tlsv1_client_free_verify_hashes(conn);
-	if (tlsv1_client_init_verify_hashes(conn) < 0) {
+	if (tls_verify_hash_init(&conn->verify) < 0) {
 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to re-initialize verify "
 			   "hash");
 		return -1;
@@ -2315,7 +522,7 @@
 {
 	u8 *pos;
 
-	conn->ticket = 0;
+	conn->session_ticket_included = 0;
 	os_free(conn->client_hello_ext);
 	conn->client_hello_ext = NULL;
 	conn->client_hello_ext_len = 0;
@@ -2337,7 +544,7 @@
 	conn->client_hello_ext_len = 6 + data_len;
 
 	if (ext_type == TLS_EXT_PAC_OPAQUE) {
-		conn->ticket = 1;
+		conn->session_ticket_included = 1;
 		wpa_printf(MSG_DEBUG, "TLSv1: Using session ticket");
 	}
 
@@ -2372,27 +579,6 @@
 
 
 /**
- * tlsv1_client_set_master_key - Configure master secret for TLS connection
- * @conn: TLSv1 client connection data from tlsv1_client_init()
- * @key: TLS pre-master-secret
- * @key_len: length of key in bytes
- * Returns: 0 on success, -1 on failure
- */
-int tlsv1_client_set_master_key(struct tlsv1_client *conn,
-				const u8 *key, size_t key_len)
-{
-	if (key_len > TLS_MASTER_SECRET_LEN)
-		return -1;
-	wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: master_secret from session "
-			"ticket", key, key_len);
-	os_memcpy(conn->master_secret, key, key_len);
-	conn->ticket_key = 1;
-
-	return 0;
-}
-
-
-/**
  * tlsv1_client_get_keyblock_size - Get TLS key_block size
  * @conn: TLSv1 client connection data from tlsv1_client_init()
  * Returns: Size of the key_block for the negotiated cipher suite or -1 on
@@ -2425,7 +611,9 @@
 	if (ciphers[0] == TLS_CIPHER_ANON_DH_AES128_SHA) {
 		count = 0;
 		suites = conn->cipher_suites;
+#ifndef CONFIG_CRYPTO_INTERNAL
 		suites[count++] = TLS_DH_anon_WITH_AES_256_CBC_SHA;
+#endif /* CONFIG_CRYPTO_INTERNAL */
 		suites[count++] = TLS_DH_anon_WITH_AES_128_CBC_SHA;
 		suites[count++] = TLS_DH_anon_WITH_3DES_EDE_CBC_SHA;
 		suites[count++] = TLS_DH_anon_WITH_RC4_128_MD5;
@@ -2440,223 +628,31 @@
 }
 
 
-static int tlsv1_client_add_cert_der(struct x509_certificate **chain,
-				     const u8 *buf, size_t len)
-{
-	struct x509_certificate *cert;
-	char name[128];
-
-	cert = x509_certificate_parse(buf, len);
-	if (cert == NULL) {
-		wpa_printf(MSG_INFO, "TLSv1: %s - failed to parse certificate",
-			   __func__);
-		return -1;
-	}
-
-	cert->next = *chain;
-	*chain = cert;
-
-	x509_name_string(&cert->subject, name, sizeof(name));
-	wpa_printf(MSG_DEBUG, "TLSv1: Added certificate: %s", name);
-
-	return 0;
-}
-
-
-static const char *pem_cert_begin = "-----BEGIN CERTIFICATE-----";
-static const char *pem_cert_end = "-----END CERTIFICATE-----";
-
-
-static const u8 * search_tag(const char *tag, const u8 *buf, size_t len)
-{
-	size_t i, plen;
-
-	plen = os_strlen(tag);
-	if (len < plen)
-		return NULL;
-
-	for (i = 0; i < len - plen; i++) {
-		if (os_memcmp(buf + i, tag, plen) == 0)
-			return buf + i;
-	}
-
-	return NULL;
-}
-
-
-static int tlsv1_client_add_cert(struct x509_certificate **chain,
-				 const u8 *buf, size_t len)
-{
-	const u8 *pos, *end;
-	unsigned char *der;
-	size_t der_len;
-
-	pos = search_tag(pem_cert_begin, buf, len);
-	if (!pos) {
-		wpa_printf(MSG_DEBUG, "TLSv1: No PEM certificate tag found - "
-			   "assume DER format");
-		return tlsv1_client_add_cert_der(chain, buf, len);
-	}
-
-	wpa_printf(MSG_DEBUG, "TLSv1: Converting PEM format certificate into "
-		   "DER format");
-
-	while (pos) {
-		pos += os_strlen(pem_cert_begin);
-		end = search_tag(pem_cert_end, pos, buf + len - pos);
-		if (end == NULL) {
-			wpa_printf(MSG_INFO, "TLSv1: Could not find PEM "
-				   "certificate end tag (%s)", pem_cert_end);
-			return -1;
-		}
-
-		der = base64_decode(pos, end - pos, &der_len);
-		if (der == NULL) {
-			wpa_printf(MSG_INFO, "TLSv1: Could not decode PEM "
-				   "certificate");
-			return -1;
-		}
-
-		if (tlsv1_client_add_cert_der(chain, der, der_len) < 0) {
-			wpa_printf(MSG_INFO, "TLSv1: Failed to parse PEM "
-				   "certificate after DER conversion");
-			os_free(der);
-			return -1;
-		}
-
-		os_free(der);
-
-		end += os_strlen(pem_cert_end);
-		pos = search_tag(pem_cert_begin, end, buf + len - end);
-	}
-
-	return 0;
-}
-
-
-static int tlsv1_client_set_cert_chain(struct x509_certificate **chain,
-				       const char *cert, const u8 *cert_blob,
-				       size_t cert_blob_len)
-{
-	if (cert_blob)
-		return tlsv1_client_add_cert(chain, cert_blob, cert_blob_len);
-
-	if (cert) {
-		u8 *buf;
-		size_t len;
-		int ret;
-
-		buf = (u8 *) os_readfile(cert, &len);
-		if (buf == NULL) {
-			wpa_printf(MSG_INFO, "TLSv1: Failed to read '%s'",
-				   cert);
-			return -1;
-		}
-
-		ret = tlsv1_client_add_cert(chain, buf, len);
-		os_free(buf);
-		return ret;
-	}
-
-	return 0;
-}
-
-
-/**
- * tlsv1_client_set_ca_cert - Set trusted CA certificate(s)
- * @conn: TLSv1 client connection data from tlsv1_client_init()
- * @cert: File or reference name for X.509 certificate in PEM or DER format
- * @cert_blob: cert as inlined data or %NULL if not used
- * @cert_blob_len: ca_cert_blob length
- * @path: Path to CA certificates (not yet supported)
- * Returns: 0 on success, -1 on failure
- */
-int tlsv1_client_set_ca_cert(struct tlsv1_client *conn, const char *cert,
-			     const u8 *cert_blob, size_t cert_blob_len,
-			     const char *path)
-{
-	if (tlsv1_client_set_cert_chain(&conn->trusted_certs, cert,
-					cert_blob, cert_blob_len) < 0)
-		return -1;
-
-	if (path) {
-		/* TODO: add support for reading number of certificate files */
-		wpa_printf(MSG_INFO, "TLSv1: Use of CA certificate directory "
-			   "not yet supported");
-		return -1;
-	}
-
-	return 0;
-}
-
-
-/**
- * tlsv1_client_set_client_cert - Set client certificate
- * @conn: TLSv1 client connection data from tlsv1_client_init()
- * @cert: File or reference name for X.509 certificate in PEM or DER format
- * @cert_blob: cert as inlined data or %NULL if not used
- * @cert_blob_len: ca_cert_blob length
- * Returns: 0 on success, -1 on failure
- */
-int tlsv1_client_set_client_cert(struct tlsv1_client *conn, const char *cert,
-				 const u8 *cert_blob, size_t cert_blob_len)
-{
-	return tlsv1_client_set_cert_chain(&conn->client_cert, cert,
-					   cert_blob, cert_blob_len);
-}
-
-
-static int tlsv1_client_set_key(struct tlsv1_client *conn,
-				const u8 *key, size_t len)
-{
-	conn->client_key = crypto_private_key_import(key, len);
-	if (conn->client_key == NULL) {
-		wpa_printf(MSG_INFO, "TLSv1: Failed to parse private key");
-		return -1;
-	}
-	return 0;
-}
-
-
-/**
- * tlsv1_client_set_private_key - Set client private key
- * @conn: TLSv1 client connection data from tlsv1_client_init()
- * @private_key: File or reference name for the key in PEM or DER format
- * @private_key_passwd: Passphrase for decrypted private key, %NULL if no
- * passphrase is used.
- * @private_key_blob: private_key as inlined data or %NULL if not used
- * @private_key_blob_len: private_key_blob length
- * Returns: 0 on success, -1 on failure
- */
-int tlsv1_client_set_private_key(struct tlsv1_client *conn,
-				 const char *private_key,
-				 const char *private_key_passwd,
-				 const u8 *private_key_blob,
-				 size_t private_key_blob_len)
-{
-	crypto_private_key_free(conn->client_key);
-	conn->client_key = NULL;
-
-	if (private_key_blob)
-		return tlsv1_client_set_key(conn, private_key_blob,
-					    private_key_blob_len);
-
-	if (private_key) {
-		u8 *buf;
-		size_t len;
-		int ret;
-
-		buf = (u8 *) os_readfile(private_key, &len);
-		if (buf == NULL) {
-			wpa_printf(MSG_INFO, "TLSv1: Failed to read '%s'",
-				   private_key);
-			return -1;
-		}
-
-		ret = tlsv1_client_set_key(conn, buf, len);
-		os_free(buf);
-		return ret;
-	}
-
-	return 0;
-}
+/**
+ * tlsv1_client_set_cred - Set client credentials
+ * @conn: TLSv1 client connection data from tlsv1_client_init()
+ * @cred: Credentials from tlsv1_cred_alloc()
+ * Returns: 0 on success, -1 on failure
+ *
+ * On success, the client takes ownership of the credentials block and caller
+ * must not free it. On failure, caller is responsible for freeing the
+ * credential block.
+ */
+int tlsv1_client_set_cred(struct tlsv1_client *conn,
+			  struct tlsv1_credentials *cred)
+{
+	tlsv1_cred_free(conn->cred);
+	conn->cred = cred;
+	return 0;
+}
+
+
+void tlsv1_client_set_session_ticket_cb(struct tlsv1_client *conn,
+					tlsv1_client_session_ticket_cb cb,
+					void *ctx)
+{
+	wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket callback set %p (ctx %p)",
+		   cb, ctx);
+	conn->session_ticket_cb = cb;
+	conn->session_ticket_cb_ctx = ctx;
+}

Modified: wpasupplicant/trunk/src/tls/tlsv1_client.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/tls/tlsv1_client.h?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/src/tls/tlsv1_client.h (original)
+++ wpasupplicant/trunk/src/tls/tlsv1_client.h Sat Nov  3 11:46:49 2007
@@ -1,6 +1,6 @@
 /*
- * wpa_supplicant: TLSv1 client (RFC 2246)
- * Copyright (c) 2006, Jouni Malinen <j at w1.fi>
+ * TLSv1 client (RFC 2246)
+ * Copyright (c) 2006-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
@@ -14,6 +14,8 @@
 
 #ifndef TLSV1_CLIENT_H
 #define TLSV1_CLIENT_H
+
+#include "tlsv1_cred.h"
 
 struct tlsv1_client;
 
@@ -41,19 +43,17 @@
 int tlsv1_client_hello_ext(struct tlsv1_client *conn, int ext_type,
 			   const u8 *data, size_t data_len);
 int tlsv1_client_get_keys(struct tlsv1_client *conn, struct tls_keys *keys);
-int tlsv1_client_set_master_key(struct tlsv1_client *conn,
-				const u8 *key, size_t key_len);
 int tlsv1_client_get_keyblock_size(struct tlsv1_client *conn);
 int tlsv1_client_set_cipher_list(struct tlsv1_client *conn, u8 *ciphers);
-int tlsv1_client_set_ca_cert(struct tlsv1_client *conn, const char *cert,
-			     const u8 *cert_blob, size_t cert_blob_len,
-			     const char *path);
-int tlsv1_client_set_client_cert(struct tlsv1_client *conn, const char *cert,
-				 const u8 *cert_blob, size_t cert_blob_len);
-int tlsv1_client_set_private_key(struct tlsv1_client *conn,
-				 const char *private_key,
-				 const char *private_key_passwd,
-				 const u8 *private_key_blob,
-				 size_t private_key_blob_len);
+int tlsv1_client_set_cred(struct tlsv1_client *conn,
+			  struct tlsv1_credentials *cred);
+
+typedef int (*tlsv1_client_session_ticket_cb)
+(void *ctx, const u8 *ticket, size_t len, const u8 *client_random,
+ const u8 *server_random, u8 *master_secret);
+
+void tlsv1_client_set_session_ticket_cb(struct tlsv1_client *conn,
+					tlsv1_client_session_ticket_cb cb,
+					void *ctx);
 
 #endif /* TLSV1_CLIENT_H */

Modified: wpasupplicant/trunk/src/tls/tlsv1_common.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/tls/tlsv1_common.c?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/src/tls/tlsv1_common.c (original)
+++ wpasupplicant/trunk/src/tls/tlsv1_common.c Sat Nov  3 11:46:49 2007
@@ -1,6 +1,6 @@
 /*
- * wpa_supplicant/hostapd: TLSv1 common routines
- * Copyright (c) 2006, Jouni Malinen <j at w1.fi>
+ * TLSv1 common routines
+ * Copyright (c) 2006-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,9 +15,6 @@
 #include "includes.h"
 
 #include "common.h"
-#include "md5.h"
-#include "sha1.h"
-#include "crypto.h"
 #include "x509v3.h"
 #include "tlsv1_common.h"
 
@@ -101,13 +98,38 @@
 }
 
 
-static const struct tls_cipher_data * tls_get_cipher_data(tls_cipher cipher)
+const struct tls_cipher_data * tls_get_cipher_data(tls_cipher cipher)
 {
 	size_t i;
 	for (i = 0; i < NUM_TLS_CIPHER_DATA; i++)
 		if (tls_ciphers[i].cipher == cipher)
 			return &tls_ciphers[i];
 	return NULL;
+}
+
+
+int tls_server_key_exchange_allowed(tls_cipher cipher)
+{
+	const struct tls_cipher_suite *suite;
+
+	/* RFC 2246, Section 7.4.3 */
+	suite = tls_get_cipher_suite(cipher);
+	if (suite == NULL)
+		return 0;
+
+	switch (suite->key_exchange) {
+	case TLS_KEY_X_DHE_DSS:
+	case TLS_KEY_X_DHE_DSS_EXPORT:
+	case TLS_KEY_X_DHE_RSA:
+	case TLS_KEY_X_DHE_RSA_EXPORT:
+	case TLS_KEY_X_DH_anon_EXPORT:
+	case TLS_KEY_X_DH_anon:
+		return 1;
+	case TLS_KEY_X_RSA_EXPORT:
+		return 1 /* FIX: public key len > 512 bits */;
+	default:
+		return 0;
+	}
 }
 
 
@@ -165,388 +187,55 @@
 }
 
 
-/**
- * tlsv1_record_set_cipher_suite - TLS record layer: Set cipher suite
- * @rl: Pointer to TLS record layer data
- * @cipher_suite: New cipher suite
- * Returns: 0 on success, -1 on failure
- *
- * This function is used to prepare TLS record layer for cipher suite change.
- * tlsv1_record_change_write_cipher() and
- * tlsv1_record_change_read_cipher() functions can then be used to change the
- * currently used ciphers.
- */
-int tlsv1_record_set_cipher_suite(struct tlsv1_record_layer *rl,
-				  u16 cipher_suite)
-{
-	const struct tls_cipher_suite *suite;
-	const struct tls_cipher_data *data;
-
-	wpa_printf(MSG_DEBUG, "TLSv1: Selected cipher suite: 0x%04x",
-		   cipher_suite);
-	rl->cipher_suite = cipher_suite;
-
-	suite = tls_get_cipher_suite(cipher_suite);
-	if (suite == NULL)
+int tls_verify_hash_init(struct tls_verify_hash *verify)
+{
+	tls_verify_hash_free(verify);
+	verify->md5_client = crypto_hash_init(CRYPTO_HASH_ALG_MD5, NULL, 0);
+	verify->md5_server = crypto_hash_init(CRYPTO_HASH_ALG_MD5, NULL, 0);
+	verify->md5_cert = crypto_hash_init(CRYPTO_HASH_ALG_MD5, NULL, 0);
+	verify->sha1_client = crypto_hash_init(CRYPTO_HASH_ALG_SHA1, NULL, 0);
+	verify->sha1_server = crypto_hash_init(CRYPTO_HASH_ALG_SHA1, NULL, 0);
+	verify->sha1_cert = crypto_hash_init(CRYPTO_HASH_ALG_SHA1, NULL, 0);
+	if (verify->md5_client == NULL || verify->md5_server == NULL ||
+	    verify->md5_cert == NULL || verify->sha1_client == NULL ||
+	    verify->sha1_server == NULL || verify->sha1_cert == NULL) {
+		tls_verify_hash_free(verify);
 		return -1;
-
-	if (suite->hash == TLS_HASH_MD5) {
-		rl->hash_alg = CRYPTO_HASH_ALG_HMAC_MD5;
-		rl->hash_size = MD5_MAC_LEN;
-	} else if (suite->hash == TLS_HASH_SHA) {
-		rl->hash_alg = CRYPTO_HASH_ALG_HMAC_SHA1;
-		rl->hash_size = SHA1_MAC_LEN;
-	}
-
-	data = tls_get_cipher_data(suite->cipher);
-	if (data == NULL)
-		return -1;
-
-	rl->key_material_len = data->key_material;
-	rl->iv_size = data->block_size;
-	rl->cipher_alg = data->alg;
-
+	}
 	return 0;
 }
 
 
-/**
- * tlsv1_record_change_write_cipher - TLS record layer: Change write cipher
- * @rl: Pointer to TLS record layer data
- * Returns: 0 on success (cipher changed), -1 on failure
- *
- * This function changes TLS record layer to use the new cipher suite
- * configured with tlsv1_record_set_cipher_suite() for writing.
- */
-int tlsv1_record_change_write_cipher(struct tlsv1_record_layer *rl)
-{
-	wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - New write cipher suite "
-		   "0x%04x", rl->cipher_suite);
-	rl->write_cipher_suite = rl->cipher_suite;
-	os_memset(rl->write_seq_num, 0, TLS_SEQ_NUM_LEN);
-
-	if (rl->write_cbc) {
-		crypto_cipher_deinit(rl->write_cbc);
-		rl->write_cbc = NULL;
-	}
-	if (rl->cipher_alg != CRYPTO_CIPHER_NULL) {
-		rl->write_cbc = crypto_cipher_init(rl->cipher_alg,
-						   rl->write_iv, rl->write_key,
-						   rl->key_material_len);
-		if (rl->write_cbc == NULL) {
-			wpa_printf(MSG_DEBUG, "TLSv1: Failed to initialize "
-				   "cipher");
-			return -1;
-		}
-	}
-
-	return 0;
-}
-
-
-/**
- * tlsv1_record_change_read_cipher - TLS record layer: Change read cipher
- * @rl: Pointer to TLS record layer data
- * Returns: 0 on success (cipher changed), -1 on failure
- *
- * This function changes TLS record layer to use the new cipher suite
- * configured with tlsv1_record_set_cipher_suite() for reading.
- */
-int tlsv1_record_change_read_cipher(struct tlsv1_record_layer *rl)
-{
-	wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - New read cipher suite "
-		   "0x%04x", rl->cipher_suite);
-	rl->read_cipher_suite = rl->cipher_suite;
-	os_memset(rl->read_seq_num, 0, TLS_SEQ_NUM_LEN);
-
-	if (rl->read_cbc) {
-		crypto_cipher_deinit(rl->read_cbc);
-		rl->read_cbc = NULL;
-	}
-	if (rl->cipher_alg != CRYPTO_CIPHER_NULL) {
-		rl->read_cbc = crypto_cipher_init(rl->cipher_alg,
-						  rl->read_iv, rl->read_key,
-						  rl->key_material_len);
-		if (rl->read_cbc == NULL) {
-			wpa_printf(MSG_DEBUG, "TLSv1: Failed to initialize "
-				   "cipher");
-			return -1;
-		}
-	}
-
-	return 0;
-}
-
-
-/**
- * tlsv1_record_send - TLS record layer: Send a message
- * @rl: Pointer to TLS record layer data
- * @content_type: Content type (TLS_CONTENT_TYPE_*)
- * @buf: Buffer to send (with TLS_RECORD_HEADER_LEN octets reserved in the
- * beginning for record layer to fill in; payload filled in after this and
- * extra space in the end for HMAC).
- * @buf_size: Maximum buf size
- * @payload_len: Length of the payload
- * @out_len: Buffer for returning the used buf length
- * Returns: 0 on success, -1 on failure
- *
- * This function fills in the TLS record layer header, adds HMAC, and encrypts
- * the data using the current write cipher.
- */
-int tlsv1_record_send(struct tlsv1_record_layer *rl, u8 content_type, u8 *buf,
-		      size_t buf_size, size_t payload_len, size_t *out_len)
-{
-	u8 *pos, *ct_start, *length, *payload;
-	struct crypto_hash *hmac;
-	size_t clen;
-
-	pos = buf;
-	/* ContentType type */
-	ct_start = pos;
-	*pos++ = content_type;
-	/* ProtocolVersion version */
-	WPA_PUT_BE16(pos, TLS_VERSION);
-	pos += 2;
-	/* uint16 length */
-	length = pos;
-	WPA_PUT_BE16(length, payload_len);
-	pos += 2;
-
-	/* opaque fragment[TLSPlaintext.length] */
-	payload = pos;
-	pos += payload_len;
-
-	if (rl->write_cipher_suite != TLS_NULL_WITH_NULL_NULL) {
-		hmac = crypto_hash_init(rl->hash_alg, rl->write_mac_secret,
-					rl->hash_size);
-		if (hmac == NULL) {
-			wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - Failed "
-				   "to initialize HMAC");
-			return -1;
-		}
-		crypto_hash_update(hmac, rl->write_seq_num, TLS_SEQ_NUM_LEN);
-		/* type + version + length + fragment */
-		crypto_hash_update(hmac, ct_start, pos - ct_start);
-		clen = buf + buf_size - pos;
-		if (clen < rl->hash_size) {
-			wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - Not "
-				   "enough room for MAC");
-			crypto_hash_finish(hmac, NULL, NULL);
-			return -1;
-		}
-
-		if (crypto_hash_finish(hmac, pos, &clen) < 0) {
-			wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - Failed "
-				   "to calculate HMAC");
-			return -1;
-		}
-		wpa_hexdump(MSG_MSGDUMP, "TLSv1: Record Layer - Write HMAC",
-			    pos, clen);
-		pos += clen;
-		if (rl->iv_size) {
-			size_t len = pos - payload;
-			size_t pad;
-			pad = (len + 1) % rl->iv_size;
-			if (pad)
-				pad = rl->iv_size - pad;
-			if (pos + pad + 1 > buf + buf_size) {
-				wpa_printf(MSG_DEBUG, "TLSv1: No room for "
-					   "block cipher padding");
-				return -1;
-			}
-			os_memset(pos, pad, pad + 1);
-			pos += pad + 1;
-		}
-
-		if (crypto_cipher_encrypt(rl->write_cbc, payload,
-					  payload, pos - payload) < 0)
-			return -1;
-	}
-
-	WPA_PUT_BE16(length, pos - length - 2);
-	inc_byte_array(rl->write_seq_num, TLS_SEQ_NUM_LEN);
-
-	*out_len = pos - buf;
-
-	return 0;
-}
-
-
-/**
- * tlsv1_record_receive - TLS record layer: Process a received message
- * @rl: Pointer to TLS record layer data
- * @in_data: Received data
- * @in_len: Length of the received data
- * @out_data: Buffer for output data (must be at least as long as in_data)
- * @out_len: Set to maximum out_data length by caller; used to return the
- * length of the used data
- * @alert: Buffer for returning an alert value on failure
- * Returns: 0 on success, -1 on failure
- *
- * This function decrypts the received message, verifies HMAC and TLS record
- * layer header.
- */
-int tlsv1_record_receive(struct tlsv1_record_layer *rl,
-			 const u8 *in_data, size_t in_len,
-			 u8 *out_data, size_t *out_len, u8 *alert)
-{
-	size_t i, rlen, hlen;
-	u8 padlen;
-	struct crypto_hash *hmac;
-	u8 len[2], hash[100];
-
-	wpa_hexdump(MSG_MSGDUMP, "TLSv1: Record Layer - Received",
-		    in_data, in_len);
-
-	if (in_len < TLS_RECORD_HEADER_LEN) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Too short record (in_len=%lu)",
-			   (unsigned long) in_len);
-		*alert = TLS_ALERT_DECODE_ERROR;
-		return -1;
-	}
-
-	wpa_printf(MSG_DEBUG, "TLSv1: Received content type %d version %d.%d "
-		   "length %d", in_data[0], in_data[1], in_data[2],
-		   WPA_GET_BE16(in_data + 3));
-
-	if (in_data[0] != TLS_CONTENT_TYPE_HANDSHAKE &&
-	    in_data[0] != TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC &&
-	    in_data[0] != TLS_CONTENT_TYPE_APPLICATION_DATA) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Unexpected content type 0x%x",
-			   in_data[0]);
-		*alert = TLS_ALERT_UNEXPECTED_MESSAGE;
-		return -1;
-	}
-
-	if (WPA_GET_BE16(in_data + 1) != TLS_VERSION) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Unexpected protocol version "
-			   "%d.%d", in_data[1], in_data[2]);
-		*alert = TLS_ALERT_PROTOCOL_VERSION;
-		return -1;
-	}
-
-	rlen = WPA_GET_BE16(in_data + 3);
-
-	/* TLSCiphertext must not be more than 2^14+2048 bytes */
-	if (TLS_RECORD_HEADER_LEN + rlen > 18432) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Record overflow (len=%lu)",
-			   (unsigned long) (TLS_RECORD_HEADER_LEN + rlen));
-		*alert = TLS_ALERT_RECORD_OVERFLOW;
-		return -1;
-	}
-
-	in_data += TLS_RECORD_HEADER_LEN;
-	in_len -= TLS_RECORD_HEADER_LEN;
-
-	if (rlen > in_len) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Not all record data included "
-			   "(rlen=%lu > in_len=%lu)",
-			   (unsigned long) rlen, (unsigned long) in_len);
-		*alert = TLS_ALERT_DECODE_ERROR;
-		return -1;
-	}
-
-	in_len = rlen;
-
-	if (*out_len < in_len) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Not enough output buffer for "
-			   "processing received record");
-		*alert = TLS_ALERT_INTERNAL_ERROR;
-		return -1;
-	}
-
-	os_memcpy(out_data, in_data, in_len);
-	*out_len = in_len;
-
-	if (rl->read_cipher_suite != TLS_NULL_WITH_NULL_NULL) {
-		if (crypto_cipher_decrypt(rl->read_cbc, out_data,
-					  out_data, in_len) < 0) {
-			*alert = TLS_ALERT_DECRYPTION_FAILED;
-			return -1;
-		}
-		if (rl->iv_size) {
-			if (in_len == 0) {
-				wpa_printf(MSG_DEBUG, "TLSv1: Too short record"
-					   " (no pad)");
-				*alert = TLS_ALERT_DECODE_ERROR;
-				return -1;
-			}
-			padlen = out_data[in_len - 1];
-			if (padlen >= in_len) {
-				wpa_printf(MSG_DEBUG, "TLSv1: Incorrect pad "
-					   "length (%u, in_len=%lu) in "
-					   "received record",
-					   padlen, (unsigned long) in_len);
-				*alert = TLS_ALERT_DECRYPTION_FAILED;
-				return -1;
-			}
-			for (i = in_len - padlen; i < in_len; i++) {
-				if (out_data[i] != padlen) {
-					wpa_hexdump(MSG_DEBUG,
-						    "TLSv1: Invalid pad in "
-						    "received record",
-						    out_data + in_len - padlen,
-						    padlen);
-					*alert = TLS_ALERT_DECRYPTION_FAILED;
-					return -1;
-				}
-			}
-
-			*out_len -= padlen + 1;
-		}
-
-		wpa_hexdump(MSG_MSGDUMP,
-			    "TLSv1: Record Layer - Decrypted data",
-			    out_data, in_len);
-
-		if (*out_len < rl->hash_size) {
-			wpa_printf(MSG_DEBUG, "TLSv1: Too short record; no "
-				   "hash value");
-			*alert = TLS_ALERT_INTERNAL_ERROR;
-			return -1;
-		}
-
-		*out_len -= rl->hash_size;
-
-		hmac = crypto_hash_init(rl->hash_alg, rl->read_mac_secret,
-					rl->hash_size);
-		if (hmac == NULL) {
-			wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - Failed "
-				   "to initialize HMAC");
-			*alert = TLS_ALERT_INTERNAL_ERROR;
-			return -1;
-		}
-
-		crypto_hash_update(hmac, rl->read_seq_num, TLS_SEQ_NUM_LEN);
-		/* type + version + length + fragment */
-		crypto_hash_update(hmac, in_data - TLS_RECORD_HEADER_LEN, 3);
-		WPA_PUT_BE16(len, *out_len);
-		crypto_hash_update(hmac, len, 2);
-		crypto_hash_update(hmac, out_data, *out_len);
-		hlen = sizeof(hash);
-		if (crypto_hash_finish(hmac, hash, &hlen) < 0) {
-			wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - Failed "
-				   "to calculate HMAC");
-			return -1;
-		}
-		if (hlen != rl->hash_size ||
-		    os_memcmp(hash, out_data + *out_len, hlen) != 0) {
-			wpa_printf(MSG_DEBUG, "TLSv1: Invalid HMAC value in "
-				   "received message");
-			*alert = TLS_ALERT_BAD_RECORD_MAC;
-			return -1;
-		}
-	}
-
-	/* TLSCompressed must not be more than 2^14+1024 bytes */
-	if (TLS_RECORD_HEADER_LEN + *out_len > 17408) {
-		wpa_printf(MSG_DEBUG, "TLSv1: Record overflow (len=%lu)",
-			   (unsigned long) (TLS_RECORD_HEADER_LEN + *out_len));
-		*alert = TLS_ALERT_RECORD_OVERFLOW;
-		return -1;
-	}
-
-	inc_byte_array(rl->read_seq_num, TLS_SEQ_NUM_LEN);
-
-	return 0;
-}
+void tls_verify_hash_add(struct tls_verify_hash *verify, const u8 *buf,
+			 size_t len)
+{
+	if (verify->md5_client && verify->sha1_client) {
+		crypto_hash_update(verify->md5_client, buf, len);
+		crypto_hash_update(verify->sha1_client, buf, len);
+	}
+	if (verify->md5_server && verify->sha1_server) {
+		crypto_hash_update(verify->md5_server, buf, len);
+		crypto_hash_update(verify->sha1_server, buf, len);
+	}
+	if (verify->md5_cert && verify->sha1_cert) {
+		crypto_hash_update(verify->md5_cert, buf, len);
+		crypto_hash_update(verify->sha1_cert, buf, len);
+	}
+}
+
+
+void tls_verify_hash_free(struct tls_verify_hash *verify)
+{
+	crypto_hash_finish(verify->md5_client, NULL, NULL);
+	crypto_hash_finish(verify->md5_server, NULL, NULL);
+	crypto_hash_finish(verify->md5_cert, NULL, NULL);
+	crypto_hash_finish(verify->sha1_client, NULL, NULL);
+	crypto_hash_finish(verify->sha1_server, NULL, NULL);
+	crypto_hash_finish(verify->sha1_cert, NULL, NULL);
+	verify->md5_client = NULL;
+	verify->md5_server = NULL;
+	verify->md5_cert = NULL;
+	verify->sha1_client = NULL;
+	verify->sha1_server = NULL;
+	verify->sha1_cert = NULL;
+}

Modified: wpasupplicant/trunk/src/tls/tlsv1_common.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/tls/tlsv1_common.h?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/src/tls/tlsv1_common.h (original)
+++ wpasupplicant/trunk/src/tls/tlsv1_common.h Sat Nov  3 11:46:49 2007
@@ -1,6 +1,6 @@
 /*
- * wpa_supplicant/hostapd: TLSv1 common definitions
- * Copyright (c) 2006, Jouni Malinen <j at w1.fi>
+ * TLSv1 common definitions
+ * Copyright (c) 2006-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,8 +12,10 @@
  * See README and COPYING for more details.
  */
 
-#ifndef TLSV1_COMMON
-#define TLSV1_COMMON
+#ifndef TLSV1_COMMON_H
+#define TLSV1_COMMON_H
+
+#include "crypto.h"
 
 #define TLS_VERSION 0x0301 /* TLSv1 */
 #define TLS_RANDOM_LEN 32
@@ -21,34 +23,22 @@
 #define TLS_MASTER_SECRET_LEN 48
 #define TLS_SESSION_ID_MAX_LEN 32
 #define TLS_VERIFY_DATA_LEN 12
-#define TLS_MAX_WRITE_MAC_SECRET_LEN 20
-#define TLS_MAX_WRITE_KEY_LEN 32
-#define TLS_MAX_IV_LEN 16
-#define TLS_MAX_KEY_BLOCK_LEN (2 * (TLS_MAX_WRITE_MAC_SECRET_LEN + \
-				    TLS_MAX_WRITE_KEY_LEN + TLS_MAX_IV_LEN))
-#define TLS_SEQ_NUM_LEN 8
-#define TLS_RECORD_HEADER_LEN 5
-
-/* ContentType */
-enum {
-	TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC = 20,
-	TLS_CONTENT_TYPE_ALERT = 21,
-	TLS_CONTENT_TYPE_HANDSHAKE = 22,
-	TLS_CONTENT_TYPE_APPLICATION_DATA = 23
-};
 
 /* HandshakeType */
 enum {
 	TLS_HANDSHAKE_TYPE_HELLO_REQUEST = 0,
 	TLS_HANDSHAKE_TYPE_CLIENT_HELLO = 1,
 	TLS_HANDSHAKE_TYPE_SERVER_HELLO = 2,
+	TLS_HANDSHAKE_TYPE_NEW_SESSION_TICKET = 4 /* RFC 4507 */,
 	TLS_HANDSHAKE_TYPE_CERTIFICATE = 11,
 	TLS_HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE = 12,
 	TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST = 13,
 	TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE = 14,
 	TLS_HANDSHAKE_TYPE_CERTIFICATE_VERIFY = 15,
 	TLS_HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE = 16,
-	TLS_HANDSHAKE_TYPE_FINISHED = 20
+	TLS_HANDSHAKE_TYPE_FINISHED = 20,
+	TLS_HANDSHAKE_TYPE_CERTIFICATE_URL = 21 /* RFC 4366 */,
+	TLS_HANDSHAKE_TYPE_CERTIFICATE_STATUS = 22 /* RFC 4366 */
 };
 
 /* CipherSuite */
@@ -124,6 +114,11 @@
 #define TLS_ALERT_INTERNAL_ERROR		80
 #define TLS_ALERT_USER_CANCELED			90
 #define TLS_ALERT_NO_RENEGOTIATION		100
+#define TLS_ALERT_UNSUPPORTED_EXTENSION		110 /* RFC 4366 */
+#define TLS_ALERT_CERTIFICATE_UNOBTAINABLE	111 /* RFC 4366 */
+#define TLS_ALERT_UNRECOGNIZED_NAME		112 /* RFC 4366 */
+#define TLS_ALERT_BAD_CERTIFICATE_STATUS_RESPONSE	113 /* RFC 4366 */
+#define TLS_ALERT_BAD_CERTIFICATE_HASH_VALUE	114 /* RFC 4366 */
 
 /* ChangeCipherSpec */
 enum {
@@ -131,7 +126,15 @@
 };
 
 /* TLS Extensions */
-#define TLS_EXT_PAC_OPAQUE 35
+#define TLS_EXT_SERVER_NAME			0 /* RFC 4366 */
+#define TLS_EXT_MAX_FRAGMENT_LENGTH		1 /* RFC 4366 */
+#define TLS_EXT_CLIENT_CERTIFICATE_URL		2 /* RFC 4366 */
+#define TLS_EXT_TRUSTED_CA_KEYS			3 /* RFC 4366 */
+#define TLS_EXT_TRUNCATED_HMAC			4 /* RFC 4366 */
+#define TLS_EXT_STATUS_REQUEST			5 /* RFC 4366 */
+#define TLS_EXT_SESSION_TICKET			35 /* RFC 4507 */
+
+#define TLS_EXT_PAC_OPAQUE TLS_EXT_SESSION_TICKET /* EAP-FAST terminology */
 
 
 typedef enum {
@@ -191,43 +194,23 @@
 };
 
 
-struct tlsv1_record_layer {
-	u8 write_mac_secret[TLS_MAX_WRITE_MAC_SECRET_LEN];
-	u8 read_mac_secret[TLS_MAX_WRITE_MAC_SECRET_LEN];
-	u8 write_key[TLS_MAX_WRITE_KEY_LEN];
-	u8 read_key[TLS_MAX_WRITE_KEY_LEN];
-	u8 write_iv[TLS_MAX_IV_LEN];
-	u8 read_iv[TLS_MAX_IV_LEN];
-
-	size_t hash_size;
-	size_t key_material_len;
-	size_t iv_size; /* also block_size */
-
-	enum crypto_hash_alg hash_alg;
-	enum crypto_cipher_alg cipher_alg;
-
-	u8 write_seq_num[TLS_SEQ_NUM_LEN];
-	u8 read_seq_num[TLS_SEQ_NUM_LEN];
-
-	u16 cipher_suite;
-	u16 write_cipher_suite;
-	u16 read_cipher_suite;
-
-	struct crypto_cipher *write_cbc;
-	struct crypto_cipher *read_cbc;
+struct tls_verify_hash {
+	struct crypto_hash *md5_client;
+	struct crypto_hash *sha1_client;
+	struct crypto_hash *md5_server;
+	struct crypto_hash *sha1_server;
+	struct crypto_hash *md5_cert;
+	struct crypto_hash *sha1_cert;
 };
 
 
 const struct tls_cipher_suite * tls_get_cipher_suite(u16 suite);
+const struct tls_cipher_data * tls_get_cipher_data(tls_cipher cipher);
+int tls_server_key_exchange_allowed(tls_cipher cipher);
 int tls_parse_cert(const u8 *buf, size_t len, struct crypto_public_key **pk);
-int tlsv1_record_set_cipher_suite(struct tlsv1_record_layer *rl,
-				  u16 cipher_suite);
-int tlsv1_record_change_write_cipher(struct tlsv1_record_layer *rl);
-int tlsv1_record_change_read_cipher(struct tlsv1_record_layer *rl);
-int tlsv1_record_send(struct tlsv1_record_layer *rl, u8 content_type, u8 *buf,
-		      size_t buf_size, size_t payload_len, size_t *out_len);
-int tlsv1_record_receive(struct tlsv1_record_layer *rl,
-			 const u8 *in_data, size_t in_len,
-			 u8 *out_data, size_t *out_len, u8 *alert);
+int tls_verify_hash_init(struct tls_verify_hash *verify);
+void tls_verify_hash_add(struct tls_verify_hash *verify, const u8 *buf,
+			 size_t len);
+void tls_verify_hash_free(struct tls_verify_hash *verify);
 
 #endif /* TLSV1_COMMON_H */

Modified: wpasupplicant/trunk/src/tls/x509v3.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/tls/x509v3.c?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/src/tls/x509v3.c (original)
+++ wpasupplicant/trunk/src/tls/x509v3.c Sat Nov  3 11:46:49 2007
@@ -1,6 +1,6 @@
 /*
  * X.509v3 certificate parsing and processing (RFC 3280 profile)
- * Copyright (c) 2006, Jouni Malinen <j at w1.fi>
+ * Copyright (c) 2006-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
@@ -75,8 +75,39 @@
 }
 
 
+static int x509_whitespace(char c)
+{
+	return c == ' ' || c == '\t';
+}
+
+
+static void x509_str_strip_whitespace(char *a)
+{
+	char *ipos, *opos;
+	int remove_whitespace = 1;
+
+	ipos = opos = a;
+
+	while (*ipos) {
+		if (remove_whitespace && x509_whitespace(*ipos))
+			ipos++;
+		else {
+			remove_whitespace = x509_whitespace(*ipos);
+			*opos++ = *ipos++;
+		}
+	}
+
+	*opos-- = '\0';
+	if (opos > a && x509_whitespace(*opos))
+		*opos = '\0';
+}
+
+
 static int x509_str_compare(const char *a, const char *b)
 {
+	char *aa, *bb;
+	int ret;
+
 	if (!a && b)
 		return -1;
 	if (a && !b)
@@ -84,14 +115,31 @@
 	if (!a && !b)
 		return 0;
 
-	return os_strcmp(a, b);
+	aa = os_strdup(a);
+	bb = os_strdup(b);
+
+	if (aa == NULL || bb == NULL) {
+		os_free(aa);
+		os_free(bb);
+		return os_strcasecmp(a, b);
+	}
+
+	x509_str_strip_whitespace(aa);
+	x509_str_strip_whitespace(bb);
+
+	ret = os_strcasecmp(aa, bb);
+
+	os_free(aa);
+	os_free(bb);
+
+	return ret;
 }
 
 
 /**
  * x509_name_compare - Compare X.509 certificate names
  * @a: Certificate name
- * @b: Certifiatte name
+ * @b: Certificate name
  * Returns: <0, 0, or >0 based on whether a is less than, equal to, or
  * greater than b
  */
@@ -553,6 +601,17 @@
 	if (os_mktime(year, month, day, hour, min, sec, val) < 0) {
 		wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to convert Time",
 				  buf, len);
+		if (year < 1970) {
+			/*
+			 * At least some test certificates have been configured
+			 * to use dates prior to 1970. Set the date to
+			 * beginning of 1970 to handle these case.
+			 */
+			wpa_printf(MSG_DEBUG, "X509: Year=%d before epoch - "
+				   "assume epoch as the time", year);
+			*val = 0;
+			return 0;
+		}
 		return -1;
 	}
 
@@ -720,7 +779,8 @@
 			return 0;
 		}
 
-		if (asn1_get_next(pos, len, &hdr) < 0 ||
+		if (asn1_get_next(hdr.payload + hdr.length, len - hdr.length,
+				  &hdr) < 0 ||
 		    hdr.class != ASN1_CLASS_UNIVERSAL) {
 			wpa_printf(MSG_DEBUG, "X509: Failed to parse "
 				   "BasicConstraints");
@@ -1443,6 +1503,13 @@
 		return -1;
 	}
 
+	if (cert->version == X509_CERT_V3 &&
+	    !(cert->extensions_present & X509_EXT_BASIC_CONSTRAINTS)) {
+		wpa_printf(MSG_DEBUG, "X509: v3 CA certificate did not "
+			   "include BasicConstraints extension");
+		return -1;
+	}
+
 	if ((cert->extensions_present & X509_EXT_KEY_USAGE) &&
 	    !(cert->key_usage & X509_KEY_USAGE_KEY_CERT_SIGN)) {
 		wpa_printf(MSG_DEBUG, "X509: Issuer certificate did not have "
@@ -1466,7 +1533,8 @@
 				    struct x509_certificate *chain,
 				    int *reason)
 {
-	int idx, chain_trusted = 0;
+	long unsigned idx;
+	int chain_trusted = 0;
 	struct x509_certificate *cert, *trust;
 	char buf[128];
 	struct os_time now;
@@ -1478,12 +1546,15 @@
 
 	for (cert = chain, idx = 0; cert; cert = cert->next, idx++) {
 		x509_name_string(&cert->subject, buf, sizeof(buf)); 
-		wpa_printf(MSG_DEBUG, "X509: %d: %s", idx, buf);
+		wpa_printf(MSG_DEBUG, "X509: %lu: %s", idx, buf);
 
 		if (chain_trusted)
 			continue;
 
-		if (now.sec < cert->not_before || now.sec > cert->not_after) {
+		if ((unsigned long) now.sec <
+		    (unsigned long) cert->not_before ||
+		    (unsigned long) now.sec >
+		    (unsigned long) cert->not_after) {
 			wpa_printf(MSG_INFO, "X509: Certificate not valid "
 				   "(now=%lu not_before=%lu not_after=%lu)",
 				   now.sec, cert->not_before, cert->not_after);
@@ -1505,7 +1576,16 @@
 				return -1;
 			}
 
-			/* TODO: validate pathLenConstraint */
+			if ((cert->next->extensions_present &
+			     X509_EXT_PATH_LEN_CONSTRAINT) &&
+			    idx > cert->next->path_len_constraint) {
+				wpa_printf(MSG_DEBUG, "X509: pathLenConstraint"
+					   " not met (idx=%lu issuer "
+					   "pathLenConstraint=%lu)", idx,
+					   cert->next->path_len_constraint);
+				*reason = X509_VALIDATE_BAD_CERTIFICATE;
+				return -1;
+			}
 
 			if (x509_certificate_check_signature(cert->next, cert)
 			    < 0) {

Modified: wpasupplicant/trunk/src/utils/common.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/utils/common.h?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/src/utils/common.h (original)
+++ wpasupplicant/trunk/src/utils/common.h Sat Nov  3 11:46:49 2007
@@ -33,6 +33,24 @@
 #define bswap_64 bswap64
 #endif /* defined(__FreeBSD__) || defined(__NetBSD__) ||
 	* defined(__DragonFly__) */
+
+#ifdef __APPLE__
+#include <sys/types.h>
+#include <machine/endian.h>
+#define __BYTE_ORDER	_BYTE_ORDER
+#define __LITTLE_ENDIAN	_LITTLE_ENDIAN
+#define __BIG_ENDIAN	_BIG_ENDIAN
+static inline unsigned short bswap_16(unsigned short v)
+{
+	return ((v & 0xff) << 8) | (v >> 8);
+}
+
+static inline unsigned int bswap_32(unsigned int v)
+{
+	return ((v & 0xff) << 24) | ((v & 0xff00) << 8) |
+		((v & 0xff0000) >> 8) | (v >> 24);
+}
+#endif /* __APPLE__ */
 
 #ifdef CONFIG_TI_COMPILER
 #define __BIG_ENDIAN 4321

Modified: wpasupplicant/trunk/src/utils/os_unix.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/utils/os_unix.c?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/src/utils/os_unix.c (original)
+++ wpasupplicant/trunk/src/utils/os_unix.c Sat Nov  3 11:46:49 2007
@@ -175,7 +175,7 @@
 
 int os_unsetenv(const char *name)
 {
-#if defined(__FreeBSD__) || defined(__NetBSD__)
+#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE__)
 	unsetenv(name);
 	return 0;
 #else

Modified: wpasupplicant/trunk/wpa_supplicant/ChangeLog
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/wpa_supplicant/ChangeLog?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/wpa_supplicant/ChangeLog (original)
+++ wpasupplicant/trunk/wpa_supplicant/ChangeLog Sat Nov  3 11:46:49 2007
@@ -1,4 +1,26 @@
 ChangeLog for wpa_supplicant
+
+????-??-?? - v0.6.1
+	* added support for configuring password as NtPasswordHash
+	  (16-byte MD4 hash of password) in hash:<32 hex digits> format
+	* added support for fallback from abbreviated TLS handshake to
+	  full handshake when using EAP-FAST (e.g., due to an expired
+	  PAC-Opaque)
+	* updated EAP Generalized Pre-Shared Key (EAP-GPSK) to use the latest
+	  draft (draft-ietf-emu-eap-gpsk-06.txt)
+	* added support for drivers that take care of RSN 4-way handshake
+	  internally (WPA_DRIVER_FLAGS_4WAY_HANDSHAKE in get_capa flags and
+	  WPA_ALG_PMK in set_key)
+	* added an experimental port for Mac OS X (CONFIG_DRIVER_OSX=y in
+	  .config); this version supports only ap_scan=2 mode and allow the
+	  driver to take care of the 4-way handshake
+	* fixed a buffer overflow in parsing TSF from scan results when using
+	  driver_wext.c with a driver that includes the TSF (e.g., iwl4965)
+	  [Bug 232]
+	* updated FT support to use the latest draft, IEEE 802.11r/D8.0
+	* fixed an integer overflow issue in the ASN.1 parser used by the
+	  (experimental) internal TLS implementation to avoid a potential
+	  buffer read overflow
 
 2007-05-28 - v0.6.0
 	* added network configuration parameter 'frequency' for setting

Modified: wpasupplicant/trunk/wpa_supplicant/Makefile
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/wpa_supplicant/Makefile?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/wpa_supplicant/Makefile (original)
+++ wpasupplicant/trunk/wpa_supplicant/Makefile Sat Nov  3 11:46:49 2007
@@ -189,6 +189,20 @@
 OBJS_d += ../src/drivers/driver_test.o
 endif
 
+ifdef CONFIG_DRIVER_OSX
+CFLAGS += -DCONFIG_DRIVER_OSX
+OBJS_d += ../src/drivers/driver_osx.o
+LDFLAGS += -framework CoreFoundation
+LDFLAGS += -F/System/Library/PrivateFrameworks -framework Apple80211
+endif
+
+ifdef CONFIG_DRIVER_IPHONE
+CFLAGS += -DCONFIG_DRIVER_IPHONE
+OBJS_d += ../src/drivers/driver_iphone.o
+OBJS_d += ../src/drivers/MobileApple80211.o
+LIBS += -framework CoreFoundation
+endif
+
 ifndef CONFIG_L2_PACKET
 CONFIG_L2_PACKET=linux
 endif
@@ -393,6 +407,7 @@
 else
 CFLAGS += -DEAP_FAST
 OBJS += ../src/eap_peer/eap_fast.o ../src/eap_peer/eap_fast_pac.o
+OBJS_h += ../src/eap_server/eap_fast.o
 endif
 TLS_FUNCS=y
 endif
@@ -555,12 +570,15 @@
 endif
 ifeq ($(CONFIG_TLS), internal)
 OBJS += ../src/crypto/tls_internal.o
-OBJS += ../src/tls/tlsv1_common.o ../src/tls/tlsv1_client.o
+OBJS += ../src/tls/tlsv1_common.o ../src/tls/tlsv1_record.o
+OBJS += ../src/tls/tlsv1_cred.o ../src/tls/tlsv1_client.o
+OBJS += ../src/tls/tlsv1_client_write.o ../src/tls/tlsv1_client_read.o
 OBJS += ../src/tls/asn1.o ../src/tls/x509v3.o
 OBJS_p += ../src/tls/asn1.o
 OBJS_p += ../src/crypto/rc4.o ../src/crypto/aes_wrap.o ../src/crypto/aes.o
 NEED_BASE64=y
 CFLAGS += -DCONFIG_TLS_INTERNAL
+CFLAGS += -DCONFIG_TLS_INTERNAL_CLIENT
 ifeq ($(CONFIG_CRYPTO), internal)
 ifdef CONFIG_INTERNAL_LIBTOMMATH
 CFLAGS += -DCONFIG_INTERNAL_LIBTOMMATH

Modified: wpasupplicant/trunk/wpa_supplicant/config.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/wpa_supplicant/config.c?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/wpa_supplicant/config.c (original)
+++ wpasupplicant/trunk/wpa_supplicant/config.c Sat Nov  3 11:46:49 2007
@@ -949,6 +949,86 @@
 
 	return buf;
 }
+
+
+static int wpa_config_parse_password(const struct parse_data *data,
+				     struct wpa_ssid *ssid, int line,
+				     const char *value)
+{
+	u8 *hash;
+
+	if (os_strncmp(value, "hash:", 5) != 0) {
+		char *tmp;
+		size_t res_len;
+
+		tmp = wpa_config_parse_string(value, &res_len);
+		if (tmp == NULL) {
+			wpa_printf(MSG_ERROR, "Line %d: failed to parse "
+				   "password.", line);
+			return -1;
+		}
+		wpa_hexdump_ascii(MSG_MSGDUMP, data->name,
+				  (u8 *) tmp, res_len);
+
+		os_free(ssid->password);
+		ssid->password = (u8 *) tmp;
+		ssid->password_len = res_len;
+		ssid->flags &= ~WPA_CONFIG_FLAGS_PASSWORD_NTHASH;
+
+		return 0;
+	}
+
+
+	/* NtPasswordHash: hash:<32 hex digits> */
+	if (os_strlen(value + 5) != 2 * 16) {
+		wpa_printf(MSG_ERROR, "Line %d: Invalid password hash length "
+			   "(expected 32 hex digits)", line);
+		return -1;
+	}
+
+	hash = os_malloc(16);
+	if (hash == NULL)
+		return -1;
+
+	if (hexstr2bin(value + 5, hash, 16)) {
+		os_free(hash);
+		wpa_printf(MSG_ERROR, "Line %d: Invalid password hash", line);
+		return -1;
+	}
+
+	wpa_hexdump_key(MSG_MSGDUMP, data->name, hash, 16);
+
+	os_free(ssid->password);
+	ssid->password = hash;
+	ssid->password_len = 16;
+	ssid->flags |= WPA_CONFIG_FLAGS_PASSWORD_NTHASH;
+
+	return 0;
+}
+
+
+static char * wpa_config_write_password(const struct parse_data *data,
+					struct wpa_ssid *ssid)
+{
+	char *buf;
+
+	if (ssid->password == NULL)
+		return NULL;
+
+	if (!(ssid->flags & WPA_CONFIG_FLAGS_PASSWORD_NTHASH)) {
+		return wpa_config_write_string(
+			ssid->password, ssid->password_len);
+	}
+
+	buf = os_malloc(5 + 32 + 1);
+	if (buf == NULL)
+		return NULL;
+
+	os_memcpy(buf, "hash:", 5);
+	wpa_snprintf_hex(buf + 5, 32 + 1, ssid->password, 16);
+
+	return buf;
+}
 #endif /* IEEE8021X_EAPOL */
 
 
@@ -1137,7 +1217,7 @@
 	{ STR_LEN(anonymous_identity) },
 	{ STR_RANGE_KEY(eappsk, EAP_PSK_LEN_MIN, EAP_PSK_LEN_MAX) },
 	{ STR_LEN(nai) },
-	{ STR_LEN_KEY(password) },
+	{ FUNC(password) },
 	{ STR(ca_cert) },
 	{ STR(ca_path) },
 	{ STR(client_cert) },

Modified: wpasupplicant/trunk/wpa_supplicant/config_ssid.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/wpa_supplicant/config_ssid.h?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/wpa_supplicant/config_ssid.h (original)
+++ wpasupplicant/trunk/wpa_supplicant/config_ssid.h Sat Nov  3 11:46:49 2007
@@ -226,6 +226,14 @@
 
 	/**
 	 * password - Password string for EAP
+	 *
+	 * This field can include either the plaintext password (default
+	 * option) or a NtPasswordHash (16-byte MD4 hash of the unicode
+	 * presentation of the password) if flags field has
+	 * WPA_CONFIG_FLAGS_PASSWORD_NTHASH bit set to 1. NtPasswordHash can
+	 * only be used with authentication mechanism that use this hash as the
+	 * starting point for operation: MSCHAP and MSCHAPv2 (EAP-MSCHAPv2,
+	 * EAP-TTLS/MSCHAPv2, EAP-TTLS/MSCHAP, LEAP).
 	 */
 	u8 *password;
 
@@ -849,6 +857,17 @@
 	 * will be used instead of this configured value.
 	 */
 	int frequency;
+
+#define WPA_CONFIG_FLAGS_PASSWORD_NTHASH BIT(0)
+	/**
+	 * flags - Network configuration flags (bitfield)
+	 *
+	 * This variable is used for internal flags to describe further details
+	 * for the network parameters.
+	 * bit 0 = password is represented as a 16-byte NtPasswordHash value
+	 *         instead of plaintext password
+	 */
+	u32 flags;
 };
 
 int wpa_config_allowed_eap_method(struct wpa_ssid *ssid, int vendor,

Modified: wpasupplicant/trunk/wpa_supplicant/ctrl_iface.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/wpa_supplicant/ctrl_iface.c?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/wpa_supplicant/ctrl_iface.c (original)
+++ wpasupplicant/trunk/wpa_supplicant/ctrl_iface.c Sat Nov  3 11:46:49 2007
@@ -1225,6 +1225,12 @@
 		wpa_s->disconnected = 0;
 		wpa_s->reassociate = 1;
 		wpa_supplicant_req_scan(wpa_s, 0, 0);
+	} else if (os_strcmp(buf, "RECONNECT") == 0) {
+		if (wpa_s->disconnected) {
+			wpa_s->disconnected = 0;
+			wpa_s->reassociate = 1;
+			wpa_supplicant_req_scan(wpa_s, 0, 0);
+		}
 	} else if (os_strncmp(buf, "PREAUTH ", 8) == 0) {
 		if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8))
 			reply_len = -1;
@@ -1257,6 +1263,7 @@
 		reply_len = wpa_supplicant_ctrl_iface_list_networks(
 			wpa_s, reply, reply_size);
 	} else if (os_strcmp(buf, "DISCONNECT") == 0) {
+		wpa_s->reassociate = 0;
 		wpa_s->disconnected = 1;
 		wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
 	} else if (os_strcmp(buf, "SCAN") == 0) {

Modified: wpasupplicant/trunk/wpa_supplicant/doc/ctrl_iface.doxygen
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/wpa_supplicant/doc/ctrl_iface.doxygen?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/wpa_supplicant/doc/ctrl_iface.doxygen (original)
+++ wpasupplicant/trunk/wpa_supplicant/doc/ctrl_iface.doxygen Sat Nov  3 11:46:49 2007
@@ -203,6 +203,12 @@
 Force reassociation.
 
 
+\subsection ctrl_iface_RECONNECT RECONNECT
+
+Connect if disconnected (i.e., like \c REASSOCIATE, but only connect
+if in disconnected state).
+
+
 \subsection ctrl_iface_PREAUTH PREAUTH <BSSID>
 
 Start pre-authentication with the given BSSID.
@@ -255,7 +261,8 @@
 
 \subsection ctrl_iface_DISCONNECT DISCONNECT
 
-Disconnect and wait for \c REASSOCIATE command before connecting.
+Disconnect and wait for \c REASSOCIATE or \c RECONNECT command before
+connecting.
 
 
 \subsection ctrl_iface_SCAN SCAN

Modified: wpasupplicant/trunk/wpa_supplicant/doc/docbook/wpa_cli.sgml
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/wpa_supplicant/doc/docbook/wpa_cli.sgml?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/wpa_supplicant/doc/docbook/wpa_cli.sgml (original)
+++ wpasupplicant/trunk/wpa_supplicant/doc/docbook/wpa_cli.sgml Sat Nov  3 11:46:49 2007
@@ -140,7 +140,7 @@
 	<listitem><para>Run in daemon mode executing the action file
         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.
+	second to "CONNECTED" or "DISCONNECTED" depending on the event.
 	This can be used to execute networking tools required to configure
 	the interface.</para>
 

Modified: wpasupplicant/trunk/wpa_supplicant/eap_testing.txt
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/wpa_supplicant/eap_testing.txt?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/wpa_supplicant/eap_testing.txt (original)
+++ wpasupplicant/trunk/wpa_supplicant/eap_testing.txt Sat Nov  3 11:46:49 2007
@@ -79,12 +79,12 @@
 EAP-PAX			-   -   -   -   -   +   -   -   -   -   +   -
 EAP-SAKE		-   -   -   -   -   -   -   -   -   -   +   -
 EAP-GPSK		-   -   -   -   -   -   -   -   -   -   +   -
-EAP-FAST/MSCHAPv2(prov)	-   -   -   +   -   -   -   -   -   +   -   +
-EAP-FAST/GTC(auth)	-   -   -   +   -   -   -   -   -   +   -   +
-EAP-FAST/MSCHAPv2(aprov)-   -   -   -   -   -   -   -   -   -   -   +
-EAP-FAST/GTC(aprov)	-   -   -   -   -   -   -   -   -   -   -   +
+EAP-FAST/MSCHAPv2(prov)	-   -   -   +   -   -   -   -   -   +   +   +
+EAP-FAST/GTC(auth)	-   -   -   +   -   -   -   -   -   +   +   +
+EAP-FAST/MSCHAPv2(aprov)-   -   -   -   -   -   -   -   -   -   +   +
+EAP-FAST/GTC(aprov)	-   -   -   -   -   -   -   -   -   -   +   +
 EAP-FAST/TLS(aprov)	-   -   -   -   -   -   -   -   -   -   -   +
-EAP-FAST/MSCHAPv2(auth)	-   -   -   -   -   -   -   -   -   -   -   +
+EAP-FAST/MSCHAPv2(auth)	-   -   -   -   -   -   -   -   -   -   +   +
 EAP-FAST/TLS(auth)	-   -   -   -   -   -   -   -   -   -   -   +
 LEAP			+   -   +   +   +   +   F   +6  -   +   -   +
 EAP-TNC			-   -   -   -   -   +   -   -   -   -   -   -

Modified: wpasupplicant/trunk/wpa_supplicant/eapol_test.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/wpa_supplicant/eapol_test.c?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/wpa_supplicant/eapol_test.c (original)
+++ wpasupplicant/trunk/wpa_supplicant/eapol_test.c Sat Nov  3 11:46:49 2007
@@ -199,7 +199,8 @@
 				 size_t len)
 {
 	/* struct wpa_supplicant *wpa_s = ctx; */
-	printf("WPA: eapol_test_eapol_send(type=%d len=%d)\n", type, len);
+	printf("WPA: eapol_test_eapol_send(type=%d len=%lu)\n",
+	       type, (unsigned long) len);
 	if (type == IEEE802_1X_TYPE_EAP_PACKET) {
 		wpa_hexdump(MSG_DEBUG, "TX EAP -> RADIUS", buf, len);
 		ieee802_1x_encapsulate_radius(&eapol_test, buf, len);

Modified: wpasupplicant/trunk/wpa_supplicant/events.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/wpa_supplicant/events.c?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/wpa_supplicant/events.c (original)
+++ wpasupplicant/trunk/wpa_supplicant/events.c Sat Nov  3 11:46:49 2007
@@ -444,9 +444,10 @@
 				wpa_printf(MSG_DEBUG, "   skip - disabled");
 				continue;
 			}
-			if (bss->ssid_len != ssid->ssid_len ||
-			    os_memcmp(bss->ssid, ssid->ssid,
-				      bss->ssid_len) != 0) {
+			if (ssid->ssid_len != 0 &&
+			    (bss->ssid_len != ssid->ssid_len ||
+			     os_memcmp(bss->ssid, ssid->ssid,
+				       bss->ssid_len) != 0)) {
 				wpa_printf(MSG_DEBUG, "   skip - "
 					   "SSID mismatch");
 				continue;
@@ -520,7 +521,7 @@
 
 	wpa_supplicant_dbus_notify_scan_results(wpa_s);
 
-	if (wpa_s->conf->ap_scan == 2)
+	if (wpa_s->conf->ap_scan == 2 || wpa_s->disconnected)
 		return;
 	results = wpa_s->scan_results;
 	num = wpa_s->num_scan_results;
@@ -733,6 +734,19 @@
 		wpa_supplicant_req_auth_timeout(wpa_s, 10, 0);
 	}
 	wpa_supplicant_cancel_scan(wpa_s);
+
+	if (wpa_s->driver_4way_handshake &&
+	    (wpa_s->key_mgmt == WPA_KEY_MGMT_PSK ||
+	     wpa_s->key_mgmt == WPA_KEY_MGMT_FT_PSK)) {
+		/*
+		 * We are done; the driver will take care of RSN 4-way
+		 * handshake.
+		 */
+		wpa_supplicant_cancel_auth_timeout(wpa_s);
+		wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
+		eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
+		eapol_sm_notify_eap_success(wpa_s->eapol, TRUE);
+	}
 }
 
 

Modified: wpasupplicant/trunk/wpa_supplicant/mlme.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/wpa_supplicant/mlme.c?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/wpa_supplicant/mlme.c (original)
+++ wpasupplicant/trunk/wpa_supplicant/mlme.c Sat Nov  3 11:46:49 2007
@@ -460,8 +460,7 @@
 			mdie = (struct rsn_mdie *) (bss->mdie + 2);
 		if (mdie &&
 		    os_memcmp(mdie->mobility_domain, wpa_s->mlme.current_md,
-			      MOBILITY_DOMAIN_ID_LEN) == 0 &&
-		    (mdie->ft_capab & RSN_FT_CAPAB_FT_OVER_AIR)) {
+			      MOBILITY_DOMAIN_ID_LEN) == 0) {
 			wpa_printf(MSG_DEBUG, "MLME: Trying to use FT "
 				   "over-the-air");
 			wpa_s->mlme.auth_alg = WLAN_AUTH_FT;
@@ -586,15 +585,14 @@
 	    wpa_s->mlme.auth_alg != WLAN_AUTH_FT &&
 	    bss && bss->mdie &&
 	    bss->mdie_len >= 2 + sizeof(struct rsn_mdie) &&
-	    bss->mdie[1] >= sizeof(struct rsn_mdie) &&
-	    bss->mdie[2 + MOBILITY_DOMAIN_ID_LEN] & RSN_FT_CAPAB_FT_OVER_AIR) {
+	    bss->mdie[1] >= sizeof(struct rsn_mdie)) {
 		pos = buf + blen;
 		blen += 2 + sizeof(struct rsn_mdie);
 		*pos++ = WLAN_EID_MOBILITY_DOMAIN;
 		*pos++ = sizeof(struct rsn_mdie);
 		os_memcpy(pos, bss->mdie + 2, MOBILITY_DOMAIN_ID_LEN);
 		pos += MOBILITY_DOMAIN_ID_LEN;
-		*pos++ = RSN_FT_CAPAB_FT_OVER_AIR;
+		*pos++ = 0; /* FIX: copy from the target AP's MDIE */
 	}
 
 	if ((wpa_s->mlme.key_mgmt == KEY_MGMT_FT_802_1X ||

Modified: wpasupplicant/trunk/wpa_supplicant/tests/test_aes.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/wpa_supplicant/tests/test_aes.c?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/wpa_supplicant/tests/test_aes.c (original)
+++ wpasupplicant/trunk/wpa_supplicant/tests/test_aes.c Sat Nov  3 11:46:49 2007
@@ -277,6 +277,23 @@
 			printf("OMAC1-AES-128 test vector %d failed\n", i);
 			ret++;
 		}
+
+		if (tv->msg_len > 1) {
+			const u8 *addr[2];
+			size_t len[2];
+
+			addr[0] = tv->msg;
+			len[0] = 1;
+			addr[1] = tv->msg + 1;
+			len[1] = tv->msg_len - 1;
+
+			omac1_aes_128_vector(tv->k, 2, addr, len, result);
+			if (memcmp(result, tv->tag, 16) != 0) {
+				printf("OMAC1-AES-128(vector) test vector %d "
+				       "failed\n", i);
+				ret++;
+			}
+		}
 	}
 
 	ret += test_eax();

Modified: wpasupplicant/trunk/wpa_supplicant/tests/test_x509v3.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/wpa_supplicant/tests/test_x509v3.c?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/wpa_supplicant/tests/test_x509v3.c (original)
+++ wpasupplicant/trunk/wpa_supplicant/tests/test_x509v3.c Sat Nov  3 11:46:49 2007
@@ -1,6 +1,6 @@
 /*
  * Testing tool for X.509v3 routines
- * Copyright (c) 2006, Jouni Malinen <j at w1.fi>
+ * Copyright (c) 2006-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,8 +15,8 @@
 #include "includes.h"
 
 #include "common.h"
-#include "asn1.h"
-#include "x509v3.h"
+#include "tls/asn1.h"
+#include "tls/x509v3.h"
 
 extern int wpa_debug_level;
 
@@ -43,7 +43,7 @@
 			return -1;
 		}
 
-		cert = x509_certificate_parse(buf, len);
+		cert = x509_certificate_parse((u8 *) buf, len);
 		if (cert == NULL) {
 			printf("Failed to parse X.509 certificate\n");
 			return -1;

Modified: wpasupplicant/trunk/wpa_supplicant/todo.txt
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/wpa_supplicant/todo.txt?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/wpa_supplicant/todo.txt (original)
+++ wpasupplicant/trunk/wpa_supplicant/todo.txt Sat Nov  3 11:46:49 2007
@@ -50,8 +50,6 @@
 - 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>)
 - consider adding generic buffer functionality that could be used in number
   of places
   * allocate buffer (with default max size), allow reserving head room to
@@ -110,15 +108,16 @@
 - 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)
+
+- cleanup TLS/PEAP/TTLS/FAST fragmentation: both the handshake and Appl. Data
+  phases should be able to use the same functions for this;
+  the last step in processing sent should be this code and rest of the code
+  should not need to care about fragmentation at all
+- test EAP-FAST peer with OpenSSL and verify that fallback to full handshake
+  (ServerHello followed by something else than ChangeCipherSpec)

Modified: wpasupplicant/trunk/wpa_supplicant/wpa_cli.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/wpa_supplicant/wpa_cli.c?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/wpa_supplicant/wpa_cli.c (original)
+++ wpasupplicant/trunk/wpa_supplicant/wpa_cli.c Sat Nov  3 11:46:49 2007
@@ -120,8 +120,10 @@
 "    list of variables when run without arguments)\n"
 "  get_network <network id> <variable> = get network variables\n"
 "  save_config = save the current configuration\n"
-"  disconnect = disconnect and wait for reassociate command before "
-"connecting\n"
+"  disconnect = disconnect and wait for reassociate/reconnect command before\n "
+"    connecting\n"
+"  reconnect = like reassociate, but only takes effect if already "
+"disconnected\n"
 "  scan = request new BSS scan\n"
 "  scan_results = get latest scan results\n"
 "  get_capability <eap/pairwise/group/key_mgmt/proto/auth_alg> = "
@@ -323,13 +325,13 @@
 	if (argc != 2) {
 		printf("Invalid SET command: needs two arguments (variable "
 		       "name and value)\n");
-		return 0;
+		return -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;
+		return -1;
 	}
 	return wpa_ctrl_command(ctrl, cmd);
 }
@@ -363,13 +365,13 @@
 	if (argc != 1) {
 		printf("Invalid PREAUTH command: needs one argument "
 		       "(BSSID)\n");
-		return 0;
+		return -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;
+		return -1;
 	}
 	return wpa_ctrl_command(ctrl, cmd);
 }
@@ -383,12 +385,12 @@
 	if (argc != 1) {
 		printf("Invalid AP_SCAN command: needs one argument (ap_scan "
 		       "value)\n");
-		return 0;
+		return -1;
 	}
 	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 -1;
 	}
 	return wpa_ctrl_command(ctrl, cmd);
 }
@@ -403,13 +405,13 @@
 	if (argc != 1) {
 		printf("Invalid STKSTART command: needs one argument "
 		       "(Peer STA MAC address)\n");
-		return 0;
+		return -1;
 	}
 
 	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 -1;
 	}
 	return wpa_ctrl_command(ctrl, cmd);
 }
@@ -423,13 +425,13 @@
 	if (argc != 1) {
 		printf("Invalid FT_DS command: needs one argument "
 		       "(Target AP MAC address)\n");
-		return 0;
+		return -1;
 	}
 
 	res = os_snprintf(cmd, sizeof(cmd), "FT_DS %s", argv[0]);
 	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
 		printf("Too long FT_DS command.\n");
-		return 0;
+		return -1;
 	}
 	return wpa_ctrl_command(ctrl, cmd);
 }
@@ -443,12 +445,12 @@
 	if (argc != 1) {
 		printf("Invalid LEVEL command: needs one argument (debug "
 		       "level)\n");
-		return 0;
+		return -1;
 	}
 	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 -1;
 	}
 	return wpa_ctrl_command(ctrl, cmd);
 }
@@ -462,7 +464,7 @@
 	if (argc < 2) {
 		printf("Invalid IDENTITY command: needs two arguments "
 		       "(network id and identity)\n");
-		return 0;
+		return -1;
 	}
 
 	end = cmd + sizeof(cmd);
@@ -471,14 +473,14 @@
 			  argv[0], argv[1]);
 	if (ret < 0 || ret >= end - pos) {
 		printf("Too long IDENTITY command.\n");
-		return 0;
+		return -1;
 	}
 	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;
+			return -1;
 		}
 		pos += ret;
 	}
@@ -495,7 +497,7 @@
 	if (argc < 2) {
 		printf("Invalid PASSWORD command: needs two arguments "
 		       "(network id and password)\n");
-		return 0;
+		return -1;
 	}
 
 	end = cmd + sizeof(cmd);
@@ -504,14 +506,14 @@
 			  argv[0], argv[1]);
 	if (ret < 0 || ret >= end - pos) {
 		printf("Too long PASSWORD command.\n");
-		return 0;
+		return -1;
 	}
 	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;
+			return -1;
 		}
 		pos += ret;
 	}
@@ -529,7 +531,7 @@
 	if (argc < 2) {
 		printf("Invalid NEW_PASSWORD command: needs two arguments "
 		       "(network id and password)\n");
-		return 0;
+		return -1;
 	}
 
 	end = cmd + sizeof(cmd);
@@ -538,14 +540,14 @@
 			  argv[0], argv[1]);
 	if (ret < 0 || ret >= end - pos) {
 		printf("Too long NEW_PASSWORD command.\n");
-		return 0;
+		return -1;
 	}
 	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;
+			return -1;
 		}
 		pos += ret;
 	}
@@ -562,7 +564,7 @@
 	if (argc < 2) {
 		printf("Invalid PIN command: needs two arguments "
 		       "(network id and pin)\n");
-		return 0;
+		return -1;
 	}
 
 	end = cmd + sizeof(cmd);
@@ -571,14 +573,14 @@
 			  argv[0], argv[1]);
 	if (ret < 0 || ret >= end - pos) {
 		printf("Too long PIN command.\n");
-		return 0;
+		return -1;
 	}
 	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;
+			return -1;
 		}
 		pos += ret;
 	}
@@ -594,7 +596,7 @@
 	if (argc < 2) {
 		printf("Invalid OTP command: needs two arguments (network "
 		       "id and password)\n");
-		return 0;
+		return -1;
 	}
 
 	end = cmd + sizeof(cmd);
@@ -603,14 +605,14 @@
 			  argv[0], argv[1]);
 	if (ret < 0 || ret >= end - pos) {
 		printf("Too long OTP command.\n");
-		return 0;
+		return -1;
 	}
 	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;
+			return -1;
 		}
 		pos += ret;
 	}
@@ -628,7 +630,7 @@
 	if (argc < 2) {
 		printf("Invalid PASSPHRASE command: needs two arguments "
 		       "(network id and passphrase)\n");
-		return 0;
+		return -1;
 	}
 
 	end = cmd + sizeof(cmd);
@@ -637,14 +639,14 @@
 			  argv[0], argv[1]);
 	if (ret < 0 || ret >= end - pos) {
 		printf("Too long PASSPHRASE command.\n");
-		return 0;
+		return -1;
 	}
 	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;
+			return -1;
 		}
 		pos += ret;
 	}
@@ -661,7 +663,7 @@
 	if (argc < 2) {
 		printf("Invalid BSSID command: needs two arguments (network "
 		       "id and BSSID)\n");
-		return 0;
+		return -1;
 	}
 
 	end = cmd + sizeof(cmd);
@@ -669,14 +671,14 @@
 	ret = os_snprintf(pos, end - pos, "BSSID");
 	if (ret < 0 || ret >= end - pos) {
 		printf("Too long BSSID command.\n");
-		return 0;
+		return -1;
 	}
 	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;
+			return -1;
 		}
 		pos += ret;
 	}
@@ -701,7 +703,7 @@
 	if (argc < 1) {
 		printf("Invalid SELECT_NETWORK command: needs one argument "
 		       "(network id)\n");
-		return 0;
+		return -1;
 	}
 
 	res = os_snprintf(cmd, sizeof(cmd), "SELECT_NETWORK %s", argv[0]);
@@ -722,7 +724,7 @@
 	if (argc < 1) {
 		printf("Invalid ENABLE_NETWORK command: needs one argument "
 		       "(network id)\n");
-		return 0;
+		return -1;
 	}
 
 	res = os_snprintf(cmd, sizeof(cmd), "ENABLE_NETWORK %s", argv[0]);
@@ -743,7 +745,7 @@
 	if (argc < 1) {
 		printf("Invalid DISABLE_NETWORK command: needs one argument "
 		       "(network id)\n");
-		return 0;
+		return -1;
 	}
 
 	res = os_snprintf(cmd, sizeof(cmd), "DISABLE_NETWORK %s", argv[0]);
@@ -771,7 +773,7 @@
 	if (argc < 1) {
 		printf("Invalid REMOVE_NETWORK command: needs one argument "
 		       "(network id)\n");
-		return 0;
+		return -1;
 	}
 
 	res = os_snprintf(cmd, sizeof(cmd), "REMOVE_NETWORK %s", argv[0]);
@@ -818,14 +820,14 @@
 	if (argc != 3) {
 		printf("Invalid SET_NETWORK command: needs three arguments\n"
 		       "(network id, variable name, and value)\n");
-		return 0;
+		return -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;
+		return -1;
 	}
 	return wpa_ctrl_command(ctrl, cmd);
 }
@@ -845,14 +847,14 @@
 	if (argc != 2) {
 		printf("Invalid GET_NETWORK command: needs two arguments\n"
 		       "(network id and variable name)\n");
-		return 0;
+		return -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;
+		return -1;
 	}
 	return wpa_ctrl_command(ctrl, cmd);
 }
@@ -862,6 +864,13 @@
 				  char *argv[])
 {
 	return wpa_ctrl_command(ctrl, "DISCONNECT");
+}
+
+
+static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
+				  char *argv[])
+{
+	return wpa_ctrl_command(ctrl, "RECONNECT");
 }
 
 
@@ -894,13 +903,13 @@
 	if (argc < 1 || argc > 2) {
 		printf("Invalid GET_CAPABILITY command: need either one or "
 		       "two arguments\n");
-		return 0;
+		return -1;
 	}
 
 	if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
 		printf("Invalid GET_CAPABILITY command: second argument, "
 		       "if any, must be 'strict'\n");
-		return 0;
+		return -1;
 	}
 
 	res = os_snprintf(cmd, sizeof(cmd), "GET_CAPABILITY %s%s", argv[0],
@@ -972,7 +981,7 @@
 		       "argument (interface name)\n"
 		       "All arguments: ifname confname driver ctrl_interface "
 		       "driver_param bridge_name\n");
-		return 0;
+		return -1;
 	}
 
 	/*
@@ -1001,7 +1010,7 @@
 	if (argc != 1) {
 		printf("Invalid INTERFACE_REMOVE command: needs one argument "
 		       "(interface name)\n");
-		return 0;
+		return -1;
 	}
 
 	res = os_snprintf(cmd, sizeof(cmd), "INTERFACE_REMOVE %s", argv[0]);
@@ -1049,6 +1058,7 @@
 	{ "get_network", wpa_cli_cmd_get_network },
 	{ "save_config", wpa_cli_cmd_save_config },
 	{ "disconnect", wpa_cli_cmd_disconnect },
+	{ "reconnect", wpa_cli_cmd_reconnect },
 	{ "scan", wpa_cli_cmd_scan },
 	{ "scan_results", wpa_cli_cmd_scan_results },
 	{ "get_capability", wpa_cli_cmd_get_capability },
@@ -1063,10 +1073,11 @@
 };
 
 
-static void wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
+static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
 {
 	struct wpa_cli_cmd *cmd, *match = NULL;
 	int count;
+	int ret = 0;
 
 	count = 0;
 	cmd = wpa_cli_commands;
@@ -1095,11 +1106,15 @@
 			cmd++;
 		}
 		printf("\n");
+		ret = 1;
 	} else if (count == 0) {
 		printf("Unknown command '%s'\n", argv[0]);
+		ret = 1;
 	} else {
-		match->handler(ctrl, argc - 1, &argv[1]);
-	}
+		ret = match->handler(ctrl, argc - 1, &argv[1]);
+	}
+
+	return ret;
 }
 
 
@@ -1554,6 +1569,7 @@
 	int warning_displayed = 0;
 	int c;
 	int daemonize = 0;
+	int ret = 0;
 	const char *global = NULL;
 
 	if (os_program_init())
@@ -1665,12 +1681,12 @@
 	else if (action_file)
 		wpa_cli_action(ctrl_conn);
 	else
-		wpa_request(ctrl_conn, argc - optind, &argv[optind]);
+		ret = wpa_request(ctrl_conn, argc - optind, &argv[optind]);
 
 	os_free(ctrl_ifname);
 	wpa_cli_cleanup();
 
-	return 0;
+	return ret;
 }
 
 #else /* CONFIG_CTRL_IFACE */

Modified: wpasupplicant/trunk/wpa_supplicant/wpa_supplicant.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/wpa_supplicant/wpa_supplicant.c?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/wpa_supplicant/wpa_supplicant.c (original)
+++ wpasupplicant/trunk/wpa_supplicant/wpa_supplicant.c Sat Nov  3 11:46:49 2007
@@ -1512,6 +1512,11 @@
 	}
 	params.wep_tx_keyidx = ssid->wep_tx_keyidx;
 
+	if (wpa_s->driver_4way_handshake &&
+	    (params.key_mgmt_suite == KEY_MGMT_PSK ||
+	     params.key_mgmt_suite == KEY_MGMT_FT_PSK))
+		params.passphrase = ssid->passphrase;
+
 #ifdef CONFIG_IEEE80211W
 	switch (ssid->ieee80211w) {
 	case NO_IEEE80211W:
@@ -1987,7 +1992,11 @@
 		return;
 	}
 
-	if (wpa_s->eapol_received == 0) {
+	if (wpa_s->eapol_received == 0 &&
+	    (!wpa_s->driver_4way_handshake ||
+	     (wpa_s->key_mgmt != WPA_KEY_MGMT_PSK &&
+	      wpa_s->key_mgmt != WPA_KEY_MGMT_FT_PSK) ||
+	     wpa_s->wpa_state != WPA_COMPLETED)) {
 		/* Timeout for completing IEEE 802.1X and WPA authentication */
 		wpa_supplicant_req_auth_timeout(
 			wpa_s,
@@ -2016,7 +2025,18 @@
 	    eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
 		return;
 	wpa_drv_poll(wpa_s);
-	wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
+	if (!wpa_s->driver_4way_handshake)
+		wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
+	else if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X ||
+		 wpa_s->key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X) {
+		/*
+		 * Set portValid = TRUE here since we are going to skip 4-way
+		 * handshake processing which would normally set portValid. We
+		 * need this to allow the EAPOL state machines to be completed
+		 * without going through EAPOL-Key handshake.
+		 */
+		eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
+	}
 }
 
 
@@ -2220,6 +2240,57 @@
 }
 
 
+#ifdef IEEE8021X_EAPOL
+static void wpa_supplicant_eapol_cb(struct eapol_sm *eapol, int success,
+				    void *ctx)
+{
+	struct wpa_supplicant *wpa_s = ctx;
+	int res, pmk_len;
+	u8 pmk[PMK_LEN];
+
+	wpa_printf(MSG_DEBUG, "EAPOL authentication completed %ssuccessfully",
+		   success ? "" : "un");
+
+	if (!success || !wpa_s->driver_4way_handshake)
+		return;
+
+	if (wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X &&
+	    wpa_s->key_mgmt != WPA_KEY_MGMT_FT_IEEE8021X)
+		return;
+
+	wpa_printf(MSG_DEBUG, "Configure PMK for driver-based RSN 4-way "
+		   "handshake");
+
+	pmk_len = PMK_LEN;
+	res = eapol_sm_get_key(eapol, pmk, PMK_LEN);
+	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;
+	}
+
+	if (res) {
+		wpa_printf(MSG_DEBUG, "Failed to get PMK from EAPOL state "
+			   "machines");
+		return;
+	}
+
+	if (wpa_drv_set_key(wpa_s, WPA_ALG_PMK, NULL, 0, 0, NULL, 0, pmk,
+			    pmk_len)) {
+		wpa_printf(MSG_DEBUG, "Failed to set PMK to the driver");
+	}
+
+	eloop_cancel_timeout(wpa_supplicant_scan, wpa_s, NULL);
+	wpa_supplicant_cancel_auth_timeout(wpa_s);
+	wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
+
+}
+#endif /* IEEE8021X_EAPOL */
+
+
 static int wpa_supplicant_init_eapol(struct wpa_supplicant *wpa_s)
 {
 #ifdef IEEE8021X_EAPOL
@@ -2243,6 +2314,8 @@
 	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;
+	ctx->cb = wpa_supplicant_eapol_cb;
+	ctx->cb_ctx = wpa_s;
 	wpa_s->eapol = eapol_sm_init(ctx);
 	if (wpa_s->eapol == NULL) {
 		os_free(ctx);
@@ -2392,11 +2465,14 @@
 		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;
+	if (wpa_drv_get_capa(wpa_s, &capa) == 0) {
+		if (capa.flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME) {
+			wpa_s->use_client_mlme = 1;
+			if (ieee80211_sta_init(wpa_s))
+				return -1;
+		}
+		if (capa.flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE)
+			wpa_s->driver_4way_handshake = 1;
 	}
 
 	return 0;

Modified: wpasupplicant/trunk/wpa_supplicant/wpa_supplicant.conf
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/wpa_supplicant/wpa_supplicant.conf?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/wpa_supplicant/wpa_supplicant.conf (original)
+++ wpasupplicant/trunk/wpa_supplicant/wpa_supplicant.conf Sat Nov  3 11:46:49 2007
@@ -295,7 +295,11 @@
 # anonymous_identity: Anonymous identity string for EAP (to be used as the
 #	unencrypted identity with EAP types that support different tunnelled
 #	identity, e.g., EAP-TTLS)
-# password: Password string for EAP
+# password: Password string for EAP. This field can include either the
+#	plaintext password (using ASCII or hex string) or a NtPasswordHash
+#	(16-byte MD4 hash of password) in hash:<32 hex digits> format.
+#	NtPasswordHash can only be used when the password is for MSCHAPv2 or
+#	MSCHAP (EAP-MSCHAPv2, EAP-TTLS/MSCHAPv2, EAP-TTLS/MSCHAP, LEAP)
 # ca_cert: File path to CA certificate file (PEM/DER). This file can have one
 #	or more trusted CA certificates. If ca_cert and ca_path are not
 #	included, server certificate will not be verified. This is insecure and

Modified: wpasupplicant/trunk/wpa_supplicant/wpa_supplicant_i.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/wpa_supplicant/wpa_supplicant_i.h?rev=880&op=diff
==============================================================================
--- wpasupplicant/trunk/wpa_supplicant/wpa_supplicant_i.h (original)
+++ wpasupplicant/trunk/wpa_supplicant/wpa_supplicant_i.h Sat Nov  3 11:46:49 2007
@@ -349,6 +349,7 @@
 
 	struct wpa_client_mlme mlme;
 	int use_client_mlme;
+	int driver_4way_handshake;
 };
 
 




More information about the Pkg-wpa-devel mailing list