]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
tpm2-util: split out code that extends a PCR from pcrphase
authorLennart Poettering <lennart@poettering.net>
Tue, 11 Oct 2022 16:20:14 +0000 (18:20 +0200)
committerLennart Poettering <lennart@poettering.net>
Tue, 17 Jan 2023 08:42:16 +0000 (09:42 +0100)
This way we can reuse it later outside of pcrphase

src/boot/pcrphase.c
src/shared/tpm2-util.c
src/shared/tpm2-util.h

index 6e1a6a39f08ec9a231c991c0e42eac3ac9c71f3a..a4aa162801df1eecf7f3a7d196c592f6f97556c1 100644 (file)
@@ -146,7 +146,6 @@ static int run(int argc, char *argv[]) {
         const char *word;
         unsigned pcr_nr;
         size_t length;
-        TSS2_RC rc;
         int r;
 
         log_setup();
@@ -215,50 +214,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,
index abe15b54a8263b770b541db59d4c2ab8959a8bf3..36023c6de257780560cee5547b57d24941092d52 100644 (file)
@@ -1919,6 +1919,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;
index 6d83281be01ffbf60dd64677fc76cdf8991058f1..4cab52a9492ed585455bc87169dd6f637ca1be27 100644 (file)
@@ -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