g_eli_ctl.c revision 159307
1139825Simp/*- 290643Sbenno * Copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org> 390643Sbenno * All rights reserved. 490643Sbenno * 590643Sbenno * Redistribution and use in source and binary forms, with or without 690643Sbenno * modification, are permitted provided that the following conditions 790643Sbenno * are met: 890643Sbenno * 1. Redistributions of source code must retain the above copyright 990643Sbenno * notice, this list of conditions and the following disclaimer. 1090643Sbenno * 2. Redistributions in binary form must reproduce the above copyright 1190643Sbenno * notice, this list of conditions and the following disclaimer in the 1290643Sbenno * documentation and/or other materials provided with the distribution. 1390643Sbenno * 1490643Sbenno * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 1590643Sbenno * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1690643Sbenno * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1790643Sbenno * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 1890643Sbenno * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1990643Sbenno * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2090643Sbenno * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2190643Sbenno * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2290643Sbenno * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2390643Sbenno * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2490643Sbenno * SUCH DAMAGE. 2590643Sbenno */ 2690643Sbenno 2790643Sbenno#include <sys/cdefs.h> 2890643Sbenno__FBSDID("$FreeBSD: head/sys/geom/eli/g_eli_ctl.c 159307 2006-06-05 21:38:54Z pjd $"); 29139825Simp 3077957Sbenno#include <sys/param.h> 3177957Sbenno#include <sys/systm.h> 3277957Sbenno#include <sys/kernel.h> 3377957Sbenno#include <sys/module.h> 3477957Sbenno#include <sys/lock.h> 3577957Sbenno#include <sys/mutex.h> 3677957Sbenno#include <sys/bio.h> 3777957Sbenno#include <sys/sysctl.h> 3877957Sbenno#include <sys/malloc.h> 3977957Sbenno#include <sys/kthread.h> 4077957Sbenno#include <sys/proc.h> 4177957Sbenno#include <sys/sched.h> 4277957Sbenno#include <sys/uio.h> 4377957Sbenno 4477957Sbenno#include <vm/uma.h> 4577957Sbenno 4677957Sbenno#include <geom/geom.h> 4777957Sbenno#include <geom/eli/g_eli.h> 4877957Sbenno 4977957Sbenno 5077957SbennoMALLOC_DECLARE(M_ELI); 5177957Sbenno 5277957Sbenno 5377957Sbennostatic void 5477957Sbennog_eli_ctl_attach(struct gctl_req *req, struct g_class *mp) 5577957Sbenno{ 5677957Sbenno struct g_eli_metadata md; 5777957Sbenno struct g_provider *pp; 5877957Sbenno const char *name; 5978880Sbenno u_char *key, mkey[G_ELI_DATAIVKEYLEN]; 6077957Sbenno int *nargs, *detach; 61139825Simp int keysize, error; 6277957Sbenno u_int nkey; 6377957Sbenno 6477957Sbenno g_topology_assert(); 6577957Sbenno 6677957Sbenno nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); 6777957Sbenno if (nargs == NULL) { 6877957Sbenno gctl_error(req, "No '%s' argument.", "nargs"); 6977957Sbenno return; 7077957Sbenno } 7177957Sbenno if (*nargs != 1) { 7277957Sbenno gctl_error(req, "Invalid number of arguments."); 7377957Sbenno return; 7477957Sbenno } 7577957Sbenno 7677957Sbenno detach = gctl_get_paraml(req, "detach", sizeof(*detach)); 7777957Sbenno if (detach == NULL) { 7877957Sbenno gctl_error(req, "No '%s' argument.", "detach"); 7977957Sbenno return; 8077957Sbenno } 8177957Sbenno 8277957Sbenno name = gctl_get_asciiparam(req, "arg0"); 8377957Sbenno if (name == NULL) { 8477957Sbenno gctl_error(req, "No 'arg%u' argument.", 0); 8577957Sbenno return; 86113038Sobrien } 87113038Sobrien if (strncmp(name, "/dev/", strlen("/dev/")) == 0) 8877957Sbenno name += strlen("/dev/"); 8990643Sbenno pp = g_provider_by_name(name); 9090643Sbenno if (pp == NULL) { 9190643Sbenno gctl_error(req, "Provider %s is invalid.", name); 9290643Sbenno return; 9390643Sbenno } 9490643Sbenno error = g_eli_read_metadata(mp, pp, &md); 9590643Sbenno if (error != 0) { 9690643Sbenno gctl_error(req, "Cannot read metadata from %s (error=%d).", 9790643Sbenno name, error); 9890643Sbenno return; 9990643Sbenno } 10090643Sbenno if (md.md_keys == 0x00) { 10190643Sbenno bzero(&md, sizeof(md)); 10290643Sbenno gctl_error(req, "No valid keys on %s.", pp->name); 10390643Sbenno return; 10490643Sbenno } 105118239Speter 106118239Speter key = gctl_get_param(req, "key", &keysize); 10777957Sbenno if (key == NULL || keysize != G_ELI_USERKEYLEN) { 10880431Speter bzero(&md, sizeof(md)); 109222813Sattilio gctl_error(req, "No '%s' argument.", "key"); 110222813Sattilio return; 11190643Sbenno } 11290643Sbenno 11390643Sbenno error = g_eli_mkey_decrypt(&md, key, mkey, &nkey); 11490643Sbenno bzero(key, keysize); 11577957Sbenno if (error == -1) { 116238159Salc bzero(&md, sizeof(md)); 117222813Sattilio gctl_error(req, "Wrong key for %s.", pp->name); 11890643Sbenno return; 11990643Sbenno } else if (error > 0) { 12077957Sbenno bzero(&md, sizeof(md)); 12177957Sbenno gctl_error(req, "Cannot decrypt Master Key for %s (error=%d).", 12290643Sbenno pp->name, error); 12390643Sbenno return; 124152180Sgrehan } 12577957Sbenno G_ELI_DEBUG(1, "Using Master Key %u for %s.", nkey, pp->name); 12677957Sbenno 12777957Sbenno if (*detach) 12877957Sbenno md.md_flags |= G_ELI_FLAG_WO_DETACH; 12977957Sbenno g_eli_create(req, mp, pp, &md, mkey, nkey); 13077957Sbenno bzero(mkey, sizeof(mkey)); 13177957Sbenno bzero(&md, sizeof(md)); 13292847Sjeff} 13377957Sbenno 134125687Sgrehanstatic struct g_eli_softc * 135192067Snwhitehorng_eli_find_device(struct g_class *mp, const char *prov) 13683730Smp{ 13790643Sbenno struct g_eli_softc *sc; 13890643Sbenno struct g_geom *gp; 13990643Sbenno struct g_provider *pp; 14077957Sbenno struct g_consumer *cp; 141178628Smarcel 14290643Sbenno if (strncmp(prov, "/dev/", strlen("/dev/")) == 0) 143152180Sgrehan prov += strlen("/dev/"); 144265974Sian LIST_FOREACH(gp, &mp->geom, geom) { 14577957Sbenno sc = gp->softc; 146152180Sgrehan if (sc == NULL) 14777957Sbenno continue; 148152180Sgrehan pp = LIST_FIRST(&gp->provider); 149152180Sgrehan if (pp != NULL && strcmp(pp->name, prov) == 0) 15090643Sbenno return (sc); 15177957Sbenno cp = LIST_FIRST(&gp->consumer); 15290643Sbenno if (cp != NULL && cp->provider != NULL && 15390643Sbenno strcmp(cp->provider->name, prov) == 0) { 15490643Sbenno return (sc); 15590643Sbenno } 15690643Sbenno } 15790643Sbenno return (NULL); 15890643Sbenno} 15990643Sbenno 16090643Sbennostatic void 16190643Sbennog_eli_ctl_detach(struct gctl_req *req, struct g_class *mp) 16277957Sbenno{ 163249864Sjhibbits struct g_eli_softc *sc; 164249864Sjhibbits int *force, *last, *nargs, error; 165249864Sjhibbits const char *prov; 166249864Sjhibbits char param[16]; 167249864Sjhibbits int i; 16890643Sbenno 16990643Sbenno g_topology_assert(); 17090643Sbenno 17197346Sbenno nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); 17297346Sbenno if (nargs == NULL) { 173209975Snwhitehorn gctl_error(req, "No '%s' argument.", "nargs"); 174209975Snwhitehorn return; 175100319Sbenno } 17677957Sbenno if (*nargs <= 0) { 17790643Sbenno gctl_error(req, "Missing device(s)."); 178134535Salc return; 179134535Salc } 180152180Sgrehan force = gctl_get_paraml(req, "force", sizeof(*force)); 181212278Snwhitehorn if (force == NULL) { 182134535Salc gctl_error(req, "No '%s' argument.", "force"); 183183094Smarcel return; 184183094Smarcel } 185183094Smarcel last = gctl_get_paraml(req, "last", sizeof(*last)); 186134535Salc if (last == NULL) { 18790643Sbenno gctl_error(req, "No '%s' argument.", "last"); 18890643Sbenno return; 189152180Sgrehan } 190152180Sgrehan 191152180Sgrehan for (i = 0; i < *nargs; i++) { 19277957Sbenno snprintf(param, sizeof(param), "arg%d", i); 19390643Sbenno prov = gctl_get_asciiparam(req, param); 19490643Sbenno if (prov == NULL) { 19590643Sbenno gctl_error(req, "No 'arg%d' argument.", i); 196152180Sgrehan return; 197152180Sgrehan } 198152180Sgrehan sc = g_eli_find_device(mp, prov); 19977957Sbenno if (sc == NULL) { 200242534Sattilio gctl_error(req, "No such device: %s.", prov); 201238159Salc return; 202152180Sgrehan } 203152180Sgrehan if (*last) { 20477957Sbenno sc->sc_flags |= G_ELI_FLAG_RW_DETACH; 20599037Sbenno sc->sc_geom->access = g_eli_access; 206152180Sgrehan } else { 207152180Sgrehan error = g_eli_destroy(sc, *force); 20877957Sbenno if (error != 0) { 20990643Sbenno gctl_error(req, 210152180Sgrehan "Cannot destroy device %s (error=%d).", 21177957Sbenno sc->sc_name, error); 212152180Sgrehan return; 21377957Sbenno } 21490643Sbenno } 21590643Sbenno } 21690643Sbenno} 217152180Sgrehan 218152180Sgrehanstatic void 219152180Sgrehang_eli_ctl_onetime(struct gctl_req *req, struct g_class *mp) 220152180Sgrehan{ 221152180Sgrehan struct g_eli_metadata md; 222152180Sgrehan struct g_provider *pp; 223152180Sgrehan const char *name; 224152180Sgrehan intmax_t *keylen, *sectorsize; 22590643Sbenno u_char mkey[G_ELI_DATAIVKEYLEN]; 226152180Sgrehan int *nargs, *detach; 227152180Sgrehan 228152180Sgrehan g_topology_assert(); 229152180Sgrehan bzero(&md, sizeof(md)); 230152180Sgrehan 23190643Sbenno nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); 232152180Sgrehan if (nargs == NULL) { 233152180Sgrehan gctl_error(req, "No '%s' argument.", "nargs"); 234152180Sgrehan return; 235152180Sgrehan } 236152180Sgrehan if (*nargs != 1) { 237152180Sgrehan gctl_error(req, "Invalid number of arguments."); 23877957Sbenno return; 23990643Sbenno } 240152180Sgrehan 24190643Sbenno detach = gctl_get_paraml(req, "detach", sizeof(*detach)); 242152180Sgrehan if (detach == NULL) { 24377957Sbenno gctl_error(req, "No '%s' argument.", "detach"); 24490643Sbenno return; 24590643Sbenno } 24690643Sbenno 247152180Sgrehan strlcpy(md.md_magic, G_ELI_MAGIC, sizeof(md.md_magic)); 24877957Sbenno md.md_version = G_ELI_VERSION; 24977957Sbenno md.md_flags |= G_ELI_FLAG_ONETIME; 25090643Sbenno if (*detach) 25177957Sbenno md.md_flags |= G_ELI_FLAG_WO_DETACH; 252152180Sgrehan 25390643Sbenno name = gctl_get_asciiparam(req, "aalgo"); 254152180Sgrehan if (name == NULL) { 255152180Sgrehan gctl_error(req, "No '%s' argument.", "aalgo"); 256152180Sgrehan return; 25790643Sbenno } 25890643Sbenno if (strcmp(name, "none") != 0) { 25990643Sbenno md.md_aalgo = g_eli_str2aalgo(name); 26090643Sbenno if (md.md_aalgo < CRYPTO_ALGORITHM_MIN || 261270439Skib md.md_aalgo > CRYPTO_ALGORITHM_MAX) { 262270439Skib gctl_error(req, "Invalid authentication algorithm."); 263152180Sgrehan return; 264152180Sgrehan } 265208990Salc md.md_flags |= G_ELI_FLAG_AUTH; 266152180Sgrehan } 267152180Sgrehan 26890643Sbenno name = gctl_get_asciiparam(req, "ealgo"); 269152180Sgrehan if (name == NULL) { 270152180Sgrehan gctl_error(req, "No '%s' argument.", "ealgo"); 271152180Sgrehan return; 272152180Sgrehan } 273152180Sgrehan md.md_ealgo = g_eli_str2ealgo(name); 274248280Skib if (md.md_ealgo < CRYPTO_ALGORITHM_MIN || 275248280Skib md.md_ealgo > CRYPTO_ALGORITHM_MAX) { 276270439Skib gctl_error(req, "Invalid encryption algorithm."); 277270439Skib return; 278159303Salc } 279159303Salc 280159627Sups keylen = gctl_get_paraml(req, "keylen", sizeof(*keylen)); 281152180Sgrehan if (keylen == NULL) { 282152180Sgrehan gctl_error(req, "No '%s' argument.", "keylen"); 283152180Sgrehan return; 284152180Sgrehan } 285214617Salc md.md_keylen = g_eli_keylen(md.md_ealgo, *keylen); 286207155Salc if (md.md_keylen == 0) { 287238357Salc gctl_error(req, "Invalid '%s' argument.", "keylen"); 288235936Sraj return; 289152180Sgrehan } 290173708Salc 291152180Sgrehan /* Not important here. */ 292152180Sgrehan md.md_provsize = 0; 293152180Sgrehan /* Not important here. */ 294152180Sgrehan bzero(md.md_salt, sizeof(md.md_salt)); 295152180Sgrehan 296152180Sgrehan md.md_keys = 0x01; 297152180Sgrehan arc4rand(mkey, sizeof(mkey), 0); 298152180Sgrehan 299160889Salc /* Not important here. */ 300270920Skib bzero(md.md_hash, sizeof(md.md_hash)); 301152180Sgrehan 302152180Sgrehan name = gctl_get_asciiparam(req, "arg0"); 303152180Sgrehan if (name == NULL) { 304152180Sgrehan gctl_error(req, "No 'arg%u' argument.", 0); 305152180Sgrehan return; 306190681Snwhitehorn } 307152180Sgrehan if (strncmp(name, "/dev/", strlen("/dev/")) == 0) 308235936Sraj name += strlen("/dev/"); 309213307Snwhitehorn pp = g_provider_by_name(name); 310152180Sgrehan if (pp == NULL) { 311235936Sraj gctl_error(req, "Provider %s is invalid.", name); 312213307Snwhitehorn return; 313235936Sraj } 314213307Snwhitehorn 315235936Sraj sectorsize = gctl_get_paraml(req, "sectorsize", sizeof(*sectorsize)); 316198341Smarcel if (sectorsize == NULL) { 317249864Sjhibbits gctl_error(req, "No '%s' argument.", "sectorsize"); 318249864Sjhibbits return; 319249864Sjhibbits } 320152180Sgrehan if (*sectorsize == 0) 321152180Sgrehan md.md_sectorsize = pp->sectorsize; 322152180Sgrehan else { 323152180Sgrehan if (*sectorsize < 0 || (*sectorsize % pp->sectorsize) != 0) { 324248280Skib gctl_error(req, "Invalid sector size."); 325152180Sgrehan return; 326159303Salc } 327152180Sgrehan md.md_sectorsize = *sectorsize; 328152180Sgrehan } 329152180Sgrehan 330152180Sgrehan g_eli_create(req, mp, pp, &md, mkey, -1); 331152180Sgrehan bzero(mkey, sizeof(mkey)); 332214617Salc bzero(&md, sizeof(md)); 333207155Salc} 334152180Sgrehan 335152180Sgrehanstatic void 336152180Sgrehang_eli_ctl_setkey(struct gctl_req *req, struct g_class *mp) 337173708Salc{ 338152180Sgrehan struct g_eli_softc *sc; 339152180Sgrehan struct g_eli_metadata md; 340152180Sgrehan struct g_provider *pp; 341152180Sgrehan struct g_consumer *cp; 342152180Sgrehan const char *name; 343152180Sgrehan u_char *key, *mkeydst, *sector; 344152180Sgrehan intmax_t *valp; 345152180Sgrehan int keysize, nkey, error; 346160889Salc 347198341Smarcel g_topology_assert(); 348270920Skib 349152180Sgrehan name = gctl_get_asciiparam(req, "arg0"); 350152180Sgrehan if (name == NULL) { 351152180Sgrehan gctl_error(req, "No 'arg%u' argument.", 0); 352152180Sgrehan return; 353152180Sgrehan } 354213307Snwhitehorn sc = g_eli_find_device(mp, name); 355152180Sgrehan if (sc == NULL) { 356152180Sgrehan gctl_error(req, "Provider %s is invalid.", name); 357152180Sgrehan return; 358190681Snwhitehorn } 359213307Snwhitehorn cp = LIST_FIRST(&sc->sc_geom->consumer); 360152180Sgrehan pp = cp->provider; 361152180Sgrehan 362152180Sgrehan error = g_eli_read_metadata(mp, pp, &md); 363152180Sgrehan if (error != 0) { 364213307Snwhitehorn gctl_error(req, "Cannot read metadata from %s (error=%d).", 365152180Sgrehan name, error); 366249864Sjhibbits return; 367249864Sjhibbits } 368152180Sgrehan 369152180Sgrehan valp = gctl_get_paraml(req, "keyno", sizeof(*valp)); 370152180Sgrehan if (valp == NULL) { 371152180Sgrehan gctl_error(req, "No '%s' argument.", "keyno"); 372212627Sgrehan return; 373152180Sgrehan } 374213307Snwhitehorn if (*valp != -1) 375213307Snwhitehorn nkey = *valp; 376213307Snwhitehorn else 377213307Snwhitehorn nkey = sc->sc_nkey; 378213307Snwhitehorn if (nkey < 0 || nkey >= G_ELI_MAXMKEYS) { 379212627Sgrehan gctl_error(req, "Invalid '%s' argument.", "keyno"); 380213307Snwhitehorn return; 381213307Snwhitehorn } 382213307Snwhitehorn 383213307Snwhitehorn valp = gctl_get_paraml(req, "iterations", sizeof(*valp)); 384213307Snwhitehorn if (valp == NULL) { 385213307Snwhitehorn gctl_error(req, "No '%s' argument.", "iterations"); 386213307Snwhitehorn return; 387213307Snwhitehorn } 388213307Snwhitehorn /* Check if iterations number should and can be changed. */ 389213307Snwhitehorn if (*valp != -1) { 390213307Snwhitehorn if (bitcount32(md.md_keys) != 1) { 391213307Snwhitehorn gctl_error(req, "To be able to use '-i' option, only " 392213307Snwhitehorn "one key can be defined."); 393213307Snwhitehorn return; 394213307Snwhitehorn } 395213307Snwhitehorn if (md.md_keys != (1 << nkey)) { 396213307Snwhitehorn gctl_error(req, "Only already defined key can be " 397213307Snwhitehorn "changed when '-i' option is used."); 398213307Snwhitehorn return; 399213307Snwhitehorn } 400213307Snwhitehorn md.md_iterations = *valp; 401213307Snwhitehorn } 402213307Snwhitehorn 403213307Snwhitehorn key = gctl_get_param(req, "key", &keysize); 404213307Snwhitehorn if (key == NULL || keysize != G_ELI_USERKEYLEN) { 405213307Snwhitehorn bzero(&md, sizeof(md)); 406213307Snwhitehorn gctl_error(req, "No '%s' argument.", "key"); 407213307Snwhitehorn return; 408213307Snwhitehorn } 409183094Smarcel 410183094Smarcel mkeydst = md.md_mkeys + nkey * G_ELI_MKEYLEN; 411183094Smarcel md.md_keys |= (1 << nkey); 412152180Sgrehan 413183094Smarcel bcopy(sc->sc_mkey, mkeydst, sizeof(sc->sc_mkey)); 414213407Snwhitehorn 415183094Smarcel /* Encrypt Master Key with the new key. */ 416213407Snwhitehorn error = g_eli_mkey_encrypt(md.md_ealgo, key, md.md_keylen, mkeydst); 417183094Smarcel bzero(key, sizeof(key)); 418183094Smarcel if (error != 0) { 419183094Smarcel bzero(&md, sizeof(md)); 420183094Smarcel gctl_error(req, "Cannot encrypt Master Key (error=%d).", error); 421183094Smarcel return; 422183094Smarcel } 423183094Smarcel 424183094Smarcel sector = malloc(pp->sectorsize, M_ELI, M_WAITOK | M_ZERO); 425183094Smarcel /* Store metadata with fresh key. */ 426183094Smarcel eli_metadata_encode(&md, sector); 427183094Smarcel bzero(&md, sizeof(md)); 428183094Smarcel error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector, 429183094Smarcel pp->sectorsize); 430183094Smarcel bzero(sector, sizeof(sector)); 431183094Smarcel free(sector, M_ELI); 432183094Smarcel if (error != 0) { 43390643Sbenno gctl_error(req, "Cannot store metadata on %s (error=%d).", 43490643Sbenno pp->name, error); 43577957Sbenno return; 43690643Sbenno } 43790643Sbenno G_ELI_DEBUG(1, "Key %u changed on %s.", nkey, pp->name); 43877957Sbenno} 43990643Sbenno 44090643Sbennostatic void 44190643Sbennog_eli_ctl_delkey(struct gctl_req *req, struct g_class *mp) 44290643Sbenno{ 44390643Sbenno struct g_eli_softc *sc; 44490643Sbenno struct g_eli_metadata md; 44590643Sbenno struct g_provider *pp; 446152180Sgrehan struct g_consumer *cp; 44777957Sbenno const char *name; 44877957Sbenno u_char *mkeydst, *sector; 44990643Sbenno intmax_t *valp; 45090643Sbenno size_t keysize; 45190643Sbenno int error, nkey, *all, *force; 45290643Sbenno u_int i; 45390643Sbenno 45490643Sbenno g_topology_assert(); 45590643Sbenno 45677957Sbenno nkey = 0; /* fixes causeless gcc warning */ 457152180Sgrehan 45877957Sbenno name = gctl_get_asciiparam(req, "arg0"); 45990643Sbenno if (name == NULL) { 460238159Salc gctl_error(req, "No 'arg%u' argument.", 0); 46190643Sbenno return; 46277957Sbenno } 46377957Sbenno sc = g_eli_find_device(mp, name); 46477957Sbenno if (sc == NULL) { 465152180Sgrehan gctl_error(req, "Provider %s is invalid.", name); 46677957Sbenno return; 46777957Sbenno } 46890643Sbenno cp = LIST_FIRST(&sc->sc_geom->consumer); 46977957Sbenno pp = cp->provider; 47077957Sbenno 47190643Sbenno error = g_eli_read_metadata(mp, pp, &md); 472152180Sgrehan if (error != 0) { 47390643Sbenno gctl_error(req, "Cannot read metadata from %s (error=%d).", 47490643Sbenno name, error); 475238159Salc return; 47690643Sbenno } 47790643Sbenno 47890643Sbenno all = gctl_get_paraml(req, "all", sizeof(*all)); 47977957Sbenno if (all == NULL) { 480152180Sgrehan gctl_error(req, "No '%s' argument.", "all"); 48177957Sbenno return; 48290643Sbenno } 48390643Sbenno 48490643Sbenno if (*all) { 48590643Sbenno mkeydst = md.md_mkeys; 48677957Sbenno keysize = sizeof(md.md_mkeys); 48777957Sbenno } else { 48877957Sbenno force = gctl_get_paraml(req, "force", sizeof(*force)); 489152180Sgrehan if (force == NULL) { 49077957Sbenno gctl_error(req, "No '%s' argument.", "force"); 49190643Sbenno return; 49290643Sbenno } 49390643Sbenno 49490643Sbenno valp = gctl_get_paraml(req, "keyno", sizeof(*valp)); 49577957Sbenno if (valp == NULL) { 49690643Sbenno gctl_error(req, "No '%s' argument.", "keyno"); 497152180Sgrehan return; 49890643Sbenno } 499159928Salc if (*valp != -1) 500159928Salc nkey = *valp; 501159928Salc else 50290643Sbenno nkey = sc->sc_nkey; 50390643Sbenno if (nkey < 0 || nkey >= G_ELI_MAXMKEYS) { 50490643Sbenno gctl_error(req, "Invalid '%s' argument.", "keyno"); 50590643Sbenno return; 50690643Sbenno } 50790643Sbenno if (!(md.md_keys & (1 << nkey)) && !*force) { 50890643Sbenno gctl_error(req, "Master Key %u is not set.", nkey); 50990643Sbenno return; 51090643Sbenno } 51177957Sbenno md.md_keys &= ~(1 << nkey); 51277957Sbenno if (md.md_keys == 0 && !*force) { 51390643Sbenno gctl_error(req, "This is the last Master Key. Use '-f' " 514152180Sgrehan "flag if you really want to remove it."); 51577957Sbenno return; 51677957Sbenno } 517159928Salc mkeydst = md.md_mkeys + nkey * G_ELI_MKEYLEN; 51890643Sbenno keysize = G_ELI_MKEYLEN; 51977957Sbenno } 52077957Sbenno 52190643Sbenno sector = malloc(pp->sectorsize, M_ELI, M_WAITOK | M_ZERO); 522152180Sgrehan for (i = 0; i <= g_eli_overwrites; i++) { 52377957Sbenno if (i == g_eli_overwrites) 52477957Sbenno bzero(mkeydst, keysize); 525159928Salc else 526159928Salc arc4rand(mkeydst, keysize, 0); 52790643Sbenno /* Store metadata with destroyed key. */ 52890643Sbenno eli_metadata_encode(&md, sector); 52990643Sbenno error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector, 53090643Sbenno pp->sectorsize); 531183094Smarcel if (error != 0) { 53277957Sbenno G_ELI_DEBUG(0, "Cannot store metadata on %s " 53377957Sbenno "(error=%d).", pp->name, error); 53490643Sbenno } 535152180Sgrehan } 53677957Sbenno bzero(&md, sizeof(md)); 53777957Sbenno bzero(sector, sizeof(sector)); 538159928Salc free(sector, M_ELI); 53990643Sbenno if (*all) 54090643Sbenno G_ELI_DEBUG(1, "All keys removed from %s.", pp->name); 54177957Sbenno else 54290643Sbenno G_ELI_DEBUG(1, "Key %d removed from %s.", nkey, pp->name); 543253976Sjhibbits} 54490643Sbenno 54577957Sbennostatic int 54690643Sbennog_eli_kill_one(struct g_eli_softc *sc) 547183094Smarcel{ 54890643Sbenno struct g_provider *pp; 549183094Smarcel struct g_consumer *cp; 550152180Sgrehan u_char *sector; 55190643Sbenno int err, error = 0; 55277957Sbenno u_int i; 55390643Sbenno 554152180Sgrehan g_topology_assert(); 55590643Sbenno 55690643Sbenno if (sc == NULL) 557159928Salc return (ENOENT); 55890643Sbenno 55990643Sbenno pp = LIST_FIRST(&sc->sc_geom->provider); 56077957Sbenno g_error_provider(pp, ENXIO); 56190643Sbenno 56277957Sbenno cp = LIST_FIRST(&sc->sc_geom->consumer); 563183094Smarcel pp = cp->provider; 56477957Sbenno 56590643Sbenno sector = malloc(pp->sectorsize, M_ELI, M_WAITOK); 56690643Sbenno for (i = 0; i <= g_eli_overwrites; i++) { 56790643Sbenno if (i == g_eli_overwrites) 56890643Sbenno bzero(sector, pp->sectorsize); 56977957Sbenno else 570183094Smarcel arc4rand(sector, pp->sectorsize, 0); 57177957Sbenno err = g_write_data(cp, pp->mediasize - pp->sectorsize, sector, 57290643Sbenno pp->sectorsize); 57390643Sbenno if (err != 0) { 57490643Sbenno G_ELI_DEBUG(0, "Cannot erase metadata on %s " 575152180Sgrehan "(error=%d).", pp->name, err); 576152180Sgrehan if (error == 0) 57777957Sbenno error = err; 57877957Sbenno } 57990643Sbenno } 580152180Sgrehan free(sector, M_ELI); 58190643Sbenno if (error == 0) 58290643Sbenno G_ELI_DEBUG(0, "%s has been killed.", pp->name); 58390643Sbenno g_eli_destroy(sc, 1); 58490643Sbenno return (error); 58590643Sbenno} 586152180Sgrehan 587152180Sgrehanstatic void 58890643Sbennog_eli_ctl_kill(struct gctl_req *req, struct g_class *mp) 58990643Sbenno{ 59077957Sbenno int *all, *nargs; 59190643Sbenno int error; 59277957Sbenno 59390643Sbenno g_topology_assert(); 59490643Sbenno 59590643Sbenno nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); 59690643Sbenno if (nargs == NULL) { 59790643Sbenno gctl_error(req, "No '%s' argument.", "nargs"); 59890643Sbenno return; 59990643Sbenno } 60090643Sbenno all = gctl_get_paraml(req, "all", sizeof(*all)); 60190643Sbenno if (all == NULL) { 60290643Sbenno gctl_error(req, "No '%s' argument.", "all"); 60390643Sbenno return; 60490643Sbenno } 60590643Sbenno if (!*all && *nargs == 0) { 60690643Sbenno gctl_error(req, "Too few arguments."); 60790643Sbenno return; 60890643Sbenno } 60977957Sbenno 61077957Sbenno if (*all) { 61177957Sbenno struct g_geom *gp, *gp2; 612190681Snwhitehorn 613178628Smarcel LIST_FOREACH_SAFE(gp, &mp->geom, geom, gp2) { 614178628Smarcel error = g_eli_kill_one(gp->softc); 615178628Smarcel if (error != 0) 616178628Smarcel gctl_error(req, "Not fully done."); 617178628Smarcel } 618183094Smarcel } else { 619178628Smarcel struct g_eli_softc *sc; 620178628Smarcel const char *prov; 621178628Smarcel char param[16]; 622178628Smarcel int i; 623178628Smarcel 624178628Smarcel for (i = 0; i < *nargs; i++) { 625178628Smarcel snprintf(param, sizeof(param), "arg%d", i); 626178628Smarcel prov = gctl_get_asciiparam(req, param); 627243370Sadrian if (prov == NULL) { 628243370Sadrian G_ELI_DEBUG(0, "No 'arg%d' argument.", i); 629243370Sadrian continue; 630243370Sadrian } 631243370Sadrian 632243370Sadrian sc = g_eli_find_device(mp, prov); 633243370Sadrian if (sc == NULL) { 634243370Sadrian G_ELI_DEBUG(0, "No such provider: %s.", prov); 635243370Sadrian continue; 636243370Sadrian } 637243370Sadrian error = g_eli_kill_one(sc); 638178629Smarcel if (error != 0) 639178628Smarcel gctl_error(req, "Not fully done."); 640178629Smarcel } 641178629Smarcel } 642178629Smarcel} 643178629Smarcel 644178629Smarcelvoid 645178628Smarcelg_eli_config(struct gctl_req *req, struct g_class *mp, const char *verb) 646178628Smarcel{ 647178628Smarcel uint32_t *version; 648215163Snwhitehorn 649183094Smarcel g_topology_assert(); 650178628Smarcel 651178628Smarcel version = gctl_get_paraml(req, "version", sizeof(*version)); 652178628Smarcel if (version == NULL) { 653178628Smarcel gctl_error(req, "No '%s' argument.", "version"); 654178628Smarcel return; 655179254Smarcel } 656178628Smarcel if (*version != G_ELI_VERSION) { 657178628Smarcel gctl_error(req, "Userland and kernel parts are out of sync."); 658178628Smarcel return; 659152180Sgrehan } 66077957Sbenno 66197346Sbenno if (strcmp(verb, "attach") == 0) 66290643Sbenno g_eli_ctl_attach(req, mp); 66390643Sbenno else if (strcmp(verb, "detach") == 0 || strcmp(verb, "stop") == 0) 66490643Sbenno g_eli_ctl_detach(req, mp); 665143200Sgrehan else if (strcmp(verb, "onetime") == 0) 66690643Sbenno g_eli_ctl_onetime(req, mp); 667194784Sjeff else if (strcmp(verb, "setkey") == 0) 668209369Snwhitehorn g_eli_ctl_setkey(req, mp); 66977957Sbenno else if (strcmp(verb, "delkey") == 0) 67099037Sbenno g_eli_ctl_delkey(req, mp); 671103604Sgrehan else if (strcmp(verb, "kill") == 0) 67299037Sbenno g_eli_ctl_kill(req, mp); 67399037Sbenno else 67499037Sbenno gctl_error(req, "Unknown verb."); 67599037Sbenno} 676243370Sadrian