Push some duplicated code into ssl_verify_cert_chain.

No sense in having it in both the 1.2 and 1.3 code.

Change-Id: Ib3854714afed24253af7f4bcee26d25e95a10211
Reviewed-on: https://boringssl-review.googlesource.com/9071
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: Adam Langley <agl@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/ssl/handshake_client.c b/ssl/handshake_client.c
index 7135a8f..850b2bc 100644
--- a/ssl/handshake_client.c
+++ b/ssl/handshake_client.c
@@ -1092,16 +1092,10 @@
 }
 
 static int ssl3_verify_server_cert(SSL *ssl) {
-  int ret = ssl_verify_cert_chain(ssl, ssl->s3->new_session->cert_chain);
-  if (ssl->verify_mode != SSL_VERIFY_NONE && ret <= 0) {
-    int al = ssl_verify_alarm_type(ssl->verify_result);
-    ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
-    OPENSSL_PUT_ERROR(SSL, SSL_R_CERTIFICATE_VERIFY_FAILED);
-    return ret;
+  if (!ssl_verify_cert_chain(ssl, ssl->s3->new_session->cert_chain)) {
+    return -1;
   }
 
-  /* Otherwise the error is non-fatal, but we keep verify_result. */
-  ERR_clear_error();
   ssl->s3->new_session->verify_result = ssl->verify_result;
   return 1;
 }
diff --git a/ssl/handshake_server.c b/ssl/handshake_server.c
index 8a28c18..c47ba67 100644
--- a/ssl/handshake_server.c
+++ b/ssl/handshake_server.c
@@ -1313,12 +1313,15 @@
     /* No client certificate so the handshake buffer may be discarded. */
     ssl3_free_handshake_buffer(ssl);
 
-    /* TLS does not mind 0 certs returned */
+    /* In SSL 3.0, sending no certificate is signaled by omitting the
+     * Certificate message. */
     if (ssl->version == SSL3_VERSION) {
       OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CERTIFICATES_RETURNED);
       ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
       goto err;
-    } else if (ssl->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) {
+    }
+
+    if (ssl->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) {
       /* Fail for TLS only if we required a certificate */
       OPENSSL_PUT_ERROR(SSL, SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
       ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
@@ -1330,10 +1333,7 @@
       ssl->s3->new_session->peer_sha256_valid = 1;
     }
 
-    if (ssl_verify_cert_chain(ssl, chain) <= 0) {
-      OPENSSL_PUT_ERROR(SSL, SSL_R_CERTIFICATE_VERIFY_FAILED);
-      ssl3_send_alert(ssl, SSL3_AL_FATAL,
-                      ssl_verify_alarm_type(ssl->verify_result));
+    if (!ssl_verify_cert_chain(ssl, chain)) {
       goto err;
     }
   }
diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c
index e81e83d..81e6365 100644
--- a/ssl/ssl_cert.c
+++ b/ssl/ssl_cert.c
@@ -319,14 +319,26 @@
     X509_STORE_CTX_set_verify_cb(&ctx, ssl->verify_callback);
   }
 
+  int verify_ret;
   if (ssl->ctx->app_verify_callback != NULL) {
-    ret = ssl->ctx->app_verify_callback(&ctx, ssl->ctx->app_verify_arg);
+    verify_ret = ssl->ctx->app_verify_callback(&ctx, ssl->ctx->app_verify_arg);
   } else {
-    ret = X509_verify_cert(&ctx);
+    verify_ret = X509_verify_cert(&ctx);
   }
 
   ssl->verify_result = ctx.error;
 
+  /* If |SSL_VERIFY_NONE|, the error is non-fatal, but we keep the result. */
+  if (verify_ret <= 0 && ssl->verify_mode != SSL_VERIFY_NONE) {
+    ssl3_send_alert(ssl, SSL3_AL_FATAL,
+                    ssl_verify_alarm_type(ssl->verify_result));
+    OPENSSL_PUT_ERROR(SSL, SSL_R_CERTIFICATE_VERIFY_FAILED);
+    goto err;
+  }
+
+  ERR_clear_error();
+  ret = 1;
+
 err:
   X509_STORE_CTX_cleanup(&ctx);
   return ret;
diff --git a/ssl/tls13_both.c b/ssl/tls13_both.c
index 83e0c3b..dddc08e 100644
--- a/ssl/tls13_both.c
+++ b/ssl/tls13_both.c
@@ -234,15 +234,9 @@
     ssl->s3->new_session->peer_sha256_valid = 1;
   }
 
-  int verify_ret = ssl_verify_cert_chain(ssl, chain);
-  /* If |SSL_VERIFY_NONE|, the error is non-fatal, but we keep the result. */
-  if (ssl->verify_mode != SSL_VERIFY_NONE && verify_ret <= 0) {
-    int al = ssl_verify_alarm_type(ssl->verify_result);
-    ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
-    OPENSSL_PUT_ERROR(SSL, SSL_R_CERTIFICATE_VERIFY_FAILED);
+  if (!ssl_verify_cert_chain(ssl, chain)) {
     goto err;
   }
-  ERR_clear_error();
 
   ssl->s3->new_session->verify_result = ssl->verify_result;