From 7c2d4fee2547650102cd16d23f8125b76112ae75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bodo=20M=C3=B6ller?= Date: Thu, 26 Aug 2010 15:15:47 +0000 Subject: [PATCH] For better forward-security support, add functions SSL_[CTX_]set_not_resumable_session_callback. Submitted by: Emilia Kasper (Google) [A part of this change affecting ssl/s3_lib.c was accidentally commited separately, together with a compilation fix for that file; see s3_lib.c CVS revision 1.133 (http://cvs.openssl.org/chngview?cn=19855).] --- CHANGES | 18 ++++++++++++++++++ apps/s_server.c | 20 ++++++++++++++++++++ ssl/s3_srvr.c | 12 ++++++++++-- ssl/ssl.h | 18 ++++++++++++++++++ ssl/ssl_lib.c | 14 ++++++++++++++ 5 files changed, 80 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 8c6cfbe9d8..114f339e29 100644 --- a/CHANGES +++ b/CHANGES @@ -4,6 +4,24 @@ Changes between 1.0.0 and 1.1.0 [xx XXX xxxx] + *) Improve forward-security support: add functions + + void SSL_CTX_set_not_resumable_session_callback(SSL_CTX *ctx, int (*cb)(SSL *ssl, int is_forward_secure)) + void SSL_set_not_resumable_session_callback(SSL *ssl, int (*cb)(SSL *ssl, int is_forward_secure)) + + for use by SSL/TLS servers; the callback function will be called whenever a + new session is created, and gets to decide whether the session may be + cached to make it resumable (return 0) or not (return 1). (As by the + SSL/TLS protocol specifications, the session_id sent by the server will be + empty to indicate that the session is not resumable; also, the server will + not generate RFC 4507 (RFC 5077) session tickets.) + + A simple reasonable callback implementation is to return is_forward_secure. + This parameter will be set to 1 or 0 depending on the ciphersuite selected + by the SSL/TLS server library, indicating whether it can provide forward + security. + [Emilia Käsper (Google)] + *) Add Next Protocol Negotiation, http://tools.ietf.org/html/draft-agl-tls-nextprotoneg-00. Can be disabled with a no-npn flag to config or Configure. Code donated diff --git a/apps/s_server.c b/apps/s_server.c index d339968200..29c737c251 100644 --- a/apps/s_server.c +++ b/apps/s_server.c @@ -201,6 +201,7 @@ typedef unsigned int u_int; #ifndef OPENSSL_NO_RSA static RSA MS_CALLBACK *tmp_rsa_cb(SSL *s, int is_export, int keylength); #endif +static int not_resumable_sess_cb(SSL *s, int is_forward_secure); static int sv_body(char *hostname, int s, unsigned char *context); static int www_body(char *hostname, int s, unsigned char *context); static void close_accept_socket(void ); @@ -289,6 +290,7 @@ static int s_tlsextdebug=0; static int s_tlsextstatus=0; static int cert_status_cb(SSL *s, void *arg); #endif +static int no_resume_ephemeral = 0; static int s_msg=0; static int s_quiet=0; @@ -476,6 +478,7 @@ static void sv_usage(void) #ifndef OPENSSL_NO_ECDH BIO_printf(bio_err," -no_ecdhe - Disable ephemeral ECDH\n"); #endif + BIO_printf(bio_err, "-no_resume_ephemeral - Disable caching and tickets if ephemeral (EC)DH is used\n"); BIO_printf(bio_err," -bugs - Turn on SSL bug compatibility\n"); BIO_printf(bio_err," -www - Respond to a 'GET /' with a status page\n"); BIO_printf(bio_err," -WWW - Respond to a 'GET / HTTP/1.0' with file ./\n"); @@ -853,6 +856,12 @@ static int next_proto_cb(SSL *s, const unsigned char **data, unsigned int *len, # endif /* ndef OPENSSL_NO_NPN */ #endif +static int not_resumable_sess_cb(SSL *s, int is_forward_secure) + { + /* disable resumption for sessions with forward secure ciphers */ + return is_forward_secure; + } + int MAIN(int, char **); #ifndef OPENSSL_NO_JPAKE @@ -1120,6 +1129,8 @@ int MAIN(int argc, char *argv[]) { no_dhe=1; } else if (strcmp(*argv,"-no_ecdhe") == 0) { no_ecdhe=1; } + else if (strcmp(*argv,"-no_resume_ephemeral") == 0) + { no_resume_ephemeral = 1; } #ifndef OPENSSL_NO_PSK else if (strcmp(*argv,"-psk_hint") == 0) { @@ -1689,6 +1700,15 @@ bad: #endif #endif + if (no_resume_ephemeral) + { + SSL_CTX_set_not_resumable_session_callback(ctx, not_resumable_sess_cb); +#ifndef OPENSSL_NO_TLSEXT + if (ctx2) + SSL_CTX_set_not_resumable_session_callback(ctx2, not_resumable_sess_cb); +#endif + } + #ifndef OPENSSL_NO_PSK #ifdef OPENSSL_NO_JPAKE if (psk_key != NULL) diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c index c2874e7feb..bc6ece47c1 100644 --- a/ssl/s3_srvr.c +++ b/ssl/s3_srvr.c @@ -1251,6 +1251,13 @@ int ssl3_get_client_hello(SSL *s) goto f_err; } s->s3->tmp.new_cipher=c; + /* check whether we should disable session resumption */ + if (s->not_resumable_session_cb != NULL) + s->session->not_resumable=s->not_resumable_session_cb(s, + ((c->algorithm_mkey & (SSL_kEDH | SSL_kEECDH)) != 0)); + if (s->session->not_resumable) + /* do not send a session ticket */ + s->tlsext_ticket_expected = 0; } else { @@ -1354,8 +1361,9 @@ int ssl3_send_server_hello(SSL *s) * if session caching is disabled so existing functionality * is unaffected. */ - if (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_SERVER) - && !s->hit) + if (s->session->not_resumable || + (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_SERVER) + && !s->hit)) s->session->session_id_length=0; sl=s->session->session_id_length; diff --git a/ssl/ssl.h b/ssl/ssl.h index 5a35c67285..20e49ec376 100644 --- a/ssl/ssl.h +++ b/ssl/ssl.h @@ -468,6 +468,9 @@ typedef struct ssl_session_st char *psk_identity_hint; char *psk_identity; #endif + /* Used to indicate that session resumption is not allowed. + * Applications can also set this bit for a new session via + * not_resumable_session_cb to disable session caching and tickets. */ int not_resumable; /* The cert is the certificate used to establish this connection */ @@ -811,6 +814,10 @@ struct ssl_ctx_st X509_VERIFY_PARAM *param; + /* Callback for disabling session caching and ticket support + * on a session basis, depending on the chosen cipher. */ + int (*not_resumable_session_cb)(SSL *ssl, int is_forward_secure); + #if 0 int purpose; /* Purpose setting */ int trust; /* Trust setting */ @@ -1088,6 +1095,10 @@ struct ssl_st X509_VERIFY_PARAM *param; + /* Callback for disabling session caching and ticket support + * on a session basis, depending on the chosen cipher. */ + int (*not_resumable_session_cb)(SSL *ssl, int is_forward_secure); + #if 0 int purpose; /* Purpose setting */ int trust; /* Trust setting */ @@ -1477,6 +1488,7 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION) #define SSL_CTRL_GET_RI_SUPPORT 76 #define SSL_CTRL_CLEAR_OPTIONS 77 #define SSL_CTRL_CLEAR_MODE 78 +#define SSL_CTRL_SET_NOT_RESUMABLE_SESS_CB 79 #define DTLSv1_get_timeout(ssl, arg) \ SSL_ctrl(ssl,DTLS_CTRL_GET_TIMEOUT,0, (void *)arg) @@ -1875,6 +1887,12 @@ int SSL_tls1_key_exporter(SSL *s, unsigned char *label, int label_len, unsigned char *context, int context_len, unsigned char *out, int olen); +void SSL_CTX_set_not_resumable_session_callback(SSL_CTX *ctx, + int (*cb)(SSL *ssl, int is_forward_secure)); + +void SSL_set_not_resumable_session_callback(SSL *ssl, + int (*cb)(SSL *ssl, int is_forward_secure)); + /* BEGIN ERROR CODES */ /* The following lines are auto generated by the script mkerr.pl. Any changes * made after this point may be overwritten when the script is next run. diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index ff710045dc..9dfa3aa711 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -319,6 +319,7 @@ SSL *SSL_new(SSL_CTX *ctx) s->msg_callback=ctx->msg_callback; s->msg_callback_arg=ctx->msg_callback_arg; s->verify_mode=ctx->verify_mode; + s->not_resumable_session_cb=ctx->not_resumable_session_cb; #if 0 s->verify_depth=ctx->verify_depth; #endif @@ -3164,6 +3165,19 @@ void SSL_set_msg_callback(SSL *ssl, void (*cb)(int write_p, int version, int con SSL_callback_ctrl(ssl, SSL_CTRL_SET_MSG_CALLBACK, (void (*)(void))cb); } +void SSL_CTX_set_not_resumable_session_callback(SSL_CTX *ctx, + int (*cb)(SSL *ssl, int is_forward_secure)) + { + SSL_CTX_callback_ctrl(ctx, SSL_CTRL_SET_NOT_RESUMABLE_SESS_CB, + (void (*)(void))cb); + } +void SSL_set_not_resumable_session_callback(SSL *ssl, + int (*cb)(SSL *ssl, int is_forward_secure)) + { + SSL_callback_ctrl(ssl, SSL_CTRL_SET_NOT_RESUMABLE_SESS_CB, + (void (*)(void))cb); + } + /* Allocates new EVP_MD_CTX and sets pointer to it into given pointer * vairable, freeing EVP_MD_CTX previously stored in that variable, if * any. If EVP_MD pointer is passed, initializes ctx with this md -- GitLab