xref: /illumos-gate/usr/src/lib/pkcs11/pkcs11_tpm/common/loadsave.c (revision 7a088f03b431bdffa96c3b2175964d4d38420caa)
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 CK_RV
419 load_token_data(TSS_HCONTEXT hContext, TOKEN_DATA *td)
420 {
421 	FILE	*fp;
422 	CK_BYTE	fname[MAXPATHLEN];
423 	CK_RV	rc;
424 	char *p = get_tpm_keystore_path();
425 
426 	if (p == NULL)
427 		return (CKR_FUNCTION_FAILED);
428 
429 	(void) snprintf((char *)fname, sizeof (fname),
430 	    "%s/%s", p, TOKEN_DATA_FILE);
431 
432 	rc = XProcLock(xproclock);
433 	if (rc != CKR_OK)
434 		return (rc);
435 
436 	fp = fopen((char *)fname, "r");
437 	if (!fp) {
438 		/* Better error checking added */
439 		if (errno == ENOENT) {
440 			(void) XProcUnLock(xproclock);
441 			rc = create_keystore_dir();
442 			if (rc != 0)
443 				goto out_nolock;
444 
445 			rc = init_token_data(hContext, td);
446 			if (rc != CKR_OK) {
447 				goto out_nolock;
448 			}
449 
450 			rc = XProcLock(xproclock);
451 			if (rc != CKR_OK) {
452 				goto out_nolock;
453 			}
454 
455 			fp = fopen((char *)fname, "r");
456 			if (!fp) {
457 				LogError("failed opening %s for read: %s",
458 				    fname, (char *)strerror(errno));
459 				rc = CKR_FUNCTION_FAILED;
460 				goto out_unlock;
461 			}
462 		} else {
463 			/* Could not open file for some unknown reason */
464 			rc = CKR_FUNCTION_FAILED;
465 			goto out_unlock;
466 		}
467 	}
468 	if (lockfile(fileno(fp), F_RDLCK)) {
469 		(void) fclose(fp);
470 		rc = CKR_FUNCTION_FAILED;
471 		goto out_unlock;
472 	}
473 	set_perm(fileno(fp));
474 
475 	rc = fread(td, sizeof (TOKEN_DATA), 1, fp);
476 
477 	(void) lockfile(fileno(fp), F_UNLCK);
478 	(void) fclose(fp);
479 
480 	if (rc == 0)
481 		rc = CKR_FUNCTION_FAILED;
482 	else
483 		rc = CKR_OK;
484 
485 out_unlock:
486 	(void) XProcUnLock(xproclock);
487 
488 out_nolock:
489 	return (rc);
490 }
491 
492 CK_RV
493 save_token_data(TOKEN_DATA *td)
494 {
495 	FILE	*fp;
496 	CK_RV	rc;
497 	CK_BYTE	fname[MAXPATHLEN];
498 	char *p = get_tpm_keystore_path();
499 
500 	if (p == NULL)
501 		return (CKR_FUNCTION_FAILED);
502 
503 	(void) snprintf((char *)fname, sizeof (fname),
504 	    "%s/%s", p, TOKEN_DATA_FILE);
505 
506 	rc = XProcLock(xproclock);
507 	if (rc != CKR_OK)
508 		goto out_nolock;
509 
510 	fp = fopen((char *)fname, "w");
511 
512 	if (!fp) {
513 		rc = CKR_FUNCTION_FAILED;
514 		goto done;
515 	}
516 	if (lockfile(fileno(fp), F_WRLCK)) {
517 		rc = CKR_FUNCTION_FAILED;
518 		(void) fclose(fp);
519 		goto done;
520 	}
521 	set_perm(fileno(fp));
522 
523 	(void) fwrite(td, sizeof (TOKEN_DATA), 1, fp);
524 	(void) lockfile(fileno(fp), F_UNLCK);
525 	(void) fclose(fp);
526 
527 	rc = CKR_OK;
528 done:
529 	(void) XProcUnLock(xproclock);
530 
531 out_nolock:
532 	return (rc);
533 }
534 
535 CK_RV
536 save_token_object(TSS_HCONTEXT hContext, OBJECT *obj)
537 {
538 	FILE	*fp = NULL;
539 	CK_BYTE	line[100];
540 	CK_RV	rc;
541 	CK_BYTE	fname[MAXPATHLEN];
542 	char *p = get_tpm_keystore_path();
543 
544 	if (p == NULL)
545 		return (CKR_FUNCTION_FAILED);
546 
547 	if (object_is_private(obj) == TRUE)
548 		rc = save_private_token_object(hContext, obj);
549 	else
550 		rc = save_public_token_object(obj);
551 
552 	if (rc != CKR_OK)
553 		return (rc);
554 
555 	(void) snprintf((char *)fname, sizeof (fname),
556 	    "%s/%s/%s", p, TOKEN_OBJ_DIR, TOKEN_OBJ_INDEX_FILE);
557 
558 	fp = fopen((char *)fname, "r");
559 	if (fp) {
560 		if (lockfile(fileno(fp), F_RDLCK)) {
561 			(void) fclose(fp);
562 			return (CKR_FUNCTION_FAILED);
563 		}
564 		set_perm(fileno(fp));
565 		while (!feof(fp)) {
566 			(void) fgets((char *)line, 50, fp);
567 			if (!feof(fp)) {
568 				line[strlen((char *)line) - 1] = 0;
569 				if (strcmp((char *)line,
570 				    (char *)(obj->name)) == 0) {
571 					(void) lockfile(fileno(fp), F_UNLCK);
572 					(void) fclose(fp);
573 					return (CKR_OK);
574 				}
575 			}
576 		}
577 		(void) lockfile(fileno(fp), F_UNLCK);
578 		(void) fclose(fp);
579 	}
580 
581 	fp = fopen((char *)fname, "a");
582 	if (!fp)
583 		return (CKR_FUNCTION_FAILED);
584 
585 	if (lockfile(fileno(fp), F_WRLCK)) {
586 		(void) fclose(fp);
587 		return (CKR_FUNCTION_FAILED);
588 	}
589 	set_perm(fileno(fp));
590 
591 	(void) fprintf(fp, "%s\n", obj->name);
592 	(void) lockfile(fileno(fp), F_UNLCK);
593 	(void) fclose(fp);
594 
595 	return (CKR_OK);
596 }
597 
598 CK_RV
599 save_public_token_object(OBJECT *obj)
600 {
601 	FILE	*fp = NULL;
602 	CK_BYTE	*cleartxt = NULL;
603 	CK_BYTE	fname[MAXPATHLEN];
604 	CK_ULONG	cleartxt_len;
605 	CK_BBOOL	flag = FALSE;
606 	CK_RV	rc;
607 	CK_ULONG	total_len;
608 	char *p = get_tpm_keystore_path();
609 
610 	if (p == NULL)
611 		return (CKR_FUNCTION_FAILED);
612 
613 	(void) snprintf((char *)fname, sizeof (fname),
614 	    "%s/%s/%s", p, TOKEN_OBJ_DIR, obj->name);
615 
616 	rc = object_flatten(obj, &cleartxt, &cleartxt_len);
617 	if (rc != CKR_OK)
618 		goto error;
619 
620 	fp = fopen((char *)fname, "w");
621 	if (!fp) {
622 		LogError("Error opening %s - %s", fname,
623 		    (char *)strerror(errno));
624 		rc = CKR_FUNCTION_FAILED;
625 		goto error;
626 	}
627 	if (lockfile(fileno(fp), F_WRLCK)) {
628 		(void) fclose(fp);
629 		return (CKR_FUNCTION_FAILED);
630 	}
631 
632 	set_perm(fileno(fp));
633 
634 	total_len = cleartxt_len + sizeof (CK_ULONG) + sizeof (CK_BBOOL);
635 
636 	(void) fwrite(&total_len, sizeof (CK_ULONG), 1, fp);
637 	(void) fwrite(&flag, sizeof (CK_BBOOL), 1, fp);
638 	(void) fwrite(cleartxt, cleartxt_len, 1, fp);
639 
640 	(void) lockfile(fileno(fp), F_UNLCK);
641 	(void) fclose(fp);
642 	free(cleartxt);
643 
644 	return (CKR_OK);
645 
646 error:
647 	if (fp)
648 		(void) fclose(fp);
649 	if (cleartxt)
650 		free(cleartxt);
651 	return (rc);
652 }
653 
654 CK_RV
655 save_private_token_object(TSS_HCONTEXT hContext, OBJECT *obj)
656 {
657 	FILE *fp = NULL;
658 	CK_BYTE	*obj_data  = NULL;
659 	CK_BYTE	*cleartxt  = NULL;
660 	CK_BYTE	*ciphertxt = NULL;
661 	CK_BYTE	*ptr = NULL;
662 	CK_BYTE	fname[100];
663 	CK_BYTE	hash_sha[SHA1_DIGEST_LENGTH];
664 	CK_ULONG obj_data_len, cleartxt_len, ciphertxt_len;
665 	CK_ULONG	padded_len;
666 	CK_BBOOL	flag;
667 	CK_RV	rc;
668 	CK_ULONG	obj_data_len_32;
669 	CK_ULONG	total_len;
670 	CK_ULONG	chunksize, blocks;
671 	char 		*p = get_tpm_keystore_path();
672 
673 	if (p == NULL)
674 		return (CKR_FUNCTION_FAILED);
675 
676 	rc = object_flatten(obj, &obj_data, &obj_data_len);
677 	obj_data_len_32 = obj_data_len;
678 	if (rc != CKR_OK) {
679 		goto error;
680 	}
681 	/*
682 	 * format for the object file:
683 	 *    private flag
684 	 *	---- begin encrypted part	<--+
685 	 *	length of object data		|
686 	 *	object data			+---- sensitive part
687 	 *	SHA of (object data)		|
688 	 *	---- end encrypted part		<--+
689 	 */
690 	if ((rc = compute_sha(obj_data, obj_data_len, hash_sha)) != CKR_OK)
691 		goto error;
692 
693 	/*
694 	 * RSA OAEP crypto uses chunks smaller than the max to make room
695 	 * for the hashes.
696 	 * chunksize = RSA_Modulus_Size - (2 * SHA1_DIGEST_SIZE + 2) - (4 - 1)
697 	 * == 209
698 	 */
699 	chunksize = RSA_BLOCK_SIZE - (2 * SHA1_DIGEST_LENGTH + 2) - 5;
700 
701 	cleartxt_len = sizeof (CK_ULONG) + obj_data_len_32 + SHA1_DIGEST_LENGTH;
702 
703 	blocks = cleartxt_len / chunksize + ((cleartxt_len % chunksize) > 0);
704 	padded_len   = RSA_BLOCK_SIZE * blocks;
705 
706 	cleartxt  = (CK_BYTE *)malloc(padded_len);
707 	ciphertxt = (CK_BYTE *)malloc(padded_len);
708 	if (!cleartxt || !ciphertxt) {
709 		rc = CKR_HOST_MEMORY;
710 		goto error;
711 	}
712 
713 	ciphertxt_len = padded_len;
714 
715 	ptr = cleartxt;
716 	(void) memcpy(ptr, &obj_data_len_32, sizeof (CK_ULONG));
717 	ptr += sizeof (CK_ULONG);
718 	(void) memcpy(ptr,  obj_data, obj_data_len_32);
719 	ptr += obj_data_len_32;
720 	(void) memcpy(ptr, hash_sha, SHA1_DIGEST_LENGTH);
721 
722 	(void) add_pkcs_padding(cleartxt + cleartxt_len, RSA_BLOCK_SIZE,
723 	    cleartxt_len, padded_len);
724 
725 	/* the encrypt function will compute the padded length */
726 	rc = tpm_encrypt_data(hContext, hPrivateLeafKey, cleartxt, cleartxt_len,
727 	    ciphertxt, &ciphertxt_len);
728 
729 	if (rc != CKR_OK) {
730 		goto error;
731 	}
732 
733 	(void) snprintf((char *)fname, sizeof (fname),
734 	    "%s/%s/%s", p, TOKEN_OBJ_DIR, obj->name);
735 
736 	fp = fopen((char *)fname, "w");
737 	if (!fp) {
738 		rc = CKR_FUNCTION_FAILED;
739 		goto error;
740 	}
741 	if (lockfile(fileno(fp), F_WRLCK)) {
742 		rc = CKR_FUNCTION_FAILED;
743 		goto error;
744 	}
745 
746 	set_perm(fileno(fp));
747 
748 	total_len = sizeof (CK_ULONG) + sizeof (CK_BBOOL) + ciphertxt_len;
749 
750 	flag = TRUE;
751 
752 	(void) fwrite(&total_len, sizeof (CK_ULONG), 1, fp);
753 	(void) fwrite(&flag, sizeof (CK_BBOOL), 1, fp);
754 	(void) fwrite(ciphertxt, ciphertxt_len,    1, fp);
755 
756 	(void) lockfile(fileno(fp), F_UNLCK);
757 	(void) fclose(fp);
758 
759 	free(obj_data);
760 	free(cleartxt);
761 	free(ciphertxt);
762 	return (CKR_OK);
763 
764 error:
765 	if (fp)
766 		(void) fclose(fp);
767 	if (obj_data)
768 		free(obj_data);
769 	if (cleartxt)
770 		free(cleartxt);
771 	if (ciphertxt)
772 		free(ciphertxt);
773 
774 	return (rc);
775 }
776 
777 CK_RV
778 load_public_token_objects(void)
779 {
780 	FILE	*fp1 = NULL, *fp2 = NULL;
781 	CK_BYTE *buf = NULL;
782 	CK_BYTE tmp[MAXPATHLEN], fname[MAXPATHLEN], iname[MAXPATHLEN];
783 	CK_BBOOL priv;
784 	CK_ULONG size;
785 	char *ksdir = get_tpm_keystore_path();
786 
787 	if (ksdir == NULL)
788 		return (CKR_FUNCTION_FAILED);
789 
790 	(void) snprintf((char *)iname, sizeof (iname),
791 	    "%s/%s/%s", ksdir,
792 	    TOKEN_OBJ_DIR, TOKEN_OBJ_INDEX_FILE);
793 
794 	fp1 = fopen((char *)iname, "r");
795 	if (!fp1)
796 		return (CKR_OK);  // no token objects
797 
798 	if (lockfile(fileno(fp1), F_RDLCK)) {
799 		(void) fclose(fp1);
800 		return (CKR_FUNCTION_FAILED);
801 	}
802 
803 	while (!feof(fp1)) {
804 		(void) fgets((char *)tmp, 50, fp1);
805 		if (feof(fp1))
806 			break;
807 
808 		tmp[strlen((char *)tmp) - 1] = 0;
809 
810 		(void) snprintf((char *)fname, sizeof (fname),
811 		    "%s/%s/", ksdir, TOKEN_OBJ_DIR);
812 
813 		(void) strncat((char *)fname, (const char *)tmp,
814 		    (size_t)sizeof (fname));
815 
816 		fp2 = fopen((char *)fname, "r");
817 		if (!fp2)
818 			continue;
819 
820 		(void) fread(&size, sizeof (CK_ULONG), 1, fp2);
821 		(void) fread(&priv, sizeof (CK_BBOOL), 1, fp2);
822 		if (priv == TRUE) {
823 			(void) fclose(fp2);
824 			continue;
825 		}
826 
827 		size = size - sizeof (CK_ULONG) - sizeof (CK_BBOOL);
828 		buf = (CK_BYTE *)malloc(size);
829 		if (!buf) {
830 			(void) lockfile(fileno(fp1), F_UNLCK);
831 			(void) fclose(fp1);
832 			(void) fclose(fp2);
833 			return (CKR_HOST_MEMORY);
834 		}
835 
836 		(void) fread(buf, size, 1, fp2);
837 
838 		if (pthread_mutex_lock(&obj_list_mutex)) {
839 			(void) lockfile(fileno(fp1), F_UNLCK);
840 			(void) fclose(fp1);
841 			(void) fclose(fp2);
842 			free(buf);
843 			return (CKR_FUNCTION_FAILED);
844 		}
845 
846 		(void) object_mgr_restore_obj(buf, NULL);
847 
848 		(void) pthread_mutex_unlock(&obj_list_mutex);
849 		free(buf);
850 		(void) fclose(fp2);
851 	}
852 	(void) lockfile(fileno(fp1), F_UNLCK);
853 	(void) fclose(fp1);
854 
855 	return (CKR_OK);
856 }
857 
858 CK_RV
859 load_private_token_objects(TSS_HCONTEXT hContext)
860 {
861 	FILE *fp1 = NULL, *fp2 = NULL;
862 	CK_BYTE *buf = NULL;
863 	CK_BYTE tmp[MAXPATHLEN], fname[MAXPATHLEN], iname[MAXPATHLEN];
864 	CK_BBOOL priv;
865 	CK_ULONG size;
866 	CK_RV rc;
867 	char *ksdir = get_tpm_keystore_path();
868 
869 	if (ksdir == NULL)
870 		return (CKR_FUNCTION_FAILED);
871 
872 	(void) snprintf((char *)iname, sizeof (iname),
873 	    "%s/%s/%s", ksdir, TOKEN_OBJ_DIR, TOKEN_OBJ_INDEX_FILE);
874 
875 	fp1 = fopen((char *)iname, "r");
876 	if (!fp1)
877 		return (CKR_OK);
878 
879 	if (lockfile(fileno(fp1), F_RDLCK)) {
880 		rc = CKR_FUNCTION_FAILED;
881 		goto error;
882 	}
883 
884 	while (!feof(fp1)) {
885 		(void) fgets((char *)tmp, sizeof (tmp), fp1);
886 		if (feof(fp1))
887 			break;
888 
889 		tmp[strlen((char *)tmp) - 1] = 0;
890 
891 		(void) snprintf((char *)fname, sizeof (fname),
892 		    "%s/%s/%s", ksdir, TOKEN_OBJ_DIR, tmp);
893 
894 		fp2 = fopen((char *)fname, "r");
895 		if (!fp2)
896 			continue;
897 
898 		(void) fread(&size, sizeof (CK_ULONG), 1, fp2);
899 		(void) fread(&priv, sizeof (CK_BBOOL), 1, fp2);
900 		if (priv == FALSE) {
901 			(void) fclose(fp2);
902 			continue;
903 		}
904 
905 		size = size - sizeof (CK_ULONG) - sizeof (CK_BBOOL);
906 		buf = (CK_BYTE *)malloc(size);
907 		if (!buf) {
908 			rc = CKR_HOST_MEMORY;
909 			goto error;
910 		}
911 
912 		rc = fread((char *)buf, size, 1, fp2);
913 		if (rc != 1) {
914 			rc = CKR_FUNCTION_FAILED;
915 			goto error;
916 		}
917 
918 		if (pthread_mutex_lock(&obj_list_mutex)) {
919 			rc = CKR_FUNCTION_FAILED;
920 			goto error;
921 		}
922 		rc = restore_private_token_object(hContext, buf, size, NULL);
923 		(void) pthread_mutex_unlock(&obj_list_mutex);
924 		if (rc != CKR_OK)
925 			goto error;
926 
927 		free(buf);
928 		(void) fclose(fp2);
929 	}
930 	(void) lockfile(fileno(fp1), F_UNLCK);
931 	(void) fclose(fp1);
932 
933 	return (CKR_OK);
934 
935 error:
936 	if (buf)
937 		free(buf);
938 	if (fp1) {
939 		(void) lockfile(fileno(fp1), F_UNLCK);
940 		(void) fclose(fp1);
941 	}
942 	if (fp2)
943 		(void) fclose(fp2);
944 	return (rc);
945 }
946 
947 static CK_RV
948 restore_private_token_object(
949 	TSS_HCONTEXT hContext,
950 	CK_BYTE  *data,
951 	CK_ULONG len,
952 	OBJECT   *pObj)
953 {
954 	CK_BYTE * cleartxt  = NULL;
955 	CK_BYTE * obj_data  = NULL;
956 	CK_BYTE *ptr = NULL;
957 	CK_BYTE hash_sha[SHA1_DIGEST_LENGTH];
958 	CK_ULONG cleartxt_len, obj_data_len;
959 	CK_RV rc;
960 
961 	/*
962 	 * format for the object data:
963 	 *    (private flag has already been read at this point)
964 	 *    ---- begin encrypted part
965 	 *	length of object data
966 	 *	object data
967 	 *	SHA of object data
968 	 *    ---- end encrypted part
969 	 */
970 
971 	cleartxt_len = len;
972 
973 	cleartxt = (CK_BYTE *)malloc(len);
974 	if (!cleartxt) {
975 		rc = CKR_HOST_MEMORY;
976 		goto done;
977 	}
978 
979 	rc = tpm_decrypt_data(hContext, hPrivateLeafKey, data, len,
980 	    cleartxt, &len);
981 
982 	if (rc != CKR_OK) {
983 		goto done;
984 	}
985 
986 	(void) strip_pkcs_padding(cleartxt, len, &cleartxt_len);
987 
988 	if (cleartxt_len > len) {
989 		rc = CKR_FUNCTION_FAILED;
990 		goto done;
991 	}
992 
993 	ptr = cleartxt;
994 
995 	bcopy(ptr, &obj_data_len, sizeof (CK_ULONG));
996 	ptr += sizeof (CK_ULONG);
997 	obj_data = ptr;
998 
999 	if ((rc = compute_sha(ptr, obj_data_len, hash_sha)) != CKR_OK)
1000 		goto done;
1001 	ptr += obj_data_len;
1002 
1003 	if (memcmp(ptr, hash_sha, SHA1_DIGEST_LENGTH) != 0) {
1004 		rc = CKR_FUNCTION_FAILED;
1005 		goto done;
1006 	}
1007 
1008 	(void) object_mgr_restore_obj(obj_data, pObj);
1009 	rc = CKR_OK;
1010 done:
1011 	if (cleartxt)
1012 		free(cleartxt);
1013 
1014 	return (rc);
1015 }
1016 
1017 CK_RV
1018 reload_token_object(TSS_HCONTEXT hContext, OBJECT *obj)
1019 {
1020 	FILE *fp = NULL;
1021 	CK_BYTE *buf = NULL;
1022 	CK_BYTE fname[MAXPATHLEN];
1023 	CK_BBOOL priv;
1024 	CK_ULONG size;
1025 	CK_ULONG size_64;
1026 	CK_RV rc;
1027 	char *p = get_tpm_keystore_path();
1028 
1029 	if (p == NULL)
1030 		return (CKR_FUNCTION_FAILED);
1031 
1032 	(void) memset((char *)fname, 0x0, sizeof (fname));
1033 
1034 	(void) snprintf((char *)fname, sizeof (fname),
1035 	    "%s/%s/", p, TOKEN_OBJ_DIR);
1036 
1037 	(void) strncat((char *)fname, (char *)obj->name, sizeof (fname));
1038 
1039 	fp = fopen((char *)fname, "r");
1040 	if (!fp) {
1041 		rc = CKR_FUNCTION_FAILED;
1042 		goto done;
1043 	}
1044 	if (lockfile(fileno(fp), F_RDLCK)) {
1045 		rc = CKR_FUNCTION_FAILED;
1046 		goto done;
1047 	}
1048 
1049 	set_perm(fileno(fp));
1050 
1051 	(void) fread(&size, sizeof (CK_ULONG), 1, fp);
1052 	(void) fread(&priv, sizeof (CK_BBOOL), 1, fp);
1053 
1054 	size = size - sizeof (CK_ULONG) - sizeof (CK_BBOOL);
1055 
1056 	buf = (CK_BYTE *)malloc(size);
1057 	if (!buf) {
1058 		rc = CKR_HOST_MEMORY;
1059 		goto done;
1060 	}
1061 
1062 	(void) fread(buf, size, 1, fp);
1063 
1064 	size_64 = size;
1065 
1066 	if (priv) {
1067 		rc = restore_private_token_object(hContext, buf, size_64, obj);
1068 	} else {
1069 		rc = object_mgr_restore_obj(buf, obj);
1070 	}
1071 
1072 done:
1073 	if (fp) {
1074 		(void) lockfile(fileno(fp), F_UNLCK);
1075 		(void) fclose(fp);
1076 	}
1077 	if (buf)
1078 		free(buf);
1079 	return (rc);
1080 }
1081 
1082 static int
1083 islink(char *fname)
1084 {
1085 	struct stat st;
1086 
1087 	if (stat((const char *)fname, &st))
1088 		return (-1);
1089 	else if (S_ISLNK(st.st_mode))
1090 		return (1);
1091 	return (0);
1092 }
1093 
1094 CK_RV
1095 delete_token_object(OBJECT *obj)
1096 {
1097 	FILE *fp1, *fp2;
1098 	CK_BYTE line[100];
1099 	char objidx[MAXPATHLEN], idxtmp[MAXPATHLEN], fname[MAXPATHLEN];
1100 	char *ksdir = get_tpm_keystore_path();
1101 
1102 	if (ksdir == NULL)
1103 		return (CKR_FUNCTION_FAILED);
1104 
1105 	(void) snprintf(objidx, sizeof (objidx),
1106 	    "%s/%s/%s", ksdir, TOKEN_OBJ_DIR, TOKEN_OBJ_INDEX_FILE);
1107 
1108 	(void) snprintf(idxtmp, sizeof (idxtmp),
1109 	    "%s/IDX.TMP", ksdir, TOKEN_OBJ_DIR);
1110 
1111 	/*
1112 	 * If either file is a link, fail.
1113 	 */
1114 	if (islink(objidx) != 0)
1115 		return (CKR_FUNCTION_FAILED);
1116 
1117 	if (islink(idxtmp) != 0)
1118 		return (CKR_FUNCTION_FAILED);
1119 
1120 	fp1 = fopen(objidx, "r");
1121 	fp2 = fopen(idxtmp, "w");
1122 	if (!fp1 || !fp2) {
1123 		if (fp1)
1124 			(void) fclose(fp1);
1125 		if (fp2)
1126 			(void) fclose(fp2);
1127 		return (CKR_FUNCTION_FAILED);
1128 	}
1129 
1130 	if (lockfile(fileno(fp1), F_RDLCK)) {
1131 		(void) fclose(fp1);
1132 		(void) fclose(fp2);
1133 		return (CKR_FUNCTION_FAILED);
1134 	}
1135 	if (lockfile(fileno(fp2), F_WRLCK)) {
1136 		(void) lockfile(fileno(fp1), F_UNLCK);
1137 		(void) fclose(fp1);
1138 		(void) fclose(fp2);
1139 		return (CKR_FUNCTION_FAILED);
1140 	}
1141 	set_perm(fileno(fp2));
1142 
1143 	while (!feof(fp1)) {
1144 		(void) fgets((char *)line, 50, fp1);
1145 		if (!feof(fp1)) {
1146 			line[ strlen((char *)line)-1 ] = 0;
1147 			if (strcmp((char *)line, (char *)obj->name))
1148 				(void) fprintf(fp2, "%s\n", line);
1149 		}
1150 	}
1151 
1152 	(void) lockfile(fileno(fp1), F_UNLCK);
1153 	(void) lockfile(fileno(fp2), F_UNLCK);
1154 	(void) fclose(fp1);
1155 	(void) fclose(fp2);
1156 
1157 	fp2 = fopen(objidx, "w");
1158 	fp1 = fopen(idxtmp, "r");
1159 	if (!fp1 || !fp2) {
1160 		if (fp1)
1161 			(void) fclose(fp1);
1162 		if (fp2)
1163 			(void) fclose(fp2);
1164 		return (CKR_FUNCTION_FAILED);
1165 	}
1166 	if (lockfile(fileno(fp1), F_RDLCK)) {
1167 		(void) fclose(fp1);
1168 		(void) fclose(fp2);
1169 		return (CKR_FUNCTION_FAILED);
1170 	}
1171 	if (lockfile(fileno(fp2), F_WRLCK)) {
1172 		(void) lockfile(fileno(fp1), F_UNLCK);
1173 		(void) fclose(fp1);
1174 		(void) fclose(fp2);
1175 		return (CKR_FUNCTION_FAILED);
1176 	}
1177 
1178 	set_perm(fileno(fp2));
1179 
1180 	while (!feof(fp1)) {
1181 		(void) fgets((char *)line, 50, fp1);
1182 		if (!feof(fp1))
1183 			(void) fprintf(fp2, "%s", (char *)line);
1184 	}
1185 
1186 	(void) lockfile(fileno(fp1), F_UNLCK);
1187 	(void) lockfile(fileno(fp2), F_UNLCK);
1188 	(void) fclose(fp1);
1189 	(void) fclose(fp2);
1190 
1191 	(void) snprintf(fname, sizeof (fname),
1192 	    "%s/%s/%s", ksdir, TOKEN_OBJ_DIR, (char *)obj->name);
1193 
1194 	(void) unlink(fname);
1195 	return (CKR_OK);
1196 }
1197