0
0
mirror of https://github.com/OpenVPN/openvpn.git synced 2024-09-20 12:02:28 +02:00

Added support for TLS Keying Material Exporters [RFC-5705]

Keying Material Exporter [RFC-5705] allow additional keying material to be
derived from existing TLS channel. This exported keying material can then be
used for a variety of purposes.

[DS: Updated man page to document both upper and lower length boundaries]

Signed-off-by: Daniel Kubec <niel@rtfm.cz>
Signed-off-by: David Sommerseth <davids@redhat.com>
Acked-by: Steffan Karger <steffan.karger@fox-it.com
Acked-by: David Sommerseth <davids@redhat.com>
This commit is contained in:
Daniel Kubec 2015-03-12 15:14:20 +01:00 committed by David Sommerseth
parent 7246ccfdbe
commit 685e486e8b
Notes: David Sommerseth 2015-10-10 10:41:37 +02:00
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Forgot to add Message-ID and URLs to the commit message.

Message-Id: CAEW7GUswCyjPpYN8_2d5OGQzg7xRe8tAVBa=9-243W9vLL4b+g@mail.gmail.com
URL: http://article.gmane.org/gmane.network.openvpn.devel/9543

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.22 (GNU/Linux)

iEYEARECAAYFAlYYy94ACgkQDC186MBRfroOgQCgl5Qszv6ZbSqBJ29b2FE/dUMA
ilEAn2IgcE6OD4ZPFekaUCv5KKsSSrh6
=DyDt
-----END PGP SIGNATURE-----
9 changed files with 122 additions and 0 deletions

View File

@ -2757,6 +2757,18 @@ client\-connect), then
every module and script must return success (0) in order for
the connection to be authenticated.
.\"*********************************************************
.TP
.B \-\-keying-material-exporter label len
Save Exported Keying Material [RFC5705] of len bytes (must be
between 16 and 4095 bytes) using label in environment
(exported_keying_material) for use by plugins in
OPENVPN_PLUGIN_TLS_FINAL callback.
Note that exporter labels have the potential to collide with existing PRF
labels. In order to prevent this, labels MUST begin with "EXPORTER".
This option requires OpenSSL 1.0.1 or newer.
.\"*********************************************************
.SS Server Mode
Starting with OpenVPN 2.0, a multi-client TCP/UDP server mode
is supported, and can be enabled with the

View File

@ -2279,6 +2279,22 @@ do_init_crypto_tls (struct context *c, const unsigned int flags)
to.comp_options = options->comp;
#endif
#if defined(ENABLE_CRYPTO_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10001000
if (options->keying_material_exporter_label)
{
to.ekm_size = options->keying_material_exporter_length;
if (to.ekm_size < 16 || to.ekm_size > 4095)
to.ekm_size = 0;
to.ekm_label = options->keying_material_exporter_label;
to.ekm_label_size = strlen(to.ekm_label);
}
else
{
to.ekm_size = 0;
}
#endif
/* TLS handshake authentication (--tls-auth) */
if (options->tls_auth_file)
{

View File

@ -610,6 +610,10 @@ static const char usage_message[] =
#ifdef ENABLE_X509_TRACK
"--x509-track x : Save peer X509 attribute x in environment for use by\n"
" plugins and management interface.\n"
#endif
#if defined(ENABLE_CRYPTO_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10001000
"--keying-material-exporter label len : Save Exported Keying Material (RFC5705)\n"
" of len bytes (min. 16 bytes) using label in environment for use by plugins.\n"
#endif
"--remote-cert-ku v ... : Require that the peer certificate was signed with\n"
" explicit key usage, you can specify more than one value.\n"
@ -7066,6 +7070,29 @@ add_option (struct options *options,
options->use_peer_id = true;
options->peer_id = atoi(p[1]);
}
#if defined(ENABLE_CRYPTO_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10001000
else if (streq (p[0], "keying-material-exporter") && p[1] && p[2])
{
int ekm_length = positive_atoi (p[2]);
VERIFY_PERMISSION (OPT_P_GENERAL);
if (strncmp(p[1], "EXPORTER", 8))
{
msg (msglevel, "Keying material exporter label must begin with "
"\"EXPORTER\"");
goto err;
}
if (ekm_length < 16 || ekm_length > 4095)
{
msg (msglevel, "Invalid keying material exporter length");
goto err;
}
options->keying_material_exporter_label = p[1];
options->keying_material_exporter_length = ekm_length;
}
#endif
else
{
int i;

View File

@ -591,6 +591,12 @@ struct options
bool use_peer_id;
uint32_t peer_id;
#if defined(ENABLE_CRYPTO_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10001000
/* Keying Material Exporters [RFC 5705] */
const char *keying_material_exporter_label;
int keying_material_exporter_length;
#endif
};
#define streq(x, y) (!strcmp((x), (y)))

View File

@ -2160,8 +2160,12 @@ key_method_2_read (struct buffer *buf, struct tls_multi *multi, struct tls_sessi
*/
if (ks->authenticated && plugin_defined (session->opt->plugins, OPENVPN_PLUGIN_TLS_FINAL))
{
key_state_export_keying_material(&ks->ks_ssl, session);
if (plugin_call (session->opt->plugins, OPENVPN_PLUGIN_TLS_FINAL, NULL, NULL, session->opt->es) != OPENVPN_PLUGIN_FUNC_SUCCESS)
ks->authenticated = false;
setenv_del (session->opt->es, "exported_keying_material");
}
/*

View File

@ -334,6 +334,19 @@ void key_state_ssl_init(struct key_state_ssl *ks_ssl,
*/
void key_state_ssl_free(struct key_state_ssl *ks_ssl);
/**
* Keying Material Exporters [RFC 5705] allows additional keying material to be
* derived from existing TLS channel. This exported keying material can then be
* used for a variety of purposes.
*
* @param ks_ssl The SSL channel's state info
* @param session The session associated with the given key_state
*/
void
key_state_export_keying_material(struct key_state_ssl *ks_ssl,
struct tls_session *session) __attribute__((nonnull));
/**************************************************************************/
/** @addtogroup control_tls
* @{ */

View File

@ -317,6 +317,11 @@ struct tls_options
/* --gremlin bits */
int gremlin;
/* Keying Material Exporter [RFC 5705] parameters */
const char *ekm_label;
size_t ekm_label_size;
size_t ekm_size;
};
/** @addtogroup control_processor

View File

@ -133,6 +133,39 @@ bool tls_ctx_initialised(struct tls_root_ctx *ctx)
return NULL != ctx->ctx;
}
void
key_state_export_keying_material(struct key_state_ssl *ssl,
struct tls_session *session)
{
if (session->opt->ekm_size > 0)
{
#if (OPENSSL_VERSION_NUMBER >= 0x10001000)
unsigned int size = session->opt->ekm_size;
unsigned char ekm[size];
if (SSL_export_keying_material(ssl->ssl, ekm, sizeof(ekm),
session->opt->ekm_label, session->opt->ekm_label_size, NULL, 0, 0))
{
struct gc_arena gc = gc_new();
unsigned int len = (size * 2) + 2;
const char *key = format_hex_ex (ekm, size, len, 0, NULL, &gc);
setenv_str (session->opt->es, "exported_keying_material", key);
dmsg(D_TLS_DEBUG_MED, "%s: exported keying material: %s",
__func__, key);
gc_free(&gc);
}
else
{
msg (M_WARN, "WARNING: Export keying material failed!");
setenv_del (session->opt->es, "exported_keying_material");
}
#endif
}
}
/*
* Print debugging information on SSL/TLS session negotiation.
*/

View File

@ -148,6 +148,12 @@ tls_ctx_initialised(struct tls_root_ctx *ctx)
return ctx->initialised;
}
void
key_state_export_keying_material(struct key_state_ssl *ssl,
struct tls_session *session)
{
}
void
tls_ctx_set_options (struct tls_root_ctx *ctx, unsigned int ssl_flags)
{