]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
tpm2: remove tpm2_make_primary() 27713/head
authorDan Streetman <ddstreet@ieee.org>
Thu, 8 Jun 2023 10:55:45 +0000 (06:55 -0400)
committerDan Streetman <ddstreet@ieee.org>
Wed, 5 Jul 2023 21:39:33 +0000 (17:39 -0400)
Replace use of tpm2_make_primary() with tpm2_create_loaded()

src/shared/tpm2-util.c

index 0b3ef3cb7814f3a50a49fb3ce933710bf0f33765..f7b4520ee43296b52c4b5a6bae83ca8314e7237f 100644 (file)
@@ -1205,156 +1205,6 @@ static int tpm2_get_or_create_srk(
         return 0;
 }
 
-static int tpm2_make_primary(
-                Tpm2Context *c,
-                TPMI_ALG_PUBLIC alg,
-                bool use_srk_model,
-                TPMI_ALG_PUBLIC *ret_alg,
-                Tpm2Handle **ret_primary) {
-
-        static const TPM2B_SENSITIVE_CREATE primary_sensitive = {};
-        static const TPML_PCR_SELECTION creation_pcr = {};
-        TPM2B_PUBLIC primary_template = { .size = sizeof(TPMT_PUBLIC), };
-        _cleanup_(release_lock_file) LockFile srk_lock = LOCK_FILE_INIT;
-        TSS2_RC rc;
-        usec_t ts;
-        int r;
-
-        log_debug("Creating %s on TPM.", use_srk_model ? "SRK" : "Transient Primary Key");
-
-        /* So apparently not all TPM2 devices support ECC. ECC is generally preferably, because it's so much
-         * faster, noticeably so (~10s vs. ~240ms on my system). Hence, unless explicitly configured let's
-         * try to use ECC first, and if that does not work, let's fall back to RSA. */
-
-        ts = now(CLOCK_MONOTONIC);
-
-        _cleanup_(tpm2_handle_freep) Tpm2Handle *primary = NULL;
-
-        /* we only need the SRK lock when making the SRK since its not atomic, transient
-         * primary creations don't even matter if they stomp on each other, the TPM will
-         * keep kicking back the same key.
-         */
-        if (use_srk_model) {
-                r = make_lock_file("/run/systemd/tpm2-srk-init", LOCK_EX, &srk_lock);
-                if (r < 0)
-                        return log_error_errno(r, "Failed to take TPM SRK lock: %m");
-        }
-
-        /* Find existing SRK and use it if present */
-        if (use_srk_model) {
-                _cleanup_(Esys_Freep) TPM2B_PUBLIC *primary_public = NULL;
-                r = tpm2_get_srk(c, NULL, &primary_public, NULL, NULL, &primary);
-                if (r < 0)
-                        return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
-                                               "Failed to establish if SRK is present");
-                if (r == 1) {
-                        log_debug("Discovered existing SRK");
-
-                        TPMI_ALG_PUBLIC got_alg = primary_public->publicArea.type;
-                        if (alg != 0 && alg != got_alg)
-                                log_warning("Caller asked for specific algorithm %u, but existing SRK is %u, ignoring",
-                                            alg, got_alg);
-
-                        if (ret_alg)
-                                *ret_alg = alg;
-                        if (ret_primary)
-                                *ret_primary = TAKE_PTR(primary);
-                        return 0;
-                }
-                log_debug("Did not find SRK, generating...");
-        }
-
-        r = tpm2_handle_new(c, &primary);
-        if (r < 0)
-                return r;
-
-        if (IN_SET(alg, 0, TPM2_ALG_ECC)) {
-                if (use_srk_model)
-                        r = tpm2_get_srk_template(c, TPM2_ALG_ECC, &primary_template.publicArea);
-                else
-                        r = tpm2_get_legacy_template(TPM2_ALG_ECC, &primary_template.publicArea);
-                if (r < 0)
-                        return r;
-
-                rc = sym_Esys_CreatePrimary(
-                                c->esys_context,
-                                ESYS_TR_RH_OWNER,
-                                ESYS_TR_PASSWORD,
-                                ESYS_TR_NONE,
-                                ESYS_TR_NONE,
-                                &primary_sensitive,
-                                &primary_template,
-                                NULL,
-                                &creation_pcr,
-                                &primary->esys_handle,
-                                NULL,
-                                NULL,
-                                NULL,
-                                NULL);
-
-                if (rc != TSS2_RC_SUCCESS) {
-                        if (alg != 0)
-                                return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
-                                                       "Failed to generate ECC primary key in TPM: %s", sym_Tss2_RC_Decode(rc));
-
-                        log_debug("Failed to generate ECC primary key in TPM, trying RSA: %s", sym_Tss2_RC_Decode(rc));
-                } else {
-                        log_debug("Successfully created ECC primary key on TPM.");
-                        alg = TPM2_ALG_ECC;
-                }
-        }
-
-        if (IN_SET(alg, 0, TPM2_ALG_RSA)) {
-                if (use_srk_model)
-                        r = tpm2_get_srk_template(c, TPM2_ALG_RSA, &primary_template.publicArea);
-                else
-                        r = tpm2_get_legacy_template(TPM2_ALG_RSA, &primary_template.publicArea);
-                if (r < 0)
-                        return r;
-
-                rc = sym_Esys_CreatePrimary(
-                                c->esys_context,
-                                ESYS_TR_RH_OWNER,
-                                ESYS_TR_PASSWORD,
-                                ESYS_TR_NONE,
-                                ESYS_TR_NONE,
-                                &primary_sensitive,
-                                &primary_template,
-                                NULL,
-                                &creation_pcr,
-                                &primary->esys_handle,
-                                NULL,
-                                NULL,
-                                NULL,
-                                NULL);
-                if (rc != TSS2_RC_SUCCESS)
-                        return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
-                                               "Failed to generate RSA primary key in TPM: %s", sym_Tss2_RC_Decode(rc));
-                else if (alg == 0) {
-                        log_notice("TPM2 chip apparently does not support ECC primary keys, falling back to RSA. "
-                                   "This likely means TPM2 operations will be relatively slow, please be patient.");
-                        alg = TPM2_ALG_RSA;
-                }
-
-                log_debug("Successfully created RSA primary key on TPM.");
-        }
-
-        log_debug("Generating %s on the TPM2 took %s.", use_srk_model ? "SRK" : "Transient Primary Key",
-                        FORMAT_TIMESPAN(now(CLOCK_MONOTONIC) - ts, USEC_PER_MSEC));
-
-        if (use_srk_model) {
-                r = tpm2_persist_handle(c, primary, /* session= */ NULL, TPM2_SRK_HANDLE, ret_primary);
-                if (r < 0)
-                        return r;
-        } else if (ret_primary)
-                *ret_primary = TAKE_PTR(primary);
-
-        if (ret_alg)
-                *ret_alg = alg;
-
-        return 0;
-}
-
 /* Utility functions for TPMS_PCR_SELECTION. */
 
 /* Convert a TPMS_PCR_SELECTION object to a mask. */
@@ -3581,31 +3431,43 @@ int tpm2_unseal(const char *device,
         if (r < 0)
                 return r;
 
-        /* If their is a primary key we trust, like an SRK, use it */
-        _cleanup_(tpm2_handle_freep) Tpm2Handle *primary = NULL;
+        _cleanup_(tpm2_handle_freep) Tpm2Handle *primary_handle = NULL;
         if (srk_buf) {
-
-                r = tpm2_handle_new(c, &primary);
+                r = tpm2_handle_new(c, &primary_handle);
                 if (r < 0)
                         return r;
 
-                primary->flush = false;
+                primary_handle->flush = false;
 
                 log_debug("Found existing SRK key to use, deserializing ESYS_TR");
                 rc = sym_Esys_TR_Deserialize(
                                 c->esys_context,
                                 srk_buf,
                                 srk_buf_size,
-                                &primary->esys_handle);
+                                &primary_handle->esys_handle);
                 if (rc != TSS2_RC_SUCCESS)
                         return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
                                                "Failed to deserialize primary key: %s", sym_Tss2_RC_Decode(rc));
-        /* old callers without an SRK still need to create a key */
-        } else {
-                r = tpm2_make_primary(c, primary_alg, false, NULL, &primary);
+        } else if (primary_alg != 0) {
+                TPMT_PUBLIC template;
+                r = tpm2_get_legacy_template(primary_alg, &template);
+                if (r < 0)
+                        return log_error_errno(r, "Could not get legacy template: %m");
+
+                r = tpm2_create_loaded(
+                                c,
+                                /* parent= */ NULL,
+                                /* session= */ NULL,
+                                &template,
+                                /* sensitive= */ NULL,
+                                /* ret_public= */ NULL,
+                                /* ret_private= */ NULL,
+                                &primary_handle);
                 if (r < 0)
                         return r;
-        }
+        } else
+                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+                                       "No SRK or primary alg provided.");
 
         log_debug("Loading HMAC key into TPM.");
 
@@ -3616,7 +3478,7 @@ int tpm2_unseal(const char *device,
          * provides protections.
          */
         _cleanup_(tpm2_handle_freep) Tpm2Handle *hmac_key = NULL;
-        r = tpm2_load(c, primary, NULL, &public, &private, &hmac_key);
+        r = tpm2_load(c, primary_handle, NULL, &public, &private, &hmac_key);
         if (r < 0)
                 return r;
 
@@ -3642,7 +3504,7 @@ int tpm2_unseal(const char *device,
                 return r;
 
         _cleanup_(tpm2_handle_freep) Tpm2Handle *encryption_session = NULL;
-        r = tpm2_make_encryption_session(c, primary, hmac_key, &encryption_session);
+        r = tpm2_make_encryption_session(c, primary_handle, hmac_key, &encryption_session);
         if (r < 0)
                 return r;
 
@@ -3652,7 +3514,7 @@ int tpm2_unseal(const char *device,
                 _cleanup_(Esys_Freep) TPM2B_DIGEST *policy_digest = NULL;
                 r = tpm2_make_policy_session(
                                 c,
-                                primary,
+                                primary_handle,
                                 encryption_session,
                                 /* trial= */ false,
                                 &policy_session);