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