Return to tpm_tss_tss2_v1.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libtpmtss |
1.1 ! misho 1: /* ! 2: * Copyright (C) 2018 Tobias Brunner ! 3: * Copyright (C) 2016-2019 Andreas Steffen ! 4: * HSR Hochschule fuer Technik Rapperswil ! 5: * ! 6: * This program is free software; you can redistribute it and/or modify it ! 7: * under the terms of the GNU General Public License as published by the ! 8: * Free Software Foundation; either version 2 of the License, or (at your ! 9: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ! 10: * ! 11: * This program is distributed in the hope that it will be useful, but ! 12: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ! 13: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ! 14: * for more details. ! 15: */ ! 16: ! 17: #include "tpm_tss_tss2.h" ! 18: #include "tpm_tss_tss2_names.h" ! 19: ! 20: #ifdef TSS_TSS2_V1 ! 21: ! 22: #include <asn1/asn1.h> ! 23: #include <asn1/oid.h> ! 24: #include <bio/bio_reader.h> ! 25: #include <threading/mutex.h> ! 26: ! 27: #include <tpm20.h> ! 28: ! 29: #ifdef TSS2_TCTI_TABRMD ! 30: #include <tcti/tcti-tabrmd.h> ! 31: #endif /* TSS2_TCTI_TABRMD */ ! 32: ! 33: #ifdef TSS2_TCTI_SOCKET ! 34: #include <tcti_socket.h> ! 35: ! 36: #define TCTI_SOCKET_DEFAULT_ADDRESS "127.0.0.1" ! 37: #define TCTI_SOCKET_DEFAULT_PORT 2323 ! 38: #endif /* TSS2_TCTI_SOCKET */ ! 39: ! 40: #define LABEL "TPM 2.0 -" ! 41: ! 42: typedef struct private_tpm_tss_tss2_t private_tpm_tss_tss2_t; ! 43: ! 44: /** ! 45: * Private data of an tpm_tss_tss2_t object. ! 46: */ ! 47: struct private_tpm_tss_tss2_t { ! 48: ! 49: /** ! 50: * Public tpm_tss_tss2_t interface. ! 51: */ ! 52: tpm_tss_t public; ! 53: ! 54: /** ! 55: * TCTI context ! 56: */ ! 57: TSS2_TCTI_CONTEXT *tcti_context; ! 58: ! 59: /** ! 60: * SYS context ! 61: */ ! 62: TSS2_SYS_CONTEXT *sys_context; ! 63: ! 64: /** ! 65: * Number of supported algorithms ! 66: */ ! 67: size_t supported_algs_count; ! 68: ! 69: /** ! 70: * List of supported algorithms ! 71: */ ! 72: TPM_ALG_ID supported_algs[TPM_PT_ALGORITHM_SET]; ! 73: ! 74: /** ! 75: * Is TPM FIPS 186-4 compliant ? ! 76: */ ! 77: bool fips_186_4; ! 78: ! 79: /** ! 80: * Mutex controlling access to the TPM 2.0 context ! 81: */ ! 82: mutex_t *mutex; ! 83: ! 84: }; ! 85: ! 86: /** ! 87: * Some symbols required by libtctisocket ! 88: */ ! 89: FILE *outFp; ! 90: uint8_t simulator = 1; ! 91: ! 92: int TpmClientPrintf (uint8_t type, const char *format, ...) ! 93: { ! 94: return 0; ! 95: } ! 96: ! 97: /** ! 98: * Convert hash algorithm to TPM_ALG_ID ! 99: */ ! 100: static TPM_ALG_ID hash_alg_to_tpm_alg_id(hash_algorithm_t alg) ! 101: { ! 102: switch (alg) ! 103: { ! 104: case HASH_SHA1: ! 105: return TPM_ALG_SHA1; ! 106: case HASH_SHA256: ! 107: return TPM_ALG_SHA256; ! 108: case HASH_SHA384: ! 109: return TPM_ALG_SHA384; ! 110: case HASH_SHA512: ! 111: return TPM_ALG_SHA512; ! 112: default: ! 113: return TPM_ALG_ERROR; ! 114: } ! 115: } ! 116: ! 117: /** ! 118: * Convert TPM_ALG_ID to hash algorithm ! 119: */ ! 120: static hash_algorithm_t hash_alg_from_tpm_alg_id(TPM_ALG_ID alg) ! 121: { ! 122: switch (alg) ! 123: { ! 124: case TPM_ALG_SHA1: ! 125: return HASH_SHA1; ! 126: case TPM_ALG_SHA256: ! 127: return HASH_SHA256; ! 128: case TPM_ALG_SHA384: ! 129: return HASH_SHA384; ! 130: case TPM_ALG_SHA512: ! 131: return HASH_SHA512; ! 132: default: ! 133: return HASH_UNKNOWN; ! 134: } ! 135: } ! 136: ! 137: /** ! 138: * Check if an algorithm given by its TPM_ALG_ID is supported by the TPM ! 139: */ ! 140: static bool is_supported_alg(private_tpm_tss_tss2_t *this, TPM_ALG_ID alg_id) ! 141: { ! 142: int i; ! 143: ! 144: if (alg_id == TPM_ALG_ERROR) ! 145: { ! 146: return FALSE; ! 147: } ! 148: ! 149: for (i = 0; i < this->supported_algs_count; i++) ! 150: { ! 151: if (this->supported_algs[i] == alg_id) ! 152: { ! 153: return TRUE; ! 154: } ! 155: } ! 156: ! 157: return FALSE; ! 158: } ! 159: ! 160: /** ! 161: * Get a list of supported algorithms ! 162: */ ! 163: static bool get_algs_capability(private_tpm_tss_tss2_t *this) ! 164: { ! 165: TPMS_CAPABILITY_DATA cap_data; ! 166: TPMS_TAGGED_PROPERTY tp; ! 167: TPMI_YES_NO more_data; ! 168: TPM_ALG_ID alg; ! 169: bool fips_140_2 = FALSE; ! 170: uint32_t rval, i, offset, revision = 0, year = 0; ! 171: size_t len = BUF_LEN; ! 172: char buf[BUF_LEN], manufacturer[5], vendor_string[17]; ! 173: char *pos = buf; ! 174: int written; ! 175: ! 176: /* get fixed properties */ ! 177: this->mutex->lock(this->mutex); ! 178: rval = Tss2_Sys_GetCapability(this->sys_context, 0, TPM_CAP_TPM_PROPERTIES, ! 179: PT_FIXED, MAX_TPM_PROPERTIES, &more_data, &cap_data, 0); ! 180: this->mutex->unlock(this->mutex); ! 181: if (rval != TPM_RC_SUCCESS) ! 182: { ! 183: DBG1(DBG_PTS, "%s GetCapability failed for TPM_CAP_TPM_PROPERTIES: 0x%06x", ! 184: LABEL, rval); ! 185: return FALSE; ! 186: } ! 187: memset(manufacturer, '\0', sizeof(manufacturer)); ! 188: memset(vendor_string, '\0', sizeof(vendor_string)); ! 189: ! 190: /* print fixed properties */ ! 191: for (i = 0; i < cap_data.data.tpmProperties.count; i++) ! 192: { ! 193: tp = cap_data.data.tpmProperties.tpmProperty[i]; ! 194: switch (tp.property) ! 195: { ! 196: case TPM_PT_REVISION: ! 197: revision = tp.value; ! 198: break; ! 199: case TPM_PT_YEAR: ! 200: year = tp.value; ! 201: break; ! 202: case TPM_PT_MANUFACTURER: ! 203: htoun32(manufacturer, tp.value); ! 204: break; ! 205: case TPM_PT_VENDOR_STRING_1: ! 206: case TPM_PT_VENDOR_STRING_2: ! 207: case TPM_PT_VENDOR_STRING_3: ! 208: case TPM_PT_VENDOR_STRING_4: ! 209: offset = 4 * (tp.property - TPM_PT_VENDOR_STRING_1); ! 210: htoun32(vendor_string + offset, tp.value); ! 211: break; ! 212: case TPM_PT_MODES: ! 213: if (tp.value & TPMA_MODES_FIPS_140_2) ! 214: { ! 215: this->fips_186_4 = fips_140_2 = TRUE; ! 216: } ! 217: break; ! 218: default: ! 219: break; ! 220: } ! 221: } ! 222: ! 223: if (!fips_140_2) ! 224: { ! 225: this->fips_186_4 = lib->settings->get_bool(lib->settings, ! 226: "%s.plugins.tpm.fips_186_4", FALSE, lib->ns); ! 227: } ! 228: DBG2(DBG_PTS, "%s manufacturer: %s (%s) rev: %05.2f %u %s", LABEL, ! 229: manufacturer, vendor_string, (float)revision/100, year, ! 230: fips_140_2 ? "FIPS 140-2" : (this->fips_186_4 ? "FIPS 186-4" : "")); ! 231: ! 232: /* get supported algorithms */ ! 233: this->mutex->lock(this->mutex); ! 234: rval = Tss2_Sys_GetCapability(this->sys_context, 0, TPM_CAP_ALGS, ! 235: 0, TPM_PT_ALGORITHM_SET, &more_data, &cap_data, 0); ! 236: this->mutex->unlock(this->mutex); ! 237: if (rval != TPM_RC_SUCCESS) ! 238: { ! 239: DBG1(DBG_PTS, "%s GetCapability failed for TPM_CAP_ALGS: 0x%06x", ! 240: LABEL, rval); ! 241: return FALSE; ! 242: } ! 243: ! 244: /* Number of supported algorithms */ ! 245: this->supported_algs_count = cap_data.data.algorithms.count; ! 246: ! 247: /* store and print supported algorithms */ ! 248: for (i = 0; i < this->supported_algs_count; i++) ! 249: { ! 250: alg = cap_data.data.algorithms.algProperties[i].alg; ! 251: this->supported_algs[i] = alg; ! 252: ! 253: written = snprintf(pos, len, " %N", tpm_alg_id_names, alg); ! 254: if (written < 0 || written >= len) ! 255: { ! 256: break; ! 257: } ! 258: pos += written; ! 259: len -= written; ! 260: } ! 261: DBG2(DBG_PTS, "%s algorithms:%s", LABEL, buf); ! 262: ! 263: /* get supported ECC curves */ ! 264: this->mutex->lock(this->mutex); ! 265: rval = Tss2_Sys_GetCapability(this->sys_context, 0, TPM_CAP_ECC_CURVES, ! 266: 0, TPM_PT_LOADED_CURVES, &more_data, &cap_data, 0); ! 267: this->mutex->unlock(this->mutex); ! 268: if (rval != TPM_RC_SUCCESS) ! 269: { ! 270: DBG1(DBG_PTS, "%s GetCapability failed for TPM_ECC_CURVES: 0x%06x", ! 271: LABEL, rval); ! 272: return FALSE; ! 273: } ! 274: ! 275: /* reset print buffer */ ! 276: pos = buf; ! 277: len = BUF_LEN; ! 278: ! 279: /* print supported ECC curves */ ! 280: for (i = 0; i < cap_data.data.eccCurves.count; i++) ! 281: { ! 282: written = snprintf(pos, len, " %N", tpm_ecc_curve_names, ! 283: cap_data.data.eccCurves.eccCurves[i]); ! 284: if (written < 0 || written >= len) ! 285: { ! 286: break; ! 287: } ! 288: pos += written; ! 289: len -= written; ! 290: } ! 291: DBG2(DBG_PTS, "%s ECC curves:%s", LABEL, buf); ! 292: ! 293: return TRUE; ! 294: } ! 295: ! 296: /** ! 297: * Initialize TSS2 TCTI TABRMD context ! 298: */ ! 299: static bool initialize_tcti_tabrmd_context(private_tpm_tss_tss2_t *this) ! 300: { ! 301: #ifdef TSS2_TCTI_TABRMD ! 302: size_t tcti_context_size; ! 303: uint32_t rval; ! 304: ! 305: /* determine size of tcti context */ ! 306: rval = tss2_tcti_tabrmd_init(NULL, &tcti_context_size); ! 307: if (rval != TSS2_RC_SUCCESS) ! 308: { ! 309: DBG1(DBG_PTS, "%s could not get tcti_context size: 0x%06x", ! 310: LABEL, rval); ! 311: return FALSE; ! 312: } ! 313: ! 314: /* allocate and initialize memory for tcti context */ ! 315: this->tcti_context = (TSS2_TCTI_CONTEXT*)malloc(tcti_context_size); ! 316: memset(this->tcti_context, 0x00, tcti_context_size); ! 317: ! 318: /* initialize tcti context */ ! 319: rval = tss2_tcti_tabrmd_init(this->tcti_context, &tcti_context_size); ! 320: if (rval != TSS2_RC_SUCCESS) ! 321: { ! 322: DBG1(DBG_PTS, "%s could not get tcti_context: 0x%06x " ! 323: "via tabrmd interface", LABEL, rval); ! 324: return FALSE; ! 325: } ! 326: return TRUE; ! 327: #else /* TSS2_TCTI_TABRMD */ ! 328: return FALSE; ! 329: #endif /* TSS2_TCTI_TABRMD */ ! 330: } ! 331: ! 332: /** ! 333: * Initialize TSS2 TCTI Socket context ! 334: */ ! 335: static bool initialize_tcti_socket_context(private_tpm_tss_tss2_t *this) ! 336: { ! 337: #ifdef TSS2_TCTI_SOCKET ! 338: size_t tcti_context_size; ! 339: uint32_t rval; ! 340: ! 341: TCTI_SOCKET_CONF rm_if_config = { TCTI_SOCKET_DEFAULT_ADDRESS, ! 342: TCTI_SOCKET_DEFAULT_PORT ! 343: }; ! 344: ! 345: /* determine size of tcti context */ ! 346: rval = InitSocketTcti(NULL, &tcti_context_size, &rm_if_config, 0); ! 347: if (rval != TSS2_RC_SUCCESS) ! 348: { ! 349: DBG1(DBG_PTS, "%s could not get tcti_context size: 0x%06x", ! 350: LABEL, rval); ! 351: return FALSE; ! 352: } ! 353: ! 354: /* allocate memory for tcti context */ ! 355: this->tcti_context = (TSS2_TCTI_CONTEXT*)malloc(tcti_context_size); ! 356: ! 357: /* initialize tcti context */ ! 358: rval = InitSocketTcti(this->tcti_context, &tcti_context_size, ! 359: &rm_if_config, 0); ! 360: if (rval != TSS2_RC_SUCCESS) ! 361: { ! 362: DBG1(DBG_PTS, "%s could not get tcti_context: 0x%06x " ! 363: "via socket interface", LABEL, rval); ! 364: return FALSE; ! 365: } ! 366: return TRUE; ! 367: #else /* TSS2_TCTI_SOCKET */ ! 368: return FALSE; ! 369: #endif /* TSS2_TCTI_SOCKET */ ! 370: } ! 371: ! 372: /** ! 373: * Initialize TSS2 Sys context ! 374: */ ! 375: static bool initialize_sys_context(private_tpm_tss_tss2_t *this) ! 376: { ! 377: uint32_t sys_context_size; ! 378: uint32_t rval; ! 379: ! 380: TSS2_ABI_VERSION abi_version = { TSSWG_INTEROP, ! 381: TSS_SAPI_FIRST_FAMILY, ! 382: TSS_SAPI_FIRST_LEVEL, ! 383: TSS_SAPI_FIRST_VERSION ! 384: }; ! 385: ! 386: /* determine size of sys context */ ! 387: sys_context_size = Tss2_Sys_GetContextSize(0); ! 388: ! 389: /* allocate memory for sys context */ ! 390: this->sys_context = malloc(sys_context_size); ! 391: ! 392: /* initialize sys context */ ! 393: rval = Tss2_Sys_Initialize(this->sys_context, sys_context_size, ! 394: this->tcti_context, &abi_version); ! 395: if (rval != TSS2_RC_SUCCESS) ! 396: { ! 397: DBG1(DBG_PTS, "%s could not get sys_context: 0x%06x", ! 398: LABEL, rval); ! 399: return FALSE; ! 400: } ! 401: ! 402: /* get a list of supported algorithms and ECC curves */ ! 403: return get_algs_capability(this); ! 404: } ! 405: ! 406: /** ! 407: * Finalize TSS context ! 408: */ ! 409: static void finalize_context(private_tpm_tss_tss2_t *this) ! 410: { ! 411: if (this->tcti_context) ! 412: { ! 413: tss2_tcti_finalize(this->tcti_context); ! 414: free(this->tcti_context); ! 415: } ! 416: if (this->sys_context) ! 417: { ! 418: Tss2_Sys_Finalize(this->sys_context); ! 419: free(this->sys_context); ! 420: } ! 421: } ! 422: ! 423: METHOD(tpm_tss_t, get_version, tpm_version_t, ! 424: private_tpm_tss_tss2_t *this) ! 425: { ! 426: return TPM_VERSION_2_0; ! 427: } ! 428: ! 429: METHOD(tpm_tss_t, get_version_info, chunk_t, ! 430: private_tpm_tss_tss2_t *this) ! 431: { ! 432: return chunk_empty; ! 433: } ! 434: ! 435: /** ! 436: * read the public key portion of a TSS 2.0 key from NVRAM ! 437: */ ! 438: bool read_public(private_tpm_tss_tss2_t *this, TPMI_DH_OBJECT handle, ! 439: TPM2B_PUBLIC *public) ! 440: { ! 441: uint32_t rval; ! 442: ! 443: TPM2B_NAME name = { { sizeof(TPM2B_NAME)-2, } }; ! 444: TPM2B_NAME qualified_name = { { sizeof(TPM2B_NAME)-2, } }; ! 445: ! 446: TPMS_AUTH_RESPONSE session_data; ! 447: TSS2_SYS_RSP_AUTHS sessions_data; ! 448: TPMS_AUTH_RESPONSE *session_data_array[1]; ! 449: ! 450: session_data_array[0] = &session_data; ! 451: sessions_data.rspAuths = &session_data_array[0]; ! 452: sessions_data.rspAuthsCount = 1; ! 453: ! 454: /* read public key for a given object handle from TPM 2.0 NVRAM */ ! 455: this->mutex->lock(this->mutex); ! 456: rval = Tss2_Sys_ReadPublic(this->sys_context, handle, 0, public, &name, ! 457: &qualified_name, &sessions_data); ! 458: this->mutex->unlock(this->mutex); ! 459: if (rval != TPM_RC_SUCCESS) ! 460: { ! 461: DBG1(DBG_PTS, "%s could not read public key from handle 0x%08x: 0x%06x", ! 462: LABEL, handle, rval); ! 463: return FALSE; ! 464: } ! 465: return TRUE; ! 466: } ! 467: ! 468: METHOD(tpm_tss_t, generate_aik, bool, ! 469: private_tpm_tss_tss2_t *this, chunk_t ca_modulus, chunk_t *aik_blob, ! 470: chunk_t *aik_pubkey, chunk_t *identity_req) ! 471: { ! 472: return FALSE; ! 473: } ! 474: ! 475: METHOD(tpm_tss_t, get_public, chunk_t, ! 476: private_tpm_tss_tss2_t *this, uint32_t handle) ! 477: { ! 478: TPM2B_PUBLIC public = { { 0, } }; ! 479: TPM_ALG_ID sig_alg, digest_alg; ! 480: chunk_t aik_blob, aik_pubkey = chunk_empty; ! 481: ! 482: if (!read_public(this, handle, &public)) ! 483: { ! 484: return chunk_empty; ! 485: } ! 486: ! 487: aik_blob = chunk_create((u_char*)&public, sizeof(public)); ! 488: DBG3(DBG_LIB, "%s public key blob: %B", LABEL, &aik_blob); ! 489: ! 490: /* convert TSS 2.0 public key blot into PKCS#1 format */ ! 491: switch (public.t.publicArea.type) ! 492: { ! 493: case TPM_ALG_RSA: ! 494: { ! 495: TPM2B_PUBLIC_KEY_RSA *rsa; ! 496: TPMT_RSA_SCHEME *scheme; ! 497: chunk_t aik_exponent = chunk_from_chars(0x01, 0x00, 0x01); ! 498: chunk_t aik_modulus; ! 499: uint32_t exponent; ! 500: ! 501: scheme = &public.t.publicArea.parameters.rsaDetail.scheme; ! 502: sig_alg = scheme->scheme; ! 503: digest_alg = scheme->details.anySig.hashAlg; ! 504: ! 505: rsa = &public.t.publicArea.unique.rsa; ! 506: aik_modulus = chunk_create(rsa->t.buffer, rsa->t.size); ! 507: exponent = htonl(public.t.publicArea.parameters.rsaDetail.exponent); ! 508: if (exponent) ! 509: { ! 510: aik_exponent = chunk_from_thing(exponent); ! 511: } ! 512: ! 513: /* subjectPublicKeyInfo encoding of RSA public key */ ! 514: if (!lib->encoding->encode(lib->encoding, PUBKEY_SPKI_ASN1_DER, ! 515: NULL, &aik_pubkey, CRED_PART_RSA_MODULUS, aik_modulus, ! 516: CRED_PART_RSA_PUB_EXP, aik_exponent, CRED_PART_END)) ! 517: { ! 518: DBG1(DBG_PTS, "%s subjectPublicKeyInfo encoding of public key " ! 519: "failed", LABEL); ! 520: return chunk_empty; ! 521: } ! 522: break; ! 523: } ! 524: case TPM_ALG_ECC: ! 525: { ! 526: TPMS_ECC_POINT *ecc; ! 527: TPMT_ECC_SCHEME *scheme; ! 528: chunk_t ecc_point; ! 529: uint8_t *pos; ! 530: ! 531: scheme = &public.t.publicArea.parameters.eccDetail.scheme; ! 532: sig_alg = scheme->scheme; ! 533: digest_alg = scheme->details.anySig.hashAlg; ! 534: ! 535: ecc = &public.t.publicArea.unique.ecc; ! 536: ! 537: /* allocate space for bit string */ ! 538: pos = asn1_build_object(&ecc_point, ASN1_BIT_STRING, ! 539: 2 + ecc->x.t.size + ecc->y.t.size); ! 540: /* bit string length is a multiple of octets */ ! 541: *pos++ = 0x00; ! 542: /* uncompressed ECC point format */ ! 543: *pos++ = 0x04; ! 544: /* copy x coordinate of ECC point */ ! 545: memcpy(pos, ecc->x.t.buffer, ecc->x.t.size); ! 546: pos += ecc->x.t.size; ! 547: /* copy y coordinate of ECC point */ ! 548: memcpy(pos, ecc->y.t.buffer, ecc->y.t.size); ! 549: /* subjectPublicKeyInfo encoding of ECC public key */ ! 550: aik_pubkey = asn1_wrap(ASN1_SEQUENCE, "mm", ! 551: asn1_wrap(ASN1_SEQUENCE, "mm", ! 552: asn1_build_known_oid(OID_EC_PUBLICKEY), ! 553: asn1_build_known_oid(ecc->x.t.size == 32 ? ! 554: OID_PRIME256V1 : OID_SECT384R1)), ! 555: ecc_point); ! 556: break; ! 557: } ! 558: default: ! 559: DBG1(DBG_PTS, "%s unsupported key type", LABEL); ! 560: return chunk_empty; ! 561: } ! 562: DBG1(DBG_PTS, "signature algorithm is %N with %N hash", ! 563: tpm_alg_id_names, sig_alg, tpm_alg_id_names, digest_alg); ! 564: return aik_pubkey; ! 565: } ! 566: ! 567: METHOD(tpm_tss_t, supported_signature_schemes, enumerator_t*, ! 568: private_tpm_tss_tss2_t *this, uint32_t handle) ! 569: { ! 570: TPM2B_PUBLIC public = { { 0, } }; ! 571: hash_algorithm_t digest; ! 572: signature_params_t supported_scheme; ! 573: ! 574: if (!read_public(this, handle, &public)) ! 575: { ! 576: return enumerator_create_empty(); ! 577: } ! 578: ! 579: switch (public.t.publicArea.type) ! 580: { ! 581: case TPM_ALG_RSA: ! 582: { ! 583: TPMS_RSA_PARMS *rsa; ! 584: TPMT_RSA_SCHEME *scheme; ! 585: ! 586: rsa = &public.t.publicArea.parameters.rsaDetail; ! 587: scheme = &rsa->scheme; ! 588: digest = hash_alg_from_tpm_alg_id(scheme->details.anySig.hashAlg); ! 589: ! 590: switch (scheme->scheme) ! 591: { ! 592: case TPM_ALG_RSAPSS: ! 593: { ! 594: ssize_t salt_len; ! 595: ! 596: salt_len = this->fips_186_4 ? RSA_PSS_SALT_LEN_DEFAULT : ! 597: RSA_PSS_SALT_LEN_MAX; ! 598: rsa_pss_params_t pss_params = { ! 599: .hash = digest, ! 600: .mgf1_hash = digest, ! 601: .salt_len = salt_len, ! 602: }; ! 603: supported_scheme = (signature_params_t){ ! 604: .scheme = SIGN_RSA_EMSA_PSS, ! 605: .params = &pss_params, ! 606: }; ! 607: if (!rsa_pss_params_set_salt_len(&pss_params, rsa->keyBits)) ! 608: { ! 609: return enumerator_create_empty(); ! 610: } ! 611: break; ! 612: } ! 613: case TPM_ALG_RSASSA: ! 614: supported_scheme = (signature_params_t){ ! 615: .scheme = signature_scheme_from_oid( ! 616: hasher_signature_algorithm_to_oid(digest, ! 617: KEY_RSA)), ! 618: }; ! 619: break; ! 620: default: ! 621: return enumerator_create_empty(); ! 622: } ! 623: break; ! 624: } ! 625: case TPM_ALG_ECC: ! 626: { ! 627: TPMT_ECC_SCHEME *scheme; ! 628: ! 629: scheme = &public.t.publicArea.parameters.eccDetail.scheme; ! 630: digest = hash_alg_from_tpm_alg_id(scheme->details.anySig.hashAlg); ! 631: ! 632: switch (scheme->scheme) ! 633: { ! 634: case TPM_ALG_ECDSA: ! 635: supported_scheme = (signature_params_t){ ! 636: .scheme = signature_scheme_from_oid( ! 637: hasher_signature_algorithm_to_oid(digest, ! 638: KEY_ECDSA)), ! 639: }; ! 640: break; ! 641: default: ! 642: return enumerator_create_empty(); ! 643: } ! 644: break; ! 645: } ! 646: default: ! 647: DBG1(DBG_PTS, "%s unsupported key type", LABEL); ! 648: return enumerator_create_empty(); ! 649: } ! 650: return enumerator_create_single(signature_params_clone(&supported_scheme), ! 651: (void*)signature_params_destroy); ! 652: } ! 653: ! 654: /** ! 655: * Configure a PCR Selection assuming a maximum of 24 registers ! 656: */ ! 657: static bool init_pcr_selection(private_tpm_tss_tss2_t *this, uint32_t pcrs, ! 658: hash_algorithm_t alg, TPML_PCR_SELECTION *pcr_sel) ! 659: { ! 660: TPM_ALG_ID alg_id; ! 661: uint32_t pcr; ! 662: ! 663: /* check if hash algorithm is supported by TPM */ ! 664: alg_id = hash_alg_to_tpm_alg_id(alg); ! 665: if (!is_supported_alg(this, alg_id)) ! 666: { ! 667: DBG1(DBG_PTS, "%s %N hash algorithm not supported by TPM", ! 668: LABEL, hash_algorithm_short_names, alg); ! 669: return FALSE; ! 670: } ! 671: ! 672: /* initialize the PCR Selection structure,*/ ! 673: pcr_sel->count = 1; ! 674: pcr_sel->pcrSelections[0].hash = alg_id; ! 675: pcr_sel->pcrSelections[0].sizeofSelect = 3; ! 676: pcr_sel->pcrSelections[0].pcrSelect[0] = 0; ! 677: pcr_sel->pcrSelections[0].pcrSelect[1] = 0; ! 678: pcr_sel->pcrSelections[0].pcrSelect[2] = 0; ! 679: ! 680: /* set the selected PCRs */ ! 681: for (pcr = 0; pcr < PLATFORM_PCR; pcr++) ! 682: { ! 683: if (pcrs & (1 << pcr)) ! 684: { ! 685: pcr_sel->pcrSelections[0].pcrSelect[pcr / 8] |= ( 1 << (pcr % 8) ); ! 686: } ! 687: } ! 688: return TRUE; ! 689: } ! 690: ! 691: METHOD(tpm_tss_t, read_pcr, bool, ! 692: private_tpm_tss_tss2_t *this, uint32_t pcr_num, chunk_t *pcr_value, ! 693: hash_algorithm_t alg) ! 694: { ! 695: TPML_PCR_SELECTION pcr_selection; ! 696: TPML_DIGEST pcr_values; ! 697: ! 698: uint32_t pcr_update_counter, rval; ! 699: uint8_t *pcr_value_ptr; ! 700: size_t pcr_value_len; ! 701: ! 702: if (pcr_num >= PLATFORM_PCR) ! 703: { ! 704: DBG1(DBG_PTS, "%s maximum number of supported PCR is %d", ! 705: LABEL, PLATFORM_PCR); ! 706: return FALSE; ! 707: } ! 708: ! 709: if (!init_pcr_selection(this, (1 << pcr_num), alg, &pcr_selection)) ! 710: { ! 711: return FALSE; ! 712: } ! 713: ! 714: /* initialize the PCR Digest structure */ ! 715: memset(&pcr_values, 0, sizeof(TPML_DIGEST)); ! 716: ! 717: /* read the PCR value */ ! 718: this->mutex->lock(this->mutex); ! 719: rval = Tss2_Sys_PCR_Read(this->sys_context, 0, &pcr_selection, ! 720: &pcr_update_counter, &pcr_selection, &pcr_values, 0); ! 721: this->mutex->unlock(this->mutex); ! 722: if (rval != TPM_RC_SUCCESS) ! 723: { ! 724: DBG1(DBG_PTS, "%s PCR bank could not be read: 0x%60x", ! 725: LABEL, rval); ! 726: return FALSE; ! 727: } ! 728: pcr_value_ptr = (uint8_t *)pcr_values.digests[0].t.buffer; ! 729: pcr_value_len = (size_t) pcr_values.digests[0].t.size; ! 730: ! 731: *pcr_value = chunk_clone(chunk_create(pcr_value_ptr, pcr_value_len)); ! 732: ! 733: return TRUE; ! 734: } ! 735: ! 736: METHOD(tpm_tss_t, extend_pcr, bool, ! 737: private_tpm_tss_tss2_t *this, uint32_t pcr_num, chunk_t *pcr_value, ! 738: chunk_t data, hash_algorithm_t alg) ! 739: { ! 740: uint32_t rval; ! 741: TPM_ALG_ID alg_id; ! 742: TPML_DIGEST_VALUES digest_values; ! 743: TPMS_AUTH_COMMAND session_data_cmd; ! 744: TPMS_AUTH_RESPONSE session_data_rsp; ! 745: TSS2_SYS_CMD_AUTHS sessions_data_cmd; ! 746: TSS2_SYS_RSP_AUTHS sessions_data_rsp; ! 747: TPMS_AUTH_COMMAND *session_data_cmd_array[1]; ! 748: TPMS_AUTH_RESPONSE *session_data_rsp_array[1]; ! 749: ! 750: session_data_cmd_array[0] = &session_data_cmd; ! 751: session_data_rsp_array[0] = &session_data_rsp; ! 752: ! 753: sessions_data_cmd.cmdAuths = &session_data_cmd_array[0]; ! 754: sessions_data_rsp.rspAuths = &session_data_rsp_array[0]; ! 755: ! 756: sessions_data_cmd.cmdAuthsCount = 1; ! 757: sessions_data_rsp.rspAuthsCount = 1; ! 758: ! 759: session_data_cmd.sessionHandle = TPM_RS_PW; ! 760: session_data_cmd.hmac.t.size = 0; ! 761: session_data_cmd.nonce.t.size = 0; ! 762: ! 763: *( (uint8_t *)((void *)&session_data_cmd.sessionAttributes ) ) = 0; ! 764: ! 765: /* check if hash algorithm is supported by TPM */ ! 766: alg_id = hash_alg_to_tpm_alg_id(alg); ! 767: if (!is_supported_alg(this, alg_id)) ! 768: { ! 769: DBG1(DBG_PTS, "%s %N hash algorithm not supported by TPM", ! 770: LABEL, hash_algorithm_short_names, alg); ! 771: return FALSE; ! 772: } ! 773: ! 774: digest_values.count = 1; ! 775: digest_values.digests[0].hashAlg = alg_id; ! 776: ! 777: switch (alg) ! 778: { ! 779: case HASH_SHA1: ! 780: if (data.len != HASH_SIZE_SHA1) ! 781: { ! 782: return FALSE; ! 783: } ! 784: memcpy(digest_values.digests[0].digest.sha1, data.ptr, ! 785: HASH_SIZE_SHA1); ! 786: break; ! 787: case HASH_SHA256: ! 788: if (data.len != HASH_SIZE_SHA256) ! 789: { ! 790: return FALSE; ! 791: } ! 792: memcpy(digest_values.digests[0].digest.sha256, data.ptr, ! 793: HASH_SIZE_SHA256); ! 794: break; ! 795: case HASH_SHA384: ! 796: if (data.len != HASH_SIZE_SHA384) ! 797: { ! 798: return FALSE; ! 799: } ! 800: memcpy(digest_values.digests[0].digest.sha384, data.ptr, ! 801: HASH_SIZE_SHA384); ! 802: break; ! 803: case HASH_SHA512: ! 804: if (data.len != HASH_SIZE_SHA512) ! 805: { ! 806: return FALSE; ! 807: } ! 808: memcpy(digest_values.digests[0].digest.sha512, data.ptr, ! 809: HASH_SIZE_SHA512); ! 810: break; ! 811: default: ! 812: return FALSE; ! 813: } ! 814: ! 815: /* extend PCR */ ! 816: this->mutex->lock(this->mutex); ! 817: rval = Tss2_Sys_PCR_Extend(this->sys_context, pcr_num, &sessions_data_cmd, ! 818: &digest_values, &sessions_data_rsp); ! 819: this->mutex->unlock(this->mutex); ! 820: if (rval != TPM_RC_SUCCESS) ! 821: { ! 822: DBG1(DBG_PTS, "%s PCR %02u could not be extended: 0x%06x", ! 823: LABEL, pcr_num, rval); ! 824: return FALSE; ! 825: } ! 826: ! 827: /* get updated PCR value */ ! 828: return read_pcr(this, pcr_num, pcr_value, alg); ! 829: } ! 830: ! 831: METHOD(tpm_tss_t, quote, bool, ! 832: private_tpm_tss_tss2_t *this, uint32_t aik_handle, uint32_t pcr_sel, ! 833: hash_algorithm_t alg, chunk_t data, tpm_quote_mode_t *quote_mode, ! 834: tpm_tss_quote_info_t **quote_info, chunk_t *quote_sig) ! 835: { ! 836: chunk_t quoted_chunk, qualified_signer, extra_data, clock_info, ! 837: firmware_version, pcr_select, pcr_digest; ! 838: hash_algorithm_t pcr_digest_alg; ! 839: bio_reader_t *reader; ! 840: uint32_t rval; ! 841: ! 842: TPM2B_DATA qualifying_data; ! 843: TPML_PCR_SELECTION pcr_selection; ! 844: TPM2B_ATTEST quoted = { { sizeof(TPM2B_ATTEST)-2, } }; ! 845: TPMT_SIG_SCHEME scheme; ! 846: TPMT_SIGNATURE sig; ! 847: TPMI_ALG_HASH hash_alg; ! 848: TPMS_AUTH_COMMAND session_data_cmd; ! 849: TPMS_AUTH_RESPONSE session_data_rsp; ! 850: TSS2_SYS_CMD_AUTHS sessions_data_cmd; ! 851: TSS2_SYS_RSP_AUTHS sessions_data_rsp; ! 852: TPMS_AUTH_COMMAND *session_data_cmd_array[1]; ! 853: TPMS_AUTH_RESPONSE *session_data_rsp_array[1]; ! 854: ! 855: session_data_cmd_array[0] = &session_data_cmd; ! 856: session_data_rsp_array[0] = &session_data_rsp; ! 857: ! 858: sessions_data_cmd.cmdAuths = &session_data_cmd_array[0]; ! 859: sessions_data_rsp.rspAuths = &session_data_rsp_array[0]; ! 860: ! 861: sessions_data_cmd.cmdAuthsCount = 1; ! 862: sessions_data_rsp.rspAuthsCount = 1; ! 863: ! 864: session_data_cmd.sessionHandle = TPM_RS_PW; ! 865: session_data_cmd.hmac.t.size = 0; ! 866: session_data_cmd.nonce.t.size = 0; ! 867: ! 868: *( (uint8_t *)((void *)&session_data_cmd.sessionAttributes ) ) = 0; ! 869: ! 870: qualifying_data.t.size = data.len; ! 871: memcpy(qualifying_data.t.buffer, data.ptr, data.len); ! 872: ! 873: scheme.scheme = TPM_ALG_NULL; ! 874: memset(&sig, 0x00, sizeof(sig)); ! 875: ! 876: /* set Quote mode */ ! 877: *quote_mode = TPM_QUOTE_TPM2; ! 878: ! 879: if (!init_pcr_selection(this, pcr_sel, alg, &pcr_selection)) ! 880: { ! 881: return FALSE; ! 882: } ! 883: ! 884: this->mutex->lock(this->mutex); ! 885: rval = Tss2_Sys_Quote(this->sys_context, aik_handle, &sessions_data_cmd, ! 886: &qualifying_data, &scheme, &pcr_selection, "ed, ! 887: &sig, &sessions_data_rsp); ! 888: this->mutex->unlock(this->mutex); ! 889: if (rval != TPM_RC_SUCCESS) ! 890: { ! 891: DBG1(DBG_PTS,"%s Tss2_Sys_Quote failed: 0x%06x", LABEL, rval); ! 892: return FALSE; ! 893: } ! 894: quoted_chunk = chunk_create(quoted.t.attestationData, quoted.t.size); ! 895: ! 896: reader = bio_reader_create(chunk_skip(quoted_chunk, 6)); ! 897: if (!reader->read_data16(reader, &qualified_signer) || ! 898: !reader->read_data16(reader, &extra_data) || ! 899: !reader->read_data (reader, 17, &clock_info) || ! 900: !reader->read_data (reader, 8, &firmware_version) || ! 901: !reader->read_data (reader, 10, &pcr_select) || ! 902: !reader->read_data16(reader, &pcr_digest)) ! 903: { ! 904: DBG1(DBG_PTS, "%s parsing of quoted struct failed", LABEL); ! 905: reader->destroy(reader); ! 906: return FALSE; ! 907: } ! 908: reader->destroy(reader); ! 909: ! 910: DBG2(DBG_PTS, "PCR Composite digest: %B", &pcr_digest); ! 911: DBG2(DBG_PTS, "TPM Quote Info: %B", "ed_chunk); ! 912: DBG2(DBG_PTS, "qualifiedSigner: %B", &qualified_signer); ! 913: DBG2(DBG_PTS, "extraData: %B", &extra_data); ! 914: DBG2(DBG_PTS, "clockInfo: %B", &clock_info); ! 915: DBG2(DBG_PTS, "firmwareVersion: %B", &firmware_version); ! 916: DBG2(DBG_PTS, "pcrSelect: %B", &pcr_select); ! 917: ! 918: /* extract signature */ ! 919: switch (sig.sigAlg) ! 920: { ! 921: case TPM_ALG_RSASSA: ! 922: case TPM_ALG_RSAPSS: ! 923: *quote_sig = chunk_clone( ! 924: chunk_create( ! 925: sig.signature.rsassa.sig.t.buffer, ! 926: sig.signature.rsassa.sig.t.size)); ! 927: hash_alg = sig.signature.rsassa.hash; ! 928: break; ! 929: case TPM_ALG_ECDSA: ! 930: case TPM_ALG_ECDAA: ! 931: case TPM_ALG_SM2: ! 932: case TPM_ALG_ECSCHNORR: ! 933: *quote_sig = chunk_cat("cc", ! 934: chunk_create( ! 935: sig.signature.ecdsa.signatureR.t.buffer, ! 936: sig.signature.ecdsa.signatureR.t.size), ! 937: chunk_create( ! 938: sig.signature.ecdsa.signatureS.t.buffer, ! 939: sig.signature.ecdsa.signatureS.t.size)); ! 940: hash_alg = sig.signature.ecdsa.hash; ! 941: break; ! 942: default: ! 943: DBG1(DBG_PTS, "%s unsupported %N signature algorithm", ! 944: LABEL, tpm_alg_id_names, sig.sigAlg); ! 945: return FALSE; ! 946: } ! 947: ! 948: DBG2(DBG_PTS, "PCR digest algorithm is %N", tpm_alg_id_names, hash_alg); ! 949: pcr_digest_alg = hash_alg_from_tpm_alg_id(hash_alg); ! 950: ! 951: DBG2(DBG_PTS, "TPM Quote Signature: %B", quote_sig); ! 952: ! 953: /* Create and initialize Quote Info object */ ! 954: *quote_info = tpm_tss_quote_info_create(*quote_mode, pcr_digest_alg, ! 955: pcr_digest); ! 956: (*quote_info)->set_tpm2_info(*quote_info, qualified_signer, clock_info, ! 957: pcr_select); ! 958: (*quote_info)->set_version_info(*quote_info, firmware_version); ! 959: ! 960: return TRUE; ! 961: } ! 962: ! 963: METHOD(tpm_tss_t, sign, bool, ! 964: private_tpm_tss_tss2_t *this, uint32_t hierarchy, uint32_t handle, ! 965: signature_scheme_t scheme, void *params, chunk_t data, chunk_t pin, ! 966: chunk_t *signature) ! 967: { ! 968: key_type_t key_type; ! 969: hash_algorithm_t hash_alg; ! 970: rsa_pss_params_t *rsa_pss_params; ! 971: uint32_t rval; ! 972: ! 973: TPM_ALG_ID alg_id; ! 974: TPM2B_MAX_BUFFER buffer; ! 975: TPM2B_DIGEST hash = { { sizeof(TPM2B_DIGEST)-2, } }; ! 976: TPMT_TK_HASHCHECK validation; ! 977: TPM2B_PUBLIC public = { { 0, } }; ! 978: TPMT_SIG_SCHEME sig_scheme; ! 979: TPMT_SIGNATURE sig; ! 980: TPMS_AUTH_COMMAND session_data_cmd; ! 981: TPMS_AUTH_RESPONSE session_data_rsp; ! 982: TSS2_SYS_CMD_AUTHS sessions_data_cmd; ! 983: TSS2_SYS_RSP_AUTHS sessions_data_rsp; ! 984: TPMS_AUTH_COMMAND *session_data_cmd_array[1]; ! 985: TPMS_AUTH_RESPONSE *session_data_rsp_array[1]; ! 986: ! 987: session_data_cmd_array[0] = &session_data_cmd; ! 988: session_data_rsp_array[0] = &session_data_rsp; ! 989: ! 990: sessions_data_cmd.cmdAuths = &session_data_cmd_array[0]; ! 991: sessions_data_rsp.rspAuths = &session_data_rsp_array[0]; ! 992: ! 993: sessions_data_cmd.cmdAuthsCount = 1; ! 994: sessions_data_rsp.rspAuthsCount = 1; ! 995: ! 996: session_data_cmd.sessionHandle = TPM_RS_PW; ! 997: session_data_cmd.nonce.t.size = 0; ! 998: session_data_cmd.hmac.t.size = 0; ! 999: ! 1000: if (pin.len > 0) ! 1001: { ! 1002: session_data_cmd.hmac.t.size = min(sizeof(session_data_cmd.hmac.t) - 2, ! 1003: pin.len); ! 1004: memcpy(session_data_cmd.hmac.t.buffer, pin.ptr, ! 1005: session_data_cmd.hmac.t.size); ! 1006: } ! 1007: *( (uint8_t *)((void *)&session_data_cmd.sessionAttributes ) ) = 0; ! 1008: ! 1009: if (scheme == SIGN_RSA_EMSA_PSS) ! 1010: { ! 1011: key_type = KEY_RSA; ! 1012: rsa_pss_params = (rsa_pss_params_t *)params; ! 1013: hash_alg = rsa_pss_params->hash; ! 1014: } ! 1015: else ! 1016: { ! 1017: key_type = key_type_from_signature_scheme(scheme); ! 1018: hash_alg = hasher_from_signature_scheme(scheme, NULL); ! 1019: } ! 1020: ! 1021: /* Check if hash algorithm is supported by TPM */ ! 1022: alg_id = hash_alg_to_tpm_alg_id(hash_alg); ! 1023: if (!is_supported_alg(this, alg_id)) ! 1024: { ! 1025: DBG1(DBG_PTS, "%s %N hash algorithm not supported by TPM", ! 1026: LABEL, hash_algorithm_short_names, hash_alg); ! 1027: return FALSE; ! 1028: } ! 1029: ! 1030: /* Get public key */ ! 1031: if (!read_public(this, handle, &public)) ! 1032: { ! 1033: return FALSE; ! 1034: } ! 1035: ! 1036: if (key_type == KEY_RSA && public.t.publicArea.type == TPM_ALG_RSA) ! 1037: { ! 1038: if (scheme == SIGN_RSA_EMSA_PSS) ! 1039: { ! 1040: sig_scheme.scheme = TPM_ALG_RSAPSS; ! 1041: sig_scheme.details.rsapss.hashAlg = alg_id; ! 1042: } ! 1043: else ! 1044: { ! 1045: sig_scheme.scheme = TPM_ALG_RSASSA; ! 1046: sig_scheme.details.rsassa.hashAlg = alg_id; ! 1047: } ! 1048: } ! 1049: else if (key_type == KEY_ECDSA && public.t.publicArea.type == TPM_ALG_ECC) ! 1050: { ! 1051: sig_scheme.scheme = TPM_ALG_ECDSA; ! 1052: sig_scheme.details.ecdsa.hashAlg = alg_id; ! 1053: ! 1054: } ! 1055: else ! 1056: { ! 1057: DBG1(DBG_PTS, "%s signature scheme %N not supported by TPM key", ! 1058: LABEL, signature_scheme_names, scheme); ! 1059: return FALSE; ! 1060: } ! 1061: ! 1062: if (data.len <= MAX_DIGEST_BUFFER) ! 1063: { ! 1064: memcpy(buffer.t.buffer, data.ptr, data.len); ! 1065: buffer.t.size = data.len; ! 1066: ! 1067: this->mutex->lock(this->mutex); ! 1068: rval = Tss2_Sys_Hash(this->sys_context, 0, &buffer, alg_id, hierarchy, ! 1069: &hash, &validation, 0); ! 1070: this->mutex->unlock(this->mutex); ! 1071: if (rval != TPM_RC_SUCCESS) ! 1072: { ! 1073: DBG1(DBG_PTS,"%s Tss2_Sys_Hash failed: 0x%06x", LABEL, rval); ! 1074: return FALSE; ! 1075: } ! 1076: } ! 1077: else ! 1078: { ! 1079: TPMI_DH_OBJECT sequence_handle; ! 1080: TPM2B_AUTH null_auth; ! 1081: ! 1082: null_auth.t.size = 0; ! 1083: this->mutex->lock(this->mutex); ! 1084: rval = Tss2_Sys_HashSequenceStart(this->sys_context, 0, &null_auth, ! 1085: alg_id, &sequence_handle, 0); ! 1086: if (rval != TPM_RC_SUCCESS) ! 1087: { ! 1088: DBG1(DBG_PTS,"%s Tss2_Sys_HashSequenceStart failed: 0x%06x", ! 1089: LABEL, rval); ! 1090: this->mutex->unlock(this->mutex); ! 1091: return FALSE; ! 1092: } ! 1093: ! 1094: while (data.len > 0) ! 1095: { ! 1096: buffer.t.size = min(data.len, MAX_DIGEST_BUFFER); ! 1097: memcpy(buffer.t.buffer, data.ptr, buffer.t.size); ! 1098: data.ptr += buffer.t.size; ! 1099: data.len -= buffer.t.size; ! 1100: ! 1101: rval = Tss2_Sys_SequenceUpdate(this->sys_context, sequence_handle, ! 1102: &sessions_data_cmd, &buffer, 0); ! 1103: if (rval != TPM_RC_SUCCESS) ! 1104: { ! 1105: DBG1(DBG_PTS,"%s Tss2_Sys_SequenceUpdate failed: 0x%06x", ! 1106: LABEL, rval); ! 1107: this->mutex->unlock(this->mutex); ! 1108: return FALSE; ! 1109: } ! 1110: } ! 1111: buffer.t.size = 0; ! 1112: ! 1113: rval = Tss2_Sys_SequenceComplete(this->sys_context, sequence_handle, ! 1114: &sessions_data_cmd, &buffer, hierarchy, ! 1115: &hash, &validation, 0); ! 1116: this->mutex->unlock(this->mutex); ! 1117: if (rval != TPM_RC_SUCCESS) ! 1118: { ! 1119: DBG1(DBG_PTS,"%s Tss2_Sys_SequenceComplete failed: 0x%06x", ! 1120: LABEL, rval); ! 1121: return FALSE; ! 1122: } ! 1123: } ! 1124: ! 1125: this->mutex->lock(this->mutex); ! 1126: rval = Tss2_Sys_Sign(this->sys_context, handle, &sessions_data_cmd, &hash, ! 1127: &sig_scheme, &validation, &sig, &sessions_data_rsp); ! 1128: this->mutex->unlock(this->mutex); ! 1129: if (rval != TPM_RC_SUCCESS) ! 1130: { ! 1131: DBG1(DBG_PTS,"%s Tss2_Sys_Sign failed: 0x%06x", LABEL, rval); ! 1132: return FALSE; ! 1133: } ! 1134: ! 1135: /* extract signature */ ! 1136: switch (scheme) ! 1137: { ! 1138: case SIGN_RSA_EMSA_PKCS1_SHA1: ! 1139: case SIGN_RSA_EMSA_PKCS1_SHA2_256: ! 1140: case SIGN_RSA_EMSA_PKCS1_SHA2_384: ! 1141: case SIGN_RSA_EMSA_PKCS1_SHA2_512: ! 1142: *signature = chunk_clone( ! 1143: chunk_create( ! 1144: sig.signature.rsassa.sig.t.buffer, ! 1145: sig.signature.rsassa.sig.t.size)); ! 1146: break; ! 1147: case SIGN_RSA_EMSA_PSS: ! 1148: *signature = chunk_clone( ! 1149: chunk_create( ! 1150: sig.signature.rsapss.sig.t.buffer, ! 1151: sig.signature.rsapss.sig.t.size)); ! 1152: break; ! 1153: case SIGN_ECDSA_256: ! 1154: case SIGN_ECDSA_384: ! 1155: case SIGN_ECDSA_521: ! 1156: *signature = chunk_cat("cc", ! 1157: chunk_create( ! 1158: sig.signature.ecdsa.signatureR.t.buffer, ! 1159: sig.signature.ecdsa.signatureR.t.size), ! 1160: chunk_create( ! 1161: sig.signature.ecdsa.signatureS.t.buffer, ! 1162: sig.signature.ecdsa.signatureS.t.size)); ! 1163: break; ! 1164: case SIGN_ECDSA_WITH_SHA256_DER: ! 1165: case SIGN_ECDSA_WITH_SHA384_DER: ! 1166: case SIGN_ECDSA_WITH_SHA512_DER: ! 1167: *signature = asn1_wrap(ASN1_SEQUENCE, "mm", ! 1168: asn1_integer("c", ! 1169: chunk_create( ! 1170: sig.signature.ecdsa.signatureR.t.buffer, ! 1171: sig.signature.ecdsa.signatureR.t.size)), ! 1172: asn1_integer("c", ! 1173: chunk_create( ! 1174: sig.signature.ecdsa.signatureS.t.buffer, ! 1175: sig.signature.ecdsa.signatureS.t.size))); ! 1176: break; ! 1177: default: ! 1178: DBG1(DBG_PTS, "%s unsupported %N signature scheme", ! 1179: LABEL, signature_scheme_names, scheme); ! 1180: return FALSE; ! 1181: } ! 1182: ! 1183: return TRUE; ! 1184: } ! 1185: ! 1186: METHOD(tpm_tss_t, get_random, bool, ! 1187: private_tpm_tss_tss2_t *this, size_t bytes, uint8_t *buffer) ! 1188: { ! 1189: size_t len, random_len= sizeof(TPM2B_DIGEST)-2; ! 1190: TPM2B_DIGEST random = { { random_len, } }; ! 1191: uint8_t *pos = buffer; ! 1192: uint32_t rval; ! 1193: ! 1194: while (bytes > 0) ! 1195: { ! 1196: len = min(bytes, random_len); ! 1197: ! 1198: this->mutex->lock(this->mutex); ! 1199: rval = Tss2_Sys_GetRandom(this->sys_context, NULL, len, &random, NULL); ! 1200: this->mutex->unlock(this->mutex); ! 1201: if (rval != TSS2_RC_SUCCESS) ! 1202: { ! 1203: DBG1(DBG_PTS,"%s Tss2_Sys_GetRandom failed: 0x%06x", LABEL, rval); ! 1204: return FALSE; ! 1205: } ! 1206: memcpy(pos, random.t.buffer, random.t.size); ! 1207: pos += random.t.size; ! 1208: bytes -= random.t.size; ! 1209: } ! 1210: ! 1211: return TRUE; ! 1212: } ! 1213: ! 1214: METHOD(tpm_tss_t, get_data, bool, ! 1215: private_tpm_tss_tss2_t *this, uint32_t hierarchy, uint32_t handle, ! 1216: chunk_t pin, chunk_t *data) ! 1217: { ! 1218: uint16_t max_data_size, nv_size, nv_offset = 0; ! 1219: uint32_t rval; ! 1220: ! 1221: TPMS_CAPABILITY_DATA cap_data; ! 1222: TPMI_YES_NO more_data; ! 1223: TPM2B_NAME nv_name = { { sizeof(TPM2B_NAME)-2, } }; ! 1224: TPM2B_NV_PUBLIC nv_public = { { 0, } }; ! 1225: TPM2B_MAX_NV_BUFFER nv_data = { { MAX_NV_BUFFER_SIZE, } }; ! 1226: TPMS_AUTH_COMMAND session_data_cmd; ! 1227: TPMS_AUTH_RESPONSE session_data_rsp; ! 1228: TSS2_SYS_CMD_AUTHS sessions_data_cmd; ! 1229: TSS2_SYS_RSP_AUTHS sessions_data_rsp; ! 1230: TPMS_AUTH_COMMAND *session_data_cmd_array[1]; ! 1231: TPMS_AUTH_RESPONSE *session_data_rsp_array[1]; ! 1232: ! 1233: /* query maximum TPM data transmission size */ ! 1234: this->mutex->lock(this->mutex); ! 1235: rval = Tss2_Sys_GetCapability(this->sys_context, 0, TPM_CAP_TPM_PROPERTIES, ! 1236: TPM_PT_NV_BUFFER_MAX, 1, &more_data, &cap_data, 0); ! 1237: this->mutex->unlock(this->mutex); ! 1238: if (rval != TPM_RC_SUCCESS) ! 1239: { ! 1240: DBG1(DBG_PTS,"%s Tss2_Sys_GetCapability failed for " ! 1241: "TPM_CAP_TPM_PROPERTIES: 0x%06x", LABEL, rval); ! 1242: return FALSE; ! 1243: } ! 1244: max_data_size = min(cap_data.data.tpmProperties.tpmProperty[0].value, ! 1245: MAX_NV_BUFFER_SIZE); ! 1246: ! 1247: /* get size of NV object */ ! 1248: this->mutex->lock(this->mutex); ! 1249: rval = Tss2_Sys_NV_ReadPublic(this->sys_context, handle, 0, &nv_public, ! 1250: &nv_name, 0); ! 1251: this->mutex->unlock(this->mutex); ! 1252: if (rval != TPM_RC_SUCCESS) ! 1253: { ! 1254: DBG1(DBG_PTS,"%s Tss2_Sys_NV_ReadPublic failed: 0x%06x", LABEL, rval); ! 1255: return FALSE; ! 1256: } ! 1257: nv_size = nv_public.t.nvPublic.dataSize; ! 1258: *data = chunk_alloc(nv_size); ! 1259: ! 1260: /*prepare NV read session */ ! 1261: session_data_cmd_array[0] = &session_data_cmd; ! 1262: session_data_rsp_array[0] = &session_data_rsp; ! 1263: ! 1264: sessions_data_cmd.cmdAuths = &session_data_cmd_array[0]; ! 1265: sessions_data_rsp.rspAuths = &session_data_rsp_array[0]; ! 1266: ! 1267: sessions_data_cmd.cmdAuthsCount = 1; ! 1268: sessions_data_rsp.rspAuthsCount = 1; ! 1269: ! 1270: session_data_cmd.sessionHandle = TPM_RS_PW; ! 1271: session_data_cmd.nonce.t.size = 0; ! 1272: session_data_cmd.hmac.t.size = 0; ! 1273: ! 1274: if (pin.len > 0) ! 1275: { ! 1276: session_data_cmd.hmac.t.size = min(sizeof(session_data_cmd.hmac.t) - 2, ! 1277: pin.len); ! 1278: memcpy(session_data_cmd.hmac.t.buffer, pin.ptr, ! 1279: session_data_cmd.hmac.t.size); ! 1280: } ! 1281: *( (uint8_t *)((void *)&session_data_cmd.sessionAttributes ) ) = 0; ! 1282: ! 1283: /* read NV data a maximum data size block at a time */ ! 1284: while (nv_size > 0) ! 1285: { ! 1286: this->mutex->lock(this->mutex); ! 1287: rval = Tss2_Sys_NV_Read(this->sys_context, hierarchy, handle, ! 1288: &sessions_data_cmd, min(nv_size, max_data_size), ! 1289: nv_offset, &nv_data, &sessions_data_rsp); ! 1290: this->mutex->unlock(this->mutex); ! 1291: if (rval != TPM_RC_SUCCESS) ! 1292: { ! 1293: DBG1(DBG_PTS,"%s Tss2_Sys_NV_Read failed: 0x%06x", LABEL, rval); ! 1294: chunk_free(data); ! 1295: return FALSE; ! 1296: } ! 1297: memcpy(data->ptr + nv_offset, nv_data.t.buffer, nv_data.t.size); ! 1298: nv_offset += nv_data.t.size; ! 1299: nv_size -= nv_data.t.size; ! 1300: } ! 1301: ! 1302: return TRUE; ! 1303: } ! 1304: ! 1305: METHOD(tpm_tss_t, destroy, void, ! 1306: private_tpm_tss_tss2_t *this) ! 1307: { ! 1308: finalize_context(this); ! 1309: this->mutex->destroy(this->mutex); ! 1310: free(this); ! 1311: } ! 1312: ! 1313: /** ! 1314: * See header ! 1315: */ ! 1316: tpm_tss_t *tpm_tss_tss2_create() ! 1317: { ! 1318: private_tpm_tss_tss2_t *this; ! 1319: bool available; ! 1320: ! 1321: INIT(this, ! 1322: .public = { ! 1323: .get_version = _get_version, ! 1324: .get_version_info = _get_version_info, ! 1325: .generate_aik = _generate_aik, ! 1326: .get_public = _get_public, ! 1327: .supported_signature_schemes = _supported_signature_schemes, ! 1328: .read_pcr = _read_pcr, ! 1329: .extend_pcr = _extend_pcr, ! 1330: .quote = _quote, ! 1331: .sign = _sign, ! 1332: .get_random = _get_random, ! 1333: .get_data = _get_data, ! 1334: .destroy = _destroy, ! 1335: }, ! 1336: .mutex = mutex_create(MUTEX_TYPE_DEFAULT), ! 1337: ); ! 1338: ! 1339: available = initialize_tcti_tabrmd_context(this); ! 1340: if (!available) ! 1341: { ! 1342: available = initialize_tcti_socket_context(this); ! 1343: } ! 1344: if (available) ! 1345: { ! 1346: available = initialize_sys_context(this); ! 1347: } ! 1348: DBG1(DBG_PTS, "TPM 2.0 via TSS2 v1 %savailable", available ? "" : "not "); ! 1349: ! 1350: if (!available) ! 1351: { ! 1352: destroy(this); ! 1353: return NULL; ! 1354: } ! 1355: return &this->public; ! 1356: } ! 1357: ! 1358: #else /* TSS_TSS2_V1 */ ! 1359: ! 1360: #ifndef TSS_TSS2_V2 ! 1361: tpm_tss_t *tpm_tss_tss2_create(void) ! 1362: { ! 1363: return NULL; ! 1364: } ! 1365: #endif /* !TSS_TSS2_V2 */ ! 1366: ! 1367: #endif /* TSS_TSS2_V1 */ ! 1368: ! 1369: