summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cryptsetup/cryptsetup-tokens/luks2-tpm2.c21
-rw-r--r--src/cryptsetup/cryptsetup-tpm2.c22
-rw-r--r--src/shared/tpm2-util.c76
-rw-r--r--src/shared/tpm2-util.h3
4 files changed, 72 insertions, 50 deletions
diff --git a/src/cryptsetup/cryptsetup-tokens/luks2-tpm2.c b/src/cryptsetup/cryptsetup-tokens/luks2-tpm2.c
index f0286ec1bf..9f5dd46734 100644
--- a/src/cryptsetup/cryptsetup-tokens/luks2-tpm2.c
+++ b/src/cryptsetup/cryptsetup-tokens/luks2-tpm2.c
@@ -66,8 +66,8 @@ int parse_luks2_tpm2_data(
TPM2Flags *ret_flags) {
int r;
- JsonVariant *w, *e;
- uint32_t pcr_mask = 0;
+ JsonVariant *w;
+ uint32_t pcr_mask;
uint16_t pcr_bank = UINT16_MAX, primary_alg = TPM2_ALG_ECC;
_cleanup_free_ char *base64_blob = NULL, *hex_policy_hash = NULL;
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
@@ -85,21 +85,12 @@ int parse_luks2_tpm2_data(
return -EINVAL;
w = json_variant_by_key(v, "tpm2-pcrs");
- if (!w || !json_variant_is_array(w))
+ if (!w)
return -EINVAL;
- JSON_VARIANT_ARRAY_FOREACH(e, w) {
- uint64_t u;
-
- if (!json_variant_is_number(e))
- return -EINVAL;
-
- u = json_variant_unsigned(e);
- if (u >= TPM2_PCRS_MAX)
- return -EINVAL;
-
- pcr_mask |= UINT32_C(1) << u;
- }
+ r = tpm2_parse_pcr_json_array(w, &pcr_mask);
+ if (r < 0)
+ return r;
if (search_pcr_mask != UINT32_MAX &&
search_pcr_mask != pcr_mask)
diff --git a/src/cryptsetup/cryptsetup-tpm2.c b/src/cryptsetup/cryptsetup-tpm2.c
index b84d64def8..c715c8f232 100644
--- a/src/cryptsetup/cryptsetup-tpm2.c
+++ b/src/cryptsetup/cryptsetup-tpm2.c
@@ -185,7 +185,7 @@ int find_tpm2_auto_data(
for (token = start_token; token < sym_crypt_token_max(CRYPT_LUKS2); token++) {
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
- JsonVariant *w, *e;
+ JsonVariant *w;
int ks;
r = cryptsetup_get_token_as_json(cd, token, "systemd-tpm2", &v);
@@ -203,25 +203,13 @@ int find_tpm2_auto_data(
}
w = json_variant_by_key(v, "tpm2-pcrs");
- if (!w || !json_variant_is_array(w))
+ if (!w)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"TPM2 token data lacks 'tpm2-pcrs' field.");
- assert(pcr_mask == 0);
- JSON_VARIANT_ARRAY_FOREACH(e, w) {
- uint64_t u;
-
- if (!json_variant_is_number(e))
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "TPM2 PCR is not a number.");
-
- u = json_variant_unsigned(e);
- if (u >= TPM2_PCRS_MAX)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "TPM2 PCR number out of range.");
-
- pcr_mask |= UINT32_C(1) << u;
- }
+ r = tpm2_parse_pcr_json_array(w, &pcr_mask);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse TPM2 PCR mask: %m");
if (search_pcr_mask != UINT32_MAX &&
search_pcr_mask != pcr_mask) /* PCR mask doesn't match what is configured, ignore this entry */
diff --git a/src/shared/tpm2-util.c b/src/shared/tpm2-util.c
index db8d42b501..38ca862123 100644
--- a/src/shared/tpm2-util.c
+++ b/src/shared/tpm2-util.c
@@ -1380,6 +1380,62 @@ int tpm2_parse_pcrs(const char *s, uint32_t *ret) {
return 0;
}
+int tpm2_make_pcr_json_array(uint32_t pcr_mask, JsonVariant **ret) {
+ _cleanup_(json_variant_unrefp) JsonVariant *a = NULL;
+ JsonVariant* pcr_array[TPM2_PCRS_MAX];
+ unsigned n_pcrs = 0;
+ int r;
+
+ for (size_t i = 0; i < ELEMENTSOF(pcr_array); i++) {
+ if ((pcr_mask & (UINT32_C(1) << i)) == 0)
+ continue;
+
+ r = json_variant_new_integer(pcr_array + n_pcrs, i);
+ if (r < 0)
+ goto finish;
+
+ n_pcrs++;
+ }
+
+ r = json_variant_new_array(&a, pcr_array, n_pcrs);
+ if (r < 0)
+ goto finish;
+
+ if (ret)
+ *ret = TAKE_PTR(a);
+ r = 0;
+
+finish:
+ json_variant_unref_many(pcr_array, n_pcrs);
+ return r;
+}
+
+int tpm2_parse_pcr_json_array(JsonVariant *v, uint32_t *ret) {
+ JsonVariant *e;
+ uint32_t mask = 0;
+
+ if (!json_variant_is_array(v))
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 PCR array is not a JSON array.");
+
+ JSON_VARIANT_ARRAY_FOREACH(e, v) {
+ uint64_t u;
+
+ if (!json_variant_is_unsigned(e))
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 PCR is not an unsigned integer.");
+
+ u = json_variant_unsigned(e);
+ if (u >= TPM2_PCRS_MAX)
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 PCR number out of range: %" PRIu64, u);
+
+ mask |= UINT32_C(1) << u;
+ }
+
+ if (ret)
+ *ret = mask;
+
+ return 0;
+}
+
int tpm2_make_luks2_json(
int keyslot,
uint32_t pcr_mask,
@@ -1394,8 +1450,6 @@ int tpm2_make_luks2_json(
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL, *a = NULL;
_cleanup_free_ char *keyslot_as_string = NULL;
- JsonVariant* pcr_array[TPM2_PCRS_MAX];
- unsigned n_pcrs = 0;
int r;
assert(blob || blob_size == 0);
@@ -1404,23 +1458,9 @@ int tpm2_make_luks2_json(
if (asprintf(&keyslot_as_string, "%i", keyslot) < 0)
return -ENOMEM;
- for (unsigned i = 0; i < ELEMENTSOF(pcr_array); i++) {
- if ((pcr_mask & (UINT32_C(1) << i)) == 0)
- continue;
-
- r = json_variant_new_integer(pcr_array + n_pcrs, i);
- if (r < 0) {
- json_variant_unref_many(pcr_array, n_pcrs);
- return -ENOMEM;
- }
-
- n_pcrs++;
- }
-
- r = json_variant_new_array(&a, pcr_array, n_pcrs);
- json_variant_unref_many(pcr_array, n_pcrs);
+ r = tpm2_make_pcr_json_array(pcr_mask, &a);
if (r < 0)
- return -ENOMEM;
+ return r;
r = json_build(&v,
JSON_BUILD_OBJECT(
diff --git a/src/shared/tpm2-util.h b/src/shared/tpm2-util.h
index c62a0843ba..4030f2a804 100644
--- a/src/shared/tpm2-util.h
+++ b/src/shared/tpm2-util.h
@@ -54,6 +54,9 @@ int tpm2_find_device_auto(int log_level, char **ret);
int tpm2_parse_pcrs(const char *s, uint32_t *ret);
+int tpm2_make_pcr_json_array(uint32_t pcr_mask, JsonVariant **ret);
+int tpm2_parse_pcr_json_array(JsonVariant *v, uint32_t *ret);
+
int tpm2_make_luks2_json(int keyslot, uint32_t pcr_mask, uint16_t pcr_bank, uint16_t primary_alg, const void *blob, size_t blob_size, const void *policy_hash, size_t policy_hash_size, TPM2Flags flags, JsonVariant **ret);
#define TPM2_PCRS_MAX 24U