GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: sbin/bioctl/bioctl.c Lines: 0 692 0.0 %
Date: 2017-11-07 Branches: 0 405 0.0 %

Line Branch Exec Source
1
/* $OpenBSD: bioctl.c,v 1.141 2016/12/20 15:38:46 patrick 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))
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)) {
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))
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))
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))
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))
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))
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))
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))
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))
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))
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
	return;
790
}
791
792
void
793
bio_blink(char *enclosure, int target, int blinktype)
794
{
795
	int			bioh;
796
	struct bio_locate	bl;
797
	struct bioc_blink	blink;
798
799
	bioh = open("/dev/bio", O_RDWR);
800
	if (bioh == -1)
801
		err(1, "Can't open %s", "/dev/bio");
802
803
	memset(&bl, 0, sizeof(bl));
804
	bl.bl_name = enclosure;
805
	if (ioctl(bioh, BIOCLOCATE, &bl))
806
		errx(1, "Can't locate %s device via %s", enclosure, "/dev/bio");
807
808
	memset(&blink, 0, sizeof(blink));
809
	blink.bb_bio.bio_cookie = bio_cookie;
810
	blink.bb_status = blinktype;
811
	blink.bb_target = target;
812
813
	if (ioctl(bioh, BIOCBLINK, &blink))
814
		err(1, "BIOCBLINK");
815
816
	bio_status(&blink.bb_bio.bio_status);
817
818
	close(bioh);
819
}
820
821
void
822
bio_createraid(u_int16_t level, char *dev_list, char *key_disk)
823
{
824
	struct bioc_createraid	create;
825
	struct sr_crypto_kdfinfo kdfinfo;
826
	struct sr_crypto_pbkdf	kdfhint;
827
	struct stat		sb;
828
	int			rv, no_dev, fd;
829
	dev_t			*dt;
830
	u_int16_t		min_disks = 0;
831
832
	if (!dev_list)
833
		errx(1, "no devices specified");
834
835
	dt = calloc(1, BIOC_CRMAXLEN);
836
	if (!dt)
837
		err(1, "not enough memory for dev_t list");
838
839
	no_dev = bio_parse_devlist(dev_list, dt);
840
841
	switch (level) {
842
	case 0:
843
		min_disks = 2;
844
		break;
845
	case 1:
846
		min_disks = 2;
847
		break;
848
	case 5:
849
		min_disks = 3;
850
		break;
851
	case 'C':
852
		min_disks = 1;
853
		break;
854
	case 'c':
855
		min_disks = 2;
856
		break;
857
	default:
858
		errx(1, "unsupported raid level");
859
	}
860
861
	if (no_dev < min_disks)
862
		errx(1, "not enough disks");
863
864
	/* for crypto raid we only allow one single chunk */
865
	if (level == 'C' && no_dev != min_disks)
866
		errx(1, "not exactly one partition");
867
868
	memset(&create, 0, sizeof(create));
869
	create.bc_bio.bio_cookie = bio_cookie;
870
	create.bc_level = level;
871
	create.bc_dev_list_len = no_dev * sizeof(dev_t);
872
	create.bc_dev_list = dt;
873
	create.bc_flags = BIOC_SCDEVT | cflags;
874
	create.bc_key_disk = NODEV;
875
876
	if (level == 'C' && key_disk == NULL) {
877
878
		memset(&kdfinfo, 0, sizeof(kdfinfo));
879
		memset(&kdfhint, 0, sizeof(kdfhint));
880
881
		create.bc_flags |= BIOC_SCNOAUTOASSEMBLE;
882
883
		create.bc_opaque = &kdfhint;
884
		create.bc_opaque_size = sizeof(kdfhint);
885
		create.bc_opaque_flags = BIOC_SOOUT;
886
887
		/* try to get KDF hint */
888
		if (ioctl(devh, BIOCCREATERAID, &create))
889
			err(1, "ioctl");
890
891
		bio_status(&create.bc_bio.bio_status);
892
893
		if (create.bc_opaque_status == BIOC_SOINOUT_OK) {
894
			bio_kdf_derive(&kdfinfo, &kdfhint, "Passphrase: ", 0);
895
			memset(&kdfhint, 0, sizeof(kdfhint));
896
		} else {
897
			bio_kdf_generate(&kdfinfo);
898
		}
899
900
		create.bc_opaque = &kdfinfo;
901
		create.bc_opaque_size = sizeof(kdfinfo);
902
		create.bc_opaque_flags = BIOC_SOIN;
903
904
	} else if (level == 'C' && key_disk != NULL) {
905
906
		/* Get device number for key disk. */
907
		fd = opendev(key_disk, O_RDONLY, OPENDEV_BLCK, NULL);
908
		if (fd == -1)
909
			err(1, "could not open %s", key_disk);
910
		if (fstat(fd, &sb) == -1) {
911
			int saved_errno = errno;
912
			close(fd);
913
			errc(1, saved_errno, "could not stat %s", key_disk);
914
		}
915
		close(fd);
916
		create.bc_key_disk = sb.st_rdev;
917
918
		memset(&kdfinfo, 0, sizeof(kdfinfo));
919
920
		kdfinfo.genkdf.len = sizeof(kdfinfo.genkdf);
921
		kdfinfo.genkdf.type = SR_CRYPTOKDFT_KEYDISK;
922
		kdfinfo.len = sizeof(kdfinfo);
923
		kdfinfo.flags = SR_CRYPTOKDF_HINT;
924
925
		create.bc_opaque = &kdfinfo;
926
		create.bc_opaque_size = sizeof(kdfinfo);
927
		create.bc_opaque_flags = BIOC_SOIN;
928
929
	}
930
931
	rv = ioctl(devh, BIOCCREATERAID, &create);
932
	explicit_bzero(&kdfinfo, sizeof(kdfinfo));
933
	if (rv == -1)
934
		err(1, "BIOCCREATERAID");
935
936
	bio_status(&create.bc_bio.bio_status);
937
938
	free(dt);
939
}
940
941
void
942
bio_kdf_derive(struct sr_crypto_kdfinfo *kdfinfo, struct sr_crypto_pbkdf
943
    *kdfhint, char* prompt, int verify)
944
{
945
	if (!kdfinfo)
946
		errx(1, "invalid KDF info");
947
	if (!kdfhint)
948
		errx(1, "invalid KDF hint");
949
950
	if (kdfhint->generic.len != sizeof(*kdfhint))
951
		errx(1, "KDF hint has invalid size");
952
953
	kdfinfo->flags = SR_CRYPTOKDF_KEY;
954
	kdfinfo->len = sizeof(*kdfinfo);
955
956
	derive_key(kdfhint->generic.type, kdfhint->rounds,
957
	    kdfinfo->maskkey, sizeof(kdfinfo->maskkey),
958
	    kdfhint->salt, sizeof(kdfhint->salt),
959
	    prompt, verify);
960
}
961
962
void
963
bio_kdf_generate(struct sr_crypto_kdfinfo *kdfinfo)
964
{
965
	if (!kdfinfo)
966
		errx(1, "invalid KDF info");
967
968
	if (rflag == -1)
969
		rflag = bcrypt_pbkdf_autorounds();
970
971
	kdfinfo->pbkdf.generic.len = sizeof(kdfinfo->pbkdf);
972
	kdfinfo->pbkdf.generic.type = SR_CRYPTOKDFT_BCRYPT_PBKDF;
973
	kdfinfo->pbkdf.rounds = rflag ? rflag : 16;
974
975
	kdfinfo->flags = SR_CRYPTOKDF_KEY | SR_CRYPTOKDF_HINT;
976
	kdfinfo->len = sizeof(*kdfinfo);
977
978
	/* generate salt */
979
	arc4random_buf(kdfinfo->pbkdf.salt, sizeof(kdfinfo->pbkdf.salt));
980
981
	derive_key(kdfinfo->pbkdf.generic.type, kdfinfo->pbkdf.rounds,
982
	    kdfinfo->maskkey, sizeof(kdfinfo->maskkey),
983
	    kdfinfo->pbkdf.salt, sizeof(kdfinfo->pbkdf.salt),
984
	    "New passphrase: ", 1);
985
}
986
987
int
988
bio_parse_devlist(char *lst, dev_t *dt)
989
{
990
	char			*s, *e;
991
	u_int32_t		sz = 0;
992
	int			no_dev = 0, i, x;
993
	struct stat		sb;
994
	char			dev[PATH_MAX];
995
	int			fd;
996
997
	if (!lst)
998
		errx(1, "invalid device list");
999
1000
	s = e = lst;
1001
	/* make sure we have a valid device list like /dev/sdNa,/dev/sdNNa */
1002
	while (*e != '\0') {
1003
		if (*e == ',')
1004
			s = e + 1;
1005
		else if (*(e + 1) == '\0' || *(e + 1) == ',') {
1006
			/* got one */
1007
			sz = e - s + 1;
1008
			strlcpy(dev, s, sz + 1);
1009
			fd = opendev(dev, O_RDONLY, OPENDEV_BLCK, NULL);
1010
			if (fd == -1)
1011
				err(1, "could not open %s", dev);
1012
			if (fstat(fd, &sb) == -1) {
1013
				int saved_errno = errno;
1014
				close(fd);
1015
				errc(1, saved_errno, "could not stat %s", dev);
1016
			}
1017
			close(fd);
1018
			dt[no_dev] = sb.st_rdev;
1019
			no_dev++;
1020
			if (no_dev > (int)(BIOC_CRMAXLEN / sizeof(dev_t)))
1021
				errx(1, "too many devices on device list");
1022
		}
1023
		e++;
1024
	}
1025
1026
	for (i = 0; i < no_dev; i++)
1027
		for (x = 0; x < no_dev; x++)
1028
			if (dt[i] == dt[x] && x != i)
1029
				errx(1, "duplicate device in list");
1030
1031
	return (no_dev);
1032
}
1033
1034
u_int32_t
1035
bio_createflags(char *lst)
1036
{
1037
	char			*s, *e, fs[32];
1038
	u_int32_t		sz = 0;
1039
	u_int32_t		flags = 0;
1040
1041
	if (!lst)
1042
		errx(1, "invalid flags list");
1043
1044
	s = e = lst;
1045
	/* make sure we have a valid flags list like force,noassemeble */
1046
	while (*e != '\0') {
1047
		if (*e == ',')
1048
			s = e + 1;
1049
		else if (*(e + 1) == '\0' || *(e + 1) == ',') {
1050
			/* got one */
1051
			sz = e - s + 1;
1052
			switch (s[0]) {
1053
			case 'f':
1054
				flags |= BIOC_SCFORCE;
1055
				break;
1056
			case 'n':
1057
				flags |= BIOC_SCNOAUTOASSEMBLE;
1058
				break;
1059
			default:
1060
				strlcpy(fs, s, sz + 1);
1061
				errx(1, "invalid flag %s", fs);
1062
			}
1063
		}
1064
		e++;
1065
	}
1066
1067
	return (flags);
1068
}
1069
1070
void
1071
bio_deleteraid(char *dev)
1072
{
1073
	struct bioc_deleteraid	bd;
1074
	memset(&bd, 0, sizeof(bd));
1075
1076
	bd.bd_bio.bio_cookie = bio_cookie;
1077
	/* XXX make this a dev_t instead of a string */
1078
	strlcpy(bd.bd_dev, dev, sizeof bd.bd_dev);
1079
	if (ioctl(devh, BIOCDELETERAID, &bd))
1080
		err(1, "BIOCDELETERAID");
1081
1082
	bio_status(&bd.bd_bio.bio_status);
1083
}
1084
1085
void
1086
bio_changepass(char *dev)
1087
{
1088
	struct bioc_discipline bd;
1089
	struct sr_crypto_kdfpair kdfpair;
1090
	struct sr_crypto_kdfinfo kdfinfo1, kdfinfo2;
1091
	struct sr_crypto_pbkdf kdfhint;
1092
	int rv;
1093
1094
	memset(&bd, 0, sizeof(bd));
1095
	memset(&kdfhint, 0, sizeof(kdfhint));
1096
	memset(&kdfinfo1, 0, sizeof(kdfinfo1));
1097
	memset(&kdfinfo2, 0, sizeof(kdfinfo2));
1098
1099
	/* XXX use dev_t instead of string. */
1100
	strlcpy(bd.bd_dev, dev, sizeof(bd.bd_dev));
1101
	bd.bd_cmd = SR_IOCTL_GET_KDFHINT;
1102
	bd.bd_size = sizeof(kdfhint);
1103
	bd.bd_data = &kdfhint;
1104
1105
	if (ioctl(devh, BIOCDISCIPLINE, &bd))
1106
		err(1, "BIOCDISCIPLINE");
1107
1108
	bio_status(&bd.bd_bio.bio_status);
1109
1110
	/* Current passphrase. */
1111
	bio_kdf_derive(&kdfinfo1, &kdfhint, "Old passphrase: ", 0);
1112
1113
	/*
1114
	 * Unless otherwise specified, keep the previous number of rounds as
1115
	 * long as we're using the same KDF.
1116
	 */
1117
	if (kdfhint.generic.type == SR_CRYPTOKDFT_BCRYPT_PBKDF && !rflag)
1118
		rflag = kdfhint.rounds;
1119
1120
	/* New passphrase. */
1121
	bio_kdf_generate(&kdfinfo2);
1122
1123
	kdfpair.kdfinfo1 = &kdfinfo1;
1124
	kdfpair.kdfsize1 = sizeof(kdfinfo1);
1125
	kdfpair.kdfinfo2 = &kdfinfo2;
1126
	kdfpair.kdfsize2 = sizeof(kdfinfo2);
1127
1128
	bd.bd_cmd = SR_IOCTL_CHANGE_PASSPHRASE;
1129
	bd.bd_size = sizeof(kdfpair);
1130
	bd.bd_data = &kdfpair;
1131
1132
	rv = ioctl(devh, BIOCDISCIPLINE, &bd);
1133
1134
	memset(&kdfhint, 0, sizeof(kdfhint));
1135
	explicit_bzero(&kdfinfo1, sizeof(kdfinfo1));
1136
	explicit_bzero(&kdfinfo2, sizeof(kdfinfo2));
1137
1138
	if (rv)
1139
		err(1, "BIOCDISCIPLINE");
1140
1141
	bio_status(&bd.bd_bio.bio_status);
1142
}
1143
1144
#define BIOCTL_VIS_NBUF		4
1145
#define BIOCTL_VIS_BUFLEN	80
1146
1147
char *
1148
bio_vis(char *s)
1149
{
1150
	static char	 rbuf[BIOCTL_VIS_NBUF][BIOCTL_VIS_BUFLEN];
1151
	static uint	 idx = 0;
1152
	char		*buf;
1153
1154
	buf = rbuf[idx++];
1155
	if (idx == BIOCTL_VIS_NBUF)
1156
		idx = 0;
1157
1158
	strnvis(buf, s, BIOCTL_VIS_BUFLEN, VIS_NL|VIS_CSTYLE);
1159
	return (buf);
1160
}
1161
1162
void
1163
bio_diskinq(char *sd_dev)
1164
{
1165
	struct dk_inquiry	di;
1166
1167
	if (ioctl(devh, DIOCINQ, &di) == -1)
1168
		err(1, "DIOCINQ");
1169
1170
	printf("%s: <%s, %s, %s>, serial %s\n", sd_dev, bio_vis(di.vendor),
1171
	    bio_vis(di.product), bio_vis(di.revision), bio_vis(di.serial));
1172
}
1173
1174
void
1175
bio_patrol(char *arg)
1176
{
1177
	struct bioc_patrol	bp;
1178
	struct timing		timing;
1179
	const char		*errstr;
1180
1181
	memset(&bp, 0, sizeof(bp));
1182
	bp.bp_bio.bio_cookie = bio_cookie;
1183
1184
	switch (arg[0]) {
1185
	case 'a':
1186
		bp.bp_opcode = BIOC_SPAUTO;
1187
		break;
1188
1189
	case 'm':
1190
		bp.bp_opcode = BIOC_SPMANUAL;
1191
		break;
1192
1193
	case 'd':
1194
		bp.bp_opcode = BIOC_SPDISABLE;
1195
		break;
1196
1197
	case 'g': /* get patrol state */
1198
		bp.bp_opcode = BIOC_GPSTATUS;
1199
		break;
1200
1201
	case 's': /* start/stop patrol */
1202
		if (strncmp("sta", arg, 3) == 0)
1203
			bp.bp_opcode = BIOC_SPSTART;
1204
		else
1205
			bp.bp_opcode = BIOC_SPSTOP;
1206
		break;
1207
1208
	default:
1209
		errx(1, "invalid patrol function: %s", arg);
1210
	}
1211
1212
	switch (arg[0]) {
1213
	case 'a':
1214
		errstr = str2patrol(arg, &timing);
1215
		if (errstr)
1216
			errx(1, "Patrol %s: %s", arg, errstr);
1217
		bp.bp_autoival = timing.interval;
1218
		bp.bp_autonext = timing.start;
1219
		break;
1220
	}
1221
1222
	if (ioctl(devh, BIOCPATROL, &bp))
1223
		err(1, "BIOCPATROL");
1224
1225
	bio_status(&bp.bp_bio.bio_status);
1226
1227
	if (arg[0] == 'g') {
1228
		const char *mode, *status;
1229
		char interval[40];
1230
1231
		interval[0] = '\0';
1232
1233
		switch (bp.bp_mode) {
1234
		case BIOC_SPMAUTO:
1235
			mode = "auto";
1236
			snprintf(interval, sizeof interval,
1237
			    " interval=%d next=%d", bp.bp_autoival,
1238
			    bp.bp_autonext - bp.bp_autonow);
1239
			break;
1240
		case BIOC_SPMMANUAL:
1241
			mode = "manual";
1242
			break;
1243
		case BIOC_SPMDISABLED:
1244
			mode = "disabled";
1245
			break;
1246
		default:
1247
			mode = "unknown";
1248
			break;
1249
		}
1250
		switch (bp.bp_status) {
1251
		case BIOC_SPSSTOPPED:
1252
			status = "stopped";
1253
			break;
1254
		case BIOC_SPSREADY:
1255
			status = "ready";
1256
			break;
1257
		case BIOC_SPSACTIVE:
1258
			status = "active";
1259
			break;
1260
		case BIOC_SPSABORTED:
1261
			status = "aborted";
1262
			break;
1263
		default:
1264
			status = "unknown";
1265
			break;
1266
		}
1267
		printf("patrol mode: %s%s\n", mode, interval);
1268
		printf("patrol status: %s\n", status);
1269
	}
1270
}
1271
1272
/*
1273
 * Measure this system's performance by measuring the time for 100 rounds.
1274
 * We are aiming for something that takes around 1s.
1275
 */
1276
int
1277
bcrypt_pbkdf_autorounds(void)
1278
{
1279
	struct timespec before, after;
1280
	char buf[SR_CRYPTO_MAXKEYBYTES], salt[128];
1281
	int r = 100;
1282
	int duration;
1283
1284
	clock_gettime(CLOCK_THREAD_CPUTIME_ID, &before);
1285
	if (bcrypt_pbkdf("testpassword", strlen("testpassword"),
1286
	    salt, sizeof(salt), buf, sizeof(buf), r) != 0)
1287
		errx(1, "bcrypt pbkdf failed");
1288
	clock_gettime(CLOCK_THREAD_CPUTIME_ID, &after);
1289
1290
	duration = after.tv_sec - before.tv_sec;
1291
	duration *= 1000000;
1292
	duration += (after.tv_nsec - before.tv_nsec) / 1000;
1293
1294
	duration /= r;
1295
	r = 1000000 / duration;
1296
1297
	if (r < 16)
1298
		r = 16;
1299
1300
	return r;
1301
}
1302
1303
void
1304
derive_key(u_int32_t type, int rounds, u_int8_t *key, size_t keysz,
1305
    u_int8_t *salt, size_t saltsz, char *prompt, int verify)
1306
{
1307
	FILE		*f;
1308
	size_t		pl;
1309
	struct stat	sb;
1310
	char		passphrase[1024], verifybuf[1024];
1311
1312
	if (!key)
1313
		errx(1, "Invalid key");
1314
	if (!salt)
1315
		errx(1, "Invalid salt");
1316
1317
	if (type != SR_CRYPTOKDFT_PKCS5_PBKDF2 &&
1318
	    type != SR_CRYPTOKDFT_BCRYPT_PBKDF)
1319
		errx(1, "unknown KDF type %d", type);
1320
1321
	if (rounds < (type == SR_CRYPTOKDFT_PKCS5_PBKDF2 ? 1000 : 4))
1322
		errx(1, "number of KDF rounds is too small: %d", rounds);
1323
1324
	/* get passphrase */
1325
	if (password) {
1326
		if ((f = fopen(password, "r")) == NULL)
1327
			err(1, "invalid passphrase file");
1328
1329
		if (fstat(fileno(f), &sb) == -1)
1330
			err(1, "can't stat passphrase file");
1331
		if (sb.st_uid != 0)
1332
			errx(1, "passphrase file must be owned by root");
1333
		if ((sb.st_mode & ~S_IFMT) != (S_IRUSR | S_IWUSR))
1334
			errx(1, "passphrase file has the wrong permissions");
1335
1336
		if (fgets(passphrase, sizeof(passphrase), f) == NULL)
1337
			err(1, "can't read passphrase file");
1338
		pl = strlen(passphrase);
1339
		if (pl > 0 && passphrase[pl - 1] == '\n')
1340
			passphrase[pl - 1] = '\0';
1341
		else
1342
			errx(1, "invalid passphrase length");
1343
1344
		fclose(f);
1345
	} else {
1346
		if (readpassphrase(prompt, passphrase, sizeof(passphrase),
1347
		    rpp_flag) == NULL)
1348
			err(1, "unable to read passphrase");
1349
	}
1350
1351
	if (verify && !password) {
1352
		/* request user to re-type it */
1353
		if (readpassphrase("Re-type passphrase: ", verifybuf,
1354
		    sizeof(verifybuf), rpp_flag) == NULL) {
1355
			explicit_bzero(passphrase, sizeof(passphrase));
1356
			err(1, "unable to read passphrase");
1357
		}
1358
		if ((strlen(passphrase) != strlen(verifybuf)) ||
1359
		    (strcmp(passphrase, verifybuf) != 0)) {
1360
			explicit_bzero(passphrase, sizeof(passphrase));
1361
			explicit_bzero(verifybuf, sizeof(verifybuf));
1362
			errx(1, "Passphrases did not match");
1363
		}
1364
		/* forget the re-typed one */
1365
		explicit_bzero(verifybuf, sizeof(verifybuf));
1366
	}
1367
1368
	/* derive key from passphrase */
1369
	if (type == SR_CRYPTOKDFT_PKCS5_PBKDF2) {
1370
		if (verbose)
1371
			printf("Deriving key using PKCS#5 PBKDF2 with %i rounds...\n",
1372
			    rounds);
1373
		if (pkcs5_pbkdf2(passphrase, strlen(passphrase), salt, saltsz,
1374
		    key, keysz, rounds) != 0)
1375
			errx(1, "pkcs5_pbkdf2 failed");
1376
	} else if (type == SR_CRYPTOKDFT_BCRYPT_PBKDF) {
1377
		if (verbose)
1378
			printf("Deriving key using bcrypt PBKDF with %i rounds...\n",
1379
			    rounds);
1380
		if (bcrypt_pbkdf(passphrase, strlen(passphrase), salt, saltsz,
1381
		    key, keysz, rounds) != 0)
1382
			errx(1, "bcrypt_pbkdf failed");
1383
	} else {
1384
		errx(1, "unknown KDF type %d", type);
1385
	}
1386
1387
	/* forget passphrase */
1388
	explicit_bzero(passphrase, sizeof(passphrase));
1389
1390
	return;
1391
}