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
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.
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);
}
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;
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);