openssl 1.1.0d breaks Android7 TLS connects

Tributh
2017-02-14T11:01:50Z

Hi,
the actual OpenSSL version detection in dovecot is insufficient.
The implementation only checks for SSL_CTRL_SET_ECDH_AUTO.
That was effective for OpenSSL 1.0.2, but in 1.1.0 it is removed.
Thats the code part:

#ifdef SSL_CTRL_SET_ECDH_AUTO
        /* OpenSSL >= 1.0.2 automatically handles ECDH temporary key
parameter
           selection. */
        SSL_CTX_set_ecdh_auto(ssl_ctx, 1);
#else
        /* For OpenSSL < 1.0.2, ECDH temporary key parameter selection
must be
           performed manually. Attempt to select the same curve as that used
           in the server's private EC key file. Otherwise fall back to the
           NIST P-384 (secp384r1) curve to be compliant with RFC 6460 when
           AES-256 TLS cipher suites are in use. This fall back option does
           however make Dovecot non-compliant with RFC 6460 which requires
           curve NIST P-256 (prime256v1) be used when AES-128 TLS cipher
           suites are in use. At least the non-compliance is in the form of
           providing too much security rather than too little. */
        nid = ssl_proxy_ctx_get_pkey_ec_curve_name(set);
        ecdh = EC_KEY_new_by_curve_name(nid);
        if (ecdh == NULL) {
                /* Fall back option */
                nid = NID_secp384r1;
                ecdh = EC_KEY_new_by_curve_name(nid);
        }
        if ((curve_name = OBJ_nid2sn(nid)) != NULL &&
set->verbose_ssl)
                i_debug("SSL: elliptic curve %s will be used for ECDH
and"
                        " ECDHE key exchanges", curve_name);
        if (ecdh != NULL) {
                SSL_CTX_set_tmp_ecdh(ssl_ctx, ecdh);
                EC_KEY_free(ecdh);
        }
#endif




The OpenSSL CHANGES file says for version 1.1.0:
Changes between 1.0.2h and 1.1.0  [25 Aug 2016]
...
...
  *) SSL_{CTX_}set_ecdh_auto() has been removed and ECDH is support is
     always enabled now.  If you want to disable the support you should
     exclude it using the list of supported ciphers. This also means
that the
     "-no_ecdhe" option has been removed from s_server.
     [Kurt Roeckx]


So when the check for OpenSSL 1.1.0 fails, the curve selection will be
forced to use secp384r1 like it would be on older versions.
This curve change during negotiation breaks the connect for Android7
devices. They are not able to negotiate any ECDHE cipher.
The dovecot log shows:
...SSL_accept() failed: error:1417A0C1:SSL
routines:tls_post_process_client_hello:no shared cipher...

but here it is not a cipher problem. Instead it is a curve problem.
This is most relevant if the server is suited with an ECDSA-Certificate.
Than no TLS negotiation is possible.

There should be added a more sufficient check for the OpenSSL version.

If using OpenSSL 1.1.0*, the easiest way the have auto curve selection
again is to remove the whole check for testing purpose which results in
a working auto curve offering installation and allows also Android7
devices again to connect with TLS & ECDHE ciphers.


Regards Torsten