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