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

kelmo-guest at users.alioth.debian.org kelmo-guest at users.alioth.debian.org
Sat Jun 14 00:40:28 UTC 2008


Author: kelmo-guest
Date: Sat Jun 14 00:40:26 2008
New Revision: 1188

URL: http://svn.debian.org/wsvn/pkg-wpa/?sc=1&rev=1188
Log:
(NOT RELEASED YET) New upstream git snapshot.

Added:
    wpasupplicant/trunk/patches/openssl-0.9.8h-tls-extensions.patch
      - copied unchanged from r1187, wpasupplicant/branches/upstream/current/patches/openssl-0.9.8h-tls-extensions.patch
    wpasupplicant/trunk/src/drivers/driver_nl80211.c
      - copied unchanged from r1187, wpasupplicant/branches/upstream/current/src/drivers/driver_nl80211.c
    wpasupplicant/trunk/src/drivers/driver_ps3.c
      - copied unchanged from r1187, wpasupplicant/branches/upstream/current/src/drivers/driver_ps3.c
    wpasupplicant/trunk/src/eap_common/eap_fast_common.c
      - copied unchanged from r1187, wpasupplicant/branches/upstream/current/src/eap_common/eap_fast_common.c
    wpasupplicant/trunk/src/eap_common/eap_peap_common.c
      - copied unchanged from r1187, wpasupplicant/branches/upstream/current/src/eap_common/eap_peap_common.c
    wpasupplicant/trunk/src/eap_common/eap_peap_common.h
      - copied unchanged from r1187, wpasupplicant/branches/upstream/current/src/eap_common/eap_peap_common.h
    wpasupplicant/trunk/src/eap_server/eap_tnc.c
      - copied unchanged from r1187, wpasupplicant/branches/upstream/current/src/eap_server/eap_tnc.c
    wpasupplicant/trunk/src/eap_server/tncs.c
      - copied unchanged from r1187, wpasupplicant/branches/upstream/current/src/eap_server/tncs.c
    wpasupplicant/trunk/src/eap_server/tncs.h
      - copied unchanged from r1187, wpasupplicant/branches/upstream/current/src/eap_server/tncs.h
    wpasupplicant/trunk/wpa_supplicant/examples/openCryptoki.conf
      - copied unchanged from r1187, wpasupplicant/branches/upstream/current/wpa_supplicant/examples/openCryptoki.conf
Removed:
    wpasupplicant/trunk/src/eap_peer/eap_tlv.c
    wpasupplicant/trunk/src/eap_peer/eap_tlv.h
    wpasupplicant/trunk/src/eap_server/eap_tlv.c
Modified:
    wpasupplicant/trunk/debian/changelog
    wpasupplicant/trunk/patches/openssl-0.9.8g-tls-extensions.patch
    wpasupplicant/trunk/patches/openssl-0.9.9-session-ticket.patch
    wpasupplicant/trunk/src/common/ieee802_11_defs.h
    wpasupplicant/trunk/src/common/wpa_common.h
    wpasupplicant/trunk/src/crypto/crypto_internal.c
    wpasupplicant/trunk/src/crypto/sha1.c
    wpasupplicant/trunk/src/crypto/tls.h
    wpasupplicant/trunk/src/crypto/tls_openssl.c
    wpasupplicant/trunk/src/drivers/driver_hostap.h
    wpasupplicant/trunk/src/drivers/driver_ndis.c
    wpasupplicant/trunk/src/drivers/driver_ralink.c
    wpasupplicant/trunk/src/drivers/driver_wext.c
    wpasupplicant/trunk/src/drivers/driver_wext.h
    wpasupplicant/trunk/src/drivers/drivers.c
    wpasupplicant/trunk/src/eap_common/eap_defs.h
    wpasupplicant/trunk/src/eap_common/eap_fast_common.h
    wpasupplicant/trunk/src/eap_common/eap_tlv_common.h
    wpasupplicant/trunk/src/eap_peer/eap_config.h
    wpasupplicant/trunk/src/eap_peer/eap_fast.c
    wpasupplicant/trunk/src/eap_peer/eap_peap.c
    wpasupplicant/trunk/src/eap_peer/eap_tls_common.c
    wpasupplicant/trunk/src/eap_peer/eap_tnc.c
    wpasupplicant/trunk/src/eap_peer/eap_ttls.c
    wpasupplicant/trunk/src/eap_peer/tncc.c
    wpasupplicant/trunk/src/eap_peer/tncc.h
    wpasupplicant/trunk/src/eap_server/eap.c
    wpasupplicant/trunk/src/eap_server/eap.h
    wpasupplicant/trunk/src/eap_server/eap_fast.c
    wpasupplicant/trunk/src/eap_server/eap_gtc.c
    wpasupplicant/trunk/src/eap_server/eap_i.h
    wpasupplicant/trunk/src/eap_server/eap_ikev2.c
    wpasupplicant/trunk/src/eap_server/eap_methods.c
    wpasupplicant/trunk/src/eap_server/eap_peap.c
    wpasupplicant/trunk/src/eap_server/eap_tls.c
    wpasupplicant/trunk/src/eap_server/eap_tls_common.c
    wpasupplicant/trunk/src/eap_server/eap_tls_common.h
    wpasupplicant/trunk/src/eap_server/eap_ttls.c
    wpasupplicant/trunk/src/radius/radius.c
    wpasupplicant/trunk/src/radius/radius.h
    wpasupplicant/trunk/src/radius/radius_client.c
    wpasupplicant/trunk/src/radius/radius_client.h
    wpasupplicant/trunk/src/radius/radius_server.c
    wpasupplicant/trunk/src/radius/radius_server.h
    wpasupplicant/trunk/src/rsn_supp/peerkey.c
    wpasupplicant/trunk/src/rsn_supp/preauth.c
    wpasupplicant/trunk/src/rsn_supp/wpa.c
    wpasupplicant/trunk/src/rsn_supp/wpa.h
    wpasupplicant/trunk/src/rsn_supp/wpa_ft.c
    wpasupplicant/trunk/src/rsn_supp/wpa_i.h
    wpasupplicant/trunk/src/tls/libtommath.c
    wpasupplicant/trunk/src/utils/base64.c
    wpasupplicant/trunk/src/utils/common.h
    wpasupplicant/trunk/src/utils/eloop.c
    wpasupplicant/trunk/src/utils/eloop.h
    wpasupplicant/trunk/src/utils/eloop_none.c
    wpasupplicant/trunk/src/utils/eloop_win.c
    wpasupplicant/trunk/src/utils/wpabuf.c
    wpasupplicant/trunk/src/utils/wpabuf.h
    wpasupplicant/trunk/wpa_supplicant/ChangeLog
    wpasupplicant/trunk/wpa_supplicant/Makefile
    wpasupplicant/trunk/wpa_supplicant/config.c
    wpasupplicant/trunk/wpa_supplicant/config_file.c
    wpasupplicant/trunk/wpa_supplicant/config_winreg.c
    wpasupplicant/trunk/wpa_supplicant/ctrl_iface.c
    wpasupplicant/trunk/wpa_supplicant/ctrl_iface_dbus.c
    wpasupplicant/trunk/wpa_supplicant/ctrl_iface_dbus_handlers.c
    wpasupplicant/trunk/wpa_supplicant/ctrl_iface_dbus_handlers.h
    wpasupplicant/trunk/wpa_supplicant/ctrl_iface_unix.c
    wpasupplicant/trunk/wpa_supplicant/dbus_dict_helpers.c
    wpasupplicant/trunk/wpa_supplicant/defconfig
    wpasupplicant/trunk/wpa_supplicant/doc/docbook/wpa_cli.sgml
    wpasupplicant/trunk/wpa_supplicant/doc/docbook/wpa_priv.sgml
    wpasupplicant/trunk/wpa_supplicant/doc/docbook/wpa_supplicant.conf.sgml
    wpasupplicant/trunk/wpa_supplicant/doc/docbook/wpa_supplicant.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/main.c
    wpasupplicant/trunk/wpa_supplicant/mlme.c
    wpasupplicant/trunk/wpa_supplicant/preauth_test.c
    wpasupplicant/trunk/wpa_supplicant/scan.c
    wpasupplicant/trunk/wpa_supplicant/todo.txt
    wpasupplicant/trunk/wpa_supplicant/wpa_gui/networkconfig.ui.h
    wpasupplicant/trunk/wpa_supplicant/wpa_gui/userdatarequest.ui.h
    wpasupplicant/trunk/wpa_supplicant/wpa_gui/wpagui.ui.h
    wpasupplicant/trunk/wpa_supplicant/wpa_gui/wpamsg.h
    wpasupplicant/trunk/wpa_supplicant/wpa_supplicant.c
    wpasupplicant/trunk/wpa_supplicant/wpa_supplicant.conf
    wpasupplicant/trunk/wpa_supplicant/wpas_glue.c

Modified: wpasupplicant/trunk/debian/changelog
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/debian/changelog?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/debian/changelog (original)
+++ wpasupplicant/trunk/debian/changelog Sat Jun 14 00:40:26 2008
@@ -1,3 +1,9 @@
+wpasupplicant (0.6.4~git20080614.f598194-1) UNRELEASED; urgency=low
+
+  * (NOT RELEASED YET) New upstream git snapshot.
+
+ -- Kel Modderman <kel at otaku42.de>  Sat, 14 Jun 2008 10:39:51 +1000
+
 wpasupplicant (0.6.3-2) UNRELEASED; urgency=low
 
   * Add patch to remove -w option from help output, it has been removed in

Modified: wpasupplicant/trunk/patches/openssl-0.9.8g-tls-extensions.patch
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/patches/openssl-0.9.8g-tls-extensions.patch?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/patches/openssl-0.9.8g-tls-extensions.patch (original)
+++ wpasupplicant/trunk/patches/openssl-0.9.8g-tls-extensions.patch Sat Jun 14 00:40:26 2008
@@ -1,4 +1,4 @@
-This patch adds support for TLS SessionTicket extension (RFC 4507) for
+This patch adds support for TLS SessionTicket extension (RFC 5077) for
 the parts used by EAP-FAST (RFC 4851).
 
 This is based on the patch from Alexey Kobozev <akobozev at cisco.com>
@@ -10,25 +10,14 @@
 
 
 diff -upr openssl-0.9.8g.orig/ssl/s3_clnt.c openssl-0.9.8g/ssl/s3_clnt.c
---- openssl-0.9.8g.orig/ssl/s3_clnt.c	2007-08-30 17:28:51.000000000 -0700
-+++ openssl-0.9.8g/ssl/s3_clnt.c	2007-11-01 20:08:08.000000000 -0700
-@@ -660,7 +660,7 @@ int ssl3_get_server_hello(SSL *s)
- 	STACK_OF(SSL_CIPHER) *sk;
- 	SSL_CIPHER *c;
- 	unsigned char *p,*d;
--	int i,al,ok;
-+	int i,al,ok,pre_shared;
- 	unsigned int j;
- 	long n;
- #ifndef OPENSSL_NO_COMP
-@@ -727,7 +727,26 @@ int ssl3_get_server_hello(SSL *s)
+--- openssl-0.9.8g.orig/ssl/s3_clnt.c	2007-08-31 03:28:51.000000000 +0300
++++ openssl-0.9.8g/ssl/s3_clnt.c	2008-04-15 17:11:46.000000000 +0300
+@@ -727,6 +727,20 @@ int ssl3_get_server_hello(SSL *s)
  		goto f_err;
  		}
  
--	if (j != 0 && j == s->session->session_id_length
++#ifndef OPENSSL_NO_TLSEXT
 +	/* check if we want to resume the session based on external pre-shared secret */
-+	pre_shared = 0;
-+#ifndef OPENSSL_NO_TLSEXT
 +	if (s->version >= TLS1_VERSION && s->tls_session_secret_cb)
 +	{
 +		SSL_CIPHER *pref_cipher=NULL;
@@ -36,22 +25,17 @@
 +		if (s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length,
 +			NULL, &pref_cipher, s->tls_session_secret_cb_arg))
 +		{
-+			s->hit=1;
 +			s->session->cipher=pref_cipher ? pref_cipher : ssl_get_cipher_by_char(s,p+j);
-+			s->session->session_id_length = j;
-+			memcpy(s->session->session_id, p, j);
-+			pre_shared = 1;
 +		}
 +	}
 +#endif /* OPENSSL_NO_TLSEXT */
 +
-+	if ((pre_shared || j != 0) && j == s->session->session_id_length
+ 	if (j != 0 && j == s->session->session_id_length
  	    && memcmp(p,s->session->session_id,j) == 0)
  	    {
- 	    if(s->sid_ctx_length != s->session->sid_ctx_length
 diff -upr openssl-0.9.8g.orig/ssl/s3_srvr.c openssl-0.9.8g/ssl/s3_srvr.c
---- openssl-0.9.8g.orig/ssl/s3_srvr.c	2007-09-30 11:55:59.000000000 -0700
-+++ openssl-0.9.8g/ssl/s3_srvr.c	2007-11-02 19:24:20.000000000 -0700
+--- openssl-0.9.8g.orig/ssl/s3_srvr.c	2007-09-30 21:55:59.000000000 +0300
++++ openssl-0.9.8g/ssl/s3_srvr.c	2008-04-15 17:10:37.000000000 +0300
 @@ -928,6 +928,59 @@ int ssl3_get_client_hello(SSL *s)
  			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT);
  			goto err;
@@ -137,8 +121,8 @@
  		d=p= &(buf[4]);
  
 diff -upr openssl-0.9.8g.orig/ssl/ssl.h openssl-0.9.8g/ssl/ssl.h
---- openssl-0.9.8g.orig/ssl/ssl.h	2007-10-19 00:42:38.000000000 -0700
-+++ openssl-0.9.8g/ssl/ssl.h	2007-11-01 20:08:08.000000000 -0700
+--- openssl-0.9.8g.orig/ssl/ssl.h	2007-10-19 10:42:38.000000000 +0300
++++ openssl-0.9.8g/ssl/ssl.h	2008-04-15 17:10:37.000000000 +0300
 @@ -342,6 +342,7 @@ extern "C" {
   * 'struct ssl_st *' function parameters used to prototype callbacks
   * in SSL_CTX. */
@@ -193,8 +177,8 @@
  /* Reason codes. */
  #define SSL_R_APP_DATA_IN_HANDSHAKE			 100
 diff -upr openssl-0.9.8g.orig/ssl/ssl_err.c openssl-0.9.8g/ssl/ssl_err.c
---- openssl-0.9.8g.orig/ssl/ssl_err.c	2007-10-11 07:36:59.000000000 -0700
-+++ openssl-0.9.8g/ssl/ssl_err.c	2007-11-01 20:08:08.000000000 -0700
+--- openssl-0.9.8g.orig/ssl/ssl_err.c	2007-10-11 17:36:59.000000000 +0300
++++ openssl-0.9.8g/ssl/ssl_err.c	2008-04-15 17:10:37.000000000 +0300
 @@ -250,6 +250,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
  {ERR_FUNC(SSL_F_TLS1_ENC),	"TLS1_ENC"},
  {ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK),	"TLS1_SETUP_KEY_BLOCK"},
@@ -204,8 +188,8 @@
  	};
  
 diff -upr openssl-0.9.8g.orig/ssl/ssl_sess.c openssl-0.9.8g/ssl/ssl_sess.c
---- openssl-0.9.8g.orig/ssl/ssl_sess.c	2007-10-19 00:36:34.000000000 -0700
-+++ openssl-0.9.8g/ssl/ssl_sess.c	2007-11-01 20:08:08.000000000 -0700
+--- openssl-0.9.8g.orig/ssl/ssl_sess.c	2007-10-19 10:36:34.000000000 +0300
++++ openssl-0.9.8g/ssl/ssl_sess.c	2008-04-15 17:10:37.000000000 +0300
 @@ -704,6 +704,52 @@ long SSL_CTX_get_timeout(const SSL_CTX *
  	return(s->session_timeout);
  	}
@@ -260,8 +244,8 @@
  	{
  	SSL_CTX *ctx;
 diff -upr openssl-0.9.8g.orig/ssl/t1_lib.c openssl-0.9.8g/ssl/t1_lib.c
---- openssl-0.9.8g.orig/ssl/t1_lib.c	2007-10-19 00:44:10.000000000 -0700
-+++ openssl-0.9.8g/ssl/t1_lib.c	2007-11-01 20:08:08.000000000 -0700
+--- openssl-0.9.8g.orig/ssl/t1_lib.c	2007-10-19 10:44:10.000000000 +0300
++++ openssl-0.9.8g/ssl/t1_lib.c	2008-04-15 17:10:37.000000000 +0300
 @@ -105,6 +105,12 @@ int tls1_new(SSL *s)
  
  void tls1_free(SSL *s)
@@ -318,8 +302,8 @@
  									ret);
  			}
 diff -upr openssl-0.9.8g.orig/ssl/tls1.h openssl-0.9.8g/ssl/tls1.h
---- openssl-0.9.8g.orig/ssl/tls1.h	2007-08-27 18:12:44.000000000 -0700
-+++ openssl-0.9.8g/ssl/tls1.h	2007-11-01 20:08:08.000000000 -0700
+--- openssl-0.9.8g.orig/ssl/tls1.h	2007-08-28 04:12:44.000000000 +0300
++++ openssl-0.9.8g/ssl/tls1.h	2008-04-15 17:10:37.000000000 +0300
 @@ -365,6 +365,14 @@ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TLSEXT_SER
  #define TLS_MD_MASTER_SECRET_CONST    "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74"  /*master secret*/
  #endif
@@ -336,8 +320,8 @@
  }
  #endif
 diff -upr openssl-0.9.8g.orig/util/ssleay.num openssl-0.9.8g/util/ssleay.num
---- openssl-0.9.8g.orig/util/ssleay.num	2007-08-12 15:31:16.000000000 -0700
-+++ openssl-0.9.8g/util/ssleay.num	2007-11-01 20:08:08.000000000 -0700
+--- openssl-0.9.8g.orig/util/ssleay.num	2007-08-13 01:31:16.000000000 +0300
++++ openssl-0.9.8g/util/ssleay.num	2008-04-15 17:10:37.000000000 +0300
 @@ -241,3 +241,5 @@ SSL_CTX_sess_get_remove_cb              
  SSL_set_SSL_CTX                         290	EXIST::FUNCTION:
  SSL_get_servername                      291	EXIST::FUNCTION:TLSEXT

Modified: wpasupplicant/trunk/patches/openssl-0.9.9-session-ticket.patch
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/patches/openssl-0.9.9-session-ticket.patch?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/patches/openssl-0.9.9-session-ticket.patch (original)
+++ wpasupplicant/trunk/patches/openssl-0.9.9-session-ticket.patch Sat Jun 14 00:40:26 2008
@@ -1,4 +1,4 @@
-This patch adds support for TLS SessionTicket extension (RFC 4507) for
+This patch adds support for TLS SessionTicket extension (RFC 5077) for
 the parts used by EAP-FAST (RFC 4851).
 
 This is based on the patch from Alexey Kobozev <akobozev at cisco.com>
@@ -6,26 +6,15 @@
 
 
 
-diff -upr openssl-SNAP-20071101.orig/ssl/s3_clnt.c openssl-SNAP-20071101/ssl/s3_clnt.c
---- openssl-SNAP-20071101.orig/ssl/s3_clnt.c	2007-10-26 06:00:28.000000000 -0700
-+++ openssl-SNAP-20071101/ssl/s3_clnt.c	2007-11-01 19:19:43.000000000 -0700
-@@ -715,7 +715,7 @@ int ssl3_get_server_hello(SSL *s)
- 	STACK_OF(SSL_CIPHER) *sk;
- 	SSL_CIPHER *c;
- 	unsigned char *p,*d;
--	int i,al,ok;
-+	int i,al,ok,pre_shared;
- 	unsigned int j;
- 	long n;
- #ifndef OPENSSL_NO_COMP
-@@ -782,7 +782,26 @@ int ssl3_get_server_hello(SSL *s)
+diff -upr openssl-SNAP-20080528.orig/ssl/s3_clnt.c openssl-SNAP-20080528/ssl/s3_clnt.c
+--- openssl-SNAP-20080528.orig/ssl/s3_clnt.c	2008-04-29 21:00:17.000000000 +0300
++++ openssl-SNAP-20080528/ssl/s3_clnt.c	2008-05-29 10:55:43.000000000 +0300
+@@ -785,6 +785,20 @@ int ssl3_get_server_hello(SSL *s)
  		goto f_err;
  		}
  
--	if (j != 0 && j == s->session->session_id_length
++#ifndef OPENSSL_NO_TLSEXT
 +	/* check if we want to resume the session based on external pre-shared secret */
-+	pre_shared = 0;
-+#ifndef OPENSSL_NO_TLSEXT
 +	if (s->version >= TLS1_VERSION && s->tls_session_secret_cb)
 +	{
 +		SSL_CIPHER *pref_cipher=NULL;
@@ -33,23 +22,32 @@
 +		if (s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length,
 +			NULL, &pref_cipher, s->tls_session_secret_cb_arg))
 +		{
-+			s->hit=1;
 +			s->session->cipher=pref_cipher ? pref_cipher : ssl_get_cipher_by_char(s,p+j);
-+			s->session->session_id_length = j;
-+			memcpy(s->session->session_id, p, j);
-+			pre_shared = 1;
 +		}
 +	}
 +#endif /* OPENSSL_NO_TLSEXT */
 +
-+	if ((pre_shared || j != 0) && j == s->session->session_id_length
+ 	if (j != 0 && j == s->session->session_id_length
  	    && memcmp(p,s->session->session_id,j) == 0)
  	    {
- 	    if(s->sid_ctx_length != s->session->sid_ctx_length
-diff -upr openssl-SNAP-20071101.orig/ssl/s3_srvr.c openssl-SNAP-20071101/ssl/s3_srvr.c
---- openssl-SNAP-20071101.orig/ssl/s3_srvr.c	2007-10-26 06:00:29.000000000 -0700
-+++ openssl-SNAP-20071101/ssl/s3_srvr.c	2007-11-01 19:19:43.000000000 -0700
-@@ -992,6 +992,59 @@ int ssl3_get_client_hello(SSL *s)
+@@ -2918,11 +2932,8 @@ static int ssl3_check_finished(SSL *s)
+ 	{
+ 	int ok;
+ 	long n;
+-	/* If we have no ticket or session ID is non-zero length (a match of
+-	 * a non-zero session length would never reach here) it cannot be a
+-	 * resumed session.
+-	 */
+-	if (!s->session->tlsext_tick || s->session->session_id_length)
++	/* If we have no ticket it cannot be a resumed session. */
++	if (!s->session->tlsext_tick)
+ 		return 1;
+ 	/* this function is called when we really expect a Certificate
+ 	 * message, so permit appropriate message length */
+diff -upr openssl-SNAP-20080528.orig/ssl/s3_srvr.c openssl-SNAP-20080528/ssl/s3_srvr.c
+--- openssl-SNAP-20080528.orig/ssl/s3_srvr.c	2008-04-30 20:00:38.000000000 +0300
++++ openssl-SNAP-20080528/ssl/s3_srvr.c	2008-05-29 10:49:25.000000000 +0300
+@@ -1004,6 +1004,59 @@ int ssl3_get_client_hello(SSL *s)
  			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT);
  			goto err;
  		}
@@ -109,7 +107,7 @@
  #endif
  
  	/* Worst case, we will use the NULL compression, but if we have other
-@@ -1118,16 +1171,22 @@ int ssl3_send_server_hello(SSL *s)
+@@ -1130,16 +1183,22 @@ int ssl3_send_server_hello(SSL *s)
  	unsigned char *buf;
  	unsigned char *p,*d;
  	int i,sl;
@@ -133,10 +131,10 @@
  		/* Do the message type and length last */
  		d=p= &(buf[4]);
  
-diff -upr openssl-SNAP-20071101.orig/ssl/ssl.h openssl-SNAP-20071101/ssl/ssl.h
---- openssl-SNAP-20071101.orig/ssl/ssl.h	2007-10-26 17:01:28.000000000 -0700
-+++ openssl-SNAP-20071101/ssl/ssl.h	2007-11-01 19:20:47.000000000 -0700
-@@ -353,6 +353,7 @@ extern "C" {
+diff -upr openssl-SNAP-20080528.orig/ssl/ssl.h openssl-SNAP-20080528/ssl/ssl.h
+--- openssl-SNAP-20080528.orig/ssl/ssl.h	2008-05-26 15:00:37.000000000 +0300
++++ openssl-SNAP-20080528/ssl/ssl.h	2008-05-29 10:49:25.000000000 +0300
+@@ -354,6 +354,7 @@ extern "C" {
   * 'struct ssl_st *' function parameters used to prototype callbacks
   * in SSL_CTX. */
  typedef struct ssl_st *ssl_crock_st;
@@ -144,7 +142,7 @@
  
  /* used to hold info on the particular ciphers used */
  typedef struct ssl_cipher_st
-@@ -379,6 +380,8 @@ DECLARE_STACK_OF(SSL_CIPHER)
+@@ -380,6 +381,8 @@ DECLARE_STACK_OF(SSL_CIPHER)
  typedef struct ssl_st SSL;
  typedef struct ssl_ctx_st SSL_CTX;
  
@@ -153,7 +151,7 @@
  /* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */
  typedef struct ssl_method_st
  	{
-@@ -1121,6 +1124,13 @@ struct ssl_st
+@@ -1128,6 +1131,13 @@ struct ssl_st
  	void *tlsext_opaque_prf_input;
  	size_t tlsext_opaque_prf_input_len;
  
@@ -167,7 +165,7 @@
  	SSL_CTX * initial_ctx; /* initial ctx, used to store sessions */
  #define session_ctx initial_ctx
  #else
-@@ -1721,6 +1731,12 @@ void *SSL_COMP_get_compression_methods(v
+@@ -1729,6 +1739,12 @@ void *SSL_COMP_get_compression_methods(v
  int SSL_COMP_add_compression_method(int id,void *cm);
  #endif
  
@@ -180,7 +178,7 @@
  /* BEGIN ERROR CODES */
  /* The following lines are auto generated by the script mkerr.pl. Any changes
   * made after this point may be overwritten when the script is next run.
-@@ -1920,6 +1936,7 @@ void ERR_load_SSL_strings(void);
+@@ -1928,6 +1944,7 @@ void ERR_load_SSL_strings(void);
  #define SSL_F_TLS1_PRF					 284
  #define SSL_F_TLS1_SETUP_KEY_BLOCK			 211
  #define SSL_F_WRITE_PENDING				 212
@@ -188,9 +186,9 @@
  
  /* Reason codes. */
  #define SSL_R_APP_DATA_IN_HANDSHAKE			 100
-diff -upr openssl-SNAP-20071101.orig/ssl/ssl_err.c openssl-SNAP-20071101/ssl/ssl_err.c
---- openssl-SNAP-20071101.orig/ssl/ssl_err.c	2007-10-26 17:01:29.000000000 -0700
-+++ openssl-SNAP-20071101/ssl/ssl_err.c	2007-11-01 19:19:43.000000000 -0700
+diff -upr openssl-SNAP-20080528.orig/ssl/ssl_err.c openssl-SNAP-20080528/ssl/ssl_err.c
+--- openssl-SNAP-20080528.orig/ssl/ssl_err.c	2007-10-27 03:01:29.000000000 +0300
++++ openssl-SNAP-20080528/ssl/ssl_err.c	2008-05-29 10:49:25.000000000 +0300
 @@ -260,6 +260,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
  {ERR_FUNC(SSL_F_TLS1_PRF),	"tls1_prf"},
  {ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK),	"TLS1_SETUP_KEY_BLOCK"},
@@ -199,9 +197,9 @@
  {0,NULL}
  	};
  
-diff -upr openssl-SNAP-20071101.orig/ssl/ssl_sess.c openssl-SNAP-20071101/ssl/ssl_sess.c
---- openssl-SNAP-20071101.orig/ssl/ssl_sess.c	2007-10-17 11:00:45.000000000 -0700
-+++ openssl-SNAP-20071101/ssl/ssl_sess.c	2007-11-01 19:19:43.000000000 -0700
+diff -upr openssl-SNAP-20080528.orig/ssl/ssl_sess.c openssl-SNAP-20080528/ssl/ssl_sess.c
+--- openssl-SNAP-20080528.orig/ssl/ssl_sess.c	2008-05-26 15:00:37.000000000 +0300
++++ openssl-SNAP-20080528/ssl/ssl_sess.c	2008-05-29 10:49:25.000000000 +0300
 @@ -831,6 +831,52 @@ long SSL_CTX_get_timeout(const SSL_CTX *
  	return(s->session_timeout);
  	}
@@ -255,9 +253,9 @@
  typedef struct timeout_param_st
  	{
  	SSL_CTX *ctx;
-diff -upr openssl-SNAP-20071101.orig/ssl/t1_lib.c openssl-SNAP-20071101/ssl/t1_lib.c
---- openssl-SNAP-20071101.orig/ssl/t1_lib.c	2007-10-26 06:00:29.000000000 -0700
-+++ openssl-SNAP-20071101/ssl/t1_lib.c	2007-11-01 19:19:43.000000000 -0700
+diff -upr openssl-SNAP-20080528.orig/ssl/t1_lib.c openssl-SNAP-20080528/ssl/t1_lib.c
+--- openssl-SNAP-20080528.orig/ssl/t1_lib.c	2008-04-30 20:00:39.000000000 +0300
++++ openssl-SNAP-20080528/ssl/t1_lib.c	2008-05-29 10:49:25.000000000 +0300
 @@ -154,6 +154,12 @@ int tls1_new(SSL *s)
  
  void tls1_free(SSL *s)
@@ -271,7 +269,7 @@
  	ssl3_free(s);
  	}
  
-@@ -355,8 +361,24 @@ unsigned char *ssl_add_clienthello_tlsex
+@@ -357,8 +363,24 @@ unsigned char *ssl_add_clienthello_tlsex
  		int ticklen;
  		if (s->session && s->session->tlsext_tick)
  			ticklen = s->session->tlsext_ticklen;
@@ -296,7 +294,7 @@
  		/* Check for enough room 2 for extension type, 2 for len
   		 * rest for ticket
    		 */
-@@ -369,6 +391,7 @@ unsigned char *ssl_add_clienthello_tlsex
+@@ -371,6 +393,7 @@ unsigned char *ssl_add_clienthello_tlsex
  			ret += ticklen;
  			}
  		}
@@ -304,7 +302,7 @@
  
  #ifdef TLSEXT_TYPE_opaque_prf_input
  	if (s->s3->client_opaque_prf_input != NULL)
-@@ -1422,6 +1445,8 @@ int tls1_process_ticket(SSL *s, unsigned
+@@ -1427,6 +1450,8 @@ int tls1_process_ticket(SSL *s, unsigned
  				s->tlsext_ticket_expected = 1;
  				return 0;	/* Cache miss */
  				}
@@ -313,10 +311,10 @@
  			return tls_decrypt_ticket(s, p, size, session_id, len,
  									ret);
  			}
-diff -upr openssl-SNAP-20071101.orig/ssl/tls1.h openssl-SNAP-20071101/ssl/tls1.h
---- openssl-SNAP-20071101.orig/ssl/tls1.h	2007-09-26 15:01:39.000000000 -0700
-+++ openssl-SNAP-20071101/ssl/tls1.h	2007-11-01 19:19:43.000000000 -0700
-@@ -509,6 +509,14 @@ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TLSEXT_OPA
+diff -upr openssl-SNAP-20080528.orig/ssl/tls1.h openssl-SNAP-20080528/ssl/tls1.h
+--- openssl-SNAP-20080528.orig/ssl/tls1.h	2008-04-30 20:00:39.000000000 +0300
++++ openssl-SNAP-20080528/ssl/tls1.h	2008-05-29 10:49:25.000000000 +0300
+@@ -512,6 +512,14 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_T
  #define TLS_MD_MASTER_SECRET_CONST    "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74"  /*master secret*/
  #endif
  
@@ -331,9 +329,9 @@
  #ifdef  __cplusplus
  }
  #endif
-diff -upr openssl-SNAP-20071101.orig/util/ssleay.num openssl-SNAP-20071101/util/ssleay.num
---- openssl-SNAP-20071101.orig/util/ssleay.num	2007-08-31 06:03:14.000000000 -0700
-+++ openssl-SNAP-20071101/util/ssleay.num	2007-11-01 19:19:43.000000000 -0700
+diff -upr openssl-SNAP-20080528.orig/util/ssleay.num openssl-SNAP-20080528/util/ssleay.num
+--- openssl-SNAP-20080528.orig/util/ssleay.num	2007-08-31 16:03:14.000000000 +0300
++++ openssl-SNAP-20080528/util/ssleay.num	2008-05-29 10:49:25.000000000 +0300
 @@ -253,3 +253,5 @@ PEM_write_bio_SSL_SESSION               
  PEM_read_SSL_SESSION                    302	EXIST:!WIN16:FUNCTION:
  PEM_read_bio_SSL_SESSION                303	EXIST::FUNCTION:

Modified: wpasupplicant/trunk/src/common/ieee802_11_defs.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/common/ieee802_11_defs.h?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/common/ieee802_11_defs.h (original)
+++ wpasupplicant/trunk/src/common/ieee802_11_defs.h Sat Jun 14 00:40:26 2008
@@ -112,9 +112,9 @@
 #define WLAN_STATUS_PWR_CAPABILITY_NOT_VALID 23
 #define WLAN_STATUS_SUPPORTED_CHANNEL_NOT_VALID 24
 /* 802.11g */
-#define WLAN_STATUS_ASSOC_DENOED_NO_SHORT_SLOT_TIME 25
-#define WLAN_STATUS_ASSOC_DENOED_NO_ER_PBCC 26
-#define WLAN_STATUS_ASSOC_DENOED_NO_DSSS_OFDM 27
+#define WLAN_STATUS_ASSOC_DENIED_NO_SHORT_SLOT_TIME 25
+#define WLAN_STATUS_ASSOC_DENIED_NO_ER_PBCC 26
+#define WLAN_STATUS_ASSOC_DENIED_NO_DSSS_OFDM 27
 /* IEEE 802.11i */
 #define WLAN_STATUS_INVALID_IE 40
 #define WLAN_STATUS_GROUP_CIPHER_NOT_VALID 41
@@ -123,6 +123,11 @@
 #define WLAN_STATUS_UNSUPPORTED_RSN_IE_VERSION 44
 #define WLAN_STATUS_INVALID_RSN_IE_CAPAB 45
 #define WLAN_STATUS_CIPHER_REJECTED_PER_POLICY 46
+#define WLAN_STATUS_TS_NOT_CREATED 47
+#define WLAN_STATUS_DIRECT_LINK_NOT_ALLOWED 48
+#define WLAN_STATUS_DEST_STA_NOT_PRESENT 49
+#define WLAN_STATUS_DEST_STA_NOT_QOS_STA 50
+#define WLAN_STATUS_ASSOC_DENIED_LISTEN_INT_TOO_LARGE 51
 /* IEEE 802.11r */
 #define WLAN_STATUS_INVALID_FT_ACTION_FRAME_COUNT 52
 #define WLAN_STATUS_EXPECTED_RESOURCE_REQ_FT 53

Modified: wpasupplicant/trunk/src/common/wpa_common.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/common/wpa_common.h?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/common/wpa_common.h (original)
+++ wpasupplicant/trunk/src/common/wpa_common.h Sat Jun 14 00:40:26 2008
@@ -87,8 +87,8 @@
 
 #define WPA_OUI_TYPE RSN_SELECTOR(0x00, 0x50, 0xf2, 1)
 
-#define RSN_SELECTOR_PUT(a, val) WPA_PUT_BE32((a), (val))
-#define RSN_SELECTOR_GET(a) WPA_GET_BE32((a))
+#define RSN_SELECTOR_PUT(a, val) WPA_PUT_BE32((u8 *) (a), (val))
+#define RSN_SELECTOR_GET(a) WPA_GET_BE32((const u8 *) (a))
 
 #define RSN_NUM_REPLAY_COUNTERS_1 0
 #define RSN_NUM_REPLAY_COUNTERS_2 1
@@ -188,8 +188,7 @@
 struct wpa_ie_hdr {
 	u8 elem_id;
 	u8 len;
-	u8 oui[3];
-	u8 oui_type;
+	u8 oui[4]; /* 24-bit OUI followed by 8-bit OUI type */
 	u8 version[2]; /* little endian */
 } STRUCT_PACKED;
 

Modified: wpasupplicant/trunk/src/crypto/crypto_internal.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/crypto/crypto_internal.c?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/crypto/crypto_internal.c (original)
+++ wpasupplicant/trunk/src/crypto/crypto_internal.c Sat Jun 14 00:40:26 2008
@@ -22,6 +22,7 @@
 #include "aes.h"
 #include "tls/rsa.h"
 #include "tls/bignum.h"
+#include "tls/asn1.h"
 
 
 #ifdef EAP_TLS_FUNCS
@@ -434,9 +435,122 @@
 }
 
 
+static struct crypto_private_key *
+crypto_pkcs8_key_import(const u8 *buf, size_t len)
+{
+	struct asn1_hdr hdr;
+	const u8 *pos, *end;
+	struct bignum *zero;
+	struct asn1_oid oid;
+	char obuf[80];
+
+	/* PKCS #8, Chapter 6 */
+
+	/* PrivateKeyInfo ::= SEQUENCE */
+	if (asn1_get_next(buf, len, &hdr) < 0 ||
+	    hdr.class != ASN1_CLASS_UNIVERSAL ||
+	    hdr.tag != ASN1_TAG_SEQUENCE) {
+		wpa_printf(MSG_DEBUG, "PKCS #8: Does not start with PKCS #8 "
+			   "header (SEQUENCE); assume PKCS #8 not used");
+		return NULL;
+	}
+	pos = hdr.payload;
+	end = pos + hdr.length;
+
+	/* version Version (Version ::= INTEGER) */
+	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+	    hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) {
+		wpa_printf(MSG_DEBUG, "PKCS #8: Expected INTEGER - found "
+			   "class %d tag 0x%x; assume PKCS #8 not used",
+			   hdr.class, hdr.tag);
+		return NULL;
+	}
+
+	zero = bignum_init();
+	if (zero == NULL)
+		return NULL;
+
+	if (bignum_set_unsigned_bin(zero, hdr.payload, hdr.length) < 0) {
+		wpa_printf(MSG_DEBUG, "PKCS #8: Failed to parse INTEGER");
+		bignum_deinit(zero);
+		return NULL;
+	}
+	pos = hdr.payload + hdr.length;
+
+	if (bignum_cmp_d(zero, 0) != 0) {
+		wpa_printf(MSG_DEBUG, "PKCS #8: Expected zero INTEGER in the "
+			   "beginning of private key; not found; assume "
+			   "PKCS #8 not used");
+		bignum_deinit(zero);
+		return NULL;
+	}
+	bignum_deinit(zero);
+
+	/* privateKeyAlgorithm PrivateKeyAlgorithmIdentifier
+	 * (PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier) */
+	if (asn1_get_next(pos, len, &hdr) < 0 ||
+	    hdr.class != ASN1_CLASS_UNIVERSAL ||
+	    hdr.tag != ASN1_TAG_SEQUENCE) {
+		wpa_printf(MSG_DEBUG, "PKCS #8: Expected SEQUENCE "
+			   "(AlgorithmIdentifier) - found class %d tag 0x%x; "
+			   "assume PKCS #8 not used",
+			   hdr.class, hdr.tag);
+		return NULL;
+	}
+
+	if (asn1_get_oid(hdr.payload, hdr.length, &oid, &pos)) {
+		wpa_printf(MSG_DEBUG, "PKCS #8: Failed to parse OID "
+			   "(algorithm); assume PKCS #8 not used");
+		return NULL;
+	}
+
+	asn1_oid_to_str(&oid, obuf, sizeof(obuf));
+	wpa_printf(MSG_DEBUG, "PKCS #8: algorithm=%s", obuf);
+
+	if (oid.len != 7 ||
+	    oid.oid[0] != 1 /* iso */ ||
+	    oid.oid[1] != 2 /* member-body */ ||
+	    oid.oid[2] != 840 /* us */ ||
+	    oid.oid[3] != 113549 /* rsadsi */ ||
+	    oid.oid[4] != 1 /* pkcs */ ||
+	    oid.oid[5] != 1 /* pkcs-1 */ ||
+	    oid.oid[6] != 1 /* rsaEncryption */) {
+		wpa_printf(MSG_DEBUG, "PKCS #8: Unsupported private key "
+			   "algorithm %s", obuf);
+		return NULL;
+	}
+
+	pos = hdr.payload + hdr.length;
+
+	/* privateKey PrivateKey (PrivateKey ::= OCTET STRING) */
+	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+	    hdr.class != ASN1_CLASS_UNIVERSAL ||
+	    hdr.tag != ASN1_TAG_OCTETSTRING) {
+		wpa_printf(MSG_DEBUG, "PKCS #8: Expected OCTETSTRING "
+			   "(privateKey) - found class %d tag 0x%x",
+			   hdr.class, hdr.tag);
+		return NULL;
+	}
+	wpa_printf(MSG_DEBUG, "PKCS #8: Try to parse RSAPrivateKey");
+
+	return (struct crypto_private_key *)
+		crypto_rsa_import_private_key(hdr.payload, hdr.length);
+}
+
+
 struct crypto_private_key * crypto_private_key_import(const u8 *key,
 						      size_t len)
 {
+	struct crypto_private_key *res;
+
+	/* First, check for possible PKCS #8 encoding */
+	res = crypto_pkcs8_key_import(key, len);
+	if (res)
+		return res;
+
+	/* Not PKCS#8, so try to import PKCS #1 encoded RSA private key */
+	wpa_printf(MSG_DEBUG, "Trying to parse PKCS #1 encoded RSA private "
+		   "key");
 	return (struct crypto_private_key *)
 		crypto_rsa_import_private_key(key, len);
 }

Modified: wpasupplicant/trunk/src/crypto/sha1.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/crypto/sha1.c?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/crypto/sha1.c (original)
+++ wpasupplicant/trunk/src/crypto/sha1.c Sat Jun 14 00:40:26 2008
@@ -265,6 +265,10 @@
 	L_S1 = L_S2 = (secret_len + 1) / 2;
 	S1 = secret;
 	S2 = secret + L_S1;
+	if (secret_len & 1) {
+		/* The last byte of S1 will be shared with S2 */
+		S2--;
+	}
 
 	hmac_md5_vector(S1, L_S1, 2, &MD5_addr[1], &MD5_len[1], A_MD5);
 	hmac_sha1_vector(S2, L_S2, 2, &SHA1_addr[1], &SHA1_len[1], A_SHA1);

Modified: wpasupplicant/trunk/src/crypto/tls.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/crypto/tls.h?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/crypto/tls.h (original)
+++ wpasupplicant/trunk/src/crypto/tls.h Sat Jun 14 00:40:26 2008
@@ -63,7 +63,10 @@
  * @engine_id: engine id string (this is OpenSSL specific for now)
  * @ppin: pointer to the pin variable in the configuration
  * (this is OpenSSL specific for now)
- * @key_id: the private key's key id (this is OpenSSL specific for now)
+ * @key_id: the private key's id when using engine (this is OpenSSL
+ * specific for now)
+ * @cert_id: the certificate's id when using engine
+ * @ca_cert_id: the CA certificate's id when using engine
  * @tls_ia: Whether to enable TLS/IA (for EAP-TTLSv1)
  *
  * TLS connection parameters to be configured with tls_connection_set_params()
@@ -98,6 +101,8 @@
 	const char *engine_id;
 	const char *pin;
 	const char *key_id;
+	const char *cert_id;
+	const char *ca_cert_id;
 };
 
 

Modified: wpasupplicant/trunk/src/crypto/tls_openssl.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/crypto/tls_openssl.c?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/crypto/tls_openssl.c (original)
+++ wpasupplicant/trunk/src/crypto/tls_openssl.c Sat Jun 14 00:40:26 2008
@@ -777,7 +777,8 @@
 
 
 static int tls_engine_init(struct tls_connection *conn, const char *engine_id,
-			   const char *pin, const char *key_id)
+			   const char *pin, const char *key_id,
+			   const char *cert_id, const char *ca_cert_id)
 {
 #ifndef OPENSSL_NO_ENGINE
 	int ret = -1;
@@ -814,6 +815,7 @@
 			   ERR_error_string(ERR_get_error(), NULL));
 		goto err;
 	}
+	/* load private key first in-case PIN is required for cert */
 	conn->private_key = ENGINE_load_private_key(conn->engine,
 						    key_id, NULL, NULL);
 	if (!conn->private_key) {
@@ -823,6 +825,21 @@
 		ret = TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED;
 		goto err;
 	}
+
+	/* handle a certificate and/or CA certificate */
+	if (cert_id || ca_cert_id) {
+		const char *cmd_name = "LOAD_CERT_CTRL";
+
+		/* test if the engine supports a LOAD_CERT_CTRL */
+		if (!ENGINE_ctrl(conn->engine, ENGINE_CTRL_GET_CMD_FROM_NAME,
+				 0, (void *)cmd_name, NULL)) {
+			wpa_printf(MSG_ERROR, "ENGINE: engine does not support"
+				   " loading certificates");
+			ret = TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED;
+			goto err;
+		}
+	}
+
 	return 0;
 
 err:
@@ -877,6 +894,7 @@
 {
 	SSL_CTX *ssl = ssl_ctx;
 	struct tls_connection *conn;
+	long options;
 
 	conn = os_zalloc(sizeof(*conn));
 	if (conn == NULL)
@@ -890,9 +908,12 @@
 	}
 
 	SSL_set_app_data(conn->ssl, conn);
-	SSL_set_options(conn->ssl,
-			SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
-			SSL_OP_SINGLE_DH_USE);
+	options = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
+		SSL_OP_SINGLE_DH_USE;
+#ifdef SSL_OP_NO_COMPRESSION
+	options |= SSL_OP_NO_COMPRESSION;
+#endif /* SSL_OP_NO_COMPRESSION */
+	SSL_set_options(conn->ssl, options);
 
 	conn->ssl_in = BIO_new(BIO_s_mem());
 	if (!conn->ssl_in) {
@@ -1261,6 +1282,8 @@
 int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn,
 			      int verify_peer)
 {
+	static int counter = 0;
+
 	if (conn == NULL)
 		return -1;
 
@@ -1273,6 +1296,19 @@
 	}
 
 	SSL_set_accept_state(conn->ssl);
+
+	/*
+	 * Set session id context in order to avoid fatal errors when client
+	 * tries to resume a session. However, set the context to a unique
+	 * value in order to effectively disable session resumption for now
+	 * since not all areas of the server code are ready for it (e.g.,
+	 * EAP-TTLS needs special handling for Phase 2 after abbreviated TLS
+	 * handshake).
+	 */
+	counter++;
+	SSL_set_session_id_context(conn->ssl,
+				   (const unsigned char *) &counter,
+				   sizeof(counter));
 
 	return 0;
 }
@@ -1488,6 +1524,110 @@
 		   "p12/pfx blobs");
 	return -1;
 #endif  /* PKCS12_FUNCS */
+}
+
+
+#ifndef OPENSSL_NO_ENGINE
+static int tls_engine_get_cert(struct tls_connection *conn,
+			       const char *cert_id,
+			       X509 **cert)
+{
+	/* this runs after the private key is loaded so no PIN is required */
+	struct {
+		const char *cert_id;
+		X509 *cert;
+	} params;
+	params.cert_id = cert_id;
+	params.cert = NULL;
+
+	if (!ENGINE_ctrl_cmd(conn->engine, "LOAD_CERT_CTRL",
+			     0, &params, NULL, 1)) {
+		wpa_printf(MSG_ERROR, "ENGINE: cannot load client cert with id"
+			   " '%s' [%s]", cert_id,
+			   ERR_error_string(ERR_get_error(), NULL));
+		return TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED;
+	}
+	if (!params.cert) {
+		wpa_printf(MSG_ERROR, "ENGINE: did not properly cert with id"
+			   " '%s'", cert_id);
+		return TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED;
+	}
+	*cert = params.cert;
+	return 0;
+}
+#endif /* OPENSSL_NO_ENGINE */
+
+
+static int tls_connection_engine_client_cert(struct tls_connection *conn,
+					     const char *cert_id)
+{
+#ifndef OPENSSL_NO_ENGINE
+	X509 *cert;
+
+	if (tls_engine_get_cert(conn, cert_id, &cert))
+		return -1;
+
+	if (!SSL_use_certificate(conn->ssl, cert)) {
+		tls_show_errors(MSG_ERROR, __func__,
+				"SSL_use_certificate failed");
+                X509_free(cert);
+		return -1;
+	}
+	X509_free(cert);
+	wpa_printf(MSG_DEBUG, "ENGINE: SSL_use_certificate --> "
+		   "OK");
+	return 0;
+
+#else /* OPENSSL_NO_ENGINE */
+	return -1;
+#endif /* OPENSSL_NO_ENGINE */
+}
+
+
+static int tls_connection_engine_ca_cert(void *_ssl_ctx,
+					 struct tls_connection *conn,
+					 const char *ca_cert_id)
+{
+#ifndef OPENSSL_NO_ENGINE
+	X509 *cert;
+	SSL_CTX *ssl_ctx = _ssl_ctx;
+
+	if (tls_engine_get_cert(conn, ca_cert_id, &cert))
+		return -1;
+
+	/* start off the same as tls_connection_ca_cert */
+	X509_STORE_free(ssl_ctx->cert_store);
+	ssl_ctx->cert_store = X509_STORE_new();
+	if (ssl_ctx->cert_store == NULL) {
+		wpa_printf(MSG_DEBUG, "OpenSSL: %s - failed to allocate new "
+			   "certificate store", __func__);
+		X509_free(cert);
+		return -1;
+	}
+	if (!X509_STORE_add_cert(ssl_ctx->cert_store, cert)) {
+		unsigned long err = ERR_peek_error();
+		tls_show_errors(MSG_WARNING, __func__,
+				"Failed to add CA certificate from engine "
+				"to certificate store");
+		if (ERR_GET_LIB(err) == ERR_LIB_X509 &&
+		    ERR_GET_REASON(err) == X509_R_CERT_ALREADY_IN_HASH_TABLE) {
+			wpa_printf(MSG_DEBUG, "OpenSSL: %s - ignoring cert"
+				   " already in hash table error",
+				   __func__);
+		} else {
+			X509_free(cert);
+			return -1;
+		}
+	}
+	X509_free(cert);
+	wpa_printf(MSG_DEBUG, "OpenSSL: %s - added CA certificate from engine "
+		   "to certificate store", __func__);
+	SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb);
+	return 0;
+
+#else /* OPENSSL_NO_ENGINE */
+	return -1;
+#endif /* OPENSSL_NO_ENGINE */
 }
 
 
@@ -1976,8 +2116,11 @@
 {
 	int res;
 	u8 *out_data;
-	char buf[10];
-
+
+	/*
+	 * Give TLS handshake data from the client (if available) to OpenSSL
+	 * for processing.
+	 */
 	if (in_data &&
 	    BIO_write(conn->ssl_in, in_data, in_len) < 0) {
 		tls_show_errors(MSG_INFO, __func__,
@@ -1985,12 +2128,23 @@
 		return NULL;
 	}
 
-	res = SSL_read(conn->ssl, buf, sizeof(buf));
-	if (res >= 0) {
-		wpa_printf(MSG_DEBUG, "SSL: Unexpected data from SSL_read "
-			   "(res=%d)", res);
-	}
-
+	/* Initiate TLS handshake or continue the existing handshake */
+	res = SSL_accept(conn->ssl);
+	if (res != 1) {
+		int err = SSL_get_error(conn->ssl, res);
+		if (err == SSL_ERROR_WANT_READ)
+			wpa_printf(MSG_DEBUG, "SSL: SSL_accept - want "
+				   "more data");
+		else if (err == SSL_ERROR_WANT_WRITE)
+			wpa_printf(MSG_DEBUG, "SSL: SSL_accept - want to "
+				   "write");
+		else {
+			tls_show_errors(MSG_INFO, __func__, "SSL_accept");
+			return NULL;
+		}
+	}
+
+	/* Get the TLS handshake data to be sent to the client */
 	res = BIO_ctrl_pending(conn->ssl_out);
 	wpa_printf(MSG_DEBUG, "SSL: %d bytes pending from ssl_out", res);
 	out_data = os_malloc(res == 0 ? 1 : res);
@@ -2229,26 +2383,39 @@
 			   __func__, ERR_error_string(err, NULL));
 	}
 
+	if (params->engine) {
+		wpa_printf(MSG_DEBUG, "SSL: Initializing TLS engine");
+		ret = tls_engine_init(conn, params->engine_id, params->pin,
+				      params->key_id, params->cert_id,
+				      params->ca_cert_id);
+		if (ret)
+			return ret;
+	}
 	if (tls_connection_set_subject_match(conn,
 					     params->subject_match,
 					     params->altsubject_match))
 		return -1;
-	if (tls_connection_ca_cert(tls_ctx, conn, params->ca_cert,
-				   params->ca_cert_blob,
-				   params->ca_cert_blob_len,
-				   params->ca_path))
-		return -1;
-	if (tls_connection_client_cert(conn, params->client_cert,
-				       params->client_cert_blob,
-				       params->client_cert_blob_len))
-		return -1;
-
-	if (params->engine) {
-		wpa_printf(MSG_DEBUG, "SSL: Initializing TLS engine");
-		ret = tls_engine_init(conn, params->engine_id, params->pin,
-				      params->key_id);
-		if (ret)
-			return ret;
+
+	if (params->engine && params->ca_cert_id) {
+		if (tls_connection_engine_ca_cert(tls_ctx, conn,
+						  params->ca_cert_id))
+			return TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED;
+	} else if (tls_connection_ca_cert(tls_ctx, conn, params->ca_cert,
+					  params->ca_cert_blob,
+					  params->ca_cert_blob_len,
+					  params->ca_path))
+		return -1;
+
+	if (params->engine && params->cert_id) {
+		if (tls_connection_engine_client_cert(conn, params->cert_id))
+			return TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED;
+	} else if (tls_connection_client_cert(conn, params->client_cert,
+					      params->client_cert_blob,
+					      params->client_cert_blob_len))
+		return -1;
+
+	if (params->engine && params->key_id) {
+		wpa_printf(MSG_DEBUG, "TLS: Using private key from engine");
 		if (tls_connection_engine_private_key(conn))
 			return TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED;
 	} else if (tls_connection_private_key(tls_ctx, conn,

Modified: wpasupplicant/trunk/src/drivers/driver_hostap.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/drivers/driver_hostap.h?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/drivers/driver_hostap.h (original)
+++ wpasupplicant/trunk/src/drivers/driver_hostap.h Sat Jun 14 00:40:26 2008
@@ -84,9 +84,9 @@
 
 #define PRISM2_HOSTAPD_MAX_BUF_SIZE 1024
 #define PRISM2_HOSTAPD_RID_HDR_LEN \
-((int) (&((struct prism2_hostapd_param *) 0)->u.rid.data))
+((size_t) (&((struct prism2_hostapd_param *) 0)->u.rid.data))
 #define PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN \
-((int) (&((struct prism2_hostapd_param *) 0)->u.generic_elem.data))
+((size_t) (&((struct prism2_hostapd_param *) 0)->u.generic_elem.data))
 
 /* Maximum length for algorithm names (-1 for nul termination) used in ioctl()
  */

Modified: wpasupplicant/trunk/src/drivers/driver_ndis.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/drivers/driver_ndis.c?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/drivers/driver_ndis.c (original)
+++ wpasupplicant/trunk/src/drivers/driver_ndis.c Sat Jun 14 00:40:26 2008
@@ -1317,8 +1317,7 @@
 
 	if (wpa_driver_ndis_get_bssid(drv, bssid)) {
 		/* Disconnected */
-		if (os_memcmp(drv->bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN)
-		    != 0) {
+		if (!is_zero_ether_addr(drv->bssid)) {
 			os_memset(drv->bssid, 0, ETH_ALEN);
 			wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL);
 		}

Modified: wpasupplicant/trunk/src/drivers/driver_ralink.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/drivers/driver_ralink.c?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/drivers/driver_ralink.c (original)
+++ wpasupplicant/trunk/src/drivers/driver_ralink.c Sat Jun 14 00:40:26 2008
@@ -57,7 +57,7 @@
 	if (buf == NULL)
 		return -1;
 	os_memset(&iwr, 0, sizeof(iwr));
-	os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
+	os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
 	iwr.u.data.flags = oid;
 	iwr.u.data.flags |= OID_GET_SET_TOGGLE;
 
@@ -84,7 +84,7 @@
 	UCHAR enabled = 0;
 
 	os_memset(&iwr, 0, sizeof(iwr));
-	os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
+	os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
 	iwr.u.data.pointer = (UCHAR*) &enabled;
 	iwr.u.data.flags = RT_OID_NEW_DRIVER;
 
@@ -108,7 +108,7 @@
 	wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
 
 	os_memset(&iwr, 0, sizeof(iwr));
-	os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
+	os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
 
 	if (ioctl(drv->ioctl_sock, SIOCGIWAP, &iwr) < 0) {
 		perror("ioctl[SIOCGIWAP]");
@@ -145,7 +145,7 @@
 	wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
 
 	os_memset(&iwr, 0, sizeof(iwr));
-	os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
+	os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
 	iwr.u.essid.pointer = (caddr_t) ssid;
 	iwr.u.essid.length = 32;
 
@@ -236,7 +236,7 @@
 	buf->SsidLength = ssid_len;
 	os_memcpy(buf->Ssid, ssid, ssid_len);
 	os_memset(&iwr, 0, sizeof(iwr));
-	os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
+	os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
 
 	iwr.u.data.flags = OID_802_11_SSID;
 	iwr.u.data.flags |= OID_GET_SET_TOGGLE;
@@ -611,8 +611,10 @@
 					   "receive ReqIEs !!!");
 				drv->assoc_req_ies =
 					os_malloc(iwe->u.data.length);
-				if (drv->assoc_req_ies == NULL)
+				if (drv->assoc_req_ies == NULL) {
+					os_free(buf);
 					return;
+				}
 
 				drv->assoc_req_ies_len = iwe->u.data.length;
 				os_memcpy(drv->assoc_req_ies, custom,
@@ -625,6 +627,7 @@
 				if (drv->assoc_resp_ies == NULL) {
 					os_free(drv->assoc_req_ies);
 					drv->assoc_req_ies = NULL;
+					os_free(buf);
 					return;
 				}
 
@@ -637,7 +640,7 @@
 					   "receive ASSOCINFO_EVENT !!!");
 
 				assoc_info_buf =
-					os_malloc(drv->assoc_req_ies_len +
+					os_zalloc(drv->assoc_req_ies_len +
 						  drv->assoc_resp_ies_len + 1);
 
 				if (assoc_info_buf == NULL) {
@@ -649,18 +652,26 @@
 					return;
 				}
 
-				os_memcpy(assoc_info_buf, drv->assoc_req_ies,
-					  drv->assoc_req_ies_len);
+				if (drv->assoc_req_ies) {
+					os_memcpy(assoc_info_buf,
+						  drv->assoc_req_ies,
+						  drv->assoc_req_ies_len);
+				}
 				info_pos = assoc_info_buf +
 					drv->assoc_req_ies_len;
-				os_memcpy(info_pos, drv->assoc_resp_ies,
-					  drv->assoc_resp_ies_len);
+				if (drv->assoc_resp_ies) {
+					os_memcpy(info_pos,
+						  drv->assoc_resp_ies,
+						  drv->assoc_resp_ies_len);
+				}
 				assoc_info_buf[drv->assoc_req_ies_len +
 					       drv->assoc_resp_ies_len] = '\0';
 				wpa_driver_ralink_event_wireless_custom(
 					drv, ctx, assoc_info_buf);
 				os_free(drv->assoc_req_ies);
+				drv->assoc_req_ies = NULL;
 				os_free(drv->assoc_resp_ies);
+				drv->assoc_resp_ies = NULL;
 				os_free(assoc_info_buf);
 			} else if (iwe->u.data.flags == RT_DISASSOC_EVENT_FLAG)
 			{
@@ -836,7 +847,7 @@
 	UINT we_version_compiled = 0;
 
 	os_memset(&iwr, 0, sizeof(iwr));
-	os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
+	os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
 	iwr.u.data.pointer = (caddr_t) &we_version_compiled;
 	iwr.u.data.flags = RT_OID_WE_VERSION_COMPILED;
 
@@ -898,7 +909,7 @@
 		return NULL;
 	}
 	/* do it */
-	os_strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
+	os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
 
 	if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
 		perror(ifr.ifr_name);
@@ -912,7 +923,7 @@
 	drv->scanning_done = 1;
 	drv->ap_scan = 1; /* for now - let's assume ap_scan=1 is used */
 	drv->ctx = ctx;
-	os_strncpy(drv->ifname, ifname, sizeof(drv->ifname));
+	os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
 	drv->ioctl_sock = s;
 	drv->g_driver_down = 0;
 
@@ -1034,7 +1045,7 @@
 	/* wpa_driver_ralink_set_ssid(drv, ssid, ssid_len); */
 
 	os_memset(&iwr, 0, sizeof(iwr));
-	os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
+	os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
 
 	if (ioctl(drv->ioctl_sock, SIOCSIWSCAN, &iwr) < 0) {
 		perror("ioctl[SIOCSIWSCAN]");
@@ -1083,7 +1094,7 @@
 	wsr = (NDIS_802_11_BSSID_LIST_EX *) buf;
 
 	wsr->NumberOfItems = 0;
-	os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
+	os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
 	iwr.u.data.pointer = (void *) buf;
 	iwr.u.data.flags = OID_802_11_BSSID_LIST;
 

Modified: wpasupplicant/trunk/src/drivers/driver_wext.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/drivers/driver_wext.c?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/drivers/driver_wext.c (original)
+++ wpasupplicant/trunk/src/drivers/driver_wext.c Sat Jun 14 00:40:26 2008
@@ -149,32 +149,6 @@
 #endif /* CONFIG_CLIENT_MLME */
 
 
-struct wpa_driver_wext_data {
-	void *ctx;
-	int event_sock;
-	int ioctl_sock;
-	int mlme_sock;
-	char ifname[IFNAMSIZ + 1];
-	int ifindex;
-	int ifindex2;
-	u8 *assoc_req_ies;
-	size_t assoc_req_ies_len;
-	u8 *assoc_resp_ies;
-	size_t assoc_resp_ies_len;
-	struct wpa_driver_capa capa;
-	int has_capability;
-	int we_version_compiled;
-
-	/* for set_auth_alg fallback */
-	int use_crypt;
-	int auth_alg_fallback;
-
-	int operstate;
-
-	char mlmedev[IFNAMSIZ + 1];
-
-	int scan_complete_events;
-};
 
 
 static int wpa_driver_wext_flush_pmkid(void *priv);
@@ -239,8 +213,8 @@
 }
 
 
-static int wpa_driver_wext_set_auth_param(struct wpa_driver_wext_data *drv,
-					  int idx, u32 value)
+int wpa_driver_wext_set_auth_param(struct wpa_driver_wext_data *drv,
+				   int idx, u32 value)
 {
 	struct iwreq iwr;
 	int ret = 0;
@@ -251,9 +225,11 @@
 	iwr.u.param.value = value;
 
 	if (ioctl(drv->ioctl_sock, SIOCSIWAUTH, &iwr) < 0) {
-		perror("ioctl[SIOCSIWAUTH]");
-		fprintf(stderr, "WEXT auth param %d value 0x%x - ",
-			idx, value);
+		if (errno != EOPNOTSUPP) {
+			wpa_printf(MSG_DEBUG, "WEXT: SIOCSIWAUTH(param %d "
+				   "value 0x%x) failed: %s)",
+				   idx, value, strerror(errno));
+		}
 		ret = errno == EOPNOTSUPP ? -2 : -1;
 	}
 
@@ -655,9 +631,8 @@
 			wpa_printf(MSG_DEBUG, "Wireless event: new AP: "
 				   MACSTR,
 				   MAC2STR((u8 *) iwe->u.ap_addr.sa_data));
-			if (os_memcmp(iwe->u.ap_addr.sa_data,
-				      "\x00\x00\x00\x00\x00\x00", ETH_ALEN) ==
-			    0 ||
+			if (is_zero_ether_addr(
+				    (const u8 *) iwe->u.ap_addr.sa_data) ||
 			    os_memcmp(iwe->u.ap_addr.sa_data,
 				      "\x44\x44\x44\x44\x44\x44", ETH_ALEN) ==
 			    0) {
@@ -760,7 +735,7 @@
 		   (ifi->ifi_flags & IFF_UP) ? "[UP]" : "",
 		   (ifi->ifi_flags & IFF_RUNNING) ? "[RUNNING]" : "",
 		   (ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "",
-		   (ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT" : "");
+		   (ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : "");
 	/*
 	 * Some drivers send the association event before the operup event--in
 	 * this case, lifting operstate in wpa_driver_wext_set_operstate()
@@ -1318,8 +1293,15 @@
 		/*
 		 * Some drivers do not report frequency, but a channel.
 		 * Try to map this to frequency by assuming they are using
-		 * IEEE 802.11b/g.
+		 * IEEE 802.11b/g.  But don't overwrite a previously parsed
+		 * frequency if the driver sends both frequency and channel,
+		 * since the driver may be sending an A-band channel that we
+		 * don't handle here.
 		 */
+
+		if (res->res.freq)
+			return;
+
 		if (iwe->u.freq.m >= 1 && iwe->u.freq.m <= 13) {
 			res->res.freq = 2407 + 5 * iwe->u.freq.m;
 			return;
@@ -1975,7 +1957,7 @@
 }
 
 
-static int wpa_driver_wext_cipher2wext(int cipher)
+int wpa_driver_wext_cipher2wext(int cipher)
 {
 	switch (cipher) {
 	case CIPHER_NONE:
@@ -1994,7 +1976,7 @@
 }
 
 
-static int wpa_driver_wext_keymgmt2wext(int keymgmt)
+int wpa_driver_wext_keymgmt2wext(int keymgmt)
 {
 	switch (keymgmt) {
 	case KEY_MGMT_802_1X:
@@ -2052,9 +2034,8 @@
 }
 
 
-static int
-wpa_driver_wext_associate(void *priv,
-			  struct wpa_driver_associate_params *params)
+int wpa_driver_wext_associate(void *priv,
+			      struct wpa_driver_associate_params *params)
 {
 	struct wpa_driver_wext_data *drv = priv;
 	int ret = 0;
@@ -2170,17 +2151,54 @@
 {
 	struct wpa_driver_wext_data *drv = priv;
 	struct iwreq iwr;
-	int ret = 0;
+	int ret = -1, flags;
+	unsigned int new_mode = mode ? IW_MODE_ADHOC : IW_MODE_INFRA;
 
 	os_memset(&iwr, 0, sizeof(iwr));
 	os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
-	iwr.u.mode = mode ? IW_MODE_ADHOC : IW_MODE_INFRA;
-
-	if (ioctl(drv->ioctl_sock, SIOCSIWMODE, &iwr) < 0) {
+	iwr.u.mode = new_mode;
+	if (ioctl(drv->ioctl_sock, SIOCSIWMODE, &iwr) == 0) {
+		ret = 0;
+		goto done;
+	}
+
+	if (errno != EBUSY) {
 		perror("ioctl[SIOCSIWMODE]");
-		ret = -1;
-	}
-
+		goto done;
+	}
+
+	/* mac80211 doesn't allow mode changes while the device is up, so if
+	 * the device isn't in the mode we're about to change to, take device
+	 * down, try to set the mode again, and bring it back up.
+	 */
+	if (ioctl(drv->ioctl_sock, SIOCGIWMODE, &iwr) < 0) {
+		perror("ioctl[SIOCGIWMODE]");
+		goto done;
+	}
+
+	if (iwr.u.mode == new_mode) {
+		ret = 0;
+		goto done;
+	}
+
+	if (wpa_driver_wext_get_ifflags(drv, &flags) == 0) {
+		(void) wpa_driver_wext_set_ifflags(drv, flags & ~IFF_UP);
+
+		/* Try to set the mode again while the interface is down */
+		iwr.u.mode = new_mode;
+		if (ioctl(drv->ioctl_sock, SIOCSIWMODE, &iwr) < 0)
+			perror("ioctl[SIOCSIWMODE]");
+		else
+			ret = 0;
+
+		/* Ignore return value of get_ifflags to ensure that the device
+		 * is always up like it was before this function was called.
+		 */
+		(void) wpa_driver_wext_get_ifflags(drv, &flags);
+		(void) wpa_driver_wext_set_ifflags(drv, flags | IFF_UP);
+	}
+
+done:
 	return ret;
 }
 
@@ -2237,7 +2255,7 @@
 }
 
 
-static int wpa_driver_wext_get_capa(void *priv, struct wpa_driver_capa *capa)
+int wpa_driver_wext_get_capa(void *priv, struct wpa_driver_capa *capa)
 {
 	struct wpa_driver_wext_data *drv = priv;
 	if (!drv->has_capability)

Modified: wpasupplicant/trunk/src/drivers/driver_wext.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/drivers/driver_wext.h?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/drivers/driver_wext.h (original)
+++ wpasupplicant/trunk/src/drivers/driver_wext.h Sat Jun 14 00:40:26 2008
@@ -15,7 +15,34 @@
 #ifndef DRIVER_WEXT_H
 #define DRIVER_WEXT_H
 
-struct wpa_driver_wext_data;
+#include <net/if.h>
+
+struct wpa_driver_wext_data {
+	void *ctx;
+	int event_sock;
+	int ioctl_sock;
+	int mlme_sock;
+	char ifname[IFNAMSIZ + 1];
+	int ifindex;
+	int ifindex2;
+	u8 *assoc_req_ies;
+	size_t assoc_req_ies_len;
+	u8 *assoc_resp_ies;
+	size_t assoc_resp_ies_len;
+	struct wpa_driver_capa capa;
+	int has_capability;
+	int we_version_compiled;
+
+	/* for set_auth_alg fallback */
+	int use_crypt;
+	int auth_alg_fallback;
+
+	int operstate;
+
+	char mlmedev[IFNAMSIZ + 1];
+
+	int scan_complete_events;
+};
 
 int wpa_driver_wext_get_ifflags(struct wpa_driver_wext_data *drv, int *flags);
 int wpa_driver_wext_set_ifflags(struct wpa_driver_wext_data *drv, int flags);
@@ -43,4 +70,12 @@
 int wpa_driver_wext_set_operstate(void *priv, int state);
 int wpa_driver_wext_get_version(struct wpa_driver_wext_data *drv);
 
+int wpa_driver_wext_associate(void *priv,
+			      struct wpa_driver_associate_params *params);
+int wpa_driver_wext_get_capa(void *priv, struct wpa_driver_capa *capa);
+int wpa_driver_wext_set_auth_param(struct wpa_driver_wext_data *drv,
+				   int idx, u32 value);
+int wpa_driver_wext_cipher2wext(int cipher);
+int wpa_driver_wext_keymgmt2wext(int keymgmt);
+
 #endif /* DRIVER_WEXT_H */

Modified: wpasupplicant/trunk/src/drivers/drivers.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/drivers/drivers.c?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/drivers/drivers.c (original)
+++ wpasupplicant/trunk/src/drivers/drivers.c Sat Jun 14 00:40:26 2008
@@ -18,6 +18,9 @@
 #ifdef CONFIG_DRIVER_WEXT
 extern struct wpa_driver_ops wpa_driver_wext_ops; /* driver_wext.c */
 #endif /* CONFIG_DRIVER_WEXT */
+#ifdef CONFIG_DRIVER_NL80211
+extern struct wpa_driver_ops wpa_driver_nl80211_ops; /* driver_nl80211.c */
+#endif /* CONFIG_DRIVER_NL80211 */
 #ifdef CONFIG_DRIVER_HOSTAP
 extern struct wpa_driver_ops wpa_driver_hostap_ops; /* driver_hostap.c */
 #endif /* CONFIG_DRIVER_HOSTAP */
@@ -61,6 +64,9 @@
 #ifdef CONFIG_DRIVER_OSX
 extern struct wpa_driver_ops wpa_driver_osx_ops; /* driver_osx.m */
 #endif /* CONFIG_DRIVER_OSX */
+#ifdef CONFIG_DRIVER_PS3
+extern struct wpa_driver_ops wpa_driver_ps3_ops; /* driver_ps3.c */
+#endif /* CONFIG_DRIVER_PS3 */
 #ifdef CONFIG_DRIVER_IPHONE
 extern struct wpa_driver_ops wpa_driver_iphone_ops; /* driver_iphone.m */
 #endif /* CONFIG_DRIVER_IPHONE */
@@ -71,6 +77,9 @@
 #ifdef CONFIG_DRIVER_WEXT
 	&wpa_driver_wext_ops,
 #endif /* CONFIG_DRIVER_WEXT */
+#ifdef CONFIG_DRIVER_NL80211
+	&wpa_driver_nl80211_ops,
+#endif /* CONFIG_DRIVER_NL80211 */
 #ifdef CONFIG_DRIVER_HOSTAP
 	&wpa_driver_hostap_ops,
 #endif /* CONFIG_DRIVER_HOSTAP */
@@ -113,6 +122,9 @@
 #ifdef CONFIG_DRIVER_OSX
 	&wpa_driver_osx_ops,
 #endif /* CONFIG_DRIVER_OSX */
+#ifdef CONFIG_DRIVER_PS3
+	&wpa_driver_ps3_ops,
+#endif /* CONFIG_DRIVER_PS3 */
 #ifdef CONFIG_DRIVER_IPHONE
 	&wpa_driver_iphone_ops,
 #endif /* CONFIG_DRIVER_IPHONE */

Modified: wpasupplicant/trunk/src/eap_common/eap_defs.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/eap_common/eap_defs.h?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/eap_common/eap_defs.h (original)
+++ wpasupplicant/trunk/src/eap_common/eap_defs.h Sat Jun 14 00:40:26 2008
@@ -75,6 +75,7 @@
 /* SMI Network Management Private Enterprise Code for vendor specific types */
 enum {
 	EAP_VENDOR_IETF = 0,
+	EAP_VENDOR_MICROSOFT = 0x000137 /* Microsoft */,
 	EAP_VENDOR_WFA = 0x00372A /* Wi-Fi Alliance */
 };
 

Modified: wpasupplicant/trunk/src/eap_common/eap_fast_common.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/eap_common/eap_fast_common.h?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/eap_common/eap_fast_common.h (original)
+++ wpasupplicant/trunk/src/eap_common/eap_fast_common.h Sat Jun 14 00:40:26 2008
@@ -1,6 +1,6 @@
 /*
  * EAP-FAST definitions (RFC 4851)
- * Copyright (c) 2004-2007, Jouni Malinen <j at w1.fi>
+ * Copyright (c) 2004-2008, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -19,6 +19,7 @@
 #define EAP_FAST_KEY_LEN 64
 #define EAP_FAST_SIMCK_LEN 40
 #define EAP_FAST_SKS_LEN 40
+#define EAP_FAST_CMK_LEN 20
 
 #define TLS_EXT_PAC_OPAQUE 35
 
@@ -82,4 +83,35 @@
 	u8 client_challenge[16]; /* MSCHAPv2 ClientChallenge */
 };
 
+
+struct wpabuf;
+struct tls_connection;
+
+struct eap_fast_tlv_parse {
+	u8 *eap_payload_tlv;
+	size_t eap_payload_tlv_len;
+	struct eap_tlv_crypto_binding_tlv *crypto_binding;
+	size_t crypto_binding_len;
+	int iresult;
+	int result;
+	int request_action;
+	u8 *pac;
+	size_t pac_len;
+};
+
+void eap_fast_put_tlv_hdr(struct wpabuf *buf, u16 type, u16 len);
+void eap_fast_put_tlv(struct wpabuf *buf, u16 type, const void *data,
+		      u16 len);
+void eap_fast_put_tlv_buf(struct wpabuf *buf, u16 type,
+			  const struct wpabuf *data);
+struct wpabuf * eap_fast_tlv_eap_payload(struct wpabuf *buf);
+void eap_fast_derive_master_secret(const u8 *pac_key, const u8 *server_random,
+				   const u8 *client_random, u8 *master_secret);
+u8 * eap_fast_derive_key(void *ssl_ctx, struct tls_connection *conn,
+			 const char *label, size_t len);
+void eap_fast_derive_eap_msk(const u8 *simck, u8 *msk);
+void eap_fast_derive_eap_emsk(const u8 *simck, u8 *emsk);
+int eap_fast_parse_tlv(struct eap_fast_tlv_parse *tlv,
+		       int tlv_type, u8 *pos, int len);
+
 #endif /* EAP_FAST_H */

Modified: wpasupplicant/trunk/src/eap_common/eap_tlv_common.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/eap_common/eap_tlv_common.h?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/eap_common/eap_tlv_common.h (original)
+++ wpasupplicant/trunk/src/eap_common/eap_tlv_common.h Sat Jun 14 00:40:26 2008
@@ -73,7 +73,7 @@
 } STRUCT_PACKED;
 
 /* RFC 4851, Section 4.2.8 - Crypto-Binding TLV */
-struct eap_tlv_crypto_binding__tlv {
+struct eap_tlv_crypto_binding_tlv {
 	be16 tlv_type;
 	be16 length;
 	u8 reserved;

Modified: wpasupplicant/trunk/src/eap_peer/eap_config.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/eap_peer/eap_config.h?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/eap_peer/eap_config.h (original)
+++ wpasupplicant/trunk/src/eap_peer/eap_config.h Sat Jun 14 00:40:26 2008
@@ -350,6 +350,12 @@
 	 * fast_pac_format=binary option can be used to select binary format
 	 * for storing PAC entires in order to save some space (the default
 	 * text format uses about 2.5 times the size of minimal binary format).
+	 *
+	 * crypto_binding option can be used to control PEAPv0 cryptobinding
+	 * behavior:
+	 * 0 = do not use cryptobinding
+	 * 1 = use cryptobinding if server supports it (default)
+	 * 2 = require cryptobinding
 	 */
 	char *phase1;
 
@@ -409,6 +415,44 @@
 	 * using a smartcard.
 	 */
 	char *key_id;
+
+	/**
+	 * cert_id - Cert ID for OpenSSL engine
+	 *
+	 * This is used if the certificate operations for EAP-TLS are performed
+	 * using a smartcard.
+	 */
+	char *cert_id;
+
+	/**
+	 * ca_cert_id - CA Cert ID for OpenSSL engine
+	 *
+	 * This is used if the CA certificate for EAP-TLS is on a smartcard.
+	 */
+	char *ca_cert_id;
+
+	/**
+	 * key2_id - Key ID for OpenSSL engine (phase2)
+	 *
+	 * This is used if private key operations for EAP-TLS are performed
+	 * using a smartcard.
+	 */
+	char *key2_id;
+
+	/**
+	 * cert2_id - Cert ID for OpenSSL engine (phase2)
+	 *
+	 * This is used if the certificate operations for EAP-TLS are performed
+	 * using a smartcard.
+	 */
+	char *cert2_id;
+
+	/**
+	 * ca_cert2_id - CA Cert ID for OpenSSL engine (phase2)
+	 *
+	 * This is used if the CA certificate for EAP-TLS is on a smartcard.
+	 */
+	char *ca_cert2_id;
 
 	/**
 	 * otp - One-time-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=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/eap_peer/eap_fast.c (original)
+++ wpasupplicant/trunk/src/eap_peer/eap_fast.c Sat Jun 14 00:40:26 2008
@@ -19,7 +19,7 @@
 #include "eap_tls_common.h"
 #include "eap_config.h"
 #include "tls.h"
-#include "eap_tlv.h"
+#include "eap_common/eap_tlv_common.h"
 #include "sha1.h"
 #include "eap_fast_pac.h"
 
@@ -80,9 +80,6 @@
 				      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");
 
@@ -101,10 +98,6 @@
 	}
 
 	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 "
@@ -113,19 +106,9 @@
 		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);
+	eap_fast_derive_master_secret(data->current_pac->pac_key,
+				      server_random, client_random,
+				      master_secret);
 
 	data->session_ticket_used = 1;
 
@@ -268,71 +251,10 @@
 
 static int eap_fast_derive_msk(struct eap_fast_data *data)
 {
-	/* Derive EAP Master Session Keys (section 5.4) */
-	sha1_t_prf(data->simck, EAP_FAST_SIMCK_LEN,
-		   "Session Key Generating Function", (u8 *) "", 0,
-		   data->key_data, EAP_FAST_KEY_LEN);
-	wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: Derived key (MSK)",
-			data->key_data, EAP_FAST_KEY_LEN);
-
-	sha1_t_prf(data->simck, EAP_FAST_SIMCK_LEN,
-		   "Extended Session Key Generating Function",
-		   (u8 *) "", 0, data->emsk, EAP_EMSK_LEN);
-	wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: Derived key (EMSK)",
-			data->emsk, EAP_EMSK_LEN);
-
+	eap_fast_derive_eap_msk(data->simck, data->key_data);
+	eap_fast_derive_eap_emsk(data->simck, data->emsk);
 	data->success = 1;
-
 	return 0;
-}
-
-
-static u8 * eap_fast_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
-				char *label, size_t len)
-{
-	struct tls_keys keys;
-	u8 *rnd = NULL, *out;
-	int block_size;
-
-	block_size = tls_connection_get_keyblock_size(sm->ssl_ctx, data->conn);
-	if (block_size < 0)
-		return NULL;
-
-	out = os_malloc(block_size + len);
-	if (out == NULL)
-		return NULL;
-
-	if (tls_connection_prf(sm->ssl_ctx, data->conn, label, 1, out,
-			       block_size + len) == 0) {
-		os_memmove(out, out + block_size, len);
-		return out;
-	}
-
-	if (tls_connection_get_keys(sm->ssl_ctx, data->conn, &keys))
-		goto fail;
-
-	rnd = os_malloc(keys.client_random_len + keys.server_random_len);
-	if (rnd == NULL)
-		goto fail;
-
-	os_memcpy(rnd, keys.server_random, keys.server_random_len);
-	os_memcpy(rnd + keys.server_random_len, keys.client_random,
-		  keys.client_random_len);
-
-	wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: master_secret for key "
-			"expansion", keys.master_key, keys.master_key_len);
-	if (tls_prf(keys.master_key, keys.master_key_len,
-		    label, rnd, keys.client_random_len +
-		    keys.server_random_len, out, block_size + len))
-		goto fail;
-	os_free(rnd);
-	os_memmove(out, out + block_size, len);
-	return out;
-
-fail:
-	os_free(rnd);
-	os_free(out);
-	return NULL;
 }
 
 
@@ -345,7 +267,7 @@
 	 * Extra key material after TLS key_block: session_key_seed[40]
 	 */
 
-	sks = eap_fast_derive_key(sm, &data->ssl, "key expansion",
+	sks = eap_fast_derive_key(sm->ssl_ctx, data->ssl.conn, "key expansion",
 				  EAP_FAST_SKS_LEN);
 	if (sks == NULL) {
 		wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to derive "
@@ -371,7 +293,8 @@
 {
 	os_free(data->key_block_p);
 	data->key_block_p = (struct eap_fast_key_block_provisioning *)
-		eap_fast_derive_key(sm, &data->ssl, "key expansion",
+		eap_fast_derive_key(sm->ssl_ctx, data->ssl.conn,
+				    "key expansion",
 				    sizeof(*data->key_block_p));
 	if (data->key_block_p == NULL) {
 		wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to derive key block");
@@ -435,12 +358,27 @@
 {
 	size_t i;
 
+	/* TODO: TNC with anonymous provisioning; need to require both
+	 * completed MSCHAPv2 and TNC */
+
 	if (data->anon_provisioning && type != EAP_TYPE_MSCHAPV2) {
 		wpa_printf(MSG_INFO, "EAP-FAST: Only EAP-MSCHAPv2 is allowed "
 			   "during unauthenticated provisioning; reject phase2"
 			   " type %d", type);
 		return -1;
 	}
+
+#ifdef EAP_TNC
+	if (type == EAP_TYPE_TNC) {
+		data->phase2_type.vendor = EAP_VENDOR_IETF;
+		data->phase2_type.method = EAP_TYPE_TNC;
+		wpa_printf(MSG_DEBUG, "EAP-FAST: Selected Phase 2 EAP "
+			   "vendor %d method %d for TNC",
+			   data->phase2_type.vendor,
+			   data->phase2_type.method);
+		return 0;
+	}
+#endif /* EAP_TNC */
 
 	for (i = 0; i < data->num_phase2_types; i++) {
 		if (data->phase2_types[i].vendor != EAP_VENDOR_IETF ||
@@ -485,6 +423,17 @@
 	if (*pos == EAP_TYPE_IDENTITY) {
 		*resp = eap_sm_buildIdentity(sm, hdr->identifier, 1);
 		return 0;
+	}
+
+	if (data->phase2_priv && data->phase2_method &&
+	    *pos != data->phase2_type.method) {
+		wpa_printf(MSG_DEBUG, "EAP-FAST: Phase 2 EAP sequence - "
+			   "deinitialize previous method");
+		data->phase2_method->deinit(sm, data->phase2_priv);
+		data->phase2_method = NULL;
+		data->phase2_priv = NULL;
+		data->phase2_type.vendor = EAP_VENDOR_IETF;
+		data->phase2_type.method = EAP_TYPE_NONE;
 	}
 
 	if (data->phase2_type.vendor == EAP_VENDOR_IETF &&
@@ -596,32 +545,6 @@
 }
 
 
-static struct wpabuf * eap_fast_tlv_eap_payload(struct wpabuf *buf)
-{
-	struct wpabuf *msg;
-	struct eap_tlv_hdr *tlv;
-
-	if (buf == NULL)
-		return NULL;
-
-	/* Encapsulate EAP packet in EAP Payload TLV */
-	msg = wpabuf_alloc(sizeof(*tlv) + wpabuf_len(buf));
-	if (msg == NULL) {
-		wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to allocate memory "
-			   "for TLV encapsulation");
-		wpabuf_free(buf);
-		return NULL;
-	}
-	tlv = wpabuf_put(msg, sizeof(*tlv));
-	tlv->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY |
-				     EAP_TLV_EAP_PAYLOAD_TLV);
-	tlv->length = host_to_be16(wpabuf_len(buf));
-	wpabuf_put_buf(msg, buf);
-	wpabuf_free(buf);
-	return msg;
-}
-
-
 static struct wpabuf * eap_fast_process_eap_payload_tlv(
 	struct eap_sm *sm, struct eap_fast_data *data,
 	struct eap_method_ret *ret, const struct eap_hdr *req,
@@ -661,7 +584,7 @@
 
 
 static int eap_fast_validate_crypto_binding(
-	struct eap_tlv_crypto_binding__tlv *_bind)
+	struct eap_tlv_crypto_binding_tlv *_bind)
 {
 	wpa_printf(MSG_DEBUG, "EAP-FAST: Crypto-Binding TLV: Version %d "
 		   "Received Version %d SubType %d",
@@ -687,8 +610,8 @@
 
 
 static void eap_fast_write_crypto_binding(
-	struct eap_tlv_crypto_binding__tlv *rbind,
-	struct eap_tlv_crypto_binding__tlv *_bind, const u8 *cmk)
+	struct eap_tlv_crypto_binding_tlv *rbind,
+	struct eap_tlv_crypto_binding_tlv *_bind, const u8 *cmk)
 {
 	rbind->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY |
 				       EAP_TLV_CRYPTO_BINDING_TLV);
@@ -699,7 +622,8 @@
 	rbind->subtype = EAP_TLV_CRYPTO_BINDING_SUBTYPE_RESPONSE;
 	os_memcpy(rbind->nonce, _bind->nonce, sizeof(_bind->nonce));
 	inc_byte_array(rbind->nonce, sizeof(rbind->nonce));
-	hmac_sha1(cmk, 20, (u8 *) rbind, sizeof(*rbind), rbind->compound_mac);
+	hmac_sha1(cmk, EAP_FAST_CMK_LEN, (u8 *) rbind, sizeof(*rbind),
+		  rbind->compound_mac);
 
 	wpa_printf(MSG_DEBUG, "EAP-FAST: Reply Crypto-Binding TLV: Version %d "
 		   "Received Version %d SubType %d",
@@ -773,8 +697,9 @@
 	os_memcpy(data->simck, imck, EAP_FAST_SIMCK_LEN);
 	wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: S-IMCK[j]",
 			data->simck, EAP_FAST_SIMCK_LEN);
-	os_memcpy(cmk, imck + EAP_FAST_SIMCK_LEN, 20);
-	wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: CMK[j]", cmk, 20);
+	os_memcpy(cmk, imck + EAP_FAST_SIMCK_LEN, EAP_FAST_CMK_LEN);
+	wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: CMK[j]",
+			cmk, EAP_FAST_CMK_LEN);
 
 	return 0;
 }
@@ -807,17 +732,16 @@
 static struct wpabuf * eap_fast_process_crypto_binding(
 	struct eap_sm *sm, struct eap_fast_data *data,
 	struct eap_method_ret *ret,
-	struct eap_tlv_crypto_binding__tlv *_bind, size_t bind_len, int final)
+	struct eap_tlv_crypto_binding_tlv *_bind, size_t bind_len)
 {
 	struct wpabuf *resp;
 	u8 *pos;
-	struct eap_tlv_intermediate_result_tlv *rresult;
-	u8 cmk[20], cmac[20];
-	int res, req_tunnel_pac = 0;
+	u8 cmk[EAP_FAST_CMK_LEN], cmac[SHA1_MAC_LEN];
+	int res;
 	size_t len;
 
 	if (eap_fast_validate_crypto_binding(_bind) < 0)
-		return eap_fast_tlv_result(EAP_TLV_RESULT_FAILURE, 1);
+		return NULL;
 
 	if (eap_fast_get_cmk(sm, data, cmk) < 0)
 		return NULL;
@@ -827,7 +751,8 @@
 	os_memset(_bind->compound_mac, 0, sizeof(cmac));
 	wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Crypto-Binding TLV for Compound "
 		    "MAC calculation", (u8 *) _bind, bind_len);
-	hmac_sha1(cmk, 20, (u8 *) _bind, bind_len, _bind->compound_mac);
+	hmac_sha1(cmk, EAP_FAST_CMK_LEN, (u8 *) _bind, bind_len,
+		  _bind->compound_mac);
 	res = os_memcmp(cmac, _bind->compound_mac, sizeof(cmac));
 	wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Received Compound MAC",
 		    cmac, sizeof(cmac));
@@ -835,9 +760,8 @@
 		    _bind->compound_mac, sizeof(cmac));
 	if (res != 0) {
 		wpa_printf(MSG_INFO, "EAP-FAST: Compound MAC did not match");
-		resp = eap_fast_tlv_result(EAP_TLV_RESULT_FAILURE, 1);
 		os_memcpy(_bind->compound_mac, cmac, sizeof(cmac));
-		return resp;
+		return NULL;
 	}
 
 	/*
@@ -845,72 +769,24 @@
 	 * crypto binding to allow server to complete authentication.
 	 */
 
-	if (data->current_pac == NULL && data->provisioning &&
-	    !data->anon_provisioning) {
-		/*
-		 * Need to request Tunnel PAC when using authenticated
-		 * provisioning.
-		 */
-		wpa_printf(MSG_DEBUG, "EAP-FAST: Request Tunnel PAC");
-		req_tunnel_pac = 1;
-	}
-
-	len = sizeof(*rresult) + sizeof(struct eap_tlv_crypto_binding__tlv);
-	if (req_tunnel_pac)
-		len += sizeof(struct eap_tlv_hdr) +
-			sizeof(struct eap_tlv_request_action_tlv) +
-			sizeof(struct eap_tlv_pac_type_tlv);
+	len = sizeof(struct eap_tlv_crypto_binding_tlv);
 	resp = wpabuf_alloc(len);
 	if (resp == NULL)
 		return NULL;
-
-	/*
-	 * Both intermediate and final Result TLVs are identical, so ok to use
-	 * the same structure definition for them.
-	 */
-	rresult = wpabuf_put(resp, sizeof(*rresult));
-	rresult->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY |
-					 (final ? EAP_TLV_RESULT_TLV :
-					  EAP_TLV_INTERMEDIATE_RESULT_TLV));
-	rresult->length = host_to_be16(2);
-	rresult->status = host_to_be16(EAP_TLV_RESULT_SUCCESS);
 
 	if (!data->anon_provisioning && data->phase2_success &&
 	    eap_fast_derive_msk(data) < 0) {
 		wpa_printf(MSG_INFO, "EAP-FAST: Failed to generate MSK");
 		ret->methodState = METHOD_DONE;
 		ret->decision = DECISION_FAIL;
-		rresult->status = host_to_be16(EAP_TLV_RESULT_FAILURE);
 		data->phase2_success = 0;
-	}
-
-	pos = wpabuf_put(resp, sizeof(struct eap_tlv_crypto_binding__tlv));
-	eap_fast_write_crypto_binding((struct eap_tlv_crypto_binding__tlv *)
+		wpabuf_free(resp);
+		return NULL;
+	}
+
+	pos = wpabuf_put(resp, sizeof(struct eap_tlv_crypto_binding_tlv));
+	eap_fast_write_crypto_binding((struct eap_tlv_crypto_binding_tlv *)
 				      pos, _bind, cmk);
-
-	if (req_tunnel_pac) {
-		u8 *pos2;
-		pos = wpabuf_put(resp, 0);
-		pos2 = eap_fast_write_pac_request(pos, PAC_TYPE_TUNNEL_PAC);
-		wpabuf_put(resp, pos2 - pos);
-	}
-
-	if (final && data->phase2_success) {
-		if (data->anon_provisioning) {
-			wpa_printf(MSG_DEBUG, "EAP-FAST: Unauthenticated "
-				   "provisioning completed successfully.");
-			ret->methodState = METHOD_DONE;
-			ret->decision = DECISION_FAIL;
-		} else {
-			wpa_printf(MSG_DEBUG, "EAP-FAST: Authentication "
-				   "completed successfully.");
-			if (data->provisioning)
-				ret->methodState = METHOD_MAY_CONT;
-			else
-				ret->methodState = METHOD_DONE;
-			ret->decision = DECISION_UNCOND_SUCC;
-		}
-	}
 
 	return resp;
 }
@@ -1128,7 +1004,7 @@
 	os_memset(&entry, 0, sizeof(entry));
 	if (eap_fast_process_pac_tlv(&entry, pac, pac_len) ||
 	    eap_fast_process_pac_info(&entry))
-		return eap_fast_tlv_result(EAP_TLV_RESULT_FAILURE, 0);
+		return NULL;
 
 	eap_fast_add_pac(&data->pac, &data->current_pac, &entry);
 	eap_fast_pac_list_truncate(data->pac, data->max_pac_list_len);
@@ -1169,94 +1045,6 @@
 }
 
 
-struct eap_fast_tlv_parse {
-	u8 *eap_payload_tlv;
-	size_t eap_payload_tlv_len;
-	u8 *pac;
-	size_t pac_len;
-	struct eap_tlv_crypto_binding__tlv *crypto_binding;
-	size_t crypto_binding_len;
-	int iresult;
-	int result;
-};
-
-
-static int eap_fast_parse_tlv(struct eap_fast_tlv_parse *tlv,
-			      int tlv_type, u8 *pos, int len)
-{
-	switch (tlv_type) {
-	case EAP_TLV_EAP_PAYLOAD_TLV:
-		wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: EAP Payload TLV",
-			    pos, len);
-		tlv->eap_payload_tlv = pos;
-		tlv->eap_payload_tlv_len = len;
-		break;
-	case EAP_TLV_RESULT_TLV:
-		wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Result TLV", pos, len);
-		if (len < 2) {
-			wpa_printf(MSG_DEBUG, "EAP-FAST: Too short "
-				   "Result TLV");
-			tlv->result = EAP_TLV_RESULT_FAILURE;
-			break;
-		}
-		tlv->result = WPA_GET_BE16(pos);
-		if (tlv->result != EAP_TLV_RESULT_SUCCESS &&
-		    tlv->result != EAP_TLV_RESULT_FAILURE) {
-			wpa_printf(MSG_DEBUG, "EAP-FAST: Unknown Result %d",
-				   tlv->result);
-			tlv->result = EAP_TLV_RESULT_FAILURE;
-		}
-		wpa_printf(MSG_DEBUG, "EAP-FAST: Result: %s",
-			   tlv->result == EAP_TLV_RESULT_SUCCESS ?
-			   "Success" : "Failure");
-		break;
-	case EAP_TLV_INTERMEDIATE_RESULT_TLV:
-		wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Intermediate Result TLV",
-			    pos, len);
-		if (len < 2) {
-			wpa_printf(MSG_DEBUG, "EAP-FAST: Too short "
-				   "Intermediate Result TLV");
-			tlv->iresult = EAP_TLV_RESULT_FAILURE;
-			break;
-		}
-		tlv->iresult = WPA_GET_BE16(pos);
-		if (tlv->iresult != EAP_TLV_RESULT_SUCCESS &&
-		    tlv->iresult != EAP_TLV_RESULT_FAILURE) {
-			wpa_printf(MSG_DEBUG, "EAP-FAST: Unknown Intermediate "
-				   "Result %d", tlv->iresult);
-			tlv->iresult = EAP_TLV_RESULT_FAILURE;
-		}
-		wpa_printf(MSG_DEBUG, "EAP-FAST: Intermediate Result: %s",
-			   tlv->iresult == EAP_TLV_RESULT_SUCCESS ?
-			   "Success" : "Failure");
-		break;
-	case EAP_TLV_CRYPTO_BINDING_TLV:
-		wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Crypto-Binding TLV",
-			    pos, len);
-		tlv->crypto_binding_len = sizeof(struct eap_tlv_hdr) + len;
-		if (tlv->crypto_binding_len < sizeof(*tlv->crypto_binding)) {
-			wpa_printf(MSG_DEBUG, "EAP-FAST: Too short "
-				   "Crypto-Binding TLV");
-			tlv->iresult = EAP_TLV_RESULT_FAILURE;
-			return -2;
-		}
-		tlv->crypto_binding = (struct eap_tlv_crypto_binding__tlv *)
-			(pos - sizeof(struct eap_tlv_hdr));
-		break;
-	case EAP_TLV_PAC_TLV:
-		wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: PAC TLV", pos, len);
-		tlv->pac = pos;
-		tlv->pac_len = len;
-		break;
-	default:
-		/* Unknown TLV */
-		return -1;
-	}
-
-	return 0;
-}
-
-
 static int eap_fast_parse_decrypted(struct wpabuf *decrypted,
 				    struct eap_fast_tlv_parse *tlv,
 				    struct wpabuf **resp)
@@ -1328,6 +1116,24 @@
 }
 
 
+static struct wpabuf * eap_fast_pac_request(void)
+{
+	struct wpabuf *tmp;
+	u8 *pos, *pos2;
+
+	tmp = wpabuf_alloc(sizeof(struct eap_tlv_hdr) +
+			   sizeof(struct eap_tlv_request_action_tlv) +
+			   sizeof(struct eap_tlv_pac_type_tlv));
+	if (tmp == NULL)
+		return NULL;
+
+	pos = wpabuf_put(tmp, 0);
+	pos2 = eap_fast_write_pac_request(pos, PAC_TYPE_TUNNEL_PAC);
+	wpabuf_put(tmp, pos2 - pos);
+	return tmp;
+}
+
+
 static int eap_fast_process_decrypted(struct eap_sm *sm,
 				      struct eap_fast_data *data,
 				      struct eap_method_ret *ret,
@@ -1335,8 +1141,9 @@
 				      struct wpabuf *decrypted,
 				      struct wpabuf **out_data)
 {
-	struct wpabuf *resp = NULL;
+	struct wpabuf *resp = NULL, *tmp;
 	struct eap_fast_tlv_parse tlv;
+	int failed = 0;
 
 	if (eap_fast_parse_decrypted(decrypted, &tlv, &resp) < 0)
 		return 0;
@@ -1356,43 +1163,84 @@
 						 req->identifier, out_data);
 	}
 
+	if (tlv.crypto_binding) {
+		tmp = eap_fast_process_crypto_binding(sm, data, ret,
+						      tlv.crypto_binding,
+						      tlv.crypto_binding_len);
+		if (tmp == NULL)
+			failed = 1;
+		else
+			resp = wpabuf_concat(resp, tmp);
+	}
+
+	if (tlv.iresult == EAP_TLV_RESULT_SUCCESS) {
+		tmp = eap_fast_tlv_result(failed ? EAP_TLV_RESULT_FAILURE :
+					  EAP_TLV_RESULT_SUCCESS, 1);
+		resp = wpabuf_concat(resp, tmp);
+	}
+
 	if (tlv.eap_payload_tlv) {
-		resp = eap_fast_process_eap_payload_tlv(
+		tmp = eap_fast_process_eap_payload_tlv(
 			sm, data, ret, req, tlv.eap_payload_tlv,
 			tlv.eap_payload_tlv_len);
-		return eap_fast_encrypt_response(sm, data, resp,
-						 req->identifier, out_data);
-	}
-
-	if (tlv.crypto_binding) {
-		int final = tlv.result == EAP_TLV_RESULT_SUCCESS;
-		resp = eap_fast_process_crypto_binding(sm, data, ret,
-						       tlv.crypto_binding,
-						       tlv.crypto_binding_len,
-						       final);
-		return eap_fast_encrypt_response(sm, data, resp,
-						 req->identifier, out_data);
+		resp = wpabuf_concat(resp, tmp);
 	}
 
 	if (tlv.pac && tlv.result != EAP_TLV_RESULT_SUCCESS) {
 		wpa_printf(MSG_DEBUG, "EAP-FAST: PAC TLV without Result TLV "
 			   "acknowledging success");
-		resp = eap_fast_tlv_result(EAP_TLV_RESULT_FAILURE, 0);
-		return eap_fast_encrypt_response(sm, data, resp,
-						 req->identifier, out_data);
-	}
-
-	if (tlv.pac && tlv.result == EAP_TLV_RESULT_SUCCESS) {
-		resp = eap_fast_process_pac(sm, data, ret, tlv.pac,
-					    tlv.pac_len);
-		return eap_fast_encrypt_response(sm, data, resp,
-						 req->identifier, out_data);
-	}
-
-	wpa_printf(MSG_DEBUG, "EAP-FAST: No recognized TLVs - send "
-		   "empty response packet");
-	return eap_fast_encrypt_response(sm, data, wpabuf_alloc(1),
-					 req->identifier, out_data);
+		failed = 1;
+	} else if (tlv.pac && tlv.result == EAP_TLV_RESULT_SUCCESS) {
+		tmp = eap_fast_process_pac(sm, data, ret, tlv.pac,
+					   tlv.pac_len);
+		resp = wpabuf_concat(resp, tmp);
+	}
+
+	if (data->current_pac == NULL && data->provisioning &&
+	    !data->anon_provisioning) {
+		/*
+		 * Need to request Tunnel PAC when using authenticated
+		 * provisioning.
+		 */
+		wpa_printf(MSG_DEBUG, "EAP-FAST: Request Tunnel PAC");
+		tmp = eap_fast_pac_request();
+		resp = wpabuf_concat(resp, tmp);
+	}
+
+	if (tlv.result == EAP_TLV_RESULT_SUCCESS && !failed) {
+		tmp = eap_fast_tlv_result(EAP_TLV_RESULT_SUCCESS, 0);
+		resp = wpabuf_concat(resp, tmp);
+	} else if (failed) {
+		tmp = eap_fast_tlv_result(EAP_TLV_RESULT_FAILURE, 0);
+		resp = wpabuf_concat(resp, tmp);
+	}
+
+	if (resp && tlv.result == EAP_TLV_RESULT_SUCCESS && !failed &&
+	    tlv.crypto_binding && data->phase2_success) {
+		if (data->anon_provisioning) {
+			wpa_printf(MSG_DEBUG, "EAP-FAST: Unauthenticated "
+				   "provisioning completed successfully.");
+			ret->methodState = METHOD_DONE;
+			ret->decision = DECISION_FAIL;
+		} else {
+			wpa_printf(MSG_DEBUG, "EAP-FAST: Authentication "
+				   "completed successfully.");
+			if (data->provisioning)
+				ret->methodState = METHOD_MAY_CONT;
+			else
+				ret->methodState = METHOD_DONE;
+			ret->decision = DECISION_UNCOND_SUCC;
+		}
+	}
+
+	if (resp == NULL) {
+		wpa_printf(MSG_DEBUG, "EAP-FAST: No recognized TLVs - send "
+			   "empty response packet");
+		resp = wpabuf_alloc(1);
+	}
+
+	return eap_fast_encrypt_response(sm, data, resp, req->identifier,
+					 out_data);
 }
 
 

Modified: wpasupplicant/trunk/src/eap_peer/eap_peap.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/eap_peer/eap_peap.c?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/eap_peer/eap_peap.c (original)
+++ wpasupplicant/trunk/src/eap_peer/eap_peap.c Sat Jun 14 00:40:26 2008
@@ -15,11 +15,14 @@
 #include "includes.h"
 
 #include "common.h"
+#include "crypto/sha1.h"
 #include "eap_i.h"
 #include "eap_tls_common.h"
 #include "eap_config.h"
 #include "tls.h"
-#include "eap_tlv.h"
+#include "eap_common/eap_tlv_common.h"
+#include "eap_common/eap_peap_common.h"
+#include "tncc.h"
 
 
 /* Maximum supported PEAP version
@@ -60,6 +63,12 @@
 	u8 *key_data;
 
 	struct wpabuf *pending_phase2_req;
+	enum { NO_BINDING, OPTIONAL_BINDING, REQUIRE_BINDING } crypto_binding;
+	int crypto_binding_used;
+	u8 ipmk[40];
+	u8 cmk[20];
+	int soh; /* Whether IF-TNCCS-SOH (Statement of Health; Microsoft NAP)
+		  * is enabled. */
 };
 
 
@@ -96,6 +105,24 @@
 			   "receiving tunneled EAP-Success");
 	}
 
+	if (os_strstr(phase1, "crypto_binding=0")) {
+		data->crypto_binding = NO_BINDING;
+		wpa_printf(MSG_DEBUG, "EAP-PEAP: Do not use cryptobinding");
+	} else if (os_strstr(phase1, "crypto_binding=1")) {
+		data->crypto_binding = OPTIONAL_BINDING;
+		wpa_printf(MSG_DEBUG, "EAP-PEAP: Optional cryptobinding");
+	} else if (os_strstr(phase1, "crypto_binding=2")) {
+		data->crypto_binding = REQUIRE_BINDING;
+		wpa_printf(MSG_DEBUG, "EAP-PEAP: Require cryptobinding");
+	}
+
+#ifdef EAP_TNC
+	if (os_strstr(phase1, "tnc=soh")) {
+		data->soh = 1;
+		wpa_printf(MSG_DEBUG, "EAP-PEAP: SoH enabled");
+	}
+#endif /* EAP_TNC */
+
 	return 0;
 }
 
@@ -112,6 +139,7 @@
 	data->peap_version = EAP_PEAP_VERSION;
 	data->force_peap_version = -1;
 	data->peap_outer_success = 2;
+	data->crypto_binding = OPTIONAL_BINDING;
 
 	if (config && config->phase1 &&
 	    eap_peap_parse_phase1(data, config->phase1) < 0) {
@@ -154,6 +182,396 @@
 }
 
 
+/**
+ * eap_tlv_build_nak - Build EAP-TLV NAK message
+ * @id: EAP identifier for the header
+ * @nak_type: TLV type (EAP_TLV_*)
+ * Returns: Buffer to the allocated EAP-TLV NAK message or %NULL on failure
+ *
+ * This funtion builds an EAP-TLV NAK message. The caller is responsible for
+ * freeing the returned buffer.
+ */
+static struct wpabuf * eap_tlv_build_nak(int id, u16 nak_type)
+{
+	struct wpabuf *msg;
+
+	msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLV, 10,
+			    EAP_CODE_RESPONSE, id);
+	if (msg == NULL)
+		return NULL;
+
+	wpabuf_put_u8(msg, 0x80); /* Mandatory */
+	wpabuf_put_u8(msg, EAP_TLV_NAK_TLV);
+	wpabuf_put_be16(msg, 6); /* Length */
+	wpabuf_put_be32(msg, 0); /* Vendor-Id */
+	wpabuf_put_be16(msg, nak_type); /* NAK-Type */
+
+	return msg;
+}
+
+
+static int eap_peap_get_isk(struct eap_sm *sm, struct eap_peap_data *data,
+			    u8 *isk, size_t isk_len)
+{
+	u8 *key;
+	size_t key_len;
+
+	os_memset(isk, 0, isk_len);
+	if (data->phase2_method == NULL || data->phase2_priv == NULL ||
+	    data->phase2_method->isKeyAvailable == NULL ||
+	    data->phase2_method->getKey == NULL)
+		return 0;
+
+	if (!data->phase2_method->isKeyAvailable(sm, data->phase2_priv) ||
+	    (key = data->phase2_method->getKey(sm, data->phase2_priv,
+					       &key_len)) == NULL) {
+		wpa_printf(MSG_DEBUG, "EAP-PEAP: Could not get key material "
+			   "from Phase 2");
+		return -1;
+	}
+
+	if (key_len == 32 &&
+	    data->phase2_method->vendor == EAP_VENDOR_IETF &&
+	    data->phase2_method->method == EAP_TYPE_MSCHAPV2) {
+		/*
+		 * Microsoft uses reverse order for MS-MPPE keys in
+		 * EAP-PEAP when compared to EAP-FAST derivation of
+		 * ISK. Swap the keys here to get the correct ISK for
+		 * EAP-PEAPv0 cryptobinding.
+		 */
+		u8 tmp[16];
+		os_memcpy(tmp, key, 16);
+		os_memcpy(key, key + 16, 16);
+		os_memcpy(key + 16, tmp, 16);
+	}
+
+	if (key_len > isk_len)
+		key_len = isk_len;
+	os_memcpy(isk, key, key_len);
+	os_free(key);
+
+	return 0;
+}
+
+
+static int eap_peap_derive_cmk(struct eap_sm *sm, struct eap_peap_data *data)
+{
+	u8 *tk;
+	u8 isk[32], imck[60];
+
+	/*
+	 * Tunnel key (TK) is the first 60 octets of the key generated by
+	 * phase 1 of PEAP (based on TLS).
+	 */
+	tk = data->key_data;
+	if (tk == NULL)
+		return -1;
+	wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TK", tk, 60);
+
+	if (eap_peap_get_isk(sm, data, isk, sizeof(isk)) < 0)
+		return -1;
+	wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: ISK", isk, sizeof(isk));
+
+	/*
+	 * IPMK Seed = "Inner Methods Compound Keys" | ISK
+	 * TempKey = First 40 octets of TK
+	 * IPMK|CMK = PRF+(TempKey, IPMK Seed, 60)
+	 * (note: draft-josefsson-pppext-eap-tls-eap-10.txt includes a space
+	 * in the end of the label just before ISK; is that just a typo?)
+	 */
+	wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TempKey", tk, 40);
+	peap_prfplus(data->peap_version, tk, 40, "Inner Methods Compound Keys",
+		     isk, sizeof(isk), imck, sizeof(imck));
+	wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IMCK (IPMKj)",
+			imck, sizeof(imck));
+
+	/* TODO: fast-connect: IPMK|CMK = TK */
+	os_memcpy(data->ipmk, imck, 40);
+	wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IPMK (S-IPMKj)", data->ipmk, 40);
+	os_memcpy(data->cmk, imck + 40, 20);
+	wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK (CMKj)", data->cmk, 20);
+
+	return 0;
+}
+
+
+static int eap_tlv_add_cryptobinding(struct eap_sm *sm,
+				     struct eap_peap_data *data,
+				     struct wpabuf *buf)
+{
+	u8 *mac;
+	u8 eap_type = EAP_TYPE_PEAP;
+	const u8 *addr[2];
+	size_t len[2];
+	u16 tlv_type;
+	u8 binding_nonce[32];
+
+	/* FIX: should binding_nonce be copied from request? */
+	if (os_get_random(binding_nonce, 32))
+		return -1;
+
+	/* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */
+	addr[0] = wpabuf_put(buf, 0);
+	len[0] = 60;
+	addr[1] = &eap_type;
+	len[1] = 1;
+
+	tlv_type = EAP_TLV_CRYPTO_BINDING_TLV;
+	if (data->peap_version >= 2)
+		tlv_type |= EAP_TLV_TYPE_MANDATORY;
+	wpabuf_put_be16(buf, tlv_type);
+	wpabuf_put_be16(buf, 56);
+
+	wpabuf_put_u8(buf, 0); /* Reserved */
+	wpabuf_put_u8(buf, data->peap_version); /* Version */
+	wpabuf_put_u8(buf, data->peap_version); /* RecvVersion */
+	wpabuf_put_u8(buf, 1); /* SubType: 0 = Request, 1 = Response */
+	wpabuf_put_data(buf, binding_nonce, 32); /* Nonce */
+	mac = wpabuf_put(buf, 20); /* Compound_MAC */
+	wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC CMK", data->cmk, 20);
+	wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 1",
+		    addr[0], len[0]);
+	wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 2",
+		    addr[1], len[1]);
+	hmac_sha1_vector(data->cmk, 20, 2, addr, len, mac);
+	wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC", mac, SHA1_MAC_LEN);
+	data->crypto_binding_used = 1;
+
+	return 0;
+}
+
+
+/**
+ * eap_tlv_build_result - Build EAP-TLV Result message
+ * @id: EAP identifier for the header
+ * @status: Status (EAP_TLV_RESULT_SUCCESS or EAP_TLV_RESULT_FAILURE)
+ * Returns: Buffer to the allocated EAP-TLV Result message or %NULL on failure
+ *
+ * This funtion builds an EAP-TLV Result message. The caller is responsible for
+ * freeing the returned buffer.
+ */
+static struct wpabuf * eap_tlv_build_result(struct eap_sm *sm,
+					    struct eap_peap_data *data,
+					    int crypto_tlv_used,
+					    int id, u16 status)
+{
+	struct wpabuf *msg;
+	size_t len;
+
+	if (data->crypto_binding == NO_BINDING)
+		crypto_tlv_used = 0;
+
+	len = 6;
+	if (crypto_tlv_used)
+		len += 60; /* Cryptobinding TLV */
+	msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLV, len,
+			    EAP_CODE_RESPONSE, id);
+	if (msg == NULL)
+		return NULL;
+
+	wpabuf_put_u8(msg, 0x80); /* Mandatory */
+	wpabuf_put_u8(msg, EAP_TLV_RESULT_TLV);
+	wpabuf_put_be16(msg, 2); /* Length */
+	wpabuf_put_be16(msg, status); /* Status */
+
+	if (crypto_tlv_used && eap_tlv_add_cryptobinding(sm, data, msg)) {
+		wpabuf_free(msg);
+		return NULL;
+	}
+
+	return msg;
+}
+
+
+static int eap_tlv_validate_cryptobinding(struct eap_sm *sm,
+					  struct eap_peap_data *data,
+					  const u8 *crypto_tlv,
+					  size_t crypto_tlv_len)
+{
+	u8 buf[61], mac[SHA1_MAC_LEN];
+	const u8 *pos;
+
+	if (eap_peap_derive_cmk(sm, data) < 0) {
+		wpa_printf(MSG_DEBUG, "EAP-PEAP: Could not derive CMK");
+		return -1;
+	}
+
+	if (crypto_tlv_len != 4 + 56) {
+		wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid cryptobinding TLV "
+			   "length %d", (int) crypto_tlv_len);
+		return -1;
+	}
+
+	pos = crypto_tlv;
+	pos += 4; /* TLV header */
+	if (pos[1] != data->peap_version) {
+		wpa_printf(MSG_DEBUG, "EAP-PEAP: Cryptobinding TLV Version "
+			   "mismatch (was %d; expected %d)",
+			   pos[1], data->peap_version);
+		return -1;
+	}
+
+	if (pos[3] != 0) {
+		wpa_printf(MSG_DEBUG, "EAP-PEAP: Unexpected Cryptobinding TLV "
+			   "SubType %d", pos[3]);
+		return -1;
+	}
+	pos += 4;
+	pos += 32; /* Nonce */
+
+	/* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */
+	os_memcpy(buf, crypto_tlv, 60);
+	os_memset(buf + 4 + 4 + 32, 0, 20); /* Compound_MAC */
+	buf[60] = EAP_TYPE_PEAP;
+	hmac_sha1(data->cmk, 20, buf, sizeof(buf), mac);
+
+	if (os_memcmp(mac, pos, SHA1_MAC_LEN) != 0) {
+		wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid Compound_MAC in "
+			   "cryptobinding TLV");
+		return -1;
+	}
+
+	wpa_printf(MSG_DEBUG, "EAP-PEAP: Valid cryptobinding TLV received");
+
+	return 0;
+}
+
+
+/**
+ * eap_tlv_process - Process a received EAP-TLV message and generate a response
+ * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
+ * @ret: Return values from EAP request validation and processing
+ * @req: EAP-TLV request to be processed. The caller must have validated that
+ * the buffer is large enough to contain full request (hdr->length bytes) and
+ * that the EAP type is EAP_TYPE_TLV.
+ * @resp: Buffer to return a pointer to the allocated response message. This
+ * field should be initialized to %NULL before the call. The value will be
+ * updated if a response message is generated. The caller is responsible for
+ * freeing the allocated message.
+ * @force_failure: Force negotiation to fail
+ * Returns: 0 on success, -1 on failure
+ */
+static int eap_tlv_process(struct eap_sm *sm, struct eap_peap_data *data,
+			   struct eap_method_ret *ret,
+			   const struct wpabuf *req, struct wpabuf **resp,
+			   int force_failure)
+{
+	size_t left, tlv_len;
+	const u8 *pos;
+	const u8 *result_tlv = NULL, *crypto_tlv = NULL;
+	size_t result_tlv_len = 0, crypto_tlv_len = 0;
+	int tlv_type, mandatory;
+
+	/* Parse TLVs */
+	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TLV, req, &left);
+	if (pos == NULL)
+		return -1;
+	wpa_hexdump(MSG_DEBUG, "EAP-TLV: Received TLVs", pos, left);
+	while (left >= 4) {
+		mandatory = !!(pos[0] & 0x80);
+		tlv_type = WPA_GET_BE16(pos) & 0x3fff;
+		pos += 2;
+		tlv_len = WPA_GET_BE16(pos);
+		pos += 2;
+		left -= 4;
+		if (tlv_len > left) {
+			wpa_printf(MSG_DEBUG, "EAP-TLV: TLV underrun "
+				   "(tlv_len=%lu left=%lu)",
+				   (unsigned long) tlv_len,
+				   (unsigned long) left);
+			return -1;
+		}
+		switch (tlv_type) {
+		case EAP_TLV_RESULT_TLV:
+			result_tlv = pos;
+			result_tlv_len = tlv_len;
+			break;
+		case EAP_TLV_CRYPTO_BINDING_TLV:
+			crypto_tlv = pos;
+			crypto_tlv_len = tlv_len;
+			break;
+		default:
+			wpa_printf(MSG_DEBUG, "EAP-TLV: Unsupported TLV Type "
+				   "%d%s", tlv_type,
+				   mandatory ? " (mandatory)" : "");
+			if (mandatory) {
+				/* NAK TLV and ignore all TLVs in this packet.
+				 */
+				*resp = eap_tlv_build_nak(eap_get_id(req),
+							  tlv_type);
+				return *resp == NULL ? -1 : 0;
+			}
+			/* Ignore this TLV, but process other TLVs */
+			break;
+		}
+
+		pos += tlv_len;
+		left -= tlv_len;
+	}
+	if (left) {
+		wpa_printf(MSG_DEBUG, "EAP-TLV: Last TLV too short in "
+			   "Request (left=%lu)", (unsigned long) left);
+		return -1;
+	}
+
+	/* Process supported TLVs */
+	if (crypto_tlv && data->crypto_binding != NO_BINDING) {
+		wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Cryptobinding TLV",
+			    crypto_tlv, crypto_tlv_len);
+		if (eap_tlv_validate_cryptobinding(sm, data, crypto_tlv - 4,
+						   crypto_tlv_len + 4) < 0) {
+			if (result_tlv == NULL)
+				return -1;
+			force_failure = 1;
+		}
+	} else if (!crypto_tlv && data->crypto_binding == REQUIRE_BINDING) {
+		wpa_printf(MSG_DEBUG, "EAP-PEAP: No cryptobinding TLV");
+		return -1;
+	}
+
+	if (result_tlv) {
+		int status, resp_status;
+		wpa_hexdump(MSG_DEBUG, "EAP-TLV: Result TLV",
+			    result_tlv, result_tlv_len);
+		if (result_tlv_len < 2) {
+			wpa_printf(MSG_INFO, "EAP-TLV: Too short Result TLV "
+				   "(len=%lu)",
+				   (unsigned long) result_tlv_len);
+			return -1;
+		}
+		status = WPA_GET_BE16(result_tlv);
+		if (status == EAP_TLV_RESULT_SUCCESS) {
+			wpa_printf(MSG_INFO, "EAP-TLV: TLV Result - Success "
+				   "- EAP-TLV/Phase2 Completed");
+			if (force_failure) {
+				wpa_printf(MSG_INFO, "EAP-TLV: Earlier failure"
+					   " - force failed Phase 2");
+				resp_status = EAP_TLV_RESULT_FAILURE;
+				ret->decision = DECISION_FAIL;
+			} else {
+				resp_status = EAP_TLV_RESULT_SUCCESS;
+				ret->decision = DECISION_UNCOND_SUCC;
+			}
+		} else if (status == EAP_TLV_RESULT_FAILURE) {
+			wpa_printf(MSG_INFO, "EAP-TLV: TLV Result - Failure");
+			resp_status = EAP_TLV_RESULT_FAILURE;
+			ret->decision = DECISION_FAIL;
+		} else {
+			wpa_printf(MSG_INFO, "EAP-TLV: Unknown TLV Result "
+				   "Status %d", status);
+			resp_status = EAP_TLV_RESULT_FAILURE;
+			ret->decision = DECISION_FAIL;
+		}
+		ret->methodState = METHOD_DONE;
+
+		*resp = eap_tlv_build_result(sm, data, crypto_tlv != NULL,
+					     eap_get_id(req), resp_status);
+	}
+
+	return 0;
+}
+
+
 static struct wpabuf * eap_peapv2_tlv_eap_payload(struct wpabuf *buf)
 {
 	struct wpabuf *e;
@@ -206,7 +624,7 @@
 		break;
 	case EAP_TYPE_TLV:
 		os_memset(&iret, 0, sizeof(iret));
-		if (eap_tlv_process(sm, &iret, req, resp,
+		if (eap_tlv_process(sm, data, &iret, req, resp,
 				    data->phase2_eap_started &&
 				    !data->phase2_eap_success)) {
 			ret->methodState = METHOD_DONE;
@@ -220,6 +638,38 @@
 			data->phase2_success = 1;
 		}
 		break;
+	case EAP_TYPE_EXPANDED:
+#ifdef EAP_TNC
+		if (data->soh) {
+			const u8 *epos;
+			size_t eleft;
+
+			epos = eap_hdr_validate(EAP_VENDOR_MICROSOFT, 0x21,
+						req, &eleft);
+			if (epos) {
+				struct wpabuf *buf;
+				wpa_printf(MSG_DEBUG,
+					   "EAP-PEAP: SoH EAP Extensions");
+				buf = tncc_process_soh_request(epos, eleft);
+				if (buf) {
+					*resp = eap_msg_alloc(
+						EAP_VENDOR_MICROSOFT, 0x21,
+						wpabuf_len(buf),
+						EAP_CODE_RESPONSE,
+						hdr->identifier);
+					if (*resp == NULL) {
+						ret->methodState = METHOD_DONE;
+						ret->decision = DECISION_FAIL;
+						return -1;
+					}
+					wpabuf_put_buf(*resp, buf);
+					wpabuf_free(buf);
+					break;
+				}
+			}
+		}
+#endif /* EAP_TNC */
+		/* fall through */
 	default:
 		if (data->phase2_type.vendor == EAP_VENDOR_IETF &&
 		    data->phase2_type.method == EAP_TYPE_NONE) {
@@ -256,9 +706,11 @@
 				data->phase2_type.method);
 			if (data->phase2_method) {
 				sm->init_phase2 = 1;
+				sm->mschapv2_full_key = 1;
 				data->phase2_priv =
 					data->phase2_method->init(sm);
 				sm->init_phase2 = 0;
+				sm->mschapv2_full_key = 0;
 			}
 		}
 		if (data->phase2_priv == NULL || data->phase2_method == NULL) {
@@ -713,6 +1165,7 @@
 	struct eap_peap_data *data = priv;
 	wpabuf_free(data->pending_phase2_req);
 	data->pending_phase2_req = NULL;
+	data->crypto_binding_used = 0;
 }
 
 
@@ -777,7 +1230,23 @@
 		return NULL;
 
 	*len = EAP_TLS_KEY_LEN;
-	os_memcpy(key, data->key_data, EAP_TLS_KEY_LEN);
+
+	if (data->crypto_binding_used) {
+		u8 csk[128];
+		/*
+		 * Note: It looks like Microsoft implementation requires null
+		 * termination for this label while the one used for deriving
+		 * IPMK|CMK did not use null termination.
+		 */
+		peap_prfplus(data->peap_version, data->ipmk, 40,
+			     "Session Key Generating Function",
+			     (u8 *) "\00", 1, csk, sizeof(csk));
+		wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CSK", csk, sizeof(csk));
+		os_memcpy(key, csk, EAP_TLS_KEY_LEN);
+		wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived key",
+			    key, EAP_TLS_KEY_LEN);
+	} else
+		os_memcpy(key, data->key_data, EAP_TLS_KEY_LEN);
 
 	return key;
 }

Modified: wpasupplicant/trunk/src/eap_peer/eap_tls_common.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/eap_peer/eap_tls_common.c?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/eap_peer/eap_tls_common.c (original)
+++ wpasupplicant/trunk/src/eap_peer/eap_tls_common.c Sat Jun 14 00:40:26 2008
@@ -59,6 +59,8 @@
 	params->engine_id = config->engine_id;
 	params->pin = config->pin;
 	params->key_id = config->key_id;
+	params->cert_id = config->cert_id;
+	params->ca_cert_id = config->ca_cert_id;
 }
 
 
@@ -73,6 +75,11 @@
 	params->dh_file = (char *) config->dh_file2;
 	params->subject_match = (char *) config->subject_match2;
 	params->altsubject_match = (char *) config->altsubject_match2;
+	params->engine_id = config->engine_id;
+	params->pin = config->pin;
+	params->key_id = config->key2_id;
+	params->cert_id = config->cert2_id;
+	params->ca_cert_id = config->ca_cert2_id;
 }
 
 
@@ -820,6 +827,14 @@
 	buf_len = wpabuf_len(in_data);
 	if (data->tls_in_total > buf_len)
 		buf_len = data->tls_in_total;
+	/*
+	 * Even though we try to disable TLS compression, it is possible that
+	 * this cannot be done with all TLS libraries. Add extra buffer space
+	 * to handle the possibility of the decrypted data being longer than
+	 * input data.
+	 */
+	buf_len += 500;
+	buf_len *= 3;
 	*in_decrypted = wpabuf_alloc(buf_len ? buf_len : 1);
 	if (*in_decrypted == NULL) {
 		eap_peer_tls_reset_input(data);

Modified: wpasupplicant/trunk/src/eap_peer/eap_tnc.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/eap_peer/eap_tnc.c?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/eap_peer/eap_tnc.c (original)
+++ wpasupplicant/trunk/src/eap_peer/eap_tnc.c Sat Jun 14 00:40:26 2008
@@ -21,8 +21,12 @@
 
 
 struct eap_tnc_data {
-	EapMethodState state;
+	enum { WAIT_START, MSG, WAIT_FRAG_ACK, DONE, FAIL } state;
 	struct tncc_data *tncc;
+	struct wpabuf *in_buf;
+	struct wpabuf *out_buf;
+	size_t out_used;
+	size_t fragment_size;
 };
 
 
@@ -42,7 +46,8 @@
 	data = os_zalloc(sizeof(*data));
 	if (data == NULL)
 		return NULL;
-	data->state = METHOD_INIT;
+	data->state = WAIT_START;
+	data->fragment_size = 1300;
 	data->tncc = tncc_init();
 	if (data->tncc == NULL) {
 		os_free(data);
@@ -57,8 +62,140 @@
 {
 	struct eap_tnc_data *data = priv;
 
+	wpabuf_free(data->in_buf);
+	wpabuf_free(data->out_buf);
 	tncc_deinit(data->tncc);
 	os_free(data);
+}
+
+
+static struct wpabuf * eap_tnc_build_frag_ack(u8 id, u8 code)
+{
+	struct wpabuf *msg;
+
+	msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TNC, 0, code, id);
+	if (msg == NULL) {
+		wpa_printf(MSG_ERROR, "EAP-TNC: Failed to allocate memory "
+			   "for fragment ack");
+		return NULL;
+	}
+
+	wpa_printf(MSG_DEBUG, "EAP-TNC: Send fragment ack");
+
+	return msg;
+}
+
+
+static struct wpabuf * eap_tnc_build_msg(struct eap_tnc_data *data,
+					 struct eap_method_ret *ret, u8 id)
+{
+	struct wpabuf *resp;
+	u8 flags;
+	size_t send_len, plen;
+
+	ret->ignore = FALSE;
+	wpa_printf(MSG_DEBUG, "EAP-TNC: Generating Response");
+	ret->allowNotifications = TRUE;
+
+	flags = EAP_TNC_VERSION;
+	send_len = wpabuf_len(data->out_buf) - data->out_used;
+	if (1 + send_len > data->fragment_size) {
+		send_len = data->fragment_size - 1;
+		flags |= EAP_TNC_FLAGS_MORE_FRAGMENTS;
+		if (data->out_used == 0) {
+			flags |= EAP_TNC_FLAGS_LENGTH_INCLUDED;
+			send_len -= 4;
+		}
+	}
+
+	plen = 1 + send_len;
+	if (flags & EAP_TNC_FLAGS_LENGTH_INCLUDED)
+		plen += 4;
+	resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TNC, plen,
+			     EAP_CODE_RESPONSE, id);
+	if (resp == NULL)
+		return NULL;
+
+	wpabuf_put_u8(resp, flags); /* Flags */
+	if (flags & EAP_TNC_FLAGS_LENGTH_INCLUDED)
+		wpabuf_put_be32(resp, wpabuf_len(data->out_buf));
+
+	wpabuf_put_data(resp, wpabuf_head_u8(data->out_buf) + data->out_used,
+			send_len);
+	data->out_used += send_len;
+
+	ret->methodState = METHOD_MAY_CONT;
+	ret->decision = DECISION_FAIL;
+
+	if (data->out_used == wpabuf_len(data->out_buf)) {
+		wpa_printf(MSG_DEBUG, "EAP-TNC: Sending out %lu bytes "
+			   "(message sent completely)",
+			   (unsigned long) send_len);
+		wpabuf_free(data->out_buf);
+		data->out_buf = NULL;
+		data->out_used = 0;
+	} else {
+		wpa_printf(MSG_DEBUG, "EAP-TNC: Sending out %lu bytes "
+			   "(%lu more to send)", (unsigned long) send_len,
+			   (unsigned long) wpabuf_len(data->out_buf) -
+			   data->out_used);
+		data->state = WAIT_FRAG_ACK;
+	}
+
+	return resp;
+}
+
+
+static int eap_tnc_process_cont(struct eap_tnc_data *data,
+				const u8 *buf, size_t len)
+{
+	/* Process continuation of a pending message */
+	if (len > wpabuf_tailroom(data->in_buf)) {
+		wpa_printf(MSG_DEBUG, "EAP-TNC: Fragment overflow");
+		data->state = FAIL;
+		return -1;
+	}
+
+	wpabuf_put_data(data->in_buf, buf, len);
+	wpa_printf(MSG_DEBUG, "EAP-TNC: Received %lu bytes, waiting for "
+		   "%lu bytes more", (unsigned long) len,
+		   (unsigned long) wpabuf_tailroom(data->in_buf));
+
+	return 0;
+}
+
+
+static struct wpabuf * eap_tnc_process_fragment(struct eap_tnc_data *data,
+						struct eap_method_ret *ret,
+						u8 id, u8 flags,
+						u32 message_length,
+						const u8 *buf, size_t len)
+{
+	/* Process a fragment that is not the last one of the message */
+	if (data->in_buf == NULL && !(flags & EAP_TNC_FLAGS_LENGTH_INCLUDED)) {
+		wpa_printf(MSG_DEBUG, "EAP-TNC: No Message Length field in a "
+			   "fragmented packet");
+		ret->ignore = TRUE;
+		return NULL;
+	}
+
+	if (data->in_buf == NULL) {
+		/* First fragment of the message */
+		data->in_buf = wpabuf_alloc(message_length);
+		if (data->in_buf == NULL) {
+			wpa_printf(MSG_DEBUG, "EAP-TNC: No memory for "
+				   "message");
+			ret->ignore = TRUE;
+			return NULL;
+		}
+		wpabuf_put_data(data->in_buf, buf, len);
+		wpa_printf(MSG_DEBUG, "EAP-TNC: Received %lu bytes in first "
+			   "fragment, waiting for %lu bytes more",
+			   (unsigned long) len,
+			   (unsigned long) wpabuf_tailroom(data->in_buf));
+	}
+
+	return eap_tnc_build_frag_ack(id, EAP_CODE_RESPONSE);
 }
 
 
@@ -68,33 +205,93 @@
 {
 	struct eap_tnc_data *data = priv;
 	struct wpabuf *resp;
-	const u8 *pos;
+	const u8 *pos, *end;
 	u8 *rpos, *rpos1, *start;
 	size_t len, rlen;
 	size_t imc_len;
 	char *start_buf, *end_buf;
 	size_t start_len, end_len;
 	int tncs_done = 0;
+	u8 flags, id;
+	u32 message_length = 0;
+	struct wpabuf tmpbuf;
 
 	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TNC, reqData, &len);
-	if (pos == NULL || len == 0) {
+	if (pos == NULL) {
 		wpa_printf(MSG_INFO, "EAP-TNC: Invalid frame (pos=%p len=%lu)",
 			   pos, (unsigned long) len);
 		ret->ignore = TRUE;
 		return NULL;
 	}
 
-	wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-TNC: Received payload", pos, len);
-
-	if ((*pos & EAP_TNC_VERSION_MASK) != EAP_TNC_VERSION) {
+	id = eap_get_id(reqData);
+
+	end = pos + len;
+
+	if (len == 0)
+		flags = 0; /* fragment ack */
+	else
+		flags = *pos++;
+
+	if (len > 0 && (flags & EAP_TNC_VERSION_MASK) != EAP_TNC_VERSION) {
 		wpa_printf(MSG_DEBUG, "EAP-TNC: Unsupported version %d",
-			   *pos & EAP_TNC_VERSION_MASK);
+			   flags & EAP_TNC_VERSION_MASK);
 		ret->ignore = TRUE;
 		return NULL;
 	}
 
-	if (data->state == METHOD_INIT) {
-		if (!(*pos & EAP_TNC_FLAGS_START)) {
+	if (flags & EAP_TNC_FLAGS_LENGTH_INCLUDED) {
+		if (end - pos < 4) {
+			wpa_printf(MSG_DEBUG, "EAP-TNC: Message underflow");
+			ret->ignore = TRUE;
+			return NULL;
+		}
+		message_length = WPA_GET_BE32(pos);
+		pos += 4;
+
+		if (message_length < (u32) (end - pos)) {
+			wpa_printf(MSG_DEBUG, "EAP-TNC: Invalid Message "
+				   "Length (%d; %ld remaining in this msg)",
+				   message_length, (long) (end - pos));
+			ret->ignore = TRUE;
+			return NULL;
+		}
+	}
+
+	wpa_printf(MSG_DEBUG, "EAP-TNC: Received packet: Flags 0x%x "
+		   "Message Length %u", flags, message_length);
+
+	if (data->state == WAIT_FRAG_ACK) {
+		if (len != 0) {
+			wpa_printf(MSG_DEBUG, "EAP-TNC: Unexpected payload in "
+				   "WAIT_FRAG_ACK state");
+			ret->ignore = TRUE;
+			return NULL;
+		}
+		wpa_printf(MSG_DEBUG, "EAP-TNC: Fragment acknowledged");
+		data->state = MSG;
+		return eap_tnc_build_msg(data, ret, id);
+	}
+
+	if (data->in_buf && eap_tnc_process_cont(data, pos, end - pos) < 0) {
+		ret->ignore = TRUE;
+		return NULL;
+	}
+		
+	if (flags & EAP_TNC_FLAGS_MORE_FRAGMENTS) {
+		return eap_tnc_process_fragment(data, ret, id, flags,
+						message_length, pos,
+						end - pos);
+	}
+
+	if (data->in_buf == NULL) {
+		/* Wrap unfragmented messages as wpabuf without extra copy */
+		wpabuf_set(&tmpbuf, pos, end - pos);
+		data->in_buf = &tmpbuf;
+	}
+
+	if (data->state == WAIT_START) {
+		if (!(flags & EAP_TNC_FLAGS_START)) {
 			wpa_printf(MSG_DEBUG, "EAP-TNC: Server did not use "
 				   "start flag in the first message");
 			ret->ignore = TRUE;
@@ -103,18 +300,20 @@
 
 		tncc_init_connection(data->tncc);
 
-		data->state = METHOD_MAY_CONT;
+		data->state = MSG;
 	} else {
 		enum tncc_process_res res;
 
-		if (*pos & EAP_TNC_FLAGS_START) {
+		if (flags & EAP_TNC_FLAGS_START) {
 			wpa_printf(MSG_DEBUG, "EAP-TNC: Server used start "
 				   "flag again");
 			ret->ignore = TRUE;
 			return NULL;
 		}
 
-		res = tncc_process_if_tnccs(data->tncc, pos + 1, len - 1);
+		res = tncc_process_if_tnccs(data->tncc,
+					    wpabuf_head(data->in_buf),
+					    wpabuf_len(data->in_buf));
 		switch (res) {
 		case TNCCS_PROCESS_ERROR:
 			ret->ignore = TRUE;
@@ -142,10 +341,19 @@
 		}
 	}
 
+	if (data->in_buf != &tmpbuf)
+		wpabuf_free(data->in_buf);
+	data->in_buf = NULL;
+
 	ret->ignore = FALSE;
-	ret->methodState = data->state;
+	ret->methodState = METHOD_MAY_CONT;
 	ret->decision = DECISION_UNCOND_SUCC;
 	ret->allowNotifications = TRUE;
+
+	if (data->out_buf) {
+		data->state = MSG;
+		return eap_tnc_build_msg(data, ret, id);
+	}
 
 	if (tncs_done) {
 		resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TNC, 1,
@@ -195,7 +403,9 @@
 
 	wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-TNC: Response", start, rlen);
 
-	return resp;
+	data->out_buf = resp;
+	data->state = MSG;
+	return eap_tnc_build_msg(data, ret, id);
 }
 
 

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=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/eap_peer/eap_ttls.c (original)
+++ wpasupplicant/trunk/src/eap_peer/eap_ttls.c Sat Jun 14 00:40:26 2008
@@ -669,7 +669,7 @@
 
 	/* MS-CHAP-Challenge */
 	challenge = eap_ttls_implicit_challenge(
-		sm, data, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN * 2 + 1);
+		sm, data, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN + 1);
 	if (challenge == NULL) {
 		wpabuf_free(msg);
 		wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAPV2: Failed to derive "
@@ -753,7 +753,8 @@
 			       identity, identity_len);
 
 	/* MS-CHAP-Challenge */
-	challenge = eap_ttls_implicit_challenge(sm, data, EAP_TLS_KEY_LEN);
+	challenge = eap_ttls_implicit_challenge(
+		sm, data, EAP_TTLS_MSCHAP_CHALLENGE_LEN + 1);
 	if (challenge == NULL) {
 		wpabuf_free(msg);
 		wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAP: Failed to derive "
@@ -901,7 +902,8 @@
 			       identity, identity_len);
 
 	/* CHAP-Challenge */
-	challenge = eap_ttls_implicit_challenge(sm, data, EAP_TLS_KEY_LEN);
+	challenge = eap_ttls_implicit_challenge(
+		sm, data, EAP_TTLS_CHAP_CHALLENGE_LEN + 1);
 	if (challenge == NULL) {
 		wpabuf_free(msg);
 		wpa_printf(MSG_ERROR, "EAP-TTLS/CHAP: Failed to derive "
@@ -991,7 +993,7 @@
 		}
 	}
 
-	switch (data->phase2_type) {
+	switch (phase2_type) {
 	case EAP_TTLS_PHASE2_EAP:
 		res = eap_ttls_phase2_request_eap(sm, data, ret, hdr, resp);
 		break;
@@ -1334,6 +1336,15 @@
 	}
 
 	if (parse->mschapv2 == NULL) {
+#ifdef EAP_TNC
+		if (data->phase2_success && parse->eapdata) {
+			/*
+			 * Allow EAP-TNC to be started after successfully
+			 * completed MSCHAPV2.
+			 */
+			return 1;
+		}
+#endif /* EAP_TNC */
 		wpa_printf(MSG_WARNING, "EAP-TTLS: no MS-CHAP2-Success AVP "
 			   "received for Phase2 MSCHAPV2");
 		return -1;
@@ -1435,9 +1446,7 @@
 	case EAP_TTLS_PHASE2_MSCHAPV2:
 		res = eap_ttls_process_phase2_mschapv2(sm, data, ret, parse);
 #ifdef EAP_TNC
-		if (res == 1 && parse->eapdata &&
-		    ret->methodState == METHOD_DONE &&
-		    ret->decision == DECISION_UNCOND_SUCC) {
+		if (res == 1 && parse->eapdata && data->phase2_success) {
 			/*
 			 * TNC may be required as the next
 			 * authentication method within the tunnel.

Modified: wpasupplicant/trunk/src/eap_peer/tncc.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/eap_peer/tncc.c?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/eap_peer/tncc.c (original)
+++ wpasupplicant/trunk/src/eap_peer/tncc.c Sat Jun 14 00:40:26 2008
@@ -20,6 +20,8 @@
 #include "common.h"
 #include "base64.h"
 #include "tncc.h"
+#include "eap_common/eap_tlv_common.h"
+#include "eap_common/eap_defs.h"
 
 
 #ifdef UNICODE
@@ -37,7 +39,7 @@
 "xmlns=\"http://www.trustedcomputinggroup.org/IWG/TNC/1_0/IF_TNCCS#\" " \
 "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " \
 "xsi:schemaLocation=\"http://www.trustedcomputinggroup.org/IWG/TNC/1_0/" \
-"IF_TNCCS#https://www.trustedcomputinggroup.org/XML/SCHEMA/TNCCS_1.0.xsd\">\n"
+"IF_TNCCS# https://www.trustedcomputinggroup.org/XML/SCHEMA/TNCCS_1.0.xsd\">\n"
 #define IF_TNCCS_END "\n</TNCCS-Batch>"
 
 /* TNC IF-IMC */
@@ -1202,3 +1204,116 @@
 
 	os_free(tncc);
 }
+
+
+static struct wpabuf * tncc_build_soh(void)
+{
+	struct wpabuf *buf;
+	u8 *tlv_len, *tlv_len2, *outer_len, *inner_len, *ssoh_len, *end;
+	u8 correlation_id[24];
+	int ver = 2;
+
+	if (os_get_random(correlation_id, sizeof(correlation_id)))
+		return NULL;
+	wpa_hexdump(MSG_DEBUG, "TNC: SoH Correlation ID",
+		    correlation_id, sizeof(correlation_id));
+
+	buf = wpabuf_alloc(200);
+	if (buf == NULL)
+		return NULL;
+
+	/* Vendor-Specific TLV (Microsoft) - SoH */
+	wpabuf_put_be16(buf, EAP_TLV_VENDOR_SPECIFIC_TLV); /* TLV Type */
+	tlv_len = wpabuf_put(buf, 2); /* Length */
+	wpabuf_put_be32(buf, EAP_VENDOR_MICROSOFT); /* Vendor_Id */
+	wpabuf_put_be16(buf, 0x01); /* TLV Type - SoH TLV */
+	tlv_len2 = wpabuf_put(buf, 2); /* Length */
+
+	/* SoH Header */
+	wpabuf_put_be16(buf, EAP_TLV_VENDOR_SPECIFIC_TLV); /* Outer Type */
+	outer_len = wpabuf_put(buf, 2);
+	wpabuf_put_be32(buf, EAP_VENDOR_MICROSOFT); /* IANA SMI Code */
+	wpabuf_put_be16(buf, ver); /* Inner Type */
+	inner_len = wpabuf_put(buf, 2);
+
+	if (ver == 2) {
+		/* SoH Mode Sub-Header */
+		/* Outer Type */
+		wpabuf_put_be16(buf, EAP_TLV_VENDOR_SPECIFIC_TLV);
+		wpabuf_put_be16(buf, 4 + 24 + 1 + 1); /* Length */
+		wpabuf_put_be32(buf, EAP_VENDOR_MICROSOFT); /* IANA SMI Code */
+		/* Value: */
+		wpabuf_put_data(buf, correlation_id, sizeof(correlation_id));
+		wpabuf_put_u8(buf, 0x01); /* Intent Flag - Request */
+		wpabuf_put_u8(buf, 0x00); /* Content-Type Flag */
+	}
+
+	/* SSoH TLV */
+	/* System-Health-Id */
+	wpabuf_put_be16(buf, 0x0002); /* Type */
+	wpabuf_put_be16(buf, 4); /* Length */
+	wpabuf_put_be32(buf, 79616);
+	/* Vendor-Specific Attribute */
+	wpabuf_put_be16(buf, EAP_TLV_VENDOR_SPECIFIC_TLV);
+	ssoh_len = wpabuf_put(buf, 2);
+	wpabuf_put_be32(buf, EAP_VENDOR_MICROSOFT); /* IANA SMI Code */
+	/* TODO: MS-Machine-Inventory */
+	/* TODO: MS-Quarantine-State */
+	/* MS-Packet-Info */
+	wpabuf_put_u8(buf, 0x03);
+	wpabuf_put_u8(buf, 0x11); /* r=request, vers=1 */
+	/* TODO: MS-MachineName */
+	/* MS-CorrelationId */
+	wpabuf_put_u8(buf, 0x06);
+	wpabuf_put_data(buf, correlation_id, sizeof(correlation_id));
+	end = wpabuf_put(buf, 0);
+	WPA_PUT_BE16(ssoh_len, end - ssoh_len - 2);
+
+	/* TODO: SoHReportEntry TLV (zero or more) */
+
+	/* Update length fields */
+	end = wpabuf_put(buf, 0);
+	WPA_PUT_BE16(tlv_len, end - tlv_len - 2);
+	WPA_PUT_BE16(tlv_len2, end - tlv_len2 - 2);
+	WPA_PUT_BE16(outer_len, end - outer_len - 2);
+	WPA_PUT_BE16(inner_len, end - inner_len - 2);
+
+	return buf;
+}
+
+
+struct wpabuf * tncc_process_soh_request(const u8 *data, size_t len)
+{
+	const u8 *pos;
+
+	wpa_hexdump(MSG_DEBUG, "TNC: SoH Request", data, len);
+
+	if (len < 12)
+		return NULL;
+
+	/* SoH Request */
+	pos = data;
+
+	/* TLV Type */
+	if (WPA_GET_BE16(pos) != EAP_TLV_VENDOR_SPECIFIC_TLV)
+		return NULL;
+	pos += 2;
+
+	/* Length */
+	if (WPA_GET_BE16(pos) < 8)
+		return NULL;
+	pos += 2;
+
+	/* Vendor_Id */
+	if (WPA_GET_BE32(pos) != EAP_VENDOR_MICROSOFT)
+		return NULL;
+	pos += 4;
+
+	/* TLV Type */
+	if (WPA_GET_BE16(pos) != 0x02 /* SoH request TLV */)
+		return NULL;
+
+	wpa_printf(MSG_DEBUG, "TNC: SoH Request TLV received");
+
+	return tncc_build_soh();
+}

Modified: wpasupplicant/trunk/src/eap_peer/tncc.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/eap_peer/tncc.h?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/eap_peer/tncc.h (original)
+++ wpasupplicant/trunk/src/eap_peer/tncc.h Sat Jun 14 00:40:26 2008
@@ -37,4 +37,6 @@
 enum tncc_process_res tncc_process_if_tnccs(struct tncc_data *tncc,
 					    const u8 *msg, size_t len);
 
+struct wpabuf * tncc_process_soh_request(const u8 *data, size_t len);
+
 #endif /* TNCC_H */

Modified: wpasupplicant/trunk/src/eap_server/eap.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/eap_server/eap.c?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/eap_server/eap.c (original)
+++ wpasupplicant/trunk/src/eap_server/eap.c Sat Jun 14 00:40:26 2008
@@ -1154,6 +1154,7 @@
 	if (conf->eap_fast_a_id)
 		sm->eap_fast_a_id = os_strdup(conf->eap_fast_a_id);
 	sm->eap_sim_aka_result_ind = conf->eap_sim_aka_result_ind;
+	sm->tnc = conf->tnc;
 
 	wpa_printf(MSG_DEBUG, "EAP: Server state machine created");
 

Modified: wpasupplicant/trunk/src/eap_server/eap.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/eap_server/eap.h?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/eap_server/eap.h (original)
+++ wpasupplicant/trunk/src/eap_server/eap.h Sat Jun 14 00:40:26 2008
@@ -97,6 +97,7 @@
 	u8 *pac_opaque_encr_key;
 	char *eap_fast_a_id;
 	int eap_sim_aka_result_ind;
+	int tnc;
 };
 
 

Modified: wpasupplicant/trunk/src/eap_server/eap_fast.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/eap_server/eap_fast.c?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/eap_server/eap_fast.c (original)
+++ wpasupplicant/trunk/src/eap_server/eap_fast.c Sat Jun 14 00:40:26 2008
@@ -31,6 +31,7 @@
 #define PAC_OPAQUE_TYPE_PAD 0
 #define PAC_OPAQUE_TYPE_KEY 1
 #define PAC_OPAQUE_TYPE_LIFETIME 2
+#define PAC_OPAQUE_TYPE_IDENTITY 3
 
 /* PAC-Key lifetime in seconds (hard limit) */
 #define PAC_KEY_LIFETIME (7 * 24 * 60 * 60)
@@ -62,7 +63,7 @@
 	struct eap_fast_key_block_provisioning *key_block_p;
 
 	u8 simck[EAP_FAST_SIMCK_LEN];
-	u8 cmk[20];
+	u8 cmk[EAP_FAST_CMK_LEN];
 	int simck_idx;
 
 	u8 pac_opaque_encr[16];
@@ -71,6 +72,10 @@
 	int anon_provisioning;
 	int send_new_pac; /* server triggered re-keying of Tunnel PAC */
 	struct wpabuf *pending_phase2_resp;
+	u8 *identity; /* from PAC-Opaque */
+	size_t identity_len;
+	int eap_seq;
+	int tnc_started;
 };
 
 
@@ -125,22 +130,17 @@
 				      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];
 	const u8 *pac_opaque;
 	size_t pac_opaque_len;
 	u8 *buf, *pos, *end, *pac_key = NULL;
 	os_time_t lifetime = 0;
 	struct os_time now;
+	u8 *identity = NULL;
+	size_t identity_len = 0;
 
 	wpa_printf(MSG_DEBUG, "EAP-FAST: SessionTicket callback");
 	wpa_hexdump(MSG_DEBUG, "EAP-FAST: SessionTicket (PAC-Opaque)",
 		    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 (len < 4 || WPA_GET_BE16(ticket) != PAC_TYPE_PAC_OPAQUE) {
 		wpa_printf(MSG_DEBUG, "EAP-FAST: Ignore invalid "
@@ -217,6 +217,10 @@
 			}
 			lifetime = WPA_GET_BE32(pos + 2);
 			break;
+		case PAC_OPAQUE_TYPE_IDENTITY:
+			identity = pos + 2;
+			identity_len = pos[1];
+			break;
 		}
 
 		pos += 2 + pos[1];
@@ -229,6 +233,17 @@
 		return -1;
 	}
 
+	if (identity) {
+		wpa_hexdump_ascii(MSG_DEBUG, "EAP-FAST: Identity from "
+				  "PAC-Opaque", identity, identity_len);
+		os_free(data->identity);
+		data->identity = os_malloc(identity_len);
+		if (data->identity) {
+			os_memcpy(data->identity, identity, identity_len);
+			data->identity_len = identity_len;
+		}
+	}
+
 	if (os_get_time(&now) < 0 || lifetime <= 0 || now.sec > lifetime) {
 		wpa_printf(MSG_DEBUG, "EAP-FAST: PAC-Key not valid anymore "
 			   "(lifetime=%ld now=%ld)", lifetime, now.sec);
@@ -239,72 +254,12 @@
 	if (lifetime - now.sec < PAC_KEY_REFRESH_TIME)
 		data->send_new_pac = 1;
 
-	/*
-	 * 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(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);
+	eap_fast_derive_master_secret(pac_key, server_random, client_random,
+				      master_secret);
 
 	os_free(buf);
 
 	return 1;
-}
-
-
-static u8 * eap_fast_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
-				char *label, size_t len)
-{
-	struct tls_keys keys;
-	u8 *rnd = NULL, *out;
-	int block_size;
-
-	block_size = tls_connection_get_keyblock_size(sm->ssl_ctx, data->conn);
-	if (block_size < 0)
-		return NULL;
-
-	out = os_malloc(block_size + len);
-	if (out == NULL)
-		return NULL;
-
-	if (tls_connection_prf(sm->ssl_ctx, data->conn, label, 1, out,
-			       block_size + len) == 0) {
-		os_memmove(out, out + block_size, len);
-		return out;
-	}
-
-	if (tls_connection_get_keys(sm->ssl_ctx, data->conn, &keys))
-		goto fail;
-
-	rnd = os_malloc(keys.client_random_len + keys.server_random_len);
-	if (rnd == NULL)
-		goto fail;
-
-	os_memcpy(rnd, keys.server_random, keys.server_random_len);
-	os_memcpy(rnd + keys.server_random_len, keys.client_random,
-		  keys.client_random_len);
-
-	wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: master_secret for key "
-			"expansion", keys.master_key, keys.master_key_len);
-	if (tls_prf(keys.master_key, keys.master_key_len,
-		    label, rnd, keys.client_random_len +
-		    keys.server_random_len, out, block_size + len))
-		goto fail;
-	os_free(rnd);
-	os_memmove(out, out + block_size, len);
-	return out;
-
-fail:
-	os_free(rnd);
-	os_free(out);
-	return NULL;
 }
 
 
@@ -317,7 +272,7 @@
 	 * Extra key material after TLS key_block: session_key_seed[40]
 	 */
 
-	sks = eap_fast_derive_key(sm, &data->ssl, "key expansion",
+	sks = eap_fast_derive_key(sm->ssl_ctx, data->ssl.conn, "key expansion",
 				  EAP_FAST_SKS_LEN);
 	if (sks == NULL) {
 		wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to derive "
@@ -343,7 +298,8 @@
 {
 	os_free(data->key_block_p);
 	data->key_block_p = (struct eap_fast_key_block_provisioning *)
-		eap_fast_derive_key(sm, &data->ssl, "key expansion",
+		eap_fast_derive_key(sm->ssl_ctx, data->ssl.conn,
+				    "key expansion",
 				    sizeof(*data->key_block_p));
 	if (data->key_block_p == NULL) {
 		wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to derive key block");
@@ -428,8 +384,9 @@
 	os_memcpy(data->simck, imck, EAP_FAST_SIMCK_LEN);
 	wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: S-IMCK[j]",
 			data->simck, EAP_FAST_SIMCK_LEN);
-	os_memcpy(data->cmk, imck + EAP_FAST_SIMCK_LEN, 20);
-	wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: CMK[j]", data->cmk, 20);
+	os_memcpy(data->cmk, imck + EAP_FAST_SIMCK_LEN, EAP_FAST_CMK_LEN);
+	wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: CMK[j]",
+			data->cmk, EAP_FAST_CMK_LEN);
 
 	return 0;
 }
@@ -517,6 +474,7 @@
 	os_free(data->srv_id);
 	os_free(data->key_block_p);
 	wpabuf_free(data->pending_phase2_resp);
+	os_free(data->identity);
 	os_free(data);
 }
 
@@ -525,11 +483,10 @@
 					    struct eap_fast_data *data, u8 id)
 {
 	struct wpabuf *req;
-	struct pac_tlv_hdr *a_id;
 	size_t srv_id_len = os_strlen(data->srv_id);
 
 	req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_FAST,
-			    1 + sizeof(*a_id) + srv_id_len,
+			    1 + sizeof(struct pac_tlv_hdr) + srv_id_len,
 			    EAP_CODE_REQUEST, id);
 	if (req == NULL) {
 		wpa_printf(MSG_ERROR, "EAP-FAST: Failed to allocate memory for"
@@ -539,10 +496,9 @@
 	}
 
 	wpabuf_put_u8(req, EAP_TLS_FLAGS_START | data->fast_version);
-	a_id = wpabuf_put(req, sizeof(*a_id));
-	a_id->type = host_to_be16(PAC_TYPE_A_ID);
-	a_id->len = host_to_be16(srv_id_len);
-	wpabuf_put_data(req, data->srv_id, srv_id_len);
+
+	/* RFC 4851, 4.1.1. Authority ID Data */
+	eap_fast_put_tlv(req, PAC_TYPE_A_ID, data->srv_id, srv_id_len);
 
 	eap_fast_state(data, PHASE1);
 
@@ -577,90 +533,6 @@
 }
 
 
-static struct wpabuf * eap_fast_build_req(struct eap_sm *sm,
-					  struct eap_fast_data *data, u8 id)
-{
-	int res;
-	struct wpabuf *req;
-
-	res = eap_server_tls_buildReq_helper(sm, &data->ssl, EAP_TYPE_FAST,
-					     data->fast_version, id, &req);
-
-	if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
-		if (eap_fast_phase1_done(sm, data) < 0) {
-			os_free(req);
-			return NULL;
-		}
-	}
-
-	if (res == 1)
-		return eap_server_tls_build_ack(id, EAP_TYPE_FAST,
-						data->fast_version);
-	return req;
-}
-
-
-static struct wpabuf * eap_fast_encrypt(struct eap_sm *sm,
-					struct eap_fast_data *data,
-					u8 id, u8 *plain, size_t plain_len)
-{
-	int res;
-	struct wpabuf *buf;
-
-	/* TODO: add support for fragmentation, if needed. This will need to
-	 * add TLS Message Length field, if the frame is fragmented. */
-	buf = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_FAST,
-			    1 + data->ssl.tls_out_limit,
-			    EAP_CODE_REQUEST, id);
-	if (buf == NULL)
-		return NULL;
-
-	wpabuf_put_u8(buf, data->fast_version);
-
-	res = tls_connection_encrypt(sm->ssl_ctx, data->ssl.conn,
-				     plain, plain_len, wpabuf_put(buf, 0),
-				     data->ssl.tls_out_limit);
-	if (res < 0) {
-		wpa_printf(MSG_INFO, "EAP-FAST: Failed to encrypt Phase 2 "
-			   "data");
-		wpabuf_free(buf);
-		return NULL;
-	}
-
-	wpabuf_put(buf, res);
-	eap_update_len(buf);
-
-	return buf;
-}
-
-
-static struct wpabuf * eap_fast_tlv_eap_payload(struct wpabuf *buf)
-{
-	struct wpabuf *e;
-	struct eap_tlv_hdr *tlv;
-
-	if (buf == NULL)
-		return NULL;
-
-	/* Encapsulate EAP packet in EAP-Payload TLV */
-	wpa_printf(MSG_DEBUG, "EAP-FAST: Add EAP-Payload TLV");
-	e = wpabuf_alloc(sizeof(*tlv) + wpabuf_len(buf));
-	if (e == NULL) {
-		wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to allocate memory "
-			   "for TLV encapsulation");
-		wpabuf_free(buf);
-		return NULL;
-	}
-	tlv = wpabuf_put(e, sizeof(*tlv));
-	tlv->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY |
-				     EAP_TLV_EAP_PAYLOAD_TLV);
-	tlv->length = host_to_be16(wpabuf_len(buf));
-	wpabuf_put_buf(e, buf);
-	wpabuf_free(buf);
-	return e;
-}
-
-
 static struct wpabuf * eap_fast_build_phase2_req(struct eap_sm *sm,
 						 struct eap_fast_data *data,
 						 u8 id)
@@ -686,27 +558,40 @@
 {
 	struct wpabuf *buf;
 	struct eap_tlv_result_tlv *result;
-	struct eap_tlv_crypto_binding__tlv *binding;
-	int type;
-
-	buf = wpabuf_alloc(sizeof(*result) + sizeof(*binding));
+	struct eap_tlv_crypto_binding_tlv *binding;
+
+	buf = wpabuf_alloc(2 * sizeof(*result) + sizeof(*binding));
 	if (buf == NULL)
 		return NULL;
 
-	if (data->send_new_pac || data->anon_provisioning) {
-		type = EAP_TLV_INTERMEDIATE_RESULT_TLV;
+	if (data->send_new_pac || data->anon_provisioning ||
+	    data->phase2_method)
 		data->final_result = 0;
-	} else {
-		type = EAP_TLV_RESULT_TLV;
+	else
 		data->final_result = 1;
-	}
-
-	/* Result TLV */
-	wpa_printf(MSG_DEBUG, "EAP-FAST: Add Result TLV (status=SUCCESS)");
-	result = wpabuf_put(buf, sizeof(*result));
-	result->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY | type);
-	result->length = host_to_be16(2);
-	result->status = host_to_be16(EAP_TLV_RESULT_SUCCESS);
+
+	if (!data->final_result || data->eap_seq > 1) {
+		/* Intermediate-Result */
+		wpa_printf(MSG_DEBUG, "EAP-FAST: Add Intermediate-Result TLV "
+			   "(status=SUCCESS)");
+		result = wpabuf_put(buf, sizeof(*result));
+		result->tlv_type = host_to_be16(
+			EAP_TLV_TYPE_MANDATORY |
+			EAP_TLV_INTERMEDIATE_RESULT_TLV);
+		result->length = host_to_be16(2);
+		result->status = host_to_be16(EAP_TLV_RESULT_SUCCESS);
+	}
+
+	if (data->final_result) {
+		/* Result TLV */
+		wpa_printf(MSG_DEBUG, "EAP-FAST: Add Result TLV "
+			   "(status=SUCCESS)");
+		result = wpabuf_put(buf, sizeof(*result));
+		result->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY |
+						EAP_TLV_RESULT_TLV);
+		result->length = host_to_be16(2);
+		result->status = host_to_be16(EAP_TLV_RESULT_SUCCESS);
+	}
 
 	/* Crypto-Binding TLV */
 	binding = wpabuf_put(buf, sizeof(*binding));
@@ -737,7 +622,8 @@
 	 * Compound-MAC = HMAC-SHA1( CMK, Crypto-Binding TLV )
 	 */
 
-	hmac_sha1(data->cmk, 20, (u8 *) binding, sizeof(*binding),
+	hmac_sha1(data->cmk, EAP_FAST_CMK_LEN,
+		  (u8 *) binding, sizeof(*binding),
 		  binding->compound_mac);
 
 	wpa_printf(MSG_DEBUG, "EAP-FAST: Add Crypto-Binding TLV: Version %d "
@@ -756,45 +642,80 @@
 static struct wpabuf * eap_fast_build_pac(struct eap_sm *sm,
 					  struct eap_fast_data *data)
 {
-	u8 pac_key[2 + EAP_FAST_PAC_KEY_LEN + 6];
-	u8 pac_opaque[8 + EAP_FAST_PAC_KEY_LEN + 8];
+	u8 pac_key[EAP_FAST_PAC_KEY_LEN];
+	u8 *pac_buf, *pac_opaque;
 	struct wpabuf *buf;
 	u8 *pos;
-	size_t buf_len, srv_id_len;
+	size_t buf_len, srv_id_len, pac_len;
 	struct eap_tlv_hdr *pac_tlv;
-	struct pac_tlv_hdr *hdr, *pac_info;
+	struct pac_tlv_hdr *pac_info;
 	struct eap_tlv_result_tlv *result;
 	struct os_time now;
 
+	if (os_get_random(pac_key, EAP_FAST_PAC_KEY_LEN) < 0 ||
+	    os_get_time(&now) < 0)
+		return NULL;
+	wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: Generated PAC-Key",
+			pac_key, EAP_FAST_PAC_KEY_LEN);
+
+	pac_len = (2 + EAP_FAST_PAC_KEY_LEN) + (2 + 4) +
+		(2 + sm->identity_len) + 8;
+	pac_buf = os_malloc(pac_len);
+	if (pac_buf == NULL)
+		return NULL;
+
 	srv_id_len = os_strlen(data->srv_id);
 
-	pac_key[0] = PAC_OPAQUE_TYPE_KEY;
-	pac_key[1] = EAP_FAST_PAC_KEY_LEN;
-	if (os_get_random(pac_key + 2, EAP_FAST_PAC_KEY_LEN) < 0)
-		return NULL;
-	if (os_get_time(&now) < 0)
-		return NULL;
-	wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: Generated PAC-Key",
-			pac_key + 2, EAP_FAST_PAC_KEY_LEN);
-	pos = pac_key + 2 + EAP_FAST_PAC_KEY_LEN;
+	pos = pac_buf;
+	*pos++ = PAC_OPAQUE_TYPE_KEY;
+	*pos++ = EAP_FAST_PAC_KEY_LEN;
+	os_memcpy(pos, pac_key, EAP_FAST_PAC_KEY_LEN);
+	pos += EAP_FAST_PAC_KEY_LEN;
+
 	*pos++ = PAC_OPAQUE_TYPE_LIFETIME;
 	*pos++ = 4;
 	WPA_PUT_BE32(pos, now.sec + PAC_KEY_LIFETIME);
-
-	if (aes_wrap(data->pac_opaque_encr, sizeof(pac_key) / 8, pac_key,
-		     pac_opaque) < 0)
-		return NULL;
-
+	pos += 4;
+
+	if (sm->identity) {
+		*pos++ = PAC_OPAQUE_TYPE_IDENTITY;
+		*pos++ = sm->identity_len;
+		os_memcpy(pos, sm->identity, sm->identity_len);
+		pos += sm->identity_len;
+	}
+
+	pac_len = pos - pac_buf;
+	if (pac_len % 8) {
+		*pos++ = PAC_OPAQUE_TYPE_PAD;
+		pac_len++;
+	}
+
+	pac_opaque = os_malloc(pac_len + 8);
+	if (pac_opaque == NULL) {
+		os_free(pac_buf);
+		return NULL;
+	}
+	if (aes_wrap(data->pac_opaque_encr, pac_len / 8, pac_buf,
+		     pac_opaque) < 0) {
+		os_free(pac_buf);
+		os_free(pac_opaque);
+		return NULL;
+	}
+	os_free(pac_buf);
+
+	pac_len += 8;
 	wpa_hexdump(MSG_DEBUG, "EAP-FAST: PAC-Opaque",
-		    pac_opaque, sizeof(pac_opaque));
+		    pac_opaque, pac_len);
 
 	buf_len = sizeof(*pac_tlv) +
-		sizeof(*hdr) + EAP_FAST_PAC_KEY_LEN +
-		sizeof(*hdr) + sizeof(pac_opaque) +
+		sizeof(struct pac_tlv_hdr) + EAP_FAST_PAC_KEY_LEN +
+		sizeof(struct pac_tlv_hdr) + pac_len +
 		2 * srv_id_len + 100 + sizeof(*result);
 	buf = wpabuf_alloc(buf_len);
-	if (buf == NULL)
-		return NULL;
+	if (buf == NULL) {
+		os_free(pac_opaque);
+		return NULL;
+	}
 
 	/* PAC TLV */
 	wpa_printf(MSG_DEBUG, "EAP-FAST: Add PAC TLV");
@@ -803,45 +724,30 @@
 					 EAP_TLV_PAC_TLV);
 
 	/* PAC-Key */
-	hdr = wpabuf_put(buf, sizeof(*hdr));
-	hdr->type = host_to_be16(PAC_TYPE_PAC_KEY);
-	hdr->len = host_to_be16(EAP_FAST_PAC_KEY_LEN);
-	wpabuf_put_data(buf, pac_key + 2, EAP_FAST_PAC_KEY_LEN);
+	eap_fast_put_tlv(buf, PAC_TYPE_PAC_KEY, pac_key, EAP_FAST_PAC_KEY_LEN);
 
 	/* PAC-Opaque */
-	hdr = wpabuf_put(buf, sizeof(*hdr));
-	hdr->type = host_to_be16(PAC_TYPE_PAC_OPAQUE);
-	hdr->len = host_to_be16(sizeof(pac_opaque));
-	wpabuf_put_data(buf, pac_opaque, sizeof(pac_opaque));
+	eap_fast_put_tlv(buf, PAC_TYPE_PAC_OPAQUE, pac_opaque, pac_len);
+	os_free(pac_opaque);
 
 	/* PAC-Info */
 	pac_info = wpabuf_put(buf, sizeof(*pac_info));
 	pac_info->type = host_to_be16(PAC_TYPE_PAC_INFO);
 
 	/* PAC-Lifetime (inside PAC-Info) */
-	hdr = wpabuf_put(buf, sizeof(*hdr));
-	hdr->type = host_to_be16(PAC_TYPE_CRED_LIFETIME);
-	hdr->len = host_to_be16(4);
+	eap_fast_put_tlv_hdr(buf, PAC_TYPE_CRED_LIFETIME, 4);
 	wpabuf_put_be32(buf, now.sec + PAC_KEY_LIFETIME);
 
 	/* A-ID (inside PAC-Info) */
-	hdr = wpabuf_put(buf, sizeof(*hdr));
-	hdr->type = host_to_be16(PAC_TYPE_A_ID);
-	hdr->len = host_to_be16(srv_id_len);
-	wpabuf_put_data(buf, data->srv_id, srv_id_len);
+	eap_fast_put_tlv(buf, PAC_TYPE_A_ID, data->srv_id, srv_id_len);
 	
 	/* Note: headers may be misaligned after A-ID */
 
 	/* A-ID-Info (inside PAC-Info) */
-	hdr = wpabuf_put(buf, sizeof(*hdr));
-	WPA_PUT_BE16((u8 *) &hdr->type, PAC_TYPE_A_ID_INFO);
-	WPA_PUT_BE16((u8 *) &hdr->len, srv_id_len);
-	wpabuf_put_data(buf, data->srv_id, srv_id_len);
+	eap_fast_put_tlv(buf, PAC_TYPE_A_ID_INFO, data->srv_id, srv_id_len);
 
 	/* PAC-Type (inside PAC-Info) */
-	hdr = wpabuf_put(buf, sizeof(*hdr));
-	WPA_PUT_BE16((u8 *) &hdr->type, PAC_TYPE_PAC_TYPE);
-	WPA_PUT_BE16((u8 *) &hdr->len, 2);
+	eap_fast_put_tlv_hdr(buf, PAC_TYPE_PAC_TYPE, 2);
 	wpabuf_put_be16(buf, PAC_TYPE_TUNNEL_PAC);
 
 	/* Update PAC-Info and PAC TLV Length fields */
@@ -864,22 +770,45 @@
 static struct wpabuf * eap_fast_buildReq(struct eap_sm *sm, void *priv, u8 id)
 {
 	struct eap_fast_data *data = priv;
-	struct wpabuf *req;
+	struct wpabuf *req = NULL;
 	struct wpabuf *encr;
 
-	if (data->state == START)
+	if (data->ssl.state == FRAG_ACK) {
+		return eap_server_tls_build_ack(id, EAP_TYPE_FAST,
+						data->fast_version);
+	}
+
+	if (data->ssl.state == WAIT_FRAG_ACK) {
+		return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_FAST,
+						data->fast_version, id);
+	}
+
+	switch (data->state) {
+	case START:
 		return eap_fast_build_start(sm, data, id);
-
-	if (data->state == PHASE1)
-		return eap_fast_build_req(sm, data, id);
-
-	switch (data->state) {
+	case PHASE1:
+		if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
+			if (eap_fast_phase1_done(sm, data) < 0)
+				return NULL;
+		}
+		break;
 	case PHASE2_ID:
 	case PHASE2_METHOD:
 		req = eap_fast_build_phase2_req(sm, data, id);
 		break;
 	case CRYPTO_BINDING:
 		req = eap_fast_build_crypto_binding(sm, data);
+		if (data->phase2_method) {
+			/*
+			 * Include the start of the next EAP method in the
+			 * sequence in the same message with Crypto-Binding to
+			 * save a round-trip.
+			 */
+			struct wpabuf *eap;
+			eap = eap_fast_build_phase2_req(sm, data, id);
+			req = wpabuf_concat(req, eap);
+			eap_fast_state(data, PHASE2_METHOD);
+		}
 		break;
 	case REQUEST_PAC:
 		req = eap_fast_build_pac(sm, data);
@@ -890,16 +819,21 @@
 		return NULL;
 	}
 
-	if (req == NULL)
-		return NULL;
-
-	wpa_hexdump_buf_key(MSG_DEBUG, "EAP-FAST: Encrypting Phase 2 TLVs",
-			    req);
-	encr = eap_fast_encrypt(sm, data, id, wpabuf_mhead(req),
-				wpabuf_len(req));
-	wpabuf_free(req);
-
-	return encr;
+	if (req) {
+		wpa_hexdump_buf_key(MSG_DEBUG, "EAP-FAST: Encrypting Phase 2 "
+				    "TLVs", req);
+		encr = eap_server_tls_encrypt(sm, &data->ssl,
+					      wpabuf_mhead(req),
+					      wpabuf_len(req));
+		wpabuf_free(req);
+
+		wpabuf_free(data->ssl.out_buf);
+		data->ssl.out_used = 0;
+		data->ssl.out_buf = encr;
+	}
+
+	return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_FAST,
+					data->fast_version, id);
 }
 
 
@@ -971,6 +905,16 @@
 		left = in_len - sizeof(*hdr);
 		wpa_hexdump(MSG_DEBUG, "EAP-FAST: Phase2 type Nak'ed; "
 			    "allowed types", pos + 1, left - 1);
+#ifdef EAP_TNC
+		if (m && m->vendor == EAP_VENDOR_IETF &&
+		    m->method == EAP_TYPE_TNC) {
+			wpa_printf(MSG_DEBUG, "EAP-FAST: Peer Nak'ed required "
+				   "TNC negotiation");
+			next_type = eap_fast_req_failure(sm, data);
+			eap_fast_phase2_init(sm, data, next_type);
+			return;
+		}
+#endif /* EAP_TNC */
 		eap_sm_process_nak(sm, pos + 1, left - 1);
 		if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS &&
 		    sm->user->methods[sm->user_eap_method_index].method !=
@@ -1033,9 +977,18 @@
 		wpa_printf(MSG_DEBUG, "EAP-FAST: try EAP type %d", next_type);
 		break;
 	case PHASE2_METHOD:
+	case CRYPTO_BINDING:
 		eap_fast_update_icmk(sm, data);
 		eap_fast_state(data, CRYPTO_BINDING);
+		data->eap_seq++;
 		next_type = EAP_TYPE_NONE;
+#ifdef EAP_TNC
+		if (sm->tnc && !data->tnc_started) {
+			wpa_printf(MSG_DEBUG, "EAP-FAST: Initialize TNC");
+			next_type = EAP_TYPE_TNC;
+			data->tnc_started = 1;
+		}
+#endif /* EAP_TNC */
 		break;
 	case FAILURE:
 		break;
@@ -1082,144 +1035,6 @@
 			   "Phase 2 EAP header", hdr->code);
 		break;
 	}
-}
-
-
-struct eap_fast_tlv_parse {
-	u8 *eap_payload_tlv;
-	size_t eap_payload_tlv_len;
-	struct eap_tlv_crypto_binding__tlv *crypto_binding;
-	size_t crypto_binding_len;
-	int iresult;
-	int result;
-	int request_action;
-	u8 *pac;
-	size_t pac_len;
-};
-
-
-static int eap_fast_parse_tlv(struct eap_fast_tlv_parse *tlv,
-			      int tlv_type, u8 *pos, int len)
-{
-	switch (tlv_type) {
-	case EAP_TLV_EAP_PAYLOAD_TLV:
-		wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: EAP-Payload TLV",
-			    pos, len);
-		if (tlv->eap_payload_tlv) {
-			wpa_printf(MSG_DEBUG, "EAP-FAST: More than one "
-				   "EAP-Payload TLV in the message");
-			tlv->iresult = EAP_TLV_RESULT_FAILURE;
-			return -2;
-		}
-		tlv->eap_payload_tlv = pos;
-		tlv->eap_payload_tlv_len = len;
-		break;
-	case EAP_TLV_RESULT_TLV:
-		wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Result TLV", pos, len);
-		if (tlv->result) {
-			wpa_printf(MSG_DEBUG, "EAP-FAST: More than one "
-				   "Result TLV in the message");
-			tlv->result = EAP_TLV_RESULT_FAILURE;
-			return -2;
-		}
-		if (len < 2) {
-			wpa_printf(MSG_DEBUG, "EAP-FAST: Too short "
-				   "Result TLV");
-			tlv->result = EAP_TLV_RESULT_FAILURE;
-			break;
-		}
-		tlv->result = WPA_GET_BE16(pos);
-		if (tlv->result != EAP_TLV_RESULT_SUCCESS &&
-		    tlv->result != EAP_TLV_RESULT_FAILURE) {
-			wpa_printf(MSG_DEBUG, "EAP-FAST: Unknown Result %d",
-				   tlv->result);
-			tlv->result = EAP_TLV_RESULT_FAILURE;
-		}
-		wpa_printf(MSG_DEBUG, "EAP-FAST: Result: %s",
-			   tlv->result == EAP_TLV_RESULT_SUCCESS ?
-			   "Success" : "Failure");
-		break;
-	case EAP_TLV_INTERMEDIATE_RESULT_TLV:
-		wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Intermediate Result TLV",
-			    pos, len);
-		if (len < 2) {
-			wpa_printf(MSG_DEBUG, "EAP-FAST: Too short "
-				   "Intermediate-Result TLV");
-			tlv->iresult = EAP_TLV_RESULT_FAILURE;
-			break;
-		}
-		if (tlv->iresult) {
-			wpa_printf(MSG_DEBUG, "EAP-FAST: More than one "
-				   "Intermediate-Result TLV in the message");
-			tlv->iresult = EAP_TLV_RESULT_FAILURE;
-			return -2;
-		}
-		tlv->iresult = WPA_GET_BE16(pos);
-		if (tlv->iresult != EAP_TLV_RESULT_SUCCESS &&
-		    tlv->iresult != EAP_TLV_RESULT_FAILURE) {
-			wpa_printf(MSG_DEBUG, "EAP-FAST: Unknown Intermediate "
-				   "Result %d", tlv->iresult);
-			tlv->iresult = EAP_TLV_RESULT_FAILURE;
-		}
-		wpa_printf(MSG_DEBUG, "EAP-FAST: Intermediate Result: %s",
-			   tlv->iresult == EAP_TLV_RESULT_SUCCESS ?
-			   "Success" : "Failure");
-		break;
-	case EAP_TLV_CRYPTO_BINDING_TLV:
-		wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Crypto-Binding TLV",
-			    pos, len);
-		if (tlv->crypto_binding) {
-			wpa_printf(MSG_DEBUG, "EAP-FAST: More than one "
-				   "Crypto-Binding TLV in the message");
-			tlv->iresult = EAP_TLV_RESULT_FAILURE;
-			return -2;
-		}
-		tlv->crypto_binding_len = sizeof(struct eap_tlv_hdr) + len;
-		if (tlv->crypto_binding_len < sizeof(*tlv->crypto_binding)) {
-			wpa_printf(MSG_DEBUG, "EAP-FAST: Too short "
-				   "Crypto-Binding TLV");
-			tlv->iresult = EAP_TLV_RESULT_FAILURE;
-			return -2;
-		}
-		tlv->crypto_binding = (struct eap_tlv_crypto_binding__tlv *)
-			(pos - sizeof(struct eap_tlv_hdr));
-		break;
-	case EAP_TLV_REQUEST_ACTION_TLV:
-		wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Request-Action TLV",
-			    pos, len);
-		if (tlv->request_action) {
-			wpa_printf(MSG_DEBUG, "EAP-FAST: More than one "
-				   "Request-Action TLV in the message");
-			tlv->iresult = EAP_TLV_RESULT_FAILURE;
-			return -2;
-		}
-		if (len < 2) {
-			wpa_printf(MSG_DEBUG, "EAP-FAST: Too short "
-				   "Request-Action TLV");
-			tlv->iresult = EAP_TLV_RESULT_FAILURE;
-			break;
-		}
-		tlv->request_action = WPA_GET_BE16(pos);
-		wpa_printf(MSG_DEBUG, "EAP-FAST: Request-Action: %d",
-			   tlv->request_action);
-		break;
-	case EAP_TLV_PAC_TLV:
-		wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: PAC TLV", pos, len);
-		if (tlv->pac) {
-			wpa_printf(MSG_DEBUG, "EAP-FAST: More than one "
-				   "PAC TLV in the message");
-			tlv->iresult = EAP_TLV_RESULT_FAILURE;
-			return -2;
-		}
-		tlv->pac = pos;
-		tlv->pac_len = len;
-		break;
-	default:
-		/* Unknown TLV */
-		return -1;
-	}
-
-	return 0;
 }
 
 
@@ -1271,10 +1086,10 @@
 
 
 static int eap_fast_validate_crypto_binding(
-	struct eap_fast_data *data, struct eap_tlv_crypto_binding__tlv *b,
+	struct eap_fast_data *data, struct eap_tlv_crypto_binding_tlv *b,
 	size_t bind_len)
 {
-	u8 cmac[20];
+	u8 cmac[SHA1_MAC_LEN];
 
 	wpa_printf(MSG_DEBUG, "EAP-FAST: Reply Crypto-Binding TLV: "
 		   "Version %d Received Version %d SubType %d",
@@ -1311,7 +1126,8 @@
 	wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Crypto-Binding TLV for "
 		    "Compound MAC calculation",
 		    (u8 *) b, bind_len);
-	hmac_sha1(data->cmk, 20, (u8 *) b, bind_len, b->compound_mac);
+	hmac_sha1(data->cmk, EAP_FAST_CMK_LEN, (u8 *) b, bind_len,
+		  b->compound_mac);
 	if (os_memcmp(cmac, b->compound_mac, sizeof(cmac)) != 0) {
 		wpa_hexdump(MSG_MSGDUMP,
 			    "EAP-FAST: Calculated Compound MAC",
@@ -1388,11 +1204,6 @@
 		return;
 	}
 
-	if (tlv.eap_payload_tlv) {
-		eap_fast_process_phase2_eap(sm, data, tlv.eap_payload_tlv,
-					    tlv.eap_payload_tlv_len);
-	}
-
 	if (check_crypto_binding) {
 		if (tlv.crypto_binding == NULL) {
 			wpa_printf(MSG_DEBUG, "EAP-FAST: No Crypto-Binding "
@@ -1424,7 +1235,11 @@
 		}
 
 		wpa_printf(MSG_DEBUG, "EAP-FAST: Valid Crypto-Binding TLV "
-			   "received - authentication completed successfully");
+			   "received");
+		if (data->final_result) {
+			wpa_printf(MSG_DEBUG, "EAP-FAST: Authentication "
+				   "completed successfully");
+		}
 
 		if (data->anon_provisioning ||
 		    (tlv.request_action == EAP_TLV_ACTION_PROCESS_TLV &&
@@ -1437,19 +1252,29 @@
 			wpa_printf(MSG_DEBUG, "EAP-FAST: Server triggered "
 				   "re-keying of Tunnel PAC");
 			eap_fast_state(data, REQUEST_PAC);
-		} else
+		} else if (data->final_result)
 			eap_fast_state(data, SUCCESS);
+	}
+
+	if (tlv.eap_payload_tlv) {
+		eap_fast_process_phase2_eap(sm, data, tlv.eap_payload_tlv,
+					    tlv.eap_payload_tlv_len);
 	}
 }
 
 
 static void eap_fast_process_phase2(struct eap_sm *sm,
 				    struct eap_fast_data *data,
-				    const u8 *in_data, size_t in_len)
+				    struct wpabuf *in_buf)
 {
 	u8 *in_decrypted;
-	int len_decrypted, res;
+	int len_decrypted;
 	size_t buf_len;
+	u8 *in_data;
+	size_t in_len;
+
+	in_data = wpabuf_mhead(in_buf);
+	in_len = wpabuf_len(in_buf);
 
 	wpa_printf(MSG_DEBUG, "EAP-FAST: Received %lu bytes encrypted data for"
 		   " Phase 2", (unsigned long) in_len);
@@ -1465,20 +1290,17 @@
 		return;
 	}
 
-	/* FIX: get rid of const -> non-const typecast */
-	res = eap_server_tls_data_reassemble(sm, &data->ssl, (u8 **) &in_data,
-					     &in_len);
-	if (res < 0 || res == 1)
-		return;
-
 	buf_len = in_len;
-	if (data->ssl.tls_in_total > buf_len)
-		buf_len = data->ssl.tls_in_total;
+	/*
+	 * Even though we try to disable TLS compression, it is possible that
+	 * this cannot be done with all TLS libraries. Add extra buffer space
+	 * to handle the possibility of the decrypted data being longer than
+	 * input data.
+	 */
+	buf_len += 500;
+	buf_len *= 3;
 	in_decrypted = os_malloc(buf_len);
 	if (in_decrypted == NULL) {
-		os_free(data->ssl.tls_in);
-		data->ssl.tls_in = NULL;
-		data->ssl.tls_in_len = 0;
 		wpa_printf(MSG_WARNING, "EAP-FAST: Failed to allocate memory "
 			   "for decryption");
 		return;
@@ -1487,9 +1309,6 @@
 	len_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,
 					       in_data, in_len,
 					       in_decrypted, buf_len);
-	os_free(data->ssl.tls_in);
-	data->ssl.tls_in = NULL;
-	data->ssl.tls_in_len = 0;
 	if (len_decrypted < 0) {
 		wpa_printf(MSG_INFO, "EAP-FAST: Failed to decrypt Phase 2 "
 			   "data");
@@ -1515,105 +1334,125 @@
 }
 
 
-static void eap_fast_process(struct eap_sm *sm, void *priv,
-			     struct wpabuf *respData)
+static int eap_fast_process_version(struct eap_sm *sm, void *priv,
+				    int peer_version)
 {
 	struct eap_fast_data *data = priv;
-	const u8 *pos;
-	u8 flags;
-	size_t left;
-	unsigned int tls_msg_len;
-	int peer_version;
-
-	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_FAST, respData,
-			       &left);
-	if (pos == NULL || left < 1)
-		return;
-	flags = *pos++;
-	left--;
-	wpa_printf(MSG_DEBUG, "EAP-FAST: Received packet(len=%lu) - "
-		   "Flags 0x%02x", (unsigned long) wpabuf_len(respData),
-		   flags);
-	data->peer_version = peer_version = flags & EAP_PEAP_VERSION_MASK;
+
+	data->peer_version = peer_version;
+
 	if (data->force_version >= 0 && peer_version != data->force_version) {
 		wpa_printf(MSG_INFO, "EAP-FAST: peer did not select the forced"
 			   " version (forced=%d peer=%d) - reject",
 			   data->force_version, peer_version);
-		eap_fast_state(data, FAILURE);
-		return;
-	}
+		return -1;
+	}
+
 	if (peer_version < data->fast_version) {
 		wpa_printf(MSG_DEBUG, "EAP-FAST: peer ver=%d, own ver=%d; "
 			   "use version %d",
 			   peer_version, data->fast_version, peer_version);
 		data->fast_version = peer_version;
 	}
-	if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) {
-		if (left < 4) {
-			wpa_printf(MSG_INFO, "EAP-FAST: Short frame with TLS "
-				   "length");
-			eap_fast_state(data, FAILURE);
-			return;
-		}
-		tls_msg_len = WPA_GET_BE32(pos);
-		wpa_printf(MSG_DEBUG, "EAP-FAST: TLS Message Length: %d",
-			   tls_msg_len);
-		if (data->ssl.tls_in_left == 0) {
-			data->ssl.tls_in_total = tls_msg_len;
-			data->ssl.tls_in_left = tls_msg_len;
-			os_free(data->ssl.tls_in);
-			data->ssl.tls_in = NULL;
-			data->ssl.tls_in_len = 0;
-		}
-		pos += 4;
-		left -= 4;
-	}
+
+	return 0;
+}
+
+
+static int eap_fast_process_phase1(struct eap_sm *sm,
+				   struct eap_fast_data *data)
+{
+	if (eap_server_tls_phase1(sm, &data->ssl) < 0) {
+		wpa_printf(MSG_INFO, "EAP-FAST: TLS processing failed");
+		eap_fast_state(data, FAILURE);
+		return -1;
+	}
+
+	if (!tls_connection_established(sm->ssl_ctx, data->ssl.conn) ||
+	    wpabuf_len(data->ssl.out_buf) > 0)
+		return 1;
+
+	/*
+	 * Phase 1 was completed with the received message (e.g., when using
+	 * abbreviated handshake), so Phase 2 can be started immediately
+	 * without having to send through an empty message to the peer.
+	 */
+
+	return eap_fast_phase1_done(sm, data);
+}
+
+
+static void eap_fast_process_phase2_start(struct eap_sm *sm,
+					  struct eap_fast_data *data)
+{
+	u8 next_type;
+
+	if (data->identity) {
+		os_free(sm->identity);
+		sm->identity = data->identity;
+		data->identity = NULL;
+		sm->identity_len = data->identity_len;
+		data->identity_len = 0;
+		sm->require_identity_match = 1;
+		if (eap_user_get(sm, sm->identity, sm->identity_len, 1) != 0) {
+			wpa_hexdump_ascii(MSG_DEBUG, "EAP-FAST: "
+					  "Phase2 Identity not found "
+					  "in the user database",
+					  sm->identity, sm->identity_len);
+			next_type = eap_fast_req_failure(sm, data);
+		} else {
+			wpa_printf(MSG_DEBUG, "EAP-FAST: Identity already "
+				   "known - skip Phase 2 Identity Request");
+			next_type = sm->user->methods[0].method;
+			sm->user_eap_method_index = 1;
+		}
+
+		eap_fast_state(data, PHASE2_METHOD);
+	} else {
+		eap_fast_state(data, PHASE2_ID);
+		next_type = EAP_TYPE_IDENTITY;
+	}
+
+	eap_fast_phase2_init(sm, data, next_type);
+}
+
+
+static void eap_fast_process_msg(struct eap_sm *sm, void *priv,
+				 const struct wpabuf *respData)
+{
+	struct eap_fast_data *data = priv;
 
 	switch (data->state) {
 	case PHASE1:
-		if (eap_server_tls_process_helper(sm, &data->ssl, pos, left) <
-		    0) {
-			wpa_printf(MSG_INFO, "EAP-FAST: TLS processing "
-				   "failed");
-			eap_fast_state(data, FAILURE);
-		}
-
-		if (!tls_connection_established(sm->ssl_ctx, data->ssl.conn) ||
-		    data->ssl.tls_out_len > 0)
-			break;
-
-		/*
-		 * Phase 1 was completed with the received message (e.g., when
-		 * using abbreviated handshake), so Phase 2 can be started
-		 * immediately without having to send through an empty message
-		 * to the peer.
-		 */
-
-		if (eap_fast_phase1_done(sm, data) < 0)
+		if (eap_fast_process_phase1(sm, data))
 			break;
 
 		/* fall through to PHASE2_START */
 	case PHASE2_START:
-		eap_fast_state(data, PHASE2_ID);
-		eap_fast_phase2_init(sm, data, EAP_TYPE_IDENTITY);
+		eap_fast_process_phase2_start(sm, data);
 		break;
 	case PHASE2_ID:
 	case PHASE2_METHOD:
 	case CRYPTO_BINDING:
 	case REQUEST_PAC:
-		eap_fast_process_phase2(sm, data, pos, left);
+		eap_fast_process_phase2(sm, data, data->ssl.in_buf);
 		break;
 	default:
 		wpa_printf(MSG_DEBUG, "EAP-FAST: Unexpected state %d in %s",
 			   data->state, __func__);
 		break;
 	}
-
-	if (tls_connection_get_write_alerts(sm->ssl_ctx, data->ssl.conn) > 1) {
-		wpa_printf(MSG_INFO, "EAP-FAST: Locally detected fatal error "
-			   "in TLS processing");
+}
+
+
+static void eap_fast_process(struct eap_sm *sm, void *priv,
+			     struct wpabuf *respData)
+{
+	struct eap_fast_data *data = priv;
+	if (eap_server_tls_process(sm, &data->ssl, respData, data,
+				   EAP_TYPE_FAST, eap_fast_process_version,
+				   eap_fast_process_msg) < 0)
 		eap_fast_state(data, FAILURE);
-	}
 }
 
 
@@ -1632,20 +1471,11 @@
 	if (data->state != SUCCESS)
 		return NULL;
 
-	/*
-	 * RFC 4851, Section 5.4: EAP Master Session Key Genreration
-	 * MSK = T-PRF(S-IMCK[j], "Session Key Generating Function", 64)
-	 */
-
 	eapKeyData = os_malloc(EAP_FAST_KEY_LEN);
 	if (eapKeyData == NULL)
 		return NULL;
 
-	sha1_t_prf(data->simck, EAP_FAST_SIMCK_LEN,
-		   "Session Key Generating Function", (u8 *) "", 0,
-		   eapKeyData, EAP_FAST_KEY_LEN);
-	wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: Derived key (MSK)",
-			eapKeyData, EAP_FAST_KEY_LEN);
+	eap_fast_derive_eap_msk(data->simck, eapKeyData);
 	*len = EAP_FAST_KEY_LEN;
 
 	return eapKeyData;
@@ -1660,22 +1490,11 @@
 	if (data->state != SUCCESS)
 		return NULL;
 
-	/*
-	 * RFC 4851, Section 5.4: EAP Master Session Key Genreration
-	 * EMSK = T-PRF(S-IMCK[j],
-	 *        "Extended Session Key Generating Function", 64)
-	 */
-
 	eapKeyData = os_malloc(EAP_EMSK_LEN);
 	if (eapKeyData == NULL)
 		return NULL;
 
-	sha1_t_prf(data->simck, EAP_FAST_SIMCK_LEN,
-		   "Extended Session Key Generating Function",
-		   (u8 *) "", 0, eapKeyData, EAP_EMSK_LEN);
-	wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: Derived key (EMSK)",
-			eapKeyData, EAP_EMSK_LEN);
-
+	eap_fast_derive_eap_emsk(data->simck, eapKeyData);
 	*len = EAP_EMSK_LEN;
 
 	return eapKeyData;

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=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/eap_server/eap_gtc.c (original)
+++ wpasupplicant/trunk/src/eap_server/eap_gtc.c Sat Jun 14 00:40:26 2008
@@ -134,14 +134,26 @@
 
 		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 (sm->identity && sm->require_identity_match &&
+		    (pos2 - pos != (int) sm->identity_len ||
+		     os_memcmp(pos, sm->identity, sm->identity_len))) {
+			wpa_printf(MSG_DEBUG, "EAP-GTC: Phase 2 Identity did "
+				   "not match with required Identity");
+			wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-GTC: Expected "
+					  "identity",
+					  sm->identity, sm->identity_len);
+			data->state = FAILURE;
+			return;
+		} else {
+			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 "

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=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/eap_server/eap_i.h (original)
+++ wpasupplicant/trunk/src/eap_server/eap_i.h Sat Jun 14 00:40:26 2008
@@ -150,12 +150,13 @@
 	void *eap_method_priv;
 	u8 *identity;
 	size_t identity_len;
+	/* Whether Phase 2 method should validate identity match */
+	int require_identity_match;
 	int lastId; /* Identifier used in the last EAP-Packet */
 	struct eap_user *user;
 	int user_eap_method_index;
 	int init_phase2;
 	void *ssl_ctx;
-	enum { TLV_REQ_NONE, TLV_REQ_SUCCESS, TLV_REQ_FAILURE } tlv_request;
 	void *eap_sim_db_priv;
 	Boolean backend_auth;
 	Boolean update_user;
@@ -172,6 +173,7 @@
 	u8 *pac_opaque_encr_key;
 	char *eap_fast_a_id;
 	int eap_sim_aka_result_ind;
+	int tnc;
 };
 
 int eap_user_get(struct eap_sm *sm, const u8 *identity, size_t identity_len,

Modified: wpasupplicant/trunk/src/eap_server/eap_ikev2.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/eap_server/eap_ikev2.c?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/eap_server/eap_ikev2.c (original)
+++ wpasupplicant/trunk/src/eap_server/eap_ikev2.c Sat Jun 14 00:40:26 2008
@@ -416,6 +416,9 @@
 		else
 			eap_ikev2_state(data, FRAG_ACK);
 		return;
+	} else if (data->state == FRAG_ACK) {
+		wpa_printf(MSG_DEBUG, "EAP-TNC: All fragments received");
+		data->state = MSG;
 	}
 
 	if (data->in_buf == NULL) {

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=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/eap_server/eap_methods.c (original)
+++ wpasupplicant/trunk/src/eap_server/eap_methods.c Sat Jun 14 00:40:26 2008
@@ -261,6 +261,13 @@
 	}
 #endif /* EAP_IKEV2 */
 
+#ifdef EAP_TNC
+	if (ret == 0) {
+		int eap_server_tnc_register(void);
+		ret = eap_server_tnc_register();
+	}
+#endif /* EAP_TNC */
+
 	return ret;
 }
 

Modified: wpasupplicant/trunk/src/eap_server/eap_peap.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/eap_server/eap_peap.c?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/eap_server/eap_peap.c (original)
+++ wpasupplicant/trunk/src/eap_server/eap_peap.c Sat Jun 14 00:40:26 2008
@@ -15,10 +15,13 @@
 #include "includes.h"
 
 #include "common.h"
+#include "sha1.h"
 #include "eap_i.h"
 #include "eap_tls_common.h"
 #include "eap_common/eap_tlv_common.h"
+#include "eap_common/eap_peap_common.h"
 #include "tls.h"
+#include "tncs.h"
 
 
 /* Maximum supported PEAP version
@@ -36,15 +39,26 @@
 	struct eap_ssl_data ssl;
 	enum {
 		START, PHASE1, PHASE1_ID2, PHASE2_START, PHASE2_ID,
-		PHASE2_METHOD,
+		PHASE2_METHOD, PHASE2_SOH,
 		PHASE2_TLV, SUCCESS_REQ, FAILURE_REQ, SUCCESS, FAILURE
 	} state;
 
 	int peap_version;
+	int recv_version;
 	const struct eap_method *phase2_method;
 	void *phase2_priv;
 	int force_version;
 	struct wpabuf *pending_phase2_resp;
+	enum { TLV_REQ_NONE, TLV_REQ_SUCCESS, TLV_REQ_FAILURE } tlv_request;
+	int crypto_binding_sent;
+	int crypto_binding_used;
+	enum { NO_BINDING, OPTIONAL_BINDING, REQUIRE_BINDING } crypto_binding;
+	u8 binding_nonce[32];
+	u8 ipmk[40];
+	u8 cmk[20];
+	u8 *phase2_key;
+	size_t phase2_key_len;
+	struct wpabuf *soh_response;
 };
 
 
@@ -63,6 +77,8 @@
 		return "PHASE2_ID";
 	case PHASE2_METHOD:
 		return "PHASE2_METHOD";
+	case PHASE2_SOH:
+		return "PHASE2_SOH";
 	case PHASE2_TLV:
 		return "PHASE2_TLV";
 	case SUCCESS_REQ:
@@ -115,43 +131,37 @@
 }
 
 
-static EapType eap_peap_req_success(struct eap_sm *sm,
-				    struct eap_peap_data *data)
+static void eap_peap_req_success(struct eap_sm *sm,
+				 struct eap_peap_data *data)
 {
 	if (data->state == FAILURE || data->state == FAILURE_REQ) {
 		eap_peap_state(data, FAILURE);
-		return EAP_TYPE_NONE;
+		return;
 	}
 
 	if (data->peap_version == 0) {
-		sm->tlv_request = TLV_REQ_SUCCESS;
+		data->tlv_request = TLV_REQ_SUCCESS;
 		eap_peap_state(data, PHASE2_TLV);
-		return EAP_TYPE_TLV;
 	} else {
 		eap_peap_state(data, SUCCESS_REQ);
-		return EAP_TYPE_NONE;
-	}
-}
-
-
-static EapType eap_peap_req_failure(struct eap_sm *sm,
-				    struct eap_peap_data *data)
+	}
+}
+
+
+static void eap_peap_req_failure(struct eap_sm *sm,
+				 struct eap_peap_data *data)
 {
 	if (data->state == FAILURE || data->state == FAILURE_REQ ||
-	    data->state == SUCCESS_REQ ||
-	    (data->phase2_method &&
-	     data->phase2_method->method == EAP_TYPE_TLV)) {
+	    data->state == SUCCESS_REQ || data->tlv_request != TLV_REQ_NONE) {
 		eap_peap_state(data, FAILURE);
-		return EAP_TYPE_NONE;
+		return;
 	}
 
 	if (data->peap_version == 0) {
-		sm->tlv_request = TLV_REQ_FAILURE;
+		data->tlv_request = TLV_REQ_FAILURE;
 		eap_peap_state(data, PHASE2_TLV);
-		return EAP_TYPE_TLV;
 	} else {
 		eap_peap_state(data, FAILURE_REQ);
-		return EAP_TYPE_NONE;
 	}
 }
 
@@ -172,6 +182,7 @@
 		data->peap_version = data->force_version;
 	}
 	data->state = START;
+	data->crypto_binding = OPTIONAL_BINDING;
 
 	if (eap_server_tls_ssl_init(sm, &data->ssl, 0)) {
 		wpa_printf(MSG_INFO, "EAP-PEAP: Failed to initialize SSL.");
@@ -192,6 +203,8 @@
 		data->phase2_method->reset(sm, data->phase2_priv);
 	eap_server_tls_ssl_deinit(sm, &data->ssl);
 	wpabuf_free(data->pending_phase2_resp);
+	os_free(data->phase2_key);
+	wpabuf_free(data->soh_response);
 	os_free(data);
 }
 
@@ -218,64 +231,6 @@
 }
 
 
-static struct wpabuf * eap_peap_build_req(struct eap_sm *sm,
-					  struct eap_peap_data *data, u8 id)
-{
-	int res;
-	struct wpabuf *req;
-
-	res = eap_server_tls_buildReq_helper(sm, &data->ssl, EAP_TYPE_PEAP,
-					     data->peap_version, id, &req);
-
-	if (data->peap_version < 2 &&
-	    tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
-		wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase1 done, starting "
-			   "Phase2");
-		eap_peap_state(data, PHASE2_START);
-	}
-
-	if (res == 1)
-		return eap_server_tls_build_ack(id, EAP_TYPE_PEAP,
-						data->peap_version);
-	return req;
-}
-
-
-static struct wpabuf * eap_peap_encrypt(struct eap_sm *sm,
-					struct eap_peap_data *data,
-					u8 id, const u8 *plain,
-					size_t plain_len)
-{
-	int res;
-	struct wpabuf *buf;
-
-	/* TODO: add support for fragmentation, if needed. This will need to
-	 * add TLS Message Length field, if the frame is fragmented. */
-	buf = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PEAP,
-			    1 + data->ssl.tls_out_limit,
-			    EAP_CODE_REQUEST, id);
-	if (buf == NULL)
-		return NULL;
-
-	wpabuf_put_u8(buf, data->peap_version);
-
-	res = tls_connection_encrypt(sm->ssl_ctx, data->ssl.conn,
-				     plain, plain_len, wpabuf_put(buf, 0),
-				     data->ssl.tls_out_limit);
-	if (res < 0) {
-		wpa_printf(MSG_INFO, "EAP-PEAP: Failed to encrypt Phase 2 "
-			   "data");
-		wpabuf_free(buf);
-		return NULL;
-	}
-
-	wpabuf_put(buf, res);
-	eap_update_len(buf);
-
-	return buf;
-}
-
-
 static struct wpabuf * eap_peap_build_phase2_req(struct eap_sm *sm,
 						 struct eap_peap_data *data,
 						 u8 id)
@@ -284,6 +239,10 @@
 	const u8 *req;
 	size_t req_len;
 
+	if (data->phase2_method == NULL || data->phase2_priv == NULL) {
+		wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 method not ready");
+		return NULL;
+	}
 	buf = data->phase2_method->buildReq(sm, data->phase2_priv, id);
 	if (data->peap_version >= 2 && buf)
 		buf = eap_peapv2_tlv_eap_payload(buf);
@@ -301,7 +260,198 @@
 		req_len -= sizeof(struct eap_hdr);
 	}
 
-	encr_req = eap_peap_encrypt(sm, data, id, req, req_len);
+	encr_req = eap_server_tls_encrypt(sm, &data->ssl, req, req_len);
+	wpabuf_free(buf);
+
+	return encr_req;
+}
+
+
+#ifdef EAP_TNC
+static struct wpabuf * eap_peap_build_phase2_soh(struct eap_sm *sm,
+						 struct eap_peap_data *data,
+						 u8 id)
+{
+	struct wpabuf *buf1, *buf, *encr_req;
+	const u8 *req;
+	size_t req_len;
+
+	buf1 = tncs_build_soh_request();
+	if (buf1 == NULL)
+		return NULL;
+
+	buf = eap_msg_alloc(EAP_VENDOR_MICROSOFT, 0x21, wpabuf_len(buf1),
+			    EAP_CODE_REQUEST, id);
+	if (buf == NULL) {
+		wpabuf_free(buf1);
+		return NULL;
+	}
+	wpabuf_put_buf(buf, buf1);
+	wpabuf_free(buf1);
+
+	req = wpabuf_head(buf);
+	req_len = wpabuf_len(buf);
+
+	wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 SOH data",
+			req, req_len);
+
+	req += sizeof(struct eap_hdr);
+	req_len -= sizeof(struct eap_hdr);
+
+	encr_req = eap_server_tls_encrypt(sm, &data->ssl, req, req_len);
+	wpabuf_free(buf);
+
+	return encr_req;
+}
+#endif /* EAP_TNC */
+
+
+static void eap_peap_get_isk(struct eap_peap_data *data,
+			     u8 *isk, size_t isk_len)
+{
+	size_t key_len;
+
+	os_memset(isk, 0, isk_len);
+	if (data->phase2_key == NULL)
+		return;
+
+	key_len = data->phase2_key_len;
+	if (key_len > isk_len)
+		key_len = isk_len;
+	os_memcpy(isk, data->phase2_key, key_len);
+}
+
+
+static int eap_peap_derive_cmk(struct eap_sm *sm, struct eap_peap_data *data)
+{
+	u8 *tk;
+	u8 isk[32], imck[60];
+
+	/*
+	 * Tunnel key (TK) is the first 60 octets of the key generated by
+	 * phase 1 of PEAP (based on TLS).
+	 */
+	tk = eap_server_tls_derive_key(sm, &data->ssl, "client EAP encryption",
+				       EAP_TLS_KEY_LEN);
+	if (tk == NULL)
+		return -1;
+	wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TK", tk, 60);
+
+	eap_peap_get_isk(data, isk, sizeof(isk));
+	wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: ISK", isk, sizeof(isk));
+
+	/*
+	 * IPMK Seed = "Inner Methods Compound Keys" | ISK
+	 * TempKey = First 40 octets of TK
+	 * IPMK|CMK = PRF+(TempKey, IPMK Seed, 60)
+	 * (note: draft-josefsson-pppext-eap-tls-eap-10.txt includes a space
+	 * in the end of the label just before ISK; is that just a typo?)
+	 */
+	wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TempKey", tk, 40);
+	peap_prfplus(data->peap_version, tk, 40, "Inner Methods Compound Keys",
+		     isk, sizeof(isk), imck, sizeof(imck));
+	wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IMCK (IPMKj)",
+			imck, sizeof(imck));
+
+	os_free(tk);
+
+	/* TODO: fast-connect: IPMK|CMK = TK */
+	os_memcpy(data->ipmk, imck, 40);
+	wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IPMK (S-IPMKj)", data->ipmk, 40);
+	os_memcpy(data->cmk, imck + 40, 20);
+	wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK (CMKj)", data->cmk, 20);
+
+	return 0;
+}
+
+
+static struct wpabuf * eap_peap_build_phase2_tlv(struct eap_sm *sm,
+						 struct eap_peap_data *data,
+						 u8 id)
+{
+	struct wpabuf *buf, *encr_req;
+	size_t len;
+
+	len = 6; /* Result TLV */
+	if (data->crypto_binding != NO_BINDING)
+		len += 60; /* Cryptobinding TLV */
+#ifdef EAP_TNC
+	if (data->soh_response)
+		len += wpabuf_len(data->soh_response);
+#endif /* EAP_TNC */
+
+	buf = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLV, len,
+			    EAP_CODE_REQUEST, id);
+	if (buf == NULL)
+		return NULL;
+
+	wpabuf_put_u8(buf, 0x80); /* Mandatory */
+	wpabuf_put_u8(buf, EAP_TLV_RESULT_TLV);
+	/* Length */
+	wpabuf_put_be16(buf, 2);
+	/* Status */
+	wpabuf_put_be16(buf, data->tlv_request == TLV_REQ_SUCCESS ?
+			EAP_TLV_RESULT_SUCCESS : EAP_TLV_RESULT_FAILURE);
+
+	if (data->peap_version == 0 && data->tlv_request == TLV_REQ_SUCCESS &&
+	    data->crypto_binding != NO_BINDING) {
+		u8 *mac;
+		u8 eap_type = EAP_TYPE_PEAP;
+		const u8 *addr[2];
+		size_t len[2];
+		u16 tlv_type;
+
+#ifdef EAP_TNC
+		if (data->soh_response) {
+			wpa_printf(MSG_DEBUG, "EAP-PEAP: Adding MS-SOH "
+				   "Response TLV");
+			wpabuf_put_buf(buf, data->soh_response);
+			wpabuf_free(data->soh_response);
+			data->soh_response = NULL;
+		}
+#endif /* EAP_TNC */
+
+		if (eap_peap_derive_cmk(sm, data) < 0 ||
+		    os_get_random(data->binding_nonce, 32)) {
+			wpabuf_free(buf);
+			return NULL;
+		}
+
+		/* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */
+		addr[0] = wpabuf_put(buf, 0);
+		len[0] = 60;
+		addr[1] = &eap_type;
+		len[1] = 1;
+
+		tlv_type = EAP_TLV_CRYPTO_BINDING_TLV;
+		if (data->peap_version >= 2)
+			tlv_type |= EAP_TLV_TYPE_MANDATORY;
+		wpabuf_put_be16(buf, tlv_type);
+		wpabuf_put_be16(buf, 56);
+
+		wpabuf_put_u8(buf, 0); /* Reserved */
+		wpabuf_put_u8(buf, data->peap_version); /* Version */
+		wpabuf_put_u8(buf, data->recv_version); /* RecvVersion */
+		wpabuf_put_u8(buf, 0); /* SubType: 0 = Request, 1 = Response */
+		wpabuf_put_data(buf, data->binding_nonce, 32); /* Nonce */
+		mac = wpabuf_put(buf, 20); /* Compound_MAC */
+		wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC CMK",
+			    data->cmk, 20);
+		wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 1",
+			    addr[0], len[0]);
+		wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 2",
+			    addr[1], len[1]);
+		hmac_sha1_vector(data->cmk, 20, 2, addr, len, mac);
+		wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC",
+			    mac, SHA1_MAC_LEN);
+		data->crypto_binding_sent = 1;
+	}
+
+	wpa_hexdump_buf_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 TLV data",
+			    buf);
+
+	encr_req = eap_server_tls_encrypt(sm, &data->ssl, wpabuf_head(buf),
+					  wpabuf_len(buf));
 	wpabuf_free(buf);
 
 	return encr_req;
@@ -328,7 +478,7 @@
 	wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 data",
 			(u8 *) hdr, req_len);
 
-	encr_req = eap_peap_encrypt(sm, data, id, (u8 *) hdr, req_len);
+	encr_req = eap_server_tls_encrypt(sm, &data->ssl, (u8 *) hdr, req_len);
 	os_free(hdr);
 
 	return encr_req;
@@ -338,26 +488,67 @@
 static struct wpabuf * eap_peap_buildReq(struct eap_sm *sm, void *priv, u8 id)
 {
 	struct eap_peap_data *data = priv;
+
+	if (data->ssl.state == FRAG_ACK) {
+		return eap_server_tls_build_ack(id, EAP_TYPE_PEAP,
+						data->peap_version);
+	}
+
+	if (data->ssl.state == WAIT_FRAG_ACK) {
+		return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_PEAP,
+						data->peap_version, id);
+	}
 
 	switch (data->state) {
 	case START:
 		return eap_peap_build_start(sm, data, id);
 	case PHASE1:
 	case PHASE1_ID2:
-		return eap_peap_build_req(sm, data, id);
+		if (data->peap_version < 2 &&
+		    tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
+			wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase1 done, "
+				   "starting Phase2");
+			eap_peap_state(data, PHASE2_START);
+		}
+		break;
 	case PHASE2_ID:
 	case PHASE2_METHOD:
+		wpabuf_free(data->ssl.out_buf);
+		data->ssl.out_used = 0;
+		data->ssl.out_buf = eap_peap_build_phase2_req(sm, data, id);
+		break;
+#ifdef EAP_TNC
+	case PHASE2_SOH:
+		wpabuf_free(data->ssl.out_buf);
+		data->ssl.out_used = 0;
+		data->ssl.out_buf = eap_peap_build_phase2_soh(sm, data, id);
+		break;
+#endif /* EAP_TNC */
 	case PHASE2_TLV:
-		return eap_peap_build_phase2_req(sm, data, id);
+		wpabuf_free(data->ssl.out_buf);
+		data->ssl.out_used = 0;
+		data->ssl.out_buf = eap_peap_build_phase2_tlv(sm, data, id);
+		break;
 	case SUCCESS_REQ:
-		return eap_peap_build_phase2_term(sm, data, id, 1);
+		wpabuf_free(data->ssl.out_buf);
+		data->ssl.out_used = 0;
+		data->ssl.out_buf = eap_peap_build_phase2_term(sm, data, id,
+							       1);
+		break;
 	case FAILURE_REQ:
-		return eap_peap_build_phase2_term(sm, data, id, 0);
+		wpabuf_free(data->ssl.out_buf);
+		data->ssl.out_used = 0;
+		data->ssl.out_buf = eap_peap_build_phase2_term(sm, data, id,
+							       0);
+		break;
 	default:
 		wpa_printf(MSG_DEBUG, "EAP-PEAP: %s - unexpected state %d",
 			   __func__, data->state);
 		return NULL;
 	}
+
+	return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_PEAP,
+					data->peap_version, id);
 }
 
 
@@ -397,6 +588,306 @@
 }
 
 
+static int eap_tlv_validate_cryptobinding(struct eap_sm *sm,
+					  struct eap_peap_data *data,
+					  const u8 *crypto_tlv,
+					  size_t crypto_tlv_len)
+{
+	u8 buf[61], mac[SHA1_MAC_LEN];
+	const u8 *pos;
+
+	if (crypto_tlv_len != 4 + 56) {
+		wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid cryptobinding TLV "
+			   "length %d", (int) crypto_tlv_len);
+		return -1;
+	}
+
+	pos = crypto_tlv;
+	pos += 4; /* TLV header */
+	if (pos[1] != data->peap_version) {
+		wpa_printf(MSG_DEBUG, "EAP-PEAP: Cryptobinding TLV Version "
+			   "mismatch (was %d; expected %d)",
+			   pos[1], data->peap_version);
+		return -1;
+	}
+
+	if (pos[3] != 1) {
+		wpa_printf(MSG_DEBUG, "EAP-PEAP: Unexpected Cryptobinding TLV "
+			   "SubType %d", pos[3]);
+		return -1;
+	}
+	pos += 4;
+	pos += 32; /* Nonce */
+
+	/* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */
+	os_memcpy(buf, crypto_tlv, 60);
+	os_memset(buf + 4 + 4 + 32, 0, 20); /* Compound_MAC */
+	buf[60] = EAP_TYPE_PEAP;
+	hmac_sha1(data->cmk, 20, buf, sizeof(buf), mac);
+
+	if (os_memcmp(mac, pos, SHA1_MAC_LEN) != 0) {
+		wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid Compound_MAC in "
+			   "cryptobinding TLV");
+		wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK", data->cmk, 20);
+		wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Cryptobinding seed data",
+			    buf, 61);
+		return -1;
+	}
+
+	wpa_printf(MSG_DEBUG, "EAP-PEAP: Valid cryptobinding TLV received");
+
+	return 0;
+}
+
+
+static void eap_peap_process_phase2_tlv(struct eap_sm *sm,
+					struct eap_peap_data *data,
+					struct wpabuf *in_data)
+{
+	const u8 *pos;
+	size_t left;
+	const u8 *result_tlv = NULL, *crypto_tlv = NULL;
+	size_t result_tlv_len = 0, crypto_tlv_len = 0;
+	int tlv_type, mandatory, tlv_len;
+
+	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TLV, in_data, &left);
+	if (pos == NULL) {
+		wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid EAP-TLV header");
+		return;
+	}
+
+	/* Parse TLVs */
+	wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Received TLVs", pos, left);
+	while (left >= 4) {
+		mandatory = !!(pos[0] & 0x80);
+		tlv_type = pos[0] & 0x3f;
+		tlv_type = (tlv_type << 8) | pos[1];
+		tlv_len = ((int) pos[2] << 8) | pos[3];
+		pos += 4;
+		left -= 4;
+		if ((size_t) tlv_len > left) {
+			wpa_printf(MSG_DEBUG, "EAP-PEAP: TLV underrun "
+				   "(tlv_len=%d left=%lu)", tlv_len,
+				   (unsigned long) left);
+			eap_peap_state(data, FAILURE);
+			return;
+		}
+		switch (tlv_type) {
+		case EAP_TLV_RESULT_TLV:
+			result_tlv = pos;
+			result_tlv_len = tlv_len;
+			break;
+		case EAP_TLV_CRYPTO_BINDING_TLV:
+			crypto_tlv = pos;
+			crypto_tlv_len = tlv_len;
+			break;
+		default:
+			wpa_printf(MSG_DEBUG, "EAP-PEAP: Unsupported TLV Type "
+				   "%d%s", tlv_type,
+				   mandatory ? " (mandatory)" : "");
+			if (mandatory) {
+				eap_peap_state(data, FAILURE);
+				return;
+			}
+			/* Ignore this TLV, but process other TLVs */
+			break;
+		}
+
+		pos += tlv_len;
+		left -= tlv_len;
+	}
+	if (left) {
+		wpa_printf(MSG_DEBUG, "EAP-PEAP: Last TLV too short in "
+			   "Request (left=%lu)", (unsigned long) left);
+		eap_peap_state(data, FAILURE);
+		return;
+	}
+
+	/* Process supported TLVs */
+	if (crypto_tlv && data->crypto_binding_sent) {
+		wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Cryptobinding TLV",
+			    crypto_tlv, crypto_tlv_len);
+		if (eap_tlv_validate_cryptobinding(sm, data, crypto_tlv - 4,
+						   crypto_tlv_len + 4) < 0) {
+			eap_peap_state(data, FAILURE);
+			return;
+		}
+		data->crypto_binding_used = 1;
+	} else if (!crypto_tlv && data->crypto_binding_sent &&
+		   data->crypto_binding == REQUIRE_BINDING) {
+		wpa_printf(MSG_DEBUG, "EAP-PEAP: No cryptobinding TLV");
+		eap_peap_state(data, FAILURE);
+		return;
+	}
+
+	if (result_tlv) {
+		int status;
+		const char *requested;
+
+		wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Result TLV",
+			    result_tlv, result_tlv_len);
+		if (result_tlv_len < 2) {
+			wpa_printf(MSG_INFO, "EAP-PEAP: Too short Result TLV "
+				   "(len=%lu)",
+				   (unsigned long) result_tlv_len);
+			eap_peap_state(data, FAILURE);
+			return;
+		}
+		requested = data->tlv_request == TLV_REQ_SUCCESS ? "Success" :
+			"Failure";
+		status = WPA_GET_BE16(result_tlv);
+		if (status == EAP_TLV_RESULT_SUCCESS) {
+			wpa_printf(MSG_INFO, "EAP-PEAP: TLV Result - Success "
+				   "- requested %s", requested);
+			if (data->tlv_request == TLV_REQ_SUCCESS)
+				eap_peap_state(data, SUCCESS);
+			else
+				eap_peap_state(data, FAILURE);
+			
+		} else if (status == EAP_TLV_RESULT_FAILURE) {
+			wpa_printf(MSG_INFO, "EAP-PEAP: TLV Result - Failure "
+				   "- requested %s", requested);
+			eap_peap_state(data, FAILURE);
+		} else {
+			wpa_printf(MSG_INFO, "EAP-PEAP: Unknown TLV Result "
+				   "Status %d", status);
+			eap_peap_state(data, FAILURE);
+		}
+	}
+}
+
+
+#ifdef EAP_TNC
+static void eap_peap_process_phase2_soh(struct eap_sm *sm,
+					struct eap_peap_data *data,
+					struct wpabuf *in_data)
+{
+	const u8 *pos, *vpos;
+	size_t left;
+	const u8 *soh_tlv = NULL;
+	size_t soh_tlv_len = 0;
+	int tlv_type, mandatory, tlv_len, vtlv_len;
+	u8 next_type;
+	u32 vendor_id;
+
+	pos = eap_hdr_validate(EAP_VENDOR_MICROSOFT, 0x21, in_data, &left);
+	if (pos == NULL) {
+		wpa_printf(MSG_DEBUG, "EAP-PEAP: Not a valid SoH EAP "
+			   "Extensions Method header - skip TNC");
+		goto auth_method;
+	}
+
+	/* Parse TLVs */
+	wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Received TLVs (SoH)", pos, left);
+	while (left >= 4) {
+		mandatory = !!(pos[0] & 0x80);
+		tlv_type = pos[0] & 0x3f;
+		tlv_type = (tlv_type << 8) | pos[1];
+		tlv_len = ((int) pos[2] << 8) | pos[3];
+		pos += 4;
+		left -= 4;
+		if ((size_t) tlv_len > left) {
+			wpa_printf(MSG_DEBUG, "EAP-PEAP: TLV underrun "
+				   "(tlv_len=%d left=%lu)", tlv_len,
+				   (unsigned long) left);
+			eap_peap_state(data, FAILURE);
+			return;
+		}
+		switch (tlv_type) {
+		case EAP_TLV_VENDOR_SPECIFIC_TLV:
+			if (tlv_len < 4) {
+				wpa_printf(MSG_DEBUG, "EAP-PEAP: Too short "
+					   "vendor specific TLV (len=%d)",
+					   (int) tlv_len);
+				eap_peap_state(data, FAILURE);
+				return;
+			}
+
+			vendor_id = WPA_GET_BE32(pos);
+			if (vendor_id != EAP_VENDOR_MICROSOFT) {
+				if (mandatory) {
+					eap_peap_state(data, FAILURE);
+					return;
+				}
+				break;
+			}
+
+			vpos = pos + 4;
+			mandatory = !!(vpos[0] & 0x80);
+			tlv_type = vpos[0] & 0x3f;
+			tlv_type = (tlv_type << 8) | vpos[1];
+			vtlv_len = ((int) vpos[2] << 8) | vpos[3];
+			vpos += 4;
+			if (vpos + vtlv_len > pos + left) {
+				wpa_printf(MSG_DEBUG, "EAP-PEAP: Vendor TLV "
+					   "underrun");
+				eap_peap_state(data, FAILURE);
+				return;
+			}
+
+			if (tlv_type == 1) {
+				soh_tlv = vpos;
+				soh_tlv_len = vtlv_len;
+				break;
+			}
+
+			wpa_printf(MSG_DEBUG, "EAP-PEAP: Unsupported MS-TLV "
+				   "Type %d%s", tlv_type,
+				   mandatory ? " (mandatory)" : "");
+			if (mandatory) {
+				eap_peap_state(data, FAILURE);
+				return;
+			}
+			/* Ignore this TLV, but process other TLVs */
+			break;
+		default:
+			wpa_printf(MSG_DEBUG, "EAP-PEAP: Unsupported TLV Type "
+				   "%d%s", tlv_type,
+				   mandatory ? " (mandatory)" : "");
+			if (mandatory) {
+				eap_peap_state(data, FAILURE);
+				return;
+			}
+			/* Ignore this TLV, but process other TLVs */
+			break;
+		}
+
+		pos += tlv_len;
+		left -= tlv_len;
+	}
+	if (left) {
+		wpa_printf(MSG_DEBUG, "EAP-PEAP: Last TLV too short in "
+			   "Request (left=%lu)", (unsigned long) left);
+		eap_peap_state(data, FAILURE);
+		return;
+	}
+
+	/* Process supported TLVs */
+	if (soh_tlv) {
+		int failure = 0;
+		wpabuf_free(data->soh_response);
+		data->soh_response = tncs_process_soh(soh_tlv, soh_tlv_len,
+						      &failure);
+		if (failure) {
+			eap_peap_state(data, FAILURE);
+			return;
+		}
+	} else {
+		wpa_printf(MSG_DEBUG, "EAP-PEAP: No SoH TLV received");
+		eap_peap_state(data, FAILURE);
+		return;
+	}
+
+auth_method:
+	eap_peap_state(data, PHASE2_METHOD);
+	next_type = sm->user->methods[0].method;
+	sm->user_eap_method_index = 1;
+	wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP type %d", next_type);
+	eap_peap_phase2_init(sm, data, next_type);
+}
+#endif /* EAP_TNC */
+
+
 static void eap_peap_process_phase2_response(struct eap_sm *sm,
 					     struct eap_peap_data *data,
 					     struct wpabuf *in_data)
@@ -405,6 +896,18 @@
 	const struct eap_hdr *hdr;
 	const u8 *pos;
 	size_t left;
+
+	if (data->state == PHASE2_TLV) {
+		eap_peap_process_phase2_tlv(sm, data, in_data);
+		return;
+	}
+
+#ifdef EAP_TNC
+	if (data->state == PHASE2_SOH) {
+		eap_peap_process_phase2_soh(sm, data, in_data);
+		return;
+	}
+#endif /* EAP_TNC */
 
 	if (data->phase2_priv == NULL) {
 		wpa_printf(MSG_DEBUG, "EAP-PEAP: %s - Phase2 not "
@@ -428,7 +931,8 @@
 			wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP type %d",
 				   next_type);
 		} else {
-			next_type = eap_peap_req_failure(sm, data);
+			eap_peap_req_failure(sm, data);
+			next_type = EAP_TYPE_NONE;
 		}
 		eap_peap_phase2_init(sm, data, next_type);
 		return;
@@ -454,22 +958,64 @@
 
 	if (!data->phase2_method->isSuccess(sm, data->phase2_priv)) {
 		wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 method failed");
-		next_type = eap_peap_req_failure(sm, data);
+		eap_peap_req_failure(sm, data);
+		next_type = EAP_TYPE_NONE;
 		eap_peap_phase2_init(sm, data, next_type);
 		return;
+	}
+
+	os_free(data->phase2_key);
+	if (data->phase2_method->getKey) {
+		data->phase2_key = data->phase2_method->getKey(
+			sm, data->phase2_priv, &data->phase2_key_len);
+		if (data->phase2_key == NULL) {
+			wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 getKey "
+				   "failed");
+			eap_peap_req_failure(sm, data);
+			eap_peap_phase2_init(sm, data, EAP_TYPE_NONE);
+			return;
+		}
+
+		if (data->phase2_key_len == 32 &&
+		    data->phase2_method->vendor == EAP_VENDOR_IETF &&
+		    data->phase2_method->method == EAP_TYPE_MSCHAPV2) {
+			/*
+			 * Microsoft uses reverse order for MS-MPPE keys in
+			 * EAP-PEAP when compared to EAP-FAST derivation of
+			 * ISK. Swap the keys here to get the correct ISK for
+			 * EAP-PEAPv0 cryptobinding.
+			 */
+			u8 tmp[16];
+			os_memcpy(tmp, data->phase2_key, 16);
+			os_memcpy(data->phase2_key, data->phase2_key + 16, 16);
+			os_memcpy(data->phase2_key + 16, tmp, 16);
+		}
 	}
 
 	switch (data->state) {
 	case PHASE1_ID2:
 	case PHASE2_ID:
+	case PHASE2_SOH:
 		if (eap_user_get(sm, sm->identity, sm->identity_len, 1) != 0) {
 			wpa_hexdump_ascii(MSG_DEBUG, "EAP_PEAP: Phase2 "
 					  "Identity not found in the user "
 					  "database",
 					  sm->identity, sm->identity_len);
-			next_type = eap_peap_req_failure(sm, data);
+			eap_peap_req_failure(sm, data);
+			next_type = EAP_TYPE_NONE;
 			break;
 		}
+
+#ifdef EAP_TNC
+		if (data->state != PHASE2_SOH && sm->tnc &&
+		    data->peap_version == 0) {
+			eap_peap_state(data, PHASE2_SOH);
+			wpa_printf(MSG_DEBUG, "EAP-PEAP: Try to initialize "
+				   "TNC (NAP SOH)");
+			next_type = EAP_TYPE_NONE;
+			break;
+		}
+#endif /* EAP_TNC */
 
 		eap_peap_state(data, PHASE2_METHOD);
 		next_type = sm->user->methods[0].method;
@@ -477,15 +1023,8 @@
 		wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP type %d", next_type);
 		break;
 	case PHASE2_METHOD:
-		next_type = eap_peap_req_success(sm, data);
-		break;
-	case PHASE2_TLV:
-		if (sm->tlv_request == TLV_REQ_SUCCESS ||
-		    data->state == SUCCESS_REQ) {
-			eap_peap_state(data, SUCCESS);
-		} else {
-			eap_peap_state(data, FAILURE);
-		}
+		eap_peap_req_success(sm, data);
+		next_type = EAP_TYPE_NONE;
 		break;
 	case FAILURE:
 		break;
@@ -502,12 +1041,17 @@
 static void eap_peap_process_phase2(struct eap_sm *sm,
 				    struct eap_peap_data *data,
 				    const struct wpabuf *respData,
-				    const u8 *in_data, size_t in_len)
+				    struct wpabuf *in_buf)
 {
 	struct wpabuf *in_decrypted;
-	int len_decrypted, res;
+	int len_decrypted;
 	const struct eap_hdr *hdr;
 	size_t buf_len, len;
+	u8 *in_data;
+	size_t in_len;
+
+	in_data = wpabuf_mhead(in_buf);
+	in_len = wpabuf_len(in_buf);
 
 	wpa_printf(MSG_DEBUG, "EAP-PEAP: received %lu bytes encrypted data for"
 		   " Phase 2", (unsigned long) in_len);
@@ -522,20 +1066,17 @@
 		return;
 	}
 
-	/* FIX: get rid of const -> non-const typecast */
-	res = eap_server_tls_data_reassemble(sm, &data->ssl, (u8 **) &in_data,
-					     &in_len);
-	if (res < 0 || res == 1)
-		return;
-
 	buf_len = in_len;
-	if (data->ssl.tls_in_total > buf_len)
-		buf_len = data->ssl.tls_in_total;
+	/*
+	 * Even though we try to disable TLS compression, it is possible that
+	 * this cannot be done with all TLS libraries. Add extra buffer space
+	 * to handle the possibility of the decrypted data being longer than
+	 * input data.
+	 */
+	buf_len += 500;
+	buf_len *= 3;
 	in_decrypted = wpabuf_alloc(buf_len);
 	if (in_decrypted == NULL) {
-		os_free(data->ssl.tls_in);
-		data->ssl.tls_in = NULL;
-		data->ssl.tls_in_len = 0;
 		wpa_printf(MSG_WARNING, "EAP-PEAP: failed to allocate memory "
 			   "for decryption");
 		return;
@@ -545,9 +1086,6 @@
 					       in_data, in_len,
 					       wpabuf_mhead(in_decrypted),
 					       buf_len);
-	os_free(data->ssl.tls_in);
-	data->ssl.tls_in = NULL;
-	data->ssl.tls_in_len = 0;
 	if (len_decrypted < 0) {
 		wpa_printf(MSG_INFO, "EAP-PEAP: Failed to decrypt Phase 2 "
 			   "data");
@@ -677,7 +1215,6 @@
 {
 	struct wpabuf *buf, *buf2;
 	int res;
-	u8 *tls_out;
 
 	wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Phase1 done, include first Phase2 "
 		   "payload in the same message");
@@ -720,50 +1257,28 @@
 			buf);
 
 	/* Append TLS data into the pending buffer after the Server Finished */
-	tls_out = os_realloc(data->ssl.tls_out,
-			     data->ssl.tls_out_len + wpabuf_len(buf));
-	if (tls_out == NULL) {
+	if (wpabuf_resize(&data->ssl.out_buf, wpabuf_len(buf)) < 0) {
 		wpabuf_free(buf);
 		return -1;
 	}
-
-	os_memcpy(tls_out + data->ssl.tls_out_len, wpabuf_head(buf),
-		  wpabuf_len(buf));
-	data->ssl.tls_out = tls_out;
-	data->ssl.tls_out_len += wpabuf_len(buf);
-
+	wpabuf_put_buf(data->ssl.out_buf, buf);
 	wpabuf_free(buf);
 
 	return 0;
 }
 
 
-static void eap_peap_process(struct eap_sm *sm, void *priv,
-			     struct wpabuf *respData)
+static int eap_peap_process_version(struct eap_sm *sm, void *priv,
+				    int peer_version)
 {
 	struct eap_peap_data *data = priv;
-	const u8 *pos;
-	u8 flags;
-	size_t left;
-	unsigned int tls_msg_len;
-	int peer_version;
-
-	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PEAP, respData,
-			       &left);
-	if (pos == NULL || left < 1)
-		return;
-	flags = *pos++;
-	left--;
-	wpa_printf(MSG_DEBUG, "EAP-PEAP: Received packet(len=%lu) - "
-		   "Flags 0x%02x", (unsigned long) wpabuf_len(respData),
-		   flags);
-	peer_version = flags & EAP_PEAP_VERSION_MASK;
+
+	data->recv_version = peer_version;
 	if (data->force_version >= 0 && peer_version != data->force_version) {
 		wpa_printf(MSG_INFO, "EAP-PEAP: peer did not select the forced"
 			   " version (forced=%d peer=%d) - reject",
 			   data->force_version, peer_version);
-		eap_peap_state(data, FAILURE);
-		return;
+		return -1;
 	}
 	if (peer_version < data->peap_version) {
 		wpa_printf(MSG_DEBUG, "EAP-PEAP: peer ver=%d, own ver=%d; "
@@ -771,33 +1286,19 @@
 			   peer_version, data->peap_version, peer_version);
 		data->peap_version = peer_version;
 	}
-	if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) {
-		if (left < 4) {
-			wpa_printf(MSG_INFO, "EAP-PEAP: Short frame with TLS "
-				   "length");
-			eap_peap_state(data, FAILURE);
-			return;
-		}
-		tls_msg_len = WPA_GET_BE32(pos);
-		wpa_printf(MSG_DEBUG, "EAP-PEAP: TLS Message Length: %d",
-			   tls_msg_len);
-		if (data->ssl.tls_in_left == 0) {
-			data->ssl.tls_in_total = tls_msg_len;
-			data->ssl.tls_in_left = tls_msg_len;
-			os_free(data->ssl.tls_in);
-			data->ssl.tls_in = NULL;
-			data->ssl.tls_in_len = 0;
-		}
-		pos += 4;
-		left -= 4;
-	}
+
+	return 0;
+}
+
+
+static void eap_peap_process_msg(struct eap_sm *sm, void *priv,
+				 const struct wpabuf *respData)
+{
+	struct eap_peap_data *data = priv;
 
 	switch (data->state) {
 	case PHASE1:
-		if (eap_server_tls_process_helper(sm, &data->ssl, pos, left) <
-		    0) {
-			wpa_printf(MSG_INFO, "EAP-PEAP: TLS processing "
-				   "failed");
+		if (eap_server_tls_phase1(sm, &data->ssl) < 0) {
 			eap_peap_state(data, FAILURE);
 			break;
 		}
@@ -817,8 +1318,9 @@
 	case PHASE1_ID2:
 	case PHASE2_ID:
 	case PHASE2_METHOD:
+	case PHASE2_SOH:
 	case PHASE2_TLV:
-		eap_peap_process_phase2(sm, data, respData, pos, left);
+		eap_peap_process_phase2(sm, data, respData, data->ssl.in_buf);
 		break;
 	case SUCCESS_REQ:
 		eap_peap_state(data, SUCCESS);
@@ -831,12 +1333,17 @@
 			   data->state, __func__);
 		break;
 	}
-
-	if (tls_connection_get_write_alerts(sm->ssl_ctx, data->ssl.conn) > 1) {
-		wpa_printf(MSG_INFO, "EAP-PEAP: Locally detected fatal error "
-			   "in TLS processing");
+}
+
+
+static void eap_peap_process(struct eap_sm *sm, void *priv,
+			     struct wpabuf *respData)
+{
+	struct eap_peap_data *data = priv;
+	if (eap_server_tls_process(sm, &data->ssl, respData, data,
+				   EAP_TYPE_PEAP, eap_peap_process_version,
+				   eap_peap_process_msg) < 0)
 		eap_peap_state(data, FAILURE);
-	}
 }
 
 
@@ -854,6 +1361,31 @@
 
 	if (data->state != SUCCESS)
 		return NULL;
+
+	if (data->crypto_binding_used) {
+		u8 csk[128];
+		/*
+		 * Note: It looks like Microsoft implementation requires null
+		 * termination for this label while the one used for deriving
+		 * IPMK|CMK did not use null termination.
+		 */
+		peap_prfplus(data->peap_version, data->ipmk, 40,
+			     "Session Key Generating Function",
+			     (u8 *) "\00", 1, csk, sizeof(csk));
+		wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CSK", csk, sizeof(csk));
+		eapKeyData = os_malloc(EAP_TLS_KEY_LEN);
+		if (eapKeyData) {
+			os_memcpy(eapKeyData, csk, EAP_TLS_KEY_LEN);
+			*len = EAP_TLS_KEY_LEN;
+			wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived key",
+				    eapKeyData, EAP_TLS_KEY_LEN);
+		} else {
+			wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to derive "
+				   "key");
+		}
+
+		return eapKeyData;
+	}
 
 	/* TODO: PEAPv1 - different label in some cases */
 	eapKeyData = eap_server_tls_derive_key(sm, &data->ssl,

Modified: wpasupplicant/trunk/src/eap_server/eap_tls.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/eap_server/eap_tls.c?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/eap_server/eap_tls.c (original)
+++ wpasupplicant/trunk/src/eap_server/eap_tls.c Sat Jun 14 00:40:26 2008
@@ -1,6 +1,6 @@
 /*
  * hostapd / EAP-TLS (RFC 2716)
- * Copyright (c) 2004-2007, Jouni Malinen <j at w1.fi>
+ * Copyright (c) 2004-2008, 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,6 +29,32 @@
 };
 
 
+static const char * eap_tls_state_txt(int state)
+{
+	switch (state) {
+	case START:
+		return "START";
+	case CONTINUE:
+		return "CONTINUE";
+	case SUCCESS:
+		return "SUCCESS";
+	case FAILURE:
+		return "FAILURE";
+	default:
+		return "Unknown?!";
+	}
+}
+
+
+static void eap_tls_state(struct eap_tls_data *data, int state)
+{
+	wpa_printf(MSG_DEBUG, "EAP-TLS: %s -> %s",
+		   eap_tls_state_txt(data->state),
+		   eap_tls_state_txt(state));
+	data->state = state;
+}
+
+
 static void * eap_tls_init(struct eap_sm *sm)
 {
 	struct eap_tls_data *data;
@@ -68,52 +94,48 @@
 	if (req == NULL) {
 		wpa_printf(MSG_ERROR, "EAP-TLS: Failed to allocate memory for "
 			   "request");
-		data->state = FAILURE;
+		eap_tls_state(data, FAILURE);
 		return NULL;
 	}
 
 	wpabuf_put_u8(req, EAP_TLS_FLAGS_START);
 
-	data->state = CONTINUE;
+	eap_tls_state(data, CONTINUE);
 
 	return req;
 }
 
 
-static struct wpabuf * eap_tls_build_req(struct eap_sm *sm,
-					 struct eap_tls_data *data, u8 id)
-{
-	int res;
-	struct wpabuf *req;
-
-	res = eap_server_tls_buildReq_helper(sm, &data->ssl, EAP_TYPE_TLS, 0,
-					     id, &req);
-
-	if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
-		wpa_printf(MSG_DEBUG, "EAP-TLS: Done");
-		data->state = SUCCESS;
-	}
-
-	if (res == 1)
+static struct wpabuf * eap_tls_buildReq(struct eap_sm *sm, void *priv, u8 id)
+{
+	struct eap_tls_data *data = priv;
+
+
+	if (data->ssl.state == FRAG_ACK) {
 		return eap_server_tls_build_ack(id, EAP_TYPE_TLS, 0);
-	return req;
-}
-
-
-static struct wpabuf * eap_tls_buildReq(struct eap_sm *sm, void *priv, u8 id)
-{
-	struct eap_tls_data *data = priv;
+	}
+
+	if (data->ssl.state == WAIT_FRAG_ACK) {
+		return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_TLS, 0,
+						id);
+	}
 
 	switch (data->state) {
 	case START:
 		return eap_tls_build_start(sm, data, id);
 	case CONTINUE:
-		return eap_tls_build_req(sm, data, id);
+		if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
+			wpa_printf(MSG_DEBUG, "EAP-TLS: Done");
+			eap_tls_state(data, SUCCESS);
+		}
+		break;
 	default:
 		wpa_printf(MSG_DEBUG, "EAP-TLS: %s - unexpected state %d",
 			   __func__, data->state);
 		return NULL;
 	}
+
+	return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_TLS, 0, id);
 }
 
 
@@ -133,57 +155,28 @@
 }
 
 
+static void eap_tls_process_msg(struct eap_sm *sm, void *priv,
+				const struct wpabuf *respData)
+{
+	struct eap_tls_data *data = priv;
+	if (data->state == SUCCESS && wpabuf_len(data->ssl.in_buf) == 0) {
+		wpa_printf(MSG_DEBUG, "EAP-TLS: Client acknowledged final TLS "
+			   "handshake message");
+		return;
+	}
+	if (eap_server_tls_phase1(sm, &data->ssl) < 0)
+		eap_tls_state(data, FAILURE);
+}
+
+
 static void eap_tls_process(struct eap_sm *sm, void *priv,
 			    struct wpabuf *respData)
 {
 	struct eap_tls_data *data = priv;
-	const u8 *pos;
-	u8 flags;
-	size_t left;
-	unsigned int tls_msg_len;
-
-	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TLS, respData, &left);
-	if (pos == NULL || left < 1)
-		return; /* Should not happen - frame already validated */
-
-	flags = *pos++;
-	left--;
-	wpa_printf(MSG_DEBUG, "EAP-TLS: Received packet(len=%lu) - "
-		   "Flags 0x%02x", (unsigned long) wpabuf_len(respData),
-		   flags);
-	if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) {
-		if (left < 4) {
-			wpa_printf(MSG_INFO, "EAP-TLS: Short frame with TLS "
-				   "length");
-			data->state = FAILURE;
-			return;
-		}
-		tls_msg_len = WPA_GET_BE32(pos);
-		wpa_printf(MSG_DEBUG, "EAP-TLS: TLS Message Length: %d",
-			   tls_msg_len);
-		if (data->ssl.tls_in_left == 0) {
-			data->ssl.tls_in_total = tls_msg_len;
-			data->ssl.tls_in_left = tls_msg_len;
-			os_free(data->ssl.tls_in);
-			data->ssl.tls_in = NULL;
-			data->ssl.tls_in_len = 0;
-		}
-		pos += 4;
-		left -= 4;
-	}
-
-	if (eap_server_tls_process_helper(sm, &data->ssl, pos, left) < 0) {
-		wpa_printf(MSG_INFO, "EAP-TLS: TLS processing failed");
-		data->state = FAILURE;
-		return;
-	}
-
-	if (tls_connection_get_write_alerts(sm->ssl_ctx, data->ssl.conn) > 1) {
-		wpa_printf(MSG_INFO, "EAP-TLS: Locally detected fatal error "
-			   "in TLS processing");
-		data->state = FAILURE;
-		return;
-	}
+	if (eap_server_tls_process(sm, &data->ssl, respData, data,
+				   EAP_TYPE_TLS, NULL, eap_tls_process_msg) <
+	    0)
+		eap_tls_state(data, FAILURE);
 }
 
 

Modified: wpasupplicant/trunk/src/eap_server/eap_tls_common.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/eap_server/eap_tls_common.c?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/eap_server/eap_tls_common.c (original)
+++ wpasupplicant/trunk/src/eap_server/eap_tls_common.c Sat Jun 14 00:40:26 2008
@@ -1,6 +1,6 @@
 /*
  * hostapd / EAP-TLS/PEAP/TTLS/FAST common functions
- * Copyright (c) 2004-2007, Jouni Malinen <j at w1.fi>
+ * Copyright (c) 2004-2008, 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
@@ -58,8 +58,8 @@
 void eap_server_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data)
 {
 	tls_connection_deinit(sm->ssl_ctx, data->conn);
-	os_free(data->tls_in);
-	os_free(data->tls_out);
+	os_free(data->in_buf);
+	os_free(data->out_buf);
 }
 
 
@@ -106,188 +106,305 @@
 }
 
 
-int eap_server_tls_data_reassemble(struct eap_sm *sm,
-				   struct eap_ssl_data *data,
-				   u8 **in_data, size_t *in_len)
-{
-	u8 *buf;
-
-	if (data->tls_in_left > *in_len || data->tls_in) {
-		if (*in_len == 0) {
-			wpa_printf(MSG_INFO, "SSL: Empty fragment when trying "
-				   "to reassemble");
-			return -1;
+struct wpabuf * eap_server_tls_build_msg(struct eap_ssl_data *data,
+					 int eap_type, int version, u8 id)
+{
+	struct wpabuf *req;
+	u8 flags;
+	size_t send_len, plen;
+
+	wpa_printf(MSG_DEBUG, "SSL: Generating Request");
+	if (data->out_buf == NULL) {
+		wpa_printf(MSG_ERROR, "SSL: out_buf NULL in %s", __func__);
+		return NULL;
+	}
+
+	flags = version;
+	send_len = wpabuf_len(data->out_buf) - data->out_used;
+	if (1 + send_len > data->tls_out_limit) {
+		send_len = data->tls_out_limit - 1;
+		flags |= EAP_TLS_FLAGS_MORE_FRAGMENTS;
+		if (data->out_used == 0) {
+			flags |= EAP_TLS_FLAGS_LENGTH_INCLUDED;
+			send_len -= 4;
 		}
-		if (data->tls_in_len + *in_len > 65536) {
-			/* Limit length to avoid rogue peers from causing large
-			 * memory allocations. */
-			os_free(data->tls_in);
-			data->tls_in = NULL;
-			data->tls_in_len = 0;
+	}
+
+	plen = 1 + send_len;
+	if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED)
+		plen += 4;
+
+	req = eap_msg_alloc(EAP_VENDOR_IETF, eap_type, plen,
+			    EAP_CODE_REQUEST, id);
+	if (req == NULL)
+		return NULL;
+
+	wpabuf_put_u8(req, flags); /* Flags */
+	if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED)
+		wpabuf_put_be32(req, wpabuf_len(data->out_buf));
+
+	wpabuf_put_data(req, wpabuf_head_u8(data->out_buf) + data->out_used,
+			send_len);
+	data->out_used += send_len;
+
+	if (data->out_used == wpabuf_len(data->out_buf)) {
+		wpa_printf(MSG_DEBUG, "SSL: Sending out %lu bytes "
+			   "(message sent completely)",
+			   (unsigned long) send_len);
+		wpabuf_free(data->out_buf);
+		data->out_buf = NULL;
+		data->out_used = 0;
+		data->state = MSG;
+	} else {
+		wpa_printf(MSG_DEBUG, "SSL: Sending out %lu bytes "
+			   "(%lu more to send)", (unsigned long) send_len,
+			   (unsigned long) wpabuf_len(data->out_buf) -
+			   data->out_used);
+		data->state = WAIT_FRAG_ACK;
+	}
+
+	return req;
+}
+
+
+struct wpabuf * eap_server_tls_build_ack(u8 id, int eap_type, int version)
+{
+	struct wpabuf *req;
+
+	req = eap_msg_alloc(EAP_VENDOR_IETF, eap_type, 1, EAP_CODE_REQUEST,
+			    id);
+	if (req == NULL)
+		return NULL;
+	wpa_printf(MSG_DEBUG, "SSL: Building ACK");
+	wpabuf_put_u8(req, version); /* Flags */
+	return req;
+}
+
+
+static int eap_server_tls_process_cont(struct eap_ssl_data *data,
+				       const u8 *buf, size_t len)
+{
+	/* Process continuation of a pending message */
+	if (len > wpabuf_tailroom(data->in_buf)) {
+		wpa_printf(MSG_DEBUG, "SSL: Fragment overflow");
+		return -1;
+	}
+
+	wpabuf_put_data(data->in_buf, buf, len);
+	wpa_printf(MSG_DEBUG, "SSL: Received %lu bytes, waiting for %lu "
+		   "bytes more", (unsigned long) len,
+		   (unsigned long) wpabuf_tailroom(data->in_buf));
+
+	return 0;
+}
+
+
+static int eap_server_tls_process_fragment(struct eap_ssl_data *data,
+					   u8 flags, u32 message_length,
+					   const u8 *buf, size_t len)
+{
+	/* Process a fragment that is not the last one of the message */
+	if (data->in_buf == NULL && !(flags & EAP_TLS_FLAGS_LENGTH_INCLUDED)) {
+		wpa_printf(MSG_DEBUG, "SSL: No Message Length field in a "
+			   "fragmented packet");
+		return -1;
+	}
+
+	if (data->in_buf == NULL) {
+		/* First fragment of the message */
+
+		/* Limit length to avoid rogue peers from causing large
+		 * memory allocations. */
+		if (message_length > 65536) {
 			wpa_printf(MSG_INFO, "SSL: Too long TLS fragment (size"
 				   " over 64 kB)");
 			return -1;
 		}
-		buf = os_realloc(data->tls_in, data->tls_in_len + *in_len);
-		if (buf == NULL) {
-			os_free(data->tls_in);
-			data->tls_in = NULL;
-			data->tls_in_len = 0;
-			wpa_printf(MSG_INFO, "SSL: Could not allocate memory "
-				   "for TLS data");
+
+		data->in_buf = wpabuf_alloc(message_length);
+		if (data->in_buf == NULL) {
+			wpa_printf(MSG_DEBUG, "SSL: No memory for message");
 			return -1;
 		}
-		os_memcpy(buf + data->tls_in_len, *in_data, *in_len);
-		data->tls_in = buf;
-		data->tls_in_len += *in_len;
-		if (*in_len > data->tls_in_left) {
-			wpa_printf(MSG_INFO, "SSL: more data than TLS message "
-				   "length indicated");
-			data->tls_in_left = 0;
+		wpabuf_put_data(data->in_buf, buf, len);
+		wpa_printf(MSG_DEBUG, "SSL: Received %lu bytes in first "
+			   "fragment, waiting for %lu bytes more",
+			   (unsigned long) len,
+			   (unsigned long) wpabuf_tailroom(data->in_buf));
+	}
+
+	return 0;
+}
+
+
+int eap_server_tls_phase1(struct eap_sm *sm, struct eap_ssl_data *data)
+{
+	u8 *next;
+	size_t next_len;
+
+	next = tls_connection_server_handshake(
+		sm->ssl_ctx, data->conn,
+		wpabuf_mhead(data->in_buf),
+		wpabuf_len(data->in_buf),
+		&next_len);
+	if (next == NULL) {
+		wpa_printf(MSG_INFO, "SSL: TLS processing failed");
+		return -1;
+	}
+	if (data->out_buf) {
+		/* This should not happen.. */
+		wpa_printf(MSG_INFO, "SSL: pending tls_out data when "
+			   "processing new message");
+		os_free(data->out_buf);
+		WPA_ASSERT(data->out_buf == NULL);
+	}
+	data->out_buf = wpabuf_alloc_ext_data(next, next_len);
+	if (data->out_buf == NULL) {
+		os_free(next);
+		return -1;
+	}
+	return 0;
+}
+
+
+static int eap_server_tls_reassemble(struct eap_ssl_data *data, u8 flags,
+				     const u8 **pos, size_t *left)
+{
+	unsigned int tls_msg_len = 0;
+	const u8 *end = *pos + *left;
+
+	if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) {
+		if (*left < 4) {
+			wpa_printf(MSG_INFO, "SSL: Short frame with TLS "
+				   "length");
 			return -1;
 		}
-		data->tls_in_left -= *in_len;
-		if (data->tls_in_left > 0) {
-			wpa_printf(MSG_DEBUG, "SSL: Need %lu bytes more input "
-				   "data", (unsigned long) data->tls_in_left);
-			return 1;
-		}
-
-		*in_data = data->tls_in;
-		*in_len = data->tls_in_len;
-	} else
-		data->tls_in_left = 0;
-
-	return 0;
-}
-
-
-int eap_server_tls_process_helper(struct eap_sm *sm, struct eap_ssl_data *data,
-				  const u8 *in_data, size_t in_len)
-{
-	WPA_ASSERT(data->tls_out_len == 0 || in_len == 0);
-
-	if (data->tls_out_len == 0) {
-		u8 *_in_data = (u8 *) in_data; /* FIX: get rid of the typecast
-						*/
-		/* No more data to send out - expect to receive more data from
-		 * the peer. */
-		int res = eap_server_tls_data_reassemble(sm, data, &_in_data,
-							 &in_len);
-		if (res < 0 || res == 1) {
-			wpa_printf(MSG_DEBUG, "SSL: data reassembly failed");
-			return res;
-		}
-		/* Full TLS message reassembled - continue handshake processing
-		 */
-		if (data->tls_out) {
-			/* This should not happen.. */
-			wpa_printf(MSG_INFO, "SSL: eap_tls_process_helper - "
-				   "pending tls_out data even though "
-				   "tls_out_len = 0");
-			os_free(data->tls_out);
-			WPA_ASSERT(data->tls_out == NULL);
-		}
-		data->tls_out = tls_connection_server_handshake(
-			sm->ssl_ctx, data->conn, _in_data, in_len,
-			&data->tls_out_len);
-
-		/* Clear reassembled input data (if the buffer was needed). */
-		data->tls_in_left = data->tls_in_total = data->tls_in_len = 0;
-		os_free(data->tls_in);
-		data->tls_in = NULL;
-	}
-
-	if (data->tls_out == NULL) {
-		wpa_printf(MSG_DEBUG, "SSL: failed to generate output data");
-		data->tls_out_len = 0;
-		return -1;
-	}
-	if (data->tls_out_len == 0) {
-		/* TLS negotiation should now be complete since all other cases
-		 * needing more that should have been catched above based on
-		 * the TLS Message Length field. */
-		wpa_printf(MSG_DEBUG, "SSL: No data to be sent out");
-		os_free(data->tls_out);
-		data->tls_out = NULL;
-
-		if (tls_connection_get_read_alerts(sm->ssl_ctx, data->conn)) {
-			wpa_printf(MSG_DEBUG, "SSL: Remote end sent a fatal "
-				   "alert - abort handshake");
+		tls_msg_len = WPA_GET_BE32(*pos);
+		wpa_printf(MSG_DEBUG, "SSL: TLS Message Length: %d",
+			   tls_msg_len);
+		*pos += 4;
+		*left -= 4;
+	}
+
+	wpa_printf(MSG_DEBUG, "SSL: Received packet: Flags 0x%x "
+		   "Message Length %u", flags, tls_msg_len);
+
+	if (data->state == WAIT_FRAG_ACK) {
+		if (*left != 0) {
+			wpa_printf(MSG_DEBUG, "SSL: Unexpected payload in "
+				   "WAIT_FRAG_ACK state");
 			return -1;
 		}
-
+		wpa_printf(MSG_DEBUG, "SSL: Fragment acknowledged");
 		return 1;
 	}
 
-	wpa_printf(MSG_DEBUG, "SSL: %lu bytes left to be sent out (of total "
-		   "%lu bytes)",
-		   (unsigned long) data->tls_out_len - data->tls_out_pos,
-		   (unsigned long) data->tls_out_len);
+	if (data->in_buf &&
+	    eap_server_tls_process_cont(data, *pos, end - *pos) < 0)
+		return -1;
+		
+	if (flags & EAP_TLS_FLAGS_MORE_FRAGMENTS) {
+		if (eap_server_tls_process_fragment(data, flags, tls_msg_len,
+						    *pos, end - *pos) < 0)
+			return -1;
+
+		data->state = FRAG_ACK;
+		return 1;
+	}
+
+	if (data->state == FRAG_ACK) {
+		wpa_printf(MSG_DEBUG, "SSL: All fragments received");
+		data->state = MSG;
+	}
+
+	if (data->in_buf == NULL) {
+		/* Wrap unfragmented messages as wpabuf without extra copy */
+		wpabuf_set(&data->tmpbuf, *pos, end - *pos);
+		data->in_buf = &data->tmpbuf;
+	}
 
 	return 0;
 }
 
 
-int eap_server_tls_buildReq_helper(struct eap_sm *sm,
-				   struct eap_ssl_data *data,
-				   int eap_type, int peap_version, u8 id,
-				   struct wpabuf **out_data)
-{
-	size_t len;
-	u8 *flags;
-	struct wpabuf *req;
-	int incl_len;
-
-	incl_len = data->tls_out_pos == 0 &&
-		data->tls_out_len > data->tls_out_limit;
-	req = eap_msg_alloc(EAP_VENDOR_IETF, eap_type,
-			    1 + (incl_len ? 4 : 0) + data->tls_out_limit,
-			    EAP_CODE_REQUEST, id);
-	if (req == NULL) {
-		*out_data = NULL;
-		return -1;
-	}
-	flags = wpabuf_put(req, 1);
-	*flags = peap_version;
-	if (incl_len) {
-		*flags |= EAP_TLS_FLAGS_LENGTH_INCLUDED;
-		wpabuf_put_be32(req, data->tls_out_len);
-	}
-
-	len = data->tls_out_len - data->tls_out_pos;
-	if (len > data->tls_out_limit) {
-		*flags |= EAP_TLS_FLAGS_MORE_FRAGMENTS;
-		len = data->tls_out_limit;
-		wpa_printf(MSG_DEBUG, "SSL: sending %lu bytes, more fragments "
-			   "will follow", (unsigned long) len);
-	}
-	wpabuf_put_data(req, &data->tls_out[data->tls_out_pos], len);
-	data->tls_out_pos += len;
-
-	eap_update_len(req);
-	*out_data = req;
-
-	if (!(*flags & EAP_TLS_FLAGS_MORE_FRAGMENTS)) {
-		data->tls_out_len = 0;
-		data->tls_out_pos = 0;
-		os_free(data->tls_out);
-		data->tls_out = NULL;
-	}
-
-	return 0;
-}
-
-
-struct wpabuf * eap_server_tls_build_ack(u8 id, int eap_type, int peap_version)
-{
-	struct wpabuf *req;
-
-	req = eap_msg_alloc(EAP_VENDOR_IETF, eap_type, 1, EAP_CODE_REQUEST,
-			    id);
-	if (req == NULL)
-		return NULL;
-	wpa_printf(MSG_DEBUG, "SSL: Building ACK");
-	wpabuf_put_u8(req, peap_version); /* Flags */
-	return req;
-}
+static void eap_server_tls_free_in_buf(struct eap_ssl_data *data)
+{
+	if (data->in_buf != &data->tmpbuf)
+		wpabuf_free(data->in_buf);
+	data->in_buf = NULL;
+}
+
+
+struct wpabuf * eap_server_tls_encrypt(struct eap_sm *sm,
+				       struct eap_ssl_data *data,
+				       const u8 *plain, size_t plain_len)
+{
+	int res;
+	struct wpabuf *buf;
+	size_t buf_len;
+
+	/* reserve some extra room for encryption overhead */
+	buf_len = plain_len + 200;
+	buf = wpabuf_alloc(buf_len);
+	if (buf == NULL)
+		return NULL;
+	res = tls_connection_encrypt(sm->ssl_ctx, data->conn,
+				     plain, plain_len, wpabuf_put(buf, 0),
+				     buf_len);
+	if (res < 0) {
+		wpa_printf(MSG_INFO, "SSL: Failed to encrypt Phase 2 data");
+		wpabuf_free(buf);
+		return NULL;
+	}
+
+	wpabuf_put(buf, res);
+
+	return buf;
+}
+
+
+int eap_server_tls_process(struct eap_sm *sm, struct eap_ssl_data *data,
+			   struct wpabuf *respData, void *priv, int eap_type,
+			   int (*proc_version)(struct eap_sm *sm, void *priv,
+					       int peer_version),
+			   void (*proc_msg)(struct eap_sm *sm, void *priv,
+					    const struct wpabuf *respData))
+{
+	const u8 *pos;
+	u8 flags;
+	size_t left;
+	int ret, res = 0;
+
+	pos = eap_hdr_validate(EAP_VENDOR_IETF, eap_type, respData, &left);
+	if (pos == NULL || left < 1)
+		return 0; /* Should not happen - frame already validated */
+	flags = *pos++;
+	left--;
+	wpa_printf(MSG_DEBUG, "SSL: Received packet(len=%lu) - Flags 0x%02x",
+		   (unsigned long) wpabuf_len(respData), flags);
+
+	if (proc_version &&
+	    proc_version(sm, priv, flags & EAP_TLS_VERSION_MASK) < 0)
+		return -1;
+
+	ret = eap_server_tls_reassemble(data, flags, &pos, &left);
+	if (ret < 0) {
+		res = -1;
+		goto done;
+	} else if (ret == 1)
+		return 0;
+
+	if (proc_msg)
+		proc_msg(sm, priv, respData);
+
+	if (tls_connection_get_write_alerts(sm->ssl_ctx, data->conn) > 1) {
+		wpa_printf(MSG_INFO, "SSL: Locally detected fatal error in "
+			   "TLS processing");
+		res = -1;
+	}
+
+done:
+	eap_server_tls_free_in_buf(data);
+
+	return res;
+}

Modified: wpasupplicant/trunk/src/eap_server/eap_tls_common.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/eap_server/eap_tls_common.h?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/eap_server/eap_tls_common.h (original)
+++ wpasupplicant/trunk/src/eap_server/eap_tls_common.h Sat Jun 14 00:40:26 2008
@@ -1,6 +1,6 @@
 /*
  * hostapd / EAP-TLS/PEAP/TTLS/FAST common functions
- * Copyright (c) 2004-2007, Jouni Malinen <j at w1.fi>
+ * Copyright (c) 2004-2008, Jouni Malinen <j at w1.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -18,18 +18,17 @@
 struct eap_ssl_data {
 	struct tls_connection *conn;
 
-	u8 *tls_out;
-	size_t tls_out_len;
-	size_t tls_out_pos;
 	size_t tls_out_limit;
-	u8 *tls_in;
-	size_t tls_in_len;
-	size_t tls_in_left;
-	size_t tls_in_total;
 
 	int phase2;
 
 	struct eap_sm *eap;
+
+	enum { MSG, FRAG_ACK, WAIT_FRAG_ACK } state;
+	struct wpabuf *in_buf;
+	struct wpabuf *out_buf;
+	size_t out_used;
+	struct wpabuf tmpbuf;
 };
 
 
@@ -37,7 +36,7 @@
 #define EAP_TLS_FLAGS_LENGTH_INCLUDED 0x80
 #define EAP_TLS_FLAGS_MORE_FRAGMENTS 0x40
 #define EAP_TLS_FLAGS_START 0x20
-#define EAP_PEAP_VERSION_MASK 0x07
+#define EAP_TLS_VERSION_MASK 0x07
 
  /* could be up to 128 bytes, but only the first 64 bytes are used */
 #define EAP_TLS_KEY_LEN 64
@@ -48,16 +47,18 @@
 void eap_server_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data);
 u8 * eap_server_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
 			       char *label, size_t len);
-int eap_server_tls_data_reassemble(struct eap_sm *sm,
-				   struct eap_ssl_data *data,
-				   u8 **in_data, size_t *in_len);
-int eap_server_tls_process_helper(struct eap_sm *sm, struct eap_ssl_data *data,
-				  const u8 *in_data, size_t in_len);
-int eap_server_tls_buildReq_helper(struct eap_sm *sm,
-				   struct eap_ssl_data *data,
-				   int eap_type, int peap_version, u8 id,
-				   struct wpabuf **out_data);
-struct wpabuf * eap_server_tls_build_ack(u8 id, int eap_type,
-					 int peap_version);
+struct wpabuf * eap_server_tls_build_msg(struct eap_ssl_data *data,
+					 int eap_type, int version, u8 id);
+struct wpabuf * eap_server_tls_build_ack(u8 id, int eap_type, int version);
+int eap_server_tls_phase1(struct eap_sm *sm, struct eap_ssl_data *data);
+struct wpabuf * eap_server_tls_encrypt(struct eap_sm *sm,
+				       struct eap_ssl_data *data,
+				       const u8 *plain, size_t plain_len);
+int eap_server_tls_process(struct eap_sm *sm, struct eap_ssl_data *data,
+			   struct wpabuf *respData, void *priv, int eap_type,
+			   int (*proc_version)(struct eap_sm *sm, void *priv,
+					       int peer_version),
+			   void (*proc_msg)(struct eap_sm *sm, void *priv,
+					    const struct wpabuf *respData));
 
 #endif /* EAP_TLS_COMMON_H */

Modified: wpasupplicant/trunk/src/eap_server/eap_ttls.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/eap_server/eap_ttls.c?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/eap_server/eap_ttls.c (original)
+++ wpasupplicant/trunk/src/eap_server/eap_ttls.c Sat Jun 14 00:40:26 2008
@@ -55,6 +55,7 @@
 	u8 mschapv2_ident;
 	int tls_ia_configured;
 	struct wpabuf *pending_phase2_eap_resp;
+	int tnc_started;
 };
 
 
@@ -444,62 +445,6 @@
 }
 
 
-static struct wpabuf * eap_ttls_build_req(struct eap_sm *sm,
-					  struct eap_ttls_data *data, u8 id)
-{
-	int res;
-	struct wpabuf *req;
-
-	res = eap_server_tls_buildReq_helper(sm, &data->ssl, EAP_TYPE_TTLS,
-					     data->ttls_version, id, &req);
-
-	if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
-		wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase1 done, starting "
-			   "Phase2");
-		eap_ttls_state(data, PHASE2_START);
-	}
-
-	if (res == 1)
-		return eap_server_tls_build_ack(id, EAP_TYPE_TTLS,
-						data->ttls_version);
-	return req;
-}
-
-
-static struct wpabuf * eap_ttls_encrypt(struct eap_sm *sm,
-					struct eap_ttls_data *data,
-					u8 id, u8 *plain, size_t plain_len)
-{
-	int res;
-	struct wpabuf *buf;
-
-	/* TODO: add support for fragmentation, if needed. This will need to
-	 * add TLS Message Length field, if the frame is fragmented. */
-	buf = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TTLS,
-			    1 + data->ssl.tls_out_limit,
-			    EAP_CODE_REQUEST, id);
-	if (buf == NULL)
-		return NULL;
-
-	wpabuf_put_u8(buf, data->ttls_version);
-
-	res = tls_connection_encrypt(sm->ssl_ctx, data->ssl.conn,
-				     plain, plain_len, wpabuf_put(buf, 0),
-				     data->ssl.tls_out_limit);
-	if (res < 0) {
-		wpa_printf(MSG_INFO, "EAP-TTLS: Failed to encrypt Phase 2 "
-			   "data");
-		wpabuf_free(buf);
-		return NULL;
-	}
-
-	wpabuf_put(buf, res);
-	eap_update_len(buf);
-
-	return buf;
-}
-
-
 static struct wpabuf * eap_ttls_build_phase2_eap_req(
 	struct eap_sm *sm, struct eap_ttls_data *data, u8 id)
 {
@@ -527,7 +472,7 @@
 	wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS/EAP: Encrypt encapsulated Phase "
 			"2 data", req, req_len);
 
-	encr_req = eap_ttls_encrypt(sm, data, id, req, req_len);
+	encr_req = eap_server_tls_encrypt(sm, &data->ssl, req, req_len);
 	wpabuf_free(buf);
 
 	return encr_req;
@@ -535,7 +480,7 @@
 
 
 static struct wpabuf * eap_ttls_build_phase2_mschapv2(
-	struct eap_sm *sm, struct eap_ttls_data *data, u8 id)
+	struct eap_sm *sm, struct eap_ttls_data *data)
 {
 	struct wpabuf *encr_req;
 	u8 *req, *pos, *end;
@@ -569,7 +514,7 @@
 	wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Encrypting Phase 2 "
 			"data", req, req_len);
 
-	encr_req = eap_ttls_encrypt(sm, data, id, req, req_len);
+	encr_req = eap_server_tls_encrypt(sm, &data->ssl, req, req_len);
 	os_free(req);
 
 	return encr_req;
@@ -577,19 +522,15 @@
 
 
 static struct wpabuf * eap_ttls_build_phase_finished(
-	struct eap_sm *sm, struct eap_ttls_data *data, u8 id, int final)
+	struct eap_sm *sm, struct eap_ttls_data *data, int final)
 {
 	int len;
 	struct wpabuf *req;
 	const int max_len = 300;
 
-	len = 1 + max_len;
-	req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TTLS, len,
-			    EAP_CODE_REQUEST, id);
+	req = wpabuf_alloc(max_len);
 	if (req == NULL)
 		return NULL;
-
-	wpabuf_put_u8(req, data->ttls_version);
 
 	len = tls_connection_ia_send_phase_finished(sm->ssl_ctx,
 						    data->ssl.conn, final,
@@ -600,7 +541,6 @@
 		return NULL;
 	}
 	wpabuf_put(req, len);
-	eap_update_len(req);
 
 	return req;
 }
@@ -609,23 +549,51 @@
 static struct wpabuf * eap_ttls_buildReq(struct eap_sm *sm, void *priv, u8 id)
 {
 	struct eap_ttls_data *data = priv;
+
+	if (data->ssl.state == FRAG_ACK) {
+		return eap_server_tls_build_ack(id, EAP_TYPE_TTLS,
+						data->ttls_version);
+	}
+
+	if (data->ssl.state == WAIT_FRAG_ACK) {
+		return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_TTLS,
+						data->ttls_version, id);
+	}
 
 	switch (data->state) {
 	case START:
 		return eap_ttls_build_start(sm, data, id);
 	case PHASE1:
-		return eap_ttls_build_req(sm, data, id);
+		if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
+			wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase1 done, "
+				   "starting Phase2");
+			eap_ttls_state(data, PHASE2_START);
+		}
+		break;
 	case PHASE2_METHOD:
-		return eap_ttls_build_phase2_eap_req(sm, data, id);
+		wpabuf_free(data->ssl.out_buf);
+		data->ssl.out_used = 0;
+		data->ssl.out_buf = eap_ttls_build_phase2_eap_req(sm, data,
+								  id);
+		break;
 	case PHASE2_MSCHAPV2_RESP:
-		return eap_ttls_build_phase2_mschapv2(sm, data, id);
+		wpabuf_free(data->ssl.out_buf);
+		data->ssl.out_used = 0;
+		data->ssl.out_buf = eap_ttls_build_phase2_mschapv2(sm, data);
+		break;
 	case PHASE_FINISHED:
-		return eap_ttls_build_phase_finished(sm, data, id, 1);
+		wpabuf_free(data->ssl.out_buf);
+		data->ssl.out_used = 0;
+		data->ssl.out_buf = eap_ttls_build_phase_finished(sm, data, 1);
+		break;
 	default:
 		wpa_printf(MSG_DEBUG, "EAP-TTLS: %s - unexpected state %d",
 			   __func__, data->state);
 		return NULL;
 	}
+
+	return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_TTLS,
+					data->ttls_version, id);
 }
 
 
@@ -1147,12 +1115,17 @@
 
 static void eap_ttls_process_phase2(struct eap_sm *sm,
 				    struct eap_ttls_data *data,
-				    u8 *in_data, size_t in_len)
+				    struct wpabuf *in_buf)
 {
 	u8 *in_decrypted;
-	int len_decrypted, res;
+	int len_decrypted;
 	struct eap_ttls_avp parse;
 	size_t buf_len;
+	u8 *in_data;
+	size_t in_len;
+
+	in_data = wpabuf_mhead(in_buf);
+	in_len = wpabuf_len(in_buf);
 
 	wpa_printf(MSG_DEBUG, "EAP-TTLS: received %lu bytes encrypted data for"
 		   " Phase 2", (unsigned long) in_len);
@@ -1168,19 +1141,17 @@
 		return;
 	}
 
-	res = eap_server_tls_data_reassemble(sm, &data->ssl, &in_data,
-					     &in_len);
-	if (res < 0 || res == 1)
-		return;
-
 	buf_len = in_len;
-	if (data->ssl.tls_in_total > buf_len)
-		buf_len = data->ssl.tls_in_total;
+	/*
+	 * Even though we try to disable TLS compression, it is possible that
+	 * this cannot be done with all TLS libraries. Add extra buffer space
+	 * to handle the possibility of the decrypted data being longer than
+	 * input data.
+	 */
+	buf_len += 500;
+	buf_len *= 3;
 	in_decrypted = os_malloc(buf_len);
 	if (in_decrypted == NULL) {
-		os_free(data->ssl.tls_in);
-		data->ssl.tls_in = NULL;
-		data->ssl.tls_in_len = 0;
 		wpa_printf(MSG_WARNING, "EAP-TTLS: failed to allocate memory "
 			   "for decryption");
 		return;
@@ -1189,9 +1160,6 @@
 	len_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,
 					       in_data, in_len,
 					       in_decrypted, buf_len);
-	os_free(data->ssl.tls_in);
-	data->ssl.tls_in = NULL;
-	data->ssl.tls_in_len = 0;
 	if (len_decrypted < 0) {
 		wpa_printf(MSG_INFO, "EAP-TTLS: Failed to decrypt Phase 2 "
 			   "data");
@@ -1243,6 +1211,15 @@
 			goto done;
 		}
 	}
+
+#ifdef EAP_TNC
+	if (data->tnc_started && parse.eap == NULL) {
+		wpa_printf(MSG_DEBUG, "EAP-TTLS: TNC started but no EAP "
+			   "response from peer");
+		eap_ttls_state(data, FAILURE);
+		goto done;
+	}
+#endif /* EAP_TNC */
 
 	if (parse.eap) {
 		eap_ttls_process_phase2_eap(sm, data, parse.eap,
@@ -1276,26 +1253,29 @@
 }
 
 
-static void eap_ttls_process(struct eap_sm *sm, void *priv,
-			     struct wpabuf *respData)
+static void eap_ttls_start_tnc(struct eap_sm *sm, struct eap_ttls_data *data)
+{
+#ifdef EAP_TNC
+	if (!sm->tnc || data->state != SUCCESS || data->tnc_started)
+		return;
+
+	wpa_printf(MSG_DEBUG, "EAP-TTLS: Initialize TNC");
+	if (eap_ttls_phase2_eap_init(sm, data, EAP_TYPE_TNC)) {
+		wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to initialize TNC");
+		eap_ttls_state(data, FAILURE);
+		return;
+	}
+
+	data->tnc_started = 1;
+	eap_ttls_state(data, PHASE2_METHOD);
+#endif /* EAP_TNC */
+}
+
+
+static int eap_ttls_process_version(struct eap_sm *sm, void *priv,
+				    int peer_version)
 {
 	struct eap_ttls_data *data = priv;
-	const u8 *pos;
-	u8 flags;
-	size_t left;
-	unsigned int tls_msg_len;
-	int peer_version;
-
-	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TTLS, respData,
-			       &left);
-	if (pos == NULL || left < 1)
-		return;
-	flags = *pos++;
-	left--;
-	wpa_printf(MSG_DEBUG, "EAP-TTLS: Received packet(len=%lu) - "
-		   "Flags 0x%02x", (unsigned long) wpabuf_len(respData),
-		   flags);
-	peer_version = flags & EAP_PEAP_VERSION_MASK;
 	if (peer_version < data->ttls_version) {
 		wpa_printf(MSG_DEBUG, "EAP-TTLS: peer ver=%d, own ver=%d; "
 			   "use version %d",
@@ -1307,50 +1287,34 @@
 		if (tls_connection_set_ia(sm->ssl_ctx, data->ssl.conn, 1)) {
 			wpa_printf(MSG_INFO, "EAP-TTLS: Failed to enable "
 				   "TLS/IA");
-			eap_ttls_state(data, FAILURE);
-			return;
+			return -1;
 		}
 		data->tls_ia_configured = 1;
 	}
 
-	if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) {
-		if (left < 4) {
-			wpa_printf(MSG_INFO, "EAP-TTLS: Short frame with TLS "
-				   "length");
-			eap_ttls_state(data, FAILURE);
-			return;
-		}
-		tls_msg_len = WPA_GET_BE32(pos);
-		wpa_printf(MSG_DEBUG, "EAP-TTLS: TLS Message Length: %d",
-			   tls_msg_len);
-		if (data->ssl.tls_in_left == 0) {
-			data->ssl.tls_in_total = tls_msg_len;
-			data->ssl.tls_in_left = tls_msg_len;
-			os_free(data->ssl.tls_in);
-			data->ssl.tls_in = NULL;
-			data->ssl.tls_in_len = 0;
-		}
-		pos += 4;
-		left -= 4;
-	}
+	return 0;
+}
+
+
+static void eap_ttls_process_msg(struct eap_sm *sm, void *priv,
+				 const struct wpabuf *respData)
+{
+	struct eap_ttls_data *data = priv;
 
 	switch (data->state) {
 	case PHASE1:
-		if (eap_server_tls_process_helper(sm, &data->ssl, pos, left) <
-		    0) {
-			wpa_printf(MSG_INFO, "EAP-TTLS: TLS processing "
-				   "failed");
+		if (eap_server_tls_phase1(sm, &data->ssl) < 0)
 			eap_ttls_state(data, FAILURE);
-		}
 		break;
 	case PHASE2_START:
 	case PHASE2_METHOD:
 	case PHASE_FINISHED:
-		/* FIX: get rid of const->non-const typecast */
-		eap_ttls_process_phase2(sm, data, (u8 *) pos, left);
+		eap_ttls_process_phase2(sm, data, data->ssl.in_buf);
+		eap_ttls_start_tnc(sm, data);
 		break;
 	case PHASE2_MSCHAPV2_RESP:
-		if (data->mschapv2_resp_ok && left == 0) {
+		if (data->mschapv2_resp_ok && wpabuf_len(data->ssl.in_buf) ==
+		    0) {
 			wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Peer "
 				   "acknowledged response");
 			eap_ttls_state(data, data->ttls_version > 0 ?
@@ -1363,21 +1327,28 @@
 			wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Unexpected "
 				   "frame from peer (payload len %lu, "
 				   "expected empty frame)",
-				   (unsigned long) left);
+				   (unsigned long)
+				   wpabuf_len(data->ssl.in_buf));
 			eap_ttls_state(data, FAILURE);
 		}
+		eap_ttls_start_tnc(sm, data);
 		break;
 	default:
 		wpa_printf(MSG_DEBUG, "EAP-TTLS: Unexpected state %d in %s",
 			   data->state, __func__);
 		break;
 	}
-
-	if (tls_connection_get_write_alerts(sm->ssl_ctx, data->ssl.conn) > 1) {
-		wpa_printf(MSG_INFO, "EAP-TTLS: Locally detected fatal error "
-			   "in TLS processing");
-		eap_ttls_state(data, FAILURE);
-	}
+}
+
+
+static void eap_ttls_process(struct eap_sm *sm, void *priv,
+			     struct wpabuf *respData)
+{
+	struct eap_ttls_data *data = priv;
+	if (eap_server_tls_process(sm, &data->ssl, respData, data,
+				   EAP_TYPE_TTLS, eap_ttls_process_version,
+				   eap_ttls_process_msg) < 0)
+		eap_ttls_state(data, FAILURE);
 }
 
 

Modified: wpasupplicant/trunk/src/radius/radius.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/radius/radius.c?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/radius/radius.c (original)
+++ wpasupplicant/trunk/src/radius/radius.c Sat Jun 14 00:40:26 2008
@@ -181,6 +181,8 @@
 	  RADIUS_ATTR_HEXDUMP },
 	{ RADIUS_ATTR_ACCT_INTERIM_INTERVAL, "Acct-Interim-Interval",
 	  RADIUS_ATTR_INT32 },
+	{ RADIUS_ATTR_CHARGEABLE_USER_IDENTITY, "Chargable-User-Identity",
+	  RADIUS_ATTR_TEXT },
 	{ RADIUS_ATTR_NAS_IPV6_ADDRESS, "NAS-IPv6-Address", RADIUS_ATTR_IPV6 },
 };
 #define RADIUS_ATTRS (sizeof(radius_attrs) / sizeof(radius_attrs[0]))
@@ -803,6 +805,7 @@
 	ppos = plain = os_malloc(plen);
 	if (plain == NULL)
 		return NULL;
+	plain[0] = 0;
 
 	while (left > 0) {
 		/* b(1) = MD5(Secret + Request-Authenticator + Salt)
@@ -827,7 +830,7 @@
 		left -= MD5_MAC_LEN;
 	}
 
-	if (plain[0] > plen - 1) {
+	if (plain[0] == 0 || plain[0] > plen - 1) {
 		printf("Failed to decrypt MPPE key\n");
 		os_free(plain);
 		return NULL;

Modified: wpasupplicant/trunk/src/radius/radius.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/radius/radius.h?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/radius/radius.h (original)
+++ wpasupplicant/trunk/src/radius/radius.h Sat Jun 14 00:40:26 2008
@@ -87,6 +87,7 @@
        RADIUS_ATTR_MESSAGE_AUTHENTICATOR = 80,
        RADIUS_ATTR_TUNNEL_PRIVATE_GROUP_ID = 81,
        RADIUS_ATTR_ACCT_INTERIM_INTERVAL = 85,
+       RADIUS_ATTR_CHARGEABLE_USER_IDENTITY = 89,
        RADIUS_ATTR_NAS_IPV6_ADDRESS = 95
 };
 

Modified: wpasupplicant/trunk/src/radius/radius_client.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/radius/radius_client.c?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/radius/radius_client.c (original)
+++ wpasupplicant/trunk/src/radius/radius_client.c Sat Jun 14 00:40:26 2008
@@ -738,15 +738,16 @@
 		     struct hostapd_radius_server *oserv,
 		     int sock, int sock6, int auth)
 {
-	struct sockaddr_in serv;
+	struct sockaddr_in serv, claddr;
 #ifdef CONFIG_IPV6
-	struct sockaddr_in6 serv6;
+	struct sockaddr_in6 serv6, claddr6;
 #endif /* CONFIG_IPV6 */
-	struct sockaddr *addr;
-	socklen_t addrlen;
+	struct sockaddr *addr, *cl_addr;
+	socklen_t addrlen, claddrlen;
 	char abuf[50];
 	int sel_sock;
 	struct radius_msg_list *entry;
+	struct hostapd_radius_servers *conf = radius->conf;
 
 	hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
 		       HOSTAPD_LEVEL_INFO,
@@ -816,10 +817,64 @@
 		return -1;
 	}
 
+	if (conf->force_client_addr) {
+		switch (conf->client_addr.af) {
+		case AF_INET:
+			os_memset(&claddr, 0, sizeof(claddr));
+			claddr.sin_family = AF_INET;
+			claddr.sin_addr.s_addr = conf->client_addr.u.v4.s_addr;
+			claddr.sin_port = htons(0);
+			cl_addr = (struct sockaddr *) &claddr;
+			claddrlen = sizeof(claddr);
+			break;
+#ifdef CONFIG_IPV6
+		case AF_INET6:
+			os_memset(&claddr6, 0, sizeof(claddr6));
+			claddr6.sin6_family = AF_INET6;
+			os_memcpy(&claddr6.sin6_addr, &conf->client_addr.u.v6,
+				  sizeof(struct in6_addr));
+			claddr6.sin6_port = htons(0);
+			cl_addr = (struct sockaddr *) &claddr6;
+			claddrlen = sizeof(claddr6);
+			break;
+#endif /* CONFIG_IPV6 */
+		default:
+			return -1;
+		}
+
+		if (bind(sel_sock, cl_addr, claddrlen) < 0) {
+			perror("bind[radius]");
+			return -1;
+		}
+	}
+
 	if (connect(sel_sock, addr, addrlen) < 0) {
 		perror("connect[radius]");
 		return -1;
 	}
+
+#ifndef CONFIG_NATIVE_WINDOWS
+	switch (nserv->addr.af) {
+	case AF_INET:
+		claddrlen = sizeof(claddr);
+		getsockname(sel_sock, (struct sockaddr *) &claddr, &claddrlen);
+		wpa_printf(MSG_DEBUG, "RADIUS local address: %s:%u",
+			   inet_ntoa(claddr.sin_addr), ntohs(claddr.sin_port));
+		break;
+#ifdef CONFIG_IPV6
+	case AF_INET6: {
+		claddrlen = sizeof(claddr6);
+		getsockname(sel_sock, (struct sockaddr *) &claddr6,
+			    &claddrlen);
+		wpa_printf(MSG_DEBUG, "RADIUS local address: %s:%u",
+			   inet_ntop(AF_INET6, &claddr6.sin6_addr,
+				     abuf, sizeof(abuf)),
+			   ntohs(claddr6.sin6_port));
+		break;
+	}
+#endif /* CONFIG_IPV6 */
+	}
+#endif /* CONFIG_NATIVE_WINDOWS */
 
 	if (auth)
 		radius->auth_sock = sel_sock;

Modified: wpasupplicant/trunk/src/radius/radius_client.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/radius/radius_client.h?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/radius/radius_client.h (original)
+++ wpasupplicant/trunk/src/radius/radius_client.h Sat Jun 14 00:40:26 2008
@@ -57,6 +57,9 @@
 	int acct_interim_interval;
 
 	int msg_dumps;
+
+	struct hostapd_ip_addr client_addr;
+	int force_client_addr;
 };
 
 

Modified: wpasupplicant/trunk/src/radius/radius_server.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/radius/radius_server.c?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/radius/radius_server.c (original)
+++ wpasupplicant/trunk/src/radius/radius_server.c Sat Jun 14 00:40:26 2008
@@ -87,6 +87,7 @@
 	u8 *pac_opaque_encr_key;
 	char *eap_fast_a_id;
 	int eap_sim_aka_result_ind;
+	int tnc;
 	int ipv6;
 	struct os_time start_time;
 	struct radius_server_counters counters;
@@ -311,6 +312,7 @@
 	eap_conf.pac_opaque_encr_key = data->pac_opaque_encr_key;
 	eap_conf.eap_fast_a_id = data->eap_fast_a_id;
 	eap_conf.eap_sim_aka_result_ind = data->eap_sim_aka_result_ind;
+	eap_conf.tnc = data->tnc;
 	sess->eap = eap_server_sm_init(sess, &radius_server_eapol_cb,
 				       &eap_conf);
 	if (sess->eap == NULL) {
@@ -1016,6 +1018,7 @@
 		data->eap_fast_a_id = os_strdup(conf->eap_fast_a_id);
 	data->get_eap_user = conf->get_eap_user;
 	data->eap_sim_aka_result_ind = conf->eap_sim_aka_result_ind;
+	data->tnc = conf->tnc;
 
 	data->clients = radius_server_read_clients(conf->client_file,
 						   conf->ipv6);

Modified: wpasupplicant/trunk/src/radius/radius_server.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/radius/radius_server.h?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/radius/radius_server.h (original)
+++ wpasupplicant/trunk/src/radius/radius_server.h Sat Jun 14 00:40:26 2008
@@ -27,6 +27,7 @@
 	u8 *pac_opaque_encr_key;
 	char *eap_fast_a_id;
 	int eap_sim_aka_result_ind;
+	int tnc;
 	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/peerkey.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/rsn_supp/peerkey.c?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/rsn_supp/peerkey.c (original)
+++ wpasupplicant/trunk/src/rsn_supp/peerkey.c Sat Jun 14 00:40:26 2008
@@ -867,8 +867,8 @@
 	if (peerkey->cipher == WPA_CIPHER_TKIP) {
 		/* Swap Tx/Rx keys for Michael MIC */
 		os_memcpy(key_buf, _key, 16);
-		os_memcpy(key_buf + 16, _key + 24, 8);
-		os_memcpy(key_buf + 24, _key + 16, 8);
+		os_memcpy(key_buf + 16, peerkey->stk.u.auth.rx_mic_key, 8);
+		os_memcpy(key_buf + 24, peerkey->stk.u.auth.tx_mic_key, 8);
 		_key = key_buf;
 		key_len = 32;
 	} else

Modified: wpasupplicant/trunk/src/rsn_supp/preauth.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/rsn_supp/preauth.c?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/rsn_supp/preauth.c (original)
+++ wpasupplicant/trunk/src/rsn_supp/preauth.c Sat Jun 14 00:40:26 2008
@@ -68,8 +68,7 @@
 	wpa_hexdump(MSG_MSGDUMP, "RX pre-auth", buf, len);
 
 	if (sm->preauth_eapol == NULL ||
-	    os_memcmp(sm->preauth_bssid, "\x00\x00\x00\x00\x00\x00",
-		      ETH_ALEN) == 0 ||
+	    is_zero_ether_addr(sm->preauth_bssid) ||
 	    os_memcmp(sm->preauth_bssid, src_addr, ETH_ALEN) != 0) {
 		wpa_printf(MSG_WARNING, "RSN pre-auth frame received from "
 			   "unexpected source " MACSTR " - dropped",

Modified: wpasupplicant/trunk/src/rsn_supp/wpa.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/rsn_supp/wpa.c?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/rsn_supp/wpa.c (original)
+++ wpasupplicant/trunk/src/rsn_supp/wpa.c Sat Jun 14 00:40:26 2008
@@ -98,8 +98,7 @@
 			int ver, const u8 *dest, u16 proto,
 			u8 *msg, size_t msg_len, u8 *key_mic)
 {
-	if (os_memcmp(dest, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) == 0 &&
-	    os_memcmp(sm->bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) == 0) {
+	if (is_zero_ether_addr(dest) && is_zero_ether_addr(sm->bssid)) {
 		/*
 		 * Association event was not yet received; try to fetch
 		 * BSSID from the driver.
@@ -451,7 +450,6 @@
 		MACSTR " [PTK=%s GTK=%s]", MAC2STR(addr),
 		wpa_cipher_txt(sm->pairwise_cipher),
 		wpa_cipher_txt(sm->group_cipher));
-	wpa_sm_cancel_scan(sm);
 	wpa_sm_cancel_auth_timeout(sm);
 	wpa_sm_set_state(sm, WPA_COMPLETED);
 
@@ -783,7 +781,6 @@
 	}
 
 	wpa_sm_disassociate(sm, WLAN_REASON_IE_IN_4WAY_DIFFERS);
-	wpa_sm_req_scan(sm, 0, 0);
 }
 
 
@@ -1791,7 +1788,6 @@
 
 		os_memset(sm->pmk, 0, sizeof(sm->pmk));
 		wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED);
-		wpa_sm_req_scan(sm, 0, 0);
 	}
 }
 
@@ -1859,6 +1855,8 @@
  */
 void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 *bssid)
 {
+	int clear_ptk = 1;
+
 	if (sm == NULL)
 		return;
 
@@ -1871,15 +1869,25 @@
 		rsn_preauth_deinit(sm);
 
 #ifdef CONFIG_IEEE80211R
-	if ((sm->key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X ||
-	     sm->key_mgmt == WPA_KEY_MGMT_FT_PSK) &&
-	    wpa_ft_is_completed(sm)) {
+	if (wpa_ft_is_completed(sm)) {
 		wpa_supplicant_key_neg_complete(sm, sm->bssid, 1);
 
 		/* Prepare for the next transition */
 		wpa_ft_prepare_auth_request(sm);
+
+		clear_ptk = 0;
 	}
 #endif /* CONFIG_IEEE80211R */
+
+	if (clear_ptk) {
+		/*
+		 * IEEE 802.11, 8.4.10: Delete PTK SA on (re)association if
+		 * this is not part of a Fast BSS Transition.
+		 */
+		wpa_printf(MSG_DEBUG, "WPA: Clear old PTK");
+		sm->ptk_set = 0;
+		sm->tptk_set = 0;
+	}
 }
 
 

Modified: wpasupplicant/trunk/src/rsn_supp/wpa.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/rsn_supp/wpa.h?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/rsn_supp/wpa.h (original)
+++ wpasupplicant/trunk/src/rsn_supp/wpa.h Sat Jun 14 00:40:26 2008
@@ -36,8 +36,6 @@
 
 	void (*set_state)(void *ctx, wpa_states state);
 	wpa_states (*get_state)(void *ctx);
-	void (*req_scan)(void *ctx, int sec, int usec);
-	void (*cancel_scan)(void *ctx);
 	void (*deauthenticate)(void * ctx, int reason_code); 
 	void (*disassociate)(void *ctx, int reason_code);
 	int (*set_key)(void *ctx, wpa_alg alg,
@@ -280,7 +278,7 @@
 			    int ft_action, const u8 *target_ap);
 int wpa_ft_is_completed(struct wpa_sm *sm);
 int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies,
-				 size_t ies_len);
+				 size_t ies_len, const u8 *src_addr);
 int wpa_ft_start_over_ds(struct wpa_sm *sm, const u8 *target_ap);
 
 #else /* CONFIG_IEEE80211R */
@@ -310,7 +308,8 @@
 }
 
 static inline int
-wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, size_t ies_len)
+wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, size_t ies_len,
+			     const u8 *src_addr)
 {
 	return -1;
 }

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=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/rsn_supp/wpa_ft.c (original)
+++ wpasupplicant/trunk/src/rsn_supp/wpa_ft.c Sat Jun 14 00:40:26 2008
@@ -121,7 +121,7 @@
 			       const u8 *kck, const u8 *target_ap)
 {
 	size_t buf_len;
-	u8 *buf, *pos, *ftie_len;
+	u8 *buf, *pos, *ftie_len, *ftie_pos;
 	struct rsn_mdie *mdie;
 	struct rsn_ftie *ftie;
 	struct rsn_ie_hdr *rsnie;
@@ -226,6 +226,7 @@
 	mdie->ft_capab = 0; /* FIX: copy from the target AP's MDIE */
 
 	/* FTIE[SNonce, R0KH-ID] */
+	ftie_pos = pos;
 	*pos++ = WLAN_EID_FAST_BSS_TRANSITION;
 	ftie_len = pos++;
 	ftie = (struct rsn_ftie *) pos;
@@ -255,7 +256,7 @@
 		ftie->mic_control[1] = 3; /* Information element count */
 		if (wpa_ft_mic(kck, sm->own_addr, target_ap, 5,
 			       ((u8 *) mdie) - 2, 2 + sizeof(*mdie),
-			       ((u8 *) ftie) - 2, 2 + *ftie_len,
+			       ftie_pos, 2 + *ftie_len,
 			       (u8 *) rsnie, 2 + rsnie->len, NULL, 0,
 			       ftie->mic) < 0) {
 			wpa_printf(MSG_INFO, "FT: Failed to calculate MIC");
@@ -535,7 +536,7 @@
 	wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name",
 		    sm->pmk_r1_name, WPA_PMK_NAME_LEN);
 
-	bssid = ft_action ? sm->target_ap : sm->bssid;
+	bssid = target_ap;
 	wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->snonce, ftie->anonce, sm->own_addr,
 			  bssid, sm->pmk_r1_name,
 			  (u8 *) &sm->ptk, sizeof(sm->ptk), ptk_name);
@@ -581,7 +582,7 @@
 
 
 int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies,
-				 size_t ies_len)
+				 size_t ies_len, const u8 *src_addr)
 {
 	struct wpa_ft_ies parse;
 	struct rsn_mdie *mdie;
@@ -664,7 +665,7 @@
 		return -1;
 	}
 
-	if (wpa_ft_mic(sm->ptk.kck, sm->own_addr, sm->bssid, 6,
+	if (wpa_ft_mic(sm->ptk.kck, sm->own_addr, src_addr, 6,
 		       parse.mdie - 2, parse.mdie_len + 2,
 		       parse.ftie - 2, parse.ftie_len + 2,
 		       parse.rsn - 2, parse.rsn_len + 2, NULL, 0,

Modified: wpasupplicant/trunk/src/rsn_supp/wpa_i.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/rsn_supp/wpa_i.h?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/rsn_supp/wpa_i.h (original)
+++ wpasupplicant/trunk/src/rsn_supp/wpa_i.h Sat Jun 14 00:40:26 2008
@@ -120,18 +120,6 @@
 	return sm->ctx->get_state(sm->ctx->ctx);
 }
 
-static inline void wpa_sm_req_scan(struct wpa_sm *sm, int sec, int usec)
-{
-	WPA_ASSERT(sm->ctx->req_scan);
-	sm->ctx->req_scan(sm->ctx->ctx, sec, usec);
-}
-
-static inline void wpa_sm_cancel_scan(struct wpa_sm *sm)
-{
-	WPA_ASSERT(sm->ctx->cancel_scan);
-	sm->ctx->cancel_scan(sm->ctx->ctx);
-}
-
 static inline void wpa_sm_deauthenticate(struct wpa_sm *sm, int reason_code)
 {
 	WPA_ASSERT(sm->ctx->deauthenticate);

Modified: wpasupplicant/trunk/src/tls/libtommath.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/tls/libtommath.c?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/tls/libtommath.c (original)
+++ wpasupplicant/trunk/src/tls/libtommath.c Sat Jun 14 00:40:26 2008
@@ -1,17 +1,14 @@
 /*
- * Minimal code for RSA support from LibTomMath 0.3.9
- * http://math.libtomcrypt.com/
- * http://math.libtomcrypt.com/files/ltm-0.39.tar.bz2
+ * Minimal code for RSA support from LibTomMath 0.41
+ * http://libtom.org/
+ * http://libtom.org/files/ltm-0.41.tar.bz2
  * This library was released in public domain by Tom St Denis.
  *
- * The combination in this file is not using many of the optimized algorithms
- * (e.g., Montgomery reduction) and is considerable slower than the LibTomMath
- * with its default of SC_RSA_1 settins. The main purpose of having this
- * version here is to make it easier to build bignum.c wrapper without having
- * to install and build an external library. However, it is likely worth the
- * effort to use the full library with SC_RSA_1 instead of this minimized copy.
- * Including the optimized algorithms may increase the size requirements by
- * 15 kB or so (measured with x86 build).
+ * The combination in this file may not use all of the optimized algorithms
+ * from LibTomMath and may be considerable slower than the LibTomMath with its
+ * default settings. The main purpose of having this version here is to make it
+ * easier to build bignum.c wrapper without having to install and build an
+ * external library.
  *
  * If CONFIG_INTERNAL_LIBTOMMATH is defined, bignum.c includes this
  * libtommath.c file instead of using the external LibTomMath library.
@@ -30,6 +27,32 @@
 #define BN_S_MP_MUL_HIGH_DIGS_C /* Note: #undef in tommath_superclass.h; this
 				 * would require other than mp_reduce */
 
+#ifdef LTM_FAST
+
+/* Use faster div at the cost of about 1 kB */
+#define BN_MP_MUL_D_C
+
+/* Include faster exptmod (Montgomery) at the cost of about 2.5 kB in code */
+#define BN_MP_EXPTMOD_FAST_C
+#define BN_MP_MONTGOMERY_SETUP_C
+#define BN_FAST_MP_MONTGOMERY_REDUCE_C
+#define BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+#define BN_MP_MUL_2_C
+
+/* Include faster sqr at the cost of about 0.5 kB in code */
+#define BN_FAST_S_MP_SQR_C
+
+#else /* LTM_FAST */
+
+#define BN_MP_DIV_SMALL
+#define BN_MP_INIT_MULTI_C
+#define BN_MP_CLEAR_MULTI_C
+#define BN_MP_ABS_C
+#endif /* LTM_FAST */
+
+/* Current uses do not require support for negative exponent in exptmod, so we
+ * can save about 1.5 kB in leaving out invmod. */
+#define LTM_NO_NEG_EXP
 
 /* from tommath.h */
 
@@ -110,8 +133,12 @@
 
 static int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs);
 
+#ifdef BN_MP_INIT_MULTI_C
 static int mp_init_multi(mp_int *mp, ...);
+#endif
+#ifdef BN_MP_CLEAR_MULTI_C
 static void mp_clear_multi(mp_int *mp, ...);
+#endif
 static int mp_lshd(mp_int * a, int b);
 static void mp_set(mp_int * a, mp_digit b);
 static void mp_clamp(mp_int * a);
@@ -122,16 +149,20 @@
 static int mp_div_2d(mp_int * a, int b, mp_int * c, mp_int * d);
 static int mp_init_copy(mp_int * a, mp_int * b);
 static int mp_mul_2d(mp_int * a, int b, mp_int * c);
+#ifndef LTM_NO_NEG_EXP
 static int mp_div_2(mp_int * a, mp_int * b);
+static int mp_invmod(mp_int * a, mp_int * b, mp_int * c);
+static int mp_invmod_slow(mp_int * a, mp_int * b, mp_int * c);
+#endif /* LTM_NO_NEG_EXP */
 static int mp_copy(mp_int * a, mp_int * b);
 static int mp_count_bits(mp_int * a);
 static int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d);
 static int mp_mod(mp_int * a, mp_int * b, mp_int * c);
 static int mp_grow(mp_int * a, int size);
 static int mp_cmp_mag(mp_int * a, mp_int * b);
-static int mp_invmod(mp_int * a, mp_int * b, mp_int * c);
+#ifdef BN_MP_ABS_C
 static int mp_abs(mp_int * a, mp_int * b);
-static int mp_invmod_slow(mp_int * a, mp_int * b, mp_int * c);
+#endif
 static int mp_sqr(mp_int * a, mp_int * b);
 static int mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d);
 static int mp_reduce_2k_setup_l(mp_int *a, mp_int *d);
@@ -139,6 +170,15 @@
 static int mp_reduce_setup(mp_int * a, mp_int * b);
 static int mp_reduce(mp_int * x, mp_int * m, mp_int * mu);
 static int mp_init_size(mp_int * a, int size);
+#ifdef BN_MP_EXPTMOD_FAST_C
+static int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode);
+#endif /* BN_MP_EXPTMOD_FAST_C */
+#ifdef BN_FAST_S_MP_SQR_C
+static int fast_s_mp_sqr (mp_int * a, mp_int * b);
+#endif /* BN_FAST_S_MP_SQR_C */
+#ifdef BN_MP_MUL_D_C
+static int mp_mul_d (mp_int * a, mp_digit b, mp_int * c);
+#endif /* BN_MP_MUL_D_C */
 
 
 
@@ -546,6 +586,9 @@
 
   /* if exponent X is negative we have to recurse */
   if (X->sign == MP_NEG) {
+#ifdef LTM_NO_NEG_EXP
+        return MP_VAL;
+#else /* LTM_NO_NEG_EXP */
 #ifdef BN_MP_INVMOD_C
      mp_int tmpG, tmpX;
      int err;
@@ -578,6 +621,7 @@
      /* no invmod */
      return MP_VAL;
 #endif
+#endif /* LTM_NO_NEG_EXP */
   }
 
 /* modified diminished radix reduction */
@@ -668,6 +712,7 @@
 }
 
 
+#ifndef LTM_NO_NEG_EXP
 /* hac 14.61, pp608 */
 static int mp_invmod (mp_int * a, mp_int * b, mp_int * c)
 {
@@ -694,6 +739,7 @@
 #endif
   return MP_VAL;
 }
+#endif /* LTM_NO_NEG_EXP */
 
 
 /* get the size for an unsigned equivalent */
@@ -704,6 +750,7 @@
 }
 
 
+#ifndef LTM_NO_NEG_EXP
 /* hac 14.61, pp608 */
 static int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c)
 {
@@ -857,6 +904,7 @@
 LBL_ERR:mp_clear_multi (&x, &y, &u, &v, &A, &B, &C, &D, NULL);
   return res;
 }
+#endif /* LTM_NO_NEG_EXP */
 
 
 /* compare maginitude of two ints (unsigned) */
@@ -1233,6 +1281,7 @@
 }
 
 
+#ifdef BN_MP_ABS_C
 /* b = |a| 
  *
  * Simple function copies the input and fixes the sign to positive
@@ -1253,6 +1302,7 @@
 
   return MP_OKAY;
 }
+#endif
 
 
 /* set to a digit */
@@ -1264,6 +1314,7 @@
 }
 
 
+#ifndef LTM_NO_NEG_EXP
 /* b = a/2 */
 static int mp_div_2(mp_int * a, mp_int * b)
 {
@@ -1310,6 +1361,7 @@
   mp_clamp (b);
   return MP_OKAY;
 }
+#endif /* LTM_NO_NEG_EXP */
 
 
 /* shift left by a certain bit count */
@@ -1377,6 +1429,7 @@
 }
 
 
+#ifdef BN_MP_INIT_MULTI_C
 static int mp_init_multi(mp_int *mp, ...) 
 {
     mp_err res = MP_OKAY;      /* Assume ok until proven otherwise */
@@ -1412,8 +1465,10 @@
     va_end(args);
     return res;                /* Assumed ok, if error flagged above. */
 }
-
-
+#endif
+
+
+#ifdef BN_MP_CLEAR_MULTI_C
 static void mp_clear_multi(mp_int *mp, ...) 
 {
     mp_int* next_mp = mp;
@@ -1425,6 +1480,7 @@
     }
     va_end(args);
 }
+#endif
 
 
 /* shift left a certain amount of digits */
@@ -1531,6 +1587,8 @@
   return MP_OKAY;
 }
 
+
+#ifdef BN_MP_DIV_SMALL
 
 /* slower bit-bang division... also smaller */
 static int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d)
@@ -1599,6 +1657,206 @@
    mp_clear_multi(&ta, &tb, &tq, &q, NULL);
    return res;
 }
+
+#else
+
+/* integer signed division. 
+ * c*b + d == a [e.g. a/b, c=quotient, d=remainder]
+ * HAC pp.598 Algorithm 14.20
+ *
+ * Note that the description in HAC is horribly 
+ * incomplete.  For example, it doesn't consider 
+ * the case where digits are removed from 'x' in 
+ * the inner loop.  It also doesn't consider the 
+ * case that y has fewer than three digits, etc..
+ *
+ * The overall algorithm is as described as 
+ * 14.20 from HAC but fixed to treat these cases.
+*/
+static int mp_div (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
+{
+  mp_int  q, x, y, t1, t2;
+  int     res, n, t, i, norm, neg;
+
+  /* is divisor zero ? */
+  if (mp_iszero (b) == 1) {
+    return MP_VAL;
+  }
+
+  /* if a < b then q=0, r = a */
+  if (mp_cmp_mag (a, b) == MP_LT) {
+    if (d != NULL) {
+      res = mp_copy (a, d);
+    } else {
+      res = MP_OKAY;
+    }
+    if (c != NULL) {
+      mp_zero (c);
+    }
+    return res;
+  }
+
+  if ((res = mp_init_size (&q, a->used + 2)) != MP_OKAY) {
+    return res;
+  }
+  q.used = a->used + 2;
+
+  if ((res = mp_init (&t1)) != MP_OKAY) {
+    goto LBL_Q;
+  }
+
+  if ((res = mp_init (&t2)) != MP_OKAY) {
+    goto LBL_T1;
+  }
+
+  if ((res = mp_init_copy (&x, a)) != MP_OKAY) {
+    goto LBL_T2;
+  }
+
+  if ((res = mp_init_copy (&y, b)) != MP_OKAY) {
+    goto LBL_X;
+  }
+
+  /* fix the sign */
+  neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;
+  x.sign = y.sign = MP_ZPOS;
+
+  /* normalize both x and y, ensure that y >= b/2, [b == 2**DIGIT_BIT] */
+  norm = mp_count_bits(&y) % DIGIT_BIT;
+  if (norm < (int)(DIGIT_BIT-1)) {
+     norm = (DIGIT_BIT-1) - norm;
+     if ((res = mp_mul_2d (&x, norm, &x)) != MP_OKAY) {
+       goto LBL_Y;
+     }
+     if ((res = mp_mul_2d (&y, norm, &y)) != MP_OKAY) {
+       goto LBL_Y;
+     }
+  } else {
+     norm = 0;
+  }
+
+  /* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */
+  n = x.used - 1;
+  t = y.used - 1;
+
+  /* while (x >= y*b**n-t) do { q[n-t] += 1; x -= y*b**{n-t} } */
+  if ((res = mp_lshd (&y, n - t)) != MP_OKAY) { /* y = y*b**{n-t} */
+    goto LBL_Y;
+  }
+
+  while (mp_cmp (&x, &y) != MP_LT) {
+    ++(q.dp[n - t]);
+    if ((res = mp_sub (&x, &y, &x)) != MP_OKAY) {
+      goto LBL_Y;
+    }
+  }
+
+  /* reset y by shifting it back down */
+  mp_rshd (&y, n - t);
+
+  /* step 3. for i from n down to (t + 1) */
+  for (i = n; i >= (t + 1); i--) {
+    if (i > x.used) {
+      continue;
+    }
+
+    /* step 3.1 if xi == yt then set q{i-t-1} to b-1, 
+     * otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */
+    if (x.dp[i] == y.dp[t]) {
+      q.dp[i - t - 1] = ((((mp_digit)1) << DIGIT_BIT) - 1);
+    } else {
+      mp_word tmp;
+      tmp = ((mp_word) x.dp[i]) << ((mp_word) DIGIT_BIT);
+      tmp |= ((mp_word) x.dp[i - 1]);
+      tmp /= ((mp_word) y.dp[t]);
+      if (tmp > (mp_word) MP_MASK)
+        tmp = MP_MASK;
+      q.dp[i - t - 1] = (mp_digit) (tmp & (mp_word) (MP_MASK));
+    }
+
+    /* while (q{i-t-1} * (yt * b + y{t-1})) > 
+             xi * b**2 + xi-1 * b + xi-2 
+     
+       do q{i-t-1} -= 1; 
+    */
+    q.dp[i - t - 1] = (q.dp[i - t - 1] + 1) & MP_MASK;
+    do {
+      q.dp[i - t - 1] = (q.dp[i - t - 1] - 1) & MP_MASK;
+
+      /* find left hand */
+      mp_zero (&t1);
+      t1.dp[0] = (t - 1 < 0) ? 0 : y.dp[t - 1];
+      t1.dp[1] = y.dp[t];
+      t1.used = 2;
+      if ((res = mp_mul_d (&t1, q.dp[i - t - 1], &t1)) != MP_OKAY) {
+        goto LBL_Y;
+      }
+
+      /* find right hand */
+      t2.dp[0] = (i - 2 < 0) ? 0 : x.dp[i - 2];
+      t2.dp[1] = (i - 1 < 0) ? 0 : x.dp[i - 1];
+      t2.dp[2] = x.dp[i];
+      t2.used = 3;
+    } while (mp_cmp_mag(&t1, &t2) == MP_GT);
+
+    /* step 3.3 x = x - q{i-t-1} * y * b**{i-t-1} */
+    if ((res = mp_mul_d (&y, q.dp[i - t - 1], &t1)) != MP_OKAY) {
+      goto LBL_Y;
+    }
+
+    if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) {
+      goto LBL_Y;
+    }
+
+    if ((res = mp_sub (&x, &t1, &x)) != MP_OKAY) {
+      goto LBL_Y;
+    }
+
+    /* if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; } */
+    if (x.sign == MP_NEG) {
+      if ((res = mp_copy (&y, &t1)) != MP_OKAY) {
+        goto LBL_Y;
+      }
+      if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) {
+        goto LBL_Y;
+      }
+      if ((res = mp_add (&x, &t1, &x)) != MP_OKAY) {
+        goto LBL_Y;
+      }
+
+      q.dp[i - t - 1] = (q.dp[i - t - 1] - 1UL) & MP_MASK;
+    }
+  }
+
+  /* now q is the quotient and x is the remainder 
+   * [which we have to normalize] 
+   */
+  
+  /* get sign before writing to c */
+  x.sign = x.used == 0 ? MP_ZPOS : a->sign;
+
+  if (c != NULL) {
+    mp_clamp (&q);
+    mp_exch (&q, c);
+    c->sign = neg;
+  }
+
+  if (d != NULL) {
+    mp_div_2d (&x, norm, &x, NULL);
+    mp_exch (&x, d);
+  }
+
+  res = MP_OKAY;
+
+LBL_Y:mp_clear (&y);
+LBL_X:mp_clear (&x);
+LBL_T2:mp_clear (&t2);
+LBL_T1:mp_clear (&t1);
+LBL_Q:mp_clear (&q);
+  return res;
+}
+
+#endif
 
 
 #ifdef MP_LOW_MEM
@@ -2368,3 +2626,756 @@
   mp_clear (&t);
   return MP_OKAY;
 }
+
+
+#ifdef BN_MP_MONTGOMERY_SETUP_C
+/* setups the montgomery reduction stuff */
+static int
+mp_montgomery_setup (mp_int * n, mp_digit * rho)
+{
+  mp_digit x, b;
+
+/* fast inversion mod 2**k
+ *
+ * Based on the fact that
+ *
+ * XA = 1 (mod 2**n)  =>  (X(2-XA)) A = 1 (mod 2**2n)
+ *                    =>  2*X*A - X*X*A*A = 1
+ *                    =>  2*(1) - (1)     = 1
+ */
+  b = n->dp[0];
+
+  if ((b & 1) == 0) {
+    return MP_VAL;
+  }
+
+  x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
+  x *= 2 - b * x;               /* here x*a==1 mod 2**8 */
+#if !defined(MP_8BIT)
+  x *= 2 - b * x;               /* here x*a==1 mod 2**16 */
+#endif
+#if defined(MP_64BIT) || !(defined(MP_8BIT) || defined(MP_16BIT))
+  x *= 2 - b * x;               /* here x*a==1 mod 2**32 */
+#endif
+#ifdef MP_64BIT
+  x *= 2 - b * x;               /* here x*a==1 mod 2**64 */
+#endif
+
+  /* rho = -1/m mod b */
+  *rho = (unsigned long)(((mp_word)1 << ((mp_word) DIGIT_BIT)) - x) & MP_MASK;
+
+  return MP_OKAY;
+}
+#endif
+
+
+#ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C
+/* computes xR**-1 == x (mod N) via Montgomery Reduction
+ *
+ * This is an optimized implementation of montgomery_reduce
+ * which uses the comba method to quickly calculate the columns of the
+ * reduction.
+ *
+ * Based on Algorithm 14.32 on pp.601 of HAC.
+*/
+int fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho)
+{
+  int     ix, res, olduse;
+  mp_word W[MP_WARRAY];
+
+  /* get old used count */
+  olduse = x->used;
+
+  /* grow a as required */
+  if (x->alloc < n->used + 1) {
+    if ((res = mp_grow (x, n->used + 1)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  /* first we have to get the digits of the input into
+   * an array of double precision words W[...]
+   */
+  {
+    register mp_word *_W;
+    register mp_digit *tmpx;
+
+    /* alias for the W[] array */
+    _W   = W;
+
+    /* alias for the digits of  x*/
+    tmpx = x->dp;
+
+    /* copy the digits of a into W[0..a->used-1] */
+    for (ix = 0; ix < x->used; ix++) {
+      *_W++ = *tmpx++;
+    }
+
+    /* zero the high words of W[a->used..m->used*2] */
+    for (; ix < n->used * 2 + 1; ix++) {
+      *_W++ = 0;
+    }
+  }
+
+  /* now we proceed to zero successive digits
+   * from the least significant upwards
+   */
+  for (ix = 0; ix < n->used; ix++) {
+    /* mu = ai * m' mod b
+     *
+     * We avoid a double precision multiplication (which isn't required)
+     * by casting the value down to a mp_digit.  Note this requires
+     * that W[ix-1] have  the carry cleared (see after the inner loop)
+     */
+    register mp_digit mu;
+    mu = (mp_digit) (((W[ix] & MP_MASK) * rho) & MP_MASK);
+
+    /* a = a + mu * m * b**i
+     *
+     * This is computed in place and on the fly.  The multiplication
+     * by b**i is handled by offseting which columns the results
+     * are added to.
+     *
+     * Note the comba method normally doesn't handle carries in the
+     * inner loop In this case we fix the carry from the previous
+     * column since the Montgomery reduction requires digits of the
+     * result (so far) [see above] to work.  This is
+     * handled by fixing up one carry after the inner loop.  The
+     * carry fixups are done in order so after these loops the
+     * first m->used words of W[] have the carries fixed
+     */
+    {
+      register int iy;
+      register mp_digit *tmpn;
+      register mp_word *_W;
+
+      /* alias for the digits of the modulus */
+      tmpn = n->dp;
+
+      /* Alias for the columns set by an offset of ix */
+      _W = W + ix;
+
+      /* inner loop */
+      for (iy = 0; iy < n->used; iy++) {
+          *_W++ += ((mp_word)mu) * ((mp_word)*tmpn++);
+      }
+    }
+
+    /* now fix carry for next digit, W[ix+1] */
+    W[ix + 1] += W[ix] >> ((mp_word) DIGIT_BIT);
+  }
+
+  /* now we have to propagate the carries and
+   * shift the words downward [all those least
+   * significant digits we zeroed].
+   */
+  {
+    register mp_digit *tmpx;
+    register mp_word *_W, *_W1;
+
+    /* nox fix rest of carries */
+
+    /* alias for current word */
+    _W1 = W + ix;
+
+    /* alias for next word, where the carry goes */
+    _W = W + ++ix;
+
+    for (; ix <= n->used * 2 + 1; ix++) {
+      *_W++ += *_W1++ >> ((mp_word) DIGIT_BIT);
+    }
+
+    /* copy out, A = A/b**n
+     *
+     * The result is A/b**n but instead of converting from an
+     * array of mp_word to mp_digit than calling mp_rshd
+     * we just copy them in the right order
+     */
+
+    /* alias for destination word */
+    tmpx = x->dp;
+
+    /* alias for shifted double precision result */
+    _W = W + n->used;
+
+    for (ix = 0; ix < n->used + 1; ix++) {
+      *tmpx++ = (mp_digit)(*_W++ & ((mp_word) MP_MASK));
+    }
+
+    /* zero oldused digits, if the input a was larger than
+     * m->used+1 we'll have to clear the digits
+     */
+    for (; ix < olduse; ix++) {
+      *tmpx++ = 0;
+    }
+  }
+
+  /* set the max used and clamp */
+  x->used = n->used + 1;
+  mp_clamp (x);
+
+  /* if A >= m then A = A - m */
+  if (mp_cmp_mag (x, n) != MP_LT) {
+    return s_mp_sub (x, n, x);
+  }
+  return MP_OKAY;
+}
+#endif
+
+
+#ifdef BN_MP_MUL_2_C
+/* b = a*2 */
+static int mp_mul_2(mp_int * a, mp_int * b)
+{
+  int     x, res, oldused;
+
+  /* grow to accomodate result */
+  if (b->alloc < a->used + 1) {
+    if ((res = mp_grow (b, a->used + 1)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  oldused = b->used;
+  b->used = a->used;
+
+  {
+    register mp_digit r, rr, *tmpa, *tmpb;
+
+    /* alias for source */
+    tmpa = a->dp;
+    
+    /* alias for dest */
+    tmpb = b->dp;
+
+    /* carry */
+    r = 0;
+    for (x = 0; x < a->used; x++) {
+    
+      /* get what will be the *next* carry bit from the 
+       * MSB of the current digit 
+       */
+      rr = *tmpa >> ((mp_digit)(DIGIT_BIT - 1));
+      
+      /* now shift up this digit, add in the carry [from the previous] */
+      *tmpb++ = ((*tmpa++ << ((mp_digit)1)) | r) & MP_MASK;
+      
+      /* copy the carry that would be from the source 
+       * digit into the next iteration 
+       */
+      r = rr;
+    }
+
+    /* new leading digit? */
+    if (r != 0) {
+      /* add a MSB which is always 1 at this point */
+      *tmpb = 1;
+      ++(b->used);
+    }
+
+    /* now zero any excess digits on the destination 
+     * that we didn't write to 
+     */
+    tmpb = b->dp + b->used;
+    for (x = b->used; x < oldused; x++) {
+      *tmpb++ = 0;
+    }
+  }
+  b->sign = a->sign;
+  return MP_OKAY;
+}
+#endif
+
+
+#ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+/*
+ * shifts with subtractions when the result is greater than b.
+ *
+ * The method is slightly modified to shift B unconditionally upto just under
+ * the leading bit of b.  This saves alot of multiple precision shifting.
+ */
+static int mp_montgomery_calc_normalization (mp_int * a, mp_int * b)
+{
+  int     x, bits, res;
+
+  /* how many bits of last digit does b use */
+  bits = mp_count_bits (b) % DIGIT_BIT;
+
+  if (b->used > 1) {
+     if ((res = mp_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1)) != MP_OKAY) {
+        return res;
+     }
+  } else {
+     mp_set(a, 1);
+     bits = 1;
+  }
+
+
+  /* now compute C = A * B mod b */
+  for (x = bits - 1; x < (int)DIGIT_BIT; x++) {
+    if ((res = mp_mul_2 (a, a)) != MP_OKAY) {
+      return res;
+    }
+    if (mp_cmp_mag (a, b) != MP_LT) {
+      if ((res = s_mp_sub (a, b, a)) != MP_OKAY) {
+        return res;
+      }
+    }
+  }
+
+  return MP_OKAY;
+}
+#endif
+
+
+#ifdef BN_MP_EXPTMOD_FAST_C
+/* computes Y == G**X mod P, HAC pp.616, Algorithm 14.85
+ *
+ * Uses a left-to-right k-ary sliding window to compute the modular exponentiation.
+ * The value of k changes based on the size of the exponent.
+ *
+ * Uses Montgomery or Diminished Radix reduction [whichever appropriate]
+ */
+
+static int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode)
+{
+  mp_int  M[TAB_SIZE], res;
+  mp_digit buf, mp;
+  int     err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;
+
+  /* use a pointer to the reduction algorithm.  This allows us to use
+   * one of many reduction algorithms without modding the guts of
+   * the code with if statements everywhere.
+   */
+  int     (*redux)(mp_int*,mp_int*,mp_digit);
+
+  /* find window size */
+  x = mp_count_bits (X);
+  if (x <= 7) {
+    winsize = 2;
+  } else if (x <= 36) {
+    winsize = 3;
+  } else if (x <= 140) {
+    winsize = 4;
+  } else if (x <= 450) {
+    winsize = 5;
+  } else if (x <= 1303) {
+    winsize = 6;
+  } else if (x <= 3529) {
+    winsize = 7;
+  } else {
+    winsize = 8;
+  }
+
+#ifdef MP_LOW_MEM
+  if (winsize > 5) {
+     winsize = 5;
+  }
+#endif
+
+  /* init M array */
+  /* init first cell */
+  if ((err = mp_init(&M[1])) != MP_OKAY) {
+     return err;
+  }
+
+  /* now init the second half of the array */
+  for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
+    if ((err = mp_init(&M[x])) != MP_OKAY) {
+      for (y = 1<<(winsize-1); y < x; y++) {
+        mp_clear (&M[y]);
+      }
+      mp_clear(&M[1]);
+      return err;
+    }
+  }
+
+  /* determine and setup reduction code */
+  if (redmode == 0) {
+#ifdef BN_MP_MONTGOMERY_SETUP_C     
+     /* now setup montgomery  */
+     if ((err = mp_montgomery_setup (P, &mp)) != MP_OKAY) {
+        goto LBL_M;
+     }
+#else
+     err = MP_VAL;
+     goto LBL_M;
+#endif
+
+     /* automatically pick the comba one if available (saves quite a few calls/ifs) */
+#ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C
+     if (((P->used * 2 + 1) < MP_WARRAY) &&
+          P->used < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+        redux = fast_mp_montgomery_reduce;
+     } else 
+#endif
+     {
+#ifdef BN_MP_MONTGOMERY_REDUCE_C
+        /* use slower baseline Montgomery method */
+        redux = mp_montgomery_reduce;
+#else
+        err = MP_VAL;
+        goto LBL_M;
+#endif
+     }
+  } else if (redmode == 1) {
+#if defined(BN_MP_DR_SETUP_C) && defined(BN_MP_DR_REDUCE_C)
+     /* setup DR reduction for moduli of the form B**k - b */
+     mp_dr_setup(P, &mp);
+     redux = mp_dr_reduce;
+#else
+     err = MP_VAL;
+     goto LBL_M;
+#endif
+  } else {
+#if defined(BN_MP_REDUCE_2K_SETUP_C) && defined(BN_MP_REDUCE_2K_C)
+     /* setup DR reduction for moduli of the form 2**k - b */
+     if ((err = mp_reduce_2k_setup(P, &mp)) != MP_OKAY) {
+        goto LBL_M;
+     }
+     redux = mp_reduce_2k;
+#else
+     err = MP_VAL;
+     goto LBL_M;
+#endif
+  }
+
+  /* setup result */
+  if ((err = mp_init (&res)) != MP_OKAY) {
+    goto LBL_M;
+  }
+
+  /* create M table
+   *
+
+   *
+   * The first half of the table is not computed though accept for M[0] and M[1]
+   */
+
+  if (redmode == 0) {
+#ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+     /* now we need R mod m */
+     if ((err = mp_montgomery_calc_normalization (&res, P)) != MP_OKAY) {
+       goto LBL_RES;
+     }
+#else 
+     err = MP_VAL;
+     goto LBL_RES;
+#endif
+
+     /* now set M[1] to G * R mod m */
+     if ((err = mp_mulmod (G, &res, P, &M[1])) != MP_OKAY) {
+       goto LBL_RES;
+     }
+  } else {
+     mp_set(&res, 1);
+     if ((err = mp_mod(G, P, &M[1])) != MP_OKAY) {
+        goto LBL_RES;
+     }
+  }
+
+  /* compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times */
+  if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) {
+    goto LBL_RES;
+  }
+
+  for (x = 0; x < (winsize - 1); x++) {
+    if ((err = mp_sqr (&M[1 << (winsize - 1)], &M[1 << (winsize - 1)])) != MP_OKAY) {
+      goto LBL_RES;
+    }
+    if ((err = redux (&M[1 << (winsize - 1)], P, mp)) != MP_OKAY) {
+      goto LBL_RES;
+    }
+  }
+
+  /* create upper table */
+  for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
+    if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) {
+      goto LBL_RES;
+    }
+    if ((err = redux (&M[x], P, mp)) != MP_OKAY) {
+      goto LBL_RES;
+    }
+  }
+
+  /* set initial mode and bit cnt */
+  mode   = 0;
+  bitcnt = 1;
+  buf    = 0;
+  digidx = X->used - 1;
+  bitcpy = 0;
+  bitbuf = 0;
+
+  for (;;) {
+    /* grab next digit as required */
+    if (--bitcnt == 0) {
+      /* if digidx == -1 we are out of digits so break */
+      if (digidx == -1) {
+        break;
+      }
+      /* read next digit and reset bitcnt */
+      buf    = X->dp[digidx--];
+      bitcnt = (int)DIGIT_BIT;
+    }
+
+    /* grab the next msb from the exponent */
+    y     = (mp_digit)(buf >> (DIGIT_BIT - 1)) & 1;
+    buf <<= (mp_digit)1;
+
+    /* if the bit is zero and mode == 0 then we ignore it
+     * These represent the leading zero bits before the first 1 bit
+     * in the exponent.  Technically this opt is not required but it
+     * does lower the # of trivial squaring/reductions used
+     */
+    if (mode == 0 && y == 0) {
+      continue;
+    }
+
+    /* if the bit is zero and mode == 1 then we square */
+    if (mode == 1 && y == 0) {
+      if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      if ((err = redux (&res, P, mp)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      continue;
+    }
+
+    /* else we add it to the window */
+    bitbuf |= (y << (winsize - ++bitcpy));
+    mode    = 2;
+
+    if (bitcpy == winsize) {
+      /* ok window is filled so square as required and multiply  */
+      /* square first */
+      for (x = 0; x < winsize; x++) {
+        if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+        if ((err = redux (&res, P, mp)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+      }
+
+      /* then multiply */
+      if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      if ((err = redux (&res, P, mp)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+
+      /* empty window and reset */
+      bitcpy = 0;
+      bitbuf = 0;
+      mode   = 1;
+    }
+  }
+
+  /* if bits remain then square/multiply */
+  if (mode == 2 && bitcpy > 0) {
+    /* square then multiply if the bit is set */
+    for (x = 0; x < bitcpy; x++) {
+      if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      if ((err = redux (&res, P, mp)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+
+      /* get next bit of the window */
+      bitbuf <<= 1;
+      if ((bitbuf & (1 << winsize)) != 0) {
+        /* then multiply */
+        if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+        if ((err = redux (&res, P, mp)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+      }
+    }
+  }
+
+  if (redmode == 0) {
+     /* fixup result if Montgomery reduction is used
+      * recall that any value in a Montgomery system is
+      * actually multiplied by R mod n.  So we have
+      * to reduce one more time to cancel out the factor
+      * of R.
+      */
+     if ((err = redux(&res, P, mp)) != MP_OKAY) {
+       goto LBL_RES;
+     }
+  }
+
+  /* swap res with Y */
+  mp_exch (&res, Y);
+  err = MP_OKAY;
+LBL_RES:mp_clear (&res);
+LBL_M:
+  mp_clear(&M[1]);
+  for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
+    mp_clear (&M[x]);
+  }
+  return err;
+}
+#endif
+
+
+#ifdef BN_FAST_S_MP_SQR_C
+/* the jist of squaring...
+ * you do like mult except the offset of the tmpx [one that 
+ * starts closer to zero] can't equal the offset of tmpy.  
+ * So basically you set up iy like before then you min it with
+ * (ty-tx) so that it never happens.  You double all those 
+ * you add in the inner loop
+
+After that loop you do the squares and add them in.
+*/
+
+static int fast_s_mp_sqr (mp_int * a, mp_int * b)
+{
+  int       olduse, res, pa, ix, iz;
+  mp_digit   W[MP_WARRAY], *tmpx;
+  mp_word   W1;
+
+  /* grow the destination as required */
+  pa = a->used + a->used;
+  if (b->alloc < pa) {
+    if ((res = mp_grow (b, pa)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  /* number of output digits to produce */
+  W1 = 0;
+  for (ix = 0; ix < pa; ix++) { 
+      int      tx, ty, iy;
+      mp_word  _W;
+      mp_digit *tmpy;
+
+      /* clear counter */
+      _W = 0;
+
+      /* get offsets into the two bignums */
+      ty = MIN(a->used-1, ix);
+      tx = ix - ty;
+
+      /* setup temp aliases */
+      tmpx = a->dp + tx;
+      tmpy = a->dp + ty;
+
+      /* this is the number of times the loop will iterrate, essentially
+         while (tx++ < a->used && ty-- >= 0) { ... }
+       */
+      iy = MIN(a->used-tx, ty+1);
+
+      /* now for squaring tx can never equal ty 
+       * we halve the distance since they approach at a rate of 2x
+       * and we have to round because odd cases need to be executed
+       */
+      iy = MIN(iy, (ty-tx+1)>>1);
+
+      /* execute loop */
+      for (iz = 0; iz < iy; iz++) {
+         _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
+      }
+
+      /* double the inner product and add carry */
+      _W = _W + _W + W1;
+
+      /* even columns have the square term in them */
+      if ((ix&1) == 0) {
+         _W += ((mp_word)a->dp[ix>>1])*((mp_word)a->dp[ix>>1]);
+      }
+
+      /* store it */
+      W[ix] = (mp_digit)(_W & MP_MASK);
+
+      /* make next carry */
+      W1 = _W >> ((mp_word)DIGIT_BIT);
+  }
+
+  /* setup dest */
+  olduse  = b->used;
+  b->used = a->used+a->used;
+
+  {
+    mp_digit *tmpb;
+    tmpb = b->dp;
+    for (ix = 0; ix < pa; ix++) {
+      *tmpb++ = W[ix] & MP_MASK;
+    }
+
+    /* clear unused digits [that existed in the old copy of c] */
+    for (; ix < olduse; ix++) {
+      *tmpb++ = 0;
+    }
+  }
+  mp_clamp (b);
+  return MP_OKAY;
+}
+#endif
+
+
+#ifdef BN_MP_MUL_D_C
+/* multiply by a digit */
+static int
+mp_mul_d (mp_int * a, mp_digit b, mp_int * c)
+{
+  mp_digit u, *tmpa, *tmpc;
+  mp_word  r;
+  int      ix, res, olduse;
+
+  /* make sure c is big enough to hold a*b */
+  if (c->alloc < a->used + 1) {
+    if ((res = mp_grow (c, a->used + 1)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  /* get the original destinations used count */
+  olduse = c->used;
+
+  /* set the sign */
+  c->sign = a->sign;
+
+  /* alias for a->dp [source] */
+  tmpa = a->dp;
+
+  /* alias for c->dp [dest] */
+  tmpc = c->dp;
+
+  /* zero carry */
+  u = 0;
+
+  /* compute columns */
+  for (ix = 0; ix < a->used; ix++) {
+    /* compute product and carry sum for this term */
+    r       = ((mp_word) u) + ((mp_word)*tmpa++) * ((mp_word)b);
+
+    /* mask off higher bits to get a single digit */
+    *tmpc++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+    /* send carry into next iteration */
+    u       = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
+  }
+
+  /* store final carry [if any] and increment ix offset  */
+  *tmpc++ = u;
+  ++ix;
+
+  /* now zero digits above the top */
+  while (ix++ < olduse) {
+     *tmpc++ = 0;
+  }
+
+  /* set used count */
+  c->used = a->used + 1;
+  mp_clamp(c);
+
+  return MP_OKAY;
+}
+#endif

Modified: wpasupplicant/trunk/src/utils/base64.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/utils/base64.c?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/utils/base64.c (original)
+++ wpasupplicant/trunk/src/utils/base64.c Sat Jun 14 00:40:26 2008
@@ -115,7 +115,7 @@
 			count++;
 	}
 
-	if (count % 4)
+	if (count == 0 || count % 4)
 		return NULL;
 
 	olen = count / 4 * 3;

Modified: wpasupplicant/trunk/src/utils/common.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/utils/common.h?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/utils/common.h (original)
+++ wpasupplicant/trunk/src/utils/common.h Sat Jun 14 00:40:26 2008
@@ -428,6 +428,10 @@
 
 const char * wpa_ssid_txt(const u8 *ssid, size_t ssid_len);
 
+static inline int is_zero_ether_addr(const u8 *a)
+{
+	return !(a[0] | a[1] | a[2] | a[3] | a[4] | a[5]);
+}
 
 #include "wpa_debug.h"
 

Modified: wpasupplicant/trunk/src/utils/eloop.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/utils/eloop.c?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/utils/eloop.c (original)
+++ wpasupplicant/trunk/src/utils/eloop.c Sat Jun 14 00:40:26 2008
@@ -242,7 +242,10 @@
 	timeout = os_malloc(sizeof(*timeout));
 	if (timeout == NULL)
 		return -1;
-	os_get_time(&timeout->time);
+	if (os_get_time(&timeout->time) < 0) {
+		os_free(timeout);
+		return -1;
+	}
 	timeout->time.sec += secs;
 	timeout->time.usec += usecs;
 	while (timeout->time.usec >= 1000000) {
@@ -309,6 +312,25 @@
 	}
 
 	return removed;
+}
+
+
+int eloop_is_timeout_registered(eloop_timeout_handler handler,
+				void *eloop_data, void *user_data)
+{
+	struct eloop_timeout *tmp;
+
+	tmp = eloop.timeout;
+	while (tmp != NULL) {
+		if (tmp->handler == handler &&
+		    tmp->eloop_data == eloop_data &&
+		    tmp->user_data == user_data)
+			return 1;
+
+		tmp = tmp->next;
+	}
+
+	return 0;
 }
 
 

Modified: wpasupplicant/trunk/src/utils/eloop.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/utils/eloop.h?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/utils/eloop.h (original)
+++ wpasupplicant/trunk/src/utils/eloop.h Sat Jun 14 00:40:26 2008
@@ -207,6 +207,19 @@
 			 void *eloop_data, void *user_data);
 
 /**
+ * eloop_is_timeout_registered - Check if a timeout is already registered
+ * @handler: Matching callback function
+ * @eloop_data: Matching eloop_data
+ * @user_data: Matching user_data
+ * Returns: 1 if the timeout is registered, 0 if the timeout is not registered
+ *
+ * Determine if a matching <handler,eloop_data,user_data> timeout is registered
+ * with eloop_register_timeout().
+ */
+int eloop_is_timeout_registered(eloop_timeout_handler handler,
+				void *eloop_data, void *user_data);
+
+/**
  * eloop_register_signal - Register handler for signals
  * @sig: Signal number (e.g., SIGHUP)
  * @handler: Callback function to be called when the signal is received

Modified: wpasupplicant/trunk/src/utils/eloop_none.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/utils/eloop_none.c?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/utils/eloop_none.c (original)
+++ wpasupplicant/trunk/src/utils/eloop_none.c Sat Jun 14 00:40:26 2008
@@ -194,6 +194,26 @@
 	}
 
 	return removed;
+}
+
+
+int eloop_is_timeout_registered(void (*handler)(void *eloop_ctx,
+						void *timeout_ctx),
+				void *eloop_data, void *user_data)
+{
+	struct eloop_timeout *tmp;
+
+	tmp = eloop.timeout;
+	while (tmp != NULL) {
+		if (tmp->handler == handler &&
+		    tmp->eloop_data == eloop_data &&
+		    tmp->user_data == user_data)
+			return 1;
+
+		tmp = tmp->next;
+	}
+
+	return 0;
 }
 
 

Modified: wpasupplicant/trunk/src/utils/eloop_win.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/utils/eloop_win.c?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/utils/eloop_win.c (original)
+++ wpasupplicant/trunk/src/utils/eloop_win.c Sat Jun 14 00:40:26 2008
@@ -317,6 +317,25 @@
 	}
 
 	return removed;
+}
+
+
+int eloop_is_timeout_registered(eloop_timeout_handler handler,
+				void *eloop_data, void *user_data)
+{
+	struct eloop_timeout *tmp;
+
+	tmp = eloop.timeout;
+	while (tmp != NULL) {
+		if (tmp->handler == handler &&
+		    tmp->eloop_data == eloop_data &&
+		    tmp->user_data == user_data)
+			return 1;
+
+		tmp = tmp->next;
+	}
+
+	return 0;
 }
 
 

Modified: wpasupplicant/trunk/src/utils/wpabuf.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/utils/wpabuf.c?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/utils/wpabuf.c (original)
+++ wpasupplicant/trunk/src/utils/wpabuf.c Sat Jun 14 00:40:26 2008
@@ -1,6 +1,6 @@
 /*
  * Dynamic data buffer
- * Copyright (c) 2007, Jouni Malinen <j at w1.fi>
+ * Copyright (c) 2007-2008, 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
@@ -123,3 +123,40 @@
 	}
 	return tmp;
 }
+
+
+/**
+ * wpabuf_concat - Concatenate two buffers into a newly allocated one
+ * @a: First buffer
+ * @b: Second buffer
+ * Returns: wpabuf with concatenated a + b data or %NULL on failure
+ *
+ * Both buffers a and b will be freed regardless of the return value. Input
+ * buffers can be %NULL which is interpreted as an empty buffer.
+ */
+struct wpabuf * wpabuf_concat(struct wpabuf *a, struct wpabuf *b)
+{
+	struct wpabuf *n = NULL;
+	size_t len = 0;
+
+	if (b == NULL)
+		return a;
+
+	if (a)
+		len += wpabuf_len(a);
+	if (b)
+		len += wpabuf_len(b);
+
+	n = wpabuf_alloc(len);
+	if (n) {
+		if (a)
+			wpabuf_put_buf(n, a);
+		if (b)
+			wpabuf_put_buf(n, b);
+	}
+
+	wpabuf_free(a);
+	wpabuf_free(b);
+
+	return n;
+}

Modified: wpasupplicant/trunk/src/utils/wpabuf.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/src/utils/wpabuf.h?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/src/utils/wpabuf.h (original)
+++ wpasupplicant/trunk/src/utils/wpabuf.h Sat Jun 14 00:40:26 2008
@@ -36,6 +36,7 @@
 struct wpabuf * wpabuf_dup(const struct wpabuf *src);
 void wpabuf_free(struct wpabuf *buf);
 void * wpabuf_put(struct wpabuf *buf, size_t len);
+struct wpabuf * wpabuf_concat(struct wpabuf *a, struct wpabuf *b);
 
 
 /**

Modified: wpasupplicant/trunk/wpa_supplicant/ChangeLog
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/wpa_supplicant/ChangeLog?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/wpa_supplicant/ChangeLog (original)
+++ wpasupplicant/trunk/wpa_supplicant/ChangeLog Sat Jun 14 00:40:26 2008
@@ -1,4 +1,21 @@
 ChangeLog for wpa_supplicant
+
+????-??-?? - v0.6.4
+	* added support for EAP Sequences in EAP-FAST Phase 2
+	* added support for using TNC with EAP-FAST
+	* added driver_ps3 for the PS3 Linux wireless driver
+	* added support for optional cryptobinding with PEAPv0
+	* fixed the OpenSSL patches (0.9.8g and 0.9.9) for EAP-FAST to
+	  allow fallback to full handshake if server rejects PAC-Opaque
+	* added fragmentation support for EAP-TNC
+	* added support for parsing PKCS #8 formatted private keys into the
+	  internal TLS implementation (both PKCS #1 RSA key and PKCS #8
+	  encapsulated RSA key can now be used)
+	* added option of using faster, but larger, routines in the internal
+	  LibTomMath (for internal TLS implementation) to speed up DH and RSA
+	  calculations (CONFIG_INTERNAL_LIBTOMMATH_FAST=y)
+	* fixed race condition between disassociation event and group key
+	  handshake to avoid getting stuck in incorrect state [Bug 261]
 
 2008-02-22 - v0.6.3
 	* removed 'nai' and 'eappsk' network configuration variables that were

Modified: wpasupplicant/trunk/wpa_supplicant/Makefile
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/wpa_supplicant/Makefile?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/wpa_supplicant/Makefile (original)
+++ wpasupplicant/trunk/wpa_supplicant/Makefile Sat Jun 14 00:40:26 2008
@@ -127,6 +127,12 @@
 CONFIG_WIRELESS_EXTENSION=y
 endif
 
+ifdef CONFIG_DRIVER_NL80211
+CFLAGS += -DCONFIG_DRIVER_NL80211
+OBJS_d += ../src/drivers/driver_nl80211.o
+LIBS += -lnl
+endif
+
 ifdef CONFIG_DRIVER_PRISM54
 CFLAGS += -DCONFIG_DRIVER_PRISM54
 OBJS_d += ../src/drivers/driver_prism54.o
@@ -210,6 +216,12 @@
 LDFLAGS += -F/System/Library/PrivateFrameworks -framework Apple80211
 endif
 
+ifdef CONFIG_DRIVER_PS3
+CFLAGS += -DCONFIG_DRIVER_PS3 -m64
+OBJS_d += ../src/drivers/driver_ps3.o
+LDFLAGS += -m64
+endif
+
 ifdef CONFIG_DRIVER_IPHONE
 CFLAGS += -DCONFIG_DRIVER_IPHONE
 OBJS_d += ../src/drivers/driver_iphone.o
@@ -264,11 +276,11 @@
 else
 CFLAGS += -DEAP_PEAP
 OBJS += ../src/eap_peer/eap_peap.o
+OBJS += ../src/eap_common/eap_peap_common.o
 OBJS_h += ../src/eap_server/eap_peap.o
 endif
 TLS_FUNCS=y
 CONFIG_IEEE8021X_EAPOL=y
-CONFIG_EAP_TLV=y
 endif
 
 ifdef CONFIG_EAP_TTLS
@@ -411,21 +423,16 @@
 NEED_FIPS186_2_PRF=y
 endif
 
-ifdef CONFIG_EAP_TLV
-# EAP-TLV
-CFLAGS += -DEAP_TLV
-OBJS += ../src/eap_peer/eap_tlv.o
-OBJS_h += ../src/eap_server/eap_tlv.o
-endif
-
 ifdef CONFIG_EAP_FAST
 # EAP-FAST
 ifeq ($(CONFIG_EAP_FAST), dyn)
 CFLAGS += -DEAP_FAST_DYNAMIC
 EAPDYN += ../src/eap_peer/eap_fast.so
+EAPDYN += ../src/eap_common/eap_fast_common.o
 else
 CFLAGS += -DEAP_FAST
 OBJS += ../src/eap_peer/eap_fast.o ../src/eap_peer/eap_fast_pac.o
+OBJS += ../src/eap_common/eap_fast_common.o
 OBJS_h += ../src/eap_server/eap_fast.o
 endif
 TLS_FUNCS=y
@@ -621,6 +628,9 @@
 ifeq ($(CONFIG_CRYPTO), internal)
 ifdef CONFIG_INTERNAL_LIBTOMMATH
 CFLAGS += -DCONFIG_INTERNAL_LIBTOMMATH
+ifdef CONFIG_INTERNAL_LIBTOMMATH_FAST
+CFLAGS += -DLTM_FAST
+endif
 else
 LIBS += -ltommath
 LIBS_p += -ltommath

Modified: wpasupplicant/trunk/wpa_supplicant/config.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/wpa_supplicant/config.c?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/wpa_supplicant/config.c (original)
+++ wpasupplicant/trunk/wpa_supplicant/config.c Sat Jun 14 00:40:26 2008
@@ -1296,6 +1296,11 @@
 	{ STR_KEYe(pin) },
 	{ STRe(engine_id) },
 	{ STRe(key_id) },
+	{ STRe(cert_id) },
+	{ STRe(ca_cert_id) },
+	{ STRe(key2_id) },
+	{ STRe(cert2_id) },
+	{ STRe(ca_cert2_id) },
 	{ INTe(engine) },
 	{ INT(eapol_flags) },
 #endif /* IEEE8021X_EAPOL */
@@ -1453,6 +1458,11 @@
 	os_free(eap->pin);
 	os_free(eap->engine_id);
 	os_free(eap->key_id);
+	os_free(eap->cert_id);
+	os_free(eap->ca_cert_id);
+	os_free(eap->key2_id);
+	os_free(eap->cert2_id);
+	os_free(eap->ca_cert2_id);
 	os_free(eap->otp);
 	os_free(eap->pending_req_otp);
 	os_free(eap->pac_file);

Modified: wpasupplicant/trunk/wpa_supplicant/config_file.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/wpa_supplicant/config_file.c?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/wpa_supplicant/config_file.c (original)
+++ wpasupplicant/trunk/wpa_supplicant/config_file.c Sat Jun 14 00:40:26 2008
@@ -754,6 +754,11 @@
 	STR(pin);
 	STR(engine_id);
 	STR(key_id);
+	STR(cert_id);
+	STR(ca_cert_id);
+	STR(key2_id);
+	STR(cert2_id);
+	STR(ca_cert2_id);
 	INTe(engine);
 	INT_DEF(eapol_flags, DEFAULT_EAPOL_FLAGS);
 #endif /* IEEE8021X_EAPOL */

Modified: wpasupplicant/trunk/wpa_supplicant/config_winreg.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/wpa_supplicant/config_winreg.c?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/wpa_supplicant/config_winreg.c (original)
+++ wpasupplicant/trunk/wpa_supplicant/config_winreg.c Sat Jun 14 00:40:26 2008
@@ -766,6 +766,11 @@
 	STR(pin);
 	STR(engine_id);
 	STR(key_id);
+	STR(cert_id);
+	STR(ca_cert_id);
+	STR(key2_id);
+	STR(cert2_id);
+	STR(ca_cert2_id);
 	INTe(engine);
 	INT_DEF(eapol_flags, DEFAULT_EAPOL_FLAGS);
 #endif /* IEEE8021X_EAPOL */

Modified: wpasupplicant/trunk/wpa_supplicant/ctrl_iface.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/wpa_supplicant/ctrl_iface.c?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/wpa_supplicant/ctrl_iface.c (original)
+++ wpasupplicant/trunk/wpa_supplicant/ctrl_iface.c Sat Jun 14 00:40:26 2008
@@ -76,6 +76,7 @@
 }
 
 
+#ifdef IEEE8021X_EAPOL
 static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s,
 					     char *addr)
 {
@@ -95,6 +96,7 @@
 
 	return 0;
 }
+#endif /* IEEE8021X_EAPOL */
 
 
 #ifdef CONFIG_PEERKEY
@@ -328,9 +330,7 @@
 	}
 
 	os_memcpy(ssid->bssid, bssid, ETH_ALEN);
-	ssid->bssid_set =
-		os_memcmp(bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) != 0;
-		
+	ssid->bssid_set = !is_zero_ether_addr(bssid);
 
 	return 0;
 }
@@ -1396,9 +1396,11 @@
 			wpa_s->reassociate = 1;
 			wpa_supplicant_req_scan(wpa_s, 0, 0);
 		}
+#ifdef IEEE8021X_EAPOL
 	} else if (os_strncmp(buf, "PREAUTH ", 8) == 0) {
 		if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8))
 			reply_len = -1;
+#endif /* IEEE8021X_EAPOL */
 #ifdef CONFIG_PEERKEY
 	} else if (os_strncmp(buf, "STKSTART ", 9) == 0) {
 		if (wpa_supplicant_ctrl_iface_stkstart(wpa_s, buf + 9))

Modified: wpasupplicant/trunk/wpa_supplicant/ctrl_iface_dbus.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/wpa_supplicant/ctrl_iface_dbus.c?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/wpa_supplicant/ctrl_iface_dbus.c (original)
+++ wpasupplicant/trunk/wpa_supplicant/ctrl_iface_dbus.c Sat Jun 14 00:40:26 2008
@@ -21,10 +21,10 @@
 #include "ctrl_iface_dbus.h"
 #include "ctrl_iface_dbus_handlers.h"
 
-#define DBUS_VERSION (DBUS_VERSION_MAJOR << 8 | DBUS_VERSION_MINOR)
+#define _DBUS_VERSION (DBUS_VERSION_MAJOR << 8 | DBUS_VERSION_MINOR)
 #define DBUS_VER(major, minor) ((major) << 8 | (minor))
 
-#if DBUS_VERSION < DBUS_VER(1,1)
+#if _DBUS_VERSION < DBUS_VER(1,1)
 #define dbus_watch_get_unix_fd dbus_watch_get_fd
 #endif
 
@@ -534,6 +534,9 @@
 			reply = wpas_dbus_iface_disconnect(message, wpa_s);
 		else if (!strcmp(method, "setAPScan"))
 			reply = wpas_dbus_iface_set_ap_scan(message, wpa_s);
+		else if (!strcmp(method, "setSmartcardModules"))
+			reply = wpas_dbus_iface_set_smartcard_modules(message,
+								      wpa_s);
 		else if (!strcmp(method, "state"))
 			reply = wpas_dbus_iface_get_state(message, wpa_s);
 		else if (!strcmp(method, "setBlobs"))

Modified: wpasupplicant/trunk/wpa_supplicant/ctrl_iface_dbus_handlers.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/wpa_supplicant/ctrl_iface_dbus_handlers.c?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/wpa_supplicant/ctrl_iface_dbus_handlers.c (original)
+++ wpasupplicant/trunk/wpa_supplicant/ctrl_iface_dbus_handlers.c Sat Jun 14 00:40:26 2008
@@ -22,6 +22,8 @@
 #include "eap_peer/eap_methods.h"
 #include "dbus_dict_helpers.h"
 #include "ieee802_11_defs.h"
+#include "wpas_glue.h"
+#include "eapol_supp/eapol_supp_sm.h"
 
 
 /**
@@ -1179,6 +1181,76 @@
 
 
 /**
+ * wpas_dbus_iface_set_smartcard_modules - Set smartcard related module paths
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: A dbus message containing a UINT32 indicating success (1) or
+ *          failure (0)
+ *
+ * Handler function for "setSmartcardModules" method call.
+ */
+DBusMessage * wpas_dbus_iface_set_smartcard_modules(
+	DBusMessage *message, struct wpa_supplicant *wpa_s)
+{
+	DBusMessageIter iter, iter_dict;
+	char *opensc_engine_path = NULL;
+	char *pkcs11_engine_path = NULL;
+	char *pkcs11_module_path = NULL;
+	struct wpa_dbus_dict_entry entry;
+
+	if (!dbus_message_iter_init(message, &iter))
+		goto error;
+
+	if (!wpa_dbus_dict_open_read(&iter, &iter_dict))
+		goto error;
+
+	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
+		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
+			goto error;
+		if (!strcmp(entry.key, "opensc_engine_path") &&
+		    (entry.type == DBUS_TYPE_STRING)) {
+			opensc_engine_path = os_strdup(entry.str_value);
+			if (opensc_engine_path == NULL)
+				goto error;
+		} else if (!strcmp(entry.key, "pkcs11_engine_path") &&
+			   (entry.type == DBUS_TYPE_STRING)) {
+			pkcs11_engine_path = os_strdup(entry.str_value);
+			if (pkcs11_engine_path == NULL)
+				goto error;
+		} else if (!strcmp(entry.key, "pkcs11_module_path") &&
+				 (entry.type == DBUS_TYPE_STRING)) {
+			pkcs11_module_path = os_strdup(entry.str_value);
+			if (pkcs11_module_path == NULL)
+				goto error;
+		} else {
+			wpa_dbus_dict_entry_clear(&entry);
+			goto error;
+		}
+		wpa_dbus_dict_entry_clear(&entry);
+	}
+
+#ifdef EAP_TLS_OPENSSL
+	os_free(wpa_s->conf->opensc_engine_path);
+	wpa_s->conf->opensc_engine_path = opensc_engine_path;
+	os_free(wpa_s->conf->pkcs11_engine_path);
+	wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path;
+	os_free(wpa_s->conf->pkcs11_module_path);
+	wpa_s->conf->pkcs11_module_path = pkcs11_module_path;
+#endif /* EAP_TLS_OPENSSL */
+
+	eapol_sm_deinit(wpa_s->eapol);
+	wpa_supplicant_init_eapol(wpa_s);
+
+	return wpas_dbus_new_success_reply(message);
+
+error:
+	os_free(opensc_engine_path);
+	os_free(pkcs11_engine_path);
+	os_free(pkcs11_module_path);
+	return wpas_dbus_new_invalid_opts_error(message, NULL);
+}
+
+/**
  * wpas_dbus_iface_get_state - Get interface state
  * @message: Pointer to incoming dbus message
  * @wpa_s: wpa_supplicant structure for a network interface

Modified: wpasupplicant/trunk/wpa_supplicant/ctrl_iface_dbus_handlers.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/wpa_supplicant/ctrl_iface_dbus_handlers.h?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/wpa_supplicant/ctrl_iface_dbus_handlers.h (original)
+++ wpasupplicant/trunk/wpa_supplicant/ctrl_iface_dbus_handlers.h Sat Jun 14 00:40:26 2008
@@ -68,6 +68,9 @@
 DBusMessage * wpas_dbus_iface_set_ap_scan(DBusMessage *message,
                                           struct wpa_supplicant *wpa_s);
 
+DBusMessage * wpas_dbus_iface_set_smartcard_modules(
+	DBusMessage *message, struct wpa_supplicant *wpa_s);
+
 DBusMessage * wpas_dbus_iface_get_state(DBusMessage *message,
 					struct wpa_supplicant *wpa_s);
 

Modified: wpasupplicant/trunk/wpa_supplicant/ctrl_iface_unix.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/wpa_supplicant/ctrl_iface_unix.c?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/wpa_supplicant/ctrl_iface_unix.c (original)
+++ wpasupplicant/trunk/wpa_supplicant/ctrl_iface_unix.c Sat Jun 14 00:40:26 2008
@@ -311,7 +311,7 @@
 			/* Group name not found - try to parse this as gid */
 			gid = strtol(gid_str, &endp, 10);
 			if (*gid_str == '\0' || *endp != '\0') {
-				wpa_printf(MSG_DEBUG, "CTRL: Invalid group "
+				wpa_printf(MSG_ERROR, "CTRL: Invalid group "
 					   "'%s'", gid_str);
 				goto fail;
 			}

Modified: wpasupplicant/trunk/wpa_supplicant/dbus_dict_helpers.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/wpa_supplicant/dbus_dict_helpers.c?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/wpa_supplicant/dbus_dict_helpers.c (original)
+++ wpasupplicant/trunk/wpa_supplicant/dbus_dict_helpers.c Sat Jun 14 00:40:26 2008
@@ -674,7 +674,7 @@
 	/* Zero-length arrays are valid. */
 	if (entry->array_len == 0) {
 		free(entry->bytearray_value);
-		entry->strarray_value = NULL;
+		entry->bytearray_value = NULL;
 	}
 
 	success = TRUE;

Modified: wpasupplicant/trunk/wpa_supplicant/defconfig
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/wpa_supplicant/defconfig?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/wpa_supplicant/defconfig (original)
+++ wpasupplicant/trunk/wpa_supplicant/defconfig Sat Jun 14 00:40:26 2008
@@ -307,6 +307,10 @@
 #LIBS += -L$(LTM_PATH)
 #LIBS_p += -L$(LTM_PATH)
 #endif
+# At the cost of about 4 kB of additional binary size, the internal LibTomMath
+# can be configured to include faster routines for exptmod, sqr, and div to
+# speed up DH and RSA calculation considerably
+#CONFIG_INTERNAL_LIBTOMMATH_FAST=y
 
 # Include NDIS event processing through WMI into wpa_supplicant/wpasvc.
 # This is only for Windows builds and requires WMI-related header files and

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=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/wpa_supplicant/doc/docbook/wpa_cli.sgml (original)
+++ wpasupplicant/trunk/wpa_supplicant/doc/docbook/wpa_cli.sgml Sat Jun 14 00:40:26 2008
@@ -72,17 +72,18 @@
    case of OTP request, it includes the challenge from the
    authentication server.</para>
 
-    <para>The reply to these requests can be given with 'identity',
-    'password', and 'otp' commands. &lt;id&gt; needs to be copied from the
-    the matching request. 'password' and 'otp' commands can be used
-    regardless of whether the request was for PASSWORD or OTP. The
-    main difference between these two commands is that values given
-    with 'password' are remembered as long as wpa_supplicant is
-    running whereas values given with 'otp' are used only once and
-    then forgotten, i.e., wpa_supplicant will ask frontend for a new
-    value for every use. This can be used to implement
-    one-time-password lists and generic token card -based
-    authentication.</para>
+    <para>The reply to these requests can be given with
+    <emphasis>identity</emphasis>, <emphasis>password</emphasis>, and
+    <emphasis>otp</emphasis> commands. &lt;id&gt; needs to be copied from
+    the matching request. <emphasis>password</emphasis> and
+    <emphasis>otp</emphasis> commands can be used regardless of whether
+    the request was for PASSWORD or OTP. The main difference between these
+    two commands is that values given with <emphasis>password</emphasis> are
+    remembered as long as wpa_supplicant is running whereas values given
+    with <emphasis>otp</emphasis> are used only once and then forgotten,
+    i.e., wpa_supplicant will ask frontend for a new value for every use.
+    This can be used to implement one-time-password lists and generic token
+    card -based authentication.</para>
 
     <para>Example request for password and a matching reply:</para>
 

Modified: wpasupplicant/trunk/wpa_supplicant/doc/docbook/wpa_priv.sgml
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/wpa_supplicant/doc/docbook/wpa_priv.sgml?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/wpa_supplicant/doc/docbook/wpa_priv.sgml (original)
+++ wpasupplicant/trunk/wpa_supplicant/doc/docbook/wpa_priv.sgml Sat Jun 14 00:40:26 2008
@@ -49,9 +49,9 @@
     <title>Example configuration</title>
 
     <para>The following steps are an example of how to configure
-    <command>wpa_priv</command> to allow users in the 'wpapriv' group
-    to communicate with <command>wpa_supplicant</command> with privilege
-    separation:</para>
+    <command>wpa_priv</command> to allow users in the
+    <emphasis>wpapriv</emphasis> group to communicate with
+    <command>wpa_supplicant</command> with privilege separation:</para>
 
     <para>Create user group (e.g., wpapriv) and assign users that
     should be able to use wpa_supplicant into that group.</para>
@@ -111,7 +111,7 @@
 	supported <command>wpa_supplicant</command> driver backends is to be
 	used. To get a list of supported driver types see wpa_supplicant help
 	(e.g, wpa_supplicant -h). The driver backend supported by most good
-	drivers is 'wext'.</para>
+	drivers is <emphasis>wext</emphasis>.</para>
 
 	<para>The &lt;ifname&gt; string specifies which network
 	interface is to be managed by <command>wpa_supplicant</command>

Modified: wpasupplicant/trunk/wpa_supplicant/doc/docbook/wpa_supplicant.conf.sgml
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/wpa_supplicant/doc/docbook/wpa_supplicant.conf.sgml?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/wpa_supplicant/doc/docbook/wpa_supplicant.conf.sgml (original)
+++ wpasupplicant/trunk/wpa_supplicant/doc/docbook/wpa_supplicant.conf.sgml Sat Jun 14 00:40:26 2008
@@ -26,7 +26,7 @@
     <para>Changes to configuration file can be reloaded be sending
     SIGHUP signal to <command>wpa_supplicant</command> ('killall -HUP
     wpa_supplicant'). Similarly, reloading can be triggered with
-    the 'wpa_cli reconfigure' command.</para>
+    the <emphasis>wpa_cli reconfigure</emphasis> command.</para>
 
     <para>Configuration file can include one or more network blocks,
     e.g., one for each used SSID. wpa_supplicant will automatically
@@ -174,7 +174,7 @@
 
       <listitem>
 	<para>Authentication for wired Ethernet. This can be used with
-       'wired' interface (-Dwired on command line).</para>
+       <emphasis>wired</emphasis> interface (-Dwired on command line).</para>
 
 <blockquote><programlisting>
 ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=wheel

Modified: wpasupplicant/trunk/wpa_supplicant/doc/docbook/wpa_supplicant.sgml
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/wpa_supplicant/doc/docbook/wpa_supplicant.sgml?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/wpa_supplicant/doc/docbook/wpa_supplicant.sgml (original)
+++ wpasupplicant/trunk/wpa_supplicant/doc/docbook/wpa_supplicant.sgml Sat Jun 14 00:40:26 2008
@@ -238,7 +238,11 @@
 
   <refsect1>
     <title>Available Drivers</title>
-    <para>The available drivers to specify with the -D option are:</para>
+    <para>A summary of available driver backends is below. Support for each
+    of the driver backends is chosen at wpa_supplicant compile time. For a
+    list of supported driver backends that may be used with the -D option on
+    your system, refer to the help output of wpa_supplicant
+    (<emphasis>wpa_supplicant -h</emphasis>).</para>
 
     <variablelist>
       <varlistentry>
@@ -530,9 +534,9 @@
 	snapshot/v0.2.x)</term>
 	<listitem>
 	  <para> (http://hostap.epitest.fi/) Driver needs to be set in
-	Managed mode ('iwconfig wlan0 mode managed').  Please note
-	that station firmware version needs to be 1.7.0 or newer to
-	work in WPA mode.</para>
+	  Managed mode (<emphasis>iwconfig wlan0 mode managed</emphasis>).
+	  Please note that station firmware version needs to be 1.7.0 or
+	  newer to work in WPA mode.</para>
 	</listitem>
       </varlistentry>
 
@@ -736,8 +740,8 @@
     <para>Add MODE="Managed" and WPA="y" to the network scheme in
     <filename>/etc/pcmcia/wireless.opts</filename>.</para>
 
-    <para>Add the following block to the end of 'start' action handler
-    in <filename>/etc/pcmcia/wireless</filename>:</para>
+    <para>Add the following block to the end of <emphasis>start</emphasis>
+    action handler in <filename>/etc/pcmcia/wireless</filename>:</para>
 
     <blockquote><programlisting>
 if [ "$WPA" = "y" -a -x /usr/local/bin/wpa_supplicant ]; then
@@ -746,8 +750,8 @@
     </programlisting></blockquote>
 
 
-    <para>Add the following block to the end of 'stop' action handler
-    (may need to be separated from other actions) in
+    <para>Add the following block to the end of <emphasis>stop</emphasis>
+    action handler (may need to be separated from other actions) in
     <filename>/etc/pcmcia/wireless</filename>:</para>
 
     <blockquote><programlisting>

Modified: wpasupplicant/trunk/wpa_supplicant/eap_testing.txt
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/wpa_supplicant/eap_testing.txt?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/wpa_supplicant/eap_testing.txt (original)
+++ wpasupplicant/trunk/wpa_supplicant/eap_testing.txt Sat Jun 14 00:40:26 2008
@@ -91,6 +91,7 @@
 EAP-TTLS/EAP-PAX	-   -   -   -   -   -   -   -   -   -   +   -
 EAP-TTLS/EAP-SAKE	-   -   -   -   -   -   -   -   -   -   +   -
 EAP-TTLS/EAP-GPSK	-   -   -   -   -   -   -   -   -   -   +   -
+EAP-TTLS + TNC		-   -   -   -   -   +   -   -   -   -   +   -
 EAP-SIM			+   -   -   ?   -   +   -   ?   -   -   +   -
 EAP-AKA			-   -   -   -   -   +   -   -   -   -   +   -
 EAP-PSK			+7  -   -   -   -   +   -   -   -   -   +   -
@@ -110,8 +111,9 @@
 EAP-FAST/TLS(auth)	-   -   -   -   -   -   -   -   -   -   +   +
 EAP-FAST/SIM(auth)	-   -   -   -   -   -   -   -   -   -   +   -
 EAP-FAST/AKA(auth)	-   -   -   -   -   -   -   -   -   -   +   -
+EAP-FAST + TNC		-   -   -   -   -   -   -   -   -   -   +   -
 LEAP			+   -   +   +   +   +   F   +6  -   +   -   +
-EAP-TNC			+9  -   -   -   -   +   -   -   -   -   -   -
+EAP-TNC			+9  -   -   -   -   +   -   -   -   -   +   -
 EAP-IKEv2		+10 -   -   -   -   -   -   -   -   -   +   -
 
 1) PEAPv1 required new label, "client PEAP encryption" instead of "client EAP

Modified: wpasupplicant/trunk/wpa_supplicant/eapol_test.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/wpa_supplicant/eapol_test.c?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/wpa_supplicant/eapol_test.c (original)
+++ wpasupplicant/trunk/wpa_supplicant/eapol_test.c Sat Jun 14 00:40:26 2008
@@ -66,6 +66,8 @@
 
 	char *connect_info;
 	u8 own_addr[ETH_ALEN];
+	int cui_flag;
+	char *cui_str;
 };
 
 static struct eapol_test_data eapol_test;
@@ -162,6 +164,23 @@
 				 (u8 *) buf, os_strlen(buf))) {
 		printf("Could not add Connect-Info\n");
 		goto fail;
+	}
+
+	if (e->cui_flag) {
+		int l = 0;
+		if (e->cui_flag == 1) {
+			l = 1;
+			buf[0] = '\0';
+		} else if (e->cui_flag == 2) {
+			os_snprintf(buf, sizeof(buf), "%s", e->cui_str);
+			l = os_strlen(buf);
+		}
+		if (!radius_msg_add_attr(msg,
+					 RADIUS_ATTR_CHARGEABLE_USER_IDENTITY,
+					 (u8 *) buf, l)) {
+			printf("Could not add Chargeable-User-Identity\n");
+			goto fail;
+		}
 	}
 
 	if (eap && !radius_msg_add_eap(msg, eap, len)) {
@@ -616,7 +635,8 @@
 
 static void wpa_init_conf(struct eapol_test_data *e,
 			  struct wpa_supplicant *wpa_s, const char *authsrv,
-			  int port, const char *secret)
+			  int port, const char *secret,
+			  const char *cli_addr)
 {
 	struct hostapd_radius_server *as;
 	int res;
@@ -652,6 +672,16 @@
 	e->radius_conf->auth_server = as;
 	e->radius_conf->auth_servers = as;
 	e->radius_conf->msg_dumps = 1;
+	if (cli_addr) {
+		if (hostapd_parse_ip_addr(cli_addr,
+					  &e->radius_conf->client_addr) == 0)
+			e->radius_conf->force_client_addr = 1;
+		else {
+			wpa_printf(MSG_ERROR, "Invalid IP address '%s'",
+				   cli_addr);
+			assert(0);
+		}
+	}
 
 	e->radius = radius_client_init(wpa_s, e->radius_conf);
 	assert(e->radius != NULL);
@@ -846,9 +876,10 @@
 {
 	printf("usage:\n"
 	       "eapol_test [-nWS] -c<conf> [-a<AS IP>] [-p<AS port>] "
-	       "[-s<AS secret>] \\\n"
+	       "[-s<AS secret>]\\\n"
 	       "           [-r<count>] [-t<timeout>] [-C<Connect-Info>] \\\n"
-	       "           [-M<client MAC address>]\n"
+	       "           [-M<client MAC address>] \\\n"
+	       "           [-I<CUI>] [-i] [-A<client IP>]\n"
 	       "eapol_test scard\n"
 	       "eapol_test sim <PIN> <num triplets> [debug]\n"
 	       "\n");
@@ -860,6 +891,8 @@
 	       "default 1812\n"
 	       "  -s<AS secret> = shared secret with the authentication "
 	       "server, default 'radius'\n"
+	       "  -A<client IP> = IP address of the client, default: select "
+	       "automatically\n"
 	       "  -r<count> = number of re-authentications\n"
 	       "  -W = wait for a control interface monitor before starting\n"
 	       "  -S = save configuration after authentiation\n"
@@ -869,7 +902,10 @@
 	       "CONNECT 11Mbps 802.11b)\n"
 	       "  -M<client MAC address> = Set own MAC address "
 	       "(Calling-Station-Id,\n"
-	       "                           default: 02:00:00:00:00:01)\n");
+	       "                           default: 02:00:00:00:00:01)\n"
+	       "  -I<CUI> = send Chargeable-User-Identity containing the "
+	       "value of CUI\n"
+	       "  -i = send NUL value in Chargeable-User-Identity\n");
 }
 
 
@@ -880,6 +916,7 @@
 	char *as_addr = "127.0.0.1";
 	int as_port = 1812;
 	char *as_secret = "radius";
+	char *cli_addr = NULL;
 	char *conf = NULL;
 	int timeout = 30;
 
@@ -896,18 +933,28 @@
 	wpa_debug_show_keys = 1;
 
 	for (;;) {
-		c = getopt(argc, argv, "a:c:C:M:np:r:s:St:W");
+		c = getopt(argc, argv, "a:A:c:C:iI:M:np:r:s:St:W");
 		if (c < 0)
 			break;
 		switch (c) {
 		case 'a':
 			as_addr = optarg;
 			break;
+		case 'A':
+			cli_addr = optarg;
+			break;
 		case 'c':
 			conf = optarg;
 			break;
 		case 'C':
 			eapol_test.connect_info = optarg;
+			break;
+		case 'i':
+			eapol_test.cui_flag = 1;
+			break;
+		case 'I':
+			eapol_test.cui_flag = 2;
+			eapol_test.cui_str = optarg;
 			break;
 		case 'M':
 			if (hwaddr_aton(optarg, eapol_test.own_addr)) {
@@ -979,7 +1026,8 @@
 		return -1;
 	}
 
-	wpa_init_conf(&eapol_test, &wpa_s, as_addr, as_port, as_secret);
+	wpa_init_conf(&eapol_test, &wpa_s, as_addr, as_port, as_secret,
+		      cli_addr);
 	wpa_s.ctrl_iface = wpa_supplicant_ctrl_iface_init(&wpa_s);
 	if (wpa_s.ctrl_iface == NULL) {
 		printf("Failed to initialize control interface '%s'.\n"

Modified: wpasupplicant/trunk/wpa_supplicant/events.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/wpa_supplicant/events.c?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/wpa_supplicant/events.c (original)
+++ wpasupplicant/trunk/wpa_supplicant/events.c Sat Jun 14 00:40:26 2008
@@ -805,7 +805,7 @@
 	if (wpa_s->wpa_state >= WPA_ASSOCIATED)
 		wpa_supplicant_req_scan(wpa_s, 0, 100000);
 	bssid = wpa_s->bssid;
-	if (os_memcmp(bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) == 0)
+	if (is_zero_ether_addr(bssid))
 		bssid = wpa_s->pending_bssid;
 	wpa_blacklist_add(wpa_s, bssid);
 	wpa_sm_notify_disassoc(wpa_s->wpa);

Modified: wpasupplicant/trunk/wpa_supplicant/main.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/wpa_supplicant/main.c?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/wpa_supplicant/main.c (original)
+++ wpasupplicant/trunk/wpa_supplicant/main.c Sat Jun 14 00:40:26 2008
@@ -39,7 +39,7 @@
 	int i;
 	printf("%s\n\n%s\n"
 	       "usage:\n"
-	       "  wpa_supplicant [-BddhKLqqtuvwW] [-P<pid file>] "
+	       "  wpa_supplicant [-BddhKLqqtuvW] [-P<pid file>] "
 	       "[-g<global ctrl>] \\\n"
 	       "        -i<ifname> -c<config file> [-C<ctrl>] [-D<driver>] "
 	       "[-p<driver_param>] \\\n"

Modified: wpasupplicant/trunk/wpa_supplicant/mlme.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/wpa_supplicant/mlme.c?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/wpa_supplicant/mlme.c (original)
+++ wpasupplicant/trunk/wpa_supplicant/mlme.c Sat Jun 14 00:40:26 2008
@@ -356,7 +356,7 @@
 
 static void ieee80211_set_associated(struct wpa_supplicant *wpa_s, int assoc)
 {
-	if (wpa_s->mlme.associated == assoc)
+	if (wpa_s->mlme.associated == assoc && !assoc)
 		return;
 
 	wpa_s->mlme.associated = assoc;
@@ -1051,6 +1051,7 @@
 		data.ft_ies.ies = mgmt->u.auth.variable;
 		data.ft_ies.ies_len = len -
 			(mgmt->u.auth.variable - (u8 *) mgmt);
+		os_memcpy(data.ft_ies.target_ap, wpa_s->bssid, ETH_ALEN);
 		wpa_supplicant_event(wpa_s, EVENT_FT_RESPONSE, &data);
 		ieee80211_auth_completed(wpa_s);
 		break;
@@ -1258,7 +1259,8 @@
 			return;
 		}
 		if (wpa_ft_validate_reassoc_resp(
-			    wpa_s->wpa, pos, len - (pos - (u8 *) mgmt)) < 0) {
+			    wpa_s->wpa, pos, len - (pos - (u8 *) mgmt),
+			    mgmt->sa) < 0) {
 			wpa_printf(MSG_DEBUG, "MLME: FT validation of Reassoc"
 				   "Resp failed");
 			return;
@@ -2453,8 +2455,7 @@
 	wpa_s->mlme.freq = params->freq;
 	if (params->bssid) {
 		os_memcpy(wpa_s->bssid, params->bssid, ETH_ALEN);
-		if (os_memcmp(params->bssid, "\x00\x00\x00\x00\x00\x00",
-			      ETH_ALEN))
+		if (!is_zero_ether_addr(params->bssid))
 			wpa_s->mlme.bssid_set = 1;
 		bss = ieee80211_bss_get(wpa_s, wpa_s->bssid);
 		if (bss) {

Modified: wpasupplicant/trunk/wpa_supplicant/preauth_test.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/wpa_supplicant/preauth_test.c?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/wpa_supplicant/preauth_test.c (original)
+++ wpasupplicant/trunk/wpa_supplicant/preauth_test.c Sat Jun 14 00:40:26 2008
@@ -43,18 +43,6 @@
 };
 
 
-static void _wpa_supplicant_req_scan(void *wpa_s, int sec, int usec)
-{
-	wpa_supplicant_req_scan(wpa_s, sec, usec);
-}
-
-
-static void _wpa_supplicant_cancel_scan(void *wpa_s)
-{
-	wpa_supplicant_cancel_scan(wpa_s);
-}
-
-
 static void _wpa_supplicant_disassociate(void *wpa_s, int reason_code)
 {
 	wpa_supplicant_disassociate(wpa_s, reason_code);
@@ -253,8 +241,6 @@
 	ctx->ctx = wpa_s;
 	ctx->set_state = _wpa_supplicant_set_state;
 	ctx->get_state = _wpa_supplicant_get_state;
-	ctx->req_scan = _wpa_supplicant_req_scan;
-	ctx->cancel_scan = _wpa_supplicant_cancel_scan;
 	ctx->deauthenticate = _wpa_supplicant_deauthenticate;
 	ctx->disassociate = _wpa_supplicant_disassociate;
 	ctx->set_key = wpa_supplicant_set_key;

Modified: wpasupplicant/trunk/wpa_supplicant/scan.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/wpa_supplicant/scan.c?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/wpa_supplicant/scan.c (original)
+++ wpasupplicant/trunk/wpa_supplicant/scan.c Sat Jun 14 00:40:26 2008
@@ -172,6 +172,28 @@
  */
 void wpa_supplicant_req_scan(struct wpa_supplicant *wpa_s, int sec, int usec)
 {
+	/* If there's at least one network that should be specifically scanned
+	 * then don't cancel the scan and reschedule.  Some drivers do
+	 * background scanning which generates frequent scan results, and that
+	 * causes the specific SSID scan to get continually pushed back and
+	 * never happen, which causes hidden APs to never get probe-scanned.
+	 */
+	if (eloop_is_timeout_registered(wpa_supplicant_scan, wpa_s, NULL) &&
+	    wpa_s->conf->ap_scan == 1) {
+		struct wpa_ssid *ssid = wpa_s->conf->ssid;
+
+		while (ssid) {
+			if (!ssid->disabled && ssid->scan_ssid)
+				break;
+			ssid = ssid->next;
+		}
+		if (ssid) {
+			wpa_msg(wpa_s, MSG_DEBUG, "Not rescheduling scan to "
+			        "ensure that specific SSID scans occur");
+			return;
+		}
+	}
+
 	wpa_msg(wpa_s, MSG_DEBUG, "Setting scan request: %d sec %d usec",
 		sec, usec);
 	eloop_cancel_timeout(wpa_supplicant_scan, wpa_s, NULL);

Modified: wpasupplicant/trunk/wpa_supplicant/todo.txt
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/wpa_supplicant/todo.txt?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/wpa_supplicant/todo.txt (original)
+++ wpasupplicant/trunk/wpa_supplicant/todo.txt Sat Jun 14 00:40:26 2008
@@ -59,7 +59,6 @@
   could very well be done before EAP has been started
 - try to work around race in receiving association event and first EAPOL
   message
-- helper function to do memcmp(addr, "\x00\x00\x00\x00\x00\x00", ETH_ALEN)
 - add wpa_secure_memzero() macro and secure implementation (volatile u8*) to
   clear memory; this would be used to clear temporary buffers containing
   private data (e.g., keys); the macro can be defined to NOP in order to save

Modified: wpasupplicant/trunk/wpa_supplicant/wpa_gui/networkconfig.ui.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/wpa_supplicant/wpa_gui/networkconfig.ui.h?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/wpa_supplicant/wpa_gui/networkconfig.ui.h (original)
+++ wpasupplicant/trunk/wpa_supplicant/wpa_gui/networkconfig.ui.h Sat Jun 14 00:40:26 2008
@@ -10,6 +10,7 @@
 ** destructor.
 *****************************************************************************/
 
+#include <stdlib.h>
 
 enum {
     AUTH_NONE = 0,

Modified: wpasupplicant/trunk/wpa_supplicant/wpa_gui/userdatarequest.ui.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/wpa_supplicant/wpa_gui/userdatarequest.ui.h?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/wpa_supplicant/wpa_gui/userdatarequest.ui.h (original)
+++ wpasupplicant/trunk/wpa_supplicant/wpa_gui/userdatarequest.ui.h Sat Jun 14 00:40:26 2008
@@ -9,6 +9,8 @@
 ** These will automatically be called by the form's constructor and
 ** destructor.
 *****************************************************************************/
+
+#include <stdlib.h>
 
 int UserDataRequest::setParams(WpaGui *_wpagui, const char *reqMsg)
 {

Modified: wpasupplicant/trunk/wpa_supplicant/wpa_gui/wpagui.ui.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/wpa_supplicant/wpa_gui/wpagui.ui.h?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/wpa_supplicant/wpa_gui/wpagui.ui.h (original)
+++ wpasupplicant/trunk/wpa_supplicant/wpa_gui/wpagui.ui.h Sat Jun 14 00:40:26 2008
@@ -16,6 +16,7 @@
 #include <unistd.h>
 #endif
 
+#include <stdlib.h>
 
 void WpaGui::init()
 {

Modified: wpasupplicant/trunk/wpa_supplicant/wpa_gui/wpamsg.h
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/wpa_supplicant/wpa_gui/wpamsg.h?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/wpa_supplicant/wpa_gui/wpamsg.h (original)
+++ wpasupplicant/trunk/wpa_supplicant/wpa_gui/wpamsg.h Sat Jun 14 00:40:26 2008
@@ -14,6 +14,7 @@
 
 class WpaMsg {
 public:
+    WpaMsg() {}
     WpaMsg(const QString &_msg, int _priority = 2)
 	: msg(_msg), priority(_priority)
     {

Modified: wpasupplicant/trunk/wpa_supplicant/wpa_supplicant.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/wpa_supplicant/wpa_supplicant.c?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/wpa_supplicant/wpa_supplicant.c (original)
+++ wpasupplicant/trunk/wpa_supplicant/wpa_supplicant.c Sat Jun 14 00:40:26 2008
@@ -187,7 +187,7 @@
 {
 	struct wpa_supplicant *wpa_s = eloop_ctx;
 	const u8 *bssid = wpa_s->bssid;
-	if (os_memcmp(bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) == 0)
+	if (is_zero_ether_addr(bssid))
 		bssid = wpa_s->pending_bssid;
 	wpa_msg(wpa_s, MSG_INFO, "Authentication with " MACSTR " timed out.",
 		MAC2STR(bssid));
@@ -1090,13 +1090,15 @@
 		wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
 	} else {
 		/* Timeout for IEEE 802.11 authentication and association */
-		int timeout;
-		if (assoc_failed)
-			timeout = 5;
-		else if (wpa_s->conf->ap_scan == 1)
-			timeout = 10;
-		else
-			timeout = 60;
+		int timeout = 60;
+
+		if (assoc_failed) {
+			/* give IBSS a bit more time */
+ 			timeout = ssid->mode ? 10 : 5;
+		} else if (wpa_s->conf->ap_scan == 1) {
+			/* give IBSS a bit more time */
+ 			timeout = ssid->mode ? 20 : 10;
+		}
 		wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
 	}
 
@@ -1131,8 +1133,7 @@
 				 int reason_code)
 {
 	u8 *addr = NULL;
-	if (os_memcmp(wpa_s->bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) != 0)
-	{
+	if (!is_zero_ether_addr(wpa_s->bssid)) {
 		if (wpa_s->use_client_mlme)
 			ieee80211_sta_disassociate(wpa_s, reason_code);
 		else
@@ -1160,8 +1161,7 @@
 {
 	u8 *addr = NULL;
 	wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
-	if (os_memcmp(wpa_s->bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) != 0)
-	{
+	if (!is_zero_ether_addr(wpa_s->bssid)) {
 		if (wpa_s->use_client_mlme)
 			ieee80211_sta_deauthenticate(wpa_s, reason_code);
 		else

Modified: wpasupplicant/trunk/wpa_supplicant/wpa_supplicant.conf
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/wpa_supplicant/wpa_supplicant.conf?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/wpa_supplicant/wpa_supplicant.conf (original)
+++ wpasupplicant/trunk/wpa_supplicant/wpa_supplicant.conf Sat Jun 14 00:40:26 2008
@@ -304,7 +304,7 @@
 #	MSCHAP (EAP-MSCHAPv2, EAP-TTLS/MSCHAPv2, EAP-TTLS/MSCHAP, LEAP).
 #	EAP-PSK (128-bit PSK), EAP-PAX (128-bit PSK), and EAP-SAKE (256-bit
 #	PSK) is also configured using this field. For EAP-GPSK, this is a
-	variable length PSK.
+#	variable length PSK.
 # 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
@@ -387,6 +387,11 @@
 #	challenges (by default, it accepts 2 or 3)
 #	result_ind=1 can be used to enable EAP-SIM and EAP-AKA to use
 #	protected result indication.
+#	'crypto_binding' option can be used to control PEAPv0 cryptobinding
+#	behavior:
+#	 * 0 = do not use cryptobinding
+#	 * 1 = use cryptobinding if server supports it (default)
+#	 * 2 = require cryptobinding
 # phase2: Phase2 (inner authentication with TLS tunnel) parameters
 #	(string with field-value pairs, e.g., "auth=MSCHAPV2" for EAP-PEAP or
 #	"autheap=MSCHAPV2 autheap=MD5" for EAP-TTLS)

Modified: wpasupplicant/trunk/wpa_supplicant/wpas_glue.c
URL: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/wpa_supplicant/wpas_glue.c?rev=1188&op=diff
==============================================================================
--- wpasupplicant/trunk/wpa_supplicant/wpas_glue.c (original)
+++ wpasupplicant/trunk/wpa_supplicant/wpas_glue.c Sat Jun 14 00:40:26 2008
@@ -143,13 +143,11 @@
 		return -1;
 	}
 
-	if (os_memcmp(wpa_s->bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) == 0)
-	{
+	if (is_zero_ether_addr(wpa_s->bssid)) {
 		wpa_printf(MSG_DEBUG, "BSSID not set when trying to send an "
 			   "EAPOL frame");
 		if (wpa_drv_get_bssid(wpa_s, bssid) == 0 &&
-		    os_memcmp(bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) !=
-		    0) {
+		    !is_zero_ether_addr(bssid)) {
 			dst = bssid;
 			wpa_printf(MSG_DEBUG, "Using current BSSID " MACSTR
 				   " from the driver as the EAPOL destination",
@@ -271,7 +269,6 @@
 	    wpa_s->key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X) {
 		wpa_supplicant_set_state(wpa_s, WPA_4WAY_HANDSHAKE);
 	} else {
-		wpa_supplicant_cancel_scan(wpa_s);
 		wpa_supplicant_cancel_auth_timeout(wpa_s);
 		wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
 	}
@@ -355,18 +352,6 @@
 }
 
 
-static void _wpa_supplicant_req_scan(void *wpa_s, int sec, int usec)
-{
-	wpa_supplicant_req_scan(wpa_s, sec, usec);
-}
-
-
-static void _wpa_supplicant_cancel_scan(void *wpa_s)
-{
-	wpa_supplicant_cancel_scan(wpa_s);
-}
-
-
 static void _wpa_supplicant_cancel_auth_timeout(void *wpa_s)
 {
 	wpa_supplicant_cancel_auth_timeout(wpa_s);
@@ -399,12 +384,16 @@
 static void _wpa_supplicant_disassociate(void *wpa_s, int reason_code)
 {
 	wpa_supplicant_disassociate(wpa_s, reason_code);
+	/* Schedule a scan to make sure we continue looking for networks */
+	wpa_supplicant_req_scan(wpa_s, 0, 0);
 }
 
 
 static void _wpa_supplicant_deauthenticate(void *wpa_s, int reason_code)
 {
 	wpa_supplicant_deauthenticate(wpa_s, reason_code);
+	/* Schedule a scan to make sure we continue looking for networks */
+	wpa_supplicant_req_scan(wpa_s, 0, 0);
 }
 
 
@@ -576,8 +565,6 @@
 	ctx->ctx = wpa_s;
 	ctx->set_state = _wpa_supplicant_set_state;
 	ctx->get_state = _wpa_supplicant_get_state;
-	ctx->req_scan = _wpa_supplicant_req_scan;
-	ctx->cancel_scan = _wpa_supplicant_cancel_scan;
 	ctx->deauthenticate = _wpa_supplicant_deauthenticate;
 	ctx->disassociate = _wpa_supplicant_disassociate;
 	ctx->set_key = wpa_supplicant_set_key;
@@ -619,8 +606,10 @@
 		os_memset(&conf, 0, sizeof(conf));
 		conf.peerkey_enabled = ssid->peerkey;
 		conf.allowed_pairwise_cipher = ssid->pairwise_cipher;
+#ifdef IEEE8021X_EAPOL
 		conf.eap_workaround = ssid->eap_workaround;
 		conf.eap_conf_ctx = &ssid->eap;
+#endif /* IEEE8021X_EAPOL */
 		conf.ssid = ssid->ssid;
 		conf.ssid_len = ssid->ssid_len;
 	}




More information about the Pkg-wpa-devel mailing list