Home | History | Annotate | Line # | Download | only in ps
      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
     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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
   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
   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
   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