Index: ssl/t1_reneg.c =================================================================== --- ssl/t1_reneg.c (revision 0) +++ ssl/t1_reneg.c (revision 5) @@ -0,0 +1,271 @@ +/* ssl/t1_reneg.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +#include +#include +#include +#include "ssl_locl.h" + +/* Add the client's renegotiation binding */ +int ssl_add_clienthello_renegotiate_ext(SSL *s, unsigned char *p, int *len, int maxlen) + { + int ct=0; + int i; + + if(p) + { + if((s->s3->previous_client_finished_len+1) > maxlen) + { + SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATE_EXT_TOO_LONG); + return(1); + } + + /* Length byte */ + *p = s->s3->previous_client_finished_len; + p++; + + memcpy(p, s->s3->previous_client_finished, s->s3->previous_client_finished_len); + } + + *len=s->s3->previous_client_finished_len + 1; + + return(0); + } + +/* Parse the client's renegotiation binding and abort if it's not + right */ +int ssl_parse_clienthello_renegotiate_ext(SSL *s, unsigned char *d, int len,int *al) + { + int ilen; + + /* Parse the length byte */ + if(len < 1) + { + SSLerr(SSL_F_PARSE_SERVER_HELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATION_ENCODING_ERR); + *al=SSL_AD_ILLEGAL_PARAMETER; + return(1); + } + ilen = *d; + d++; + + /* Consistency check */ + if((ilen+1) != len) + { + SSLerr(SSL_F_PARSE_SERVER_HELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATION_ENCODING_ERR); + *al=SSL_AD_ILLEGAL_PARAMETER; + return(1); + } + + /* Check that the extension matches */ + if(ilen != s->s3->previous_client_finished_len) + { + SSLerr(SSL_F_PARSE_CLIENT_HELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATION_MISMATCH); + *al=SSL_AD_ILLEGAL_PARAMETER; + return(1); + } + + if(memcmp(d, s->s3->previous_client_finished, s->s3->previous_client_finished_len)) + { + SSLerr(SSL_F_PARSE_CLIENT_HELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATION_MISMATCH); + *al=SSL_AD_ILLEGAL_PARAMETER; + return(1); + } + + s->s3->send_connection_binding=1; + + return(0); + } + +/* Add the server's renegotiation binding */ +int ssl_add_serverhello_renegotiate_ext(SSL *s, unsigned char *p, int *len, int maxlen) + { + int ct=0; + int i; + + if(p) + { + if((s->s3->previous_client_finished_len + + s->s3->previous_server_finished_len + 1) > maxlen) + { + SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATE_EXT_TOO_LONG); + return(1); + } + + /* Length byte */ + *p = s->s3->previous_client_finished_len + s->s3->previous_server_finished_len; + p++; + + memcpy(p, s->s3->previous_client_finished, s->s3->previous_client_finished_len); + p += s->s3->previous_client_finished_len; + + memcpy(p, s->s3->previous_server_finished, s->s3->previous_server_finished_len); + } + + *len=s->s3->previous_client_finished_len + s->s3->previous_server_finished_len + 1; + + return(0); + } + +/* Parse the server's renegotiation binding and abort if it's not + right */ +int ssl_parse_serverhello_renegotiate_ext(SSL *s, unsigned char *d, int len,int *al) + { + int expected_len=s->s3->previous_client_finished_len + s->s3->previous_server_finished_len; + int ilen; + + /* Check for logic errors */ + assert(!expected_len || s->s3->previous_client_finished_len); + assert(!expected_len || s->s3->previous_server_finished_len); + + /* Parse the length byte */ + if(len < 1) + { + SSLerr(SSL_F_PARSE_SERVER_HELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATION_ENCODING_ERR); + *al=SSL_AD_ILLEGAL_PARAMETER; + return(1); + } + ilen = *d; + d++; + + /* Consistency check */ + if((ilen+1) != len) + { + SSLerr(SSL_F_PARSE_SERVER_HELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATION_ENCODING_ERR); + *al=SSL_AD_ILLEGAL_PARAMETER; + return(1); + } + + /* Check that the extension matches */ + if(ilen != expected_len) + { + SSLerr(SSL_F_PARSE_SERVER_HELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATION_MISMATCH); + *al=SSL_AD_ILLEGAL_PARAMETER; + return(1); + } + + if(memcmp(d, s->s3->previous_client_finished, s->s3->previous_client_finished_len)) + { + SSLerr(SSL_F_PARSE_CLIENT_HELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATION_MISMATCH); + *al=SSL_AD_ILLEGAL_PARAMETER; + return(1); + } + d += s->s3->previous_client_finished_len; + + + if(memcmp(d, s->s3->previous_server_finished, s->s3->previous_server_finished_len)) + { + SSLerr(SSL_F_PARSE_SERVER_HELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATION_MISMATCH); + *al=SSL_AD_ILLEGAL_PARAMETER; + return(1); + } + + return(0); + } + Index: ssl/ssl.h =================================================================== --- ssl/ssl.h (revision 4) +++ ssl/ssl.h (working copy) @@ -1679,6 +1679,8 @@ #define SSL_F_GET_SERVER_HELLO 109 #define SSL_F_GET_SERVER_VERIFY 110 #define SSL_F_I2D_SSL_SESSION 111 +#define SSL_F_PARSE_CLIENT_HELLO_RENEGOTIATE_EXT 280 +#define SSL_F_PARSE_SERVER_HELLO_RENEGOTIATE_EXT 281 #define SSL_F_READ_N 112 #define SSL_F_REQUEST_CERTIFICATE 113 #define SSL_F_SERVER_FINISH 239 @@ -1742,6 +1744,7 @@ #define SSL_F_SSL3_SETUP_KEY_BLOCK 157 #define SSL_F_SSL3_WRITE_BYTES 158 #define SSL_F_SSL3_WRITE_PENDING 159 +#define SSL_F_SSL_ADD_CLIENTHELLO_RENEGOTIATE_EXT 282 #define SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT 272 #define SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK 215 #define SSL_F_SSL_ADD_FILE_CERT_SUBJECTS_TO_STACK 216 @@ -1979,6 +1982,9 @@ #define SSL_R_RECORD_LENGTH_MISMATCH 213 #define SSL_R_RECORD_TOO_LARGE 214 #define SSL_R_RECORD_TOO_SMALL 298 +#define SSL_R_RENEGOTIATE_EXT_TOO_LONG 318 +#define SSL_R_RENEGOTIATION_ENCODING_ERR 320 +#define SSL_R_RENEGOTIATION_MISMATCH 319 #define SSL_R_REQUIRED_CIPHER_MISSING 215 #define SSL_R_REUSE_CERT_LENGTH_NOT_ZERO 216 #define SSL_R_REUSE_CERT_TYPE_NOT_ZERO 217 Index: ssl/ssl_err.c =================================================================== --- ssl/ssl_err.c (revision 4) +++ ssl/ssl_err.c (working copy) @@ -108,6 +108,8 @@ {ERR_FUNC(SSL_F_GET_SERVER_HELLO), "GET_SERVER_HELLO"}, {ERR_FUNC(SSL_F_GET_SERVER_VERIFY), "GET_SERVER_VERIFY"}, {ERR_FUNC(SSL_F_I2D_SSL_SESSION), "i2d_SSL_SESSION"}, +{ERR_FUNC(SSL_F_PARSE_CLIENT_HELLO_RENEGOTIATE_EXT), "PARSE_CLIENT_HELLO_RENEGOTIATE_EXT"}, +{ERR_FUNC(SSL_F_PARSE_SERVER_HELLO_RENEGOTIATE_EXT), "PARSE_SERVER_HELLO_RENEGOTIATE_EXT"}, {ERR_FUNC(SSL_F_READ_N), "READ_N"}, {ERR_FUNC(SSL_F_REQUEST_CERTIFICATE), "REQUEST_CERTIFICATE"}, {ERR_FUNC(SSL_F_SERVER_FINISH), "SERVER_FINISH"}, @@ -171,6 +173,7 @@ {ERR_FUNC(SSL_F_SSL3_SETUP_KEY_BLOCK), "SSL3_SETUP_KEY_BLOCK"}, {ERR_FUNC(SSL_F_SSL3_WRITE_BYTES), "SSL3_WRITE_BYTES"}, {ERR_FUNC(SSL_F_SSL3_WRITE_PENDING), "SSL3_WRITE_PENDING"}, +{ERR_FUNC(SSL_F_SSL_ADD_CLIENTHELLO_RENEGOTIATE_EXT), "SSL_ADD_CLIENTHELLO_RENEGOTIATE_EXT"}, {ERR_FUNC(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT), "SSL_ADD_CLIENTHELLO_TLSEXT"}, {ERR_FUNC(SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK), "SSL_add_dir_cert_subjects_to_stack"}, {ERR_FUNC(SSL_F_SSL_ADD_FILE_CERT_SUBJECTS_TO_STACK), "SSL_add_file_cert_subjects_to_stack"}, @@ -411,6 +414,9 @@ {ERR_REASON(SSL_R_RECORD_LENGTH_MISMATCH),"record length mismatch"}, {ERR_REASON(SSL_R_RECORD_TOO_LARGE) ,"record too large"}, {ERR_REASON(SSL_R_RECORD_TOO_SMALL) ,"record too small"}, +{ERR_REASON(SSL_R_RENEGOTIATE_EXT_TOO_LONG),"renegotiate ext too long"}, +{ERR_REASON(SSL_R_RENEGOTIATION_ENCODING_ERR),"renegotiation encoding err"}, +{ERR_REASON(SSL_R_RENEGOTIATION_MISMATCH),"renegotiation mismatch"}, {ERR_REASON(SSL_R_REQUIRED_CIPHER_MISSING),"required cipher missing"}, {ERR_REASON(SSL_R_REUSE_CERT_LENGTH_NOT_ZERO),"reuse cert length not zero"}, {ERR_REASON(SSL_R_REUSE_CERT_TYPE_NOT_ZERO),"reuse cert type not zero"}, Index: ssl/t1_lib.c =================================================================== --- ssl/t1_lib.c (revision 4) +++ ssl/t1_lib.c (working copy) @@ -169,7 +169,32 @@ 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; + } + + if (!(SSL_get_options(s) & SSL_OP_NO_TICKET)) { int ticklen; @@ -261,6 +286,30 @@ 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_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_serverhello_renegotiate_ext(s, ret, &el, el)) + { + SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); + return NULL; + } + + ret += el; + } if (s->tlsext_ticket_expected && !(SSL_get_options(s) & SSL_OP_NO_TICKET)) @@ -407,6 +456,13 @@ } } + else if (type == TLSEXT_TYPE_renegotiate) + { + if(ssl_parse_clienthello_renegotiate_ext(s, data, size, al)) + { + return 0; + } + } else if (type == TLSEXT_TYPE_status_request && s->ctx->tlsext_status_cb) { @@ -506,11 +562,12 @@ */ else s->tlsext_status_type = -1; - } + } + /* session ticket processed earlier */ data+=size; - } + } *p = data; return 1; @@ -574,10 +631,17 @@ /* 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; + } + } data+=size; - } + } + if (data != d+n) { *al = SSL_AD_DECODE_ERROR; Index: ssl/Makefile =================================================================== --- ssl/Makefile (revision 4) +++ ssl/Makefile (working copy) @@ -30,7 +30,7 @@ ssl_lib.c ssl_err2.c ssl_cert.c ssl_sess.c \ ssl_ciph.c ssl_stat.c ssl_rsa.c \ ssl_asn1.c ssl_txt.c ssl_algs.c \ - bio_ssl.c ssl_err.c kssl.c + bio_ssl.c ssl_err.c kssl.c t1_reneg.c LIBOBJ= \ s2_meth.o s2_srvr.o s2_clnt.o s2_lib.o s2_enc.o s2_pkt.o \ s3_meth.o s3_srvr.o s3_clnt.o s3_lib.o s3_enc.o s3_pkt.o s3_both.o \ @@ -41,7 +41,7 @@ ssl_lib.o ssl_err2.o ssl_cert.o ssl_sess.o \ ssl_ciph.o ssl_stat.o ssl_rsa.o \ ssl_asn1.o ssl_txt.o ssl_algs.o \ - bio_ssl.o ssl_err.o kssl.o + bio_ssl.o ssl_err.o kssl.o t1_reneg.o SRC= $(LIBSRC) Index: ssl/s3_both.c =================================================================== --- ssl/s3_both.c (revision 4) +++ ssl/s3_both.c (working copy) @@ -116,6 +116,7 @@ #include #include +#include #include #include "ssl_locl.h" #include @@ -168,6 +169,23 @@ p+=i; l=i; + /* Copy the finished so we can use it for + renegotiation checks */ + if(s->type == SSL_ST_CONNECT) + { + assert(i < EVP_MAX_MD_SIZE); + memcpy(s->s3->previous_client_finished, + s->s3->tmp.finish_md, i); + s->s3->previous_client_finished_len=i; + } + else + { + assert(i < EVP_MAX_MD_SIZE); + memcpy(s->s3->previous_server_finished, + s->s3->tmp.finish_md, i); + s->s3->previous_server_finished_len=i; + } + #ifdef OPENSSL_SYS_WIN16 /* MSVC 1.5 does not clear the top bytes of the word unless * I do this. @@ -232,6 +250,23 @@ goto f_err; } + /* Copy the finished so we can use it for + renegotiation checks */ + if(s->type == SSL_ST_ACCEPT) + { + assert(i < EVP_MAX_MD_SIZE); + memcpy(s->s3->previous_client_finished, + s->s3->tmp.peer_finish_md, i); + s->s3->previous_client_finished_len=i; + } + else + { + assert(i < EVP_MAX_MD_SIZE); + memcpy(s->s3->previous_server_finished, + s->s3->tmp.peer_finish_md, i); + s->s3->previous_server_finished_len=i; + } + return(1); f_err: ssl3_send_alert(s,SSL3_AL_FATAL,al); Index: ssl/tls1.h =================================================================== --- ssl/tls1.h (revision 4) +++ ssl/tls1.h (working copy) @@ -115,6 +115,9 @@ #define TLSEXT_TYPE_ec_point_formats 11 #define TLSEXT_TYPE_session_ticket 35 +#define TLSEXT_TYPE_renegotiate 0xff01 + + /* NameType value from RFC 3546 */ #define TLSEXT_NAMETYPE_host_name 0 /* status request value from RFC 3546 */ Index: ssl/ssl3.h =================================================================== --- ssl/ssl3.h (revision 4) +++ ssl/ssl3.h (working copy) @@ -391,6 +391,13 @@ int in_read_app_data; + /* Connection binding to prevent renegotiation attacks */ + unsigned char previous_client_finished[EVP_MAX_MD_SIZE]; + unsigned char previous_client_finished_len; + unsigned char previous_server_finished[EVP_MAX_MD_SIZE]; + unsigned char previous_server_finished_len; + int send_connection_binding; /* TODOEKR */ + struct { /* actually only needs to be 16+20 */ unsigned char cert_verify_md[EVP_MAX_MD_SIZE*2];