From 4555de31d96745cabd1362aea7ba3b849429e98b Mon Sep 17 00:00:00 2001 From: Dan Streetman 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");