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 (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright 2018, Joyent, Inc.
  24  */
  25 
  26 /*
  27  * Functions used for manipulating the keystore
  28  */
  29 
  30 #include <stdio.h>
  31 #include <stdlib.h>
  32 #include <errno.h>
  33 #include <sys/stat.h>
  34 #include <fcntl.h>
  35 #include <time.h>
  36 #include <unistd.h>
  37 #include <pwd.h>
  38 #include <sys/types.h>
  39 #include <dirent.h>
  40 #include <limits.h>
  41 #include <libgen.h>
  42 #include <strings.h>
  43 #include <security/cryptoki.h>
  44 #include <cryptoutil.h>
  45 #include "softGlobal.h"
  46 #include "softObject.h"
  47 #include "softSession.h"
  48 #include "softKeystore.h"
  49 #include "softKeystoreUtil.h"
  50 
  51 #define MAXPATHLEN      1024
  52 #define SUNW_PATH       ".sunw"         /* top level Sun directory */
  53 #define KEYSTORE_PATH   "pkcs11_softtoken"      /* keystore directory */
  54 #define PUB_OBJ_DIR     "public"        /* directory for public objects */
  55 #define PRI_OBJ_DIR     "private"       /* directory for private objects */
  56 #define DS_FILE         "objstore_info" /* keystore description file */
  57 #define TMP_DS_FILE     "t_info"        /* temp name for keystore desc. file */
  58 #define OBJ_PREFIX      "obj"   /* prefix of the keystore object file names */
  59 #define OBJ_PREFIX_LEN  sizeof (OBJ_PREFIX) - 1 /* length of prefix */
  60 #define TMP_OBJ_PREFIX  "t_o"   /* prefix of the temp object file names */
  61 
  62 /*
  63  * KEYSTORE DESCRIPTION FILE:
  64  *
  65  * The following describes the content of the keystore description file
  66  *
  67  * The order AND data type of the fields are very important.
  68  * All the code in this file assume that they are in the order specified
  69  * below.  If either order of the fields or their data type changed,
  70  * you must make sure the ALL the pre-define values are still valid
  71  *
  72  * 1) PKCS#11 release number.  It's 2.20 in this release (uchar_t[32])
  73  * 2) keystore version number: used for synchronizing when different
  74  *    processes access the keystore at the same time.  It is incremented
  75  *    when there is a change to the keystore. (uint_32)
  76  * 3) monotonic-counter: last counter value for name of token object file.
  77  *    used for assigning unique name to each token (uint_32)
  78  * 4) salt used for generating encryption key (uint_16)
  79  * 5) salt used for generating key used for doing HMAC (uint_16)
  80  * 6) Length of salt used for generating hashed pin (length of salt
  81  *    is variable)
  82  * 7) Salt used for generating hashed pin.
  83  * 8) Hashed pin len (length of hashed pin could be variable, the offset of
  84  *    where this value lives in the file is calculated at run time)
  85  * 9) Hashed pin
  86  *
  87  */
  88 
  89 /* Keystore description file pre-defined values */
  90 #define KS_PKCS11_VER           "2.20"
  91 #define KS_PKCS11_OFFSET        0
  92 #define KS_PKCS11_VER_SIZE      32
  93 
  94 #define KS_VER_OFFSET           (KS_PKCS11_OFFSET + KS_PKCS11_VER_SIZE)
  95 #define KS_VER_SIZE     4       /* size in bytes of keystore version value */
  96 
  97 #define KS_COUNTER_OFFSET       (KS_VER_OFFSET + KS_VER_SIZE)
  98 #define KS_COUNTER_SIZE 4       /* size in bytes of the monotonic counter */
  99 
 100 #define KS_KEY_SALT_OFFSET      (KS_COUNTER_OFFSET + KS_COUNTER_SIZE)
 101 #define KS_KEY_SALT_SIZE        PBKD2_SALT_SIZE
 102 
 103 #define KS_HMAC_SALT_OFFSET     (KS_KEY_SALT_OFFSET + KS_KEY_SALT_SIZE)
 104 #define KS_HMAC_SALT_SIZE       PBKD2_SALT_SIZE
 105 
 106 /* Salt for hashed pin */
 107 #define KS_HASHED_PIN_SALT_LEN_OFFSET (KS_HMAC_SALT_OFFSET + KS_HMAC_SALT_SIZE)
 108 #define KS_HASHED_PIN_SALT_LEN_SIZE 8 /* stores length of hashed pin salt */
 109 
 110 #define KS_HASHED_PIN_SALT_OFFSET \
 111                 (KS_HASHED_PIN_SALT_LEN_OFFSET + KS_HASHED_PIN_SALT_LEN_SIZE)
 112 
 113 /*
 114  * hashed pin
 115  *
 116  * hashed_pin length offset will be calculated at run time since
 117  * there's the hashed pin salt size is variable.
 118  *
 119  * The offset will be calculated at run time by calling the
 120  * function calculate_hashed_pin_offset()
 121  */
 122 static off_t    ks_hashed_pinlen_offset = -1;
 123 #define KS_HASHED_PINLEN_SIZE   8
 124 
 125 /* End of Keystore description file pre-defined values */
 126 
 127 /*
 128  * Metadata for each object
 129  *
 130  * The order AND data type of all the fields is very important.
 131  * All the code in this file assume that they are in the order specified
 132  * below.  If either order of the fields or their data type is changed,
 133  * you must make sure the following pre-define value is still valid
 134  * Each object will have the meta data at the beginning of the object file.
 135  *
 136  * 1) object_version: used by softtoken to see if the object
 137  *    has been modified since it last reads it. (uint_32)
 138  * 2) iv: initialization vector for encrypted data in the object.  This
 139  *    value will be 0 for public objects.  (uchar_t[16])
 140  * 3) obj_hmac: keyed hash as verifier to detect private object
 141  *    being tampered this value will be 0 for public objects (uchar_t[16])
 142  */
 143 
 144 /* Object metadata pre-defined values */
 145 #define OBJ_VER_OFFSET  0
 146 #define OBJ_VER_SIZE    4       /* size of object version in bytes */
 147 #define OBJ_IV_OFFSET   (OBJ_VER_OFFSET + OBJ_VER_SIZE)
 148 #define OBJ_IV_SIZE     16
 149 #define OBJ_HMAC_OFFSET (OBJ_IV_OFFSET + OBJ_IV_SIZE)
 150 #define OBJ_HMAC_SIZE   16      /* MD5 HMAC keyed hash */
 151 #define OBJ_DATA_OFFSET (OBJ_HMAC_OFFSET + OBJ_HMAC_SIZE)
 152 /* End of object metadata pre-defined values */
 153 
 154 #define ALTERNATE_KEYSTORE_PATH "SOFTTOKEN_DIR"
 155 
 156 static soft_object_t    *enc_key = NULL;
 157 static soft_object_t    *hmac_key = NULL;
 158 static char             keystore_path[MAXPATHLEN];
 159 static boolean_t        keystore_path_initialized = B_FALSE;
 160 static int              desc_fd = 0;
 161 
 162 static char *
 163 get_keystore_path()
 164 {
 165         char *home = getenv("HOME");
 166         char *alt = getenv(ALTERNATE_KEYSTORE_PATH);
 167 
 168         if (keystore_path_initialized) {
 169                 return (keystore_path);
 170         }
 171 
 172         bzero(keystore_path, sizeof (keystore_path));
 173         /*
 174          * If it isn't set or is set to the empty string use the
 175          * default location.  We need to check for the empty string
 176          * because some users "unset" environment variables by giving
 177          * them no value, this isn't the same thing as removing it
 178          * from the environment.
 179          *
 180          * We don't want that to attempt to open /.sunw/pkcs11_sofftoken
 181          */
 182         if ((alt != NULL) && (strcmp(alt, "") != 0)) {
 183                 (void) snprintf(keystore_path, MAXPATHLEN, "%s/%s",
 184                     alt, KEYSTORE_PATH);
 185                 keystore_path_initialized = B_TRUE;
 186         } else if ((home != NULL) && (strcmp(home, "") != 0)) {
 187                 /* alternate path not specified, try user's home dir */
 188                 (void) snprintf(keystore_path, MAXPATHLEN, "%s/%s/%s",
 189                     home, SUNW_PATH, KEYSTORE_PATH);
 190                 keystore_path_initialized = B_TRUE;
 191         }
 192         return (keystore_path);
 193 }
 194 
 195 static char *
 196 get_pub_obj_path(char *name)
 197 {
 198         bzero(name, sizeof (name));
 199         (void) snprintf(name, MAXPATHLEN, "%s/%s",
 200             get_keystore_path(), PUB_OBJ_DIR);
 201         return (name);
 202 }
 203 
 204 static char *
 205 get_pri_obj_path(char *name)
 206 {
 207         bzero(name, sizeof (name));
 208         (void) snprintf(name, MAXPATHLEN, "%s/%s",
 209             get_keystore_path(), PRI_OBJ_DIR);
 210         return (name);
 211 }
 212 
 213 static char *
 214 get_desc_file_path(char *name)
 215 {
 216         bzero(name, sizeof (name));
 217         (void) snprintf(name, MAXPATHLEN, "%s/%s",
 218             get_keystore_path(), DS_FILE);
 219         return (name);
 220 }
 221 
 222 static char *
 223 get_tmp_desc_file_path(char *name)
 224 {
 225         bzero(name, sizeof (name));
 226         (void) snprintf(name, MAXPATHLEN, "%s/%s",
 227             get_keystore_path(), TMP_DS_FILE);
 228         return (name);
 229 }
 230 
 231 /*
 232  * Calculates the offset for hashed_pin length and hashed pin
 233  *
 234  * Returns 0 if successful, -1 if there's any error.
 235  *
 236  * If successful, global variables "ks_hashed_pinlen_offset" will be set.
 237  *
 238  */
 239 static int
 240 calculate_hashed_pin_offset(int fd)
 241 {
 242         uint64_t salt_length;
 243 
 244         if (lseek(fd, KS_HASHED_PIN_SALT_LEN_OFFSET, SEEK_SET)
 245             != KS_HASHED_PIN_SALT_LEN_OFFSET) {
 246                 return (-1);
 247         }
 248 
 249         if (readn_nointr(fd, (char *)&salt_length,
 250             KS_HASHED_PIN_SALT_LEN_SIZE) != KS_HASHED_PIN_SALT_LEN_SIZE) {
 251                 return (-1);
 252         }
 253         salt_length = SWAP64(salt_length);
 254 
 255         ks_hashed_pinlen_offset = KS_HASHED_PIN_SALT_LEN_OFFSET
 256             + KS_HASHED_PIN_SALT_LEN_SIZE + salt_length;
 257 
 258         return (0);
 259 
 260 }
 261 
 262 /*
 263  * acquire or release read/write lock on a specific file
 264  *
 265  * read_lock: true for read lock; false for write lock
 266  * set_lock:  true to set a lock; false to release a lock
 267  */
 268 static int
 269 lock_file(int fd, boolean_t read_lock, boolean_t set_lock)
 270 {
 271 
 272         flock_t lock_info;
 273         int r;
 274 
 275         lock_info.l_whence = SEEK_SET;
 276         lock_info.l_start = 0;
 277         lock_info.l_len = 0; /* l_len == 0 means until end of  file */
 278 
 279         if (read_lock) {
 280                 lock_info.l_type = F_RDLCK;
 281         } else {
 282                 lock_info.l_type = F_WRLCK;
 283         }
 284 
 285         if (set_lock) {
 286                 while ((r = fcntl(fd, F_SETLKW, &lock_info)) == -1) {
 287                         if (errno != EINTR)
 288                                 break;
 289                 }
 290                 if (r == -1) {
 291                         return (-1);
 292                 }
 293         } else {
 294                 lock_info.l_type = F_UNLCK;
 295                 while ((r = fcntl(fd, F_SETLKW, &lock_info)) == -1) {
 296                         if (errno != EINTR)
 297                                 break;
 298                 }
 299                 if (r == -1) {
 300                         return (-1);
 301                 }
 302         }
 303 
 304         return (0);
 305 }
 306 
 307 int
 308 create_keystore()
 309 {
 310         int fd, buf;
 311         uint64_t hashed_pin_len, hashed_pin_salt_len, ulong_buf;
 312         uchar_t ver_buf[KS_PKCS11_VER_SIZE];
 313         char pub_obj_path[MAXPATHLEN], pri_obj_path[MAXPATHLEN],
 314             ks_desc_file[MAXPATHLEN];
 315         CK_BYTE salt[KS_KEY_SALT_SIZE];
 316         char *hashed_pin = NULL, *hashed_pin_salt = NULL;
 317         char *alt;
 318 
 319         /* keystore doesn't exist, create keystore directory */
 320         if (mkdir(get_keystore_path(), S_IRUSR|S_IWUSR|S_IXUSR) < 0) {
 321                 if (errno == EEXIST) {
 322                         return (0);
 323                 }
 324 
 325                 if (errno == EACCES) {
 326                         return (-1);
 327                 }
 328 
 329                 /* can't create keystore directory */
 330                 if (errno == ENOENT) { /* part of the path doesn't exist */
 331                         char keystore[MAXPATHLEN];
 332                         /*
 333                          * try to create $HOME/.sunw/pkcs11_softtoken if it
 334                          * doesn't exist.  If it is a alternate path provided
 335                          * by the user, it should have existed.  Will not
 336                          * create for them.
 337                          */
 338                         alt = getenv(ALTERNATE_KEYSTORE_PATH);
 339                         if ((alt == NULL) || (strcmp(alt, "") == 0)) {
 340                                 char *home = getenv("HOME");
 341 
 342                                 if (home == NULL || strcmp(home, "") == 0) {
 343                                         return (-1);
 344                                 }
 345                                 /* create $HOME/.sunw/pkcs11_softtoken */
 346                                 (void) snprintf(keystore, sizeof (keystore),
 347                                     "%s/%s/%s", home, SUNW_PATH, KEYSTORE_PATH);
 348                                 if (mkdirp(keystore,
 349                                     S_IRUSR|S_IWUSR|S_IXUSR) < 0) {
 350                                         return (-1);
 351                                 }
 352                         } else {
 353                                 return (-1);
 354                         }
 355                 }
 356         }
 357 
 358         /* create keystore description file */
 359         fd = open_nointr(get_desc_file_path(ks_desc_file),
 360             O_RDWR|O_CREAT|O_EXCL|O_NONBLOCK, S_IRUSR|S_IWUSR);
 361         if (fd < 0) {
 362                 if (errno == EEXIST) {
 363                         return (0);
 364                 } else {
 365                         /* can't create keystore description file */
 366                         (void) rmdir(get_keystore_path());
 367                         return (-1);
 368                 }
 369         }
 370 
 371         if (lock_file(fd, B_FALSE, B_TRUE) != 0) {
 372                 (void) unlink(ks_desc_file);
 373                 (void) close(fd);
 374                 (void) rmdir(get_keystore_path());
 375                 return (-1);
 376         }
 377 
 378         if (mkdir(get_pub_obj_path(pub_obj_path),
 379             S_IRUSR|S_IWUSR|S_IXUSR) < 0) {
 380                 /* can't create directory for public objects */
 381                 (void) lock_file(fd, B_FALSE, B_FALSE);
 382                 (void) unlink(ks_desc_file);
 383                 (void) close(fd);
 384                 (void) rmdir(get_keystore_path());
 385                 return (-1);
 386         }
 387 
 388         if (mkdir(get_pri_obj_path(pri_obj_path),
 389             S_IRUSR|S_IWUSR|S_IXUSR) < 0) {
 390                 /* can't create directory for private objects */
 391                 (void) lock_file(fd, B_FALSE, B_FALSE);
 392                 (void) unlink(ks_desc_file);
 393                 (void) close(fd);
 394                 (void) rmdir(get_keystore_path());
 395                 (void) rmdir(pub_obj_path);
 396                 return (-1);
 397         }
 398 
 399 
 400         /* write file format release number */
 401         bzero(ver_buf, sizeof (ver_buf));
 402         (void) strcpy((char *)ver_buf, KS_PKCS11_VER);
 403         if ((writen_nointr(fd, (char *)ver_buf, sizeof (ver_buf)))
 404             != sizeof (ver_buf)) {
 405                 goto cleanup;
 406         }
 407 
 408         /* write version number, version = 0 since keystore just created */
 409         buf = SWAP32(0);
 410         if (writen_nointr(fd, (void *)&buf, KS_VER_SIZE) != KS_VER_SIZE) {
 411                 goto cleanup;
 412         }
 413 
 414         /* write monotonic-counter.  Counter for keystore objects start at 1 */
 415         buf = SWAP32(1);
 416         if (writen_nointr(fd, (void *)&buf, KS_COUNTER_SIZE)
 417             != KS_COUNTER_SIZE) {
 418                 goto cleanup;
 419         }
 420 
 421         /* initial encryption key salt should be all NULL */
 422         bzero(salt, sizeof (salt));
 423         if (writen_nointr(fd, (void *)salt, KS_KEY_SALT_SIZE)
 424             != KS_KEY_SALT_SIZE) {
 425                 goto cleanup;
 426         }
 427 
 428         /* initial HMAC key salt should also be all NULL */
 429         if (writen_nointr(fd, (void *)salt, KS_HMAC_SALT_SIZE)
 430             != KS_HMAC_SALT_SIZE) {
 431                 goto cleanup;
 432         }
 433 
 434         /* generate the hashed pin salt, and MD5 hashed pin of default pin */
 435         if (soft_gen_hashed_pin((CK_CHAR_PTR)SOFT_DEFAULT_PIN, &hashed_pin,
 436             &hashed_pin_salt) < 0) {
 437                 goto cleanup;
 438         }
 439 
 440         if ((hashed_pin_salt == NULL) || (hashed_pin == NULL)) {
 441                 goto cleanup;
 442         }
 443 
 444         hashed_pin_salt_len = (uint64_t)strlen(hashed_pin_salt);
 445         hashed_pin_len = (uint64_t)strlen(hashed_pin);
 446 
 447         /* write hashed pin salt length */
 448         ulong_buf = SWAP64(hashed_pin_salt_len);
 449         if (writen_nointr(fd, (void *)&ulong_buf, KS_HASHED_PIN_SALT_LEN_SIZE)
 450             != KS_HASHED_PIN_SALT_LEN_SIZE) {
 451                 goto cleanup;
 452         }
 453 
 454         if (writen_nointr(fd, (void *)hashed_pin_salt,
 455             hashed_pin_salt_len) != hashed_pin_salt_len) {
 456                 goto cleanup;
 457         }
 458 
 459         /* write MD5 hashed pin of the default pin */
 460         ulong_buf = SWAP64(hashed_pin_len);
 461         if (writen_nointr(fd, (void *)&ulong_buf, KS_HASHED_PINLEN_SIZE)
 462             != KS_HASHED_PINLEN_SIZE) {
 463                 goto cleanup;
 464         }
 465 
 466         if (writen_nointr(fd, (void *)hashed_pin, hashed_pin_len)
 467             != hashed_pin_len) {
 468                 goto cleanup;
 469         }
 470 
 471         (void) lock_file(fd, B_FALSE, B_FALSE);
 472 
 473         (void) close(fd);
 474         freezero(hashed_pin_salt, hashed_pin_salt_len);
 475         return (0);
 476 
 477 cleanup:
 478         (void) lock_file(fd, B_FALSE, B_FALSE);
 479         (void) unlink(ks_desc_file);
 480         (void) close(fd);
 481         (void) rmdir(get_keystore_path());
 482         (void) rmdir(pub_obj_path);
 483         (void) rmdir(pri_obj_path);
 484         return (-1);
 485 }
 486 
 487 /*
 488  * Determines if the file referenced by "fd" has the same
 489  * inode as the file referenced by "fname".
 490  *
 491  * The argument "same" contains the result of determining
 492  * if the inode is the same or not
 493  *
 494  * Returns 0 if there's no error.
 495  * Returns 1 if there's any error with opening the file.
 496  *
 497  *
 498  */
 499 static int
 500 is_inode_same(int fd, char *fname, boolean_t *same)
 501 {
 502         struct stat fn_stat, fd_stat;
 503 
 504         if (fstat(fd, &fd_stat) != 0) {
 505                 return (-1);
 506         }
 507 
 508         if (stat(fname, &fn_stat) != 0) {
 509                 return (-1);
 510         }
 511 
 512         /* It's the same file if both st_ino and st_dev match */
 513         if ((fd_stat.st_ino == fn_stat.st_ino) &&
 514             (fd_stat.st_dev == fn_stat.st_dev)) {
 515                 *same = B_TRUE;
 516         } else {
 517                 *same = B_FALSE;
 518         }
 519         return (0);
 520 }
 521 
 522 static int
 523 acquire_file_lock(int *fd, char *fname, mode_t mode) {
 524 
 525         boolean_t read_lock = B_TRUE, same_inode;
 526 
 527         if ((mode == O_RDWR) || (mode == O_WRONLY)) {
 528                 read_lock = B_FALSE;
 529         }
 530 
 531         if (lock_file(*fd, read_lock, B_TRUE) != 0) {
 532                 return (-1);
 533         }
 534 
 535         /*
 536          * make sure another process did not modify the file
 537          * while we were trying to get the lock
 538          */
 539         if (is_inode_same(*fd, fname, &same_inode) != 0) {
 540                 (void) lock_file(*fd, B_TRUE, B_FALSE); /* unlock file */
 541                 return (-1);
 542         }
 543 
 544         while (!same_inode) {
 545                 /*
 546                  * need to unlock file, close, re-open the file,
 547                  * and re-acquire the lock
 548                  */
 549 
 550                 /* unlock file */
 551                 if (lock_file(*fd, B_TRUE, B_FALSE) != 0) {
 552                         return (-1);
 553                 }
 554 
 555                 (void) close(*fd);
 556 
 557                 /* re-open */
 558                 *fd = open_nointr(fname, mode|O_NONBLOCK);
 559                 if (*fd < 0) {
 560                         return (-1);
 561                 }
 562 
 563                 /* acquire lock again */
 564                 if (lock_file(*fd, read_lock, B_TRUE) != 0) {
 565                         return (-1);
 566                 }
 567 
 568                 if (is_inode_same(*fd, fname, &same_inode) != 0) {
 569                         (void) lock_file(*fd, B_TRUE, B_FALSE); /* unlock */
 570                         return (-1);
 571                 }
 572 
 573         }
 574 
 575         return (0);
 576 }
 577 
 578 /*
 579  * Open the keystore description file in the specified mode.
 580  * If the keystore doesn't exist, the "do_create_keystore"
 581  * argument determines if the keystore should be created
 582  */
 583 static int
 584 open_and_lock_keystore_desc(mode_t mode, boolean_t do_create_keystore,
 585     boolean_t lock_held)
 586 {
 587 
 588         int fd;
 589         char *fname, ks_desc_file[MAXPATHLEN];
 590 
 591         /* open the keystore description file in requested mode */
 592         fname = get_desc_file_path(ks_desc_file);
 593         fd = open_nointr(fname, mode|O_NONBLOCK);
 594         if (fd < 0) {
 595                 if ((errno == ENOENT) && (do_create_keystore)) {
 596                         if (create_keystore() < 0) {
 597                                 goto done;
 598                         }
 599                         fd = open_nointr(fname, mode|O_NONBLOCK);
 600                         if (fd < 0) {
 601                                 goto done;
 602                         }
 603                 } else {
 604                         goto done;
 605                 }
 606         }
 607 
 608         if (lock_held) {
 609                 /* already hold the lock */
 610                 return (fd);
 611         }
 612 
 613         if (acquire_file_lock(&fd, fname, mode) != 0) {
 614                 if (fd > 0) {
 615                         (void) close(fd);
 616                 }
 617                 return (-1);
 618         }
 619 
 620 done:
 621         return (fd);
 622 }
 623 
 624 
 625 /*
 626  * Set or remove read or write lock on keystore description file
 627  *
 628  * read_lock: true for read lock, false for write lock
 629  * set_lock: true for set a lock, false to remove a lock
 630  */
 631 static int
 632 lock_desc_file(boolean_t read_lock, boolean_t set_lock)
 633 {
 634 
 635         char ks_desc_file[MAXPATHLEN];
 636 
 637         if (set_lock) {
 638                 int oflag;
 639 
 640                 /*
 641                  * make sure desc_fd is not already used.  If used, it means
 642                  * some other lock is already set on the file
 643                  */
 644                 if (desc_fd > 0) {
 645                         return (-1);
 646                 }
 647 
 648                 (void) get_desc_file_path(ks_desc_file);
 649 
 650                 if (read_lock) {
 651                         oflag = O_RDONLY;
 652                 } else {
 653                         oflag = O_WRONLY;
 654                 }
 655                 if ((desc_fd = open_and_lock_keystore_desc(oflag,
 656                     B_FALSE, B_FALSE)) < 0) {
 657                         return (-1);
 658                 }
 659         } else {
 660                 /* make sure we have a valid fd */
 661                 if (desc_fd <= 0) {
 662                         return (-1);
 663                 }
 664 
 665                 if (lock_file(desc_fd, read_lock, B_FALSE) == 1) {
 666                         return (-1);
 667                 }
 668 
 669                 (void) close(desc_fd);
 670                 desc_fd = 0;
 671 
 672         }
 673         return (0);
 674 }
 675 
 676 static int
 677 open_and_lock_object_file(ks_obj_handle_t *ks_handle, int oflag,
 678     boolean_t lock_held)
 679 {
 680         char obj_fname[MAXPATHLEN];
 681         int fd;
 682 
 683         if (ks_handle->public) {
 684                 char pub_obj_path[MAXPATHLEN];
 685                 (void) snprintf(obj_fname, MAXPATHLEN, "%s/%s",
 686                     get_pub_obj_path(pub_obj_path), ks_handle->name);
 687         } else {
 688                 char pri_obj_path[MAXPATHLEN];
 689                 (void) snprintf(obj_fname, MAXPATHLEN, "%s/%s",
 690                     get_pri_obj_path(pri_obj_path), ks_handle->name);
 691         }
 692 
 693         fd = open_nointr(obj_fname, oflag|O_NONBLOCK);
 694         if (fd < 0) {
 695                 return (-1);
 696         }
 697 
 698         if (lock_held) {
 699                 /* already hold the lock */
 700                 return (fd);
 701         }
 702 
 703         if (acquire_file_lock(&fd, obj_fname, oflag) != 0) {
 704                 if (fd > 0) {
 705                         (void) close(fd);
 706                 }
 707                 return (-1);
 708         }
 709 
 710 
 711         return (fd);
 712 }
 713 
 714 
 715 /*
 716  * Update file version number in a temporary file that's
 717  * a copy of the keystore description file.
 718  * The update is NOT made to the original keystore description
 719  * file.  It makes the update in a tempoary file.
 720  *
 721  * Name of the temporary file is assumed to be provided, but
 722  * the file is assumed to not exist.
 723  *
 724  * return 0 if creating temp file is successful, returns -1 otherwise
 725  */
 726 static int
 727 create_updated_keystore_version(int fd, char *tmp_fname)
 728 {
 729         int version, tmp_fd;
 730         char buf[BUFSIZ];
 731         size_t nread;
 732 
 733         /* first, create the tempoary file */
 734         tmp_fd = open_nointr(tmp_fname,
 735             O_WRONLY|O_CREAT|O_EXCL|O_NONBLOCK, S_IRUSR|S_IWUSR);
 736         if (tmp_fd < 0) {
 737                 return (-1);
 738         }
 739 
 740         /*
 741          * copy everything from keystore version to temp file except
 742          * the keystore version.  Keystore version is updated
 743          *
 744          */
 745 
 746         /* pkcs11 version */
 747         if (readn_nointr(fd, buf, KS_PKCS11_VER_SIZE) != KS_PKCS11_VER_SIZE) {
 748                 goto cleanup;
 749         }
 750 
 751         if (writen_nointr(tmp_fd, buf, KS_PKCS11_VER_SIZE) !=
 752             KS_PKCS11_VER_SIZE) {
 753                 goto cleanup;
 754         }
 755 
 756         /* version number, it needs to be updated */
 757 
 758         /* read the current version number */
 759         if (readn_nointr(fd, &version, KS_VER_SIZE) != KS_VER_SIZE) {
 760                 goto cleanup;
 761         }
 762 
 763         version = SWAP32(version);
 764         version++;
 765         version = SWAP32(version);
 766 
 767         /* write the updated value to the tmp file */
 768         if (writen_nointr(tmp_fd, (void *)&version, KS_VER_SIZE)
 769             != KS_VER_SIZE) {
 770                 goto cleanup;
 771         }
 772 
 773         /* read rest of information, nothing needs to be updated */
 774         nread = readn_nointr(fd, buf, BUFSIZ);
 775         while (nread > 0) {
 776                 if (writen_nointr(tmp_fd, buf, nread) != nread) {
 777                         goto cleanup;
 778                 }
 779                 nread = readn_nointr(fd, buf, BUFSIZ);
 780         }
 781 
 782         (void) close(tmp_fd);
 783         return (0);     /* no error */
 784 
 785 cleanup:
 786         (void) close(tmp_fd);
 787         (void) remove(tmp_fname);
 788         return (-1);
 789 }
 790 
 791 static CK_RV
 792 get_all_objs_in_dir(DIR *dirp, ks_obj_handle_t *ks_handle,
 793     ks_obj_t **result_obj_list, boolean_t lock_held)
 794 {
 795         struct dirent *dp;
 796         ks_obj_t *obj;
 797         CK_RV rv;
 798 
 799         while ((dp = readdir(dirp)) != NULL) {
 800 
 801                 if (strncmp(dp->d_name, OBJ_PREFIX, OBJ_PREFIX_LEN) != 0)
 802                         continue;
 803 
 804                 (void) strcpy((char *)ks_handle->name, dp->d_name);
 805                 rv = soft_keystore_get_single_obj(ks_handle, &obj, lock_held);
 806                 if (rv != CKR_OK) {
 807                         return (rv);
 808                 }
 809                 if (obj != NULL) {
 810                         if (*result_obj_list == NULL) {
 811                                 *result_obj_list = obj;
 812                         } else {
 813                                 obj->next = *result_obj_list;
 814                                 *result_obj_list = obj;
 815                         }
 816                 }
 817         }
 818         return (CKR_OK);
 819 }
 820 
 821 /*
 822  * This function prepares the obj data for encryption by prepending
 823  * the FULL path of the file that will be used for storing
 824  * the object.  Having full path of the file as part of
 825  * of the data for the object will prevent an attacker from
 826  * copying a "bad" object into the keystore undetected.
 827  *
 828  * This function will always allocate:
 829  *      MAXPATHLEN + buf_len
 830  * amount of data.  If the full path of the filename doesn't occupy
 831  * the whole MAXPATHLEN, the rest of the space will just be empty.
 832  * It is the caller's responsibility to free the buffer allocated here.
 833  *
 834  * The allocated buffer is returned in the variable "prepared_buf"
 835  * if there's no error.
 836  *
 837  * Returns 0 if there's no error, -1 otherwise.
 838  */
 839 static int
 840 prepare_data_for_encrypt(char *obj_path, unsigned char *buf, CK_ULONG buf_len,
 841     unsigned char **prepared_buf, CK_ULONG *prepared_len)
 842 {
 843         *prepared_len = MAXPATHLEN + buf_len;
 844         *prepared_buf = malloc(*prepared_len);
 845         if (*prepared_buf == NULL) {
 846                 return (-1);
 847         }
 848 
 849         /*
 850          * only zero out the space for the path name.  I could zero out
 851          * the whole buffer, but that will be a waste of processing
 852          * cycle since the rest of the buffer will be 100% filled all
 853          * the time
 854          */
 855         bzero(*prepared_buf, MAXPATHLEN);
 856         (void) memcpy(*prepared_buf, obj_path, strlen(obj_path));
 857         (void) memcpy(*prepared_buf + MAXPATHLEN, buf, buf_len);
 858         return (0);
 859 }
 860 
 861 /*
 862  * retrieves the hashed pin from the keystore
 863  */
 864 static CK_RV
 865 get_hashed_pin(int fd, char **hashed_pin)
 866 {
 867         uint64_t hashed_pin_size;
 868 
 869         if (ks_hashed_pinlen_offset == -1) {
 870                 if (calculate_hashed_pin_offset(fd) != 0) {
 871                         return (CKR_FUNCTION_FAILED);
 872                 }
 873         }
 874 
 875         /* first, get size of the hashed pin */
 876         if (lseek(fd, ks_hashed_pinlen_offset, SEEK_SET)
 877             != ks_hashed_pinlen_offset) {
 878                 return (CKR_FUNCTION_FAILED);
 879         }
 880 
 881         if (readn_nointr(fd, (char *)&hashed_pin_size,
 882             KS_HASHED_PINLEN_SIZE) != KS_HASHED_PINLEN_SIZE) {
 883                 return (CKR_FUNCTION_FAILED);
 884         }
 885 
 886         hashed_pin_size = SWAP64(hashed_pin_size);
 887 
 888         *hashed_pin = malloc(hashed_pin_size + 1);
 889         if (*hashed_pin == NULL) {
 890                 return (CKR_HOST_MEMORY);
 891         }
 892 
 893         if ((readn_nointr(fd, *hashed_pin, hashed_pin_size))
 894             != (ssize_t)hashed_pin_size) {
 895                 freezero(*hashed_pin, hashed_pin_size + 1);
 896                 *hashed_pin = NULL;
 897                 return (CKR_FUNCTION_FAILED);
 898         }
 899         (*hashed_pin)[hashed_pin_size] = '\0';
 900         return (CKR_OK);
 901 }
 902 
 903 
 904 /*
 905  *      FUNCTION: soft_keystore_lock
 906  *
 907  *      ARGUMENTS:
 908  *              set_lock: TRUE to set readlock on the keystore object file,
 909  *                        FALSE to remove readlock on keystore object file.
 910  *
 911  *      RETURN VALUE:
 912  *
 913  *              0: success
 914  *              -1: failure
 915  *
 916  *      DESCRIPTION:
 917  *
 918  *              set or remove readlock on the keystore description file.
 919  */
 920 int
 921 soft_keystore_readlock(boolean_t set_lock)
 922 {
 923 
 924         return (lock_desc_file(B_TRUE, set_lock));
 925 }
 926 
 927 
 928 /*
 929  *      FUNCTION: soft_keystore_writelock
 930  *
 931  *      ARGUMENTS:
 932  *              set_lock: TRUE to set writelock on the keystore description file
 933  *                      FALSE to remove write lock on keystore description file.
 934  *
 935  *      RETURN VALUE:
 936  *
 937  *              0: no error
 938  *              1: some error occurred
 939  *
 940  *      DESCRIPTION:
 941  *              set/reset writelock on the keystore description file.
 942  */
 943 int
 944 soft_keystore_writelock(boolean_t set_lock)
 945 {
 946         return (lock_desc_file(B_FALSE, set_lock));
 947 
 948 }
 949 
 950 /*
 951  *
 952  *      FUNCTION: soft_keystore_lock_object
 953  *
 954  *      ARGUMENTS:
 955  *
 956  *              ks_handle: handle of the keystore object file to be accessed.
 957  *              read_lock: TRUE to set readlock on the keystore object file,
 958  *                        FALSE to set writelock on keystore object file.
 959  *
 960  *      RETURN VALUE:
 961  *
 962  *              If no error, file descriptor of locked file will be returned
 963  *              -1: some error occurred
 964  *
 965  *      DESCRIPTION:
 966  *
 967  *              set readlock or writelock on the keystore object file.
 968  */
 969 int
 970 soft_keystore_lock_object(ks_obj_handle_t *ks_handle, boolean_t read_lock)
 971 {
 972         int fd;
 973         int oflag;
 974 
 975         if (read_lock) {
 976                 oflag = O_RDONLY;
 977         } else {
 978                 oflag = O_WRONLY;
 979         }
 980 
 981         if ((fd = open_and_lock_object_file(ks_handle, oflag, B_FALSE)) < 0) {
 982                 return (-1);
 983         }
 984 
 985         return (fd);
 986 }
 987 
 988 /*
 989  *      FUNCTION: soft_keystore_unlock_object
 990  *
 991  *      ARGUMENTS:
 992  *              fd: file descriptor returned from soft_keystore_lock_object
 993  *
 994  *      RETURN VALUE:
 995  *              0: no error
 996  *              1: some error occurred while getting the pin
 997  *
 998  *      DESCRIPTION:
 999  *              set/reset writelock on the keystore object file.
1000  */
1001 int
1002 soft_keystore_unlock_object(int fd)
1003 {
1004         if (lock_file(fd, B_TRUE, B_FALSE) != 0) {
1005                 return (1);
1006         }
1007 
1008         (void) close(fd);
1009         return (0);
1010 }
1011 
1012 
1013 
1014 /*
1015  *      FUNCTION: soft_keystore_get_version
1016  *
1017  *      ARGUMENTS:
1018  *              version: pointer to caller allocated memory for storing
1019  *                       the version of the keystore.
1020  *              lock_held: TRUE if the lock is held by caller.
1021  *
1022  *      RETURN VALUE:
1023  *
1024  *              0: no error
1025  *              -1: some error occurred while getting the version number
1026  *
1027  *      DESCRIPTION:
1028  *              get the version number of the keystore from keystore
1029  *              description file.
1030  */
1031 int
1032 soft_keystore_get_version(uint_t *version, boolean_t lock_held)
1033 {
1034         int fd, ret_val = 0;
1035         uint_t buf;
1036 
1037         if ((fd = open_and_lock_keystore_desc(O_RDONLY,
1038             B_FALSE, lock_held)) < 0) {
1039                 return (-1);
1040         }
1041 
1042         if (lseek(fd, KS_VER_OFFSET, SEEK_SET) != KS_VER_OFFSET) {
1043                 ret_val = -1;
1044                 goto cleanup;
1045         }
1046 
1047         if (readn_nointr(fd, (char *)&buf, KS_VER_SIZE) != KS_VER_SIZE) {
1048                 ret_val = -1;
1049                 goto cleanup;
1050         }
1051         *version = SWAP32(buf);
1052 
1053 cleanup:
1054 
1055         if (!lock_held) {
1056                 if (lock_file(fd, B_TRUE, B_FALSE) < 0) {
1057                         ret_val = -1;
1058                 }
1059         }
1060 
1061         (void) close(fd);
1062         return (ret_val);
1063 }
1064 
1065 /*
1066  *      FUNCTION: soft_keystore_get_object_version
1067  *
1068  *      ARGUMENTS:
1069  *
1070  *              ks_handle: handle of the key store object to be accessed.
1071  *              version:
1072  *                      pointer to caller allocated memory for storing
1073  *                      the version of the object.
1074  *              lock_held: TRUE if the lock is held by caller.
1075  *
1076  *      RETURN VALUE:
1077  *
1078  *              0: no error
1079  *              -1: some error occurred while getting the pin
1080  *
1081  *      DESCRIPTION:
1082  *              get the version number of the specified token object.
1083  */
1084 int
1085 soft_keystore_get_object_version(ks_obj_handle_t *ks_handle,
1086     uint_t *version, boolean_t lock_held)
1087 {
1088         int fd, ret_val = 0;
1089         uint_t tmp;
1090 
1091         if ((fd = open_and_lock_object_file(ks_handle, O_RDONLY,
1092             lock_held)) < 0) {
1093                 return (-1);
1094         }
1095 
1096         /*
1097          * read version.  Version is always first item in object file
1098          * so, no need to do lseek
1099          */
1100         if (readn_nointr(fd, (char *)&tmp, OBJ_VER_SIZE) != OBJ_VER_SIZE) {
1101                 ret_val = -1;
1102                 goto cleanup;
1103         }
1104 
1105         *version = SWAP32(tmp);
1106 
1107 cleanup:
1108         if (!lock_held) {
1109                 if (lock_file(fd, B_TRUE, B_FALSE) < 0) {
1110                         ret_val = -1;
1111                 }
1112         }
1113 
1114 
1115         (void) close(fd);
1116         return (ret_val);
1117 }
1118 
1119 /*
1120  *              FUNCTION: soft_keystore_getpin
1121  *
1122  *              ARGUMENTS:
1123  *                      hashed_pin: pointer to caller allocated memory
1124  *                              for storing the pin to be returned.
1125  *                      lock_held: TRUE if the lock is held by caller.
1126  *
1127  *              RETURN VALUE:
1128  *
1129  *                      0: no error
1130  *                      -1: some error occurred while getting the pin
1131  *
1132  *              DESCRIPTION:
1133  *
1134  *                      Reads the MD5 hash from the keystore description
1135  *                      file and return it to the caller in the provided
1136  *                      buffer. If there is no PIN in the description file
1137  *                      because the file is just created, this function
1138  *                      will get a MD5 digest of the string "changeme",
1139  *                      store it in the file, and also return this
1140  *                      string to the caller.
1141  */
1142 int
1143 soft_keystore_getpin(char **hashed_pin, boolean_t lock_held)
1144 {
1145         int fd, ret_val = -1;
1146         CK_RV rv;
1147 
1148         if ((fd = open_and_lock_keystore_desc(O_RDONLY, B_FALSE,
1149             lock_held)) < 0) {
1150                 return (-1);
1151         }
1152 
1153         rv = get_hashed_pin(fd, hashed_pin);
1154         if (rv == CKR_OK) {
1155                 ret_val = 0;
1156         }
1157 
1158 cleanup:
1159         if (!lock_held) {
1160                 if (lock_file(fd, B_TRUE, B_FALSE) < 0) {
1161                         ret_val = -1;
1162                 }
1163         }
1164 
1165         (void) close(fd);
1166         return (ret_val);
1167 }
1168 
1169 
1170 /*
1171  * Generate a 16-byte Initialization Vector (IV).
1172  */
1173 CK_RV
1174 soft_gen_iv(CK_BYTE *iv)
1175 {
1176         return (pkcs11_get_nzero_urandom(iv, 16) < 0 ?
1177             CKR_DEVICE_ERROR : CKR_OK);
1178 }
1179 
1180 
1181 /*
1182  * This function reads all the data until the end of the file, and
1183  * put the data into the "buf" in argument.  Memory for buf will
1184  * be allocated in this function.  It is the caller's responsibility
1185  * to free it.  The number of bytes read will be returned
1186  * in the argument "bytes_read"
1187  *
1188  * returns CKR_OK if no error.  Other CKR error codes if there's an error
1189  */
1190 static CK_RV
1191 read_obj_data(int old_fd, char **buf, ssize_t *bytes_read)
1192 {
1193 
1194         ssize_t nread, loop_count;
1195         char *buf1 = NULL;
1196 
1197         *buf = malloc(BUFSIZ);
1198         if (*buf == NULL) {
1199                 return (CKR_HOST_MEMORY);
1200         }
1201 
1202         nread = readn_nointr(old_fd, *buf, BUFSIZ);
1203         if (nread < 0) {
1204                 free(*buf);
1205                 return (CKR_FUNCTION_FAILED);
1206         }
1207         loop_count = 1;
1208         while (nread == (loop_count * BUFSIZ)) {
1209                 ssize_t nread_tmp;
1210 
1211                 loop_count++;
1212                 /* more than BUFSIZ of data */
1213                 buf1 = realloc(*buf, loop_count * BUFSIZ);
1214                 if (buf1 == NULL) {
1215                         free(*buf);
1216                         return (CKR_HOST_MEMORY);
1217                 }
1218                 *buf = buf1;
1219                 nread_tmp = readn_nointr(old_fd,
1220                     *buf + ((loop_count - 1) * BUFSIZ), BUFSIZ);
1221                 if (nread_tmp < 0) {
1222                         free(*buf);
1223                         return (CKR_FUNCTION_FAILED);
1224                 }
1225                 nread += nread_tmp;
1226         }
1227         *bytes_read = nread;
1228         return (CKR_OK);
1229 }
1230 
1231 /*
1232  * Re-encrypt an object using the provided new_enc_key.  The new HMAC
1233  * is calculated using the new_hmac_key.  The global static variables
1234  * enc_key, and hmac_key will be used for decrypting the original
1235  * object, and verifying its signature.
1236  *
1237  * The re-encrypted object will be stored in the file named
1238  * in the "new_obj_name" variable.  The content of the "original"
1239  * file named in "orig_obj_name" is not disturbed.
1240  *
1241  * Returns 0 if there's no error, returns -1 otherwise.
1242  *
1243  */
1244 static int
1245 reencrypt_obj(soft_object_t *new_enc_key, soft_object_t *new_hmac_key,
1246     char *orig_obj_name, char *new_obj_name) {
1247 
1248         int old_fd, new_fd, version, ret_val = -1;
1249         CK_BYTE iv[OBJ_IV_SIZE], old_iv[OBJ_IV_SIZE];
1250         ssize_t nread;
1251         CK_ULONG decrypted_len, encrypted_len, hmac_len;
1252         CK_BYTE hmac[OBJ_HMAC_SIZE], *decrypted_buf = NULL, *buf = NULL;
1253 
1254         old_fd = open_nointr(orig_obj_name, O_RDONLY|O_NONBLOCK);
1255         if (old_fd < 0) {
1256                 return (-1);
1257         }
1258 
1259         if (acquire_file_lock(&old_fd, orig_obj_name, O_RDONLY) != 0) {
1260                 if (old_fd > 0) {
1261                         (void) close(old_fd);
1262                 }
1263                 return (-1);
1264         }
1265 
1266         new_fd = open_nointr(new_obj_name,
1267             O_WRONLY|O_CREAT|O_EXCL|O_NONBLOCK, S_IRUSR|S_IWUSR);
1268         if (new_fd < 0) {
1269                 (void) close(old_fd);
1270                 return (-1);
1271         }
1272 
1273         if (lock_file(new_fd, B_FALSE, B_TRUE) != 0) {
1274                 /* unlock old file */
1275                 (void) lock_file(old_fd, B_TRUE, B_FALSE);
1276                 (void) close(old_fd);
1277                 (void) close(new_fd);
1278                 return (-1);
1279         }
1280 
1281         /* read version, increment, and write to tmp file */
1282         if (readn_nointr(old_fd, (char *)&version, OBJ_VER_SIZE)
1283             != OBJ_VER_SIZE) {
1284                 goto cleanup;
1285         }
1286 
1287         version = SWAP32(version);
1288         version++;
1289         version = SWAP32(version);
1290 
1291         if (writen_nointr(new_fd, (char *)&version, OBJ_VER_SIZE)
1292             != OBJ_VER_SIZE) {
1293                 goto cleanup;
1294         }
1295 
1296         /* read old iv */
1297         if (readn_nointr(old_fd, (char *)old_iv, OBJ_IV_SIZE) != OBJ_IV_SIZE) {
1298                 goto cleanup;
1299         }
1300 
1301         /* generate new IV */
1302         if (soft_gen_iv(iv) != CKR_OK) {
1303                 goto cleanup;
1304         }
1305 
1306         if (writen_nointr(new_fd, (char *)iv, OBJ_IV_SIZE) != OBJ_IV_SIZE) {
1307                 goto cleanup;
1308         }
1309 
1310         /* seek to the original encrypted data, and read all of them */
1311         if (lseek(old_fd, OBJ_DATA_OFFSET, SEEK_SET) != OBJ_DATA_OFFSET) {
1312                 goto cleanup;
1313         }
1314 
1315         if (read_obj_data(old_fd, (char **)&buf, &nread) != CKR_OK) {
1316                 goto cleanup;
1317         }
1318 
1319         /* decrypt data using old key */
1320         decrypted_len = 0;
1321         if (soft_keystore_crypt(enc_key, old_iv, B_FALSE, buf, nread,
1322             NULL, &decrypted_len) != CKR_OK) {
1323                 freezero(buf, nread);
1324                 goto cleanup;
1325         }
1326 
1327         decrypted_buf = malloc(decrypted_len);
1328         if (decrypted_buf == NULL) {
1329                 freezero(buf, nread);
1330                 goto cleanup;
1331         }
1332 
1333         if (soft_keystore_crypt(enc_key, old_iv, B_FALSE, buf, nread,
1334             decrypted_buf, &decrypted_len) != CKR_OK) {
1335                 freezero(buf, nread);
1336                 freezero(decrypted_buf, decrypted_len);
1337         }
1338 
1339         freezero(buf, nread);
1340 
1341         /* re-encrypt with new key */
1342         encrypted_len = 0;
1343         if (soft_keystore_crypt(new_enc_key, iv, B_TRUE, decrypted_buf,
1344             decrypted_len, NULL, &encrypted_len) != CKR_OK) {
1345                 freezero(decrypted_buf, decrypted_len);
1346                 goto cleanup;
1347         }
1348 
1349         buf = malloc(encrypted_len);
1350         if (buf == NULL) {
1351                 freezero(decrypted_buf, decrypted_len);
1352                 goto cleanup;
1353         }
1354 
1355         if (soft_keystore_crypt(new_enc_key, iv, B_TRUE, decrypted_buf,
1356             decrypted_len, buf, &encrypted_len) != CKR_OK) {
1357                 freezero(buf, encrypted_len);
1358                 freezero(buf, decrypted_len);
1359                 goto cleanup;
1360         }
1361 
1362         freezero(decrypted_buf, decrypted_len);
1363 
1364         /* calculate hmac on re-encrypted data using new hmac key */
1365         hmac_len = OBJ_HMAC_SIZE;
1366         if (soft_keystore_hmac(new_hmac_key, B_TRUE, buf,
1367             encrypted_len, hmac, &hmac_len) != CKR_OK) {
1368                 freezero(buf, encrypted_len);
1369                 goto cleanup;
1370         }
1371 
1372         /* just for sanity check */
1373         if (hmac_len != OBJ_HMAC_SIZE) {
1374                 freezero(buf, encrypted_len);
1375                 goto cleanup;
1376         }
1377 
1378         /* write new hmac */
1379         if (writen_nointr(new_fd, (char *)hmac, OBJ_HMAC_SIZE)
1380             != OBJ_HMAC_SIZE) {
1381                 freezero(buf, encrypted_len);
1382                 goto cleanup;
1383         }
1384 
1385         /* write re-encrypted buffer to temp file */
1386         if (writen_nointr(new_fd, (void *)buf, encrypted_len)
1387             != encrypted_len) {
1388                 freezero(buf, encrypted_len);
1389                 goto cleanup;
1390         }
1391         freezero(buf, encrypted_len);
1392         ret_val = 0;
1393 
1394 cleanup:
1395         /* unlock the files */
1396         (void) lock_file(old_fd, B_TRUE, B_FALSE);
1397         (void) lock_file(new_fd, B_FALSE, B_FALSE);
1398 
1399         (void) close(old_fd);
1400         (void) close(new_fd);
1401         if (ret_val != 0) {
1402                 (void) remove(new_obj_name);
1403         }
1404         return (ret_val);
1405 }
1406 
1407 /*
1408  *      FUNCTION: soft_keystore_setpin
1409  *
1410  *      ARGUMENTS:
1411  *              newpin: new pin entered by the user.
1412  *              lock_held: TRUE if the lock is held by caller.
1413  *
1414  *      RETURN VALUE:
1415  *              0: no error
1416  *              -1: failure
1417  *
1418  *      DESCRIPTION:
1419  *
1420  *              This function does the following:
1421  *
1422  *              1) Generates crypted value of newpin and store it
1423  *                 in keystore description file.
1424  *              2) Dervies the new encryption key from the newpin.  This key
1425  *                 will be used to re-encrypt the private token objects.
1426  *              3) Re-encrypt all of this user's existing private token
1427  *                 objects (if any).
1428  *              4) Increments the keystore version number.
1429  */
1430 int
1431 soft_keystore_setpin(uchar_t *oldpin, uchar_t *newpin, boolean_t lock_held)
1432 {
1433         int fd, tmp_ks_fd, version, ret_val = -1;
1434         soft_object_t *new_crypt_key = NULL, *new_hmac_key = NULL;
1435         char filebuf[BUFSIZ];
1436         DIR     *pri_dirp;
1437         struct dirent *pri_ent;
1438         char pri_obj_path[MAXPATHLEN], ks_desc_file[MAXPATHLEN],
1439             tmp_ks_desc_name[MAXPATHLEN];
1440         typedef struct priobjs {
1441                 char orig_name[MAXPATHLEN];
1442                 char tmp_name[MAXPATHLEN];
1443                 struct priobjs *next;
1444         } priobjs_t;
1445         priobjs_t *pri_objs = NULL, *tmp;
1446         CK_BYTE *crypt_salt = NULL, *hmac_salt = NULL;
1447         boolean_t pin_never_set = B_FALSE, user_logged_in;
1448         char *new_hashed_pin = NULL;
1449         uint64_t hashed_pin_salt_length, new_hashed_pin_len, swaped_val;
1450         char *hashed_pin_salt = NULL;
1451         priobjs_t *obj;
1452 
1453         if ((enc_key == NULL) ||
1454             (enc_key->magic_marker != SOFTTOKEN_OBJECT_MAGIC)) {
1455                 user_logged_in = B_FALSE;
1456         } else {
1457                 user_logged_in = B_TRUE;
1458         }
1459 
1460         if ((fd = open_and_lock_keystore_desc(O_RDWR, B_TRUE,
1461             lock_held)) < 0) {
1462                 return (-1);
1463         }
1464 
1465         (void) get_desc_file_path(ks_desc_file);
1466         (void) get_tmp_desc_file_path(tmp_ks_desc_name);
1467 
1468         /*
1469          * create a tempoary file for the keystore description
1470          * file for updating version and counter information
1471          */
1472         tmp_ks_fd = open_nointr(tmp_ks_desc_name,
1473             O_RDWR|O_CREAT|O_EXCL|O_NONBLOCK, S_IRUSR|S_IWUSR);
1474         if (tmp_ks_fd < 0) {
1475                 (void) close(fd);
1476                 return (-1);
1477         }
1478 
1479         /* read and write PKCS version to temp file */
1480         if (readn_nointr(fd, filebuf, KS_PKCS11_VER_SIZE)
1481             != KS_PKCS11_VER_SIZE) {
1482                 goto cleanup;
1483         }
1484 
1485         if (writen_nointr(tmp_ks_fd, filebuf, KS_PKCS11_VER_SIZE)
1486             != KS_PKCS11_VER_SIZE) {
1487                 goto cleanup;
1488         }
1489 
1490         /* get version number, and write updated number to temp file */
1491         if (readn_nointr(fd, &version, KS_VER_SIZE) != KS_VER_SIZE) {
1492                 goto cleanup;
1493         }
1494 
1495         version = SWAP32(version);
1496         version++;
1497         version = SWAP32(version);
1498 
1499         if (writen_nointr(tmp_ks_fd, (void *)&version, KS_VER_SIZE)
1500             != KS_VER_SIZE) {
1501                 goto cleanup;
1502         }
1503 
1504 
1505         /* read and write counter, no modification necessary */
1506         if (readn_nointr(fd, filebuf, KS_COUNTER_SIZE) != KS_COUNTER_SIZE) {
1507                 goto cleanup;
1508         }
1509 
1510         if (writen_nointr(tmp_ks_fd, filebuf, KS_COUNTER_SIZE)
1511             != KS_COUNTER_SIZE) {
1512                 goto cleanup;
1513         }
1514 
1515         /* read old encryption salt */
1516         crypt_salt = malloc(KS_KEY_SALT_SIZE);
1517         if (crypt_salt == NULL) {
1518                 goto cleanup;
1519         }
1520         if (readn_nointr(fd, (char *)crypt_salt, KS_KEY_SALT_SIZE)
1521             != KS_KEY_SALT_SIZE) {
1522                 goto cleanup;
1523         }
1524 
1525         /* read old hmac salt */
1526         hmac_salt = malloc(KS_HMAC_SALT_SIZE);
1527         if (hmac_salt == NULL) {
1528                 goto cleanup;
1529         }
1530         if (readn_nointr(fd, (char *)hmac_salt, KS_HMAC_SALT_SIZE)
1531             != KS_HMAC_SALT_SIZE) {
1532                 goto cleanup;
1533         }
1534 
1535         /* just create some empty bytes */
1536         bzero(filebuf, sizeof (filebuf));
1537 
1538         if (memcmp(crypt_salt, filebuf, KS_KEY_SALT_SIZE) == 0) {
1539                 /* PIN as never been set */
1540                 CK_BYTE *new_crypt_salt = NULL, *new_hmac_salt = NULL;
1541 
1542                 pin_never_set = B_TRUE;
1543                 if (soft_gen_crypt_key(newpin, &new_crypt_key, &new_crypt_salt)
1544                     != CKR_OK) {
1545                         goto cleanup;
1546                 }
1547                 if (writen_nointr(tmp_ks_fd, (void *)new_crypt_salt,
1548                     KS_KEY_SALT_SIZE) != KS_KEY_SALT_SIZE) {
1549                         freezero(new_crypt_salt,
1550                             KS_KEY_SALT_SIZE);
1551                         (void) soft_cleanup_object(new_crypt_key);
1552                         goto cleanup;
1553                 }
1554                 freezero(new_crypt_salt, KS_KEY_SALT_SIZE);
1555 
1556                 if (soft_gen_hmac_key(newpin, &new_hmac_key, &new_hmac_salt)
1557                     != CKR_OK) {
1558                         (void) soft_cleanup_object(new_crypt_key);
1559                         goto cleanup;
1560                 }
1561                 if (writen_nointr(tmp_ks_fd, (void *)new_hmac_salt,
1562                     KS_HMAC_SALT_SIZE) != KS_HMAC_SALT_SIZE) {
1563                         freezero(new_hmac_salt,
1564                             KS_HMAC_SALT_SIZE);
1565                         goto cleanup3;
1566                 }
1567                 freezero(new_hmac_salt, KS_HMAC_SALT_SIZE);
1568         } else {
1569                 if (soft_gen_crypt_key(newpin, &new_crypt_key,
1570                     (CK_BYTE **)&crypt_salt) != CKR_OK) {
1571                         goto cleanup;
1572                 }
1573                 /* no change to the encryption salt */
1574                 if (writen_nointr(tmp_ks_fd, (void *)crypt_salt,
1575                     KS_KEY_SALT_SIZE) != KS_KEY_SALT_SIZE) {
1576                         (void) soft_cleanup_object(new_crypt_key);
1577                         goto cleanup;
1578                 }
1579 
1580                 if (soft_gen_hmac_key(newpin, &new_hmac_key,
1581                     (CK_BYTE **)&hmac_salt) != CKR_OK) {
1582                         (void) soft_cleanup_object(new_crypt_key);
1583                         goto cleanup;
1584                 }
1585 
1586                 /* no change to the hmac salt */
1587                 if (writen_nointr(tmp_ks_fd, (void *)hmac_salt,
1588                     KS_HMAC_SALT_SIZE) != KS_HMAC_SALT_SIZE) {
1589                         goto cleanup3;
1590                 }
1591         }
1592 
1593         /*
1594          * read hashed pin salt, and write to updated keystore description
1595          * file unmodified.
1596          */
1597         if (readn_nointr(fd, (char *)&hashed_pin_salt_length,
1598             KS_HASHED_PIN_SALT_LEN_SIZE) != KS_HASHED_PIN_SALT_LEN_SIZE) {
1599                 goto cleanup3;
1600         }
1601 
1602         if (writen_nointr(tmp_ks_fd, (void *)&hashed_pin_salt_length,
1603             KS_HASHED_PIN_SALT_LEN_SIZE) != KS_HASHED_PIN_SALT_LEN_SIZE) {
1604                 goto cleanup3;
1605         }
1606 
1607         hashed_pin_salt_length = SWAP64(hashed_pin_salt_length);
1608 
1609         hashed_pin_salt = malloc(hashed_pin_salt_length + 1);
1610         if (hashed_pin_salt == NULL) {
1611                 goto cleanup3;
1612         }
1613 
1614         if ((readn_nointr(fd, hashed_pin_salt, hashed_pin_salt_length)) !=
1615             (ssize_t)hashed_pin_salt_length) {
1616                 freezero(hashed_pin_salt,
1617                     hashed_pin_salt_length + 1);
1618                 goto cleanup3;
1619         }
1620 
1621         if ((writen_nointr(tmp_ks_fd, hashed_pin_salt, hashed_pin_salt_length))
1622             != (ssize_t)hashed_pin_salt_length) {
1623                 freezero(hashed_pin_salt,
1624                     hashed_pin_salt_length + 1);
1625                 goto cleanup3;
1626         }
1627 
1628         hashed_pin_salt[hashed_pin_salt_length] = '\0';
1629 
1630         /* old hashed pin length and value can be ignored, generate new one */
1631         if (soft_gen_hashed_pin(newpin, &new_hashed_pin,
1632             &hashed_pin_salt) < 0) {
1633                 freezero(hashed_pin_salt,
1634                     hashed_pin_salt_length + 1);
1635                 goto cleanup3;
1636         }
1637 
1638         freezero(hashed_pin_salt, hashed_pin_salt_length + 1);
1639 
1640         if (new_hashed_pin == NULL) {
1641                 goto cleanup3;
1642         }
1643 
1644         new_hashed_pin_len = strlen(new_hashed_pin);
1645 
1646         /* write new hashed pin length to file */
1647         swaped_val = SWAP64(new_hashed_pin_len);
1648         if (writen_nointr(tmp_ks_fd, (void *)&swaped_val,
1649             KS_HASHED_PINLEN_SIZE) != KS_HASHED_PINLEN_SIZE) {
1650                 goto cleanup3;
1651         }
1652 
1653         if (writen_nointr(tmp_ks_fd, (void *)new_hashed_pin,
1654             new_hashed_pin_len) != (ssize_t)new_hashed_pin_len) {
1655                 goto cleanup3;
1656         }
1657 
1658         if (pin_never_set) {
1659                 /* there was no private object, no need to re-encrypt them */
1660                 goto rename_desc_file;
1661         }
1662 
1663         /* re-encrypt all the private objects */
1664         pri_dirp = opendir(get_pri_obj_path(pri_obj_path));
1665         if (pri_dirp == NULL) {
1666                 /*
1667                  * this directory should exist, even if it doesn't contain
1668                  * any objects.  Don't want to update the pin if the
1669                  * keystore is somehow messed up.
1670                  */
1671 
1672                 goto cleanup3;
1673         }
1674 
1675         /* if user did not login, need to set the old pin */
1676         if (!user_logged_in) {
1677                 if (soft_keystore_authpin(oldpin) != 0) {
1678                         goto cleanup3;
1679                 }
1680         }
1681 
1682         while ((pri_ent = readdir(pri_dirp)) != NULL) {
1683 
1684                 if ((strcmp(pri_ent->d_name, ".") == 0) ||
1685                     (strcmp(pri_ent->d_name, "..") == 0) ||
1686                     (strncmp(pri_ent->d_name, TMP_OBJ_PREFIX,
1687                     strlen(TMP_OBJ_PREFIX)) == 0)) {
1688                         continue;
1689                 }
1690 
1691                 obj = malloc(sizeof (priobjs_t));
1692                 if (obj == NULL) {
1693                         goto cleanup2;
1694                 }
1695                 (void) snprintf(obj->orig_name, MAXPATHLEN,
1696                     "%s/%s", pri_obj_path, pri_ent->d_name);
1697                 (void) snprintf(obj->tmp_name, MAXPATHLEN, "%s/%s%s",
1698                     pri_obj_path, TMP_OBJ_PREFIX,
1699                     (pri_ent->d_name) + OBJ_PREFIX_LEN);
1700                 if (reencrypt_obj(new_crypt_key, new_hmac_key,
1701                     obj->orig_name, obj->tmp_name) != 0) {
1702                         free(obj);
1703                         goto cleanup2;
1704                 }
1705 
1706                 /* insert into list of file to be renamed */
1707                 if (pri_objs == NULL) {
1708                         obj->next = NULL;
1709                         pri_objs = obj;
1710                 } else {
1711                         obj->next = pri_objs;
1712                         pri_objs = obj;
1713                 }
1714         }
1715 
1716         /* rename all the private objects */
1717         tmp = pri_objs;
1718         while (tmp) {
1719                 (void) rename(tmp->tmp_name, tmp->orig_name);
1720                 tmp = tmp->next;
1721         }
1722 
1723 rename_desc_file:
1724 
1725         /* destroy the old encryption key, and hmac key */
1726         if ((!pin_never_set) && (user_logged_in)) {
1727                 (void) soft_cleanup_object(enc_key);
1728                 (void) soft_cleanup_object(hmac_key);
1729         }
1730 
1731         if (user_logged_in) {
1732                 enc_key = new_crypt_key;
1733                 hmac_key = new_hmac_key;
1734         }
1735         (void) rename(tmp_ks_desc_name, ks_desc_file);
1736 
1737         ret_val = 0;
1738 
1739 cleanup2:
1740         if (pri_objs != NULL) {
1741                 priobjs_t *p = pri_objs;
1742                 while (p) {
1743                         tmp = p->next;
1744                         free(p);
1745                         p = tmp;
1746                 }
1747         }
1748         if (!pin_never_set) {
1749                 (void) closedir(pri_dirp);
1750         }
1751 
1752         if ((!user_logged_in) && (!pin_never_set)) {
1753                 (void) soft_cleanup_object(enc_key);
1754                 (void) soft_cleanup_object(hmac_key);
1755                 enc_key = NULL;
1756                 hmac_key = NULL;
1757         }
1758 cleanup3:
1759         if ((ret_val != 0) || (!user_logged_in)) {
1760                 (void) soft_cleanup_object(new_crypt_key);
1761                 (void) soft_cleanup_object(new_hmac_key);
1762         }
1763 
1764 cleanup:
1765         if (!lock_held) {
1766                 if (lock_file(fd, B_FALSE, B_FALSE) < 0) {
1767                         ret_val = 1;
1768                 }
1769         }
1770         freezero(crypt_salt, KS_KEY_SALT_SIZE);
1771         freezero(hmac_salt, KS_HMAC_SALT_SIZE);
1772         (void) close(fd);
1773         (void) close(tmp_ks_fd);
1774         if (ret_val != 0) {
1775                 (void) remove(tmp_ks_desc_name);
1776         }
1777         return (ret_val);
1778 }
1779 
1780 /*
1781  *      FUNCTION: soft_keystore_authpin
1782  *
1783  *      ARGUMENTS:
1784  *              pin: pin specified by the user for logging into
1785  *                   the keystore.
1786  *
1787  *      RETURN VALUE:
1788  *              0: if no error
1789  *              -1: if there is any error
1790  *
1791  *      DESCRIPTION:
1792  *
1793  *              This function takes the pin specified in the argument
1794  *              and generates an encryption key based on the pin.
1795  *              The generated encryption key will be used for
1796  *              all future encryption and decryption for private
1797  *              objects.  Before this function is called, none
1798  *              of the keystore related interfaces is able
1799  *              to decrypt/encrypt any private object.
1800  */
1801 int
1802 soft_keystore_authpin(uchar_t  *pin)
1803 {
1804         int fd;
1805         int ret_val = -1;
1806         CK_BYTE *crypt_salt = NULL, *hmac_salt;
1807 
1808         /* get the salt from the keystore description file */
1809         if ((fd = open_and_lock_keystore_desc(O_RDONLY,
1810             B_FALSE, B_FALSE)) < 0) {
1811                 return (-1);
1812         }
1813 
1814         crypt_salt = malloc(KS_KEY_SALT_SIZE);
1815         if (crypt_salt == NULL) {
1816                 goto cleanup;
1817         }
1818 
1819         if (lseek(fd, KS_KEY_SALT_OFFSET, SEEK_SET) != KS_KEY_SALT_OFFSET) {
1820                 goto cleanup;
1821         }
1822 
1823         if (readn_nointr(fd, (char *)crypt_salt, KS_KEY_SALT_SIZE)
1824             != KS_KEY_SALT_SIZE) {
1825                 goto cleanup;
1826         }
1827 
1828         if (soft_gen_crypt_key(pin, &enc_key, (CK_BYTE **)&crypt_salt)
1829             != CKR_OK) {
1830                 goto cleanup;
1831         }
1832 
1833         hmac_salt = malloc(KS_HMAC_SALT_SIZE);
1834         if (hmac_salt == NULL) {
1835                 goto cleanup;
1836         }
1837 
1838         if (lseek(fd, KS_HMAC_SALT_OFFSET, SEEK_SET) != KS_HMAC_SALT_OFFSET) {
1839                 goto cleanup;
1840         }
1841 
1842         if (readn_nointr(fd, (char *)hmac_salt, KS_HMAC_SALT_SIZE)
1843             != KS_HMAC_SALT_SIZE) {
1844                 goto cleanup;
1845         }
1846 
1847         if (soft_gen_hmac_key(pin, &hmac_key, (CK_BYTE **)&hmac_salt)
1848             != CKR_OK) {
1849                 goto cleanup;
1850         }
1851 
1852         ret_val = 0;
1853 
1854 cleanup:
1855         /* unlock the file */
1856         (void) lock_file(fd, B_TRUE, B_FALSE);
1857         (void) close(fd);
1858         freezero(crypt_salt, KS_KEY_SALT_SIZE);
1859         freezero(hmac_salt, KS_HMAC_SALT_SIZE);
1860         return (ret_val);
1861 }
1862 
1863 /*
1864  *      FUNCTION: soft_keystore_get_objs
1865  *
1866  *      ARGUMENTS:
1867  *
1868  *              search_type: Specify type of objects to return.
1869  *              lock_held: TRUE if the lock is held by caller.
1870  *
1871  *
1872  *      RETURN VALUE:
1873  *
1874  *              NULL: if there are no object in the database.
1875  *
1876  *              Otherwise, linked list of objects as requested
1877  *              in search type.
1878  *
1879  *              The linked list returned will need to be freed
1880  *              by the caller.
1881  *
1882  *      DESCRIPTION:
1883  *
1884  *              Returns objects as requested.
1885  *
1886  *              If private objects is requested, and the caller
1887  *              has not previously passed in the pin or if the pin
1888  *              passed in is wrong, private objects will not
1889  *              be returned.
1890  *
1891  *              The buffers returned for private objects are already
1892  *              decrypted.
1893  */
1894 CK_RV
1895 soft_keystore_get_objs(ks_search_type_t search_type,
1896     ks_obj_t **result_obj_list, boolean_t lock_held)
1897 {
1898         DIR *dirp;
1899         ks_obj_handle_t ks_handle;
1900         CK_RV rv;
1901         ks_obj_t *tmp;
1902         int ks_fd;
1903 
1904         *result_obj_list = NULL;
1905 
1906         /*
1907          * lock the keystore description file in "read" mode so that
1908          * objects won't get added/deleted/modified while we are
1909          * doing the search
1910          */
1911         if ((ks_fd = open_and_lock_keystore_desc(O_RDONLY, B_FALSE,
1912             B_FALSE)) < 0) {
1913                 return (CKR_FUNCTION_FAILED);
1914         }
1915 
1916         if ((search_type == ALL_TOKENOBJS) || (search_type == PUB_TOKENOBJS)) {
1917 
1918                 char pub_obj_path[MAXPATHLEN];
1919 
1920                 ks_handle.public = B_TRUE;
1921 
1922                 if ((dirp = opendir(get_pub_obj_path(pub_obj_path))) == NULL) {
1923                         (void) lock_file(ks_fd, B_TRUE, B_FALSE);
1924                         (void) close(ks_fd);
1925                         return (CKR_FUNCTION_FAILED);
1926                 }
1927                 rv = get_all_objs_in_dir(dirp, &ks_handle, result_obj_list,
1928                     lock_held);
1929                 if (rv != CKR_OK) {
1930                         (void) closedir(dirp);
1931                         goto cleanup;
1932                 }
1933 
1934                 (void) closedir(dirp);
1935         }
1936 
1937         if ((search_type == ALL_TOKENOBJS) || (search_type == PRI_TOKENOBJS)) {
1938 
1939                 char pri_obj_path[MAXPATHLEN];
1940 
1941                 if ((enc_key == NULL) ||
1942                     (enc_key->magic_marker != SOFTTOKEN_OBJECT_MAGIC)) {
1943                         /* has not login - no need to go any further */
1944                         (void) lock_file(ks_fd, B_TRUE, B_FALSE);
1945                         (void) close(ks_fd);
1946                         return (CKR_OK);
1947                 }
1948 
1949                 ks_handle.public = B_FALSE;
1950 
1951                 if ((dirp = opendir(get_pri_obj_path(pri_obj_path))) == NULL) {
1952                         (void) lock_file(ks_fd, B_TRUE, B_FALSE);
1953                         (void) close(ks_fd);
1954                         return (CKR_OK);
1955                 }
1956                 rv = get_all_objs_in_dir(dirp, &ks_handle, result_obj_list,
1957                     lock_held);
1958                 if (rv != CKR_OK) {
1959                         (void) closedir(dirp);
1960                         goto cleanup;
1961                 }
1962 
1963                 (void) closedir(dirp);
1964         }
1965         /* close the keystore description file */
1966         (void) lock_file(ks_fd, B_TRUE, B_FALSE);
1967         (void) close(ks_fd);
1968         return (CKR_OK);
1969 cleanup:
1970 
1971         /* close the keystore description file */
1972         (void) lock_file(ks_fd, B_TRUE, B_FALSE);
1973         (void) close(ks_fd);
1974 
1975         /* free all the objects found before hitting the error */
1976         tmp = *result_obj_list;
1977         while (tmp) {
1978                 *result_obj_list = tmp->next;
1979                 freezero(tmp->buf, tmp->size);
1980                 free(tmp);
1981                 tmp = *result_obj_list;
1982         }
1983         *result_obj_list = NULL;
1984         return (rv);
1985 }
1986 
1987 
1988 /*
1989  *      FUNCTION: soft_keystore_get_single_obj
1990  *
1991  *      ARGUMENTS:
1992  *              ks_handle: handle of the key store object to be accessed
1993  *              lock_held: TRUE if the lock is held by caller.
1994  *
1995  *      RETURN VALUE:
1996  *
1997  *              NULL: if handle doesn't match any object
1998  *
1999  *              Otherwise, the object is returned in
2000  *              the same structure used in soft_keystore_get_objs().
2001  *              The structure need to be freed by the caller.
2002  *
2003  *      DESCRIPTION:
2004  *
2005  *              Retrieves the object specified by the object
2006  *              handle to the caller.
2007  *
2008  *              If a private object is requested, and the caller
2009  *              has not previously passed in the pin or if the pin
2010  *              passed in is wrong, the requested private object will not
2011  *              be returned.
2012  *
2013  *              The buffer returned for the requested private object
2014  *              is already decrypted.
2015  */
2016 CK_RV
2017 soft_keystore_get_single_obj(ks_obj_handle_t *ks_handle,
2018     ks_obj_t **return_obj, boolean_t lock_held)
2019 {
2020 
2021         ks_obj_t *obj;
2022         uchar_t iv[OBJ_IV_SIZE], obj_hmac[OBJ_HMAC_SIZE];
2023         uchar_t *buf, *decrypted_buf;
2024         int fd;
2025         ssize_t nread;
2026         CK_RV rv = CKR_FUNCTION_FAILED;
2027 
2028         if (!(ks_handle->public)) {
2029                 if ((enc_key == NULL) ||
2030                     (enc_key->magic_marker != SOFTTOKEN_OBJECT_MAGIC)) {
2031                         return (CKR_FUNCTION_FAILED);
2032                 }
2033         }
2034 
2035         if ((fd = open_and_lock_object_file(ks_handle, O_RDONLY,
2036             lock_held)) < 0) {
2037                 return (CKR_FUNCTION_FAILED);
2038         }
2039 
2040         obj = malloc(sizeof (ks_obj_t));
2041         if (obj == NULL) {
2042                 return (CKR_HOST_MEMORY);
2043         }
2044 
2045         obj->next = NULL;
2046 
2047         (void) strcpy((char *)((obj->ks_handle).name),
2048             (char *)ks_handle->name);
2049         (obj->ks_handle).public = ks_handle->public;
2050 
2051         /* 1st get the version */
2052         if (readn_nointr(fd, &(obj->obj_version), OBJ_VER_SIZE)
2053             != OBJ_VER_SIZE) {
2054                 goto cleanup;
2055         }
2056         obj->obj_version = SWAP32(obj->obj_version);
2057 
2058         /* Then, read the IV */
2059         if (readn_nointr(fd, iv, OBJ_IV_SIZE) != OBJ_IV_SIZE) {
2060                 goto cleanup;
2061         }
2062 
2063         /* Then, read the HMAC */
2064         if (readn_nointr(fd, obj_hmac, OBJ_HMAC_SIZE) != OBJ_HMAC_SIZE) {
2065                 goto cleanup;
2066         }
2067 
2068         /* read the object */
2069         rv = read_obj_data(fd, (char **)&buf, &nread);
2070         if (rv != CKR_OK) {
2071                 goto cleanup;
2072         }
2073 
2074         if (ks_handle->public) {
2075                 obj->size = nread;
2076                 obj->buf = buf;
2077                 *return_obj = obj;
2078         } else {
2079 
2080                 CK_ULONG out_len = 0, hmac_size;
2081 
2082                 /* verify HMAC of the object, make sure it matches */
2083                 hmac_size = OBJ_HMAC_SIZE;
2084                 if (soft_keystore_hmac(hmac_key, B_FALSE, buf,
2085                     nread, obj_hmac, &hmac_size) != CKR_OK) {
2086                         freezero(buf, nread);
2087                         rv = CKR_FUNCTION_FAILED;
2088                         goto cleanup;
2089                 }
2090 
2091                 /* decrypt object */
2092                 if (soft_keystore_crypt(enc_key, iv, B_FALSE, buf, nread,
2093                     NULL, &out_len) != CKR_OK) {
2094                         freezero(buf, nread);
2095                         rv = CKR_FUNCTION_FAILED;
2096                         goto cleanup;
2097                 }
2098 
2099                 decrypted_buf = malloc(sizeof (uchar_t) * out_len);
2100                 if (decrypted_buf == NULL) {
2101                         freezero(buf, nread);
2102                         rv = CKR_HOST_MEMORY;
2103                         goto cleanup;
2104                 }
2105 
2106                 if (soft_keystore_crypt(enc_key, iv, B_FALSE, buf, nread,
2107                     decrypted_buf, &out_len) != CKR_OK) {
2108                         freezero(buf, nread);
2109                         freezero(decrypted_buf, out_len);
2110                         rv = CKR_FUNCTION_FAILED;
2111                         goto cleanup;
2112                 }
2113 
2114                 obj->size = out_len - MAXPATHLEN;
2115 
2116                 /*
2117                  * decrypted buf here actually contains full path name of
2118                  * object plus the actual data.  so, need to skip the
2119                  * full pathname.
2120                  * See prepare_data_for_encrypt() function in the file
2121                  * to understand how and why the pathname is added.
2122                  */
2123                 obj->buf = malloc(sizeof (uchar_t) * (out_len - MAXPATHLEN));
2124                 if (obj->buf == NULL) {
2125                         freezero(buf, nread);
2126                         freezero(decrypted_buf, out_len);
2127                         rv = CKR_HOST_MEMORY;
2128                         goto cleanup;
2129                 }
2130                 (void) memcpy(obj->buf, decrypted_buf + MAXPATHLEN, obj->size);
2131                 freezero(buf, nread);
2132                 freezero(decrypted_buf, out_len);
2133                 *return_obj = obj;
2134         }
2135 
2136 cleanup:
2137 
2138         if (rv != CKR_OK) {
2139                 free(obj);
2140         }
2141 
2142         /* unlock the file after reading */
2143         if (!lock_held) {
2144                 (void) lock_file(fd, B_TRUE, B_FALSE);
2145         }
2146 
2147         (void) close(fd);
2148 
2149         return (rv);
2150 }
2151 
2152 
2153 /*
2154  *      FUNCTION: soft_keystore_put_new_obj
2155  *
2156  *      ARGUMENTS:
2157  *              buf: buffer containing un-encrypted data
2158  *                   to be stored in keystore.
2159  *              len: length of data
2160  *              public:  TRUE if it is a public object,
2161  *                       FALSE if it is private obj
2162  *              lock_held: TRUE if the lock is held by caller.
2163  *              keyhandle: pointer to object handle to
2164  *                         receive keyhandle for new object
2165  *
2166  *      RETURN VALUE:
2167  *              0: object successfully stored in file
2168  *              -1: some error occurred, object is not stored in file.
2169  *
2170  *      DESCRIPTION:
2171  *              This API is used to write a newly created token object
2172  *              to keystore.
2173  *
2174  *              This function does the following:
2175  *
2176  *              1) Creates a token object file based on "public" parameter.
2177  *              2) Generates a new IV and stores it in obj_meta_data_t if it is
2178  *                 private object.
2179  *              3) Set object version number to 1.
2180  *              4) If it is a private object, it will be encrypted before
2181  *                 being written to the newly created keystore token object
2182  *                 file.
2183  *              5) Calculates the obj_chksum in obj_meta_data_t.
2184  *              6) Calculates the pin_chksum in obj_meta_data_t.
2185  *              7) Increments the keystore version number.
2186  */
2187 int
2188 soft_keystore_put_new_obj(uchar_t *buf, size_t len, boolean_t public,
2189     boolean_t lock_held, ks_obj_handle_t *keyhandle)
2190 {
2191 
2192         int fd, tmp_ks_fd, obj_fd;
2193         unsigned int counter, version;
2194         uchar_t obj_hmac[OBJ_HMAC_SIZE];
2195         CK_BYTE iv[OBJ_IV_SIZE];
2196         char obj_name[MAXPATHLEN], tmp_ks_desc_name[MAXPATHLEN];
2197         char filebuf[BUFSIZ];
2198         char pub_obj_path[MAXPATHLEN], pri_obj_path[MAXPATHLEN],
2199             ks_desc_file[MAXPATHLEN];
2200         CK_ULONG hmac_size;
2201         ssize_t nread;
2202 
2203         if (keyhandle == NULL) {
2204                 return (-1);
2205         }
2206 
2207         /* if it is private object, make sure we have the key */
2208         if (!public) {
2209                 if ((enc_key == NULL) ||
2210                     (enc_key->magic_marker != SOFTTOKEN_OBJECT_MAGIC)) {
2211                         return (-1);
2212                 }
2213         }
2214 
2215         /* open keystore, and set write lock */
2216         if ((fd = open_and_lock_keystore_desc(O_RDWR, B_FALSE,
2217             lock_held)) < 0) {
2218                 return (-1);
2219         }
2220 
2221         (void) get_desc_file_path(ks_desc_file);
2222         (void) get_tmp_desc_file_path(tmp_ks_desc_name);
2223 
2224         /*
2225          * create a tempoary file for the keystore description
2226          * file for updating version and counter information
2227          */
2228         tmp_ks_fd = open_nointr(tmp_ks_desc_name,
2229             O_RDWR|O_CREAT|O_EXCL|O_NONBLOCK, S_IRUSR|S_IWUSR);
2230         if (tmp_ks_fd < 0) {
2231                 (void) close(fd);
2232                 return (-1);
2233         }
2234 
2235         /* read and write pkcs11 version */
2236         if (readn_nointr(fd, filebuf, KS_PKCS11_VER_SIZE)
2237             != KS_PKCS11_VER_SIZE) {
2238                 goto cleanup;
2239         }
2240 
2241         if (writen_nointr(tmp_ks_fd, filebuf, KS_PKCS11_VER_SIZE)
2242             != KS_PKCS11_VER_SIZE) {
2243                 goto cleanup;
2244         }
2245 
2246         /* get version number, and write updated number to temp file */
2247         if (readn_nointr(fd, &version, KS_VER_SIZE) != KS_VER_SIZE) {
2248                 goto cleanup;
2249         }
2250 
2251         version = SWAP32(version);
2252         version++;
2253         version = SWAP32(version);
2254 
2255         if (writen_nointr(tmp_ks_fd, (void *)&version,
2256             KS_VER_SIZE) != KS_VER_SIZE) {
2257                 goto cleanup;
2258         }
2259 
2260         /* get object count value */
2261         if (readn_nointr(fd, &counter, KS_COUNTER_SIZE) != KS_COUNTER_SIZE) {
2262                 goto cleanup;
2263         }
2264         counter = SWAP32(counter);
2265 
2266         bzero(obj_name, sizeof (obj_name));
2267         if (public) {
2268                 (void) snprintf(obj_name, MAXPATHLEN,  "%s/%s%d",
2269                     get_pub_obj_path(pub_obj_path), OBJ_PREFIX, counter);
2270         } else {
2271                 (void) snprintf(obj_name, MAXPATHLEN,  "%s/%s%d",
2272                     get_pri_obj_path(pri_obj_path), OBJ_PREFIX, counter);
2273         }
2274 
2275         /* create object file */
2276         obj_fd = open_nointr(obj_name,
2277             O_WRONLY|O_CREAT|O_EXCL|O_NONBLOCK, S_IRUSR|S_IWUSR);
2278         if (obj_fd < 0) {
2279                 /* can't create object file */
2280                 goto cleanup;
2281         }
2282 
2283         /* lock object file for writing */
2284         if (lock_file(obj_fd, B_FALSE, B_TRUE) != 0) {
2285                 (void) close(obj_fd);
2286                 goto cleanup2;
2287         }
2288 
2289         /* write object meta data */
2290         version = SWAP32(1);
2291         if (writen_nointr(obj_fd, (void *)&version, sizeof (version))
2292             != sizeof (version)) {
2293                 goto cleanup2;
2294         }
2295 
2296         if (public) {
2297                 bzero(iv, sizeof (iv));
2298         } else {
2299                 /* generate an IV */
2300                 if (soft_gen_iv(iv) != CKR_OK) {
2301                         goto cleanup2;
2302                 }
2303 
2304         }
2305 
2306         if (writen_nointr(obj_fd, (void *)iv, sizeof (iv)) != sizeof (iv)) {
2307                 goto cleanup2;
2308         }
2309 
2310         if (public) {
2311 
2312                 bzero(obj_hmac, sizeof (obj_hmac));
2313                 if (writen_nointr(obj_fd, (void *)obj_hmac,
2314                     sizeof (obj_hmac)) != sizeof (obj_hmac)) {
2315                         goto cleanup2;
2316                 }
2317 
2318                 if (writen_nointr(obj_fd, (char *)buf, len) != len) {
2319                         goto cleanup2;
2320                 }
2321 
2322         } else {
2323 
2324                 uchar_t *encrypted_buf, *prepared_buf;
2325                 CK_ULONG out_len = 0, prepared_len;
2326 
2327                 if (prepare_data_for_encrypt(obj_name, buf, len,
2328                     &prepared_buf, &prepared_len) != 0) {
2329                         goto cleanup2;
2330                 }
2331 
2332                 if (soft_keystore_crypt(enc_key, iv,
2333                     B_TRUE, prepared_buf, prepared_len,
2334                     NULL, &out_len) != CKR_OK) {
2335                         freezero(prepared_buf, prepared_len);
2336                         goto cleanup2;
2337                 }
2338 
2339                 encrypted_buf = malloc(out_len * sizeof (char));
2340                 if (encrypted_buf == NULL) {
2341                         freezero(prepared_buf, prepared_len);
2342                         goto cleanup2;
2343                 }
2344 
2345                 if (soft_keystore_crypt(enc_key, iv,
2346                     B_TRUE, prepared_buf, prepared_len,
2347                     encrypted_buf, &out_len) != CKR_OK) {
2348                         freezero(encrypted_buf, out_len);
2349                         freezero(prepared_buf, prepared_len);
2350                         goto cleanup2;
2351                 }
2352                 freezero(prepared_buf, prepared_len);
2353 
2354                 /* calculate HMAC of encrypted object */
2355                 hmac_size = OBJ_HMAC_SIZE;
2356                 if (soft_keystore_hmac(hmac_key, B_TRUE, encrypted_buf,
2357                     out_len, obj_hmac, &hmac_size) != CKR_OK) {
2358                         freezero(encrypted_buf, out_len);
2359                         goto cleanup2;
2360                 }
2361 
2362                 if (hmac_size != OBJ_HMAC_SIZE) {
2363                         freezero(encrypted_buf, out_len);
2364                         goto cleanup2;
2365                 }
2366 
2367                 /* write hmac */
2368                 if (writen_nointr(obj_fd, (void *)obj_hmac,
2369                     sizeof (obj_hmac)) != sizeof (obj_hmac)) {
2370                         freezero(encrypted_buf, out_len);
2371                         goto cleanup2;
2372                 }
2373 
2374                 /* write encrypted object */
2375                 if (writen_nointr(obj_fd, (void *)encrypted_buf, out_len)
2376                     != out_len) {
2377                         freezero(encrypted_buf, out_len);
2378                         goto cleanup2;
2379                 }
2380 
2381                 freezero(encrypted_buf, out_len);
2382         }
2383 
2384 
2385         (void) close(obj_fd);
2386         (void) snprintf((char *)keyhandle->name, sizeof (keyhandle->name),
2387             "obj%d", counter);
2388         keyhandle->public = public;
2389 
2390         /*
2391          * store new counter to temp keystore description file.
2392          */
2393         counter++;
2394         counter = SWAP32(counter);
2395         if (writen_nointr(tmp_ks_fd, (void *)&counter,
2396             sizeof (counter)) != sizeof (counter)) {
2397                 goto cleanup2;
2398         }
2399 
2400         /* read rest of keystore description file and store into temp file */
2401         nread = readn_nointr(fd, filebuf, sizeof (filebuf));
2402         while (nread > 0) {
2403                 if (writen_nointr(tmp_ks_fd, filebuf, nread) != nread) {
2404                         goto cleanup2;
2405                 }
2406                 nread = readn_nointr(fd, filebuf, sizeof (filebuf));
2407         }
2408 
2409         (void) close(tmp_ks_fd);
2410         (void) rename(tmp_ks_desc_name, ks_desc_file);
2411 
2412         if (!lock_held) {
2413                 /* release lock on description file */
2414                 if (lock_file(fd, B_FALSE, B_FALSE) != 0) {
2415                         (void) close(fd);
2416                         return (-1);
2417                 }
2418         }
2419         (void) close(fd);
2420         explicit_bzero(obj_hmac, sizeof (obj_hmac));
2421         explicit_bzero(iv, sizeof (iv));
2422         return (0);
2423 
2424 cleanup2:
2425 
2426         /* remove object file.  No need to remove lock first */
2427         (void) unlink(obj_name);
2428 
2429 cleanup:
2430 
2431         (void) close(tmp_ks_fd);
2432         (void) remove(tmp_ks_desc_name);
2433         if (!lock_held) {
2434                 /* release lock on description file */
2435                 (void) lock_file(fd, B_FALSE, B_FALSE);
2436         }
2437 
2438         (void) close(fd);
2439         explicit_bzero(obj_hmac, sizeof (obj_hmac));
2440         explicit_bzero(iv, sizeof (iv));
2441         return (-1);
2442 }
2443 
2444 /*
2445  *      FUNCTION: soft_keystore_modify_obj
2446  *
2447  *      ARGUMENTS:
2448  *              ks_handle: handle of the key store object to be modified
2449  *              buf: buffer containing un-encrypted data
2450  *                   to be modified in keystore.
2451  *              len: length of data
2452  *              lock_held: TRUE if the lock is held by caller.
2453  *
2454  *      RETURN VALUE:
2455  *              -1: if any error occurred.
2456  *              Otherwise, 0 is returned.
2457  *
2458  *      DESCRIPTION:
2459  *
2460  *              This API is used to write a modified token object back
2461  *              to keystore.   This function will do the following:
2462  *
2463  *              1) If it is a private object, it will be encrypted before
2464  *                 being written to the corresponding keystore token
2465  *                 object file.
2466  *              2) Record incremented object version number.
2467  *              3) Record incremented keystore version number.
2468  */
2469 int
2470 soft_keystore_modify_obj(ks_obj_handle_t *ks_handle, uchar_t *buf,
2471     size_t len, boolean_t lock_held)
2472 {
2473         int fd, ks_fd, tmp_fd, version;
2474         char orig_name[MAXPATHLEN], tmp_name[MAXPATHLEN],
2475             tmp_ks_name[MAXPATHLEN];
2476         uchar_t iv[OBJ_IV_SIZE], obj_hmac[OBJ_HMAC_SIZE];
2477         char pub_obj_path[MAXPATHLEN], pri_obj_path[MAXPATHLEN],
2478             ks_desc_file[MAXPATHLEN];
2479         CK_ULONG hmac_size;
2480 
2481         /* if it is private object, make sure we have the key */
2482         if (!(ks_handle->public)) {
2483                 if ((enc_key == NULL) ||
2484                     (enc_key->magic_marker != SOFTTOKEN_OBJECT_MAGIC)) {
2485                         return (-1);
2486                 }
2487         }
2488 
2489         /* open and lock keystore description file */
2490         if ((ks_fd = open_and_lock_keystore_desc(O_RDWR, B_FALSE,
2491             B_FALSE)) < 0) {
2492                 return (-1);
2493         }
2494 
2495         (void) get_desc_file_path(ks_desc_file);
2496 
2497         /* update the version of for keystore file in tempoary file */
2498         (void) get_tmp_desc_file_path(tmp_ks_name);
2499         if (create_updated_keystore_version(ks_fd, tmp_ks_name) != 0) {
2500                 /* unlock keystore description file */
2501                 (void) lock_file(ks_fd, B_FALSE, B_FALSE);
2502                 (void) close(ks_fd);
2503                 return (-1);
2504         }
2505 
2506         /* open object file */
2507         if ((fd = open_and_lock_object_file(ks_handle, O_RDWR,
2508             lock_held)) < 0) {
2509                 goto cleanup;
2510         }
2511 
2512         /*
2513          * make the change in a temporary file.  Create the temp
2514          * file in the same directory as the token object.  That
2515          * way, the "rename" later will be an atomic operation
2516          */
2517         if (ks_handle->public) {
2518                 (void) snprintf(orig_name, MAXPATHLEN, "%s/%s",
2519                     get_pub_obj_path(pub_obj_path), ks_handle->name);
2520                 (void) snprintf(tmp_name, MAXPATHLEN, "%s/%s%s",
2521                     pub_obj_path, TMP_OBJ_PREFIX,
2522                     (ks_handle->name) + OBJ_PREFIX_LEN);
2523         } else {
2524                 (void) snprintf(orig_name, MAXPATHLEN, "%s/%s",
2525                     get_pri_obj_path(pri_obj_path), ks_handle->name);
2526                 (void) snprintf(tmp_name, MAXPATHLEN, "%s/%s%s",
2527                     pri_obj_path, TMP_OBJ_PREFIX,
2528                     (ks_handle->name) + OBJ_PREFIX_LEN);
2529         }
2530 
2531         tmp_fd = open_nointr(tmp_name,
2532             O_WRONLY|O_CREAT|O_EXCL|O_NONBLOCK, S_IRUSR|S_IWUSR);
2533         if (tmp_fd < 0) {
2534                 /* can't create tmp object file */
2535                 goto cleanup1;
2536         }
2537 
2538         /* read version, increment, and write to tmp file */
2539         if (readn_nointr(fd, (char *)&version, OBJ_VER_SIZE) != OBJ_VER_SIZE) {
2540                 goto cleanup2;
2541         }
2542 
2543         version = SWAP32(version);
2544         version++;
2545         version = SWAP32(version);
2546 
2547         if (writen_nointr(tmp_fd, (char *)&version, OBJ_VER_SIZE)
2548             != OBJ_VER_SIZE) {
2549                 goto cleanup2;
2550         }
2551 
2552         /* generate a new IV for the object, old one can be ignored */
2553         if (soft_gen_iv(iv) != CKR_OK) {
2554                 goto cleanup2;
2555         }
2556 
2557         if (writen_nointr(tmp_fd, (char *)iv, OBJ_IV_SIZE) != OBJ_IV_SIZE) {
2558                 goto cleanup2;
2559         }
2560 
2561         if (ks_handle->public) {
2562 
2563                 /* hmac is always NULL for public objects */
2564                 bzero(obj_hmac, sizeof (obj_hmac));
2565                 if (writen_nointr(tmp_fd, (char *)obj_hmac, OBJ_HMAC_SIZE)
2566                     != OBJ_HMAC_SIZE) {
2567                         goto cleanup2;
2568                 }
2569 
2570                 /* write updated object */
2571                 if (writen_nointr(tmp_fd, (char *)buf, len) != len) {
2572                         goto cleanup2;
2573                 }
2574 
2575         } else {
2576 
2577                 uchar_t *encrypted_buf, *prepared_buf;
2578                 CK_ULONG out_len = 0, prepared_len;
2579 
2580                 if (prepare_data_for_encrypt(orig_name, buf, len,
2581                     &prepared_buf, &prepared_len) != 0) {
2582                         goto cleanup2;
2583                 }
2584 
2585                 /* encrypt the data */
2586                 if (soft_keystore_crypt(enc_key, iv, B_TRUE, prepared_buf,
2587                     prepared_len, NULL, &out_len) != CKR_OK) {
2588                         free(prepared_buf);
2589                         goto cleanup2;
2590                 }
2591 
2592                 encrypted_buf = malloc(out_len * sizeof (char));
2593                 if (encrypted_buf == NULL) {
2594                         freezero(prepared_buf, prepared_len);
2595                         goto cleanup2;
2596                 }
2597 
2598                 if (soft_keystore_crypt(enc_key, iv, B_TRUE, prepared_buf,
2599                     prepared_len, encrypted_buf, &out_len) != CKR_OK) {
2600                         freezero(prepared_buf, prepared_len);
2601                         freezero(encrypted_buf, out_len);
2602                         goto cleanup2;
2603                 }
2604 
2605                 freezero(prepared_buf, prepared_len);
2606 
2607                 /* calculate hmac on encrypted buf */
2608                 hmac_size = OBJ_HMAC_SIZE;
2609                 if (soft_keystore_hmac(hmac_key, B_TRUE, encrypted_buf,
2610                     out_len, obj_hmac, &hmac_size) != CKR_OK) {
2611                         freezero(encrypted_buf, out_len);
2612                         goto cleanup2;
2613                 }
2614 
2615                 if (hmac_size != OBJ_HMAC_SIZE) {
2616                         freezero(encrypted_buf, out_len);
2617                         goto cleanup2;
2618                 }
2619 
2620                 if (writen_nointr(tmp_fd, (char *)obj_hmac, OBJ_HMAC_SIZE)
2621                     != OBJ_HMAC_SIZE) {
2622                         freezero(encrypted_buf, out_len);
2623                         goto cleanup2;
2624                 }
2625 
2626                 if (writen_nointr(tmp_fd, (void *)encrypted_buf, out_len)
2627                     != out_len) {
2628                         freezero(encrypted_buf, out_len);
2629                         goto cleanup2;
2630                 }
2631                 freezero(encrypted_buf, out_len);
2632         }
2633         (void) close(tmp_fd);
2634 
2635         /* rename updated temporary object file */
2636         if (rename(tmp_name, orig_name) != 0) {
2637                 (void) unlink(tmp_name);
2638                 return (-1);
2639         }
2640 
2641         /* rename updated keystore description file */
2642         if (rename(tmp_ks_name, ks_desc_file) != 0) {
2643                 (void) unlink(tmp_name);
2644                 (void) unlink(tmp_ks_name);
2645                 return (-1);
2646         }
2647 
2648         /* determine need to unlock file or not */
2649         if (!lock_held) {
2650                 if (lock_file(fd, B_FALSE, B_FALSE) < 0) {
2651                         (void) close(fd);
2652                         (void) unlink(tmp_name);
2653                         return (-1);
2654                 }
2655         }
2656 
2657         /* unlock keystore description file */
2658         if (lock_file(ks_fd, B_FALSE, B_FALSE) != 0) {
2659                 (void) close(ks_fd);
2660                 (void) close(fd);
2661                 return (-1);
2662         }
2663 
2664         (void) close(ks_fd);
2665 
2666         (void) close(fd);
2667 
2668         explicit_bzero(iv, sizeof (iv));
2669         explicit_bzero(obj_hmac, sizeof (obj_hmac));
2670         return (0); /* All operations completed successfully */
2671 
2672 cleanup2:
2673         (void) close(tmp_fd);
2674         (void) remove(tmp_name);
2675 
2676 cleanup1:
2677         (void) close(fd);
2678 
2679 cleanup:
2680         /* unlock keystore description file */
2681         (void) lock_file(ks_fd, B_FALSE, B_FALSE);
2682         (void) close(ks_fd);
2683         (void) remove(tmp_ks_name);
2684         explicit_bzero(iv, sizeof (iv));
2685         explicit_bzero(obj_hmac, sizeof (obj_hmac));
2686         return (-1);
2687 }
2688 
2689 /*
2690  *      FUNCTION: soft_keystore_del_obj
2691  *
2692  *      ARGUMENTS:
2693  *              ks_handle: handle of the key store object to be deleted
2694  *              lock_held: TRUE if the lock is held by caller.
2695  *
2696  *      RETURN VALUE:
2697  *              -1: if any error occurred.
2698  *              0: object successfully deleted from keystore.
2699  *
2700  *      DESCRIPTION:
2701  *              This API is used to delete a particular token object from
2702  *              the keystore.  The corresponding token object file will be
2703  *              removed from the file system.
2704  *              Any future reference to the deleted file will
2705  *              return an CKR_OBJECT_HANDLE_INVALID error.
2706  */
2707 int
2708 soft_keystore_del_obj(ks_obj_handle_t *ks_handle, boolean_t lock_held)
2709 {
2710         char objname[MAXPATHLEN], tmp_ks_name[MAXPATHLEN];
2711         int fd;
2712         char pub_obj_path[MAXPATHLEN], pri_obj_path[MAXPATHLEN],
2713             ks_desc_file[MAXPATHLEN];
2714         int ret_val = -1;
2715         int obj_fd;
2716 
2717         if ((fd = open_and_lock_keystore_desc(O_RDWR, B_FALSE,
2718             lock_held)) < 0) {
2719                 return (-1);
2720         }
2721 
2722         (void) get_desc_file_path(ks_desc_file);
2723         (void) get_tmp_desc_file_path(tmp_ks_name);
2724         if (create_updated_keystore_version(fd, tmp_ks_name) != 0) {
2725                 goto cleanup;
2726         }
2727 
2728         if (ks_handle->public) {
2729                 (void) snprintf(objname, MAXPATHLEN, "%s/%s",
2730                     get_pub_obj_path(pub_obj_path), ks_handle->name);
2731         } else {
2732                 (void) snprintf(objname, MAXPATHLEN, "%s/%s",
2733                     get_pri_obj_path(pri_obj_path), ks_handle->name);
2734         }
2735 
2736         /*
2737          * make sure no other process is reading/writing the file
2738          * by acquiring the lock on the file
2739          */
2740         if ((obj_fd = open_and_lock_object_file(ks_handle, O_WRONLY,
2741             B_FALSE)) < 0) {
2742                 return (-1);
2743         }
2744 
2745         if (unlink(objname) != 0) {
2746                 (void) lock_file(obj_fd, B_FALSE, B_FALSE);
2747                 (void) close(obj_fd);
2748                 goto cleanup;
2749         }
2750 
2751         (void) lock_file(obj_fd, B_FALSE, B_FALSE);
2752         (void) close(obj_fd);
2753 
2754         if (rename(tmp_ks_name, ks_desc_file) != 0) {
2755                 goto cleanup;
2756         }
2757         ret_val = 0;
2758 
2759 cleanup:
2760         /* unlock keystore description file */
2761         if (!lock_held) {
2762                 if (lock_file(fd, B_FALSE, B_FALSE) != 0) {
2763                         (void) close(fd);
2764                         return (-1);
2765                 }
2766         }
2767 
2768         (void) close(fd);
2769         return (ret_val);
2770 }
2771 
2772 /*
2773  * Get the salt used for generating hashed pin from the
2774  * keystore description file.
2775  *
2776  * The result will be stored in the provided buffer "salt" passed
2777  * in as an argument.
2778  *
2779  * Return 0 if no error, return -1 if there's any error.
2780  */
2781 int
2782 soft_keystore_get_pin_salt(char **salt)
2783 {
2784         int fd, ret_val = -1;
2785         uint64_t hashed_pin_salt_size;
2786 
2787         if ((fd = open_and_lock_keystore_desc(O_RDONLY, B_FALSE,
2788             B_FALSE)) < 0) {
2789                 return (-1);
2790         }
2791 
2792         if (lseek(fd, KS_HASHED_PIN_SALT_LEN_OFFSET, SEEK_SET)
2793             != KS_HASHED_PIN_SALT_LEN_OFFSET) {
2794                 goto cleanup;
2795         }
2796 
2797         if (readn_nointr(fd, (char *)&hashed_pin_salt_size,
2798             KS_HASHED_PIN_SALT_LEN_SIZE) != KS_HASHED_PIN_SALT_LEN_SIZE) {
2799                 goto cleanup;
2800         }
2801         hashed_pin_salt_size = SWAP64(hashed_pin_salt_size);
2802 
2803         *salt = malloc(hashed_pin_salt_size + 1);
2804         if (*salt == NULL) {
2805                 goto cleanup;
2806         }
2807 
2808         if ((readn_nointr(fd, *salt, hashed_pin_salt_size))
2809             != (ssize_t)hashed_pin_salt_size) {
2810                 freezero(*salt, hashed_pin_salt_size + 1);
2811                 goto cleanup;
2812         }
2813         (*salt)[hashed_pin_salt_size] = '\0';
2814 
2815         ret_val = 0;
2816 
2817 cleanup:
2818         if (lock_file(fd, B_TRUE, B_FALSE) < 0) {
2819                 ret_val = -1;
2820         }
2821 
2822         (void) close(fd);
2823         return (ret_val);
2824 }
2825 
2826 /*
2827  *      FUNCTION: soft_keystore_pin_initialized
2828  *
2829  *      ARGUMENTS:
2830  *              initialized: This value will be set to true if keystore is
2831  *                           initialized, and false otherwise.
2832  *              hashed_pin: If the keystore is initialized, this will contain
2833  *                          the hashed pin.  It will be NULL if the keystore
2834  *                          pin is not initialized.  Memory allocated
2835  *                          for the hashed pin needs to be freed by
2836  *                          the caller.
2837  *              lock_held: TRUE if the lock is held by caller.
2838  *
2839  *      RETURN VALUE:
2840  *              CKR_OK: No error
2841  *              any other appropriate CKR_value
2842  *
2843  *      DESCRIPTION:
2844  *              This API is used to determine if the PIN in the keystore
2845  *              has been initialized or not.
2846  *              It makes the determination using the salt for generating the
2847  *              encryption key.  The salt is stored in the keystore
2848  *              descryption file.  The salt should be all zero if
2849  *              the keystore pin has not been initialized.
2850  *              If the pin has been initialized, it is returned in the
2851  *              hashed_pin argument.
2852  */
2853 CK_RV
2854 soft_keystore_pin_initialized(boolean_t *initialized, char **hashed_pin,
2855     boolean_t lock_held)
2856 {
2857         int fd;
2858         CK_BYTE crypt_salt[KS_KEY_SALT_SIZE], tmp_buf[KS_KEY_SALT_SIZE];
2859         CK_RV ret_val = CKR_OK;
2860 
2861         if ((fd = open_and_lock_keystore_desc(O_RDONLY, B_FALSE,
2862             lock_held)) < 0) {
2863                 return (CKR_FUNCTION_FAILED);
2864         }
2865 
2866         if (lseek(fd, KS_KEY_SALT_OFFSET, SEEK_SET) != KS_KEY_SALT_OFFSET) {
2867                 ret_val = CKR_FUNCTION_FAILED;
2868                 goto cleanup;
2869         }
2870 
2871         if (readn_nointr(fd, (char *)crypt_salt, KS_KEY_SALT_SIZE)
2872             != KS_KEY_SALT_SIZE) {
2873                 ret_val = CKR_FUNCTION_FAILED;
2874                 goto cleanup;
2875         }
2876 
2877         (void) bzero(tmp_buf, KS_KEY_SALT_SIZE);
2878 
2879         if (memcmp(crypt_salt, tmp_buf, KS_KEY_SALT_SIZE) == 0) {
2880                 *initialized = B_FALSE;
2881                 hashed_pin = NULL;
2882         } else {
2883                 *initialized = B_TRUE;
2884                 ret_val = get_hashed_pin(fd, hashed_pin);
2885         }
2886 
2887 cleanup:
2888 
2889         if (!lock_held) {
2890                 if (lock_file(fd, B_TRUE, B_FALSE) < 0) {
2891                         ret_val = CKR_FUNCTION_FAILED;
2892                 }
2893         }
2894 
2895         (void) close(fd);
2896         return (ret_val);
2897 }
2898 
2899 /*
2900  * This checks if the keystore file exists
2901  */
2902 
2903 static int
2904 soft_keystore_exists()
2905 {
2906         int ret;
2907         struct stat fn_stat;
2908         char *fname, ks_desc_file[MAXPATHLEN];
2909 
2910         fname = get_desc_file_path(ks_desc_file);
2911         ret = stat(fname, &fn_stat);
2912         if (ret == 0)
2913                 return (0);
2914         return (errno);
2915 }
2916 
2917 /*
2918  *      FUNCTION: soft_keystore_init
2919  *
2920  *      ARGUMENTS:
2921  *              desired_state:  The keystore state the caller would like
2922  *                              it to be.
2923  *
2924  *      RETURN VALUE:
2925  *              Returns the state the function is in.  If it succeeded, it
2926  *              will be the same as the desired, if not it will be
2927  *              KEYSTORE_UNAVAILABLE.
2928  *
2929  *      DESCRIPTION:
2930  *              This function will only load as much keystore data as is
2931  *              requested at that time. This is for performace by delaying the
2932  *              reading of token objects until they are needed or never at
2933  *              all if they are not used.
2934  *
2935  *              Primary use is from C_InitToken().
2936  *              It is also called by soft_keystore_status() when the
2937  *              "desired_state" is not the the current load state of keystore.
2938  *
2939  */
2940 int
2941 soft_keystore_init(int desired_state)
2942 {
2943         int ret;
2944 
2945         (void) pthread_mutex_lock(&soft_slot.keystore_mutex);
2946 
2947         /*
2948          * If more than one session tries to initialize the keystore, the
2949          * second and other following sessions that were waiting for the lock
2950          * will quickly exit if their requirements are satisfied.
2951          */
2952         if (desired_state <= soft_slot.keystore_load_status) {
2953                 (void) pthread_mutex_unlock(&soft_slot.keystore_mutex);
2954                 return (soft_slot.keystore_load_status);
2955         }
2956 
2957         /*
2958          * With 'keystore_load_status' giving the current state of the
2959          * process, this switch will bring it up to the desired state if
2960          * possible.
2961          */
2962 
2963         switch (soft_slot.keystore_load_status) {
2964         case KEYSTORE_UNINITIALIZED:
2965                 ret = soft_keystore_exists();
2966                 if (ret == 0)
2967                         soft_slot.keystore_load_status = KEYSTORE_PRESENT;
2968                 else if (ret == ENOENT)
2969                         if (create_keystore() == 0)
2970                                 soft_slot.keystore_load_status =
2971                                     KEYSTORE_PRESENT;
2972                         else {
2973                                 soft_slot.keystore_load_status =
2974                                     KEYSTORE_UNAVAILABLE;
2975                                 cryptoerror(LOG_DEBUG,
2976                                     "pkcs11_softtoken: "
2977                                     "Cannot create keystore.");
2978                                 break;
2979                         }
2980 
2981                 if (desired_state <= KEYSTORE_PRESENT)
2982                         break;
2983 
2984         /* FALLTHRU */
2985         case KEYSTORE_PRESENT:
2986                 if (soft_keystore_get_version(&soft_slot.ks_version, B_FALSE)
2987                     != 0) {
2988                         soft_slot.keystore_load_status = KEYSTORE_UNAVAILABLE;
2989                         cryptoerror(LOG_DEBUG,
2990                             "pkcs11_softtoken: Keystore access failed.");
2991                         break;
2992                 }
2993 
2994                 soft_slot.keystore_load_status = KEYSTORE_LOAD;
2995                 if (desired_state <= KEYSTORE_LOAD)
2996                         break;
2997 
2998         /* FALLTHRU */
2999         case KEYSTORE_LOAD:
3000                 /* Load all the public token objects from keystore */
3001                 if (soft_get_token_objects_from_keystore(PUB_TOKENOBJS)
3002                     != CKR_OK) {
3003                         (void) soft_destroy_token_session();
3004                         soft_slot.keystore_load_status = KEYSTORE_UNAVAILABLE;
3005                         cryptoerror(LOG_DEBUG,
3006                             "pkcs11_softtoken: Cannot initialize keystore.");
3007                         break;
3008                 }
3009 
3010                 soft_slot.keystore_load_status = KEYSTORE_INITIALIZED;
3011         };
3012 
3013         (void) pthread_mutex_unlock(&soft_slot.keystore_mutex);
3014         return (soft_slot.keystore_load_status);
3015 }
3016 
3017 /*
3018  *      FUNCTION: soft_keystore_status
3019  *
3020  *      ARGUMENTS:
3021  *              desired_state:  The keystore state the caller would like
3022  *                              it to be.
3023  *
3024  *      RETURN VALUE:
3025  *              B_TRUE if keystore is ready and at the desired state.
3026  *              B_FALSE if keystore had an error and is not available.
3027  *
3028  *      DESCRIPTION:
3029  *              The calling function wants to make sure the keystore load
3030  *              status to in a state it requires.  If it is not at that
3031  *              state it will call the load function.
3032  *              If keystore is at the desired state or has just been
3033  *              loaded to that state, it will return TRUE.  If there has been
3034  *              load failure, it will return FALSE.
3035  *
3036  */
3037 boolean_t
3038 soft_keystore_status(int desired_state)
3039 {
3040 
3041         if (soft_slot.keystore_load_status == KEYSTORE_UNAVAILABLE)
3042                 return (B_FALSE);
3043 
3044         return ((desired_state <= soft_slot.keystore_load_status) ||
3045             (soft_keystore_init(desired_state) == desired_state));
3046 }