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