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