tpm2-util: decouple NvPCR write policy from PolicyAuthorize
Pass the digest of the init branch to the NvPCR define and write policy helpers instead of the PCR public key and policy ref, bundle what is needed to satisfy the init branch into a struct, and split opening the write session into an init and an extend variant. No functional change. This prepares for supporting a second kind of init policy. Signed-off-by: Paul Meyer <katexochen0@gmail.com> (cherry picked from commit 13c417c1faa372a5c7f32d01385f741bc6e5cf57)
This commit is contained in:
committed by
Luca Boccassi
parent
42115775d2
commit
b59d59d71c
+173
-136
@@ -7594,34 +7594,24 @@ int tpm2_write_policy_nv_index(
|
||||
}
|
||||
|
||||
#if HAVE_OPENSSL
|
||||
/* Calculates the write policy of a NvPCR, which is TPM2_PolicyAuthorize OR TPM2_PolicyNvWritten(true),
|
||||
* where the authorized policy is bound to the supplied public key and policy ref. Returns the overall write
|
||||
* policy, and optionally, the PolicyAuthorize branch digest (which the extend path needs later on in order
|
||||
* to reconstruct the PolicyOR). */
|
||||
/* Calculates the write policy of a NvPCR, which is 'init_policy' OR TPM2_PolicyNvWritten(true).
|
||||
* Returns the overall write policy. */
|
||||
static int tpm2_nvpcr_calculate_write_policy(
|
||||
const TPM2B_PUBLIC *public,
|
||||
const char *pubkey_policy_ref,
|
||||
TPM2B_DIGEST *ret_authorize_policy,
|
||||
const TPM2B_DIGEST *init_policy,
|
||||
TPM2B_DIGEST *ret_write_policy) {
|
||||
|
||||
int r;
|
||||
|
||||
assert(public);
|
||||
assert(init_policy);
|
||||
assert(init_policy->size == SHA256_DIGEST_SIZE);
|
||||
assert(ret_write_policy);
|
||||
|
||||
TPM2B_NONCE policy_ref;
|
||||
tpm2_make_policy_ref(pubkey_policy_ref, &policy_ref);
|
||||
|
||||
/* Branch order matters here and must match the reconstruction in tpm2_nvpcr_open_write_session. */
|
||||
/* Branch order matters here and must match the reconstruction in tpm2_nvpcr_policy_or_written(). */
|
||||
TPM2B_DIGEST branches[2] = {
|
||||
TPM2B_DIGEST_MAKE(NULL, SHA256_DIGEST_SIZE), /* PolicyAuthorize branch */
|
||||
*init_policy, /* Init branch */
|
||||
TPM2B_DIGEST_MAKE(NULL, SHA256_DIGEST_SIZE), /* PolicyNvWritten branch */
|
||||
};
|
||||
|
||||
r = tpm2_calculate_policy_authorize(public, &policy_ref, &branches[0]);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = tpm2_calculate_policy_nv_written(/* written_set= */ true, &branches[1]);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -7631,8 +7621,6 @@ static int tpm2_nvpcr_calculate_write_policy(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (ret_authorize_policy)
|
||||
*ret_authorize_policy = branches[0];
|
||||
*ret_write_policy = write_policy;
|
||||
return 0;
|
||||
}
|
||||
@@ -7895,26 +7883,24 @@ static int tpm2_define_nvpcr_nv_index(
|
||||
const Tpm2Handle *session,
|
||||
TPM2_HANDLE nv_index,
|
||||
TPMI_ALG_HASH algorithm,
|
||||
const TPM2B_PUBLIC *public,
|
||||
const char *pubkey_policy_ref,
|
||||
const TPM2B_DIGEST *init_policy,
|
||||
bool orderly,
|
||||
TPM2B_DIGEST *ret_authorize_policy,
|
||||
Tpm2Handle **ret_nv_handle) {
|
||||
|
||||
TSS2_RC rc;
|
||||
int r;
|
||||
|
||||
assert(c);
|
||||
assert(public);
|
||||
assert(init_policy);
|
||||
|
||||
/* Allocates an nvindex to use as a "fake" PCR. We call these "NvPCR" in our codebase. The index is
|
||||
* created to require a policy for writing, so that the first write (which sets TPMA_NV_WRITTEN)
|
||||
* requires a signed PolicyAuthorize authorization, while all subsequent writes can be performed using
|
||||
* a PolicyNvWritten(true) branch without any further authorization. The intention here is that a
|
||||
* NvPCR can only be defined and initialized for as long as the authorized policy can be satisfied
|
||||
* (ie, during an early boot phase). Once the authorized policy can no longer be satisfied (ie, after
|
||||
* the early boot has ended), it is no longer possible to redefine and initialize the same NvPCR in
|
||||
* order to spoof its measurements. */
|
||||
* requires 'init_policy' to be satisfied, while all subsequent writes can be performed using a
|
||||
* PolicyNvWritten(true) branch without any further authorization. The intention here is that a
|
||||
* NvPCR can only be defined and initialized for as long as 'init_policy' can be satisfied (ie,
|
||||
* during an early boot phase). Once it can no longer be satisfied (ie, after the early boot has
|
||||
* ended), it is no longer possible to redefine and initialize the same NvPCR in order to spoof its
|
||||
* measurements. */
|
||||
|
||||
log_debug("Allocating NvPCR index 0x%" PRIx32 ".", nv_index);
|
||||
|
||||
@@ -7936,11 +7922,10 @@ static int tpm2_define_nvpcr_nv_index(
|
||||
"/run/systemd/tpm2-nv-space-exhausted-orderly" :
|
||||
"/run/systemd/tpm2-nv-space-exhausted-non-orderly";
|
||||
|
||||
/* Calculate the write policy, which is TPM2_PolicyAuthorize() OR TPM2_PolicyNvWritten(true). The
|
||||
* PolicyAuthorize() branch is used for the first write, but we need to retain the digest of that so
|
||||
* that we can reconstruct the digests used for the TPM2_PolicyOR() assertion on subsequent writes. */
|
||||
TPM2B_DIGEST authorize_policy, write_policy;
|
||||
r = tpm2_nvpcr_calculate_write_policy(public, pubkey_policy_ref, &authorize_policy, &write_policy);
|
||||
/* Calculate the write policy, which is init_policy OR TPM2_PolicyNvWritten(true). The init_policy
|
||||
* branch is used for the first write and can only be satisfied during early boot. */
|
||||
TPM2B_DIGEST write_policy;
|
||||
r = tpm2_nvpcr_calculate_write_policy(init_policy, &write_policy);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -7973,8 +7958,6 @@ static int tpm2_define_nvpcr_nv_index(
|
||||
|
||||
log_debug("NV index 0x%" PRIx32 " successfully %s for NvPCR.", nv_index, r == 0 ? "reused" : "reallocated");
|
||||
|
||||
if (ret_authorize_policy)
|
||||
*ret_authorize_policy = authorize_policy;
|
||||
if (ret_nv_handle)
|
||||
*ret_nv_handle = TAKE_PTR(handle);
|
||||
|
||||
@@ -8012,8 +7995,6 @@ static int tpm2_define_nvpcr_nv_index(
|
||||
if (rc == TSS2_RC_SUCCESS) {
|
||||
log_debug("NV index 0x%" PRIx32 " successfully allocated for NvPCR.", nv_index);
|
||||
|
||||
if (ret_authorize_policy)
|
||||
*ret_authorize_policy = authorize_policy;
|
||||
if (ret_nv_handle)
|
||||
*ret_nv_handle = TAKE_PTR(new_handle);
|
||||
|
||||
@@ -8041,8 +8022,6 @@ static int tpm2_define_nvpcr_nv_index(
|
||||
|
||||
log_debug("NV index 0x%" PRIx32 " successfully %s for NvPCR.", nv_index, r == 0 ? "reused" : "reallocated");
|
||||
|
||||
if (ret_authorize_policy)
|
||||
*ret_authorize_policy = authorize_policy;
|
||||
if (ret_nv_handle)
|
||||
*ret_nv_handle = TAKE_PTR(handle);
|
||||
|
||||
@@ -8898,9 +8877,9 @@ static int tpm2_nvpcr_load_pcr_public_key(
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Reads the stored PolicyAuthorize branch digest of a previously initialized NvPCR. This is written by
|
||||
/* Reads the stored init policy digest of a previously initialized NvPCR. This is written by
|
||||
* tpm2_nvpcr_initialize() and is needed to reconstruct the TPM2_PolicyOR for runtime extends. */
|
||||
static int tpm2_nvpcr_read_authorize_policy(const char *name, TPM2B_DIGEST *ret) {
|
||||
static int tpm2_nvpcr_read_init_policy(const char *name, TPM2B_DIGEST *ret) {
|
||||
int r;
|
||||
|
||||
assert(name);
|
||||
@@ -8913,82 +8892,137 @@ static int tpm2_nvpcr_read_authorize_policy(const char *name, TPM2B_DIGEST *ret)
|
||||
if (r == -ENOENT)
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(ENETDOWN), "NvPCR '%s' not initialized yet, refusing.", name);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to read NvPCR authorize policy '%s': %m", fname);
|
||||
return log_debug_errno(r, "Failed to read NvPCR init policy '%s': %m", fname);
|
||||
|
||||
_cleanup_free_ void *d = NULL;
|
||||
size_t d_size;
|
||||
r = unhexmem(strstrip(h), &d, &d_size);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to decode NvPCR authorize policy from '%s': %m", fname);
|
||||
return log_debug_errno(r, "Failed to decode NvPCR init policy from '%s': %m", fname);
|
||||
if (d_size != SHA256_DIGEST_SIZE)
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "NvPCR authorize policy in '%s' has unexpected size.", fname);
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "NvPCR init policy in '%s' has unexpected size.", fname);
|
||||
|
||||
*ret = TPM2B_DIGEST_MAKE(d, d_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Opens and executes a policy session that satisfies an NvPCR's write policy, leaving it ready for a
|
||||
* subsequent extend. If 'signature_json' is provided, the PolicyAuthorize branch is used (for the
|
||||
* initializing write that sets TPMA_NV_WRITTEN); otherwise the PolicyNvWritten(true) branch is used (for
|
||||
* all later writes). */
|
||||
static int tpm2_nvpcr_open_write_session(
|
||||
/* Policy reference for the PolicyAuthorize assertion that guards the first write to an NvPCR. */
|
||||
#define NVPCR_INIT_POLICY_REF "initrd"
|
||||
|
||||
/* PCR mask for the policy that guards the first write to an NvPCR. */
|
||||
#define NVPCR_INIT_PCRMASK (UINT32_C(1) << TPM2_PCR_KERNEL_BOOT)
|
||||
|
||||
/* The init policy of an NvPCR, i.e. the branch of its write policy that guards the initializing write,
|
||||
* together with everything needed to satisfy it. */
|
||||
typedef struct NvPCRInitPolicy {
|
||||
TPM2B_DIGEST digest;
|
||||
TPML_PCR_SELECTION pcr_selection;
|
||||
TPM2B_PUBLIC public;
|
||||
struct iovec fingerprint;
|
||||
sd_json_variant *signature_json;
|
||||
} NvPCRInitPolicy;
|
||||
|
||||
static void nvpcr_init_policy_done(NvPCRInitPolicy *p) {
|
||||
assert(p);
|
||||
|
||||
iovec_done(&p->fingerprint);
|
||||
p->signature_json = sd_json_variant_unref(p->signature_json);
|
||||
}
|
||||
|
||||
/* Completes the write policy of an NvPCR in 'session' by submitting PolicyOR('init_policy',
|
||||
* PolicyNvWritten(true)). 'session' must already satisfy one of the two branches. */
|
||||
static int tpm2_nvpcr_policy_or_written(
|
||||
Tpm2Context *c,
|
||||
const TPM2B_PUBLIC *public,
|
||||
const char *pubkey_policy_ref,
|
||||
uint32_t pubkey_pcr_mask,
|
||||
const struct iovec *fingerprint,
|
||||
sd_json_variant *signature_json,
|
||||
const TPM2B_DIGEST *authorize_policy,
|
||||
Tpm2Handle **ret_session) {
|
||||
const Tpm2Handle *session,
|
||||
const TPM2B_DIGEST *init_policy) {
|
||||
|
||||
int r;
|
||||
|
||||
assert(c);
|
||||
assert(authorize_policy);
|
||||
assert(ret_session);
|
||||
|
||||
_cleanup_(tpm2_handle_freep) Tpm2Handle *session = NULL;
|
||||
r = tpm2_make_policy_session(c, /* primary= */ NULL, /* encryption_session= */ NULL, &session);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (signature_json) {
|
||||
assert(public);
|
||||
assert(fingerprint);
|
||||
|
||||
/* Initializing write: satisfy the PolicyAuthorize branch using the signed PCR policy. */
|
||||
TPML_PCR_SELECTION pcr_selection;
|
||||
tpm2_tpml_pcr_selection_from_mask(pubkey_pcr_mask, TPM2_ALG_SHA256, &pcr_selection);
|
||||
|
||||
r = tpm2_policy_authorize(
|
||||
c,
|
||||
session,
|
||||
&pcr_selection,
|
||||
public,
|
||||
pubkey_policy_ref,
|
||||
fingerprint->iov_base, fingerprint->iov_len,
|
||||
signature_json,
|
||||
/* ret_policy_digest= */ NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else {
|
||||
/* Subsequent write: the NvPCR is already written, so the PolicyNvWritten(true) branch can be
|
||||
* satisfied without any authorization. */
|
||||
r = tpm2_policy_nv_written(c, session, /* written_set= */ true, /* ret_policy_digest= */ NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
assert(session);
|
||||
assert(init_policy);
|
||||
|
||||
/* Branch order must match tpm2_nvpcr_calculate_write_policy(). */
|
||||
TPM2B_DIGEST branches[2] = {
|
||||
*authorize_policy,
|
||||
*init_policy, /* Init branch */
|
||||
TPM2B_DIGEST_MAKE(NULL, SHA256_DIGEST_SIZE), /* PolicyNvWritten branch */
|
||||
};
|
||||
r = tpm2_calculate_policy_nv_written(/* written_set= */ true, &branches[1]);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = tpm2_policy_or(c, session, branches, ELEMENTSOF(branches), /* ret_policy_digest= */ NULL);
|
||||
return tpm2_policy_or(c, session, branches, ELEMENTSOF(branches), /* ret_policy_digest= */ NULL);
|
||||
}
|
||||
|
||||
/* Opens a policy session that satisfies the init branch of an NvPCR's write policy, for the initializing
|
||||
* write that sets TPMA_NV_WRITTEN. */
|
||||
static int tpm2_nvpcr_open_init_session(
|
||||
Tpm2Context *c,
|
||||
const NvPCRInitPolicy *init,
|
||||
Tpm2Handle **ret_session) {
|
||||
|
||||
_cleanup_(tpm2_handle_freep) Tpm2Handle *session = NULL;
|
||||
TPML_PCR_SELECTION pcr_selection;
|
||||
int r;
|
||||
|
||||
assert(c);
|
||||
assert(init);
|
||||
assert(iovec_is_set(&init->fingerprint));
|
||||
assert(init->signature_json);
|
||||
assert(ret_session);
|
||||
|
||||
r = tpm2_make_policy_session(c, /* primary= */ NULL, /* encryption_session= */ NULL, &session);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* tpm2_policy_authorize() takes a non-const selection. */
|
||||
pcr_selection = init->pcr_selection;
|
||||
|
||||
/* Satisfy the PolicyAuthorize branch using the signed PCR policy. */
|
||||
r = tpm2_policy_authorize(
|
||||
c,
|
||||
session,
|
||||
&pcr_selection,
|
||||
&init->public,
|
||||
NVPCR_INIT_POLICY_REF,
|
||||
init->fingerprint.iov_base, init->fingerprint.iov_len,
|
||||
init->signature_json,
|
||||
/* ret_policy_digest= */ NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = tpm2_nvpcr_policy_or_written(c, session, &init->digest);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*ret_session = TAKE_PTR(session);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Opens a policy session that satisfies the PolicyNvWritten(true) branch of an NvPCR's write policy, for all
|
||||
* writes after the initializing one. 'init_policy' is the digest of the init branch, needed for the
|
||||
* PolicyOR. */
|
||||
static int tpm2_nvpcr_open_extend_session(
|
||||
Tpm2Context *c,
|
||||
const TPM2B_DIGEST *init_policy,
|
||||
Tpm2Handle **ret_session) {
|
||||
|
||||
_cleanup_(tpm2_handle_freep) Tpm2Handle *session = NULL;
|
||||
int r;
|
||||
|
||||
assert(c);
|
||||
assert(init_policy);
|
||||
assert(ret_session);
|
||||
|
||||
r = tpm2_make_policy_session(c, /* primary= */ NULL, /* encryption_session= */ NULL, &session);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = tpm2_policy_nv_written(c, session, /* written_set= */ true, /* ret_policy_digest= */ NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = tpm2_nvpcr_policy_or_written(c, session, init_policy);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -9028,10 +9062,10 @@ static int nvpcr_extend_bytes(
|
||||
* and our measurement and change either */
|
||||
log_fd = tpm2_userspace_log_open();
|
||||
|
||||
/* Read the stored PolicyAuthorize branch digest. Its presence also tells us this NvPCR has been
|
||||
/* Read the stored init policy digest. Its presence also tells us this NvPCR has been
|
||||
* initialized; we need it to reconstruct the TPM2_PolicyOR below. */
|
||||
TPM2B_DIGEST authorize_policy;
|
||||
r = tpm2_nvpcr_read_authorize_policy(name, &authorize_policy);
|
||||
TPM2B_DIGEST init_policy;
|
||||
r = tpm2_nvpcr_read_init_policy(name, &init_policy);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -9078,15 +9112,7 @@ static int nvpcr_extend_bytes(
|
||||
/* Open a policy session that satisfies the write policy via the PolicyNvWritten(true) branch
|
||||
* (the index was already written during initialization). */
|
||||
_cleanup_(tpm2_handle_freep) Tpm2Handle *policy_session = NULL;
|
||||
r = tpm2_nvpcr_open_write_session(
|
||||
c,
|
||||
/* public= */ NULL,
|
||||
/* pubkey_policy_ref= */ NULL,
|
||||
/* pubkey_pcr_mask= */ 0,
|
||||
/* fingerprint= */ NULL,
|
||||
/* signature_json= */ NULL,
|
||||
&authorize_policy,
|
||||
&policy_session);
|
||||
r = tpm2_nvpcr_open_extend_session(c, &init_policy, &policy_session);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -9191,15 +9217,35 @@ static int tpm2_context_can_nvindex(Tpm2Context *c) {
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Policy reference for the PolicyAuthorize assertion that guards the first write to an NvPCR. */
|
||||
#define NVPCR_INIT_POLICY_REF "initrd"
|
||||
|
||||
/* PCR mask for the policy that guards the first write to an NvPCR, via the signed policy and PolicyAuthorize. */
|
||||
#define NVPCR_PUBKEY_PCRMASK (UINT32_C(1) << TPM2_PCR_KERNEL_BOOT)
|
||||
|
||||
/* The maximum number of times to try initializing a NvPCR before failing if PCR values change under our feet. */
|
||||
#define RETRY_NVPCR_INIT_MAX 30u
|
||||
|
||||
#if HAVE_OPENSSL
|
||||
/* Calculate the init policy for an NvPCR protected by a signed PCR policy:
|
||||
* PolicyAuthorize is bound to 'public' and the "initrd" policy reference. */
|
||||
static int tpm2_nvpcr_calculate_signed_init_policy(
|
||||
const TPM2B_PUBLIC *public,
|
||||
TPM2B_DIGEST *ret) {
|
||||
|
||||
TPM2B_NONCE policy_ref;
|
||||
TPM2B_DIGEST init_policy;
|
||||
int r;
|
||||
|
||||
assert(public);
|
||||
assert(ret);
|
||||
|
||||
tpm2_make_policy_ref(NVPCR_INIT_POLICY_REF, &policy_ref);
|
||||
|
||||
init_policy = TPM2B_DIGEST_MAKE(NULL, SHA256_DIGEST_SIZE);
|
||||
r = tpm2_calculate_policy_authorize(public, &policy_ref, &init_policy);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*ret = init_policy;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int tpm2_nvpcr_initialize(
|
||||
Tpm2Context *c,
|
||||
const Tpm2Handle *session,
|
||||
@@ -9269,11 +9315,11 @@ int tpm2_nvpcr_initialize(
|
||||
if ((size_t) digest_size > sizeof_field(TPM2B_MAX_NV_BUFFER, buffer))
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(E2BIG), "Hash function result too large for TPM, refusing.");
|
||||
|
||||
_cleanup_(nvpcr_init_policy_done) NvPCRInitPolicy init = {};
|
||||
|
||||
/* Load the PCR public key. Its signatures authorize the initializing write to the NvPCR via the
|
||||
* PolicyAuthorize branch of the write policy. */
|
||||
TPM2B_PUBLIC public;
|
||||
_cleanup_(iovec_done) struct iovec fingerprint = {};
|
||||
r = tpm2_nvpcr_load_pcr_public_key(/* path= */ NULL, &public, &fingerprint);
|
||||
r = tpm2_nvpcr_load_pcr_public_key(/* path= */ NULL, &init.public, &init.fingerprint);
|
||||
if (r == -ENOENT)
|
||||
/* Avoid failing systemd-tpm2-setup if there is no PCR public key attached to the UKI. */
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(ENOKEY),
|
||||
@@ -9282,8 +9328,7 @@ int tpm2_nvpcr_initialize(
|
||||
return r;
|
||||
|
||||
/* Load the signed PCR policy, which authorizes the initializing write. */
|
||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *signature_json = NULL;
|
||||
r = tpm2_load_pcr_signature(/* path= */ NULL, &signature_json);
|
||||
r = tpm2_load_pcr_signature(/* path= */ NULL, &init.signature_json);
|
||||
if (r == -ENOENT)
|
||||
/* Avoid failing systemd-tpm2-setup if there are no PCR signatures attached to the UKI. */
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(ENOKEY),
|
||||
@@ -9296,12 +9341,11 @@ int tpm2_nvpcr_initialize(
|
||||
* policy reference. We don't check the policy digest here: if there is a matching policy but it doesn't
|
||||
* match the current PCR state, or its signature is invalid, then that's a real error which we
|
||||
* want to report below. */
|
||||
TPML_PCR_SELECTION pcr_selection;
|
||||
tpm2_tpml_pcr_selection_from_mask(NVPCR_PUBKEY_PCRMASK, TPM2_ALG_SHA256, &pcr_selection);
|
||||
tpm2_tpml_pcr_selection_from_mask(NVPCR_INIT_PCRMASK, TPM2_ALG_SHA256, &init.pcr_selection);
|
||||
r = find_signature(
|
||||
signature_json,
|
||||
&pcr_selection,
|
||||
fingerprint.iov_base, fingerprint.iov_len,
|
||||
init.signature_json,
|
||||
&init.pcr_selection,
|
||||
init.fingerprint.iov_base, init.fingerprint.iov_len,
|
||||
NVPCR_INIT_POLICY_REF,
|
||||
/* policy= */ NULL, /* policy_size= */ 0,
|
||||
/* ret_signature= */ NULL, /* ret_signature_size= */ NULL);
|
||||
@@ -9312,17 +9356,18 @@ int tpm2_nvpcr_initialize(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
TPM2B_DIGEST authorize_policy;
|
||||
r = tpm2_nvpcr_calculate_signed_init_policy(&init.public, &init.digest);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
_cleanup_(tpm2_handle_freep) Tpm2Handle *nv_handle = NULL;
|
||||
r = tpm2_define_nvpcr_nv_index(
|
||||
c,
|
||||
session,
|
||||
p.nv_index,
|
||||
p.algorithm,
|
||||
&public,
|
||||
NVPCR_INIT_POLICY_REF,
|
||||
&init.digest,
|
||||
p.orderly,
|
||||
&authorize_policy,
|
||||
&nv_handle);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -9333,15 +9378,7 @@ int tpm2_nvpcr_initialize(
|
||||
for (unsigned i = RETRY_NVPCR_INIT_MAX;; i--) {
|
||||
/* Open a policy session to perform the initializing write. */
|
||||
_cleanup_(tpm2_handle_freep) Tpm2Handle *policy_session = NULL;
|
||||
r = tpm2_nvpcr_open_write_session(
|
||||
c,
|
||||
&public,
|
||||
NVPCR_INIT_POLICY_REF,
|
||||
NVPCR_PUBKEY_PCRMASK,
|
||||
&fingerprint,
|
||||
signature_json,
|
||||
&authorize_policy,
|
||||
&policy_session);
|
||||
r = tpm2_nvpcr_open_init_session(c, &init, &policy_session);
|
||||
if (r == -EUCLEAN) {
|
||||
/* A PCR was extended while we submitted the policy, so this session is unusable.
|
||||
* Same situation as below, just observed while building the policy rather than
|
||||
@@ -9379,9 +9416,9 @@ int tpm2_nvpcr_initialize(
|
||||
break;
|
||||
}
|
||||
|
||||
/* Persist the PolicyAuthorize branch digest. The extend path needs it to reconstruct the
|
||||
/* Persist the init policy digest. The extend path needs it to reconstruct the
|
||||
* TPM2_PolicyOR, and its presence doubles as an indication that this NvPCR is initialized. */
|
||||
_cleanup_free_ char *h = hexmem(authorize_policy.buffer, authorize_policy.size);
|
||||
_cleanup_free_ char *h = hexmem(init.digest.buffer, init.digest.size);
|
||||
if (!h)
|
||||
return log_oom_debug();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user