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