1 |
This patch adds support for TLS SessionTicket extension (RFC 5077) for |
2 |
the parts used by EAP-FAST (RFC 4851). |
3 |
|
4 |
This 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 |
|
7 |
OpenSSL 0.9.8g does not enable TLS extension support by default, so it |
8 |
will need to be enabled by adding enable-tlsext to config script |
9 |
command line. |
10 |
|
11 |
|
12 |
diff -upr openssl-0.9.8g.orig/ssl/s3_clnt.c openssl-0.9.8g/ssl/s3_clnt.c |
13 |
--- openssl-0.9.8g.orig/ssl/s3_clnt.c 2007-08-31 03:28:51.000000000 +0300 |
14 |
+++ openssl-0.9.8g/ssl/s3_clnt.c 2008-04-15 17:11:46.000000000 +0300 |
15 |
@@ -727,6 +727,20 @@ 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 ? pref_cipher : ssl_get_cipher_by_char(s,p+j); |
29 |
+ } |
30 |
+ } |
31 |
+#endif /* OPENSSL_NO_TLSEXT */ |
32 |
+ |
33 |
if (j != 0 && j == s->session->session_id_length |
34 |
&& memcmp(p,s->session->session_id,j) == 0) |
35 |
{ |
36 |
diff -upr openssl-0.9.8g.orig/ssl/s3_srvr.c openssl-0.9.8g/ssl/s3_srvr.c |
37 |
--- openssl-0.9.8g.orig/ssl/s3_srvr.c 2007-09-30 21:55:59.000000000 +0300 |
38 |
+++ openssl-0.9.8g/ssl/s3_srvr.c 2008-04-15 17:10:37.000000000 +0300 |
39 |
@@ -928,6 +928,59 @@ int ssl3_get_client_hello(SSL *s) |
40 |
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT); |
41 |
goto err; |
42 |
} |
43 |
+ |
44 |
+ /* Check if we want to use external pre-shared secret for this |
45 |
+ * handshake for not reused session only. We need to generate |
46 |
+ * server_random before calling tls_session_secret_cb in order to allow |
47 |
+ * SessionTicket processing to use it in key derivation. */ |
48 |
+ { |
49 |
+ unsigned long Time; |
50 |
+ unsigned char *pos; |
51 |
+ Time=(unsigned long)time(NULL); /* Time */ |
52 |
+ pos=s->s3->server_random; |
53 |
+ l2n(Time,pos); |
54 |
+ if (RAND_pseudo_bytes(pos,SSL3_RANDOM_SIZE-4) <= 0) |
55 |
+ { |
56 |
+ al=SSL_AD_INTERNAL_ERROR; |
57 |
+ goto f_err; |
58 |
+ } |
59 |
+ } |
60 |
+ |
61 |
+ if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb) |
62 |
+ { |
63 |
+ SSL_CIPHER *pref_cipher=NULL; |
64 |
+ |
65 |
+ s->session->master_key_length=sizeof(s->session->master_key); |
66 |
+ if(s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length, |
67 |
+ ciphers, &pref_cipher, s->tls_session_secret_cb_arg)) |
68 |
+ { |
69 |
+ s->hit=1; |
70 |
+ s->session->ciphers=ciphers; |
71 |
+ s->session->verify_result=X509_V_OK; |
72 |
+ |
73 |
+ ciphers=NULL; |
74 |
+ |
75 |
+ /* check if some cipher was preferred by call back */ |
76 |
+ pref_cipher=pref_cipher ? pref_cipher : ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s)); |
77 |
+ if (pref_cipher == NULL) |
78 |
+ { |
79 |
+ al=SSL_AD_HANDSHAKE_FAILURE; |
80 |
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER); |
81 |
+ goto f_err; |
82 |
+ } |
83 |
+ |
84 |
+ s->session->cipher=pref_cipher; |
85 |
+ |
86 |
+ if (s->cipher_list) |
87 |
+ sk_SSL_CIPHER_free(s->cipher_list); |
88 |
+ |
89 |
+ if (s->cipher_list_by_id) |
90 |
+ sk_SSL_CIPHER_free(s->cipher_list_by_id); |
91 |
+ |
92 |
+ s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers); |
93 |
+ s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers); |
94 |
+ } |
95 |
+ } |
96 |
#endif |
97 |
/* Worst case, we will use the NULL compression, but if we have other |
98 |
* options, we will now look for them. We have i-1 compression |
99 |
@@ -1066,16 +1119,22 @@ int ssl3_send_server_hello(SSL *s) |
100 |
unsigned char *buf; |
101 |
unsigned char *p,*d; |
102 |
int i,sl; |
103 |
- unsigned long l,Time; |
104 |
+ unsigned long l; |
105 |
+#ifdef OPENSSL_NO_TLSEXT |
106 |
+ unsigned long Time; |
107 |
+#endif |
108 |
|
109 |
if (s->state == SSL3_ST_SW_SRVR_HELLO_A) |
110 |
{ |
111 |
buf=(unsigned char *)s->init_buf->data; |
112 |
+#ifdef OPENSSL_NO_TLSEXT |
113 |
p=s->s3->server_random; |
114 |
+ /* Generate server_random if it was not needed previously */ |
115 |
Time=(unsigned long)time(NULL); /* Time */ |
116 |
l2n(Time,p); |
117 |
if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0) |
118 |
return -1; |
119 |
+#endif |
120 |
/* Do the message type and length last */ |
121 |
d=p= &(buf[4]); |
122 |
|
123 |
diff -upr openssl-0.9.8g.orig/ssl/ssl.h openssl-0.9.8g/ssl/ssl.h |
124 |
--- openssl-0.9.8g.orig/ssl/ssl.h 2007-10-19 10:42:38.000000000 +0300 |
125 |
+++ openssl-0.9.8g/ssl/ssl.h 2008-04-15 17:10:37.000000000 +0300 |
126 |
@@ -342,6 +342,7 @@ extern "C" { |
127 |
* 'struct ssl_st *' function parameters used to prototype callbacks |
128 |
* in SSL_CTX. */ |
129 |
typedef struct ssl_st *ssl_crock_st; |
130 |
+typedef struct tls_extension_st TLS_EXTENSION; |
131 |
|
132 |
/* used to hold info on the particular ciphers used */ |
133 |
typedef struct ssl_cipher_st |
134 |
@@ -363,6 +364,8 @@ DECLARE_STACK_OF(SSL_CIPHER) |
135 |
typedef struct ssl_st SSL; |
136 |
typedef struct ssl_ctx_st SSL_CTX; |
137 |
|
138 |
+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); |
139 |
+ |
140 |
/* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */ |
141 |
typedef struct ssl_method_st |
142 |
{ |
143 |
@@ -1004,6 +1007,14 @@ struct ssl_st |
144 |
*/ |
145 |
/* RFC4507 session ticket expected to be received or sent */ |
146 |
int tlsext_ticket_expected; |
147 |
+ |
148 |
+ /* TLS extensions */ |
149 |
+ TLS_EXTENSION *tls_extension; |
150 |
+ |
151 |
+ /* TLS pre-shared secret session resumption */ |
152 |
+ tls_session_secret_cb_fn tls_session_secret_cb; |
153 |
+ void *tls_session_secret_cb_arg; |
154 |
+ |
155 |
SSL_CTX * initial_ctx; /* initial ctx, used to store sessions */ |
156 |
#define session_ctx initial_ctx |
157 |
#else |
158 |
@@ -1589,6 +1600,12 @@ void *SSL_COMP_get_compression_methods(v |
159 |
int SSL_COMP_add_compression_method(int id,void *cm); |
160 |
#endif |
161 |
|
162 |
+/* TLS extensions functions */ |
163 |
+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len); |
164 |
+ |
165 |
+/* Pre-shared secret session resumption functions */ |
166 |
+int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg); |
167 |
+ |
168 |
/* BEGIN ERROR CODES */ |
169 |
/* The following lines are auto generated by the script mkerr.pl. Any changes |
170 |
* made after this point may be overwritten when the script is next run. |
171 |
@@ -1778,6 +1795,7 @@ void ERR_load_SSL_strings(void); |
172 |
#define SSL_F_TLS1_ENC 210 |
173 |
#define SSL_F_TLS1_SETUP_KEY_BLOCK 211 |
174 |
#define SSL_F_WRITE_PENDING 212 |
175 |
+#define SSL_F_SSL_SET_HELLO_EXTENSION 213 |
176 |
|
177 |
/* Reason codes. */ |
178 |
#define SSL_R_APP_DATA_IN_HANDSHAKE 100 |
179 |
diff -upr openssl-0.9.8g.orig/ssl/ssl_err.c openssl-0.9.8g/ssl/ssl_err.c |
180 |
--- openssl-0.9.8g.orig/ssl/ssl_err.c 2007-10-11 17:36:59.000000000 +0300 |
181 |
+++ openssl-0.9.8g/ssl/ssl_err.c 2008-04-15 17:10:37.000000000 +0300 |
182 |
@@ -250,6 +250,7 @@ static ERR_STRING_DATA SSL_str_functs[]= |
183 |
{ERR_FUNC(SSL_F_TLS1_ENC), "TLS1_ENC"}, |
184 |
{ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK), "TLS1_SETUP_KEY_BLOCK"}, |
185 |
{ERR_FUNC(SSL_F_WRITE_PENDING), "WRITE_PENDING"}, |
186 |
+{ERR_FUNC(SSL_F_SSL_SET_HELLO_EXTENSION), "SSL_set_hello_extension"}, |
187 |
{0,NULL} |
188 |
}; |
189 |
|
190 |
diff -upr openssl-0.9.8g.orig/ssl/ssl_sess.c openssl-0.9.8g/ssl/ssl_sess.c |
191 |
--- openssl-0.9.8g.orig/ssl/ssl_sess.c 2007-10-19 10:36:34.000000000 +0300 |
192 |
+++ openssl-0.9.8g/ssl/ssl_sess.c 2008-04-15 17:10:37.000000000 +0300 |
193 |
@@ -704,6 +704,52 @@ long SSL_CTX_get_timeout(const SSL_CTX * |
194 |
return(s->session_timeout); |
195 |
} |
196 |
|
197 |
+#ifndef OPENSSL_NO_TLSEXT |
198 |
+int SSL_set_session_secret_cb(SSL *s, int (*tls_session_secret_cb)(SSL *s, void *secret, int *secret_len, |
199 |
+ STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg), void *arg) |
200 |
+{ |
201 |
+ if (s == NULL) return(0); |
202 |
+ s->tls_session_secret_cb = tls_session_secret_cb; |
203 |
+ s->tls_session_secret_cb_arg = arg; |
204 |
+ return(1); |
205 |
+} |
206 |
+ |
207 |
+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len) |
208 |
+{ |
209 |
+ if(s->version >= TLS1_VERSION) |
210 |
+ { |
211 |
+ if(s->tls_extension) |
212 |
+ { |
213 |
+ OPENSSL_free(s->tls_extension); |
214 |
+ s->tls_extension = NULL; |
215 |
+ } |
216 |
+ |
217 |
+ s->tls_extension = OPENSSL_malloc(sizeof(TLS_EXTENSION) + ext_len); |
218 |
+ if(!s->tls_extension) |
219 |
+ { |
220 |
+ SSLerr(SSL_F_SSL_SET_HELLO_EXTENSION, ERR_R_MALLOC_FAILURE); |
221 |
+ return 0; |
222 |
+ } |
223 |
+ |
224 |
+ s->tls_extension->type = ext_type; |
225 |
+ |
226 |
+ if(ext_data) |
227 |
+ { |
228 |
+ s->tls_extension->length = ext_len; |
229 |
+ s->tls_extension->data = s->tls_extension + 1; |
230 |
+ memcpy(s->tls_extension->data, ext_data, ext_len); |
231 |
+ } else { |
232 |
+ s->tls_extension->length = 0; |
233 |
+ s->tls_extension->data = NULL; |
234 |
+ } |
235 |
+ |
236 |
+ return 1; |
237 |
+ } |
238 |
+ |
239 |
+ return 0; |
240 |
+} |
241 |
+#endif /* OPENSSL_NO_TLSEXT */ |
242 |
+ |
243 |
typedef struct timeout_param_st |
244 |
{ |
245 |
SSL_CTX *ctx; |
246 |
diff -upr openssl-0.9.8g.orig/ssl/t1_lib.c openssl-0.9.8g/ssl/t1_lib.c |
247 |
--- openssl-0.9.8g.orig/ssl/t1_lib.c 2007-10-19 10:44:10.000000000 +0300 |
248 |
+++ openssl-0.9.8g/ssl/t1_lib.c 2008-04-15 17:10:37.000000000 +0300 |
249 |
@@ -105,6 +105,12 @@ int tls1_new(SSL *s) |
250 |
|
251 |
void tls1_free(SSL *s) |
252 |
{ |
253 |
+#ifndef OPENSSL_NO_TLSEXT |
254 |
+ if(s->tls_extension) |
255 |
+ { |
256 |
+ OPENSSL_free(s->tls_extension); |
257 |
+ } |
258 |
+#endif |
259 |
ssl3_free(s); |
260 |
} |
261 |
|
262 |
@@ -174,8 +180,24 @@ unsigned char *ssl_add_clienthello_tlsex |
263 |
int ticklen; |
264 |
if (s->session && s->session->tlsext_tick) |
265 |
ticklen = s->session->tlsext_ticklen; |
266 |
+ else if (s->session && s->tls_extension && |
267 |
+ s->tls_extension->type == TLSEXT_TYPE_session_ticket && |
268 |
+ s->tls_extension->data) |
269 |
+ { |
270 |
+ ticklen = s->tls_extension->length; |
271 |
+ s->session->tlsext_tick = OPENSSL_malloc(ticklen); |
272 |
+ if (!s->session->tlsext_tick) |
273 |
+ return NULL; |
274 |
+ memcpy(s->session->tlsext_tick, s->tls_extension->data, |
275 |
+ ticklen); |
276 |
+ s->session->tlsext_ticklen = ticklen; |
277 |
+ } |
278 |
else |
279 |
ticklen = 0; |
280 |
+ if (ticklen == 0 && s->tls_extension && |
281 |
+ s->tls_extension->type == TLSEXT_TYPE_session_ticket && |
282 |
+ s->tls_extension->data == NULL) |
283 |
+ goto skip_ext; |
284 |
/* Check for enough room 2 for extension type, 2 for len |
285 |
* rest for ticket |
286 |
*/ |
287 |
@@ -189,6 +211,7 @@ unsigned char *ssl_add_clienthello_tlsex |
288 |
ret += ticklen; |
289 |
} |
290 |
} |
291 |
+ skip_ext: |
292 |
|
293 |
if ((extdatalen = ret-p-2)== 0) |
294 |
return p; |
295 |
@@ -543,6 +566,8 @@ int tls1_process_ticket(SSL *s, unsigned |
296 |
s->tlsext_ticket_expected = 1; |
297 |
return 0; /* Cache miss */ |
298 |
} |
299 |
+ if (s->tls_session_secret_cb) |
300 |
+ return 0; |
301 |
return tls_decrypt_ticket(s, p, size, session_id, len, |
302 |
ret); |
303 |
} |
304 |
diff -upr openssl-0.9.8g.orig/ssl/tls1.h openssl-0.9.8g/ssl/tls1.h |
305 |
--- openssl-0.9.8g.orig/ssl/tls1.h 2007-08-28 04:12:44.000000000 +0300 |
306 |
+++ openssl-0.9.8g/ssl/tls1.h 2008-04-15 17:10:37.000000000 +0300 |
307 |
@@ -365,6 +365,14 @@ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TLSEXT_SER |
308 |
#define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" /*master secret*/ |
309 |
#endif |
310 |
|
311 |
+/* TLS extension struct */ |
312 |
+struct tls_extension_st |
313 |
+{ |
314 |
+ unsigned short type; |
315 |
+ unsigned short length; |
316 |
+ void *data; |
317 |
+}; |
318 |
+ |
319 |
#ifdef __cplusplus |
320 |
} |
321 |
#endif |
322 |
diff -upr openssl-0.9.8g.orig/util/ssleay.num openssl-0.9.8g/util/ssleay.num |
323 |
--- openssl-0.9.8g.orig/util/ssleay.num 2007-08-13 01:31:16.000000000 +0300 |
324 |
+++ openssl-0.9.8g/util/ssleay.num 2008-04-15 17:10:37.000000000 +0300 |
325 |
@@ -241,3 +241,5 @@ SSL_CTX_sess_get_remove_cb |
326 |
SSL_set_SSL_CTX 290 EXIST::FUNCTION: |
327 |
SSL_get_servername 291 EXIST::FUNCTION:TLSEXT |
328 |
SSL_get_servername_type 292 EXIST::FUNCTION:TLSEXT |
329 |
+SSL_set_hello_extension 305 EXIST::FUNCTION:TLSEXT |
330 |
+SSL_set_session_secret_cb 306 EXIST::FUNCTION:TLSEXT |