Allow users of the |CRYPTO_BUFFER|-based methods to verify certs after the handshake.
Previously, the |CRYPTO_BUFFER|-based methods always rejected
certificate chains because none of the current callbacks is suitable to
use. In the medium-term, we want an async callback for this but, for
now, we would like to get Chromium working. Chromium already installs a
no-op callback (except for the logic that was moved into BoringSSL in
a58baaf9e68f887a9e1daf88cb25d911a376851f) and so this hack will suffice
for Chromium.
Change-Id: Ie44b7b32b9e42f503c47b072e958507754136d72
Reviewed-on: https://boringssl-review.googlesource.com/14125
Commit-Queue: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 6b39096..c938a41 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -2266,6 +2266,13 @@
SSL_CTX *ctx, int (*callback)(X509_STORE_CTX *store_ctx, void *arg),
void *arg);
+/* SSL_CTX_i_promise_to_verify_certs_after_the_handshake indicates that the
+ * caller understands that the |CRYPTO_BUFFER|-based methods currently require
+ * post-handshake verification of certificates and thus it's ok to accept any
+ * certificates during the handshake. */
+OPENSSL_EXPORT void SSL_CTX_i_promise_to_verify_certs_after_the_handshake(
+ SSL_CTX *ctx);
+
/* SSL_enable_signed_cert_timestamps causes |ssl| (which must be the client end
* of a connection) to request SCTs from the server. See
* https://tools.ietf.org/html/rfc6962.
@@ -4137,6 +4144,12 @@
/* grease_enabled is one if draft-davidben-tls-grease-01 is enabled and zero
* otherwise. */
unsigned grease_enabled:1;
+
+ /* i_promise_to_verify_certs_after_the_handshake indicates that the
+ * application is using the |CRYPTO_BUFFER|-based methods and understands
+ * that this currently requires post-handshake verification of
+ * certificates. */
+ unsigned i_promise_to_verify_certs_after_the_handshake:1;
};
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index 7ead554..856fba2 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -1598,6 +1598,10 @@
ctx->signed_cert_timestamps_enabled = 1;
}
+void SSL_CTX_i_promise_to_verify_certs_after_the_handshake(SSL_CTX *ctx) {
+ ctx->i_promise_to_verify_certs_after_the_handshake = 1;
+}
+
void SSL_enable_signed_cert_timestamps(SSL *ssl) {
ssl->signed_cert_timestamps_enabled = 1;
}
diff --git a/ssl/tls_method.c b/ssl/tls_method.c
index 7313dad..6144f86 100644
--- a/ssl/tls_method.c
+++ b/ssl/tls_method.c
@@ -278,8 +278,14 @@
static void ssl_noop_x509_session_clear(SSL_SESSION *session) {}
static int ssl_noop_x509_session_verify_cert_chain(SSL_SESSION *session,
SSL *ssl) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_CERTIFICATE_VERIFY_FAILED);
- return 0;
+ if (!ssl->ctx->i_promise_to_verify_certs_after_the_handshake) {
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNKNOWN_CA);
+ OPENSSL_PUT_ERROR(SSL, SSL_R_CERTIFICATE_VERIFY_FAILED);
+ return 0;
+ }
+
+ session->verify_result = X509_V_OK;
+ return 1;
}
static void ssl_noop_x509_hs_flush_cached_ca_names(SSL_HANDSHAKE *hs) {}