e527443fb9715ff9bad502653f1020d2508a4078
[strongswan.git] / src / libtpmtss / tpm_tss_tss2_v2.c
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, aik_modulus;
452 uint32_t exponent;
453
454 scheme = &public.publicArea.parameters.rsaDetail.scheme;
455 sig_alg = scheme->scheme;
456 digest_alg = scheme->details.anySig.hashAlg;
457
458 rsa = &public.publicArea.unique.rsa;
459 aik_modulus = chunk_create(rsa->buffer, rsa->size);
460 exponent = public.publicArea.parameters.rsaDetail.exponent;
461 if (!exponent)
462 {
463 aik_exponent = chunk_from_chars(0x01, 0x00, 0x01);
464 }
465 else
466 {
467 aik_exponent = chunk_from_thing(exponent);
468 }
469
470 /* subjectPublicKeyInfo encoding of RSA public key */
471 if (!lib->encoding->encode(lib->encoding, PUBKEY_SPKI_ASN1_DER,
472 NULL, &aik_pubkey, CRED_PART_RSA_MODULUS, aik_modulus,
473 CRED_PART_RSA_PUB_EXP, aik_exponent, CRED_PART_END))
474 {
475 DBG1(DBG_PTS, "%s subjectPublicKeyInfo encoding of public key "
476 "failed", LABEL);
477 return chunk_empty;
478 }
479 break;
480 }
481 case TPM2_ALG_ECC:
482 {
483 TPMS_ECC_POINT *ecc;
484 TPMT_ECC_SCHEME *scheme;
485 chunk_t ecc_point;
486 uint8_t *pos;
487
488 scheme = &public.publicArea.parameters.eccDetail.scheme;
489 sig_alg = scheme->scheme;
490 digest_alg = scheme->details.anySig.hashAlg;
491
492 ecc = &public.publicArea.unique.ecc;
493
494 /* allocate space for bit string */
495 pos = asn1_build_object(&ecc_point, ASN1_BIT_STRING,
496 2 + ecc->x.size + ecc->y.size);
497 /* bit string length is a multiple of octets */
498 *pos++ = 0x00;
499 /* uncompressed ECC point format */
500 *pos++ = 0x04;
501 /* copy x coordinate of ECC point */
502 memcpy(pos, ecc->x.buffer, ecc->x.size);
503 pos += ecc->x.size;
504 /* copy y coordinate of ECC point */
505 memcpy(pos, ecc->y.buffer, ecc->y.size);
506 /* subjectPublicKeyInfo encoding of ECC public key */
507 aik_pubkey = asn1_wrap(ASN1_SEQUENCE, "mm",
508 asn1_wrap(ASN1_SEQUENCE, "mm",
509 asn1_build_known_oid(OID_EC_PUBLICKEY),
510 asn1_build_known_oid(ecc->x.size == 32 ?
511 OID_PRIME256V1 : OID_SECT384R1)),
512 ecc_point);
513 break;
514 }
515 default:
516 DBG1(DBG_PTS, "%s unsupported key type", LABEL);
517 return chunk_empty;
518 }
519 DBG1(DBG_PTS, "signature algorithm is %N with %N hash",
520 tpm_alg_id_names, sig_alg, tpm_alg_id_names, digest_alg);
521 return aik_pubkey;
522 }
523
524 METHOD(tpm_tss_t, supported_signature_schemes, enumerator_t*,
525 private_tpm_tss_tss2_t *this, uint32_t handle)
526 {
527 TPM2B_PUBLIC public = { 0, };
528 hash_algorithm_t digest;
529 signature_params_t supported_scheme;
530
531 if (!read_public(this, handle, &public))
532 {
533 return enumerator_create_empty();
534 }
535
536 switch (public.publicArea.type)
537 {
538 case TPM2_ALG_RSA:
539 {
540 TPMS_RSA_PARMS *rsa;
541 TPMT_RSA_SCHEME *scheme;
542
543 rsa = &public.publicArea.parameters.rsaDetail;
544 scheme = &rsa->scheme;
545 digest = hash_alg_from_tpm_alg_id(scheme->details.anySig.hashAlg);
546
547 switch (scheme->scheme)
548 {
549 case TPM2_ALG_RSAPSS:
550 {
551 ssize_t salt_len;
552
553 salt_len = this->fips_186_4 ? RSA_PSS_SALT_LEN_DEFAULT :
554 RSA_PSS_SALT_LEN_MAX;
555 rsa_pss_params_t pss_params = {
556 .hash = digest,
557 .mgf1_hash = digest,
558 .salt_len = salt_len,
559 };
560 supported_scheme = (signature_params_t){
561 .scheme = SIGN_RSA_EMSA_PSS,
562 .params = &pss_params,
563 };
564 if (!rsa_pss_params_set_salt_len(&pss_params, rsa->keyBits))
565 {
566 return enumerator_create_empty();
567 }
568 break;
569 }
570 case TPM2_ALG_RSASSA:
571 supported_scheme = (signature_params_t){
572 .scheme = signature_scheme_from_oid(
573 hasher_signature_algorithm_to_oid(digest,
574 KEY_RSA)),
575 };
576 break;
577 default:
578 return enumerator_create_empty();
579 }
580 break;
581 }
582 case TPM2_ALG_ECC:
583 {
584 TPMT_ECC_SCHEME *scheme;
585
586 scheme = &public.publicArea.parameters.eccDetail.scheme;
587 digest = hash_alg_from_tpm_alg_id(scheme->details.anySig.hashAlg);
588
589 switch (scheme->scheme)
590 {
591 case TPM2_ALG_ECDSA:
592 supported_scheme = (signature_params_t){
593 .scheme = signature_scheme_from_oid(
594 hasher_signature_algorithm_to_oid(digest,
595 KEY_ECDSA)),
596 };
597 break;
598 default:
599 return enumerator_create_empty();
600 }
601 break;
602 }
603 default:
604 DBG1(DBG_PTS, "%s unsupported key type", LABEL);
605 return enumerator_create_empty();
606 }
607 return enumerator_create_single(signature_params_clone(&supported_scheme),
608 (void*)signature_params_destroy);
609 }
610
611 /**
612 * Configure a PCR Selection assuming a maximum of 24 registers
613 */
614 static bool init_pcr_selection(private_tpm_tss_tss2_t *this, uint32_t pcrs,
615 hash_algorithm_t alg, TPML_PCR_SELECTION *pcr_sel)
616 {
617 TPM2_ALG_ID alg_id;
618 uint32_t pcr;
619
620 /* check if hash algorithm is supported by TPM */
621 alg_id = hash_alg_to_tpm_alg_id(alg);
622 if (!is_supported_alg(this, alg_id))
623 {
624 DBG1(DBG_PTS, "%s %N hash algorithm not supported by TPM",
625 LABEL, hash_algorithm_short_names, alg);
626 return FALSE;
627 }
628
629 /* initialize the PCR Selection structure,*/
630 pcr_sel->count = 1;
631 pcr_sel->pcrSelections[0].hash = alg_id;
632 pcr_sel->pcrSelections[0].sizeofSelect = 3;
633 pcr_sel->pcrSelections[0].pcrSelect[0] = 0;
634 pcr_sel->pcrSelections[0].pcrSelect[1] = 0;
635 pcr_sel->pcrSelections[0].pcrSelect[2] = 0;
636
637 /* set the selected PCRs */
638 for (pcr = 0; pcr < PLATFORM_PCR; pcr++)
639 {
640 if (pcrs & (1 << pcr))
641 {
642 pcr_sel->pcrSelections[0].pcrSelect[pcr / 8] |= ( 1 << (pcr % 8) );
643 }
644 }
645 return TRUE;
646 }
647
648 METHOD(tpm_tss_t, read_pcr, bool,
649 private_tpm_tss_tss2_t *this, uint32_t pcr_num, chunk_t *pcr_value,
650 hash_algorithm_t alg)
651 {
652 TPML_PCR_SELECTION pcr_selection;
653 TPML_DIGEST pcr_values;
654
655 uint32_t pcr_update_counter, rval;
656 uint8_t *pcr_value_ptr;
657 size_t pcr_value_len;
658
659 if (pcr_num >= PLATFORM_PCR)
660 {
661 DBG1(DBG_PTS, "%s maximum number of supported PCR is %d",
662 LABEL, PLATFORM_PCR);
663 return FALSE;
664 }
665
666 if (!init_pcr_selection(this, (1 << pcr_num), alg, &pcr_selection))
667 {
668 return FALSE;
669 }
670
671 /* initialize the PCR Digest structure */
672 memset(&pcr_values, 0, sizeof(TPML_DIGEST));
673
674 /* read the PCR value */
675 this->mutex->lock(this->mutex);
676 rval = Tss2_Sys_PCR_Read(this->sys_context, 0, &pcr_selection,
677 &pcr_update_counter, &pcr_selection, &pcr_values, 0);
678 this->mutex->unlock(this->mutex);
679 if (rval != TPM2_RC_SUCCESS)
680 {
681 DBG1(DBG_PTS, "%s PCR bank could not be read: 0x%60x",
682 LABEL, rval);
683 return FALSE;
684 }
685 pcr_value_ptr = (uint8_t *)pcr_values.digests[0].buffer;
686 pcr_value_len = (size_t) pcr_values.digests[0].size;
687
688 *pcr_value = chunk_clone(chunk_create(pcr_value_ptr, pcr_value_len));
689
690 return TRUE;
691 }
692
693 METHOD(tpm_tss_t, extend_pcr, bool,
694 private_tpm_tss_tss2_t *this, uint32_t pcr_num, chunk_t *pcr_value,
695 chunk_t data, hash_algorithm_t alg)
696 {
697 uint32_t rval;
698 TPM2_ALG_ID alg_id;
699 TPML_DIGEST_VALUES digest_values;
700 TSS2L_SYS_AUTH_COMMAND auth_cmd = { 1, { auth_cmd_empty } };
701 TSS2L_SYS_AUTH_RESPONSE auth_rsp;
702
703 auth_cmd.auths[0].sessionHandle = TPM2_RS_PW;
704
705 /* check if hash algorithm is supported by TPM */
706 alg_id = hash_alg_to_tpm_alg_id(alg);
707 if (!is_supported_alg(this, alg_id))
708 {
709 DBG1(DBG_PTS, "%s %N hash algorithm not supported by TPM",
710 LABEL, hash_algorithm_short_names, alg);
711 return FALSE;
712 }
713
714 digest_values.count = 1;
715 digest_values.digests[0].hashAlg = alg_id;
716
717 switch (alg)
718 {
719 case HASH_SHA1:
720 if (data.len != HASH_SIZE_SHA1)
721 {
722 return FALSE;
723 }
724 memcpy(digest_values.digests[0].digest.sha1, data.ptr,
725 HASH_SIZE_SHA1);
726 break;
727 case HASH_SHA256:
728 if (data.len != HASH_SIZE_SHA256)
729 {
730 return FALSE;
731 }
732 memcpy(digest_values.digests[0].digest.sha256, data.ptr,
733 HASH_SIZE_SHA256);
734 break;
735 case HASH_SHA384:
736 if (data.len != HASH_SIZE_SHA384)
737 {
738 return FALSE;
739 }
740 memcpy(digest_values.digests[0].digest.sha384, data.ptr,
741 HASH_SIZE_SHA384);
742 break;
743 case HASH_SHA512:
744 if (data.len != HASH_SIZE_SHA512)
745 {
746 return FALSE;
747 }
748 memcpy(digest_values.digests[0].digest.sha512, data.ptr,
749 HASH_SIZE_SHA512);
750 break;
751 default:
752 return FALSE;
753 }
754
755 /* extend PCR */
756 this->mutex->lock(this->mutex);
757 rval = Tss2_Sys_PCR_Extend(this->sys_context, pcr_num, &auth_cmd,
758 &digest_values, &auth_rsp);
759 this->mutex->unlock(this->mutex);
760 if (rval != TPM2_RC_SUCCESS)
761 {
762 DBG1(DBG_PTS, "%s PCR %02u could not be extended: 0x%06x",
763 LABEL, pcr_num, rval);
764 return FALSE;
765 }
766
767 /* get updated PCR value */
768 return read_pcr(this, pcr_num, pcr_value, alg);
769 }
770
771 METHOD(tpm_tss_t, quote, bool,
772 private_tpm_tss_tss2_t *this, uint32_t aik_handle, uint32_t pcr_sel,
773 hash_algorithm_t alg, chunk_t data, tpm_quote_mode_t *quote_mode,
774 tpm_tss_quote_info_t **quote_info, chunk_t *quote_sig)
775 {
776 chunk_t quoted_chunk, qualified_signer, extra_data, clock_info,
777 firmware_version, pcr_select, pcr_digest;
778 hash_algorithm_t pcr_digest_alg;
779 bio_reader_t *reader;
780 uint32_t rval;
781
782 TPM2B_DATA qualifying_data;
783 TPML_PCR_SELECTION pcr_selection;
784 TPM2B_ATTEST quoted = { sizeof(TPM2B_ATTEST)-2, };
785 TPMT_SIG_SCHEME scheme;
786 TPMT_SIGNATURE sig;
787 TPMI_ALG_HASH hash_alg;
788 TSS2L_SYS_AUTH_COMMAND auth_cmd = { 1, { auth_cmd_empty } };
789 TSS2L_SYS_AUTH_RESPONSE auth_rsp;
790
791 auth_cmd.auths[0].sessionHandle = TPM2_RS_PW;
792
793 qualifying_data.size = data.len;
794 memcpy(qualifying_data.buffer, data.ptr, data.len);
795
796 scheme.scheme = TPM2_ALG_NULL;
797 memset(&sig, 0x00, sizeof(sig));
798
799 /* set Quote mode */
800 *quote_mode = TPM_QUOTE_TPM2;
801
802 if (!init_pcr_selection(this, pcr_sel, alg, &pcr_selection))
803 {
804 return FALSE;
805 }
806
807 this->mutex->lock(this->mutex);
808 rval = Tss2_Sys_Quote(this->sys_context, aik_handle, &auth_cmd,
809 &qualifying_data, &scheme, &pcr_selection, &quoted,
810 &sig, &auth_rsp);
811 this->mutex->unlock(this->mutex);
812 if (rval != TPM2_RC_SUCCESS)
813 {
814 DBG1(DBG_PTS,"%s Tss2_Sys_Quote failed: 0x%06x", LABEL, rval);
815 return FALSE;
816 }
817 quoted_chunk = chunk_create(quoted.attestationData, quoted.size);
818
819 reader = bio_reader_create(chunk_skip(quoted_chunk, 6));
820 if (!reader->read_data16(reader, &qualified_signer) ||
821 !reader->read_data16(reader, &extra_data) ||
822 !reader->read_data (reader, 17, &clock_info) ||
823 !reader->read_data (reader, 8, &firmware_version) ||
824 !reader->read_data (reader, 10, &pcr_select) ||
825 !reader->read_data16(reader, &pcr_digest))
826 {
827 DBG1(DBG_PTS, "%s parsing of quoted struct failed", LABEL);
828 reader->destroy(reader);
829 return FALSE;
830 }
831 reader->destroy(reader);
832
833 DBG2(DBG_PTS, "PCR Composite digest: %B", &pcr_digest);
834 DBG2(DBG_PTS, "TPM Quote Info: %B", &quoted_chunk);
835 DBG2(DBG_PTS, "qualifiedSigner: %B", &qualified_signer);
836 DBG2(DBG_PTS, "extraData: %B", &extra_data);
837 DBG2(DBG_PTS, "clockInfo: %B", &clock_info);
838 DBG2(DBG_PTS, "firmwareVersion: %B", &firmware_version);
839 DBG2(DBG_PTS, "pcrSelect: %B", &pcr_select);
840
841 /* extract signature */
842 switch (sig.sigAlg)
843 {
844 case TPM2_ALG_RSASSA:
845 case TPM2_ALG_RSAPSS:
846 *quote_sig = chunk_clone(
847 chunk_create(
848 sig.signature.rsassa.sig.buffer,
849 sig.signature.rsassa.sig.size));
850 hash_alg = sig.signature.rsassa.hash;
851 break;
852 case TPM2_ALG_ECDSA:
853 case TPM2_ALG_ECDAA:
854 case TPM2_ALG_SM2:
855 case TPM2_ALG_ECSCHNORR:
856 *quote_sig = chunk_cat("cc",
857 chunk_create(
858 sig.signature.ecdsa.signatureR.buffer,
859 sig.signature.ecdsa.signatureR.size),
860 chunk_create(
861 sig.signature.ecdsa.signatureS.buffer,
862 sig.signature.ecdsa.signatureS.size));
863 hash_alg = sig.signature.ecdsa.hash;
864 break;
865 default:
866 DBG1(DBG_PTS, "%s unsupported %N signature algorithm",
867 LABEL, tpm_alg_id_names, sig.sigAlg);
868 return FALSE;
869 }
870
871 DBG2(DBG_PTS, "PCR digest algorithm is %N", tpm_alg_id_names, hash_alg);
872 pcr_digest_alg = hash_alg_from_tpm_alg_id(hash_alg);
873
874 DBG2(DBG_PTS, "TPM Quote Signature: %B", quote_sig);
875
876 /* Create and initialize Quote Info object */
877 *quote_info = tpm_tss_quote_info_create(*quote_mode, pcr_digest_alg,
878 pcr_digest);
879 (*quote_info)->set_tpm2_info(*quote_info, qualified_signer, clock_info,
880 pcr_select);
881 (*quote_info)->set_version_info(*quote_info, firmware_version);
882
883 return TRUE;
884 }
885
886 METHOD(tpm_tss_t, sign, bool,
887 private_tpm_tss_tss2_t *this, uint32_t hierarchy, uint32_t handle,
888 signature_scheme_t scheme, void *params, chunk_t data, chunk_t pin,
889 chunk_t *signature)
890 {
891 key_type_t key_type;
892 hash_algorithm_t hash_alg;
893 rsa_pss_params_t *rsa_pss_params;
894 uint32_t rval;
895
896 TPM2_ALG_ID alg_id;
897 TPM2B_MAX_BUFFER buffer;
898 TPM2B_DIGEST hash = { sizeof(TPM2B_DIGEST)-2, };
899 TPMT_TK_HASHCHECK validation;
900 TPM2B_PUBLIC public = { 0, };
901 TPMT_SIG_SCHEME sig_scheme;
902 TPMT_SIGNATURE sig;
903 TPMS_AUTH_COMMAND *cmd;
904 TSS2L_SYS_AUTH_COMMAND auth_cmd = { 1, { auth_cmd_empty } };
905 TSS2L_SYS_AUTH_RESPONSE auth_rsp;
906
907 cmd = &auth_cmd.auths[0];
908 cmd->sessionHandle = TPM2_RS_PW;
909
910 if (pin.len > 0)
911 {
912 cmd->hmac.size = min(sizeof(cmd->hmac)-2, pin.len);
913 memcpy(cmd->hmac.buffer, pin.ptr, cmd->hmac.size);
914 }
915
916 if (scheme == SIGN_RSA_EMSA_PSS)
917 {
918 key_type = KEY_RSA;
919 rsa_pss_params = (rsa_pss_params_t *)params;
920 hash_alg = rsa_pss_params->hash;
921 }
922 else
923 {
924 key_type = key_type_from_signature_scheme(scheme);
925 hash_alg = hasher_from_signature_scheme(scheme, NULL);
926 }
927
928 /* Check if hash algorithm is supported by TPM */
929 alg_id = hash_alg_to_tpm_alg_id(hash_alg);
930 if (!is_supported_alg(this, alg_id))
931 {
932 DBG1(DBG_PTS, "%s %N hash algorithm not supported by TPM",
933 LABEL, hash_algorithm_short_names, hash_alg);
934 return FALSE;
935 }
936
937 /* Get public key */
938 if (!read_public(this, handle, &public))
939 {
940 return FALSE;
941 }
942
943 if (key_type == KEY_RSA && public.publicArea.type == TPM2_ALG_RSA)
944 {
945 if (scheme == SIGN_RSA_EMSA_PSS)
946 {
947 sig_scheme.scheme = TPM2_ALG_RSAPSS;
948 sig_scheme.details.rsapss.hashAlg = alg_id;
949 }
950 else
951 {
952 sig_scheme.scheme = TPM2_ALG_RSASSA;
953 sig_scheme.details.rsassa.hashAlg = alg_id;
954 }
955 }
956 else if (key_type == KEY_ECDSA && public.publicArea.type == TPM2_ALG_ECC)
957 {
958 sig_scheme.scheme = TPM2_ALG_ECDSA;
959 sig_scheme.details.ecdsa.hashAlg = alg_id;
960
961 }
962 else
963 {
964 DBG1(DBG_PTS, "%s signature scheme %N not supported by TPM key",
965 LABEL, signature_scheme_names, scheme);
966 return FALSE;
967 }
968
969 if (data.len <= TPM2_MAX_DIGEST_BUFFER)
970 {
971 memcpy(buffer.buffer, data.ptr, data.len);
972 buffer.size = data.len;
973
974 this->mutex->lock(this->mutex);
975 rval = Tss2_Sys_Hash(this->sys_context, 0, &buffer, alg_id, hierarchy,
976 &hash, &validation, 0);
977 this->mutex->unlock(this->mutex);
978 if (rval != TPM2_RC_SUCCESS)
979 {
980 DBG1(DBG_PTS,"%s Tss2_Sys_Hash failed: 0x%06x", LABEL, rval);
981 return FALSE;
982 }
983 }
984 else
985 {
986 TPMI_DH_OBJECT sequence_handle;
987 TPM2B_AUTH null_auth;
988
989 null_auth.size = 0;
990 this->mutex->lock(this->mutex);
991 rval = Tss2_Sys_HashSequenceStart(this->sys_context, 0, &null_auth,
992 alg_id, &sequence_handle, 0);
993 if (rval != TPM2_RC_SUCCESS)
994 {
995 DBG1(DBG_PTS,"%s Tss2_Sys_HashSequenceStart failed: 0x%06x",
996 LABEL, rval);
997 this->mutex->unlock(this->mutex);
998 return FALSE;
999 }
1000
1001 while (data.len > 0)
1002 {
1003 buffer.size = min(data.len, TPM2_MAX_DIGEST_BUFFER);
1004 memcpy(buffer.buffer, data.ptr, buffer.size);
1005 data.ptr += buffer.size;
1006 data.len -= buffer.size;
1007
1008 rval = Tss2_Sys_SequenceUpdate(this->sys_context, sequence_handle,
1009 &auth_cmd, &buffer, 0);
1010 if (rval != TPM2_RC_SUCCESS)
1011 {
1012 DBG1(DBG_PTS,"%s Tss2_Sys_SequenceUpdate failed: 0x%06x",
1013 LABEL, rval);
1014 this->mutex->unlock(this->mutex);
1015 return FALSE;
1016 }
1017 }
1018 buffer.size = 0;
1019
1020 rval = Tss2_Sys_SequenceComplete(this->sys_context, sequence_handle,
1021 &auth_cmd, &buffer, hierarchy,
1022 &hash, &validation, 0);
1023 this->mutex->unlock(this->mutex);
1024 if (rval != TPM2_RC_SUCCESS)
1025 {
1026 DBG1(DBG_PTS,"%s Tss2_Sys_SequenceComplete failed: 0x%06x",
1027 LABEL, rval);
1028 return FALSE;
1029 }
1030 }
1031
1032 this->mutex->lock(this->mutex);
1033 rval = Tss2_Sys_Sign(this->sys_context, handle, &auth_cmd, &hash,
1034 &sig_scheme, &validation, &sig, &auth_rsp);
1035 this->mutex->unlock(this->mutex);
1036 if (rval != TPM2_RC_SUCCESS)
1037 {
1038 DBG1(DBG_PTS,"%s Tss2_Sys_Sign failed: 0x%06x", LABEL, rval);
1039 return FALSE;
1040 }
1041
1042 /* extract signature */
1043 switch (scheme)
1044 {
1045 case SIGN_RSA_EMSA_PKCS1_SHA1:
1046 case SIGN_RSA_EMSA_PKCS1_SHA2_256:
1047 case SIGN_RSA_EMSA_PKCS1_SHA2_384:
1048 case SIGN_RSA_EMSA_PKCS1_SHA2_512:
1049 *signature = chunk_clone(
1050 chunk_create(
1051 sig.signature.rsassa.sig.buffer,
1052 sig.signature.rsassa.sig.size));
1053 break;
1054 case SIGN_RSA_EMSA_PSS:
1055 *signature = chunk_clone(
1056 chunk_create(
1057 sig.signature.rsapss.sig.buffer,
1058 sig.signature.rsapss.sig.size));
1059 break;
1060 case SIGN_ECDSA_256:
1061 case SIGN_ECDSA_384:
1062 case SIGN_ECDSA_521:
1063 *signature = chunk_cat("cc",
1064 chunk_create(
1065 sig.signature.ecdsa.signatureR.buffer,
1066 sig.signature.ecdsa.signatureR.size),
1067 chunk_create(
1068 sig.signature.ecdsa.signatureS.buffer,
1069 sig.signature.ecdsa.signatureS.size));
1070 break;
1071 case SIGN_ECDSA_WITH_SHA256_DER:
1072 case SIGN_ECDSA_WITH_SHA384_DER:
1073 case SIGN_ECDSA_WITH_SHA512_DER:
1074 *signature = asn1_wrap(ASN1_SEQUENCE, "mm",
1075 asn1_integer("c",
1076 chunk_create(
1077 sig.signature.ecdsa.signatureR.buffer,
1078 sig.signature.ecdsa.signatureR.size)),
1079 asn1_integer("c",
1080 chunk_create(
1081 sig.signature.ecdsa.signatureS.buffer,
1082 sig.signature.ecdsa.signatureS.size)));
1083 break;
1084 default:
1085 DBG1(DBG_PTS, "%s unsupported %N signature scheme",
1086 LABEL, signature_scheme_names, scheme);
1087 return FALSE;
1088 }
1089
1090 return TRUE;
1091 }
1092
1093 METHOD(tpm_tss_t, get_random, bool,
1094 private_tpm_tss_tss2_t *this, size_t bytes, uint8_t *buffer)
1095 {
1096 size_t len, random_len= sizeof(TPM2B_DIGEST)-2;
1097 TPM2B_DIGEST random = { random_len, };
1098 uint8_t *pos = buffer;
1099 uint32_t rval;
1100
1101 while (bytes > 0)
1102 {
1103 len = min(bytes, random_len);
1104
1105 this->mutex->lock(this->mutex);
1106 rval = Tss2_Sys_GetRandom(this->sys_context, NULL, len, &random, NULL);
1107 this->mutex->unlock(this->mutex);
1108 if (rval != TSS2_RC_SUCCESS)
1109 {
1110 DBG1(DBG_PTS,"%s Tss2_Sys_GetRandom failed: 0x%06x", LABEL, rval);
1111 return FALSE;
1112 }
1113 memcpy(pos, random.buffer, random.size);
1114 pos += random.size;
1115 bytes -= random.size;
1116 }
1117
1118 return TRUE;
1119 }
1120
1121 METHOD(tpm_tss_t, get_data, bool,
1122 private_tpm_tss_tss2_t *this, uint32_t hierarchy, uint32_t handle,
1123 chunk_t pin, chunk_t *data)
1124 {
1125 uint16_t max_data_size, nv_size, nv_offset = 0;
1126 uint32_t rval;
1127
1128 TPMS_CAPABILITY_DATA cap_data;
1129 TPMI_YES_NO more_data;
1130 TPM2B_NAME nv_name = { sizeof(TPM2B_NAME)-2, };
1131 TPM2B_NV_PUBLIC nv_public = { 0, };
1132 TPM2B_MAX_NV_BUFFER nv_data = { TPM2_MAX_NV_BUFFER_SIZE, };
1133 TPMS_AUTH_COMMAND *cmd;
1134 TSS2L_SYS_AUTH_COMMAND auth_cmd = { 1, { auth_cmd_empty } };
1135 TSS2L_SYS_AUTH_RESPONSE auth_rsp;
1136
1137 /* query maximum TPM data transmission size */
1138 this->mutex->lock(this->mutex);
1139 rval = Tss2_Sys_GetCapability(this->sys_context, 0, TPM2_CAP_TPM_PROPERTIES,
1140 TPM2_PT_NV_BUFFER_MAX, 1, &more_data, &cap_data, 0);
1141 this->mutex->unlock(this->mutex);
1142 if (rval != TPM2_RC_SUCCESS)
1143 {
1144 DBG1(DBG_PTS,"%s Tss2_Sys_GetCapability failed for "
1145 "TPM2_CAP_TPM_PROPERTIES: 0x%06x", LABEL, rval);
1146 return FALSE;
1147 }
1148 max_data_size = min(cap_data.data.tpmProperties.tpmProperty[0].value,
1149 TPM2_MAX_NV_BUFFER_SIZE);
1150
1151 /* get size of NV object */
1152 this->mutex->lock(this->mutex);
1153 rval = Tss2_Sys_NV_ReadPublic(this->sys_context, handle, 0, &nv_public,
1154 &nv_name, 0);
1155 this->mutex->unlock(this->mutex);
1156 if (rval != TPM2_RC_SUCCESS)
1157 {
1158 DBG1(DBG_PTS,"%s Tss2_Sys_NV_ReadPublic failed: 0x%06x", LABEL, rval);
1159 return FALSE;
1160 }
1161 nv_size = nv_public.nvPublic.dataSize;
1162 *data = chunk_alloc(nv_size);
1163
1164 /* prepare NV read session */
1165 cmd = &auth_cmd.auths[0];
1166 cmd->sessionHandle = TPM2_RS_PW;
1167
1168 if (pin.len > 0)
1169 {
1170 cmd->hmac.size = min(sizeof(cmd->hmac)-2, pin.len);
1171 memcpy(cmd->hmac.buffer, pin.ptr, cmd->hmac.size);
1172 }
1173
1174 /* read NV data a maximum data size block at a time */
1175 while (nv_size > 0)
1176 {
1177 this->mutex->lock(this->mutex);
1178 rval = Tss2_Sys_NV_Read(this->sys_context, hierarchy, handle, &auth_cmd,
1179 min(nv_size, max_data_size), nv_offset, &nv_data, &auth_rsp);
1180 this->mutex->unlock(this->mutex);
1181 if (rval != TPM2_RC_SUCCESS)
1182 {
1183 DBG1(DBG_PTS,"%s Tss2_Sys_NV_Read failed: 0x%06x", LABEL, rval);
1184 chunk_free(data);
1185 return FALSE;
1186 }
1187 memcpy(data->ptr + nv_offset, nv_data.buffer, nv_data.size);
1188 nv_offset += nv_data.size;
1189 nv_size -= nv_data.size;
1190 }
1191
1192 return TRUE;
1193 }
1194
1195 METHOD(tpm_tss_t, destroy, void,
1196 private_tpm_tss_tss2_t *this)
1197 {
1198 finalize_context(this);
1199 this->mutex->destroy(this->mutex);
1200 free(this);
1201 }
1202
1203 /**
1204 * See header
1205 */
1206 tpm_tss_t *tpm_tss_tss2_create()
1207 {
1208 private_tpm_tss_tss2_t *this;
1209 bool available;
1210
1211 INIT(this,
1212 .public = {
1213 .get_version = _get_version,
1214 .get_version_info = _get_version_info,
1215 .generate_aik = _generate_aik,
1216 .get_public = _get_public,
1217 .supported_signature_schemes = _supported_signature_schemes,
1218 .read_pcr = _read_pcr,
1219 .extend_pcr = _extend_pcr,
1220 .quote = _quote,
1221 .sign = _sign,
1222 .get_random = _get_random,
1223 .get_data = _get_data,
1224 .destroy = _destroy,
1225 },
1226 .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
1227 );
1228
1229 available = initialize_tcti_context(this);
1230 if (available)
1231 {
1232 available = initialize_sys_context(this);
1233 }
1234 DBG1(DBG_PTS, "TPM 2.0 via TSS2 v2 %savailable", available ? "" : "not ");
1235
1236 if (!available)
1237 {
1238 destroy(this);
1239 return NULL;
1240 }
1241 return &this->public;
1242 }
1243
1244 /**
1245 * See header
1246 */
1247 bool tpm_tss_tss2_init(void)
1248 {
1249 TSS2_TCTI_INFO_FUNC infofn;
1250 const TSS2_TCTI_INFO *info;
1251 char tcti_lib_format[] = "libtss2-tcti-%s.so.0";
1252 char tcti_lib[BUF_LEN];
1253 char *tcti_names[] = { "device", "tabrmd", "mssim" };
1254 char *tcti_options[] = { "/dev/tpmrm0", "", "" };
1255 char *tcti_name;
1256 bool match = FALSE;
1257 struct stat st;
1258 int i = 0;
1259
1260 /* check for the existence of an in-kernel TPM resource manager */
1261 if (stat(tcti_options[i], &st))
1262 {
1263 i = 1;
1264 }
1265 DBG2(DBG_PTS, "%s \"%s\" in-kernel resource manager is %spresent",
1266 LABEL, tcti_options[0], i ? "not " : "");
1267
1268 /* select a dynamic TCTI library (device, tabrmd or mssim) */
1269 tcti_name = lib->settings->get_str(lib->settings,
1270 "%s.plugins.tpm.tcti.name", tcti_names[i], lib->ns);
1271 snprintf(tcti_lib, BUF_LEN, tcti_lib_format, tcti_name);
1272
1273 for (i = 0; i < countof(tcti_names); i++)
1274 {
1275 if (streq(tcti_name, tcti_names[i]))
1276 {
1277 match = TRUE;
1278 break;
1279 }
1280 }
1281 if (!match)
1282 {
1283 DBG1(DBG_PTS, "%s \"%s\" is not a valid TCTI library name",
1284 LABEL, tcti_lib);
1285 return FALSE;
1286 }
1287
1288 tcti_opts = lib->settings->get_str(lib->settings,
1289 "%s.plugins.tpm.tcti.opts", tcti_options[i], lib->ns);
1290
1291 /* open the selected dynamic TCTI library */
1292 tcti_handle = dlopen(tcti_lib, RTLD_LAZY);
1293 if (!tcti_handle)
1294 {
1295 DBG1(DBG_PTS, "%s could not load \"%s\"", LABEL, tcti_lib);
1296 return FALSE;
1297 }
1298
1299 infofn = (TSS2_TCTI_INFO_FUNC)dlsym(tcti_handle, TSS2_TCTI_INFO_SYMBOL);
1300 if (!infofn)
1301 {
1302 DBG1(DBG_PTS, "%s symbol \"%s\" not found in \"%s\"", LABEL,
1303 TSS2_TCTI_INFO_SYMBOL, tcti_lib);
1304 tpm_tss_tss2_deinit();
1305
1306 return FALSE;
1307 }
1308 DBG2(DBG_PTS, "%s \"%s\" successfully loaded", LABEL, tcti_lib);
1309 info = infofn();
1310 tcti_init = info->init;
1311
1312 return TRUE;
1313 }
1314
1315 /**
1316 * See header
1317 */
1318 void tpm_tss_tss2_deinit(void)
1319 {
1320 dlclose(tcti_handle);
1321 tcti_handle = NULL;
1322 tcti_init = NULL;
1323 tcti_opts = NULL;
1324 }
1325
1326 #else /* TSS_TSS2_V2 */
1327
1328 /**
1329 * See header
1330 */
1331 bool tpm_tss_tss2_init(void)
1332 {
1333 return TRUE;
1334 }
1335
1336 /**
1337 * See header
1338 */
1339 void tpm_tss_tss2_deinit(void)
1340 {
1341 /* empty */
1342 }
1343
1344 #endif /* TSS_TSS2_V2 */
1345