diff options
author | Daniel Kubec <niel@rtfm.cz> | 2015-03-12 15:14:20 +0100 |
---|---|---|
committer | David Sommerseth <davids@redhat.com> | 2015-10-10 00:02:40 +0200 |
commit | 685e486e8b8f70c25f09590c24762ff734f94a51 (patch) | |
tree | 2352755e34a75ea39f48497d6fb7dc7469330294 /src | |
parent | 7246ccfdbe6039c5c578ecaa07505307d53b8e84 (diff) | |
download | openvpn-685e486e8b8f70c25f09590c24762ff734f94a51.tar.gz openvpn-685e486e8b8f70c25f09590c24762ff734f94a51.tar.xz openvpn-685e486e8b8f70c25f09590c24762ff734f94a51.zip |
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>
Diffstat (limited to 'src')
-rw-r--r-- | src/openvpn/init.c | 16 | ||||
-rw-r--r-- | src/openvpn/options.c | 27 | ||||
-rw-r--r-- | src/openvpn/options.h | 6 | ||||
-rw-r--r-- | src/openvpn/ssl.c | 4 | ||||
-rw-r--r-- | src/openvpn/ssl_backend.h | 13 | ||||
-rw-r--r-- | src/openvpn/ssl_common.h | 5 | ||||
-rw-r--r-- | src/openvpn/ssl_openssl.c | 33 | ||||
-rw-r--r-- | src/openvpn/ssl_polarssl.c | 6 |
8 files changed, 110 insertions, 0 deletions
diff --git a/src/openvpn/init.c b/src/openvpn/init.c index 3decd23..c32a809 100644 --- a/src/openvpn/init.c +++ b/src/openvpn/init.c @@ -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) { diff --git a/src/openvpn/options.c b/src/openvpn/options.c index de4fa38..7906f46 100644 --- a/src/openvpn/options.c +++ b/src/openvpn/options.c @@ -611,6 +611,10 @@ static const char usage_message[] = "--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" " value should be given in hex format.\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; diff --git a/src/openvpn/options.h b/src/openvpn/options.h index abec83f..c642aa0 100644 --- a/src/openvpn/options.h +++ b/src/openvpn/options.h @@ -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))) diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c index 529d14d..86eda77 100644 --- a/src/openvpn/ssl.c +++ b/src/openvpn/ssl.c @@ -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"); } /* diff --git a/src/openvpn/ssl_backend.h b/src/openvpn/ssl_backend.h index b0777bf..99930e5 100644 --- a/src/openvpn/ssl_backend.h +++ b/src/openvpn/ssl_backend.h @@ -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 * @{ */ diff --git a/src/openvpn/ssl_common.h b/src/openvpn/ssl_common.h index 95cd2f7..86e4ac8 100644 --- a/src/openvpn/ssl_common.h +++ b/src/openvpn/ssl_common.h @@ -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 diff --git a/src/openvpn/ssl_openssl.c b/src/openvpn/ssl_openssl.c index a38c41b..c08d4fe 100644 --- a/src/openvpn/ssl_openssl.c +++ b/src/openvpn/ssl_openssl.c @@ -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. */ diff --git a/src/openvpn/ssl_polarssl.c b/src/openvpn/ssl_polarssl.c index 2056735..cd77aa5 100644 --- a/src/openvpn/ssl_polarssl.c +++ b/src/openvpn/ssl_polarssl.c @@ -149,6 +149,12 @@ tls_ctx_initialised(struct tls_root_ctx *ctx) } 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) { } |