From patchwork Wed Dec 29 05:34:45 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arne Schwabe X-Patchwork-Id: 2188 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director8.mail.ord1d.rsapps.net ([172.30.191.6]) by backend41.mail.ord1d.rsapps.net with LMTP id oMyQAn2OzGHeFQAAqwncew (envelope-from ) for ; Wed, 29 Dec 2021 11:36:13 -0500 Received: from proxy20.mail.ord1d.rsapps.net ([172.30.191.6]) by director8.mail.ord1d.rsapps.net with LMTP id uGyYH32OzGGPfQAAfY0hYg (envelope-from ) for ; Wed, 29 Dec 2021 11:36:13 -0500 Received: from smtp33.gate.ord1d ([172.30.191.6]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy20.mail.ord1d.rsapps.net with LMTPS id MGQuH32OzGHRLgAAsk8m8w (envelope-from ) for ; Wed, 29 Dec 2021 11:36:13 -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: smtp33.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: 6f241d38-68c5-11ec-9884-525400041ef2-1-1 Received: from [216.105.38.7] ([216.105.38.7:52432] helo=lists.sourceforge.net) by smtp33.gate.ord1d.rsapps.net (envelope-from ) (ecelerity 4.2.38.62370 r(:)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id B2/C2-00840-C7E8CC16; Wed, 29 Dec 2021 11:36:13 -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.94.2) (envelope-from ) id 1n2buq-0003qH-HR; Wed, 29 Dec 2021 16:35:04 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-2.v29.lw.sourceforge.com with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1n2buo-0003qB-SW for openvpn-devel@lists.sourceforge.net; Wed, 29 Dec 2021 16:35:02 +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=xcCCl5sak4iII3TUFKYLxystfcApDdb/XYQsbUs20c8=; b=YNTV80qnMLsVbIihettUV8J9Em hg+YAwWwU0CFVfl4i6ClwOicfVoFBefNjmv8AP/vcpC4KxaGsWjBVMAhhCC9k2hFqyq/FQ7IrUrL1 ZJDVVJ6ahdN8cA5V1nm3oHh5yVHpT1qnTu8Gh9tydQFbpFtruQnolwk0UCvkskyb7/GM=; 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=xcCCl5sak4iII3TUFKYLxystfcApDdb/XYQsbUs20c8=; b=J+3PPC6fKWtZhn+fs1IIVn3A6P qfWfW8agAczmEVxEZOtMVjzyitJgiYR5fE+kQwGFA73ilVs/+ypHcPTTfOFxffKkZRSbtt1WWABPK U69E1q8uhM0z2Lwyhf0EhOsx9lXwdrw4lpvNexm6SxVDHVeJ/sy8zRC84/T3rJTyWrpk=; 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.3) id 1n2buj-00Cwum-Mk for openvpn-devel@lists.sourceforge.net; Wed, 29 Dec 2021 16:35:02 +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 1n2buX-0000Bl-PA for openvpn-devel@lists.sourceforge.net; Wed, 29 Dec 2021 17:34:45 +0100 Received: (nullmailer pid 1893734 invoked by uid 10006); Wed, 29 Dec 2021 16:34:45 -0000 From: Arne Schwabe To: openvpn-devel@lists.sourceforge.net Date: Wed, 29 Dec 2021 17:34:45 +0100 Message-Id: <20211229163445.1893687-1-arne@rfc2549.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20211207170211.3275837-1-arne@rfc2549.org> References: <20211207170211.3275837-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: These functions are intended to lay the groundwork to later replace the distributed frame calculations and centralise the calculation in one place. Patch v2: clarify that the socks comments is assuming IPv4 and improve other comments Content analysis details: (0.3 points, 6.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.2 HEADER_FROM_DIFFERENT_DOMAINS From and EnvelopeFrom 2nd level mail domains are different 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 X-Headers-End: 1n2buj-00Cwum-Mk Subject: [Openvpn-devel] [PATCH v2 07/21] Add helper functions to calculate header/payload sizes 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 These functions are intended to lay the groundwork to later replace the distributed frame calculations and centralise the calculation in one place. Patch v2: clarify that the socks comments is assuming IPv4 and improve other comments Signed-off-by: Arne Schwabe Acked-by: Gert Doering --- src/openvpn/crypto.c | 55 ++++++++++++++++++++++++++++ src/openvpn/crypto.h | 18 +++++++++ src/openvpn/mtu.c | 87 ++++++++++++++++++++++++++++++++++++++++++++ src/openvpn/mtu.h | 54 +++++++++++++++++++++++++++ 4 files changed, 214 insertions(+) diff --git a/src/openvpn/crypto.c b/src/openvpn/crypto.c index dc7ba542..5626e2b6 100644 --- a/src/openvpn/crypto.c +++ b/src/openvpn/crypto.c @@ -667,6 +667,61 @@ openvpn_decrypt(struct buffer *buf, struct buffer work, return ret; } +unsigned int +calculate_crypto_overhead(const struct key_type *kt, + bool packet_id, + bool packet_id_long_form, + unsigned int payload_size, + bool occ) +{ + unsigned int crypto_overhead = 0; + + /* We always have a packet id, no matter if encrypted or unencrypted */ + if (packet_id) + { + crypto_overhead += packet_id_size(packet_id_long_form); + } + + if (cipher_kt_mode_aead(kt->cipher)) + { + /* For AEAD ciphers, we basically use a stream cipher/CTR for + * the encryption, so no overhead apart from the extra bytes + * we add */ + crypto_overhead += cipher_kt_tag_size(kt->cipher); + + if (occ) + { + /* the frame calculation of old clients adds these to the link-mtu + * even though they are not part of the actual packet */ + crypto_overhead += cipher_kt_iv_size(kt->cipher); + crypto_overhead += cipher_kt_block_size(kt->cipher); + } + } + else + { + if (cipher_defined(kt->cipher)) + { + /* CBC, OFB or CFB mode */ + /* This is a worst case upper bound of needing to add + * a full extra block for padding when the payload + * is exactly a multiple of the block size */ + if (occ || (cipher_kt_mode_cbc(kt->cipher) && + (payload_size % cipher_kt_block_size(kt->cipher) == 0))) + { + crypto_overhead += cipher_kt_block_size(kt->cipher); + } + /* IV is always added (no-iv has been removed a while ago) */ + crypto_overhead += cipher_kt_iv_size(kt->cipher); + } + if (md_defined(kt->digest)) + { + crypto_overhead += md_kt_size(kt->digest); + } + } + + return crypto_overhead; +} + void crypto_adjust_frame_parameters(struct frame *frame, const struct key_type *kt, diff --git a/src/openvpn/crypto.h b/src/openvpn/crypto.h index ad3543c1..5a67b7ac 100644 --- a/src/openvpn/crypto.h +++ b/src/openvpn/crypto.h @@ -415,6 +415,24 @@ void crypto_adjust_frame_parameters(struct frame *frame, bool packet_id, bool packet_id_long_form); +/** Calculate the maximum overhead that our encryption has + * on a packet. This does not include needed additional buffer size + * + * @param kt Struct with the crypto algorithm to use + * @param packet_id Whether packet_id is used + * @param packet_id_long_form Whether the packet id has the long form + * @param payload_size payload size, only used if occ is false + * @param occ if true calculates the overhead for crypto in the same + * incorrect way as all previous OpenVPN versions did, to + * end up with identical numbers for OCC compatibility + */ +unsigned int +calculate_crypto_overhead(const struct key_type *kt, + bool packet_id, + bool packet_id_long_form, + unsigned int payload_size, + bool occ); + /** Return the worst-case OpenVPN crypto overhead (in bytes) */ unsigned int crypto_max_overhead(void); diff --git a/src/openvpn/mtu.c b/src/openvpn/mtu.c index 0ab716d7..70ef9599 100644 --- a/src/openvpn/mtu.c +++ b/src/openvpn/mtu.c @@ -35,6 +35,7 @@ #include "integer.h" #include "mtu.h" #include "options.h" +#include "crypto.h" #include "memdbg.h" @@ -51,6 +52,92 @@ alloc_buf_sock_tun(struct buffer *buf, ASSERT(buf_safe(buf, 0)); } +size_t +frame_calculate_protocol_header_size(const struct key_type *kt, + const struct options *options, + unsigned int payload_size, + bool occ) +{ + /* Sum of all the overhead that reduces the usable packet size */ + size_t header_size = 0; + + bool tlsmode = options->tls_server || options->tls_client; + + /* A socks proxy adds 10 byte of extra header to each packet + * (we only support Socks with IPv4, this value is different for IPv6) */ + if (options->ce.socks_proxy_server && proto_is_udp(options->ce.proto)) + { + header_size += 10; + } + + /* TCP stream based packets have a 16 bit length field */ + if (proto_is_tcp(options->ce.proto)) + { + header_size += 2; + } + + /* Add the opcode and peerid */ + if (tlsmode) + { + header_size += options->use_peer_id ? 4 : 1; + } + + /* Add the crypto overhead */ + bool packet_id = options->replay; + bool packet_id_long_form = !tlsmode || cipher_kt_mode_ofb_cfb(kt->cipher); + + /* For figuring out the crypto overhead, we need to the size of the payload + * including all headers that also get encrypted as part of the payload */ + header_size += calculate_crypto_overhead(kt, packet_id, + packet_id_long_form, + payload_size, occ); + return header_size; +} + + +size_t +frame_calculate_payload_overhead(const struct frame *frame, + const struct options *options, + bool extra_tun) +{ + size_t overhead = 0; + + /* This is the overhead of tap device that is not included in the MTU itself + * i.e. Ethernet header that we still need to transmit as part of the + * payload*/ + if (extra_tun) + { + overhead += frame->extra_tun; + } + +#if defined(USE_COMP) + /* v1 Compression schemes add 1 byte header. V2 only adds a header when it + * does not increase the packet length. We ignore the unlikely escaping + * for tap here */ + if (options->comp.alg == COMP_ALG_LZ4 || options->comp.alg == COMP_ALG_STUB + || options->comp.alg == COMP_ALG_LZO) + { + overhead += 1; + } +#endif +#if defined(ENABLE_FRAGMENT) + /* Add the size of the fragment header (uint32_t) */ + if (options->ce.fragment) + { + overhead += 4; + } +#endif + return overhead; +} + +size_t +frame_calculate_payload_size(const struct frame *frame, const struct options *options) +{ + size_t payload_size = options->ce.tun_mtu; + payload_size += frame_calculate_payload_overhead(frame, options, true); + return payload_size; +} + void frame_finalize(struct frame *frame, bool link_mtu_defined, diff --git a/src/openvpn/mtu.h b/src/openvpn/mtu.h index c1148c31..5ad0931f 100644 --- a/src/openvpn/mtu.h +++ b/src/openvpn/mtu.h @@ -221,6 +221,60 @@ void set_mtu_discover_type(socket_descriptor_t sd, int mtu_type, sa_family_t pro int translate_mtu_discover_type_name(const char *name); +/** + * Calculates the size of the payload according to tun-mtu and tap overhead. + * This also includes compression and fragmentation overhead if they are + * enabled. + * + * * [IP][UDP][OPENVPN PROTOCOL HEADER][ **PAYLOAD incl compression header** ] + * @param frame + * @param options + * @return + */ +size_t +frame_calculate_payload_size(const struct frame *frame, + const struct options *options); + +/** + * Calculates the size of the payload overhead according to tun-mtu and + * tap overhead. This all the overhead that is considered part of the payload + * itself. The compression and fragmentation header and extra header from tap + * are considered part of this overhead that increases the payload larger than + * tun-mtu. + * + * * [IP][UDP][OPENVPN PROTOCOL HEADER][ **PAYLOAD incl compression header** ] + * @param frame + * @param options + * @param extra_tun + * @return + */ +size_t +frame_calculate_payload_overhead(const struct frame *frame, + const struct options *options, + bool extra_tun); + +/* forward declaration of key_type */ +struct key_type; + +/** + * Calculates the size of the OpenVPN protocol header. This includes + * the crypto IV/tag/HMAC but does not include the IP encapsulation + * + * + * [IP][UDP][ **OPENVPN PROTOCOL HEADER**][PAYLOAD incl compression header] + * + * @param kt the key_type to use to calculate the crypto overhead + * @param options the options struct to be used to calculate + * @param payload_size the payload size, ignored if occ is true + * @param occ if the calculation should be done for occ compatibility + * @return size of the overhead in bytes + */ +size_t +frame_calculate_protocol_header_size(const struct key_type *kt, + const struct options *options, + unsigned int payload_size, + bool occ); + /* * frame_set_mtu_dynamic and flags */