summaryrefslogtreecommitdiff
path: root/src/tcs/tcs_key_ps.c
diff options
context:
space:
mode:
authorIgor Pashev <pashev.igor@gmail.com>2012-11-25 14:36:20 +0000
committerIgor Pashev <pashev.igor@gmail.com>2012-11-25 14:36:20 +0000
commitc3649a2def02c41d837ae1f79dda729ccb91e677 (patch)
treebea46dff212fdef977fe9094a70a939e8cc21885 /src/tcs/tcs_key_ps.c
downloadtrousers-upstream.tar.gz
Imported Upstream version 0.3.9upstream/0.3.9upstream
Diffstat (limited to 'src/tcs/tcs_key_ps.c')
-rw-r--r--src/tcs/tcs_key_ps.c367
1 files changed, 367 insertions, 0 deletions
diff --git a/src/tcs/tcs_key_ps.c b/src/tcs/tcs_key_ps.c
new file mode 100644
index 0000000..0ea28c1
--- /dev/null
+++ b/src/tcs/tcs_key_ps.c
@@ -0,0 +1,367 @@
+
+/*
+ * Licensed Materials - Property of IBM
+ *
+ * trousers - An open source TCG Software Stack
+ *
+ * (C) Copyright International Business Machines Corp. 2004-2006
+ *
+ */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "trousers/tss.h"
+#include "trousers_types.h"
+#include "trousers_types.h"
+#include "tcs_tsp.h"
+#include "tcs_utils.h"
+#include "tcs_int_literals.h"
+#include "capabilities.h"
+#include "tcslog.h"
+#include "tcsps.h"
+#include "req_mgr.h"
+
+
+TSS_RESULT
+ps_init_disk_cache(void)
+{
+ int fd;
+ TSS_RESULT rc;
+
+ MUTEX_INIT(disk_cache_lock);
+
+ if ((fd = get_file()) < 0)
+ return TCSERR(TSS_E_INTERNAL_ERROR);
+
+ if ((rc = init_disk_cache(fd)))
+ return rc;
+
+ /* this is temporary, to clear out a PS file from trousers
+ * versions before 0.2.1 */
+ if ((rc = clean_disk_cache(fd)))
+ return rc;
+
+ put_file(fd);
+ return TSS_SUCCESS;
+}
+
+void
+ps_close_disk_cache(void)
+{
+ int fd;
+
+ if ((fd = get_file()) < 0) {
+ LogError("get_file() failed while trying to close disk cache.");
+ return;
+ }
+
+ close_disk_cache(fd);
+
+ put_file(fd);
+}
+
+TSS_BOOL
+ps_is_key_registered(TCPA_STORE_PUBKEY *pub)
+{
+ TSS_UUID *uuid;
+ int fd;
+ TSS_RESULT rc;
+ TSS_BOOL is_reg = FALSE;
+
+ if ((fd = get_file()) < 0)
+ return FALSE;
+
+ if ((rc = psfile_get_uuid_by_pub(fd, pub, &uuid))) {
+ put_file(fd);
+ return FALSE;
+ }
+
+ put_file(fd);
+
+ if ((isUUIDRegistered(uuid, &is_reg)))
+ is_reg = FALSE;
+
+ free(uuid);
+ return is_reg;
+}
+
+TSS_RESULT
+getParentUUIDByUUID(TSS_UUID *uuid, TSS_UUID *ret_uuid)
+{
+ struct key_disk_cache *disk_tmp;
+
+ /* check the registered key disk cache */
+ MUTEX_LOCK(disk_cache_lock);
+
+ for (disk_tmp = key_disk_cache_head; disk_tmp; disk_tmp = disk_tmp->next) {
+ if ((disk_tmp->flags & CACHE_FLAG_VALID) &&
+ !memcmp(&disk_tmp->uuid, uuid, sizeof(TSS_UUID))) {
+ memcpy(ret_uuid, &disk_tmp->parent_uuid, sizeof(TSS_UUID));
+ MUTEX_UNLOCK(disk_cache_lock);
+ return TSS_SUCCESS;
+ }
+ }
+ MUTEX_UNLOCK(disk_cache_lock);
+
+ return TCSERR(TSS_E_FAIL);
+}
+
+TSS_RESULT
+isUUIDRegistered(TSS_UUID *uuid, TSS_BOOL *is_reg)
+{
+ struct key_disk_cache *disk_tmp;
+
+ /* check the registered key disk cache */
+ MUTEX_LOCK(disk_cache_lock);
+
+ for (disk_tmp = key_disk_cache_head; disk_tmp; disk_tmp = disk_tmp->next) {
+ if ((disk_tmp->flags & CACHE_FLAG_VALID) &&
+ !memcmp(&disk_tmp->uuid, uuid, sizeof(TSS_UUID))) {
+ *is_reg = TRUE;
+ MUTEX_UNLOCK(disk_cache_lock);
+ return TSS_SUCCESS;
+ }
+ }
+ MUTEX_UNLOCK(disk_cache_lock);
+ *is_reg = FALSE;
+
+ return TSS_SUCCESS;
+}
+
+void
+disk_cache_shift(struct key_disk_cache *c)
+{
+ UINT32 key_size, offset;
+ struct key_disk_cache *tmp = key_disk_cache_head;
+
+ /* offset is the end of the key location in the file */
+ offset = TSSPS_VENDOR_DATA_OFFSET(c) + c->vendor_data_size;
+ /* key_size is the size of the key entry on disk */
+ key_size = offset - TSSPS_UUID_OFFSET(c);
+
+ /* for each disk cache entry, if the data for that entry is at an
+ * offset greater than the key beign removed, then the entry needs to
+ * be decremented by the size of key's disk footprint (the key_size
+ * variable) */
+ while (tmp) {
+ if (tmp->offset >= offset) {
+ tmp->offset -= key_size;
+ }
+
+ tmp = tmp->next;
+ }
+}
+
+TSS_RESULT
+ps_remove_key(TSS_UUID *uuid)
+{
+ struct key_disk_cache *tmp, *prev = NULL;
+ TSS_RESULT rc;
+ int fd = -1;
+
+ MUTEX_LOCK(disk_cache_lock);
+ tmp = key_disk_cache_head;
+
+ for (; tmp; prev = tmp, tmp = tmp->next) {
+ if ((tmp->flags & CACHE_FLAG_VALID) &&
+ !memcmp(uuid, &tmp->uuid, sizeof(TSS_UUID))) {
+ if ((fd = get_file()) < 0) {
+ rc = TCSERR(TSS_E_INTERNAL_ERROR);
+ break;
+ }
+
+ rc = psfile_remove_key(fd, tmp);
+
+ put_file(fd);
+
+ /* if moving the file contents around succeeded, then
+ * change the offsets of the keys in the cache in
+ * mem_cache_shift() and remove the key from the
+ * cache. */
+ if (!rc) {
+ disk_cache_shift(tmp);
+ if (prev) {
+ prev->next = tmp->next;
+ } else {
+ key_disk_cache_head = tmp->next;
+ }
+ free(tmp);
+ } else {
+ LogError("Error removing registered key.");
+ }
+
+ MUTEX_UNLOCK(disk_cache_lock);
+ return rc;
+ }
+ }
+
+ MUTEX_UNLOCK(disk_cache_lock);
+
+ return TCSERR(TCSERR(TSS_E_PS_KEY_NOTFOUND));
+}
+
+/*
+ * temporary function to clean out blanked keys from a PS file from
+ * trousers 0.2.0 and before
+ */
+TSS_RESULT
+clean_disk_cache(int fd)
+{
+ struct key_disk_cache *tmp, *prev = NULL;
+ TSS_RESULT rc;
+
+ MUTEX_LOCK(disk_cache_lock);
+ tmp = key_disk_cache_head;
+
+ for (; tmp; prev = tmp, tmp = tmp->next) {
+ if (!(tmp->flags & CACHE_FLAG_VALID)) {
+ rc = psfile_remove_key(fd, tmp);
+
+ /* if moving the file contents around succeeded, then
+ * change the offsets of the keys in the cache in
+ * mem_cache_shift() and remove the key from the
+ * cache. */
+ if (!rc) {
+ disk_cache_shift(tmp);
+ if (prev) {
+ prev->next = tmp->next;
+ }
+ free(tmp);
+ } else {
+ LogError("Error removing blank key.");
+ }
+
+ MUTEX_UNLOCK(disk_cache_lock);
+ return rc;
+ }
+ }
+
+ MUTEX_UNLOCK(disk_cache_lock);
+ return TSS_SUCCESS;
+}
+
+TSS_RESULT
+ps_get_key_by_uuid(TSS_UUID *uuid, BYTE *blob, UINT16 *blob_size)
+{
+ int fd = -1;
+ TSS_RESULT rc = TSS_SUCCESS;
+
+ if ((fd = get_file()) < 0)
+ return TCSERR(TSS_E_INTERNAL_ERROR);
+
+ rc = psfile_get_key_by_uuid(fd, uuid, blob, blob_size);
+
+ put_file(fd);
+ return rc;
+}
+
+TSS_RESULT
+ps_get_key_by_cache_entry(struct key_disk_cache *c, BYTE *blob, UINT16 *blob_size)
+{
+ int fd = -1;
+ TSS_RESULT rc = TSS_SUCCESS;
+
+ if ((fd = get_file()) < 0)
+ return TCSERR(TSS_E_INTERNAL_ERROR);
+
+ rc = psfile_get_key_by_cache_entry(fd, c, blob, blob_size);
+
+ put_file(fd);
+ return rc;
+}
+
+TSS_RESULT
+ps_get_vendor_data(struct key_disk_cache *c, UINT32 *size, BYTE **data)
+{
+ int fd = -1;
+ TSS_RESULT rc;
+
+ if ((fd = get_file()) < 0)
+ return TCSERR(TSS_E_INTERNAL_ERROR);
+
+ rc = psfile_get_vendor_data(fd, c, size, data);
+
+ put_file(fd);
+ return rc;
+}
+
+TSS_RESULT
+ps_is_pub_registered(TCPA_STORE_PUBKEY *key)
+{
+ int fd = -1;
+ TSS_BOOL answer;
+
+ if ((fd = get_file()) < 0)
+ return FALSE;
+
+ if (psfile_is_pub_registered(fd, key, &answer)) {
+ put_file(fd);
+ return FALSE;
+ }
+
+ put_file(fd);
+ return answer;
+}
+
+TSS_RESULT
+ps_get_uuid_by_pub(TCPA_STORE_PUBKEY *pub, TSS_UUID **uuid)
+{
+ int fd = -1;
+ TSS_RESULT ret;
+
+ if ((fd = get_file()) < 0)
+ return TCSERR(TSS_E_INTERNAL_ERROR);
+
+ ret = psfile_get_uuid_by_pub(fd, pub, uuid);
+
+ put_file(fd);
+ return ret;
+}
+
+TSS_RESULT
+ps_get_key_by_pub(TCPA_STORE_PUBKEY *pub, UINT32 *size, BYTE **key)
+{
+ int fd = -1;
+ TSS_RESULT ret;
+
+ if ((fd = get_file()) < 0)
+ return TCSERR(TSS_E_INTERNAL_ERROR);
+
+ ret = psfile_get_key_by_pub(fd, pub, size, key);
+
+ put_file(fd);
+ return ret;
+}
+
+TSS_RESULT
+ps_write_key(TSS_UUID *uuid, TSS_UUID *parent_uuid, BYTE *vendor_data,
+ UINT32 vendor_size, BYTE *blob, UINT32 blob_size)
+{
+ int fd = -1;
+ TSS_RESULT rc;
+ UINT32 parent_ps;
+ UINT16 short_blob_size = (UINT16)blob_size;
+
+ if ((fd = get_file()) < 0)
+ return TCSERR(TSS_E_INTERNAL_ERROR);
+
+ /* this case needed for PS file init. if the key file doesn't yet exist, the
+ * psfile_get_parent_ps_type_by_uuid() call would fail. */
+ if (!memcmp(parent_uuid, &NULL_UUID, sizeof(TSS_UUID))) {
+ parent_ps = TSS_PS_TYPE_SYSTEM;
+ } else {
+ if ((rc = psfile_get_ps_type_by_uuid(fd, parent_uuid, &parent_ps)))
+ return rc;
+ }
+
+ rc = psfile_write_key(fd, uuid, parent_uuid, &parent_ps, vendor_data,
+ vendor_size, blob, short_blob_size);
+
+ put_file(fd);
+ return TSS_SUCCESS;
+}