2 * Copyright (C) 2016 Andreas Steffen
3 * HSR Hochschule fuer Technik Rapperswil
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 #include "tpm_tss_tss2.h"
17 #include "tpm_tss_tss2_names.h"
21 #include <asn1/asn1.h>
23 #include <bio/bio_reader.h>
27 #ifdef TSS2_TCTI_TABRMD
28 #include <tcti/tcti-tabrmd.h>
29 #endif /* TSS2_TCTI_TABRMD */
31 #ifdef TSS2_TCTI_SOCKET
32 #include <tcti_socket.h>
34 #define TCTI_SOCKET_DEFAULT_ADDRESS "127.0.0.1"
35 #define TCTI_SOCKET_DEFAULT_PORT 2323
36 #endif /* TSS2_TCTI_SOCKET */
38 #define LABEL "TPM 2.0 -"
40 typedef struct private_tpm_tss_tss2_t private_tpm_tss_tss2_t
;
43 * Private data of an tpm_tss_tss2_t object.
45 struct private_tpm_tss_tss2_t
{
48 * Public tpm_tss_tss2_t interface.
55 TSS2_TCTI_CONTEXT
*tcti_context
;
60 TSS2_SYS_CONTEXT
*sys_context
;
63 * Number of supported algorithms
65 size_t supported_algs_count
;
68 * List of supported algorithms
70 TPM_ALG_ID supported_algs
[TPM_PT_ALGORITHM_SET
];
74 * Some symbols required by libtctisocket
77 uint8_t simulator
= 1;
79 int TpmClientPrintf (uint8_t type
, const char *format
, ...)
85 * Convert hash algorithm to TPM_ALG_ID
87 static TPM_ALG_ID
hash_alg_to_tpm_alg_id(hash_algorithm_t alg
)
94 return TPM_ALG_SHA256
;
96 return TPM_ALG_SHA384
;
98 return TPM_ALG_SHA512
;
100 return TPM_ALG_ERROR
;
105 * Convert TPM_ALG_ID to hash algorithm
107 static hash_algorithm_t
hash_alg_from_tpm_alg_id(TPM_ALG_ID alg
)
125 * Check if an algorithm given by its TPM_ALG_ID is supported by the TPM
127 static bool is_supported_alg(private_tpm_tss_tss2_t
*this, TPM_ALG_ID alg_id
)
131 if (alg_id
== TPM_ALG_ERROR
)
136 for (i
= 0; i
< this->supported_algs_count
; i
++)
138 if (this->supported_algs
[i
] == alg_id
)
148 * Get a list of supported algorithms
150 static bool get_algs_capability(private_tpm_tss_tss2_t
*this)
152 TPMS_CAPABILITY_DATA cap_data
;
153 TPMS_TAGGED_PROPERTY tp
;
154 TPMI_YES_NO more_data
;
156 uint32_t rval
, i
, offset
, revision
= 0, year
= 0;
157 size_t len
= BUF_LEN
;
158 char buf
[BUF_LEN
], manufacturer
[5], vendor_string
[17];
162 /* get fixed properties */
163 rval
= Tss2_Sys_GetCapability(this->sys_context
, 0, TPM_CAP_TPM_PROPERTIES
,
164 PT_FIXED
, MAX_TPM_PROPERTIES
, &more_data
, &cap_data
, 0);
165 if (rval
!= TPM_RC_SUCCESS
)
167 DBG1(DBG_PTS
, "%s GetCapability failed for TPM_CAP_TPM_PROPERTIES: 0x%06x",
170 memset(manufacturer
, '\0', sizeof(manufacturer
));
171 memset(vendor_string
, '\0', sizeof(vendor_string
));
173 /* print fixed properties */
174 for (i
= 0; i
< cap_data
.data
.tpmProperties
.count
; i
++)
176 tp
= cap_data
.data
.tpmProperties
.tpmProperty
[i
];
179 case TPM_PT_REVISION
:
185 case TPM_PT_MANUFACTURER
:
186 htoun32(manufacturer
, tp
.value
);
188 case TPM_PT_VENDOR_STRING_1
:
189 case TPM_PT_VENDOR_STRING_2
:
190 case TPM_PT_VENDOR_STRING_3
:
191 case TPM_PT_VENDOR_STRING_4
:
192 offset
= 4 * (tp
.property
- TPM_PT_VENDOR_STRING_1
);
193 htoun32(vendor_string
+ offset
, tp
.value
);
199 DBG2(DBG_PTS
, "%s manufacturer: %s (%s) rev: %05.2f %u", LABEL
, manufacturer
,
200 vendor_string
, (float)revision
/100, year
);
202 /* get supported algorithms */
203 rval
= Tss2_Sys_GetCapability(this->sys_context
, 0, TPM_CAP_ALGS
,
204 0, TPM_PT_ALGORITHM_SET
, &more_data
, &cap_data
, 0);
205 if (rval
!= TPM_RC_SUCCESS
)
207 DBG1(DBG_PTS
, "%s GetCapability failed for TPM_CAP_ALGS: 0x%06x",
212 /* Number of supported algorithms */
213 this->supported_algs_count
= cap_data
.data
.algorithms
.count
;
215 /* store and print supported algorithms */
216 for (i
= 0; i
< this->supported_algs_count
; i
++)
218 alg
= cap_data
.data
.algorithms
.algProperties
[i
].alg
;
219 this->supported_algs
[i
] = alg
;
221 written
= snprintf(pos
, len
, " %N", tpm_alg_id_names
, alg
);
222 if (written
< 0 || written
>= len
)
229 DBG2(DBG_PTS
, "%s algorithms:%s", LABEL
, buf
);
231 /* get supported ECC curves */
232 rval
= Tss2_Sys_GetCapability(this->sys_context
, 0, TPM_CAP_ECC_CURVES
,
233 0, TPM_PT_LOADED_CURVES
, &more_data
, &cap_data
, 0);
234 if (rval
!= TPM_RC_SUCCESS
)
236 DBG1(DBG_PTS
, "%s GetCapability failed for TPM_ECC_CURVES: 0x%06x",
241 /* reset print buffer */
245 /* print supported ECC curves */
246 for (i
= 0; i
< cap_data
.data
.eccCurves
.count
; i
++)
248 written
= snprintf(pos
, len
, " %N", tpm_ecc_curve_names
,
249 cap_data
.data
.eccCurves
.eccCurves
[i
]);
250 if (written
< 0 || written
>= len
)
257 DBG2(DBG_PTS
, "%s ECC curves:%s", LABEL
, buf
);
263 * Initialize TSS2 TCTI TABRMD context
265 static bool initialize_tcti_tabrmd_context(private_tpm_tss_tss2_t
*this)
267 #ifdef TSS2_TCTI_TABRMD
268 size_t tcti_context_size
;
271 /* determine size of tcti context */
272 rval
= tss2_tcti_tabrmd_init(NULL
, &tcti_context_size
);
273 if (rval
!= TSS2_RC_SUCCESS
)
275 DBG1(DBG_PTS
, "%s could not get tcti_context size: 0x%06x",
280 /* allocate memory for tcti context */
281 this->tcti_context
= (TSS2_TCTI_CONTEXT
*)malloc(tcti_context_size
);
283 /* initialize tcti context */
284 rval
= tss2_tcti_tabrmd_init(this->tcti_context
, &tcti_context_size
);
285 if (rval
!= TSS2_RC_SUCCESS
)
287 DBG1(DBG_PTS
, "%s could not get tcti_context: 0x%06x "
288 "via tabrmd interface", LABEL
, rval
);
292 #else /* TSS2_TCTI_TABRMD */
294 #endif /* TSS2_TCTI_TABRMD */
298 * Initialize TSS2 TCTI Socket context
300 static bool initialize_tcti_socket_context(private_tpm_tss_tss2_t
*this)
302 #ifdef TSS2_TCTI_SOCKET
303 size_t tcti_context_size
;
306 TCTI_SOCKET_CONF rm_if_config
= { TCTI_SOCKET_DEFAULT_ADDRESS
,
307 TCTI_SOCKET_DEFAULT_PORT
310 /* determine size of tcti context */
311 rval
= InitSocketTcti(NULL
, &tcti_context_size
, &rm_if_config
, 0);
312 if (rval
!= TSS2_RC_SUCCESS
)
314 DBG1(DBG_PTS
, "%s could not get tcti_context size: 0x%06x",
319 /* allocate memory for tcti context */
320 this->tcti_context
= (TSS2_TCTI_CONTEXT
*)malloc(tcti_context_size
);
322 /* initialize tcti context */
323 rval
= InitSocketTcti(this->tcti_context
, &tcti_context_size
,
325 if (rval
!= TSS2_RC_SUCCESS
)
327 DBG1(DBG_PTS
, "%s could not get tcti_context: 0x%06x "
328 "via socket interface", LABEL
, rval
);
332 #else /* TSS2_TCTI_SOCKET */
334 #endif /* TSS2_TCTI_SOCKET */
338 * Initialize TSS2 Sys context
340 static bool initialize_sys_context(private_tpm_tss_tss2_t
*this)
342 uint32_t sys_context_size
;
345 TSS2_ABI_VERSION abi_version
= { TSSWG_INTEROP
,
346 TSS_SAPI_FIRST_FAMILY
,
347 TSS_SAPI_FIRST_LEVEL
,
348 TSS_SAPI_FIRST_VERSION
351 /* determine size of sys context */
352 sys_context_size
= Tss2_Sys_GetContextSize(0);
354 /* allocate memory for sys context */
355 this->sys_context
= malloc(sys_context_size
);
357 /* initialize sys context */
358 rval
= Tss2_Sys_Initialize(this->sys_context
, sys_context_size
,
359 this->tcti_context
, &abi_version
);
360 if (rval
!= TSS2_RC_SUCCESS
)
362 DBG1(DBG_PTS
, "%s could not get sys_context: 0x%06x",
367 /* get a list of supported algorithms and ECC curves */
368 return get_algs_capability(this);
372 * Finalize TSS context
374 static void finalize_context(private_tpm_tss_tss2_t
*this)
376 if (this->tcti_context
)
378 tss2_tcti_finalize(this->tcti_context
);
379 free(this->tcti_context
);
381 if (this->sys_context
)
383 Tss2_Sys_Finalize(this->sys_context
);
384 free(this->sys_context
);
388 METHOD(tpm_tss_t
, get_version
, tpm_version_t
,
389 private_tpm_tss_tss2_t
*this)
391 return TPM_VERSION_2_0
;
394 METHOD(tpm_tss_t
, get_version_info
, chunk_t
,
395 private_tpm_tss_tss2_t
*this)
401 * read the public key portion of a TSS 2.0 AIK key from NVRAM
403 bool read_public(private_tpm_tss_tss2_t
*this, TPMI_DH_OBJECT handle
,
404 TPM2B_PUBLIC
*public)
408 TPM2B_NAME name
= { { sizeof(TPM2B_NAME
)-2, } };
409 TPM2B_NAME qualified_name
= { { sizeof(TPM2B_NAME
)-2, } };
411 TPMS_AUTH_RESPONSE session_data
;
412 TSS2_SYS_RSP_AUTHS sessions_data
;
413 TPMS_AUTH_RESPONSE
*session_data_array
[1];
415 session_data_array
[0] = &session_data
;
416 sessions_data
.rspAuths
= &session_data_array
[0];
417 sessions_data
.rspAuthsCount
= 1;
419 /* read public key for a given object handle from TPM 2.0 NVRAM */
420 rval
= Tss2_Sys_ReadPublic(this->sys_context
, handle
, 0, public, &name
,
421 &qualified_name
, &sessions_data
);
422 if (rval
!= TPM_RC_SUCCESS
)
424 DBG1(DBG_PTS
, "%s could not read public key from handle 0x%08x: 0x%06x",
425 LABEL
, handle
, rval
);
431 METHOD(tpm_tss_t
, generate_aik
, bool,
432 private_tpm_tss_tss2_t
*this, chunk_t ca_modulus
, chunk_t
*aik_blob
,
433 chunk_t
*aik_pubkey
, chunk_t
*identity_req
)
438 METHOD(tpm_tss_t
, get_public
, chunk_t
,
439 private_tpm_tss_tss2_t
*this, uint32_t handle
)
441 TPM2B_PUBLIC
public = { { 0, } };
442 TPM_ALG_ID sig_alg
, digest_alg
;
443 chunk_t aik_blob
, aik_pubkey
= chunk_empty
;
445 if (!read_public(this, handle
, &public))
450 aik_blob
= chunk_create((u_char
*)&public, sizeof(public));
451 DBG3(DBG_LIB
, "%s AIK public key blob: %B", LABEL
, &aik_blob
);
453 /* convert TSS 2.0 AIK public key blot into PKCS#1 format */
454 switch (public.t
.publicArea
.type
)
458 TPM2B_PUBLIC_KEY_RSA
*rsa
;
459 TPMT_RSA_SCHEME
*scheme
;
460 chunk_t aik_exponent
, aik_modulus
;
462 scheme
= &public.t
.publicArea
.parameters
.rsaDetail
.scheme
;
463 sig_alg
= scheme
->scheme
;
464 digest_alg
= scheme
->details
.anySig
.hashAlg
;
466 rsa
= &public.t
.publicArea
.unique
.rsa
;
467 aik_modulus
= chunk_create(rsa
->t
.buffer
, rsa
->t
.size
);
468 aik_exponent
= chunk_from_chars(0x01, 0x00, 0x01);
470 /* subjectPublicKeyInfo encoding of AIK RSA key */
471 if (!lib
->encoding
->encode(lib
->encoding
, PUBKEY_SPKI_ASN1_DER
,
472 NULL
, &aik_pubkey
, CRED_PART_RSA_MODULUS
, aik_modulus
,
473 CRED_PART_RSA_PUB_EXP
, aik_exponent
, CRED_PART_END
))
475 DBG1(DBG_PTS
, "%s subjectPublicKeyInfo encoding of AIK key "
483 TPMT_ECC_SCHEME
*scheme
;
487 scheme
= &public.t
.publicArea
.parameters
.eccDetail
.scheme
;
488 sig_alg
= scheme
->scheme
;
489 digest_alg
= scheme
->details
.anySig
.hashAlg
;
491 ecc
= &public.t
.publicArea
.unique
.ecc
;
493 /* allocate space for bit string */
494 pos
= asn1_build_object(&ecc_point
, ASN1_BIT_STRING
,
495 2 + ecc
->x
.t
.size
+ ecc
->y
.t
.size
);
496 /* bit string length is a multiple of octets */
498 /* uncompressed ECC point format */
500 /* copy x coordinate of ECC point */
501 memcpy(pos
, ecc
->x
.t
.buffer
, ecc
->x
.t
.size
);
502 pos
+= ecc
->x
.t
.size
;
503 /* copy y coordinate of ECC point */
504 memcpy(pos
, ecc
->y
.t
.buffer
, ecc
->y
.t
.size
);
505 /* subjectPublicKeyInfo encoding of AIK ECC key */
506 aik_pubkey
= asn1_wrap(ASN1_SEQUENCE
, "mm",
507 asn1_wrap(ASN1_SEQUENCE
, "mm",
508 asn1_build_known_oid(OID_EC_PUBLICKEY
),
509 asn1_build_known_oid(ecc
->x
.t
.size
== 32 ?
510 OID_PRIME256V1
: OID_SECT384R1
)),
515 DBG1(DBG_PTS
, "%s unsupported AIK key type", LABEL
);
518 DBG1(DBG_PTS
, "AIK signature algorithm is %N with %N hash",
519 tpm_alg_id_names
, sig_alg
, tpm_alg_id_names
, digest_alg
);
524 * Configure a PCR Selection assuming a maximum of 24 registers
526 static bool init_pcr_selection(private_tpm_tss_tss2_t
*this, uint32_t pcrs
,
527 hash_algorithm_t alg
, TPML_PCR_SELECTION
*pcr_sel
)
532 /* check if hash algorithm is supported by TPM */
533 alg_id
= hash_alg_to_tpm_alg_id(alg
);
534 if (!is_supported_alg(this, alg_id
))
536 DBG1(DBG_PTS
, "%s %N hash algorithm not supported by TPM",
537 LABEL
, hash_algorithm_short_names
, alg
);
541 /* initialize the PCR Selection structure,*/
543 pcr_sel
->pcrSelections
[0].hash
= alg_id
;
544 pcr_sel
->pcrSelections
[0].sizeofSelect
= 3;
545 pcr_sel
->pcrSelections
[0].pcrSelect
[0] = 0;
546 pcr_sel
->pcrSelections
[0].pcrSelect
[1] = 0;
547 pcr_sel
->pcrSelections
[0].pcrSelect
[2] = 0;
549 /* set the selected PCRs */
550 for (pcr
= 0; pcr
< PLATFORM_PCR
; pcr
++)
552 if (pcrs
& (1 << pcr
))
554 pcr_sel
->pcrSelections
[0].pcrSelect
[pcr
/ 8] |= ( 1 << (pcr
% 8) );
560 METHOD(tpm_tss_t
, read_pcr
, bool,
561 private_tpm_tss_tss2_t
*this, uint32_t pcr_num
, chunk_t
*pcr_value
,
562 hash_algorithm_t alg
)
564 TPML_PCR_SELECTION pcr_selection
;
565 TPML_DIGEST pcr_values
;
567 uint32_t pcr_update_counter
, rval
;
568 uint8_t *pcr_value_ptr
;
569 size_t pcr_value_len
;
571 if (pcr_num
>= PLATFORM_PCR
)
573 DBG1(DBG_PTS
, "%s maximum number of supported PCR is %d",
574 LABEL
, PLATFORM_PCR
);
578 if (!init_pcr_selection(this, (1 << pcr_num
), alg
, &pcr_selection
))
583 /* initialize the PCR Digest structure */
584 memset(&pcr_values
, 0, sizeof(TPML_DIGEST
));
586 /* read the PCR value */
587 rval
= Tss2_Sys_PCR_Read(this->sys_context
, 0, &pcr_selection
,
588 &pcr_update_counter
, &pcr_selection
, &pcr_values
, 0);
589 if (rval
!= TPM_RC_SUCCESS
)
591 DBG1(DBG_PTS
, "%s PCR bank could not be read: 0x%60x",
595 pcr_value_ptr
= (uint8_t *)pcr_values
.digests
[0].t
.buffer
;
596 pcr_value_len
= (size_t) pcr_values
.digests
[0].t
.size
;
598 *pcr_value
= chunk_clone(chunk_create(pcr_value_ptr
, pcr_value_len
));
603 METHOD(tpm_tss_t
, extend_pcr
, bool,
604 private_tpm_tss_tss2_t
*this, uint32_t pcr_num
, chunk_t
*pcr_value
,
605 chunk_t data
, hash_algorithm_t alg
)
611 METHOD(tpm_tss_t
, quote
, bool,
612 private_tpm_tss_tss2_t
*this, uint32_t aik_handle
, uint32_t pcr_sel
,
613 hash_algorithm_t alg
, chunk_t data
, tpm_quote_mode_t
*quote_mode
,
614 tpm_tss_quote_info_t
**quote_info
, chunk_t
*quote_sig
)
616 chunk_t quoted_chunk
, qualified_signer
, extra_data
, clock_info
,
617 firmware_version
, pcr_select
, pcr_digest
;
618 hash_algorithm_t pcr_digest_alg
;
619 bio_reader_t
*reader
;
622 TPM2B_DATA qualifying_data
;
623 TPML_PCR_SELECTION pcr_selection
;
624 TPM2B_ATTEST quoted
= { { sizeof(TPM2B_ATTEST
)-2, } };
625 TPMT_SIG_SCHEME scheme
;
627 TPMI_ALG_HASH hash_alg
;
628 TPMS_AUTH_COMMAND session_data_cmd
;
629 TPMS_AUTH_RESPONSE session_data_rsp
;
630 TSS2_SYS_CMD_AUTHS sessions_data_cmd
;
631 TSS2_SYS_RSP_AUTHS sessions_data_rsp
;
632 TPMS_AUTH_COMMAND
*session_data_cmd_array
[1];
633 TPMS_AUTH_RESPONSE
*session_data_rsp_array
[1];
635 session_data_cmd_array
[0] = &session_data_cmd
;
636 session_data_rsp_array
[0] = &session_data_rsp
;
638 sessions_data_cmd
.cmdAuths
= &session_data_cmd_array
[0];
639 sessions_data_rsp
.rspAuths
= &session_data_rsp_array
[0];
641 sessions_data_cmd
.cmdAuthsCount
= 1;
642 sessions_data_rsp
.rspAuthsCount
= 1;
644 session_data_cmd
.sessionHandle
= TPM_RS_PW
;
645 session_data_cmd
.hmac
.t
.size
= 0;
646 session_data_cmd
.nonce
.t
.size
= 0;
648 *( (uint8_t *)((void *)&session_data_cmd
.sessionAttributes
) ) = 0;
650 qualifying_data
.t
.size
= data
.len
;
651 memcpy(qualifying_data
.t
.buffer
, data
.ptr
, data
.len
);
653 scheme
.scheme
= TPM_ALG_NULL
;
654 memset(&sig
, 0x00, sizeof(sig
));
657 *quote_mode
= TPM_QUOTE_TPM2
;
659 if (!init_pcr_selection(this, pcr_sel
, alg
, &pcr_selection
))
664 rval
= Tss2_Sys_Quote(this->sys_context
, aik_handle
, &sessions_data_cmd
,
665 &qualifying_data
, &scheme
, &pcr_selection
, "ed
,
666 &sig
, &sessions_data_rsp
);
667 if (rval
!= TPM_RC_SUCCESS
)
669 DBG1(DBG_PTS
,"%s Tss2_Sys_Quote failed: 0x%06x", LABEL
, rval
);
672 quoted_chunk
= chunk_create(quoted
.t
.attestationData
, quoted
.t
.size
);
674 reader
= bio_reader_create(chunk_skip(quoted_chunk
, 6));
675 if (!reader
->read_data16(reader
, &qualified_signer
) ||
676 !reader
->read_data16(reader
, &extra_data
) ||
677 !reader
->read_data (reader
, 17, &clock_info
) ||
678 !reader
->read_data (reader
, 8, &firmware_version
) ||
679 !reader
->read_data (reader
, 10, &pcr_select
) ||
680 !reader
->read_data16(reader
, &pcr_digest
))
682 DBG1(DBG_PTS
, "%s parsing of quoted struct failed", LABEL
);
683 reader
->destroy(reader
);
686 reader
->destroy(reader
);
688 DBG2(DBG_PTS
, "PCR Composite digest: %B", &pcr_digest
);
689 DBG2(DBG_PTS
, "TPM Quote Info: %B", "ed_chunk
);
690 DBG2(DBG_PTS
, "qualifiedSigner: %B", &qualified_signer
);
691 DBG2(DBG_PTS
, "extraData: %B", &extra_data
);
692 DBG2(DBG_PTS
, "clockInfo: %B", &clock_info
);
693 DBG2(DBG_PTS
, "firmwareVersion: %B", &firmware_version
);
694 DBG2(DBG_PTS
, "pcrSelect: %B", &pcr_select
);
696 /* extract signature */
701 *quote_sig
= chunk_clone(
703 sig
.signature
.rsassa
.sig
.t
.buffer
,
704 sig
.signature
.rsassa
.sig
.t
.size
));
705 hash_alg
= sig
.signature
.rsassa
.hash
;
710 case TPM_ALG_ECSCHNORR
:
711 *quote_sig
= chunk_cat("cc",
713 sig
.signature
.ecdsa
.signatureR
.t
.buffer
,
714 sig
.signature
.ecdsa
.signatureR
.t
.size
),
716 sig
.signature
.ecdsa
.signatureS
.t
.buffer
,
717 sig
.signature
.ecdsa
.signatureS
.t
.size
));
718 hash_alg
= sig
.signature
.ecdsa
.hash
;
721 DBG1(DBG_PTS
, "%s unsupported %N signature algorithm",
722 LABEL
, tpm_alg_id_names
, sig
.sigAlg
);
726 DBG2(DBG_PTS
, "PCR digest algorithm is %N", tpm_alg_id_names
, hash_alg
);
727 pcr_digest_alg
= hash_alg_from_tpm_alg_id(hash_alg
);
729 DBG2(DBG_PTS
, "TPM Quote Signature: %B", quote_sig
);
731 /* Create and initialize Quote Info object */
732 *quote_info
= tpm_tss_quote_info_create(*quote_mode
, pcr_digest_alg
,
734 (*quote_info
)->set_tpm2_info(*quote_info
, qualified_signer
, clock_info
,
736 (*quote_info
)->set_version_info(*quote_info
, firmware_version
);
741 METHOD(tpm_tss_t
, sign
, bool,
742 private_tpm_tss_tss2_t
*this, uint32_t hierarchy
, uint32_t handle
,
743 signature_scheme_t scheme
, chunk_t data
, chunk_t pin
, chunk_t
*signature
)
746 hash_algorithm_t hash_alg
;
750 TPM2B_MAX_BUFFER buffer
;
751 TPM2B_DIGEST hash
= { { sizeof(TPM2B_DIGEST
)-2, } };
752 TPMT_TK_HASHCHECK validation
;
753 TPM2B_PUBLIC
public = { { 0, } };
754 TPMT_SIG_SCHEME sig_scheme
;
756 TPMS_AUTH_COMMAND session_data_cmd
;
757 TPMS_AUTH_RESPONSE session_data_rsp
;
758 TSS2_SYS_CMD_AUTHS sessions_data_cmd
;
759 TSS2_SYS_RSP_AUTHS sessions_data_rsp
;
760 TPMS_AUTH_COMMAND
*session_data_cmd_array
[1];
761 TPMS_AUTH_RESPONSE
*session_data_rsp_array
[1];
763 session_data_cmd_array
[0] = &session_data_cmd
;
764 session_data_rsp_array
[0] = &session_data_rsp
;
766 sessions_data_cmd
.cmdAuths
= &session_data_cmd_array
[0];
767 sessions_data_rsp
.rspAuths
= &session_data_rsp_array
[0];
769 sessions_data_cmd
.cmdAuthsCount
= 1;
770 sessions_data_rsp
.rspAuthsCount
= 1;
772 session_data_cmd
.sessionHandle
= TPM_RS_PW
;
773 session_data_cmd
.nonce
.t
.size
= 0;
774 session_data_cmd
.hmac
.t
.size
= 0;
778 session_data_cmd
.hmac
.t
.size
= min(sizeof(session_data_cmd
.hmac
.t
) - 2,
780 memcpy(session_data_cmd
.hmac
.t
.buffer
, pin
.ptr
,
781 session_data_cmd
.hmac
.t
.size
);
783 *( (uint8_t *)((void *)&session_data_cmd
.sessionAttributes
) ) = 0;
785 key_type
= key_type_from_signature_scheme(scheme
);
786 hash_alg
= hasher_from_signature_scheme(scheme
, NULL
);
788 /* Check if hash algorithm is supported by TPM */
789 alg_id
= hash_alg_to_tpm_alg_id(hash_alg
);
790 if (!is_supported_alg(this, alg_id
))
792 DBG1(DBG_PTS
, "%s %N hash algorithm not supported by TPM",
793 LABEL
, hash_algorithm_short_names
, hash_alg
);
798 if (!read_public(this, handle
, &public))
803 if (key_type
== KEY_RSA
&& public.t
.publicArea
.type
== TPM_ALG_RSA
)
805 sig_scheme
.scheme
= TPM_ALG_RSASSA
;
806 sig_scheme
.details
.rsassa
.hashAlg
= alg_id
;
808 else if (key_type
== KEY_ECDSA
&& public.t
.publicArea
.type
== TPM_ALG_ECC
)
810 sig_scheme
.scheme
= TPM_ALG_ECDSA
;
811 sig_scheme
.details
.ecdsa
.hashAlg
= alg_id
;
816 DBG1(DBG_PTS
, "%s signature scheme %N not supported by TPM key",
817 LABEL
, signature_scheme_names
, scheme
);
821 if (data
.len
<= MAX_DIGEST_BUFFER
)
823 memcpy(buffer
.t
.buffer
, data
.ptr
, data
.len
);
824 buffer
.t
.size
= data
.len
;
826 rval
= Tss2_Sys_Hash(this->sys_context
, 0, &buffer
, alg_id
, hierarchy
,
827 &hash
, &validation
, 0);
828 if (rval
!= TPM_RC_SUCCESS
)
830 DBG1(DBG_PTS
,"%s Tss2_Sys_Hash failed: 0x%06x", LABEL
, rval
);
836 TPMI_DH_OBJECT sequence_handle
;
837 TPM2B_AUTH null_auth
;
839 null_auth
.t
.size
= 0;
840 rval
= Tss2_Sys_HashSequenceStart(this->sys_context
, 0, &null_auth
,
841 alg_id
, &sequence_handle
, 0);
842 if (rval
!= TPM_RC_SUCCESS
)
844 DBG1(DBG_PTS
,"%s Tss2_Sys_HashSequenceStart failed: 0x%06x",
851 buffer
.t
.size
= min(data
.len
, MAX_DIGEST_BUFFER
);
852 memcpy(buffer
.t
.buffer
, data
.ptr
, buffer
.t
.size
);
853 data
.ptr
+= buffer
.t
.size
;
854 data
.len
-= buffer
.t
.size
;
856 rval
= Tss2_Sys_SequenceUpdate(this->sys_context
, sequence_handle
,
857 &sessions_data_cmd
, &buffer
, 0);
858 if (rval
!= TPM_RC_SUCCESS
)
860 DBG1(DBG_PTS
,"%s Tss2_Sys_SequenceUpdate failed: 0x%06x",
867 rval
= Tss2_Sys_SequenceComplete(this->sys_context
, sequence_handle
,
868 &sessions_data_cmd
, &buffer
, hierarchy
,
869 &hash
, &validation
, 0);
870 if (rval
!= TPM_RC_SUCCESS
)
872 DBG1(DBG_PTS
,"%s Tss2_Sys_SequenceComplete failed: 0x%06x",
878 rval
= Tss2_Sys_Sign(this->sys_context
, handle
, &sessions_data_cmd
, &hash
,
879 &sig_scheme
, &validation
, &sig
, &sessions_data_rsp
);
880 if (rval
!= TPM_RC_SUCCESS
)
882 DBG1(DBG_PTS
,"%s Tss2_Sys_Sign failed: 0x%06x", LABEL
, rval
);
886 /* extract signature */
889 case SIGN_RSA_EMSA_PKCS1_SHA1
:
890 case SIGN_RSA_EMSA_PKCS1_SHA2_256
:
891 case SIGN_RSA_EMSA_PKCS1_SHA2_384
:
892 case SIGN_RSA_EMSA_PKCS1_SHA2_512
:
893 *signature
= chunk_clone(
895 sig
.signature
.rsassa
.sig
.t
.buffer
,
896 sig
.signature
.rsassa
.sig
.t
.size
));
901 *signature
= chunk_cat("cc",
903 sig
.signature
.ecdsa
.signatureR
.t
.buffer
,
904 sig
.signature
.ecdsa
.signatureR
.t
.size
),
906 sig
.signature
.ecdsa
.signatureS
.t
.buffer
,
907 sig
.signature
.ecdsa
.signatureS
.t
.size
));
909 case SIGN_ECDSA_WITH_SHA256_DER
:
910 case SIGN_ECDSA_WITH_SHA384_DER
:
911 case SIGN_ECDSA_WITH_SHA512_DER
:
912 *signature
= asn1_wrap(ASN1_SEQUENCE
, "mm",
915 sig
.signature
.ecdsa
.signatureR
.t
.buffer
,
916 sig
.signature
.ecdsa
.signatureR
.t
.size
)),
919 sig
.signature
.ecdsa
.signatureS
.t
.buffer
,
920 sig
.signature
.ecdsa
.signatureS
.t
.size
)));
923 DBG1(DBG_PTS
, "%s unsupported %N signature scheme",
924 LABEL
, signature_scheme_names
, scheme
);
931 METHOD(tpm_tss_t
, get_random
, bool,
932 private_tpm_tss_tss2_t
*this, size_t bytes
, uint8_t *buffer
)
934 size_t len
, random_len
= sizeof(TPM2B_DIGEST
)-2;
935 TPM2B_DIGEST random
= { { random_len
, } };
936 uint8_t *pos
= buffer
;
941 len
= min(bytes
, random_len
);
943 rval
= Tss2_Sys_GetRandom(this->sys_context
, NULL
, len
, &random
, NULL
);
944 if (rval
!= TSS2_RC_SUCCESS
)
946 DBG1(DBG_PTS
,"%s Tss2_Sys_GetRandom failed: 0x%06x", LABEL
, rval
);
949 memcpy(pos
, random
.t
.buffer
, random
.t
.size
);
950 pos
+= random
.t
.size
;
951 bytes
-= random
.t
.size
;
957 METHOD(tpm_tss_t
, get_data
, bool,
958 private_tpm_tss_tss2_t
*this, uint32_t hierarchy
, uint32_t handle
,
959 chunk_t pin
, chunk_t
*data
)
961 uint16_t nv_size
, nv_offset
= 0;
964 TPM2B_NAME nv_name
= { { sizeof(TPM2B_NAME
)-2, } };
965 TPM2B_NV_PUBLIC nv_public
= { { 0, } };
966 TPM2B_MAX_NV_BUFFER nv_data
= { { sizeof(TPM2B_MAX_NV_BUFFER
)-2, } };
967 TPMS_AUTH_COMMAND session_data_cmd
;
968 TPMS_AUTH_RESPONSE session_data_rsp
;
969 TSS2_SYS_CMD_AUTHS sessions_data_cmd
;
970 TSS2_SYS_RSP_AUTHS sessions_data_rsp
;
971 TPMS_AUTH_COMMAND
*session_data_cmd_array
[1];
972 TPMS_AUTH_RESPONSE
*session_data_rsp_array
[1];
974 /* get size of NV object */
975 rval
= Tss2_Sys_NV_ReadPublic(this->sys_context
, handle
, 0, &nv_public
,
977 if (rval
!= TPM_RC_SUCCESS
)
979 DBG1(DBG_PTS
,"%s Tss2_Sys_NV_ReadPublic failed: 0x%06x", LABEL
, rval
);
982 nv_size
= nv_public
.t
.nvPublic
.dataSize
;
983 *data
= chunk_alloc(nv_size
);
985 /*prepare NV read session */
986 session_data_cmd_array
[0] = &session_data_cmd
;
987 session_data_rsp_array
[0] = &session_data_rsp
;
989 sessions_data_cmd
.cmdAuths
= &session_data_cmd_array
[0];
990 sessions_data_rsp
.rspAuths
= &session_data_rsp_array
[0];
992 sessions_data_cmd
.cmdAuthsCount
= 1;
993 sessions_data_rsp
.rspAuthsCount
= 1;
995 session_data_cmd
.sessionHandle
= TPM_RS_PW
;
996 session_data_cmd
.nonce
.t
.size
= 0;
997 session_data_cmd
.hmac
.t
.size
= 0;
1001 session_data_cmd
.hmac
.t
.size
= min(sizeof(session_data_cmd
.hmac
.t
) - 2,
1003 memcpy(session_data_cmd
.hmac
.t
.buffer
, pin
.ptr
,
1004 session_data_cmd
.hmac
.t
.size
);
1006 *( (uint8_t *)((void *)&session_data_cmd
.sessionAttributes
) ) = 0;
1008 /* read NV data an NV buffer block at a time */
1011 rval
= Tss2_Sys_NV_Read(this->sys_context
, hierarchy
, handle
,
1012 &sessions_data_cmd
, min(nv_size
, MAX_NV_BUFFER_SIZE
),
1013 nv_offset
, &nv_data
, &sessions_data_rsp
);
1015 if (rval
!= TPM_RC_SUCCESS
)
1017 DBG1(DBG_PTS
,"%s Tss2_Sys_NV_Read failed: 0x%06x", LABEL
, rval
);
1021 memcpy(data
->ptr
+ nv_offset
, nv_data
.t
.buffer
, nv_data
.t
.size
);
1022 nv_offset
+= nv_data
.t
.size
;
1023 nv_size
-= nv_data
.t
.size
;
1029 METHOD(tpm_tss_t
, destroy
, void,
1030 private_tpm_tss_tss2_t
*this)
1032 finalize_context(this);
1039 tpm_tss_t
*tpm_tss_tss2_create()
1041 private_tpm_tss_tss2_t
*this;
1046 .get_version
= _get_version
,
1047 .get_version_info
= _get_version_info
,
1048 .generate_aik
= _generate_aik
,
1049 .get_public
= _get_public
,
1050 .read_pcr
= _read_pcr
,
1051 .extend_pcr
= _extend_pcr
,
1054 .get_random
= _get_random
,
1055 .get_data
= _get_data
,
1056 .destroy
= _destroy
,
1060 available
= initialize_tcti_tabrmd_context(this);
1063 available
= initialize_tcti_socket_context(this);
1067 available
= initialize_sys_context(this);
1069 DBG1(DBG_PTS
, "TPM 2.0 via TSS2 %savailable", available
? "" : "not ");
1076 return &this->public;
1079 #else /* TSS_TSS2 */
1081 tpm_tss_t
*tpm_tss_tss2_create()
1086 #endif /* TSS_TSS2 */