First cut of renegotiation extension. (port to HEAD)
authorDr. Stephen Henson <steve@openssl.org>
Mon, 9 Nov 2009 19:03:34 +0000 (19:03 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Mon, 9 Nov 2009 19:03:34 +0000 (19:03 +0000)
CHANGES
ssl/Makefile
ssl/s3_both.c
ssl/ssl.h
ssl/ssl3.h
ssl/ssl_err.c
ssl/ssl_locl.h
ssl/t1_reneg.c [new file with mode: 0644]

diff --git a/CHANGES b/CHANGES
index f0e2c1dbb13233823d7984e170c9dbd7b070d6b3..46803f33d86380da81feafb1431d61465d573f4e 100644 (file)
--- a/CHANGES
+++ b/CHANGES
 
  Changes between 0.9.8l and 0.9.8m  [xx XXX xxxx]
 
+  *) Implement
+     https://svn.resiprocate.org/rep/ietf-drafts/ekr/draft-rescorla-tls-renegotiate.txt. Re-enable
+     renegotiation but require the extension as needed. Unfortunately,
+     SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION turns out to be a
+     bad idea. It has been replaced by
+     SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION which can be set with
+     SSL_CTX_set_options(). This is really not recommended unless you
+     know what you are doing.
+     [Eric Rescorla <ekr@networkresonance.com> and Ben Laurie]
+
   *) Fixes to stateless session resumption handling. Use initial_ctx when
      issuing and attempting to decrypt tickets in case it has changed during
      servername handling. Use a non-zero length session ID when attempting
index a97627c56d9d54755129519cf7531e53520725c2..2b8ee269f2b9df30af1ea31735f5dacef55a78a8 100644 (file)
@@ -30,7 +30,7 @@ LIBSRC=       \
        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 @@ LIBOBJ= \
        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 d757c4dd58e0cc1af2cc9951a64bfddcdcc05436..16d92610e95f1283a63f3bb959496ab4b662291a 100644 (file)
@@ -166,6 +166,23 @@ int ssl3_send_finished(SSL *s, int a, int b, const char *sender, int slen)
                p+=i;
                l=i;
 
+                /* Copy the finished so we can use it for
+                   renegotiation checks */
+                if(s->type == SSL_ST_CONNECT)
+                        {
+                         OPENSSL_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
+                        {
+                        OPENSSL_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.
@@ -230,6 +247,23 @@ int ssl3_get_finished(SSL *s, int a, int b)
                goto f_err;
                }
 
+        /* Copy the finished so we can use it for
+           renegotiation checks */
+        if(s->type == SSL_ST_ACCEPT)
+                {
+                OPENSSL_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
+                {
+                OPENSSL_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 8e901b913ce606651a0b1e3bacbac7f623af22b1..c4a5fc9d41babc9818ce39e5c447945bf51ce90e 100644 (file)
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -524,6 +524,7 @@ typedef struct ssl_session_st
 #define SSL_OP_SSLEAY_080_CLIENT_DH_BUG                        0x00000080L
 #define SSL_OP_TLS_D5_BUG                              0x00000100L
 #define SSL_OP_TLS_BLOCK_PADDING_BUG                   0x00000200L
+#define SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION       0x00000400L
 
 /* Disable SSL 3.0/TLS 1.0 CBC vulnerability workaround that was added
  * in OpenSSL 0.9.6d.  Usually (depending on the application protocol)
@@ -1904,9 +1905,11 @@ void ERR_load_SSL_strings(void);
 #define SSL_F_SSL3_SETUP_WRITE_BUFFER                   291
 #define SSL_F_SSL3_WRITE_BYTES                          158
 #define SSL_F_SSL3_WRITE_PENDING                        159
+#define SSL_F_SSL_ADD_CLIENTHELLO_RENEGOTIATE_EXT       298
 #define SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT                277
 #define SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK        215
 #define SSL_F_SSL_ADD_FILE_CERT_SUBJECTS_TO_STACK       216
+#define SSL_F_SSL_ADD_SERVERHELLO_RENEGOTIATE_EXT       299
 #define SSL_F_SSL_ADD_SERVERHELLO_TLSEXT                278
 #define SSL_F_SSL_BAD_METHOD                            160
 #define SSL_F_SSL_BYTES_TO_CIPHER_LIST                  161
@@ -1950,6 +1953,8 @@ void ERR_load_SSL_strings(void);
 #define SSL_F_SSL_INIT_WBIO_BUFFER                      184
 #define SSL_F_SSL_LOAD_CLIENT_CA_FILE                   185
 #define SSL_F_SSL_NEW                                   186
+#define SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT     300
+#define SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT     301
 #define SSL_F_SSL_PEEK                                  270
 #define SSL_F_SSL_PREPARE_CLIENTHELLO_TLSEXT            281
 #define SSL_F_SSL_PREPARE_SERVERHELLO_TLSEXT            282
@@ -2164,6 +2169,9 @@ void ERR_load_SSL_strings(void);
 #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                  335
+#define SSL_R_RENEGOTIATION_ENCODING_ERR                336
+#define SSL_R_RENEGOTIATION_MISMATCH                    337
 #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 a4a6ce28c300e544171c377ab3e823dc5db26b69..5f0eee6dbba6c25778cc130f77c5e92f4f53806c 100644 (file)
@@ -503,6 +503,12 @@ typedef struct ssl3_state_st
                int cert_request;
                } tmp;
 
+        /* 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 */
        } SSL3_STATE;
 
 
index f29e61692c7368fd60a32157b9c383a30f3fd913..f20c0548ab7799683eb812aaec7f389a868f9eb5 100644 (file)
@@ -177,9 +177,11 @@ static ERR_STRING_DATA SSL_str_functs[]=
 {ERR_FUNC(SSL_F_SSL3_SETUP_WRITE_BUFFER),      "SSL3_SETUP_WRITE_BUFFER"},
 {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"},
+{ERR_FUNC(SSL_F_SSL_ADD_SERVERHELLO_RENEGOTIATE_EXT),  "SSL_ADD_SERVERHELLO_RENEGOTIATE_EXT"},
 {ERR_FUNC(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT),   "SSL_ADD_SERVERHELLO_TLSEXT"},
 {ERR_FUNC(SSL_F_SSL_BAD_METHOD),       "SSL_BAD_METHOD"},
 {ERR_FUNC(SSL_F_SSL_BYTES_TO_CIPHER_LIST),     "SSL_BYTES_TO_CIPHER_LIST"},
@@ -223,6 +225,8 @@ static ERR_STRING_DATA SSL_str_functs[]=
 {ERR_FUNC(SSL_F_SSL_INIT_WBIO_BUFFER), "SSL_INIT_WBIO_BUFFER"},
 {ERR_FUNC(SSL_F_SSL_LOAD_CLIENT_CA_FILE),      "SSL_load_client_CA_file"},
 {ERR_FUNC(SSL_F_SSL_NEW),      "SSL_new"},
+{ERR_FUNC(SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT),        "SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT"},
+{ERR_FUNC(SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT),        "SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT"},
 {ERR_FUNC(SSL_F_SSL_PEEK),     "SSL_peek"},
 {ERR_FUNC(SSL_F_SSL_PREPARE_CLIENTHELLO_TLSEXT),       "SSL_PREPARE_CLIENTHELLO_TLSEXT"},
 {ERR_FUNC(SSL_F_SSL_PREPARE_SERVERHELLO_TLSEXT),       "SSL_PREPARE_SERVERHELLO_TLSEXT"},
@@ -440,6 +444,9 @@ static ERR_STRING_DATA SSL_str_reasons[]=
 {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 74fc972908bc79a67e19b1e619f61b7ca8c0cee6..8f37008c1df38501bcb628d4a51665757982ed7e 100644 (file)
@@ -1063,4 +1063,12 @@ int tls1_process_ticket(SSL *s, unsigned char *session_id, int len,
 #endif
 EVP_MD_CTX* ssl_replace_hash(EVP_MD_CTX **hash,const EVP_MD *md) ;
 void ssl_clear_hash_ctx(EVP_MD_CTX **hash);
+int ssl_add_serverhello_renegotiate_ext(SSL *s, unsigned char *p, int *len,
+                                       int maxlen);
+int ssl_parse_serverhello_renegotiate_ext(SSL *s, unsigned char *d, int len,
+                                         int *al);
+int ssl_add_clienthello_renegotiate_ext(SSL *s, unsigned char *p, int *len,
+                                       int maxlen);
+int ssl_parse_clienthello_renegotiate_ext(SSL *s, unsigned char *d, int len,
+                                         int *al);
 #endif
diff --git a/ssl/t1_reneg.c b/ssl/t1_reneg.c
new file mode 100644 (file)
index 0000000..5222094
--- /dev/null
@@ -0,0 +1,274 @@
+/* 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-2009 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 <stdio.h>
+#include <openssl/objects.h>
+#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)
+    {
+    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 0;
+            }
+            
+        /* 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 1;
+    }
+
+/* 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_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATION_ENCODING_ERR);
+        *al=SSL_AD_ILLEGAL_PARAMETER;
+        return 0;
+        }
+    ilen = *d;
+    d++;
+
+    /* Consistency check */
+    if((ilen+1) != len)
+        {
+        SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATION_ENCODING_ERR);
+        *al=SSL_AD_ILLEGAL_PARAMETER;
+        return 0;
+        }
+
+    /* Check that the extension matches */
+    if(ilen != s->s3->previous_client_finished_len)
+        {
+        SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATION_MISMATCH);
+        *al=SSL_AD_ILLEGAL_PARAMETER;
+        return 0;
+        }
+    
+    if(memcmp(d, s->s3->previous_client_finished,
+             s->s3->previous_client_finished_len))
+        {
+        SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATION_MISMATCH);
+        *al=SSL_AD_ILLEGAL_PARAMETER;
+        return 0;
+        }
+
+    s->s3->send_connection_binding=1;
+
+    return 1;
+    }
+
+/* Add the server's renegotiation binding */
+int ssl_add_serverhello_renegotiate_ext(SSL *s, unsigned char *p, int *len,
+                                       int maxlen)
+    {
+    if(p)
+        {
+        if((s->s3->previous_client_finished_len +
+            s->s3->previous_server_finished_len + 1) > maxlen)
+            {
+            SSLerr(SSL_F_SSL_ADD_SERVERHELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATE_EXT_TOO_LONG);
+            return 0;
+            }
+        
+        /* 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 1;
+    }
+
+/* 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 */
+    OPENSSL_assert(!expected_len || s->s3->previous_client_finished_len);
+    OPENSSL_assert(!expected_len || s->s3->previous_server_finished_len);
+    
+    /* Parse the length byte */
+    if(len < 1)
+        {
+        SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATION_ENCODING_ERR);
+        *al=SSL_AD_ILLEGAL_PARAMETER;
+        return 0;
+        }
+    ilen = *d;
+    d++;
+
+    /* Consistency check */
+    if(ilen+1 != len)
+        {
+        SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATION_ENCODING_ERR);
+        *al=SSL_AD_ILLEGAL_PARAMETER;
+        return 0;
+        }
+    
+    /* Check that the extension matches */
+    if(ilen != expected_len)
+        {
+        SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATION_MISMATCH);
+        *al=SSL_AD_ILLEGAL_PARAMETER;
+        return 0;
+        }
+
+    if(memcmp(d, s->s3->previous_client_finished,
+             s->s3->previous_client_finished_len))
+        {
+        SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATION_MISMATCH);
+        *al=SSL_AD_ILLEGAL_PARAMETER;
+        return 0;
+        }
+    d += s->s3->previous_client_finished_len;
+
+    if(memcmp(d, s->s3->previous_server_finished,
+             s->s3->previous_server_finished_len))
+        {
+        SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATION_MISMATCH);
+        *al=SSL_AD_ILLEGAL_PARAMETER;
+        return 0;
+        }
+
+    return 1;
+    }