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