diff options
author | Lennart Poettering <lennart@poettering.net> | 2022-08-19 21:51:47 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-08-19 21:51:47 +0200 |
commit | 82b0039eb0b5237a8651b3a2e70487207835bdcd (patch) | |
tree | 2f9b908c395d663aeeeef7e10bc28849aa85f251 | |
parent | 3093b158bc715f61da288c1b01053794107ddd59 (diff) | |
parent | 8de8ec88da2a0008752a08bc6886fa1c1d885776 (diff) | |
download | systemd-82b0039eb0b5237a8651b3a2e70487207835bdcd.tar.gz |
Merge pull request #24368 from poettering/tpm2-json-pcr-array-rework
tpm2: add helpers for building/parsing JSON arrays of PCR indexes
-rw-r--r-- | src/cryptsetup/cryptsetup-tokens/luks2-tpm2.c | 21 | ||||
-rw-r--r-- | src/cryptsetup/cryptsetup-tpm2.c | 22 | ||||
-rw-r--r-- | src/shared/tpm2-util.c | 76 | ||||
-rw-r--r-- | src/shared/tpm2-util.h | 3 |
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 |