From patchwork Wed Feb 14 13:27:19 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Frank Lichtenheld X-Patchwork-Id: 3615 Return-Path: Delivered-To: patchwork@openvpn.net Received: by 2002:a05:7000:59c4:b0:554:adf7:68e6 with SMTP id z4csp955265may; Wed, 14 Feb 2024 05:28:19 -0800 (PST) X-Forwarded-Encrypted: i=2; AJvYcCXuj2/p8G4CbpIaQIla1VsZqzybsFoxXZZUzu4KydYCUB/uwKG7yRZS6LPxN439aA/jg5uhJornzdTi+QHMIVjMvEgRifA= X-Google-Smtp-Source: AGHT+IFhp5aqqL+rl9jAtnB+lS0J1FdKAF2Xtpi+BjyNHZWwbHlYhNMxDbamRDdfwAZo+Zta6Z9t X-Received: by 2002:a05:6a20:8e0f:b0:19e:8293:f362 with SMTP id y15-20020a056a208e0f00b0019e8293f362mr2057392pzj.2.1707917298937; Wed, 14 Feb 2024 05:28:18 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1707917298; cv=none; d=google.com; s=arc-20160816; b=PEAdkU0Lpb7NrB98+nzM1CFhhgEOw2nmsrrLaL7wKXBspTTxFOg2BK0L34GVHX7Gms r0HOjLNfg/jNCk3aWZ5rIWRBrAL6vv4tA8qKNC+eP2yaeWV4GG8w+KASf1N1LU+c5QB8 oCg89lODvyXArHvBs9YR6gbZbz5j9DIyzfQdKLh3NQM98WYViXRzgPPAciTVvnktjhWR SSDO/MEWU3Y73LGcvtYDaDleYkl21dry2msVpeJrvLLmk826GuHHrovcyGFpOlrls74Q +1eO1OlPOYa2b/nXCNa9S7gFtoBYmTGy+BEK36KNslUVDJm/zQ34PQLBQBSuHzA40XTU pN1A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=errors-to:content-transfer-encoding:list-subscribe:list-help :list-post:list-archive:list-unsubscribe:list-id:precedence:subject :mime-version:references:in-reply-to:message-id:date:to:from :dkim-signature:dkim-signature:dkim-signature; bh=21Vck9tmtu/xLTRG/2TptArZIg4yT1GyIauznPb/bTY=; fh=04P6EbDqqozl3fTJgA49asgEwderk+os9x+mxP8ZkYE=; b=qwuD8lYQ37oCJQToBUsb4aRlqItg1yvzfkHDRvl4fwuPi6x72I0R/fizjEf2mxAU2A cyai9zjuKxF5nQMQdpTFaQdLSEw06SSQSepPyJr4S+epatw8WhrySV+oSkvpjLyZoWR3 ONEW97Ql3xQqr2c0zH4JgmgUKDs+4zQ1Qa3LJDhUoSFxG8uWgfGZLniviSbxrloFs+gY 2ydpFgLpWvmKZYIcNbQoUTQIDH/cM0QzkoE2H3AJjebWtHvP6hZlnP/2d29HgCfJRdC0 Cg/DMo5pxHcYpKnouu6Nia5AjEtNeoydsn6ClLFEvrPtElW+CbxTdXpgjlpJpoqqJ1zl +Slg==; darn=openvpn.net ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=Yhf7jfRN; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=jo7jhUev; dkim=neutral (body hash did not verify) header.i=@lichtenheld.com header.s=MBO0001 header.b=Z608oAGI; spf=pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) smtp.mailfrom=openvpn-devel-bounces@lists.sourceforge.net X-Forwarded-Encrypted: i=1; AJvYcCVmpPZcWdBu62ornDWLGC9nJ9+fQwokF+RQlICRW5SUEmld/RZxU0YdHM44lMMryiGue3aYIQj8JXFAx+e/UuGQ03uTFGcxpvx/FTReH2YO4ilckD7F8uiBW2pA3doT+DUrBBD6rG/i2+vyAxw1Clp3p1c06lU= Received: from lists.sourceforge.net (lists.sourceforge.net. [216.105.38.7]) by mx.google.com with ESMTPS id ma15-20020a170903094f00b001db5c9ec2ecsi186729plb.607.2024.02.14.05.28.18 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Wed, 14 Feb 2024 05:28:18 -0800 (PST) Received-SPF: pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) client-ip=216.105.38.7; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=Yhf7jfRN; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=jo7jhUev; dkim=neutral (body hash did not verify) header.i=@lichtenheld.com header.s=MBO0001 header.b=Z608oAGI; spf=pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) smtp.mailfrom=openvpn-devel-bounces@lists.sourceforge.net 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.95) (envelope-from ) id 1raFIZ-0005up-In; Wed, 14 Feb 2024 13:27:40 +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.95) (envelope-from ) id 1raFIY-0005ue-SZ for openvpn-devel@lists.sourceforge.net; Wed, 14 Feb 2024 13:27:39 +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:Cc:To:From:Sender:Reply-To: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=Zfdax/CwLD9EyE2mMkjhN8ELK7MvfI6sq3il7gvplLI=; b=Yhf7jfRNdNE8n/i1C++oFZwpIj LH/d8BZnZ2XUEwsYAkQEUy5P2zOv3alJ/djAs6/wbb2MOiCRFemEMw3crm/MQvJKyejA+vsUiueSR iOWAIBxRz2DnS/5ErV+ffKj3C8pfLoKjfgbkXEFc5gJbNzi3uZc7qN4q1hsol0MZ4ZI8=; 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:Cc:To:From:Sender:Reply-To: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=Zfdax/CwLD9EyE2mMkjhN8ELK7MvfI6sq3il7gvplLI=; b=jo7jhUev18jsvIoNAO8sRnInIV uPwm5bc7ET1+yTUhbMTnWcCtbLJv2t7aKO3OCjo0o5tZL17HMWD8HzCLsVkgWQuc+RBvlQJl1rXGb 0iDvHvEDlMACCrlo3BLhtOtH65H1Rexu4ICwiWnJV/f+TYEGyL4xPOPlB2Lj7BPwcc2w=; Received: from mout-p-102.mailbox.org ([80.241.56.152]) by sfi-mx-2.v28.lw.sourceforge.com with esmtps (TLS1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.95) id 1raFIU-0002wr-L2 for openvpn-devel@lists.sourceforge.net; Wed, 14 Feb 2024 13:27:39 +0000 Received: from smtp102.mailbox.org (smtp102.mailbox.org [IPv6:2001:67c:2050:b231:465::102]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mout-p-102.mailbox.org (Postfix) with ESMTPS id 4TZfBK3MZvz9sqx; Wed, 14 Feb 2024 14:27:21 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=lichtenheld.com; s=MBO0001; t=1707917241; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Zfdax/CwLD9EyE2mMkjhN8ELK7MvfI6sq3il7gvplLI=; b=Z608oAGIHH/bfRes8kwuKEIp8t1gO7B1nK8KVHCmwooJKIgl/3MWYtNYKYuB2FotGiY7+3 pqXN5vmHV11Fnx20xNvumtAoAroL94n4OQYkMgXbEXQkLLN62lymUk/b2mhvsneW0OeX+6 GY6xLCSFRgFxShbq0veqiWfLUNbdnpodH++yoACCEYSCwcua0wWh8NWDOYxcPt4CT1VvT4 oKkU+A/zc64CDF0/GrmMx9HcLqx+3w0WMgy975WgyvC4QIZVeDexHK2YEFltbJm0vr26Vj oJdCnxaGLknQ4wzsAMRKLaXth0j6Qhi8evoVDdBOJDmo75gGAxQh/OIb4eBz7Q== From: Frank Lichtenheld To: openvpn-devel@lists.sourceforge.net Date: Wed, 14 Feb 2024 14:27:19 +0100 Message-Id: <20240214132719.3031492-1-frank@lichtenheld.com> In-Reply-To: References: MIME-Version: 1.0 X-Rspamd-Queue-Id: 4TZfBK3MZvz9sqx X-Spam-Score: -0.9 (/) X-Spam-Report: Spam detection software, running on the system "util-spamd-2.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: From: Arne Schwabe Using the AEAD tag at the end is the standard way of doing AEAD. Several APIs even only support the tag at the end (e.g. mbed TLS). Having the tag at the front or end makes no difference for security [...] Content analysis details: (-0.9 points, 6.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at https://www.dnswl.org/, low trust [80.241.56.152 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.0 T_SCC_BODY_TEXT_LINE No description available. X-Headers-End: 1raFIU-0002wr-L2 Subject: [Openvpn-devel] [PATCH v3] Implement support for AEAD tag at the end 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 X-GMAIL-THRID: =?utf-8?q?1790881089768269526?= X-GMAIL-MSGID: =?utf-8?q?1790881089768269526?= From: Arne Schwabe Using the AEAD tag at the end is the standard way of doing AEAD. Several APIs even only support the tag at the end (e.g. mbed TLS). Having the tag at the front or end makes no difference for security but allows streaming HW implementations like NICs to be much more efficient as they do not need to buffer a whole packet content and encrypt it to finally write the tag but instead just add the calculated tag at the end of processing. Change-Id: I00821d75342daf3f813b829812d648fe298bea81 Signed-off-by: Arne Schwabe Acked-by: Frank Lichtenheld --- This change was reviewed on Gerrit and approved by at least one developer. I request to merge it to master. Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/506 This mail reflects revision 3 of this Change. Acked-by according to Gerrit (reflected above): Frank Lichtenheld diff --git a/src/openvpn/crypto.c b/src/openvpn/crypto.c index 2fca131..9988ebe 100644 --- a/src/openvpn/crypto.c +++ b/src/openvpn/crypto.c @@ -104,14 +104,10 @@ ASSERT(cipher_ctx_reset(ctx->cipher, iv)); } - /* Reserve space for authentication tag */ - mac_out = buf_write_alloc(&work, mac_len); - ASSERT(mac_out); - dmsg(D_PACKET_CONTENT, "ENCRYPT FROM: %s", format_hex(BPTR(buf), BLEN(buf), 80, &gc)); /* Buffer overflow check */ - if (!buf_safe(&work, buf->len + cipher_ctx_block_size(ctx->cipher))) + if (!buf_safe(&work, buf->len + mac_len + cipher_ctx_block_size(ctx->cipher))) { msg(D_CRYPT_ERRORS, "ENCRYPT: buffer size error, bc=%d bo=%d bl=%d wc=%d wo=%d wl=%d", @@ -121,9 +117,16 @@ } /* For AEAD ciphers, authenticate Additional Data, including opcode */ - ASSERT(cipher_ctx_update_ad(ctx->cipher, BPTR(&work), BLEN(&work) - mac_len)); + ASSERT(cipher_ctx_update_ad(ctx->cipher, BPTR(&work), BLEN(&work))); dmsg(D_PACKET_CONTENT, "ENCRYPT AD: %s", - format_hex(BPTR(&work), BLEN(&work) - mac_len, 0, &gc)); + format_hex(BPTR(&work), BLEN(&work), 0, &gc)); + + if (!(opt->flags & CO_AEAD_TAG_AT_THE_END)) + { + /* Reserve space for authentication tag */ + mac_out = buf_write_alloc(&work, mac_len); + ASSERT(mac_out); + } /* Encrypt packet ID, payload */ ASSERT(cipher_ctx_update(ctx->cipher, BEND(&work), &outlen, BPTR(buf), BLEN(buf))); @@ -133,6 +136,14 @@ ASSERT(cipher_ctx_final(ctx->cipher, BEND(&work), &outlen)); ASSERT(buf_inc_len(&work, outlen)); + /* if the tag is at end the end, allocate it now */ + if (opt->flags & CO_AEAD_TAG_AT_THE_END) + { + /* Reserve space for authentication tag */ + mac_out = buf_write_alloc(&work, mac_len); + ASSERT(mac_out); + } + /* Write authentication tag */ ASSERT(cipher_ctx_get_tag(ctx->cipher, mac_out, mac_len)); @@ -353,7 +364,6 @@ static const char error_prefix[] = "AEAD Decrypt error"; struct packet_id_net pin = { 0 }; const struct key_ctx *ctx = &opt->key_ctx_bi.decrypt; - uint8_t *tag_ptr = NULL; int outlen; struct gc_arena gc; @@ -406,19 +416,29 @@ /* keep the tag value to feed in later */ const int tag_size = OPENVPN_AEAD_TAG_LENGTH; - if (buf->len < tag_size) + if (buf->len < tag_size + 1) { - CRYPT_ERROR("missing tag"); + CRYPT_ERROR("missing tag or no payload"); } - tag_ptr = BPTR(buf); - ASSERT(buf_advance(buf, tag_size)); + + const int ad_size = BPTR(buf) - ad_start; + + uint8_t *tag_ptr = NULL; + int data_len = 0; + + if (opt->flags & CO_AEAD_TAG_AT_THE_END) + { + data_len = BLEN(buf) - tag_size; + tag_ptr = BPTR(buf) + data_len; + } + else + { + tag_ptr = BPTR(buf); + ASSERT(buf_advance(buf, tag_size)); + data_len = BLEN(buf); + } + dmsg(D_PACKET_CONTENT, "DECRYPT MAC: %s", format_hex(tag_ptr, tag_size, 0, &gc)); - - if (buf->len < 1) - { - CRYPT_ERROR("missing payload"); - } - dmsg(D_PACKET_CONTENT, "DECRYPT FROM: %s", format_hex(BPTR(buf), BLEN(buf), 0, &gc)); /* Buffer overflow check (should never fail) */ @@ -427,20 +447,19 @@ CRYPT_ERROR("potential buffer overflow"); } - { - /* feed in tag and the authenticated data */ - const int ad_size = BPTR(buf) - ad_start - tag_size; - ASSERT(cipher_ctx_update_ad(ctx->cipher, ad_start, ad_size)); - dmsg(D_PACKET_CONTENT, "DECRYPT AD: %s", - format_hex(BPTR(buf) - ad_size - tag_size, ad_size, 0, &gc)); - } + + /* feed in tag and the authenticated data */ + ASSERT(cipher_ctx_update_ad(ctx->cipher, ad_start, ad_size)); + dmsg(D_PACKET_CONTENT, "DECRYPT AD: %s", + format_hex(ad_start, ad_size, 0, &gc)); /* Decrypt and authenticate packet */ if (!cipher_ctx_update(ctx->cipher, BPTR(&work), &outlen, BPTR(buf), - BLEN(buf))) + data_len)) { CRYPT_ERROR("cipher update failed"); } + ASSERT(buf_inc_len(&work, outlen)); if (!cipher_ctx_final_check_tag(ctx->cipher, BPTR(&work) + outlen, &outlen, tag_ptr, tag_size)) diff --git a/src/openvpn/crypto.h b/src/openvpn/crypto.h index 4201524..95a5b31 100644 --- a/src/openvpn/crypto.h +++ b/src/openvpn/crypto.h @@ -279,6 +279,10 @@ /**< Bit-flag indicating that renegotiations are using tls-crypt * with a TLS-EKM derived key. */ +#define CO_AEAD_TAG_AT_THE_END (1<<8) + /**< Bit-flag indicating that the AEAD tag is at the end of the + * packet. + */ unsigned int flags; /**< Bit-flags determining behavior of * security operation functions. */ diff --git a/src/openvpn/init.c b/src/openvpn/init.c index c5cc154..cd37b36 100644 --- a/src/openvpn/init.c +++ b/src/openvpn/init.c @@ -2323,6 +2323,10 @@ { buf_printf(&out, " dyn-tls-crypt"); } + if (o->imported_protocol_flags & CO_AEAD_TAG_AT_THE_END) + { + buf_printf(&out, " aead-tag-end"); + } } if (buf_len(&out) > strlen(header)) diff --git a/src/openvpn/options.c b/src/openvpn/options.c index 2c79a1e..39f00c0 100644 --- a/src/openvpn/options.c +++ b/src/openvpn/options.c @@ -8686,6 +8686,10 @@ options->imported_protocol_flags |= CO_USE_DYNAMIC_TLS_CRYPT; } #endif + else if (streq(p[j], "aead-tag-end")) + { + options->imported_protocol_flags |= CO_AEAD_TAG_AT_THE_END; + } else { msg(msglevel, "Unknown protocol-flags flag: %s", p[j]); diff --git a/src/openvpn/push.c b/src/openvpn/push.c index 2249434..e4c122c 100644 --- a/src/openvpn/push.c +++ b/src/openvpn/push.c @@ -29,6 +29,7 @@ #include "push.h" #include "options.h" +#include "crypto.h" #include "ssl.h" #include "ssl_verify.h" #include "ssl_ncp.h" @@ -686,6 +687,11 @@ buf_printf(&proto_flags, " dyn-tls-crypt"); } + if (o->imported_protocol_flags & CO_AEAD_TAG_AT_THE_END) + { + buf_printf(&proto_flags, " aead-tag-end"); + } + if (buf_len(&proto_flags) > 0) { push_option_fmt(gc, push_list, M_USAGE, "protocol-flags%s", buf_str(&proto_flags)); diff --git a/tests/unit_tests/openvpn/test_ssl.c b/tests/unit_tests/openvpn/test_ssl.c index 8c1fb5b..2ccfa45 100644 --- a/tests/unit_tests/openvpn/test_ssl.c +++ b/tests/unit_tests/openvpn/test_ssl.c @@ -265,6 +265,17 @@ } +/* This adds a few more methods than strictly necessary but this allows + * us to see which exact test was run from the backtrace of the test + * when it fails */ +static void +run_data_channel_with_cipher_end(const char *cipher) +{ + struct crypto_options co = init_crypto_options(cipher, "none"); + co.flags |= CO_AEAD_TAG_AT_THE_END; + do_data_channel_round_trip(&co); + uninit_crypto_options(&co); +} static void run_data_channel_with_cipher(const char *cipher, const char *auth) @@ -274,21 +285,25 @@ uninit_crypto_options(&co); } + static void test_data_channel_roundtrip_aes_128_gcm(void **state) { + run_data_channel_with_cipher_end("AES-128-GCM"); run_data_channel_with_cipher("AES-128-GCM", "none"); } static void test_data_channel_roundtrip_aes_192_gcm(void **state) { + run_data_channel_with_cipher_end("AES-192-GCM"); run_data_channel_with_cipher("AES-192-GCM", "none"); } static void test_data_channel_roundtrip_aes_256_gcm(void **state) { + run_data_channel_with_cipher_end("AES-256-GCM"); run_data_channel_with_cipher("AES-256-GCM", "none"); } @@ -318,6 +333,8 @@ skip(); return; } + + run_data_channel_with_cipher_end("ChaCha20-Poly1305"); run_data_channel_with_cipher("ChaCha20-Poly1305", "none"); }