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