From patchwork Tue Dec 14 04:09:03 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arne Schwabe X-Patchwork-Id: 2160 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director14.mail.ord1d.rsapps.net ([172.30.191.6]) by backend41.mail.ord1d.rsapps.net with LMTP id qMe4HdCzuGFZZQAAqwncew (envelope-from ) for ; Tue, 14 Dec 2021 10:10:08 -0500 Received: from proxy15.mail.ord1d.rsapps.net ([172.30.191.6]) by director14.mail.ord1d.rsapps.net with LMTP id iCGQNNCzuGHqegAAeJ7fFg (envelope-from ) for ; Tue, 14 Dec 2021 10:10:08 -0500 Received: from smtp1.gate.ord1d ([172.30.191.6]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy15.mail.ord1d.rsapps.net with LMTPS id 2PNPNNCzuGHQOQAAAY1PeQ (envelope-from ) for ; Tue, 14 Dec 2021 10:10:08 -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.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: ec287fd6-5cef-11ec-b483-5254002d775b-1-1 Received: from [216.105.38.7] ([216.105.38.7:53396] helo=lists.sourceforge.net) by smtp1.gate.ord1d.rsapps.net (envelope-from ) (ecelerity 4.2.38.62370 r(:)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id AE/3A-09579-FC3B8B16; Tue, 14 Dec 2021 10:10:07 -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.94.2) (envelope-from ) id 1mx9QY-0005pB-6H; Tue, 14 Dec 2021 15:09:14 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-4.v29.lw.sourceforge.com with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1mx9QW-0005p4-DS for openvpn-devel@lists.sourceforge.net; Tue, 14 Dec 2021 15:09:12 +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=/PACZO4AFzoqAcUTu+H00B42emyn9tSD4Lwk3zYAL04=; b=DKUuKgqPwmUOxgDxjk0AuXXt6K VhRa45DOPAf2Si/sAInoEd5lPClYuMwfIz9KW7ce47yW8ccVuXL9W6GV0DckjMZPeFOAxG2eFTxXy bzYqXtAnHQZSzp1y/ZzeuJDL2E6ruSKSihlYpS5j3VlXoGNdLz8cGM0p883+dLsRzwhQ=; 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=/PACZO4AFzoqAcUTu+H00B42emyn9tSD4Lwk3zYAL04=; b=BEmCWOW5YspY7yrv7W5LP40jPB NT4436THKBOf0+HP9SglpnR0W5s55/LsM+CXFmpiRW4plu9i0Fp/Nvzdlyrge0Hz8jV/Gdd+m5Y8j UGawIC1TC0mP0mmLBqgoiaV1iC6IqgSzNNVRLD4tthIELVYNTdQc/Lz8Zc9QfrtiC2V4=; 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 1mx9QU-00FEnk-VJ for openvpn-devel@lists.sourceforge.net; Tue, 14 Dec 2021 15:09:12 +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 1mx9QN-000ID5-O8 for openvpn-devel@lists.sourceforge.net; Tue, 14 Dec 2021 16:09:03 +0100 Received: (nullmailer pid 4119221 invoked by uid 10006); Tue, 14 Dec 2021 15:09:03 -0000 From: Arne Schwabe To: openvpn-devel@lists.sourceforge.net Date: Tue, 14 Dec 2021 16:09:03 +0100 Message-Id: <20211214150903.4119175-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 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: 1mx9QU-00FEnk-VJ 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 Signed-off-by: Arne Schwabe --- src/openvpn/crypto.c | 55 ++++++++++++++++++++++++++++ src/openvpn/crypto.h | 18 ++++++++++ src/openvpn/mtu.c | 86 ++++++++++++++++++++++++++++++++++++++++++++ src/openvpn/mtu.h | 54 ++++++++++++++++++++++++++++ 4 files changed, 213 insertions(+) diff --git a/src/openvpn/crypto.c b/src/openvpn/crypto.c index dc7ba5422..a58a48007 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; + + /* No encryption */ + 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 ad3543c1c..5a67b7ac1 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 0ab716d7a..0da1dadfa 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,91 @@ 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 use the real payload + * including all extra headers that also get encrypted */ + 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) + 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 c1148c317..5ad0931fd 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 */