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, *prev = NULL;
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			return;
100	} else
101		hContext = (TSS_HCONTEXT)hObject;
102
103	for (obj = list->head; obj; prev = obj, obj = obj->next) {
104		if (obj->tspContext != hContext)
105			continue;
106
107		delfamily = (struct tr_delfamily_obj *)obj->data;
108		if (delfamily->familyID == familyID) {
109			*hFamily = obj->handle;
110			break;
111		}
112	}
113
114	pthread_mutex_unlock(&list->lock);
115}
116
117TSS_RESULT
118obj_delfamily_get_tsp_context(TSS_HDELFAMILY hFamily, TSS_HCONTEXT *hContext)
119{
120	struct tsp_object *obj;
121
122	if ((obj = obj_list_get_obj(&delfamily_list, hFamily)) == NULL)
123		return TSPERR(TSS_E_INVALID_HANDLE);
124
125	*hContext = obj->tspContext;
126
127	obj_list_put(&delfamily_list);
128
129	return TSS_SUCCESS;
130}
131
132TSS_RESULT
133obj_delfamily_set_locked(TSS_HDELFAMILY hFamily, TSS_BOOL state, TSS_BOOL setInTpm)
134{
135	struct tsp_object *obj;
136	struct tr_delfamily_obj *delfamily;
137	TSS_HTPM hTpm;
138	UINT32 opDataSize;
139	BYTE opData[8];
140	UINT32 outDataSize;
141	BYTE *outData = NULL;
142	UINT64 offset;
143	TSS_RESULT result = TSS_SUCCESS;
144
145	if ((obj = obj_list_get_obj(&delfamily_list, hFamily)) == NULL)
146		return TSPERR(TSS_E_INVALID_HANDLE);
147
148	delfamily = (struct tr_delfamily_obj *)obj->data;
149
150	if (setInTpm) {
151		if ((result = obj_tpm_get(obj->tspContext, &hTpm)))
152			goto done;
153
154		offset = 0;
155		Trspi_LoadBlob_BOOL(&offset, state, opData);
156		opDataSize = offset;
157		if ((result = do_delegate_manage(hTpm, delfamily->familyID, TPM_FAMILY_ADMIN,
158				opDataSize, opData, &outDataSize, &outData)))
159			goto done;
160	}
161
162	if (state)
163		delfamily->stateFlags |= TSS_DELFAMILY_FLAGS_STATE_LOCKED;
164	else
165		delfamily->stateFlags &= ~TSS_DELFAMILY_FLAGS_STATE_LOCKED;
166
167done:
168	obj_list_put(&delfamily_list);
169
170	free(outData);
171
172	return result;
173}
174
175TSS_RESULT
176obj_delfamily_get_locked(TSS_HDELFAMILY hFamily, TSS_BOOL *state)
177{
178	struct tsp_object *obj;
179	struct tr_delfamily_obj *delfamily;
180
181	if ((obj = obj_list_get_obj(&delfamily_list, hFamily)) == NULL)
182		return TSPERR(TSS_E_INVALID_HANDLE);
183
184	delfamily = (struct tr_delfamily_obj *)obj->data;
185
186	*state = (delfamily->stateFlags & TSS_DELFAMILY_FLAGS_STATE_LOCKED) ? TRUE : FALSE;
187
188	obj_list_put(&delfamily_list);
189
190	return TSS_SUCCESS;
191}
192
193TSS_RESULT
194obj_delfamily_set_enabled(TSS_HDELFAMILY hFamily, TSS_BOOL state, TSS_BOOL setInTpm)
195{
196	struct tsp_object *obj;
197	struct tr_delfamily_obj *delfamily;
198	TSS_HTPM hTpm;
199	UINT32 opDataSize;
200	BYTE opData[8];
201	UINT32 outDataSize;
202	BYTE *outData = NULL;
203	UINT64 offset;
204	TSS_RESULT result = TSS_SUCCESS;
205
206	if ((obj = obj_list_get_obj(&delfamily_list, hFamily)) == NULL)
207		return TSPERR(TSS_E_INVALID_HANDLE);
208
209	delfamily = (struct tr_delfamily_obj *)obj->data;
210
211	if (setInTpm) {
212		if ((result = obj_tpm_get(obj->tspContext, &hTpm)))
213			goto done;
214
215		offset = 0;
216		Trspi_LoadBlob_BOOL(&offset, state, opData);
217		opDataSize = offset;
218		if ((result = do_delegate_manage(hTpm, delfamily->familyID, TPM_FAMILY_ENABLE,
219				opDataSize, opData, &outDataSize, &outData)))
220			goto done;
221	}
222
223	if (state)
224		delfamily->stateFlags |= TSS_DELFAMILY_FLAGS_STATE_ENABLED;
225	else
226		delfamily->stateFlags &= ~TSS_DELFAMILY_FLAGS_STATE_ENABLED;
227
228done:
229	obj_list_put(&delfamily_list);
230
231	free(outData);
232
233	return result;
234}
235
236TSS_RESULT
237obj_delfamily_get_enabled(TSS_HDELFAMILY hFamily, TSS_BOOL *state)
238{
239	struct tsp_object *obj;
240	struct tr_delfamily_obj *delfamily;
241
242	if ((obj = obj_list_get_obj(&delfamily_list, hFamily)) == NULL)
243		return TSPERR(TSS_E_INVALID_HANDLE);
244
245	delfamily = (struct tr_delfamily_obj *)obj->data;
246
247	*state = (delfamily->stateFlags & TSS_DELFAMILY_FLAGS_STATE_ENABLED) ? TRUE : FALSE;
248
249	obj_list_put(&delfamily_list);
250
251	return TSS_SUCCESS;
252}
253
254TSS_RESULT
255obj_delfamily_set_vercount(TSS_HDELFAMILY hFamily, UINT32 verCount)
256{
257	struct tsp_object *obj;
258	struct tr_delfamily_obj *delfamily;
259
260	if ((obj = obj_list_get_obj(&delfamily_list, hFamily)) == NULL)
261		return TSPERR(TSS_E_INVALID_HANDLE);
262
263	delfamily = (struct tr_delfamily_obj *)obj->data;
264
265	delfamily->verCount = verCount;
266
267	obj_list_put(&delfamily_list);
268
269	return TSS_SUCCESS;
270}
271
272TSS_RESULT
273obj_delfamily_get_vercount(TSS_HDELFAMILY hFamily, UINT32 *verCount)
274{
275	struct tsp_object *obj;
276	struct tr_delfamily_obj *delfamily;
277
278	if ((obj = obj_list_get_obj(&delfamily_list, hFamily)) == NULL)
279		return TSPERR(TSS_E_INVALID_HANDLE);
280
281	delfamily = (struct tr_delfamily_obj *)obj->data;
282
283	*verCount = delfamily->verCount;
284
285	obj_list_put(&delfamily_list);
286
287	return TSS_SUCCESS;
288}
289
290TSS_RESULT
291obj_delfamily_set_familyid(TSS_HDELFAMILY hFamily, UINT32 familyID)
292{
293	struct tsp_object *obj;
294	struct tr_delfamily_obj *delfamily;
295
296	if ((obj = obj_list_get_obj(&delfamily_list, hFamily)) == NULL)
297		return TSPERR(TSS_E_INVALID_HANDLE);
298
299	delfamily = (struct tr_delfamily_obj *)obj->data;
300
301	delfamily->familyID = familyID;
302
303	obj_list_put(&delfamily_list);
304
305	return TSS_SUCCESS;
306}
307
308TSS_RESULT
309obj_delfamily_get_familyid(TSS_HDELFAMILY hFamily, UINT32 *familyID)
310{
311	struct tsp_object *obj;
312	struct tr_delfamily_obj *delfamily;
313
314	if ((obj = obj_list_get_obj(&delfamily_list, hFamily)) == NULL)
315		return TSPERR(TSS_E_INVALID_HANDLE);
316
317	delfamily = (struct tr_delfamily_obj *)obj->data;
318
319	*familyID = delfamily->familyID;
320
321	obj_list_put(&delfamily_list);
322
323	return TSS_SUCCESS;
324}
325
326TSS_RESULT
327obj_delfamily_set_label(TSS_HDELFAMILY hFamily, BYTE label)
328{
329	struct tsp_object *obj;
330	struct tr_delfamily_obj *delfamily;
331
332	if ((obj = obj_list_get_obj(&delfamily_list, hFamily)) == NULL)
333		return TSPERR(TSS_E_INVALID_HANDLE);
334
335	delfamily = (struct tr_delfamily_obj *)obj->data;
336
337	delfamily->label = label;
338
339	obj_list_put(&delfamily_list);
340
341	return TSS_SUCCESS;
342}
343
344TSS_RESULT
345obj_delfamily_get_label(TSS_HDELFAMILY hFamily, BYTE *label)
346{
347	struct tsp_object *obj;
348	struct tr_delfamily_obj *delfamily;
349
350	if ((obj = obj_list_get_obj(&delfamily_list, hFamily)) == NULL)
351		return TSPERR(TSS_E_INVALID_HANDLE);
352
353	delfamily = (struct tr_delfamily_obj *)obj->data;
354
355	*label = delfamily->label;
356
357	obj_list_put(&delfamily_list);
358
359	return TSS_SUCCESS;
360}
361
362