xref: /netbsd-src/crypto/external/cpl/trousers/dist/src/tspi/obj_tpm.c (revision 1023804e3833a0bd94414f2545512128f6502c74)
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