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