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