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