231 lines
10 KiB
Diff
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,
|