Return to tpm_tss_trousers.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libtpmtss |
1.1 ! misho 1: /* ! 2: * Copyright (C) 2016 Andreas Steffen ! 3: * HSR Hochschule fuer Technik Rapperswil ! 4: * ! 5: * Copyright (c) 2008 Hal Finney ! 6: * ! 7: * Permission is hereby granted, free of charge, to any person obtaining a copy ! 8: * of this software and associated documentation files (the "Software"), to deal ! 9: * in the Software without restriction, including without limitation the rights ! 10: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ! 11: * copies of the Software, and to permit persons to whom the Software is ! 12: * furnished to do so, subject to the following conditions: ! 13: * ! 14: * The above copyright notice and this permission notice shall be included in ! 15: * all copies or substantial portions of the Software. ! 16: * ! 17: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ! 18: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ! 19: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ! 20: * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ! 21: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ! 22: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ! 23: * THE SOFTWARE. ! 24: */ ! 25: ! 26: #include "tpm_tss_trousers.h" ! 27: ! 28: #ifdef TSS_TROUSERS ! 29: ! 30: #ifdef _BASETSD_H_ ! 31: /* MinGW defines _BASETSD_H_, but TSS checks for _BASETSD_H */ ! 32: # define _BASETSD_H ! 33: #endif ! 34: ! 35: #include <trousers/tss.h> ! 36: #include <trousers/trousers.h> ! 37: ! 38: #define LABEL "TPM 1.2 -" ! 39: ! 40: /* size in bytes of a TSS AIK public key blob */ ! 41: #define AIK_PUBKEY_BLOB_SIZE 284 ! 42: ! 43: /* maximum number of PCR registers */ ! 44: #define PCR_NUM_MAX 24 ! 45: ! 46: typedef struct private_tpm_tss_trousers_t private_tpm_tss_trousers_t; ! 47: typedef struct aik_t aik_t; ! 48: ! 49: /** ! 50: * Private data of an tpm_tss_trousers_t object. ! 51: */ ! 52: struct private_tpm_tss_trousers_t { ! 53: ! 54: /** ! 55: * Public tpm_tss_trousers_t interface. ! 56: */ ! 57: tpm_tss_trousers_t interface; ! 58: ! 59: /** ! 60: * TSS context ! 61: */ ! 62: TSS_HCONTEXT hContext; ! 63: ! 64: /** ! 65: * TPM handle ! 66: */ ! 67: TSS_HTPM hTPM; ! 68: ! 69: /** ! 70: * TPM version info ! 71: */ ! 72: chunk_t version_info; ! 73: ! 74: /** ! 75: * List of AIKs retrievable by an object handle ! 76: */ ! 77: linked_list_t *aik_list; ! 78: ! 79: }; ! 80: ! 81: struct aik_t { ! 82: /** AIK object handle */ ! 83: uint32_t handle; ! 84: ! 85: /** AIK private key blob */ ! 86: chunk_t blob; ! 87: ! 88: /** AIK public key */ ! 89: chunk_t pubkey; ! 90: }; ! 91: ! 92: static void free_aik(aik_t *this) ! 93: { ! 94: free(this->blob.ptr); ! 95: free(this->pubkey.ptr); ! 96: free(this); ! 97: } ! 98: ! 99: /** ! 100: * Initialize TSS context ! 101: * ! 102: * TPM 1.2 Specification, Part 2 TPM Structures, 21.6 TPM_CAP_VERSION_INFO ! 103: * ! 104: * typedef struct tdTPM_VERSION { ! 105: * TPM_VERSION_BYTE major; ! 106: * TPM_VERSION_BYTE minor; ! 107: * BYTE revMajor; ! 108: * BYTE revMinor; ! 109: * } TPM_VERSION; ! 110: * ! 111: * typedef struct tdTPM_CAP_VERSION_INFO { ! 112: * TPM_STRUCTURE_TAG tag; ! 113: * TPM_VERSION version; ! 114: * UINT16 specLevel; ! 115: * BYTE errataRev; ! 116: * BYTE tpmVendorID[4]; ! 117: * UINT16 vendorSpecificSize; ! 118: * [size_is(vendorSpecificSize)] BYTE* vendorSpecific; ! 119: * } TPM_CAP_VERSION_INFO; ! 120: */ ! 121: static bool initialize_context(private_tpm_tss_trousers_t *this) ! 122: { ! 123: uint8_t *version_ptr; ! 124: uint32_t version_len; ! 125: ! 126: TSS_RESULT result; ! 127: TPM_CAP_VERSION_INFO *info; ! 128: ! 129: result = Tspi_Context_Create(&this->hContext); ! 130: if (result != TSS_SUCCESS) ! 131: { ! 132: DBG1(DBG_PTS, "%s could not created context: 0x%x", ! 133: LABEL, result); ! 134: return FALSE; ! 135: } ! 136: ! 137: result = Tspi_Context_Connect(this->hContext, NULL); ! 138: if (result != TSS_SUCCESS) ! 139: { ! 140: DBG1(DBG_PTS, "%s could not connect with context: 0x%x", ! 141: LABEL, result); ! 142: return FALSE; ! 143: } ! 144: ! 145: result = Tspi_Context_GetTpmObject (this->hContext, &this->hTPM); ! 146: if (result != TSS_SUCCESS) ! 147: { ! 148: DBG1(DBG_PTS, "%s could not get TPM object: 0x%x", ! 149: LABEL, result); ! 150: return FALSE; ! 151: } ! 152: ! 153: result = Tspi_TPM_GetCapability(this->hTPM, TSS_TPMCAP_VERSION_VAL, 0, ! 154: NULL, &version_len, &version_ptr); ! 155: if (result != TSS_SUCCESS) ! 156: { ! 157: DBG1(DBG_PTS, "%s Tspi_TPM_GetCapability failed: 0x%x", ! 158: LABEL, result); ! 159: return FALSE; ! 160: } ! 161: ! 162: info = (TPM_CAP_VERSION_INFO *)version_ptr; ! 163: DBG2(DBG_PTS, "TPM Version Info: Chip Version: %u.%u.%u.%u, " ! 164: "Spec Level: %u, Errata Rev: %u, Vendor ID: %.4s", ! 165: info->version.major, info->version.minor, ! 166: info->version.revMajor, info->version.revMinor, ! 167: untoh16(&info->specLevel), info->errataRev, info->tpmVendorID); ! 168: ! 169: this->version_info = chunk_clone(chunk_create(version_ptr, version_len)); ! 170: ! 171: return TRUE; ! 172: } ! 173: ! 174: /** ! 175: * Finalize TSS context ! 176: */ ! 177: static void finalize_context(private_tpm_tss_trousers_t *this) ! 178: { ! 179: if (this->hContext) ! 180: { ! 181: Tspi_Context_FreeMemory(this->hContext, NULL); ! 182: Tspi_Context_Close(this->hContext); ! 183: } ! 184: } ! 185: ! 186: METHOD(tpm_tss_t, get_version, tpm_version_t, ! 187: private_tpm_tss_trousers_t *this) ! 188: { ! 189: return TPM_VERSION_1_2; ! 190: } ! 191: ! 192: METHOD(tpm_tss_t, get_version_info, chunk_t, ! 193: private_tpm_tss_trousers_t *this) ! 194: { ! 195: return this->version_info; ! 196: } ! 197: ! 198: METHOD(tpm_tss_t, generate_aik, bool, ! 199: private_tpm_tss_trousers_t *this, chunk_t ca_modulus, chunk_t *aik_blob, ! 200: chunk_t *aik_pubkey, chunk_t *identity_req) ! 201: { ! 202: chunk_t aik_pubkey_blob; ! 203: chunk_t aik_modulus; ! 204: chunk_t aik_exponent; ! 205: ! 206: TSS_RESULT result; ! 207: TSS_HKEY hSRK; ! 208: TSS_HKEY hPCAKey; ! 209: TSS_HPOLICY hSrkPolicy; ! 210: TSS_HPOLICY hTPMPolicy; ! 211: TSS_HKEY hIdentKey; ! 212: TSS_UUID SRK_UUID = TSS_UUID_SRK; ! 213: BYTE secret[] = TSS_WELL_KNOWN_SECRET; ! 214: BYTE *IdentityReq; ! 215: UINT32 IdentityReqLen; ! 216: BYTE *blob; ! 217: UINT32 blobLen; ! 218: ! 219: /* get SRK plus SRK policy and set SRK secret */ ! 220: result = Tspi_Context_LoadKeyByUUID(this->hContext, TSS_PS_TYPE_SYSTEM, ! 221: SRK_UUID, &hSRK); ! 222: if (result != TSS_SUCCESS) ! 223: { ! 224: DBG1(DBG_PTS, "%s Tspi_Context_LoadKeyByUUID for SRK failed: 0x%x", ! 225: LABEL, result); ! 226: return FALSE; ! 227: } ! 228: result = Tspi_GetPolicyObject(hSRK, TSS_POLICY_USAGE, &hSrkPolicy); ! 229: if (result != TSS_SUCCESS) ! 230: { ! 231: DBG1(DBG_PTS, "%s Tspi_GetPolicyObject or SRK failed: 0x%x ", ! 232: LABEL, result); ! 233: return FALSE; ! 234: } ! 235: result = Tspi_Policy_SetSecret(hSrkPolicy, TSS_SECRET_MODE_SHA1, 20, secret); ! 236: if (result != TSS_SUCCESS) ! 237: { ! 238: DBG1(DBG_PTS, "%s Tspi_Policy_SetSecret for SRK failed: 0x%x ", ! 239: LABEL, result); ! 240: return FALSE; ! 241: } ! 242: ! 243: /* get TPM plus TPM policy and set TPM secret */ ! 244: result = Tspi_Context_GetTpmObject (this->hContext, &this->hTPM); ! 245: if (result != TSS_SUCCESS) ! 246: { ! 247: DBG1(DBG_PTS, "%s Tspi_Context_GetTpmObject failed: 0x%x", ! 248: LABEL, result); ! 249: return FALSE; ! 250: } ! 251: result = Tspi_GetPolicyObject(this->hTPM, TSS_POLICY_USAGE, &hTPMPolicy); ! 252: if (result != TSS_SUCCESS) ! 253: { ! 254: DBG1(DBG_PTS, "%s Tspi_GetPolicyObject for TPM failed: 0x%x", ! 255: LABEL, result); ! 256: return FALSE; ! 257: } ! 258: result = Tspi_Policy_SetSecret(hTPMPolicy, TSS_SECRET_MODE_SHA1, 20, secret); ! 259: if (result != TSS_SUCCESS) ! 260: { ! 261: DBG1(DBG_PTS,"%s Tspi_Policy_SetSecret for TPM failed: 0x%x", ! 262: LABEL, result); ! 263: return FALSE; ! 264: } ! 265: ! 266: /* create context for a 2048 bit AIK */ ! 267: result = Tspi_Context_CreateObject(this->hContext, TSS_OBJECT_TYPE_RSAKEY, ! 268: TSS_KEY_TYPE_IDENTITY | TSS_KEY_SIZE_2048 | ! 269: TSS_KEY_VOLATILE | TSS_KEY_NOT_MIGRATABLE, &hIdentKey); ! 270: if (result != TSS_SUCCESS) ! 271: { ! 272: DBG1(DBG_PTS, "%s Tspi_Context_CreateObject for key failed: 0x%x", ! 273: LABEL, result); ! 274: return FALSE; ! 275: } ! 276: ! 277: /* create context for the Privacy CA public key and assign modulus */ ! 278: result = Tspi_Context_CreateObject(this->hContext, TSS_OBJECT_TYPE_RSAKEY, ! 279: TSS_KEY_TYPE_LEGACY|TSS_KEY_SIZE_2048, &hPCAKey); ! 280: if (result != TSS_SUCCESS) ! 281: { ! 282: DBG1(DBG_PTS, "%s Tspi_Context_CreateObject for PCA failed: 0x%x", ! 283: LABEL, result); ! 284: return FALSE; ! 285: } ! 286: result = Tspi_SetAttribData (hPCAKey, TSS_TSPATTRIB_RSAKEY_INFO, ! 287: TSS_TSPATTRIB_KEYINFO_RSA_MODULUS, ca_modulus.len, ! 288: ca_modulus.ptr); ! 289: if (result != TSS_SUCCESS) ! 290: { ! 291: DBG1(DBG_PTS, "%s Tspi_SetAttribData for PCA modulus failed: 0x%x", ! 292: LABEL, result); ! 293: return FALSE; ! 294: } ! 295: result = Tspi_SetAttribUint32(hPCAKey, TSS_TSPATTRIB_KEY_INFO, ! 296: TSS_TSPATTRIB_KEYINFO_ENCSCHEME, TSS_ES_RSAESPKCSV15); ! 297: if (result != TSS_SUCCESS) ! 298: { ! 299: DBG1(DBG_PTS,"%s Tspi_SetAttribUint32 for PCA encryption scheme " ! 300: "failed: 0x%x", LABEL, result); ! 301: return FALSE; ! 302: } ! 303: ! 304: /* generate AIK */ ! 305: DBG1(DBG_LIB, "Generating identity key..."); ! 306: result = Tspi_TPM_CollateIdentityRequest(this->hTPM, hSRK, hPCAKey, 0, NULL, ! 307: hIdentKey, TSS_ALG_AES, &IdentityReqLen, &IdentityReq); ! 308: if (result != TSS_SUCCESS) ! 309: { ! 310: DBG1(DBG_PTS, "%s Tspi_TPM_CollateIdentityRequest failed: 0x%x", ! 311: LABEL, result); ! 312: return FALSE; ! 313: } ! 314: *identity_req = chunk_create(IdentityReq, IdentityReqLen); ! 315: DBG3(DBG_LIB, "%s Identity Request: %B", LABEL, identity_req); ! 316: ! 317: /* load identity key */ ! 318: result = Tspi_Key_LoadKey (hIdentKey, hSRK); ! 319: if (result != TSS_SUCCESS) ! 320: { ! 321: DBG1(DBG_PTS, "%s Tspi_Key_LoadKey for AIK failed: 0x%x", ! 322: LABEL, result); ! 323: return FALSE; ! 324: } ! 325: ! 326: /* output AIK private key in TSS blob format */ ! 327: result = Tspi_GetAttribData (hIdentKey, TSS_TSPATTRIB_KEY_BLOB, ! 328: TSS_TSPATTRIB_KEYBLOB_BLOB, &blobLen, &blob); ! 329: if (result != TSS_SUCCESS) ! 330: { ! 331: DBG1(DBG_PTS, "%s Tspi_GetAttribData for private key blob failed: 0x%x", ! 332: LABEL, result); ! 333: return FALSE; ! 334: } ! 335: *aik_blob = chunk_create(blob, blobLen); ! 336: DBG3(DBG_LIB, "%s AIK private key blob: %B", LABEL, aik_blob); ! 337: ! 338: /* output AIK Public Key in TSS blob format */ ! 339: result = Tspi_GetAttribData (hIdentKey, TSS_TSPATTRIB_KEY_BLOB, ! 340: TSS_TSPATTRIB_KEYBLOB_PUBLIC_KEY, &blobLen, &blob); ! 341: if (result != TSS_SUCCESS) ! 342: { ! 343: DBG1(DBG_PTS, "%s Tspi_GetAttribData for public key blob failed: 0x%x", ! 344: LABEL, result); ! 345: return FALSE; ! 346: } ! 347: aik_pubkey_blob = chunk_create(blob, blobLen); ! 348: DBG3(DBG_LIB, "%s AIK public key blob: %B", LABEL, &aik_pubkey_blob); ! 349: ! 350: /* create a trusted AIK public key */ ! 351: if (aik_pubkey_blob.len != AIK_PUBKEY_BLOB_SIZE) ! 352: { ! 353: DBG1(DBG_PTS, "%s AIK public key is not in TSS blob format", ! 354: LABEL); ! 355: return FALSE; ! 356: } ! 357: aik_modulus = chunk_skip(aik_pubkey_blob, AIK_PUBKEY_BLOB_SIZE - 256); ! 358: aik_exponent = chunk_from_chars(0x01, 0x00, 0x01); ! 359: ! 360: /* output subjectPublicKeyInfo encoding of AIK public key */ ! 361: if (!lib->encoding->encode(lib->encoding, PUBKEY_SPKI_ASN1_DER, NULL, ! 362: aik_pubkey, CRED_PART_RSA_MODULUS, aik_modulus, ! 363: CRED_PART_RSA_PUB_EXP, aik_exponent, CRED_PART_END)) ! 364: { ! 365: DBG1(DBG_PTS, "%s subjectPublicKeyInfo encoding of AIK key failed", ! 366: LABEL); ! 367: return FALSE; ! 368: } ! 369: return TRUE; ! 370: } ! 371: ! 372: METHOD(tpm_tss_t, get_public, chunk_t, ! 373: private_tpm_tss_trousers_t *this, uint32_t handle) ! 374: { ! 375: enumerator_t *enumerator; ! 376: chunk_t aik_pubkey = chunk_empty; ! 377: aik_t *aik; ! 378: ! 379: enumerator = this->aik_list->create_enumerator(this->aik_list); ! 380: while (enumerator->enumerate(enumerator, &aik)) ! 381: { ! 382: if (aik->handle == handle) ! 383: { ! 384: aik_pubkey = chunk_clone(aik->pubkey); ! 385: break; ! 386: } ! 387: } ! 388: enumerator->destroy(enumerator); ! 389: ! 390: return aik_pubkey; ! 391: } ! 392: ! 393: METHOD(tpm_tss_t, supported_signature_schemes, enumerator_t*, ! 394: private_tpm_tss_trousers_t *this, uint32_t handle) ! 395: { ! 396: return enumerator_create_empty(); ! 397: } ! 398: ! 399: METHOD(tpm_tss_t, read_pcr, bool, ! 400: private_tpm_tss_trousers_t *this, uint32_t pcr_num, chunk_t *pcr_value, ! 401: hash_algorithm_t alg) ! 402: { ! 403: TSS_RESULT result; ! 404: uint8_t *value; ! 405: uint32_t len; ! 406: ! 407: result = Tspi_TPM_PcrRead(this->hTPM, pcr_num, &len, &value); ! 408: if (result != TSS_SUCCESS) ! 409: { ! 410: DBG1(DBG_PTS, "%s Tspi_TPM_PcrRead failed: 0x%x", LABEL, result); ! 411: return FALSE; ! 412: } ! 413: *pcr_value = chunk_clone(chunk_create(value, len)); ! 414: ! 415: return TRUE; ! 416: } ! 417: ! 418: METHOD(tpm_tss_t, extend_pcr, bool, ! 419: private_tpm_tss_trousers_t *this, uint32_t pcr_num, chunk_t *pcr_value, ! 420: chunk_t data, hash_algorithm_t alg) ! 421: { ! 422: TSS_RESULT result; ! 423: uint32_t pcr_len; ! 424: uint8_t *pcr_ptr; ! 425: ! 426: result = Tspi_TPM_PcrExtend(this->hTPM, pcr_num, data.len, data.ptr, ! 427: NULL, &pcr_len, &pcr_ptr); ! 428: if (result != TSS_SUCCESS) ! 429: { ! 430: DBG1(DBG_PTS, "%s Tspi_TPM_PcrExtend failed: 0x%x", LABEL, result); ! 431: return FALSE; ! 432: } ! 433: *pcr_value = chunk_clone(chunk_create(pcr_ptr, pcr_len)); ! 434: ! 435: return TRUE; ! 436: } ! 437: ! 438: METHOD(tpm_tss_t, quote, bool, ! 439: private_tpm_tss_trousers_t *this, uint32_t aik_handle, uint32_t pcr_sel, ! 440: hash_algorithm_t alg, chunk_t data, tpm_quote_mode_t *quote_mode, ! 441: tpm_tss_quote_info_t **quote_info, chunk_t *quote_sig) ! 442: { ! 443: TSS_HKEY hAIK; ! 444: TSS_HKEY hSRK; ! 445: TSS_HPOLICY srkUsagePolicy; ! 446: TSS_UUID SRK_UUID = TSS_UUID_SRK; ! 447: TSS_HPCRS hPcrComposite; ! 448: TSS_VALIDATION valData; ! 449: TSS_RESULT result; ! 450: uint8_t secret[] = TSS_WELL_KNOWN_SECRET; ! 451: uint8_t *version_info, *comp_hash; ! 452: uint32_t version_info_size, pcr; ! 453: aik_t *aik; ! 454: chunk_t aik_blob = chunk_empty; ! 455: chunk_t quote_chunk, pcr_digest; ! 456: enumerator_t *enumerator; ! 457: bool success = FALSE; ! 458: ! 459: /* Retrieve SRK from TPM and set the authentication to well known secret*/ ! 460: result = Tspi_Context_LoadKeyByUUID(this->hContext, TSS_PS_TYPE_SYSTEM, ! 461: SRK_UUID, &hSRK); ! 462: if (result != TSS_SUCCESS) ! 463: { ! 464: DBG1(DBG_PTS, "%s Tspi_Context_LoadKeyByUUID for SRK failed: 0x%x", ! 465: LABEL, result); ! 466: return FALSE; ! 467: } ! 468: result = Tspi_GetPolicyObject(hSRK, TSS_POLICY_USAGE, &srkUsagePolicy); ! 469: if (result != TSS_SUCCESS) ! 470: { ! 471: DBG1(DBG_PTS, "%s Tspi_GetPolicyObject for SRK failed: 0x%x", ! 472: LABEL, result); ! 473: return FALSE; ! 474: } ! 475: result = Tspi_Policy_SetSecret(srkUsagePolicy, TSS_SECRET_MODE_SHA1, ! 476: 20, secret); ! 477: if (result != TSS_SUCCESS) ! 478: { ! 479: DBG1(DBG_PTS, "%s Tspi_Policy_SetSecret for SRK failed: 0x%x", ! 480: LABEL, result); ! 481: return FALSE; ! 482: } ! 483: ! 484: /* Retrieve AIK using its handle and load private key into TPM 1.2 */ ! 485: enumerator = this->aik_list->create_enumerator(this->aik_list); ! 486: while (enumerator->enumerate(enumerator, &aik)) ! 487: { ! 488: if (aik->handle == aik_handle) ! 489: { ! 490: aik_blob = aik->blob; ! 491: break; ! 492: } ! 493: } ! 494: enumerator->destroy(enumerator); ! 495: ! 496: if (aik_blob.len == 0) ! 497: { ! 498: DBG1(DBG_PTS, "%s AIK private key for handle 0x%80x not found", LABEL); ! 499: return FALSE; ! 500: } ! 501: result = Tspi_Context_LoadKeyByBlob(this->hContext, hSRK, aik_blob.len, ! 502: aik_blob.ptr, &hAIK); ! 503: if (result != TSS_SUCCESS) ! 504: { ! 505: DBG1(DBG_PTS, "%s Tspi_Context_LoadKeyByBlob for AIK failed: 0x%x", ! 506: LABEL, result); ! 507: return FALSE; ! 508: } ! 509: ! 510: /* Create PCR composite object */ ! 511: result = Tspi_Context_CreateObject(this->hContext, TSS_OBJECT_TYPE_PCRS, ! 512: (*quote_mode == TPM_QUOTE) ? TSS_PCRS_STRUCT_INFO : ! 513: TSS_PCRS_STRUCT_INFO_SHORT, ! 514: &hPcrComposite); ! 515: if (result != TSS_SUCCESS) ! 516: { ! 517: DBG1(DBG_PTS, "%s Tspi_Context_CreateObject for pcrComposite failed: " ! 518: "0x%x", LABEL, result); ! 519: goto err1; ! 520: } ! 521: ! 522: /* Select PCRs */ ! 523: for (pcr = 0; pcr < PCR_NUM_MAX; pcr++) ! 524: { ! 525: if (pcr_sel & (1 << pcr)) ! 526: { ! 527: result = (*quote_mode == TPM_QUOTE) ? ! 528: Tspi_PcrComposite_SelectPcrIndex(hPcrComposite, pcr) : ! 529: Tspi_PcrComposite_SelectPcrIndexEx(hPcrComposite, pcr, ! 530: TSS_PCRS_DIRECTION_RELEASE); ! 531: if (result != TSS_SUCCESS) ! 532: { ! 533: DBG1(DBG_PTS, "%s Tspi_PcrComposite_SelectPcrIndex failed: " ! 534: "0x%x", LABEL, result); ! 535: goto err2; ! 536: } ! 537: } ! 538: } ! 539: ! 540: /* Set the Validation Data */ ! 541: valData.ulExternalDataLength = data.len; ! 542: valData.rgbExternalData = data.ptr; ! 543: ! 544: /* TPM Quote */ ! 545: result = (*quote_mode == TPM_QUOTE) ? ! 546: Tspi_TPM_Quote (this->hTPM, hAIK, hPcrComposite, &valData) : ! 547: Tspi_TPM_Quote2(this->hTPM, hAIK, ! 548: *quote_mode == TPM_QUOTE2_VERSION_INFO, ! 549: hPcrComposite, &valData, &version_info_size, ! 550: &version_info); ! 551: if (result != TSS_SUCCESS) ! 552: { ! 553: DBG1(DBG_PTS, "%s Tspi_TPM_Quote%s failed: 0x%x", LABEL, ! 554: (*quote_mode == TPM_QUOTE) ? "" : "2", result); ! 555: goto err2; ! 556: } ! 557: ! 558: if (*quote_mode == TPM_QUOTE) ! 559: { ! 560: /* TPM_Composite_Hash starts at byte 8 of TPM_Quote_Info structure */ ! 561: comp_hash = valData.rgbData + 8; ! 562: } ! 563: else ! 564: { ! 565: /* TPM_Composite_Hash is last 20 bytes of TPM_Quote_Info2 structure */ ! 566: comp_hash = valData.rgbData + valData.ulDataLength - version_info_size - ! 567: HASH_SIZE_SHA1; ! 568: } ! 569: pcr_digest = chunk_create(comp_hash, HASH_SIZE_SHA1); ! 570: DBG2(DBG_PTS, "PCR composite digest: %B", &pcr_digest); ! 571: ! 572: quote_chunk = chunk_create(valData.rgbData, valData.ulDataLength); ! 573: DBG2(DBG_PTS, "TPM Quote Info: %B", "e_chunk); ! 574: ! 575: *quote_info = tpm_tss_quote_info_create(*quote_mode, HASH_SHA1, pcr_digest); ! 576: ! 577: *quote_sig = chunk_clone(chunk_create(valData.rgbValidationData, ! 578: valData.ulValidationDataLength)); ! 579: DBG2(DBG_PTS, "TPM Quote Signature: %B", quote_sig); ! 580: ! 581: success = TRUE; ! 582: ! 583: err2: ! 584: Tspi_Context_CloseObject(this->hContext, hPcrComposite); ! 585: err1: ! 586: Tspi_Context_CloseObject(this->hContext, hAIK); ! 587: ! 588: return success; ! 589: } ! 590: ! 591: METHOD(tpm_tss_t, sign, bool, ! 592: private_tpm_tss_trousers_t *this, uint32_t hierarchy, uint32_t handle, ! 593: signature_scheme_t scheme, void *params, chunk_t data, chunk_t pin, ! 594: chunk_t *signature) ! 595: { ! 596: return FALSE; ! 597: } ! 598: ! 599: METHOD(tpm_tss_t, get_random, bool, ! 600: private_tpm_tss_trousers_t *this, size_t bytes, uint8_t *buffer) ! 601: { ! 602: return FALSE; ! 603: } ! 604: ! 605: METHOD(tpm_tss_t, get_data, bool, ! 606: private_tpm_tss_trousers_t *this, uint32_t hierarchy, uint32_t handle, ! 607: chunk_t pin, chunk_t *data) ! 608: { ! 609: return FALSE; ! 610: } ! 611: ! 612: METHOD(tpm_tss_t, destroy, void, ! 613: private_tpm_tss_trousers_t *this) ! 614: { ! 615: finalize_context(this); ! 616: this->aik_list->destroy_function(this->aik_list, (void*)free_aik); ! 617: free(this->version_info.ptr); ! 618: free(this); ! 619: } ! 620: ! 621: METHOD(tpm_tss_trousers_t, load_aik, void, ! 622: private_tpm_tss_trousers_t *this, chunk_t blob, chunk_t pubkey, ! 623: uint32_t handle) ! 624: { ! 625: aik_t *item; ! 626: ! 627: INIT(item, ! 628: .handle = handle, ! 629: .blob = blob, ! 630: .pubkey = pubkey, ! 631: ); ! 632: ! 633: this->aik_list->insert_last(this->aik_list, item); ! 634: } ! 635: ! 636: /** ! 637: * See header ! 638: */ ! 639: tpm_tss_t *tpm_tss_trousers_create() ! 640: { ! 641: private_tpm_tss_trousers_t *this; ! 642: bool available; ! 643: ! 644: INIT(this, ! 645: .interface = { ! 646: .public = { ! 647: .get_version = _get_version, ! 648: .get_version_info = _get_version_info, ! 649: .generate_aik = _generate_aik, ! 650: .get_public = _get_public, ! 651: .supported_signature_schemes = _supported_signature_schemes, ! 652: .read_pcr = _read_pcr, ! 653: .extend_pcr = _extend_pcr, ! 654: .quote = _quote, ! 655: .sign = _sign, ! 656: .get_random = _get_random, ! 657: .get_data = _get_data, ! 658: .destroy = _destroy, ! 659: }, ! 660: .load_aik = _load_aik, ! 661: }, ! 662: .aik_list = linked_list_create(), ! 663: ); ! 664: ! 665: available = initialize_context(this); ! 666: DBG1(DBG_PTS, "TPM 1.2 via TrouSerS %savailable", available ? "" : "not "); ! 667: ! 668: if (!available) ! 669: { ! 670: destroy(this); ! 671: return NULL; ! 672: } ! 673: return &this->interface.public; ! 674: } ! 675: ! 676: #else /* TSS_TROUSERS */ ! 677: ! 678: tpm_tss_t *tpm_tss_trousers_create() ! 679: { ! 680: return NULL; ! 681: } ! 682: ! 683: #endif /* TSS_TROUSERS */ ! 684: ! 685: ! 686: