Bug 12632

Summary: Custom generated Diffie Hellman parameters are insecure according to RFC 7919
Product: IPFire Reporter: Peter Müller <peter.mueller>
Component: ---Assignee: Peter Müller <peter.mueller>
Status: CLOSED FIXED QA Contact:
Severity: Security    
Priority: Will affect an average number of users CC: ummeegge
Version: 2Keywords: Security
Hardware: all   
OS: All   
Attachments: Deletes DH parameter sections from CGI and uses static one

Description Peter Müller 2021-06-03 08:37:53 UTC
RFC 7919 (https://datatracker.ietf.org/doc/html/rfc7919) points out custom generated Diffie Hellman parameters can, under certain circumstances, be abused to weaken strength of traffic encrypted using a PFS cipher.

This is backed by various other sources, such as

(a) Dutch NCSC (https://english.ncsc.nl/binaries/ncsc-en/documents/publications/2019/juni/01/it-security-guidelines-for-transport-layer-security-tls/IT+Security+Guidelines+for+Transport+Layer+Security+v2.0.pdf, page 27, table 10)

(b) OpenSSL (https://wiki.openssl.org/index.php/Diffie-Hellman_parameters#RFC_7919_Groups)

Currently, we allow - even require - IPFire users to generate Diffie Hellman parameters on their own if they use OpenVPN. In my understanding of RFC 7919 et al., we should not do this.

Instead, we should use one of the audited Diffie Hellman parameters (personally, I use ffdhe4096 for public mail servers), and drop the ability to generate or upload custom ones.

Compared to Diffie Hellman key exchanges over elliptic curves (ECDHE), Diffie Hellman itself is remarkably slower. Modern clients do not need it anymore, which is why I would also raise the question if we could stop supporting DH ciphers for OpenVPN at all.
Comment 1 Erik Kapfer 2021-06-05 06:45:47 UTC
We have tested the '--dh none' in combination with '--ecdh-curve name' option in the old forum relatively extensive also because of the really long generation time while the PKI has been created. The testing results are lost since the forum has been deleted also i thought that we have had a smaller discussion about that topic on the mailinglist which i haven´t found so far.
According to a ecdh configuration, here the details

From OpenVPN manpage:
"
--dh file
File containing Diffie Hellman parameters in .pem format (required for --tls-server only).
Set file=none to disable Diffie Hellman key exchange (and use ECDH only). Note that this requires peers to be using an SSL library that supports ECDH TLS cipher suites (e.g. OpenSSL 1.0.1+, or mbed TLS 2.0+).

Use openssl dhparam -out dh2048.pem 2048 to generate 2048-bit DH parameters. Diffie Hellman parameters may be considered public.

--ecdh-curve name
Specify the curve to use for elliptic curve Diffie Hellman. Available curves can be listed with --show-curves. The specified curve will only be used for ECDH TLS-ciphers.
This option is not supported in mbed TLS builds of OpenVPN.
"

What is your opinion Peter. Deliver a DH-Parameter with the core system and stay on the old algorithm and delete the dh options from the WUI or open up a new algorithm and disable the Diffie Hellman key exchange fully and use ECDH only may with a choice of different curves in the WUI ?

Best,

Erik
Comment 2 Peter Müller 2021-06-05 11:25:05 UTC
Hi Erik,

thanks for your reply.

> What is your opinion Peter. Deliver a DH-Parameter with the core system and
> stay on the old algorithm and delete the dh options from the WUI or open up a
> new algorithm and disable the Diffie Hellman key exchange fully and use ECDH
> only may with a choice of different curves in the WUI ?

Personally, I would prefer the latter, since this is what we are doing for IPsec
as well. However, I have no idea how much collateral damage this would cause to
IPFire users - you have a better insight in our OpenVPN community, I guess. :-)

If dropping DH entirely is not an option, I would vote for your first suggestion:
Deliver a safe DH parameter, and drop related options from the WUI.

Thanks, and best regards,
Peter Müller
Comment 3 Erik Kapfer 2021-11-10 12:40:40 UTC
Hello Peter and sorry for the long break.
A first step to go here further can be to add a ffdhe4096 from --> https://wiki.openssl.org/index.php/Diffie-Hellman_parameters#RFC_7919_Groups which should be in essence the same then --> https://ssl-config.mozilla.org/ffdhe4096.txt (this format is needed) to the Core system while building OpenVPN like the verify script --> https://git.ipfire.org/?p=ipfire-2.x.git;a=blob;f=lfs/openvpn;h=81ccc52bfd24ba05c0f56ba2106111238655021f;hb=refs/heads/core160#l96 and store the DH parameter in /usr/lib/openvpn (safe place which should not be deleted) since /var/ipfire/ovpn will completely wiped out if the PKI get´s renewed for example. The permission of e.g. dh.pem differs to the verify script from the openvpn LFS with

-rw-r--r-- 1 root root 769 Oct 27 15:11 /usr/lib/openvpn/dh.pem

. Have made a patch (with Core 160) for this which i add to the attachment since i currently do not have access to the development environment, may you can test and deliver this too...

Lines in the configuration files (N2N and RW) needs to be changed which should made the commands at the beginning (after commit messages) of the patch.

The ECDHE curve topic might be the next/additional step but i wanted to leave this short as possible.

Best,

Erik
Comment 4 Erik Kapfer 2021-11-10 12:42:15 UTC
Created attachment 954 [details]
Deletes DH parameter sections from CGI and uses static one
Comment 5 Erik Kapfer 2021-11-18 11:24:04 UTC
According to "dropping DH entirely", have tested it with '--dh none' and commented the old '--dh ..' line entirely which works out of the box and a key exchange on server side looks like this:

Nov 18 11:55:44 ipfire openvpnserver[9895]: testdhnone/192.168.10.5:40991 VERIFY SCRIPT OK: depth=1, C=AF, O=ummeegge, CN=ummeegge CA
Nov 18 11:55:44 ipfire openvpnserver[9895]: testdhnone/192.168.10.5:40991 VERIFY OK: depth=1, C=AF, O=ummeegge, CN=ummeegge CA
Nov 18 11:55:44 ipfire openvpnserver[9895]: testdhnone/192.168.10.5:40991 VERIFY SCRIPT OK: depth=0, C=DE, ST=BW, O=ummeegge, OU=FZeit, CN=testdhnone
Nov 18 11:55:44 ipfire openvpnserver[9895]: testdhnone/192.168.10.5:40991 VERIFY OK: depth=0, C=DE, ST=BW, O=ummeegge, OU=FZeit, CN=testdhnone
Nov 18 11:55:44 ipfire openvpnserver[9895]: testdhnone/192.168.10.5:40991 peer info: IV_VER=2.5.4
Nov 18 11:55:44 ipfire openvpnserver[9895]: testdhnone/192.168.10.5:40991 peer info: IV_PLAT=linux
Nov 18 11:55:44 ipfire openvpnserver[9895]: testdhnone/192.168.10.5:40991 peer info: IV_PROTO=6
Nov 18 11:55:44 ipfire openvpnserver[9895]: testdhnone/192.168.10.5:40991 peer info: IV_NCP=2
Nov 18 11:55:44 ipfire openvpnserver[9895]: testdhnone/192.168.10.5:40991 peer info: IV_CIPHERS=AES-256-GCM:AES-128-GCM:AES-256-CBC
Nov 18 11:55:44 ipfire openvpnserver[9895]: testdhnone/192.168.10.5:40991 peer info: IV_LZ4=1
Nov 18 11:55:44 ipfire openvpnserver[9895]: testdhnone/192.168.10.5:40991 peer info: IV_LZ4v2=1
Nov 18 11:55:44 ipfire openvpnserver[9895]: testdhnone/192.168.10.5:40991 peer info: IV_LZO=1
Nov 18 11:55:44 ipfire openvpnserver[9895]: testdhnone/192.168.10.5:40991 peer info: IV_COMP_STUB=1
Nov 18 11:55:44 ipfire openvpnserver[9895]: testdhnone/192.168.10.5:40991 peer info: IV_COMP_STUBv2=1
Nov 18 11:55:44 ipfire openvpnserver[9895]: testdhnone/192.168.10.5:40991 peer info: IV_TCPNL=1
Nov 18 11:55:44 ipfire openvpnserver[9895]: testdhnone/192.168.10.5:40991 Outgoing Data Channel: Cipher 'AES-256-CBC' initialized with 256 bit key
Nov 18 11:55:44 ipfire openvpnserver[9895]: testdhnone/192.168.10.5:40991 Outgoing Data Channel: Using 160 bit message hash 'SHA1' for HMAC authentication
Nov 18 11:55:44 ipfire openvpnserver[9895]: testdhnone/192.168.10.5:40991 Incoming Data Channel: Cipher 'AES-256-CBC' initialized with 256 bit key
Nov 18 11:55:44 ipfire openvpnserver[9895]: testdhnone/192.168.10.5:40991 Incoming Data Channel: Using 160 bit message hash 'SHA1' for HMAC authentication
Nov 18 11:55:44 ipfire openvpnserver[9895]: testdhnone/192.168.10.5:40991 Control Channel: TLSv1.3, cipher TLSv1.3 TLS_AES_256_GCM_SHA384, peer certificate: 2048 bit RSA, signature: RSA-SHA256

This requires peers to be using an SSL library that supports ECDH TLS cipher suites (e.g. OpenSSL 1.0.1+, or mbed TLS 2.0+).

To get an comparison of the keylength DH vs. ECDH take a look to 'Discrete Logarithm Group' in here --> https://www.keylength.com/en/4/ . Also, to get a ECDHE key exchange, i think a complete ECC PKI might be needed.

To use other curves, the '--ecdh-curve name' directive can also be used. An overview of the available ones can be checked via 'openvpn --show-curves' on IPFire console.

Just to get more butter to the fish for testings and for other possibilities. 

Best,

Erik

P.S.: Manpage 2.5 --> https://build.openvpn.net/man/openvpn-2.5/openvpn.8.html
Comment 6 Erik Kapfer 2022-02-01 18:42:33 UTC
Hi Peter,
have pushed now a possible idea of how to solve this --> https://git.ipfire.org/?p=people/ummeegge/ipfire-2.x.git;a=commit;h=2ccc799f8bd6a12c3edab5f1a89fab4d2cd05ea8 .

The main idea is to deliver a standard group of a ffdhe4096.pem parameter via OpenSSL which will be copied while OpenSSL compilation from the ssl directory to /etc/ssl . The complete DH-parameter code in ovpnmain.cgi an the lang files are removed except the "Certificate Authorities and -Keys" chart.

As a first step, the second can be to offer also some ECDHE curves via WUI which i am currently working on.

What do you think ?

Best,

Erik
Comment 7 Peter Müller 2022-11-10 19:40:15 UTC
Hello Erik,

this time, it is my fault. Apologies for the tardy reply.

Thanks for your patch, it looks quite good to me. Just one question: Is it safe to replace the Diffie-Hellman parameter on existing installations? To the best of my understanding, it should be possible to do so without breaking anything already configured, but you are the OpenVPN guru around here, so I just wanted to be sure. :-)

All the best,
Peter Müller
Comment 8 Peter Müller 2022-11-10 19:41:06 UTC
Sorry, adding you to CC again. Please review my last comment and respond. :-)
Comment 9 Erik Kapfer 2022-11-11 08:36:58 UTC
Good morning Peter,

(In reply to Peter Müller from comment #7)
> Thanks for your patch, it looks quite good to me. Just one question: Is it
> safe to replace the Diffie-Hellman parameter on existing installations? To
> the best of my understanding, it should be possible to do so without
> breaking anything already configured, but you are the OpenVPN guru around
> here, so I just wanted to be sure. :-)
> 
this should be no problem also for existing installation/running OpenVPN instances. Since we also need to modify the server.conf and all N2N configurations (new path to DH-parameter), we should stop and start all N2Ns and RWs, after that, the new DH-parameter will be in usage for every connection.

What do you think of the location where the DH-parameter is placed ? Should we use '/etc/ssl' or may '/etc/pki' ?
Also, is it the best way to deliver the 'ffdhe4096.pem' while the build of OpenSSL ? We can surely use the DH-parameter also for other software so i thought this should be the place to distribute it.

Best,

Erik
Comment 10 Peter Müller 2022-11-11 10:36:08 UTC
Thanks for your reply. Very good to hear that we can migrate existing IPFire installations.

> What do you think of the location where the DH-parameter is placed ? Should we use '/etc/ssl' or may '/etc/pki' ?

/etc/ssl/ is fine to me.

> Also, is it the best way to deliver the 'ffdhe4096.pem' while the build of OpenSSL ? We can surely use the DH-parameter also for other software so i thought this should be the place to distribute it.

Well, since we use own Diffie-Hellman parameters in context of OpenVPN only (we shifted away from that for Apache long time ago, and IPsec comes with some DH params built-in), I guess it is more straight-forward to do this in the OpenVPN package rather than OpenSSL.

Non-ECC-based Diffie-Hellman is a dying thing anyway... :-)

I'll pick up your patch and amend it to Core Update 172.
Comment 11 Peter Müller 2022-11-11 11:48:18 UTC
Ah, sorry, mixed OpenSSL and OpenVPN in my last comment. Sorry for the confusion.
Comment 15 Erik Kapfer 2022-12-04 20:11:50 UTC
Hello,
according to this bug --> https://community.ipfire.org/t/core-172-testing-fails/9002/14 but also another one i have found (N2N related) the the following patch should solve those problems.

--- /var/ipfire/langs/de.pl_core172_buggy	2022-12-04 20:34:44.901874457 +0100
+++ /var/ipfire/langs/de.pl	2022-12-04 20:39:54.810759610 +0100
@@ -760,6 +760,7 @@
 'details' => 'Mehr',
 'device' => 'Gerät',
 'devices on blue' => 'Geräte auf BLAU',
+'dh' => 'Diffie-Hellman-Parameter',
 'dhcp advopt add' => 'DHCP Option hinzufügen',
 'dhcp advopt added' => 'DHCP Option hinzugefügt',
 'dhcp advopt blank value' => 'Wert für DHCP Option darf nicht leer sein',
@@ -2256,6 +2257,7 @@
 'show ca certificate' => 'CA Zertifikat anzeigen',
 'show certificate' => 'Datei anzeigen',
 'show crl' => 'Certificate Revocation List anzeigen',
+'show dh' => 'Diffie-Hellman-Parameter anzeigen',
 'show host certificate' => 'Host-Zertifikat anzeigen',
 'show last x lines' => 'die letzten x Zeilen anzeigen',
 'show otp qrcode' => 'Zeige OTP QRCode',
--- /var/ipfire/langs/en.pl_core172_buggy	2022-12-04 20:06:24.628640598 +0100
+++ /var/ipfire/langs/en.pl	2022-12-04 20:11:56.363993014 +0100
@@ -795,6 +795,7 @@
 'details' => 'Details',
 'device' => 'Device',
 'devices on blue' => 'Devices on BLUE',
+'dh' => 'Diffie-Hellman-Parameter',
 'dhcp advopt add' => 'Add a DHCP option',
 'dhcp advopt added' => 'DHCP option added',
 'dhcp advopt blank value' => 'DHCP Option value cannot be empty.',
@@ -2313,6 +2314,7 @@
 'show ca certificate' => 'Show CA certificate',
 'show certificate' => 'Show file',
 'show crl' => 'Show certificate revocation list',
+'show dh' => 'Show Diffie-Hellman parameters',
 'show host certificate' => 'Show host certificate',
 'show last x lines' => 'Show last x lines',
 'show lines' => 'Show lines',
--- /srv/web/ipfire/cgi-bin/ovpnmain.cgi_core172_buggy	2022-12-04 19:58:07.719077771 +0100
+++ /srv/web/ipfire/cgi-bin/ovpnmain.cgi	2022-12-04 20:32:13.904384551 +0100
@@ -977,7 +977,7 @@
   print SERVERCONF "ca ${General::swroot}/ovpn/ca/cacert.pem\n";
   print SERVERCONF "cert ${General::swroot}/ovpn/certs/servercert.pem\n";
   print SERVERCONF "key ${General::swroot}/ovpn/certs/serverkey.pem\n";
-  print SERVERCONF "dh ${General::swroot}/ovpn/ca/$cgiparams{'DH_NAME'}\n";
+  print SERVERCONF "dh $dhparameter\n";
   print SERVERCONF "# Cipher\n";
   print SERVERCONF "cipher $cgiparams{'DCIPHER'}\n";
 
@@ -5700,7 +5700,7 @@
 
 	print <<END;
 		<tr>
-			<td class='base' $col3>$Lang::tr{'dh parameter'}</td>
+			<td class='base' $col3>$Lang::tr{'dh'}</td>
 			<td class='base' $col3>$dhsubject</td>
 			<form method='post' name='frmdhparam'><td width='3%' align='center' $col3>
 			<input type='hidden' name='ACTION' value='$Lang::tr{'show dh'}' />

Best,

Erik