17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 590e0e8c4Sizick * Common Development and Distribution License (the "License"). 690e0e8c4Sizick * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*19193bb6SDina K Nimeh * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate /* 277c478bd9Sstevel@tonic-gate * Functions used for manipulating the keystore 287c478bd9Sstevel@tonic-gate */ 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate #include <stdio.h> 317c478bd9Sstevel@tonic-gate #include <stdlib.h> 327c478bd9Sstevel@tonic-gate #include <errno.h> 337c478bd9Sstevel@tonic-gate #include <sys/stat.h> 347c478bd9Sstevel@tonic-gate #include <fcntl.h> 357c478bd9Sstevel@tonic-gate #include <time.h> 367c478bd9Sstevel@tonic-gate #include <unistd.h> 377c478bd9Sstevel@tonic-gate #include <pwd.h> 387c478bd9Sstevel@tonic-gate #include <sys/types.h> 397c478bd9Sstevel@tonic-gate #include <dirent.h> 407c478bd9Sstevel@tonic-gate #include <limits.h> 417c478bd9Sstevel@tonic-gate #include <strings.h> 427c478bd9Sstevel@tonic-gate #include <security/cryptoki.h> 437c478bd9Sstevel@tonic-gate #include <cryptoutil.h> 447c478bd9Sstevel@tonic-gate #include "softGlobal.h" 457c478bd9Sstevel@tonic-gate #include "softObject.h" 4690e0e8c4Sizick #include "softSession.h" 477c478bd9Sstevel@tonic-gate #include "softKeystore.h" 487c478bd9Sstevel@tonic-gate #include "softKeystoreUtil.h" 497c478bd9Sstevel@tonic-gate 507c478bd9Sstevel@tonic-gate #define MAXPATHLEN 1024 517c478bd9Sstevel@tonic-gate #define SUNW_PATH ".sunw" /* top level Sun directory */ 527c478bd9Sstevel@tonic-gate #define KEYSTORE_PATH "pkcs11_softtoken" /* keystore directory */ 537c478bd9Sstevel@tonic-gate #define PUB_OBJ_DIR "public" /* directory for public objects */ 547c478bd9Sstevel@tonic-gate #define PRI_OBJ_DIR "private" /* directory for private objects */ 557c478bd9Sstevel@tonic-gate #define DS_FILE "objstore_info" /* keystore description file */ 567c478bd9Sstevel@tonic-gate #define TMP_DS_FILE "t_info" /* temp name for keystore desc. file */ 577c478bd9Sstevel@tonic-gate #define OBJ_PREFIX "obj" /* prefix of the keystore object file names */ 587c478bd9Sstevel@tonic-gate #define TMP_OBJ_PREFIX "t_o" /* prefix of the temp object file names */ 597c478bd9Sstevel@tonic-gate 607c478bd9Sstevel@tonic-gate /* 617c478bd9Sstevel@tonic-gate * KEYSTORE DESCRIPTION FILE: 627c478bd9Sstevel@tonic-gate * 637c478bd9Sstevel@tonic-gate * The following describes the content of the keystore description file 647c478bd9Sstevel@tonic-gate * 657c478bd9Sstevel@tonic-gate * The order AND data type of the fields are very important. 667c478bd9Sstevel@tonic-gate * All the code in this file assume that they are in the order specified 677c478bd9Sstevel@tonic-gate * below. If either order of the fields or their data type changed, 687c478bd9Sstevel@tonic-gate * you must make sure the ALL the pre-define values are still valid 697c478bd9Sstevel@tonic-gate * 7090e0e8c4Sizick * 1) PKCS#11 release number. It's 2.20 in this release (uchar_t[32]) 717c478bd9Sstevel@tonic-gate * 2) keystore version number: used for synchronizing when different 727c478bd9Sstevel@tonic-gate * processes access the keystore at the same time. It is incremented 737c478bd9Sstevel@tonic-gate * when there is a change to the keystore. (uint_32) 747c478bd9Sstevel@tonic-gate * 3) monotonic-counter: last counter value for name of token object file. 757c478bd9Sstevel@tonic-gate * used for assigning unique name to each token (uint_32) 767c478bd9Sstevel@tonic-gate * 4) salt used for generating encryption key (uint_16) 777c478bd9Sstevel@tonic-gate * 5) salt used for generating key used for doing HMAC (uint_16) 787c478bd9Sstevel@tonic-gate * 6) Length of salt used for generating hashed pin (length of salt 797c478bd9Sstevel@tonic-gate * is variable) 807c478bd9Sstevel@tonic-gate * 7) Salt used for generating hashed pin. 817c478bd9Sstevel@tonic-gate * 8) Hashed pin len (length of hashed pin could be variable, the offset of 827c478bd9Sstevel@tonic-gate * where this value lives in the file is calculated at run time) 837c478bd9Sstevel@tonic-gate * 9) Hashed pin 847c478bd9Sstevel@tonic-gate * 857c478bd9Sstevel@tonic-gate */ 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate /* Keystore description file pre-defined values */ 88f66d273dSizick #define KS_PKCS11_VER "2.20" 897c478bd9Sstevel@tonic-gate #define KS_PKCS11_OFFSET 0 907c478bd9Sstevel@tonic-gate #define KS_PKCS11_VER_SIZE 32 917c478bd9Sstevel@tonic-gate 927c478bd9Sstevel@tonic-gate #define KS_VER_OFFSET (KS_PKCS11_OFFSET + KS_PKCS11_VER_SIZE) 937c478bd9Sstevel@tonic-gate #define KS_VER_SIZE 4 /* size in bytes of keystore version value */ 947c478bd9Sstevel@tonic-gate 957c478bd9Sstevel@tonic-gate #define KS_COUNTER_OFFSET (KS_VER_OFFSET + KS_VER_SIZE) 967c478bd9Sstevel@tonic-gate #define KS_COUNTER_SIZE 4 /* size in bytes of the monotonic counter */ 977c478bd9Sstevel@tonic-gate 987c478bd9Sstevel@tonic-gate #define KS_KEY_SALT_OFFSET (KS_COUNTER_OFFSET + KS_COUNTER_SIZE) 997c478bd9Sstevel@tonic-gate #define KS_KEY_SALT_SIZE PBKD2_SALT_SIZE 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gate #define KS_HMAC_SALT_OFFSET (KS_KEY_SALT_OFFSET + KS_KEY_SALT_SIZE) 1027c478bd9Sstevel@tonic-gate #define KS_HMAC_SALT_SIZE PBKD2_SALT_SIZE 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate /* Salt for hashed pin */ 1057c478bd9Sstevel@tonic-gate #define KS_HASHED_PIN_SALT_LEN_OFFSET (KS_HMAC_SALT_OFFSET + KS_HMAC_SALT_SIZE) 1067c478bd9Sstevel@tonic-gate #define KS_HASHED_PIN_SALT_LEN_SIZE 8 /* stores length of hashed pin salt */ 1077c478bd9Sstevel@tonic-gate 1087c478bd9Sstevel@tonic-gate #define KS_HASHED_PIN_SALT_OFFSET \ 1097c478bd9Sstevel@tonic-gate (KS_HASHED_PIN_SALT_LEN_OFFSET + KS_HASHED_PIN_SALT_LEN_SIZE) 1107c478bd9Sstevel@tonic-gate 1117c478bd9Sstevel@tonic-gate /* 1127c478bd9Sstevel@tonic-gate * hashed pin 1137c478bd9Sstevel@tonic-gate * 1147c478bd9Sstevel@tonic-gate * hashed_pin length offset will be calculated at run time since 1157c478bd9Sstevel@tonic-gate * there's the hashed pin salt size is variable. 1167c478bd9Sstevel@tonic-gate * 1177c478bd9Sstevel@tonic-gate * The offset will be calculated at run time by calling the 1187c478bd9Sstevel@tonic-gate * function calculate_hashed_pin_offset() 1197c478bd9Sstevel@tonic-gate */ 1207c478bd9Sstevel@tonic-gate static off_t ks_hashed_pinlen_offset = -1; 1217c478bd9Sstevel@tonic-gate #define KS_HASHED_PINLEN_SIZE 8 1227c478bd9Sstevel@tonic-gate 1237c478bd9Sstevel@tonic-gate /* End of Keystore description file pre-defined values */ 1247c478bd9Sstevel@tonic-gate 1257c478bd9Sstevel@tonic-gate /* 1267c478bd9Sstevel@tonic-gate * Metadata for each object 1277c478bd9Sstevel@tonic-gate * 1287c478bd9Sstevel@tonic-gate * The order AND data type of all the fields is very important. 1297c478bd9Sstevel@tonic-gate * All the code in this file assume that they are in the order specified 1307c478bd9Sstevel@tonic-gate * below. If either order of the fields or their data type is changed, 1317c478bd9Sstevel@tonic-gate * you must make sure the following pre-define value is still valid 1327c478bd9Sstevel@tonic-gate * Each object will have the meta data at the beginning of the object file. 1337c478bd9Sstevel@tonic-gate * 1347c478bd9Sstevel@tonic-gate * 1) object_version: used by softtoken to see if the object 1357c478bd9Sstevel@tonic-gate * has been modified since it last reads it. (uint_32) 1367c478bd9Sstevel@tonic-gate * 2) iv: initialization vector for encrypted data in the object. This 1377c478bd9Sstevel@tonic-gate * value will be 0 for public objects. (uchar_t[16]) 1387c478bd9Sstevel@tonic-gate * 3) obj_hmac: keyed hash as verifier to detect private object 1397c478bd9Sstevel@tonic-gate * being tampered this value will be 0 for public objects (uchar_t[16]) 1407c478bd9Sstevel@tonic-gate */ 1417c478bd9Sstevel@tonic-gate 1427c478bd9Sstevel@tonic-gate /* Object metadata pre-defined values */ 1437c478bd9Sstevel@tonic-gate #define OBJ_VER_OFFSET 0 1447c478bd9Sstevel@tonic-gate #define OBJ_VER_SIZE 4 /* size of object version in bytes */ 1457c478bd9Sstevel@tonic-gate #define OBJ_IV_OFFSET (OBJ_VER_OFFSET + OBJ_VER_SIZE) 1467c478bd9Sstevel@tonic-gate #define OBJ_IV_SIZE 16 1477c478bd9Sstevel@tonic-gate #define OBJ_HMAC_OFFSET (OBJ_IV_OFFSET + OBJ_IV_SIZE) 1487c478bd9Sstevel@tonic-gate #define OBJ_HMAC_SIZE 16 /* MD5 HMAC keyed hash */ 1497c478bd9Sstevel@tonic-gate #define OBJ_DATA_OFFSET (OBJ_HMAC_OFFSET + OBJ_HMAC_SIZE) 1507c478bd9Sstevel@tonic-gate /* End of object metadata pre-defined values */ 1517c478bd9Sstevel@tonic-gate 1527c478bd9Sstevel@tonic-gate #define ALTERNATE_KEYSTORE_PATH "SOFTTOKEN_DIR" 1537c478bd9Sstevel@tonic-gate 1547c478bd9Sstevel@tonic-gate static soft_object_t *enc_key = NULL; 1557c478bd9Sstevel@tonic-gate static soft_object_t *hmac_key = NULL; 1567c478bd9Sstevel@tonic-gate static char keystore_path[MAXPATHLEN]; 1577c478bd9Sstevel@tonic-gate static boolean_t keystore_path_initialized = B_FALSE; 1587c478bd9Sstevel@tonic-gate static int desc_fd = 0; 1597c478bd9Sstevel@tonic-gate 16090e0e8c4Sizick 1617c478bd9Sstevel@tonic-gate static char * 1627c478bd9Sstevel@tonic-gate get_user_home_sunw_path(char *home_path) 1637c478bd9Sstevel@tonic-gate { 164e81dd421Sizick struct passwd pwd, *user_info; 165e81dd421Sizick char pwdbuf[PWD_BUFFER_SIZE]; 1667c478bd9Sstevel@tonic-gate 167e81dd421Sizick (void) getpwuid_r(getuid(), &pwd, pwdbuf, PWD_BUFFER_SIZE, &user_info); 1687c478bd9Sstevel@tonic-gate 1697c478bd9Sstevel@tonic-gate (void) snprintf(home_path, MAXPATHLEN, "%s/%s", 1707c478bd9Sstevel@tonic-gate user_info ? user_info->pw_dir : "", SUNW_PATH); 1717c478bd9Sstevel@tonic-gate 1727c478bd9Sstevel@tonic-gate return (home_path); 1737c478bd9Sstevel@tonic-gate } 1747c478bd9Sstevel@tonic-gate 1757c478bd9Sstevel@tonic-gate static char * 1767c478bd9Sstevel@tonic-gate get_keystore_path() 1777c478bd9Sstevel@tonic-gate { 1787c478bd9Sstevel@tonic-gate char *env_val; 1797c478bd9Sstevel@tonic-gate char home_path[MAXPATHLEN]; 1807c478bd9Sstevel@tonic-gate 1817c478bd9Sstevel@tonic-gate if (!keystore_path_initialized) { 1827c478bd9Sstevel@tonic-gate env_val = getenv(ALTERNATE_KEYSTORE_PATH); 1837c478bd9Sstevel@tonic-gate bzero(keystore_path, sizeof (keystore_path)); 1847c478bd9Sstevel@tonic-gate /* 1857c478bd9Sstevel@tonic-gate * If it isn't set or is set to the empty string use the 1867c478bd9Sstevel@tonic-gate * default location. We need to check for the empty string 1877c478bd9Sstevel@tonic-gate * because some users "unset" environment variables by giving 1887c478bd9Sstevel@tonic-gate * them no value, this isn't the same thing as removing it 1897c478bd9Sstevel@tonic-gate * from the environment. 1907c478bd9Sstevel@tonic-gate * 1917c478bd9Sstevel@tonic-gate * We don't want that to attempt to open /.sunw/pkcs11_sofftoken 1927c478bd9Sstevel@tonic-gate */ 1937c478bd9Sstevel@tonic-gate if ((env_val == NULL) || (strcmp(env_val, "") == 0)) { 1947c478bd9Sstevel@tonic-gate /* alternate path not specified, use user's home dir */ 1957c478bd9Sstevel@tonic-gate (void) snprintf(keystore_path, MAXPATHLEN, "%s/%s", 1967c478bd9Sstevel@tonic-gate get_user_home_sunw_path(home_path), KEYSTORE_PATH); 1977c478bd9Sstevel@tonic-gate } else { 1987c478bd9Sstevel@tonic-gate (void) snprintf(keystore_path, MAXPATHLEN, "%s/%s", 1997c478bd9Sstevel@tonic-gate env_val, KEYSTORE_PATH); 2007c478bd9Sstevel@tonic-gate } 2017c478bd9Sstevel@tonic-gate keystore_path_initialized = B_TRUE; 2027c478bd9Sstevel@tonic-gate } 2037c478bd9Sstevel@tonic-gate return (keystore_path); 2047c478bd9Sstevel@tonic-gate } 2057c478bd9Sstevel@tonic-gate 2067c478bd9Sstevel@tonic-gate static char * 2077c478bd9Sstevel@tonic-gate get_pub_obj_path(char *name) 2087c478bd9Sstevel@tonic-gate { 2097c478bd9Sstevel@tonic-gate bzero(name, sizeof (name)); 2107c478bd9Sstevel@tonic-gate (void) snprintf(name, MAXPATHLEN, "%s/%s", 2117c478bd9Sstevel@tonic-gate get_keystore_path(), PUB_OBJ_DIR); 2127c478bd9Sstevel@tonic-gate return (name); 2137c478bd9Sstevel@tonic-gate } 2147c478bd9Sstevel@tonic-gate 2157c478bd9Sstevel@tonic-gate static char * 2167c478bd9Sstevel@tonic-gate get_pri_obj_path(char *name) 2177c478bd9Sstevel@tonic-gate { 2187c478bd9Sstevel@tonic-gate bzero(name, sizeof (name)); 2197c478bd9Sstevel@tonic-gate (void) snprintf(name, MAXPATHLEN, "%s/%s", 2207c478bd9Sstevel@tonic-gate get_keystore_path(), PRI_OBJ_DIR); 2217c478bd9Sstevel@tonic-gate return (name); 2227c478bd9Sstevel@tonic-gate } 2237c478bd9Sstevel@tonic-gate 2247c478bd9Sstevel@tonic-gate static char * 2257c478bd9Sstevel@tonic-gate get_desc_file_path(char *name) 2267c478bd9Sstevel@tonic-gate { 2277c478bd9Sstevel@tonic-gate bzero(name, sizeof (name)); 2287c478bd9Sstevel@tonic-gate (void) snprintf(name, MAXPATHLEN, "%s/%s", 2297c478bd9Sstevel@tonic-gate get_keystore_path(), DS_FILE); 2307c478bd9Sstevel@tonic-gate return (name); 2317c478bd9Sstevel@tonic-gate } 2327c478bd9Sstevel@tonic-gate 2337c478bd9Sstevel@tonic-gate static char * 2347c478bd9Sstevel@tonic-gate get_tmp_desc_file_path(char *name) 2357c478bd9Sstevel@tonic-gate { 2367c478bd9Sstevel@tonic-gate bzero(name, sizeof (name)); 2377c478bd9Sstevel@tonic-gate (void) snprintf(name, MAXPATHLEN, "%s/%s", 2387c478bd9Sstevel@tonic-gate get_keystore_path(), TMP_DS_FILE); 2397c478bd9Sstevel@tonic-gate return (name); 2407c478bd9Sstevel@tonic-gate } 2417c478bd9Sstevel@tonic-gate 2427c478bd9Sstevel@tonic-gate /* 2437c478bd9Sstevel@tonic-gate * Calculates the offset for hashed_pin length and hashed pin 2447c478bd9Sstevel@tonic-gate * 2457c478bd9Sstevel@tonic-gate * Returns 0 if successful, -1 if there's any error. 2467c478bd9Sstevel@tonic-gate * 2477c478bd9Sstevel@tonic-gate * If successful, global variables "ks_hashed_pinlen_offset" will be set. 2487c478bd9Sstevel@tonic-gate * 2497c478bd9Sstevel@tonic-gate */ 2507c478bd9Sstevel@tonic-gate static int 2517c478bd9Sstevel@tonic-gate calculate_hashed_pin_offset(int fd) 2527c478bd9Sstevel@tonic-gate { 2537c478bd9Sstevel@tonic-gate uint64_t salt_length; 2547c478bd9Sstevel@tonic-gate 2557c478bd9Sstevel@tonic-gate if (lseek(fd, KS_HASHED_PIN_SALT_LEN_OFFSET, SEEK_SET) 2567c478bd9Sstevel@tonic-gate != KS_HASHED_PIN_SALT_LEN_OFFSET) { 2577c478bd9Sstevel@tonic-gate return (-1); 2587c478bd9Sstevel@tonic-gate } 2597c478bd9Sstevel@tonic-gate 260*19193bb6SDina K Nimeh if (readn_nointr(fd, (char *)&salt_length, 2617c478bd9Sstevel@tonic-gate KS_HASHED_PIN_SALT_LEN_SIZE) != KS_HASHED_PIN_SALT_LEN_SIZE) { 2627c478bd9Sstevel@tonic-gate return (-1); 2637c478bd9Sstevel@tonic-gate } 2647c478bd9Sstevel@tonic-gate salt_length = SWAP64(salt_length); 2657c478bd9Sstevel@tonic-gate 2667c478bd9Sstevel@tonic-gate ks_hashed_pinlen_offset = KS_HASHED_PIN_SALT_LEN_OFFSET 2677c478bd9Sstevel@tonic-gate + KS_HASHED_PIN_SALT_LEN_SIZE + salt_length; 2687c478bd9Sstevel@tonic-gate 2697c478bd9Sstevel@tonic-gate return (0); 2707c478bd9Sstevel@tonic-gate 2717c478bd9Sstevel@tonic-gate } 2727c478bd9Sstevel@tonic-gate 2737c478bd9Sstevel@tonic-gate /* 2747c478bd9Sstevel@tonic-gate * acquire or release read/write lock on a specific file 2757c478bd9Sstevel@tonic-gate * 2767c478bd9Sstevel@tonic-gate * read_lock: true for read lock; false for write lock 2777c478bd9Sstevel@tonic-gate * set_lock: true to set a lock; false to release a lock 2787c478bd9Sstevel@tonic-gate */ 2797c478bd9Sstevel@tonic-gate static int 2807c478bd9Sstevel@tonic-gate lock_file(int fd, boolean_t read_lock, boolean_t set_lock) 2817c478bd9Sstevel@tonic-gate { 2827c478bd9Sstevel@tonic-gate 2837c478bd9Sstevel@tonic-gate flock_t lock_info; 2847c478bd9Sstevel@tonic-gate int r; 2857c478bd9Sstevel@tonic-gate 2867c478bd9Sstevel@tonic-gate lock_info.l_whence = SEEK_SET; 2877c478bd9Sstevel@tonic-gate lock_info.l_start = 0; 2887c478bd9Sstevel@tonic-gate lock_info.l_len = 0; /* l_len == 0 means until end of file */ 2897c478bd9Sstevel@tonic-gate 2907c478bd9Sstevel@tonic-gate if (read_lock) { 2917c478bd9Sstevel@tonic-gate lock_info.l_type = F_RDLCK; 2927c478bd9Sstevel@tonic-gate } else { 2937c478bd9Sstevel@tonic-gate lock_info.l_type = F_WRLCK; 2947c478bd9Sstevel@tonic-gate } 2957c478bd9Sstevel@tonic-gate 2967c478bd9Sstevel@tonic-gate if (set_lock) { 2977c478bd9Sstevel@tonic-gate while ((r = fcntl(fd, F_SETLKW, &lock_info)) == -1) { 2987c478bd9Sstevel@tonic-gate if (errno != EINTR) 2997c478bd9Sstevel@tonic-gate break; 3007c478bd9Sstevel@tonic-gate } 3017c478bd9Sstevel@tonic-gate if (r == -1) { 3027c478bd9Sstevel@tonic-gate return (-1); 3037c478bd9Sstevel@tonic-gate } 3047c478bd9Sstevel@tonic-gate } else { 3057c478bd9Sstevel@tonic-gate lock_info.l_type = F_UNLCK; 3067c478bd9Sstevel@tonic-gate while ((r = fcntl(fd, F_SETLKW, &lock_info)) == -1) { 3077c478bd9Sstevel@tonic-gate if (errno != EINTR) 3087c478bd9Sstevel@tonic-gate break; 3097c478bd9Sstevel@tonic-gate } 3107c478bd9Sstevel@tonic-gate if (r == -1) { 3117c478bd9Sstevel@tonic-gate return (-1); 3127c478bd9Sstevel@tonic-gate } 3137c478bd9Sstevel@tonic-gate } 3147c478bd9Sstevel@tonic-gate 3157c478bd9Sstevel@tonic-gate return (0); 3167c478bd9Sstevel@tonic-gate } 3177c478bd9Sstevel@tonic-gate 3187c478bd9Sstevel@tonic-gate static int 3197c478bd9Sstevel@tonic-gate create_keystore() 3207c478bd9Sstevel@tonic-gate { 3217c478bd9Sstevel@tonic-gate int fd, buf; 3227c478bd9Sstevel@tonic-gate uint64_t hashed_pin_len, hashed_pin_salt_len, ulong_buf; 3237c478bd9Sstevel@tonic-gate uchar_t ver_buf[KS_PKCS11_VER_SIZE]; 3247c478bd9Sstevel@tonic-gate char pub_obj_path[MAXPATHLEN], pri_obj_path[MAXPATHLEN], 3257c478bd9Sstevel@tonic-gate ks_desc_file[MAXPATHLEN]; 3267c478bd9Sstevel@tonic-gate CK_BYTE salt[KS_KEY_SALT_SIZE]; 3277c478bd9Sstevel@tonic-gate char *hashed_pin = NULL, *hashed_pin_salt = NULL; 3287c478bd9Sstevel@tonic-gate char *env_val; 3297c478bd9Sstevel@tonic-gate 3307c478bd9Sstevel@tonic-gate /* keystore doesn't exist, create keystore directory */ 3317c478bd9Sstevel@tonic-gate if (mkdir(get_keystore_path(), S_IRUSR|S_IWUSR|S_IXUSR) < 0) { 3327c478bd9Sstevel@tonic-gate if (errno == EEXIST) { 3337c478bd9Sstevel@tonic-gate return (0); 3347c478bd9Sstevel@tonic-gate } 3357c478bd9Sstevel@tonic-gate 3367c478bd9Sstevel@tonic-gate if (errno == EACCES) { 3377c478bd9Sstevel@tonic-gate return (-1); 3387c478bd9Sstevel@tonic-gate } 3397c478bd9Sstevel@tonic-gate 3407c478bd9Sstevel@tonic-gate /* can't create keystore directory */ 3417c478bd9Sstevel@tonic-gate if (errno == ENOENT) { /* part of the path doesn't exist */ 3427c478bd9Sstevel@tonic-gate /* 3437c478bd9Sstevel@tonic-gate * try to create $HOME/.sunw if it doesn't 3447c478bd9Sstevel@tonic-gate * exist. If it is a alternate path provided by the 3457c478bd9Sstevel@tonic-gate * user, it should have existed. Will not 3467c478bd9Sstevel@tonic-gate * create for them. 3477c478bd9Sstevel@tonic-gate */ 3487c478bd9Sstevel@tonic-gate env_val = getenv(ALTERNATE_KEYSTORE_PATH); 3497c478bd9Sstevel@tonic-gate if ((env_val == NULL) || (strcmp(env_val, "") == 0)) { 3507c478bd9Sstevel@tonic-gate char sunw_path[MAXPATHLEN]; 3517c478bd9Sstevel@tonic-gate 3527c478bd9Sstevel@tonic-gate /* create $HOME/.sunw */ 3537c478bd9Sstevel@tonic-gate if (mkdir(get_user_home_sunw_path(sunw_path), 3547c478bd9Sstevel@tonic-gate S_IRUSR|S_IWUSR|S_IXUSR) < 0) { 3557c478bd9Sstevel@tonic-gate return (-1); 3567c478bd9Sstevel@tonic-gate } 3577c478bd9Sstevel@tonic-gate 3587c478bd9Sstevel@tonic-gate /* create $HOME/.sunw/pkcs11_softtoken */ 3597c478bd9Sstevel@tonic-gate if (mkdir(get_keystore_path(), 3607c478bd9Sstevel@tonic-gate S_IRUSR|S_IWUSR|S_IXUSR) < 0) { 3617c478bd9Sstevel@tonic-gate return (-1); 3627c478bd9Sstevel@tonic-gate } 3637c478bd9Sstevel@tonic-gate } else { 3647c478bd9Sstevel@tonic-gate return (-1); 3657c478bd9Sstevel@tonic-gate } 3667c478bd9Sstevel@tonic-gate } 3677c478bd9Sstevel@tonic-gate } 3687c478bd9Sstevel@tonic-gate 3697c478bd9Sstevel@tonic-gate /* create keystore description file */ 370*19193bb6SDina K Nimeh fd = open_nointr(get_desc_file_path(ks_desc_file), 371*19193bb6SDina K Nimeh O_RDWR|O_CREAT|O_EXCL|O_NONBLOCK, S_IRUSR|S_IWUSR); 3727c478bd9Sstevel@tonic-gate if (fd < 0) { 3737c478bd9Sstevel@tonic-gate if (errno == EEXIST) { 3747c478bd9Sstevel@tonic-gate return (0); 3757c478bd9Sstevel@tonic-gate } else { 3767c478bd9Sstevel@tonic-gate /* can't create keystore description file */ 3777c478bd9Sstevel@tonic-gate (void) rmdir(get_keystore_path()); 3787c478bd9Sstevel@tonic-gate return (-1); 3797c478bd9Sstevel@tonic-gate } 3807c478bd9Sstevel@tonic-gate } 3817c478bd9Sstevel@tonic-gate 3827c478bd9Sstevel@tonic-gate if (lock_file(fd, B_FALSE, B_TRUE) != 0) { 3837c478bd9Sstevel@tonic-gate (void) unlink(ks_desc_file); 3847c478bd9Sstevel@tonic-gate (void) close(fd); 3857c478bd9Sstevel@tonic-gate (void) rmdir(get_keystore_path()); 3867c478bd9Sstevel@tonic-gate return (-1); 3877c478bd9Sstevel@tonic-gate } 3887c478bd9Sstevel@tonic-gate 3897c478bd9Sstevel@tonic-gate if (mkdir(get_pub_obj_path(pub_obj_path), 3907c478bd9Sstevel@tonic-gate S_IRUSR|S_IWUSR|S_IXUSR) < 0) { 3917c478bd9Sstevel@tonic-gate /* can't create directory for public objects */ 3927c478bd9Sstevel@tonic-gate (void) lock_file(fd, B_FALSE, B_FALSE); 3937c478bd9Sstevel@tonic-gate (void) unlink(ks_desc_file); 3947c478bd9Sstevel@tonic-gate (void) close(fd); 3957c478bd9Sstevel@tonic-gate (void) rmdir(get_keystore_path()); 3967c478bd9Sstevel@tonic-gate return (-1); 3977c478bd9Sstevel@tonic-gate } 3987c478bd9Sstevel@tonic-gate 3997c478bd9Sstevel@tonic-gate if (mkdir(get_pri_obj_path(pri_obj_path), 4007c478bd9Sstevel@tonic-gate S_IRUSR|S_IWUSR|S_IXUSR) < 0) { 4017c478bd9Sstevel@tonic-gate /* can't create directory for private objects */ 4027c478bd9Sstevel@tonic-gate (void) lock_file(fd, B_FALSE, B_FALSE); 4037c478bd9Sstevel@tonic-gate (void) unlink(ks_desc_file); 4047c478bd9Sstevel@tonic-gate (void) close(fd); 4057c478bd9Sstevel@tonic-gate (void) rmdir(get_keystore_path()); 4067c478bd9Sstevel@tonic-gate (void) rmdir(pub_obj_path); 4077c478bd9Sstevel@tonic-gate return (-1); 4087c478bd9Sstevel@tonic-gate } 4097c478bd9Sstevel@tonic-gate 4107c478bd9Sstevel@tonic-gate 4117c478bd9Sstevel@tonic-gate /* write file format release number */ 4127c478bd9Sstevel@tonic-gate bzero(ver_buf, sizeof (ver_buf)); 4137c478bd9Sstevel@tonic-gate (void) strcpy((char *)ver_buf, KS_PKCS11_VER); 414*19193bb6SDina K Nimeh if ((writen_nointr(fd, (char *)ver_buf, sizeof (ver_buf))) 4157c478bd9Sstevel@tonic-gate != sizeof (ver_buf)) { 4167c478bd9Sstevel@tonic-gate goto cleanup; 4177c478bd9Sstevel@tonic-gate } 4187c478bd9Sstevel@tonic-gate 4197c478bd9Sstevel@tonic-gate /* write version number, version = 0 since keystore just created */ 4207c478bd9Sstevel@tonic-gate buf = SWAP32(0); 421*19193bb6SDina K Nimeh if (writen_nointr(fd, (void *)&buf, KS_VER_SIZE) != KS_VER_SIZE) { 4227c478bd9Sstevel@tonic-gate goto cleanup; 4237c478bd9Sstevel@tonic-gate } 4247c478bd9Sstevel@tonic-gate 4257c478bd9Sstevel@tonic-gate /* write monotonic-counter. Counter for keystore objects start at 1 */ 4267c478bd9Sstevel@tonic-gate buf = SWAP32(1); 427*19193bb6SDina K Nimeh if (writen_nointr(fd, (void *)&buf, KS_COUNTER_SIZE) 4287c478bd9Sstevel@tonic-gate != KS_COUNTER_SIZE) { 4297c478bd9Sstevel@tonic-gate goto cleanup; 4307c478bd9Sstevel@tonic-gate } 4317c478bd9Sstevel@tonic-gate 4327c478bd9Sstevel@tonic-gate /* initial encryption key salt should be all NULL */ 4337c478bd9Sstevel@tonic-gate bzero(salt, sizeof (salt)); 434*19193bb6SDina K Nimeh if (writen_nointr(fd, (void *)salt, KS_KEY_SALT_SIZE) 4357c478bd9Sstevel@tonic-gate != KS_KEY_SALT_SIZE) { 4367c478bd9Sstevel@tonic-gate goto cleanup; 4377c478bd9Sstevel@tonic-gate } 4387c478bd9Sstevel@tonic-gate 4397c478bd9Sstevel@tonic-gate /* initial HMAC key salt should also be all NULL */ 440*19193bb6SDina K Nimeh if (writen_nointr(fd, (void *)salt, KS_HMAC_SALT_SIZE) 4417c478bd9Sstevel@tonic-gate != KS_HMAC_SALT_SIZE) { 4427c478bd9Sstevel@tonic-gate goto cleanup; 4437c478bd9Sstevel@tonic-gate } 4447c478bd9Sstevel@tonic-gate 4457c478bd9Sstevel@tonic-gate /* generate the hashed pin salt, and MD5 hashed pin of default pin */ 4467c478bd9Sstevel@tonic-gate if (soft_gen_hashed_pin((CK_CHAR_PTR)SOFT_DEFAULT_PIN, &hashed_pin, 4477c478bd9Sstevel@tonic-gate &hashed_pin_salt) < 0) { 4487c478bd9Sstevel@tonic-gate goto cleanup; 4497c478bd9Sstevel@tonic-gate } 4507c478bd9Sstevel@tonic-gate 4517c478bd9Sstevel@tonic-gate if ((hashed_pin_salt == NULL) || (hashed_pin == NULL)) { 4527c478bd9Sstevel@tonic-gate goto cleanup; 4537c478bd9Sstevel@tonic-gate } 4547c478bd9Sstevel@tonic-gate 4557c478bd9Sstevel@tonic-gate hashed_pin_salt_len = (uint64_t)strlen(hashed_pin_salt); 4567c478bd9Sstevel@tonic-gate hashed_pin_len = (uint64_t)strlen(hashed_pin); 4577c478bd9Sstevel@tonic-gate 4587c478bd9Sstevel@tonic-gate /* write hashed pin salt length */ 4597c478bd9Sstevel@tonic-gate ulong_buf = SWAP64(hashed_pin_salt_len); 460*19193bb6SDina K Nimeh if (writen_nointr(fd, (void *)&ulong_buf, KS_HASHED_PIN_SALT_LEN_SIZE) 4617c478bd9Sstevel@tonic-gate != KS_HASHED_PIN_SALT_LEN_SIZE) { 4627c478bd9Sstevel@tonic-gate goto cleanup; 4637c478bd9Sstevel@tonic-gate } 4647c478bd9Sstevel@tonic-gate 465*19193bb6SDina K Nimeh if (writen_nointr(fd, (void *)hashed_pin_salt, 4667c478bd9Sstevel@tonic-gate hashed_pin_salt_len) != hashed_pin_salt_len) { 4677c478bd9Sstevel@tonic-gate goto cleanup; 4687c478bd9Sstevel@tonic-gate } 4697c478bd9Sstevel@tonic-gate 4707c478bd9Sstevel@tonic-gate /* write MD5 hashed pin of the default pin */ 4717c478bd9Sstevel@tonic-gate ulong_buf = SWAP64(hashed_pin_len); 472*19193bb6SDina K Nimeh if (writen_nointr(fd, (void *)&ulong_buf, KS_HASHED_PINLEN_SIZE) 4737c478bd9Sstevel@tonic-gate != KS_HASHED_PINLEN_SIZE) { 4747c478bd9Sstevel@tonic-gate goto cleanup; 4757c478bd9Sstevel@tonic-gate } 4767c478bd9Sstevel@tonic-gate 477*19193bb6SDina K Nimeh if (writen_nointr(fd, (void *)hashed_pin, hashed_pin_len) 4787c478bd9Sstevel@tonic-gate != hashed_pin_len) { 4797c478bd9Sstevel@tonic-gate goto cleanup; 4807c478bd9Sstevel@tonic-gate } 4817c478bd9Sstevel@tonic-gate 4827c478bd9Sstevel@tonic-gate (void) lock_file(fd, B_FALSE, B_FALSE); 4837c478bd9Sstevel@tonic-gate 4847c478bd9Sstevel@tonic-gate (void) close(fd); 4857c478bd9Sstevel@tonic-gate if (hashed_pin_salt) 486*19193bb6SDina K Nimeh free(hashed_pin_salt); 4877c478bd9Sstevel@tonic-gate return (0); 4887c478bd9Sstevel@tonic-gate 4897c478bd9Sstevel@tonic-gate cleanup: 4907c478bd9Sstevel@tonic-gate (void) lock_file(fd, B_FALSE, B_FALSE); 4917c478bd9Sstevel@tonic-gate (void) unlink(ks_desc_file); 4927c478bd9Sstevel@tonic-gate (void) close(fd); 4937c478bd9Sstevel@tonic-gate (void) rmdir(get_keystore_path()); 4947c478bd9Sstevel@tonic-gate (void) rmdir(pub_obj_path); 4957c478bd9Sstevel@tonic-gate (void) rmdir(pri_obj_path); 4967c478bd9Sstevel@tonic-gate return (-1); 4977c478bd9Sstevel@tonic-gate } 4987c478bd9Sstevel@tonic-gate 4997c478bd9Sstevel@tonic-gate /* 5007c478bd9Sstevel@tonic-gate * Determines if the file referenced by "fd" has the same 5017c478bd9Sstevel@tonic-gate * inode as the file referenced by "fname". 5027c478bd9Sstevel@tonic-gate * 5037c478bd9Sstevel@tonic-gate * The argument "same" contains the result of determining 5047c478bd9Sstevel@tonic-gate * if the inode is the same or not 5057c478bd9Sstevel@tonic-gate * 5067c478bd9Sstevel@tonic-gate * Returns 0 if there's no error. 5077c478bd9Sstevel@tonic-gate * Returns 1 if there's any error with opening the file. 5087c478bd9Sstevel@tonic-gate * 5097c478bd9Sstevel@tonic-gate * 5107c478bd9Sstevel@tonic-gate */ 5117c478bd9Sstevel@tonic-gate static int 5127c478bd9Sstevel@tonic-gate is_inode_same(int fd, char *fname, boolean_t *same) 5137c478bd9Sstevel@tonic-gate { 5147c478bd9Sstevel@tonic-gate struct stat fn_stat, fd_stat; 5157c478bd9Sstevel@tonic-gate 5167c478bd9Sstevel@tonic-gate if (fstat(fd, &fd_stat) != 0) { 5177c478bd9Sstevel@tonic-gate return (-1); 5187c478bd9Sstevel@tonic-gate } 5197c478bd9Sstevel@tonic-gate 5207c478bd9Sstevel@tonic-gate if (stat(fname, &fn_stat) != 0) { 5217c478bd9Sstevel@tonic-gate return (-1); 5227c478bd9Sstevel@tonic-gate } 5237c478bd9Sstevel@tonic-gate 5247c478bd9Sstevel@tonic-gate /* It's the same file if both st_ino and st_dev match */ 5257c478bd9Sstevel@tonic-gate if ((fd_stat.st_ino == fn_stat.st_ino) && 5267c478bd9Sstevel@tonic-gate (fd_stat.st_dev == fn_stat.st_dev)) { 5277c478bd9Sstevel@tonic-gate *same = B_TRUE; 5287c478bd9Sstevel@tonic-gate } else { 5297c478bd9Sstevel@tonic-gate *same = B_FALSE; 5307c478bd9Sstevel@tonic-gate } 5317c478bd9Sstevel@tonic-gate return (0); 5327c478bd9Sstevel@tonic-gate } 5337c478bd9Sstevel@tonic-gate 5347c478bd9Sstevel@tonic-gate static int 5357c478bd9Sstevel@tonic-gate acquire_file_lock(int *fd, char *fname, mode_t mode) { 5367c478bd9Sstevel@tonic-gate 5377c478bd9Sstevel@tonic-gate boolean_t read_lock = B_TRUE, same_inode; 5387c478bd9Sstevel@tonic-gate 5397c478bd9Sstevel@tonic-gate if ((mode == O_RDWR) || (mode == O_WRONLY)) { 5407c478bd9Sstevel@tonic-gate read_lock = B_FALSE; 5417c478bd9Sstevel@tonic-gate } 5427c478bd9Sstevel@tonic-gate 5437c478bd9Sstevel@tonic-gate if (lock_file(*fd, read_lock, B_TRUE) != 0) { 5447c478bd9Sstevel@tonic-gate return (-1); 5457c478bd9Sstevel@tonic-gate } 5467c478bd9Sstevel@tonic-gate 5477c478bd9Sstevel@tonic-gate /* 5487c478bd9Sstevel@tonic-gate * make sure another process did not modify the file 5497c478bd9Sstevel@tonic-gate * while we were trying to get the lock 5507c478bd9Sstevel@tonic-gate */ 5517c478bd9Sstevel@tonic-gate if (is_inode_same(*fd, fname, &same_inode) != 0) { 5527c478bd9Sstevel@tonic-gate (void) lock_file(*fd, B_TRUE, B_FALSE); /* unlock file */ 5537c478bd9Sstevel@tonic-gate return (-1); 5547c478bd9Sstevel@tonic-gate } 5557c478bd9Sstevel@tonic-gate 5567c478bd9Sstevel@tonic-gate while (!same_inode) { 5577c478bd9Sstevel@tonic-gate /* 5587c478bd9Sstevel@tonic-gate * need to unlock file, close, re-open the file, 5597c478bd9Sstevel@tonic-gate * and re-acquire the lock 5607c478bd9Sstevel@tonic-gate */ 5617c478bd9Sstevel@tonic-gate 5627c478bd9Sstevel@tonic-gate /* unlock file */ 5637c478bd9Sstevel@tonic-gate if (lock_file(*fd, B_TRUE, B_FALSE) != 0) { 5647c478bd9Sstevel@tonic-gate return (-1); 5657c478bd9Sstevel@tonic-gate } 5667c478bd9Sstevel@tonic-gate 5677c478bd9Sstevel@tonic-gate (void) close(*fd); 5687c478bd9Sstevel@tonic-gate 5697c478bd9Sstevel@tonic-gate /* re-open */ 570*19193bb6SDina K Nimeh *fd = open_nointr(fname, mode|O_NONBLOCK); 5717c478bd9Sstevel@tonic-gate if (*fd < 0) { 5727c478bd9Sstevel@tonic-gate return (-1); 5737c478bd9Sstevel@tonic-gate } 5747c478bd9Sstevel@tonic-gate 5757c478bd9Sstevel@tonic-gate /* acquire lock again */ 5767c478bd9Sstevel@tonic-gate if (lock_file(*fd, read_lock, B_TRUE) != 0) { 5777c478bd9Sstevel@tonic-gate return (-1); 5787c478bd9Sstevel@tonic-gate } 5797c478bd9Sstevel@tonic-gate 5807c478bd9Sstevel@tonic-gate if (is_inode_same(*fd, fname, &same_inode) != 0) { 5817c478bd9Sstevel@tonic-gate (void) lock_file(*fd, B_TRUE, B_FALSE); /* unlock */ 5827c478bd9Sstevel@tonic-gate return (-1); 5837c478bd9Sstevel@tonic-gate } 5847c478bd9Sstevel@tonic-gate 5857c478bd9Sstevel@tonic-gate } 5867c478bd9Sstevel@tonic-gate 5877c478bd9Sstevel@tonic-gate return (0); 5887c478bd9Sstevel@tonic-gate } 5897c478bd9Sstevel@tonic-gate 5907c478bd9Sstevel@tonic-gate /* 5917c478bd9Sstevel@tonic-gate * Open the keystore description file in the specified mode. 5927c478bd9Sstevel@tonic-gate * If the keystore doesn't exist, the "do_create_keystore" 5937c478bd9Sstevel@tonic-gate * argument determines if the keystore should be created 5947c478bd9Sstevel@tonic-gate */ 5957c478bd9Sstevel@tonic-gate static int 5967c478bd9Sstevel@tonic-gate open_and_lock_keystore_desc(mode_t mode, boolean_t do_create_keystore, 5977c478bd9Sstevel@tonic-gate boolean_t lock_held) 5987c478bd9Sstevel@tonic-gate { 5997c478bd9Sstevel@tonic-gate 6007c478bd9Sstevel@tonic-gate int fd; 6017c478bd9Sstevel@tonic-gate char *fname, ks_desc_file[MAXPATHLEN]; 6027c478bd9Sstevel@tonic-gate 6037c478bd9Sstevel@tonic-gate /* open the keystore description file in requested mode */ 6047c478bd9Sstevel@tonic-gate fname = get_desc_file_path(ks_desc_file); 605*19193bb6SDina K Nimeh fd = open_nointr(fname, mode|O_NONBLOCK); 6067c478bd9Sstevel@tonic-gate if (fd < 0) { 6077c478bd9Sstevel@tonic-gate if ((errno == ENOENT) && (do_create_keystore)) { 6087c478bd9Sstevel@tonic-gate if (create_keystore() < 0) { 6097c478bd9Sstevel@tonic-gate goto done; 6107c478bd9Sstevel@tonic-gate } 611*19193bb6SDina K Nimeh fd = open_nointr(fname, mode|O_NONBLOCK); 6127c478bd9Sstevel@tonic-gate if (fd < 0) { 6137c478bd9Sstevel@tonic-gate goto done; 6147c478bd9Sstevel@tonic-gate } 6157c478bd9Sstevel@tonic-gate } else { 6167c478bd9Sstevel@tonic-gate goto done; 6177c478bd9Sstevel@tonic-gate } 6187c478bd9Sstevel@tonic-gate } 6197c478bd9Sstevel@tonic-gate 6207c478bd9Sstevel@tonic-gate if (lock_held) { 6217c478bd9Sstevel@tonic-gate /* already hold the lock */ 6227c478bd9Sstevel@tonic-gate return (fd); 6237c478bd9Sstevel@tonic-gate } 6247c478bd9Sstevel@tonic-gate 6257c478bd9Sstevel@tonic-gate if (acquire_file_lock(&fd, fname, mode) != 0) { 6267c478bd9Sstevel@tonic-gate if (fd > 0) { 6277c478bd9Sstevel@tonic-gate (void) close(fd); 6287c478bd9Sstevel@tonic-gate } 6297c478bd9Sstevel@tonic-gate return (-1); 6307c478bd9Sstevel@tonic-gate } 6317c478bd9Sstevel@tonic-gate 6327c478bd9Sstevel@tonic-gate done: 6337c478bd9Sstevel@tonic-gate return (fd); 6347c478bd9Sstevel@tonic-gate } 6357c478bd9Sstevel@tonic-gate 6367c478bd9Sstevel@tonic-gate 6377c478bd9Sstevel@tonic-gate /* 6387c478bd9Sstevel@tonic-gate * Set or remove read or write lock on keystore description file 6397c478bd9Sstevel@tonic-gate * 6407c478bd9Sstevel@tonic-gate * read_lock: true for read lock, false for write lock 6417c478bd9Sstevel@tonic-gate * set_lock: true for set a lock, false to remove a lock 6427c478bd9Sstevel@tonic-gate */ 6437c478bd9Sstevel@tonic-gate static int 6447c478bd9Sstevel@tonic-gate lock_desc_file(boolean_t read_lock, boolean_t set_lock) 6457c478bd9Sstevel@tonic-gate { 6467c478bd9Sstevel@tonic-gate 6477c478bd9Sstevel@tonic-gate char ks_desc_file[MAXPATHLEN]; 6487c478bd9Sstevel@tonic-gate 6497c478bd9Sstevel@tonic-gate if (set_lock) { 6507c478bd9Sstevel@tonic-gate int oflag; 6517c478bd9Sstevel@tonic-gate 6527c478bd9Sstevel@tonic-gate /* 6537c478bd9Sstevel@tonic-gate * make sure desc_fd is not already used. If used, it means 6547c478bd9Sstevel@tonic-gate * some other lock is already set on the file 6557c478bd9Sstevel@tonic-gate */ 6567c478bd9Sstevel@tonic-gate if (desc_fd > 0) { 6577c478bd9Sstevel@tonic-gate return (-1); 6587c478bd9Sstevel@tonic-gate } 6597c478bd9Sstevel@tonic-gate 6607c478bd9Sstevel@tonic-gate (void) get_desc_file_path(ks_desc_file); 6617c478bd9Sstevel@tonic-gate 6627c478bd9Sstevel@tonic-gate if (read_lock) { 6637c478bd9Sstevel@tonic-gate oflag = O_RDONLY; 6647c478bd9Sstevel@tonic-gate } else { 6657c478bd9Sstevel@tonic-gate oflag = O_WRONLY; 6667c478bd9Sstevel@tonic-gate } 6677c478bd9Sstevel@tonic-gate if ((desc_fd = open_and_lock_keystore_desc(oflag, 6687c478bd9Sstevel@tonic-gate B_FALSE, B_FALSE)) < 0) { 6697c478bd9Sstevel@tonic-gate return (-1); 6707c478bd9Sstevel@tonic-gate } 6717c478bd9Sstevel@tonic-gate } else { 6727c478bd9Sstevel@tonic-gate /* make sure we have a valid fd */ 6737c478bd9Sstevel@tonic-gate if (desc_fd <= 0) { 6747c478bd9Sstevel@tonic-gate return (-1); 6757c478bd9Sstevel@tonic-gate } 6767c478bd9Sstevel@tonic-gate 6777c478bd9Sstevel@tonic-gate if (lock_file(desc_fd, read_lock, B_FALSE) == 1) { 6787c478bd9Sstevel@tonic-gate return (-1); 6797c478bd9Sstevel@tonic-gate } 6807c478bd9Sstevel@tonic-gate 6817c478bd9Sstevel@tonic-gate (void) close(desc_fd); 6827c478bd9Sstevel@tonic-gate desc_fd = 0; 6837c478bd9Sstevel@tonic-gate 6847c478bd9Sstevel@tonic-gate } 6857c478bd9Sstevel@tonic-gate return (0); 6867c478bd9Sstevel@tonic-gate } 6877c478bd9Sstevel@tonic-gate 6887c478bd9Sstevel@tonic-gate static int 6897c478bd9Sstevel@tonic-gate open_and_lock_object_file(ks_obj_handle_t *ks_handle, int oflag, 6907c478bd9Sstevel@tonic-gate boolean_t lock_held) 6917c478bd9Sstevel@tonic-gate { 6927c478bd9Sstevel@tonic-gate char obj_fname[MAXPATHLEN]; 6937c478bd9Sstevel@tonic-gate int fd; 6947c478bd9Sstevel@tonic-gate 6957c478bd9Sstevel@tonic-gate if (ks_handle->public) { 6967c478bd9Sstevel@tonic-gate char pub_obj_path[MAXPATHLEN]; 6977c478bd9Sstevel@tonic-gate (void) snprintf(obj_fname, MAXPATHLEN, "%s/%s", 6987c478bd9Sstevel@tonic-gate get_pub_obj_path(pub_obj_path), ks_handle->name); 6997c478bd9Sstevel@tonic-gate } else { 7007c478bd9Sstevel@tonic-gate char pri_obj_path[MAXPATHLEN]; 7017c478bd9Sstevel@tonic-gate (void) snprintf(obj_fname, MAXPATHLEN, "%s/%s", 7027c478bd9Sstevel@tonic-gate get_pri_obj_path(pri_obj_path), ks_handle->name); 7037c478bd9Sstevel@tonic-gate } 7047c478bd9Sstevel@tonic-gate 705*19193bb6SDina K Nimeh fd = open_nointr(obj_fname, oflag|O_NONBLOCK); 7067c478bd9Sstevel@tonic-gate if (fd < 0) { 7077c478bd9Sstevel@tonic-gate return (-1); 7087c478bd9Sstevel@tonic-gate } 7097c478bd9Sstevel@tonic-gate 7107c478bd9Sstevel@tonic-gate if (lock_held) { 7117c478bd9Sstevel@tonic-gate /* already hold the lock */ 7127c478bd9Sstevel@tonic-gate return (fd); 7137c478bd9Sstevel@tonic-gate } 7147c478bd9Sstevel@tonic-gate 7157c478bd9Sstevel@tonic-gate if (acquire_file_lock(&fd, obj_fname, oflag) != 0) { 7167c478bd9Sstevel@tonic-gate if (fd > 0) { 7177c478bd9Sstevel@tonic-gate (void) close(fd); 7187c478bd9Sstevel@tonic-gate } 7197c478bd9Sstevel@tonic-gate return (-1); 7207c478bd9Sstevel@tonic-gate } 7217c478bd9Sstevel@tonic-gate 7227c478bd9Sstevel@tonic-gate 7237c478bd9Sstevel@tonic-gate return (fd); 7247c478bd9Sstevel@tonic-gate } 7257c478bd9Sstevel@tonic-gate 7267c478bd9Sstevel@tonic-gate 7277c478bd9Sstevel@tonic-gate /* 7287c478bd9Sstevel@tonic-gate * Update file version number in a temporary file that's 7297c478bd9Sstevel@tonic-gate * a copy of the keystore description file. 7307c478bd9Sstevel@tonic-gate * The update is NOT made to the original keystore description 7317c478bd9Sstevel@tonic-gate * file. It makes the update in a tempoary file. 7327c478bd9Sstevel@tonic-gate * 7337c478bd9Sstevel@tonic-gate * Name of the temporary file is assumed to be provided, but 7347c478bd9Sstevel@tonic-gate * the file is assumed to not exist. 7357c478bd9Sstevel@tonic-gate * 7367c478bd9Sstevel@tonic-gate * return 0 if creating temp file is successful, returns -1 otherwise 7377c478bd9Sstevel@tonic-gate */ 7387c478bd9Sstevel@tonic-gate static int 7397c478bd9Sstevel@tonic-gate create_updated_keystore_version(int fd, char *tmp_fname) 7407c478bd9Sstevel@tonic-gate { 7417c478bd9Sstevel@tonic-gate int version, tmp_fd; 7427c478bd9Sstevel@tonic-gate char buf[BUFSIZ]; 7437c478bd9Sstevel@tonic-gate size_t nread; 7447c478bd9Sstevel@tonic-gate 7457c478bd9Sstevel@tonic-gate /* first, create the tempoary file */ 746*19193bb6SDina K Nimeh tmp_fd = open_nointr(tmp_fname, 747*19193bb6SDina K Nimeh O_WRONLY|O_CREAT|O_EXCL|O_NONBLOCK, S_IRUSR|S_IWUSR); 7487c478bd9Sstevel@tonic-gate if (tmp_fd < 0) { 7497c478bd9Sstevel@tonic-gate return (-1); 7507c478bd9Sstevel@tonic-gate } 7517c478bd9Sstevel@tonic-gate 7527c478bd9Sstevel@tonic-gate /* 7537c478bd9Sstevel@tonic-gate * copy everything from keystore version to temp file except 7547c478bd9Sstevel@tonic-gate * the keystore version. Keystore version is updated 7557c478bd9Sstevel@tonic-gate * 7567c478bd9Sstevel@tonic-gate */ 7577c478bd9Sstevel@tonic-gate 7587c478bd9Sstevel@tonic-gate /* pkcs11 version */ 759*19193bb6SDina K Nimeh if (readn_nointr(fd, buf, KS_PKCS11_VER_SIZE) != KS_PKCS11_VER_SIZE) { 7607c478bd9Sstevel@tonic-gate goto cleanup; 7617c478bd9Sstevel@tonic-gate } 7627c478bd9Sstevel@tonic-gate 763*19193bb6SDina K Nimeh if (writen_nointr(tmp_fd, buf, KS_PKCS11_VER_SIZE) != 764*19193bb6SDina K Nimeh KS_PKCS11_VER_SIZE) { 7657c478bd9Sstevel@tonic-gate goto cleanup; 7667c478bd9Sstevel@tonic-gate } 7677c478bd9Sstevel@tonic-gate 7687c478bd9Sstevel@tonic-gate /* version number, it needs to be updated */ 7697c478bd9Sstevel@tonic-gate 7707c478bd9Sstevel@tonic-gate /* read the current version number */ 771*19193bb6SDina K Nimeh if (readn_nointr(fd, &version, KS_VER_SIZE) != KS_VER_SIZE) { 7727c478bd9Sstevel@tonic-gate goto cleanup; 7737c478bd9Sstevel@tonic-gate } 7747c478bd9Sstevel@tonic-gate 7757c478bd9Sstevel@tonic-gate version = SWAP32(version); 7767c478bd9Sstevel@tonic-gate version++; 7777c478bd9Sstevel@tonic-gate version = SWAP32(version); 7787c478bd9Sstevel@tonic-gate 7797c478bd9Sstevel@tonic-gate /* write the updated value to the tmp file */ 780*19193bb6SDina K Nimeh if (writen_nointr(tmp_fd, (void *)&version, KS_VER_SIZE) 7817c478bd9Sstevel@tonic-gate != KS_VER_SIZE) { 7827c478bd9Sstevel@tonic-gate goto cleanup; 7837c478bd9Sstevel@tonic-gate } 7847c478bd9Sstevel@tonic-gate 7857c478bd9Sstevel@tonic-gate /* read rest of information, nothing needs to be updated */ 786*19193bb6SDina K Nimeh nread = readn_nointr(fd, buf, BUFSIZ); 7877c478bd9Sstevel@tonic-gate while (nread > 0) { 788*19193bb6SDina K Nimeh if (writen_nointr(tmp_fd, buf, nread) != nread) { 7897c478bd9Sstevel@tonic-gate goto cleanup; 7907c478bd9Sstevel@tonic-gate } 791*19193bb6SDina K Nimeh nread = readn_nointr(fd, buf, BUFSIZ); 7927c478bd9Sstevel@tonic-gate } 7937c478bd9Sstevel@tonic-gate 7947c478bd9Sstevel@tonic-gate (void) close(tmp_fd); 7957c478bd9Sstevel@tonic-gate return (0); /* no error */ 7967c478bd9Sstevel@tonic-gate 7977c478bd9Sstevel@tonic-gate cleanup: 7987c478bd9Sstevel@tonic-gate (void) close(tmp_fd); 7997c478bd9Sstevel@tonic-gate (void) remove(tmp_fname); 8007c478bd9Sstevel@tonic-gate return (-1); 8017c478bd9Sstevel@tonic-gate } 8027c478bd9Sstevel@tonic-gate 8037c478bd9Sstevel@tonic-gate static CK_RV 8047c478bd9Sstevel@tonic-gate get_all_objs_in_dir(DIR *dirp, ks_obj_handle_t *ks_handle, 8054bc0a2efScasper ks_obj_t **result_obj_list, boolean_t lock_held) 8067c478bd9Sstevel@tonic-gate { 8074bc0a2efScasper struct dirent *dp; 8087c478bd9Sstevel@tonic-gate ks_obj_t *obj; 8097c478bd9Sstevel@tonic-gate CK_RV rv; 8107c478bd9Sstevel@tonic-gate 8114bc0a2efScasper while ((dp = readdir(dirp)) != NULL) { 8127c478bd9Sstevel@tonic-gate 8137c478bd9Sstevel@tonic-gate if ((strcmp(dp->d_name, ".") == 0) || 8147c478bd9Sstevel@tonic-gate (strcmp(dp->d_name, "..") == 0)) { 8157c478bd9Sstevel@tonic-gate continue; 8167c478bd9Sstevel@tonic-gate } 8177c478bd9Sstevel@tonic-gate 8187c478bd9Sstevel@tonic-gate (void) strcpy((char *)ks_handle->name, dp->d_name); 8197c478bd9Sstevel@tonic-gate rv = soft_keystore_get_single_obj(ks_handle, &obj, lock_held); 8207c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 8217c478bd9Sstevel@tonic-gate return (rv); 8227c478bd9Sstevel@tonic-gate } 8237c478bd9Sstevel@tonic-gate if (obj != NULL) { 8247c478bd9Sstevel@tonic-gate if (*result_obj_list == NULL) { 8257c478bd9Sstevel@tonic-gate *result_obj_list = obj; 8267c478bd9Sstevel@tonic-gate } else { 8277c478bd9Sstevel@tonic-gate obj->next = *result_obj_list; 8287c478bd9Sstevel@tonic-gate *result_obj_list = obj; 8297c478bd9Sstevel@tonic-gate } 8307c478bd9Sstevel@tonic-gate } 8317c478bd9Sstevel@tonic-gate } 8327c478bd9Sstevel@tonic-gate return (CKR_OK); 8337c478bd9Sstevel@tonic-gate } 8347c478bd9Sstevel@tonic-gate 8357c478bd9Sstevel@tonic-gate /* 8367c478bd9Sstevel@tonic-gate * This function prepares the obj data for encryption by prepending 8377c478bd9Sstevel@tonic-gate * the FULL path of the file that will be used for storing 8387c478bd9Sstevel@tonic-gate * the object. Having full path of the file as part of 8397c478bd9Sstevel@tonic-gate * of the data for the object will prevent an attacker from 8407c478bd9Sstevel@tonic-gate * copying a "bad" object into the keystore undetected. 8417c478bd9Sstevel@tonic-gate * 8427c478bd9Sstevel@tonic-gate * This function will always allocate: 8437c478bd9Sstevel@tonic-gate * MAXPATHLEN + buf_len 8447c478bd9Sstevel@tonic-gate * amount of data. If the full path of the filename doesn't occupy 8457c478bd9Sstevel@tonic-gate * the whole MAXPATHLEN, the rest of the space will just be empty. 8467c478bd9Sstevel@tonic-gate * It is the caller's responsibility to free the buffer allocated here. 8477c478bd9Sstevel@tonic-gate * 8487c478bd9Sstevel@tonic-gate * The allocated buffer is returned in the variable "prepared_buf" 8497c478bd9Sstevel@tonic-gate * if there's no error. 8507c478bd9Sstevel@tonic-gate * 8517c478bd9Sstevel@tonic-gate * Returns 0 if there's no error, -1 otherwise. 8527c478bd9Sstevel@tonic-gate */ 8537c478bd9Sstevel@tonic-gate static int 8547c478bd9Sstevel@tonic-gate prepare_data_for_encrypt(char *obj_path, unsigned char *buf, CK_ULONG buf_len, 8557c478bd9Sstevel@tonic-gate unsigned char **prepared_buf, CK_ULONG *prepared_len) 8567c478bd9Sstevel@tonic-gate { 8577c478bd9Sstevel@tonic-gate *prepared_len = MAXPATHLEN + buf_len; 8587c478bd9Sstevel@tonic-gate *prepared_buf = malloc(*prepared_len); 8597c478bd9Sstevel@tonic-gate if (*prepared_buf == NULL) { 8607c478bd9Sstevel@tonic-gate return (-1); 8617c478bd9Sstevel@tonic-gate } 8627c478bd9Sstevel@tonic-gate 8637c478bd9Sstevel@tonic-gate /* 8647c478bd9Sstevel@tonic-gate * only zero out the space for the path name. I could zero out 8657c478bd9Sstevel@tonic-gate * the whole buffer, but that will be a waste of processing 8667c478bd9Sstevel@tonic-gate * cycle since the rest of the buffer will be 100% filled all 8677c478bd9Sstevel@tonic-gate * the time 8687c478bd9Sstevel@tonic-gate */ 8697c478bd9Sstevel@tonic-gate bzero(*prepared_buf, MAXPATHLEN); 8707c478bd9Sstevel@tonic-gate (void) memcpy(*prepared_buf, obj_path, strlen(obj_path)); 8717c478bd9Sstevel@tonic-gate (void) memcpy(*prepared_buf + MAXPATHLEN, buf, buf_len); 8727c478bd9Sstevel@tonic-gate return (0); 8737c478bd9Sstevel@tonic-gate } 8747c478bd9Sstevel@tonic-gate 8757c478bd9Sstevel@tonic-gate /* 8767c478bd9Sstevel@tonic-gate * retrieves the hashed pin from the keystore 8777c478bd9Sstevel@tonic-gate */ 8787c478bd9Sstevel@tonic-gate static CK_RV 8797c478bd9Sstevel@tonic-gate get_hashed_pin(int fd, char **hashed_pin) 8807c478bd9Sstevel@tonic-gate { 8817c478bd9Sstevel@tonic-gate uint64_t hashed_pin_size; 8827c478bd9Sstevel@tonic-gate 8837c478bd9Sstevel@tonic-gate if (ks_hashed_pinlen_offset == -1) { 8847c478bd9Sstevel@tonic-gate if (calculate_hashed_pin_offset(fd) != 0) { 8857c478bd9Sstevel@tonic-gate return (CKR_FUNCTION_FAILED); 8867c478bd9Sstevel@tonic-gate } 8877c478bd9Sstevel@tonic-gate } 8887c478bd9Sstevel@tonic-gate 8897c478bd9Sstevel@tonic-gate /* first, get size of the hashed pin */ 8907c478bd9Sstevel@tonic-gate if (lseek(fd, ks_hashed_pinlen_offset, SEEK_SET) 8917c478bd9Sstevel@tonic-gate != ks_hashed_pinlen_offset) { 8927c478bd9Sstevel@tonic-gate return (CKR_FUNCTION_FAILED); 8937c478bd9Sstevel@tonic-gate } 8947c478bd9Sstevel@tonic-gate 895*19193bb6SDina K Nimeh if (readn_nointr(fd, (char *)&hashed_pin_size, 8967c478bd9Sstevel@tonic-gate KS_HASHED_PINLEN_SIZE) != KS_HASHED_PINLEN_SIZE) { 8977c478bd9Sstevel@tonic-gate return (CKR_FUNCTION_FAILED); 8987c478bd9Sstevel@tonic-gate } 8997c478bd9Sstevel@tonic-gate 9007c478bd9Sstevel@tonic-gate hashed_pin_size = SWAP64(hashed_pin_size); 9017c478bd9Sstevel@tonic-gate 9027c478bd9Sstevel@tonic-gate *hashed_pin = malloc(hashed_pin_size + 1); 9037c478bd9Sstevel@tonic-gate if (*hashed_pin == NULL) { 9047c478bd9Sstevel@tonic-gate return (CKR_HOST_MEMORY); 9057c478bd9Sstevel@tonic-gate } 9067c478bd9Sstevel@tonic-gate 907*19193bb6SDina K Nimeh if ((readn_nointr(fd, *hashed_pin, hashed_pin_size)) 9087c478bd9Sstevel@tonic-gate != (ssize_t)hashed_pin_size) { 9097c478bd9Sstevel@tonic-gate free(*hashed_pin); 9107c478bd9Sstevel@tonic-gate *hashed_pin = NULL; 9117c478bd9Sstevel@tonic-gate return (CKR_FUNCTION_FAILED); 9127c478bd9Sstevel@tonic-gate } 9137c478bd9Sstevel@tonic-gate (*hashed_pin)[hashed_pin_size] = '\0'; 9147c478bd9Sstevel@tonic-gate return (CKR_OK); 9157c478bd9Sstevel@tonic-gate } 9167c478bd9Sstevel@tonic-gate 9177c478bd9Sstevel@tonic-gate 9187c478bd9Sstevel@tonic-gate /* 9197c478bd9Sstevel@tonic-gate * FUNCTION: soft_keystore_lock 9207c478bd9Sstevel@tonic-gate * 9217c478bd9Sstevel@tonic-gate * ARGUMENTS: 9227c478bd9Sstevel@tonic-gate * set_lock: TRUE to set readlock on the keystore object file, 9237c478bd9Sstevel@tonic-gate * FALSE to remove readlock on keystore object file. 9247c478bd9Sstevel@tonic-gate * 9257c478bd9Sstevel@tonic-gate * RETURN VALUE: 9267c478bd9Sstevel@tonic-gate * 9277c478bd9Sstevel@tonic-gate * 0: success 9287c478bd9Sstevel@tonic-gate * -1: failure 9297c478bd9Sstevel@tonic-gate * 9307c478bd9Sstevel@tonic-gate * DESCRIPTION: 9317c478bd9Sstevel@tonic-gate * 9327c478bd9Sstevel@tonic-gate * set or remove readlock on the keystore description file. 9337c478bd9Sstevel@tonic-gate */ 9347c478bd9Sstevel@tonic-gate int 9357c478bd9Sstevel@tonic-gate soft_keystore_readlock(boolean_t set_lock) 9367c478bd9Sstevel@tonic-gate { 9377c478bd9Sstevel@tonic-gate 9387c478bd9Sstevel@tonic-gate return (lock_desc_file(B_TRUE, set_lock)); 9397c478bd9Sstevel@tonic-gate } 9407c478bd9Sstevel@tonic-gate 9417c478bd9Sstevel@tonic-gate 9427c478bd9Sstevel@tonic-gate /* 9437c478bd9Sstevel@tonic-gate * FUNCTION: soft_keystore_writelock 9447c478bd9Sstevel@tonic-gate * 9457c478bd9Sstevel@tonic-gate * ARGUMENTS: 9467c478bd9Sstevel@tonic-gate * set_lock: TRUE to set writelock on the keystore description file 9477c478bd9Sstevel@tonic-gate * FALSE to remove write lock on keystore description file. 9487c478bd9Sstevel@tonic-gate * 9497c478bd9Sstevel@tonic-gate * RETURN VALUE: 9507c478bd9Sstevel@tonic-gate * 9517c478bd9Sstevel@tonic-gate * 0: no error 9527c478bd9Sstevel@tonic-gate * 1: some error occurred 9537c478bd9Sstevel@tonic-gate * 9547c478bd9Sstevel@tonic-gate * DESCRIPTION: 9557c478bd9Sstevel@tonic-gate * set/reset writelock on the keystore description file. 9567c478bd9Sstevel@tonic-gate */ 9577c478bd9Sstevel@tonic-gate int 9587c478bd9Sstevel@tonic-gate soft_keystore_writelock(boolean_t set_lock) 9597c478bd9Sstevel@tonic-gate { 9607c478bd9Sstevel@tonic-gate return (lock_desc_file(B_FALSE, set_lock)); 9617c478bd9Sstevel@tonic-gate 9627c478bd9Sstevel@tonic-gate } 9637c478bd9Sstevel@tonic-gate 9647c478bd9Sstevel@tonic-gate /* 9657c478bd9Sstevel@tonic-gate * 9667c478bd9Sstevel@tonic-gate * FUNCTION: soft_keystore_lock_object 9677c478bd9Sstevel@tonic-gate * 9687c478bd9Sstevel@tonic-gate * ARGUMENTS: 9697c478bd9Sstevel@tonic-gate * 9707c478bd9Sstevel@tonic-gate * ks_handle: handle of the keystore object file to be accessed. 9717c478bd9Sstevel@tonic-gate * read_lock: TRUE to set readlock on the keystore object file, 9727c478bd9Sstevel@tonic-gate * FALSE to set writelock on keystore object file. 9737c478bd9Sstevel@tonic-gate * 9747c478bd9Sstevel@tonic-gate * RETURN VALUE: 9757c478bd9Sstevel@tonic-gate * 9767c478bd9Sstevel@tonic-gate * If no error, file descriptor of locked file will be returned 9777c478bd9Sstevel@tonic-gate * -1: some error occurred 9787c478bd9Sstevel@tonic-gate * 9797c478bd9Sstevel@tonic-gate * DESCRIPTION: 9807c478bd9Sstevel@tonic-gate * 9817c478bd9Sstevel@tonic-gate * set readlock or writelock on the keystore object file. 9827c478bd9Sstevel@tonic-gate */ 9837c478bd9Sstevel@tonic-gate int 9847c478bd9Sstevel@tonic-gate soft_keystore_lock_object(ks_obj_handle_t *ks_handle, boolean_t read_lock) 9857c478bd9Sstevel@tonic-gate { 9867c478bd9Sstevel@tonic-gate int fd; 9877c478bd9Sstevel@tonic-gate int oflag; 9887c478bd9Sstevel@tonic-gate 9897c478bd9Sstevel@tonic-gate if (read_lock) { 9907c478bd9Sstevel@tonic-gate oflag = O_RDONLY; 9917c478bd9Sstevel@tonic-gate } else { 9927c478bd9Sstevel@tonic-gate oflag = O_WRONLY; 9937c478bd9Sstevel@tonic-gate } 9947c478bd9Sstevel@tonic-gate 9957c478bd9Sstevel@tonic-gate if ((fd = open_and_lock_object_file(ks_handle, oflag, B_FALSE)) < 0) { 9967c478bd9Sstevel@tonic-gate return (-1); 9977c478bd9Sstevel@tonic-gate } 9987c478bd9Sstevel@tonic-gate 9997c478bd9Sstevel@tonic-gate return (fd); 10007c478bd9Sstevel@tonic-gate } 10017c478bd9Sstevel@tonic-gate 10027c478bd9Sstevel@tonic-gate /* 10037c478bd9Sstevel@tonic-gate * FUNCTION: soft_keystore_unlock_object 10047c478bd9Sstevel@tonic-gate * 10057c478bd9Sstevel@tonic-gate * ARGUMENTS: 10067c478bd9Sstevel@tonic-gate * fd: file descriptor returned from soft_keystore_lock_object 10077c478bd9Sstevel@tonic-gate * 10087c478bd9Sstevel@tonic-gate * RETURN VALUE: 10097c478bd9Sstevel@tonic-gate * 0: no error 10107c478bd9Sstevel@tonic-gate * 1: some error occurred while getting the pin 10117c478bd9Sstevel@tonic-gate * 10127c478bd9Sstevel@tonic-gate * DESCRIPTION: 10137c478bd9Sstevel@tonic-gate * set/reset writelock on the keystore object file. 10147c478bd9Sstevel@tonic-gate */ 10157c478bd9Sstevel@tonic-gate int 10167c478bd9Sstevel@tonic-gate soft_keystore_unlock_object(int fd) 10177c478bd9Sstevel@tonic-gate { 10187c478bd9Sstevel@tonic-gate if (lock_file(fd, B_TRUE, B_FALSE) != 0) { 10197c478bd9Sstevel@tonic-gate return (1); 10207c478bd9Sstevel@tonic-gate } 10217c478bd9Sstevel@tonic-gate 10227c478bd9Sstevel@tonic-gate (void) close(fd); 10237c478bd9Sstevel@tonic-gate return (0); 10247c478bd9Sstevel@tonic-gate } 10257c478bd9Sstevel@tonic-gate 10267c478bd9Sstevel@tonic-gate 10277c478bd9Sstevel@tonic-gate 10287c478bd9Sstevel@tonic-gate /* 10297c478bd9Sstevel@tonic-gate * FUNCTION: soft_keystore_get_version 10307c478bd9Sstevel@tonic-gate * 10317c478bd9Sstevel@tonic-gate * ARGUMENTS: 10327c478bd9Sstevel@tonic-gate * version: pointer to caller allocated memory for storing 10337c478bd9Sstevel@tonic-gate * the version of the keystore. 10347c478bd9Sstevel@tonic-gate * lock_held: TRUE if the lock is held by caller. 10357c478bd9Sstevel@tonic-gate * 10367c478bd9Sstevel@tonic-gate * RETURN VALUE: 10377c478bd9Sstevel@tonic-gate * 10387c478bd9Sstevel@tonic-gate * 0: no error 10397c478bd9Sstevel@tonic-gate * -1: some error occurred while getting the version number 10407c478bd9Sstevel@tonic-gate * 10417c478bd9Sstevel@tonic-gate * DESCRIPTION: 10427c478bd9Sstevel@tonic-gate * get the version number of the keystore from keystore 10437c478bd9Sstevel@tonic-gate * description file. 10447c478bd9Sstevel@tonic-gate */ 10457c478bd9Sstevel@tonic-gate int 10467c478bd9Sstevel@tonic-gate soft_keystore_get_version(uint_t *version, boolean_t lock_held) 10477c478bd9Sstevel@tonic-gate { 10487c478bd9Sstevel@tonic-gate int fd, ret_val = 0; 10497c478bd9Sstevel@tonic-gate uint_t buf; 10507c478bd9Sstevel@tonic-gate 10517c478bd9Sstevel@tonic-gate if ((fd = open_and_lock_keystore_desc(O_RDONLY, 10527c478bd9Sstevel@tonic-gate B_TRUE, lock_held)) < 0) { 10537c478bd9Sstevel@tonic-gate return (-1); 10547c478bd9Sstevel@tonic-gate } 10557c478bd9Sstevel@tonic-gate 10567c478bd9Sstevel@tonic-gate if (lseek(fd, KS_VER_OFFSET, SEEK_SET) != KS_VER_OFFSET) { 10577c478bd9Sstevel@tonic-gate ret_val = -1; 10587c478bd9Sstevel@tonic-gate goto cleanup; 10597c478bd9Sstevel@tonic-gate } 10607c478bd9Sstevel@tonic-gate 1061*19193bb6SDina K Nimeh if (readn_nointr(fd, (char *)&buf, KS_VER_SIZE) != KS_VER_SIZE) { 10627c478bd9Sstevel@tonic-gate ret_val = -1; 10637c478bd9Sstevel@tonic-gate goto cleanup; 10647c478bd9Sstevel@tonic-gate } 10657c478bd9Sstevel@tonic-gate *version = SWAP32(buf); 10667c478bd9Sstevel@tonic-gate 10677c478bd9Sstevel@tonic-gate cleanup: 10687c478bd9Sstevel@tonic-gate 10697c478bd9Sstevel@tonic-gate if (!lock_held) { 10707c478bd9Sstevel@tonic-gate if (lock_file(fd, B_TRUE, B_FALSE) < 0) { 10717c478bd9Sstevel@tonic-gate ret_val = -1; 10727c478bd9Sstevel@tonic-gate } 10737c478bd9Sstevel@tonic-gate } 10747c478bd9Sstevel@tonic-gate 10757c478bd9Sstevel@tonic-gate (void) close(fd); 10767c478bd9Sstevel@tonic-gate return (ret_val); 10777c478bd9Sstevel@tonic-gate } 10787c478bd9Sstevel@tonic-gate 10797c478bd9Sstevel@tonic-gate /* 10807c478bd9Sstevel@tonic-gate * FUNCTION: soft_keystore_get_object_version 10817c478bd9Sstevel@tonic-gate * 10827c478bd9Sstevel@tonic-gate * ARGUMENTS: 10837c478bd9Sstevel@tonic-gate * 10847c478bd9Sstevel@tonic-gate * ks_handle: handle of the key store object to be accessed. 10857c478bd9Sstevel@tonic-gate * version: 10867c478bd9Sstevel@tonic-gate * pointer to caller allocated memory for storing 10877c478bd9Sstevel@tonic-gate * the version of the object. 10887c478bd9Sstevel@tonic-gate * lock_held: TRUE if the lock is held by caller. 10897c478bd9Sstevel@tonic-gate * 10907c478bd9Sstevel@tonic-gate * RETURN VALUE: 10917c478bd9Sstevel@tonic-gate * 10927c478bd9Sstevel@tonic-gate * 0: no error 10937c478bd9Sstevel@tonic-gate * -1: some error occurred while getting the pin 10947c478bd9Sstevel@tonic-gate * 10957c478bd9Sstevel@tonic-gate * DESCRIPTION: 10967c478bd9Sstevel@tonic-gate * get the version number of the specified token object. 10977c478bd9Sstevel@tonic-gate */ 10987c478bd9Sstevel@tonic-gate int 10997c478bd9Sstevel@tonic-gate soft_keystore_get_object_version(ks_obj_handle_t *ks_handle, 11007c478bd9Sstevel@tonic-gate uint_t *version, boolean_t lock_held) 11017c478bd9Sstevel@tonic-gate { 11027c478bd9Sstevel@tonic-gate int fd, ret_val = 0; 11037c478bd9Sstevel@tonic-gate uint_t tmp; 11047c478bd9Sstevel@tonic-gate 11057c478bd9Sstevel@tonic-gate if ((fd = open_and_lock_object_file(ks_handle, O_RDONLY, 11067c478bd9Sstevel@tonic-gate lock_held)) < 0) { 11077c478bd9Sstevel@tonic-gate return (-1); 11087c478bd9Sstevel@tonic-gate } 11097c478bd9Sstevel@tonic-gate 11107c478bd9Sstevel@tonic-gate /* 11117c478bd9Sstevel@tonic-gate * read version. Version is always first item in object file 11127c478bd9Sstevel@tonic-gate * so, no need to do lseek 11137c478bd9Sstevel@tonic-gate */ 1114*19193bb6SDina K Nimeh if (readn_nointr(fd, (char *)&tmp, OBJ_VER_SIZE) != OBJ_VER_SIZE) { 11157c478bd9Sstevel@tonic-gate ret_val = -1; 11167c478bd9Sstevel@tonic-gate goto cleanup; 11177c478bd9Sstevel@tonic-gate } 11187c478bd9Sstevel@tonic-gate 11197c478bd9Sstevel@tonic-gate *version = SWAP32(tmp); 11207c478bd9Sstevel@tonic-gate 11217c478bd9Sstevel@tonic-gate cleanup: 11227c478bd9Sstevel@tonic-gate if (!lock_held) { 11237c478bd9Sstevel@tonic-gate if (lock_file(fd, B_TRUE, B_FALSE) < 0) { 11247c478bd9Sstevel@tonic-gate ret_val = -1; 11257c478bd9Sstevel@tonic-gate } 11267c478bd9Sstevel@tonic-gate } 11277c478bd9Sstevel@tonic-gate 11287c478bd9Sstevel@tonic-gate 11297c478bd9Sstevel@tonic-gate (void) close(fd); 11307c478bd9Sstevel@tonic-gate return (ret_val); 11317c478bd9Sstevel@tonic-gate } 11327c478bd9Sstevel@tonic-gate 11337c478bd9Sstevel@tonic-gate /* 11347c478bd9Sstevel@tonic-gate * FUNCTION: soft_keystore_getpin 11357c478bd9Sstevel@tonic-gate * 11367c478bd9Sstevel@tonic-gate * ARGUMENTS: 11377c478bd9Sstevel@tonic-gate * hashed_pin: pointer to caller allocated memory 11387c478bd9Sstevel@tonic-gate * for storing the pin to be returned. 11397c478bd9Sstevel@tonic-gate * lock_held: TRUE if the lock is held by caller. 11407c478bd9Sstevel@tonic-gate * 11417c478bd9Sstevel@tonic-gate * RETURN VALUE: 11427c478bd9Sstevel@tonic-gate * 11437c478bd9Sstevel@tonic-gate * 0: no error 11447c478bd9Sstevel@tonic-gate * -1: some error occurred while getting the pin 11457c478bd9Sstevel@tonic-gate * 11467c478bd9Sstevel@tonic-gate * DESCRIPTION: 11477c478bd9Sstevel@tonic-gate * 11487c478bd9Sstevel@tonic-gate * Reads the MD5 hash from the keystore description 11497c478bd9Sstevel@tonic-gate * file and return it to the caller in the provided 11507c478bd9Sstevel@tonic-gate * buffer. If there is no PIN in the description file 11517c478bd9Sstevel@tonic-gate * because the file is just created, this function 11527c478bd9Sstevel@tonic-gate * will get a MD5 digest of the string "changeme", 11537c478bd9Sstevel@tonic-gate * store it in the file, and also return this 11547c478bd9Sstevel@tonic-gate * string to the caller. 11557c478bd9Sstevel@tonic-gate */ 11567c478bd9Sstevel@tonic-gate int 11577c478bd9Sstevel@tonic-gate soft_keystore_getpin(char **hashed_pin, boolean_t lock_held) 11587c478bd9Sstevel@tonic-gate { 11597c478bd9Sstevel@tonic-gate int fd, ret_val = -1; 11607c478bd9Sstevel@tonic-gate CK_RV rv; 11617c478bd9Sstevel@tonic-gate 11627c478bd9Sstevel@tonic-gate if ((fd = open_and_lock_keystore_desc(O_RDONLY, B_TRUE, 11637c478bd9Sstevel@tonic-gate lock_held)) < 0) { 11647c478bd9Sstevel@tonic-gate return (-1); 11657c478bd9Sstevel@tonic-gate } 11667c478bd9Sstevel@tonic-gate 11677c478bd9Sstevel@tonic-gate rv = get_hashed_pin(fd, hashed_pin); 11687c478bd9Sstevel@tonic-gate if (rv == CKR_OK) { 11697c478bd9Sstevel@tonic-gate ret_val = 0; 11707c478bd9Sstevel@tonic-gate } 11717c478bd9Sstevel@tonic-gate 11727c478bd9Sstevel@tonic-gate cleanup: 11737c478bd9Sstevel@tonic-gate if (!lock_held) { 11747c478bd9Sstevel@tonic-gate if (lock_file(fd, B_TRUE, B_FALSE) < 0) { 11757c478bd9Sstevel@tonic-gate ret_val = -1; 11767c478bd9Sstevel@tonic-gate } 11777c478bd9Sstevel@tonic-gate } 11787c478bd9Sstevel@tonic-gate 11797c478bd9Sstevel@tonic-gate (void) close(fd); 11807c478bd9Sstevel@tonic-gate return (ret_val); 11817c478bd9Sstevel@tonic-gate } 11827c478bd9Sstevel@tonic-gate 11837c478bd9Sstevel@tonic-gate /* 11847c478bd9Sstevel@tonic-gate * This function reads all the data until the end of the file, and 11857c478bd9Sstevel@tonic-gate * put the data into the "buf" in argument. Memory for buf will 11867c478bd9Sstevel@tonic-gate * be allocated in this function. It is the caller's responsibility 11877c478bd9Sstevel@tonic-gate * to free it. The number of bytes read will be returned 11887c478bd9Sstevel@tonic-gate * in the argument "bytes_read" 11897c478bd9Sstevel@tonic-gate * 11907c478bd9Sstevel@tonic-gate * returns CKR_OK if no error. Other CKR error codes if there's an error 11917c478bd9Sstevel@tonic-gate */ 11927c478bd9Sstevel@tonic-gate static CK_RV 11937c478bd9Sstevel@tonic-gate read_obj_data(int old_fd, char **buf, ssize_t *bytes_read) 11947c478bd9Sstevel@tonic-gate { 11957c478bd9Sstevel@tonic-gate 11967c478bd9Sstevel@tonic-gate ssize_t nread, loop_count; 11977c478bd9Sstevel@tonic-gate char *buf1 = NULL; 11987c478bd9Sstevel@tonic-gate 11997c478bd9Sstevel@tonic-gate *buf = malloc(BUFSIZ); 12007c478bd9Sstevel@tonic-gate if (*buf == NULL) { 12017c478bd9Sstevel@tonic-gate return (CKR_HOST_MEMORY); 12027c478bd9Sstevel@tonic-gate } 12037c478bd9Sstevel@tonic-gate 1204*19193bb6SDina K Nimeh nread = readn_nointr(old_fd, *buf, BUFSIZ); 12057c478bd9Sstevel@tonic-gate if (nread < 0) { 12067c478bd9Sstevel@tonic-gate free(*buf); 12077c478bd9Sstevel@tonic-gate return (CKR_FUNCTION_FAILED); 12087c478bd9Sstevel@tonic-gate } 12097c478bd9Sstevel@tonic-gate loop_count = 1; 12107c478bd9Sstevel@tonic-gate while (nread == (loop_count * BUFSIZ)) { 12117c478bd9Sstevel@tonic-gate ssize_t nread_tmp; 12127c478bd9Sstevel@tonic-gate 12137c478bd9Sstevel@tonic-gate loop_count++; 12147c478bd9Sstevel@tonic-gate /* more than BUFSIZ of data */ 12157c478bd9Sstevel@tonic-gate buf1 = realloc(*buf, loop_count * BUFSIZ); 12167c478bd9Sstevel@tonic-gate if (buf1 == NULL) { 12177c478bd9Sstevel@tonic-gate free(*buf); 12187c478bd9Sstevel@tonic-gate return (CKR_HOST_MEMORY); 12197c478bd9Sstevel@tonic-gate } 12207c478bd9Sstevel@tonic-gate *buf = buf1; 1221*19193bb6SDina K Nimeh nread_tmp = readn_nointr(old_fd, 12227c478bd9Sstevel@tonic-gate *buf + ((loop_count - 1) * BUFSIZ), BUFSIZ); 12237c478bd9Sstevel@tonic-gate if (nread_tmp < 0) { 12247c478bd9Sstevel@tonic-gate free(*buf); 12257c478bd9Sstevel@tonic-gate return (CKR_FUNCTION_FAILED); 12267c478bd9Sstevel@tonic-gate } 12277c478bd9Sstevel@tonic-gate nread += nread_tmp; 12287c478bd9Sstevel@tonic-gate } 12297c478bd9Sstevel@tonic-gate *bytes_read = nread; 12307c478bd9Sstevel@tonic-gate return (CKR_OK); 12317c478bd9Sstevel@tonic-gate } 12327c478bd9Sstevel@tonic-gate 12337c478bd9Sstevel@tonic-gate /* 12347c478bd9Sstevel@tonic-gate * Re-encrypt an object using the provided new_enc_key. The new HMAC 12357c478bd9Sstevel@tonic-gate * is calculated using the new_hmac_key. The global static variables 12367c478bd9Sstevel@tonic-gate * enc_key, and hmac_key will be used for decrypting the original 12377c478bd9Sstevel@tonic-gate * object, and verifying its signature. 12387c478bd9Sstevel@tonic-gate * 12397c478bd9Sstevel@tonic-gate * The re-encrypted object will be stored in the file named 12407c478bd9Sstevel@tonic-gate * in the "new_obj_name" variable. The content of the "original" 12417c478bd9Sstevel@tonic-gate * file named in "orig_obj_name" is not disturbed. 12427c478bd9Sstevel@tonic-gate * 12437c478bd9Sstevel@tonic-gate * Returns 0 if there's no error, returns -1 otherwise. 12447c478bd9Sstevel@tonic-gate * 12457c478bd9Sstevel@tonic-gate */ 12467c478bd9Sstevel@tonic-gate static int 12477c478bd9Sstevel@tonic-gate reencrypt_obj(soft_object_t *new_enc_key, soft_object_t *new_hmac_key, 12487c478bd9Sstevel@tonic-gate char *orig_obj_name, char *new_obj_name) { 12497c478bd9Sstevel@tonic-gate 12507c478bd9Sstevel@tonic-gate int old_fd, new_fd, version, ret_val = -1; 12517c478bd9Sstevel@tonic-gate CK_BYTE iv[OBJ_IV_SIZE], old_iv[OBJ_IV_SIZE]; 12527c478bd9Sstevel@tonic-gate ssize_t nread; 12537c478bd9Sstevel@tonic-gate CK_ULONG decrypted_len, encrypted_len, hmac_len; 12547c478bd9Sstevel@tonic-gate CK_BYTE hmac[OBJ_HMAC_SIZE], *decrypted_buf = NULL, *buf = NULL; 12557c478bd9Sstevel@tonic-gate 1256*19193bb6SDina K Nimeh old_fd = open_nointr(orig_obj_name, O_RDONLY|O_NONBLOCK); 12577c478bd9Sstevel@tonic-gate if (old_fd < 0) { 12587c478bd9Sstevel@tonic-gate return (-1); 12597c478bd9Sstevel@tonic-gate } 12607c478bd9Sstevel@tonic-gate 12617c478bd9Sstevel@tonic-gate if (acquire_file_lock(&old_fd, orig_obj_name, O_RDONLY) != 0) { 12627c478bd9Sstevel@tonic-gate if (old_fd > 0) { 12637c478bd9Sstevel@tonic-gate (void) close(old_fd); 12647c478bd9Sstevel@tonic-gate } 12657c478bd9Sstevel@tonic-gate return (-1); 12667c478bd9Sstevel@tonic-gate } 12677c478bd9Sstevel@tonic-gate 1268*19193bb6SDina K Nimeh new_fd = open_nointr(new_obj_name, 1269*19193bb6SDina K Nimeh O_WRONLY|O_CREAT|O_EXCL|O_NONBLOCK, S_IRUSR|S_IWUSR); 12707c478bd9Sstevel@tonic-gate if (new_fd < 0) { 12717c478bd9Sstevel@tonic-gate (void) close(old_fd); 12727c478bd9Sstevel@tonic-gate return (-1); 12737c478bd9Sstevel@tonic-gate } 12747c478bd9Sstevel@tonic-gate 12757c478bd9Sstevel@tonic-gate if (lock_file(new_fd, B_FALSE, B_TRUE) != 0) { 12767c478bd9Sstevel@tonic-gate /* unlock old file */ 12777c478bd9Sstevel@tonic-gate (void) lock_file(old_fd, B_TRUE, B_FALSE); 12787c478bd9Sstevel@tonic-gate (void) close(old_fd); 12797c478bd9Sstevel@tonic-gate (void) close(new_fd); 12807c478bd9Sstevel@tonic-gate return (-1); 12817c478bd9Sstevel@tonic-gate } 12827c478bd9Sstevel@tonic-gate 12837c478bd9Sstevel@tonic-gate /* read version, increment, and write to tmp file */ 1284*19193bb6SDina K Nimeh if (readn_nointr(old_fd, (char *)&version, OBJ_VER_SIZE) 12857c478bd9Sstevel@tonic-gate != OBJ_VER_SIZE) { 12867c478bd9Sstevel@tonic-gate goto cleanup; 12877c478bd9Sstevel@tonic-gate } 12887c478bd9Sstevel@tonic-gate 12897c478bd9Sstevel@tonic-gate version = SWAP32(version); 12907c478bd9Sstevel@tonic-gate version++; 12917c478bd9Sstevel@tonic-gate version = SWAP32(version); 12927c478bd9Sstevel@tonic-gate 1293*19193bb6SDina K Nimeh if (writen_nointr(new_fd, (char *)&version, OBJ_VER_SIZE) 12947c478bd9Sstevel@tonic-gate != OBJ_VER_SIZE) { 12957c478bd9Sstevel@tonic-gate goto cleanup; 12967c478bd9Sstevel@tonic-gate } 12977c478bd9Sstevel@tonic-gate 12987c478bd9Sstevel@tonic-gate /* read old iv */ 1299*19193bb6SDina K Nimeh if (readn_nointr(old_fd, (char *)old_iv, OBJ_IV_SIZE) != OBJ_IV_SIZE) { 13007c478bd9Sstevel@tonic-gate goto cleanup; 13017c478bd9Sstevel@tonic-gate } 13027c478bd9Sstevel@tonic-gate 13037c478bd9Sstevel@tonic-gate /* generate new IV */ 13047c478bd9Sstevel@tonic-gate if (soft_gen_iv(iv) != CKR_OK) { 13057c478bd9Sstevel@tonic-gate goto cleanup; 13067c478bd9Sstevel@tonic-gate } 13077c478bd9Sstevel@tonic-gate 1308*19193bb6SDina K Nimeh if (writen_nointr(new_fd, (char *)iv, OBJ_IV_SIZE) != OBJ_IV_SIZE) { 13097c478bd9Sstevel@tonic-gate goto cleanup; 13107c478bd9Sstevel@tonic-gate } 13117c478bd9Sstevel@tonic-gate 13127c478bd9Sstevel@tonic-gate /* seek to the original encrypted data, and read all of them */ 13137c478bd9Sstevel@tonic-gate if (lseek(old_fd, OBJ_DATA_OFFSET, SEEK_SET) != OBJ_DATA_OFFSET) { 13147c478bd9Sstevel@tonic-gate goto cleanup; 13157c478bd9Sstevel@tonic-gate } 13167c478bd9Sstevel@tonic-gate 13177c478bd9Sstevel@tonic-gate if (read_obj_data(old_fd, (char **)&buf, &nread) != CKR_OK) { 13187c478bd9Sstevel@tonic-gate goto cleanup; 13197c478bd9Sstevel@tonic-gate } 13207c478bd9Sstevel@tonic-gate 13217c478bd9Sstevel@tonic-gate /* decrypt data using old key */ 13227c478bd9Sstevel@tonic-gate decrypted_len = 0; 13237c478bd9Sstevel@tonic-gate if (soft_keystore_crypt(enc_key, old_iv, B_FALSE, buf, nread, 13247c478bd9Sstevel@tonic-gate NULL, &decrypted_len) != CKR_OK) { 13257c478bd9Sstevel@tonic-gate free(buf); 13267c478bd9Sstevel@tonic-gate goto cleanup; 13277c478bd9Sstevel@tonic-gate } 13287c478bd9Sstevel@tonic-gate 13297c478bd9Sstevel@tonic-gate decrypted_buf = malloc(decrypted_len); 13307c478bd9Sstevel@tonic-gate if (decrypted_buf == NULL) { 13317c478bd9Sstevel@tonic-gate free(buf); 13327c478bd9Sstevel@tonic-gate goto cleanup; 13337c478bd9Sstevel@tonic-gate } 13347c478bd9Sstevel@tonic-gate 13357c478bd9Sstevel@tonic-gate if (soft_keystore_crypt(enc_key, old_iv, B_FALSE, buf, nread, 13367c478bd9Sstevel@tonic-gate decrypted_buf, &decrypted_len) != CKR_OK) { 13377c478bd9Sstevel@tonic-gate free(buf); 13387c478bd9Sstevel@tonic-gate free(decrypted_buf); 13397c478bd9Sstevel@tonic-gate goto cleanup; 13407c478bd9Sstevel@tonic-gate } 13417c478bd9Sstevel@tonic-gate 13427c478bd9Sstevel@tonic-gate free(buf); 13437c478bd9Sstevel@tonic-gate 13447c478bd9Sstevel@tonic-gate /* re-encrypt with new key */ 13457c478bd9Sstevel@tonic-gate encrypted_len = 0; 13467c478bd9Sstevel@tonic-gate if (soft_keystore_crypt(new_enc_key, iv, B_TRUE, decrypted_buf, 13477c478bd9Sstevel@tonic-gate decrypted_len, NULL, &encrypted_len) != CKR_OK) { 13487c478bd9Sstevel@tonic-gate free(decrypted_buf); 13497c478bd9Sstevel@tonic-gate goto cleanup; 13507c478bd9Sstevel@tonic-gate } 13517c478bd9Sstevel@tonic-gate 13527c478bd9Sstevel@tonic-gate buf = malloc(encrypted_len); 13537c478bd9Sstevel@tonic-gate if (buf == NULL) { 13547c478bd9Sstevel@tonic-gate free(decrypted_buf); 13557c478bd9Sstevel@tonic-gate goto cleanup; 13567c478bd9Sstevel@tonic-gate } 13577c478bd9Sstevel@tonic-gate 13587c478bd9Sstevel@tonic-gate if (soft_keystore_crypt(new_enc_key, iv, B_TRUE, decrypted_buf, 13597c478bd9Sstevel@tonic-gate decrypted_len, buf, &encrypted_len) != CKR_OK) { 13607c478bd9Sstevel@tonic-gate free(buf); 13617c478bd9Sstevel@tonic-gate free(decrypted_buf); 13627c478bd9Sstevel@tonic-gate goto cleanup; 13637c478bd9Sstevel@tonic-gate } 13647c478bd9Sstevel@tonic-gate 13657c478bd9Sstevel@tonic-gate free(decrypted_buf); 13667c478bd9Sstevel@tonic-gate 13677c478bd9Sstevel@tonic-gate /* calculate hmac on re-encrypted data using new hmac key */ 13687c478bd9Sstevel@tonic-gate hmac_len = OBJ_HMAC_SIZE; 13697c478bd9Sstevel@tonic-gate if (soft_keystore_hmac(new_hmac_key, B_TRUE, buf, 13707c478bd9Sstevel@tonic-gate encrypted_len, hmac, &hmac_len) != CKR_OK) { 13717c478bd9Sstevel@tonic-gate free(buf); 13727c478bd9Sstevel@tonic-gate goto cleanup; 13737c478bd9Sstevel@tonic-gate } 13747c478bd9Sstevel@tonic-gate 13757c478bd9Sstevel@tonic-gate /* just for sanity check */ 13767c478bd9Sstevel@tonic-gate if (hmac_len != OBJ_HMAC_SIZE) { 13777c478bd9Sstevel@tonic-gate free(buf); 13787c478bd9Sstevel@tonic-gate goto cleanup; 13797c478bd9Sstevel@tonic-gate } 13807c478bd9Sstevel@tonic-gate 13817c478bd9Sstevel@tonic-gate /* write new hmac */ 1382*19193bb6SDina K Nimeh if (writen_nointr(new_fd, (char *)hmac, OBJ_HMAC_SIZE) 13837c478bd9Sstevel@tonic-gate != OBJ_HMAC_SIZE) { 13847c478bd9Sstevel@tonic-gate free(buf); 13857c478bd9Sstevel@tonic-gate goto cleanup; 13867c478bd9Sstevel@tonic-gate } 13877c478bd9Sstevel@tonic-gate 13887c478bd9Sstevel@tonic-gate /* write re-encrypted buffer to temp file */ 1389*19193bb6SDina K Nimeh if (writen_nointr(new_fd, (void *)buf, encrypted_len) 13907c478bd9Sstevel@tonic-gate != encrypted_len) { 13917c478bd9Sstevel@tonic-gate free(buf); 13927c478bd9Sstevel@tonic-gate goto cleanup; 13937c478bd9Sstevel@tonic-gate } 13947c478bd9Sstevel@tonic-gate free(buf); 13957c478bd9Sstevel@tonic-gate ret_val = 0; 13967c478bd9Sstevel@tonic-gate 13977c478bd9Sstevel@tonic-gate cleanup: 13987c478bd9Sstevel@tonic-gate /* unlock the files */ 13997c478bd9Sstevel@tonic-gate (void) lock_file(old_fd, B_TRUE, B_FALSE); 14007c478bd9Sstevel@tonic-gate (void) lock_file(new_fd, B_FALSE, B_FALSE); 14017c478bd9Sstevel@tonic-gate 14027c478bd9Sstevel@tonic-gate (void) close(old_fd); 14037c478bd9Sstevel@tonic-gate (void) close(new_fd); 14047c478bd9Sstevel@tonic-gate if (ret_val != 0) { 14057c478bd9Sstevel@tonic-gate (void) remove(new_obj_name); 14067c478bd9Sstevel@tonic-gate } 14077c478bd9Sstevel@tonic-gate return (ret_val); 14087c478bd9Sstevel@tonic-gate } 14097c478bd9Sstevel@tonic-gate 14107c478bd9Sstevel@tonic-gate /* 14117c478bd9Sstevel@tonic-gate * FUNCTION: soft_keystore_setpin 14127c478bd9Sstevel@tonic-gate * 14137c478bd9Sstevel@tonic-gate * ARGUMENTS: 14147c478bd9Sstevel@tonic-gate * newpin: new pin entered by the user. 14157c478bd9Sstevel@tonic-gate * lock_held: TRUE if the lock is held by caller. 14167c478bd9Sstevel@tonic-gate * 14177c478bd9Sstevel@tonic-gate * RETURN VALUE: 14187c478bd9Sstevel@tonic-gate * 0: no error 14197c478bd9Sstevel@tonic-gate * -1: failure 14207c478bd9Sstevel@tonic-gate * 14217c478bd9Sstevel@tonic-gate * DESCRIPTION: 14227c478bd9Sstevel@tonic-gate * 14237c478bd9Sstevel@tonic-gate * This function does the following: 14247c478bd9Sstevel@tonic-gate * 14257c478bd9Sstevel@tonic-gate * 1) Generates crypted value of newpin and store it 14267c478bd9Sstevel@tonic-gate * in keystore description file. 14277c478bd9Sstevel@tonic-gate * 2) Dervies the new encryption key from the newpin. This key 14287c478bd9Sstevel@tonic-gate * will be used to re-encrypt the private token objects. 14297c478bd9Sstevel@tonic-gate * 3) Re-encrypt all of this user's existing private token 14307c478bd9Sstevel@tonic-gate * objects (if any). 14317c478bd9Sstevel@tonic-gate * 4) Increments the keystore version number. 14327c478bd9Sstevel@tonic-gate */ 14337c478bd9Sstevel@tonic-gate int 14347c478bd9Sstevel@tonic-gate soft_keystore_setpin(uchar_t *oldpin, uchar_t *newpin, boolean_t lock_held) 14357c478bd9Sstevel@tonic-gate { 14367c478bd9Sstevel@tonic-gate int fd, tmp_ks_fd, version, ret_val = -1; 14377c478bd9Sstevel@tonic-gate soft_object_t *new_crypt_key = NULL, *new_hmac_key = NULL; 14387c478bd9Sstevel@tonic-gate char filebuf[BUFSIZ]; 14397c478bd9Sstevel@tonic-gate DIR *pri_dirp; 14404bc0a2efScasper struct dirent *pri_ent; 14417c478bd9Sstevel@tonic-gate char pri_obj_path[MAXPATHLEN], ks_desc_file[MAXPATHLEN], 14427c478bd9Sstevel@tonic-gate tmp_ks_desc_name[MAXPATHLEN]; 14437c478bd9Sstevel@tonic-gate typedef struct priobjs { 14447c478bd9Sstevel@tonic-gate char orig_name[MAXPATHLEN]; 14457c478bd9Sstevel@tonic-gate char tmp_name[MAXPATHLEN]; 14467c478bd9Sstevel@tonic-gate struct priobjs *next; 14477c478bd9Sstevel@tonic-gate } priobjs_t; 14487c478bd9Sstevel@tonic-gate priobjs_t *pri_objs = NULL, *tmp; 14497c478bd9Sstevel@tonic-gate CK_BYTE *crypt_salt = NULL, *hmac_salt = NULL; 14507c478bd9Sstevel@tonic-gate boolean_t pin_never_set = B_FALSE, user_logged_in; 14517c478bd9Sstevel@tonic-gate char *new_hashed_pin = NULL; 14527c478bd9Sstevel@tonic-gate uint64_t hashed_pin_salt_length, new_hashed_pin_len, swaped_val; 14537c478bd9Sstevel@tonic-gate char *hashed_pin_salt = NULL; 14547c478bd9Sstevel@tonic-gate priobjs_t *obj; 14557c478bd9Sstevel@tonic-gate 14567c478bd9Sstevel@tonic-gate if ((enc_key == NULL) || 14577c478bd9Sstevel@tonic-gate (enc_key->magic_marker != SOFTTOKEN_OBJECT_MAGIC)) { 14587c478bd9Sstevel@tonic-gate user_logged_in = B_FALSE; 14597c478bd9Sstevel@tonic-gate } else { 14607c478bd9Sstevel@tonic-gate user_logged_in = B_TRUE; 14617c478bd9Sstevel@tonic-gate } 14627c478bd9Sstevel@tonic-gate 14637c478bd9Sstevel@tonic-gate if ((fd = open_and_lock_keystore_desc(O_RDWR, B_FALSE, 14647c478bd9Sstevel@tonic-gate lock_held)) < 0) { 14657c478bd9Sstevel@tonic-gate return (-1); 14667c478bd9Sstevel@tonic-gate } 14677c478bd9Sstevel@tonic-gate 14687c478bd9Sstevel@tonic-gate (void) get_desc_file_path(ks_desc_file); 14697c478bd9Sstevel@tonic-gate (void) get_tmp_desc_file_path(tmp_ks_desc_name); 14707c478bd9Sstevel@tonic-gate 14717c478bd9Sstevel@tonic-gate /* 14727c478bd9Sstevel@tonic-gate * create a tempoary file for the keystore description 14737c478bd9Sstevel@tonic-gate * file for updating version and counter information 14747c478bd9Sstevel@tonic-gate */ 1475*19193bb6SDina K Nimeh tmp_ks_fd = open_nointr(tmp_ks_desc_name, 1476*19193bb6SDina K Nimeh O_RDWR|O_CREAT|O_EXCL|O_NONBLOCK, S_IRUSR|S_IWUSR); 14777c478bd9Sstevel@tonic-gate if (tmp_ks_fd < 0) { 14787c478bd9Sstevel@tonic-gate (void) close(fd); 14797c478bd9Sstevel@tonic-gate return (-1); 14807c478bd9Sstevel@tonic-gate } 14817c478bd9Sstevel@tonic-gate 14827c478bd9Sstevel@tonic-gate /* read and write PKCS version to temp file */ 1483*19193bb6SDina K Nimeh if (readn_nointr(fd, filebuf, KS_PKCS11_VER_SIZE) 14847c478bd9Sstevel@tonic-gate != KS_PKCS11_VER_SIZE) { 14857c478bd9Sstevel@tonic-gate goto cleanup; 14867c478bd9Sstevel@tonic-gate } 14877c478bd9Sstevel@tonic-gate 1488*19193bb6SDina K Nimeh if (writen_nointr(tmp_ks_fd, filebuf, KS_PKCS11_VER_SIZE) 14897c478bd9Sstevel@tonic-gate != KS_PKCS11_VER_SIZE) { 14907c478bd9Sstevel@tonic-gate goto cleanup; 14917c478bd9Sstevel@tonic-gate } 14927c478bd9Sstevel@tonic-gate 14937c478bd9Sstevel@tonic-gate /* get version number, and write updated number to temp file */ 1494*19193bb6SDina K Nimeh if (readn_nointr(fd, &version, KS_VER_SIZE) != KS_VER_SIZE) { 14957c478bd9Sstevel@tonic-gate goto cleanup; 14967c478bd9Sstevel@tonic-gate } 14977c478bd9Sstevel@tonic-gate 14987c478bd9Sstevel@tonic-gate version = SWAP32(version); 14997c478bd9Sstevel@tonic-gate version++; 15007c478bd9Sstevel@tonic-gate version = SWAP32(version); 15017c478bd9Sstevel@tonic-gate 1502*19193bb6SDina K Nimeh if (writen_nointr(tmp_ks_fd, (void *)&version, KS_VER_SIZE) 15037c478bd9Sstevel@tonic-gate != KS_VER_SIZE) { 15047c478bd9Sstevel@tonic-gate goto cleanup; 15057c478bd9Sstevel@tonic-gate } 15067c478bd9Sstevel@tonic-gate 15077c478bd9Sstevel@tonic-gate 15087c478bd9Sstevel@tonic-gate /* read and write counter, no modification necessary */ 1509*19193bb6SDina K Nimeh if (readn_nointr(fd, filebuf, KS_COUNTER_SIZE) != KS_COUNTER_SIZE) { 15107c478bd9Sstevel@tonic-gate goto cleanup; 15117c478bd9Sstevel@tonic-gate } 15127c478bd9Sstevel@tonic-gate 1513*19193bb6SDina K Nimeh if (writen_nointr(tmp_ks_fd, filebuf, KS_COUNTER_SIZE) 15147c478bd9Sstevel@tonic-gate != KS_COUNTER_SIZE) { 15157c478bd9Sstevel@tonic-gate goto cleanup; 15167c478bd9Sstevel@tonic-gate } 15177c478bd9Sstevel@tonic-gate 15187c478bd9Sstevel@tonic-gate /* read old encryption salt */ 15197c478bd9Sstevel@tonic-gate crypt_salt = malloc(KS_KEY_SALT_SIZE); 15207c478bd9Sstevel@tonic-gate if (crypt_salt == NULL) { 15217c478bd9Sstevel@tonic-gate goto cleanup; 15227c478bd9Sstevel@tonic-gate } 1523*19193bb6SDina K Nimeh if (readn_nointr(fd, (char *)crypt_salt, KS_KEY_SALT_SIZE) 15247c478bd9Sstevel@tonic-gate != KS_KEY_SALT_SIZE) { 15257c478bd9Sstevel@tonic-gate goto cleanup; 15267c478bd9Sstevel@tonic-gate } 15277c478bd9Sstevel@tonic-gate 15287c478bd9Sstevel@tonic-gate /* read old hmac salt */ 15297c478bd9Sstevel@tonic-gate hmac_salt = malloc(KS_HMAC_SALT_SIZE); 15307c478bd9Sstevel@tonic-gate if (hmac_salt == NULL) { 15317c478bd9Sstevel@tonic-gate goto cleanup; 15327c478bd9Sstevel@tonic-gate } 1533*19193bb6SDina K Nimeh if (readn_nointr(fd, (char *)hmac_salt, KS_HMAC_SALT_SIZE) 15347c478bd9Sstevel@tonic-gate != KS_HMAC_SALT_SIZE) { 15357c478bd9Sstevel@tonic-gate goto cleanup; 15367c478bd9Sstevel@tonic-gate } 15377c478bd9Sstevel@tonic-gate 15387c478bd9Sstevel@tonic-gate /* just create some empty bytes */ 15397c478bd9Sstevel@tonic-gate bzero(filebuf, sizeof (filebuf)); 15407c478bd9Sstevel@tonic-gate 15417c478bd9Sstevel@tonic-gate if (memcmp(crypt_salt, filebuf, KS_KEY_SALT_SIZE) == 0) { 15427c478bd9Sstevel@tonic-gate /* PIN as never been set */ 15437c478bd9Sstevel@tonic-gate CK_BYTE *new_crypt_salt = NULL, *new_hmac_salt = NULL; 15447c478bd9Sstevel@tonic-gate 15457c478bd9Sstevel@tonic-gate pin_never_set = B_TRUE; 15467c478bd9Sstevel@tonic-gate if (soft_gen_crypt_key(newpin, &new_crypt_key, &new_crypt_salt) 15477c478bd9Sstevel@tonic-gate != CKR_OK) { 15487c478bd9Sstevel@tonic-gate goto cleanup; 15497c478bd9Sstevel@tonic-gate } 1550*19193bb6SDina K Nimeh if (writen_nointr(tmp_ks_fd, (void *)new_crypt_salt, 15517c478bd9Sstevel@tonic-gate KS_KEY_SALT_SIZE) != KS_KEY_SALT_SIZE) { 15527c478bd9Sstevel@tonic-gate free(new_crypt_salt); 15537c478bd9Sstevel@tonic-gate (void) soft_cleanup_object(new_crypt_key); 15547c478bd9Sstevel@tonic-gate goto cleanup; 15557c478bd9Sstevel@tonic-gate } 15567c478bd9Sstevel@tonic-gate free(new_crypt_salt); 15577c478bd9Sstevel@tonic-gate 15587c478bd9Sstevel@tonic-gate if (soft_gen_hmac_key(newpin, &new_hmac_key, &new_hmac_salt) 15597c478bd9Sstevel@tonic-gate != CKR_OK) { 15607c478bd9Sstevel@tonic-gate (void) soft_cleanup_object(new_crypt_key); 15617c478bd9Sstevel@tonic-gate goto cleanup; 15627c478bd9Sstevel@tonic-gate } 1563*19193bb6SDina K Nimeh if (writen_nointr(tmp_ks_fd, (void *)new_hmac_salt, 15647c478bd9Sstevel@tonic-gate KS_HMAC_SALT_SIZE) != KS_HMAC_SALT_SIZE) { 15657c478bd9Sstevel@tonic-gate free(new_hmac_salt); 15667c478bd9Sstevel@tonic-gate goto cleanup3; 15677c478bd9Sstevel@tonic-gate } 15687c478bd9Sstevel@tonic-gate free(new_hmac_salt); 15697c478bd9Sstevel@tonic-gate } else { 15707c478bd9Sstevel@tonic-gate if (soft_gen_crypt_key(newpin, &new_crypt_key, 15717c478bd9Sstevel@tonic-gate (CK_BYTE **)&crypt_salt) != CKR_OK) { 15727c478bd9Sstevel@tonic-gate goto cleanup; 15737c478bd9Sstevel@tonic-gate } 15747c478bd9Sstevel@tonic-gate /* no change to the encryption salt */ 1575*19193bb6SDina K Nimeh if (writen_nointr(tmp_ks_fd, (void *)crypt_salt, 15767c478bd9Sstevel@tonic-gate KS_KEY_SALT_SIZE) != KS_KEY_SALT_SIZE) { 15777c478bd9Sstevel@tonic-gate (void) soft_cleanup_object(new_crypt_key); 15787c478bd9Sstevel@tonic-gate goto cleanup; 15797c478bd9Sstevel@tonic-gate } 15807c478bd9Sstevel@tonic-gate 15817c478bd9Sstevel@tonic-gate if (soft_gen_hmac_key(newpin, &new_hmac_key, 15827c478bd9Sstevel@tonic-gate (CK_BYTE **)&hmac_salt) != CKR_OK) { 15837c478bd9Sstevel@tonic-gate (void) soft_cleanup_object(new_crypt_key); 15847c478bd9Sstevel@tonic-gate goto cleanup; 15857c478bd9Sstevel@tonic-gate } 15867c478bd9Sstevel@tonic-gate 15877c478bd9Sstevel@tonic-gate /* no change to the hmac salt */ 1588*19193bb6SDina K Nimeh if (writen_nointr(tmp_ks_fd, (void *)hmac_salt, 15897c478bd9Sstevel@tonic-gate KS_HMAC_SALT_SIZE) != KS_HMAC_SALT_SIZE) { 15907c478bd9Sstevel@tonic-gate goto cleanup3; 15917c478bd9Sstevel@tonic-gate } 15927c478bd9Sstevel@tonic-gate } 15937c478bd9Sstevel@tonic-gate 15947c478bd9Sstevel@tonic-gate /* 15957c478bd9Sstevel@tonic-gate * read hashed pin salt, and write to updated keystore description 15967c478bd9Sstevel@tonic-gate * file unmodified. 15977c478bd9Sstevel@tonic-gate */ 1598*19193bb6SDina K Nimeh if (readn_nointr(fd, (char *)&hashed_pin_salt_length, 15997c478bd9Sstevel@tonic-gate KS_HASHED_PIN_SALT_LEN_SIZE) != KS_HASHED_PIN_SALT_LEN_SIZE) { 16007c478bd9Sstevel@tonic-gate goto cleanup3; 16017c478bd9Sstevel@tonic-gate } 16027c478bd9Sstevel@tonic-gate 1603*19193bb6SDina K Nimeh if (writen_nointr(tmp_ks_fd, (void *)&hashed_pin_salt_length, 16047c478bd9Sstevel@tonic-gate KS_HASHED_PIN_SALT_LEN_SIZE) != KS_HASHED_PIN_SALT_LEN_SIZE) { 16057c478bd9Sstevel@tonic-gate goto cleanup3; 16067c478bd9Sstevel@tonic-gate } 16077c478bd9Sstevel@tonic-gate 16087c478bd9Sstevel@tonic-gate hashed_pin_salt_length = SWAP64(hashed_pin_salt_length); 16097c478bd9Sstevel@tonic-gate 16107c478bd9Sstevel@tonic-gate hashed_pin_salt = malloc(hashed_pin_salt_length + 1); 16117c478bd9Sstevel@tonic-gate if (hashed_pin_salt == NULL) { 16127c478bd9Sstevel@tonic-gate goto cleanup3; 16137c478bd9Sstevel@tonic-gate } 16147c478bd9Sstevel@tonic-gate 1615*19193bb6SDina K Nimeh if ((readn_nointr(fd, hashed_pin_salt, hashed_pin_salt_length)) != 16167c478bd9Sstevel@tonic-gate (ssize_t)hashed_pin_salt_length) { 16177c478bd9Sstevel@tonic-gate free(hashed_pin_salt); 16187c478bd9Sstevel@tonic-gate goto cleanup3; 16197c478bd9Sstevel@tonic-gate } 16207c478bd9Sstevel@tonic-gate 1621*19193bb6SDina K Nimeh if ((writen_nointr(tmp_ks_fd, hashed_pin_salt, hashed_pin_salt_length)) 16227c478bd9Sstevel@tonic-gate != (ssize_t)hashed_pin_salt_length) { 16237c478bd9Sstevel@tonic-gate free(hashed_pin_salt); 16247c478bd9Sstevel@tonic-gate goto cleanup3; 16257c478bd9Sstevel@tonic-gate } 16267c478bd9Sstevel@tonic-gate 16277c478bd9Sstevel@tonic-gate hashed_pin_salt[hashed_pin_salt_length] = '\0'; 16287c478bd9Sstevel@tonic-gate 16297c478bd9Sstevel@tonic-gate /* old hashed pin length and value can be ignored, generate new one */ 16307c478bd9Sstevel@tonic-gate if (soft_gen_hashed_pin(newpin, &new_hashed_pin, 16317c478bd9Sstevel@tonic-gate &hashed_pin_salt) < 0) { 16327c478bd9Sstevel@tonic-gate free(hashed_pin_salt); 16337c478bd9Sstevel@tonic-gate goto cleanup3; 16347c478bd9Sstevel@tonic-gate } 16357c478bd9Sstevel@tonic-gate 16367c478bd9Sstevel@tonic-gate free(hashed_pin_salt); 16377c478bd9Sstevel@tonic-gate 16387c478bd9Sstevel@tonic-gate if (new_hashed_pin == NULL) { 16397c478bd9Sstevel@tonic-gate goto cleanup3; 16407c478bd9Sstevel@tonic-gate } 16417c478bd9Sstevel@tonic-gate 16427c478bd9Sstevel@tonic-gate new_hashed_pin_len = strlen(new_hashed_pin); 16437c478bd9Sstevel@tonic-gate 16447c478bd9Sstevel@tonic-gate /* write new hashed pin length to file */ 16457c478bd9Sstevel@tonic-gate swaped_val = SWAP64(new_hashed_pin_len); 1646*19193bb6SDina K Nimeh if (writen_nointr(tmp_ks_fd, (void *)&swaped_val, 16477c478bd9Sstevel@tonic-gate KS_HASHED_PINLEN_SIZE) != KS_HASHED_PINLEN_SIZE) { 16487c478bd9Sstevel@tonic-gate goto cleanup3; 16497c478bd9Sstevel@tonic-gate } 16507c478bd9Sstevel@tonic-gate 1651*19193bb6SDina K Nimeh if (writen_nointr(tmp_ks_fd, (void *)new_hashed_pin, 16527c478bd9Sstevel@tonic-gate new_hashed_pin_len) != (ssize_t)new_hashed_pin_len) { 16537c478bd9Sstevel@tonic-gate goto cleanup3; 16547c478bd9Sstevel@tonic-gate } 16557c478bd9Sstevel@tonic-gate 16567c478bd9Sstevel@tonic-gate if (pin_never_set) { 16577c478bd9Sstevel@tonic-gate /* there was no private object, no need to re-encrypt them */ 16587c478bd9Sstevel@tonic-gate goto rename_desc_file; 16597c478bd9Sstevel@tonic-gate } 16607c478bd9Sstevel@tonic-gate 16617c478bd9Sstevel@tonic-gate /* re-encrypt all the private objects */ 16627c478bd9Sstevel@tonic-gate pri_dirp = opendir(get_pri_obj_path(pri_obj_path)); 16637c478bd9Sstevel@tonic-gate if (pri_dirp == NULL) { 16647c478bd9Sstevel@tonic-gate /* 16657c478bd9Sstevel@tonic-gate * this directory should exist, even if it doesn't contain 16667c478bd9Sstevel@tonic-gate * any objects. Don't want to update the pin if the 16677c478bd9Sstevel@tonic-gate * keystore is somehow messed up. 16687c478bd9Sstevel@tonic-gate */ 16697c478bd9Sstevel@tonic-gate 16707c478bd9Sstevel@tonic-gate goto cleanup3; 16717c478bd9Sstevel@tonic-gate } 16727c478bd9Sstevel@tonic-gate 16737c478bd9Sstevel@tonic-gate /* if user did not login, need to set the old pin */ 16747c478bd9Sstevel@tonic-gate if (!user_logged_in) { 16757c478bd9Sstevel@tonic-gate if (soft_keystore_authpin(oldpin) != 0) { 16767c478bd9Sstevel@tonic-gate goto cleanup3; 16777c478bd9Sstevel@tonic-gate } 16787c478bd9Sstevel@tonic-gate } 16797c478bd9Sstevel@tonic-gate 16804bc0a2efScasper while ((pri_ent = readdir(pri_dirp)) != NULL) { 16817c478bd9Sstevel@tonic-gate 16827c478bd9Sstevel@tonic-gate if ((strcmp(pri_ent->d_name, ".") == 0) || 16837c478bd9Sstevel@tonic-gate (strcmp(pri_ent->d_name, "..") == 0) || 16847c478bd9Sstevel@tonic-gate (strncmp(pri_ent->d_name, TMP_OBJ_PREFIX, 16857c478bd9Sstevel@tonic-gate strlen(TMP_OBJ_PREFIX)) == 0)) { 16867c478bd9Sstevel@tonic-gate continue; 16877c478bd9Sstevel@tonic-gate } 16887c478bd9Sstevel@tonic-gate 16897c478bd9Sstevel@tonic-gate obj = malloc(sizeof (priobjs_t)); 16907c478bd9Sstevel@tonic-gate if (obj == NULL) { 16917c478bd9Sstevel@tonic-gate goto cleanup2; 16927c478bd9Sstevel@tonic-gate } 16937c478bd9Sstevel@tonic-gate (void) snprintf(obj->orig_name, MAXPATHLEN, 16947c478bd9Sstevel@tonic-gate "%s/%s", pri_obj_path, pri_ent->d_name); 16957c478bd9Sstevel@tonic-gate (void) snprintf(obj->tmp_name, MAXPATHLEN, "%s/%s%s", 16967c478bd9Sstevel@tonic-gate pri_obj_path, TMP_OBJ_PREFIX, 16977c478bd9Sstevel@tonic-gate (pri_ent->d_name) + strlen(OBJ_PREFIX)); 16987c478bd9Sstevel@tonic-gate if (reencrypt_obj(new_crypt_key, new_hmac_key, 16997c478bd9Sstevel@tonic-gate obj->orig_name, obj->tmp_name) != 0) { 17007c478bd9Sstevel@tonic-gate free(obj); 17017c478bd9Sstevel@tonic-gate goto cleanup2; 17027c478bd9Sstevel@tonic-gate } 17037c478bd9Sstevel@tonic-gate 17047c478bd9Sstevel@tonic-gate /* insert into list of file to be renamed */ 17057c478bd9Sstevel@tonic-gate if (pri_objs == NULL) { 17067c478bd9Sstevel@tonic-gate obj->next = NULL; 17077c478bd9Sstevel@tonic-gate pri_objs = obj; 17087c478bd9Sstevel@tonic-gate } else { 17097c478bd9Sstevel@tonic-gate obj->next = pri_objs; 17107c478bd9Sstevel@tonic-gate pri_objs = obj; 17117c478bd9Sstevel@tonic-gate } 17127c478bd9Sstevel@tonic-gate } 17137c478bd9Sstevel@tonic-gate 17147c478bd9Sstevel@tonic-gate /* rename all the private objects */ 17157c478bd9Sstevel@tonic-gate tmp = pri_objs; 17167c478bd9Sstevel@tonic-gate while (tmp) { 17177c478bd9Sstevel@tonic-gate (void) rename(tmp->tmp_name, tmp->orig_name); 17187c478bd9Sstevel@tonic-gate tmp = tmp->next; 17197c478bd9Sstevel@tonic-gate } 17207c478bd9Sstevel@tonic-gate 17217c478bd9Sstevel@tonic-gate rename_desc_file: 17227c478bd9Sstevel@tonic-gate 17237c478bd9Sstevel@tonic-gate /* destroy the old encryption key, and hmac key */ 17247c478bd9Sstevel@tonic-gate if ((!pin_never_set) && (user_logged_in)) { 17257c478bd9Sstevel@tonic-gate (void) soft_cleanup_object(enc_key); 17267c478bd9Sstevel@tonic-gate (void) soft_cleanup_object(hmac_key); 17277c478bd9Sstevel@tonic-gate } 17287c478bd9Sstevel@tonic-gate 17297c478bd9Sstevel@tonic-gate if (user_logged_in) { 17307c478bd9Sstevel@tonic-gate enc_key = new_crypt_key; 17317c478bd9Sstevel@tonic-gate hmac_key = new_hmac_key; 17327c478bd9Sstevel@tonic-gate } 17337c478bd9Sstevel@tonic-gate (void) rename(tmp_ks_desc_name, ks_desc_file); 17347c478bd9Sstevel@tonic-gate 17357c478bd9Sstevel@tonic-gate ret_val = 0; 17367c478bd9Sstevel@tonic-gate 17377c478bd9Sstevel@tonic-gate cleanup2: 17387c478bd9Sstevel@tonic-gate if (pri_objs != NULL) { 17397c478bd9Sstevel@tonic-gate priobjs_t *p = pri_objs; 17407c478bd9Sstevel@tonic-gate while (p) { 17417c478bd9Sstevel@tonic-gate tmp = p->next; 17427c478bd9Sstevel@tonic-gate free(p); 17437c478bd9Sstevel@tonic-gate p = tmp; 17447c478bd9Sstevel@tonic-gate } 17457c478bd9Sstevel@tonic-gate } 17467c478bd9Sstevel@tonic-gate if (!pin_never_set) { 17477c478bd9Sstevel@tonic-gate (void) closedir(pri_dirp); 17487c478bd9Sstevel@tonic-gate } 17497c478bd9Sstevel@tonic-gate 17507c478bd9Sstevel@tonic-gate if ((!user_logged_in) && (!pin_never_set)) { 17517c478bd9Sstevel@tonic-gate (void) soft_cleanup_object(enc_key); 17527c478bd9Sstevel@tonic-gate (void) soft_cleanup_object(hmac_key); 17537c478bd9Sstevel@tonic-gate enc_key = NULL; 17547c478bd9Sstevel@tonic-gate hmac_key = NULL; 17557c478bd9Sstevel@tonic-gate } 17567c478bd9Sstevel@tonic-gate cleanup3: 17577c478bd9Sstevel@tonic-gate if ((ret_val != 0) || (!user_logged_in)) { 17587c478bd9Sstevel@tonic-gate (void) soft_cleanup_object(new_crypt_key); 17597c478bd9Sstevel@tonic-gate (void) soft_cleanup_object(new_hmac_key); 17607c478bd9Sstevel@tonic-gate } 17617c478bd9Sstevel@tonic-gate 17627c478bd9Sstevel@tonic-gate cleanup: 17637c478bd9Sstevel@tonic-gate if (!lock_held) { 17647c478bd9Sstevel@tonic-gate if (lock_file(fd, B_FALSE, B_FALSE) < 0) { 17657c478bd9Sstevel@tonic-gate ret_val = 1; 17667c478bd9Sstevel@tonic-gate } 17677c478bd9Sstevel@tonic-gate } 17687c478bd9Sstevel@tonic-gate if (crypt_salt != NULL) { 17697c478bd9Sstevel@tonic-gate free(crypt_salt); 17707c478bd9Sstevel@tonic-gate } 17717c478bd9Sstevel@tonic-gate if (hmac_salt != NULL) { 17727c478bd9Sstevel@tonic-gate free(hmac_salt); 17737c478bd9Sstevel@tonic-gate } 17747c478bd9Sstevel@tonic-gate (void) close(fd); 17757c478bd9Sstevel@tonic-gate (void) close(tmp_ks_fd); 17767c478bd9Sstevel@tonic-gate if (ret_val != 0) { 17777c478bd9Sstevel@tonic-gate (void) remove(tmp_ks_desc_name); 17787c478bd9Sstevel@tonic-gate } 17797c478bd9Sstevel@tonic-gate return (ret_val); 17807c478bd9Sstevel@tonic-gate } 17817c478bd9Sstevel@tonic-gate 17827c478bd9Sstevel@tonic-gate /* 17837c478bd9Sstevel@tonic-gate * FUNCTION: soft_keystore_authpin 17847c478bd9Sstevel@tonic-gate * 17857c478bd9Sstevel@tonic-gate * ARGUMENTS: 17867c478bd9Sstevel@tonic-gate * pin: pin specified by the user for logging into 17877c478bd9Sstevel@tonic-gate * the keystore. 17887c478bd9Sstevel@tonic-gate * 17897c478bd9Sstevel@tonic-gate * RETURN VALUE: 17907c478bd9Sstevel@tonic-gate * 0: if no error 17917c478bd9Sstevel@tonic-gate * -1: if there is any error 17927c478bd9Sstevel@tonic-gate * 17937c478bd9Sstevel@tonic-gate * DESCRIPTION: 17947c478bd9Sstevel@tonic-gate * 17957c478bd9Sstevel@tonic-gate * This function takes the pin specified in the argument 17967c478bd9Sstevel@tonic-gate * and generates an encryption key based on the pin. 17977c478bd9Sstevel@tonic-gate * The generated encryption key will be used for 17987c478bd9Sstevel@tonic-gate * all future encryption and decryption for private 17997c478bd9Sstevel@tonic-gate * objects. Before this function is called, none 18007c478bd9Sstevel@tonic-gate * of the keystore related interfaces is able 18017c478bd9Sstevel@tonic-gate * to decrypt/encrypt any private object. 18027c478bd9Sstevel@tonic-gate */ 18037c478bd9Sstevel@tonic-gate int 18047c478bd9Sstevel@tonic-gate soft_keystore_authpin(uchar_t *pin) 18057c478bd9Sstevel@tonic-gate { 18067c478bd9Sstevel@tonic-gate int fd; 18077c478bd9Sstevel@tonic-gate int ret_val = -1; 18087c478bd9Sstevel@tonic-gate CK_BYTE *crypt_salt = NULL, *hmac_salt; 18097c478bd9Sstevel@tonic-gate 18107c478bd9Sstevel@tonic-gate /* get the salt from the keystore description file */ 18117c478bd9Sstevel@tonic-gate if ((fd = open_and_lock_keystore_desc(O_RDONLY, 18127c478bd9Sstevel@tonic-gate B_FALSE, B_FALSE)) < 0) { 18137c478bd9Sstevel@tonic-gate return (-1); 18147c478bd9Sstevel@tonic-gate } 18157c478bd9Sstevel@tonic-gate 18167c478bd9Sstevel@tonic-gate crypt_salt = malloc(KS_KEY_SALT_SIZE); 18177c478bd9Sstevel@tonic-gate if (crypt_salt == NULL) { 18187c478bd9Sstevel@tonic-gate goto cleanup; 18197c478bd9Sstevel@tonic-gate } 18207c478bd9Sstevel@tonic-gate 18217c478bd9Sstevel@tonic-gate if (lseek(fd, KS_KEY_SALT_OFFSET, SEEK_SET) != KS_KEY_SALT_OFFSET) { 18227c478bd9Sstevel@tonic-gate goto cleanup; 18237c478bd9Sstevel@tonic-gate } 18247c478bd9Sstevel@tonic-gate 1825*19193bb6SDina K Nimeh if (readn_nointr(fd, (char *)crypt_salt, KS_KEY_SALT_SIZE) 18267c478bd9Sstevel@tonic-gate != KS_KEY_SALT_SIZE) { 18277c478bd9Sstevel@tonic-gate goto cleanup; 18287c478bd9Sstevel@tonic-gate } 18297c478bd9Sstevel@tonic-gate 18307c478bd9Sstevel@tonic-gate if (soft_gen_crypt_key(pin, &enc_key, (CK_BYTE **)&crypt_salt) 18317c478bd9Sstevel@tonic-gate != CKR_OK) { 18327c478bd9Sstevel@tonic-gate goto cleanup; 18337c478bd9Sstevel@tonic-gate } 18347c478bd9Sstevel@tonic-gate 18357c478bd9Sstevel@tonic-gate hmac_salt = malloc(KS_HMAC_SALT_SIZE); 18367c478bd9Sstevel@tonic-gate if (hmac_salt == NULL) { 18377c478bd9Sstevel@tonic-gate goto cleanup; 18387c478bd9Sstevel@tonic-gate } 18397c478bd9Sstevel@tonic-gate 18407c478bd9Sstevel@tonic-gate if (lseek(fd, KS_HMAC_SALT_OFFSET, SEEK_SET) != KS_HMAC_SALT_OFFSET) { 18417c478bd9Sstevel@tonic-gate goto cleanup; 18427c478bd9Sstevel@tonic-gate } 18437c478bd9Sstevel@tonic-gate 1844*19193bb6SDina K Nimeh if (readn_nointr(fd, (char *)hmac_salt, KS_HMAC_SALT_SIZE) 18457c478bd9Sstevel@tonic-gate != KS_HMAC_SALT_SIZE) { 18467c478bd9Sstevel@tonic-gate goto cleanup; 18477c478bd9Sstevel@tonic-gate } 18487c478bd9Sstevel@tonic-gate 18497c478bd9Sstevel@tonic-gate if (soft_gen_hmac_key(pin, &hmac_key, (CK_BYTE **)&hmac_salt) 18507c478bd9Sstevel@tonic-gate != CKR_OK) { 18517c478bd9Sstevel@tonic-gate goto cleanup; 18527c478bd9Sstevel@tonic-gate } 18537c478bd9Sstevel@tonic-gate 18547c478bd9Sstevel@tonic-gate ret_val = 0; 18557c478bd9Sstevel@tonic-gate 18567c478bd9Sstevel@tonic-gate cleanup: 18577c478bd9Sstevel@tonic-gate /* unlock the file */ 18587c478bd9Sstevel@tonic-gate (void) lock_file(fd, B_TRUE, B_FALSE); 18597c478bd9Sstevel@tonic-gate (void) close(fd); 18607c478bd9Sstevel@tonic-gate if (crypt_salt != NULL) { 18617c478bd9Sstevel@tonic-gate free(crypt_salt); 18627c478bd9Sstevel@tonic-gate } 18637c478bd9Sstevel@tonic-gate if (hmac_salt != NULL) { 18647c478bd9Sstevel@tonic-gate free(hmac_salt); 18657c478bd9Sstevel@tonic-gate } 18667c478bd9Sstevel@tonic-gate return (ret_val); 18677c478bd9Sstevel@tonic-gate } 18687c478bd9Sstevel@tonic-gate 18697c478bd9Sstevel@tonic-gate /* 18707c478bd9Sstevel@tonic-gate * FUNCTION: soft_keystore_get_objs 18717c478bd9Sstevel@tonic-gate * 18727c478bd9Sstevel@tonic-gate * ARGUMENTS: 18737c478bd9Sstevel@tonic-gate * 18747c478bd9Sstevel@tonic-gate * search_type: Specify type of objects to return. 18757c478bd9Sstevel@tonic-gate * lock_held: TRUE if the lock is held by caller. 18767c478bd9Sstevel@tonic-gate * 18777c478bd9Sstevel@tonic-gate * 18787c478bd9Sstevel@tonic-gate * RETURN VALUE: 18797c478bd9Sstevel@tonic-gate * 18807c478bd9Sstevel@tonic-gate * NULL: if there are no object in the database. 18817c478bd9Sstevel@tonic-gate * 18827c478bd9Sstevel@tonic-gate * Otherwise, linked list of objects as requested 18837c478bd9Sstevel@tonic-gate * in search type. 18847c478bd9Sstevel@tonic-gate * 18857c478bd9Sstevel@tonic-gate * The linked list returned will need to be freed 18867c478bd9Sstevel@tonic-gate * by the caller. 18877c478bd9Sstevel@tonic-gate * 18887c478bd9Sstevel@tonic-gate * DESCRIPTION: 18897c478bd9Sstevel@tonic-gate * 18907c478bd9Sstevel@tonic-gate * Returns objects as requested. 18917c478bd9Sstevel@tonic-gate * 18927c478bd9Sstevel@tonic-gate * If private objects is requested, and the caller 18937c478bd9Sstevel@tonic-gate * has not previously passed in the pin or if the pin 18947c478bd9Sstevel@tonic-gate * passed in is wrong, private objects will not 18957c478bd9Sstevel@tonic-gate * be returned. 18967c478bd9Sstevel@tonic-gate * 18977c478bd9Sstevel@tonic-gate * The buffers returned for private objects are already 18987c478bd9Sstevel@tonic-gate * decrypted. 18997c478bd9Sstevel@tonic-gate */ 19007c478bd9Sstevel@tonic-gate CK_RV 19017c478bd9Sstevel@tonic-gate soft_keystore_get_objs(ks_search_type_t search_type, 19027c478bd9Sstevel@tonic-gate ks_obj_t **result_obj_list, boolean_t lock_held) 19037c478bd9Sstevel@tonic-gate { 19047c478bd9Sstevel@tonic-gate DIR *dirp; 19057c478bd9Sstevel@tonic-gate ks_obj_handle_t ks_handle; 19067c478bd9Sstevel@tonic-gate CK_RV rv; 19077c478bd9Sstevel@tonic-gate ks_obj_t *tmp; 19087c478bd9Sstevel@tonic-gate int ks_fd; 19097c478bd9Sstevel@tonic-gate 19107c478bd9Sstevel@tonic-gate *result_obj_list = NULL; 19117c478bd9Sstevel@tonic-gate 19127c478bd9Sstevel@tonic-gate /* 19137c478bd9Sstevel@tonic-gate * lock the keystore description file in "read" mode so that 19147c478bd9Sstevel@tonic-gate * objects won't get added/deleted/modified while we are 19157c478bd9Sstevel@tonic-gate * doing the search 19167c478bd9Sstevel@tonic-gate */ 19177c478bd9Sstevel@tonic-gate if ((ks_fd = open_and_lock_keystore_desc(O_RDONLY, B_TRUE, 19187c478bd9Sstevel@tonic-gate B_FALSE)) < 0) { 19197c478bd9Sstevel@tonic-gate return (CKR_FUNCTION_FAILED); 19207c478bd9Sstevel@tonic-gate } 19217c478bd9Sstevel@tonic-gate 19227c478bd9Sstevel@tonic-gate if ((search_type == ALL_TOKENOBJS) || (search_type == PUB_TOKENOBJS)) { 19237c478bd9Sstevel@tonic-gate 19247c478bd9Sstevel@tonic-gate char pub_obj_path[MAXPATHLEN]; 19257c478bd9Sstevel@tonic-gate 19267c478bd9Sstevel@tonic-gate ks_handle.public = B_TRUE; 19277c478bd9Sstevel@tonic-gate 19287c478bd9Sstevel@tonic-gate if ((dirp = opendir(get_pub_obj_path(pub_obj_path))) == NULL) { 19297c478bd9Sstevel@tonic-gate (void) lock_file(ks_fd, B_TRUE, B_FALSE); 19307c478bd9Sstevel@tonic-gate (void) close(ks_fd); 19317c478bd9Sstevel@tonic-gate return (CKR_FUNCTION_FAILED); 19327c478bd9Sstevel@tonic-gate } 19337c478bd9Sstevel@tonic-gate rv = get_all_objs_in_dir(dirp, &ks_handle, result_obj_list, 19344bc0a2efScasper lock_held); 19357c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 19367c478bd9Sstevel@tonic-gate (void) closedir(dirp); 19377c478bd9Sstevel@tonic-gate goto cleanup; 19387c478bd9Sstevel@tonic-gate } 19397c478bd9Sstevel@tonic-gate 19407c478bd9Sstevel@tonic-gate (void) closedir(dirp); 19417c478bd9Sstevel@tonic-gate } 19427c478bd9Sstevel@tonic-gate 19437c478bd9Sstevel@tonic-gate if ((search_type == ALL_TOKENOBJS) || (search_type == PRI_TOKENOBJS)) { 19447c478bd9Sstevel@tonic-gate 19457c478bd9Sstevel@tonic-gate char pri_obj_path[MAXPATHLEN]; 19467c478bd9Sstevel@tonic-gate 19477c478bd9Sstevel@tonic-gate if ((enc_key == NULL) || 19487c478bd9Sstevel@tonic-gate (enc_key->magic_marker != SOFTTOKEN_OBJECT_MAGIC)) { 19497c478bd9Sstevel@tonic-gate /* has not login - no need to go any further */ 19507c478bd9Sstevel@tonic-gate (void) lock_file(ks_fd, B_TRUE, B_FALSE); 19517c478bd9Sstevel@tonic-gate (void) close(ks_fd); 19527c478bd9Sstevel@tonic-gate return (CKR_OK); 19537c478bd9Sstevel@tonic-gate } 19547c478bd9Sstevel@tonic-gate 19557c478bd9Sstevel@tonic-gate ks_handle.public = B_FALSE; 19567c478bd9Sstevel@tonic-gate 19577c478bd9Sstevel@tonic-gate if ((dirp = opendir(get_pri_obj_path(pri_obj_path))) == NULL) { 19587c478bd9Sstevel@tonic-gate (void) lock_file(ks_fd, B_TRUE, B_FALSE); 19597c478bd9Sstevel@tonic-gate (void) close(ks_fd); 19607c478bd9Sstevel@tonic-gate return (CKR_OK); 19617c478bd9Sstevel@tonic-gate } 19627c478bd9Sstevel@tonic-gate rv = get_all_objs_in_dir(dirp, &ks_handle, result_obj_list, 19634bc0a2efScasper lock_held); 19647c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 19657c478bd9Sstevel@tonic-gate (void) closedir(dirp); 19667c478bd9Sstevel@tonic-gate goto cleanup; 19677c478bd9Sstevel@tonic-gate } 19687c478bd9Sstevel@tonic-gate 19697c478bd9Sstevel@tonic-gate (void) closedir(dirp); 19707c478bd9Sstevel@tonic-gate } 19717c478bd9Sstevel@tonic-gate /* close the keystore description file */ 19727c478bd9Sstevel@tonic-gate (void) lock_file(ks_fd, B_TRUE, B_FALSE); 19737c478bd9Sstevel@tonic-gate (void) close(ks_fd); 19747c478bd9Sstevel@tonic-gate return (CKR_OK); 19757c478bd9Sstevel@tonic-gate cleanup: 19767c478bd9Sstevel@tonic-gate 19777c478bd9Sstevel@tonic-gate /* close the keystore description file */ 19787c478bd9Sstevel@tonic-gate (void) lock_file(ks_fd, B_TRUE, B_FALSE); 19797c478bd9Sstevel@tonic-gate (void) close(ks_fd); 19807c478bd9Sstevel@tonic-gate 19817c478bd9Sstevel@tonic-gate /* free all the objects found before hitting the error */ 19827c478bd9Sstevel@tonic-gate tmp = *result_obj_list; 19837c478bd9Sstevel@tonic-gate while (tmp) { 19847c478bd9Sstevel@tonic-gate *result_obj_list = tmp->next; 19857c478bd9Sstevel@tonic-gate free(tmp->buf); 19867c478bd9Sstevel@tonic-gate free(tmp); 19877c478bd9Sstevel@tonic-gate tmp = *result_obj_list; 19887c478bd9Sstevel@tonic-gate } 19897c478bd9Sstevel@tonic-gate *result_obj_list = NULL; 19907c478bd9Sstevel@tonic-gate return (rv); 19917c478bd9Sstevel@tonic-gate } 19927c478bd9Sstevel@tonic-gate 19937c478bd9Sstevel@tonic-gate 19947c478bd9Sstevel@tonic-gate /* 19957c478bd9Sstevel@tonic-gate * FUNCTION: soft_keystore_get_single_obj 19967c478bd9Sstevel@tonic-gate * 19977c478bd9Sstevel@tonic-gate * ARGUMENTS: 19987c478bd9Sstevel@tonic-gate * ks_handle: handle of the key store object to be accessed 19997c478bd9Sstevel@tonic-gate * lock_held: TRUE if the lock is held by caller. 20007c478bd9Sstevel@tonic-gate * 20017c478bd9Sstevel@tonic-gate * RETURN VALUE: 20027c478bd9Sstevel@tonic-gate * 20037c478bd9Sstevel@tonic-gate * NULL: if handle doesn't match any object 20047c478bd9Sstevel@tonic-gate * 20057c478bd9Sstevel@tonic-gate * Otherwise, the object is returned in 20067c478bd9Sstevel@tonic-gate * the same structure used in soft_keystore_get_objs(). 20077c478bd9Sstevel@tonic-gate * The structure need to be freed by the caller. 20087c478bd9Sstevel@tonic-gate * 20097c478bd9Sstevel@tonic-gate * DESCRIPTION: 20107c478bd9Sstevel@tonic-gate * 20117c478bd9Sstevel@tonic-gate * Retrieves the object specified by the object 20127c478bd9Sstevel@tonic-gate * handle to the caller. 20137c478bd9Sstevel@tonic-gate * 20147c478bd9Sstevel@tonic-gate * If a private object is requested, and the caller 20157c478bd9Sstevel@tonic-gate * has not previously passed in the pin or if the pin 20167c478bd9Sstevel@tonic-gate * passed in is wrong, the requested private object will not 20177c478bd9Sstevel@tonic-gate * be returned. 20187c478bd9Sstevel@tonic-gate * 20197c478bd9Sstevel@tonic-gate * The buffer returned for the requested private object 20207c478bd9Sstevel@tonic-gate * is already decrypted. 20217c478bd9Sstevel@tonic-gate */ 20227c478bd9Sstevel@tonic-gate CK_RV 20237c478bd9Sstevel@tonic-gate soft_keystore_get_single_obj(ks_obj_handle_t *ks_handle, 20247c478bd9Sstevel@tonic-gate ks_obj_t **return_obj, boolean_t lock_held) 20257c478bd9Sstevel@tonic-gate { 20267c478bd9Sstevel@tonic-gate 20277c478bd9Sstevel@tonic-gate ks_obj_t *obj; 20287c478bd9Sstevel@tonic-gate uchar_t iv[OBJ_IV_SIZE], obj_hmac[OBJ_HMAC_SIZE]; 20297c478bd9Sstevel@tonic-gate uchar_t *buf, *decrypted_buf; 20307c478bd9Sstevel@tonic-gate int fd; 20317c478bd9Sstevel@tonic-gate ssize_t nread; 20327c478bd9Sstevel@tonic-gate CK_RV rv = CKR_FUNCTION_FAILED; 20337c478bd9Sstevel@tonic-gate 20347c478bd9Sstevel@tonic-gate if (!(ks_handle->public)) { 20357c478bd9Sstevel@tonic-gate if ((enc_key == NULL) || 20367c478bd9Sstevel@tonic-gate (enc_key->magic_marker != SOFTTOKEN_OBJECT_MAGIC)) { 20377c478bd9Sstevel@tonic-gate return (CKR_FUNCTION_FAILED); 20387c478bd9Sstevel@tonic-gate } 20397c478bd9Sstevel@tonic-gate } 20407c478bd9Sstevel@tonic-gate 20417c478bd9Sstevel@tonic-gate if ((fd = open_and_lock_object_file(ks_handle, O_RDONLY, 20427c478bd9Sstevel@tonic-gate lock_held)) < 0) { 20437c478bd9Sstevel@tonic-gate return (CKR_FUNCTION_FAILED); 20447c478bd9Sstevel@tonic-gate } 20457c478bd9Sstevel@tonic-gate 20467c478bd9Sstevel@tonic-gate obj = malloc(sizeof (ks_obj_t)); 20477c478bd9Sstevel@tonic-gate if (obj == NULL) { 20487c478bd9Sstevel@tonic-gate return (CKR_HOST_MEMORY); 20497c478bd9Sstevel@tonic-gate } 20507c478bd9Sstevel@tonic-gate 20517c478bd9Sstevel@tonic-gate obj->next = NULL; 20527c478bd9Sstevel@tonic-gate 20537c478bd9Sstevel@tonic-gate (void) strcpy((char *)((obj->ks_handle).name), 20547c478bd9Sstevel@tonic-gate (char *)ks_handle->name); 20557c478bd9Sstevel@tonic-gate (obj->ks_handle).public = ks_handle->public; 20567c478bd9Sstevel@tonic-gate 20577c478bd9Sstevel@tonic-gate /* 1st get the version */ 2058*19193bb6SDina K Nimeh if (readn_nointr(fd, &(obj->obj_version), OBJ_VER_SIZE) 20597c478bd9Sstevel@tonic-gate != OBJ_VER_SIZE) { 20607c478bd9Sstevel@tonic-gate goto cleanup; 20617c478bd9Sstevel@tonic-gate } 20627c478bd9Sstevel@tonic-gate obj->obj_version = SWAP32(obj->obj_version); 20637c478bd9Sstevel@tonic-gate 20647c478bd9Sstevel@tonic-gate /* Then, read the IV */ 2065*19193bb6SDina K Nimeh if (readn_nointr(fd, iv, OBJ_IV_SIZE) != OBJ_IV_SIZE) { 20667c478bd9Sstevel@tonic-gate goto cleanup; 20677c478bd9Sstevel@tonic-gate } 20687c478bd9Sstevel@tonic-gate 20697c478bd9Sstevel@tonic-gate /* Then, read the HMAC */ 2070*19193bb6SDina K Nimeh if (readn_nointr(fd, obj_hmac, OBJ_HMAC_SIZE) != OBJ_HMAC_SIZE) { 20717c478bd9Sstevel@tonic-gate goto cleanup; 20727c478bd9Sstevel@tonic-gate } 20737c478bd9Sstevel@tonic-gate 20747c478bd9Sstevel@tonic-gate /* read the object */ 20757c478bd9Sstevel@tonic-gate rv = read_obj_data(fd, (char **)&buf, &nread); 20767c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 20777c478bd9Sstevel@tonic-gate goto cleanup; 20787c478bd9Sstevel@tonic-gate } 20797c478bd9Sstevel@tonic-gate 20807c478bd9Sstevel@tonic-gate if (ks_handle->public) { 20817c478bd9Sstevel@tonic-gate obj->size = nread; 20827c478bd9Sstevel@tonic-gate obj->buf = buf; 20837c478bd9Sstevel@tonic-gate *return_obj = obj; 20847c478bd9Sstevel@tonic-gate } else { 20857c478bd9Sstevel@tonic-gate 20867c478bd9Sstevel@tonic-gate CK_ULONG out_len = 0, hmac_size; 20877c478bd9Sstevel@tonic-gate 20887c478bd9Sstevel@tonic-gate /* verify HMAC of the object, make sure it matches */ 20897c478bd9Sstevel@tonic-gate hmac_size = OBJ_HMAC_SIZE; 20907c478bd9Sstevel@tonic-gate if (soft_keystore_hmac(hmac_key, B_FALSE, buf, 20917c478bd9Sstevel@tonic-gate nread, obj_hmac, &hmac_size) != CKR_OK) { 20927c478bd9Sstevel@tonic-gate free(buf); 20937c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED; 20947c478bd9Sstevel@tonic-gate goto cleanup; 20957c478bd9Sstevel@tonic-gate } 20967c478bd9Sstevel@tonic-gate 20977c478bd9Sstevel@tonic-gate /* decrypt object */ 20987c478bd9Sstevel@tonic-gate if (soft_keystore_crypt(enc_key, iv, B_FALSE, buf, nread, 20997c478bd9Sstevel@tonic-gate NULL, &out_len) != CKR_OK) { 21007c478bd9Sstevel@tonic-gate free(buf); 21017c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED; 21027c478bd9Sstevel@tonic-gate goto cleanup; 21037c478bd9Sstevel@tonic-gate } 21047c478bd9Sstevel@tonic-gate 21057c478bd9Sstevel@tonic-gate decrypted_buf = malloc(sizeof (uchar_t) * out_len); 21067c478bd9Sstevel@tonic-gate if (decrypted_buf == NULL) { 21077c478bd9Sstevel@tonic-gate free(buf); 21087c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY; 21097c478bd9Sstevel@tonic-gate goto cleanup; 21107c478bd9Sstevel@tonic-gate } 21117c478bd9Sstevel@tonic-gate 21127c478bd9Sstevel@tonic-gate if (soft_keystore_crypt(enc_key, iv, B_FALSE, buf, nread, 21137c478bd9Sstevel@tonic-gate decrypted_buf, &out_len) != CKR_OK) { 21147c478bd9Sstevel@tonic-gate free(decrypted_buf); 21157c478bd9Sstevel@tonic-gate free(buf); 21167c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED; 21177c478bd9Sstevel@tonic-gate goto cleanup; 21187c478bd9Sstevel@tonic-gate } 21197c478bd9Sstevel@tonic-gate 21207c478bd9Sstevel@tonic-gate obj->size = out_len - MAXPATHLEN; 21217c478bd9Sstevel@tonic-gate 21227c478bd9Sstevel@tonic-gate /* 21237c478bd9Sstevel@tonic-gate * decrypted buf here actually contains full path name of 21247c478bd9Sstevel@tonic-gate * object plus the actual data. so, need to skip the 21257c478bd9Sstevel@tonic-gate * full pathname. 21267c478bd9Sstevel@tonic-gate * See prepare_data_for_encrypt() function in the file 21277c478bd9Sstevel@tonic-gate * to understand how and why the pathname is added. 21287c478bd9Sstevel@tonic-gate */ 21297c478bd9Sstevel@tonic-gate obj->buf = malloc(sizeof (uchar_t) * (out_len - MAXPATHLEN)); 21307c478bd9Sstevel@tonic-gate if (obj->buf == NULL) { 21317c478bd9Sstevel@tonic-gate free(decrypted_buf); 21327c478bd9Sstevel@tonic-gate free(buf); 21337c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY; 21347c478bd9Sstevel@tonic-gate goto cleanup; 21357c478bd9Sstevel@tonic-gate } 21367c478bd9Sstevel@tonic-gate (void) memcpy(obj->buf, decrypted_buf + MAXPATHLEN, obj->size); 21377c478bd9Sstevel@tonic-gate free(decrypted_buf); 21387c478bd9Sstevel@tonic-gate free(buf); 21397c478bd9Sstevel@tonic-gate *return_obj = obj; 21407c478bd9Sstevel@tonic-gate } 21417c478bd9Sstevel@tonic-gate 21427c478bd9Sstevel@tonic-gate cleanup: 21437c478bd9Sstevel@tonic-gate 21447c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 21457c478bd9Sstevel@tonic-gate free(obj); 21467c478bd9Sstevel@tonic-gate } 21477c478bd9Sstevel@tonic-gate 21487c478bd9Sstevel@tonic-gate /* unlock the file after reading */ 21497c478bd9Sstevel@tonic-gate if (!lock_held) { 21507c478bd9Sstevel@tonic-gate (void) lock_file(fd, B_TRUE, B_FALSE); 21517c478bd9Sstevel@tonic-gate } 21527c478bd9Sstevel@tonic-gate 21537c478bd9Sstevel@tonic-gate (void) close(fd); 21547c478bd9Sstevel@tonic-gate 21557c478bd9Sstevel@tonic-gate return (rv); 21567c478bd9Sstevel@tonic-gate } 21577c478bd9Sstevel@tonic-gate 21587c478bd9Sstevel@tonic-gate 21597c478bd9Sstevel@tonic-gate /* 21607c478bd9Sstevel@tonic-gate * FUNCTION: soft_keystore_put_new_obj 21617c478bd9Sstevel@tonic-gate * 21627c478bd9Sstevel@tonic-gate * ARGUMENTS: 21637c478bd9Sstevel@tonic-gate * buf: buffer containing un-encrypted data 21647c478bd9Sstevel@tonic-gate * to be stored in keystore. 21657c478bd9Sstevel@tonic-gate * len: length of data 21667c478bd9Sstevel@tonic-gate * public: TRUE if it is a public object, 21677c478bd9Sstevel@tonic-gate * FALSE if it is private obj 21687c478bd9Sstevel@tonic-gate * lock_held: TRUE if the lock is held by caller. 21697c478bd9Sstevel@tonic-gate * keyhandle: pointer to object handle to 21707c478bd9Sstevel@tonic-gate * receive keyhandle for new object 21717c478bd9Sstevel@tonic-gate * 21727c478bd9Sstevel@tonic-gate * RETURN VALUE: 21737c478bd9Sstevel@tonic-gate * 0: object successfully stored in file 21747c478bd9Sstevel@tonic-gate * -1: some error occurred, object is not stored in file. 21757c478bd9Sstevel@tonic-gate * 21767c478bd9Sstevel@tonic-gate * DESCRIPTION: 21777c478bd9Sstevel@tonic-gate * This API is used to write a newly created token object 21787c478bd9Sstevel@tonic-gate * to keystore. 21797c478bd9Sstevel@tonic-gate * 21807c478bd9Sstevel@tonic-gate * This function does the following: 21817c478bd9Sstevel@tonic-gate * 21827c478bd9Sstevel@tonic-gate * 1) Creates a token object file based on "public" parameter. 21837c478bd9Sstevel@tonic-gate * 2) Generates a new IV and stores it in obj_meta_data_t if it is 21847c478bd9Sstevel@tonic-gate * private object. 21857c478bd9Sstevel@tonic-gate * 3) Set object version number to 1. 21867c478bd9Sstevel@tonic-gate * 4) If it is a private object, it will be encrypted before 21877c478bd9Sstevel@tonic-gate * being written to the newly created keystore token object 21887c478bd9Sstevel@tonic-gate * file. 21897c478bd9Sstevel@tonic-gate * 5) Calculates the obj_chksum in obj_meta_data_t. 21907c478bd9Sstevel@tonic-gate * 6) Calculates the pin_chksum in obj_meta_data_t. 21917c478bd9Sstevel@tonic-gate * 7) Increments the keystore version number. 21927c478bd9Sstevel@tonic-gate */ 21937c478bd9Sstevel@tonic-gate int 21947c478bd9Sstevel@tonic-gate soft_keystore_put_new_obj(uchar_t *buf, size_t len, boolean_t public, 21957c478bd9Sstevel@tonic-gate boolean_t lock_held, ks_obj_handle_t *keyhandle) 21967c478bd9Sstevel@tonic-gate { 21977c478bd9Sstevel@tonic-gate 21987c478bd9Sstevel@tonic-gate int fd, tmp_ks_fd, obj_fd; 21997c478bd9Sstevel@tonic-gate unsigned int counter, version; 22007c478bd9Sstevel@tonic-gate uchar_t obj_hmac[OBJ_HMAC_SIZE]; 22017c478bd9Sstevel@tonic-gate CK_BYTE iv[OBJ_IV_SIZE]; 22027c478bd9Sstevel@tonic-gate char obj_name[MAXPATHLEN], tmp_ks_desc_name[MAXPATHLEN]; 22037c478bd9Sstevel@tonic-gate char filebuf[BUFSIZ]; 22047c478bd9Sstevel@tonic-gate char pub_obj_path[MAXPATHLEN], pri_obj_path[MAXPATHLEN], 22057c478bd9Sstevel@tonic-gate ks_desc_file[MAXPATHLEN]; 22067c478bd9Sstevel@tonic-gate CK_ULONG hmac_size; 22077c478bd9Sstevel@tonic-gate ssize_t nread; 22087c478bd9Sstevel@tonic-gate 22097c478bd9Sstevel@tonic-gate if (keyhandle == NULL) { 22107c478bd9Sstevel@tonic-gate return (-1); 22117c478bd9Sstevel@tonic-gate } 22127c478bd9Sstevel@tonic-gate 22137c478bd9Sstevel@tonic-gate /* if it is private object, make sure we have the key */ 22147c478bd9Sstevel@tonic-gate if (!public) { 22157c478bd9Sstevel@tonic-gate if ((enc_key == NULL) || 22167c478bd9Sstevel@tonic-gate (enc_key->magic_marker != SOFTTOKEN_OBJECT_MAGIC)) { 22177c478bd9Sstevel@tonic-gate return (-1); 22187c478bd9Sstevel@tonic-gate } 22197c478bd9Sstevel@tonic-gate } 22207c478bd9Sstevel@tonic-gate 22217c478bd9Sstevel@tonic-gate /* open keystore, and set write lock */ 22227c478bd9Sstevel@tonic-gate if ((fd = open_and_lock_keystore_desc(O_RDWR, B_TRUE, 22237c478bd9Sstevel@tonic-gate lock_held)) < 0) { 22247c478bd9Sstevel@tonic-gate return (-1); 22257c478bd9Sstevel@tonic-gate } 22267c478bd9Sstevel@tonic-gate 22277c478bd9Sstevel@tonic-gate (void) get_desc_file_path(ks_desc_file); 22287c478bd9Sstevel@tonic-gate (void) get_tmp_desc_file_path(tmp_ks_desc_name); 22297c478bd9Sstevel@tonic-gate 22307c478bd9Sstevel@tonic-gate /* 22317c478bd9Sstevel@tonic-gate * create a tempoary file for the keystore description 22327c478bd9Sstevel@tonic-gate * file for updating version and counter information 22337c478bd9Sstevel@tonic-gate */ 2234*19193bb6SDina K Nimeh tmp_ks_fd = open_nointr(tmp_ks_desc_name, 2235*19193bb6SDina K Nimeh O_RDWR|O_CREAT|O_EXCL|O_NONBLOCK, S_IRUSR|S_IWUSR); 22367c478bd9Sstevel@tonic-gate if (tmp_ks_fd < 0) { 22377c478bd9Sstevel@tonic-gate (void) close(fd); 22387c478bd9Sstevel@tonic-gate return (-1); 22397c478bd9Sstevel@tonic-gate } 22407c478bd9Sstevel@tonic-gate 22417c478bd9Sstevel@tonic-gate /* read and write pkcs11 version */ 2242*19193bb6SDina K Nimeh if (readn_nointr(fd, filebuf, KS_PKCS11_VER_SIZE) 22437c478bd9Sstevel@tonic-gate != KS_PKCS11_VER_SIZE) { 22447c478bd9Sstevel@tonic-gate goto cleanup; 22457c478bd9Sstevel@tonic-gate } 22467c478bd9Sstevel@tonic-gate 2247*19193bb6SDina K Nimeh if (writen_nointr(tmp_ks_fd, filebuf, KS_PKCS11_VER_SIZE) 22487c478bd9Sstevel@tonic-gate != KS_PKCS11_VER_SIZE) { 22497c478bd9Sstevel@tonic-gate goto cleanup; 22507c478bd9Sstevel@tonic-gate } 22517c478bd9Sstevel@tonic-gate 22527c478bd9Sstevel@tonic-gate /* get version number, and write updated number to temp file */ 2253*19193bb6SDina K Nimeh if (readn_nointr(fd, &version, KS_VER_SIZE) != KS_VER_SIZE) { 22547c478bd9Sstevel@tonic-gate goto cleanup; 22557c478bd9Sstevel@tonic-gate } 22567c478bd9Sstevel@tonic-gate 22577c478bd9Sstevel@tonic-gate version = SWAP32(version); 22587c478bd9Sstevel@tonic-gate version++; 22597c478bd9Sstevel@tonic-gate version = SWAP32(version); 22607c478bd9Sstevel@tonic-gate 2261*19193bb6SDina K Nimeh if (writen_nointr(tmp_ks_fd, (void *)&version, 22627c478bd9Sstevel@tonic-gate KS_VER_SIZE) != KS_VER_SIZE) { 22637c478bd9Sstevel@tonic-gate goto cleanup; 22647c478bd9Sstevel@tonic-gate } 22657c478bd9Sstevel@tonic-gate 22667c478bd9Sstevel@tonic-gate /* get object count value */ 2267*19193bb6SDina K Nimeh if (readn_nointr(fd, &counter, KS_COUNTER_SIZE) != KS_COUNTER_SIZE) { 22687c478bd9Sstevel@tonic-gate goto cleanup; 22697c478bd9Sstevel@tonic-gate } 22707c478bd9Sstevel@tonic-gate counter = SWAP32(counter); 22717c478bd9Sstevel@tonic-gate 22727c478bd9Sstevel@tonic-gate bzero(obj_name, sizeof (obj_name)); 22737c478bd9Sstevel@tonic-gate if (public) { 22747c478bd9Sstevel@tonic-gate (void) snprintf(obj_name, MAXPATHLEN, "%s/%s%d", 22757c478bd9Sstevel@tonic-gate get_pub_obj_path(pub_obj_path), OBJ_PREFIX, counter); 22767c478bd9Sstevel@tonic-gate } else { 22777c478bd9Sstevel@tonic-gate (void) snprintf(obj_name, MAXPATHLEN, "%s/%s%d", 22787c478bd9Sstevel@tonic-gate get_pri_obj_path(pri_obj_path), OBJ_PREFIX, counter); 22797c478bd9Sstevel@tonic-gate } 22807c478bd9Sstevel@tonic-gate 22817c478bd9Sstevel@tonic-gate /* create object file */ 2282*19193bb6SDina K Nimeh obj_fd = open_nointr(obj_name, 2283*19193bb6SDina K Nimeh O_WRONLY|O_CREAT|O_EXCL|O_NONBLOCK, S_IRUSR|S_IWUSR); 22847c478bd9Sstevel@tonic-gate if (obj_fd < 0) { 22857c478bd9Sstevel@tonic-gate /* can't create object file */ 22867c478bd9Sstevel@tonic-gate goto cleanup; 22877c478bd9Sstevel@tonic-gate } 22887c478bd9Sstevel@tonic-gate 22897c478bd9Sstevel@tonic-gate /* lock object file for writing */ 22907c478bd9Sstevel@tonic-gate if (lock_file(obj_fd, B_FALSE, B_TRUE) != 0) { 22917c478bd9Sstevel@tonic-gate (void) close(obj_fd); 22927c478bd9Sstevel@tonic-gate goto cleanup2; 22937c478bd9Sstevel@tonic-gate } 22947c478bd9Sstevel@tonic-gate 22957c478bd9Sstevel@tonic-gate /* write object meta data */ 22967c478bd9Sstevel@tonic-gate version = SWAP32(1); 2297*19193bb6SDina K Nimeh if (writen_nointr(obj_fd, (void *)&version, sizeof (version)) 22987c478bd9Sstevel@tonic-gate != sizeof (version)) { 22997c478bd9Sstevel@tonic-gate goto cleanup2; 23007c478bd9Sstevel@tonic-gate } 23017c478bd9Sstevel@tonic-gate 23027c478bd9Sstevel@tonic-gate if (public) { 23037c478bd9Sstevel@tonic-gate bzero(iv, sizeof (iv)); 23047c478bd9Sstevel@tonic-gate } else { 23057c478bd9Sstevel@tonic-gate /* generate an IV */ 23067c478bd9Sstevel@tonic-gate if (soft_gen_iv(iv) != CKR_OK) { 23077c478bd9Sstevel@tonic-gate goto cleanup2; 23087c478bd9Sstevel@tonic-gate } 23097c478bd9Sstevel@tonic-gate 23107c478bd9Sstevel@tonic-gate } 23117c478bd9Sstevel@tonic-gate 2312*19193bb6SDina K Nimeh if (writen_nointr(obj_fd, (void *)iv, sizeof (iv)) != sizeof (iv)) { 23137c478bd9Sstevel@tonic-gate goto cleanup2; 23147c478bd9Sstevel@tonic-gate } 23157c478bd9Sstevel@tonic-gate 23167c478bd9Sstevel@tonic-gate if (public) { 23177c478bd9Sstevel@tonic-gate 23187c478bd9Sstevel@tonic-gate bzero(obj_hmac, sizeof (obj_hmac)); 2319*19193bb6SDina K Nimeh if (writen_nointr(obj_fd, (void *)obj_hmac, 23207c478bd9Sstevel@tonic-gate sizeof (obj_hmac)) != sizeof (obj_hmac)) { 23217c478bd9Sstevel@tonic-gate goto cleanup2; 23227c478bd9Sstevel@tonic-gate } 23237c478bd9Sstevel@tonic-gate 2324*19193bb6SDina K Nimeh if (writen_nointr(obj_fd, (char *)buf, len) != len) { 23257c478bd9Sstevel@tonic-gate goto cleanup2; 23267c478bd9Sstevel@tonic-gate } 23277c478bd9Sstevel@tonic-gate 23287c478bd9Sstevel@tonic-gate } else { 23297c478bd9Sstevel@tonic-gate 23307c478bd9Sstevel@tonic-gate uchar_t *encrypted_buf, *prepared_buf; 23317c478bd9Sstevel@tonic-gate CK_ULONG out_len = 0, prepared_len; 23327c478bd9Sstevel@tonic-gate 23337c478bd9Sstevel@tonic-gate if (prepare_data_for_encrypt(obj_name, buf, len, 23347c478bd9Sstevel@tonic-gate &prepared_buf, &prepared_len) != 0) { 23357c478bd9Sstevel@tonic-gate goto cleanup2; 23367c478bd9Sstevel@tonic-gate } 23377c478bd9Sstevel@tonic-gate 23387c478bd9Sstevel@tonic-gate if (soft_keystore_crypt(enc_key, iv, 23397c478bd9Sstevel@tonic-gate B_TRUE, prepared_buf, prepared_len, 23407c478bd9Sstevel@tonic-gate NULL, &out_len) != CKR_OK) { 23417c478bd9Sstevel@tonic-gate free(prepared_buf); 23427c478bd9Sstevel@tonic-gate goto cleanup2; 23437c478bd9Sstevel@tonic-gate } 23447c478bd9Sstevel@tonic-gate 23457c478bd9Sstevel@tonic-gate encrypted_buf = malloc(out_len * sizeof (char)); 23467c478bd9Sstevel@tonic-gate if (encrypted_buf == NULL) { 23477c478bd9Sstevel@tonic-gate free(prepared_buf); 23487c478bd9Sstevel@tonic-gate goto cleanup2; 23497c478bd9Sstevel@tonic-gate } 23507c478bd9Sstevel@tonic-gate 23517c478bd9Sstevel@tonic-gate if (soft_keystore_crypt(enc_key, iv, 23527c478bd9Sstevel@tonic-gate B_TRUE, prepared_buf, prepared_len, 23537c478bd9Sstevel@tonic-gate encrypted_buf, &out_len) != CKR_OK) { 23547c478bd9Sstevel@tonic-gate free(encrypted_buf); 23557c478bd9Sstevel@tonic-gate free(prepared_buf); 23567c478bd9Sstevel@tonic-gate goto cleanup2; 23577c478bd9Sstevel@tonic-gate } 23587c478bd9Sstevel@tonic-gate free(prepared_buf); 23597c478bd9Sstevel@tonic-gate 23607c478bd9Sstevel@tonic-gate /* calculate HMAC of encrypted object */ 23617c478bd9Sstevel@tonic-gate hmac_size = OBJ_HMAC_SIZE; 23627c478bd9Sstevel@tonic-gate if (soft_keystore_hmac(hmac_key, B_TRUE, encrypted_buf, 23637c478bd9Sstevel@tonic-gate out_len, obj_hmac, &hmac_size) != CKR_OK) { 23647c478bd9Sstevel@tonic-gate free(encrypted_buf); 23657c478bd9Sstevel@tonic-gate goto cleanup2; 23667c478bd9Sstevel@tonic-gate } 23677c478bd9Sstevel@tonic-gate 23687c478bd9Sstevel@tonic-gate if (hmac_size != OBJ_HMAC_SIZE) { 23697c478bd9Sstevel@tonic-gate free(encrypted_buf); 23707c478bd9Sstevel@tonic-gate goto cleanup2; 23717c478bd9Sstevel@tonic-gate } 23727c478bd9Sstevel@tonic-gate 23737c478bd9Sstevel@tonic-gate /* write hmac */ 2374*19193bb6SDina K Nimeh if (writen_nointr(obj_fd, (void *)obj_hmac, 23757c478bd9Sstevel@tonic-gate sizeof (obj_hmac)) != sizeof (obj_hmac)) { 23767c478bd9Sstevel@tonic-gate free(encrypted_buf); 23777c478bd9Sstevel@tonic-gate goto cleanup2; 23787c478bd9Sstevel@tonic-gate } 23797c478bd9Sstevel@tonic-gate 23807c478bd9Sstevel@tonic-gate /* write encrypted object */ 2381*19193bb6SDina K Nimeh if (writen_nointr(obj_fd, (void *)encrypted_buf, out_len) 23827c478bd9Sstevel@tonic-gate != out_len) { 23837c478bd9Sstevel@tonic-gate free(encrypted_buf); 23847c478bd9Sstevel@tonic-gate goto cleanup2; 23857c478bd9Sstevel@tonic-gate } 23867c478bd9Sstevel@tonic-gate 23877c478bd9Sstevel@tonic-gate free(encrypted_buf); 23887c478bd9Sstevel@tonic-gate } 23897c478bd9Sstevel@tonic-gate 23907c478bd9Sstevel@tonic-gate 23917c478bd9Sstevel@tonic-gate (void) close(obj_fd); 23927c478bd9Sstevel@tonic-gate (void) snprintf((char *)keyhandle->name, sizeof (keyhandle->name), 23937c478bd9Sstevel@tonic-gate "obj%d", counter); 23947c478bd9Sstevel@tonic-gate keyhandle->public = public; 23957c478bd9Sstevel@tonic-gate 23967c478bd9Sstevel@tonic-gate /* 23977c478bd9Sstevel@tonic-gate * store new counter to temp keystore description file. 23987c478bd9Sstevel@tonic-gate */ 23997c478bd9Sstevel@tonic-gate counter++; 24007c478bd9Sstevel@tonic-gate counter = SWAP32(counter); 2401*19193bb6SDina K Nimeh if (writen_nointr(tmp_ks_fd, (void *)&counter, 24027c478bd9Sstevel@tonic-gate sizeof (counter)) != sizeof (counter)) { 24037c478bd9Sstevel@tonic-gate goto cleanup2; 24047c478bd9Sstevel@tonic-gate } 24057c478bd9Sstevel@tonic-gate 24067c478bd9Sstevel@tonic-gate /* read rest of keystore description file and store into temp file */ 2407*19193bb6SDina K Nimeh nread = readn_nointr(fd, filebuf, sizeof (filebuf)); 24087c478bd9Sstevel@tonic-gate while (nread > 0) { 2409*19193bb6SDina K Nimeh if (writen_nointr(tmp_ks_fd, filebuf, nread) != nread) { 24107c478bd9Sstevel@tonic-gate goto cleanup2; 24117c478bd9Sstevel@tonic-gate } 2412*19193bb6SDina K Nimeh nread = readn_nointr(fd, filebuf, sizeof (filebuf)); 24137c478bd9Sstevel@tonic-gate } 24147c478bd9Sstevel@tonic-gate 24157c478bd9Sstevel@tonic-gate (void) close(tmp_ks_fd); 24167c478bd9Sstevel@tonic-gate (void) rename(tmp_ks_desc_name, ks_desc_file); 24177c478bd9Sstevel@tonic-gate 24187c478bd9Sstevel@tonic-gate if (!lock_held) { 24197c478bd9Sstevel@tonic-gate /* release lock on description file */ 24207c478bd9Sstevel@tonic-gate if (lock_file(fd, B_FALSE, B_FALSE) != 0) { 24217c478bd9Sstevel@tonic-gate (void) close(fd); 24227c478bd9Sstevel@tonic-gate return (-1); 24237c478bd9Sstevel@tonic-gate } 24247c478bd9Sstevel@tonic-gate } 24257c478bd9Sstevel@tonic-gate (void) close(fd); 24267c478bd9Sstevel@tonic-gate return (0); 24277c478bd9Sstevel@tonic-gate 24287c478bd9Sstevel@tonic-gate cleanup2: 24297c478bd9Sstevel@tonic-gate 24307c478bd9Sstevel@tonic-gate /* remove object file. No need to remove lock first */ 24317c478bd9Sstevel@tonic-gate (void) unlink(obj_name); 24327c478bd9Sstevel@tonic-gate 24337c478bd9Sstevel@tonic-gate cleanup: 24347c478bd9Sstevel@tonic-gate 24357c478bd9Sstevel@tonic-gate (void) close(tmp_ks_fd); 24367c478bd9Sstevel@tonic-gate (void) remove(tmp_ks_desc_name); 24377c478bd9Sstevel@tonic-gate if (!lock_held) { 24387c478bd9Sstevel@tonic-gate /* release lock on description file */ 24397c478bd9Sstevel@tonic-gate (void) lock_file(fd, B_FALSE, B_FALSE); 24407c478bd9Sstevel@tonic-gate } 24417c478bd9Sstevel@tonic-gate 24427c478bd9Sstevel@tonic-gate (void) close(fd); 24437c478bd9Sstevel@tonic-gate return (-1); 24447c478bd9Sstevel@tonic-gate } 24457c478bd9Sstevel@tonic-gate 24467c478bd9Sstevel@tonic-gate /* 24477c478bd9Sstevel@tonic-gate * FUNCTION: soft_keystore_modify_obj 24487c478bd9Sstevel@tonic-gate * 24497c478bd9Sstevel@tonic-gate * ARGUMENTS: 24507c478bd9Sstevel@tonic-gate * ks_handle: handle of the key store object to be modified 24517c478bd9Sstevel@tonic-gate * buf: buffer containing un-encrypted data 24527c478bd9Sstevel@tonic-gate * to be modified in keystore. 24537c478bd9Sstevel@tonic-gate * len: length of data 24547c478bd9Sstevel@tonic-gate * lock_held: TRUE if the lock is held by caller. 24557c478bd9Sstevel@tonic-gate * 24567c478bd9Sstevel@tonic-gate * RETURN VALUE: 24577c478bd9Sstevel@tonic-gate * -1: if any error occurred. 24587c478bd9Sstevel@tonic-gate * Otherwise, 0 is returned. 24597c478bd9Sstevel@tonic-gate * 24607c478bd9Sstevel@tonic-gate * DESCRIPTION: 24617c478bd9Sstevel@tonic-gate * 24627c478bd9Sstevel@tonic-gate * This API is used to write a modified token object back 24637c478bd9Sstevel@tonic-gate * to keystore. This function will do the following: 24647c478bd9Sstevel@tonic-gate * 24657c478bd9Sstevel@tonic-gate * 1) If it is a private object, it will be encrypted before 24667c478bd9Sstevel@tonic-gate * being written to the corresponding keystore token 24677c478bd9Sstevel@tonic-gate * object file. 24687c478bd9Sstevel@tonic-gate * 2) Record incremented object version number. 24697c478bd9Sstevel@tonic-gate * 3) Record incremented keystore version number. 24707c478bd9Sstevel@tonic-gate */ 24717c478bd9Sstevel@tonic-gate int 24727c478bd9Sstevel@tonic-gate soft_keystore_modify_obj(ks_obj_handle_t *ks_handle, uchar_t *buf, 24737c478bd9Sstevel@tonic-gate size_t len, boolean_t lock_held) 24747c478bd9Sstevel@tonic-gate { 24757c478bd9Sstevel@tonic-gate int fd, ks_fd, tmp_fd, version; 24767c478bd9Sstevel@tonic-gate char orig_name[MAXPATHLEN], tmp_name[MAXPATHLEN], 24777c478bd9Sstevel@tonic-gate tmp_ks_name[MAXPATHLEN]; 24787c478bd9Sstevel@tonic-gate uchar_t iv[OBJ_IV_SIZE], obj_hmac[OBJ_HMAC_SIZE]; 24797c478bd9Sstevel@tonic-gate char pub_obj_path[MAXPATHLEN], pri_obj_path[MAXPATHLEN], 24807c478bd9Sstevel@tonic-gate ks_desc_file[MAXPATHLEN]; 24817c478bd9Sstevel@tonic-gate CK_ULONG hmac_size; 24827c478bd9Sstevel@tonic-gate 24837c478bd9Sstevel@tonic-gate /* if it is private object, make sure we have the key */ 24847c478bd9Sstevel@tonic-gate if (!(ks_handle->public)) { 24857c478bd9Sstevel@tonic-gate if ((enc_key == NULL) || 24867c478bd9Sstevel@tonic-gate (enc_key->magic_marker != SOFTTOKEN_OBJECT_MAGIC)) { 24877c478bd9Sstevel@tonic-gate return (-1); 24887c478bd9Sstevel@tonic-gate } 24897c478bd9Sstevel@tonic-gate } 24907c478bd9Sstevel@tonic-gate 24917c478bd9Sstevel@tonic-gate /* open and lock keystore description file */ 24927c478bd9Sstevel@tonic-gate if ((ks_fd = open_and_lock_keystore_desc(O_RDWR, B_FALSE, 24937c478bd9Sstevel@tonic-gate B_FALSE)) < 0) { 24947c478bd9Sstevel@tonic-gate return (-1); 24957c478bd9Sstevel@tonic-gate } 24967c478bd9Sstevel@tonic-gate 24977c478bd9Sstevel@tonic-gate (void) get_desc_file_path(ks_desc_file); 24987c478bd9Sstevel@tonic-gate 24997c478bd9Sstevel@tonic-gate /* update the version of for keystore file in tempoary file */ 25007c478bd9Sstevel@tonic-gate (void) get_tmp_desc_file_path(tmp_ks_name); 25017c478bd9Sstevel@tonic-gate if (create_updated_keystore_version(ks_fd, tmp_ks_name) != 0) { 25027c478bd9Sstevel@tonic-gate /* unlock keystore description file */ 25037c478bd9Sstevel@tonic-gate (void) lock_file(ks_fd, B_FALSE, B_FALSE); 25047c478bd9Sstevel@tonic-gate (void) close(ks_fd); 25057c478bd9Sstevel@tonic-gate return (-1); 25067c478bd9Sstevel@tonic-gate } 25077c478bd9Sstevel@tonic-gate 25087c478bd9Sstevel@tonic-gate /* open object file */ 25097c478bd9Sstevel@tonic-gate if ((fd = open_and_lock_object_file(ks_handle, O_RDWR, 25107c478bd9Sstevel@tonic-gate lock_held)) < 0) { 25117c478bd9Sstevel@tonic-gate goto cleanup; 25127c478bd9Sstevel@tonic-gate } 25137c478bd9Sstevel@tonic-gate 25147c478bd9Sstevel@tonic-gate /* 25157c478bd9Sstevel@tonic-gate * make the change in a temporary file. Create the temp 25167c478bd9Sstevel@tonic-gate * file in the same directory as the token object. That 25177c478bd9Sstevel@tonic-gate * way, the "rename" later will be an atomic operation 25187c478bd9Sstevel@tonic-gate */ 25197c478bd9Sstevel@tonic-gate if (ks_handle->public) { 25207c478bd9Sstevel@tonic-gate (void) snprintf(orig_name, MAXPATHLEN, "%s/%s", 25217c478bd9Sstevel@tonic-gate get_pub_obj_path(pub_obj_path), ks_handle->name); 25227c478bd9Sstevel@tonic-gate (void) snprintf(tmp_name, MAXPATHLEN, "%s/%s%s", 25237c478bd9Sstevel@tonic-gate pub_obj_path, TMP_OBJ_PREFIX, 25247c478bd9Sstevel@tonic-gate (ks_handle->name) + strlen(OBJ_PREFIX)); 25257c478bd9Sstevel@tonic-gate } else { 25267c478bd9Sstevel@tonic-gate (void) snprintf(orig_name, MAXPATHLEN, "%s/%s", 25277c478bd9Sstevel@tonic-gate get_pri_obj_path(pri_obj_path), ks_handle->name); 25287c478bd9Sstevel@tonic-gate (void) snprintf(tmp_name, MAXPATHLEN, "%s/%s%s", 25297c478bd9Sstevel@tonic-gate pri_obj_path, TMP_OBJ_PREFIX, 25307c478bd9Sstevel@tonic-gate (ks_handle->name) + strlen(OBJ_PREFIX)); 25317c478bd9Sstevel@tonic-gate } 25327c478bd9Sstevel@tonic-gate 2533*19193bb6SDina K Nimeh tmp_fd = open_nointr(tmp_name, 2534*19193bb6SDina K Nimeh O_WRONLY|O_CREAT|O_EXCL|O_NONBLOCK, S_IRUSR|S_IWUSR); 25357c478bd9Sstevel@tonic-gate if (tmp_fd < 0) { 25367c478bd9Sstevel@tonic-gate /* can't create tmp object file */ 25377c478bd9Sstevel@tonic-gate goto cleanup1; 25387c478bd9Sstevel@tonic-gate } 25397c478bd9Sstevel@tonic-gate 25407c478bd9Sstevel@tonic-gate /* read version, increment, and write to tmp file */ 2541*19193bb6SDina K Nimeh if (readn_nointr(fd, (char *)&version, OBJ_VER_SIZE) != OBJ_VER_SIZE) { 25427c478bd9Sstevel@tonic-gate goto cleanup2; 25437c478bd9Sstevel@tonic-gate } 25447c478bd9Sstevel@tonic-gate 25457c478bd9Sstevel@tonic-gate version = SWAP32(version); 25467c478bd9Sstevel@tonic-gate version++; 25477c478bd9Sstevel@tonic-gate version = SWAP32(version); 25487c478bd9Sstevel@tonic-gate 2549*19193bb6SDina K Nimeh if (writen_nointr(tmp_fd, (char *)&version, OBJ_VER_SIZE) 25507c478bd9Sstevel@tonic-gate != OBJ_VER_SIZE) { 25517c478bd9Sstevel@tonic-gate goto cleanup2; 25527c478bd9Sstevel@tonic-gate } 25537c478bd9Sstevel@tonic-gate 25547c478bd9Sstevel@tonic-gate /* generate a new IV for the object, old one can be ignored */ 25557c478bd9Sstevel@tonic-gate if (soft_gen_iv(iv) != CKR_OK) { 25567c478bd9Sstevel@tonic-gate goto cleanup2; 25577c478bd9Sstevel@tonic-gate } 25587c478bd9Sstevel@tonic-gate 2559*19193bb6SDina K Nimeh if (writen_nointr(tmp_fd, (char *)iv, OBJ_IV_SIZE) != OBJ_IV_SIZE) { 25607c478bd9Sstevel@tonic-gate goto cleanup2; 25617c478bd9Sstevel@tonic-gate } 25627c478bd9Sstevel@tonic-gate 25637c478bd9Sstevel@tonic-gate if (ks_handle->public) { 25647c478bd9Sstevel@tonic-gate 25657c478bd9Sstevel@tonic-gate /* hmac is always NULL for public objects */ 25667c478bd9Sstevel@tonic-gate bzero(obj_hmac, sizeof (obj_hmac)); 2567*19193bb6SDina K Nimeh if (writen_nointr(tmp_fd, (char *)obj_hmac, OBJ_HMAC_SIZE) 25687c478bd9Sstevel@tonic-gate != OBJ_HMAC_SIZE) { 25697c478bd9Sstevel@tonic-gate goto cleanup2; 25707c478bd9Sstevel@tonic-gate } 25717c478bd9Sstevel@tonic-gate 25727c478bd9Sstevel@tonic-gate /* write updated object */ 2573*19193bb6SDina K Nimeh if (writen_nointr(tmp_fd, (char *)buf, len) != len) { 25747c478bd9Sstevel@tonic-gate goto cleanup2; 25757c478bd9Sstevel@tonic-gate } 25767c478bd9Sstevel@tonic-gate 25777c478bd9Sstevel@tonic-gate } else { 25787c478bd9Sstevel@tonic-gate 25797c478bd9Sstevel@tonic-gate uchar_t *encrypted_buf, *prepared_buf; 25807c478bd9Sstevel@tonic-gate CK_ULONG out_len = 0, prepared_len; 25817c478bd9Sstevel@tonic-gate 25827c478bd9Sstevel@tonic-gate if (prepare_data_for_encrypt(orig_name, buf, len, 25837c478bd9Sstevel@tonic-gate &prepared_buf, &prepared_len) != 0) { 25847c478bd9Sstevel@tonic-gate goto cleanup2; 25857c478bd9Sstevel@tonic-gate } 25867c478bd9Sstevel@tonic-gate 25877c478bd9Sstevel@tonic-gate /* encrypt the data */ 25887c478bd9Sstevel@tonic-gate if (soft_keystore_crypt(enc_key, iv, B_TRUE, prepared_buf, 25897c478bd9Sstevel@tonic-gate prepared_len, NULL, &out_len) != CKR_OK) { 25907c478bd9Sstevel@tonic-gate free(prepared_buf); 25917c478bd9Sstevel@tonic-gate goto cleanup2; 25927c478bd9Sstevel@tonic-gate } 25937c478bd9Sstevel@tonic-gate 25947c478bd9Sstevel@tonic-gate encrypted_buf = malloc(out_len * sizeof (char)); 25957c478bd9Sstevel@tonic-gate if (encrypted_buf == NULL) { 25967c478bd9Sstevel@tonic-gate free(prepared_buf); 25977c478bd9Sstevel@tonic-gate goto cleanup2; 25987c478bd9Sstevel@tonic-gate } 25997c478bd9Sstevel@tonic-gate 26007c478bd9Sstevel@tonic-gate if (soft_keystore_crypt(enc_key, iv, B_TRUE, prepared_buf, 26017c478bd9Sstevel@tonic-gate prepared_len, encrypted_buf, &out_len) != CKR_OK) { 26027c478bd9Sstevel@tonic-gate free(encrypted_buf); 26037c478bd9Sstevel@tonic-gate free(prepared_buf); 26047c478bd9Sstevel@tonic-gate goto cleanup2; 26057c478bd9Sstevel@tonic-gate } 26067c478bd9Sstevel@tonic-gate 26077c478bd9Sstevel@tonic-gate free(prepared_buf); 26087c478bd9Sstevel@tonic-gate 26097c478bd9Sstevel@tonic-gate /* calculate hmac on encrypted buf */ 26107c478bd9Sstevel@tonic-gate hmac_size = OBJ_HMAC_SIZE; 26117c478bd9Sstevel@tonic-gate if (soft_keystore_hmac(hmac_key, B_TRUE, encrypted_buf, 26127c478bd9Sstevel@tonic-gate out_len, obj_hmac, &hmac_size) != CKR_OK) { 26137c478bd9Sstevel@tonic-gate free(encrypted_buf); 26147c478bd9Sstevel@tonic-gate goto cleanup2; 26157c478bd9Sstevel@tonic-gate } 26167c478bd9Sstevel@tonic-gate 26177c478bd9Sstevel@tonic-gate if (hmac_size != OBJ_HMAC_SIZE) { 26187c478bd9Sstevel@tonic-gate free(encrypted_buf); 26197c478bd9Sstevel@tonic-gate goto cleanup2; 26207c478bd9Sstevel@tonic-gate } 26217c478bd9Sstevel@tonic-gate 2622*19193bb6SDina K Nimeh if (writen_nointr(tmp_fd, (char *)obj_hmac, OBJ_HMAC_SIZE) 26237c478bd9Sstevel@tonic-gate != OBJ_HMAC_SIZE) { 26247c478bd9Sstevel@tonic-gate free(encrypted_buf); 26257c478bd9Sstevel@tonic-gate goto cleanup2; 26267c478bd9Sstevel@tonic-gate } 26277c478bd9Sstevel@tonic-gate 2628*19193bb6SDina K Nimeh if (writen_nointr(tmp_fd, (void *)encrypted_buf, out_len) 26297c478bd9Sstevel@tonic-gate != out_len) { 26307c478bd9Sstevel@tonic-gate free(encrypted_buf); 26317c478bd9Sstevel@tonic-gate goto cleanup2; 26327c478bd9Sstevel@tonic-gate } 26337c478bd9Sstevel@tonic-gate free(encrypted_buf); 26347c478bd9Sstevel@tonic-gate } 26357c478bd9Sstevel@tonic-gate (void) close(tmp_fd); 26367c478bd9Sstevel@tonic-gate 26377c478bd9Sstevel@tonic-gate /* rename updated temporary object file */ 26387c478bd9Sstevel@tonic-gate if (rename(tmp_name, orig_name) != 0) { 26397c478bd9Sstevel@tonic-gate (void) unlink(tmp_name); 26407c478bd9Sstevel@tonic-gate return (-1); 26417c478bd9Sstevel@tonic-gate } 26427c478bd9Sstevel@tonic-gate 26437c478bd9Sstevel@tonic-gate /* rename updated keystore description file */ 26447c478bd9Sstevel@tonic-gate if (rename(tmp_ks_name, ks_desc_file) != 0) { 26457c478bd9Sstevel@tonic-gate (void) unlink(tmp_name); 26467c478bd9Sstevel@tonic-gate (void) unlink(tmp_ks_name); 26477c478bd9Sstevel@tonic-gate return (-1); 26487c478bd9Sstevel@tonic-gate } 26497c478bd9Sstevel@tonic-gate 26507c478bd9Sstevel@tonic-gate /* determine need to unlock file or not */ 26517c478bd9Sstevel@tonic-gate if (!lock_held) { 26527c478bd9Sstevel@tonic-gate if (lock_file(fd, B_FALSE, B_FALSE) < 0) { 26537c478bd9Sstevel@tonic-gate (void) close(fd); 26547c478bd9Sstevel@tonic-gate (void) unlink(tmp_name); 26557c478bd9Sstevel@tonic-gate return (-1); 26567c478bd9Sstevel@tonic-gate } 26577c478bd9Sstevel@tonic-gate } 26587c478bd9Sstevel@tonic-gate 26597c478bd9Sstevel@tonic-gate /* unlock keystore description file */ 26607c478bd9Sstevel@tonic-gate if (lock_file(ks_fd, B_FALSE, B_FALSE) != 0) { 26617c478bd9Sstevel@tonic-gate (void) close(ks_fd); 26627c478bd9Sstevel@tonic-gate (void) close(fd); 26637c478bd9Sstevel@tonic-gate return (-1); 26647c478bd9Sstevel@tonic-gate } 26657c478bd9Sstevel@tonic-gate 26667c478bd9Sstevel@tonic-gate (void) close(ks_fd); 26677c478bd9Sstevel@tonic-gate 26687c478bd9Sstevel@tonic-gate (void) close(fd); 26697c478bd9Sstevel@tonic-gate 26707c478bd9Sstevel@tonic-gate return (0); /* All operations completed successfully */ 26717c478bd9Sstevel@tonic-gate 26727c478bd9Sstevel@tonic-gate cleanup2: 26737c478bd9Sstevel@tonic-gate (void) close(tmp_fd); 26747c478bd9Sstevel@tonic-gate (void) remove(tmp_name); 26757c478bd9Sstevel@tonic-gate 26767c478bd9Sstevel@tonic-gate cleanup1: 26777c478bd9Sstevel@tonic-gate (void) close(fd); 26787c478bd9Sstevel@tonic-gate 26797c478bd9Sstevel@tonic-gate cleanup: 26807c478bd9Sstevel@tonic-gate /* unlock keystore description file */ 26817c478bd9Sstevel@tonic-gate (void) lock_file(ks_fd, B_FALSE, B_FALSE); 26827c478bd9Sstevel@tonic-gate (void) close(ks_fd); 26837c478bd9Sstevel@tonic-gate (void) remove(tmp_ks_name); 26847c478bd9Sstevel@tonic-gate return (-1); 26857c478bd9Sstevel@tonic-gate } 26867c478bd9Sstevel@tonic-gate 26877c478bd9Sstevel@tonic-gate /* 26887c478bd9Sstevel@tonic-gate * FUNCTION: soft_keystore_del_obj 26897c478bd9Sstevel@tonic-gate * 26907c478bd9Sstevel@tonic-gate * ARGUMENTS: 26917c478bd9Sstevel@tonic-gate * ks_handle: handle of the key store object to be deleted 26927c478bd9Sstevel@tonic-gate * lock_held: TRUE if the lock is held by caller. 26937c478bd9Sstevel@tonic-gate * 26947c478bd9Sstevel@tonic-gate * RETURN VALUE: 26957c478bd9Sstevel@tonic-gate * -1: if any error occurred. 26967c478bd9Sstevel@tonic-gate * 0: object successfully deleted from keystore. 26977c478bd9Sstevel@tonic-gate * 26987c478bd9Sstevel@tonic-gate * DESCRIPTION: 26997c478bd9Sstevel@tonic-gate * This API is used to delete a particular token object from 27007c478bd9Sstevel@tonic-gate * the keystore. The corresponding token object file will be 27017c478bd9Sstevel@tonic-gate * removed from the file system. 27027c478bd9Sstevel@tonic-gate * Any future reference to the deleted file will 27037c478bd9Sstevel@tonic-gate * return an CKR_OBJECT_HANDLE_INVALID error. 27047c478bd9Sstevel@tonic-gate */ 27057c478bd9Sstevel@tonic-gate int 27067c478bd9Sstevel@tonic-gate soft_keystore_del_obj(ks_obj_handle_t *ks_handle, boolean_t lock_held) 27077c478bd9Sstevel@tonic-gate { 27087c478bd9Sstevel@tonic-gate char objname[MAXPATHLEN], tmp_ks_name[MAXPATHLEN]; 27097c478bd9Sstevel@tonic-gate int fd; 27107c478bd9Sstevel@tonic-gate char pub_obj_path[MAXPATHLEN], pri_obj_path[MAXPATHLEN], 27117c478bd9Sstevel@tonic-gate ks_desc_file[MAXPATHLEN]; 27127c478bd9Sstevel@tonic-gate int ret_val = -1; 27137c478bd9Sstevel@tonic-gate int obj_fd; 27147c478bd9Sstevel@tonic-gate 27157c478bd9Sstevel@tonic-gate if ((fd = open_and_lock_keystore_desc(O_RDWR, B_FALSE, 27167c478bd9Sstevel@tonic-gate lock_held)) < 0) { 27177c478bd9Sstevel@tonic-gate return (-1); 27187c478bd9Sstevel@tonic-gate } 27197c478bd9Sstevel@tonic-gate 27207c478bd9Sstevel@tonic-gate (void) get_desc_file_path(ks_desc_file); 27217c478bd9Sstevel@tonic-gate (void) get_tmp_desc_file_path(tmp_ks_name); 27227c478bd9Sstevel@tonic-gate if (create_updated_keystore_version(fd, tmp_ks_name) != 0) { 27237c478bd9Sstevel@tonic-gate goto cleanup; 27247c478bd9Sstevel@tonic-gate } 27257c478bd9Sstevel@tonic-gate 27267c478bd9Sstevel@tonic-gate if (ks_handle->public) { 27277c478bd9Sstevel@tonic-gate (void) snprintf(objname, MAXPATHLEN, "%s/%s", 27287c478bd9Sstevel@tonic-gate get_pub_obj_path(pub_obj_path), ks_handle->name); 27297c478bd9Sstevel@tonic-gate } else { 27307c478bd9Sstevel@tonic-gate (void) snprintf(objname, MAXPATHLEN, "%s/%s", 27317c478bd9Sstevel@tonic-gate get_pri_obj_path(pri_obj_path), ks_handle->name); 27327c478bd9Sstevel@tonic-gate } 27337c478bd9Sstevel@tonic-gate 27347c478bd9Sstevel@tonic-gate /* 27357c478bd9Sstevel@tonic-gate * make sure no other process is reading/writing the file 27367c478bd9Sstevel@tonic-gate * by acquiring the lock on the file 27377c478bd9Sstevel@tonic-gate */ 27387c478bd9Sstevel@tonic-gate if ((obj_fd = open_and_lock_object_file(ks_handle, O_WRONLY, 27397c478bd9Sstevel@tonic-gate B_FALSE)) < 0) { 27407c478bd9Sstevel@tonic-gate return (-1); 27417c478bd9Sstevel@tonic-gate } 27427c478bd9Sstevel@tonic-gate 27437c478bd9Sstevel@tonic-gate if (unlink(objname) != 0) { 27447c478bd9Sstevel@tonic-gate (void) lock_file(obj_fd, B_FALSE, B_FALSE); 27457c478bd9Sstevel@tonic-gate (void) close(obj_fd); 27467c478bd9Sstevel@tonic-gate goto cleanup; 27477c478bd9Sstevel@tonic-gate } 27487c478bd9Sstevel@tonic-gate 27497c478bd9Sstevel@tonic-gate (void) lock_file(obj_fd, B_FALSE, B_FALSE); 27507c478bd9Sstevel@tonic-gate (void) close(obj_fd); 27517c478bd9Sstevel@tonic-gate 27527c478bd9Sstevel@tonic-gate if (rename(tmp_ks_name, ks_desc_file) != 0) { 27537c478bd9Sstevel@tonic-gate goto cleanup; 27547c478bd9Sstevel@tonic-gate } 27557c478bd9Sstevel@tonic-gate ret_val = 0; 27567c478bd9Sstevel@tonic-gate 27577c478bd9Sstevel@tonic-gate cleanup: 27587c478bd9Sstevel@tonic-gate /* unlock keystore description file */ 27597c478bd9Sstevel@tonic-gate if (!lock_held) { 27607c478bd9Sstevel@tonic-gate if (lock_file(fd, B_FALSE, B_FALSE) != 0) { 27617c478bd9Sstevel@tonic-gate (void) close(fd); 27627c478bd9Sstevel@tonic-gate return (-1); 27637c478bd9Sstevel@tonic-gate } 27647c478bd9Sstevel@tonic-gate } 27657c478bd9Sstevel@tonic-gate 27667c478bd9Sstevel@tonic-gate (void) close(fd); 27677c478bd9Sstevel@tonic-gate return (ret_val); 27687c478bd9Sstevel@tonic-gate } 27697c478bd9Sstevel@tonic-gate 27707c478bd9Sstevel@tonic-gate /* 27717c478bd9Sstevel@tonic-gate * Get the salt used for generating hashed pin from the 27727c478bd9Sstevel@tonic-gate * keystore description file. 27737c478bd9Sstevel@tonic-gate * 27747c478bd9Sstevel@tonic-gate * The result will be stored in the provided buffer "salt" passed 27757c478bd9Sstevel@tonic-gate * in as an argument. 27767c478bd9Sstevel@tonic-gate * 27777c478bd9Sstevel@tonic-gate * Return 0 if no error, return -1 if there's any error. 27787c478bd9Sstevel@tonic-gate */ 27797c478bd9Sstevel@tonic-gate int 27807c478bd9Sstevel@tonic-gate soft_keystore_get_pin_salt(char **salt) 27817c478bd9Sstevel@tonic-gate { 27827c478bd9Sstevel@tonic-gate int fd, ret_val = -1; 27837c478bd9Sstevel@tonic-gate uint64_t hashed_pin_salt_size; 27847c478bd9Sstevel@tonic-gate 27857c478bd9Sstevel@tonic-gate if ((fd = open_and_lock_keystore_desc(O_RDONLY, B_TRUE, 27867c478bd9Sstevel@tonic-gate B_FALSE)) < 0) { 27877c478bd9Sstevel@tonic-gate return (-1); 27887c478bd9Sstevel@tonic-gate } 27897c478bd9Sstevel@tonic-gate 27907c478bd9Sstevel@tonic-gate if (lseek(fd, KS_HASHED_PIN_SALT_LEN_OFFSET, SEEK_SET) 27917c478bd9Sstevel@tonic-gate != KS_HASHED_PIN_SALT_LEN_OFFSET) { 27927c478bd9Sstevel@tonic-gate goto cleanup; 27937c478bd9Sstevel@tonic-gate } 27947c478bd9Sstevel@tonic-gate 2795*19193bb6SDina K Nimeh if (readn_nointr(fd, (char *)&hashed_pin_salt_size, 27967c478bd9Sstevel@tonic-gate KS_HASHED_PIN_SALT_LEN_SIZE) != KS_HASHED_PIN_SALT_LEN_SIZE) { 27977c478bd9Sstevel@tonic-gate goto cleanup; 27987c478bd9Sstevel@tonic-gate } 27997c478bd9Sstevel@tonic-gate hashed_pin_salt_size = SWAP64(hashed_pin_salt_size); 28007c478bd9Sstevel@tonic-gate 28017c478bd9Sstevel@tonic-gate *salt = malloc(hashed_pin_salt_size + 1); 28027c478bd9Sstevel@tonic-gate if (*salt == NULL) { 28037c478bd9Sstevel@tonic-gate goto cleanup; 28047c478bd9Sstevel@tonic-gate } 28057c478bd9Sstevel@tonic-gate 2806*19193bb6SDina K Nimeh if ((readn_nointr(fd, *salt, hashed_pin_salt_size)) 28077c478bd9Sstevel@tonic-gate != (ssize_t)hashed_pin_salt_size) { 28087c478bd9Sstevel@tonic-gate free(*salt); 28097c478bd9Sstevel@tonic-gate goto cleanup; 28107c478bd9Sstevel@tonic-gate } 28117c478bd9Sstevel@tonic-gate (*salt)[hashed_pin_salt_size] = '\0'; 28127c478bd9Sstevel@tonic-gate 28137c478bd9Sstevel@tonic-gate ret_val = 0; 28147c478bd9Sstevel@tonic-gate 28157c478bd9Sstevel@tonic-gate cleanup: 28167c478bd9Sstevel@tonic-gate if (lock_file(fd, B_TRUE, B_FALSE) < 0) { 28177c478bd9Sstevel@tonic-gate ret_val = -1; 28187c478bd9Sstevel@tonic-gate } 28197c478bd9Sstevel@tonic-gate 28207c478bd9Sstevel@tonic-gate (void) close(fd); 28217c478bd9Sstevel@tonic-gate return (ret_val); 28227c478bd9Sstevel@tonic-gate } 28237c478bd9Sstevel@tonic-gate 28247c478bd9Sstevel@tonic-gate /* 28257c478bd9Sstevel@tonic-gate * FUNCTION: soft_keystore_pin_initialized 28267c478bd9Sstevel@tonic-gate * 28277c478bd9Sstevel@tonic-gate * ARGUMENTS: 28287c478bd9Sstevel@tonic-gate * initialized: This value will be set to true if keystore is 28297c478bd9Sstevel@tonic-gate * initialized, and false otherwise. 28307c478bd9Sstevel@tonic-gate * hashed_pin: If the keystore is initialized, this will contain 28317c478bd9Sstevel@tonic-gate * the hashed pin. It will be NULL if the keystore 28327c478bd9Sstevel@tonic-gate * pin is not initialized. Memory allocated 28337c478bd9Sstevel@tonic-gate * for the hashed pin needs to be freed by 28347c478bd9Sstevel@tonic-gate * the caller. 28357c478bd9Sstevel@tonic-gate * lock_held: TRUE if the lock is held by caller. 28367c478bd9Sstevel@tonic-gate * 28377c478bd9Sstevel@tonic-gate * RETURN VALUE: 28387c478bd9Sstevel@tonic-gate * CKR_OK: No error 28397c478bd9Sstevel@tonic-gate * any other appropriate CKR_value 28407c478bd9Sstevel@tonic-gate * 28417c478bd9Sstevel@tonic-gate * DESCRIPTION: 28427c478bd9Sstevel@tonic-gate * This API is used to determine if the PIN in the keystore 28437c478bd9Sstevel@tonic-gate * has been initialized or not. 28447c478bd9Sstevel@tonic-gate * It makes the determination using the salt for generating the 28457c478bd9Sstevel@tonic-gate * encryption key. The salt is stored in the keystore 28467c478bd9Sstevel@tonic-gate * descryption file. The salt should be all zero if 28477c478bd9Sstevel@tonic-gate * the keystore pin has not been initialized. 28487c478bd9Sstevel@tonic-gate * If the pin has been initialized, it is returned in the 28497c478bd9Sstevel@tonic-gate * hashed_pin argument. 28507c478bd9Sstevel@tonic-gate */ 28517c478bd9Sstevel@tonic-gate CK_RV 28527c478bd9Sstevel@tonic-gate soft_keystore_pin_initialized(boolean_t *initialized, char **hashed_pin, 28537c478bd9Sstevel@tonic-gate boolean_t lock_held) 28547c478bd9Sstevel@tonic-gate { 28557c478bd9Sstevel@tonic-gate int fd; 28567c478bd9Sstevel@tonic-gate CK_BYTE crypt_salt[KS_KEY_SALT_SIZE], tmp_buf[KS_KEY_SALT_SIZE]; 28577c478bd9Sstevel@tonic-gate CK_RV ret_val = CKR_OK; 28587c478bd9Sstevel@tonic-gate 28597c478bd9Sstevel@tonic-gate if ((fd = open_and_lock_keystore_desc(O_RDONLY, B_TRUE, 28607c478bd9Sstevel@tonic-gate lock_held)) < 0) { 28617c478bd9Sstevel@tonic-gate return (CKR_FUNCTION_FAILED); 28627c478bd9Sstevel@tonic-gate } 28637c478bd9Sstevel@tonic-gate 28647c478bd9Sstevel@tonic-gate if (lseek(fd, KS_KEY_SALT_OFFSET, SEEK_SET) != KS_KEY_SALT_OFFSET) { 28657c478bd9Sstevel@tonic-gate ret_val = CKR_FUNCTION_FAILED; 28667c478bd9Sstevel@tonic-gate goto cleanup; 28677c478bd9Sstevel@tonic-gate } 28687c478bd9Sstevel@tonic-gate 2869*19193bb6SDina K Nimeh if (readn_nointr(fd, (char *)crypt_salt, KS_KEY_SALT_SIZE) 28707c478bd9Sstevel@tonic-gate != KS_KEY_SALT_SIZE) { 28717c478bd9Sstevel@tonic-gate ret_val = CKR_FUNCTION_FAILED; 28727c478bd9Sstevel@tonic-gate goto cleanup; 28737c478bd9Sstevel@tonic-gate } 28747c478bd9Sstevel@tonic-gate 28757c478bd9Sstevel@tonic-gate (void) bzero(tmp_buf, KS_KEY_SALT_SIZE); 28767c478bd9Sstevel@tonic-gate 28777c478bd9Sstevel@tonic-gate if (memcmp(crypt_salt, tmp_buf, KS_KEY_SALT_SIZE) == 0) { 28787c478bd9Sstevel@tonic-gate *initialized = B_FALSE; 28797c478bd9Sstevel@tonic-gate hashed_pin = NULL; 28807c478bd9Sstevel@tonic-gate } else { 28817c478bd9Sstevel@tonic-gate *initialized = B_TRUE; 28827c478bd9Sstevel@tonic-gate ret_val = get_hashed_pin(fd, hashed_pin); 28837c478bd9Sstevel@tonic-gate } 28847c478bd9Sstevel@tonic-gate 28857c478bd9Sstevel@tonic-gate cleanup: 28867c478bd9Sstevel@tonic-gate 28877c478bd9Sstevel@tonic-gate if (!lock_held) { 28887c478bd9Sstevel@tonic-gate if (lock_file(fd, B_TRUE, B_FALSE) < 0) { 28897c478bd9Sstevel@tonic-gate ret_val = CKR_FUNCTION_FAILED; 28907c478bd9Sstevel@tonic-gate } 28917c478bd9Sstevel@tonic-gate } 28927c478bd9Sstevel@tonic-gate 28937c478bd9Sstevel@tonic-gate (void) close(fd); 28947c478bd9Sstevel@tonic-gate return (ret_val); 28957c478bd9Sstevel@tonic-gate } 289690e0e8c4Sizick 289790e0e8c4Sizick /* 289890e0e8c4Sizick * This checks if the keystore file exists 289990e0e8c4Sizick */ 290090e0e8c4Sizick 290190e0e8c4Sizick static int 290290e0e8c4Sizick soft_keystore_exists() 290390e0e8c4Sizick { 290490e0e8c4Sizick int ret; 290590e0e8c4Sizick struct stat fn_stat; 290690e0e8c4Sizick char *fname, ks_desc_file[MAXPATHLEN]; 290790e0e8c4Sizick 290890e0e8c4Sizick fname = get_desc_file_path(ks_desc_file); 290990e0e8c4Sizick ret = stat(fname, &fn_stat); 291090e0e8c4Sizick if (ret == 0) 291190e0e8c4Sizick return (0); 291290e0e8c4Sizick return (errno); 291390e0e8c4Sizick } 291490e0e8c4Sizick 291590e0e8c4Sizick /* 291690e0e8c4Sizick * FUNCTION: soft_keystore_init 291790e0e8c4Sizick * 291890e0e8c4Sizick * ARGUMENTS: 291990e0e8c4Sizick * desired_state: The keystore state the caller would like 292090e0e8c4Sizick * it to be. 292190e0e8c4Sizick * 292290e0e8c4Sizick * RETURN VALUE: 292390e0e8c4Sizick * Returns the state the function is in. If it succeeded, it 292490e0e8c4Sizick * will be the same as the desired, if not it will be 292590e0e8c4Sizick * KEYSTORE_UNAVAILABLE. 292690e0e8c4Sizick * 292790e0e8c4Sizick * DESCRIPTION: 292890e0e8c4Sizick * This function will only load as much keystore data as is 292990e0e8c4Sizick * requested at that time. This is for performace by delaying the 293090e0e8c4Sizick * reading of token objects until they are needed or never at 293190e0e8c4Sizick * all if they are not used. 293290e0e8c4Sizick * 293390e0e8c4Sizick * It is only called by soft_keystore_status() when the 293490e0e8c4Sizick * "desired_state" is not the the current load state of keystore. 293590e0e8c4Sizick * 293690e0e8c4Sizick */ 293790e0e8c4Sizick int 293890e0e8c4Sizick soft_keystore_init(int desired_state) 293990e0e8c4Sizick { 294090e0e8c4Sizick int ret; 294190e0e8c4Sizick 294290e0e8c4Sizick (void) pthread_mutex_lock(&soft_slot.keystore_mutex); 294390e0e8c4Sizick 294490e0e8c4Sizick /* 294590e0e8c4Sizick * If more than one session tries to initialize the keystore, the 294690e0e8c4Sizick * second and other following sessions that were waiting for the lock 294790e0e8c4Sizick * will quickly exit if their requirements are satisfied. 294890e0e8c4Sizick */ 294990e0e8c4Sizick if (desired_state <= soft_slot.keystore_load_status) { 295090e0e8c4Sizick (void) pthread_mutex_unlock(&soft_slot.keystore_mutex); 295190e0e8c4Sizick return (soft_slot.keystore_load_status); 295290e0e8c4Sizick } 295390e0e8c4Sizick 295490e0e8c4Sizick /* 295590e0e8c4Sizick * With 'keystore_load_status' giving the current state of the 295690e0e8c4Sizick * process, this switch will bring it up to the desired state if 295790e0e8c4Sizick * possible. 295890e0e8c4Sizick */ 295990e0e8c4Sizick 296090e0e8c4Sizick switch (soft_slot.keystore_load_status) { 296190e0e8c4Sizick case KEYSTORE_UNINITIALIZED: 296290e0e8c4Sizick ret = soft_keystore_exists(); 296390e0e8c4Sizick if (ret == 0) 296490e0e8c4Sizick soft_slot.keystore_load_status = KEYSTORE_PRESENT; 296590e0e8c4Sizick else if (ret == ENOENT) 296690e0e8c4Sizick if (create_keystore() == 0) 296790e0e8c4Sizick soft_slot.keystore_load_status = 296890e0e8c4Sizick KEYSTORE_PRESENT; 296990e0e8c4Sizick else { 297090e0e8c4Sizick soft_slot.keystore_load_status = 297190e0e8c4Sizick KEYSTORE_UNAVAILABLE; 29724c21f043Sizick cryptoerror(LOG_DEBUG, 297390e0e8c4Sizick "pkcs11_softtoken: " 297490e0e8c4Sizick "Cannot create keystore."); 297590e0e8c4Sizick break; 297690e0e8c4Sizick } 297790e0e8c4Sizick 297890e0e8c4Sizick if (desired_state <= KEYSTORE_PRESENT) 297990e0e8c4Sizick break; 298090e0e8c4Sizick 298190e0e8c4Sizick /* FALLTHRU */ 298290e0e8c4Sizick case KEYSTORE_PRESENT: 298390e0e8c4Sizick if (soft_keystore_get_version(&soft_slot.ks_version, B_FALSE) 298490e0e8c4Sizick != 0) { 298590e0e8c4Sizick soft_slot.keystore_load_status = KEYSTORE_UNAVAILABLE; 29864c21f043Sizick cryptoerror(LOG_DEBUG, 29874c21f043Sizick "pkcs11_softtoken: Keystore access failed."); 298890e0e8c4Sizick break; 298990e0e8c4Sizick } 299090e0e8c4Sizick 299190e0e8c4Sizick soft_slot.keystore_load_status = KEYSTORE_VERSION_OK; 299290e0e8c4Sizick if (desired_state <= KEYSTORE_VERSION_OK) 299390e0e8c4Sizick break; 299490e0e8c4Sizick 299590e0e8c4Sizick /* FALLTHRU */ 299690e0e8c4Sizick case KEYSTORE_VERSION_OK: 299790e0e8c4Sizick /* Load all the public token objects from keystore */ 299890e0e8c4Sizick if (soft_get_token_objects_from_keystore(PUB_TOKENOBJS) 299990e0e8c4Sizick != CKR_OK) { 300090e0e8c4Sizick (void) soft_destroy_token_session(); 300190e0e8c4Sizick soft_slot.keystore_load_status = KEYSTORE_UNAVAILABLE; 30024c21f043Sizick cryptoerror(LOG_DEBUG, 300390e0e8c4Sizick "pkcs11_softtoken: Cannot initialize keystore."); 300490e0e8c4Sizick break; 300590e0e8c4Sizick } 300690e0e8c4Sizick 300790e0e8c4Sizick soft_slot.keystore_load_status = KEYSTORE_INITIALIZED; 300890e0e8c4Sizick }; 300990e0e8c4Sizick 301090e0e8c4Sizick (void) pthread_mutex_unlock(&soft_slot.keystore_mutex); 301190e0e8c4Sizick return (soft_slot.keystore_load_status); 301290e0e8c4Sizick } 301390e0e8c4Sizick 301490e0e8c4Sizick /* 301590e0e8c4Sizick * FUNCTION: soft_keystore_status 301690e0e8c4Sizick * 301790e0e8c4Sizick * ARGUMENTS: 301890e0e8c4Sizick * desired_state: The keystore state the caller would like 301990e0e8c4Sizick * it to be. 302090e0e8c4Sizick * 302190e0e8c4Sizick * RETURN VALUE: 302290e0e8c4Sizick * B_TRUE if keystore is ready and at the desired state. 302390e0e8c4Sizick * B_FALSE if keystore had an error and is not available. 302490e0e8c4Sizick * 302590e0e8c4Sizick * DESCRIPTION: 302690e0e8c4Sizick * The calling function wants to make sure the keystore load 302790e0e8c4Sizick * status to in a state it requires. If it is not at that 302890e0e8c4Sizick * state it will call the load function. 302990e0e8c4Sizick * If keystore is at the desired state or has just been 303090e0e8c4Sizick * loaded to that state, it will return TRUE. If there has been 303190e0e8c4Sizick * load failure, it will return FALSE. 303290e0e8c4Sizick * 303390e0e8c4Sizick */ 303490e0e8c4Sizick boolean_t 303590e0e8c4Sizick soft_keystore_status(int desired_state) 303690e0e8c4Sizick { 303790e0e8c4Sizick 303890e0e8c4Sizick if (soft_slot.keystore_load_status == KEYSTORE_UNAVAILABLE) 303990e0e8c4Sizick return (B_FALSE); 304090e0e8c4Sizick 304190e0e8c4Sizick return ((desired_state <= soft_slot.keystore_load_status) || 304290e0e8c4Sizick (soft_keystore_init(desired_state) == desired_state)); 304390e0e8c4Sizick } 3044