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.
174 lines
6.6 KiB
174 lines
6.6 KiB
6 months ago
|
From bbb9be16572c4fcc31387c3d3bfd628644db4723 Mon Sep 17 00:00:00 2001
|
||
|
From: Lennart Poettering <lennart@poettering.net>
|
||
|
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
|