libtpmtss: Fix problematic usage of chunk_from_chars() in TSS2 implementations
[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 = 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, &quoted,
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", &quoted_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