mirror of
https://github.com/morgan9e/systemd
synced 2026-04-14 00:14:32 +09:00
tpm2: tweaks to PCR mask parsing (#35835)
This commit is contained in:
4
TODO
4
TODO
@@ -328,10 +328,6 @@ Features:
|
||||
probably should measure the dm-verity root hash from the kernel side, but
|
||||
DDI meta info from userspace.
|
||||
|
||||
* rework tpm2_parse_pcr_argument_to_mask() to refuse literal hash value
|
||||
specifications. They are currently parsed but ignored. We should refuse them
|
||||
however, to not confuse people.
|
||||
|
||||
* use name_to_handle_at() with AT_HANDLE_FID instead of .st_ino (inode
|
||||
number) for identifying inodes, for example in copy.c when finding hard
|
||||
links, or loop-util.c for tracking backing files, and other places.
|
||||
|
||||
@@ -1845,8 +1845,11 @@ int tpm2_pcr_values_from_mask(uint32_t mask, TPMI_ALG_HASH hash, Tpm2PCRValue **
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tpm2_pcr_values_to_mask(const Tpm2PCRValue *pcr_values, size_t n_pcr_values, TPMI_ALG_HASH hash, uint32_t *ret_mask) {
|
||||
uint32_t mask = 0;
|
||||
int tpm2_pcr_values_to_mask(
|
||||
const Tpm2PCRValue *pcr_values,
|
||||
size_t n_pcr_values,
|
||||
TPMI_ALG_HASH hash,
|
||||
uint32_t *ret_mask) {
|
||||
|
||||
assert(pcr_values || n_pcr_values == 0);
|
||||
assert(ret_mask);
|
||||
@@ -1854,12 +1857,12 @@ int tpm2_pcr_values_to_mask(const Tpm2PCRValue *pcr_values, size_t n_pcr_values,
|
||||
if (!tpm2_pcr_values_valid(pcr_values, n_pcr_values))
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid PCR values.");
|
||||
|
||||
uint32_t mask = 0;
|
||||
FOREACH_ARRAY(v, pcr_values, n_pcr_values)
|
||||
if (v->hash == hash)
|
||||
if (hash == 0 || v->hash == hash)
|
||||
SET_BIT(mask, v->index);
|
||||
|
||||
*ret_mask = mask;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -8087,46 +8090,48 @@ int tpm2_parse_pcr_argument_append(const char *arg, Tpm2PCRValue **pcr_values, s
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Same as tpm2_parse_pcr_argument() but converts the pcr values to a pcr mask. If more than one hash
|
||||
* algorithm is included in the pcr values array this results in error. This retains the previous behavior of
|
||||
* tpm2_parse_pcr_argument() of clearing the mask if 'arg' is empty, replacing the mask if it is set to
|
||||
* UINT32_MAX, and or-ing the mask otherwise. */
|
||||
int tpm2_parse_pcr_argument_to_mask(const char *arg, uint32_t *ret_mask) {
|
||||
int tpm2_parse_pcr_argument_to_mask(const char *arg, uint32_t *mask) {
|
||||
#if HAVE_TPM2
|
||||
_cleanup_free_ Tpm2PCRValue *pcr_values = NULL;
|
||||
size_t n_pcr_values;
|
||||
int r;
|
||||
|
||||
assert(arg);
|
||||
assert(ret_mask);
|
||||
/* Same as tpm2_parse_pcr_argument() but converts the pcr values to a pcr mask. If a hash algorithm or
|
||||
* hash value is specified an error is generated (after all we only return the mask here, nothing
|
||||
* else). This retains the previous behavior of tpm2_parse_pcr_argument() of clearing the mask if
|
||||
* 'arg' is empty, replacing the mask if it is set to UINT32_MAX, and or-ing the mask otherwise. */
|
||||
|
||||
assert(arg);
|
||||
assert(mask);
|
||||
|
||||
_cleanup_free_ Tpm2PCRValue *pcr_values = NULL;
|
||||
size_t n_pcr_values;
|
||||
r = tpm2_parse_pcr_argument(arg, &pcr_values, &n_pcr_values);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (n_pcr_values == 0) {
|
||||
/* This retains the previous behavior of clearing the mask if the arg is empty */
|
||||
*ret_mask = 0;
|
||||
*mask = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t hash_count;
|
||||
r = tpm2_pcr_values_hash_count(pcr_values, n_pcr_values, &hash_count);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Could not get hash count from pcr values: %m");
|
||||
|
||||
if (hash_count > 1)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Multiple PCR hash banks selected.");
|
||||
FOREACH_ARRAY(v, pcr_values, n_pcr_values) {
|
||||
if (v->hash != 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Not expecting hash algorithm specification in PCR mask value, refusing: %s", arg);
|
||||
if (v->value.size != 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Not expecting hash value specification in PCR mask value, refusing: %s", arg);
|
||||
}
|
||||
|
||||
uint32_t new_mask;
|
||||
r = tpm2_pcr_values_to_mask(pcr_values, n_pcr_values, pcr_values[0].hash, &new_mask);
|
||||
r = tpm2_pcr_values_to_mask(pcr_values, n_pcr_values, /* algorithm= */ 0, &new_mask);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Could not get pcr values mask: %m");
|
||||
|
||||
if (*ret_mask == UINT32_MAX)
|
||||
*ret_mask = new_mask;
|
||||
if (*mask == UINT32_MAX)
|
||||
*mask = new_mask;
|
||||
else
|
||||
*ret_mask |= new_mask;
|
||||
*mask |= new_mask;
|
||||
|
||||
return 0;
|
||||
#else
|
||||
|
||||
@@ -479,7 +479,7 @@ static inline bool tpm2_is_fully_supported(void) {
|
||||
int verb_has_tpm2_generic(bool quiet);
|
||||
|
||||
int tpm2_parse_pcr_argument(const char *arg, Tpm2PCRValue **ret_pcr_values, size_t *ret_n_pcr_values);
|
||||
int tpm2_parse_pcr_argument_append(const char *arg, Tpm2PCRValue **ret_pcr_values, size_t *ret_n_pcr_values);
|
||||
int tpm2_parse_pcr_argument_append(const char *arg, Tpm2PCRValue **pcr_values, size_t *n_pcr_values);
|
||||
int tpm2_parse_pcr_argument_to_mask(const char *arg, uint32_t *mask);
|
||||
|
||||
int tpm2_load_pcr_signature(const char *path, sd_json_variant **ret);
|
||||
|
||||
@@ -556,8 +556,13 @@ static void check_parse_pcr_argument(
|
||||
|
||||
assert_se(tpm2_pcr_values_to_mask(expected_values, n_expected_values, expected_values[0].hash, &expected_mask) == 0);
|
||||
|
||||
assert_se(tpm2_parse_pcr_argument_to_mask(arg, &mask) == 0);
|
||||
assert_se(mask == expected_mask);
|
||||
_cleanup_free_ Tpm2PCRValue *arg_pcr_values = NULL;
|
||||
size_t n_arg_pcr_values = 0;
|
||||
assert_se(tpm2_parse_pcr_argument(arg, &arg_pcr_values, &n_arg_pcr_values) >= 0);
|
||||
uint32_t mask2 = UINT32_MAX;
|
||||
assert_se(tpm2_pcr_values_to_mask(arg_pcr_values, n_arg_pcr_values, /* algorithm= */ 0, &mask2) >= 0);
|
||||
|
||||
assert_se((mask == UINT32_MAX ? mask2 : (mask|mask2)) == expected_mask);
|
||||
}
|
||||
|
||||
size_t old_n_values = n_values;
|
||||
@@ -701,6 +706,10 @@ TEST(parse_pcr_argument) {
|
||||
check_parse_pcr_argument_to_mask("sysexts+17+23", 0x822000);
|
||||
check_parse_pcr_argument_to_mask("6+boot-loader-code,44", -EINVAL);
|
||||
check_parse_pcr_argument_to_mask("debug+24", -EINVAL);
|
||||
check_parse_pcr_argument_to_mask("5:sha1=f013d66c7f6817d08b7eb2a93e6d0440c1f3e7f8", -EINVAL);
|
||||
check_parse_pcr_argument_to_mask("0:sha256=f013d66c7f6817d08b7eb2a93e6d0440c1f3e7f8", -EINVAL);
|
||||
check_parse_pcr_argument_to_mask("5:sha1=f013d66c7f6817d08b7eb2a93e6d0440c1f3e7f8,3", -EINVAL);
|
||||
check_parse_pcr_argument_to_mask("3,0:sha256=f013d66c7f6817d08b7eb2a93e6d0440c1f3e7f8", -EINVAL);
|
||||
}
|
||||
|
||||
static const TPMT_PUBLIC test_rsa_template = {
|
||||
|
||||
Reference in New Issue
Block a user