Home | History | Annotate | Line # | Download | only in tspi
      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-2007
      8  *
      9  */
     10 
     11 
     12 #include <stdlib.h>
     13 #include <stdio.h>
     14 #include <errno.h>
     15 #include <string.h>
     16 
     17 #include "trousers/tss.h"
     18 #include "trousers/trousers.h"
     19 #include "trousers_types.h"
     20 #include "spi_utils.h"
     21 #include "tsplog.h"
     22 #include "obj.h"
     23 
     24 UINT32 nextObjectHandle = 0xC0000000;
     25 
     26 MUTEX_DECLARE_INIT(handle_lock);
     27 
     28 TPM_LIST_DECLARE;
     29 CONTEXT_LIST_DECLARE;
     30 HASH_LIST_DECLARE;
     31 PCRS_LIST_DECLARE;
     32 POLICY_LIST_DECLARE;
     33 RSAKEY_LIST_DECLARE;
     34 ENCDATA_LIST_DECLARE;
     35 DAACRED_LIST_DECLARE;
     36 DAAARAKEY_LIST_DECLARE;
     37 DAAISSUERKEY_LIST_DECLARE;
     38 NVSTORE_LIST_DECLARE;
     39 DELFAMILY_LIST_DECLARE;
     40 MIGDATA_LIST_DECLARE;
     41 
     42 static void
     43 tspi_list_init(struct obj_list *list)
     44 {
     45 	list->head = NULL;
     46 	MUTEX_INIT(list->lock);
     47 }
     48 
     49 void
     50 __tspi_obj_list_init()
     51 {
     52 	TPM_LIST_INIT();
     53 	CONTEXT_LIST_INIT();
     54 	HASH_LIST_INIT();
     55 	PCRS_LIST_INIT();
     56 	POLICY_LIST_INIT();
     57 	RSAKEY_LIST_INIT();
     58 	ENCDATA_LIST_INIT();
     59 	DAACRED_LIST_INIT();
     60 	DAAARAKEY_LIST_INIT();
     61 	DAAISSUERKEY_LIST_INIT();
     62 	NVSTORE_LIST_INIT();
     63 	DELFAMILY_LIST_INIT();
     64 	MIGDATA_LIST_INIT();
     65 }
     66 
     67 TSS_HOBJECT
     68 obj_get_next_handle()
     69 {
     70 	MUTEX_LOCK(handle_lock);
     71 
     72 	/* return any object handle except NULL_HOBJECT */
     73 	do {
     74 		nextObjectHandle++;
     75 	} while (nextObjectHandle == NULL_HOBJECT);
     76 
     77 	MUTEX_UNLOCK(handle_lock);
     78 
     79 	return nextObjectHandle;
     80 }
     81 
     82 /* search through the provided list for an object with handle matching
     83  * @handle. If found, return a pointer to the object with the list
     84  * locked, else return NULL.  To release the lock, caller should
     85  * call obj_list_put() after manipulating the object.
     86  */
     87 struct tsp_object *
     88 obj_list_get_obj(struct obj_list *list, UINT32 handle)
     89 {
     90 	struct tsp_object *obj;
     91 
     92 	MUTEX_LOCK(list->lock);
     93 
     94 	for (obj = list->head; obj; obj = obj->next) {
     95 		if (obj->handle == handle)
     96 			break;
     97 	}
     98 
     99 	if (obj == NULL)
    100 		MUTEX_UNLOCK(list->lock);
    101 
    102 	return obj;
    103 }
    104 
    105 /* search through the provided list for an object with TSP context
    106  * matching @tspContext. If found, return a pointer to the object
    107  * with the list locked, else return NULL.  To release the lock,
    108  * caller should call obj_list_put() after manipulating the object.
    109  */
    110 struct tsp_object *
    111 obj_list_get_tspcontext(struct obj_list *list, UINT32 tspContext)
    112 {
    113 	struct tsp_object *obj;
    114 
    115 	MUTEX_LOCK(list->lock);
    116 
    117 	for (obj = list->head; obj; obj = obj->next) {
    118 		if (obj->tspContext == tspContext)
    119 			break;
    120 	}
    121 
    122 	return obj;
    123 }
    124 
    125 /* release a list whose handle was returned by obj_list_get_obj() */
    126 void
    127 obj_list_put(struct obj_list *list)
    128 {
    129 	MUTEX_UNLOCK(list->lock);
    130 }
    131 
    132 TSS_RESULT
    133 obj_list_add(struct obj_list *list, UINT32 tsp_context, TSS_FLAG flags, void *data,
    134 	     TSS_HOBJECT *phObject)
    135 {
    136         struct tsp_object *new_obj, *tmp;
    137 
    138         new_obj = calloc(1, sizeof(struct tsp_object));
    139         if (new_obj == NULL) {
    140 		LogError("malloc of %zd bytes failed.", sizeof(struct tsp_object));
    141                 return TSPERR(TSS_E_OUTOFMEMORY);
    142         }
    143 
    144         new_obj->handle = obj_get_next_handle();
    145 	new_obj->flags = flags;
    146         new_obj->data = data;
    147 
    148 	if (list == &context_list)
    149 		new_obj->tspContext = new_obj->handle;
    150 	else
    151 		new_obj->tspContext = tsp_context;
    152 
    153         MUTEX_LOCK(list->lock);
    154 
    155         if (list->head == NULL) {
    156                 list->head = new_obj;
    157         } else {
    158                 tmp = list->head;
    159                 list->head = new_obj;
    160                 new_obj->next = tmp;
    161         }
    162 
    163         MUTEX_UNLOCK(list->lock);
    164 
    165         *phObject = new_obj->handle;
    166 
    167         return TSS_SUCCESS;
    168 }
    169 
    170 TSS_RESULT
    171 obj_list_remove(struct obj_list *list, void (*freeFcn)(void *), TSS_HOBJECT hObject, TSS_HCONTEXT tspContext)
    172 {
    173 	struct tsp_object *obj, *prev = NULL;
    174 
    175 	MUTEX_LOCK(list->lock);
    176 
    177 	for (obj = list->head; obj; prev = obj, obj = obj->next) {
    178 		if (obj->handle == hObject) {
    179 			/* validate tspContext */
    180 			if (obj->tspContext != tspContext)
    181 				break;
    182 
    183 			(*freeFcn)(obj->data);
    184 
    185 			if (prev)
    186 				prev->next = obj->next;
    187 			else
    188 				list->head = obj->next;
    189 			free(obj);
    190 
    191 			MUTEX_UNLOCK(list->lock);
    192 			return TSS_SUCCESS;
    193 		}
    194 	}
    195 
    196 	MUTEX_UNLOCK(list->lock);
    197 
    198 	return TSPERR(TSS_E_INVALID_HANDLE);
    199 }
    200 
    201 /* a generic routine for removing all members of a list who's tsp context
    202  * matches @tspContext */
    203 void
    204 obj_list_close(struct obj_list *list, void (*freeFcn)(void *), TSS_HCONTEXT tspContext)
    205 {
    206 	struct tsp_object *index;
    207 	struct tsp_object *next = NULL;
    208 	struct tsp_object *toKill;
    209 	struct tsp_object *prev = NULL;
    210 
    211 	MUTEX_LOCK(list->lock);
    212 
    213 	for (index = list->head; index; ) {
    214 		next = index->next;
    215 		if (index->tspContext == tspContext) {
    216 			toKill = index;
    217 			if (prev == NULL) {
    218 				list->head = toKill->next;
    219 			} else {
    220 				prev->next = toKill->next;
    221 			}
    222 
    223 			(*freeFcn)(toKill->data);
    224 			free(toKill);
    225 
    226 			index = next;
    227 		} else {
    228 			prev = index;
    229 			index = next;
    230 		}
    231 	}
    232 
    233 	MUTEX_UNLOCK(list->lock);
    234 }
    235 
    236 void
    237 obj_close_context(TSS_HCONTEXT tspContext)
    238 {
    239 	TPM_LIST_CLOSE(tspContext);
    240 	CONTEXT_LIST_CLOSE(tspContext);
    241 	HASH_LIST_CLOSE(tspContext);
    242 	PCRS_LIST_CLOSE(tspContext);
    243 	POLICY_LIST_CLOSE(tspContext);
    244 	RSAKEY_LIST_CLOSE(tspContext);
    245 	ENCDATA_LIST_CLOSE(tspContext);
    246 	DAACRED_LIST_CLOSE(tspContext);
    247 	DAAARAKEY_LIST_CLOSE(tspContext);
    248 	DAAISSUERKEY_LIST_CLOSE(tspContext);
    249 	NVSTORE_LIST_CLOSE(tspContext);
    250 	DELFAMILY_LIST_CLOSE(tspContext);
    251 	MIGDATA_LIST_CLOSE(tspContext);
    252 }
    253 
    254 /* When a policy object is closed, all references to it must be removed. This function
    255  * calls the object specific routines for each working object type to remove all refs to the
    256  * policy */
    257 void
    258 obj_lists_remove_policy_refs(TSS_HPOLICY hPolicy, TSS_HCONTEXT tspContext)
    259 {
    260 	obj_rsakey_remove_policy_refs(hPolicy, tspContext);
    261 	obj_encdata_remove_policy_refs(hPolicy, tspContext);
    262 	obj_tpm_remove_policy_refs(hPolicy, tspContext);
    263 }
    264 
    265 /* search all key lists (right now only RSA keys exist) looking for a TCS key handle, when
    266  * found, return the hash of its TPM_STORE_PUBKEY structure */
    267 TSS_RESULT
    268 obj_tcskey_get_pubkeyhash(TCS_KEY_HANDLE hKey, BYTE *pubKeyHash)
    269 {
    270 	struct tsp_object *obj;
    271 	struct obj_list *list = &rsakey_list;
    272 	struct tr_rsakey_obj *rsakey = NULL;
    273 	TSS_RESULT result = TSS_SUCCESS;
    274 	Trspi_HashCtx hashCtx;
    275 
    276 	MUTEX_LOCK(list->lock);
    277 
    278 	for (obj = list->head; obj; obj = obj->next) {
    279 		rsakey = (struct tr_rsakey_obj *)obj->data;
    280 		if (rsakey->tcsHandle == hKey)
    281 			break;
    282 	}
    283 
    284 	if (obj == NULL || rsakey == NULL) {
    285 		MUTEX_UNLOCK(list->lock);
    286 		return TSPERR(TSS_E_KEY_NOT_LOADED);
    287 	}
    288 
    289 	result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
    290 	result |= Trspi_Hash_STORE_PUBKEY(&hashCtx, &rsakey->key.pubKey);
    291 	if ((result |= Trspi_HashFinal(&hashCtx, pubKeyHash)))
    292 		result = TSPERR(TSS_E_INTERNAL_ERROR);
    293 
    294 	MUTEX_UNLOCK(list->lock);
    295 
    296 	return result;
    297 }
    298