21

Summary

Chrome is reporting ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY when I try and connect to my local web server over HTTPS. I am almost certain this problem has to do with my recent Windows 10 upgrade, but I don't know how to fix it.

What worked

Here's the chain of events, with me having Windows 8.1 Pro installed at the start:

  1. Generated a self-signed certificate intended for use as a trusted root CA using the following command: makecert.exe -pe -ss Root -sr LocalMachine -n "CN=local, OU=development" -r -a sha512 -e 01/01/2020
  2. Generated an application-specific certificate from the trusted root CA: makecert.exe -pe -ss My -sr LocalMachine -n "CN=myapp.local, OU=Development" -is Root -ir LocalMachine -in local -sp "Microsoft RSA SChannel Cryptographic Provider" -sy 12 -a sha512 -e 01/01/2020 -sky -eku 1.3.6.1.5.5.7.3.1
  3. Added a HOSTS file entry for myapp.local that points to 127.0.0.1
  4. Created an IIS 8.5 application that is bound to the myapp.local domain and listens for HTTPS requests only
  5. Assigned the myapp.local certificate to the web site

With this setup, I had no trouble accessing my local web site from Chrome without any certificate or security warnings. The browser displayed the green padlock, as expected.

What doesn't work

Recently, I upgraded to Windows 10. I did not know at the time that Windows 10 ships with IIS 10, which supports HTTP/2. Now, when I try and access my local web sites with Chrome, I receive an ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY error. I should note that the same request sent from Edge does not result in an error and does use HTTP/2 for the connection. A cursory Google search didn't turn up anything promising, except to hint that the problem might be that HTTP/2 or Chrome is strict about what ciphers it will accept in SSL certificates.

Thinking it may be an issue with enabled cipher suites in Windows (but not being an expert in such things), I downloaded the latest version of IIS Crypto. I clicked the Best Practices button, clicked Apply, and restarted my machine.

IIS Crypto reports these settings as "best practices":

  • Enabled protocols: TLS 1.0, TLS 1.1, TLS 1.2
  • Enabled ciphers: Triple DES 168, AES 128/128, AES 256/256
  • Enabled hashes: MD5, SHA, SHA 256, SHA 384, SHA 512
  • Enabled key exchanges: Diffie-Hellman, PKCS, ECDH
  • SSL cipher suite order:

    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P521
    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384
    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256
    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P521
    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P284
    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P256
    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P521
    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P284
    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256
    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA_P521
    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA_P284
    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA_P256
    TLS_RSA_WITH_AES_256_GCM_SHA384
    TLS_RSA_WITH_AES_128_GCM_SHA256
    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_3DES_EDE_CBC_SHA

I'll also add that the browser application I'm developing does not need to be usable from Windows XP. I know there are some issues about Windows XP not supporting newer protocols.

Detailed information about the HTTPS negotiation

I decided to use Fiddler to intercept the HTTPS negotiation. Here's what Fiddler reported about the request:

Version: 3.3 (TLS/1.2)
Random: 6B 47 6D 2B BC AE 00 F1 1D 41 57 7C 46 DB 35 19 D7 EF A9 2B B1 D0 81 1D 35 0D 75 7E 4C 05 14 B0
"Time": 2/1/1993 9:53:15 AM
SessionID: 98 2F 00 00 15 E7 C5 70 12 70 CD A8 D5 C7 D4 4D ED D8 1F 42 F9 A8 2C E6 67 13 AD C0 47 C1 EA 04
Extensions: 
    server_name myapp.local
    extended_master_secret  empty
    SessionTicket   empty
    signature_algs  sha512_rsa, sha512_ecdsa, sha384_rsa, sha384_ecdsa, sha256_rsa, sha256_ecdsa, sha224_rsa, sha224_ecdsa, sha1_rsa, sha1_ecdsa
    status_request  OCSP - Implicit Responder
    NextProtocolNego    empty
    SignedCertTimestamp (RFC6962)   empty
    ALPN        http/1.1, spdy/3.1, h2-14, h2
    channel_id(GoogleDraft) empty
    ec_point_formats    uncompressed [0x0]
    elliptic_curves secp256r1 [0x17], secp384r1 [0x18]
Ciphers: 
    [C02B]  TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
    [C02F]  TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
    [009E]  TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
    [CC14]  TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
    [CC13]  TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
    [CC15]  TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256
    [C00A]  TLS1_CK_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
    [C014]  TLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA
    [0039]  TLS_DHE_RSA_WITH_AES_256_SHA
    [C009]  TLS1_CK_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
    [C013]  TLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA
    [0033]  TLS_DHE_RSA_WITH_AES_128_SHA
    [009C]  TLS_RSA_WITH_AES_128_GCM_SHA256
    [0035]  TLS_RSA_AES_256_SHA
    [002F]  TLS_RSA_AES_128_SHA
    [000A]  SSL_RSA_WITH_3DES_EDE_SHA
    [00FF]  TLS_EMPTY_RENEGOTIATION_INFO_SCSV

Compression: 
    [00]    NO_COMPRESSION

and the response:

Version: 3.3 (TLS/1.2)
SessionID:  98 2F 00 00 15 E7 C5 70 12 70 CD A8 D5 C7 D4 4D ED D8 1F 42 F9 A8 2C E6 67 13 AD C0 47 C1 EA 04
Random:     55 C6 8D BF 78 72 88 41 34 BD B4 B8 DA ED D3 C6 20 5C 46 D6 5A 81 BD 6B FC 36 23 0B 15 21 5C F6
Cipher:     TLS_RSA_WITH_AES_128_GCM_SHA256 [0x009C]
CompressionSuite:   NO_COMPRESSION [0x00]
Extensions:
        ALPN        h2
        0x0017      empty
        renegotiation_info  00
        server_name empty

What's working

Based on Håkan Lindqvist's answer, and the very detailed and apparently-thoroughly-researched answer here, I reconfigured IIS Crypto with the following settings, which eliminated the Chrome error:

  • Enabled protocols: TLS 1.0, TLS 2.0, TLS 3.0
  • Enabled ciphers: AES 128/128, AES 256/256
  • Enabled hashes: SHA, SHA 256, SHA 384, SHA 512
  • Enabled key exchanges: Diffie-Hellman, PKCS, ECDH
  • SSL cipher suite order:

    TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
    TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
    TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384_P521
    TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384_P384
    TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256_P521
    TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256_P384
    TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256_P256
    TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384_P521
    TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384_P384
    TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256_P521
    TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256_P384
    TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256_P256
    TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA_P521
    TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA_P384
    TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA_P256
    TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA_P521
    TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA_P384
    TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA_P256
    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P521
    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384
    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256
    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P521
    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P384
    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256
    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P521
    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P384
    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P256
    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA_P521
    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA_P384
    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA_P256
    TLS_RSA_WITH_AES_256_GCM_SHA384
    TLS_RSA_WITH_AES_128_GCM_SHA256
    TLS_RSA_WITH_AES_256_CBC_SHA256
    TLS_RSA_WITH_AES_128_CBC_SHA256
    TLS_RSA_WITH_AES_256_CBC_SHA
    TLS_RSA_WITH_AES_128_CBC_SHA

NathanAldenSr
  • 365
  • 1
  • 2
  • 10
  • Before anyone points out the obvious: Yes, I am aware `makecert.exe` is deprecated. I only use it for development scenarios like this because it is the easiest option that [used to?] works. – NathanAldenSr Aug 08 '15 at 22:50
  • Prehaps not the cipher but the ssl/tls version that is enabled. Have you got tls v1.0 or lower enabled? – Drifter104 Aug 08 '15 at 22:55
  • I updated the question to include what I did with IIS Crypto to control those settings. Do you know if the settings are too permissive for HTTP/2 and Chrome? – NathanAldenSr Aug 08 '15 at 23:00
  • http://stackoverflow.com/questions/31746620/iis-10-chrome-44-err-spdy-inadequate-transport-security may help. Apparently disabling spdy in browser is the way to go – Drifter104 Aug 08 '15 at 23:05
  • Thanks for the link; I missed that in my initial search. Thing is, I don't really *want* to disable HTTP/2. I'd like to use it in production for my web application, if I can. Obviously, I won't have control over my users' browser so disabling it client-side isn't an option. – NathanAldenSr Aug 08 '15 at 23:09
  • spdy is not http/2 however I don't know if you can disable spdy in chrome without also disabling. the flag to lauch chrome without spdy is --use-spdy=off you can then use the http2 indicator extension in chrome to test if turning one off turns the other off. This is an application issue. I don't think you'll be able to support both until chrome is patched to switch to http/2 if it is present – Drifter104 Aug 08 '15 at 23:16
  • I added a Fiddler trace that could help someone experienced with these issues diagnose the problem. Until then, it looks like my only option is to disable SPDY and HTTP/2 in IIS 10. :( – NathanAldenSr Aug 08 '15 at 23:20
  • 1
    IIS Crypto "Best Practices" in version 2.0 fixed this error for me. I tried using the suite order you specified but had no effect. Apparently it's been fixed in either Windows or IIS Crypto somewhere along the way. :) – ahwm Jun 09 '17 at 21:06
  • @ahwm Thanks! After clicking "Best Practices" in IIS Crypto and restarting my machine multiple times the error was gone. – Vin Shahrdar Aug 09 '18 at 22:06

3 Answers3

22

Http/2 requirements as per https://httpwg.org/specs/rfc7540.html#rfc.section.9.2.2 :

9.2.2 TLS 1.2 Cipher Suites

A deployment of HTTP/2 over TLS 1.2 SHOULD NOT use any of the cipher suites that are listed in the cipher suite black list (Appendix A).

Endpoints MAY choose to generate a connection error (Section 5.4.1) of type INADEQUATE_SECURITY if one of the cipher suites from the black list is negotiated. A deployment that chooses to use a black-listed cipher suite risks triggering a connection error unless the set of potential peers is known to accept that cipher suite.

Implementations MUST NOT generate this error in reaction to the negotiation of a cipher suite that is not on the black list. Consequently, when clients offer a cipher suite that is not on the black list, they have to be prepared to use that cipher suite with HTTP/2.

The black list includes the cipher suite that TLS 1.2 makes mandatory, which means that TLS 1.2 deployments could have non-intersecting sets of permitted cipher suites. To avoid this problem causing TLS handshake failures, deployments of HTTP/2 that use TLS 1.2 MUST support TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 [TLS-ECDHE] with the P-256 elliptic curve [FIPS186].

Note that clients might advertise support of cipher suites that are on the black list in order to allow for connection to servers that do not support HTTP/2. This allows servers to select HTTP/1.1 with a cipher suite that is on the HTTP/2 black list. However, this can result in HTTP/2 being negotiated with a black-listed cipher suite if the application protocol and cipher suite are independently selected.


Your negotiated cipher `TLS_RSA_WITH_AES_128_GCM_SHA256` is in the above mentioned (and linked) Http/2 blacklist.

I believe you will want to adjust your cipher suites (ordering?) to meet the above requirements. Maybe simply putting TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 with the NIST P-256 elliptic curve (identified as TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256_P256 on Windows) at the top of the list, or at least before anything included in the blacklist?

Andy Hames
  • 105
  • 5
Håkan Lindqvist
  • 33,741
  • 5
  • 65
  • 90
  • I will try this immediately and let you know how it turns out. Thanks for the detailed answer! :) Honestly, it seems like this cipher suite issue may make using HTTP/2 at the same time as HTTP/1.1 really tricky, if not impossible, until browsers are guaranteed to work around the inconsistencies. IPv4/IPv6, anyone? – NathanAldenSr Aug 09 '15 at 14:26
  • I compared IIS Crypto's "best practices" cipher suite list against the blacklist. What I found is that all the best-practice `TLS_RSA` cipher suites are in the blacklist. I disabled them all and rebooted. However, now I cannot establish a secure connection to my local web site with *any* browser. I just get `ERR_CONNECTION_RESET`. Could this have anything to do with the certificates themselves? – NathanAldenSr Aug 09 '15 at 14:54
  • @NathanAldenSr I don't think you need to *remove* the blacklisted ciphers (they may be useful for compatibility purposes for HTTP/1.x clients) as long as non-blacklisted ciphers have higher priority. In particular the one mentioned that all HTTP/2 deployments *MUST* support (`TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256`). – Håkan Lindqvist Aug 09 '15 at 15:04
  • 1
    Thank you for the starting point. I've updated my answer to show what worked for me. – NathanAldenSr Aug 09 '15 at 15:44
  • 1
    Note, the HTTP/2 spec says it's TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 **with** the P-256 elliptic curve [FIPS186], meaning the string: `TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256_P256` for Windows. – Bart Verkoeijen Jul 11 '16 at 10:26
  • @BartVerkoeijen Good point, I added a note about this. Thanks. – Håkan Lindqvist Jul 13 '16 at 12:15
  • i used IISCrypto to move TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256_P256 to the top of the list, rebooted and it worked. Thanks @HåkanLindqvist – Khalid Rahaman Apr 24 '19 at 19:50
3

Here's some PowerShell I created to temporarily disable HTTP/2 in IIS:

Set-ItemProperty -Path HKLM:\System\CurrentControlSet\Services\HTTP\Parameters -Name EnableHttp2Tls -Value 0 -Type DWord
Set-ItemProperty -Path HKLM:\System\CurrentControlSet\Services\HTTP\Parameters -Name EnableHttp2Cleartext -Value 0 -Type DWord

I'm making this an answer since disabling HTTP/2 seems to be the only "solution" to the problem. I won't accept it, though, since I'd really like to use HTTP/2 in IIS 10 reliably with all browsers.

NathanAldenSr
  • 365
  • 1
  • 2
  • 10
-1

Just get a certificate from a proper CA, there are free ones (StartSSL) and it doesn't take that much longer to get one.

When using a proper cert I had no problem with using IIS 10 on Windows 10 and HTTP/2 with Chrome.

Peter Hahndorf
  • 13,763
  • 3
  • 37
  • 58
  • 1
    This won't work for me, unfortunately. I have automated scripts that generate these certificates for both local and development environments, and every developer's workstation needs them. Additionally, I want the flexibility to be able to change host names without having to go back to a third-party to get new certificates. – NathanAldenSr Aug 09 '15 at 14:26
  • @NathanAldenSr - I understand. For a fully scripted process we are using a local internal CA. It would be nice to know whether the `makecert.exe` self-created certs are the problem. I never used makecert.exe, I always thought a local CA is a much cleaner solution. – Peter Hahndorf Aug 09 '15 at 14:34