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
302static char keystore_path[MAXPATHLEN];
303static boolean_t keystore_path_initialized = 0;
304
305TSS_HKEY hPrivateLeafKey;
306static CK_RV
307restore_private_token_object(TSS_HCONTEXT, CK_BYTE  *, CK_ULONG, OBJECT *);
308
309static struct flock fl = {
310	0,
311	0,
312	0,
313	0,
314	0,
315	0,
316	{0, 0, 0, 0}
317};
318
319static int
320lockfile(int fd, int op)
321{
322	fl.l_type = op;
323	return (fcntl(fd, F_SETLKW, &fl));
324}
325
326static char *
327get_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
342char *
343get_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
375static CK_RV
376create_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
407static void
408set_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
426CK_RV
427load_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
526out_unlock:
527	(void) XProcUnLock(xproclock);
528
529out_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
541CK_RV
542save_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;
611done:
612	(void) XProcUnLock(xproclock);
613
614out_nolock:
615	return (rc);
616}
617
618CK_RV
619save_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
681CK_RV
682save_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
730error:
731	if (fp)
732		(void) fclose(fp);
733	if (cleartxt)
734		free(cleartxt);
735	return (rc);
736}
737
738CK_RV
739save_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
848error:
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
861CK_RV
862load_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
942CK_RV
943load_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
1019error:
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
1031static CK_RV
1032restore_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;
1096done:
1097	if (cleartxt)
1098		free(cleartxt);
1099
1100	return (rc);
1101}
1102
1103CK_RV
1104reload_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
1155done:
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
1165static int
1166islink(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
1177CK_RV
1178delete_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