1214501SrpauloThis patch adds support for TLS SessionTicket extension (RFC 5077) for 2214501Srpaulothe parts used by EAP-FAST (RFC 4851). 3214501Srpaulo 4214501SrpauloThis is based on the patch from Alexey Kobozev <akobozev@cisco.com> 5214501Srpaulo(sent to openssl-dev mailing list on Tue, 07 Jun 2005 15:40:58 +0300). 6214501Srpaulo 7214501SrpauloOpenSSL 0.9.8g does not enable TLS extension support by default, so it 8214501Srpaulowill need to be enabled by adding enable-tlsext to config script 9214501Srpaulocommand line. 10214501Srpaulo 11214501Srpaulo 12214501Srpaulodiff -upr openssl-0.9.8g.orig/ssl/s3_clnt.c openssl-0.9.8g/ssl/s3_clnt.c 13214501Srpaulo--- openssl-0.9.8g.orig/ssl/s3_clnt.c 2007-08-31 03:28:51.000000000 +0300 14214501Srpaulo+++ openssl-0.9.8g/ssl/s3_clnt.c 2008-04-15 17:11:46.000000000 +0300 15214501Srpaulo@@ -727,6 +727,20 @@ int ssl3_get_server_hello(SSL *s) 16214501Srpaulo goto f_err; 17214501Srpaulo } 18214501Srpaulo 19214501Srpaulo+#ifndef OPENSSL_NO_TLSEXT 20214501Srpaulo+ /* check if we want to resume the session based on external pre-shared secret */ 21214501Srpaulo+ if (s->version >= TLS1_VERSION && s->tls_session_secret_cb) 22214501Srpaulo+ { 23214501Srpaulo+ SSL_CIPHER *pref_cipher=NULL; 24214501Srpaulo+ s->session->master_key_length=sizeof(s->session->master_key); 25214501Srpaulo+ if (s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length, 26214501Srpaulo+ NULL, &pref_cipher, s->tls_session_secret_cb_arg)) 27214501Srpaulo+ { 28214501Srpaulo+ s->session->cipher=pref_cipher ? pref_cipher : ssl_get_cipher_by_char(s,p+j); 29214501Srpaulo+ } 30214501Srpaulo+ } 31214501Srpaulo+#endif /* OPENSSL_NO_TLSEXT */ 32214501Srpaulo+ 33214501Srpaulo if (j != 0 && j == s->session->session_id_length 34214501Srpaulo && memcmp(p,s->session->session_id,j) == 0) 35214501Srpaulo { 36214501Srpaulodiff -upr openssl-0.9.8g.orig/ssl/s3_srvr.c openssl-0.9.8g/ssl/s3_srvr.c 37214501Srpaulo--- openssl-0.9.8g.orig/ssl/s3_srvr.c 2007-09-30 21:55:59.000000000 +0300 38214501Srpaulo+++ openssl-0.9.8g/ssl/s3_srvr.c 2008-04-15 17:10:37.000000000 +0300 39214501Srpaulo@@ -928,6 +928,59 @@ int ssl3_get_client_hello(SSL *s) 40214501Srpaulo SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT); 41214501Srpaulo goto err; 42214501Srpaulo } 43214501Srpaulo+ 44214501Srpaulo+ /* Check if we want to use external pre-shared secret for this 45214501Srpaulo+ * handshake for not reused session only. We need to generate 46214501Srpaulo+ * server_random before calling tls_session_secret_cb in order to allow 47214501Srpaulo+ * SessionTicket processing to use it in key derivation. */ 48214501Srpaulo+ { 49214501Srpaulo+ unsigned long Time; 50214501Srpaulo+ unsigned char *pos; 51214501Srpaulo+ Time=(unsigned long)time(NULL); /* Time */ 52214501Srpaulo+ pos=s->s3->server_random; 53214501Srpaulo+ l2n(Time,pos); 54214501Srpaulo+ if (RAND_pseudo_bytes(pos,SSL3_RANDOM_SIZE-4) <= 0) 55214501Srpaulo+ { 56214501Srpaulo+ al=SSL_AD_INTERNAL_ERROR; 57214501Srpaulo+ goto f_err; 58214501Srpaulo+ } 59214501Srpaulo+ } 60214501Srpaulo+ 61214501Srpaulo+ if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb) 62214501Srpaulo+ { 63214501Srpaulo+ SSL_CIPHER *pref_cipher=NULL; 64214501Srpaulo+ 65214501Srpaulo+ s->session->master_key_length=sizeof(s->session->master_key); 66214501Srpaulo+ if(s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length, 67214501Srpaulo+ ciphers, &pref_cipher, s->tls_session_secret_cb_arg)) 68214501Srpaulo+ { 69214501Srpaulo+ s->hit=1; 70214501Srpaulo+ s->session->ciphers=ciphers; 71214501Srpaulo+ s->session->verify_result=X509_V_OK; 72214501Srpaulo+ 73214501Srpaulo+ ciphers=NULL; 74214501Srpaulo+ 75214501Srpaulo+ /* check if some cipher was preferred by call back */ 76214501Srpaulo+ pref_cipher=pref_cipher ? pref_cipher : ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s)); 77214501Srpaulo+ if (pref_cipher == NULL) 78214501Srpaulo+ { 79214501Srpaulo+ al=SSL_AD_HANDSHAKE_FAILURE; 80214501Srpaulo+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER); 81214501Srpaulo+ goto f_err; 82214501Srpaulo+ } 83214501Srpaulo+ 84214501Srpaulo+ s->session->cipher=pref_cipher; 85214501Srpaulo+ 86214501Srpaulo+ if (s->cipher_list) 87214501Srpaulo+ sk_SSL_CIPHER_free(s->cipher_list); 88214501Srpaulo+ 89214501Srpaulo+ if (s->cipher_list_by_id) 90214501Srpaulo+ sk_SSL_CIPHER_free(s->cipher_list_by_id); 91214501Srpaulo+ 92214501Srpaulo+ s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers); 93214501Srpaulo+ s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers); 94214501Srpaulo+ } 95214501Srpaulo+ } 96214501Srpaulo #endif 97214501Srpaulo /* Worst case, we will use the NULL compression, but if we have other 98214501Srpaulo * options, we will now look for them. We have i-1 compression 99214501Srpaulo@@ -1066,16 +1119,22 @@ int ssl3_send_server_hello(SSL *s) 100214501Srpaulo unsigned char *buf; 101214501Srpaulo unsigned char *p,*d; 102214501Srpaulo int i,sl; 103214501Srpaulo- unsigned long l,Time; 104214501Srpaulo+ unsigned long l; 105214501Srpaulo+#ifdef OPENSSL_NO_TLSEXT 106214501Srpaulo+ unsigned long Time; 107214501Srpaulo+#endif 108214501Srpaulo 109214501Srpaulo if (s->state == SSL3_ST_SW_SRVR_HELLO_A) 110214501Srpaulo { 111214501Srpaulo buf=(unsigned char *)s->init_buf->data; 112214501Srpaulo+#ifdef OPENSSL_NO_TLSEXT 113214501Srpaulo p=s->s3->server_random; 114214501Srpaulo+ /* Generate server_random if it was not needed previously */ 115214501Srpaulo Time=(unsigned long)time(NULL); /* Time */ 116214501Srpaulo l2n(Time,p); 117214501Srpaulo if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0) 118214501Srpaulo return -1; 119214501Srpaulo+#endif 120214501Srpaulo /* Do the message type and length last */ 121214501Srpaulo d=p= &(buf[4]); 122214501Srpaulo 123214501Srpaulodiff -upr openssl-0.9.8g.orig/ssl/ssl.h openssl-0.9.8g/ssl/ssl.h 124214501Srpaulo--- openssl-0.9.8g.orig/ssl/ssl.h 2007-10-19 10:42:38.000000000 +0300 125214501Srpaulo+++ openssl-0.9.8g/ssl/ssl.h 2008-04-15 17:10:37.000000000 +0300 126214501Srpaulo@@ -342,6 +342,7 @@ extern "C" { 127214501Srpaulo * 'struct ssl_st *' function parameters used to prototype callbacks 128214501Srpaulo * in SSL_CTX. */ 129214501Srpaulo typedef struct ssl_st *ssl_crock_st; 130214501Srpaulo+typedef struct tls_extension_st TLS_EXTENSION; 131214501Srpaulo 132214501Srpaulo /* used to hold info on the particular ciphers used */ 133214501Srpaulo typedef struct ssl_cipher_st 134214501Srpaulo@@ -363,6 +364,8 @@ DECLARE_STACK_OF(SSL_CIPHER) 135214501Srpaulo typedef struct ssl_st SSL; 136214501Srpaulo typedef struct ssl_ctx_st SSL_CTX; 137214501Srpaulo 138214501Srpaulo+typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg); 139214501Srpaulo+ 140214501Srpaulo /* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */ 141214501Srpaulo typedef struct ssl_method_st 142214501Srpaulo { 143214501Srpaulo@@ -1004,6 +1007,14 @@ struct ssl_st 144214501Srpaulo */ 145214501Srpaulo /* RFC4507 session ticket expected to be received or sent */ 146214501Srpaulo int tlsext_ticket_expected; 147214501Srpaulo+ 148214501Srpaulo+ /* TLS extensions */ 149214501Srpaulo+ TLS_EXTENSION *tls_extension; 150214501Srpaulo+ 151214501Srpaulo+ /* TLS pre-shared secret session resumption */ 152214501Srpaulo+ tls_session_secret_cb_fn tls_session_secret_cb; 153214501Srpaulo+ void *tls_session_secret_cb_arg; 154214501Srpaulo+ 155214501Srpaulo SSL_CTX * initial_ctx; /* initial ctx, used to store sessions */ 156214501Srpaulo #define session_ctx initial_ctx 157214501Srpaulo #else 158214501Srpaulo@@ -1589,6 +1600,12 @@ void *SSL_COMP_get_compression_methods(v 159214501Srpaulo int SSL_COMP_add_compression_method(int id,void *cm); 160214501Srpaulo #endif 161214501Srpaulo 162214501Srpaulo+/* TLS extensions functions */ 163214501Srpaulo+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len); 164214501Srpaulo+ 165214501Srpaulo+/* Pre-shared secret session resumption functions */ 166214501Srpaulo+int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg); 167214501Srpaulo+ 168214501Srpaulo /* BEGIN ERROR CODES */ 169214501Srpaulo /* The following lines are auto generated by the script mkerr.pl. Any changes 170214501Srpaulo * made after this point may be overwritten when the script is next run. 171214501Srpaulo@@ -1778,6 +1795,7 @@ void ERR_load_SSL_strings(void); 172214501Srpaulo #define SSL_F_TLS1_ENC 210 173214501Srpaulo #define SSL_F_TLS1_SETUP_KEY_BLOCK 211 174214501Srpaulo #define SSL_F_WRITE_PENDING 212 175214501Srpaulo+#define SSL_F_SSL_SET_HELLO_EXTENSION 213 176214501Srpaulo 177214501Srpaulo /* Reason codes. */ 178214501Srpaulo #define SSL_R_APP_DATA_IN_HANDSHAKE 100 179214501Srpaulodiff -upr openssl-0.9.8g.orig/ssl/ssl_err.c openssl-0.9.8g/ssl/ssl_err.c 180214501Srpaulo--- openssl-0.9.8g.orig/ssl/ssl_err.c 2007-10-11 17:36:59.000000000 +0300 181214501Srpaulo+++ openssl-0.9.8g/ssl/ssl_err.c 2008-04-15 17:10:37.000000000 +0300 182214501Srpaulo@@ -250,6 +250,7 @@ static ERR_STRING_DATA SSL_str_functs[]= 183214501Srpaulo {ERR_FUNC(SSL_F_TLS1_ENC), "TLS1_ENC"}, 184214501Srpaulo {ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK), "TLS1_SETUP_KEY_BLOCK"}, 185214501Srpaulo {ERR_FUNC(SSL_F_WRITE_PENDING), "WRITE_PENDING"}, 186214501Srpaulo+{ERR_FUNC(SSL_F_SSL_SET_HELLO_EXTENSION), "SSL_set_hello_extension"}, 187214501Srpaulo {0,NULL} 188214501Srpaulo }; 189214501Srpaulo 190214501Srpaulodiff -upr openssl-0.9.8g.orig/ssl/ssl_sess.c openssl-0.9.8g/ssl/ssl_sess.c 191214501Srpaulo--- openssl-0.9.8g.orig/ssl/ssl_sess.c 2007-10-19 10:36:34.000000000 +0300 192214501Srpaulo+++ openssl-0.9.8g/ssl/ssl_sess.c 2008-04-15 17:10:37.000000000 +0300 193214501Srpaulo@@ -704,6 +704,52 @@ long SSL_CTX_get_timeout(const SSL_CTX * 194214501Srpaulo return(s->session_timeout); 195214501Srpaulo } 196214501Srpaulo 197214501Srpaulo+#ifndef OPENSSL_NO_TLSEXT 198214501Srpaulo+int SSL_set_session_secret_cb(SSL *s, int (*tls_session_secret_cb)(SSL *s, void *secret, int *secret_len, 199214501Srpaulo+ STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg), void *arg) 200214501Srpaulo+{ 201214501Srpaulo+ if (s == NULL) return(0); 202214501Srpaulo+ s->tls_session_secret_cb = tls_session_secret_cb; 203214501Srpaulo+ s->tls_session_secret_cb_arg = arg; 204214501Srpaulo+ return(1); 205214501Srpaulo+} 206214501Srpaulo+ 207214501Srpaulo+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len) 208214501Srpaulo+{ 209214501Srpaulo+ if(s->version >= TLS1_VERSION) 210214501Srpaulo+ { 211214501Srpaulo+ if(s->tls_extension) 212214501Srpaulo+ { 213214501Srpaulo+ OPENSSL_free(s->tls_extension); 214214501Srpaulo+ s->tls_extension = NULL; 215214501Srpaulo+ } 216214501Srpaulo+ 217214501Srpaulo+ s->tls_extension = OPENSSL_malloc(sizeof(TLS_EXTENSION) + ext_len); 218214501Srpaulo+ if(!s->tls_extension) 219214501Srpaulo+ { 220214501Srpaulo+ SSLerr(SSL_F_SSL_SET_HELLO_EXTENSION, ERR_R_MALLOC_FAILURE); 221214501Srpaulo+ return 0; 222214501Srpaulo+ } 223214501Srpaulo+ 224214501Srpaulo+ s->tls_extension->type = ext_type; 225214501Srpaulo+ 226214501Srpaulo+ if(ext_data) 227214501Srpaulo+ { 228214501Srpaulo+ s->tls_extension->length = ext_len; 229214501Srpaulo+ s->tls_extension->data = s->tls_extension + 1; 230214501Srpaulo+ memcpy(s->tls_extension->data, ext_data, ext_len); 231214501Srpaulo+ } else { 232214501Srpaulo+ s->tls_extension->length = 0; 233214501Srpaulo+ s->tls_extension->data = NULL; 234214501Srpaulo+ } 235214501Srpaulo+ 236214501Srpaulo+ return 1; 237214501Srpaulo+ } 238214501Srpaulo+ 239214501Srpaulo+ return 0; 240214501Srpaulo+} 241214501Srpaulo+#endif /* OPENSSL_NO_TLSEXT */ 242214501Srpaulo+ 243214501Srpaulo typedef struct timeout_param_st 244214501Srpaulo { 245214501Srpaulo SSL_CTX *ctx; 246214501Srpaulodiff -upr openssl-0.9.8g.orig/ssl/t1_lib.c openssl-0.9.8g/ssl/t1_lib.c 247214501Srpaulo--- openssl-0.9.8g.orig/ssl/t1_lib.c 2007-10-19 10:44:10.000000000 +0300 248214501Srpaulo+++ openssl-0.9.8g/ssl/t1_lib.c 2008-04-15 17:10:37.000000000 +0300 249214501Srpaulo@@ -105,6 +105,12 @@ int tls1_new(SSL *s) 250214501Srpaulo 251214501Srpaulo void tls1_free(SSL *s) 252214501Srpaulo { 253214501Srpaulo+#ifndef OPENSSL_NO_TLSEXT 254214501Srpaulo+ if(s->tls_extension) 255214501Srpaulo+ { 256214501Srpaulo+ OPENSSL_free(s->tls_extension); 257214501Srpaulo+ } 258214501Srpaulo+#endif 259214501Srpaulo ssl3_free(s); 260214501Srpaulo } 261214501Srpaulo 262214501Srpaulo@@ -174,8 +180,24 @@ unsigned char *ssl_add_clienthello_tlsex 263214501Srpaulo int ticklen; 264214501Srpaulo if (s->session && s->session->tlsext_tick) 265214501Srpaulo ticklen = s->session->tlsext_ticklen; 266214501Srpaulo+ else if (s->session && s->tls_extension && 267214501Srpaulo+ s->tls_extension->type == TLSEXT_TYPE_session_ticket && 268214501Srpaulo+ s->tls_extension->data) 269214501Srpaulo+ { 270214501Srpaulo+ ticklen = s->tls_extension->length; 271214501Srpaulo+ s->session->tlsext_tick = OPENSSL_malloc(ticklen); 272214501Srpaulo+ if (!s->session->tlsext_tick) 273214501Srpaulo+ return NULL; 274214501Srpaulo+ memcpy(s->session->tlsext_tick, s->tls_extension->data, 275214501Srpaulo+ ticklen); 276214501Srpaulo+ s->session->tlsext_ticklen = ticklen; 277214501Srpaulo+ } 278214501Srpaulo else 279214501Srpaulo ticklen = 0; 280214501Srpaulo+ if (ticklen == 0 && s->tls_extension && 281214501Srpaulo+ s->tls_extension->type == TLSEXT_TYPE_session_ticket && 282214501Srpaulo+ s->tls_extension->data == NULL) 283214501Srpaulo+ goto skip_ext; 284214501Srpaulo /* Check for enough room 2 for extension type, 2 for len 285214501Srpaulo * rest for ticket 286214501Srpaulo */ 287214501Srpaulo@@ -189,6 +211,7 @@ unsigned char *ssl_add_clienthello_tlsex 288214501Srpaulo ret += ticklen; 289214501Srpaulo } 290214501Srpaulo } 291214501Srpaulo+ skip_ext: 292214501Srpaulo 293214501Srpaulo if ((extdatalen = ret-p-2)== 0) 294214501Srpaulo return p; 295214501Srpaulo@@ -543,6 +566,8 @@ int tls1_process_ticket(SSL *s, unsigned 296214501Srpaulo s->tlsext_ticket_expected = 1; 297214501Srpaulo return 0; /* Cache miss */ 298214501Srpaulo } 299214501Srpaulo+ if (s->tls_session_secret_cb) 300214501Srpaulo+ return 0; 301214501Srpaulo return tls_decrypt_ticket(s, p, size, session_id, len, 302214501Srpaulo ret); 303214501Srpaulo } 304214501Srpaulodiff -upr openssl-0.9.8g.orig/ssl/tls1.h openssl-0.9.8g/ssl/tls1.h 305214501Srpaulo--- openssl-0.9.8g.orig/ssl/tls1.h 2007-08-28 04:12:44.000000000 +0300 306214501Srpaulo+++ openssl-0.9.8g/ssl/tls1.h 2008-04-15 17:10:37.000000000 +0300 307214501Srpaulo@@ -365,6 +365,14 @@ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TLSEXT_SER 308214501Srpaulo #define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" /*master secret*/ 309214501Srpaulo #endif 310214501Srpaulo 311214501Srpaulo+/* TLS extension struct */ 312214501Srpaulo+struct tls_extension_st 313214501Srpaulo+{ 314214501Srpaulo+ unsigned short type; 315214501Srpaulo+ unsigned short length; 316214501Srpaulo+ void *data; 317214501Srpaulo+}; 318214501Srpaulo+ 319214501Srpaulo #ifdef __cplusplus 320214501Srpaulo } 321214501Srpaulo #endif 322214501Srpaulodiff -upr openssl-0.9.8g.orig/util/ssleay.num openssl-0.9.8g/util/ssleay.num 323214501Srpaulo--- openssl-0.9.8g.orig/util/ssleay.num 2007-08-13 01:31:16.000000000 +0300 324214501Srpaulo+++ openssl-0.9.8g/util/ssleay.num 2008-04-15 17:10:37.000000000 +0300 325214501Srpaulo@@ -241,3 +241,5 @@ SSL_CTX_sess_get_remove_cb 326214501Srpaulo SSL_set_SSL_CTX 290 EXIST::FUNCTION: 327214501Srpaulo SSL_get_servername 291 EXIST::FUNCTION:TLSEXT 328214501Srpaulo SSL_get_servername_type 292 EXIST::FUNCTION:TLSEXT 329214501Srpaulo+SSL_set_hello_extension 305 EXIST::FUNCTION:TLSEXT 330214501Srpaulo+SSL_set_session_secret_cb 306 EXIST::FUNCTION:TLSEXT 331