1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 * Copyright 2012 Joyent, Inc. All rights reserved. 25 * 26 * Copyright 2013 Nexenta Systems, Inc. All rights reserved. 27 * Copyright (c) 2014 Gary Mills 28 * Copyright (c) 2016 Andrey Sokolov 29 */ 30 31 /* 32 * lofiadm - administer lofi(7d). Very simple, add and remove file<->device 33 * associations, and display status. All the ioctls are private between 34 * lofi and lofiadm, and so are very simple - device information is 35 * communicated via a minor number. 36 */ 37 38 #include <sys/types.h> 39 #include <sys/param.h> 40 #include <sys/lofi.h> 41 #include <sys/stat.h> 42 #include <sys/sysmacros.h> 43 #include <sys/modctl.h> 44 #include <netinet/in.h> 45 #include <stdio.h> 46 #include <fcntl.h> 47 #include <locale.h> 48 #include <string.h> 49 #include <strings.h> 50 #include <errno.h> 51 #include <stdlib.h> 52 #include <unistd.h> 53 #include <stropts.h> 54 #include <libdevinfo.h> 55 #include <libgen.h> 56 #include <ctype.h> 57 #include <dlfcn.h> 58 #include <limits.h> 59 #include <security/cryptoki.h> 60 #include <cryptoutil.h> 61 #include <sys/crypto/ioctl.h> 62 #include <sys/crypto/ioctladmin.h> 63 #include <sys/cmlb.h> 64 #include <sys/mkdev.h> 65 #include "utils.h" 66 #include <LzmaEnc.h> 67 68 /* Only need the IV len #defines out of these files, nothing else. */ 69 #include <aes/aes_impl.h> 70 #include <des/des_impl.h> 71 #include <blowfish/blowfish_impl.h> 72 73 static const char USAGE[] = 74 "Usage: %s [-r] [-l] -a file [ device ]\n" 75 " %s [-r] -c crypto_algorithm -a file [device]\n" 76 " %s [-r] -c crypto_algorithm -k raw_key_file -a file [device]\n" 77 " %s [-r] -c crypto_algorithm -T [token]:[manuf]:[serial]:key " 78 "-a file [device]\n" 79 " %s [-r] -c crypto_algorithm -T [token]:[manuf]:[serial]:key " 80 "-k wrapped_key_file -a file [device]\n" 81 " %s [-r] -c crypto_algorithm -e -a file [device]\n" 82 " %s -d file | device\n" 83 " %s -C [gzip|gzip-6|gzip-9|lzma] [-s segment_size] file\n" 84 " %s -U file\n" 85 " %s [ file | device ]\n"; 86 87 typedef struct token_spec { 88 char *name; 89 char *mfr; 90 char *serno; 91 char *key; 92 } token_spec_t; 93 94 typedef struct mech_alias { 95 char *alias; 96 CK_MECHANISM_TYPE type; 97 char *name; /* for ioctl */ 98 char *iv_name; /* for ioctl */ 99 size_t iv_len; /* for ioctl */ 100 iv_method_t iv_type; /* for ioctl */ 101 size_t min_keysize; /* in bytes */ 102 size_t max_keysize; /* in bytes */ 103 token_spec_t *token; 104 CK_SLOT_ID slot; 105 } mech_alias_t; 106 107 static mech_alias_t mech_aliases[] = { 108 /* Preferred one should always be listed first. */ 109 { "aes-256-cbc", CKM_AES_CBC, "CKM_AES_CBC", "CKM_AES_ECB", AES_IV_LEN, 110 IVM_ENC_BLKNO, ULONG_MAX, 0L, NULL, (CK_SLOT_ID) -1 }, 111 { "aes-192-cbc", CKM_AES_CBC, "CKM_AES_CBC", "CKM_AES_ECB", AES_IV_LEN, 112 IVM_ENC_BLKNO, ULONG_MAX, 0L, NULL, (CK_SLOT_ID) -1 }, 113 { "aes-128-cbc", CKM_AES_CBC, "CKM_AES_CBC", "CKM_AES_ECB", AES_IV_LEN, 114 IVM_ENC_BLKNO, ULONG_MAX, 0L, NULL, (CK_SLOT_ID) -1 }, 115 { "des3-cbc", CKM_DES3_CBC, "CKM_DES3_CBC", "CKM_DES3_ECB", DES_IV_LEN, 116 IVM_ENC_BLKNO, ULONG_MAX, 0L, NULL, (CK_SLOT_ID)-1 }, 117 { "blowfish-cbc", CKM_BLOWFISH_CBC, "CKM_BLOWFISH_CBC", 118 "CKM_BLOWFISH_ECB", BLOWFISH_IV_LEN, IVM_ENC_BLKNO, ULONG_MAX, 119 0L, NULL, (CK_SLOT_ID)-1 } 120 /* 121 * A cipher without an iv requirement would look like this: 122 * { "aes-xex", CKM_AES_XEX, "CKM_AES_XEX", NULL, 0, 123 * IVM_NONE, ULONG_MAX, 0L, NULL, (CK_SLOT_ID)-1 } 124 */ 125 }; 126 127 int mech_aliases_count = (sizeof (mech_aliases) / sizeof (mech_alias_t)); 128 129 /* Preferred cipher, if one isn't specified on command line. */ 130 #define DEFAULT_CIPHER (&mech_aliases[0]) 131 132 #define DEFAULT_CIPHER_NUM 64 /* guess # kernel ciphers available */ 133 #define DEFAULT_MECHINFO_NUM 16 /* guess # kernel mechs available */ 134 #define MIN_PASSLEN 8 /* min acceptable passphrase size */ 135 136 static int gzip_compress(void *src, size_t srclen, void *dst, 137 size_t *destlen, int level); 138 static int lzma_compress(void *src, size_t srclen, void *dst, 139 size_t *destlen, int level); 140 141 lofi_compress_info_t lofi_compress_table[LOFI_COMPRESS_FUNCTIONS] = { 142 {NULL, gzip_compress, 6, "gzip"}, /* default */ 143 {NULL, gzip_compress, 6, "gzip-6"}, 144 {NULL, gzip_compress, 9, "gzip-9"}, 145 {NULL, lzma_compress, 0, "lzma"} 146 }; 147 148 /* For displaying lofi mappings */ 149 #define FORMAT "%-20s %-30s %s\n" 150 151 #define COMPRESS_ALGORITHM "gzip" 152 #define COMPRESS_THRESHOLD 2048 153 #define SEGSIZE 131072 154 #define BLOCK_SIZE 512 155 #define KILOBYTE 1024 156 #define MEGABYTE (KILOBYTE * KILOBYTE) 157 #define GIGABYTE (KILOBYTE * MEGABYTE) 158 #define LIBZ "libz.so.1" 159 160 const char lofi_crypto_magic[6] = LOFI_CRYPTO_MAGIC; 161 162 static void 163 usage(const char *pname) 164 { 165 (void) fprintf(stderr, gettext(USAGE), pname, pname, pname, 166 pname, pname, pname, pname, pname, pname, pname); 167 exit(E_USAGE); 168 } 169 170 static int 171 gzip_compress(void *src, size_t srclen, void *dst, size_t *dstlen, int level) 172 { 173 static int (*compress2p)(void *, ulong_t *, void *, size_t, int) = NULL; 174 void *libz_hdl = NULL; 175 176 /* 177 * The first time we are called, attempt to dlopen() 178 * libz.so.1 and get a pointer to the compress2() function 179 */ 180 if (compress2p == NULL) { 181 if ((libz_hdl = openlib(LIBZ)) == NULL) 182 die(gettext("could not find %s. " 183 "gzip compression unavailable\n"), LIBZ); 184 185 if ((compress2p = 186 (int (*)(void *, ulong_t *, void *, size_t, int)) 187 dlsym(libz_hdl, "compress2")) == NULL) { 188 closelib(); 189 die(gettext("could not find the correct %s. " 190 "gzip compression unavailable\n"), LIBZ); 191 } 192 } 193 194 if ((*compress2p)(dst, (ulong_t *)dstlen, src, srclen, level) != 0) 195 return (-1); 196 return (0); 197 } 198 199 /*ARGSUSED*/ 200 static void 201 *SzAlloc(void *p, size_t size) 202 { 203 return (malloc(size)); 204 } 205 206 /*ARGSUSED*/ 207 static void 208 SzFree(void *p, void *address, size_t size) 209 { 210 free(address); 211 } 212 213 static ISzAlloc g_Alloc = { 214 SzAlloc, 215 SzFree 216 }; 217 218 #define LZMA_UNCOMPRESSED_SIZE 8 219 #define LZMA_HEADER_SIZE (LZMA_PROPS_SIZE + LZMA_UNCOMPRESSED_SIZE) 220 221 /*ARGSUSED*/ 222 static int 223 lzma_compress(void *src, size_t srclen, void *dst, 224 size_t *dstlen, int level) 225 { 226 CLzmaEncProps props; 227 size_t outsize2; 228 size_t outsizeprocessed; 229 size_t outpropssize = LZMA_PROPS_SIZE; 230 uint64_t t = 0; 231 SRes res; 232 Byte *dstp; 233 int i; 234 235 outsize2 = *dstlen; 236 237 LzmaEncProps_Init(&props); 238 239 /* 240 * The LZMA compressed file format is as follows - 241 * 242 * Offset Size(bytes) Description 243 * 0 1 LZMA properties (lc, lp, lp (encoded)) 244 * 1 4 Dictionary size (little endian) 245 * 5 8 Uncompressed size (little endian) 246 * 13 Compressed data 247 */ 248 249 /* set the dictionary size to be 8MB */ 250 props.dictSize = 1 << 23; 251 252 if (*dstlen < LZMA_HEADER_SIZE) 253 return (SZ_ERROR_OUTPUT_EOF); 254 255 dstp = (Byte *)dst; 256 t = srclen; 257 /* 258 * Set the uncompressed size in the LZMA header 259 * The LZMA properties (specified in 'props') 260 * will be set by the call to LzmaEncode() 261 */ 262 for (i = 0; i < LZMA_UNCOMPRESSED_SIZE; i++, t >>= 8) { 263 dstp[LZMA_PROPS_SIZE + i] = (Byte)t; 264 } 265 266 outsizeprocessed = outsize2 - LZMA_HEADER_SIZE; 267 res = LzmaEncode(dstp + LZMA_HEADER_SIZE, &outsizeprocessed, 268 src, srclen, &props, dstp, &outpropssize, 0, NULL, 269 &g_Alloc, &g_Alloc); 270 271 if (res != 0) 272 return (-1); 273 274 *dstlen = outsizeprocessed + LZMA_HEADER_SIZE; 275 return (0); 276 } 277 278 /* 279 * Translate a lofi device name to a minor number. We might be asked 280 * to do this when there is no association (such as when the user specifies 281 * a particular device), so we can only look at the string. 282 */ 283 static int 284 name_to_minor(const char *devicename) 285 { 286 struct stat st; 287 288 /* 289 * If devicename does not exist, then devicename contains 290 * the name of the device to be created. 291 * Note we only allow non-labeled devices here. 292 */ 293 if (stat(devicename, &st)) { 294 int minor, rv; 295 296 rv = sscanf(devicename, "/dev/" LOFI_BLOCK_NAME "/%d", &minor); 297 if (rv == 1) 298 return (minor); 299 rv = sscanf(devicename, "/dev/" LOFI_CHAR_NAME "/%d", &minor); 300 if (rv == 1) 301 return (minor); 302 303 return (0); 304 } 305 306 /* 307 * For disk devices we use modctl(MODGETNAME) to read driver name 308 * for major device. 309 */ 310 if (st.st_mode & S_IFCHR || st.st_mode & S_IFBLK) { 311 major_t maj; 312 char mname[MODMAXNAMELEN]; 313 314 maj = major(st.st_rdev); 315 316 if (modctl(MODGETNAME, mname, MODMAXNAMELEN, &maj) == 0) { 317 if (strncmp(mname, LOFI_DRIVER_NAME, 318 sizeof (LOFI_DRIVER_NAME)) == 0) { 319 return (LOFI_MINOR2ID(minor(st.st_rdev))); 320 } 321 } 322 } 323 324 return (0); 325 } 326 327 /* 328 * This might be the first time we've used this minor number. If so, 329 * it might also be that the /dev links are in the process of being created 330 * by devfsadmd (or that they'll be created "soon"). We cannot return 331 * until they're there or the invoker of lofiadm might try to use them 332 * and not find them. This can happen if a shell script is running on 333 * an MP. 334 */ 335 static int sleeptime = 2; /* number of seconds to sleep between stat's */ 336 static int maxsleep = 120; /* maximum number of seconds to sleep */ 337 338 static void 339 make_blkdevname(struct lofi_ioctl *li, char *path, size_t len) 340 { 341 char *r1, *r2; 342 size_t l1; 343 344 if (li->li_devpath[0] == '\0') { 345 if (li->li_labeled) 346 (void) strlcpy(path, "unknown", len); 347 else 348 (void) snprintf(path, len, 349 "/dev/" LOFI_BLOCK_NAME "/%d", li->li_id); 350 return; 351 } 352 (void) strlcpy(path, li->li_devpath, len); 353 r1 = strchr(path, 'r'); 354 l1 = r1 - path; 355 r2 = strchr(li->li_devpath, 'r'); 356 (void) strlcpy(r1, r2+1, len - l1); 357 358 if (li->li_labeled) { 359 (void) strlcat(path, "p0", len); 360 } 361 } 362 363 static void 364 wait_until_dev_complete(struct lofi_ioctl *li) 365 { 366 struct stat64 buf; 367 int cursleep; 368 char blkpath[MAXPATHLEN]; 369 char charpath[MAXPATHLEN]; 370 di_devlink_handle_t hdl; 371 372 make_blkdevname(li, blkpath, sizeof (blkpath)); 373 (void) strlcpy(charpath, li->li_devpath, sizeof (charpath)); 374 375 if (li->li_labeled) { 376 (void) strlcat(charpath, "p0", sizeof (charpath)); 377 } 378 379 /* Check if links already present */ 380 if (stat64(blkpath, &buf) == 0 && stat64(charpath, &buf) == 0) 381 return; 382 383 /* First use di_devlink_init() */ 384 if (hdl = di_devlink_init("lofi", DI_MAKE_LINK)) { 385 (void) di_devlink_fini(&hdl); 386 goto out; 387 } 388 389 /* 390 * Under normal conditions, di_devlink_init(DI_MAKE_LINK) above will 391 * only fail if the caller is non-root. In that case, wait for 392 * link creation via sysevents. 393 */ 394 for (cursleep = 0; cursleep < maxsleep; cursleep += sleeptime) { 395 if (stat64(blkpath, &buf) == 0 && stat64(charpath, &buf) == 0) 396 return; 397 (void) sleep(sleeptime); 398 } 399 400 /* one last try */ 401 out: 402 if (stat64(blkpath, &buf) == -1) { 403 die(gettext("%s was not created"), blkpath); 404 } 405 if (stat64(charpath, &buf) == -1) { 406 die(gettext("%s was not created"), charpath); 407 } 408 } 409 410 /* 411 * Map the file and return the minor number the driver picked for the file 412 * DO NOT use this function if the filename is actually the device name. 413 */ 414 static int 415 lofi_map_file(int lfd, struct lofi_ioctl *li, const char *filename) 416 { 417 int minor; 418 419 li->li_id = 0; 420 (void) strlcpy(li->li_filename, filename, sizeof (li->li_filename)); 421 minor = ioctl(lfd, LOFI_MAP_FILE, li); 422 if (minor == -1) { 423 if (errno == ENOTSUP) 424 warn(gettext("encrypting compressed files is " 425 "unsupported")); 426 die(gettext("could not map file %s"), filename); 427 } 428 wait_until_dev_complete(li); 429 return (minor); 430 } 431 432 /* 433 * Add a device association. If devicename is NULL, let the driver 434 * pick a device. 435 */ 436 static void 437 add_mapping(int lfd, const char *devicename, const char *filename, 438 mech_alias_t *cipher, const char *rkey, size_t rksz, boolean_t rdonly, 439 boolean_t label) 440 { 441 struct lofi_ioctl li; 442 443 bzero(&li, sizeof (li)); 444 li.li_readonly = rdonly; 445 li.li_labeled = label; 446 447 li.li_crypto_enabled = B_FALSE; 448 if (cipher != NULL) { 449 /* set up encryption for mapped file */ 450 li.li_crypto_enabled = B_TRUE; 451 (void) strlcpy(li.li_cipher, cipher->name, 452 sizeof (li.li_cipher)); 453 if (rksz > sizeof (li.li_key)) { 454 die(gettext("key too large")); 455 } 456 bcopy(rkey, li.li_key, rksz); 457 li.li_key_len = rksz << 3; /* convert to bits */ 458 459 li.li_iv_type = cipher->iv_type; 460 li.li_iv_len = cipher->iv_len; /* 0 when no iv needed */ 461 switch (cipher->iv_type) { 462 case IVM_ENC_BLKNO: 463 (void) strlcpy(li.li_iv_cipher, cipher->iv_name, 464 sizeof (li.li_iv_cipher)); 465 break; 466 case IVM_NONE: 467 /* FALLTHROUGH */ 468 default: 469 break; 470 } 471 } 472 473 if (devicename == NULL) { 474 int minor; 475 char path[MAXPATHLEN]; 476 477 /* pick one via the driver */ 478 minor = lofi_map_file(lfd, &li, filename); 479 if (minor > 0) { 480 make_blkdevname(&li, path, sizeof (path)); 481 482 /* if mapping succeeds, print the one picked */ 483 (void) printf("%s\n", path); 484 } 485 return; 486 } 487 488 /* use device we were given */ 489 li.li_id = name_to_minor(devicename); 490 if (li.li_id == 0) { 491 die(gettext("malformed device name %s\n"), devicename); 492 } 493 (void) strlcpy(li.li_filename, filename, sizeof (li.li_filename)); 494 495 /* if device is already in use li.li_minor won't change */ 496 if (ioctl(lfd, LOFI_MAP_FILE_MINOR, &li) == -1) { 497 if (errno == ENOTSUP) 498 warn(gettext("encrypting compressed files is " 499 "unsupported")); 500 die(gettext("could not map file %s to %s"), filename, 501 devicename); 502 } 503 wait_until_dev_complete(&li); 504 } 505 506 /* 507 * Remove an association. Delete by device name if non-NULL, or by 508 * filename otherwise. 509 */ 510 static void 511 delete_mapping(int lfd, const char *devicename, const char *filename, 512 boolean_t force) 513 { 514 struct lofi_ioctl li; 515 516 li.li_force = force; 517 li.li_cleanup = B_FALSE; 518 519 if (devicename == NULL) { 520 /* delete by filename */ 521 (void) strlcpy(li.li_filename, filename, 522 sizeof (li.li_filename)); 523 li.li_id = 0; 524 if (ioctl(lfd, LOFI_UNMAP_FILE, &li) == -1) { 525 die(gettext("could not unmap file %s"), filename); 526 } 527 return; 528 } 529 530 /* delete by device */ 531 li.li_id = name_to_minor(devicename); 532 if (li.li_id == 0) { 533 die(gettext("malformed device name %s\n"), devicename); 534 } 535 if (ioctl(lfd, LOFI_UNMAP_FILE_MINOR, &li) == -1) { 536 die(gettext("could not unmap device %s"), devicename); 537 } 538 } 539 540 /* 541 * Show filename given devicename, or devicename given filename. 542 */ 543 static void 544 print_one_mapping(int lfd, const char *devicename, const char *filename) 545 { 546 struct lofi_ioctl li; 547 char blkpath[MAXPATHLEN]; 548 549 if (devicename == NULL) { 550 /* given filename, print devicename */ 551 li.li_id = 0; 552 (void) strlcpy(li.li_filename, filename, 553 sizeof (li.li_filename)); 554 if (ioctl(lfd, LOFI_GET_MINOR, &li) == -1) { 555 die(gettext("could not find device for %s"), filename); 556 } 557 make_blkdevname(&li, blkpath, sizeof (blkpath)); 558 (void) printf("%s\n", blkpath); 559 return; 560 } 561 562 /* given devicename, print filename */ 563 li.li_id = name_to_minor(devicename); 564 if (li.li_id == 0) { 565 die(gettext("malformed device name %s\n"), devicename); 566 } 567 if (ioctl(lfd, LOFI_GET_FILENAME, &li) == -1) { 568 die(gettext("could not find filename for %s"), devicename); 569 } 570 (void) printf("%s\n", li.li_filename); 571 } 572 573 /* 574 * Print the list of all the mappings, including a header. 575 */ 576 static void 577 print_mappings(int fd) 578 { 579 struct lofi_ioctl li; 580 int minor; 581 int maxminor; 582 char path[MAXPATHLEN]; 583 char options[MAXPATHLEN] = { 0 }; 584 585 li.li_id = 0; 586 if (ioctl(fd, LOFI_GET_MAXMINOR, &li) == -1) { 587 die("ioctl"); 588 } 589 maxminor = li.li_id; 590 591 (void) printf(FORMAT, gettext("Block Device"), gettext("File"), 592 gettext("Options")); 593 for (minor = 1; minor <= maxminor; minor++) { 594 li.li_id = minor; 595 if (ioctl(fd, LOFI_GET_FILENAME, &li) == -1) { 596 if (errno == ENXIO) 597 continue; 598 warn("ioctl"); 599 break; 600 } 601 make_blkdevname(&li, path, sizeof (path)); 602 603 options[0] = '\0'; 604 605 /* 606 * Encrypted lofi and compressed lofi are mutually exclusive. 607 */ 608 if (li.li_crypto_enabled) 609 (void) snprintf(options, sizeof (options), 610 gettext("Encrypted")); 611 else if (li.li_algorithm[0] != '\0') 612 (void) snprintf(options, sizeof (options), 613 gettext("Compressed(%s)"), li.li_algorithm); 614 if (li.li_readonly) { 615 if (strlen(options) != 0) { 616 (void) strlcat(options, ",Readonly", 617 sizeof (options)); 618 } else { 619 (void) snprintf(options, sizeof (options), 620 gettext("Readonly")); 621 } 622 } 623 if (li.li_labeled) { 624 if (strlen(options) != 0) { 625 (void) strlcat(options, ",Labeled", 626 sizeof (options)); 627 } else { 628 (void) snprintf(options, sizeof (options), 629 gettext("Labeled")); 630 } 631 } 632 if (strlen(options) == 0) 633 (void) snprintf(options, sizeof (options), "-"); 634 635 (void) printf(FORMAT, path, li.li_filename, options); 636 } 637 } 638 639 /* 640 * Verify the cipher selected by user. 641 */ 642 static mech_alias_t * 643 ciph2mech(const char *alias) 644 { 645 int i; 646 647 for (i = 0; i < mech_aliases_count; i++) { 648 if (strcasecmp(alias, mech_aliases[i].alias) == 0) 649 return (&mech_aliases[i]); 650 } 651 return (NULL); 652 } 653 654 /* 655 * Verify user selected cipher is also available in kernel. 656 * 657 * While traversing kernel list of mechs, if the cipher is supported in the 658 * kernel for both encryption and decryption, it also picks up the min/max 659 * key size. 660 */ 661 static boolean_t 662 kernel_cipher_check(mech_alias_t *cipher) 663 { 664 boolean_t ciph_ok = B_FALSE; 665 boolean_t iv_ok = B_FALSE; 666 int i; 667 int count; 668 crypto_get_mechanism_list_t *kciphers = NULL; 669 crypto_get_all_mechanism_info_t *kinfo = NULL; 670 int fd = -1; 671 size_t keymin; 672 size_t keymax; 673 674 /* if cipher doesn't need iv generating mech, bypass that check now */ 675 if (cipher->iv_name == NULL) 676 iv_ok = B_TRUE; 677 678 /* allocate some space for the list of kernel ciphers */ 679 count = DEFAULT_CIPHER_NUM; 680 kciphers = malloc(sizeof (crypto_get_mechanism_list_t) + 681 sizeof (crypto_mech_name_t) * (count - 1)); 682 if (kciphers == NULL) 683 die(gettext("failed to allocate memory for list of " 684 "kernel mechanisms")); 685 kciphers->ml_count = count; 686 687 /* query crypto device to get list of kernel ciphers */ 688 if ((fd = open("/dev/crypto", O_RDWR)) == -1) { 689 warn(gettext("failed to open %s"), "/dev/crypto"); 690 goto kcc_out; 691 } 692 693 if (ioctl(fd, CRYPTO_GET_MECHANISM_LIST, kciphers) == -1) { 694 warn(gettext("CRYPTO_GET_MECHANISM_LIST ioctl failed")); 695 goto kcc_out; 696 } 697 698 if (kciphers->ml_return_value == CRYPTO_BUFFER_TOO_SMALL) { 699 count = kciphers->ml_count; 700 free(kciphers); 701 kciphers = malloc(sizeof (crypto_get_mechanism_list_t) + 702 sizeof (crypto_mech_name_t) * (count - 1)); 703 if (kciphers == NULL) { 704 warn(gettext("failed to allocate memory for list of " 705 "kernel mechanisms")); 706 goto kcc_out; 707 } 708 kciphers->ml_count = count; 709 710 if (ioctl(fd, CRYPTO_GET_MECHANISM_LIST, kciphers) == -1) { 711 warn(gettext("CRYPTO_GET_MECHANISM_LIST ioctl failed")); 712 goto kcc_out; 713 } 714 } 715 716 if (kciphers->ml_return_value != CRYPTO_SUCCESS) { 717 warn(gettext( 718 "CRYPTO_GET_MECHANISM_LIST ioctl return value = %d\n"), 719 kciphers->ml_return_value); 720 goto kcc_out; 721 } 722 723 /* 724 * scan list of kernel ciphers looking for the selected one and if 725 * it needs an iv generated using another cipher, also look for that 726 * additional cipher to be used for generating the iv 727 */ 728 count = kciphers->ml_count; 729 for (i = 0; i < count && !(ciph_ok && iv_ok); i++) { 730 if (!ciph_ok && 731 strcasecmp(cipher->name, kciphers->ml_list[i]) == 0) 732 ciph_ok = B_TRUE; 733 if (!iv_ok && 734 strcasecmp(cipher->iv_name, kciphers->ml_list[i]) == 0) 735 iv_ok = B_TRUE; 736 } 737 free(kciphers); 738 kciphers = NULL; 739 740 if (!ciph_ok) 741 warn(gettext("%s mechanism not supported in kernel\n"), 742 cipher->name); 743 if (!iv_ok) 744 warn(gettext("%s mechanism not supported in kernel\n"), 745 cipher->iv_name); 746 747 if (ciph_ok) { 748 /* Get the details about the user selected cipher */ 749 count = DEFAULT_MECHINFO_NUM; 750 kinfo = malloc(sizeof (crypto_get_all_mechanism_info_t) + 751 sizeof (crypto_mechanism_info_t) * (count - 1)); 752 if (kinfo == NULL) { 753 warn(gettext("failed to allocate memory for " 754 "kernel mechanism info")); 755 goto kcc_out; 756 } 757 kinfo->mi_count = count; 758 (void) strlcpy(kinfo->mi_mechanism_name, cipher->name, 759 CRYPTO_MAX_MECH_NAME); 760 761 if (ioctl(fd, CRYPTO_GET_ALL_MECHANISM_INFO, kinfo) == -1) { 762 warn(gettext( 763 "CRYPTO_GET_ALL_MECHANISM_INFO ioctl failed")); 764 goto kcc_out; 765 } 766 767 if (kinfo->mi_return_value == CRYPTO_BUFFER_TOO_SMALL) { 768 count = kinfo->mi_count; 769 free(kinfo); 770 kinfo = malloc( 771 sizeof (crypto_get_all_mechanism_info_t) + 772 sizeof (crypto_mechanism_info_t) * (count - 1)); 773 if (kinfo == NULL) { 774 warn(gettext("failed to allocate memory for " 775 "kernel mechanism info")); 776 goto kcc_out; 777 } 778 kinfo->mi_count = count; 779 (void) strlcpy(kinfo->mi_mechanism_name, cipher->name, 780 CRYPTO_MAX_MECH_NAME); 781 782 if (ioctl(fd, CRYPTO_GET_ALL_MECHANISM_INFO, kinfo) == 783 -1) { 784 warn(gettext("CRYPTO_GET_ALL_MECHANISM_INFO " 785 "ioctl failed")); 786 goto kcc_out; 787 } 788 } 789 790 if (kinfo->mi_return_value != CRYPTO_SUCCESS) { 791 warn(gettext("CRYPTO_GET_ALL_MECHANISM_INFO ioctl " 792 "return value = %d\n"), kinfo->mi_return_value); 793 goto kcc_out; 794 } 795 796 /* Set key min and max size */ 797 count = kinfo->mi_count; 798 i = 0; 799 if (i < count) { 800 keymin = kinfo->mi_list[i].mi_min_key_size; 801 keymax = kinfo->mi_list[i].mi_max_key_size; 802 if (kinfo->mi_list[i].mi_keysize_unit & 803 CRYPTO_KEYSIZE_UNIT_IN_BITS) { 804 keymin = CRYPTO_BITS2BYTES(keymin); 805 keymax = CRYPTO_BITS2BYTES(keymax); 806 807 } 808 cipher->min_keysize = keymin; 809 cipher->max_keysize = keymax; 810 } 811 free(kinfo); 812 kinfo = NULL; 813 814 if (i == count) { 815 (void) close(fd); 816 die(gettext( 817 "failed to find usable %s kernel mechanism, " 818 "use \"cryptoadm list -m\" to find available " 819 "mechanisms\n"), 820 cipher->name); 821 } 822 } 823 824 /* Note: key min/max, unit size, usage for iv cipher are not checked. */ 825 826 return (ciph_ok && iv_ok); 827 828 kcc_out: 829 if (kinfo != NULL) 830 free(kinfo); 831 if (kciphers != NULL) 832 free(kciphers); 833 if (fd != -1) 834 (void) close(fd); 835 return (B_FALSE); 836 } 837 838 /* 839 * Break up token spec into its components (non-destructive) 840 */ 841 static token_spec_t * 842 parsetoken(char *spec) 843 { 844 #define FLD_NAME 0 845 #define FLD_MANUF 1 846 #define FLD_SERIAL 2 847 #define FLD_LABEL 3 848 #define NFIELDS 4 849 #define nullfield(i) ((field[(i)+1] - field[(i)]) <= 1) 850 #define copyfield(fld, i) \ 851 { \ 852 int n; \ 853 (fld) = NULL; \ 854 if ((n = (field[(i)+1] - field[(i)])) > 1) { \ 855 if (((fld) = malloc(n)) != NULL) { \ 856 (void) strncpy((fld), field[(i)], n); \ 857 ((fld))[n - 1] = '\0'; \ 858 } \ 859 } \ 860 } 861 862 int i; 863 char *field[NFIELDS + 1]; /* +1 to catch extra delimiters */ 864 token_spec_t *ti = NULL; 865 866 if (spec == NULL) 867 return (NULL); 868 869 /* 870 * Correct format is "[name]:[manuf]:[serial]:key". Can't use 871 * strtok because it treats ":::key" and "key:::" and "key" all 872 * as the same thing, and we can't have the :s compressed away. 873 */ 874 field[0] = spec; 875 for (i = 1; i < NFIELDS + 1; i++) { 876 field[i] = strchr(field[i-1], ':'); 877 if (field[i] == NULL) 878 break; 879 field[i]++; 880 } 881 if (i < NFIELDS) /* not enough fields */ 882 return (NULL); 883 if (field[NFIELDS] != NULL) /* too many fields */ 884 return (NULL); 885 field[NFIELDS] = strchr(field[NFIELDS-1], '\0') + 1; 886 887 /* key label can't be empty */ 888 if (nullfield(FLD_LABEL)) 889 return (NULL); 890 891 ti = malloc(sizeof (token_spec_t)); 892 if (ti == NULL) 893 return (NULL); 894 895 copyfield(ti->name, FLD_NAME); 896 copyfield(ti->mfr, FLD_MANUF); 897 copyfield(ti->serno, FLD_SERIAL); 898 copyfield(ti->key, FLD_LABEL); 899 900 /* 901 * If token specified and it only contains a key label, then 902 * search all tokens for the key, otherwise only those with 903 * matching name, mfr, and serno are used. 904 */ 905 /* 906 * That's how we'd like it to be, however, if only the key label 907 * is specified, default to using softtoken. It's easier. 908 */ 909 if (ti->name == NULL && ti->mfr == NULL && ti->serno == NULL) 910 ti->name = strdup(pkcs11_default_token()); 911 return (ti); 912 } 913 914 /* 915 * PBE the passphrase into a raw key 916 */ 917 static void 918 getkeyfromuser(mech_alias_t *cipher, char **raw_key, size_t *raw_key_sz, 919 boolean_t with_confirmation) 920 { 921 CK_SESSION_HANDLE sess; 922 CK_RV rv; 923 char *pass = NULL; 924 size_t passlen = 0; 925 void *salt = NULL; /* don't use NULL, see note on salt below */ 926 size_t saltlen = 0; 927 CK_KEY_TYPE ktype; 928 void *kvalue; 929 size_t klen; 930 931 /* did init_crypto find a slot that supports this cipher? */ 932 if (cipher->slot == (CK_SLOT_ID)-1 || cipher->max_keysize == 0) { 933 rv = CKR_MECHANISM_INVALID; 934 goto cleanup; 935 } 936 937 rv = pkcs11_mech2keytype(cipher->type, &ktype); 938 if (rv != CKR_OK) 939 goto cleanup; 940 941 /* 942 * use the passphrase to generate a PBE PKCS#5 secret key and 943 * retrieve the raw key data to eventually pass it to the kernel; 944 */ 945 rv = C_OpenSession(cipher->slot, CKF_SERIAL_SESSION, NULL, NULL, &sess); 946 if (rv != CKR_OK) 947 goto cleanup; 948 949 /* get user passphrase with 8 byte minimum */ 950 if (pkcs11_get_pass(NULL, &pass, &passlen, MIN_PASSLEN, 951 with_confirmation) < 0) { 952 die(gettext("passphrases do not match\n")); 953 } 954 955 /* 956 * salt should not be NULL, or else pkcs11_PasswdToKey() will 957 * complain about CKR_MECHANISM_PARAM_INVALID; the following is 958 * to make up for not having a salt until a proper one is used 959 */ 960 salt = pass; 961 saltlen = passlen; 962 963 klen = cipher->max_keysize; 964 rv = pkcs11_PasswdToKey(sess, pass, passlen, salt, saltlen, ktype, 965 cipher->max_keysize, &kvalue, &klen); 966 967 (void) C_CloseSession(sess); 968 969 if (rv != CKR_OK) { 970 goto cleanup; 971 } 972 973 /* assert(klen == cipher->max_keysize); */ 974 *raw_key_sz = klen; 975 *raw_key = (char *)kvalue; 976 return; 977 978 cleanup: 979 die(gettext("failed to generate %s key from passphrase: %s"), 980 cipher->alias, pkcs11_strerror(rv)); 981 } 982 983 /* 984 * Read raw key from file; also handles ephemeral keys. 985 */ 986 void 987 getkeyfromfile(const char *pathname, mech_alias_t *cipher, char **key, 988 size_t *ksz) 989 { 990 int fd; 991 struct stat sbuf; 992 boolean_t notplain = B_FALSE; 993 ssize_t cursz; 994 ssize_t nread; 995 996 /* ephemeral keys are just random data */ 997 if (pathname == NULL) { 998 *ksz = cipher->max_keysize; 999 *key = malloc(*ksz); 1000 if (*key == NULL) 1001 die(gettext("failed to allocate memory for" 1002 " ephemeral key")); 1003 if (pkcs11_get_urandom(*key, *ksz) < 0) { 1004 free(*key); 1005 die(gettext("failed to get enough random data")); 1006 } 1007 return; 1008 } 1009 1010 /* 1011 * If the remaining section of code didn't also check for secure keyfile 1012 * permissions and whether the key is within cipher min and max lengths, 1013 * (or, if those things moved out of this block), we could have had: 1014 * if (pkcs11_read_data(pathname, key, ksz) < 0) 1015 * handle_error(); 1016 */ 1017 1018 if ((fd = open(pathname, O_RDONLY, 0)) == -1) 1019 die(gettext("open of keyfile (%s) failed"), pathname); 1020 1021 if (fstat(fd, &sbuf) == -1) 1022 die(gettext("fstat of keyfile (%s) failed"), pathname); 1023 1024 if (S_ISREG(sbuf.st_mode)) { 1025 if ((sbuf.st_mode & (S_IWGRP | S_IWOTH)) != 0) 1026 die(gettext("insecure permissions on keyfile %s\n"), 1027 pathname); 1028 1029 *ksz = sbuf.st_size; 1030 if (*ksz < cipher->min_keysize || cipher->max_keysize < *ksz) { 1031 warn(gettext("%s: invalid keysize: %d\n"), 1032 pathname, (int)*ksz); 1033 die(gettext("\t%d <= keysize <= %d\n"), 1034 cipher->min_keysize, cipher->max_keysize); 1035 } 1036 } else { 1037 *ksz = cipher->max_keysize; 1038 notplain = B_TRUE; 1039 } 1040 1041 *key = malloc(*ksz); 1042 if (*key == NULL) 1043 die(gettext("failed to allocate memory for key from file")); 1044 1045 for (cursz = 0, nread = 0; cursz < *ksz; cursz += nread) { 1046 nread = read(fd, *key, *ksz); 1047 if (nread > 0) 1048 continue; 1049 /* 1050 * nread == 0. If it's not a regular file we were trying to 1051 * get the maximum keysize of data possible for this cipher. 1052 * But if we've got at least the minimum keysize of data, 1053 * round down to the nearest keysize unit and call it good. 1054 * If we haven't met the minimum keysize, that's an error. 1055 * If it's a regular file, nread = 0 is also an error. 1056 */ 1057 if (nread == 0 && notplain && cursz >= cipher->min_keysize) { 1058 *ksz = (cursz / cipher->min_keysize) * 1059 cipher->min_keysize; 1060 break; 1061 } 1062 die(gettext("%s: can't read all keybytes"), pathname); 1063 } 1064 (void) close(fd); 1065 } 1066 1067 /* 1068 * Read the raw key from token, or from a file that was wrapped with a 1069 * key from token 1070 */ 1071 void 1072 getkeyfromtoken(CK_SESSION_HANDLE sess, 1073 token_spec_t *token, const char *keyfile, mech_alias_t *cipher, 1074 char **raw_key, size_t *raw_key_sz) 1075 { 1076 CK_RV rv = CKR_OK; 1077 CK_BBOOL trueval = B_TRUE; 1078 CK_OBJECT_CLASS kclass; /* secret key or RSA private key */ 1079 CK_KEY_TYPE ktype; /* from selected cipher or CKK_RSA */ 1080 CK_KEY_TYPE raw_ktype; /* from selected cipher */ 1081 CK_ATTRIBUTE key_tmpl[] = { 1082 { CKA_CLASS, NULL, 0 }, /* re-used for token key and unwrap */ 1083 { CKA_KEY_TYPE, NULL, 0 }, /* ditto */ 1084 { CKA_LABEL, NULL, 0 }, 1085 { CKA_TOKEN, NULL, 0 }, 1086 { CKA_PRIVATE, NULL, 0 } 1087 }; 1088 CK_ULONG attrs = sizeof (key_tmpl) / sizeof (CK_ATTRIBUTE); 1089 int i; 1090 char *pass = NULL; 1091 size_t passlen = 0; 1092 CK_OBJECT_HANDLE obj, rawobj; 1093 CK_ULONG num_objs = 1; /* just want to find 1 token key */ 1094 CK_MECHANISM unwrap = { CKM_RSA_PKCS, NULL, 0 }; 1095 char *rkey; 1096 size_t rksz; 1097 1098 if (token == NULL || token->key == NULL) 1099 return; 1100 1101 /* did init_crypto find a slot that supports this cipher? */ 1102 if (cipher->slot == (CK_SLOT_ID)-1 || cipher->max_keysize == 0) { 1103 die(gettext("failed to find any cryptographic provider, " 1104 "use \"cryptoadm list -p\" to find providers: %s\n"), 1105 pkcs11_strerror(CKR_MECHANISM_INVALID)); 1106 } 1107 1108 if (pkcs11_get_pass(token->name, &pass, &passlen, 0, B_FALSE) < 0) 1109 die(gettext("unable to get passphrase")); 1110 1111 /* use passphrase to login to token */ 1112 if (pass != NULL && passlen > 0) { 1113 rv = C_Login(sess, CKU_USER, (CK_UTF8CHAR_PTR)pass, passlen); 1114 if (rv != CKR_OK) { 1115 die(gettext("cannot login to the token %s: %s\n"), 1116 token->name, pkcs11_strerror(rv)); 1117 } 1118 } 1119 1120 rv = pkcs11_mech2keytype(cipher->type, &raw_ktype); 1121 if (rv != CKR_OK) { 1122 die(gettext("failed to get key type for cipher %s: %s\n"), 1123 cipher->name, pkcs11_strerror(rv)); 1124 } 1125 1126 /* 1127 * If no keyfile was given, then the token key is secret key to 1128 * be used for encryption/decryption. Otherwise, the keyfile 1129 * contains a wrapped secret key, and the token is actually the 1130 * unwrapping RSA private key. 1131 */ 1132 if (keyfile == NULL) { 1133 kclass = CKO_SECRET_KEY; 1134 ktype = raw_ktype; 1135 } else { 1136 kclass = CKO_PRIVATE_KEY; 1137 ktype = CKK_RSA; 1138 } 1139 1140 /* Find the key in the token first */ 1141 for (i = 0; i < attrs; i++) { 1142 switch (key_tmpl[i].type) { 1143 case CKA_CLASS: 1144 key_tmpl[i].pValue = &kclass; 1145 key_tmpl[i].ulValueLen = sizeof (kclass); 1146 break; 1147 case CKA_KEY_TYPE: 1148 key_tmpl[i].pValue = &ktype; 1149 key_tmpl[i].ulValueLen = sizeof (ktype); 1150 break; 1151 case CKA_LABEL: 1152 key_tmpl[i].pValue = token->key; 1153 key_tmpl[i].ulValueLen = strlen(token->key); 1154 break; 1155 case CKA_TOKEN: 1156 key_tmpl[i].pValue = &trueval; 1157 key_tmpl[i].ulValueLen = sizeof (trueval); 1158 break; 1159 case CKA_PRIVATE: 1160 key_tmpl[i].pValue = &trueval; 1161 key_tmpl[i].ulValueLen = sizeof (trueval); 1162 break; 1163 default: 1164 break; 1165 } 1166 } 1167 rv = C_FindObjectsInit(sess, key_tmpl, attrs); 1168 if (rv != CKR_OK) 1169 die(gettext("cannot find key %s: %s\n"), token->key, 1170 pkcs11_strerror(rv)); 1171 rv = C_FindObjects(sess, &obj, 1, &num_objs); 1172 (void) C_FindObjectsFinal(sess); 1173 1174 if (num_objs == 0) { 1175 die(gettext("cannot find key %s\n"), token->key); 1176 } else if (rv != CKR_OK) { 1177 die(gettext("cannot find key %s: %s\n"), token->key, 1178 pkcs11_strerror(rv)); 1179 } 1180 1181 /* 1182 * No keyfile means when token key is found, convert it to raw key, 1183 * and done. Otherwise still need do an unwrap to create yet another 1184 * obj and that needs to be converted to raw key before we're done. 1185 */ 1186 if (keyfile == NULL) { 1187 /* obj contains raw key, extract it */ 1188 rv = pkcs11_ObjectToKey(sess, obj, (void **)&rkey, &rksz, 1189 B_FALSE); 1190 if (rv != CKR_OK) { 1191 die(gettext("failed to get key value for %s" 1192 " from token %s, %s\n"), token->key, 1193 token->name, pkcs11_strerror(rv)); 1194 } 1195 } else { 1196 getkeyfromfile(keyfile, cipher, &rkey, &rksz); 1197 1198 /* 1199 * Got the wrapping RSA obj and the wrapped key from file. 1200 * Unwrap the key from file with RSA obj to get rawkey obj. 1201 */ 1202 1203 /* re-use the first two attributes of key_tmpl */ 1204 kclass = CKO_SECRET_KEY; 1205 ktype = raw_ktype; 1206 1207 rv = C_UnwrapKey(sess, &unwrap, obj, (CK_BYTE_PTR)rkey, 1208 rksz, key_tmpl, 2, &rawobj); 1209 if (rv != CKR_OK) { 1210 die(gettext("failed to unwrap key in keyfile %s," 1211 " %s\n"), keyfile, pkcs11_strerror(rv)); 1212 } 1213 /* rawobj contains raw key, extract it */ 1214 rv = pkcs11_ObjectToKey(sess, rawobj, (void **)&rkey, &rksz, 1215 B_TRUE); 1216 if (rv != CKR_OK) { 1217 die(gettext("failed to get unwrapped key value for" 1218 " key in keyfile %s, %s\n"), keyfile, 1219 pkcs11_strerror(rv)); 1220 } 1221 } 1222 1223 /* validate raw key size */ 1224 if (rksz < cipher->min_keysize || cipher->max_keysize < rksz) { 1225 warn(gettext("%s: invalid keysize: %d\n"), keyfile, (int)rksz); 1226 die(gettext("\t%d <= keysize <= %d\n"), cipher->min_keysize, 1227 cipher->max_keysize); 1228 } 1229 1230 *raw_key_sz = rksz; 1231 *raw_key = (char *)rkey; 1232 } 1233 1234 /* 1235 * Set up cipher key limits and verify PKCS#11 can be done 1236 * match_token_cipher is the function pointer used by 1237 * pkcs11_GetCriteriaSession() init_crypto. 1238 */ 1239 boolean_t 1240 match_token_cipher(CK_SLOT_ID slot_id, void *args, CK_RV *rv) 1241 { 1242 token_spec_t *token; 1243 mech_alias_t *cipher; 1244 CK_TOKEN_INFO tokinfo; 1245 CK_MECHANISM_INFO mechinfo; 1246 boolean_t token_match; 1247 1248 /* 1249 * While traversing slot list, pick up the following info per slot: 1250 * - if token specified, whether it matches this slot's token info 1251 * - if the slot supports the PKCS#5 PBKD2 cipher 1252 * 1253 * If the user said on the command line 1254 * -T tok:mfr:ser:lab -k keyfile 1255 * -c cipher -T tok:mfr:ser:lab -k keyfile 1256 * the given cipher or the default cipher apply to keyfile, 1257 * If the user said instead 1258 * -T tok:mfr:ser:lab 1259 * -c cipher -T tok:mfr:ser:lab 1260 * the key named "lab" may or may not agree with the given 1261 * cipher or the default cipher. In those cases, cipher will 1262 * be overridden with the actual cipher type of the key "lab". 1263 */ 1264 *rv = CKR_FUNCTION_FAILED; 1265 1266 if (args == NULL) { 1267 return (B_FALSE); 1268 } 1269 1270 cipher = (mech_alias_t *)args; 1271 token = cipher->token; 1272 1273 if (C_GetMechanismInfo(slot_id, cipher->type, &mechinfo) != CKR_OK) { 1274 return (B_FALSE); 1275 } 1276 1277 if (token == NULL) { 1278 if (C_GetMechanismInfo(slot_id, CKM_PKCS5_PBKD2, &mechinfo) != 1279 CKR_OK) { 1280 return (B_FALSE); 1281 } 1282 goto foundit; 1283 } 1284 1285 /* does the token match the token spec? */ 1286 if (token->key == NULL || (C_GetTokenInfo(slot_id, &tokinfo) != CKR_OK)) 1287 return (B_FALSE); 1288 1289 token_match = B_TRUE; 1290 1291 if (token->name != NULL && (token->name)[0] != '\0' && 1292 strncmp((char *)token->name, (char *)tokinfo.label, 1293 TOKEN_LABEL_SIZE) != 0) 1294 token_match = B_FALSE; 1295 if (token->mfr != NULL && (token->mfr)[0] != '\0' && 1296 strncmp((char *)token->mfr, (char *)tokinfo.manufacturerID, 1297 TOKEN_MANUFACTURER_SIZE) != 0) 1298 token_match = B_FALSE; 1299 if (token->serno != NULL && (token->serno)[0] != '\0' && 1300 strncmp((char *)token->serno, (char *)tokinfo.serialNumber, 1301 TOKEN_SERIAL_SIZE) != 0) 1302 token_match = B_FALSE; 1303 1304 if (!token_match) 1305 return (B_FALSE); 1306 1307 foundit: 1308 cipher->slot = slot_id; 1309 return (B_TRUE); 1310 } 1311 1312 /* 1313 * Clean up crypto loose ends 1314 */ 1315 static void 1316 end_crypto(CK_SESSION_HANDLE sess) 1317 { 1318 (void) C_CloseSession(sess); 1319 (void) C_Finalize(NULL); 1320 } 1321 1322 /* 1323 * Set up crypto, opening session on slot that matches token and cipher 1324 */ 1325 static void 1326 init_crypto(token_spec_t *token, mech_alias_t *cipher, 1327 CK_SESSION_HANDLE_PTR sess) 1328 { 1329 CK_RV rv; 1330 1331 cipher->token = token; 1332 1333 /* Turn off Metaslot so that we can see actual tokens */ 1334 if (setenv("METASLOT_ENABLED", "false", 1) < 0) { 1335 die(gettext("could not disable Metaslot")); 1336 } 1337 1338 rv = pkcs11_GetCriteriaSession(match_token_cipher, (void *)cipher, 1339 sess); 1340 if (rv != CKR_OK) { 1341 end_crypto(*sess); 1342 if (rv == CKR_HOST_MEMORY) { 1343 die("malloc"); 1344 } 1345 die(gettext("failed to find any cryptographic provider, " 1346 "use \"cryptoadm list -p\" to find providers: %s\n"), 1347 pkcs11_strerror(rv)); 1348 } 1349 } 1350 1351 /* 1352 * Uncompress a file. 1353 * 1354 * First map the file in to establish a device 1355 * association, then read from it. On-the-fly 1356 * decompression will automatically uncompress 1357 * the file if it's compressed 1358 * 1359 * If the file is mapped and a device association 1360 * has been established, disallow uncompressing 1361 * the file until it is unmapped. 1362 */ 1363 static void 1364 lofi_uncompress(int lfd, const char *filename) 1365 { 1366 struct lofi_ioctl li; 1367 char buf[MAXBSIZE]; 1368 char devicename[32]; 1369 char tmpfilename[MAXPATHLEN]; 1370 char *x; 1371 char *dir = NULL; 1372 char *file = NULL; 1373 int minor = 0; 1374 struct stat64 statbuf; 1375 int compfd = -1; 1376 int uncompfd = -1; 1377 ssize_t rbytes; 1378 1379 /* 1380 * Disallow uncompressing the file if it is 1381 * already mapped. 1382 */ 1383 li.li_crypto_enabled = B_FALSE; 1384 li.li_id = 0; 1385 (void) strlcpy(li.li_filename, filename, sizeof (li.li_filename)); 1386 if (ioctl(lfd, LOFI_GET_MINOR, &li) != -1) 1387 die(gettext("%s must be unmapped before uncompressing"), 1388 filename); 1389 1390 /* Zero length files don't need to be uncompressed */ 1391 if (stat64(filename, &statbuf) == -1) 1392 die(gettext("stat: %s"), filename); 1393 if (statbuf.st_size == 0) 1394 return; 1395 1396 minor = lofi_map_file(lfd, &li, filename); 1397 (void) snprintf(devicename, sizeof (devicename), "/dev/%s/%d", 1398 LOFI_BLOCK_NAME, minor); 1399 1400 /* If the file isn't compressed, we just return */ 1401 if ((ioctl(lfd, LOFI_CHECK_COMPRESSED, &li) == -1) || 1402 (li.li_algorithm[0] == '\0')) { 1403 delete_mapping(lfd, devicename, filename, B_TRUE); 1404 die("%s is not compressed\n", filename); 1405 } 1406 1407 if ((compfd = open64(devicename, O_RDONLY | O_NONBLOCK)) == -1) { 1408 delete_mapping(lfd, devicename, filename, B_TRUE); 1409 die(gettext("open: %s"), filename); 1410 } 1411 /* Create a temp file in the same directory */ 1412 x = strdup(filename); 1413 dir = strdup(dirname(x)); 1414 free(x); 1415 x = strdup(filename); 1416 file = strdup(basename(x)); 1417 free(x); 1418 (void) snprintf(tmpfilename, sizeof (tmpfilename), 1419 "%s/.%sXXXXXX", dir, file); 1420 free(dir); 1421 free(file); 1422 1423 if ((uncompfd = mkstemp64(tmpfilename)) == -1) { 1424 (void) close(compfd); 1425 delete_mapping(lfd, devicename, filename, B_TRUE); 1426 die("%s could not be uncompressed\n", filename); 1427 } 1428 1429 /* 1430 * Set the mode bits and the owner of this temporary 1431 * file to be that of the original uncompressed file 1432 */ 1433 (void) fchmod(uncompfd, statbuf.st_mode); 1434 1435 if (fchown(uncompfd, statbuf.st_uid, statbuf.st_gid) == -1) { 1436 (void) close(compfd); 1437 (void) close(uncompfd); 1438 delete_mapping(lfd, devicename, filename, B_TRUE); 1439 die("%s could not be uncompressed\n", filename); 1440 } 1441 1442 /* Now read from the device in MAXBSIZE-sized chunks */ 1443 for (;;) { 1444 rbytes = read(compfd, buf, sizeof (buf)); 1445 1446 if (rbytes <= 0) 1447 break; 1448 1449 if (write(uncompfd, buf, rbytes) != rbytes) { 1450 rbytes = -1; 1451 break; 1452 } 1453 } 1454 1455 (void) close(compfd); 1456 (void) close(uncompfd); 1457 1458 /* Delete the mapping */ 1459 delete_mapping(lfd, devicename, filename, B_TRUE); 1460 1461 /* 1462 * If an error occured while reading or writing, rbytes will 1463 * be negative 1464 */ 1465 if (rbytes < 0) { 1466 (void) unlink(tmpfilename); 1467 die(gettext("could not read from %s"), filename); 1468 } 1469 1470 /* Rename the temp file to the actual file */ 1471 if (rename(tmpfilename, filename) == -1) 1472 (void) unlink(tmpfilename); 1473 } 1474 1475 /* 1476 * Compress a file 1477 */ 1478 static void 1479 lofi_compress(int *lfd, const char *filename, int compress_index, 1480 uint32_t segsize) 1481 { 1482 struct lofi_ioctl lic; 1483 lofi_compress_info_t *li; 1484 struct flock lock; 1485 char tmpfilename[MAXPATHLEN]; 1486 char comp_filename[MAXPATHLEN]; 1487 char algorithm[MAXALGLEN]; 1488 char *x; 1489 char *dir = NULL, *file = NULL; 1490 uchar_t *uncompressed_seg = NULL; 1491 uchar_t *compressed_seg = NULL; 1492 uint32_t compressed_segsize; 1493 uint32_t len_compressed, count; 1494 uint32_t index_entries, index_sz; 1495 uint64_t *index = NULL; 1496 uint64_t offset; 1497 size_t real_segsize; 1498 struct stat64 statbuf; 1499 int compfd = -1, uncompfd = -1; 1500 int tfd = -1; 1501 ssize_t rbytes, wbytes, lastread; 1502 int i, type; 1503 1504 /* 1505 * Disallow compressing the file if it is 1506 * already mapped 1507 */ 1508 lic.li_id = 0; 1509 (void) strlcpy(lic.li_filename, filename, sizeof (lic.li_filename)); 1510 if (ioctl(*lfd, LOFI_GET_MINOR, &lic) != -1) 1511 die(gettext("%s must be unmapped before compressing"), 1512 filename); 1513 1514 /* 1515 * Close the control device so other operations 1516 * can use it 1517 */ 1518 (void) close(*lfd); 1519 *lfd = -1; 1520 1521 li = &lofi_compress_table[compress_index]; 1522 1523 /* 1524 * The size of the buffer to hold compressed data must 1525 * be slightly larger than the compressed segment size. 1526 * 1527 * The compress functions use part of the buffer as 1528 * scratch space to do calculations. 1529 * Ref: http://www.zlib.net/manual.html#compress2 1530 */ 1531 compressed_segsize = segsize + (segsize >> 6); 1532 compressed_seg = (uchar_t *)malloc(compressed_segsize + SEGHDR); 1533 uncompressed_seg = (uchar_t *)malloc(segsize); 1534 1535 if (compressed_seg == NULL || uncompressed_seg == NULL) 1536 die(gettext("No memory")); 1537 1538 if ((uncompfd = open64(filename, O_RDWR|O_LARGEFILE, 0)) == -1) 1539 die(gettext("open: %s"), filename); 1540 1541 lock.l_type = F_WRLCK; 1542 lock.l_whence = SEEK_SET; 1543 lock.l_start = 0; 1544 lock.l_len = 0; 1545 1546 /* 1547 * Use an advisory lock to ensure that only a 1548 * single lofiadm process compresses a given 1549 * file at any given time 1550 * 1551 * A close on the file descriptor automatically 1552 * closes all lock state on the file 1553 */ 1554 if (fcntl(uncompfd, F_SETLKW, &lock) == -1) 1555 die(gettext("fcntl: %s"), filename); 1556 1557 if (fstat64(uncompfd, &statbuf) == -1) { 1558 (void) close(uncompfd); 1559 die(gettext("fstat: %s"), filename); 1560 } 1561 1562 /* Zero length files don't need to be compressed */ 1563 if (statbuf.st_size == 0) { 1564 (void) close(uncompfd); 1565 return; 1566 } 1567 1568 /* 1569 * Create temporary files in the same directory that 1570 * will hold the intermediate data 1571 */ 1572 x = strdup(filename); 1573 dir = strdup(dirname(x)); 1574 free(x); 1575 x = strdup(filename); 1576 file = strdup(basename(x)); 1577 free(x); 1578 (void) snprintf(tmpfilename, sizeof (tmpfilename), 1579 "%s/.%sXXXXXX", dir, file); 1580 (void) snprintf(comp_filename, sizeof (comp_filename), 1581 "%s/.%sXXXXXX", dir, file); 1582 free(dir); 1583 free(file); 1584 1585 if ((tfd = mkstemp64(tmpfilename)) == -1) 1586 goto cleanup; 1587 1588 if ((compfd = mkstemp64(comp_filename)) == -1) 1589 goto cleanup; 1590 1591 /* 1592 * Set the mode bits and owner of the compressed 1593 * file to be that of the original uncompressed file 1594 */ 1595 (void) fchmod(compfd, statbuf.st_mode); 1596 1597 if (fchown(compfd, statbuf.st_uid, statbuf.st_gid) == -1) 1598 goto cleanup; 1599 1600 /* 1601 * Calculate the number of index entries required. 1602 * index entries are stored as an array. adding 1603 * a '2' here accounts for the fact that the last 1604 * segment may not be a multiple of the segment size 1605 */ 1606 index_sz = (statbuf.st_size / segsize) + 2; 1607 index = malloc(sizeof (*index) * index_sz); 1608 1609 if (index == NULL) 1610 goto cleanup; 1611 1612 offset = 0; 1613 lastread = segsize; 1614 count = 0; 1615 1616 /* 1617 * Now read from the uncompressed file in 'segsize' 1618 * sized chunks, compress what was read in and 1619 * write it out to a temporary file 1620 */ 1621 for (;;) { 1622 rbytes = read(uncompfd, uncompressed_seg, segsize); 1623 1624 if (rbytes <= 0) 1625 break; 1626 1627 if (lastread < segsize) 1628 goto cleanup; 1629 1630 /* 1631 * Account for the first byte that 1632 * indicates whether a segment is 1633 * compressed or not 1634 */ 1635 real_segsize = segsize - 1; 1636 (void) li->l_compress(uncompressed_seg, rbytes, 1637 compressed_seg + SEGHDR, &real_segsize, li->l_level); 1638 1639 /* 1640 * If the length of the compressed data is more 1641 * than a threshold then there isn't any benefit 1642 * to be had from compressing this segment - leave 1643 * it uncompressed. 1644 * 1645 * NB. In case an error occurs during compression (above) 1646 * the 'real_segsize' isn't changed. The logic below 1647 * ensures that that segment is left uncompressed. 1648 */ 1649 len_compressed = real_segsize; 1650 if (segsize <= COMPRESS_THRESHOLD || 1651 real_segsize > (segsize - COMPRESS_THRESHOLD)) { 1652 (void) memcpy(compressed_seg + SEGHDR, uncompressed_seg, 1653 rbytes); 1654 type = UNCOMPRESSED; 1655 len_compressed = rbytes; 1656 } else { 1657 type = COMPRESSED; 1658 } 1659 1660 /* 1661 * Set the first byte or the SEGHDR to 1662 * indicate if it's compressed or not 1663 */ 1664 *compressed_seg = type; 1665 wbytes = write(tfd, compressed_seg, len_compressed + SEGHDR); 1666 if (wbytes != (len_compressed + SEGHDR)) { 1667 rbytes = -1; 1668 break; 1669 } 1670 1671 index[count] = BE_64(offset); 1672 offset += wbytes; 1673 lastread = rbytes; 1674 count++; 1675 } 1676 1677 (void) close(uncompfd); 1678 1679 if (rbytes < 0) 1680 goto cleanup; 1681 /* 1682 * The last index entry is a sentinel entry. It does not point to 1683 * an actual compressed segment but helps in computing the size of 1684 * the compressed segment. The size of each compressed segment is 1685 * computed by subtracting the current index value from the next 1686 * one (the compressed blocks are stored sequentially) 1687 */ 1688 index[count++] = BE_64(offset); 1689 1690 /* 1691 * Now write the compressed data along with the 1692 * header information to this file which will 1693 * later be renamed to the original uncompressed 1694 * file name 1695 * 1696 * The header is as follows - 1697 * 1698 * Signature (name of the compression algorithm) 1699 * Compression segment size (a multiple of 512) 1700 * Number of index entries 1701 * Size of the last block 1702 * The array containing the index entries 1703 * 1704 * the header is always stored in network byte 1705 * order 1706 */ 1707 (void) bzero(algorithm, sizeof (algorithm)); 1708 (void) strlcpy(algorithm, li->l_name, sizeof (algorithm)); 1709 if (write(compfd, algorithm, sizeof (algorithm)) 1710 != sizeof (algorithm)) 1711 goto cleanup; 1712 1713 segsize = htonl(segsize); 1714 if (write(compfd, &segsize, sizeof (segsize)) != sizeof (segsize)) 1715 goto cleanup; 1716 1717 index_entries = htonl(count); 1718 if (write(compfd, &index_entries, sizeof (index_entries)) != 1719 sizeof (index_entries)) 1720 goto cleanup; 1721 1722 lastread = htonl(lastread); 1723 if (write(compfd, &lastread, sizeof (lastread)) != sizeof (lastread)) 1724 goto cleanup; 1725 1726 for (i = 0; i < count; i++) { 1727 if (write(compfd, index + i, sizeof (*index)) != 1728 sizeof (*index)) 1729 goto cleanup; 1730 } 1731 1732 /* Header is written, now write the compressed data */ 1733 if (lseek(tfd, 0, SEEK_SET) != 0) 1734 goto cleanup; 1735 1736 rbytes = wbytes = 0; 1737 1738 for (;;) { 1739 rbytes = read(tfd, compressed_seg, compressed_segsize + SEGHDR); 1740 1741 if (rbytes <= 0) 1742 break; 1743 1744 if (write(compfd, compressed_seg, rbytes) != rbytes) 1745 goto cleanup; 1746 } 1747 1748 if (fstat64(compfd, &statbuf) == -1) 1749 goto cleanup; 1750 1751 /* 1752 * Round up the compressed file size to be a multiple of 1753 * DEV_BSIZE. lofi(7D) likes it that way. 1754 */ 1755 if ((offset = statbuf.st_size % DEV_BSIZE) > 0) { 1756 1757 offset = DEV_BSIZE - offset; 1758 1759 for (i = 0; i < offset; i++) 1760 uncompressed_seg[i] = '\0'; 1761 if (write(compfd, uncompressed_seg, offset) != offset) 1762 goto cleanup; 1763 } 1764 (void) close(compfd); 1765 (void) close(tfd); 1766 (void) unlink(tmpfilename); 1767 cleanup: 1768 if (rbytes < 0) { 1769 if (tfd != -1) 1770 (void) unlink(tmpfilename); 1771 if (compfd != -1) 1772 (void) unlink(comp_filename); 1773 die(gettext("error compressing file %s"), filename); 1774 } else { 1775 /* Rename the compressed file to the actual file */ 1776 if (rename(comp_filename, filename) == -1) { 1777 (void) unlink(comp_filename); 1778 die(gettext("error compressing file %s"), filename); 1779 } 1780 } 1781 if (compressed_seg != NULL) 1782 free(compressed_seg); 1783 if (uncompressed_seg != NULL) 1784 free(uncompressed_seg); 1785 if (index != NULL) 1786 free(index); 1787 if (compfd != -1) 1788 (void) close(compfd); 1789 if (uncompfd != -1) 1790 (void) close(uncompfd); 1791 if (tfd != -1) 1792 (void) close(tfd); 1793 } 1794 1795 static int 1796 lofi_compress_select(const char *algname) 1797 { 1798 int i; 1799 1800 for (i = 0; i < LOFI_COMPRESS_FUNCTIONS; i++) { 1801 if (strcmp(lofi_compress_table[i].l_name, algname) == 0) 1802 return (i); 1803 } 1804 return (-1); 1805 } 1806 1807 static void 1808 check_algorithm_validity(const char *algname, int *compress_index) 1809 { 1810 *compress_index = lofi_compress_select(algname); 1811 if (*compress_index < 0) 1812 die(gettext("invalid algorithm name: %s\n"), algname); 1813 } 1814 1815 static void 1816 check_file_validity(const char *filename) 1817 { 1818 struct stat64 buf; 1819 int error; 1820 int fd; 1821 1822 fd = open64(filename, O_RDONLY); 1823 if (fd == -1) { 1824 die(gettext("open: %s"), filename); 1825 } 1826 error = fstat64(fd, &buf); 1827 if (error == -1) { 1828 die(gettext("fstat: %s"), filename); 1829 } else if (!S_ISLOFIABLE(buf.st_mode)) { 1830 die(gettext("%s is not a regular file, " 1831 "block, or character device\n"), 1832 filename); 1833 } else if ((buf.st_size % DEV_BSIZE) != 0) { 1834 die(gettext("size of %s is not a multiple of %d\n"), 1835 filename, DEV_BSIZE); 1836 } 1837 (void) close(fd); 1838 1839 if (name_to_minor(filename) != 0) { 1840 die(gettext("cannot use %s on itself\n"), LOFI_DRIVER_NAME); 1841 } 1842 } 1843 1844 static boolean_t 1845 check_file_is_encrypted(const char *filename) 1846 { 1847 int fd; 1848 char buf[sizeof (lofi_crypto_magic)]; 1849 int got; 1850 int rest = sizeof (lofi_crypto_magic); 1851 1852 fd = open64(filename, O_RDONLY); 1853 if (fd == -1) 1854 die(gettext("failed to open: %s"), filename); 1855 1856 if (lseek(fd, CRYOFF, SEEK_SET) != CRYOFF) 1857 die(gettext("failed to seek to offset 0x%lx in file %s"), 1858 CRYOFF, filename); 1859 1860 do { 1861 got = read(fd, buf + sizeof (lofi_crypto_magic) - rest, rest); 1862 if ((got == 0) || ((got == -1) && (errno != EINTR))) 1863 die(gettext("failed to read crypto header" 1864 " at offset 0x%lx in file %s"), CRYOFF, filename); 1865 1866 if (got > 0) 1867 rest -= got; 1868 } while (rest > 0); 1869 1870 while (close(fd) == -1) { 1871 if (errno != EINTR) 1872 die(gettext("failed to close file %s"), filename); 1873 } 1874 1875 return (strncmp(buf, lofi_crypto_magic, 1876 sizeof (lofi_crypto_magic)) == 0); 1877 } 1878 1879 static uint32_t 1880 convert_to_num(const char *str) 1881 { 1882 int len; 1883 uint32_t segsize, mult = 1; 1884 1885 len = strlen(str); 1886 if (len && isalpha(str[len - 1])) { 1887 switch (str[len - 1]) { 1888 case 'k': 1889 case 'K': 1890 mult = KILOBYTE; 1891 break; 1892 case 'b': 1893 case 'B': 1894 mult = BLOCK_SIZE; 1895 break; 1896 case 'm': 1897 case 'M': 1898 mult = MEGABYTE; 1899 break; 1900 case 'g': 1901 case 'G': 1902 mult = GIGABYTE; 1903 break; 1904 default: 1905 die(gettext("invalid segment size %s\n"), str); 1906 } 1907 } 1908 1909 segsize = atol(str); 1910 segsize *= mult; 1911 1912 return (segsize); 1913 } 1914 1915 int 1916 main(int argc, char *argv[]) 1917 { 1918 int lfd; 1919 int c; 1920 const char *devicename = NULL; 1921 const char *filename = NULL; 1922 const char *algname = COMPRESS_ALGORITHM; 1923 int openflag; 1924 int minor; 1925 int compress_index; 1926 uint32_t segsize = SEGSIZE; 1927 static char *lofictl = "/dev/" LOFI_CTL_NAME; 1928 boolean_t force = B_FALSE; 1929 const char *pname; 1930 boolean_t errflag = B_FALSE; 1931 boolean_t addflag = B_FALSE; 1932 boolean_t labelflag = B_FALSE; 1933 boolean_t rdflag = B_FALSE; 1934 boolean_t deleteflag = B_FALSE; 1935 boolean_t ephflag = B_FALSE; 1936 boolean_t compressflag = B_FALSE; 1937 boolean_t uncompressflag = B_FALSE; 1938 /* the next two work together for -c, -k, -T, -e options only */ 1939 boolean_t need_crypto = B_FALSE; /* if any -c, -k, -T, -e */ 1940 boolean_t cipher_only = B_TRUE; /* if -c only */ 1941 const char *keyfile = NULL; 1942 mech_alias_t *cipher = NULL; 1943 token_spec_t *token = NULL; 1944 char *rkey = NULL; 1945 size_t rksz = 0; 1946 char realfilename[MAXPATHLEN]; 1947 1948 pname = getpname(argv[0]); 1949 1950 (void) setlocale(LC_ALL, ""); 1951 (void) textdomain(TEXT_DOMAIN); 1952 1953 while ((c = getopt(argc, argv, "a:c:Cd:efk:lrs:T:U")) != EOF) { 1954 switch (c) { 1955 case 'a': 1956 addflag = B_TRUE; 1957 if ((filename = realpath(optarg, realfilename)) == NULL) 1958 die("%s", optarg); 1959 if (((argc - optind) > 0) && (*argv[optind] != '-')) { 1960 /* optional device */ 1961 devicename = argv[optind]; 1962 optind++; 1963 } 1964 break; 1965 case 'C': 1966 compressflag = B_TRUE; 1967 if (((argc - optind) > 1) && (*argv[optind] != '-')) { 1968 /* optional algorithm */ 1969 algname = argv[optind]; 1970 optind++; 1971 } 1972 check_algorithm_validity(algname, &compress_index); 1973 break; 1974 case 'c': 1975 /* is the chosen cipher allowed? */ 1976 if ((cipher = ciph2mech(optarg)) == NULL) { 1977 errflag = B_TRUE; 1978 warn(gettext("cipher %s not allowed\n"), 1979 optarg); 1980 } 1981 need_crypto = B_TRUE; 1982 /* cipher_only is already set */ 1983 break; 1984 case 'd': 1985 deleteflag = B_TRUE; 1986 minor = name_to_minor(optarg); 1987 if (minor != 0) 1988 devicename = optarg; 1989 else { 1990 if ((filename = realpath(optarg, 1991 realfilename)) == NULL) 1992 die("%s", optarg); 1993 } 1994 break; 1995 case 'e': 1996 ephflag = B_TRUE; 1997 need_crypto = B_TRUE; 1998 cipher_only = B_FALSE; /* need to unset cipher_only */ 1999 break; 2000 case 'f': 2001 force = B_TRUE; 2002 break; 2003 case 'k': 2004 keyfile = optarg; 2005 need_crypto = B_TRUE; 2006 cipher_only = B_FALSE; /* need to unset cipher_only */ 2007 break; 2008 case 'l': 2009 labelflag = B_TRUE; 2010 break; 2011 case 'r': 2012 rdflag = B_TRUE; 2013 break; 2014 case 's': 2015 segsize = convert_to_num(optarg); 2016 if (segsize < DEV_BSIZE || !ISP2(segsize)) 2017 die(gettext("segment size %s is invalid " 2018 "or not a multiple of minimum block " 2019 "size %ld\n"), optarg, DEV_BSIZE); 2020 break; 2021 case 'T': 2022 if ((token = parsetoken(optarg)) == NULL) { 2023 errflag = B_TRUE; 2024 warn( 2025 gettext("invalid token key specifier %s\n"), 2026 optarg); 2027 } 2028 need_crypto = B_TRUE; 2029 cipher_only = B_FALSE; /* need to unset cipher_only */ 2030 break; 2031 case 'U': 2032 uncompressflag = B_TRUE; 2033 break; 2034 case '?': 2035 default: 2036 errflag = B_TRUE; 2037 break; 2038 } 2039 } 2040 2041 /* Check for mutually exclusive combinations of options */ 2042 if (errflag || 2043 (addflag && deleteflag) || 2044 (labelflag && !addflag) || 2045 (rdflag && !addflag) || 2046 (!addflag && need_crypto) || 2047 (need_crypto && labelflag) || 2048 ((compressflag || uncompressflag) && 2049 (labelflag || addflag || deleteflag))) 2050 usage(pname); 2051 2052 /* ephemeral key, and key from either file or token are incompatible */ 2053 if (ephflag && (keyfile != NULL || token != NULL)) { 2054 die(gettext("ephemeral key cannot be used with keyfile" 2055 " or token key\n")); 2056 } 2057 2058 /* 2059 * "-c" but no "-k", "-T", "-e", or "-T -k" means derive key from 2060 * command line passphrase 2061 */ 2062 2063 switch (argc - optind) { 2064 case 0: /* no more args */ 2065 if (compressflag || uncompressflag) /* needs filename */ 2066 usage(pname); 2067 break; 2068 case 1: 2069 if (addflag || deleteflag) 2070 usage(pname); 2071 /* one arg means compress/uncompress the file ... */ 2072 if (compressflag || uncompressflag) { 2073 if ((filename = realpath(argv[optind], 2074 realfilename)) == NULL) 2075 die("%s", argv[optind]); 2076 /* ... or without options means print the association */ 2077 } else { 2078 minor = name_to_minor(argv[optind]); 2079 if (minor != 0) 2080 devicename = argv[optind]; 2081 else { 2082 if ((filename = realpath(argv[optind], 2083 realfilename)) == NULL) 2084 die("%s", argv[optind]); 2085 } 2086 } 2087 break; 2088 default: 2089 usage(pname); 2090 break; 2091 } 2092 2093 if (addflag || compressflag || uncompressflag) 2094 check_file_validity(filename); 2095 2096 if (filename && !valid_abspath(filename)) 2097 exit(E_ERROR); 2098 2099 /* 2100 * Here, we know the arguments are correct, the filename is an 2101 * absolute path, it exists and is a regular file. We don't yet 2102 * know that the device name is ok or not. 2103 */ 2104 2105 openflag = O_EXCL; 2106 if (addflag || deleteflag || compressflag || uncompressflag) 2107 openflag |= O_RDWR; 2108 else 2109 openflag |= O_RDONLY; 2110 lfd = open(lofictl, openflag); 2111 if (lfd == -1) { 2112 if ((errno == EPERM) || (errno == EACCES)) { 2113 die(gettext("you do not have permission to perform " 2114 "that operation.\n")); 2115 } else { 2116 die(gettext("open: %s"), lofictl); 2117 } 2118 /*NOTREACHED*/ 2119 } 2120 2121 /* 2122 * No passphrase is needed for ephemeral key, or when key is 2123 * in a file and not wrapped by another key from a token. 2124 * However, a passphrase is needed in these cases: 2125 * 1. cipher with no ephemeral key, key file, or token, 2126 * in which case the passphrase is used to build the key 2127 * 2. token with an optional cipher or optional key file, 2128 * in which case the passphrase unlocks the token 2129 * If only the cipher is specified, reconfirm the passphrase 2130 * to ensure the user hasn't mis-entered it. Otherwise, the 2131 * token will enforce the token passphrase. 2132 */ 2133 if (need_crypto) { 2134 CK_SESSION_HANDLE sess; 2135 2136 /* pick a cipher if none specified */ 2137 if (cipher == NULL) 2138 cipher = DEFAULT_CIPHER; 2139 2140 if (!kernel_cipher_check(cipher)) 2141 die(gettext( 2142 "use \"cryptoadm list -m\" to find available " 2143 "mechanisms\n")); 2144 2145 init_crypto(token, cipher, &sess); 2146 2147 if (cipher_only) { 2148 getkeyfromuser(cipher, &rkey, &rksz, 2149 !check_file_is_encrypted(filename)); 2150 } else if (token != NULL) { 2151 getkeyfromtoken(sess, token, keyfile, cipher, 2152 &rkey, &rksz); 2153 } else { 2154 /* this also handles ephemeral keys */ 2155 getkeyfromfile(keyfile, cipher, &rkey, &rksz); 2156 } 2157 2158 end_crypto(sess); 2159 } 2160 2161 /* 2162 * Now to the real work. 2163 */ 2164 if (addflag) 2165 add_mapping(lfd, devicename, filename, cipher, rkey, rksz, 2166 rdflag, labelflag); 2167 else if (compressflag) 2168 lofi_compress(&lfd, filename, compress_index, segsize); 2169 else if (uncompressflag) 2170 lofi_uncompress(lfd, filename); 2171 else if (deleteflag) 2172 delete_mapping(lfd, devicename, filename, force); 2173 else if (filename || devicename) 2174 print_one_mapping(lfd, devicename, filename); 2175 else 2176 print_mappings(lfd); 2177 2178 if (lfd != -1) 2179 (void) close(lfd); 2180 closelib(); 2181 return (E_SUCCESS); 2182 } 2183