Skip to content

Commit

Permalink
Check PRF availability on initialisation and add --force-tls-key-mate…
Browse files Browse the repository at this point in the history
…rial-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 <[email protected]>
Acked-by: Gert Doering <[email protected]>
Message-Id: <[email protected]>
URL: https://www.mail-archive.com/[email protected]/msg27924.html
Signed-off-by: Gert Doering <[email protected]>
(cherry picked from commit fa79609)
  • Loading branch information
schwabe authored and cron2 committed Jan 4, 2024
1 parent bfd5b12 commit b29ada3
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 0 deletions.
8 changes: 8 additions & 0 deletions doc/man-sections/protocol-options.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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.
20 changes: 20 additions & 0 deletions src/openvpn/crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#endif

#include "syshead.h"
#include <string.h>

#include "crypto.h"
#include "error.h"
Expand Down Expand Up @@ -1817,3 +1818,22 @@ read_pem_key_file(struct buffer *key, const char *pem_name,
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);
}
8 changes: 8 additions & 0 deletions src/openvpn/crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
10 changes: 10 additions & 0 deletions src/openvpn/multi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
36 changes: 36 additions & 0 deletions src/openvpn/options.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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");
}
}

/*
Expand Down Expand Up @@ -3642,6 +3648,30 @@ options_set_backwards_compatible_options(struct options *o)
#endif
}

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)
{
Expand All @@ -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);
Expand Down Expand Up @@ -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)");
Expand Down
2 changes: 2 additions & 0 deletions src/openvpn/options.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit b29ada3

Please sign in to comment.