1
0
mirror of https://github.com/systemd/systemd.git synced 2024-12-22 17:35:35 +03:00

tpm2: in tpm2_pcr_values_valid() use FOREACH_ARRAY()

This commit is contained in:
Dan Streetman 2023-08-21 11:02:55 -04:00
parent 064ac95d81
commit 193fd5730e

View File

@ -1282,21 +1282,14 @@ void tpm2_tpms_pcr_selection_move(TPMS_PCR_SELECTION *a, TPMS_PCR_SELECTION *b)
tpm2_tpms_pcr_selection_from_mask(0, b->hash, b);
}
#define FOREACH_PCR_IN_TPMS_PCR_SELECTION(pcr, tpms) \
_FOREACH_PCR_IN_TPMS_PCR_SELECTION(pcr, tpms, UNIQ)
#define _FOREACH_PCR_IN_TPMS_PCR_SELECTION(pcr, tpms, uniq) \
FOREACH_PCR_IN_MASK(pcr, tpm2_tpms_pcr_selection_to_mask(tpms))
#define FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml) \
UNIQ_FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml, UNIQ)
#define UNIQ_FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml, uniq) \
for (TPML_PCR_SELECTION *UNIQ_T(_tpml, uniq) = (TPML_PCR_SELECTION*)(tpml); \
UNIQ_T(_tpml, uniq); UNIQ_T(_tpml, uniq) = NULL) \
_FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, UNIQ_T(_tpml, uniq))
#define _FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml) \
for (TPMS_PCR_SELECTION *tpms = tpml->pcrSelections; \
(uint32_t)(tpms - tpml->pcrSelections) < tpml->count; \
tpms++)
_FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml, UNIQ_T(l, UNIQ))
#define _FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml, l) \
for (typeof(tpml) (l) = (tpml); (l); (l) = NULL) \
FOREACH_ARRAY(tpms, (l)->pcrSelections, (l)->count)
#define FOREACH_PCR_IN_TPMS_PCR_SELECTION(pcr, tpms) \
FOREACH_PCR_IN_MASK(pcr, tpm2_tpms_pcr_selection_to_mask(tpms))
#define FOREACH_PCR_IN_TPML_PCR_SELECTION(pcr, tpms, tpml) \
FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml) \
@ -1369,6 +1362,14 @@ static TPMS_PCR_SELECTION *tpm2_tpml_pcr_selection_get_tpms_pcr_selection(
return selection;
}
/* Combine all duplicate (same hash alg) TPMS_PCR_SELECTION entries in 'l'. */
static void tpm2_tpml_pcr_selection_cleanup(TPML_PCR_SELECTION *l) {
/* Can't use FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION() because we might modify l->count */
for (uint32_t i = 0; i < l->count; i++)
/* This removes all duplicate TPMS_PCR_SELECTION entries for this hash. */
(void) tpm2_tpml_pcr_selection_get_tpms_pcr_selection(l, l->pcrSelections[i].hash);
}
/* Convert a TPML_PCR_SELECTION object to a mask. Returns empty mask (i.e. 0) if 'hash_alg' is not in the object. */
uint32_t tpm2_tpml_pcr_selection_to_mask(const TPML_PCR_SELECTION *l, TPMI_ALG_HASH hash_alg) {
assert(l);
@ -1398,13 +1399,6 @@ void tpm2_tpml_pcr_selection_from_mask(uint32_t mask, TPMI_ALG_HASH hash_alg, TP
};
}
/* Combine all duplicate (same hash alg) TPMS_PCR_SELECTION entries in 'l'. */
static void tpm2_tpml_pcr_selection_cleanup(TPML_PCR_SELECTION *l) {
FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(s, l)
/* This removes all duplicates for s->hash. */
(void) tpm2_tpml_pcr_selection_get_tpms_pcr_selection(l, s->hash);
}
/* Add the PCR selections in 's' to the corresponding hash alg TPMS_PCR_SELECTION entry in 'l'. Adds a new
* TPMS_PCR_SELECTION entry for the hash alg if needed. This may modify the TPML_PCR_SELECTION by combining
* entries with the same hash alg. */
@ -1478,7 +1472,7 @@ void tpm2_tpml_pcr_selection_add(TPML_PCR_SELECTION *a, const TPML_PCR_SELECTION
assert(a);
assert(b);
FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(selection_b, (TPML_PCR_SELECTION*) b)
FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(selection_b, b)
tpm2_tpml_pcr_selection_add_tpms_pcr_selection(a, selection_b);
}
@ -1487,7 +1481,7 @@ void tpm2_tpml_pcr_selection_sub(TPML_PCR_SELECTION *a, const TPML_PCR_SELECTION
assert(a);
assert(b);
FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(selection_b, (TPML_PCR_SELECTION*) b)
FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(selection_b, b)
tpm2_tpml_pcr_selection_sub_tpms_pcr_selection(a, selection_b);
}
@ -1495,7 +1489,7 @@ char *tpm2_tpml_pcr_selection_to_string(const TPML_PCR_SELECTION *l) {
assert(l);
_cleanup_free_ char *banks = NULL;
FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(s, (TPML_PCR_SELECTION*) l) {
FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(s, l) {
if (tpm2_tpms_pcr_selection_is_empty(s))
continue;
@ -1559,36 +1553,35 @@ bool tpm2_pcr_values_valid(const Tpm2PCRValue *pcr_values, size_t n_pcr_values)
if (!pcr_values && n_pcr_values > 0)
return false;
for (size_t i = 0; i < n_pcr_values; i++) {
const Tpm2PCRValue *v = &pcr_values[i];
if (!tpm2_pcr_value_valid(v))
const Tpm2PCRValue *previous = NULL;
FOREACH_ARRAY(current, pcr_values, n_pcr_values) {
if (!tpm2_pcr_value_valid(current))
return false;
if (i == 0)
if (!previous) {
previous = current;
continue;
const Tpm2PCRValue *l = &pcr_values[i - 1];
}
/* Hashes must be sorted in ascending order */
if (v->hash < l->hash) {
if (current->hash < previous->hash) {
log_debug("PCR values not in ascending order, hash %" PRIu16 " is after %" PRIu16 ".",
v->hash, l->hash);
current->hash, previous->hash);
return false;
}
if (v->hash == l->hash) {
if (current->hash == previous->hash) {
/* Indexes (for the same hash) must be sorted in ascending order */
if (v->index < l->index) {
if (current->index < previous->index) {
log_debug("PCR values not in ascending order, hash %" PRIu16 " index %u is after %u.",
v->hash, v->index, l->index);
current->hash, current->index, previous->index);
return false;
}
/* Indexes (for the same hash) must not be duplicates */
if (v->index == l->index) {
if (current->index == previous->index) {
log_debug("PCR values contain duplicates for hash %" PRIu16 " index %u.",
v->hash, v->index);
current->hash, previous->index);
return false;
}
}
@ -1640,9 +1633,9 @@ 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.");
for (size_t i = 0; i < n_pcr_values; i++)
if (pcr_values[i].hash == hash)
SET_BIT(mask, pcr_values[i].index);
FOREACH_ARRAY(v, pcr_values, n_pcr_values)
if (v->hash == hash)
SET_BIT(mask, v->index);
*ret_mask = mask;
@ -1665,14 +1658,10 @@ int tpm2_tpml_pcr_selection_from_pcr_values(
if (!tpm2_pcr_values_valid(pcr_values, n_pcr_values))
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "PCR values are not valid.");
for (size_t i = 0; i < n_pcr_values; i++) {
unsigned index = pcr_values[i].index;
TPMI_ALG_HASH hash = pcr_values[i].hash;
const TPM2B_DIGEST *digest = &pcr_values[i].value;
FOREACH_ARRAY(v, pcr_values, n_pcr_values) {
tpm2_tpml_pcr_selection_add_mask(&selection, v->hash, INDEX_TO_MASK(uint32_t, v->index));
tpm2_tpml_pcr_selection_add_mask(&selection, hash, INDEX_TO_MASK(uint32_t, index));
if (!GREEDY_REALLOC_APPEND(values, n_values, digest, 1))
if (!GREEDY_REALLOC_APPEND(values, n_values, &v->value, 1))
return log_oom_debug();
}
@ -1830,8 +1819,8 @@ int tpm2_pcr_values_from_string(const char *arg, Tpm2PCRValue **ret_pcr_values,
char *tpm2_pcr_values_to_string(const Tpm2PCRValue *pcr_values, size_t n_pcr_values) {
_cleanup_free_ char *s = NULL;
for (size_t i = 0; i < n_pcr_values; i++) {
_cleanup_free_ char *pcrstr = tpm2_pcr_value_to_string(&pcr_values[i]);
FOREACH_ARRAY(v, pcr_values, n_pcr_values) {
_cleanup_free_ char *pcrstr = tpm2_pcr_value_to_string(v);
if (!pcrstr || !strextend_with_separator(&s, "+", pcrstr))
return NULL;
}
@ -2357,9 +2346,7 @@ int tpm2_pcr_read_missing_values(Tpm2Context *c, Tpm2PCRValue *pcr_values, size_
}
}
for (size_t i = 0; i < n_pcr_values; i++) {
Tpm2PCRValue *v = &pcr_values[i];
FOREACH_ARRAY(v, pcr_values, n_pcr_values) {
if (v->hash == 0)
v->hash = pcr_bank;
@ -2415,9 +2402,9 @@ static int tpm2_pcr_mask_good(
return r;
/* If at least one of the selected PCR values is something other than all 0x00 or all 0xFF we are happy. */
for (unsigned i = 0; i < n_pcr_values; i++)
if (!memeqbyte(0x00, pcr_values[i].value.buffer, pcr_values[i].value.size) &&
!memeqbyte(0xFF, pcr_values[i].value.buffer, pcr_values[i].value.size))
FOREACH_ARRAY(v, pcr_values, n_pcr_values)
if (!memeqbyte(0x00, v->value.buffer, v->value.size) &&
!memeqbyte(0xFF, v->value.buffer, v->value.size))
return true;
return false;
@ -2611,12 +2598,12 @@ int tpm2_get_good_pcr_banks_strv(
if (n_algs < 0)
return n_algs;
for (int i = 0; i < n_algs; i++) {
FOREACH_ARRAY(a, algs, n_algs) {
_cleanup_free_ char *n = NULL;
const EVP_MD *implementation;
const char *salg;
salg = tpm2_hash_alg_to_string(algs[i]);
salg = tpm2_hash_alg_to_string(*a);
if (!salg)
return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "TPM2 operates with unknown PCR algorithm, can't measure.");
@ -2688,8 +2675,8 @@ int tpm2_digest_many(
return 0;
}
for (size_t i = 0; i < n_data; i++)
sha256_process_bytes(data[i].iov_base, data[i].iov_len, &ctx);
FOREACH_ARRAY(d, data, n_data)
sha256_process_bytes(d->iov_base, d->iov_len, &ctx);
sha256_finish_ctx(&ctx, digest->buffer);
@ -4758,16 +4745,16 @@ Tpm2Support tpm2_support(void) {
#if HAVE_TPM2
static void tpm2_pcr_values_apply_default_hash_alg(Tpm2PCRValue *pcr_values, size_t n_pcr_values) {
TPMI_ALG_HASH default_hash = 0;
for (size_t i = 0; i < n_pcr_values; i++)
if (pcr_values[i].hash != 0) {
default_hash = pcr_values[i].hash;
FOREACH_ARRAY(v, pcr_values, n_pcr_values)
if (v->hash != 0) {
default_hash = v->hash;
break;
}
if (default_hash != 0)
for (size_t i = 0; i < n_pcr_values; i++)
if (pcr_values[i].hash == 0)
pcr_values[i].hash = default_hash;
FOREACH_ARRAY(v, pcr_values, n_pcr_values)
if (v->hash == 0)
v->hash = default_hash;
}
#endif