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 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 * 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 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 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