Fix compilation with no-ec and/or no-tlsext.
[openssl.git] / ssl / s3_both.c
index a6d869df59e862be10547a97afd1168b7196ea44..a537738f4298971a61304ab130921f81ab6b652a 100644 (file)
@@ -202,15 +202,40 @@ int ssl3_send_finished(SSL *s, int a, int b, const char *sender, int slen)
        return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
        }
 
+#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)
+       {
+       const char *sender;
+       int slen;
+
+       if (s->state & SSL_ST_CONNECT)
+               {
+               sender=s->method->ssl3_enc->server_finished_label;
+               slen=s->method->ssl3_enc->server_finished_label_len;
+               }
+       else
+               {
+               sender=s->method->ssl3_enc->client_finished_label;
+               slen=s->method->ssl3_enc->client_finished_label_len;
+               }
+
+       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)
        {
        int al,i,ok;
        long n;
        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
         */ 
+#endif
 
        n=s->method->ssl_get_message(s,
                a,
@@ -240,7 +265,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);
@@ -296,84 +321,14 @@ int ssl3_send_change_cipher_spec(SSL *s, int a, int b)
        return(ssl3_do_write(s,SSL3_RT_CHANGE_CIPHER_SPEC));
        }
 
-static int ssl3_add_cert_to_buf(BUF_MEM *buf, unsigned long *l, X509 *x)
+unsigned long ssl3_output_cert_chain(SSL *s, CERT_PKEY *cpk)
        {
-       int n;
        unsigned char *p;
-
-       n=i2d_X509(x,NULL);
-       if (!BUF_MEM_grow_clean(buf,(int)(n+(*l)+3)))
-               {
-               SSLerr(SSL_F_SSL3_ADD_CERT_TO_BUF,ERR_R_BUF_LIB);
-               return(-1);
-               }
-       p=(unsigned char *)&(buf->data[*l]);
-       l2n3(n,p);
-       i2d_X509(x,&p);
-       *l+=n+3;
-
-       return(0);
-       }
-
-unsigned long ssl3_output_cert_chain(SSL *s, X509 *x)
-       {
-       unsigned char *p;
-       int i;
        unsigned long l=7;
-       BUF_MEM *buf;
-       int no_chain;
+       BUF_MEM *buf = s->init_buf;
 
-       if ((s->mode & SSL_MODE_NO_AUTO_CHAIN) || s->ctx->extra_certs)
-               no_chain = 1;
-       else
-               no_chain = 0;
-
-       /* TLSv1 sends a chain with nothing in it, instead of an alert */
-       buf=s->init_buf;
-       if (!BUF_MEM_grow_clean(buf,10))
-               {
-               SSLerr(SSL_F_SSL3_OUTPUT_CERT_CHAIN,ERR_R_BUF_LIB);
-               return(0);
-               }
-       if (x != NULL)
-               {
-               if (no_chain)
-                       {
-                       if (ssl3_add_cert_to_buf(buf, &l, x))
-                               return(0);
-                       }
-               else
-                       {
-                       X509_STORE_CTX xs_ctx;
-
-                       if (!X509_STORE_CTX_init(&xs_ctx,s->ctx->cert_store,x,NULL))
-                               {
-                               SSLerr(SSL_F_SSL3_OUTPUT_CERT_CHAIN,ERR_R_X509_LIB);
-                               return(0);
-                               }
-                       X509_verify_cert(&xs_ctx);
-                       /* Don't leave errors in the queue */
-                       ERR_clear_error();
-                       for (i=0; i < sk_X509_num(xs_ctx.chain); i++)
-                               {
-                               x = sk_X509_value(xs_ctx.chain, i);
-
-                               if (ssl3_add_cert_to_buf(buf, &l, x))
-                                       {
-                                       X509_STORE_CTX_cleanup(&xs_ctx);
-                                       return 0;
-                                       }
-                               }
-                       X509_STORE_CTX_cleanup(&xs_ctx);
-                       }
-               }
-       /* Thawte special :-) */
-       for (i=0; i<sk_X509_num(s->ctx->extra_certs); i++)
-               {
-               x=sk_X509_value(s->ctx->extra_certs,i);
-               if (ssl3_add_cert_to_buf(buf, &l, x))
-                       return(0);
-               }
+       if (!ssl_add_cert_chain(s, cpk, &l))
+               return 0;
 
        l-=7;
        p=(unsigned char *)&(buf->data[4]);
@@ -514,6 +469,15 @@ 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)
                s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, s->init_buf->data, (size_t)s->init_num + 4, s, s->msg_callback_arg);
@@ -560,6 +524,18 @@ int ssl_cert_type(X509 *x, EVP_PKEY *pkey)
                {
                ret = SSL_PKEY_GOST01;
                }
+       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.
+                */
+               i = X509_certificate_type(x, pk);
+               if (i & EVP_PKS_RSA)
+                       ret = SSL_PKEY_DH_RSA;
+               else if (i & EVP_PKS_DSA)
+                       ret = SSL_PKEY_DH_DSA;
+               }
+               
 err:
        if(!pkey) EVP_PKEY_free(pk);
        return(ret);