Message ID | 20201009115453.4279-1-arne@rfc2549.org |
---|---|
State | Accepted |
Headers | show |
Series | [Openvpn-devel,v5] Implement generating data channel keys via EKM/RFC 5705 | expand |
Hi, On 09-10-2020 13:54, Arne Schwabe wrote: > OpenVPN currently uses its own (based on TLS 1.0) key derivation > mechanism to generate the 256 bytes key data in key2 struct that > are then used used to generate encryption/hmac/iv vectors. While > this mechanism is still secure, it is not state of the art. > > Instead of modernising our own approach, this commit implements > key derivation using the Keying Material Exporters API introduced > by RFC 5705. > > We also use an opportunistic approach of negotiating the use of > EKM (exported key material) through an IV_PROTO flag and prefer > EKM to our own PRF if both client and server support it. The > use of EKM is pushed to the client as part of NCP as > key-derivation tls-ekm. > > We still exchange the random data (112 bytes from client to server > and 64 byte from server to client) for the OpenVPN PRF but > do not use it. Removing that exchange would break the handshake > and make a key-method 3 or similar necessary. > > As a side effect, this makes a little bit easier to have a FIPS compatible > version of OpenVPN since we do not rely on calling MD5 anymore. > > Side note: this commit breaks the (not yet merged) WolfSSL support as it > claims to support EKM in the OpenSSL compat API but always returns an error > if you try to use it. > > Signed-off-by: Arne Schwabe <arne@rfc2549.org> > > Patch v2: rebase/change to V2 of EKM refactoring > > Patch v3: add Changes.rst > > Patch v4: Rebase on master. > > Patch v5: Refuse internal label to be used with --keying-material-exporter, > polishing/fixes suggested by Steffan integrated > > Signed-off-by: Arne Schwabe <arne@rfc2549.org> Still the duplicate signed-off line. But that's easy enough to fix at commit time I guess. > --- > Changes.rst | 11 +++++++ > doc/doxygen/doc_key_generation.h | 14 +++++++-- > src/openvpn/crypto.h | 4 +++ > src/openvpn/init.c | 1 + > src/openvpn/multi.c | 4 +++ > src/openvpn/options.c | 19 +++++++++++ > src/openvpn/options.h | 3 ++ > src/openvpn/push.c | 5 ++- > src/openvpn/ssl.c | 54 ++++++++++++++++++++++++++++---- > src/openvpn/ssl.h | 2 ++ > src/openvpn/ssl_backend.h | 1 + > src/openvpn/ssl_mbedtls.c | 7 ++--- > 12 files changed, 111 insertions(+), 14 deletions(-) > > diff --git a/Changes.rst b/Changes.rst > index f67e1d76..2a2829e7 100644 > --- a/Changes.rst > +++ b/Changes.rst > @@ -1,3 +1,14 @@ > +Overview of changes in 2.6 > +========================== > + > + > +New features > +------------ > +Keying Material Exporters (RFC 5705) based key generation > + As part of the cipher negotiation OpenVPN will automatically prefer > + the RFC5705 based key material generation to the current custom > + OpenVPN PRF. This feature requires OpenSSL or mbed TLS 2.18+. > + > Overview of changes in 2.5 > ========================== > > diff --git a/doc/doxygen/doc_key_generation.h b/doc/doxygen/doc_key_generation.h > index 4bb9c708..cef773a9 100644 > --- a/doc/doxygen/doc_key_generation.h > +++ b/doc/doxygen/doc_key_generation.h > @@ -58,6 +58,12 @@ > * > * @subsection key_generation_method_2 Key method 2 > * > + * There are two methods for generating key data when using key method 2 > + * the first is OpenVPN's traditional approach that exchanges random > + * data and uses a PRF and the other is using the RFC5705 keying material > + * exporter to generate the key material. For both methods the random > + * data is exchange but only used in the traditional method. > + * > * -# The client generates random material in the following amounts: > * - Pre-master secret: 48 bytes > * - Client's PRF seed for master secret: 32 bytes > @@ -73,8 +79,12 @@ > * server's random material. > * > * %Key method 2 %key expansion is performed by the \c > - * generate_key_expansion() function. Please refer to its source code for > - * details of the %key expansion process. > + * generate_key_expansion_oepnvpn_prf() function. Please refer to its source What is this oepnvpn your are talking about? :-p (Interesting how you managed to re-introduce this typo from v4 to v5...) > + * code for details of the %key expansion process. > + * > + * When the client sends the IV_PROTO_TLS_KEY_EXPORT flag and the server replies > + * with `key-derivation tls-ekm` the RFC5705 key material exporter with the > + * label EXPORTER-OpenVPN-datakeys is used for the key data. > * > * @subsection key_generation_random Source of random material > * > diff --git a/src/openvpn/crypto.h b/src/openvpn/crypto.h > index 999f643e..1ad669ce 100644 > --- a/src/openvpn/crypto.h > +++ b/src/openvpn/crypto.h > @@ -254,6 +254,10 @@ struct crypto_options > #define CO_MUTE_REPLAY_WARNINGS (1<<2) > /**< Bit-flag indicating not to display > * replay warnings. */ > +#define CO_USE_TLS_KEY_MATERIAL_EXPORT (1<<3) > + /**< Bit-flag indicating that data channel key derivation > + * is done using TLS keying material export [RFC5705] > + */ > unsigned int flags; /**< Bit-flags determining behavior of > * security operation functions. */ > }; > diff --git a/src/openvpn/init.c b/src/openvpn/init.c > index f87c11e7..580a8550 100644 > --- a/src/openvpn/init.c > +++ b/src/openvpn/init.c > @@ -687,6 +687,7 @@ restore_ncp_options(struct context *c) > c->options.ciphername = c->c1.ciphername; > c->options.authname = c->c1.authname; > c->options.keysize = c->c1.keysize; > + c->options.data_channel_use_ekm = false; > } > > void > diff --git a/src/openvpn/multi.c b/src/openvpn/multi.c > index 13738180..a5862020 100644 > --- a/src/openvpn/multi.c > +++ b/src/openvpn/multi.c > @@ -1817,6 +1817,10 @@ multi_client_set_protocol_options(struct context *c) > c->c2.push_request_received = true; > } > > +#ifdef HAVE_EXPORT_KEYING_MATERIAL > + o->data_channel_use_ekm = (proto & IV_PROTO_TLS_KEY_EXPORT); > +#endif > + > /* Select cipher if client supports Negotiable Crypto Parameters */ > if (!o->ncp_enabled) > { > diff --git a/src/openvpn/options.c b/src/openvpn/options.c > index 772323df..4e19d7cb 100644 > --- a/src/openvpn/options.c > +++ b/src/openvpn/options.c > @@ -7979,6 +7979,20 @@ add_option(struct options *options, > } > options->ncp_ciphers = p[1]; > } > + else if (streq(p[0], "key-derivation") && p[1]) > + { > + VERIFY_PERMISSION(OPT_P_NCP) > +#ifdef HAVE_EXPORT_KEYING_MATERIAL > + if (streq(p[1], "tls-ekm")) > + { > + options->data_channel_use_ekm = true; > + } > + else > +#endif > + { > + msg(msglevel, "Unknown key-derivation method %s", p[1]); > + } > + } > else if (streq(p[0], "ncp-disable") && !p[1]) > { > VERIFY_PERMISSION(OPT_P_GENERAL|OPT_P_INSTANCE); > @@ -8707,6 +8721,11 @@ add_option(struct options *options, > "\"EXPORTER\""); > goto err; > } > + if (streq(p[1], EXPORT_KEY_DATA_LABEL)) > + { > + msg(msglevel, "Keying material exporter label must not be '" > + EXPORT_KEY_DATA_LABEL "'."); > + } > if (ekm_length < 16 || ekm_length > 4095) > { > msg(msglevel, "Invalid keying material exporter length"); > diff --git a/src/openvpn/options.h b/src/openvpn/options.h > index e527d70e..5d977793 100644 > --- a/src/openvpn/options.h > +++ b/src/openvpn/options.h > @@ -648,6 +648,9 @@ struct options > /* Useful when packets sent by openvpn itself are not subject > * to the routing tables that would move packets into the tunnel. */ > bool allow_recursive_routing; > + > + /* Use RFC5705 key export to generate data channel keys */ > + bool data_channel_use_ekm; > }; > > #define streq(x, y) (!strcmp((x), (y))) > diff --git a/src/openvpn/push.c b/src/openvpn/push.c > index e0d2eeaf..17bba948 100644 > --- a/src/openvpn/push.c > +++ b/src/openvpn/push.c > @@ -479,7 +479,10 @@ prepare_push_reply(struct context *c, struct gc_arena *gc, > { > push_option_fmt(gc, push_list, M_USAGE, "cipher %s", o->ciphername); > } > - > + if (o->data_channel_use_ekm) > + { > + push_option_fmt(gc, push_list, M_USAGE, "key-derivation tls-ekm"); > + } > return true; > } > > diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c > index f90c6a85..b572b7b8 100644 > --- a/src/openvpn/ssl.c > +++ b/src/openvpn/ssl.c > @@ -1783,6 +1783,29 @@ init_key_contexts(struct key_ctx_bi *key, > > } > > +static bool > +generate_key_expansion_tls_export(struct tls_session *session, struct key2 *key2) > +{ > + struct gc_arena gc = gc_new(); > + unsigned char *key2data; > + > + key2data = key_state_export_keying_material(session, > + EXPORT_KEY_DATA_LABEL, > + strlen(EXPORT_KEY_DATA_LABEL), > + sizeof(key2->keys), > + &gc); > + if (!key2data) > + { > + return false; > + } > + memcpy(key2->keys, key2data, sizeof(key2->keys)); > + secure_memzero(key2data, sizeof(key2->keys)); > + key2->n = 2; > + > + gc_free(&gc); > + return true; > +} > + > static struct key2 > generate_key_expansion_openvpn_prf(const struct tls_session *session) > { > @@ -1854,7 +1877,7 @@ generate_key_expansion_openvpn_prf(const struct tls_session *session) > */ > static bool > generate_key_expansion(struct key_ctx_bi *key, > - const struct tls_session *session) > + struct tls_session *session) > { > bool ret = false; > struct key2 key2; > @@ -1865,10 +1888,20 @@ generate_key_expansion(struct key_ctx_bi *key, > goto exit; > } > > - > bool server = session->opt->server; > > - key2 = generate_key_expansion_openvpn_prf(session); > + if (session->opt->crypto_flags & CO_USE_TLS_KEY_MATERIAL_EXPORT) > + { > + if (!generate_key_expansion_tls_export(session, &key2)) > + { > + msg(D_TLS_ERRORS, "TLS Error: Keying material export failed"); > + goto exit; > + } > + } > + else > + { > + key2 = generate_key_expansion_openvpn_prf(session); > + } > > key2_print(&key2, &session->opt->key_type, > "Master Encrypt", "Master Decrypt"); > @@ -1967,6 +2000,11 @@ tls_session_update_crypto_params(struct tls_session *session, > return false; > } > > + if (options->data_channel_use_ekm) > + { > + session->opt->crypto_flags |= CO_USE_TLS_KEY_MATERIAL_EXPORT; > + } > + > if (strcmp(options->ciphername, session->opt->config_ciphername)) > { > msg(D_HANDSHAKE, "Data Channel: using negotiated cipher '%s'", > @@ -2251,13 +2289,11 @@ push_peer_info(struct buffer *buf, struct tls_session *session) > * push request, also signal that the client wants > * to get push-reply messages without without requiring a round > * trip for a push request message*/ > - if(session->opt->pull) > + if (session->opt->pull) > { > iv_proto |= IV_PROTO_REQUEST_PUSH; > } > > - buf_printf(&out, "IV_PROTO=%d\n", iv_proto); > - > /* support for Negotiable Crypto Parameters */ > if (session->opt->ncp_enabled > && (session->opt->mode == MODE_SERVER || session->opt->pull)) > @@ -2269,8 +2305,14 @@ push_peer_info(struct buffer *buf, struct tls_session *session) > buf_printf(&out, "IV_NCP=2\n"); > } > buf_printf(&out, "IV_CIPHERS=%s\n", session->opt->config_ncp_ciphers); > + > +#ifdef HAVE_EXPORT_KEYING_MATERIAL > + iv_proto |= IV_PROTO_TLS_KEY_EXPORT; > +#endif > } > > + buf_printf(&out, "IV_PROTO=%d\n", iv_proto); > + > /* push compression status */ > #ifdef USE_COMP > comp_generate_peer_info_string(&session->opt->comp_options, &out); > diff --git a/src/openvpn/ssl.h b/src/openvpn/ssl.h > index 005628f6..f00f8abd 100644 > --- a/src/openvpn/ssl.h > +++ b/src/openvpn/ssl.h > @@ -116,6 +116,8 @@ > * to wait for a push-request to send a push-reply */ > #define IV_PROTO_REQUEST_PUSH (1<<2) > > +/** Supports key derivation via TLS key material exporter [RFC5705] */ > +#define IV_PROTO_TLS_KEY_EXPORT (1<<3) > > /* Default field in X509 to be username */ > #define X509_USERNAME_FIELD_DEFAULT "CN" > diff --git a/src/openvpn/ssl_backend.h b/src/openvpn/ssl_backend.h > index cf9fba25..4bcb3181 100644 > --- a/src/openvpn/ssl_backend.h > +++ b/src/openvpn/ssl_backend.h > @@ -389,6 +389,7 @@ void key_state_ssl_free(struct key_state_ssl *ks_ssl); > void backend_tls_ctx_reload_crl(struct tls_root_ctx *ssl_ctx, > const char *crl_file, bool crl_inline); > > +#define EXPORT_KEY_DATA_LABEL "EXPORTER-OpenVPN-datakeys" > /** > * Keying Material Exporters [RFC 5705] allows additional keying material to be > * derived from existing TLS channel. This exported keying material can then be > diff --git a/src/openvpn/ssl_mbedtls.c b/src/openvpn/ssl_mbedtls.c > index 4ec355a9..f375e957 100644 > --- a/src/openvpn/ssl_mbedtls.c > +++ b/src/openvpn/ssl_mbedtls.c > @@ -1168,11 +1168,8 @@ key_state_ssl_init(struct key_state_ssl *ks_ssl, > > #ifdef HAVE_EXPORT_KEYING_MATERIAL > /* Initialize keying material exporter */ > - if (session->opt->ekm_size) > - { > - mbedtls_ssl_conf_export_keys_ext_cb(ks_ssl->ssl_config, > - mbedtls_ssl_export_keys_cb, session); > - } > + mbedtls_ssl_conf_export_keys_ext_cb(ks_ssl->ssl_config, > + mbedtls_ssl_export_keys_cb, session); > #endif > > /* Initialise SSL context */ > If the above is fixed: Acked-by: Steffan Karger <steffan@karger.me> -Steffan
In addition to the thorough review from Steffan, I have tortured this patch on the client and server side (read: patched client talking to an old server, old clients talking to a patched server, patched client talking to patched server, with/without NCP) and everything succeeded/failed as expected. I have actually seen the handshake happen between openssl client and server, and mbedtls 2.24.0 (gentoo) client / openssl server (I have not checked if the handshake had any actual *effect*, just if I could see it in the PUSH_REPLY message, and that ping worked afterwards). "PUSH_REPLY ... cipher none,key-derivation tls-ekm" looks weird :-) Your patch has been applied to the master branch. commit 6dc09d0d4520483716530e12a444b156720cdfcc Author: Arne Schwabe Date: Fri Oct 9 13:54:53 2020 +0200 Implement generating data channel keys via EKM/RFC 5705 Signed-off-by: Arne Schwabe <arne@rfc2549.org> Acked-by: Steffan Karger <steffan.karger@foxcrypto.com> Message-Id: <20201009115453.4279-1-arne@rfc2549.org> URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg21187.html Signed-off-by: Gert Doering <gert@greenie.muc.de> -- kind regards, Gert Doering
diff --git a/Changes.rst b/Changes.rst index f67e1d76..2a2829e7 100644 --- a/Changes.rst +++ b/Changes.rst @@ -1,3 +1,14 @@ +Overview of changes in 2.6 +========================== + + +New features +------------ +Keying Material Exporters (RFC 5705) based key generation + As part of the cipher negotiation OpenVPN will automatically prefer + the RFC5705 based key material generation to the current custom + OpenVPN PRF. This feature requires OpenSSL or mbed TLS 2.18+. + Overview of changes in 2.5 ========================== diff --git a/doc/doxygen/doc_key_generation.h b/doc/doxygen/doc_key_generation.h index 4bb9c708..cef773a9 100644 --- a/doc/doxygen/doc_key_generation.h +++ b/doc/doxygen/doc_key_generation.h @@ -58,6 +58,12 @@ * * @subsection key_generation_method_2 Key method 2 * + * There are two methods for generating key data when using key method 2 + * the first is OpenVPN's traditional approach that exchanges random + * data and uses a PRF and the other is using the RFC5705 keying material + * exporter to generate the key material. For both methods the random + * data is exchange but only used in the traditional method. + * * -# The client generates random material in the following amounts: * - Pre-master secret: 48 bytes * - Client's PRF seed for master secret: 32 bytes @@ -73,8 +79,12 @@ * server's random material. * * %Key method 2 %key expansion is performed by the \c - * generate_key_expansion() function. Please refer to its source code for - * details of the %key expansion process. + * generate_key_expansion_oepnvpn_prf() function. Please refer to its source + * code for details of the %key expansion process. + * + * When the client sends the IV_PROTO_TLS_KEY_EXPORT flag and the server replies + * with `key-derivation tls-ekm` the RFC5705 key material exporter with the + * label EXPORTER-OpenVPN-datakeys is used for the key data. * * @subsection key_generation_random Source of random material * diff --git a/src/openvpn/crypto.h b/src/openvpn/crypto.h index 999f643e..1ad669ce 100644 --- a/src/openvpn/crypto.h +++ b/src/openvpn/crypto.h @@ -254,6 +254,10 @@ struct crypto_options #define CO_MUTE_REPLAY_WARNINGS (1<<2) /**< Bit-flag indicating not to display * replay warnings. */ +#define CO_USE_TLS_KEY_MATERIAL_EXPORT (1<<3) + /**< Bit-flag indicating that data channel key derivation + * is done using TLS keying material export [RFC5705] + */ unsigned int flags; /**< Bit-flags determining behavior of * security operation functions. */ }; diff --git a/src/openvpn/init.c b/src/openvpn/init.c index f87c11e7..580a8550 100644 --- a/src/openvpn/init.c +++ b/src/openvpn/init.c @@ -687,6 +687,7 @@ restore_ncp_options(struct context *c) c->options.ciphername = c->c1.ciphername; c->options.authname = c->c1.authname; c->options.keysize = c->c1.keysize; + c->options.data_channel_use_ekm = false; } void diff --git a/src/openvpn/multi.c b/src/openvpn/multi.c index 13738180..a5862020 100644 --- a/src/openvpn/multi.c +++ b/src/openvpn/multi.c @@ -1817,6 +1817,10 @@ multi_client_set_protocol_options(struct context *c) c->c2.push_request_received = true; } +#ifdef HAVE_EXPORT_KEYING_MATERIAL + o->data_channel_use_ekm = (proto & IV_PROTO_TLS_KEY_EXPORT); +#endif + /* Select cipher if client supports Negotiable Crypto Parameters */ if (!o->ncp_enabled) { diff --git a/src/openvpn/options.c b/src/openvpn/options.c index 772323df..4e19d7cb 100644 --- a/src/openvpn/options.c +++ b/src/openvpn/options.c @@ -7979,6 +7979,20 @@ add_option(struct options *options, } options->ncp_ciphers = p[1]; } + else if (streq(p[0], "key-derivation") && p[1]) + { + VERIFY_PERMISSION(OPT_P_NCP) +#ifdef HAVE_EXPORT_KEYING_MATERIAL + if (streq(p[1], "tls-ekm")) + { + options->data_channel_use_ekm = true; + } + else +#endif + { + msg(msglevel, "Unknown key-derivation method %s", p[1]); + } + } else if (streq(p[0], "ncp-disable") && !p[1]) { VERIFY_PERMISSION(OPT_P_GENERAL|OPT_P_INSTANCE); @@ -8707,6 +8721,11 @@ add_option(struct options *options, "\"EXPORTER\""); goto err; } + if (streq(p[1], EXPORT_KEY_DATA_LABEL)) + { + msg(msglevel, "Keying material exporter label must not be '" + EXPORT_KEY_DATA_LABEL "'."); + } if (ekm_length < 16 || ekm_length > 4095) { msg(msglevel, "Invalid keying material exporter length"); diff --git a/src/openvpn/options.h b/src/openvpn/options.h index e527d70e..5d977793 100644 --- a/src/openvpn/options.h +++ b/src/openvpn/options.h @@ -648,6 +648,9 @@ struct options /* Useful when packets sent by openvpn itself are not subject * to the routing tables that would move packets into the tunnel. */ bool allow_recursive_routing; + + /* Use RFC5705 key export to generate data channel keys */ + bool data_channel_use_ekm; }; #define streq(x, y) (!strcmp((x), (y))) diff --git a/src/openvpn/push.c b/src/openvpn/push.c index e0d2eeaf..17bba948 100644 --- a/src/openvpn/push.c +++ b/src/openvpn/push.c @@ -479,7 +479,10 @@ prepare_push_reply(struct context *c, struct gc_arena *gc, { push_option_fmt(gc, push_list, M_USAGE, "cipher %s", o->ciphername); } - + if (o->data_channel_use_ekm) + { + push_option_fmt(gc, push_list, M_USAGE, "key-derivation tls-ekm"); + } return true; } diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c index f90c6a85..b572b7b8 100644 --- a/src/openvpn/ssl.c +++ b/src/openvpn/ssl.c @@ -1783,6 +1783,29 @@ init_key_contexts(struct key_ctx_bi *key, } +static bool +generate_key_expansion_tls_export(struct tls_session *session, struct key2 *key2) +{ + struct gc_arena gc = gc_new(); + unsigned char *key2data; + + key2data = key_state_export_keying_material(session, + EXPORT_KEY_DATA_LABEL, + strlen(EXPORT_KEY_DATA_LABEL), + sizeof(key2->keys), + &gc); + if (!key2data) + { + return false; + } + memcpy(key2->keys, key2data, sizeof(key2->keys)); + secure_memzero(key2data, sizeof(key2->keys)); + key2->n = 2; + + gc_free(&gc); + return true; +} + static struct key2 generate_key_expansion_openvpn_prf(const struct tls_session *session) { @@ -1854,7 +1877,7 @@ generate_key_expansion_openvpn_prf(const struct tls_session *session) */ static bool generate_key_expansion(struct key_ctx_bi *key, - const struct tls_session *session) + struct tls_session *session) { bool ret = false; struct key2 key2; @@ -1865,10 +1888,20 @@ generate_key_expansion(struct key_ctx_bi *key, goto exit; } - bool server = session->opt->server; - key2 = generate_key_expansion_openvpn_prf(session); + if (session->opt->crypto_flags & CO_USE_TLS_KEY_MATERIAL_EXPORT) + { + if (!generate_key_expansion_tls_export(session, &key2)) + { + msg(D_TLS_ERRORS, "TLS Error: Keying material export failed"); + goto exit; + } + } + else + { + key2 = generate_key_expansion_openvpn_prf(session); + } key2_print(&key2, &session->opt->key_type, "Master Encrypt", "Master Decrypt"); @@ -1967,6 +2000,11 @@ tls_session_update_crypto_params(struct tls_session *session, return false; } + if (options->data_channel_use_ekm) + { + session->opt->crypto_flags |= CO_USE_TLS_KEY_MATERIAL_EXPORT; + } + if (strcmp(options->ciphername, session->opt->config_ciphername)) { msg(D_HANDSHAKE, "Data Channel: using negotiated cipher '%s'", @@ -2251,13 +2289,11 @@ push_peer_info(struct buffer *buf, struct tls_session *session) * push request, also signal that the client wants * to get push-reply messages without without requiring a round * trip for a push request message*/ - if(session->opt->pull) + if (session->opt->pull) { iv_proto |= IV_PROTO_REQUEST_PUSH; } - buf_printf(&out, "IV_PROTO=%d\n", iv_proto); - /* support for Negotiable Crypto Parameters */ if (session->opt->ncp_enabled && (session->opt->mode == MODE_SERVER || session->opt->pull)) @@ -2269,8 +2305,14 @@ push_peer_info(struct buffer *buf, struct tls_session *session) buf_printf(&out, "IV_NCP=2\n"); } buf_printf(&out, "IV_CIPHERS=%s\n", session->opt->config_ncp_ciphers); + +#ifdef HAVE_EXPORT_KEYING_MATERIAL + iv_proto |= IV_PROTO_TLS_KEY_EXPORT; +#endif } + buf_printf(&out, "IV_PROTO=%d\n", iv_proto); + /* push compression status */ #ifdef USE_COMP comp_generate_peer_info_string(&session->opt->comp_options, &out); diff --git a/src/openvpn/ssl.h b/src/openvpn/ssl.h index 005628f6..f00f8abd 100644 --- a/src/openvpn/ssl.h +++ b/src/openvpn/ssl.h @@ -116,6 +116,8 @@ * to wait for a push-request to send a push-reply */ #define IV_PROTO_REQUEST_PUSH (1<<2) +/** Supports key derivation via TLS key material exporter [RFC5705] */ +#define IV_PROTO_TLS_KEY_EXPORT (1<<3) /* Default field in X509 to be username */ #define X509_USERNAME_FIELD_DEFAULT "CN" diff --git a/src/openvpn/ssl_backend.h b/src/openvpn/ssl_backend.h index cf9fba25..4bcb3181 100644 --- a/src/openvpn/ssl_backend.h +++ b/src/openvpn/ssl_backend.h @@ -389,6 +389,7 @@ void key_state_ssl_free(struct key_state_ssl *ks_ssl); void backend_tls_ctx_reload_crl(struct tls_root_ctx *ssl_ctx, const char *crl_file, bool crl_inline); +#define EXPORT_KEY_DATA_LABEL "EXPORTER-OpenVPN-datakeys" /** * Keying Material Exporters [RFC 5705] allows additional keying material to be * derived from existing TLS channel. This exported keying material can then be diff --git a/src/openvpn/ssl_mbedtls.c b/src/openvpn/ssl_mbedtls.c index 4ec355a9..f375e957 100644 --- a/src/openvpn/ssl_mbedtls.c +++ b/src/openvpn/ssl_mbedtls.c @@ -1168,11 +1168,8 @@ key_state_ssl_init(struct key_state_ssl *ks_ssl, #ifdef HAVE_EXPORT_KEYING_MATERIAL /* Initialize keying material exporter */ - if (session->opt->ekm_size) - { - mbedtls_ssl_conf_export_keys_ext_cb(ks_ssl->ssl_config, - mbedtls_ssl_export_keys_cb, session); - } + mbedtls_ssl_conf_export_keys_ext_cb(ks_ssl->ssl_config, + mbedtls_ssl_export_keys_cb, session); #endif /* Initialise SSL context */