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