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