10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
51937Sizick * Common Development and Distribution License (the "License").
61937Sizick * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
2212256SPeter.Shoults@Sun.COM * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
230Sstevel@tonic-gate */
240Sstevel@tonic-gate
250Sstevel@tonic-gate /*
260Sstevel@tonic-gate * Functions used for manipulating the keystore
270Sstevel@tonic-gate */
280Sstevel@tonic-gate
290Sstevel@tonic-gate #include <stdio.h>
300Sstevel@tonic-gate #include <stdlib.h>
310Sstevel@tonic-gate #include <errno.h>
320Sstevel@tonic-gate #include <sys/stat.h>
330Sstevel@tonic-gate #include <fcntl.h>
340Sstevel@tonic-gate #include <time.h>
350Sstevel@tonic-gate #include <unistd.h>
360Sstevel@tonic-gate #include <pwd.h>
370Sstevel@tonic-gate #include <sys/types.h>
380Sstevel@tonic-gate #include <dirent.h>
390Sstevel@tonic-gate #include <limits.h>
4012256SPeter.Shoults@Sun.COM #include <libgen.h>
410Sstevel@tonic-gate #include <strings.h>
420Sstevel@tonic-gate #include <security/cryptoki.h>
430Sstevel@tonic-gate #include <cryptoutil.h>
440Sstevel@tonic-gate #include "softGlobal.h"
450Sstevel@tonic-gate #include "softObject.h"
461937Sizick #include "softSession.h"
470Sstevel@tonic-gate #include "softKeystore.h"
480Sstevel@tonic-gate #include "softKeystoreUtil.h"
490Sstevel@tonic-gate
500Sstevel@tonic-gate #define MAXPATHLEN 1024
510Sstevel@tonic-gate #define SUNW_PATH ".sunw" /* top level Sun directory */
520Sstevel@tonic-gate #define KEYSTORE_PATH "pkcs11_softtoken" /* keystore directory */
530Sstevel@tonic-gate #define PUB_OBJ_DIR "public" /* directory for public objects */
540Sstevel@tonic-gate #define PRI_OBJ_DIR "private" /* directory for private objects */
550Sstevel@tonic-gate #define DS_FILE "objstore_info" /* keystore description file */
560Sstevel@tonic-gate #define TMP_DS_FILE "t_info" /* temp name for keystore desc. file */
570Sstevel@tonic-gate #define OBJ_PREFIX "obj" /* prefix of the keystore object file names */
589341SAnthony.Scarpino@Sun.COM #define OBJ_PREFIX_LEN sizeof (OBJ_PREFIX) - 1 /* length of prefix */
590Sstevel@tonic-gate #define TMP_OBJ_PREFIX "t_o" /* prefix of the temp object file names */
600Sstevel@tonic-gate
610Sstevel@tonic-gate /*
620Sstevel@tonic-gate * KEYSTORE DESCRIPTION FILE:
630Sstevel@tonic-gate *
640Sstevel@tonic-gate * The following describes the content of the keystore description file
650Sstevel@tonic-gate *
660Sstevel@tonic-gate * The order AND data type of the fields are very important.
670Sstevel@tonic-gate * All the code in this file assume that they are in the order specified
680Sstevel@tonic-gate * below. If either order of the fields or their data type changed,
690Sstevel@tonic-gate * you must make sure the ALL the pre-define values are still valid
700Sstevel@tonic-gate *
711937Sizick * 1) PKCS#11 release number. It's 2.20 in this release (uchar_t[32])
720Sstevel@tonic-gate * 2) keystore version number: used for synchronizing when different
730Sstevel@tonic-gate * processes access the keystore at the same time. It is incremented
740Sstevel@tonic-gate * when there is a change to the keystore. (uint_32)
750Sstevel@tonic-gate * 3) monotonic-counter: last counter value for name of token object file.
760Sstevel@tonic-gate * used for assigning unique name to each token (uint_32)
770Sstevel@tonic-gate * 4) salt used for generating encryption key (uint_16)
780Sstevel@tonic-gate * 5) salt used for generating key used for doing HMAC (uint_16)
790Sstevel@tonic-gate * 6) Length of salt used for generating hashed pin (length of salt
800Sstevel@tonic-gate * is variable)
810Sstevel@tonic-gate * 7) Salt used for generating hashed pin.
820Sstevel@tonic-gate * 8) Hashed pin len (length of hashed pin could be variable, the offset of
830Sstevel@tonic-gate * where this value lives in the file is calculated at run time)
840Sstevel@tonic-gate * 9) Hashed pin
850Sstevel@tonic-gate *
860Sstevel@tonic-gate */
870Sstevel@tonic-gate
880Sstevel@tonic-gate /* Keystore description file pre-defined values */
89676Sizick #define KS_PKCS11_VER "2.20"
900Sstevel@tonic-gate #define KS_PKCS11_OFFSET 0
910Sstevel@tonic-gate #define KS_PKCS11_VER_SIZE 32
920Sstevel@tonic-gate
930Sstevel@tonic-gate #define KS_VER_OFFSET (KS_PKCS11_OFFSET + KS_PKCS11_VER_SIZE)
940Sstevel@tonic-gate #define KS_VER_SIZE 4 /* size in bytes of keystore version value */
950Sstevel@tonic-gate
960Sstevel@tonic-gate #define KS_COUNTER_OFFSET (KS_VER_OFFSET + KS_VER_SIZE)
970Sstevel@tonic-gate #define KS_COUNTER_SIZE 4 /* size in bytes of the monotonic counter */
980Sstevel@tonic-gate
990Sstevel@tonic-gate #define KS_KEY_SALT_OFFSET (KS_COUNTER_OFFSET + KS_COUNTER_SIZE)
1000Sstevel@tonic-gate #define KS_KEY_SALT_SIZE PBKD2_SALT_SIZE
1010Sstevel@tonic-gate
1020Sstevel@tonic-gate #define KS_HMAC_SALT_OFFSET (KS_KEY_SALT_OFFSET + KS_KEY_SALT_SIZE)
1030Sstevel@tonic-gate #define KS_HMAC_SALT_SIZE PBKD2_SALT_SIZE
1040Sstevel@tonic-gate
1050Sstevel@tonic-gate /* Salt for hashed pin */
1060Sstevel@tonic-gate #define KS_HASHED_PIN_SALT_LEN_OFFSET (KS_HMAC_SALT_OFFSET + KS_HMAC_SALT_SIZE)
1070Sstevel@tonic-gate #define KS_HASHED_PIN_SALT_LEN_SIZE 8 /* stores length of hashed pin salt */
1080Sstevel@tonic-gate
1090Sstevel@tonic-gate #define KS_HASHED_PIN_SALT_OFFSET \
1100Sstevel@tonic-gate (KS_HASHED_PIN_SALT_LEN_OFFSET + KS_HASHED_PIN_SALT_LEN_SIZE)
1110Sstevel@tonic-gate
1120Sstevel@tonic-gate /*
1130Sstevel@tonic-gate * hashed pin
1140Sstevel@tonic-gate *
1150Sstevel@tonic-gate * hashed_pin length offset will be calculated at run time since
1160Sstevel@tonic-gate * there's the hashed pin salt size is variable.
1170Sstevel@tonic-gate *
1180Sstevel@tonic-gate * The offset will be calculated at run time by calling the
1190Sstevel@tonic-gate * function calculate_hashed_pin_offset()
1200Sstevel@tonic-gate */
1210Sstevel@tonic-gate static off_t ks_hashed_pinlen_offset = -1;
1220Sstevel@tonic-gate #define KS_HASHED_PINLEN_SIZE 8
1230Sstevel@tonic-gate
1240Sstevel@tonic-gate /* End of Keystore description file pre-defined values */
1250Sstevel@tonic-gate
1260Sstevel@tonic-gate /*
1270Sstevel@tonic-gate * Metadata for each object
1280Sstevel@tonic-gate *
1290Sstevel@tonic-gate * The order AND data type of all the fields is very important.
1300Sstevel@tonic-gate * All the code in this file assume that they are in the order specified
1310Sstevel@tonic-gate * below. If either order of the fields or their data type is changed,
1320Sstevel@tonic-gate * you must make sure the following pre-define value is still valid
1330Sstevel@tonic-gate * Each object will have the meta data at the beginning of the object file.
1340Sstevel@tonic-gate *
1350Sstevel@tonic-gate * 1) object_version: used by softtoken to see if the object
1360Sstevel@tonic-gate * has been modified since it last reads it. (uint_32)
1370Sstevel@tonic-gate * 2) iv: initialization vector for encrypted data in the object. This
1380Sstevel@tonic-gate * value will be 0 for public objects. (uchar_t[16])
1390Sstevel@tonic-gate * 3) obj_hmac: keyed hash as verifier to detect private object
1400Sstevel@tonic-gate * being tampered this value will be 0 for public objects (uchar_t[16])
1410Sstevel@tonic-gate */
1420Sstevel@tonic-gate
1430Sstevel@tonic-gate /* Object metadata pre-defined values */
1440Sstevel@tonic-gate #define OBJ_VER_OFFSET 0
1450Sstevel@tonic-gate #define OBJ_VER_SIZE 4 /* size of object version in bytes */
1460Sstevel@tonic-gate #define OBJ_IV_OFFSET (OBJ_VER_OFFSET + OBJ_VER_SIZE)
1470Sstevel@tonic-gate #define OBJ_IV_SIZE 16
1480Sstevel@tonic-gate #define OBJ_HMAC_OFFSET (OBJ_IV_OFFSET + OBJ_IV_SIZE)
1490Sstevel@tonic-gate #define OBJ_HMAC_SIZE 16 /* MD5 HMAC keyed hash */
1500Sstevel@tonic-gate #define OBJ_DATA_OFFSET (OBJ_HMAC_OFFSET + OBJ_HMAC_SIZE)
1510Sstevel@tonic-gate /* End of object metadata pre-defined values */
1520Sstevel@tonic-gate
1530Sstevel@tonic-gate #define ALTERNATE_KEYSTORE_PATH "SOFTTOKEN_DIR"
1540Sstevel@tonic-gate
1550Sstevel@tonic-gate static soft_object_t *enc_key = NULL;
1560Sstevel@tonic-gate static soft_object_t *hmac_key = NULL;
1570Sstevel@tonic-gate static char keystore_path[MAXPATHLEN];
1580Sstevel@tonic-gate static boolean_t keystore_path_initialized = B_FALSE;
1590Sstevel@tonic-gate static int desc_fd = 0;
1600Sstevel@tonic-gate
1610Sstevel@tonic-gate static char *
get_keystore_path()1620Sstevel@tonic-gate get_keystore_path()
1630Sstevel@tonic-gate {
16412256SPeter.Shoults@Sun.COM char *home = getenv("HOME");
16512256SPeter.Shoults@Sun.COM char *alt = getenv(ALTERNATE_KEYSTORE_PATH);
16612256SPeter.Shoults@Sun.COM
16712256SPeter.Shoults@Sun.COM if (keystore_path_initialized) {
16812256SPeter.Shoults@Sun.COM return (keystore_path);
16912256SPeter.Shoults@Sun.COM }
17012256SPeter.Shoults@Sun.COM
17112256SPeter.Shoults@Sun.COM bzero(keystore_path, sizeof (keystore_path));
17212256SPeter.Shoults@Sun.COM /*
17312256SPeter.Shoults@Sun.COM * If it isn't set or is set to the empty string use the
17412256SPeter.Shoults@Sun.COM * default location. We need to check for the empty string
17512256SPeter.Shoults@Sun.COM * because some users "unset" environment variables by giving
17612256SPeter.Shoults@Sun.COM * them no value, this isn't the same thing as removing it
17712256SPeter.Shoults@Sun.COM * from the environment.
17812256SPeter.Shoults@Sun.COM *
17912256SPeter.Shoults@Sun.COM * We don't want that to attempt to open /.sunw/pkcs11_sofftoken
18012256SPeter.Shoults@Sun.COM */
18112256SPeter.Shoults@Sun.COM if ((alt != NULL) && (strcmp(alt, "") != 0)) {
18212256SPeter.Shoults@Sun.COM (void) snprintf(keystore_path, MAXPATHLEN, "%s/%s",
18312256SPeter.Shoults@Sun.COM alt, KEYSTORE_PATH);
18412256SPeter.Shoults@Sun.COM keystore_path_initialized = B_TRUE;
18512256SPeter.Shoults@Sun.COM } else if ((home != NULL) && (strcmp(home, "") != 0)) {
18612256SPeter.Shoults@Sun.COM /* alternate path not specified, try user's home dir */
18712256SPeter.Shoults@Sun.COM (void) snprintf(keystore_path, MAXPATHLEN, "%s/%s/%s",
18812256SPeter.Shoults@Sun.COM home, SUNW_PATH, KEYSTORE_PATH);
1890Sstevel@tonic-gate keystore_path_initialized = B_TRUE;
1900Sstevel@tonic-gate }
1910Sstevel@tonic-gate return (keystore_path);
1920Sstevel@tonic-gate }
1930Sstevel@tonic-gate
1940Sstevel@tonic-gate static char *
get_pub_obj_path(char * name)1950Sstevel@tonic-gate get_pub_obj_path(char *name)
1960Sstevel@tonic-gate {
1970Sstevel@tonic-gate bzero(name, sizeof (name));
1980Sstevel@tonic-gate (void) snprintf(name, MAXPATHLEN, "%s/%s",
1990Sstevel@tonic-gate get_keystore_path(), PUB_OBJ_DIR);
2000Sstevel@tonic-gate return (name);
2010Sstevel@tonic-gate }
2020Sstevel@tonic-gate
2030Sstevel@tonic-gate static char *
get_pri_obj_path(char * name)2040Sstevel@tonic-gate get_pri_obj_path(char *name)
2050Sstevel@tonic-gate {
2060Sstevel@tonic-gate bzero(name, sizeof (name));
2070Sstevel@tonic-gate (void) snprintf(name, MAXPATHLEN, "%s/%s",
2080Sstevel@tonic-gate get_keystore_path(), PRI_OBJ_DIR);
2090Sstevel@tonic-gate return (name);
2100Sstevel@tonic-gate }
2110Sstevel@tonic-gate
2120Sstevel@tonic-gate static char *
get_desc_file_path(char * name)2130Sstevel@tonic-gate get_desc_file_path(char *name)
2140Sstevel@tonic-gate {
2150Sstevel@tonic-gate bzero(name, sizeof (name));
2160Sstevel@tonic-gate (void) snprintf(name, MAXPATHLEN, "%s/%s",
2170Sstevel@tonic-gate get_keystore_path(), DS_FILE);
2180Sstevel@tonic-gate return (name);
2190Sstevel@tonic-gate }
2200Sstevel@tonic-gate
2210Sstevel@tonic-gate static char *
get_tmp_desc_file_path(char * name)2220Sstevel@tonic-gate get_tmp_desc_file_path(char *name)
2230Sstevel@tonic-gate {
2240Sstevel@tonic-gate bzero(name, sizeof (name));
2250Sstevel@tonic-gate (void) snprintf(name, MAXPATHLEN, "%s/%s",
2260Sstevel@tonic-gate get_keystore_path(), TMP_DS_FILE);
2270Sstevel@tonic-gate return (name);
2280Sstevel@tonic-gate }
2290Sstevel@tonic-gate
2300Sstevel@tonic-gate /*
2310Sstevel@tonic-gate * Calculates the offset for hashed_pin length and hashed pin
2320Sstevel@tonic-gate *
2330Sstevel@tonic-gate * Returns 0 if successful, -1 if there's any error.
2340Sstevel@tonic-gate *
2350Sstevel@tonic-gate * If successful, global variables "ks_hashed_pinlen_offset" will be set.
2360Sstevel@tonic-gate *
2370Sstevel@tonic-gate */
2380Sstevel@tonic-gate static int
calculate_hashed_pin_offset(int fd)2390Sstevel@tonic-gate calculate_hashed_pin_offset(int fd)
2400Sstevel@tonic-gate {
2410Sstevel@tonic-gate uint64_t salt_length;
2420Sstevel@tonic-gate
2430Sstevel@tonic-gate if (lseek(fd, KS_HASHED_PIN_SALT_LEN_OFFSET, SEEK_SET)
2440Sstevel@tonic-gate != KS_HASHED_PIN_SALT_LEN_OFFSET) {
2450Sstevel@tonic-gate return (-1);
2460Sstevel@tonic-gate }
2470Sstevel@tonic-gate
2488932SDina.Nimeh@Sun.COM if (readn_nointr(fd, (char *)&salt_length,
2490Sstevel@tonic-gate KS_HASHED_PIN_SALT_LEN_SIZE) != KS_HASHED_PIN_SALT_LEN_SIZE) {
2500Sstevel@tonic-gate return (-1);
2510Sstevel@tonic-gate }
2520Sstevel@tonic-gate salt_length = SWAP64(salt_length);
2530Sstevel@tonic-gate
2540Sstevel@tonic-gate ks_hashed_pinlen_offset = KS_HASHED_PIN_SALT_LEN_OFFSET
2550Sstevel@tonic-gate + KS_HASHED_PIN_SALT_LEN_SIZE + salt_length;
2560Sstevel@tonic-gate
2570Sstevel@tonic-gate return (0);
2580Sstevel@tonic-gate
2590Sstevel@tonic-gate }
2600Sstevel@tonic-gate
2610Sstevel@tonic-gate /*
2620Sstevel@tonic-gate * acquire or release read/write lock on a specific file
2630Sstevel@tonic-gate *
2640Sstevel@tonic-gate * read_lock: true for read lock; false for write lock
2650Sstevel@tonic-gate * set_lock: true to set a lock; false to release a lock
2660Sstevel@tonic-gate */
2670Sstevel@tonic-gate static int
lock_file(int fd,boolean_t read_lock,boolean_t set_lock)2680Sstevel@tonic-gate lock_file(int fd, boolean_t read_lock, boolean_t set_lock)
2690Sstevel@tonic-gate {
2700Sstevel@tonic-gate
2710Sstevel@tonic-gate flock_t lock_info;
2720Sstevel@tonic-gate int r;
2730Sstevel@tonic-gate
2740Sstevel@tonic-gate lock_info.l_whence = SEEK_SET;
2750Sstevel@tonic-gate lock_info.l_start = 0;
2760Sstevel@tonic-gate lock_info.l_len = 0; /* l_len == 0 means until end of file */
2770Sstevel@tonic-gate
2780Sstevel@tonic-gate if (read_lock) {
2790Sstevel@tonic-gate lock_info.l_type = F_RDLCK;
2800Sstevel@tonic-gate } else {
2810Sstevel@tonic-gate lock_info.l_type = F_WRLCK;
2820Sstevel@tonic-gate }
2830Sstevel@tonic-gate
2840Sstevel@tonic-gate if (set_lock) {
2850Sstevel@tonic-gate while ((r = fcntl(fd, F_SETLKW, &lock_info)) == -1) {
2860Sstevel@tonic-gate if (errno != EINTR)
2870Sstevel@tonic-gate break;
2880Sstevel@tonic-gate }
2890Sstevel@tonic-gate if (r == -1) {
2900Sstevel@tonic-gate return (-1);
2910Sstevel@tonic-gate }
2920Sstevel@tonic-gate } else {
2930Sstevel@tonic-gate lock_info.l_type = F_UNLCK;
2940Sstevel@tonic-gate while ((r = fcntl(fd, F_SETLKW, &lock_info)) == -1) {
2950Sstevel@tonic-gate if (errno != EINTR)
2960Sstevel@tonic-gate break;
2970Sstevel@tonic-gate }
2980Sstevel@tonic-gate if (r == -1) {
2990Sstevel@tonic-gate return (-1);
3000Sstevel@tonic-gate }
3010Sstevel@tonic-gate }
3020Sstevel@tonic-gate
3030Sstevel@tonic-gate return (0);
3040Sstevel@tonic-gate }
3050Sstevel@tonic-gate
30612256SPeter.Shoults@Sun.COM int
create_keystore()3070Sstevel@tonic-gate create_keystore()
3080Sstevel@tonic-gate {
3090Sstevel@tonic-gate int fd, buf;
3100Sstevel@tonic-gate uint64_t hashed_pin_len, hashed_pin_salt_len, ulong_buf;
3110Sstevel@tonic-gate uchar_t ver_buf[KS_PKCS11_VER_SIZE];
3120Sstevel@tonic-gate char pub_obj_path[MAXPATHLEN], pri_obj_path[MAXPATHLEN],
3130Sstevel@tonic-gate ks_desc_file[MAXPATHLEN];
3140Sstevel@tonic-gate CK_BYTE salt[KS_KEY_SALT_SIZE];
3150Sstevel@tonic-gate char *hashed_pin = NULL, *hashed_pin_salt = NULL;
31612256SPeter.Shoults@Sun.COM char *alt;
3170Sstevel@tonic-gate
3180Sstevel@tonic-gate /* keystore doesn't exist, create keystore directory */
3190Sstevel@tonic-gate if (mkdir(get_keystore_path(), S_IRUSR|S_IWUSR|S_IXUSR) < 0) {
3200Sstevel@tonic-gate if (errno == EEXIST) {
3210Sstevel@tonic-gate return (0);
3220Sstevel@tonic-gate }
3230Sstevel@tonic-gate
3240Sstevel@tonic-gate if (errno == EACCES) {
3250Sstevel@tonic-gate return (-1);
3260Sstevel@tonic-gate }
3270Sstevel@tonic-gate
3280Sstevel@tonic-gate /* can't create keystore directory */
3290Sstevel@tonic-gate if (errno == ENOENT) { /* part of the path doesn't exist */
33012256SPeter.Shoults@Sun.COM char keystore[MAXPATHLEN];
3310Sstevel@tonic-gate /*
33212256SPeter.Shoults@Sun.COM * try to create $HOME/.sunw/pkcs11_softtoken if it
33312256SPeter.Shoults@Sun.COM * doesn't exist. If it is a alternate path provided
33412256SPeter.Shoults@Sun.COM * by the user, it should have existed. Will not
3350Sstevel@tonic-gate * create for them.
3360Sstevel@tonic-gate */
33712256SPeter.Shoults@Sun.COM alt = getenv(ALTERNATE_KEYSTORE_PATH);
33812256SPeter.Shoults@Sun.COM if ((alt == NULL) || (strcmp(alt, "") == 0)) {
33912256SPeter.Shoults@Sun.COM char *home = getenv("HOME");
34012256SPeter.Shoults@Sun.COM
34112256SPeter.Shoults@Sun.COM if (home == NULL || strcmp(home, "") == 0) {
3420Sstevel@tonic-gate return (-1);
3430Sstevel@tonic-gate }
3440Sstevel@tonic-gate /* create $HOME/.sunw/pkcs11_softtoken */
34512256SPeter.Shoults@Sun.COM (void) snprintf(keystore, sizeof (keystore),
346*12517SPeter.Shoults@Sun.COM "%s/%s/%s", home, SUNW_PATH, KEYSTORE_PATH);
34712256SPeter.Shoults@Sun.COM if (mkdirp(keystore,
3480Sstevel@tonic-gate S_IRUSR|S_IWUSR|S_IXUSR) < 0) {
3490Sstevel@tonic-gate return (-1);
3500Sstevel@tonic-gate }
3510Sstevel@tonic-gate } else {
3520Sstevel@tonic-gate return (-1);
3530Sstevel@tonic-gate }
3540Sstevel@tonic-gate }
3550Sstevel@tonic-gate }
3560Sstevel@tonic-gate
3570Sstevel@tonic-gate /* create keystore description file */
3588932SDina.Nimeh@Sun.COM fd = open_nointr(get_desc_file_path(ks_desc_file),
3598932SDina.Nimeh@Sun.COM O_RDWR|O_CREAT|O_EXCL|O_NONBLOCK, S_IRUSR|S_IWUSR);
3600Sstevel@tonic-gate if (fd < 0) {
3610Sstevel@tonic-gate if (errno == EEXIST) {
3620Sstevel@tonic-gate return (0);
3630Sstevel@tonic-gate } else {
3640Sstevel@tonic-gate /* can't create keystore description file */
3650Sstevel@tonic-gate (void) rmdir(get_keystore_path());
3660Sstevel@tonic-gate return (-1);
3670Sstevel@tonic-gate }
3680Sstevel@tonic-gate }
3690Sstevel@tonic-gate
3700Sstevel@tonic-gate if (lock_file(fd, B_FALSE, B_TRUE) != 0) {
3710Sstevel@tonic-gate (void) unlink(ks_desc_file);
3720Sstevel@tonic-gate (void) close(fd);
3730Sstevel@tonic-gate (void) rmdir(get_keystore_path());
3740Sstevel@tonic-gate return (-1);
3750Sstevel@tonic-gate }
3760Sstevel@tonic-gate
3770Sstevel@tonic-gate if (mkdir(get_pub_obj_path(pub_obj_path),
3780Sstevel@tonic-gate S_IRUSR|S_IWUSR|S_IXUSR) < 0) {
3790Sstevel@tonic-gate /* can't create directory for public objects */
3800Sstevel@tonic-gate (void) lock_file(fd, B_FALSE, B_FALSE);
3810Sstevel@tonic-gate (void) unlink(ks_desc_file);
3820Sstevel@tonic-gate (void) close(fd);
3830Sstevel@tonic-gate (void) rmdir(get_keystore_path());
3840Sstevel@tonic-gate return (-1);
3850Sstevel@tonic-gate }
3860Sstevel@tonic-gate
3870Sstevel@tonic-gate if (mkdir(get_pri_obj_path(pri_obj_path),
3880Sstevel@tonic-gate S_IRUSR|S_IWUSR|S_IXUSR) < 0) {
3890Sstevel@tonic-gate /* can't create directory for private objects */
3900Sstevel@tonic-gate (void) lock_file(fd, B_FALSE, B_FALSE);
3910Sstevel@tonic-gate (void) unlink(ks_desc_file);
3920Sstevel@tonic-gate (void) close(fd);
3930Sstevel@tonic-gate (void) rmdir(get_keystore_path());
3940Sstevel@tonic-gate (void) rmdir(pub_obj_path);
3950Sstevel@tonic-gate return (-1);
3960Sstevel@tonic-gate }
3970Sstevel@tonic-gate
3980Sstevel@tonic-gate
3990Sstevel@tonic-gate /* write file format release number */
4000Sstevel@tonic-gate bzero(ver_buf, sizeof (ver_buf));
4010Sstevel@tonic-gate (void) strcpy((char *)ver_buf, KS_PKCS11_VER);
4028932SDina.Nimeh@Sun.COM if ((writen_nointr(fd, (char *)ver_buf, sizeof (ver_buf)))
4030Sstevel@tonic-gate != sizeof (ver_buf)) {
4040Sstevel@tonic-gate goto cleanup;
4050Sstevel@tonic-gate }
4060Sstevel@tonic-gate
4070Sstevel@tonic-gate /* write version number, version = 0 since keystore just created */
4080Sstevel@tonic-gate buf = SWAP32(0);
4098932SDina.Nimeh@Sun.COM if (writen_nointr(fd, (void *)&buf, KS_VER_SIZE) != KS_VER_SIZE) {
4100Sstevel@tonic-gate goto cleanup;
4110Sstevel@tonic-gate }
4120Sstevel@tonic-gate
4130Sstevel@tonic-gate /* write monotonic-counter. Counter for keystore objects start at 1 */
4140Sstevel@tonic-gate buf = SWAP32(1);
4158932SDina.Nimeh@Sun.COM if (writen_nointr(fd, (void *)&buf, KS_COUNTER_SIZE)
4160Sstevel@tonic-gate != KS_COUNTER_SIZE) {
4170Sstevel@tonic-gate goto cleanup;
4180Sstevel@tonic-gate }
4190Sstevel@tonic-gate
4200Sstevel@tonic-gate /* initial encryption key salt should be all NULL */
4210Sstevel@tonic-gate bzero(salt, sizeof (salt));
4228932SDina.Nimeh@Sun.COM if (writen_nointr(fd, (void *)salt, KS_KEY_SALT_SIZE)
4230Sstevel@tonic-gate != KS_KEY_SALT_SIZE) {
4240Sstevel@tonic-gate goto cleanup;
4250Sstevel@tonic-gate }
4260Sstevel@tonic-gate
4270Sstevel@tonic-gate /* initial HMAC key salt should also be all NULL */
4288932SDina.Nimeh@Sun.COM if (writen_nointr(fd, (void *)salt, KS_HMAC_SALT_SIZE)
4290Sstevel@tonic-gate != KS_HMAC_SALT_SIZE) {
4300Sstevel@tonic-gate goto cleanup;
4310Sstevel@tonic-gate }
4320Sstevel@tonic-gate
4330Sstevel@tonic-gate /* generate the hashed pin salt, and MD5 hashed pin of default pin */
4340Sstevel@tonic-gate if (soft_gen_hashed_pin((CK_CHAR_PTR)SOFT_DEFAULT_PIN, &hashed_pin,
4350Sstevel@tonic-gate &hashed_pin_salt) < 0) {
4360Sstevel@tonic-gate goto cleanup;
4370Sstevel@tonic-gate }
4380Sstevel@tonic-gate
4390Sstevel@tonic-gate if ((hashed_pin_salt == NULL) || (hashed_pin == NULL)) {
4400Sstevel@tonic-gate goto cleanup;
4410Sstevel@tonic-gate }
4420Sstevel@tonic-gate
4430Sstevel@tonic-gate hashed_pin_salt_len = (uint64_t)strlen(hashed_pin_salt);
4440Sstevel@tonic-gate hashed_pin_len = (uint64_t)strlen(hashed_pin);
4450Sstevel@tonic-gate
4460Sstevel@tonic-gate /* write hashed pin salt length */
4470Sstevel@tonic-gate ulong_buf = SWAP64(hashed_pin_salt_len);
4488932SDina.Nimeh@Sun.COM if (writen_nointr(fd, (void *)&ulong_buf, KS_HASHED_PIN_SALT_LEN_SIZE)
4490Sstevel@tonic-gate != KS_HASHED_PIN_SALT_LEN_SIZE) {
4500Sstevel@tonic-gate goto cleanup;
4510Sstevel@tonic-gate }
4520Sstevel@tonic-gate
4538932SDina.Nimeh@Sun.COM if (writen_nointr(fd, (void *)hashed_pin_salt,
4540Sstevel@tonic-gate hashed_pin_salt_len) != hashed_pin_salt_len) {
4550Sstevel@tonic-gate goto cleanup;
4560Sstevel@tonic-gate }
4570Sstevel@tonic-gate
4580Sstevel@tonic-gate /* write MD5 hashed pin of the default pin */
4590Sstevel@tonic-gate ulong_buf = SWAP64(hashed_pin_len);
4608932SDina.Nimeh@Sun.COM if (writen_nointr(fd, (void *)&ulong_buf, KS_HASHED_PINLEN_SIZE)
4610Sstevel@tonic-gate != KS_HASHED_PINLEN_SIZE) {
4620Sstevel@tonic-gate goto cleanup;
4630Sstevel@tonic-gate }
4640Sstevel@tonic-gate
4658932SDina.Nimeh@Sun.COM if (writen_nointr(fd, (void *)hashed_pin, hashed_pin_len)
4660Sstevel@tonic-gate != hashed_pin_len) {
4670Sstevel@tonic-gate goto cleanup;
4680Sstevel@tonic-gate }
4690Sstevel@tonic-gate
4700Sstevel@tonic-gate (void) lock_file(fd, B_FALSE, B_FALSE);
4710Sstevel@tonic-gate
4720Sstevel@tonic-gate (void) close(fd);
4730Sstevel@tonic-gate if (hashed_pin_salt)
4748932SDina.Nimeh@Sun.COM free(hashed_pin_salt);
4750Sstevel@tonic-gate return (0);
4760Sstevel@tonic-gate
4770Sstevel@tonic-gate cleanup:
4780Sstevel@tonic-gate (void) lock_file(fd, B_FALSE, B_FALSE);
4790Sstevel@tonic-gate (void) unlink(ks_desc_file);
4800Sstevel@tonic-gate (void) close(fd);
4810Sstevel@tonic-gate (void) rmdir(get_keystore_path());
4820Sstevel@tonic-gate (void) rmdir(pub_obj_path);
4830Sstevel@tonic-gate (void) rmdir(pri_obj_path);
4840Sstevel@tonic-gate return (-1);
4850Sstevel@tonic-gate }
4860Sstevel@tonic-gate
4870Sstevel@tonic-gate /*
4880Sstevel@tonic-gate * Determines if the file referenced by "fd" has the same
4890Sstevel@tonic-gate * inode as the file referenced by "fname".
4900Sstevel@tonic-gate *
4910Sstevel@tonic-gate * The argument "same" contains the result of determining
4920Sstevel@tonic-gate * if the inode is the same or not
4930Sstevel@tonic-gate *
4940Sstevel@tonic-gate * Returns 0 if there's no error.
4950Sstevel@tonic-gate * Returns 1 if there's any error with opening the file.
4960Sstevel@tonic-gate *
4970Sstevel@tonic-gate *
4980Sstevel@tonic-gate */
4990Sstevel@tonic-gate static int
is_inode_same(int fd,char * fname,boolean_t * same)5000Sstevel@tonic-gate is_inode_same(int fd, char *fname, boolean_t *same)
5010Sstevel@tonic-gate {
5020Sstevel@tonic-gate struct stat fn_stat, fd_stat;
5030Sstevel@tonic-gate
5040Sstevel@tonic-gate if (fstat(fd, &fd_stat) != 0) {
5050Sstevel@tonic-gate return (-1);
5060Sstevel@tonic-gate }
5070Sstevel@tonic-gate
5080Sstevel@tonic-gate if (stat(fname, &fn_stat) != 0) {
5090Sstevel@tonic-gate return (-1);
5100Sstevel@tonic-gate }
5110Sstevel@tonic-gate
5120Sstevel@tonic-gate /* It's the same file if both st_ino and st_dev match */
5130Sstevel@tonic-gate if ((fd_stat.st_ino == fn_stat.st_ino) &&
5140Sstevel@tonic-gate (fd_stat.st_dev == fn_stat.st_dev)) {
5150Sstevel@tonic-gate *same = B_TRUE;
5160Sstevel@tonic-gate } else {
5170Sstevel@tonic-gate *same = B_FALSE;
5180Sstevel@tonic-gate }
5190Sstevel@tonic-gate return (0);
5200Sstevel@tonic-gate }
5210Sstevel@tonic-gate
5220Sstevel@tonic-gate static int
acquire_file_lock(int * fd,char * fname,mode_t mode)5230Sstevel@tonic-gate acquire_file_lock(int *fd, char *fname, mode_t mode) {
5240Sstevel@tonic-gate
5250Sstevel@tonic-gate boolean_t read_lock = B_TRUE, same_inode;
5260Sstevel@tonic-gate
5270Sstevel@tonic-gate if ((mode == O_RDWR) || (mode == O_WRONLY)) {
5280Sstevel@tonic-gate read_lock = B_FALSE;
5290Sstevel@tonic-gate }
5300Sstevel@tonic-gate
5310Sstevel@tonic-gate if (lock_file(*fd, read_lock, B_TRUE) != 0) {
5320Sstevel@tonic-gate return (-1);
5330Sstevel@tonic-gate }
5340Sstevel@tonic-gate
5350Sstevel@tonic-gate /*
5360Sstevel@tonic-gate * make sure another process did not modify the file
5370Sstevel@tonic-gate * while we were trying to get the lock
5380Sstevel@tonic-gate */
5390Sstevel@tonic-gate if (is_inode_same(*fd, fname, &same_inode) != 0) {
5400Sstevel@tonic-gate (void) lock_file(*fd, B_TRUE, B_FALSE); /* unlock file */
5410Sstevel@tonic-gate return (-1);
5420Sstevel@tonic-gate }
5430Sstevel@tonic-gate
5440Sstevel@tonic-gate while (!same_inode) {
5450Sstevel@tonic-gate /*
5460Sstevel@tonic-gate * need to unlock file, close, re-open the file,
5470Sstevel@tonic-gate * and re-acquire the lock
5480Sstevel@tonic-gate */
5490Sstevel@tonic-gate
5500Sstevel@tonic-gate /* unlock file */
5510Sstevel@tonic-gate if (lock_file(*fd, B_TRUE, B_FALSE) != 0) {
5520Sstevel@tonic-gate return (-1);
5530Sstevel@tonic-gate }
5540Sstevel@tonic-gate
5550Sstevel@tonic-gate (void) close(*fd);
5560Sstevel@tonic-gate
5570Sstevel@tonic-gate /* re-open */
5588932SDina.Nimeh@Sun.COM *fd = open_nointr(fname, mode|O_NONBLOCK);
5590Sstevel@tonic-gate if (*fd < 0) {
5600Sstevel@tonic-gate return (-1);
5610Sstevel@tonic-gate }
5620Sstevel@tonic-gate
5630Sstevel@tonic-gate /* acquire lock again */
5640Sstevel@tonic-gate if (lock_file(*fd, read_lock, B_TRUE) != 0) {
5650Sstevel@tonic-gate return (-1);
5660Sstevel@tonic-gate }
5670Sstevel@tonic-gate
5680Sstevel@tonic-gate if (is_inode_same(*fd, fname, &same_inode) != 0) {
5690Sstevel@tonic-gate (void) lock_file(*fd, B_TRUE, B_FALSE); /* unlock */
5700Sstevel@tonic-gate return (-1);
5710Sstevel@tonic-gate }
5720Sstevel@tonic-gate
5730Sstevel@tonic-gate }
5740Sstevel@tonic-gate
5750Sstevel@tonic-gate return (0);
5760Sstevel@tonic-gate }
5770Sstevel@tonic-gate
5780Sstevel@tonic-gate /*
5790Sstevel@tonic-gate * Open the keystore description file in the specified mode.
5800Sstevel@tonic-gate * If the keystore doesn't exist, the "do_create_keystore"
5810Sstevel@tonic-gate * argument determines if the keystore should be created
5820Sstevel@tonic-gate */
5830Sstevel@tonic-gate static int
open_and_lock_keystore_desc(mode_t mode,boolean_t do_create_keystore,boolean_t lock_held)5840Sstevel@tonic-gate open_and_lock_keystore_desc(mode_t mode, boolean_t do_create_keystore,
5850Sstevel@tonic-gate boolean_t lock_held)
5860Sstevel@tonic-gate {
5870Sstevel@tonic-gate
5880Sstevel@tonic-gate int fd;
5890Sstevel@tonic-gate char *fname, ks_desc_file[MAXPATHLEN];
5900Sstevel@tonic-gate
5910Sstevel@tonic-gate /* open the keystore description file in requested mode */
5920Sstevel@tonic-gate fname = get_desc_file_path(ks_desc_file);
5938932SDina.Nimeh@Sun.COM fd = open_nointr(fname, mode|O_NONBLOCK);
5940Sstevel@tonic-gate if (fd < 0) {
5950Sstevel@tonic-gate if ((errno == ENOENT) && (do_create_keystore)) {
5960Sstevel@tonic-gate if (create_keystore() < 0) {
5970Sstevel@tonic-gate goto done;
5980Sstevel@tonic-gate }
5998932SDina.Nimeh@Sun.COM fd = open_nointr(fname, mode|O_NONBLOCK);
6000Sstevel@tonic-gate if (fd < 0) {
6010Sstevel@tonic-gate goto done;
6020Sstevel@tonic-gate }
6030Sstevel@tonic-gate } else {
6040Sstevel@tonic-gate goto done;
6050Sstevel@tonic-gate }
6060Sstevel@tonic-gate }
6070Sstevel@tonic-gate
6080Sstevel@tonic-gate if (lock_held) {
6090Sstevel@tonic-gate /* already hold the lock */
6100Sstevel@tonic-gate return (fd);
6110Sstevel@tonic-gate }
6120Sstevel@tonic-gate
6130Sstevel@tonic-gate if (acquire_file_lock(&fd, fname, mode) != 0) {
6140Sstevel@tonic-gate if (fd > 0) {
6150Sstevel@tonic-gate (void) close(fd);
6160Sstevel@tonic-gate }
6170Sstevel@tonic-gate return (-1);
6180Sstevel@tonic-gate }
6190Sstevel@tonic-gate
6200Sstevel@tonic-gate done:
6210Sstevel@tonic-gate return (fd);
6220Sstevel@tonic-gate }
6230Sstevel@tonic-gate
6240Sstevel@tonic-gate
6250Sstevel@tonic-gate /*
6260Sstevel@tonic-gate * Set or remove read or write lock on keystore description file
6270Sstevel@tonic-gate *
6280Sstevel@tonic-gate * read_lock: true for read lock, false for write lock
6290Sstevel@tonic-gate * set_lock: true for set a lock, false to remove a lock
6300Sstevel@tonic-gate */
6310Sstevel@tonic-gate static int
lock_desc_file(boolean_t read_lock,boolean_t set_lock)6320Sstevel@tonic-gate lock_desc_file(boolean_t read_lock, boolean_t set_lock)
6330Sstevel@tonic-gate {
6340Sstevel@tonic-gate
6350Sstevel@tonic-gate char ks_desc_file[MAXPATHLEN];
6360Sstevel@tonic-gate
6370Sstevel@tonic-gate if (set_lock) {
6380Sstevel@tonic-gate int oflag;
6390Sstevel@tonic-gate
6400Sstevel@tonic-gate /*
6410Sstevel@tonic-gate * make sure desc_fd is not already used. If used, it means
6420Sstevel@tonic-gate * some other lock is already set on the file
6430Sstevel@tonic-gate */
6440Sstevel@tonic-gate if (desc_fd > 0) {
6450Sstevel@tonic-gate return (-1);
6460Sstevel@tonic-gate }
6470Sstevel@tonic-gate
6480Sstevel@tonic-gate (void) get_desc_file_path(ks_desc_file);
6490Sstevel@tonic-gate
6500Sstevel@tonic-gate if (read_lock) {
6510Sstevel@tonic-gate oflag = O_RDONLY;
6520Sstevel@tonic-gate } else {
6530Sstevel@tonic-gate oflag = O_WRONLY;
6540Sstevel@tonic-gate }
6550Sstevel@tonic-gate if ((desc_fd = open_and_lock_keystore_desc(oflag,
6560Sstevel@tonic-gate B_FALSE, B_FALSE)) < 0) {
6570Sstevel@tonic-gate return (-1);
6580Sstevel@tonic-gate }
6590Sstevel@tonic-gate } else {
6600Sstevel@tonic-gate /* make sure we have a valid fd */
6610Sstevel@tonic-gate if (desc_fd <= 0) {
6620Sstevel@tonic-gate return (-1);
6630Sstevel@tonic-gate }
6640Sstevel@tonic-gate
6650Sstevel@tonic-gate if (lock_file(desc_fd, read_lock, B_FALSE) == 1) {
6660Sstevel@tonic-gate return (-1);
6670Sstevel@tonic-gate }
6680Sstevel@tonic-gate
6690Sstevel@tonic-gate (void) close(desc_fd);
6700Sstevel@tonic-gate desc_fd = 0;
6710Sstevel@tonic-gate
6720Sstevel@tonic-gate }
6730Sstevel@tonic-gate return (0);
6740Sstevel@tonic-gate }
6750Sstevel@tonic-gate
6760Sstevel@tonic-gate static int
open_and_lock_object_file(ks_obj_handle_t * ks_handle,int oflag,boolean_t lock_held)6770Sstevel@tonic-gate open_and_lock_object_file(ks_obj_handle_t *ks_handle, int oflag,
6780Sstevel@tonic-gate boolean_t lock_held)
6790Sstevel@tonic-gate {
6800Sstevel@tonic-gate char obj_fname[MAXPATHLEN];
6810Sstevel@tonic-gate int fd;
6820Sstevel@tonic-gate
6830Sstevel@tonic-gate if (ks_handle->public) {
6840Sstevel@tonic-gate char pub_obj_path[MAXPATHLEN];
6850Sstevel@tonic-gate (void) snprintf(obj_fname, MAXPATHLEN, "%s/%s",
6860Sstevel@tonic-gate get_pub_obj_path(pub_obj_path), ks_handle->name);
6870Sstevel@tonic-gate } else {
6880Sstevel@tonic-gate char pri_obj_path[MAXPATHLEN];
6890Sstevel@tonic-gate (void) snprintf(obj_fname, MAXPATHLEN, "%s/%s",
6900Sstevel@tonic-gate get_pri_obj_path(pri_obj_path), ks_handle->name);
6910Sstevel@tonic-gate }
6920Sstevel@tonic-gate
6938932SDina.Nimeh@Sun.COM fd = open_nointr(obj_fname, oflag|O_NONBLOCK);
6940Sstevel@tonic-gate if (fd < 0) {
6950Sstevel@tonic-gate return (-1);
6960Sstevel@tonic-gate }
6970Sstevel@tonic-gate
6980Sstevel@tonic-gate if (lock_held) {
6990Sstevel@tonic-gate /* already hold the lock */
7000Sstevel@tonic-gate return (fd);
7010Sstevel@tonic-gate }
7020Sstevel@tonic-gate
7030Sstevel@tonic-gate if (acquire_file_lock(&fd, obj_fname, oflag) != 0) {
7040Sstevel@tonic-gate if (fd > 0) {
7050Sstevel@tonic-gate (void) close(fd);
7060Sstevel@tonic-gate }
7070Sstevel@tonic-gate return (-1);
7080Sstevel@tonic-gate }
7090Sstevel@tonic-gate
7100Sstevel@tonic-gate
7110Sstevel@tonic-gate return (fd);
7120Sstevel@tonic-gate }
7130Sstevel@tonic-gate
7140Sstevel@tonic-gate
7150Sstevel@tonic-gate /*
7160Sstevel@tonic-gate * Update file version number in a temporary file that's
7170Sstevel@tonic-gate * a copy of the keystore description file.
7180Sstevel@tonic-gate * The update is NOT made to the original keystore description
7190Sstevel@tonic-gate * file. It makes the update in a tempoary file.
7200Sstevel@tonic-gate *
7210Sstevel@tonic-gate * Name of the temporary file is assumed to be provided, but
7220Sstevel@tonic-gate * the file is assumed to not exist.
7230Sstevel@tonic-gate *
7240Sstevel@tonic-gate * return 0 if creating temp file is successful, returns -1 otherwise
7250Sstevel@tonic-gate */
7260Sstevel@tonic-gate static int
create_updated_keystore_version(int fd,char * tmp_fname)7270Sstevel@tonic-gate create_updated_keystore_version(int fd, char *tmp_fname)
7280Sstevel@tonic-gate {
7290Sstevel@tonic-gate int version, tmp_fd;
7300Sstevel@tonic-gate char buf[BUFSIZ];
7310Sstevel@tonic-gate size_t nread;
7320Sstevel@tonic-gate
7330Sstevel@tonic-gate /* first, create the tempoary file */
7348932SDina.Nimeh@Sun.COM tmp_fd = open_nointr(tmp_fname,
7358932SDina.Nimeh@Sun.COM O_WRONLY|O_CREAT|O_EXCL|O_NONBLOCK, S_IRUSR|S_IWUSR);
7360Sstevel@tonic-gate if (tmp_fd < 0) {
7370Sstevel@tonic-gate return (-1);
7380Sstevel@tonic-gate }
7390Sstevel@tonic-gate
7400Sstevel@tonic-gate /*
7410Sstevel@tonic-gate * copy everything from keystore version to temp file except
7420Sstevel@tonic-gate * the keystore version. Keystore version is updated
7430Sstevel@tonic-gate *
7440Sstevel@tonic-gate */
7450Sstevel@tonic-gate
7460Sstevel@tonic-gate /* pkcs11 version */
7478932SDina.Nimeh@Sun.COM if (readn_nointr(fd, buf, KS_PKCS11_VER_SIZE) != KS_PKCS11_VER_SIZE) {
7480Sstevel@tonic-gate goto cleanup;
7490Sstevel@tonic-gate }
7500Sstevel@tonic-gate
7518932SDina.Nimeh@Sun.COM if (writen_nointr(tmp_fd, buf, KS_PKCS11_VER_SIZE) !=
7528932SDina.Nimeh@Sun.COM KS_PKCS11_VER_SIZE) {
7530Sstevel@tonic-gate goto cleanup;
7540Sstevel@tonic-gate }
7550Sstevel@tonic-gate
7560Sstevel@tonic-gate /* version number, it needs to be updated */
7570Sstevel@tonic-gate
7580Sstevel@tonic-gate /* read the current version number */
7598932SDina.Nimeh@Sun.COM if (readn_nointr(fd, &version, KS_VER_SIZE) != KS_VER_SIZE) {
7600Sstevel@tonic-gate goto cleanup;
7610Sstevel@tonic-gate }
7620Sstevel@tonic-gate
7630Sstevel@tonic-gate version = SWAP32(version);
7640Sstevel@tonic-gate version++;
7650Sstevel@tonic-gate version = SWAP32(version);
7660Sstevel@tonic-gate
7670Sstevel@tonic-gate /* write the updated value to the tmp file */
7688932SDina.Nimeh@Sun.COM if (writen_nointr(tmp_fd, (void *)&version, KS_VER_SIZE)
7690Sstevel@tonic-gate != KS_VER_SIZE) {
7700Sstevel@tonic-gate goto cleanup;
7710Sstevel@tonic-gate }
7720Sstevel@tonic-gate
7730Sstevel@tonic-gate /* read rest of information, nothing needs to be updated */
7748932SDina.Nimeh@Sun.COM nread = readn_nointr(fd, buf, BUFSIZ);
7750Sstevel@tonic-gate while (nread > 0) {
7768932SDina.Nimeh@Sun.COM if (writen_nointr(tmp_fd, buf, nread) != nread) {
7770Sstevel@tonic-gate goto cleanup;
7780Sstevel@tonic-gate }
7798932SDina.Nimeh@Sun.COM nread = readn_nointr(fd, buf, BUFSIZ);
7800Sstevel@tonic-gate }
7810Sstevel@tonic-gate
7820Sstevel@tonic-gate (void) close(tmp_fd);
7830Sstevel@tonic-gate return (0); /* no error */
7840Sstevel@tonic-gate
7850Sstevel@tonic-gate cleanup:
7860Sstevel@tonic-gate (void) close(tmp_fd);
7870Sstevel@tonic-gate (void) remove(tmp_fname);
7880Sstevel@tonic-gate return (-1);
7890Sstevel@tonic-gate }
7900Sstevel@tonic-gate
7910Sstevel@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)7920Sstevel@tonic-gate get_all_objs_in_dir(DIR *dirp, ks_obj_handle_t *ks_handle,
793871Scasper ks_obj_t **result_obj_list, boolean_t lock_held)
7940Sstevel@tonic-gate {
795871Scasper struct dirent *dp;
7960Sstevel@tonic-gate ks_obj_t *obj;
7970Sstevel@tonic-gate CK_RV rv;
798871Scasper
799871Scasper while ((dp = readdir(dirp)) != NULL) {
8000Sstevel@tonic-gate
8019341SAnthony.Scarpino@Sun.COM if (strncmp(dp->d_name, OBJ_PREFIX, OBJ_PREFIX_LEN) != 0)
8020Sstevel@tonic-gate continue;
8030Sstevel@tonic-gate
8040Sstevel@tonic-gate (void) strcpy((char *)ks_handle->name, dp->d_name);
8050Sstevel@tonic-gate rv = soft_keystore_get_single_obj(ks_handle, &obj, lock_held);
8060Sstevel@tonic-gate if (rv != CKR_OK) {
8070Sstevel@tonic-gate return (rv);
8080Sstevel@tonic-gate }
8090Sstevel@tonic-gate if (obj != NULL) {
8100Sstevel@tonic-gate if (*result_obj_list == NULL) {
8110Sstevel@tonic-gate *result_obj_list = obj;
8120Sstevel@tonic-gate } else {
8130Sstevel@tonic-gate obj->next = *result_obj_list;
8140Sstevel@tonic-gate *result_obj_list = obj;
8150Sstevel@tonic-gate }
8160Sstevel@tonic-gate }
8170Sstevel@tonic-gate }
8180Sstevel@tonic-gate return (CKR_OK);
8190Sstevel@tonic-gate }
8200Sstevel@tonic-gate
8210Sstevel@tonic-gate /*
8220Sstevel@tonic-gate * This function prepares the obj data for encryption by prepending
8230Sstevel@tonic-gate * the FULL path of the file that will be used for storing
8240Sstevel@tonic-gate * the object. Having full path of the file as part of
8250Sstevel@tonic-gate * of the data for the object will prevent an attacker from
8260Sstevel@tonic-gate * copying a "bad" object into the keystore undetected.
8270Sstevel@tonic-gate *
8280Sstevel@tonic-gate * This function will always allocate:
8290Sstevel@tonic-gate * MAXPATHLEN + buf_len
8300Sstevel@tonic-gate * amount of data. If the full path of the filename doesn't occupy
8310Sstevel@tonic-gate * the whole MAXPATHLEN, the rest of the space will just be empty.
8320Sstevel@tonic-gate * It is the caller's responsibility to free the buffer allocated here.
8330Sstevel@tonic-gate *
8340Sstevel@tonic-gate * The allocated buffer is returned in the variable "prepared_buf"
8350Sstevel@tonic-gate * if there's no error.
8360Sstevel@tonic-gate *
8370Sstevel@tonic-gate * Returns 0 if there's no error, -1 otherwise.
8380Sstevel@tonic-gate */
8390Sstevel@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)8400Sstevel@tonic-gate prepare_data_for_encrypt(char *obj_path, unsigned char *buf, CK_ULONG buf_len,
8410Sstevel@tonic-gate unsigned char **prepared_buf, CK_ULONG *prepared_len)
8420Sstevel@tonic-gate {
8430Sstevel@tonic-gate *prepared_len = MAXPATHLEN + buf_len;
8440Sstevel@tonic-gate *prepared_buf = malloc(*prepared_len);
8450Sstevel@tonic-gate if (*prepared_buf == NULL) {
8460Sstevel@tonic-gate return (-1);
8470Sstevel@tonic-gate }
8480Sstevel@tonic-gate
8490Sstevel@tonic-gate /*
8500Sstevel@tonic-gate * only zero out the space for the path name. I could zero out
8510Sstevel@tonic-gate * the whole buffer, but that will be a waste of processing
8520Sstevel@tonic-gate * cycle since the rest of the buffer will be 100% filled all
8530Sstevel@tonic-gate * the time
8540Sstevel@tonic-gate */
8550Sstevel@tonic-gate bzero(*prepared_buf, MAXPATHLEN);
8560Sstevel@tonic-gate (void) memcpy(*prepared_buf, obj_path, strlen(obj_path));
8570Sstevel@tonic-gate (void) memcpy(*prepared_buf + MAXPATHLEN, buf, buf_len);
8580Sstevel@tonic-gate return (0);
8590Sstevel@tonic-gate }
8600Sstevel@tonic-gate
8610Sstevel@tonic-gate /*
8620Sstevel@tonic-gate * retrieves the hashed pin from the keystore
8630Sstevel@tonic-gate */
8640Sstevel@tonic-gate static CK_RV
get_hashed_pin(int fd,char ** hashed_pin)8650Sstevel@tonic-gate get_hashed_pin(int fd, char **hashed_pin)
8660Sstevel@tonic-gate {
8670Sstevel@tonic-gate uint64_t hashed_pin_size;
8680Sstevel@tonic-gate
8690Sstevel@tonic-gate if (ks_hashed_pinlen_offset == -1) {
8700Sstevel@tonic-gate if (calculate_hashed_pin_offset(fd) != 0) {
8710Sstevel@tonic-gate return (CKR_FUNCTION_FAILED);
8720Sstevel@tonic-gate }
8730Sstevel@tonic-gate }
8740Sstevel@tonic-gate
8750Sstevel@tonic-gate /* first, get size of the hashed pin */
8760Sstevel@tonic-gate if (lseek(fd, ks_hashed_pinlen_offset, SEEK_SET)
8770Sstevel@tonic-gate != ks_hashed_pinlen_offset) {
8780Sstevel@tonic-gate return (CKR_FUNCTION_FAILED);
8790Sstevel@tonic-gate }
8800Sstevel@tonic-gate
8818932SDina.Nimeh@Sun.COM if (readn_nointr(fd, (char *)&hashed_pin_size,
8820Sstevel@tonic-gate KS_HASHED_PINLEN_SIZE) != KS_HASHED_PINLEN_SIZE) {
8830Sstevel@tonic-gate return (CKR_FUNCTION_FAILED);
8840Sstevel@tonic-gate }
8850Sstevel@tonic-gate
8860Sstevel@tonic-gate hashed_pin_size = SWAP64(hashed_pin_size);
8870Sstevel@tonic-gate
8880Sstevel@tonic-gate *hashed_pin = malloc(hashed_pin_size + 1);
8890Sstevel@tonic-gate if (*hashed_pin == NULL) {
8900Sstevel@tonic-gate return (CKR_HOST_MEMORY);
8910Sstevel@tonic-gate }
8920Sstevel@tonic-gate
8938932SDina.Nimeh@Sun.COM if ((readn_nointr(fd, *hashed_pin, hashed_pin_size))
8940Sstevel@tonic-gate != (ssize_t)hashed_pin_size) {
8950Sstevel@tonic-gate free(*hashed_pin);
8960Sstevel@tonic-gate *hashed_pin = NULL;
8970Sstevel@tonic-gate return (CKR_FUNCTION_FAILED);
8980Sstevel@tonic-gate }
8990Sstevel@tonic-gate (*hashed_pin)[hashed_pin_size] = '\0';
9000Sstevel@tonic-gate return (CKR_OK);
9010Sstevel@tonic-gate }
9020Sstevel@tonic-gate
9030Sstevel@tonic-gate
9040Sstevel@tonic-gate /*
9050Sstevel@tonic-gate * FUNCTION: soft_keystore_lock
9060Sstevel@tonic-gate *
9070Sstevel@tonic-gate * ARGUMENTS:
9080Sstevel@tonic-gate * set_lock: TRUE to set readlock on the keystore object file,
9090Sstevel@tonic-gate * FALSE to remove readlock on keystore object file.
9100Sstevel@tonic-gate *
9110Sstevel@tonic-gate * RETURN VALUE:
9120Sstevel@tonic-gate *
9130Sstevel@tonic-gate * 0: success
9140Sstevel@tonic-gate * -1: failure
9150Sstevel@tonic-gate *
9160Sstevel@tonic-gate * DESCRIPTION:
9170Sstevel@tonic-gate *
9180Sstevel@tonic-gate * set or remove readlock on the keystore description file.
9190Sstevel@tonic-gate */
9200Sstevel@tonic-gate int
soft_keystore_readlock(boolean_t set_lock)9210Sstevel@tonic-gate soft_keystore_readlock(boolean_t set_lock)
9220Sstevel@tonic-gate {
9230Sstevel@tonic-gate
9240Sstevel@tonic-gate return (lock_desc_file(B_TRUE, set_lock));
9250Sstevel@tonic-gate }
9260Sstevel@tonic-gate
9270Sstevel@tonic-gate
9280Sstevel@tonic-gate /*
9290Sstevel@tonic-gate * FUNCTION: soft_keystore_writelock
9300Sstevel@tonic-gate *
9310Sstevel@tonic-gate * ARGUMENTS:
9320Sstevel@tonic-gate * set_lock: TRUE to set writelock on the keystore description file
9330Sstevel@tonic-gate * FALSE to remove write lock on keystore description file.
9340Sstevel@tonic-gate *
9350Sstevel@tonic-gate * RETURN VALUE:
9360Sstevel@tonic-gate *
9370Sstevel@tonic-gate * 0: no error
9380Sstevel@tonic-gate * 1: some error occurred
9390Sstevel@tonic-gate *
9400Sstevel@tonic-gate * DESCRIPTION:
9410Sstevel@tonic-gate * set/reset writelock on the keystore description file.
9420Sstevel@tonic-gate */
9430Sstevel@tonic-gate int
soft_keystore_writelock(boolean_t set_lock)9440Sstevel@tonic-gate soft_keystore_writelock(boolean_t set_lock)
9450Sstevel@tonic-gate {
9460Sstevel@tonic-gate return (lock_desc_file(B_FALSE, set_lock));
9470Sstevel@tonic-gate
9480Sstevel@tonic-gate }
9490Sstevel@tonic-gate
9500Sstevel@tonic-gate /*
9510Sstevel@tonic-gate *
9520Sstevel@tonic-gate * FUNCTION: soft_keystore_lock_object
9530Sstevel@tonic-gate *
9540Sstevel@tonic-gate * ARGUMENTS:
9550Sstevel@tonic-gate *
9560Sstevel@tonic-gate * ks_handle: handle of the keystore object file to be accessed.
9570Sstevel@tonic-gate * read_lock: TRUE to set readlock on the keystore object file,
9580Sstevel@tonic-gate * FALSE to set writelock on keystore object file.
9590Sstevel@tonic-gate *
9600Sstevel@tonic-gate * RETURN VALUE:
9610Sstevel@tonic-gate *
9620Sstevel@tonic-gate * If no error, file descriptor of locked file will be returned
9630Sstevel@tonic-gate * -1: some error occurred
9640Sstevel@tonic-gate *
9650Sstevel@tonic-gate * DESCRIPTION:
9660Sstevel@tonic-gate *
9670Sstevel@tonic-gate * set readlock or writelock on the keystore object file.
9680Sstevel@tonic-gate */
9690Sstevel@tonic-gate int
soft_keystore_lock_object(ks_obj_handle_t * ks_handle,boolean_t read_lock)9700Sstevel@tonic-gate soft_keystore_lock_object(ks_obj_handle_t *ks_handle, boolean_t read_lock)
9710Sstevel@tonic-gate {
9720Sstevel@tonic-gate int fd;
9730Sstevel@tonic-gate int oflag;
9740Sstevel@tonic-gate
9750Sstevel@tonic-gate if (read_lock) {
9760Sstevel@tonic-gate oflag = O_RDONLY;
9770Sstevel@tonic-gate } else {
9780Sstevel@tonic-gate oflag = O_WRONLY;
9790Sstevel@tonic-gate }
9800Sstevel@tonic-gate
9810Sstevel@tonic-gate if ((fd = open_and_lock_object_file(ks_handle, oflag, B_FALSE)) < 0) {
9820Sstevel@tonic-gate return (-1);
9830Sstevel@tonic-gate }
9840Sstevel@tonic-gate
9850Sstevel@tonic-gate return (fd);
9860Sstevel@tonic-gate }
9870Sstevel@tonic-gate
9880Sstevel@tonic-gate /*
9890Sstevel@tonic-gate * FUNCTION: soft_keystore_unlock_object
9900Sstevel@tonic-gate *
9910Sstevel@tonic-gate * ARGUMENTS:
9920Sstevel@tonic-gate * fd: file descriptor returned from soft_keystore_lock_object
9930Sstevel@tonic-gate *
9940Sstevel@tonic-gate * RETURN VALUE:
9950Sstevel@tonic-gate * 0: no error
9960Sstevel@tonic-gate * 1: some error occurred while getting the pin
9970Sstevel@tonic-gate *
9980Sstevel@tonic-gate * DESCRIPTION:
9990Sstevel@tonic-gate * set/reset writelock on the keystore object file.
10000Sstevel@tonic-gate */
10010Sstevel@tonic-gate int
soft_keystore_unlock_object(int fd)10020Sstevel@tonic-gate soft_keystore_unlock_object(int fd)
10030Sstevel@tonic-gate {
10040Sstevel@tonic-gate if (lock_file(fd, B_TRUE, B_FALSE) != 0) {
10050Sstevel@tonic-gate return (1);
10060Sstevel@tonic-gate }
10070Sstevel@tonic-gate
10080Sstevel@tonic-gate (void) close(fd);
10090Sstevel@tonic-gate return (0);
10100Sstevel@tonic-gate }
10110Sstevel@tonic-gate
10120Sstevel@tonic-gate
10130Sstevel@tonic-gate
10140Sstevel@tonic-gate /*
10150Sstevel@tonic-gate * FUNCTION: soft_keystore_get_version
10160Sstevel@tonic-gate *
10170Sstevel@tonic-gate * ARGUMENTS:
10180Sstevel@tonic-gate * version: pointer to caller allocated memory for storing
10190Sstevel@tonic-gate * the version of the keystore.
10200Sstevel@tonic-gate * lock_held: TRUE if the lock is held by caller.
10210Sstevel@tonic-gate *
10220Sstevel@tonic-gate * RETURN VALUE:
10230Sstevel@tonic-gate *
10240Sstevel@tonic-gate * 0: no error
10250Sstevel@tonic-gate * -1: some error occurred while getting the version number
10260Sstevel@tonic-gate *
10270Sstevel@tonic-gate * DESCRIPTION:
10280Sstevel@tonic-gate * get the version number of the keystore from keystore
10290Sstevel@tonic-gate * description file.
10300Sstevel@tonic-gate */
10310Sstevel@tonic-gate int
soft_keystore_get_version(uint_t * version,boolean_t lock_held)10320Sstevel@tonic-gate soft_keystore_get_version(uint_t *version, boolean_t lock_held)
10330Sstevel@tonic-gate {
10340Sstevel@tonic-gate int fd, ret_val = 0;
10350Sstevel@tonic-gate uint_t buf;
10360Sstevel@tonic-gate
10370Sstevel@tonic-gate if ((fd = open_and_lock_keystore_desc(O_RDONLY,
103812256SPeter.Shoults@Sun.COM B_FALSE, lock_held)) < 0) {
10390Sstevel@tonic-gate return (-1);
10400Sstevel@tonic-gate }
10410Sstevel@tonic-gate
10420Sstevel@tonic-gate if (lseek(fd, KS_VER_OFFSET, SEEK_SET) != KS_VER_OFFSET) {
10430Sstevel@tonic-gate ret_val = -1;
10440Sstevel@tonic-gate goto cleanup;
10450Sstevel@tonic-gate }
10460Sstevel@tonic-gate
10478932SDina.Nimeh@Sun.COM if (readn_nointr(fd, (char *)&buf, KS_VER_SIZE) != KS_VER_SIZE) {
10480Sstevel@tonic-gate ret_val = -1;
10490Sstevel@tonic-gate goto cleanup;
10500Sstevel@tonic-gate }
10510Sstevel@tonic-gate *version = SWAP32(buf);
10520Sstevel@tonic-gate
10530Sstevel@tonic-gate cleanup:
10540Sstevel@tonic-gate
10550Sstevel@tonic-gate if (!lock_held) {
10560Sstevel@tonic-gate if (lock_file(fd, B_TRUE, B_FALSE) < 0) {
10570Sstevel@tonic-gate ret_val = -1;
10580Sstevel@tonic-gate }
10590Sstevel@tonic-gate }
10600Sstevel@tonic-gate
10610Sstevel@tonic-gate (void) close(fd);
10620Sstevel@tonic-gate return (ret_val);
10630Sstevel@tonic-gate }
10640Sstevel@tonic-gate
10650Sstevel@tonic-gate /*
10660Sstevel@tonic-gate * FUNCTION: soft_keystore_get_object_version
10670Sstevel@tonic-gate *
10680Sstevel@tonic-gate * ARGUMENTS:
10690Sstevel@tonic-gate *
10700Sstevel@tonic-gate * ks_handle: handle of the key store object to be accessed.
10710Sstevel@tonic-gate * version:
10720Sstevel@tonic-gate * pointer to caller allocated memory for storing
10730Sstevel@tonic-gate * the version of the object.
10740Sstevel@tonic-gate * lock_held: TRUE if the lock is held by caller.
10750Sstevel@tonic-gate *
10760Sstevel@tonic-gate * RETURN VALUE:
10770Sstevel@tonic-gate *
10780Sstevel@tonic-gate * 0: no error
10790Sstevel@tonic-gate * -1: some error occurred while getting the pin
10800Sstevel@tonic-gate *
10810Sstevel@tonic-gate * DESCRIPTION:
10820Sstevel@tonic-gate * get the version number of the specified token object.
10830Sstevel@tonic-gate */
10840Sstevel@tonic-gate int
soft_keystore_get_object_version(ks_obj_handle_t * ks_handle,uint_t * version,boolean_t lock_held)10850Sstevel@tonic-gate soft_keystore_get_object_version(ks_obj_handle_t *ks_handle,
10860Sstevel@tonic-gate uint_t *version, boolean_t lock_held)
10870Sstevel@tonic-gate {
10880Sstevel@tonic-gate int fd, ret_val = 0;
10890Sstevel@tonic-gate uint_t tmp;
10900Sstevel@tonic-gate
10910Sstevel@tonic-gate if ((fd = open_and_lock_object_file(ks_handle, O_RDONLY,
10920Sstevel@tonic-gate lock_held)) < 0) {
10930Sstevel@tonic-gate return (-1);
10940Sstevel@tonic-gate }
10950Sstevel@tonic-gate
10960Sstevel@tonic-gate /*
10970Sstevel@tonic-gate * read version. Version is always first item in object file
10980Sstevel@tonic-gate * so, no need to do lseek
10990Sstevel@tonic-gate */
11008932SDina.Nimeh@Sun.COM if (readn_nointr(fd, (char *)&tmp, OBJ_VER_SIZE) != OBJ_VER_SIZE) {
11010Sstevel@tonic-gate ret_val = -1;
11020Sstevel@tonic-gate goto cleanup;
11030Sstevel@tonic-gate }
11040Sstevel@tonic-gate
11050Sstevel@tonic-gate *version = SWAP32(tmp);
11060Sstevel@tonic-gate
11070Sstevel@tonic-gate cleanup:
11080Sstevel@tonic-gate if (!lock_held) {
11090Sstevel@tonic-gate if (lock_file(fd, B_TRUE, B_FALSE) < 0) {
11100Sstevel@tonic-gate ret_val = -1;
11110Sstevel@tonic-gate }
11120Sstevel@tonic-gate }
11130Sstevel@tonic-gate
11140Sstevel@tonic-gate
11150Sstevel@tonic-gate (void) close(fd);
11160Sstevel@tonic-gate return (ret_val);
11170Sstevel@tonic-gate }
11180Sstevel@tonic-gate
11190Sstevel@tonic-gate /*
11200Sstevel@tonic-gate * FUNCTION: soft_keystore_getpin
11210Sstevel@tonic-gate *
11220Sstevel@tonic-gate * ARGUMENTS:
11230Sstevel@tonic-gate * hashed_pin: pointer to caller allocated memory
11240Sstevel@tonic-gate * for storing the pin to be returned.
11250Sstevel@tonic-gate * lock_held: TRUE if the lock is held by caller.
11260Sstevel@tonic-gate *
11270Sstevel@tonic-gate * RETURN VALUE:
11280Sstevel@tonic-gate *
11290Sstevel@tonic-gate * 0: no error
11300Sstevel@tonic-gate * -1: some error occurred while getting the pin
11310Sstevel@tonic-gate *
11320Sstevel@tonic-gate * DESCRIPTION:
11330Sstevel@tonic-gate *
11340Sstevel@tonic-gate * Reads the MD5 hash from the keystore description
11350Sstevel@tonic-gate * file and return it to the caller in the provided
11360Sstevel@tonic-gate * buffer. If there is no PIN in the description file
11370Sstevel@tonic-gate * because the file is just created, this function
11380Sstevel@tonic-gate * will get a MD5 digest of the string "changeme",
11390Sstevel@tonic-gate * store it in the file, and also return this
11400Sstevel@tonic-gate * string to the caller.
11410Sstevel@tonic-gate */
11420Sstevel@tonic-gate int
soft_keystore_getpin(char ** hashed_pin,boolean_t lock_held)11430Sstevel@tonic-gate soft_keystore_getpin(char **hashed_pin, boolean_t lock_held)
11440Sstevel@tonic-gate {
11450Sstevel@tonic-gate int fd, ret_val = -1;
11460Sstevel@tonic-gate CK_RV rv;
11470Sstevel@tonic-gate
114812256SPeter.Shoults@Sun.COM if ((fd = open_and_lock_keystore_desc(O_RDONLY, B_FALSE,
11490Sstevel@tonic-gate lock_held)) < 0) {
11500Sstevel@tonic-gate return (-1);
11510Sstevel@tonic-gate }
11520Sstevel@tonic-gate
11530Sstevel@tonic-gate rv = get_hashed_pin(fd, hashed_pin);
11540Sstevel@tonic-gate if (rv == CKR_OK) {
11550Sstevel@tonic-gate ret_val = 0;
11560Sstevel@tonic-gate }
11570Sstevel@tonic-gate
11580Sstevel@tonic-gate cleanup:
11590Sstevel@tonic-gate if (!lock_held) {
11600Sstevel@tonic-gate if (lock_file(fd, B_TRUE, B_FALSE) < 0) {
11610Sstevel@tonic-gate ret_val = -1;
11620Sstevel@tonic-gate }
11630Sstevel@tonic-gate }
11640Sstevel@tonic-gate
11650Sstevel@tonic-gate (void) close(fd);
11660Sstevel@tonic-gate return (ret_val);
11670Sstevel@tonic-gate }
11680Sstevel@tonic-gate
11699127SDina.Nimeh@Sun.COM
11709127SDina.Nimeh@Sun.COM /*
11719127SDina.Nimeh@Sun.COM * Generate a 16-byte Initialization Vector (IV).
11729127SDina.Nimeh@Sun.COM */
11739127SDina.Nimeh@Sun.COM CK_RV
soft_gen_iv(CK_BYTE * iv)11749127SDina.Nimeh@Sun.COM soft_gen_iv(CK_BYTE *iv)
11759127SDina.Nimeh@Sun.COM {
11769127SDina.Nimeh@Sun.COM return (pkcs11_get_nzero_urandom(iv, 16) < 0 ?
11779127SDina.Nimeh@Sun.COM CKR_DEVICE_ERROR : CKR_OK);
11789127SDina.Nimeh@Sun.COM }
11799127SDina.Nimeh@Sun.COM
11809127SDina.Nimeh@Sun.COM
11810Sstevel@tonic-gate /*
11820Sstevel@tonic-gate * This function reads all the data until the end of the file, and
11830Sstevel@tonic-gate * put the data into the "buf" in argument. Memory for buf will
11840Sstevel@tonic-gate * be allocated in this function. It is the caller's responsibility
11850Sstevel@tonic-gate * to free it. The number of bytes read will be returned
11860Sstevel@tonic-gate * in the argument "bytes_read"
11870Sstevel@tonic-gate *
11880Sstevel@tonic-gate * returns CKR_OK if no error. Other CKR error codes if there's an error
11890Sstevel@tonic-gate */
11900Sstevel@tonic-gate static CK_RV
read_obj_data(int old_fd,char ** buf,ssize_t * bytes_read)11910Sstevel@tonic-gate read_obj_data(int old_fd, char **buf, ssize_t *bytes_read)
11920Sstevel@tonic-gate {
11930Sstevel@tonic-gate
11940Sstevel@tonic-gate ssize_t nread, loop_count;
11950Sstevel@tonic-gate char *buf1 = NULL;
11960Sstevel@tonic-gate
11970Sstevel@tonic-gate *buf = malloc(BUFSIZ);
11980Sstevel@tonic-gate if (*buf == NULL) {
11990Sstevel@tonic-gate return (CKR_HOST_MEMORY);
12000Sstevel@tonic-gate }
12010Sstevel@tonic-gate
12028932SDina.Nimeh@Sun.COM nread = readn_nointr(old_fd, *buf, BUFSIZ);
12030Sstevel@tonic-gate if (nread < 0) {
12040Sstevel@tonic-gate free(*buf);
12050Sstevel@tonic-gate return (CKR_FUNCTION_FAILED);
12060Sstevel@tonic-gate }
12070Sstevel@tonic-gate loop_count = 1;
12080Sstevel@tonic-gate while (nread == (loop_count * BUFSIZ)) {
12090Sstevel@tonic-gate ssize_t nread_tmp;
12100Sstevel@tonic-gate
12110Sstevel@tonic-gate loop_count++;
12120Sstevel@tonic-gate /* more than BUFSIZ of data */
12130Sstevel@tonic-gate buf1 = realloc(*buf, loop_count * BUFSIZ);
12140Sstevel@tonic-gate if (buf1 == NULL) {
12150Sstevel@tonic-gate free(*buf);
12160Sstevel@tonic-gate return (CKR_HOST_MEMORY);
12170Sstevel@tonic-gate }
12180Sstevel@tonic-gate *buf = buf1;
12198932SDina.Nimeh@Sun.COM nread_tmp = readn_nointr(old_fd,
12200Sstevel@tonic-gate *buf + ((loop_count - 1) * BUFSIZ), BUFSIZ);
12210Sstevel@tonic-gate if (nread_tmp < 0) {
12220Sstevel@tonic-gate free(*buf);
12230Sstevel@tonic-gate return (CKR_FUNCTION_FAILED);
12240Sstevel@tonic-gate }
12250Sstevel@tonic-gate nread += nread_tmp;
12260Sstevel@tonic-gate }
12270Sstevel@tonic-gate *bytes_read = nread;
12280Sstevel@tonic-gate return (CKR_OK);
12290Sstevel@tonic-gate }
12300Sstevel@tonic-gate
12310Sstevel@tonic-gate /*
12320Sstevel@tonic-gate * Re-encrypt an object using the provided new_enc_key. The new HMAC
12330Sstevel@tonic-gate * is calculated using the new_hmac_key. The global static variables
12340Sstevel@tonic-gate * enc_key, and hmac_key will be used for decrypting the original
12350Sstevel@tonic-gate * object, and verifying its signature.
12360Sstevel@tonic-gate *
12370Sstevel@tonic-gate * The re-encrypted object will be stored in the file named
12380Sstevel@tonic-gate * in the "new_obj_name" variable. The content of the "original"
12390Sstevel@tonic-gate * file named in "orig_obj_name" is not disturbed.
12400Sstevel@tonic-gate *
12410Sstevel@tonic-gate * Returns 0 if there's no error, returns -1 otherwise.
12420Sstevel@tonic-gate *
12430Sstevel@tonic-gate */
12440Sstevel@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)12450Sstevel@tonic-gate reencrypt_obj(soft_object_t *new_enc_key, soft_object_t *new_hmac_key,
12460Sstevel@tonic-gate char *orig_obj_name, char *new_obj_name) {
12470Sstevel@tonic-gate
12480Sstevel@tonic-gate int old_fd, new_fd, version, ret_val = -1;
12490Sstevel@tonic-gate CK_BYTE iv[OBJ_IV_SIZE], old_iv[OBJ_IV_SIZE];
12500Sstevel@tonic-gate ssize_t nread;
12510Sstevel@tonic-gate CK_ULONG decrypted_len, encrypted_len, hmac_len;
12520Sstevel@tonic-gate CK_BYTE hmac[OBJ_HMAC_SIZE], *decrypted_buf = NULL, *buf = NULL;
12530Sstevel@tonic-gate
12548932SDina.Nimeh@Sun.COM old_fd = open_nointr(orig_obj_name, O_RDONLY|O_NONBLOCK);
12550Sstevel@tonic-gate if (old_fd < 0) {
12560Sstevel@tonic-gate return (-1);
12570Sstevel@tonic-gate }
12580Sstevel@tonic-gate
12590Sstevel@tonic-gate if (acquire_file_lock(&old_fd, orig_obj_name, O_RDONLY) != 0) {
12600Sstevel@tonic-gate if (old_fd > 0) {
12610Sstevel@tonic-gate (void) close(old_fd);
12620Sstevel@tonic-gate }
12630Sstevel@tonic-gate return (-1);
12640Sstevel@tonic-gate }
12650Sstevel@tonic-gate
12668932SDina.Nimeh@Sun.COM new_fd = open_nointr(new_obj_name,
12678932SDina.Nimeh@Sun.COM O_WRONLY|O_CREAT|O_EXCL|O_NONBLOCK, S_IRUSR|S_IWUSR);
12680Sstevel@tonic-gate if (new_fd < 0) {
12690Sstevel@tonic-gate (void) close(old_fd);
12700Sstevel@tonic-gate return (-1);
12710Sstevel@tonic-gate }
12720Sstevel@tonic-gate
12730Sstevel@tonic-gate if (lock_file(new_fd, B_FALSE, B_TRUE) != 0) {
12740Sstevel@tonic-gate /* unlock old file */
12750Sstevel@tonic-gate (void) lock_file(old_fd, B_TRUE, B_FALSE);
12760Sstevel@tonic-gate (void) close(old_fd);
12770Sstevel@tonic-gate (void) close(new_fd);
12780Sstevel@tonic-gate return (-1);
12790Sstevel@tonic-gate }
12800Sstevel@tonic-gate
12810Sstevel@tonic-gate /* read version, increment, and write to tmp file */
12828932SDina.Nimeh@Sun.COM if (readn_nointr(old_fd, (char *)&version, OBJ_VER_SIZE)
12830Sstevel@tonic-gate != OBJ_VER_SIZE) {
12840Sstevel@tonic-gate goto cleanup;
12850Sstevel@tonic-gate }
12860Sstevel@tonic-gate
12870Sstevel@tonic-gate version = SWAP32(version);
12880Sstevel@tonic-gate version++;
12890Sstevel@tonic-gate version = SWAP32(version);
12900Sstevel@tonic-gate
12918932SDina.Nimeh@Sun.COM if (writen_nointr(new_fd, (char *)&version, OBJ_VER_SIZE)
12920Sstevel@tonic-gate != OBJ_VER_SIZE) {
12930Sstevel@tonic-gate goto cleanup;
12940Sstevel@tonic-gate }
12950Sstevel@tonic-gate
12960Sstevel@tonic-gate /* read old iv */
12978932SDina.Nimeh@Sun.COM if (readn_nointr(old_fd, (char *)old_iv, OBJ_IV_SIZE) != OBJ_IV_SIZE) {
12980Sstevel@tonic-gate goto cleanup;
12990Sstevel@tonic-gate }
13000Sstevel@tonic-gate
13010Sstevel@tonic-gate /* generate new IV */
13020Sstevel@tonic-gate if (soft_gen_iv(iv) != CKR_OK) {
13030Sstevel@tonic-gate goto cleanup;
13040Sstevel@tonic-gate }
13050Sstevel@tonic-gate
13068932SDina.Nimeh@Sun.COM if (writen_nointr(new_fd, (char *)iv, OBJ_IV_SIZE) != OBJ_IV_SIZE) {
13070Sstevel@tonic-gate goto cleanup;
13080Sstevel@tonic-gate }
13090Sstevel@tonic-gate
13100Sstevel@tonic-gate /* seek to the original encrypted data, and read all of them */
13110Sstevel@tonic-gate if (lseek(old_fd, OBJ_DATA_OFFSET, SEEK_SET) != OBJ_DATA_OFFSET) {
13120Sstevel@tonic-gate goto cleanup;
13130Sstevel@tonic-gate }
13140Sstevel@tonic-gate
13150Sstevel@tonic-gate if (read_obj_data(old_fd, (char **)&buf, &nread) != CKR_OK) {
13160Sstevel@tonic-gate goto cleanup;
13170Sstevel@tonic-gate }
13180Sstevel@tonic-gate
13190Sstevel@tonic-gate /* decrypt data using old key */
13200Sstevel@tonic-gate decrypted_len = 0;
13210Sstevel@tonic-gate if (soft_keystore_crypt(enc_key, old_iv, B_FALSE, buf, nread,
13220Sstevel@tonic-gate NULL, &decrypted_len) != CKR_OK) {
13230Sstevel@tonic-gate free(buf);
13240Sstevel@tonic-gate goto cleanup;
13250Sstevel@tonic-gate }
13260Sstevel@tonic-gate
13270Sstevel@tonic-gate decrypted_buf = malloc(decrypted_len);
13280Sstevel@tonic-gate if (decrypted_buf == NULL) {
13290Sstevel@tonic-gate free(buf);
13300Sstevel@tonic-gate goto cleanup;
13310Sstevel@tonic-gate }
13320Sstevel@tonic-gate
13330Sstevel@tonic-gate if (soft_keystore_crypt(enc_key, old_iv, B_FALSE, buf, nread,
13340Sstevel@tonic-gate decrypted_buf, &decrypted_len) != CKR_OK) {
13350Sstevel@tonic-gate free(buf);
13360Sstevel@tonic-gate free(decrypted_buf);
13370Sstevel@tonic-gate goto cleanup;
13380Sstevel@tonic-gate }
13390Sstevel@tonic-gate
13400Sstevel@tonic-gate free(buf);
13410Sstevel@tonic-gate
13420Sstevel@tonic-gate /* re-encrypt with new key */
13430Sstevel@tonic-gate encrypted_len = 0;
13440Sstevel@tonic-gate if (soft_keystore_crypt(new_enc_key, iv, B_TRUE, decrypted_buf,
13450Sstevel@tonic-gate decrypted_len, NULL, &encrypted_len) != CKR_OK) {
13460Sstevel@tonic-gate free(decrypted_buf);
13470Sstevel@tonic-gate goto cleanup;
13480Sstevel@tonic-gate }
13490Sstevel@tonic-gate
13500Sstevel@tonic-gate buf = malloc(encrypted_len);
13510Sstevel@tonic-gate if (buf == NULL) {
13520Sstevel@tonic-gate free(decrypted_buf);
13530Sstevel@tonic-gate goto cleanup;
13540Sstevel@tonic-gate }
13550Sstevel@tonic-gate
13560Sstevel@tonic-gate if (soft_keystore_crypt(new_enc_key, iv, B_TRUE, decrypted_buf,
13570Sstevel@tonic-gate decrypted_len, buf, &encrypted_len) != CKR_OK) {
13580Sstevel@tonic-gate free(buf);
13590Sstevel@tonic-gate free(decrypted_buf);
13600Sstevel@tonic-gate goto cleanup;
13610Sstevel@tonic-gate }
13620Sstevel@tonic-gate
13630Sstevel@tonic-gate free(decrypted_buf);
13640Sstevel@tonic-gate
13650Sstevel@tonic-gate /* calculate hmac on re-encrypted data using new hmac key */
13660Sstevel@tonic-gate hmac_len = OBJ_HMAC_SIZE;
13670Sstevel@tonic-gate if (soft_keystore_hmac(new_hmac_key, B_TRUE, buf,
13680Sstevel@tonic-gate encrypted_len, hmac, &hmac_len) != CKR_OK) {
13690Sstevel@tonic-gate free(buf);
13700Sstevel@tonic-gate goto cleanup;
13710Sstevel@tonic-gate }
13720Sstevel@tonic-gate
13730Sstevel@tonic-gate /* just for sanity check */
13740Sstevel@tonic-gate if (hmac_len != OBJ_HMAC_SIZE) {
13750Sstevel@tonic-gate free(buf);
13760Sstevel@tonic-gate goto cleanup;
13770Sstevel@tonic-gate }
13780Sstevel@tonic-gate
13790Sstevel@tonic-gate /* write new hmac */
13808932SDina.Nimeh@Sun.COM if (writen_nointr(new_fd, (char *)hmac, OBJ_HMAC_SIZE)
13810Sstevel@tonic-gate != OBJ_HMAC_SIZE) {
13820Sstevel@tonic-gate free(buf);
13830Sstevel@tonic-gate goto cleanup;
13840Sstevel@tonic-gate }
13850Sstevel@tonic-gate
13860Sstevel@tonic-gate /* write re-encrypted buffer to temp file */
13878932SDina.Nimeh@Sun.COM if (writen_nointr(new_fd, (void *)buf, encrypted_len)
13880Sstevel@tonic-gate != encrypted_len) {
13890Sstevel@tonic-gate free(buf);
13900Sstevel@tonic-gate goto cleanup;
13910Sstevel@tonic-gate }
13920Sstevel@tonic-gate free(buf);
13930Sstevel@tonic-gate ret_val = 0;
13940Sstevel@tonic-gate
13950Sstevel@tonic-gate cleanup:
13960Sstevel@tonic-gate /* unlock the files */
13970Sstevel@tonic-gate (void) lock_file(old_fd, B_TRUE, B_FALSE);
13980Sstevel@tonic-gate (void) lock_file(new_fd, B_FALSE, B_FALSE);
13990Sstevel@tonic-gate
14000Sstevel@tonic-gate (void) close(old_fd);
14010Sstevel@tonic-gate (void) close(new_fd);
14020Sstevel@tonic-gate if (ret_val != 0) {
14030Sstevel@tonic-gate (void) remove(new_obj_name);
14040Sstevel@tonic-gate }
14050Sstevel@tonic-gate return (ret_val);
14060Sstevel@tonic-gate }
14070Sstevel@tonic-gate
14080Sstevel@tonic-gate /*
14090Sstevel@tonic-gate * FUNCTION: soft_keystore_setpin
14100Sstevel@tonic-gate *
14110Sstevel@tonic-gate * ARGUMENTS:
14120Sstevel@tonic-gate * newpin: new pin entered by the user.
14130Sstevel@tonic-gate * lock_held: TRUE if the lock is held by caller.
14140Sstevel@tonic-gate *
14150Sstevel@tonic-gate * RETURN VALUE:
14160Sstevel@tonic-gate * 0: no error
14170Sstevel@tonic-gate * -1: failure
14180Sstevel@tonic-gate *
14190Sstevel@tonic-gate * DESCRIPTION:
14200Sstevel@tonic-gate *
14210Sstevel@tonic-gate * This function does the following:
14220Sstevel@tonic-gate *
14230Sstevel@tonic-gate * 1) Generates crypted value of newpin and store it
14240Sstevel@tonic-gate * in keystore description file.
14250Sstevel@tonic-gate * 2) Dervies the new encryption key from the newpin. This key
14260Sstevel@tonic-gate * will be used to re-encrypt the private token objects.
14270Sstevel@tonic-gate * 3) Re-encrypt all of this user's existing private token
14280Sstevel@tonic-gate * objects (if any).
14290Sstevel@tonic-gate * 4) Increments the keystore version number.
14300Sstevel@tonic-gate */
14310Sstevel@tonic-gate int
soft_keystore_setpin(uchar_t * oldpin,uchar_t * newpin,boolean_t lock_held)14320Sstevel@tonic-gate soft_keystore_setpin(uchar_t *oldpin, uchar_t *newpin, boolean_t lock_held)
14330Sstevel@tonic-gate {
14340Sstevel@tonic-gate int fd, tmp_ks_fd, version, ret_val = -1;
14350Sstevel@tonic-gate soft_object_t *new_crypt_key = NULL, *new_hmac_key = NULL;
14360Sstevel@tonic-gate char filebuf[BUFSIZ];
14370Sstevel@tonic-gate DIR *pri_dirp;
1438871Scasper struct dirent *pri_ent;
14390Sstevel@tonic-gate char pri_obj_path[MAXPATHLEN], ks_desc_file[MAXPATHLEN],
14400Sstevel@tonic-gate tmp_ks_desc_name[MAXPATHLEN];
14410Sstevel@tonic-gate typedef struct priobjs {
14420Sstevel@tonic-gate char orig_name[MAXPATHLEN];
14430Sstevel@tonic-gate char tmp_name[MAXPATHLEN];
14440Sstevel@tonic-gate struct priobjs *next;
14450Sstevel@tonic-gate } priobjs_t;
14460Sstevel@tonic-gate priobjs_t *pri_objs = NULL, *tmp;
14470Sstevel@tonic-gate CK_BYTE *crypt_salt = NULL, *hmac_salt = NULL;
14480Sstevel@tonic-gate boolean_t pin_never_set = B_FALSE, user_logged_in;
14490Sstevel@tonic-gate char *new_hashed_pin = NULL;
14500Sstevel@tonic-gate uint64_t hashed_pin_salt_length, new_hashed_pin_len, swaped_val;
14510Sstevel@tonic-gate char *hashed_pin_salt = NULL;
14520Sstevel@tonic-gate priobjs_t *obj;
14530Sstevel@tonic-gate
14540Sstevel@tonic-gate if ((enc_key == NULL) ||
14550Sstevel@tonic-gate (enc_key->magic_marker != SOFTTOKEN_OBJECT_MAGIC)) {
14560Sstevel@tonic-gate user_logged_in = B_FALSE;
14570Sstevel@tonic-gate } else {
14580Sstevel@tonic-gate user_logged_in = B_TRUE;
14590Sstevel@tonic-gate }
14600Sstevel@tonic-gate
146112256SPeter.Shoults@Sun.COM if ((fd = open_and_lock_keystore_desc(O_RDWR, B_TRUE,
14620Sstevel@tonic-gate lock_held)) < 0) {
14630Sstevel@tonic-gate return (-1);
14640Sstevel@tonic-gate }
14650Sstevel@tonic-gate
14660Sstevel@tonic-gate (void) get_desc_file_path(ks_desc_file);
14670Sstevel@tonic-gate (void) get_tmp_desc_file_path(tmp_ks_desc_name);
14680Sstevel@tonic-gate
14690Sstevel@tonic-gate /*
14700Sstevel@tonic-gate * create a tempoary file for the keystore description
14710Sstevel@tonic-gate * file for updating version and counter information
14720Sstevel@tonic-gate */
14738932SDina.Nimeh@Sun.COM tmp_ks_fd = open_nointr(tmp_ks_desc_name,
14748932SDina.Nimeh@Sun.COM O_RDWR|O_CREAT|O_EXCL|O_NONBLOCK, S_IRUSR|S_IWUSR);
14750Sstevel@tonic-gate if (tmp_ks_fd < 0) {
14760Sstevel@tonic-gate (void) close(fd);
14770Sstevel@tonic-gate return (-1);
14780Sstevel@tonic-gate }
14790Sstevel@tonic-gate
14800Sstevel@tonic-gate /* read and write PKCS version to temp file */
14818932SDina.Nimeh@Sun.COM if (readn_nointr(fd, filebuf, KS_PKCS11_VER_SIZE)
14820Sstevel@tonic-gate != KS_PKCS11_VER_SIZE) {
14830Sstevel@tonic-gate goto cleanup;
14840Sstevel@tonic-gate }
14850Sstevel@tonic-gate
14868932SDina.Nimeh@Sun.COM if (writen_nointr(tmp_ks_fd, filebuf, KS_PKCS11_VER_SIZE)
14870Sstevel@tonic-gate != KS_PKCS11_VER_SIZE) {
14880Sstevel@tonic-gate goto cleanup;
14890Sstevel@tonic-gate }
14900Sstevel@tonic-gate
14910Sstevel@tonic-gate /* get version number, and write updated number to temp file */
14928932SDina.Nimeh@Sun.COM if (readn_nointr(fd, &version, KS_VER_SIZE) != KS_VER_SIZE) {
14930Sstevel@tonic-gate goto cleanup;
14940Sstevel@tonic-gate }
14950Sstevel@tonic-gate
14960Sstevel@tonic-gate version = SWAP32(version);
14970Sstevel@tonic-gate version++;
14980Sstevel@tonic-gate version = SWAP32(version);
14990Sstevel@tonic-gate
15008932SDina.Nimeh@Sun.COM if (writen_nointr(tmp_ks_fd, (void *)&version, KS_VER_SIZE)
15010Sstevel@tonic-gate != KS_VER_SIZE) {
15020Sstevel@tonic-gate goto cleanup;
15030Sstevel@tonic-gate }
15040Sstevel@tonic-gate
15050Sstevel@tonic-gate
15060Sstevel@tonic-gate /* read and write counter, no modification necessary */
15078932SDina.Nimeh@Sun.COM if (readn_nointr(fd, filebuf, KS_COUNTER_SIZE) != KS_COUNTER_SIZE) {
15080Sstevel@tonic-gate goto cleanup;
15090Sstevel@tonic-gate }
15100Sstevel@tonic-gate
15118932SDina.Nimeh@Sun.COM if (writen_nointr(tmp_ks_fd, filebuf, KS_COUNTER_SIZE)
15120Sstevel@tonic-gate != KS_COUNTER_SIZE) {
15130Sstevel@tonic-gate goto cleanup;
15140Sstevel@tonic-gate }
15150Sstevel@tonic-gate
15160Sstevel@tonic-gate /* read old encryption salt */
15170Sstevel@tonic-gate crypt_salt = malloc(KS_KEY_SALT_SIZE);
15180Sstevel@tonic-gate if (crypt_salt == NULL) {
15190Sstevel@tonic-gate goto cleanup;
15200Sstevel@tonic-gate }
15218932SDina.Nimeh@Sun.COM if (readn_nointr(fd, (char *)crypt_salt, KS_KEY_SALT_SIZE)
15220Sstevel@tonic-gate != KS_KEY_SALT_SIZE) {
15230Sstevel@tonic-gate goto cleanup;
15240Sstevel@tonic-gate }
15250Sstevel@tonic-gate
15260Sstevel@tonic-gate /* read old hmac salt */
15270Sstevel@tonic-gate hmac_salt = malloc(KS_HMAC_SALT_SIZE);
15280Sstevel@tonic-gate if (hmac_salt == NULL) {
15290Sstevel@tonic-gate goto cleanup;
15300Sstevel@tonic-gate }
15318932SDina.Nimeh@Sun.COM if (readn_nointr(fd, (char *)hmac_salt, KS_HMAC_SALT_SIZE)
15320Sstevel@tonic-gate != KS_HMAC_SALT_SIZE) {
15330Sstevel@tonic-gate goto cleanup;
15340Sstevel@tonic-gate }
15350Sstevel@tonic-gate
15360Sstevel@tonic-gate /* just create some empty bytes */
15370Sstevel@tonic-gate bzero(filebuf, sizeof (filebuf));
15380Sstevel@tonic-gate
15390Sstevel@tonic-gate if (memcmp(crypt_salt, filebuf, KS_KEY_SALT_SIZE) == 0) {
15400Sstevel@tonic-gate /* PIN as never been set */
15410Sstevel@tonic-gate CK_BYTE *new_crypt_salt = NULL, *new_hmac_salt = NULL;
15420Sstevel@tonic-gate
15430Sstevel@tonic-gate pin_never_set = B_TRUE;
15440Sstevel@tonic-gate if (soft_gen_crypt_key(newpin, &new_crypt_key, &new_crypt_salt)
15450Sstevel@tonic-gate != CKR_OK) {
15460Sstevel@tonic-gate goto cleanup;
15470Sstevel@tonic-gate }
15488932SDina.Nimeh@Sun.COM if (writen_nointr(tmp_ks_fd, (void *)new_crypt_salt,
15490Sstevel@tonic-gate KS_KEY_SALT_SIZE) != KS_KEY_SALT_SIZE) {
15500Sstevel@tonic-gate free(new_crypt_salt);
15510Sstevel@tonic-gate (void) soft_cleanup_object(new_crypt_key);
15520Sstevel@tonic-gate goto cleanup;
15530Sstevel@tonic-gate }
15540Sstevel@tonic-gate free(new_crypt_salt);
15550Sstevel@tonic-gate
15560Sstevel@tonic-gate if (soft_gen_hmac_key(newpin, &new_hmac_key, &new_hmac_salt)
15570Sstevel@tonic-gate != CKR_OK) {
15580Sstevel@tonic-gate (void) soft_cleanup_object(new_crypt_key);
15590Sstevel@tonic-gate goto cleanup;
15600Sstevel@tonic-gate }
15618932SDina.Nimeh@Sun.COM if (writen_nointr(tmp_ks_fd, (void *)new_hmac_salt,
15620Sstevel@tonic-gate KS_HMAC_SALT_SIZE) != KS_HMAC_SALT_SIZE) {
15630Sstevel@tonic-gate free(new_hmac_salt);
15640Sstevel@tonic-gate goto cleanup3;
15650Sstevel@tonic-gate }
15660Sstevel@tonic-gate free(new_hmac_salt);
15670Sstevel@tonic-gate } else {
15680Sstevel@tonic-gate if (soft_gen_crypt_key(newpin, &new_crypt_key,
15690Sstevel@tonic-gate (CK_BYTE **)&crypt_salt) != CKR_OK) {
15700Sstevel@tonic-gate goto cleanup;
15710Sstevel@tonic-gate }
15720Sstevel@tonic-gate /* no change to the encryption salt */
15738932SDina.Nimeh@Sun.COM if (writen_nointr(tmp_ks_fd, (void *)crypt_salt,
15740Sstevel@tonic-gate KS_KEY_SALT_SIZE) != KS_KEY_SALT_SIZE) {
15750Sstevel@tonic-gate (void) soft_cleanup_object(new_crypt_key);
15760Sstevel@tonic-gate goto cleanup;
15770Sstevel@tonic-gate }
15780Sstevel@tonic-gate
15790Sstevel@tonic-gate if (soft_gen_hmac_key(newpin, &new_hmac_key,
15800Sstevel@tonic-gate (CK_BYTE **)&hmac_salt) != CKR_OK) {
15810Sstevel@tonic-gate (void) soft_cleanup_object(new_crypt_key);
15820Sstevel@tonic-gate goto cleanup;
15830Sstevel@tonic-gate }
15840Sstevel@tonic-gate
15850Sstevel@tonic-gate /* no change to the hmac salt */
15868932SDina.Nimeh@Sun.COM if (writen_nointr(tmp_ks_fd, (void *)hmac_salt,
15870Sstevel@tonic-gate KS_HMAC_SALT_SIZE) != KS_HMAC_SALT_SIZE) {
15880Sstevel@tonic-gate goto cleanup3;
15890Sstevel@tonic-gate }
15900Sstevel@tonic-gate }
15910Sstevel@tonic-gate
15920Sstevel@tonic-gate /*
15930Sstevel@tonic-gate * read hashed pin salt, and write to updated keystore description
15940Sstevel@tonic-gate * file unmodified.
15950Sstevel@tonic-gate */
15968932SDina.Nimeh@Sun.COM if (readn_nointr(fd, (char *)&hashed_pin_salt_length,
15970Sstevel@tonic-gate KS_HASHED_PIN_SALT_LEN_SIZE) != KS_HASHED_PIN_SALT_LEN_SIZE) {
15980Sstevel@tonic-gate goto cleanup3;
15990Sstevel@tonic-gate }
16000Sstevel@tonic-gate
16018932SDina.Nimeh@Sun.COM if (writen_nointr(tmp_ks_fd, (void *)&hashed_pin_salt_length,
16020Sstevel@tonic-gate KS_HASHED_PIN_SALT_LEN_SIZE) != KS_HASHED_PIN_SALT_LEN_SIZE) {
16030Sstevel@tonic-gate goto cleanup3;
16040Sstevel@tonic-gate }
16050Sstevel@tonic-gate
16060Sstevel@tonic-gate hashed_pin_salt_length = SWAP64(hashed_pin_salt_length);
16070Sstevel@tonic-gate
16080Sstevel@tonic-gate hashed_pin_salt = malloc(hashed_pin_salt_length + 1);
16090Sstevel@tonic-gate if (hashed_pin_salt == NULL) {
16100Sstevel@tonic-gate goto cleanup3;
16110Sstevel@tonic-gate }
16120Sstevel@tonic-gate
16138932SDina.Nimeh@Sun.COM if ((readn_nointr(fd, hashed_pin_salt, hashed_pin_salt_length)) !=
16140Sstevel@tonic-gate (ssize_t)hashed_pin_salt_length) {
16150Sstevel@tonic-gate free(hashed_pin_salt);
16160Sstevel@tonic-gate goto cleanup3;
16170Sstevel@tonic-gate }
16180Sstevel@tonic-gate
16198932SDina.Nimeh@Sun.COM if ((writen_nointr(tmp_ks_fd, hashed_pin_salt, hashed_pin_salt_length))
16200Sstevel@tonic-gate != (ssize_t)hashed_pin_salt_length) {
16210Sstevel@tonic-gate free(hashed_pin_salt);
16220Sstevel@tonic-gate goto cleanup3;
16230Sstevel@tonic-gate }
16240Sstevel@tonic-gate
16250Sstevel@tonic-gate hashed_pin_salt[hashed_pin_salt_length] = '\0';
16260Sstevel@tonic-gate
16270Sstevel@tonic-gate /* old hashed pin length and value can be ignored, generate new one */
16280Sstevel@tonic-gate if (soft_gen_hashed_pin(newpin, &new_hashed_pin,
16290Sstevel@tonic-gate &hashed_pin_salt) < 0) {
16300Sstevel@tonic-gate free(hashed_pin_salt);
16310Sstevel@tonic-gate goto cleanup3;
16320Sstevel@tonic-gate }
16330Sstevel@tonic-gate
16340Sstevel@tonic-gate free(hashed_pin_salt);
16350Sstevel@tonic-gate
16360Sstevel@tonic-gate if (new_hashed_pin == NULL) {
16370Sstevel@tonic-gate goto cleanup3;
16380Sstevel@tonic-gate }
16390Sstevel@tonic-gate
16400Sstevel@tonic-gate new_hashed_pin_len = strlen(new_hashed_pin);
16410Sstevel@tonic-gate
16420Sstevel@tonic-gate /* write new hashed pin length to file */
16430Sstevel@tonic-gate swaped_val = SWAP64(new_hashed_pin_len);
16448932SDina.Nimeh@Sun.COM if (writen_nointr(tmp_ks_fd, (void *)&swaped_val,
16450Sstevel@tonic-gate KS_HASHED_PINLEN_SIZE) != KS_HASHED_PINLEN_SIZE) {
16460Sstevel@tonic-gate goto cleanup3;
16470Sstevel@tonic-gate }
16480Sstevel@tonic-gate
16498932SDina.Nimeh@Sun.COM if (writen_nointr(tmp_ks_fd, (void *)new_hashed_pin,
16500Sstevel@tonic-gate new_hashed_pin_len) != (ssize_t)new_hashed_pin_len) {
16510Sstevel@tonic-gate goto cleanup3;
16520Sstevel@tonic-gate }
16530Sstevel@tonic-gate
16540Sstevel@tonic-gate if (pin_never_set) {
16550Sstevel@tonic-gate /* there was no private object, no need to re-encrypt them */
16560Sstevel@tonic-gate goto rename_desc_file;
16570Sstevel@tonic-gate }
16580Sstevel@tonic-gate
16590Sstevel@tonic-gate /* re-encrypt all the private objects */
16600Sstevel@tonic-gate pri_dirp = opendir(get_pri_obj_path(pri_obj_path));
16610Sstevel@tonic-gate if (pri_dirp == NULL) {
16620Sstevel@tonic-gate /*
16630Sstevel@tonic-gate * this directory should exist, even if it doesn't contain
16640Sstevel@tonic-gate * any objects. Don't want to update the pin if the
16650Sstevel@tonic-gate * keystore is somehow messed up.
16660Sstevel@tonic-gate */
16670Sstevel@tonic-gate
16680Sstevel@tonic-gate goto cleanup3;
16690Sstevel@tonic-gate }
16700Sstevel@tonic-gate
16710Sstevel@tonic-gate /* if user did not login, need to set the old pin */
16720Sstevel@tonic-gate if (!user_logged_in) {
16730Sstevel@tonic-gate if (soft_keystore_authpin(oldpin) != 0) {
16740Sstevel@tonic-gate goto cleanup3;
16750Sstevel@tonic-gate }
16760Sstevel@tonic-gate }
16770Sstevel@tonic-gate
1678871Scasper while ((pri_ent = readdir(pri_dirp)) != NULL) {
16790Sstevel@tonic-gate
16800Sstevel@tonic-gate if ((strcmp(pri_ent->d_name, ".") == 0) ||
16810Sstevel@tonic-gate (strcmp(pri_ent->d_name, "..") == 0) ||
16820Sstevel@tonic-gate (strncmp(pri_ent->d_name, TMP_OBJ_PREFIX,
16830Sstevel@tonic-gate strlen(TMP_OBJ_PREFIX)) == 0)) {
16840Sstevel@tonic-gate continue;
16850Sstevel@tonic-gate }
16860Sstevel@tonic-gate
16870Sstevel@tonic-gate obj = malloc(sizeof (priobjs_t));
16880Sstevel@tonic-gate if (obj == NULL) {
16890Sstevel@tonic-gate goto cleanup2;
16900Sstevel@tonic-gate }
16910Sstevel@tonic-gate (void) snprintf(obj->orig_name, MAXPATHLEN,
16920Sstevel@tonic-gate "%s/%s", pri_obj_path, pri_ent->d_name);
16930Sstevel@tonic-gate (void) snprintf(obj->tmp_name, MAXPATHLEN, "%s/%s%s",
16940Sstevel@tonic-gate pri_obj_path, TMP_OBJ_PREFIX,
16959341SAnthony.Scarpino@Sun.COM (pri_ent->d_name) + OBJ_PREFIX_LEN);
16960Sstevel@tonic-gate if (reencrypt_obj(new_crypt_key, new_hmac_key,
16970Sstevel@tonic-gate obj->orig_name, obj->tmp_name) != 0) {
16980Sstevel@tonic-gate free(obj);
16990Sstevel@tonic-gate goto cleanup2;
17000Sstevel@tonic-gate }
17010Sstevel@tonic-gate
17020Sstevel@tonic-gate /* insert into list of file to be renamed */
17030Sstevel@tonic-gate if (pri_objs == NULL) {
17040Sstevel@tonic-gate obj->next = NULL;
17050Sstevel@tonic-gate pri_objs = obj;
17060Sstevel@tonic-gate } else {
17070Sstevel@tonic-gate obj->next = pri_objs;
17080Sstevel@tonic-gate pri_objs = obj;
17090Sstevel@tonic-gate }
17100Sstevel@tonic-gate }
17110Sstevel@tonic-gate
17120Sstevel@tonic-gate /* rename all the private objects */
17130Sstevel@tonic-gate tmp = pri_objs;
17140Sstevel@tonic-gate while (tmp) {
17150Sstevel@tonic-gate (void) rename(tmp->tmp_name, tmp->orig_name);
17160Sstevel@tonic-gate tmp = tmp->next;
17170Sstevel@tonic-gate }
17180Sstevel@tonic-gate
17190Sstevel@tonic-gate rename_desc_file:
17200Sstevel@tonic-gate
17210Sstevel@tonic-gate /* destroy the old encryption key, and hmac key */
17220Sstevel@tonic-gate if ((!pin_never_set) && (user_logged_in)) {
17230Sstevel@tonic-gate (void) soft_cleanup_object(enc_key);
17240Sstevel@tonic-gate (void) soft_cleanup_object(hmac_key);
17250Sstevel@tonic-gate }
17260Sstevel@tonic-gate
17270Sstevel@tonic-gate if (user_logged_in) {
17280Sstevel@tonic-gate enc_key = new_crypt_key;
17290Sstevel@tonic-gate hmac_key = new_hmac_key;
17300Sstevel@tonic-gate }
17310Sstevel@tonic-gate (void) rename(tmp_ks_desc_name, ks_desc_file);
17320Sstevel@tonic-gate
17330Sstevel@tonic-gate ret_val = 0;
17340Sstevel@tonic-gate
17350Sstevel@tonic-gate cleanup2:
17360Sstevel@tonic-gate if (pri_objs != NULL) {
17370Sstevel@tonic-gate priobjs_t *p = pri_objs;
17380Sstevel@tonic-gate while (p) {
17390Sstevel@tonic-gate tmp = p->next;
17400Sstevel@tonic-gate free(p);
17410Sstevel@tonic-gate p = tmp;
17420Sstevel@tonic-gate }
17430Sstevel@tonic-gate }
17440Sstevel@tonic-gate if (!pin_never_set) {
17450Sstevel@tonic-gate (void) closedir(pri_dirp);
17460Sstevel@tonic-gate }
17470Sstevel@tonic-gate
17480Sstevel@tonic-gate if ((!user_logged_in) && (!pin_never_set)) {
17490Sstevel@tonic-gate (void) soft_cleanup_object(enc_key);
17500Sstevel@tonic-gate (void) soft_cleanup_object(hmac_key);
17510Sstevel@tonic-gate enc_key = NULL;
17520Sstevel@tonic-gate hmac_key = NULL;
17530Sstevel@tonic-gate }
17540Sstevel@tonic-gate cleanup3:
17550Sstevel@tonic-gate if ((ret_val != 0) || (!user_logged_in)) {
17560Sstevel@tonic-gate (void) soft_cleanup_object(new_crypt_key);
17570Sstevel@tonic-gate (void) soft_cleanup_object(new_hmac_key);
17580Sstevel@tonic-gate }
17590Sstevel@tonic-gate
17600Sstevel@tonic-gate cleanup:
17610Sstevel@tonic-gate if (!lock_held) {
17620Sstevel@tonic-gate if (lock_file(fd, B_FALSE, B_FALSE) < 0) {
17630Sstevel@tonic-gate ret_val = 1;
17640Sstevel@tonic-gate }
17650Sstevel@tonic-gate }
17660Sstevel@tonic-gate if (crypt_salt != NULL) {
17670Sstevel@tonic-gate free(crypt_salt);
17680Sstevel@tonic-gate }
17690Sstevel@tonic-gate if (hmac_salt != NULL) {
17700Sstevel@tonic-gate free(hmac_salt);
17710Sstevel@tonic-gate }
17720Sstevel@tonic-gate (void) close(fd);
17730Sstevel@tonic-gate (void) close(tmp_ks_fd);
17740Sstevel@tonic-gate if (ret_val != 0) {
17750Sstevel@tonic-gate (void) remove(tmp_ks_desc_name);
17760Sstevel@tonic-gate }
17770Sstevel@tonic-gate return (ret_val);
17780Sstevel@tonic-gate }
17790Sstevel@tonic-gate
17800Sstevel@tonic-gate /*
17810Sstevel@tonic-gate * FUNCTION: soft_keystore_authpin
17820Sstevel@tonic-gate *
17830Sstevel@tonic-gate * ARGUMENTS:
17840Sstevel@tonic-gate * pin: pin specified by the user for logging into
17850Sstevel@tonic-gate * the keystore.
17860Sstevel@tonic-gate *
17870Sstevel@tonic-gate * RETURN VALUE:
17880Sstevel@tonic-gate * 0: if no error
17890Sstevel@tonic-gate * -1: if there is any error
17900Sstevel@tonic-gate *
17910Sstevel@tonic-gate * DESCRIPTION:
17920Sstevel@tonic-gate *
17930Sstevel@tonic-gate * This function takes the pin specified in the argument
17940Sstevel@tonic-gate * and generates an encryption key based on the pin.
17950Sstevel@tonic-gate * The generated encryption key will be used for
17960Sstevel@tonic-gate * all future encryption and decryption for private
17970Sstevel@tonic-gate * objects. Before this function is called, none
17980Sstevel@tonic-gate * of the keystore related interfaces is able
17990Sstevel@tonic-gate * to decrypt/encrypt any private object.
18000Sstevel@tonic-gate */
18010Sstevel@tonic-gate int
soft_keystore_authpin(uchar_t * pin)18020Sstevel@tonic-gate soft_keystore_authpin(uchar_t *pin)
18030Sstevel@tonic-gate {
18040Sstevel@tonic-gate int fd;
18050Sstevel@tonic-gate int ret_val = -1;
18060Sstevel@tonic-gate CK_BYTE *crypt_salt = NULL, *hmac_salt;
18070Sstevel@tonic-gate
18080Sstevel@tonic-gate /* get the salt from the keystore description file */
18090Sstevel@tonic-gate if ((fd = open_and_lock_keystore_desc(O_RDONLY,
18100Sstevel@tonic-gate B_FALSE, B_FALSE)) < 0) {
18110Sstevel@tonic-gate return (-1);
18120Sstevel@tonic-gate }
18130Sstevel@tonic-gate
18140Sstevel@tonic-gate crypt_salt = malloc(KS_KEY_SALT_SIZE);
18150Sstevel@tonic-gate if (crypt_salt == NULL) {
18160Sstevel@tonic-gate goto cleanup;
18170Sstevel@tonic-gate }
18180Sstevel@tonic-gate
18190Sstevel@tonic-gate if (lseek(fd, KS_KEY_SALT_OFFSET, SEEK_SET) != KS_KEY_SALT_OFFSET) {
18200Sstevel@tonic-gate goto cleanup;
18210Sstevel@tonic-gate }
18220Sstevel@tonic-gate
18238932SDina.Nimeh@Sun.COM if (readn_nointr(fd, (char *)crypt_salt, KS_KEY_SALT_SIZE)
18240Sstevel@tonic-gate != KS_KEY_SALT_SIZE) {
18250Sstevel@tonic-gate goto cleanup;
18260Sstevel@tonic-gate }
18270Sstevel@tonic-gate
18280Sstevel@tonic-gate if (soft_gen_crypt_key(pin, &enc_key, (CK_BYTE **)&crypt_salt)
18290Sstevel@tonic-gate != CKR_OK) {
18300Sstevel@tonic-gate goto cleanup;
18310Sstevel@tonic-gate }
18320Sstevel@tonic-gate
18330Sstevel@tonic-gate hmac_salt = malloc(KS_HMAC_SALT_SIZE);
18340Sstevel@tonic-gate if (hmac_salt == NULL) {
18350Sstevel@tonic-gate goto cleanup;
18360Sstevel@tonic-gate }
18370Sstevel@tonic-gate
18380Sstevel@tonic-gate if (lseek(fd, KS_HMAC_SALT_OFFSET, SEEK_SET) != KS_HMAC_SALT_OFFSET) {
18390Sstevel@tonic-gate goto cleanup;
18400Sstevel@tonic-gate }
18410Sstevel@tonic-gate
18428932SDina.Nimeh@Sun.COM if (readn_nointr(fd, (char *)hmac_salt, KS_HMAC_SALT_SIZE)
18430Sstevel@tonic-gate != KS_HMAC_SALT_SIZE) {
18440Sstevel@tonic-gate goto cleanup;
18450Sstevel@tonic-gate }
18460Sstevel@tonic-gate
18470Sstevel@tonic-gate if (soft_gen_hmac_key(pin, &hmac_key, (CK_BYTE **)&hmac_salt)
18480Sstevel@tonic-gate != CKR_OK) {
18490Sstevel@tonic-gate goto cleanup;
18500Sstevel@tonic-gate }
18510Sstevel@tonic-gate
18520Sstevel@tonic-gate ret_val = 0;
18530Sstevel@tonic-gate
18540Sstevel@tonic-gate cleanup:
18550Sstevel@tonic-gate /* unlock the file */
18560Sstevel@tonic-gate (void) lock_file(fd, B_TRUE, B_FALSE);
18570Sstevel@tonic-gate (void) close(fd);
18580Sstevel@tonic-gate if (crypt_salt != NULL) {
18590Sstevel@tonic-gate free(crypt_salt);
18600Sstevel@tonic-gate }
18610Sstevel@tonic-gate if (hmac_salt != NULL) {
18620Sstevel@tonic-gate free(hmac_salt);
18630Sstevel@tonic-gate }
18640Sstevel@tonic-gate return (ret_val);
18650Sstevel@tonic-gate }
18660Sstevel@tonic-gate
18670Sstevel@tonic-gate /*
18680Sstevel@tonic-gate * FUNCTION: soft_keystore_get_objs
18690Sstevel@tonic-gate *
18700Sstevel@tonic-gate * ARGUMENTS:
18710Sstevel@tonic-gate *
18720Sstevel@tonic-gate * search_type: Specify type of objects to return.
18730Sstevel@tonic-gate * lock_held: TRUE if the lock is held by caller.
18740Sstevel@tonic-gate *
18750Sstevel@tonic-gate *
18760Sstevel@tonic-gate * RETURN VALUE:
18770Sstevel@tonic-gate *
18780Sstevel@tonic-gate * NULL: if there are no object in the database.
18790Sstevel@tonic-gate *
18800Sstevel@tonic-gate * Otherwise, linked list of objects as requested
18810Sstevel@tonic-gate * in search type.
18820Sstevel@tonic-gate *
18830Sstevel@tonic-gate * The linked list returned will need to be freed
18840Sstevel@tonic-gate * by the caller.
18850Sstevel@tonic-gate *
18860Sstevel@tonic-gate * DESCRIPTION:
18870Sstevel@tonic-gate *
18880Sstevel@tonic-gate * Returns objects as requested.
18890Sstevel@tonic-gate *
18900Sstevel@tonic-gate * If private objects is requested, and the caller
18910Sstevel@tonic-gate * has not previously passed in the pin or if the pin
18920Sstevel@tonic-gate * passed in is wrong, private objects will not
18930Sstevel@tonic-gate * be returned.
18940Sstevel@tonic-gate *
18950Sstevel@tonic-gate * The buffers returned for private objects are already
18960Sstevel@tonic-gate * decrypted.
18970Sstevel@tonic-gate */
18980Sstevel@tonic-gate CK_RV
soft_keystore_get_objs(ks_search_type_t search_type,ks_obj_t ** result_obj_list,boolean_t lock_held)18990Sstevel@tonic-gate soft_keystore_get_objs(ks_search_type_t search_type,
19000Sstevel@tonic-gate ks_obj_t **result_obj_list, boolean_t lock_held)
19010Sstevel@tonic-gate {
19020Sstevel@tonic-gate DIR *dirp;
19030Sstevel@tonic-gate ks_obj_handle_t ks_handle;
19040Sstevel@tonic-gate CK_RV rv;
19050Sstevel@tonic-gate ks_obj_t *tmp;
19060Sstevel@tonic-gate int ks_fd;
19070Sstevel@tonic-gate
19080Sstevel@tonic-gate *result_obj_list = NULL;
19090Sstevel@tonic-gate
19100Sstevel@tonic-gate /*
19110Sstevel@tonic-gate * lock the keystore description file in "read" mode so that
19120Sstevel@tonic-gate * objects won't get added/deleted/modified while we are
19130Sstevel@tonic-gate * doing the search
19140Sstevel@tonic-gate */
191512256SPeter.Shoults@Sun.COM if ((ks_fd = open_and_lock_keystore_desc(O_RDONLY, B_FALSE,
19160Sstevel@tonic-gate B_FALSE)) < 0) {
19170Sstevel@tonic-gate return (CKR_FUNCTION_FAILED);
19180Sstevel@tonic-gate }
19190Sstevel@tonic-gate
19200Sstevel@tonic-gate if ((search_type == ALL_TOKENOBJS) || (search_type == PUB_TOKENOBJS)) {
19210Sstevel@tonic-gate
19220Sstevel@tonic-gate char pub_obj_path[MAXPATHLEN];
19230Sstevel@tonic-gate
19240Sstevel@tonic-gate ks_handle.public = B_TRUE;
19250Sstevel@tonic-gate
19260Sstevel@tonic-gate if ((dirp = opendir(get_pub_obj_path(pub_obj_path))) == NULL) {
19270Sstevel@tonic-gate (void) lock_file(ks_fd, B_TRUE, B_FALSE);
19280Sstevel@tonic-gate (void) close(ks_fd);
19290Sstevel@tonic-gate return (CKR_FUNCTION_FAILED);
19300Sstevel@tonic-gate }
19310Sstevel@tonic-gate rv = get_all_objs_in_dir(dirp, &ks_handle, result_obj_list,
1932871Scasper lock_held);
19330Sstevel@tonic-gate if (rv != CKR_OK) {
19340Sstevel@tonic-gate (void) closedir(dirp);
19350Sstevel@tonic-gate goto cleanup;
19360Sstevel@tonic-gate }
19370Sstevel@tonic-gate
19380Sstevel@tonic-gate (void) closedir(dirp);
19390Sstevel@tonic-gate }
19400Sstevel@tonic-gate
19410Sstevel@tonic-gate if ((search_type == ALL_TOKENOBJS) || (search_type == PRI_TOKENOBJS)) {
19420Sstevel@tonic-gate
19430Sstevel@tonic-gate char pri_obj_path[MAXPATHLEN];
19440Sstevel@tonic-gate
19450Sstevel@tonic-gate if ((enc_key == NULL) ||
19460Sstevel@tonic-gate (enc_key->magic_marker != SOFTTOKEN_OBJECT_MAGIC)) {
19470Sstevel@tonic-gate /* has not login - no need to go any further */
19480Sstevel@tonic-gate (void) lock_file(ks_fd, B_TRUE, B_FALSE);
19490Sstevel@tonic-gate (void) close(ks_fd);
19500Sstevel@tonic-gate return (CKR_OK);
19510Sstevel@tonic-gate }
19520Sstevel@tonic-gate
19530Sstevel@tonic-gate ks_handle.public = B_FALSE;
19540Sstevel@tonic-gate
19550Sstevel@tonic-gate if ((dirp = opendir(get_pri_obj_path(pri_obj_path))) == NULL) {
19560Sstevel@tonic-gate (void) lock_file(ks_fd, B_TRUE, B_FALSE);
19570Sstevel@tonic-gate (void) close(ks_fd);
19580Sstevel@tonic-gate return (CKR_OK);
19590Sstevel@tonic-gate }
19600Sstevel@tonic-gate rv = get_all_objs_in_dir(dirp, &ks_handle, result_obj_list,
1961871Scasper lock_held);
19620Sstevel@tonic-gate if (rv != CKR_OK) {
19630Sstevel@tonic-gate (void) closedir(dirp);
19640Sstevel@tonic-gate goto cleanup;
19650Sstevel@tonic-gate }
19660Sstevel@tonic-gate
19670Sstevel@tonic-gate (void) closedir(dirp);
19680Sstevel@tonic-gate }
19690Sstevel@tonic-gate /* close the keystore description file */
19700Sstevel@tonic-gate (void) lock_file(ks_fd, B_TRUE, B_FALSE);
19710Sstevel@tonic-gate (void) close(ks_fd);
19720Sstevel@tonic-gate return (CKR_OK);
19730Sstevel@tonic-gate cleanup:
19740Sstevel@tonic-gate
19750Sstevel@tonic-gate /* close the keystore description file */
19760Sstevel@tonic-gate (void) lock_file(ks_fd, B_TRUE, B_FALSE);
19770Sstevel@tonic-gate (void) close(ks_fd);
19780Sstevel@tonic-gate
19790Sstevel@tonic-gate /* free all the objects found before hitting the error */
19800Sstevel@tonic-gate tmp = *result_obj_list;
19810Sstevel@tonic-gate while (tmp) {
19820Sstevel@tonic-gate *result_obj_list = tmp->next;
19830Sstevel@tonic-gate free(tmp->buf);
19840Sstevel@tonic-gate free(tmp);
19850Sstevel@tonic-gate tmp = *result_obj_list;
19860Sstevel@tonic-gate }
19870Sstevel@tonic-gate *result_obj_list = NULL;
19880Sstevel@tonic-gate return (rv);
19890Sstevel@tonic-gate }
19900Sstevel@tonic-gate
19910Sstevel@tonic-gate
19920Sstevel@tonic-gate /*
19930Sstevel@tonic-gate * FUNCTION: soft_keystore_get_single_obj
19940Sstevel@tonic-gate *
19950Sstevel@tonic-gate * ARGUMENTS:
19960Sstevel@tonic-gate * ks_handle: handle of the key store object to be accessed
19970Sstevel@tonic-gate * lock_held: TRUE if the lock is held by caller.
19980Sstevel@tonic-gate *
19990Sstevel@tonic-gate * RETURN VALUE:
20000Sstevel@tonic-gate *
20010Sstevel@tonic-gate * NULL: if handle doesn't match any object
20020Sstevel@tonic-gate *
20030Sstevel@tonic-gate * Otherwise, the object is returned in
20040Sstevel@tonic-gate * the same structure used in soft_keystore_get_objs().
20050Sstevel@tonic-gate * The structure need to be freed by the caller.
20060Sstevel@tonic-gate *
20070Sstevel@tonic-gate * DESCRIPTION:
20080Sstevel@tonic-gate *
20090Sstevel@tonic-gate * Retrieves the object specified by the object
20100Sstevel@tonic-gate * handle to the caller.
20110Sstevel@tonic-gate *
20120Sstevel@tonic-gate * If a private object is requested, and the caller
20130Sstevel@tonic-gate * has not previously passed in the pin or if the pin
20140Sstevel@tonic-gate * passed in is wrong, the requested private object will not
20150Sstevel@tonic-gate * be returned.
20160Sstevel@tonic-gate *
20170Sstevel@tonic-gate * The buffer returned for the requested private object
20180Sstevel@tonic-gate * is already decrypted.
20190Sstevel@tonic-gate */
20200Sstevel@tonic-gate CK_RV
soft_keystore_get_single_obj(ks_obj_handle_t * ks_handle,ks_obj_t ** return_obj,boolean_t lock_held)20210Sstevel@tonic-gate soft_keystore_get_single_obj(ks_obj_handle_t *ks_handle,
20220Sstevel@tonic-gate ks_obj_t **return_obj, boolean_t lock_held)
20230Sstevel@tonic-gate {
20240Sstevel@tonic-gate
20250Sstevel@tonic-gate ks_obj_t *obj;
20260Sstevel@tonic-gate uchar_t iv[OBJ_IV_SIZE], obj_hmac[OBJ_HMAC_SIZE];
20270Sstevel@tonic-gate uchar_t *buf, *decrypted_buf;
20280Sstevel@tonic-gate int fd;
20290Sstevel@tonic-gate ssize_t nread;
20300Sstevel@tonic-gate CK_RV rv = CKR_FUNCTION_FAILED;
20310Sstevel@tonic-gate
20320Sstevel@tonic-gate if (!(ks_handle->public)) {
20330Sstevel@tonic-gate if ((enc_key == NULL) ||
20340Sstevel@tonic-gate (enc_key->magic_marker != SOFTTOKEN_OBJECT_MAGIC)) {
20350Sstevel@tonic-gate return (CKR_FUNCTION_FAILED);
20360Sstevel@tonic-gate }
20370Sstevel@tonic-gate }
20380Sstevel@tonic-gate
20390Sstevel@tonic-gate if ((fd = open_and_lock_object_file(ks_handle, O_RDONLY,
20400Sstevel@tonic-gate lock_held)) < 0) {
20410Sstevel@tonic-gate return (CKR_FUNCTION_FAILED);
20420Sstevel@tonic-gate }
20430Sstevel@tonic-gate
20440Sstevel@tonic-gate obj = malloc(sizeof (ks_obj_t));
20450Sstevel@tonic-gate if (obj == NULL) {
20460Sstevel@tonic-gate return (CKR_HOST_MEMORY);
20470Sstevel@tonic-gate }
20480Sstevel@tonic-gate
20490Sstevel@tonic-gate obj->next = NULL;
20500Sstevel@tonic-gate
20510Sstevel@tonic-gate (void) strcpy((char *)((obj->ks_handle).name),
20520Sstevel@tonic-gate (char *)ks_handle->name);
20530Sstevel@tonic-gate (obj->ks_handle).public = ks_handle->public;
20540Sstevel@tonic-gate
20550Sstevel@tonic-gate /* 1st get the version */
20568932SDina.Nimeh@Sun.COM if (readn_nointr(fd, &(obj->obj_version), OBJ_VER_SIZE)
20570Sstevel@tonic-gate != OBJ_VER_SIZE) {
20580Sstevel@tonic-gate goto cleanup;
20590Sstevel@tonic-gate }
20600Sstevel@tonic-gate obj->obj_version = SWAP32(obj->obj_version);
20610Sstevel@tonic-gate
20620Sstevel@tonic-gate /* Then, read the IV */
20638932SDina.Nimeh@Sun.COM if (readn_nointr(fd, iv, OBJ_IV_SIZE) != OBJ_IV_SIZE) {
20640Sstevel@tonic-gate goto cleanup;
20650Sstevel@tonic-gate }
20660Sstevel@tonic-gate
20670Sstevel@tonic-gate /* Then, read the HMAC */
20688932SDina.Nimeh@Sun.COM if (readn_nointr(fd, obj_hmac, OBJ_HMAC_SIZE) != OBJ_HMAC_SIZE) {
20690Sstevel@tonic-gate goto cleanup;
20700Sstevel@tonic-gate }
20710Sstevel@tonic-gate
20720Sstevel@tonic-gate /* read the object */
20730Sstevel@tonic-gate rv = read_obj_data(fd, (char **)&buf, &nread);
20740Sstevel@tonic-gate if (rv != CKR_OK) {
20750Sstevel@tonic-gate goto cleanup;
20760Sstevel@tonic-gate }
20770Sstevel@tonic-gate
20780Sstevel@tonic-gate if (ks_handle->public) {
20790Sstevel@tonic-gate obj->size = nread;
20800Sstevel@tonic-gate obj->buf = buf;
20810Sstevel@tonic-gate *return_obj = obj;
20820Sstevel@tonic-gate } else {
20830Sstevel@tonic-gate
20840Sstevel@tonic-gate CK_ULONG out_len = 0, hmac_size;
20850Sstevel@tonic-gate
20860Sstevel@tonic-gate /* verify HMAC of the object, make sure it matches */
20870Sstevel@tonic-gate hmac_size = OBJ_HMAC_SIZE;
20880Sstevel@tonic-gate if (soft_keystore_hmac(hmac_key, B_FALSE, buf,
20890Sstevel@tonic-gate nread, obj_hmac, &hmac_size) != CKR_OK) {
20900Sstevel@tonic-gate free(buf);
20910Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED;
20920Sstevel@tonic-gate goto cleanup;
20930Sstevel@tonic-gate }
20940Sstevel@tonic-gate
20950Sstevel@tonic-gate /* decrypt object */
20960Sstevel@tonic-gate if (soft_keystore_crypt(enc_key, iv, B_FALSE, buf, nread,
20970Sstevel@tonic-gate NULL, &out_len) != CKR_OK) {
20980Sstevel@tonic-gate free(buf);
20990Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED;
21000Sstevel@tonic-gate goto cleanup;
21010Sstevel@tonic-gate }
21020Sstevel@tonic-gate
21030Sstevel@tonic-gate decrypted_buf = malloc(sizeof (uchar_t) * out_len);
21040Sstevel@tonic-gate if (decrypted_buf == NULL) {
21050Sstevel@tonic-gate free(buf);
21060Sstevel@tonic-gate rv = CKR_HOST_MEMORY;
21070Sstevel@tonic-gate goto cleanup;
21080Sstevel@tonic-gate }
21090Sstevel@tonic-gate
21100Sstevel@tonic-gate if (soft_keystore_crypt(enc_key, iv, B_FALSE, buf, nread,
21110Sstevel@tonic-gate decrypted_buf, &out_len) != CKR_OK) {
21120Sstevel@tonic-gate free(decrypted_buf);
21130Sstevel@tonic-gate free(buf);
21140Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED;
21150Sstevel@tonic-gate goto cleanup;
21160Sstevel@tonic-gate }
21170Sstevel@tonic-gate
21180Sstevel@tonic-gate obj->size = out_len - MAXPATHLEN;
21190Sstevel@tonic-gate
21200Sstevel@tonic-gate /*
21210Sstevel@tonic-gate * decrypted buf here actually contains full path name of
21220Sstevel@tonic-gate * object plus the actual data. so, need to skip the
21230Sstevel@tonic-gate * full pathname.
21240Sstevel@tonic-gate * See prepare_data_for_encrypt() function in the file
21250Sstevel@tonic-gate * to understand how and why the pathname is added.
21260Sstevel@tonic-gate */
21270Sstevel@tonic-gate obj->buf = malloc(sizeof (uchar_t) * (out_len - MAXPATHLEN));
21280Sstevel@tonic-gate if (obj->buf == NULL) {
21290Sstevel@tonic-gate free(decrypted_buf);
21300Sstevel@tonic-gate free(buf);
21310Sstevel@tonic-gate rv = CKR_HOST_MEMORY;
21320Sstevel@tonic-gate goto cleanup;
21330Sstevel@tonic-gate }
21340Sstevel@tonic-gate (void) memcpy(obj->buf, decrypted_buf + MAXPATHLEN, obj->size);
21350Sstevel@tonic-gate free(decrypted_buf);
21360Sstevel@tonic-gate free(buf);
21370Sstevel@tonic-gate *return_obj = obj;
21380Sstevel@tonic-gate }
21390Sstevel@tonic-gate
21400Sstevel@tonic-gate cleanup:
21410Sstevel@tonic-gate
21420Sstevel@tonic-gate if (rv != CKR_OK) {
21430Sstevel@tonic-gate free(obj);
21440Sstevel@tonic-gate }
21450Sstevel@tonic-gate
21460Sstevel@tonic-gate /* unlock the file after reading */
21470Sstevel@tonic-gate if (!lock_held) {
21480Sstevel@tonic-gate (void) lock_file(fd, B_TRUE, B_FALSE);
21490Sstevel@tonic-gate }
21500Sstevel@tonic-gate
21510Sstevel@tonic-gate (void) close(fd);
21520Sstevel@tonic-gate
21530Sstevel@tonic-gate return (rv);
21540Sstevel@tonic-gate }
21550Sstevel@tonic-gate
21560Sstevel@tonic-gate
21570Sstevel@tonic-gate /*
21580Sstevel@tonic-gate * FUNCTION: soft_keystore_put_new_obj
21590Sstevel@tonic-gate *
21600Sstevel@tonic-gate * ARGUMENTS:
21610Sstevel@tonic-gate * buf: buffer containing un-encrypted data
21620Sstevel@tonic-gate * to be stored in keystore.
21630Sstevel@tonic-gate * len: length of data
21640Sstevel@tonic-gate * public: TRUE if it is a public object,
21650Sstevel@tonic-gate * FALSE if it is private obj
21660Sstevel@tonic-gate * lock_held: TRUE if the lock is held by caller.
21670Sstevel@tonic-gate * keyhandle: pointer to object handle to
21680Sstevel@tonic-gate * receive keyhandle for new object
21690Sstevel@tonic-gate *
21700Sstevel@tonic-gate * RETURN VALUE:
21710Sstevel@tonic-gate * 0: object successfully stored in file
21720Sstevel@tonic-gate * -1: some error occurred, object is not stored in file.
21730Sstevel@tonic-gate *
21740Sstevel@tonic-gate * DESCRIPTION:
21750Sstevel@tonic-gate * This API is used to write a newly created token object
21760Sstevel@tonic-gate * to keystore.
21770Sstevel@tonic-gate *
21780Sstevel@tonic-gate * This function does the following:
21790Sstevel@tonic-gate *
21800Sstevel@tonic-gate * 1) Creates a token object file based on "public" parameter.
21810Sstevel@tonic-gate * 2) Generates a new IV and stores it in obj_meta_data_t if it is
21820Sstevel@tonic-gate * private object.
21830Sstevel@tonic-gate * 3) Set object version number to 1.
21840Sstevel@tonic-gate * 4) If it is a private object, it will be encrypted before
21850Sstevel@tonic-gate * being written to the newly created keystore token object
21860Sstevel@tonic-gate * file.
21870Sstevel@tonic-gate * 5) Calculates the obj_chksum in obj_meta_data_t.
21880Sstevel@tonic-gate * 6) Calculates the pin_chksum in obj_meta_data_t.
21890Sstevel@tonic-gate * 7) Increments the keystore version number.
21900Sstevel@tonic-gate */
21910Sstevel@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)21920Sstevel@tonic-gate soft_keystore_put_new_obj(uchar_t *buf, size_t len, boolean_t public,
21930Sstevel@tonic-gate boolean_t lock_held, ks_obj_handle_t *keyhandle)
21940Sstevel@tonic-gate {
21950Sstevel@tonic-gate
21960Sstevel@tonic-gate int fd, tmp_ks_fd, obj_fd;
21970Sstevel@tonic-gate unsigned int counter, version;
21980Sstevel@tonic-gate uchar_t obj_hmac[OBJ_HMAC_SIZE];
21990Sstevel@tonic-gate CK_BYTE iv[OBJ_IV_SIZE];
22000Sstevel@tonic-gate char obj_name[MAXPATHLEN], tmp_ks_desc_name[MAXPATHLEN];
22010Sstevel@tonic-gate char filebuf[BUFSIZ];
22020Sstevel@tonic-gate char pub_obj_path[MAXPATHLEN], pri_obj_path[MAXPATHLEN],
22030Sstevel@tonic-gate ks_desc_file[MAXPATHLEN];
22040Sstevel@tonic-gate CK_ULONG hmac_size;
22050Sstevel@tonic-gate ssize_t nread;
22060Sstevel@tonic-gate
22070Sstevel@tonic-gate if (keyhandle == NULL) {
22080Sstevel@tonic-gate return (-1);
22090Sstevel@tonic-gate }
22100Sstevel@tonic-gate
22110Sstevel@tonic-gate /* if it is private object, make sure we have the key */
22120Sstevel@tonic-gate if (!public) {
22130Sstevel@tonic-gate if ((enc_key == NULL) ||
22140Sstevel@tonic-gate (enc_key->magic_marker != SOFTTOKEN_OBJECT_MAGIC)) {
22150Sstevel@tonic-gate return (-1);
22160Sstevel@tonic-gate }
22170Sstevel@tonic-gate }
22180Sstevel@tonic-gate
22190Sstevel@tonic-gate /* open keystore, and set write lock */
222012256SPeter.Shoults@Sun.COM if ((fd = open_and_lock_keystore_desc(O_RDWR, B_FALSE,
22210Sstevel@tonic-gate lock_held)) < 0) {
22220Sstevel@tonic-gate return (-1);
22230Sstevel@tonic-gate }
22240Sstevel@tonic-gate
22250Sstevel@tonic-gate (void) get_desc_file_path(ks_desc_file);
22260Sstevel@tonic-gate (void) get_tmp_desc_file_path(tmp_ks_desc_name);
22270Sstevel@tonic-gate
22280Sstevel@tonic-gate /*
22290Sstevel@tonic-gate * create a tempoary file for the keystore description
22300Sstevel@tonic-gate * file for updating version and counter information
22310Sstevel@tonic-gate */
22328932SDina.Nimeh@Sun.COM tmp_ks_fd = open_nointr(tmp_ks_desc_name,
22338932SDina.Nimeh@Sun.COM O_RDWR|O_CREAT|O_EXCL|O_NONBLOCK, S_IRUSR|S_IWUSR);
22340Sstevel@tonic-gate if (tmp_ks_fd < 0) {
22350Sstevel@tonic-gate (void) close(fd);
22360Sstevel@tonic-gate return (-1);
22370Sstevel@tonic-gate }
22380Sstevel@tonic-gate
22390Sstevel@tonic-gate /* read and write pkcs11 version */
22408932SDina.Nimeh@Sun.COM if (readn_nointr(fd, filebuf, KS_PKCS11_VER_SIZE)
22410Sstevel@tonic-gate != KS_PKCS11_VER_SIZE) {
22420Sstevel@tonic-gate goto cleanup;
22430Sstevel@tonic-gate }
22440Sstevel@tonic-gate
22458932SDina.Nimeh@Sun.COM if (writen_nointr(tmp_ks_fd, filebuf, KS_PKCS11_VER_SIZE)
22460Sstevel@tonic-gate != KS_PKCS11_VER_SIZE) {
22470Sstevel@tonic-gate goto cleanup;
22480Sstevel@tonic-gate }
22490Sstevel@tonic-gate
22500Sstevel@tonic-gate /* get version number, and write updated number to temp file */
22518932SDina.Nimeh@Sun.COM if (readn_nointr(fd, &version, KS_VER_SIZE) != KS_VER_SIZE) {
22520Sstevel@tonic-gate goto cleanup;
22530Sstevel@tonic-gate }
22540Sstevel@tonic-gate
22550Sstevel@tonic-gate version = SWAP32(version);
22560Sstevel@tonic-gate version++;
22570Sstevel@tonic-gate version = SWAP32(version);
22580Sstevel@tonic-gate
22598932SDina.Nimeh@Sun.COM if (writen_nointr(tmp_ks_fd, (void *)&version,
22600Sstevel@tonic-gate KS_VER_SIZE) != KS_VER_SIZE) {
22610Sstevel@tonic-gate goto cleanup;
22620Sstevel@tonic-gate }
22630Sstevel@tonic-gate
22640Sstevel@tonic-gate /* get object count value */
22658932SDina.Nimeh@Sun.COM if (readn_nointr(fd, &counter, KS_COUNTER_SIZE) != KS_COUNTER_SIZE) {
22660Sstevel@tonic-gate goto cleanup;
22670Sstevel@tonic-gate }
22680Sstevel@tonic-gate counter = SWAP32(counter);
22690Sstevel@tonic-gate
22700Sstevel@tonic-gate bzero(obj_name, sizeof (obj_name));
22710Sstevel@tonic-gate if (public) {
22720Sstevel@tonic-gate (void) snprintf(obj_name, MAXPATHLEN, "%s/%s%d",
22730Sstevel@tonic-gate get_pub_obj_path(pub_obj_path), OBJ_PREFIX, counter);
22740Sstevel@tonic-gate } else {
22750Sstevel@tonic-gate (void) snprintf(obj_name, MAXPATHLEN, "%s/%s%d",
22760Sstevel@tonic-gate get_pri_obj_path(pri_obj_path), OBJ_PREFIX, counter);
22770Sstevel@tonic-gate }
22780Sstevel@tonic-gate
22790Sstevel@tonic-gate /* create object file */
22808932SDina.Nimeh@Sun.COM obj_fd = open_nointr(obj_name,
22818932SDina.Nimeh@Sun.COM O_WRONLY|O_CREAT|O_EXCL|O_NONBLOCK, S_IRUSR|S_IWUSR);
22820Sstevel@tonic-gate if (obj_fd < 0) {
22830Sstevel@tonic-gate /* can't create object file */
22840Sstevel@tonic-gate goto cleanup;
22850Sstevel@tonic-gate }
22860Sstevel@tonic-gate
22870Sstevel@tonic-gate /* lock object file for writing */
22880Sstevel@tonic-gate if (lock_file(obj_fd, B_FALSE, B_TRUE) != 0) {
22890Sstevel@tonic-gate (void) close(obj_fd);
22900Sstevel@tonic-gate goto cleanup2;
22910Sstevel@tonic-gate }
22920Sstevel@tonic-gate
22930Sstevel@tonic-gate /* write object meta data */
22940Sstevel@tonic-gate version = SWAP32(1);
22958932SDina.Nimeh@Sun.COM if (writen_nointr(obj_fd, (void *)&version, sizeof (version))
22960Sstevel@tonic-gate != sizeof (version)) {
22970Sstevel@tonic-gate goto cleanup2;
22980Sstevel@tonic-gate }
22990Sstevel@tonic-gate
23000Sstevel@tonic-gate if (public) {
23010Sstevel@tonic-gate bzero(iv, sizeof (iv));
23020Sstevel@tonic-gate } else {
23030Sstevel@tonic-gate /* generate an IV */
23040Sstevel@tonic-gate if (soft_gen_iv(iv) != CKR_OK) {
23050Sstevel@tonic-gate goto cleanup2;
23060Sstevel@tonic-gate }
23070Sstevel@tonic-gate
23080Sstevel@tonic-gate }
23090Sstevel@tonic-gate
23108932SDina.Nimeh@Sun.COM if (writen_nointr(obj_fd, (void *)iv, sizeof (iv)) != sizeof (iv)) {
23110Sstevel@tonic-gate goto cleanup2;
23120Sstevel@tonic-gate }
23130Sstevel@tonic-gate
23140Sstevel@tonic-gate if (public) {
23150Sstevel@tonic-gate
23160Sstevel@tonic-gate bzero(obj_hmac, sizeof (obj_hmac));
23178932SDina.Nimeh@Sun.COM if (writen_nointr(obj_fd, (void *)obj_hmac,
23180Sstevel@tonic-gate sizeof (obj_hmac)) != sizeof (obj_hmac)) {
23190Sstevel@tonic-gate goto cleanup2;
23200Sstevel@tonic-gate }
23210Sstevel@tonic-gate
23228932SDina.Nimeh@Sun.COM if (writen_nointr(obj_fd, (char *)buf, len) != len) {
23230Sstevel@tonic-gate goto cleanup2;
23240Sstevel@tonic-gate }
23250Sstevel@tonic-gate
23260Sstevel@tonic-gate } else {
23270Sstevel@tonic-gate
23280Sstevel@tonic-gate uchar_t *encrypted_buf, *prepared_buf;
23290Sstevel@tonic-gate CK_ULONG out_len = 0, prepared_len;
23300Sstevel@tonic-gate
23310Sstevel@tonic-gate if (prepare_data_for_encrypt(obj_name, buf, len,
23320Sstevel@tonic-gate &prepared_buf, &prepared_len) != 0) {
23330Sstevel@tonic-gate goto cleanup2;
23340Sstevel@tonic-gate }
23350Sstevel@tonic-gate
23360Sstevel@tonic-gate if (soft_keystore_crypt(enc_key, iv,
23370Sstevel@tonic-gate B_TRUE, prepared_buf, prepared_len,
23380Sstevel@tonic-gate NULL, &out_len) != CKR_OK) {
23390Sstevel@tonic-gate free(prepared_buf);
23400Sstevel@tonic-gate goto cleanup2;
23410Sstevel@tonic-gate }
23420Sstevel@tonic-gate
23430Sstevel@tonic-gate encrypted_buf = malloc(out_len * sizeof (char));
23440Sstevel@tonic-gate if (encrypted_buf == NULL) {
23450Sstevel@tonic-gate free(prepared_buf);
23460Sstevel@tonic-gate goto cleanup2;
23470Sstevel@tonic-gate }
23480Sstevel@tonic-gate
23490Sstevel@tonic-gate if (soft_keystore_crypt(enc_key, iv,
23500Sstevel@tonic-gate B_TRUE, prepared_buf, prepared_len,
23510Sstevel@tonic-gate encrypted_buf, &out_len) != CKR_OK) {
23520Sstevel@tonic-gate free(encrypted_buf);
23530Sstevel@tonic-gate free(prepared_buf);
23540Sstevel@tonic-gate goto cleanup2;
23550Sstevel@tonic-gate }
23560Sstevel@tonic-gate free(prepared_buf);
23570Sstevel@tonic-gate
23580Sstevel@tonic-gate /* calculate HMAC of encrypted object */
23590Sstevel@tonic-gate hmac_size = OBJ_HMAC_SIZE;
23600Sstevel@tonic-gate if (soft_keystore_hmac(hmac_key, B_TRUE, encrypted_buf,
23610Sstevel@tonic-gate out_len, obj_hmac, &hmac_size) != CKR_OK) {
23620Sstevel@tonic-gate free(encrypted_buf);
23630Sstevel@tonic-gate goto cleanup2;
23640Sstevel@tonic-gate }
23650Sstevel@tonic-gate
23660Sstevel@tonic-gate if (hmac_size != OBJ_HMAC_SIZE) {
23670Sstevel@tonic-gate free(encrypted_buf);
23680Sstevel@tonic-gate goto cleanup2;
23690Sstevel@tonic-gate }
23700Sstevel@tonic-gate
23710Sstevel@tonic-gate /* write hmac */
23728932SDina.Nimeh@Sun.COM if (writen_nointr(obj_fd, (void *)obj_hmac,
23730Sstevel@tonic-gate sizeof (obj_hmac)) != sizeof (obj_hmac)) {
23740Sstevel@tonic-gate free(encrypted_buf);
23750Sstevel@tonic-gate goto cleanup2;
23760Sstevel@tonic-gate }
23770Sstevel@tonic-gate
23780Sstevel@tonic-gate /* write encrypted object */
23798932SDina.Nimeh@Sun.COM if (writen_nointr(obj_fd, (void *)encrypted_buf, out_len)
23800Sstevel@tonic-gate != out_len) {
23810Sstevel@tonic-gate free(encrypted_buf);
23820Sstevel@tonic-gate goto cleanup2;
23830Sstevel@tonic-gate }
23840Sstevel@tonic-gate
23850Sstevel@tonic-gate free(encrypted_buf);
23860Sstevel@tonic-gate }
23870Sstevel@tonic-gate
23880Sstevel@tonic-gate
23890Sstevel@tonic-gate (void) close(obj_fd);
23900Sstevel@tonic-gate (void) snprintf((char *)keyhandle->name, sizeof (keyhandle->name),
23910Sstevel@tonic-gate "obj%d", counter);
23920Sstevel@tonic-gate keyhandle->public = public;
23930Sstevel@tonic-gate
23940Sstevel@tonic-gate /*
23950Sstevel@tonic-gate * store new counter to temp keystore description file.
23960Sstevel@tonic-gate */
23970Sstevel@tonic-gate counter++;
23980Sstevel@tonic-gate counter = SWAP32(counter);
23998932SDina.Nimeh@Sun.COM if (writen_nointr(tmp_ks_fd, (void *)&counter,
24000Sstevel@tonic-gate sizeof (counter)) != sizeof (counter)) {
24010Sstevel@tonic-gate goto cleanup2;
24020Sstevel@tonic-gate }
24030Sstevel@tonic-gate
24040Sstevel@tonic-gate /* read rest of keystore description file and store into temp file */
24058932SDina.Nimeh@Sun.COM nread = readn_nointr(fd, filebuf, sizeof (filebuf));
24060Sstevel@tonic-gate while (nread > 0) {
24078932SDina.Nimeh@Sun.COM if (writen_nointr(tmp_ks_fd, filebuf, nread) != nread) {
24080Sstevel@tonic-gate goto cleanup2;
24090Sstevel@tonic-gate }
24108932SDina.Nimeh@Sun.COM nread = readn_nointr(fd, filebuf, sizeof (filebuf));
24110Sstevel@tonic-gate }
24120Sstevel@tonic-gate
24130Sstevel@tonic-gate (void) close(tmp_ks_fd);
24140Sstevel@tonic-gate (void) rename(tmp_ks_desc_name, ks_desc_file);
24150Sstevel@tonic-gate
24160Sstevel@tonic-gate if (!lock_held) {
24170Sstevel@tonic-gate /* release lock on description file */
24180Sstevel@tonic-gate if (lock_file(fd, B_FALSE, B_FALSE) != 0) {
24190Sstevel@tonic-gate (void) close(fd);
24200Sstevel@tonic-gate return (-1);
24210Sstevel@tonic-gate }
24220Sstevel@tonic-gate }
24230Sstevel@tonic-gate (void) close(fd);
24240Sstevel@tonic-gate return (0);
24250Sstevel@tonic-gate
24260Sstevel@tonic-gate cleanup2:
24270Sstevel@tonic-gate
24280Sstevel@tonic-gate /* remove object file. No need to remove lock first */
24290Sstevel@tonic-gate (void) unlink(obj_name);
24300Sstevel@tonic-gate
24310Sstevel@tonic-gate cleanup:
24320Sstevel@tonic-gate
24330Sstevel@tonic-gate (void) close(tmp_ks_fd);
24340Sstevel@tonic-gate (void) remove(tmp_ks_desc_name);
24350Sstevel@tonic-gate if (!lock_held) {
24360Sstevel@tonic-gate /* release lock on description file */
24370Sstevel@tonic-gate (void) lock_file(fd, B_FALSE, B_FALSE);
24380Sstevel@tonic-gate }
24390Sstevel@tonic-gate
24400Sstevel@tonic-gate (void) close(fd);
24410Sstevel@tonic-gate return (-1);
24420Sstevel@tonic-gate }
24430Sstevel@tonic-gate
24440Sstevel@tonic-gate /*
24450Sstevel@tonic-gate * FUNCTION: soft_keystore_modify_obj
24460Sstevel@tonic-gate *
24470Sstevel@tonic-gate * ARGUMENTS:
24480Sstevel@tonic-gate * ks_handle: handle of the key store object to be modified
24490Sstevel@tonic-gate * buf: buffer containing un-encrypted data
24500Sstevel@tonic-gate * to be modified in keystore.
24510Sstevel@tonic-gate * len: length of data
24520Sstevel@tonic-gate * lock_held: TRUE if the lock is held by caller.
24530Sstevel@tonic-gate *
24540Sstevel@tonic-gate * RETURN VALUE:
24550Sstevel@tonic-gate * -1: if any error occurred.
24560Sstevel@tonic-gate * Otherwise, 0 is returned.
24570Sstevel@tonic-gate *
24580Sstevel@tonic-gate * DESCRIPTION:
24590Sstevel@tonic-gate *
24600Sstevel@tonic-gate * This API is used to write a modified token object back
24610Sstevel@tonic-gate * to keystore. This function will do the following:
24620Sstevel@tonic-gate *
24630Sstevel@tonic-gate * 1) If it is a private object, it will be encrypted before
24640Sstevel@tonic-gate * being written to the corresponding keystore token
24650Sstevel@tonic-gate * object file.
24660Sstevel@tonic-gate * 2) Record incremented object version number.
24670Sstevel@tonic-gate * 3) Record incremented keystore version number.
24680Sstevel@tonic-gate */
24690Sstevel@tonic-gate int
soft_keystore_modify_obj(ks_obj_handle_t * ks_handle,uchar_t * buf,size_t len,boolean_t lock_held)24700Sstevel@tonic-gate soft_keystore_modify_obj(ks_obj_handle_t *ks_handle, uchar_t *buf,
24710Sstevel@tonic-gate size_t len, boolean_t lock_held)
24720Sstevel@tonic-gate {
24730Sstevel@tonic-gate int fd, ks_fd, tmp_fd, version;
24740Sstevel@tonic-gate char orig_name[MAXPATHLEN], tmp_name[MAXPATHLEN],
24750Sstevel@tonic-gate tmp_ks_name[MAXPATHLEN];
24760Sstevel@tonic-gate uchar_t iv[OBJ_IV_SIZE], obj_hmac[OBJ_HMAC_SIZE];
24770Sstevel@tonic-gate char pub_obj_path[MAXPATHLEN], pri_obj_path[MAXPATHLEN],
24780Sstevel@tonic-gate ks_desc_file[MAXPATHLEN];
24790Sstevel@tonic-gate CK_ULONG hmac_size;
24800Sstevel@tonic-gate
24810Sstevel@tonic-gate /* if it is private object, make sure we have the key */
24820Sstevel@tonic-gate if (!(ks_handle->public)) {
24830Sstevel@tonic-gate if ((enc_key == NULL) ||
24840Sstevel@tonic-gate (enc_key->magic_marker != SOFTTOKEN_OBJECT_MAGIC)) {
24850Sstevel@tonic-gate return (-1);
24860Sstevel@tonic-gate }
24870Sstevel@tonic-gate }
24880Sstevel@tonic-gate
24890Sstevel@tonic-gate /* open and lock keystore description file */
24900Sstevel@tonic-gate if ((ks_fd = open_and_lock_keystore_desc(O_RDWR, B_FALSE,
24910Sstevel@tonic-gate B_FALSE)) < 0) {
24920Sstevel@tonic-gate return (-1);
24930Sstevel@tonic-gate }
24940Sstevel@tonic-gate
24950Sstevel@tonic-gate (void) get_desc_file_path(ks_desc_file);
24960Sstevel@tonic-gate
24970Sstevel@tonic-gate /* update the version of for keystore file in tempoary file */
24980Sstevel@tonic-gate (void) get_tmp_desc_file_path(tmp_ks_name);
24990Sstevel@tonic-gate if (create_updated_keystore_version(ks_fd, tmp_ks_name) != 0) {
25000Sstevel@tonic-gate /* unlock keystore description file */
25010Sstevel@tonic-gate (void) lock_file(ks_fd, B_FALSE, B_FALSE);
25020Sstevel@tonic-gate (void) close(ks_fd);
25030Sstevel@tonic-gate return (-1);
25040Sstevel@tonic-gate }
25050Sstevel@tonic-gate
25060Sstevel@tonic-gate /* open object file */
25070Sstevel@tonic-gate if ((fd = open_and_lock_object_file(ks_handle, O_RDWR,
25080Sstevel@tonic-gate lock_held)) < 0) {
25090Sstevel@tonic-gate goto cleanup;
25100Sstevel@tonic-gate }
25110Sstevel@tonic-gate
25120Sstevel@tonic-gate /*
25130Sstevel@tonic-gate * make the change in a temporary file. Create the temp
25140Sstevel@tonic-gate * file in the same directory as the token object. That
25150Sstevel@tonic-gate * way, the "rename" later will be an atomic operation
25160Sstevel@tonic-gate */
25170Sstevel@tonic-gate if (ks_handle->public) {
25180Sstevel@tonic-gate (void) snprintf(orig_name, MAXPATHLEN, "%s/%s",
25190Sstevel@tonic-gate get_pub_obj_path(pub_obj_path), ks_handle->name);
25200Sstevel@tonic-gate (void) snprintf(tmp_name, MAXPATHLEN, "%s/%s%s",
25210Sstevel@tonic-gate pub_obj_path, TMP_OBJ_PREFIX,
25229341SAnthony.Scarpino@Sun.COM (ks_handle->name) + OBJ_PREFIX_LEN);
25230Sstevel@tonic-gate } else {
25240Sstevel@tonic-gate (void) snprintf(orig_name, MAXPATHLEN, "%s/%s",
25250Sstevel@tonic-gate get_pri_obj_path(pri_obj_path), ks_handle->name);
25260Sstevel@tonic-gate (void) snprintf(tmp_name, MAXPATHLEN, "%s/%s%s",
25270Sstevel@tonic-gate pri_obj_path, TMP_OBJ_PREFIX,
25289341SAnthony.Scarpino@Sun.COM (ks_handle->name) + OBJ_PREFIX_LEN);
25290Sstevel@tonic-gate }
25300Sstevel@tonic-gate
25318932SDina.Nimeh@Sun.COM tmp_fd = open_nointr(tmp_name,
25328932SDina.Nimeh@Sun.COM O_WRONLY|O_CREAT|O_EXCL|O_NONBLOCK, S_IRUSR|S_IWUSR);
25330Sstevel@tonic-gate if (tmp_fd < 0) {
25340Sstevel@tonic-gate /* can't create tmp object file */
25350Sstevel@tonic-gate goto cleanup1;
25360Sstevel@tonic-gate }
25370Sstevel@tonic-gate
25380Sstevel@tonic-gate /* read version, increment, and write to tmp file */
25398932SDina.Nimeh@Sun.COM if (readn_nointr(fd, (char *)&version, OBJ_VER_SIZE) != OBJ_VER_SIZE) {
25400Sstevel@tonic-gate goto cleanup2;
25410Sstevel@tonic-gate }
25420Sstevel@tonic-gate
25430Sstevel@tonic-gate version = SWAP32(version);
25440Sstevel@tonic-gate version++;
25450Sstevel@tonic-gate version = SWAP32(version);
25460Sstevel@tonic-gate
25478932SDina.Nimeh@Sun.COM if (writen_nointr(tmp_fd, (char *)&version, OBJ_VER_SIZE)
25480Sstevel@tonic-gate != OBJ_VER_SIZE) {
25490Sstevel@tonic-gate goto cleanup2;
25500Sstevel@tonic-gate }
25510Sstevel@tonic-gate
25520Sstevel@tonic-gate /* generate a new IV for the object, old one can be ignored */
25530Sstevel@tonic-gate if (soft_gen_iv(iv) != CKR_OK) {
25540Sstevel@tonic-gate goto cleanup2;
25550Sstevel@tonic-gate }
25560Sstevel@tonic-gate
25578932SDina.Nimeh@Sun.COM if (writen_nointr(tmp_fd, (char *)iv, OBJ_IV_SIZE) != OBJ_IV_SIZE) {
25580Sstevel@tonic-gate goto cleanup2;
25590Sstevel@tonic-gate }
25600Sstevel@tonic-gate
25610Sstevel@tonic-gate if (ks_handle->public) {
25620Sstevel@tonic-gate
25630Sstevel@tonic-gate /* hmac is always NULL for public objects */
25640Sstevel@tonic-gate bzero(obj_hmac, sizeof (obj_hmac));
25658932SDina.Nimeh@Sun.COM if (writen_nointr(tmp_fd, (char *)obj_hmac, OBJ_HMAC_SIZE)
25660Sstevel@tonic-gate != OBJ_HMAC_SIZE) {
25670Sstevel@tonic-gate goto cleanup2;
25680Sstevel@tonic-gate }
25690Sstevel@tonic-gate
25700Sstevel@tonic-gate /* write updated object */
25718932SDina.Nimeh@Sun.COM if (writen_nointr(tmp_fd, (char *)buf, len) != len) {
25720Sstevel@tonic-gate goto cleanup2;
25730Sstevel@tonic-gate }
25740Sstevel@tonic-gate
25750Sstevel@tonic-gate } else {
25760Sstevel@tonic-gate
25770Sstevel@tonic-gate uchar_t *encrypted_buf, *prepared_buf;
25780Sstevel@tonic-gate CK_ULONG out_len = 0, prepared_len;
25790Sstevel@tonic-gate
25800Sstevel@tonic-gate if (prepare_data_for_encrypt(orig_name, buf, len,
25810Sstevel@tonic-gate &prepared_buf, &prepared_len) != 0) {
25820Sstevel@tonic-gate goto cleanup2;
25830Sstevel@tonic-gate }
25840Sstevel@tonic-gate
25850Sstevel@tonic-gate /* encrypt the data */
25860Sstevel@tonic-gate if (soft_keystore_crypt(enc_key, iv, B_TRUE, prepared_buf,
25870Sstevel@tonic-gate prepared_len, NULL, &out_len) != CKR_OK) {
25880Sstevel@tonic-gate free(prepared_buf);
25890Sstevel@tonic-gate goto cleanup2;
25900Sstevel@tonic-gate }
25910Sstevel@tonic-gate
25920Sstevel@tonic-gate encrypted_buf = malloc(out_len * sizeof (char));
25930Sstevel@tonic-gate if (encrypted_buf == NULL) {
25940Sstevel@tonic-gate free(prepared_buf);
25950Sstevel@tonic-gate goto cleanup2;
25960Sstevel@tonic-gate }
25970Sstevel@tonic-gate
25980Sstevel@tonic-gate if (soft_keystore_crypt(enc_key, iv, B_TRUE, prepared_buf,
25990Sstevel@tonic-gate prepared_len, encrypted_buf, &out_len) != CKR_OK) {
26000Sstevel@tonic-gate free(encrypted_buf);
26010Sstevel@tonic-gate free(prepared_buf);
26020Sstevel@tonic-gate goto cleanup2;
26030Sstevel@tonic-gate }
26040Sstevel@tonic-gate
26050Sstevel@tonic-gate free(prepared_buf);
26060Sstevel@tonic-gate
26070Sstevel@tonic-gate /* calculate hmac on encrypted buf */
26080Sstevel@tonic-gate hmac_size = OBJ_HMAC_SIZE;
26090Sstevel@tonic-gate if (soft_keystore_hmac(hmac_key, B_TRUE, encrypted_buf,
26100Sstevel@tonic-gate out_len, obj_hmac, &hmac_size) != CKR_OK) {
26110Sstevel@tonic-gate free(encrypted_buf);
26120Sstevel@tonic-gate goto cleanup2;
26130Sstevel@tonic-gate }
26140Sstevel@tonic-gate
26150Sstevel@tonic-gate if (hmac_size != OBJ_HMAC_SIZE) {
26160Sstevel@tonic-gate free(encrypted_buf);
26170Sstevel@tonic-gate goto cleanup2;
26180Sstevel@tonic-gate }
26190Sstevel@tonic-gate
26208932SDina.Nimeh@Sun.COM if (writen_nointr(tmp_fd, (char *)obj_hmac, OBJ_HMAC_SIZE)
26210Sstevel@tonic-gate != OBJ_HMAC_SIZE) {
26220Sstevel@tonic-gate free(encrypted_buf);
26230Sstevel@tonic-gate goto cleanup2;
26240Sstevel@tonic-gate }
26250Sstevel@tonic-gate
26268932SDina.Nimeh@Sun.COM if (writen_nointr(tmp_fd, (void *)encrypted_buf, out_len)
26270Sstevel@tonic-gate != out_len) {
26280Sstevel@tonic-gate free(encrypted_buf);
26290Sstevel@tonic-gate goto cleanup2;
26300Sstevel@tonic-gate }
26310Sstevel@tonic-gate free(encrypted_buf);
26320Sstevel@tonic-gate }
26330Sstevel@tonic-gate (void) close(tmp_fd);
26340Sstevel@tonic-gate
26350Sstevel@tonic-gate /* rename updated temporary object file */
26360Sstevel@tonic-gate if (rename(tmp_name, orig_name) != 0) {
26370Sstevel@tonic-gate (void) unlink(tmp_name);
26380Sstevel@tonic-gate return (-1);
26390Sstevel@tonic-gate }
26400Sstevel@tonic-gate
26410Sstevel@tonic-gate /* rename updated keystore description file */
26420Sstevel@tonic-gate if (rename(tmp_ks_name, ks_desc_file) != 0) {
26430Sstevel@tonic-gate (void) unlink(tmp_name);
26440Sstevel@tonic-gate (void) unlink(tmp_ks_name);
26450Sstevel@tonic-gate return (-1);
26460Sstevel@tonic-gate }
26470Sstevel@tonic-gate
26480Sstevel@tonic-gate /* determine need to unlock file or not */
26490Sstevel@tonic-gate if (!lock_held) {
26500Sstevel@tonic-gate if (lock_file(fd, B_FALSE, B_FALSE) < 0) {
26510Sstevel@tonic-gate (void) close(fd);
26520Sstevel@tonic-gate (void) unlink(tmp_name);
26530Sstevel@tonic-gate return (-1);
26540Sstevel@tonic-gate }
26550Sstevel@tonic-gate }
26560Sstevel@tonic-gate
26570Sstevel@tonic-gate /* unlock keystore description file */
26580Sstevel@tonic-gate if (lock_file(ks_fd, B_FALSE, B_FALSE) != 0) {
26590Sstevel@tonic-gate (void) close(ks_fd);
26600Sstevel@tonic-gate (void) close(fd);
26610Sstevel@tonic-gate return (-1);
26620Sstevel@tonic-gate }
26630Sstevel@tonic-gate
26640Sstevel@tonic-gate (void) close(ks_fd);
26650Sstevel@tonic-gate
26660Sstevel@tonic-gate (void) close(fd);
26670Sstevel@tonic-gate
26680Sstevel@tonic-gate return (0); /* All operations completed successfully */
26690Sstevel@tonic-gate
26700Sstevel@tonic-gate cleanup2:
26710Sstevel@tonic-gate (void) close(tmp_fd);
26720Sstevel@tonic-gate (void) remove(tmp_name);
26730Sstevel@tonic-gate
26740Sstevel@tonic-gate cleanup1:
26750Sstevel@tonic-gate (void) close(fd);
26760Sstevel@tonic-gate
26770Sstevel@tonic-gate cleanup:
26780Sstevel@tonic-gate /* unlock keystore description file */
26790Sstevel@tonic-gate (void) lock_file(ks_fd, B_FALSE, B_FALSE);
26800Sstevel@tonic-gate (void) close(ks_fd);
26810Sstevel@tonic-gate (void) remove(tmp_ks_name);
26820Sstevel@tonic-gate return (-1);
26830Sstevel@tonic-gate }
26840Sstevel@tonic-gate
26850Sstevel@tonic-gate /*
26860Sstevel@tonic-gate * FUNCTION: soft_keystore_del_obj
26870Sstevel@tonic-gate *
26880Sstevel@tonic-gate * ARGUMENTS:
26890Sstevel@tonic-gate * ks_handle: handle of the key store object to be deleted
26900Sstevel@tonic-gate * lock_held: TRUE if the lock is held by caller.
26910Sstevel@tonic-gate *
26920Sstevel@tonic-gate * RETURN VALUE:
26930Sstevel@tonic-gate * -1: if any error occurred.
26940Sstevel@tonic-gate * 0: object successfully deleted from keystore.
26950Sstevel@tonic-gate *
26960Sstevel@tonic-gate * DESCRIPTION:
26970Sstevel@tonic-gate * This API is used to delete a particular token object from
26980Sstevel@tonic-gate * the keystore. The corresponding token object file will be
26990Sstevel@tonic-gate * removed from the file system.
27000Sstevel@tonic-gate * Any future reference to the deleted file will
27010Sstevel@tonic-gate * return an CKR_OBJECT_HANDLE_INVALID error.
27020Sstevel@tonic-gate */
27030Sstevel@tonic-gate int
soft_keystore_del_obj(ks_obj_handle_t * ks_handle,boolean_t lock_held)27040Sstevel@tonic-gate soft_keystore_del_obj(ks_obj_handle_t *ks_handle, boolean_t lock_held)
27050Sstevel@tonic-gate {
27060Sstevel@tonic-gate char objname[MAXPATHLEN], tmp_ks_name[MAXPATHLEN];
27070Sstevel@tonic-gate int fd;
27080Sstevel@tonic-gate char pub_obj_path[MAXPATHLEN], pri_obj_path[MAXPATHLEN],
27090Sstevel@tonic-gate ks_desc_file[MAXPATHLEN];
27100Sstevel@tonic-gate int ret_val = -1;
27110Sstevel@tonic-gate int obj_fd;
27120Sstevel@tonic-gate
27130Sstevel@tonic-gate if ((fd = open_and_lock_keystore_desc(O_RDWR, B_FALSE,
27140Sstevel@tonic-gate lock_held)) < 0) {
27150Sstevel@tonic-gate return (-1);
27160Sstevel@tonic-gate }
27170Sstevel@tonic-gate
27180Sstevel@tonic-gate (void) get_desc_file_path(ks_desc_file);
27190Sstevel@tonic-gate (void) get_tmp_desc_file_path(tmp_ks_name);
27200Sstevel@tonic-gate if (create_updated_keystore_version(fd, tmp_ks_name) != 0) {
27210Sstevel@tonic-gate goto cleanup;
27220Sstevel@tonic-gate }
27230Sstevel@tonic-gate
27240Sstevel@tonic-gate if (ks_handle->public) {
27250Sstevel@tonic-gate (void) snprintf(objname, MAXPATHLEN, "%s/%s",
27260Sstevel@tonic-gate get_pub_obj_path(pub_obj_path), ks_handle->name);
27270Sstevel@tonic-gate } else {
27280Sstevel@tonic-gate (void) snprintf(objname, MAXPATHLEN, "%s/%s",
27290Sstevel@tonic-gate get_pri_obj_path(pri_obj_path), ks_handle->name);
27300Sstevel@tonic-gate }
27310Sstevel@tonic-gate
27320Sstevel@tonic-gate /*
27330Sstevel@tonic-gate * make sure no other process is reading/writing the file
27340Sstevel@tonic-gate * by acquiring the lock on the file
27350Sstevel@tonic-gate */
27360Sstevel@tonic-gate if ((obj_fd = open_and_lock_object_file(ks_handle, O_WRONLY,
27370Sstevel@tonic-gate B_FALSE)) < 0) {
27380Sstevel@tonic-gate return (-1);
27390Sstevel@tonic-gate }
27400Sstevel@tonic-gate
27410Sstevel@tonic-gate if (unlink(objname) != 0) {
27420Sstevel@tonic-gate (void) lock_file(obj_fd, B_FALSE, B_FALSE);
27430Sstevel@tonic-gate (void) close(obj_fd);
27440Sstevel@tonic-gate goto cleanup;
27450Sstevel@tonic-gate }
27460Sstevel@tonic-gate
27470Sstevel@tonic-gate (void) lock_file(obj_fd, B_FALSE, B_FALSE);
27480Sstevel@tonic-gate (void) close(obj_fd);
27490Sstevel@tonic-gate
27500Sstevel@tonic-gate if (rename(tmp_ks_name, ks_desc_file) != 0) {
27510Sstevel@tonic-gate goto cleanup;
27520Sstevel@tonic-gate }
27530Sstevel@tonic-gate ret_val = 0;
27540Sstevel@tonic-gate
27550Sstevel@tonic-gate cleanup:
27560Sstevel@tonic-gate /* unlock keystore description file */
27570Sstevel@tonic-gate if (!lock_held) {
27580Sstevel@tonic-gate if (lock_file(fd, B_FALSE, B_FALSE) != 0) {
27590Sstevel@tonic-gate (void) close(fd);
27600Sstevel@tonic-gate return (-1);
27610Sstevel@tonic-gate }
27620Sstevel@tonic-gate }
27630Sstevel@tonic-gate
27640Sstevel@tonic-gate (void) close(fd);
27650Sstevel@tonic-gate return (ret_val);
27660Sstevel@tonic-gate }
27670Sstevel@tonic-gate
27680Sstevel@tonic-gate /*
27690Sstevel@tonic-gate * Get the salt used for generating hashed pin from the
27700Sstevel@tonic-gate * keystore description file.
27710Sstevel@tonic-gate *
27720Sstevel@tonic-gate * The result will be stored in the provided buffer "salt" passed
27730Sstevel@tonic-gate * in as an argument.
27740Sstevel@tonic-gate *
27750Sstevel@tonic-gate * Return 0 if no error, return -1 if there's any error.
27760Sstevel@tonic-gate */
27770Sstevel@tonic-gate int
soft_keystore_get_pin_salt(char ** salt)27780Sstevel@tonic-gate soft_keystore_get_pin_salt(char **salt)
27790Sstevel@tonic-gate {
27800Sstevel@tonic-gate int fd, ret_val = -1;
27810Sstevel@tonic-gate uint64_t hashed_pin_salt_size;
27820Sstevel@tonic-gate
278312256SPeter.Shoults@Sun.COM if ((fd = open_and_lock_keystore_desc(O_RDONLY, B_FALSE,
27840Sstevel@tonic-gate B_FALSE)) < 0) {
27850Sstevel@tonic-gate return (-1);
27860Sstevel@tonic-gate }
27870Sstevel@tonic-gate
27880Sstevel@tonic-gate if (lseek(fd, KS_HASHED_PIN_SALT_LEN_OFFSET, SEEK_SET)
27890Sstevel@tonic-gate != KS_HASHED_PIN_SALT_LEN_OFFSET) {
27900Sstevel@tonic-gate goto cleanup;
27910Sstevel@tonic-gate }
27920Sstevel@tonic-gate
27938932SDina.Nimeh@Sun.COM if (readn_nointr(fd, (char *)&hashed_pin_salt_size,
27940Sstevel@tonic-gate KS_HASHED_PIN_SALT_LEN_SIZE) != KS_HASHED_PIN_SALT_LEN_SIZE) {
27950Sstevel@tonic-gate goto cleanup;
27960Sstevel@tonic-gate }
27970Sstevel@tonic-gate hashed_pin_salt_size = SWAP64(hashed_pin_salt_size);
27980Sstevel@tonic-gate
27990Sstevel@tonic-gate *salt = malloc(hashed_pin_salt_size + 1);
28000Sstevel@tonic-gate if (*salt == NULL) {
28010Sstevel@tonic-gate goto cleanup;
28020Sstevel@tonic-gate }
28030Sstevel@tonic-gate
28048932SDina.Nimeh@Sun.COM if ((readn_nointr(fd, *salt, hashed_pin_salt_size))
28050Sstevel@tonic-gate != (ssize_t)hashed_pin_salt_size) {
28060Sstevel@tonic-gate free(*salt);
28070Sstevel@tonic-gate goto cleanup;
28080Sstevel@tonic-gate }
28090Sstevel@tonic-gate (*salt)[hashed_pin_salt_size] = '\0';
28100Sstevel@tonic-gate
28110Sstevel@tonic-gate ret_val = 0;
28120Sstevel@tonic-gate
28130Sstevel@tonic-gate cleanup:
28140Sstevel@tonic-gate if (lock_file(fd, B_TRUE, B_FALSE) < 0) {
28150Sstevel@tonic-gate ret_val = -1;
28160Sstevel@tonic-gate }
28170Sstevel@tonic-gate
28180Sstevel@tonic-gate (void) close(fd);
28190Sstevel@tonic-gate return (ret_val);
28200Sstevel@tonic-gate }
28210Sstevel@tonic-gate
28220Sstevel@tonic-gate /*
28230Sstevel@tonic-gate * FUNCTION: soft_keystore_pin_initialized
28240Sstevel@tonic-gate *
28250Sstevel@tonic-gate * ARGUMENTS:
28260Sstevel@tonic-gate * initialized: This value will be set to true if keystore is
28270Sstevel@tonic-gate * initialized, and false otherwise.
28280Sstevel@tonic-gate * hashed_pin: If the keystore is initialized, this will contain
28290Sstevel@tonic-gate * the hashed pin. It will be NULL if the keystore
28300Sstevel@tonic-gate * pin is not initialized. Memory allocated
28310Sstevel@tonic-gate * for the hashed pin needs to be freed by
28320Sstevel@tonic-gate * the caller.
28330Sstevel@tonic-gate * lock_held: TRUE if the lock is held by caller.
28340Sstevel@tonic-gate *
28350Sstevel@tonic-gate * RETURN VALUE:
28360Sstevel@tonic-gate * CKR_OK: No error
28370Sstevel@tonic-gate * any other appropriate CKR_value
28380Sstevel@tonic-gate *
28390Sstevel@tonic-gate * DESCRIPTION:
28400Sstevel@tonic-gate * This API is used to determine if the PIN in the keystore
28410Sstevel@tonic-gate * has been initialized or not.
28420Sstevel@tonic-gate * It makes the determination using the salt for generating the
28430Sstevel@tonic-gate * encryption key. The salt is stored in the keystore
28440Sstevel@tonic-gate * descryption file. The salt should be all zero if
28450Sstevel@tonic-gate * the keystore pin has not been initialized.
28460Sstevel@tonic-gate * If the pin has been initialized, it is returned in the
28470Sstevel@tonic-gate * hashed_pin argument.
28480Sstevel@tonic-gate */
28490Sstevel@tonic-gate CK_RV
soft_keystore_pin_initialized(boolean_t * initialized,char ** hashed_pin,boolean_t lock_held)28500Sstevel@tonic-gate soft_keystore_pin_initialized(boolean_t *initialized, char **hashed_pin,
28510Sstevel@tonic-gate boolean_t lock_held)
28520Sstevel@tonic-gate {
28530Sstevel@tonic-gate int fd;
28540Sstevel@tonic-gate CK_BYTE crypt_salt[KS_KEY_SALT_SIZE], tmp_buf[KS_KEY_SALT_SIZE];
28550Sstevel@tonic-gate CK_RV ret_val = CKR_OK;
28560Sstevel@tonic-gate
285712256SPeter.Shoults@Sun.COM if ((fd = open_and_lock_keystore_desc(O_RDONLY, B_FALSE,
28580Sstevel@tonic-gate lock_held)) < 0) {
28590Sstevel@tonic-gate return (CKR_FUNCTION_FAILED);
28600Sstevel@tonic-gate }
28610Sstevel@tonic-gate
28620Sstevel@tonic-gate if (lseek(fd, KS_KEY_SALT_OFFSET, SEEK_SET) != KS_KEY_SALT_OFFSET) {
28630Sstevel@tonic-gate ret_val = CKR_FUNCTION_FAILED;
28640Sstevel@tonic-gate goto cleanup;
28650Sstevel@tonic-gate }
28660Sstevel@tonic-gate
28678932SDina.Nimeh@Sun.COM if (readn_nointr(fd, (char *)crypt_salt, KS_KEY_SALT_SIZE)
28680Sstevel@tonic-gate != KS_KEY_SALT_SIZE) {
28690Sstevel@tonic-gate ret_val = CKR_FUNCTION_FAILED;
28700Sstevel@tonic-gate goto cleanup;
28710Sstevel@tonic-gate }
28720Sstevel@tonic-gate
28730Sstevel@tonic-gate (void) bzero(tmp_buf, KS_KEY_SALT_SIZE);
28740Sstevel@tonic-gate
28750Sstevel@tonic-gate if (memcmp(crypt_salt, tmp_buf, KS_KEY_SALT_SIZE) == 0) {
28760Sstevel@tonic-gate *initialized = B_FALSE;
28770Sstevel@tonic-gate hashed_pin = NULL;
28780Sstevel@tonic-gate } else {
28790Sstevel@tonic-gate *initialized = B_TRUE;
28800Sstevel@tonic-gate ret_val = get_hashed_pin(fd, hashed_pin);
28810Sstevel@tonic-gate }
28820Sstevel@tonic-gate
28830Sstevel@tonic-gate cleanup:
28840Sstevel@tonic-gate
28850Sstevel@tonic-gate if (!lock_held) {
28860Sstevel@tonic-gate if (lock_file(fd, B_TRUE, B_FALSE) < 0) {
28870Sstevel@tonic-gate ret_val = CKR_FUNCTION_FAILED;
28880Sstevel@tonic-gate }
28890Sstevel@tonic-gate }
28900Sstevel@tonic-gate
28910Sstevel@tonic-gate (void) close(fd);
28920Sstevel@tonic-gate return (ret_val);
28930Sstevel@tonic-gate }
28941937Sizick
28951937Sizick /*
28961937Sizick * This checks if the keystore file exists
28971937Sizick */
28981937Sizick
28991937Sizick static int
soft_keystore_exists()29001937Sizick soft_keystore_exists()
29011937Sizick {
29021937Sizick int ret;
29031937Sizick struct stat fn_stat;
29041937Sizick char *fname, ks_desc_file[MAXPATHLEN];
29051937Sizick
29061937Sizick fname = get_desc_file_path(ks_desc_file);
29071937Sizick ret = stat(fname, &fn_stat);
29081937Sizick if (ret == 0)
29091937Sizick return (0);
29101937Sizick return (errno);
29111937Sizick }
29121937Sizick
29131937Sizick /*
29141937Sizick * FUNCTION: soft_keystore_init
29151937Sizick *
29161937Sizick * ARGUMENTS:
29171937Sizick * desired_state: The keystore state the caller would like
29181937Sizick * it to be.
29191937Sizick *
29201937Sizick * RETURN VALUE:
29211937Sizick * Returns the state the function is in. If it succeeded, it
29221937Sizick * will be the same as the desired, if not it will be
29231937Sizick * KEYSTORE_UNAVAILABLE.
29241937Sizick *
29251937Sizick * DESCRIPTION:
29261937Sizick * This function will only load as much keystore data as is
29271937Sizick * requested at that time. This is for performace by delaying the
29281937Sizick * reading of token objects until they are needed or never at
29291937Sizick * all if they are not used.
29301937Sizick *
293112256SPeter.Shoults@Sun.COM * Primary use is from C_InitToken().
293212256SPeter.Shoults@Sun.COM * It is also called by soft_keystore_status() when the
29331937Sizick * "desired_state" is not the the current load state of keystore.
29341937Sizick *
29351937Sizick */
29361937Sizick int
soft_keystore_init(int desired_state)29371937Sizick soft_keystore_init(int desired_state)
29381937Sizick {
29391937Sizick int ret;
29401937Sizick
29411937Sizick (void) pthread_mutex_lock(&soft_slot.keystore_mutex);
29421937Sizick
29431937Sizick /*
29441937Sizick * If more than one session tries to initialize the keystore, the
29451937Sizick * second and other following sessions that were waiting for the lock
29461937Sizick * will quickly exit if their requirements are satisfied.
29471937Sizick */
29481937Sizick if (desired_state <= soft_slot.keystore_load_status) {
29491937Sizick (void) pthread_mutex_unlock(&soft_slot.keystore_mutex);
29501937Sizick return (soft_slot.keystore_load_status);
29511937Sizick }
29521937Sizick
29531937Sizick /*
29541937Sizick * With 'keystore_load_status' giving the current state of the
29551937Sizick * process, this switch will bring it up to the desired state if
29561937Sizick * possible.
29571937Sizick */
29581937Sizick
29591937Sizick switch (soft_slot.keystore_load_status) {
29601937Sizick case KEYSTORE_UNINITIALIZED:
29611937Sizick ret = soft_keystore_exists();
29621937Sizick if (ret == 0)
29631937Sizick soft_slot.keystore_load_status = KEYSTORE_PRESENT;
29641937Sizick else if (ret == ENOENT)
29651937Sizick if (create_keystore() == 0)
29661937Sizick soft_slot.keystore_load_status =
29671937Sizick KEYSTORE_PRESENT;
29681937Sizick else {
29691937Sizick soft_slot.keystore_load_status =
29701937Sizick KEYSTORE_UNAVAILABLE;
29712940Sizick cryptoerror(LOG_DEBUG,
29721937Sizick "pkcs11_softtoken: "
29731937Sizick "Cannot create keystore.");
29741937Sizick break;
29751937Sizick }
29761937Sizick
29771937Sizick if (desired_state <= KEYSTORE_PRESENT)
29781937Sizick break;
29791937Sizick
29801937Sizick /* FALLTHRU */
29811937Sizick case KEYSTORE_PRESENT:
29821937Sizick if (soft_keystore_get_version(&soft_slot.ks_version, B_FALSE)
29831937Sizick != 0) {
29841937Sizick soft_slot.keystore_load_status = KEYSTORE_UNAVAILABLE;
29852940Sizick cryptoerror(LOG_DEBUG,
29862940Sizick "pkcs11_softtoken: Keystore access failed.");
29871937Sizick break;
29881937Sizick }
29891937Sizick
299012256SPeter.Shoults@Sun.COM soft_slot.keystore_load_status = KEYSTORE_LOAD;
299112256SPeter.Shoults@Sun.COM if (desired_state <= KEYSTORE_LOAD)
29921937Sizick break;
29931937Sizick
29941937Sizick /* FALLTHRU */
299512256SPeter.Shoults@Sun.COM case KEYSTORE_LOAD:
29961937Sizick /* Load all the public token objects from keystore */
29971937Sizick if (soft_get_token_objects_from_keystore(PUB_TOKENOBJS)
29981937Sizick != CKR_OK) {
29991937Sizick (void) soft_destroy_token_session();
30001937Sizick soft_slot.keystore_load_status = KEYSTORE_UNAVAILABLE;
30012940Sizick cryptoerror(LOG_DEBUG,
30021937Sizick "pkcs11_softtoken: Cannot initialize keystore.");
30031937Sizick break;
30041937Sizick }
30051937Sizick
30061937Sizick soft_slot.keystore_load_status = KEYSTORE_INITIALIZED;
30071937Sizick };
30081937Sizick
30091937Sizick (void) pthread_mutex_unlock(&soft_slot.keystore_mutex);
30101937Sizick return (soft_slot.keystore_load_status);
30111937Sizick }
30121937Sizick
30131937Sizick /*
30141937Sizick * FUNCTION: soft_keystore_status
30151937Sizick *
30161937Sizick * ARGUMENTS:
30171937Sizick * desired_state: The keystore state the caller would like
30181937Sizick * it to be.
30191937Sizick *
30201937Sizick * RETURN VALUE:
30211937Sizick * B_TRUE if keystore is ready and at the desired state.
30221937Sizick * B_FALSE if keystore had an error and is not available.
30231937Sizick *
30241937Sizick * DESCRIPTION:
30251937Sizick * The calling function wants to make sure the keystore load
30261937Sizick * status to in a state it requires. If it is not at that
30271937Sizick * state it will call the load function.
30281937Sizick * If keystore is at the desired state or has just been
30291937Sizick * loaded to that state, it will return TRUE. If there has been
30301937Sizick * load failure, it will return FALSE.
30311937Sizick *
30321937Sizick */
30331937Sizick boolean_t
soft_keystore_status(int desired_state)30341937Sizick soft_keystore_status(int desired_state)
30351937Sizick {
30361937Sizick
30371937Sizick if (soft_slot.keystore_load_status == KEYSTORE_UNAVAILABLE)
30381937Sizick return (B_FALSE);
30391937Sizick
30401937Sizick return ((desired_state <= soft_slot.keystore_load_status) ||
30411937Sizick (soft_keystore_init(desired_state) == desired_state));
30421937Sizick }
3043