1 /*- 2 * Copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include <sys/cdefs.h> 28 __FBSDID("$FreeBSD$"); 29 30 #include <sys/param.h> 31 #include <sys/systm.h> 32 #include <sys/kernel.h> 33 #include <sys/module.h> 34 #include <sys/lock.h> 35 #include <sys/mutex.h> 36 #include <sys/bio.h> 37 #include <sys/sysctl.h> 38 #include <sys/malloc.h> 39 #include <sys/kthread.h> 40 #include <sys/proc.h> 41 #include <sys/sched.h> 42 #include <sys/uio.h> 43 44 #include <vm/uma.h> 45 46 #include <geom/geom.h> 47 #include <geom/eli/g_eli.h> 48 49 50 MALLOC_DECLARE(M_ELI); 51 52 53 static void 54 g_eli_ctl_attach(struct gctl_req *req, struct g_class *mp) 55 { 56 struct g_eli_metadata md; 57 struct g_provider *pp; 58 const char *name; 59 u_char *key, mkey[G_ELI_DATAIVKEYLEN]; 60 int *nargs, *detach; 61 int keysize, error; 62 u_int nkey; 63 64 g_topology_assert(); 65 66 nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); 67 if (nargs == NULL) { 68 gctl_error(req, "No '%s' argument.", "nargs"); 69 return; 70 } 71 if (*nargs != 1) { 72 gctl_error(req, "Invalid number of arguments."); 73 return; 74 } 75 76 detach = gctl_get_paraml(req, "detach", sizeof(*detach)); 77 if (detach == NULL) { 78 gctl_error(req, "No '%s' argument.", "detach"); 79 return; 80 } 81 82 name = gctl_get_asciiparam(req, "arg0"); 83 if (name == NULL) { 84 gctl_error(req, "No 'arg%u' argument.", 0); 85 return; 86 } 87 if (strncmp(name, "/dev/", strlen("/dev/")) == 0) 88 name += strlen("/dev/"); 89 pp = g_provider_by_name(name); 90 if (pp == NULL) { 91 gctl_error(req, "Provider %s is invalid.", name); 92 return; 93 } 94 error = g_eli_read_metadata(mp, pp, &md); 95 if (error != 0) { 96 gctl_error(req, "Cannot read metadata from %s (error=%d).", 97 name, error); 98 return; 99 } 100 if (md.md_keys == 0x00) { 101 bzero(&md, sizeof(md)); 102 gctl_error(req, "No valid keys on %s.", pp->name); 103 return; 104 } 105 106 key = gctl_get_param(req, "key", &keysize); 107 if (key == NULL || keysize != G_ELI_USERKEYLEN) { 108 bzero(&md, sizeof(md)); 109 gctl_error(req, "No '%s' argument.", "key"); 110 return; 111 } 112 113 error = g_eli_mkey_decrypt(&md, key, mkey, &nkey); 114 bzero(key, keysize); 115 if (error == -1) { 116 bzero(&md, sizeof(md)); 117 gctl_error(req, "Wrong key for %s.", pp->name); 118 return; 119 } else if (error > 0) { 120 bzero(&md, sizeof(md)); 121 gctl_error(req, "Cannot decrypt Master Key for %s (error=%d).", 122 pp->name, error); 123 return; 124 } 125 G_ELI_DEBUG(1, "Using Master Key %u for %s.", nkey, pp->name); 126 127 if (*detach) 128 md.md_flags |= G_ELI_FLAG_WO_DETACH; 129 g_eli_create(req, mp, pp, &md, mkey, nkey); 130 bzero(mkey, sizeof(mkey)); 131 bzero(&md, sizeof(md)); 132 } 133 134 static struct g_eli_softc * 135 g_eli_find_device(struct g_class *mp, const char *prov) 136 { 137 struct g_eli_softc *sc; 138 struct g_geom *gp; 139 struct g_provider *pp; 140 struct g_consumer *cp; 141 142 if (strncmp(prov, "/dev/", strlen("/dev/")) == 0) 143 prov += strlen("/dev/"); 144 LIST_FOREACH(gp, &mp->geom, geom) { 145 sc = gp->softc; 146 if (sc == NULL) 147 continue; 148 pp = LIST_FIRST(&gp->provider); 149 if (pp != NULL && strcmp(pp->name, prov) == 0) 150 return (sc); 151 cp = LIST_FIRST(&gp->consumer); 152 if (cp != NULL && cp->provider != NULL && 153 strcmp(cp->provider->name, prov) == 0) { 154 return (sc); 155 } 156 } 157 return (NULL); 158 } 159 160 static void 161 g_eli_ctl_detach(struct gctl_req *req, struct g_class *mp) 162 { 163 struct g_eli_softc *sc; 164 int *force, *last, *nargs, error; 165 const char *prov; 166 char param[16]; 167 u_int i; 168 169 g_topology_assert(); 170 171 nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); 172 if (nargs == NULL) { 173 gctl_error(req, "No '%s' argument.", "nargs"); 174 return; 175 } 176 if (*nargs <= 0) { 177 gctl_error(req, "Missing device(s)."); 178 return; 179 } 180 force = gctl_get_paraml(req, "force", sizeof(*force)); 181 if (force == NULL) { 182 gctl_error(req, "No '%s' argument.", "force"); 183 return; 184 } 185 last = gctl_get_paraml(req, "last", sizeof(*last)); 186 if (last == NULL) { 187 gctl_error(req, "No '%s' argument.", "last"); 188 return; 189 } 190 191 for (i = 0; i < (u_int)*nargs; i++) { 192 snprintf(param, sizeof(param), "arg%u", i); 193 prov = gctl_get_asciiparam(req, param); 194 if (prov == NULL) { 195 gctl_error(req, "No 'arg%u' argument.", i); 196 return; 197 } 198 sc = g_eli_find_device(mp, prov); 199 if (sc == NULL) { 200 gctl_error(req, "No such device: %s.", prov); 201 return; 202 } 203 if (*last) { 204 sc->sc_flags |= G_ELI_FLAG_RW_DETACH; 205 sc->sc_geom->access = g_eli_access; 206 } else { 207 error = g_eli_destroy(sc, *force); 208 if (error != 0) { 209 gctl_error(req, 210 "Cannot destroy device %s (error=%d).", 211 sc->sc_name, error); 212 return; 213 } 214 } 215 } 216 } 217 218 static void 219 g_eli_ctl_onetime(struct gctl_req *req, struct g_class *mp) 220 { 221 struct g_eli_metadata md; 222 struct g_provider *pp; 223 const char *name; 224 intmax_t *keylen, *sectorsize; 225 u_char mkey[G_ELI_DATAIVKEYLEN]; 226 int *nargs, *detach; 227 228 g_topology_assert(); 229 bzero(&md, sizeof(md)); 230 231 nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); 232 if (nargs == NULL) { 233 gctl_error(req, "No '%s' argument.", "nargs"); 234 return; 235 } 236 if (*nargs != 1) { 237 gctl_error(req, "Invalid number of arguments."); 238 return; 239 } 240 241 detach = gctl_get_paraml(req, "detach", sizeof(*detach)); 242 if (detach == NULL) { 243 gctl_error(req, "No '%s' argument.", "detach"); 244 return; 245 } 246 247 strlcpy(md.md_magic, G_ELI_MAGIC, sizeof(md.md_magic)); 248 md.md_version = G_ELI_VERSION; 249 md.md_flags |= G_ELI_FLAG_ONETIME; 250 if (*detach) 251 md.md_flags |= G_ELI_FLAG_WO_DETACH; 252 253 name = gctl_get_asciiparam(req, "algo"); 254 if (name == NULL) { 255 gctl_error(req, "No '%s' argument.", "algo"); 256 return; 257 } 258 md.md_algo = g_eli_str2algo(name); 259 if (md.md_algo < CRYPTO_ALGORITHM_MIN || 260 md.md_algo > CRYPTO_ALGORITHM_MAX) { 261 gctl_error(req, "Invalid '%s' argument.", "algo"); 262 return; 263 } 264 265 keylen = gctl_get_paraml(req, "keylen", sizeof(*keylen)); 266 if (keylen == NULL) { 267 gctl_error(req, "No '%s' argument.", "keylen"); 268 return; 269 } 270 md.md_keylen = g_eli_keylen(md.md_algo, *keylen); 271 if (md.md_keylen == 0) { 272 gctl_error(req, "Invalid '%s' argument.", "keylen"); 273 return; 274 } 275 276 /* Not important here. */ 277 md.md_provsize = 0; 278 /* Not important here. */ 279 bzero(md.md_salt, sizeof(md.md_salt)); 280 281 md.md_keys = 0x01; 282 arc4rand(mkey, sizeof(mkey), 0); 283 284 /* Not important here. */ 285 bzero(md.md_hash, sizeof(md.md_hash)); 286 287 name = gctl_get_asciiparam(req, "arg0"); 288 if (name == NULL) { 289 gctl_error(req, "No 'arg%u' argument.", 0); 290 return; 291 } 292 if (strncmp(name, "/dev/", strlen("/dev/")) == 0) 293 name += strlen("/dev/"); 294 pp = g_provider_by_name(name); 295 if (pp == NULL) { 296 gctl_error(req, "Provider %s is invalid.", name); 297 return; 298 } 299 300 sectorsize = gctl_get_paraml(req, "sectorsize", sizeof(*sectorsize)); 301 if (sectorsize == NULL) { 302 gctl_error(req, "No '%s' argument.", "sectorsize"); 303 return; 304 } 305 if (*sectorsize == 0) 306 md.md_sectorsize = pp->sectorsize; 307 else { 308 if (*sectorsize < 0 || (*sectorsize % pp->sectorsize) != 0) { 309 gctl_error(req, "Invalid sector size."); 310 return; 311 } 312 md.md_sectorsize = *sectorsize; 313 } 314 315 g_eli_create(req, mp, pp, &md, mkey, -1); 316 bzero(mkey, sizeof(mkey)); 317 bzero(&md, sizeof(md)); 318 } 319 320 static void 321 g_eli_ctl_setkey(struct gctl_req *req, struct g_class *mp) 322 { 323 struct g_eli_softc *sc; 324 struct g_eli_metadata md; 325 struct g_provider *pp; 326 struct g_consumer *cp; 327 const char *name; 328 u_char *key, *mkeydst, *sector; 329 intmax_t *valp; 330 int keysize, nkey, error; 331 332 g_topology_assert(); 333 334 name = gctl_get_asciiparam(req, "arg0"); 335 if (name == NULL) { 336 gctl_error(req, "No 'arg%u' argument.", 0); 337 return; 338 } 339 sc = g_eli_find_device(mp, name); 340 if (sc == NULL) { 341 gctl_error(req, "Provider %s is invalid.", name); 342 return; 343 } 344 cp = LIST_FIRST(&sc->sc_geom->consumer); 345 pp = cp->provider; 346 347 error = g_eli_read_metadata(mp, pp, &md); 348 if (error != 0) { 349 gctl_error(req, "Cannot read metadata from %s (error=%d).", 350 name, error); 351 return; 352 } 353 354 valp = gctl_get_paraml(req, "keyno", sizeof(*valp)); 355 if (valp == NULL) { 356 gctl_error(req, "No '%s' argument.", "keyno"); 357 return; 358 } 359 if (*valp != -1) 360 nkey = *valp; 361 else 362 nkey = sc->sc_nkey; 363 if (nkey < 0 || nkey >= G_ELI_MAXMKEYS) { 364 gctl_error(req, "Invalid '%s' argument.", "keyno"); 365 return; 366 } 367 368 valp = gctl_get_paraml(req, "iterations", sizeof(*valp)); 369 if (valp == NULL) { 370 gctl_error(req, "No '%s' argument.", "iterations"); 371 return; 372 } 373 /* Check if iterations number should and can be changed. */ 374 if (*valp != -1) { 375 if (bitcount32(md.md_keys) != 1) { 376 gctl_error(req, "To be able to use '-i' option, only " 377 "one key can be defined."); 378 return; 379 } 380 if (md.md_keys != (1 << nkey)) { 381 gctl_error(req, "Only already defined key can be " 382 "changed when '-i' option is used."); 383 return; 384 } 385 md.md_iterations = *valp; 386 } 387 388 key = gctl_get_param(req, "key", &keysize); 389 if (key == NULL || keysize != G_ELI_USERKEYLEN) { 390 bzero(&md, sizeof(md)); 391 gctl_error(req, "No '%s' argument.", "key"); 392 return; 393 } 394 395 mkeydst = md.md_mkeys + nkey * G_ELI_MKEYLEN; 396 md.md_keys |= (1 << nkey); 397 398 bcopy(sc->sc_ivkey, mkeydst, sizeof(sc->sc_ivkey)); 399 bcopy(sc->sc_datakey, mkeydst + sizeof(sc->sc_ivkey), 400 sizeof(sc->sc_datakey)); 401 402 /* Encrypt Master Key with the new key. */ 403 error = g_eli_mkey_encrypt(md.md_algo, key, md.md_keylen, mkeydst); 404 bzero(key, sizeof(key)); 405 if (error != 0) { 406 bzero(&md, sizeof(md)); 407 gctl_error(req, "Cannot encrypt Master Key (error=%d).", error); 408 return; 409 } 410 411 sector = malloc(pp->sectorsize, M_ELI, M_WAITOK | M_ZERO); 412 /* Store metadata with fresh key. */ 413 eli_metadata_encode(&md, sector); 414 bzero(&md, sizeof(md)); 415 error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector, 416 pp->sectorsize); 417 bzero(sector, sizeof(sector)); 418 free(sector, M_ELI); 419 if (error != 0) { 420 gctl_error(req, "Cannot store metadata on %s (error=%d).", 421 pp->name, error); 422 return; 423 } 424 G_ELI_DEBUG(1, "Key %u changed on %s.", nkey, pp->name); 425 } 426 427 static void 428 g_eli_ctl_delkey(struct gctl_req *req, struct g_class *mp) 429 { 430 struct g_eli_softc *sc; 431 struct g_eli_metadata md; 432 struct g_provider *pp; 433 struct g_consumer *cp; 434 const char *name; 435 u_char *mkeydst, *sector; 436 intmax_t *valp; 437 size_t keysize; 438 int error, nkey, *all, *force; 439 u_int i; 440 441 g_topology_assert(); 442 443 nkey = 0; /* fixes causeless gcc warning */ 444 445 name = gctl_get_asciiparam(req, "arg0"); 446 if (name == NULL) { 447 gctl_error(req, "No 'arg%u' argument.", 0); 448 return; 449 } 450 sc = g_eli_find_device(mp, name); 451 if (sc == NULL) { 452 gctl_error(req, "Provider %s is invalid.", name); 453 return; 454 } 455 cp = LIST_FIRST(&sc->sc_geom->consumer); 456 pp = cp->provider; 457 458 error = g_eli_read_metadata(mp, pp, &md); 459 if (error != 0) { 460 gctl_error(req, "Cannot read metadata from %s (error=%d).", 461 name, error); 462 return; 463 } 464 465 all = gctl_get_paraml(req, "all", sizeof(*all)); 466 if (all == NULL) { 467 gctl_error(req, "No '%s' argument.", "all"); 468 return; 469 } 470 471 if (*all) { 472 mkeydst = md.md_mkeys; 473 keysize = sizeof(md.md_mkeys); 474 } else { 475 force = gctl_get_paraml(req, "force", sizeof(*force)); 476 if (force == NULL) { 477 gctl_error(req, "No '%s' argument.", "force"); 478 return; 479 } 480 481 valp = gctl_get_paraml(req, "keyno", sizeof(*valp)); 482 if (valp == NULL) { 483 gctl_error(req, "No '%s' argument.", "keyno"); 484 return; 485 } 486 if (*valp != -1) 487 nkey = *valp; 488 else 489 nkey = sc->sc_nkey; 490 if (nkey < 0 || nkey >= G_ELI_MAXMKEYS) { 491 gctl_error(req, "Invalid '%s' argument.", "keyno"); 492 return; 493 } 494 if (!(md.md_keys & (1 << nkey)) && !*force) { 495 gctl_error(req, "Master Key %u is not set.", nkey); 496 return; 497 } 498 md.md_keys &= ~(1 << nkey); 499 if (md.md_keys == 0 && !*force) { 500 gctl_error(req, "This is the last Master Key. Use '-f' " 501 "flag if you really want to remove it."); 502 return; 503 } 504 mkeydst = md.md_mkeys + nkey * G_ELI_MKEYLEN; 505 keysize = G_ELI_MKEYLEN; 506 } 507 508 sector = malloc(pp->sectorsize, M_ELI, M_WAITOK | M_ZERO); 509 for (i = 0; i <= g_eli_overwrites; i++) { 510 if (i == g_eli_overwrites) 511 bzero(mkeydst, keysize); 512 else 513 arc4rand(mkeydst, keysize, 0); 514 /* Store metadata with destroyed key. */ 515 eli_metadata_encode(&md, sector); 516 error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector, 517 pp->sectorsize); 518 if (error != 0) { 519 G_ELI_DEBUG(0, "Cannot store metadata on %s " 520 "(error=%d).", pp->name, error); 521 } 522 } 523 bzero(&md, sizeof(md)); 524 bzero(sector, sizeof(sector)); 525 free(sector, M_ELI); 526 if (*all) 527 G_ELI_DEBUG(1, "All keys removed from %s.", pp->name); 528 else 529 G_ELI_DEBUG(1, "Key %d removed from %s.", nkey, pp->name); 530 } 531 532 static int 533 g_eli_kill_one(struct g_eli_softc *sc) 534 { 535 struct g_provider *pp; 536 struct g_consumer *cp; 537 u_char *sector; 538 int err, error = 0; 539 u_int i; 540 541 g_topology_assert(); 542 543 if (sc == NULL) 544 return (ENOENT); 545 546 pp = LIST_FIRST(&sc->sc_geom->provider); 547 g_error_provider(pp, ENXIO); 548 549 cp = LIST_FIRST(&sc->sc_geom->consumer); 550 pp = cp->provider; 551 552 sector = malloc(pp->sectorsize, M_ELI, M_WAITOK); 553 for (i = 0; i <= g_eli_overwrites; i++) { 554 if (i == g_eli_overwrites) 555 bzero(sector, pp->sectorsize); 556 else 557 arc4rand(sector, pp->sectorsize, 0); 558 err = g_write_data(cp, pp->mediasize - pp->sectorsize, sector, 559 pp->sectorsize); 560 if (err != 0) { 561 G_ELI_DEBUG(0, "Cannot erase metadata on %s " 562 "(error=%d).", pp->name, err); 563 if (error == 0) 564 error = err; 565 } 566 } 567 free(sector, M_ELI); 568 if (error == 0) 569 G_ELI_DEBUG(0, "%s has been killed.", pp->name); 570 g_eli_destroy(sc, 1); 571 return (error); 572 } 573 574 static void 575 g_eli_ctl_kill(struct gctl_req *req, struct g_class *mp) 576 { 577 int *all, *nargs; 578 int error; 579 580 g_topology_assert(); 581 582 nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); 583 if (nargs == NULL) { 584 gctl_error(req, "No '%s' argument.", "nargs"); 585 return; 586 } 587 all = gctl_get_paraml(req, "all", sizeof(*all)); 588 if (all == NULL) { 589 gctl_error(req, "No '%s' argument.", "all"); 590 return; 591 } 592 if (!*all && *nargs == 0) { 593 gctl_error(req, "Too few arguments."); 594 return; 595 } 596 597 if (*all) { 598 struct g_geom *gp, *gp2; 599 600 LIST_FOREACH_SAFE(gp, &mp->geom, geom, gp2) { 601 error = g_eli_kill_one(gp->softc); 602 if (error != 0) 603 gctl_error(req, "Not fully done."); 604 } 605 } else { 606 struct g_eli_softc *sc; 607 const char *prov; 608 char param[16]; 609 int i; 610 611 for (i = 0; i < *nargs; i++) { 612 snprintf(param, sizeof(param), "arg%u", i); 613 prov = gctl_get_asciiparam(req, param); 614 615 sc = g_eli_find_device(mp, prov); 616 if (sc == NULL) { 617 G_ELI_DEBUG(1, "No such provider: %s.", prov); 618 continue; 619 } 620 error = g_eli_kill_one(sc); 621 if (error != 0) 622 gctl_error(req, "Not fully done."); 623 } 624 } 625 } 626 627 void 628 g_eli_config(struct gctl_req *req, struct g_class *mp, const char *verb) 629 { 630 uint32_t *version; 631 632 g_topology_assert(); 633 634 version = gctl_get_paraml(req, "version", sizeof(*version)); 635 if (version == NULL) { 636 gctl_error(req, "No '%s' argument.", "version"); 637 return; 638 } 639 if (*version != G_ELI_VERSION) { 640 gctl_error(req, "Userland and kernel parts are out of sync."); 641 return; 642 } 643 644 if (strcmp(verb, "attach") == 0) 645 g_eli_ctl_attach(req, mp); 646 else if (strcmp(verb, "detach") == 0 || strcmp(verb, "stop") == 0) 647 g_eli_ctl_detach(req, mp); 648 else if (strcmp(verb, "onetime") == 0) 649 g_eli_ctl_onetime(req, mp); 650 else if (strcmp(verb, "setkey") == 0) 651 g_eli_ctl_setkey(req, mp); 652 else if (strcmp(verb, "delkey") == 0) 653 g_eli_ctl_delkey(req, mp); 654 else if (strcmp(verb, "kill") == 0) 655 g_eli_ctl_kill(req, mp); 656 else 657 gctl_error(req, "Unknown verb."); 658 } 659