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