mirror of
https://github.com/systemd/systemd.git
synced 2025-01-10 05:18:17 +03:00
tpm2-util: add generic helpers for sealing/unsealing data
These helpers tpm2_seal_data()/tpm2_unseal_data() are useful for sealing/unsealing data without any further semantics around them. This is different from the existing tpm2_seal()/tpm2_unseal() which seal with a specific policy and serialize in a specific way, as we use it for disk encryption. These new helpers are more generic, they do not serialize in a specific way or imply policy, they are just the core of the sealing/unsealing. (We should look into porting tpm2_seal()/tpm2_unseal() onto these new helpers, but this isn#t trivial, since the classic serialization we use uses a merged marshalling of private/public key, which we'd have to change in one way or another)
This commit is contained in:
parent
48d060564a
commit
ce80da02b8
@ -4919,6 +4919,131 @@ int tpm2_undefine_policy_nv_index(
|
||||
log_debug("Undefined NV index 0x%x", nv_index);
|
||||
return 0;
|
||||
}
|
||||
|
||||
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 r;
|
||||
|
||||
assert(c);
|
||||
assert(data);
|
||||
assert(primary_handle);
|
||||
|
||||
/* This is a generic version of tpm2_seal(), that doesn't imply any policy or any specific
|
||||
* combination of the two keypairs in their marshalling. tpm2_seal() is somewhat specific to the FDE
|
||||
* usecase. We probably should migrate tpm2_seal() to use tpm2_seal_data() eventually. */
|
||||
|
||||
if (data->iov_len >= sizeof_field(TPMS_SENSITIVE_CREATE, data.buffer))
|
||||
return -E2BIG;
|
||||
|
||||
TPMT_PUBLIC hmac_template = {
|
||||
.type = TPM2_ALG_KEYEDHASH,
|
||||
.nameAlg = TPM2_ALG_SHA256,
|
||||
.objectAttributes = TPMA_OBJECT_FIXEDTPM | TPMA_OBJECT_FIXEDPARENT,
|
||||
.parameters.keyedHashDetail.scheme.scheme = TPM2_ALG_NULL,
|
||||
.unique.keyedHash.size = data->iov_len,
|
||||
.authPolicy = policy ? *policy : TPM2B_DIGEST_MAKE(NULL, TPM2_SHA256_DIGEST_SIZE),
|
||||
};
|
||||
|
||||
TPMS_SENSITIVE_CREATE hmac_sensitive = {
|
||||
.data.size = hmac_template.unique.keyedHash.size,
|
||||
};
|
||||
|
||||
CLEANUP_ERASE(hmac_sensitive);
|
||||
|
||||
memcpy_safe(hmac_sensitive.data.buffer, data->iov_base, data->iov_len);
|
||||
|
||||
_cleanup_(Esys_Freep) TPM2B_PUBLIC *public = NULL;
|
||||
_cleanup_(Esys_Freep) TPM2B_PRIVATE *private = NULL;
|
||||
r = tpm2_create(c, primary_handle, encryption_session, &hmac_template, &hmac_sensitive, &public, &private);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
_cleanup_(iovec_done) struct iovec public_blob = {}, private_blob = {};
|
||||
|
||||
r = tpm2_marshal_private(private, &private_blob.iov_base, &private_blob.iov_len);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = tpm2_marshal_public(public, &public_blob.iov_base, &public_blob.iov_len);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (ret_public)
|
||||
*ret_public = TAKE_STRUCT(public_blob);
|
||||
if (ret_private)
|
||||
*ret_private = TAKE_STRUCT(private_blob);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tpm2_unseal_data(
|
||||
Tpm2Context *c,
|
||||
const struct iovec *public_blob,
|
||||
const struct iovec *private_blob,
|
||||
const Tpm2Handle *primary_handle,
|
||||
const Tpm2Handle *policy_session,
|
||||
const Tpm2Handle *encryption_session,
|
||||
struct iovec *ret_data) {
|
||||
|
||||
TSS2_RC rc;
|
||||
int r;
|
||||
|
||||
assert(c);
|
||||
assert(public_blob);
|
||||
assert(private_blob);
|
||||
assert(primary_handle);
|
||||
|
||||
TPM2B_PUBLIC public;
|
||||
r = tpm2_unmarshal_public(public_blob->iov_base, public_blob->iov_len, &public);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
TPM2B_PRIVATE private;
|
||||
r = tpm2_unmarshal_private(private_blob->iov_base, private_blob->iov_len, &private);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
_cleanup_(tpm2_handle_freep) Tpm2Handle *what = NULL;
|
||||
r = tpm2_load(c, primary_handle, NULL, &public, &private, &what);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
_cleanup_(Esys_Freep) TPM2B_SENSITIVE_DATA* unsealed = NULL;
|
||||
rc = sym_Esys_Unseal(
|
||||
c->esys_context,
|
||||
what->esys_handle,
|
||||
policy_session ? policy_session->esys_handle : ESYS_TR_NONE,
|
||||
encryption_session ? encryption_session->esys_handle : ESYS_TR_NONE,
|
||||
ESYS_TR_NONE,
|
||||
&unsealed);
|
||||
if (rc == TPM2_RC_PCR_CHANGED)
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(ESTALE),
|
||||
"PCR changed while unsealing.");
|
||||
if (rc != TSS2_RC_SUCCESS)
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
|
||||
"Failed to unseal data: %s", sym_Tss2_RC_Decode(rc));
|
||||
|
||||
_cleanup_(iovec_done) struct iovec d = {};
|
||||
d = (struct iovec) {
|
||||
.iov_base = memdup(unsealed->buffer, unsealed->size),
|
||||
.iov_len = unsealed->size,
|
||||
};
|
||||
|
||||
explicit_bzero_safe(unsealed->buffer, unsealed->size);
|
||||
|
||||
if (!d.iov_base)
|
||||
return log_oom_debug();
|
||||
|
||||
*ret_data = TAKE_STRUCT(d);
|
||||
return 0;
|
||||
}
|
||||
#endif /* HAVE_TPM2 */
|
||||
|
||||
int tpm2_list_devices(void) {
|
||||
|
@ -238,6 +238,9 @@ int tpm2_define_policy_nv_index(Tpm2Context *c, const Tpm2Handle *session, TPM2_
|
||||
int tpm2_write_policy_nv_index(Tpm2Context *c, const Tpm2Handle *policy_session, TPM2_HANDLE nv_index, const Tpm2Handle *nv_handle, const TPM2B_DIGEST *policy_digest);
|
||||
int tpm2_undefine_policy_nv_index(Tpm2Context *c, const Tpm2Handle *session, TPM2_HANDLE nv_index, const Tpm2Handle *nv_handle);
|
||||
|
||||
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_deserialize(Tpm2Context *c, const void *serialized, size_t serialized_size, Tpm2Handle **ret_handle);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user