blob: ad5c79ae4f6ad6229a1f2c0a8e7340a77695629f [file] [log] [blame]
/*
* Licensed Materials - Property of IBM
*
* trousers - An open source TCG Software Stack
*
* (C) Copyright International Business Machines Corp. 2004-2007
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include "trousers/tss.h"
#include "trousers/trousers.h"
#include "trousers_types.h"
#include "spi_utils.h"
#include "tsplog.h"
#include "obj.h"
UINT32 nextObjectHandle = 0xC0000000;
MUTEX_DECLARE_INIT(handle_lock);
TPM_LIST_DECLARE;
CONTEXT_LIST_DECLARE;
HASH_LIST_DECLARE;
PCRS_LIST_DECLARE;
POLICY_LIST_DECLARE;
RSAKEY_LIST_DECLARE;
ENCDATA_LIST_DECLARE;
DAACRED_LIST_DECLARE;
DAAARAKEY_LIST_DECLARE;
DAAISSUERKEY_LIST_DECLARE;
NVSTORE_LIST_DECLARE;
DELFAMILY_LIST_DECLARE;
MIGDATA_LIST_DECLARE;
void
list_init(struct obj_list *list)
{
list->head = NULL;
MUTEX_INIT(list->lock);
}
void
__tspi_obj_list_init()
{
TPM_LIST_INIT();
CONTEXT_LIST_INIT();
HASH_LIST_INIT();
PCRS_LIST_INIT();
POLICY_LIST_INIT();
RSAKEY_LIST_INIT();
ENCDATA_LIST_INIT();
DAACRED_LIST_INIT();
DAAARAKEY_LIST_INIT();
DAAISSUERKEY_LIST_INIT();
NVSTORE_LIST_INIT();
DELFAMILY_LIST_INIT();
MIGDATA_LIST_INIT();
}
TSS_HOBJECT
obj_get_next_handle()
{
MUTEX_LOCK(handle_lock);
/* return any object handle except NULL_HOBJECT */
do {
nextObjectHandle++;
} while (nextObjectHandle == NULL_HOBJECT);
MUTEX_UNLOCK(handle_lock);
return nextObjectHandle;
}
/* search through the provided list for an object with handle matching
* @handle. If found, return a pointer to the object with the list
* locked, else return NULL. To release the lock, caller should
* call obj_list_put() after manipulating the object.
*/
struct tsp_object *
obj_list_get_obj(struct obj_list *list, UINT32 handle)
{
struct tsp_object *obj;
MUTEX_LOCK(list->lock);
for (obj = list->head; obj; obj = obj->next) {
if (obj->handle == handle)
break;
}
if (obj == NULL)
MUTEX_UNLOCK(list->lock);
return obj;
}
/* search through the provided list for an object with TSP context
* matching @tspContext. If found, return a pointer to the object
* with the list locked, else return NULL. To release the lock,
* caller should call obj_list_put() after manipulating the object.
*/
struct tsp_object *
obj_list_get_tspcontext(struct obj_list *list, UINT32 tspContext)
{
struct tsp_object *obj;
MUTEX_LOCK(list->lock);
for (obj = list->head; obj; obj = obj->next) {
if (obj->tspContext == tspContext)
break;
}
return obj;
}
/* release a list whose handle was returned by obj_list_get_obj() */
void
obj_list_put(struct obj_list *list)
{
MUTEX_UNLOCK(list->lock);
}
TSS_RESULT
obj_list_add(struct obj_list *list, UINT32 tsp_context, TSS_FLAG flags, void *data,
TSS_HOBJECT *phObject)
{
struct tsp_object *new_obj, *tmp;
new_obj = calloc(1, sizeof(struct tsp_object));
if (new_obj == NULL) {
LogError("malloc of %zd bytes failed.", sizeof(struct tsp_object));
return TSPERR(TSS_E_OUTOFMEMORY);
}
new_obj->handle = obj_get_next_handle();
new_obj->flags = flags;
new_obj->data = data;
if (list == &context_list)
new_obj->tspContext = new_obj->handle;
else
new_obj->tspContext = tsp_context;
MUTEX_LOCK(list->lock);
if (list->head == NULL) {
list->head = new_obj;
} else {
tmp = list->head;
list->head = new_obj;
new_obj->next = tmp;
}
MUTEX_UNLOCK(list->lock);
*phObject = new_obj->handle;
return TSS_SUCCESS;
}
TSS_RESULT
obj_list_remove(struct obj_list *list, void (*freeFcn)(void *), TSS_HOBJECT hObject, TSS_HCONTEXT tspContext)
{
struct tsp_object *obj, *prev = NULL;
MUTEX_LOCK(list->lock);
for (obj = list->head; obj; prev = obj, obj = obj->next) {
if (obj->handle == hObject) {
/* validate tspContext */
if (obj->tspContext != tspContext)
break;
(*freeFcn)(obj->data);
if (prev)
prev->next = obj->next;
else
list->head = obj->next;
free(obj);
MUTEX_UNLOCK(list->lock);
return TSS_SUCCESS;
}
}
MUTEX_UNLOCK(list->lock);
return TSPERR(TSS_E_INVALID_HANDLE);
}
/* a generic routine for removing all members of a list who's tsp context
* matches @tspContext */
void
obj_list_close(struct obj_list *list, void (*freeFcn)(void *), TSS_HCONTEXT tspContext)
{
struct tsp_object *index;
struct tsp_object *next = NULL;
struct tsp_object *toKill;
struct tsp_object *prev = NULL;
MUTEX_LOCK(list->lock);
for (index = list->head; index; ) {
next = index->next;
if (index->tspContext == tspContext) {
toKill = index;
if (prev == NULL) {
list->head = toKill->next;
} else {
prev->next = toKill->next;
}
(*freeFcn)(toKill->data);
free(toKill);
index = next;
} else {
prev = index;
index = next;
}
}
MUTEX_UNLOCK(list->lock);
}
void
obj_close_context(TSS_HCONTEXT tspContext)
{
TPM_LIST_CLOSE(tspContext);
CONTEXT_LIST_CLOSE(tspContext);
HASH_LIST_CLOSE(tspContext);
PCRS_LIST_CLOSE(tspContext);
POLICY_LIST_CLOSE(tspContext);
RSAKEY_LIST_CLOSE(tspContext);
ENCDATA_LIST_CLOSE(tspContext);
DAACRED_LIST_CLOSE(tspContext);
DAAARAKEY_LIST_CLOSE(tspContext);
DAAISSUERKEY_LIST_CLOSE(tspContext);
NVSTORE_LIST_CLOSE(tspContext);
DELFAMILY_LIST_CLOSE(tspContext);
MIGDATA_LIST_CLOSE(tspContext);
}
/* When a policy object is closed, all references to it must be removed. This function
* calls the object specific routines for each working object type to remove all refs to the
* policy */
void
obj_lists_remove_policy_refs(TSS_HPOLICY hPolicy, TSS_HCONTEXT tspContext)
{
obj_rsakey_remove_policy_refs(hPolicy, tspContext);
obj_encdata_remove_policy_refs(hPolicy, tspContext);
obj_tpm_remove_policy_refs(hPolicy, tspContext);
}
/* search all key lists (right now only RSA keys exist) looking for a TCS key handle, when
* found, return the hash of its TPM_STORE_PUBKEY structure */
TSS_RESULT
obj_tcskey_get_pubkeyhash(TCS_KEY_HANDLE hKey, BYTE *pubKeyHash)
{
struct tsp_object *obj;
struct obj_list *list = &rsakey_list;
struct tr_rsakey_obj *rsakey = NULL;
TSS_RESULT result = TSS_SUCCESS;
Trspi_HashCtx hashCtx;
MUTEX_LOCK(list->lock);
for (obj = list->head; obj; obj = obj->next) {
rsakey = (struct tr_rsakey_obj *)obj->data;
if (rsakey->tcsHandle == hKey)
break;
}
if (obj == NULL || rsakey == NULL) {
MUTEX_UNLOCK(list->lock);
return TSPERR(TSS_E_KEY_NOT_LOADED);
}
result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
result |= Trspi_Hash_STORE_PUBKEY(&hashCtx, &rsakey->key.pubKey);
if ((result |= Trspi_HashFinal(&hashCtx, pubKeyHash)))
result = TSPERR(TSS_E_INTERNAL_ERROR);
MUTEX_UNLOCK(list->lock);
return result;
}