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