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
retire TLS1.0/1.1 ciphers from default list #40746
Conversation
Tagging subscribers to this area: @dotnet/ncl |
src/libraries/Native/Unix/System.Security.Cryptography.Native/apibridge.c
Outdated
Show resolved
Hide resolved
src/libraries/Native/Unix/System.Security.Cryptography.Native/apibridge.c
Outdated
Show resolved
Hide resolved
src/libraries/Native/Unix/System.Security.Cryptography.Native/pal_ssl.c
Outdated
Show resolved
Hide resolved
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 is only test changes right?
A few comments above but generally LGTM. I don't grok all the OpenSsl stuff, so you may want to get a review from someone who understands that better.
no. DOTNET_DEFAULT_CIPHERSTRING impacts the product. With that in place, SslStream may or may not be able to negotiate older TLS versions. (depending on openssl configuration) @bartonjs can probably explain better. |
Ok, seems like @bartonjs should review this. |
return ret; | ||
} | ||
|
||
int32_t CryptoNative_OpenSslGetProtocolSupport(SslProtocols protocol) |
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 is a lot of native code to add for a test probe, especially with needing to add creating a self-signed cert. If it's just for tests can we detect the state somehow else? Maybe move the cert generation to managed code and leave this as passing in a cert and a protocol? (Then it's easier to expand to test for the combinatorics of {RSA,DSA,ECDSA} x { TLS protocol versions })
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.
that is where I started. But the PlatfdormDetection build did not work for me the way other tests projects work and I was getting unresolved references. I can try to ping some build experts.
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.
While I'd prefer to see this as
int32_t CryptoNative_OpenSslGetProtocolSupport(SslProtocols protocol) | |
int32_t CryptoNative_OpenSslGetProtocolSupport(SslProtocols protocol, X509* cert, EVP_PKEY* key) |
and the cert generation moved to managed code (and then no longer need the X509 mutation functions), if this is what we have to do based on the calendar, it's OK for a test probe.
#39633 claimed:
There is problem with OpenSSL 1.0 as CipherSuitePolicy throws PNSP and config is not available. |
@@ -42,7 +43,7 @@ static int32_t g_config_specified_ciphersuites = 0; | |||
|
|||
static void DetectCiphersuiteConfiguration() | |||
{ | |||
// This routine will always produce g_config_specified_ciphersuites = 0 on OpenSSL 1.0.x, | |||
// This routine will always produce g_config_specified_ciphersuites = 1 on OpenSSL 1.0.x, |
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.
If a non-portable build is built against OpenSSL 1.0.x it'll still return 0 with the current code.
if (API_EXISTS(SSL_state)) | ||
{ | ||
// OpenSSL 1.0 does not support CipherSuites so there is no way for caller to override default | ||
g_config_specified_ciphersuites = 1; |
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.
If the intent is really "OpenSSL 1.0.x should use the OpenSSL default list" (assuming @blowdart said OK), this check could be much earlier and shortcut a lot of work.
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.
What is the percentage of platforms stuck on OpenSSL 1.0?
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.
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.
RHEL.7 (EOL Aug 2021), CentOS.7 (mainstream support ended, extended ends 2024), Ubuntu 16.04 (EOL April 2021).
Probably anything that hit RTM before ~Mar 2018; which might be just those three.
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.
Oh, and the Fedora/RHEL builds will already hit a special case where they have improved the built-in defaults. So we might only really be talking Ubuntu 16.04. Debian 9 (Stretch) has already received its last update, and is now only in extended support.
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.
RHEL.7 (EOL Aug 2021), CentOS.7 (mainstream support ended, extended ends 2024), Ubuntu 16.04 (EOL April 2021).
CentOS 7 is based on the RHEL 7 lifecycle. RHEL 7's EOL would be Aug 2024 (or later).
if (x509->cert_info->validity->notBefore) | ||
{ | ||
ASN1_TIME_free(x509->cert_info->validity->notBefore); | ||
} | ||
|
||
x509->cert_info->validity->notBefore = ASN1_STRING_dup(time); |
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 should be wrapped in if (x509->cert_info->validity->notBefore != time)
, both for side effect observability reasons, and to avoid X509_set1_notBefore(cert, X509_get0_notBefore(cert))
from segfaulting.
if (x509->cert_info->validity->notAfter) | ||
{ | ||
ASN1_TIME_free(x509->cert_info->validity->notAfter); | ||
} | ||
|
||
x509->cert_info->validity->notAfter = ASN1_STRING_dup(time); |
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.
Similarly should be guarded with "if time isn't the current value"
@@ -19,7 +19,7 @@ | |||
|
|||
#define CRYPTO_LOCK_X509 3 | |||
#define CRYPTO_LOCK_EVP_PKEY 10 | |||
|
|||
#define CRYPTO_LOCK_BIO 21 |
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.
#define CRYPTO_LOCK_BIO 21 | |
#define CRYPTO_LOCK_BIO 21 | |
Please leave the separation between the crypto lock IDs and the SSL_CTRL IDs.
{ | ||
// OpenSSL 1.0 does not support CipherSuites so there is no way for caller to override default | ||
g_config_specified_ciphersuites = 1; | ||
} | ||
} | ||
else | ||
{ |
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 can't put a comment far enough down, but if the intent is to just use the builtin default on OpenSSL 1.0, replace the complex #elif !defined(FEATURE_DISTRO_AGNOSTIC_SSL) && defined(SSL_SYSTEM_DEFAULT_CIPHER_LIST)
with just #else
#define X509_new X509_new_ptr | ||
#define X509_NAME_get_index_by_NID X509_NAME_get_index_by_NID_ptr |
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.
#define X509_new X509_new_ptr | |
#define X509_NAME_get_index_by_NID X509_NAME_get_index_by_NID_ptr | |
#define X509_NAME_get_index_by_NID X509_NAME_get_index_by_NID_ptr | |
#define X509_new X509_new_ptr |
#define X509_subject_name_hash X509_subject_name_hash_ptr | ||
#define X509_set_pubkey X509_set_pubkey_ptr |
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.
#define X509_subject_name_hash X509_subject_name_hash_ptr | |
#define X509_set_pubkey X509_set_pubkey_ptr | |
#define X509_set_pubkey X509_set_pubkey_ptr | |
#define X509_subject_name_hash X509_subject_name_hash_ptr |
I see this is tagged breaking change -- we don't have much preview time left for feedback to get an idea of the level of impact. Should we have a way for customers to force the old behavior, an AppContext? |
if (!IsOpenSslSupported) | ||
{ | ||
// on Windows and macOS TLS1.0/1.1 are supported. | ||
return false; |
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.
The comment doesn't make sense with the return. Perhaps this if should just be Debug.Assert(IsOpenSslSupported);
?
They can set it in OpenSSL's config. AppContext won't work because the place that needs to read it is native code. |
Some nitpicks, but LGTM once all 1.0-based executions agree on which default list to use (and Barry has OK'd/asserted the choice) |
I would say this needs to be accompanied by very clear documentation on the docs site on how to reenable them if you need to, but otherwise, have fun :) |
I don't understand your comment @blowdart. The problem is that with old (1.0) OpenSSL you cannot override the default to the proposal and current change is to level it as it was before on old OSes. With 1.1, we will strip pout TLS1.0/1.1 ciphers and proceeded with |
I mean document how, if for some ungodly reason, someone needs TLS1.1, document how they can turn it add it back. You're not stripping entirely just setting the default selection because linux & openssl can't be trusted to be sensible :), |
it seems this broke powershell ? (mentioned in PowerShell/PowerShell#13643) which reinforces that we should have a breaking change note published. |
@wfurt I wonder if both of us were silently thinking the other was going to write the documentation for this. If you haven't already started, I'll find some time today or tomorrow to do it. |
that would be great @bartonjs. It was in my TODO list but I got distracted with some other activities ;( |
@@ -1048,13 +1074,16 @@ FOR_ALL_OPENSSL_FUNCTIONS | |||
#define SSL_is_init_finished local_SSL_is_init_finished | |||
#define X509_CRL_get0_nextUpdate local_X509_CRL_get0_nextUpdate | |||
#define X509_NAME_get0_der local_X509_NAME_get0_der | |||
#define X509_new local_X509_new |
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 is a leftover and should be removed, right?
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 created a PR for this: #43039
This is follow-up on #39633 and #40303. Product change is update to DOTNET_DEFAULT_CIPHERSTRING to have it the way how @bartonjs originally wanted. As #40303 fixed most tests, this should just work now.
Bulk of this change is update to PlatformDetection.SupportsTlsXX. In the past that would be based on OS version but since this impacts wide ranges of distributions, the static mapping is difficult to maintain and it created fragility for developers as their systems may be different.
So instead of static map, This change updated detection of Tls 1.0/1.1 to actually try to do handshake using our PAL CryptoNative_SslCtxCreate(). I originally wanted to do that using Interop but that is heavily intertwined with SslStream and build and dependencies were messy so I eventually give up. Also the platform detection is used in may places and build is special so I did not want to pull inn dependency on SslStream.
Instead, I added one function to OpenSSL PAL. That has minimal code to generate certificate on the flaw and test handshake using memory BIO. I had to pull in few more functions but the outcome is self contained and the decision only depends on OpenSSL it self. I may eventually updated other parts as well but for now I'm happy it coverts the two "problematic" version.
contributes to #30767