You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
149 lines
8.1 KiB
149 lines
8.1 KiB
8 months ago
|
From 4555de31d96745cabd1362aea7ba3b849429e98b Mon Sep 17 00:00:00 2001
|
||
|
From: Dan Streetman <ddstreet@ieee.org>
|
||
|
Date: Fri, 5 May 2023 19:48:14 -0400
|
||
|
Subject: [PATCH] boot/measure: replace TPM PolicyPCR session with calculation
|
||
|
|
||
|
Instead of using a trial policy with a TPM to calculate the measurement hash,
|
||
|
this uses a function to calculate the hash with no TPM needed.
|
||
|
|
||
|
(cherry picked from commit b2efe286587e11e2aa4a6c7e4a2c15da3bb58a2a)
|
||
|
|
||
|
Related: RHEL-16182
|
||
|
---
|
||
|
src/boot/measure.c | 85 +++++++++-------------------------------------
|
||
|
1 file changed, 16 insertions(+), 69 deletions(-)
|
||
|
|
||
|
diff --git a/src/boot/measure.c b/src/boot/measure.c
|
||
|
index 86edf77c52..5ce3049147 100644
|
||
|
--- a/src/boot/measure.c
|
||
|
+++ b/src/boot/measure.c
|
||
|
@@ -718,7 +718,6 @@ static int verb_sign(int argc, char *argv[], void *userdata) {
|
||
|
_cleanup_(pcr_state_free_all) PcrState *pcr_states = NULL;
|
||
|
_cleanup_(EVP_PKEY_freep) EVP_PKEY *privkey = NULL, *pubkey = NULL;
|
||
|
_cleanup_fclose_ FILE *privkeyf = NULL;
|
||
|
- TSS2_RC rc;
|
||
|
size_t n;
|
||
|
int r;
|
||
|
|
||
|
@@ -787,15 +786,6 @@ static int verb_sign(int argc, char *argv[], void *userdata) {
|
||
|
if (r < 0)
|
||
|
return r;
|
||
|
|
||
|
- r = dlopen_tpm2();
|
||
|
- if (r < 0)
|
||
|
- return r;
|
||
|
-
|
||
|
- _cleanup_tpm2_context_ Tpm2Context *c = NULL;
|
||
|
- r = tpm2_context_new(arg_tpm2_device, &c);
|
||
|
- if (r < 0)
|
||
|
- return r;
|
||
|
-
|
||
|
STRV_FOREACH(phase, arg_phase) {
|
||
|
|
||
|
r = measure_phase(pcr_states, n, *phase);
|
||
|
@@ -803,42 +793,8 @@ static int verb_sign(int argc, char *argv[], void *userdata) {
|
||
|
return r;
|
||
|
|
||
|
for (size_t i = 0; i < n; i++) {
|
||
|
- static const TPMT_SYM_DEF symmetric = {
|
||
|
- .algorithm = TPM2_ALG_AES,
|
||
|
- .keyBits.aes = 128,
|
||
|
- .mode.aes = TPM2_ALG_CFB,
|
||
|
- };
|
||
|
PcrState *p = pcr_states + i;
|
||
|
|
||
|
- _cleanup_tpm2_handle_ Tpm2Handle *session = NULL;
|
||
|
- r = tpm2_handle_new(c, &session);
|
||
|
- if (r < 0)
|
||
|
- return r;
|
||
|
-
|
||
|
- rc = sym_Esys_StartAuthSession(
|
||
|
- c->esys_context,
|
||
|
- ESYS_TR_NONE,
|
||
|
- ESYS_TR_NONE,
|
||
|
- ESYS_TR_NONE,
|
||
|
- ESYS_TR_NONE,
|
||
|
- ESYS_TR_NONE,
|
||
|
- NULL,
|
||
|
- TPM2_SE_TRIAL,
|
||
|
- &symmetric,
|
||
|
- TPM2_ALG_SHA256,
|
||
|
- &session->esys_handle);
|
||
|
- if (rc != TSS2_RC_SUCCESS)
|
||
|
- return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
|
||
|
- "Failed to open session in TPM: %s", sym_Tss2_RC_Decode(rc));
|
||
|
-
|
||
|
- /* Generate a single hash value from the PCRs included in our policy. Given that that's
|
||
|
- * exactly one, the calculation is trivial. */
|
||
|
- TPM2B_DIGEST intermediate_digest = {
|
||
|
- .size = SHA256_DIGEST_SIZE,
|
||
|
- };
|
||
|
- assert(sizeof(intermediate_digest.buffer) >= SHA256_DIGEST_SIZE);
|
||
|
- sha256_direct(p->value, p->value_size, intermediate_digest.buffer);
|
||
|
-
|
||
|
int tpmalg = tpm2_hash_alg_from_string(EVP_MD_name(p->md));
|
||
|
if (tpmalg < 0)
|
||
|
return log_error_errno(tpmalg, "Unsupported PCR bank");
|
||
|
@@ -848,29 +804,20 @@ static int verb_sign(int argc, char *argv[], void *userdata) {
|
||
|
tpmalg,
|
||
|
&pcr_selection);
|
||
|
|
||
|
- rc = sym_Esys_PolicyPCR(
|
||
|
- c->esys_context,
|
||
|
- session->esys_handle,
|
||
|
- ESYS_TR_NONE,
|
||
|
- ESYS_TR_NONE,
|
||
|
- ESYS_TR_NONE,
|
||
|
- &intermediate_digest,
|
||
|
- &pcr_selection);
|
||
|
- if (rc != TSS2_RC_SUCCESS)
|
||
|
- return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
|
||
|
- "Failed to push PCR policy into TPM: %s", sym_Tss2_RC_Decode(rc));
|
||
|
-
|
||
|
- _cleanup_(Esys_Freep) TPM2B_DIGEST *pcr_policy_digest = NULL;
|
||
|
- rc = sym_Esys_PolicyGetDigest(
|
||
|
- c->esys_context,
|
||
|
- session->esys_handle,
|
||
|
- ESYS_TR_NONE,
|
||
|
- ESYS_TR_NONE,
|
||
|
- ESYS_TR_NONE,
|
||
|
- &pcr_policy_digest);
|
||
|
- if (rc != TSS2_RC_SUCCESS)
|
||
|
- return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
|
||
|
- "Failed to get policy digest from TPM: %s", sym_Tss2_RC_Decode(rc));
|
||
|
+ TPM2B_DIGEST pcr_values = {
|
||
|
+ .size = p->value_size,
|
||
|
+ };
|
||
|
+ assert(sizeof(pcr_values.buffer) >= p->value_size);
|
||
|
+ memcpy_safe(pcr_values.buffer, p->value, p->value_size);
|
||
|
+
|
||
|
+ TPM2B_DIGEST pcr_policy_digest;
|
||
|
+ r = tpm2_digest_init(TPM2_ALG_SHA256, &pcr_policy_digest);
|
||
|
+ if (r < 0)
|
||
|
+ return r;
|
||
|
+
|
||
|
+ r = tpm2_calculate_policy_pcr(&pcr_selection, &pcr_values, 1, &pcr_policy_digest);
|
||
|
+ if (r < 0)
|
||
|
+ return r;
|
||
|
|
||
|
_cleanup_(EVP_MD_CTX_freep) EVP_MD_CTX* mdctx = NULL;
|
||
|
mdctx = EVP_MD_CTX_new();
|
||
|
@@ -881,7 +828,7 @@ static int verb_sign(int argc, char *argv[], void *userdata) {
|
||
|
return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
|
||
|
"Failed to initialize signature context.");
|
||
|
|
||
|
- if (EVP_DigestSignUpdate(mdctx, pcr_policy_digest->buffer, pcr_policy_digest->size) != 1)
|
||
|
+ if (EVP_DigestSignUpdate(mdctx, pcr_policy_digest.buffer, pcr_policy_digest.size) != 1)
|
||
|
return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
|
||
|
"Failed to sign data.");
|
||
|
|
||
|
@@ -913,7 +860,7 @@ static int verb_sign(int argc, char *argv[], void *userdata) {
|
||
|
r = json_build(&bv, JSON_BUILD_OBJECT(
|
||
|
JSON_BUILD_PAIR("pcrs", JSON_BUILD_VARIANT(a)), /* PCR mask */
|
||
|
JSON_BUILD_PAIR("pkfp", JSON_BUILD_HEX(pubkey_fp, pubkey_fp_size)), /* SHA256 fingerprint of public key (DER) used for the signature */
|
||
|
- JSON_BUILD_PAIR("pol", JSON_BUILD_HEX(pcr_policy_digest->buffer, pcr_policy_digest->size)), /* TPM2 policy hash that is signed */
|
||
|
+ JSON_BUILD_PAIR("pol", JSON_BUILD_HEX(pcr_policy_digest.buffer, pcr_policy_digest.size)), /* TPM2 policy hash that is signed */
|
||
|
JSON_BUILD_PAIR("sig", JSON_BUILD_BASE64(sig, ss)))); /* signature data */
|
||
|
if (r < 0)
|
||
|
return log_error_errno(r, "Failed to build JSON object: %m");
|