1 /* $OpenBSD: mount_vnd.c,v 1.22 2019/06/28 13:32:45 deraadt Exp $ */
2 /*
3 * Copyright (c) 1993 University of Utah.
4 * Copyright (c) 1990, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * the Systems Programming Group of the University of Utah Computer
9 * Science Department.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36 #include <sys/param.h> /* DEV_BSIZE */
37 #include <sys/ioctl.h>
38 #include <sys/mount.h>
39 #include <sys/stat.h>
40 #include <sys/disklabel.h>
41
42 #include <dev/vndioctl.h>
43
44 #include <blf.h>
45 #include <err.h>
46 #include <errno.h>
47 #include <fcntl.h>
48 #include <readpassphrase.h>
49 #include <stdio.h>
50 #include <stdlib.h>
51 #include <string.h>
52 #include <unistd.h>
53 #include <limits.h>
54 #include <util.h>
55
56 __dead void usage(void);
57 int config(char *, char *, struct disklabel *, char *, size_t);
58 char *get_pkcs_key(char *, char *);
59
60 int
main(int argc,char ** argv)61 main(int argc, char **argv)
62 {
63 int ch, rv, opt_k = 0, opt_K = 0;
64 char *key = NULL, *mntopts = NULL, *rounds = NULL, *saltopt = NULL;
65 size_t keylen = 0;
66 struct disklabel *dp = NULL;
67
68 while ((ch = getopt(argc, argv, "kK:o:S:t:")) != -1) {
69 switch (ch) {
70 case 'k':
71 opt_k = 1;
72 break;
73 case 'K':
74 opt_K = 1;
75 rounds = optarg;
76 break;
77 case 'o':
78 mntopts = optarg;
79 break;
80 case 'S':
81 saltopt = optarg;
82 break;
83 case 't':
84 dp = getdiskbyname(optarg);
85 if (dp == NULL)
86 errx(1, "unknown disk type: %s", optarg);
87 break;
88 default:
89 usage();
90 /* NOTREACHED */
91 }
92 }
93 argc -= optind;
94 argv += optind;
95
96 if (saltopt && !opt_K)
97 errx(1, "-S only makes sense when used with -K");
98
99 if (argc != 2)
100 usage();
101
102 if (opt_k || opt_K)
103 fprintf(stderr, "WARNING: Consider using softraid crypto.\n");
104 if (opt_k) {
105 if (opt_K)
106 errx(1, "-k and -K are mutually exclusive");
107 key = getpass("Encryption key: ");
108 if (key == NULL || (keylen = strlen(key)) == 0)
109 errx(1, "Need an encryption key");
110 } else if (opt_K) {
111 key = get_pkcs_key(rounds, saltopt);
112 keylen = BLF_MAXUTILIZED;
113 }
114 rv = config(argv[1], argv[0], dp, key, keylen);
115
116 exit(rv);
117 }
118
119 char *
get_pkcs_key(char * arg,char * saltopt)120 get_pkcs_key(char *arg, char *saltopt)
121 {
122 char passphrase[128] = {'\0'};
123 char saltbuf[128] = {'\0'}, saltfilebuf[PATH_MAX];
124 char *key = NULL;
125 char *saltfile;
126 const char *errstr;
127 int rounds;
128
129 rounds = strtonum(arg, 1000, INT_MAX, &errstr);
130 if (errstr)
131 err(1, "rounds: %s", errstr);
132 if (readpassphrase("Encryption key: ", passphrase, sizeof(passphrase),
133 RPP_REQUIRE_TTY) == NULL)
134 errx(1, "Unable to read passphrase");
135 if (saltopt)
136 saltfile = saltopt;
137 else {
138 printf("Salt file: ");
139 fflush(stdout);
140 saltfile = fgets(saltfilebuf, sizeof(saltfilebuf), stdin);
141 if (saltfile)
142 saltfile[strcspn(saltfile, "\n")] = '\0';
143 }
144 if (!saltfile || saltfile[0] == '\0')
145 warnx("Skipping salt file, insecure");
146 else {
147 int fd;
148
149 fd = open(saltfile, O_RDONLY);
150 if (fd == -1) {
151 int *s;
152
153 fprintf(stderr, "Salt file not found, attempting to "
154 "create one\n");
155 fd = open(saltfile, O_RDWR|O_CREAT|O_EXCL, 0600);
156 if (fd == -1)
157 err(1, "Unable to create salt file: '%s'",
158 saltfile);
159 for (s = (int *)saltbuf;
160 s < (int *)(saltbuf + sizeof(saltbuf)); s++)
161 *s = arc4random();
162 if (write(fd, saltbuf, sizeof(saltbuf))
163 != sizeof(saltbuf))
164 err(1, "Unable to write salt file: '%s'",
165 saltfile);
166 fprintf(stderr, "Salt file created as '%s'\n",
167 saltfile);
168 } else {
169 if (read(fd, saltbuf, sizeof(saltbuf))
170 != sizeof(saltbuf))
171 err(1, "Unable to read salt file: '%s'",
172 saltfile);
173 }
174 close(fd);
175 }
176 if ((key = calloc(1, BLF_MAXUTILIZED)) == NULL)
177 err(1, NULL);
178 if (pkcs5_pbkdf2(passphrase, sizeof(passphrase), saltbuf,
179 sizeof (saltbuf), key, BLF_MAXUTILIZED, rounds))
180 errx(1, "pkcs5_pbkdf2 failed");
181 explicit_bzero(passphrase, sizeof(passphrase));
182
183 return (key);
184 }
185
186 int
config(char * dev,char * file,struct disklabel * dp,char * key,size_t keylen)187 config(char *dev, char *file, struct disklabel *dp, char *key, size_t keylen)
188 {
189 struct vnd_ioctl vndio;
190 char *rdev;
191 int fd, rv = -1;
192
193 if ((fd = opendev(dev, O_RDONLY, OPENDEV_PART, &rdev)) == -1) {
194 err(4, "%s", rdev);
195 goto out;
196 }
197
198 vndio.vnd_file = file;
199 vndio.vnd_secsize = (dp && dp->d_secsize) ? dp->d_secsize : DEV_BSIZE;
200 vndio.vnd_nsectors = (dp && dp->d_nsectors) ? dp->d_nsectors : 100;
201 vndio.vnd_ntracks = (dp && dp->d_ntracks) ? dp->d_ntracks : 1;
202 vndio.vnd_key = (u_char *)key;
203 vndio.vnd_keylen = keylen;
204
205 /*
206 * Configure the device
207 */
208 rv = ioctl(fd, VNDIOCSET, &vndio);
209 if (rv)
210 warn("VNDIOCSET");
211
212 close(fd);
213 fflush(stdout);
214 out:
215 if (key)
216 explicit_bzero(key, keylen);
217 return (rv < 0);
218 }
219
220 __dead void
usage(void)221 usage(void)
222 {
223 (void)fprintf(stderr,
224 "usage: mount_vnd [-k] [-K rounds] [-o options] "
225 "[-S saltfile] [-t disktype]\n"
226 "\t\t image vnd_dev\n");
227 exit(1);
228 }
229