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