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