tpm2-util: copy serialized result in tpm2_serialize()

For safety, though typically Esys_Free() is just a simple wrapper of
free(), but let's do unconditionally. See the comment in the code.

While at it, this makes it store the result into struct iovec.
This commit is contained in:
Yu Watanabe
2025-08-12 06:11:34 +09:00
parent 8d40f3f42e
commit 48d06b99e6
3 changed files with 14 additions and 26 deletions
+2 -2
View File
@@ -4794,13 +4794,13 @@ static int make_policy(bool force, RecoveryPinMode recovery_pin_mode) {
}
if (!iovec_is_set(&nv_blob)) {
r = tpm2_serialize(tc, nv_handle, &nv_blob.iov_base, &nv_blob.iov_len);
r = tpm2_serialize(tc, nv_handle, &nv_blob);
if (r < 0)
return log_error_errno(r, "Failed to serialize NV index TR: %m");
}
if (!iovec_is_set(&srk_blob)) {
r = tpm2_serialize(tc, srk_handle, &srk_blob.iov_base, &srk_blob.iov_len);
r = tpm2_serialize(tc, srk_handle, &srk_blob);
if (r < 0)
return log_error_errno(r, "Failed to serialize SRK index TR: %m");
}
+11 -23
View File
@@ -4579,15 +4579,13 @@ int tpm2_calculate_serialize(
int tpm2_serialize(
Tpm2Context *c,
const Tpm2Handle *handle,
void **ret_serialized,
size_t *ret_serialized_size) {
struct iovec *ret) {
TSS2_RC rc;
assert(c);
assert(handle);
assert(ret_serialized);
assert(ret_serialized_size);
assert(ret);
_cleanup_(Esys_Freep) unsigned char *serialized = NULL;
size_t size = 0;
@@ -4596,9 +4594,15 @@ int tpm2_serialize(
return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
"Failed to serialize: %s", sym_Tss2_RC_Decode(rc));
*ret_serialized = TAKE_PTR(serialized);
*ret_serialized_size = size;
/* Make a copy since we don't want the caller to understand that ESYS allocated the pointer.
* It would make tracking what deallocator to use for the result in which context a PITA. */
struct iovec v;
v.iov_base = memdup(serialized, size);
if (!v.iov_base)
return log_oom_debug();
v.iov_len = size;
*ret = v;
return 0;
}
@@ -5466,25 +5470,9 @@ int tpm2_seal(Tpm2Context *c,
log_debug("Completed TPM2 key sealing in %s.", FORMAT_TIMESPAN(now(CLOCK_MONOTONIC) - start, 1));
if (ret_srk) {
_cleanup_(iovec_done) struct iovec srk = {};
_cleanup_(Esys_Freep) void *tmp = NULL;
size_t tmp_size;
r = tpm2_serialize(c, primary_handle, &tmp, &tmp_size);
r = tpm2_serialize(c, primary_handle, ret_srk);
if (r < 0)
return r;
/*
* make a copy since we don't want the caller to understand that
* ESYS allocated the pointer. It would make tracking what deallocator
* to use for srk in which context a PITA.
*/
srk.iov_base = memdup(tmp, tmp_size);
if (!srk.iov_base)
return log_oom_debug();
srk.iov_len = tmp_size;
*ret_srk = TAKE_STRUCT(srk);
}
*ret_secret = TAKE_STRUCT(secret);
+1 -1
View File
@@ -301,7 +301,7 @@ int tpm2_undefine_policy_nv_index(Tpm2Context *c, const Tpm2Handle *session, TPM
int tpm2_seal_data(Tpm2Context *c, const struct iovec *data, const Tpm2Handle *primary_handle, const Tpm2Handle *encryption_session, const TPM2B_DIGEST *policy, struct iovec *ret_public, struct iovec *ret_private);
int tpm2_unseal_data(Tpm2Context *c, const struct iovec *public, const struct iovec *private, const Tpm2Handle *primary_handle, const Tpm2Handle *policy_session, const Tpm2Handle *encryption_session, struct iovec *ret_data);
int tpm2_serialize(Tpm2Context *c, const Tpm2Handle *handle, void **ret_serialized, size_t *ret_serialized_size);
int tpm2_serialize(Tpm2Context *c, const Tpm2Handle *handle, struct iovec *ret);
int tpm2_deserialize(Tpm2Context *c, const struct iovec *serialized, Tpm2Handle **ret_handle);
int tpm2_load_public_key_file(const char *path, TPM2B_PUBLIC *ret);