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