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