xref: /illumos-gate/usr/src/lib/pkcs11/pkcs11_tpm/common/loadsave.c (revision 5279807d7e1818eac6f90ac640b7a89cdb37522d)
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 	CK_ULONG	cleartxt_len;
688 	CK_BBOOL	flag = FALSE;
689 	CK_RV	rc;
690 	UINT32	total_len;
691 	char *p = get_tpm_keystore_path();
692 
693 	if (p == NULL)
694 		return (CKR_FUNCTION_FAILED);
695 
696 	(void) snprintf((char *)fname, sizeof (fname),
697 	    "%s/%s/%s", p, TOKEN_OBJ_DIR, obj->name);
698 
699 	rc = object_flatten(obj, &cleartxt, &cleartxt_len);
700 	if (rc != CKR_OK)
701 		goto error;
702 
703 	fp = fopen((char *)fname, "w");
704 	if (!fp) {
705 		LogError("Error opening %s - %s", fname,
706 		    (char *)strerror(errno));
707 		rc = CKR_FUNCTION_FAILED;
708 		goto error;
709 	}
710 	if (lockfile(fileno(fp), F_WRLCK)) {
711 		(void) fclose(fp);
712 		return (CKR_FUNCTION_FAILED);
713 	}
714 
715 	set_perm(fileno(fp));
716 
717 	total_len = cleartxt_len + sizeof (CK_ULONG) + sizeof (CK_BBOOL);
718 
719 	(void) fwrite(&total_len, sizeof (UINT32), 1, fp);
720 	(void) fwrite(&flag, sizeof (CK_BBOOL), 1, fp);
721 	(void) fwrite(cleartxt, cleartxt_len, 1, fp);
722 
723 	(void) lockfile(fileno(fp), F_UNLCK);
724 	(void) fclose(fp);
725 	free(cleartxt);
726 
727 	return (CKR_OK);
728 
729 error:
730 	if (fp)
731 		(void) fclose(fp);
732 	if (cleartxt)
733 		free(cleartxt);
734 	return (rc);
735 }
736 
737 CK_RV
738 save_private_token_object(TSS_HCONTEXT hContext, OBJECT *obj)
739 {
740 	FILE *fp = NULL;
741 	CK_BYTE	*obj_data  = NULL;
742 	CK_BYTE	*cleartxt  = NULL;
743 	CK_BYTE	*ciphertxt = NULL;
744 	CK_BYTE	*ptr = NULL;
745 	CK_BYTE	fname[100];
746 	CK_BYTE	hash_sha[SHA1_DIGEST_LENGTH];
747 	CK_ULONG obj_data_len, cleartxt_len, ciphertxt_len;
748 	UINT32	padded_len;
749 	CK_BBOOL	flag;
750 	CK_RV	rc;
751 	UINT32	obj_data_len_32;
752 	UINT32	total_len;
753 	UINT32	chunksize, blocks;
754 	char 	*p = get_tpm_keystore_path();
755 
756 	if (p == NULL)
757 		return (CKR_FUNCTION_FAILED);
758 
759 	rc = object_flatten(obj, &obj_data, &obj_data_len);
760 	obj_data_len_32 = obj_data_len;
761 	if (rc != CKR_OK) {
762 		goto error;
763 	}
764 	/*
765 	 * format for the object file:
766 	 *    private flag
767 	 *	---- begin encrypted part	<--+
768 	 *	length of object data		|
769 	 *	object data			+---- sensitive part
770 	 *	SHA of (object data)		|
771 	 *	---- end encrypted part		<--+
772 	 */
773 	if ((rc = compute_sha(obj_data, obj_data_len, hash_sha)) != CKR_OK)
774 		goto error;
775 
776 	/*
777 	 * RSA OAEP crypto uses chunks smaller than the max to make room
778 	 * for the hashes.
779 	 * chunksize = RSA_Modulus_Size - (2 * SHA1_DIGEST_SIZE + 2) - (4 - 1)
780 	 * == 209
781 	 */
782 	chunksize = RSA_BLOCK_SIZE - (2 * SHA1_DIGEST_LENGTH + 2) - 5;
783 
784 	cleartxt_len = sizeof (CK_ULONG) + obj_data_len_32 + SHA1_DIGEST_LENGTH;
785 
786 	blocks = cleartxt_len / chunksize + ((cleartxt_len % chunksize) > 0);
787 	padded_len   = RSA_BLOCK_SIZE * blocks;
788 
789 	cleartxt  = (CK_BYTE *)malloc(padded_len);
790 	ciphertxt = (CK_BYTE *)malloc(padded_len);
791 	if (!cleartxt || !ciphertxt) {
792 		rc = CKR_HOST_MEMORY;
793 		goto error;
794 	}
795 
796 	ciphertxt_len = padded_len;
797 
798 	ptr = cleartxt;
799 	(void) memcpy(ptr, &obj_data_len_32, sizeof (CK_ULONG));
800 	ptr += sizeof (CK_ULONG);
801 	(void) memcpy(ptr,  obj_data, obj_data_len_32);
802 	ptr += obj_data_len_32;
803 	(void) memcpy(ptr, hash_sha, SHA1_DIGEST_LENGTH);
804 
805 	(void) add_pkcs_padding(cleartxt + cleartxt_len, RSA_BLOCK_SIZE,
806 	    cleartxt_len, padded_len);
807 
808 	/* the encrypt function will compute the padded length */
809 	rc = tpm_encrypt_data(hContext, hPrivateLeafKey, cleartxt, cleartxt_len,
810 	    ciphertxt, &ciphertxt_len);
811 
812 	if (rc != CKR_OK) {
813 		goto error;
814 	}
815 
816 	(void) snprintf((char *)fname, sizeof (fname),
817 	    "%s/%s/%s", p, TOKEN_OBJ_DIR, obj->name);
818 
819 	fp = fopen((char *)fname, "w");
820 	if (!fp) {
821 		rc = CKR_FUNCTION_FAILED;
822 		goto error;
823 	}
824 	if (lockfile(fileno(fp), F_WRLCK)) {
825 		rc = CKR_FUNCTION_FAILED;
826 		goto error;
827 	}
828 
829 	set_perm(fileno(fp));
830 
831 	total_len = sizeof (UINT32) + sizeof (CK_BBOOL) + ciphertxt_len;
832 
833 	flag = TRUE;
834 
835 	(void) fwrite(&total_len, sizeof (UINT32), 1, fp);
836 	(void) fwrite(&flag, sizeof (CK_BBOOL), 1, fp);
837 	(void) fwrite(ciphertxt, ciphertxt_len,    1, fp);
838 
839 	(void) lockfile(fileno(fp), F_UNLCK);
840 	(void) fclose(fp);
841 
842 	free(obj_data);
843 	free(cleartxt);
844 	free(ciphertxt);
845 	return (CKR_OK);
846 
847 error:
848 	if (fp)
849 		(void) fclose(fp);
850 	if (obj_data)
851 		free(obj_data);
852 	if (cleartxt)
853 		free(cleartxt);
854 	if (ciphertxt)
855 		free(ciphertxt);
856 
857 	return (rc);
858 }
859 
860 CK_RV
861 load_public_token_objects(void)
862 {
863 	FILE	*fp1 = NULL, *fp2 = NULL;
864 	CK_BYTE *buf = NULL;
865 	CK_BYTE tmp[MAXPATHLEN], fname[MAXPATHLEN], iname[MAXPATHLEN];
866 	CK_BBOOL priv;
867 	UINT32 size;
868 	char *ksdir = get_tpm_keystore_path();
869 
870 	if (ksdir == NULL)
871 		return (CKR_FUNCTION_FAILED);
872 
873 	(void) snprintf((char *)iname, sizeof (iname),
874 	    "%s/%s/%s", ksdir,
875 	    TOKEN_OBJ_DIR, TOKEN_OBJ_INDEX_FILE);
876 
877 	fp1 = fopen((char *)iname, "r");
878 	if (!fp1)
879 		return (CKR_OK);  // no token objects
880 
881 	if (lockfile(fileno(fp1), F_RDLCK)) {
882 		(void) fclose(fp1);
883 		return (CKR_FUNCTION_FAILED);
884 	}
885 
886 	while (!feof(fp1)) {
887 		(void) fgets((char *)tmp, 50, fp1);
888 		if (feof(fp1))
889 			break;
890 
891 		tmp[strlen((char *)tmp) - 1] = 0;
892 
893 		(void) snprintf((char *)fname, sizeof (fname),
894 		    "%s/%s/", ksdir, TOKEN_OBJ_DIR);
895 
896 		(void) strncat((char *)fname, (const char *)tmp,
897 		    (size_t)sizeof (fname));
898 
899 		fp2 = fopen((char *)fname, "r");
900 		if (!fp2)
901 			continue;
902 
903 		(void) fread(&size, sizeof (UINT32), 1, fp2);
904 		(void) fread(&priv, sizeof (CK_BBOOL), 1, fp2);
905 		if (priv == TRUE) {
906 			(void) fclose(fp2);
907 			continue;
908 		}
909 
910 		size = size - sizeof (UINT32) - sizeof (CK_BBOOL);
911 		buf = (CK_BYTE *)malloc(size);
912 		if (!buf) {
913 			(void) lockfile(fileno(fp1), F_UNLCK);
914 			(void) fclose(fp1);
915 			(void) fclose(fp2);
916 			return (CKR_HOST_MEMORY);
917 		}
918 
919 		(void) fread(buf, size, 1, fp2);
920 
921 		if (pthread_mutex_lock(&obj_list_mutex)) {
922 			(void) lockfile(fileno(fp1), F_UNLCK);
923 			(void) fclose(fp1);
924 			(void) fclose(fp2);
925 			free(buf);
926 			return (CKR_FUNCTION_FAILED);
927 		}
928 
929 		(void) object_mgr_restore_obj(buf, NULL);
930 
931 		(void) pthread_mutex_unlock(&obj_list_mutex);
932 		free(buf);
933 		(void) fclose(fp2);
934 	}
935 	(void) lockfile(fileno(fp1), F_UNLCK);
936 	(void) fclose(fp1);
937 
938 	return (CKR_OK);
939 }
940 
941 CK_RV
942 load_private_token_objects(TSS_HCONTEXT hContext)
943 {
944 	FILE *fp1 = NULL, *fp2 = NULL;
945 	CK_BYTE *buf = NULL;
946 	CK_BYTE tmp[MAXPATHLEN], fname[MAXPATHLEN], iname[MAXPATHLEN];
947 	CK_BBOOL priv;
948 	UINT32 size;
949 	CK_RV rc;
950 	char *ksdir = get_tpm_keystore_path();
951 
952 	if (ksdir == NULL)
953 		return (CKR_FUNCTION_FAILED);
954 
955 	(void) snprintf((char *)iname, sizeof (iname),
956 	    "%s/%s/%s", ksdir, TOKEN_OBJ_DIR, TOKEN_OBJ_INDEX_FILE);
957 
958 	fp1 = fopen((char *)iname, "r");
959 	if (!fp1)
960 		return (CKR_OK);
961 
962 	if (lockfile(fileno(fp1), F_RDLCK)) {
963 		rc = CKR_FUNCTION_FAILED;
964 		goto error;
965 	}
966 
967 	while (!feof(fp1)) {
968 		(void) fgets((char *)tmp, sizeof (tmp), fp1);
969 		if (feof(fp1))
970 			break;
971 
972 		tmp[strlen((char *)tmp) - 1] = 0;
973 
974 		(void) snprintf((char *)fname, sizeof (fname),
975 		    "%s/%s/%s", ksdir, TOKEN_OBJ_DIR, tmp);
976 
977 		fp2 = fopen((char *)fname, "r");
978 		if (!fp2)
979 			continue;
980 
981 		(void) fread(&size, sizeof (UINT32), 1, fp2);
982 		(void) fread(&priv, sizeof (CK_BBOOL), 1, fp2);
983 		if (priv == FALSE) {
984 			(void) fclose(fp2);
985 			continue;
986 		}
987 
988 		size = size - sizeof (UINT32) - sizeof (CK_BBOOL);
989 		buf = (CK_BYTE *)malloc(size);
990 		if (!buf) {
991 			rc = CKR_HOST_MEMORY;
992 			goto error;
993 		}
994 
995 		rc = fread((char *)buf, size, 1, fp2);
996 		if (rc != 1) {
997 			rc = CKR_FUNCTION_FAILED;
998 			goto error;
999 		}
1000 
1001 		if (pthread_mutex_lock(&obj_list_mutex)) {
1002 			rc = CKR_FUNCTION_FAILED;
1003 			goto error;
1004 		}
1005 		rc = restore_private_token_object(hContext, buf, size, NULL);
1006 		(void) pthread_mutex_unlock(&obj_list_mutex);
1007 		if (rc != CKR_OK)
1008 			goto error;
1009 
1010 		free(buf);
1011 		(void) fclose(fp2);
1012 	}
1013 	(void) lockfile(fileno(fp1), F_UNLCK);
1014 	(void) fclose(fp1);
1015 
1016 	return (CKR_OK);
1017 
1018 error:
1019 	if (buf)
1020 		free(buf);
1021 	if (fp1) {
1022 		(void) lockfile(fileno(fp1), F_UNLCK);
1023 		(void) fclose(fp1);
1024 	}
1025 	if (fp2)
1026 		(void) fclose(fp2);
1027 	return (rc);
1028 }
1029 
1030 static CK_RV
1031 restore_private_token_object(
1032 	TSS_HCONTEXT hContext,
1033 	CK_BYTE  *data,
1034 	CK_ULONG len,
1035 	OBJECT   *pObj)
1036 {
1037 	CK_BYTE * cleartxt  = NULL;
1038 	CK_BYTE * obj_data  = NULL;
1039 	CK_BYTE *ptr = NULL;
1040 	CK_BYTE hash_sha[SHA1_DIGEST_LENGTH];
1041 	CK_ULONG cleartxt_len, obj_data_len;
1042 	CK_RV rc;
1043 
1044 	/*
1045 	 * format for the object data:
1046 	 *    (private flag has already been read at this point)
1047 	 *    ---- begin encrypted part
1048 	 *	length of object data
1049 	 *	object data
1050 	 *	SHA of object data
1051 	 *    ---- end encrypted part
1052 	 */
1053 
1054 	cleartxt_len = len;
1055 
1056 	cleartxt = (CK_BYTE *)malloc(len);
1057 	if (!cleartxt) {
1058 		rc = CKR_HOST_MEMORY;
1059 		goto done;
1060 	}
1061 
1062 	rc = tpm_decrypt_data(hContext, hPrivateLeafKey, data, len,
1063 	    cleartxt, &len);
1064 
1065 	if (rc != CKR_OK) {
1066 		goto done;
1067 	}
1068 
1069 	(void) strip_pkcs_padding(cleartxt, len, &cleartxt_len);
1070 
1071 	if (cleartxt_len > len) {
1072 		rc = CKR_FUNCTION_FAILED;
1073 		goto done;
1074 	}
1075 
1076 	ptr = cleartxt;
1077 
1078 	bcopy(ptr, &obj_data_len, sizeof (CK_ULONG));
1079 	ptr += sizeof (CK_ULONG);
1080 	obj_data = ptr;
1081 
1082 	if ((rc = compute_sha(ptr, obj_data_len, hash_sha)) != CKR_OK)
1083 		goto done;
1084 	ptr += obj_data_len;
1085 
1086 	if (memcmp(ptr, hash_sha, SHA1_DIGEST_LENGTH) != 0) {
1087 		rc = CKR_FUNCTION_FAILED;
1088 		goto done;
1089 	}
1090 
1091 	(void) object_mgr_restore_obj(obj_data, pObj);
1092 	rc = CKR_OK;
1093 done:
1094 	if (cleartxt)
1095 		free(cleartxt);
1096 
1097 	return (rc);
1098 }
1099 
1100 CK_RV
1101 reload_token_object(TSS_HCONTEXT hContext, OBJECT *obj)
1102 {
1103 	FILE *fp = NULL;
1104 	CK_BYTE *buf = NULL;
1105 	CK_BYTE fname[MAXPATHLEN];
1106 	CK_BBOOL priv;
1107 	UINT32 size;
1108 	CK_RV rc;
1109 	char *p = get_tpm_keystore_path();
1110 
1111 	if (p == NULL)
1112 		return (CKR_FUNCTION_FAILED);
1113 
1114 	(void) memset((char *)fname, 0x0, sizeof (fname));
1115 
1116 	(void) snprintf((char *)fname, sizeof (fname),
1117 	    "%s/%s/", p, TOKEN_OBJ_DIR);
1118 
1119 	(void) strncat((char *)fname, (char *)obj->name, sizeof (fname));
1120 
1121 	fp = fopen((char *)fname, "r");
1122 	if (!fp) {
1123 		rc = CKR_FUNCTION_FAILED;
1124 		goto done;
1125 	}
1126 	if (lockfile(fileno(fp), F_RDLCK)) {
1127 		rc = CKR_FUNCTION_FAILED;
1128 		goto done;
1129 	}
1130 
1131 	set_perm(fileno(fp));
1132 
1133 	(void) fread(&size, sizeof (UINT32), 1, fp);
1134 	(void) fread(&priv, sizeof (CK_BBOOL), 1, fp);
1135 
1136 	size = size - sizeof (UINT32) - sizeof (CK_BBOOL);
1137 
1138 	buf = (CK_BYTE *)malloc(size);
1139 	if (!buf) {
1140 		rc = CKR_HOST_MEMORY;
1141 		goto done;
1142 	}
1143 
1144 	(void) fread(buf, size, 1, fp);
1145 
1146 	if (priv) {
1147 		rc = restore_private_token_object(hContext, buf, size, obj);
1148 	} else {
1149 		rc = object_mgr_restore_obj(buf, obj);
1150 	}
1151 
1152 done:
1153 	if (fp) {
1154 		(void) lockfile(fileno(fp), F_UNLCK);
1155 		(void) fclose(fp);
1156 	}
1157 	if (buf)
1158 		free(buf);
1159 	return (rc);
1160 }
1161 
1162 static int
1163 islink(char *fname)
1164 {
1165 	struct stat st;
1166 
1167 	if (stat((const char *)fname, &st))
1168 		return (-1);
1169 	else if (S_ISLNK(st.st_mode))
1170 		return (1);
1171 	return (0);
1172 }
1173 
1174 CK_RV
1175 delete_token_object(OBJECT *obj)
1176 {
1177 	FILE *fp1, *fp2;
1178 	CK_BYTE line[100];
1179 	char objidx[MAXPATHLEN], idxtmp[MAXPATHLEN], fname[MAXPATHLEN];
1180 	char *ksdir = get_tpm_keystore_path();
1181 
1182 	if (ksdir == NULL)
1183 		return (CKR_FUNCTION_FAILED);
1184 
1185 	(void) snprintf(objidx, sizeof (objidx),
1186 	    "%s/%s/%s", ksdir, TOKEN_OBJ_DIR, TOKEN_OBJ_INDEX_FILE);
1187 
1188 	(void) snprintf(idxtmp, sizeof (idxtmp),
1189 	    "%s/IDX.TMP", ksdir, TOKEN_OBJ_DIR);
1190 
1191 	/*
1192 	 * If either file is a link, fail.
1193 	 */
1194 	if (islink(objidx) != 0)
1195 		return (CKR_FUNCTION_FAILED);
1196 
1197 	if (islink(idxtmp) != 0)
1198 		return (CKR_FUNCTION_FAILED);
1199 
1200 	fp1 = fopen(objidx, "r");
1201 	fp2 = fopen(idxtmp, "w");
1202 	if (!fp1 || !fp2) {
1203 		if (fp1)
1204 			(void) fclose(fp1);
1205 		if (fp2)
1206 			(void) fclose(fp2);
1207 		return (CKR_FUNCTION_FAILED);
1208 	}
1209 
1210 	if (lockfile(fileno(fp1), F_RDLCK)) {
1211 		(void) fclose(fp1);
1212 		(void) fclose(fp2);
1213 		return (CKR_FUNCTION_FAILED);
1214 	}
1215 	if (lockfile(fileno(fp2), F_WRLCK)) {
1216 		(void) lockfile(fileno(fp1), F_UNLCK);
1217 		(void) fclose(fp1);
1218 		(void) fclose(fp2);
1219 		return (CKR_FUNCTION_FAILED);
1220 	}
1221 	set_perm(fileno(fp2));
1222 
1223 	while (!feof(fp1)) {
1224 		(void) fgets((char *)line, 50, fp1);
1225 		if (!feof(fp1)) {
1226 			line[ strlen((char *)line)-1 ] = 0;
1227 			if (strcmp((char *)line, (char *)obj->name))
1228 				(void) fprintf(fp2, "%s\n", line);
1229 		}
1230 	}
1231 
1232 	(void) lockfile(fileno(fp1), F_UNLCK);
1233 	(void) lockfile(fileno(fp2), F_UNLCK);
1234 	(void) fclose(fp1);
1235 	(void) fclose(fp2);
1236 
1237 	fp2 = fopen(objidx, "w");
1238 	fp1 = fopen(idxtmp, "r");
1239 	if (!fp1 || !fp2) {
1240 		if (fp1)
1241 			(void) fclose(fp1);
1242 		if (fp2)
1243 			(void) fclose(fp2);
1244 		return (CKR_FUNCTION_FAILED);
1245 	}
1246 	if (lockfile(fileno(fp1), F_RDLCK)) {
1247 		(void) fclose(fp1);
1248 		(void) fclose(fp2);
1249 		return (CKR_FUNCTION_FAILED);
1250 	}
1251 	if (lockfile(fileno(fp2), F_WRLCK)) {
1252 		(void) lockfile(fileno(fp1), F_UNLCK);
1253 		(void) fclose(fp1);
1254 		(void) fclose(fp2);
1255 		return (CKR_FUNCTION_FAILED);
1256 	}
1257 
1258 	set_perm(fileno(fp2));
1259 
1260 	while (!feof(fp1)) {
1261 		(void) fgets((char *)line, 50, fp1);
1262 		if (!feof(fp1))
1263 			(void) fprintf(fp2, "%s", (char *)line);
1264 	}
1265 
1266 	(void) lockfile(fileno(fp1), F_UNLCK);
1267 	(void) lockfile(fileno(fp2), F_UNLCK);
1268 	(void) fclose(fp1);
1269 	(void) fclose(fp2);
1270 
1271 	(void) snprintf(fname, sizeof (fname),
1272 	    "%s/%s/%s", ksdir, TOKEN_OBJ_DIR, (char *)obj->name);
1273 
1274 	(void) unlink(fname);
1275 	return (CKR_OK);
1276 }
1277