]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
tpm2: cache TPM's supported ECC curves 29426/head
authorDan Streetman <ddstreet@ieee.org>
Fri, 8 Sep 2023 17:14:38 +0000 (13:14 -0400)
committerDan Streetman <ddstreet@ieee.org>
Tue, 3 Oct 2023 16:56:55 +0000 (12:56 -0400)
This brings the tpm2_supports_ecc_curve() api in line with the other
tpm2_supports_*() functions, of returning a boolean.

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

index 47a88d3d20f09b524ea84236c7d3d818161313b0..1e560f39ceed392eb7db342a9463b83e43d5ddca 100644 (file)
@@ -289,6 +289,39 @@ static int tpm2_cache_capabilities(Tpm2Context *c) {
                 current_cc = TPMA_CC_TO_TPM2_CC(commands.commandAttributes[commands.count - 1]) + 1;
         }
 
+        /* Cache the ECC curves. The spec isn't actually clear if ECC curves can be added/removed
+         * while running, but that would be crazy, so let's hope it is not possible. */
+        TPM2_ECC_CURVE current_ecc_curve = TPM2_ECC_NONE;
+        for (;;) {
+                r = tpm2_get_capability(
+                                c,
+                                TPM2_CAP_ECC_CURVES,
+                                current_ecc_curve,
+                                TPM2_MAX_ECC_CURVES,
+                                &capability);
+                if (r < 0)
+                        return r;
+
+                TPML_ECC_CURVE ecc_curves = capability.eccCurves;
+
+                /* ECC support isn't required */
+                if (ecc_curves.count == 0)
+                        break;
+
+                if (!GREEDY_REALLOC_APPEND(
+                                c->capability_ecc_curves,
+                                c->n_capability_ecc_curves,
+                                ecc_curves.eccCurves,
+                                ecc_curves.count))
+                        return log_oom_debug();
+
+                if (r == 0)
+                        break;
+
+                /* Set current_ecc_curve to index after last ecc curve the TPM provided */
+                current_ecc_curve = ecc_curves.eccCurves[ecc_curves.count - 1] + 1;
+        }
+
         /* Cache the PCR capabilities, which are safe to cache, as the only way they can change is
          * TPM2_PCR_Allocate(), which changes the allocation after the next _TPM_Init(). If the TPM is
          * reinitialized while we are using it, all our context and sessions will be invalid, so we can
@@ -358,23 +391,16 @@ bool tpm2_supports_command(Tpm2Context *c, TPM2_CC command) {
         return tpm2_get_capability_command(c, command, NULL);
 }
 
-/* Returns 1 if the TPM supports the ECC curve, 0 if not, or < 0 for any error. */
-static int tpm2_supports_ecc_curve(Tpm2Context *c, TPM2_ECC_CURVE curve) {
-        TPMU_CAPABILITIES capability;
-        int r;
-
-        /* The spec explicitly states the TPM2_ECC_CURVE should be cast to uint32_t. */
-        r = tpm2_get_capability(c, TPM2_CAP_ECC_CURVES, (uint32_t) curve, 1, &capability);
-        if (r < 0)
-                return r;
+/* Returns true if the TPM supports the ECC curve, otherwise false. */
+bool tpm2_supports_ecc_curve(Tpm2Context *c, TPM2_ECC_CURVE ecc_curve) {
+        assert(c);
 
-        TPML_ECC_CURVE eccCurves = capability.eccCurves;
-        if (eccCurves.count == 0 || eccCurves.eccCurves[0] != curve) {
-                log_debug("TPM does not support ECC curve 0x%02" PRIx16 ".", curve);
-                return 0;
-        }
+        FOREACH_ARRAY(curve, c->capability_ecc_curves, c->n_capability_ecc_curves)
+                if (*curve == ecc_curve)
+                        return true;
 
-        return 1;
+        log_debug("TPM does not support ECC curve 0x%" PRIx16 ".", ecc_curve);
+        return false;
 }
 
 /* Query the TPM for populated handles.
@@ -522,6 +548,7 @@ static Tpm2Context *tpm2_context_free(Tpm2Context *c) {
 
         c->capability_algorithms = mfree(c->capability_algorithms);
         c->capability_commands = mfree(c->capability_commands);
+        c->capability_ecc_curves = mfree(c->capability_ecc_curves);
 
         return mfree(c);
 }
index 045f200fbb9d3e51dd73fa4442692e0f26422681..3fd2a13f920e6ef689deb70763fd08d041639306 100644 (file)
@@ -49,6 +49,8 @@ typedef struct {
         size_t n_capability_algorithms;
         TPMA_CC *capability_commands;
         size_t n_capability_commands;
+        TPM2_ECC_CURVE *capability_ecc_curves;
+        size_t n_capability_ecc_curves;
         TPML_PCR_SELECTION capability_pcrs;
 } Tpm2Context;
 
@@ -107,6 +109,7 @@ int tpm2_create_loaded(Tpm2Context *c, const Tpm2Handle *parent, const Tpm2Handl
 
 bool tpm2_supports_alg(Tpm2Context *c, TPM2_ALG_ID alg);
 bool tpm2_supports_command(Tpm2Context *c, TPM2_CC command);
+bool tpm2_supports_ecc_curve(Tpm2Context *c, TPM2_ECC_CURVE ecc_curve);
 
 bool tpm2_test_parms(Tpm2Context *c, TPMI_ALG_PUBLIC alg, const TPMU_PUBLIC_PARMS *parms);