You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
systemd/SOURCES/0584-tpm2-in-tpm2_pcr_value...

267 lines
12 KiB

From e3d00443ab82b7faafc57dd9bacd59479d565ac3 Mon Sep 17 00:00:00 2001
From: Dan Streetman <ddstreet@ieee.org>
Date: Mon, 21 Aug 2023 11:02:55 -0400
Subject: [PATCH] tpm2: in tpm2_pcr_values_valid() use FOREACH_ARRAY()
(cherry picked from commit 193fd5730e980db57cb092bd90cbc1966d9b404e)
Related: RHEL-16182
---
src/shared/tpm2-util.c | 117 ++++++++++++++++++-----------------------
1 file changed, 52 insertions(+), 65 deletions(-)
diff --git a/src/shared/tpm2-util.c b/src/shared/tpm2-util.c
index 4288d1b897..a91e805e06 100644
--- a/src/shared/tpm2-util.c
+++ b/src/shared/tpm2-util.c
@@ -1278,22 +1278,15 @@ 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_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml) \
+ _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_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++)
-
#define FOREACH_PCR_IN_TPML_PCR_SELECTION(pcr, tpms, tpml) \
FOREACH_TPMS_PCR_SELECTION_IN_TPML_PCR_SELECTION(tpms, tpml) \
FOREACH_PCR_IN_TPMS_PCR_SELECTION(pcr, tpms)
@@ -1364,6 +1357,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);
@@ -1393,13 +1394,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. */
@@ -1473,7 +1467,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);
}
@@ -1482,7 +1476,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);
}
@@ -1490,7 +1484,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;
@@ -1554,36 +1548,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;
}
}
@@ -1635,9 +1628,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;
@@ -1660,14 +1653,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;
-
- tpm2_tpml_pcr_selection_add_mask(&selection, hash, INDEX_TO_MASK(uint32_t, index));
+ FOREACH_ARRAY(v, pcr_values, n_pcr_values) {
+ tpm2_tpml_pcr_selection_add_mask(&selection, v->hash, INDEX_TO_MASK(uint32_t, v->index));
- if (!GREEDY_REALLOC_APPEND(values, n_values, digest, 1))
+ if (!GREEDY_REALLOC_APPEND(values, n_values, &v->value, 1))
return log_oom_debug();
}
@@ -1825,8 +1814,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;
}
@@ -2352,9 +2341,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;
@@ -2410,9 +2397,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;
@@ -2605,12 +2592,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.");
@@ -2679,8 +2666,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);
@@ -4688,16 +4675,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