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. 2007 8 * 9 */ 10 11 12#include <stdlib.h> 13#include <stdio.h> 14#include <string.h> 15#include <inttypes.h> 16 17#include "trousers/tss.h" 18#include "trousers/trousers.h" 19#include "trousers_types.h" 20#include "spi_utils.h" 21#include "obj.h" 22#include "tsp_delegate.h" 23#include "tsplog.h" 24 25 26TSS_RESULT 27Tspi_TPM_Delegate_AddFamily(TSS_HTPM hTpm, /* in, must not be NULL */ 28 BYTE bLabel, /* in */ 29 TSS_HDELFAMILY* phFamily) /* out */ 30{ 31 TPM_FAMILY_ID familyID = 0; 32 UINT32 outDataSize; 33 BYTE *outData = NULL; 34 UINT64 offset; 35 TSS_RESULT result; 36 37 if (phFamily == NULL) 38 return TSPERR(TSS_E_BAD_PARAMETER); 39 *phFamily = NULL_HDELFAMILY; 40 41 if ((result = do_delegate_manage(hTpm, familyID, TPM_FAMILY_CREATE, sizeof(bLabel), &bLabel, 42 &outDataSize, &outData))) 43 return result; 44 45 offset = 0; 46 Trspi_UnloadBlob_UINT32(&offset, &familyID, outData); 47 48 /* Create or update the delfamily object */ 49 if ((result = update_delfamily_object(hTpm, familyID))) 50 goto done; 51 52 obj_delfamily_find_by_familyid(hTpm, familyID, phFamily); 53 if (*phFamily == NULL_HDELFAMILY) 54 result = TSPERR(TSS_E_INTERNAL_ERROR); 55 56done: 57 free(outData); 58 59 return result; 60} 61 62TSS_RESULT 63Tspi_TPM_Delegate_GetFamily(TSS_HTPM hTpm, /* in, must not NULL */ 64 UINT32 ulFamilyID, /* in */ 65 TSS_HDELFAMILY* phFamily) /* out */ 66{ 67 TSS_RESULT result; 68 69 if (phFamily == NULL) 70 return TSPERR(TSS_E_BAD_PARAMETER); 71 *phFamily = NULL_HDELFAMILY; 72 73 /* Update the delfamily object */ 74 if ((result = update_delfamily_object(hTpm, ulFamilyID))) 75 return result; 76 77 obj_delfamily_find_by_familyid(hTpm, ulFamilyID, phFamily); 78 if (*phFamily == NULL_HDELFAMILY) 79 result = TSPERR(TSS_E_BAD_PARAMETER); 80 81 return result; 82} 83 84TSS_RESULT 85Tspi_TPM_Delegate_InvalidateFamily(TSS_HTPM hTpm, /* in, must not be NULL */ 86 TSS_HDELFAMILY hFamily) /* in */ 87{ 88 TPM_FAMILY_ID familyID; 89 UINT32 outDataSize; 90 BYTE *outData = NULL; 91 TSS_RESULT result; 92 93 if ((result = obj_delfamily_get_familyid(hFamily, &familyID))) 94 return result; 95 96 if ((result = do_delegate_manage(hTpm, familyID, TPM_FAMILY_INVALIDATE, 0, NULL, 97 &outDataSize, &outData))) 98 return result; 99 100 /* Delete the delfamily object */ 101 result = obj_delfamily_remove(hFamily, hTpm); 102 103 free(outData); 104 105 return result; 106} 107 108TSS_RESULT 109Tspi_TPM_Delegate_CreateDelegation(TSS_HOBJECT hObject, /* in */ 110 BYTE bLabel, /* in */ 111 UINT32 ulFlags, /* in */ 112 TSS_HPCRS hPcrs, /* in */ 113 TSS_HDELFAMILY hFamily, /* in */ 114 TSS_HPOLICY hDelegation) /* in, out */ 115{ 116 TSS_RESULT result; 117 118 if (obj_is_tpm(hObject)) { 119 if ((result = create_owner_delegation(hObject, bLabel, ulFlags, hPcrs, hFamily, 120 hDelegation))) 121 return result; 122 } else if (obj_is_rsakey(hObject)) { 123 if ((result = create_key_delegation(hObject, bLabel, ulFlags, hPcrs, hFamily, 124 hDelegation))) 125 return result; 126 } else 127 return TSPERR(TSS_E_INVALID_HANDLE); 128 129 return TSS_SUCCESS; 130} 131 132TSS_RESULT 133Tspi_TPM_Delegate_CacheOwnerDelegation(TSS_HTPM hTpm, /* in */ 134 TSS_HPOLICY hDelegation, /* in */ 135 UINT32 ulIndex, /* in */ 136 UINT32 ulFlags) /* in */ 137{ 138 TSS_HCONTEXT hContext; 139 TSS_HPOLICY hPolicy; 140 UINT32 blobSize; 141 BYTE *blob = NULL; 142 UINT32 secretMode = TSS_SECRET_MODE_NONE; 143 Trspi_HashCtx hashCtx; 144 TCPA_DIGEST digest; 145 TPM_AUTH ownerAuth, *pAuth; 146 TSS_RESULT result; 147 148 if ((result = obj_tpm_get_tsp_context(hTpm, &hContext))) 149 return result; 150 151 if ((result = obj_tpm_get_policy(hTpm, TSS_POLICY_USAGE, &hPolicy))) 152 return result; 153 154 if ((result = obj_policy_get_delegation_blob(hDelegation, TSS_DELEGATIONTYPE_OWNER, 155 &blobSize, &blob))) 156 return result; 157 158 if (ulFlags & ~TSS_DELEGATE_CACHEOWNERDELEGATION_OVERWRITEEXISTING) { 159 result = TSPERR(TSS_E_BAD_PARAMETER); 160 goto done; 161 } 162 163 if ((ulFlags & TSS_DELEGATE_CACHEOWNERDELEGATION_OVERWRITEEXISTING) == 0) { 164 TPM_DELEGATE_PUBLIC public; 165 166 /* Verify there is nothing occupying the specified row */ 167 result = get_delegate_index(hContext, ulIndex, &public); 168 if (result == TSS_SUCCESS) { 169 free(public.pcrInfo.pcrSelection.pcrSelect); 170 result = TSPERR(TSS_E_DELFAMILY_ROWEXISTS); 171 goto done; 172 } 173 } 174 175 if (hPolicy != NULL_HPOLICY) { 176 if ((result = obj_policy_get_mode(hPolicy, &secretMode))) 177 goto done; 178 } 179 180 if (secretMode != TSS_SECRET_MODE_NONE) { 181 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); 182 result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_Delegate_LoadOwnerDelegation); 183 result |= Trspi_Hash_UINT32(&hashCtx, ulIndex); 184 result |= Trspi_Hash_UINT32(&hashCtx, blobSize); 185 result |= Trspi_HashUpdate(&hashCtx, blobSize, blob); 186 if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) 187 goto done; 188 189 pAuth = &ownerAuth; 190 if ((result = secret_PerformAuth_OIAP(hTpm, TPM_ORD_Delegate_LoadOwnerDelegation, 191 hPolicy, FALSE, &digest, pAuth))) 192 goto done; 193 } else 194 pAuth = NULL; 195 196 if ((result = TCS_API(hContext)->Delegate_LoadOwnerDelegation(hContext, ulIndex, blobSize, 197 blob, pAuth))) 198 goto done; 199 200 if (pAuth) { 201 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); 202 result |= Trspi_Hash_UINT32(&hashCtx, result); 203 result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_Delegate_LoadOwnerDelegation); 204 if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) 205 goto done; 206 207 if ((result = obj_policy_validate_auth_oiap(hPolicy, &digest, pAuth))) 208 goto done; 209 } 210 211 result = obj_policy_set_delegation_index(hDelegation, ulIndex); 212 213done: 214 free_tspi(hContext, blob); 215 216 return result; 217} 218 219TSS_RESULT 220Tspi_TPM_Delegate_UpdateVerificationCount(TSS_HTPM hTpm, /* in */ 221 TSS_HPOLICY hDelegation) /* in, out */ 222{ 223 TSS_HCONTEXT hContext; 224 TSS_HPOLICY hPolicy; 225 UINT32 secretMode = TSS_SECRET_MODE_NONE; 226 Trspi_HashCtx hashCtx; 227 TCPA_DIGEST digest; 228 TPM_AUTH ownerAuth, *pAuth; 229 TSS_BOOL indexSet; 230 UINT32 inputSize; 231 BYTE *input = NULL; 232 UINT32 outputSize; 233 BYTE *output = NULL; 234 UINT64 offset; 235 TSS_RESULT result; 236 237 if ((result = obj_tpm_get_tsp_context(hTpm, &hContext))) 238 return result; 239 240 if ((result = obj_tpm_get_policy(hTpm, TSS_POLICY_USAGE, &hPolicy))) 241 return result; 242 243 if (hPolicy != NULL_HPOLICY) { 244 if ((result = obj_policy_get_mode(hPolicy, &secretMode))) 245 goto done; 246 } 247 248 if ((result = obj_policy_is_delegation_index_set(hDelegation, &indexSet))) 249 return result; 250 if (indexSet) { 251 UINT32 index; 252 253 if ((result = obj_policy_get_delegation_index(hDelegation, &index))) 254 return result; 255 inputSize = sizeof(UINT32); 256 input = calloc_tspi(hContext, inputSize); 257 if (!input) { 258 LogError("malloc of %zd bytes failed.", sizeof(UINT32)); 259 return TSPERR(TSS_E_OUTOFMEMORY); 260 } 261 offset = 0; 262 Trspi_LoadBlob_UINT32(&offset, index, input); 263 } else { 264 if ((result = obj_policy_get_delegation_blob(hDelegation, 0, 265 &inputSize, &input))) 266 return result; 267 } 268 269 if (secretMode != TSS_SECRET_MODE_NONE) { 270 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); 271 result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_Delegate_UpdateVerification); 272 result |= Trspi_Hash_UINT32(&hashCtx, inputSize); 273 result |= Trspi_HashUpdate(&hashCtx, inputSize, input); 274 if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) 275 goto done; 276 277 pAuth = &ownerAuth; 278 if ((result = secret_PerformAuth_OIAP(hTpm, TPM_ORD_Delegate_UpdateVerification, 279 hPolicy, FALSE, &digest, pAuth))) 280 goto done; 281 } else 282 pAuth = NULL; 283 284 if ((result = TCS_API(hContext)->Delegate_UpdateVerificationCount(hContext, inputSize, 285 input, pAuth, &outputSize, 286 &output))) 287 goto done; 288 289 if (pAuth) { 290 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); 291 result |= Trspi_Hash_UINT32(&hashCtx, result); 292 result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_Delegate_UpdateVerification); 293 result |= Trspi_Hash_UINT32(&hashCtx, outputSize); 294 result |= Trspi_HashUpdate(&hashCtx, outputSize, output); 295 if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) 296 goto done; 297 298 if ((result = obj_policy_validate_auth_oiap(hPolicy, &digest, pAuth))) 299 goto done; 300 } 301 302 result = obj_policy_set_delegation_blob(hDelegation, 0, outputSize, output); 303 304done: 305 free_tspi(hContext, input); 306 free(output); 307 308 return result; 309} 310 311TSS_RESULT 312Tspi_TPM_Delegate_VerifyDelegation(TSS_HPOLICY hDelegation) /* in, out */ 313{ 314 TSS_HCONTEXT hContext; 315 UINT32 delegateSize; 316 BYTE *delegate = NULL; 317 TSS_RESULT result; 318 319 if ((result = obj_policy_get_tsp_context(hDelegation, &hContext))) 320 return result; 321 322 if ((result = obj_policy_get_delegation_blob(hDelegation, 0, &delegateSize, &delegate))) 323 return result; 324 325 result = TCS_API(hContext)->Delegate_VerifyDelegation(hContext, delegateSize, delegate); 326 327 free_tspi(hContext, delegate); 328 329 return result; 330} 331 332TSS_RESULT 333Tspi_TPM_Delegate_ReadTables(TSS_HCONTEXT hContext, /* in */ 334 UINT32* pulFamilyTableSize, /* out */ 335 TSS_FAMILY_TABLE_ENTRY** ppFamilyTable, /* out */ 336 UINT32* pulDelegateTableSize, /* out */ 337 TSS_DELEGATION_TABLE_ENTRY** ppDelegateTable) /* out */ 338{ 339 UINT32 tpmFamilyTableSize, tpmDelegateTableSize; 340 BYTE *tpmFamilyTable = NULL, *tpmDelegateTable = NULL; 341 TPM_FAMILY_TABLE_ENTRY tpmFamilyEntry; 342 TSS_FAMILY_TABLE_ENTRY tssFamilyEntry, *tssFamilyTable = NULL; 343 UINT32 tssFamilyTableSize = 0; 344 TPM_DELEGATE_PUBLIC tpmDelegatePublic; 345 TSS_DELEGATION_TABLE_ENTRY tssDelegateEntry, *tssDelegateTable = NULL; 346 UINT32 tssDelegateTableSize = 0; 347 UINT32 tableIndex; 348 UINT64 tpmOffset; 349 UINT64 tssOffset; 350 TSS_RESULT result; 351 352 if (!pulFamilyTableSize || !ppFamilyTable || !pulDelegateTableSize || !ppDelegateTable) 353 return TSPERR(TSS_E_BAD_PARAMETER); 354 355 if (!obj_is_context(hContext)) 356 return TSPERR(TSS_E_INVALID_HANDLE); 357 358 if ((result = TCS_API(hContext)->Delegate_ReadTable(hContext, &tpmFamilyTableSize, 359 &tpmFamilyTable, &tpmDelegateTableSize, 360 &tpmDelegateTable))) 361 return result; 362 363 if (tpmFamilyTableSize > 0) { 364 /* Create the TSS_FAMILY_TABLE_ENTRY array */ 365 for (tpmOffset = 0, tssOffset = 0; tpmOffset < tpmFamilyTableSize;) { 366 Trspi_UnloadBlob_TPM_FAMILY_TABLE_ENTRY(&tpmOffset, tpmFamilyTable, 367 &tpmFamilyEntry); 368 369 /* No pointers in the family table entries, so no 370 assignments required before doing LoadBlob */ 371 Trspi_LoadBlob_TSS_FAMILY_TABLE_ENTRY(&tssOffset, NULL, &tssFamilyEntry); 372 } 373 374 if ((tssFamilyTable = calloc_tspi(hContext, tssOffset)) == NULL) { 375 LogError("malloc of %" PRIu64 " bytes failed.", tssOffset); 376 result = TSPERR(TSS_E_OUTOFMEMORY); 377 goto done; 378 } 379 for (tpmOffset = 0, tssOffset = 0; tpmOffset < tpmFamilyTableSize; tssFamilyTableSize++) { 380 Trspi_UnloadBlob_TPM_FAMILY_TABLE_ENTRY(&tpmOffset, tpmFamilyTable, 381 &tpmFamilyEntry); 382 383 tssFamilyEntry.familyID = tpmFamilyEntry.familyID; 384 tssFamilyEntry.label = tpmFamilyEntry.label.label; 385 tssFamilyEntry.verificationCount = tpmFamilyEntry.verificationCount; 386 tssFamilyEntry.enabled = 387 (tpmFamilyEntry.flags & TPM_FAMFLAG_ENABLE) ? TRUE : FALSE; 388 tssFamilyEntry.locked = 389 (tpmFamilyEntry.flags & TPM_FAMFLAG_DELEGATE_ADMIN_LOCK) ? TRUE : FALSE; 390 Trspi_LoadBlob_TSS_FAMILY_TABLE_ENTRY(&tssOffset, (BYTE *)tssFamilyTable, 391 &tssFamilyEntry); 392 } 393 } 394 395 if (tpmDelegateTableSize > 0) { 396 /* Create the TSS_DELEGATION_TABLE_ENTRY array */ 397 for (tpmOffset = 0, tssOffset = 0; tpmOffset < tpmDelegateTableSize;) { 398 Trspi_UnloadBlob_UINT32(&tpmOffset, &tableIndex, tpmDelegateTable); 399 if ((result = Trspi_UnloadBlob_TPM_DELEGATE_PUBLIC(&tpmOffset, tpmDelegateTable, 400 &tpmDelegatePublic))) { 401 free_tspi(hContext, tssFamilyTable); 402 goto done; 403 } 404 405 /* Some pointers in the delegate table entries, so 406 do some assignments before doing LoadBlob */ 407 tssDelegateEntry.pcrInfo.sizeOfSelect = 408 tpmDelegatePublic.pcrInfo.pcrSelection.sizeOfSelect; 409 tssDelegateEntry.pcrInfo.selection = 410 tpmDelegatePublic.pcrInfo.pcrSelection.pcrSelect; 411 tssDelegateEntry.pcrInfo.sizeOfDigestAtRelease = 412 sizeof(tpmDelegatePublic.pcrInfo.digestAtRelease.digest); 413 tssDelegateEntry.pcrInfo.digestAtRelease = 414 tpmDelegatePublic.pcrInfo.digestAtRelease.digest; 415 Trspi_LoadBlob_TSS_DELEGATION_TABLE_ENTRY(&tssOffset, NULL, 416 &tssDelegateEntry); 417 418 free(tpmDelegatePublic.pcrInfo.pcrSelection.pcrSelect); 419 } 420 421 if ((tssDelegateTable = calloc_tspi(hContext, tssOffset)) == NULL) { 422 LogError("malloc of %" PRIu64 " bytes failed.", tssOffset); 423 free_tspi(hContext, tssFamilyTable); 424 result = TSPERR(TSS_E_OUTOFMEMORY); 425 goto done; 426 } 427 for (tpmOffset = 0, tssOffset = 0; tpmOffset < tpmDelegateTableSize; tssDelegateTableSize++) { 428 Trspi_UnloadBlob_UINT32(&tpmOffset, &tableIndex, tpmDelegateTable); 429 if ((result = Trspi_UnloadBlob_TPM_DELEGATE_PUBLIC(&tpmOffset, 430 tpmDelegateTable, &tpmDelegatePublic))) { 431 free_tspi(hContext, tssFamilyTable); 432 free_tspi(hContext, tssDelegateTable); 433 goto done; 434 } 435 436 tssDelegateEntry.tableIndex = tableIndex; 437 tssDelegateEntry.label = tpmDelegatePublic.label.label; 438 tssDelegateEntry.pcrInfo.sizeOfSelect = 439 tpmDelegatePublic.pcrInfo.pcrSelection.sizeOfSelect; 440 tssDelegateEntry.pcrInfo.selection = 441 tpmDelegatePublic.pcrInfo.pcrSelection.pcrSelect; 442 tssDelegateEntry.pcrInfo.localityAtRelease = 443 tpmDelegatePublic.pcrInfo.localityAtRelease; 444 tssDelegateEntry.pcrInfo.sizeOfDigestAtRelease = 445 sizeof(tpmDelegatePublic.pcrInfo.digestAtRelease.digest); 446 tssDelegateEntry.pcrInfo.digestAtRelease = 447 tpmDelegatePublic.pcrInfo.digestAtRelease.digest; 448 tssDelegateEntry.per1 = tpmDelegatePublic.permissions.per1; 449 tssDelegateEntry.per2 = tpmDelegatePublic.permissions.per2; 450 tssDelegateEntry.familyID = tpmDelegatePublic.familyID; 451 tssDelegateEntry.verificationCount = tpmDelegatePublic.verificationCount; 452 Trspi_LoadBlob_TSS_DELEGATION_TABLE_ENTRY(&tssOffset, 453 (BYTE *)tssDelegateTable, &tssDelegateEntry); 454 455 free(tpmDelegatePublic.pcrInfo.pcrSelection.pcrSelect); 456 } 457 } 458 459 *ppFamilyTable = tssFamilyTable; 460 *pulFamilyTableSize = tssFamilyTableSize; 461 *ppDelegateTable = tssDelegateTable; 462 *pulDelegateTableSize = tssDelegateTableSize; 463 464done: 465 free(tpmFamilyTable); 466 free(tpmDelegateTable); 467 468 return result; 469} 470 471