[gnome-remote-desktop] tpm: Add ability to do capability check
- From: Jonas Ådahl <jadahl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-remote-desktop] tpm: Add ability to do capability check
- Date: Fri, 5 Aug 2022 21:58:06 +0000 (UTC)
commit 942b04f648cf6e65a9edcacc4b4d9212615d23ba
Author: Jonas Ådahl <jadahl gmail com>
Date: Tue Jun 21 18:55:45 2022 +0200
tpm: Add ability to do capability check
This will be used to determie whether a GrdCredentials backend can be
instantiated or not.
src/grd-tpm.c | 188 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
src/grd-tpm.h | 4 ++
tests/tpm-test.c | 21 +++++++
3 files changed, 210 insertions(+), 3 deletions(-)
---
diff --git a/src/grd-tpm.c b/src/grd-tpm.c
index e11be70a..06624f88 100644
--- a/src/grd-tpm.c
+++ b/src/grd-tpm.c
@@ -535,6 +535,185 @@ grd_tpm_restore_secret (GrdTpm *tpm,
return g_strdup ((char *) unsealed_data->buffer);
}
+static const char *
+get_algorithm_name (uint32_t algorithm)
+{
+ switch (algorithm)
+ {
+ case TPM2_ALG_SHA256:
+ return "SHA-256";
+ case TPM2_ALG_RSA:
+ return "RSA";
+ default:
+ return "unknown";
+ }
+}
+
+static const char *
+get_command_name (uint32_t command)
+{
+ switch (command)
+ {
+ case TPM2_CC_CreatePrimary:
+ return "CreatePrimary";
+ case TPM2_CC_StartAuthSession:
+ return "StartAuthSession";
+ case TPM2_CC_FlushContext:
+ return "FlushContext";
+ case TPM2_CC_PCR_Read:
+ return "PCR_Read";
+ case TPM2_CC_PolicyPCR:
+ return "PolicyPCR";
+ case TPM2_CC_PolicyGetDigest:
+ return "PolicyGetDigest";
+ case TPM2_CC_CreateLoaded:
+ return "CreateLoaded";
+ case TPM2_CC_ContextSave:
+ return "ContextSave";
+ case TPM2_CC_ContextLoad:
+ return "ContextLoad";
+ case TPM2_CC_Unseal:
+ return "Unseal";
+ default:
+ return "unkown";
+ }
+}
+
+gboolean
+grd_tpm_check_capabilities (GrdTpm *tpm,
+ GError **error)
+{
+ const struct
+ {
+ TPM2_CAP capability;
+ uint32_t property;
+ int count;
+ } capabilities[] = {
+ { .capability = TPM2_CAP_ALGS, .property = TPM2_ALG_SHA256 },
+ { .capability = TPM2_CAP_ALGS, .property = TPM2_ALG_RSA },
+ { .capability = TPM2_CAP_COMMANDS, .property = TPM2_CC_CreatePrimary },
+ { .capability = TPM2_CAP_COMMANDS, .property = TPM2_CC_StartAuthSession },
+ { .capability = TPM2_CAP_COMMANDS, .property = TPM2_CC_FlushContext },
+ { .capability = TPM2_CAP_COMMANDS, .property = TPM2_CC_PCR_Read },
+ { .capability = TPM2_CAP_COMMANDS, .property = TPM2_CC_PolicyPCR },
+ { .capability = TPM2_CAP_COMMANDS, .property = TPM2_CC_PolicyGetDigest },
+ { .capability = TPM2_CAP_COMMANDS, .property = TPM2_CC_CreateLoaded },
+ { .capability = TPM2_CAP_COMMANDS, .property = TPM2_CC_ContextSave },
+ { .capability = TPM2_CAP_COMMANDS, .property = TPM2_CC_ContextLoad },
+ };
+ gboolean sha256_pcrs_found = FALSE;
+ uint32_t property = 0;
+ uint32_t count = TPM2_MAX_TPM_PROPERTIES;
+ int i;
+
+ for (i = 0; i < G_N_ELEMENTS (capabilities); i++)
+ {
+ g_autofree TPMS_CAPABILITY_DATA *data = NULL;
+ TSS2_RC rc;
+
+ rc = Esys_GetCapability (tpm->esys_context,
+ ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
+ capabilities[i].capability,
+ capabilities[i].property,
+ 1,
+ NULL,
+ &data);
+ if (rc != TSS2_RC_SUCCESS)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Failed to get capability: %s",
+ Tss2_RC_Decode (rc));
+ return FALSE;
+ }
+
+ switch (capabilities[i].capability)
+ {
+ case TPM2_CAP_ALGS:
+ g_warn_if_fail (data->data.algorithms.count == 1);
+
+ if (capabilities[i].property !=
+ data->data.algorithms.algProperties[0].alg)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ "Algorithm %s not supported",
+ get_algorithm_name (capabilities[i].property));
+ return FALSE;
+ }
+
+ break;
+
+ case TPM2_CAP_COMMANDS:
+ g_warn_if_fail (data->data.command.count == 1);
+
+ if ((data->data.command.commandAttributes[0] &
+ TPMA_CC_COMMANDINDEX_MASK) !=
+ capabilities[i].property)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ "Command %s not supported",
+ get_command_name (capabilities[i].property));
+ return FALSE;
+ }
+
+ break;
+
+ case TPM2_CAP_PCRS:
+ g_warn_if_fail (data->data.assignedPCR.count == 1);
+ break;
+ }
+ }
+
+ while (TRUE)
+ {
+ TPMI_YES_NO more_data = TPM2_NO;
+ g_autofree TPMS_CAPABILITY_DATA *data = NULL;
+ TSS2_RC rc;
+
+ rc = Esys_GetCapability (tpm->esys_context,
+ ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
+ TPM2_CAP_PCRS,
+ property,
+ count,
+ &more_data,
+ &data);
+ if (rc != TSS2_RC_SUCCESS)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Failed to get capability: %s",
+ Tss2_RC_Decode (rc));
+ return FALSE;
+ }
+
+ property += data->data.assignedPCR.count;
+ count -= data->data.assignedPCR.count;
+
+ for (i = 0; i < data->data.assignedPCR.count; i++)
+ {
+ if (data->data.assignedPCR.pcrSelections[i].hash != TPM2_ALG_SHA256)
+ continue;
+
+ if (data->data.assignedPCR.pcrSelections[i].pcrSelect[0] &
+ (1 << 0 | 1 << 1 | 1 << 2))
+ {
+ sha256_pcrs_found = TRUE;
+ break;
+ }
+ }
+
+ if (more_data == TPM2_NO)
+ break;
+ }
+
+ if (!sha256_pcrs_found)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ "SHA-256 PCRs not available");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
GrdTpm *
grd_tpm_new (GrdTpmMode mode,
GError **error)
@@ -549,16 +728,19 @@ grd_tpm_new (GrdTpmMode mode,
if (!init_tss2_esys (tpm, error))
return NULL;
- if (!start_hmac_session (tpm, error))
- return NULL;
-
switch (mode)
{
+ case GRD_TPM_MODE_NONE:
+ break;
case GRD_TPM_MODE_WRITE:
+ if (!start_hmac_session (tpm, error))
+ return NULL;
if (!start_trial_session (tpm, error))
return NULL;
break;
case GRD_TPM_MODE_READ:
+ if (!start_hmac_session (tpm, error))
+ return NULL;
if (!start_policy_session (tpm, error))
return NULL;
break;
diff --git a/src/grd-tpm.h b/src/grd-tpm.h
index 6bdf0586..19bb415d 100644
--- a/src/grd-tpm.h
+++ b/src/grd-tpm.h
@@ -27,6 +27,7 @@
typedef enum _GrdTpmMode
{
+ GRD_TPM_MODE_NONE,
GRD_TPM_MODE_WRITE,
GRD_TPM_MODE_READ,
} GrdTpmMode;
@@ -62,4 +63,7 @@ char * grd_tpm_restore_secret (GrdTpm *tpm,
TPML_DIGEST *pcr_digest,
GError **error);
+gboolean grd_tpm_check_capabilities (GrdTpm *tpm,
+ GError **error);
+
#endif /* GRD_TPM_H */
diff --git a/tests/tpm-test.c b/tests/tpm-test.c
index f2e9377c..8bbcc87d 100644
--- a/tests/tpm-test.c
+++ b/tests/tpm-test.c
@@ -29,6 +29,25 @@
static GVariant *secret_variant;
+static void
+test_tpm_caps (void)
+{
+ g_autoptr (GrdTpm) tpm = NULL;
+ g_autoptr (GError) error = NULL;
+
+ tpm = grd_tpm_new (GRD_TPM_MODE_NONE, &error);
+ if (!tpm)
+ g_error ("Failed to create TPM credentials manager: %s", error->message);
+
+ if (!grd_tpm_check_capabilities (tpm, &error))
+ {
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED))
+ g_debug ("Incompatible TPM 2.0 module: %s", error->message);
+ else
+ g_error ("Capability check failed: %s", error->message);
+ }
+}
+
static void
test_tpm_write (void)
{
@@ -123,6 +142,8 @@ main (int argc,
return 77;
}
+ g_test_add_func ("/tpm/caps",
+ test_tpm_caps);
g_test_add_func ("/tpm/write",
test_tpm_write);
g_test_add_func ("/tpm/read",
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]