systemd/0527-tpm2-use-tpm2_policy_a...

231 lines
10 KiB
Diff

From dc66857abd6ffdf6414d54b8e95f1da594b7317e Mon Sep 17 00:00:00 2001
From: Dan Streetman <ddstreet@ieee.org>
Date: Thu, 9 Feb 2023 10:04:58 -0500
Subject: [PATCH] tpm2: use tpm2_policy_authorize()
This updates the function to build the sealing policy to use the dedicated
function to perform PolicyAuthorize.
This is separate from the previous commit to make each commit easier to read.
(cherry picked from commit 524cef3ff5e52ab8683a5c95c519d598dd3d0726)
Related: RHEL-16182
---
src/shared/tpm2-util.c | 154 ++++++++---------------------------------
1 file changed, 29 insertions(+), 125 deletions(-)
diff --git a/src/shared/tpm2-util.c b/src/shared/tpm2-util.c
index 4be07d8944..2747cf0b53 100644
--- a/src/shared/tpm2-util.c
+++ b/src/shared/tpm2-util.c
@@ -2268,20 +2268,19 @@ static int tpm2_build_sealing_policy(
const Tpm2Handle *session,
uint32_t hash_pcr_mask,
uint16_t pcr_bank,
- const void *pubkey,
- size_t pubkey_size,
+ const TPM2B_PUBLIC *public,
+ const void *fp,
+ size_t fp_size,
uint32_t pubkey_pcr_mask,
JsonVariant *signature_json,
bool use_pin,
TPM2B_DIGEST **ret_policy_digest) {
- TSS2_RC rc;
int r;
assert(c);
assert(session);
- assert(pubkey || pubkey_size == 0);
- assert(pubkey_pcr_mask == 0 || pubkey_size > 0);
+ assert(pubkey_pcr_mask == 0 || public);
log_debug("Building sealing policy.");
@@ -2294,128 +2293,11 @@ static int tpm2_build_sealing_policy(
}
if (pubkey_pcr_mask != 0) {
- _cleanup_free_ void *fp = NULL;
- size_t fp_size = 0;
- TPM2B_PUBLIC pubkey_tpm2;
-
- log_debug("Configuring public key based PCR policy.");
-
- /* Convert the PEM key to TPM2 format */
- r = openssl_pubkey_to_tpm2_pubkey(pubkey, pubkey_size, &pubkey_tpm2, &fp, &fp_size);
- if (r < 0)
- return r;
-
- _cleanup_tpm2_handle_ Tpm2Handle *pubkey_handle = NULL;
- r = tpm2_handle_new(c, &pubkey_handle);
- if (r < 0)
- return r;
-
- rc = sym_Esys_LoadExternal(
- c->esys_context,
- ESYS_TR_NONE,
- ESYS_TR_NONE,
- ESYS_TR_NONE,
- NULL,
- &pubkey_tpm2,
-#if HAVE_TSS2_ESYS3
- /* tpm2-tss >= 3.0.0 requires a ESYS_TR_RH_* constant specifying the requested
- * hierarchy, older versions need TPM2_RH_* instead. */
- ESYS_TR_RH_OWNER,
-#else
- TPM2_RH_OWNER,
-#endif
- &pubkey_handle->esys_handle);
- if (rc != TSS2_RC_SUCCESS)
- return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
- "Failed to load public key into TPM: %s", sym_Tss2_RC_Decode(rc));
-
- /* Acquire the "name" of what we just loaded */
- _cleanup_(Esys_Freep) TPM2B_NAME *pubkey_name = NULL;
- r = tpm2_get_name(c, pubkey_handle, &pubkey_name);
- if (r < 0)
- return r;
-
- /* Put together the PCR policy we want to use */
TPML_PCR_SELECTION pcr_selection;
tpm2_tpml_pcr_selection_from_mask(pubkey_pcr_mask, (TPMI_ALG_HASH)pcr_bank, &pcr_selection);
- _cleanup_(Esys_Freep) TPM2B_DIGEST *approved_policy = NULL;
- r = tpm2_policy_pcr(c, session, &pcr_selection, &approved_policy);
+ r = tpm2_policy_authorize(c, session, &pcr_selection, public, fp, fp_size, signature_json, NULL);
if (r < 0)
return r;
-
- /* When we are unlocking and have a signature, let's pass it to the TPM */
- _cleanup_(Esys_Freep) TPMT_TK_VERIFIED *check_ticket_buffer = NULL;
- const TPMT_TK_VERIFIED *check_ticket;
- if (signature_json) {
- _cleanup_free_ void *signature_raw = NULL;
- size_t signature_size;
-
- r = find_signature(
- signature_json,
- &pcr_selection,
- fp, fp_size,
- approved_policy->buffer,
- approved_policy->size,
- &signature_raw,
- &signature_size);
- if (r < 0)
- return r;
-
- /* TPM2_VerifySignature() will only verify the RSA part of the RSA+SHA256 signature,
- * hence we need to do the SHA256 part ourselves, first */
- TPM2B_DIGEST signature_hash = *approved_policy;
- r = tpm2_digest_rehash(TPM2_ALG_SHA256, &signature_hash);
- if (r < 0)
- return r;
-
- TPMT_SIGNATURE policy_signature = {
- .sigAlg = TPM2_ALG_RSASSA,
- .signature.rsassa = {
- .hash = TPM2_ALG_SHA256,
- .sig.size = signature_size,
- },
- };
- if (signature_size > sizeof(policy_signature.signature.rsassa.sig.buffer))
- return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Signature larger than buffer.");
- memcpy(policy_signature.signature.rsassa.sig.buffer, signature_raw, signature_size);
-
- rc = sym_Esys_VerifySignature(
- c->esys_context,
- pubkey_handle->esys_handle,
- ESYS_TR_NONE,
- ESYS_TR_NONE,
- ESYS_TR_NONE,
- &signature_hash,
- &policy_signature,
- &check_ticket_buffer);
- if (rc != TSS2_RC_SUCCESS)
- return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
- "Failed to validate signature in TPM: %s", sym_Tss2_RC_Decode(rc));
-
- check_ticket = check_ticket_buffer;
- } else {
- /* When enrolling, we pass a NULL ticket */
- static const TPMT_TK_VERIFIED check_ticket_null = {
- .tag = TPM2_ST_VERIFIED,
- .hierarchy = TPM2_RH_OWNER,
- };
-
- check_ticket = &check_ticket_null;
- }
-
- rc = sym_Esys_PolicyAuthorize(
- c->esys_context,
- session->esys_handle,
- ESYS_TR_NONE,
- ESYS_TR_NONE,
- ESYS_TR_NONE,
- approved_policy,
- /* policyRef= */ &(const TPM2B_NONCE) {},
- pubkey_name,
- check_ticket);
- if (rc != TSS2_RC_SUCCESS)
- return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
- "Failed to push Authorize policy into TPM: %s", sym_Tss2_RC_Decode(rc));
}
if (hash_pcr_mask != 0) {
@@ -2516,6 +2398,16 @@ int tpm2_seal(const char *device,
return r;
}
+ TPM2B_PUBLIC pubkey_tpm2, *authorize_key = NULL;
+ _cleanup_free_ void *fp = NULL;
+ size_t fp_size = 0;
+ if (pubkey) {
+ r = openssl_pubkey_to_tpm2_pubkey(pubkey, pubkey_size, &pubkey_tpm2, &fp, &fp_size);
+ if (r < 0)
+ return r;
+ authorize_key = &pubkey_tpm2;
+ }
+
_cleanup_tpm2_handle_ Tpm2Handle *primary = NULL;
r = tpm2_make_primary(c, /* alg = */0, !!ret_srk_buf, &primary_alg, &primary);
if (r < 0)
@@ -2554,7 +2446,8 @@ int tpm2_seal(const char *device,
policy_session,
hash_pcr_mask,
pcr_bank,
- pubkey, pubkey_size,
+ authorize_key,
+ fp, fp_size,
pubkey_pcr_mask,
/* signature_json= */ NULL,
!!pin,
@@ -2820,6 +2713,16 @@ int tpm2_unseal(const char *device,
sym_Tss2_RC_Decode(rc));
}
+ TPM2B_PUBLIC pubkey_tpm2, *authorize_key = NULL;
+ _cleanup_free_ void *fp = NULL;
+ size_t fp_size = 0;
+ if (pubkey) {
+ r = openssl_pubkey_to_tpm2_pubkey(pubkey, pubkey_size, &pubkey_tpm2, &fp, &fp_size);
+ if (r < 0)
+ return r;
+ authorize_key = &pubkey_tpm2;
+ }
+
/*
* if a pin is set for the seal object, use it to bind the session
* key to that object. This prevents active bus interposers from
@@ -2853,7 +2756,8 @@ int tpm2_unseal(const char *device,
policy_session,
hash_pcr_mask,
pcr_bank,
- pubkey, pubkey_size,
+ authorize_key,
+ fp, fp_size,
pubkey_pcr_mask,
signature,
!!pin,