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 60uint32_t lib_version = G_LIB_VERSION; 61uint32_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 */ 71static char cached_passphrase[BUFSIZE] = ""; 72 73static void eli_main(struct gctl_req *req, unsigned flags); 74static void eli_init(struct gctl_req *req); 75static void eli_attach(struct gctl_req *req); 76static void eli_configure(struct gctl_req *req); 77static void eli_setkey(struct gctl_req *req); 78static void eli_delkey(struct gctl_req *req); 79static void eli_resume(struct gctl_req *req); 80static void eli_kill(struct gctl_req *req); 81static void eli_backup(struct gctl_req *req); 82static void eli_restore(struct gctl_req *req); 83static void eli_resize(struct gctl_req *req); 84static void eli_version(struct gctl_req *req); 85static void eli_clear(struct gctl_req *req); 86static void eli_dump(struct gctl_req *req); 87 88static 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 */ 113struct 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 283static int verbose = 0; 284 285static int 286eli_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 306static void 307eli_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 352static bool 353eli_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 366static int 367eli_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 439static int 440eli_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 482static int 483eli_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 568static unsigned char * 569eli_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 597static int 598eli_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 653static int 654eli_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 694static void 695eli_init(struct gctl_req *req) 696{ 697 struct g_eli_metadata md; 698 struct gctl_req *r; 699 unsigned char sector[sizeof(struct g_eli_metadata)] __aligned(4); 700 unsigned char key[G_ELI_USERKEYLEN]; 701 char backfile[MAXPATHLEN]; 702 const char *str, *prov; 703 unsigned int secsize, eli_version; 704 off_t mediasize; 705 intmax_t val; 706 int error, i, nargs, nparams, param; 707 const int one = 1; 708 709 nargs = gctl_get_int(req, "nargs"); 710 if (nargs <= 0) { 711 gctl_error(req, "Too few arguments."); 712 return; 713 } 714 715 /* Start generating metadata for provider(s) being initialized. */ 716 explicit_bzero(&md, sizeof(md)); 717 strlcpy(md.md_magic, G_ELI_MAGIC, sizeof(md.md_magic)); 718 val = gctl_get_intmax(req, "mdversion"); 719 if (val == -1) { 720 eli_version = G_ELI_VERSION; 721 } else if (val < 0 || val > G_ELI_VERSION) { 722 gctl_error(req, 723 "Invalid version specified should be between %u and %u.", 724 G_ELI_VERSION_00, G_ELI_VERSION); 725 return; 726 } else { 727 eli_version = val; 728 } 729 md.md_version = eli_version; 730 md.md_flags = 0; 731 if (gctl_get_int(req, "boot")) 732 md.md_flags |= G_ELI_FLAG_BOOT; 733 if (gctl_get_int(req, "geliboot")) 734 md.md_flags |= G_ELI_FLAG_GELIBOOT; 735 if (gctl_get_int(req, "displaypass")) 736 md.md_flags |= G_ELI_FLAG_GELIDISPLAYPASS; 737 if (gctl_get_int(req, "notrim")) 738 md.md_flags |= G_ELI_FLAG_NODELETE; 739 md.md_ealgo = CRYPTO_ALGORITHM_MIN - 1; 740 str = gctl_get_ascii(req, "aalgo"); 741 if (*str != '\0') { 742 if (eli_version < G_ELI_VERSION_01) { 743 gctl_error(req, 744 "Data authentication is supported starting from version %u.", 745 G_ELI_VERSION_01); 746 return; 747 } 748 md.md_aalgo = g_eli_str2aalgo(str); 749 if (md.md_aalgo >= CRYPTO_ALGORITHM_MIN && 750 md.md_aalgo <= CRYPTO_ALGORITHM_MAX) { 751 md.md_flags |= G_ELI_FLAG_AUTH; 752 } else { 753 /* 754 * For backward compatibility, check if the -a option 755 * was used to provide encryption algorithm. 756 */ 757 md.md_ealgo = g_eli_str2ealgo(str); 758 if (md.md_ealgo < CRYPTO_ALGORITHM_MIN || 759 md.md_ealgo > CRYPTO_ALGORITHM_MAX) { 760 gctl_error(req, 761 "Invalid authentication algorithm."); 762 return; 763 } else { 764 fprintf(stderr, "warning: The -e option, not " 765 "the -a option is now used to specify " 766 "encryption algorithm to use.\n"); 767 } 768 } 769 } 770 if (md.md_ealgo < CRYPTO_ALGORITHM_MIN || 771 md.md_ealgo > CRYPTO_ALGORITHM_MAX) { 772 str = gctl_get_ascii(req, "ealgo"); 773 if (*str == '\0') { 774 if (eli_version < G_ELI_VERSION_05) 775 str = "aes-cbc"; 776 else 777 str = GELI_ENC_ALGO; 778 } 779 md.md_ealgo = g_eli_str2ealgo(str); 780 if (md.md_ealgo < CRYPTO_ALGORITHM_MIN || 781 md.md_ealgo > CRYPTO_ALGORITHM_MAX) { 782 gctl_error(req, "Invalid encryption algorithm."); 783 return; 784 } 785 if (md.md_ealgo == CRYPTO_CAMELLIA_CBC && 786 eli_version < G_ELI_VERSION_04) { 787 gctl_error(req, 788 "Camellia-CBC algorithm is supported starting from version %u.", 789 G_ELI_VERSION_04); 790 return; 791 } 792 if (md.md_ealgo == CRYPTO_AES_XTS && 793 eli_version < G_ELI_VERSION_05) { 794 gctl_error(req, 795 "AES-XTS algorithm is supported starting from version %u.", 796 G_ELI_VERSION_05); 797 return; 798 } 799 } 800 if (md.md_flags & G_ELI_FLAG_AUTH) { 801 switch (md.md_aalgo) { 802 case CRYPTO_MD5_HMAC: 803 gctl_error(req, 804 "The %s authentication algorithm is deprecated.", 805 g_eli_algo2str(md.md_aalgo)); 806 return; 807 } 808 } 809 switch (md.md_ealgo) { 810 case CRYPTO_3DES_CBC: 811 case CRYPTO_BLF_CBC: 812 gctl_error(req, "The %s encryption algorithm is deprecated.", 813 g_eli_algo2str(md.md_ealgo)); 814 return; 815 } 816 val = gctl_get_intmax(req, "keylen"); 817 md.md_keylen = val; 818 md.md_keylen = g_eli_keylen(md.md_ealgo, md.md_keylen); 819 if (md.md_keylen == 0) { 820 gctl_error(req, "Invalid key length."); 821 return; 822 } 823 824 val = gctl_get_intmax(req, "iterations"); 825 if (val != -1) { 826 int nonewpassphrase; 827 828 /* 829 * Don't allow to set iterations when there will be no 830 * passphrase. 831 */ 832 nonewpassphrase = gctl_get_int(req, "nonewpassphrase"); 833 if (nonewpassphrase) { 834 gctl_error(req, 835 "Options -i and -P are mutually exclusive."); 836 return; 837 } 838 } 839 md.md_iterations = val; 840 841 val = gctl_get_intmax(req, "sectorsize"); 842 if (val > sysconf(_SC_PAGE_SIZE)) { 843 fprintf(stderr, 844 "warning: Using sectorsize bigger than the page size!\n"); 845 } 846 847 md.md_keys = 0x01; 848 849 /* 850 * Determine number of parameters in the parent geom request before the 851 * nargs parameter and list of providers. 852 */ 853 nparams = req->narg - nargs - 1; 854 855 /* Create new child request for each provider and issue to kernel */ 856 for (i = 0; i < nargs; i++) { 857 r = gctl_get_handle(); 858 859 /* Copy each parameter from the parent request to the child */ 860 for (param = 0; param < nparams; param++) { 861 gctl_ro_param(r, req->arg[param].name, 862 req->arg[param].len, req->arg[param].value); 863 } 864 865 /* Add a single provider to the parameter list of the child */ 866 gctl_ro_param(r, "nargs", sizeof(one), &one); 867 prov = gctl_get_ascii(req, "arg%d", i); 868 gctl_ro_param(r, "arg0", -1, prov); 869 870 mediasize = g_get_mediasize(prov); 871 secsize = g_get_sectorsize(prov); 872 if (mediasize == 0 || secsize == 0) { 873 gctl_error(r, "Cannot get information about %s: %s.", 874 prov, strerror(errno)); 875 goto out; 876 } 877 878 md.md_provsize = mediasize; 879 880 val = gctl_get_intmax(r, "sectorsize"); 881 if (val == 0) { 882 md.md_sectorsize = secsize; 883 } else { 884 if (val < 0 || (val % secsize) != 0 || !powerof2(val)) { 885 gctl_error(r, "Invalid sector size."); 886 goto out; 887 } 888 md.md_sectorsize = val; 889 } 890 891 /* Use different salt and Master Key for each provider. */ 892 arc4random_buf(md.md_salt, sizeof(md.md_salt)); 893 arc4random_buf(md.md_mkeys, sizeof(md.md_mkeys)); 894 895 /* Generate user key. */ 896 if (eli_genkey(r, &md, key, true) == NULL) { 897 /* 898 * Error generating key - details added to geom request 899 * by eli_genkey(). 900 */ 901 goto out; 902 } 903 904 /* Encrypt the first and the only Master Key. */ 905 error = g_eli_mkey_encrypt(md.md_ealgo, key, md.md_keylen, 906 md.md_mkeys); 907 if (error != 0) { 908 gctl_error(r, "Cannot encrypt Master Key: %s.", 909 strerror(error)); 910 goto out; 911 } 912 913 /* Convert metadata to on-disk format. */ 914 eli_metadata_encode(&md, sector); 915 916 /* Store metadata to disk. */ 917 error = g_metadata_store(prov, sector, sizeof(sector)); 918 if (error != 0) { 919 gctl_error(r, "Cannot store metadata on %s: %s.", prov, 920 strerror(error)); 921 goto out; 922 } 923 if (verbose) 924 printf("Metadata value stored on %s.\n", prov); 925 926 /* Backup metadata to a file. */ 927 const char *p = prov; 928 unsigned int j; 929 930 /* 931 * Check if provider string includes the devfs mountpoint 932 * (typically /dev/). 933 */ 934 if (strncmp(p, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0) { 935 /* Skip forward to the device filename only. */ 936 p += sizeof(_PATH_DEV) - 1; 937 } 938 939 str = gctl_get_ascii(r, "backupfile"); 940 if (str[0] != '\0') { 941 /* Backupfile given by the user, just copy it. */ 942 strlcpy(backfile, str, sizeof(backfile)); 943 944 /* If multiple providers have been initialized in one 945 * command, and the backup filename has been specified 946 * as anything other than "none", make the backup 947 * filename unique for each provider. */ 948 if (nargs > 1 && strcmp(backfile, "none") != 0) { 949 /* 950 * Replace first occurrence of "PROV" with 951 * provider name. 952 */ 953 str = strnstr(backfile, "PROV", 954 sizeof(backfile)); 955 if (str != NULL) { 956 char suffix[MAXPATHLEN]; 957 j = str - backfile; 958 strlcpy(suffix, &backfile[j+4], 959 sizeof(suffix)); 960 backfile[j] = '\0'; 961 strlcat(backfile, p, sizeof(backfile)); 962 strlcat(backfile, suffix, 963 sizeof(backfile)); 964 } else { 965 /* 966 * "PROV" not found in backfile, append 967 * provider name. 968 */ 969 strlcat(backfile, "-", 970 sizeof(backfile)); 971 strlcat(backfile, p, sizeof(backfile)); 972 } 973 } 974 } else { 975 /* Generate filename automatically. */ 976 snprintf(backfile, sizeof(backfile), "%s%s.eli", 977 GELI_BACKUP_DIR, p); 978 /* Replace all / with _. */ 979 for (j = strlen(GELI_BACKUP_DIR); backfile[j] != '\0'; 980 j++) { 981 if (backfile[j] == '/') 982 backfile[j] = '_'; 983 } 984 } 985 if (strcmp(backfile, "none") != 0 && 986 eli_backup_create(r, prov, backfile) == 0) { 987 printf("\nMetadata backup for provider %s can be found " 988 "in %s\n", prov, backfile); 989 printf("and can be restored with the following " 990 "command:\n"); 991 printf("\n\t# geli restore %s %s\n\n", backfile, prov); 992 } 993 994out: 995 /* 996 * Print error for this request, and set parent request error 997 * message. 998 */ 999 if (r->error != NULL && r->error[0] != '\0') { 1000 warnx("%s", r->error); 1001 gctl_error(req, "There was an error with at least one " 1002 "provider."); 1003 } 1004 1005 gctl_free(r); 1006 1007 /* 1008 * Erase sensitive and provider specific data from memory. 1009 */ 1010 explicit_bzero(key, sizeof(key)); 1011 explicit_bzero(sector, sizeof(sector)); 1012 explicit_bzero(&md.md_provsize, sizeof(md.md_provsize)); 1013 explicit_bzero(&md.md_sectorsize, sizeof(md.md_sectorsize)); 1014 explicit_bzero(&md.md_salt, sizeof(md.md_salt)); 1015 explicit_bzero(&md.md_mkeys, sizeof(md.md_mkeys)); 1016 } 1017 1018 /* Clear the cached metadata, including keys. */ 1019 explicit_bzero(&md, sizeof(md)); 1020} 1021 1022static void 1023eli_attach(struct gctl_req *req) 1024{ 1025 struct g_eli_metadata md; 1026 struct gctl_req *r; 1027 const char *prov; 1028 off_t mediasize; 1029 int i, nargs, nparams, param; 1030 const int one = 1; 1031 1032 nargs = gctl_get_int(req, "nargs"); 1033 if (nargs <= 0) { 1034 gctl_error(req, "Too few arguments."); 1035 return; 1036 } 1037 1038 unsigned char key[G_ELI_USERKEYLEN]; 1039 1040 /* 1041 * Determine number of parameters in the parent geom request before the 1042 * nargs parameter and list of providers. 1043 */ 1044 nparams = req->narg - nargs - 1; 1045 1046 /* Create new child request for each provider and issue to kernel */ 1047 for (i = 0; i < nargs; i++) { 1048 r = gctl_get_handle(); 1049 1050 /* Copy each parameter from the parent request to the child */ 1051 for (param = 0; param < nparams; param++) { 1052 gctl_ro_param(r, req->arg[param].name, 1053 req->arg[param].len, req->arg[param].value); 1054 } 1055 1056 /* Add a single provider to the parameter list of the child */ 1057 gctl_ro_param(r, "nargs", sizeof(one), &one); 1058 prov = gctl_get_ascii(req, "arg%d", i); 1059 gctl_ro_param(r, "arg0", -1, prov); 1060 1061 if (eli_metadata_read(r, prov, &md) == -1) { 1062 /* 1063 * Error reading metadata - details added to geom 1064 * request by eli_metadata_read(). 1065 */ 1066 goto out; 1067 } 1068 1069 mediasize = g_get_mediasize(prov); 1070 if (md.md_provsize != (uint64_t)mediasize) { 1071 gctl_error(r, "Provider size mismatch."); 1072 goto out; 1073 } 1074 1075 if (eli_genkey(r, &md, key, false) == NULL) { 1076 /* 1077 * Error generating key - details added to geom request 1078 * by eli_genkey(). 1079 */ 1080 goto out; 1081 } 1082 1083 gctl_ro_param(r, "key", sizeof(key), key); 1084 1085 if (gctl_issue(r) == NULL) { 1086 if (verbose) 1087 printf("Attached to %s.\n", prov); 1088 } 1089 1090out: 1091 /* 1092 * Print error for this request, and set parent request error 1093 * message. 1094 */ 1095 if (r->error != NULL && r->error[0] != '\0') { 1096 warnx("%s", r->error); 1097 gctl_error(req, "There was an error with at least one " 1098 "provider."); 1099 } 1100 1101 gctl_free(r); 1102 1103 /* Clear sensitive data from memory. */ 1104 explicit_bzero(key, sizeof(key)); 1105 } 1106 1107 /* Clear sensitive data from memory. */ 1108 explicit_bzero(cached_passphrase, sizeof(cached_passphrase)); 1109} 1110 1111static void 1112eli_configure_detached(struct gctl_req *req, const char *prov, int boot, 1113 int geliboot, int displaypass, int trim) 1114{ 1115 struct g_eli_metadata md; 1116 bool changed = 0; 1117 1118 if (eli_metadata_read(req, prov, &md) == -1) 1119 return; 1120 1121 if (boot == 1 && (md.md_flags & G_ELI_FLAG_BOOT)) { 1122 if (verbose) 1123 printf("BOOT flag already configured for %s.\n", prov); 1124 } else if (boot == 0 && !(md.md_flags & G_ELI_FLAG_BOOT)) { 1125 if (verbose) 1126 printf("BOOT flag not configured for %s.\n", prov); 1127 } else if (boot >= 0) { 1128 if (boot) 1129 md.md_flags |= G_ELI_FLAG_BOOT; 1130 else 1131 md.md_flags &= ~G_ELI_FLAG_BOOT; 1132 changed = 1; 1133 } 1134 1135 if (geliboot == 1 && (md.md_flags & G_ELI_FLAG_GELIBOOT)) { 1136 if (verbose) 1137 printf("GELIBOOT flag already configured for %s.\n", prov); 1138 } else if (geliboot == 0 && !(md.md_flags & G_ELI_FLAG_GELIBOOT)) { 1139 if (verbose) 1140 printf("GELIBOOT flag not configured for %s.\n", prov); 1141 } else if (geliboot >= 0) { 1142 if (geliboot) 1143 md.md_flags |= G_ELI_FLAG_GELIBOOT; 1144 else 1145 md.md_flags &= ~G_ELI_FLAG_GELIBOOT; 1146 changed = 1; 1147 } 1148 1149 if (displaypass == 1 && (md.md_flags & G_ELI_FLAG_GELIDISPLAYPASS)) { 1150 if (verbose) 1151 printf("GELIDISPLAYPASS flag already configured for %s.\n", prov); 1152 } else if (displaypass == 0 && 1153 !(md.md_flags & G_ELI_FLAG_GELIDISPLAYPASS)) { 1154 if (verbose) 1155 printf("GELIDISPLAYPASS flag not configured for %s.\n", prov); 1156 } else if (displaypass >= 0) { 1157 if (displaypass) 1158 md.md_flags |= G_ELI_FLAG_GELIDISPLAYPASS; 1159 else 1160 md.md_flags &= ~G_ELI_FLAG_GELIDISPLAYPASS; 1161 changed = 1; 1162 } 1163 1164 if (trim == 0 && (md.md_flags & G_ELI_FLAG_NODELETE)) { 1165 if (verbose) 1166 printf("TRIM disable flag already configured for %s.\n", prov); 1167 } else if (trim == 1 && !(md.md_flags & G_ELI_FLAG_NODELETE)) { 1168 if (verbose) 1169 printf("TRIM disable flag not configured for %s.\n", prov); 1170 } else if (trim >= 0) { 1171 if (trim) 1172 md.md_flags &= ~G_ELI_FLAG_NODELETE; 1173 else 1174 md.md_flags |= G_ELI_FLAG_NODELETE; 1175 changed = 1; 1176 } 1177 1178 if (changed) 1179 eli_metadata_store(req, prov, &md); 1180 explicit_bzero(&md, sizeof(md)); 1181} 1182 1183static void 1184eli_configure(struct gctl_req *req) 1185{ 1186 const char *prov; 1187 bool boot, noboot, geliboot, nogeliboot, displaypass, nodisplaypass; 1188 bool trim, notrim; 1189 int doboot, dogeliboot, dodisplaypass, dotrim; 1190 int i, nargs; 1191 1192 nargs = gctl_get_int(req, "nargs"); 1193 if (nargs == 0) { 1194 gctl_error(req, "Too few arguments."); 1195 return; 1196 } 1197 1198 boot = gctl_get_int(req, "boot"); 1199 noboot = gctl_get_int(req, "noboot"); 1200 geliboot = gctl_get_int(req, "geliboot"); 1201 nogeliboot = gctl_get_int(req, "nogeliboot"); 1202 displaypass = gctl_get_int(req, "displaypass"); 1203 nodisplaypass = gctl_get_int(req, "nodisplaypass"); 1204 trim = gctl_get_int(req, "trim"); 1205 notrim = gctl_get_int(req, "notrim"); 1206 1207 doboot = -1; 1208 if (boot && noboot) { 1209 gctl_error(req, "Options -b and -B are mutually exclusive."); 1210 return; 1211 } 1212 if (boot) 1213 doboot = 1; 1214 else if (noboot) 1215 doboot = 0; 1216 1217 dogeliboot = -1; 1218 if (geliboot && nogeliboot) { 1219 gctl_error(req, "Options -g and -G are mutually exclusive."); 1220 return; 1221 } 1222 if (geliboot) 1223 dogeliboot = 1; 1224 else if (nogeliboot) 1225 dogeliboot = 0; 1226 1227 dodisplaypass = -1; 1228 if (displaypass && nodisplaypass) { 1229 gctl_error(req, "Options -d and -D are mutually exclusive."); 1230 return; 1231 } 1232 if (displaypass) 1233 dodisplaypass = 1; 1234 else if (nodisplaypass) 1235 dodisplaypass = 0; 1236 1237 dotrim = -1; 1238 if (trim && notrim) { 1239 gctl_error(req, "Options -t and -T are mutually exclusive."); 1240 return; 1241 } 1242 if (trim) 1243 dotrim = 1; 1244 else if (notrim) 1245 dotrim = 0; 1246 1247 if (doboot == -1 && dogeliboot == -1 && dodisplaypass == -1 && 1248 dotrim == -1) { 1249 gctl_error(req, "No option given."); 1250 return; 1251 } 1252 1253 /* First attached providers. */ 1254 gctl_issue(req); 1255 /* Now the rest. */ 1256 for (i = 0; i < nargs; i++) { 1257 prov = gctl_get_ascii(req, "arg%d", i); 1258 if (!eli_is_attached(prov)) { 1259 eli_configure_detached(req, prov, doboot, dogeliboot, 1260 dodisplaypass, dotrim); 1261 } 1262 } 1263} 1264 1265static void 1266eli_setkey_attached(struct gctl_req *req, struct g_eli_metadata *md) 1267{ 1268 unsigned char key[G_ELI_USERKEYLEN]; 1269 intmax_t val, old = 0; 1270 int error; 1271 1272 val = gctl_get_intmax(req, "iterations"); 1273 /* Check if iterations number should be changed. */ 1274 if (val != -1) 1275 md->md_iterations = val; 1276 else 1277 old = md->md_iterations; 1278 1279 /* Generate key for Master Key encryption. */ 1280 if (eli_genkey(req, md, key, true) == NULL) { 1281 explicit_bzero(key, sizeof(key)); 1282 return; 1283 } 1284 /* 1285 * If number of iterations has changed, but wasn't given as a 1286 * command-line argument, update the request. 1287 */ 1288 if (val == -1 && md->md_iterations != old) { 1289 error = gctl_change_param(req, "iterations", sizeof(intmax_t), 1290 &md->md_iterations); 1291 assert(error == 0); 1292 } 1293 1294 gctl_ro_param(req, "key", sizeof(key), key); 1295 gctl_issue(req); 1296 explicit_bzero(key, sizeof(key)); 1297} 1298 1299static void 1300eli_setkey_detached(struct gctl_req *req, const char *prov, 1301 struct g_eli_metadata *md) 1302{ 1303 unsigned char key[G_ELI_USERKEYLEN], mkey[G_ELI_DATAIVKEYLEN]; 1304 unsigned char *mkeydst; 1305 unsigned int nkey; 1306 intmax_t val; 1307 int error; 1308 1309 if (md->md_keys == 0) { 1310 gctl_error(req, "No valid keys on %s.", prov); 1311 return; 1312 } 1313 1314 /* Generate key for Master Key decryption. */ 1315 if (eli_genkey(req, md, key, false) == NULL) { 1316 explicit_bzero(key, sizeof(key)); 1317 return; 1318 } 1319 1320 /* Decrypt Master Key. */ 1321 error = g_eli_mkey_decrypt_any(md, key, mkey, &nkey); 1322 explicit_bzero(key, sizeof(key)); 1323 if (error != 0) { 1324 explicit_bzero(md, sizeof(*md)); 1325 if (error == -1) 1326 gctl_error(req, "Wrong key for %s.", prov); 1327 else /* if (error > 0) */ { 1328 gctl_error(req, "Cannot decrypt Master Key: %s.", 1329 strerror(error)); 1330 } 1331 return; 1332 } 1333 if (verbose) 1334 printf("Decrypted Master Key %u.\n", nkey); 1335 1336 val = gctl_get_intmax(req, "keyno"); 1337 if (val != -1) 1338 nkey = val; 1339#if 0 1340 else 1341 ; /* Use the key number which was found during decryption. */ 1342#endif 1343 if (nkey >= G_ELI_MAXMKEYS) { 1344 gctl_error(req, "Invalid '%s' argument.", "keyno"); 1345 return; 1346 } 1347 1348 val = gctl_get_intmax(req, "iterations"); 1349 /* Check if iterations number should and can be changed. */ 1350 if (val != -1 && md->md_iterations == -1) { 1351 md->md_iterations = val; 1352 } else if (val != -1 && val != md->md_iterations) { 1353 if (bitcount32(md->md_keys) != 1) { 1354 gctl_error(req, "To be able to use '-i' option, only " 1355 "one key can be defined."); 1356 return; 1357 } 1358 if (md->md_keys != (1 << nkey)) { 1359 gctl_error(req, "Only already defined key can be " 1360 "changed when '-i' option is used."); 1361 return; 1362 } 1363 md->md_iterations = val; 1364 } 1365 1366 mkeydst = md->md_mkeys + nkey * G_ELI_MKEYLEN; 1367 md->md_keys |= (1 << nkey); 1368 1369 bcopy(mkey, mkeydst, sizeof(mkey)); 1370 explicit_bzero(mkey, sizeof(mkey)); 1371 1372 /* Generate key for Master Key encryption. */ 1373 if (eli_genkey(req, md, key, true) == NULL) { 1374 explicit_bzero(key, sizeof(key)); 1375 explicit_bzero(md, sizeof(*md)); 1376 return; 1377 } 1378 1379 /* Encrypt the Master-Key with the new key. */ 1380 error = g_eli_mkey_encrypt(md->md_ealgo, key, md->md_keylen, mkeydst); 1381 explicit_bzero(key, sizeof(key)); 1382 if (error != 0) { 1383 explicit_bzero(md, sizeof(*md)); 1384 gctl_error(req, "Cannot encrypt Master Key: %s.", 1385 strerror(error)); 1386 return; 1387 } 1388 1389 /* Store metadata with fresh key. */ 1390 eli_metadata_store(req, prov, md); 1391 explicit_bzero(md, sizeof(*md)); 1392} 1393 1394static void 1395eli_setkey(struct gctl_req *req) 1396{ 1397 struct g_eli_metadata md; 1398 const char *prov; 1399 int nargs; 1400 1401 nargs = gctl_get_int(req, "nargs"); 1402 if (nargs != 1) { 1403 gctl_error(req, "Invalid number of arguments."); 1404 return; 1405 } 1406 prov = gctl_get_ascii(req, "arg0"); 1407 1408 if (eli_metadata_read(req, prov, &md) == -1) 1409 return; 1410 1411 if (eli_is_attached(prov)) 1412 eli_setkey_attached(req, &md); 1413 else 1414 eli_setkey_detached(req, prov, &md); 1415 1416 if (req->error == NULL || req->error[0] == '\0') { 1417 printf("Note, that the master key encrypted with old keys " 1418 "and/or passphrase may still exists in a metadata backup " 1419 "file.\n"); 1420 } 1421} 1422 1423static void 1424eli_delkey_attached(struct gctl_req *req, const char *prov __unused) 1425{ 1426 1427 gctl_issue(req); 1428} 1429 1430static void 1431eli_delkey_detached(struct gctl_req *req, const char *prov) 1432{ 1433 struct g_eli_metadata md; 1434 unsigned char *mkeydst; 1435 unsigned int nkey; 1436 intmax_t val; 1437 bool all, force; 1438 1439 if (eli_metadata_read(req, prov, &md) == -1) 1440 return; 1441 1442 all = gctl_get_int(req, "all"); 1443 if (all) 1444 arc4random_buf(md.md_mkeys, sizeof(md.md_mkeys)); 1445 else { 1446 force = gctl_get_int(req, "force"); 1447 val = gctl_get_intmax(req, "keyno"); 1448 if (val == -1) { 1449 gctl_error(req, "Key number has to be specified."); 1450 return; 1451 } 1452 nkey = val; 1453 if (nkey >= G_ELI_MAXMKEYS) { 1454 gctl_error(req, "Invalid '%s' argument.", "keyno"); 1455 return; 1456 } 1457 if (!(md.md_keys & (1 << nkey)) && !force) { 1458 gctl_error(req, "Master Key %u is not set.", nkey); 1459 return; 1460 } 1461 md.md_keys &= ~(1 << nkey); 1462 if (md.md_keys == 0 && !force) { 1463 gctl_error(req, "This is the last Master Key. Use '-f' " 1464 "option if you really want to remove it."); 1465 return; 1466 } 1467 mkeydst = md.md_mkeys + nkey * G_ELI_MKEYLEN; 1468 arc4random_buf(mkeydst, G_ELI_MKEYLEN); 1469 } 1470 1471 eli_metadata_store(req, prov, &md); 1472 explicit_bzero(&md, sizeof(md)); 1473} 1474 1475static void 1476eli_delkey(struct gctl_req *req) 1477{ 1478 const char *prov; 1479 int nargs; 1480 1481 nargs = gctl_get_int(req, "nargs"); 1482 if (nargs != 1) { 1483 gctl_error(req, "Invalid number of arguments."); 1484 return; 1485 } 1486 prov = gctl_get_ascii(req, "arg0"); 1487 1488 if (eli_is_attached(prov)) 1489 eli_delkey_attached(req, prov); 1490 else 1491 eli_delkey_detached(req, prov); 1492} 1493 1494static void 1495eli_resume(struct gctl_req *req) 1496{ 1497 struct g_eli_metadata md; 1498 unsigned char key[G_ELI_USERKEYLEN]; 1499 const char *prov; 1500 off_t mediasize; 1501 int nargs; 1502 1503 nargs = gctl_get_int(req, "nargs"); 1504 if (nargs != 1) { 1505 gctl_error(req, "Invalid number of arguments."); 1506 return; 1507 } 1508 prov = gctl_get_ascii(req, "arg0"); 1509 1510 if (eli_metadata_read(req, prov, &md) == -1) 1511 return; 1512 1513 mediasize = g_get_mediasize(prov); 1514 if (md.md_provsize != (uint64_t)mediasize) { 1515 gctl_error(req, "Provider size mismatch."); 1516 return; 1517 } 1518 1519 if (eli_genkey(req, &md, key, false) == NULL) { 1520 explicit_bzero(key, sizeof(key)); 1521 return; 1522 } 1523 1524 gctl_ro_param(req, "key", sizeof(key), key); 1525 if (gctl_issue(req) == NULL) { 1526 if (verbose) 1527 printf("Resumed %s.\n", prov); 1528 } 1529 explicit_bzero(key, sizeof(key)); 1530} 1531 1532static int 1533eli_trash_metadata(struct gctl_req *req, const char *prov, int fd, off_t offset) 1534{ 1535 unsigned int overwrites; 1536 unsigned char *sector; 1537 ssize_t size; 1538 int error; 1539 1540 size = sizeof(overwrites); 1541 if (sysctlbyname("kern.geom.eli.overwrites", &overwrites, &size, 1542 NULL, 0) == -1 || overwrites == 0) { 1543 overwrites = G_ELI_OVERWRITES; 1544 } 1545 1546 size = g_sectorsize(fd); 1547 if (size <= 0) { 1548 gctl_error(req, "Cannot obtain provider sector size %s: %s.", 1549 prov, strerror(errno)); 1550 return (-1); 1551 } 1552 sector = malloc(size); 1553 if (sector == NULL) { 1554 gctl_error(req, "Cannot allocate %zd bytes of memory.", size); 1555 return (-1); 1556 } 1557 1558 error = 0; 1559 do { 1560 arc4random_buf(sector, size); 1561 if (pwrite(fd, sector, size, offset) != size) { 1562 if (error == 0) 1563 error = errno; 1564 } 1565 (void)g_flush(fd); 1566 } while (--overwrites > 0); 1567 free(sector); 1568 if (error != 0) { 1569 gctl_error(req, "Cannot trash metadata on provider %s: %s.", 1570 prov, strerror(error)); 1571 return (-1); 1572 } 1573 return (0); 1574} 1575 1576static void 1577eli_kill_detached(struct gctl_req *req, const char *prov) 1578{ 1579 off_t offset; 1580 int fd; 1581 1582 /* 1583 * NOTE: Maybe we should verify if this is geli provider first, 1584 * but 'kill' command is quite critical so better don't waste 1585 * the time. 1586 */ 1587#if 0 1588 error = g_metadata_read(prov, (unsigned char *)&md, sizeof(md), 1589 G_ELI_MAGIC); 1590 if (error != 0) { 1591 gctl_error(req, "Cannot read metadata from %s: %s.", prov, 1592 strerror(error)); 1593 return; 1594 } 1595#endif 1596 1597 fd = g_open(prov, 1); 1598 if (fd == -1) { 1599 gctl_error(req, "Cannot open provider %s: %s.", prov, 1600 strerror(errno)); 1601 return; 1602 } 1603 offset = g_mediasize(fd) - g_sectorsize(fd); 1604 if (offset <= 0) { 1605 gctl_error(req, 1606 "Cannot obtain media size or sector size for provider %s: %s.", 1607 prov, strerror(errno)); 1608 (void)g_close(fd); 1609 return; 1610 } 1611 (void)eli_trash_metadata(req, prov, fd, offset); 1612 (void)g_close(fd); 1613} 1614 1615static void 1616eli_kill(struct gctl_req *req) 1617{ 1618 const char *prov; 1619 int i, nargs, all; 1620 1621 nargs = gctl_get_int(req, "nargs"); 1622 all = gctl_get_int(req, "all"); 1623 if (!all && nargs == 0) { 1624 gctl_error(req, "Too few arguments."); 1625 return; 1626 } 1627 /* 1628 * How '-a' option combine with a list of providers: 1629 * Delete Master Keys from all attached providers: 1630 * geli kill -a 1631 * Delete Master Keys from all attached providers and from 1632 * detached da0 and da1: 1633 * geli kill -a da0 da1 1634 * Delete Master Keys from (attached or detached) da0 and da1: 1635 * geli kill da0 da1 1636 */ 1637 1638 /* First detached providers. */ 1639 for (i = 0; i < nargs; i++) { 1640 prov = gctl_get_ascii(req, "arg%d", i); 1641 if (!eli_is_attached(prov)) 1642 eli_kill_detached(req, prov); 1643 } 1644 /* Now attached providers. */ 1645 gctl_issue(req); 1646} 1647 1648static int 1649eli_backup_create(struct gctl_req *req, const char *prov, const char *file) 1650{ 1651 unsigned char *sector; 1652 ssize_t secsize; 1653 int error, filefd, ret; 1654 1655 ret = -1; 1656 filefd = -1; 1657 sector = NULL; 1658 secsize = 0; 1659 1660 secsize = g_get_sectorsize(prov); 1661 if (secsize == 0) { 1662 gctl_error(req, "Cannot get informations about %s: %s.", prov, 1663 strerror(errno)); 1664 goto out; 1665 } 1666 sector = malloc(secsize); 1667 if (sector == NULL) { 1668 gctl_error(req, "Cannot allocate memory."); 1669 goto out; 1670 } 1671 /* Read metadata from the provider. */ 1672 error = g_metadata_read(prov, sector, secsize, G_ELI_MAGIC); 1673 if (error != 0) { 1674 gctl_error(req, "Unable to read metadata from %s: %s.", prov, 1675 strerror(error)); 1676 goto out; 1677 } 1678 1679 filefd = open(file, O_WRONLY | O_TRUNC | O_CREAT, 0600); 1680 if (filefd == -1) { 1681 gctl_error(req, "Unable to open %s: %s.", file, 1682 strerror(errno)); 1683 goto out; 1684 } 1685 /* Write metadata to the destination file. */ 1686 if (write(filefd, sector, secsize) != secsize) { 1687 gctl_error(req, "Unable to write to %s: %s.", file, 1688 strerror(errno)); 1689 (void)close(filefd); 1690 (void)unlink(file); 1691 goto out; 1692 } 1693 (void)fsync(filefd); 1694 (void)close(filefd); 1695 /* Success. */ 1696 ret = 0; 1697out: 1698 if (sector != NULL) { 1699 explicit_bzero(sector, secsize); 1700 free(sector); 1701 } 1702 return (ret); 1703} 1704 1705static void 1706eli_backup(struct gctl_req *req) 1707{ 1708 const char *file, *prov; 1709 int nargs; 1710 1711 nargs = gctl_get_int(req, "nargs"); 1712 if (nargs != 2) { 1713 gctl_error(req, "Invalid number of arguments."); 1714 return; 1715 } 1716 prov = gctl_get_ascii(req, "arg0"); 1717 file = gctl_get_ascii(req, "arg1"); 1718 1719 eli_backup_create(req, prov, file); 1720} 1721 1722static void 1723eli_restore(struct gctl_req *req) 1724{ 1725 struct g_eli_metadata md; 1726 const char *file, *prov; 1727 off_t mediasize; 1728 int nargs; 1729 1730 nargs = gctl_get_int(req, "nargs"); 1731 if (nargs != 2) { 1732 gctl_error(req, "Invalid number of arguments."); 1733 return; 1734 } 1735 file = gctl_get_ascii(req, "arg0"); 1736 prov = gctl_get_ascii(req, "arg1"); 1737 1738 /* Read metadata from the backup file. */ 1739 if (eli_metadata_read(req, file, &md) == -1) 1740 return; 1741 /* Obtain provider's mediasize. */ 1742 mediasize = g_get_mediasize(prov); 1743 if (mediasize == 0) { 1744 gctl_error(req, "Cannot get informations about %s: %s.", prov, 1745 strerror(errno)); 1746 return; 1747 } 1748 /* Check if the provider size has changed since we did the backup. */ 1749 if (md.md_provsize != (uint64_t)mediasize) { 1750 if (gctl_get_int(req, "force")) { 1751 md.md_provsize = mediasize; 1752 } else { 1753 gctl_error(req, "Provider size mismatch: " 1754 "wrong backup file?"); 1755 return; 1756 } 1757 } 1758 /* Write metadata to the provider. */ 1759 (void)eli_metadata_store(req, prov, &md); 1760} 1761 1762static void 1763eli_resize(struct gctl_req *req) 1764{ 1765 struct g_eli_metadata md; 1766 const char *prov; 1767 unsigned char *sector; 1768 ssize_t secsize; 1769 off_t mediasize, oldsize; 1770 int error, nargs, provfd; 1771 1772 nargs = gctl_get_int(req, "nargs"); 1773 if (nargs != 1) { 1774 gctl_error(req, "Invalid number of arguments."); 1775 return; 1776 } 1777 prov = gctl_get_ascii(req, "arg0"); 1778 1779 provfd = -1; 1780 sector = NULL; 1781 secsize = 0; 1782 1783 provfd = g_open(prov, 1); 1784 if (provfd == -1) { 1785 gctl_error(req, "Cannot open %s: %s.", prov, strerror(errno)); 1786 goto out; 1787 } 1788 1789 mediasize = g_mediasize(provfd); 1790 secsize = g_sectorsize(provfd); 1791 if (mediasize == -1 || secsize == -1) { 1792 gctl_error(req, "Cannot get information about %s: %s.", prov, 1793 strerror(errno)); 1794 goto out; 1795 } 1796 1797 sector = malloc(secsize); 1798 if (sector == NULL) { 1799 gctl_error(req, "Cannot allocate memory."); 1800 goto out; 1801 } 1802 1803 oldsize = gctl_get_intmax(req, "oldsize"); 1804 if (oldsize < 0 || oldsize > mediasize) { 1805 gctl_error(req, "Invalid oldsize: Out of range."); 1806 goto out; 1807 } 1808 if (oldsize == mediasize) { 1809 gctl_error(req, "Size hasn't changed."); 1810 goto out; 1811 } 1812 1813 /* Read metadata from the 'oldsize' offset. */ 1814 if (pread(provfd, sector, secsize, oldsize - secsize) != secsize) { 1815 gctl_error(req, "Cannot read old metadata: %s.", 1816 strerror(errno)); 1817 goto out; 1818 } 1819 1820 /* Check if this sector contains geli metadata. */ 1821 error = eli_metadata_decode(sector, &md); 1822 switch (error) { 1823 case 0: 1824 break; 1825 case EOPNOTSUPP: 1826 gctl_error(req, 1827 "Provider's %s metadata version %u is too new.\n" 1828 "geli: The highest supported version is %u.", 1829 prov, (unsigned int)md.md_version, G_ELI_VERSION); 1830 goto out; 1831 case EINVAL: 1832 gctl_error(req, "Inconsistent provider's %s metadata.", prov); 1833 goto out; 1834 default: 1835 gctl_error(req, 1836 "Unexpected error while decoding provider's %s metadata: %s.", 1837 prov, strerror(error)); 1838 goto out; 1839 } 1840 1841 /* 1842 * If the old metadata doesn't have a correct provider size, refuse 1843 * to resize. 1844 */ 1845 if (md.md_provsize != (uint64_t)oldsize) { 1846 gctl_error(req, "Provider size mismatch at oldsize."); 1847 goto out; 1848 } 1849 1850 /* 1851 * Update the old metadata with the current provider size and write 1852 * it back to the correct place on the provider. 1853 */ 1854 md.md_provsize = mediasize; 1855 /* Write metadata to the provider. */ 1856 (void)eli_metadata_store(req, prov, &md); 1857 /* Now trash the old metadata. */ 1858 (void)eli_trash_metadata(req, prov, provfd, oldsize - secsize); 1859out: 1860 if (provfd != -1) 1861 (void)g_close(provfd); 1862 if (sector != NULL) { 1863 explicit_bzero(sector, secsize); 1864 free(sector); 1865 } 1866} 1867 1868static void 1869eli_version(struct gctl_req *req) 1870{ 1871 struct g_eli_metadata md; 1872 const char *name; 1873 unsigned int eli_version; 1874 int error, i, nargs; 1875 1876 nargs = gctl_get_int(req, "nargs"); 1877 1878 if (nargs == 0) { 1879 unsigned int kernver; 1880 ssize_t size; 1881 1882 size = sizeof(kernver); 1883 if (sysctlbyname("kern.geom.eli.version", &kernver, &size, 1884 NULL, 0) == -1) { 1885 warn("Unable to obtain GELI kernel version"); 1886 } else { 1887 printf("kernel: %u\n", kernver); 1888 } 1889 printf("userland: %u\n", G_ELI_VERSION); 1890 return; 1891 } 1892 1893 for (i = 0; i < nargs; i++) { 1894 name = gctl_get_ascii(req, "arg%d", i); 1895 error = g_metadata_read(name, (unsigned char *)&md, 1896 sizeof(md), G_ELI_MAGIC); 1897 if (error != 0) { 1898 warn("%s: Unable to read metadata: %s.", name, 1899 strerror(error)); 1900 gctl_error(req, "Not fully done."); 1901 continue; 1902 } 1903 eli_version = le32dec(&md.md_version); 1904 printf("%s: %u\n", name, eli_version); 1905 } 1906} 1907 1908static void 1909eli_clear(struct gctl_req *req) 1910{ 1911 const char *name; 1912 int error, i, nargs; 1913 1914 nargs = gctl_get_int(req, "nargs"); 1915 if (nargs < 1) { 1916 gctl_error(req, "Too few arguments."); 1917 return; 1918 } 1919 1920 for (i = 0; i < nargs; i++) { 1921 name = gctl_get_ascii(req, "arg%d", i); 1922 error = g_metadata_clear(name, G_ELI_MAGIC); 1923 if (error != 0) { 1924 fprintf(stderr, "Cannot clear metadata on %s: %s.\n", 1925 name, strerror(error)); 1926 gctl_error(req, "Not fully done."); 1927 continue; 1928 } 1929 if (verbose) 1930 printf("Metadata cleared on %s.\n", name); 1931 } 1932} 1933 1934static void 1935eli_dump(struct gctl_req *req) 1936{ 1937 struct g_eli_metadata md; 1938 const char *name; 1939 int i, nargs; 1940 1941 nargs = gctl_get_int(req, "nargs"); 1942 if (nargs < 1) { 1943 gctl_error(req, "Too few arguments."); 1944 return; 1945 } 1946 1947 for (i = 0; i < nargs; i++) { 1948 name = gctl_get_ascii(req, "arg%d", i); 1949 if (eli_metadata_read(NULL, name, &md) == -1) { 1950 gctl_error(req, "Not fully done."); 1951 continue; 1952 } 1953 printf("Metadata on %s:\n", name); 1954 eli_metadata_dump(&md); 1955 printf("\n"); 1956 } 1957} 1958