All of lore.kernel.org
 help / color / mirror / Atom feed
From: Dmitry Safonov <dima@arista.com>
To: linux-kernel@vger.kernel.org, David Ahern <dsahern@kernel.org>,
	Eric Dumazet <edumazet@google.com>
Cc: Dmitry Safonov <dima@arista.com>,
	Andy Lutomirski <luto@amacapital.net>,
	Ard Biesheuvel <ardb@kernel.org>,
	Bob Gilligan <gilligan@arista.com>,
	Dan Carpenter <dan.carpenter@oracle.com>,
	"David S. Miller" <davem@davemloft.net>,
	Dmitry Safonov <0x7f454c46@gmail.com>,
	Eric Biggers <ebiggers@kernel.org>,
	"Eric W. Biederman" <ebiederm@xmission.com>,
	Francesco Ruggeri <fruggeri@arista.com>,
	Herbert Xu <herbert@gondor.apana.org.au>,
	Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>,
	Ivan Delalande <colona@arista.com>,
	Jakub Kicinski <kuba@kernel.org>,
	Leonard Crestez <cdleonard@gmail.com>,
	Paolo Abeni <pabeni@redhat.com>,
	Salam Noureddine <noureddine@arista.com>,
	Shuah Khan <shuah@kernel.org>,
	netdev@vger.kernel.org, linux-crypto@vger.kernel.org
Subject: [PATCH v3 35/36] selftests/nettest: Add TCP-AO support
Date: Thu, 27 Oct 2022 21:43:46 +0100	[thread overview]
Message-ID: <20221027204347.529913-36-dima@arista.com> (raw)
In-Reply-To: <20221027204347.529913-1-dima@arista.com>

Roughly, the same as TCP-MD5 support.

Signed-off-by: Dmitry Safonov <dima@arista.com>
---
 tools/testing/selftests/net/nettest.c | 179 +++++++++++++++++++++++---
 1 file changed, 160 insertions(+), 19 deletions(-)

diff --git a/tools/testing/selftests/net/nettest.c b/tools/testing/selftests/net/nettest.c
index 3499d6aff9e4..c81d3e2ceae1 100644
--- a/tools/testing/selftests/net/nettest.c
+++ b/tools/testing/selftests/net/nettest.c
@@ -77,7 +77,9 @@ struct sock_args {
 		     has_expected_laddr:1,
 		     has_expected_raddr:1,
 		     bind_test_only:1,
-		     use_md5:1;
+		     use_md5:1,
+		     use_tcpao:1,
+		     tcp_ao_excopts:1;
 
 	unsigned short port;
 
@@ -96,7 +98,7 @@ struct sock_args {
 	const char *serverns;
 
 	const char *password;
-	/* prefix for MD5 password */
+	/* prefix for MD5/TCP-AO password */
 	const char *auth_prefix_str;
 	union {
 		struct sockaddr_in v4;
@@ -105,6 +107,8 @@ struct sock_args {
 	unsigned int prefix_len;
 	/* 0: default, -1: force off, +1: force on */
 	int bind_key_ifindex;
+	unsigned int tcp_ao_sndid, tcp_ao_rcvid, tcp_ao_maclen;
+	char *tcp_ao_algo;
 
 	/* expected addresses and device index for connection */
 	const char *expected_dev;
@@ -300,7 +304,67 @@ static int tcp_md5sig(int sd, void *addr, socklen_t alen, struct sock_args *args
 	return rc;
 }
 
-static int tcp_md5_remote(int sd, struct sock_args *args)
+static int tcp_ao(int sd, void *addr, socklen_t alen, struct sock_args *args)
+{
+	int keylen = strlen(args->password);
+	struct tcp_ao ao = {};
+	int opt = TCP_AO;
+	int rc;
+
+	if (keylen > TCP_AO_MAXKEYLEN) {
+		log_error("key length is too big");
+		return -1;
+	}
+	ao.tcpa_keylen = keylen;
+	memcpy(ao.tcpa_key, args->password, keylen);
+	if (args->tcp_ao_algo)
+		strcpy(ao.tcpa_alg_name, args->tcp_ao_algo);
+	else
+		strcpy(ao.tcpa_alg_name, "cmac(aes128)");
+	if (args->tcp_ao_maclen)
+		ao.tcpa_maclen = args->tcp_ao_maclen;
+
+	ao.tcpa_sndid = args->tcp_ao_sndid;
+	ao.tcpa_rcvid = args->tcp_ao_rcvid;
+	if (args->tcp_ao_excopts)
+		ao.tcpa_keyflags |= TCP_AO_KEYF_EXCLUDE_OPT;
+
+	if (args->prefix_len) {
+		ao.tcpa_prefix = args->prefix_len;
+	} else {
+		switch (args->version) {
+		case AF_INET:
+			ao.tcpa_prefix = 32;
+			break;
+		case AF_INET6:
+			ao.tcpa_prefix = 128;
+			break;
+		default:
+			log_error("unknown address family\n");
+			exit(1);
+		}
+	}
+	memcpy(&ao.tcpa_addr, addr, alen);
+
+	/* FIXME: Remove once matching by port is supported */
+	if (args->version == AF_INET) {
+		struct sockaddr_in *sin = (void *)&ao.tcpa_addr;
+
+		sin->sin_port = htons(0);
+	} else if (args->version == AF_INET6) {
+		struct sockaddr_in6 *sin6 = (void *)&ao.tcpa_addr;
+
+		sin6->sin6_port = htons(0);
+	}
+
+	rc = setsockopt(sd, IPPROTO_TCP, opt, &ao, sizeof(ao));
+	if (rc < 0)
+		log_err_errno("setsockopt(TCP_AO)");
+
+	return rc;
+}
+
+static int tcp_auth_remote(int sd, struct sock_args *args)
 {
 	struct sockaddr_in sin = {
 		.sin_family = AF_INET,
@@ -329,7 +393,10 @@ static int tcp_md5_remote(int sd, struct sock_args *args)
 		exit(1);
 	}
 
-	if (tcp_md5sig(sd, addr, alen, args))
+	if (args->use_md5 && tcp_md5sig(sd, addr, alen, args))
+		return -1;
+
+	if (args->use_tcpao && tcp_ao(sd, addr, alen, args))
 		return -1;
 
 	return 0;
@@ -1546,10 +1613,8 @@ static int do_server(struct sock_args *args, int ipc_fd)
 		return rc;
 	}
 
-	if (args->use_md5 && tcp_md5_remote(lsd, args)) {
-		close(lsd);
-		goto err_exit;
-	}
+	if (tcp_auth_remote(lsd, args))
+		goto err_close;
 
 	ipc_write(ipc_fd, 1);
 	while (1) {
@@ -1598,6 +1663,8 @@ static int do_server(struct sock_args *args, int ipc_fd)
 	close(lsd);
 
 	return rc;
+err_close:
+	close(lsd);
 err_exit:
 	ipc_write(ipc_fd, 0);
 	return 1;
@@ -1673,6 +1740,9 @@ static int connectsock(void *addr, socklen_t alen, struct sock_args *args)
 	if (args->use_md5 && tcp_md5sig(sd, addr, alen, args))
 		goto err;
 
+	if (args->use_tcpao && tcp_ao(sd, addr, alen, args))
+		goto err;
+
 	if (args->bind_test_only)
 		goto out;
 
@@ -1799,6 +1869,44 @@ static char *random_msg(int len)
 	return m;
 }
 
+static void strip_newlines(char *str)
+{
+	size_t i = strlen(str);
+
+	for (; i > 0; i--) {
+		if (str[i - 1] != '\n')
+			return;
+		str[i - 1] = '\0';
+	}
+}
+
+static int set_tcp_ao_param(struct sock_args *args, const char *opt)
+{
+	char *end, *sep = strstr(opt, ":");
+	unsigned long tmp;
+
+	errno = 0;
+	if (sep == NULL)
+		goto err_fail;
+
+	tmp = strtoul(opt, &end, 0);
+	if (errno || tmp > 255 || end != sep)
+		goto err_fail;
+	args->tcp_ao_sndid = (unsigned int) tmp;
+
+	tmp = strtoul(++sep, &end, 0);
+	if (errno || tmp > 255 || (*end != '\n' && *end != '\0'))
+		goto err_fail;
+	args->tcp_ao_rcvid = (unsigned int) tmp;
+
+	return 0;
+
+err_fail:
+	fprintf(stderr, "TCP-AO argument format is sndid:rcvid where ids in [0,255]\n"
+			"Example: -T 100:200\n");
+	return -1;
+}
+
 static int ipc_child(int fd, struct sock_args *args)
 {
 	char *outbuf, *errbuf;
@@ -1860,13 +1968,19 @@ static int ipc_parent(int cpid, int fd, struct sock_args *args)
 	return client_status;
 }
 
-#define GETOPT_STR  "sr:l:c:p:t:g:P:DRn:MX:m:d:I:BN:O:SUCi6xL:0:1:2:3:Fbqf"
-#define OPT_FORCE_BIND_KEY_IFINDEX 1001
-#define OPT_NO_BIND_KEY_IFINDEX 1002
+#define GETOPT_STR  "sr:l:c:p:t:g:P:DRn:MT:X:m:d:I:BN:O:SUCi6xL:0:1:2:3:Fbqf"
+#define OPT_FORCE_BIND_KEY_IFINDEX	1001
+#define OPT_NO_BIND_KEY_IFINDEX		1002
+#define OPT_TCPAO_ALGO			1003
+#define OPT_TCPAO_MACLEN		1004
+#define OPT_TCPAO_EXCOPTS		1005
 
 static struct option long_opts[] = {
-	{"force-bind-key-ifindex", 0, 0, OPT_FORCE_BIND_KEY_IFINDEX},
-	{"no-bind-key-ifindex", 0, 0, OPT_NO_BIND_KEY_IFINDEX},
+	{"force-bind-key-ifindex",	0, 0, OPT_FORCE_BIND_KEY_IFINDEX},
+	{"no-bind-key-ifindex",		0, 0, OPT_NO_BIND_KEY_IFINDEX},
+	{"tcpao_algo",			1, 0, OPT_TCPAO_ALGO },
+	{"tcpao_maclen",		1, 0, OPT_TCPAO_MACLEN },
+	{"tcpao_excopts",		0, 0, OPT_TCPAO_EXCOPTS },
 	{0, 0, 0, 0}
 };
 
@@ -1905,8 +2019,12 @@ static void print_usage(char *prog)
 	"    -n num        number of times to send message\n"
 	"\n"
 	"    -M            use MD5 sum protection\n"
-	"    -X password   MD5 password\n"
-	"    -m prefix/len prefix and length to use for MD5 key\n"
+	"    -T snd:rcvid  use TCP authopt (RFC5925) with snd/rcv ids\n"
+	"    --tcpao_algo=algo      TCP-AO hashing algorithm [valid with -T]\n"
+	"    --tcpao_maclen=maclen  TCP-AO MAC length [valid with -T]\n"
+	"    --tcpao_excopts        Exclude TCP options [valid with -T]\n"
+	"    -X password   MD5/TCP-AO password\n"
+	"    -m prefix/len prefix and length to use for MD5/TCP-AO key\n"
 	"    --no-bind-key-ifindex: Force TCP_MD5SIG_FLAG_IFINDEX off\n"
 	"    --force-bind-key-ifindex: Force TCP_MD5SIG_FLAG_IFINDEX on\n"
 	"        (default: only if -I is passed)\n"
@@ -2025,6 +2143,29 @@ int main(int argc, char *argv[])
 		case OPT_NO_BIND_KEY_IFINDEX:
 			args.bind_key_ifindex = -1;
 			break;
+		case OPT_TCPAO_ALGO:
+			args.tcp_ao_algo = strdup(optarg);
+			strip_newlines(args.tcp_ao_algo);
+			if (strlen(args.tcp_ao_algo) == 0) {
+				fprintf(stderr, "Invalid argument --tcpao_algo=%s\n", optarg);
+				return 1;
+			}
+			break;
+		case OPT_TCPAO_MACLEN:
+			if (str_to_uint(optarg, 1, 255, &tmp) != 0) {
+				fprintf(stderr, "Invalid --tcpao_maclen=%s\n", optarg);
+				return 1;
+			}
+			args.tcp_ao_maclen = tmp;
+			break;
+		case OPT_TCPAO_EXCOPTS:
+			args.tcp_ao_excopts = 1;
+			break;
+		case 'T':
+			args.use_tcpao = 1;
+			if (set_tcp_ao_param(&args, optarg))
+				return 1;
+			break;
 		case 'X':
 			args.password = optarg;
 			break;
@@ -2090,15 +2231,15 @@ int main(int argc, char *argv[])
 		}
 	}
 
-	if (args.password && (!args.use_md5 ||
+	if (args.password && ((!args.use_md5 && !args.use_tcpao) ||
 	      (!args.has_remote_ip && !args.auth_prefix_str) ||
 	      args.type != SOCK_STREAM)) {
-		log_error("MD5 passwords apply to TCP only and require a remote ip for the password\n");
+		log_error("TCP-MD5/TCP-AO passwords apply to TCP only and require a remote ip for the password\n");
 		return 1;
 	}
 
-	if ((args.auth_prefix_str || args.use_md5) && !args.password) {
-		log_error("Prefix range for MD5 protection specified without a password\n");
+	if ((args.auth_prefix_str || args.use_md5 || args.use_tcpao) && !args.password) {
+		log_error("Prefix range for TCP-MD5/TCP-AO protection specified without a password\n");
 		return 1;
 	}
 
-- 
2.38.1


  parent reply	other threads:[~2022-10-27 20:53 UTC|newest]

Thread overview: 42+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-10-27 20:43 [PATCH v3 00/36] net/tcp: Add TCP-AO support Dmitry Safonov
2022-10-27 20:43 ` [PATCH v3 01/36] crypto: Introduce crypto_pool Dmitry Safonov
2022-10-27 20:43 ` [PATCH v3 02/36] crypto_pool: Add crypto_pool_reserve_scratch() Dmitry Safonov
2022-10-28  7:06   ` kernel test robot
2022-10-27 20:43 ` [PATCH v3 03/36] net/tcp: Separate tcp_md5sig_info allocation into tcp_md5sig_info_add() Dmitry Safonov
2022-10-27 20:43 ` [PATCH v3 04/36] net/tcp: Disable TCP-MD5 static key on tcp_md5sig_info destruction Dmitry Safonov
2022-10-27 20:43 ` [PATCH v3 05/36] net/tcp: Use crypto_pool for TCP-MD5 Dmitry Safonov
2022-10-27 20:43 ` [PATCH v3 06/36] net/ipv6: sr: Switch to using crypto_pool Dmitry Safonov
2022-10-27 20:43 ` [PATCH v3 07/36] tcp: Add TCP-AO config and structures Dmitry Safonov
2022-10-27 20:43 ` [PATCH v3 08/36] net/tcp: Introduce TCP_AO setsockopt()s Dmitry Safonov
2022-10-27 20:43 ` [PATCH v3 09/36] net/tcp: Prevent TCP-MD5 with TCP-AO being set Dmitry Safonov
2022-10-27 20:43 ` [PATCH v3 10/36] net/tcp: Calculate TCP-AO traffic keys Dmitry Safonov
2022-10-28  8:07   ` kernel test robot
2022-10-27 20:43 ` [PATCH v3 11/36] net/tcp: Add TCP-AO sign to outgoing packets Dmitry Safonov
2022-10-27 20:43 ` [PATCH v3 12/36] net/tcp: Add tcp_parse_auth_options() Dmitry Safonov
2022-10-27 20:43 ` [PATCH v3 13/36] net/tcp: Add AO sign to RST packets Dmitry Safonov
2022-10-27 20:43 ` [PATCH v3 14/36] net/tcp: Add TCP-AO sign to twsk Dmitry Safonov
2022-10-27 20:43 ` [PATCH v3 15/36] net/tcp: Wire TCP-AO to request sockets Dmitry Safonov
2022-10-27 20:43 ` [PATCH v3 16/36] net/tcp: Sign SYN-ACK segments with TCP-AO Dmitry Safonov
2022-10-27 20:43 ` [PATCH v3 17/36] net/tcp: Verify inbound TCP-AO signed segments Dmitry Safonov
2022-10-28  5:15   ` kernel test robot
2022-10-27 20:43 ` [PATCH v3 18/36] net/tcp: Add TCP-AO segments counters Dmitry Safonov
2022-10-27 20:43 ` [PATCH v3 19/36] net/tcp: Add TCP-AO SNE support Dmitry Safonov
2022-10-27 20:43 ` [PATCH v3 20/36] net/tcp: Add tcp_hash_fail() ratelimited logs Dmitry Safonov
2022-10-27 20:43 ` [PATCH v3 21/36] net/tcp: Ignore specific ICMPs for TCP-AO connections Dmitry Safonov
2022-10-27 20:43 ` [PATCH v3 22/36] net/tcp: Add option for TCP-AO to (not) hash header Dmitry Safonov
2022-10-27 20:43 ` [PATCH v3 23/36] net/tcp: Add getsockopt(TCP_AO_GET) Dmitry Safonov
2022-10-27 20:43 ` [PATCH v3 24/36] net/tcp: Allow asynchronous delete for TCP-AO keys (MKTs) Dmitry Safonov
2022-10-27 20:43 ` [PATCH v3 25/36] net/tcp-ao: Add static_key for TCP-AO Dmitry Safonov
2022-10-27 20:43 ` [PATCH v3 26/36] selftests/net: Add TCP-AO library Dmitry Safonov
2022-10-27 20:43 ` [PATCH v3 27/36] selftests/net: Verify that TCP-AO complies with ignoring ICMPs Dmitry Safonov
2022-10-27 20:43 ` [PATCH v3 28/36] selftest/net: Add TCP-AO ICMPs accept test Dmitry Safonov
2022-10-27 20:43 ` [PATCH v3 29/36] selftest/tcp-ao: Add a test for MKT matching Dmitry Safonov
2022-10-27 20:43 ` [PATCH v3 30/36] selftest/tcp-ao: Add test for TCP-AO add setsockopt() command Dmitry Safonov
2022-10-27 20:43 ` [PATCH v3 31/36] selftests/tcp-ao: Add TCP-AO + TCP-MD5 + no sign listen socket tests Dmitry Safonov
2022-10-27 20:43 ` [PATCH v3 32/36] selftests/aolib: Add test/benchmark for removing MKTs Dmitry Safonov
2022-10-27 20:43 ` [PATCH v3 33/36] selftests/nettest: Remove client_pw Dmitry Safonov
2022-10-27 20:43 ` [PATCH v3 34/36] selftest/nettest: Rename md5_prefix* => auth_prefix* Dmitry Safonov
2022-10-27 20:43 ` Dmitry Safonov [this message]
2022-10-27 20:43 ` [PATCH v3 36/36] selftests/fcnal-test.sh: Add TCP-AO tests Dmitry Safonov
2022-11-01  2:22 ` [PATCH v3 00/36] net/tcp: Add TCP-AO support David Ahern
2022-11-01 17:35   ` Dmitry Safonov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20221027204347.529913-36-dima@arista.com \
    --to=dima@arista.com \
    --cc=0x7f454c46@gmail.com \
    --cc=ardb@kernel.org \
    --cc=cdleonard@gmail.com \
    --cc=colona@arista.com \
    --cc=dan.carpenter@oracle.com \
    --cc=davem@davemloft.net \
    --cc=dsahern@kernel.org \
    --cc=ebiederm@xmission.com \
    --cc=ebiggers@kernel.org \
    --cc=edumazet@google.com \
    --cc=fruggeri@arista.com \
    --cc=gilligan@arista.com \
    --cc=herbert@gondor.apana.org.au \
    --cc=kuba@kernel.org \
    --cc=linux-crypto@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=luto@amacapital.net \
    --cc=netdev@vger.kernel.org \
    --cc=noureddine@arista.com \
    --cc=pabeni@redhat.com \
    --cc=shuah@kernel.org \
    --cc=yoshfuji@linux-ipv6.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.