tl;dr: TLS 1.2 between Server 2012 R2 and Chromium based browsers fails when using AD CS issued certs. Works fine on Server 2016+, and on 2012 R2 with Firefox/IE/Cygwin-curl.
We have several internal Server 2012 R2 web servers which we are trying to move off of publicly issued certificates, onto ones issued by our AD integrated CA, and eliminate less secure crypto settings, including CBC MAC. Server 2012 R2 does not support ECDHE_RSA with GCM, which means that we're trying to use an ECDH based cert. We have experienced a similar issue, however, when we allow cipher suites with CBC-MAC, such as TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 with an RSA cert issued from the same CA. Using our public wildcard cert issued by GlobalSign, we're able to connect with all browsers.
The enterprise CA, and the offline root CA are both trusted, and we've verified that this is working properly. Certificates using multiple different templates issued to 2016 and 2019 servers work without issue across all browsers. The ECDH and RSA based templates work equally well on 2016+.
ECDH certificate template crypto:
RSA certificate template crypto:
Both RSA and ECDH certificates on the 2012 R2 servers are accepted by Firefox (once it's been told to trust them both via policy, and manually setting security.enterprise_roots.enabled
), pre-Chromium Edge, IE, and Cygwin's curl
and wget
. I've confirmed we're using modern ciphers in the registry, re-setting them with IISCrypto, and verified there are compatible available ciphers being offered by the server with OpenSSL, and nmap. Likewise, I've confirmed that clients are actually able to connect using those ciphers.
Firefox shows it's connecting with TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, which according to Qualys is supported in the version of Chrome which we're using.
With the ECDH
PORT STATE SERVICE
443/tcp open https
| ciphers:
| TLSv1.1:
| ciphers:
| TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (secp256r1) - A
| TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (secp256r1) - A
| compressors:
| NULL
| cipher preference: server
| TLSv1.2:
| ciphers:
| TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (secp256r1) - A
| TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 (secp256r1) - A
| TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (secp256r1) - A
| TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (secp256r1) - A
| compressors:
| NULL
| cipher preference: server
|_ least strength: A
Each time we try to connect with Chrome a pair of event 36874/36888 are logged stating there were no supported cipher suites on the client.
A list of the cipher suites we experience the issue with when using an Enterprise CA issued cert, most of which were enabled just for testing (warnings snipped):
PORT STATE SERVICE
443/tcp open https
| ciphers:
| SSLv3:
| ciphers:
| TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C
| TLS_RSA_WITH_RC4_128_SHA (rsa 2048) - C
| TLS_RSA_WITH_RC4_128_MD5 (rsa 2048) - C
| compressors:
| NULL
| cipher preference: server
| warnings:
| TLSv1.0:
| ciphers:
| TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A
| TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A
| TLS_DHE_RSA_WITH_AES_256_CBC_SHA (dh 1024) - A
| TLS_DHE_RSA_WITH_AES_128_CBC_SHA (dh 1024) - A
| TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
| TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
| TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C
| TLS_RSA_WITH_RC4_128_SHA (rsa 2048) - C
| TLS_RSA_WITH_RC4_128_MD5 (rsa 2048) - C
| compressors:
| NULL
| cipher preference: server
| TLSv1.1:
| ciphers:
| TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A
| TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A
| TLS_DHE_RSA_WITH_AES_256_CBC_SHA (dh 1024) - A
| TLS_DHE_RSA_WITH_AES_128_CBC_SHA (dh 1024) - A
| TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
| TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
| TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C
| TLS_RSA_WITH_RC4_128_SHA (rsa 2048) - C
| TLS_RSA_WITH_RC4_128_MD5 (rsa 2048) - C
| compressors:
| NULL
| cipher preference: server
| TLSv1.2:
| ciphers:
| TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (secp256r1) - A
| TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (secp256r1) - A
| TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A
| TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A
| TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 (dh 1024) - A
| TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 (dh 1024) - A
| TLS_DHE_RSA_WITH_AES_256_CBC_SHA (dh 1024) - A
| TLS_DHE_RSA_WITH_AES_128_CBC_SHA (dh 1024) - A
| TLS_RSA_WITH_AES_256_GCM_SHA384 (rsa 2048) - A
| TLS_RSA_WITH_AES_128_GCM_SHA256 (rsa 2048) - A
| TLS_RSA_WITH_AES_256_CBC_SHA256 (rsa 2048) - A
| TLS_RSA_WITH_AES_128_CBC_SHA256 (rsa 2048) - A
| TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
| TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
| TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C
| TLS_RSA_WITH_RC4_128_SHA (rsa 2048) - C
| TLS_RSA_WITH_RC4_128_MD5 (rsa 2048) - C
| compressors:
| NULL
| cipher preference: server
|_ least strength: C
My questions are:
- Why do Chromium based browsers fail to negotiate a cipher suite when there are compatible cipher suites offered by the server?
- What do I need to set in order to allow Server 2012 R2 to use internally issued certs?
- Is there a better way to handle what I'm trying to do, aside from upgrading the application servers to 2016/2019? At this point, it seems like disabling TLS completely and putting everything behind a LB/reverse proxy may be a better idea, even if these are single-server solutions.
EDIT: I've opened a bug with Chromium and they have confirmed that the cipher suites being offered by the server should be accepted by Chrome. They are now investigating after I've provided network logging captured via CHROME://Net-Export. This may be related to an old Chrome/2012 bug. Once Google has reported back about what the issue is, I'll update this post again. However, at this point it looks as though there's nothing wrong with the configuration on our side.
Thanks for looking!
Please, make sure your certificate signing request (CSR) is not requesting a certificate that is valid for signing only, rather than signing and encryption. If the CSR ask for a certificate valid only for signing and your CA has a policy that allows for encryption even when the request was signing only, then you will likely see this problem... sometimes. Clearly a certificate requested for signature only shouldn't work at all when used for encryption, but if your CA overrides the request to allow for encryption that will create a situation where encryption will work, but only under circumstances when the client supports a couple specific protocol suites. Identifying certificates causing this problem is complicated.
Try to capture the traffic between the W2012 R2 and Chrome using wireshark. If a protocol negotiation is the issue, you'll see the connection reset by the server immediately after the client suggests a list of cipher suites. This packet from the client will have the info of "client hello" followed immediately with a TCP RST (reset) from the server. If you drill into the details of the "client hello" packet you will be able to see the suites the client is proposing.
To remediate this issue you'll need to make sure that certificate ordered is for the correct purpose (https://docs.microsoft.com/en-us/archive/blogs/pki/how-to-create-a-web-server-ssl-certificate-manually). It's critical to ensure your certificate request has the correct parameters including the certificate usage. If you are using Windows PKI with AD integrated templates, you can "hard code" this in the templates if you like.
Google has confirmed that this is an issue with the way that Chromium handles the ClientHello, how IIS handles things on 2012, and the algorithm used in our root CA's root cert signing.
IIS on 2012r2 performs a check with the ClientHello, against every cert in the chain. Chrome doesn't advertise, but does support, the root CA's SHA-512, ECDH cert. So when IIS performs the check against the entire cert chain, it sees that Chrome offers support for the ciphers from the webserver, the from our intermediate CA, but that it doesn't offer support for the (admittedly overkill), P-521 ECDH curve so IIS resets the connection. Chrome doesn't advertise support for this to handle edge cases in the mess of field mappings that is TLS1.2/1.3.
The recommendation on my bug report with Chromium was to either replace the root CA, or upgrade to 2016/2019 where this is no-longer an issue.