2 * Copyright (C) 2018 Tobias Brunner
3 * Copyright (C) 2018-2020 Andreas Steffen
4 * HSR Hochschule fuer Technik Rapperswil
6 * Copyright (C) 2021 Andreas Steffen, strongSec GmbH
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 #include "tpm_tss_tss2.h"
20 #include "tpm_tss_tss2_names.h"
24 #include "tpm_tss_tss2_session.h"
26 #include <asn1/asn1.h>
28 #include <bio/bio_reader.h>
29 #include <bio/bio_writer.h>
30 #include <threading/mutex.h>
33 #include <sys/types.h>
37 #define LABEL "TPM 2.0 - "
39 #define PLATFORM_PCR 24
40 #define MAX_PCR_BANKS 4
42 typedef struct private_tpm_tss_tss2_t private_tpm_tss_tss2_t
;
45 * Private data of an tpm_tss_tss2_t object.
47 struct private_tpm_tss_tss2_t
{
50 * Public tpm_tss_tss2_t interface.
57 TSS2_TCTI_CONTEXT
*tcti_context
;
62 TSS2_SYS_CONTEXT
*sys_context
;
70 * Number of supported algorithms
72 size_t supported_algs_count
;
75 * List of supported algorithms
77 TPM2_ALG_ID supported_algs
[TPM2_PT_ALGORITHM_SET
];
80 * Number of assigned PCR banks
82 size_t assigned_pcrs_count
;
85 * List of assigned PCR banks
87 TPM2_ALG_ID assigned_pcrs
[MAX_PCR_BANKS
];
90 * Is TPM FIPS 186-4 compliant ?
95 * Does the TPM use the old TCG SHA1-only event digest format
97 bool old_event_digest_format
;
100 * TSS2 session used for protected communication with TPM 2.0
102 tpm_tss_tss2_session_t
*session
;
105 * Mutex controlling access to the TPM 2.0 context
112 * Global TCTI dynamic library handle and init function
114 static void *tcti_handle
;
116 static TSS2_TCTI_INIT_FUNC tcti_init
;
118 static char *tcti_opts
;
123 static const TPMS_AUTH_COMMAND auth_cmd_empty
;
126 * Convert hash algorithm to TPM2_ALG_ID
128 static TPM2_ALG_ID
hash_alg_to_tpm_alg_id(hash_algorithm_t alg
)
133 return TPM2_ALG_SHA1
;
135 return TPM2_ALG_SHA256
;
137 return TPM2_ALG_SHA384
;
139 return TPM2_ALG_SHA512
;
141 return TPM2_ALG_SHA3_256
;
143 return TPM2_ALG_SHA3_384
;
145 return TPM2_ALG_SHA3_512
;
147 return TPM2_ALG_ERROR
;
152 * Convert TPM2_ALG_ID to hash algorithm
154 hash_algorithm_t
hash_alg_from_tpm_alg_id(TPM2_ALG_ID alg
)
160 case TPM2_ALG_SHA256
:
162 case TPM2_ALG_SHA384
:
164 case TPM2_ALG_SHA512
:
166 case TPM2_ALG_SHA3_256
:
167 return HASH_SHA3_256
;
168 case TPM2_ALG_SHA3_384
:
169 return HASH_SHA3_384
;
170 case TPM2_ALG_SHA3_512
:
171 return HASH_SHA3_512
;
178 * Return hash length of TPM2_ALG_ID algorithm
180 size_t hash_len_from_tpm_alg_id(TPM2_ALG_ID alg
)
185 return TPM2_SHA1_DIGEST_SIZE
;
186 case TPM2_ALG_SHA256
:
187 case TPM2_ALG_SHA3_256
:
188 return TPM2_SHA256_DIGEST_SIZE
;
189 case TPM2_ALG_SHA384
:
190 case TPM2_ALG_SHA3_384
:
191 return TPM2_SHA384_DIGEST_SIZE
;
192 case TPM2_ALG_SHA512
:
193 case TPM2_ALG_SHA3_512
:
194 return TPM2_SHA512_DIGEST_SIZE
;
195 case TPM2_ALG_SM3_256
:
196 return TPM2_SM3_256_DIGEST_SIZE
;
203 * Check if an algorithm given by its TPM2_ALG_ID is supported by the TPM
205 static bool is_supported_alg(private_tpm_tss_tss2_t
*this, TPM2_ALG_ID alg_id
)
209 if (alg_id
== TPM2_ALG_ERROR
)
214 for (i
= 0; i
< this->supported_algs_count
; i
++)
216 if (this->supported_algs
[i
] == alg_id
)
226 * Get the TPM version_info and a list of supported algorithms
229 * 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
231 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
232 * | TPM 2.0 Version_Info Tag | Reserved | Locality |
233 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
235 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
237 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
239 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
241 #define TPM2_VERSION_INFO_TAG 0x0200
242 #define TPM2_VERSION_INFO_RESERVED 0x00
243 #define TPM2_VERSION_INFO_SIZE 16
244 #define TPM2_DEFAULT_LOCALITY 3
246 static bool get_algs_capability(private_tpm_tss_tss2_t
*this)
248 TPMS_CAPABILITY_DATA cap_data
;
249 TPMS_TAGGED_PROPERTY tp
;
250 TPMI_YES_NO more_data
;
252 bio_writer_t
*writer
;
253 bool fips_140_2
= FALSE
;
254 uint32_t rval
, i
, offset
, revision
= 0, year
= 0, vendor
= 0;
255 uint8_t locality
= TPM2_DEFAULT_LOCALITY
;
256 size_t len
= BUF_LEN
;
257 char buf
[BUF_LEN
], manufacturer
[5], vendor_string
[17];
261 /* get fixed properties */
262 this->mutex
->lock(this->mutex
);
263 rval
= Tss2_Sys_GetCapability(this->sys_context
, 0, TPM2_CAP_TPM_PROPERTIES
,
264 TPM2_PT_FIXED
, TPM2_MAX_TPM_PROPERTIES
,
265 &more_data
, &cap_data
, 0);
266 this->mutex
->unlock(this->mutex
);
267 if (rval
!= TPM2_RC_SUCCESS
)
269 DBG1(DBG_PTS
, LABEL
"GetCapability failed for TPM2_CAP_TPM_PROPERTIES: 0x%06x",
273 memset(manufacturer
, '\0', sizeof(manufacturer
));
274 memset(vendor_string
, '\0', sizeof(vendor_string
));
276 /* print fixed properties */
277 for (i
= 0; i
< cap_data
.data
.tpmProperties
.count
; i
++)
279 tp
= cap_data
.data
.tpmProperties
.tpmProperty
[i
];
282 case TPM2_PT_REVISION
:
288 case TPM2_PT_MANUFACTURER
:
290 htoun32(manufacturer
, tp
.value
);
292 case TPM2_PT_VENDOR_STRING_1
:
293 case TPM2_PT_VENDOR_STRING_2
:
294 case TPM2_PT_VENDOR_STRING_3
:
295 case TPM2_PT_VENDOR_STRING_4
:
296 offset
= 4 * (tp
.property
- TPM2_PT_VENDOR_STRING_1
);
297 htoun32(vendor_string
+ offset
, tp
.value
);
300 if (tp
.value
& TPMA_MODES_FIPS_140_2
)
302 this->fips_186_4
= fips_140_2
= TRUE
;
312 this->fips_186_4
= lib
->settings
->get_bool(lib
->settings
,
313 "%s.plugins.tpm.fips_186_4", FALSE
, lib
->ns
);
315 DBG2(DBG_PTS
, LABEL
"manufacturer: %s (%s) rev: %05.2f %u %s",
316 manufacturer
, vendor_string
, (float)revision
/100, year
,
317 fips_140_2
? "FIPS 140-2" : (this->fips_186_4
? "FIPS 186-4" : ""));
319 /* determine if TPM uses old event digest format and a different locality */
320 if (streq(manufacturer
, "INTC"))
324 if (revision
== 116 && year
== 2016)
326 this->old_event_digest_format
= TRUE
;
330 /* construct TPM 2.0 version_info object */
331 writer
= bio_writer_create( TPM2_VERSION_INFO_SIZE
);
332 writer
->write_uint16(writer
, TPM2_VERSION_INFO_TAG
);
333 writer
->write_uint8(writer
, TPM2_VERSION_INFO_RESERVED
);
334 writer
->write_uint8(writer
, locality
);
335 writer
->write_uint32(writer
, revision
);
336 writer
->write_uint32(writer
, year
);
337 writer
->write_uint32(writer
, vendor
);
338 this->version_info
= writer
->extract_buf(writer
);
339 writer
->destroy(writer
);
341 /* get supported algorithms */
342 this->mutex
->lock(this->mutex
);
343 rval
= Tss2_Sys_GetCapability(this->sys_context
, 0, TPM2_CAP_ALGS
,
344 0, TPM2_PT_ALGORITHM_SET
, &more_data
, &cap_data
, 0);
345 this->mutex
->unlock(this->mutex
);
346 if (rval
!= TPM2_RC_SUCCESS
)
348 DBG1(DBG_PTS
, LABEL
"GetCapability failed for TPM2_CAP_ALGS: 0x%06x",
353 /* Number of supported algorithms */
354 this->supported_algs_count
= cap_data
.data
.algorithms
.count
;
356 /* store and print supported algorithms */
357 for (i
= 0; i
< this->supported_algs_count
; i
++)
359 alg
= cap_data
.data
.algorithms
.algProperties
[i
].alg
;
360 this->supported_algs
[i
] = alg
;
362 written
= snprintf(pos
, len
, " %N", tpm_alg_id_names
, alg
);
363 if (written
< 0 || written
>= len
)
370 DBG2(DBG_PTS
, LABEL
"algorithms:%s", buf
);
372 /* get supported ECC curves */
373 this->mutex
->lock(this->mutex
);
374 rval
= Tss2_Sys_GetCapability(this->sys_context
, 0, TPM2_CAP_ECC_CURVES
,
375 0, TPM2_PT_LOADED_CURVES
, &more_data
, &cap_data
, 0);
376 this->mutex
->unlock(this->mutex
);
377 if (rval
!= TPM2_RC_SUCCESS
)
379 DBG1(DBG_PTS
, LABEL
"GetCapability failed for TPM2_CAP_ECC_CURVES: 0x%06x",
384 /* reset print buffer */
388 /* print supported ECC curves */
389 for (i
= 0; i
< cap_data
.data
.eccCurves
.count
; i
++)
391 written
= snprintf(pos
, len
, " %N", tpm_ecc_curve_names
,
392 cap_data
.data
.eccCurves
.eccCurves
[i
]);
393 if (written
< 0 || written
>= len
)
400 DBG2(DBG_PTS
, LABEL
"ECC curves:%s", buf
);
402 /* get assigned PCR banks */
403 this->mutex
->lock(this->mutex
);
404 rval
= Tss2_Sys_GetCapability(this->sys_context
, 0, TPM2_CAP_PCRS
,
405 0, MAX_PCR_BANKS
, &more_data
, &cap_data
, 0);
406 this->mutex
->unlock(this->mutex
);
407 if (rval
!= TPM2_RC_SUCCESS
)
409 DBG1(DBG_PTS
, LABEL
"GetCapability failed for TPM2_CAP_PCRS: 0x%06x",
414 /* Number of assigned PCR banks */
415 this->assigned_pcrs_count
= cap_data
.data
.assignedPCR
.count
;
417 /* reset print buffer */
421 /* store and print assigned PCR banks */
422 for (i
= 0; i
< cap_data
.data
.assignedPCR
.count
; i
++)
424 alg
= cap_data
.data
.assignedPCR
.pcrSelections
[i
].hash
;
425 this->assigned_pcrs
[i
] = alg
;
426 written
= snprintf(pos
, len
, " %N", tpm_alg_id_names
, alg
);
427 if (written
< 0 || written
>= len
)
434 DBG2(DBG_PTS
, LABEL
"PCR banks:%s", buf
);
440 * Initialize TSS2 TCTI context
442 static bool initialize_tcti_context(private_tpm_tss_tss2_t
*this)
444 size_t tcti_context_size
;
452 /* determine size of tcti context */
453 rval
= tcti_init(NULL
, &tcti_context_size
, tcti_opts
);
454 if (rval
!= TSS2_RC_SUCCESS
)
456 DBG1(DBG_PTS
, LABEL
"tcti init setup failed: 0x%06x", rval
);
460 /* allocate and initialize memory for tcti context */
461 this->tcti_context
= (TSS2_TCTI_CONTEXT
*)malloc(tcti_context_size
);
462 memset(this->tcti_context
, 0x00, tcti_context_size
);
464 /* initialize tcti context */
465 rval
= tcti_init(this->tcti_context
, &tcti_context_size
, tcti_opts
);
466 if (rval
!= TSS2_RC_SUCCESS
)
468 DBG1(DBG_PTS
, LABEL
"tcti init allocation failed: 0x%06x", rval
);
475 * Initialize TSS2 Sys context
477 static bool initialize_sys_context(private_tpm_tss_tss2_t
*this)
479 uint32_t sys_context_size
;
482 TSS2_ABI_VERSION abi_version
= {
489 /* determine size of sys context */
490 sys_context_size
= Tss2_Sys_GetContextSize(0);
492 /* allocate memory for sys context */
493 this->sys_context
= (TSS2_SYS_CONTEXT
*)malloc(sys_context_size
);
495 /* initialize sys context */
496 rval
= Tss2_Sys_Initialize(this->sys_context
, sys_context_size
,
497 this->tcti_context
, &abi_version
);
498 if (rval
!= TSS2_RC_SUCCESS
)
500 DBG1(DBG_PTS
, LABEL
"could not get sys_context: 0x%06x", rval
);
504 /* get a list of supported algorithms and ECC curves */
505 return get_algs_capability(this);
509 * Finalize TSS context
511 static void finalize_context(private_tpm_tss_tss2_t
*this)
513 if (this->tcti_context
)
515 Tss2_Tcti_Finalize(this->tcti_context
);
516 free(this->tcti_context
);
518 if (this->sys_context
)
520 Tss2_Sys_Finalize(this->sys_context
);
521 free(this->sys_context
);
525 METHOD(tpm_tss_t
, get_version
, tpm_version_t
,
526 private_tpm_tss_tss2_t
*this)
528 return TPM_VERSION_2_0
;
531 METHOD(tpm_tss_t
, get_version_info
, chunk_t
,
532 private_tpm_tss_tss2_t
*this)
534 return this->version_info
;
538 * read the public key portion of a TSS 2.0 key from NVRAM
540 bool read_public(private_tpm_tss_tss2_t
*this, TPMI_DH_OBJECT handle
,
541 TPM2B_PUBLIC
*public)
545 TPM2B_NAME name
= { sizeof(TPM2B_NAME
)-2, };
546 TPM2B_NAME qualified_name
= { sizeof(TPM2B_NAME
)-2, };
547 TSS2L_SYS_AUTH_RESPONSE auth_rsp
;
550 /* read public key for a given object handle from TPM 2.0 NVRAM */
551 this->mutex
->lock(this->mutex
);
552 rval
= Tss2_Sys_ReadPublic(this->sys_context
, handle
, 0, public, &name
,
553 &qualified_name
, &auth_rsp
);
554 this->mutex
->unlock(this->mutex
);
555 if (rval
!= TPM2_RC_SUCCESS
)
557 DBG1(DBG_PTS
, LABEL
"could not read public key from handle 0x%08x: 0x%06x",
564 METHOD(tpm_tss_t
, generate_aik
, bool,
565 private_tpm_tss_tss2_t
*this, chunk_t ca_modulus
, chunk_t
*aik_blob
,
566 chunk_t
*aik_pubkey
, chunk_t
*identity_req
)
571 METHOD(tpm_tss_t
, get_public
, chunk_t
,
572 private_tpm_tss_tss2_t
*this, uint32_t handle
)
574 TPM2B_PUBLIC
public = { 0, };
575 chunk_t aik_pubkey
= chunk_empty
;
577 if (!read_public(this, handle
, &public))
582 /* convert TSS 2.0 public key blot into PKCS#1 format */
583 switch (public.publicArea
.type
)
587 TPM2B_PUBLIC_KEY_RSA
*rsa
;
588 chunk_t aik_exponent
= chunk_from_chars(0x01, 0x00, 0x01);
592 rsa
= &public.publicArea
.unique
.rsa
;
593 aik_modulus
= chunk_create(rsa
->buffer
, rsa
->size
);
594 exponent
= htonl(public.publicArea
.parameters
.rsaDetail
.exponent
);
597 aik_exponent
= chunk_from_thing(exponent
);
600 /* subjectPublicKeyInfo encoding of RSA public key */
601 if (!lib
->encoding
->encode(lib
->encoding
, PUBKEY_SPKI_ASN1_DER
,
602 NULL
, &aik_pubkey
, CRED_PART_RSA_MODULUS
, aik_modulus
,
603 CRED_PART_RSA_PUB_EXP
, aik_exponent
, CRED_PART_END
))
605 DBG1(DBG_PTS
, LABEL
"subjectPublicKeyInfo encoding of public key "
618 /* determine ECC curveID */
619 switch (public.publicArea
.parameters
.eccDetail
.curveID
)
621 case TPM2_ECC_NIST_P192
:
622 curve_oid
= OID_PRIME192V1
;
624 case TPM2_ECC_NIST_P224
:
625 curve_oid
= OID_SECT224R1
;
627 case TPM2_ECC_NIST_P256
:
628 curve_oid
= OID_PRIME256V1
;
630 case TPM2_ECC_NIST_P384
:
631 curve_oid
= OID_SECT384R1
;
633 case TPM2_ECC_NIST_P521
:
634 curve_oid
= OID_SECT521R1
;
637 DBG1(DBG_PTS
, "ECC curve type not supported");
641 ecc
= &public.publicArea
.unique
.ecc
;
643 /* allocate space for bit string */
644 pos
= asn1_build_object(&ecc_point
, ASN1_BIT_STRING
,
645 2 + ecc
->x
.size
+ ecc
->y
.size
);
646 /* bit string length is a multiple of octets */
648 /* uncompressed ECC point format */
650 /* copy x coordinate of ECC point */
651 memcpy(pos
, ecc
->x
.buffer
, ecc
->x
.size
);
653 /* copy y coordinate of ECC point */
654 memcpy(pos
, ecc
->y
.buffer
, ecc
->y
.size
);
656 /* subjectPublicKeyInfo encoding of ECC public key */
657 aik_pubkey
= asn1_wrap(ASN1_SEQUENCE
, "mm",
658 asn1_wrap(ASN1_SEQUENCE
, "mm",
659 asn1_build_known_oid(OID_EC_PUBLICKEY
),
660 asn1_build_known_oid(curve_oid
)),
665 DBG1(DBG_PTS
, LABEL
"unsupported key type");
668 if (public.publicArea
.objectAttributes
& TPMA_OBJECT_SIGN_ENCRYPT
)
672 s
= &public.publicArea
.parameters
.asymDetail
.scheme
;
673 DBG1(DBG_PTS
, "signature algorithm is %N with %N hash",
674 tpm_alg_id_names
, s
->scheme
,
675 tpm_alg_id_names
, s
->details
.anySig
.hashAlg
);
677 if (public.publicArea
.objectAttributes
& TPMA_OBJECT_DECRYPT
)
679 TPMT_SYM_DEF_OBJECT
*s
;
681 s
= &public.publicArea
.parameters
.asymDetail
.symmetric
;
682 DBG1(DBG_PTS
, "encryption algorithm is %N-%N with %u bits",
683 tpm_alg_id_names
, s
->algorithm
,
684 tpm_alg_id_names
, s
->mode
, s
->keyBits
.sym
);
690 METHOD(tpm_tss_t
, supported_signature_schemes
, enumerator_t
*,
691 private_tpm_tss_tss2_t
*this, uint32_t handle
)
693 TPM2B_PUBLIC
public = { 0, };
694 hash_algorithm_t digest
;
695 signature_params_t supported_scheme
;
697 if (!read_public(this, handle
, &public))
699 return enumerator_create_empty();
702 switch (public.publicArea
.type
)
707 TPMT_RSA_SCHEME
*scheme
;
709 rsa
= &public.publicArea
.parameters
.rsaDetail
;
710 scheme
= &rsa
->scheme
;
711 digest
= hash_alg_from_tpm_alg_id(scheme
->details
.anySig
.hashAlg
);
713 switch (scheme
->scheme
)
715 case TPM2_ALG_RSAPSS
:
719 salt_len
= this->fips_186_4
? RSA_PSS_SALT_LEN_DEFAULT
:
720 RSA_PSS_SALT_LEN_MAX
;
721 rsa_pss_params_t pss_params
= {
724 .salt_len
= salt_len
,
726 supported_scheme
= (signature_params_t
){
727 .scheme
= SIGN_RSA_EMSA_PSS
,
728 .params
= &pss_params
,
730 if (!rsa_pss_params_set_salt_len(&pss_params
, rsa
->keyBits
))
732 return enumerator_create_empty();
736 case TPM2_ALG_RSASSA
:
737 supported_scheme
= (signature_params_t
){
738 .scheme
= signature_scheme_from_oid(
739 hasher_signature_algorithm_to_oid(digest
,
744 return enumerator_create_empty();
750 TPMT_ECC_SCHEME
*scheme
;
752 scheme
= &public.publicArea
.parameters
.eccDetail
.scheme
;
753 digest
= hash_alg_from_tpm_alg_id(scheme
->details
.anySig
.hashAlg
);
755 switch (scheme
->scheme
)
758 supported_scheme
= (signature_params_t
){
759 .scheme
= signature_scheme_from_oid(
760 hasher_signature_algorithm_to_oid(digest
,
765 return enumerator_create_empty();
770 DBG1(DBG_PTS
, LABEL
"unsupported key type");
771 return enumerator_create_empty();
773 return enumerator_create_single(signature_params_clone(&supported_scheme
),
774 (void*)signature_params_destroy
);
777 METHOD(tpm_tss_t
, has_pcr_bank
, bool,
778 private_tpm_tss_tss2_t
*this, hash_algorithm_t alg
)
783 alg_id
= hash_alg_to_tpm_alg_id(alg
);
785 for (i
= 0; i
< this->assigned_pcrs_count
; i
++)
787 if (this->assigned_pcrs
[i
] == alg_id
)
797 * Configure a PCR Selection assuming a maximum of 24 registers
799 static bool init_pcr_selection(private_tpm_tss_tss2_t
*this, uint32_t pcrs
,
800 hash_algorithm_t alg
, TPML_PCR_SELECTION
*pcr_sel
)
804 /* check if there is an assigned PCR bank for this hash algorithm */
805 if (!has_pcr_bank(this, alg
))
807 DBG1(DBG_PTS
, LABEL
"%N hash algorithm not supported by any PCR bank",
808 hash_algorithm_short_names
, alg
);
812 /* initialize the PCR Selection structure,*/
814 pcr_sel
->pcrSelections
[0].hash
= hash_alg_to_tpm_alg_id(alg
);
816 pcr_sel
->pcrSelections
[0].sizeofSelect
= 3;
817 pcr_sel
->pcrSelections
[0].pcrSelect
[0] = 0;
818 pcr_sel
->pcrSelections
[0].pcrSelect
[1] = 0;
819 pcr_sel
->pcrSelections
[0].pcrSelect
[2] = 0;
821 /* set the selected PCRs */
822 for (pcr
= 0; pcr
< PLATFORM_PCR
; pcr
++)
824 if (pcrs
& (1 << pcr
))
826 pcr_sel
->pcrSelections
[0].pcrSelect
[pcr
/ 8] |= ( 1 << (pcr
% 8) );
832 METHOD(tpm_tss_t
, read_pcr
, bool,
833 private_tpm_tss_tss2_t
*this, uint32_t pcr_num
, chunk_t
*pcr_value
,
834 hash_algorithm_t alg
)
836 TPML_PCR_SELECTION pcr_selection
;
837 TPML_DIGEST pcr_values
;
839 uint32_t pcr_update_counter
, rval
;
840 uint8_t *pcr_value_ptr
;
841 size_t pcr_value_len
;
843 if (pcr_num
>= PLATFORM_PCR
)
845 DBG1(DBG_PTS
, LABEL
"maximum number of supported PCR is %d",
850 if (!init_pcr_selection(this, (1 << pcr_num
), alg
, &pcr_selection
))
855 /* initialize the PCR Digest structure */
856 memset(&pcr_values
, 0, sizeof(TPML_DIGEST
));
858 /* read the PCR value */
859 this->mutex
->lock(this->mutex
);
860 rval
= Tss2_Sys_PCR_Read(this->sys_context
, 0, &pcr_selection
,
861 &pcr_update_counter
, &pcr_selection
, &pcr_values
, 0);
862 this->mutex
->unlock(this->mutex
);
863 if (rval
!= TPM2_RC_SUCCESS
)
865 DBG1(DBG_PTS
, LABEL
"PCR bank could not be read: 0x%60x", rval
);
868 pcr_value_ptr
= (uint8_t *)pcr_values
.digests
[0].buffer
;
869 pcr_value_len
= (size_t) pcr_values
.digests
[0].size
;
871 *pcr_value
= chunk_clone(chunk_create(pcr_value_ptr
, pcr_value_len
));
876 METHOD(tpm_tss_t
, extend_pcr
, bool,
877 private_tpm_tss_tss2_t
*this, uint32_t pcr_num
, chunk_t
*pcr_value
,
878 chunk_t data
, hash_algorithm_t alg
)
881 TPML_DIGEST_VALUES digest_values
;
882 TSS2L_SYS_AUTH_COMMAND auth_cmd
= { 1, { auth_cmd_empty
} };
883 TSS2L_SYS_AUTH_RESPONSE auth_rsp
;
885 auth_cmd
.auths
[0].sessionHandle
= TPM2_RS_PW
;
887 /* check if there is an assigned PCR bank for this hash algorithm */
888 if (!has_pcr_bank(this, alg
))
890 DBG1(DBG_PTS
, LABEL
"%N hash algorithm not supported by any PCR bank",
891 hash_algorithm_short_names
, alg
);
895 digest_values
.count
= 1;
896 digest_values
.digests
[0].hashAlg
= hash_alg_to_tpm_alg_id(alg
);
901 if (data
.len
!= HASH_SIZE_SHA1
)
905 memcpy(digest_values
.digests
[0].digest
.sha1
, data
.ptr
,
910 if (data
.len
!= HASH_SIZE_SHA256
)
914 memcpy(digest_values
.digests
[0].digest
.sha256
, data
.ptr
,
919 if (data
.len
!= HASH_SIZE_SHA384
)
923 memcpy(digest_values
.digests
[0].digest
.sha384
, data
.ptr
,
928 if (data
.len
!= HASH_SIZE_SHA512
)
932 memcpy(digest_values
.digests
[0].digest
.sha512
, data
.ptr
,
940 this->mutex
->lock(this->mutex
);
941 rval
= Tss2_Sys_PCR_Extend(this->sys_context
, pcr_num
, &auth_cmd
,
942 &digest_values
, &auth_rsp
);
943 this->mutex
->unlock(this->mutex
);
944 if (rval
!= TPM2_RC_SUCCESS
)
946 DBG1(DBG_PTS
, LABEL
"PCR %02u could not be extended: 0x%06x",
951 /* get updated PCR value */
952 return read_pcr(this, pcr_num
, pcr_value
, alg
);
955 METHOD(tpm_tss_t
, quote
, bool,
956 private_tpm_tss_tss2_t
*this, uint32_t aik_handle
, uint32_t pcr_sel
,
957 hash_algorithm_t alg
, chunk_t data
, tpm_quote_mode_t
*quote_mode
,
958 tpm_tss_quote_info_t
**quote_info
, chunk_t
*quote_sig
)
960 chunk_t quoted_chunk
, qualified_signer
, extra_data
, clock_info
,
961 firmware_version
, pcr_select
, pcr_digest
;
962 hash_algorithm_t pcr_digest_alg
;
963 bio_reader_t
*reader
;
966 TPM2B_DATA qualifying_data
;
967 TPML_PCR_SELECTION pcr_selection
;
968 TPM2B_ATTEST quoted
= { sizeof(TPM2B_ATTEST
)-2, };
969 TPMT_SIG_SCHEME scheme
;
971 TPMI_ALG_HASH hash_alg
;
972 TSS2L_SYS_AUTH_COMMAND auth_cmd
= { 1, { auth_cmd_empty
} };
973 TSS2L_SYS_AUTH_RESPONSE auth_rsp
;
975 auth_cmd
.auths
[0].sessionHandle
= TPM2_RS_PW
;
977 qualifying_data
.size
= data
.len
;
978 memcpy(qualifying_data
.buffer
, data
.ptr
, data
.len
);
980 scheme
.scheme
= TPM2_ALG_NULL
;
981 memset(&sig
, 0x00, sizeof(sig
));
984 *quote_mode
= TPM_QUOTE_TPM2
;
986 if (!init_pcr_selection(this, pcr_sel
, alg
, &pcr_selection
))
991 this->mutex
->lock(this->mutex
);
992 rval
= Tss2_Sys_Quote(this->sys_context
, aik_handle
, &auth_cmd
,
993 &qualifying_data
, &scheme
, &pcr_selection
, "ed
,
995 this->mutex
->unlock(this->mutex
);
996 if (rval
!= TPM2_RC_SUCCESS
)
998 DBG1(DBG_PTS
, LABEL
"Tss2_Sys_Quote failed: 0x%06x", rval
);
1001 quoted_chunk
= chunk_create(quoted
.attestationData
, quoted
.size
);
1003 reader
= bio_reader_create(chunk_skip(quoted_chunk
, 6));
1004 if (!reader
->read_data16(reader
, &qualified_signer
) ||
1005 !reader
->read_data16(reader
, &extra_data
) ||
1006 !reader
->read_data (reader
, 17, &clock_info
) ||
1007 !reader
->read_data (reader
, 8, &firmware_version
) ||
1008 !reader
->read_data (reader
, 10, &pcr_select
) ||
1009 !reader
->read_data16(reader
, &pcr_digest
))
1011 DBG1(DBG_PTS
, LABEL
"parsing of quoted struct failed");
1012 reader
->destroy(reader
);
1015 reader
->destroy(reader
);
1017 DBG2(DBG_PTS
, "PCR Composite digest: %B", &pcr_digest
);
1018 DBG2(DBG_PTS
, "TPM Quote Info: %B", "ed_chunk
);
1019 DBG2(DBG_PTS
, "qualifiedSigner: %B", &qualified_signer
);
1020 DBG2(DBG_PTS
, "extraData: %B", &extra_data
);
1021 DBG2(DBG_PTS
, "clockInfo: %B", &clock_info
);
1022 DBG2(DBG_PTS
, "firmwareVersion: %B", &firmware_version
);
1023 DBG2(DBG_PTS
, "pcrSelect: %B", &pcr_select
);
1025 /* extract signature */
1028 case TPM2_ALG_RSASSA
:
1029 case TPM2_ALG_RSAPSS
:
1030 *quote_sig
= chunk_clone(
1032 sig
.signature
.rsassa
.sig
.buffer
,
1033 sig
.signature
.rsassa
.sig
.size
));
1034 hash_alg
= sig
.signature
.rsassa
.hash
;
1036 case TPM2_ALG_ECDSA
:
1037 case TPM2_ALG_ECDAA
:
1039 case TPM2_ALG_ECSCHNORR
:
1040 *quote_sig
= chunk_cat("cc",
1042 sig
.signature
.ecdsa
.signatureR
.buffer
,
1043 sig
.signature
.ecdsa
.signatureR
.size
),
1045 sig
.signature
.ecdsa
.signatureS
.buffer
,
1046 sig
.signature
.ecdsa
.signatureS
.size
));
1047 hash_alg
= sig
.signature
.ecdsa
.hash
;
1050 DBG1(DBG_PTS
, LABEL
"unsupported %N signature algorithm",
1051 tpm_alg_id_names
, sig
.sigAlg
);
1055 DBG2(DBG_PTS
, "PCR digest algorithm is %N", tpm_alg_id_names
, hash_alg
);
1056 pcr_digest_alg
= hash_alg_from_tpm_alg_id(hash_alg
);
1058 DBG2(DBG_PTS
, "TPM Quote Signature: %B", quote_sig
);
1060 /* Create and initialize Quote Info object */
1061 *quote_info
= tpm_tss_quote_info_create(*quote_mode
, pcr_digest_alg
,
1063 (*quote_info
)->set_tpm2_info(*quote_info
, qualified_signer
, clock_info
,
1065 (*quote_info
)->set_version_info(*quote_info
, firmware_version
);
1070 METHOD(tpm_tss_t
, sign
, bool,
1071 private_tpm_tss_tss2_t
*this, uint32_t hierarchy
, uint32_t handle
,
1072 signature_scheme_t scheme
, void *params
, chunk_t data
, chunk_t pin
,
1075 key_type_t key_type
;
1076 hash_algorithm_t hash_alg
;
1077 rsa_pss_params_t
*rsa_pss_params
;
1081 TPM2B_MAX_BUFFER buffer
;
1082 TPM2B_DIGEST hash
= { sizeof(TPM2B_DIGEST
)-2, };
1083 TPMT_TK_HASHCHECK validation
;
1084 TPM2B_PUBLIC
public = { 0, };
1085 TPMT_SIG_SCHEME sig_scheme
;
1087 TPMS_AUTH_COMMAND
*cmd
;
1088 TSS2L_SYS_AUTH_COMMAND auth_cmd
= { 1, { auth_cmd_empty
} };
1089 TSS2L_SYS_AUTH_RESPONSE auth_rsp
;
1091 cmd
= &auth_cmd
.auths
[0];
1092 cmd
->sessionHandle
= TPM2_RS_PW
;
1096 cmd
->hmac
.size
= min(sizeof(cmd
->hmac
)-2, pin
.len
);
1097 memcpy(cmd
->hmac
.buffer
, pin
.ptr
, cmd
->hmac
.size
);
1100 if (scheme
== SIGN_RSA_EMSA_PSS
)
1103 rsa_pss_params
= (rsa_pss_params_t
*)params
;
1104 hash_alg
= rsa_pss_params
->hash
;
1108 key_type
= key_type_from_signature_scheme(scheme
);
1109 hash_alg
= hasher_from_signature_scheme(scheme
, NULL
);
1112 /* Check if hash algorithm is supported by TPM */
1113 alg_id
= hash_alg_to_tpm_alg_id(hash_alg
);
1114 if (!is_supported_alg(this, alg_id
))
1116 DBG1(DBG_PTS
, LABEL
"%N hash algorithm not supported by TPM",
1117 hash_algorithm_short_names
, hash_alg
);
1121 /* Get public key */
1122 if (!read_public(this, handle
, &public))
1127 if (key_type
== KEY_RSA
&& public.publicArea
.type
== TPM2_ALG_RSA
)
1129 if (scheme
== SIGN_RSA_EMSA_PSS
)
1131 sig_scheme
.scheme
= TPM2_ALG_RSAPSS
;
1132 sig_scheme
.details
.rsapss
.hashAlg
= alg_id
;
1136 sig_scheme
.scheme
= TPM2_ALG_RSASSA
;
1137 sig_scheme
.details
.rsassa
.hashAlg
= alg_id
;
1140 else if (key_type
== KEY_ECDSA
&& public.publicArea
.type
== TPM2_ALG_ECC
)
1142 sig_scheme
.scheme
= TPM2_ALG_ECDSA
;
1143 sig_scheme
.details
.ecdsa
.hashAlg
= alg_id
;
1148 DBG1(DBG_PTS
, LABEL
"signature scheme %N not supported by TPM key",
1149 signature_scheme_names
, scheme
);
1153 if (data
.len
<= TPM2_MAX_DIGEST_BUFFER
)
1155 memcpy(buffer
.buffer
, data
.ptr
, data
.len
);
1156 buffer
.size
= data
.len
;
1158 this->mutex
->lock(this->mutex
);
1159 rval
= Tss2_Sys_Hash(this->sys_context
, 0, &buffer
, alg_id
, hierarchy
,
1160 &hash
, &validation
, 0);
1161 this->mutex
->unlock(this->mutex
);
1162 if (rval
!= TPM2_RC_SUCCESS
)
1164 DBG1(DBG_PTS
,LABEL
"Tss2_Sys_Hash failed: 0x%06x", rval
);
1170 TPMI_DH_OBJECT sequence_handle
;
1171 TPM2B_AUTH null_auth
;
1174 this->mutex
->lock(this->mutex
);
1175 rval
= Tss2_Sys_HashSequenceStart(this->sys_context
, 0, &null_auth
,
1176 alg_id
, &sequence_handle
, 0);
1177 if (rval
!= TPM2_RC_SUCCESS
)
1179 DBG1(DBG_PTS
, LABEL
"Tss2_Sys_HashSequenceStart failed: 0x%06x",
1181 this->mutex
->unlock(this->mutex
);
1185 while (data
.len
> 0)
1187 buffer
.size
= min(data
.len
, TPM2_MAX_DIGEST_BUFFER
);
1188 memcpy(buffer
.buffer
, data
.ptr
, buffer
.size
);
1189 data
.ptr
+= buffer
.size
;
1190 data
.len
-= buffer
.size
;
1192 rval
= Tss2_Sys_SequenceUpdate(this->sys_context
, sequence_handle
,
1193 &auth_cmd
, &buffer
, 0);
1194 if (rval
!= TPM2_RC_SUCCESS
)
1196 DBG1(DBG_PTS
, LABEL
"Tss2_Sys_SequenceUpdate failed: 0x%06x",
1198 this->mutex
->unlock(this->mutex
);
1204 rval
= Tss2_Sys_SequenceComplete(this->sys_context
, sequence_handle
,
1205 &auth_cmd
, &buffer
, hierarchy
,
1206 &hash
, &validation
, 0);
1207 this->mutex
->unlock(this->mutex
);
1208 if (rval
!= TPM2_RC_SUCCESS
)
1210 DBG1(DBG_PTS
, LABEL
"Tss2_Sys_SequenceComplete failed: 0x%06x",
1216 this->mutex
->lock(this->mutex
);
1217 rval
= Tss2_Sys_Sign(this->sys_context
, handle
, &auth_cmd
, &hash
,
1218 &sig_scheme
, &validation
, &sig
, &auth_rsp
);
1219 this->mutex
->unlock(this->mutex
);
1220 if (rval
!= TPM2_RC_SUCCESS
)
1222 DBG1(DBG_PTS
, LABEL
"Tss2_Sys_Sign failed: 0x%06x", rval
);
1226 /* extract signature */
1229 case SIGN_RSA_EMSA_PKCS1_SHA1
:
1230 case SIGN_RSA_EMSA_PKCS1_SHA2_256
:
1231 case SIGN_RSA_EMSA_PKCS1_SHA2_384
:
1232 case SIGN_RSA_EMSA_PKCS1_SHA2_512
:
1233 *signature
= chunk_clone(
1235 sig
.signature
.rsassa
.sig
.buffer
,
1236 sig
.signature
.rsassa
.sig
.size
));
1238 case SIGN_RSA_EMSA_PSS
:
1239 *signature
= chunk_clone(
1241 sig
.signature
.rsapss
.sig
.buffer
,
1242 sig
.signature
.rsapss
.sig
.size
));
1244 case SIGN_ECDSA_256
:
1245 case SIGN_ECDSA_384
:
1246 case SIGN_ECDSA_521
:
1247 *signature
= chunk_cat("cc",
1249 sig
.signature
.ecdsa
.signatureR
.buffer
,
1250 sig
.signature
.ecdsa
.signatureR
.size
),
1252 sig
.signature
.ecdsa
.signatureS
.buffer
,
1253 sig
.signature
.ecdsa
.signatureS
.size
));
1255 case SIGN_ECDSA_WITH_SHA256_DER
:
1256 case SIGN_ECDSA_WITH_SHA384_DER
:
1257 case SIGN_ECDSA_WITH_SHA512_DER
:
1258 *signature
= asn1_wrap(ASN1_SEQUENCE
, "mm",
1261 sig
.signature
.ecdsa
.signatureR
.buffer
,
1262 sig
.signature
.ecdsa
.signatureR
.size
)),
1265 sig
.signature
.ecdsa
.signatureS
.buffer
,
1266 sig
.signature
.ecdsa
.signatureS
.size
)));
1269 DBG1(DBG_PTS
, LABEL
"unsupported %N signature scheme",
1270 signature_scheme_names
, scheme
);
1278 * Check if an authenticated session with the TPM 2.0 can be started
1279 * The handle of the RSA Endorsement Key (EK) is required
1281 static void try_session_start(private_tpm_tss_tss2_t
*this)
1283 uint32_t ek_handle
= 0;
1284 chunk_t handle_chunk
;
1287 TPM2B_PUBLIC
public = { 0, };
1289 /* get Endorsement Key (EK) handle from settings */
1290 handle_str
= lib
->settings
->get_str(lib
->settings
,
1291 "%s.plugins.tpm.ek_handle", NULL
, lib
->ns
);
1294 handle_chunk
= chunk_from_hex(chunk_from_str(handle_str
),
1295 (char *)&ek_handle
);
1296 ek_handle
= (handle_chunk
.len
== 4) ? htonl(ek_handle
) : 0;
1298 /* establish protected auth session if ek_handle is set */
1299 if (ek_handle
&& read_public(this, ek_handle
, &public))
1301 this->mutex
->lock(this->mutex
);
1302 this->session
= tpm_tss_tss2_session_create(ek_handle
, &public,
1304 this->mutex
->unlock(this->mutex
);
1309 METHOD(tpm_tss_t
, get_random
, bool,
1310 private_tpm_tss_tss2_t
*this, size_t bytes
, uint8_t *buffer
)
1312 size_t len
, random_len
= sizeof(TPM2B_DIGEST
)-2;
1313 TPM2B_DIGEST random
= { random_len
, };
1314 uint8_t *pos
= buffer
;
1319 try_session_start(this);
1324 bool success
= FALSE
;
1326 len
= min(bytes
, random_len
);
1327 this->mutex
->lock(this->mutex
);
1329 rval
= Tss2_Sys_GetRandom_Prepare(this->sys_context
, len
);
1330 if (rval
!= TSS2_RC_SUCCESS
)
1332 DBG1(DBG_PTS
, "%s Tss2_Sys_GetRandom_Prepare failed: 0x%06x",
1337 if (this->session
&& !this->session
->set_cmd_auths(this->session
))
1342 rval
= Tss2_Sys_Execute(this->sys_context
);
1343 if (rval
!= TSS2_RC_SUCCESS
)
1345 DBG1(DBG_PTS
, LABEL
"Tss2_Sys_Execute failed: 0x%06x", rval
);
1349 if (this->session
&& !this->session
->get_rsp_auths(this->session
))
1354 rval
= Tss2_Sys_GetRandom_Complete(this->sys_context
, &random
);
1355 if (rval
!= TSS2_RC_SUCCESS
)
1357 DBG1(DBG_PTS
, LABEL
"Tss2_Sys_GetRandom_Complete failed: 0x%06x",
1364 this->mutex
->unlock(this->mutex
);
1370 memcpy(pos
, random
.buffer
, random
.size
);
1372 bytes
-= random
.size
;
1378 METHOD(tpm_tss_t
, get_data
, bool,
1379 private_tpm_tss_tss2_t
*this, uint32_t hierarchy
, uint32_t handle
,
1380 chunk_t pin
, chunk_t
*data
)
1382 uint16_t max_data_size
, nv_size
, nv_offset
= 0;
1385 TPMS_CAPABILITY_DATA cap_data
;
1386 TPMI_YES_NO more_data
;
1387 TPM2B_NAME nv_name
= { sizeof(TPM2B_NAME
)-2, };
1388 TPM2B_NV_PUBLIC nv_public
= { 0, };
1389 TPM2B_MAX_NV_BUFFER nv_data
= { TPM2_MAX_NV_BUFFER_SIZE
, };
1390 TPMS_AUTH_COMMAND
*cmd
;
1391 TSS2L_SYS_AUTH_COMMAND auth_cmd
= { 1, { auth_cmd_empty
} };
1392 TSS2L_SYS_AUTH_RESPONSE auth_rsp
;
1394 /* query maximum TPM data transmission size */
1395 this->mutex
->lock(this->mutex
);
1396 rval
= Tss2_Sys_GetCapability(this->sys_context
, 0, TPM2_CAP_TPM_PROPERTIES
,
1397 TPM2_PT_NV_BUFFER_MAX
, 1, &more_data
, &cap_data
, 0);
1398 this->mutex
->unlock(this->mutex
);
1399 if (rval
!= TPM2_RC_SUCCESS
)
1401 DBG1(DBG_PTS
, LABEL
"Tss2_Sys_GetCapability failed for "
1402 "TPM2_CAP_TPM_PROPERTIES: 0x%06x", rval
);
1405 max_data_size
= min(cap_data
.data
.tpmProperties
.tpmProperty
[0].value
,
1406 TPM2_MAX_NV_BUFFER_SIZE
);
1408 /* get size of NV object */
1409 this->mutex
->lock(this->mutex
);
1410 rval
= Tss2_Sys_NV_ReadPublic(this->sys_context
, handle
, 0, &nv_public
,
1412 this->mutex
->unlock(this->mutex
);
1413 if (rval
!= TPM2_RC_SUCCESS
)
1415 DBG1(DBG_PTS
, LABEL
"Tss2_Sys_NV_ReadPublic failed: 0x%06x", rval
);
1418 nv_size
= nv_public
.nvPublic
.dataSize
;
1419 *data
= chunk_alloc(nv_size
);
1421 /* prepare NV read session */
1422 cmd
= &auth_cmd
.auths
[0];
1423 cmd
->sessionHandle
= TPM2_RS_PW
;
1427 cmd
->hmac
.size
= min(sizeof(cmd
->hmac
)-2, pin
.len
);
1428 memcpy(cmd
->hmac
.buffer
, pin
.ptr
, cmd
->hmac
.size
);
1431 /* read NV data a maximum data size block at a time */
1434 this->mutex
->lock(this->mutex
);
1435 rval
= Tss2_Sys_NV_Read(this->sys_context
, hierarchy
, handle
, &auth_cmd
,
1436 min(nv_size
, max_data_size
), nv_offset
, &nv_data
, &auth_rsp
);
1437 this->mutex
->unlock(this->mutex
);
1438 if (rval
!= TPM2_RC_SUCCESS
)
1440 DBG1(DBG_PTS
, LABEL
"Tss2_Sys_NV_Read failed: 0x%06x", rval
);
1444 memcpy(data
->ptr
+ nv_offset
, nv_data
.buffer
, nv_data
.size
);
1445 nv_offset
+= nv_data
.size
;
1446 nv_size
-= nv_data
.size
;
1452 METHOD(tpm_tss_t
, get_event_digest
, bool,
1453 private_tpm_tss_tss2_t
*this, int fd
, hash_algorithm_t alg
, chunk_t
*digest
)
1455 uint8_t digest_buf
[HASH_SIZE_SHA512
];
1456 uint32_t digest_count
;
1457 size_t digest_len
= 0;
1458 hash_algorithm_t hash_alg
;
1461 if (this->old_event_digest_format
)
1463 if (alg
!= HASH_SHA1
)
1467 digest_len
= HASH_SIZE_SHA1
;
1469 *digest
= chunk_alloc(digest_len
);
1471 if (read(fd
, digest
->ptr
, digest_len
) != digest_len
)
1478 if (read(fd
, &digest_count
, 4) != 4)
1482 while (digest_count
--)
1484 if (read(fd
, &alg_id
, 2) != 2)
1488 hash_alg
= hash_alg_from_tpm_alg_id(alg_id
);
1489 digest_len
= hash_len_from_tpm_alg_id(alg_id
);
1491 if (hash_alg
== alg
)
1493 *digest
= chunk_alloc(digest_len
);
1494 if (read(fd
, digest
->ptr
, digest_len
) != digest_len
)
1501 /* read without storing */
1502 if (read(fd
, digest_buf
, digest_len
) != digest_len
)
1513 METHOD(tpm_tss_t
, destroy
, void,
1514 private_tpm_tss_tss2_t
*this)
1516 DESTROY_IF(this->session
);
1517 finalize_context(this);
1518 this->mutex
->destroy(this->mutex
);
1519 free(this->version_info
.ptr
);
1526 tpm_tss_t
*tpm_tss_tss2_create()
1528 private_tpm_tss_tss2_t
*this;
1533 .get_version
= _get_version
,
1534 .get_version_info
= _get_version_info
,
1535 .generate_aik
= _generate_aik
,
1536 .get_public
= _get_public
,
1537 .supported_signature_schemes
= _supported_signature_schemes
,
1538 .has_pcr_bank
= _has_pcr_bank
,
1539 .read_pcr
= _read_pcr
,
1540 .extend_pcr
= _extend_pcr
,
1543 .get_random
= _get_random
,
1544 .get_data
= _get_data
,
1545 .get_event_digest
= _get_event_digest
,
1546 .destroy
= _destroy
,
1548 .mutex
= mutex_create(MUTEX_TYPE_DEFAULT
),
1551 available
= initialize_tcti_context(this);
1554 available
= initialize_sys_context(this);
1556 DBG1(DBG_PTS
, "TPM 2.0 via TSS2 v2 %savailable", available
? "" : "not ");
1564 return &this->public;
1570 bool tpm_tss_tss2_init(void)
1572 TSS2_TCTI_INFO_FUNC infofn
;
1573 const TSS2_TCTI_INFO
*info
;
1574 char tcti_lib_format
[] = "libtss2-tcti-%s.so.0";
1575 char tcti_lib
[BUF_LEN
];
1576 char *tcti_names
[] = { "device", "tabrmd", "mssim" };
1577 char *tcti_options
[] = { "/dev/tpmrm0", "", "" };
1583 /* check for the existence of an in-kernel TPM resource manager */
1584 if (stat(tcti_options
[i
], &st
))
1588 DBG2(DBG_PTS
, LABEL
"\"%s\" in-kernel resource manager is %spresent",
1589 tcti_options
[0], i
? "not " : "");
1591 /* select a dynamic TCTI library (device, tabrmd or mssim) */
1592 tcti_name
= lib
->settings
->get_str(lib
->settings
,
1593 "%s.plugins.tpm.tcti.name", tcti_names
[i
], lib
->ns
);
1594 snprintf(tcti_lib
, BUF_LEN
, tcti_lib_format
, tcti_name
);
1596 for (i
= 0; i
< countof(tcti_names
); i
++)
1598 if (streq(tcti_name
, tcti_names
[i
]))
1606 DBG1(DBG_PTS
, LABEL
"\"%s\" is not a valid TCTI library name", tcti_lib
);
1610 tcti_opts
= lib
->settings
->get_str(lib
->settings
,
1611 "%s.plugins.tpm.tcti.opts", tcti_options
[i
], lib
->ns
);
1613 /* open the selected dynamic TCTI library */
1614 tcti_handle
= dlopen(tcti_lib
, RTLD_LAZY
);
1617 DBG1(DBG_PTS
, LABEL
"could not load \"%s\"", tcti_lib
);
1621 infofn
= (TSS2_TCTI_INFO_FUNC
)dlsym(tcti_handle
, TSS2_TCTI_INFO_SYMBOL
);
1624 DBG1(DBG_PTS
, LABEL
"symbol \"%s\" not found in \"%s\"",
1625 TSS2_TCTI_INFO_SYMBOL
, tcti_lib
);
1626 tpm_tss_tss2_deinit();
1630 DBG2(DBG_PTS
, LABEL
"\"%s\" successfully loaded", tcti_lib
);
1632 tcti_init
= info
->init
;
1640 void tpm_tss_tss2_deinit(void)
1642 dlclose(tcti_handle
);
1648 #else /* TSS_TSS2_V2 */
1653 bool tpm_tss_tss2_init(void)
1661 void tpm_tss_tss2_deinit(void)
1666 #endif /* TSS_TSS2_V2 */