257 lines
11 KiB
Diff
257 lines
11 KiB
Diff
From 27f6d0b788dd29dfbed8d2b5a9acc8d5bbb04b0e Mon Sep 17 00:00:00 2001
|
|
From: Dan Streetman <ddstreet@ieee.org>
|
|
Date: Thu, 8 Jun 2023 06:55:45 -0400
|
|
Subject: [PATCH] tpm2: remove tpm2_make_primary()
|
|
|
|
Replace use of tpm2_make_primary() with tpm2_create_loaded()
|
|
|
|
(cherry picked from commit 20988602ff203f6645762ceb8cda70b5f26b0e1d)
|
|
|
|
Related: RHEL-16182
|
|
---
|
|
src/shared/tpm2-util.c | 188 ++++++-----------------------------------
|
|
1 file changed, 25 insertions(+), 163 deletions(-)
|
|
|
|
diff --git a/src/shared/tpm2-util.c b/src/shared/tpm2-util.c
|
|
index 92f1fdd962..320261afb6 100644
|
|
--- a/src/shared/tpm2-util.c
|
|
+++ b/src/shared/tpm2-util.c
|
|
@@ -1200,156 +1200,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. */
|
|
@@ -3572,31 +3422,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.");
|
|
|
|
@@ -3607,7 +3469,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;
|
|
|
|
@@ -3633,7 +3495,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;
|
|
|
|
@@ -3643,7 +3505,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);
|