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