Choose matching credentials if we have ca_names Mark credentials that are a candidate for issuer matching. Match only credentials by name if they are a candidate. This allows us to have credentials in the list that will be a candidate even if they do not match a requested issuer. Change-Id: If09b8861f58a5d7d2107eb991f5db7892c23f7e7 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/71612 Commit-Queue: Bob Beck <bbe@google.com> Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/internal.h b/ssl/internal.h index dc539a9..092b298 100644 --- a/ssl/internal.h +++ b/ssl/internal.h
@@ -1974,6 +1974,11 @@ CRYPTO_EX_DATA ex_data; + // must_match_issuer is a flag indicating that this credential should be + // considered only when it matches a peer request for a particular issuer via + // a negotiation mechanism (such as the certificate_authorities extension). + bool must_match_issuer = false; + private: friend RefCounted; ~ssl_credential_st(); @@ -1989,6 +1994,10 @@ // The pointers in the result are only valid until |hs| is next mutated. bool ssl_get_credential_list(SSL_HANDSHAKE *hs, Array<SSL_CREDENTIAL *> *out); +// ssl_credential_matches_requested_issuers returns true if |cred| is a +// usable match for any requested issuers in |hs|. +bool ssl_credential_matches_requested_issuers(SSL_HANDSHAKE *hs, + const SSL_CREDENTIAL *cred); // Handshake functions.
diff --git a/ssl/ssl_credential.cc b/ssl/ssl_credential.cc index 357d8f8..5f13ea5 100644 --- a/ssl/ssl_credential.cc +++ b/ssl/ssl_credential.cc
@@ -61,6 +61,31 @@ return true; } +bool ssl_credential_matches_requested_issuers(SSL_HANDSHAKE *hs, + const SSL_CREDENTIAL *cred) { + if (cred->must_match_issuer) { + // If we have names sent by the CA extension, and this + // credential matches it, it is good. + if (hs->ca_names != nullptr) { + for (const CRYPTO_BUFFER *ca_name : hs->ca_names.get()) { + if (cred->ChainContainsIssuer(MakeConstSpan( + CRYPTO_BUFFER_data(ca_name), CRYPTO_BUFFER_len(ca_name)))) { + return true; + } + } + } + // TODO(bbe): Other forms of issuer matching go here. + + // If this cred must match a requested issuer and we + // get here, we should not use it. + return false; + } + + // This cred does not need to match a requested issuer, so + // it is good to use without a match. + return true; +} + BSSL_NAMESPACE_END using namespace bssl;
diff --git a/ssl/tls13_client.cc b/ssl/tls13_client.cc index fbe94ad..b747215 100644 --- a/ssl/tls13_client.cc +++ b/ssl/tls13_client.cc
@@ -851,7 +851,12 @@ } // All currently supported credentials require a signature. - return tls1_choose_signature_algorithm(hs, cred, out_sigalg); + if (!tls1_choose_signature_algorithm(hs, cred, out_sigalg)) { + return false; + } + // Use this credential if it either matches a requested issuer, + // or does not require issuer matching. + return ssl_credential_matches_requested_issuers(hs, cred); } static enum ssl_hs_wait_t do_send_client_certificate(SSL_HANDSHAKE *hs) {
diff --git a/ssl/tls13_server.cc b/ssl/tls13_server.cc index fcee108..d3cb492 100644 --- a/ssl/tls13_server.cc +++ b/ssl/tls13_server.cc
@@ -226,7 +226,12 @@ // All currently supported credentials require a signature. If |cred| is a // delegated credential, this also checks that the peer supports delegated // credentials and matched |dc_cert_verify_algorithm|. - return tls1_choose_signature_algorithm(hs, cred, out_sigalg); + if (!tls1_choose_signature_algorithm(hs, cred, out_sigalg)) { + return false; + } + // Use this credential if it either matches a requested issuer, + // or does not require issuer matching. + return ssl_credential_matches_requested_issuers(hs, cred); } static enum ssl_hs_wait_t do_select_parameters(SSL_HANDSHAKE *hs) {