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