]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
boot/measure: replace TPM PolicyPCR session with calculation
authorDan Streetman <ddstreet@ieee.org>
Fri, 5 May 2023 23:48:14 +0000 (19:48 -0400)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Sat, 27 May 2023 06:50:04 +0000 (08:50 +0200)
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.

src/boot/measure.c

index 9b677a2a4875f02e3aa51e768c099bb689f21bbe..a3b6e4f9df63881bcb34a6f06fd732c22371b4e0 100644 (file)
@@ -733,7 +733,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;
 
@@ -816,15 +815,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);
@@ -832,42 +822,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");
@@ -877,29 +833,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();
@@ -910,7 +857,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.");
 
@@ -942,7 +889,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");