diff options
Diffstat (limited to 'src/tcs/ps/tcsps.c')
-rw-r--r-- | src/tcs/ps/tcsps.c | 784 |
1 files changed, 784 insertions, 0 deletions
diff --git a/src/tcs/ps/tcsps.c b/src/tcs/ps/tcsps.c new file mode 100644 index 0000000..0d55608 --- /dev/null +++ b/src/tcs/ps/tcsps.c @@ -0,0 +1,784 @@ + +/* + * Licensed Materials - Property of IBM + * + * trousers - An open source TCG Software Stack + * + * (C) Copyright International Business Machines Corp. 2004-2006 + * + */ + + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/file.h> +#include <sys/stat.h> +#if defined (HAVE_BYTEORDER_H) +#include <sys/byteorder.h> +#elif defined (HTOLE_DEFINED) +#include <endian.h> +#define LE_16 htole16 +#define LE_32 htole32 +#define LE_64 htole64 +#else +#define LE_16(x) (x) +#define LE_32(x) (x) +#define LE_64(x) (x) +#endif +#include <assert.h> +#include <fcntl.h> +#include <limits.h> + +#include "trousers/tss.h" +#include "trousers_types.h" +#include "tcsps.h" +#include "tcs_tsp.h" +#include "tcs_utils.h" +#include "capabilities.h" +#include "tcslog.h" +#include "tcsd_wrap.h" +#include "tcsd.h" + +int system_ps_fd = -1; +MUTEX_DECLARE(disk_cache_lock); + +static struct flock fl; + +int +get_file() +{ + int rc; + /* check the global file handle first. If it exists, lock it and return */ + if (system_ps_fd != -1) { + int rc = 0; + + fl.l_type = F_WRLCK; + if ((rc = fcntl(system_ps_fd, F_SETLKW, &fl))) { + LogError("failed to get system PS lock: %s", strerror(errno)); + return -1; + } + + return system_ps_fd; + } + + /* open and lock the file */ + system_ps_fd = open(tcsd_options.system_ps_file, O_CREAT|O_RDWR, 0600); + if (system_ps_fd < 0) { + LogError("system PS: open() of %s failed: %s", + tcsd_options.system_ps_file, strerror(errno)); + return -1; + } + + fl.l_type = F_WRLCK; + if ((rc = fcntl(system_ps_fd, F_SETLKW, &fl))) { + LogError("failed to get system PS lock of file %s: %s", + tcsd_options.system_ps_file, strerror(errno)); + return -1; + } + + return system_ps_fd; +} + +int +put_file(int fd) +{ + int rc = 0; + /* release the file lock */ + + fl.l_type = F_UNLCK; + if ((rc = fcntl(fd, F_SETLKW, &fl))) { + LogError("failed to unlock system PS file: %s", + strerror(errno)); + return -1; + } + + return rc; +} + +void +close_file(int fd) +{ + close(fd); + system_ps_fd = -1; +} + +TSS_RESULT +psfile_get_parent_uuid_by_uuid(int fd, TSS_UUID *uuid, TSS_UUID *ret_uuid) +{ + int rc; + UINT32 file_offset = 0; + struct key_disk_cache *tmp; + + MUTEX_LOCK(disk_cache_lock); + tmp = key_disk_cache_head; + + while (tmp) { + if (memcmp(uuid, &tmp->uuid, sizeof(TSS_UUID)) || !(tmp->flags & CACHE_FLAG_VALID)) { + tmp = tmp->next; + continue; + } + + /* jump to the location of the parent uuid */ + file_offset = TSSPS_PARENT_UUID_OFFSET(tmp); + + rc = lseek(fd, file_offset, SEEK_SET); + if (rc == ((off_t) - 1)) { + LogError("lseek: %s", strerror(errno)); + MUTEX_UNLOCK(disk_cache_lock); + return -1; + } + + if ((rc = read_data(fd, ret_uuid, sizeof(TSS_UUID)))) { + LogError("%s", __FUNCTION__); + MUTEX_UNLOCK(disk_cache_lock); + return rc; + } + + MUTEX_UNLOCK(disk_cache_lock); + return TSS_SUCCESS; + } + MUTEX_UNLOCK(disk_cache_lock); + /* key not found */ + return -2; +} + +/* + * return a key blob from PS given a uuid + */ +TSS_RESULT +psfile_get_key_by_uuid(int fd, TSS_UUID *uuid, BYTE *ret_buffer, UINT16 *ret_buffer_size) +{ + int rc; + UINT32 file_offset = 0; + struct key_disk_cache *tmp; + + MUTEX_LOCK(disk_cache_lock); + tmp = key_disk_cache_head; + + while (tmp) { + if (memcmp(uuid, &tmp->uuid, sizeof(TSS_UUID)) || !(tmp->flags & CACHE_FLAG_VALID)) { + tmp = tmp->next; + continue; + } + + /* jump to the location of the key blob */ + file_offset = TSSPS_BLOB_DATA_OFFSET(tmp); + + rc = lseek(fd, file_offset, SEEK_SET); + if (rc == ((off_t) - 1)) { + LogError("lseek: %s", strerror(errno)); + MUTEX_UNLOCK(disk_cache_lock); + return TCSERR(TSS_E_INTERNAL_ERROR); + } + + /* we found the key; file ptr is pointing at the blob */ + if (*ret_buffer_size < tmp->blob_size) { + /* not enough room */ + MUTEX_UNLOCK(disk_cache_lock); + return TCSERR(TSS_E_FAIL); + } + + if ((rc = read_data(fd, ret_buffer, tmp->blob_size))) { + LogError("%s", __FUNCTION__); + MUTEX_UNLOCK(disk_cache_lock); + return rc; + } + *ret_buffer_size = tmp->blob_size; + LogDebugUnrollKey(ret_buffer); + MUTEX_UNLOCK(disk_cache_lock); + return TSS_SUCCESS; + } + MUTEX_UNLOCK(disk_cache_lock); + /* key not found */ + return TCSERR(TSS_E_FAIL); +} + +/* + * return a key blob from PS given its cache entry. The disk cache must be + * locked by the caller. + */ +TSS_RESULT +psfile_get_key_by_cache_entry(int fd, struct key_disk_cache *c, BYTE *ret_buffer, + UINT16 *ret_buffer_size) +{ + int rc; + UINT32 file_offset = 0; + + /* jump to the location of the key blob */ + file_offset = TSSPS_BLOB_DATA_OFFSET(c); + + rc = lseek(fd, file_offset, SEEK_SET); + if (rc == ((off_t) - 1)) { + LogError("lseek: %s", strerror(errno)); + return TCSERR(TSS_E_INTERNAL_ERROR); + } + + /* we found the key; file ptr is pointing at the blob */ + if (*ret_buffer_size < c->blob_size) { + /* not enough room */ + LogError("%s: Buf size too small. Needed %d bytes, passed %d", __FUNCTION__, + c->blob_size, *ret_buffer_size); + return TCSERR(TSS_E_INTERNAL_ERROR); + } + + if ((rc = read_data(fd, ret_buffer, c->blob_size))) { + LogError("%s: error reading %d bytes", __FUNCTION__, c->blob_size); + return TCSERR(TSS_E_INTERNAL_ERROR); + } + *ret_buffer_size = c->blob_size; + + return TSS_SUCCESS; +} + +/* + * return the vendor data from PS given its cache entry. The disk cache must be + * locked by the caller. + */ +TSS_RESULT +psfile_get_vendor_data(int fd, struct key_disk_cache *c, UINT32 *size, BYTE **data) +{ + int rc; + UINT32 file_offset; + + /* jump to the location of the data */ + file_offset = TSSPS_VENDOR_DATA_OFFSET(c); + + rc = lseek(fd, file_offset, SEEK_SET); + if (rc == ((off_t) - 1)) { + LogError("lseek: %s", strerror(errno)); + return TCSERR(TSS_E_INTERNAL_ERROR); + } + + if ((*data = malloc(c->vendor_data_size)) == NULL) { + LogError("malloc of %u bytes failed", c->vendor_data_size); + return TCSERR(TSS_E_OUTOFMEMORY); + } + + if ((rc = read_data(fd, *data, c->vendor_data_size))) { + LogError("%s: error reading %u bytes", __FUNCTION__, c->vendor_data_size); + free(*data); + *data = NULL; + return TCSERR(TSS_E_INTERNAL_ERROR); + } + *size = c->vendor_data_size; + + return TSS_SUCCESS; +} + +TSS_RESULT +psfile_get_ps_type_by_uuid(int fd, TSS_UUID *uuid, UINT32 *ret_ps_type) +{ + struct key_disk_cache *tmp; + + MUTEX_LOCK(disk_cache_lock); + tmp = key_disk_cache_head; + + while (tmp) { + if (memcmp(uuid, &tmp->uuid, sizeof(TSS_UUID)) || + !(tmp->flags & CACHE_FLAG_VALID)) { + tmp = tmp->next; + continue; + } + + if (tmp->flags & CACHE_FLAG_PARENT_PS_SYSTEM) { + *ret_ps_type = TSS_PS_TYPE_SYSTEM; + goto done; + } else + break; + } + + *ret_ps_type = TSS_PS_TYPE_USER; +done: + MUTEX_UNLOCK(disk_cache_lock); + return TSS_SUCCESS; +} + +TSS_RESULT +psfile_is_pub_registered(int fd, TCPA_STORE_PUBKEY *pub, TSS_BOOL *is_reg) +{ + int rc; + UINT32 file_offset = 0; + struct key_disk_cache *tmp; + char tmp_buffer[2048]; + + MUTEX_LOCK(disk_cache_lock); + tmp = key_disk_cache_head; + + while (tmp) { + /* if the key is of the wrong size or is invalid, try the next one */ + if (pub->keyLength != tmp->pub_data_size || !(tmp->flags & CACHE_FLAG_VALID)) { + tmp = tmp->next; + continue; + } + + /* we have a valid key with the same key size as the one we're looking for. + * grab the pub key data off disk and compare it. */ + + /* jump to the location of the public key */ + file_offset = TSSPS_PUB_DATA_OFFSET(tmp); + + rc = lseek(fd, file_offset, SEEK_SET); + if (rc == ((off_t) - 1)) { + LogError("lseek: %s", strerror(errno)); + MUTEX_UNLOCK(disk_cache_lock); + return TCSERR(TSS_E_INTERNAL_ERROR); + } + + DBG_ASSERT(tmp->pub_data_size < 2048); + + /* read in the key */ + if ((rc = read_data(fd, tmp_buffer, tmp->pub_data_size))) { + LogError("%s", __FUNCTION__); + MUTEX_UNLOCK(disk_cache_lock); + return rc; + } + + /* do the compare */ + if (memcmp(tmp_buffer, pub->key, tmp->pub_data_size)) { + tmp = tmp->next; + continue; + } + + /* the key matches, copy the uuid out */ + *is_reg = TRUE; + + MUTEX_UNLOCK(disk_cache_lock); + return TSS_SUCCESS; + } + MUTEX_UNLOCK(disk_cache_lock); + /* key not found */ + *is_reg = FALSE; + return TSS_SUCCESS; +} + + +TSS_RESULT +psfile_get_uuid_by_pub(int fd, TCPA_STORE_PUBKEY *pub, TSS_UUID **ret_uuid) +{ + int rc; + UINT32 file_offset = 0; + struct key_disk_cache *tmp; + char tmp_buffer[2048]; + + MUTEX_LOCK(disk_cache_lock); + tmp = key_disk_cache_head; + + while (tmp) { + /* if the key is of the wrong size or is invalid, try the next one */ + if (pub->keyLength != tmp->pub_data_size || !(tmp->flags & CACHE_FLAG_VALID)) { + tmp = tmp->next; + continue; + } + + /* we have a valid key with the same key size as the one we're looking for. + * grab the pub key data off disk and compare it. */ + + /* jump to the location of the public key */ + file_offset = TSSPS_PUB_DATA_OFFSET(tmp); + + rc = lseek(fd, file_offset, SEEK_SET); + if (rc == ((off_t) - 1)) { + LogError("lseek: %s", strerror(errno)); + MUTEX_UNLOCK(disk_cache_lock); + return TCSERR(TSS_E_INTERNAL_ERROR); + } + + DBG_ASSERT(tmp->pub_data_size < 2048); + + if (tmp->pub_data_size > sizeof(tmp_buffer)) { + LogError("Source buffer size too big! Size: %d", + tmp->pub_data_size); + MUTEX_UNLOCK(disk_cache_lock); + return TCSERR(TSS_E_INTERNAL_ERROR); + } + /* read in the key */ + if ((rc = read_data(fd, tmp_buffer, tmp->pub_data_size))) { + LogError("%s", __FUNCTION__); + MUTEX_UNLOCK(disk_cache_lock); + return rc; + } + + /* do the compare */ + if (memcmp(tmp_buffer, pub->key, tmp->pub_data_size)) { + tmp = tmp->next; + continue; + } + + *ret_uuid = (TSS_UUID *)malloc(sizeof(TSS_UUID)); + if (*ret_uuid == NULL) { + LogError("malloc of %zd bytes failed.", sizeof(TSS_UUID)); + MUTEX_UNLOCK(disk_cache_lock); + return TCSERR(TSS_E_OUTOFMEMORY); + } + + /* the key matches, copy the uuid out */ + memcpy(*ret_uuid, &tmp->uuid, sizeof(TSS_UUID)); + + MUTEX_UNLOCK(disk_cache_lock); + return TSS_SUCCESS; + } + MUTEX_UNLOCK(disk_cache_lock); + /* key not found */ + return TCSERR(TSS_E_PS_KEY_NOTFOUND); +} + +TSS_RESULT +psfile_get_key_by_pub(int fd, TCPA_STORE_PUBKEY *pub, UINT32 *size, BYTE **ret_key) +{ + int rc; + UINT32 file_offset = 0; + struct key_disk_cache *tmp; + BYTE tmp_buffer[4096]; + + MUTEX_LOCK(disk_cache_lock); + tmp = key_disk_cache_head; + + while (tmp) { + /* if the key is of the wrong size or is invalid, try the next one */ + if (pub->keyLength != tmp->pub_data_size || !(tmp->flags & CACHE_FLAG_VALID)) { + tmp = tmp->next; + continue; + } + + /* we have a valid key with the same key size as the one we're looking for. + * grab the pub key data off disk and compare it. */ + + /* jump to the location of the public key */ + file_offset = TSSPS_PUB_DATA_OFFSET(tmp); + + rc = lseek(fd, file_offset, SEEK_SET); + if (rc == ((off_t) - 1)) { + LogError("lseek: %s", strerror(errno)); + MUTEX_UNLOCK(disk_cache_lock); + return TCSERR(TSS_E_INTERNAL_ERROR); + } + + DBG_ASSERT(tmp->pub_data_size < 2048); + if (tmp->pub_data_size > sizeof(tmp_buffer)) { + LogError("Source buffer size too big! Size: %d", + tmp->pub_data_size); + MUTEX_UNLOCK(disk_cache_lock); + return TCSERR(TSS_E_INTERNAL_ERROR); + } + + /* read in the key */ + if ((rc = read_data(fd, tmp_buffer, tmp->pub_data_size))) { + LogError("%s", __FUNCTION__); + MUTEX_UNLOCK(disk_cache_lock); + return rc; + } + + /* do the compare */ + if (memcmp(tmp_buffer, pub->key, tmp->pub_data_size)) { + tmp = tmp->next; + continue; + } + + /* jump to the location of the key blob */ + file_offset = TSSPS_BLOB_DATA_OFFSET(tmp); + + rc = lseek(fd, file_offset, SEEK_SET); + if (rc == ((off_t) - 1)) { + LogError("lseek: %s", strerror(errno)); + MUTEX_UNLOCK(disk_cache_lock); + return TCSERR(TSS_E_INTERNAL_ERROR); + } + + DBG_ASSERT(tmp->blob_size < 4096); + if (tmp->blob_size > sizeof(tmp_buffer)) { + LogError("Blob size greater than 4096! Size: %d", + tmp->blob_size); + MUTEX_UNLOCK(disk_cache_lock); + return TCSERR(TSS_E_INTERNAL_ERROR); + } + + /* read in the key blob */ + if ((rc = read_data(fd, tmp_buffer, tmp->blob_size))) { + LogError("%s", __FUNCTION__); + MUTEX_UNLOCK(disk_cache_lock); + return rc; + } + + *ret_key = malloc(tmp->blob_size); + if (*ret_key == NULL) { + LogError("malloc of %d bytes failed.", tmp->blob_size); + MUTEX_UNLOCK(disk_cache_lock); + return TCSERR(TSS_E_OUTOFMEMORY); + } + + memcpy(*ret_key, tmp_buffer, tmp->blob_size); + *size = tmp->blob_size; + + MUTEX_UNLOCK(disk_cache_lock); + return rc; + } + MUTEX_UNLOCK(disk_cache_lock); + /* key not found */ + return -2; +} + +/* + * disk store format: + * + * TrouSerS 0.2.0 and before: + * Version 0: cached? + * [UINT32 num_keys_on_disk] + * [TSS_UUID uuid0 ] yes + * [TSS_UUID uuid_parent0 ] yes + * [UINT16 pub_data_size0 ] yes + * [UINT16 blob_size0 ] yes + * [UINT16 cache_flags0 ] yes + * [BYTE[] pub_data0 ] + * [BYTE[] blob0 ] + * [...] + * + * TrouSerS 0.2.1+ + * Version 1: cached? + * [BYTE PS version = '\1'] + * [UINT32 num_keys_on_disk ] + * [TSS_UUID uuid0 ] yes + * [TSS_UUID uuid_parent0 ] yes + * [UINT16 pub_data_size0 ] yes + * [UINT16 blob_size0 ] yes + * [UINT32 vendor_data_size0] yes + * [UINT16 cache_flags0 ] yes + * [BYTE[] pub_data0 ] + * [BYTE[] blob0 ] + * [BYTE[] vendor_data0 ] + * [...] + * + */ +TSS_RESULT +psfile_write_key(int fd, + TSS_UUID *uuid, + TSS_UUID *parent_uuid, + UINT32 *parent_ps, + BYTE *vendor_data, + UINT32 vendor_size, + BYTE *key_blob, + UINT16 key_blob_size) +{ + TSS_KEY key; + UINT16 pub_key_size, cache_flags = CACHE_FLAG_VALID; + UINT64 offset; + int rc = 0; + + /* leaving the cache flag for parent ps type as 0 implies TSS_PS_TYPE_USER */ + if (*parent_ps == TSS_PS_TYPE_SYSTEM) + cache_flags |= CACHE_FLAG_PARENT_PS_SYSTEM; + + /* Unload the blob to get the public key */ + offset = 0; + if ((rc = UnloadBlob_TSS_KEY(&offset, key_blob, &key))) + return rc; + + pub_key_size = key.pubKey.keyLength; + + if ((rc = write_key_init(fd, pub_key_size, key_blob_size, vendor_size)) < 0) + goto done; + + /* offset now holds the number of bytes from the beginning of the file + * the key will be stored at + */ + offset = rc; + +#ifdef TSS_DEBUG + if (offset == 0) + LogDebug("ERROR: key being written with offset 0!!"); +#endif + + /* [TSS_UUID uuid0 ] yes */ + if ((rc = write_data(fd, (void *)uuid, sizeof(TSS_UUID)))) { + LogError("%s", __FUNCTION__); + goto done; + } + + /* [TSS_UUID uuid_parent0 ] yes */ + if ((rc = write_data(fd, (void *)parent_uuid, sizeof(TSS_UUID)))) { + LogError("%s", __FUNCTION__); + goto done; + } + + /* [UINT16 pub_data_size0 ] yes */ + pub_key_size = LE_16(pub_key_size); + if ((rc = write_data(fd, &pub_key_size, sizeof(UINT16)))) { + LogError("%s", __FUNCTION__); + goto done; + } + /* Swap it back for later */ + pub_key_size = LE_16(pub_key_size); + + /* [UINT16 blob_size0 ] yes */ + key_blob_size = LE_16(key_blob_size); + if ((rc = write_data(fd, &key_blob_size, sizeof(UINT16)))) { + LogError("%s", __FUNCTION__); + goto done; + } + /* Swap it back for later */ + key_blob_size = LE_16(key_blob_size); + + /* [UINT32 vendor_data_size0 ] yes */ + vendor_size = LE_32(vendor_size); + if ((rc = write_data(fd, &vendor_size, sizeof(UINT32)))) { + LogError("%s", __FUNCTION__); + goto done; + } + /* Swap it back for later */ + vendor_size = LE_32(vendor_size); + + /* [UINT16 cache_flags0 ] yes */ + cache_flags = LE_16(cache_flags); + if ((rc = write_data(fd, &cache_flags, sizeof(UINT16)))) { + LogError("%s", __FUNCTION__); + goto done; + } + /* Swap it back for later */ + cache_flags = LE_16(cache_flags); + + /* [BYTE[] pub_data0 ] no */ + if ((rc = write_data(fd, (void *)key.pubKey.key, pub_key_size))) { + LogError("%s", __FUNCTION__); + goto done; + } + + /* [BYTE[] blob0 ] no */ + if ((rc = write_data(fd, (void *)key_blob, key_blob_size))) { + LogError("%s", __FUNCTION__); + goto done; + } + + /* [BYTE[] vendor_data0 ] no */ + if (vendor_size > 0) { + if ((rc = write_data(fd, (void *)vendor_data, vendor_size))) { + LogError("%s", __FUNCTION__); + goto done; + } + } + + if ((rc = cache_key((UINT32)offset, cache_flags, uuid, parent_uuid, pub_key_size, + key_blob_size, vendor_size))) + goto done; +done: + destroy_key_refs(&key); + + return rc; +} + +TSS_RESULT +psfile_remove_key(int fd, struct key_disk_cache *c) +{ + TSS_RESULT result; + UINT32 head_offset = 0, tail_offset, num_keys; + BYTE buf[4096]; + struct stat stat_buf; + int rc, size = 0; + + if ((rc = fstat(fd, &stat_buf)) != 0) { + LogError("fstat: %s", strerror(errno)); + return TSS_E_INTERNAL_ERROR; + } + + /* head_offset is the offset the beginning of the key */ + head_offset = TSSPS_UUID_OFFSET(c); + + /* tail_offset is the offset the beginning of the next key */ + tail_offset = TSSPS_VENDOR_DATA_OFFSET(c) + c->vendor_data_size; + + rc = lseek(fd, tail_offset, SEEK_SET); + if (rc == ((off_t) - 1)) { + LogError("lseek: %s", strerror(errno)); + return TCSERR(TSS_E_INTERNAL_ERROR); + } + + /* read in from tail, write out to head to fill the gap */ + while ((rc = read(fd, buf, sizeof(buf))) > 0) { + size = rc; + tail_offset += size; + + /* set the file pointer to where we want to write */ + rc = lseek(fd, head_offset, SEEK_SET); + if (rc == ((off_t) - 1)) { + LogError("lseek: %s", strerror(errno)); + return TCSERR(TSS_E_INTERNAL_ERROR); + } + + /* write the data */ + if ((result = write_data(fd, (void *)buf, size))) { + LogError("%s", __FUNCTION__); + return result; + } + head_offset += size; + + /* set the file pointer to where we want to read in the next + * loop */ + rc = lseek(fd, tail_offset, SEEK_SET); + if (rc == ((off_t) - 1)) { + LogError("lseek: %s", strerror(errno)); + return TCSERR(TSS_E_INTERNAL_ERROR); + } + } + + if (rc < 0) { + LogError("read: %s", strerror(errno)); + return TCSERR(TSS_E_INTERNAL_ERROR); + } + + /* set the file pointer to where we want to write */ + rc = lseek(fd, head_offset, SEEK_SET); + if (rc == ((off_t) - 1)) { + LogError("lseek: %s", strerror(errno)); + return TCSERR(TSS_E_INTERNAL_ERROR); + } + + /* head_offset now contains a pointer to where we want to truncate the + * file. Zero out the old tail end of the file and truncate it. */ + + memset(buf, 0, sizeof(buf)); + + /* Zero out the old tail end of the file */ + if ((result = write_data(fd, (void *)buf, tail_offset - head_offset))) { + LogError("%s", __FUNCTION__); + return result; + } + + if ((rc = ftruncate(fd, head_offset)) < 0) { + LogError("ftruncate: %s", strerror(errno)); + return TCSERR(TSS_E_INTERNAL_ERROR); + } + + /* we succeeded in removing a key from the disk. Decrement the number + * of keys in the file */ + rc = lseek(fd, TSSPS_NUM_KEYS_OFFSET, SEEK_SET); + if (rc == ((off_t) - 1)) { + LogError("lseek: %s", strerror(errno)); + return TCSERR(TSS_E_INTERNAL_ERROR); + } + + rc = read(fd, &num_keys, sizeof(UINT32)); + num_keys = LE_32(num_keys); + if (rc != sizeof(UINT32)) { + LogError("read of %zd bytes: %s", sizeof(UINT32), strerror(errno)); + return TCSERR(TSS_E_INTERNAL_ERROR); + } + + rc = lseek(fd, TSSPS_NUM_KEYS_OFFSET, SEEK_SET); + if (rc == ((off_t) - 1)) { + LogError("lseek: %s", strerror(errno)); + return TCSERR(TSS_E_INTERNAL_ERROR); + } + + /* decrement, then write back out to disk */ + num_keys--; + + num_keys = LE_32(num_keys); + if ((result = write_data(fd, (void *)&num_keys, sizeof(UINT32)))) { + LogError("%s", __FUNCTION__); + return result; + } + + return TSS_SUCCESS; +} |