xref: /netbsd-src/crypto/external/cpl/trousers/dist/src/tspi/obj.c (revision 1023804e3833a0bd94414f2545512128f6502c74)
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