xref: /netbsd-src/sbin/cgdconfig/cgdconfig.c (revision c162bcc0edf759ef7f5c47f387dc4ea5a2f0013a)
1 /* $NetBSD: cgdconfig.c,v 1.63 2024/05/12 18:02:16 christos Exp $ */
2 
3 /*-
4  * Copyright (c) 2002, 2003 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Roland C. Dowdeswell.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include <sys/cdefs.h>
33 #ifndef lint
34 __COPYRIGHT("@(#) Copyright (c) 2002, 2003\
35  The NetBSD Foundation, Inc.  All rights reserved.");
36 __RCSID("$NetBSD: cgdconfig.c,v 1.63 2024/05/12 18:02:16 christos Exp $");
37 #endif
38 
39 #ifdef HAVE_ARGON2
40 #include <argon2.h>
41 #endif
42 #include <assert.h>
43 #include <err.h>
44 #include <errno.h>
45 #include <fcntl.h>
46 #include <libgen.h>
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <string.h>
50 #include <unistd.h>
51 #include <util.h>
52 #include <paths.h>
53 #include <dirent.h>
54 
55 /* base64 gunk */
56 #include <netinet/in.h>
57 #include <arpa/nameser.h>
58 #include <resolv.h>
59 
60 #include <sys/ioctl.h>
61 #include <sys/stat.h>
62 #include <sys/bootblock.h>
63 #include <sys/disklabel.h>
64 #include <sys/disklabel_gpt.h>
65 #include <sys/mman.h>
66 #include <sys/param.h>
67 #include <sys/resource.h>
68 #include <sys/statvfs.h>
69 #include <sys/bitops.h>
70 #include <sys/queue.h>
71 
72 #include <dev/cgdvar.h>
73 
74 #include <ufs/ffs/fs.h>
75 
76 #ifdef HAVE_ZFS
77 #include <sys/vdev_impl.h>
78 #include <sha2.h>
79 #endif
80 
81 #include "params.h"
82 #include "pkcs5_pbkdf2.h"
83 #include "utils.h"
84 #include "cgdconfig.h"
85 #include "prog_ops.h"
86 #include "hkdf_hmac_sha256.h"
87 
88 #define CGDCONFIG_CFILE		CGDCONFIG_DIR "/cgd.conf"
89 
90 enum action {
91 	 ACTION_DEFAULT,		/* default -> configure */
92 	 ACTION_CONFIGURE,		/* configure, with paramsfile */
93 	 ACTION_UNCONFIGURE,		/* unconfigure */
94 	 ACTION_GENERATE,		/* generate a paramsfile */
95 	 ACTION_GENERATE_CONVERT,	/* generate a ``dup'' paramsfile */
96 	 ACTION_CONFIGALL,		/* configure all from config file */
97 	 ACTION_UNCONFIGALL,		/* unconfigure all from config file */
98 	 ACTION_CONFIGSTDIN,		/* configure, key from stdin */
99 	 ACTION_LIST,			/* list configured devices */
100 	 ACTION_PRINTKEY,		/* print key to stdout */
101 	 ACTION_PRINTALLKEYS,		/* print all keys to stdout */
102 };
103 
104 /* if nflag is set, do not configure/unconfigure the cgd's */
105 
106 static int	nflag = 0;
107 
108 /* if Sflag is set, generate shared keys */
109 
110 static int	Sflag = 0;
111 
112 /* if pflag is set to PFLAG_STDIN read from stdin rather than getpass(3) */
113 
114 #define	PFLAG_GETPASS		0x01
115 #define	PFLAG_GETPASS_ECHO	0x02
116 #define	PFLAG_GETPASS_MASK	0x03
117 #define	PFLAG_STDIN		0x04
118 static int	pflag = PFLAG_GETPASS;
119 
120 /*
121  * When configuring all cgds, save a cache of shared keys for key
122  * derivation.  If the _first_ verification with a shared key fails, we
123  * chuck it and start over; if _subsequent_ verifications fail, we
124  * assume the disk is wrong and give up on it immediately.
125  */
126 
127 struct sharedkey {
128 	int			 alg;
129 	string_t		*id;
130 	bits_t			*key;
131 	LIST_ENTRY(sharedkey)	 list;
132 	SLIST_ENTRY(sharedkey)	 used;
133 	int			 verified;
134 };
135 static LIST_HEAD(, sharedkey) sharedkeys;
136 SLIST_HEAD(sharedkeyhits, sharedkey);
137 
138 static int	configure(int, char **, struct params *, int);
139 static int	configure_stdin(struct params *, int argc, char **);
140 static int	generate(struct params *, int, char **, const char *,
141 		    const char *);
142 static int	generate_convert(struct params *, int, char **, const char *,
143 		    const char *);
144 static int	unconfigure(int, char **, struct params *, int);
145 static int	do_all(const char *, int, char **,
146 		       int (*)(int, char **, struct params *, int));
147 static int	do_list(int, char **);
148 static int	printkey(const char *, const char *, const char *, ...)
149 		    __printflike(3,4);
150 static int	printkey1(int, char **, struct params *, int);
151 static int	do_printkey(int, char **);
152 
153 #define CONFIG_FLAGS_FROMALL	1	/* called from configure_all() */
154 #define CONFIG_FLAGS_FROMMAIN	2	/* called from main() */
155 
156 static int	 configure_params(int, const char *, const char *,
157 				  struct params *);
158 static void	 eliminate_cores(void);
159 static bits_t	*getkey(const char *, struct keygen *, size_t,
160 		     struct sharedkeyhits *);
161 static bits_t	*getkey_storedkey(const char *, struct keygen *, size_t);
162 static bits_t	*getkey_randomkey(const char *, struct keygen *, size_t, int);
163 #ifdef HAVE_ARGON2
164 static bits_t	*getkey_argon2id(const char *, struct keygen *, size_t);
165 #endif
166 static bits_t	*getkey_pkcs5_pbkdf2(const char *, struct keygen *, size_t,
167 				     int);
168 static bits_t	*getkey_shell_cmd(const char *, struct keygen *, size_t);
169 static char	*maybe_getpass(char *);
170 static int	 opendisk_werror(const char *, char *, size_t);
171 static int	 unconfigure_fd(int);
172 static int	 verify(struct params *, int);
173 static int	 verify_disklabel(int);
174 static int	 verify_ffs(int);
175 static int	 verify_reenter(struct params *);
176 static int	 verify_mbr(int);
177 static int	 verify_gpt(int);
178 #ifdef HAVE_ZFS
179 static int	 verify_zfs(int);
180 #endif
181 
182 __dead static void	 usage(void);
183 
184 /* Verbose Framework */
185 static unsigned	verbose = 0;
186 
187 #define VERBOSE(x,y)	if (verbose >= x) y
188 #define VPRINTF(x,y)	if (verbose >= x) (void)printf y
189 
190 static void
usage(void)191 usage(void)
192 {
193 
194 	(void)fprintf(stderr, "usage: %s [-enpv] [-V vmeth] cgd dev "
195 	    "[paramsfile]\n", getprogname());
196 	(void)fprintf(stderr, "       %s -C [-enpv] [-f configfile]\n",
197 	    getprogname());
198 	(void)fprintf(stderr, "       %s -G [-enpSv] [-i ivmeth] [-k kgmeth] "
199 	    "[-P paramsfile] [-o outfile] paramsfile\n", getprogname());
200 	(void)fprintf(stderr, "       %s -g [-Sv] [-i ivmeth] [-k kgmeth] "
201 	    "[-P paramsfile] [-o outfile] alg [keylen]\n", getprogname());
202 	(void)fprintf(stderr, "       %s -l [-v[v]] [cgd]\n", getprogname());
203 	(void)fprintf(stderr, "       %s -s [-nv] [-i ivmeth] cgd dev alg "
204 	    "[keylen]\n", getprogname());
205 	(void)fprintf(stderr, "       %s -t paramsfile\n", getprogname());
206 	(void)fprintf(stderr, "       %s -T [-f configfile]\n", getprogname());
207 	(void)fprintf(stderr, "       %s -U [-nv] [-f configfile]\n",
208 	    getprogname());
209 	(void)fprintf(stderr, "       %s -u [-nv] cgd\n", getprogname());
210 	exit(EXIT_FAILURE);
211 }
212 
213 static int
parse_size_t(const char * s,size_t * l)214 parse_size_t(const char *s, size_t *l)
215 {
216 	char *endptr;
217 	long v;
218 
219 	errno = 0;
220 	v = strtol(s, &endptr, 10);
221 	if ((v == LONG_MIN || v == LONG_MAX) && errno)
222 		return -1;
223 	if (v < INT_MIN || v > INT_MAX) {
224 		errno = ERANGE;
225 		return -1;
226 	}
227 	if (endptr == s) {
228 		errno = EINVAL;
229 		return -1;
230 	}
231 	*l = (size_t)v;
232 	return 0;
233 }
234 
235 static void
set_action(enum action * action,enum action value)236 set_action(enum action *action, enum action value)
237 {
238 	if (*action != ACTION_DEFAULT)
239 		usage();
240 	*action = value;
241 }
242 
243 int
main(int argc,char ** argv)244 main(int argc, char **argv)
245 {
246 	struct params *p;
247 	struct params *tp;
248 	struct keygen *kg;
249 	enum action action = ACTION_DEFAULT;
250 	int	ch;
251 	const char	*cfile = NULL;
252 	const char	*outfile = NULL;
253 	const char	*Pfile = NULL;
254 
255 	setprogname(*argv);
256 	if (hkdf_hmac_sha256_selftest())
257 		err(EXIT_FAILURE, "Crypto self-test failed");
258 	eliminate_cores();
259 	if (mlockall(MCL_FUTURE))
260 		err(EXIT_FAILURE, "Can't lock memory");
261 	p = params_new();
262 	kg = NULL;
263 
264 	while ((ch = getopt(argc, argv, "CGP:STUV:b:ef:gi:k:lno:sptuv")) != -1)
265 		switch (ch) {
266 		case 'C':
267 			set_action(&action, ACTION_CONFIGALL);
268 			break;
269 		case 'G':
270 			set_action(&action, ACTION_GENERATE_CONVERT);
271 			break;
272 		case 'P':
273 			if (Pfile)
274 				usage();
275 			Pfile = estrdup(optarg);
276 			break;
277 		case 'S':
278 			Sflag = 1;
279 			break;
280 		case 'T':
281 			set_action(&action, ACTION_PRINTALLKEYS);
282 			break;
283 		case 'U':
284 			set_action(&action, ACTION_UNCONFIGALL);
285 			break;
286 		case 'V':
287 			tp = params_verify_method(string_fromcharstar(optarg));
288 			if (!tp)
289 				usage();
290 			p = params_combine(p, tp);
291 			break;
292 		case 'b':
293 			{
294 				size_t size;
295 
296 				if (parse_size_t(optarg, &size) == -1)
297 					usage();
298 				tp = params_bsize(size);
299 				if (!tp)
300 					usage();
301 				p = params_combine(p, tp);
302 			}
303 			break;
304 		case 'e':
305 			pflag = PFLAG_GETPASS_ECHO;
306 			break;
307 		case 'f':
308 			if (cfile)
309 				usage();
310 			cfile = estrdup(optarg);
311 			break;
312 		case 'g':
313 			set_action(&action, ACTION_GENERATE);
314 			break;
315 		case 'i':
316 			tp = params_ivmeth(string_fromcharstar(optarg));
317 			p = params_combine(p, tp);
318 			break;
319 		case 'k':
320 			kg = keygen_method(string_fromcharstar(optarg));
321 			if (!kg)
322 				usage();
323 			keygen_addlist(&p->keygen, kg);
324 			break;
325 		case 'l':
326 			set_action(&action, ACTION_LIST);
327 			break;
328 		case 'n':
329 			nflag = 1;
330 			break;
331 		case 'o':
332 			if (outfile)
333 				usage();
334 			outfile = estrdup(optarg);
335 			break;
336 		case 'p':
337 			pflag = PFLAG_STDIN;
338 			break;
339 		case 's':
340 			set_action(&action, ACTION_CONFIGSTDIN);
341 			break;
342 		case 't':
343 			set_action(&action, ACTION_PRINTKEY);
344 			break;
345 		case 'u':
346 			set_action(&action, ACTION_UNCONFIGURE);
347 			break;
348 		case 'v':
349 			verbose++;
350 			break;
351 		default:
352 			usage();
353 			/* NOTREACHED */
354 		}
355 
356 	argc -= optind;
357 	argv += optind;
358 
359 	if (!outfile)
360 		outfile = "";
361 	if (!cfile)
362 		cfile = "";
363 
364 	if (prog_init && prog_init() == -1)
365 		err(1, "init failed");
366 
367 	/* validate the consistency of the arguments */
368 	if (Pfile != NULL &&
369 	    action != ACTION_GENERATE &&
370 	    action != ACTION_GENERATE_CONVERT) {
371 		warnx("-P is only for use with -g/-G action");
372 		usage();
373 	}
374 	if (Pfile != NULL && !Sflag) {
375 		warnx("-P only makes sense with -S flag");
376 	}
377 	if (Sflag &&
378 	    action != ACTION_GENERATE &&
379 	    action != ACTION_GENERATE_CONVERT) {
380 		warnx("-S is only for use with -g/-G action");
381 		usage();
382 	}
383 
384 	switch (action) {
385 	case ACTION_DEFAULT:	/* ACTION_CONFIGURE is the default */
386 	case ACTION_CONFIGURE:
387 		return configure(argc, argv, p, CONFIG_FLAGS_FROMMAIN);
388 	case ACTION_UNCONFIGURE:
389 		return unconfigure(argc, argv, NULL, CONFIG_FLAGS_FROMMAIN);
390 	case ACTION_GENERATE:
391 		return generate(p, argc, argv, outfile, Pfile);
392 	case ACTION_GENERATE_CONVERT:
393 		return generate_convert(p, argc, argv, outfile, Pfile);
394 	case ACTION_CONFIGALL:
395 		return do_all(cfile, argc, argv, configure);
396 	case ACTION_UNCONFIGALL:
397 		return do_all(cfile, argc, argv, unconfigure);
398 	case ACTION_CONFIGSTDIN:
399 		return configure_stdin(p, argc, argv);
400 	case ACTION_LIST:
401 		return do_list(argc, argv);
402 	case ACTION_PRINTKEY:
403 		return do_printkey(argc, argv);
404 	case ACTION_PRINTALLKEYS:
405 		return do_all(cfile, argc, argv, printkey1);
406 	default:
407 		errx(EXIT_FAILURE, "undefined action");
408 		/* NOTREACHED */
409 	}
410 }
411 
412 static bits_t *
getsubkey_hkdf_hmac_sha256(bits_t * key,bits_t * info,size_t subkeylen)413 getsubkey_hkdf_hmac_sha256(bits_t *key, bits_t *info, size_t subkeylen)
414 {
415 	bits_t		*ret = NULL;
416 	uint8_t		*tmp;
417 
418 	tmp = emalloc(BITS2BYTES(subkeylen));
419 	if (hkdf_hmac_sha256(tmp, BITS2BYTES(subkeylen),
420 		bits_getbuf(key), BITS2BYTES(bits_len(key)),
421 		bits_getbuf(info), BITS2BYTES(bits_len(info)))) {
422 		warnx("failed to derive HKDF-HMAC-SHA256 subkey");
423 		goto out;
424 	}
425 
426 	ret = bits_new(tmp, subkeylen);
427 
428 out:	free(tmp);
429 	return ret;
430 }
431 
432 static bits_t *
getsubkey(int alg,bits_t * key,bits_t * info,size_t subkeylen)433 getsubkey(int alg, bits_t *key, bits_t *info, size_t subkeylen)
434 {
435 
436 	switch (alg) {
437 	case SHARED_ALG_HKDF_HMAC_SHA256:
438 		return getsubkey_hkdf_hmac_sha256(key, info, subkeylen);
439 	default:
440 		warnx("unrecognised shared key derivation method %d", alg);
441 		return NULL;
442 	}
443 }
444 
445 static bits_t *
getkey(const char * dev,struct keygen * kg,size_t len0,struct sharedkeyhits * skh)446 getkey(const char *dev, struct keygen *kg, size_t len0,
447     struct sharedkeyhits *skh)
448 {
449 	bits_t	*ret = NULL;
450 	bits_t	*tmp;
451 
452 	VPRINTF(3, ("getkey(\"%s\", %p, %zu) called\n", dev, kg, len0));
453 	for (; kg; kg=kg->next) {
454 		struct sharedkey *sk = NULL;
455 		size_t len = len0;
456 
457 		/*
458 		 * If shared, determine the shared key's length and
459 		 * probe the cache of shared keys.
460 		 */
461 		if (kg->kg_sharedid) {
462 			const char *id = string_tocharstar(kg->kg_sharedid);
463 
464 			len = kg->kg_sharedlen;
465 			LIST_FOREACH(sk, &sharedkeys, list) {
466 				if (kg->kg_sharedalg == sk->alg &&
467 				    kg->kg_sharedlen == bits_len(sk->key) &&
468 				    strcmp(id, string_tocharstar(sk->id)) == 0)
469 					break;
470 			}
471 			if (sk) {
472 				tmp = sk->key;
473 				goto derive;
474 			}
475 		}
476 
477 		switch (kg->kg_method) {
478 		case KEYGEN_STOREDKEY:
479 			tmp = getkey_storedkey(dev, kg, len);
480 			break;
481 		case KEYGEN_RANDOMKEY:
482 			tmp = getkey_randomkey(dev, kg, len, 1);
483 			break;
484 		case KEYGEN_URANDOMKEY:
485 			tmp = getkey_randomkey(dev, kg, len, 0);
486 			break;
487 #ifdef HAVE_ARGON2
488 		case KEYGEN_ARGON2ID:
489 			tmp = getkey_argon2id(dev, kg, len);
490 			break;
491 #endif
492 		case KEYGEN_PKCS5_PBKDF2_SHA1:
493 			tmp = getkey_pkcs5_pbkdf2(dev, kg, len, 0);
494 			break;
495 		/* provide backwards compatibility for old config files */
496 		case KEYGEN_PKCS5_PBKDF2_OLD:
497 			tmp = getkey_pkcs5_pbkdf2(dev, kg, len, 1);
498 			break;
499 		case KEYGEN_SHELL_CMD:
500 			tmp = getkey_shell_cmd(dev, kg, len);
501 			break;
502 		default:
503 			warnx("unrecognised keygen method %d in getkey()",
504 			    kg->kg_method);
505 			if (ret)
506 				bits_free(ret);
507 			return NULL;
508 		}
509 
510 		/*
511 		 * If shared, cache the key.
512 		 */
513 		if (kg->kg_sharedid) {
514 			assert(sk == NULL);
515 			sk = ecalloc(1, sizeof(*sk));
516 			sk->alg = kg->kg_sharedalg;
517 			sk->id = string_dup(kg->kg_sharedid);
518 			sk->key = tmp;
519 			LIST_INSERT_HEAD(&sharedkeys, sk, list);
520 			sk->verified = 0;
521 		}
522 
523 derive:		if (kg->kg_sharedid) {
524 			assert(sk != NULL);
525 			/*
526 			 * tmp holds the master key, owned by the
527 			 * struct sharedkey record; replace it by the
528 			 * derived subkey.
529 			 */
530 			tmp = getsubkey(kg->kg_sharedalg, tmp,
531 			    kg->kg_sharedinfo, len0);
532 			if (tmp == NULL) {
533 				if (ret)
534 					bits_free(ret);
535 				return NULL;
536 			}
537 			if (skh)
538 				SLIST_INSERT_HEAD(skh, sk, used);
539 		}
540 		if (ret)
541 			ret = bits_xor_d(tmp, ret);
542 		else
543 			ret = tmp;
544 	}
545 
546 	return ret;
547 }
548 
549 /*ARGSUSED*/
550 static bits_t *
getkey_storedkey(const char * target,struct keygen * kg,size_t keylen)551 getkey_storedkey(const char *target, struct keygen *kg, size_t keylen)
552 {
553 	return bits_dup(kg->kg_key);
554 }
555 
556 /*ARGSUSED*/
557 static bits_t *
getkey_randomkey(const char * target,struct keygen * kg,size_t keylen,int hard)558 getkey_randomkey(const char *target, struct keygen *kg, size_t keylen, int hard)
559 {
560 	return bits_getrandombits(keylen, hard);
561 }
562 
563 static char *
maybe_getpass(char * prompt)564 maybe_getpass(char *prompt)
565 {
566 	char	 buf[1024];
567 	char	*p = NULL;
568 	char	*tmp, *pass;
569 
570 	switch (pflag) {
571 	case PFLAG_GETPASS:
572 		p = getpass_r(prompt, buf, sizeof(buf));
573 		break;
574 
575 	case PFLAG_GETPASS_ECHO:
576 		p = getpassfd(prompt, buf, sizeof(buf), NULL,
577 		    GETPASS_ECHO|GETPASS_ECHO_NL|GETPASS_NEED_TTY, 0);
578 		break;
579 
580 	case PFLAG_STDIN:
581 		p = fgets(buf, sizeof(buf), stdin);
582 		if (p) {
583 			tmp = strchr(p, '\n');
584 			if (tmp)
585 				*tmp = '\0';
586 		}
587 		break;
588 
589 	default:
590 		errx(EXIT_FAILURE, "pflag set inappropriately?");
591 	}
592 
593 	if (!p)
594 		err(EXIT_FAILURE, "failed to read passphrase");
595 
596 	pass = estrdup(p);
597 	explicit_memset(buf, 0, sizeof(buf));
598 
599 	return pass;
600 }
601 
602 /*ARGSUSED*/
603 /*
604  * XXX take, and pass through, a compat flag that indicates whether we
605  * provide backwards compatibility with a previous bug.  The previous
606  * behaviour is indicated by the keygen method pkcs5_pbkdf2, and a
607  * non-zero compat flag. The new default, and correct keygen method is
608  * called pcks5_pbkdf2/sha1.  When the old method is removed, so will
609  * be the compat argument.
610  */
611 static bits_t *
getkey_pkcs5_pbkdf2(const char * target,struct keygen * kg,size_t keylen,int compat)612 getkey_pkcs5_pbkdf2(const char *target, struct keygen *kg, size_t keylen,
613     int compat)
614 {
615 	bits_t		*ret;
616 	char		*passp;
617 	char		 buf[1024];
618 	u_int8_t	*tmp;
619 
620 	snprintf(buf, sizeof(buf), "%s's passphrase%s:", target,
621 	    pflag & PFLAG_GETPASS_ECHO ? " (echo)" : "");
622 	passp = maybe_getpass(buf);
623 	if (pkcs5_pbkdf2(&tmp, BITS2BYTES(keylen), (uint8_t *)passp,
624 	    strlen(passp),
625 	    bits_getbuf(kg->kg_salt), BITS2BYTES(bits_len(kg->kg_salt)),
626 	    kg->kg_iterations, compat)) {
627 		warnx("failed to generate PKCS#5 PBKDF2 key");
628 		return NULL;
629 	}
630 
631 	ret = bits_new(tmp, keylen);
632 	kg->kg_key = bits_dup(ret);
633 	explicit_memset(passp, 0, strlen(passp));
634 	free(passp);
635 	free(tmp);
636 	return ret;
637 }
638 
639 #ifdef HAVE_ARGON2
640 static bits_t *
getkey_argon2id(const char * target,struct keygen * kg,size_t keylen)641 getkey_argon2id(const char *target, struct keygen *kg, size_t keylen)
642 {
643 	bits_t *ret;
644 	char *passp;
645 	char buf[1024];
646 	uint8_t	raw[256];
647 	int error;
648 
649 	snprintf(buf, sizeof(buf), "%s's passphrase%s:", target,
650 	    pflag & PFLAG_GETPASS_ECHO ? " (echo)" : "");
651 	passp = maybe_getpass(buf);
652 	if ((error = argon2_hash(kg->kg_iterations, kg->kg_memory,
653 	    kg->kg_parallelism,
654 	    passp, strlen(passp),
655 	    bits_getbuf(kg->kg_salt),
656 	    BITS2BYTES(bits_len(kg->kg_salt)),
657 	    raw, sizeof(raw),
658 	    NULL, 0,
659 	    Argon2_id, kg->kg_version)) != ARGON2_OK) {
660 		warnx("failed to generate Argon2id key, error code %d", error);
661 		return NULL;
662 	}
663 
664 	ret = bits_new(raw, keylen);
665 	kg->kg_key = bits_dup(ret);
666 	explicit_memset(passp, 0, strlen(passp));
667 	explicit_memset(raw, 0, sizeof(raw));
668 	free(passp);
669 	return ret;
670 }
671 #endif
672 
673 /*ARGSUSED*/
674 static bits_t *
getkey_shell_cmd(const char * target,struct keygen * kg,size_t keylen)675 getkey_shell_cmd(const char *target, struct keygen *kg, size_t keylen)
676 {
677 	FILE	*f;
678 	bits_t	*ret;
679 	int	status;
680 
681 	if ((f = popen(string_tocharstar(kg->kg_cmd), "r")) == NULL)
682 		errx(1, "command failed");
683 	if ((ret = bits_fget(f, keylen)) == NULL)
684 		errx(1, "command output too short");
685 	if ((status = pclose(f)) != 0)
686 		err(1, "command failed with status %d", status);
687 
688 	return ret;
689 }
690 
691 /*ARGSUSED*/
692 static int
unconfigure(int argc,char ** argv,struct params * inparams,int flags)693 unconfigure(int argc, char **argv, struct params *inparams, int flags)
694 {
695 	int	fd;
696 	int	ret;
697 	char	buf[MAXPATHLEN] = "";
698 
699 	/* only complain about additional arguments, if called from main() */
700 	if (flags == CONFIG_FLAGS_FROMMAIN && argc != 1)
701 		usage();
702 
703 	/* if called from do_all(), then ensure that 2 or 3 args exist */
704 	if (flags == CONFIG_FLAGS_FROMALL && (argc < 2 || argc > 3))
705 		return -1;
706 
707 	fd = opendisk1(*argv, O_RDWR, buf, sizeof(buf), 1, prog_open);
708 	if (fd == -1) {
709 		int saved_errno = errno;
710 
711 		warn("can't open cgd \"%s\", \"%s\"", *argv, buf);
712 
713 		/* this isn't fatal with nflag != 0 */
714 		if (!nflag)
715 			return saved_errno;
716 	}
717 
718 	VPRINTF(1, ("%s (%s): clearing\n", *argv, buf));
719 
720 	if (nflag)
721 		return 0;
722 
723 	ret = unconfigure_fd(fd);
724 	(void)prog_close(fd);
725 	return ret;
726 }
727 
728 static int
unconfigure_fd(int fd)729 unconfigure_fd(int fd)
730 {
731 	struct	cgd_ioctl ci;
732 
733 	if (prog_ioctl(fd, CGDIOCCLR, &ci) == -1) {
734 		warn("ioctl");
735 		return -1;
736 	}
737 
738 	return 0;
739 }
740 
741 /*ARGSUSED*/
742 static int
configure(int argc,char ** argv,struct params * inparams,int flags)743 configure(int argc, char **argv, struct params *inparams, int flags)
744 {
745 	struct params	*p;
746 	struct keygen	*kg;
747 	int		 fd;
748 	int		 loop = 0;
749 	int		 ret;
750 	char		 cgdname[PATH_MAX];
751 	char		 devicename[PATH_MAX];
752 	const char	*dev = NULL;	/* XXX: gcc */
753 
754 	if (argc < 2 || argc > 3) {
755 		/* print usage and exit, only if called from main() */
756 		if (flags == CONFIG_FLAGS_FROMMAIN) {
757 			warnx("wrong number of args");
758 			usage();
759 		}
760 		return -1;
761 	}
762 
763 	if ((
764 	  fd = opendisk1(*argv, O_RDWR, cgdname, sizeof(cgdname), 1, prog_open)
765 	    ) != -1) {
766 		struct cgd_user cgu;
767 
768 		cgu.cgu_unit = -1;
769 		if (prog_ioctl(fd, CGDIOCGET, &cgu) != -1 && cgu.cgu_dev != 0) {
770 			warnx("device %s already in use", *argv);
771 			prog_close(fd);
772 			return -1;
773 		}
774 		prog_close(fd);
775 	}
776 
777 	dev = getfsspecname(devicename, sizeof(devicename), argv[1]);
778 	if (dev == NULL) {
779 		warnx("getfsspecname failed: %s", devicename);
780 		return -1;
781 	}
782 
783 	if (argc == 2) {
784 		char pfile[MAXPATHLEN];
785 
786 		/* make string writable for basename */
787 		strlcpy(pfile, dev, sizeof(pfile));
788 		p = params_cget(basename(pfile));
789 	} else
790 		p = params_cget(argv[2]);
791 
792 	if (!p)
793 		return -1;
794 
795 	/*
796 	 * over-ride with command line specifications and fill in default
797 	 * values.
798 	 */
799 
800 	p = params_combine(p, inparams);
801 	ret = params_filldefaults(p);
802 	if (ret) {
803 		params_free(p);
804 		return ret;
805 	}
806 
807 	if (!params_verify(p)) {
808 		warnx("params invalid");
809 		return -1;
810 	}
811 
812 	/*
813 	 * loop over configuring the disk and checking to see if it
814 	 * verifies properly.  We open and close the disk device each
815 	 * time, because if the user passes us the block device we
816 	 * need to flush the buffer cache.
817 	 *
818 	 * We only loop if one of the verification methods prompts for
819 	 * a password.
820 	 */
821 
822 	for (kg = p->keygen;
823 	    (pflag & PFLAG_GETPASS_MASK) && kg;
824 	    kg = kg->next)
825 		if (kg->kg_method == KEYGEN_ARGON2ID ||
826 		    kg->kg_method == KEYGEN_PKCS5_PBKDF2_SHA1 ||
827 		    kg->kg_method == KEYGEN_PKCS5_PBKDF2_OLD) {
828 			loop = 1;
829 			break;
830 		}
831 
832 	for (;;) {
833 		struct sharedkeyhits skh;
834 		struct sharedkey *sk, *sk1;
835 		int all_verified;
836 
837 		SLIST_INIT(&skh);
838 
839 		fd = opendisk_werror(argv[0], cgdname, sizeof(cgdname));
840 		if (fd == -1)
841 			return -1;
842 
843 		if (p->key)
844 			bits_free(p->key);
845 
846 		p->key = getkey(argv[1], p->keygen, p->keylen, &skh);
847 		if (!p->key)
848 			goto bail_err;
849 
850 		ret = configure_params(fd, cgdname, dev, p);
851 		if (ret)
852 			goto bail_err;
853 
854 		ret = verify(p, fd);
855 		if (ret == -1) {
856 			(void)unconfigure_fd(fd);
857 			goto bail_err;
858 		}
859 		if (ret == 0) {		/* success */
860 			SLIST_FOREACH(sk, &skh, used)
861 				sk->verified = 1;
862 			break;
863 		}
864 
865 		(void)unconfigure_fd(fd);
866 		(void)prog_close(fd);
867 
868 		/*
869 		 * For shared keys: If the shared keys were all
870 		 * verified already, assume something is wrong with the
871 		 * disk and give up.  If not, flush the cache of the
872 		 * ones that have not been verified in case we can try
873 		 * again with passphrase re-entry.
874 		 */
875 		if (!SLIST_EMPTY(&skh)) {
876 			all_verified = 1;
877 			SLIST_FOREACH_SAFE(sk, &skh, used, sk1) {
878 				all_verified &= sk->verified;
879 				if (!sk->verified) {
880 					LIST_REMOVE(sk, list);
881 					free(sk);
882 				}
883 			}
884 			if (all_verified)
885 				loop = 0;
886 		}
887 
888 		if (!loop) {
889 			warnx("verification failed permanently");
890 			goto bail_err;
891 		}
892 
893 		warnx("verification failed, please reenter passphrase");
894 	}
895 
896 	params_free(p);
897 	(void)prog_close(fd);
898 	return 0;
899 
900  bail_err:;
901 	params_free(p);
902 	(void)prog_close(fd);
903 	return -1;
904 }
905 
906 static int
configure_stdin(struct params * p,int argc,char ** argv)907 configure_stdin(struct params *p, int argc, char **argv)
908 {
909 	int		 fd;
910 	int		 ret;
911 	char		 cgdname[PATH_MAX];
912 	char		 devicename[PATH_MAX];
913 	const char	*dev;
914 
915 	if (argc < 3 || argc > 4)
916 		usage();
917 
918 	dev = getfsspecname(devicename, sizeof(devicename), argv[1]);
919 	if (dev == NULL) {
920 		warnx("getfsspecname failed: %s", devicename);
921 		return -1;
922 	}
923 
924 	p->algorithm = string_fromcharstar(argv[2]);
925 	if (argc > 3) {
926 		size_t keylen;
927 
928 		if (parse_size_t(argv[3], &keylen) == -1) {
929 			warn("failed to parse key length");
930 			return -1;
931 		}
932 		p->keylen = keylen;
933 	}
934 
935 	ret = params_filldefaults(p);
936 	if (ret)
937 		return ret;
938 
939 	fd = opendisk_werror(argv[0], cgdname, sizeof(cgdname));
940 	if (fd == -1)
941 		return -1;
942 
943 	p->key = bits_fget(stdin, p->keylen);
944 	if (!p->key) {
945 		warnx("failed to read key from stdin");
946 		return -1;
947 	}
948 
949 	return configure_params(fd, cgdname, dev, p);
950 }
951 
952 static int
opendisk_werror(const char * cgd,char * buf,size_t buflen)953 opendisk_werror(const char *cgd, char *buf, size_t buflen)
954 {
955 	int	fd;
956 
957 	VPRINTF(3, ("opendisk_werror(%s, %s, %zu) called.\n", cgd,buf,buflen));
958 
959 	/* sanity */
960 	if (!cgd || !buf)
961 		return -1;
962 
963 	if (nflag) {
964 		if (strlcpy(buf, cgd, buflen) >= buflen)
965 			return -1;
966 		return 0;
967 	}
968 
969 	fd = opendisk1(cgd, O_RDWR, buf, buflen, 0, prog_open);
970 	if (fd == -1)
971 		warnx("can't open cgd \"%s\", \"%s\"", cgd, buf);
972 
973 	return fd;
974 }
975 
976 static int
configure_params(int fd,const char * cgd,const char * dev,struct params * p)977 configure_params(int fd, const char *cgd, const char *dev, struct params *p)
978 {
979 	struct cgd_ioctl ci;
980 
981 	/* sanity */
982 	if (!cgd || !dev)
983 		return -1;
984 
985 	(void)memset(&ci, 0x0, sizeof(ci));
986 	ci.ci_disk = dev;
987 	ci.ci_alg = string_tocharstar(p->algorithm);
988 	ci.ci_ivmethod = string_tocharstar(p->ivmeth);
989 	ci.ci_key = bits_getbuf(p->key);
990 	ci.ci_keylen = p->keylen;
991 	ci.ci_blocksize = p->bsize;
992 
993 	VPRINTF(1, ("    with alg %s keylen %zu blocksize %zu ivmethod %s\n",
994 	    string_tocharstar(p->algorithm), p->keylen, p->bsize,
995 	    string_tocharstar(p->ivmeth)));
996 	VPRINTF(2, ("key: "));
997 	VERBOSE(2, bits_fprint(stdout, p->key));
998 	VPRINTF(2, ("\n"));
999 
1000 	if (nflag)
1001 		return 0;
1002 
1003 	if (prog_ioctl(fd, CGDIOCSET, &ci) == -1) {
1004 		int saved_errno = errno;
1005 		warn("ioctl");
1006 		return saved_errno;
1007 	}
1008 
1009 	return 0;
1010 }
1011 
1012 /*
1013  * verify returns 0 for success, -1 for unrecoverable error, or 1 for retry.
1014  */
1015 
1016 #define SCANSIZE	8192
1017 
1018 static int
verify(struct params * p,int fd)1019 verify(struct params *p, int fd)
1020 {
1021 
1022 	switch (p->verify_method) {
1023 	case VERIFY_NONE:
1024 		return 0;
1025 	case VERIFY_DISKLABEL:
1026 		return verify_disklabel(fd);
1027 	case VERIFY_FFS:
1028 		return verify_ffs(fd);
1029 	case VERIFY_REENTER:
1030 		return verify_reenter(p);
1031 	case VERIFY_MBR:
1032 		return verify_mbr(fd);
1033 	case VERIFY_GPT:
1034 		return verify_gpt(fd);
1035 #ifdef HAVE_ZFS
1036 	case VERIFY_ZFS:
1037 		return verify_zfs(fd);
1038 #endif
1039 	default:
1040 		warnx("unimplemented verification method");
1041 		return -1;
1042 	}
1043 }
1044 
1045 static int
verify_disklabel(int fd)1046 verify_disklabel(int fd)
1047 {
1048 	struct	disklabel l;
1049 	ssize_t	ret;
1050 	char	buf[SCANSIZE];
1051 
1052 	/*
1053 	 * we simply scan the first few blocks for a disklabel, ignoring
1054 	 * any MBR/filecore sorts of logic.  MSDOS and RiscOS can't read
1055 	 * a cgd, anyway, so it is unlikely that there will be non-native
1056 	 * partition information.
1057 	 */
1058 
1059 	ret = prog_pread(fd, buf, SCANSIZE, 0);
1060 	if (ret < 0) {
1061 		warn("can't read disklabel area");
1062 		return -1;
1063 	}
1064 
1065 	/* now scan for the disklabel */
1066 
1067 	return disklabel_scan(&l, buf, (size_t)ret);
1068 }
1069 
1070 static int
verify_mbr(int fd)1071 verify_mbr(int fd)
1072 {
1073 	struct mbr_sector mbr;
1074 	ssize_t	ret;
1075 	char	buf[SCANSIZE];
1076 
1077 	/*
1078 	 * we read the first blocks to avoid sector size issues and
1079 	 * verify the MBR in the beginning
1080 	 */
1081 
1082 	ret = prog_pread(fd, buf, SCANSIZE, 0);
1083 	if (ret < 0) {
1084 		warn("can't read mbr area");
1085 		return -1;
1086 	}
1087 
1088 	memcpy(&mbr, buf, sizeof(mbr));
1089 	if (le16toh(mbr.mbr_magic) != MBR_MAGIC)
1090 		return 1;
1091 
1092 	return 0;
1093 }
1094 
1095 static uint32_t crc32_tab[] = {
1096 	0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
1097 	0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
1098 	0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
1099 	0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
1100 	0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
1101 	0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
1102 	0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
1103 	0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
1104 	0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
1105 	0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
1106 	0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
1107 	0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
1108 	0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
1109 	0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
1110 	0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
1111 	0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
1112 	0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
1113 	0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
1114 	0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
1115 	0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
1116 	0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
1117 	0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
1118 	0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
1119 	0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
1120 	0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
1121 	0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
1122 	0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
1123 	0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
1124 	0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
1125 	0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
1126 	0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
1127 	0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
1128 	0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
1129 	0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
1130 	0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
1131 	0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
1132 	0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
1133 	0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
1134 	0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
1135 	0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
1136 	0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
1137 	0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
1138 	0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
1139 };
1140 
1141 static uint32_t
crc32(const void * buf,size_t size)1142 crc32(const void *buf, size_t size)
1143 {
1144 	const uint8_t *p;
1145 	uint32_t crc;
1146 
1147 	p = buf;
1148 	crc = ~0U;
1149 
1150 	while (size--)
1151 		crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
1152 
1153 	return crc ^ ~0U;
1154 }
1155 
1156 static int
verify_gpt(int fd)1157 verify_gpt(int fd)
1158 {
1159 	struct	 gpt_hdr hdr;
1160 	ssize_t	 ret;
1161 	char	 buf[SCANSIZE];
1162 	unsigned blksize;
1163 	size_t	 off;
1164 
1165 	/*
1166 	 * we read the first blocks to avoid sector size issues and
1167 	 * verify the GPT header.
1168 	 */
1169 
1170 	ret = prog_pread(fd, buf, SCANSIZE, 0);
1171 	if (ret < 0) {
1172 		warn("can't read gpt area");
1173 		return -1;
1174 	}
1175 
1176 	for (blksize = DEV_BSIZE;
1177              (off = (blksize * GPT_HDR_BLKNO)) <= SCANSIZE - sizeof(hdr);
1178              blksize <<= 1) {
1179 
1180 		memcpy(&hdr, &buf[off], sizeof(hdr));
1181 		if (memcmp(hdr.hdr_sig, GPT_HDR_SIG, sizeof(hdr.hdr_sig)) == 0
1182 		    && le32toh(hdr.hdr_revision) == GPT_HDR_REVISION
1183 		    && le32toh(hdr.hdr_size) == GPT_HDR_SIZE) {
1184 
1185 			hdr.hdr_crc_self = 0;
1186 			if (crc32(&hdr, sizeof(hdr))) {
1187 				return 0;
1188 			}
1189 		}
1190 	}
1191 
1192 	return 1;
1193 }
1194 
1195 #ifdef HAVE_ZFS
1196 
1197 #define ZIO_CHECKSUM_BE(zcp)					\
1198 {								\
1199 	(zcp)->zc_word[0] = BE_64((zcp)->zc_word[0]);		\
1200 	(zcp)->zc_word[1] = BE_64((zcp)->zc_word[1]);		\
1201 	(zcp)->zc_word[2] = BE_64((zcp)->zc_word[2]);		\
1202 	(zcp)->zc_word[3] = BE_64((zcp)->zc_word[3]);		\
1203 }
1204 
1205 static int
verify_zfs(int fd)1206 verify_zfs(int fd)
1207 {
1208 	off_t vdev_size;
1209 	int rv = 1;
1210 
1211 	if (prog_ioctl(fd, DIOCGMEDIASIZE, &vdev_size) == -1) {
1212 		warn("%s: ioctl", __func__);
1213 		return rv;
1214 	}
1215 
1216 	vdev_phys_t *vdev_phys = emalloc(sizeof(*vdev_phys));
1217 	for (size_t i = 0; i < VDEV_LABELS; i++) {
1218 		off_t vdev_phys_off = (i < VDEV_LABELS / 2 ?
1219 		    i * sizeof(vdev_label_t) :
1220 		    vdev_size - (VDEV_LABELS - i) * sizeof(vdev_label_t))
1221 		    + offsetof(vdev_label_t, vl_vdev_phys);
1222 
1223 		ssize_t ret = prog_pread(fd, vdev_phys, sizeof(*vdev_phys),
1224 		    vdev_phys_off);
1225 		if (ret == -1) {
1226 			warn("%s: read failed", __func__);
1227 			goto out;
1228 		}
1229 		if ((size_t)ret < sizeof(*vdev_phys)) {
1230 			warnx("%s: incomplete block", __func__);
1231 			goto out;
1232 		}
1233 
1234 		bool byteswap;
1235 		switch (vdev_phys->vp_zbt.zec_magic) {
1236 		case BSWAP_64(ZEC_MAGIC):
1237 			byteswap = true;
1238 			break;
1239 		case ZEC_MAGIC:
1240 			byteswap = false;
1241 			break;
1242 		default:
1243 			goto out;
1244 		}
1245 
1246 		zio_cksum_t cksum_found = vdev_phys->vp_zbt.zec_cksum;
1247 		if (byteswap) {
1248 			ZIO_CHECKSUM_BSWAP(&cksum_found);
1249 		}
1250 
1251 		ZIO_SET_CHECKSUM(&vdev_phys->vp_zbt.zec_cksum,
1252 		    vdev_phys_off, 0, 0, 0);
1253 		if (byteswap) {
1254 			ZIO_CHECKSUM_BSWAP(&vdev_phys->vp_zbt.zec_cksum);
1255 		}
1256 
1257 		SHA256_CTX ctx;
1258 		zio_cksum_t cksum_real;
1259 
1260 		SHA256Init(&ctx);
1261 		SHA256Update(&ctx, (uint8_t *)vdev_phys, sizeof *vdev_phys);
1262 		SHA256Final(&cksum_real, &ctx);
1263 
1264 		/*
1265 		 * For historical reasons the on-disk sha256 checksums are
1266 		 * always in big endian format.
1267 		 * (see cddl/osnet/dist/uts/common/fs/zfs/sha256.c)
1268 		 */
1269 		ZIO_CHECKSUM_BE(&cksum_real);
1270 
1271 		if (!ZIO_CHECKSUM_EQUAL(cksum_found, cksum_real)) {
1272 			warnx("%s: checksum mismatch on vdev label %zu",
1273 			    __func__, i);
1274 			warnx("%s: found %#jx, %#jx, %#jx, %#jx", __func__,
1275 			    (uintmax_t)cksum_found.zc_word[0],
1276 			    (uintmax_t)cksum_found.zc_word[1],
1277 			    (uintmax_t)cksum_found.zc_word[2],
1278 			    (uintmax_t)cksum_found.zc_word[3]);
1279 			warnx("%s: expected %#jx, %#jx, %#jx, %#jx", __func__,
1280 			    (uintmax_t)cksum_real.zc_word[0],
1281 			    (uintmax_t)cksum_real.zc_word[1],
1282 			    (uintmax_t)cksum_real.zc_word[2],
1283 			    (uintmax_t)cksum_real.zc_word[3]);
1284 			goto out;
1285 		}
1286 	}
1287 	rv = 0;
1288 out:
1289 	free(vdev_phys);
1290 	return rv;
1291 }
1292 
1293 #endif
1294 
1295 static off_t sblock_try[] = SBLOCKSEARCH;
1296 
1297 static int
verify_ffs(int fd)1298 verify_ffs(int fd)
1299 {
1300 	size_t	i;
1301 
1302 	for (i = 0; sblock_try[i] != -1; i++) {
1303 		union {
1304 		    char	buf[SBLOCKSIZE];
1305 		    struct	fs fs;
1306 		} u;
1307 		ssize_t ret;
1308 
1309 		ret = prog_pread(fd, &u, sizeof(u), sblock_try[i]);
1310 		if (ret < 0) {
1311 			warn("pread");
1312 			break;
1313 		} else if ((size_t)ret < sizeof(u)) {
1314 			warnx("pread: incomplete block");
1315 			break;
1316 		}
1317 		switch (u.fs.fs_magic) {
1318 		case FS_UFS1_MAGIC:
1319 		case FS_UFS2_MAGIC:
1320 		case FS_UFS2EA_MAGIC:
1321 		case FS_UFS1_MAGIC_SWAPPED:
1322 		case FS_UFS2_MAGIC_SWAPPED:
1323 		case FS_UFS2EA_MAGIC_SWAPPED:
1324 			return 0;
1325 		default:
1326 			continue;
1327 		}
1328 	}
1329 
1330 	return 1;	/* failure */
1331 }
1332 
1333 static int
verify_reenter(struct params * p)1334 verify_reenter(struct params *p)
1335 {
1336 	struct keygen *kg;
1337 	bits_t *orig_key, *key = NULL;
1338 	int ret;
1339 
1340 	ret = 0;
1341 	for (kg = p->keygen; kg && !ret; kg = kg->next) {
1342 		if (kg->kg_method != KEYGEN_ARGON2ID &&
1343 		    kg->kg_method != KEYGEN_PKCS5_PBKDF2_SHA1 &&
1344 		    kg->kg_method != KEYGEN_PKCS5_PBKDF2_OLD)
1345 			continue;
1346 
1347 		orig_key = kg->kg_key;
1348 		kg->kg_key = NULL;
1349 
1350 		switch (kg->kg_method) {
1351 #ifdef HAVE_ARGON2
1352 		case KEYGEN_ARGON2ID:
1353 			key = getkey_argon2id("re-enter device", kg,
1354 				bits_len(orig_key));
1355 			break;
1356 #endif
1357 		case KEYGEN_PKCS5_PBKDF2_SHA1:
1358 			key = getkey_pkcs5_pbkdf2("re-enter device", kg,
1359 				bits_len(orig_key), 0);
1360 			break;
1361 		case KEYGEN_PKCS5_PBKDF2_OLD:
1362 			key = getkey_pkcs5_pbkdf2("re-enter device", kg,
1363 				bits_len(orig_key), 1);
1364 			break;
1365 		default:
1366 			warnx("unsupported keygen method");
1367 			kg->kg_key = orig_key;
1368 			return -1;
1369 		}
1370 
1371 		ret = !bits_match(key, orig_key);
1372 
1373 		bits_free(key);
1374 		bits_free(kg->kg_key);
1375 		kg->kg_key = orig_key;
1376 	}
1377 
1378 	return ret;
1379 }
1380 
1381 static int
generate(struct params * p,int argc,char ** argv,const char * outfile,const char * Pfile)1382 generate(struct params *p, int argc, char **argv, const char *outfile,
1383     const char *Pfile)
1384 {
1385 	int	 ret;
1386 
1387 	if (argc < 1 || argc > 2)
1388 		usage();
1389 
1390 	p->algorithm = string_fromcharstar(argv[0]);
1391 	if (argc > 1) {
1392 		size_t keylen;
1393 
1394 		if (parse_size_t(argv[1], &keylen) == -1) {
1395 			warn("Failed to parse key length");
1396 			return -1;
1397 		}
1398 		p->keylen = keylen;
1399 	}
1400 
1401 	ret = params_filldefaults(p);
1402 	if (ret)
1403 		return ret;
1404 
1405 	if (Pfile) {
1406 		struct params *pp;
1407 
1408 		pp = params_cget(Pfile);
1409 		if (pp == NULL)
1410 			return -1;
1411 		if (!params_verify(pp)) {
1412 			params_free(pp);
1413 			warnx("invalid parameters file \"%s\"", Pfile);
1414 			return -1;
1415 		}
1416 		p = params_combine(pp, p);
1417 		keygen_stripstored(&p->keygen);
1418 		if (!p->keygen) {
1419 			warnx("no keygen in parameters file \"%s\"", Pfile);
1420 			return -1;
1421 		}
1422 	} else {
1423 		if (!p->keygen) {
1424 			p->keygen = keygen_generate(KEYGEN_PKCS5_PBKDF2_SHA1);
1425 			if (!p->keygen)
1426 				return -1;
1427 		}
1428 
1429 		if (keygen_filldefaults(p->keygen, p->keylen)) {
1430 			warnx("Failed to generate defaults for keygen");
1431 			return -1;
1432 		}
1433 	}
1434 
1435 	if (Sflag) {
1436 		if (Pfile)
1437 			ret = keygen_tweakshared(p->keygen);
1438 		else
1439 			ret = keygen_makeshared(p->keygen);
1440 		if (ret)
1441 			return ret;
1442 	}
1443 
1444 	if (!params_verify(p)) {
1445 		warnx("invalid parameters generated");
1446 		return -1;
1447 	}
1448 
1449 	return params_cput(p, outfile);
1450 }
1451 
1452 static int
generate_convert(struct params * p,int argc,char ** argv,const char * outfile,const char * Pfile)1453 generate_convert(struct params *p, int argc, char **argv, const char *outfile,
1454     const char *Pfile)
1455 {
1456 	struct params	*oldp;
1457 	struct keygen	*kg;
1458 	int		 ret;
1459 
1460 	if (argc != 1)
1461 		usage();
1462 
1463 	oldp = params_cget(*argv);
1464 	if (!oldp)
1465 		return -1;
1466 
1467 	/* for sanity, we ensure that none of the keygens are randomkey */
1468 	for (kg=p->keygen; kg; kg=kg->next)
1469 		if ((kg->kg_method == KEYGEN_RANDOMKEY) ||
1470 		    (kg->kg_method == KEYGEN_URANDOMKEY)) {
1471 			warnx("can't preserve randomly generated key");
1472 			goto bail;
1473 		}
1474 	for (kg=oldp->keygen; kg; kg=kg->next)
1475 		if ((kg->kg_method == KEYGEN_RANDOMKEY) ||
1476 		    (kg->kg_method == KEYGEN_URANDOMKEY)) {
1477 			warnx("can't preserve randomly generated key");
1478 			goto bail;
1479 		}
1480 
1481 	if (!params_verify(oldp)) {
1482 		warnx("invalid old parameters file \"%s\"", *argv);
1483 		return -1;
1484 	}
1485 
1486 	oldp->key = getkey("old file", oldp->keygen, oldp->keylen, NULL);
1487 
1488 	/* we copy across the non-keygen info, here. */
1489 
1490 	string_free(p->algorithm);
1491 	string_free(p->ivmeth);
1492 
1493 	p->algorithm = string_dup(oldp->algorithm);
1494 	p->ivmeth = string_dup(oldp->ivmeth);
1495 	p->keylen = oldp->keylen;
1496 	p->bsize = oldp->bsize;
1497 	if (p->verify_method == VERIFY_UNKNOWN)
1498 		p->verify_method = oldp->verify_method;
1499 
1500 	params_free(oldp);
1501 
1502 	if (Pfile) {
1503 		struct params *pp;
1504 
1505 		pp = params_cget(Pfile);
1506 		if (pp == NULL)
1507 			return -1;
1508 		if (!params_verify(pp)) {
1509 			params_free(pp);
1510 			warnx("invalid parameters file \"%s\"", Pfile);
1511 			return -1;
1512 		}
1513 		p = params_combine(pp, p);
1514 		keygen_stripstored(&p->keygen);
1515 		if (!p->keygen) {
1516 			warnx("no keygen in parameters file \"%s\"", Pfile);
1517 			return -1;
1518 		}
1519 	} else {
1520 		if (!p->keygen) {
1521 			p->keygen = keygen_generate(KEYGEN_PKCS5_PBKDF2_SHA1);
1522 			if (!p->keygen)
1523 				return -1;
1524 		}
1525 		(void)params_filldefaults(p);
1526 		(void)keygen_filldefaults(p->keygen, p->keylen);
1527 	}
1528 
1529 	if (Sflag) {
1530 		if (Pfile)
1531 			ret = keygen_tweakshared(p->keygen);
1532 		else
1533 			ret = keygen_makeshared(p->keygen);
1534 		if (ret)
1535 			return ret;
1536 	}
1537 
1538 	p->key = getkey("new file", p->keygen, p->keylen, NULL);
1539 
1540 	kg = keygen_generate(KEYGEN_STOREDKEY);
1541 	kg->kg_key = bits_xor(p->key, oldp->key);
1542 	keygen_addlist(&p->keygen, kg);
1543 
1544 	if (!params_verify(p)) {
1545 		warnx("can't generate new parameters file");
1546 		return -1;
1547 	}
1548 
1549 	return params_cput(p, outfile);
1550  bail:;
1551 	params_free(oldp);
1552 	return -1;
1553 }
1554 
1555 static int
1556 /*ARGSUSED*/
do_all(const char * cfile,int argc,char ** argv,int (* conf)(int,char **,struct params *,int))1557 do_all(const char *cfile, int argc, char **argv,
1558        int (*conf)(int, char **, struct params *, int))
1559 {
1560 	FILE		 *f;
1561 	size_t		  len;
1562 	size_t		  lineno;
1563 	int		  my_argc;
1564 	int		  ret;
1565 	const char	 *fn;
1566 	char		 *line;
1567 	char		**my_argv;
1568 
1569 	if (argc > 0)
1570 		usage();
1571 
1572 	if (!cfile[0])
1573 		fn = CGDCONFIG_CFILE;
1574 	else
1575 		fn = cfile;
1576 
1577 	f = fopen(fn, "r");
1578 	if (f == NULL) {
1579 		warn("could not open config file \"%s\"", fn);
1580 		return -1;
1581 	}
1582 
1583 	ret = 0;
1584 	lineno = 0;
1585 	for (;;) {
1586 		line = fparseln(f, &len, &lineno, "\\\\#", FPARSELN_UNESCALL);
1587 		if (!line)
1588 			break;
1589 		if (!*line)
1590 			continue;
1591 
1592 		my_argv = words(line, &my_argc);
1593 		ret = conf(my_argc, my_argv, NULL, CONFIG_FLAGS_FROMALL);
1594 		if (ret) {
1595 			warnx("action failed on \"%s\" line %lu", fn,
1596 			    (u_long)lineno);
1597 			break;
1598 		}
1599 		words_free(my_argv, my_argc);
1600 	}
1601 	return ret;
1602 }
1603 
1604 static const char *
iv_method(int mode)1605 iv_method(int mode)
1606 {
1607 
1608 	switch (mode) {
1609 	case CGD_CIPHER_CBC_ENCBLKNO8:
1610 		return "encblkno8";
1611 	case CGD_CIPHER_CBC_ENCBLKNO1:
1612 		return "encblkno1";
1613 	default:
1614 		return "unknown";
1615 	}
1616 }
1617 
1618 
1619 static void
show(const char * dev)1620 show(const char *dev)
1621 {
1622 	char path[64];
1623 	struct cgd_user cgu;
1624 	int fd;
1625 
1626 	fd = opendisk(dev, O_RDONLY, path, sizeof(path), 0);
1627 	if (fd == -1) {
1628 		warn("open: %s", dev);
1629 		return;
1630 	}
1631 
1632 	cgu.cgu_unit = -1;
1633 	if (prog_ioctl(fd, CGDIOCGET, &cgu) == -1) {
1634 		close(fd);
1635 		err(1, "CGDIOCGET");
1636 	}
1637 
1638 	printf("%s: ", dev);
1639 
1640 	if (cgu.cgu_dev == 0) {
1641 		printf("not in use");
1642 		goto out;
1643 	}
1644 
1645 	dev = devname(cgu.cgu_dev, S_IFBLK);
1646 	if (dev != NULL) {
1647 		printf("%s ", dev);
1648 	} else {
1649 		printf("dev %llu,%llu ",
1650 		    (unsigned long long)major(cgu.cgu_dev),
1651 		    (unsigned long long)minor(cgu.cgu_dev));
1652 	}
1653 
1654 	if (verbose)
1655 		printf("%s ", cgu.cgu_alg);
1656 	if (verbose > 1) {
1657 		printf("keylen %d ", cgu.cgu_keylen);
1658 		printf("blksize %zd ", cgu.cgu_blocksize);
1659 		printf("%s ", iv_method(cgu.cgu_mode));
1660 	}
1661 
1662  out:;
1663 	putchar('\n');
1664 	close(fd);
1665 }
1666 
1667 static int
do_list(int argc,char ** argv)1668 do_list(int argc, char **argv)
1669 {
1670 
1671 	if (argc != 0 && argc != 1)
1672 		usage();
1673 
1674 	if (argc) {
1675 		show(argv[0]);
1676 		return 0;
1677 	}
1678 
1679 	DIR *dirp;
1680 	struct dirent *dp;
1681 	__BITMAP_TYPE(, uint32_t, 65536) bm;
1682 
1683 	__BITMAP_ZERO(&bm);
1684 
1685 	if ((dirp = opendir(_PATH_DEV)) == NULL)
1686 		err(1, "opendir: %s", _PATH_DEV);
1687 
1688 	while ((dp = readdir(dirp)) != NULL) {
1689 		char *ep;
1690 		if (strncmp(dp->d_name, "rcgd", 4) != 0)
1691 			continue;
1692 		errno = 0;
1693 		int n = (int)strtol(dp->d_name + 4, &ep, 0);
1694 		if (ep == dp->d_name + 4 || errno != 0) {
1695 			warnx("bad name %s", dp->d_name);
1696 			continue;
1697 		}
1698 		*ep = '\0';
1699 		if (__BITMAP_ISSET(n, &bm))
1700 			continue;
1701 		__BITMAP_SET(n, &bm);
1702 		show(dp->d_name + 1);
1703 	}
1704 
1705 	closedir(dirp);
1706 	return 0;
1707 }
1708 
1709 static int
printkey(const char * dev,const char * paramsfile,const char * fmt,...)1710 printkey(const char *dev, const char *paramsfile, const char *fmt, ...)
1711 {
1712 	va_list va;
1713 	struct params *p;
1714 	const uint8_t *raw;
1715 	size_t nbits, nbytes;
1716 	size_t nb64;
1717 	char *b64;
1718 	int ret;
1719 
1720 	p = params_cget(paramsfile);
1721 	if (p == NULL)
1722 		return -1;
1723 	if (!params_verify(p)) {
1724 		warnx("invalid parameters file \"%s\"", paramsfile);
1725 		return -1;
1726 	}
1727 	p->key = getkey(dev, p->keygen, p->keylen, NULL);
1728 	raw = bits_getbuf(p->key);
1729 	nbits = bits_len(p->key);
1730 	assert(nbits <= INT_MAX - 7);
1731 	nbytes = BITS2BYTES(nbits);
1732 	assert(nbytes <= 3*(INT_MAX/4) - 2);
1733 
1734 	nb64 = 4*((nbytes + 2)/3);
1735 	b64 = emalloc(nb64 + 2);
1736 	ret = __b64_ntop(raw, nbytes, b64, nb64 + 1);
1737 	assert(ret == (int)nb64);
1738 	b64[nb64] = '\n';
1739 	b64[nb64 + 1] = '\0';
1740 
1741 	va_start(va, fmt);
1742 	vprintf(fmt, va);
1743 	va_end(va);
1744 	if (fwrite(b64, nb64 + 1, 1, stdout) != 1)
1745 		err(1, "fwrite");
1746 	fflush(stdout);
1747 	return ferror(stdout);
1748 }
1749 
1750 static int
printkey1(int argc,char ** argv,struct params * inparams,int flags)1751 printkey1(int argc, char **argv, struct params *inparams, int flags)
1752 {
1753 	char devicename[PATH_MAX], paramsfilebuf[PATH_MAX];
1754 	const char *dev, *paramsfile;
1755 
1756 	assert(flags == CONFIG_FLAGS_FROMALL);
1757 
1758 	if (argc < 2 || argc > 3)
1759 		return -1;
1760 
1761 	dev = getfsspecname(devicename, sizeof(devicename), argv[1]);
1762 	if (dev == NULL) {
1763 		warnx("getfsspecname failed: %s", devicename);
1764 		return -1;
1765 	}
1766 
1767 	if (argc == 2) {
1768 		strlcpy(paramsfilebuf, dev, sizeof(paramsfilebuf));
1769 		paramsfile = basename(paramsfilebuf);
1770 	} else {
1771 		paramsfile = argv[2];
1772 	}
1773 
1774 	return printkey(dev, paramsfile, "%s: ", dev);
1775 }
1776 
1777 static int
do_printkey(int argc,char ** argv)1778 do_printkey(int argc, char **argv)
1779 {
1780 
1781 	if (argc != 1)
1782 		usage();
1783 	return printkey("key", argv[0], "");
1784 }
1785 
1786 static void
eliminate_cores(void)1787 eliminate_cores(void)
1788 {
1789 	struct rlimit	rlp;
1790 
1791 	rlp.rlim_cur = 0;
1792 	rlp.rlim_max = 0;
1793 	if (setrlimit(RLIMIT_CORE, &rlp) == -1)
1794 		err(EXIT_FAILURE, "Can't disable cores");
1795 }
1796