From patchwork Mon Feb 1 06:43:08 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arne Schwabe X-Patchwork-Id: 1592 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director14.mail.ord1d.rsapps.net ([172.30.191.6]) by backend30.mail.ord1d.rsapps.net with LMTP id MI/RFPQ9GGDJaAAAIUCqbw (envelope-from ) for ; Mon, 01 Feb 2021 12:44:20 -0500 Received: from proxy16.mail.ord1d.rsapps.net ([172.30.191.6]) by director14.mail.ord1d.rsapps.net with LMTP id sHygFPQ9GGCGTQAAeJ7fFg (envelope-from ) for ; Mon, 01 Feb 2021 12:44:20 -0500 Received: from smtp14.gate.ord1d ([172.30.191.6]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy16.mail.ord1d.rsapps.net with LMTPS id 4L9VFPQ9GGA1AgAAetu3IA (envelope-from ) for ; Mon, 01 Feb 2021 12:44:20 -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: smtp14.gate.ord1d.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; dmarc=none (p=nil; dis=none) header.from=rfc2549.org X-Suspicious-Flag: YES X-Classification-ID: 1c8f8eb4-64b5-11eb-aa0b-525400504bae-1-1 Received: from [216.105.38.7] ([216.105.38.7:52862] helo=lists.sourceforge.net) by smtp14.gate.ord1d.rsapps.net (envelope-from ) (ecelerity 4.2.38.62370 r(:)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id 49/9E-04334-3FD38106; Mon, 01 Feb 2021 12:44:20 -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 1l6dEZ-0001iS-42; Mon, 01 Feb 2021 17:43:31 +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 1l6dEX-0001hx-3y for openvpn-devel@lists.sourceforge.net; Mon, 01 Feb 2021 17:43:29 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=References:In-Reply-To:Message-Id:Date:Subject:To: From:Sender:Reply-To:Cc:MIME-Version:Content-Type:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=PZYdmWfnrlAIJhjYDrEZTOpKE+kR31svAbT9syLOv8Y=; b=WBv30zR8D/yUAXLZndBxlw6yMB F2GjUTo6eDKxHB85w1Mo6IcrWpfzsdvmnVxTFZ4ZsjLC/vFDs8rqrxXS21w+1LNM1BMZIs1Qik/tS 5JVPXy23u/qK+P0L4r+Ao6gOASNa1qPOmux6OyqN5JWBvNaV/IvSRi2ljLXFg35ygtKo=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=References:In-Reply-To:Message-Id:Date:Subject:To:From:Sender:Reply-To:Cc :MIME-Version:Content-Type:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=PZYdmWfnrlAIJhjYDrEZTOpKE+kR31svAbT9syLOv8Y=; b=VxEt4JlxD81Xo82DCbPdC7c8fM z1/R8h8RJAkd6KHaJKEb9JODEjHvokk/x07FvQUhPoY45tyHuAnzlFZuemndNMe+PvoKyo13Q1xgX E3n/fMB54OHYB+2Ig29D1ybzOEdJWfkkWgl5t7nb5Zr7ZarIGMxTQRUu84q0ZdsET1l8=; Received: from mail.blinkt.de ([192.26.174.232]) by sfi-mx-2.v28.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.92.3) id 1l6dEN-0000Np-7e for openvpn-devel@lists.sourceforge.net; Mon, 01 Feb 2021 17:43:28 +0000 Received: from kamera.blinkt.de ([2001:638:502:390:20c:29ff:fec8:535c]) by mail.blinkt.de with smtp (Exim 4.94 (FreeBSD)) (envelope-from ) id 1l6dEE-000NVW-Ft for openvpn-devel@lists.sourceforge.net; Mon, 01 Feb 2021 18:43:10 +0100 Received: (nullmailer pid 22200 invoked by uid 10006); Mon, 01 Feb 2021 17:43:10 -0000 From: Arne Schwabe To: openvpn-devel@lists.sourceforge.net Date: Mon, 1 Feb 2021 18:43:08 +0100 Message-Id: <20210201174310.22153-2-arne@rfc2549.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210201174310.22153-1-arne@rfc2549.org> References: <20210201174310.22153-1-arne@rfc2549.org> X-Spam-Report: Spam Filtering performed by mx.sourceforge.net. See http://spamassassin.org/tag/ for more details. 0.2 HEADER_FROM_DIFFERENT_DOMAINS From and EnvelopeFrom 2nd level mail domains are different 0.0 SPF_NONE SPF: sender does not publish an SPF Record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record X-Headers-End: 1l6dEN-0000Np-7e Subject: [Openvpn-devel] [PATCH v3 1/3] Check return values in md_ctx_init and hmac_ctx_init 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: , MIME-Version: 1.0 Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox Without this OpenVPN will later segfault on a FIPS enabled system due to the algorithm available but not allowed. Patch V2: Use (!func) instead (func != 1) Signed-off-by: Arne Schwabe Acked-by: Antonio Quartulli --- src/openvpn/crypto_openssl.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/openvpn/crypto_openssl.c b/src/openvpn/crypto_openssl.c index c60d4a54..e124a7b6 100644 --- a/src/openvpn/crypto_openssl.c +++ b/src/openvpn/crypto_openssl.c @@ -954,7 +954,10 @@ md_ctx_init(EVP_MD_CTX *ctx, const EVP_MD *kt) ASSERT(NULL != ctx && NULL != kt); EVP_MD_CTX_init(ctx); - EVP_DigestInit(ctx, kt); + if (!EVP_DigestInit(ctx, kt)) + { + crypto_msg(M_FATAL, "EVP_DigestInit failed"); + } } void @@ -1011,7 +1014,10 @@ hmac_ctx_init(HMAC_CTX *ctx, const uint8_t *key, int key_len, ASSERT(NULL != kt && NULL != ctx); HMAC_CTX_reset(ctx); - HMAC_Init_ex(ctx, key, key_len, kt, NULL); + if (!HMAC_Init_ex(ctx, key, key_len, kt, NULL)) + { + crypto_msg(M_FATAL, "HMAC_Init_ex failed"); + } /* make sure we used a big enough key */ ASSERT(HMAC_size(ctx) <= key_len); @@ -1032,7 +1038,10 @@ hmac_ctx_size(const HMAC_CTX *ctx) void hmac_ctx_reset(HMAC_CTX *ctx) { - HMAC_Init_ex(ctx, NULL, 0, NULL, NULL); + if(!HMAC_Init_ex(ctx, NULL, 0, NULL, NULL)) + { + crypto_msg(M_FATAL, "HMAC_Init_ex failed"); + } } void From patchwork Mon Feb 1 06:43:09 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arne Schwabe X-Patchwork-Id: 1589 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director15.mail.ord1d.rsapps.net ([172.30.191.6]) by backend30.mail.ord1d.rsapps.net with LMTP id ID5nEvE9GGDjLAAAIUCqbw (envelope-from ) for ; Mon, 01 Feb 2021 12:44:17 -0500 Received: from proxy4.mail.ord1d.rsapps.net ([172.30.191.6]) by director15.mail.ord1d.rsapps.net with LMTP id iObZEfE9GGBMKQAAIcMcQg (envelope-from ) for ; Mon, 01 Feb 2021 12:44:17 -0500 Received: from smtp25.gate.ord1d ([172.30.191.6]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy4.mail.ord1d.rsapps.net with LMTPS id WN6yEfE9GGAIWgAAiYrejw (envelope-from ) for ; Mon, 01 Feb 2021 12:44:17 -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: smtp25.gate.ord1d.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; dmarc=none (p=nil; dis=none) header.from=rfc2549.org X-Suspicious-Flag: YES X-Classification-ID: 1a6708b0-64b5-11eb-b3e4-52540081550e-1-1 Received: from [216.105.38.7] ([216.105.38.7:38472] helo=lists.sourceforge.net) by smtp25.gate.ord1d.rsapps.net (envelope-from ) (ecelerity 4.2.38.62370 r(:)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id A5/FA-02214-0FD38106; Mon, 01 Feb 2021 12:44:16 -0500 Received: from [127.0.0.1] (helo=sfs-ml-4.v29.lw.sourceforge.com) by sfs-ml-4.v29.lw.sourceforge.com with esmtp (Exim 4.90_1) (envelope-from ) id 1l6dEY-0000As-BT; Mon, 01 Feb 2021 17:43:30 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-4.v29.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) (envelope-from ) id 1l6dEX-0000AD-1u for openvpn-devel@lists.sourceforge.net; Mon, 01 Feb 2021 17:43:29 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=References:In-Reply-To:Message-Id:Date:Subject:To: From:Sender:Reply-To:Cc:MIME-Version:Content-Type:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=ajuz2vfCqBLgZw87MhHhTlTWNaVjr6ObblaZbs07o/Y=; b=B+B3+yK+yb0os9/zDTQc5KRn1z /hN4hhwnsDm17aFQAWfEtu1XGrwp4oLDDn/QRCXWwHVel7sELpCYl77PXQqZdHWXxFjLlQ+8PvT29 olZlUMZUCHeaCBLVEwltfQf44jWohdGqFLwiQqNhrmGnPjbd1oFvr7gtmYkPYwdFio54=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=References:In-Reply-To:Message-Id:Date:Subject:To:From:Sender:Reply-To:Cc :MIME-Version:Content-Type:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=ajuz2vfCqBLgZw87MhHhTlTWNaVjr6ObblaZbs07o/Y=; b=equvTrF22largH9PPfx/vtZk76 WxTKfOKd/9ELBDxaH1GnWfOiih+jBCtcO6/7gm0xEaXVBu3BdXKAQB1DXDb5VDlpm+890M1Ra5D0D FwIzXcFXsRWi0Rhr2mchdt4EiPdrakcgojHbkLq2C0dWRQRqdn1IcUUh/XuT5zFZcweQ=; Received: from mail.blinkt.de ([192.26.174.232]) by sfi-mx-2.v28.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.92.3) id 1l6dEN-0000Nq-1K for openvpn-devel@lists.sourceforge.net; Mon, 01 Feb 2021 17:43:28 +0000 Received: from kamera.blinkt.de ([2001:638:502:390:20c:29ff:fec8:535c]) by mail.blinkt.de with smtp (Exim 4.94 (FreeBSD)) (envelope-from ) id 1l6dEE-000NVa-I4 for openvpn-devel@lists.sourceforge.net; Mon, 01 Feb 2021 18:43:10 +0100 Received: (nullmailer pid 22203 invoked by uid 10006); Mon, 01 Feb 2021 17:43:10 -0000 From: Arne Schwabe To: openvpn-devel@lists.sourceforge.net Date: Mon, 1 Feb 2021 18:43:09 +0100 Message-Id: <20210201174310.22153-3-arne@rfc2549.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210201174310.22153-1-arne@rfc2549.org> References: <20210201174310.22153-1-arne@rfc2549.org> X-Spam-Report: Spam Filtering performed by mx.sourceforge.net. See http://spamassassin.org/tag/ for more details. 0.2 HEADER_FROM_DIFFERENT_DOMAINS From and EnvelopeFrom 2nd level mail domains are different 0.0 SPF_NONE SPF: sender does not publish an SPF Record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record X-Headers-End: 1l6dEN-0000Nq-1K Subject: [Openvpn-devel] [PATCH v3 2/3] Prefer TLS libraries TLS PRF function, fix OpenVPN in FIPS mode 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: , MIME-Version: 1.0 Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox This moves from using our own copy of the TLS1 PRF function to using TLS library provided function where possible. This includes currently OpenSSL 1.1.0+ and mbed TLS 2.18+. For the libraries where it is not possible to use the library's own function, we still use our own implementation. mbed TLS will continue to use our own old PRF function while for OpenSSL we will use a adapted version from OpenSSL 1.0.2t code. The version allows to be used in a FIPS enabled environment. The old OpenSSL and mbed TLS implementation could have shared some more code but as we will eventually drop support for older TLS libraries, the separation makes it easier it remove that code invdidually. In FIPS mode MD5 is normally forbidden, the TLS1 PRF1 function we use, makes uses of MD5, which in the past has caused OpenVPN to segfault. The new implementation for OpenSSL version of our custom implementation has added the special flags that tell OpenSSL that this specific use of MD5 is allowed in FIPS mode. No FIPS conformitiy testing etc has been done, this is only about allowing OpenVPN on a system where FIPS mode has been enabled system wide (e.g. on RHEL derivates). Signed-off-by: Arne Schwabe --- Changes.rst | 10 +- src/openvpn/crypto_backend.h | 14 +++ src/openvpn/crypto_mbedtls.c | 134 ++++++++++++++++++++ src/openvpn/crypto_openssl.c | 165 +++++++++++++++++++++++++ src/openvpn/ssl.c | 130 +------------------ tests/unit_tests/openvpn/test_crypto.c | 32 +++++ 6 files changed, 351 insertions(+), 134 deletions(-) diff --git a/Changes.rst b/Changes.rst index 2a847564..0c66fe2a 100644 --- a/Changes.rst +++ b/Changes.rst @@ -9,11 +9,11 @@ Keying Material Exporters (RFC 5705) based key generation the RFC5705 based key material generation to the current custom OpenVPN PRF. This feature requires OpenSSL or mbed TLS 2.18+. -Deprecated features -------------------- -``inetd`` has been removed - This was a very limited and not-well-tested way to run OpenVPN, on TCP - and TAP mode only. +Compatibility with OpenSSL in FIPS mode + OpenVPN will now work with OpenSSL in FIPS mode. Note, no effort + has been made to check or implement all the + requirements/recommendation of FIPS 140-2. This just allows OpenVPN + to be run on a system that be configured OpenSSL in FIPS mode. Overview of changes in 2.5 diff --git a/src/openvpn/crypto_backend.h b/src/openvpn/crypto_backend.h index 85cb084a..d86d9a34 100644 --- a/src/openvpn/crypto_backend.h +++ b/src/openvpn/crypto_backend.h @@ -699,4 +699,18 @@ const char *translate_cipher_name_from_openvpn(const char *cipher_name); */ const char *translate_cipher_name_to_openvpn(const char *cipher_name); + +/** + * Calculates the TLS 1.0-1.1 PRF function. For the exact specification of the + * function definition see the TLS RFCs like RFC 4346. + * + * @param seed seed to use + * @param seed_len length of the seed + * @param secret secret to use + * @param secret_len length of the secret + * @param output output destination + * @param output_len length of output/number of bytes to generate + */ +void ssl_tls1_PRF(const uint8_t *seed, int seed_len, const uint8_t *secret, + int secret_len, uint8_t *output, int output_len); #endif /* CRYPTO_BACKEND_H_ */ diff --git a/src/openvpn/crypto_mbedtls.c b/src/openvpn/crypto_mbedtls.c index fbb1f120..5ed88d6d 100644 --- a/src/openvpn/crypto_mbedtls.c +++ b/src/openvpn/crypto_mbedtls.c @@ -54,6 +54,7 @@ #include #include +#include /* @@ -984,4 +985,137 @@ memcmp_constant_time(const void *a, const void *b, size_t size) return diff; } +/* mbedtls-2.18.0 or newer */ +#ifdef HAVE_MBEDTLS_SSL_TLS_PRF +void ssl_tls1_PRF(const uint8_t *seed, int seed_len, const uint8_t *secret, + int secret_len, uint8_t *output, int output_len) +{ + mbedtls_ssl_tls_prf(MBEDTLS_SSL_TLS_PRF_TLS1, secret, secret_len, "", seed, + seed_len, output, output_len); +} +#else +/* + * Generate the hash required by for the \c tls1_PRF function. + * + * @param md_kt Message digest to use + * @param sec Secret to base the hash on + * @param sec_len Length of the secret + * @param seed Seed to hash + * @param seed_len Length of the seed + * @param out Output buffer + * @param olen Length of the output buffer + */ +static void +tls1_P_hash(const md_kt_t *md_kt, + const uint8_t *sec, + int sec_len, + const uint8_t *seed, + int seed_len, + uint8_t *out, + int olen) +{ + struct gc_arena gc = gc_new(); + uint8_t A1[MAX_HMAC_KEY_LENGTH]; + +#ifdef ENABLE_DEBUG + const int olen_orig = olen; + const uint8_t *out_orig = out; +#endif + + hmac_ctx_t *ctx = hmac_ctx_new(); + hmac_ctx_t *ctx_tmp = hmac_ctx_new(); + + dmsg(D_SHOW_KEY_SOURCE, "tls1_P_hash sec: %s", format_hex(sec, sec_len, 0, &gc)); + dmsg(D_SHOW_KEY_SOURCE, "tls1_P_hash seed: %s", format_hex(seed, seed_len, 0, &gc)); + + int chunk = md_kt_size(md_kt); + unsigned int A1_len = md_kt_size(md_kt); + + hmac_ctx_init(ctx, sec, sec_len, md_kt); + hmac_ctx_init(ctx_tmp, sec, sec_len, md_kt); + + hmac_ctx_update(ctx,seed,seed_len); + hmac_ctx_final(ctx, A1); + + for (;;) + { + hmac_ctx_reset(ctx); + hmac_ctx_reset(ctx_tmp); + hmac_ctx_update(ctx, A1, A1_len); + hmac_ctx_update(ctx_tmp, A1, A1_len); + hmac_ctx_update(ctx, seed, seed_len); + + if (olen > chunk) + { + hmac_ctx_final(ctx, out); + out += chunk; + olen -= chunk; + hmac_ctx_final(ctx_tmp, A1); /* calc the next A1 value */ + } + else /* last one */ + { + hmac_ctx_final(ctx, A1); + memcpy(out, A1, olen); + break; + } + } + hmac_ctx_cleanup(ctx); + hmac_ctx_free(ctx); + hmac_ctx_cleanup(ctx_tmp); + hmac_ctx_free(ctx_tmp); + secure_memzero(A1, sizeof(A1)); + + dmsg(D_SHOW_KEY_SOURCE, "tls1_P_hash out: %s", format_hex(out_orig, olen_orig, 0, &gc)); + gc_free(&gc); +} + +/* + * Use the TLS PRF function for generating data channel keys. + * This code is based on the OpenSSL library. + * + * TLS generates keys as such: + * + * master_secret[48] = PRF(pre_master_secret[48], "master secret", + * ClientHello.random[32] + ServerHello.random[32]) + * + * key_block[] = PRF(SecurityParameters.master_secret[48], + * "key expansion", + * SecurityParameters.server_random[32] + + * SecurityParameters.client_random[32]); + * + * Notes: + * + * (1) key_block contains a full set of 4 keys. + * (2) The pre-master secret is generated by the client. + */ +void +ssl_tls1_PRF(const uint8_t *label, int label_len, const uint8_t *sec, int slen, + uint8_t *out1, int olen) +{ + struct gc_arena gc = gc_new(); + const md_kt_t *md5 = md_kt_get("MD5"); + const md_kt_t *sha1 = md_kt_get("SHA1"); + + uint8_t *out2 = (uint8_t *) gc_malloc(olen, false, &gc); + + int len = slen/2; + const uint8_t *S1 = sec; + const uint8_t *S2 = &(sec[len]); + len += (slen&1); /* add for odd, make longer */ + + tls1_P_hash(md5,S1,len,label,label_len,out1,olen); + tls1_P_hash(sha1,S2,len,label,label_len,out2,olen); + + for (int i = 0; i #include #include +#if OPENSSL_VERSION_NUMBER >= 0x10100000L +#include +#endif /* * Check for key size creepage. @@ -1124,4 +1127,166 @@ engine_load_key(const char *file, SSL_CTX *ctx) #endif /* if HAVE_OPENSSL_ENGINE */ } +#if OPENSSL_VERSION_NUMBER >= 0x10100000L +void ssl_tls1_PRF(const uint8_t *seed, int seed_len, const uint8_t *secret, + int secret_len, uint8_t *output, int output_len) +{ + EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_TLS1_PRF, NULL); + ASSERT(EVP_PKEY_derive_init(pctx) == 1); + + ASSERT(EVP_PKEY_CTX_set_tls1_prf_md(pctx, EVP_md5_sha1()) == 1); + + ASSERT(EVP_PKEY_CTX_set1_tls1_prf_secret(pctx, secret, secret_len) == 1); + + ASSERT(EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, seed, seed_len) == 1); + + size_t out_len = output_len; + ASSERT (EVP_PKEY_derive(pctx, output, &out_len) == 1); + ASSERT (out_len == output_len); +} +#else +/* + * Generate the hash required by for the \c tls1_PRF function. + * + * We cannot use our normal hmac_* function as they do not work + * in a FIPS environment (no MD5 allowed, which we need). Instead + * we need to directly use the EVP_MD_* API with the special + * EVP_MD_CTX_FLAG_NON_FIPS_ALLOW flag. + * + * + * The function below is adapted from OpenSSL 1.0.2t + * + * @param md_kt Message digest to use + * @param sec Secret to base the hash on + * @param sec_len Length of the secret + * @param seed Seed to hash + * @param seed_len Length of the seed + * @param out Output buffer + * @param olen Length of the output buffer + */ +static +int tls1_P_hash(const EVP_MD *md, const unsigned char *sec, + int sec_len, + const void *seed, int seed_len, + unsigned char *out, int olen) +{ + int chunk; + size_t j; + EVP_MD_CTX ctx, ctx_tmp, ctx_init; + EVP_PKEY *mac_key; + unsigned char A1[EVP_MAX_MD_SIZE]; + size_t A1_len; + int ret = 0; + + chunk = EVP_MD_size(md); + OPENSSL_assert(chunk >= 0); + + EVP_MD_CTX_init(&ctx); + EVP_MD_CTX_init(&ctx_tmp); + EVP_MD_CTX_init(&ctx_init); + EVP_MD_CTX_set_flags(&ctx_init, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); + mac_key = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, sec, sec_len); + if (!mac_key) + goto err; + if (!EVP_DigestSignInit(&ctx_init, NULL, md, NULL, mac_key)) + goto err; + if (!EVP_MD_CTX_copy_ex(&ctx, &ctx_init)) + goto err; + if (!EVP_DigestSignUpdate(&ctx, seed, seed_len)) + goto err; + if (!EVP_DigestSignFinal(&ctx, A1, &A1_len)) + goto err; + + for (;;) { + /* Reinit mac contexts */ + if (!EVP_MD_CTX_copy_ex(&ctx, &ctx_init)) + goto err; + if (!EVP_DigestSignUpdate(&ctx, A1, A1_len)) + goto err; + if (olen > chunk && !EVP_MD_CTX_copy_ex(&ctx_tmp, &ctx)) + goto err; + if (!EVP_DigestSignUpdate(&ctx, seed, seed_len)) + goto err; + + if (olen > chunk) + { + if (!EVP_DigestSignFinal(&ctx, out, &j)) + goto err; + out += j; + olen -= j; + /* calc the next A1 value */ + if (!EVP_DigestSignFinal(&ctx_tmp, A1, &A1_len)) + goto err; + } + else + { + /* last one */ + + if (!EVP_DigestSignFinal(&ctx, A1, &A1_len)) + goto err; + memcpy(out, A1, olen); + break; + } + } + ret = 1; +err: + EVP_PKEY_free(mac_key); + EVP_MD_CTX_cleanup(&ctx); + EVP_MD_CTX_cleanup(&ctx_tmp); + EVP_MD_CTX_cleanup(&ctx_init); + OPENSSL_cleanse(A1, sizeof(A1)); + return ret; +} + + +/* + * Use the TLS PRF function for generating data channel keys. + * This code is based on the OpenSSL library. + * + * TLS generates keys as such: + * + * master_secret[48] = PRF(pre_master_secret[48], "master secret", + * ClientHello.random[32] + ServerHello.random[32]) + * + * key_block[] = PRF(SecurityParameters.master_secret[48], + * "key expansion", + * SecurityParameters.server_random[32] + + * SecurityParameters.client_random[32]); + * + * Notes: + * + * (1) key_block contains a full set of 4 keys. + * (2) The pre-master secret is generated by the client. + */ +void ssl_tls1_PRF(const uint8_t *label, int label_len, const uint8_t *sec, + int slen, uint8_t *out1, int olen) +{ + struct gc_arena gc = gc_new(); + /* For some reason our md_kt_get("MD5") fails otherwise in the unit test */ + const md_kt_t *md5 = EVP_md5(); + const md_kt_t *sha1 = EVP_sha1(); + + uint8_t *out2 = (uint8_t *) gc_malloc(olen, false, &gc); + + int len = slen/2; + const uint8_t *S1 = sec; + const uint8_t *S2 = &(sec[len]); + len += (slen&1); /* add for odd, make longer */ + + if(!tls1_P_hash(md5,S1,len,label,label_len,out1,olen)) + + ASSERT(tls1_P_hash(sha1,S2,len,label,label_len,out2,olen)); + + for (int i = 0; iserver, "Server"); } -/* - * Generate the hash required by for the \c tls1_PRF function. - * - * @param md_kt Message digest to use - * @param sec Secret to base the hash on - * @param sec_len Length of the secret - * @param seed Seed to hash - * @param seed_len Length of the seed - * @param out Output buffer - * @param olen Length of the output buffer - */ -static void -tls1_P_hash(const md_kt_t *md_kt, - const uint8_t *sec, - int sec_len, - const uint8_t *seed, - int seed_len, - uint8_t *out, - int olen) -{ - struct gc_arena gc = gc_new(); - uint8_t A1[MAX_HMAC_KEY_LENGTH]; - -#ifdef ENABLE_DEBUG - const int olen_orig = olen; - const uint8_t *out_orig = out; -#endif - - hmac_ctx_t *ctx = hmac_ctx_new(); - hmac_ctx_t *ctx_tmp = hmac_ctx_new(); - - dmsg(D_SHOW_KEY_SOURCE, "tls1_P_hash sec: %s", format_hex(sec, sec_len, 0, &gc)); - dmsg(D_SHOW_KEY_SOURCE, "tls1_P_hash seed: %s", format_hex(seed, seed_len, 0, &gc)); - - int chunk = md_kt_size(md_kt); - unsigned int A1_len = md_kt_size(md_kt); - - hmac_ctx_init(ctx, sec, sec_len, md_kt); - hmac_ctx_init(ctx_tmp, sec, sec_len, md_kt); - - hmac_ctx_update(ctx,seed,seed_len); - hmac_ctx_final(ctx, A1); - - for (;; ) - { - hmac_ctx_reset(ctx); - hmac_ctx_reset(ctx_tmp); - hmac_ctx_update(ctx,A1,A1_len); - hmac_ctx_update(ctx_tmp,A1,A1_len); - hmac_ctx_update(ctx,seed,seed_len); - - if (olen > chunk) - { - hmac_ctx_final(ctx, out); - out += chunk; - olen -= chunk; - hmac_ctx_final(ctx_tmp, A1); /* calc the next A1 value */ - } - else /* last one */ - { - hmac_ctx_final(ctx, A1); - memcpy(out,A1,olen); - break; - } - } - hmac_ctx_cleanup(ctx); - hmac_ctx_free(ctx); - hmac_ctx_cleanup(ctx_tmp); - hmac_ctx_free(ctx_tmp); - secure_memzero(A1, sizeof(A1)); - - dmsg(D_SHOW_KEY_SOURCE, "tls1_P_hash out: %s", format_hex(out_orig, olen_orig, 0, &gc)); - gc_free(&gc); -} - -/* - * Use the TLS PRF function for generating data channel keys. - * This code is based on the OpenSSL library. - * - * TLS generates keys as such: - * - * master_secret[48] = PRF(pre_master_secret[48], "master secret", - * ClientHello.random[32] + ServerHello.random[32]) - * - * key_block[] = PRF(SecurityParameters.master_secret[48], - * "key expansion", - * SecurityParameters.server_random[32] + - * SecurityParameters.client_random[32]); - * - * Notes: - * - * (1) key_block contains a full set of 4 keys. - * (2) The pre-master secret is generated by the client. - */ -static void -tls1_PRF(const uint8_t *label, - int label_len, - const uint8_t *sec, - int slen, - uint8_t *out1, - int olen) -{ - struct gc_arena gc = gc_new(); - const md_kt_t *md5 = md_kt_get("MD5"); - const md_kt_t *sha1 = md_kt_get("SHA1"); - - uint8_t *out2 = (uint8_t *) gc_malloc(olen, false, &gc); - - int len = slen/2; - const uint8_t *S1 = sec; - const uint8_t *S2 = &(sec[len]); - len += (slen&1); /* add for odd, make longer */ - - tls1_P_hash(md5,S1,len,label,label_len,out1,olen); - tls1_P_hash(sha1,S2,len,label,label_len,out2,olen); - - for (int i = 0; i #include "crypto.h" +#include "ssl_backend.h" #include "mock_msg.h" @@ -136,12 +137,43 @@ crypto_translate_cipher_names(void **state) test_cipher_names("id-aes256-GCM", "AES-256-GCM"); } + +static uint8_t good_prf[32] = {0xd9, 0x8c, 0x85, 0x18, 0xc8, 0x5e, 0x94, 0x69, + 0x27, 0x91, 0x6a, 0xcf, 0xc2, 0xd5, 0x92, 0xfb, + 0xb1, 0x56, 0x7e, 0x4b, 0x4b, 0x14, 0x59, 0xe6, + 0xa9, 0x04, 0xac, 0x2d, 0xda, 0xb7, 0x2d, 0x67}; +static void +crypto_test_tls_prf(void **state) +{ + const char *seedstr = "Quis aute iure reprehenderit in voluptate " + "velit esse cillum dolore"; + const unsigned char *seed = (const unsigned char *) seedstr; + const size_t seed_len = strlen(seedstr); + + + + + const char* ipsumlorem = "Lorem ipsum dolor sit amet, consectetur " + "adipisici elit, sed eiusmod tempor incidunt ut " + "labore et dolore magna aliqua."; + + const unsigned char *secret = (const unsigned char *) ipsumlorem; + size_t secret_len = strlen((const char *)secret); + + + uint8_t out[32]; + ssl_tls1_PRF(seed, seed_len, secret, secret_len, out, sizeof(out)); + + assert_memory_equal(good_prf, out, sizeof(out)); +} + int main(void) { const struct CMUnitTest tests[] = { cmocka_unit_test(crypto_pem_encode_decode_loopback), cmocka_unit_test(crypto_translate_cipher_names), + cmocka_unit_test(crypto_test_tls_prf) }; #if defined(ENABLE_CRYPTO_OPENSSL) From patchwork Mon Feb 1 06:43:10 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arne Schwabe X-Patchwork-Id: 1590 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director15.mail.ord1d.rsapps.net ([172.30.191.6]) by backend30.mail.ord1d.rsapps.net with LMTP id 2OtAFPE9GGBQXAAAIUCqbw (envelope-from ) for ; Mon, 01 Feb 2021 12:44:17 -0500 Received: from proxy16.mail.ord1d.rsapps.net ([172.30.191.6]) by director15.mail.ord1d.rsapps.net with LMTP id AOnzE/E9GGDzJgAAIcMcQg (envelope-from ) for ; Mon, 01 Feb 2021 12:44:17 -0500 Received: from smtp14.gate.ord1d ([172.30.191.6]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy16.mail.ord1d.rsapps.net with LMTPS id qJCVE/E9GGA1AgAAetu3IA (envelope-from ) for ; Mon, 01 Feb 2021 12:44:17 -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: smtp14.gate.ord1d.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; dmarc=none (p=nil; dis=none) header.from=rfc2549.org X-Suspicious-Flag: YES X-Classification-ID: 1a59c704-64b5-11eb-aa0b-525400504bae-1-1 Received: from [216.105.38.7] ([216.105.38.7:52838] helo=lists.sourceforge.net) by smtp14.gate.ord1d.rsapps.net (envelope-from ) (ecelerity 4.2.38.62370 r(:)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id C1/9E-04334-0FD38106; Mon, 01 Feb 2021 12:44:16 -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 1l6dEX-0001i3-S5; Mon, 01 Feb 2021 17:43:29 +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 1l6dEW-0001hq-OR for openvpn-devel@lists.sourceforge.net; Mon, 01 Feb 2021 17:43:28 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=References:In-Reply-To:Message-Id:Date:Subject:To: From:Sender:Reply-To:Cc:MIME-Version:Content-Type:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=o2jP4g+PhP6V0KY1j0RuvNeCiuoemaGSYRCqYmP4K8A=; b=DX7KYrsSPJKskKl1WesWn9kSiT MgYnhFZ0tWLpNBPqQ6mPRT4FVdaJbKlpGeFtxVGuQFeSBMTdyODtvQqcMN0azTymwdJMbqQ5LG0GO 3Xagg0mbI1/hynhvfWBAIE2CASxUkQ0Ls4aQreIZqP0IVLSbn+cChqJ7FeGteVC8eplk=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=References:In-Reply-To:Message-Id:Date:Subject:To:From:Sender:Reply-To:Cc :MIME-Version:Content-Type:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=o2jP4g+PhP6V0KY1j0RuvNeCiuoemaGSYRCqYmP4K8A=; b=dUseuv24HubQ3RwMyutzbuiAbJ t308EAeon/mYocJgFa7fQ6vfS5VNAU3950cvUa8Zj59fjHRPIaIiG+YHmWZuWA5vIXx731YtOZIqf D+Kn5eJRH1lJG2IlaG7vGJM/AvUdmYFIIaMmCTmQPdTqZWON1KVyHSzU7iARuAjJ1l18=; Received: from mail.blinkt.de ([192.26.174.232]) by sfi-mx-1.v28.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.92.2) id 1l6dEO-00BGHy-HJ for openvpn-devel@lists.sourceforge.net; Mon, 01 Feb 2021 17:43:28 +0000 Received: from kamera.blinkt.de ([2001:638:502:390:20c:29ff:fec8:535c]) by mail.blinkt.de with smtp (Exim 4.94 (FreeBSD)) (envelope-from ) id 1l6dEE-000NVd-K9 for openvpn-devel@lists.sourceforge.net; Mon, 01 Feb 2021 18:43:10 +0100 Received: (nullmailer pid 22206 invoked by uid 10006); Mon, 01 Feb 2021 17:43:10 -0000 From: Arne Schwabe To: openvpn-devel@lists.sourceforge.net Date: Mon, 1 Feb 2021 18:43:10 +0100 Message-Id: <20210201174310.22153-4-arne@rfc2549.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210201174310.22153-1-arne@rfc2549.org> References: <20210201174310.22153-1-arne@rfc2549.org> X-Spam-Report: Spam Filtering performed by mx.sourceforge.net. See http://spamassassin.org/tag/ for more details. 0.2 HEADER_FROM_DIFFERENT_DOMAINS From and EnvelopeFrom 2nd level mail domains are different 0.0 SPF_NONE SPF: sender does not publish an SPF Record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record X-Headers-End: 1l6dEO-00BGHy-HJ Subject: [Openvpn-devel] [PATCH v3 3/3] Handle the unlikely case that PRF generation fails 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: , MIME-Version: 1.0 Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox We never had handling of this failure condition. But should it happen we can now handle it. Signed-off-by: Arne Schwabe --- src/openvpn/crypto_backend.h | 4 +- src/openvpn/crypto_mbedtls.c | 17 ++++---- src/openvpn/crypto_openssl.c | 50 ++++++++++++++++++----- src/openvpn/ssl.c | 78 ++++++++++++++++++++++-------------- 4 files changed, 99 insertions(+), 50 deletions(-) diff --git a/src/openvpn/crypto_backend.h b/src/openvpn/crypto_backend.h index d86d9a34..384ffc80 100644 --- a/src/openvpn/crypto_backend.h +++ b/src/openvpn/crypto_backend.h @@ -710,7 +710,9 @@ const char *translate_cipher_name_to_openvpn(const char *cipher_name); * @param secret_len length of the secret * @param output output destination * @param output_len length of output/number of bytes to generate + * + * @return true if successful, false on any error */ -void ssl_tls1_PRF(const uint8_t *seed, int seed_len, const uint8_t *secret, +bool ssl_tls1_PRF(const uint8_t *seed, int seed_len, const uint8_t *secret, int secret_len, uint8_t *output, int output_len); #endif /* CRYPTO_BACKEND_H_ */ diff --git a/src/openvpn/crypto_mbedtls.c b/src/openvpn/crypto_mbedtls.c index 5ed88d6d..3b28ba26 100644 --- a/src/openvpn/crypto_mbedtls.c +++ b/src/openvpn/crypto_mbedtls.c @@ -987,11 +987,12 @@ memcmp_constant_time(const void *a, const void *b, size_t size) } /* mbedtls-2.18.0 or newer */ #ifdef HAVE_MBEDTLS_SSL_TLS_PRF -void ssl_tls1_PRF(const uint8_t *seed, int seed_len, const uint8_t *secret, +bool ssl_tls1_PRF(const uint8_t *seed, int seed_len, const uint8_t *secret, int secret_len, uint8_t *output, int output_len) { - mbedtls_ssl_tls_prf(MBEDTLS_SSL_TLS_PRF_TLS1, secret, secret_len, "", seed, - seed_len, output, output_len); + return mbed_ok(mbedtls_ssl_tls_prf(MBEDTLS_SSL_TLS_PRF_TLS1, secret, + secret_len, "", seed, seed_len, output, + output_len)); } #else /* @@ -1088,9 +1089,8 @@ tls1_P_hash(const md_kt_t *md_kt, * (1) key_block contains a full set of 4 keys. * (2) The pre-master secret is generated by the client. */ -void -ssl_tls1_PRF(const uint8_t *label, int label_len, const uint8_t *sec, int slen, - uint8_t *out1, int olen) +bool ssl_tls1_PRF(const uint8_t *label, int label_len, const uint8_t *sec, + int slen, uint8_t *out1, int olen) { struct gc_arena gc = gc_new(); const md_kt_t *md5 = md_kt_get("MD5"); @@ -1103,8 +1103,8 @@ ssl_tls1_PRF(const uint8_t *label, int label_len, const uint8_t *sec, int slen, const uint8_t *S2 = &(sec[len]); len += (slen&1); /* add for odd, make longer */ - tls1_P_hash(md5,S1,len,label,label_len,out1,olen); - tls1_P_hash(sha1,S2,len,label,label_len,out2,olen); + tls1_P_hash(md5, S1, len, label, label_len, out1, olen); + tls1_P_hash(sha1, S2, len, label, label_len, out2, olen); for (int i = 0; i= 0x10100000L -void ssl_tls1_PRF(const uint8_t *seed, int seed_len, const uint8_t *secret, +bool ssl_tls1_PRF(const uint8_t *seed, int seed_len, const uint8_t *secret, int secret_len, uint8_t *output, int output_len) { EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_TLS1_PRF, NULL); - ASSERT(EVP_PKEY_derive_init(pctx) == 1); + if(!EVP_PKEY_derive_init(pctx)) + { + return false; + } - ASSERT(EVP_PKEY_CTX_set_tls1_prf_md(pctx, EVP_md5_sha1()) == 1); - ASSERT(EVP_PKEY_CTX_set1_tls1_prf_secret(pctx, secret, secret_len) == 1); + if(!EVP_PKEY_CTX_set_tls1_prf_md(pctx, EVP_md5_sha1())) + { + return false; + } - ASSERT(EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, seed, seed_len) == 1); + if(!EVP_PKEY_CTX_set1_tls1_prf_secret(pctx, secret, secret_len)) + { + return false; + } + + if(!EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, seed, seed_len)) + { + return false; + } size_t out_len = output_len; - ASSERT (EVP_PKEY_derive(pctx, output, &out_len) == 1); - ASSERT (out_len == output_len); + if(!EVP_PKEY_derive(pctx, output, &out_len)) + { + return false; + } + if (out_len != output_len) + { + return false; + } + return true; } #else /* @@ -1258,9 +1278,10 @@ err: * (1) key_block contains a full set of 4 keys. * (2) The pre-master secret is generated by the client. */ -void ssl_tls1_PRF(const uint8_t *label, int label_len, const uint8_t *sec, +bool ssl_tls1_PRF(const uint8_t *label, int label_len, const uint8_t *sec, int slen, uint8_t *out1, int olen) { + bool ret = true; struct gc_arena gc = gc_new(); /* For some reason our md_kt_get("MD5") fails otherwise in the unit test */ const md_kt_t *md5 = EVP_md5(); @@ -1274,8 +1295,16 @@ void ssl_tls1_PRF(const uint8_t *label, int label_len, const uint8_t *sec, len += (slen&1); /* add for odd, make longer */ if(!tls1_P_hash(md5,S1,len,label,label_len,out1,olen)) + { + ret = false; + goto done; + } - ASSERT(tls1_P_hash(sha1,S2,len,label,label_len,out2,olen)); + if(!tls1_P_hash(sha1,S2,len,label,label_len,out2,olen)) + { + ret = false; + goto done; + } for (int i = 0; iserver, "Server"); } -static void +static bool openvpn_PRF(const uint8_t *secret, int secret_len, const char *label, @@ -1593,6 +1593,7 @@ openvpn_PRF(const uint8_t *secret, uint8_t *output, int output_len) { + bool ret = true; /* concatenate seed components */ struct buffer seed = alloc_buf(strlen(label) @@ -1614,12 +1615,16 @@ openvpn_PRF(const uint8_t *secret, } /* compute PRF */ - ssl_tls1_PRF(BPTR(&seed), BLEN(&seed), secret, secret_len, output, output_len); + if (!ssl_tls1_PRF(BPTR(&seed), BLEN(&seed), secret, secret_len, output, output_len)) + { + ret = false; + } buf_clear(&seed); free_buf(&seed); VALGRIND_MAKE_READABLE((void *)output, output_len); + return ret; } static void @@ -1654,8 +1659,8 @@ generate_key_expansion_tls_export(struct tls_session *session, struct key2 *key2 return true; } -static struct key2 -generate_key_expansion_openvpn_prf(const struct tls_session *session) +static bool +generate_key_expansion_openvpn_prf(const struct tls_session *session, struct key2 *key2) { uint8_t master[48] = { 0 }; @@ -1671,33 +1676,40 @@ generate_key_expansion_openvpn_prf(const struct tls_session *session) key_source2_print(key_src); /* compute master secret */ - openvpn_PRF(key_src->client.pre_master, - sizeof(key_src->client.pre_master), - KEY_EXPANSION_ID " master secret", - key_src->client.random1, - sizeof(key_src->client.random1), - key_src->server.random1, - sizeof(key_src->server.random1), - NULL, - NULL, - master, - sizeof(master)); + if(!openvpn_PRF(key_src->client.pre_master, + sizeof(key_src->client.pre_master), + KEY_EXPANSION_ID " master secret", + key_src->client.random1, + sizeof(key_src->client.random1), + key_src->server.random1, + sizeof(key_src->server.random1), + NULL, + NULL, + master, + sizeof(master))) + { + return false; + } - struct key2 key2; /* compute key expansion */ - openvpn_PRF(master, - sizeof(master), - KEY_EXPANSION_ID " key expansion", - key_src->client.random2, - sizeof(key_src->client.random2), - key_src->server.random2, - sizeof(key_src->server.random2), - client_sid, - server_sid, - (uint8_t *)key2.keys, - sizeof(key2.keys)); + if (!openvpn_PRF(master, + sizeof(master), + KEY_EXPANSION_ID " key expansion", + key_src->client.random2, + sizeof(key_src->client.random2), + key_src->server.random2, + sizeof(key_src->server.random2), + client_sid, + server_sid, + (uint8_t *)key2->keys, + sizeof(key2->keys))) + { + return false; + } secure_memzero(&master, sizeof(master)); + + /* * fixup_key only correctly sets DES parity bits if the cipher is a * DES variant. @@ -1712,11 +1724,11 @@ generate_key_expansion_openvpn_prf(const struct tls_session *session) */ for (int i = 0; i < 2; ++i) { - fixup_key(&key2.keys[i], &session->opt->key_type); + fixup_key(&key2->keys[i], &session->opt->key_type); } - key2.n = 2; + key2->n = 2; - return key2; + return true; } /* @@ -1748,7 +1760,11 @@ generate_key_expansion(struct key_ctx_bi *key, } else { - key2 = generate_key_expansion_openvpn_prf(session); + if (!generate_key_expansion_openvpn_prf(session, &key2)) + { + msg(D_TLS_ERRORS, "TLS Error: PRF calcuation failed"); + goto exit; + } } key2_print(&key2, &session->opt->key_type,