Home | History | Annotate | Line # | Download | only in cgdconfig
cgdconfig.c revision 1.40
      1  1.40  christos /* $NetBSD: cgdconfig.c,v 1.40 2015/11/22 20:24:19 christos Exp $ */
      2   1.1     elric 
      3   1.1     elric /*-
      4   1.5     elric  * Copyright (c) 2002, 2003 The NetBSD Foundation, Inc.
      5   1.1     elric  * All rights reserved.
      6   1.1     elric  *
      7   1.1     elric  * This code is derived from software contributed to The NetBSD Foundation
      8   1.1     elric  * by Roland C. Dowdeswell.
      9   1.1     elric  *
     10   1.1     elric  * Redistribution and use in source and binary forms, with or without
     11   1.1     elric  * modification, are permitted provided that the following conditions
     12   1.1     elric  * are met:
     13   1.1     elric  * 1. Redistributions of source code must retain the above copyright
     14   1.1     elric  *    notice, this list of conditions and the following disclaimer.
     15   1.1     elric  * 2. Redistributions in binary form must reproduce the above copyright
     16   1.1     elric  *    notice, this list of conditions and the following disclaimer in the
     17   1.1     elric  *    documentation and/or other materials provided with the distribution.
     18   1.1     elric  *
     19   1.1     elric  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20   1.1     elric  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21   1.1     elric  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22   1.1     elric  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23   1.1     elric  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24   1.1     elric  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25   1.1     elric  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26   1.1     elric  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27   1.1     elric  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28   1.1     elric  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29   1.1     elric  * POSSIBILITY OF SUCH DAMAGE.
     30   1.1     elric  */
     31   1.1     elric 
     32   1.1     elric #include <sys/cdefs.h>
     33   1.1     elric #ifndef lint
     34  1.24     lukem __COPYRIGHT("@(#) Copyright (c) 2002, 2003\
     35  1.24     lukem  The NetBSD Foundation, Inc.  All rights reserved.");
     36  1.40  christos __RCSID("$NetBSD: cgdconfig.c,v 1.40 2015/11/22 20:24:19 christos Exp $");
     37   1.1     elric #endif
     38   1.1     elric 
     39   1.5     elric #include <err.h>
     40   1.1     elric #include <errno.h>
     41   1.1     elric #include <fcntl.h>
     42   1.1     elric #include <libgen.h>
     43   1.1     elric #include <stdio.h>
     44   1.1     elric #include <stdlib.h>
     45   1.1     elric #include <string.h>
     46   1.1     elric #include <unistd.h>
     47   1.1     elric #include <util.h>
     48  1.35  christos #include <paths.h>
     49  1.35  christos #include <dirent.h>
     50   1.1     elric 
     51   1.1     elric #include <sys/ioctl.h>
     52  1.37   mlelstv #include <sys/bootblock.h>
     53   1.3     elric #include <sys/disklabel.h>
     54  1.37   mlelstv #include <sys/disklabel_gpt.h>
     55  1.14     elric #include <sys/mman.h>
     56   1.1     elric #include <sys/param.h>
     57  1.13     elric #include <sys/resource.h>
     58  1.34  christos #include <sys/statvfs.h>
     59  1.35  christos #include <sys/bitops.h>
     60   1.1     elric 
     61   1.1     elric #include <dev/cgdvar.h>
     62   1.1     elric 
     63   1.5     elric #include <ufs/ffs/fs.h>
     64   1.5     elric 
     65   1.1     elric #include "params.h"
     66   1.1     elric #include "pkcs5_pbkdf2.h"
     67   1.1     elric #include "utils.h"
     68  1.28     pooka #include "cgdconfig.h"
     69  1.32     pooka #include "prog_ops.h"
     70   1.1     elric 
     71   1.1     elric #define CGDCONFIG_CFILE		CGDCONFIG_DIR "/cgd.conf"
     72   1.1     elric 
     73  1.17    cbiere enum action {
     74  1.17    cbiere 	 ACTION_DEFAULT,		/* default -> configure */
     75  1.17    cbiere 	 ACTION_CONFIGURE,		/* configure, with paramsfile */
     76  1.17    cbiere 	 ACTION_UNCONFIGURE,		/* unconfigure */
     77  1.17    cbiere 	 ACTION_GENERATE,		/* generate a paramsfile */
     78  1.17    cbiere 	 ACTION_GENERATE_CONVERT,	/* generate a ``dup'' paramsfile */
     79  1.17    cbiere 	 ACTION_CONFIGALL,		/* configure all from config file */
     80  1.17    cbiere 	 ACTION_UNCONFIGALL,		/* unconfigure all from config file */
     81  1.34  christos 	 ACTION_CONFIGSTDIN,		/* configure, key from stdin */
     82  1.34  christos 	 ACTION_LIST			/* list configured devices */
     83  1.17    cbiere };
     84   1.1     elric 
     85   1.1     elric /* if nflag is set, do not configure/unconfigure the cgd's */
     86   1.1     elric 
     87   1.1     elric int	nflag = 0;
     88   1.1     elric 
     89  1.22     elric /* if pflag is set to PFLAG_STDIN read from stdin rather than getpass(3) */
     90  1.22     elric 
     91  1.22     elric #define	PFLAG_GETPASS	0x01
     92  1.22     elric #define	PFLAG_STDIN	0x02
     93  1.22     elric int	pflag = PFLAG_GETPASS;
     94  1.22     elric 
     95   1.3     elric static int	configure(int, char **, struct params *, int);
     96   1.1     elric static int	configure_stdin(struct params *, int argc, char **);
     97   1.1     elric static int	generate(struct params *, int, char **, const char *);
     98   1.5     elric static int	generate_convert(struct params *, int, char **, const char *);
     99   1.3     elric static int	unconfigure(int, char **, struct params *, int);
    100   1.3     elric static int	do_all(const char *, int, char **,
    101   1.3     elric 		       int (*)(int, char **, struct params *, int));
    102  1.34  christos static int	do_list(int, char **);
    103   1.1     elric 
    104   1.1     elric #define CONFIG_FLAGS_FROMALL	1	/* called from configure_all() */
    105   1.1     elric #define CONFIG_FLAGS_FROMMAIN	2	/* called from main() */
    106   1.1     elric 
    107   1.2     elric static int	 configure_params(int, const char *, const char *,
    108   1.2     elric 				  struct params *);
    109  1.13     elric static void	 eliminate_cores(void);
    110  1.19  christos static bits_t	*getkey(const char *, struct keygen *, size_t);
    111  1.19  christos static bits_t	*getkey_storedkey(const char *, struct keygen *, size_t);
    112  1.19  christos static bits_t	*getkey_randomkey(const char *, struct keygen *, size_t, int);
    113  1.23     elric static bits_t	*getkey_pkcs5_pbkdf2(const char *, struct keygen *, size_t,
    114  1.23     elric 				     int);
    115  1.23     elric static bits_t	*getkey_shell_cmd(const char *, struct keygen *, size_t);
    116  1.22     elric static char	*maybe_getpass(char *);
    117  1.17    cbiere static int	 opendisk_werror(const char *, char *, size_t);
    118   1.3     elric static int	 unconfigure_fd(int);
    119   1.3     elric static int	 verify(struct params *, int);
    120   1.5     elric static int	 verify_disklabel(int);
    121   1.5     elric static int	 verify_ffs(int);
    122   1.9        cb static int	 verify_reenter(struct params *);
    123  1.37   mlelstv static int	 verify_mbr(int);
    124  1.37   mlelstv static int	 verify_gpt(int);
    125   1.1     elric 
    126  1.33     joerg __dead static void	 usage(void);
    127   1.1     elric 
    128   1.1     elric /* Verbose Framework */
    129  1.17    cbiere unsigned	verbose = 0;
    130   1.1     elric 
    131   1.1     elric #define VERBOSE(x,y)	if (verbose >= x) y
    132  1.19  christos #define VPRINTF(x,y)	if (verbose >= x) (void)printf y
    133   1.1     elric 
    134   1.1     elric static void
    135   1.1     elric usage(void)
    136   1.1     elric {
    137   1.1     elric 
    138  1.19  christos 	(void)fprintf(stderr, "usage: %s [-nv] [-V vmeth] cgd dev [paramsfile]\n",
    139   1.1     elric 	    getprogname());
    140  1.19  christos 	(void)fprintf(stderr, "       %s -C [-nv] [-f configfile]\n", getprogname());
    141  1.19  christos 	(void)fprintf(stderr, "       %s -G [-nv] [-i ivmeth] [-k kgmeth] "
    142   1.5     elric 	    "[-o outfile] paramsfile\n", getprogname());
    143  1.19  christos 	(void)fprintf(stderr, "       %s -g [-nv] [-i ivmeth] [-k kgmeth] "
    144   1.5     elric 	    "[-o outfile] alg [keylen]\n", getprogname());
    145  1.34  christos 	(void)fprintf(stderr, "       %s -l\n", getprogname());
    146  1.19  christos 	(void)fprintf(stderr, "       %s -s [-nv] [-i ivmeth] cgd dev alg "
    147   1.1     elric 	    "[keylen]\n", getprogname());
    148  1.34  christos 	(void)fprintf(stderr, "       %s -U [-nv] [-f configfile]\n", getprogname());
    149  1.19  christos 	(void)fprintf(stderr, "       %s -u [-nv] cgd\n", getprogname());
    150  1.17    cbiere 	exit(EXIT_FAILURE);
    151  1.17    cbiere }
    152  1.17    cbiere 
    153  1.17    cbiere static int
    154  1.19  christos parse_size_t(const char *s, size_t *l)
    155  1.17    cbiere {
    156  1.17    cbiere 	char *endptr;
    157  1.17    cbiere 	long v;
    158  1.17    cbiere 
    159  1.17    cbiere 	errno = 0;
    160  1.17    cbiere 	v = strtol(s, &endptr, 10);
    161  1.17    cbiere 	if ((v == LONG_MIN || v == LONG_MAX) && errno)
    162  1.17    cbiere 		return -1;
    163  1.17    cbiere 	if (v < INT_MIN || v > INT_MAX) {
    164  1.17    cbiere 		errno = ERANGE;
    165  1.17    cbiere 		return -1;
    166  1.17    cbiere 	}
    167  1.17    cbiere 	if (endptr == s) {
    168  1.17    cbiere 		errno = EINVAL;
    169  1.17    cbiere 		return -1;
    170  1.17    cbiere 	}
    171  1.19  christos 	*l = (size_t)v;
    172  1.19  christos 	return 0;
    173  1.17    cbiere }
    174  1.17    cbiere 
    175  1.17    cbiere static void
    176  1.17    cbiere set_action(enum action *action, enum action value)
    177  1.17    cbiere {
    178  1.17    cbiere 	if (*action != ACTION_DEFAULT)
    179  1.17    cbiere 		usage();
    180  1.17    cbiere 	*action = value;
    181   1.1     elric }
    182   1.1     elric 
    183   1.1     elric int
    184   1.1     elric main(int argc, char **argv)
    185   1.1     elric {
    186   1.5     elric 	struct params *p;
    187   1.5     elric 	struct params *tp;
    188   1.5     elric 	struct keygen *kg;
    189  1.17    cbiere 	enum action action = ACTION_DEFAULT;
    190   1.1     elric 	int	ch;
    191  1.17    cbiere 	const char	*cfile = NULL;
    192  1.17    cbiere 	const char	*outfile = NULL;
    193   1.1     elric 
    194  1.15     elric 	setprogname(*argv);
    195  1.13     elric 	eliminate_cores();
    196  1.14     elric 	if (mlockall(MCL_FUTURE))
    197  1.14     elric 		err(EXIT_FAILURE, "Can't lock memory");
    198   1.5     elric 	p = params_new();
    199   1.5     elric 	kg = NULL;
    200   1.1     elric 
    201  1.34  christos 	while ((ch = getopt(argc, argv, "CGUV:b:f:gi:k:lno:spuv")) != -1)
    202   1.1     elric 		switch (ch) {
    203   1.1     elric 		case 'C':
    204  1.17    cbiere 			set_action(&action, ACTION_CONFIGALL);
    205   1.1     elric 			break;
    206   1.5     elric 		case 'G':
    207  1.17    cbiere 			set_action(&action, ACTION_GENERATE_CONVERT);
    208   1.5     elric 			break;
    209   1.1     elric 		case 'U':
    210  1.17    cbiere 			set_action(&action, ACTION_UNCONFIGALL);
    211   1.1     elric 			break;
    212   1.3     elric 		case 'V':
    213   1.5     elric 			tp = params_verify_method(string_fromcharstar(optarg));
    214   1.5     elric 			if (!tp)
    215   1.3     elric 				usage();
    216   1.5     elric 			p = params_combine(p, tp);
    217   1.3     elric 			break;
    218   1.1     elric 		case 'b':
    219  1.17    cbiere 			{
    220  1.19  christos 				size_t size;
    221  1.17    cbiere 
    222  1.19  christos 				if (parse_size_t(optarg, &size) == -1)
    223  1.17    cbiere 					usage();
    224  1.17    cbiere 				tp = params_bsize(size);
    225  1.17    cbiere 				if (!tp)
    226  1.17    cbiere 					usage();
    227  1.17    cbiere 				p = params_combine(p, tp);
    228  1.17    cbiere 			}
    229   1.1     elric 			break;
    230   1.1     elric 		case 'f':
    231  1.17    cbiere 			if (cfile)
    232  1.17    cbiere 				usage();
    233  1.17    cbiere 			cfile = estrdup(optarg);
    234   1.1     elric 			break;
    235   1.1     elric 		case 'g':
    236  1.17    cbiere 			set_action(&action, ACTION_GENERATE);
    237   1.1     elric 			break;
    238   1.1     elric 		case 'i':
    239   1.5     elric 			tp = params_ivmeth(string_fromcharstar(optarg));
    240   1.5     elric 			p = params_combine(p, tp);
    241   1.1     elric 			break;
    242   1.1     elric 		case 'k':
    243   1.5     elric 			kg = keygen_method(string_fromcharstar(optarg));
    244   1.5     elric 			if (!kg)
    245   1.1     elric 				usage();
    246   1.5     elric 			keygen_addlist(&p->keygen, kg);
    247   1.1     elric 			break;
    248  1.34  christos 		case 'l':
    249  1.34  christos 			set_action(&action, ACTION_LIST);
    250  1.34  christos 			break;
    251   1.1     elric 		case 'n':
    252   1.1     elric 			nflag = 1;
    253   1.1     elric 			break;
    254   1.1     elric 		case 'o':
    255  1.17    cbiere 			if (outfile)
    256  1.17    cbiere 				usage();
    257  1.17    cbiere 			outfile = estrdup(optarg);
    258   1.1     elric 			break;
    259  1.22     elric 		case 'p':
    260  1.22     elric 			pflag = PFLAG_STDIN;
    261  1.22     elric 			break;
    262   1.1     elric 		case 's':
    263  1.17    cbiere 			set_action(&action, ACTION_CONFIGSTDIN);
    264   1.1     elric 			break;
    265   1.1     elric 
    266   1.1     elric 		case 'u':
    267  1.17    cbiere 			set_action(&action, ACTION_UNCONFIGURE);
    268   1.1     elric 			break;
    269   1.1     elric 		case 'v':
    270   1.1     elric 			verbose++;
    271   1.1     elric 			break;
    272   1.1     elric 		default:
    273   1.1     elric 			usage();
    274   1.1     elric 			/* NOTREACHED */
    275   1.1     elric 		}
    276   1.1     elric 
    277   1.1     elric 	argc -= optind;
    278   1.1     elric 	argv += optind;
    279   1.1     elric 
    280  1.17    cbiere 	if (!outfile)
    281  1.17    cbiere 		outfile = "";
    282  1.17    cbiere 	if (!cfile)
    283  1.17    cbiere 		cfile = "";
    284  1.17    cbiere 
    285  1.32     pooka 	if (prog_init && prog_init() == -1)
    286  1.32     pooka 		err(1, "init failed");
    287  1.32     pooka 
    288   1.1     elric 	/* validate the consistency of the arguments */
    289   1.1     elric 
    290   1.1     elric 	switch (action) {
    291  1.17    cbiere 	case ACTION_DEFAULT:	/* ACTION_CONFIGURE is the default */
    292   1.1     elric 	case ACTION_CONFIGURE:
    293   1.5     elric 		return configure(argc, argv, p, CONFIG_FLAGS_FROMMAIN);
    294   1.1     elric 	case ACTION_UNCONFIGURE:
    295   1.3     elric 		return unconfigure(argc, argv, NULL, CONFIG_FLAGS_FROMMAIN);
    296   1.1     elric 	case ACTION_GENERATE:
    297   1.5     elric 		return generate(p, argc, argv, outfile);
    298   1.5     elric 	case ACTION_GENERATE_CONVERT:
    299   1.5     elric 		return generate_convert(p, argc, argv, outfile);
    300   1.1     elric 	case ACTION_CONFIGALL:
    301   1.1     elric 		return do_all(cfile, argc, argv, configure);
    302   1.1     elric 	case ACTION_UNCONFIGALL:
    303   1.1     elric 		return do_all(cfile, argc, argv, unconfigure);
    304   1.1     elric 	case ACTION_CONFIGSTDIN:
    305   1.5     elric 		return configure_stdin(p, argc, argv);
    306  1.34  christos 	case ACTION_LIST:
    307  1.34  christos 		return do_list(argc, argv);
    308  1.19  christos 	default:
    309  1.19  christos 		errx(EXIT_FAILURE, "undefined action");
    310  1.19  christos 		/* NOTREACHED */
    311   1.1     elric 	}
    312   1.1     elric }
    313   1.1     elric 
    314   1.5     elric static bits_t *
    315  1.19  christos getkey(const char *dev, struct keygen *kg, size_t len)
    316   1.1     elric {
    317   1.5     elric 	bits_t	*ret = NULL;
    318   1.5     elric 	bits_t	*tmp;
    319   1.1     elric 
    320  1.19  christos 	VPRINTF(3, ("getkey(\"%s\", %p, %zu) called\n", dev, kg, len));
    321   1.5     elric 	for (; kg; kg=kg->next) {
    322   1.5     elric 		switch (kg->kg_method) {
    323   1.5     elric 		case KEYGEN_STOREDKEY:
    324   1.5     elric 			tmp = getkey_storedkey(dev, kg, len);
    325   1.5     elric 			break;
    326   1.5     elric 		case KEYGEN_RANDOMKEY:
    327  1.12        tv 			tmp = getkey_randomkey(dev, kg, len, 1);
    328  1.12        tv 			break;
    329  1.12        tv 		case KEYGEN_URANDOMKEY:
    330  1.12        tv 			tmp = getkey_randomkey(dev, kg, len, 0);
    331   1.5     elric 			break;
    332  1.10       dan 		case KEYGEN_PKCS5_PBKDF2_SHA1:
    333  1.10       dan 			tmp = getkey_pkcs5_pbkdf2(dev, kg, len, 0);
    334  1.10       dan 			break;
    335  1.10       dan 		/* provide backwards compatibility for old config files */
    336  1.10       dan 		case KEYGEN_PKCS5_PBKDF2_OLD:
    337  1.10       dan 			tmp = getkey_pkcs5_pbkdf2(dev, kg, len, 1);
    338   1.5     elric 			break;
    339  1.23     elric 		case KEYGEN_SHELL_CMD:
    340  1.23     elric 			tmp = getkey_shell_cmd(dev, kg, len);
    341  1.23     elric 			break;
    342   1.5     elric 		default:
    343   1.5     elric 			warnx("unrecognised keygen method %d in getkey()",
    344   1.5     elric 			    kg->kg_method);
    345   1.5     elric 			if (ret)
    346   1.5     elric 				bits_free(ret);
    347   1.5     elric 			return NULL;
    348   1.5     elric 		}
    349   1.5     elric 
    350   1.5     elric 		if (ret)
    351   1.5     elric 			ret = bits_xor_d(tmp, ret);
    352   1.5     elric 		else
    353   1.5     elric 			ret = tmp;
    354   1.1     elric 	}
    355   1.5     elric 
    356   1.5     elric 	return ret;
    357   1.5     elric }
    358   1.5     elric 
    359   1.5     elric /*ARGSUSED*/
    360   1.5     elric static bits_t *
    361  1.19  christos getkey_storedkey(const char *target, struct keygen *kg, size_t keylen)
    362   1.5     elric {
    363   1.5     elric 	return bits_dup(kg->kg_key);
    364   1.1     elric }
    365   1.1     elric 
    366   1.5     elric /*ARGSUSED*/
    367   1.5     elric static bits_t *
    368  1.19  christos getkey_randomkey(const char *target, struct keygen *kg, size_t keylen, int hard)
    369   1.1     elric {
    370  1.12        tv 	return bits_getrandombits(keylen, hard);
    371   1.1     elric }
    372   1.1     elric 
    373  1.22     elric static char *
    374  1.22     elric maybe_getpass(char *prompt)
    375  1.22     elric {
    376  1.22     elric 	char	 buf[1024];
    377  1.22     elric 	char	*p = buf;
    378  1.22     elric 	char	*tmp;
    379  1.22     elric 
    380  1.22     elric 	switch (pflag) {
    381  1.22     elric 	case PFLAG_GETPASS:
    382  1.22     elric 		p = getpass(prompt);
    383  1.22     elric 		break;
    384  1.22     elric 
    385  1.22     elric 	case PFLAG_STDIN:
    386  1.22     elric 		p = fgets(buf, sizeof(buf), stdin);
    387  1.22     elric 		if (p) {
    388  1.22     elric 			tmp = strchr(p, '\n');
    389  1.22     elric 			if (tmp)
    390  1.22     elric 				*tmp = '\0';
    391  1.22     elric 		}
    392  1.22     elric 		break;
    393  1.22     elric 
    394  1.22     elric 	default:
    395  1.22     elric 		errx(EXIT_FAILURE, "pflag set inappropriately?");
    396  1.22     elric 	}
    397  1.22     elric 
    398  1.22     elric 	if (!p)
    399  1.22     elric 		err(EXIT_FAILURE, "failed to read passphrase");
    400  1.22     elric 
    401  1.22     elric 	return estrdup(p);
    402  1.22     elric }
    403  1.22     elric 
    404   1.5     elric /*ARGSUSED*/
    405  1.29     elric /*
    406  1.10       dan  * XXX take, and pass through, a compat flag that indicates whether we
    407  1.10       dan  * provide backwards compatibility with a previous bug.  The previous
    408  1.10       dan  * behaviour is indicated by the keygen method pkcs5_pbkdf2, and a
    409  1.10       dan  * non-zero compat flag. The new default, and correct keygen method is
    410  1.10       dan  * called pcks5_pbkdf2/sha1.  When the old method is removed, so will
    411  1.10       dan  * be the compat argument.
    412  1.10       dan  */
    413   1.5     elric static bits_t *
    414  1.19  christos getkey_pkcs5_pbkdf2(const char *target, struct keygen *kg, size_t keylen,
    415  1.19  christos     int compat)
    416   1.1     elric {
    417   1.5     elric 	bits_t		*ret;
    418  1.25  dholland 	char		*passp;
    419   1.5     elric 	char		 buf[1024];
    420   1.5     elric 	u_int8_t	*tmp;
    421   1.1     elric 
    422   1.5     elric 	snprintf(buf, sizeof(buf), "%s's passphrase:", target);
    423  1.25  dholland 	passp = maybe_getpass(buf);
    424  1.25  dholland 	if (pkcs5_pbkdf2(&tmp, BITS2BYTES(keylen), (uint8_t *)passp,
    425  1.25  dholland 	    strlen(passp),
    426   1.5     elric 	    bits_getbuf(kg->kg_salt), BITS2BYTES(bits_len(kg->kg_salt)),
    427  1.10       dan 	    kg->kg_iterations, compat)) {
    428   1.5     elric 		warnx("failed to generate PKCS#5 PBKDF2 key");
    429   1.5     elric 		return NULL;
    430   1.5     elric 	}
    431   1.5     elric 
    432   1.5     elric 	ret = bits_new(tmp, keylen);
    433   1.9        cb 	kg->kg_key = bits_dup(ret);
    434  1.27  christos 	memset(passp, 0, strlen(passp));
    435  1.22     elric 	free(passp);
    436   1.5     elric 	free(tmp);
    437   1.1     elric 	return ret;
    438   1.1     elric }
    439   1.1     elric 
    440   1.5     elric /*ARGSUSED*/
    441  1.23     elric static bits_t *
    442  1.23     elric getkey_shell_cmd(const char *target, struct keygen *kg, size_t keylen)
    443  1.23     elric {
    444  1.23     elric 	FILE	*f;
    445  1.23     elric 	bits_t	*ret;
    446  1.23     elric 
    447  1.23     elric 	f = popen(string_tocharstar(kg->kg_cmd), "r");
    448  1.23     elric 	ret = bits_fget(f, keylen);
    449  1.23     elric 	pclose(f);
    450  1.23     elric 
    451  1.23     elric 	return ret;
    452  1.23     elric }
    453  1.23     elric 
    454  1.23     elric /*ARGSUSED*/
    455   1.1     elric static int
    456   1.3     elric unconfigure(int argc, char **argv, struct params *inparams, int flags)
    457   1.1     elric {
    458   1.1     elric 	int	fd;
    459   1.1     elric 	int	ret;
    460   1.1     elric 	char	buf[MAXPATHLEN] = "";
    461   1.1     elric 
    462   1.1     elric 	/* only complain about additional arguments, if called from main() */
    463   1.1     elric 	if (flags == CONFIG_FLAGS_FROMMAIN && argc != 1)
    464   1.1     elric 		usage();
    465   1.1     elric 
    466   1.1     elric 	/* if called from do_all(), then ensure that 2 or 3 args exist */
    467   1.1     elric 	if (flags == CONFIG_FLAGS_FROMALL && (argc < 2 || argc > 3))
    468   1.1     elric 		return -1;
    469   1.1     elric 
    470  1.32     pooka 	fd = opendisk1(*argv, O_RDWR, buf, sizeof(buf), 1, prog_open);
    471   1.1     elric 	if (fd == -1) {
    472  1.17    cbiere 		int saved_errno = errno;
    473  1.17    cbiere 
    474   1.5     elric 		warn("can't open cgd \"%s\", \"%s\"", *argv, buf);
    475   1.1     elric 
    476   1.1     elric 		/* this isn't fatal with nflag != 0 */
    477   1.1     elric 		if (!nflag)
    478  1.17    cbiere 			return saved_errno;
    479   1.1     elric 	}
    480   1.1     elric 
    481   1.1     elric 	VPRINTF(1, ("%s (%s): clearing\n", *argv, buf));
    482   1.1     elric 
    483   1.1     elric 	if (nflag)
    484   1.1     elric 		return 0;
    485   1.1     elric 
    486   1.3     elric 	ret = unconfigure_fd(fd);
    487  1.32     pooka 	(void)prog_close(fd);
    488   1.3     elric 	return ret;
    489   1.3     elric }
    490   1.3     elric 
    491   1.3     elric static int
    492   1.3     elric unconfigure_fd(int fd)
    493   1.3     elric {
    494   1.3     elric 	struct	cgd_ioctl ci;
    495   1.3     elric 
    496  1.32     pooka 	if (prog_ioctl(fd, CGDIOCCLR, &ci) == -1) {
    497  1.17    cbiere 		warn("ioctl");
    498   1.3     elric 		return -1;
    499   1.1     elric 	}
    500   1.1     elric 
    501   1.1     elric 	return 0;
    502   1.1     elric }
    503   1.1     elric 
    504   1.5     elric /*ARGSUSED*/
    505   1.1     elric static int
    506   1.3     elric configure(int argc, char **argv, struct params *inparams, int flags)
    507   1.1     elric {
    508   1.5     elric 	struct params	*p;
    509  1.22     elric 	struct keygen	*kg;
    510   1.5     elric 	int		 fd;
    511  1.22     elric 	int		 loop = 0;
    512   1.5     elric 	int		 ret;
    513   1.5     elric 	char		 cgdname[PATH_MAX];
    514  1.38  christos 	char		 devicename[PATH_MAX];
    515  1.39  christos 	const char	*dev = NULL;	/* XXX: gcc */
    516  1.36   mlelstv 
    517  1.36   mlelstv 	if (argc == 2 || argc == 3) {
    518  1.38  christos 		dev = getfsspecname(devicename, sizeof(devicename), argv[1]);
    519  1.36   mlelstv 		if (dev == NULL) {
    520  1.38  christos 			warnx("getfsspecname failed: %s", devicename);
    521  1.36   mlelstv 			return -1;
    522  1.36   mlelstv 		}
    523  1.36   mlelstv 	}
    524   1.1     elric 
    525  1.34  christos 	if (argc == 2) {
    526  1.40  christos 		char pfile[MAXPATHLEN];
    527  1.36   mlelstv 
    528  1.36   mlelstv 		/* make string writable for basename */
    529  1.40  christos 		strlcpy(pfile, dev, sizeof(pfile));
    530  1.40  christos 		p = params_cget(basename(pfile));
    531  1.17    cbiere 	} else if (argc == 3) {
    532  1.17    cbiere 		p = params_cget(argv[2]);
    533  1.17    cbiere 	} else {
    534   1.1     elric 		/* print usage and exit, only if called from main() */
    535   1.5     elric 		if (flags == CONFIG_FLAGS_FROMMAIN) {
    536   1.5     elric 			warnx("wrong number of args");
    537   1.1     elric 			usage();
    538   1.5     elric 		}
    539   1.1     elric 		return -1;
    540   1.1     elric 	}
    541   1.1     elric 
    542   1.5     elric 	if (!p)
    543   1.5     elric 		return -1;
    544   1.2     elric 
    545   1.3     elric 	/*
    546   1.5     elric 	 * over-ride with command line specifications and fill in default
    547   1.5     elric 	 * values.
    548   1.3     elric 	 */
    549   1.3     elric 
    550   1.5     elric 	p = params_combine(p, inparams);
    551   1.5     elric 	ret = params_filldefaults(p);
    552   1.5     elric 	if (ret) {
    553   1.5     elric 		params_free(p);
    554   1.5     elric 		return ret;
    555   1.5     elric 	}
    556   1.5     elric 
    557   1.5     elric 	if (!params_verify(p)) {
    558   1.5     elric 		warnx("params invalid");
    559   1.5     elric 		return -1;
    560   1.5     elric 	}
    561   1.3     elric 
    562   1.3     elric 	/*
    563   1.3     elric 	 * loop over configuring the disk and checking to see if it
    564   1.3     elric 	 * verifies properly.  We open and close the disk device each
    565   1.3     elric 	 * time, because if the user passes us the block device we
    566   1.3     elric 	 * need to flush the buffer cache.
    567  1.22     elric 	 *
    568  1.22     elric 	 * We only loop if one of the verification methods prompts for
    569  1.22     elric 	 * a password.
    570   1.3     elric 	 */
    571   1.3     elric 
    572  1.22     elric 	for (kg = p->keygen; pflag == PFLAG_GETPASS && kg; kg = kg->next)
    573  1.22     elric 		if ((kg->kg_method == KEYGEN_PKCS5_PBKDF2_SHA1) ||
    574  1.22     elric 		    (kg->kg_method == KEYGEN_PKCS5_PBKDF2_OLD )) {
    575  1.22     elric 			loop = 1;
    576  1.22     elric 			break;
    577  1.22     elric 		}
    578  1.22     elric 
    579   1.3     elric 	for (;;) {
    580   1.3     elric 		fd = opendisk_werror(argv[0], cgdname, sizeof(cgdname));
    581   1.3     elric 		if (fd == -1)
    582   1.3     elric 			return -1;
    583   1.3     elric 
    584   1.5     elric 		if (p->key)
    585   1.5     elric 			bits_free(p->key);
    586   1.5     elric 
    587   1.5     elric 		p->key = getkey(argv[1], p->keygen, p->keylen);
    588   1.5     elric 		if (!p->key)
    589   1.3     elric 			goto bail_err;
    590   1.3     elric 
    591  1.36   mlelstv 		ret = configure_params(fd, cgdname, dev, p);
    592   1.3     elric 		if (ret)
    593   1.3     elric 			goto bail_err;
    594   1.3     elric 
    595   1.5     elric 		ret = verify(p, fd);
    596   1.3     elric 		if (ret == -1)
    597   1.3     elric 			goto bail_err;
    598   1.3     elric 		if (!ret)
    599   1.3     elric 			break;
    600   1.2     elric 
    601  1.19  christos 		(void)unconfigure_fd(fd);
    602  1.32     pooka 		(void)prog_close(fd);
    603  1.22     elric 
    604  1.22     elric 		if (!loop) {
    605  1.22     elric 			warnx("verification failed permanently");
    606  1.22     elric 			goto bail_err;
    607  1.22     elric 		}
    608  1.22     elric 
    609  1.22     elric 		warnx("verification failed, please reenter passphrase");
    610   1.3     elric 	}
    611   1.2     elric 
    612   1.5     elric 	params_free(p);
    613  1.32     pooka 	(void)prog_close(fd);
    614   1.3     elric 	return 0;
    615   1.3     elric bail_err:
    616   1.5     elric 	params_free(p);
    617  1.32     pooka 	(void)prog_close(fd);
    618   1.3     elric 	return -1;
    619   1.1     elric }
    620   1.1     elric 
    621   1.1     elric static int
    622   1.1     elric configure_stdin(struct params *p, int argc, char **argv)
    623   1.1     elric {
    624  1.36   mlelstv 	int		 fd;
    625  1.36   mlelstv 	int		 ret;
    626  1.36   mlelstv 	char		 cgdname[PATH_MAX];
    627  1.38  christos 	char		 devicename[PATH_MAX];
    628  1.36   mlelstv 	const char	*dev;
    629   1.1     elric 
    630   1.1     elric 	if (argc < 3 || argc > 4)
    631   1.1     elric 		usage();
    632   1.1     elric 
    633  1.38  christos 	dev = getfsspecname(devicename, sizeof(devicename), argv[1]);
    634  1.36   mlelstv 	if (dev == NULL) {
    635  1.38  christos 		warnx("getfsspecname failed: %s", devicename);
    636  1.36   mlelstv 		return -1;
    637  1.36   mlelstv 	}
    638  1.36   mlelstv 
    639   1.5     elric 	p->algorithm = string_fromcharstar(argv[2]);
    640  1.17    cbiere 	if (argc > 3) {
    641  1.19  christos 		size_t keylen;
    642  1.17    cbiere 
    643  1.19  christos 		if (parse_size_t(argv[3], &keylen) == -1) {
    644  1.17    cbiere 			warn("failed to parse key length");
    645  1.17    cbiere 			return -1;
    646  1.17    cbiere 		}
    647  1.17    cbiere 		p->keylen = keylen;
    648  1.17    cbiere 	}
    649   1.1     elric 
    650   1.1     elric 	ret = params_filldefaults(p);
    651   1.1     elric 	if (ret)
    652   1.1     elric 		return ret;
    653   1.1     elric 
    654   1.2     elric 	fd = opendisk_werror(argv[0], cgdname, sizeof(cgdname));
    655   1.2     elric 	if (fd == -1)
    656   1.2     elric 		return -1;
    657   1.2     elric 
    658   1.5     elric 	p->key = bits_fget(stdin, p->keylen);
    659   1.5     elric 	if (!p->key) {
    660   1.5     elric 		warnx("failed to read key from stdin");
    661   1.1     elric 		return -1;
    662   1.5     elric 	}
    663   1.1     elric 
    664  1.36   mlelstv 	return configure_params(fd, cgdname, dev, p);
    665   1.1     elric }
    666   1.1     elric 
    667   1.1     elric static int
    668  1.17    cbiere opendisk_werror(const char *cgd, char *buf, size_t buflen)
    669   1.2     elric {
    670   1.2     elric 	int	fd;
    671   1.2     elric 
    672  1.18    cbiere 	VPRINTF(3, ("opendisk_werror(%s, %s, %zu) called.\n", cgd, buf, buflen));
    673   1.5     elric 
    674   1.2     elric 	/* sanity */
    675   1.2     elric 	if (!cgd || !buf)
    676   1.2     elric 		return -1;
    677   1.2     elric 
    678   1.2     elric 	if (nflag) {
    679  1.17    cbiere 		if (strlcpy(buf, cgd, buflen) >= buflen)
    680  1.17    cbiere 			return -1;
    681   1.2     elric 		return 0;
    682   1.2     elric 	}
    683   1.2     elric 
    684  1.32     pooka 	fd = opendisk1(cgd, O_RDWR, buf, buflen, 0, prog_open);
    685   1.2     elric 	if (fd == -1)
    686   1.5     elric 		warnx("can't open cgd \"%s\", \"%s\"", cgd, buf);
    687   1.5     elric 
    688   1.2     elric 	return fd;
    689   1.2     elric }
    690   1.2     elric 
    691   1.2     elric static int
    692   1.2     elric configure_params(int fd, const char *cgd, const char *dev, struct params *p)
    693   1.1     elric {
    694   1.1     elric 	struct cgd_ioctl ci;
    695   1.1     elric 
    696   1.1     elric 	/* sanity */
    697   1.1     elric 	if (!cgd || !dev)
    698   1.1     elric 		return -1;
    699   1.1     elric 
    700  1.19  christos 	(void)memset(&ci, 0x0, sizeof(ci));
    701  1.16  christos 	ci.ci_disk = dev;
    702  1.16  christos 	ci.ci_alg = string_tocharstar(p->algorithm);
    703  1.16  christos 	ci.ci_ivmethod = string_tocharstar(p->ivmeth);
    704  1.16  christos 	ci.ci_key = bits_getbuf(p->key);
    705   1.1     elric 	ci.ci_keylen = p->keylen;
    706   1.1     elric 	ci.ci_blocksize = p->bsize;
    707   1.1     elric 
    708  1.20    martin 	VPRINTF(1, ("    with alg %s keylen %zu blocksize %zu ivmethod %s\n",
    709   1.5     elric 	    string_tocharstar(p->algorithm), p->keylen, p->bsize,
    710   1.5     elric 	    string_tocharstar(p->ivmeth)));
    711   1.5     elric 	VPRINTF(2, ("key: "));
    712   1.5     elric 	VERBOSE(2, bits_fprint(stdout, p->key));
    713   1.5     elric 	VPRINTF(2, ("\n"));
    714   1.1     elric 
    715   1.1     elric 	if (nflag)
    716   1.1     elric 		return 0;
    717   1.1     elric 
    718  1.32     pooka 	if (prog_ioctl(fd, CGDIOCSET, &ci) == -1) {
    719  1.17    cbiere 		int saved_errno = errno;
    720  1.17    cbiere 		warn("ioctl");
    721  1.17    cbiere 		return saved_errno;
    722   1.1     elric 	}
    723   1.1     elric 
    724   1.1     elric 	return 0;
    725   1.1     elric }
    726   1.1     elric 
    727   1.3     elric /*
    728   1.3     elric  * verify returns 0 for success, -1 for unrecoverable error, or 1 for retry.
    729   1.3     elric  */
    730   1.3     elric 
    731   1.3     elric #define SCANSIZE	8192
    732   1.3     elric 
    733   1.3     elric static int
    734   1.3     elric verify(struct params *p, int fd)
    735   1.3     elric {
    736   1.3     elric 
    737   1.3     elric 	switch (p->verify_method) {
    738   1.3     elric 	case VERIFY_NONE:
    739   1.3     elric 		return 0;
    740   1.3     elric 	case VERIFY_DISKLABEL:
    741   1.5     elric 		return verify_disklabel(fd);
    742   1.5     elric 	case VERIFY_FFS:
    743   1.5     elric 		return verify_ffs(fd);
    744   1.9        cb 	case VERIFY_REENTER:
    745   1.9        cb 		return verify_reenter(p);
    746  1.37   mlelstv 	case VERIFY_MBR:
    747  1.37   mlelstv 		return verify_mbr(fd);
    748  1.37   mlelstv 	case VERIFY_GPT:
    749  1.37   mlelstv 		return verify_gpt(fd);
    750   1.3     elric 	default:
    751   1.5     elric 		warnx("unimplemented verification method");
    752   1.3     elric 		return -1;
    753   1.3     elric 	}
    754   1.5     elric }
    755   1.5     elric 
    756   1.5     elric static int
    757   1.5     elric verify_disklabel(int fd)
    758   1.5     elric {
    759   1.5     elric 	struct	disklabel l;
    760  1.17    cbiere 	ssize_t	ret;
    761   1.5     elric 	char	buf[SCANSIZE];
    762   1.3     elric 
    763   1.3     elric 	/*
    764   1.3     elric 	 * we simply scan the first few blocks for a disklabel, ignoring
    765   1.3     elric 	 * any MBR/filecore sorts of logic.  MSDOS and RiscOS can't read
    766   1.3     elric 	 * a cgd, anyway, so it is unlikely that there will be non-native
    767   1.3     elric 	 * partition information.
    768   1.3     elric 	 */
    769   1.3     elric 
    770  1.37   mlelstv 	ret = prog_pread(fd, buf, SCANSIZE, 0);
    771  1.17    cbiere 	if (ret < 0) {
    772   1.5     elric 		warn("can't read disklabel area");
    773   1.3     elric 		return -1;
    774   1.3     elric 	}
    775   1.3     elric 
    776   1.3     elric 	/* now scan for the disklabel */
    777   1.3     elric 
    778  1.17    cbiere 	return disklabel_scan(&l, buf, (size_t)ret);
    779   1.3     elric }
    780   1.3     elric 
    781  1.37   mlelstv static int
    782  1.37   mlelstv verify_mbr(int fd)
    783  1.37   mlelstv {
    784  1.37   mlelstv 	struct mbr_sector mbr;
    785  1.37   mlelstv 	ssize_t	ret;
    786  1.37   mlelstv 	char	buf[SCANSIZE];
    787  1.37   mlelstv 
    788  1.37   mlelstv 	/*
    789  1.37   mlelstv 	 * we read the first blocks to avoid sector size issues and
    790  1.37   mlelstv 	 * verify the MBR in the beginning
    791  1.37   mlelstv 	 */
    792  1.37   mlelstv 
    793  1.37   mlelstv 	ret = prog_pread(fd, buf, SCANSIZE, 0);
    794  1.37   mlelstv 	if (ret < 0) {
    795  1.37   mlelstv 		warn("can't read mbr area");
    796  1.37   mlelstv 		return -1;
    797  1.37   mlelstv 	}
    798  1.37   mlelstv 
    799  1.37   mlelstv 	memcpy(&mbr, buf, sizeof(mbr));
    800  1.37   mlelstv 	if (le16toh(mbr.mbr_magic) != MBR_MAGIC)
    801  1.37   mlelstv 		return -1;
    802  1.37   mlelstv 
    803  1.37   mlelstv 	return 0;
    804  1.37   mlelstv }
    805  1.37   mlelstv 
    806  1.37   mlelstv static uint32_t crc32_tab[] = {
    807  1.37   mlelstv 	0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
    808  1.37   mlelstv 	0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
    809  1.37   mlelstv 	0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
    810  1.37   mlelstv 	0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
    811  1.37   mlelstv 	0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
    812  1.37   mlelstv 	0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
    813  1.37   mlelstv 	0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
    814  1.37   mlelstv 	0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
    815  1.37   mlelstv 	0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
    816  1.37   mlelstv 	0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
    817  1.37   mlelstv 	0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
    818  1.37   mlelstv 	0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
    819  1.37   mlelstv 	0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
    820  1.37   mlelstv 	0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
    821  1.37   mlelstv 	0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
    822  1.37   mlelstv 	0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
    823  1.37   mlelstv 	0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
    824  1.37   mlelstv 	0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
    825  1.37   mlelstv 	0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
    826  1.37   mlelstv 	0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
    827  1.37   mlelstv 	0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
    828  1.37   mlelstv 	0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
    829  1.37   mlelstv 	0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
    830  1.37   mlelstv 	0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
    831  1.37   mlelstv 	0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
    832  1.37   mlelstv 	0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
    833  1.37   mlelstv 	0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
    834  1.37   mlelstv 	0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
    835  1.37   mlelstv 	0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
    836  1.37   mlelstv 	0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
    837  1.37   mlelstv 	0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
    838  1.37   mlelstv 	0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
    839  1.37   mlelstv 	0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
    840  1.37   mlelstv 	0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
    841  1.37   mlelstv 	0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
    842  1.37   mlelstv 	0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
    843  1.37   mlelstv 	0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
    844  1.37   mlelstv 	0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
    845  1.37   mlelstv 	0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
    846  1.37   mlelstv 	0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
    847  1.37   mlelstv 	0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
    848  1.37   mlelstv 	0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
    849  1.37   mlelstv 	0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
    850  1.37   mlelstv };
    851  1.37   mlelstv 
    852  1.37   mlelstv static uint32_t
    853  1.37   mlelstv crc32(const void *buf, size_t size)
    854  1.37   mlelstv {
    855  1.37   mlelstv 	const uint8_t *p;
    856  1.37   mlelstv 	uint32_t crc;
    857  1.37   mlelstv 
    858  1.37   mlelstv 	p = buf;
    859  1.37   mlelstv 	crc = ~0U;
    860  1.37   mlelstv 
    861  1.37   mlelstv 	while (size--)
    862  1.37   mlelstv 		crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
    863  1.37   mlelstv 
    864  1.37   mlelstv 	return crc ^ ~0U;
    865  1.37   mlelstv }
    866  1.37   mlelstv 
    867  1.37   mlelstv static int
    868  1.37   mlelstv verify_gpt(int fd)
    869  1.37   mlelstv {
    870  1.37   mlelstv 	struct	 gpt_hdr hdr;
    871  1.37   mlelstv 	ssize_t	 ret;
    872  1.37   mlelstv 	char	 buf[SCANSIZE];
    873  1.37   mlelstv 	unsigned blksize;
    874  1.37   mlelstv 	size_t	 off;
    875  1.37   mlelstv 
    876  1.37   mlelstv 	/*
    877  1.37   mlelstv 	 * we read the first blocks to avoid sector size issues and
    878  1.37   mlelstv 	 * verify the GPT header.
    879  1.37   mlelstv 	 */
    880  1.37   mlelstv 
    881  1.37   mlelstv 	ret = prog_pread(fd, buf, SCANSIZE, 0);
    882  1.37   mlelstv 	if (ret < 0) {
    883  1.37   mlelstv 		warn("can't read gpt area");
    884  1.37   mlelstv 		return -1;
    885  1.37   mlelstv 	}
    886  1.37   mlelstv 
    887  1.37   mlelstv 	ret = -1;
    888  1.37   mlelstv 	for (blksize=DEV_BSIZE;
    889  1.37   mlelstv              (off = blksize * GPT_HDR_BLKNO) <= SCANSIZE - sizeof(hdr);
    890  1.37   mlelstv              blksize <<= 1) {
    891  1.37   mlelstv 
    892  1.37   mlelstv 		memcpy(&hdr, &buf[off], sizeof(hdr));
    893  1.37   mlelstv 		if (memcmp(hdr.hdr_sig, GPT_HDR_SIG, sizeof(hdr.hdr_sig)) == 0 &&
    894  1.37   mlelstv 		    le32toh(hdr.hdr_revision) == GPT_HDR_REVISION &&
    895  1.37   mlelstv 		    le32toh(hdr.hdr_size) == GPT_HDR_SIZE) {
    896  1.37   mlelstv 
    897  1.37   mlelstv 			hdr.hdr_crc_self = 0;
    898  1.37   mlelstv 			if (crc32(&hdr, sizeof(hdr))) {
    899  1.37   mlelstv 				ret = 0;
    900  1.37   mlelstv 				break;
    901  1.37   mlelstv 			}
    902  1.37   mlelstv 		}
    903  1.37   mlelstv 	}
    904  1.37   mlelstv 
    905  1.37   mlelstv 	return ret;
    906  1.37   mlelstv }
    907  1.37   mlelstv 
    908   1.7      fvdl static off_t sblock_try[] = SBLOCKSEARCH;
    909   1.7      fvdl 
    910   1.1     elric static int
    911   1.5     elric verify_ffs(int fd)
    912   1.5     elric {
    913  1.19  christos 	size_t	i;
    914   1.5     elric 
    915   1.7      fvdl 	for (i = 0; sblock_try[i] != -1; i++) {
    916  1.19  christos 		union {
    917  1.19  christos 		    char	buf[SBLOCKSIZE];
    918  1.19  christos 		    struct	fs fs;
    919  1.19  christos 		} u;
    920  1.17    cbiere 		ssize_t ret;
    921  1.17    cbiere 
    922  1.32     pooka 		ret = prog_pread(fd, &u, sizeof(u), sblock_try[i]);
    923  1.17    cbiere 		if (ret < 0) {
    924   1.7      fvdl 			warn("pread");
    925  1.17    cbiere 			break;
    926  1.19  christos 		} else if ((size_t)ret < sizeof(u)) {
    927  1.17    cbiere 			warnx("pread: incomplete block");
    928  1.17    cbiere 			break;
    929   1.7      fvdl 		}
    930  1.19  christos 		switch (u.fs.fs_magic) {
    931   1.7      fvdl 		case FS_UFS1_MAGIC:
    932   1.7      fvdl 		case FS_UFS2_MAGIC:
    933   1.7      fvdl 		case FS_UFS1_MAGIC_SWAPPED:
    934   1.7      fvdl 		case FS_UFS2_MAGIC_SWAPPED:
    935   1.7      fvdl 			return 0;
    936   1.7      fvdl 		default:
    937   1.7      fvdl 			continue;
    938   1.7      fvdl 		}
    939   1.5     elric 	}
    940  1.17    cbiere 
    941  1.17    cbiere 	return 1;	/* failure */
    942   1.9        cb }
    943   1.9        cb 
    944   1.9        cb static int
    945   1.9        cb verify_reenter(struct params *p)
    946   1.9        cb {
    947   1.9        cb 	struct keygen *kg;
    948   1.9        cb 	bits_t *orig_key, *key;
    949   1.9        cb 	int ret;
    950   1.9        cb 
    951   1.9        cb 	ret = 0;
    952   1.9        cb 	for (kg = p->keygen; kg && !ret; kg = kg->next) {
    953  1.29     elric 		if ((kg->kg_method != KEYGEN_PKCS5_PBKDF2_SHA1) &&
    954  1.10       dan 		    (kg->kg_method != KEYGEN_PKCS5_PBKDF2_OLD ))
    955   1.9        cb 			continue;
    956   1.9        cb 
    957   1.9        cb 		orig_key = kg->kg_key;
    958   1.9        cb 		kg->kg_key = NULL;
    959   1.9        cb 
    960  1.10       dan 		/* add a compat flag till the _OLD method goes away */
    961   1.9        cb 		key = getkey_pkcs5_pbkdf2("re-enter device", kg,
    962  1.10       dan 			bits_len(orig_key), kg->kg_method == KEYGEN_PKCS5_PBKDF2_OLD);
    963   1.9        cb 		ret = !bits_match(key, orig_key);
    964   1.9        cb 
    965   1.9        cb 		bits_free(key);
    966   1.9        cb 		bits_free(kg->kg_key);
    967   1.9        cb 		kg->kg_key = orig_key;
    968   1.9        cb 	}
    969   1.9        cb 
    970   1.9        cb 	return ret;
    971   1.5     elric }
    972   1.5     elric 
    973   1.5     elric static int
    974   1.1     elric generate(struct params *p, int argc, char **argv, const char *outfile)
    975   1.1     elric {
    976   1.1     elric 	int	 ret;
    977   1.1     elric 
    978   1.1     elric 	if (argc < 1 || argc > 2)
    979   1.1     elric 		usage();
    980   1.1     elric 
    981   1.5     elric 	p->algorithm = string_fromcharstar(argv[0]);
    982  1.17    cbiere 	if (argc > 1) {
    983  1.19  christos 		size_t keylen;
    984  1.17    cbiere 
    985  1.19  christos 		if (parse_size_t(argv[1], &keylen) == -1) {
    986  1.17    cbiere 			warn("Failed to parse key length");
    987  1.17    cbiere 			return -1;
    988  1.17    cbiere 		}
    989  1.17    cbiere 		p->keylen = keylen;
    990  1.17    cbiere 	}
    991   1.5     elric 
    992   1.5     elric 	ret = params_filldefaults(p);
    993   1.1     elric 	if (ret)
    994   1.1     elric 		return ret;
    995   1.5     elric 
    996   1.5     elric 	if (!p->keygen) {
    997  1.10       dan 		p->keygen = keygen_generate(KEYGEN_PKCS5_PBKDF2_SHA1);
    998   1.5     elric 		if (!p->keygen)
    999   1.5     elric 			return -1;
   1000   1.5     elric 	}
   1001   1.5     elric 
   1002   1.5     elric 	if (keygen_filldefaults(p->keygen, p->keylen)) {
   1003   1.5     elric 		warnx("Failed to generate defaults for keygen");
   1004   1.5     elric 		return -1;
   1005   1.5     elric 	}
   1006   1.5     elric 
   1007   1.5     elric 	if (!params_verify(p)) {
   1008   1.5     elric 		warnx("invalid parameters generated");
   1009   1.5     elric 		return -1;
   1010   1.5     elric 	}
   1011   1.5     elric 
   1012   1.5     elric 	return params_cput(p, outfile);
   1013   1.5     elric }
   1014   1.5     elric 
   1015   1.5     elric static int
   1016   1.5     elric generate_convert(struct params *p, int argc, char **argv, const char *outfile)
   1017   1.5     elric {
   1018   1.5     elric 	struct params	*oldp;
   1019   1.5     elric 	struct keygen	*kg;
   1020   1.5     elric 
   1021   1.5     elric 	if (argc != 1)
   1022   1.5     elric 		usage();
   1023   1.5     elric 
   1024   1.5     elric 	oldp = params_cget(*argv);
   1025   1.5     elric 	if (!oldp)
   1026   1.5     elric 		return -1;
   1027   1.5     elric 
   1028   1.5     elric 	/* for sanity, we ensure that none of the keygens are randomkey */
   1029   1.5     elric 	for (kg=p->keygen; kg; kg=kg->next)
   1030  1.30     elric 		if ((kg->kg_method == KEYGEN_RANDOMKEY) ||
   1031  1.30     elric 		    (kg->kg_method == KEYGEN_URANDOMKEY)) {
   1032  1.30     elric 			warnx("can't preserve randomly generated key");
   1033   1.5     elric 			goto bail;
   1034  1.30     elric 		}
   1035   1.5     elric 	for (kg=oldp->keygen; kg; kg=kg->next)
   1036  1.30     elric 		if ((kg->kg_method == KEYGEN_RANDOMKEY) ||
   1037  1.30     elric 		    (kg->kg_method == KEYGEN_URANDOMKEY)) {
   1038  1.30     elric 			warnx("can't preserve randomly generated key");
   1039   1.5     elric 			goto bail;
   1040  1.30     elric 		}
   1041   1.5     elric 
   1042   1.5     elric 	if (!params_verify(oldp)) {
   1043   1.5     elric 		warnx("invalid old parameters file \"%s\"", *argv);
   1044   1.5     elric 		return -1;
   1045   1.1     elric 	}
   1046   1.1     elric 
   1047   1.5     elric 	oldp->key = getkey("old file", oldp->keygen, oldp->keylen);
   1048   1.5     elric 
   1049   1.5     elric 	/* we copy across the non-keygen info, here. */
   1050   1.5     elric 
   1051   1.5     elric 	string_free(p->algorithm);
   1052   1.5     elric 	string_free(p->ivmeth);
   1053   1.5     elric 
   1054   1.5     elric 	p->algorithm = string_dup(oldp->algorithm);
   1055   1.5     elric 	p->ivmeth = string_dup(oldp->ivmeth);
   1056   1.5     elric 	p->keylen = oldp->keylen;
   1057   1.5     elric 	p->bsize = oldp->bsize;
   1058   1.5     elric 	if (p->verify_method == VERIFY_UNKNOWN)
   1059   1.5     elric 		p->verify_method = oldp->verify_method;
   1060   1.5     elric 
   1061   1.5     elric 	params_free(oldp);
   1062   1.1     elric 
   1063   1.5     elric 	if (!p->keygen) {
   1064  1.10       dan 		p->keygen = keygen_generate(KEYGEN_PKCS5_PBKDF2_SHA1);
   1065   1.5     elric 		if (!p->keygen)
   1066   1.1     elric 			return -1;
   1067   1.5     elric 	}
   1068  1.19  christos 	(void)params_filldefaults(p);
   1069  1.19  christos 	(void)keygen_filldefaults(p->keygen, p->keylen);
   1070   1.5     elric 	p->key = getkey("new file", p->keygen, p->keylen);
   1071   1.5     elric 
   1072   1.5     elric 	kg = keygen_generate(KEYGEN_STOREDKEY);
   1073   1.5     elric 	kg->kg_key = bits_xor(p->key, oldp->key);
   1074   1.5     elric 	keygen_addlist(&p->keygen, kg);
   1075   1.5     elric 
   1076   1.5     elric 	if (!params_verify(p)) {
   1077   1.5     elric 		warnx("can't generate new parameters file");
   1078   1.5     elric 		return -1;
   1079   1.1     elric 	}
   1080   1.1     elric 
   1081   1.5     elric 	return params_cput(p, outfile);
   1082   1.5     elric bail:
   1083   1.5     elric 	params_free(oldp);
   1084   1.5     elric 	return -1;
   1085   1.1     elric }
   1086   1.1     elric 
   1087   1.1     elric static int
   1088  1.19  christos /*ARGSUSED*/
   1089   1.1     elric do_all(const char *cfile, int argc, char **argv,
   1090   1.3     elric        int (*conf)(int, char **, struct params *, int))
   1091   1.1     elric {
   1092   1.1     elric 	FILE		 *f;
   1093   1.1     elric 	size_t		  len;
   1094   1.1     elric 	size_t		  lineno;
   1095   1.1     elric 	int		  my_argc;
   1096   1.1     elric 	int		  ret;
   1097   1.1     elric 	const char	 *fn;
   1098   1.1     elric 	char		 *line;
   1099   1.1     elric 	char		**my_argv;
   1100   1.1     elric 
   1101   1.1     elric 	if (argc > 0)
   1102   1.1     elric 		usage();
   1103   1.1     elric 
   1104   1.1     elric 	if (!cfile[0])
   1105   1.1     elric 		fn = CGDCONFIG_CFILE;
   1106   1.1     elric 	else
   1107   1.1     elric 		fn = cfile;
   1108   1.1     elric 
   1109   1.1     elric 	f = fopen(fn, "r");
   1110   1.1     elric 	if (!f) {
   1111   1.5     elric 		warn("could not open config file \"%s\"", fn);
   1112   1.1     elric 		return -1;
   1113   1.1     elric 	}
   1114   1.1     elric 
   1115   1.1     elric 	ret = 0;
   1116   1.1     elric 	lineno = 0;
   1117   1.1     elric 	for (;;) {
   1118   1.1     elric 		line = fparseln(f, &len, &lineno, "\\\\#", FPARSELN_UNESCALL);
   1119   1.1     elric 		if (!line)
   1120   1.1     elric 			break;
   1121   1.1     elric 		if (!*line)
   1122   1.1     elric 			continue;
   1123   1.1     elric 
   1124   1.1     elric 		my_argv = words(line, &my_argc);
   1125   1.3     elric 		ret = conf(my_argc, my_argv, NULL, CONFIG_FLAGS_FROMALL);
   1126   1.1     elric 		if (ret) {
   1127   1.5     elric 			warnx("action failed on \"%s\" line %lu", fn,
   1128   1.1     elric 			    (u_long)lineno);
   1129   1.1     elric 			break;
   1130   1.1     elric 		}
   1131   1.1     elric 		words_free(my_argv, my_argc);
   1132   1.1     elric 	}
   1133   1.1     elric 	return ret;
   1134   1.1     elric }
   1135  1.13     elric 
   1136  1.34  christos static const char *
   1137  1.34  christos iv_method(int mode)
   1138  1.34  christos {
   1139  1.34  christos 
   1140  1.34  christos 	switch (mode) {
   1141  1.34  christos 	case CGD_CIPHER_CBC_ENCBLKNO8:
   1142  1.34  christos 		return "encblkno8";
   1143  1.34  christos 	case CGD_CIPHER_CBC_ENCBLKNO1:
   1144  1.34  christos 		return "encblkno1";
   1145  1.34  christos 	default:
   1146  1.34  christos 		return "unknown";
   1147  1.34  christos 	}
   1148  1.34  christos }
   1149  1.34  christos 
   1150  1.35  christos 
   1151  1.35  christos static void
   1152  1.35  christos show(const char *dev) {
   1153  1.35  christos 	char path[64];
   1154  1.35  christos 	struct cgd_user cgu;
   1155  1.35  christos 	int fd;
   1156  1.35  christos 
   1157  1.35  christos 	fd = opendisk(dev, O_RDONLY, path, sizeof(path), 0);
   1158  1.35  christos 	if (fd == -1) {
   1159  1.35  christos 		warn("open: %s", dev);
   1160  1.35  christos 		return;
   1161  1.35  christos 	}
   1162  1.35  christos 
   1163  1.35  christos 	cgu.cgu_unit = -1;
   1164  1.35  christos 	if (prog_ioctl(fd, CGDIOCGET, &cgu) == -1) {
   1165  1.35  christos 		close(fd);
   1166  1.35  christos 		err(1, "CGDIOCGET");
   1167  1.35  christos 	}
   1168  1.35  christos 
   1169  1.35  christos 	printf("%s: ", dev);
   1170  1.35  christos 
   1171  1.35  christos 	if (cgu.cgu_dev == 0) {
   1172  1.35  christos 		printf("not in use");
   1173  1.35  christos 		goto out;
   1174  1.35  christos 	}
   1175  1.35  christos 
   1176  1.35  christos 	dev = devname(cgu.cgu_dev, S_IFBLK);
   1177  1.35  christos 	if (dev != NULL)
   1178  1.35  christos 		printf("%s ", dev);
   1179  1.35  christos 	else
   1180  1.35  christos 		printf("dev %llu,%llu ", (unsigned long long)major(cgu.cgu_dev),
   1181  1.35  christos 		    (unsigned long long)minor(cgu.cgu_dev));
   1182  1.35  christos 
   1183  1.35  christos 	if (verbose)
   1184  1.35  christos 		printf("%s ", cgu.cgu_alg);
   1185  1.35  christos 	if (verbose > 1) {
   1186  1.35  christos 		printf("keylen %d ", cgu.cgu_keylen);
   1187  1.35  christos 		printf("blksize %zd ", cgu.cgu_blocksize);
   1188  1.35  christos 		printf("%s ", iv_method(cgu.cgu_mode));
   1189  1.35  christos 	}
   1190  1.35  christos 
   1191  1.35  christos out:
   1192  1.35  christos 	putchar('\n');
   1193  1.35  christos 	close(fd);
   1194  1.35  christos }
   1195  1.35  christos 
   1196  1.34  christos static int
   1197  1.34  christos do_list(int argc, char **argv)
   1198  1.34  christos {
   1199  1.34  christos 
   1200  1.34  christos 	if (argc != 0 && argc != 1)
   1201  1.34  christos 		usage();
   1202  1.34  christos 
   1203  1.35  christos 	if (argc) {
   1204  1.35  christos 		show(argv[0]);
   1205  1.35  christos 		return 0;
   1206  1.35  christos 	}
   1207  1.34  christos 
   1208  1.35  christos 	DIR *dirp;
   1209  1.35  christos 	struct dirent *dp;
   1210  1.35  christos 	__BITMAP_TYPE(, uint32_t, 65536) bm;
   1211  1.35  christos 
   1212  1.35  christos 	__BITMAP_ZERO(&bm);
   1213  1.35  christos 
   1214  1.35  christos 	if ((dirp = opendir(_PATH_DEV)) == NULL)
   1215  1.35  christos 		err(1, "opendir: %s", _PATH_DEV);
   1216  1.35  christos 
   1217  1.35  christos 	while ((dp = readdir(dirp)) != NULL) {
   1218  1.35  christos 		char *ep;
   1219  1.35  christos 		if (strncmp(dp->d_name, "rcgd", 4) != 0)
   1220  1.35  christos 			continue;
   1221  1.35  christos 		errno = 0;
   1222  1.35  christos 		int n = (int)strtol(dp->d_name + 4, &ep, 0);
   1223  1.35  christos 		if (ep == dp->d_name + 4 || errno != 0) {
   1224  1.35  christos 			warnx("bad name %s", dp->d_name);
   1225  1.35  christos 			continue;
   1226  1.34  christos 		}
   1227  1.35  christos 		*ep = '\0';
   1228  1.35  christos 		if (__BITMAP_ISSET(n, &bm))
   1229  1.35  christos 			continue;
   1230  1.35  christos 		__BITMAP_SET(n, &bm);
   1231  1.35  christos 		show(dp->d_name + 1);
   1232  1.34  christos 	}
   1233  1.34  christos 
   1234  1.35  christos 	closedir(dirp);
   1235  1.34  christos 	return 0;
   1236  1.34  christos }
   1237  1.34  christos 
   1238  1.13     elric static void
   1239  1.13     elric eliminate_cores(void)
   1240  1.13     elric {
   1241  1.13     elric 	struct rlimit	rlp;
   1242  1.13     elric 
   1243  1.13     elric 	rlp.rlim_cur = 0;
   1244  1.13     elric 	rlp.rlim_max = 0;
   1245  1.17    cbiere 	if (setrlimit(RLIMIT_CORE, &rlp) == -1)
   1246  1.13     elric 		err(EXIT_FAILURE, "Can't disable cores");
   1247  1.13     elric }
   1248