From patchwork Wed Dec 1 07:07:21 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arne Schwabe X-Patchwork-Id: 2098 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director9.mail.ord1d.rsapps.net ([172.31.255.6]) by backend30.mail.ord1d.rsapps.net with LMTP id wCiNJSW6p2EGbAAAIUCqbw (envelope-from ) for ; Wed, 01 Dec 2021 13:08:37 -0500 Received: from proxy19.mail.iad3b.rsapps.net ([172.31.255.6]) by director9.mail.ord1d.rsapps.net with LMTP id EA1KJSW6p2F7ZAAAalYnBA (envelope-from ) for ; Wed, 01 Dec 2021 13:08:37 -0500 Received: from smtp23.gate.iad3b ([172.31.255.6]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy19.mail.iad3b.rsapps.net with LMTPS id yAk+HSW6p2EOcAAAIG4riQ (envelope-from ) for ; Wed, 01 Dec 2021 13:08:37 -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: smtp23.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; dmarc=none (p=nil; dis=none) header.from=rfc2549.org X-Suspicious-Flag: YES X-Classification-ID: b3b347d0-52d1-11ec-864c-525400aa5716-1-1 Received: from [216.105.38.7] ([216.105.38.7:55196] helo=lists.sourceforge.net) by smtp23.gate.iad3b.rsapps.net (envelope-from ) (ecelerity 4.2.38.62370 r(:)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id 00/5A-27394-42AB7A16; Wed, 01 Dec 2021 13:08:36 -0500 Received: from [127.0.0.1] (helo=sfs-ml-1.v29.lw.sourceforge.com) by sfs-ml-1.v29.lw.sourceforge.com with esmtp (Exim 4.94.2) (envelope-from ) id 1msU1D-0000GM-1Z; Wed, 01 Dec 2021 18:07:48 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-1.v29.lw.sourceforge.com with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1msU16-0000Fp-PT for openvpn-devel@lists.sourceforge.net; Wed, 01 Dec 2021 18:07:41 +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:References: In-Reply-To:Message-Id:Date:Subject:To:From:Sender:Reply-To:Cc:Content-Type: 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=Ns3a+oEjuC2FpWwk/69GdkDOIIDfzx/WmPdqWwThzzc=; b=PKagRmA3+VqGuoOKKaC8gHq5vi CoZTNwCljByFG0TVg3YSwKNR1VDMV7zTgnMBdNMFYMHkd0A1J+Zw8Z2s7f31kgag//xCEIGqkkNIL zEs78ERy96HZu1GgtFIlZf88z3R0nzpsHjZBE9ye+ejeMvtw/ppl/tsQnGhQjDMkChi4=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-Id: Date:Subject:To:From:Sender:Reply-To:Cc:Content-Type: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=Ns3a+oEjuC2FpWwk/69GdkDOIIDfzx/WmPdqWwThzzc=; b=gfOvu96jidku1GvLsl/nhkWbcS Gm3fNnig8xWLZmDbIPivqeNm8vJx4yC0xlWTBGTksY16oW2BWmcZ6gmTHxbQTb/d1GT1wQX5ec/sL YdMpZ6LNZxtAYVqtPUwZf30lwG0vDP9Cu16tPVK+IugZ417/fUahkyjEC+l7JUGdQg8o=; 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 1msU15-0005En-P9 for openvpn-devel@lists.sourceforge.net; Wed, 01 Dec 2021 18:07:41 +0000 Received: from kamera.blinkt.de ([2001:638:502:390:20c:29ff:fec8:535c]) by mail.blinkt.de with smtp (Exim 4.94.2 (FreeBSD)) (envelope-from ) id 1msU0t-0000KK-IP for openvpn-devel@lists.sourceforge.net; Wed, 01 Dec 2021 19:07:27 +0100 Received: (nullmailer pid 2496955 invoked by uid 10006); Wed, 01 Dec 2021 18:07:27 -0000 From: Arne Schwabe To: openvpn-devel@lists.sourceforge.net Date: Wed, 1 Dec 2021 19:07:21 +0100 Message-Id: <20211201180727.2496903-3-arne@rfc2549.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20211201180727.2496903-1-arne@rfc2549.org> References: <20211201180727.2496903-1-arne@rfc2549.org> MIME-Version: 1.0 X-Spam-Report: Spam detection software, running on the system "util-spamd-1.v13.lw.sourceforge.com", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: We currently have a number of calls that fetch the cipher_kt from a cipher_ctx to then do a query on the cipher_kt. Directly fetching the desired property from the context is cleaner and helps for usi [...] Content analysis details: (0.3 points, 6.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.0 SPF_NONE SPF: sender does not publish an SPF Record 0.2 HEADER_FROM_DIFFERENT_DOMAINS From and EnvelopeFrom 2nd level mail domains are different X-Headers-End: 1msU15-0005En-P9 Subject: [Openvpn-devel] [PATCH 3/9] Remove cipher_ctx_get_cipher_kt and replace with direct context calls 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 We currently have a number of calls that fetch the cipher_kt from a cipher_ctx to then do a query on the cipher_kt. Directly fetching the desired property from the context is cleaner and helps for using the proper APIs with OpenSSL 3.0 and mbed TLS 3.0 Signed-off-by: Arne Schwabe Acked-by: Gert Doering --- src/openvpn/crypto.c | 36 ++++++++--------------- src/openvpn/crypto_backend.h | 29 ++++++++++++++---- src/openvpn/crypto_mbedtls.c | 21 +++++++++++-- src/openvpn/crypto_openssl.c | 57 ++++++++++++++++++++++++++++++++++-- src/openvpn/openssl_compat.h | 1 + src/openvpn/ssl.c | 8 ++--- src/openvpn/ssl_ncp.c | 18 +++++------- 7 files changed, 119 insertions(+), 51 deletions(-) diff --git a/src/openvpn/crypto.c b/src/openvpn/crypto.c index 270d83c56..27ed1402c 100644 --- a/src/openvpn/crypto.c +++ b/src/openvpn/crypto.c @@ -68,12 +68,10 @@ openvpn_encrypt_aead(struct buffer *buf, struct buffer work, int outlen = 0; const struct key_ctx *ctx = &opt->key_ctx_bi.encrypt; uint8_t *mac_out = NULL; - const cipher_kt_t *cipher_kt = cipher_ctx_get_cipher_kt(ctx->cipher); const int mac_len = OPENVPN_AEAD_TAG_LENGTH; /* IV, packet-ID and implicit IV required for this mode. */ ASSERT(ctx->cipher); - ASSERT(cipher_kt_mode_aead(cipher_kt)); ASSERT(packet_id_initialized(&opt->packet_id)); gc_init(&gc); @@ -171,7 +169,6 @@ openvpn_encrypt_v1(struct buffer *buf, struct buffer work, { uint8_t iv_buf[OPENVPN_MAX_IV_LENGTH] = {0}; const int iv_size = cipher_ctx_iv_length(ctx->cipher); - const cipher_kt_t *cipher_kt = cipher_ctx_get_cipher_kt(ctx->cipher); int outlen; /* Reserve space for HMAC */ @@ -182,7 +179,7 @@ openvpn_encrypt_v1(struct buffer *buf, struct buffer work, hmac_start = BEND(&work); } - if (cipher_kt_mode_cbc(cipher_kt)) + if (cipher_ctx_mode_cbc(ctx->cipher)) { /* generate pseudo-random IV */ prng_bytes(iv_buf, iv_size); @@ -197,7 +194,7 @@ openvpn_encrypt_v1(struct buffer *buf, struct buffer work, goto err; } } - else if (cipher_kt_mode_ofb_cfb(cipher_kt)) + else if (cipher_ctx_mode_ofb_cfb(ctx->cipher)) { struct buffer b; @@ -245,7 +242,7 @@ openvpn_encrypt_v1(struct buffer *buf, struct buffer work, ASSERT(buf_inc_len(&work, outlen)); /* For all CBC mode ciphers, check the last block is complete */ - ASSERT(cipher_kt_mode(cipher_kt) != OPENVPN_MODE_CBC + ASSERT(cipher_ctx_mode(ctx->cipher) != OPENVPN_MODE_CBC || outlen == iv_size); } else /* No Encryption */ @@ -301,10 +298,7 @@ openvpn_encrypt(struct buffer *buf, struct buffer work, { if (buf->len > 0 && opt) { - const cipher_kt_t *cipher_kt = - cipher_ctx_get_cipher_kt(opt->key_ctx_bi.encrypt.cipher); - - if (cipher_kt_mode_aead(cipher_kt)) + if (cipher_ctx_mode_aead(opt->key_ctx_bi.encrypt.cipher)) { openvpn_encrypt_aead(buf, work, opt); } @@ -360,7 +354,6 @@ openvpn_decrypt_aead(struct buffer *buf, struct buffer work, static const char error_prefix[] = "AEAD Decrypt error"; struct packet_id_net pin = { 0 }; const struct key_ctx *ctx = &opt->key_ctx_bi.decrypt; - const cipher_kt_t *cipher_kt = cipher_ctx_get_cipher_kt(ctx->cipher); uint8_t *tag_ptr = NULL; int outlen; struct gc_arena gc; @@ -371,7 +364,6 @@ openvpn_decrypt_aead(struct buffer *buf, struct buffer work, ASSERT(frame); ASSERT(buf->len > 0); ASSERT(ctx->cipher); - ASSERT(cipher_kt_mode_aead(cipher_kt)); dmsg(D_PACKET_CONTENT, "DECRYPT FROM: %s", format_hex(BPTR(buf), BLEN(buf), 80, &gc)); @@ -537,7 +529,6 @@ openvpn_decrypt_v1(struct buffer *buf, struct buffer work, if (ctx->cipher) { const int iv_size = cipher_ctx_iv_length(ctx->cipher); - const cipher_kt_t *cipher_kt = cipher_ctx_get_cipher_kt(ctx->cipher); uint8_t iv_buf[OPENVPN_MAX_IV_LENGTH] = { 0 }; int outlen; @@ -589,7 +580,7 @@ openvpn_decrypt_v1(struct buffer *buf, struct buffer work, /* Get packet ID from plaintext buffer or IV, depending on cipher mode */ { - if (cipher_kt_mode_cbc(cipher_kt)) + if (cipher_ctx_mode_cbc(ctx->cipher)) { if (packet_id_initialized(&opt->packet_id)) { @@ -600,7 +591,7 @@ openvpn_decrypt_v1(struct buffer *buf, struct buffer work, have_pin = true; } } - else if (cipher_kt_mode_ofb_cfb(cipher_kt)) + else if (cipher_ctx_mode_ofb_cfb(ctx->cipher)) { struct buffer b; @@ -660,8 +651,7 @@ openvpn_decrypt(struct buffer *buf, struct buffer work, if (buf->len > 0 && opt) { - const struct key_ctx *ctx = &opt->key_ctx_bi.decrypt; - if (cipher_kt_mode_aead(cipher_ctx_get_cipher_kt(ctx->cipher))) + if (cipher_ctx_mode_aead(opt->key_ctx_bi.decrypt.cipher)) { ret = openvpn_decrypt_aead(buf, work, opt, frame, ad_start); } @@ -1036,14 +1026,12 @@ test_crypto(struct crypto_options *co, struct frame *frame) /* init implicit IV */ { - const cipher_kt_t *cipher = - cipher_ctx_get_cipher_kt(co->key_ctx_bi.encrypt.cipher); - - if (cipher_kt_mode_aead(cipher)) + cipher_ctx_t *cipher = co->key_ctx_bi.encrypt.cipher; + if (cipher_ctx_mode_aead(cipher)) { - size_t impl_iv_len = cipher_kt_iv_size(cipher) - sizeof(packet_id_type); - ASSERT(cipher_kt_iv_size(cipher) <= OPENVPN_MAX_IV_LENGTH); - ASSERT(cipher_kt_iv_size(cipher) >= OPENVPN_AEAD_MIN_IV_LEN); + size_t impl_iv_len = cipher_ctx_iv_length(cipher) - sizeof(packet_id_type); + ASSERT(cipher_ctx_iv_length(cipher) <= OPENVPN_MAX_IV_LENGTH); + ASSERT(cipher_ctx_iv_length(cipher) >= OPENVPN_AEAD_MIN_IV_LEN); /* Generate dummy implicit IV */ ASSERT(rand_bytes(co->key_ctx_bi.encrypt.implicit_iv, diff --git a/src/openvpn/crypto_backend.h b/src/openvpn/crypto_backend.h index 7c1f123e4..925d1db37 100644 --- a/src/openvpn/crypto_backend.h +++ b/src/openvpn/crypto_backend.h @@ -338,7 +338,7 @@ void cipher_ctx_init(cipher_ctx_t *ctx, const uint8_t *key, int key_len, * @param ctx The cipher's context * * @return Size of the IV, in bytes, or \c 0 if the cipher does not - * use an IV or ctx was NULL. + * use an IV. */ int cipher_ctx_iv_length(const cipher_ctx_t *ctx); @@ -371,14 +371,31 @@ int cipher_ctx_block_size(const cipher_ctx_t *ctx); int cipher_ctx_mode(const cipher_ctx_t *ctx); /** - * Returns the static cipher parameters for this context. + * Check if the supplied cipher is a supported CBC mode cipher. + * + * @param ctx Cipher's context. May not be NULL. + * + * @return true iff the cipher is a CBC mode cipher. + */ +bool cipher_ctx_mode_cbc(const cipher_ctx_t *ctx); + +/** + * Check if the supplied cipher is a supported OFB or CFB mode cipher. + * + * @param ctx Cipher's context. May not be NULL. + * + * @return true iff the cipher is a OFB or CFB mode cipher. + */ +bool cipher_ctx_mode_ofb_cfb(const cipher_ctx_t *ctx); + +/** + * Check if the supplied cipher is a supported AEAD mode cipher. * - * @param ctx Cipher's context. + * @param ctx Cipher's context. May not be NULL. * - * @return Static cipher parameters for the supplied context, or - * NULL if unable to determine cipher parameters. + * @return true iff the cipher is a AEAD mode cipher. */ -const cipher_kt_t *cipher_ctx_get_cipher_kt(const cipher_ctx_t *ctx); +bool cipher_ctx_mode_aead(const cipher_ctx_t *ctx); /** * Resets the given cipher context, setting the IV to the specified value. diff --git a/src/openvpn/crypto_mbedtls.c b/src/openvpn/crypto_mbedtls.c index 893a4ab02..566baadde 100644 --- a/src/openvpn/crypto_mbedtls.c +++ b/src/openvpn/crypto_mbedtls.c @@ -591,10 +591,25 @@ cipher_ctx_mode(const mbedtls_cipher_context_t *ctx) return cipher_kt_mode(ctx->cipher_info); } -const cipher_kt_t * -cipher_ctx_get_cipher_kt(const cipher_ctx_t *ctx) +bool cipher_ctx_mode_cbc(const cipher_ctx_t *ctx) { - return ctx ? ctx->cipher_info : NULL; + return ctx && cipher_ctx_mode(ctx) == OPENVPN_MODE_CBC; +} + + +bool cipher_ctx_mode_ofb_cfb(const cipher_ctx_t *ctx) +{ + return ctx && (cipher_ctx_mode(ctx) == OPENVPN_MODE_OFB + || cipher_ctx_mode(ctx) == OPENVPN_MODE_CFB); +} + +bool cipher_ctx_mode_aead(const cipher_ctx_t *ctx) +{ + return ctx && (cipher_ctx_mode(ctx) == OPENVPN_MODE_GCM +#ifdef MBEDTLS_CHACHAPOLY_C + || cipher_ctx_mode(ctx) == MBEDTLS_MODE_CHACHAPOLY +#endif + ); } int diff --git a/src/openvpn/crypto_openssl.c b/src/openvpn/crypto_openssl.c index 3044ea944..9d6c7c807 100644 --- a/src/openvpn/crypto_openssl.c +++ b/src/openvpn/crypto_openssl.c @@ -797,10 +797,61 @@ cipher_ctx_mode(const EVP_CIPHER_CTX *ctx) return EVP_CIPHER_CTX_mode(ctx); } -const cipher_kt_t * -cipher_ctx_get_cipher_kt(const cipher_ctx_t *ctx) + +bool +cipher_ctx_mode_cbc(const cipher_ctx_t *ctx) +{ + if (!ctx) + { + return false; + } + + int flags = EVP_CIPHER_CTX_flags(ctx); + int mode = EVP_CIPHER_CTX_mode(ctx); + + return mode == EVP_CIPH_CBC_MODE + /* Exclude AEAD cipher modes, they require a different API */ +#ifdef EVP_CIPH_FLAG_CTS + && !(flags & EVP_CIPH_FLAG_CTS) +#endif + && !(flags & EVP_CIPH_FLAG_AEAD_CIPHER); +} + +bool +cipher_ctx_mode_ofb_cfb(const cipher_ctx_t *ctx) +{ + if (!ctx) + { + return false; + } + + int mode = EVP_CIPHER_CTX_get_mode(ctx); + + return (mode == EVP_CIPH_OFB_MODE || mode == EVP_CIPH_CFB_MODE) + /* Exclude AEAD cipher modes, they require a different API */ + && !(EVP_CIPHER_CTX_flags(ctx) & EVP_CIPH_FLAG_AEAD_CIPHER); +} + +bool +cipher_ctx_mode_aead(const cipher_ctx_t *ctx) { - return ctx ? EVP_CIPHER_CTX_cipher(ctx) : NULL; + if (ctx) + { + int flags = EVP_CIPHER_CTX_flags(ctx); + if (flags & EVP_CIPH_FLAG_AEAD_CIPHER) + { + return true; + } + +#if defined(NID_chacha20_poly1305) && OPENSSL_VERSION_NUMBER < 0x30000000L + if (EVP_CIPHER_CTX_nid(ctx) == NID_chacha20_poly1305) + { + return true; + } +#endif + } + + return false; } diff --git a/src/openvpn/openssl_compat.h b/src/openvpn/openssl_compat.h index cbd7fd1d2..54fd5d60f 100644 --- a/src/openvpn/openssl_compat.h +++ b/src/openvpn/openssl_compat.h @@ -757,6 +757,7 @@ int EVP_PKEY_get_group_name(EVP_PKEY *pkey, char *gname, size_t gname_sz, #if OPENSSL_VERSION_NUMBER < 0x30000000L #define EVP_MD_get0_name EVP_MD_name +#define EVP_CIPHER_CTX_get_mode EVP_CIPHER_CTX_mode /* Mimics the functions but only when the default context without * options is chosen */ diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c index ad3e08274..3de229e39 100644 --- a/src/openvpn/ssl.c +++ b/src/openvpn/ssl.c @@ -1803,14 +1803,12 @@ exit: static void key_ctx_update_implicit_iv(struct key_ctx *ctx, uint8_t *key, size_t key_len) { - const cipher_kt_t *cipher_kt = cipher_ctx_get_cipher_kt(ctx->cipher); - /* Only use implicit IV in AEAD cipher mode, where HMAC key is not used */ - if (cipher_kt_mode_aead(cipher_kt)) + if (cipher_ctx_mode_aead(ctx->cipher)) { size_t impl_iv_len = 0; - ASSERT(cipher_kt_iv_size(cipher_kt) >= OPENVPN_AEAD_MIN_IV_LEN); - impl_iv_len = cipher_kt_iv_size(cipher_kt) - sizeof(packet_id_type); + ASSERT(cipher_ctx_iv_length(ctx->cipher) >= OPENVPN_AEAD_MIN_IV_LEN); + impl_iv_len = cipher_ctx_iv_length(ctx->cipher) - sizeof(packet_id_type); ASSERT(impl_iv_len <= OPENVPN_MAX_IV_LENGTH); ASSERT(impl_iv_len <= key_len); memcpy(ctx->implicit_iv, key, impl_iv_len); diff --git a/src/openvpn/ssl_ncp.c b/src/openvpn/ssl_ncp.c index b0b248aae..e5cfbd180 100644 --- a/src/openvpn/ssl_ncp.c +++ b/src/openvpn/ssl_ncp.c @@ -466,19 +466,17 @@ p2p_mode_ncp(struct tls_multi *multi, struct tls_session *session) if (!common_cipher) { struct buffer out = alloc_buf_gc(128, &gc); - struct key_state *ks = get_key_scan(multi, KS_PRIMARY); + const cipher_kt_t *cipher = session->opt->key_type.cipher; - const cipher_ctx_t *ctx = ks->crypto_options.key_ctx_bi.encrypt.cipher; - const cipher_kt_t *cipher = cipher_ctx_get_cipher_kt(ctx); - const char *fallback_name = cipher_kt_name(cipher); + /* at this point we do not really know if our fallback is + * not enabled or if we use 'none' cipher as fallback, so + * keep this ambiguity here and print fallback-cipher: none + */ - if (!cipher) + const char *fallback_name = "none"; + if (cipher) { - /* at this point we do not really know if our fallback is - * not enabled or if we use 'none' cipher as fallback, so - * keep this ambiguity here and print fallback-cipher: none - */ - fallback_name = "none"; + fallback_name = cipher_kt_name(cipher); } buf_printf(&out, "(not negotiated, fallback-cipher: %s)", fallback_name);