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. 2005, 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
25void
26tpm_free(void *data)
27{
28	struct tr_tpm_obj *tpm = (struct tr_tpm_obj *)data;
29
30	free(tpm);
31}
32
33TSS_RESULT
34obj_tpm_add(TSS_HCONTEXT tspContext, TSS_HOBJECT *phObject)
35{
36	TSS_RESULT result;
37	struct tr_tpm_obj *tpm = calloc(1, sizeof(struct tr_tpm_obj));
38
39	if (tpm == NULL) {
40		LogError("malloc of %zd bytes failed.",
41				sizeof(struct tr_tpm_obj));
42		return TSPERR(TSS_E_OUTOFMEMORY);
43	}
44
45	/* add usage policy */
46	if ((result = obj_policy_add(tspContext, TSS_POLICY_USAGE,
47					&tpm->policy))) {
48		free(tpm);
49		return result;
50	}
51
52	/* initialize the default ctr_id to inactive until we query the TPM */
53	tpm->ctr_id = 0xffffffff;
54
55	if ((result = obj_list_add(&tpm_list, tspContext, 0, tpm, phObject))) {
56		free(tpm);
57		return result;
58	}
59
60	return TSS_SUCCESS;
61}
62
63TSS_BOOL
64obj_is_tpm(TSS_HOBJECT hObject)
65{
66	TSS_BOOL answer = FALSE;
67
68	if ((obj_list_get_obj(&tpm_list, hObject))) {
69		answer = TRUE;
70		obj_list_put(&tpm_list);
71	}
72
73	return answer;
74}
75
76TSS_RESULT
77obj_tpm_set_policy(TSS_HTPM hTpm, TSS_HPOLICY hPolicy)
78{
79	struct tsp_object *obj;
80	struct tr_tpm_obj *tpm;
81	UINT32 policyType;
82	TSS_RESULT result = TSS_SUCCESS;
83
84	if ((result = obj_policy_get_type(hPolicy, &policyType)))
85		return result;
86
87	if ((obj = obj_list_get_obj(&tpm_list, hTpm)) == NULL)
88		return TSPERR(TSS_E_INVALID_HANDLE);
89
90	tpm = (struct tr_tpm_obj *)obj->data;
91
92	switch (policyType) {
93		case TSS_POLICY_USAGE:
94			tpm->policy = hPolicy;
95			break;
96#ifdef TSS_BUILD_TSS12
97		case TSS_POLICY_OPERATOR:
98			tpm->operatorPolicy = hPolicy;
99			break;
100#endif
101		default:
102			result = TSPERR(TSS_E_BAD_PARAMETER);
103	}
104
105	obj_list_put(&tpm_list);
106
107	return result;
108}
109
110TSS_RESULT
111obj_tpm_get_policy(TSS_HTPM hTpm, UINT32 policyType, TSS_HPOLICY *phPolicy)
112{
113	struct tsp_object *obj;
114	struct tr_tpm_obj *tpm;
115	TSS_RESULT result = TSS_SUCCESS;
116
117	if ((obj = obj_list_get_obj(&tpm_list, hTpm)) == NULL)
118		return TSPERR(TSS_E_INVALID_HANDLE);
119
120	tpm = (struct tr_tpm_obj *)obj->data;
121
122	switch (policyType) {
123		case TSS_POLICY_USAGE:
124			*phPolicy = tpm->policy;
125			break;
126#ifdef TSS_BUILD_TSS12
127		case TSS_POLICY_OPERATOR:
128			*phPolicy = tpm->operatorPolicy;
129			break;
130#endif
131		default:
132			result = TSPERR(TSS_E_BAD_PARAMETER);
133	}
134
135	obj_list_put(&tpm_list);
136
137	return result;
138}
139
140TSS_RESULT
141obj_tpm_get_tsp_context(TSS_HTPM hTpm, TSS_HCONTEXT *tspContext)
142{
143	struct tsp_object *obj;
144
145	if ((obj = obj_list_get_obj(&tpm_list, hTpm)) == NULL)
146		return TSPERR(TSS_E_INVALID_HANDLE);
147
148	*tspContext = obj->tspContext;
149
150	obj_list_put(&tpm_list);
151
152	return TSS_SUCCESS;
153}
154
155TSS_RESULT
156obj_tpm_get(TSS_HCONTEXT tspContext, TSS_HTPM *phTpm)
157{
158	struct tsp_object *obj;
159
160	if ((obj = obj_list_get_tspcontext(&tpm_list, tspContext)) == NULL)
161		return TSPERR(TSS_E_INVALID_HANDLE);
162
163	*phTpm = obj->handle;
164
165	obj_list_put(&tpm_list);
166
167	return TSS_SUCCESS;
168}
169
170TSS_RESULT
171obj_tpm_get_cb11(TSS_HTPM hTpm, TSS_FLAG type, UINT32 *cb)
172{
173#ifndef __LP64__
174	struct tsp_object *obj;
175	struct tr_tpm_obj *tpm;
176	TSS_RESULT result = TSS_SUCCESS;
177
178	if ((obj = obj_list_get_obj(&tpm_list, hTpm)) == NULL)
179		return TSPERR(TSS_E_INVALID_HANDLE);
180
181	tpm = (struct tr_tpm_obj *)obj->data;
182
183	switch (type) {
184		case TSS_TSPATTRIB_TPM_CALLBACK_COLLATEIDENTITY:
185			*cb = (UINT32)tpm->Tspicb_CollateIdentity;
186			break;
187		case TSS_TSPATTRIB_TPM_CALLBACK_ACTIVATEIDENTITY:
188			*cb = (UINT32)tpm->Tspicb_ActivateIdentity;
189			break;
190		default:
191			result = TSPERR(TSS_E_INVALID_ATTRIB_FLAG);
192			break;
193	}
194
195	obj_list_put(&tpm_list);
196
197	return result;
198#else
199	return TSPERR(TSS_E_FAIL);
200#endif
201}
202
203TSS_RESULT
204obj_tpm_set_cb11(TSS_HTPM hTpm, TSS_FLAG type, TSS_FLAG app_data, UINT32 cb)
205{
206#ifndef __LP64__
207	struct tsp_object *obj;
208	struct tr_tpm_obj *tpm;
209	TSS_RESULT result = TSS_SUCCESS;
210
211	if ((obj = obj_list_get_obj(&tpm_list, hTpm)) == NULL)
212		return TSPERR(TSS_E_INVALID_HANDLE);
213
214	tpm = (struct tr_tpm_obj *)obj->data;
215
216	switch (type) {
217		case TSS_TSPATTRIB_TPM_CALLBACK_COLLATEIDENTITY:
218			tpm->Tspicb_CollateIdentity = (PVOID)cb;
219			tpm->collateAppData = (PVOID)app_data;
220			break;
221		case TSS_TSPATTRIB_TPM_CALLBACK_ACTIVATEIDENTITY:
222			tpm->Tspicb_ActivateIdentity = (PVOID)cb;
223			tpm->activateAppData = (PVOID)app_data;
224			break;
225		default:
226			result = TSPERR(TSS_E_INVALID_ATTRIB_FLAG);
227			break;
228	}
229
230	obj_list_put(&tpm_list);
231
232	return result;
233#else
234	return TSPERR(TSS_E_FAIL);
235#endif
236}
237
238TSS_RESULT
239obj_tpm_set_cred(TSS_HTPM hTpm, TSS_FLAG type, UINT32 CredSize, BYTE *CredData)
240{
241	struct tsp_object *obj;
242	struct tr_tpm_obj *tpm;
243	TSS_RESULT result = TSS_SUCCESS;
244
245	if ((obj = obj_list_get_obj(&tpm_list, hTpm)) == NULL)
246		return TSPERR(TSS_E_INVALID_HANDLE);
247
248	tpm = (struct tr_tpm_obj *)obj->data;
249
250	switch (type) {
251		case TSS_TPMATTRIB_EKCERT:
252			if ((tpm->EndorsementCred = malloc(CredSize)) == NULL) {
253				LogError("malloc of %u bytes failed", CredSize);
254				result = TSPERR(TSS_E_OUTOFMEMORY);
255				goto done;
256			}
257			memcpy(tpm->EndorsementCred, CredData, CredSize);
258			tpm->EndorsementCredSize = CredSize;
259			break;
260		case TSS_TPMATTRIB_TPM_CC:
261			if ((tpm->ConformanceCred = malloc(CredSize)) == NULL) {
262				LogError("malloc of %u bytes failed", CredSize);
263				result = TSPERR(TSS_E_OUTOFMEMORY);
264				goto done;
265			}
266			memcpy(tpm->ConformanceCred, CredData, CredSize);
267			tpm->ConformanceCredSize = CredSize;
268			break;
269		case TSS_TPMATTRIB_PLATFORMCERT:
270			if ((tpm->PlatformCred = malloc(CredSize)) == NULL) {
271				LogError("malloc of %u bytes failed", CredSize);
272				result = TSPERR(TSS_E_OUTOFMEMORY);
273				goto done;
274			}
275			memcpy(tpm->PlatformCred, CredData, CredSize);
276			tpm->PlatformCredSize = CredSize;
277			break;
278		case TSS_TPMATTRIB_PLATFORM_CC:
279			if ((tpm->PlatformConfCred = malloc(CredSize)) == NULL) {
280				LogError("malloc of %u bytes failed", CredSize);
281				result = TSPERR(TSS_E_OUTOFMEMORY);
282				goto done;
283			}
284			memcpy(tpm->PlatformConfCred, CredData, CredSize);
285			tpm->PlatformConfCredSize = CredSize;
286			break;
287		default:
288			result = TSPERR(TSS_E_INVALID_ATTRIB_FLAG);
289			break;
290	}
291done:
292	obj_list_put(&tpm_list);
293
294	return result;
295}
296
297TSS_RESULT
298obj_tpm_get_cred(TSS_HTPM hTpm, TSS_FLAG type, UINT32 *CredSize, BYTE **CredData)
299{
300	struct tsp_object *obj;
301	struct tr_tpm_obj *tpm;
302	TSS_RESULT result = TSS_SUCCESS;
303
304	if ((obj = obj_list_get_obj(&tpm_list, hTpm)) == NULL)
305		return TSPERR(TSS_E_INVALID_HANDLE);
306
307	tpm = (struct tr_tpm_obj *)obj->data;
308
309	/* get the size of data we need to allocate */
310	switch (type) {
311		case TSS_TPMATTRIB_EKCERT:
312			*CredSize = tpm->EndorsementCredSize;
313			break;
314		case TSS_TPMATTRIB_TPM_CC:
315			*CredSize = tpm->ConformanceCredSize;
316			break;
317		case TSS_TPMATTRIB_PLATFORMCERT:
318			*CredSize = tpm->PlatformCredSize;
319			break;
320		case TSS_TPMATTRIB_PLATFORM_CC:
321			*CredSize = tpm->PlatformConfCredSize;
322			break;
323		default:
324			LogError("Credential type is unknown");
325			result = TSPERR(TSS_E_INTERNAL_ERROR);
326			goto done;
327	}
328
329	if (*CredSize == 0) {
330		*CredData = NULL;
331		goto done;
332	}
333
334	if ((*CredData = calloc_tspi(obj->tspContext, *CredSize)) == NULL) {
335		*CredSize = 0;
336		result = TSPERR(TSS_E_OUTOFMEMORY);
337		goto done;
338	}
339
340	switch (type) {
341		case TSS_TPMATTRIB_EKCERT:
342			memcpy(*CredData, tpm->EndorsementCred, *CredSize);
343			break;
344		case TSS_TPMATTRIB_TPM_CC:
345			memcpy(*CredData, tpm->ConformanceCred, *CredSize);
346			break;
347		case TSS_TPMATTRIB_PLATFORMCERT:
348			memcpy(*CredData, tpm->PlatformCred, *CredSize);
349			break;
350		case TSS_TPMATTRIB_PLATFORM_CC:
351			memcpy(*CredData, tpm->PlatformConfCred, *CredSize);
352			break;
353		default:
354			result = TSPERR(TSS_E_BAD_PARAMETER);
355			*CredSize = 0;
356			free(*CredData);
357			*CredData = NULL;
358			break;
359	}
360
361done:
362	obj_list_put(&tpm_list);
363	return result;
364}
365
366TSS_RESULT
367obj_tpm_set_cb12(TSS_HTPM hTpm, TSS_FLAG flag, BYTE *in)
368{
369	struct tsp_object *obj;
370	struct tr_tpm_obj *tpm;
371	TSS_RESULT result = TSS_SUCCESS;
372	TSS_CALLBACK *cb = (TSS_CALLBACK *)in;
373
374	if ((obj = obj_list_get_obj(&tpm_list, hTpm)) == NULL)
375		return TSPERR(TSS_E_INVALID_HANDLE);
376
377	tpm = (struct tr_tpm_obj *)obj->data;
378
379	switch (flag) {
380		case TSS_TSPATTRIB_TPM_CALLBACK_COLLATEIDENTITY:
381			if (!cb) {
382				tpm->Tspicb_CollateIdentity = NULL;
383				break;
384			}
385
386			tpm->Tspicb_CollateIdentity = (TSS_RESULT (*)(PVOID,
387				UINT32, BYTE *, TSS_ALGORITHM_ID, UINT32 *,
388				BYTE *, UINT32 *, BYTE *))cb->callback;
389			tpm->collateAppData = cb->appData;
390			tpm->collateAlg = cb->alg;
391			break;
392		case TSS_TSPATTRIB_TPM_CALLBACK_ACTIVATEIDENTITY:
393			if (!cb) {
394				tpm->Tspicb_ActivateIdentity = NULL;
395				break;
396			}
397
398			tpm->Tspicb_ActivateIdentity = (TSS_RESULT (*)(PVOID,
399				UINT32, BYTE *, UINT32, BYTE *, UINT32 *,
400				BYTE *))cb->callback;
401			tpm->activateAppData = cb->appData;
402			tpm->activateAlg = cb->alg;
403			break;
404		default:
405			result = TSPERR(TSS_E_INVALID_ATTRIB_FLAG);
406			break;
407	}
408
409	obj_list_put(&tpm_list);
410
411	return result;
412}
413
414TSS_RESULT
415obj_tpm_get_cb12(TSS_HTPM hTpm, TSS_FLAG flag, UINT32 *size, BYTE **out)
416{
417	struct tsp_object *obj;
418	struct tr_tpm_obj *tpm;
419	TSS_RESULT result = TSS_SUCCESS;
420	TSS_CALLBACK *cb;
421
422	if ((obj = obj_list_get_obj(&tpm_list, hTpm)) == NULL)
423		return TSPERR(TSS_E_INVALID_HANDLE);
424
425	tpm = (struct tr_tpm_obj *)obj->data;
426
427	if ((cb = calloc_tspi(obj->tspContext, sizeof(TSS_CALLBACK))) == NULL) {
428		LogError("malloc of %zd bytes failed.", sizeof(TSS_CALLBACK));
429		result = TSPERR(TSS_E_OUTOFMEMORY);
430		goto done;
431	}
432
433	switch (flag) {
434		case TSS_TSPATTRIB_TPM_CALLBACK_COLLATEIDENTITY:
435			cb->callback = tpm->Tspicb_CollateIdentity;
436			cb->appData = tpm->collateAppData;
437			cb->alg = tpm->collateAlg;
438			*size = sizeof(TSS_CALLBACK);
439			*out = (BYTE *)cb;
440			break;
441		case TSS_TSPATTRIB_TPM_CALLBACK_ACTIVATEIDENTITY:
442			cb->callback = tpm->Tspicb_ActivateIdentity;
443			cb->appData = tpm->activateAppData;
444			cb->alg = tpm->activateAlg;
445			*size = sizeof(TSS_CALLBACK);
446			*out = (BYTE *)cb;
447			break;
448		default:
449			free_tspi(obj->tspContext, cb);
450			result = TSPERR(TSS_E_INVALID_ATTRIB_FLAG);
451			break;
452	}
453done:
454	obj_list_put(&tpm_list);
455
456	return result;
457}
458
459void
460obj_tpm_remove_policy_refs(TSS_HPOLICY hPolicy, TSS_HCONTEXT tspContext)
461{
462	struct tsp_object *obj, *prev = NULL;
463	struct obj_list *list = &tpm_list;
464	struct tr_tpm_obj *tpm;
465
466	pthread_mutex_lock(&list->lock);
467
468	for (obj = list->head; obj; prev = obj, obj = obj->next) {
469		if (obj->tspContext != tspContext)
470			continue;
471
472		tpm = (struct tr_tpm_obj *)obj->data;
473		if (tpm->policy == hPolicy)
474			tpm->policy = NULL_HPOLICY;
475#ifdef TSS_BUILD_TSS12
476		if (tpm->operatorPolicy == hPolicy)
477			tpm->operatorPolicy = NULL_HPOLICY;
478#endif
479	}
480
481	pthread_mutex_unlock(&list->lock);
482}
483
484#ifdef TSS_BUILD_COUNTER
485TSS_RESULT
486obj_tpm_get_current_counter(TSS_HTPM hTPM, TSS_COUNTER_ID *ctr_id)
487{
488	struct tsp_object *obj;
489	struct tr_tpm_obj *tpm;
490	TSS_RESULT result = TSS_SUCCESS;
491	UINT32 respLen, subCap = endian32(TPM_CAP_PROP_ACTIVE_COUNTER);
492	BYTE *resp;
493
494	if ((obj = obj_list_get_obj(&tpm_list, hTPM)) == NULL)
495		return TSPERR(TSS_E_INVALID_HANDLE);
496
497	tpm = (struct tr_tpm_obj *)obj->data;
498
499	if (tpm->ctr_id != 0xffffffff) {
500		*ctr_id = tpm->ctr_id;
501		goto done;
502	}
503
504	/* No counter has yet been associated with the TPM object, so let the TPM object lock
505	 * protect us here and get a counter ID */
506	if ((result = TCS_API(obj->tspContext)->GetTPMCapability(obj->tspContext, TPM_CAP_PROPERTY,
507								 sizeof(UINT32), (BYTE *)&subCap,
508								 &respLen, &resp)))
509		goto done;
510
511	if (respLen != sizeof(UINT32)) {
512		LogDebug("TPM GetCap response size isn't sizeof(UINT32)!");
513		result = TSPERR(TSS_E_INTERNAL_ERROR);
514		goto done;
515	}
516
517	memcpy(&tpm->ctr_id, resp, respLen);
518	free(resp);
519
520	if (tpm->ctr_id == 0xffffffff) {
521		result = TSPERR(TSS_E_NO_ACTIVE_COUNTER);
522		goto done;
523	}
524	*ctr_id = tpm->ctr_id;
525done:
526	obj_list_put(&tpm_list);
527
528	return result;
529}
530#endif
531
532