|
|
8735de0 |
Patch by Robert Scheck <robert@fedoraproject.org> for Zarafa >= 7.1.13 which implements DHE aka EDH
|
|
|
8735de0 |
(diffie-hellman key exchange) support. https://en.wikipedia.org/wiki/Diffie-Hellman_key_exchange is
|
|
|
8735de0 |
providing more information about Perfect Forward Secrecy (PFS). This implementation might need some
|
|
|
8735de0 |
more resources compared to ECDHE, however not all servers and/or clients are supporting it through;
|
|
|
8735de0 |
e.g. Red Hat Enterprise Linux 5 (and derivates). The prime length of 1024, 2048, 3072, 4096, 6144
|
|
|
8735de0 |
and 8192 bits are based on the private key size to avoid any static DH parameters. Please be aware
|
|
|
8735de0 |
that this patch may cause issues with some older SSL/TLS clients, mostly Java 7 or earlier, that do
|
|
|
8735de0 |
not support primes larger than 1024 bits.
|
|
|
8735de0 |
|
|
|
8735de0 |
Suggestions for testing; run the following openssl(1) commands before and after applying this patch:
|
|
|
8735de0 |
|
|
|
8735de0 |
1. echo QUIT | openssl s_client -cipher 'kEDH:ALL' -connect <host>:110 -starttls pop3 2>&1 | grep Cipher
|
|
|
8735de0 |
2. echo QUIT | openssl s_client -cipher 'kEDH:ALL' -connect <host>:143 -starttls imap 2>&1 | grep Cipher
|
|
|
8735de0 |
3. echo QUIT | openssl s_client -cipher 'kEDH:ALL' -connect <host>:237 2>&1 | grep Cipher
|
|
|
8735de0 |
4. echo QUIT | openssl s_client -cipher 'kEDH:ALL' -connect <host>:993 2>&1 | grep Cipher
|
|
|
8735de0 |
5. echo QUIT | openssl s_client -cipher 'kEDH:ALL' -connect <host>:995 2>&1 | grep Cipher
|
|
|
8735de0 |
6. echo QUIT | openssl s_client -cipher 'kEDH:ALL' -connect <host>:8443 2>&1 | grep Cipher
|
|
|
8735de0 |
|
|
|
8735de0 |
After applying this patch the output should contain e.g. "DHE-RSA-AES256-GCM-SHA384" on a Red Hat
|
|
|
8735de0 |
Enterprise Linux 6 (and derivates). Without this patch the result is e.g. "AES256-GCM-SHA384". Note
|
|
|
8735de0 |
that ZCP-12237 is maybe having influence on the result depending on the exact test case.
|
|
|
8735de0 |
|
|
|
8735de0 |
Important: As https://www.mail-archive.com/haproxy@formilux.org/msg13274.html is the origin for this
|
|
|
8735de0 |
patch (a HAProxy patch suggestion, which itself bases on mod_ssl of Apache httpd), the licensing is
|
|
|
8735de0 |
likely a combination out of the Apache License, Version 2.0, the GNU General Public License, version
|
|
|
8735de0 |
2 (or later) and the GNU Affero General Public License, version 3 (and thus excludes dual-licensing
|
|
|
8735de0 |
situations such as at the upstream of Zarafa).
|
|
|
8735de0 |
|
|
|
8735de0 |
This patch should be only applied after ZCP-12237 and its dependencies.
|
|
|
8735de0 |
|
|
|
8735de0 |
--- zarafa-7.1.13/common/ECChannel.cpp 2015-07-30 01:01:07.212313822 +0200
|
|
|
8735de0 |
+++ zarafa-7.1.13/common/ECChannel.cpp.ssl_dhe 2015-07-30 02:05:36.045747555 +0200
|
|
|
8735de0 |
@@ -85,6 +85,119 @@
|
|
|
8735de0 |
// because of statics
|
|
|
8735de0 |
SSL_CTX* ECChannel::lpCTX = NULL;
|
|
|
8735de0 |
|
|
|
8735de0 |
+#if !defined(OPENSSL_NO_DH)
|
|
|
8735de0 |
+static DH *ssl_get_dh_1024(void) {
|
|
|
8735de0 |
+ DH *dh = DH_new();
|
|
|
8735de0 |
+ if (dh) {
|
|
|
8735de0 |
+ dh->p = get_rfc2409_prime_1024(NULL);
|
|
|
8735de0 |
+ // See RFC 2409, Section 6 "Oakley Groups" for the reason why we use 2 as a generator
|
|
|
8735de0 |
+ BN_dec2bn(&dh->g, "2");
|
|
|
8735de0 |
+ if (!dh->p || !dh->g) {
|
|
|
8735de0 |
+ DH_free(dh);
|
|
|
8735de0 |
+ dh = NULL;
|
|
|
8735de0 |
+ }
|
|
|
8735de0 |
+ }
|
|
|
8735de0 |
+ return dh;
|
|
|
8735de0 |
+}
|
|
|
8735de0 |
+
|
|
|
8735de0 |
+static DH *ssl_get_dh_2048(void) {
|
|
|
8735de0 |
+ DH *dh = DH_new();
|
|
|
8735de0 |
+ if (dh) {
|
|
|
8735de0 |
+ dh->p = get_rfc3526_prime_2048(NULL);
|
|
|
8735de0 |
+ // See RFC 3526, Section 3 "2048-bit MODP Group" for the reason why we use 2 as a generator
|
|
|
8735de0 |
+ BN_dec2bn(&dh->g, "2");
|
|
|
8735de0 |
+ if (!dh->p || !dh->g) {
|
|
|
8735de0 |
+ DH_free(dh);
|
|
|
8735de0 |
+ dh = NULL;
|
|
|
8735de0 |
+ }
|
|
|
8735de0 |
+ }
|
|
|
8735de0 |
+ return dh;
|
|
|
8735de0 |
+}
|
|
|
8735de0 |
+
|
|
|
8735de0 |
+static DH *ssl_get_dh_3072(void) {
|
|
|
8735de0 |
+ DH *dh = DH_new();
|
|
|
8735de0 |
+ if (dh) {
|
|
|
8735de0 |
+ dh->p = get_rfc3526_prime_3072(NULL);
|
|
|
8735de0 |
+ // See RFC 3526, Section 4 "3072-bit MODP Group" for the reason why we use 2 as a generator
|
|
|
8735de0 |
+ BN_dec2bn(&dh->g, "2");
|
|
|
8735de0 |
+ if (!dh->p || !dh->g) {
|
|
|
8735de0 |
+ DH_free(dh);
|
|
|
8735de0 |
+ dh = NULL;
|
|
|
8735de0 |
+ }
|
|
|
8735de0 |
+ }
|
|
|
8735de0 |
+ return dh;
|
|
|
8735de0 |
+}
|
|
|
8735de0 |
+
|
|
|
8735de0 |
+static DH *ssl_get_dh_4096(void) {
|
|
|
8735de0 |
+ DH *dh = DH_new();
|
|
|
8735de0 |
+ if (dh) {
|
|
|
8735de0 |
+ dh->p = get_rfc3526_prime_4096(NULL);
|
|
|
8735de0 |
+ // See RFC 3526, Section 5 "4096-bit MODP Group" for the reason why we use 2 as a generator
|
|
|
8735de0 |
+ BN_dec2bn(&dh->g, "2");
|
|
|
8735de0 |
+ if (!dh->p || !dh->g) {
|
|
|
8735de0 |
+ DH_free(dh);
|
|
|
8735de0 |
+ dh = NULL;
|
|
|
8735de0 |
+ }
|
|
|
8735de0 |
+ }
|
|
|
8735de0 |
+ return dh;
|
|
|
8735de0 |
+}
|
|
|
8735de0 |
+
|
|
|
8735de0 |
+static DH *ssl_get_dh_6144(void) {
|
|
|
8735de0 |
+ DH *dh = DH_new();
|
|
|
8735de0 |
+ if (dh) {
|
|
|
8735de0 |
+ dh->p = get_rfc3526_prime_6144(NULL);
|
|
|
8735de0 |
+ // See RFC 3526, Section 6 "6144-bit MODP Group" for the reason why we use 2 as a generator
|
|
|
8735de0 |
+ BN_dec2bn(&dh->g, "2");
|
|
|
8735de0 |
+ if (!dh->p || !dh->g) {
|
|
|
8735de0 |
+ DH_free(dh);
|
|
|
8735de0 |
+ dh = NULL;
|
|
|
8735de0 |
+ }
|
|
|
8735de0 |
+ }
|
|
|
8735de0 |
+ return dh;
|
|
|
8735de0 |
+}
|
|
|
8735de0 |
+
|
|
|
8735de0 |
+static DH *ssl_get_dh_8192(void) {
|
|
|
8735de0 |
+ DH *dh = DH_new();
|
|
|
8735de0 |
+ if (dh) {
|
|
|
8735de0 |
+ dh->p = get_rfc3526_prime_8192(NULL);
|
|
|
8735de0 |
+ // See RFC 3526, Section 7 "8192-bit MODP Group" for the reason why we use 2 as a generator
|
|
|
8735de0 |
+ BN_dec2bn(&dh->g, "2");
|
|
|
8735de0 |
+ if (!dh->p || !dh->g) {
|
|
|
8735de0 |
+ DH_free(dh);
|
|
|
8735de0 |
+ dh = NULL;
|
|
|
8735de0 |
+ }
|
|
|
8735de0 |
+ }
|
|
|
8735de0 |
+ return dh;
|
|
|
8735de0 |
+}
|
|
|
8735de0 |
+
|
|
|
8735de0 |
+// Returns Diffie-Hellman parameters matching the private key length
|
|
|
8735de0 |
+static DH *ssl_get_tmp_dh(SSL *ssl, int exporting, int keylen) {
|
|
|
8735de0 |
+ DH *dh = NULL;
|
|
|
8735de0 |
+ EVP_PKEY *pkey = SSL_get_privatekey(ssl);
|
|
|
8735de0 |
+ int type = pkey ? EVP_PKEY_type(pkey->type) : EVP_PKEY_NONE;
|
|
|
8735de0 |
+
|
|
|
8735de0 |
+ if (type == EVP_PKEY_RSA || type == EVP_PKEY_DSA) {
|
|
|
8735de0 |
+ keylen = EVP_PKEY_bits(pkey);
|
|
|
8735de0 |
+ }
|
|
|
8735de0 |
+
|
|
|
8735de0 |
+ if (keylen >= 8192) {
|
|
|
8735de0 |
+ dh = ssl_get_dh_8192();
|
|
|
8735de0 |
+ } else if (keylen >= 6144) {
|
|
|
8735de0 |
+ dh = ssl_get_dh_6144();
|
|
|
8735de0 |
+ } else if (keylen >= 4096) {
|
|
|
8735de0 |
+ dh = ssl_get_dh_4096();
|
|
|
8735de0 |
+ } else if (keylen >= 3072) {
|
|
|
8735de0 |
+ dh = ssl_get_dh_3072();
|
|
|
8735de0 |
+ } else if (keylen >= 2048) {
|
|
|
8735de0 |
+ dh = ssl_get_dh_2048();
|
|
|
8735de0 |
+ } else {
|
|
|
8735de0 |
+ dh = ssl_get_dh_1024();
|
|
|
8735de0 |
+ }
|
|
|
8735de0 |
+
|
|
|
8735de0 |
+ return dh;
|
|
|
8735de0 |
+}
|
|
|
8735de0 |
+#endif
|
|
|
8735de0 |
+
|
|
|
8735de0 |
HRESULT ECChannel::HrSetCtx(ECConfig *lpConfig, ECLogger *lpLogger) {
|
|
|
8735de0 |
HRESULT hr = hrSuccess;
|
|
|
8735de0 |
char *szFile = NULL;
|
|
|
8735de0 |
@@ -116,6 +229,11 @@
|
|
|
8735de0 |
|
|
|
8735de0 |
SSL_CTX_set_options(lpCTX, SSL_OP_ALL); // enable quirk and bug workarounds
|
|
|
8735de0 |
|
|
|
8735de0 |
+#if !defined(OPENSSL_NO_DH)
|
|
|
8735de0 |
+ SSL_CTX_set_options(lpCTX, SSL_OP_SINGLE_DH_USE);
|
|
|
8735de0 |
+ SSL_CTX_set_tmp_dh_callback(lpCTX, ssl_get_tmp_dh);
|
|
|
8735de0 |
+#endif
|
|
|
8735de0 |
+
|
|
|
8735de0 |
#if !defined(OPENSSL_NO_ECDH) && defined(NID_X9_62_prime256v1)
|
|
|
8735de0 |
ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
|
|
|
8735de0 |
|
|
|
8735de0 |
--- zarafa-7.1.13/provider/server/ECSoapServerConnection.cpp 2015-07-30 01:01:07.212313822 +0200
|
|
|
8735de0 |
+++ zarafa-7.1.13/provider/server/ECSoapServerConnection.cpp.ssl_dhe 2015-07-30 02:05:54.658626465 +0200
|
|
|
8735de0 |
@@ -165,6 +165,119 @@
|
|
|
8735de0 |
return nRet;
|
|
|
8735de0 |
}
|
|
|
8735de0 |
|
|
|
8735de0 |
+#if !defined(OPENSSL_NO_DH)
|
|
|
8735de0 |
+static DH *ssl_get_dh_1024(void) {
|
|
|
8735de0 |
+ DH *dh = DH_new();
|
|
|
8735de0 |
+ if (dh) {
|
|
|
8735de0 |
+ dh->p = get_rfc2409_prime_1024(NULL);
|
|
|
8735de0 |
+ // See RFC 2409, Section 6 "Oakley Groups" for the reason why we use 2 as a generator
|
|
|
8735de0 |
+ BN_dec2bn(&dh->g, "2");
|
|
|
8735de0 |
+ if (!dh->p || !dh->g) {
|
|
|
8735de0 |
+ DH_free(dh);
|
|
|
8735de0 |
+ dh = NULL;
|
|
|
8735de0 |
+ }
|
|
|
8735de0 |
+ }
|
|
|
8735de0 |
+ return dh;
|
|
|
8735de0 |
+}
|
|
|
8735de0 |
+
|
|
|
8735de0 |
+static DH *ssl_get_dh_2048(void) {
|
|
|
8735de0 |
+ DH *dh = DH_new();
|
|
|
8735de0 |
+ if (dh) {
|
|
|
8735de0 |
+ dh->p = get_rfc3526_prime_2048(NULL);
|
|
|
8735de0 |
+ // See RFC 3526, Section 3 "2048-bit MODP Group" for the reason why we use 2 as a generator
|
|
|
8735de0 |
+ BN_dec2bn(&dh->g, "2");
|
|
|
8735de0 |
+ if (!dh->p || !dh->g) {
|
|
|
8735de0 |
+ DH_free(dh);
|
|
|
8735de0 |
+ dh = NULL;
|
|
|
8735de0 |
+ }
|
|
|
8735de0 |
+ }
|
|
|
8735de0 |
+ return dh;
|
|
|
8735de0 |
+}
|
|
|
8735de0 |
+
|
|
|
8735de0 |
+static DH *ssl_get_dh_3072(void) {
|
|
|
8735de0 |
+ DH *dh = DH_new();
|
|
|
8735de0 |
+ if (dh) {
|
|
|
8735de0 |
+ dh->p = get_rfc3526_prime_3072(NULL);
|
|
|
8735de0 |
+ // See RFC 3526, Section 4 "3072-bit MODP Group" for the reason why we use 2 as a generator
|
|
|
8735de0 |
+ BN_dec2bn(&dh->g, "2");
|
|
|
8735de0 |
+ if (!dh->p || !dh->g) {
|
|
|
8735de0 |
+ DH_free(dh);
|
|
|
8735de0 |
+ dh = NULL;
|
|
|
8735de0 |
+ }
|
|
|
8735de0 |
+ }
|
|
|
8735de0 |
+ return dh;
|
|
|
8735de0 |
+}
|
|
|
8735de0 |
+
|
|
|
8735de0 |
+static DH *ssl_get_dh_4096(void) {
|
|
|
8735de0 |
+ DH *dh = DH_new();
|
|
|
8735de0 |
+ if (dh) {
|
|
|
8735de0 |
+ dh->p = get_rfc3526_prime_4096(NULL);
|
|
|
8735de0 |
+ // See RFC 3526, Section 5 "4096-bit MODP Group" for the reason why we use 2 as a generator
|
|
|
8735de0 |
+ BN_dec2bn(&dh->g, "2");
|
|
|
8735de0 |
+ if (!dh->p || !dh->g) {
|
|
|
8735de0 |
+ DH_free(dh);
|
|
|
8735de0 |
+ dh = NULL;
|
|
|
8735de0 |
+ }
|
|
|
8735de0 |
+ }
|
|
|
8735de0 |
+ return dh;
|
|
|
8735de0 |
+}
|
|
|
8735de0 |
+
|
|
|
8735de0 |
+static DH *ssl_get_dh_6144(void) {
|
|
|
8735de0 |
+ DH *dh = DH_new();
|
|
|
8735de0 |
+ if (dh) {
|
|
|
8735de0 |
+ dh->p = get_rfc3526_prime_6144(NULL);
|
|
|
8735de0 |
+ // See RFC 3526, Section 6 "6144-bit MODP Group" for the reason why we use 2 as a generator
|
|
|
8735de0 |
+ BN_dec2bn(&dh->g, "2");
|
|
|
8735de0 |
+ if (!dh->p || !dh->g) {
|
|
|
8735de0 |
+ DH_free(dh);
|
|
|
8735de0 |
+ dh = NULL;
|
|
|
8735de0 |
+ }
|
|
|
8735de0 |
+ }
|
|
|
8735de0 |
+ return dh;
|
|
|
8735de0 |
+}
|
|
|
8735de0 |
+
|
|
|
8735de0 |
+static DH *ssl_get_dh_8192(void) {
|
|
|
8735de0 |
+ DH *dh = DH_new();
|
|
|
8735de0 |
+ if (dh) {
|
|
|
8735de0 |
+ dh->p = get_rfc3526_prime_8192(NULL);
|
|
|
8735de0 |
+ // See RFC 3526, Section 7 "8192-bit MODP Group" for the reason why we use 2 as a generator
|
|
|
8735de0 |
+ BN_dec2bn(&dh->g, "2");
|
|
|
8735de0 |
+ if (!dh->p || !dh->g) {
|
|
|
8735de0 |
+ DH_free(dh);
|
|
|
8735de0 |
+ dh = NULL;
|
|
|
8735de0 |
+ }
|
|
|
8735de0 |
+ }
|
|
|
8735de0 |
+ return dh;
|
|
|
8735de0 |
+}
|
|
|
8735de0 |
+
|
|
|
8735de0 |
+// Returns Diffie-Hellman parameters matching the private key length
|
|
|
8735de0 |
+static DH *ssl_get_tmp_dh(SSL *ssl, int exporting, int keylen) {
|
|
|
8735de0 |
+ DH *dh = NULL;
|
|
|
8735de0 |
+ EVP_PKEY *pkey = SSL_get_privatekey(ssl);
|
|
|
8735de0 |
+ int type = pkey ? EVP_PKEY_type(pkey->type) : EVP_PKEY_NONE;
|
|
|
8735de0 |
+
|
|
|
8735de0 |
+ if (type == EVP_PKEY_RSA || type == EVP_PKEY_DSA) {
|
|
|
8735de0 |
+ keylen = EVP_PKEY_bits(pkey);
|
|
|
8735de0 |
+ }
|
|
|
8735de0 |
+
|
|
|
8735de0 |
+ if (keylen >= 8192) {
|
|
|
8735de0 |
+ dh = ssl_get_dh_8192();
|
|
|
8735de0 |
+ } else if (keylen >= 6144) {
|
|
|
8735de0 |
+ dh = ssl_get_dh_6144();
|
|
|
8735de0 |
+ } else if (keylen >= 4096) {
|
|
|
8735de0 |
+ dh = ssl_get_dh_4096();
|
|
|
8735de0 |
+ } else if (keylen >= 3072) {
|
|
|
8735de0 |
+ dh = ssl_get_dh_3072();
|
|
|
8735de0 |
+ } else if (keylen >= 2048) {
|
|
|
8735de0 |
+ dh = ssl_get_dh_2048();
|
|
|
8735de0 |
+ } else {
|
|
|
8735de0 |
+ dh = ssl_get_dh_1024();
|
|
|
8735de0 |
+ }
|
|
|
8735de0 |
+
|
|
|
8735de0 |
+ return dh;
|
|
|
8735de0 |
+}
|
|
|
8735de0 |
+#endif
|
|
|
8735de0 |
+
|
|
|
8735de0 |
ECSoapServerConnection::ECSoapServerConnection(ECConfig* lpConfig, ECLogger* lpLogger)
|
|
|
8735de0 |
{
|
|
|
8735de0 |
m_lpConfig = lpConfig;
|
|
|
8735de0 |
@@ -271,6 +384,11 @@
|
|
|
8735de0 |
|
|
|
8735de0 |
SSL_CTX_set_options(lpsSoap->ctx, SSL_OP_ALL);
|
|
|
8735de0 |
|
|
|
8735de0 |
+#if !defined(OPENSSL_NO_DH)
|
|
|
8735de0 |
+ SSL_CTX_set_options(lpsSoap->ctx, SSL_OP_SINGLE_DH_USE);
|
|
|
8735de0 |
+ SSL_CTX_set_tmp_dh_callback(lpsSoap->ctx, ssl_get_tmp_dh);
|
|
|
8735de0 |
+#endif
|
|
|
8735de0 |
+
|
|
|
8735de0 |
#if !defined(OPENSSL_NO_ECDH) && defined(NID_X9_62_prime256v1)
|
|
|
8735de0 |
ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
|
|
|
8735de0 |
|