From e3d00443ab82b7faafc57dd9bacd59479d565ac3 Mon Sep 17 00:00:00 2001 From: Dan Streetman 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