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
tspi_list_init(struct obj_list * list)43 tspi_list_init(struct obj_list *list)
44 {
45 list->head = NULL;
46 MUTEX_INIT(list->lock);
47 }
48
49 void
__tspi_obj_list_init()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
obj_get_next_handle()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 *
obj_list_get_obj(struct obj_list * list,UINT32 handle)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 *
obj_list_get_tspcontext(struct obj_list * list,UINT32 tspContext)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
obj_list_put(struct obj_list * list)127 obj_list_put(struct obj_list *list)
128 {
129 MUTEX_UNLOCK(list->lock);
130 }
131
132 TSS_RESULT
obj_list_add(struct obj_list * list,UINT32 tsp_context,TSS_FLAG flags,void * data,TSS_HOBJECT * phObject)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
obj_list_remove(struct obj_list * list,void (* freeFcn)(void *),TSS_HOBJECT hObject,TSS_HCONTEXT tspContext)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
obj_list_close(struct obj_list * list,void (* freeFcn)(void *),TSS_HCONTEXT tspContext)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
obj_close_context(TSS_HCONTEXT tspContext)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
obj_lists_remove_policy_refs(TSS_HPOLICY hPolicy,TSS_HCONTEXT tspContext)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
obj_tcskey_get_pubkeyhash(TCS_KEY_HANDLE hKey,BYTE * pubKeyHash)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