tpm2-util: add calls for calculating/submitting PolicyAuthorizeNV + PolicyOR TPM2 policies

This commit is contained in:
Lennart Poettering
2023-11-03 11:22:16 +01:00
parent 34657b1f0b
commit 2cd8f75316
2 changed files with 186 additions and 2 deletions
+181 -2
View File
@@ -3438,7 +3438,7 @@ int tpm2_policy_auth_value(
assert(c);
assert(session);
log_debug("Adding authValue policy.");
log_debug("Submitting AuthValue policy.");
rc = sym_Esys_PolicyAuthValue(
c->esys_context,
@@ -3454,6 +3454,185 @@ int tpm2_policy_auth_value(
return tpm2_get_policy_digest(c, session, ret_policy_digest);
}
int tpm2_calculate_policy_authorize_nv(
const TPM2B_NV_PUBLIC *public_info,
TPM2B_DIGEST *digest) {
TPM2_CC command = TPM2_CC_PolicyAuthorizeNV;
TSS2_RC rc;
int r;
assert(public_info);
assert(digest);
assert(digest->size == SHA256_DIGEST_SIZE);
r = dlopen_tpm2();
if (r < 0)
return log_debug_errno(r, "TPM2 support not installed: %m");
uint8_t buf[sizeof(command)];
size_t offset = 0;
rc = sym_Tss2_MU_TPM2_CC_Marshal(command, buf, sizeof(buf), &offset);
if (rc != TSS2_RC_SUCCESS)
return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
"Failed to marshal PolicyAuthorizeNV command: %s", sym_Tss2_RC_Decode(rc));
if (offset != sizeof(command))
return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
"Offset 0x%zx wrong after marshalling PolicyAuthorizeNV command", offset);
TPM2B_NV_PUBLIC public_info_copy = *public_info; /* Make a copy, since we must set TPMA_NV_WRITTEN for the calculation */
public_info_copy.nvPublic.attributes |= TPMA_NV_WRITTEN;
TPM2B_NAME name = {};
r = tpm2_calculate_nv_index_name(&public_info_copy.nvPublic, &name);
if (r < 0)
return r;
struct iovec data[] = {
IOVEC_MAKE(buf, offset),
IOVEC_MAKE(name.name, name.size),
};
r = tpm2_digest_many(TPM2_ALG_SHA256, digest, data, ELEMENTSOF(data), /* extend= */ true);
if (r < 0)
return r;
tpm2_log_debug_digest(digest, "PolicyAuthorizeNV calculated digest");
return 0;
}
int tpm2_policy_authorize_nv(
Tpm2Context *c,
const Tpm2Handle *session,
const Tpm2Handle *nv_handle,
TPM2B_DIGEST **ret_policy_digest) {
TSS2_RC rc;
assert(c);
assert(session);
log_debug("Submitting AuthorizeNV policy.");
rc = sym_Esys_PolicyAuthorizeNV(
c->esys_context,
ESYS_TR_RH_OWNER,
nv_handle->esys_handle,
session->esys_handle,
ESYS_TR_PASSWORD,
ESYS_TR_NONE,
ESYS_TR_NONE);
if (rc != TSS2_RC_SUCCESS)
return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
"Failed to add AuthorizeNV policy to TPM: %s",
sym_Tss2_RC_Decode(rc));
return tpm2_get_policy_digest(c, session, ret_policy_digest);
}
int tpm2_policy_or(
Tpm2Context *c,
const Tpm2Handle *session,
const TPM2B_DIGEST *branches, size_t n_branches,
TPM2B_DIGEST **ret_policy_digest) {
TPML_DIGEST hash_list;
TSS2_RC rc;
assert(c);
assert(session);
if (n_branches > ELEMENTSOF(hash_list.digests))
return -EOPNOTSUPP;
log_debug("Submitting OR policy.");
hash_list = (TPML_DIGEST) {
.count = n_branches,
};
memcpy(hash_list.digests, branches, n_branches * sizeof(TPM2B_DIGEST));
if (DEBUG_LOGGING)
for (size_t i = 0; i < hash_list.count; i++) {
_cleanup_free_ char *h = hexmem(hash_list.digests[i].buffer, hash_list.digests[i].size);
log_debug("Submitting OR Branch #%zu: %s", i, h);
}
rc = sym_Esys_PolicyOR(
c->esys_context,
session->esys_handle,
ESYS_TR_NONE,
ESYS_TR_NONE,
ESYS_TR_NONE,
&hash_list);
if (rc != TSS2_RC_SUCCESS)
return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
"Failed to add OR policy to TPM: %s",
sym_Tss2_RC_Decode(rc));
return tpm2_get_policy_digest(c, session, ret_policy_digest);
}
/* Extend 'digest' with the PolicyOR calculated hash. */
int tpm2_calculate_policy_or(const TPM2B_DIGEST *branches, size_t n_branches, TPM2B_DIGEST *digest) {
TPM2_CC command = TPM2_CC_PolicyOR;
TSS2_RC rc;
int r;
assert(digest);
assert(digest->size == SHA256_DIGEST_SIZE);
if (n_branches == 0)
return -EINVAL;
if (n_branches == 1)
log_warning("PolicyOR with a single branch submitted, this is weird.");
if (n_branches > 8)
return -E2BIG;
r = dlopen_tpm2();
if (r < 0)
return log_error_errno(r, "TPM2 support not installed: %m");
uint8_t buf[sizeof(command)];
size_t offset = 0;
rc = sym_Tss2_MU_TPM2_CC_Marshal(command, buf, sizeof(buf), &offset);
if (rc != TSS2_RC_SUCCESS)
return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
"Failed to marshal PolicyOR command: %s", sym_Tss2_RC_Decode(rc));
if (offset != sizeof(command))
return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
"Offset 0x%zx wrong after marshalling PolicyOR command", offset);
_cleanup_free_ struct iovec *data = new(struct iovec, 1 + n_branches);
if (!data)
return log_oom();
data[0] = IOVEC_MAKE(buf, offset);
for (size_t i = 0; i < n_branches; i++) {
data[1 + i] = IOVEC_MAKE((void*) branches[i].buffer, branches[i].size);
if (DEBUG_LOGGING) {
_cleanup_free_ char *h = hexmem(branches[i].buffer, branches[i].size);
log_debug("OR Branch #%zu: %s", i, h);
}
}
/* PolicyOR does not use the previous hash value; we must zero and then extend it. */
zero(digest->buffer);
r = tpm2_digest_many(TPM2_ALG_SHA256, digest, data, 1 + n_branches, /* extend= */ true);
if (r < 0)
return r;
tpm2_log_debug_digest(digest, "PolicyOR calculated digest");
return 0;
}
/* Extend 'digest' with the PolicyPCR calculated hash. */
int tpm2_calculate_policy_pcr(
const Tpm2PCRValue *pcr_values,
@@ -3526,7 +3705,7 @@ int tpm2_policy_pcr(
assert(session);
assert(pcr_selection);
log_debug("Adding PCR hash policy.");
log_debug("Submitting PCR hash policy.");
rc = sym_Esys_PolicyPCR(
c->esys_context,
+5
View File
@@ -205,15 +205,20 @@ int tpm2_set_auth(Tpm2Context *c, const Tpm2Handle *handle, const char *pin);
int tpm2_set_auth_binary(Tpm2Context *c, const Tpm2Handle *handle, const TPM2B_AUTH *auth);
int tpm2_make_policy_session(Tpm2Context *c, const Tpm2Handle *primary, const Tpm2Handle *encryption_session, Tpm2Handle **ret_session);
int tpm2_policy_auth_value(Tpm2Context *c, const Tpm2Handle *session, TPM2B_DIGEST **ret_policy_digest);
int tpm2_policy_authorize_nv(Tpm2Context *c, const Tpm2Handle *session, const Tpm2Handle *nv_handle, TPM2B_DIGEST **ret_policy_digest);
int tpm2_policy_pcr(Tpm2Context *c, const Tpm2Handle *session, const TPML_PCR_SELECTION *pcr_selection, TPM2B_DIGEST **ret_policy_digest);
int tpm2_policy_or(Tpm2Context *c, const Tpm2Handle *session, const TPM2B_DIGEST *branches, size_t n_branches, TPM2B_DIGEST **ret_policy_digest);
int tpm2_calculate_pubkey_name(const TPMT_PUBLIC *public, TPM2B_NAME *ret_name);
int tpm2_calculate_nv_index_name(const TPMS_NV_PUBLIC *nvpublic, TPM2B_NAME *ret_name);
int tpm2_calculate_policy_auth_value(TPM2B_DIGEST *digest);
int tpm2_calculate_policy_authorize(const TPM2B_PUBLIC *public, const TPM2B_DIGEST *policy_ref, TPM2B_DIGEST *digest);
int tpm2_calculate_policy_authorize_nv(const TPM2B_NV_PUBLIC *public, TPM2B_DIGEST *digest);
int tpm2_calculate_policy_pcr(const Tpm2PCRValue *pcr_values, size_t n_pcr_values, TPM2B_DIGEST *digest);
int tpm2_calculate_policy_or(const TPM2B_DIGEST *branches, size_t n_branches, TPM2B_DIGEST *digest);
int tpm2_calculate_sealing_policy(const Tpm2PCRValue *pcr_values, size_t n_pcr_values, const TPM2B_PUBLIC *public, bool use_pin, TPM2B_DIGEST *digest);
int tpm2_get_or_create_srk(Tpm2Context *c, const Tpm2Handle *session, TPM2B_PUBLIC **ret_public, TPM2B_NAME **ret_name, TPM2B_NAME **ret_qname, Tpm2Handle **ret_handle);