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.
267 lines
12 KiB
267 lines
12 KiB
8 months ago
|
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
|
||
|
|