xref: /illumos-gate/usr/src/lib/pkcs11/pkcs11_tpm/common/loadsave.c (revision 4f364e7c95ee7fd9d5bbeddc1940e92405bb0e72)
1 /*
2  *		Common Public License Version 0.5
3  *
4  *		THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF
5  *		THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE,
6  *		REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES
7  *		RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
8  *
9  *		1. DEFINITIONS
10  *
11  *		"Contribution" means:
12  *		      a) in the case of the initial Contributor, the
13  *		      initial code and documentation distributed under
14  *		      this Agreement, and
15  *
16  *		      b) in the case of each subsequent Contributor:
17  *		      i) changes to the Program, and
18  *		      ii) additions to the Program;
19  *
20  *		      where such changes and/or additions to the Program
21  *		      originate from and are distributed by that
22  *		      particular Contributor. A Contribution 'originates'
23  *		      from a Contributor if it was added to the Program
24  *		      by such Contributor itself or anyone acting on such
25  *		      Contributor's behalf. Contributions do not include
26  *		      additions to the Program which: (i) are separate
27  *		      modules of software distributed in conjunction with
28  *		      the Program under their own license agreement, and
29  *		      (ii) are not derivative works of the Program.
30  *
31  *
32  *		"Contributor" means any person or entity that distributes
33  *		the Program.
34  *
35  *		"Licensed Patents " mean patent claims licensable by a
36  *		Contributor which are necessarily infringed by the use or
37  *		sale of its Contribution alone or when combined with the
38  *		Program.
39  *
40  *		"Program" means the Contributions distributed in
41  *		accordance with this Agreement.
42  *
43  *		"Recipient" means anyone who receives the Program under
44  *		this Agreement, including all Contributors.
45  *
46  *		2. GRANT OF RIGHTS
47  *
48  *		      a) Subject to the terms of this Agreement, each
49  *		      Contributor hereby grants Recipient a
50  *		      non-exclusive, worldwide, royalty-free copyright
51  *		      license to reproduce, prepare derivative works of,
52  *		      publicly display, publicly perform, distribute and
53  *		      sublicense the Contribution of such Contributor, if
54  *		      any, and such derivative works, in source code and
55  *		      object code form.
56  *
57  *		      b) Subject to the terms of this Agreement, each
58  *		      Contributor hereby grants Recipient a
59  *		      non-exclusive, worldwide, royalty-free patent
60  *		      license under Licensed Patents to make, use, sell,
61  *		      offer to sell, import and otherwise transfer the
62  *		      Contribution of such Contributor, if any, in source
63  *		      code and object code form. This patent license
64  *		      shall apply to the combination of the Contribution
65  *		      and the Program if, at the time the Contribution is
66  *		      added by the Contributor, such addition of the
67  *		      Contribution causes such combination to be covered
68  *		      by the Licensed Patents. The patent license shall
69  *		      not apply to any other combinations which include
70  *		      the Contribution. No hardware per se is licensed
71  *		      hereunder.
72  *
73  *		      c) Recipient understands that although each
74  *		      Contributor grants the licenses to its
75  *		      Contributions set forth herein, no assurances are
76  *		      provided by any Contributor that the Program does
77  *		      not infringe the patent or other intellectual
78  *		      property rights of any other entity. Each
79  *		      Contributor disclaims any liability to Recipient
80  *		      for claims brought by any other entity based on
81  *		      infringement of intellectual property rights or
82  *		      otherwise. As a condition to exercising the rights
83  *		      and licenses granted hereunder, each Recipient
84  *		      hereby assumes sole responsibility to secure any
85  *		      other intellectual property rights needed, if any.
86  *
87  *		      For example, if a third party patent license is
88  *		      required to allow Recipient to distribute the
89  *		      Program, it is Recipient's responsibility to
90  *		      acquire that license before distributing the
91  *		      Program.
92  *
93  *		      d) Each Contributor represents that to its
94  *		      knowledge it has sufficient copyright rights in its
95  *		      Contribution, if any, to grant the copyright
96  *		      license set forth in this Agreement.
97  *
98  *		3. REQUIREMENTS
99  *
100  *		A Contributor may choose to distribute the Program in
101  *		object code form under its own license agreement, provided
102  *		that:
103  *		      a) it complies with the terms and conditions of
104  *		      this Agreement; and
105  *
106  *		      b) its license agreement:
107  *		      i) effectively disclaims on behalf of all
108  *		      Contributors all warranties and conditions, express
109  *		      and implied, including warranties or conditions of
110  *		      title and non-infringement, and implied warranties
111  *		      or conditions of merchantability and fitness for a
112  *		      particular purpose;
113  *
114  *		      ii) effectively excludes on behalf of all
115  *		      Contributors all liability for damages, including
116  *		      direct, indirect, special, incidental and
117  *		      consequential damages, such as lost profits;
118  *
119  *		      iii) states that any provisions which differ from
120  *		      this Agreement are offered by that Contributor
121  *		      alone and not by any other party; and
122  *
123  *		      iv) states that source code for the Program is
124  *		      available from such Contributor, and informs
125  *		      licensees how to obtain it in a reasonable manner
126  *		      on or through a medium customarily used for
127  *		      software exchange.
128  *
129  *		When the Program is made available in source code form:
130  *		      a) it must be made available under this Agreement;
131  *		      and
132  *		      b) a copy of this Agreement must be included with
133  *		      each copy of the Program.
134  *
135  *		Contributors may not remove or alter any copyright notices
136  *		contained within the Program.
137  *
138  *		Each Contributor must identify itself as the originator of
139  *		its Contribution, if any, in a manner that reasonably
140  *		allows subsequent Recipients to identify the originator of
141  *		the Contribution.
142  *
143  *
144  *		4. COMMERCIAL DISTRIBUTION
145  *
146  *		Commercial distributors of software may accept certain
147  *		responsibilities with respect to end users, business
148  *		partners and the like. While this license is intended to
149  *		facilitate the commercial use of the Program, the
150  *		Contributor who includes the Program in a commercial
151  *		product offering should do so in a manner which does not
152  *		create potential liability for other Contributors.
153  *		Therefore, if a Contributor includes the Program in a
154  *		commercial product offering, such Contributor ("Commercial
155  *		Contributor") hereby agrees to defend and indemnify every
156  *		other Contributor ("Indemnified Contributor") against any
157  *		losses, damages and costs (collectively "Losses") arising
158  *		from claims, lawsuits and other legal actions brought by a
159  *		third party against the Indemnified Contributor to the
160  *		extent caused by the acts or omissions of such Commercial
161  *		Contributor in connection with its distribution of the
162  *		Program in a commercial product offering. The obligations
163  *		in this section do not apply to any claims or Losses
164  *		relating to any actual or alleged intellectual property
165  *		infringement. In order to qualify, an Indemnified
166  *		Contributor must: a) promptly notify the Commercial
167  *		Contributor in writing of such claim, and b) allow the
168  *		Commercial Contributor to control, and cooperate with the
169  *		Commercial Contributor in, the defense and any related
170  *		settlement negotiations. The Indemnified Contributor may
171  *		participate in any such claim at its own expense.
172  *
173  *
174  *		For example, a Contributor might include the Program in a
175  *		commercial product offering, Product X. That Contributor
176  *		is then a Commercial Contributor. If that Commercial
177  *		Contributor then makes performance claims, or offers
178  *		warranties related to Product X, those performance claims
179  *		and warranties are such Commercial Contributor's
180  *		responsibility alone. Under this section, the Commercial
181  *		Contributor would have to defend claims against the other
182  *		Contributors related to those performance claims and
183  *		warranties, and if a court requires any other Contributor
184  *		to pay any damages as a result, the Commercial Contributor
185  *		must pay those damages.
186  *
187  *
188  *		5. NO WARRANTY
189  *
190  *		EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE
191  *		PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT
192  *		WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR
193  *		IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR
194  *		CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
195  *		FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely
196  *		responsible for determining the appropriateness of using
197  *		and distributing the Program and assumes all risks
198  *		associated with its exercise of rights under this
199  *		Agreement, including but not limited to the risks and
200  *		costs of program errors, compliance with applicable laws,
201  *		damage to or loss of data, programs or equipment, and
202  *		unavailability or interruption of operations.
203  *
204  *		6. DISCLAIMER OF LIABILITY
205  *		EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER
206  *		RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY
207  *		FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
208  *		OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION
209  *		LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF
210  *		LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
211  *		(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
212  *		OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE
213  *		OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE
214  *		POSSIBILITY OF SUCH DAMAGES.
215  *
216  *		7. GENERAL
217  *
218  *		If any provision of this Agreement is invalid or
219  *		unenforceable under applicable law, it shall not affect
220  *		the validity or enforceability of the remainder of the
221  *		terms of this Agreement, and without further action by the
222  *		parties hereto, such provision shall be reformed to the
223  *		minimum extent necessary to make such provision valid and
224  *		enforceable.
225  *
226  *
227  *		If Recipient institutes patent litigation against a
228  *		Contributor with respect to a patent applicable to
229  *		software (including a cross-claim or counterclaim in a
230  *		lawsuit), then any patent licenses granted by that
231  *		Contributor to such Recipient under this Agreement shall
232  *		terminate as of the date such litigation is filed. In
233  *		addition, If Recipient institutes patent litigation
234  *		against any entity (including a cross-claim or
235  *		counterclaim in a lawsuit) alleging that the Program
236  *		itself (excluding combinations of the Program with other
237  *		software or hardware) infringes such Recipient's
238  *		patent(s), then such Recipient's rights granted under
239  *		Section 2(b) shall terminate as of the date such
240  *		litigation is filed.
241  *
242  *		All Recipient's rights under this Agreement shall
243  *		terminate if it fails to comply with any of the material
244  *		terms or conditions of this Agreement and does not cure
245  *		such failure in a reasonable period of time after becoming
246  *		aware of such noncompliance. If all Recipient's rights
247  *		under this Agreement terminate, Recipient agrees to cease
248  *		use and distribution of the Program as soon as reasonably
249  *		practicable. However, Recipient's obligations under this
250  *		Agreement and any licenses granted by Recipient relating
251  *		to the Program shall continue and survive.
252  *
253  *		Everyone is permitted to copy and distribute copies of
254  *		this Agreement, but in order to avoid inconsistency the
255  *		Agreement is copyrighted and may only be modified in the
256  *		following manner. The Agreement Steward reserves the right
257  *		to publish new versions (including revisions) of this
258  *		Agreement from time to time. No one other than the
259  *		Agreement Steward has the right to modify this Agreement.
260  *
261  *		IBM is the initial Agreement Steward. IBM may assign the
262  *		responsibility to serve as the Agreement Steward to a
263  *		suitable separate entity. Each new version of the
264  *		Agreement will be given a distinguishing version number.
265  *		The Program (including Contributions) may always be
266  *		distributed subject to the version of the Agreement under
267  *		which it was received. In addition, after a new version of
268  *		the Agreement is published, Contributor may elect to
269  *		distribute the Program (including its Contributions) under
270  *		the new version. Except as expressly stated in Sections
271  *		2(a) and 2(b) above, Recipient receives no rights or
272  *		licenses to the intellectual property of any Contributor
273  *		under this Agreement, whether expressly, by implication,
274  *		estoppel or otherwise. All rights in the Program not
275  *		expressly granted under this Agreement are reserved.
276  *
277  *
278  *		This Agreement is governed by the laws of the State of New
279  *		York and the intellectual property laws of the United
280  *		States of America. No party to this Agreement will bring a
281  *		legal action under this Agreement more than one year after
282  *		the cause of action arose. Each party waives its rights to
283  *		a jury trial in any resulting litigation.
284  *
285  *
286  *
287  * (C) COPYRIGHT International Business Machines Corp. 2001,2002
288  */
289 /*
290  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
291  * Use is subject to license terms.
292  */
293 
294 #include "tpmtok_int.h"
295 #include <pwd.h>
296 #include <grp.h>
297 #include <fcntl.h>
298 
299 #define	ALTERNATE_KEYSTORE_PATH "PKCS11_TPM_DIR"
300 #define	PWD_BUFFER_SIZE	1024
301 
302 static char keystore_path[MAXPATHLEN];
303 static boolean_t keystore_path_initialized = 0;
304 
305 TSS_HKEY hPrivateLeafKey;
306 static CK_RV
307 restore_private_token_object(TSS_HCONTEXT, CK_BYTE  *, CK_ULONG, OBJECT *);
308 
309 static struct flock fl = {
310 	0,
311 	0,
312 	0,
313 	0,
314 	0,
315 	0,
316 	{0, 0, 0, 0}
317 };
318 
319 static int
320 lockfile(int fd, int op)
321 {
322 	fl.l_type = op;
323 	return (fcntl(fd, F_SETLKW, &fl));
324 }
325 
326 static char *
327 get_user_default_path(char *home_path)
328 {
329 	struct passwd pwd, *user_info;
330 	char pwdbuf[PWD_BUFFER_SIZE];
331 
332 	if (getpwuid_r(getuid(), &pwd, pwdbuf, PWD_BUFFER_SIZE,
333 	    &user_info) != 0)
334 		return (NULL);
335 
336 	(void) snprintf(home_path, MAXPATHLEN, "/var/tpm/pkcs11/%s",
337 	    user_info ? user_info->pw_name : "");
338 
339 	return (home_path);
340 }
341 
342 char *
343 get_tpm_keystore_path()
344 {
345 	char *env_val;
346 	char home_path[MAXPATHLEN];
347 
348 	if (!keystore_path_initialized) {
349 		env_val = getenv(ALTERNATE_KEYSTORE_PATH);
350 		bzero(keystore_path, sizeof (keystore_path));
351 		/*
352 		 * If it isn't set or is set to the empty string use the
353 		 * default location.  We need to check for the empty string
354 		 * because some users "unset" environment variables by giving
355 		 * them no value, this isn't the same thing as removing it
356 		 * from the environment.
357 		 *
358 		 * We don't want that to attempt to open the token area.
359 		 */
360 		if ((env_val == NULL) || (strcmp(env_val, "") == 0)) {
361 			/* alternate path not specified, use default dir */
362 			char *p = get_user_default_path(home_path);
363 			if (p == NULL)
364 				return (NULL);
365 			(void) snprintf(keystore_path, MAXPATHLEN, "%s", p);
366 		} else {
367 			(void) snprintf(keystore_path, MAXPATHLEN, "%s",
368 			    env_val);
369 		}
370 		keystore_path_initialized = 1;
371 	}
372 	return (keystore_path);
373 }
374 
375 static CK_RV
376 create_keystore_dir()
377 {
378 	char *ksdir = get_tpm_keystore_path();
379 	char objdir[MAXPATHLEN];
380 	CK_RV rv = 0;
381 
382 	if (ksdir == NULL)
383 		return (CKR_FUNCTION_FAILED);
384 
385 	if (mkdir(ksdir, S_IRUSR|S_IWUSR|S_IXUSR) < 0) {
386 		if (errno == EEXIST) {
387 			rv = 0;
388 		} else {
389 			return (CKR_FUNCTION_FAILED);
390 		}
391 	}
392 	if (rv == 0) {
393 		(void) snprintf(objdir, sizeof (objdir),
394 		    "%s/%s", ksdir, TOKEN_OBJ_DIR);
395 
396 		if (mkdir(objdir, S_IRUSR|S_IWUSR|S_IXUSR) < 0) {
397 			if (errno == EEXIST) {
398 				rv = 0;
399 			} else {
400 				return (CKR_FUNCTION_FAILED);
401 			}
402 		}
403 	}
404 	return (CKR_OK);
405 }
406 
407 static void
408 set_perm(int file)
409 {
410 	/*
411 	 * In the TPM token, with per user data stores, we don't share the token
412 	 * object amongst a group. In fact, we want to restrict access to
413 	 * a single user.
414 	 */
415 	(void) fchmod(file, S_IRUSR|S_IWUSR);
416 }
417 
418 #define	READ_TOKEN_INFO_STR(fp, rec, reclen) rc = fread(rec, reclen, 1, fp); \
419 	if (rc != 1) { rc = CKR_FUNCTION_FAILED; goto out_unlock; }
420 
421 #define	READ_TOKEN_INFO_UINT32(fp, rec) rc = fread(&fieldval, \
422 	sizeof (UINT32), 1, fp); \
423 	if (rc != 1) { rc = CKR_FUNCTION_FAILED; goto out_unlock; } \
424 	rec = (CK_ULONG)fieldval;
425 
426 CK_RV
427 load_token_data(TSS_HCONTEXT hContext, TOKEN_DATA *td)
428 {
429 	FILE	*fp;
430 	CK_BYTE	fname[MAXPATHLEN];
431 	CK_RV	rc;
432 	UINT32	fieldval;
433 	char *p = get_tpm_keystore_path();
434 
435 	if (p == NULL)
436 		return (CKR_FUNCTION_FAILED);
437 
438 	(void) snprintf((char *)fname, sizeof (fname),
439 	    "%s/%s", p, TOKEN_DATA_FILE);
440 
441 	rc = XProcLock(xproclock);
442 	if (rc != CKR_OK)
443 		return (rc);
444 
445 	fp = fopen((char *)fname, "r");
446 	if (!fp) {
447 		/* Better error checking added */
448 		if (errno == ENOENT) {
449 			(void) XProcUnLock(xproclock);
450 			rc = create_keystore_dir();
451 			if (rc != 0)
452 				goto out_nolock;
453 
454 			rc = init_token_data(hContext, td);
455 			if (rc != CKR_OK) {
456 				goto out_nolock;
457 			}
458 
459 			rc = XProcLock(xproclock);
460 			if (rc != CKR_OK) {
461 				goto out_nolock;
462 			}
463 
464 			fp = fopen((char *)fname, "r");
465 			if (!fp) {
466 				LogError("failed opening %s for read: %s",
467 				    fname, (char *)strerror(errno));
468 				rc = CKR_FUNCTION_FAILED;
469 				goto out_unlock;
470 			}
471 		} else {
472 			/* Could not open file for some unknown reason */
473 			rc = CKR_FUNCTION_FAILED;
474 			goto out_unlock;
475 		}
476 	}
477 	if (lockfile(fileno(fp), F_RDLCK)) {
478 		(void) fclose(fp);
479 		rc = CKR_FUNCTION_FAILED;
480 		goto out_unlock;
481 	}
482 	set_perm(fileno(fp));
483 
484 	/* Read fields individually because of 64-bit size diffs */
485 	READ_TOKEN_INFO_STR(fp, td->token_info.label,
486 	    sizeof (td->token_info.label));
487 	READ_TOKEN_INFO_STR(fp, td->token_info.manufacturerID,
488 	    sizeof (td->token_info.manufacturerID));
489 	READ_TOKEN_INFO_STR(fp, td->token_info.model,
490 	    sizeof (td->token_info.model));
491 	READ_TOKEN_INFO_STR(fp, td->token_info.serialNumber,
492 	    sizeof (td->token_info.serialNumber));
493 	READ_TOKEN_INFO_UINT32(fp, td->token_info.flags);
494 	READ_TOKEN_INFO_UINT32(fp, td->token_info.ulMaxSessionCount);
495 	READ_TOKEN_INFO_UINT32(fp, td->token_info.ulSessionCount);
496 	READ_TOKEN_INFO_UINT32(fp, td->token_info.ulRwSessionCount);
497 	READ_TOKEN_INFO_UINT32(fp, td->token_info.ulMaxPinLen);
498 	READ_TOKEN_INFO_UINT32(fp, td->token_info.ulMinPinLen);
499 	READ_TOKEN_INFO_UINT32(fp, td->token_info.ulTotalPublicMemory);
500 	READ_TOKEN_INFO_UINT32(fp, td->token_info.ulFreePublicMemory);
501 	READ_TOKEN_INFO_UINT32(fp, td->token_info.ulTotalPrivateMemory);
502 	READ_TOKEN_INFO_UINT32(fp, td->token_info.ulFreePrivateMemory);
503 	READ_TOKEN_INFO_STR(fp, &td->token_info.hardwareVersion,
504 	    sizeof (td->token_info.hardwareVersion));
505 	READ_TOKEN_INFO_STR(fp, &td->token_info.firmwareVersion,
506 	    sizeof (td->token_info.firmwareVersion));
507 	READ_TOKEN_INFO_STR(fp, td->token_info.utcTime,
508 	    sizeof (td->token_info.utcTime));
509 	READ_TOKEN_INFO_STR(fp, td->user_pin_sha,
510 	    sizeof (td->user_pin_sha));
511 	READ_TOKEN_INFO_STR(fp, td->so_pin_sha,
512 	    sizeof (td->so_pin_sha));
513 	READ_TOKEN_INFO_STR(fp, td->next_token_object_name,
514 	    sizeof (td->next_token_object_name));
515 	READ_TOKEN_INFO_STR(fp, &td->tweak_vector,
516 	    sizeof (td->tweak_vector));
517 
518 	(void) lockfile(fileno(fp), F_UNLCK);
519 	(void) fclose(fp);
520 
521 	if (rc == 0)
522 		rc = CKR_FUNCTION_FAILED;
523 	else
524 		rc = CKR_OK;
525 
526 out_unlock:
527 	(void) XProcUnLock(xproclock);
528 
529 out_nolock:
530 	return (rc);
531 }
532 
533 
534 #define	WRITE_TOKEN_INFO_STR(fp, rec, reclen) rc = fwrite(rec, reclen, 1, fp); \
535 	if (rc != 1) { rc = CKR_FUNCTION_FAILED; goto done; }
536 
537 #define	WRITE_TOKEN_INFO_UINT32(fp, rec) fieldval = (UINT32)rec; \
538 	rc = fwrite(&fieldval, sizeof (UINT32), 1, fp); \
539 	if (rc != 1) { rc = CKR_FUNCTION_FAILED; goto done; }
540 
541 CK_RV
542 save_token_data(TOKEN_DATA *td)
543 {
544 	FILE	*fp;
545 	CK_RV	rc;
546 	CK_BYTE	fname[MAXPATHLEN];
547 	char *p = get_tpm_keystore_path();
548 	UINT32 fieldval;
549 
550 	if (p == NULL)
551 		return (CKR_FUNCTION_FAILED);
552 
553 	(void) snprintf((char *)fname, sizeof (fname),
554 	    "%s/%s", p, TOKEN_DATA_FILE);
555 
556 	rc = XProcLock(xproclock);
557 	if (rc != CKR_OK)
558 		goto out_nolock;
559 
560 	fp = fopen((char *)fname, "w");
561 
562 	if (!fp) {
563 		rc = CKR_FUNCTION_FAILED;
564 		goto done;
565 	}
566 	if (lockfile(fileno(fp), F_WRLCK)) {
567 		rc = CKR_FUNCTION_FAILED;
568 		(void) fclose(fp);
569 		goto done;
570 	}
571 	set_perm(fileno(fp));
572 
573 	/* Write token fields individually to maintain sizes on 64 and 32 bit */
574 	WRITE_TOKEN_INFO_STR(fp, td->token_info.label,
575 	    sizeof (td->token_info.label));
576 	WRITE_TOKEN_INFO_STR(fp, td->token_info.manufacturerID,
577 	    sizeof (td->token_info.manufacturerID));
578 	WRITE_TOKEN_INFO_STR(fp, td->token_info.model,
579 	    sizeof (td->token_info.model));
580 	WRITE_TOKEN_INFO_STR(fp, td->token_info.serialNumber,
581 	    sizeof (td->token_info.serialNumber));
582 	WRITE_TOKEN_INFO_UINT32(fp, td->token_info.flags);
583 	WRITE_TOKEN_INFO_UINT32(fp, td->token_info.ulMaxSessionCount);
584 	WRITE_TOKEN_INFO_UINT32(fp, td->token_info.ulSessionCount);
585 	WRITE_TOKEN_INFO_UINT32(fp, td->token_info.ulRwSessionCount);
586 	WRITE_TOKEN_INFO_UINT32(fp, td->token_info.ulMaxPinLen);
587 	WRITE_TOKEN_INFO_UINT32(fp, td->token_info.ulMinPinLen);
588 	WRITE_TOKEN_INFO_UINT32(fp, td->token_info.ulTotalPublicMemory);
589 	WRITE_TOKEN_INFO_UINT32(fp, td->token_info.ulFreePublicMemory);
590 	WRITE_TOKEN_INFO_UINT32(fp, td->token_info.ulTotalPrivateMemory);
591 	WRITE_TOKEN_INFO_UINT32(fp, td->token_info.ulFreePrivateMemory);
592 	WRITE_TOKEN_INFO_STR(fp, &td->token_info.hardwareVersion,
593 	    sizeof (td->token_info.hardwareVersion));
594 	WRITE_TOKEN_INFO_STR(fp, &td->token_info.firmwareVersion,
595 	    sizeof (td->token_info.firmwareVersion));
596 	WRITE_TOKEN_INFO_STR(fp, td->token_info.utcTime,
597 	    sizeof (td->token_info.utcTime));
598 	WRITE_TOKEN_INFO_STR(fp, td->user_pin_sha,
599 	    sizeof (td->user_pin_sha));
600 	WRITE_TOKEN_INFO_STR(fp, td->so_pin_sha,
601 	    sizeof (td->so_pin_sha));
602 	WRITE_TOKEN_INFO_STR(fp, td->next_token_object_name,
603 	    sizeof (td->next_token_object_name));
604 	WRITE_TOKEN_INFO_STR(fp, &td->tweak_vector,
605 	    sizeof (td->tweak_vector));
606 
607 	(void) lockfile(fileno(fp), F_UNLCK);
608 	(void) fclose(fp);
609 
610 	rc = CKR_OK;
611 done:
612 	(void) XProcUnLock(xproclock);
613 
614 out_nolock:
615 	return (rc);
616 }
617 
618 CK_RV
619 save_token_object(TSS_HCONTEXT hContext, OBJECT *obj)
620 {
621 	FILE	*fp = NULL;
622 	CK_BYTE	line[100];
623 	CK_RV	rc;
624 	CK_BYTE	fname[MAXPATHLEN];
625 	char *p = get_tpm_keystore_path();
626 
627 	if (p == NULL)
628 		return (CKR_FUNCTION_FAILED);
629 
630 	if (object_is_private(obj) == TRUE)
631 		rc = save_private_token_object(hContext, obj);
632 	else
633 		rc = save_public_token_object(obj);
634 
635 	if (rc != CKR_OK)
636 		return (rc);
637 
638 	(void) snprintf((char *)fname, sizeof (fname),
639 	    "%s/%s/%s", p, TOKEN_OBJ_DIR, TOKEN_OBJ_INDEX_FILE);
640 
641 	fp = fopen((char *)fname, "r");
642 	if (fp) {
643 		if (lockfile(fileno(fp), F_RDLCK)) {
644 			(void) fclose(fp);
645 			return (CKR_FUNCTION_FAILED);
646 		}
647 		set_perm(fileno(fp));
648 		while (!feof(fp)) {
649 			(void) fgets((char *)line, 50, fp);
650 			if (!feof(fp)) {
651 				line[strlen((char *)line) - 1] = 0;
652 				if (strcmp((char *)line,
653 				    (char *)(obj->name)) == 0) {
654 					(void) lockfile(fileno(fp), F_UNLCK);
655 					(void) fclose(fp);
656 					return (CKR_OK);
657 				}
658 			}
659 		}
660 		(void) lockfile(fileno(fp), F_UNLCK);
661 		(void) fclose(fp);
662 	}
663 
664 	fp = fopen((char *)fname, "a");
665 	if (!fp)
666 		return (CKR_FUNCTION_FAILED);
667 
668 	if (lockfile(fileno(fp), F_WRLCK)) {
669 		(void) fclose(fp);
670 		return (CKR_FUNCTION_FAILED);
671 	}
672 	set_perm(fileno(fp));
673 
674 	(void) fprintf(fp, "%s\n", obj->name);
675 	(void) lockfile(fileno(fp), F_UNLCK);
676 	(void) fclose(fp);
677 
678 	return (CKR_OK);
679 }
680 
681 CK_RV
682 save_public_token_object(OBJECT *obj)
683 {
684 	FILE	*fp = NULL;
685 	CK_BYTE	*cleartxt = NULL;
686 	CK_BYTE	fname[MAXPATHLEN];
687 	UINT32	cleartxt_len;
688 	CK_BBOOL	flag = FALSE;
689 	CK_RV	rc;
690 	UINT32	total_len;
691 
692 	char *p = get_tpm_keystore_path();
693 
694 	if (p == NULL)
695 		return (CKR_FUNCTION_FAILED);
696 
697 	(void) snprintf((char *)fname, sizeof (fname),
698 	    "%s/%s/%s", p, TOKEN_OBJ_DIR, obj->name);
699 
700 	rc = object_flatten(obj, &cleartxt, &cleartxt_len);
701 	if (rc != CKR_OK)
702 		goto error;
703 
704 	fp = fopen((char *)fname, "w");
705 	if (!fp) {
706 		LogError("Error opening %s - %s", fname,
707 		    (char *)strerror(errno));
708 		rc = CKR_FUNCTION_FAILED;
709 		goto error;
710 	}
711 	if (lockfile(fileno(fp), F_WRLCK)) {
712 		(void) fclose(fp);
713 		return (CKR_FUNCTION_FAILED);
714 	}
715 
716 	set_perm(fileno(fp));
717 
718 	total_len = cleartxt_len + sizeof (UINT32) + sizeof (CK_BBOOL);
719 
720 	(void) fwrite(&total_len, sizeof (total_len), 1, fp);
721 	(void) fwrite(&flag, sizeof (flag), 1, fp);
722 	(void) fwrite(cleartxt, cleartxt_len, 1, fp);
723 
724 	(void) lockfile(fileno(fp), F_UNLCK);
725 	(void) fclose(fp);
726 	free(cleartxt);
727 
728 	return (CKR_OK);
729 
730 error:
731 	if (fp)
732 		(void) fclose(fp);
733 	if (cleartxt)
734 		free(cleartxt);
735 	return (rc);
736 }
737 
738 CK_RV
739 save_private_token_object(TSS_HCONTEXT hContext, OBJECT *obj)
740 {
741 	FILE *fp = NULL;
742 	CK_BYTE	*obj_data  = NULL;
743 	CK_BYTE	*cleartxt  = NULL;
744 	CK_BYTE	*ciphertxt = NULL;
745 	CK_BYTE	*ptr = NULL;
746 	CK_BYTE	fname[100];
747 	CK_BYTE	hash_sha[SHA1_DIGEST_LENGTH];
748 	CK_BBOOL	flag;
749 	CK_RV	rc;
750 	CK_ULONG ciphertxt_len;
751 	UINT32 cleartxt_len;
752 	UINT32 padded_len;
753 	UINT32	obj_data_len_32;
754 	UINT32	total_len;
755 	UINT32	chunksize, blocks;
756 	char 	*p = get_tpm_keystore_path();
757 
758 	if (p == NULL)
759 		return (CKR_FUNCTION_FAILED);
760 
761 	rc = object_flatten(obj, &obj_data, &obj_data_len_32);
762 	if (rc != CKR_OK) {
763 		goto error;
764 	}
765 	/*
766 	 * format for the object file:
767 	 *    private flag
768 	 *	---- begin encrypted part	<--+
769 	 *	length of object data (4 bytes)	|
770 	 *	object data			+---- sensitive part
771 	 *	SHA of (object data)		|
772 	 *	---- end encrypted part		<--+
773 	 */
774 	if ((rc = compute_sha(obj_data, obj_data_len_32, hash_sha)) != CKR_OK)
775 		goto error;
776 
777 	/*
778 	 * RSA OAEP crypto uses chunks smaller than the max to make room
779 	 * for the hashes.
780 	 * chunksize = RSA_Modulus_Size - (2 * SHA1_DIGEST_SIZE + 2) - (4 - 1)
781 	 * == 209
782 	 */
783 	chunksize = RSA_BLOCK_SIZE - (2 * SHA1_DIGEST_LENGTH + 2) - 5;
784 
785 	cleartxt_len = sizeof (UINT32) + obj_data_len_32 + SHA1_DIGEST_LENGTH;
786 
787 	blocks = cleartxt_len / chunksize + ((cleartxt_len % chunksize) > 0);
788 	padded_len   = RSA_BLOCK_SIZE * blocks;
789 
790 	cleartxt  = (CK_BYTE *)malloc(padded_len);
791 	ciphertxt = (CK_BYTE *)malloc(padded_len);
792 	if (!cleartxt || !ciphertxt) {
793 		rc = CKR_HOST_MEMORY;
794 		goto error;
795 	}
796 
797 	ciphertxt_len = padded_len;
798 
799 	ptr = cleartxt;
800 	(void) memcpy(ptr, &obj_data_len_32, sizeof (UINT32));
801 	ptr += sizeof (UINT32);
802 	(void) memcpy(ptr,  obj_data, obj_data_len_32);
803 	ptr += obj_data_len_32;
804 	(void) memcpy(ptr, hash_sha, SHA1_DIGEST_LENGTH);
805 
806 	(void) add_pkcs_padding(cleartxt + cleartxt_len, RSA_BLOCK_SIZE,
807 	    cleartxt_len, padded_len);
808 
809 	/* the encrypt function will compute the padded length */
810 	rc = tpm_encrypt_data(hContext, hPrivateLeafKey, cleartxt, cleartxt_len,
811 	    ciphertxt, &ciphertxt_len);
812 
813 	if (rc != CKR_OK) {
814 		goto error;
815 	}
816 
817 	(void) snprintf((char *)fname, sizeof (fname),
818 	    "%s/%s/%s", p, TOKEN_OBJ_DIR, obj->name);
819 
820 	fp = fopen((char *)fname, "w");
821 	if (!fp) {
822 		rc = CKR_FUNCTION_FAILED;
823 		goto error;
824 	}
825 	if (lockfile(fileno(fp), F_WRLCK)) {
826 		rc = CKR_FUNCTION_FAILED;
827 		goto error;
828 	}
829 
830 	set_perm(fileno(fp));
831 
832 	total_len = sizeof (UINT32) + sizeof (CK_BBOOL) + (UINT32)ciphertxt_len;
833 
834 	flag = TRUE;
835 
836 	(void) fwrite(&total_len, sizeof (UINT32), 1, fp);
837 	(void) fwrite(&flag, sizeof (CK_BBOOL), 1, fp);
838 	(void) fwrite(ciphertxt, ciphertxt_len,    1, fp);
839 
840 	(void) lockfile(fileno(fp), F_UNLCK);
841 	(void) fclose(fp);
842 
843 	free(obj_data);
844 	free(cleartxt);
845 	free(ciphertxt);
846 	return (CKR_OK);
847 
848 error:
849 	if (fp)
850 		(void) fclose(fp);
851 	if (obj_data)
852 		free(obj_data);
853 	if (cleartxt)
854 		free(cleartxt);
855 	if (ciphertxt)
856 		free(ciphertxt);
857 
858 	return (rc);
859 }
860 
861 CK_RV
862 load_public_token_objects(void)
863 {
864 	FILE	*fp1 = NULL, *fp2 = NULL;
865 	CK_BYTE *buf = NULL;
866 	CK_BYTE tmp[MAXPATHLEN], fname[MAXPATHLEN], iname[MAXPATHLEN];
867 	CK_BBOOL priv;
868 	UINT32 size;
869 	char *ksdir = get_tpm_keystore_path();
870 
871 	if (ksdir == NULL)
872 		return (CKR_FUNCTION_FAILED);
873 
874 	(void) snprintf((char *)iname, sizeof (iname),
875 	    "%s/%s/%s", ksdir,
876 	    TOKEN_OBJ_DIR, TOKEN_OBJ_INDEX_FILE);
877 
878 	fp1 = fopen((char *)iname, "r");
879 	if (!fp1)
880 		return (CKR_OK);  // no token objects
881 
882 	if (lockfile(fileno(fp1), F_RDLCK)) {
883 		(void) fclose(fp1);
884 		return (CKR_FUNCTION_FAILED);
885 	}
886 
887 	while (!feof(fp1)) {
888 		(void) fgets((char *)tmp, 50, fp1);
889 		if (feof(fp1))
890 			break;
891 
892 		tmp[strlen((char *)tmp) - 1] = 0;
893 
894 		(void) snprintf((char *)fname, sizeof (fname),
895 		    "%s/%s/", ksdir, TOKEN_OBJ_DIR);
896 
897 		(void) strncat((char *)fname, (const char *)tmp,
898 		    (size_t)sizeof (fname));
899 
900 		fp2 = fopen((char *)fname, "r");
901 		if (!fp2)
902 			continue;
903 
904 		(void) fread(&size, sizeof (UINT32), 1, fp2);
905 		(void) fread(&priv, sizeof (CK_BBOOL), 1, fp2);
906 		if (priv == TRUE) {
907 			(void) fclose(fp2);
908 			continue;
909 		}
910 
911 		size = size - sizeof (UINT32) - sizeof (CK_BBOOL);
912 		buf = (CK_BYTE *)malloc(size);
913 		if (!buf) {
914 			(void) lockfile(fileno(fp1), F_UNLCK);
915 			(void) fclose(fp1);
916 			(void) fclose(fp2);
917 			return (CKR_HOST_MEMORY);
918 		}
919 
920 		(void) fread(buf, size, 1, fp2);
921 
922 		if (pthread_mutex_lock(&obj_list_mutex)) {
923 			(void) lockfile(fileno(fp1), F_UNLCK);
924 			(void) fclose(fp1);
925 			(void) fclose(fp2);
926 			free(buf);
927 			return (CKR_FUNCTION_FAILED);
928 		}
929 
930 		(void) object_mgr_restore_obj(buf, NULL);
931 
932 		(void) pthread_mutex_unlock(&obj_list_mutex);
933 		free(buf);
934 		(void) fclose(fp2);
935 	}
936 	(void) lockfile(fileno(fp1), F_UNLCK);
937 	(void) fclose(fp1);
938 
939 	return (CKR_OK);
940 }
941 
942 CK_RV
943 load_private_token_objects(TSS_HCONTEXT hContext)
944 {
945 	FILE *fp1 = NULL, *fp2 = NULL;
946 	CK_BYTE *buf = NULL;
947 	CK_BYTE tmp[MAXPATHLEN], fname[MAXPATHLEN], iname[MAXPATHLEN];
948 	CK_BBOOL priv;
949 	UINT32 size;
950 	CK_RV rc;
951 	char *ksdir = get_tpm_keystore_path();
952 
953 	if (ksdir == NULL)
954 		return (CKR_FUNCTION_FAILED);
955 
956 	(void) snprintf((char *)iname, sizeof (iname),
957 	    "%s/%s/%s", ksdir, TOKEN_OBJ_DIR, TOKEN_OBJ_INDEX_FILE);
958 
959 	fp1 = fopen((char *)iname, "r");
960 	if (!fp1)
961 		return (CKR_OK);
962 
963 	if (lockfile(fileno(fp1), F_RDLCK)) {
964 		rc = CKR_FUNCTION_FAILED;
965 		goto error;
966 	}
967 
968 	while (!feof(fp1)) {
969 		(void) fgets((char *)tmp, sizeof (tmp), fp1);
970 		if (feof(fp1))
971 			break;
972 
973 		tmp[strlen((char *)tmp) - 1] = 0;
974 
975 		(void) snprintf((char *)fname, sizeof (fname),
976 		    "%s/%s/%s", ksdir, TOKEN_OBJ_DIR, tmp);
977 
978 		fp2 = fopen((char *)fname, "r");
979 		if (!fp2)
980 			continue;
981 
982 		(void) fread(&size, sizeof (UINT32), 1, fp2);
983 		(void) fread(&priv, sizeof (CK_BBOOL), 1, fp2);
984 		if (priv == FALSE) {
985 			(void) fclose(fp2);
986 			continue;
987 		}
988 
989 		size = size - sizeof (UINT32) - sizeof (CK_BBOOL);
990 		buf = (CK_BYTE *)malloc(size);
991 		if (!buf) {
992 			rc = CKR_HOST_MEMORY;
993 			goto error;
994 		}
995 
996 		rc = fread((char *)buf, size, 1, fp2);
997 		if (rc != 1) {
998 			rc = CKR_FUNCTION_FAILED;
999 			goto error;
1000 		}
1001 
1002 		if (pthread_mutex_lock(&obj_list_mutex)) {
1003 			rc = CKR_FUNCTION_FAILED;
1004 			goto error;
1005 		}
1006 		rc = restore_private_token_object(hContext, buf, size, NULL);
1007 		(void) pthread_mutex_unlock(&obj_list_mutex);
1008 		if (rc != CKR_OK)
1009 			goto error;
1010 
1011 		free(buf);
1012 		(void) fclose(fp2);
1013 	}
1014 	(void) lockfile(fileno(fp1), F_UNLCK);
1015 	(void) fclose(fp1);
1016 
1017 	return (CKR_OK);
1018 
1019 error:
1020 	if (buf)
1021 		free(buf);
1022 	if (fp1) {
1023 		(void) lockfile(fileno(fp1), F_UNLCK);
1024 		(void) fclose(fp1);
1025 	}
1026 	if (fp2)
1027 		(void) fclose(fp2);
1028 	return (rc);
1029 }
1030 
1031 static CK_RV
1032 restore_private_token_object(
1033 	TSS_HCONTEXT hContext,
1034 	CK_BYTE  *data,
1035 	CK_ULONG len,
1036 	OBJECT   *pObj)
1037 {
1038 	CK_BYTE * cleartxt  = NULL;
1039 	CK_BYTE * obj_data  = NULL;
1040 	CK_BYTE *ptr = NULL;
1041 	CK_BYTE hash_sha[SHA1_DIGEST_LENGTH];
1042 	UINT32 cleartxt_len;
1043 	UINT32 obj_data_len;
1044 	CK_RV rc;
1045 
1046 	/*
1047 	 * format for the object data:
1048 	 *    (private flag has already been read at this point)
1049 	 *    ---- begin encrypted part
1050 	 *	length of object data (4 bytes)
1051 	 *	object data
1052 	 *	SHA of object data
1053 	 *    ---- end encrypted part
1054 	 */
1055 
1056 	cleartxt_len = len;
1057 
1058 	cleartxt = (CK_BYTE *)malloc(len);
1059 	if (!cleartxt) {
1060 		rc = CKR_HOST_MEMORY;
1061 		goto done;
1062 	}
1063 
1064 	rc = tpm_decrypt_data(hContext, hPrivateLeafKey, data, len,
1065 	    cleartxt, &len);
1066 
1067 	if (rc != CKR_OK) {
1068 		goto done;
1069 	}
1070 
1071 	(void) strip_pkcs_padding(cleartxt, len, &cleartxt_len);
1072 
1073 	if (cleartxt_len > len) {
1074 		rc = CKR_FUNCTION_FAILED;
1075 		goto done;
1076 	}
1077 
1078 	ptr = cleartxt;
1079 
1080 	bcopy(ptr, &obj_data_len, sizeof (UINT32));
1081 	ptr += sizeof (UINT32);
1082 	obj_data = ptr;
1083 
1084 	if ((rc = compute_sha(ptr, obj_data_len, hash_sha)) != CKR_OK)
1085 		goto done;
1086 	ptr += obj_data_len;
1087 
1088 	if (memcmp((const void *)ptr, (const void *)hash_sha,
1089 	    (size_t)SHA1_DIGEST_LENGTH) != 0) {
1090 		rc = CKR_FUNCTION_FAILED;
1091 		goto done;
1092 	}
1093 
1094 	(void) object_mgr_restore_obj(obj_data, pObj);
1095 	rc = CKR_OK;
1096 done:
1097 	if (cleartxt)
1098 		free(cleartxt);
1099 
1100 	return (rc);
1101 }
1102 
1103 CK_RV
1104 reload_token_object(TSS_HCONTEXT hContext, OBJECT *obj)
1105 {
1106 	FILE *fp = NULL;
1107 	CK_BYTE *buf = NULL;
1108 	CK_BYTE fname[MAXPATHLEN];
1109 	CK_BBOOL priv;
1110 	UINT32 size;
1111 	CK_RV rc;
1112 	char *p = get_tpm_keystore_path();
1113 
1114 	if (p == NULL)
1115 		return (CKR_FUNCTION_FAILED);
1116 
1117 	(void) memset((char *)fname, 0x0, sizeof (fname));
1118 
1119 	(void) snprintf((char *)fname, sizeof (fname),
1120 	    "%s/%s/", p, TOKEN_OBJ_DIR);
1121 
1122 	(void) strncat((char *)fname, (char *)obj->name, sizeof (fname));
1123 
1124 	fp = fopen((char *)fname, "r");
1125 	if (!fp) {
1126 		rc = CKR_FUNCTION_FAILED;
1127 		goto done;
1128 	}
1129 	if (lockfile(fileno(fp), F_RDLCK)) {
1130 		rc = CKR_FUNCTION_FAILED;
1131 		goto done;
1132 	}
1133 
1134 	set_perm(fileno(fp));
1135 
1136 	(void) fread(&size, sizeof (UINT32), 1, fp);
1137 	(void) fread(&priv, sizeof (CK_BBOOL), 1, fp);
1138 
1139 	size = size - sizeof (UINT32) - sizeof (CK_BBOOL);
1140 
1141 	buf = (CK_BYTE *)malloc(size);
1142 	if (!buf) {
1143 		rc = CKR_HOST_MEMORY;
1144 		goto done;
1145 	}
1146 
1147 	(void) fread(buf, size, 1, fp);
1148 
1149 	if (priv) {
1150 		rc = restore_private_token_object(hContext, buf, size, obj);
1151 	} else {
1152 		rc = object_mgr_restore_obj(buf, obj);
1153 	}
1154 
1155 done:
1156 	if (fp) {
1157 		(void) lockfile(fileno(fp), F_UNLCK);
1158 		(void) fclose(fp);
1159 	}
1160 	if (buf)
1161 		free(buf);
1162 	return (rc);
1163 }
1164 
1165 static int
1166 islink(char *fname)
1167 {
1168 	struct stat st;
1169 
1170 	if (stat((const char *)fname, &st))
1171 		return (-1);
1172 	else if (S_ISLNK(st.st_mode))
1173 		return (1);
1174 	return (0);
1175 }
1176 
1177 CK_RV
1178 delete_token_object(OBJECT *obj)
1179 {
1180 	FILE *fp1, *fp2;
1181 	CK_BYTE line[100];
1182 	char objidx[MAXPATHLEN], idxtmp[MAXPATHLEN], fname[MAXPATHLEN];
1183 	char *ksdir = get_tpm_keystore_path();
1184 
1185 	if (ksdir == NULL)
1186 		return (CKR_FUNCTION_FAILED);
1187 
1188 	(void) snprintf(objidx, sizeof (objidx),
1189 	    "%s/%s/%s", ksdir, TOKEN_OBJ_DIR, TOKEN_OBJ_INDEX_FILE);
1190 
1191 	(void) snprintf(idxtmp, sizeof (idxtmp),
1192 	    "%s/IDX.TMP", ksdir, TOKEN_OBJ_DIR);
1193 
1194 	/*
1195 	 * If either file is a link, fail.
1196 	 */
1197 	if (islink(objidx) != 0)
1198 		return (CKR_FUNCTION_FAILED);
1199 
1200 	/*
1201 	 * idxtmp is a temporary file (and should not exist yet), only fail
1202 	 * if it is already an existing link.
1203 	 */
1204 	if (islink(idxtmp) == 1)
1205 		return (CKR_FUNCTION_FAILED);
1206 
1207 	fp1 = fopen(objidx, "r");
1208 	fp2 = fopen(idxtmp, "w");
1209 	if (!fp1 || !fp2) {
1210 		if (fp1)
1211 			(void) fclose(fp1);
1212 		if (fp2)
1213 			(void) fclose(fp2);
1214 		return (CKR_FUNCTION_FAILED);
1215 	}
1216 
1217 	if (lockfile(fileno(fp1), F_RDLCK)) {
1218 		(void) fclose(fp1);
1219 		(void) fclose(fp2);
1220 		return (CKR_FUNCTION_FAILED);
1221 	}
1222 	if (lockfile(fileno(fp2), F_WRLCK)) {
1223 		(void) lockfile(fileno(fp1), F_UNLCK);
1224 		(void) fclose(fp1);
1225 		(void) fclose(fp2);
1226 		return (CKR_FUNCTION_FAILED);
1227 	}
1228 	set_perm(fileno(fp2));
1229 
1230 	while (!feof(fp1)) {
1231 		(void) fgets((char *)line, 50, fp1);
1232 		if (!feof(fp1)) {
1233 			line[ strlen((char *)line)-1 ] = 0;
1234 			if (strcmp((char *)line, (char *)obj->name))
1235 				(void) fprintf(fp2, "%s\n", line);
1236 		}
1237 	}
1238 
1239 	(void) lockfile(fileno(fp1), F_UNLCK);
1240 	(void) lockfile(fileno(fp2), F_UNLCK);
1241 	(void) fclose(fp1);
1242 	(void) fclose(fp2);
1243 
1244 	fp2 = fopen(objidx, "w");
1245 	fp1 = fopen(idxtmp, "r");
1246 	if (!fp1 || !fp2) {
1247 		if (fp1)
1248 			(void) fclose(fp1);
1249 		if (fp2)
1250 			(void) fclose(fp2);
1251 		return (CKR_FUNCTION_FAILED);
1252 	}
1253 	if (lockfile(fileno(fp1), F_RDLCK)) {
1254 		(void) fclose(fp1);
1255 		(void) fclose(fp2);
1256 		return (CKR_FUNCTION_FAILED);
1257 	}
1258 	if (lockfile(fileno(fp2), F_WRLCK)) {
1259 		(void) lockfile(fileno(fp1), F_UNLCK);
1260 		(void) fclose(fp1);
1261 		(void) fclose(fp2);
1262 		return (CKR_FUNCTION_FAILED);
1263 	}
1264 
1265 	set_perm(fileno(fp2));
1266 
1267 	while (!feof(fp1)) {
1268 		(void) fgets((char *)line, 50, fp1);
1269 		if (!feof(fp1))
1270 			(void) fprintf(fp2, "%s", (char *)line);
1271 	}
1272 
1273 	(void) lockfile(fileno(fp1), F_UNLCK);
1274 	(void) lockfile(fileno(fp2), F_UNLCK);
1275 	(void) fclose(fp1);
1276 	(void) fclose(fp2);
1277 
1278 	(void) snprintf(fname, sizeof (fname),
1279 	    "%s/%s/%s", ksdir, TOKEN_OBJ_DIR, (char *)obj->name);
1280 
1281 	(void) unlink(fname);
1282 	return (CKR_OK);
1283 }
1284