2 * Copyright (C) 2018-2021 Andreas Steffen
3 * Copyright (C) 2018 Tobias Brunner
5 * Copyright (C) secunet Security Networks AG
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 #include "tpm_tss_tss2.h"
19 #include "tpm_tss_tss2_names.h"
23 #include "tpm_tss_tss2_session.h"
25 #include <asn1/asn1.h>
27 #include <bio/bio_reader.h>
28 #include <bio/bio_writer.h>
29 #include <threading/mutex.h>
32 #include <sys/types.h>
36 #define LABEL "TPM 2.0 - "
38 #define PLATFORM_PCR 24
39 #define MAX_PCR_BANKS 4
41 typedef struct private_tpm_tss_tss2_t private_tpm_tss_tss2_t
;
44 * Private data of an tpm_tss_tss2_t object.
46 struct private_tpm_tss_tss2_t
{
49 * Public tpm_tss_tss2_t interface.
56 TSS2_TCTI_CONTEXT
*tcti_context
;
61 TSS2_SYS_CONTEXT
*sys_context
;
69 * Number of supported algorithms
71 size_t supported_algs_count
;
74 * List of supported algorithms
76 TPM2_ALG_ID supported_algs
[TPM2_PT_ALGORITHM_SET
];
79 * Number of assigned PCR banks
81 size_t assigned_pcrs_count
;
84 * List of assigned PCR banks
86 TPM2_ALG_ID assigned_pcrs
[MAX_PCR_BANKS
];
89 * Is TPM FIPS 186-4 compliant ?
94 * Does the TPM use the old TCG SHA1-only event digest format
96 bool old_event_digest_format
;
99 * TSS2 session used for protected communication with TPM 2.0
101 tpm_tss_tss2_session_t
*session
;
104 * Mutex controlling access to the TPM 2.0 context
111 * Global TCTI dynamic library handle and init function
113 static void *tcti_handle
;
115 static TSS2_TCTI_INIT_FUNC tcti_init
;
117 static char *tcti_opts
;
122 static const TPMS_AUTH_COMMAND auth_cmd_empty
;
125 * Convert hash algorithm to TPM2_ALG_ID
127 static TPM2_ALG_ID
hash_alg_to_tpm_alg_id(hash_algorithm_t alg
)
132 return TPM2_ALG_SHA1
;
134 return TPM2_ALG_SHA256
;
136 return TPM2_ALG_SHA384
;
138 return TPM2_ALG_SHA512
;
140 return TPM2_ALG_SHA3_256
;
142 return TPM2_ALG_SHA3_384
;
144 return TPM2_ALG_SHA3_512
;
146 return TPM2_ALG_ERROR
;
151 * Convert TPM2_ALG_ID to hash algorithm
153 hash_algorithm_t
hash_alg_from_tpm_alg_id(TPM2_ALG_ID alg
)
159 case TPM2_ALG_SHA256
:
161 case TPM2_ALG_SHA384
:
163 case TPM2_ALG_SHA512
:
165 case TPM2_ALG_SHA3_256
:
166 return HASH_SHA3_256
;
167 case TPM2_ALG_SHA3_384
:
168 return HASH_SHA3_384
;
169 case TPM2_ALG_SHA3_512
:
170 return HASH_SHA3_512
;
177 * Return hash length of TPM2_ALG_ID algorithm
179 size_t hash_len_from_tpm_alg_id(TPM2_ALG_ID alg
)
184 return TPM2_SHA1_DIGEST_SIZE
;
185 case TPM2_ALG_SHA256
:
186 case TPM2_ALG_SHA3_256
:
187 return TPM2_SHA256_DIGEST_SIZE
;
188 case TPM2_ALG_SHA384
:
189 case TPM2_ALG_SHA3_384
:
190 return TPM2_SHA384_DIGEST_SIZE
;
191 case TPM2_ALG_SHA512
:
192 case TPM2_ALG_SHA3_512
:
193 return TPM2_SHA512_DIGEST_SIZE
;
194 case TPM2_ALG_SM3_256
:
195 return TPM2_SM3_256_DIGEST_SIZE
;
202 * Check if an algorithm given by its TPM2_ALG_ID is supported by the TPM
204 static bool is_supported_alg(private_tpm_tss_tss2_t
*this, TPM2_ALG_ID alg_id
)
208 if (alg_id
== TPM2_ALG_ERROR
)
213 for (i
= 0; i
< this->supported_algs_count
; i
++)
215 if (this->supported_algs
[i
] == alg_id
)
225 * Get the TPM version_info and a list of supported algorithms
228 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
230 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
231 * | TPM 2.0 Version_Info Tag | Reserved | Locality |
232 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
234 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
236 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
238 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
240 #define TPM2_VERSION_INFO_TAG 0x0200
241 #define TPM2_VERSION_INFO_RESERVED 0x00
242 #define TPM2_VERSION_INFO_SIZE 16
243 #define TPM2_DEFAULT_LOCALITY 3
245 static bool get_algs_capability(private_tpm_tss_tss2_t
*this)
247 TPMS_CAPABILITY_DATA cap_data
;
248 TPMS_TAGGED_PROPERTY tp
;
249 TPMI_YES_NO more_data
;
251 bio_writer_t
*writer
;
252 bool fips_140_2
= FALSE
;
253 uint32_t rval
, i
, offset
, revision
= 0, year
= 0, vendor
= 0;
254 uint8_t locality
= TPM2_DEFAULT_LOCALITY
;
255 size_t len
= BUF_LEN
;
256 char buf
[BUF_LEN
], manufacturer
[5], vendor_string
[17];
260 /* get fixed properties */
261 this->mutex
->lock(this->mutex
);
262 rval
= Tss2_Sys_GetCapability(this->sys_context
, 0, TPM2_CAP_TPM_PROPERTIES
,
263 TPM2_PT_FIXED
, TPM2_MAX_TPM_PROPERTIES
,
264 &more_data
, &cap_data
, 0);
265 this->mutex
->unlock(this->mutex
);
266 if (rval
!= TPM2_RC_SUCCESS
)
268 DBG1(DBG_PTS
, LABEL
"GetCapability failed for TPM2_CAP_TPM_PROPERTIES: 0x%06x",
272 memset(manufacturer
, '\0', sizeof(manufacturer
));
273 memset(vendor_string
, '\0', sizeof(vendor_string
));
275 /* print fixed properties */
276 for (i
= 0; i
< cap_data
.data
.tpmProperties
.count
; i
++)
278 tp
= cap_data
.data
.tpmProperties
.tpmProperty
[i
];
281 case TPM2_PT_REVISION
:
287 case TPM2_PT_MANUFACTURER
:
289 htoun32(manufacturer
, tp
.value
);
291 case TPM2_PT_VENDOR_STRING_1
:
292 case TPM2_PT_VENDOR_STRING_2
:
293 case TPM2_PT_VENDOR_STRING_3
:
294 case TPM2_PT_VENDOR_STRING_4
:
295 offset
= 4 * (tp
.property
- TPM2_PT_VENDOR_STRING_1
);
296 htoun32(vendor_string
+ offset
, tp
.value
);
299 if (tp
.value
& TPMA_MODES_FIPS_140_2
)
301 this->fips_186_4
= fips_140_2
= TRUE
;
311 this->fips_186_4
= lib
->settings
->get_bool(lib
->settings
,
312 "%s.plugins.tpm.fips_186_4", FALSE
, lib
->ns
);
314 DBG2(DBG_PTS
, LABEL
"manufacturer: %s (%s) rev: %05.2f %u %s",
315 manufacturer
, vendor_string
, (float)revision
/100, year
,
316 fips_140_2
? "FIPS 140-2" : (this->fips_186_4
? "FIPS 186-4" : ""));
318 /* determine if TPM uses old event digest format and a different locality */
319 if (streq(manufacturer
, "INTC"))
323 if (revision
== 116 && year
== 2016)
325 this->old_event_digest_format
= TRUE
;
329 /* construct TPM 2.0 version_info object */
330 writer
= bio_writer_create( TPM2_VERSION_INFO_SIZE
);
331 writer
->write_uint16(writer
, TPM2_VERSION_INFO_TAG
);
332 writer
->write_uint8(writer
, TPM2_VERSION_INFO_RESERVED
);
333 writer
->write_uint8(writer
, locality
);
334 writer
->write_uint32(writer
, revision
);
335 writer
->write_uint32(writer
, year
);
336 writer
->write_uint32(writer
, vendor
);
337 this->version_info
= writer
->extract_buf(writer
);
338 writer
->destroy(writer
);
340 /* get supported algorithms */
341 this->mutex
->lock(this->mutex
);
342 rval
= Tss2_Sys_GetCapability(this->sys_context
, 0, TPM2_CAP_ALGS
,
343 0, TPM2_PT_ALGORITHM_SET
, &more_data
, &cap_data
, 0);
344 this->mutex
->unlock(this->mutex
);
345 if (rval
!= TPM2_RC_SUCCESS
)
347 DBG1(DBG_PTS
, LABEL
"GetCapability failed for TPM2_CAP_ALGS: 0x%06x",
352 /* Number of supported algorithms */
353 this->supported_algs_count
= cap_data
.data
.algorithms
.count
;
355 /* store and print supported algorithms */
356 for (i
= 0; i
< this->supported_algs_count
; i
++)
358 alg
= cap_data
.data
.algorithms
.algProperties
[i
].alg
;
359 this->supported_algs
[i
] = alg
;
361 written
= snprintf(pos
, len
, " %N", tpm_alg_id_names
, alg
);
362 if (written
< 0 || written
>= len
)
369 DBG2(DBG_PTS
, LABEL
"algorithms:%s", buf
);
371 /* get supported ECC curves */
372 this->mutex
->lock(this->mutex
);
373 rval
= Tss2_Sys_GetCapability(this->sys_context
, 0, TPM2_CAP_ECC_CURVES
,
374 0, TPM2_PT_LOADED_CURVES
, &more_data
, &cap_data
, 0);
375 this->mutex
->unlock(this->mutex
);
376 if (rval
!= TPM2_RC_SUCCESS
)
378 DBG1(DBG_PTS
, LABEL
"GetCapability failed for TPM2_CAP_ECC_CURVES: 0x%06x",
383 /* reset print buffer */
387 /* print supported ECC curves */
388 for (i
= 0; i
< cap_data
.data
.eccCurves
.count
; i
++)
390 written
= snprintf(pos
, len
, " %N", tpm_ecc_curve_names
,
391 cap_data
.data
.eccCurves
.eccCurves
[i
]);
392 if (written
< 0 || written
>= len
)
399 DBG2(DBG_PTS
, LABEL
"ECC curves:%s", buf
);
401 /* get assigned PCR banks */
402 this->mutex
->lock(this->mutex
);
403 rval
= Tss2_Sys_GetCapability(this->sys_context
, 0, TPM2_CAP_PCRS
,
404 0, MAX_PCR_BANKS
, &more_data
, &cap_data
, 0);
405 this->mutex
->unlock(this->mutex
);
406 if (rval
!= TPM2_RC_SUCCESS
)
408 DBG1(DBG_PTS
, LABEL
"GetCapability failed for TPM2_CAP_PCRS: 0x%06x",
413 /* Number of assigned PCR banks */
414 this->assigned_pcrs_count
= cap_data
.data
.assignedPCR
.count
;
416 /* reset print buffer */
420 /* store and print assigned PCR banks */
421 for (i
= 0; i
< cap_data
.data
.assignedPCR
.count
; i
++)
423 alg
= cap_data
.data
.assignedPCR
.pcrSelections
[i
].hash
;
424 this->assigned_pcrs
[i
] = alg
;
425 written
= snprintf(pos
, len
, " %N", tpm_alg_id_names
, alg
);
426 if (written
< 0 || written
>= len
)
433 DBG2(DBG_PTS
, LABEL
"PCR banks:%s", buf
);
439 * Initialize TSS2 TCTI context
441 static bool initialize_tcti_context(private_tpm_tss_tss2_t
*this)
443 size_t tcti_context_size
;
451 /* determine size of tcti context */
452 rval
= tcti_init(NULL
, &tcti_context_size
, tcti_opts
);
453 if (rval
!= TSS2_RC_SUCCESS
)
455 DBG1(DBG_PTS
, LABEL
"tcti init setup failed: 0x%06x", rval
);
459 /* allocate and initialize memory for tcti context */
460 this->tcti_context
= (TSS2_TCTI_CONTEXT
*)malloc(tcti_context_size
);
461 memset(this->tcti_context
, 0x00, tcti_context_size
);
463 /* initialize tcti context */
464 rval
= tcti_init(this->tcti_context
, &tcti_context_size
, tcti_opts
);
465 if (rval
!= TSS2_RC_SUCCESS
)
467 DBG1(DBG_PTS
, LABEL
"tcti init allocation failed: 0x%06x", rval
);
474 * Initialize TSS2 Sys context
476 static bool initialize_sys_context(private_tpm_tss_tss2_t
*this)
478 uint32_t sys_context_size
;
481 TSS2_ABI_VERSION abi_version
= {
488 /* determine size of sys context */
489 sys_context_size
= Tss2_Sys_GetContextSize(0);
491 /* allocate memory for sys context */
492 this->sys_context
= (TSS2_SYS_CONTEXT
*)malloc(sys_context_size
);
494 /* initialize sys context */
495 rval
= Tss2_Sys_Initialize(this->sys_context
, sys_context_size
,
496 this->tcti_context
, &abi_version
);
497 if (rval
!= TSS2_RC_SUCCESS
)
499 DBG1(DBG_PTS
, LABEL
"could not get sys_context: 0x%06x", rval
);
503 /* get a list of supported algorithms and ECC curves */
504 return get_algs_capability(this);
508 * Finalize TSS context
510 static void finalize_context(private_tpm_tss_tss2_t
*this)
512 if (this->tcti_context
)
514 Tss2_Tcti_Finalize(this->tcti_context
);
515 free(this->tcti_context
);
517 if (this->sys_context
)
519 Tss2_Sys_Finalize(this->sys_context
);
520 free(this->sys_context
);
524 METHOD(tpm_tss_t
, get_version
, tpm_version_t
,
525 private_tpm_tss_tss2_t
*this)
527 return TPM_VERSION_2_0
;
530 METHOD(tpm_tss_t
, get_version_info
, chunk_t
,
531 private_tpm_tss_tss2_t
*this)
533 return this->version_info
;
537 * read the public key portion of a TSS 2.0 key from NVRAM
539 bool read_public(private_tpm_tss_tss2_t
*this, TPMI_DH_OBJECT handle
,
540 TPM2B_PUBLIC
*public)
544 TPM2B_NAME name
= { sizeof(TPM2B_NAME
)-2, };
545 TPM2B_NAME qualified_name
= { sizeof(TPM2B_NAME
)-2, };
546 TSS2L_SYS_AUTH_RESPONSE auth_rsp
;
549 /* read public key for a given object handle from TPM 2.0 NVRAM */
550 this->mutex
->lock(this->mutex
);
551 rval
= Tss2_Sys_ReadPublic(this->sys_context
, handle
, 0, public, &name
,
552 &qualified_name
, &auth_rsp
);
553 this->mutex
->unlock(this->mutex
);
554 if (rval
!= TPM2_RC_SUCCESS
)
556 DBG1(DBG_PTS
, LABEL
"could not read public key from handle 0x%08x: 0x%06x",
563 METHOD(tpm_tss_t
, generate_aik
, bool,
564 private_tpm_tss_tss2_t
*this, chunk_t ca_modulus
, chunk_t
*aik_blob
,
565 chunk_t
*aik_pubkey
, chunk_t
*identity_req
)
570 METHOD(tpm_tss_t
, get_public
, chunk_t
,
571 private_tpm_tss_tss2_t
*this, uint32_t handle
)
573 TPM2B_PUBLIC
public = { 0, };
574 chunk_t aik_pubkey
= chunk_empty
;
576 if (!read_public(this, handle
, &public))
581 /* convert TSS 2.0 public key blot into PKCS#1 format */
582 switch (public.publicArea
.type
)
586 TPM2B_PUBLIC_KEY_RSA
*rsa
;
587 chunk_t aik_exponent
= chunk_from_chars(0x01, 0x00, 0x01);
591 rsa
= &public.publicArea
.unique
.rsa
;
592 aik_modulus
= chunk_create(rsa
->buffer
, rsa
->size
);
593 exponent
= htonl(public.publicArea
.parameters
.rsaDetail
.exponent
);
596 aik_exponent
= chunk_from_thing(exponent
);
599 /* subjectPublicKeyInfo encoding of RSA public key */
600 if (!lib
->encoding
->encode(lib
->encoding
, PUBKEY_SPKI_ASN1_DER
,
601 NULL
, &aik_pubkey
, CRED_PART_RSA_MODULUS
, aik_modulus
,
602 CRED_PART_RSA_PUB_EXP
, aik_exponent
, CRED_PART_END
))
604 DBG1(DBG_PTS
, LABEL
"subjectPublicKeyInfo encoding of public key "
617 /* determine ECC curveID */
618 switch (public.publicArea
.parameters
.eccDetail
.curveID
)
620 case TPM2_ECC_NIST_P192
:
621 curve_oid
= OID_PRIME192V1
;
623 case TPM2_ECC_NIST_P224
:
624 curve_oid
= OID_SECT224R1
;
626 case TPM2_ECC_NIST_P256
:
627 curve_oid
= OID_PRIME256V1
;
629 case TPM2_ECC_NIST_P384
:
630 curve_oid
= OID_SECT384R1
;
632 case TPM2_ECC_NIST_P521
:
633 curve_oid
= OID_SECT521R1
;
636 DBG1(DBG_PTS
, "ECC curve type not supported");
640 ecc
= &public.publicArea
.unique
.ecc
;
642 /* allocate space for bit string */
643 pos
= asn1_build_object(&ecc_point
, ASN1_BIT_STRING
,
644 2 + ecc
->x
.size
+ ecc
->y
.size
);
645 /* bit string length is a multiple of octets */
647 /* uncompressed ECC point format */
649 /* copy x coordinate of ECC point */
650 memcpy(pos
, ecc
->x
.buffer
, ecc
->x
.size
);
652 /* copy y coordinate of ECC point */
653 memcpy(pos
, ecc
->y
.buffer
, ecc
->y
.size
);
655 /* subjectPublicKeyInfo encoding of ECC public key */
656 aik_pubkey
= asn1_wrap(ASN1_SEQUENCE
, "mm",
657 asn1_wrap(ASN1_SEQUENCE
, "mm",
658 asn1_build_known_oid(OID_EC_PUBLICKEY
),
659 asn1_build_known_oid(curve_oid
)),
664 DBG1(DBG_PTS
, LABEL
"unsupported key type");
667 if (public.publicArea
.objectAttributes
& TPMA_OBJECT_SIGN_ENCRYPT
)
671 s
= &public.publicArea
.parameters
.asymDetail
.scheme
;
672 DBG1(DBG_PTS
, "signature algorithm is %N with %N hash",
673 tpm_alg_id_names
, s
->scheme
,
674 tpm_alg_id_names
, s
->details
.anySig
.hashAlg
);
676 if (public.publicArea
.objectAttributes
& TPMA_OBJECT_DECRYPT
)
678 TPMT_SYM_DEF_OBJECT
*s
;
680 s
= &public.publicArea
.parameters
.asymDetail
.symmetric
;
681 DBG1(DBG_PTS
, "encryption algorithm is %N-%N with %u bits",
682 tpm_alg_id_names
, s
->algorithm
,
683 tpm_alg_id_names
, s
->mode
, s
->keyBits
.sym
);
689 METHOD(tpm_tss_t
, supported_signature_schemes
, enumerator_t
*,
690 private_tpm_tss_tss2_t
*this, uint32_t handle
)
692 TPM2B_PUBLIC
public = { 0, };
693 hash_algorithm_t digest
;
694 signature_params_t supported_scheme
;
696 if (!read_public(this, handle
, &public))
698 return enumerator_create_empty();
701 switch (public.publicArea
.type
)
706 TPMT_RSA_SCHEME
*scheme
;
708 rsa
= &public.publicArea
.parameters
.rsaDetail
;
709 scheme
= &rsa
->scheme
;
710 digest
= hash_alg_from_tpm_alg_id(scheme
->details
.anySig
.hashAlg
);
712 switch (scheme
->scheme
)
714 case TPM2_ALG_RSAPSS
:
718 salt_len
= this->fips_186_4
? RSA_PSS_SALT_LEN_DEFAULT
:
719 RSA_PSS_SALT_LEN_MAX
;
720 rsa_pss_params_t pss_params
= {
723 .salt_len
= salt_len
,
725 supported_scheme
= (signature_params_t
){
726 .scheme
= SIGN_RSA_EMSA_PSS
,
727 .params
= &pss_params
,
729 if (!rsa_pss_params_set_salt_len(&pss_params
, rsa
->keyBits
))
731 return enumerator_create_empty();
735 case TPM2_ALG_RSASSA
:
736 supported_scheme
= (signature_params_t
){
737 .scheme
= signature_scheme_from_oid(
738 hasher_signature_algorithm_to_oid(digest
,
743 return enumerator_create_empty();
749 TPMT_ECC_SCHEME
*scheme
;
751 scheme
= &public.publicArea
.parameters
.eccDetail
.scheme
;
752 digest
= hash_alg_from_tpm_alg_id(scheme
->details
.anySig
.hashAlg
);
754 switch (scheme
->scheme
)
757 supported_scheme
= (signature_params_t
){
758 .scheme
= signature_scheme_from_oid(
759 hasher_signature_algorithm_to_oid(digest
,
764 return enumerator_create_empty();
769 DBG1(DBG_PTS
, LABEL
"unsupported key type");
770 return enumerator_create_empty();
772 return enumerator_create_single(signature_params_clone(&supported_scheme
),
773 (void*)signature_params_destroy
);
776 METHOD(tpm_tss_t
, has_pcr_bank
, bool,
777 private_tpm_tss_tss2_t
*this, hash_algorithm_t alg
)
782 alg_id
= hash_alg_to_tpm_alg_id(alg
);
784 for (i
= 0; i
< this->assigned_pcrs_count
; i
++)
786 if (this->assigned_pcrs
[i
] == alg_id
)
796 * Configure a PCR Selection assuming a maximum of 24 registers
798 static bool init_pcr_selection(private_tpm_tss_tss2_t
*this, uint32_t pcrs
,
799 hash_algorithm_t alg
, TPML_PCR_SELECTION
*pcr_sel
)
803 /* check if there is an assigned PCR bank for this hash algorithm */
804 if (!has_pcr_bank(this, alg
))
806 DBG1(DBG_PTS
, LABEL
"%N hash algorithm not supported by any PCR bank",
807 hash_algorithm_short_names
, alg
);
811 /* initialize the PCR Selection structure,*/
813 pcr_sel
->pcrSelections
[0].hash
= hash_alg_to_tpm_alg_id(alg
);
815 pcr_sel
->pcrSelections
[0].sizeofSelect
= 3;
816 pcr_sel
->pcrSelections
[0].pcrSelect
[0] = 0;
817 pcr_sel
->pcrSelections
[0].pcrSelect
[1] = 0;
818 pcr_sel
->pcrSelections
[0].pcrSelect
[2] = 0;
820 /* set the selected PCRs */
821 for (pcr
= 0; pcr
< PLATFORM_PCR
; pcr
++)
823 if (pcrs
& (1 << pcr
))
825 pcr_sel
->pcrSelections
[0].pcrSelect
[pcr
/ 8] |= ( 1 << (pcr
% 8) );
831 METHOD(tpm_tss_t
, read_pcr
, bool,
832 private_tpm_tss_tss2_t
*this, uint32_t pcr_num
, chunk_t
*pcr_value
,
833 hash_algorithm_t alg
)
835 TPML_PCR_SELECTION pcr_selection
;
836 TPML_DIGEST pcr_values
;
838 uint32_t pcr_update_counter
, rval
;
839 uint8_t *pcr_value_ptr
;
840 size_t pcr_value_len
;
842 if (pcr_num
>= PLATFORM_PCR
)
844 DBG1(DBG_PTS
, LABEL
"maximum number of supported PCR is %d",
849 if (!init_pcr_selection(this, (1 << pcr_num
), alg
, &pcr_selection
))
854 /* initialize the PCR Digest structure */
855 memset(&pcr_values
, 0, sizeof(TPML_DIGEST
));
857 /* read the PCR value */
858 this->mutex
->lock(this->mutex
);
859 rval
= Tss2_Sys_PCR_Read(this->sys_context
, 0, &pcr_selection
,
860 &pcr_update_counter
, &pcr_selection
, &pcr_values
, 0);
861 this->mutex
->unlock(this->mutex
);
862 if (rval
!= TPM2_RC_SUCCESS
)
864 DBG1(DBG_PTS
, LABEL
"PCR bank could not be read: 0x%60x", rval
);
867 pcr_value_ptr
= (uint8_t *)pcr_values
.digests
[0].buffer
;
868 pcr_value_len
= (size_t) pcr_values
.digests
[0].size
;
870 *pcr_value
= chunk_clone(chunk_create(pcr_value_ptr
, pcr_value_len
));
875 METHOD(tpm_tss_t
, extend_pcr
, bool,
876 private_tpm_tss_tss2_t
*this, uint32_t pcr_num
, chunk_t
*pcr_value
,
877 chunk_t data
, hash_algorithm_t alg
)
880 TPML_DIGEST_VALUES digest_values
;
881 TSS2L_SYS_AUTH_COMMAND auth_cmd
= { 1, { auth_cmd_empty
} };
882 TSS2L_SYS_AUTH_RESPONSE auth_rsp
;
884 auth_cmd
.auths
[0].sessionHandle
= TPM2_RS_PW
;
886 /* check if there is an assigned PCR bank for this hash algorithm */
887 if (!has_pcr_bank(this, alg
))
889 DBG1(DBG_PTS
, LABEL
"%N hash algorithm not supported by any PCR bank",
890 hash_algorithm_short_names
, alg
);
894 digest_values
.count
= 1;
895 digest_values
.digests
[0].hashAlg
= hash_alg_to_tpm_alg_id(alg
);
900 if (data
.len
!= HASH_SIZE_SHA1
)
904 memcpy(digest_values
.digests
[0].digest
.sha1
, data
.ptr
,
909 if (data
.len
!= HASH_SIZE_SHA256
)
913 memcpy(digest_values
.digests
[0].digest
.sha256
, data
.ptr
,
918 if (data
.len
!= HASH_SIZE_SHA384
)
922 memcpy(digest_values
.digests
[0].digest
.sha384
, data
.ptr
,
927 if (data
.len
!= HASH_SIZE_SHA512
)
931 memcpy(digest_values
.digests
[0].digest
.sha512
, data
.ptr
,
939 this->mutex
->lock(this->mutex
);
940 rval
= Tss2_Sys_PCR_Extend(this->sys_context
, pcr_num
, &auth_cmd
,
941 &digest_values
, &auth_rsp
);
942 this->mutex
->unlock(this->mutex
);
943 if (rval
!= TPM2_RC_SUCCESS
)
945 DBG1(DBG_PTS
, LABEL
"PCR %02u could not be extended: 0x%06x",
950 /* get updated PCR value */
951 return read_pcr(this, pcr_num
, pcr_value
, alg
);
954 METHOD(tpm_tss_t
, quote
, bool,
955 private_tpm_tss_tss2_t
*this, uint32_t aik_handle
, uint32_t pcr_sel
,
956 hash_algorithm_t alg
, chunk_t data
, tpm_quote_mode_t
*quote_mode
,
957 tpm_tss_quote_info_t
**quote_info
, chunk_t
*quote_sig
)
959 chunk_t quoted_chunk
, qualified_signer
, extra_data
, clock_info
,
960 firmware_version
, pcr_select
, pcr_digest
;
961 hash_algorithm_t pcr_digest_alg
;
962 bio_reader_t
*reader
;
965 TPM2B_DATA qualifying_data
;
966 TPML_PCR_SELECTION pcr_selection
;
967 TPM2B_ATTEST quoted
= { sizeof(TPM2B_ATTEST
)-2, };
968 TPMT_SIG_SCHEME scheme
;
970 TPMI_ALG_HASH hash_alg
;
971 TSS2L_SYS_AUTH_COMMAND auth_cmd
= { 1, { auth_cmd_empty
} };
972 TSS2L_SYS_AUTH_RESPONSE auth_rsp
;
974 auth_cmd
.auths
[0].sessionHandle
= TPM2_RS_PW
;
976 qualifying_data
.size
= data
.len
;
977 memcpy(qualifying_data
.buffer
, data
.ptr
, data
.len
);
979 scheme
.scheme
= TPM2_ALG_NULL
;
980 memset(&sig
, 0x00, sizeof(sig
));
983 *quote_mode
= TPM_QUOTE_TPM2
;
985 if (!init_pcr_selection(this, pcr_sel
, alg
, &pcr_selection
))
990 this->mutex
->lock(this->mutex
);
991 rval
= Tss2_Sys_Quote(this->sys_context
, aik_handle
, &auth_cmd
,
992 &qualifying_data
, &scheme
, &pcr_selection
, "ed
,
994 this->mutex
->unlock(this->mutex
);
995 if (rval
!= TPM2_RC_SUCCESS
)
997 DBG1(DBG_PTS
, LABEL
"Tss2_Sys_Quote failed: 0x%06x", rval
);
1000 quoted_chunk
= chunk_create(quoted
.attestationData
, quoted
.size
);
1002 reader
= bio_reader_create(chunk_skip(quoted_chunk
, 6));
1003 if (!reader
->read_data16(reader
, &qualified_signer
) ||
1004 !reader
->read_data16(reader
, &extra_data
) ||
1005 !reader
->read_data (reader
, 17, &clock_info
) ||
1006 !reader
->read_data (reader
, 8, &firmware_version
) ||
1007 !reader
->read_data (reader
, 10, &pcr_select
) ||
1008 !reader
->read_data16(reader
, &pcr_digest
))
1010 DBG1(DBG_PTS
, LABEL
"parsing of quoted struct failed");
1011 reader
->destroy(reader
);
1014 reader
->destroy(reader
);
1016 DBG2(DBG_PTS
, "PCR Composite digest: %B", &pcr_digest
);
1017 DBG2(DBG_PTS
, "TPM Quote Info: %B", "ed_chunk
);
1018 DBG2(DBG_PTS
, "qualifiedSigner: %B", &qualified_signer
);
1019 DBG2(DBG_PTS
, "extraData: %B", &extra_data
);
1020 DBG2(DBG_PTS
, "clockInfo: %B", &clock_info
);
1021 DBG2(DBG_PTS
, "firmwareVersion: %B", &firmware_version
);
1022 DBG2(DBG_PTS
, "pcrSelect: %B", &pcr_select
);
1024 /* extract signature */
1027 case TPM2_ALG_RSASSA
:
1028 case TPM2_ALG_RSAPSS
:
1029 *quote_sig
= chunk_clone(
1031 sig
.signature
.rsassa
.sig
.buffer
,
1032 sig
.signature
.rsassa
.sig
.size
));
1033 hash_alg
= sig
.signature
.rsassa
.hash
;
1035 case TPM2_ALG_ECDSA
:
1036 case TPM2_ALG_ECDAA
:
1038 case TPM2_ALG_ECSCHNORR
:
1039 *quote_sig
= chunk_cat("cc",
1041 sig
.signature
.ecdsa
.signatureR
.buffer
,
1042 sig
.signature
.ecdsa
.signatureR
.size
),
1044 sig
.signature
.ecdsa
.signatureS
.buffer
,
1045 sig
.signature
.ecdsa
.signatureS
.size
));
1046 hash_alg
= sig
.signature
.ecdsa
.hash
;
1049 DBG1(DBG_PTS
, LABEL
"unsupported %N signature algorithm",
1050 tpm_alg_id_names
, sig
.sigAlg
);
1054 DBG2(DBG_PTS
, "PCR digest algorithm is %N", tpm_alg_id_names
, hash_alg
);
1055 pcr_digest_alg
= hash_alg_from_tpm_alg_id(hash_alg
);
1057 DBG2(DBG_PTS
, "TPM Quote Signature: %B", quote_sig
);
1059 /* Create and initialize Quote Info object */
1060 *quote_info
= tpm_tss_quote_info_create(*quote_mode
, pcr_digest_alg
,
1062 (*quote_info
)->set_tpm2_info(*quote_info
, qualified_signer
, clock_info
,
1064 (*quote_info
)->set_version_info(*quote_info
, firmware_version
);
1069 METHOD(tpm_tss_t
, sign
, bool,
1070 private_tpm_tss_tss2_t
*this, uint32_t hierarchy
, uint32_t handle
,
1071 signature_scheme_t scheme
, void *params
, chunk_t data
, chunk_t pin
,
1074 key_type_t key_type
;
1075 hash_algorithm_t hash_alg
;
1076 rsa_pss_params_t
*rsa_pss_params
;
1080 TPM2B_MAX_BUFFER buffer
;
1081 TPM2B_DIGEST hash
= { sizeof(TPM2B_DIGEST
)-2, };
1082 TPMT_TK_HASHCHECK validation
;
1083 TPM2B_PUBLIC
public = { 0, };
1084 TPMT_SIG_SCHEME sig_scheme
;
1086 TPMS_AUTH_COMMAND
*cmd
;
1087 TSS2L_SYS_AUTH_COMMAND auth_cmd
= { 1, { auth_cmd_empty
} };
1088 TSS2L_SYS_AUTH_RESPONSE auth_rsp
;
1090 cmd
= &auth_cmd
.auths
[0];
1091 cmd
->sessionHandle
= TPM2_RS_PW
;
1095 cmd
->hmac
.size
= min(sizeof(cmd
->hmac
)-2, pin
.len
);
1096 memcpy(cmd
->hmac
.buffer
, pin
.ptr
, cmd
->hmac
.size
);
1099 if (scheme
== SIGN_RSA_EMSA_PSS
)
1102 rsa_pss_params
= (rsa_pss_params_t
*)params
;
1103 hash_alg
= rsa_pss_params
->hash
;
1107 key_type
= key_type_from_signature_scheme(scheme
);
1108 hash_alg
= hasher_from_signature_scheme(scheme
, NULL
);
1111 /* Check if hash algorithm is supported by TPM */
1112 alg_id
= hash_alg_to_tpm_alg_id(hash_alg
);
1113 if (!is_supported_alg(this, alg_id
))
1115 DBG1(DBG_PTS
, LABEL
"%N hash algorithm not supported by TPM",
1116 hash_algorithm_short_names
, hash_alg
);
1120 /* Get public key */
1121 if (!read_public(this, handle
, &public))
1126 if (key_type
== KEY_RSA
&& public.publicArea
.type
== TPM2_ALG_RSA
)
1128 if (scheme
== SIGN_RSA_EMSA_PSS
)
1130 sig_scheme
.scheme
= TPM2_ALG_RSAPSS
;
1131 sig_scheme
.details
.rsapss
.hashAlg
= alg_id
;
1135 sig_scheme
.scheme
= TPM2_ALG_RSASSA
;
1136 sig_scheme
.details
.rsassa
.hashAlg
= alg_id
;
1139 else if (key_type
== KEY_ECDSA
&& public.publicArea
.type
== TPM2_ALG_ECC
)
1141 sig_scheme
.scheme
= TPM2_ALG_ECDSA
;
1142 sig_scheme
.details
.ecdsa
.hashAlg
= alg_id
;
1147 DBG1(DBG_PTS
, LABEL
"signature scheme %N not supported by TPM key",
1148 signature_scheme_names
, scheme
);
1152 if (data
.len
<= TPM2_MAX_DIGEST_BUFFER
)
1154 memcpy(buffer
.buffer
, data
.ptr
, data
.len
);
1155 buffer
.size
= data
.len
;
1157 this->mutex
->lock(this->mutex
);
1158 rval
= Tss2_Sys_Hash(this->sys_context
, 0, &buffer
, alg_id
, hierarchy
,
1159 &hash
, &validation
, 0);
1160 this->mutex
->unlock(this->mutex
);
1161 if (rval
!= TPM2_RC_SUCCESS
)
1163 DBG1(DBG_PTS
,LABEL
"Tss2_Sys_Hash failed: 0x%06x", rval
);
1169 TPMI_DH_OBJECT sequence_handle
;
1170 TPM2B_AUTH null_auth
;
1173 this->mutex
->lock(this->mutex
);
1174 rval
= Tss2_Sys_HashSequenceStart(this->sys_context
, 0, &null_auth
,
1175 alg_id
, &sequence_handle
, 0);
1176 if (rval
!= TPM2_RC_SUCCESS
)
1178 DBG1(DBG_PTS
, LABEL
"Tss2_Sys_HashSequenceStart failed: 0x%06x",
1180 this->mutex
->unlock(this->mutex
);
1184 while (data
.len
> 0)
1186 buffer
.size
= min(data
.len
, TPM2_MAX_DIGEST_BUFFER
);
1187 memcpy(buffer
.buffer
, data
.ptr
, buffer
.size
);
1188 data
.ptr
+= buffer
.size
;
1189 data
.len
-= buffer
.size
;
1191 rval
= Tss2_Sys_SequenceUpdate(this->sys_context
, sequence_handle
,
1192 &auth_cmd
, &buffer
, 0);
1193 if (rval
!= TPM2_RC_SUCCESS
)
1195 DBG1(DBG_PTS
, LABEL
"Tss2_Sys_SequenceUpdate failed: 0x%06x",
1197 this->mutex
->unlock(this->mutex
);
1203 rval
= Tss2_Sys_SequenceComplete(this->sys_context
, sequence_handle
,
1204 &auth_cmd
, &buffer
, hierarchy
,
1205 &hash
, &validation
, 0);
1206 this->mutex
->unlock(this->mutex
);
1207 if (rval
!= TPM2_RC_SUCCESS
)
1209 DBG1(DBG_PTS
, LABEL
"Tss2_Sys_SequenceComplete failed: 0x%06x",
1215 this->mutex
->lock(this->mutex
);
1216 rval
= Tss2_Sys_Sign(this->sys_context
, handle
, &auth_cmd
, &hash
,
1217 &sig_scheme
, &validation
, &sig
, &auth_rsp
);
1218 this->mutex
->unlock(this->mutex
);
1219 if (rval
!= TPM2_RC_SUCCESS
)
1221 DBG1(DBG_PTS
, LABEL
"Tss2_Sys_Sign failed: 0x%06x", rval
);
1225 /* extract signature */
1228 case SIGN_RSA_EMSA_PKCS1_SHA1
:
1229 case SIGN_RSA_EMSA_PKCS1_SHA2_256
:
1230 case SIGN_RSA_EMSA_PKCS1_SHA2_384
:
1231 case SIGN_RSA_EMSA_PKCS1_SHA2_512
:
1232 *signature
= chunk_clone(
1234 sig
.signature
.rsassa
.sig
.buffer
,
1235 sig
.signature
.rsassa
.sig
.size
));
1237 case SIGN_RSA_EMSA_PSS
:
1238 *signature
= chunk_clone(
1240 sig
.signature
.rsapss
.sig
.buffer
,
1241 sig
.signature
.rsapss
.sig
.size
));
1243 case SIGN_ECDSA_256
:
1244 case SIGN_ECDSA_384
:
1245 case SIGN_ECDSA_521
:
1246 *signature
= chunk_cat("cc",
1248 sig
.signature
.ecdsa
.signatureR
.buffer
,
1249 sig
.signature
.ecdsa
.signatureR
.size
),
1251 sig
.signature
.ecdsa
.signatureS
.buffer
,
1252 sig
.signature
.ecdsa
.signatureS
.size
));
1254 case SIGN_ECDSA_WITH_SHA256_DER
:
1255 case SIGN_ECDSA_WITH_SHA384_DER
:
1256 case SIGN_ECDSA_WITH_SHA512_DER
:
1257 *signature
= asn1_wrap(ASN1_SEQUENCE
, "mm",
1260 sig
.signature
.ecdsa
.signatureR
.buffer
,
1261 sig
.signature
.ecdsa
.signatureR
.size
)),
1264 sig
.signature
.ecdsa
.signatureS
.buffer
,
1265 sig
.signature
.ecdsa
.signatureS
.size
)));
1268 DBG1(DBG_PTS
, LABEL
"unsupported %N signature scheme",
1269 signature_scheme_names
, scheme
);
1277 * Check if an authenticated session with the TPM 2.0 can be started
1278 * The handle of the RSA Endorsement Key (EK) is required
1280 static void try_session_start(private_tpm_tss_tss2_t
*this)
1282 uint32_t ek_handle
= 0;
1283 chunk_t handle_chunk
;
1286 TPM2B_PUBLIC
public = { 0, };
1288 /* get Endorsement Key (EK) handle from settings */
1289 handle_str
= lib
->settings
->get_str(lib
->settings
,
1290 "%s.plugins.tpm.ek_handle", NULL
, lib
->ns
);
1293 handle_chunk
= chunk_from_hex(chunk_from_str(handle_str
),
1294 (char *)&ek_handle
);
1295 ek_handle
= (handle_chunk
.len
== 4) ? htonl(ek_handle
) : 0;
1297 /* establish protected auth session if ek_handle is set */
1298 if (ek_handle
&& read_public(this, ek_handle
, &public))
1300 this->mutex
->lock(this->mutex
);
1301 this->session
= tpm_tss_tss2_session_create(ek_handle
, &public,
1303 this->mutex
->unlock(this->mutex
);
1308 METHOD(tpm_tss_t
, get_random
, bool,
1309 private_tpm_tss_tss2_t
*this, size_t bytes
, uint8_t *buffer
)
1311 size_t len
, random_len
= sizeof(TPM2B_DIGEST
)-2;
1312 TPM2B_DIGEST random
= { random_len
, };
1313 uint8_t *pos
= buffer
;
1318 try_session_start(this);
1323 bool success
= FALSE
;
1325 len
= min(bytes
, random_len
);
1326 this->mutex
->lock(this->mutex
);
1328 rval
= Tss2_Sys_GetRandom_Prepare(this->sys_context
, len
);
1329 if (rval
!= TSS2_RC_SUCCESS
)
1331 DBG1(DBG_PTS
, "%s Tss2_Sys_GetRandom_Prepare failed: 0x%06x",
1336 if (this->session
&& !this->session
->set_cmd_auths(this->session
))
1341 rval
= Tss2_Sys_Execute(this->sys_context
);
1342 if (rval
!= TSS2_RC_SUCCESS
)
1344 DBG1(DBG_PTS
, LABEL
"Tss2_Sys_Execute failed: 0x%06x", rval
);
1348 if (this->session
&& !this->session
->get_rsp_auths(this->session
))
1353 rval
= Tss2_Sys_GetRandom_Complete(this->sys_context
, &random
);
1354 if (rval
!= TSS2_RC_SUCCESS
)
1356 DBG1(DBG_PTS
, LABEL
"Tss2_Sys_GetRandom_Complete failed: 0x%06x",
1363 this->mutex
->unlock(this->mutex
);
1369 memcpy(pos
, random
.buffer
, random
.size
);
1371 bytes
-= random
.size
;
1377 METHOD(tpm_tss_t
, get_data
, bool,
1378 private_tpm_tss_tss2_t
*this, uint32_t hierarchy
, uint32_t handle
,
1379 chunk_t pin
, chunk_t
*data
)
1381 uint16_t max_data_size
, nv_size
, nv_offset
= 0;
1384 TPMS_CAPABILITY_DATA cap_data
;
1385 TPMI_YES_NO more_data
;
1386 TPM2B_NAME nv_name
= { sizeof(TPM2B_NAME
)-2, };
1387 TPM2B_NV_PUBLIC nv_public
= { 0, };
1388 TPM2B_MAX_NV_BUFFER nv_data
= { TPM2_MAX_NV_BUFFER_SIZE
, };
1389 TPMS_AUTH_COMMAND
*cmd
;
1390 TSS2L_SYS_AUTH_COMMAND auth_cmd
= { 1, { auth_cmd_empty
} };
1391 TSS2L_SYS_AUTH_RESPONSE auth_rsp
;
1393 /* query maximum TPM data transmission size */
1394 this->mutex
->lock(this->mutex
);
1395 rval
= Tss2_Sys_GetCapability(this->sys_context
, 0, TPM2_CAP_TPM_PROPERTIES
,
1396 TPM2_PT_NV_BUFFER_MAX
, 1, &more_data
, &cap_data
, 0);
1397 this->mutex
->unlock(this->mutex
);
1398 if (rval
!= TPM2_RC_SUCCESS
)
1400 DBG1(DBG_PTS
, LABEL
"Tss2_Sys_GetCapability failed for "
1401 "TPM2_CAP_TPM_PROPERTIES: 0x%06x", rval
);
1404 max_data_size
= min(cap_data
.data
.tpmProperties
.tpmProperty
[0].value
,
1405 TPM2_MAX_NV_BUFFER_SIZE
);
1407 /* get size of NV object */
1408 this->mutex
->lock(this->mutex
);
1409 rval
= Tss2_Sys_NV_ReadPublic(this->sys_context
, handle
, 0, &nv_public
,
1411 this->mutex
->unlock(this->mutex
);
1412 if (rval
!= TPM2_RC_SUCCESS
)
1414 DBG1(DBG_PTS
, LABEL
"Tss2_Sys_NV_ReadPublic failed: 0x%06x", rval
);
1417 nv_size
= nv_public
.nvPublic
.dataSize
;
1418 *data
= chunk_alloc(nv_size
);
1420 /* prepare NV read session */
1421 cmd
= &auth_cmd
.auths
[0];
1422 cmd
->sessionHandle
= TPM2_RS_PW
;
1426 cmd
->hmac
.size
= min(sizeof(cmd
->hmac
)-2, pin
.len
);
1427 memcpy(cmd
->hmac
.buffer
, pin
.ptr
, cmd
->hmac
.size
);
1430 /* read NV data a maximum data size block at a time */
1433 this->mutex
->lock(this->mutex
);
1434 rval
= Tss2_Sys_NV_Read(this->sys_context
, hierarchy
, handle
, &auth_cmd
,
1435 min(nv_size
, max_data_size
), nv_offset
, &nv_data
, &auth_rsp
);
1436 this->mutex
->unlock(this->mutex
);
1437 if (rval
!= TPM2_RC_SUCCESS
)
1439 DBG1(DBG_PTS
, LABEL
"Tss2_Sys_NV_Read failed: 0x%06x", rval
);
1443 memcpy(data
->ptr
+ nv_offset
, nv_data
.buffer
, nv_data
.size
);
1444 nv_offset
+= nv_data
.size
;
1445 nv_size
-= nv_data
.size
;
1451 METHOD(tpm_tss_t
, get_event_digest
, bool,
1452 private_tpm_tss_tss2_t
*this, int fd
, hash_algorithm_t alg
, chunk_t
*digest
)
1454 uint8_t digest_buf
[HASH_SIZE_SHA512
];
1455 uint32_t digest_count
;
1456 size_t digest_len
= 0;
1457 hash_algorithm_t hash_alg
;
1460 if (this->old_event_digest_format
)
1462 if (alg
!= HASH_SHA1
)
1466 digest_len
= HASH_SIZE_SHA1
;
1468 *digest
= chunk_alloc(digest_len
);
1470 if (read(fd
, digest
->ptr
, digest_len
) != digest_len
)
1477 if (read(fd
, &digest_count
, 4) != 4)
1481 while (digest_count
--)
1483 if (read(fd
, &alg_id
, 2) != 2)
1487 hash_alg
= hash_alg_from_tpm_alg_id(alg_id
);
1488 digest_len
= hash_len_from_tpm_alg_id(alg_id
);
1490 if (hash_alg
== alg
)
1492 *digest
= chunk_alloc(digest_len
);
1493 if (read(fd
, digest
->ptr
, digest_len
) != digest_len
)
1500 /* read without storing */
1501 if (read(fd
, digest_buf
, digest_len
) != digest_len
)
1512 METHOD(tpm_tss_t
, destroy
, void,
1513 private_tpm_tss_tss2_t
*this)
1515 DESTROY_IF(this->session
);
1516 finalize_context(this);
1517 this->mutex
->destroy(this->mutex
);
1518 free(this->version_info
.ptr
);
1525 tpm_tss_t
*tpm_tss_tss2_create()
1527 private_tpm_tss_tss2_t
*this;
1532 .get_version
= _get_version
,
1533 .get_version_info
= _get_version_info
,
1534 .generate_aik
= _generate_aik
,
1535 .get_public
= _get_public
,
1536 .supported_signature_schemes
= _supported_signature_schemes
,
1537 .has_pcr_bank
= _has_pcr_bank
,
1538 .read_pcr
= _read_pcr
,
1539 .extend_pcr
= _extend_pcr
,
1542 .get_random
= _get_random
,
1543 .get_data
= _get_data
,
1544 .get_event_digest
= _get_event_digest
,
1545 .destroy
= _destroy
,
1547 .mutex
= mutex_create(MUTEX_TYPE_DEFAULT
),
1550 available
= initialize_tcti_context(this);
1553 available
= initialize_sys_context(this);
1555 DBG1(DBG_PTS
, "TPM 2.0 via TSS2 v2 %savailable", available
? "" : "not ");
1563 return &this->public;
1569 bool tpm_tss_tss2_init(void)
1571 TSS2_TCTI_INFO_FUNC infofn
;
1572 const TSS2_TCTI_INFO
*info
;
1573 char tcti_lib_format
[] = "libtss2-tcti-%s.so.0";
1574 char tcti_lib
[BUF_LEN
];
1575 char *tcti_names
[] = { "device", "tabrmd", "mssim" };
1576 char *tcti_options
[] = { "/dev/tpmrm0", "", "" };
1582 /* check for the existence of an in-kernel TPM resource manager */
1583 if (stat(tcti_options
[i
], &st
))
1587 DBG2(DBG_PTS
, LABEL
"\"%s\" in-kernel resource manager is %spresent",
1588 tcti_options
[0], i
? "not " : "");
1590 /* select a dynamic TCTI library (device, tabrmd or mssim) */
1591 tcti_name
= lib
->settings
->get_str(lib
->settings
,
1592 "%s.plugins.tpm.tcti.name", tcti_names
[i
], lib
->ns
);
1593 snprintf(tcti_lib
, BUF_LEN
, tcti_lib_format
, tcti_name
);
1595 for (i
= 0; i
< countof(tcti_names
); i
++)
1597 if (streq(tcti_name
, tcti_names
[i
]))
1605 DBG1(DBG_PTS
, LABEL
"\"%s\" is not a valid TCTI library name", tcti_lib
);
1609 tcti_opts
= lib
->settings
->get_str(lib
->settings
,
1610 "%s.plugins.tpm.tcti.opts", tcti_options
[i
], lib
->ns
);
1612 /* open the selected dynamic TCTI library */
1613 tcti_handle
= dlopen(tcti_lib
, RTLD_LAZY
);
1616 DBG1(DBG_PTS
, LABEL
"could not load \"%s\"", tcti_lib
);
1620 infofn
= (TSS2_TCTI_INFO_FUNC
)dlsym(tcti_handle
, TSS2_TCTI_INFO_SYMBOL
);
1623 DBG1(DBG_PTS
, LABEL
"symbol \"%s\" not found in \"%s\"",
1624 TSS2_TCTI_INFO_SYMBOL
, tcti_lib
);
1625 tpm_tss_tss2_deinit();
1629 DBG2(DBG_PTS
, LABEL
"\"%s\" successfully loaded", tcti_lib
);
1631 tcti_init
= info
->init
;
1639 void tpm_tss_tss2_deinit(void)
1641 dlclose(tcti_handle
);
1647 #else /* TSS_TSS2_V2 */
1652 bool tpm_tss_tss2_init(void)
1660 void tpm_tss_tss2_deinit(void)
1665 #endif /* TSS_TSS2_V2 */