From patchwork Tue Dec 7 06:01:57 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arne Schwabe X-Patchwork-Id: 2136 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director10.mail.ord1d.rsapps.net ([172.31.255.6]) by backend41.mail.ord1d.rsapps.net with LMTP id CNhyDNOTr2FBUwAAqwncew (envelope-from ) for ; Tue, 07 Dec 2021 12:03:15 -0500 Received: from proxy18.mail.iad3b.rsapps.net ([172.31.255.6]) by director10.mail.ord1d.rsapps.net with LMTP id qDCeKdOTr2FVbAAApN4f7A (envelope-from ) for ; Tue, 07 Dec 2021 12:03:15 -0500 Received: from smtp29.gate.iad3b ([172.31.255.6]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy18.mail.iad3b.rsapps.net with LMTPS id wB9iItOTr2FwaQAA3NpJmQ (envelope-from ) for ; Tue, 07 Dec 2021 12:03:15 -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: smtp29.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: 90e4f8a4-577f-11ec-941d-525400534f55-1-1 Received: from [216.105.38.7] ([216.105.38.7:60516] helo=lists.sourceforge.net) by smtp29.gate.iad3b.rsapps.net (envelope-from ) (ecelerity 4.2.38.62370 r(:)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id 6B/ED-08843-3D39FA16; Tue, 07 Dec 2021 12:03:15 -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 1mudrI-0000wO-HE; Tue, 07 Dec 2021 17:02:28 +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 1mudrF-0000uk-9w for openvpn-devel@lists.sourceforge.net; Tue, 07 Dec 2021 17:02:25 +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=+VtInGkMlo1tN7GkcdRQjEDiZbtn5JXaqx56CenNXaw=; b=POdTNHrBYqHIRjK6LjDTJ2WT5E L2GkIME6sB1dwjpUOLt8Q1POzFhdA4AB6HYSWZSKuopZO/1fXpPsfIjltWuIMI02dF5PamPCt79Wg yui1KH24672AmLNAn0G2PWA5a0sGlf1EzRt0xGSa/lhttS/Il7tJaWOA7aC1yqFEs3eI=; 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=+VtInGkMlo1tN7GkcdRQjEDiZbtn5JXaqx56CenNXaw=; b=cGmWnxN4IjRClyjkLaSEnSMY/W A+24XgbpZ/8vB9DFKnLeLCzX0wVNpgtPAOBPZFP9RARudsVb/Yy4+Q0pbXmA3gEXIfc3hep5EwACh 7L+TGbLclElTR3DkPU+tywaFQHOf+/SSZQHCn+MjWe7tiY/JX5jlj83LuRGPt4LvE/Nk=; 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 1mudrD-0006Mq-H9 for openvpn-devel@lists.sourceforge.net; Tue, 07 Dec 2021 17:02:25 +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 1mudr1-000Idw-Qd for openvpn-devel@lists.sourceforge.net; Tue, 07 Dec 2021 18:02:11 +0100 Received: (nullmailer pid 3275906 invoked by uid 10006); Tue, 07 Dec 2021 17:02:12 -0000 From: Arne Schwabe To: openvpn-devel@lists.sourceforge.net Date: Tue, 7 Dec 2021 18:01:57 +0100 Message-Id: <20211207170211.3275837-8-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. Signed-off-by: Arne Schwabe --- src/openvpn/crypto.c | 55 ++++++++++++++++++++++++++++++ src/openvpn/crypto.h | 18 ++++++++++ src/openvpn/mtu.c | 80 ++++++++++++++++++++++++++++++++ [...] 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: 1mudrD-0006Mq-H9 Subject: [Openvpn-devel] [PATCH 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. Signed-off-by: Arne Schwabe --- src/openvpn/crypto.c | 55 ++++++++++++++++++++++++++++++ src/openvpn/crypto.h | 18 ++++++++++ src/openvpn/mtu.c | 80 ++++++++++++++++++++++++++++++++++++++++++++ src/openvpn/mtu.h | 54 ++++++++++++++++++++++++++++++ 4 files changed, 207 insertions(+) diff --git a/src/openvpn/crypto.c b/src/openvpn/crypto.c index cd791ab8a..249c4212d 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..25b943722 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,85 @@ 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; + + /* A socks proxy adds 10 byte of extra header to each packet */ + 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 */ + 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 */