1c58794deSPawel Jakub Dawidek /*- 2c58794deSPawel Jakub Dawidek * Copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org> 3c58794deSPawel Jakub Dawidek * All rights reserved. 4c58794deSPawel Jakub Dawidek * 5c58794deSPawel Jakub Dawidek * Redistribution and use in source and binary forms, with or without 6c58794deSPawel Jakub Dawidek * modification, are permitted provided that the following conditions 7c58794deSPawel Jakub Dawidek * are met: 8c58794deSPawel Jakub Dawidek * 1. Redistributions of source code must retain the above copyright 9c58794deSPawel Jakub Dawidek * notice, this list of conditions and the following disclaimer. 10c58794deSPawel Jakub Dawidek * 2. Redistributions in binary form must reproduce the above copyright 11c58794deSPawel Jakub Dawidek * notice, this list of conditions and the following disclaimer in the 12c58794deSPawel Jakub Dawidek * documentation and/or other materials provided with the distribution. 13c58794deSPawel Jakub Dawidek * 14c58794deSPawel Jakub Dawidek * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 15c58794deSPawel Jakub Dawidek * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16c58794deSPawel Jakub Dawidek * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17c58794deSPawel Jakub Dawidek * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 18c58794deSPawel Jakub Dawidek * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19c58794deSPawel Jakub Dawidek * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20c58794deSPawel Jakub Dawidek * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21c58794deSPawel Jakub Dawidek * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22c58794deSPawel Jakub Dawidek * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23c58794deSPawel Jakub Dawidek * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24c58794deSPawel Jakub Dawidek * SUCH DAMAGE. 25c58794deSPawel Jakub Dawidek */ 26c58794deSPawel Jakub Dawidek 27c58794deSPawel Jakub Dawidek #include <sys/cdefs.h> 28c58794deSPawel Jakub Dawidek __FBSDID("$FreeBSD$"); 29c58794deSPawel Jakub Dawidek 30c58794deSPawel Jakub Dawidek #include <sys/param.h> 31c58794deSPawel Jakub Dawidek #include <sys/systm.h> 32c58794deSPawel Jakub Dawidek #include <sys/kernel.h> 33c58794deSPawel Jakub Dawidek #include <sys/module.h> 34c58794deSPawel Jakub Dawidek #include <sys/lock.h> 35c58794deSPawel Jakub Dawidek #include <sys/mutex.h> 36c58794deSPawel Jakub Dawidek #include <sys/bio.h> 37c58794deSPawel Jakub Dawidek #include <sys/sysctl.h> 38c58794deSPawel Jakub Dawidek #include <sys/malloc.h> 39c58794deSPawel Jakub Dawidek #include <sys/kthread.h> 40c58794deSPawel Jakub Dawidek #include <sys/proc.h> 41c58794deSPawel Jakub Dawidek #include <sys/sched.h> 42c58794deSPawel Jakub Dawidek #include <sys/uio.h> 43c58794deSPawel Jakub Dawidek 44c58794deSPawel Jakub Dawidek #include <vm/uma.h> 45c58794deSPawel Jakub Dawidek 46c58794deSPawel Jakub Dawidek #include <geom/geom.h> 47c58794deSPawel Jakub Dawidek #include <geom/eli/g_eli.h> 48c58794deSPawel Jakub Dawidek 49c58794deSPawel Jakub Dawidek 50c58794deSPawel Jakub Dawidek MALLOC_DECLARE(M_ELI); 51c58794deSPawel Jakub Dawidek 52c58794deSPawel Jakub Dawidek 53c58794deSPawel Jakub Dawidek static void 54c58794deSPawel Jakub Dawidek g_eli_ctl_attach(struct gctl_req *req, struct g_class *mp) 55c58794deSPawel Jakub Dawidek { 56c58794deSPawel Jakub Dawidek struct g_eli_metadata md; 57c58794deSPawel Jakub Dawidek struct g_provider *pp; 58c58794deSPawel Jakub Dawidek const char *name; 59c58794deSPawel Jakub Dawidek u_char *key, mkey[G_ELI_DATAIVKEYLEN]; 6085059016SPawel Jakub Dawidek int *nargs, *detach, *readonly; 61c58794deSPawel Jakub Dawidek int keysize, error; 62c58794deSPawel Jakub Dawidek u_int nkey; 63c58794deSPawel Jakub Dawidek 64c58794deSPawel Jakub Dawidek g_topology_assert(); 65c58794deSPawel Jakub Dawidek 66c58794deSPawel Jakub Dawidek nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); 67c58794deSPawel Jakub Dawidek if (nargs == NULL) { 68c58794deSPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "nargs"); 69c58794deSPawel Jakub Dawidek return; 70c58794deSPawel Jakub Dawidek } 71c58794deSPawel Jakub Dawidek if (*nargs != 1) { 72c58794deSPawel Jakub Dawidek gctl_error(req, "Invalid number of arguments."); 73c58794deSPawel Jakub Dawidek return; 74c58794deSPawel Jakub Dawidek } 75c58794deSPawel Jakub Dawidek 76c58794deSPawel Jakub Dawidek detach = gctl_get_paraml(req, "detach", sizeof(*detach)); 77c58794deSPawel Jakub Dawidek if (detach == NULL) { 78c58794deSPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "detach"); 79c58794deSPawel Jakub Dawidek return; 80c58794deSPawel Jakub Dawidek } 81c58794deSPawel Jakub Dawidek 8285059016SPawel Jakub Dawidek readonly = gctl_get_paraml(req, "readonly", sizeof(*readonly)); 8385059016SPawel Jakub Dawidek if (readonly == NULL) { 8485059016SPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "readonly"); 8585059016SPawel Jakub Dawidek return; 8685059016SPawel Jakub Dawidek } 8785059016SPawel Jakub Dawidek 88c58794deSPawel Jakub Dawidek name = gctl_get_asciiparam(req, "arg0"); 89c58794deSPawel Jakub Dawidek if (name == NULL) { 90c58794deSPawel Jakub Dawidek gctl_error(req, "No 'arg%u' argument.", 0); 91c58794deSPawel Jakub Dawidek return; 92c58794deSPawel Jakub Dawidek } 93c58794deSPawel Jakub Dawidek if (strncmp(name, "/dev/", strlen("/dev/")) == 0) 94c58794deSPawel Jakub Dawidek name += strlen("/dev/"); 95c58794deSPawel Jakub Dawidek pp = g_provider_by_name(name); 96c58794deSPawel Jakub Dawidek if (pp == NULL) { 97c58794deSPawel Jakub Dawidek gctl_error(req, "Provider %s is invalid.", name); 98c58794deSPawel Jakub Dawidek return; 99c58794deSPawel Jakub Dawidek } 100c58794deSPawel Jakub Dawidek error = g_eli_read_metadata(mp, pp, &md); 101c58794deSPawel Jakub Dawidek if (error != 0) { 102c58794deSPawel Jakub Dawidek gctl_error(req, "Cannot read metadata from %s (error=%d).", 103c58794deSPawel Jakub Dawidek name, error); 104c58794deSPawel Jakub Dawidek return; 105c58794deSPawel Jakub Dawidek } 106c58794deSPawel Jakub Dawidek if (md.md_keys == 0x00) { 107c58794deSPawel Jakub Dawidek bzero(&md, sizeof(md)); 108c58794deSPawel Jakub Dawidek gctl_error(req, "No valid keys on %s.", pp->name); 109c58794deSPawel Jakub Dawidek return; 110c58794deSPawel Jakub Dawidek } 111c58794deSPawel Jakub Dawidek 112c58794deSPawel Jakub Dawidek key = gctl_get_param(req, "key", &keysize); 113c58794deSPawel Jakub Dawidek if (key == NULL || keysize != G_ELI_USERKEYLEN) { 114c58794deSPawel Jakub Dawidek bzero(&md, sizeof(md)); 115c58794deSPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "key"); 116c58794deSPawel Jakub Dawidek return; 117c58794deSPawel Jakub Dawidek } 118c58794deSPawel Jakub Dawidek 119c58794deSPawel Jakub Dawidek error = g_eli_mkey_decrypt(&md, key, mkey, &nkey); 120c58794deSPawel Jakub Dawidek bzero(key, keysize); 121c58794deSPawel Jakub Dawidek if (error == -1) { 122c58794deSPawel Jakub Dawidek bzero(&md, sizeof(md)); 123c58794deSPawel Jakub Dawidek gctl_error(req, "Wrong key for %s.", pp->name); 124c58794deSPawel Jakub Dawidek return; 125c58794deSPawel Jakub Dawidek } else if (error > 0) { 126c58794deSPawel Jakub Dawidek bzero(&md, sizeof(md)); 127c58794deSPawel Jakub Dawidek gctl_error(req, "Cannot decrypt Master Key for %s (error=%d).", 128c58794deSPawel Jakub Dawidek pp->name, error); 129c58794deSPawel Jakub Dawidek return; 130c58794deSPawel Jakub Dawidek } 131c58794deSPawel Jakub Dawidek G_ELI_DEBUG(1, "Using Master Key %u for %s.", nkey, pp->name); 132c58794deSPawel Jakub Dawidek 13385059016SPawel Jakub Dawidek if (*detach && *readonly) { 13485059016SPawel Jakub Dawidek bzero(&md, sizeof(md)); 135dec53cddSPawel Jakub Dawidek gctl_error(req, "Options -d and -r are mutually exclusive."); 13685059016SPawel Jakub Dawidek return; 13785059016SPawel Jakub Dawidek } 138c58794deSPawel Jakub Dawidek if (*detach) 139c58794deSPawel Jakub Dawidek md.md_flags |= G_ELI_FLAG_WO_DETACH; 14085059016SPawel Jakub Dawidek if (*readonly) 14185059016SPawel Jakub Dawidek md.md_flags |= G_ELI_FLAG_RO; 142c58794deSPawel Jakub Dawidek g_eli_create(req, mp, pp, &md, mkey, nkey); 143c58794deSPawel Jakub Dawidek bzero(mkey, sizeof(mkey)); 144c58794deSPawel Jakub Dawidek bzero(&md, sizeof(md)); 145c58794deSPawel Jakub Dawidek } 146c58794deSPawel Jakub Dawidek 147c58794deSPawel Jakub Dawidek static struct g_eli_softc * 148c58794deSPawel Jakub Dawidek g_eli_find_device(struct g_class *mp, const char *prov) 149c58794deSPawel Jakub Dawidek { 150c58794deSPawel Jakub Dawidek struct g_eli_softc *sc; 151c58794deSPawel Jakub Dawidek struct g_geom *gp; 152c58794deSPawel Jakub Dawidek struct g_provider *pp; 153c58794deSPawel Jakub Dawidek struct g_consumer *cp; 154c58794deSPawel Jakub Dawidek 155c58794deSPawel Jakub Dawidek if (strncmp(prov, "/dev/", strlen("/dev/")) == 0) 156c58794deSPawel Jakub Dawidek prov += strlen("/dev/"); 157c58794deSPawel Jakub Dawidek LIST_FOREACH(gp, &mp->geom, geom) { 158c58794deSPawel Jakub Dawidek sc = gp->softc; 159c58794deSPawel Jakub Dawidek if (sc == NULL) 160c58794deSPawel Jakub Dawidek continue; 161c58794deSPawel Jakub Dawidek pp = LIST_FIRST(&gp->provider); 162c58794deSPawel Jakub Dawidek if (pp != NULL && strcmp(pp->name, prov) == 0) 163c58794deSPawel Jakub Dawidek return (sc); 164c58794deSPawel Jakub Dawidek cp = LIST_FIRST(&gp->consumer); 165c58794deSPawel Jakub Dawidek if (cp != NULL && cp->provider != NULL && 166c58794deSPawel Jakub Dawidek strcmp(cp->provider->name, prov) == 0) { 167c58794deSPawel Jakub Dawidek return (sc); 168c58794deSPawel Jakub Dawidek } 169c58794deSPawel Jakub Dawidek } 170c58794deSPawel Jakub Dawidek return (NULL); 171c58794deSPawel Jakub Dawidek } 172c58794deSPawel Jakub Dawidek 173c58794deSPawel Jakub Dawidek static void 174c58794deSPawel Jakub Dawidek g_eli_ctl_detach(struct gctl_req *req, struct g_class *mp) 175c58794deSPawel Jakub Dawidek { 176c58794deSPawel Jakub Dawidek struct g_eli_softc *sc; 177c58794deSPawel Jakub Dawidek int *force, *last, *nargs, error; 178c58794deSPawel Jakub Dawidek const char *prov; 179c58794deSPawel Jakub Dawidek char param[16]; 1807d54b385SPawel Jakub Dawidek int i; 181c58794deSPawel Jakub Dawidek 182c58794deSPawel Jakub Dawidek g_topology_assert(); 183c58794deSPawel Jakub Dawidek 184c58794deSPawel Jakub Dawidek nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); 185c58794deSPawel Jakub Dawidek if (nargs == NULL) { 186c58794deSPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "nargs"); 187c58794deSPawel Jakub Dawidek return; 188c58794deSPawel Jakub Dawidek } 189c58794deSPawel Jakub Dawidek if (*nargs <= 0) { 190c58794deSPawel Jakub Dawidek gctl_error(req, "Missing device(s)."); 191c58794deSPawel Jakub Dawidek return; 192c58794deSPawel Jakub Dawidek } 193c58794deSPawel Jakub Dawidek force = gctl_get_paraml(req, "force", sizeof(*force)); 194c58794deSPawel Jakub Dawidek if (force == NULL) { 195c58794deSPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "force"); 196c58794deSPawel Jakub Dawidek return; 197c58794deSPawel Jakub Dawidek } 198c58794deSPawel Jakub Dawidek last = gctl_get_paraml(req, "last", sizeof(*last)); 199c58794deSPawel Jakub Dawidek if (last == NULL) { 200c58794deSPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "last"); 201c58794deSPawel Jakub Dawidek return; 202c58794deSPawel Jakub Dawidek } 203c58794deSPawel Jakub Dawidek 2047d54b385SPawel Jakub Dawidek for (i = 0; i < *nargs; i++) { 2057d54b385SPawel Jakub Dawidek snprintf(param, sizeof(param), "arg%d", i); 206c58794deSPawel Jakub Dawidek prov = gctl_get_asciiparam(req, param); 207c58794deSPawel Jakub Dawidek if (prov == NULL) { 2087d54b385SPawel Jakub Dawidek gctl_error(req, "No 'arg%d' argument.", i); 209c58794deSPawel Jakub Dawidek return; 210c58794deSPawel Jakub Dawidek } 211c58794deSPawel Jakub Dawidek sc = g_eli_find_device(mp, prov); 212c58794deSPawel Jakub Dawidek if (sc == NULL) { 213c58794deSPawel Jakub Dawidek gctl_error(req, "No such device: %s.", prov); 214c58794deSPawel Jakub Dawidek return; 215c58794deSPawel Jakub Dawidek } 216c58794deSPawel Jakub Dawidek if (*last) { 217c58794deSPawel Jakub Dawidek sc->sc_flags |= G_ELI_FLAG_RW_DETACH; 218c58794deSPawel Jakub Dawidek sc->sc_geom->access = g_eli_access; 219c58794deSPawel Jakub Dawidek } else { 220c58794deSPawel Jakub Dawidek error = g_eli_destroy(sc, *force); 221c58794deSPawel Jakub Dawidek if (error != 0) { 222c58794deSPawel Jakub Dawidek gctl_error(req, 223c58794deSPawel Jakub Dawidek "Cannot destroy device %s (error=%d).", 224c58794deSPawel Jakub Dawidek sc->sc_name, error); 225c58794deSPawel Jakub Dawidek return; 226c58794deSPawel Jakub Dawidek } 227c58794deSPawel Jakub Dawidek } 228c58794deSPawel Jakub Dawidek } 229c58794deSPawel Jakub Dawidek } 230c58794deSPawel Jakub Dawidek 231c58794deSPawel Jakub Dawidek static void 232c58794deSPawel Jakub Dawidek g_eli_ctl_onetime(struct gctl_req *req, struct g_class *mp) 233c58794deSPawel Jakub Dawidek { 234c58794deSPawel Jakub Dawidek struct g_eli_metadata md; 235c58794deSPawel Jakub Dawidek struct g_provider *pp; 236c58794deSPawel Jakub Dawidek const char *name; 237c58794deSPawel Jakub Dawidek intmax_t *keylen, *sectorsize; 238c58794deSPawel Jakub Dawidek u_char mkey[G_ELI_DATAIVKEYLEN]; 239c58794deSPawel Jakub Dawidek int *nargs, *detach; 240c58794deSPawel Jakub Dawidek 241c58794deSPawel Jakub Dawidek g_topology_assert(); 242c58794deSPawel Jakub Dawidek bzero(&md, sizeof(md)); 243c58794deSPawel Jakub Dawidek 244c58794deSPawel Jakub Dawidek nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); 245c58794deSPawel Jakub Dawidek if (nargs == NULL) { 246c58794deSPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "nargs"); 247c58794deSPawel Jakub Dawidek return; 248c58794deSPawel Jakub Dawidek } 249c58794deSPawel Jakub Dawidek if (*nargs != 1) { 250c58794deSPawel Jakub Dawidek gctl_error(req, "Invalid number of arguments."); 251c58794deSPawel Jakub Dawidek return; 252c58794deSPawel Jakub Dawidek } 253c58794deSPawel Jakub Dawidek 254c58794deSPawel Jakub Dawidek detach = gctl_get_paraml(req, "detach", sizeof(*detach)); 255c58794deSPawel Jakub Dawidek if (detach == NULL) { 256c58794deSPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "detach"); 257c58794deSPawel Jakub Dawidek return; 258c58794deSPawel Jakub Dawidek } 259c58794deSPawel Jakub Dawidek 260c58794deSPawel Jakub Dawidek strlcpy(md.md_magic, G_ELI_MAGIC, sizeof(md.md_magic)); 261c58794deSPawel Jakub Dawidek md.md_version = G_ELI_VERSION; 262c58794deSPawel Jakub Dawidek md.md_flags |= G_ELI_FLAG_ONETIME; 263c58794deSPawel Jakub Dawidek if (*detach) 264c58794deSPawel Jakub Dawidek md.md_flags |= G_ELI_FLAG_WO_DETACH; 265c58794deSPawel Jakub Dawidek 266c84efdcaSPawel Jakub Dawidek md.md_ealgo = CRYPTO_ALGORITHM_MIN - 1; 267eaa3b919SPawel Jakub Dawidek name = gctl_get_asciiparam(req, "aalgo"); 268c58794deSPawel Jakub Dawidek if (name == NULL) { 269eaa3b919SPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "aalgo"); 270c58794deSPawel Jakub Dawidek return; 271c58794deSPawel Jakub Dawidek } 272*a478ea74SPawel Jakub Dawidek if (*name != '\0') { 273eaa3b919SPawel Jakub Dawidek md.md_aalgo = g_eli_str2aalgo(name); 274c84efdcaSPawel Jakub Dawidek if (md.md_aalgo >= CRYPTO_ALGORITHM_MIN && 275c84efdcaSPawel Jakub Dawidek md.md_aalgo <= CRYPTO_ALGORITHM_MAX) { 276eaa3b919SPawel Jakub Dawidek md.md_flags |= G_ELI_FLAG_AUTH; 277c84efdcaSPawel Jakub Dawidek } else { 278c84efdcaSPawel Jakub Dawidek /* 279c84efdcaSPawel Jakub Dawidek * For backward compatibility, check if the -a option 280c84efdcaSPawel Jakub Dawidek * was used to provide encryption algorithm. 281c84efdcaSPawel Jakub Dawidek */ 282c84efdcaSPawel Jakub Dawidek md.md_ealgo = g_eli_str2ealgo(name); 283c84efdcaSPawel Jakub Dawidek if (md.md_ealgo < CRYPTO_ALGORITHM_MIN || 284c84efdcaSPawel Jakub Dawidek md.md_ealgo > CRYPTO_ALGORITHM_MAX) { 285c84efdcaSPawel Jakub Dawidek gctl_error(req, 286c84efdcaSPawel Jakub Dawidek "Invalid authentication algorithm."); 287c84efdcaSPawel Jakub Dawidek return; 288c84efdcaSPawel Jakub Dawidek } else { 289c84efdcaSPawel Jakub Dawidek gctl_error(req, "warning: The -e option, not " 290c84efdcaSPawel Jakub Dawidek "the -a option is now used to specify " 291c84efdcaSPawel Jakub Dawidek "encryption algorithm to use."); 292c84efdcaSPawel Jakub Dawidek } 293c84efdcaSPawel Jakub Dawidek } 294eaa3b919SPawel Jakub Dawidek } 295eaa3b919SPawel Jakub Dawidek 296c84efdcaSPawel Jakub Dawidek if (md.md_ealgo < CRYPTO_ALGORITHM_MIN || 297c84efdcaSPawel Jakub Dawidek md.md_ealgo > CRYPTO_ALGORITHM_MAX) { 298eaa3b919SPawel Jakub Dawidek name = gctl_get_asciiparam(req, "ealgo"); 299eaa3b919SPawel Jakub Dawidek if (name == NULL) { 300eaa3b919SPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "ealgo"); 301eaa3b919SPawel Jakub Dawidek return; 302eaa3b919SPawel Jakub Dawidek } 303eaa3b919SPawel Jakub Dawidek md.md_ealgo = g_eli_str2ealgo(name); 304eaa3b919SPawel Jakub Dawidek if (md.md_ealgo < CRYPTO_ALGORITHM_MIN || 305eaa3b919SPawel Jakub Dawidek md.md_ealgo > CRYPTO_ALGORITHM_MAX) { 306eaa3b919SPawel Jakub Dawidek gctl_error(req, "Invalid encryption algorithm."); 307c58794deSPawel Jakub Dawidek return; 308c58794deSPawel Jakub Dawidek } 309c84efdcaSPawel Jakub Dawidek } 310c58794deSPawel Jakub Dawidek 311c58794deSPawel Jakub Dawidek keylen = gctl_get_paraml(req, "keylen", sizeof(*keylen)); 312c58794deSPawel Jakub Dawidek if (keylen == NULL) { 313c58794deSPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "keylen"); 314c58794deSPawel Jakub Dawidek return; 315c58794deSPawel Jakub Dawidek } 316eaa3b919SPawel Jakub Dawidek md.md_keylen = g_eli_keylen(md.md_ealgo, *keylen); 317c58794deSPawel Jakub Dawidek if (md.md_keylen == 0) { 318c58794deSPawel Jakub Dawidek gctl_error(req, "Invalid '%s' argument.", "keylen"); 319c58794deSPawel Jakub Dawidek return; 320c58794deSPawel Jakub Dawidek } 321c58794deSPawel Jakub Dawidek 322c58794deSPawel Jakub Dawidek /* Not important here. */ 323c58794deSPawel Jakub Dawidek md.md_provsize = 0; 324c58794deSPawel Jakub Dawidek /* Not important here. */ 325c58794deSPawel Jakub Dawidek bzero(md.md_salt, sizeof(md.md_salt)); 326c58794deSPawel Jakub Dawidek 327c58794deSPawel Jakub Dawidek md.md_keys = 0x01; 328c58794deSPawel Jakub Dawidek arc4rand(mkey, sizeof(mkey), 0); 329c58794deSPawel Jakub Dawidek 330c58794deSPawel Jakub Dawidek /* Not important here. */ 331c58794deSPawel Jakub Dawidek bzero(md.md_hash, sizeof(md.md_hash)); 332c58794deSPawel Jakub Dawidek 333c58794deSPawel Jakub Dawidek name = gctl_get_asciiparam(req, "arg0"); 334c58794deSPawel Jakub Dawidek if (name == NULL) { 335c58794deSPawel Jakub Dawidek gctl_error(req, "No 'arg%u' argument.", 0); 336c58794deSPawel Jakub Dawidek return; 337c58794deSPawel Jakub Dawidek } 338c58794deSPawel Jakub Dawidek if (strncmp(name, "/dev/", strlen("/dev/")) == 0) 339c58794deSPawel Jakub Dawidek name += strlen("/dev/"); 340c58794deSPawel Jakub Dawidek pp = g_provider_by_name(name); 341c58794deSPawel Jakub Dawidek if (pp == NULL) { 342c58794deSPawel Jakub Dawidek gctl_error(req, "Provider %s is invalid.", name); 343c58794deSPawel Jakub Dawidek return; 344c58794deSPawel Jakub Dawidek } 345c58794deSPawel Jakub Dawidek 346c58794deSPawel Jakub Dawidek sectorsize = gctl_get_paraml(req, "sectorsize", sizeof(*sectorsize)); 347c58794deSPawel Jakub Dawidek if (sectorsize == NULL) { 348c58794deSPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "sectorsize"); 349c58794deSPawel Jakub Dawidek return; 350c58794deSPawel Jakub Dawidek } 351c58794deSPawel Jakub Dawidek if (*sectorsize == 0) 352c58794deSPawel Jakub Dawidek md.md_sectorsize = pp->sectorsize; 353c58794deSPawel Jakub Dawidek else { 354c58794deSPawel Jakub Dawidek if (*sectorsize < 0 || (*sectorsize % pp->sectorsize) != 0) { 355c58794deSPawel Jakub Dawidek gctl_error(req, "Invalid sector size."); 356c58794deSPawel Jakub Dawidek return; 357c58794deSPawel Jakub Dawidek } 35897a669a3SPawel Jakub Dawidek if (*sectorsize > PAGE_SIZE) { 35997a669a3SPawel Jakub Dawidek gctl_error(req, "warning: Using sectorsize bigger than " 36097a669a3SPawel Jakub Dawidek "the page size!"); 36197a669a3SPawel Jakub Dawidek } 362c58794deSPawel Jakub Dawidek md.md_sectorsize = *sectorsize; 363c58794deSPawel Jakub Dawidek } 364c58794deSPawel Jakub Dawidek 365c58794deSPawel Jakub Dawidek g_eli_create(req, mp, pp, &md, mkey, -1); 366c58794deSPawel Jakub Dawidek bzero(mkey, sizeof(mkey)); 367c58794deSPawel Jakub Dawidek bzero(&md, sizeof(md)); 368c58794deSPawel Jakub Dawidek } 369c58794deSPawel Jakub Dawidek 370c58794deSPawel Jakub Dawidek static void 3718abd1ad1SPawel Jakub Dawidek g_eli_ctl_configure(struct gctl_req *req, struct g_class *mp) 3728abd1ad1SPawel Jakub Dawidek { 3738abd1ad1SPawel Jakub Dawidek struct g_eli_softc *sc; 3748abd1ad1SPawel Jakub Dawidek struct g_eli_metadata md; 3758abd1ad1SPawel Jakub Dawidek struct g_provider *pp; 3768abd1ad1SPawel Jakub Dawidek struct g_consumer *cp; 3778abd1ad1SPawel Jakub Dawidek char param[16]; 3788abd1ad1SPawel Jakub Dawidek const char *prov; 3798abd1ad1SPawel Jakub Dawidek u_char *sector; 3808abd1ad1SPawel Jakub Dawidek int *nargs, *boot, *noboot; 3818abd1ad1SPawel Jakub Dawidek int error; 3828abd1ad1SPawel Jakub Dawidek u_int i; 3838abd1ad1SPawel Jakub Dawidek 3848abd1ad1SPawel Jakub Dawidek g_topology_assert(); 3858abd1ad1SPawel Jakub Dawidek 3868abd1ad1SPawel Jakub Dawidek nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); 3878abd1ad1SPawel Jakub Dawidek if (nargs == NULL) { 3888abd1ad1SPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "nargs"); 3898abd1ad1SPawel Jakub Dawidek return; 3908abd1ad1SPawel Jakub Dawidek } 3918abd1ad1SPawel Jakub Dawidek if (*nargs <= 0) { 3928abd1ad1SPawel Jakub Dawidek gctl_error(req, "Missing device(s)."); 3938abd1ad1SPawel Jakub Dawidek return; 3948abd1ad1SPawel Jakub Dawidek } 3958abd1ad1SPawel Jakub Dawidek 3968abd1ad1SPawel Jakub Dawidek boot = gctl_get_paraml(req, "boot", sizeof(*boot)); 3978abd1ad1SPawel Jakub Dawidek if (boot == NULL) { 3988abd1ad1SPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "boot"); 3998abd1ad1SPawel Jakub Dawidek return; 4008abd1ad1SPawel Jakub Dawidek } 4018abd1ad1SPawel Jakub Dawidek noboot = gctl_get_paraml(req, "noboot", sizeof(*noboot)); 4028abd1ad1SPawel Jakub Dawidek if (noboot == NULL) { 4038abd1ad1SPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "noboot"); 4048abd1ad1SPawel Jakub Dawidek return; 4058abd1ad1SPawel Jakub Dawidek } 4068abd1ad1SPawel Jakub Dawidek if (*boot && *noboot) { 4078abd1ad1SPawel Jakub Dawidek gctl_error(req, "Options -b and -B are mutually exclusive."); 4088abd1ad1SPawel Jakub Dawidek return; 4098abd1ad1SPawel Jakub Dawidek } 4108abd1ad1SPawel Jakub Dawidek if (!*boot && !*noboot) { 4118abd1ad1SPawel Jakub Dawidek gctl_error(req, "No option given."); 4128abd1ad1SPawel Jakub Dawidek return; 4138abd1ad1SPawel Jakub Dawidek } 4148abd1ad1SPawel Jakub Dawidek 4158abd1ad1SPawel Jakub Dawidek for (i = 0; i < *nargs; i++) { 4168abd1ad1SPawel Jakub Dawidek snprintf(param, sizeof(param), "arg%d", i); 4178abd1ad1SPawel Jakub Dawidek prov = gctl_get_asciiparam(req, param); 4188abd1ad1SPawel Jakub Dawidek if (prov == NULL) { 4198abd1ad1SPawel Jakub Dawidek gctl_error(req, "No 'arg%d' argument.", i); 4208abd1ad1SPawel Jakub Dawidek return; 4218abd1ad1SPawel Jakub Dawidek } 4228abd1ad1SPawel Jakub Dawidek sc = g_eli_find_device(mp, prov); 4238abd1ad1SPawel Jakub Dawidek if (sc == NULL) { 4248abd1ad1SPawel Jakub Dawidek /* 4258abd1ad1SPawel Jakub Dawidek * We ignore not attached providers, userland part will 4268abd1ad1SPawel Jakub Dawidek * take care of them. 4278abd1ad1SPawel Jakub Dawidek */ 4288abd1ad1SPawel Jakub Dawidek G_ELI_DEBUG(1, "Skipping configuration of not attached " 4298abd1ad1SPawel Jakub Dawidek "provider %s.", prov); 4308abd1ad1SPawel Jakub Dawidek continue; 4318abd1ad1SPawel Jakub Dawidek } 4328abd1ad1SPawel Jakub Dawidek if (*boot && (sc->sc_flags & G_ELI_FLAG_BOOT)) { 4338abd1ad1SPawel Jakub Dawidek G_ELI_DEBUG(1, "BOOT flag already configured for %s.", 4348abd1ad1SPawel Jakub Dawidek prov); 4358abd1ad1SPawel Jakub Dawidek continue; 4368abd1ad1SPawel Jakub Dawidek } else if (!*boot && !(sc->sc_flags & G_ELI_FLAG_BOOT)) { 4378abd1ad1SPawel Jakub Dawidek G_ELI_DEBUG(1, "BOOT flag not configured for %s.", 4388abd1ad1SPawel Jakub Dawidek prov); 4398abd1ad1SPawel Jakub Dawidek continue; 4408abd1ad1SPawel Jakub Dawidek } 4418abd1ad1SPawel Jakub Dawidek if (sc->sc_flags & G_ELI_FLAG_RO) { 4428abd1ad1SPawel Jakub Dawidek gctl_error(req, "Cannot change configuration of " 4438abd1ad1SPawel Jakub Dawidek "read-only provider %s.", prov); 4448abd1ad1SPawel Jakub Dawidek continue; 4458abd1ad1SPawel Jakub Dawidek } 4468abd1ad1SPawel Jakub Dawidek cp = LIST_FIRST(&sc->sc_geom->consumer); 4478abd1ad1SPawel Jakub Dawidek pp = cp->provider; 4488abd1ad1SPawel Jakub Dawidek error = g_eli_read_metadata(mp, pp, &md); 4498abd1ad1SPawel Jakub Dawidek if (error != 0) { 4508abd1ad1SPawel Jakub Dawidek gctl_error(req, 4518abd1ad1SPawel Jakub Dawidek "Cannot read metadata from %s (error=%d).", 4528abd1ad1SPawel Jakub Dawidek prov, error); 4538abd1ad1SPawel Jakub Dawidek continue; 4548abd1ad1SPawel Jakub Dawidek } 4558abd1ad1SPawel Jakub Dawidek 4568abd1ad1SPawel Jakub Dawidek if (*boot) { 4578abd1ad1SPawel Jakub Dawidek md.md_flags |= G_ELI_FLAG_BOOT; 4588abd1ad1SPawel Jakub Dawidek sc->sc_flags |= G_ELI_FLAG_BOOT; 4598abd1ad1SPawel Jakub Dawidek } else { 4608abd1ad1SPawel Jakub Dawidek md.md_flags &= ~G_ELI_FLAG_BOOT; 4618abd1ad1SPawel Jakub Dawidek sc->sc_flags &= ~G_ELI_FLAG_BOOT; 4628abd1ad1SPawel Jakub Dawidek } 4638abd1ad1SPawel Jakub Dawidek 4648abd1ad1SPawel Jakub Dawidek sector = malloc(pp->sectorsize, M_ELI, M_WAITOK | M_ZERO); 4658abd1ad1SPawel Jakub Dawidek eli_metadata_encode(&md, sector); 4668abd1ad1SPawel Jakub Dawidek error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector, 4678abd1ad1SPawel Jakub Dawidek pp->sectorsize); 4688abd1ad1SPawel Jakub Dawidek if (error != 0) { 4698abd1ad1SPawel Jakub Dawidek gctl_error(req, 4708abd1ad1SPawel Jakub Dawidek "Cannot store metadata on %s (error=%d).", 4718abd1ad1SPawel Jakub Dawidek prov, error); 4728abd1ad1SPawel Jakub Dawidek } 4738abd1ad1SPawel Jakub Dawidek bzero(&md, sizeof(md)); 4748abd1ad1SPawel Jakub Dawidek bzero(sector, sizeof(sector)); 4758abd1ad1SPawel Jakub Dawidek free(sector, M_ELI); 4768abd1ad1SPawel Jakub Dawidek } 4778abd1ad1SPawel Jakub Dawidek } 4788abd1ad1SPawel Jakub Dawidek 4798abd1ad1SPawel Jakub Dawidek static void 480c58794deSPawel Jakub Dawidek g_eli_ctl_setkey(struct gctl_req *req, struct g_class *mp) 481c58794deSPawel Jakub Dawidek { 482c58794deSPawel Jakub Dawidek struct g_eli_softc *sc; 483c58794deSPawel Jakub Dawidek struct g_eli_metadata md; 484c58794deSPawel Jakub Dawidek struct g_provider *pp; 485c58794deSPawel Jakub Dawidek struct g_consumer *cp; 486c58794deSPawel Jakub Dawidek const char *name; 487c58794deSPawel Jakub Dawidek u_char *key, *mkeydst, *sector; 488c58794deSPawel Jakub Dawidek intmax_t *valp; 4897a5c26fcSPawel Jakub Dawidek int keysize, nkey, error; 490c58794deSPawel Jakub Dawidek 491c58794deSPawel Jakub Dawidek g_topology_assert(); 492c58794deSPawel Jakub Dawidek 493c58794deSPawel Jakub Dawidek name = gctl_get_asciiparam(req, "arg0"); 494c58794deSPawel Jakub Dawidek if (name == NULL) { 495c58794deSPawel Jakub Dawidek gctl_error(req, "No 'arg%u' argument.", 0); 496c58794deSPawel Jakub Dawidek return; 497c58794deSPawel Jakub Dawidek } 498c58794deSPawel Jakub Dawidek sc = g_eli_find_device(mp, name); 499c58794deSPawel Jakub Dawidek if (sc == NULL) { 500c58794deSPawel Jakub Dawidek gctl_error(req, "Provider %s is invalid.", name); 501c58794deSPawel Jakub Dawidek return; 502c58794deSPawel Jakub Dawidek } 50385059016SPawel Jakub Dawidek if (sc->sc_flags & G_ELI_FLAG_RO) { 50485059016SPawel Jakub Dawidek gctl_error(req, "Cannot change keys for read-only provider."); 50585059016SPawel Jakub Dawidek return; 50685059016SPawel Jakub Dawidek } 507c58794deSPawel Jakub Dawidek cp = LIST_FIRST(&sc->sc_geom->consumer); 508c58794deSPawel Jakub Dawidek pp = cp->provider; 509c58794deSPawel Jakub Dawidek 510c58794deSPawel Jakub Dawidek error = g_eli_read_metadata(mp, pp, &md); 511c58794deSPawel Jakub Dawidek if (error != 0) { 512c58794deSPawel Jakub Dawidek gctl_error(req, "Cannot read metadata from %s (error=%d).", 513c58794deSPawel Jakub Dawidek name, error); 514c58794deSPawel Jakub Dawidek return; 515c58794deSPawel Jakub Dawidek } 516c58794deSPawel Jakub Dawidek 517c58794deSPawel Jakub Dawidek valp = gctl_get_paraml(req, "keyno", sizeof(*valp)); 518c58794deSPawel Jakub Dawidek if (valp == NULL) { 519c58794deSPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "keyno"); 520c58794deSPawel Jakub Dawidek return; 521c58794deSPawel Jakub Dawidek } 522c58794deSPawel Jakub Dawidek if (*valp != -1) 523c58794deSPawel Jakub Dawidek nkey = *valp; 524c58794deSPawel Jakub Dawidek else 525c58794deSPawel Jakub Dawidek nkey = sc->sc_nkey; 526c58794deSPawel Jakub Dawidek if (nkey < 0 || nkey >= G_ELI_MAXMKEYS) { 527c58794deSPawel Jakub Dawidek gctl_error(req, "Invalid '%s' argument.", "keyno"); 528c58794deSPawel Jakub Dawidek return; 529c58794deSPawel Jakub Dawidek } 530c58794deSPawel Jakub Dawidek 5317a5c26fcSPawel Jakub Dawidek valp = gctl_get_paraml(req, "iterations", sizeof(*valp)); 5327a5c26fcSPawel Jakub Dawidek if (valp == NULL) { 5337a5c26fcSPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "iterations"); 5347a5c26fcSPawel Jakub Dawidek return; 5357a5c26fcSPawel Jakub Dawidek } 5367a5c26fcSPawel Jakub Dawidek /* Check if iterations number should and can be changed. */ 5377a5c26fcSPawel Jakub Dawidek if (*valp != -1) { 5387a5c26fcSPawel Jakub Dawidek if (bitcount32(md.md_keys) != 1) { 5397a5c26fcSPawel Jakub Dawidek gctl_error(req, "To be able to use '-i' option, only " 5407a5c26fcSPawel Jakub Dawidek "one key can be defined."); 5417a5c26fcSPawel Jakub Dawidek return; 5427a5c26fcSPawel Jakub Dawidek } 5437a5c26fcSPawel Jakub Dawidek if (md.md_keys != (1 << nkey)) { 5447a5c26fcSPawel Jakub Dawidek gctl_error(req, "Only already defined key can be " 5457a5c26fcSPawel Jakub Dawidek "changed when '-i' option is used."); 5467a5c26fcSPawel Jakub Dawidek return; 5477a5c26fcSPawel Jakub Dawidek } 5487a5c26fcSPawel Jakub Dawidek md.md_iterations = *valp; 5497a5c26fcSPawel Jakub Dawidek } 5507a5c26fcSPawel Jakub Dawidek 551c58794deSPawel Jakub Dawidek key = gctl_get_param(req, "key", &keysize); 552c58794deSPawel Jakub Dawidek if (key == NULL || keysize != G_ELI_USERKEYLEN) { 553c58794deSPawel Jakub Dawidek bzero(&md, sizeof(md)); 554c58794deSPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "key"); 555c58794deSPawel Jakub Dawidek return; 556c58794deSPawel Jakub Dawidek } 557c58794deSPawel Jakub Dawidek 558c58794deSPawel Jakub Dawidek mkeydst = md.md_mkeys + nkey * G_ELI_MKEYLEN; 559c58794deSPawel Jakub Dawidek md.md_keys |= (1 << nkey); 560c58794deSPawel Jakub Dawidek 561eaa3b919SPawel Jakub Dawidek bcopy(sc->sc_mkey, mkeydst, sizeof(sc->sc_mkey)); 562c58794deSPawel Jakub Dawidek 563c58794deSPawel Jakub Dawidek /* Encrypt Master Key with the new key. */ 564eaa3b919SPawel Jakub Dawidek error = g_eli_mkey_encrypt(md.md_ealgo, key, md.md_keylen, mkeydst); 565c58794deSPawel Jakub Dawidek bzero(key, sizeof(key)); 566c58794deSPawel Jakub Dawidek if (error != 0) { 567c58794deSPawel Jakub Dawidek bzero(&md, sizeof(md)); 568c58794deSPawel Jakub Dawidek gctl_error(req, "Cannot encrypt Master Key (error=%d).", error); 569c58794deSPawel Jakub Dawidek return; 570c58794deSPawel Jakub Dawidek } 571c58794deSPawel Jakub Dawidek 572c58794deSPawel Jakub Dawidek sector = malloc(pp->sectorsize, M_ELI, M_WAITOK | M_ZERO); 573c58794deSPawel Jakub Dawidek /* Store metadata with fresh key. */ 574c58794deSPawel Jakub Dawidek eli_metadata_encode(&md, sector); 575c58794deSPawel Jakub Dawidek bzero(&md, sizeof(md)); 576c58794deSPawel Jakub Dawidek error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector, 577c58794deSPawel Jakub Dawidek pp->sectorsize); 578c58794deSPawel Jakub Dawidek bzero(sector, sizeof(sector)); 579c58794deSPawel Jakub Dawidek free(sector, M_ELI); 580c58794deSPawel Jakub Dawidek if (error != 0) { 581c58794deSPawel Jakub Dawidek gctl_error(req, "Cannot store metadata on %s (error=%d).", 582c58794deSPawel Jakub Dawidek pp->name, error); 583c58794deSPawel Jakub Dawidek return; 584c58794deSPawel Jakub Dawidek } 585c58794deSPawel Jakub Dawidek G_ELI_DEBUG(1, "Key %u changed on %s.", nkey, pp->name); 586c58794deSPawel Jakub Dawidek } 587c58794deSPawel Jakub Dawidek 588c58794deSPawel Jakub Dawidek static void 589c58794deSPawel Jakub Dawidek g_eli_ctl_delkey(struct gctl_req *req, struct g_class *mp) 590c58794deSPawel Jakub Dawidek { 591c58794deSPawel Jakub Dawidek struct g_eli_softc *sc; 592c58794deSPawel Jakub Dawidek struct g_eli_metadata md; 593c58794deSPawel Jakub Dawidek struct g_provider *pp; 594c58794deSPawel Jakub Dawidek struct g_consumer *cp; 595c58794deSPawel Jakub Dawidek const char *name; 596c58794deSPawel Jakub Dawidek u_char *mkeydst, *sector; 597c58794deSPawel Jakub Dawidek intmax_t *valp; 598c58794deSPawel Jakub Dawidek size_t keysize; 599c58794deSPawel Jakub Dawidek int error, nkey, *all, *force; 600c58794deSPawel Jakub Dawidek u_int i; 601c58794deSPawel Jakub Dawidek 602c58794deSPawel Jakub Dawidek g_topology_assert(); 603c58794deSPawel Jakub Dawidek 604c58794deSPawel Jakub Dawidek nkey = 0; /* fixes causeless gcc warning */ 605c58794deSPawel Jakub Dawidek 606c58794deSPawel Jakub Dawidek name = gctl_get_asciiparam(req, "arg0"); 607c58794deSPawel Jakub Dawidek if (name == NULL) { 608c58794deSPawel Jakub Dawidek gctl_error(req, "No 'arg%u' argument.", 0); 609c58794deSPawel Jakub Dawidek return; 610c58794deSPawel Jakub Dawidek } 611c58794deSPawel Jakub Dawidek sc = g_eli_find_device(mp, name); 612c58794deSPawel Jakub Dawidek if (sc == NULL) { 613c58794deSPawel Jakub Dawidek gctl_error(req, "Provider %s is invalid.", name); 614c58794deSPawel Jakub Dawidek return; 615c58794deSPawel Jakub Dawidek } 61685059016SPawel Jakub Dawidek if (sc->sc_flags & G_ELI_FLAG_RO) { 61785059016SPawel Jakub Dawidek gctl_error(req, "Cannot delete keys for read-only provider."); 61885059016SPawel Jakub Dawidek return; 61985059016SPawel Jakub Dawidek } 620c58794deSPawel Jakub Dawidek cp = LIST_FIRST(&sc->sc_geom->consumer); 621c58794deSPawel Jakub Dawidek pp = cp->provider; 622c58794deSPawel Jakub Dawidek 623c58794deSPawel Jakub Dawidek error = g_eli_read_metadata(mp, pp, &md); 624c58794deSPawel Jakub Dawidek if (error != 0) { 625c58794deSPawel Jakub Dawidek gctl_error(req, "Cannot read metadata from %s (error=%d).", 626c58794deSPawel Jakub Dawidek name, error); 627c58794deSPawel Jakub Dawidek return; 628c58794deSPawel Jakub Dawidek } 629c58794deSPawel Jakub Dawidek 630c58794deSPawel Jakub Dawidek all = gctl_get_paraml(req, "all", sizeof(*all)); 631c58794deSPawel Jakub Dawidek if (all == NULL) { 632c58794deSPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "all"); 633c58794deSPawel Jakub Dawidek return; 634c58794deSPawel Jakub Dawidek } 635c58794deSPawel Jakub Dawidek 636c58794deSPawel Jakub Dawidek if (*all) { 637c58794deSPawel Jakub Dawidek mkeydst = md.md_mkeys; 638c58794deSPawel Jakub Dawidek keysize = sizeof(md.md_mkeys); 639c58794deSPawel Jakub Dawidek } else { 640c58794deSPawel Jakub Dawidek force = gctl_get_paraml(req, "force", sizeof(*force)); 641c58794deSPawel Jakub Dawidek if (force == NULL) { 642c58794deSPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "force"); 643c58794deSPawel Jakub Dawidek return; 644c58794deSPawel Jakub Dawidek } 645c58794deSPawel Jakub Dawidek 646c58794deSPawel Jakub Dawidek valp = gctl_get_paraml(req, "keyno", sizeof(*valp)); 647c58794deSPawel Jakub Dawidek if (valp == NULL) { 648c58794deSPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "keyno"); 649c58794deSPawel Jakub Dawidek return; 650c58794deSPawel Jakub Dawidek } 651c58794deSPawel Jakub Dawidek if (*valp != -1) 652c58794deSPawel Jakub Dawidek nkey = *valp; 653c58794deSPawel Jakub Dawidek else 654c58794deSPawel Jakub Dawidek nkey = sc->sc_nkey; 655c58794deSPawel Jakub Dawidek if (nkey < 0 || nkey >= G_ELI_MAXMKEYS) { 656c58794deSPawel Jakub Dawidek gctl_error(req, "Invalid '%s' argument.", "keyno"); 657c58794deSPawel Jakub Dawidek return; 658c58794deSPawel Jakub Dawidek } 659c58794deSPawel Jakub Dawidek if (!(md.md_keys & (1 << nkey)) && !*force) { 660c58794deSPawel Jakub Dawidek gctl_error(req, "Master Key %u is not set.", nkey); 661c58794deSPawel Jakub Dawidek return; 662c58794deSPawel Jakub Dawidek } 663c58794deSPawel Jakub Dawidek md.md_keys &= ~(1 << nkey); 664c58794deSPawel Jakub Dawidek if (md.md_keys == 0 && !*force) { 665c58794deSPawel Jakub Dawidek gctl_error(req, "This is the last Master Key. Use '-f' " 666c58794deSPawel Jakub Dawidek "flag if you really want to remove it."); 667c58794deSPawel Jakub Dawidek return; 668c58794deSPawel Jakub Dawidek } 669c58794deSPawel Jakub Dawidek mkeydst = md.md_mkeys + nkey * G_ELI_MKEYLEN; 670c58794deSPawel Jakub Dawidek keysize = G_ELI_MKEYLEN; 671c58794deSPawel Jakub Dawidek } 672c58794deSPawel Jakub Dawidek 673c58794deSPawel Jakub Dawidek sector = malloc(pp->sectorsize, M_ELI, M_WAITOK | M_ZERO); 674c58794deSPawel Jakub Dawidek for (i = 0; i <= g_eli_overwrites; i++) { 675c58794deSPawel Jakub Dawidek if (i == g_eli_overwrites) 676c58794deSPawel Jakub Dawidek bzero(mkeydst, keysize); 677c58794deSPawel Jakub Dawidek else 678c58794deSPawel Jakub Dawidek arc4rand(mkeydst, keysize, 0); 679c58794deSPawel Jakub Dawidek /* Store metadata with destroyed key. */ 680c58794deSPawel Jakub Dawidek eli_metadata_encode(&md, sector); 681c58794deSPawel Jakub Dawidek error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector, 682c58794deSPawel Jakub Dawidek pp->sectorsize); 683c58794deSPawel Jakub Dawidek if (error != 0) { 684c58794deSPawel Jakub Dawidek G_ELI_DEBUG(0, "Cannot store metadata on %s " 685c58794deSPawel Jakub Dawidek "(error=%d).", pp->name, error); 686c58794deSPawel Jakub Dawidek } 687f0256e71SPawel Jakub Dawidek /* 688f0256e71SPawel Jakub Dawidek * Flush write cache so we don't overwrite data N times in cache 689f0256e71SPawel Jakub Dawidek * and only once on disk. 690f0256e71SPawel Jakub Dawidek */ 691f0256e71SPawel Jakub Dawidek g_io_flush(cp); 692c58794deSPawel Jakub Dawidek } 693c58794deSPawel Jakub Dawidek bzero(&md, sizeof(md)); 694c58794deSPawel Jakub Dawidek bzero(sector, sizeof(sector)); 695c58794deSPawel Jakub Dawidek free(sector, M_ELI); 696c58794deSPawel Jakub Dawidek if (*all) 697c58794deSPawel Jakub Dawidek G_ELI_DEBUG(1, "All keys removed from %s.", pp->name); 698c58794deSPawel Jakub Dawidek else 699c58794deSPawel Jakub Dawidek G_ELI_DEBUG(1, "Key %d removed from %s.", nkey, pp->name); 700c58794deSPawel Jakub Dawidek } 701c58794deSPawel Jakub Dawidek 702c58794deSPawel Jakub Dawidek static int 703c58794deSPawel Jakub Dawidek g_eli_kill_one(struct g_eli_softc *sc) 704c58794deSPawel Jakub Dawidek { 705c58794deSPawel Jakub Dawidek struct g_provider *pp; 706c58794deSPawel Jakub Dawidek struct g_consumer *cp; 70785059016SPawel Jakub Dawidek int error = 0; 708c58794deSPawel Jakub Dawidek 709c58794deSPawel Jakub Dawidek g_topology_assert(); 710c58794deSPawel Jakub Dawidek 711c58794deSPawel Jakub Dawidek if (sc == NULL) 712c58794deSPawel Jakub Dawidek return (ENOENT); 713c58794deSPawel Jakub Dawidek 714c58794deSPawel Jakub Dawidek pp = LIST_FIRST(&sc->sc_geom->provider); 715c58794deSPawel Jakub Dawidek g_error_provider(pp, ENXIO); 716c58794deSPawel Jakub Dawidek 717c58794deSPawel Jakub Dawidek cp = LIST_FIRST(&sc->sc_geom->consumer); 718c58794deSPawel Jakub Dawidek pp = cp->provider; 719c58794deSPawel Jakub Dawidek 72085059016SPawel Jakub Dawidek if (sc->sc_flags & G_ELI_FLAG_RO) { 72185059016SPawel Jakub Dawidek G_ELI_DEBUG(0, "WARNING: Metadata won't be erased on read-only " 72285059016SPawel Jakub Dawidek "provider: %s.", pp->name); 72385059016SPawel Jakub Dawidek } else { 72485059016SPawel Jakub Dawidek u_char *sector; 72585059016SPawel Jakub Dawidek u_int i; 72685059016SPawel Jakub Dawidek int err; 72785059016SPawel Jakub Dawidek 728c58794deSPawel Jakub Dawidek sector = malloc(pp->sectorsize, M_ELI, M_WAITOK); 729c58794deSPawel Jakub Dawidek for (i = 0; i <= g_eli_overwrites; i++) { 730c58794deSPawel Jakub Dawidek if (i == g_eli_overwrites) 731c58794deSPawel Jakub Dawidek bzero(sector, pp->sectorsize); 732c58794deSPawel Jakub Dawidek else 733c58794deSPawel Jakub Dawidek arc4rand(sector, pp->sectorsize, 0); 73485059016SPawel Jakub Dawidek err = g_write_data(cp, pp->mediasize - pp->sectorsize, 73585059016SPawel Jakub Dawidek sector, pp->sectorsize); 736c58794deSPawel Jakub Dawidek if (err != 0) { 737c58794deSPawel Jakub Dawidek G_ELI_DEBUG(0, "Cannot erase metadata on %s " 738c58794deSPawel Jakub Dawidek "(error=%d).", pp->name, err); 739c58794deSPawel Jakub Dawidek if (error == 0) 740c58794deSPawel Jakub Dawidek error = err; 741c58794deSPawel Jakub Dawidek } 742c58794deSPawel Jakub Dawidek } 743c58794deSPawel Jakub Dawidek free(sector, M_ELI); 74485059016SPawel Jakub Dawidek } 745c58794deSPawel Jakub Dawidek if (error == 0) 746c58794deSPawel Jakub Dawidek G_ELI_DEBUG(0, "%s has been killed.", pp->name); 747c58794deSPawel Jakub Dawidek g_eli_destroy(sc, 1); 748c58794deSPawel Jakub Dawidek return (error); 749c58794deSPawel Jakub Dawidek } 750c58794deSPawel Jakub Dawidek 751c58794deSPawel Jakub Dawidek static void 752c58794deSPawel Jakub Dawidek g_eli_ctl_kill(struct gctl_req *req, struct g_class *mp) 753c58794deSPawel Jakub Dawidek { 754c58794deSPawel Jakub Dawidek int *all, *nargs; 755c58794deSPawel Jakub Dawidek int error; 756c58794deSPawel Jakub Dawidek 757c58794deSPawel Jakub Dawidek g_topology_assert(); 758c58794deSPawel Jakub Dawidek 759c58794deSPawel Jakub Dawidek nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); 760c58794deSPawel Jakub Dawidek if (nargs == NULL) { 761c58794deSPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "nargs"); 762c58794deSPawel Jakub Dawidek return; 763c58794deSPawel Jakub Dawidek } 764c58794deSPawel Jakub Dawidek all = gctl_get_paraml(req, "all", sizeof(*all)); 765c58794deSPawel Jakub Dawidek if (all == NULL) { 766c58794deSPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "all"); 767c58794deSPawel Jakub Dawidek return; 768c58794deSPawel Jakub Dawidek } 769c58794deSPawel Jakub Dawidek if (!*all && *nargs == 0) { 770c58794deSPawel Jakub Dawidek gctl_error(req, "Too few arguments."); 771c58794deSPawel Jakub Dawidek return; 772c58794deSPawel Jakub Dawidek } 773c58794deSPawel Jakub Dawidek 774c58794deSPawel Jakub Dawidek if (*all) { 775c58794deSPawel Jakub Dawidek struct g_geom *gp, *gp2; 776c58794deSPawel Jakub Dawidek 777c58794deSPawel Jakub Dawidek LIST_FOREACH_SAFE(gp, &mp->geom, geom, gp2) { 778c58794deSPawel Jakub Dawidek error = g_eli_kill_one(gp->softc); 779c58794deSPawel Jakub Dawidek if (error != 0) 780c58794deSPawel Jakub Dawidek gctl_error(req, "Not fully done."); 781c58794deSPawel Jakub Dawidek } 782c58794deSPawel Jakub Dawidek } else { 783c58794deSPawel Jakub Dawidek struct g_eli_softc *sc; 784c58794deSPawel Jakub Dawidek const char *prov; 785c58794deSPawel Jakub Dawidek char param[16]; 786c58794deSPawel Jakub Dawidek int i; 787c58794deSPawel Jakub Dawidek 788c58794deSPawel Jakub Dawidek for (i = 0; i < *nargs; i++) { 7897d54b385SPawel Jakub Dawidek snprintf(param, sizeof(param), "arg%d", i); 790c58794deSPawel Jakub Dawidek prov = gctl_get_asciiparam(req, param); 791b5f30223SPawel Jakub Dawidek if (prov == NULL) { 792b5f30223SPawel Jakub Dawidek G_ELI_DEBUG(0, "No 'arg%d' argument.", i); 793b5f30223SPawel Jakub Dawidek continue; 794b5f30223SPawel Jakub Dawidek } 795c58794deSPawel Jakub Dawidek 796c58794deSPawel Jakub Dawidek sc = g_eli_find_device(mp, prov); 797c58794deSPawel Jakub Dawidek if (sc == NULL) { 7987d54b385SPawel Jakub Dawidek G_ELI_DEBUG(0, "No such provider: %s.", prov); 799c58794deSPawel Jakub Dawidek continue; 800c58794deSPawel Jakub Dawidek } 801c58794deSPawel Jakub Dawidek error = g_eli_kill_one(sc); 802c58794deSPawel Jakub Dawidek if (error != 0) 803c58794deSPawel Jakub Dawidek gctl_error(req, "Not fully done."); 804c58794deSPawel Jakub Dawidek } 805c58794deSPawel Jakub Dawidek } 806c58794deSPawel Jakub Dawidek } 807c58794deSPawel Jakub Dawidek 808c58794deSPawel Jakub Dawidek void 809c58794deSPawel Jakub Dawidek g_eli_config(struct gctl_req *req, struct g_class *mp, const char *verb) 810c58794deSPawel Jakub Dawidek { 811c58794deSPawel Jakub Dawidek uint32_t *version; 812c58794deSPawel Jakub Dawidek 813c58794deSPawel Jakub Dawidek g_topology_assert(); 814c58794deSPawel Jakub Dawidek 815c58794deSPawel Jakub Dawidek version = gctl_get_paraml(req, "version", sizeof(*version)); 816c58794deSPawel Jakub Dawidek if (version == NULL) { 817c58794deSPawel Jakub Dawidek gctl_error(req, "No '%s' argument.", "version"); 818c58794deSPawel Jakub Dawidek return; 819c58794deSPawel Jakub Dawidek } 820c58794deSPawel Jakub Dawidek if (*version != G_ELI_VERSION) { 821c58794deSPawel Jakub Dawidek gctl_error(req, "Userland and kernel parts are out of sync."); 822c58794deSPawel Jakub Dawidek return; 823c58794deSPawel Jakub Dawidek } 824c58794deSPawel Jakub Dawidek 825c58794deSPawel Jakub Dawidek if (strcmp(verb, "attach") == 0) 826c58794deSPawel Jakub Dawidek g_eli_ctl_attach(req, mp); 827c58794deSPawel Jakub Dawidek else if (strcmp(verb, "detach") == 0 || strcmp(verb, "stop") == 0) 828c58794deSPawel Jakub Dawidek g_eli_ctl_detach(req, mp); 829c58794deSPawel Jakub Dawidek else if (strcmp(verb, "onetime") == 0) 830c58794deSPawel Jakub Dawidek g_eli_ctl_onetime(req, mp); 8318abd1ad1SPawel Jakub Dawidek else if (strcmp(verb, "configure") == 0) 8328abd1ad1SPawel Jakub Dawidek g_eli_ctl_configure(req, mp); 833c58794deSPawel Jakub Dawidek else if (strcmp(verb, "setkey") == 0) 834c58794deSPawel Jakub Dawidek g_eli_ctl_setkey(req, mp); 835c58794deSPawel Jakub Dawidek else if (strcmp(verb, "delkey") == 0) 836c58794deSPawel Jakub Dawidek g_eli_ctl_delkey(req, mp); 837c58794deSPawel Jakub Dawidek else if (strcmp(verb, "kill") == 0) 838c58794deSPawel Jakub Dawidek g_eli_ctl_kill(req, mp); 839c58794deSPawel Jakub Dawidek else 840c58794deSPawel Jakub Dawidek gctl_error(req, "Unknown verb."); 841c58794deSPawel Jakub Dawidek } 842