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
26void
27delfamily_free(void *data)
28{
29	struct tr_delfamily_obj *delfamily = (struct tr_delfamily_obj *)data;
30
31	free(delfamily);
32}
33
34TSS_BOOL
35obj_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
47TSS_RESULT
48obj_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
67TSS_RESULT
68obj_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
85void
86obj_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
119TSS_RESULT
120obj_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
134TSS_RESULT
135obj_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
169done:
170	obj_list_put(&delfamily_list);
171
172	free(outData);
173
174	return result;
175}
176
177TSS_RESULT
178obj_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
195TSS_RESULT
196obj_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
230done:
231	obj_list_put(&delfamily_list);
232
233	free(outData);
234
235	return result;
236}
237
238TSS_RESULT
239obj_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
256TSS_RESULT
257obj_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
274TSS_RESULT
275obj_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
292TSS_RESULT
293obj_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
310TSS_RESULT
311obj_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
328TSS_RESULT
329obj_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
346TSS_RESULT
347obj_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