aspnetcore
aspnetcore copied to clipboard
TLS 1.3 negotiation fails with FIPS-enabled Ubuntu 22.04 server and Chromium based browsers
Is there an existing issue for this?
- [X] I have searched the existing issues
Describe the bug
When Kestrel is running on a FIPS-enabled Ubuntu 22.04, TLS 1.3 negotiation fails for Chromium browsers and ERR_SSL_PROTOCOL_ERROR is displayed.
Scenarios tested:
- Different clients against Kestrel server: Firefox, curl and OpenSSL s_client all work. Chrome and Chromium Edge fail.
- Different servers against Chrome: OpenSSL s_server, nginx and Python https.server+ssl work. Kestrel fails.
Expected Behavior
Chromium based browsers should be able to establish a TLS 1.3 session with Kestrel servers running on FIPS-enabled Ubuntu 22.04.
Steps To Reproduce
- Provision VM running Ubuntu 22.04
- Obtain a free Ubuntu Pro token by registering a private account at https://ubuntu.com/pro
- Enable FIPS on the VM:
-
sudo pro attach --no-auto-enable <token> -
sudo pro enable fips-preview --assume-yes -
sudo reboot -
cat /proc/sys/crypto/fips_enabled<-- Ensure the output is1
-
- Install ssl-cert package:
-
sudo apt install ssl-cert
-
- Install Chrome on the VM:
-
wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb -
sudo dpkg -i google-chrome-stable_current_amd64.deb
-
- Install .NET 8 SDK on the VM:
-
wget https://packages.microsoft.com/config/ubuntu/22.04/packages-microsoft-prod.deb -
sudo dpkg -i packages-microsoft-prod.deb -
sudo apt update -
sudo apt install dotnet-sdk-8.0
-
- Configure a hostname and create a snakeoil certificate:
-
sudo bash -c 'echo some.host.internal > /etc/hostname -
sudo bash -c 'echo "127.0.0.1 some.host.internal" >> /etc/hosts -
sudo make-ssl-cert generate-default-snakeoil --force-overwrite
-
- Create a ASP.NET Core webapi boilerplate application
-
mkdir app -
cd app -
dotnet new webapi -au None
-
- Add the following configurations to
appsetting.Development.json-
Urls = https://127.0.0.1:4445 -
Kestrel:Certificates:Default:Path = /etc/ssl/certs/ssl-cert-snakeoil.pem -
Kestrel:Certificates:Default:KeyPath = /etc/ssl/private/ssl-cert-snakeoil.key -
Logging:LogLevel:Microsoft.AspeNetCore.HttpLogging.HttpLoggingMiddleware = Trace -
Logging:LogLevel:Microsoft.AspeNetCore.Server.Kestrel = Trace
-
- Start the application (with sudo for access to the certificates)
-
dotnet build -
sudo dotnet run --no-build
-
- Start the Chrome browser and navigate to
https://some.host.internal:4445/weatherforecast. It should display the following: - By forcing TLS 1.2 Chrome is able to connect:
- Add
Kestrel:EndpointDefaults:SslProtocols = [ "Tls12" ]toappsettings.Developmen.json - Restart the app
- Reload the page in Chrome, accept the security risk of the self-signed certificate and Chrome should display the following:
- Add
- Observe that
openssl s_serveris able to successfully negotiate TLS 1.3 with Chrome:-
sudo openssl s_server -key /etc/ssl/private/ssl-cert-snakeoil.key -cert /etc/ssl/certs/ssl-cert-snakeoil.pem -accept 4446 -www - Open https://some.host.internal:4446 in Chrome. It should display a successful TLS 1.3 connection (after accepting the self-signed certificate):
-
Exceptions (if any)
dbug: Microsoft.Extensions.Hosting.Internal.Host[1]
Hosting starting
dbug: Microsoft.AspNetCore.Server.Kestrel.Core.Internal.CertificatePathWatcher[4]
Created directory watcher for '/etc/ssl/certs'.
dbug: Microsoft.AspNetCore.Server.Kestrel.Core.Internal.CertificatePathWatcher[5]
Created file watcher for '/etc/ssl/certs/ssl-cert-snakeoil.pem'.
trce: Microsoft.AspNetCore.Server.Kestrel.Core.Internal.CertificatePathWatcher[11]
Added observer to file watcher for '/etc/ssl/certs/ssl-cert-snakeoil.pem'.
trce: Microsoft.AspNetCore.Server.Kestrel.Core.Internal.CertificatePathWatcher[13]
File '/etc/ssl/certs/ssl-cert-snakeoil.pem' now has 1 observers.
trce: Microsoft.AspNetCore.Server.Kestrel.Core.Internal.CertificatePathWatcher[14]
Directory '/etc/ssl/certs' now has watchers on 1 files.
info: Microsoft.Hosting.Lifetime[14]
Now listening on: https://127.0.0.1:4445
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
Content root path: /home/vendor/dotnettest
dbug: Microsoft.Extensions.Hosting.Internal.Host[2]
Hosting started
dbug: Microsoft.AspNetCore.Server.Kestrel.Connections[39]
Connection id "0HN1JEM94TIM8" accepted.
dbug: Microsoft.AspNetCore.Server.Kestrel.Connections[1]
Connection id "0HN1JEM94TIM8" started.
dbug: Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets[6]
Connection id "0HN1JEM94TIM8" received FIN.
dbug: Microsoft.AspNetCore.Server.Kestrel.Connections[39]
Connection id "0HN1JEM94TIM9" accepted.
dbug: Microsoft.AspNetCore.Server.Kestrel.Connections[1]
Connection id "0HN1JEM94TIM9" started.
dbug: Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets[6]
Connection id "0HN1JEM94TIM9" received FIN.
dbug: Microsoft.AspNetCore.Server.Kestrel.Connections[39]
Connection id "0HN1JEM94TIMA" accepted.
dbug: Microsoft.AspNetCore.Server.Kestrel.Connections[1]
Connection id "0HN1JEM94TIMA" started.
dbug: Microsoft.AspNetCore.Server.Kestrel.Https.Internal.HttpsConnectionMiddleware[1]
Failed to authenticate HTTPS connection.
System.Security.Authentication.AuthenticationException: Authentication failed, see inner exception.
---> Interop+OpenSsl+SslException: SSL Handshake failed with OpenSSL error - SSL_ERROR_SSL.
---> Interop+Crypto+OpenSslCryptographicException: error:0A0000EB:SSL routines::no application protocol
--- End of inner exception stack trace ---
at Interop.OpenSsl.DoSslHandshake(SafeSslHandle context, ReadOnlySpan`1 input, Byte[]& sendBuf, Int32& sendCount)
at System.Net.Security.SslStreamPal.HandshakeInternal(SafeDeleteSslContext& context, ReadOnlySpan`1 inputBuffer, Byte[]& outputBuffer, SslAuthenticationOptions sslAuthenticationOptions)
--- End of inner exception stack trace ---
at System.Net.Security.SslStream.ForceAuthenticationAsync[TIOAdapter](Boolean receiveFirst, Byte[] reAuthenticationData, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Server.Kestrel.Https.Internal.HttpsConnectionMiddleware.OnConnectionAsync(ConnectionContext context)
dbug: Microsoft.AspNetCore.Server.Kestrel.Https.Internal.HttpsConnectionMiddleware[1]
Failed to authenticate HTTPS connection.
System.Security.Authentication.AuthenticationException: Authentication failed, see inner exception.
---> Interop+OpenSsl+SslException: SSL Handshake failed with OpenSSL error - SSL_ERROR_SSL.
---> Interop+Crypto+OpenSslCryptographicException: error:0A0000EB:SSL routines::no application protocol
--- End of inner exception stack trace ---
at Interop.OpenSsl.DoSslHandshake(SafeSslHandle context, ReadOnlySpan`1 input, Byte[]& sendBuf, Int32& sendCount)
at System.Net.Security.SslStreamPal.HandshakeInternal(SafeDeleteSslContext& context, ReadOnlySpan`1 inputBuffer, Byte[]& outputBuffer, SslAuthenticationOptions sslAuthenticationOptions)
--- End of inner exception stack trace ---
at System.Net.Security.SslStream.ForceAuthenticationAsync[TIOAdapter](Boolean receiveFirst, Byte[] reAuthenticationData, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Server.Kestrel.Https.Internal.HttpsConnectionMiddleware.OnConnectionAsync(ConnectionContext context)
dbug: Microsoft.AspNetCore.Server.Kestrel.Https.Internal.HttpsConnectionMiddleware[1]
Failed to authenticate HTTPS connection.
System.Security.Authentication.AuthenticationException: Authentication failed, see inner exception.
---> Interop+OpenSsl+SslException: SSL Handshake failed with OpenSSL error - SSL_ERROR_SSL.
---> Interop+Crypto+OpenSslCryptographicException: error:0A0000EB:SSL routines::no application protocol
--- End of inner exception stack trace ---
at Interop.OpenSsl.DoSslHandshake(SafeSslHandle context, ReadOnlySpan`1 input, Byte[]& sendBuf, Int32& sendCount)
at System.Net.Security.SslStreamPal.HandshakeInternal(SafeDeleteSslContext& context, ReadOnlySpan`1 inputBuffer, Byte[]& outputBuffer, SslAuthenticationOptions sslAuthenticationOptions)
--- End of inner exception stack trace ---
at System.Net.Security.SslStream.ForceAuthenticationAsync[TIOAdapter](Boolean receiveFirst, Byte[] reAuthenticationData, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Server.Kestrel.Https.Internal.HttpsConnectionMiddleware.OnConnectionAsync(ConnectionContext context)
dbug: Microsoft.AspNetCore.Server.Kestrel.Connections[2]
Connection id "0HN1JEM94TIM8" stopped.
dbug: Microsoft.AspNetCore.Server.Kestrel.Connections[2]
Connection id "0HN1JEM94TIMA" stopped.
dbug: Microsoft.AspNetCore.Server.Kestrel.Connections[2]
Connection id "0HN1JEM94TIM9" stopped.
dbug: Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets[7]
Connection id "0HN1JEM94TIMA" sending FIN because: "The Socket transport's send loop completed gracefully."
dbug: Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets[7]
Connection id "0HN1JEM94TIM9" sending FIN because: "The Socket transport's send loop completed gracefully."
dbug: Microsoft.AspNetCore.Server.Kestrel.Connections[39]
Connection id "0HN1JEM94TIMB" accepted.
dbug: Microsoft.AspNetCore.Server.Kestrel.Connections[1]
Connection id "0HN1JEM94TIMB" started.
dbug: Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets[7]
Connection id "0HN1JEM94TIM8" sending FIN because: "The Socket transport's send loop completed gracefully."
dbug: Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets[6]
Connection id "0HN1JEM94TIMB" received FIN.
dbug: Microsoft.AspNetCore.Server.Kestrel.Https.Internal.HttpsConnectionMiddleware[1]
Failed to authenticate HTTPS connection.
System.Security.Authentication.AuthenticationException: Authentication failed, see inner exception.
---> Interop+OpenSsl+SslException: SSL Handshake failed with OpenSSL error - SSL_ERROR_SSL.
---> Interop+Crypto+OpenSslCryptographicException: error:0A0000EB:SSL routines::no application protocol
--- End of inner exception stack trace ---
at Interop.OpenSsl.DoSslHandshake(SafeSslHandle context, ReadOnlySpan`1 input, Byte[]& sendBuf, Int32& sendCount)
at System.Net.Security.SslStreamPal.HandshakeInternal(SafeDeleteSslContext& context, ReadOnlySpan`1 inputBuffer, Byte[]& outputBuffer, SslAuthenticationOptions sslAuthenticationOptions)
--- End of inner exception stack trace ---
at System.Net.Security.SslStream.ForceAuthenticationAsync[TIOAdapter](Boolean receiveFirst, Byte[] reAuthenticationData, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Server.Kestrel.Https.Internal.HttpsConnectionMiddleware.OnConnectionAsync(ConnectionContext context)
dbug: Microsoft.AspNetCore.Server.Kestrel.Connections[2]
Connection id "0HN1JEM94TIMB" stopped.
dbug: Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets[7]
Connection id "0HN1JEM94TIMB" sending FIN because: "The Socket transport's send loop completed gracefully."
.NET Version
8.0.200
Anything else?
Output of dotnet --info:
.NET SDK:
Version: 8.0.200
Commit: 438cab6a9d
Workload version: 8.0.200-manifests.cdf2cc8e
Runtime Environment:
OS Name: ubuntu
OS Version: 22.04
OS Platform: Linux
RID: linux-x64
Base Path: /usr/share/dotnet/sdk/8.0.200/
.NET workloads installed:
There are no installed workloads to display.
Host:
Version: 8.0.2
Architecture: x64
Commit: 1381d5ebd2
.NET SDKs installed:
8.0.200 [/usr/share/dotnet/sdk]
.NET runtimes installed:
Microsoft.AspNetCore.App 8.0.2 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.NETCore.App 8.0.2 [/usr/share/dotnet/shared/Microsoft.NETCore.App]
Other architectures found:
None
Environment variables:
Not set
global.json file:
Not found
Learn more:
https://aka.ms/dotnet/info
Download .NET:
https://aka.ms/dotnet/download
On request I can provide Wireshark captures via email.