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