Fix for TLS record tampering bug CVE-2013-4353
[openssl.git] / ssl / s3_both.c
index b63460a56ddd3edd56d55d5d1237baf27768e4a9..53b9390fdd3af30d0576825d0b0e19bc5d290ac6 100644 (file)
@@ -161,6 +161,8 @@ int ssl3_send_finished(SSL *s, int a, int b, const char *sender, int slen)
 
                i=s->method->ssl3_enc->final_finish_mac(s,
                        sender,slen,s->s3->tmp.finish_md);
+               if (i == 0)
+                       return 0;
                s->s3->tmp.finish_md_len = i;
                memcpy(p, s->s3->tmp.finish_md, i);
                p+=i;
@@ -204,10 +206,15 @@ int ssl3_send_finished(SSL *s, int a, int b, const char *sender, int slen)
 
 #ifndef OPENSSL_NO_NEXTPROTONEG
 /* ssl3_take_mac calculates the Finished MAC for the handshakes messages seen to far. */
-static void ssl3_take_mac(SSL *s) {
+static void ssl3_take_mac(SSL *s)
+       {
        const char *sender;
        int slen;
-
+       /* If no new cipher setup return immediately: other functions will
+        * set the appropriate error.
+        */
+       if (s->s3->tmp.new_cipher == NULL)
+               return;
        if (s->state & SSL_ST_CONNECT)
                {
                sender=s->method->ssl3_enc->server_finished_label;
@@ -221,7 +228,7 @@ static void ssl3_take_mac(SSL *s) {
 
        s->s3->tmp.peer_finish_md_len = s->method->ssl3_enc->final_finish_mac(s,
                sender,slen,s->s3->tmp.peer_finish_md);
-}
+       }
 #endif
 
 int ssl3_get_finished(SSL *s, int a, int b)
@@ -231,8 +238,9 @@ int ssl3_get_finished(SSL *s, int a, int b)
        unsigned char *p;
 
 #ifdef OPENSSL_NO_NEXTPROTONEG
-       /* the mac has already been generated when we received the change
-        * cipher spec message and is in s->s3->tmp.peer_finish_md. */
+       /* the mac has already been generated when we received the
+        * change cipher spec message and is in s->s3->tmp.peer_finish_md.
+        */ 
 #endif
 
        n=s->method->ssl_get_message(s,
@@ -263,7 +271,7 @@ int ssl3_get_finished(SSL *s, int a, int b)
                goto f_err;
                }
 
-       if (memcmp(p, s->s3->tmp.peer_finish_md, i) != 0)
+       if (CRYPTO_memcmp(p, s->s3->tmp.peer_finish_md, i) != 0)
                {
                al=SSL_AD_DECRYPT_ERROR;
                SSLerr(SSL_F_SSL3_GET_FINISHED,SSL_R_DIGEST_CHECK_FAILED);
@@ -537,12 +545,14 @@ long ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok)
                s->init_num += i;
                n -= i;
                }
+
 #ifndef OPENSSL_NO_NEXTPROTONEG
        /* If receiving Finished, record MAC of prior handshake messages for
         * Finished verification. */
        if (*s->init_buf->data == SSL3_MT_FINISHED)
                ssl3_take_mac(s);
 #endif
+
        /* Feed this message into MAC computation. */
        ssl3_finish_mac(s, (unsigned char *)s->init_buf->data, s->init_num + 4);
        if (s->msg_callback)