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) {}