diff -up openssl-1.0.0-beta4/apps/s_cb.c.reneg openssl-1.0.0-beta4/apps/s_cb.c --- openssl-1.0.0-beta4/apps/s_cb.c.reneg 2009-10-15 20:48:47.000000000 +0200 +++ openssl-1.0.0-beta4/apps/s_cb.c 2009-11-12 15:02:30.000000000 +0100 @@ -669,6 +669,10 @@ void MS_CALLBACK tlsext_cb(SSL *s, int c extname = "server ticket"; break; + case TLSEXT_TYPE_renegotiate: + extname = "renegotiate"; + break; + #ifdef TLSEXT_TYPE_opaque_prf_input case TLSEXT_TYPE_opaque_prf_input: extname = "opaque PRF input"; diff -up openssl-1.0.0-beta4/apps/s_client.c.reneg openssl-1.0.0-beta4/apps/s_client.c --- openssl-1.0.0-beta4/apps/s_client.c.reneg 2009-11-12 14:57:48.000000000 +0100 +++ openssl-1.0.0-beta4/apps/s_client.c 2009-11-12 15:01:48.000000000 +0100 @@ -343,6 +343,7 @@ static void sc_usage(void) BIO_printf(bio_err," -status - request certificate status from server\n"); BIO_printf(bio_err," -no_ticket - disable use of RFC4507bis session tickets\n"); #endif + BIO_printf(bio_err," -legacy_renegotiation - enable use of legacy renegotiation (dangerous)\n"); } #ifndef OPENSSL_NO_TLSEXT @@ -657,6 +658,8 @@ int MAIN(int argc, char **argv) #endif else if (strcmp(*argv,"-serverpref") == 0) off|=SSL_OP_CIPHER_SERVER_PREFERENCE; + else if (strcmp(*argv,"-legacy_renegotiation") == 0) + off|=SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION; else if (strcmp(*argv,"-cipher") == 0) { if (--argc < 1) goto bad; diff -up openssl-1.0.0-beta4/apps/s_server.c.reneg openssl-1.0.0-beta4/apps/s_server.c --- openssl-1.0.0-beta4/apps/s_server.c.reneg 2009-11-12 14:57:48.000000000 +0100 +++ openssl-1.0.0-beta4/apps/s_server.c 2009-11-12 15:01:48.000000000 +0100 @@ -491,6 +491,7 @@ static void sv_usage(void) BIO_printf(bio_err," not specified (default is %s)\n",TEST_CERT2); BIO_printf(bio_err," -tlsextdebug - hex dump of all TLS extensions received\n"); BIO_printf(bio_err," -no_ticket - disable use of RFC4507bis session tickets\n"); + BIO_printf(bio_err," -legacy_renegotiation - enable use of legacy renegotiation (dangerous)\n"); #endif } @@ -1013,6 +1014,8 @@ int MAIN(int argc, char *argv[]) verify_return_error = 1; else if (strcmp(*argv,"-serverpref") == 0) { off|=SSL_OP_CIPHER_SERVER_PREFERENCE; } + else if (strcmp(*argv,"-legacy_renegotiation") == 0) + off|=SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION; else if (strcmp(*argv,"-cipher") == 0) { if (--argc < 1) goto bad; diff -up openssl-1.0.0-beta4/ssl/tls1.h.reneg openssl-1.0.0-beta4/ssl/tls1.h --- openssl-1.0.0-beta4/ssl/tls1.h.reneg 2009-11-12 14:57:47.000000000 +0100 +++ openssl-1.0.0-beta4/ssl/tls1.h 2009-11-12 15:02:30.000000000 +0100 @@ -201,6 +201,9 @@ extern "C" { # define TLSEXT_TYPE_opaque_prf_input ?? */ #endif +/* Temporary extension type */ +#define TLSEXT_TYPE_renegotiate 0xff01 + /* NameType value from RFC 3546 */ #define TLSEXT_NAMETYPE_host_name 0 /* status request value from RFC 3546 */ diff -up openssl-1.0.0-beta4/ssl/t1_lib.c.reneg openssl-1.0.0-beta4/ssl/t1_lib.c --- openssl-1.0.0-beta4/ssl/t1_lib.c.reneg 2009-11-08 15:36:32.000000000 +0100 +++ openssl-1.0.0-beta4/ssl/t1_lib.c 2009-11-12 15:02:30.000000000 +0100 @@ -315,6 +315,30 @@ unsigned char *ssl_add_clienthello_tlsex ret+=size_str; } + /* Add the renegotiation option: TODOEKR switch */ + { + int el; + + if(!ssl_add_clienthello_renegotiate_ext(s, 0, &el, 0)) + { + SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); + return NULL; + } + + if((limit - p - 4 - el) < 0) return NULL; + + s2n(TLSEXT_TYPE_renegotiate,ret); + s2n(el,ret); + + if(!ssl_add_clienthello_renegotiate_ext(s, ret, &el, el)) + { + SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); + return NULL; + } + + ret += el; + } + #ifndef OPENSSL_NO_EC if (s->tlsext_ecpointformatlist != NULL) { @@ -490,6 +514,31 @@ unsigned char *ssl_add_serverhello_tlsex s2n(TLSEXT_TYPE_server_name,ret); s2n(0,ret); } + + if(s->s3->send_connection_binding) + { + int el; + + if(!ssl_add_serverhello_renegotiate_ext(s, 0, &el, 0)) + { + SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); + return NULL; + } + + if((limit - p - 4 - el) < 0) return NULL; + + s2n(TLSEXT_TYPE_renegotiate,ret); + s2n(el,ret); + + if(!ssl_add_serverhello_renegotiate_ext(s, ret, &el, el)) + { + SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); + return NULL; + } + + ret += el; + } + #ifndef OPENSSL_NO_EC if (s->tlsext_ecpointformatlist != NULL) { @@ -574,11 +623,23 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned short size; unsigned short len; unsigned char *data = *p; + int renegotiate_seen = 0; + s->servername_done = 0; s->tlsext_status_type = -1; + s->s3->send_connection_binding = 0; if (data >= (d+n-2)) + { + if (s->new_session + && !(s->ctx->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)) + { + /* We should always see one extension: the renegotiate extension */ + *al = SSL_AD_ILLEGAL_PARAMETER; /* is this the right alert? */ + return 0; + } return 1; + } n2s(data,len); if (data > (d+n-len)) @@ -790,6 +851,12 @@ int ssl_parse_clienthello_tlsext(SSL *s, return 0; } } + else if (type == TLSEXT_TYPE_renegotiate) + { + if(!ssl_parse_clienthello_renegotiate_ext(s, data, size, al)) + return 0; + renegotiate_seen = 1; + } else if (type == TLSEXT_TYPE_status_request && s->ctx->tlsext_status_cb) { @@ -894,6 +961,14 @@ int ssl_parse_clienthello_tlsext(SSL *s, /* session ticket processed earlier */ data+=size; } + + if (s->new_session && !renegotiate_seen + && !(s->ctx->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)) + { + *al = SSL_AD_ILLEGAL_PARAMETER; /* is this the right alert? */ + return 0; + } + *p = data; return 1; @@ -905,11 +980,22 @@ int ssl_parse_serverhello_tlsext(SSL *s, unsigned short size; unsigned short len; unsigned char *data = *p; - int tlsext_servername = 0; + int renegotiate_seen = 0; if (data >= (d+n-2)) + { + /* Because the client does not see any renegotiation during an + attack, we must enforce this on all server hellos, even the + first */ + if (!(s->ctx->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)) + { + /* We should always see one extension: the renegotiate extension */ + *al = SSL_AD_ILLEGAL_PARAMETER; /* is this the right alert? */ + return 0; + } return 1; + } n2s(data,len); @@ -1025,7 +1111,12 @@ int ssl_parse_serverhello_tlsext(SSL *s, /* Set flag to expect CertificateStatus message */ s->tlsext_status_expected = 1; } - + else if (type == TLSEXT_TYPE_renegotiate) + { + if(!ssl_parse_serverhello_renegotiate_ext(s, data, size, al)) + return 0; + renegotiate_seen = 1; + } data+=size; } @@ -1035,6 +1126,13 @@ int ssl_parse_serverhello_tlsext(SSL *s, return 0; } + if (!renegotiate_seen + && !(s->ctx->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)) + { + *al = SSL_AD_ILLEGAL_PARAMETER; /* is this the right alert? */ + return 0; + } + if (!s->hit && tlsext_servername == 1) { if (s->tlsext_hostname)