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. 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 "capabilities.h"
22 #include "tsplog.h"
23 #include "obj.h"
24 #include "tsp_delegate.h"
25 
26 void
delfamily_free(void * data)27 delfamily_free(void *data)
28 {
29 	struct tr_delfamily_obj *delfamily = (struct tr_delfamily_obj *)data;
30 
31 	free(delfamily);
32 }
33 
34 TSS_BOOL
obj_is_delfamily(TSS_HOBJECT hObject)35 obj_is_delfamily(TSS_HOBJECT hObject)
36 {
37 	TSS_BOOL answer = FALSE;
38 
39 	if ((obj_list_get_obj(&delfamily_list, hObject))) {
40 		answer = TRUE;
41 		obj_list_put(&delfamily_list);
42 	}
43 
44 	return answer;
45 }
46 
47 TSS_RESULT
obj_delfamily_add(TSS_HCONTEXT hContext,TSS_HOBJECT * phObject)48 obj_delfamily_add(TSS_HCONTEXT hContext, TSS_HOBJECT *phObject)
49 {
50 	TSS_RESULT result;
51 	struct tr_delfamily_obj *delfamily = calloc(1, sizeof(struct tr_delfamily_obj));
52 
53 	if (delfamily == NULL) {
54 		LogError("malloc of %zd bytes failed.",
55 				sizeof(struct tr_delfamily_obj));
56 		return TSPERR(TSS_E_OUTOFMEMORY);
57 	}
58 
59 	if ((result = obj_list_add(&delfamily_list, hContext, 0, delfamily, phObject))) {
60 		free(delfamily);
61 		return result;
62 	}
63 
64 	return TSS_SUCCESS;
65 }
66 
67 TSS_RESULT
obj_delfamily_remove(TSS_HDELFAMILY hFamily,TSS_HOBJECT hObject)68 obj_delfamily_remove(TSS_HDELFAMILY hFamily, TSS_HOBJECT hObject)
69 {
70 	TSS_HCONTEXT hContext;
71 	TSS_RESULT result;
72 
73 	if (obj_is_tpm(hObject)) {
74 		if ((result = obj_tpm_get_tsp_context((TSS_HTPM)hObject, &hContext)))
75 			return result;
76 	} else
77 		hContext = (TSS_HCONTEXT)hObject;
78 
79 	if ((result = obj_list_remove(&delfamily_list, &delfamily_free, hFamily, hContext)))
80 		return result;
81 
82 	return TSS_SUCCESS;
83 }
84 
85 void
obj_delfamily_find_by_familyid(TSS_HOBJECT hObject,UINT32 familyID,TSS_HDELFAMILY * hFamily)86 obj_delfamily_find_by_familyid(TSS_HOBJECT hObject, UINT32 familyID, TSS_HDELFAMILY *hFamily)
87 {
88 	TSS_HCONTEXT hContext;
89 	struct tsp_object *obj;
90 	struct obj_list *list = &delfamily_list;
91 	struct tr_delfamily_obj *delfamily;
92 
93 	pthread_mutex_lock(&list->lock);
94 
95 	*hFamily = NULL_HDELFAMILY;
96 
97 	if (obj_is_tpm(hObject)) {
98 		if (obj_tpm_get_tsp_context((TSS_HTPM)hObject, &hContext)) {
99 			pthread_mutex_unlock(&list->lock);
100 			return;
101 		}
102 	} else
103 		hContext = (TSS_HCONTEXT)hObject;
104 
105 	for (obj = list->head; obj; obj = obj->next) {
106 		if (obj->tspContext != hContext)
107 			continue;
108 
109 		delfamily = (struct tr_delfamily_obj *)obj->data;
110 		if (delfamily->familyID == familyID) {
111 			*hFamily = obj->handle;
112 			break;
113 		}
114 	}
115 
116 	pthread_mutex_unlock(&list->lock);
117 }
118 
119 TSS_RESULT
obj_delfamily_get_tsp_context(TSS_HDELFAMILY hFamily,TSS_HCONTEXT * hContext)120 obj_delfamily_get_tsp_context(TSS_HDELFAMILY hFamily, TSS_HCONTEXT *hContext)
121 {
122 	struct tsp_object *obj;
123 
124 	if ((obj = obj_list_get_obj(&delfamily_list, hFamily)) == NULL)
125 		return TSPERR(TSS_E_INVALID_HANDLE);
126 
127 	*hContext = obj->tspContext;
128 
129 	obj_list_put(&delfamily_list);
130 
131 	return TSS_SUCCESS;
132 }
133 
134 TSS_RESULT
obj_delfamily_set_locked(TSS_HDELFAMILY hFamily,TSS_BOOL state,TSS_BOOL setInTpm)135 obj_delfamily_set_locked(TSS_HDELFAMILY hFamily, TSS_BOOL state, TSS_BOOL setInTpm)
136 {
137 	struct tsp_object *obj;
138 	struct tr_delfamily_obj *delfamily;
139 	TSS_HTPM hTpm;
140 	UINT32 opDataSize;
141 	BYTE opData[8];
142 	UINT32 outDataSize;
143 	BYTE *outData = NULL;
144 	UINT64 offset;
145 	TSS_RESULT result = TSS_SUCCESS;
146 
147 	if ((obj = obj_list_get_obj(&delfamily_list, hFamily)) == NULL)
148 		return TSPERR(TSS_E_INVALID_HANDLE);
149 
150 	delfamily = (struct tr_delfamily_obj *)obj->data;
151 
152 	if (setInTpm) {
153 		if ((result = obj_tpm_get(obj->tspContext, &hTpm)))
154 			goto done;
155 
156 		offset = 0;
157 		Trspi_LoadBlob_BOOL(&offset, state, opData);
158 		opDataSize = offset;
159 		if ((result = do_delegate_manage(hTpm, delfamily->familyID, TPM_FAMILY_ADMIN,
160 				opDataSize, opData, &outDataSize, &outData)))
161 			goto done;
162 	}
163 
164 	if (state)
165 		delfamily->stateFlags |= TSS_DELFAMILY_FLAGS_STATE_LOCKED;
166 	else
167 		delfamily->stateFlags &= ~TSS_DELFAMILY_FLAGS_STATE_LOCKED;
168 
169 done:
170 	obj_list_put(&delfamily_list);
171 
172 	free(outData);
173 
174 	return result;
175 }
176 
177 TSS_RESULT
obj_delfamily_get_locked(TSS_HDELFAMILY hFamily,TSS_BOOL * state)178 obj_delfamily_get_locked(TSS_HDELFAMILY hFamily, TSS_BOOL *state)
179 {
180 	struct tsp_object *obj;
181 	struct tr_delfamily_obj *delfamily;
182 
183 	if ((obj = obj_list_get_obj(&delfamily_list, hFamily)) == NULL)
184 		return TSPERR(TSS_E_INVALID_HANDLE);
185 
186 	delfamily = (struct tr_delfamily_obj *)obj->data;
187 
188 	*state = (delfamily->stateFlags & TSS_DELFAMILY_FLAGS_STATE_LOCKED) ? TRUE : FALSE;
189 
190 	obj_list_put(&delfamily_list);
191 
192 	return TSS_SUCCESS;
193 }
194 
195 TSS_RESULT
obj_delfamily_set_enabled(TSS_HDELFAMILY hFamily,TSS_BOOL state,TSS_BOOL setInTpm)196 obj_delfamily_set_enabled(TSS_HDELFAMILY hFamily, TSS_BOOL state, TSS_BOOL setInTpm)
197 {
198 	struct tsp_object *obj;
199 	struct tr_delfamily_obj *delfamily;
200 	TSS_HTPM hTpm;
201 	UINT32 opDataSize;
202 	BYTE opData[8];
203 	UINT32 outDataSize;
204 	BYTE *outData = NULL;
205 	UINT64 offset;
206 	TSS_RESULT result = TSS_SUCCESS;
207 
208 	if ((obj = obj_list_get_obj(&delfamily_list, hFamily)) == NULL)
209 		return TSPERR(TSS_E_INVALID_HANDLE);
210 
211 	delfamily = (struct tr_delfamily_obj *)obj->data;
212 
213 	if (setInTpm) {
214 		if ((result = obj_tpm_get(obj->tspContext, &hTpm)))
215 			goto done;
216 
217 		offset = 0;
218 		Trspi_LoadBlob_BOOL(&offset, state, opData);
219 		opDataSize = offset;
220 		if ((result = do_delegate_manage(hTpm, delfamily->familyID, TPM_FAMILY_ENABLE,
221 				opDataSize, opData, &outDataSize, &outData)))
222 			goto done;
223 	}
224 
225 	if (state)
226 		delfamily->stateFlags |= TSS_DELFAMILY_FLAGS_STATE_ENABLED;
227 	else
228 		delfamily->stateFlags &= ~TSS_DELFAMILY_FLAGS_STATE_ENABLED;
229 
230 done:
231 	obj_list_put(&delfamily_list);
232 
233 	free(outData);
234 
235 	return result;
236 }
237 
238 TSS_RESULT
obj_delfamily_get_enabled(TSS_HDELFAMILY hFamily,TSS_BOOL * state)239 obj_delfamily_get_enabled(TSS_HDELFAMILY hFamily, TSS_BOOL *state)
240 {
241 	struct tsp_object *obj;
242 	struct tr_delfamily_obj *delfamily;
243 
244 	if ((obj = obj_list_get_obj(&delfamily_list, hFamily)) == NULL)
245 		return TSPERR(TSS_E_INVALID_HANDLE);
246 
247 	delfamily = (struct tr_delfamily_obj *)obj->data;
248 
249 	*state = (delfamily->stateFlags & TSS_DELFAMILY_FLAGS_STATE_ENABLED) ? TRUE : FALSE;
250 
251 	obj_list_put(&delfamily_list);
252 
253 	return TSS_SUCCESS;
254 }
255 
256 TSS_RESULT
obj_delfamily_set_vercount(TSS_HDELFAMILY hFamily,UINT32 verCount)257 obj_delfamily_set_vercount(TSS_HDELFAMILY hFamily, UINT32 verCount)
258 {
259 	struct tsp_object *obj;
260 	struct tr_delfamily_obj *delfamily;
261 
262 	if ((obj = obj_list_get_obj(&delfamily_list, hFamily)) == NULL)
263 		return TSPERR(TSS_E_INVALID_HANDLE);
264 
265 	delfamily = (struct tr_delfamily_obj *)obj->data;
266 
267 	delfamily->verCount = verCount;
268 
269 	obj_list_put(&delfamily_list);
270 
271 	return TSS_SUCCESS;
272 }
273 
274 TSS_RESULT
obj_delfamily_get_vercount(TSS_HDELFAMILY hFamily,UINT32 * verCount)275 obj_delfamily_get_vercount(TSS_HDELFAMILY hFamily, UINT32 *verCount)
276 {
277 	struct tsp_object *obj;
278 	struct tr_delfamily_obj *delfamily;
279 
280 	if ((obj = obj_list_get_obj(&delfamily_list, hFamily)) == NULL)
281 		return TSPERR(TSS_E_INVALID_HANDLE);
282 
283 	delfamily = (struct tr_delfamily_obj *)obj->data;
284 
285 	*verCount = delfamily->verCount;
286 
287 	obj_list_put(&delfamily_list);
288 
289 	return TSS_SUCCESS;
290 }
291 
292 TSS_RESULT
obj_delfamily_set_familyid(TSS_HDELFAMILY hFamily,UINT32 familyID)293 obj_delfamily_set_familyid(TSS_HDELFAMILY hFamily, UINT32 familyID)
294 {
295 	struct tsp_object *obj;
296 	struct tr_delfamily_obj *delfamily;
297 
298 	if ((obj = obj_list_get_obj(&delfamily_list, hFamily)) == NULL)
299 		return TSPERR(TSS_E_INVALID_HANDLE);
300 
301 	delfamily = (struct tr_delfamily_obj *)obj->data;
302 
303 	delfamily->familyID = familyID;
304 
305 	obj_list_put(&delfamily_list);
306 
307 	return TSS_SUCCESS;
308 }
309 
310 TSS_RESULT
obj_delfamily_get_familyid(TSS_HDELFAMILY hFamily,UINT32 * familyID)311 obj_delfamily_get_familyid(TSS_HDELFAMILY hFamily, UINT32 *familyID)
312 {
313 	struct tsp_object *obj;
314 	struct tr_delfamily_obj *delfamily;
315 
316 	if ((obj = obj_list_get_obj(&delfamily_list, hFamily)) == NULL)
317 		return TSPERR(TSS_E_INVALID_HANDLE);
318 
319 	delfamily = (struct tr_delfamily_obj *)obj->data;
320 
321 	*familyID = delfamily->familyID;
322 
323 	obj_list_put(&delfamily_list);
324 
325 	return TSS_SUCCESS;
326 }
327 
328 TSS_RESULT
obj_delfamily_set_label(TSS_HDELFAMILY hFamily,BYTE label)329 obj_delfamily_set_label(TSS_HDELFAMILY hFamily, BYTE label)
330 {
331 	struct tsp_object *obj;
332 	struct tr_delfamily_obj *delfamily;
333 
334 	if ((obj = obj_list_get_obj(&delfamily_list, hFamily)) == NULL)
335 		return TSPERR(TSS_E_INVALID_HANDLE);
336 
337 	delfamily = (struct tr_delfamily_obj *)obj->data;
338 
339 	delfamily->label = label;
340 
341 	obj_list_put(&delfamily_list);
342 
343 	return TSS_SUCCESS;
344 }
345 
346 TSS_RESULT
obj_delfamily_get_label(TSS_HDELFAMILY hFamily,BYTE * label)347 obj_delfamily_get_label(TSS_HDELFAMILY hFamily, BYTE *label)
348 {
349 	struct tsp_object *obj;
350 	struct tr_delfamily_obj *delfamily;
351 
352 	if ((obj = obj_list_get_obj(&delfamily_list, hFamily)) == NULL)
353 		return TSPERR(TSS_E_INVALID_HANDLE);
354 
355 	delfamily = (struct tr_delfamily_obj *)obj->data;
356 
357 	*label = delfamily->label;
358 
359 	obj_list_put(&delfamily_list);
360 
361 	return TSS_SUCCESS;
362 }
363 
364