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