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