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