1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2004-2010 Pawel Jakub Dawidek <pjd@FreeBSD.org> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 __FBSDID("$FreeBSD$"); 31 32 #include <sys/param.h> 33 #include <sys/mman.h> 34 #include <sys/sysctl.h> 35 #include <sys/resource.h> 36 #include <opencrypto/cryptodev.h> 37 38 #include <assert.h> 39 #include <err.h> 40 #include <errno.h> 41 #include <fcntl.h> 42 #include <libgeom.h> 43 #include <paths.h> 44 #include <readpassphrase.h> 45 #include <stdbool.h> 46 #include <stdint.h> 47 #include <stdio.h> 48 #include <stdlib.h> 49 #include <string.h> 50 #include <strings.h> 51 #include <unistd.h> 52 53 #include <geom/eli/g_eli.h> 54 #include <geom/eli/pkcs5v2.h> 55 56 #include "core/geom.h" 57 #include "misc/subr.h" 58 59 60 uint32_t lib_version = G_LIB_VERSION; 61 uint32_t version = G_ELI_VERSION; 62 63 #define GELI_BACKUP_DIR "/var/backups/" 64 #define GELI_ENC_ALGO "aes" 65 #define BUFSIZE 1024 66 67 /* 68 * Passphrase cached when attaching multiple providers, in order to be more 69 * user-friendly if they are using the same passphrase. 70 */ 71 static char cached_passphrase[BUFSIZE] = ""; 72 73 static void eli_main(struct gctl_req *req, unsigned flags); 74 static void eli_init(struct gctl_req *req); 75 static void eli_attach(struct gctl_req *req); 76 static void eli_configure(struct gctl_req *req); 77 static void eli_setkey(struct gctl_req *req); 78 static void eli_delkey(struct gctl_req *req); 79 static void eli_resume(struct gctl_req *req); 80 static void eli_kill(struct gctl_req *req); 81 static void eli_backup(struct gctl_req *req); 82 static void eli_restore(struct gctl_req *req); 83 static void eli_resize(struct gctl_req *req); 84 static void eli_version(struct gctl_req *req); 85 static void eli_clear(struct gctl_req *req); 86 static void eli_dump(struct gctl_req *req); 87 88 static int eli_backup_create(struct gctl_req *req, const char *prov, 89 const char *file); 90 91 /* 92 * Available commands: 93 * 94 * init [-bdgPTv] [-a aalgo] [-B backupfile] [-e ealgo] [-i iterations] [-l keylen] [-J newpassfile] [-K newkeyfile] [-s sectorsize] [-V version] prov 95 * label - alias for 'init' 96 * attach [-Cdprv] [-n keyno] [-j passfile] [-k keyfile] prov ... 97 * detach [-fl] prov ... 98 * stop - alias for 'detach' 99 * onetime [-d] [-a aalgo] [-e ealgo] [-l keylen] prov 100 * configure [-bBgGtT] prov ... 101 * setkey [-pPv] [-n keyno] [-j passfile] [-J newpassfile] [-k keyfile] [-K newkeyfile] prov 102 * delkey [-afv] [-n keyno] prov 103 * suspend [-v] -a | prov ... 104 * resume [-pv] [-j passfile] [-k keyfile] prov 105 * kill [-av] [prov ...] 106 * backup [-v] prov file 107 * restore [-fv] file prov 108 * resize [-v] -s oldsize prov 109 * version [prov ...] 110 * clear [-v] prov ... 111 * dump [-v] prov ... 112 */ 113 struct g_command class_commands[] = { 114 { "init", G_FLAG_VERBOSE, eli_main, 115 { 116 { 'a', "aalgo", "", G_TYPE_STRING }, 117 { 'b', "boot", NULL, G_TYPE_BOOL }, 118 { 'B', "backupfile", "", G_TYPE_STRING }, 119 { 'd', "displaypass", NULL, G_TYPE_BOOL }, 120 { 'e', "ealgo", "", G_TYPE_STRING }, 121 { 'g', "geliboot", NULL, G_TYPE_BOOL }, 122 { 'i', "iterations", "-1", G_TYPE_NUMBER }, 123 { 'J', "newpassfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI }, 124 { 'K', "newkeyfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI }, 125 { 'l', "keylen", "0", G_TYPE_NUMBER }, 126 { 'P', "nonewpassphrase", NULL, G_TYPE_BOOL }, 127 { 's', "sectorsize", "0", G_TYPE_NUMBER }, 128 { 'T', "notrim", NULL, G_TYPE_BOOL }, 129 { 'V', "mdversion", "-1", G_TYPE_NUMBER }, 130 G_OPT_SENTINEL 131 }, 132 "[-bdgPTv] [-a aalgo] [-B backupfile] [-e ealgo] [-i iterations] [-l keylen] [-J newpassfile] [-K newkeyfile] [-s sectorsize] [-V version] prov" 133 }, 134 { "label", G_FLAG_VERBOSE, eli_main, 135 { 136 { 'a', "aalgo", "", G_TYPE_STRING }, 137 { 'b', "boot", NULL, G_TYPE_BOOL }, 138 { 'B', "backupfile", "", G_TYPE_STRING }, 139 { 'd', "displaypass", NULL, G_TYPE_BOOL }, 140 { 'e', "ealgo", "", G_TYPE_STRING }, 141 { 'g', "geliboot", NULL, G_TYPE_BOOL }, 142 { 'i', "iterations", "-1", G_TYPE_NUMBER }, 143 { 'J', "newpassfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI }, 144 { 'K', "newkeyfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI }, 145 { 'l', "keylen", "0", G_TYPE_NUMBER }, 146 { 'P', "nonewpassphrase", NULL, G_TYPE_BOOL }, 147 { 's', "sectorsize", "0", G_TYPE_NUMBER }, 148 { 'V', "mdversion", "-1", G_TYPE_NUMBER }, 149 G_OPT_SENTINEL 150 }, 151 "- an alias for 'init'" 152 }, 153 { "attach", G_FLAG_VERBOSE | G_FLAG_LOADKLD, eli_main, 154 { 155 { 'C', "dryrun", NULL, G_TYPE_BOOL }, 156 { 'd', "detach", NULL, G_TYPE_BOOL }, 157 { 'j', "passfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI }, 158 { 'k', "keyfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI }, 159 { 'n', "keyno", "-1", G_TYPE_NUMBER }, 160 { 'p', "nopassphrase", NULL, G_TYPE_BOOL }, 161 { 'r', "readonly", NULL, G_TYPE_BOOL }, 162 G_OPT_SENTINEL 163 }, 164 "[-Cdprv] [-n keyno] [-j passfile] [-k keyfile] prov ..." 165 }, 166 { "detach", 0, NULL, 167 { 168 { 'f', "force", NULL, G_TYPE_BOOL }, 169 { 'l', "last", NULL, G_TYPE_BOOL }, 170 G_OPT_SENTINEL 171 }, 172 "[-fl] prov ..." 173 }, 174 { "stop", 0, NULL, 175 { 176 { 'f', "force", NULL, G_TYPE_BOOL }, 177 { 'l', "last", NULL, G_TYPE_BOOL }, 178 G_OPT_SENTINEL 179 }, 180 "- an alias for 'detach'" 181 }, 182 { "onetime", G_FLAG_VERBOSE | G_FLAG_LOADKLD, NULL, 183 { 184 { 'a', "aalgo", "", G_TYPE_STRING }, 185 { 'd', "detach", NULL, G_TYPE_BOOL }, 186 { 'e', "ealgo", GELI_ENC_ALGO, G_TYPE_STRING }, 187 { 'l', "keylen", "0", G_TYPE_NUMBER }, 188 { 's', "sectorsize", "0", G_TYPE_NUMBER }, 189 { 'T', "notrim", NULL, G_TYPE_BOOL }, 190 G_OPT_SENTINEL 191 }, 192 "[-dT] [-a aalgo] [-e ealgo] [-l keylen] [-s sectorsize] prov" 193 }, 194 { "configure", G_FLAG_VERBOSE, eli_main, 195 { 196 { 'b', "boot", NULL, G_TYPE_BOOL }, 197 { 'B', "noboot", NULL, G_TYPE_BOOL }, 198 { 'd', "displaypass", NULL, G_TYPE_BOOL }, 199 { 'D', "nodisplaypass", NULL, G_TYPE_BOOL }, 200 { 'g', "geliboot", NULL, G_TYPE_BOOL }, 201 { 'G', "nogeliboot", NULL, G_TYPE_BOOL }, 202 { 't', "trim", NULL, G_TYPE_BOOL }, 203 { 'T', "notrim", NULL, G_TYPE_BOOL }, 204 G_OPT_SENTINEL 205 }, 206 "[-bBdDgGtT] prov ..." 207 }, 208 { "setkey", G_FLAG_VERBOSE, eli_main, 209 { 210 { 'i', "iterations", "-1", G_TYPE_NUMBER }, 211 { 'j', "passfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI }, 212 { 'J', "newpassfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI }, 213 { 'k', "keyfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI }, 214 { 'K', "newkeyfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI }, 215 { 'n', "keyno", "-1", G_TYPE_NUMBER }, 216 { 'p', "nopassphrase", NULL, G_TYPE_BOOL }, 217 { 'P', "nonewpassphrase", NULL, G_TYPE_BOOL }, 218 G_OPT_SENTINEL 219 }, 220 "[-pPv] [-n keyno] [-i iterations] [-j passfile] [-J newpassfile] [-k keyfile] [-K newkeyfile] prov" 221 }, 222 { "delkey", G_FLAG_VERBOSE, eli_main, 223 { 224 { 'a', "all", NULL, G_TYPE_BOOL }, 225 { 'f', "force", NULL, G_TYPE_BOOL }, 226 { 'n', "keyno", "-1", G_TYPE_NUMBER }, 227 G_OPT_SENTINEL 228 }, 229 "[-afv] [-n keyno] prov" 230 }, 231 { "suspend", G_FLAG_VERBOSE, NULL, 232 { 233 { 'a', "all", NULL, G_TYPE_BOOL }, 234 G_OPT_SENTINEL 235 }, 236 "[-v] -a | prov ..." 237 }, 238 { "resume", G_FLAG_VERBOSE, eli_main, 239 { 240 { 'j', "passfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI }, 241 { 'k', "keyfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI }, 242 { 'p', "nopassphrase", NULL, G_TYPE_BOOL }, 243 G_OPT_SENTINEL 244 }, 245 "[-pv] [-j passfile] [-k keyfile] prov" 246 }, 247 { "kill", G_FLAG_VERBOSE, eli_main, 248 { 249 { 'a', "all", NULL, G_TYPE_BOOL }, 250 G_OPT_SENTINEL 251 }, 252 "[-av] [prov ...]" 253 }, 254 { "backup", G_FLAG_VERBOSE, eli_main, G_NULL_OPTS, 255 "[-v] prov file" 256 }, 257 { "restore", G_FLAG_VERBOSE, eli_main, 258 { 259 { 'f', "force", NULL, G_TYPE_BOOL }, 260 G_OPT_SENTINEL 261 }, 262 "[-fv] file prov" 263 }, 264 { "resize", G_FLAG_VERBOSE, eli_main, 265 { 266 { 's', "oldsize", NULL, G_TYPE_NUMBER }, 267 G_OPT_SENTINEL 268 }, 269 "[-v] -s oldsize prov" 270 }, 271 { "version", G_FLAG_LOADKLD, eli_main, G_NULL_OPTS, 272 "[prov ...]" 273 }, 274 { "clear", G_FLAG_VERBOSE, eli_main, G_NULL_OPTS, 275 "[-v] prov ..." 276 }, 277 { "dump", G_FLAG_VERBOSE, eli_main, G_NULL_OPTS, 278 "[-v] prov ..." 279 }, 280 G_CMD_SENTINEL 281 }; 282 283 static int verbose = 0; 284 285 static int 286 eli_protect(struct gctl_req *req) 287 { 288 struct rlimit rl; 289 290 /* Disable core dumps. */ 291 rl.rlim_cur = 0; 292 rl.rlim_max = 0; 293 if (setrlimit(RLIMIT_CORE, &rl) == -1) { 294 gctl_error(req, "Cannot disable core dumps: %s.", 295 strerror(errno)); 296 return (-1); 297 } 298 /* Disable swapping. */ 299 if (mlockall(MCL_FUTURE) == -1) { 300 gctl_error(req, "Cannot lock memory: %s.", strerror(errno)); 301 return (-1); 302 } 303 return (0); 304 } 305 306 static void 307 eli_main(struct gctl_req *req, unsigned int flags) 308 { 309 const char *name; 310 311 if (eli_protect(req) == -1) 312 return; 313 314 if ((flags & G_FLAG_VERBOSE) != 0) 315 verbose = 1; 316 317 name = gctl_get_ascii(req, "verb"); 318 if (name == NULL) { 319 gctl_error(req, "No '%s' argument.", "verb"); 320 return; 321 } 322 if (strcmp(name, "init") == 0 || strcmp(name, "label") == 0) 323 eli_init(req); 324 else if (strcmp(name, "attach") == 0) 325 eli_attach(req); 326 else if (strcmp(name, "configure") == 0) 327 eli_configure(req); 328 else if (strcmp(name, "setkey") == 0) 329 eli_setkey(req); 330 else if (strcmp(name, "delkey") == 0) 331 eli_delkey(req); 332 else if (strcmp(name, "resume") == 0) 333 eli_resume(req); 334 else if (strcmp(name, "kill") == 0) 335 eli_kill(req); 336 else if (strcmp(name, "backup") == 0) 337 eli_backup(req); 338 else if (strcmp(name, "restore") == 0) 339 eli_restore(req); 340 else if (strcmp(name, "resize") == 0) 341 eli_resize(req); 342 else if (strcmp(name, "version") == 0) 343 eli_version(req); 344 else if (strcmp(name, "dump") == 0) 345 eli_dump(req); 346 else if (strcmp(name, "clear") == 0) 347 eli_clear(req); 348 else 349 gctl_error(req, "Unknown command: %s.", name); 350 } 351 352 static bool 353 eli_is_attached(const char *prov) 354 { 355 char name[MAXPATHLEN]; 356 357 /* 358 * Not the best way to do it, but the easiest. 359 * We try to open provider and check if it is a GEOM provider 360 * by asking about its sectorsize. 361 */ 362 snprintf(name, sizeof(name), "%s%s", prov, G_ELI_SUFFIX); 363 return (g_get_sectorsize(name) > 0); 364 } 365 366 static int 367 eli_genkey_files(struct gctl_req *req, bool new, const char *type, 368 struct hmac_ctx *ctxp, char *passbuf, size_t passbufsize) 369 { 370 char *p, buf[BUFSIZE], argname[16]; 371 const char *file; 372 int error, fd, i; 373 ssize_t done; 374 375 assert((strcmp(type, "keyfile") == 0 && ctxp != NULL && 376 passbuf == NULL && passbufsize == 0) || 377 (strcmp(type, "passfile") == 0 && ctxp == NULL && 378 passbuf != NULL && passbufsize > 0)); 379 assert(strcmp(type, "keyfile") == 0 || passbuf[0] == '\0'); 380 381 for (i = 0; ; i++) { 382 snprintf(argname, sizeof(argname), "%s%s%d", 383 new ? "new" : "", type, i); 384 385 /* No more {key,pass}files? */ 386 if (!gctl_has_param(req, argname)) 387 return (i); 388 389 file = gctl_get_ascii(req, "%s", argname); 390 assert(file != NULL); 391 392 if (strcmp(file, "-") == 0) 393 fd = STDIN_FILENO; 394 else { 395 fd = open(file, O_RDONLY); 396 if (fd == -1) { 397 gctl_error(req, "Cannot open %s %s: %s.", 398 type, file, strerror(errno)); 399 return (-1); 400 } 401 } 402 if (strcmp(type, "keyfile") == 0) { 403 while ((done = read(fd, buf, sizeof(buf))) > 0) 404 g_eli_crypto_hmac_update(ctxp, buf, done); 405 } else /* if (strcmp(type, "passfile") == 0) */ { 406 assert(strcmp(type, "passfile") == 0); 407 408 while ((done = read(fd, buf, sizeof(buf) - 1)) > 0) { 409 buf[done] = '\0'; 410 p = strchr(buf, '\n'); 411 if (p != NULL) { 412 *p = '\0'; 413 done = p - buf; 414 } 415 if (strlcat(passbuf, buf, passbufsize) >= 416 passbufsize) { 417 gctl_error(req, 418 "Passphrase in %s too long.", file); 419 explicit_bzero(buf, sizeof(buf)); 420 return (-1); 421 } 422 if (p != NULL) 423 break; 424 } 425 } 426 error = errno; 427 if (strcmp(file, "-") != 0) 428 close(fd); 429 explicit_bzero(buf, sizeof(buf)); 430 if (done == -1) { 431 gctl_error(req, "Cannot read %s %s: %s.", 432 type, file, strerror(error)); 433 return (-1); 434 } 435 } 436 /* NOTREACHED */ 437 } 438 439 static int 440 eli_genkey_passphrase_prompt(struct gctl_req *req, bool new, char *passbuf, 441 size_t passbufsize) 442 { 443 char *p; 444 445 for (;;) { 446 p = readpassphrase( 447 new ? "Enter new passphrase: " : "Enter passphrase: ", 448 passbuf, passbufsize, RPP_ECHO_OFF | RPP_REQUIRE_TTY); 449 if (p == NULL) { 450 explicit_bzero(passbuf, passbufsize); 451 gctl_error(req, "Cannot read passphrase: %s.", 452 strerror(errno)); 453 return (-1); 454 } 455 456 if (new) { 457 char tmpbuf[BUFSIZE]; 458 459 p = readpassphrase("Reenter new passphrase: ", 460 tmpbuf, sizeof(tmpbuf), 461 RPP_ECHO_OFF | RPP_REQUIRE_TTY); 462 if (p == NULL) { 463 explicit_bzero(passbuf, passbufsize); 464 gctl_error(req, 465 "Cannot read passphrase: %s.", 466 strerror(errno)); 467 return (-1); 468 } 469 470 if (strcmp(passbuf, tmpbuf) != 0) { 471 explicit_bzero(passbuf, passbufsize); 472 fprintf(stderr, "They didn't match.\n"); 473 continue; 474 } 475 explicit_bzero(tmpbuf, sizeof(tmpbuf)); 476 } 477 return (0); 478 } 479 /* NOTREACHED */ 480 } 481 482 static int 483 eli_genkey_passphrase(struct gctl_req *req, struct g_eli_metadata *md, bool new, 484 struct hmac_ctx *ctxp) 485 { 486 char passbuf[BUFSIZE]; 487 bool nopassphrase; 488 int nfiles; 489 490 /* 491 * Return error if the 'do not use passphrase' flag was given but a 492 * passfile was provided. 493 */ 494 nopassphrase = 495 gctl_get_int(req, new ? "nonewpassphrase" : "nopassphrase"); 496 if (nopassphrase) { 497 if (gctl_has_param(req, new ? "newpassfile0" : "passfile0")) { 498 gctl_error(req, 499 "Options -%c and -%c are mutually exclusive.", 500 new ? 'J' : 'j', new ? 'P' : 'p'); 501 return (-1); 502 } 503 return (0); 504 } 505 506 /* 507 * Return error if using a provider which does not require a passphrase 508 * but the 'do not use passphrase' flag was not given. 509 */ 510 if (!new && md->md_iterations == -1) { 511 gctl_error(req, "Missing -p flag."); 512 return (-1); 513 } 514 passbuf[0] = '\0'; 515 516 /* Use cached passphrase if defined. */ 517 if (strlen(cached_passphrase) > 0) { 518 strlcpy(passbuf, cached_passphrase, sizeof(passbuf)); 519 } else { 520 nfiles = eli_genkey_files(req, new, "passfile", NULL, passbuf, 521 sizeof(passbuf)); 522 if (nfiles == -1) { 523 return (-1); 524 } else if (nfiles == 0) { 525 if (eli_genkey_passphrase_prompt(req, new, passbuf, 526 sizeof(passbuf)) == -1) { 527 return (-1); 528 } 529 } 530 /* Cache the passphrase for other providers. */ 531 strlcpy(cached_passphrase, passbuf, sizeof(cached_passphrase)); 532 } 533 /* 534 * Field md_iterations equal to -1 means "choose some sane 535 * value for me". 536 */ 537 if (md->md_iterations == -1) { 538 assert(new); 539 if (verbose) 540 printf("Calculating number of iterations...\n"); 541 md->md_iterations = pkcs5v2_calculate(2000000); 542 assert(md->md_iterations > 0); 543 if (verbose) { 544 printf("Done, using %d iterations.\n", 545 md->md_iterations); 546 } 547 } 548 /* 549 * If md_iterations is equal to 0, user doesn't want PKCS#5v2. 550 */ 551 if (md->md_iterations == 0) { 552 g_eli_crypto_hmac_update(ctxp, md->md_salt, 553 sizeof(md->md_salt)); 554 g_eli_crypto_hmac_update(ctxp, passbuf, strlen(passbuf)); 555 } else /* if (md->md_iterations > 0) */ { 556 unsigned char dkey[G_ELI_USERKEYLEN]; 557 558 pkcs5v2_genkey(dkey, sizeof(dkey), md->md_salt, 559 sizeof(md->md_salt), passbuf, md->md_iterations); 560 g_eli_crypto_hmac_update(ctxp, dkey, sizeof(dkey)); 561 explicit_bzero(dkey, sizeof(dkey)); 562 } 563 explicit_bzero(passbuf, sizeof(passbuf)); 564 565 return (0); 566 } 567 568 static unsigned char * 569 eli_genkey(struct gctl_req *req, struct g_eli_metadata *md, unsigned char *key, 570 bool new) 571 { 572 struct hmac_ctx ctx; 573 bool nopassphrase; 574 int nfiles; 575 576 nopassphrase = 577 gctl_get_int(req, new ? "nonewpassphrase" : "nopassphrase"); 578 579 g_eli_crypto_hmac_init(&ctx, NULL, 0); 580 581 nfiles = eli_genkey_files(req, new, "keyfile", &ctx, NULL, 0); 582 if (nfiles == -1) 583 return (NULL); 584 else if (nfiles == 0 && nopassphrase) { 585 gctl_error(req, "No key components given."); 586 return (NULL); 587 } 588 589 if (eli_genkey_passphrase(req, md, new, &ctx) == -1) 590 return (NULL); 591 592 g_eli_crypto_hmac_final(&ctx, key, 0); 593 594 return (key); 595 } 596 597 static int 598 eli_metadata_read(struct gctl_req *req, const char *prov, 599 struct g_eli_metadata *md) 600 { 601 unsigned char sector[sizeof(struct g_eli_metadata)]; 602 int error; 603 604 if (g_get_sectorsize(prov) == 0) { 605 int fd; 606 607 /* This is a file probably. */ 608 fd = open(prov, O_RDONLY); 609 if (fd == -1) { 610 gctl_error(req, "Cannot open %s: %s.", prov, 611 strerror(errno)); 612 return (-1); 613 } 614 if (read(fd, sector, sizeof(sector)) != sizeof(sector)) { 615 gctl_error(req, "Cannot read metadata from %s: %s.", 616 prov, strerror(errno)); 617 close(fd); 618 return (-1); 619 } 620 close(fd); 621 } else { 622 /* This is a GEOM provider. */ 623 error = g_metadata_read(prov, sector, sizeof(sector), 624 G_ELI_MAGIC); 625 if (error != 0) { 626 gctl_error(req, "Cannot read metadata from %s: %s.", 627 prov, strerror(error)); 628 return (-1); 629 } 630 } 631 error = eli_metadata_decode(sector, md); 632 switch (error) { 633 case 0: 634 break; 635 case EOPNOTSUPP: 636 gctl_error(req, 637 "Provider's %s metadata version %u is too new.\n" 638 "geli: The highest supported version is %u.", 639 prov, (unsigned int)md->md_version, G_ELI_VERSION); 640 return (-1); 641 case EINVAL: 642 gctl_error(req, "Inconsistent provider's %s metadata.", prov); 643 return (-1); 644 default: 645 gctl_error(req, 646 "Unexpected error while decoding provider's %s metadata: %s.", 647 prov, strerror(error)); 648 return (-1); 649 } 650 return (0); 651 } 652 653 static int 654 eli_metadata_store(struct gctl_req *req, const char *prov, 655 struct g_eli_metadata *md) 656 { 657 unsigned char sector[sizeof(struct g_eli_metadata)]; 658 int error; 659 660 eli_metadata_encode(md, sector); 661 if (g_get_sectorsize(prov) == 0) { 662 int fd; 663 664 /* This is a file probably. */ 665 fd = open(prov, O_WRONLY | O_TRUNC); 666 if (fd == -1) { 667 gctl_error(req, "Cannot open %s: %s.", prov, 668 strerror(errno)); 669 explicit_bzero(sector, sizeof(sector)); 670 return (-1); 671 } 672 if (write(fd, sector, sizeof(sector)) != sizeof(sector)) { 673 gctl_error(req, "Cannot write metadata to %s: %s.", 674 prov, strerror(errno)); 675 explicit_bzero(sector, sizeof(sector)); 676 close(fd); 677 return (-1); 678 } 679 close(fd); 680 } else { 681 /* This is a GEOM provider. */ 682 error = g_metadata_store(prov, sector, sizeof(sector)); 683 if (error != 0) { 684 gctl_error(req, "Cannot write metadata to %s: %s.", 685 prov, strerror(errno)); 686 explicit_bzero(sector, sizeof(sector)); 687 return (-1); 688 } 689 } 690 explicit_bzero(sector, sizeof(sector)); 691 return (0); 692 } 693 694 static void 695 eli_init(struct gctl_req *req) 696 { 697 struct g_eli_metadata md; 698 unsigned char sector[sizeof(struct g_eli_metadata)] __aligned(4); 699 unsigned char key[G_ELI_USERKEYLEN]; 700 char backfile[MAXPATHLEN]; 701 const char *str, *prov; 702 unsigned int secsize, version; 703 off_t mediasize; 704 intmax_t val; 705 int error, nargs; 706 707 nargs = gctl_get_int(req, "nargs"); 708 if (nargs != 1) { 709 gctl_error(req, "Invalid number of arguments."); 710 return; 711 } 712 prov = gctl_get_ascii(req, "arg0"); 713 mediasize = g_get_mediasize(prov); 714 secsize = g_get_sectorsize(prov); 715 if (mediasize == 0 || secsize == 0) { 716 gctl_error(req, "Cannot get informations about %s: %s.", prov, 717 strerror(errno)); 718 return; 719 } 720 721 explicit_bzero(&md, sizeof(md)); 722 strlcpy(md.md_magic, G_ELI_MAGIC, sizeof(md.md_magic)); 723 val = gctl_get_intmax(req, "mdversion"); 724 if (val == -1) { 725 version = G_ELI_VERSION; 726 } else if (val < 0 || val > G_ELI_VERSION) { 727 gctl_error(req, 728 "Invalid version specified should be between %u and %u.", 729 G_ELI_VERSION_00, G_ELI_VERSION); 730 return; 731 } else { 732 version = val; 733 } 734 md.md_version = version; 735 md.md_flags = 0; 736 if (gctl_get_int(req, "boot")) 737 md.md_flags |= G_ELI_FLAG_BOOT; 738 if (gctl_get_int(req, "geliboot")) 739 md.md_flags |= G_ELI_FLAG_GELIBOOT; 740 if (gctl_get_int(req, "displaypass")) 741 md.md_flags |= G_ELI_FLAG_GELIDISPLAYPASS; 742 if (gctl_get_int(req, "notrim")) 743 md.md_flags |= G_ELI_FLAG_NODELETE; 744 md.md_ealgo = CRYPTO_ALGORITHM_MIN - 1; 745 str = gctl_get_ascii(req, "aalgo"); 746 if (*str != '\0') { 747 if (version < G_ELI_VERSION_01) { 748 gctl_error(req, 749 "Data authentication is supported starting from version %u.", 750 G_ELI_VERSION_01); 751 return; 752 } 753 md.md_aalgo = g_eli_str2aalgo(str); 754 if (md.md_aalgo >= CRYPTO_ALGORITHM_MIN && 755 md.md_aalgo <= CRYPTO_ALGORITHM_MAX) { 756 md.md_flags |= G_ELI_FLAG_AUTH; 757 } else { 758 /* 759 * For backward compatibility, check if the -a option 760 * was used to provide encryption algorithm. 761 */ 762 md.md_ealgo = g_eli_str2ealgo(str); 763 if (md.md_ealgo < CRYPTO_ALGORITHM_MIN || 764 md.md_ealgo > CRYPTO_ALGORITHM_MAX) { 765 gctl_error(req, 766 "Invalid authentication algorithm."); 767 return; 768 } else { 769 fprintf(stderr, "warning: The -e option, not " 770 "the -a option is now used to specify " 771 "encryption algorithm to use.\n"); 772 } 773 } 774 } 775 if (md.md_ealgo < CRYPTO_ALGORITHM_MIN || 776 md.md_ealgo > CRYPTO_ALGORITHM_MAX) { 777 str = gctl_get_ascii(req, "ealgo"); 778 if (*str == '\0') { 779 if (version < G_ELI_VERSION_05) 780 str = "aes-cbc"; 781 else 782 str = GELI_ENC_ALGO; 783 } 784 md.md_ealgo = g_eli_str2ealgo(str); 785 if (md.md_ealgo < CRYPTO_ALGORITHM_MIN || 786 md.md_ealgo > CRYPTO_ALGORITHM_MAX) { 787 gctl_error(req, "Invalid encryption algorithm."); 788 return; 789 } 790 if (md.md_ealgo == CRYPTO_CAMELLIA_CBC && 791 version < G_ELI_VERSION_04) { 792 gctl_error(req, 793 "Camellia-CBC algorithm is supported starting from version %u.", 794 G_ELI_VERSION_04); 795 return; 796 } 797 if (md.md_ealgo == CRYPTO_AES_XTS && 798 version < G_ELI_VERSION_05) { 799 gctl_error(req, 800 "AES-XTS algorithm is supported starting from version %u.", 801 G_ELI_VERSION_05); 802 return; 803 } 804 } 805 val = gctl_get_intmax(req, "keylen"); 806 md.md_keylen = val; 807 md.md_keylen = g_eli_keylen(md.md_ealgo, md.md_keylen); 808 if (md.md_keylen == 0) { 809 gctl_error(req, "Invalid key length."); 810 return; 811 } 812 md.md_provsize = mediasize; 813 814 val = gctl_get_intmax(req, "iterations"); 815 if (val != -1) { 816 int nonewpassphrase; 817 818 /* 819 * Don't allow to set iterations when there will be no 820 * passphrase. 821 */ 822 nonewpassphrase = gctl_get_int(req, "nonewpassphrase"); 823 if (nonewpassphrase) { 824 gctl_error(req, 825 "Options -i and -P are mutually exclusive."); 826 return; 827 } 828 } 829 md.md_iterations = val; 830 831 val = gctl_get_intmax(req, "sectorsize"); 832 if (val == 0) 833 md.md_sectorsize = secsize; 834 else { 835 if (val < 0 || (val % secsize) != 0 || !powerof2(val)) { 836 gctl_error(req, "Invalid sector size."); 837 return; 838 } 839 if (val > sysconf(_SC_PAGE_SIZE)) { 840 fprintf(stderr, 841 "warning: Using sectorsize bigger than the page size!\n"); 842 } 843 md.md_sectorsize = val; 844 } 845 846 md.md_keys = 0x01; 847 arc4random_buf(md.md_salt, sizeof(md.md_salt)); 848 arc4random_buf(md.md_mkeys, sizeof(md.md_mkeys)); 849 850 /* Generate user key. */ 851 if (eli_genkey(req, &md, key, true) == NULL) { 852 explicit_bzero(key, sizeof(key)); 853 explicit_bzero(&md, sizeof(md)); 854 return; 855 } 856 857 /* Encrypt the first and the only Master Key. */ 858 error = g_eli_mkey_encrypt(md.md_ealgo, key, md.md_keylen, md.md_mkeys); 859 explicit_bzero(key, sizeof(key)); 860 if (error != 0) { 861 explicit_bzero(&md, sizeof(md)); 862 gctl_error(req, "Cannot encrypt Master Key: %s.", 863 strerror(error)); 864 return; 865 } 866 867 eli_metadata_encode(&md, sector); 868 explicit_bzero(&md, sizeof(md)); 869 error = g_metadata_store(prov, sector, sizeof(sector)); 870 explicit_bzero(sector, sizeof(sector)); 871 if (error != 0) { 872 gctl_error(req, "Cannot store metadata on %s: %s.", prov, 873 strerror(error)); 874 return; 875 } 876 if (verbose) 877 printf("Metadata value stored on %s.\n", prov); 878 /* Backup metadata to a file. */ 879 str = gctl_get_ascii(req, "backupfile"); 880 if (str[0] != '\0') { 881 /* Backupfile given be the user, just copy it. */ 882 strlcpy(backfile, str, sizeof(backfile)); 883 } else { 884 /* Generate file name automatically. */ 885 const char *p = prov; 886 unsigned int i; 887 888 if (strncmp(p, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0) 889 p += sizeof(_PATH_DEV) - 1; 890 snprintf(backfile, sizeof(backfile), "%s%s.eli", 891 GELI_BACKUP_DIR, p); 892 /* Replace all / with _. */ 893 for (i = strlen(GELI_BACKUP_DIR); backfile[i] != '\0'; i++) { 894 if (backfile[i] == '/') 895 backfile[i] = '_'; 896 } 897 } 898 if (strcmp(backfile, "none") != 0 && 899 eli_backup_create(req, prov, backfile) == 0) { 900 printf("\nMetadata backup can be found in %s and\n", backfile); 901 printf("can be restored with the following command:\n"); 902 printf("\n\t# geli restore %s %s\n\n", backfile, prov); 903 } 904 } 905 906 static void 907 eli_attach(struct gctl_req *req) 908 { 909 struct g_eli_metadata md; 910 struct gctl_req *r; 911 const char *prov; 912 off_t mediasize; 913 int i, nargs, nparams, param; 914 const int one = 1; 915 916 nargs = gctl_get_int(req, "nargs"); 917 if (nargs == 0) { 918 gctl_error(req, "Too few arguments."); 919 return; 920 } 921 922 unsigned char key[G_ELI_USERKEYLEN]; 923 924 /* 925 * Determine number of parameters in the parent geom request before the 926 * nargs parameter and list of providers. 927 */ 928 nparams = req->narg - nargs - 1; 929 930 /* Create new child geom request for each provider and issue to kernel */ 931 for (i = 0; i < nargs; i++) { 932 r = gctl_get_handle(); 933 934 /* Copy each parameter from the parent request to the child request */ 935 for (param = 0; param < nparams; param++) { 936 gctl_ro_param(r, req->arg[param].name, req->arg[param].len, req->arg[param].value); 937 } 938 939 /* Add a single provider to the parameter list of the child */ 940 gctl_ro_param(r, "nargs", sizeof(one), &one); 941 prov = gctl_get_ascii(req, "arg%d", i); 942 gctl_ro_param(r, "arg0", -1, prov); 943 944 if (eli_metadata_read(r, prov, &md) == -1) 945 return; 946 947 mediasize = g_get_mediasize(prov); 948 if (md.md_provsize != (uint64_t)mediasize) { 949 gctl_error(r, "Provider size mismatch."); 950 return; 951 } 952 953 if (eli_genkey(r, &md, key, false) == NULL) { 954 explicit_bzero(key, sizeof(key)); 955 return; 956 } 957 958 gctl_ro_param(r, "key", sizeof(key), key); 959 960 if (gctl_issue(r) == NULL) { 961 if (verbose) 962 printf("Attached to %s.\n", prov); 963 } 964 965 /* Print error for this request, and set parent request error message */ 966 if (r->error != NULL && r->error[0] != '\0') { 967 warnx("%s", r->error); 968 gctl_error(req, "At least one provider failed to attach."); 969 } 970 971 gctl_free(r); 972 973 /* Clear the derived key */ 974 explicit_bzero(key, sizeof(key)); 975 } 976 977 /* Clear the cached passphrase */ 978 explicit_bzero(cached_passphrase, sizeof(cached_passphrase)); 979 } 980 981 static void 982 eli_configure_detached(struct gctl_req *req, const char *prov, int boot, 983 int geliboot, int displaypass, int trim) 984 { 985 struct g_eli_metadata md; 986 bool changed = 0; 987 988 if (eli_metadata_read(req, prov, &md) == -1) 989 return; 990 991 if (boot == 1 && (md.md_flags & G_ELI_FLAG_BOOT)) { 992 if (verbose) 993 printf("BOOT flag already configured for %s.\n", prov); 994 } else if (boot == 0 && !(md.md_flags & G_ELI_FLAG_BOOT)) { 995 if (verbose) 996 printf("BOOT flag not configured for %s.\n", prov); 997 } else if (boot >= 0) { 998 if (boot) 999 md.md_flags |= G_ELI_FLAG_BOOT; 1000 else 1001 md.md_flags &= ~G_ELI_FLAG_BOOT; 1002 changed = 1; 1003 } 1004 1005 if (geliboot == 1 && (md.md_flags & G_ELI_FLAG_GELIBOOT)) { 1006 if (verbose) 1007 printf("GELIBOOT flag already configured for %s.\n", prov); 1008 } else if (geliboot == 0 && !(md.md_flags & G_ELI_FLAG_GELIBOOT)) { 1009 if (verbose) 1010 printf("GELIBOOT flag not configured for %s.\n", prov); 1011 } else if (geliboot >= 0) { 1012 if (geliboot) 1013 md.md_flags |= G_ELI_FLAG_GELIBOOT; 1014 else 1015 md.md_flags &= ~G_ELI_FLAG_GELIBOOT; 1016 changed = 1; 1017 } 1018 1019 if (displaypass == 1 && (md.md_flags & G_ELI_FLAG_GELIDISPLAYPASS)) { 1020 if (verbose) 1021 printf("GELIDISPLAYPASS flag already configured for %s.\n", prov); 1022 } else if (displaypass == 0 && 1023 !(md.md_flags & G_ELI_FLAG_GELIDISPLAYPASS)) { 1024 if (verbose) 1025 printf("GELIDISPLAYPASS flag not configured for %s.\n", prov); 1026 } else if (displaypass >= 0) { 1027 if (displaypass) 1028 md.md_flags |= G_ELI_FLAG_GELIDISPLAYPASS; 1029 else 1030 md.md_flags &= ~G_ELI_FLAG_GELIDISPLAYPASS; 1031 changed = 1; 1032 } 1033 1034 if (trim == 0 && (md.md_flags & G_ELI_FLAG_NODELETE)) { 1035 if (verbose) 1036 printf("TRIM disable flag already configured for %s.\n", prov); 1037 } else if (trim == 1 && !(md.md_flags & G_ELI_FLAG_NODELETE)) { 1038 if (verbose) 1039 printf("TRIM disable flag not configured for %s.\n", prov); 1040 } else if (trim >= 0) { 1041 if (trim) 1042 md.md_flags &= ~G_ELI_FLAG_NODELETE; 1043 else 1044 md.md_flags |= G_ELI_FLAG_NODELETE; 1045 changed = 1; 1046 } 1047 1048 if (changed) 1049 eli_metadata_store(req, prov, &md); 1050 explicit_bzero(&md, sizeof(md)); 1051 } 1052 1053 static void 1054 eli_configure(struct gctl_req *req) 1055 { 1056 const char *prov; 1057 bool boot, noboot, geliboot, nogeliboot, displaypass, nodisplaypass; 1058 bool trim, notrim; 1059 int doboot, dogeliboot, dodisplaypass, dotrim; 1060 int i, nargs; 1061 1062 nargs = gctl_get_int(req, "nargs"); 1063 if (nargs == 0) { 1064 gctl_error(req, "Too few arguments."); 1065 return; 1066 } 1067 1068 boot = gctl_get_int(req, "boot"); 1069 noboot = gctl_get_int(req, "noboot"); 1070 geliboot = gctl_get_int(req, "geliboot"); 1071 nogeliboot = gctl_get_int(req, "nogeliboot"); 1072 displaypass = gctl_get_int(req, "displaypass"); 1073 nodisplaypass = gctl_get_int(req, "nodisplaypass"); 1074 trim = gctl_get_int(req, "trim"); 1075 notrim = gctl_get_int(req, "notrim"); 1076 1077 doboot = -1; 1078 if (boot && noboot) { 1079 gctl_error(req, "Options -b and -B are mutually exclusive."); 1080 return; 1081 } 1082 if (boot) 1083 doboot = 1; 1084 else if (noboot) 1085 doboot = 0; 1086 1087 dogeliboot = -1; 1088 if (geliboot && nogeliboot) { 1089 gctl_error(req, "Options -g and -G are mutually exclusive."); 1090 return; 1091 } 1092 if (geliboot) 1093 dogeliboot = 1; 1094 else if (nogeliboot) 1095 dogeliboot = 0; 1096 1097 dodisplaypass = -1; 1098 if (displaypass && nodisplaypass) { 1099 gctl_error(req, "Options -d and -D are mutually exclusive."); 1100 return; 1101 } 1102 if (displaypass) 1103 dodisplaypass = 1; 1104 else if (nodisplaypass) 1105 dodisplaypass = 0; 1106 1107 dotrim = -1; 1108 if (trim && notrim) { 1109 gctl_error(req, "Options -t and -T are mutually exclusive."); 1110 return; 1111 } 1112 if (trim) 1113 dotrim = 1; 1114 else if (notrim) 1115 dotrim = 0; 1116 1117 if (doboot == -1 && dogeliboot == -1 && dodisplaypass == -1 && 1118 dotrim == -1) { 1119 gctl_error(req, "No option given."); 1120 return; 1121 } 1122 1123 /* First attached providers. */ 1124 gctl_issue(req); 1125 /* Now the rest. */ 1126 for (i = 0; i < nargs; i++) { 1127 prov = gctl_get_ascii(req, "arg%d", i); 1128 if (!eli_is_attached(prov)) { 1129 eli_configure_detached(req, prov, doboot, dogeliboot, 1130 dodisplaypass, dotrim); 1131 } 1132 } 1133 } 1134 1135 static void 1136 eli_setkey_attached(struct gctl_req *req, struct g_eli_metadata *md) 1137 { 1138 unsigned char key[G_ELI_USERKEYLEN]; 1139 intmax_t val, old = 0; 1140 int error; 1141 1142 val = gctl_get_intmax(req, "iterations"); 1143 /* Check if iterations number should be changed. */ 1144 if (val != -1) 1145 md->md_iterations = val; 1146 else 1147 old = md->md_iterations; 1148 1149 /* Generate key for Master Key encryption. */ 1150 if (eli_genkey(req, md, key, true) == NULL) { 1151 explicit_bzero(key, sizeof(key)); 1152 return; 1153 } 1154 /* 1155 * If number of iterations has changed, but wasn't given as a 1156 * command-line argument, update the request. 1157 */ 1158 if (val == -1 && md->md_iterations != old) { 1159 error = gctl_change_param(req, "iterations", sizeof(intmax_t), 1160 &md->md_iterations); 1161 assert(error == 0); 1162 } 1163 1164 gctl_ro_param(req, "key", sizeof(key), key); 1165 gctl_issue(req); 1166 explicit_bzero(key, sizeof(key)); 1167 } 1168 1169 static void 1170 eli_setkey_detached(struct gctl_req *req, const char *prov, 1171 struct g_eli_metadata *md) 1172 { 1173 unsigned char key[G_ELI_USERKEYLEN], mkey[G_ELI_DATAIVKEYLEN]; 1174 unsigned char *mkeydst; 1175 unsigned int nkey; 1176 intmax_t val; 1177 int error; 1178 1179 if (md->md_keys == 0) { 1180 gctl_error(req, "No valid keys on %s.", prov); 1181 return; 1182 } 1183 1184 /* Generate key for Master Key decryption. */ 1185 if (eli_genkey(req, md, key, false) == NULL) { 1186 explicit_bzero(key, sizeof(key)); 1187 return; 1188 } 1189 1190 /* Decrypt Master Key. */ 1191 error = g_eli_mkey_decrypt_any(md, key, mkey, &nkey); 1192 explicit_bzero(key, sizeof(key)); 1193 if (error != 0) { 1194 explicit_bzero(md, sizeof(*md)); 1195 if (error == -1) 1196 gctl_error(req, "Wrong key for %s.", prov); 1197 else /* if (error > 0) */ { 1198 gctl_error(req, "Cannot decrypt Master Key: %s.", 1199 strerror(error)); 1200 } 1201 return; 1202 } 1203 if (verbose) 1204 printf("Decrypted Master Key %u.\n", nkey); 1205 1206 val = gctl_get_intmax(req, "keyno"); 1207 if (val != -1) 1208 nkey = val; 1209 #if 0 1210 else 1211 ; /* Use the key number which was found during decryption. */ 1212 #endif 1213 if (nkey >= G_ELI_MAXMKEYS) { 1214 gctl_error(req, "Invalid '%s' argument.", "keyno"); 1215 return; 1216 } 1217 1218 val = gctl_get_intmax(req, "iterations"); 1219 /* Check if iterations number should and can be changed. */ 1220 if (val != -1 && md->md_iterations == -1) { 1221 md->md_iterations = val; 1222 } else if (val != -1 && val != md->md_iterations) { 1223 if (bitcount32(md->md_keys) != 1) { 1224 gctl_error(req, "To be able to use '-i' option, only " 1225 "one key can be defined."); 1226 return; 1227 } 1228 if (md->md_keys != (1 << nkey)) { 1229 gctl_error(req, "Only already defined key can be " 1230 "changed when '-i' option is used."); 1231 return; 1232 } 1233 md->md_iterations = val; 1234 } 1235 1236 mkeydst = md->md_mkeys + nkey * G_ELI_MKEYLEN; 1237 md->md_keys |= (1 << nkey); 1238 1239 bcopy(mkey, mkeydst, sizeof(mkey)); 1240 explicit_bzero(mkey, sizeof(mkey)); 1241 1242 /* Generate key for Master Key encryption. */ 1243 if (eli_genkey(req, md, key, true) == NULL) { 1244 explicit_bzero(key, sizeof(key)); 1245 explicit_bzero(md, sizeof(*md)); 1246 return; 1247 } 1248 1249 /* Encrypt the Master-Key with the new key. */ 1250 error = g_eli_mkey_encrypt(md->md_ealgo, key, md->md_keylen, mkeydst); 1251 explicit_bzero(key, sizeof(key)); 1252 if (error != 0) { 1253 explicit_bzero(md, sizeof(*md)); 1254 gctl_error(req, "Cannot encrypt Master Key: %s.", 1255 strerror(error)); 1256 return; 1257 } 1258 1259 /* Store metadata with fresh key. */ 1260 eli_metadata_store(req, prov, md); 1261 explicit_bzero(md, sizeof(*md)); 1262 } 1263 1264 static void 1265 eli_setkey(struct gctl_req *req) 1266 { 1267 struct g_eli_metadata md; 1268 const char *prov; 1269 int nargs; 1270 1271 nargs = gctl_get_int(req, "nargs"); 1272 if (nargs != 1) { 1273 gctl_error(req, "Invalid number of arguments."); 1274 return; 1275 } 1276 prov = gctl_get_ascii(req, "arg0"); 1277 1278 if (eli_metadata_read(req, prov, &md) == -1) 1279 return; 1280 1281 if (eli_is_attached(prov)) 1282 eli_setkey_attached(req, &md); 1283 else 1284 eli_setkey_detached(req, prov, &md); 1285 1286 if (req->error == NULL || req->error[0] == '\0') { 1287 printf("Note, that the master key encrypted with old keys " 1288 "and/or passphrase may still exists in a metadata backup " 1289 "file.\n"); 1290 } 1291 } 1292 1293 static void 1294 eli_delkey_attached(struct gctl_req *req, const char *prov __unused) 1295 { 1296 1297 gctl_issue(req); 1298 } 1299 1300 static void 1301 eli_delkey_detached(struct gctl_req *req, const char *prov) 1302 { 1303 struct g_eli_metadata md; 1304 unsigned char *mkeydst; 1305 unsigned int nkey; 1306 intmax_t val; 1307 bool all, force; 1308 1309 if (eli_metadata_read(req, prov, &md) == -1) 1310 return; 1311 1312 all = gctl_get_int(req, "all"); 1313 if (all) 1314 arc4random_buf(md.md_mkeys, sizeof(md.md_mkeys)); 1315 else { 1316 force = gctl_get_int(req, "force"); 1317 val = gctl_get_intmax(req, "keyno"); 1318 if (val == -1) { 1319 gctl_error(req, "Key number has to be specified."); 1320 return; 1321 } 1322 nkey = val; 1323 if (nkey >= G_ELI_MAXMKEYS) { 1324 gctl_error(req, "Invalid '%s' argument.", "keyno"); 1325 return; 1326 } 1327 if (!(md.md_keys & (1 << nkey)) && !force) { 1328 gctl_error(req, "Master Key %u is not set.", nkey); 1329 return; 1330 } 1331 md.md_keys &= ~(1 << nkey); 1332 if (md.md_keys == 0 && !force) { 1333 gctl_error(req, "This is the last Master Key. Use '-f' " 1334 "option if you really want to remove it."); 1335 return; 1336 } 1337 mkeydst = md.md_mkeys + nkey * G_ELI_MKEYLEN; 1338 arc4random_buf(mkeydst, G_ELI_MKEYLEN); 1339 } 1340 1341 eli_metadata_store(req, prov, &md); 1342 explicit_bzero(&md, sizeof(md)); 1343 } 1344 1345 static void 1346 eli_delkey(struct gctl_req *req) 1347 { 1348 const char *prov; 1349 int nargs; 1350 1351 nargs = gctl_get_int(req, "nargs"); 1352 if (nargs != 1) { 1353 gctl_error(req, "Invalid number of arguments."); 1354 return; 1355 } 1356 prov = gctl_get_ascii(req, "arg0"); 1357 1358 if (eli_is_attached(prov)) 1359 eli_delkey_attached(req, prov); 1360 else 1361 eli_delkey_detached(req, prov); 1362 } 1363 1364 static void 1365 eli_resume(struct gctl_req *req) 1366 { 1367 struct g_eli_metadata md; 1368 unsigned char key[G_ELI_USERKEYLEN]; 1369 const char *prov; 1370 off_t mediasize; 1371 int nargs; 1372 1373 nargs = gctl_get_int(req, "nargs"); 1374 if (nargs != 1) { 1375 gctl_error(req, "Invalid number of arguments."); 1376 return; 1377 } 1378 prov = gctl_get_ascii(req, "arg0"); 1379 1380 if (eli_metadata_read(req, prov, &md) == -1) 1381 return; 1382 1383 mediasize = g_get_mediasize(prov); 1384 if (md.md_provsize != (uint64_t)mediasize) { 1385 gctl_error(req, "Provider size mismatch."); 1386 return; 1387 } 1388 1389 if (eli_genkey(req, &md, key, false) == NULL) { 1390 explicit_bzero(key, sizeof(key)); 1391 return; 1392 } 1393 1394 gctl_ro_param(req, "key", sizeof(key), key); 1395 if (gctl_issue(req) == NULL) { 1396 if (verbose) 1397 printf("Resumed %s.\n", prov); 1398 } 1399 explicit_bzero(key, sizeof(key)); 1400 } 1401 1402 static int 1403 eli_trash_metadata(struct gctl_req *req, const char *prov, int fd, off_t offset) 1404 { 1405 unsigned int overwrites; 1406 unsigned char *sector; 1407 ssize_t size; 1408 int error; 1409 1410 size = sizeof(overwrites); 1411 if (sysctlbyname("kern.geom.eli.overwrites", &overwrites, &size, 1412 NULL, 0) == -1 || overwrites == 0) { 1413 overwrites = G_ELI_OVERWRITES; 1414 } 1415 1416 size = g_sectorsize(fd); 1417 if (size <= 0) { 1418 gctl_error(req, "Cannot obtain provider sector size %s: %s.", 1419 prov, strerror(errno)); 1420 return (-1); 1421 } 1422 sector = malloc(size); 1423 if (sector == NULL) { 1424 gctl_error(req, "Cannot allocate %zd bytes of memory.", size); 1425 return (-1); 1426 } 1427 1428 error = 0; 1429 do { 1430 arc4random_buf(sector, size); 1431 if (pwrite(fd, sector, size, offset) != size) { 1432 if (error == 0) 1433 error = errno; 1434 } 1435 (void)g_flush(fd); 1436 } while (--overwrites > 0); 1437 free(sector); 1438 if (error != 0) { 1439 gctl_error(req, "Cannot trash metadata on provider %s: %s.", 1440 prov, strerror(error)); 1441 return (-1); 1442 } 1443 return (0); 1444 } 1445 1446 static void 1447 eli_kill_detached(struct gctl_req *req, const char *prov) 1448 { 1449 off_t offset; 1450 int fd; 1451 1452 /* 1453 * NOTE: Maybe we should verify if this is geli provider first, 1454 * but 'kill' command is quite critical so better don't waste 1455 * the time. 1456 */ 1457 #if 0 1458 error = g_metadata_read(prov, (unsigned char *)&md, sizeof(md), 1459 G_ELI_MAGIC); 1460 if (error != 0) { 1461 gctl_error(req, "Cannot read metadata from %s: %s.", prov, 1462 strerror(error)); 1463 return; 1464 } 1465 #endif 1466 1467 fd = g_open(prov, 1); 1468 if (fd == -1) { 1469 gctl_error(req, "Cannot open provider %s: %s.", prov, 1470 strerror(errno)); 1471 return; 1472 } 1473 offset = g_mediasize(fd) - g_sectorsize(fd); 1474 if (offset <= 0) { 1475 gctl_error(req, 1476 "Cannot obtain media size or sector size for provider %s: %s.", 1477 prov, strerror(errno)); 1478 (void)g_close(fd); 1479 return; 1480 } 1481 (void)eli_trash_metadata(req, prov, fd, offset); 1482 (void)g_close(fd); 1483 } 1484 1485 static void 1486 eli_kill(struct gctl_req *req) 1487 { 1488 const char *prov; 1489 int i, nargs, all; 1490 1491 nargs = gctl_get_int(req, "nargs"); 1492 all = gctl_get_int(req, "all"); 1493 if (!all && nargs == 0) { 1494 gctl_error(req, "Too few arguments."); 1495 return; 1496 } 1497 /* 1498 * How '-a' option combine with a list of providers: 1499 * Delete Master Keys from all attached providers: 1500 * geli kill -a 1501 * Delete Master Keys from all attached providers and from 1502 * detached da0 and da1: 1503 * geli kill -a da0 da1 1504 * Delete Master Keys from (attached or detached) da0 and da1: 1505 * geli kill da0 da1 1506 */ 1507 1508 /* First detached providers. */ 1509 for (i = 0; i < nargs; i++) { 1510 prov = gctl_get_ascii(req, "arg%d", i); 1511 if (!eli_is_attached(prov)) 1512 eli_kill_detached(req, prov); 1513 } 1514 /* Now attached providers. */ 1515 gctl_issue(req); 1516 } 1517 1518 static int 1519 eli_backup_create(struct gctl_req *req, const char *prov, const char *file) 1520 { 1521 unsigned char *sector; 1522 ssize_t secsize; 1523 int error, filefd, ret; 1524 1525 ret = -1; 1526 filefd = -1; 1527 sector = NULL; 1528 secsize = 0; 1529 1530 secsize = g_get_sectorsize(prov); 1531 if (secsize == 0) { 1532 gctl_error(req, "Cannot get informations about %s: %s.", prov, 1533 strerror(errno)); 1534 goto out; 1535 } 1536 sector = malloc(secsize); 1537 if (sector == NULL) { 1538 gctl_error(req, "Cannot allocate memory."); 1539 goto out; 1540 } 1541 /* Read metadata from the provider. */ 1542 error = g_metadata_read(prov, sector, secsize, G_ELI_MAGIC); 1543 if (error != 0) { 1544 gctl_error(req, "Unable to read metadata from %s: %s.", prov, 1545 strerror(error)); 1546 goto out; 1547 } 1548 1549 filefd = open(file, O_WRONLY | O_TRUNC | O_CREAT, 0600); 1550 if (filefd == -1) { 1551 gctl_error(req, "Unable to open %s: %s.", file, 1552 strerror(errno)); 1553 goto out; 1554 } 1555 /* Write metadata to the destination file. */ 1556 if (write(filefd, sector, secsize) != secsize) { 1557 gctl_error(req, "Unable to write to %s: %s.", file, 1558 strerror(errno)); 1559 (void)close(filefd); 1560 (void)unlink(file); 1561 goto out; 1562 } 1563 (void)fsync(filefd); 1564 (void)close(filefd); 1565 /* Success. */ 1566 ret = 0; 1567 out: 1568 if (sector != NULL) { 1569 explicit_bzero(sector, secsize); 1570 free(sector); 1571 } 1572 return (ret); 1573 } 1574 1575 static void 1576 eli_backup(struct gctl_req *req) 1577 { 1578 const char *file, *prov; 1579 int nargs; 1580 1581 nargs = gctl_get_int(req, "nargs"); 1582 if (nargs != 2) { 1583 gctl_error(req, "Invalid number of arguments."); 1584 return; 1585 } 1586 prov = gctl_get_ascii(req, "arg0"); 1587 file = gctl_get_ascii(req, "arg1"); 1588 1589 eli_backup_create(req, prov, file); 1590 } 1591 1592 static void 1593 eli_restore(struct gctl_req *req) 1594 { 1595 struct g_eli_metadata md; 1596 const char *file, *prov; 1597 off_t mediasize; 1598 int nargs; 1599 1600 nargs = gctl_get_int(req, "nargs"); 1601 if (nargs != 2) { 1602 gctl_error(req, "Invalid number of arguments."); 1603 return; 1604 } 1605 file = gctl_get_ascii(req, "arg0"); 1606 prov = gctl_get_ascii(req, "arg1"); 1607 1608 /* Read metadata from the backup file. */ 1609 if (eli_metadata_read(req, file, &md) == -1) 1610 return; 1611 /* Obtain provider's mediasize. */ 1612 mediasize = g_get_mediasize(prov); 1613 if (mediasize == 0) { 1614 gctl_error(req, "Cannot get informations about %s: %s.", prov, 1615 strerror(errno)); 1616 return; 1617 } 1618 /* Check if the provider size has changed since we did the backup. */ 1619 if (md.md_provsize != (uint64_t)mediasize) { 1620 if (gctl_get_int(req, "force")) { 1621 md.md_provsize = mediasize; 1622 } else { 1623 gctl_error(req, "Provider size mismatch: " 1624 "wrong backup file?"); 1625 return; 1626 } 1627 } 1628 /* Write metadata to the provider. */ 1629 (void)eli_metadata_store(req, prov, &md); 1630 } 1631 1632 static void 1633 eli_resize(struct gctl_req *req) 1634 { 1635 struct g_eli_metadata md; 1636 const char *prov; 1637 unsigned char *sector; 1638 ssize_t secsize; 1639 off_t mediasize, oldsize; 1640 int error, nargs, provfd; 1641 1642 nargs = gctl_get_int(req, "nargs"); 1643 if (nargs != 1) { 1644 gctl_error(req, "Invalid number of arguments."); 1645 return; 1646 } 1647 prov = gctl_get_ascii(req, "arg0"); 1648 1649 provfd = -1; 1650 sector = NULL; 1651 secsize = 0; 1652 1653 provfd = g_open(prov, 1); 1654 if (provfd == -1) { 1655 gctl_error(req, "Cannot open %s: %s.", prov, strerror(errno)); 1656 goto out; 1657 } 1658 1659 mediasize = g_mediasize(provfd); 1660 secsize = g_sectorsize(provfd); 1661 if (mediasize == -1 || secsize == -1) { 1662 gctl_error(req, "Cannot get information about %s: %s.", prov, 1663 strerror(errno)); 1664 goto out; 1665 } 1666 1667 sector = malloc(secsize); 1668 if (sector == NULL) { 1669 gctl_error(req, "Cannot allocate memory."); 1670 goto out; 1671 } 1672 1673 oldsize = gctl_get_intmax(req, "oldsize"); 1674 if (oldsize < 0 || oldsize > mediasize) { 1675 gctl_error(req, "Invalid oldsize: Out of range."); 1676 goto out; 1677 } 1678 if (oldsize == mediasize) { 1679 gctl_error(req, "Size hasn't changed."); 1680 goto out; 1681 } 1682 1683 /* Read metadata from the 'oldsize' offset. */ 1684 if (pread(provfd, sector, secsize, oldsize - secsize) != secsize) { 1685 gctl_error(req, "Cannot read old metadata: %s.", 1686 strerror(errno)); 1687 goto out; 1688 } 1689 1690 /* Check if this sector contains geli metadata. */ 1691 error = eli_metadata_decode(sector, &md); 1692 switch (error) { 1693 case 0: 1694 break; 1695 case EOPNOTSUPP: 1696 gctl_error(req, 1697 "Provider's %s metadata version %u is too new.\n" 1698 "geli: The highest supported version is %u.", 1699 prov, (unsigned int)md.md_version, G_ELI_VERSION); 1700 goto out; 1701 case EINVAL: 1702 gctl_error(req, "Inconsistent provider's %s metadata.", prov); 1703 goto out; 1704 default: 1705 gctl_error(req, 1706 "Unexpected error while decoding provider's %s metadata: %s.", 1707 prov, strerror(error)); 1708 goto out; 1709 } 1710 1711 /* 1712 * If the old metadata doesn't have a correct provider size, refuse 1713 * to resize. 1714 */ 1715 if (md.md_provsize != (uint64_t)oldsize) { 1716 gctl_error(req, "Provider size mismatch at oldsize."); 1717 goto out; 1718 } 1719 1720 /* 1721 * Update the old metadata with the current provider size and write 1722 * it back to the correct place on the provider. 1723 */ 1724 md.md_provsize = mediasize; 1725 /* Write metadata to the provider. */ 1726 (void)eli_metadata_store(req, prov, &md); 1727 /* Now trash the old metadata. */ 1728 (void)eli_trash_metadata(req, prov, provfd, oldsize - secsize); 1729 out: 1730 if (provfd != -1) 1731 (void)g_close(provfd); 1732 if (sector != NULL) { 1733 explicit_bzero(sector, secsize); 1734 free(sector); 1735 } 1736 } 1737 1738 static void 1739 eli_version(struct gctl_req *req) 1740 { 1741 struct g_eli_metadata md; 1742 const char *name; 1743 unsigned int version; 1744 int error, i, nargs; 1745 1746 nargs = gctl_get_int(req, "nargs"); 1747 1748 if (nargs == 0) { 1749 unsigned int kernver; 1750 ssize_t size; 1751 1752 size = sizeof(kernver); 1753 if (sysctlbyname("kern.geom.eli.version", &kernver, &size, 1754 NULL, 0) == -1) { 1755 warn("Unable to obtain GELI kernel version"); 1756 } else { 1757 printf("kernel: %u\n", kernver); 1758 } 1759 printf("userland: %u\n", G_ELI_VERSION); 1760 return; 1761 } 1762 1763 for (i = 0; i < nargs; i++) { 1764 name = gctl_get_ascii(req, "arg%d", i); 1765 error = g_metadata_read(name, (unsigned char *)&md, 1766 sizeof(md), G_ELI_MAGIC); 1767 if (error != 0) { 1768 warn("%s: Unable to read metadata: %s.", name, 1769 strerror(error)); 1770 gctl_error(req, "Not fully done."); 1771 continue; 1772 } 1773 version = le32dec(&md.md_version); 1774 printf("%s: %u\n", name, version); 1775 } 1776 } 1777 1778 static void 1779 eli_clear(struct gctl_req *req) 1780 { 1781 const char *name; 1782 int error, i, nargs; 1783 1784 nargs = gctl_get_int(req, "nargs"); 1785 if (nargs < 1) { 1786 gctl_error(req, "Too few arguments."); 1787 return; 1788 } 1789 1790 for (i = 0; i < nargs; i++) { 1791 name = gctl_get_ascii(req, "arg%d", i); 1792 error = g_metadata_clear(name, G_ELI_MAGIC); 1793 if (error != 0) { 1794 fprintf(stderr, "Cannot clear metadata on %s: %s.\n", 1795 name, strerror(error)); 1796 gctl_error(req, "Not fully done."); 1797 continue; 1798 } 1799 if (verbose) 1800 printf("Metadata cleared on %s.\n", name); 1801 } 1802 } 1803 1804 static void 1805 eli_dump(struct gctl_req *req) 1806 { 1807 struct g_eli_metadata md; 1808 const char *name; 1809 int i, nargs; 1810 1811 nargs = gctl_get_int(req, "nargs"); 1812 if (nargs < 1) { 1813 gctl_error(req, "Too few arguments."); 1814 return; 1815 } 1816 1817 for (i = 0; i < nargs; i++) { 1818 name = gctl_get_ascii(req, "arg%d", i); 1819 if (eli_metadata_read(NULL, name, &md) == -1) { 1820 gctl_error(req, "Not fully done."); 1821 continue; 1822 } 1823 printf("Metadata on %s:\n", name); 1824 eli_metadata_dump(&md); 1825 printf("\n"); 1826 } 1827 } 1828