Set up Netty-with TLS handsake with ECC and RSA client certificate auth - ssl

I am working on a remote server that uses Netty to perform client authentication with a TLS handshake through the Netty SSLHandler library. This S/O question gives a bit: Set up Netty with 2-way SSL Handsake (client and server certificate)
Now, the question I have about this system is that the Server requires a TrustManager to initialize a SSLContext. From what I observe this uses the SunJSSE provider. Now after setting up this implementation, I got it working with RSA client certs. Now, I am having trouble using ECC client certs as SunJSSE cannot recognize them (I think Java SE 7 include SunEC as a provider. But SunEC is a SunJCE implementation and not a SunJSSE one and thus cannot be used as a provider for TrustManager). So, how do I proceed. I heard Bouncy Castle can recognize these certs, but I still cannot instantiate a TrustManager with BC as the provider.
Edit: Also if there is no way to use TrustManagers, should I do the entire handshake only use BouncyCastle's API's and not netty's libraries? That seems off though.
This is my other S/O question that shows the stack trace: Client ECC SSL Certificate contains "unknown named curve"

Related

Delayed certificate in TLS 1.3

In ASP.NET Core there are 4 available certificate modes:
// Summary:
// A client certificate is not required and will not be requested from clients.
NoCertificate,
// Summary:
// A client certificate will be requested; however, authentication will not fail
// if a certificate is not provided by the client.
AllowCertificate,
// Summary:
// A client certificate will be requested, and the client must provide a valid certificate
// for authentication to succeed.
RequireCertificate,
// Summary:
// A client certificate is not required and will not be requested from clients at
// the start of the connection. It may be requested by the application later.
DelayCertificate
I want to use DelayCertificate mode because this shouldn't ask for certificate to user in e.g. web explorer, but still I can require certificate on some endpoints. But I have one consideration: It seems to me that I once read that delayed certificates aren't supported in TLS 1.3. I'm not sure about it, and I can't find the source where I read this. So what's it like with this mode? Will it work with TLS 1.3?
... I once read that delayed certificates aren't supported in TLS 1.3
In TLS 1.2 and lower renegotiation was used to ask for client certificates after the initial TLS handshake was already done. This mechanism does not exist in TLS 1.3 anymore, which means it also cannot be used for delayed client certificates anymore in TLS 1.3.
But, TLS 1.3 introduced a different mechanism for this purpose: Post-Handshake Client Authentication. Thus, delayed client certificates can still work with TLS 1.3, only differently. But it requires that the client supports it and not all might do.
Additionally TLS 1.3 post-handshake client authentication is explicitly forbidden in HTTP/2 - see RFC 8740. But similar to this delaying client certificates in response to access to a protected resource weren't allowed with TLS 1.2 in HTTP/2 either: RFC 7540 explicitly forbids renegotiation after the actual HTTP/2 protocol (inside the TLS) has been started.

Is there any method in netty ssl client to know if server requested client certificate after completion of SSL Handshake process

I have a Netty HTTPS(SSL ENABLED) Client which communicates with both Mutual Authentication enabled servers and Mutual Authentication non-enabled servers.
Following is the code I use to Setup SSL Handler for Client.
TrustManagerFactory tmf= ...// Necessary Trust certs
KeyManagerFactory kmf = ...// Necessary Client certs
SslContext sslContext = SslContextBuilder.forClient().keyManager(kmf).trustManager(tmf).build();
SslHandler sslHandler = sslContex.newHandler(ByteBuffAllocator);
I use the above sslHandler in the pipeline. I know that providing keyManager(kmf) will provide client certificate to server if server requests. Everything works as expected.
MY NEED : I need to know if the Server requested Client certificate or not(ie. Mutual Auth enabled server or not) in SSL Handshake process. I need to know this after completion of Handshake process.
You could provide your own KeyManager implementation (that later calls the actual KeyManager). If getPrivateKey() is called you know that the server has requested the client certificate.

SSL and JKS to TLS 1.2 client side

I am running an old version of jetty that allows SSL TLS v1.0 and v1.1. I want to disable anything other than TLS 1.2 as there are security vulnerabilities with the other implementations.
Currently clients connect to the jetty server using SSL, without any jks file for java clients or any certs or pk12 equivalent for c#/.net clients.
My understanding of jks is that the client and server needs it, which isn't a vulnerability in itself as the alias and servers should not be available in the jks file.
So my question is when I enforce stricter security protocol TLS 1.2 do i need to provide the clients with jks/pk12 or whatever the windows equivalent is? If i dont change the code to allow trustAll etc?
Client(is a request running within jetty server 9.4) server and request code:
System.setProperty("javax.net.ssl.trustStore", "filename");
System.setProperty("java.net.ssl.trustStorePassword", "xyx")
ServletContextHandler context =
ServletContextHandler(ServletContextHandler.SESSIONS);
...
server.setPort(8080);
server.start();
//Then call is via apache server code
CLoseableHttpClient httpClient = HttpClients.createMinimal();
HttpGet httpGet = new HttpGet("https://server:8080/getLogisticsData");
...
httpClient.execute(httpGet), response -> {
//format response
}));

SHA256 Server Certificate forcing ECDHE ciphers

I am experiencing a strange issue with assigning a new SHA256 certificate to an IIS web server.
The server has SSL 3.0, TLS 1.0, 1.1 and 1.2 enabled and when using a server certificate on a site signed with RSA (rather than SHA256RSA) the client connects and negotiates TLS_RSA_WITH_AES_256_CBC_SHA for the TLS encryption.
The second the SHA256 certificate is used on the site it then tries to use TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA.
What is odd is that when checking using www.ssllabs.com server test I can see that completely different ciphers are presented from the server when the SHA256 certificate is used or is not.
Ciphers Suites presented when site using SHA1 certificate.
TLS_RSA_WITH_AES_256_CBC_SHA256
TLS_RSA_WITH_AES_256_CBC_SHA
TLS_RSA_WITH_AES_128_CBC_SHA256
TLS_RSA_WITH_AES_128_CBC_SHA
TLS_RSA_WITH_RC4_128_SHA
TLS_RSA_WITH_3DES_EDE_CBC_SHA
TLS_ECHDE_RSA_WITH_AES_128_CBC_SHA256
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
TLS_RSA_WTH_RC4_128_MD5
Ciphers Suites presented when site using SHA256 certificate.
TLS_ECHDE_RSA_WITH_AES_128_CBC_SHA256
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
I can find no information to show why this happens but I was aware TLS_RSA_WITH_AES ciphers were TLS 1.2 compatible and there seems to be no literature to state if the server certificate is SHA256 that it enforces Elliptical Curve Diffie-Hellman Exchange for the key encryption.
Can anyone explain why this might be happening?
Kind Regards
James Tighe
I have now managed to resolve this issue in case anyone else is getting it.
It seems that it is to do with the Cryptography/Key Store Provider used to request the CSR.
If the CSR is generated on the Windows Server 2008 R2 machine using a Crypto API providers (such as Microsoft Strong Cryptographic Provider) and the KeySpec is not specifically mentioned when generated the CSR it sets the KeySpec = 2 AT_SIGNATURE. The KeySpec determines whether the key can be used for Signatures, Key Exchange (encryption) or both.
When setting the Cryptography provider to a Crypto API provider seems to cause the Windows Server 2008 R2 machine to complete the request but default to KeySpec = 2 In our case it was because we had generated a .INF file to be used with CERTREQ as IIS was not able to enforce the use of SHA256 as the signing algorithm.
If the KeySpec is set in the .INF file to KeySpec = 1 AT_KEYEXCHANGE then this should work although we resolved this issue a different way.
In order to resolve the issue we changed the .INF file to set the ProviderName = "Microsoft Software Key Storage Provider" (a CNG provider). When the certificate was completed it showed the KeySpec = 0 AT_NONE which is when the key store provider is set to CNG.
This issue was raised to Microsoft to help us get a better understanding and it appears that we were right in the KeySpec behaviour and the usage of the Cryptography Provider.
They confirmed that in the .INF file (or the customer template enrolment in Cert MMC) you need to ensure the KeySpec property is set to 1 AT_KEYEXCHANGE or else it will default to 2 AT_SIGNATURE. If you use a CNG provider it will instead default to use 0 AT_NONE and will work correctly.
I hope this can help other people that might be getting this annoying issue as it was quite hard to find a solution.
Kind Regards
James Tighe

403.7 IIS 7.5 SSL client certificate authentication issue

I am testing a web service with an external partner using 2 way SSL under IIS 7.5. I am requiring SSL, requiring a client cert, and using one to one mapping to authenticate to a domain account. I have configured everything and it works fine on our network (I am able to provide a client cert, get authenticated and invoke the service from browser and test harness).
From outside of our network (in most cases, see below), I am getting a 403.7 error. I have gone through the machine level certificate store and made sure the certificates and CAs are trusted.
Here's the weird thing. I obtained a Type I cert to test from home (and got 403.7 like our intended partner is). So I setup Fiddler to debug SSL and send my certificate, and this works for some reason. I setup a test harness to pass the exact same certificate, and got 403.7. I test in my browser (IE 9), don't get a prompt for a client cert, and get 403.7.
Any help appreciated.
Bill
Last time I checked, IIS was using re-negotiation (by default) to get the client certificate: there is a first handshake where the server doesn't request a client certificate, followed by another handshake (encrypted this time) where the server requests the certificate (via a TLS CertificateRequest message). This will prevent you from seeing anything from Wireshark, unless you configure it to use the server's private key and decipher the traffic (note that this only works with some cipher suites).
One way to see the client-certificate negotiation is to configure IIS to use initial client certificate negotiation, using netsh and clientcertnegotiation=true (which is about initial negotiation). At least the CertificateRequest and the certificate will be sent in clear during the handshake, so you should be able to see this with Wireshark.
If the client isn't sending a certificate to the server as a response to the CertificateRequest, you'll still see an empty Certificate message from the client.
If you don't export the private key with the certificate to use with Fiddler or whichever other client, there is no chance that it will be able to use the certificate. It may at best try to send the certificate, but the handshake will fail (since the CertificateVerify message needs to be signed by the client's private key).
I guess you may encounter a problem whereby:
not presenting a certificate is accepted by the server (it's effectively optional),
presenting an invalid certificate makes it fail and causes this 403.7 status code (many servers and SSL/TLS stacks would implement this as a fatal error, but TLS specification doesn't say that unsupported_certificate, certificate_revoked, certificate_expired, certificate_unknown should be fatal, so this is at the server's discretion).
Are you using the same physical machine to test both the in-network and external-network connections? If not, are you sure that the external-network client has the private key accessible?
I have not configured Fiddler client authentication before. Does it read the client certificate and key from the standard certificate stores? Does it read directly from a PKCS12?
One other thing that may be helpful is inspecting the TLS handshake in WireShark. Specifically, check out the Server's "Certificate Request" message, as the data here clues the client (IE9) which client certificates it should display in the prompt. Compare this for the internal and external connections.