Home | History | Annotate | Line # | Download | only in tspi
      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
     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
     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
     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
     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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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