From bbb9be16572c4fcc31387c3d3bfd628644db4723 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 11 Oct 2022 18:20:14 +0200 Subject: [PATCH] tpm2-util: split out code that extends a PCR from pcrphase This way we can reuse it later outside of pcrphase (cherry picked from commit 15c591d1e2b555070f540cafb1b3d1e564e3410a) Related: RHEL-16182 --- src/boot/pcrphase.c | 42 ++------------------------ src/shared/tpm2-util.c | 67 ++++++++++++++++++++++++++++++++++++++++++ src/shared/tpm2-util.h | 2 ++ 3 files changed, 72 insertions(+), 39 deletions(-) diff --git a/src/boot/pcrphase.c b/src/boot/pcrphase.c index 6e3a564f35..62bdf0ad29 100644 --- a/src/boot/pcrphase.c +++ b/src/boot/pcrphase.c @@ -145,7 +145,6 @@ static int run(int argc, char *argv[]) { const char *word; unsigned pcr_nr; size_t length; - TSS2_RC rc; int r; log_setup(); @@ -214,50 +213,15 @@ static int run(int argc, char *argv[]) { if (strv_isempty(arg_banks)) /* Still none? */ return log_error_errno(SYNTHETIC_ERRNO(ENOENT), "Found a TPM2 without enabled PCR banks. Can't operate."); - TPML_DIGEST_VALUES values = {}; - STRV_FOREACH(bank, arg_banks) { - const EVP_MD *implementation; - int id; - - assert_se(implementation = EVP_get_digestbyname(*bank)); - - if (values.count >= ELEMENTSOF(values.digests)) - return log_error_errno(SYNTHETIC_ERRNO(E2BIG), "Too many banks selected."); - - if ((size_t) EVP_MD_size(implementation) > sizeof(values.digests[values.count].digest)) - return log_error_errno(SYNTHETIC_ERRNO(E2BIG), "Hash result too large for TPM2."); - - id = tpm2_pcr_bank_from_string(EVP_MD_name(implementation)); - if (id < 0) - return log_error_errno(id, "Can't map hash name to TPM2."); - - values.digests[values.count].hashAlg = id; - - if (EVP_Digest(word, length, (unsigned char*) &values.digests[values.count].digest, NULL, implementation, NULL) != 1) - return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to hash word."); - - values.count++; - } - joined = strv_join(arg_banks, ", "); if (!joined) return log_oom(); log_debug("Measuring '%s' into PCR index %u, banks %s.", word, TPM_PCR_INDEX_KERNEL_IMAGE, joined); - rc = sym_Esys_PCR_Extend( - c.esys_context, - ESYS_TR_PCR0 + TPM_PCR_INDEX_KERNEL_IMAGE, /* → PCR 11 */ - ESYS_TR_PASSWORD, - ESYS_TR_NONE, - ESYS_TR_NONE, - &values); - if (rc != TSS2_RC_SUCCESS) - return log_error_errno( - SYNTHETIC_ERRNO(ENOTRECOVERABLE), - "Failed to measure '%s': %s", - word, - sym_Tss2_RC_Decode(rc)); + r = tpm2_extend_bytes(c.esys_context, arg_banks, TPM_PCR_INDEX_KERNEL_IMAGE, word, length); /* → PCR 11 */ + if (r < 0) + return r; log_struct(LOG_INFO, "MESSAGE_ID=" SD_MESSAGE_TPM_PCR_EXTEND_STR, diff --git a/src/shared/tpm2-util.c b/src/shared/tpm2-util.c index 45ece9d1a6..336c681c71 100644 --- a/src/shared/tpm2-util.c +++ b/src/shared/tpm2-util.c @@ -1907,6 +1907,73 @@ int tpm2_find_device_auto( #endif } +#if HAVE_TPM2 +int tpm2_extend_bytes( + ESYS_CONTEXT *c, + char **banks, + unsigned pcr_index, + const void *data, + size_t sz) { + +#if HAVE_OPENSSL + TPML_DIGEST_VALUES values = {}; + TSS2_RC rc; + + assert(c); + assert(data || sz == 0); + + if (pcr_index >= TPM2_PCRS_MAX) + return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Can't measure into unsupported PCR %u, refusing.", pcr_index); + + if (strv_isempty(banks)) + return 0; + + STRV_FOREACH(bank, banks) { + const EVP_MD *implementation; + int id; + + assert_se(implementation = EVP_get_digestbyname(*bank)); + + if (values.count >= ELEMENTSOF(values.digests)) + return log_error_errno(SYNTHETIC_ERRNO(E2BIG), "Too many banks selected."); + + if ((size_t) EVP_MD_size(implementation) > sizeof(values.digests[values.count].digest)) + return log_error_errno(SYNTHETIC_ERRNO(E2BIG), "Hash result too large for TPM2."); + + id = tpm2_pcr_bank_from_string(EVP_MD_name(implementation)); + if (id < 0) + return log_error_errno(id, "Can't map hash name to TPM2."); + + values.digests[values.count].hashAlg = id; + + if (EVP_Digest(data, sz, (unsigned char*) &values.digests[values.count].digest, NULL, implementation, NULL) != 1) + return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to hash word."); + + values.count++; + } + + rc = sym_Esys_PCR_Extend( + c, + ESYS_TR_PCR0 + pcr_index, + ESYS_TR_PASSWORD, + ESYS_TR_NONE, + ESYS_TR_NONE, + &values); + if (rc != TSS2_RC_SUCCESS) + return log_error_errno( + SYNTHETIC_ERRNO(ENOTRECOVERABLE), + "Failed to measure into PCR %u: %s", + pcr_index, + sym_Tss2_RC_Decode(rc)); + + return 0; +#else + return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), + "OpenSSL not supported on this build."); +#endif +} +#endif + int tpm2_parse_pcrs(const char *s, uint32_t *ret) { const char *p = ASSERT_PTR(s); uint32_t mask = 0; diff --git a/src/shared/tpm2-util.h b/src/shared/tpm2-util.h index 6d83281be0..4cab52a949 100644 --- a/src/shared/tpm2-util.h +++ b/src/shared/tpm2-util.h @@ -70,6 +70,8 @@ static inline void Esys_Freep(void *p) { int tpm2_get_good_pcr_banks(ESYS_CONTEXT *c, uint32_t pcr_mask, TPMI_ALG_HASH **ret_banks); int tpm2_get_good_pcr_banks_strv(ESYS_CONTEXT *c, uint32_t pcr_mask, char ***ret); +int tpm2_extend_bytes(ESYS_CONTEXT *c, char **banks, unsigned pcr_index, const void *data, size_t sz); + #else struct tpm2_context; #endif