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