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",
171 memset(manufacturer
, '\0', sizeof(manufacturer
));
172 memset(vendor_string
, '\0', sizeof(vendor_string
));
174 /* print fixed properties */
175 for (i
= 0; i
< cap_data
.data
.tpmProperties
.count
; i
++)
177 tp
= cap_data
.data
.tpmProperties
.tpmProperty
[i
];
180 case TPM_PT_REVISION
:
186 case TPM_PT_MANUFACTURER
:
187 htoun32(manufacturer
, tp
.value
);
189 case TPM_PT_VENDOR_STRING_1
:
190 case TPM_PT_VENDOR_STRING_2
:
191 case TPM_PT_VENDOR_STRING_3
:
192 case TPM_PT_VENDOR_STRING_4
:
193 offset
= 4 * (tp
.property
- TPM_PT_VENDOR_STRING_1
);
194 htoun32(vendor_string
+ offset
, tp
.value
);
200 DBG2(DBG_PTS
, "%s manufacturer: %s (%s) rev: %05.2f %u", LABEL
, manufacturer
,
201 vendor_string
, (float)revision
/100, year
);
203 /* get supported algorithms */
204 rval
= Tss2_Sys_GetCapability(this->sys_context
, 0, TPM_CAP_ALGS
,
205 0, TPM_PT_ALGORITHM_SET
, &more_data
, &cap_data
, 0);
206 if (rval
!= TPM_RC_SUCCESS
)
208 DBG1(DBG_PTS
, "%s GetCapability failed for TPM_CAP_ALGS: 0x%06x",
213 /* Number of supported algorithms */
214 this->supported_algs_count
= cap_data
.data
.algorithms
.count
;
216 /* store and print supported algorithms */
217 for (i
= 0; i
< this->supported_algs_count
; i
++)
219 alg
= cap_data
.data
.algorithms
.algProperties
[i
].alg
;
220 this->supported_algs
[i
] = alg
;
222 written
= snprintf(pos
, len
, " %N", tpm_alg_id_names
, alg
);
223 if (written
< 0 || written
>= len
)
230 DBG2(DBG_PTS
, "%s algorithms:%s", LABEL
, buf
);
232 /* get supported ECC curves */
233 rval
= Tss2_Sys_GetCapability(this->sys_context
, 0, TPM_CAP_ECC_CURVES
,
234 0, TPM_PT_LOADED_CURVES
, &more_data
, &cap_data
, 0);
235 if (rval
!= TPM_RC_SUCCESS
)
237 DBG1(DBG_PTS
, "%s GetCapability failed for TPM_ECC_CURVES: 0x%06x",
242 /* reset print buffer */
246 /* print supported ECC curves */
247 for (i
= 0; i
< cap_data
.data
.eccCurves
.count
; i
++)
249 written
= snprintf(pos
, len
, " %N", tpm_ecc_curve_names
,
250 cap_data
.data
.eccCurves
.eccCurves
[i
]);
251 if (written
< 0 || written
>= len
)
258 DBG2(DBG_PTS
, "%s ECC curves:%s", LABEL
, buf
);
264 * Initialize TSS2 TCTI TABRMD context
266 static bool initialize_tcti_tabrmd_context(private_tpm_tss_tss2_t
*this)
268 #ifdef TSS2_TCTI_TABRMD
269 size_t tcti_context_size
;
272 /* determine size of tcti context */
273 rval
= tss2_tcti_tabrmd_init(NULL
, &tcti_context_size
);
274 if (rval
!= TSS2_RC_SUCCESS
)
276 DBG1(DBG_PTS
, "%s could not get tcti_context size: 0x%06x",
281 /* allocate and initialize memory for tcti context */
282 this->tcti_context
= (TSS2_TCTI_CONTEXT
*)malloc(tcti_context_size
);
283 memset(this->tcti_context
, 0x00, tcti_context_size
);
285 /* initialize tcti context */
286 rval
= tss2_tcti_tabrmd_init(this->tcti_context
, &tcti_context_size
);
287 if (rval
!= TSS2_RC_SUCCESS
)
289 DBG1(DBG_PTS
, "%s could not get tcti_context: 0x%06x "
290 "via tabrmd interface", LABEL
, rval
);
294 #else /* TSS2_TCTI_TABRMD */
296 #endif /* TSS2_TCTI_TABRMD */
300 * Initialize TSS2 TCTI Socket context
302 static bool initialize_tcti_socket_context(private_tpm_tss_tss2_t
*this)
304 #ifdef TSS2_TCTI_SOCKET
305 size_t tcti_context_size
;
308 TCTI_SOCKET_CONF rm_if_config
= { TCTI_SOCKET_DEFAULT_ADDRESS
,
309 TCTI_SOCKET_DEFAULT_PORT
312 /* determine size of tcti context */
313 rval
= InitSocketTcti(NULL
, &tcti_context_size
, &rm_if_config
, 0);
314 if (rval
!= TSS2_RC_SUCCESS
)
316 DBG1(DBG_PTS
, "%s could not get tcti_context size: 0x%06x",
321 /* allocate memory for tcti context */
322 this->tcti_context
= (TSS2_TCTI_CONTEXT
*)malloc(tcti_context_size
);
324 /* initialize tcti context */
325 rval
= InitSocketTcti(this->tcti_context
, &tcti_context_size
,
327 if (rval
!= TSS2_RC_SUCCESS
)
329 DBG1(DBG_PTS
, "%s could not get tcti_context: 0x%06x "
330 "via socket interface", LABEL
, rval
);
334 #else /* TSS2_TCTI_SOCKET */
336 #endif /* TSS2_TCTI_SOCKET */
340 * Initialize TSS2 Sys context
342 static bool initialize_sys_context(private_tpm_tss_tss2_t
*this)
344 uint32_t sys_context_size
;
347 TSS2_ABI_VERSION abi_version
= { TSSWG_INTEROP
,
348 TSS_SAPI_FIRST_FAMILY
,
349 TSS_SAPI_FIRST_LEVEL
,
350 TSS_SAPI_FIRST_VERSION
353 /* determine size of sys context */
354 sys_context_size
= Tss2_Sys_GetContextSize(0);
356 /* allocate memory for sys context */
357 this->sys_context
= malloc(sys_context_size
);
359 /* initialize sys context */
360 rval
= Tss2_Sys_Initialize(this->sys_context
, sys_context_size
,
361 this->tcti_context
, &abi_version
);
362 if (rval
!= TSS2_RC_SUCCESS
)
364 DBG1(DBG_PTS
, "%s could not get sys_context: 0x%06x",
369 /* get a list of supported algorithms and ECC curves */
370 return get_algs_capability(this);
374 * Finalize TSS context
376 static void finalize_context(private_tpm_tss_tss2_t
*this)
378 if (this->tcti_context
)
380 tss2_tcti_finalize(this->tcti_context
);
381 free(this->tcti_context
);
383 if (this->sys_context
)
385 Tss2_Sys_Finalize(this->sys_context
);
386 free(this->sys_context
);
390 METHOD(tpm_tss_t
, get_version
, tpm_version_t
,
391 private_tpm_tss_tss2_t
*this)
393 return TPM_VERSION_2_0
;
396 METHOD(tpm_tss_t
, get_version_info
, chunk_t
,
397 private_tpm_tss_tss2_t
*this)
403 * read the public key portion of a TSS 2.0 AIK key from NVRAM
405 bool read_public(private_tpm_tss_tss2_t
*this, TPMI_DH_OBJECT handle
,
406 TPM2B_PUBLIC
*public)
410 TPM2B_NAME name
= { { sizeof(TPM2B_NAME
)-2, } };
411 TPM2B_NAME qualified_name
= { { sizeof(TPM2B_NAME
)-2, } };
413 TPMS_AUTH_RESPONSE session_data
;
414 TSS2_SYS_RSP_AUTHS sessions_data
;
415 TPMS_AUTH_RESPONSE
*session_data_array
[1];
417 session_data_array
[0] = &session_data
;
418 sessions_data
.rspAuths
= &session_data_array
[0];
419 sessions_data
.rspAuthsCount
= 1;
421 /* read public key for a given object handle from TPM 2.0 NVRAM */
422 rval
= Tss2_Sys_ReadPublic(this->sys_context
, handle
, 0, public, &name
,
423 &qualified_name
, &sessions_data
);
424 if (rval
!= TPM_RC_SUCCESS
)
426 DBG1(DBG_PTS
, "%s could not read public key from handle 0x%08x: 0x%06x",
427 LABEL
, handle
, rval
);
433 METHOD(tpm_tss_t
, generate_aik
, bool,
434 private_tpm_tss_tss2_t
*this, chunk_t ca_modulus
, chunk_t
*aik_blob
,
435 chunk_t
*aik_pubkey
, chunk_t
*identity_req
)
440 METHOD(tpm_tss_t
, get_public
, chunk_t
,
441 private_tpm_tss_tss2_t
*this, uint32_t handle
)
443 TPM2B_PUBLIC
public = { { 0, } };
444 TPM_ALG_ID sig_alg
, digest_alg
;
445 chunk_t aik_blob
, aik_pubkey
= chunk_empty
;
447 if (!read_public(this, handle
, &public))
452 aik_blob
= chunk_create((u_char
*)&public, sizeof(public));
453 DBG3(DBG_LIB
, "%s AIK public key blob: %B", LABEL
, &aik_blob
);
455 /* convert TSS 2.0 AIK public key blot into PKCS#1 format */
456 switch (public.t
.publicArea
.type
)
460 TPM2B_PUBLIC_KEY_RSA
*rsa
;
461 TPMT_RSA_SCHEME
*scheme
;
462 chunk_t aik_exponent
, aik_modulus
;
464 scheme
= &public.t
.publicArea
.parameters
.rsaDetail
.scheme
;
465 sig_alg
= scheme
->scheme
;
466 digest_alg
= scheme
->details
.anySig
.hashAlg
;
468 rsa
= &public.t
.publicArea
.unique
.rsa
;
469 aik_modulus
= chunk_create(rsa
->t
.buffer
, rsa
->t
.size
);
470 aik_exponent
= chunk_from_chars(0x01, 0x00, 0x01);
472 /* subjectPublicKeyInfo encoding of AIK RSA key */
473 if (!lib
->encoding
->encode(lib
->encoding
, PUBKEY_SPKI_ASN1_DER
,
474 NULL
, &aik_pubkey
, CRED_PART_RSA_MODULUS
, aik_modulus
,
475 CRED_PART_RSA_PUB_EXP
, aik_exponent
, CRED_PART_END
))
477 DBG1(DBG_PTS
, "%s subjectPublicKeyInfo encoding of AIK key "
486 TPMT_ECC_SCHEME
*scheme
;
490 scheme
= &public.t
.publicArea
.parameters
.eccDetail
.scheme
;
491 sig_alg
= scheme
->scheme
;
492 digest_alg
= scheme
->details
.anySig
.hashAlg
;
494 ecc
= &public.t
.publicArea
.unique
.ecc
;
496 /* allocate space for bit string */
497 pos
= asn1_build_object(&ecc_point
, ASN1_BIT_STRING
,
498 2 + ecc
->x
.t
.size
+ ecc
->y
.t
.size
);
499 /* bit string length is a multiple of octets */
501 /* uncompressed ECC point format */
503 /* copy x coordinate of ECC point */
504 memcpy(pos
, ecc
->x
.t
.buffer
, ecc
->x
.t
.size
);
505 pos
+= ecc
->x
.t
.size
;
506 /* copy y coordinate of ECC point */
507 memcpy(pos
, ecc
->y
.t
.buffer
, ecc
->y
.t
.size
);
508 /* subjectPublicKeyInfo encoding of AIK ECC key */
509 aik_pubkey
= asn1_wrap(ASN1_SEQUENCE
, "mm",
510 asn1_wrap(ASN1_SEQUENCE
, "mm",
511 asn1_build_known_oid(OID_EC_PUBLICKEY
),
512 asn1_build_known_oid(ecc
->x
.t
.size
== 32 ?
513 OID_PRIME256V1
: OID_SECT384R1
)),
518 DBG1(DBG_PTS
, "%s unsupported AIK key type", LABEL
);
521 DBG1(DBG_PTS
, "AIK signature algorithm is %N with %N hash",
522 tpm_alg_id_names
, sig_alg
, tpm_alg_id_names
, digest_alg
);
527 * Configure a PCR Selection assuming a maximum of 24 registers
529 static bool init_pcr_selection(private_tpm_tss_tss2_t
*this, uint32_t pcrs
,
530 hash_algorithm_t alg
, TPML_PCR_SELECTION
*pcr_sel
)
535 /* check if hash algorithm is supported by TPM */
536 alg_id
= hash_alg_to_tpm_alg_id(alg
);
537 if (!is_supported_alg(this, alg_id
))
539 DBG1(DBG_PTS
, "%s %N hash algorithm not supported by TPM",
540 LABEL
, hash_algorithm_short_names
, alg
);
544 /* initialize the PCR Selection structure,*/
546 pcr_sel
->pcrSelections
[0].hash
= alg_id
;
547 pcr_sel
->pcrSelections
[0].sizeofSelect
= 3;
548 pcr_sel
->pcrSelections
[0].pcrSelect
[0] = 0;
549 pcr_sel
->pcrSelections
[0].pcrSelect
[1] = 0;
550 pcr_sel
->pcrSelections
[0].pcrSelect
[2] = 0;
552 /* set the selected PCRs */
553 for (pcr
= 0; pcr
< PLATFORM_PCR
; pcr
++)
555 if (pcrs
& (1 << pcr
))
557 pcr_sel
->pcrSelections
[0].pcrSelect
[pcr
/ 8] |= ( 1 << (pcr
% 8) );
563 METHOD(tpm_tss_t
, read_pcr
, bool,
564 private_tpm_tss_tss2_t
*this, uint32_t pcr_num
, chunk_t
*pcr_value
,
565 hash_algorithm_t alg
)
567 TPML_PCR_SELECTION pcr_selection
;
568 TPML_DIGEST pcr_values
;
570 uint32_t pcr_update_counter
, rval
;
571 uint8_t *pcr_value_ptr
;
572 size_t pcr_value_len
;
574 if (pcr_num
>= PLATFORM_PCR
)
576 DBG1(DBG_PTS
, "%s maximum number of supported PCR is %d",
577 LABEL
, PLATFORM_PCR
);
581 if (!init_pcr_selection(this, (1 << pcr_num
), alg
, &pcr_selection
))
586 /* initialize the PCR Digest structure */
587 memset(&pcr_values
, 0, sizeof(TPML_DIGEST
));
589 /* read the PCR value */
590 rval
= Tss2_Sys_PCR_Read(this->sys_context
, 0, &pcr_selection
,
591 &pcr_update_counter
, &pcr_selection
, &pcr_values
, 0);
592 if (rval
!= TPM_RC_SUCCESS
)
594 DBG1(DBG_PTS
, "%s PCR bank could not be read: 0x%60x",
598 pcr_value_ptr
= (uint8_t *)pcr_values
.digests
[0].t
.buffer
;
599 pcr_value_len
= (size_t) pcr_values
.digests
[0].t
.size
;
601 *pcr_value
= chunk_clone(chunk_create(pcr_value_ptr
, pcr_value_len
));
606 METHOD(tpm_tss_t
, extend_pcr
, bool,
607 private_tpm_tss_tss2_t
*this, uint32_t pcr_num
, chunk_t
*pcr_value
,
608 chunk_t data
, hash_algorithm_t alg
)
612 TPML_DIGEST_VALUES digest_values
;
613 TPMS_AUTH_COMMAND session_data_cmd
;
614 TPMS_AUTH_RESPONSE session_data_rsp
;
615 TSS2_SYS_CMD_AUTHS sessions_data_cmd
;
616 TSS2_SYS_RSP_AUTHS sessions_data_rsp
;
617 TPMS_AUTH_COMMAND
*session_data_cmd_array
[1];
618 TPMS_AUTH_RESPONSE
*session_data_rsp_array
[1];
620 session_data_cmd_array
[0] = &session_data_cmd
;
621 session_data_rsp_array
[0] = &session_data_rsp
;
623 sessions_data_cmd
.cmdAuths
= &session_data_cmd_array
[0];
624 sessions_data_rsp
.rspAuths
= &session_data_rsp_array
[0];
626 sessions_data_cmd
.cmdAuthsCount
= 1;
627 sessions_data_rsp
.rspAuthsCount
= 1;
629 session_data_cmd
.sessionHandle
= TPM_RS_PW
;
630 session_data_cmd
.hmac
.t
.size
= 0;
631 session_data_cmd
.nonce
.t
.size
= 0;
633 *( (uint8_t *)((void *)&session_data_cmd
.sessionAttributes
) ) = 0;
635 /* check if hash algorithm is supported by TPM */
636 alg_id
= hash_alg_to_tpm_alg_id(alg
);
637 if (!is_supported_alg(this, alg_id
))
639 DBG1(DBG_PTS
, "%s %N hash algorithm not supported by TPM",
640 LABEL
, hash_algorithm_short_names
, alg
);
644 digest_values
.count
= 1;
645 digest_values
.digests
[0].hashAlg
= alg_id
;
650 if (data
.len
!= HASH_SIZE_SHA1
)
654 memcpy(digest_values
.digests
[0].digest
.sha1
, data
.ptr
,
658 if (data
.len
!= HASH_SIZE_SHA256
)
662 memcpy(digest_values
.digests
[0].digest
.sha256
, data
.ptr
,
666 if (data
.len
!= HASH_SIZE_SHA384
)
670 memcpy(digest_values
.digests
[0].digest
.sha384
, data
.ptr
,
674 if (data
.len
!= HASH_SIZE_SHA512
)
678 memcpy(digest_values
.digests
[0].digest
.sha512
, data
.ptr
,
686 rval
= Tss2_Sys_PCR_Extend(this->sys_context
, pcr_num
, &sessions_data_cmd
,
687 &digest_values
, &sessions_data_rsp
);
688 if (rval
!= TPM_RC_SUCCESS
)
690 DBG1(DBG_PTS
, "%s PCR %02u could not be extended: 0x%06x",
691 LABEL
, pcr_num
, rval
);
695 /* get updated PCR value */
696 return read_pcr(this, pcr_num
, pcr_value
, alg
);
699 METHOD(tpm_tss_t
, quote
, bool,
700 private_tpm_tss_tss2_t
*this, uint32_t aik_handle
, uint32_t pcr_sel
,
701 hash_algorithm_t alg
, chunk_t data
, tpm_quote_mode_t
*quote_mode
,
702 tpm_tss_quote_info_t
**quote_info
, chunk_t
*quote_sig
)
704 chunk_t quoted_chunk
, qualified_signer
, extra_data
, clock_info
,
705 firmware_version
, pcr_select
, pcr_digest
;
706 hash_algorithm_t pcr_digest_alg
;
707 bio_reader_t
*reader
;
710 TPM2B_DATA qualifying_data
;
711 TPML_PCR_SELECTION pcr_selection
;
712 TPM2B_ATTEST quoted
= { { sizeof(TPM2B_ATTEST
)-2, } };
713 TPMT_SIG_SCHEME scheme
;
715 TPMI_ALG_HASH hash_alg
;
716 TPMS_AUTH_COMMAND session_data_cmd
;
717 TPMS_AUTH_RESPONSE session_data_rsp
;
718 TSS2_SYS_CMD_AUTHS sessions_data_cmd
;
719 TSS2_SYS_RSP_AUTHS sessions_data_rsp
;
720 TPMS_AUTH_COMMAND
*session_data_cmd_array
[1];
721 TPMS_AUTH_RESPONSE
*session_data_rsp_array
[1];
723 session_data_cmd_array
[0] = &session_data_cmd
;
724 session_data_rsp_array
[0] = &session_data_rsp
;
726 sessions_data_cmd
.cmdAuths
= &session_data_cmd_array
[0];
727 sessions_data_rsp
.rspAuths
= &session_data_rsp_array
[0];
729 sessions_data_cmd
.cmdAuthsCount
= 1;
730 sessions_data_rsp
.rspAuthsCount
= 1;
732 session_data_cmd
.sessionHandle
= TPM_RS_PW
;
733 session_data_cmd
.hmac
.t
.size
= 0;
734 session_data_cmd
.nonce
.t
.size
= 0;
736 *( (uint8_t *)((void *)&session_data_cmd
.sessionAttributes
) ) = 0;
738 qualifying_data
.t
.size
= data
.len
;
739 memcpy(qualifying_data
.t
.buffer
, data
.ptr
, data
.len
);
741 scheme
.scheme
= TPM_ALG_NULL
;
742 memset(&sig
, 0x00, sizeof(sig
));
745 *quote_mode
= TPM_QUOTE_TPM2
;
747 if (!init_pcr_selection(this, pcr_sel
, alg
, &pcr_selection
))
752 rval
= Tss2_Sys_Quote(this->sys_context
, aik_handle
, &sessions_data_cmd
,
753 &qualifying_data
, &scheme
, &pcr_selection
, "ed
,
754 &sig
, &sessions_data_rsp
);
755 if (rval
!= TPM_RC_SUCCESS
)
757 DBG1(DBG_PTS
,"%s Tss2_Sys_Quote failed: 0x%06x", LABEL
, rval
);
760 quoted_chunk
= chunk_create(quoted
.t
.attestationData
, quoted
.t
.size
);
762 reader
= bio_reader_create(chunk_skip(quoted_chunk
, 6));
763 if (!reader
->read_data16(reader
, &qualified_signer
) ||
764 !reader
->read_data16(reader
, &extra_data
) ||
765 !reader
->read_data (reader
, 17, &clock_info
) ||
766 !reader
->read_data (reader
, 8, &firmware_version
) ||
767 !reader
->read_data (reader
, 10, &pcr_select
) ||
768 !reader
->read_data16(reader
, &pcr_digest
))
770 DBG1(DBG_PTS
, "%s parsing of quoted struct failed", LABEL
);
771 reader
->destroy(reader
);
774 reader
->destroy(reader
);
776 DBG2(DBG_PTS
, "PCR Composite digest: %B", &pcr_digest
);
777 DBG2(DBG_PTS
, "TPM Quote Info: %B", "ed_chunk
);
778 DBG2(DBG_PTS
, "qualifiedSigner: %B", &qualified_signer
);
779 DBG2(DBG_PTS
, "extraData: %B", &extra_data
);
780 DBG2(DBG_PTS
, "clockInfo: %B", &clock_info
);
781 DBG2(DBG_PTS
, "firmwareVersion: %B", &firmware_version
);
782 DBG2(DBG_PTS
, "pcrSelect: %B", &pcr_select
);
784 /* extract signature */
789 *quote_sig
= chunk_clone(
791 sig
.signature
.rsassa
.sig
.t
.buffer
,
792 sig
.signature
.rsassa
.sig
.t
.size
));
793 hash_alg
= sig
.signature
.rsassa
.hash
;
798 case TPM_ALG_ECSCHNORR
:
799 *quote_sig
= chunk_cat("cc",
801 sig
.signature
.ecdsa
.signatureR
.t
.buffer
,
802 sig
.signature
.ecdsa
.signatureR
.t
.size
),
804 sig
.signature
.ecdsa
.signatureS
.t
.buffer
,
805 sig
.signature
.ecdsa
.signatureS
.t
.size
));
806 hash_alg
= sig
.signature
.ecdsa
.hash
;
809 DBG1(DBG_PTS
, "%s unsupported %N signature algorithm",
810 LABEL
, tpm_alg_id_names
, sig
.sigAlg
);
814 DBG2(DBG_PTS
, "PCR digest algorithm is %N", tpm_alg_id_names
, hash_alg
);
815 pcr_digest_alg
= hash_alg_from_tpm_alg_id(hash_alg
);
817 DBG2(DBG_PTS
, "TPM Quote Signature: %B", quote_sig
);
819 /* Create and initialize Quote Info object */
820 *quote_info
= tpm_tss_quote_info_create(*quote_mode
, pcr_digest_alg
,
822 (*quote_info
)->set_tpm2_info(*quote_info
, qualified_signer
, clock_info
,
824 (*quote_info
)->set_version_info(*quote_info
, firmware_version
);
829 METHOD(tpm_tss_t
, sign
, bool,
830 private_tpm_tss_tss2_t
*this, uint32_t hierarchy
, uint32_t handle
,
831 signature_scheme_t scheme
, chunk_t data
, chunk_t pin
, chunk_t
*signature
)
834 hash_algorithm_t hash_alg
;
838 TPM2B_MAX_BUFFER buffer
;
839 TPM2B_DIGEST hash
= { { sizeof(TPM2B_DIGEST
)-2, } };
840 TPMT_TK_HASHCHECK validation
;
841 TPM2B_PUBLIC
public = { { 0, } };
842 TPMT_SIG_SCHEME sig_scheme
;
844 TPMS_AUTH_COMMAND session_data_cmd
;
845 TPMS_AUTH_RESPONSE session_data_rsp
;
846 TSS2_SYS_CMD_AUTHS sessions_data_cmd
;
847 TSS2_SYS_RSP_AUTHS sessions_data_rsp
;
848 TPMS_AUTH_COMMAND
*session_data_cmd_array
[1];
849 TPMS_AUTH_RESPONSE
*session_data_rsp_array
[1];
851 session_data_cmd_array
[0] = &session_data_cmd
;
852 session_data_rsp_array
[0] = &session_data_rsp
;
854 sessions_data_cmd
.cmdAuths
= &session_data_cmd_array
[0];
855 sessions_data_rsp
.rspAuths
= &session_data_rsp_array
[0];
857 sessions_data_cmd
.cmdAuthsCount
= 1;
858 sessions_data_rsp
.rspAuthsCount
= 1;
860 session_data_cmd
.sessionHandle
= TPM_RS_PW
;
861 session_data_cmd
.nonce
.t
.size
= 0;
862 session_data_cmd
.hmac
.t
.size
= 0;
866 session_data_cmd
.hmac
.t
.size
= min(sizeof(session_data_cmd
.hmac
.t
) - 2,
868 memcpy(session_data_cmd
.hmac
.t
.buffer
, pin
.ptr
,
869 session_data_cmd
.hmac
.t
.size
);
871 *( (uint8_t *)((void *)&session_data_cmd
.sessionAttributes
) ) = 0;
873 key_type
= key_type_from_signature_scheme(scheme
);
874 hash_alg
= hasher_from_signature_scheme(scheme
, NULL
);
876 /* Check if hash algorithm is supported by TPM */
877 alg_id
= hash_alg_to_tpm_alg_id(hash_alg
);
878 if (!is_supported_alg(this, alg_id
))
880 DBG1(DBG_PTS
, "%s %N hash algorithm not supported by TPM",
881 LABEL
, hash_algorithm_short_names
, hash_alg
);
886 if (!read_public(this, handle
, &public))
891 if (key_type
== KEY_RSA
&& public.t
.publicArea
.type
== TPM_ALG_RSA
)
893 sig_scheme
.scheme
= TPM_ALG_RSASSA
;
894 sig_scheme
.details
.rsassa
.hashAlg
= alg_id
;
896 else if (key_type
== KEY_ECDSA
&& public.t
.publicArea
.type
== TPM_ALG_ECC
)
898 sig_scheme
.scheme
= TPM_ALG_ECDSA
;
899 sig_scheme
.details
.ecdsa
.hashAlg
= alg_id
;
904 DBG1(DBG_PTS
, "%s signature scheme %N not supported by TPM key",
905 LABEL
, signature_scheme_names
, scheme
);
909 if (data
.len
<= MAX_DIGEST_BUFFER
)
911 memcpy(buffer
.t
.buffer
, data
.ptr
, data
.len
);
912 buffer
.t
.size
= data
.len
;
914 rval
= Tss2_Sys_Hash(this->sys_context
, 0, &buffer
, alg_id
, hierarchy
,
915 &hash
, &validation
, 0);
916 if (rval
!= TPM_RC_SUCCESS
)
918 DBG1(DBG_PTS
,"%s Tss2_Sys_Hash failed: 0x%06x", LABEL
, rval
);
924 TPMI_DH_OBJECT sequence_handle
;
925 TPM2B_AUTH null_auth
;
927 null_auth
.t
.size
= 0;
928 rval
= Tss2_Sys_HashSequenceStart(this->sys_context
, 0, &null_auth
,
929 alg_id
, &sequence_handle
, 0);
930 if (rval
!= TPM_RC_SUCCESS
)
932 DBG1(DBG_PTS
,"%s Tss2_Sys_HashSequenceStart failed: 0x%06x",
939 buffer
.t
.size
= min(data
.len
, MAX_DIGEST_BUFFER
);
940 memcpy(buffer
.t
.buffer
, data
.ptr
, buffer
.t
.size
);
941 data
.ptr
+= buffer
.t
.size
;
942 data
.len
-= buffer
.t
.size
;
944 rval
= Tss2_Sys_SequenceUpdate(this->sys_context
, sequence_handle
,
945 &sessions_data_cmd
, &buffer
, 0);
946 if (rval
!= TPM_RC_SUCCESS
)
948 DBG1(DBG_PTS
,"%s Tss2_Sys_SequenceUpdate failed: 0x%06x",
955 rval
= Tss2_Sys_SequenceComplete(this->sys_context
, sequence_handle
,
956 &sessions_data_cmd
, &buffer
, hierarchy
,
957 &hash
, &validation
, 0);
958 if (rval
!= TPM_RC_SUCCESS
)
960 DBG1(DBG_PTS
,"%s Tss2_Sys_SequenceComplete failed: 0x%06x",
966 rval
= Tss2_Sys_Sign(this->sys_context
, handle
, &sessions_data_cmd
, &hash
,
967 &sig_scheme
, &validation
, &sig
, &sessions_data_rsp
);
968 if (rval
!= TPM_RC_SUCCESS
)
970 DBG1(DBG_PTS
,"%s Tss2_Sys_Sign failed: 0x%06x", LABEL
, rval
);
974 /* extract signature */
977 case SIGN_RSA_EMSA_PKCS1_SHA1
:
978 case SIGN_RSA_EMSA_PKCS1_SHA2_256
:
979 case SIGN_RSA_EMSA_PKCS1_SHA2_384
:
980 case SIGN_RSA_EMSA_PKCS1_SHA2_512
:
981 *signature
= chunk_clone(
983 sig
.signature
.rsassa
.sig
.t
.buffer
,
984 sig
.signature
.rsassa
.sig
.t
.size
));
989 *signature
= chunk_cat("cc",
991 sig
.signature
.ecdsa
.signatureR
.t
.buffer
,
992 sig
.signature
.ecdsa
.signatureR
.t
.size
),
994 sig
.signature
.ecdsa
.signatureS
.t
.buffer
,
995 sig
.signature
.ecdsa
.signatureS
.t
.size
));
997 case SIGN_ECDSA_WITH_SHA256_DER
:
998 case SIGN_ECDSA_WITH_SHA384_DER
:
999 case SIGN_ECDSA_WITH_SHA512_DER
:
1000 *signature
= asn1_wrap(ASN1_SEQUENCE
, "mm",
1003 sig
.signature
.ecdsa
.signatureR
.t
.buffer
,
1004 sig
.signature
.ecdsa
.signatureR
.t
.size
)),
1007 sig
.signature
.ecdsa
.signatureS
.t
.buffer
,
1008 sig
.signature
.ecdsa
.signatureS
.t
.size
)));
1011 DBG1(DBG_PTS
, "%s unsupported %N signature scheme",
1012 LABEL
, signature_scheme_names
, scheme
);
1019 METHOD(tpm_tss_t
, get_random
, bool,
1020 private_tpm_tss_tss2_t
*this, size_t bytes
, uint8_t *buffer
)
1022 size_t len
, random_len
= sizeof(TPM2B_DIGEST
)-2;
1023 TPM2B_DIGEST random
= { { random_len
, } };
1024 uint8_t *pos
= buffer
;
1029 len
= min(bytes
, random_len
);
1031 rval
= Tss2_Sys_GetRandom(this->sys_context
, NULL
, len
, &random
, NULL
);
1032 if (rval
!= TSS2_RC_SUCCESS
)
1034 DBG1(DBG_PTS
,"%s Tss2_Sys_GetRandom failed: 0x%06x", LABEL
, rval
);
1037 memcpy(pos
, random
.t
.buffer
, random
.t
.size
);
1038 pos
+= random
.t
.size
;
1039 bytes
-= random
.t
.size
;
1045 METHOD(tpm_tss_t
, get_data
, bool,
1046 private_tpm_tss_tss2_t
*this, uint32_t hierarchy
, uint32_t handle
,
1047 chunk_t pin
, chunk_t
*data
)
1049 uint16_t nv_size
, nv_offset
= 0;
1052 TPM2B_NAME nv_name
= { { sizeof(TPM2B_NAME
)-2, } };
1053 TPM2B_NV_PUBLIC nv_public
= { { 0, } };
1054 TPM2B_MAX_NV_BUFFER nv_data
= { { sizeof(TPM2B_MAX_NV_BUFFER
)-2, } };
1055 TPMS_AUTH_COMMAND session_data_cmd
;
1056 TPMS_AUTH_RESPONSE session_data_rsp
;
1057 TSS2_SYS_CMD_AUTHS sessions_data_cmd
;
1058 TSS2_SYS_RSP_AUTHS sessions_data_rsp
;
1059 TPMS_AUTH_COMMAND
*session_data_cmd_array
[1];
1060 TPMS_AUTH_RESPONSE
*session_data_rsp_array
[1];
1062 /* get size of NV object */
1063 rval
= Tss2_Sys_NV_ReadPublic(this->sys_context
, handle
, 0, &nv_public
,
1065 if (rval
!= TPM_RC_SUCCESS
)
1067 DBG1(DBG_PTS
,"%s Tss2_Sys_NV_ReadPublic failed: 0x%06x", LABEL
, rval
);
1070 nv_size
= nv_public
.t
.nvPublic
.dataSize
;
1071 *data
= chunk_alloc(nv_size
);
1073 /*prepare NV read session */
1074 session_data_cmd_array
[0] = &session_data_cmd
;
1075 session_data_rsp_array
[0] = &session_data_rsp
;
1077 sessions_data_cmd
.cmdAuths
= &session_data_cmd_array
[0];
1078 sessions_data_rsp
.rspAuths
= &session_data_rsp_array
[0];
1080 sessions_data_cmd
.cmdAuthsCount
= 1;
1081 sessions_data_rsp
.rspAuthsCount
= 1;
1083 session_data_cmd
.sessionHandle
= TPM_RS_PW
;
1084 session_data_cmd
.nonce
.t
.size
= 0;
1085 session_data_cmd
.hmac
.t
.size
= 0;
1089 session_data_cmd
.hmac
.t
.size
= min(sizeof(session_data_cmd
.hmac
.t
) - 2,
1091 memcpy(session_data_cmd
.hmac
.t
.buffer
, pin
.ptr
,
1092 session_data_cmd
.hmac
.t
.size
);
1094 *( (uint8_t *)((void *)&session_data_cmd
.sessionAttributes
) ) = 0;
1096 /* read NV data an NV buffer block at a time */
1099 rval
= Tss2_Sys_NV_Read(this->sys_context
, hierarchy
, handle
,
1100 &sessions_data_cmd
, min(nv_size
, MAX_NV_BUFFER_SIZE
),
1101 nv_offset
, &nv_data
, &sessions_data_rsp
);
1103 if (rval
!= TPM_RC_SUCCESS
)
1105 DBG1(DBG_PTS
,"%s Tss2_Sys_NV_Read failed: 0x%06x", LABEL
, rval
);
1109 memcpy(data
->ptr
+ nv_offset
, nv_data
.t
.buffer
, nv_data
.t
.size
);
1110 nv_offset
+= nv_data
.t
.size
;
1111 nv_size
-= nv_data
.t
.size
;
1117 METHOD(tpm_tss_t
, destroy
, void,
1118 private_tpm_tss_tss2_t
*this)
1120 finalize_context(this);
1127 tpm_tss_t
*tpm_tss_tss2_create()
1129 private_tpm_tss_tss2_t
*this;
1134 .get_version
= _get_version
,
1135 .get_version_info
= _get_version_info
,
1136 .generate_aik
= _generate_aik
,
1137 .get_public
= _get_public
,
1138 .read_pcr
= _read_pcr
,
1139 .extend_pcr
= _extend_pcr
,
1142 .get_random
= _get_random
,
1143 .get_data
= _get_data
,
1144 .destroy
= _destroy
,
1148 available
= initialize_tcti_tabrmd_context(this);
1151 available
= initialize_tcti_socket_context(this);
1155 available
= initialize_sys_context(this);
1157 DBG1(DBG_PTS
, "TPM 2.0 via TSS2 %savailable", available
? "" : "not ");
1164 return &this->public;
1167 #else /* TSS_TSS2 */
1169 tpm_tss_t
*tpm_tss_tss2_create()
1174 #endif /* TSS_TSS2 */