Add fix for CVE-2013-4353
[openssl.git] / ssl / s3_both.c
index 11a9998..0a259b1 100644 (file)
@@ -150,20 +150,20 @@ int ssl3_do_write(SSL *s, int type)
 
 int ssl3_send_finished(SSL *s, int a, int b, const char *sender, int slen)
        {
-       unsigned char *p,*d;
+       unsigned char *p;
        int i;
        unsigned long l;
 
        if (s->state == a)
                {
-               d=(unsigned char *)s->init_buf->data;
-               p= &(d[4]);
+               p = ssl_handshake_start(s);
 
                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;
                l=i;
 
                 /* Copy the finished so we can use it for
@@ -189,17 +189,12 @@ int ssl3_send_finished(SSL *s, int a, int b, const char *sender, int slen)
                 */
                l&=0xffff;
 #endif
-
-               *(d++)=SSL3_MT_FINISHED;
-               l2n3(l,d);
-               s->init_num=(int)l+4;
-               s->init_off=0;
-
+               ssl_set_handshake_header(s, SSL3_MT_FINISHED, l);
                s->state=b;
                }
 
        /* SSL3_ST_SEND_xxxxxx_HELLO_B */
-       return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
+       return ssl_do_write(s);
        }
 
 #ifndef OPENSSL_NO_NEXTPROTONEG
@@ -208,7 +203,11 @@ 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;
@@ -265,7 +264,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);
@@ -324,21 +323,17 @@ int ssl3_send_change_cipher_spec(SSL *s, int a, int b)
 unsigned long ssl3_output_cert_chain(SSL *s, CERT_PKEY *cpk)
        {
        unsigned char *p;
-       unsigned long l=7;
-       BUF_MEM *buf = s->init_buf;
+       unsigned long l = 3 + SSL_HM_HEADER_LENGTH(s);
 
        if (!ssl_add_cert_chain(s, cpk, &l))
                return 0;
 
-       l-=7;
-       p=(unsigned char *)&(buf->data[4]);
-       l2n3(l,p);
-       l+=3;
-       p=(unsigned char *)&(buf->data[0]);
-       *(p++)=SSL3_MT_CERTIFICATE;
+       l -= 3 + SSL_HM_HEADER_LENGTH(s);
+       p = ssl_handshake_start(s);
        l2n3(l,p);
-       l+=4;
-       return(l);
+       l += 3;
+       ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE, l);
+       return l + SSL_HM_HEADER_LENGTH(s);
        }
 
 /* Obtain handshake message of message type 'mt' (any if mt == -1),
@@ -524,7 +519,7 @@ int ssl_cert_type(X509 *x, EVP_PKEY *pkey)
                {
                ret = SSL_PKEY_GOST01;
                }
-       else if (x && i == EVP_PKEY_DH)
+       else if (x && (i == EVP_PKEY_DH || i == EVP_PKEY_DHX))
                {
                /* For DH two cases: DH certificate signed with RSA and
                 * DH certificate signed with DSA.