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
25 void
tpm_free(void * data)26 tpm_free(void *data)
27 {
28 struct tr_tpm_obj *tpm = (struct tr_tpm_obj *)data;
29
30 free(tpm);
31 }
32
33 TSS_RESULT
obj_tpm_add(TSS_HCONTEXT tspContext,TSS_HOBJECT * phObject)34 obj_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
63 TSS_BOOL
obj_is_tpm(TSS_HOBJECT hObject)64 obj_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
76 TSS_RESULT
obj_tpm_set_policy(TSS_HTPM hTpm,TSS_HPOLICY hPolicy)77 obj_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
110 TSS_RESULT
obj_tpm_get_policy(TSS_HTPM hTpm,UINT32 policyType,TSS_HPOLICY * phPolicy)111 obj_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
140 TSS_RESULT
obj_tpm_get_tsp_context(TSS_HTPM hTpm,TSS_HCONTEXT * tspContext)141 obj_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
155 TSS_RESULT
obj_tpm_get(TSS_HCONTEXT tspContext,TSS_HTPM * phTpm)156 obj_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
170 TSS_RESULT
obj_tpm_get_cb11(TSS_HTPM hTpm,TSS_FLAG type,UINT32 * cb)171 obj_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
203 TSS_RESULT
obj_tpm_set_cb11(TSS_HTPM hTpm,TSS_FLAG type,TSS_FLAG app_data,UINT32 cb)204 obj_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
238 TSS_RESULT
obj_tpm_set_cred(TSS_HTPM hTpm,TSS_FLAG type,UINT32 CredSize,BYTE * CredData)239 obj_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 }
291 done:
292 obj_list_put(&tpm_list);
293
294 return result;
295 }
296
297 TSS_RESULT
obj_tpm_get_cred(TSS_HTPM hTpm,TSS_FLAG type,UINT32 * CredSize,BYTE ** CredData)298 obj_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
361 done:
362 obj_list_put(&tpm_list);
363 return result;
364 }
365
366 TSS_RESULT
obj_tpm_set_cb12(TSS_HTPM hTpm,TSS_FLAG flag,BYTE * in)367 obj_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
414 TSS_RESULT
obj_tpm_get_cb12(TSS_HTPM hTpm,TSS_FLAG flag,UINT32 * size,BYTE ** out)415 obj_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 }
453 done:
454 obj_list_put(&tpm_list);
455
456 return result;
457 }
458
459 void
obj_tpm_remove_policy_refs(TSS_HPOLICY hPolicy,TSS_HCONTEXT tspContext)460 obj_tpm_remove_policy_refs(TSS_HPOLICY hPolicy, TSS_HCONTEXT tspContext)
461 {
462 struct tsp_object *obj;
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; 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
485 TSS_RESULT
obj_tpm_get_current_counter(TSS_HTPM hTPM,TSS_COUNTER_ID * ctr_id)486 obj_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;
525 done:
526 obj_list_put(&tpm_list);
527
528 return result;
529 }
530 #endif
531
532