/* * Licensed Materials - Property of IBM * * trousers - An open source TCG Software Stack * * (C) Copyright International Business Machines Corp. 2004-2006 * */ #include #include #include #include #include "trousers/tss.h" #include "trousers_types.h" #include "tcs_context.h" #include "tcs_tsp.h" #include "tcs_utils.h" #include "tcs_int_literals.h" #include "capabilities.h" #include "tcslog.h" MUTEX_DECLARE_EXTERN(tcs_ctx_lock); /* runs through the list of all keys loaded by context c and decrements * their ref count by 1, then free's their structures. */ void ctx_ref_count_keys(struct tcs_context *c) { struct keys_loaded *cur, *prev; if (c == NULL) return; cur = prev = c->keys; while (cur != NULL) { key_mgr_dec_ref_count(cur->key_handle); cur = cur->next; free(prev); prev = cur; } } /* Traverse loaded keys list and if matching key handle is found return TRUE else return FALSE */ TSS_BOOL ctx_has_key_loaded(TCS_CONTEXT_HANDLE ctx_handle, TCS_KEY_HANDLE key_handle) { struct tcs_context *c; struct keys_loaded *k = NULL; MUTEX_LOCK(tcs_ctx_lock); c = get_context(ctx_handle); if (c == NULL) { MUTEX_UNLOCK(tcs_ctx_lock); return FALSE; } k = c->keys; while (k != NULL) { if (k->key_handle == key_handle) { MUTEX_UNLOCK(tcs_ctx_lock); return TRUE; } k = k->next; } MUTEX_UNLOCK(tcs_ctx_lock); return FALSE; } /* Traverse loaded keys list and if matching key handle is found remove it */ TSS_RESULT ctx_remove_key_loaded(TCS_CONTEXT_HANDLE ctx_handle, TCS_KEY_HANDLE key_handle) { struct tcs_context *c; struct keys_loaded *cur, *prev; MUTEX_LOCK(tcs_ctx_lock); c = get_context(ctx_handle); if (c == NULL) { MUTEX_UNLOCK(tcs_ctx_lock); return TCSERR(TCS_E_INVALID_CONTEXTHANDLE); } for (prev = cur = c->keys; cur; prev = cur, cur = cur->next) { if (cur->key_handle == key_handle) { if (cur == c->keys) c->keys = cur->next; else prev->next = cur->next; free(cur); MUTEX_UNLOCK(tcs_ctx_lock); return TCS_SUCCESS; } } MUTEX_UNLOCK(tcs_ctx_lock); return TCSERR(TCS_E_INVALID_KEY); } /* make a new entry in the per-context list of loaded keys. If the list already * contains a pointer to the key in memory, just return success. */ TSS_RESULT ctx_mark_key_loaded(TCS_CONTEXT_HANDLE ctx_handle, TCS_KEY_HANDLE key_handle) { struct tcs_context *c; struct keys_loaded *k = NULL, *new; TSS_RESULT result; MUTEX_LOCK(tcs_ctx_lock); c = get_context(ctx_handle); if (c != NULL) { k = c->keys; while (k != NULL) { if (k->key_handle == key_handle) { /* we've previously created a pointer to key_handle in the global * list of loaded keys and incremented that key's reference count, * so there's no need to do anything. */ result = TSS_SUCCESS; break; } k = k->next; } } else { MUTEX_UNLOCK(tcs_ctx_lock); return TCSERR(TSS_E_FAIL); } /* if we have no record of this key being loaded by this context, create a new * entry and increment the key's reference count in the global list. */ if (k == NULL) { new = calloc(1, sizeof(struct keys_loaded)); if (new == NULL) { LogError("malloc of %zd bytes failed.", sizeof(struct keys_loaded)); MUTEX_UNLOCK(tcs_ctx_lock); return TCSERR(TSS_E_OUTOFMEMORY); } new->key_handle = key_handle; new->next = c->keys; c->keys = new; result = key_mgr_inc_ref_count(new->key_handle); } MUTEX_UNLOCK(tcs_ctx_lock); return result; }