From patchwork Fri Dec 27 12:46:32 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Frank Lichtenheld X-Patchwork-Id: 4024 Return-Path: Delivered-To: patchwork@openvpn.net Received: by 2002:a05:7000:998b:b0:5e7:b9eb:58e8 with SMTP id d11csp6189181mav; Fri, 27 Dec 2024 04:46:57 -0800 (PST) X-Forwarded-Encrypted: i=2; AJvYcCVsfByK37VSkDT/YrKm6pafWnBKaENYazEZpMafaH9+7BmLzTtbATpUo68hQDHZSx4aGqWHj2N2qYY=@openvpn.net X-Google-Smtp-Source: AGHT+IGnxrvnRVeB6/Qflgr7xFoOsWIYhi1XjUgorufYGpzUdmHbmmNqX3+NhCotj/EnNvwlkXGj X-Received: by 2002:a05:6830:441e:b0:71e:4fc:6ed6 with SMTP id 46e09a7af769-720ff841454mr17999213a34.10.1735303616853; Fri, 27 Dec 2024 04:46:56 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1735303616; cv=none; d=google.com; s=arc-20240605; b=AtknIGy/+gl7ntipXSgWW8YCPf0FTT3RfyYP4w4n9pClLXK4qngHf1pf5FLALTF/Vk 20IndaINcqugRrDpNob7SZxwPwtYbtkAPGz+sGP2kdqT2jL2J+XGWrLYxb23HGI5k6cO or9Sgz+me4JP4wn9ARC1Mm+58AtQVOqXJcDNkz5g+/NomBgYEzsbBF2bceG+V+Mm9NN8 FtUzlvzZveoQ22CUQdd+X8Es8nlAWqe3H8OEg4x2G27Coj3R6L32QDXnq0NPnpny6ale 2/BWQlfefS5BkJ2XLFOJLpL/0lBdAMOSDkVTFtHkU0HGPu6tDUBsOAsxEwjpE31I50hE vYwA== 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:dkim-signature; bh=G6Af1xBBBDnmz8nBgW/VR/l5hWd+I7KjueK8tmf2YTM=; fh=4NbAC/LsuMLI0S0hprUlLSLCiHwg6SCAifhH718Jh0Q=; b=FA7mBIre90mm3rFv82DJyu+FXoG2Z2F1tWCdTAgxQUomcADQLgRcCLJ4ZKtLqRTa3+ GY+c3INCuxpzYKdlj3p39bNiG0dLV+2IuhJp608t+oXrDOVQtoWNi8mWfQ2zbJm2u1On 8KuB1Kvp2cX8zmWJYlI2cSDBKjffxQSCGU20Rrqugarnbzw+aUFbQCCZmrXyOy6wPwTa EUR4ofTD6ksbVr2YzyWPDMFUfIcRAdS6FGB4R9ZOxrmewzow673SUD/2EAEl41dDpYg+ lrCtpjQyHxMT3R7uEz4GNPSBm+wH5jv6JOXrFwYelacnsnuLMWqBAeMjECLXsX7kc2nr 6giA==; 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=VFWqgDt5; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=jvEGL1YO; dkim=neutral (body hash did not verify) header.i=@lichtenheld.com header.s=MBO0001 header.b=U2STv67H; 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 lists.sourceforge.net (lists.sourceforge.net. [216.105.38.7]) by mx.google.com with ESMTPS id 46e09a7af769-71fc9a1023esi10715045a34.211.2024.12.27.04.46.56 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 27 Dec 2024 04:46:56 -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=VFWqgDt5; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=jvEGL1YO; dkim=neutral (body hash did not verify) header.i=@lichtenheld.com header.s=MBO0001 header.b=U2STv67H; 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-3.v29.lw.sourceforge.com) by sfs-ml-3.v29.lw.sourceforge.com with esmtp (Exim 4.95) (envelope-from ) id 1tR9jx-0002mn-Hh; Fri, 27 Dec 2024 12:46:52 +0000 Received: from [172.30.29.66] (helo=mx.sourceforge.net) by sfs-ml-3.v29.lw.sourceforge.com with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.95) (envelope-from ) id 1tR9jv-0002md-Er for openvpn-devel@lists.sourceforge.net; Fri, 27 Dec 2024 12:46:51 +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=QD4wPZTGbFpUeLAvRahTXDYNWA334XqXEe3jTex9uYo=; b=VFWqgDt5gco/LKoUdDXVhWCfNS BZwQLbMioH3rfeO6AVOIX58557P74uQ+q5KjNG8SpwYieTAParg209VI66DdY6dxkwf9qcWN865OC xjWc2ioIiXY1oBsDLWt4PHbT1ijE5lnpprBqjyL5YdWlzEdRqmUe78sN+8RkP8RHlcT8=; 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=QD4wPZTGbFpUeLAvRahTXDYNWA334XqXEe3jTex9uYo=; b=jvEGL1YOEEu9vyCqGKgXtCOORR 2HNNVmezrFx4YWtijyn5Sa/wLSAWc7zCVa4GcqH/61BoC9spSo/V9oGfjQpi3lvzsbLTmNBxDtqDW CGSs1+tuA70/rQvoOi540WYjp27tprHFPXDNYfmrro3moP9YrvYQnz4P8Lhz1VI4KBGw=; Received: from mout-p-202.mailbox.org ([80.241.56.172]) by sfi-mx-2.v28.lw.sourceforge.com with esmtps (TLS1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.95) id 1tR9js-0001nZ-AZ for openvpn-devel@lists.sourceforge.net; Fri, 27 Dec 2024 12:46:50 +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-202.mailbox.org (Postfix) with ESMTPS id 4YKQGy46pVz9sbY; Fri, 27 Dec 2024 13:46:34 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=lichtenheld.com; s=MBO0001; t=1735303594; 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=QD4wPZTGbFpUeLAvRahTXDYNWA334XqXEe3jTex9uYo=; b=U2STv67Ht0AWO/Uo5vuGWWcR6HUFZ0xN9FNATPMNw+xUMCm4kZJiMzfsJG5adDw42DbeYv 3Wfk3npz04uEcT2Yh8+yn9EZNryI46a5z6tirfpkbp6SY8/HYzqLMDOjFQOJNHY26qgxjr 7BZ+c8fUI1/SqINB6lScj+7SabCozh3aaIRxVjbDMzfY7YHensWKHUQlHyzZsXoX76zne1 CGozy9Vqw6XrOj0zJIqq3UZIogenyb9ynixAK2qfof0GwmrUQMQh8I6pEVdPWe0KUwTIHw TElQ0cYvTyINJS+dOwtVt+FL/9cB/BOjc3CSu0TMRzYtXOXitgZBuqBshrnImQ== From: Frank Lichtenheld To: openvpn-devel@lists.sourceforge.net Date: Fri, 27 Dec 2024 13:46:32 +0100 Message-Id: <20241227124632.110920-1-frank@lichtenheld.com> In-Reply-To: References: MIME-Version: 1.0 X-Rspamd-Queue-Id: 4YKQGy46pVz9sbY X-Spam-Score: -0.9 (/) 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: From: Arne Schwabe This adds support for parsing DEFAULT in data-ciphers, the idea is that people can modify the default without repeating the default ciphers. In the past we have seem that people will use data-ciphers BF-CBC or data-ciphers AES-128-CBC when getting the warning that the cipher is not supported by the server. This commit aims to provide a bet [...] Content analysis details: (-0.9 points, 6.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 RCVD_IN_VALIDITY_SAFE_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [80.241.56.172 listed in sa-trusted.bondedsender.org] 0.0 RCVD_IN_VALIDITY_RPBL_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [80.241.56.172 listed in bl.score.senderscore.com] -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at https://www.dnswl.org/, low trust [80.241.56.172 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid X-Headers-End: 1tR9js-0001nZ-AZ Subject: [Openvpn-devel] [PATCH v3] Allow DEFAULT in data-ciphers and report both expanded and user set option 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?1819597724989776170?= X-GMAIL-MSGID: =?utf-8?q?1819597724989776170?= From: Arne Schwabe This adds support for parsing DEFAULT in data-ciphers, the idea is that people can modify the default without repeating the default ciphers. In the past we have seem that people will use data-ciphers BF-CBC or data-ciphers AES-128-CBC when getting the warning that the cipher is not supported by the server. This commit aims to provide a better way for these situation as we still want people to rely on default cipher selection from OpenVPN when possible. Change-Id: Ia1c5209022d3ab4c0dac6438c41891c7d059f812 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/+/828 This mail reflects revision 3 of this Change. Acked-by according to Gerrit (reflected above): Frank Lichtenheld diff --git a/Changes.rst b/Changes.rst index 34542a5..16ae6fc 100644 --- a/Changes.rst +++ b/Changes.rst @@ -30,6 +30,12 @@ https://datatracker.ietf.org/doc/draft-irtf-cfrg-aead-limits/ +Default ciphers in ``--data-ciphers`` + Ciphers in ``--data-ciphers`` can contain the string DEFAULT that is + replaced by the default ciphers used by OpenVPN, making it easier to + add an allowed cipher without having to spell out the default ciphers. + + Deprecated features ------------------- ``secret`` support has been removed by default. diff --git a/doc/man-sections/protocol-options.rst b/doc/man-sections/protocol-options.rst index 05f87cc..d04ace8 100644 --- a/doc/man-sections/protocol-options.rst +++ b/doc/man-sections/protocol-options.rst @@ -178,6 +178,12 @@ Chacha20-Poly1305 if the underlying SSL library (and its configuration) supports it. + Starting with OpenVPN 2.7 the special keyword :code:`DEFAULT` can be used + in the string and is replaced by the default ciphers. This can be used to + add an additional allowed cipher to the allowed ciphers, e.g. + :code:`DEFAULT:AES-192-CBC` to use the default ciphers but also allow + :code:`AES-192-CBC`. + Cipher negotiation is enabled in client-server mode only. I.e. if ``--mode`` is set to `server` (server-side, implied by setting ``--server`` ), or if ``--pull`` is specified (client-side, implied by diff --git a/src/openvpn/multi.c b/src/openvpn/multi.c index 45b3cfa..279be57 100644 --- a/src/openvpn/multi.c +++ b/src/openvpn/multi.c @@ -1896,14 +1896,15 @@ if (strlen(peer_ciphers) > 0) { msg(M_INFO, "PUSH: No common cipher between server and client. " - "Server data-ciphers: '%s', client supported ciphers '%s'", - o->ncp_ciphers, peer_ciphers); + "Server data-ciphers: '%s'%s, client supported ciphers '%s'", + o->ncp_ciphers_conf, ncp_expanded_ciphers(o, &gc), peer_ciphers); } else if (tls_multi->remote_ciphername) { msg(M_INFO, "PUSH: No common cipher between server and client. " - "Server data-ciphers: '%s', client supports cipher '%s'", - o->ncp_ciphers, tls_multi->remote_ciphername); + "Server data-ciphers: '%s'%s, client supports cipher '%s'", + o->ncp_ciphers_conf, ncp_expanded_ciphers(o, &gc), + tls_multi->remote_ciphername); } else { diff --git a/src/openvpn/options.c b/src/openvpn/options.c index b2a3a8b..d1714fd 100644 --- a/src/openvpn/options.c +++ b/src/openvpn/options.c @@ -3486,40 +3486,6 @@ } } - -/** - * Checks for availibility of Chacha20-Poly1305 and sets - * the ncp_cipher to either AES-256-GCM:AES-128-GCM or - * AES-256-GCM:AES-128-GCM:CHACHA20-POLY1305. - */ -static void -options_postprocess_setdefault_ncpciphers(struct options *o) -{ - if (o->ncp_ciphers) - { - /* custom --data-ciphers set, keep list */ - return; - } - - /* check if crypto library supports chacha */ - bool can_do_chacha = cipher_valid("CHACHA20-POLY1305"); - - if (can_do_chacha && dco_enabled(o)) - { - /* also make sure that dco supports chacha */ - can_do_chacha = tls_item_in_cipher_list("CHACHA20-POLY1305", dco_get_supported_ciphers()); - } - - if (can_do_chacha) - { - o->ncp_ciphers = "AES-256-GCM:AES-128-GCM:CHACHA20-POLY1305"; - } - else - { - o->ncp_ciphers = "AES-256-GCM:AES-128-GCM"; - } -} - static void options_postprocess_cipher(struct options *o) { @@ -3550,7 +3516,8 @@ "defaulted to BF-CBC as fallback when cipher negotiation " "failed in this case. If you need this fallback please add " "'--data-ciphers-fallback BF-CBC' to your configuration " - "and/or add BF-CBC to --data-ciphers."); + "and/or add BF-CBC to --data-ciphers. E.g. " + "--data-ciphers %s:BF-CBC", o->ncp_ciphers_conf); } else if (!o->enable_ncp_fallback && !tls_item_in_cipher_list(o->ciphername, o->ncp_ciphers)) @@ -3558,7 +3525,7 @@ msg(M_WARN, "DEPRECATED OPTION: --cipher set to '%s' but missing in " "--data-ciphers (%s). OpenVPN ignores --cipher for cipher " "negotiations. ", - o->ciphername, o->ncp_ciphers); + o->ciphername, o->ncp_ciphers_conf); } } diff --git a/src/openvpn/options.h b/src/openvpn/options.h index 6ab92e2..55f12dd 100644 --- a/src/openvpn/options.h +++ b/src/openvpn/options.h @@ -559,6 +559,8 @@ const char *ciphername; bool enable_ncp_fallback; /**< If defined fall back to * ciphername if NCP fails */ + /** The original ncp_ciphers specified by the user in the configuration*/ + const char *ncp_ciphers_conf; const char *ncp_ciphers; const char *authname; const char *engine; diff --git a/src/openvpn/ssl_ncp.c b/src/openvpn/ssl_ncp.c index 968858e..e403ae6 100644 --- a/src/openvpn/ssl_ncp.c +++ b/src/openvpn/ssl_ncp.c @@ -39,6 +39,8 @@ #include "config.h" #endif +#include + #include "syshead.h" #include "win32.h" @@ -222,7 +224,6 @@ return token != NULL; } - const char * tls_peer_ncp_list(const char *peer_info, struct gc_arena *gc) { @@ -334,15 +335,16 @@ return true; } - /* We failed negotiation, give appropiate error message */ + /* We failed negotiation, give appropriate error message */ if (c->c2.tls_multi->remote_ciphername) { msg(D_TLS_ERRORS, "OPTIONS ERROR: failed to negotiate " "cipher with server. Add the server's " - "cipher ('%s') to --data-ciphers (currently '%s') if " - "you want to connect to this server.", + "cipher ('%s') to --data-ciphers (currently '%s'), e.g." + "--data-ciphers %s:%s if you want to connect to this server.", c->c2.tls_multi->remote_ciphername, - c->options.ncp_ciphers); + c->options.ncp_ciphers_conf, c->options.ncp_ciphers_conf, + c->c2.tls_multi->remote_ciphername); return false; } @@ -516,10 +518,13 @@ if (!session->opt->server && !cipher_allowed_as_fallback && !tls_item_in_cipher_list(options->ciphername, options->ncp_ciphers)) { - msg(D_TLS_ERRORS, "Error: negotiated cipher not allowed - %s not in %s", - options->ciphername, options->ncp_ciphers); + struct gc_arena gc = gc_new(); + msg(D_TLS_ERRORS, "Error: negotiated cipher not allowed - %s not in %s%s", + options->ciphername, options->ncp_ciphers_conf, + ncp_expanded_ciphers(options, &gc)); /* undo cipher push, abort connection setup */ options->ciphername = session->opt->config_ciphername; + gc_free(&gc); return false; } else @@ -527,3 +532,100 @@ return true; } } + +/** + * Replaces the string DEFAULT with the string \c replace. + * + * @param o Options struct to modify and to use the gc from + * @param replace string used to replace the DEFAULT string + */ +static void +replace_default_in_ncp_ciphers_option(struct options *o, const char *replace) +{ + const char *search = "DEFAULT"; + const int ncp_ciphers_len = strlen(o->ncp_ciphers) + strlen(replace) - strlen(search) + 1; + + uint8_t *ncp_ciphers = gc_malloc(ncp_ciphers_len, true, &o->gc); + + struct buffer ncp_ciphers_buf; + buf_set_write(&ncp_ciphers_buf, ncp_ciphers, ncp_ciphers_len); + + const char *def = strstr(o->ncp_ciphers, search); + + /* Copy everything before the DEFAULT string */ + buf_write(&ncp_ciphers_buf, o->ncp_ciphers, def - o->ncp_ciphers); + + /* copy the default string. */ + buf_write(&ncp_ciphers_buf, replace, strlen(replace)); + + /* copy the rest of the ncp cipher string */ + const char *after_default = def + strlen(search); + buf_write(&ncp_ciphers_buf, after_default, strlen(after_default)); + + o->ncp_ciphers = (char *) ncp_ciphers; +} + +/** + * Checks for availibility of Chacha20-Poly1305 and sets + * the ncp_cipher to either AES-256-GCM:AES-128-GCM or + * AES-256-GCM:AES-128-GCM:CHACHA20-POLY1305. + */ +void +options_postprocess_setdefault_ncpciphers(struct options *o) +{ + bool default_in_cipher_list = o->ncp_ciphers + && tls_item_in_cipher_list("DEFAULT", o->ncp_ciphers); + + /* preserve the values that the user put into the configuration */ + o->ncp_ciphers_conf = o->ncp_ciphers; + + /* check if crypto library supports chacha */ + bool can_do_chacha = cipher_valid("CHACHA20-POLY1305"); + + if (can_do_chacha && dco_enabled(o)) + { + /* also make sure that dco supports chacha */ + can_do_chacha = tls_item_in_cipher_list("CHACHA20-POLY1305", dco_get_supported_ciphers()); + } + + const char *default_ciphers = "AES-256-GCM:AES-128-GCM:CHACHA20-POLY1305"; + + if (!can_do_chacha) + { + default_ciphers = "AES-256-GCM:AES-128-GCM"; + } + + /* want to rather print DEFAULT instead of a manually set default list */ + if (!o->ncp_ciphers_conf || !strcmp(default_ciphers, o->ncp_ciphers_conf)) + { + o->ncp_ciphers = default_ciphers; + o->ncp_ciphers_conf = "DEFAULT"; + } + else if (!default_in_cipher_list) + { + /* custom cipher list without DEFAULT string in it, + * nothing to replace/mutate */ + return; + } + else + { + replace_default_in_ncp_ciphers_option(o, default_ciphers); + } +} + +const char * +ncp_expanded_ciphers(struct options *o, struct gc_arena *gc) +{ + if (!strcmp(o->ncp_ciphers, o->ncp_ciphers_conf)) + { + /* expanded ciphers and user set ciphers are identical, no need to + * add an expanded version */ + return ""; + } + + /* two extra brackets, one space, NUL byte */ + struct buffer expanded_ciphers_buf = alloc_buf_gc(strlen(o->ncp_ciphers) + 4, gc); + + buf_printf(&expanded_ciphers_buf, " (%s)", o->ncp_ciphers); + return BSTR(&expanded_ciphers_buf); +} diff --git a/src/openvpn/ssl_ncp.h b/src/openvpn/ssl_ncp.h index afbe331..f90b19a 100644 --- a/src/openvpn/ssl_ncp.h +++ b/src/openvpn/ssl_ncp.h @@ -156,4 +156,23 @@ bool check_session_cipher(struct tls_session *session, struct options *options); +/** + * Checks for availability of Chacha20-Poly1305 and sets + * the ncp_cipher to either AES-256-GCM:AES-128-GCM or + * AES-256-GCM:AES-128-GCM:CHACHA20-POLY1305 if not set. + * + * If DEFAULT is in the ncp_cipher string, it will be replaced + * by the default cipher string as defined above. + */ +void +options_postprocess_setdefault_ncpciphers(struct options *o); + +/** returns the o->ncp_ciphers in brackets, e.g. + * (AES-256-GCM:CHACHA20-POLY1305) if o->ncp_ciphers_conf + * and o->ncp_ciphers differ, otherwise an empty string + * + * The returned string will be allocated in the passed \c gc + */ +const char * +ncp_expanded_ciphers(struct options *o, struct gc_arena *gc); #endif /* ifndef OPENVPN_SSL_NCP_H */ diff --git a/tests/unit_tests/openvpn/test_ncp.c b/tests/unit_tests/openvpn/test_ncp.c index a8e1021..b744e96 100644 --- a/tests/unit_tests/openvpn/test_ncp.c +++ b/tests/unit_tests/openvpn/test_ncp.c @@ -54,6 +54,17 @@ ASSERT(0); } + +/* Define a dummy dco cipher option to avoid linking against all the DCO + * units */ +#if defined(ENABLE_DCO) +const char * +dco_get_supported_ciphers(void) +{ + return "AES-192-GCM:AES-128-CBC:AES-256-GCM:AES-128-GCM:CHACHA20-POLY1305"; +} +#endif + static void test_check_ncp_ciphers_list(void **state) { @@ -260,13 +271,135 @@ gc_free(&gc); } +static void +test_ncp_default(void **state) +{ + bool have_chacha = cipher_valid("CHACHA20-POLY1305"); + + struct options o = { 0 }; + + o.gc = gc_new(); + + /* no user specified string */ + o.ncp_ciphers = NULL; + options_postprocess_setdefault_ncpciphers(&o); + + if (have_chacha) + { + assert_string_equal(o.ncp_ciphers, "AES-256-GCM:AES-128-GCM:CHACHA20-POLY1305"); + } + else + { + assert_string_equal(o.ncp_ciphers, "AES-256-GCM:AES-128-GCM"); + } + assert_string_equal(o.ncp_ciphers_conf, "DEFAULT"); + + /* check that a default string is replaced with DEFAULT */ + if (have_chacha) + { + o.ncp_ciphers = "AES-256-GCM:AES-128-GCM:CHACHA20-POLY1305"; + } + else + { + o.ncp_ciphers = "AES-256-GCM:AES-128-GCM"; + } + + options_postprocess_setdefault_ncpciphers(&o); + assert_string_equal(o.ncp_ciphers_conf, "DEFAULT"); + + /* test default in the middle of the string */ + o.ncp_ciphers = "BF-CBC:DEFAULT:AES-128-CBC:AES-256-CBC"; + options_postprocess_setdefault_ncpciphers(&o); + + if (have_chacha) + { + assert_string_equal(o.ncp_ciphers, "BF-CBC:AES-256-GCM:AES-128-GCM:CHACHA20-POLY1305:AES-128-CBC:AES-256-CBC"); + } + else + { + assert_string_equal(o.ncp_ciphers, "BF-CBC:AES-256-GCM:AES-128-GCM:AES-128-CBC:AES-256-CBC"); + } + assert_string_equal(o.ncp_ciphers_conf, "BF-CBC:DEFAULT:AES-128-CBC:AES-256-CBC"); + + /* string at the beginning */ + o.ncp_ciphers = "DEFAULT:AES-128-CBC:AES-192-CBC"; + options_postprocess_setdefault_ncpciphers(&o); + + if (have_chacha) + { + assert_string_equal(o.ncp_ciphers, "AES-256-GCM:AES-128-GCM:CHACHA20-POLY1305:AES-128-CBC:AES-192-CBC"); + } + else + { + assert_string_equal(o.ncp_ciphers, "AES-256-GCM:AES-128-GCM:AES-128-CBC:AES-192-CBC"); + } + assert_string_equal(o.ncp_ciphers_conf, "DEFAULT:AES-128-CBC:AES-192-CBC"); + + /* DEFAULT at the end */ + o.ncp_ciphers = "AES-192-GCM:AES-128-CBC:DEFAULT"; + options_postprocess_setdefault_ncpciphers(&o); + + if (have_chacha) + { + assert_string_equal(o.ncp_ciphers, "AES-192-GCM:AES-128-CBC:AES-256-GCM:AES-128-GCM:CHACHA20-POLY1305"); + } + else + { + assert_string_equal(o.ncp_ciphers, "AES-192-GCM:AES-128-CBC:AES-256-GCM:AES-128-GCM"); + } + assert_string_equal(o.ncp_ciphers_conf, "AES-192-GCM:AES-128-CBC:DEFAULT"); + + gc_free(&o.gc); +} + +static void +test_ncp_expand(void **state) +{ + bool have_chacha = cipher_valid("CHACHA20-POLY1305"); + struct options o = {0}; + + o.gc = gc_new(); + struct gc_arena gc = gc_new(); + + /* no user specified string */ + o.ncp_ciphers = NULL; + options_postprocess_setdefault_ncpciphers(&o); + + const char *expanded = ncp_expanded_ciphers(&o, &gc); + + /* user specificed string with DEFAULT in it */ + o.ncp_ciphers = "AES-192-GCM:DEFAULT"; + options_postprocess_setdefault_ncpciphers(&o); + const char *expanded2 = ncp_expanded_ciphers(&o, &gc); + + if (have_chacha) + { + assert_string_equal(expanded, " (AES-256-GCM:AES-128-GCM:CHACHA20-POLY1305)"); + assert_string_equal(expanded2, " (AES-192-GCM:AES-256-GCM:AES-128-GCM:CHACHA20-POLY1305)"); + } + else + { + assert_string_equal(expanded, " (AES-256-GCM:AES-128-GCM)"); + assert_string_equal(expanded2, " (AES-192-GCM:AES-256-GCM:AES-128-GCM)"); + } + + o.ncp_ciphers = "AES-192-GCM:BF-CBC"; + options_postprocess_setdefault_ncpciphers(&o); + + assert_string_equal(ncp_expanded_ciphers(&o, &gc), ""); + + gc_free(&o.gc); + gc_free(&gc); +} const struct CMUnitTest ncp_tests[] = { cmocka_unit_test(test_check_ncp_ciphers_list), cmocka_unit_test(test_extract_client_ciphers), cmocka_unit_test(test_poor_man), - cmocka_unit_test(test_ncp_best) + cmocka_unit_test(test_ncp_best), + cmocka_unit_test(test_ncp_default), + cmocka_unit_test(test_ncp_expand), };