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