-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
tls: make X.509 certificate parsing and verification explicit. #10621
Conversation
BoringSSL would like to deprecate OpenSSL's X.509 certificate parsing and verification code. Although the replacements are not yet ready, we can take a step in this direction by making certificate parsing and certificate chain validation explicit. This changes Envoy to use TLS_with_buffers_method(), which removes the OpenSSL behavior of parsing certificates to an |X509| object implicitly, as well as the behavior of calling X509_verify_cert() implicitly. Instead, Envoy now does these things explicitly, as required. Usefully, operations that require parsing (such as extracting a certificate's serial number) are now distinguished from operations that do not require parsing (such as returning the SHA-256 hash of a certificate's DER encoding). This makes it easier to take the next step of using a better parser, when it is available. Signed-off-by: Matt Braithwaite <mab@google.com> Signed-off-by: Piotr Sikora <piotrsikora@google.com>
cc @SAHF |
Signed-off-by: Piotr Sikora <piotrsikora@google.com>
/azp run |
Azure Pipelines successfully started running 1 pipeline(s), but failed to run 2 pipeline(s). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good but scares me a bit. Can you add the PR template to the PR description, mark it at least Medium risk level? Would love to get @ggreenway to double check.
Can you provide more information about the changes happening in BoringSSL, so I have more context on this change? What has happened already, and what is planned for the future? |
Signed-off-by: Piotr Sikora <piotrsikora@google.com>
Signed-off-by: Piotr Sikora <piotrsikora@google.com>
Signed-off-by: Piotr Sikora <piotrsikora@google.com>
@ggreenway BoringSSL comes with X.509 parser and verifier it inherited from OpenSSL, but that codebase is not actively maintained, and Google doesn't use it anymore. This PR effectively removes X.509 parsing and verification from BoringSSL's internal processing, and moves it to Envoy, which coincidentally uses X.509 parser and verifier that's bundled with BoringSSL, but it can be replaced with others in the future. The certificate verifier that we should eventually use is hidden inside Chromium's codebase, but it's not yet a standalone project, so it's going to be a while before we can use it in Envoy. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm uncomfortable with moving core TLS stuff out of the TLS library (BoringSSL) and into Envoy. If BoringSSL is moving towards pushing this into chromium, can we work on factoring out the chromium code into a re-usable library instead of re-implementing it in Envoy?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm uncomfortable with moving core TLS stuff out of the TLS library (BoringSSL) and into Envoy. If BoringSSL is moving towards pushing this into chromium, can we work on factoring out the chromium code into a re-usable library instead of re-implementing it in Envoy?
@ggreenway We're not re-implementing certificate verification in Envoy. This PR separates TLS processing (using BoringSSL) from certificate verification (using X.509 verifier from BoringSSL), so that we could use the separate library for certificate verification when it's ready.
I've been asking about moving Chromium's certificate verifier to a standalone library for a while, but I don't have anything to share yet. It's going to be available, eventually...
Right, but in my mind I was including all the byte-level parsing. I'd like a higher-level API. Either an API that takes the raw DER and finds what it needs itself, or an accessor from BoringSSL that finds the bits we need to pass to a verifier. Anytime I see |
This pull request has been automatically marked as stale because it has not had activity in the last 7 days. It will be closed in 7 days if no further activity occurs. Please feel free to give a status update now, ping for review, or re-open when it's ready. Thank you for your contributions! |
This pull request has been automatically closed because it has not had activity in the last 14 days. Please feel free to give a status update now, ping for review, or re-open when it's ready. Thank you for your contributions! |
The functions in question are part of the aforementioned Chromium's certificate verifier, so it's unlikely that they'll be added to BoringSSL itself, since they're a part of the component that's getting extracted into a separate library. Also, as you've already noticed, those functions already exist in Envoy (in |
I don't feel strongly about which library they come from. But I do feel that byte-level parsing certificates (or the protocol) should be coming from some library, not directly in Envoy. When everything you want to be exported from chromium is exported, what will this code look like? Will it be mostly as it is in this PR, but we'll replace a call to As I see it, if BoringSSL removes it's x509 parsing/verifying code, this change will be needed whether I like it or not. I'm trying to get a sense of how much of this is "final" and how much of this is just an intermediate step.
I understand the frustration, but that is somewhat different. That function is part of the quiche API for supporting a platform. I don't think there is any alternative. |
The certificate-parsing functions would be replaced with calls to their copies in Chromium's certificate verifier (see: ExtractSubjectFromDERCert(), ExtractSPKIFromDERCert()), and Having said that, the switch to |
This pull request has been automatically marked as stale because it has not had activity in the last 7 days. It will be closed in 7 days if no further activity occurs. Please feel free to give a status update now, ping for review, or re-open when it's ready. Thank you for your contributions! |
@ggreenway @alyssawilk is there any way that we can move this forward? |
The QUIC code you reference is considered to be an untrusted path. As discussed offline, if we need them for QUICHE and Envoy though, maybe we could add them to boringssl directly, since they seem to be general utility functions for crypto handshakes? Then more crypto-savvy folks could own and maintain and we could just consume? cc @agl |
}()); | ||
} | ||
|
||
bool seekToSubject(CRYPTO_BUFFER* cert, CBS* tbs_certificate) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this (and the other similar functions) return optional? I'm assuming CBS is just a pointer and length (not a big struct).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a little bit more than that:
https://boringssl.googlesource.com/boringssl/+/74161f485b5d54fe963cbd3d081b718ec84d2e00/include/openssl/bytestring.h#39
let me know how do you want to proceed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, let's make it return an optional.
/wait |
This pull request has been automatically marked as stale because it has not had activity in the last 7 days. It will be closed in 7 days if no further activity occurs. Please feel free to give a status update now, ping for review, or re-open when it's ready. Thank you for your contributions! |
Not stale. |
…buffers Signed-off-by: Piotr Sikora <piotrsikora@google.com>
Signed-off-by: Piotr Sikora <piotrsikora@google.com>
Signed-off-by: Piotr Sikora <piotrsikora@google.com>
Signed-off-by: Piotr Sikora <piotrsikora@google.com>
Signed-off-by: Piotr Sikora <piotrsikora@google.com>
Signed-off-by: Piotr Sikora <piotrsikora@google.com>
Signed-off-by: Piotr Sikora <piotrsikora@google.com>
Signed-off-by: Piotr Sikora <piotrsikora@google.com>
/retest |
Retrying Azure Pipelines, to retry CircleCI checks, use |
}()); | ||
} | ||
|
||
bool seekToSubject(CRYPTO_BUFFER* cert, CBS* tbs_certificate) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, let's make it return an optional.
|
||
ContextImpl* impl = reinterpret_cast<ContextImpl*>(SSL_CTX_get_app_data(SSL_get_SSL_CTX(ssl))); | ||
const Network::TransportSocketOptions* transport_socket_options = | ||
static_cast<const Network::TransportSocketOptions*>(SSL_get_app_data(ssl)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this would be clearer as a reinterpret_cast
// subject Name, | ||
// subjectPublicKeyInfo SubjectPublicKeyInfo, | ||
// ... | ||
if (!CBS_get_asn1(&der, &certificate, CBS_ASN1_SEQUENCE) || |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add some test coverage for this. At least the case of of trailing junk after cert, and an invalid cert (either complete junk, or a cert that's in some way invalid (missing a required field, etc)). I want to make sure that the code is exercised a bit since the error path is reachable by client-controlled data.
This pull request has been automatically marked as stale because it has not had activity in the last 7 days. It will be closed in 7 days if no further activity occurs. Please feel free to give a status update now, ping for review, or re-open when it's ready. Thank you for your contributions! |
This pull request has been automatically closed because it has not had activity in the last 14 days. Please feel free to give a status update now, ping for review, or re-open when it's ready. Thank you for your contributions! |
BoringSSL would like to deprecate OpenSSL's X.509 certificate parsing
and verification code. Although the replacements are not yet ready,
we can take a step in this direction by making certificate parsing
and certificate chain validation explicit.
This changes Envoy to use TLS_with_buffers_method(), which removes the
OpenSSL behavior of parsing certificates to an |X509| object implicitly,
as well as the behavior of calling X509_verify_cert() implicitly.
Instead, Envoy now does these things explicitly, as required.
Usefully, operations that require parsing (such as extracting a
certificate's serial number) are now distinguished from operations
that do not require parsing (such as returning the SHA-256 hash of a
certificate's DER encoding).
This makes it easier to take the next step of using a better parser,
when it is available.
Risk Level: Medium
Testing: Existing tests
Docs Changes: N/A (not user-visible change)
Release Notes: N/A (not user-visible change)
Signed-off-by: Matt Braithwaite mab@google.com
Signed-off-by: Piotr Sikora piotrsikora@google.com