From patchwork Mon Sep 9 14:23:30 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gert Doering X-Patchwork-Id: 3813 Return-Path: Delivered-To: patchwork@openvpn.net Received: by 2002:a05:7000:6bd4:b0:5b9:581e:f939 with SMTP id c20csp1550860max; Mon, 9 Sep 2024 07:23:46 -0700 (PDT) X-Forwarded-Encrypted: i=2; AJvYcCX+yL/vD9s5hmiL90KAMaCm5fJ8wagU/0VQZKLbfWJMdY/0ca+5Be95K+T+kOkwbwvjVFvcr/rCjK8=@openvpn.net X-Google-Smtp-Source: AGHT+IHzRVlRT5YHPQve1s8sUz2rlenHASUTJaNHBmJMZBXvlhbPsBNaS8Ht5NXmg6PcGKC+dIlk X-Received: by 2002:a05:6830:3148:b0:703:783a:dad5 with SMTP id 46e09a7af769-710cc26e969mr9800801a34.27.1725891826291; Mon, 09 Sep 2024 07:23:46 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1725891826; cv=none; d=google.com; s=arc-20240605; b=S79z+I+KHJDuCAPgquX9KEI8BWOAYHbiB8mTMp/Saxr8acKcgDV/5cliNixVa0zBsp B7kGqobZSd4775qqJ/aO0U6SBB2jucwlFCLH4n+As3zoxRDPs8pjn3A4wmsPfN8GOV1d vgMmTO0EiN59RX0sYtvrAfAPA8kNXXEerPsXkOBYHV3vkMq6OBi3bhf1vbKbRCoj0hB5 3QRdhBNL8+0z6cP7Z4RaFthabxEC9C2g1mM+XkQoEork8IM9htneA5rUVFmVEFeaT8cN n1yTRQo4MQqN0qgB+OvXt7MACM47xt7wmkEHZieIiHejD2+oB5BxT3s+VEuwBl0p2T9r XUaA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; 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; bh=qiU6ohgegBPU1fNty0ya9rUH4O/shOUnVJGVJjkd394=; fh=4NbAC/LsuMLI0S0hprUlLSLCiHwg6SCAifhH718Jh0Q=; b=jDpiDIanfWQi8b6sVZUSBdsalBhR2/ABSoy/hDNbv9EdtrCI/6cCjjbCXx/HxciAqd A0CoFdX1e7NWDKajCCnK73gO5f393jbLaYXMO4IR8Kp+AI8j8LT+zxtZo+7VB/K+424E HqmUw1x39Sy1k4Xf3GsqK0bKd9gWsKJZYX1wqsKRk4F/vK50EzRum6guQ6XftaaavZqV /HUkKINuspGWITkX5vdbfzUqi5BP8qz42gK0llneP+ARHhsaVA/hA+v5yw/boZG2mcX4 Zu3V75cYl4J4NqYVpZ1Zhs6PbLxlTw4BgBb4bHI1yCg41IkFSTWW/+LXPhTWh5t4eg4Q PyRQ==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b="e/X8/NLu"; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=YvX26vH5; 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; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=muc.de Received: from lists.sourceforge.net (lists.sourceforge.net. [216.105.38.7]) by mx.google.com with ESMTPS id 46e09a7af769-710d9df8260si2312550a34.346.2024.09.09.07.23.45 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Mon, 09 Sep 2024 07:23:45 -0700 (PDT) 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="e/X8/NLu"; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=YvX26vH5; 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; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=muc.de 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.95) (envelope-from ) id 1snfIq-0005qm-Nz; Mon, 09 Sep 2024 14:23:41 +0000 Received: from [172.30.29.66] (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.95) (envelope-from ) id 1snfIo-0005qf-J6 for openvpn-devel@lists.sourceforge.net; Mon, 09 Sep 2024 14:23: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: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=vfvLghcSQvpYqrvxtoCbFXLjUTkAdaxS20pSF54Te18=; b=e/X8/NLuSXO7pGXsGEbTeYnIO1 J28G8anxVVRyWUPIOh2LRyU/97MHDgnjIhB57ACUYzt1M4mVLJLfRZaCpzc+GePXj/TbyBktpp4MH befI72lEPtIpQ335Gi49Nk7ZhMNsPCklUcRIRd/RLlv35VX2ZpsGxP+oammRUyQoFZgY=; 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=vfvLghcSQvpYqrvxtoCbFXLjUTkAdaxS20pSF54Te18=; b=YvX26vH5op8py88ZwLfCxC3VY0 8cVmMw2HKzH9uKs9rP180s6IMgn66GJLJM74uPpSfgw3Aoxv7rcdPK4AqpZt1GE0AbfGK4DEEOiZx CXP3rHxO03HO1FvTYfBWI7peLhwjz2A5xLrTNJHyKui8Oa3tunVR1r7DxDkPktZvNt/g=; Received: from dhcp-174.greenie.muc.de ([193.149.48.174] helo=blue.greenie.muc.de) by sfi-mx-2.v28.lw.sourceforge.com with esmtps (TLS1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.95) id 1snfIn-0003Yd-Iq for openvpn-devel@lists.sourceforge.net; Mon, 09 Sep 2024 14:23:39 +0000 Received: from blue.greenie.muc.de (localhost [127.0.0.1]) by blue.greenie.muc.de (8.17.1.9/8.17.1.9) with ESMTP id 489ENVDn020446 for ; Mon, 9 Sep 2024 16:23:31 +0200 Received: (from gert@localhost) by blue.greenie.muc.de (8.17.1.9/8.17.1.9/Submit) id 489ENUhg020445 for openvpn-devel@lists.sourceforge.net; Mon, 9 Sep 2024 16:23:30 +0200 From: Gert Doering To: openvpn-devel@lists.sourceforge.net Date: Mon, 9 Sep 2024 16:23:30 +0200 Message-ID: <20240909142330.20424-1-gert@greenie.muc.de> X-Mailer: git-send-email 2.44.2 In-Reply-To: References: MIME-Version: 1.0 X-Spam-Score: -0.0 (/) 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: Lev Stipakov Since version 1.4, dco-win drivere supports data_v3 features such as: - AEAD tag at the end - 64bit pktid Content analysis details: (-0.0 points, 6.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_HELO_PASS SPF: HELO matches SPF record -0.0 SPF_PASS SPF: sender matches SPF record X-Headers-End: 1snfIn-0003Yd-Iq Subject: [Openvpn-devel] [PATCH v3] dco-win: support for data_v3 features 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?1809728747584124175?= X-GMAIL-MSGID: =?utf-8?q?1809728747584124175?= From: Lev Stipakov Since version 1.4, dco-win drivere supports data_v3 features such as: - AEAD tag at the end - 64bit pktid We have to: - check in runtime if driver supports data_v3 features (we might be running with the older driver) - if those features are negotiated, we pass them to the driver as bit flags via the (newly added) NEW_KEY_V2 ioctl Introduce NEW_KEY_V2 ioctl, which accepts a new OVPN_CRYPTO_DATA_V2 structure, which includes a field for bit flags for the new crypto options. Make dco_supports_data_v3() implementation platform-dependend (as it should be) and indicate data_v3 support by dco-win if the driver version is at least 1.4. Extend the Windows-specific struct dco_context and store data_v3 support there so that when dco_new_key() is called, we know which API to use. Change the dco internal API and pass crypto options flags to dco_new_key(). Change-Id: I2e0c50d33f8a57c023120cf348f95d34acbfcde5 Signed-off-by: Lev Stipakov 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/+/725 This mail reflects revision 3 of this Change. Acked-by according to Gerrit (reflected above): Frank Lichtenheld diff --git a/src/openvpn/dco.c b/src/openvpn/dco.c index 7f0d53d..baaeb95 100644 --- a/src/openvpn/dco.c +++ b/src/openvpn/dco.c @@ -70,7 +70,7 @@ int ret = dco_new_key(multi->dco, multi->dco_peer_id, ks->key_id, slot, encrypt_key, encrypt_iv, decrypt_key, decrypt_iv, - ciphername); + ciphername, ks->crypto_options.flags); if ((ret == 0) && (multi->dco_keys_installed < 2)) { multi->dco_keys_installed++; diff --git a/src/openvpn/dco.h b/src/openvpn/dco.h index 3ce2c31..ec4ec42 100644 --- a/src/openvpn/dco.h +++ b/src/openvpn/dco.h @@ -253,11 +253,7 @@ * Return whether the dco implementation supports the new protocol features of * a 64 bit packet counter and AEAD tag at the end. */ -static inline bool -dco_supports_data_v3(struct context *c) -{ - return false; -} +bool dco_supports_data_v3(struct context *c); #else /* if defined(ENABLE_DCO) */ diff --git a/src/openvpn/dco_freebsd.c b/src/openvpn/dco_freebsd.c index 9a90f5c..4516cd5 100644 --- a/src/openvpn/dco_freebsd.c +++ b/src/openvpn/dco_freebsd.c @@ -415,14 +415,14 @@ dco_key_slot_t slot, const uint8_t *encrypt_key, const uint8_t *encrypt_iv, const uint8_t *decrypt_key, const uint8_t *decrypt_iv, - const char *ciphername) + const char *ciphername, unsigned int co_flags) { struct ifdrv drv; nvlist_t *nvl; int ret; - msg(D_DCO_DEBUG, "%s: slot %d, key-id %d, peer-id %d, cipher %s", - __func__, slot, keyid, peerid, ciphername); + msg(D_DCO_DEBUG, "%s: slot %d, key-id %d, peer-id %d, cipher %s, co_flags %u", + __func__, slot, keyid, peerid, ciphername, co_flags); nvl = nvlist_create(0); @@ -778,4 +778,11 @@ return "none:AES-256-GCM:AES-192-GCM:AES-128-GCM:CHACHA20-POLY1305"; } +bool +dco_supports_data_v3(struct context *c) +{ + /* not implemented */ + return false; +} + #endif /* defined(ENABLE_DCO) && defined(TARGET_FREEBSD) */ diff --git a/src/openvpn/dco_internal.h b/src/openvpn/dco_internal.h index 624c110..35500a4 100644 --- a/src/openvpn/dco_internal.h +++ b/src/openvpn/dco_internal.h @@ -70,7 +70,7 @@ dco_key_slot_t slot, const uint8_t *encrypt_key, const uint8_t *encrypt_iv, const uint8_t *decrypt_key, const uint8_t *decrypt_iv, - const char *ciphername); + const char *ciphername, unsigned int co_flags); int dco_del_key(dco_context_t *dco, unsigned int peerid, dco_key_slot_t slot); diff --git a/src/openvpn/dco_linux.c b/src/openvpn/dco_linux.c index 277cd64..4197d30 100644 --- a/src/openvpn/dco_linux.c +++ b/src/openvpn/dco_linux.c @@ -557,10 +557,10 @@ dco_key_slot_t slot, const uint8_t *encrypt_key, const uint8_t *encrypt_iv, const uint8_t *decrypt_key, const uint8_t *decrypt_iv, - const char *ciphername) + const char *ciphername, unsigned int co_flags) { - msg(D_DCO_DEBUG, "%s: slot %d, key-id %d, peer-id %d, cipher %s", - __func__, slot, keyid, peerid, ciphername); + msg(D_DCO_DEBUG, "%s: slot %d, key-id %d, peer-id %d, cipher %s, co_flags %u", + __func__, slot, keyid, peerid, ciphername, co_flags); const size_t key_len = cipher_kt_key_size(ciphername); const int nonce_tail_len = 8; @@ -1058,4 +1058,11 @@ return "AES-128-GCM:AES-256-GCM:AES-192-GCM:CHACHA20-POLY1305"; } +bool +dco_supports_data_v3(struct context *c) +{ + /* not implemented */ + return false; +} + #endif /* defined(ENABLE_DCO) && defined(TARGET_LINUX) */ diff --git a/src/openvpn/dco_win.c b/src/openvpn/dco_win.c index 3ec946f..189864b 100644 --- a/src/openvpn/dco_win.c +++ b/src/openvpn/dco_win.c @@ -55,6 +55,9 @@ bool ovpn_dco_init(int mode, dco_context_t *dco) { + dco->supports_data_v3 = dco_supports_data_v3(NULL); + msg(D_DCO_DEBUG, "dco supports data_v3: %d", dco->supports_data_v3); + return true; } @@ -291,47 +294,85 @@ return 0; } -int -dco_new_key(dco_context_t *dco, unsigned int peerid, int keyid, - dco_key_slot_t slot, - const uint8_t *encrypt_key, const uint8_t *encrypt_iv, - const uint8_t *decrypt_key, const uint8_t *decrypt_iv, - const char *ciphername) +static int +dco_new_key_v1(HANDLE handle, OVPN_CRYPTO_DATA *crypto_data) { - msg(D_DCO_DEBUG, "%s: slot %d, key-id %d, peer-id %d, cipher %s", - __func__, slot, keyid, peerid, ciphername); - - const int nonce_len = 8; - size_t key_len = cipher_kt_key_size(ciphername); - - OVPN_CRYPTO_DATA crypto_data; - ZeroMemory(&crypto_data, sizeof(crypto_data)); - - crypto_data.CipherAlg = dco_get_cipher(ciphername); - crypto_data.KeyId = keyid; - crypto_data.PeerId = peerid; - crypto_data.KeySlot = slot; - - CopyMemory(crypto_data.Encrypt.Key, encrypt_key, key_len); - crypto_data.Encrypt.KeyLen = (char)key_len; - CopyMemory(crypto_data.Encrypt.NonceTail, encrypt_iv, nonce_len); - - CopyMemory(crypto_data.Decrypt.Key, decrypt_key, key_len); - crypto_data.Decrypt.KeyLen = (char)key_len; - CopyMemory(crypto_data.Decrypt.NonceTail, decrypt_iv, nonce_len); - - ASSERT(crypto_data.CipherAlg > 0); - DWORD bytes_returned = 0; - if (!DeviceIoControl(dco->tt->hand, OVPN_IOCTL_NEW_KEY, &crypto_data, - sizeof(crypto_data), NULL, 0, &bytes_returned, NULL)) + if (!DeviceIoControl(handle, OVPN_IOCTL_NEW_KEY, crypto_data, sizeof(*crypto_data), NULL, 0, &bytes_returned, NULL)) { msg(M_ERR, "DeviceIoControl(OVPN_IOCTL_NEW_KEY) failed"); return -1; } return 0; } + +static int +dco_new_key_v2(HANDLE handle, OVPN_CRYPTO_DATA_V2 *crypto_data, unsigned int co_flags) +{ + if (co_flags & CO_AEAD_TAG_AT_THE_END) + { + crypto_data->CryptoOptions |= CRYPTO_OPTIONS_AEAD_TAG_END; + } + + if (co_flags & CO_64_BIT_PKT_ID) + { + crypto_data->CryptoOptions |= CRYPTO_OPTIONS_64BIT_PKTID; + } + + DWORD bytes_returned = 0; + if (!DeviceIoControl(handle, OVPN_IOCTL_NEW_KEY_V2, crypto_data, sizeof(*crypto_data), NULL, 0, &bytes_returned, NULL)) + { + msg(M_ERR, "DeviceIoControl(OVPN_IOCTL_NEW_KEY_V2) failed"); + return -1; + } + + return 0; +} + +int +dco_new_key(dco_context_t *dco, unsigned int peerid, int keyid, + dco_key_slot_t slot, + const uint8_t *encrypt_key, const uint8_t *encrypt_iv, + const uint8_t *decrypt_key, const uint8_t *decrypt_iv, + const char *ciphername, unsigned int co_flags) +{ + msg(D_DCO_DEBUG, "%s: slot %d, key-id %d, peer-id %d, cipher %s, co_flags %u", + __func__, slot, keyid, peerid, ciphername, co_flags); + + const int nonce_len = 8; + size_t key_len = cipher_kt_key_size(ciphername); + + OVPN_CRYPTO_DATA_V2 crypto_data_v2; + ZeroMemory(&crypto_data_v2, sizeof(crypto_data_v2)); + + OVPN_CRYPTO_DATA *crypto_data = &crypto_data_v2.V1; + + crypto_data->CipherAlg = dco_get_cipher(ciphername); + crypto_data->KeyId = keyid; + crypto_data->PeerId = peerid; + crypto_data->KeySlot = slot; + + CopyMemory(crypto_data->Encrypt.Key, encrypt_key, key_len); + crypto_data->Encrypt.KeyLen = (char)key_len; + CopyMemory(crypto_data->Encrypt.NonceTail, encrypt_iv, nonce_len); + + CopyMemory(crypto_data->Decrypt.Key, decrypt_key, key_len); + crypto_data->Decrypt.KeyLen = (char)key_len; + CopyMemory(crypto_data->Decrypt.NonceTail, decrypt_iv, nonce_len); + + ASSERT(crypto_data->CipherAlg > 0); + + if (dco->supports_data_v3) + { + return dco_new_key_v2(dco->tt->hand, &crypto_data_v2, co_flags); + } + else + { + return dco_new_key_v1(dco->tt->hand, crypto_data); + } +} + int dco_del_key(dco_context_t *dco, unsigned int peerid, dco_key_slot_t slot) { @@ -494,4 +535,39 @@ } } +bool +dco_supports_data_v3(struct context *c) +{ + bool res = false; + + HANDLE h = CreateFile("\\\\.\\ovpn-dco-ver", GENERIC_READ, + 0, NULL, OPEN_EXISTING, 0, NULL); + + if (h == INVALID_HANDLE_VALUE) + { + goto done; + } + + OVPN_VERSION version; + ZeroMemory(&version, sizeof(OVPN_VERSION)); + + DWORD bytes_returned = 0; + if (!DeviceIoControl(h, OVPN_IOCTL_GET_VERSION, NULL, 0, + &version, sizeof(version), &bytes_returned, NULL)) + { + goto done; + } + + /* data_v3 is supported starting from 1.4 */ + res = (version.Major > 1) || (version.Minor >= 4); + +done: + if (h != INVALID_HANDLE_VALUE) + { + CloseHandle(h); + } + + return res; +} + #endif /* defined(_WIN32) */ diff --git a/src/openvpn/dco_win.h b/src/openvpn/dco_win.h index 4883629..f58488f 100644 --- a/src/openvpn/dco_win.h +++ b/src/openvpn/dco_win.h @@ -33,6 +33,7 @@ struct dco_context { struct tuntap *tt; + bool supports_data_v3; }; typedef struct dco_context dco_context_t; diff --git a/src/openvpn/ovpn_dco_win.h b/src/openvpn/ovpn_dco_win.h index ea2a733..9e437f0 100644 --- a/src/openvpn/ovpn_dco_win.h +++ b/src/openvpn/ovpn_dco_win.h @@ -94,6 +94,14 @@ int PeerId; } OVPN_CRYPTO_DATA, * POVPN_CRYPTO_DATA; +#define CRYPTO_OPTIONS_AEAD_TAG_END (1<<1) +#define CRYPTO_OPTIONS_64BIT_PKTID (1<<2) + +typedef struct _OVPN_CRYPTO_DATA_V2 { + OVPN_CRYPTO_DATA V1; + UINT32 CryptoOptions; +} OVPN_CRYPTO_DATA_V2, * POVPN_CRYPTO_DATA_V2; + typedef struct _OVPN_SET_PEER { LONG KeepaliveInterval; LONG KeepaliveTimeout; @@ -114,3 +122,4 @@ #define OVPN_IOCTL_START_VPN CTL_CODE(FILE_DEVICE_UNKNOWN, 6, METHOD_BUFFERED, FILE_ANY_ACCESS) #define OVPN_IOCTL_DEL_PEER CTL_CODE(FILE_DEVICE_UNKNOWN, 7, METHOD_BUFFERED, FILE_ANY_ACCESS) #define OVPN_IOCTL_GET_VERSION CTL_CODE(FILE_DEVICE_UNKNOWN, 8, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define OVPN_IOCTL_NEW_KEY_V2 CTL_CODE(FILE_DEVICE_UNKNOWN, 9, METHOD_BUFFERED, FILE_ANY_ACCESS)