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