]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/geom/eli/g_eli_ctl.c
Merge OpenBSM 1.2 alpha 4.
[FreeBSD/FreeBSD.git] / sys / geom / eli / g_eli_ctl.c
1 /*-
2  * Copyright (c) 2005-2011 Pawel Jakub Dawidek <pawel@dawidek.net>
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, *readonly;
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         readonly = gctl_get_paraml(req, "readonly", sizeof(*readonly));
83         if (readonly == NULL) {
84                 gctl_error(req, "No '%s' argument.", "readonly");
85                 return;
86         }
87
88         name = gctl_get_asciiparam(req, "arg0");
89         if (name == NULL) {
90                 gctl_error(req, "No 'arg%u' argument.", 0);
91                 return;
92         }
93         if (strncmp(name, "/dev/", strlen("/dev/")) == 0)
94                 name += strlen("/dev/");
95         pp = g_provider_by_name(name);
96         if (pp == NULL) {
97                 gctl_error(req, "Provider %s is invalid.", name);
98                 return;
99         }
100         error = g_eli_read_metadata(mp, pp, &md);
101         if (error != 0) {
102                 gctl_error(req, "Cannot read metadata from %s (error=%d).",
103                     name, error);
104                 return;
105         }
106         if (md.md_keys == 0x00) {
107                 bzero(&md, sizeof(md));
108                 gctl_error(req, "No valid keys on %s.", pp->name);
109                 return;
110         }
111
112         key = gctl_get_param(req, "key", &keysize);
113         if (key == NULL || keysize != G_ELI_USERKEYLEN) {
114                 bzero(&md, sizeof(md));
115                 gctl_error(req, "No '%s' argument.", "key");
116                 return;
117         }
118
119         error = g_eli_mkey_decrypt(&md, key, mkey, &nkey);
120         bzero(key, keysize);
121         if (error == -1) {
122                 bzero(&md, sizeof(md));
123                 gctl_error(req, "Wrong key for %s.", pp->name);
124                 return;
125         } else if (error > 0) {
126                 bzero(&md, sizeof(md));
127                 gctl_error(req, "Cannot decrypt Master Key for %s (error=%d).",
128                     pp->name, error);
129                 return;
130         }
131         G_ELI_DEBUG(1, "Using Master Key %u for %s.", nkey, pp->name);
132
133         if (*detach && *readonly) {
134                 bzero(&md, sizeof(md));
135                 gctl_error(req, "Options -d and -r are mutually exclusive.");
136                 return;
137         }
138         if (*detach)
139                 md.md_flags |= G_ELI_FLAG_WO_DETACH;
140         if (*readonly)
141                 md.md_flags |= G_ELI_FLAG_RO;
142         g_eli_create(req, mp, pp, &md, mkey, nkey);
143         bzero(mkey, sizeof(mkey));
144         bzero(&md, sizeof(md));
145 }
146
147 static struct g_eli_softc *
148 g_eli_find_device(struct g_class *mp, const char *prov)
149 {
150         struct g_eli_softc *sc;
151         struct g_geom *gp;
152         struct g_provider *pp;
153         struct g_consumer *cp;
154
155         if (strncmp(prov, "/dev/", strlen("/dev/")) == 0)
156                 prov += strlen("/dev/");
157         LIST_FOREACH(gp, &mp->geom, geom) {
158                 sc = gp->softc;
159                 if (sc == NULL)
160                         continue;
161                 pp = LIST_FIRST(&gp->provider);
162                 if (pp != NULL && strcmp(pp->name, prov) == 0)
163                         return (sc);
164                 cp = LIST_FIRST(&gp->consumer);
165                 if (cp != NULL && cp->provider != NULL &&
166                     strcmp(cp->provider->name, prov) == 0) {
167                         return (sc);
168                 }
169         }
170         return (NULL);
171 }
172
173 static void
174 g_eli_ctl_detach(struct gctl_req *req, struct g_class *mp)
175 {
176         struct g_eli_softc *sc;
177         int *force, *last, *nargs, error;
178         const char *prov;
179         char param[16];
180         int i;
181
182         g_topology_assert();
183
184         nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
185         if (nargs == NULL) {
186                 gctl_error(req, "No '%s' argument.", "nargs");
187                 return;
188         }
189         if (*nargs <= 0) {
190                 gctl_error(req, "Missing device(s).");
191                 return;
192         }
193         force = gctl_get_paraml(req, "force", sizeof(*force));
194         if (force == NULL) {
195                 gctl_error(req, "No '%s' argument.", "force");
196                 return;
197         }
198         last = gctl_get_paraml(req, "last", sizeof(*last));
199         if (last == NULL) {
200                 gctl_error(req, "No '%s' argument.", "last");
201                 return;
202         }
203
204         for (i = 0; i < *nargs; i++) {
205                 snprintf(param, sizeof(param), "arg%d", i);
206                 prov = gctl_get_asciiparam(req, param);
207                 if (prov == NULL) {
208                         gctl_error(req, "No 'arg%d' argument.", i);
209                         return;
210                 }
211                 sc = g_eli_find_device(mp, prov);
212                 if (sc == NULL) {
213                         gctl_error(req, "No such device: %s.", prov);
214                         return;
215                 }
216                 if (*last) {
217                         sc->sc_flags |= G_ELI_FLAG_RW_DETACH;
218                         sc->sc_geom->access = g_eli_access;
219                 } else {
220                         error = g_eli_destroy(sc, *force ? TRUE : FALSE);
221                         if (error != 0) {
222                                 gctl_error(req,
223                                     "Cannot destroy device %s (error=%d).",
224                                     sc->sc_name, error);
225                                 return;
226                         }
227                 }
228         }
229 }
230
231 static void
232 g_eli_ctl_onetime(struct gctl_req *req, struct g_class *mp)
233 {
234         struct g_eli_metadata md;
235         struct g_provider *pp;
236         const char *name;
237         intmax_t *keylen, *sectorsize;
238         u_char mkey[G_ELI_DATAIVKEYLEN];
239         int *nargs, *detach, *notrim;
240
241         g_topology_assert();
242         bzero(&md, sizeof(md));
243
244         nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
245         if (nargs == NULL) {
246                 gctl_error(req, "No '%s' argument.", "nargs");
247                 return;
248         }
249         if (*nargs != 1) {
250                 gctl_error(req, "Invalid number of arguments.");
251                 return;
252         }
253
254         strlcpy(md.md_magic, G_ELI_MAGIC, sizeof(md.md_magic));
255         md.md_version = G_ELI_VERSION;
256         md.md_flags |= G_ELI_FLAG_ONETIME;
257
258         detach = gctl_get_paraml(req, "detach", sizeof(*detach));
259         if (detach != NULL && *detach)
260                 md.md_flags |= G_ELI_FLAG_WO_DETACH;
261         notrim = gctl_get_paraml(req, "notrim", sizeof(*notrim));
262         if (notrim != NULL && *notrim)
263                 md.md_flags |= G_ELI_FLAG_NODELETE;
264
265         md.md_ealgo = CRYPTO_ALGORITHM_MIN - 1;
266         name = gctl_get_asciiparam(req, "aalgo");
267         if (name == NULL) {
268                 gctl_error(req, "No '%s' argument.", "aalgo");
269                 return;
270         }
271         if (*name != '\0') {
272                 md.md_aalgo = g_eli_str2aalgo(name);
273                 if (md.md_aalgo >= CRYPTO_ALGORITHM_MIN &&
274                     md.md_aalgo <= CRYPTO_ALGORITHM_MAX) {
275                         md.md_flags |= G_ELI_FLAG_AUTH;
276                 } else {
277                         /*
278                          * For backward compatibility, check if the -a option
279                          * was used to provide encryption algorithm.
280                          */
281                         md.md_ealgo = g_eli_str2ealgo(name);
282                         if (md.md_ealgo < CRYPTO_ALGORITHM_MIN ||
283                             md.md_ealgo > CRYPTO_ALGORITHM_MAX) {
284                                 gctl_error(req,
285                                     "Invalid authentication algorithm.");
286                                 return;
287                         } else {
288                                 gctl_error(req, "warning: The -e option, not "
289                                     "the -a option is now used to specify "
290                                     "encryption algorithm to use.");
291                         }
292                 }
293         }
294
295         if (md.md_ealgo < CRYPTO_ALGORITHM_MIN ||
296             md.md_ealgo > CRYPTO_ALGORITHM_MAX) {
297                 name = gctl_get_asciiparam(req, "ealgo");
298                 if (name == NULL) {
299                         gctl_error(req, "No '%s' argument.", "ealgo");
300                         return;
301                 }
302                 md.md_ealgo = g_eli_str2ealgo(name);
303                 if (md.md_ealgo < CRYPTO_ALGORITHM_MIN ||
304                     md.md_ealgo > CRYPTO_ALGORITHM_MAX) {
305                         gctl_error(req, "Invalid encryption algorithm.");
306                         return;
307                 }
308         }
309
310         keylen = gctl_get_paraml(req, "keylen", sizeof(*keylen));
311         if (keylen == NULL) {
312                 gctl_error(req, "No '%s' argument.", "keylen");
313                 return;
314         }
315         md.md_keylen = g_eli_keylen(md.md_ealgo, *keylen);
316         if (md.md_keylen == 0) {
317                 gctl_error(req, "Invalid '%s' argument.", "keylen");
318                 return;
319         }
320
321         /* Not important here. */
322         md.md_provsize = 0;
323         /* Not important here. */
324         bzero(md.md_salt, sizeof(md.md_salt));
325
326         md.md_keys = 0x01;
327         arc4rand(mkey, sizeof(mkey), 0);
328
329         /* Not important here. */
330         bzero(md.md_hash, sizeof(md.md_hash));
331
332         name = gctl_get_asciiparam(req, "arg0");
333         if (name == NULL) {
334                 gctl_error(req, "No 'arg%u' argument.", 0);
335                 return;
336         }
337         if (strncmp(name, "/dev/", strlen("/dev/")) == 0)
338                 name += strlen("/dev/");
339         pp = g_provider_by_name(name);
340         if (pp == NULL) {
341                 gctl_error(req, "Provider %s is invalid.", name);
342                 return;
343         }
344
345         sectorsize = gctl_get_paraml(req, "sectorsize", sizeof(*sectorsize));
346         if (sectorsize == NULL) {
347                 gctl_error(req, "No '%s' argument.", "sectorsize");
348                 return;
349         }
350         if (*sectorsize == 0)
351                 md.md_sectorsize = pp->sectorsize;
352         else {
353                 if (*sectorsize < 0 || (*sectorsize % pp->sectorsize) != 0) {
354                         gctl_error(req, "Invalid sector size.");
355                         return;
356                 }
357                 if (*sectorsize > PAGE_SIZE) {
358                         gctl_error(req, "warning: Using sectorsize bigger than "
359                             "the page size!");
360                 }
361                 md.md_sectorsize = *sectorsize;
362         }
363
364         g_eli_create(req, mp, pp, &md, mkey, -1);
365         bzero(mkey, sizeof(mkey));
366         bzero(&md, sizeof(md));
367 }
368
369 static void
370 g_eli_ctl_configure(struct gctl_req *req, struct g_class *mp)
371 {
372         struct g_eli_softc *sc;
373         struct g_eli_metadata md;
374         struct g_provider *pp;
375         struct g_consumer *cp;
376         char param[16];
377         const char *prov;
378         u_char *sector;
379         int *nargs, *boot, *noboot, *trim, *notrim;
380         int zero, error, changed;
381         u_int i;
382
383         g_topology_assert();
384
385         changed = 0;
386         zero = 0;
387
388         nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
389         if (nargs == NULL) {
390                 gctl_error(req, "No '%s' argument.", "nargs");
391                 return;
392         }
393         if (*nargs <= 0) {
394                 gctl_error(req, "Missing device(s).");
395                 return;
396         }
397
398         boot = gctl_get_paraml(req, "boot", sizeof(*boot));
399         if (boot == NULL)
400                 boot = &zero;
401         noboot = gctl_get_paraml(req, "noboot", sizeof(*noboot));
402         if (noboot == NULL)
403                 noboot = &zero;
404         if (*boot && *noboot) {
405                 gctl_error(req, "Options -b and -B are mutually exclusive.");
406                 return;
407         }
408         if (*boot || *noboot)
409                 changed = 1;
410
411         trim = gctl_get_paraml(req, "trim", sizeof(*trim));
412         if (trim == NULL)
413                 trim = &zero;
414         notrim = gctl_get_paraml(req, "notrim", sizeof(*notrim));
415         if (notrim == NULL)
416                 notrim = &zero;
417         if (*trim && *notrim) {
418                 gctl_error(req, "Options -t and -T are mutually exclusive.");
419                 return;
420         }
421         if (*trim || *notrim)
422                 changed = 1;
423
424         if (!changed) {
425                 gctl_error(req, "No option given.");
426                 return;
427         }
428
429         for (i = 0; i < *nargs; i++) {
430                 snprintf(param, sizeof(param), "arg%d", i);
431                 prov = gctl_get_asciiparam(req, param);
432                 if (prov == NULL) {
433                         gctl_error(req, "No 'arg%d' argument.", i);
434                         return;
435                 }
436                 sc = g_eli_find_device(mp, prov);
437                 if (sc == NULL) {
438                         /*
439                          * We ignore not attached providers, userland part will
440                          * take care of them.
441                          */
442                         G_ELI_DEBUG(1, "Skipping configuration of not attached "
443                             "provider %s.", prov);
444                         continue;
445                 }
446                 if (sc->sc_flags & G_ELI_FLAG_RO) {
447                         gctl_error(req, "Cannot change configuration of "
448                             "read-only provider %s.", prov);
449                         continue;
450                 }
451
452                 if (*boot && (sc->sc_flags & G_ELI_FLAG_BOOT)) {
453                         G_ELI_DEBUG(1, "BOOT flag already configured for %s.",
454                             prov);
455                         continue;
456                 } else if (*noboot && !(sc->sc_flags & G_ELI_FLAG_BOOT)) {
457                         G_ELI_DEBUG(1, "BOOT flag not configured for %s.",
458                             prov);
459                         continue;
460                 }
461
462                 if (*notrim && (sc->sc_flags & G_ELI_FLAG_NODELETE)) {
463                         G_ELI_DEBUG(1, "TRIM disable flag already configured for %s.",
464                             prov);
465                         continue;
466                 } else if (*trim && !(sc->sc_flags & G_ELI_FLAG_NODELETE)) {
467                         G_ELI_DEBUG(1, "TRIM disable flag not configured for %s.",
468                             prov);
469                         continue;
470                 }
471
472                 if (!(sc->sc_flags & G_ELI_FLAG_ONETIME)) {
473                         /*
474                          * ONETIME providers don't write metadata to
475                          * disk, so don't try reading it.  This means
476                          * we're bit-flipping uninitialized memory in md
477                          * below, but that's OK; we don't do anything
478                          * with it later.
479                          */
480                         cp = LIST_FIRST(&sc->sc_geom->consumer);
481                         pp = cp->provider;
482                         error = g_eli_read_metadata(mp, pp, &md);
483                         if (error != 0) {
484                             gctl_error(req,
485                                 "Cannot read metadata from %s (error=%d).",
486                                 prov, error);
487                             continue;
488                         }
489                 }
490
491                 if (*boot) {
492                         md.md_flags |= G_ELI_FLAG_BOOT;
493                         sc->sc_flags |= G_ELI_FLAG_BOOT;
494                 } else if (*noboot) {
495                         md.md_flags &= ~G_ELI_FLAG_BOOT;
496                         sc->sc_flags &= ~G_ELI_FLAG_BOOT;
497                 }
498
499                 if (*notrim) {
500                         md.md_flags |= G_ELI_FLAG_NODELETE;
501                         sc->sc_flags |= G_ELI_FLAG_NODELETE;
502                 } else if (*trim) {
503                         md.md_flags &= ~G_ELI_FLAG_NODELETE;
504                         sc->sc_flags &= ~G_ELI_FLAG_NODELETE;
505                 }
506
507                 if (sc->sc_flags & G_ELI_FLAG_ONETIME) {
508                         /* There's no metadata on disk so we are done here. */
509                         continue;
510                 }
511
512                 sector = malloc(pp->sectorsize, M_ELI, M_WAITOK | M_ZERO);
513                 eli_metadata_encode(&md, sector);
514                 error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector,
515                     pp->sectorsize);
516                 if (error != 0) {
517                         gctl_error(req,
518                             "Cannot store metadata on %s (error=%d).",
519                             prov, error);
520                 }
521                 bzero(&md, sizeof(md));
522                 bzero(sector, pp->sectorsize);
523                 free(sector, M_ELI);
524         }
525 }
526
527 static void
528 g_eli_ctl_setkey(struct gctl_req *req, struct g_class *mp)
529 {
530         struct g_eli_softc *sc;
531         struct g_eli_metadata md;
532         struct g_provider *pp;
533         struct g_consumer *cp;
534         const char *name;
535         u_char *key, *mkeydst, *sector;
536         intmax_t *valp;
537         int keysize, nkey, error;
538
539         g_topology_assert();
540
541         name = gctl_get_asciiparam(req, "arg0");
542         if (name == NULL) {
543                 gctl_error(req, "No 'arg%u' argument.", 0);
544                 return;
545         }
546         sc = g_eli_find_device(mp, name);
547         if (sc == NULL) {
548                 gctl_error(req, "Provider %s is invalid.", name);
549                 return;
550         }
551         if (sc->sc_flags & G_ELI_FLAG_RO) {
552                 gctl_error(req, "Cannot change keys for read-only provider.");
553                 return;
554         }
555         cp = LIST_FIRST(&sc->sc_geom->consumer);
556         pp = cp->provider;
557
558         error = g_eli_read_metadata(mp, pp, &md);
559         if (error != 0) {
560                 gctl_error(req, "Cannot read metadata from %s (error=%d).",
561                     name, error);
562                 return;
563         }
564
565         valp = gctl_get_paraml(req, "keyno", sizeof(*valp));
566         if (valp == NULL) {
567                 gctl_error(req, "No '%s' argument.", "keyno");
568                 return;
569         }
570         if (*valp != -1)
571                 nkey = *valp;
572         else
573                 nkey = sc->sc_nkey;
574         if (nkey < 0 || nkey >= G_ELI_MAXMKEYS) {
575                 gctl_error(req, "Invalid '%s' argument.", "keyno");
576                 return;
577         }
578
579         valp = gctl_get_paraml(req, "iterations", sizeof(*valp));
580         if (valp == NULL) {
581                 gctl_error(req, "No '%s' argument.", "iterations");
582                 return;
583         }
584         /* Check if iterations number should and can be changed. */
585         if (*valp != -1) {
586                 if (bitcount32(md.md_keys) != 1) {
587                         gctl_error(req, "To be able to use '-i' option, only "
588                             "one key can be defined.");
589                         return;
590                 }
591                 if (md.md_keys != (1 << nkey)) {
592                         gctl_error(req, "Only already defined key can be "
593                             "changed when '-i' option is used.");
594                         return;
595                 }
596                 md.md_iterations = *valp;
597         }
598
599         key = gctl_get_param(req, "key", &keysize);
600         if (key == NULL || keysize != G_ELI_USERKEYLEN) {
601                 bzero(&md, sizeof(md));
602                 gctl_error(req, "No '%s' argument.", "key");
603                 return;
604         }
605
606         mkeydst = md.md_mkeys + nkey * G_ELI_MKEYLEN;
607         md.md_keys |= (1 << nkey);
608
609         bcopy(sc->sc_mkey, mkeydst, sizeof(sc->sc_mkey));
610
611         /* Encrypt Master Key with the new key. */
612         error = g_eli_mkey_encrypt(md.md_ealgo, key, md.md_keylen, mkeydst);
613         bzero(key, keysize);
614         if (error != 0) {
615                 bzero(&md, sizeof(md));
616                 gctl_error(req, "Cannot encrypt Master Key (error=%d).", error);
617                 return;
618         }
619
620         sector = malloc(pp->sectorsize, M_ELI, M_WAITOK | M_ZERO);
621         /* Store metadata with fresh key. */
622         eli_metadata_encode(&md, sector);
623         bzero(&md, sizeof(md));
624         error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector,
625             pp->sectorsize);
626         bzero(sector, pp->sectorsize);
627         free(sector, M_ELI);
628         if (error != 0) {
629                 gctl_error(req, "Cannot store metadata on %s (error=%d).",
630                     pp->name, error);
631                 return;
632         }
633         G_ELI_DEBUG(1, "Key %u changed on %s.", nkey, pp->name);
634 }
635
636 static void
637 g_eli_ctl_delkey(struct gctl_req *req, struct g_class *mp)
638 {
639         struct g_eli_softc *sc;
640         struct g_eli_metadata md;
641         struct g_provider *pp;
642         struct g_consumer *cp;
643         const char *name;
644         u_char *mkeydst, *sector;
645         intmax_t *valp;
646         size_t keysize;
647         int error, nkey, *all, *force;
648         u_int i;
649
650         g_topology_assert();
651
652         nkey = 0;       /* fixes causeless gcc warning */
653
654         name = gctl_get_asciiparam(req, "arg0");
655         if (name == NULL) {
656                 gctl_error(req, "No 'arg%u' argument.", 0);
657                 return;
658         }
659         sc = g_eli_find_device(mp, name);
660         if (sc == NULL) {
661                 gctl_error(req, "Provider %s is invalid.", name);
662                 return;
663         }
664         if (sc->sc_flags & G_ELI_FLAG_RO) {
665                 gctl_error(req, "Cannot delete keys for read-only provider.");
666                 return;
667         }
668         cp = LIST_FIRST(&sc->sc_geom->consumer);
669         pp = cp->provider;
670
671         error = g_eli_read_metadata(mp, pp, &md);
672         if (error != 0) {
673                 gctl_error(req, "Cannot read metadata from %s (error=%d).",
674                     name, error);
675                 return;
676         }
677
678         all = gctl_get_paraml(req, "all", sizeof(*all));
679         if (all == NULL) {
680                 gctl_error(req, "No '%s' argument.", "all");
681                 return;
682         }
683
684         if (*all) {
685                 mkeydst = md.md_mkeys;
686                 keysize = sizeof(md.md_mkeys);
687         } else {
688                 force = gctl_get_paraml(req, "force", sizeof(*force));
689                 if (force == NULL) {
690                         gctl_error(req, "No '%s' argument.", "force");
691                         return;
692                 }
693
694                 valp = gctl_get_paraml(req, "keyno", sizeof(*valp));
695                 if (valp == NULL) {
696                         gctl_error(req, "No '%s' argument.", "keyno");
697                         return;
698                 }
699                 if (*valp != -1)
700                         nkey = *valp;
701                 else
702                         nkey = sc->sc_nkey;
703                 if (nkey < 0 || nkey >= G_ELI_MAXMKEYS) {
704                         gctl_error(req, "Invalid '%s' argument.", "keyno");
705                         return;
706                 }
707                 if (!(md.md_keys & (1 << nkey)) && !*force) {
708                         gctl_error(req, "Master Key %u is not set.", nkey);
709                         return;
710                 }
711                 md.md_keys &= ~(1 << nkey);
712                 if (md.md_keys == 0 && !*force) {
713                         gctl_error(req, "This is the last Master Key. Use '-f' "
714                             "flag if you really want to remove it.");
715                         return;
716                 }
717                 mkeydst = md.md_mkeys + nkey * G_ELI_MKEYLEN;
718                 keysize = G_ELI_MKEYLEN;
719         }
720
721         sector = malloc(pp->sectorsize, M_ELI, M_WAITOK | M_ZERO);
722         for (i = 0; i <= g_eli_overwrites; i++) {
723                 if (i == g_eli_overwrites)
724                         bzero(mkeydst, keysize);
725                 else
726                         arc4rand(mkeydst, keysize, 0);
727                 /* Store metadata with destroyed key. */
728                 eli_metadata_encode(&md, sector);
729                 error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector,
730                     pp->sectorsize);
731                 if (error != 0) {
732                         G_ELI_DEBUG(0, "Cannot store metadata on %s "
733                             "(error=%d).", pp->name, error);
734                 }
735                 /*
736                  * Flush write cache so we don't overwrite data N times in cache
737                  * and only once on disk.
738                  */
739                 (void)g_io_flush(cp);
740         }
741         bzero(&md, sizeof(md));
742         bzero(sector, pp->sectorsize);
743         free(sector, M_ELI);
744         if (*all)
745                 G_ELI_DEBUG(1, "All keys removed from %s.", pp->name);
746         else
747                 G_ELI_DEBUG(1, "Key %d removed from %s.", nkey, pp->name);
748 }
749
750 static void
751 g_eli_suspend_one(struct g_eli_softc *sc, struct gctl_req *req)
752 {
753         struct g_eli_worker *wr;
754
755         g_topology_assert();
756
757         KASSERT(sc != NULL, ("NULL sc"));
758
759         if (sc->sc_flags & G_ELI_FLAG_ONETIME) {
760                 gctl_error(req,
761                     "Device %s is using one-time key, suspend not supported.",
762                     sc->sc_name);
763                 return;
764         }
765
766         mtx_lock(&sc->sc_queue_mtx);
767         if (sc->sc_flags & G_ELI_FLAG_SUSPEND) {
768                 mtx_unlock(&sc->sc_queue_mtx);
769                 gctl_error(req, "Device %s already suspended.",
770                     sc->sc_name);
771                 return;
772         }
773         sc->sc_flags |= G_ELI_FLAG_SUSPEND;
774         wakeup(sc);
775         for (;;) {
776                 LIST_FOREACH(wr, &sc->sc_workers, w_next) {
777                         if (wr->w_active)
778                                 break;
779                 }
780                 if (wr == NULL)
781                         break;
782                 /* Not all threads suspended. */
783                 msleep(&sc->sc_workers, &sc->sc_queue_mtx, PRIBIO,
784                     "geli:suspend", 0);
785         }
786         /*
787          * Clear sensitive data on suspend, they will be recovered on resume.
788          */
789         bzero(sc->sc_mkey, sizeof(sc->sc_mkey));
790         g_eli_key_destroy(sc);
791         bzero(sc->sc_akey, sizeof(sc->sc_akey));
792         bzero(&sc->sc_akeyctx, sizeof(sc->sc_akeyctx));
793         bzero(sc->sc_ivkey, sizeof(sc->sc_ivkey));
794         bzero(&sc->sc_ivctx, sizeof(sc->sc_ivctx));
795         mtx_unlock(&sc->sc_queue_mtx);
796         G_ELI_DEBUG(0, "Device %s has been suspended.", sc->sc_name);
797 }
798
799 static void
800 g_eli_ctl_suspend(struct gctl_req *req, struct g_class *mp)
801 {
802         struct g_eli_softc *sc;
803         int *all, *nargs;
804
805         g_topology_assert();
806
807         nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
808         if (nargs == NULL) {
809                 gctl_error(req, "No '%s' argument.", "nargs");
810                 return;
811         }
812         all = gctl_get_paraml(req, "all", sizeof(*all));
813         if (all == NULL) {
814                 gctl_error(req, "No '%s' argument.", "all");
815                 return;
816         }
817         if (!*all && *nargs == 0) {
818                 gctl_error(req, "Too few arguments.");
819                 return;
820         }
821
822         if (*all) {
823                 struct g_geom *gp, *gp2;
824
825                 LIST_FOREACH_SAFE(gp, &mp->geom, geom, gp2) {
826                         sc = gp->softc;
827                         if (sc->sc_flags & G_ELI_FLAG_ONETIME) {
828                                 G_ELI_DEBUG(0,
829                                     "Device %s is using one-time key, suspend not supported, skipping.",
830                                     sc->sc_name);
831                                 continue;
832                         }
833                         g_eli_suspend_one(sc, req);
834                 }
835         } else {
836                 const char *prov;
837                 char param[16];
838                 int i;
839
840                 for (i = 0; i < *nargs; i++) {
841                         snprintf(param, sizeof(param), "arg%d", i);
842                         prov = gctl_get_asciiparam(req, param);
843                         if (prov == NULL) {
844                                 G_ELI_DEBUG(0, "No 'arg%d' argument.", i);
845                                 continue;
846                         }
847
848                         sc = g_eli_find_device(mp, prov);
849                         if (sc == NULL) {
850                                 G_ELI_DEBUG(0, "No such provider: %s.", prov);
851                                 continue;
852                         }
853                         g_eli_suspend_one(sc, req);
854                 }
855         }
856 }
857
858 static void
859 g_eli_ctl_resume(struct gctl_req *req, struct g_class *mp)
860 {
861         struct g_eli_metadata md;
862         struct g_eli_softc *sc;
863         struct g_provider *pp;
864         struct g_consumer *cp;
865         const char *name;
866         u_char *key, mkey[G_ELI_DATAIVKEYLEN];
867         int *nargs, keysize, error;
868         u_int nkey;
869
870         g_topology_assert();
871
872         nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
873         if (nargs == NULL) {
874                 gctl_error(req, "No '%s' argument.", "nargs");
875                 return;
876         }
877         if (*nargs != 1) {
878                 gctl_error(req, "Invalid number of arguments.");
879                 return;
880         }
881
882         name = gctl_get_asciiparam(req, "arg0");
883         if (name == NULL) {
884                 gctl_error(req, "No 'arg%u' argument.", 0);
885                 return;
886         }
887         sc = g_eli_find_device(mp, name);
888         if (sc == NULL) {
889                 gctl_error(req, "Provider %s is invalid.", name);
890                 return;
891         }
892         cp = LIST_FIRST(&sc->sc_geom->consumer);
893         pp = cp->provider;
894         error = g_eli_read_metadata(mp, pp, &md);
895         if (error != 0) {
896                 gctl_error(req, "Cannot read metadata from %s (error=%d).",
897                     name, error);
898                 return;
899         }
900         if (md.md_keys == 0x00) {
901                 bzero(&md, sizeof(md));
902                 gctl_error(req, "No valid keys on %s.", pp->name);
903                 return;
904         }
905
906         key = gctl_get_param(req, "key", &keysize);
907         if (key == NULL || keysize != G_ELI_USERKEYLEN) {
908                 bzero(&md, sizeof(md));
909                 gctl_error(req, "No '%s' argument.", "key");
910                 return;
911         }
912
913         error = g_eli_mkey_decrypt(&md, key, mkey, &nkey);
914         bzero(key, keysize);
915         if (error == -1) {
916                 bzero(&md, sizeof(md));
917                 gctl_error(req, "Wrong key for %s.", pp->name);
918                 return;
919         } else if (error > 0) {
920                 bzero(&md, sizeof(md));
921                 gctl_error(req, "Cannot decrypt Master Key for %s (error=%d).",
922                     pp->name, error);
923                 return;
924         }
925         G_ELI_DEBUG(1, "Using Master Key %u for %s.", nkey, pp->name);
926
927         mtx_lock(&sc->sc_queue_mtx);
928         if (!(sc->sc_flags & G_ELI_FLAG_SUSPEND))
929                 gctl_error(req, "Device %s is not suspended.", name);
930         else {
931                 /* Restore sc_mkey, sc_ekeys, sc_akey and sc_ivkey. */
932                 g_eli_mkey_propagate(sc, mkey);
933                 sc->sc_flags &= ~G_ELI_FLAG_SUSPEND;
934                 G_ELI_DEBUG(1, "Resumed %s.", pp->name);
935                 wakeup(sc);
936         }
937         mtx_unlock(&sc->sc_queue_mtx);
938         bzero(mkey, sizeof(mkey));
939         bzero(&md, sizeof(md));
940 }
941
942 static int
943 g_eli_kill_one(struct g_eli_softc *sc)
944 {
945         struct g_provider *pp;
946         struct g_consumer *cp;
947         int error = 0;
948
949         g_topology_assert();
950
951         if (sc == NULL)
952                 return (ENOENT);
953
954         pp = LIST_FIRST(&sc->sc_geom->provider);
955         g_error_provider(pp, ENXIO);
956
957         cp = LIST_FIRST(&sc->sc_geom->consumer);
958         pp = cp->provider;
959
960         if (sc->sc_flags & G_ELI_FLAG_RO) {
961                 G_ELI_DEBUG(0, "WARNING: Metadata won't be erased on read-only "
962                     "provider: %s.", pp->name);
963         } else {
964                 u_char *sector;
965                 u_int i;
966                 int err;
967
968                 sector = malloc(pp->sectorsize, M_ELI, M_WAITOK);
969                 for (i = 0; i <= g_eli_overwrites; i++) {
970                         if (i == g_eli_overwrites)
971                                 bzero(sector, pp->sectorsize);
972                         else
973                                 arc4rand(sector, pp->sectorsize, 0);
974                         err = g_write_data(cp, pp->mediasize - pp->sectorsize,
975                             sector, pp->sectorsize);
976                         if (err != 0) {
977                                 G_ELI_DEBUG(0, "Cannot erase metadata on %s "
978                                     "(error=%d).", pp->name, err);
979                                 if (error == 0)
980                                         error = err;
981                         }
982                         /*
983                          * Flush write cache so we don't overwrite data N times
984                          * in cache and only once on disk.
985                          */
986                         (void)g_io_flush(cp);
987                 }
988                 free(sector, M_ELI);
989         }
990         if (error == 0)
991                 G_ELI_DEBUG(0, "%s has been killed.", pp->name);
992         g_eli_destroy(sc, TRUE);
993         return (error);
994 }
995
996 static void
997 g_eli_ctl_kill(struct gctl_req *req, struct g_class *mp)
998 {
999         int *all, *nargs;
1000         int error;
1001
1002         g_topology_assert();
1003
1004         nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
1005         if (nargs == NULL) {
1006                 gctl_error(req, "No '%s' argument.", "nargs");
1007                 return;
1008         }
1009         all = gctl_get_paraml(req, "all", sizeof(*all));
1010         if (all == NULL) {
1011                 gctl_error(req, "No '%s' argument.", "all");
1012                 return;
1013         }
1014         if (!*all && *nargs == 0) {
1015                 gctl_error(req, "Too few arguments.");
1016                 return;
1017         }
1018
1019         if (*all) {
1020                 struct g_geom *gp, *gp2;
1021
1022                 LIST_FOREACH_SAFE(gp, &mp->geom, geom, gp2) {
1023                         error = g_eli_kill_one(gp->softc);
1024                         if (error != 0)
1025                                 gctl_error(req, "Not fully done.");
1026                 }
1027         } else {
1028                 struct g_eli_softc *sc;
1029                 const char *prov;
1030                 char param[16];
1031                 int i;
1032
1033                 for (i = 0; i < *nargs; i++) {
1034                         snprintf(param, sizeof(param), "arg%d", i);
1035                         prov = gctl_get_asciiparam(req, param);
1036                         if (prov == NULL) {
1037                                 G_ELI_DEBUG(0, "No 'arg%d' argument.", i);
1038                                 continue;
1039                         }
1040
1041                         sc = g_eli_find_device(mp, prov);
1042                         if (sc == NULL) {
1043                                 G_ELI_DEBUG(0, "No such provider: %s.", prov);
1044                                 continue;
1045                         }
1046                         error = g_eli_kill_one(sc);
1047                         if (error != 0)
1048                                 gctl_error(req, "Not fully done.");
1049                 }
1050         }
1051 }
1052
1053 void
1054 g_eli_config(struct gctl_req *req, struct g_class *mp, const char *verb)
1055 {
1056         uint32_t *version;
1057
1058         g_topology_assert();
1059
1060         version = gctl_get_paraml(req, "version", sizeof(*version));
1061         if (version == NULL) {
1062                 gctl_error(req, "No '%s' argument.", "version");
1063                 return;
1064         }
1065         while (*version != G_ELI_VERSION) {
1066                 if (G_ELI_VERSION == G_ELI_VERSION_06 &&
1067                     *version == G_ELI_VERSION_05) {
1068                         /* Compatible. */
1069                         break;
1070                 }
1071                 if (G_ELI_VERSION == G_ELI_VERSION_07 &&
1072                     (*version == G_ELI_VERSION_05 ||
1073                      *version == G_ELI_VERSION_06)) {
1074                         /* Compatible. */
1075                         break;
1076                 }
1077                 gctl_error(req, "Userland and kernel parts are out of sync.");
1078                 return;
1079         }
1080
1081         if (strcmp(verb, "attach") == 0)
1082                 g_eli_ctl_attach(req, mp);
1083         else if (strcmp(verb, "detach") == 0 || strcmp(verb, "stop") == 0)
1084                 g_eli_ctl_detach(req, mp);
1085         else if (strcmp(verb, "onetime") == 0)
1086                 g_eli_ctl_onetime(req, mp);
1087         else if (strcmp(verb, "configure") == 0)
1088                 g_eli_ctl_configure(req, mp);
1089         else if (strcmp(verb, "setkey") == 0)
1090                 g_eli_ctl_setkey(req, mp);
1091         else if (strcmp(verb, "delkey") == 0)
1092                 g_eli_ctl_delkey(req, mp);
1093         else if (strcmp(verb, "suspend") == 0)
1094                 g_eli_ctl_suspend(req, mp);
1095         else if (strcmp(verb, "resume") == 0)
1096                 g_eli_ctl_resume(req, mp);
1097         else if (strcmp(verb, "kill") == 0)
1098                 g_eli_ctl_kill(req, mp);
1099         else
1100                 gctl_error(req, "Unknown verb.");
1101 }