From patchwork Sun Nov 10 12:10:18 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steffan Karger X-Patchwork-Id: 909 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director11.mail.ord1d.rsapps.net ([172.31.255.6]) by backend30.mail.ord1d.rsapps.net with LMTP id aKgcNz6ZyF3qagAAIUCqbw for ; Sun, 10 Nov 2019 18:11:58 -0500 Received: from proxy8.mail.iad3b.rsapps.net ([172.31.255.6]) by director11.mail.ord1d.rsapps.net with LMTP id 4A/WND6ZyF0DRwAAvGGmqA ; Sun, 10 Nov 2019 18:11:58 -0500 Received: from smtp1.gate.iad3b ([172.31.255.6]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy8.mail.iad3b.rsapps.net with LMTP id WJYEMD6ZyF2BRwAAoCsc3g ; Sun, 10 Nov 2019 18:11:58 -0500 X-Spam-Threshold: 95 X-Spam-Score: 0 X-Spam-Flag: NO X-Virus-Scanned: OK X-Orig-To: openvpnslackdevel@openvpn.net X-Originating-Ip: [216.105.38.7] Authentication-Results: smtp1.gate.iad3b.rsapps.net; iprev=pass policy.iprev="216.105.38.7"; spf=pass smtp.mailfrom="openvpn-devel-bounces@lists.sourceforge.net" smtp.helo="lists.sourceforge.net"; dkim=fail (signature verification failed) header.d=sourceforge.net; dkim=fail (signature verification failed) header.d=sf.net; dkim=fail (signature verification failed) header.d=karger-me.20150623.gappssmtp.com; dmarc=none (p=nil; dis=none) header.from=karger.me X-Suspicious-Flag: YES X-Classification-ID: 7e27020e-040f-11ea-958c-5254008fd675-1-1 Received: from [216.105.38.7] ([216.105.38.7:39320] helo=lists.sourceforge.net) by smtp1.gate.iad3b.rsapps.net (envelope-from ) (ecelerity 4.2.38.62370 r(:)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id 08/CF-17643-E3998CD5; Sun, 10 Nov 2019 18:11:58 -0500 Received: from [127.0.0.1] (helo=sfs-ml-2.v29.lw.sourceforge.com) by sfs-ml-2.v29.lw.sourceforge.com with esmtp (Exim 4.90_1) (envelope-from ) id 1iTwMA-0006zS-GE; Sun, 10 Nov 2019 23:10:54 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-2.v29.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) (envelope-from ) id 1iTwM7-0006zJ-RW for openvpn-devel@lists.sourceforge.net; Sun, 10 Nov 2019 23:10:51 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=Content-Transfer-Encoding:MIME-Version:Message-Id: Date:Subject:Cc:To:From:Sender:Reply-To:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=W82gAHu0LzjYnQVVwDyB9BHnz6uASAgpO5/tFAd1cWk=; b=aZEezzGKbEcbz0Ae1n+1EKmwQc cKJYS35Tk2Wj1G1Aa8i2T9S6al/cdppKqVIPTGKME+yQ0IqWXrJu3XaEnJdbplc33i7UNDg0y1R/A KDvN/zOILRfgc211jaRXyKb2m5ZbO/hRkRQ79+QOTRGrtBYvP/+2hQZiVQRau6RInfa0=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=Content-Transfer-Encoding:MIME-Version:Message-Id:Date:Subject:Cc:To:From :Sender:Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To: References:List-Id:List-Help:List-Unsubscribe:List-Subscribe:List-Post: List-Owner:List-Archive; bh=W82gAHu0LzjYnQVVwDyB9BHnz6uASAgpO5/tFAd1cWk=; b=c 5B/U7JnwhZky45McJGwsPAFYmRFtbaQplb2lwuCY5rYCkj0eludu19nYrK6+PGaQe3tMEv2MQv7UG gGUyX8W4r5u4X/zb1ztKQfbXCCRexdDwvCFq9QUk+1Yppjp0Sdk1GOIAXUW4ugeJrGGkCie7WwM8w UWAqnf04D+URZNFE=; Received: from mail-wm1-f65.google.com ([209.85.128.65]) by sfi-mx-3.v28.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES128-GCM-SHA256:128) (Exim 4.92.2) id 1iTwLz-00BAxH-Vo for openvpn-devel@lists.sourceforge.net; Sun, 10 Nov 2019 23:10:51 +0000 Received: by mail-wm1-f65.google.com with SMTP id z19so11396950wmk.3 for ; Sun, 10 Nov 2019 15:10:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=karger-me.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=W82gAHu0LzjYnQVVwDyB9BHnz6uASAgpO5/tFAd1cWk=; b=UXZTstBej7vN+jYgfnybLgg9U28ubRhSuHs8yQ7iiYsLZJk9gHNIpyoedwpPkqgNx6 OgXvSLibrcUWLxYvbqHg7PYShNVGXlx0BoaSMnj252+mfrL4bDtXu0UOjHvk4idC1tH7 GKVrD81GzxDHM47M8wDdE1aht/0un3i1d9PTnkNZqEm/EeY6syde2AUUsv9XfWfksoL9 QnosMrjpne4uq2SdcaYl0Ej/3vqW99y7rxIqS2eTFuF+xJqm7QL5hL9E03m8EU47Z7b4 ZoYiU5PFmaFP1eJVZ55FYS8iuZLOfQRmudZunP1bRBfy985P5QEHUdZrfLUCI9P9Uvtn 7Jvw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=W82gAHu0LzjYnQVVwDyB9BHnz6uASAgpO5/tFAd1cWk=; b=czLa3dV7OySAC41bIw+Us6OAxVffSBlkUFpam2v3SoSFBE9snBgK3O0EWRh70w1AuV 10wRkrFAL+0mRQKmA6smy+n1anKjuLPBNUNF0zF8FzildwnZtJalT88Iz/hjCnZOzJUV xJp0PQpIWagjkuu9fM5DqHPvPIAOUyijuhVnDbwkzLeeW/N9CZD5Zll21+AhB6AXzUNd o7bRSQe9ZhmwKDR+ZGHADv41HKOAZApzn0N5vjPxh7u85aD4KizreiauKr0bPDOvpWAE iQXVJ0PmrXnUP/vXHok0IdFQFBO7PGALnJMWtFMRFx6buL1sqmtmnV/tpZuDSlwUfbg2 tgVw== X-Gm-Message-State: APjAAAV+LwDQXaL2JSsPWG4sONXTfniW5TWbwHVniZOQBmPHB5pjPqPq uxtyj0vOY64vLi0BRYGotItGN8ZWWiA0MQ== X-Google-Smtp-Source: APXvYqyJXC5H3TaRt0F0b8zQ8dkBl5MAgSxsz+nKfq3VLmSz0nhHGWzsgF1fHVK86pNbpnVchGedRA== X-Received: by 2002:a1c:8055:: with SMTP id b82mr18389835wmd.176.1573427437019; Sun, 10 Nov 2019 15:10:37 -0800 (PST) Received: from luna.l.certwifi.com (93-56-11-168.ip287.fastwebnet.it. [93.56.11.168]) by smtp.gmail.com with ESMTPSA id b17sm14455330wru.36.2019.11.10.15.10.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 Nov 2019 15:10:36 -0800 (PST) From: Steffan Karger To: openvpn-devel@lists.sourceforge.net Date: Mon, 11 Nov 2019 00:10:18 +0100 Message-Id: <20191110231018.30621-1-steffan@karger.me> X-Mailer: git-send-email 2.20.1 MIME-Version: 1.0 X-Spam-Report: Spam Filtering performed by mx.sourceforge.net. See http://spamassassin.org/tag/ for more details. -0.0 RCVD_IN_MSPIKE_H2 RBL: Average reputation (+2) [209.85.128.65 listed in wl.mailspike.net] -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [209.85.128.65 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid X-Headers-End: 1iTwLz-00BAxH-Vo Subject: [Openvpn-devel] [PATCH] mbedtls: add RFC 5705 keying material exporter support X-BeenThere: openvpn-devel@lists.sourceforge.net X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox Since mbed TLS 2.18, mbed TLS can also implement RFC 5705. As a first step towards using the keying material exporter as a method to generate key material for the data channel, implement the --keying-material-exporter function we already have for OpenSSL also for mbed TLS builds. Implementing RFC 5705 for mbed TLS is a bit more cumbersome, because the library itself only provides a callback that is called during connection setup, which enables us to implement RFC 5705 ourselves. To protect ourselves against mistakes, we immediately perform the required key derivation to generate the exporterd keying material, and only cache the derived key material until we can actually export it to the environment (similar to the OpenSSL builds). To test this, I found it easiest to temporarily move the call to key_state_export_keying_material outside the if statement, and use a script that runs after connection setup (e.g. --ipchange) that prints the environment. E.g. #!/bin/sh env | sort This should show the same value for the exported_keying_material env variable for both mbed TLS and OpenSSL builds. Of course you can also use the code as-is, and write a plugin to verify the same thing. Signed-off-by: Steffan Karger Acked-By: Arne Schwabe --- src/openvpn/init.c | 4 +-- src/openvpn/options.c | 4 +-- src/openvpn/options.h | 2 +- src/openvpn/ssl_mbedtls.c | 64 ++++++++++++++++++++++++++++++++++++++- src/openvpn/ssl_mbedtls.h | 5 +++ src/openvpn/ssl_openssl.c | 4 ++- src/openvpn/syshead.h | 14 ++++++++- 7 files changed, 89 insertions(+), 8 deletions(-) diff --git a/src/openvpn/init.c b/src/openvpn/init.c index 0bdb0a9c..1ed6ae11 100644 --- a/src/openvpn/init.c +++ b/src/openvpn/init.c @@ -2931,7 +2931,7 @@ 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 +#ifdef HAVE_EKM if (options->keying_material_exporter_label) { to.ekm_size = options->keying_material_exporter_length; @@ -2947,7 +2947,7 @@ do_init_crypto_tls(struct context *c, const unsigned int flags) { to.ekm_size = 0; } -#endif +#endif /* HAVE_EKM */ /* TLS handshake authentication (--tls-auth) */ if (options->ce.tls_auth_file) diff --git a/src/openvpn/options.c b/src/openvpn/options.c index c282b582..98d94b86 100644 --- a/src/openvpn/options.c +++ b/src/openvpn/options.c @@ -661,7 +661,7 @@ static const char usage_message[] = " an explicit nsCertType designation t = 'client' | 'server'.\n" "--x509-track x : Save peer X509 attribute x in environment for use by\n" " plugins and management interface.\n" -#if defined(ENABLE_CRYPTO_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10001000 +#ifdef HAVE_EKM "--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 @@ -8468,7 +8468,7 @@ 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 +#ifdef HAVE_EKM else if (streq(p[0], "keying-material-exporter") && p[1] && p[2]) { int ekm_length = positive_atoi(p[2]); diff --git a/src/openvpn/options.h b/src/openvpn/options.h index 7fd2c00f..7f3b3b20 100644 --- a/src/openvpn/options.h +++ b/src/openvpn/options.h @@ -640,7 +640,7 @@ struct options bool use_peer_id; uint32_t peer_id; -#if defined(ENABLE_CRYPTO_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10001000 +#ifdef HAVE_EKM /* Keying Material Exporters [RFC 5705] */ const char *keying_material_exporter_label; int keying_material_exporter_length; diff --git a/src/openvpn/ssl_mbedtls.c b/src/openvpn/ssl_mbedtls.c index a4197cba..54f692e0 100644 --- a/src/openvpn/ssl_mbedtls.c +++ b/src/openvpn/ssl_mbedtls.c @@ -190,12 +190,62 @@ tls_ctx_initialised(struct tls_root_ctx *ctx) return ctx->initialised; } +#ifdef HAVE_EKM +int mbedtls_ssl_export_keys_cb(void *p_expkey, const unsigned char *ms, + const unsigned char *kb, size_t maclen, + size_t keylen, size_t ivlen, + const unsigned char client_random[32], + const unsigned char server_random[32], + mbedtls_tls_prf_types tls_prf_type) +{ + struct tls_session *session = p_expkey; + struct key_state_ssl *ks_ssl = &session->key[KS_PRIMARY].ks_ssl; + unsigned char client_server_random[64]; + + ks_ssl->exported_key_material = gc_malloc(session->opt->ekm_size, + true, NULL); + + memcpy(client_server_random, client_random, 32); + memcpy(client_server_random + 32, server_random, 32); + + const size_t ms_len = sizeof(ks_ssl->ctx->session->master); + int ret = mbedtls_ssl_tls_prf( + tls_prf_type, ms, ms_len, session->opt->ekm_label, + client_server_random, sizeof(client_server_random), + ks_ssl->exported_key_material, session->opt->ekm_size); + + if (!mbed_ok(ret)) + { + secure_memzero(ks_ssl->exported_key_material, session->opt->ekm_size); + } + + secure_memzero(client_server_random, sizeof(client_server_random)); + + return ret; +} +#endif /* HAVE_EKM */ + void key_state_export_keying_material(struct key_state_ssl *ssl, struct tls_session *session) { + if (ssl->exported_key_material) + { + unsigned int size = session->opt->ekm_size; + struct gc_arena gc = gc_new(); + unsigned int len = (size * 2) + 2; + + const char *key = format_hex_ex(ssl->exported_key_material, + 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); + } } + bool tls_ctx_set_options(struct tls_root_ctx *ctx, unsigned int ssl_flags) { @@ -974,7 +1024,8 @@ err: void key_state_ssl_init(struct key_state_ssl *ks_ssl, - const struct tls_root_ctx *ssl_ctx, bool is_server, struct tls_session *session) + const struct tls_root_ctx *ssl_ctx, bool is_server, + struct tls_session *session) { ASSERT(NULL != ssl_ctx); ASSERT(ks_ssl); @@ -1065,6 +1116,15 @@ key_state_ssl_init(struct key_state_ssl *ks_ssl, } } +#if MBEDTLS_VERSION_NUMBER >= 0x02120000 + /* Initialize keying material exporter */ + if (session->opt->ekm_size) + { + mbedtls_ssl_conf_export_keys_ext_cb(&ks_ssl->ssl_config, + mbedtls_ssl_export_keys_cb, session); + } +#endif + /* Initialise SSL context */ ALLOC_OBJ_CLEAR(ks_ssl->ctx, mbedtls_ssl_context); mbedtls_ssl_init(ks_ssl->ctx); @@ -1081,6 +1141,8 @@ key_state_ssl_free(struct key_state_ssl *ks_ssl) { if (ks_ssl) { + free(ks_ssl->exported_key_material); + if (ks_ssl->ctx) { mbedtls_ssl_free(ks_ssl->ctx); diff --git a/src/openvpn/ssl_mbedtls.h b/src/openvpn/ssl_mbedtls.h index 1328ceb7..c1c676dc 100644 --- a/src/openvpn/ssl_mbedtls.h +++ b/src/openvpn/ssl_mbedtls.h @@ -33,6 +33,7 @@ #include #include +#include #if defined(ENABLE_PKCS11) #include @@ -111,6 +112,10 @@ struct key_state_ssl { mbedtls_ssl_config ssl_config; /**< mbedTLS global ssl config */ mbedtls_ssl_context *ctx; /**< mbedTLS connection context */ bio_ctx bio_ctx; + + /** Keying material exporter cache (RFC 5705). */ + uint8_t *exported_key_material; + }; /** diff --git a/src/openvpn/ssl_openssl.c b/src/openvpn/ssl_openssl.c index 07916c3c..c80d9fab 100644 --- a/src/openvpn/ssl_openssl.c +++ b/src/openvpn/ssl_openssl.c @@ -160,7 +160,9 @@ key_state_export_keying_material(struct key_state_ssl *ssl, unsigned char *ekm = (unsigned char *) gc_malloc(size, true, &gc); if (SSL_export_keying_material(ssl->ssl, ekm, size, - session->opt->ekm_label, session->opt->ekm_label_size, NULL, 0, 0)) + session->opt->ekm_label, + session->opt->ekm_label_size, + NULL, 0, 0)) { unsigned int len = (size * 2) + 2; diff --git a/src/openvpn/syshead.h b/src/openvpn/syshead.h index 899aa59e..a2401e26 100644 --- a/src/openvpn/syshead.h +++ b/src/openvpn/syshead.h @@ -548,11 +548,15 @@ socket_defined(const socket_descriptor_t sd) #undef ENABLE_DEF_AUTH #endif -/* Enable mbed TLS RNG prediction resistance support */ #ifdef ENABLE_CRYPTO_MBEDTLS +#include #define ENABLE_PREDICTION_RESISTANCE #endif /* ENABLE_CRYPTO_MBEDTLS */ +#ifdef ENABLE_CRYPTO_OPENSSL +#include +#endif /* ENABLE_CRYPTO_OPENSSL */ + /* * Enable packet filter? */ @@ -597,6 +601,14 @@ socket_defined(const socket_descriptor_t sd) #define ENABLE_CRYPTOAPI #endif +/* + * Do we support RFC 5705 keying material exporters? + */ +#if (defined(ENABLE_CRYPTO_MBEDTLS) && MBEDTLS_VERSION_NUMBER >= 0x02120000) || \ + (defined(ENABLE_CRYPTO_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10001000) +#define HAVE_EKM +#endif + /* * Is poll available on this platform? */