fix error discrepancy
[openssl.git] / ssl / s3_srvr.c
index 0f203ec6b16ccbcf189cecbca90dcb5192a66fca..8600d0602f2bc571fa7f5c2ba101686588e5493c 100644 (file)
@@ -516,6 +516,9 @@ int ssl3_accept(SSL *s)
                                skip=1;
                                s->s3->tmp.cert_request=0;
                                s->state=SSL3_ST_SW_SRVR_DONE_A;
+                               if (s->s3->handshake_buffer)
+                                       if (!ssl3_digest_cached_records(s))
+                                               return -1;
                                }
                        else
                                {
@@ -608,6 +611,24 @@ int ssl3_accept(SSL *s)
 #endif
                                s->init_num = 0;
                                }
+                       else if (TLS1_get_version(s) >= TLS1_2_VERSION)
+                               {
+                               s->state=SSL3_ST_SR_CERT_VRFY_A;
+                               s->init_num=0;
+                               if (!s->session->peer)
+                                       break;
+                               /* For TLS v1.2 freeze the handshake buffer
+                                * at this point and digest cached records.
+                                */
+                               if (!s->s3->handshake_buffer)
+                                       {
+                                       SSLerr(SSL_F_SSL3_ACCEPT,ERR_R_INTERNAL_ERROR);
+                                       return -1;
+                                       }
+                               s->s3->flags |= TLS1_FLAGS_KEEP_HANDSHAKE;
+                               if (!ssl3_digest_cached_records(s))
+                                       return -1;
+                               }
                        else
                                {
                                int offset=0;
@@ -1359,8 +1380,11 @@ int ssl3_get_client_hello(SSL *s)
                s->s3->tmp.new_cipher=s->session->cipher;
                }
 
-       if (!ssl3_digest_cached_records(s))
-               goto f_err;
+       if (TLS1_get_version(s) < TLS1_2_VERSION || !(s->verify_mode & SSL_VERIFY_PEER))
+               {
+               if (!ssl3_digest_cached_records(s))
+                       goto f_err;
+               }
        
        /* we now have the following setup. 
         * client_random
@@ -1869,6 +1893,7 @@ int ssl3_send_server_key_exchange(SSL *s)
                            (unsigned char *)encodedPoint, 
                            encodedlen);
                        OPENSSL_free(encodedPoint);
+                       encodedPoint = NULL;
                        p += encodedlen;
                        }
 #endif
@@ -1890,7 +1915,7 @@ int ssl3_send_server_key_exchange(SSL *s)
                         * and p points to the space at the end. */
 #ifndef OPENSSL_NO_RSA
                        if (pkey->type == EVP_PKEY_RSA
-                                       && s->version < TLS1_2_VERSION)
+                                       && TLS1_get_version(s) < TLS1_2_VERSION)
                                {
                                q=md_buf;
                                j=0;
@@ -1898,6 +1923,8 @@ int ssl3_send_server_key_exchange(SSL *s)
                                        {
                                        EVP_DigestInit_ex(&md_ctx,(num == 2)
                                                ?s->ctx->md5:s->ctx->sha1, NULL);
+                                       EVP_MD_CTX_set_flags(&md_ctx,
+                                               EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
                                        EVP_DigestUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
                                        EVP_DigestUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
                                        EVP_DigestUpdate(&md_ctx,&(d[4]),n);
@@ -1921,7 +1948,7 @@ int ssl3_send_server_key_exchange(SSL *s)
                                {
                                /* For TLS1.2 and later send signature
                                 * algorithm */
-                               if (s->version >= TLS1_2_VERSION)
+                               if (TLS1_get_version(s) >= TLS1_2_VERSION)
                                        {
                                        if (!tls12_get_sigandhash(p, pkey, md))
                                                {
@@ -1948,7 +1975,7 @@ int ssl3_send_server_key_exchange(SSL *s)
                                        }
                                s2n(i,p);
                                n+=i+2;
-                               if (s->version >= TLS1_2_VERSION)
+                               if (TLS1_get_version(s) >= TLS1_2_VERSION)
                                        n+= 2;
                                }
                        else
@@ -2004,6 +2031,14 @@ int ssl3_send_certificate_request(SSL *s)
                p+=n;
                n++;
 
+               if (TLS1_get_version(s) >= TLS1_2_VERSION)
+                       {
+                       nl = tls12_get_req_sig_algs(s, p + 2);
+                       s2n(nl, p);
+                       p += nl + 2;
+                       n += nl + 2;
+                       }
+
                off=n;
                p+=2;
                n+=2;
@@ -2858,6 +2893,9 @@ int ssl3_get_cert_verify(SSL *s)
        long n;
        int type=0,i,j;
        X509 *peer;
+       const EVP_MD *md = NULL;
+       EVP_MD_CTX mctx;
+       EVP_MD_CTX_init(&mctx);
 
        n=s->method->ssl_get_message(s,
                SSL3_ST_SR_CERT_VRFY_A,
@@ -2926,6 +2964,36 @@ int ssl3_get_cert_verify(SSL *s)
                } 
        else 
                {       
+               if (TLS1_get_version(s) >= TLS1_2_VERSION)
+                       {
+                       int sigalg = tls12_get_sigid(pkey);
+                       /* Should never happen */
+                       if (sigalg == -1)
+                               {
+                               SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,ERR_R_INTERNAL_ERROR);
+                               al=SSL_AD_INTERNAL_ERROR;
+                               goto f_err;
+                               }
+                       /* Check key type is consistent with signature */
+                       if (sigalg != (int)p[1])
+                               {
+                               SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_WRONG_SIGNATURE_TYPE);
+                               al=SSL_AD_DECODE_ERROR;
+                               goto f_err;
+                               }
+                       md = tls12_get_hash(p[0]);
+                       if (md == NULL)
+                               {
+                               SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_UNKNOWN_DIGEST);
+                               al=SSL_AD_DECODE_ERROR;
+                               goto f_err;
+                               }
+#ifdef SSL_DEBUG
+fprintf(stderr, "USING TLSv1.2 HASH %s\n", EVP_MD_name(md));
+#endif
+                       p += 2;
+                       n -= 2;
+                       }
                n2s(p,i);
                n-=2;
                if (i > n)
@@ -2943,6 +3011,37 @@ int ssl3_get_cert_verify(SSL *s)
                goto f_err;
                }
 
+       if (TLS1_get_version(s) >= TLS1_2_VERSION)
+               {
+               long hdatalen = 0;
+               void *hdata;
+               hdatalen = BIO_get_mem_data(s->s3->handshake_buffer, &hdata);
+               if (hdatalen <= 0)
+                       {
+                       SSLerr(SSL_F_SSL3_GET_CERT_VERIFY, ERR_R_INTERNAL_ERROR);
+                       al=SSL_AD_INTERNAL_ERROR;
+                       goto f_err;
+                       }
+#ifdef SSL_DEBUG
+               fprintf(stderr, "Using TLS 1.2 with client verify alg %s\n",
+                                                       EVP_MD_name(md));
+#endif
+               if (!EVP_VerifyInit_ex(&mctx, md, NULL)
+                       || !EVP_VerifyUpdate(&mctx, hdata, hdatalen))
+                       {
+                       SSLerr(SSL_F_SSL3_GET_CERT_VERIFY, ERR_R_EVP_LIB);
+                       al=SSL_AD_INTERNAL_ERROR;
+                       goto f_err;
+                       }
+
+               if (EVP_VerifyFinal(&mctx, p , i, pkey) <= 0)
+                       {
+                       al=SSL_AD_DECRYPT_ERROR;
+                       SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_BAD_SIGNATURE);
+                       goto f_err;
+                       }
+               }
+       else
 #ifndef OPENSSL_NO_RSA 
        if (pkey->type == EVP_PKEY_RSA)
                {
@@ -3033,6 +3132,13 @@ f_err:
                ssl3_send_alert(s,SSL3_AL_FATAL,al);
                }
 end:
+       if (s->s3->handshake_buffer)
+               {
+               BIO_free(s->s3->handshake_buffer);
+               s->s3->handshake_buffer = NULL;
+               s->s3->flags &= ~TLS1_FLAGS_KEEP_HANDSHAKE;
+               }
+       EVP_MD_CTX_cleanup(&mctx);
        EVP_PKEY_free(pkey);
        return(ret);
        }
@@ -3145,6 +3251,12 @@ int ssl3_get_client_certificate(SSL *s)
                        al=SSL_AD_HANDSHAKE_FAILURE;
                        goto f_err;
                        }
+               /* No client certificate so digest cached records */
+               if (s->s3->handshake_buffer && !ssl3_digest_cached_records(s))
+                       {
+                       al=SSL_AD_INTERNAL_ERROR;
+                       goto f_err;
+                       }
                }
        else
                {