1/*- 2 * Copyright (c) 2004-2006 Pawel Jakub Dawidek <pjd@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h>
| 1/*- 2 * Copyright (c) 2004-2006 Pawel Jakub Dawidek <pjd@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h>
|
28__FBSDID("$FreeBSD: head/sbin/geom/class/eli/geom_eli.c 162347 2006-09-16 09:26:57Z pjd $");
| 28__FBSDID("$FreeBSD: head/sbin/geom/class/eli/geom_eli.c 162353 2006-09-16 10:43:17Z pjd $");
|
29 30#include <stdio.h> 31#include <stdint.h> 32#include <stdlib.h> 33#include <unistd.h> 34#include <fcntl.h> 35#include <readpassphrase.h> 36#include <string.h> 37#include <strings.h> 38#include <libgeom.h> 39#include <paths.h> 40#include <errno.h> 41#include <assert.h> 42 43#include <sys/param.h> 44#include <sys/mman.h> 45#include <sys/resource.h> 46#include <opencrypto/cryptodev.h> 47#include <geom/eli/g_eli.h> 48#include <geom/eli/pkcs5v2.h> 49 50#include "core/geom.h" 51#include "misc/subr.h" 52 53 54uint32_t lib_version = G_LIB_VERSION; 55uint32_t version = G_ELI_VERSION; 56 57static char aalgo[] = "none"; 58static char ealgo[] = "aes"; 59static intmax_t keylen = 0; 60static intmax_t keyno = -1; 61static intmax_t iterations = -1; 62static intmax_t sectorsize = 0; 63static char keyfile[] = "", newkeyfile[] = ""; 64 65static void eli_main(struct gctl_req *req, unsigned flags); 66static void eli_init(struct gctl_req *req); 67static void eli_attach(struct gctl_req *req);
| 29 30#include <stdio.h> 31#include <stdint.h> 32#include <stdlib.h> 33#include <unistd.h> 34#include <fcntl.h> 35#include <readpassphrase.h> 36#include <string.h> 37#include <strings.h> 38#include <libgeom.h> 39#include <paths.h> 40#include <errno.h> 41#include <assert.h> 42 43#include <sys/param.h> 44#include <sys/mman.h> 45#include <sys/resource.h> 46#include <opencrypto/cryptodev.h> 47#include <geom/eli/g_eli.h> 48#include <geom/eli/pkcs5v2.h> 49 50#include "core/geom.h" 51#include "misc/subr.h" 52 53 54uint32_t lib_version = G_LIB_VERSION; 55uint32_t version = G_ELI_VERSION; 56 57static char aalgo[] = "none"; 58static char ealgo[] = "aes"; 59static intmax_t keylen = 0; 60static intmax_t keyno = -1; 61static intmax_t iterations = -1; 62static intmax_t sectorsize = 0; 63static char keyfile[] = "", newkeyfile[] = ""; 64 65static void eli_main(struct gctl_req *req, unsigned flags); 66static void eli_init(struct gctl_req *req); 67static void eli_attach(struct gctl_req *req);
|
| 68static void eli_configure(struct gctl_req *req);
|
68static void eli_setkey(struct gctl_req *req); 69static void eli_delkey(struct gctl_req *req); 70static void eli_kill(struct gctl_req *req); 71static void eli_backup(struct gctl_req *req); 72static void eli_restore(struct gctl_req *req); 73static void eli_clear(struct gctl_req *req); 74static void eli_dump(struct gctl_req *req); 75 76/* 77 * Available commands: 78 * 79 * init [-bhPv] [-a aalgo] [-e ealgo] [-i iterations] [-l keylen] [-K newkeyfile] prov 80 * label - alias for 'init' 81 * attach [-dprv] [-k keyfile] prov 82 * detach [-fl] prov ... 83 * stop - alias for 'detach' 84 * onetime [-d] [-a aalgo] [-e ealgo] [-l keylen] prov ...
| 69static void eli_setkey(struct gctl_req *req); 70static void eli_delkey(struct gctl_req *req); 71static void eli_kill(struct gctl_req *req); 72static void eli_backup(struct gctl_req *req); 73static void eli_restore(struct gctl_req *req); 74static void eli_clear(struct gctl_req *req); 75static void eli_dump(struct gctl_req *req); 76 77/* 78 * Available commands: 79 * 80 * init [-bhPv] [-a aalgo] [-e ealgo] [-i iterations] [-l keylen] [-K newkeyfile] prov 81 * label - alias for 'init' 82 * attach [-dprv] [-k keyfile] prov 83 * detach [-fl] prov ... 84 * stop - alias for 'detach' 85 * onetime [-d] [-a aalgo] [-e ealgo] [-l keylen] prov ...
|
| 86 * configure [-bB] prov ...
|
85 * setkey [-pPv] [-n keyno] [-k keyfile] [-K newkeyfile] prov 86 * delkey [-afv] [-n keyno] prov 87 * kill [-av] [prov ...] 88 * backup [-v] prov file 89 * restore [-v] file prov 90 * clear [-v] prov ... 91 * dump [-v] prov ... 92 */ 93struct g_command class_commands[] = { 94 { "init", G_FLAG_VERBOSE, eli_main, 95 { 96 { 'a', "aalgo", aalgo, G_TYPE_STRING }, 97 { 'b', "boot", NULL, G_TYPE_NONE }, 98 { 'e', "ealgo", ealgo, G_TYPE_STRING }, 99 { 'i', "iterations", &iterations, G_TYPE_NUMBER }, 100 { 'K', "newkeyfile", newkeyfile, G_TYPE_STRING }, 101 { 'l', "keylen", &keylen, G_TYPE_NUMBER }, 102 { 'P', "nonewpassphrase", NULL, G_TYPE_NONE }, 103 { 's', "sectorsize", §orsize, G_TYPE_NUMBER }, 104 G_OPT_SENTINEL 105 }, 106 "[-bPv] [-a aalgo] [-e ealgo] [-i iterations] [-l keylen] [-K newkeyfile] [-s sectorsize] prov" 107 }, 108 { "label", G_FLAG_VERBOSE, eli_main, 109 { 110 { 'a', "aalgo", aalgo, G_TYPE_STRING }, 111 { 'b', "boot", NULL, G_TYPE_NONE }, 112 { 'e', "ealgo", ealgo, G_TYPE_STRING }, 113 { 'i', "iterations", &iterations, G_TYPE_NUMBER }, 114 { 'K', "newkeyfile", newkeyfile, G_TYPE_STRING }, 115 { 'l', "keylen", &keylen, G_TYPE_NUMBER }, 116 { 'P', "nonewpassphrase", NULL, G_TYPE_NONE }, 117 { 's', "sectorsize", §orsize, G_TYPE_NUMBER }, 118 G_OPT_SENTINEL 119 }, 120 "- an alias for 'init'" 121 }, 122 { "attach", G_FLAG_VERBOSE | G_FLAG_LOADKLD, eli_main, 123 { 124 { 'd', "detach", NULL, G_TYPE_NONE }, 125 { 'k', "keyfile", keyfile, G_TYPE_STRING }, 126 { 'p', "nopassphrase", NULL, G_TYPE_NONE }, 127 { 'r', "readonly", NULL, G_TYPE_NONE }, 128 G_OPT_SENTINEL 129 }, 130 "[-dprv] [-k keyfile] prov" 131 }, 132 { "detach", 0, NULL, 133 { 134 { 'f', "force", NULL, G_TYPE_NONE }, 135 { 'l', "last", NULL, G_TYPE_NONE }, 136 G_OPT_SENTINEL 137 }, 138 "[-fl] prov ..." 139 }, 140 { "stop", 0, NULL, 141 { 142 { 'f', "force", NULL, G_TYPE_NONE }, 143 { 'l', "last", NULL, G_TYPE_NONE }, 144 G_OPT_SENTINEL 145 }, 146 "- an alias for 'detach'" 147 }, 148 { "onetime", G_FLAG_VERBOSE | G_FLAG_LOADKLD, NULL, 149 { 150 { 'a', "aalgo", aalgo, G_TYPE_STRING }, 151 { 'd', "detach", NULL, G_TYPE_NONE }, 152 { 'e', "ealgo", ealgo, G_TYPE_STRING }, 153 { 'l', "keylen", &keylen, G_TYPE_NUMBER }, 154 { 's', "sectorsize", §orsize, G_TYPE_NUMBER }, 155 G_OPT_SENTINEL 156 }, 157 "[-d] [-a aalgo] [-e ealgo] [-l keylen] [-s sectorsize] prov ..." 158 },
| 87 * setkey [-pPv] [-n keyno] [-k keyfile] [-K newkeyfile] prov 88 * delkey [-afv] [-n keyno] prov 89 * kill [-av] [prov ...] 90 * backup [-v] prov file 91 * restore [-v] file prov 92 * clear [-v] prov ... 93 * dump [-v] prov ... 94 */ 95struct g_command class_commands[] = { 96 { "init", G_FLAG_VERBOSE, eli_main, 97 { 98 { 'a', "aalgo", aalgo, G_TYPE_STRING }, 99 { 'b', "boot", NULL, G_TYPE_NONE }, 100 { 'e', "ealgo", ealgo, G_TYPE_STRING }, 101 { 'i', "iterations", &iterations, G_TYPE_NUMBER }, 102 { 'K', "newkeyfile", newkeyfile, G_TYPE_STRING }, 103 { 'l', "keylen", &keylen, G_TYPE_NUMBER }, 104 { 'P', "nonewpassphrase", NULL, G_TYPE_NONE }, 105 { 's', "sectorsize", §orsize, G_TYPE_NUMBER }, 106 G_OPT_SENTINEL 107 }, 108 "[-bPv] [-a aalgo] [-e ealgo] [-i iterations] [-l keylen] [-K newkeyfile] [-s sectorsize] prov" 109 }, 110 { "label", G_FLAG_VERBOSE, eli_main, 111 { 112 { 'a', "aalgo", aalgo, G_TYPE_STRING }, 113 { 'b', "boot", NULL, G_TYPE_NONE }, 114 { 'e', "ealgo", ealgo, G_TYPE_STRING }, 115 { 'i', "iterations", &iterations, G_TYPE_NUMBER }, 116 { 'K', "newkeyfile", newkeyfile, G_TYPE_STRING }, 117 { 'l', "keylen", &keylen, G_TYPE_NUMBER }, 118 { 'P', "nonewpassphrase", NULL, G_TYPE_NONE }, 119 { 's', "sectorsize", §orsize, G_TYPE_NUMBER }, 120 G_OPT_SENTINEL 121 }, 122 "- an alias for 'init'" 123 }, 124 { "attach", G_FLAG_VERBOSE | G_FLAG_LOADKLD, eli_main, 125 { 126 { 'd', "detach", NULL, G_TYPE_NONE }, 127 { 'k', "keyfile", keyfile, G_TYPE_STRING }, 128 { 'p', "nopassphrase", NULL, G_TYPE_NONE }, 129 { 'r', "readonly", NULL, G_TYPE_NONE }, 130 G_OPT_SENTINEL 131 }, 132 "[-dprv] [-k keyfile] prov" 133 }, 134 { "detach", 0, NULL, 135 { 136 { 'f', "force", NULL, G_TYPE_NONE }, 137 { 'l', "last", NULL, G_TYPE_NONE }, 138 G_OPT_SENTINEL 139 }, 140 "[-fl] prov ..." 141 }, 142 { "stop", 0, NULL, 143 { 144 { 'f', "force", NULL, G_TYPE_NONE }, 145 { 'l', "last", NULL, G_TYPE_NONE }, 146 G_OPT_SENTINEL 147 }, 148 "- an alias for 'detach'" 149 }, 150 { "onetime", G_FLAG_VERBOSE | G_FLAG_LOADKLD, NULL, 151 { 152 { 'a', "aalgo", aalgo, G_TYPE_STRING }, 153 { 'd', "detach", NULL, G_TYPE_NONE }, 154 { 'e', "ealgo", ealgo, G_TYPE_STRING }, 155 { 'l', "keylen", &keylen, G_TYPE_NUMBER }, 156 { 's', "sectorsize", §orsize, G_TYPE_NUMBER }, 157 G_OPT_SENTINEL 158 }, 159 "[-d] [-a aalgo] [-e ealgo] [-l keylen] [-s sectorsize] prov ..." 160 },
|
| 161 { "configure", G_FLAG_VERBOSE, eli_main, 162 { 163 { 'b', "boot", NULL, G_TYPE_NONE }, 164 { 'B', "noboot", NULL, G_TYPE_NONE }, 165 G_OPT_SENTINEL 166 }, 167 "[-bB] prov ..." 168 },
|
159 { "setkey", G_FLAG_VERBOSE, eli_main, 160 { 161 { 'i', "iterations", &iterations, G_TYPE_NUMBER }, 162 { 'k', "keyfile", keyfile, G_TYPE_STRING }, 163 { 'K', "newkeyfile", newkeyfile, G_TYPE_STRING }, 164 { 'n', "keyno", &keyno, G_TYPE_NUMBER }, 165 { 'p', "nopassphrase", NULL, G_TYPE_NONE }, 166 { 'P', "nonewpassphrase", NULL, G_TYPE_NONE }, 167 G_OPT_SENTINEL 168 }, 169 "[-pPv] [-n keyno] [-i iterations] [-k keyfile] [-K newkeyfile] prov" 170 }, 171 { "delkey", G_FLAG_VERBOSE, eli_main, 172 { 173 { 'a', "all", NULL, G_TYPE_NONE }, 174 { 'f', "force", NULL, G_TYPE_NONE }, 175 { 'n', "keyno", &keyno, G_TYPE_NUMBER }, 176 G_OPT_SENTINEL 177 }, 178 "[-afv] [-n keyno] prov" 179 }, 180 { "kill", G_FLAG_VERBOSE, eli_main, 181 { 182 { 'a', "all", NULL, G_TYPE_NONE }, 183 G_OPT_SENTINEL 184 }, 185 "[-av] [prov ...]" 186 }, 187 { "backup", G_FLAG_VERBOSE, eli_main, G_NULL_OPTS, 188 "[-v] prov file" 189 }, 190 { "restore", G_FLAG_VERBOSE, eli_main, G_NULL_OPTS, 191 "[-v] file prov" 192 }, 193 { "clear", G_FLAG_VERBOSE, eli_main, G_NULL_OPTS, 194 "[-v] prov ..." 195 }, 196 { "dump", G_FLAG_VERBOSE, eli_main, G_NULL_OPTS, 197 "[-v] prov ..." 198 }, 199 G_CMD_SENTINEL 200}; 201 202static int verbose = 0; 203 204static int 205eli_protect(struct gctl_req *req) 206{ 207 struct rlimit rl; 208 209 /* Disable core dumps. */ 210 rl.rlim_cur = 0; 211 rl.rlim_max = 0; 212 if (setrlimit(RLIMIT_CORE, &rl) == -1) { 213 gctl_error(req, "Cannot disable core dumps: %s.", 214 strerror(errno)); 215 return (-1); 216 } 217 /* Disable swapping. */ 218 if (mlockall(MCL_FUTURE) == -1) { 219 gctl_error(req, "Cannot lock memory: %s.", strerror(errno)); 220 return (-1); 221 } 222 return (0); 223} 224 225static void 226eli_main(struct gctl_req *req, unsigned flags) 227{ 228 const char *name; 229 230 if (eli_protect(req) == -1) 231 return; 232 233 if ((flags & G_FLAG_VERBOSE) != 0) 234 verbose = 1; 235 236 name = gctl_get_ascii(req, "verb"); 237 if (name == NULL) { 238 gctl_error(req, "No '%s' argument.", "verb"); 239 return; 240 } 241 if (strcmp(name, "init") == 0 || strcmp(name, "label") == 0) 242 eli_init(req); 243 else if (strcmp(name, "attach") == 0) 244 eli_attach(req);
| 169 { "setkey", G_FLAG_VERBOSE, eli_main, 170 { 171 { 'i', "iterations", &iterations, G_TYPE_NUMBER }, 172 { 'k', "keyfile", keyfile, G_TYPE_STRING }, 173 { 'K', "newkeyfile", newkeyfile, G_TYPE_STRING }, 174 { 'n', "keyno", &keyno, G_TYPE_NUMBER }, 175 { 'p', "nopassphrase", NULL, G_TYPE_NONE }, 176 { 'P', "nonewpassphrase", NULL, G_TYPE_NONE }, 177 G_OPT_SENTINEL 178 }, 179 "[-pPv] [-n keyno] [-i iterations] [-k keyfile] [-K newkeyfile] prov" 180 }, 181 { "delkey", G_FLAG_VERBOSE, eli_main, 182 { 183 { 'a', "all", NULL, G_TYPE_NONE }, 184 { 'f', "force", NULL, G_TYPE_NONE }, 185 { 'n', "keyno", &keyno, G_TYPE_NUMBER }, 186 G_OPT_SENTINEL 187 }, 188 "[-afv] [-n keyno] prov" 189 }, 190 { "kill", G_FLAG_VERBOSE, eli_main, 191 { 192 { 'a', "all", NULL, G_TYPE_NONE }, 193 G_OPT_SENTINEL 194 }, 195 "[-av] [prov ...]" 196 }, 197 { "backup", G_FLAG_VERBOSE, eli_main, G_NULL_OPTS, 198 "[-v] prov file" 199 }, 200 { "restore", G_FLAG_VERBOSE, eli_main, G_NULL_OPTS, 201 "[-v] file prov" 202 }, 203 { "clear", G_FLAG_VERBOSE, eli_main, G_NULL_OPTS, 204 "[-v] prov ..." 205 }, 206 { "dump", G_FLAG_VERBOSE, eli_main, G_NULL_OPTS, 207 "[-v] prov ..." 208 }, 209 G_CMD_SENTINEL 210}; 211 212static int verbose = 0; 213 214static int 215eli_protect(struct gctl_req *req) 216{ 217 struct rlimit rl; 218 219 /* Disable core dumps. */ 220 rl.rlim_cur = 0; 221 rl.rlim_max = 0; 222 if (setrlimit(RLIMIT_CORE, &rl) == -1) { 223 gctl_error(req, "Cannot disable core dumps: %s.", 224 strerror(errno)); 225 return (-1); 226 } 227 /* Disable swapping. */ 228 if (mlockall(MCL_FUTURE) == -1) { 229 gctl_error(req, "Cannot lock memory: %s.", strerror(errno)); 230 return (-1); 231 } 232 return (0); 233} 234 235static void 236eli_main(struct gctl_req *req, unsigned flags) 237{ 238 const char *name; 239 240 if (eli_protect(req) == -1) 241 return; 242 243 if ((flags & G_FLAG_VERBOSE) != 0) 244 verbose = 1; 245 246 name = gctl_get_ascii(req, "verb"); 247 if (name == NULL) { 248 gctl_error(req, "No '%s' argument.", "verb"); 249 return; 250 } 251 if (strcmp(name, "init") == 0 || strcmp(name, "label") == 0) 252 eli_init(req); 253 else if (strcmp(name, "attach") == 0) 254 eli_attach(req);
|
| 255 else if (strcmp(name, "configure") == 0) 256 eli_configure(req);
|
245 else if (strcmp(name, "setkey") == 0) 246 eli_setkey(req); 247 else if (strcmp(name, "delkey") == 0) 248 eli_delkey(req); 249 else if (strcmp(name, "kill") == 0) 250 eli_kill(req); 251 else if (strcmp(name, "backup") == 0) 252 eli_backup(req); 253 else if (strcmp(name, "restore") == 0) 254 eli_restore(req); 255 else if (strcmp(name, "dump") == 0) 256 eli_dump(req); 257 else if (strcmp(name, "clear") == 0) 258 eli_clear(req); 259 else 260 gctl_error(req, "Unknown command: %s.", name); 261} 262 263static void 264arc4rand(unsigned char *buf, size_t size) 265{ 266 uint32_t *buf4; 267 size_t size4; 268 unsigned i; 269 270 buf4 = (uint32_t *)buf; 271 size4 = size / 4; 272 273 for (i = 0; i < size4; i++) 274 buf4[i] = arc4random(); 275 for (i *= 4; i < size; i++) 276 buf[i] = arc4random() % 0xff; 277} 278 279static int 280eli_is_attached(const char *prov) 281{ 282 char name[MAXPATHLEN]; 283 unsigned secsize; 284 285 /* 286 * Not the best way to do it, but the easiest. 287 * We try to open provider and check if it is a GEOM provider 288 * by asking about its sectorsize. 289 */ 290 snprintf(name, sizeof(name), "%s%s", prov, G_ELI_SUFFIX); 291 secsize = g_get_sectorsize(name); 292 if (secsize > 0) 293 return (1); 294 return (0); 295} 296 297static unsigned char * 298eli_genkey(struct gctl_req *req, struct g_eli_metadata *md, unsigned char *key, 299 int new) 300{ 301 struct hmac_ctx ctx; 302 const char *str; 303 int error, nopassphrase; 304 305 nopassphrase = 306 gctl_get_int(req, new ? "nonewpassphrase" : "nopassphrase"); 307 308 g_eli_crypto_hmac_init(&ctx, NULL, 0); 309 310 str = gctl_get_ascii(req, new ? "newkeyfile" : "keyfile"); 311 if (str[0] == '\0' && nopassphrase) { 312 gctl_error(req, "No key components given."); 313 return (NULL); 314 } else if (str[0] != '\0') { 315 char buf[MAXPHYS]; 316 ssize_t done; 317 int fd; 318 319 if (strcmp(str, "-") == 0) 320 fd = STDIN_FILENO; 321 else { 322 fd = open(str, O_RDONLY); 323 if (fd == -1) { 324 gctl_error(req, "Cannot open keyfile %s: %s.", 325 str, strerror(errno)); 326 return (NULL); 327 } 328 } 329 while ((done = read(fd, buf, sizeof(buf))) > 0) 330 g_eli_crypto_hmac_update(&ctx, buf, done); 331 error = errno; 332 if (strcmp(str, "-") != 0) 333 close(fd); 334 bzero(buf, sizeof(buf)); 335 if (done == -1) { 336 gctl_error(req, "Cannot read keyfile %s: %s.", str, 337 strerror(error)); 338 return (NULL); 339 } 340 } 341 342 if (!nopassphrase) { 343 char buf1[BUFSIZ], buf2[BUFSIZ], *p; 344 345 if (!new && md->md_iterations == -1) { 346 gctl_error(req, "Missing -p flag."); 347 return (NULL); 348 } 349 for (;;) { 350 p = readpassphrase( 351 new ? "Enter new passphrase:" : "Enter passphrase:", 352 buf1, sizeof(buf1), RPP_ECHO_OFF | RPP_REQUIRE_TTY); 353 if (p == NULL) { 354 bzero(buf1, sizeof(buf1)); 355 gctl_error(req, "Cannot read passphrase: %s.", 356 strerror(errno)); 357 return (NULL); 358 } 359 360 if (new) { 361 p = readpassphrase("Reenter new passphrase: ", 362 buf2, sizeof(buf2), 363 RPP_ECHO_OFF | RPP_REQUIRE_TTY); 364 if (p == NULL) { 365 bzero(buf1, sizeof(buf1)); 366 gctl_error(req, 367 "Cannot read passphrase: %s.", 368 strerror(errno)); 369 return (NULL); 370 } 371 372 if (strcmp(buf1, buf2) != 0) { 373 bzero(buf2, sizeof(buf2)); 374 fprintf(stderr, "They didn't match.\n"); 375 continue; 376 } 377 bzero(buf2, sizeof(buf2)); 378 } 379 break; 380 } 381 /* 382 * Field md_iterations equal to -1 means "choose some sane 383 * value for me". 384 */ 385 if (md->md_iterations == -1) { 386 assert(new); 387 if (verbose) 388 printf("Calculating number of iterations...\n"); 389 md->md_iterations = pkcs5v2_calculate(2000000); 390 assert(md->md_iterations > 0); 391 if (verbose) { 392 printf("Done, using %d iterations.\n", 393 md->md_iterations); 394 } 395 } 396 /* 397 * If md_iterations is equal to 0, user don't want PKCS#5v2. 398 */ 399 if (md->md_iterations == 0) { 400 g_eli_crypto_hmac_update(&ctx, md->md_salt, 401 sizeof(md->md_salt)); 402 g_eli_crypto_hmac_update(&ctx, buf1, strlen(buf1)); 403 } else /* if (md->md_iterations > 0) */ { 404 unsigned char dkey[G_ELI_USERKEYLEN]; 405 406 pkcs5v2_genkey(dkey, sizeof(dkey), md->md_salt, 407 sizeof(md->md_salt), buf1, md->md_iterations); 408 g_eli_crypto_hmac_update(&ctx, dkey, sizeof(dkey)); 409 bzero(dkey, sizeof(dkey)); 410 } 411 bzero(buf1, sizeof(buf1)); 412 } 413 g_eli_crypto_hmac_final(&ctx, key, 0); 414 return (key); 415} 416 417static int 418eli_metadata_read(struct gctl_req *req, const char *prov, 419 struct g_eli_metadata *md) 420{ 421 unsigned char sector[sizeof(struct g_eli_metadata)]; 422 int error; 423 424 if (g_get_sectorsize(prov) == 0) { 425 int fd; 426 427 /* This is a file probably. */ 428 fd = open(prov, O_RDONLY); 429 if (fd == -1) { 430 gctl_error(req, "Cannot open %s: %s.", prov, 431 strerror(errno)); 432 return (-1); 433 } 434 if (read(fd, sector, sizeof(sector)) != sizeof(sector)) { 435 gctl_error(req, "Cannot read metadata from %s: %s.", 436 prov, strerror(errno)); 437 close(fd); 438 return (-1); 439 } 440 close(fd); 441 } else { 442 /* This is a GEOM provider. */ 443 error = g_metadata_read(prov, sector, sizeof(sector), 444 G_ELI_MAGIC); 445 if (error != 0) { 446 gctl_error(req, "Cannot read metadata from %s: %s.", 447 prov, strerror(error)); 448 return (-1); 449 } 450 } 451 if (eli_metadata_decode(sector, md) != 0) { 452 gctl_error(req, "MD5 hash mismatch for %s.", prov); 453 return (-1); 454 } 455 return (0); 456} 457 458static int 459eli_metadata_store(struct gctl_req *req, const char *prov, 460 struct g_eli_metadata *md) 461{ 462 unsigned char sector[sizeof(struct g_eli_metadata)]; 463 int error; 464 465 eli_metadata_encode(md, sector); 466 if (g_get_sectorsize(prov) == 0) { 467 int fd; 468 469 /* This is a file probably. */ 470 fd = open(prov, O_WRONLY | O_TRUNC); 471 if (fd == -1) { 472 gctl_error(req, "Cannot open %s: %s.", prov, 473 strerror(errno)); 474 bzero(sector, sizeof(sector)); 475 return (-1); 476 } 477 if (write(fd, sector, sizeof(sector)) != sizeof(sector)) { 478 gctl_error(req, "Cannot write metadata to %s: %s.", 479 prov, strerror(errno)); 480 bzero(sector, sizeof(sector)); 481 close(fd); 482 return (-1); 483 } 484 close(fd); 485 } else { 486 /* This is a GEOM provider. */ 487 error = g_metadata_store(prov, sector, sizeof(sector)); 488 if (error != 0) { 489 gctl_error(req, "Cannot write metadata to %s: %s.", 490 prov, strerror(errno)); 491 bzero(sector, sizeof(sector)); 492 return (-1); 493 } 494 } 495 bzero(sector, sizeof(sector)); 496 return (0); 497} 498 499static void 500eli_init(struct gctl_req *req) 501{ 502 struct g_eli_metadata md; 503 unsigned char sector[sizeof(struct g_eli_metadata)]; 504 unsigned char key[G_ELI_USERKEYLEN]; 505 const char *str, *prov; 506 unsigned secsize; 507 off_t mediasize; 508 intmax_t val; 509 int error, nargs; 510 511 nargs = gctl_get_int(req, "nargs"); 512 if (nargs != 1) { 513 gctl_error(req, "Invalid number of arguments."); 514 return; 515 } 516 prov = gctl_get_ascii(req, "arg0"); 517 mediasize = g_get_mediasize(prov); 518 secsize = g_get_sectorsize(prov); 519 if (mediasize == 0 || secsize == 0) { 520 gctl_error(req, "Cannot get informations about %s: %s.", prov, 521 strerror(errno)); 522 return; 523 } 524 525 bzero(&md, sizeof(md)); 526 strlcpy(md.md_magic, G_ELI_MAGIC, sizeof(md.md_magic)); 527 md.md_version = G_ELI_VERSION; 528 md.md_flags = 0; 529 if (gctl_get_int(req, "boot")) 530 md.md_flags |= G_ELI_FLAG_BOOT; 531 md.md_ealgo = CRYPTO_ALGORITHM_MIN - 1; 532 str = gctl_get_ascii(req, "aalgo"); 533 if (strcmp(str, "none") != 0) { 534 md.md_aalgo = g_eli_str2aalgo(str); 535 if (md.md_aalgo >= CRYPTO_ALGORITHM_MIN && 536 md.md_aalgo <= CRYPTO_ALGORITHM_MAX) { 537 md.md_flags |= G_ELI_FLAG_AUTH; 538 } else { 539 /* 540 * For backward compatibility, check if the -a option 541 * was used to provide encryption algorithm. 542 */ 543 md.md_ealgo = g_eli_str2ealgo(str); 544 if (md.md_ealgo < CRYPTO_ALGORITHM_MIN || 545 md.md_ealgo > CRYPTO_ALGORITHM_MAX) { 546 gctl_error(req, 547 "Invalid authentication algorithm."); 548 return; 549 } else { 550 fprintf(stderr, "warning: The -e option, not " 551 "the -a option is now used to specify " 552 "encryption algorithm to use.\n"); 553 } 554 } 555 } 556 if (md.md_ealgo < CRYPTO_ALGORITHM_MIN || 557 md.md_ealgo > CRYPTO_ALGORITHM_MAX) { 558 str = gctl_get_ascii(req, "ealgo"); 559 md.md_ealgo = g_eli_str2ealgo(str); 560 if (md.md_ealgo < CRYPTO_ALGORITHM_MIN || 561 md.md_ealgo > CRYPTO_ALGORITHM_MAX) { 562 gctl_error(req, "Invalid encryption algorithm."); 563 return; 564 } 565 } 566 val = gctl_get_intmax(req, "keylen"); 567 md.md_keylen = val; 568 md.md_keylen = g_eli_keylen(md.md_ealgo, md.md_keylen); 569 if (md.md_keylen == 0) { 570 gctl_error(req, "Invalid key length."); 571 return; 572 } 573 md.md_provsize = mediasize; 574 575 val = gctl_get_intmax(req, "iterations"); 576 if (val != -1) { 577 int nonewpassphrase; 578 579 /* 580 * Don't allow to set iterations when there will be no 581 * passphrase. 582 */ 583 nonewpassphrase = gctl_get_int(req, "nonewpassphrase"); 584 if (nonewpassphrase) { 585 gctl_error(req, 586 "Options -i and -P are mutually exclusive."); 587 return; 588 } 589 } 590 md.md_iterations = val; 591 592 val = gctl_get_intmax(req, "sectorsize"); 593 if (val == 0) 594 md.md_sectorsize = secsize; 595 else { 596 if (val < 0 || (val % secsize) != 0) { 597 gctl_error(req, "Invalid sector size."); 598 return; 599 } 600 md.md_sectorsize = val; 601 } 602 603 md.md_keys = 0x01; 604 arc4rand(md.md_salt, sizeof(md.md_salt)); 605 arc4rand(md.md_mkeys, sizeof(md.md_mkeys)); 606 607 /* Generate user key. */ 608 if (eli_genkey(req, &md, key, 1) == NULL) { 609 bzero(key, sizeof(key)); 610 bzero(&md, sizeof(md)); 611 return; 612 } 613 614 /* Encrypt the first and the only Master Key. */ 615 error = g_eli_mkey_encrypt(md.md_ealgo, key, md.md_keylen, md.md_mkeys); 616 bzero(key, sizeof(key)); 617 if (error != 0) { 618 bzero(&md, sizeof(md)); 619 gctl_error(req, "Cannot encrypt Master Key: %s.", 620 strerror(error)); 621 return; 622 } 623 624 eli_metadata_encode(&md, sector); 625 bzero(&md, sizeof(md)); 626 error = g_metadata_store(prov, sector, sizeof(sector)); 627 bzero(sector, sizeof(sector)); 628 if (error != 0) { 629 gctl_error(req, "Cannot store metadata on %s: %s.", prov, 630 strerror(error)); 631 return; 632 } 633 if (verbose) 634 printf("Metadata value stored on %s.\n", prov); 635} 636 637static void 638eli_attach(struct gctl_req *req) 639{ 640 struct g_eli_metadata md; 641 unsigned char key[G_ELI_USERKEYLEN]; 642 const char *prov; 643 int nargs; 644 645 nargs = gctl_get_int(req, "nargs"); 646 if (nargs != 1) { 647 gctl_error(req, "Invalid number of arguments."); 648 return; 649 } 650 prov = gctl_get_ascii(req, "arg0"); 651 652 if (eli_metadata_read(req, prov, &md) == -1) 653 return; 654 655 if (eli_genkey(req, &md, key, 0) == NULL) { 656 bzero(key, sizeof(key)); 657 return; 658 } 659 660 gctl_ro_param(req, "key", sizeof(key), key); 661 if (gctl_issue(req) == NULL) { 662 if (verbose) 663 printf("Attched to %s.\n", prov); 664 } 665 bzero(key, sizeof(key)); 666} 667 668static void
| 257 else if (strcmp(name, "setkey") == 0) 258 eli_setkey(req); 259 else if (strcmp(name, "delkey") == 0) 260 eli_delkey(req); 261 else if (strcmp(name, "kill") == 0) 262 eli_kill(req); 263 else if (strcmp(name, "backup") == 0) 264 eli_backup(req); 265 else if (strcmp(name, "restore") == 0) 266 eli_restore(req); 267 else if (strcmp(name, "dump") == 0) 268 eli_dump(req); 269 else if (strcmp(name, "clear") == 0) 270 eli_clear(req); 271 else 272 gctl_error(req, "Unknown command: %s.", name); 273} 274 275static void 276arc4rand(unsigned char *buf, size_t size) 277{ 278 uint32_t *buf4; 279 size_t size4; 280 unsigned i; 281 282 buf4 = (uint32_t *)buf; 283 size4 = size / 4; 284 285 for (i = 0; i < size4; i++) 286 buf4[i] = arc4random(); 287 for (i *= 4; i < size; i++) 288 buf[i] = arc4random() % 0xff; 289} 290 291static int 292eli_is_attached(const char *prov) 293{ 294 char name[MAXPATHLEN]; 295 unsigned secsize; 296 297 /* 298 * Not the best way to do it, but the easiest. 299 * We try to open provider and check if it is a GEOM provider 300 * by asking about its sectorsize. 301 */ 302 snprintf(name, sizeof(name), "%s%s", prov, G_ELI_SUFFIX); 303 secsize = g_get_sectorsize(name); 304 if (secsize > 0) 305 return (1); 306 return (0); 307} 308 309static unsigned char * 310eli_genkey(struct gctl_req *req, struct g_eli_metadata *md, unsigned char *key, 311 int new) 312{ 313 struct hmac_ctx ctx; 314 const char *str; 315 int error, nopassphrase; 316 317 nopassphrase = 318 gctl_get_int(req, new ? "nonewpassphrase" : "nopassphrase"); 319 320 g_eli_crypto_hmac_init(&ctx, NULL, 0); 321 322 str = gctl_get_ascii(req, new ? "newkeyfile" : "keyfile"); 323 if (str[0] == '\0' && nopassphrase) { 324 gctl_error(req, "No key components given."); 325 return (NULL); 326 } else if (str[0] != '\0') { 327 char buf[MAXPHYS]; 328 ssize_t done; 329 int fd; 330 331 if (strcmp(str, "-") == 0) 332 fd = STDIN_FILENO; 333 else { 334 fd = open(str, O_RDONLY); 335 if (fd == -1) { 336 gctl_error(req, "Cannot open keyfile %s: %s.", 337 str, strerror(errno)); 338 return (NULL); 339 } 340 } 341 while ((done = read(fd, buf, sizeof(buf))) > 0) 342 g_eli_crypto_hmac_update(&ctx, buf, done); 343 error = errno; 344 if (strcmp(str, "-") != 0) 345 close(fd); 346 bzero(buf, sizeof(buf)); 347 if (done == -1) { 348 gctl_error(req, "Cannot read keyfile %s: %s.", str, 349 strerror(error)); 350 return (NULL); 351 } 352 } 353 354 if (!nopassphrase) { 355 char buf1[BUFSIZ], buf2[BUFSIZ], *p; 356 357 if (!new && md->md_iterations == -1) { 358 gctl_error(req, "Missing -p flag."); 359 return (NULL); 360 } 361 for (;;) { 362 p = readpassphrase( 363 new ? "Enter new passphrase:" : "Enter passphrase:", 364 buf1, sizeof(buf1), RPP_ECHO_OFF | RPP_REQUIRE_TTY); 365 if (p == NULL) { 366 bzero(buf1, sizeof(buf1)); 367 gctl_error(req, "Cannot read passphrase: %s.", 368 strerror(errno)); 369 return (NULL); 370 } 371 372 if (new) { 373 p = readpassphrase("Reenter new passphrase: ", 374 buf2, sizeof(buf2), 375 RPP_ECHO_OFF | RPP_REQUIRE_TTY); 376 if (p == NULL) { 377 bzero(buf1, sizeof(buf1)); 378 gctl_error(req, 379 "Cannot read passphrase: %s.", 380 strerror(errno)); 381 return (NULL); 382 } 383 384 if (strcmp(buf1, buf2) != 0) { 385 bzero(buf2, sizeof(buf2)); 386 fprintf(stderr, "They didn't match.\n"); 387 continue; 388 } 389 bzero(buf2, sizeof(buf2)); 390 } 391 break; 392 } 393 /* 394 * Field md_iterations equal to -1 means "choose some sane 395 * value for me". 396 */ 397 if (md->md_iterations == -1) { 398 assert(new); 399 if (verbose) 400 printf("Calculating number of iterations...\n"); 401 md->md_iterations = pkcs5v2_calculate(2000000); 402 assert(md->md_iterations > 0); 403 if (verbose) { 404 printf("Done, using %d iterations.\n", 405 md->md_iterations); 406 } 407 } 408 /* 409 * If md_iterations is equal to 0, user don't want PKCS#5v2. 410 */ 411 if (md->md_iterations == 0) { 412 g_eli_crypto_hmac_update(&ctx, md->md_salt, 413 sizeof(md->md_salt)); 414 g_eli_crypto_hmac_update(&ctx, buf1, strlen(buf1)); 415 } else /* if (md->md_iterations > 0) */ { 416 unsigned char dkey[G_ELI_USERKEYLEN]; 417 418 pkcs5v2_genkey(dkey, sizeof(dkey), md->md_salt, 419 sizeof(md->md_salt), buf1, md->md_iterations); 420 g_eli_crypto_hmac_update(&ctx, dkey, sizeof(dkey)); 421 bzero(dkey, sizeof(dkey)); 422 } 423 bzero(buf1, sizeof(buf1)); 424 } 425 g_eli_crypto_hmac_final(&ctx, key, 0); 426 return (key); 427} 428 429static int 430eli_metadata_read(struct gctl_req *req, const char *prov, 431 struct g_eli_metadata *md) 432{ 433 unsigned char sector[sizeof(struct g_eli_metadata)]; 434 int error; 435 436 if (g_get_sectorsize(prov) == 0) { 437 int fd; 438 439 /* This is a file probably. */ 440 fd = open(prov, O_RDONLY); 441 if (fd == -1) { 442 gctl_error(req, "Cannot open %s: %s.", prov, 443 strerror(errno)); 444 return (-1); 445 } 446 if (read(fd, sector, sizeof(sector)) != sizeof(sector)) { 447 gctl_error(req, "Cannot read metadata from %s: %s.", 448 prov, strerror(errno)); 449 close(fd); 450 return (-1); 451 } 452 close(fd); 453 } else { 454 /* This is a GEOM provider. */ 455 error = g_metadata_read(prov, sector, sizeof(sector), 456 G_ELI_MAGIC); 457 if (error != 0) { 458 gctl_error(req, "Cannot read metadata from %s: %s.", 459 prov, strerror(error)); 460 return (-1); 461 } 462 } 463 if (eli_metadata_decode(sector, md) != 0) { 464 gctl_error(req, "MD5 hash mismatch for %s.", prov); 465 return (-1); 466 } 467 return (0); 468} 469 470static int 471eli_metadata_store(struct gctl_req *req, const char *prov, 472 struct g_eli_metadata *md) 473{ 474 unsigned char sector[sizeof(struct g_eli_metadata)]; 475 int error; 476 477 eli_metadata_encode(md, sector); 478 if (g_get_sectorsize(prov) == 0) { 479 int fd; 480 481 /* This is a file probably. */ 482 fd = open(prov, O_WRONLY | O_TRUNC); 483 if (fd == -1) { 484 gctl_error(req, "Cannot open %s: %s.", prov, 485 strerror(errno)); 486 bzero(sector, sizeof(sector)); 487 return (-1); 488 } 489 if (write(fd, sector, sizeof(sector)) != sizeof(sector)) { 490 gctl_error(req, "Cannot write metadata to %s: %s.", 491 prov, strerror(errno)); 492 bzero(sector, sizeof(sector)); 493 close(fd); 494 return (-1); 495 } 496 close(fd); 497 } else { 498 /* This is a GEOM provider. */ 499 error = g_metadata_store(prov, sector, sizeof(sector)); 500 if (error != 0) { 501 gctl_error(req, "Cannot write metadata to %s: %s.", 502 prov, strerror(errno)); 503 bzero(sector, sizeof(sector)); 504 return (-1); 505 } 506 } 507 bzero(sector, sizeof(sector)); 508 return (0); 509} 510 511static void 512eli_init(struct gctl_req *req) 513{ 514 struct g_eli_metadata md; 515 unsigned char sector[sizeof(struct g_eli_metadata)]; 516 unsigned char key[G_ELI_USERKEYLEN]; 517 const char *str, *prov; 518 unsigned secsize; 519 off_t mediasize; 520 intmax_t val; 521 int error, nargs; 522 523 nargs = gctl_get_int(req, "nargs"); 524 if (nargs != 1) { 525 gctl_error(req, "Invalid number of arguments."); 526 return; 527 } 528 prov = gctl_get_ascii(req, "arg0"); 529 mediasize = g_get_mediasize(prov); 530 secsize = g_get_sectorsize(prov); 531 if (mediasize == 0 || secsize == 0) { 532 gctl_error(req, "Cannot get informations about %s: %s.", prov, 533 strerror(errno)); 534 return; 535 } 536 537 bzero(&md, sizeof(md)); 538 strlcpy(md.md_magic, G_ELI_MAGIC, sizeof(md.md_magic)); 539 md.md_version = G_ELI_VERSION; 540 md.md_flags = 0; 541 if (gctl_get_int(req, "boot")) 542 md.md_flags |= G_ELI_FLAG_BOOT; 543 md.md_ealgo = CRYPTO_ALGORITHM_MIN - 1; 544 str = gctl_get_ascii(req, "aalgo"); 545 if (strcmp(str, "none") != 0) { 546 md.md_aalgo = g_eli_str2aalgo(str); 547 if (md.md_aalgo >= CRYPTO_ALGORITHM_MIN && 548 md.md_aalgo <= CRYPTO_ALGORITHM_MAX) { 549 md.md_flags |= G_ELI_FLAG_AUTH; 550 } else { 551 /* 552 * For backward compatibility, check if the -a option 553 * was used to provide encryption algorithm. 554 */ 555 md.md_ealgo = g_eli_str2ealgo(str); 556 if (md.md_ealgo < CRYPTO_ALGORITHM_MIN || 557 md.md_ealgo > CRYPTO_ALGORITHM_MAX) { 558 gctl_error(req, 559 "Invalid authentication algorithm."); 560 return; 561 } else { 562 fprintf(stderr, "warning: The -e option, not " 563 "the -a option is now used to specify " 564 "encryption algorithm to use.\n"); 565 } 566 } 567 } 568 if (md.md_ealgo < CRYPTO_ALGORITHM_MIN || 569 md.md_ealgo > CRYPTO_ALGORITHM_MAX) { 570 str = gctl_get_ascii(req, "ealgo"); 571 md.md_ealgo = g_eli_str2ealgo(str); 572 if (md.md_ealgo < CRYPTO_ALGORITHM_MIN || 573 md.md_ealgo > CRYPTO_ALGORITHM_MAX) { 574 gctl_error(req, "Invalid encryption algorithm."); 575 return; 576 } 577 } 578 val = gctl_get_intmax(req, "keylen"); 579 md.md_keylen = val; 580 md.md_keylen = g_eli_keylen(md.md_ealgo, md.md_keylen); 581 if (md.md_keylen == 0) { 582 gctl_error(req, "Invalid key length."); 583 return; 584 } 585 md.md_provsize = mediasize; 586 587 val = gctl_get_intmax(req, "iterations"); 588 if (val != -1) { 589 int nonewpassphrase; 590 591 /* 592 * Don't allow to set iterations when there will be no 593 * passphrase. 594 */ 595 nonewpassphrase = gctl_get_int(req, "nonewpassphrase"); 596 if (nonewpassphrase) { 597 gctl_error(req, 598 "Options -i and -P are mutually exclusive."); 599 return; 600 } 601 } 602 md.md_iterations = val; 603 604 val = gctl_get_intmax(req, "sectorsize"); 605 if (val == 0) 606 md.md_sectorsize = secsize; 607 else { 608 if (val < 0 || (val % secsize) != 0) { 609 gctl_error(req, "Invalid sector size."); 610 return; 611 } 612 md.md_sectorsize = val; 613 } 614 615 md.md_keys = 0x01; 616 arc4rand(md.md_salt, sizeof(md.md_salt)); 617 arc4rand(md.md_mkeys, sizeof(md.md_mkeys)); 618 619 /* Generate user key. */ 620 if (eli_genkey(req, &md, key, 1) == NULL) { 621 bzero(key, sizeof(key)); 622 bzero(&md, sizeof(md)); 623 return; 624 } 625 626 /* Encrypt the first and the only Master Key. */ 627 error = g_eli_mkey_encrypt(md.md_ealgo, key, md.md_keylen, md.md_mkeys); 628 bzero(key, sizeof(key)); 629 if (error != 0) { 630 bzero(&md, sizeof(md)); 631 gctl_error(req, "Cannot encrypt Master Key: %s.", 632 strerror(error)); 633 return; 634 } 635 636 eli_metadata_encode(&md, sector); 637 bzero(&md, sizeof(md)); 638 error = g_metadata_store(prov, sector, sizeof(sector)); 639 bzero(sector, sizeof(sector)); 640 if (error != 0) { 641 gctl_error(req, "Cannot store metadata on %s: %s.", prov, 642 strerror(error)); 643 return; 644 } 645 if (verbose) 646 printf("Metadata value stored on %s.\n", prov); 647} 648 649static void 650eli_attach(struct gctl_req *req) 651{ 652 struct g_eli_metadata md; 653 unsigned char key[G_ELI_USERKEYLEN]; 654 const char *prov; 655 int nargs; 656 657 nargs = gctl_get_int(req, "nargs"); 658 if (nargs != 1) { 659 gctl_error(req, "Invalid number of arguments."); 660 return; 661 } 662 prov = gctl_get_ascii(req, "arg0"); 663 664 if (eli_metadata_read(req, prov, &md) == -1) 665 return; 666 667 if (eli_genkey(req, &md, key, 0) == NULL) { 668 bzero(key, sizeof(key)); 669 return; 670 } 671 672 gctl_ro_param(req, "key", sizeof(key), key); 673 if (gctl_issue(req) == NULL) { 674 if (verbose) 675 printf("Attched to %s.\n", prov); 676 } 677 bzero(key, sizeof(key)); 678} 679 680static void
|
| 681eli_configure_detached(struct gctl_req *req, const char *prov, int boot) 682{ 683 struct g_eli_metadata md; 684 685 if (eli_metadata_read(req, prov, &md) == -1) 686 return; 687 688 if (boot && (md.md_flags & G_ELI_FLAG_BOOT)) { 689 if (verbose) 690 printf("BOOT flag already configured for %s.\n", prov); 691 } else if (!boot && !(md.md_flags & G_ELI_FLAG_BOOT)) { 692 if (verbose) 693 printf("BOOT flag not configured for %s.\n", prov); 694 } else { 695 if (boot) 696 md.md_flags |= G_ELI_FLAG_BOOT; 697 else 698 md.md_flags &= ~G_ELI_FLAG_BOOT; 699 eli_metadata_store(req, prov, &md); 700 } 701 bzero(&md, sizeof(md)); 702} 703 704static void 705eli_configure(struct gctl_req *req) 706{ 707 const char *prov; 708 int i, nargs, boot, noboot; 709 710 nargs = gctl_get_int(req, "nargs"); 711 if (nargs == 0) { 712 gctl_error(req, "Too few arguments."); 713 return; 714 } 715 716 boot = gctl_get_int(req, "boot"); 717 noboot = gctl_get_int(req, "noboot"); 718 719 if (boot && noboot) { 720 gctl_error(req, "Options -b and -B are mutually exclusive."); 721 return; 722 } 723 if (!boot && !noboot) { 724 gctl_error(req, "No option given."); 725 return; 726 } 727 728 /* First attached providers. */ 729 gctl_issue(req); 730 /* Now the rest. */ 731 for (i = 0; i < nargs; i++) { 732 prov = gctl_get_ascii(req, "arg%d", i); 733 if (!eli_is_attached(prov)) 734 eli_configure_detached(req, prov, boot); 735 } 736} 737 738static void
|
669eli_setkey_attached(struct gctl_req *req, struct g_eli_metadata *md) 670{ 671 unsigned char key[G_ELI_USERKEYLEN]; 672 intmax_t val; 673 674 val = gctl_get_intmax(req, "iterations"); 675 /* Check if iterations number should be changed. */ 676 if (val != -1) 677 md->md_iterations = val; 678 679 /* Generate key for Master Key encryption. */ 680 if (eli_genkey(req, md, key, 1) == NULL) { 681 bzero(key, sizeof(key)); 682 return; 683 } 684 685 gctl_ro_param(req, "key", sizeof(key), key); 686 gctl_issue(req); 687 bzero(key, sizeof(key)); 688} 689 690static void 691eli_setkey_detached(struct gctl_req *req, const char *prov, 692 struct g_eli_metadata *md) 693{ 694 unsigned char key[G_ELI_USERKEYLEN], mkey[G_ELI_DATAIVKEYLEN]; 695 unsigned char *mkeydst; 696 intmax_t val; 697 unsigned nkey; 698 int error; 699 700 if (md->md_keys == 0) { 701 gctl_error(req, "No valid keys on %s.", prov); 702 return; 703 } 704 705 /* Generate key for Master Key decryption. */ 706 if (eli_genkey(req, md, key, 0) == NULL) { 707 bzero(key, sizeof(key)); 708 return; 709 } 710 711 /* Decrypt Master Key. */ 712 error = g_eli_mkey_decrypt(md, key, mkey, &nkey); 713 bzero(key, sizeof(key)); 714 if (error != 0) { 715 bzero(md, sizeof(*md)); 716 if (error == -1) 717 gctl_error(req, "Wrong key for %s.", prov); 718 else /* if (error > 0) */ { 719 gctl_error(req, "Cannot decrypt Master Key: %s.", 720 strerror(error)); 721 } 722 return; 723 } 724 if (verbose) 725 printf("Decrypted Master Key %u.\n", nkey); 726 727 val = gctl_get_intmax(req, "keyno"); 728 if (val != -1) 729 nkey = val; 730#if 0 731 else 732 ; /* Use the key number which was found during decryption. */ 733#endif 734 if (nkey >= G_ELI_MAXMKEYS) { 735 gctl_error(req, "Invalid '%s' argument.", "keyno"); 736 return; 737 } 738 739 val = gctl_get_intmax(req, "iterations"); 740 /* Check if iterations number should and can be changed. */ 741 if (val != -1) { 742 if (bitcount32(md->md_keys) != 1) { 743 gctl_error(req, "To be able to use '-i' option, only " 744 "one key can be defined."); 745 return; 746 } 747 if (md->md_keys != (1 << nkey)) { 748 gctl_error(req, "Only already defined key can be " 749 "changed when '-i' option is used."); 750 return; 751 } 752 md->md_iterations = val; 753 } 754 755 mkeydst = md->md_mkeys + nkey * G_ELI_MKEYLEN; 756 md->md_keys |= (1 << nkey); 757 758 bcopy(mkey, mkeydst, sizeof(mkey)); 759 bzero(mkey, sizeof(mkey)); 760 761 /* Generate key for Master Key encryption. */ 762 if (eli_genkey(req, md, key, 1) == NULL) { 763 bzero(key, sizeof(key)); 764 bzero(md, sizeof(*md)); 765 return; 766 } 767 768 /* Encrypt the Master-Key with the new key. */ 769 error = g_eli_mkey_encrypt(md->md_ealgo, key, md->md_keylen, mkeydst); 770 bzero(key, sizeof(key)); 771 if (error != 0) { 772 bzero(md, sizeof(*md)); 773 gctl_error(req, "Cannot encrypt Master Key: %s.", 774 strerror(error)); 775 return; 776 } 777 778 /* Store metadata with fresh key. */ 779 eli_metadata_store(req, prov, md); 780 bzero(md, sizeof(*md)); 781} 782 783static void 784eli_setkey(struct gctl_req *req) 785{ 786 struct g_eli_metadata md; 787 const char *prov; 788 int nargs; 789 790 nargs = gctl_get_int(req, "nargs"); 791 if (nargs != 1) { 792 gctl_error(req, "Invalid number of arguments."); 793 return; 794 } 795 prov = gctl_get_ascii(req, "arg0"); 796 797 if (eli_metadata_read(req, prov, &md) == -1) 798 return; 799 800 if (eli_is_attached(prov)) 801 eli_setkey_attached(req, &md); 802 else 803 eli_setkey_detached(req, prov, &md); 804} 805 806static void 807eli_delkey_attached(struct gctl_req *req, const char *prov __unused) 808{ 809 810 gctl_issue(req); 811} 812 813static void 814eli_delkey_detached(struct gctl_req *req, const char *prov) 815{ 816 struct g_eli_metadata md; 817 unsigned char *mkeydst; 818 intmax_t val; 819 unsigned nkey; 820 int all, force; 821 822 if (eli_metadata_read(req, prov, &md) == -1) 823 return; 824 825 all = gctl_get_int(req, "all"); 826 if (all) 827 arc4rand(md.md_mkeys, sizeof(md.md_mkeys)); 828 else { 829 force = gctl_get_int(req, "force"); 830 val = gctl_get_intmax(req, "keyno"); 831 if (val == -1) { 832 gctl_error(req, "Key number has to be specified."); 833 return; 834 } 835 nkey = val; 836 if (nkey >= G_ELI_MAXMKEYS) { 837 gctl_error(req, "Invalid '%s' argument.", "keyno"); 838 return; 839 } 840 if (!(md.md_keys & (1 << nkey)) && !force) { 841 gctl_error(req, "Master Key %u is not set.", nkey); 842 return; 843 } 844 md.md_keys &= ~(1 << nkey); 845 if (md.md_keys == 0 && !force) { 846 gctl_error(req, "This is the last Master Key. Use '-f' " 847 "option if you really want to remove it."); 848 return; 849 } 850 mkeydst = md.md_mkeys + nkey * G_ELI_MKEYLEN; 851 arc4rand(mkeydst, G_ELI_MKEYLEN); 852 } 853 854 eli_metadata_store(req, prov, &md); 855 bzero(&md, sizeof(md)); 856} 857 858static void 859eli_delkey(struct gctl_req *req) 860{ 861 const char *prov; 862 int nargs; 863 864 nargs = gctl_get_int(req, "nargs"); 865 if (nargs != 1) { 866 gctl_error(req, "Invalid number of arguments."); 867 return; 868 } 869 prov = gctl_get_ascii(req, "arg0"); 870 871 if (eli_is_attached(prov)) 872 eli_delkey_attached(req, prov); 873 else 874 eli_delkey_detached(req, prov); 875} 876 877static void 878eli_kill_detached(struct gctl_req *req, const char *prov) 879{ 880 struct g_eli_metadata md; 881 int error; 882 883 /* 884 * NOTE: Maybe we should verify if this is geli provider first, 885 * but 'kill' command is quite critical so better don't waste 886 * the time. 887 */ 888#if 0 889 error = g_metadata_read(prov, (unsigned char *)&md, sizeof(md), 890 G_ELI_MAGIC); 891 if (error != 0) { 892 gctl_error(req, "Cannot read metadata from %s: %s.", prov, 893 strerror(error)); 894 return; 895 } 896#endif 897 898 arc4rand((unsigned char *)&md, sizeof(md)); 899 error = g_metadata_store(prov, (unsigned char *)&md, sizeof(md)); 900 if (error != 0) { 901 gctl_error(req, "Cannot write metadata to %s: %s.", prov, 902 strerror(error)); 903 } 904} 905 906static void 907eli_kill(struct gctl_req *req) 908{ 909 const char *prov; 910 int i, nargs, all; 911 912 nargs = gctl_get_int(req, "nargs"); 913 all = gctl_get_int(req, "all"); 914 if (!all && nargs == 0) { 915 gctl_error(req, "Too few arguments."); 916 return; 917 } 918 /* 919 * How '-a' option combine with a list of providers: 920 * Delete Master Keys from all attached providers: 921 * geli kill -a 922 * Delete Master Keys from all attached provider and from 923 * detached da0 and da1: 924 * geli kill -a da0 da1 925 * Delete Master Keys from (attached or detached) da0 and da1: 926 * geli kill da0 da1 927 */ 928 929 /* First detached provider. */ 930 for (i = 0; i < nargs; i++) { 931 prov = gctl_get_ascii(req, "arg%d", i); 932 if (!eli_is_attached(prov)) 933 eli_kill_detached(req, prov); 934 } 935 /* Now attached providers. */ 936 gctl_issue(req); 937} 938 939static void 940eli_backup(struct gctl_req *req) 941{ 942 struct g_eli_metadata md; 943 const char *file, *prov; 944 unsigned secsize; 945 unsigned char *sector; 946 off_t mediasize; 947 int nargs, filefd, provfd; 948 949 nargs = gctl_get_int(req, "nargs"); 950 if (nargs != 2) { 951 gctl_error(req, "Invalid number of arguments."); 952 return; 953 } 954 prov = gctl_get_ascii(req, "arg0"); 955 file = gctl_get_ascii(req, "arg1"); 956 957 provfd = filefd = -1; 958 sector = NULL; 959 secsize = 0; 960 961 provfd = open(prov, O_RDONLY); 962 if (provfd == -1 && errno == ENOENT && prov[0] != '/') { 963 char devprov[MAXPATHLEN]; 964 965 snprintf(devprov, sizeof(devprov), "%s%s", _PATH_DEV, prov); 966 provfd = open(devprov, O_RDONLY); 967 } 968 if (provfd == -1) { 969 gctl_error(req, "Cannot open %s: %s.", prov, strerror(errno)); 970 return; 971 } 972 filefd = open(file, O_WRONLY | O_TRUNC | O_CREAT, 0600); 973 if (filefd == -1) { 974 gctl_error(req, "Cannot open %s: %s.", file, strerror(errno)); 975 goto out; 976 } 977 978 mediasize = g_get_mediasize(prov); 979 secsize = g_get_sectorsize(prov); 980 if (mediasize == 0 || secsize == 0) { 981 gctl_error(req, "Cannot get informations about %s: %s.", prov, 982 strerror(errno)); 983 return; 984 } 985 986 sector = malloc(secsize); 987 if (sector == NULL) { 988 gctl_error(req, "Cannot allocate memory."); 989 return; 990 } 991 992 /* Read metadata from the provider. */ 993 if (pread(provfd, sector, secsize, mediasize - secsize) != 994 (ssize_t)secsize) { 995 gctl_error(req, "Cannot read metadata: %s.", strerror(errno)); 996 goto out; 997 } 998 /* Check if this is geli provider. */ 999 if (eli_metadata_decode(sector, &md) != 0) { 1000 gctl_error(req, "MD5 hash mismatch: not a geli provider?"); 1001 goto out; 1002 } 1003 /* Write metadata to the destination file. */ 1004 if (write(filefd, sector, secsize) != (ssize_t)secsize) { 1005 gctl_error(req, "Cannot write to %s: %s.", file, 1006 strerror(errno)); 1007 goto out; 1008 } 1009out: 1010 if (provfd > 0) 1011 close(provfd); 1012 if (filefd > 0) 1013 close(filefd); 1014 if (sector != NULL) { 1015 bzero(sector, secsize); 1016 free(sector); 1017 } 1018} 1019 1020static void 1021eli_restore(struct gctl_req *req) 1022{ 1023 struct g_eli_metadata md; 1024 const char *file, *prov; 1025 unsigned char *sector; 1026 unsigned secsize; 1027 off_t mediasize; 1028 int nargs, filefd, provfd; 1029 1030 nargs = gctl_get_int(req, "nargs"); 1031 if (nargs != 2) { 1032 gctl_error(req, "Invalid number of arguments."); 1033 return; 1034 } 1035 file = gctl_get_ascii(req, "arg0"); 1036 prov = gctl_get_ascii(req, "arg1"); 1037 1038 provfd = filefd = -1; 1039 sector = NULL; 1040 secsize = 0; 1041 1042 filefd = open(file, O_RDONLY); 1043 if (filefd == -1) { 1044 gctl_error(req, "Cannot open %s: %s.", file, strerror(errno)); 1045 goto out; 1046 } 1047 provfd = open(prov, O_WRONLY); 1048 if (provfd == -1 && errno == ENOENT && prov[0] != '/') { 1049 char devprov[MAXPATHLEN]; 1050 1051 snprintf(devprov, sizeof(devprov), "%s%s", _PATH_DEV, prov); 1052 provfd = open(devprov, O_WRONLY); 1053 } 1054 if (provfd == -1) { 1055 gctl_error(req, "Cannot open %s: %s.", prov, strerror(errno)); 1056 return; 1057 } 1058 1059 mediasize = g_get_mediasize(prov); 1060 secsize = g_get_sectorsize(prov); 1061 if (mediasize == 0 || secsize == 0) { 1062 gctl_error(req, "Cannot get informations about %s: %s.", prov, 1063 strerror(errno)); 1064 return; 1065 } 1066 1067 sector = malloc(secsize); 1068 if (sector == NULL) { 1069 gctl_error(req, "Cannot allocate memory."); 1070 return; 1071 } 1072 1073 /* Read metadata from the backup file. */ 1074 if (read(filefd, sector, secsize) != (ssize_t)secsize) { 1075 gctl_error(req, "Cannot read from %s: %s.", file, 1076 strerror(errno)); 1077 goto out; 1078 } 1079 /* Check if this file contains geli metadata. */ 1080 if (eli_metadata_decode(sector, &md) != 0) { 1081 gctl_error(req, "MD5 hash mismatch: not a geli backup file?"); 1082 goto out; 1083 } 1084 /* Read metadata from the provider. */ 1085 if (pwrite(provfd, sector, secsize, mediasize - secsize) != 1086 (ssize_t)secsize) { 1087 gctl_error(req, "Cannot write metadata: %s.", strerror(errno)); 1088 goto out; 1089 } 1090out: 1091 if (provfd > 0) 1092 close(provfd); 1093 if (filefd > 0) 1094 close(filefd); 1095 if (sector != NULL) { 1096 bzero(sector, secsize); 1097 free(sector); 1098 } 1099} 1100 1101static void 1102eli_clear(struct gctl_req *req) 1103{ 1104 const char *name; 1105 int error, i, nargs; 1106 1107 nargs = gctl_get_int(req, "nargs"); 1108 if (nargs < 1) { 1109 gctl_error(req, "Too few arguments."); 1110 return; 1111 } 1112 1113 for (i = 0; i < nargs; i++) { 1114 name = gctl_get_ascii(req, "arg%d", i); 1115 error = g_metadata_clear(name, G_ELI_MAGIC); 1116 if (error != 0) { 1117 fprintf(stderr, "Cannot clear metadata on %s: %s.\n", 1118 name, strerror(error)); 1119 gctl_error(req, "Not fully done."); 1120 continue; 1121 } 1122 if (verbose) 1123 printf("Metadata cleared on %s.\n", name); 1124 } 1125} 1126 1127static void 1128eli_dump(struct gctl_req *req) 1129{ 1130 struct g_eli_metadata md, tmpmd; 1131 const char *name; 1132 int error, i, nargs; 1133 1134 nargs = gctl_get_int(req, "nargs"); 1135 if (nargs < 1) { 1136 gctl_error(req, "Too few arguments."); 1137 return; 1138 } 1139 1140 for (i = 0; i < nargs; i++) { 1141 name = gctl_get_ascii(req, "arg%d", i); 1142 error = g_metadata_read(name, (unsigned char *)&tmpmd, 1143 sizeof(tmpmd), G_ELI_MAGIC); 1144 if (error != 0) { 1145 fprintf(stderr, "Cannot read metadata from %s: %s.\n", 1146 name, strerror(error)); 1147 gctl_error(req, "Not fully done."); 1148 continue; 1149 } 1150 if (eli_metadata_decode((unsigned char *)&tmpmd, &md) != 0) { 1151 fprintf(stderr, "MD5 hash mismatch for %s, skipping.\n", 1152 name); 1153 gctl_error(req, "Not fully done."); 1154 continue; 1155 } 1156 printf("Metadata on %s:\n", name); 1157 eli_metadata_dump(&md); 1158 printf("\n"); 1159 } 1160}
| 739eli_setkey_attached(struct gctl_req *req, struct g_eli_metadata *md) 740{ 741 unsigned char key[G_ELI_USERKEYLEN]; 742 intmax_t val; 743 744 val = gctl_get_intmax(req, "iterations"); 745 /* Check if iterations number should be changed. */ 746 if (val != -1) 747 md->md_iterations = val; 748 749 /* Generate key for Master Key encryption. */ 750 if (eli_genkey(req, md, key, 1) == NULL) { 751 bzero(key, sizeof(key)); 752 return; 753 } 754 755 gctl_ro_param(req, "key", sizeof(key), key); 756 gctl_issue(req); 757 bzero(key, sizeof(key)); 758} 759 760static void 761eli_setkey_detached(struct gctl_req *req, const char *prov, 762 struct g_eli_metadata *md) 763{ 764 unsigned char key[G_ELI_USERKEYLEN], mkey[G_ELI_DATAIVKEYLEN]; 765 unsigned char *mkeydst; 766 intmax_t val; 767 unsigned nkey; 768 int error; 769 770 if (md->md_keys == 0) { 771 gctl_error(req, "No valid keys on %s.", prov); 772 return; 773 } 774 775 /* Generate key for Master Key decryption. */ 776 if (eli_genkey(req, md, key, 0) == NULL) { 777 bzero(key, sizeof(key)); 778 return; 779 } 780 781 /* Decrypt Master Key. */ 782 error = g_eli_mkey_decrypt(md, key, mkey, &nkey); 783 bzero(key, sizeof(key)); 784 if (error != 0) { 785 bzero(md, sizeof(*md)); 786 if (error == -1) 787 gctl_error(req, "Wrong key for %s.", prov); 788 else /* if (error > 0) */ { 789 gctl_error(req, "Cannot decrypt Master Key: %s.", 790 strerror(error)); 791 } 792 return; 793 } 794 if (verbose) 795 printf("Decrypted Master Key %u.\n", nkey); 796 797 val = gctl_get_intmax(req, "keyno"); 798 if (val != -1) 799 nkey = val; 800#if 0 801 else 802 ; /* Use the key number which was found during decryption. */ 803#endif 804 if (nkey >= G_ELI_MAXMKEYS) { 805 gctl_error(req, "Invalid '%s' argument.", "keyno"); 806 return; 807 } 808 809 val = gctl_get_intmax(req, "iterations"); 810 /* Check if iterations number should and can be changed. */ 811 if (val != -1) { 812 if (bitcount32(md->md_keys) != 1) { 813 gctl_error(req, "To be able to use '-i' option, only " 814 "one key can be defined."); 815 return; 816 } 817 if (md->md_keys != (1 << nkey)) { 818 gctl_error(req, "Only already defined key can be " 819 "changed when '-i' option is used."); 820 return; 821 } 822 md->md_iterations = val; 823 } 824 825 mkeydst = md->md_mkeys + nkey * G_ELI_MKEYLEN; 826 md->md_keys |= (1 << nkey); 827 828 bcopy(mkey, mkeydst, sizeof(mkey)); 829 bzero(mkey, sizeof(mkey)); 830 831 /* Generate key for Master Key encryption. */ 832 if (eli_genkey(req, md, key, 1) == NULL) { 833 bzero(key, sizeof(key)); 834 bzero(md, sizeof(*md)); 835 return; 836 } 837 838 /* Encrypt the Master-Key with the new key. */ 839 error = g_eli_mkey_encrypt(md->md_ealgo, key, md->md_keylen, mkeydst); 840 bzero(key, sizeof(key)); 841 if (error != 0) { 842 bzero(md, sizeof(*md)); 843 gctl_error(req, "Cannot encrypt Master Key: %s.", 844 strerror(error)); 845 return; 846 } 847 848 /* Store metadata with fresh key. */ 849 eli_metadata_store(req, prov, md); 850 bzero(md, sizeof(*md)); 851} 852 853static void 854eli_setkey(struct gctl_req *req) 855{ 856 struct g_eli_metadata md; 857 const char *prov; 858 int nargs; 859 860 nargs = gctl_get_int(req, "nargs"); 861 if (nargs != 1) { 862 gctl_error(req, "Invalid number of arguments."); 863 return; 864 } 865 prov = gctl_get_ascii(req, "arg0"); 866 867 if (eli_metadata_read(req, prov, &md) == -1) 868 return; 869 870 if (eli_is_attached(prov)) 871 eli_setkey_attached(req, &md); 872 else 873 eli_setkey_detached(req, prov, &md); 874} 875 876static void 877eli_delkey_attached(struct gctl_req *req, const char *prov __unused) 878{ 879 880 gctl_issue(req); 881} 882 883static void 884eli_delkey_detached(struct gctl_req *req, const char *prov) 885{ 886 struct g_eli_metadata md; 887 unsigned char *mkeydst; 888 intmax_t val; 889 unsigned nkey; 890 int all, force; 891 892 if (eli_metadata_read(req, prov, &md) == -1) 893 return; 894 895 all = gctl_get_int(req, "all"); 896 if (all) 897 arc4rand(md.md_mkeys, sizeof(md.md_mkeys)); 898 else { 899 force = gctl_get_int(req, "force"); 900 val = gctl_get_intmax(req, "keyno"); 901 if (val == -1) { 902 gctl_error(req, "Key number has to be specified."); 903 return; 904 } 905 nkey = val; 906 if (nkey >= G_ELI_MAXMKEYS) { 907 gctl_error(req, "Invalid '%s' argument.", "keyno"); 908 return; 909 } 910 if (!(md.md_keys & (1 << nkey)) && !force) { 911 gctl_error(req, "Master Key %u is not set.", nkey); 912 return; 913 } 914 md.md_keys &= ~(1 << nkey); 915 if (md.md_keys == 0 && !force) { 916 gctl_error(req, "This is the last Master Key. Use '-f' " 917 "option if you really want to remove it."); 918 return; 919 } 920 mkeydst = md.md_mkeys + nkey * G_ELI_MKEYLEN; 921 arc4rand(mkeydst, G_ELI_MKEYLEN); 922 } 923 924 eli_metadata_store(req, prov, &md); 925 bzero(&md, sizeof(md)); 926} 927 928static void 929eli_delkey(struct gctl_req *req) 930{ 931 const char *prov; 932 int nargs; 933 934 nargs = gctl_get_int(req, "nargs"); 935 if (nargs != 1) { 936 gctl_error(req, "Invalid number of arguments."); 937 return; 938 } 939 prov = gctl_get_ascii(req, "arg0"); 940 941 if (eli_is_attached(prov)) 942 eli_delkey_attached(req, prov); 943 else 944 eli_delkey_detached(req, prov); 945} 946 947static void 948eli_kill_detached(struct gctl_req *req, const char *prov) 949{ 950 struct g_eli_metadata md; 951 int error; 952 953 /* 954 * NOTE: Maybe we should verify if this is geli provider first, 955 * but 'kill' command is quite critical so better don't waste 956 * the time. 957 */ 958#if 0 959 error = g_metadata_read(prov, (unsigned char *)&md, sizeof(md), 960 G_ELI_MAGIC); 961 if (error != 0) { 962 gctl_error(req, "Cannot read metadata from %s: %s.", prov, 963 strerror(error)); 964 return; 965 } 966#endif 967 968 arc4rand((unsigned char *)&md, sizeof(md)); 969 error = g_metadata_store(prov, (unsigned char *)&md, sizeof(md)); 970 if (error != 0) { 971 gctl_error(req, "Cannot write metadata to %s: %s.", prov, 972 strerror(error)); 973 } 974} 975 976static void 977eli_kill(struct gctl_req *req) 978{ 979 const char *prov; 980 int i, nargs, all; 981 982 nargs = gctl_get_int(req, "nargs"); 983 all = gctl_get_int(req, "all"); 984 if (!all && nargs == 0) { 985 gctl_error(req, "Too few arguments."); 986 return; 987 } 988 /* 989 * How '-a' option combine with a list of providers: 990 * Delete Master Keys from all attached providers: 991 * geli kill -a 992 * Delete Master Keys from all attached provider and from 993 * detached da0 and da1: 994 * geli kill -a da0 da1 995 * Delete Master Keys from (attached or detached) da0 and da1: 996 * geli kill da0 da1 997 */ 998 999 /* First detached provider. */ 1000 for (i = 0; i < nargs; i++) { 1001 prov = gctl_get_ascii(req, "arg%d", i); 1002 if (!eli_is_attached(prov)) 1003 eli_kill_detached(req, prov); 1004 } 1005 /* Now attached providers. */ 1006 gctl_issue(req); 1007} 1008 1009static void 1010eli_backup(struct gctl_req *req) 1011{ 1012 struct g_eli_metadata md; 1013 const char *file, *prov; 1014 unsigned secsize; 1015 unsigned char *sector; 1016 off_t mediasize; 1017 int nargs, filefd, provfd; 1018 1019 nargs = gctl_get_int(req, "nargs"); 1020 if (nargs != 2) { 1021 gctl_error(req, "Invalid number of arguments."); 1022 return; 1023 } 1024 prov = gctl_get_ascii(req, "arg0"); 1025 file = gctl_get_ascii(req, "arg1"); 1026 1027 provfd = filefd = -1; 1028 sector = NULL; 1029 secsize = 0; 1030 1031 provfd = open(prov, O_RDONLY); 1032 if (provfd == -1 && errno == ENOENT && prov[0] != '/') { 1033 char devprov[MAXPATHLEN]; 1034 1035 snprintf(devprov, sizeof(devprov), "%s%s", _PATH_DEV, prov); 1036 provfd = open(devprov, O_RDONLY); 1037 } 1038 if (provfd == -1) { 1039 gctl_error(req, "Cannot open %s: %s.", prov, strerror(errno)); 1040 return; 1041 } 1042 filefd = open(file, O_WRONLY | O_TRUNC | O_CREAT, 0600); 1043 if (filefd == -1) { 1044 gctl_error(req, "Cannot open %s: %s.", file, strerror(errno)); 1045 goto out; 1046 } 1047 1048 mediasize = g_get_mediasize(prov); 1049 secsize = g_get_sectorsize(prov); 1050 if (mediasize == 0 || secsize == 0) { 1051 gctl_error(req, "Cannot get informations about %s: %s.", prov, 1052 strerror(errno)); 1053 return; 1054 } 1055 1056 sector = malloc(secsize); 1057 if (sector == NULL) { 1058 gctl_error(req, "Cannot allocate memory."); 1059 return; 1060 } 1061 1062 /* Read metadata from the provider. */ 1063 if (pread(provfd, sector, secsize, mediasize - secsize) != 1064 (ssize_t)secsize) { 1065 gctl_error(req, "Cannot read metadata: %s.", strerror(errno)); 1066 goto out; 1067 } 1068 /* Check if this is geli provider. */ 1069 if (eli_metadata_decode(sector, &md) != 0) { 1070 gctl_error(req, "MD5 hash mismatch: not a geli provider?"); 1071 goto out; 1072 } 1073 /* Write metadata to the destination file. */ 1074 if (write(filefd, sector, secsize) != (ssize_t)secsize) { 1075 gctl_error(req, "Cannot write to %s: %s.", file, 1076 strerror(errno)); 1077 goto out; 1078 } 1079out: 1080 if (provfd > 0) 1081 close(provfd); 1082 if (filefd > 0) 1083 close(filefd); 1084 if (sector != NULL) { 1085 bzero(sector, secsize); 1086 free(sector); 1087 } 1088} 1089 1090static void 1091eli_restore(struct gctl_req *req) 1092{ 1093 struct g_eli_metadata md; 1094 const char *file, *prov; 1095 unsigned char *sector; 1096 unsigned secsize; 1097 off_t mediasize; 1098 int nargs, filefd, provfd; 1099 1100 nargs = gctl_get_int(req, "nargs"); 1101 if (nargs != 2) { 1102 gctl_error(req, "Invalid number of arguments."); 1103 return; 1104 } 1105 file = gctl_get_ascii(req, "arg0"); 1106 prov = gctl_get_ascii(req, "arg1"); 1107 1108 provfd = filefd = -1; 1109 sector = NULL; 1110 secsize = 0; 1111 1112 filefd = open(file, O_RDONLY); 1113 if (filefd == -1) { 1114 gctl_error(req, "Cannot open %s: %s.", file, strerror(errno)); 1115 goto out; 1116 } 1117 provfd = open(prov, O_WRONLY); 1118 if (provfd == -1 && errno == ENOENT && prov[0] != '/') { 1119 char devprov[MAXPATHLEN]; 1120 1121 snprintf(devprov, sizeof(devprov), "%s%s", _PATH_DEV, prov); 1122 provfd = open(devprov, O_WRONLY); 1123 } 1124 if (provfd == -1) { 1125 gctl_error(req, "Cannot open %s: %s.", prov, strerror(errno)); 1126 return; 1127 } 1128 1129 mediasize = g_get_mediasize(prov); 1130 secsize = g_get_sectorsize(prov); 1131 if (mediasize == 0 || secsize == 0) { 1132 gctl_error(req, "Cannot get informations about %s: %s.", prov, 1133 strerror(errno)); 1134 return; 1135 } 1136 1137 sector = malloc(secsize); 1138 if (sector == NULL) { 1139 gctl_error(req, "Cannot allocate memory."); 1140 return; 1141 } 1142 1143 /* Read metadata from the backup file. */ 1144 if (read(filefd, sector, secsize) != (ssize_t)secsize) { 1145 gctl_error(req, "Cannot read from %s: %s.", file, 1146 strerror(errno)); 1147 goto out; 1148 } 1149 /* Check if this file contains geli metadata. */ 1150 if (eli_metadata_decode(sector, &md) != 0) { 1151 gctl_error(req, "MD5 hash mismatch: not a geli backup file?"); 1152 goto out; 1153 } 1154 /* Read metadata from the provider. */ 1155 if (pwrite(provfd, sector, secsize, mediasize - secsize) != 1156 (ssize_t)secsize) { 1157 gctl_error(req, "Cannot write metadata: %s.", strerror(errno)); 1158 goto out; 1159 } 1160out: 1161 if (provfd > 0) 1162 close(provfd); 1163 if (filefd > 0) 1164 close(filefd); 1165 if (sector != NULL) { 1166 bzero(sector, secsize); 1167 free(sector); 1168 } 1169} 1170 1171static void 1172eli_clear(struct gctl_req *req) 1173{ 1174 const char *name; 1175 int error, i, nargs; 1176 1177 nargs = gctl_get_int(req, "nargs"); 1178 if (nargs < 1) { 1179 gctl_error(req, "Too few arguments."); 1180 return; 1181 } 1182 1183 for (i = 0; i < nargs; i++) { 1184 name = gctl_get_ascii(req, "arg%d", i); 1185 error = g_metadata_clear(name, G_ELI_MAGIC); 1186 if (error != 0) { 1187 fprintf(stderr, "Cannot clear metadata on %s: %s.\n", 1188 name, strerror(error)); 1189 gctl_error(req, "Not fully done."); 1190 continue; 1191 } 1192 if (verbose) 1193 printf("Metadata cleared on %s.\n", name); 1194 } 1195} 1196 1197static void 1198eli_dump(struct gctl_req *req) 1199{ 1200 struct g_eli_metadata md, tmpmd; 1201 const char *name; 1202 int error, i, nargs; 1203 1204 nargs = gctl_get_int(req, "nargs"); 1205 if (nargs < 1) { 1206 gctl_error(req, "Too few arguments."); 1207 return; 1208 } 1209 1210 for (i = 0; i < nargs; i++) { 1211 name = gctl_get_ascii(req, "arg%d", i); 1212 error = g_metadata_read(name, (unsigned char *)&tmpmd, 1213 sizeof(tmpmd), G_ELI_MAGIC); 1214 if (error != 0) { 1215 fprintf(stderr, "Cannot read metadata from %s: %s.\n", 1216 name, strerror(error)); 1217 gctl_error(req, "Not fully done."); 1218 continue; 1219 } 1220 if (eli_metadata_decode((unsigned char *)&tmpmd, &md) != 0) { 1221 fprintf(stderr, "MD5 hash mismatch for %s, skipping.\n", 1222 name); 1223 gctl_error(req, "Not fully done."); 1224 continue; 1225 } 1226 printf("Metadata on %s:\n", name); 1227 eli_metadata_dump(&md); 1228 printf("\n"); 1229 } 1230}
|