]> CyberLeo.Net >> Repos - FreeBSD/releng/8.2.git/blob - sys/geom/eli/g_eli_ctl.c
Copy stable/8 to releng/8.2 in preparation for FreeBSD-8.2 release.
[FreeBSD/releng/8.2.git] / sys / geom / eli / g_eli_ctl.c
1 /*-
2  * Copyright (c) 2005-2010 Pawel Jakub Dawidek <pjd@FreeBSD.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/kernel.h>
33 #include <sys/module.h>
34 #include <sys/lock.h>
35 #include <sys/mutex.h>
36 #include <sys/bio.h>
37 #include <sys/sysctl.h>
38 #include <sys/malloc.h>
39 #include <sys/kthread.h>
40 #include <sys/proc.h>
41 #include <sys/sched.h>
42 #include <sys/uio.h>
43
44 #include <vm/uma.h>
45
46 #include <geom/geom.h>
47 #include <geom/eli/g_eli.h>
48
49
50 MALLOC_DECLARE(M_ELI);
51
52
53 static void
54 g_eli_ctl_attach(struct gctl_req *req, struct g_class *mp)
55 {
56         struct g_eli_metadata md;
57         struct g_provider *pp;
58         const char *name;
59         u_char *key, mkey[G_ELI_DATAIVKEYLEN];
60         int *nargs, *detach, *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 (strcmp(name, "none") != 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, sizeof(sector));
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, sizeof(key));
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, sizeof(sector));
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, sizeof(sector));
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         bzero(sc->sc_ekeys,
743             sc->sc_nekeys * (sizeof(uint8_t *) + G_ELI_DATAKEYLEN));
744         free(sc->sc_ekeys, M_ELI);
745         sc->sc_ekeys = NULL;
746         bzero(sc->sc_akey, sizeof(sc->sc_akey));
747         bzero(&sc->sc_akeyctx, sizeof(sc->sc_akeyctx));
748         bzero(sc->sc_ivkey, sizeof(sc->sc_ivkey));
749         bzero(&sc->sc_ivctx, sizeof(sc->sc_ivctx));
750         mtx_unlock(&sc->sc_queue_mtx);
751         G_ELI_DEBUG(0, "Device %s has been suspended.", sc->sc_name);
752 }
753
754 static void
755 g_eli_ctl_suspend(struct gctl_req *req, struct g_class *mp)
756 {
757         struct g_eli_softc *sc;
758         int *all, *nargs;
759
760         g_topology_assert();
761
762         nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
763         if (nargs == NULL) {
764                 gctl_error(req, "No '%s' argument.", "nargs");
765                 return;
766         }
767         all = gctl_get_paraml(req, "all", sizeof(*all));
768         if (all == NULL) {
769                 gctl_error(req, "No '%s' argument.", "all");
770                 return;
771         }
772         if (!*all && *nargs == 0) {
773                 gctl_error(req, "Too few arguments.");
774                 return;
775         }
776
777         if (*all) {
778                 struct g_geom *gp, *gp2;
779
780                 LIST_FOREACH_SAFE(gp, &mp->geom, geom, gp2) {
781                         sc = gp->softc;
782                         if (sc->sc_flags & G_ELI_FLAG_ONETIME) {
783                                 G_ELI_DEBUG(0,
784                                     "Device %s is using one-time key, suspend not supported, skipping.",
785                                     sc->sc_name);
786                                 continue;
787                         }
788                         g_eli_suspend_one(sc, req);
789                 }
790         } else {
791                 const char *prov;
792                 char param[16];
793                 int i;
794
795                 for (i = 0; i < *nargs; i++) {
796                         snprintf(param, sizeof(param), "arg%d", i);
797                         prov = gctl_get_asciiparam(req, param);
798                         if (prov == NULL) {
799                                 G_ELI_DEBUG(0, "No 'arg%d' argument.", i);
800                                 continue;
801                         }
802
803                         sc = g_eli_find_device(mp, prov);
804                         if (sc == NULL) {
805                                 G_ELI_DEBUG(0, "No such provider: %s.", prov);
806                                 continue;
807                         }
808                         g_eli_suspend_one(sc, req);
809                 }
810         }
811 }
812
813 static void
814 g_eli_ctl_resume(struct gctl_req *req, struct g_class *mp)
815 {
816         struct g_eli_metadata md;
817         struct g_eli_softc *sc;
818         struct g_provider *pp;
819         struct g_consumer *cp;
820         const char *name;
821         u_char *key, mkey[G_ELI_DATAIVKEYLEN];
822         int *nargs, keysize, error;
823         u_int nkey;
824
825         g_topology_assert();
826
827         nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
828         if (nargs == NULL) {
829                 gctl_error(req, "No '%s' argument.", "nargs");
830                 return;
831         }
832         if (*nargs != 1) {
833                 gctl_error(req, "Invalid number of arguments.");
834                 return;
835         }
836
837         name = gctl_get_asciiparam(req, "arg0");
838         if (name == NULL) {
839                 gctl_error(req, "No 'arg%u' argument.", 0);
840                 return;
841         }
842         sc = g_eli_find_device(mp, name);
843         if (sc == NULL) {
844                 gctl_error(req, "Provider %s is invalid.", name);
845                 return;
846         }
847         cp = LIST_FIRST(&sc->sc_geom->consumer);
848         pp = cp->provider;
849         error = g_eli_read_metadata(mp, pp, &md);
850         if (error != 0) {
851                 gctl_error(req, "Cannot read metadata from %s (error=%d).",
852                     name, error);
853                 return;
854         }
855         if (md.md_keys == 0x00) {
856                 bzero(&md, sizeof(md));
857                 gctl_error(req, "No valid keys on %s.", pp->name);
858                 return;
859         }
860
861         key = gctl_get_param(req, "key", &keysize);
862         if (key == NULL || keysize != G_ELI_USERKEYLEN) {
863                 bzero(&md, sizeof(md));
864                 gctl_error(req, "No '%s' argument.", "key");
865                 return;
866         }
867
868         error = g_eli_mkey_decrypt(&md, key, mkey, &nkey);
869         bzero(key, keysize);
870         if (error == -1) {
871                 bzero(&md, sizeof(md));
872                 gctl_error(req, "Wrong key for %s.", pp->name);
873                 return;
874         } else if (error > 0) {
875                 bzero(&md, sizeof(md));
876                 gctl_error(req, "Cannot decrypt Master Key for %s (error=%d).",
877                     pp->name, error);
878                 return;
879         }
880         G_ELI_DEBUG(1, "Using Master Key %u for %s.", nkey, pp->name);
881
882         mtx_lock(&sc->sc_queue_mtx);
883         if (!(sc->sc_flags & G_ELI_FLAG_SUSPEND))
884                 gctl_error(req, "Device %s is not suspended.", name);
885         else {
886                 /* Restore sc_mkey, sc_ekeys, sc_akey and sc_ivkey. */
887                 g_eli_mkey_propagate(sc, mkey);
888                 sc->sc_flags &= ~G_ELI_FLAG_SUSPEND;
889                 G_ELI_DEBUG(1, "Resumed %s.", pp->name);
890                 wakeup(sc);
891         }
892         mtx_unlock(&sc->sc_queue_mtx);
893         bzero(mkey, sizeof(mkey));
894         bzero(&md, sizeof(md));
895 }
896
897 static int
898 g_eli_kill_one(struct g_eli_softc *sc)
899 {
900         struct g_provider *pp;
901         struct g_consumer *cp;
902         int error = 0;
903
904         g_topology_assert();
905
906         if (sc == NULL)
907                 return (ENOENT);
908
909         pp = LIST_FIRST(&sc->sc_geom->provider);
910         g_error_provider(pp, ENXIO);
911
912         cp = LIST_FIRST(&sc->sc_geom->consumer);
913         pp = cp->provider;
914
915         if (sc->sc_flags & G_ELI_FLAG_RO) {
916                 G_ELI_DEBUG(0, "WARNING: Metadata won't be erased on read-only "
917                     "provider: %s.", pp->name);
918         } else {
919                 u_char *sector;
920                 u_int i;
921                 int err;
922
923                 sector = malloc(pp->sectorsize, M_ELI, M_WAITOK);
924                 for (i = 0; i <= g_eli_overwrites; i++) {
925                         if (i == g_eli_overwrites)
926                                 bzero(sector, pp->sectorsize);
927                         else
928                                 arc4rand(sector, pp->sectorsize, 0);
929                         err = g_write_data(cp, pp->mediasize - pp->sectorsize,
930                             sector, pp->sectorsize);
931                         if (err != 0) {
932                                 G_ELI_DEBUG(0, "Cannot erase metadata on %s "
933                                     "(error=%d).", pp->name, err);
934                                 if (error == 0)
935                                         error = err;
936                         }
937                         /*
938                          * Flush write cache so we don't overwrite data N times
939                          * in cache and only once on disk.
940                          */
941                         (void)g_io_flush(cp);
942                 }
943                 free(sector, M_ELI);
944         }
945         if (error == 0)
946                 G_ELI_DEBUG(0, "%s has been killed.", pp->name);
947         g_eli_destroy(sc, TRUE);
948         return (error);
949 }
950
951 static void
952 g_eli_ctl_kill(struct gctl_req *req, struct g_class *mp)
953 {
954         int *all, *nargs;
955         int error;
956
957         g_topology_assert();
958
959         nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
960         if (nargs == NULL) {
961                 gctl_error(req, "No '%s' argument.", "nargs");
962                 return;
963         }
964         all = gctl_get_paraml(req, "all", sizeof(*all));
965         if (all == NULL) {
966                 gctl_error(req, "No '%s' argument.", "all");
967                 return;
968         }
969         if (!*all && *nargs == 0) {
970                 gctl_error(req, "Too few arguments.");
971                 return;
972         }
973
974         if (*all) {
975                 struct g_geom *gp, *gp2;
976
977                 LIST_FOREACH_SAFE(gp, &mp->geom, geom, gp2) {
978                         error = g_eli_kill_one(gp->softc);
979                         if (error != 0)
980                                 gctl_error(req, "Not fully done.");
981                 }
982         } else {
983                 struct g_eli_softc *sc;
984                 const char *prov;
985                 char param[16];
986                 int i;
987
988                 for (i = 0; i < *nargs; i++) {
989                         snprintf(param, sizeof(param), "arg%d", i);
990                         prov = gctl_get_asciiparam(req, param);
991                         if (prov == NULL) {
992                                 G_ELI_DEBUG(0, "No 'arg%d' argument.", i);
993                                 continue;
994                         }
995
996                         sc = g_eli_find_device(mp, prov);
997                         if (sc == NULL) {
998                                 G_ELI_DEBUG(0, "No such provider: %s.", prov);
999                                 continue;
1000                         }
1001                         error = g_eli_kill_one(sc);
1002                         if (error != 0)
1003                                 gctl_error(req, "Not fully done.");
1004                 }
1005         }
1006 }
1007
1008 void
1009 g_eli_config(struct gctl_req *req, struct g_class *mp, const char *verb)
1010 {
1011         uint32_t *version;
1012
1013         g_topology_assert();
1014
1015         version = gctl_get_paraml(req, "version", sizeof(*version));
1016         if (version == NULL) {
1017                 gctl_error(req, "No '%s' argument.", "version");
1018                 return;
1019         }
1020         if (*version != G_ELI_VERSION) {
1021                 gctl_error(req, "Userland and kernel parts are out of sync.");
1022                 return;
1023         }
1024
1025         if (strcmp(verb, "attach") == 0)
1026                 g_eli_ctl_attach(req, mp);
1027         else if (strcmp(verb, "detach") == 0 || strcmp(verb, "stop") == 0)
1028                 g_eli_ctl_detach(req, mp);
1029         else if (strcmp(verb, "onetime") == 0)
1030                 g_eli_ctl_onetime(req, mp);
1031         else if (strcmp(verb, "configure") == 0)
1032                 g_eli_ctl_configure(req, mp);
1033         else if (strcmp(verb, "setkey") == 0)
1034                 g_eli_ctl_setkey(req, mp);
1035         else if (strcmp(verb, "delkey") == 0)
1036                 g_eli_ctl_delkey(req, mp);
1037         else if (strcmp(verb, "suspend") == 0)
1038                 g_eli_ctl_suspend(req, mp);
1039         else if (strcmp(verb, "resume") == 0)
1040                 g_eli_ctl_resume(req, mp);
1041         else if (strcmp(verb, "kill") == 0)
1042                 g_eli_ctl_kill(req, mp);
1043         else
1044                 gctl_error(req, "Unknown verb.");
1045 }