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