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