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