From: Chris Coulson Date: Mon, 1 Jun 2026 12:27:15 +0000 (+0100) Subject: shared/tpm2: split the tpm2_index_to_handle helper function X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5e7f94a23f23b6f904db71db12dca2ae472389e3;p=thirdparty%2Fsystemd.git shared/tpm2: split the tpm2_index_to_handle helper function The existing tpm2_index_to_handle helper has optional return arguments for an object's public area and its qualified name. However, it can also be called for handles corresponding to NV indexes, where the public area and qualified name don't apply. I'm working on another change that would benefit from having an equivalent helper for NV indexes, and there is already some code in shared/tpm2-util.c that could use this as well. This splits the existing tpm2_index_to_handle function into 3 functions: - tpm2_index_to_handle, which works for both objects and NV indexes and returns a name and handle. - tpm2_object_index_to_handle, which works the same as the existing function for transient or persistent objects, returning a public area, name, qualified name and handle. - tpm2_nv_index_to_handle, which works for NV indexes, returning the NV public area, name and handle. --- diff --git a/src/shared/tpm2-util.c b/src/shared/tpm2-util.c index d718824376b..cdc7712c1a4 100644 --- a/src/shared/tpm2-util.c +++ b/src/shared/tpm2-util.c @@ -1143,6 +1143,33 @@ static int tpm2_read_public( return 0; } +static int tpm2_read_nv_public( + Tpm2Context *c, + const Tpm2Handle *session, + const Tpm2Handle *handle, + TPM2B_NV_PUBLIC **ret_nv_public, + TPM2B_NAME **ret_name) { + + TSS2_RC rc; + + assert(c); + assert(handle); + + rc = sym_Esys_NV_ReadPublic( + c->esys_context, + handle->esys_handle, + session ? session->esys_handle : ESYS_TR_NONE, + ESYS_TR_NONE, + ESYS_TR_NONE, + ret_nv_public, + ret_name); + if (rc != TSS2_RC_SUCCESS) + return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), + "Failed to read NV public info: %s", sym_Tss2_RC_Decode(rc)); + + return 0; +} + /* Create a Tpm2Handle object that references a pre-existing handle in the TPM, at the handle index provided. * This should be used only for persistent, transient, or NV handles; and the handle must already exist in * the TPM at the specified handle index. The handle index should not be 0. Returns 1 if found, 0 if the @@ -1152,9 +1179,7 @@ int tpm2_index_to_handle( Tpm2Context *c, TPM2_HANDLE index, const Tpm2Handle *session, - TPM2B_PUBLIC **ret_public, TPM2B_NAME **ret_name, - TPM2B_NAME **ret_qname, Tpm2Handle **ret_handle) { TSS2_RC rc; @@ -1195,12 +1220,8 @@ int tpm2_index_to_handle( return r; if (r == 0) { log_debug("TPM handle 0x%08" PRIx32 " not populated.", index); - if (ret_public) - *ret_public = NULL; if (ret_name) *ret_name = NULL; - if (ret_qname) - *ret_qname = NULL; if (ret_handle) *ret_handle = NULL; return 0; @@ -1227,12 +1248,109 @@ int tpm2_index_to_handle( return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to read public info: %s", sym_Tss2_RC_Decode(rc)); - if (ret_public || ret_name || ret_qname) { - r = tpm2_read_public(c, session, handle, ret_public, ret_name, ret_qname); + if (ret_name) { + r = tpm2_get_name(c, handle, ret_name); + if (r < 0) + return r; + } + + if (ret_handle) + *ret_handle = TAKE_PTR(handle); + + return 1; +} + +/* Create a Tpm2Handle object that references a pre-existing persistent or transient object in the TPM, at + * the handle index provided. The handle index should not be 0. Returns 1 if found, 0 if the index is empty, + * or < 0 on error. Also see tpm2_get_srk() below; the SRK is a commonly used persistent Tpm2Handle. */ +int tpm2_object_index_to_handle( + Tpm2Context *c, + TPM2_HANDLE index, + const Tpm2Handle *session, + TPM2B_PUBLIC **ret_public, + TPM2B_NAME **ret_name, + TPM2B_NAME **ret_qname, + Tpm2Handle **ret_handle) { + + int r; + + assert(c); + + _cleanup_(tpm2_handle_freep) Tpm2Handle *handle = NULL; + _cleanup_(Esys_Freep) TPM2B_NAME *name = NULL; + r = tpm2_index_to_handle(c, index, session, ret_name ? &name : NULL, &handle); + if (r < 0) + return r; + if (r == 0) { + if (ret_public) + *ret_public = NULL; + if (ret_name) + *ret_name = NULL; + if (ret_qname) + *ret_qname = NULL; + if (ret_handle) + *ret_handle = NULL; + return 0; + } + + if (ret_public || ret_qname) { + sym_Esys_Free(name); + name = NULL; + + r = tpm2_read_public(c, session, handle, ret_public, &name, ret_qname); if (r < 0) return r; } + if (ret_name) + *ret_name = TAKE_PTR(name); + if (ret_handle) + *ret_handle = TAKE_PTR(handle); + + return 1; +} + +/* Create a Tpm2Handle object that references a pre-existing NV index in the TPM, at the handle index + * provided. The handle index should not be 0. Returns 1 if found, 0 if the index is empty, or < 0 on + * error. */ +int tpm2_nv_index_to_handle( + Tpm2Context *c, + TPM2_HANDLE index, + const Tpm2Handle *session, + TPM2B_NV_PUBLIC **ret_nv_public, + TPM2B_NAME **ret_name, + Tpm2Handle **ret_handle) { + + int r; + + assert(c); + + _cleanup_(tpm2_handle_freep) Tpm2Handle *handle = NULL; + _cleanup_(Esys_Freep) TPM2B_NAME *name = NULL; + r = tpm2_index_to_handle(c, index, session, ret_name ? &name : NULL, &handle); + if (r < 0) + return r; + if (r == 0) { + if (ret_nv_public) + *ret_nv_public = NULL; + if (ret_name) + *ret_name = NULL; + if (ret_handle) + *ret_handle = NULL; + return 0; + } + + if (ret_nv_public) { + sym_Esys_Free(name); + name = NULL; + + r = tpm2_read_nv_public(c, session, handle, ret_nv_public, &name); + if (r < 0) + return r; + } + + if (ret_name) + *ret_name = TAKE_PTR(name); if (ret_handle) *ret_handle = TAKE_PTR(handle); @@ -1585,7 +1703,7 @@ int tpm2_get_srk( TPM2B_NAME **ret_qname, Tpm2Handle **ret_handle) { - return tpm2_index_to_handle(c, TPM2_SRK_HANDLE, session, ret_public, ret_name, ret_qname, ret_handle); + return tpm2_object_index_to_handle(c, TPM2_SRK_HANDLE, session, ret_public, ret_name, ret_qname, ret_handle); } /* Get the SRK, creating one if needed. Returns 1 if a new SRK was created and persisted, 0 if an SRK already @@ -5677,7 +5795,7 @@ int tpm2_seal(Tpm2Context *c, if (r < 0) return r; } else if (IN_SET(TPM2_HANDLE_TYPE(seal_key_handle), TPM2_HT_TRANSIENT, TPM2_HT_PERSISTENT)) { - r = tpm2_index_to_handle( + r = tpm2_object_index_to_handle( c, seal_key_handle, /* session= */ NULL, @@ -6298,34 +6416,20 @@ static int tpm2_define_nvpcr_nv_index( new_handle = tpm2_handle_free(new_handle); - r = tpm2_index_to_handle( + _cleanup_(Esys_Freep) TPM2B_NV_PUBLIC *nv_public_real = NULL; + r = tpm2_nv_index_to_handle( c, nv_index, session, - /* ret_public= */ NULL, + &nv_public_real, /* ret_name= */ NULL, - /* ret_qname= */ NULL, &new_handle); - if (r < 0) - return log_debug_errno(r, "Failed to acquire handle to existing NV index 0x%" PRIu32 ".", nv_index); + if (r <= 0) + return log_debug_errno(r < 0 ? r : SYNTHETIC_ERRNO(ENOTRECOVERABLE), + "Failed to acquire handle to existing NV index 0x%" PRIu32 ".", nv_index); log_debug("Successfully acquired handle to existing NV index 0x%" PRIx32 ".", nv_index); - _cleanup_(Esys_Freep) TPM2B_NV_PUBLIC *nv_public_real = NULL; - rc = sym_Esys_NV_ReadPublic( - c->esys_context, - /* nvIndex= */ new_handle->esys_handle, - /* shandle1= */ ESYS_TR_NONE, - /* shandle2= */ ESYS_TR_NONE, - /* shandle3= */ ESYS_TR_NONE, - &nv_public_real, - /* ret_nv_name= */ NULL); - if (rc != TSS2_RC_SUCCESS) - return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), - "Failed read public data of nvindex 0x%x: %s", nv_index, sym_Tss2_RC_Decode(rc)); - - log_debug("Read public info for nvindex 0x%x.", nv_index); - if (nv_public_real->size < endoffsetof_field(TPMS_NV_PUBLIC, attributes) + sizeof_field(TPMS_NV_PUBLIC, dataSize) || nv_public_real->nvPublic.nvIndex != public_info.nvPublic.nvIndex || nv_public_real->nvPublic.nameAlg != public_info.nvPublic.nameAlg || @@ -6404,23 +6508,16 @@ int tpm2_read_nv_index( struct iovec *ret_value) { TPM2_RC rc; + int r; assert(c); assert(nv_index); assert(nv_handle); _cleanup_(Esys_Freep) TPM2B_NV_PUBLIC *nv_public = NULL; - rc = sym_Esys_NV_ReadPublic( - c->esys_context, - /* nvIndex= */ nv_handle->esys_handle, - /* shandle1= */ ESYS_TR_NONE, - /* shandle2= */ ESYS_TR_NONE, - /* shandle3= */ ESYS_TR_NONE, - &nv_public, - /* ret_nv_name= */ NULL); - if (rc != TSS2_RC_SUCCESS) - return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), - "Failed read public data of nvindex 0x%x: %s", nv_index, sym_Tss2_RC_Decode(rc)); + r = tpm2_read_nv_public(c, /* session= */ NULL, nv_handle, &nv_public, /* ret_name= */ NULL); + if (r < 0) + return r; log_debug("Read public info for nvindex 0x%x, value size is %zu", nv_index, (size_t) nv_public->nvPublic.dataSize); @@ -7176,9 +7273,7 @@ int tpm2_nvpcr_extend_bytes( c, p.nv_index, session, - /* ret_public= */ NULL, /* ret_name= */ NULL, - /* ret_qname= */ NULL, &nv_handle); if (r < 0) return log_debug_errno(r, "Failed to acquire handle to NV index 0x%" PRIu32 ".", p.nv_index); @@ -7833,9 +7928,7 @@ int tpm2_nvpcr_read( c, p.nv_index, session, - /* ret_public= */ NULL, /* ret_name= */ NULL, - /* ret_qname= */ NULL, &nv_handle); if (r < 0) return log_debug_errno(r, "Failed to acquire handle to NV index 0x%" PRIu32 ".", p.nv_index); diff --git a/src/shared/tpm2-util.h b/src/shared/tpm2-util.h index 922cc439de9..c5f0ca22eca 100644 --- a/src/shared/tpm2-util.h +++ b/src/shared/tpm2-util.h @@ -304,7 +304,9 @@ int tpm2_pcrlock_search_file(const char *path, FILE **ret_file, char **ret_path) int tpm2_pcrlock_policy_load(const char *path, Tpm2PCRLockPolicy *ret_policy); int tpm2_pcrlock_policy_from_credentials(const struct iovec *srk, const struct iovec *nv, Tpm2PCRLockPolicy *ret); -int tpm2_index_to_handle(Tpm2Context *c, TPM2_HANDLE index, const Tpm2Handle *session, TPM2B_PUBLIC **ret_public, TPM2B_NAME **ret_name, TPM2B_NAME **ret_qname, Tpm2Handle **ret_handle); +int tpm2_index_to_handle(Tpm2Context *c, TPM2_HANDLE index, const Tpm2Handle *session, TPM2B_NAME **ret_name, Tpm2Handle **ret_handle); +int tpm2_object_index_to_handle(Tpm2Context *c, TPM2_HANDLE index, const Tpm2Handle *session, TPM2B_PUBLIC **ret_public, TPM2B_NAME **ret_name, TPM2B_NAME **ret_qname, Tpm2Handle **ret_handle); +int tpm2_nv_index_to_handle(Tpm2Context *c, TPM2_HANDLE index, const Tpm2Handle *session, TPM2B_NV_PUBLIC **ret_nv_public, TPM2B_NAME **ret_name, Tpm2Handle **ret_handle); int tpm2_index_from_handle(Tpm2Context *c, const Tpm2Handle *handle, TPM2_HANDLE *ret_index); int tpm2_pcr_read(Tpm2Context *c, const TPML_PCR_SELECTION *pcr_selection, Tpm2PCRValue **ret_pcr_values, size_t *ret_n_pcr_values);