EAP-FAST has some additional requirements for TLS that do not seem to be
currently supported in OpenSSL. EAP-FAST uses ClientHello extension (RFC
3546, Section 3.1) and it does not use certificates in TLS handshake;
instead, TLS pre-master-secret is set based on PAC-Key (shared secret
from EAP-FAST provisioning).

I have made a proof-of-concept type of patch for OpenSSL to allow
testing EAP-FAST implementation in wpa_supplicant. This seems to be
enough to make EAP-FAST interoperate with Cisco ACS. However, the
changes to OpenSSL are not very clean and may very well be completely
incorrect. Consequently, I would be interested in finding out whether
someone with better understanding of OpenSSL than I have would be
interested in commenting the changes, or even better, in actually making
such changes to OpenSSL distribution.

I've attached the patch file showing the changes I needed to get
EAP-FAST authentication completed. This adds a simple way of adding
ClientHello extensions (RFC 3546, Section 3.1). More generic support for
TLS extensions would of course be ok for this, too. Rest of the patch is
very quick hack to allow TLS handshake to be completed without
certificates; I just changed number of functions to skip certificate
request and validation during the handshake. This is clearly not
suitable to be applied as-is, but I hope it would be enough to generate
some comments on how this should be done correctly.

-- 
Jouni Malinen                                            PGP id EFC895FA
This is a quick hack for testing EAP-FAST with openssl.

Addition of TLS extensions to ClientHello/ServerHello is more or less
ok, though not very clean in the way that the caller needs to take
care of constructing set of all extensions. In addition there is not
mechanism for reading the TLS extensions, i.e., this would not be
enough for EAP-FAST authenticator.

Rest of the changes are obviously ugly and/or incorrect for most
parts, but it demonstrates the minimum set of changes to skip some of
the error cases that prevented completion of TLS handshake without
certificates. In other words, this is just a proof-of-concept type of
example to make it possible to experiment with EAP-FAST. Cleaner patch
for the needed functionality would be welcome..


diff -upr openssl-0.9.7e.orig/include/openssl/ssl.h 
openssl-0.9.7e/include/openssl/ssl.h
--- openssl-0.9.7e.orig/include/openssl/ssl.h   2004-07-27 11:28:49.000000000 
-0700
+++ openssl-0.9.7e/include/openssl/ssl.h        2004-12-24 20:29:01.000000000 
-0800
@@ -929,6 +929,11 @@ struct ssl_st
        int first_packet;
        int client_version;     /* what was passed, used for
                                 * SSLv3/TLS rollback check */
+
+       /* Optional ClientHello/ServerHello extension to be added to the end
+        * of the SSLv3/TLS hello message. */
+       char *hello_extension;
+       int hello_extension_len;
        };
 
 #ifdef __cplusplus
diff -upr openssl-0.9.7e.orig/ssl/s3_both.c openssl-0.9.7e/ssl/s3_both.c
--- openssl-0.9.7e.orig/ssl/s3_both.c   2003-02-12 09:05:17.000000000 -0800
+++ openssl-0.9.7e/ssl/s3_both.c        2004-12-31 21:18:15.556846272 -0800
@@ -199,6 +199,12 @@ int ssl3_get_finished(SSL *s, int a, int
                64, /* should actually be 36+4 :-) */
                &ok);
 
+       if (!ok && s->hello_extension)
+               {
+               /* Quick hack to test EAP-FAST. */
+               return(1);
+       }
+
        if (!ok) return((int)n);
 
        /* If this occurs, we have missed a message */
diff -upr openssl-0.9.7e.orig/ssl/s3_clnt.c openssl-0.9.7e/ssl/s3_clnt.c
--- openssl-0.9.7e.orig/ssl/s3_clnt.c   2004-05-15 09:39:22.000000000 -0700
+++ openssl-0.9.7e/ssl/s3_clnt.c        2004-12-31 21:16:38.617583280 -0800
@@ -588,6 +588,12 @@ static int ssl3_client_hello(SSL *s)
                        *(p++)=comp->id;
                        }
                *(p++)=0; /* Add the NULL method */
+
+               if (s->hello_extension)
+                       {
+                       memcpy(p,s->hello_extension,s->hello_extension_len);
+                       p+=s->hello_extension_len;
+                       }
                
                l=(p-d);
                d=buf;
@@ -779,6 +785,11 @@ static int ssl3_get_server_certificate(S
 
        if (s->s3->tmp.message_type != SSL3_MT_CERTIFICATE)
                {
+               if (s->hello_extension)
+                       {
+                       /* Quick hack to test EAP-FAST. */
+                       return(1);
+                       }
                al=SSL_AD_UNEXPECTED_MESSAGE;
                
SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_BAD_MESSAGE_TYPE);
                goto f_err;
@@ -951,6 +962,12 @@ static int ssl3_get_key_exchange(SSL *s)
        DH *dh=NULL;
 #endif
 
+       if (s->hello_extension)
+               {
+               /* Quick hack to test EAP-FAST. */
+               return(1);
+               }
+
        /* use same message size as in ssl3_get_certificate_request()
         * as ServerKeyExchange message may be skipped */
        n=ssl3_get_message(s,
@@ -1264,6 +1281,12 @@ static int ssl3_get_certificate_request(
        unsigned char *p,*d,*q;
        STACK_OF(X509_NAME) *ca_sk=NULL;
 
+       if (s->hello_extension)
+               {
+               /* Quick hack to test EAP-FAST. */
+               return(1);
+               }
+
        n=ssl3_get_message(s,
                SSL3_ST_CR_CERT_REQ_A,
                SSL3_ST_CR_CERT_REQ_B,
@@ -1407,6 +1430,12 @@ static int ssl3_get_server_done(SSL *s)
        int ok,ret=0;
        long n;
 
+       if (s->hello_extension)
+               {
+               /* Quick hack to test EAP-FAST. */
+               return(1);
+               }
+
        n=ssl3_get_message(s,
                SSL3_ST_CR_SRVR_DONE_A,
                SSL3_ST_CR_SRVR_DONE_B,
@@ -1439,6 +1468,12 @@ static int ssl3_send_client_key_exchange
         KSSL_ERR kssl_err;
 #endif /* OPENSSL_NO_KRB5 */
 
+       if (s->hello_extension)
+               {
+               /* Quick hack to test EAP-FAST. */
+               return(1);
+               }
+
        if (s->state == SSL3_ST_CW_KEY_EXCH_A)
                {
                d=(unsigned char *)s->init_buf->data;
@@ -1880,6 +1915,12 @@ static int ssl3_check_cert_and_algorithm
        DH *dh;
 #endif
 
+       if (s->hello_extension)
+               {
+               /* Quick hack to test EAP-FAST. */
+               return(1);
+               }
+
        sc=s->session->sess_cert;
 
        if (sc == NULL)
diff -upr openssl-0.9.7e.orig/ssl/ssl.h openssl-0.9.7e/ssl/ssl.h
--- openssl-0.9.7e.orig/ssl/ssl.h       2004-07-27 11:28:49.000000000 -0700
+++ openssl-0.9.7e/ssl/ssl.h    2004-12-24 20:29:01.000000000 -0800
@@ -929,6 +929,11 @@ struct ssl_st
        int first_packet;
        int client_version;     /* what was passed, used for
                                 * SSLv3/TLS rollback check */
+
+       /* Optional ClientHello/ServerHello extension to be added to the end
+        * of the SSLv3/TLS hello message. */
+       char *hello_extension;
+       int hello_extension_len;
        };
 
 #ifdef __cplusplus
diff -upr openssl-0.9.7e.orig/ssl/ssl_lib.c openssl-0.9.7e/ssl/ssl_lib.c
--- openssl-0.9.7e.orig/ssl/ssl_lib.c   2004-05-11 05:46:12.000000000 -0700
+++ openssl-0.9.7e/ssl/ssl_lib.c        2004-12-24 20:35:22.000000000 -0800
@@ -478,6 +478,7 @@ void SSL_free(SSL *s)
                kssl_ctx_free(s->kssl_ctx);
 #endif /* OPENSSL_NO_KRB5 */
 
+       OPENSSL_free(s->hello_extension);
        OPENSSL_free(s);
        }
 

Reply via email to