From c26fbec462c481c42ac1d4e57f177219256e9bb4 Mon Sep 17 00:00:00 2001
From: Taylor R Campbell <riastradh@NetBSD.org>
Date: Sat, 6 Aug 2022 13:36:13 +0000
Subject: [PATCH 2/5] cgdconfig(8): New -T operation prints all generated keys
 in cgd.conf.

For testing purposes.
---
 sbin/cgdconfig/cgdconfig.8   |  8 ++++++
 sbin/cgdconfig/cgdconfig.c   | 56 ++++++++++++++++++++++++++++++++----
 tests/dev/cgd/t_cgdconfig.sh | 35 ++++++++++++++++++++++
 3 files changed, 93 insertions(+), 6 deletions(-)

diff --git a/sbin/cgdconfig/cgdconfig.8 b/sbin/cgdconfig/cgdconfig.8
index f0d1a1332a00..18732cf02056 100644
--- a/sbin/cgdconfig/cgdconfig.8
+++ b/sbin/cgdconfig/cgdconfig.8
@@ -60,6 +60,9 @@
 .Ar alg
 .Op Ar keylen
 .Nm
+.Fl T
+.Op Fl f Ar configfile
+.Nm
 .Fl t
 .Ar paramsfile
 .Nm
@@ -117,6 +120,11 @@ from before
 released in 2010; see
 .Xr cgd 4
 for details.
+.It Fl T
+Generate all keys for all the devices listed in the
+.Nm
+configuration file and print them to standard output encoded in
+base64.
 .It Fl t
 Generate the key and print it to standard output encoded in base64.
 .It Fl k Ar kgmeth
diff --git a/sbin/cgdconfig/cgdconfig.c b/sbin/cgdconfig/cgdconfig.c
index e2f28625b94a..0629cd9c20d4 100644
--- a/sbin/cgdconfig/cgdconfig.c
+++ b/sbin/cgdconfig/cgdconfig.c
@@ -90,6 +90,7 @@ enum action {
 	 ACTION_CONFIGSTDIN,		/* configure, key from stdin */
 	 ACTION_LIST,			/* list configured devices */
 	 ACTION_PRINTKEY,		/* print key to stdout */
+	 ACTION_PRINTALLKEYS,		/* print all keys to stdout */
 };
 
 /* if nflag is set, do not configure/unconfigure the cgd's */
@@ -112,6 +113,8 @@ static int	unconfigure(int, char **, struct params *, int);
 static int	do_all(const char *, int, char **,
 		       int (*)(int, char **, struct params *, int));
 static int	do_list(int, char **);
+static int	printkey(const char *);
+static int	printkey1(int, char **, struct params *, int);
 static int	do_printkey(int, char **);
 
 #define CONFIG_FLAGS_FROMALL	1	/* called from configure_all() */
@@ -163,6 +166,7 @@ usage(void)
 	(void)fprintf(stderr, "       %s -s [-nv] [-i ivmeth] cgd dev alg "
 	    "[keylen]\n", getprogname());
 	(void)fprintf(stderr, "       %s -t paramsfile\n", getprogname());
+	(void)fprintf(stderr, "       %s -T [-f configfile]\n", getprogname());
 	(void)fprintf(stderr, "       %s -U [-nv] [-f configfile]\n",
 	    getprogname());
 	(void)fprintf(stderr, "       %s -u [-nv] cgd\n", getprogname());
@@ -217,7 +221,7 @@ main(int argc, char **argv)
 	p = params_new();
 	kg = NULL;
 
-	while ((ch = getopt(argc, argv, "CGUV:b:ef:gi:k:lno:sptuv")) != -1)
+	while ((ch = getopt(argc, argv, "CGTUV:b:ef:gi:k:lno:sptuv")) != -1)
 		switch (ch) {
 		case 'C':
 			set_action(&action, ACTION_CONFIGALL);
@@ -225,6 +229,9 @@ main(int argc, char **argv)
 		case 'G':
 			set_action(&action, ACTION_GENERATE_CONVERT);
 			break;
+		case 'T':
+			set_action(&action, ACTION_PRINTALLKEYS);
+			break;
 		case 'U':
 			set_action(&action, ACTION_UNCONFIGALL);
 			break;
@@ -331,6 +338,8 @@ main(int argc, char **argv)
 		return do_list(argc, argv);
 	case ACTION_PRINTKEY:
 		return do_printkey(argc, argv);
+	case ACTION_PRINTALLKEYS:
+		return do_all(cfile, argc, argv, printkey1);
 	default:
 		errx(EXIT_FAILURE, "undefined action");
 		/* NOTREACHED */
@@ -1352,7 +1361,7 @@ do_list(int argc, char **argv)
 }
 
 static int
-do_printkey(int argc, char **argv)
+printkey(const char *paramsfile)
 {
 	struct params *p;
 	const uint8_t *raw;
@@ -1361,13 +1370,11 @@ do_printkey(int argc, char **argv)
 	char *b64;
 	int ret;
 
-	if (argc != 1)
-		usage();
-	p = params_cget(argv[0]);
+	p = params_cget(paramsfile);
 	if (p == NULL)
 		return -1;
 	if (!params_verify(p)) {
-		warnx("invalid parameters file \"%s\"", argv[0]);
+		warnx("invalid parameters file \"%s\"", paramsfile);
 		return -1;
 	}
 	p->key = getkey("key", p->keygen, p->keylen);
@@ -1390,6 +1397,43 @@ do_printkey(int argc, char **argv)
 	return ferror(stdout);
 }
 
+static int
+printkey1(int argc, char **argv, struct params *inparams, int flags)
+{
+	char devicename[PATH_MAX], paramsfilebuf[PATH_MAX];
+	const char *dev, *paramsfile;
+
+	assert(flags == CONFIG_FLAGS_FROMALL);
+
+	if (argc < 2 || argc > 3)
+		return -1;
+
+	dev = getfsspecname(devicename, sizeof(devicename), argv[1]);
+	if (dev == NULL) {
+		warnx("getfsspecname failed: %s", devicename);
+		return -1;
+	}
+
+	if (argc == 2) {
+		strlcpy(paramsfilebuf, dev, sizeof(paramsfilebuf));
+		paramsfile = basename(paramsfilebuf);
+	} else {
+		paramsfile = argv[2];
+	}
+
+	printf("%s: ", dev);
+	return printkey(paramsfile);
+}
+
+static int
+do_printkey(int argc, char **argv)
+{
+
+	if (argc != 1)
+		usage();
+	return printkey(argv[0]);
+}
+
 static void
 eliminate_cores(void)
 {
diff --git a/tests/dev/cgd/t_cgdconfig.sh b/tests/dev/cgd/t_cgdconfig.sh
index 7a4edc21ce1a..d7cccb2db08d 100644
--- a/tests/dev/cgd/t_cgdconfig.sh
+++ b/tests/dev/cgd/t_cgdconfig.sh
@@ -44,6 +44,40 @@ EOF
 	    cgdconfig -t params
 }
 
+atf_test_case storedkeys
+storedkeys_head()
+{
+	atf_set descr "Test multiple stored keys with cgd.conf"
+}
+storedkeys_body()
+{
+	cat <<EOF >wd0e
+algorithm adiantum;
+iv-method encblkno1;
+keylength 256;
+verify_method none;
+keygen storedkey key AAABAJtnmp3XZspMBAFpCYnB8Hekn0 \
+                     gj5cDVngslfGLSqwcy;
+EOF
+	cat <<EOF >ld1e
+algorithm adiantum;
+iv-method encblkno1;
+keylength 256;
+verify_method none;
+keygen storedkey key AAABAK1pbgIayXftX0RQ3AaMK4YEd/ \
+                     fowKwQbENxpu3o1k9m;
+EOF
+	cat <<EOF >cgd.conf
+cgd0	/dev/wd0e	wd0e
+cgd1	/dev/ld1e	ld1e
+EOF
+	cat <<EOF >expected
+/dev/wd0e: m2eanddmykwEAWkJicHwd6SfSCPlwNWeCyV8YtKrBzI=
+/dev/ld1e: rWluAhrJd+1fRFDcBowrhgR39+jArBBsQ3Gm7ejWT2Y=
+EOF
+	atf_check -o file:expected cgdconfig -T -f cgd.conf
+}
+
 atf_test_case storedkey2a
 storedkey2a_head()
 {
@@ -91,4 +125,5 @@ atf_init_test_cases()
 	atf_add_test_case storedkey
 	atf_add_test_case storedkey2a
 	atf_add_test_case storedkey2b
+	atf_add_test_case storedkeys
 }