1
2 /*
3 * Licensed Materials - Property of IBM
4 *
5 * trousers - An open source TCG Software Stack
6 *
7 * (C) Copyright International Business Machines Corp. 2004-2006
8 *
9 */
10
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <unistd.h>
16 #include <errno.h>
17 #include <pwd.h>
18 #include <sys/types.h>
19 #include <sys/file.h>
20 #include <sys/stat.h>
21 #include <assert.h>
22 #include <fcntl.h>
23 #include <limits.h>
24 #include <netdb.h>
25 #if defined (HAVE_BYTEORDER_H)
26 #include <sys/byteorder.h>
27 #elif defined(HTOLE_DEFINED)
28
29 #ifndef __APPLE__
30 #include <endian.h>
31 #else
32 #include "portable_endian.h"
33 #endif
34
35 #define LE_16 htole16
36 #define LE_32 htole32
37 #define LE_64 htole64
38 #elif defined(HAVE_SYS_ENDIAN_H) || defined(__DragonFly__)
39 #include <sys/endian.h>
40 #define LE_16 htole16
41 #define LE_32 htole32
42 #define LE_64 htole64
43 #else
44 #define LE_16(x) (x)
45 #define LE_32(x) (x)
46 #define LE_64(x) (x)
47 #endif
48
49 #include "trousers/tss.h"
50 #include "trousers/trousers.h"
51 #include "trousers_types.h"
52 #include "tcs_tsp.h"
53 #include "spi_utils.h"
54 #include "tspps.h"
55 #include "tsplog.h"
56
57
58 static int user_ps_fd = -1;
59 static MUTEX_DECLARE_INIT(user_ps_lock);
60 #if (defined (__FreeBSD__) || defined (__OpenBSD__) || defined(__DragonFly__))
61 #include <sys/endian.h>
62 #define LE_16 htole16
63 #define LE_32 htole32
64 static MUTEX_DECLARE_INIT(user_ps_path);
65 #endif
66 static struct flock fl;
67
68
69 /*
70 * Determine the default path to the persistent storage file and create it if it doesn't exist.
71 */
72 TSS_RESULT
get_user_ps_path(char ** file)73 get_user_ps_path(char **file)
74 {
75 TSS_RESULT result;
76 char *file_name = NULL, *home_dir = NULL;
77 struct passwd *pwp;
78 struct passwd pw;
79 struct stat stat_buf;
80 char buf[PASSWD_BUFSIZE];
81 uid_t euid;
82 int rc;
83
84 if ((file_name = getenv("TSS_USER_PS_FILE"))) {
85 *file = strdup(file_name);
86 return (*file) ? TSS_SUCCESS : TSPERR(TSS_E_OUTOFMEMORY);
87 }
88 euid = geteuid();
89
90 #if defined (SOLARIS)
91 /*
92 * Solaris keeps user PS in a local directory instead of
93 * in the user's home directory, which may be shared
94 * by multiple systems.
95 *
96 * The directory path on Solaris is /var/tpm/userps/[EUID]/
97 */
98 rc = snprintf(buf, sizeof (buf), "%s/%d", TSS_USER_PS_DIR, euid);
99 #else
100 rc = getpwuid_r(euid, &pw, buf, PASSWD_BUFSIZE, &pwp);
101 if (rc) {
102 LogDebugFn("USER PS: Error getting path to home directory: "
103 "getpwent_r: %s", strerror(rc));
104 return TSPERR(TSS_E_INTERNAL_ERROR);
105 }
106
107 home_dir = strdup(pwp->pw_dir);
108
109 if (!home_dir)
110 return TSPERR(TSS_E_OUTOFMEMORY);
111
112 /* Tack on TSS_USER_PS_DIR and see if it exists */
113 rc = snprintf(buf, sizeof (buf), "%s/%s", home_dir, TSS_USER_PS_DIR);
114 #endif /* SOLARIS */
115 if (rc == sizeof (buf)) {
116 LogDebugFn("USER PS: Path to file too long! (> %d bytes)", PASSWD_BUFSIZE);
117 result = TSPERR(TSS_E_INTERNAL_ERROR);
118 goto done;
119 }
120
121 errno = 0;
122 if ((rc = stat(buf, &stat_buf)) == -1) {
123 if (errno == ENOENT) {
124 errno = 0;
125 /* Create the user's ps directory if it is not there. */
126 if ((rc = mkdir(buf, 0700)) == -1) {
127 LogDebugFn("USER PS: Error creating dir: %s: %s", buf,
128 strerror(errno));
129 result = TSPERR(TSS_E_INTERNAL_ERROR);
130 goto done;
131 }
132 } else {
133 LogDebugFn("USER PS: Error stating dir: %s: %s", buf, strerror(errno));
134 result = TSPERR(TSS_E_INTERNAL_ERROR);
135 goto done;
136 }
137 }
138
139 /* Directory exists or has been created, return the path to the file */
140 #if defined (SOLARIS)
141 rc = snprintf(buf, sizeof (buf), "%s/%d/%s", TSS_USER_PS_DIR, euid,
142 TSS_USER_PS_FILE);
143 #else
144 rc = snprintf(buf, sizeof (buf), "%s/%s/%s", home_dir, TSS_USER_PS_DIR,
145 TSS_USER_PS_FILE);
146 #endif
147 if (rc == sizeof (buf)) {
148 LogDebugFn("USER PS: Path to file too long! (> %zd bytes)", sizeof (buf));
149 } else
150 *file = strdup(buf);
151
152 result = (*file) ? TSS_SUCCESS : TSPERR(TSS_E_OUTOFMEMORY);
153 done:
154 free(home_dir);
155 return result;
156 }
157
158 TSS_RESULT
get_file(int * fd)159 get_file(int *fd)
160 {
161 TSS_RESULT result;
162 int rc = 0;
163 char *file_name = NULL;
164
165 MUTEX_LOCK(user_ps_lock);
166
167 /* check the global file handle first. If it exists, lock it and return */
168 if (user_ps_fd != -1) {
169 fl.l_type = F_WRLCK;
170 if ((rc = fcntl(user_ps_fd, F_SETLKW, &fl))) {
171 LogDebug("USER PS: failed to lock file: %s", strerror(errno));
172 MUTEX_UNLOCK(user_ps_lock);
173 return TSPERR(TSS_E_INTERNAL_ERROR);
174 }
175 *fd = user_ps_fd;
176 return TSS_SUCCESS;
177 }
178
179 /* open and lock the file */
180 if ((result = get_user_ps_path(&file_name))) {
181 LogDebugFn("USER PS: error getting file path");
182 MUTEX_UNLOCK(user_ps_lock);
183 return result;
184 }
185
186 user_ps_fd = open(file_name, O_CREAT|O_RDWR, 0600);
187 if (user_ps_fd < 0) {
188 LogDebug("USER PS: open of %s failed: %s", file_name, strerror(errno));
189 free(file_name);
190 MUTEX_UNLOCK(user_ps_lock);
191 return TSPERR(TSS_E_INTERNAL_ERROR);
192 }
193 fl.l_type = F_WRLCK;
194 if ((rc = fcntl(user_ps_fd, F_SETLKW, &fl))) {
195 LogDebug("USER PS: failed to get lock of %s: %s", file_name, strerror(errno));
196 free(file_name);
197 close(user_ps_fd);
198 user_ps_fd = -1;
199 MUTEX_UNLOCK(user_ps_lock);
200 return TSPERR(TSS_E_INTERNAL_ERROR);
201 }
202
203 *fd = user_ps_fd;
204 free(file_name);
205 return TSS_SUCCESS;
206 }
207
208 int
put_file(int fd)209 put_file(int fd)
210 {
211 int rc = 0;
212
213 fsync(fd);
214
215 /* release the file lock */
216 fl.l_type = F_UNLCK;
217 if ((rc = fcntl(fd, F_SETLKW, &fl))) {
218 LogDebug("USER PS: failed to unlock file: %s", strerror(errno));
219 rc = -1;
220 }
221
222 MUTEX_UNLOCK(user_ps_lock);
223 return rc;
224 }
225
226 void
psfile_close(int fd)227 psfile_close(int fd)
228 {
229 close(fd);
230 user_ps_fd = -1;
231 MUTEX_UNLOCK(user_ps_lock);
232 }
233
234 TSS_RESULT
psfile_is_key_registered(int fd,TSS_UUID * uuid,TSS_BOOL * answer)235 psfile_is_key_registered(int fd, TSS_UUID *uuid, TSS_BOOL *answer)
236 {
237 TSS_RESULT result;
238 struct key_disk_cache tmp;
239
240 if ((result = psfile_get_cache_entry_by_uuid(fd, uuid, &tmp)) == TSS_SUCCESS)
241 *answer = TRUE;
242 else if (result == (TSS_E_PS_KEY_NOTFOUND | TSS_LAYER_TSP))
243 *answer = FALSE;
244 else
245 return result;
246
247 return TSS_SUCCESS;
248 }
249
250 TSS_RESULT
psfile_get_parent_uuid_by_uuid(int fd,TSS_UUID * uuid,TSS_UUID * ret_uuid)251 psfile_get_parent_uuid_by_uuid(int fd, TSS_UUID *uuid, TSS_UUID *ret_uuid)
252 {
253 TSS_RESULT result;
254 struct key_disk_cache tmp;
255
256 if ((result = psfile_get_cache_entry_by_uuid(fd, uuid, &tmp)))
257 return result;
258
259 memcpy(ret_uuid, &tmp.parent_uuid, sizeof(TSS_UUID));
260
261 return TSS_SUCCESS;
262 }
263
264 TSS_RESULT
psfile_get_parent_ps_type(int fd,TSS_UUID * uuid,UINT32 * type)265 psfile_get_parent_ps_type(int fd, TSS_UUID *uuid, UINT32 *type)
266 {
267 TSS_RESULT result;
268 struct key_disk_cache tmp;
269
270 if ((result = psfile_get_cache_entry_by_uuid(fd, uuid, &tmp)))
271 return result;
272
273 if (tmp.flags & CACHE_FLAG_PARENT_PS_SYSTEM)
274 *type = TSS_PS_TYPE_SYSTEM;
275 else
276 *type = TSS_PS_TYPE_USER;
277
278 return TSS_SUCCESS;
279 }
280
281 /*
282 * return a key struct from PS given a uuid
283 */
284 TSS_RESULT
psfile_get_key_by_uuid(int fd,TSS_UUID * uuid,BYTE * key)285 psfile_get_key_by_uuid(int fd, TSS_UUID *uuid, BYTE *key)
286 {
287 int rc;
288 TSS_RESULT result;
289 off_t file_offset;
290 struct key_disk_cache tmp;
291 BYTE buf[4096];
292
293 if ((result = psfile_get_cache_entry_by_uuid(fd, uuid, &tmp)))
294 return result;
295
296 /* jump to the location of the key blob */
297 file_offset = TSSPS_BLOB_DATA_OFFSET(&tmp);
298
299 rc = lseek(fd, file_offset, SEEK_SET);
300 if (rc == ((off_t)-1)) {
301 LogDebugFn("lseek: %s", strerror(errno));
302 return TSPERR(TSS_E_INTERNAL_ERROR);
303 }
304
305 if (tmp.blob_size > 4096) {
306 LogError("Blob size greater than 4096! Size: %d",
307 tmp.blob_size);
308 return TSPERR(TSS_E_INTERNAL_ERROR);
309 }
310 if ((rc = read_data(fd, buf, tmp.blob_size))) {
311 LogDebugFn("Blob read from disk failed.");
312 return rc;
313 }
314
315 memcpy(key, buf, tmp.blob_size);
316 return TSS_SUCCESS;
317 }
318
319 /*
320 * return a key struct from PS given a public key
321 */
322 TSS_RESULT
psfile_get_key_by_pub(int fd,TSS_UUID * uuid,UINT32 pub_size,BYTE * pub,BYTE * key)323 psfile_get_key_by_pub(int fd, TSS_UUID *uuid, UINT32 pub_size, BYTE *pub, BYTE *key)
324 {
325 int rc;
326 TSS_RESULT result;
327 off_t file_offset;
328 struct key_disk_cache tmp;
329 BYTE buf[4096];
330
331 if ((result = psfile_get_cache_entry_by_pub(fd, pub_size, pub, &tmp)))
332 return result;
333
334 /* jump to the location of the key blob */
335 file_offset = TSSPS_BLOB_DATA_OFFSET(&tmp);
336
337 rc = lseek(fd, file_offset, SEEK_SET);
338 if (rc == ((off_t)-1)) {
339 LogDebugFn("lseek: %s", strerror(errno));
340 return TSPERR(TSS_E_INTERNAL_ERROR);
341 }
342
343 if (tmp.blob_size > 4096) {
344 LogError("Blob size greater than 4096! Size: %d",
345 tmp.blob_size);
346 return TSPERR(TSS_E_INTERNAL_ERROR);
347 }
348
349 if ((result = read_data(fd, buf, tmp.blob_size))) {
350 LogDebugFn("Blob read from disk failed.");
351 return result;
352 }
353
354 memcpy(key, buf, tmp.blob_size);
355 memcpy(uuid, &tmp.uuid, sizeof(TSS_UUID));
356
357 return TSS_SUCCESS;
358 }
359
360 TSS_RESULT
psfile_get_uuid_by_pub(int fd,UINT32 pub_size,BYTE * pub,TSS_UUID * uuid)361 psfile_get_uuid_by_pub(int fd, UINT32 pub_size, BYTE *pub, TSS_UUID *uuid)
362 {
363 TSS_RESULT result;
364 struct key_disk_cache tmp;
365
366 if ((result = psfile_get_cache_entry_by_pub(fd, pub_size, pub, &tmp)))
367 return result;
368
369 memcpy(uuid, &tmp.uuid, sizeof(TSS_UUID));
370
371 return TSS_SUCCESS;
372 }
373
374 TSS_RESULT
psfile_change_num_keys(int fd,BYTE increment)375 psfile_change_num_keys(int fd, BYTE increment)
376 {
377 int rc;
378 TSS_RESULT result;
379 UINT32 num_keys;
380
381 rc = lseek(fd, TSSPS_NUM_KEYS_OFFSET, SEEK_SET);
382 if (rc == ((off_t)-1)) {
383 LogDebug("lseek: %s", strerror(errno));
384 return TSPERR(TSS_E_INTERNAL_ERROR);
385 }
386
387 rc = read(fd, &num_keys, sizeof(UINT32));
388 if (rc != sizeof(UINT32)) {
389 LogDebug("read of %zd bytes: %s", sizeof(UINT32), strerror(errno));
390 return TSPERR(TSS_E_INTERNAL_ERROR);
391 }
392 num_keys = LE_32(num_keys);
393
394 if (increment)
395 num_keys++;
396 else
397 num_keys--;
398
399 rc = lseek(fd, TSSPS_NUM_KEYS_OFFSET, SEEK_SET);
400 if (rc == ((off_t)-1)) {
401 LogDebug("lseek: %s", strerror(errno));
402 return TSPERR(TSS_E_INTERNAL_ERROR);
403 }
404
405 num_keys = LE_32(num_keys);
406 if ((result = write_data(fd, (void *)&num_keys, sizeof(UINT32)))) {
407 LogDebug("%s", __FUNCTION__);
408 return result;
409 }
410
411 return TSS_SUCCESS;
412 }
413
414 /* Write the initial header (number of keys and PS version) to initialize a new file */
415 TSS_RESULT
psfile_write_key_header(int fd)416 psfile_write_key_header(int fd)
417 {
418 int rc;
419 TSS_RESULT result;
420 UINT32 i;
421
422 rc = lseek(fd, TSSPS_VERSION_OFFSET, SEEK_SET);
423 if (rc == ((off_t)-1)) {
424 LogDebug("lseek: %s", strerror(errno));
425 return TSPERR(TSS_E_INTERNAL_ERROR);
426 }
427
428 i = TSSPS_VERSION;
429 if ((result = write_data(fd, &i, sizeof(BYTE)))) {
430 LogDebug("%s", __FUNCTION__);
431 return result;
432 }
433
434 rc = lseek(fd, TSSPS_NUM_KEYS_OFFSET, SEEK_SET);
435 if (rc == ((off_t)-1)) {
436 LogDebug("lseek: %s", strerror(errno));
437 return TSPERR(TSS_E_INTERNAL_ERROR);
438 }
439
440 i = 0;
441 if ((result = write_data(fd, &i, sizeof(UINT32)))) {
442 LogDebug("%s", __FUNCTION__);
443 return result;
444 }
445
446 return TSS_SUCCESS;
447 }
448
449 /*
450 * disk store format:
451 *
452 * TrouSerS 0.2.1+
453 * Version 1: cached?
454 * [BYTE PS version = '\1']
455 * [UINT32 num_keys_on_disk ]
456 * [TSS_UUID uuid0 ] yes
457 * [TSS_UUID uuid_parent0 ] yes
458 * [UINT16 pub_data_size0 ] yes
459 * [UINT16 blob_size0 ] yes
460 * [UINT32 vendor_data_size0] yes
461 * [UINT16 cache_flags0 ] yes
462 * [BYTE[] pub_data0 ]
463 * [BYTE[] blob0 ]
464 * [BYTE[] vendor_data0 ]
465 * [...]
466 *
467 */
468 TSS_RESULT
psfile_write_key(int fd,TSS_UUID * uuid,TSS_UUID * parent_uuid,UINT32 parent_ps,BYTE * key_blob,UINT16 key_blob_size)469 psfile_write_key(int fd,
470 TSS_UUID *uuid,
471 TSS_UUID *parent_uuid,
472 UINT32 parent_ps,
473 BYTE *key_blob,
474 UINT16 key_blob_size)
475 {
476 TSS_RESULT result;
477 TSS_KEY key;
478 UINT32 zero = 0;
479 UINT64 offset;
480 UINT16 pub_key_size, cache_flags = 0;
481 struct stat stat_buf;
482 int rc, file_offset;
483
484 /* leaving the cache flag for parent ps type as 0 implies TSS_PS_TYPE_USER */
485 if (parent_ps == TSS_PS_TYPE_SYSTEM)
486 cache_flags |= CACHE_FLAG_PARENT_PS_SYSTEM;
487
488 if ((rc = fstat(fd, &stat_buf)) == -1) {
489 LogDebugFn("stat failed: %s", strerror(errno));
490 return TSPERR(TSS_E_INTERNAL_ERROR);
491 }
492
493 file_offset = stat_buf.st_size;
494
495 if (file_offset < (int)TSSPS_KEYS_OFFSET) {
496 if ((result = psfile_write_key_header(fd)))
497 return result;
498 file_offset = TSSPS_KEYS_OFFSET;
499 }
500
501 rc = lseek(fd, file_offset, SEEK_SET);
502 if (rc == ((off_t)-1)) {
503 LogDebug("lseek: %s", strerror(errno));
504 return TSPERR(TSS_E_INTERNAL_ERROR);
505 }
506
507 /* Unload the blob to get the public key */
508 offset = 0;
509 if ((result = UnloadBlob_TSS_KEY(&offset, key_blob, &key)))
510 return result;
511
512 pub_key_size = key.pubKey.keyLength;
513
514 /* [TSS_UUID uuid0 ] yes */
515 if ((result = write_data(fd, (void *)uuid, sizeof(TSS_UUID)))) {
516 LogDebug("%s", __FUNCTION__);
517 goto done;
518 }
519
520 /* [TSS_UUID uuid_parent0 ] yes */
521 if ((result = write_data(fd, (void *)parent_uuid, sizeof(TSS_UUID)))) {
522 LogDebug("%s", __FUNCTION__);
523 goto done;
524 }
525
526 /* [UINT16 pub_data_size0 ] yes */
527 pub_key_size = LE_16(pub_key_size);
528 if ((result = write_data(fd, &pub_key_size, sizeof(UINT16)))) {
529 LogDebug("%s", __FUNCTION__);
530 goto done;
531 }
532 pub_key_size = LE_16(pub_key_size);
533
534 /* [UINT16 blob_size0 ] yes */
535 key_blob_size = LE_16(key_blob_size);
536 if ((result = write_data(fd, &key_blob_size, sizeof(UINT16)))) {
537 LogDebug("%s", __FUNCTION__);
538 goto done;
539 }
540 key_blob_size = LE_16(key_blob_size);
541
542 /* [UINT32 vendor_data_size0 ] yes */
543 if ((result = write_data(fd, &zero, sizeof(UINT32)))) {
544 LogDebug("%s", __FUNCTION__);
545 goto done;
546 }
547
548 /* [UINT16 cache_flags0 ] yes */
549 cache_flags = LE_16(cache_flags);
550 if ((result = write_data(fd, &cache_flags, sizeof(UINT16)))) {
551 LogDebug("%s", __FUNCTION__);
552 goto done;
553 }
554 cache_flags = LE_16(cache_flags);
555
556 /* [BYTE[] pub_data0 ] no */
557 if ((result = write_data(fd, (void *)key.pubKey.key, pub_key_size))) {
558 LogDebug("%s", __FUNCTION__);
559 goto done;
560 }
561
562 /* [BYTE[] blob0 ] no */
563 if ((result = write_data(fd, (void *)key_blob, key_blob_size))) {
564 LogDebug("%s", __FUNCTION__);
565 goto done;
566 }
567
568 if ((result = psfile_change_num_keys(fd, TSS_PSFILE_INCREMENT_NUM_KEYS))) {
569 LogDebug("%s", __FUNCTION__);
570 goto done;
571 }
572
573 done:
574 free_key_refs(&key);
575 return result;
576 }
577
578 TSS_RESULT
psfile_remove_key(int fd,TSS_UUID * uuid)579 psfile_remove_key(int fd, TSS_UUID *uuid)
580 {
581 TSS_RESULT result;
582 UINT32 head_offset = 0, tail_offset;
583 int rc, size = 0;
584 struct key_disk_cache c;
585 BYTE buf[4096];
586
587 if ((result = psfile_get_cache_entry_by_uuid(fd, uuid, &c)))
588 return result;
589
590 /* head_offset is the offset the beginning of the key */
591 head_offset = TSSPS_UUID_OFFSET(&c);
592
593 /* tail_offset is the offset the beginning of the next key */
594 tail_offset = TSSPS_VENDOR_DATA_OFFSET(&c) + c.vendor_data_size;
595
596 rc = lseek(fd, tail_offset, SEEK_SET);
597 if (rc == ((off_t)-1)) {
598 LogDebug("lseek: %s", strerror(errno));
599 return TSPERR(TSS_E_INTERNAL_ERROR);
600 }
601
602 /* read in from tail, write out to head to fill the gap */
603 while ((rc = read(fd, buf, sizeof(buf))) > 0) {
604 size = rc;
605 tail_offset += size;
606
607 /* set the file pointer to where we want to write */
608 rc = lseek(fd, head_offset, SEEK_SET);
609 if (rc == ((off_t)-1)) {
610 LogDebug("lseek: %s", strerror(errno));
611 return TSPERR(TSS_E_INTERNAL_ERROR);
612 }
613
614 /* write the data */
615 if ((result = write_data(fd, (void *)buf, size))) {
616 LogDebug("%s", __FUNCTION__);
617 return result;
618 }
619 head_offset += size;
620
621 /* set the file pointer to where we want to read in the next
622 * loop */
623 rc = lseek(fd, tail_offset, SEEK_SET);
624 if (rc == ((off_t)-1)) {
625 LogDebug("lseek: %s", strerror(errno));
626 return TSPERR(TSS_E_INTERNAL_ERROR);
627 }
628 }
629
630 if (rc < 0) {
631 LogDebug("read: %s", strerror(errno));
632 return TSPERR(TSS_E_INTERNAL_ERROR);
633 }
634
635 /* set the file pointer to where we want to write */
636 rc = lseek(fd, head_offset, SEEK_SET);
637 if (rc == ((off_t)-1)) {
638 LogDebug("lseek: %s", strerror(errno));
639 return TSPERR(TSS_E_INTERNAL_ERROR);
640 }
641
642 /* head_offset now contains a pointer to where we want to truncate the
643 * file. Zero out the old tail end of the file and truncate it. */
644
645 __tspi_memset(buf, 0, sizeof(buf));
646
647 /* Zero out the old tail end of the file */
648 if ((result = write_data(fd, (void *)buf, tail_offset - head_offset))) {
649 LogDebug("%s", __FUNCTION__);
650 return result;
651 }
652
653 if ((rc = ftruncate(fd, head_offset)) < 0) {
654 LogDebug("ftruncate: %s", strerror(errno));
655 return TSPERR(TSS_E_INTERNAL_ERROR);
656 }
657
658 /* we succeeded in removing a key from the disk. Decrement the number
659 * of keys in the file */
660 if ((result = psfile_change_num_keys(fd, TSS_PSFILE_DECREMENT_NUM_KEYS)))
661 return result;
662
663 return TSS_SUCCESS;
664 }
665
666 TSS_RESULT
psfile_get_all_cache_entries(int fd,UINT32 * size,struct key_disk_cache ** c)667 psfile_get_all_cache_entries(int fd, UINT32 *size, struct key_disk_cache **c)
668 {
669 UINT32 i, num_keys = psfile_get_num_keys(fd);
670 int offset;
671 TSS_RESULT result;
672 struct key_disk_cache *tmp = NULL;
673
674 if (num_keys == 0) {
675 *size = 0;
676 *c = NULL;
677 return TSS_SUCCESS;
678 }
679
680 /* make sure the file pointer is where we expect, just after the number
681 * of keys on disk at the head of the file
682 */
683 offset = lseek(fd, TSSPS_KEYS_OFFSET, SEEK_SET);
684 if (offset == ((off_t)-1)) {
685 LogDebug("lseek: %s", strerror(errno));
686 return TSPERR(TSS_E_INTERNAL_ERROR);
687 }
688
689 if ((tmp = malloc(num_keys * sizeof(struct key_disk_cache))) == NULL) {
690 LogDebug("malloc of %zu bytes failed.", num_keys * sizeof(struct key_disk_cache));
691 return TSPERR(TSS_E_OUTOFMEMORY);
692 }
693
694 for (i = 0; i < num_keys; i++) {
695 offset = lseek(fd, 0, SEEK_CUR);
696 if (offset == ((off_t)-1)) {
697 LogDebug("lseek: %s", strerror(errno));
698 result = TSPERR(TSS_E_INTERNAL_ERROR);
699 goto err_exit;
700 }
701 tmp[i].offset = offset;
702
703 /* read UUID */
704 if ((result = read_data(fd, &tmp[i].uuid, sizeof(TSS_UUID)))) {
705 LogDebug("%s", __FUNCTION__);
706 goto err_exit;
707 }
708
709 /* read parent UUID */
710 if ((result = read_data(fd, &tmp[i].parent_uuid, sizeof(TSS_UUID)))) {
711 LogDebug("%s", __FUNCTION__);
712 goto err_exit;
713 }
714
715 /* pub data size */
716 if ((result = read_data(fd, &tmp[i].pub_data_size, sizeof(UINT16)))) {
717 LogDebug("%s", __FUNCTION__);
718 goto err_exit;
719 }
720 tmp[i].pub_data_size = LE_16(tmp[i].pub_data_size);
721
722 DBG_ASSERT(tmp[i].pub_data_size <= 2048);
723
724 /* blob size */
725 if ((result = read_data(fd, &tmp[i].blob_size, sizeof(UINT16)))) {
726 LogDebug("%s", __FUNCTION__);
727 goto err_exit;
728 }
729 tmp[i].blob_size = LE_16(tmp[i].blob_size);
730
731 DBG_ASSERT(tmp[i].blob_size <= 4096);
732
733 /* vendor data size */
734 if ((result = read_data(fd, &tmp[i].vendor_data_size, sizeof(UINT32)))) {
735 LogDebug("%s", __FUNCTION__);
736 goto err_exit;
737 }
738 tmp[i].vendor_data_size = LE_32(tmp[i].vendor_data_size);
739
740 /* cache flags */
741 if ((result = read_data(fd, &tmp[i].flags, sizeof(UINT16)))) {
742 LogDebug("%s", __FUNCTION__);
743 goto err_exit;
744 }
745 tmp[i].flags = LE_16(tmp[i].flags);
746
747 /* fast forward over the pub key */
748 offset = lseek(fd, tmp[i].pub_data_size, SEEK_CUR);
749 if (offset == ((off_t)-1)) {
750 LogDebug("lseek: %s", strerror(errno));
751 result = TSPERR(TSS_E_INTERNAL_ERROR);
752 goto err_exit;
753 }
754
755 /* fast forward over the blob */
756 offset = lseek(fd, tmp[i].blob_size, SEEK_CUR);
757 if (offset == ((off_t)-1)) {
758 LogDebug("lseek: %s", strerror(errno));
759 result = TSPERR(TSS_E_INTERNAL_ERROR);
760 goto err_exit;
761 }
762
763 /* ignore vendor data for user ps */
764 }
765
766 *size = num_keys;
767 *c = tmp;
768
769 return TSS_SUCCESS;
770
771 err_exit:
772 free(tmp);
773 return result;
774 }
775
776 TSS_RESULT
copy_key_info(int fd,TSS_KM_KEYINFO * ki,struct key_disk_cache * c)777 copy_key_info(int fd, TSS_KM_KEYINFO *ki, struct key_disk_cache *c)
778 {
779 TSS_KEY key;
780 BYTE blob[4096];
781 UINT64 offset;
782 TSS_RESULT result;
783 off_t off;
784
785 /* Set the file pointer to the offset that the key blob is at */
786 off = lseek(fd, TSSPS_BLOB_DATA_OFFSET(c), SEEK_SET);
787 if (off == ((off_t)-1)) {
788 LogDebug("lseek: %s", strerror(errno));
789 return TSPERR(TSS_E_INTERNAL_ERROR);
790 }
791
792 /* Read in the key blob */
793 if ((result = read_data(fd, (void *)blob, c->blob_size))) {
794 LogDebug("%s", __FUNCTION__);
795 return result;
796 }
797
798 /* Expand the blob into a useable form */
799 offset = 0;
800 if ((result = UnloadBlob_TSS_KEY(&offset, blob, &key)))
801 return result;
802
803 if (key.hdr.key12.tag == TPM_TAG_KEY12) {
804 ki->versionInfo.bMajor = TSS_SPEC_MAJOR;
805 ki->versionInfo.bMinor = TSS_SPEC_MINOR;
806 ki->versionInfo.bRevMajor = 0;
807 ki->versionInfo.bRevMinor = 0;
808 } else
809 memcpy(&ki->versionInfo, &key.hdr.key11.ver, sizeof(TSS_VERSION));
810 memcpy(&ki->keyUUID, &c->uuid, sizeof(TSS_UUID));
811 memcpy(&ki->parentKeyUUID, &c->parent_uuid, sizeof(TSS_UUID));
812 ki->bAuthDataUsage = key.authDataUsage;
813
814 free_key_refs(&key);
815
816 return TSS_SUCCESS;
817 }
818
819 TSS_RESULT
copy_key_info2(int fd,TSS_KM_KEYINFO2 * ki,struct key_disk_cache * c)820 copy_key_info2(int fd, TSS_KM_KEYINFO2 *ki, struct key_disk_cache *c)
821 {
822 TSS_KEY key;
823 BYTE blob[4096];
824 UINT64 offset;
825 TSS_RESULT result;
826 off_t off;
827
828 /* Set the file pointer to the offset that the key blob is at */
829 off = lseek(fd, TSSPS_BLOB_DATA_OFFSET(c), SEEK_SET);
830 if (off == ((off_t)-1)) {
831 LogDebug("lseek: %s", strerror(errno));
832 return TSPERR(TSS_E_INTERNAL_ERROR);
833 }
834
835 /* Read in the key blob */
836 if ((result = read_data(fd, (void *)blob, c->blob_size))) {
837 LogDebug("%s", __FUNCTION__);
838 return result;
839 }
840
841 /* Expand the blob into a useable form */
842 offset = 0;
843 if ((result = UnloadBlob_TSS_KEY(&offset, blob, &key)))
844 return result;
845
846 if (key.hdr.key12.tag == TPM_TAG_KEY12) {
847 ki->versionInfo.bMajor = TSS_SPEC_MAJOR;
848 ki->versionInfo.bMinor = TSS_SPEC_MINOR;
849 ki->versionInfo.bRevMajor = 0;
850 ki->versionInfo.bRevMinor = 0;
851 } else
852 memcpy(&ki->versionInfo, &key.hdr.key11.ver, sizeof(TSS_VERSION));
853 memcpy(&ki->keyUUID, &c->uuid, sizeof(TSS_UUID));
854 memcpy(&ki->parentKeyUUID, &c->parent_uuid, sizeof(TSS_UUID));
855
856 /* CHECK: fill the two new fields of TSS_KM_KEYINFO2 */
857 ki->persistentStorageType = TSS_PS_TYPE_USER;
858 ki->persistentStorageTypeParent = c->flags & CACHE_FLAG_PARENT_PS_SYSTEM ?
859 TSS_PS_TYPE_SYSTEM : TSS_PS_TYPE_USER;
860
861 ki->bAuthDataUsage = key.authDataUsage;
862
863 free_key_refs(&key);
864
865 return TSS_SUCCESS;
866 }
867
868
869 TSS_RESULT
psfile_get_registered_keys(int fd,TSS_UUID * uuid,TSS_UUID * tcs_uuid,UINT32 * size,TSS_KM_KEYINFO ** keys)870 psfile_get_registered_keys(int fd,
871 TSS_UUID *uuid,
872 TSS_UUID *tcs_uuid,
873 UINT32 *size,
874 TSS_KM_KEYINFO **keys)
875 {
876 TSS_RESULT result;
877 struct key_disk_cache *cache_entries;
878 UINT32 cache_size, i, j;
879 TSS_KM_KEYINFO *keyinfos = NULL;
880 TSS_UUID *find_uuid;
881
882 if ((result = psfile_get_all_cache_entries(fd, &cache_size, &cache_entries)))
883 return result;
884
885 if (cache_size == 0) {
886 if (uuid)
887 return TSPERR(TSS_E_PS_KEY_NOTFOUND);
888 else {
889 *size = 0;
890 *keys = NULL;
891 return TSS_SUCCESS;
892 }
893 }
894
895 if (uuid) {
896 find_uuid = uuid;
897 j = 0;
898
899 restart_search:
900 /* Search for the requested UUID. When found, allocate new space for it, copy
901 * it in, then change the uuid to be searched for it its parent and start over. */
902 for (i = 0; i < cache_size; i++) {
903 if (!memcmp(&cache_entries[i].uuid, find_uuid, sizeof(TSS_UUID))) {
904 if (!(keyinfos = realloc(keyinfos,
905 (j+1) * sizeof(TSS_KM_KEYINFO)))) {
906 free(cache_entries);
907 free(keyinfos);
908 return TSPERR(TSS_E_OUTOFMEMORY);
909 }
910 __tspi_memset(&keyinfos[j], 0, sizeof(TSS_KM_KEYINFO));
911
912 if ((result = copy_key_info(fd, &keyinfos[j], &cache_entries[i]))) {
913 free(cache_entries);
914 free(keyinfos);
915 return result;
916 }
917
918 find_uuid = &keyinfos[j].parentKeyUUID;
919 j++;
920 goto restart_search;
921 }
922 }
923
924 /* Searching for keys in the user PS will always lead us up to some key in the
925 * system PS. Return that key's uuid so that the upper layers can call down to TCS
926 * to search for it. */
927 memcpy(tcs_uuid, find_uuid, sizeof(TSS_UUID));
928
929 *size = j;
930 } else {
931 if ((keyinfos = calloc(cache_size, sizeof(TSS_KM_KEYINFO))) == NULL) {
932 LogDebug("malloc of %zu bytes failed.",
933 cache_size * sizeof(TSS_KM_KEYINFO));
934 free(cache_entries);
935 return TSPERR(TSS_E_OUTOFMEMORY);
936 }
937
938 for (i = 0; i < cache_size; i++) {
939 if ((result = copy_key_info(fd, &keyinfos[i], &cache_entries[i]))) {
940 free(cache_entries);
941 free(keyinfos);
942 return result;
943 }
944 }
945
946 *size = cache_size;
947 }
948
949 free(cache_entries);
950
951 *keys = keyinfos;
952
953 return TSS_SUCCESS;
954 }
955
956 TSS_RESULT
psfile_get_registered_keys2(int fd,TSS_UUID * uuid,TSS_UUID * tcs_uuid,UINT32 * size,TSS_KM_KEYINFO2 ** keys)957 psfile_get_registered_keys2(int fd,
958 TSS_UUID *uuid,
959 TSS_UUID *tcs_uuid,
960 UINT32 *size,
961 TSS_KM_KEYINFO2 **keys)
962 {
963 TSS_RESULT result;
964 struct key_disk_cache *cache_entries;
965 UINT32 cache_size, i, j;
966 TSS_KM_KEYINFO2 *keyinfos = NULL;
967 TSS_UUID *find_uuid;
968
969 if ((result = psfile_get_all_cache_entries(fd, &cache_size, &cache_entries)))
970 return result;
971
972 if (cache_size == 0) {
973 if (uuid)
974 return TSPERR(TSS_E_PS_KEY_NOTFOUND);
975 else {
976 *size = 0;
977 *keys = NULL;
978 return TSS_SUCCESS;
979 }
980 }
981
982 if (uuid) {
983 find_uuid = uuid;
984 j = 0;
985
986 restart_search:
987 /* Search for the requested UUID. When found, allocate new space for it, copy
988 * it in, then change the uuid to be searched for it its parent and start over. */
989 for (i = 0; i < cache_size; i++) {
990 /*Return 0 if normal finish*/
991 if (!memcmp(&cache_entries[i].uuid, find_uuid, sizeof(TSS_UUID))) {
992 if (!(keyinfos = realloc(keyinfos,
993 (j+1) * sizeof(TSS_KM_KEYINFO2)))) {
994 free(cache_entries);
995 free(keyinfos);
996 return TSPERR(TSS_E_OUTOFMEMORY);
997 }
998 /* Here the key UUID is found and needs to be copied for the array*/
999 /* Initializes the keyinfos with 0's*/
1000 __tspi_memset(&keyinfos[j], 0, sizeof(TSS_KM_KEYINFO2));
1001
1002 if ((result = copy_key_info2(fd, &keyinfos[j], &cache_entries[i]))) {
1003 free(cache_entries);
1004 free(keyinfos);
1005 return result;
1006 }
1007
1008 find_uuid = &keyinfos[j].parentKeyUUID;
1009 j++;
1010 goto restart_search;
1011 }
1012 }
1013
1014 /* Searching for keys in the user PS will always lead us up to some key in the
1015 * system PS. Return that key's uuid so that the upper layers can call down to TCS
1016 * to search for it. */
1017 memcpy(tcs_uuid, find_uuid, sizeof(TSS_UUID));
1018
1019 *size = j;
1020 } else {
1021 if ((keyinfos = calloc(cache_size, sizeof(TSS_KM_KEYINFO2))) == NULL) {
1022 LogDebug("malloc of %zu bytes failed.",
1023 cache_size * sizeof(TSS_KM_KEYINFO2));
1024 free(cache_entries);
1025 return TSPERR(TSS_E_OUTOFMEMORY);
1026 }
1027
1028 for (i = 0; i < cache_size; i++) {
1029 if ((result = copy_key_info2(fd, &keyinfos[i], &cache_entries[i]))) {
1030 free(cache_entries);
1031 free(keyinfos);
1032 return result;
1033 }
1034 }
1035
1036 *size = cache_size;
1037 }
1038
1039 free(cache_entries);
1040
1041 *keys = keyinfos;
1042
1043 return TSS_SUCCESS;
1044 }
1045
1046 /*
1047 * read into the PS file and return the number of keys
1048 */
1049 UINT32
psfile_get_num_keys(int fd)1050 psfile_get_num_keys(int fd)
1051 {
1052 UINT32 num_keys;
1053 int rc;
1054
1055 /* go to the number of keys */
1056 rc = lseek(fd, TSSPS_NUM_KEYS_OFFSET, SEEK_SET);
1057 if (rc == ((off_t)-1)) {
1058 LogDebug("lseek: %s", strerror(errno));
1059 return 0;
1060 }
1061
1062 rc = read(fd, &num_keys, sizeof(UINT32));
1063 if (rc < 0) {
1064 LogDebug("read of %zd bytes: %s", sizeof(UINT32), strerror(errno));
1065 return 0;
1066 } else if ((unsigned)rc < sizeof(UINT32)) {
1067 num_keys = 0;
1068 }
1069
1070 /* The system PS file is written in little-endian */
1071 num_keys = LE_32(num_keys);
1072 return num_keys;
1073 }
1074
1075 /*
1076 * disk store format:
1077 *
1078 * TrouSerS 0.2.1+
1079 * Version 1: cached?
1080 * [BYTE PS version = '\1']
1081 * [UINT32 num_keys_on_disk ]
1082 * [TSS_UUID uuid0 ] yes
1083 * [TSS_UUID uuid_parent0 ] yes
1084 * [UINT16 pub_data_size0 ] yes
1085 * [UINT16 blob_size0 ] yes
1086 * [UINT32 vendor_data_size0] yes
1087 * [UINT16 cache_flags0 ] yes
1088 * [BYTE[] pub_data0 ]
1089 * [BYTE[] blob0 ]
1090 * [BYTE[] vendor_data0 ]
1091 * [...]
1092 *
1093 */
1094 TSS_RESULT
psfile_get_cache_entry_by_uuid(int fd,TSS_UUID * uuid,struct key_disk_cache * c)1095 psfile_get_cache_entry_by_uuid(int fd, TSS_UUID *uuid, struct key_disk_cache *c)
1096 {
1097 UINT32 i, num_keys = psfile_get_num_keys(fd);
1098 int offset;
1099 TSS_RESULT result;
1100 BYTE found = 0;
1101
1102 if (num_keys == 0)
1103 return TSPERR(TSS_E_PS_KEY_NOTFOUND);
1104
1105 /* make sure the file pointer is where we expect, just after the number
1106 * of keys on disk at the head of the file
1107 */
1108 offset = lseek(fd, TSSPS_KEYS_OFFSET, SEEK_SET);
1109 if (offset == ((off_t)-1)) {
1110 LogDebug("lseek: %s", strerror(errno));
1111 return TSPERR(TSS_E_INTERNAL_ERROR);
1112 }
1113
1114 for (i = 0; i < num_keys && !found; i++) {
1115 offset = lseek(fd, 0, SEEK_CUR);
1116 if (offset == ((off_t)-1)) {
1117 LogDebug("lseek: %s", strerror(errno));
1118 return TSPERR(TSS_E_INTERNAL_ERROR);
1119 }
1120 c->offset = offset;
1121
1122 /* read UUID */
1123 if ((result = read_data(fd, (void *)&c->uuid, sizeof(TSS_UUID)))) {
1124 LogDebug("%s", __FUNCTION__);
1125 return result;
1126 }
1127
1128 if (!memcmp(&c->uuid, uuid, sizeof(TSS_UUID))) {
1129 found = 1;
1130
1131 /* read parent UUID */
1132 if ((result = read_data(fd, (void *)&c->parent_uuid, sizeof(TSS_UUID)))) {
1133 LogDebug("%s", __FUNCTION__);
1134 return result;
1135 }
1136 } else {
1137 /* fast forward over the parent UUID */
1138 offset = lseek(fd, sizeof(TSS_UUID), SEEK_CUR);
1139 if (offset == ((off_t)-1)) {
1140 LogDebug("lseek: %s", strerror(errno));
1141 return TSPERR(TSS_E_INTERNAL_ERROR);
1142 }
1143 }
1144
1145 /* pub data size */
1146 if ((result = read_data(fd, &c->pub_data_size, sizeof(UINT16)))) {
1147 LogDebug("%s", __FUNCTION__);
1148 return result;
1149 }
1150 c->pub_data_size = LE_16(c->pub_data_size);
1151 DBG_ASSERT(c->pub_data_size <= 2048 && c->pub_data_size > 0);
1152
1153 /* blob size */
1154 if ((result = read_data(fd, &c->blob_size, sizeof(UINT16)))) {
1155 LogDebug("%s", __FUNCTION__);
1156 return result;
1157 }
1158 c->blob_size = LE_16(c->blob_size);
1159 DBG_ASSERT(c->blob_size <= 4096 && c->blob_size > 0);
1160
1161 /* vendor data size */
1162 if ((result = read_data(fd, &c->vendor_data_size, sizeof(UINT32)))) {
1163 LogDebug("%s", __FUNCTION__);
1164 return result;
1165 }
1166 c->vendor_data_size = LE_32(c->vendor_data_size);
1167
1168 /* cache flags */
1169 if ((result = read_data(fd, &c->flags, sizeof(UINT16)))) {
1170 LogDebug("%s", __FUNCTION__);
1171 return result;
1172 }
1173 c->flags = LE_16(c->flags);
1174
1175 /* fast forward over the pub key */
1176 offset = lseek(fd, c->pub_data_size, SEEK_CUR);
1177 if (offset == ((off_t)-1)) {
1178 LogDebug("lseek: %s", strerror(errno));
1179 return TSPERR(TSS_E_INTERNAL_ERROR);
1180 }
1181
1182 /* fast forward over the blob */
1183 offset = lseek(fd, c->blob_size, SEEK_CUR);
1184 if (offset == ((off_t)-1)) {
1185 LogDebug("lseek: %s", strerror(errno));
1186 return TSPERR(TSS_E_INTERNAL_ERROR);
1187 }
1188
1189 /* ignore vendor data in user ps */
1190 }
1191
1192 return found ? TSS_SUCCESS : TSPERR(TSS_E_PS_KEY_NOTFOUND);
1193 }
1194
1195 TSS_RESULT
psfile_get_cache_entry_by_pub(int fd,UINT32 pub_size,BYTE * pub,struct key_disk_cache * c)1196 psfile_get_cache_entry_by_pub(int fd, UINT32 pub_size, BYTE *pub, struct key_disk_cache *c)
1197 {
1198 BYTE blob[2048];
1199 UINT32 i, num_keys = psfile_get_num_keys(fd);
1200 int offset;
1201 TSS_RESULT result;
1202
1203 if (num_keys == 0)
1204 return TSPERR(TSS_E_PS_KEY_NOTFOUND);
1205
1206 /* make sure the file pointer is where we expect, just after the number
1207 * of keys on disk at the head of the file
1208 */
1209 offset = lseek(fd, TSSPS_KEYS_OFFSET, SEEK_SET);
1210 if (offset == ((off_t)-1)) {
1211 LogDebug("lseek: %s", strerror(errno));
1212 return TSPERR(TSS_E_INTERNAL_ERROR);
1213 }
1214
1215 for (i = 0; i < num_keys; i++) {
1216 offset = lseek(fd, 0, SEEK_CUR);
1217 if (offset == ((off_t)-1)) {
1218 LogDebug("lseek: %s", strerror(errno));
1219 return TSPERR(TSS_E_INTERNAL_ERROR);
1220 }
1221 c->offset = offset;
1222
1223 /* read UUID */
1224 if ((result = read_data(fd, (void *)&c->uuid, sizeof(TSS_UUID)))) {
1225 LogDebug("%s", __FUNCTION__);
1226 return result;
1227 }
1228
1229 /* read parent UUID */
1230 if ((result = read_data(fd, (void *)&c->parent_uuid, sizeof(TSS_UUID)))) {
1231 LogDebug("%s", __FUNCTION__);
1232 return result;
1233 }
1234
1235 /* pub data size */
1236 if ((result = read_data(fd, &c->pub_data_size, sizeof(UINT16)))) {
1237 LogDebug("%s", __FUNCTION__);
1238 return result;
1239 }
1240
1241 c->pub_data_size = LE_16(c->pub_data_size);
1242 DBG_ASSERT(c->pub_data_size <= 2048 && c->pub_data_size > 0);
1243
1244 /* blob size */
1245 if ((result = read_data(fd, &c->blob_size, sizeof(UINT16)))) {
1246 LogDebug("%s", __FUNCTION__);
1247 return result;
1248 }
1249
1250 c->blob_size = LE_16(c->blob_size);
1251 DBG_ASSERT(c->blob_size <= 4096 && c->blob_size > 0);
1252
1253 /* vendor data size */
1254 if ((result = read_data(fd, &c->vendor_data_size, sizeof(UINT32)))) {
1255 LogDebug("%s", __FUNCTION__);
1256 return result;
1257 }
1258 c->vendor_data_size = LE_32(c->vendor_data_size);
1259
1260 /* cache flags */
1261 if ((result = read_data(fd, &c->flags, sizeof(UINT16)))) {
1262 LogDebug("%s", __FUNCTION__);
1263 return result;
1264 }
1265 c->flags = LE_16(c->flags);
1266
1267 if (c->pub_data_size == pub_size) {
1268 /* read in the pub key */
1269 if ((result = read_data(fd, blob, c->pub_data_size))) {
1270 LogDebug("%s", __FUNCTION__);
1271 return result;
1272 }
1273
1274 if (!memcmp(blob, pub, pub_size))
1275 break;
1276 }
1277
1278 /* fast forward over the blob */
1279 offset = lseek(fd, c->blob_size, SEEK_CUR);
1280 if (offset == ((off_t)-1)) {
1281 LogDebug("lseek: %s", strerror(errno));
1282 return TSPERR(TSS_E_INTERNAL_ERROR);
1283 }
1284
1285 /* ignore vendor data */
1286 }
1287
1288 return TSS_SUCCESS;
1289 }
1290