xref: /openbsd-src/sbin/bioctl/bioctl.c (revision f2da64fbbbf1b03f09f390ab01267c93dfd77c4c)
1 /* $OpenBSD: bioctl.c,v 1.138 2016/09/19 17:46:52 jsing Exp $ */
2 
3 /*
4  * Copyright (c) 2004, 2005 Marco Peereboom
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 FOR
20  * 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 
30 #include <sys/param.h>	/* NODEV */
31 #include <sys/ioctl.h>
32 #include <sys/dkio.h>
33 #include <sys/stat.h>
34 #include <dev/softraidvar.h>
35 #include <dev/biovar.h>
36 
37 #include <errno.h>
38 #include <err.h>
39 #include <fcntl.h>
40 #include <util.h>
41 #include <ctype.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <unistd.h>
46 #include <limits.h>
47 #include <vis.h>
48 #include <readpassphrase.h>
49 
50 struct locator {
51 	int		channel;
52 	int		target;
53 	int		lun;
54 };
55 
56 struct timing {
57 	int		interval;
58 	int		start;
59 };
60 
61 void			usage(void);
62 const char 		*str2locator(const char *, struct locator *);
63 const char 		*str2patrol(const char *, struct timing *);
64 void			bio_status(struct bio_status *);
65 int			bio_parse_devlist(char *, dev_t *);
66 void			bio_kdf_derive(struct sr_crypto_kdfinfo *,
67 			    struct sr_crypto_pbkdf *, char *, int);
68 void			bio_kdf_generate(struct sr_crypto_kdfinfo *);
69 void			derive_key(u_int32_t, int, u_int8_t *, size_t,
70 			    u_int8_t *, size_t, char *, int);
71 
72 void			bio_inq(char *);
73 void			bio_alarm(char *);
74 int			bio_getvolbyname(char *);
75 void			bio_setstate(char *, int, char *);
76 void			bio_setblink(char *, char *, int);
77 void			bio_blink(char *, int, int);
78 void			bio_createraid(u_int16_t, char *, char *);
79 void			bio_deleteraid(char *);
80 void			bio_changepass(char *);
81 u_int32_t		bio_createflags(char *);
82 char			*bio_vis(char *);
83 void			bio_diskinq(char *);
84 void			bio_patrol(char *);
85 
86 int			devh = -1;
87 int			human;
88 int			verbose;
89 u_int32_t		cflags = 0;
90 int			rflag = 0;
91 char			*password;
92 
93 void			*bio_cookie;
94 
95 int rpp_flag = RPP_REQUIRE_TTY;
96 
97 int
98 main(int argc, char *argv[])
99 {
100 	struct bio_locate	bl;
101 	extern char		*optarg;
102 	u_int64_t		func = 0;
103 	char			*devicename = NULL;
104 	char			*realname = NULL, *al_arg = NULL;
105 	char			*bl_arg = NULL, *dev_list = NULL;
106 	char			*key_disk = NULL;
107 	const char		*errstr;
108 	int			ch, blink = 0, changepass = 0, diskinq = 0;
109 	int			ss_func = 0;
110 	u_int16_t		cr_level = 0;
111 	int			biodev = 0;
112 
113 	if (argc < 2)
114 		usage();
115 
116 	while ((ch = getopt(argc, argv, "a:b:C:c:dH:hik:l:O:Pp:qr:R:st:u:v")) !=
117 	    -1) {
118 		switch (ch) {
119 		case 'a': /* alarm */
120 			func |= BIOC_ALARM;
121 			al_arg = optarg;
122 			break;
123 		case 'b': /* blink */
124 			func |= BIOC_BLINK;
125 			blink = BIOC_SBBLINK;
126 			bl_arg = optarg;
127 			break;
128 		case 'C': /* creation flags */
129 			cflags = bio_createflags(optarg);
130 			break;
131 		case 'c': /* create */
132 			func |= BIOC_CREATERAID;
133 			if (isdigit((unsigned char)*optarg)) {
134 				cr_level = strtonum(optarg, 0, 10, &errstr);
135 				if (errstr != NULL)
136 					errx(1, "Invalid RAID level");
137 			} else
138 				cr_level = *optarg;
139 			break;
140 		case 'd':
141 			/* delete volume */
142 			func |= BIOC_DELETERAID;
143 			break;
144 		case 'u': /* unblink */
145 			func |= BIOC_BLINK;
146 			blink = BIOC_SBUNBLINK;
147 			bl_arg = optarg;
148 			break;
149 		case 'H': /* set hotspare */
150 			func |= BIOC_SETSTATE;
151 			ss_func = BIOC_SSHOTSPARE;
152 			al_arg = optarg;
153 			break;
154 		case 'h':
155 			human = 1;
156 			break;
157 		case 'i': /* inquiry */
158 			func |= BIOC_INQ;
159 			break;
160 		case 'k': /* Key disk. */
161 			key_disk = optarg;
162 			break;
163 		case 'l': /* device list */
164 			func |= BIOC_DEVLIST;
165 			dev_list = optarg;
166 			break;
167 		case 'P':
168 			/* Change passphrase. */
169 			changepass = 1;
170 			break;
171 		case 'p':
172 			password = optarg;
173 			break;
174 		case 'r':
175 			rflag = strtonum(optarg, 4, 1<<30, &errstr);
176 			if (errstr != NULL)
177 				errx(1, "number of KDF rounds is %s: %s",
178 				    errstr, optarg);
179 			break;
180 		case 'O':
181 			/* set a chunk to offline */
182 			func |= BIOC_SETSTATE;
183 			ss_func = BIOC_SSOFFLINE;
184 			al_arg = optarg;
185 			break;
186 		case 'R':
187 			/* rebuild to provided chunk/CTL */
188 			func |= BIOC_SETSTATE;
189 			ss_func = BIOC_SSREBUILD;
190 			al_arg = optarg;
191 			break;
192 		case 's':
193 			rpp_flag = RPP_STDIN;
194 			break;
195 		case 't': /* patrol */
196 			func |= BIOC_PATROL;
197 			al_arg = optarg;
198 			break;
199 		case 'v':
200 			verbose = 1;
201 			break;
202 		case 'q':
203 			diskinq = 1;
204 			break;
205 		default:
206 			usage();
207 			/* NOTREACHED */
208 		}
209 	}
210 	argc -= optind;
211 	argv += optind;
212 
213 	if (argc != 1 || (changepass && func != 0))
214 		usage();
215 
216 	if (func == 0)
217 		func |= BIOC_INQ;
218 
219 	devicename = argv[0];
220 	if (devicename == NULL)
221 		errx(1, "need device");
222 
223 	devh = opendev(devicename, O_RDWR, OPENDEV_PART, &realname);
224 	if (devh == -1) {
225 		devh = open("/dev/bio", O_RDWR);
226 		if (devh == -1)
227 			err(1, "Can't open %s", "/dev/bio");
228 
229 		bl.bl_name = devicename;
230 		if (ioctl(devh, BIOCLOCATE, &bl))
231 			errx(1, "Can't locate %s device via %s",
232 			    bl.bl_name, "/dev/bio");
233 
234 		bio_status(&bl.bl_bio.bio_status);
235 
236 		bio_cookie = bl.bl_bio.bio_cookie;
237 		biodev = 1;
238 		devicename = NULL;
239 	}
240 
241 	if (diskinq) {
242 		bio_diskinq(devicename);
243 	} else if (changepass && !biodev) {
244 		bio_changepass(devicename);
245 	} else if (func & BIOC_INQ) {
246 		bio_inq(devicename);
247 	} else if (func == BIOC_ALARM) {
248 		bio_alarm(al_arg);
249 	} else if (func == BIOC_BLINK) {
250 		bio_setblink(devicename, bl_arg, blink);
251 	} else if (func == BIOC_PATROL) {
252 		bio_patrol(al_arg);
253 	} else if (func == BIOC_SETSTATE) {
254 		bio_setstate(al_arg, ss_func, argv[0]);
255 	} else if (func == BIOC_DELETERAID && !biodev) {
256 		bio_deleteraid(devicename);
257 	} else if (func & BIOC_CREATERAID || func & BIOC_DEVLIST) {
258 		if (!(func & BIOC_CREATERAID))
259 			errx(1, "need -c parameter");
260 		if (!(func & BIOC_DEVLIST))
261 			errx(1, "need -l parameter");
262 		if (!biodev)
263 			errx(1, "must use bio device");
264 		bio_createraid(cr_level, dev_list, key_disk);
265 	}
266 
267 	return (0);
268 }
269 
270 void
271 usage(void)
272 {
273 	extern char		*__progname;
274 
275 	fprintf(stderr,
276 		"usage: %s [-hiqv] [-a alarm-function] "
277 		"[-b channel:target[.lun]]\n"
278 		"\t[-H channel:target[.lun]] "
279 		"[-R device | channel:target[.lun]]\n"
280 		"\t[-t patrol-function] "
281 		"[-u channel:target[.lun]] "
282 		"device\n"
283 		"       %s [-dhiPqsv] "
284 		"[-C flag[,flag,...]] [-c raidlevel] [-k keydisk]\n"
285 		"\t[-l special[,special,...]] "
286 		"[-O device | channel:target[.lun]]\n"
287 		"\t[-p passfile] [-R device | channel:target[.lun]]\n"
288 		"\t[-r rounds] "
289 		"device\n", __progname, __progname);
290 
291 	exit(1);
292 }
293 
294 const char *
295 str2locator(const char *string, struct locator *location)
296 {
297 	const char		*errstr;
298 	char			parse[80], *targ, *lun;
299 
300 	strlcpy(parse, string, sizeof parse);
301 	targ = strchr(parse, ':');
302 	if (targ == NULL)
303 		return ("target not specified");
304 	*targ++ = '\0';
305 
306 	lun = strchr(targ, '.');
307 	if (lun != NULL) {
308 		*lun++ = '\0';
309 		location->lun = strtonum(lun, 0, 256, &errstr);
310 		if (errstr)
311 			return (errstr);
312 	} else
313 		location->lun = 0;
314 
315 	location->target = strtonum(targ, 0, 256, &errstr);
316 	if (errstr)
317 		return (errstr);
318 	location->channel = strtonum(parse, 0, 256, &errstr);
319 	if (errstr)
320 		return (errstr);
321 	return (NULL);
322 }
323 
324 const char *
325 str2patrol(const char *string, struct timing *timing)
326 {
327 	const char		*errstr;
328 	char			parse[80], *interval = NULL, *start = NULL;
329 
330 	timing->interval = 0;
331 	timing->start = 0;
332 
333 	strlcpy(parse, string, sizeof parse);
334 
335 	interval = strchr(parse, '.');
336 	if (interval != NULL) {
337 		*interval++ = '\0';
338 		start = strchr(interval, '.');
339 		if (start != NULL)
340 			*start++ = '\0';
341 	}
342 	if (interval != NULL) {
343 		/* -1 == continuously */
344 		timing->interval = strtonum(interval, -1, INT_MAX, &errstr);
345 		if (errstr)
346 			return (errstr);
347 	}
348 	if (start != NULL) {
349 		timing->start = strtonum(start, 0, INT_MAX, &errstr);
350 		if (errstr)
351 			return (errstr);
352 	}
353 
354 	return (NULL);
355 }
356 
357 void
358 bio_status(struct bio_status *bs)
359 {
360 	extern char		*__progname;
361 	char			*prefix;
362 	int			i;
363 
364 	if (strlen(bs->bs_controller))
365 		prefix = bs->bs_controller;
366 	else
367 		prefix = __progname;
368 
369 	for (i = 0; i < bs->bs_msg_count; i++)
370 		printf("%s: %s\n", prefix, bs->bs_msgs[i].bm_msg);
371 
372 	if (bs->bs_status == BIO_STATUS_ERROR) {
373 		if (bs->bs_msg_count == 0)
374 			errx(1, "unknown error");
375 		else
376 			exit(1);
377 	}
378 }
379 
380 void
381 bio_inq(char *name)
382 {
383 	char 			*status, *cache;
384 	char			size[64], scsiname[16], volname[32];
385 	char			percent[20], seconds[20];
386 	int			i, d, volheader, hotspare, unused;
387 	char			encname[16], serial[32];
388 	struct bioc_inq		bi;
389 	struct bioc_vol		bv;
390 	struct bioc_disk	bd;
391 
392 	memset(&bi, 0, sizeof(bi));
393 
394 	bi.bi_bio.bio_cookie = bio_cookie;
395 
396 	if (ioctl(devh, BIOCINQ, &bi)) {
397 		if (errno == ENOTTY)
398 			bio_diskinq(name);
399 		else
400 			err(1, "BIOCINQ");
401 		return;
402 	}
403 
404 	bio_status(&bi.bi_bio.bio_status);
405 
406 	volheader = 0;
407 	for (i = 0; i < bi.bi_novol; i++) {
408 		memset(&bv, 0, sizeof(bv));
409 		bv.bv_bio.bio_cookie = bio_cookie;
410 		bv.bv_volid = i;
411 		bv.bv_percent = -1;
412 		bv.bv_seconds = 0;
413 
414 		if (ioctl(devh, BIOCVOL, &bv))
415 			err(1, "BIOCVOL");
416 
417 		bio_status(&bv.bv_bio.bio_status);
418 
419 		if (name && strcmp(name, bv.bv_dev) != 0)
420 			continue;
421 
422 		if (!volheader) {
423 			volheader = 1;
424 			printf("%-11s %-10s %14s %-8s\n",
425 			    "Volume", "Status", "Size", "Device");
426 		}
427 
428 		percent[0] = '\0';
429 		seconds[0] = '\0';
430 		if (bv.bv_percent != -1)
431 			snprintf(percent, sizeof percent,
432 			    " %d%% done", bv.bv_percent);
433 		if (bv.bv_seconds)
434 			snprintf(seconds, sizeof seconds,
435 			    " %u seconds", bv.bv_seconds);
436 		switch (bv.bv_status) {
437 		case BIOC_SVONLINE:
438 			status = BIOC_SVONLINE_S;
439 			break;
440 		case BIOC_SVOFFLINE:
441 			status = BIOC_SVOFFLINE_S;
442 			break;
443 		case BIOC_SVDEGRADED:
444 			status = BIOC_SVDEGRADED_S;
445 			break;
446 		case BIOC_SVBUILDING:
447 			status = BIOC_SVBUILDING_S;
448 			break;
449 		case BIOC_SVREBUILD:
450 			status = BIOC_SVREBUILD_S;
451 			break;
452 		case BIOC_SVSCRUB:
453 			status = BIOC_SVSCRUB_S;
454 			break;
455 		case BIOC_SVINVALID:
456 		default:
457 			status = BIOC_SVINVALID_S;
458 		}
459 		switch (bv.bv_cache) {
460 		case BIOC_CVWRITEBACK:
461 			cache = BIOC_CVWRITEBACK_S;
462 			break;
463 		case BIOC_CVWRITETHROUGH:
464 			cache = BIOC_CVWRITETHROUGH_S;
465 			break;
466 		case BIOC_CVUNKNOWN:
467 		default:
468 			cache = BIOC_CVUNKNOWN_S;
469 		}
470 
471 		snprintf(volname, sizeof volname, "%s %u",
472 		    bi.bi_dev, bv.bv_volid);
473 
474 		unused = 0;
475 		hotspare = 0;
476 		if (bv.bv_level == -1 && bv.bv_nodisk == 1)
477 			hotspare = 1;
478 		else if (bv.bv_level == -2 && bv.bv_nodisk == 1)
479 			unused = 1;
480 		else {
481 			if (human)
482 				fmt_scaled(bv.bv_size, size);
483 			else
484 				snprintf(size, sizeof size, "%14llu",
485 				    bv.bv_size);
486 			switch (bv.bv_level) {
487 			case 'C':
488 				printf("%11s %-10s %14s %-7s CRYPTO%s%s\n",
489 				    volname, status, size, bv.bv_dev,
490 				    percent, seconds);
491 				break;
492 			case 'c':
493 				printf("%11s %-10s %14s %-7s CONCAT%s%s\n",
494 				    volname, status, size, bv.bv_dev,
495 				    percent, seconds);
496 				break;
497 			default:
498 				printf("%11s %-10s %14s %-7s RAID%u%s%s %s\n",
499 				    volname, status, size, bv.bv_dev,
500 				    bv.bv_level, percent, seconds, cache);
501 				break;
502 			}
503 
504 		}
505 
506 		for (d = 0; d < bv.bv_nodisk; d++) {
507 			memset(&bd, 0, sizeof(bd));
508 			bd.bd_bio.bio_cookie = bio_cookie;
509 			bd.bd_diskid = d;
510 			bd.bd_volid = i;
511 			bd.bd_patrol.bdp_percent = -1;
512 			bd.bd_patrol.bdp_seconds = 0;
513 
514 			if (ioctl(devh, BIOCDISK, &bd))
515 				err(1, "BIOCDISK");
516 
517 			bio_status(&bd.bd_bio.bio_status);
518 
519 			switch (bd.bd_status) {
520 			case BIOC_SDONLINE:
521 				status = BIOC_SDONLINE_S;
522 				break;
523 			case BIOC_SDOFFLINE:
524 				status = BIOC_SDOFFLINE_S;
525 				break;
526 			case BIOC_SDFAILED:
527 				status = BIOC_SDFAILED_S;
528 				break;
529 			case BIOC_SDREBUILD:
530 				status = BIOC_SDREBUILD_S;
531 				break;
532 			case BIOC_SDHOTSPARE:
533 				status = BIOC_SDHOTSPARE_S;
534 				break;
535 			case BIOC_SDUNUSED:
536 				status = BIOC_SDUNUSED_S;
537 				break;
538 			case BIOC_SDSCRUB:
539 				status = BIOC_SDSCRUB_S;
540 				break;
541 			case BIOC_SDINVALID:
542 			default:
543 				status = BIOC_SDINVALID_S;
544 			}
545 
546 			if (hotspare || unused)
547 				;	/* use volname from parent volume */
548 			else
549 				snprintf(volname, sizeof volname, "    %3u",
550 				    bd.bd_diskid);
551 
552 			if (bv.bv_level == 'C' && bd.bd_size == 0)
553 				snprintf(size, sizeof size, "%14s", "key disk");
554 			else if (human)
555 				fmt_scaled(bd.bd_size, size);
556 			else
557 				snprintf(size, sizeof size, "%14llu",
558 				    bd.bd_size);
559 			snprintf(scsiname, sizeof scsiname,
560 			    "%u:%u.%u",
561 			    bd.bd_channel, bd.bd_target, bd.bd_lun);
562 			if (bd.bd_procdev[0])
563 				strlcpy(encname, bd.bd_procdev, sizeof encname);
564 			else
565 				strlcpy(encname, "noencl", sizeof encname);
566 			if (bd.bd_serial[0])
567 				strlcpy(serial, bd.bd_serial, sizeof serial);
568 			else
569 				strlcpy(serial, "unknown serial", sizeof serial);
570 
571 			percent[0] = '\0';
572 			seconds[0] = '\0';
573 			if (bd.bd_patrol.bdp_percent != -1)
574 				snprintf(percent, sizeof percent,
575 				    " patrol %d%% done", bd.bd_patrol.bdp_percent);
576 			if (bd.bd_patrol.bdp_seconds)
577 				snprintf(seconds, sizeof seconds,
578 				    " %u seconds", bd.bd_patrol.bdp_seconds);
579 
580 			printf("%11s %-10s %14s %-7s %-6s <%s>\n",
581 			    volname, status, size, scsiname, encname,
582 			    bd.bd_vendor);
583 			if (verbose)
584 				printf("%11s %-10s %14s %-7s %-6s '%s'%s%s\n",
585 				    "", "", "", "", "", serial, percent, seconds);
586 		}
587 	}
588 }
589 
590 void
591 bio_alarm(char *arg)
592 {
593 	struct bioc_alarm	ba;
594 
595 	memset(&ba, 0, sizeof(ba));
596 	ba.ba_bio.bio_cookie = bio_cookie;
597 
598 	switch (arg[0]) {
599 	case 'q': /* silence alarm */
600 		/* FALLTHROUGH */
601 	case 's':
602 		ba.ba_opcode = BIOC_SASILENCE;
603 		break;
604 
605 	case 'e': /* enable alarm */
606 		ba.ba_opcode = BIOC_SAENABLE;
607 		break;
608 
609 	case 'd': /* disable alarm */
610 		ba.ba_opcode = BIOC_SADISABLE;
611 		break;
612 
613 	case 't': /* test alarm */
614 		ba.ba_opcode = BIOC_SATEST;
615 		break;
616 
617 	case 'g': /* get alarm state */
618 		ba.ba_opcode = BIOC_GASTATUS;
619 		break;
620 
621 	default:
622 		errx(1, "invalid alarm function: %s", arg);
623 	}
624 
625 	if (ioctl(devh, BIOCALARM, &ba))
626 		err(1, "BIOCALARM");
627 
628 	bio_status(&ba.ba_bio.bio_status);
629 
630 	if (arg[0] == 'g')
631 		printf("alarm is currently %s\n",
632 		    ba.ba_status ? "enabled" : "disabled");
633 }
634 
635 int
636 bio_getvolbyname(char *name)
637 {
638 	int			id = -1, i;
639 	struct bioc_inq		bi;
640 	struct bioc_vol		bv;
641 
642 	memset(&bi, 0, sizeof(bi));
643 	bi.bi_bio.bio_cookie = bio_cookie;
644 	if (ioctl(devh, BIOCINQ, &bi))
645 		err(1, "BIOCINQ");
646 
647 	bio_status(&bi.bi_bio.bio_status);
648 
649 	for (i = 0; i < bi.bi_novol; i++) {
650 		memset(&bv, 0, sizeof(bv));
651 		bv.bv_bio.bio_cookie = bio_cookie;
652 		bv.bv_volid = i;
653 		if (ioctl(devh, BIOCVOL, &bv))
654 			err(1, "BIOCVOL");
655 
656 		bio_status(&bv.bv_bio.bio_status);
657 
658 		if (name && strcmp(name, bv.bv_dev) != 0)
659 			continue;
660 		id = i;
661 		break;
662 	}
663 
664 	return (id);
665 }
666 
667 void
668 bio_setstate(char *arg, int status, char *devicename)
669 {
670 	struct bioc_setstate	bs;
671 	struct locator		location;
672 	struct stat		sb;
673 	const char		*errstr;
674 
675 	memset(&bs, 0, sizeof(bs));
676 	if (stat(arg, &sb) == -1) {
677 		/* use CTL */
678 		errstr = str2locator(arg, &location);
679 		if (errstr)
680 			errx(1, "Target %s: %s", arg, errstr);
681 		bs.bs_channel = location.channel;
682 		bs.bs_target = location.target;
683 		bs.bs_lun = location.lun;
684 	} else {
685 		/* use other id */
686 		bs.bs_other_id = sb.st_rdev;
687 		bs.bs_other_id_type = BIOC_SSOTHER_DEVT;
688 	}
689 
690 	bs.bs_bio.bio_cookie = bio_cookie;
691 	bs.bs_status = status;
692 
693 	if (status != BIOC_SSHOTSPARE) {
694 		/* make sure user supplied a sd device */
695 		bs.bs_volid = bio_getvolbyname(devicename);
696 		if (bs.bs_volid == -1)
697 			errx(1, "invalid device %s", devicename);
698 	}
699 
700 	if (ioctl(devh, BIOCSETSTATE, &bs))
701 		err(1, "BIOCSETSTATE");
702 
703 	bio_status(&bs.bs_bio.bio_status);
704 }
705 
706 void
707 bio_setblink(char *name, char *arg, int blink)
708 {
709 	struct locator		location;
710 	struct bioc_blink	bb;
711 	struct bioc_inq		bi;
712 	struct bioc_vol		bv;
713 	struct bioc_disk	bd;
714 	const char		*errstr;
715 	int			v, d, rv;
716 
717 	errstr = str2locator(arg, &location);
718 	if (errstr)
719 		errx(1, "Target %s: %s", arg, errstr);
720 
721 	/* try setting blink on the device directly */
722 	memset(&bb, 0, sizeof(bb));
723 	bb.bb_bio.bio_cookie = bio_cookie;
724 	bb.bb_status = blink;
725 	bb.bb_target = location.target;
726 	bb.bb_channel = location.channel;
727 	rv = ioctl(devh, BIOCBLINK, &bb);
728 
729 	if (rv == 0 && bb.bb_bio.bio_status.bs_status == BIO_STATUS_UNKNOWN)
730 		return;
731 
732 	if (rv == 0 && bb.bb_bio.bio_status.bs_status == BIO_STATUS_SUCCESS) {
733 		bio_status(&bb.bb_bio.bio_status);
734 		return;
735 	}
736 
737 	/* if the blink didn't work, try to find something that will */
738 
739 	memset(&bi, 0, sizeof(bi));
740 	bi.bi_bio.bio_cookie = bio_cookie;
741 	if (ioctl(devh, BIOCINQ, &bi))
742 		err(1, "BIOCINQ");
743 
744 	bio_status(&bi.bi_bio.bio_status);
745 
746 	for (v = 0; v < bi.bi_novol; v++) {
747 		memset(&bv, 0, sizeof(bv));
748 		bv.bv_bio.bio_cookie = bio_cookie;
749 		bv.bv_volid = v;
750 		if (ioctl(devh, BIOCVOL, &bv))
751 			err(1, "BIOCVOL");
752 
753 		bio_status(&bv.bv_bio.bio_status);
754 
755 		if (name && strcmp(name, bv.bv_dev) != 0)
756 			continue;
757 
758 		for (d = 0; d < bv.bv_nodisk; d++) {
759 			memset(&bd, 0, sizeof(bd));
760 			bd.bd_bio.bio_cookie = bio_cookie;
761 			bd.bd_volid = v;
762 			bd.bd_diskid = d;
763 
764 			if (ioctl(devh, BIOCDISK, &bd))
765 				err(1, "BIOCDISK");
766 
767 			bio_status(&bd.bd_bio.bio_status);
768 
769 			if (bd.bd_channel == location.channel &&
770 			    bd.bd_target == location.target &&
771 			    bd.bd_lun == location.lun) {
772 				if (bd.bd_procdev[0] != '\0')
773 					bio_blink(bd.bd_procdev,
774 					    location.target, blink);
775 				else
776 					warnx("Disk %s is not in an enclosure",
777 					    arg);
778 				return;
779 			}
780 		}
781 	}
782 
783 	warnx("Disk %s does not exist", arg);
784 
785 	return;
786 }
787 
788 void
789 bio_blink(char *enclosure, int target, int blinktype)
790 {
791 	int			bioh;
792 	struct bio_locate	bl;
793 	struct bioc_blink	blink;
794 
795 	bioh = open("/dev/bio", O_RDWR);
796 	if (bioh == -1)
797 		err(1, "Can't open %s", "/dev/bio");
798 
799 	memset(&bl, 0, sizeof(bl));
800 	bl.bl_name = enclosure;
801 	if (ioctl(bioh, BIOCLOCATE, &bl))
802 		errx(1, "Can't locate %s device via %s", enclosure, "/dev/bio");
803 
804 	bio_status(&bl.bl_bio.bio_status);
805 
806 	memset(&blink, 0, sizeof(blink));
807 	blink.bb_bio.bio_cookie = bio_cookie;
808 	blink.bb_status = blinktype;
809 	blink.bb_target = target;
810 
811 	if (ioctl(bioh, BIOCBLINK, &blink))
812 		err(1, "BIOCBLINK");
813 
814 	bio_status(&blink.bb_bio.bio_status);
815 
816 	close(bioh);
817 }
818 
819 void
820 bio_createraid(u_int16_t level, char *dev_list, char *key_disk)
821 {
822 	struct bioc_createraid	create;
823 	struct sr_crypto_kdfinfo kdfinfo;
824 	struct sr_crypto_pbkdf	kdfhint;
825 	struct stat		sb;
826 	int			rv, no_dev, fd;
827 	dev_t			*dt;
828 	u_int16_t		min_disks = 0;
829 
830 	if (!dev_list)
831 		errx(1, "no devices specified");
832 
833 	dt = calloc(1, BIOC_CRMAXLEN);
834 	if (!dt)
835 		err(1, "not enough memory for dev_t list");
836 
837 	no_dev = bio_parse_devlist(dev_list, dt);
838 
839 	switch (level) {
840 	case 0:
841 		min_disks = 2;
842 		break;
843 	case 1:
844 		min_disks = 2;
845 		break;
846 	case 5:
847 		min_disks = 3;
848 		break;
849 	case 'C':
850 		min_disks = 1;
851 		break;
852 	case 'c':
853 		min_disks = 2;
854 		break;
855 	default:
856 		errx(1, "unsupported raid level");
857 	}
858 
859 	if (no_dev < min_disks)
860 		errx(1, "not enough disks");
861 
862 	/* for crypto raid we only allow one single chunk */
863 	if (level == 'C' && no_dev != min_disks)
864 		errx(1, "not exactly one partition");
865 
866 	memset(&create, 0, sizeof(create));
867 	create.bc_bio.bio_cookie = bio_cookie;
868 	create.bc_level = level;
869 	create.bc_dev_list_len = no_dev * sizeof(dev_t);
870 	create.bc_dev_list = dt;
871 	create.bc_flags = BIOC_SCDEVT | cflags;
872 	create.bc_key_disk = NODEV;
873 
874 	if (level == 'C' && key_disk == NULL) {
875 
876 		memset(&kdfinfo, 0, sizeof(kdfinfo));
877 		memset(&kdfhint, 0, sizeof(kdfhint));
878 
879 		create.bc_flags |= BIOC_SCNOAUTOASSEMBLE;
880 
881 		create.bc_opaque = &kdfhint;
882 		create.bc_opaque_size = sizeof(kdfhint);
883 		create.bc_opaque_flags = BIOC_SOOUT;
884 
885 		/* try to get KDF hint */
886 		if (ioctl(devh, BIOCCREATERAID, &create))
887 			err(1, "ioctl");
888 
889 		bio_status(&create.bc_bio.bio_status);
890 
891 		if (create.bc_opaque_status == BIOC_SOINOUT_OK) {
892 			bio_kdf_derive(&kdfinfo, &kdfhint, "Passphrase: ", 0);
893 			memset(&kdfhint, 0, sizeof(kdfhint));
894 		} else {
895 			bio_kdf_generate(&kdfinfo);
896 		}
897 
898 		create.bc_opaque = &kdfinfo;
899 		create.bc_opaque_size = sizeof(kdfinfo);
900 		create.bc_opaque_flags = BIOC_SOIN;
901 
902 	} else if (level == 'C' && key_disk != NULL) {
903 
904 		/* Get device number for key disk. */
905 		fd = opendev(key_disk, O_RDONLY, OPENDEV_BLCK, NULL);
906 		if (fd == -1)
907 			err(1, "could not open %s", key_disk);
908 		if (fstat(fd, &sb) == -1) {
909 			int saved_errno = errno;
910 			close(fd);
911 			errc(1, saved_errno, "could not stat %s", key_disk);
912 		}
913 		close(fd);
914 		create.bc_key_disk = sb.st_rdev;
915 
916 		memset(&kdfinfo, 0, sizeof(kdfinfo));
917 
918 		kdfinfo.genkdf.len = sizeof(kdfinfo.genkdf);
919 		kdfinfo.genkdf.type = SR_CRYPTOKDFT_KEYDISK;
920 		kdfinfo.len = sizeof(kdfinfo);
921 		kdfinfo.flags = SR_CRYPTOKDF_HINT;
922 
923 		create.bc_opaque = &kdfinfo;
924 		create.bc_opaque_size = sizeof(kdfinfo);
925 		create.bc_opaque_flags = BIOC_SOIN;
926 
927 	}
928 
929 	rv = ioctl(devh, BIOCCREATERAID, &create);
930 	explicit_bzero(&kdfinfo, sizeof(kdfinfo));
931 	if (rv == -1)
932 		err(1, "BIOCCREATERAID");
933 
934 	bio_status(&create.bc_bio.bio_status);
935 
936 	free(dt);
937 }
938 
939 void
940 bio_kdf_derive(struct sr_crypto_kdfinfo *kdfinfo, struct sr_crypto_pbkdf
941     *kdfhint, char* prompt, int verify)
942 {
943 	if (!kdfinfo)
944 		errx(1, "invalid KDF info");
945 	if (!kdfhint)
946 		errx(1, "invalid KDF hint");
947 
948 	if (kdfhint->generic.len != sizeof(*kdfhint))
949 		errx(1, "KDF hint has invalid size");
950 
951 	kdfinfo->flags = SR_CRYPTOKDF_KEY;
952 	kdfinfo->len = sizeof(*kdfinfo);
953 
954 	derive_key(kdfhint->generic.type, kdfhint->rounds,
955 	    kdfinfo->maskkey, sizeof(kdfinfo->maskkey),
956 	    kdfhint->salt, sizeof(kdfhint->salt),
957 	    prompt, verify);
958 }
959 
960 void
961 bio_kdf_generate(struct sr_crypto_kdfinfo *kdfinfo)
962 {
963 	if (!kdfinfo)
964 		errx(1, "invalid KDF info");
965 
966 	kdfinfo->pbkdf.generic.len = sizeof(kdfinfo->pbkdf);
967 	kdfinfo->pbkdf.generic.type = SR_CRYPTOKDFT_BCRYPT_PBKDF;
968 	kdfinfo->pbkdf.rounds = rflag ? rflag : 16;
969 
970 	kdfinfo->flags = SR_CRYPTOKDF_KEY | SR_CRYPTOKDF_HINT;
971 	kdfinfo->len = sizeof(*kdfinfo);
972 
973 	/* generate salt */
974 	arc4random_buf(kdfinfo->pbkdf.salt, sizeof(kdfinfo->pbkdf.salt));
975 
976 	derive_key(kdfinfo->pbkdf.generic.type, kdfinfo->pbkdf.rounds,
977 	    kdfinfo->maskkey, sizeof(kdfinfo->maskkey),
978 	    kdfinfo->pbkdf.salt, sizeof(kdfinfo->pbkdf.salt),
979 	    "New passphrase: ", 1);
980 }
981 
982 int
983 bio_parse_devlist(char *lst, dev_t *dt)
984 {
985 	char			*s, *e;
986 	u_int32_t		sz = 0;
987 	int			no_dev = 0, i, x;
988 	struct stat		sb;
989 	char			dev[PATH_MAX];
990 	int			fd;
991 
992 	if (!lst)
993 		errx(1, "invalid device list");
994 
995 	s = e = lst;
996 	/* make sure we have a valid device list like /dev/sdNa,/dev/sdNNa */
997 	while (*e != '\0') {
998 		if (*e == ',')
999 			s = e + 1;
1000 		else if (*(e + 1) == '\0' || *(e + 1) == ',') {
1001 			/* got one */
1002 			sz = e - s + 1;
1003 			strlcpy(dev, s, sz + 1);
1004 			fd = opendev(dev, O_RDONLY, OPENDEV_BLCK, NULL);
1005 			if (fd == -1)
1006 				err(1, "could not open %s", dev);
1007 			if (fstat(fd, &sb) == -1) {
1008 				int saved_errno = errno;
1009 				close(fd);
1010 				errc(1, saved_errno, "could not stat %s", dev);
1011 			}
1012 			close(fd);
1013 			dt[no_dev] = sb.st_rdev;
1014 			no_dev++;
1015 			if (no_dev > (int)(BIOC_CRMAXLEN / sizeof(dev_t)))
1016 				errx(1, "too many devices on device list");
1017 		}
1018 		e++;
1019 	}
1020 
1021 	for (i = 0; i < no_dev; i++)
1022 		for (x = 0; x < no_dev; x++)
1023 			if (dt[i] == dt[x] && x != i)
1024 				errx(1, "duplicate device in list");
1025 
1026 	return (no_dev);
1027 }
1028 
1029 u_int32_t
1030 bio_createflags(char *lst)
1031 {
1032 	char			*s, *e, fs[32];
1033 	u_int32_t		sz = 0;
1034 	u_int32_t		flags = 0;
1035 
1036 	if (!lst)
1037 		errx(1, "invalid flags list");
1038 
1039 	s = e = lst;
1040 	/* make sure we have a valid flags list like force,noassemeble */
1041 	while (*e != '\0') {
1042 		if (*e == ',')
1043 			s = e + 1;
1044 		else if (*(e + 1) == '\0' || *(e + 1) == ',') {
1045 			/* got one */
1046 			sz = e - s + 1;
1047 			switch (s[0]) {
1048 			case 'f':
1049 				flags |= BIOC_SCFORCE;
1050 				break;
1051 			case 'n':
1052 				flags |= BIOC_SCNOAUTOASSEMBLE;
1053 				break;
1054 			default:
1055 				strlcpy(fs, s, sz + 1);
1056 				errx(1, "invalid flag %s", fs);
1057 			}
1058 		}
1059 		e++;
1060 	}
1061 
1062 	return (flags);
1063 }
1064 
1065 void
1066 bio_deleteraid(char *dev)
1067 {
1068 	struct bioc_deleteraid	bd;
1069 	memset(&bd, 0, sizeof(bd));
1070 
1071 	bd.bd_bio.bio_cookie = bio_cookie;
1072 	/* XXX make this a dev_t instead of a string */
1073 	strlcpy(bd.bd_dev, dev, sizeof bd.bd_dev);
1074 	if (ioctl(devh, BIOCDELETERAID, &bd))
1075 		err(1, "BIOCDELETERAID");
1076 
1077 	bio_status(&bd.bd_bio.bio_status);
1078 }
1079 
1080 void
1081 bio_changepass(char *dev)
1082 {
1083 	struct bioc_discipline bd;
1084 	struct sr_crypto_kdfpair kdfpair;
1085 	struct sr_crypto_kdfinfo kdfinfo1, kdfinfo2;
1086 	struct sr_crypto_pbkdf kdfhint;
1087 	int rv;
1088 
1089 	memset(&bd, 0, sizeof(bd));
1090 	memset(&kdfhint, 0, sizeof(kdfhint));
1091 	memset(&kdfinfo1, 0, sizeof(kdfinfo1));
1092 	memset(&kdfinfo2, 0, sizeof(kdfinfo2));
1093 
1094 	/* XXX use dev_t instead of string. */
1095 	strlcpy(bd.bd_dev, dev, sizeof(bd.bd_dev));
1096 	bd.bd_cmd = SR_IOCTL_GET_KDFHINT;
1097 	bd.bd_size = sizeof(kdfhint);
1098 	bd.bd_data = &kdfhint;
1099 
1100 	if (ioctl(devh, BIOCDISCIPLINE, &bd))
1101 		err(1, "BIOCDISCIPLINE");
1102 
1103 	bio_status(&bd.bd_bio.bio_status);
1104 
1105 	/* Current passphrase. */
1106 	bio_kdf_derive(&kdfinfo1, &kdfhint, "Old passphrase: ", 0);
1107 
1108 	/*
1109 	 * Unless otherwise specified, keep the previous number of rounds as
1110 	 * long as we're using the same KDF.
1111 	 */
1112 	if (kdfhint.generic.type == SR_CRYPTOKDFT_BCRYPT_PBKDF && !rflag)
1113 		rflag = kdfhint.rounds;
1114 
1115 	/* New passphrase. */
1116 	bio_kdf_generate(&kdfinfo2);
1117 
1118 	kdfpair.kdfinfo1 = &kdfinfo1;
1119 	kdfpair.kdfsize1 = sizeof(kdfinfo1);
1120 	kdfpair.kdfinfo2 = &kdfinfo2;
1121 	kdfpair.kdfsize2 = sizeof(kdfinfo2);
1122 
1123 	bd.bd_cmd = SR_IOCTL_CHANGE_PASSPHRASE;
1124 	bd.bd_size = sizeof(kdfpair);
1125 	bd.bd_data = &kdfpair;
1126 
1127 	rv = ioctl(devh, BIOCDISCIPLINE, &bd);
1128 
1129 	memset(&kdfhint, 0, sizeof(kdfhint));
1130 	explicit_bzero(&kdfinfo1, sizeof(kdfinfo1));
1131 	explicit_bzero(&kdfinfo2, sizeof(kdfinfo2));
1132 
1133 	if (rv)
1134 		err(1, "BIOCDISCIPLINE");
1135 
1136 	bio_status(&bd.bd_bio.bio_status);
1137 }
1138 
1139 #define BIOCTL_VIS_NBUF		4
1140 #define BIOCTL_VIS_BUFLEN	80
1141 
1142 char *
1143 bio_vis(char *s)
1144 {
1145 	static char	 rbuf[BIOCTL_VIS_NBUF][BIOCTL_VIS_BUFLEN];
1146 	static uint	 idx = 0;
1147 	char		*buf;
1148 
1149 	buf = rbuf[idx++];
1150 	if (idx == BIOCTL_VIS_NBUF)
1151 		idx = 0;
1152 
1153 	strnvis(buf, s, BIOCTL_VIS_BUFLEN, VIS_NL|VIS_CSTYLE);
1154 	return (buf);
1155 }
1156 
1157 void
1158 bio_diskinq(char *sd_dev)
1159 {
1160 	struct dk_inquiry	di;
1161 
1162 	if (ioctl(devh, DIOCINQ, &di) == -1)
1163 		err(1, "DIOCINQ");
1164 
1165 	printf("%s: <%s, %s, %s>, serial %s\n", sd_dev, bio_vis(di.vendor),
1166 	    bio_vis(di.product), bio_vis(di.revision), bio_vis(di.serial));
1167 }
1168 
1169 void
1170 bio_patrol(char *arg)
1171 {
1172 	struct bioc_patrol	bp;
1173 	struct timing		timing;
1174 	const char		*errstr;
1175 
1176 	memset(&bp, 0, sizeof(bp));
1177 	bp.bp_bio.bio_cookie = bio_cookie;
1178 
1179 	switch (arg[0]) {
1180 	case 'a':
1181 		bp.bp_opcode = BIOC_SPAUTO;
1182 		break;
1183 
1184 	case 'm':
1185 		bp.bp_opcode = BIOC_SPMANUAL;
1186 		break;
1187 
1188 	case 'd':
1189 		bp.bp_opcode = BIOC_SPDISABLE;
1190 		break;
1191 
1192 	case 'g': /* get patrol state */
1193 		bp.bp_opcode = BIOC_GPSTATUS;
1194 		break;
1195 
1196 	case 's': /* start/stop patrol */
1197 		if (strncmp("sta", arg, 3) == 0)
1198 			bp.bp_opcode = BIOC_SPSTART;
1199 		else
1200 			bp.bp_opcode = BIOC_SPSTOP;
1201 		break;
1202 
1203 	default:
1204 		errx(1, "invalid patrol function: %s", arg);
1205 	}
1206 
1207 	switch (arg[0]) {
1208 	case 'a':
1209 		errstr = str2patrol(arg, &timing);
1210 		if (errstr)
1211 			errx(1, "Patrol %s: %s", arg, errstr);
1212 		bp.bp_autoival = timing.interval;
1213 		bp.bp_autonext = timing.start;
1214 		break;
1215 	}
1216 
1217 	if (ioctl(devh, BIOCPATROL, &bp))
1218 		err(1, "BIOCPATROL");
1219 
1220 	bio_status(&bp.bp_bio.bio_status);
1221 
1222 	if (arg[0] == 'g') {
1223 		const char *mode, *status;
1224 		char interval[40];
1225 
1226 		interval[0] = '\0';
1227 
1228 		switch (bp.bp_mode) {
1229 		case BIOC_SPMAUTO:
1230 			mode = "auto";
1231 			snprintf(interval, sizeof interval,
1232 			    " interval=%d next=%d", bp.bp_autoival,
1233 			    bp.bp_autonext - bp.bp_autonow);
1234 			break;
1235 		case BIOC_SPMMANUAL:
1236 			mode = "manual";
1237 			break;
1238 		case BIOC_SPMDISABLED:
1239 			mode = "disabled";
1240 			break;
1241 		default:
1242 			mode = "unknown";
1243 			break;
1244 		}
1245 		switch (bp.bp_status) {
1246 		case BIOC_SPSSTOPPED:
1247 			status = "stopped";
1248 			break;
1249 		case BIOC_SPSREADY:
1250 			status = "ready";
1251 			break;
1252 		case BIOC_SPSACTIVE:
1253 			status = "active";
1254 			break;
1255 		case BIOC_SPSABORTED:
1256 			status = "aborted";
1257 			break;
1258 		default:
1259 			status = "unknown";
1260 			break;
1261 		}
1262 		printf("patrol mode: %s%s\n", mode, interval);
1263 		printf("patrol status: %s\n", status);
1264 	}
1265 }
1266 
1267 void
1268 derive_key(u_int32_t type, int rounds, u_int8_t *key, size_t keysz,
1269     u_int8_t *salt, size_t saltsz, char *prompt, int verify)
1270 {
1271 	FILE		*f;
1272 	size_t		pl;
1273 	struct stat	sb;
1274 	char		passphrase[1024], verifybuf[1024];
1275 
1276 	if (!key)
1277 		errx(1, "Invalid key");
1278 	if (!salt)
1279 		errx(1, "Invalid salt");
1280 
1281 	if (type != SR_CRYPTOKDFT_PKCS5_PBKDF2 &&
1282 	    type != SR_CRYPTOKDFT_BCRYPT_PBKDF)
1283 		errx(1, "unknown KDF type %d", type);
1284 
1285 	if (rounds < (type == SR_CRYPTOKDFT_PKCS5_PBKDF2 ? 1000 : 4))
1286 		errx(1, "number of KDF rounds is too small: %d", rounds);
1287 
1288 	/* get passphrase */
1289 	if (password) {
1290 		if ((f = fopen(password, "r")) == NULL)
1291 			err(1, "invalid passphrase file");
1292 
1293 		if (fstat(fileno(f), &sb) == -1)
1294 			err(1, "can't stat passphrase file");
1295 		if (sb.st_uid != 0)
1296 			errx(1, "passphrase file must be owned by root");
1297 		if ((sb.st_mode & ~S_IFMT) != (S_IRUSR | S_IWUSR))
1298 			errx(1, "passphrase file has the wrong permissions");
1299 
1300 		if (fgets(passphrase, sizeof(passphrase), f) == NULL)
1301 			err(1, "can't read passphrase file");
1302 		pl = strlen(passphrase);
1303 		if (pl > 0 && passphrase[pl - 1] == '\n')
1304 			passphrase[pl - 1] = '\0';
1305 		else
1306 			errx(1, "invalid passphrase length");
1307 
1308 		fclose(f);
1309 	} else {
1310 		if (readpassphrase(prompt, passphrase, sizeof(passphrase),
1311 		    rpp_flag) == NULL)
1312 			err(1, "unable to read passphrase");
1313 	}
1314 
1315 	if (verify && !password) {
1316 		/* request user to re-type it */
1317 		if (readpassphrase("Re-type passphrase: ", verifybuf,
1318 		    sizeof(verifybuf), rpp_flag) == NULL) {
1319 			explicit_bzero(passphrase, sizeof(passphrase));
1320 			err(1, "unable to read passphrase");
1321 		}
1322 		if ((strlen(passphrase) != strlen(verifybuf)) ||
1323 		    (strcmp(passphrase, verifybuf) != 0)) {
1324 			explicit_bzero(passphrase, sizeof(passphrase));
1325 			explicit_bzero(verifybuf, sizeof(verifybuf));
1326 			errx(1, "Passphrases did not match");
1327 		}
1328 		/* forget the re-typed one */
1329 		explicit_bzero(verifybuf, sizeof(verifybuf));
1330 	}
1331 
1332 	/* derive key from passphrase */
1333 	if (type == SR_CRYPTOKDFT_PKCS5_PBKDF2) {
1334 		if (pkcs5_pbkdf2(passphrase, strlen(passphrase), salt, saltsz,
1335 		    key, keysz, rounds) != 0)
1336 			errx(1, "pkcs5_pbkdf2 failed");
1337 	} else if (type == SR_CRYPTOKDFT_BCRYPT_PBKDF) {
1338 		if (bcrypt_pbkdf(passphrase, strlen(passphrase), salt, saltsz,
1339 		    key, keysz, rounds) != 0)
1340 			errx(1, "bcrypt_pbkdf failed");
1341 	} else {
1342 		errx(1, "unknown KDF type %d", type);
1343 	}
1344 
1345 	/* forget passphrase */
1346 	explicit_bzero(passphrase, sizeof(passphrase));
1347 
1348 	return;
1349 }
1350