Enabling weak SSL ciphers to overcome SSL handshake problem

Hi, @openhabbe and me are working on the CarNet binding, which integrates the VW/Audi CarNet service into openHAB (similar to WeConnect, but this is limited to VW only :-()- We already made some progress, but now struggeling with the fact that one of the ID services refuses the SSL encryption/cyphers offered by OH/the JVM resulting in a SSL handshake error.

That’s what OH/Java sends out as a proposal:

TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
TLS_DHE_DSS_WITH_AES_128_CBC_SHA256
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
TLS_DHE_DSS_WITH_AES_128_GCM_SHA256
TLS_EMPTY_RENEGOTIATION_INFO_SCSV

and this is the list the mbboauth-1d.prd.ece.vwg-connect.com accepts:

TLS_RSA_WITH_AES_256_CBC_SHA (0x35)
TLS_RSA_WITH_AES_256_CBC_SHA256 (0x3d)
TLS_RSA_WITH_AES_128_CBC_SHA (0x2f)
TLS_RSA_WITH_AES_128_CBC_SHA256 (0x3c)

= no overlap resulting in “ExecutionException javax.net.ssl.SSLException: Received fatal alert: handshake_failure” when trying to send the token request. I found [SOLVED] Failed downloading Marketplace entries: Received fatal alert: handshake_failure and copies the jars into the lib/security directory of the JVM (on 2 machines), but still no success.

Nevertheless, the fact that Java offers only AES128 whereas the servier requires AES256 is an indicator that this is exactly the problem (no strong AES due to US export policies).

We also tried to add “crypto.policy: unlimited” to /usr/lib/jvm/zulu-embedded-8-armhf/jre/lib/security/java.security, no change.

I found the info on SslContextFactory(), but from my understanding this is more to filter the proposal rather than forcing to offer stronger encryption.

Any idea?

I don’t know a solution, but the problem is not that OH doesn’t use 256 bit AES, but that the API only supports RSA key exchange which is not as secure as DH/ECDH. So really the should be the ones who change cipher suites.

That’s the hen and the egg - they are there, we want to get access, I think… we need find work around :slight_smile:

What I don’t get: Installating the unlimited policy files AND setting the “crypto.policy: unlimited” should result in an offering of all supported enc/dyphers, but it still doesn’t work.

To add to the mystery this seems to suggest that java 8 should be happy to choose TLS_RSA_WITH_AES_256_CBC_SHA (even if it is a bit weak):

https://www.ssllabs.com/ssltest/analyze.html?d=mbboauth-1d.prd.ece.vwg-connect.com

I wonder if there is a zulu specific configuration thing/bug. Have you used any other JREs?

A little further down on that thread about the marketplace there is a post from Kai. Apparently Zulu provides their own crypto extension. Maybe that would work. I don’t think the crypto.policy flag works unless you also install the extension.

You’re probably using a Jetty client which has TLS RSA ciphers excluded by default because they don’t support forward secrecy, see:

Bingo, solved it

    @Reference
    protected void setHttpClientFactory(HttpClientFactory httpClientFactory) {
        try {
            // this.httpClient = httpClientFactory.getCommonHttpClient();
            SslContextFactory ssl = new SslContextFactory();
            // ssl.setIncludeCipherSuites("^TLS_RSA_.*$");
            String[] excludedCiphersWithoutTlsRsaExclusion = Arrays.stream(ssl.getExcludeCipherSuites())
                    .filter(cipher -> !cipher.equals("^TLS_RSA_.*$")).toArray(String[]::new);
            ssl.setExcludeCipherSuites(excludedCiphersWithoutTlsRsaExclusion);
            this.httpClient = new HttpClient(ssl);
            this.httpClient.start();
        } catch (Exception e) {
            logger.warn("Unable to start HttpClient!");
        }
    }

The outcome looks good for me

+? HttpClientTransportOverHTTP@412440c1{STOPPED} - STOPPED
+? SslContextFactory@42ac309[provider=null,keyStore=null,trustStore=null] - STOPPED
|  +> trustAll=false
|  +> Protocol Selections
|  |  +> Enabled size=3
|  |  |  +> TLSv1
|  |  |  +> TLSv1.1
|  |  |  +> TLSv1.2
|  |  +> Disabled size=2
|  |     +> SSLv2Hello - ConfigExcluded:'SSLv2Hello'
|  |     +> SSLv3 - ConfigExcluded:'SSLv3' JVM:disabled
|  +> Cipher Suite Selections
|     +> Enabled size=15
|     |  +> TLS_DHE_DSS_WITH_AES_128_CBC_SHA256
|     |  +> TLS_DHE_DSS_WITH_AES_128_GCM_SHA256
|     |  +> TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
|     |  +> TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
|     |  +> TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
|     |  +> TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
|     |  +> TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
|     |  +> TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
|     |  +> TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
|     |  +> TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
|     |  +> TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
|     |  +> TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
|     |  +> TLS_EMPTY_RENEGOTIATION_INFO_SCSV
|     |  +> TLS_RSA_WITH_AES_128_CBC_SHA256
|     |  +> TLS_RSA_WITH_AES_128_GCM_SHA256
|     +> Disabled size=42
|        +> SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA - ConfigExcluded:'^.*_(MD5|SHA|SHA1)$', ConfigExcluded:'^SSL_.*$' JVM:disabled
|        +> SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA - ConfigExcluded:'^.*_(MD5|SHA|SHA1)$', ConfigExcluded:'^SSL_.*$'
|        +> SSL_DHE_DSS_WITH_DES_CBC_SHA - ConfigExcluded:'^.*_(MD5|SHA|SHA1)$', ConfigExcluded:'^SSL_.*$' JVM:disabled
|        +> SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA - ConfigExcluded:'^.*_(MD5|SHA|SHA1)$', ConfigExcluded:'^SSL_.*$' JVM:disabled
|        +> SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA - ConfigExcluded:'^.*_(MD5|SHA|SHA1)$', ConfigExcluded:'^SSL_.*$'
|        +> SSL_DHE_RSA_WITH_DES_CBC_SHA - ConfigExcluded:'^.*_(MD5|SHA|SHA1)$', ConfigExcluded:'^SSL_.*$' JVM:disabled
|        +> SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA - ConfigExcluded:'^.*_(MD5|SHA|SHA1)$', ConfigExcluded:'^SSL_.*$', ConfigExcluded:'^.*_anon_.*$' JVM:disabled
|        +> SSL_DH_anon_WITH_3DES_EDE_CBC_SHA - ConfigExcluded:'^.*_(MD5|SHA|SHA1)$', ConfigExcluded:'^SSL_.*$', ConfigExcluded:'^.*_anon_.*$' JVM:disabled
|        +> SSL_DH_anon_WITH_DES_CBC_SHA - ConfigExcluded:'^.*_(MD5|SHA|SHA1)$', ConfigExcluded:'^SSL_.*$', ConfigExcluded:'^.*_anon_.*$' JVM:disabled
|        +> SSL_RSA_EXPORT_WITH_DES40_CBC_SHA - ConfigExcluded:'^.*_(MD5|SHA|SHA1)$', ConfigExcluded:'^SSL_.*$' JVM:disabled
|        +> SSL_RSA_WITH_3DES_EDE_CBC_SHA - ConfigExcluded:'^.*_(MD5|SHA|SHA1)$', ConfigExcluded:'^SSL_.*$'
|        +> SSL_RSA_WITH_DES_CBC_SHA - ConfigExcluded:'^.*_(MD5|SHA|SHA1)$', ConfigExcluded:'^SSL_.*$' JVM:disabled
|        +> SSL_RSA_WITH_NULL_MD5 - ConfigExcluded:'^.*_(MD5|SHA|SHA1)$', ConfigExcluded:'^SSL_.*$', ConfigExcluded:'^.*_NULL_.*$' JVM:disabled
|        +> SSL_RSA_WITH_NULL_SHA - ConfigExcluded:'^.*_(MD5|SHA|SHA1)$', ConfigExcluded:'^SSL_.*$', ConfigExcluded:'^.*_NULL_.*$' JVM:disabled
|        +> TLS_DHE_DSS_WITH_AES_128_CBC_SHA - ConfigExcluded:'^.*_(MD5|SHA|SHA1)$'
|        +> TLS_DHE_RSA_WITH_AES_128_CBC_SHA - ConfigExcluded:'^.*_(MD5|SHA|SHA1)$'
|        +> TLS_DH_anon_WITH_AES_128_CBC_SHA - ConfigExcluded:'^.*_(MD5|SHA|SHA1)$', ConfigExcluded:'^.*_anon_.*$' JVM:disabled
|        +> TLS_DH_anon_WITH_AES_128_CBC_SHA256 - ConfigExcluded:'^.*_anon_.*$' JVM:disabled
|        +> TLS_DH_anon_WITH_AES_128_GCM_SHA256 - ConfigExcluded:'^.*_anon_.*$' JVM:disabled
|        +> TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA - ConfigExcluded:'^.*_(MD5|SHA|SHA1)$'
|        +> TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA - ConfigExcluded:'^.*_(MD5|SHA|SHA1)$'
|        +> TLS_ECDHE_ECDSA_WITH_NULL_SHA - ConfigExcluded:'^.*_(MD5|SHA|SHA1)$', ConfigExcluded:'^.*_NULL_.*$' JVM:disabled
|        +> TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA - ConfigExcluded:'^.*_(MD5|SHA|SHA1)$'
|        +> TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA - ConfigExcluded:'^.*_(MD5|SHA|SHA1)$'
|        +> TLS_ECDHE_RSA_WITH_NULL_SHA - ConfigExcluded:'^.*_(MD5|SHA|SHA1)$', ConfigExcluded:'^.*_NULL_.*$' JVM:disabled
|        +> TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA - ConfigExcluded:'^.*_(MD5|SHA|SHA1)$'
|        +> TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA - ConfigExcluded:'^.*_(MD5|SHA|SHA1)$'
|        +> TLS_ECDH_ECDSA_WITH_NULL_SHA - ConfigExcluded:'^.*_(MD5|SHA|SHA1)$', ConfigExcluded:'^.*_NULL_.*$' JVM:disabled
|        +> TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA - ConfigExcluded:'^.*_(MD5|SHA|SHA1)$'
|        +> TLS_ECDH_RSA_WITH_AES_128_CBC_SHA - ConfigExcluded:'^.*_(MD5|SHA|SHA1)$'
|        +> TLS_ECDH_RSA_WITH_NULL_SHA - ConfigExcluded:'^.*_(MD5|SHA|SHA1)$', ConfigExcluded:'^.*_NULL_.*$' JVM:disabled
|        +> TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA - ConfigExcluded:'^.*_(MD5|SHA|SHA1)$', ConfigExcluded:'^.*_anon_.*$' JVM:disabled
|        +> TLS_ECDH_anon_WITH_AES_128_CBC_SHA - ConfigExcluded:'^.*_(MD5|SHA|SHA1)$', ConfigExcluded:'^.*_anon_.*$' JVM:disabled
|        +> TLS_ECDH_anon_WITH_NULL_SHA - ConfigExcluded:'^.*_(MD5|SHA|SHA1)$', ConfigExcluded:'^.*_NULL_.*$', ConfigExcluded:'^.*_anon_.*$' JVM:disabled
|        +> TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5 - ConfigExcluded:'^.*_(MD5|SHA|SHA1)$' JVM:disabled
|        +> TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA - ConfigExcluded:'^.*_(MD5|SHA|SHA1)$' JVM:disabled
|        +> TLS_KRB5_WITH_3DES_EDE_CBC_MD5 - ConfigExcluded:'^.*_(MD5|SHA|SHA1)$' JVM:disabled
|        +> TLS_KRB5_WITH_3DES_EDE_CBC_SHA - ConfigExcluded:'^.*_(MD5|SHA|SHA1)$' JVM:disabled
|        +> TLS_KRB5_WITH_DES_CBC_MD5 - ConfigExcluded:'^.*_(MD5|SHA|SHA1)$' JVM:disabled
|        +> TLS_KRB5_WITH_DES_CBC_SHA - ConfigExcluded:'^.*_(MD5|SHA|SHA1)$' JVM:disabled
|        +> TLS_RSA_WITH_AES_128_CBC_SHA - ConfigExcluded:'^.*_(MD5|SHA|SHA1)$'
|        +> TLS_RSA_WITH_NULL_SHA256 - ConfigExcluded:'^.*_NULL_.*$' JVM:disabled
+- org.eclipse.jetty.client.ProtocolHandlers@4b4228cf
|  +> java.util.LinkedHashMap@0{size=0}
+- org.eclipse.jetty.client.HttpClient$ContentDecoderFactorySet@7d216ee8(size=0)
+> requestListeners size=0
key: +- bean, += managed, +~ unmanaged, +? auto, +: iterable, +] array, +@ map, +> undefined

TLS_RSA_WITH_AES_128_CBC_SHA256 is not perferct, but would do the job.

The preferred solution would be to pass the SslContextFactory to the https session creation, so I could differ on a per-host level if I need go “downgrade” the cyphers or not. The binding will talk to 3 different servers, only one has the problem, interestingly the one, which provides the token for privileged control functions. Is that possible()?

Yes you’ll probably want to create your own client and not reuse the common http client for this particular use case. I don’t know the Jetty code by heart and if it is possible to differ per host. You can also create multiple clients for that. There is of course also the possibility that they start configuring the other hosts with the same cipher suites. You might also want to send them an e-mail and tell them about being insecure by not using ciphers supporting forward secrecy and this resulting into these compatibility issues.