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