Depends on SslStream API proposal: dotnet/corefx#24588
Re-opening a previously closed issue (https://github.com/dotnet/corefx/issues/15157) with a supporting use case.
For US government compliance (FIPS, CNSA, etc), the set of allowed ciphers over TLS is mandated. There does not seem to be any mechanism for .NET Core on Linux to adjust the cipher suite offered when using HttpClient and friends, and therefore .NET Core cannot currently be used in most government installations. This is a key blocker to adoption for us.
[EDIT] Add dependency on SslStream issue by @karelz
On Windows this is achievable via system-wide registry key changes: https://technet.microsoft.com/en-us/library/dn786418(v=ws.11).aspx#BKMK_SchannelTR_CipherSuites
It should be configurable per connection, just like how the protocol level now is (Http鈥婥lient鈥婬andler.鈥婼sl鈥婸rotocols). I would expect a Http鈥婥lient鈥婬andler.鈥婼sl鈥婥ipherSuites property to exist and work across all supported platforms
This is not just an issue on Linux. We want to say that our webserver only uses the following secure ciphers (say ECDHE + AES + GCM) but then sometimes we have to connect to older less secure services with Http client from these webservers. We are forced to make a "global" configuration and therefore drop to the lowest common denominator out of all the other services we call. This is not just a problem for Government but Finance, and I imagine a number of other industries.
Hello,
any news about this topic?
Are that changes included in https://github.com/dotnet/corefx/pull/24389?
It will be really helpful to change cipher suit per connection.
That PR doesn't address it at all. This will require an API review so someone will need to launch it.
Thank for quick answer.
So let to be clear - At this time API is waiting for review before any development process?
Or someone should propose API changes?
Someone needs to propose an API ....
I am happy to do it if you don't want to...
I can do it, however - I did not do this ever.
You can do it quicker or better.
NIST guidelines allow quite a number of potential cipher suites. It seems bad to only let people pick one (because then they can only connect to servers that support that particular suite), but it also seems bad to make people specify a large list.
How about something simpler: on the HttpClientHandler add a ".RequireStrongCrypto". On Windows, this would turn on the strong crypto in the SChannel layer, and that should be FIPS compliant. And as time goes by, the OS can evolve the set of strong crypto and keep our customer secure.
If we want to be bold about security, we can have this value TRUE by default. That protects our users by default (which is good) and the inconvenience that some developers need to connect to weak servers (and there will be servers that start out strong, but over time are deemed weak)
Alternatively you could do what I did in my demo .net managed tls lib. Have the ability to supply a list for those that want to and know what they're doing.
Reasoning... I have current places of employment that have a specific list of allowed protocols that aren't FIPS based ( not everyone is in the US) but then have some precanned lists ... FIPS could be one, but these should be included
https://wiki.mozilla.org/Security/Server_Side_TLS
As they are pretty well regarded in industry and include a low medium and high (effectively) setting.
Converting your comments into a full API, is the below roughly what you're looking for? Ignore all of the obvious errors, spelling mistakes and syntax issues, please :-)
class HttpClientHandler
{
public property IList
}
class SslStream
{
public property IList
}
class CipherSuites
{
// Individual named sets of values
static CipherSuite TLS_ECDHE_RSA_WITH_AES_128_CGM_SHA256 = { IndividualSettings, RsaKeyX, Aes128, Sha256 };
// Common lists of values from different sources
static List<CipherSuite> FipsCipherSuite2017 = { ... };
static list <CipherSuite> MozillaModernCipherSuite = { ... }
static list <CipherSuite> MozillaIntermediateCipherSuite = { ... }
[deprecated]
static list <CipherSuite> MozillaOldCipherSuite = { ... }
static list<CipherSuite> OSStrongCipherSuite = { ... } // uses a special indicator that will
// enable, e.g., the Windows STRONG_CRYPTO flag.
}
class CipherSuite
{
enum CipherSuiteType { OsStrong, IndividualSettings }
public ExchangeAlgorithmType { get; set; } // e.g. RsaKeyX
public CipherAlgorithmType {get; set;} // e.g. Aes128
public HashAlgorithmType { get; set; } // e.g. Sha256
// From namespace system.security.authentication
}
And then to use this the end developer does something like this:
var handler = new HttpBaseHandler ();
handler.AllowedCipherSuites = CipherSuites.FipsCipherSuite2017;
That way you can lead the dev by the nose and help them with the classic "Pit of success". As someone who often advises other teams (infact just this week) on what ciphers to enable/disable it would be great to just say, look you use websockets, all your clients have to have a modern browser to use it turn on MozillaModernCipherSuite... :)
As long as users are able to construct their own CipherSuite instances, and are not just limited to the pre-canned ones, then I think something along the lines of Peter's proposal would meet our specific needs.
Another tricky aspect will be defining the set of cross-platform (SChannel, OpenSSL, etc) cipher types (I think CipherAlgorithmType in the proposal), and again supporting custom user provided instances (for custom OpenSSL builds with new ciphers, etc)
SslStream part is being tracked in dotnet/corefx#24588
Duplicate of dotnet/corefx#24588 ... closing.
@karelz This defect is about adding protocol selection to HttpClient. https://github.com/dotnet/corefx/issues/24588 is about adding it to SSLStream, which may be a prerequisite to getting it into HttpClient, but I don't think obviates the need for this issue.
I see, it was incorrectly labeled (both area and issue type) and the title isn't super clear. Reopening.
We need official API proposal next.
The API proposal would depend very much on the final API that's used in SSLStream, so I'll hold off until that is settled.
Adding ciphersuite property to sslstream is not a pre-requisite for this issue, the underlying implementations don't use SslStream .NET class for making secure connections. Only ManagedHandler depends on that, the curlhandler and WinhttpHandlers should be configuration through libcurl and winhttpapi support. This api proposal can happen independently from sslstream proposal.
@Priya91 What I meant was that while the implementation isn't dependent on SslStream, the APIs exposed for cipher customization should be identical to what's being discussed in https://github.com/dotnet/corefx/issues/24588.
We have just merged support for changing cipher suites in SslStream: https://github.com/dotnet/corefx/issues/24588 - currently Linux with OpenSsl 1.1.1 is or OSX is required.
This is available via SocketsHttpHandler.SslOptions.CipherSuitesPolicy.
@stephentoub I think I must be missing something with that API. The following code enables 1 cipher suite, yet the result in wireshark TLS1.3 ClientHello lists 31 cipher suites (of which TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 is indeed one, but that is beside the question)
var sslOptions = new SslClientAuthenticationOptions {
CipherSuitesPolicy = new CipherSuitesPolicy(new List<TlsCipherSuite>{ TlsCipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 })
};
var socketsHttpHandler = new SocketsHttpHandler { SslOptions = sslOptions };
var httpClient = new HttpClient(socketsHttpHandler, true);
httpClient.GetAsync("https://www.google.com").Wait();
Edit: .NET Core SDK | Version: 3.0.100 | 04339c3a26
@tick-rick what OS are you running on? Can you file a separate issue on that? (please share dotnet --info output)
Most helpful comment
It should be configurable per connection, just like how the protocol level now is (
Http鈥婥lient鈥婬andler.鈥婼sl鈥婸rotocols). I would expect aHttp鈥婥lient鈥婬andler.鈥婼sl鈥婥ipherSuitesproperty to exist and work across all supported platforms