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