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  */
  24 
  25 /*
  26  * Functions used for manipulating the keystore
  27  */
  28 
  29 #include <stdio.h>
  30 #include <stdlib.h>
  31 #include <errno.h>
  32 #include <sys/stat.h>
  33 #include <fcntl.h>
  34 #include <time.h>
  35 #include <unistd.h>
  36 #include <pwd.h>
  37 #include <sys/types.h>
  38 #include <dirent.h>
  39 #include <limits.h>
  40 #include <libgen.h>
  41 #include <strings.h>
  42 #include <security/cryptoki.h>
  43 #include <cryptoutil.h>
  44 #include "softGlobal.h"
  45 #include "softObject.h"
  46 #include "softSession.h"
  47 #include "softKeystore.h"
  48 #include "softKeystoreUtil.h"
  49 
  50 #define MAXPATHLEN      1024
  51 #define SUNW_PATH       ".sunw"         /* top level Sun directory */
  52 #define KEYSTORE_PATH   "pkcs11_softtoken"      /* keystore directory */
  53 #define PUB_OBJ_DIR     "public"        /* directory for public objects */
  54 #define PRI_OBJ_DIR     "private"       /* directory for private objects */
  55 #define DS_FILE         "objstore_info" /* keystore description file */
  56 #define TMP_DS_FILE     "t_info"        /* temp name for keystore desc. file */
  57 #define OBJ_PREFIX      "obj"   /* prefix of the keystore object file names */
  58 #define OBJ_PREFIX_LEN  sizeof (OBJ_PREFIX) - 1 /* length of prefix */
  59 #define TMP_OBJ_PREFIX  "t_o"   /* prefix of the temp object file names */
  60 
  61 /*
  62  * KEYSTORE DESCRIPTION FILE:
  63  *
  64  * The following describes the content of the keystore description file
  65  *
  66  * The order AND data type of the fields are very important.
  67  * All the code in this file assume that they are in the order specified
  68  * below.  If either order of the fields or their data type changed,
  69  * you must make sure the ALL the pre-define values are still valid
  70  *
  71  * 1) PKCS#11 release number.  It's 2.20 in this release (uchar_t[32])
  72  * 2) keystore version number: used for synchronizing when different
  73  *    processes access the keystore at the same time.  It is incremented
  74  *    when there is a change to the keystore. (uint_32)
  75  * 3) monotonic-counter: last counter value for name of token object file.
  76  *    used for assigning unique name to each token (uint_32)
  77  * 4) salt used for generating encryption key (uint_16)
  78  * 5) salt used for generating key used for doing HMAC (uint_16)
  79  * 6) Length of salt used for generating hashed pin (length of salt
  80  *    is variable)
  81  * 7) Salt used for generating hashed pin.
  82  * 8) Hashed pin len (length of hashed pin could be variable, the offset of
  83  *    where this value lives in the file is calculated at run time)
  84  * 9) Hashed pin
  85  *
  86  */
  87 
  88 /* Keystore description file pre-defined values */
  89 #define KS_PKCS11_VER           "2.20"
  90 #define KS_PKCS11_OFFSET        0
  91 #define KS_PKCS11_VER_SIZE      32
  92 
  93 #define KS_VER_OFFSET           (KS_PKCS11_OFFSET + KS_PKCS11_VER_SIZE)
  94 #define KS_VER_SIZE     4       /* size in bytes of keystore version value */
  95 
  96 #define KS_COUNTER_OFFSET       (KS_VER_OFFSET + KS_VER_SIZE)
  97 #define KS_COUNTER_SIZE 4       /* size in bytes of the monotonic counter */
  98 
  99 #define KS_KEY_SALT_OFFSET      (KS_COUNTER_OFFSET + KS_COUNTER_SIZE)
 100 #define KS_KEY_SALT_SIZE        PBKD2_SALT_SIZE
 101 
 102 #define KS_HMAC_SALT_OFFSET     (KS_KEY_SALT_OFFSET + KS_KEY_SALT_SIZE)
 103 #define KS_HMAC_SALT_SIZE       PBKD2_SALT_SIZE
 104 
 105 /* Salt for hashed pin */
 106 #define KS_HASHED_PIN_SALT_LEN_OFFSET (KS_HMAC_SALT_OFFSET + KS_HMAC_SALT_SIZE)
 107 #define KS_HASHED_PIN_SALT_LEN_SIZE 8 /* stores length of hashed pin salt */
 108 
 109 #define KS_HASHED_PIN_SALT_OFFSET \
 110                 (KS_HASHED_PIN_SALT_LEN_OFFSET + KS_HASHED_PIN_SALT_LEN_SIZE)
 111 
 112 /*
 113  * hashed pin
 114  *
 115  * hashed_pin length offset will be calculated at run time since
 116  * there's the hashed pin salt size is variable.
 117  *
 118  * The offset will be calculated at run time by calling the
 119  * function calculate_hashed_pin_offset()
 120  */
 121 static off_t    ks_hashed_pinlen_offset = -1;
 122 #define KS_HASHED_PINLEN_SIZE   8
 123 
 124 /* End of Keystore description file pre-defined values */
 125 
 126 /*
 127  * Metadata for each object
 128  *
 129  * The order AND data type of all the fields is very important.
 130  * All the code in this file assume that they are in the order specified
 131  * below.  If either order of the fields or their data type is changed,
 132  * you must make sure the following pre-define value is still valid
 133  * Each object will have the meta data at the beginning of the object file.
 134  *
 135  * 1) object_version: used by softtoken to see if the object
 136  *    has been modified since it last reads it. (uint_32)
 137  * 2) iv: initialization vector for encrypted data in the object.  This
 138  *    value will be 0 for public objects.  (uchar_t[16])
 139  * 3) obj_hmac: keyed hash as verifier to detect private object
 140  *    being tampered this value will be 0 for public objects (uchar_t[16])
 141  */
 142 
 143 /* Object metadata pre-defined values */
 144 #define OBJ_VER_OFFSET  0
 145 #define OBJ_VER_SIZE    4       /* size of object version in bytes */
 146 #define OBJ_IV_OFFSET   (OBJ_VER_OFFSET + OBJ_VER_SIZE)
 147 #define OBJ_IV_SIZE     16
 148 #define OBJ_HMAC_OFFSET (OBJ_IV_OFFSET + OBJ_IV_SIZE)
 149 #define OBJ_HMAC_SIZE   16      /* MD5 HMAC keyed hash */
 150 #define OBJ_DATA_OFFSET (OBJ_HMAC_OFFSET + OBJ_HMAC_SIZE)
 151 /* End of object metadata pre-defined values */
 152 
 153 #define ALTERNATE_KEYSTORE_PATH "SOFTTOKEN_DIR"
 154 
 155 static soft_object_t    *enc_key = NULL;
 156 static soft_object_t    *hmac_key = NULL;
 157 static char             keystore_path[MAXPATHLEN];
 158 static boolean_t        keystore_path_initialized = B_FALSE;
 159 static int              desc_fd = 0;
 160 
 161 static char *
 162 get_keystore_path()
 163 {
 164         char *home = getenv("HOME");
 165         char *alt = getenv(ALTERNATE_KEYSTORE_PATH);
 166 
 167         if (keystore_path_initialized) {
 168                 return (keystore_path);
 169         }
 170 
 171         bzero(keystore_path, sizeof (keystore_path));
 172         /*
 173          * If it isn't set or is set to the empty string use the
 174          * default location.  We need to check for the empty string
 175          * because some users "unset" environment variables by giving
 176          * them no value, this isn't the same thing as removing it
 177          * from the environment.
 178          *
 179          * We don't want that to attempt to open /.sunw/pkcs11_sofftoken
 180          */
 181         if ((alt != NULL) && (strcmp(alt, "") != 0)) {
 182                 (void) snprintf(keystore_path, MAXPATHLEN, "%s/%s",
 183                     alt, KEYSTORE_PATH);
 184                 keystore_path_initialized = B_TRUE;
 185         } else if ((home != NULL) && (strcmp(home, "") != 0)) {
 186                 /* alternate path not specified, try user's home dir */
 187                 (void) snprintf(keystore_path, MAXPATHLEN, "%s/%s/%s",
 188                     home, SUNW_PATH, KEYSTORE_PATH);
 189                 keystore_path_initialized = B_TRUE;
 190         }
 191         return (keystore_path);
 192 }
 193 
 194 static char *
 195 get_pub_obj_path(char *name)
 196 {
 197         bzero(name, sizeof (name));
 198         (void) snprintf(name, MAXPATHLEN, "%s/%s",
 199             get_keystore_path(), PUB_OBJ_DIR);
 200         return (name);
 201 }
 202 
 203 static char *
 204 get_pri_obj_path(char *name)
 205 {
 206         bzero(name, sizeof (name));
 207         (void) snprintf(name, MAXPATHLEN, "%s/%s",
 208             get_keystore_path(), PRI_OBJ_DIR);
 209         return (name);
 210 }
 211 
 212 static char *
 213 get_desc_file_path(char *name)
 214 {
 215         bzero(name, sizeof (name));
 216         (void) snprintf(name, MAXPATHLEN, "%s/%s",
 217             get_keystore_path(), DS_FILE);
 218         return (name);
 219 }
 220 
 221 static char *
 222 get_tmp_desc_file_path(char *name)
 223 {
 224         bzero(name, sizeof (name));
 225         (void) snprintf(name, MAXPATHLEN, "%s/%s",
 226             get_keystore_path(), TMP_DS_FILE);
 227         return (name);
 228 }
 229 
 230 /*
 231  * Calculates the offset for hashed_pin length and hashed pin
 232  *
 233  * Returns 0 if successful, -1 if there's any error.
 234  *
 235  * If successful, global variables "ks_hashed_pinlen_offset" will be set.
 236  *
 237  */
 238 static int
 239 calculate_hashed_pin_offset(int fd)
 240 {
 241         uint64_t salt_length;
 242 
 243         if (lseek(fd, KS_HASHED_PIN_SALT_LEN_OFFSET, SEEK_SET)
 244             != KS_HASHED_PIN_SALT_LEN_OFFSET) {
 245                 return (-1);
 246         }
 247 
 248         if (readn_nointr(fd, (char *)&salt_length,
 249             KS_HASHED_PIN_SALT_LEN_SIZE) != KS_HASHED_PIN_SALT_LEN_SIZE) {
 250                 return (-1);
 251         }
 252         salt_length = SWAP64(salt_length);
 253 
 254         ks_hashed_pinlen_offset = KS_HASHED_PIN_SALT_LEN_OFFSET
 255             + KS_HASHED_PIN_SALT_LEN_SIZE + salt_length;
 256 
 257         return (0);
 258 
 259 }
 260 
 261 /*
 262  * acquire or release read/write lock on a specific file
 263  *
 264  * read_lock: true for read lock; false for write lock
 265  * set_lock:  true to set a lock; false to release a lock
 266  */
 267 static int
 268 lock_file(int fd, boolean_t read_lock, boolean_t set_lock)
 269 {
 270 
 271         flock_t lock_info;
 272         int r;
 273 
 274         lock_info.l_whence = SEEK_SET;
 275         lock_info.l_start = 0;
 276         lock_info.l_len = 0; /* l_len == 0 means until end of  file */
 277 
 278         if (read_lock) {
 279                 lock_info.l_type = F_RDLCK;
 280         } else {
 281                 lock_info.l_type = F_WRLCK;
 282         }
 283 
 284         if (set_lock) {
 285                 while ((r = fcntl(fd, F_SETLKW, &lock_info)) == -1) {
 286                         if (errno != EINTR)
 287                                 break;
 288                 }
 289                 if (r == -1) {
 290                         return (-1);
 291                 }
 292         } else {
 293                 lock_info.l_type = F_UNLCK;
 294                 while ((r = fcntl(fd, F_SETLKW, &lock_info)) == -1) {
 295                         if (errno != EINTR)
 296                                 break;
 297                 }
 298                 if (r == -1) {
 299                         return (-1);
 300                 }
 301         }
 302 
 303         return (0);
 304 }
 305 
 306 int
 307 create_keystore()
 308 {
 309         int fd, buf;
 310         uint64_t hashed_pin_len, hashed_pin_salt_len, ulong_buf;
 311         uchar_t ver_buf[KS_PKCS11_VER_SIZE];
 312         char pub_obj_path[MAXPATHLEN], pri_obj_path[MAXPATHLEN],
 313             ks_desc_file[MAXPATHLEN];
 314         CK_BYTE salt[KS_KEY_SALT_SIZE];
 315         char *hashed_pin = NULL, *hashed_pin_salt = NULL;
 316         char *alt;
 317 
 318         /* keystore doesn't exist, create keystore directory */
 319         if (mkdir(get_keystore_path(), S_IRUSR|S_IWUSR|S_IXUSR) < 0) {
 320                 if (errno == EEXIST) {
 321                         return (0);
 322                 }
 323 
 324                 if (errno == EACCES) {
 325                         return (-1);
 326                 }
 327 
 328                 /* can't create keystore directory */
 329                 if (errno == ENOENT) { /* part of the path doesn't exist */
 330                         char keystore[MAXPATHLEN];
 331                         /*
 332                          * try to create $HOME/.sunw/pkcs11_softtoken if it
 333                          * doesn't exist.  If it is a alternate path provided
 334                          * by the user, it should have existed.  Will not
 335                          * create for them.
 336                          */
 337                         alt = getenv(ALTERNATE_KEYSTORE_PATH);
 338                         if ((alt == NULL) || (strcmp(alt, "") == 0)) {
 339                                 char *home = getenv("HOME");
 340 
 341                                 if (home == NULL || strcmp(home, "") == 0) {
 342                                         return (-1);
 343                                 }
 344                                 /* create $HOME/.sunw/pkcs11_softtoken */
 345                                 (void) snprintf(keystore, sizeof (keystore),
 346                                     "%s/%s/%s", home, SUNW_PATH, KEYSTORE_PATH);
 347                                 if (mkdirp(keystore,
 348                                     S_IRUSR|S_IWUSR|S_IXUSR) < 0) {
 349                                         return (-1);
 350                                 }
 351                         } else {
 352                                 return (-1);
 353                         }
 354                 }
 355         }
 356 
 357         /* create keystore description file */
 358         fd = open_nointr(get_desc_file_path(ks_desc_file),
 359             O_RDWR|O_CREAT|O_EXCL|O_NONBLOCK, S_IRUSR|S_IWUSR);
 360         if (fd < 0) {
 361                 if (errno == EEXIST) {
 362                         return (0);
 363                 } else {
 364                         /* can't create keystore description file */
 365                         (void) rmdir(get_keystore_path());
 366                         return (-1);
 367                 }
 368         }
 369 
 370         if (lock_file(fd, B_FALSE, B_TRUE) != 0) {
 371                 (void) unlink(ks_desc_file);
 372                 (void) close(fd);
 373                 (void) rmdir(get_keystore_path());
 374                 return (-1);
 375         }
 376 
 377         if (mkdir(get_pub_obj_path(pub_obj_path),
 378             S_IRUSR|S_IWUSR|S_IXUSR) < 0) {
 379                 /* can't create directory for public objects */
 380                 (void) lock_file(fd, B_FALSE, B_FALSE);
 381                 (void) unlink(ks_desc_file);
 382                 (void) close(fd);
 383                 (void) rmdir(get_keystore_path());
 384                 return (-1);
 385         }
 386 
 387         if (mkdir(get_pri_obj_path(pri_obj_path),
 388             S_IRUSR|S_IWUSR|S_IXUSR) < 0) {
 389                 /* can't create directory for private objects */
 390                 (void) lock_file(fd, B_FALSE, B_FALSE);
 391                 (void) unlink(ks_desc_file);
 392                 (void) close(fd);
 393                 (void) rmdir(get_keystore_path());
 394                 (void) rmdir(pub_obj_path);
 395                 return (-1);
 396         }
 397 
 398 
 399         /* write file format release number */
 400         bzero(ver_buf, sizeof (ver_buf));
 401         (void) strcpy((char *)ver_buf, KS_PKCS11_VER);
 402         if ((writen_nointr(fd, (char *)ver_buf, sizeof (ver_buf)))
 403             != sizeof (ver_buf)) {
 404                 goto cleanup;
 405         }
 406 
 407         /* write version number, version = 0 since keystore just created */
 408         buf = SWAP32(0);
 409         if (writen_nointr(fd, (void *)&buf, KS_VER_SIZE) != KS_VER_SIZE) {
 410                 goto cleanup;
 411         }
 412 
 413         /* write monotonic-counter.  Counter for keystore objects start at 1 */
 414         buf = SWAP32(1);
 415         if (writen_nointr(fd, (void *)&buf, KS_COUNTER_SIZE)
 416             != KS_COUNTER_SIZE) {
 417                 goto cleanup;
 418         }
 419 
 420         /* initial encryption key salt should be all NULL */
 421         bzero(salt, sizeof (salt));
 422         if (writen_nointr(fd, (void *)salt, KS_KEY_SALT_SIZE)
 423             != KS_KEY_SALT_SIZE) {
 424                 goto cleanup;
 425         }
 426 
 427         /* initial HMAC key salt should also be all NULL */
 428         if (writen_nointr(fd, (void *)salt, KS_HMAC_SALT_SIZE)
 429             != KS_HMAC_SALT_SIZE) {
 430                 goto cleanup;
 431         }
 432 
 433         /* generate the hashed pin salt, and MD5 hashed pin of default pin */
 434         if (soft_gen_hashed_pin((CK_CHAR_PTR)SOFT_DEFAULT_PIN, &hashed_pin,
 435             &hashed_pin_salt) < 0) {
 436                 goto cleanup;
 437         }
 438 
 439         if ((hashed_pin_salt == NULL) || (hashed_pin == NULL)) {
 440                 goto cleanup;
 441         }
 442 
 443         hashed_pin_salt_len = (uint64_t)strlen(hashed_pin_salt);
 444         hashed_pin_len = (uint64_t)strlen(hashed_pin);
 445 
 446         /* write hashed pin salt length */
 447         ulong_buf = SWAP64(hashed_pin_salt_len);
 448         if (writen_nointr(fd, (void *)&ulong_buf, KS_HASHED_PIN_SALT_LEN_SIZE)
 449             != KS_HASHED_PIN_SALT_LEN_SIZE) {
 450                 goto cleanup;
 451         }
 452 
 453         if (writen_nointr(fd, (void *)hashed_pin_salt,
 454             hashed_pin_salt_len) != hashed_pin_salt_len) {
 455                 goto cleanup;
 456         }
 457 
 458         /* write MD5 hashed pin of the default pin */
 459         ulong_buf = SWAP64(hashed_pin_len);
 460         if (writen_nointr(fd, (void *)&ulong_buf, KS_HASHED_PINLEN_SIZE)
 461             != KS_HASHED_PINLEN_SIZE) {
 462                 goto cleanup;
 463         }
 464 
 465         if (writen_nointr(fd, (void *)hashed_pin, hashed_pin_len)
 466             != hashed_pin_len) {
 467                 goto cleanup;
 468         }
 469 
 470         (void) lock_file(fd, B_FALSE, B_FALSE);
 471 
 472         (void) close(fd);
 473         if (hashed_pin_salt)
 474                 free(hashed_pin_salt);
 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                 free(*hashed_pin);
 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                 free(buf);
1324                 goto cleanup;
1325         }
1326 
1327         decrypted_buf = malloc(decrypted_len);
1328         if (decrypted_buf == NULL) {
1329                 free(buf);
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                 free(buf);
1336                 free(decrypted_buf);
1337                 goto cleanup;
1338         }
1339 
1340         free(buf);
1341 
1342         /* re-encrypt with new key */
1343         encrypted_len = 0;
1344         if (soft_keystore_crypt(new_enc_key, iv, B_TRUE, decrypted_buf,
1345             decrypted_len, NULL, &encrypted_len) != CKR_OK) {
1346                 free(decrypted_buf);
1347                 goto cleanup;
1348         }
1349 
1350         buf = malloc(encrypted_len);
1351         if (buf == NULL) {
1352                 free(decrypted_buf);
1353                 goto cleanup;
1354         }
1355 
1356         if (soft_keystore_crypt(new_enc_key, iv, B_TRUE, decrypted_buf,
1357             decrypted_len, buf, &encrypted_len) != CKR_OK) {
1358                 free(buf);
1359                 free(decrypted_buf);
1360                 goto cleanup;
1361         }
1362 
1363         free(decrypted_buf);
1364 
1365         /* calculate hmac on re-encrypted data using new hmac key */
1366         hmac_len = OBJ_HMAC_SIZE;
1367         if (soft_keystore_hmac(new_hmac_key, B_TRUE, buf,
1368             encrypted_len, hmac, &hmac_len) != CKR_OK) {
1369                 free(buf);
1370                 goto cleanup;
1371         }
1372 
1373         /* just for sanity check */
1374         if (hmac_len != OBJ_HMAC_SIZE) {
1375                 free(buf);
1376                 goto cleanup;
1377         }
1378 
1379         /* write new hmac */
1380         if (writen_nointr(new_fd, (char *)hmac, OBJ_HMAC_SIZE)
1381             != OBJ_HMAC_SIZE) {
1382                 free(buf);
1383                 goto cleanup;
1384         }
1385 
1386         /* write re-encrypted buffer to temp file */
1387         if (writen_nointr(new_fd, (void *)buf, encrypted_len)
1388             != encrypted_len) {
1389                 free(buf);
1390                 goto cleanup;
1391         }
1392         free(buf);
1393         ret_val = 0;
1394 
1395 cleanup:
1396         /* unlock the files */
1397         (void) lock_file(old_fd, B_TRUE, B_FALSE);
1398         (void) lock_file(new_fd, B_FALSE, B_FALSE);
1399 
1400         (void) close(old_fd);
1401         (void) close(new_fd);
1402         if (ret_val != 0) {
1403                 (void) remove(new_obj_name);
1404         }
1405         return (ret_val);
1406 }
1407 
1408 /*
1409  *      FUNCTION: soft_keystore_setpin
1410  *
1411  *      ARGUMENTS:
1412  *              newpin: new pin entered by the user.
1413  *              lock_held: TRUE if the lock is held by caller.
1414  *
1415  *      RETURN VALUE:
1416  *              0: no error
1417  *              -1: failure
1418  *
1419  *      DESCRIPTION:
1420  *
1421  *              This function does the following:
1422  *
1423  *              1) Generates crypted value of newpin and store it
1424  *                 in keystore description file.
1425  *              2) Dervies the new encryption key from the newpin.  This key
1426  *                 will be used to re-encrypt the private token objects.
1427  *              3) Re-encrypt all of this user's existing private token
1428  *                 objects (if any).
1429  *              4) Increments the keystore version number.
1430  */
1431 int
1432 soft_keystore_setpin(uchar_t *oldpin, uchar_t *newpin, boolean_t lock_held)
1433 {
1434         int fd, tmp_ks_fd, version, ret_val = -1;
1435         soft_object_t *new_crypt_key = NULL, *new_hmac_key = NULL;
1436         char filebuf[BUFSIZ];
1437         DIR     *pri_dirp;
1438         struct dirent *pri_ent;
1439         char pri_obj_path[MAXPATHLEN], ks_desc_file[MAXPATHLEN],
1440             tmp_ks_desc_name[MAXPATHLEN];
1441         typedef struct priobjs {
1442                 char orig_name[MAXPATHLEN];
1443                 char tmp_name[MAXPATHLEN];
1444                 struct priobjs *next;
1445         } priobjs_t;
1446         priobjs_t *pri_objs = NULL, *tmp;
1447         CK_BYTE *crypt_salt = NULL, *hmac_salt = NULL;
1448         boolean_t pin_never_set = B_FALSE, user_logged_in;
1449         char *new_hashed_pin = NULL;
1450         uint64_t hashed_pin_salt_length, new_hashed_pin_len, swaped_val;
1451         char *hashed_pin_salt = NULL;
1452         priobjs_t *obj;
1453 
1454         if ((enc_key == NULL) ||
1455             (enc_key->magic_marker != SOFTTOKEN_OBJECT_MAGIC)) {
1456                 user_logged_in = B_FALSE;
1457         } else {
1458                 user_logged_in = B_TRUE;
1459         }
1460 
1461         if ((fd = open_and_lock_keystore_desc(O_RDWR, B_TRUE,
1462             lock_held)) < 0) {
1463                 return (-1);
1464         }
1465 
1466         (void) get_desc_file_path(ks_desc_file);
1467         (void) get_tmp_desc_file_path(tmp_ks_desc_name);
1468 
1469         /*
1470          * create a tempoary file for the keystore description
1471          * file for updating version and counter information
1472          */
1473         tmp_ks_fd = open_nointr(tmp_ks_desc_name,
1474             O_RDWR|O_CREAT|O_EXCL|O_NONBLOCK, S_IRUSR|S_IWUSR);
1475         if (tmp_ks_fd < 0) {
1476                 (void) close(fd);
1477                 return (-1);
1478         }
1479 
1480         /* read and write PKCS version to temp file */
1481         if (readn_nointr(fd, filebuf, KS_PKCS11_VER_SIZE)
1482             != KS_PKCS11_VER_SIZE) {
1483                 goto cleanup;
1484         }
1485 
1486         if (writen_nointr(tmp_ks_fd, filebuf, KS_PKCS11_VER_SIZE)
1487             != KS_PKCS11_VER_SIZE) {
1488                 goto cleanup;
1489         }
1490 
1491         /* get version number, and write updated number to temp file */
1492         if (readn_nointr(fd, &version, KS_VER_SIZE) != KS_VER_SIZE) {
1493                 goto cleanup;
1494         }
1495 
1496         version = SWAP32(version);
1497         version++;
1498         version = SWAP32(version);
1499 
1500         if (writen_nointr(tmp_ks_fd, (void *)&version, KS_VER_SIZE)
1501             != KS_VER_SIZE) {
1502                 goto cleanup;
1503         }
1504 
1505 
1506         /* read and write counter, no modification necessary */
1507         if (readn_nointr(fd, filebuf, KS_COUNTER_SIZE) != KS_COUNTER_SIZE) {
1508                 goto cleanup;
1509         }
1510 
1511         if (writen_nointr(tmp_ks_fd, filebuf, KS_COUNTER_SIZE)
1512             != KS_COUNTER_SIZE) {
1513                 goto cleanup;
1514         }
1515 
1516         /* read old encryption salt */
1517         crypt_salt = malloc(KS_KEY_SALT_SIZE);
1518         if (crypt_salt == NULL) {
1519                 goto cleanup;
1520         }
1521         if (readn_nointr(fd, (char *)crypt_salt, KS_KEY_SALT_SIZE)
1522             != KS_KEY_SALT_SIZE) {
1523                 goto cleanup;
1524         }
1525 
1526         /* read old hmac salt */
1527         hmac_salt = malloc(KS_HMAC_SALT_SIZE);
1528         if (hmac_salt == NULL) {
1529                 goto cleanup;
1530         }
1531         if (readn_nointr(fd, (char *)hmac_salt, KS_HMAC_SALT_SIZE)
1532             != KS_HMAC_SALT_SIZE) {
1533                 goto cleanup;
1534         }
1535 
1536         /* just create some empty bytes */
1537         bzero(filebuf, sizeof (filebuf));
1538 
1539         if (memcmp(crypt_salt, filebuf, KS_KEY_SALT_SIZE) == 0) {
1540                 /* PIN as never been set */
1541                 CK_BYTE *new_crypt_salt = NULL, *new_hmac_salt = NULL;
1542 
1543                 pin_never_set = B_TRUE;
1544                 if (soft_gen_crypt_key(newpin, &new_crypt_key, &new_crypt_salt)
1545                     != CKR_OK) {
1546                         goto cleanup;
1547                 }
1548                 if (writen_nointr(tmp_ks_fd, (void *)new_crypt_salt,
1549                     KS_KEY_SALT_SIZE) != KS_KEY_SALT_SIZE) {
1550                         free(new_crypt_salt);
1551                         (void) soft_cleanup_object(new_crypt_key);
1552                         goto cleanup;
1553                 }
1554                 free(new_crypt_salt);
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                         free(new_hmac_salt);
1564                         goto cleanup3;
1565                 }
1566                 free(new_hmac_salt);
1567         } else {
1568                 if (soft_gen_crypt_key(newpin, &new_crypt_key,
1569                     (CK_BYTE **)&crypt_salt) != CKR_OK) {
1570                         goto cleanup;
1571                 }
1572                 /* no change to the encryption salt */
1573                 if (writen_nointr(tmp_ks_fd, (void *)crypt_salt,
1574                     KS_KEY_SALT_SIZE) != KS_KEY_SALT_SIZE) {
1575                         (void) soft_cleanup_object(new_crypt_key);
1576                         goto cleanup;
1577                 }
1578 
1579                 if (soft_gen_hmac_key(newpin, &new_hmac_key,
1580                     (CK_BYTE **)&hmac_salt) != CKR_OK) {
1581                         (void) soft_cleanup_object(new_crypt_key);
1582                         goto cleanup;
1583                 }
1584 
1585                 /* no change to the hmac salt */
1586                 if (writen_nointr(tmp_ks_fd, (void *)hmac_salt,
1587                     KS_HMAC_SALT_SIZE) != KS_HMAC_SALT_SIZE) {
1588                         goto cleanup3;
1589                 }
1590         }
1591 
1592         /*
1593          * read hashed pin salt, and write to updated keystore description
1594          * file unmodified.
1595          */
1596         if (readn_nointr(fd, (char *)&hashed_pin_salt_length,
1597             KS_HASHED_PIN_SALT_LEN_SIZE) != KS_HASHED_PIN_SALT_LEN_SIZE) {
1598                 goto cleanup3;
1599         }
1600 
1601         if (writen_nointr(tmp_ks_fd, (void *)&hashed_pin_salt_length,
1602             KS_HASHED_PIN_SALT_LEN_SIZE) != KS_HASHED_PIN_SALT_LEN_SIZE) {
1603                 goto cleanup3;
1604         }
1605 
1606         hashed_pin_salt_length = SWAP64(hashed_pin_salt_length);
1607 
1608         hashed_pin_salt = malloc(hashed_pin_salt_length + 1);
1609         if (hashed_pin_salt == NULL) {
1610                 goto cleanup3;
1611         }
1612 
1613         if ((readn_nointr(fd, hashed_pin_salt, hashed_pin_salt_length)) !=
1614             (ssize_t)hashed_pin_salt_length) {
1615                 free(hashed_pin_salt);
1616                 goto cleanup3;
1617         }
1618 
1619         if ((writen_nointr(tmp_ks_fd, hashed_pin_salt, hashed_pin_salt_length))
1620             != (ssize_t)hashed_pin_salt_length) {
1621                 free(hashed_pin_salt);
1622                 goto cleanup3;
1623         }
1624 
1625         hashed_pin_salt[hashed_pin_salt_length] = '\0';
1626 
1627         /* old hashed pin length and value can be ignored, generate new one */
1628         if (soft_gen_hashed_pin(newpin, &new_hashed_pin,
1629             &hashed_pin_salt) < 0) {
1630                 free(hashed_pin_salt);
1631                 goto cleanup3;
1632         }
1633 
1634         free(hashed_pin_salt);
1635 
1636         if (new_hashed_pin == NULL) {
1637                 goto cleanup3;
1638         }
1639 
1640         new_hashed_pin_len = strlen(new_hashed_pin);
1641 
1642         /* write new hashed pin length to file */
1643         swaped_val = SWAP64(new_hashed_pin_len);
1644         if (writen_nointr(tmp_ks_fd, (void *)&swaped_val,
1645             KS_HASHED_PINLEN_SIZE) != KS_HASHED_PINLEN_SIZE) {
1646                 goto cleanup3;
1647         }
1648 
1649         if (writen_nointr(tmp_ks_fd, (void *)new_hashed_pin,
1650             new_hashed_pin_len) != (ssize_t)new_hashed_pin_len) {
1651                 goto cleanup3;
1652         }
1653 
1654         if (pin_never_set) {
1655                 /* there was no private object, no need to re-encrypt them */
1656                 goto rename_desc_file;
1657         }
1658 
1659         /* re-encrypt all the private objects */
1660         pri_dirp = opendir(get_pri_obj_path(pri_obj_path));
1661         if (pri_dirp == NULL) {
1662                 /*
1663                  * this directory should exist, even if it doesn't contain
1664                  * any objects.  Don't want to update the pin if the
1665                  * keystore is somehow messed up.
1666                  */
1667 
1668                 goto cleanup3;
1669         }
1670 
1671         /* if user did not login, need to set the old pin */
1672         if (!user_logged_in) {
1673                 if (soft_keystore_authpin(oldpin) != 0) {
1674                         goto cleanup3;
1675                 }
1676         }
1677 
1678         while ((pri_ent = readdir(pri_dirp)) != NULL) {
1679 
1680                 if ((strcmp(pri_ent->d_name, ".") == 0) ||
1681                     (strcmp(pri_ent->d_name, "..") == 0) ||
1682                     (strncmp(pri_ent->d_name, TMP_OBJ_PREFIX,
1683                     strlen(TMP_OBJ_PREFIX)) == 0)) {
1684                         continue;
1685                 }
1686 
1687                 obj = malloc(sizeof (priobjs_t));
1688                 if (obj == NULL) {
1689                         goto cleanup2;
1690                 }
1691                 (void) snprintf(obj->orig_name, MAXPATHLEN,
1692                     "%s/%s", pri_obj_path, pri_ent->d_name);
1693                 (void) snprintf(obj->tmp_name, MAXPATHLEN, "%s/%s%s",
1694                     pri_obj_path, TMP_OBJ_PREFIX,
1695                     (pri_ent->d_name) + OBJ_PREFIX_LEN);
1696                 if (reencrypt_obj(new_crypt_key, new_hmac_key,
1697                     obj->orig_name, obj->tmp_name) != 0) {
1698                         free(obj);
1699                         goto cleanup2;
1700                 }
1701 
1702                 /* insert into list of file to be renamed */
1703                 if (pri_objs == NULL) {
1704                         obj->next = NULL;
1705                         pri_objs = obj;
1706                 } else {
1707                         obj->next = pri_objs;
1708                         pri_objs = obj;
1709                 }
1710         }
1711 
1712         /* rename all the private objects */
1713         tmp = pri_objs;
1714         while (tmp) {
1715                 (void) rename(tmp->tmp_name, tmp->orig_name);
1716                 tmp = tmp->next;
1717         }
1718 
1719 rename_desc_file:
1720 
1721         /* destroy the old encryption key, and hmac key */
1722         if ((!pin_never_set) && (user_logged_in)) {
1723                 (void) soft_cleanup_object(enc_key);
1724                 (void) soft_cleanup_object(hmac_key);
1725         }
1726 
1727         if (user_logged_in) {
1728                 enc_key = new_crypt_key;
1729                 hmac_key = new_hmac_key;
1730         }
1731         (void) rename(tmp_ks_desc_name, ks_desc_file);
1732 
1733         ret_val = 0;
1734 
1735 cleanup2:
1736         if (pri_objs != NULL) {
1737                 priobjs_t *p = pri_objs;
1738                 while (p) {
1739                         tmp = p->next;
1740                         free(p);
1741                         p = tmp;
1742                 }
1743         }
1744         if (!pin_never_set) {
1745                 (void) closedir(pri_dirp);
1746         }
1747 
1748         if ((!user_logged_in) && (!pin_never_set)) {
1749                 (void) soft_cleanup_object(enc_key);
1750                 (void) soft_cleanup_object(hmac_key);
1751                 enc_key = NULL;
1752                 hmac_key = NULL;
1753         }
1754 cleanup3:
1755         if ((ret_val != 0) || (!user_logged_in)) {
1756                 (void) soft_cleanup_object(new_crypt_key);
1757                 (void) soft_cleanup_object(new_hmac_key);
1758         }
1759 
1760 cleanup:
1761         if (!lock_held) {
1762                 if (lock_file(fd, B_FALSE, B_FALSE) < 0) {
1763                         ret_val = 1;
1764                 }
1765         }
1766         if (crypt_salt != NULL) {
1767                 free(crypt_salt);
1768         }
1769         if (hmac_salt != NULL) {
1770                 free(hmac_salt);
1771         }
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         if (crypt_salt != NULL) {
1859                 free(crypt_salt);
1860         }
1861         if (hmac_salt != NULL) {
1862                 free(hmac_salt);
1863         }
1864         return (ret_val);
1865 }
1866 
1867 /*
1868  *      FUNCTION: soft_keystore_get_objs
1869  *
1870  *      ARGUMENTS:
1871  *
1872  *              search_type: Specify type of objects to return.
1873  *              lock_held: TRUE if the lock is held by caller.
1874  *
1875  *
1876  *      RETURN VALUE:
1877  *
1878  *              NULL: if there are no object in the database.
1879  *
1880  *              Otherwise, linked list of objects as requested
1881  *              in search type.
1882  *
1883  *              The linked list returned will need to be freed
1884  *              by the caller.
1885  *
1886  *      DESCRIPTION:
1887  *
1888  *              Returns objects as requested.
1889  *
1890  *              If private objects is requested, and the caller
1891  *              has not previously passed in the pin or if the pin
1892  *              passed in is wrong, private objects will not
1893  *              be returned.
1894  *
1895  *              The buffers returned for private objects are already
1896  *              decrypted.
1897  */
1898 CK_RV
1899 soft_keystore_get_objs(ks_search_type_t search_type,
1900     ks_obj_t **result_obj_list, boolean_t lock_held)
1901 {
1902         DIR *dirp;
1903         ks_obj_handle_t ks_handle;
1904         CK_RV rv;
1905         ks_obj_t *tmp;
1906         int ks_fd;
1907 
1908         *result_obj_list = NULL;
1909 
1910         /*
1911          * lock the keystore description file in "read" mode so that
1912          * objects won't get added/deleted/modified while we are
1913          * doing the search
1914          */
1915         if ((ks_fd = open_and_lock_keystore_desc(O_RDONLY, B_FALSE,
1916             B_FALSE)) < 0) {
1917                 return (CKR_FUNCTION_FAILED);
1918         }
1919 
1920         if ((search_type == ALL_TOKENOBJS) || (search_type == PUB_TOKENOBJS)) {
1921 
1922                 char pub_obj_path[MAXPATHLEN];
1923 
1924                 ks_handle.public = B_TRUE;
1925 
1926                 if ((dirp = opendir(get_pub_obj_path(pub_obj_path))) == NULL) {
1927                         (void) lock_file(ks_fd, B_TRUE, B_FALSE);
1928                         (void) close(ks_fd);
1929                         return (CKR_FUNCTION_FAILED);
1930                 }
1931                 rv = get_all_objs_in_dir(dirp, &ks_handle, result_obj_list,
1932                     lock_held);
1933                 if (rv != CKR_OK) {
1934                         (void) closedir(dirp);
1935                         goto cleanup;
1936                 }
1937 
1938                 (void) closedir(dirp);
1939         }
1940 
1941         if ((search_type == ALL_TOKENOBJS) || (search_type == PRI_TOKENOBJS)) {
1942 
1943                 char pri_obj_path[MAXPATHLEN];
1944 
1945                 if ((enc_key == NULL) ||
1946                     (enc_key->magic_marker != SOFTTOKEN_OBJECT_MAGIC)) {
1947                         /* has not login - no need to go any further */
1948                         (void) lock_file(ks_fd, B_TRUE, B_FALSE);
1949                         (void) close(ks_fd);
1950                         return (CKR_OK);
1951                 }
1952 
1953                 ks_handle.public = B_FALSE;
1954 
1955                 if ((dirp = opendir(get_pri_obj_path(pri_obj_path))) == NULL) {
1956                         (void) lock_file(ks_fd, B_TRUE, B_FALSE);
1957                         (void) close(ks_fd);
1958                         return (CKR_OK);
1959                 }
1960                 rv = get_all_objs_in_dir(dirp, &ks_handle, result_obj_list,
1961                     lock_held);
1962                 if (rv != CKR_OK) {
1963                         (void) closedir(dirp);
1964                         goto cleanup;
1965                 }
1966 
1967                 (void) closedir(dirp);
1968         }
1969         /* close the keystore description file */
1970         (void) lock_file(ks_fd, B_TRUE, B_FALSE);
1971         (void) close(ks_fd);
1972         return (CKR_OK);
1973 cleanup:
1974 
1975         /* close the keystore description file */
1976         (void) lock_file(ks_fd, B_TRUE, B_FALSE);
1977         (void) close(ks_fd);
1978 
1979         /* free all the objects found before hitting the error */
1980         tmp = *result_obj_list;
1981         while (tmp) {
1982                 *result_obj_list = tmp->next;
1983                 free(tmp->buf);
1984                 free(tmp);
1985                 tmp = *result_obj_list;
1986         }
1987         *result_obj_list = NULL;
1988         return (rv);
1989 }
1990 
1991 
1992 /*
1993  *      FUNCTION: soft_keystore_get_single_obj
1994  *
1995  *      ARGUMENTS:
1996  *              ks_handle: handle of the key store object to be accessed
1997  *              lock_held: TRUE if the lock is held by caller.
1998  *
1999  *      RETURN VALUE:
2000  *
2001  *              NULL: if handle doesn't match any object
2002  *
2003  *              Otherwise, the object is returned in
2004  *              the same structure used in soft_keystore_get_objs().
2005  *              The structure need to be freed by the caller.
2006  *
2007  *      DESCRIPTION:
2008  *
2009  *              Retrieves the object specified by the object
2010  *              handle to the caller.
2011  *
2012  *              If a private object is requested, and the caller
2013  *              has not previously passed in the pin or if the pin
2014  *              passed in is wrong, the requested private object will not
2015  *              be returned.
2016  *
2017  *              The buffer returned for the requested private object
2018  *              is already decrypted.
2019  */
2020 CK_RV
2021 soft_keystore_get_single_obj(ks_obj_handle_t *ks_handle,
2022     ks_obj_t **return_obj, boolean_t lock_held)
2023 {
2024 
2025         ks_obj_t *obj;
2026         uchar_t iv[OBJ_IV_SIZE], obj_hmac[OBJ_HMAC_SIZE];
2027         uchar_t *buf, *decrypted_buf;
2028         int fd;
2029         ssize_t nread;
2030         CK_RV rv = CKR_FUNCTION_FAILED;
2031 
2032         if (!(ks_handle->public)) {
2033                 if ((enc_key == NULL) ||
2034                     (enc_key->magic_marker != SOFTTOKEN_OBJECT_MAGIC)) {
2035                         return (CKR_FUNCTION_FAILED);
2036                 }
2037         }
2038 
2039         if ((fd = open_and_lock_object_file(ks_handle, O_RDONLY,
2040             lock_held)) < 0) {
2041                 return (CKR_FUNCTION_FAILED);
2042         }
2043 
2044         obj = malloc(sizeof (ks_obj_t));
2045         if (obj == NULL) {
2046                 return (CKR_HOST_MEMORY);
2047         }
2048 
2049         obj->next = NULL;
2050 
2051         (void) strcpy((char *)((obj->ks_handle).name),
2052             (char *)ks_handle->name);
2053         (obj->ks_handle).public = ks_handle->public;
2054 
2055         /* 1st get the version */
2056         if (readn_nointr(fd, &(obj->obj_version), OBJ_VER_SIZE)
2057             != OBJ_VER_SIZE) {
2058                 goto cleanup;
2059         }
2060         obj->obj_version = SWAP32(obj->obj_version);
2061 
2062         /* Then, read the IV */
2063         if (readn_nointr(fd, iv, OBJ_IV_SIZE) != OBJ_IV_SIZE) {
2064                 goto cleanup;
2065         }
2066 
2067         /* Then, read the HMAC */
2068         if (readn_nointr(fd, obj_hmac, OBJ_HMAC_SIZE) != OBJ_HMAC_SIZE) {
2069                 goto cleanup;
2070         }
2071 
2072         /* read the object */
2073         rv = read_obj_data(fd, (char **)&buf, &nread);
2074         if (rv != CKR_OK) {
2075                 goto cleanup;
2076         }
2077 
2078         if (ks_handle->public) {
2079                 obj->size = nread;
2080                 obj->buf = buf;
2081                 *return_obj = obj;
2082         } else {
2083 
2084                 CK_ULONG out_len = 0, hmac_size;
2085 
2086                 /* verify HMAC of the object, make sure it matches */
2087                 hmac_size = OBJ_HMAC_SIZE;
2088                 if (soft_keystore_hmac(hmac_key, B_FALSE, buf,
2089                     nread, obj_hmac, &hmac_size) != CKR_OK) {
2090                         free(buf);
2091                         rv = CKR_FUNCTION_FAILED;
2092                         goto cleanup;
2093                 }
2094 
2095                 /* decrypt object */
2096                 if (soft_keystore_crypt(enc_key, iv, B_FALSE, buf, nread,
2097                     NULL, &out_len) != CKR_OK) {
2098                         free(buf);
2099                         rv = CKR_FUNCTION_FAILED;
2100                         goto cleanup;
2101                 }
2102 
2103                 decrypted_buf = malloc(sizeof (uchar_t) * out_len);
2104                 if (decrypted_buf == NULL) {
2105                         free(buf);
2106                         rv = CKR_HOST_MEMORY;
2107                         goto cleanup;
2108                 }
2109 
2110                 if (soft_keystore_crypt(enc_key, iv, B_FALSE, buf, nread,
2111                     decrypted_buf, &out_len) != CKR_OK) {
2112                         free(decrypted_buf);
2113                         free(buf);
2114                         rv = CKR_FUNCTION_FAILED;
2115                         goto cleanup;
2116                 }
2117 
2118                 obj->size = out_len - MAXPATHLEN;
2119 
2120                 /*
2121                  * decrypted buf here actually contains full path name of
2122                  * object plus the actual data.  so, need to skip the
2123                  * full pathname.
2124                  * See prepare_data_for_encrypt() function in the file
2125                  * to understand how and why the pathname is added.
2126                  */
2127                 obj->buf = malloc(sizeof (uchar_t) * (out_len - MAXPATHLEN));
2128                 if (obj->buf == NULL) {
2129                         free(decrypted_buf);
2130                         free(buf);
2131                         rv = CKR_HOST_MEMORY;
2132                         goto cleanup;
2133                 }
2134                 (void) memcpy(obj->buf, decrypted_buf + MAXPATHLEN, obj->size);
2135                 free(decrypted_buf);
2136                 free(buf);
2137                 *return_obj = obj;
2138         }
2139 
2140 cleanup:
2141 
2142         if (rv != CKR_OK) {
2143                 free(obj);
2144         }
2145 
2146         /* unlock the file after reading */
2147         if (!lock_held) {
2148                 (void) lock_file(fd, B_TRUE, B_FALSE);
2149         }
2150 
2151         (void) close(fd);
2152 
2153         return (rv);
2154 }
2155 
2156 
2157 /*
2158  *      FUNCTION: soft_keystore_put_new_obj
2159  *
2160  *      ARGUMENTS:
2161  *              buf: buffer containing un-encrypted data
2162  *                   to be stored in keystore.
2163  *              len: length of data
2164  *              public:  TRUE if it is a public object,
2165  *                       FALSE if it is private obj
2166  *              lock_held: TRUE if the lock is held by caller.
2167  *              keyhandle: pointer to object handle to
2168  *                         receive keyhandle for new object
2169  *
2170  *      RETURN VALUE:
2171  *              0: object successfully stored in file
2172  *              -1: some error occurred, object is not stored in file.
2173  *
2174  *      DESCRIPTION:
2175  *              This API is used to write a newly created token object
2176  *              to keystore.
2177  *
2178  *              This function does the following:
2179  *
2180  *              1) Creates a token object file based on "public" parameter.
2181  *              2) Generates a new IV and stores it in obj_meta_data_t if it is
2182  *                 private object.
2183  *              3) Set object version number to 1.
2184  *              4) If it is a private object, it will be encrypted before
2185  *                 being written to the newly created keystore token object
2186  *                 file.
2187  *              5) Calculates the obj_chksum in obj_meta_data_t.
2188  *              6) Calculates the pin_chksum in obj_meta_data_t.
2189  *              7) Increments the keystore version number.
2190  */
2191 int
2192 soft_keystore_put_new_obj(uchar_t *buf, size_t len, boolean_t public,
2193     boolean_t lock_held, ks_obj_handle_t *keyhandle)
2194 {
2195 
2196         int fd, tmp_ks_fd, obj_fd;
2197         unsigned int counter, version;
2198         uchar_t obj_hmac[OBJ_HMAC_SIZE];
2199         CK_BYTE iv[OBJ_IV_SIZE];
2200         char obj_name[MAXPATHLEN], tmp_ks_desc_name[MAXPATHLEN];
2201         char filebuf[BUFSIZ];
2202         char pub_obj_path[MAXPATHLEN], pri_obj_path[MAXPATHLEN],
2203             ks_desc_file[MAXPATHLEN];
2204         CK_ULONG hmac_size;
2205         ssize_t nread;
2206 
2207         if (keyhandle == NULL) {
2208                 return (-1);
2209         }
2210 
2211         /* if it is private object, make sure we have the key */
2212         if (!public) {
2213                 if ((enc_key == NULL) ||
2214                     (enc_key->magic_marker != SOFTTOKEN_OBJECT_MAGIC)) {
2215                         return (-1);
2216                 }
2217         }
2218 
2219         /* open keystore, and set write lock */
2220         if ((fd = open_and_lock_keystore_desc(O_RDWR, B_FALSE,
2221             lock_held)) < 0) {
2222                 return (-1);
2223         }
2224 
2225         (void) get_desc_file_path(ks_desc_file);
2226         (void) get_tmp_desc_file_path(tmp_ks_desc_name);
2227 
2228         /*
2229          * create a tempoary file for the keystore description
2230          * file for updating version and counter information
2231          */
2232         tmp_ks_fd = open_nointr(tmp_ks_desc_name,
2233             O_RDWR|O_CREAT|O_EXCL|O_NONBLOCK, S_IRUSR|S_IWUSR);
2234         if (tmp_ks_fd < 0) {
2235                 (void) close(fd);
2236                 return (-1);
2237         }
2238 
2239         /* read and write pkcs11 version */
2240         if (readn_nointr(fd, filebuf, KS_PKCS11_VER_SIZE)
2241             != KS_PKCS11_VER_SIZE) {
2242                 goto cleanup;
2243         }
2244 
2245         if (writen_nointr(tmp_ks_fd, filebuf, KS_PKCS11_VER_SIZE)
2246             != KS_PKCS11_VER_SIZE) {
2247                 goto cleanup;
2248         }
2249 
2250         /* get version number, and write updated number to temp file */
2251         if (readn_nointr(fd, &version, KS_VER_SIZE) != KS_VER_SIZE) {
2252                 goto cleanup;
2253         }
2254 
2255         version = SWAP32(version);
2256         version++;
2257         version = SWAP32(version);
2258 
2259         if (writen_nointr(tmp_ks_fd, (void *)&version,
2260             KS_VER_SIZE) != KS_VER_SIZE) {
2261                 goto cleanup;
2262         }
2263 
2264         /* get object count value */
2265         if (readn_nointr(fd, &counter, KS_COUNTER_SIZE) != KS_COUNTER_SIZE) {
2266                 goto cleanup;
2267         }
2268         counter = SWAP32(counter);
2269 
2270         bzero(obj_name, sizeof (obj_name));
2271         if (public) {
2272                 (void) snprintf(obj_name, MAXPATHLEN,  "%s/%s%d",
2273                     get_pub_obj_path(pub_obj_path), OBJ_PREFIX, counter);
2274         } else {
2275                 (void) snprintf(obj_name, MAXPATHLEN,  "%s/%s%d",
2276                     get_pri_obj_path(pri_obj_path), OBJ_PREFIX, counter);
2277         }
2278 
2279         /* create object file */
2280         obj_fd = open_nointr(obj_name,
2281             O_WRONLY|O_CREAT|O_EXCL|O_NONBLOCK, S_IRUSR|S_IWUSR);
2282         if (obj_fd < 0) {
2283                 /* can't create object file */
2284                 goto cleanup;
2285         }
2286 
2287         /* lock object file for writing */
2288         if (lock_file(obj_fd, B_FALSE, B_TRUE) != 0) {
2289                 (void) close(obj_fd);
2290                 goto cleanup2;
2291         }
2292 
2293         /* write object meta data */
2294         version = SWAP32(1);
2295         if (writen_nointr(obj_fd, (void *)&version, sizeof (version))
2296             != sizeof (version)) {
2297                 goto cleanup2;
2298         }
2299 
2300         if (public) {
2301                 bzero(iv, sizeof (iv));
2302         } else {
2303                 /* generate an IV */
2304                 if (soft_gen_iv(iv) != CKR_OK) {
2305                         goto cleanup2;
2306                 }
2307 
2308         }
2309 
2310         if (writen_nointr(obj_fd, (void *)iv, sizeof (iv)) != sizeof (iv)) {
2311                 goto cleanup2;
2312         }
2313 
2314         if (public) {
2315 
2316                 bzero(obj_hmac, sizeof (obj_hmac));
2317                 if (writen_nointr(obj_fd, (void *)obj_hmac,
2318                     sizeof (obj_hmac)) != sizeof (obj_hmac)) {
2319                         goto cleanup2;
2320                 }
2321 
2322                 if (writen_nointr(obj_fd, (char *)buf, len) != len) {
2323                         goto cleanup2;
2324                 }
2325 
2326         } else {
2327 
2328                 uchar_t *encrypted_buf, *prepared_buf;
2329                 CK_ULONG out_len = 0, prepared_len;
2330 
2331                 if (prepare_data_for_encrypt(obj_name, buf, len,
2332                     &prepared_buf, &prepared_len) != 0) {
2333                         goto cleanup2;
2334                 }
2335 
2336                 if (soft_keystore_crypt(enc_key, iv,
2337                     B_TRUE, prepared_buf, prepared_len,
2338                     NULL, &out_len) != CKR_OK) {
2339                         free(prepared_buf);
2340                         goto cleanup2;
2341                 }
2342 
2343                 encrypted_buf = malloc(out_len * sizeof (char));
2344                 if (encrypted_buf == NULL) {
2345                         free(prepared_buf);
2346                         goto cleanup2;
2347                 }
2348 
2349                 if (soft_keystore_crypt(enc_key, iv,
2350                     B_TRUE, prepared_buf, prepared_len,
2351                     encrypted_buf, &out_len) != CKR_OK) {
2352                         free(encrypted_buf);
2353                         free(prepared_buf);
2354                         goto cleanup2;
2355                 }
2356                 free(prepared_buf);
2357 
2358                 /* calculate HMAC of encrypted object */
2359                 hmac_size = OBJ_HMAC_SIZE;
2360                 if (soft_keystore_hmac(hmac_key, B_TRUE, encrypted_buf,
2361                     out_len, obj_hmac, &hmac_size) != CKR_OK) {
2362                         free(encrypted_buf);
2363                         goto cleanup2;
2364                 }
2365 
2366                 if (hmac_size != OBJ_HMAC_SIZE) {
2367                         free(encrypted_buf);
2368                         goto cleanup2;
2369                 }
2370 
2371                 /* write hmac */
2372                 if (writen_nointr(obj_fd, (void *)obj_hmac,
2373                     sizeof (obj_hmac)) != sizeof (obj_hmac)) {
2374                         free(encrypted_buf);
2375                         goto cleanup2;
2376                 }
2377 
2378                 /* write encrypted object */
2379                 if (writen_nointr(obj_fd, (void *)encrypted_buf, out_len)
2380                     != out_len) {
2381                         free(encrypted_buf);
2382                         goto cleanup2;
2383                 }
2384 
2385                 free(encrypted_buf);
2386         }
2387 
2388 
2389         (void) close(obj_fd);
2390         (void) snprintf((char *)keyhandle->name, sizeof (keyhandle->name),
2391             "obj%d", counter);
2392         keyhandle->public = public;
2393 
2394         /*
2395          * store new counter to temp keystore description file.
2396          */
2397         counter++;
2398         counter = SWAP32(counter);
2399         if (writen_nointr(tmp_ks_fd, (void *)&counter,
2400             sizeof (counter)) != sizeof (counter)) {
2401                 goto cleanup2;
2402         }
2403 
2404         /* read rest of keystore description file and store into temp file */
2405         nread = readn_nointr(fd, filebuf, sizeof (filebuf));
2406         while (nread > 0) {
2407                 if (writen_nointr(tmp_ks_fd, filebuf, nread) != nread) {
2408                         goto cleanup2;
2409                 }
2410                 nread = readn_nointr(fd, filebuf, sizeof (filebuf));
2411         }
2412 
2413         (void) close(tmp_ks_fd);
2414         (void) rename(tmp_ks_desc_name, ks_desc_file);
2415 
2416         if (!lock_held) {
2417                 /* release lock on description file */
2418                 if (lock_file(fd, B_FALSE, B_FALSE) != 0) {
2419                         (void) close(fd);
2420                         return (-1);
2421                 }
2422         }
2423         (void) close(fd);
2424         return (0);
2425 
2426 cleanup2:
2427 
2428         /* remove object file.  No need to remove lock first */
2429         (void) unlink(obj_name);
2430 
2431 cleanup:
2432 
2433         (void) close(tmp_ks_fd);
2434         (void) remove(tmp_ks_desc_name);
2435         if (!lock_held) {
2436                 /* release lock on description file */
2437                 (void) lock_file(fd, B_FALSE, B_FALSE);
2438         }
2439 
2440         (void) close(fd);
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                         free(prepared_buf);
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                         free(encrypted_buf);
2601                         free(prepared_buf);
2602                         goto cleanup2;
2603                 }
2604 
2605                 free(prepared_buf);
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                         free(encrypted_buf);
2612                         goto cleanup2;
2613                 }
2614 
2615                 if (hmac_size != OBJ_HMAC_SIZE) {
2616                         free(encrypted_buf);
2617                         goto cleanup2;
2618                 }
2619 
2620                 if (writen_nointr(tmp_fd, (char *)obj_hmac, OBJ_HMAC_SIZE)
2621                     != OBJ_HMAC_SIZE) {
2622                         free(encrypted_buf);
2623                         goto cleanup2;
2624                 }
2625 
2626                 if (writen_nointr(tmp_fd, (void *)encrypted_buf, out_len)
2627                     != out_len) {
2628                         free(encrypted_buf);
2629                         goto cleanup2;
2630                 }
2631                 free(encrypted_buf);
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         return (0); /* All operations completed successfully */
2669 
2670 cleanup2:
2671         (void) close(tmp_fd);
2672         (void) remove(tmp_name);
2673 
2674 cleanup1:
2675         (void) close(fd);
2676 
2677 cleanup:
2678         /* unlock keystore description file */
2679         (void) lock_file(ks_fd, B_FALSE, B_FALSE);
2680         (void) close(ks_fd);
2681         (void) remove(tmp_ks_name);
2682         return (-1);
2683 }
2684 
2685 /*
2686  *      FUNCTION: soft_keystore_del_obj
2687  *
2688  *      ARGUMENTS:
2689  *              ks_handle: handle of the key store object to be deleted
2690  *              lock_held: TRUE if the lock is held by caller.
2691  *
2692  *      RETURN VALUE:
2693  *              -1: if any error occurred.
2694  *              0: object successfully deleted from keystore.
2695  *
2696  *      DESCRIPTION:
2697  *              This API is used to delete a particular token object from
2698  *              the keystore.  The corresponding token object file will be
2699  *              removed from the file system.
2700  *              Any future reference to the deleted file will
2701  *              return an CKR_OBJECT_HANDLE_INVALID error.
2702  */
2703 int
2704 soft_keystore_del_obj(ks_obj_handle_t *ks_handle, boolean_t lock_held)
2705 {
2706         char objname[MAXPATHLEN], tmp_ks_name[MAXPATHLEN];
2707         int fd;
2708         char pub_obj_path[MAXPATHLEN], pri_obj_path[MAXPATHLEN],
2709             ks_desc_file[MAXPATHLEN];
2710         int ret_val = -1;
2711         int obj_fd;
2712 
2713         if ((fd = open_and_lock_keystore_desc(O_RDWR, B_FALSE,
2714             lock_held)) < 0) {
2715                 return (-1);
2716         }
2717 
2718         (void) get_desc_file_path(ks_desc_file);
2719         (void) get_tmp_desc_file_path(tmp_ks_name);
2720         if (create_updated_keystore_version(fd, tmp_ks_name) != 0) {
2721                 goto cleanup;
2722         }
2723 
2724         if (ks_handle->public) {
2725                 (void) snprintf(objname, MAXPATHLEN, "%s/%s",
2726                     get_pub_obj_path(pub_obj_path), ks_handle->name);
2727         } else {
2728                 (void) snprintf(objname, MAXPATHLEN, "%s/%s",
2729                     get_pri_obj_path(pri_obj_path), ks_handle->name);
2730         }
2731 
2732         /*
2733          * make sure no other process is reading/writing the file
2734          * by acquiring the lock on the file
2735          */
2736         if ((obj_fd = open_and_lock_object_file(ks_handle, O_WRONLY,
2737             B_FALSE)) < 0) {
2738                 return (-1);
2739         }
2740 
2741         if (unlink(objname) != 0) {
2742                 (void) lock_file(obj_fd, B_FALSE, B_FALSE);
2743                 (void) close(obj_fd);
2744                 goto cleanup;
2745         }
2746 
2747         (void) lock_file(obj_fd, B_FALSE, B_FALSE);
2748         (void) close(obj_fd);
2749 
2750         if (rename(tmp_ks_name, ks_desc_file) != 0) {
2751                 goto cleanup;
2752         }
2753         ret_val = 0;
2754 
2755 cleanup:
2756         /* unlock keystore description file */
2757         if (!lock_held) {
2758                 if (lock_file(fd, B_FALSE, B_FALSE) != 0) {
2759                         (void) close(fd);
2760                         return (-1);
2761                 }
2762         }
2763 
2764         (void) close(fd);
2765         return (ret_val);
2766 }
2767 
2768 /*
2769  * Get the salt used for generating hashed pin from the
2770  * keystore description file.
2771  *
2772  * The result will be stored in the provided buffer "salt" passed
2773  * in as an argument.
2774  *
2775  * Return 0 if no error, return -1 if there's any error.
2776  */
2777 int
2778 soft_keystore_get_pin_salt(char **salt)
2779 {
2780         int fd, ret_val = -1;
2781         uint64_t hashed_pin_salt_size;
2782 
2783         if ((fd = open_and_lock_keystore_desc(O_RDONLY, B_FALSE,
2784             B_FALSE)) < 0) {
2785                 return (-1);
2786         }
2787 
2788         if (lseek(fd, KS_HASHED_PIN_SALT_LEN_OFFSET, SEEK_SET)
2789             != KS_HASHED_PIN_SALT_LEN_OFFSET) {
2790                 goto cleanup;
2791         }
2792 
2793         if (readn_nointr(fd, (char *)&hashed_pin_salt_size,
2794             KS_HASHED_PIN_SALT_LEN_SIZE) != KS_HASHED_PIN_SALT_LEN_SIZE) {
2795                 goto cleanup;
2796         }
2797         hashed_pin_salt_size = SWAP64(hashed_pin_salt_size);
2798 
2799         *salt = malloc(hashed_pin_salt_size + 1);
2800         if (*salt == NULL) {
2801                 goto cleanup;
2802         }
2803 
2804         if ((readn_nointr(fd, *salt, hashed_pin_salt_size))
2805             != (ssize_t)hashed_pin_salt_size) {
2806                 free(*salt);
2807                 goto cleanup;
2808         }
2809         (*salt)[hashed_pin_salt_size] = '\0';
2810 
2811         ret_val = 0;
2812 
2813 cleanup:
2814         if (lock_file(fd, B_TRUE, B_FALSE) < 0) {
2815                 ret_val = -1;
2816         }
2817 
2818         (void) close(fd);
2819         return (ret_val);
2820 }
2821 
2822 /*
2823  *      FUNCTION: soft_keystore_pin_initialized
2824  *
2825  *      ARGUMENTS:
2826  *              initialized: This value will be set to true if keystore is
2827  *                           initialized, and false otherwise.
2828  *              hashed_pin: If the keystore is initialized, this will contain
2829  *                          the hashed pin.  It will be NULL if the keystore
2830  *                          pin is not initialized.  Memory allocated
2831  *                          for the hashed pin needs to be freed by
2832  *                          the caller.
2833  *              lock_held: TRUE if the lock is held by caller.
2834  *
2835  *      RETURN VALUE:
2836  *              CKR_OK: No error
2837  *              any other appropriate CKR_value
2838  *
2839  *      DESCRIPTION:
2840  *              This API is used to determine if the PIN in the keystore
2841  *              has been initialized or not.
2842  *              It makes the determination using the salt for generating the
2843  *              encryption key.  The salt is stored in the keystore
2844  *              descryption file.  The salt should be all zero if
2845  *              the keystore pin has not been initialized.
2846  *              If the pin has been initialized, it is returned in the
2847  *              hashed_pin argument.
2848  */
2849 CK_RV
2850 soft_keystore_pin_initialized(boolean_t *initialized, char **hashed_pin,
2851     boolean_t lock_held)
2852 {
2853         int fd;
2854         CK_BYTE crypt_salt[KS_KEY_SALT_SIZE], tmp_buf[KS_KEY_SALT_SIZE];
2855         CK_RV ret_val = CKR_OK;
2856 
2857         if ((fd = open_and_lock_keystore_desc(O_RDONLY, B_FALSE,
2858             lock_held)) < 0) {
2859                 return (CKR_FUNCTION_FAILED);
2860         }
2861 
2862         if (lseek(fd, KS_KEY_SALT_OFFSET, SEEK_SET) != KS_KEY_SALT_OFFSET) {
2863                 ret_val = CKR_FUNCTION_FAILED;
2864                 goto cleanup;
2865         }
2866 
2867         if (readn_nointr(fd, (char *)crypt_salt, KS_KEY_SALT_SIZE)
2868             != KS_KEY_SALT_SIZE) {
2869                 ret_val = CKR_FUNCTION_FAILED;
2870                 goto cleanup;
2871         }
2872 
2873         (void) bzero(tmp_buf, KS_KEY_SALT_SIZE);
2874 
2875         if (memcmp(crypt_salt, tmp_buf, KS_KEY_SALT_SIZE) == 0) {
2876                 *initialized = B_FALSE;
2877                 hashed_pin = NULL;
2878         } else {
2879                 *initialized = B_TRUE;
2880                 ret_val = get_hashed_pin(fd, hashed_pin);
2881         }
2882 
2883 cleanup:
2884 
2885         if (!lock_held) {
2886                 if (lock_file(fd, B_TRUE, B_FALSE) < 0) {
2887                         ret_val = CKR_FUNCTION_FAILED;
2888                 }
2889         }
2890 
2891         (void) close(fd);
2892         return (ret_val);
2893 }
2894 
2895 /*
2896  * This checks if the keystore file exists
2897  */
2898 
2899 static int
2900 soft_keystore_exists()
2901 {
2902         int ret;
2903         struct stat fn_stat;
2904         char *fname, ks_desc_file[MAXPATHLEN];
2905 
2906         fname = get_desc_file_path(ks_desc_file);
2907         ret = stat(fname, &fn_stat);
2908         if (ret == 0)
2909                 return (0);
2910         return (errno);
2911 }
2912 
2913 /*
2914  *      FUNCTION: soft_keystore_init
2915  *
2916  *      ARGUMENTS:
2917  *              desired_state:  The keystore state the caller would like
2918  *                              it to be.
2919  *
2920  *      RETURN VALUE:
2921  *              Returns the state the function is in.  If it succeeded, it
2922  *              will be the same as the desired, if not it will be
2923  *              KEYSTORE_UNAVAILABLE.
2924  *
2925  *      DESCRIPTION:
2926  *              This function will only load as much keystore data as is
2927  *              requested at that time. This is for performace by delaying the
2928  *              reading of token objects until they are needed or never at
2929  *              all if they are not used.
2930  *
2931  *              Primary use is from C_InitToken().
2932  *              It is also called by soft_keystore_status() when the
2933  *              "desired_state" is not the the current load state of keystore.
2934  *
2935  */
2936 int
2937 soft_keystore_init(int desired_state)
2938 {
2939         int ret;
2940 
2941         (void) pthread_mutex_lock(&soft_slot.keystore_mutex);
2942 
2943         /*
2944          * If more than one session tries to initialize the keystore, the
2945          * second and other following sessions that were waiting for the lock
2946          * will quickly exit if their requirements are satisfied.
2947          */
2948         if (desired_state <= soft_slot.keystore_load_status) {
2949                 (void) pthread_mutex_unlock(&soft_slot.keystore_mutex);
2950                 return (soft_slot.keystore_load_status);
2951         }
2952 
2953         /*
2954          * With 'keystore_load_status' giving the current state of the
2955          * process, this switch will bring it up to the desired state if
2956          * possible.
2957          */
2958 
2959         switch (soft_slot.keystore_load_status) {
2960         case KEYSTORE_UNINITIALIZED:
2961                 ret = soft_keystore_exists();
2962                 if (ret == 0)
2963                         soft_slot.keystore_load_status = KEYSTORE_PRESENT;
2964                 else if (ret == ENOENT)
2965                         if (create_keystore() == 0)
2966                                 soft_slot.keystore_load_status =
2967                                     KEYSTORE_PRESENT;
2968                         else {
2969                                 soft_slot.keystore_load_status =
2970                                     KEYSTORE_UNAVAILABLE;
2971                                 cryptoerror(LOG_DEBUG,
2972                                     "pkcs11_softtoken: "
2973                                     "Cannot create keystore.");
2974                                 break;
2975                         }
2976 
2977                 if (desired_state <= KEYSTORE_PRESENT)
2978                         break;
2979 
2980         /* FALLTHRU */
2981         case KEYSTORE_PRESENT:
2982                 if (soft_keystore_get_version(&soft_slot.ks_version, B_FALSE)
2983                     != 0) {
2984                         soft_slot.keystore_load_status = KEYSTORE_UNAVAILABLE;
2985                         cryptoerror(LOG_DEBUG,
2986                             "pkcs11_softtoken: Keystore access failed.");
2987                         break;
2988                 }
2989 
2990                 soft_slot.keystore_load_status = KEYSTORE_LOAD;
2991                 if (desired_state <= KEYSTORE_LOAD)
2992                         break;
2993 
2994         /* FALLTHRU */
2995         case KEYSTORE_LOAD:
2996                 /* Load all the public token objects from keystore */
2997                 if (soft_get_token_objects_from_keystore(PUB_TOKENOBJS)
2998                     != CKR_OK) {
2999                         (void) soft_destroy_token_session();
3000                         soft_slot.keystore_load_status = KEYSTORE_UNAVAILABLE;
3001                         cryptoerror(LOG_DEBUG,
3002                             "pkcs11_softtoken: Cannot initialize keystore.");
3003                         break;
3004                 }
3005 
3006                 soft_slot.keystore_load_status = KEYSTORE_INITIALIZED;
3007         };
3008 
3009         (void) pthread_mutex_unlock(&soft_slot.keystore_mutex);
3010         return (soft_slot.keystore_load_status);
3011 }
3012 
3013 /*
3014  *      FUNCTION: soft_keystore_status
3015  *
3016  *      ARGUMENTS:
3017  *              desired_state:  The keystore state the caller would like
3018  *                              it to be.
3019  *
3020  *      RETURN VALUE:
3021  *              B_TRUE if keystore is ready and at the desired state.
3022  *              B_FALSE if keystore had an error and is not available.
3023  *
3024  *      DESCRIPTION:
3025  *              The calling function wants to make sure the keystore load
3026  *              status to in a state it requires.  If it is not at that
3027  *              state it will call the load function.
3028  *              If keystore is at the desired state or has just been
3029  *              loaded to that state, it will return TRUE.  If there has been
3030  *              load failure, it will return FALSE.
3031  *
3032  */
3033 boolean_t
3034 soft_keystore_status(int desired_state)
3035 {
3036 
3037         if (soft_slot.keystore_load_status == KEYSTORE_UNAVAILABLE)
3038                 return (B_FALSE);
3039 
3040         return ((desired_state <= soft_slot.keystore_load_status) ||
3041             (soft_keystore_init(desired_state) == desired_state));
3042 }