aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArne Schwabe2024-01-04 15:02:14 +0100
committerGert Doering2024-01-04 15:28:23 +0100
commitb29ada314cc79497a1e50e29b4b72dede2955b3d (patch)
tree54a31354b78cd593ed3346390df51db3b611e9bf
parentbfd5b12e49785cc658f6f2f86360797fd2201cdc (diff)
downloadopenvpn-b29ada314cc79497a1e50e29b4b72dede2955b3d.zip
openvpn-b29ada314cc79497a1e50e29b4b72dede2955b3d.tar.gz
Check PRF availability on initialisation and add --force-tls-key-material-export
We now warn a user if the TLS 1.0 PRF is not supported by the cryptographic library of the system. Also add the option --force-tls-key-material-export that automatically rejects clients that do not support TLS Keying Material Export and automatically enable it when TLS 1.0 PRF support is not available. Change-Id: I04f8c7c413e7cb62c726262feee6ca89c7e86c70 Signed-off-by: Arne Schwabe <arne@rfc2549.org> Acked-by: Gert Doering <gert@greenie.muc.de> Message-Id: <20240104140214.32196-1-gert@greenie.muc.de> URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg27924.html Signed-off-by: Gert Doering <gert@greenie.muc.de> (cherry picked from commit fa7960961415fa4f368e9bbb39dc4047680ff30c)
-rw-r--r--doc/man-sections/protocol-options.rst8
-rw-r--r--src/openvpn/crypto.c20
-rw-r--r--src/openvpn/crypto.h8
-rw-r--r--src/openvpn/multi.c10
-rw-r--r--src/openvpn/options.c36
-rw-r--r--src/openvpn/options.h2
6 files changed, 84 insertions, 0 deletions
diff --git a/doc/man-sections/protocol-options.rst b/doc/man-sections/protocol-options.rst
index 8134157..4699b98 100644
--- a/doc/man-sections/protocol-options.rst
+++ b/doc/man-sections/protocol-options.rst
@@ -288,3 +288,11 @@ configured in a compatible way between both the local and remote side.
a key renegotiation begins (default :code:`3600` seconds). This feature
allows for a graceful transition from old to new key, and removes the key
renegotiation sequence from the critical path of tunnel data forwarding.
+
+--force-tls-key-material-export
+ This option is only available in --mode server and forces to use
+ Keying Material Exporters (RFC 5705) for clients. This can be used to
+ simulate an environment where the cryptographic library does not support
+ the older method to generate data channel keys anymore. This option is
+ intended to be a test option and might be removed in a future OpenVPN
+ version without notice.
diff --git a/src/openvpn/crypto.c b/src/openvpn/crypto.c
index b5268f1..ef4ec92 100644
--- a/src/openvpn/crypto.c
+++ b/src/openvpn/crypto.c
@@ -27,6 +27,7 @@
#endif
#include "syshead.h"
+#include <string.h>
#include "crypto.h"
#include "error.h"
@@ -1817,3 +1818,22 @@ cleanup:
gc_free(&gc);
return ret;
}
+
+bool
+check_tls_prf_working(void)
+{
+ /* Modern TLS libraries might no longer support the TLS 1.0 PRF with
+ * MD5+SHA1. This allows us to establish connections only
+ * with other 2.6.0+ OpenVPN peers.
+ * Do a simple dummy test here to see if it works. */
+ const char *seed = "tls1-prf-test";
+ const char *secret = "tls1-prf-test-secret";
+ uint8_t out[8];
+ uint8_t expected_out[] = { 'q', 'D', '\xfe', '%', '@', 's', 'u', '\x95' };
+
+ int ret = ssl_tls1_PRF((uint8_t *)seed, (int) strlen(seed),
+ (uint8_t *)secret, (int) strlen(secret),
+ out, sizeof(out));
+
+ return (ret && memcmp(out, expected_out, sizeof(out)) == 0);
+}
diff --git a/src/openvpn/crypto.h b/src/openvpn/crypto.h
index 846a725..2ed4d1f 100644
--- a/src/openvpn/crypto.h
+++ b/src/openvpn/crypto.h
@@ -597,4 +597,12 @@ create_kt(const char *cipher, const char *md, const char *optname)
return kt;
}
+/**
+ * Checks if the current TLS library supports the TLS 1.0 PRF with MD5+SHA1
+ * that OpenVPN uses when TLS Keying Material Export is not available.
+ *
+ * @return true if supported, false otherwise.
+ */
+bool check_tls_prf_working(void);
+
#endif /* CRYPTO_H */
diff --git a/src/openvpn/multi.c b/src/openvpn/multi.c
index 83411e8..d3e5f0d 100644
--- a/src/openvpn/multi.c
+++ b/src/openvpn/multi.c
@@ -1830,6 +1830,16 @@ multi_client_set_protocol_options(struct context *c)
{
o->imported_protocol_flags |= CO_USE_TLS_KEY_MATERIAL_EXPORT;
}
+ else if (o->force_key_material_export)
+ {
+ msg(M_INFO, "PUSH: client does not support TLS Keying Material "
+ "Exporters but --force-tls-key-material-export is enabled.");
+ auth_set_client_reason(tls_multi, "Client incompatible with this "
+ "server. Keying Material Exporters (RFC 5705) "
+ "support missing. Upgrade to a client that "
+ "supports this feature (OpenVPN 2.6.0+).");
+ return false;
+ }
if (proto & IV_PROTO_DYN_TLS_CRYPT)
{
o->imported_protocol_flags |= CO_USE_DYNAMIC_TLS_CRYPT;
diff --git a/src/openvpn/options.c b/src/openvpn/options.c
index dc18b33..26b5648 100644
--- a/src/openvpn/options.c
+++ b/src/openvpn/options.c
@@ -1569,6 +1569,7 @@ show_p2mp_parms(const struct options *o)
SHOW_STR(auth_user_pass_verify_script);
SHOW_BOOL(auth_user_pass_verify_script_via_file);
SHOW_BOOL(auth_token_generate);
+ SHOW_BOOL(force_key_material_export);
SHOW_INT(auth_token_lifetime);
SHOW_STR_INLINE(auth_token_secret_file);
#if PORT_SHARE
@@ -2811,6 +2812,11 @@ options_postprocess_verify_ce(const struct options *options,
{
msg(M_USAGE, "--vlan-tagging requires --mode server");
}
+
+ if (options->force_key_material_export)
+ {
+ msg(M_USAGE, "--force-tls-key-material-export requires --mode server");
+ }
}
/*
@@ -3643,6 +3649,30 @@ options_set_backwards_compatible_options(struct options *o)
}
static void
+options_process_mutate_prf(struct options *o)
+{
+ if (!check_tls_prf_working())
+ {
+ msg(D_TLS_ERRORS, "Warning: TLS 1.0 PRF with MD5+SHA1 PRF is not "
+ "supported by the TLS library. Your system does not support this "
+ "calculation anymore or your security policy (e.g. FIPS 140-2) "
+ "forbids it. Connections will only work with peers running "
+ "OpenVPN 2.6.0 or higher)");
+#ifndef HAVE_EXPORT_KEYING_MATERIAL
+ msg(M_FATAL, "Keying Material Exporters (RFC 5705) not available either. "
+ "No way to generate data channel keys left.");
+#endif
+ if (o->mode == MODE_SERVER)
+ {
+ msg(M_WARN, "Automatically enabling option "
+ "--force-tls-key-material-export");
+ o->force_key_material_export = true;
+ }
+
+ }
+}
+
+static void
options_postprocess_mutate(struct options *o, struct env_set *es)
{
int i;
@@ -3656,6 +3686,7 @@ options_postprocess_mutate(struct options *o, struct env_set *es)
options_postprocess_setdefault_ncpciphers(o);
options_set_backwards_compatible_options(o);
+ options_process_mutate_prf(o);
options_postprocess_cipher(o);
o->ncp_ciphers = mutate_ncp_cipher_list(o->ncp_ciphers, &o->gc);
@@ -8641,6 +8672,11 @@ add_option(struct options *options,
}
}
}
+ else if (streq(p[0], "force-tls-key-material-export"))
+ {
+ VERIFY_PERMISSION(OPT_P_GENERAL);
+ options->force_key_material_export = true;
+ }
else if (streq(p[0], "prng") && p[1] && !p[3])
{
msg(M_WARN, "NOTICE: --prng option ignored (SSL library PRNG is used)");
diff --git a/src/openvpn/options.h b/src/openvpn/options.h
index 8e53f6f..2aacfea 100644
--- a/src/openvpn/options.h
+++ b/src/openvpn/options.h
@@ -687,6 +687,8 @@ struct options
const char *keying_material_exporter_label;
int keying_material_exporter_length;
#endif
+ /* force using TLS key material export for data channel key generation */
+ bool force_key_material_export;
bool vlan_tagging;
enum vlan_acceptable_frames vlan_accept;