Skip to contentSkip to conversation

Channel Binding Key based on Keying Material Exporters [RFC 5705]

PATCH New Daniel Kubec 1 participant 1 message Apr 17, 2014

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 Channel Binding Key based on Keying Material Exporters [RFC 5705]

Channel Binding Key based on 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.

Attributes

tls_channel_id: Identifies TLS Sessions across (re)negotiation
tls_binding_key: Secret crypto derivate based on Keying Material Exporters

Configuration

TLS Binding Key is generated when *.ovpn contains following for each TLS negotiation.

example.ovpn:
{
# Channel Binding based on 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".
# This is not a MUST because there are existing uses that have labels
which do
# not begin with this prefix.
keying-material-exporter-label "EXPORTER_OPENVPN"

# Export len bytes of keying material (min. 20)
keying-material-exporter-length 20
}

Changes

This patch stays on top of crypto layer and that's reason why it will work for
both crypto backends (openssl/polarssl).

TLS_FINAL Plugin was called in key_method_2_read() before server_random was generated for the TLS server end-point and that's the reason why it's called at
2 places now. key_method_2_read() for server and key_method_2_write() for client.

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 +11 -0
index c2907cd..8b57419 100644
@@ -2307,6 +2307,16 @@ 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.binding_key_size = options->keying_material_exporter_length;
+
+  to.kme_label = (uint8_t*)options->keying_material_exporter_label;
+  to.kme_label_size = to.kme_label ? strlen(to.kme_label) : 0;
+
+  to.binding_key_size = options->keying_material_exporter_length;
+  to.binding_key_gen = (to.kme_label_size && to.binding_key_size >= 20) ?
+                        true : false;
+
   /*
    * Initialize OpenVPN's master TLS-mode object.
    */
@@ -2315,6 +2325,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
index 18cb354..5323cd7 100644
@@ -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
index ec1d091..f5609f9 100644
@@ -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 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)))
src/openvpn/ssl.c +315 -50

460 lines not on this page · raw message

src/openvpn/ssl_common.h +12 -0
index 04ba789..9af68bc 100644
@@ -314,6 +314,12 @@ struct tls_options
 
   /* --gremlin bits */
   int gremlin;
+
+  /* Keying Material Exporter [RFC 5705] parameters */
+  uint8_t *kme_label;
+  int kme_label_size;
+  bool binding_key_gen; /* true when binding key should be generated */
+  int binding_key_size;
 };
 
 /** @addtogroup control_processor
@@ -359,6 +365,12 @@ struct tls_session
   struct 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];                 
+
   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) */