Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dual cert support for BoringSSL #8014

Merged
merged 2 commits into from
Jul 20, 2021

Conversation

randall
Copy link
Contributor

@randall randall commented Jun 29, 2021

BoringSSL removed support for slotted SSL_CTXs. This is key for
supporting multiple certs for a CTX. When BoringSSL is used,
multiple CTXs will be created if more than one cert type is specified.
When a client connection does come in, ATS will interrogate the
connection and present the approriate CTX (preferring ECDSA)

@randall randall self-assigned this Jun 29, 2021
@randall randall force-pushed the dual_certs_for_boringssl branch from dda65d3 to e04219e Compare June 29, 2021 18:12
Copy link
Contributor

@bneradt bneradt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. In general the patch looks fine, I just have a few suggestions about using auto& or auto const& if it's possible in some places. It would probably be helpful to have someone more familiar with TLS than I review this as well.

@randall randall force-pushed the dual_certs_for_boringssl branch from e04219e to 0bce664 Compare June 29, 2021 21:42
@randall
Copy link
Contributor Author

randall commented Jun 29, 2021

Looks good. In general the patch looks fine, I just have a few suggestions about using auto& or auto const& if it's possible in some places. It would probably be helpful to have someone more familiar with TLS than I review this as well.

Thanks for the early feedback I think I hit all those autos (and maybe some more in that file)!

@randall randall force-pushed the dual_certs_for_boringssl branch from 5508ea8 to 101d247 Compare June 29, 2021 22:37
@randall randall force-pushed the dual_certs_for_boringssl branch from 101d247 to a5e0afa Compare June 30, 2021 21:17
@randall randall added the WIP label Jun 30, 2021
@randall randall changed the title Dual cert support for BoringSSL WIP Dual cert support for BoringSSL Jun 30, 2021
@randall randall force-pushed the dual_certs_for_boringssl branch 6 times, most recently from 6034889 to 0f4d375 Compare July 1, 2021 17:08
@randall randall added this to the 10.0.0 milestone Jul 1, 2021
@randall randall added the TLS label Jul 1, 2021
@randall randall force-pushed the dual_certs_for_boringssl branch 3 times, most recently from f1cd319 to d0ae94e Compare July 5, 2021 23:20
@randall randall changed the title WIP Dual cert support for BoringSSL Dual cert support for BoringSSL Jul 5, 2021
@randall randall removed the WIP label Jul 5, 2021
@randall randall marked this pull request as ready for review July 5, 2021 23:24
@randall randall requested a review from bryancall as a code owner July 5, 2021 23:24
@randall randall requested review from shinrich and removed request for bryancall and shinrich July 5, 2021 23:56
@randall randall force-pushed the dual_certs_for_boringssl branch from 5cd2b8e to 0bbdc32 Compare July 12, 2021 17:00
@randall randall requested review from bneradt and maskit July 12, 2021 17:00
@@ -412,12 +424,48 @@ ssl_client_hello_callback(SSL *s, int *al, void *arg)
}
#endif

#ifdef OPENSSL_IS_BORINGSSL
static ssl_select_cert_result_t
ssl_client_hello_callback(const SSL_CLIENT_HELLO *client_hello)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe you want a different name for the BORINGSSL version of this function, which is really a utility function for the callback instead of the proper callback. Took me a few minutes looking around to resolve in my head that the boring version of the function and openssl version with the same name weren't going to conflict with each other.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this function should have a different name, although it's a shame that we have two very similar functions.

The lambda expression in _set_handshake_callbacks mimics OpenSSL's behavior, and it enables reusing two other callback functions as well. In that sense I think having the same name make sense.

Having this in a #elif clause may ease the confusion.

#if TS_USE_HELLO_CB
static int
ssl_client_hello_callback(SSL *s, int *al, void *arg)
{
}
#elif defined(OPENSSL_IS_BORINGSSL)
static ssl_select_cert_result_t
ssl_client_hello_callback(const SSL_CLIENT_HELLO *client_hello)
{
}
#endif

And we may also be able to have exactly the same function signature by passing SSL_CLIENT_HELLO to arg.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doing the #elif here makes sense.

The callback return values are different types (and different values for equivalent states):

enum ssl_select_cert_result_t BORINGSSL_ENUM_INT {
  // ssl_select_cert_success indicates that the certificate selection was
  // successful.
  ssl_select_cert_success = 1,
  // ssl_select_cert_retry indicates that the operation could not be
  // immediately completed and must be reattempted at a later point.
  ssl_select_cert_retry = 0,
  // ssl_select_cert_error indicates that a fatal error occured and the
  // handshake should be terminated.
  ssl_select_cert_error = -1,
};

vs openssl:

# define SSL_CLIENT_HELLO_SUCCESS 1
# define SSL_CLIENT_HELLO_ERROR   0
# define SSL_CLIENT_HELLO_RETRY   (-1)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm fine with the current code, but I guess we could have aliases for the type and also the values.

#ifndef OPENSSL_IS_BORING
typedef int ssl_curve_id;
#else
typedef uint16_t ssl_curve_id;
#endif

@@ -430,13 +478,17 @@ ssl_cert_callback(SSL *ssl, void * /*arg*/)

// If we are in tunnel mode, don't select a cert. Pause!
if (HttpProxyPort::TRANSPORT_BLIND_TUNNEL == netvc->attributes) {
#ifdef OPENSSL_IS_BORINGSSL
return -2; // Retry
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the difference between pause and retry with boring? Guess I should go back and look more carefully at your docs.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like there is not "pause" in BoringSSL. Maybe they just use different terms.

OpenSSL

The callback can then inspect the passed ssl structure and set or clear any appropriate certificates. If the callback is successful it MUST return 1 even if no certificates have been set. A zero is returned on error which will abort the handshake with a fatal internal error alert. A negative return value will suspend the handshake and the handshake function will return immediately. SSL_get_error(3) will return SSL_ERROR_WANT_X509_LOOKUP to indicate, that the handshake was suspended. The next call to the handshake function will again lead to the call of cert_cb(). It is the job of the cert_cb() to store information about the state of the last call, if required to continue.

BoringSSL

enum ssl_select_cert_result_t BORINGSSL_ENUM_INT {
  // ssl_select_cert_success indicates that the certificate selection was
  // successful.
  ssl_select_cert_success = 1,
  // ssl_select_cert_retry indicates that the operation could not be
  // immediately completed and must be reattempted at a later point.
  ssl_select_cert_retry = 0,
  // ssl_select_cert_error indicates that a fatal error occured and the
  // handshake should be terminated.
  ssl_select_cert_error = -1,
};

@shinrich
Copy link
Member

I notice that you enabled one of the tlshook checks with this test (removed the openssl requirement). But I see that the tls_check_dual_cert* checks have no restriction to only openssl. Are they failing when built against boringssl without this PR?

@bryancall
Copy link
Contributor

@shinrich is going to take a look

@randall
Copy link
Contributor Author

randall commented Jul 13, 2021

I notice that you enabled one of the tlshook checks with this test (removed the openssl requirement). But I see that the tls_check_dual_cert* checks have no restriction to only openssl. Are they failing when built against boringssl without this PR?

Currently, a large number of tls tests fail when run under BoringSSL. I added #8014 recently which added the IsOpenSSL condition, and marked up a few tests that I knew depended on OpenSSL. I didn't add the dual cert tests because I knew I had this PR and #7298 in the wings.

And even after this PR, there are still a few tls_hooks test that still fail which I probably won't worry about since we don't depend on them. I'll document(by adding the Condition.IsOpenSSL) to them.

@randall randall force-pushed the dual_certs_for_boringssl branch from 0bbdc32 to 6ae1b70 Compare July 15, 2021 20:17
@shinrich
Copy link
Member

I made on rather nit-picky comment on a Debug message. Once the clang-format is happy, I am willing to approve.

@randall randall force-pushed the dual_certs_for_boringssl branch from 6ae1b70 to 40fdc0b Compare July 19, 2021 21:02
BoringSSL removed support for slotted SSL_CTXs. This is key for
supporting multiple certs for a CTX. When BoringSSL is used,
multiple CTXs will be created if more than one cert type is specified.
When a client connection does come in, ATS will interrogate the
connection and present the approriate CTX (preferring ECDSA)
@randall randall force-pushed the dual_certs_for_boringssl branch from 40fdc0b to 7de0795 Compare July 19, 2021 21:27
@shinrich shinrich dismissed bneradt’s stale review July 20, 2021 14:18

Brian's issues were resolved.

@randall randall merged commit 46422df into apache:master Jul 20, 2021
@randall randall deleted the dual_certs_for_boringssl branch July 20, 2021 15:39
@zwoop zwoop modified the milestones: 10.0.0, 9.2.0 Sep 23, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Dual cert is not available with BoringSSL valid_tls_versions_in is not available with BoringSSL
6 participants