Keying Material Exporters [RFC 5705]
PATCH 1/1 Keying Material Exporters [RFC 5705]
TLS Keying Material Exporters [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.
TLS allows client and server to establish keying material for use in the upper layers between the TLS end-points. Channel Bindings is straitforward and well-defined mechanism how to authenticate other layers.
Following two attributes were added primary for the possible plugins extensions.
Attribute
tls_ekm: Exported Keying Material
Configuration
EKM is generated when *.ovpn contains following for each TLS negotiation.
example.ovpn:
{
# TLS Keying Material Exporter [RFC 5705]
#
# Note that exporter labels have the potential to collide with existing PRF
# labels. In order to prevent this, labels SHOULD begin with "EXPORTER". keying-material-exporter-label "EXPORTER_OPENVPN"
# Export len bytes of keying material (min. 20)
keying-material-exporter-length 20
}
Use Cases:
1) Authentication of upper layers (like Kerberos etc)
2) Authentication of VPN's TLS channel using QRCODE and device such as smartphones.
(Instead of user/pass dialog TLS VPN client could show for example QRCODE
based on keying material derivate)
3) Authentication of Binding Key in confidental side-channel can be also used and avoid/detect MITM (MITM provides his public key and that's reason why authentication of binding key will fail)
src/openvpn/init.c +8 -0
@@ -2307,6 +2307,13 @@ do_init_crypto_tls (struct context *c, const unsigned int flags)length prefix */ socket_adjust_frame_parameters (&to.frame, options->ce.proto); +/* Checking for required parameters for Channel Bindings */ + to.ekm_size = options->keying_material_exporter_length; + + to.ekm_label = (uint8_t *)options->keying_material_exporter_label; + to.ekm_label_size = to.ekm_label ?strlen (to.ekm_label) :0 ; + to.ekm_used = (to.ekm_label_size && to.ekm_size >=20 ) ? true : false; +/* * Initialize OpenVPN's master TLS-mode object. */
@@ -2315,6 +2322,7 @@ do_init_crypto_tls (struct context *c, const unsigned int flags)if (flags &CF_INIT_TLS_AUTH_STANDALONE ) c->c2.tls_auth_standalone =tls_auth_standalone_init (&to, &c->c2.gc); + } static void
src/openvpn/options.c +18 -0
@@ -6966,6 +6966,24 @@ add_option (struct options *options, options->persist_mode =1 ; }#endif + else if (streq (p[0], "keying-material-exporter-label") && p[1]) + { +if (strncmp (p[1 ],"EXPORTER" ,8 )) + { +msg (msglevel,"keying material exporter labels SHOULD begin with \"EXPORTER\"" ); + goto err; + } +VERIFY_PERMISSION (OPT_P_GENERAL ); + + options->keying_material_exporter_label = p[1 ]; + } + else if (streq (p[0], "keying-material-exporter-length")) + { +int len =positive_atoi (p[1 ]); +VERIFY_PERMISSION (OPT_P_GENERAL ); + + options->keying_material_exporter_length = len; + } else {int i;
src/openvpn/options.h +13 -7
@@ -30,26 +30,28 @@#ifndef OPTIONS_H #define OPTIONS_H +/* +* Maximum number of parameters associated with an option, +* including the option name itself. +*/ + +#define MAX_PARMS 16 +#include "basic.h" #include "common.h" #include "mtu.h" #include "route.h" #include "tun.h" #include "socket.h" +#include "comp.h" +#include "ssl_common.h" #include "plugin.h" #include "manage.h" #include "proxy.h" -#include "comp.h" #include "pushlist.h" #include "clinat.h" /* -* Maximum number of parameters associated with an option, -* including the option name itself. -*/ -#define MAX_PARMS 16 - -/* * Max size of options line and parameter. */ #define OPTION_PARM_SIZE 256
@@ -600,6 +602,10 @@ struct optionsbool show_net_up;int route_method;#endif + +/* Keying Material Exporters [RFC 5705] */ +const char *keying_material_exporter_label; +int keying_material_exporter_length; };#define streq (x, y) (!strcmp((x), (y)))
src/openvpn/ssl.c +5 -0
@@ -2126,6 +2126,11 @@ 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 )) { + +/* Exported Keying Material [RFC 5705] */ +if (session->opt->ekm_used) +setenv_str (session->opt->es,"tls_ekm" ,format_hex (session->ekm, session->ekm_size,0 , &gc)); +if (plugin_call (session->opt->plugins,OPENVPN_PLUGIN_TLS_FINAL ,NULL ,NULL , session->opt->es) !=OPENVPN_PLUGIN_FUNC_SUCCESS ) ks->authenticated = false; }
src/openvpn/ssl_common.h +16 -0
@@ -314,6 +314,12 @@ struct tls_options/* --gremlin bits */ int gremlin; + +/* Keying Material Exporter [RFC 5705] parameters */ +uint8_t *ekm_label; +int ekm_label_size; +bool ekm_used;/* true when Keying Material should be exported */ +int ekm_size; };/** @addtogroup control_processor
@@ -359,6 +365,16 @@ struct tls_sessionstruct crypto_options tls_auth;struct packet_id tls_auth_pid; +/* number of negotiations for this session */ +unsigned int negotiations; + +/* channel_id identifies TLS session across (re)negotiations */ +uint8_t channel_id[32 ]; + +/* Exported Keying Material [RFC 5705] */ +uint8_t *ekm; +int ekm_size; +int initial_opcode;/* our initial P_ opcode */ struct session_id session_id;/* our random session ID */ int key_id;/* increments with each soft reset (for key renegotiation) */
src/openvpn/ssl_openssl.c +24 -0
@@ -154,6 +154,30 @@ info_callback (INFO_CALLBACK_SSL_CONST SSL * s, int where, int ret)SSL_alert_type_string_long (ret), SSL_alert_desc_string_long (ret)); } +else if (where &SSL_CB_HANDSHAKE_DONE ) + { +struct tls_session *tls; + tls = (struct tls_session *)SSL_get_ex_data (s, mydata_index); + +if (tls->opt->ekm_used == false) + goto done; + +if (tls->ekm) +free (tls->ekm); + + tls->ekm_size = tls->opt->ekm_size; + tls->ekm =gc_malloc (tls->ekm_size, true,NULL ); + +SSL_export_keying_material ((SSL *)s, + tls->ekm, + tls->ekm_size, + tls->opt->ekm_label, + tls->opt->ekm_label_size, +NULL ,0 ,0 ); + +done: +msg (D_HANDSHAKE_VERBOSE ,"SSL Handshake done." ); + } }/*
Re: [Openvpn-devel] [PATCH] Keying Material Exporter [RFC 5705]
Updated patch.
vpn_binding_key:
- keying material derived by openvpn's crypto later (ssl.c:tls1_*)
- life time across negotiations (works a bit like EKM)
tls_ekm: Exported Keying Material [RFC 5705]
- derived when crypto backend support ( currently openssl >= 1.0.2 )
src/openvpn/init.c +8 -0
@@ -2307,6 +2307,13 @@ do_init_crypto_tls (struct context *c, const unsigned int flags)length prefix */ socket_adjust_frame_parameters (&to.frame, options->ce.proto); +/* Checking for required parameters for Channel Bindings */ + to.ekm_size = options->keying_material_exporter_length; + + to.ekm_label = (uint8_t *)options->keying_material_exporter_label; + to.ekm_label_size = to.ekm_label ?strlen (to.ekm_label) :0 ; + to.ekm_used = (to.ekm_label_size && to.ekm_size >=20 ) ? true : false; +/* * Initialize OpenVPN's master TLS-mode object. */
@@ -2315,6 +2322,7 @@ do_init_crypto_tls (struct context *c, const unsigned int flags)if (flags &CF_INIT_TLS_AUTH_STANDALONE ) c->c2.tls_auth_standalone =tls_auth_standalone_init (&to, &c->c2.gc); + } static void
src/openvpn/options.c +18 -0
@@ -6966,6 +6966,24 @@ add_option (struct options *options, options->persist_mode =1 ; }#endif + else if (streq (p[0], "keying-material-exporter-label") && p[1]) + { +if (strncmp (p[1 ],"EXPORTER" ,8 )) + { +msg (msglevel,"keying material exporter labels SHOULD begin with \"EXPORTER\"" ); + goto err; + } +VERIFY_PERMISSION (OPT_P_GENERAL ); + + options->keying_material_exporter_label = p[1 ]; + } + else if (streq (p[0], "keying-material-exporter-length")) + { +int len =positive_atoi (p[1 ]); +VERIFY_PERMISSION (OPT_P_GENERAL ); + + options->keying_material_exporter_length = len; + } else {int i;
src/openvpn/options.h +4 -0
@@ -600,6 +600,10 @@ struct optionsbool show_net_up;int route_method;#endif + +/* Keying Material Exporters [RFC 5705] */ +const char *keying_material_exporter_label; +int keying_material_exporter_length; };#define streq (x, y) (!strcmp((x), (y)))
src/openvpn/ssl.c +252 -50
409 lines not on this page · raw message
src/openvpn/ssl_common.h +15 -0
@@ -314,6 +314,12 @@ struct tls_options/* --gremlin bits */ int gremlin; + +/* Keying Material Exporter [RFC 5705] parameters */ +uint8_t *ekm_label; +int ekm_label_size; +bool ekm_used;/* true when Keying Material should be exported */ +int ekm_size; };/** @addtogroup control_processor
@@ -359,6 +365,15 @@ struct tls_sessionstruct crypto_options tls_auth;struct packet_id tls_auth_pid; +/* number of negotiations for this session */ +unsigned int negotiations; + +/* Exported Keying Material [RFC 5705] */ +uint8_t *ekm;/* buffer size: session->opt->ekm_size */ + +/* VPN's binding key derived by tls1_keying_material_exporter */ +uint8_t *binding_key;/* buffer size: session->opt->ekm_size */ +int initial_opcode;/* our initial P_ opcode */ struct session_id session_id;/* our random session ID */ int key_id;/* increments with each soft reset (for key renegotiation) */
src/openvpn/ssl_openssl.c +21 -0
@@ -154,6 +154,27 @@ info_callback (INFO_CALLBACK_SSL_CONST SSL * s, int where, int ret)SSL_alert_type_string_long (ret), SSL_alert_desc_string_long (ret)); } +else if (where &SSL_CB_HANDSHAKE_DONE ) + { +#if OPENSSL_VERSION_NUMBER >=0x0010002fL +struct tls_session *tls; + tls = (struct tls_session *)SSL_get_ex_data (s, mydata_index); + +if (tls->opt->ekm_used == false) + goto done; + +memset (tls->ekm,0 , tls->opt->ekm_size); + +SSL_export_keying_material ((SSL *)s, + tls->ekm, + tls->opt->ekm_size, + tls->opt->ekm_label, + tls->opt->ekm_label_size, +NULL ,0 ,0 ); +done: +#endif +msg (D_HANDSHAKE_VERBOSE ,"SSL Handshake done." ); + } }/*
Re: [Openvpn-devel] [PATCH] Keying Material Exporter [RFC 5705]
In reply to Daniel KubecUpdated patch:
- setenv_str() will set only valid tls_ekm attribute
src/openvpn/init.c +8 -0
@@ -2307,6 +2307,13 @@ do_init_crypto_tls (struct context *c, const unsigned int flags)length prefix */ socket_adjust_frame_parameters (&to.frame, options->ce.proto); +/* Checking for required parameters for Channel Bindings */ + to.ekm_size = options->keying_material_exporter_length; + + to.ekm_label = (uint8_t *)options->keying_material_exporter_label; + to.ekm_label_size = to.ekm_label ?strlen (to.ekm_label) :0 ; + to.ekm_used = (to.ekm_label_size && to.ekm_size >=20 ) ? true : false; +/* * Initialize OpenVPN's master TLS-mode object. */
@@ -2315,6 +2322,7 @@ do_init_crypto_tls (struct context *c, const unsigned int flags)if (flags &CF_INIT_TLS_AUTH_STANDALONE ) c->c2.tls_auth_standalone =tls_auth_standalone_init (&to, &c->c2.gc); + } static void
src/openvpn/options.c +18 -0
@@ -6966,6 +6966,24 @@ add_option (struct options *options, options->persist_mode =1 ; }#endif + else if (streq (p[0], "keying-material-exporter-label") && p[1]) + { +if (strncmp (p[1 ],"EXPORTER" ,8 )) + { +msg (msglevel,"keying material exporter labels SHOULD begin with \"EXPORTER\"" ); + goto err; + } +VERIFY_PERMISSION (OPT_P_GENERAL ); + + options->keying_material_exporter_label = p[1 ]; + } + else if (streq (p[0], "keying-material-exporter-length")) + { +int len =positive_atoi (p[1 ]); +VERIFY_PERMISSION (OPT_P_GENERAL ); + + options->keying_material_exporter_length = len; + } else {int i;
src/openvpn/options.h +4 -0
@@ -600,6 +600,10 @@ struct optionsbool show_net_up;int route_method;#endif + +/* Keying Material Exporters [RFC 5705] */ +const char *keying_material_exporter_label; +int keying_material_exporter_length; };#define streq (x, y) (!strcmp((x), (y)))
src/openvpn/ssl.c +262 -50
419 lines not on this page · raw message
src/openvpn/ssl_common.h +16 -0
@@ -314,6 +314,12 @@ struct tls_options/* --gremlin bits */ int gremlin; + +/* Keying Material Exporter [RFC 5705] parameters */ +uint8_t *ekm_label; +int ekm_label_size; +bool ekm_used;/* true when Keying Material should be exported */ +int ekm_size; };/** @addtogroup control_processor
@@ -359,6 +365,16 @@ struct tls_sessionstruct crypto_options tls_auth;struct packet_id tls_auth_pid; +/* number of negotiations for this session */ +unsigned int negotiations; + +/* Exported Keying Material [RFC 5705] */ +uint8_t *ekm;/* buffer size: session->opt->ekm_size */ +bool ekm_exported;/* true when ekm contains updated material */ + +/* VPN's binding key derived by tls1_keying_material_exporter */ +uint8_t *binding_key;/* buffer size: session->opt->ekm_size */ +int initial_opcode;/* our initial P_ opcode */ struct session_id session_id;/* our random session ID */ int key_id;/* increments with each soft reset (for key renegotiation) */
src/openvpn/ssl_openssl.c +22 -0
@@ -154,6 +154,28 @@ info_callback (INFO_CALLBACK_SSL_CONST SSL * s, int where, int ret)SSL_alert_type_string_long (ret), SSL_alert_desc_string_long (ret)); } +else if (where &SSL_CB_HANDSHAKE_DONE ) + { +struct tls_session *tls; + tls = (struct tls_session *)SSL_get_ex_data (s, mydata_index); + + tls->ekm_exported = false; +if (tls->opt->ekm_used == false) + goto done; + +memset (tls->ekm,0 , tls->opt->ekm_size); + +#if (OPENSSL_VERSION_NUMBER >0x10002000 ) + tls->ekm_exported = (bool )SSL_export_keying_material ((SSL *)s, + tls->ekm, + tls->opt->ekm_size, + tls->opt->ekm_label, + tls->opt->ekm_label_size, +NULL ,0 ,0 ); +#endif +done: +msg (D_HANDSHAKE_VERBOSE ,"SSL Handshake done." ); + } }/*
updated patch:
git format-patch -n HEAD^ --stdout > ./openvpn-channel-bindings.patch
vpn_binding_key:
- keying material derived by openvpn's crypto later (ssl.c:tls1_*)
- life time across negotiations (works a bit like EKM)
tls_binding_key: Exported Keying Material [RFC 5705]
- derived when crypto backend support ( currently openssl >= 1.0.2 )
From b577afe5c076b9f93ff6112c9efb7966f32f86a3 Mon Sep 17 00:00:00 2001
From: Daniel Kubec <[email protected]...>
Date: Thu, 24 Apr 2014 18:17:17 +0200
Subject: [PATCH 1/1] Channel Bindings based on Keying Material Exporters [RFC 5705]
--- src/openvpn/init.c | 8 ++ src/openvpn/options.c | 17 +++ src/openvpn/options.h | 4 + src/openvpn/ssl.c | 262 +++++++++++++++++++++++++++++++++++---------- src/openvpn/ssl_common.h | 13 +++ src/openvpn/ssl_openssl.c | 22 ++++ 6 files changed, 267 insertions(+), 59 deletions(-)
src/openvpn/init.c +8 -0
@@ -2292,6 +2292,13 @@ do_init_crypto_tls (struct context *c, const unsigned int flags) to.comp_options = options->comp;#endif +/* Checking for required parameters for Channel Bindings */ + to.ekm_size = options->keying_material_exporter_length; + to.ekm_label = (uint8_t *)options->keying_material_exporter_label; + to.ekm_label_size = to.ekm_label ?strlen (to.ekm_label) :0 ; + + to.ekm_used = (to.ekm_label_size && to.ekm_size >=20 ) ? true : false; +/* TLS handshake authentication (--tls-auth) */ if (options->tls_auth_file) {
@@ -2315,6 +2322,7 @@ do_init_crypto_tls (struct context *c, const unsigned int flags)if (flags &CF_INIT_TLS_AUTH_STANDALONE ) c->c2.tls_auth_standalone =tls_auth_standalone_init (&to, &c->c2.gc); + } static void
src/openvpn/options.c +17 -0
@@ -6984,6 +6984,23 @@ add_option (struct options *options, options->persist_mode =1 ; }#endif + else if (streq (p[0], "keying-material-exporter-label") && p[1]) + { +if (strncmp (p[1 ],"EXPORTER" ,8 )) + { +msg (msglevel,"keying material exporter labels SHOULD begin with \"EXPORTER\"" ); + goto err; + } +VERIFY_PERMISSION (OPT_P_GENERAL ); + options->keying_material_exporter_label = p[1 ]; + } + else if (streq (p[0], "keying-material-exporter-length")) + { +int len =positive_atoi (p[1 ]); +VERIFY_PERMISSION (OPT_P_GENERAL ); + + options->keying_material_exporter_length = len; + } else {int i;
src/openvpn/options.h +4 -0
@@ -600,6 +600,10 @@ struct optionsbool show_net_up;int route_method;#endif + +/* Keying Material Exporters [RFC 5705] */ +const char *keying_material_exporter_label; +int keying_material_exporter_length; };#define streq (x, y) (!strcmp((x), (y)))
src/openvpn/ssl.c +203 -59
331 lines not on this page · raw message
src/openvpn/ssl_common.h +13 -0
@@ -314,6 +314,12 @@ struct tls_options/* --gremlin bits */ int gremlin; + +/* Keying Material Exporter [RFC 5705] parameters */ +uint8_t *ekm_label; +int ekm_label_size; +bool ekm_used;/* true when Keying Material should be exported */ +int ekm_size; };/** @addtogroup control_processor
@@ -355,6 +361,13 @@ struct tls_session/* during hard reset used to control burst retransmit */ bool burst; +/* Exported Keying Material [RFC 5705] */ +uint8_t *ekm;/* buffer size: session->opt->ekm_size */ +bool ekm_exported;/* true when ekm contains updated material */ + +/* VPN's binding key derived by tls1_keying_material_exporter() */ +uint8_t *binding_key;/* buffer size: session->opt->ekm_size */ +/* authenticate control packets */ struct crypto_options tls_auth;struct packet_id tls_auth_pid;
src/openvpn/ssl_openssl.c +22 -0
@@ -154,6 +154,28 @@ info_callback (INFO_CALLBACK_SSL_CONST SSL * s, int where, int ret)SSL_alert_type_string_long (ret), SSL_alert_desc_string_long (ret)); } +else if (where &SSL_CB_HANDSHAKE_DONE ) + { +struct tls_session *tls; + tls = (struct tls_session *)SSL_get_ex_data (s, mydata_index); + + tls->ekm_exported = false; +if (tls->opt->ekm_used == false) + goto done; + +memset (tls->ekm,0 , tls->opt->ekm_size); + +#if (OPENSSL_VERSION_NUMBER >0x10002000 ) + tls->ekm_exported = (bool )SSL_export_keying_material ((SSL *)s, + tls->ekm, + tls->opt->ekm_size, + tls->opt->ekm_label, + tls->opt->ekm_label_size, +NULL ,0 ,0 ); +#endif +done: +msg (D_HANDSHAKE_VERBOSE ,"SSL Handshake done." ); + } }/*
Signature · 1 line
1.7.1
Hi Daniel,
Sorry for the delay, I've finally found some spare time to dig a bit into your patch. I've not looked at the implementation details yet, just the big picture for now.
First of all, I can see exported key material being useful. As a matter of fact, OpenVPN does something similar to derive its data channel keys.
Quoted 3 lines · Daniel Kubec
updated patch:
git format-patch -n HEAD^ --stdout > ./openvpn-channel-bindings.patch
It's probably easier if you create commits while doing work, and then use 'git format-patch origin/master' or 'git format-patch HEAD~n' (with n your number of commits). That generates patch files including your commit message, and are easy to apply using 'git am'.
Also, your patch does a number of things to achieve you goal; abstract some functions, add plugin calls, and do the actual export. Patches are more easily reviewed if those separate steps are separated into several commits (with each having a clear commit message describing the goal and the changes of the commit).
Quoted 6 lines
vpn_binding_key:
- keying material derived by openvpn's crypto later (ssl.c:tls1_*)
- life time across negotiations (works a bit like EKM)
tls_binding_key: Exported Keying Material [RFC 5705]
- derived when crypto backend support ( currently openssl >= 1.0.2 )
I'm not sure we should do the vpn_binding_key part, because:
1) I believe we should leave the crypto to the crypto libraries as much as possible. From this perspective I'd vote for just calling SSL_export_keying_material() if it's available (which according tot the OpenSSL ChangeLog / git tree is since 1.0.1, not 1.0.2). PolarSSL does not support EKM yet, so our PolarSSL builds just won't support it either. Just put that into the manpage, and we can add it when(/if) PolarSSL adds support too.
2) I think the exported keying material should *not* survive negotiations; negotiations by design force the endpoints to authenticate again, which should also be the case when using EKM.
3) As a positive side effect, the patch will add a lot less code to OpenVPN if vpn_binding_key is not added.
The new code calls the OPENVPN_PLUGIN_TLS_FINAL plugin twice (also from key_method_2_write() now), why is that? And (partly as a question to our plugin meister David), will that not break stuff for current plugin interface consumers?
Once the big picture is clear, I'll have to look more carefully at the implementation details.
-Steffan
PATCH 1/1 Keying Material Exporters [RFC 5705]
Hi Steffan,
Thank you for your comments.
Based on our previous conversation, I'd like to offer you splitted EKM patch without the vpn_binding_key attribute.
Later I'd like to discucess concept of TLS identifier which lives across negotiations.
Daniel
From d6c231cae830e1045c2debdb04a166e4b81f363e Mon Sep 17 00:00:00 2001
From: Daniel Kubec <[email protected]...>
Date: Wed, 14 May 2014 12:37:30 +0200
Subject: [PATCH 1/2] TLS 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.
--- src/openvpn/init.c | 8 ++++++++ src/openvpn/options.c | 19 +++++++++++++++++++ src/openvpn/options.h | 4 ++++ src/openvpn/ssl.c | 12 ++++++++++++ src/openvpn/ssl_common.h | 10 ++++++++++ src/openvpn/ssl_openssl.c | 30 ++++++++++++++++++++++++++++++ 6 files changed, 83 insertions(+), 0 deletions(-)
src/openvpn/init.c +8 -0
@@ -2294,6 +2294,14 @@ do_init_crypto_tls (struct context *c, const unsigned int flags) to.comp_options = options->comp;#endif +/* TLS Exported Keying Material [RFC 5705] */ + to.ekm_size = options->keying_material_exporter_length; + + to.ekm_label = (uint8_t *)options->keying_material_exporter_label; + to.ekm_label_size = to.ekm_label ?strlen (to.ekm_label) :0 ; + + to.ekm_used = (to.ekm_label_size && to.ekm_size >=20 ) ? true : false; +/* TLS handshake authentication (--tls-auth) */ if (options->tls_auth_file) {
src/openvpn/options.c +19 -0
@@ -639,6 +639,8 @@ static const char usage_message[] ="--remote-cert-tls t: Require that peer certificate was signed with explicit\n" " key usage and extended key usage based on RFC3280 TLS rules.\n" " t = 'client' | 'server'.\n" +"--keying-material-exporter-label l : Exported Keying Material Label RFC5705.\n" + "--keying-material-exporter-length l : Exported Keying Material Length RFC5705.\n"#endif /* ENABLE_SSL */ #ifdef ENABLE_PKCS11 "\n"
@@ -6995,6 +6997,23 @@ add_option (struct options *options, options->persist_mode =1 ; }#endif + else if (streq (p[0], "keying-material-exporter-label") && p[1]) + { +if (strncmp (p[1 ],"EXPORTER" ,8 )) + { +msg (msglevel,"keying material exporter labels SHOULD begin with \"EXPORTER\"" ); + goto err; + } +VERIFY_PERMISSION (OPT_P_GENERAL ); + options->keying_material_exporter_label = p[1 ]; + } + else if (streq (p[0], "keying-material-exporter-length")) + { +int len =positive_atoi (p[1 ]); +VERIFY_PERMISSION (OPT_P_GENERAL ); + + options->keying_material_exporter_length = len; + } else {int i;
src/openvpn/options.h +4 -0
@@ -602,6 +602,10 @@ struct optionsbool show_net_up;int route_method;#endif + +/* Keying Material Exporters [RFC 5705] */ +const char *keying_material_exporter_label; +int keying_material_exporter_length; };#define streq (x, y) (!strcmp((x), (y)))
src/openvpn/ssl.c +12 -0
@@ -891,6 +891,12 @@ tls_session_init (struct tls_multi *multi, struct tls_session *session) P_CONTROL_HARD_RESET_SERVER_V2 :P_CONTROL_HARD_RESET_CLIENT_V2 ; } +/* allocate buffers for Exported Keying Material [RFC 5705] */ + session->ekm =malloc (session->opt->ekm_size); + session->ekm_exported = false; + +memset (session->ekm,0 , session->opt->ekm_size); +/* Initialize control channel authentication parameters */ session->tls_auth = session->opt->tls_auth;
@@ -2131,6 +2137,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 )) { +const char *tls_binding_key =format_hex (session->ekm, session->opt->ekm_size,0 , &gc); +dmsg (M_INFO ,"TLS: Exported Keying Material [RFC5705] : length=%d, key=%s" , + session->opt->ekm_size, tls_binding_key); + +setenv_str (session->opt->es,"tls_binding_key" , tls_binding_key); +if (plugin_call (session->opt->plugins,OPENVPN_PLUGIN_TLS_FINAL ,NULL ,NULL , session->opt->es) !=OPENVPN_PLUGIN_FUNC_SUCCESS ) ks->authenticated = false; }
src/openvpn/ssl_common.h +10 -0
@@ -314,6 +314,12 @@ struct tls_options/* --gremlin bits */ int gremlin; + +/* Keying Material Exporter [RFC 5705] parameters */ +uint8_t *ekm_label; +int ekm_label_size; +bool ekm_used;/* true when Keying Material should be exported */ +int ekm_size; };/** @addtogroup control_processor
@@ -355,6 +361,10 @@ struct tls_session/* during hard reset used to control burst retransmit */ bool burst; +/* Exported Keying Material [RFC 5705] */ +uint8_t *ekm;/* buffer size: session->opt->ekm_size */ +bool ekm_exported;/* true when ekm contains updated material */ +/* authenticate control packets */ struct crypto_options tls_auth;struct packet_id tls_auth_pid;
src/openvpn/ssl_openssl.c +30 -0
@@ -134,6 +134,30 @@ bool tls_ctx_initialised(struct tls_root_ctx *ctx) }/* +* 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. +*/ + +static void +export_keying_material (const SSL *ssl) +{ +struct tls_session *tls =SSL_get_ex_data (ssl, mydata_index); +ASSERT (tls !=NULL ); + + tls->ekm_exported = false; + +#if (OPENSSL_VERSION_NUMBER >=0x10001000 ) + tls->ekm_exported = (bool )SSL_export_keying_material ((SSL *)ssl, + tls->ekm, + tls->opt->ekm_size, + tls->opt->ekm_label, + tls->opt->ekm_label_size, +NULL ,0 ,0 ); +#endif +} + +/* * Print debugging information on SSL/TLS session negotiation. */
@@ -157,6 +181,12 @@ info_callback (INFO_CALLBACK_SSL_CONST SSL * s, int where, int ret)SSL_alert_type_string_long (ret), SSL_alert_desc_string_long (ret)); } +else if (where &SSL_CB_HANDSHAKE_DONE ) + { +export_keying_material (s); + +dmsg (D_HANDSHAKE_VERBOSE ,"SSL handshake done." ); + } }/*
Signature · 19 lines
1.7.1 From 64bd4ead32cf304537eb006bf2b13ca1680ea5e1 Mon Sep 17 00:00:00 2001 From: Daniel Kubec <[email protected]...> Date: Wed, 14 May 2014 13:30:24 +0200 Subject: [PATCH 2/2] Updated doc/openvpn.8 Exported Keying Material [RFC5705] Parameters: keying-material-exporter-label keying-material-exporter-length Output: tls_binding_key --- doc/openvpn.8 | 16 ++++++++++++++++ 1 files changed, 16 insertions(+), 0 deletions(-)
doc/openvpn.8 +16 -0
@@ -2691,6 +2691,17 @@ 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 label [RFC 5705] +Labels here have the same definition as in TLS, i.e., an ASCII string with no +terminating NULL. Note that exporter labels have the potential to collide with +existing PRF labels. In order to prevent this, labels MUST begin with +"EXPORTER". +.\"********************************************************* +.TP +.B \-\-keying-material-exporter-length length [RFC 5705] +The output is a pseudorandom bit string of length bytes derived from TLS. +.\"********************************************************* .SS Server Mode Starting with OpenVPN 2.0, a multi-client TCP/UDP server mode is supported, and can be enabled with the
@@ -6116,6 +6127,11 @@ Like but in hex form (e.g. "12:34:56:78:9A"). .\"********************************************************* .TP +.B tls_binding_key +TLS Binding Key is a pseudorandom hex string based on Exported Keying Material +[RFC 5705]. +.\"********************************************************* +.TP .B tun_mtu The MTU of the TUN/TAP device. Set prior to
Signature · 1 line
1.7.1