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 <n...@rtfm.cz>
List-Post: openvpn-devel@lists.sourceforge.net
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(-)

diff --git a/src/openvpn/init.c b/src/openvpn/init.c
index 467b98a..90598ef 100644
--- a/src/openvpn/init.c
+++ b/src/openvpn/init.c
@@ -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)
     {
diff --git a/src/openvpn/options.c b/src/openvpn/options.c
index fe9b99d..8011c01 100644
--- a/src/openvpn/options.c
+++ b/src/openvpn/options.c
@@ -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;
diff --git a/src/openvpn/options.h b/src/openvpn/options.h
index 092eac4..dcf081e 100644
--- a/src/openvpn/options.h
+++ b/src/openvpn/options.h
@@ -602,6 +602,10 @@ struct options
   bool 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)))
diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c
index 9bcb2ac..49bd8c0 100644
--- a/src/openvpn/ssl.c
+++ b/src/openvpn/ssl.c
@@ -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;
     }
diff --git a/src/openvpn/ssl_common.h b/src/openvpn/ssl_common.h
index 04ba789..d12be0e 100644
--- a/src/openvpn/ssl_common.h
+++ b/src/openvpn/ssl_common.h
@@ -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;
diff --git a/src/openvpn/ssl_openssl.c b/src/openvpn/ssl_openssl.c
index 1481850..6ec7bcc 100644
--- a/src/openvpn/ssl_openssl.c
+++ b/src/openvpn/ssl_openssl.c
@@ -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.");
+    }
 }

 /*
-- 
1.7.1


>From 64bd4ead32cf304537eb006bf2b13ca1680ea5e1 Mon Sep 17 00:00:00 2001
From: Daniel Kubec <n...@rtfm.cz>
List-Post: openvpn-devel@lists.sourceforge.net
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(-)

diff --git a/doc/openvpn.8 b/doc/openvpn.8
index 34894e5..6f72b4e 100644
--- a/doc/openvpn.8
+++ b/doc/openvpn.8
@@ -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
-- 
1.7.1

Reply via email to