1This patch adds support for TLS SessionTicket extension (RFC 5077) for 2the parts used by EAP-FAST (RFC 4851). 3 4This is based on the patch from Alexey Kobozev <akobozev@cisco.com> 5(sent to openssl-dev mailing list on Tue, 07 Jun 2005 15:40:58 +0300). 6 7NOTE: This patch (without SSL_set_hello_extension() wrapper) was 8merged into the upstream OpenSSL 0.9.9 tree and as such, an external 9patch for EAP-FAST support is not needed anymore. 10 11 12 13Index: openssl-SNAP-20081111/ssl/s3_clnt.c 14=================================================================== 15--- openssl-SNAP-20081111.orig/ssl/s3_clnt.c 16+++ openssl-SNAP-20081111/ssl/s3_clnt.c 17@@ -788,6 +788,23 @@ int ssl3_get_server_hello(SSL *s) 18 goto f_err; 19 } 20 21+#ifndef OPENSSL_NO_TLSEXT 22+ /* check if we want to resume the session based on external pre-shared secret */ 23+ if (s->version >= TLS1_VERSION && s->tls_session_secret_cb) 24+ { 25+ SSL_CIPHER *pref_cipher=NULL; 26+ s->session->master_key_length=sizeof(s->session->master_key); 27+ if (s->tls_session_secret_cb(s, s->session->master_key, 28+ &s->session->master_key_length, 29+ NULL, &pref_cipher, 30+ s->tls_session_secret_cb_arg)) 31+ { 32+ s->session->cipher = pref_cipher ? 33+ pref_cipher : ssl_get_cipher_by_char(s, p+j); 34+ } 35+ } 36+#endif /* OPENSSL_NO_TLSEXT */ 37+ 38 if (j != 0 && j == s->session->session_id_length 39 && memcmp(p,s->session->session_id,j) == 0) 40 { 41@@ -2927,11 +2944,8 @@ static int ssl3_check_finished(SSL *s) 42 { 43 int ok; 44 long n; 45- /* If we have no ticket or session ID is non-zero length (a match of 46- * a non-zero session length would never reach here) it cannot be a 47- * resumed session. 48- */ 49- if (!s->session->tlsext_tick || s->session->session_id_length) 50+ /* If we have no ticket it cannot be a resumed session. */ 51+ if (!s->session->tlsext_tick) 52 return 1; 53 /* this function is called when we really expect a Certificate 54 * message, so permit appropriate message length */ 55Index: openssl-SNAP-20081111/ssl/s3_srvr.c 56=================================================================== 57--- openssl-SNAP-20081111.orig/ssl/s3_srvr.c 58+++ openssl-SNAP-20081111/ssl/s3_srvr.c 59@@ -1010,6 +1010,59 @@ int ssl3_get_client_hello(SSL *s) 60 SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT); 61 goto err; 62 } 63+ 64+ /* Check if we want to use external pre-shared secret for this 65+ * handshake for not reused session only. We need to generate 66+ * server_random before calling tls_session_secret_cb in order to allow 67+ * SessionTicket processing to use it in key derivation. */ 68+ { 69+ unsigned long Time; 70+ unsigned char *pos; 71+ Time=(unsigned long)time(NULL); /* Time */ 72+ pos=s->s3->server_random; 73+ l2n(Time,pos); 74+ if (RAND_pseudo_bytes(pos,SSL3_RANDOM_SIZE-4) <= 0) 75+ { 76+ al=SSL_AD_INTERNAL_ERROR; 77+ goto f_err; 78+ } 79+ } 80+ 81+ if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb) 82+ { 83+ SSL_CIPHER *pref_cipher=NULL; 84+ 85+ s->session->master_key_length=sizeof(s->session->master_key); 86+ if(s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length, 87+ ciphers, &pref_cipher, s->tls_session_secret_cb_arg)) 88+ { 89+ s->hit=1; 90+ s->session->ciphers=ciphers; 91+ s->session->verify_result=X509_V_OK; 92+ 93+ ciphers=NULL; 94+ 95+ /* check if some cipher was preferred by call back */ 96+ pref_cipher=pref_cipher ? pref_cipher : ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s)); 97+ if (pref_cipher == NULL) 98+ { 99+ al=SSL_AD_HANDSHAKE_FAILURE; 100+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER); 101+ goto f_err; 102+ } 103+ 104+ s->session->cipher=pref_cipher; 105+ 106+ if (s->cipher_list) 107+ sk_SSL_CIPHER_free(s->cipher_list); 108+ 109+ if (s->cipher_list_by_id) 110+ sk_SSL_CIPHER_free(s->cipher_list_by_id); 111+ 112+ s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers); 113+ s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers); 114+ } 115+ } 116 #endif 117 118 /* Worst case, we will use the NULL compression, but if we have other 119@@ -1134,16 +1187,22 @@ int ssl3_send_server_hello(SSL *s) 120 unsigned char *buf; 121 unsigned char *p,*d; 122 int i,sl; 123- unsigned long l,Time; 124+ unsigned long l; 125+#ifdef OPENSSL_NO_TLSEXT 126+ unsigned long Time; 127+#endif 128 129 if (s->state == SSL3_ST_SW_SRVR_HELLO_A) 130 { 131 buf=(unsigned char *)s->init_buf->data; 132+#ifdef OPENSSL_NO_TLSEXT 133 p=s->s3->server_random; 134+ /* Generate server_random if it was not needed previously */ 135 Time=(unsigned long)time(NULL); /* Time */ 136 l2n(Time,p); 137 if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0) 138 return -1; 139+#endif 140 /* Do the message type and length last */ 141 d=p= &(buf[4]); 142 143Index: openssl-SNAP-20081111/ssl/ssl_err.c 144=================================================================== 145--- openssl-SNAP-20081111.orig/ssl/ssl_err.c 146+++ openssl-SNAP-20081111/ssl/ssl_err.c 147@@ -263,6 +263,7 @@ static ERR_STRING_DATA SSL_str_functs[]= 148 {ERR_FUNC(SSL_F_TLS1_PRF), "tls1_prf"}, 149 {ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK), "TLS1_SETUP_KEY_BLOCK"}, 150 {ERR_FUNC(SSL_F_WRITE_PENDING), "WRITE_PENDING"}, 151+{ERR_FUNC(SSL_F_SSL_SET_SESSION_TICKET_EXT), "SSL_set_session_ticket_ext"}, 152 {0,NULL} 153 }; 154 155Index: openssl-SNAP-20081111/ssl/ssl.h 156=================================================================== 157--- openssl-SNAP-20081111.orig/ssl/ssl.h 158+++ openssl-SNAP-20081111/ssl/ssl.h 159@@ -355,6 +355,7 @@ extern "C" { 160 * 'struct ssl_st *' function parameters used to prototype callbacks 161 * in SSL_CTX. */ 162 typedef struct ssl_st *ssl_crock_st; 163+typedef struct tls_session_ticket_ext_st TLS_SESSION_TICKET_EXT; 164 165 /* used to hold info on the particular ciphers used */ 166 typedef struct ssl_cipher_st 167@@ -378,6 +379,8 @@ typedef struct ssl_cipher_st 168 169 DECLARE_STACK_OF(SSL_CIPHER) 170 171+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); 172+ 173 /* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */ 174 typedef struct ssl_method_st 175 { 176@@ -1145,6 +1148,13 @@ struct ssl_st 177 void *tlsext_opaque_prf_input; 178 size_t tlsext_opaque_prf_input_len; 179 180+ /* TLS Session Ticket extension override */ 181+ TLS_SESSION_TICKET_EXT *tlsext_session_ticket; 182+ 183+ /* TLS pre-shared secret session resumption */ 184+ tls_session_secret_cb_fn tls_session_secret_cb; 185+ void *tls_session_secret_cb_arg; 186+ 187 SSL_CTX * initial_ctx; /* initial ctx, used to store sessions */ 188 #define session_ctx initial_ctx 189 #else 190@@ -1746,6 +1756,16 @@ void *SSL_COMP_get_compression_methods(v 191 int SSL_COMP_add_compression_method(int id,void *cm); 192 #endif 193 194+/* NOTE: This function will be removed; it is only here for backwards 195+ * compatibility for the API during testing. */ 196+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len); 197+ 198+/* TLS extensions functions */ 199+int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len); 200+ 201+/* Pre-shared secret session resumption functions */ 202+int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg); 203+ 204 /* BEGIN ERROR CODES */ 205 /* The following lines are auto generated by the script mkerr.pl. Any changes 206 * made after this point may be overwritten when the script is next run. 207@@ -1948,6 +1968,7 @@ void ERR_load_SSL_strings(void); 208 #define SSL_F_TLS1_PRF 284 209 #define SSL_F_TLS1_SETUP_KEY_BLOCK 211 210 #define SSL_F_WRITE_PENDING 212 211+#define SSL_F_SSL_SET_SESSION_TICKET_EXT 213 212 213 /* Reason codes. */ 214 #define SSL_R_APP_DATA_IN_HANDSHAKE 100 215Index: openssl-SNAP-20081111/ssl/ssl_sess.c 216=================================================================== 217--- openssl-SNAP-20081111.orig/ssl/ssl_sess.c 218+++ openssl-SNAP-20081111/ssl/ssl_sess.c 219@@ -834,6 +834,62 @@ long SSL_CTX_get_timeout(const SSL_CTX * 220 return(s->session_timeout); 221 } 222 223+#ifndef OPENSSL_NO_TLSEXT 224+int SSL_set_session_secret_cb(SSL *s, int (*tls_session_secret_cb)(SSL *s, void *secret, int *secret_len, 225+ STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg), void *arg) 226+ { 227+ if (s == NULL) return(0); 228+ s->tls_session_secret_cb = tls_session_secret_cb; 229+ s->tls_session_secret_cb_arg = arg; 230+ return(1); 231+ } 232+ 233+int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len) 234+ { 235+ if (s->version >= TLS1_VERSION) 236+ { 237+ if (s->tlsext_session_ticket) 238+ { 239+ OPENSSL_free(s->tlsext_session_ticket); 240+ s->tlsext_session_ticket = NULL; 241+ } 242+ 243+ s->tlsext_session_ticket = OPENSSL_malloc(sizeof(TLS_SESSION_TICKET_EXT) + ext_len); 244+ if (!s->tlsext_session_ticket) 245+ { 246+ SSLerr(SSL_F_SSL_SET_SESSION_TICKET_EXT, ERR_R_MALLOC_FAILURE); 247+ return 0; 248+ } 249+ 250+ if (ext_data) 251+ { 252+ s->tlsext_session_ticket->length = ext_len; 253+ s->tlsext_session_ticket->data = s->tlsext_session_ticket + 1; 254+ memcpy(s->tlsext_session_ticket->data, ext_data, ext_len); 255+ } 256+ else 257+ { 258+ s->tlsext_session_ticket->length = 0; 259+ s->tlsext_session_ticket->data = NULL; 260+ } 261+ 262+ return 1; 263+ } 264+ 265+ return 0; 266+ } 267+ 268+/* NOTE: This function will be removed; it is only here for backwards 269+ * compatibility for the API during testing. */ 270+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len) 271+ { 272+ if (ext_type != TLSEXT_TYPE_session_ticket) 273+ return 0; 274+ 275+ return SSL_set_session_ticket_ext(s, ext_data, ext_len); 276+ } 277+#endif /* OPENSSL_NO_TLSEXT */ 278+ 279 typedef struct timeout_param_st 280 { 281 SSL_CTX *ctx; 282Index: openssl-SNAP-20081111/ssl/t1_lib.c 283=================================================================== 284--- openssl-SNAP-20081111.orig/ssl/t1_lib.c 285+++ openssl-SNAP-20081111/ssl/t1_lib.c 286@@ -154,6 +154,12 @@ int tls1_new(SSL *s) 287 288 void tls1_free(SSL *s) 289 { 290+#ifndef OPENSSL_NO_TLSEXT 291+ if (s->tlsext_session_ticket) 292+ { 293+ OPENSSL_free(s->tlsext_session_ticket); 294+ } 295+#endif /* OPENSSL_NO_TLSEXT */ 296 ssl3_free(s); 297 } 298 299@@ -357,8 +363,23 @@ unsigned char *ssl_add_clienthello_tlsex 300 int ticklen; 301 if (s->session && s->session->tlsext_tick) 302 ticklen = s->session->tlsext_ticklen; 303+ else if (s->session && s->tlsext_session_ticket && 304+ s->tlsext_session_ticket->data) 305+ { 306+ ticklen = s->tlsext_session_ticket->length; 307+ s->session->tlsext_tick = OPENSSL_malloc(ticklen); 308+ if (!s->session->tlsext_tick) 309+ return NULL; 310+ memcpy(s->session->tlsext_tick, 311+ s->tlsext_session_ticket->data, 312+ ticklen); 313+ s->session->tlsext_ticklen = ticklen; 314+ } 315 else 316 ticklen = 0; 317+ if (ticklen == 0 && s->tlsext_session_ticket && 318+ s->tlsext_session_ticket->data == NULL) 319+ goto skip_ext; 320 /* Check for enough room 2 for extension type, 2 for len 321 * rest for ticket 322 */ 323@@ -371,6 +392,7 @@ unsigned char *ssl_add_clienthello_tlsex 324 ret += ticklen; 325 } 326 } 327+ skip_ext: 328 329 #ifdef TLSEXT_TYPE_opaque_prf_input 330 if (s->s3->client_opaque_prf_input != NULL) 331@@ -1435,6 +1457,15 @@ int tls1_process_ticket(SSL *s, unsigned 332 s->tlsext_ticket_expected = 1; 333 return 0; /* Cache miss */ 334 } 335+ if (s->tls_session_secret_cb) 336+ { 337+ /* Indicate cache miss here and instead of 338+ * generating the session from ticket now, 339+ * trigger abbreviated handshake based on 340+ * external mechanism to calculate the master 341+ * secret later. */ 342+ return 0; 343+ } 344 return tls_decrypt_ticket(s, p, size, session_id, len, 345 ret); 346 } 347Index: openssl-SNAP-20081111/ssl/tls1.h 348=================================================================== 349--- openssl-SNAP-20081111.orig/ssl/tls1.h 350+++ openssl-SNAP-20081111/ssl/tls1.h 351@@ -512,6 +512,13 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_T 352 #define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" /*master secret*/ 353 #endif 354 355+/* TLS Session Ticket extension struct */ 356+struct tls_session_ticket_ext_st 357+ { 358+ unsigned short length; 359+ void *data; 360+ }; 361+ 362 #ifdef __cplusplus 363 } 364 #endif 365Index: openssl-SNAP-20081111/util/ssleay.num 366=================================================================== 367--- openssl-SNAP-20081111.orig/util/ssleay.num 368+++ openssl-SNAP-20081111/util/ssleay.num 369@@ -254,3 +254,5 @@ PEM_read_bio_SSL_SESSION 370 SSL_CTX_set_psk_server_callback 303 EXIST::FUNCTION:PSK 371 SSL_get_psk_identity 304 EXIST::FUNCTION:PSK 372 PEM_write_SSL_SESSION 305 EXIST:!WIN16:FUNCTION: 373+SSL_set_session_ticket_ext 306 EXIST::FUNCTION:TLSEXT 374+SSL_set_session_secret_cb 307 EXIST::FUNCTION:TLSEXT 375