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>
... | ... |
@@ -2757,6 +2757,18 @@ client\-connect), then |
2757 | 2757 |
every module and script must return success (0) in order for |
2758 | 2758 |
the connection to be authenticated. |
2759 | 2759 |
.\"********************************************************* |
2760 |
+.TP |
|
2761 |
+.B \-\-keying-material-exporter label len |
|
2762 |
+Save Exported Keying Material [RFC5705] of len bytes (must be |
|
2763 |
+between 16 and 4095 bytes) using label in environment |
|
2764 |
+(exported_keying_material) for use by plugins in |
|
2765 |
+OPENVPN_PLUGIN_TLS_FINAL callback. |
|
2766 |
+ |
|
2767 |
+Note that exporter labels have the potential to collide with existing PRF |
|
2768 |
+labels. In order to prevent this, labels MUST begin with "EXPORTER". |
|
2769 |
+ |
|
2770 |
+This option requires OpenSSL 1.0.1 or newer. |
|
2771 |
+.\"********************************************************* |
|
2760 | 2772 |
.SS Server Mode |
2761 | 2773 |
Starting with OpenVPN 2.0, a multi-client TCP/UDP server mode |
2762 | 2774 |
is supported, and can be enabled with the |
... | ... |
@@ -2279,6 +2279,22 @@ do_init_crypto_tls (struct context *c, const unsigned int flags) |
2279 | 2279 |
to.comp_options = options->comp; |
2280 | 2280 |
#endif |
2281 | 2281 |
|
2282 |
+#if defined(ENABLE_CRYPTO_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10001000 |
|
2283 |
+ if (options->keying_material_exporter_label) |
|
2284 |
+ { |
|
2285 |
+ to.ekm_size = options->keying_material_exporter_length; |
|
2286 |
+ if (to.ekm_size < 16 || to.ekm_size > 4095) |
|
2287 |
+ to.ekm_size = 0; |
|
2288 |
+ |
|
2289 |
+ to.ekm_label = options->keying_material_exporter_label; |
|
2290 |
+ to.ekm_label_size = strlen(to.ekm_label); |
|
2291 |
+ } |
|
2292 |
+ else |
|
2293 |
+ { |
|
2294 |
+ to.ekm_size = 0; |
|
2295 |
+ } |
|
2296 |
+#endif |
|
2297 |
+ |
|
2282 | 2298 |
/* TLS handshake authentication (--tls-auth) */ |
2283 | 2299 |
if (options->tls_auth_file) |
2284 | 2300 |
{ |
... | ... |
@@ -611,6 +611,10 @@ static const char usage_message[] = |
611 | 611 |
"--x509-track x : Save peer X509 attribute x in environment for use by\n" |
612 | 612 |
" plugins and management interface.\n" |
613 | 613 |
#endif |
614 |
+#if defined(ENABLE_CRYPTO_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10001000 |
|
615 |
+ "--keying-material-exporter label len : Save Exported Keying Material (RFC5705)\n" |
|
616 |
+ " of len bytes (min. 16 bytes) using label in environment for use by plugins.\n" |
|
617 |
+#endif |
|
614 | 618 |
"--remote-cert-ku v ... : Require that the peer certificate was signed with\n" |
615 | 619 |
" explicit key usage, you can specify more than one value.\n" |
616 | 620 |
" value should be given in hex format.\n" |
... | ... |
@@ -7066,6 +7070,29 @@ add_option (struct options *options, |
7066 | 7066 |
options->use_peer_id = true; |
7067 | 7067 |
options->peer_id = atoi(p[1]); |
7068 | 7068 |
} |
7069 |
+#if defined(ENABLE_CRYPTO_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10001000 |
|
7070 |
+ else if (streq (p[0], "keying-material-exporter") && p[1] && p[2]) |
|
7071 |
+ { |
|
7072 |
+ int ekm_length = positive_atoi (p[2]); |
|
7073 |
+ |
|
7074 |
+ VERIFY_PERMISSION (OPT_P_GENERAL); |
|
7075 |
+ |
|
7076 |
+ if (strncmp(p[1], "EXPORTER", 8)) |
|
7077 |
+ { |
|
7078 |
+ msg (msglevel, "Keying material exporter label must begin with " |
|
7079 |
+ "\"EXPORTER\""); |
|
7080 |
+ goto err; |
|
7081 |
+ } |
|
7082 |
+ if (ekm_length < 16 || ekm_length > 4095) |
|
7083 |
+ { |
|
7084 |
+ msg (msglevel, "Invalid keying material exporter length"); |
|
7085 |
+ goto err; |
|
7086 |
+ } |
|
7087 |
+ |
|
7088 |
+ options->keying_material_exporter_label = p[1]; |
|
7089 |
+ options->keying_material_exporter_length = ekm_length; |
|
7090 |
+ } |
|
7091 |
+#endif |
|
7069 | 7092 |
else |
7070 | 7093 |
{ |
7071 | 7094 |
int i; |
... | ... |
@@ -591,6 +591,12 @@ struct options |
591 | 591 |
|
592 | 592 |
bool use_peer_id; |
593 | 593 |
uint32_t peer_id; |
594 |
+ |
|
595 |
+#if defined(ENABLE_CRYPTO_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10001000 |
|
596 |
+ /* Keying Material Exporters [RFC 5705] */ |
|
597 |
+ const char *keying_material_exporter_label; |
|
598 |
+ int keying_material_exporter_length; |
|
599 |
+#endif |
|
594 | 600 |
}; |
595 | 601 |
|
596 | 602 |
#define streq(x, y) (!strcmp((x), (y))) |
... | ... |
@@ -2160,8 +2160,12 @@ key_method_2_read (struct buffer *buf, struct tls_multi *multi, struct tls_sessi |
2160 | 2160 |
*/ |
2161 | 2161 |
if (ks->authenticated && plugin_defined (session->opt->plugins, OPENVPN_PLUGIN_TLS_FINAL)) |
2162 | 2162 |
{ |
2163 |
+ key_state_export_keying_material(&ks->ks_ssl, session); |
|
2164 |
+ |
|
2163 | 2165 |
if (plugin_call (session->opt->plugins, OPENVPN_PLUGIN_TLS_FINAL, NULL, NULL, session->opt->es) != OPENVPN_PLUGIN_FUNC_SUCCESS) |
2164 | 2166 |
ks->authenticated = false; |
2167 |
+ |
|
2168 |
+ setenv_del (session->opt->es, "exported_keying_material"); |
|
2165 | 2169 |
} |
2166 | 2170 |
|
2167 | 2171 |
/* |
... | ... |
@@ -334,6 +334,19 @@ void key_state_ssl_init(struct key_state_ssl *ks_ssl, |
334 | 334 |
*/ |
335 | 335 |
void key_state_ssl_free(struct key_state_ssl *ks_ssl); |
336 | 336 |
|
337 |
+/** |
|
338 |
+ * Keying Material Exporters [RFC 5705] allows additional keying material to be |
|
339 |
+ * derived from existing TLS channel. This exported keying material can then be |
|
340 |
+ * used for a variety of purposes. |
|
341 |
+ * |
|
342 |
+ * @param ks_ssl The SSL channel's state info |
|
343 |
+ * @param session The session associated with the given key_state |
|
344 |
+ */ |
|
345 |
+ |
|
346 |
+void |
|
347 |
+key_state_export_keying_material(struct key_state_ssl *ks_ssl, |
|
348 |
+ struct tls_session *session) __attribute__((nonnull)); |
|
349 |
+ |
|
337 | 350 |
/**************************************************************************/ |
338 | 351 |
/** @addtogroup control_tls |
339 | 352 |
* @{ */ |
... | ... |
@@ -317,6 +317,11 @@ struct tls_options |
317 | 317 |
|
318 | 318 |
/* --gremlin bits */ |
319 | 319 |
int gremlin; |
320 |
+ |
|
321 |
+ /* Keying Material Exporter [RFC 5705] parameters */ |
|
322 |
+ const char *ekm_label; |
|
323 |
+ size_t ekm_label_size; |
|
324 |
+ size_t ekm_size; |
|
320 | 325 |
}; |
321 | 326 |
|
322 | 327 |
/** @addtogroup control_processor |
... | ... |
@@ -133,6 +133,39 @@ bool tls_ctx_initialised(struct tls_root_ctx *ctx) |
133 | 133 |
return NULL != ctx->ctx; |
134 | 134 |
} |
135 | 135 |
|
136 |
+void |
|
137 |
+key_state_export_keying_material(struct key_state_ssl *ssl, |
|
138 |
+ struct tls_session *session) |
|
139 |
+{ |
|
140 |
+ if (session->opt->ekm_size > 0) |
|
141 |
+ { |
|
142 |
+#if (OPENSSL_VERSION_NUMBER >= 0x10001000) |
|
143 |
+ unsigned int size = session->opt->ekm_size; |
|
144 |
+ unsigned char ekm[size]; |
|
145 |
+ |
|
146 |
+ if (SSL_export_keying_material(ssl->ssl, ekm, sizeof(ekm), |
|
147 |
+ session->opt->ekm_label, session->opt->ekm_label_size, NULL, 0, 0)) |
|
148 |
+ { |
|
149 |
+ struct gc_arena gc = gc_new(); |
|
150 |
+ unsigned int len = (size * 2) + 2; |
|
151 |
+ |
|
152 |
+ const char *key = format_hex_ex (ekm, size, len, 0, NULL, &gc); |
|
153 |
+ setenv_str (session->opt->es, "exported_keying_material", key); |
|
154 |
+ |
|
155 |
+ dmsg(D_TLS_DEBUG_MED, "%s: exported keying material: %s", |
|
156 |
+ __func__, key); |
|
157 |
+ |
|
158 |
+ gc_free(&gc); |
|
159 |
+ } |
|
160 |
+ else |
|
161 |
+ { |
|
162 |
+ msg (M_WARN, "WARNING: Export keying material failed!"); |
|
163 |
+ setenv_del (session->opt->es, "exported_keying_material"); |
|
164 |
+ } |
|
165 |
+#endif |
|
166 |
+ } |
|
167 |
+} |
|
168 |
+ |
|
136 | 169 |
/* |
137 | 170 |
* Print debugging information on SSL/TLS session negotiation. |
138 | 171 |
*/ |
... | ... |
@@ -149,6 +149,12 @@ tls_ctx_initialised(struct tls_root_ctx *ctx) |
149 | 149 |
} |
150 | 150 |
|
151 | 151 |
void |
152 |
+key_state_export_keying_material(struct key_state_ssl *ssl, |
|
153 |
+ struct tls_session *session) |
|
154 |
+{ |
|
155 |
+} |
|
156 |
+ |
|
157 |
+void |
|
152 | 158 |
tls_ctx_set_options (struct tls_root_ctx *ctx, unsigned int ssl_flags) |
153 | 159 |
{ |
154 | 160 |
} |