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.
683 lines
33 KiB
683 lines
33 KiB
From 18bff28024350b8553e89de6ed145470c26786fe Mon Sep 17 00:00:00 2001
|
|
From: Dan Streetman <ddstreet@ieee.org>
|
|
Date: Wed, 12 Jul 2023 22:36:37 -0400
|
|
Subject: [PATCH] tpm2: change tpm2_parse_pcr_argument() parameters to parse to
|
|
Tpm2PCRValue array
|
|
|
|
In order to allow users to specify expected PCR values, change the
|
|
tpm2_parse_pcr_argument() to parse the text argument into an array of
|
|
Tpm2PCRValue objects, which provide not only the selected PCR indexes, but also
|
|
(optionally) the hash algorithm and hash value for each PCR index.
|
|
|
|
(cherry picked from commit 07c040611751facf075dab7a72ab4935142dda3c)
|
|
|
|
Related: RHEL-16182
|
|
---
|
|
src/creds/creds.c | 4 +-
|
|
src/cryptenroll/cryptenroll.c | 4 +-
|
|
src/cryptsetup/cryptsetup.c | 2 +-
|
|
src/partition/repart.c | 4 +-
|
|
src/shared/tpm2-util.c | 179 ++++++++++++++++------
|
|
src/shared/tpm2-util.h | 5 +-
|
|
src/test/test-tpm2.c | 279 ++++++++++++++++++++++++++--------
|
|
7 files changed, 355 insertions(+), 122 deletions(-)
|
|
|
|
diff --git a/src/creds/creds.c b/src/creds/creds.c
|
|
index a755a52c34..7edaa5f24c 100644
|
|
--- a/src/creds/creds.c
|
|
+++ b/src/creds/creds.c
|
|
@@ -862,7 +862,7 @@ static int parse_argv(int argc, char *argv[]) {
|
|
break;
|
|
|
|
case ARG_TPM2_PCRS: /* For fixed hash PCR policies only */
|
|
- r = tpm2_parse_pcr_argument(optarg, &arg_tpm2_pcr_mask);
|
|
+ r = tpm2_parse_pcr_argument_to_mask(optarg, &arg_tpm2_pcr_mask);
|
|
if (r < 0)
|
|
return r;
|
|
|
|
@@ -876,7 +876,7 @@ static int parse_argv(int argc, char *argv[]) {
|
|
break;
|
|
|
|
case ARG_TPM2_PUBLIC_KEY_PCRS: /* For public key PCR policies only */
|
|
- r = tpm2_parse_pcr_argument(optarg, &arg_tpm2_public_key_pcr_mask);
|
|
+ r = tpm2_parse_pcr_argument_to_mask(optarg, &arg_tpm2_public_key_pcr_mask);
|
|
if (r < 0)
|
|
return r;
|
|
|
|
diff --git a/src/cryptenroll/cryptenroll.c b/src/cryptenroll/cryptenroll.c
|
|
index 6a9170f000..c84e10e567 100644
|
|
--- a/src/cryptenroll/cryptenroll.c
|
|
+++ b/src/cryptenroll/cryptenroll.c
|
|
@@ -335,7 +335,7 @@ static int parse_argv(int argc, char *argv[]) {
|
|
}
|
|
|
|
case ARG_TPM2_PCRS:
|
|
- r = tpm2_parse_pcr_argument(optarg, &arg_tpm2_pcr_mask);
|
|
+ r = tpm2_parse_pcr_argument_to_mask(optarg, &arg_tpm2_pcr_mask);
|
|
if (r < 0)
|
|
return r;
|
|
|
|
@@ -356,7 +356,7 @@ static int parse_argv(int argc, char *argv[]) {
|
|
break;
|
|
|
|
case ARG_TPM2_PUBLIC_KEY_PCRS:
|
|
- r = tpm2_parse_pcr_argument(optarg, &arg_tpm2_public_key_pcr_mask);
|
|
+ r = tpm2_parse_pcr_argument_to_mask(optarg, &arg_tpm2_public_key_pcr_mask);
|
|
if (r < 0)
|
|
return r;
|
|
|
|
diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c
|
|
index 866141ac44..d70516c237 100644
|
|
--- a/src/cryptsetup/cryptsetup.c
|
|
+++ b/src/cryptsetup/cryptsetup.c
|
|
@@ -390,7 +390,7 @@ static int parse_one_option(const char *option) {
|
|
|
|
} else if ((val = startswith(option, "tpm2-pcrs="))) {
|
|
|
|
- r = tpm2_parse_pcr_argument(val, &arg_tpm2_pcr_mask);
|
|
+ r = tpm2_parse_pcr_argument_to_mask(val, &arg_tpm2_pcr_mask);
|
|
if (r < 0)
|
|
return r;
|
|
|
|
diff --git a/src/partition/repart.c b/src/partition/repart.c
|
|
index 57e1a8052a..a2c5e214f6 100644
|
|
--- a/src/partition/repart.c
|
|
+++ b/src/partition/repart.c
|
|
@@ -5276,7 +5276,7 @@ static int parse_argv(int argc, char *argv[]) {
|
|
}
|
|
|
|
case ARG_TPM2_PCRS:
|
|
- r = tpm2_parse_pcr_argument(optarg, &arg_tpm2_pcr_mask);
|
|
+ r = tpm2_parse_pcr_argument_to_mask(optarg, &arg_tpm2_pcr_mask);
|
|
if (r < 0)
|
|
return r;
|
|
|
|
@@ -5290,7 +5290,7 @@ static int parse_argv(int argc, char *argv[]) {
|
|
break;
|
|
|
|
case ARG_TPM2_PUBLIC_KEY_PCRS:
|
|
- r = tpm2_parse_pcr_argument(optarg, &arg_tpm2_public_key_pcr_mask);
|
|
+ r = tpm2_parse_pcr_argument_to_mask(optarg, &arg_tpm2_public_key_pcr_mask);
|
|
if (r < 0)
|
|
return r;
|
|
|
|
diff --git a/src/shared/tpm2-util.c b/src/shared/tpm2-util.c
|
|
index 50a01f55a6..0ad470b0c5 100644
|
|
--- a/src/shared/tpm2-util.c
|
|
+++ b/src/shared/tpm2-util.c
|
|
@@ -4192,45 +4192,6 @@ char *tpm2_pcr_mask_to_string(uint32_t mask) {
|
|
return TAKE_PTR(s);
|
|
}
|
|
|
|
-int tpm2_pcr_mask_from_string(const char *arg, uint32_t *ret_mask) {
|
|
- uint32_t mask = 0;
|
|
- int r;
|
|
-
|
|
- assert(arg);
|
|
- assert(ret_mask);
|
|
-
|
|
- if (isempty(arg)) {
|
|
- *ret_mask = 0;
|
|
- return 0;
|
|
- }
|
|
-
|
|
- /* Parses a "," or "+" separated list of PCR indexes. We support "," since this is a list after all,
|
|
- * and most other tools expect comma separated PCR specifications. We also support "+" since in
|
|
- * /etc/crypttab the "," is already used to separate options, hence a different separator is nice to
|
|
- * avoid escaping. */
|
|
-
|
|
- const char *p = arg;
|
|
- for (;;) {
|
|
- _cleanup_free_ char *pcr = NULL;
|
|
- unsigned n;
|
|
-
|
|
- r = extract_first_word(&p, &pcr, ",+", EXTRACT_DONT_COALESCE_SEPARATORS);
|
|
- if (r == 0)
|
|
- break;
|
|
- if (r < 0)
|
|
- return log_error_errno(r, "Failed to parse PCR list: %s", arg);
|
|
-
|
|
- r = pcr_index_from_string(pcr);
|
|
- if (r < 0)
|
|
- return log_error_errno(r, "Failed to parse specified PCR or specified PCR is out of range: %s", pcr);
|
|
- n = r;
|
|
- SET_BIT(mask, n);;
|
|
- }
|
|
-
|
|
- *ret_mask = mask;
|
|
- return 0;
|
|
-}
|
|
-
|
|
int tpm2_make_pcr_json_array(uint32_t pcr_mask, JsonVariant **ret) {
|
|
_cleanup_(json_variant_unrefp) JsonVariant *a = NULL;
|
|
JsonVariant* pcr_array[TPM2_PCRS_MAX];
|
|
@@ -4609,29 +4570,147 @@ Tpm2Support tpm2_support(void) {
|
|
return support;
|
|
}
|
|
|
|
-int tpm2_parse_pcr_argument(const char *arg, uint32_t *mask) {
|
|
- uint32_t m;
|
|
+#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;
|
|
+ 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;
|
|
+}
|
|
+#endif
|
|
+
|
|
+/* Parse the PCR selection/value arg(s) and return a corresponding array of Tpm2PCRValue objects.
|
|
+ *
|
|
+ * The format is the same as tpm2_pcr_values_from_string(). The first provided entry with a hash algorithm
|
|
+ * set will be used as the 'default' hash algorithm. All entries with an unset hash algorithm will be updated
|
|
+ * with the 'default' hash algorithm. The resulting array will be sorted and checked for validity.
|
|
+ *
|
|
+ * This will replace *ret_pcr_values with the new array of pcr values; to append to an existing array, use
|
|
+ * tpm2_parse_pcr_argument_append(). */
|
|
+int tpm2_parse_pcr_argument(const char *arg, Tpm2PCRValue **ret_pcr_values, size_t *ret_n_pcr_values) {
|
|
+#if HAVE_TPM2
|
|
int r;
|
|
|
|
- assert(mask);
|
|
+ assert(arg);
|
|
+ assert(ret_pcr_values);
|
|
+ assert(ret_n_pcr_values);
|
|
|
|
- /* For use in getopt_long() command line parsers: merges masks specified on the command line */
|
|
+ _cleanup_free_ Tpm2PCRValue *pcr_values = NULL;
|
|
+ size_t n_pcr_values = 0;
|
|
+ r = tpm2_pcr_values_from_string(arg, &pcr_values, &n_pcr_values);
|
|
+ if (r < 0)
|
|
+ return r;
|
|
+
|
|
+ tpm2_pcr_values_apply_default_hash_alg(pcr_values, n_pcr_values);
|
|
+
|
|
+ tpm2_sort_pcr_values(pcr_values, n_pcr_values);
|
|
+
|
|
+ if (!TPM2_PCR_VALUES_VALID(pcr_values, n_pcr_values))
|
|
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Parsed PCR values are not valid.");
|
|
+
|
|
+ *ret_pcr_values = TAKE_PTR(pcr_values);
|
|
+ *ret_n_pcr_values = n_pcr_values;
|
|
|
|
- if (isempty(arg)) {
|
|
- *mask = 0;
|
|
+ return 0;
|
|
+#else
|
|
+ return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "TPM2 support is disabled.");
|
|
+#endif
|
|
+}
|
|
+
|
|
+/* Same as tpm2_parse_pcr_argument(), but the pcr values array is appended to. If the provided pcr values
|
|
+ * array is not NULL, it must point to an allocated pcr values array and the provided number of pcr values
|
|
+ * must be correct.
|
|
+ *
|
|
+ * Note that 'arg' is parsed into a new array of pcr values independently of any previous pcr values,
|
|
+ * including application of the default hash algorithm. Then the two arrays are combined, the default hash
|
|
+ * algorithm check applied again (in case either the previous or current array had no default hash
|
|
+ * algorithm), and then the resulting array is sorted and rechecked for validity. */
|
|
+int tpm2_parse_pcr_argument_append(const char *arg, Tpm2PCRValue **ret_pcr_values, size_t *ret_n_pcr_values) {
|
|
+#if HAVE_TPM2
|
|
+ int r;
|
|
+
|
|
+ assert(arg);
|
|
+ assert(ret_pcr_values);
|
|
+ assert(ret_n_pcr_values);
|
|
+
|
|
+ _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 we got previous values, append them. */
|
|
+ if (*ret_pcr_values && !GREEDY_REALLOC_APPEND(pcr_values, n_pcr_values, *ret_pcr_values, *ret_n_pcr_values))
|
|
+ return log_oom();
|
|
+
|
|
+ tpm2_pcr_values_apply_default_hash_alg(pcr_values, n_pcr_values);
|
|
+
|
|
+ tpm2_sort_pcr_values(pcr_values, n_pcr_values);
|
|
+
|
|
+ if (!TPM2_PCR_VALUES_VALID(pcr_values, n_pcr_values))
|
|
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Parsed PCR values are not valid.");
|
|
+
|
|
+ SWAP_TWO(*ret_pcr_values, pcr_values);
|
|
+ *ret_n_pcr_values = n_pcr_values;
|
|
+
|
|
+ return 0;
|
|
+#else
|
|
+ return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "TPM2 support is disabled.");
|
|
+#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) {
|
|
+#if HAVE_TPM2
|
|
+ _cleanup_free_ Tpm2PCRValue *pcr_values = NULL;
|
|
+ size_t n_pcr_values;
|
|
+ int r;
|
|
+
|
|
+ assert(arg);
|
|
+ assert(ret_mask);
|
|
+
|
|
+ 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;
|
|
return 0;
|
|
}
|
|
|
|
- r = tpm2_pcr_mask_from_string(arg, &m);
|
|
+ size_t hash_count;
|
|
+ r = tpm2_pcr_values_hash_count(pcr_values, n_pcr_values, &hash_count);
|
|
if (r < 0)
|
|
- return r;
|
|
+ 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.");
|
|
+
|
|
+ uint32_t new_mask;
|
|
+ r = tpm2_pcr_values_to_mask(pcr_values, n_pcr_values, pcr_values[0].hash, &new_mask);
|
|
+ if (r < 0)
|
|
+ return log_error_errno(r, "Could not get pcr values mask: %m");
|
|
|
|
- if (*mask == UINT32_MAX)
|
|
- *mask = m;
|
|
+ if (*ret_mask == UINT32_MAX)
|
|
+ *ret_mask = new_mask;
|
|
else
|
|
- *mask |= m;
|
|
+ *ret_mask |= new_mask;
|
|
|
|
return 0;
|
|
+#else
|
|
+ return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "TPM2 support is disabled.");
|
|
+#endif
|
|
}
|
|
|
|
int tpm2_load_pcr_signature(const char *path, JsonVariant **ret) {
|
|
diff --git a/src/shared/tpm2-util.h b/src/shared/tpm2-util.h
|
|
index c6e9339e0e..be19c7972b 100644
|
|
--- a/src/shared/tpm2-util.h
|
|
+++ b/src/shared/tpm2-util.h
|
|
@@ -208,7 +208,6 @@ const char *tpm2_asym_alg_to_string(uint16_t alg);
|
|
int tpm2_asym_alg_from_string(const char *alg);
|
|
|
|
char *tpm2_pcr_mask_to_string(uint32_t mask);
|
|
-int tpm2_pcr_mask_from_string(const char *arg, uint32_t *mask);
|
|
|
|
typedef struct {
|
|
uint32_t search_pcr_mask;
|
|
@@ -254,7 +253,9 @@ typedef enum PcrIndex {
|
|
|
|
Tpm2Support tpm2_support(void);
|
|
|
|
-int tpm2_parse_pcr_argument(const char *arg, uint32_t *mask);
|
|
+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_to_mask(const char *arg, uint32_t *mask);
|
|
|
|
int tpm2_load_pcr_signature(const char *path, JsonVariant **ret);
|
|
int tpm2_load_pcr_public_key(const char *path, void **ret_pubkey, size_t *ret_pubkey_size);
|
|
diff --git a/src/test/test-tpm2.c b/src/test/test-tpm2.c
|
|
index 8a4e9f5142..f121b4760a 100644
|
|
--- a/src/test/test-tpm2.c
|
|
+++ b/src/test/test-tpm2.c
|
|
@@ -4,39 +4,6 @@
|
|
#include "tpm2-util.h"
|
|
#include "tests.h"
|
|
|
|
-static void test_tpm2_pcr_mask_from_string_one(const char *s, uint32_t mask, int ret) {
|
|
- uint32_t m;
|
|
-
|
|
- assert_se(tpm2_pcr_mask_from_string(s, &m) == ret);
|
|
-
|
|
- if (ret >= 0)
|
|
- assert_se(m == mask);
|
|
-}
|
|
-
|
|
-TEST(tpm2_mask_from_string) {
|
|
- test_tpm2_pcr_mask_from_string_one("", 0, 0);
|
|
- test_tpm2_pcr_mask_from_string_one("0", 1, 0);
|
|
- test_tpm2_pcr_mask_from_string_one("1", 2, 0);
|
|
- test_tpm2_pcr_mask_from_string_one("0,1", 3, 0);
|
|
- test_tpm2_pcr_mask_from_string_one("0+1", 3, 0);
|
|
- test_tpm2_pcr_mask_from_string_one("0-1", 0, -EINVAL);
|
|
- test_tpm2_pcr_mask_from_string_one("0,1,2", 7, 0);
|
|
- test_tpm2_pcr_mask_from_string_one("0+1+2", 7, 0);
|
|
- test_tpm2_pcr_mask_from_string_one("0+1,2", 7, 0);
|
|
- test_tpm2_pcr_mask_from_string_one("0,1+2", 7, 0);
|
|
- test_tpm2_pcr_mask_from_string_one("0,2", 5, 0);
|
|
- test_tpm2_pcr_mask_from_string_one("0+2", 5, 0);
|
|
- test_tpm2_pcr_mask_from_string_one("foo", 0, -EINVAL);
|
|
- test_tpm2_pcr_mask_from_string_one("7+application-support", 8388736, 0);
|
|
- test_tpm2_pcr_mask_from_string_one("8+boot-loader-code", 272, 0);
|
|
- test_tpm2_pcr_mask_from_string_one("6+boot-loader-code,44", 0, -EINVAL);
|
|
- test_tpm2_pcr_mask_from_string_one("7,shim-policy,4", 16528, 0);
|
|
- test_tpm2_pcr_mask_from_string_one("sysexts,shim-policy+kernel-boot", 26624, 0);
|
|
- test_tpm2_pcr_mask_from_string_one("sysexts,shim+kernel-boot", 0, -EINVAL);
|
|
- test_tpm2_pcr_mask_from_string_one("sysexts+17+23", 8527872, 0);
|
|
- test_tpm2_pcr_mask_from_string_one("debug+24", 16842752, 0);
|
|
-}
|
|
-
|
|
TEST(pcr_index_from_string) {
|
|
assert_se(pcr_index_from_string("platform-code") == 0);
|
|
assert_se(pcr_index_from_string("0") == 0);
|
|
@@ -462,18 +429,19 @@ static bool digest_check(const TPM2B_DIGEST *digest, const char *expect) {
|
|
h = hexmem(digest->buffer, digest->size);
|
|
assert_se(h);
|
|
|
|
- return streq(expect, h);
|
|
+ return strcaseeq(expect, h);
|
|
}
|
|
|
|
-static void digest_init_sha256(TPM2B_DIGEST *digest, const char *hash) {
|
|
+static void digest_init(TPM2B_DIGEST *digest, const char *hash) {
|
|
_cleanup_free_ void *h = NULL;
|
|
size_t s = 0;
|
|
|
|
- assert_se(strlen(hash) == SHA256_DIGEST_SIZE * 2);
|
|
assert_se(strlen(hash) <= sizeof(digest->buffer) * 2);
|
|
|
|
assert_se(unhexmem(hash, strlen(hash), &h, &s) == 0);
|
|
- assert_se(s == SHA256_DIGEST_SIZE);
|
|
+
|
|
+ /* Make sure the length matches a known hash algorithm */
|
|
+ assert_se(IN_SET(s, TPM2_SHA1_DIGEST_SIZE, TPM2_SHA256_DIGEST_SIZE, TPM2_SHA384_DIGEST_SIZE, TPM2_SHA512_DIGEST_SIZE));
|
|
|
|
memcpy_safe(digest->buffer, h, s);
|
|
digest->size = s;
|
|
@@ -484,11 +452,11 @@ static void digest_init_sha256(TPM2B_DIGEST *digest, const char *hash) {
|
|
TEST(digest_many) {
|
|
TPM2B_DIGEST d, d0, d1, d2, d3, d4;
|
|
|
|
- digest_init_sha256(&d0, "0000000000000000000000000000000000000000000000000000000000000000");
|
|
- digest_init_sha256(&d1, "17b7703d9d00776310ba032e88c1a8c2a9c630ebdd799db622f6631530789175");
|
|
- digest_init_sha256(&d2, "12998c017066eb0d2a70b94e6ed3192985855ce390f321bbdb832022888bd251");
|
|
- digest_init_sha256(&d3, "c3a65887fedd3fb4f5d0047e906dff830bcbd1293160909eb4b05f485e7387ad");
|
|
- digest_init_sha256(&d4, "6491fb4bc08fc0b2ef47fc63db57e249917885e69d8c0d99667df83a59107a33");
|
|
+ digest_init(&d0, "0000000000000000000000000000000000000000000000000000000000000000");
|
|
+ digest_init(&d1, "17b7703d9d00776310ba032e88c1a8c2a9c630ebdd799db622f6631530789175");
|
|
+ digest_init(&d2, "12998c017066eb0d2a70b94e6ed3192985855ce390f321bbdb832022888bd251");
|
|
+ digest_init(&d3, "c3a65887fedd3fb4f5d0047e906dff830bcbd1293160909eb4b05f485e7387ad");
|
|
+ digest_init(&d4, "6491fb4bc08fc0b2ef47fc63db57e249917885e69d8c0d99667df83a59107a33");
|
|
|
|
/* tpm2_digest_init, tpm2_digest_rehash */
|
|
d = (TPM2B_DIGEST){ .size = 1, .buffer = { 2, }, };
|
|
@@ -552,6 +520,191 @@ TEST(digest_many) {
|
|
assert_se(digest_check(&d, "02ecb0628264235111e0053e271092981c8b15d59cd46617836bee3149a4ecb0"));
|
|
}
|
|
|
|
+static void check_parse_pcr_argument(
|
|
+ const char *arg,
|
|
+ const Tpm2PCRValue *prev_values,
|
|
+ size_t n_prev_values,
|
|
+ const Tpm2PCRValue *expected_values,
|
|
+ size_t n_expected_values) {
|
|
+
|
|
+ _cleanup_free_ Tpm2PCRValue *values = NULL;
|
|
+ size_t n_values = 0;
|
|
+
|
|
+ if (n_prev_values > 0) {
|
|
+ assert_se(GREEDY_REALLOC_APPEND(values, n_values, prev_values, n_prev_values));
|
|
+ assert_se(tpm2_parse_pcr_argument_append(arg, &values, &n_values) == 0);
|
|
+ } else
|
|
+ assert_se(tpm2_parse_pcr_argument(arg, &values, &n_values) == 0);
|
|
+
|
|
+ assert_se(n_values == n_expected_values);
|
|
+ for (size_t i = 0; i < n_values; i++) {
|
|
+ const Tpm2PCRValue *v = &values[i], *e = &expected_values[i];
|
|
+ //tpm2_log_debug_pcr_value(e, "Expected value");
|
|
+ //tpm2_log_debug_pcr_value(v, "Actual value");
|
|
+
|
|
+ assert_se(v->index == e->index);
|
|
+ assert_se(v->hash == e->hash);
|
|
+ assert_se(v->value.size == e->value.size);
|
|
+ assert_se(memcmp(v->value.buffer, e->value.buffer, e->value.size) == 0);
|
|
+ }
|
|
+
|
|
+ size_t hash_count;
|
|
+ assert_se(tpm2_pcr_values_hash_count(expected_values, n_expected_values, &hash_count) == 0);
|
|
+ if (hash_count == 1) {
|
|
+ uint32_t mask = UINT32_MAX, expected_mask = 0;
|
|
+
|
|
+ if (n_prev_values > 0)
|
|
+ assert_se(tpm2_pcr_values_to_mask(prev_values, n_prev_values, prev_values[0].hash, &mask) == 0);
|
|
+
|
|
+ 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);
|
|
+ }
|
|
+
|
|
+ size_t old_n_values = n_values;
|
|
+ assert_se(tpm2_parse_pcr_argument_append("", &values, &n_values) == 0);
|
|
+ assert_se(values);
|
|
+ assert_se(n_values == old_n_values);
|
|
+}
|
|
+
|
|
+static void check_parse_pcr_argument_to_mask(const char *arg, int mask) {
|
|
+ uint32_t m = 0;
|
|
+ int r = tpm2_parse_pcr_argument_to_mask(arg, &m);
|
|
+
|
|
+ if (mask < 0)
|
|
+ assert_se(mask == r);
|
|
+ else
|
|
+ assert_se((uint32_t) mask == m);
|
|
+}
|
|
+
|
|
+TEST(parse_pcr_argument) {
|
|
+ _cleanup_free_ Tpm2PCRValue *t0p = NULL;
|
|
+ size_t n_t0p;
|
|
+ assert_se(tpm2_parse_pcr_argument("", &t0p, &n_t0p) == 0);
|
|
+ assert_se(n_t0p == 0);
|
|
+ assert_se(tpm2_parse_pcr_argument_append("", &t0p, &n_t0p) == 0);
|
|
+ assert_se(n_t0p == 0);
|
|
+ uint32_t m0 = 0xf;
|
|
+ assert_se(tpm2_parse_pcr_argument_to_mask("", &m0) == 0);
|
|
+ assert_se(m0 == 0);
|
|
+ assert_se(tpm2_parse_pcr_argument_to_mask("", &m0) == 0);
|
|
+ assert_se(m0 == 0);
|
|
+
|
|
+ Tpm2PCRValue t1[] = {
|
|
+ TPM2_PCR_VALUE_MAKE(0, 0, {}),
|
|
+ TPM2_PCR_VALUE_MAKE(4, 0, {}),
|
|
+ TPM2_PCR_VALUE_MAKE(7, 0, {}),
|
|
+ TPM2_PCR_VALUE_MAKE(11, 0, {}),
|
|
+ };
|
|
+ check_parse_pcr_argument("0,4,7,11", NULL, 0, t1, ELEMENTSOF(t1));
|
|
+ check_parse_pcr_argument("11,4,7,0", NULL, 0, t1, ELEMENTSOF(t1));
|
|
+ check_parse_pcr_argument("7,4,0,11", NULL, 0, t1, ELEMENTSOF(t1));
|
|
+ check_parse_pcr_argument("11,7,4,0", NULL, 0, t1, ELEMENTSOF(t1));
|
|
+ check_parse_pcr_argument("0+4+7+11", NULL, 0, t1, ELEMENTSOF(t1));
|
|
+ check_parse_pcr_argument("0,4+7,11", NULL, 0, t1, ELEMENTSOF(t1));
|
|
+
|
|
+ Tpm2PCRValue t2[] = {
|
|
+ TPM2_PCR_VALUE_MAKE(0, TPM2_ALG_SHA1, {}),
|
|
+ TPM2_PCR_VALUE_MAKE(4, TPM2_ALG_SHA1, {}),
|
|
+ TPM2_PCR_VALUE_MAKE(7, TPM2_ALG_SHA1, {}),
|
|
+ TPM2_PCR_VALUE_MAKE(11, TPM2_ALG_SHA1, {}),
|
|
+ };
|
|
+ check_parse_pcr_argument("0:sha1,4,7,11", NULL, 0, t2, ELEMENTSOF(t2));
|
|
+ check_parse_pcr_argument("11,4,7,0:sha1", NULL, 0, t2, ELEMENTSOF(t2));
|
|
+ check_parse_pcr_argument("7,4:sha1,0,11", NULL, 0, t2, ELEMENTSOF(t2));
|
|
+ check_parse_pcr_argument("0:sha1,4:sha1,7:sha1,11:sha1", NULL, 0, t2, ELEMENTSOF(t2));
|
|
+ check_parse_pcr_argument("0:sha1+4:sha1,11:sha1+7:sha1", NULL, 0, t2, ELEMENTSOF(t2));
|
|
+
|
|
+ Tpm2PCRValue t3[] = {
|
|
+ TPM2_PCR_VALUE_MAKE(0, TPM2_ALG_SHA1, {}),
|
|
+ TPM2_PCR_VALUE_MAKE(1, TPM2_ALG_SHA1, {}),
|
|
+ TPM2_PCR_VALUE_MAKE(2, TPM2_ALG_SHA1, {}),
|
|
+ TPM2_PCR_VALUE_MAKE(3, TPM2_ALG_SHA1, {}),
|
|
+ TPM2_PCR_VALUE_MAKE(4, TPM2_ALG_SHA1, {}),
|
|
+ TPM2_PCR_VALUE_MAKE(7, TPM2_ALG_SHA1, {}),
|
|
+ TPM2_PCR_VALUE_MAKE(11, TPM2_ALG_SHA1, {}),
|
|
+ TPM2_PCR_VALUE_MAKE(12, TPM2_ALG_SHA1, {}),
|
|
+ };
|
|
+ check_parse_pcr_argument("1,2,3,12", t2, ELEMENTSOF(t2), t3, ELEMENTSOF(t3));
|
|
+ check_parse_pcr_argument("12,2,3,1", t2, ELEMENTSOF(t2), t3, ELEMENTSOF(t3));
|
|
+ check_parse_pcr_argument("1,2,3,12:sha1", t1, ELEMENTSOF(t1), t3, ELEMENTSOF(t3));
|
|
+ check_parse_pcr_argument("1,2,3,12:sha1", t2, ELEMENTSOF(t2), t3, ELEMENTSOF(t3));
|
|
+ check_parse_pcr_argument("1:sha1,2,3,12", t1, ELEMENTSOF(t1), t3, ELEMENTSOF(t3));
|
|
+ check_parse_pcr_argument("1:sha1,2,3,12", t2, ELEMENTSOF(t2), t3, ELEMENTSOF(t3));
|
|
+ check_parse_pcr_argument("1:sha1,2:sha1,3:sha1,12:sha1", t1, ELEMENTSOF(t1), t3, ELEMENTSOF(t3));
|
|
+ check_parse_pcr_argument("1:sha1,2:sha1,3:sha1,12:sha1", t2, ELEMENTSOF(t2), t3, ELEMENTSOF(t3));
|
|
+
|
|
+ TPM2B_DIGEST d4;
|
|
+ digest_init(&d4, "FCE7F1083082B16CFE2B085DD7858BB11A37C09B78E36C79E5A2FD529353C4E2");
|
|
+ Tpm2PCRValue t4[] = {
|
|
+ TPM2_PCR_VALUE_MAKE(0, TPM2_ALG_SHA256, {}),
|
|
+ TPM2_PCR_VALUE_MAKE(1, TPM2_ALG_SHA256, d4),
|
|
+ TPM2_PCR_VALUE_MAKE(2, TPM2_ALG_SHA256, {}),
|
|
+ TPM2_PCR_VALUE_MAKE(3, TPM2_ALG_SHA256, {}),
|
|
+ TPM2_PCR_VALUE_MAKE(4, TPM2_ALG_SHA256, {}),
|
|
+ TPM2_PCR_VALUE_MAKE(7, TPM2_ALG_SHA256, {}),
|
|
+ TPM2_PCR_VALUE_MAKE(11, TPM2_ALG_SHA256, {}),
|
|
+ TPM2_PCR_VALUE_MAKE(12, TPM2_ALG_SHA256, {}),
|
|
+ };
|
|
+ check_parse_pcr_argument("1:sha256=0xFCE7F1083082B16CFE2B085DD7858BB11A37C09B78E36C79E5A2FD529353C4E2,2,3,12", t1, ELEMENTSOF(t1), t4, ELEMENTSOF(t4));
|
|
+ check_parse_pcr_argument("12,2,3,1:sha256=FCE7F1083082B16CFE2B085DD7858BB11A37C09B78E36C79E5A2FD529353C4E2", t1, ELEMENTSOF(t1), t4, ELEMENTSOF(t4));
|
|
+ check_parse_pcr_argument("12,2,3,1:sha256=0xFCE7F1083082B16CFE2B085DD7858BB11A37C09B78E36C79E5A2FD529353C4E2", t1, ELEMENTSOF(t1), t4, ELEMENTSOF(t4));
|
|
+ check_parse_pcr_argument("1:sha256=0xFCE7F1083082B16CFE2B085DD7858BB11A37C09B78E36C79E5A2FD529353C4E2,2,3,12:SHA256", t1, ELEMENTSOF(t1), t4, ELEMENTSOF(t4));
|
|
+ check_parse_pcr_argument("1:sha256=0xFCE7F1083082B16CFE2B085DD7858BB11A37C09B78E36C79E5A2FD529353C4E2,2,3,12", t1, ELEMENTSOF(t1), t4, ELEMENTSOF(t4));
|
|
+ check_parse_pcr_argument("1:sha256=FCE7F1083082B16CFE2B085DD7858BB11A37C09B78E36C79E5A2FD529353C4E2,2:sha256,3:sha256,12:sha256", t1, ELEMENTSOF(t1), t4, ELEMENTSOF(t4));
|
|
+ check_parse_pcr_argument("1:sha256=0xFCE7F1083082B16CFE2B085DD7858BB11A37C09B78E36C79E5A2FD529353C4E2,2:sha256,3:sha256,12:sha256", t1, ELEMENTSOF(t1), t4, ELEMENTSOF(t4));
|
|
+
|
|
+ TPM2B_DIGEST d5;
|
|
+ digest_init(&d5, "0F21EADB7F27377668E3C8069BE88D116491FBEE");
|
|
+ Tpm2PCRValue t5[] = {
|
|
+ TPM2_PCR_VALUE_MAKE(1, TPM2_ALG_SHA1, d5),
|
|
+ TPM2_PCR_VALUE_MAKE(0, TPM2_ALG_SHA256, {}),
|
|
+ TPM2_PCR_VALUE_MAKE(1, TPM2_ALG_SHA256, d4),
|
|
+ TPM2_PCR_VALUE_MAKE(2, TPM2_ALG_SHA256, {}),
|
|
+ TPM2_PCR_VALUE_MAKE(3, TPM2_ALG_SHA256, {}),
|
|
+ TPM2_PCR_VALUE_MAKE(4, TPM2_ALG_SHA256, {}),
|
|
+ TPM2_PCR_VALUE_MAKE(7, TPM2_ALG_SHA256, {}),
|
|
+ TPM2_PCR_VALUE_MAKE(11, TPM2_ALG_SHA256, {}),
|
|
+ TPM2_PCR_VALUE_MAKE(12, TPM2_ALG_SHA256, {}),
|
|
+ TPM2_PCR_VALUE_MAKE(5, TPM2_ALG_SHA384, {}),
|
|
+ TPM2_PCR_VALUE_MAKE(6, TPM2_ALG_SHA512, {}),
|
|
+ };
|
|
+ check_parse_pcr_argument("0,1:sha256=0xFCE7F1083082B16CFE2B085DD7858BB11A37C09B78E36C79E5A2FD529353C4E2,1:sha1=0F21EADB7F27377668E3C8069BE88D116491FBEE,2,3,4,7,11,12,5:sha384,6:sha512", NULL, 0, t5, ELEMENTSOF(t5));
|
|
+ check_parse_pcr_argument("1:sha1=0F21EADB7F27377668E3C8069BE88D116491FBEE,6:sha512,5:sha384", t4, ELEMENTSOF(t4), t5, ELEMENTSOF(t5));
|
|
+
|
|
+ Tpm2PCRValue *v = NULL;
|
|
+ size_t n_v = 0;
|
|
+ assert_se(tpm2_parse_pcr_argument("1,100", &v, &n_v) < 0);
|
|
+ assert_se(tpm2_parse_pcr_argument("1,2=123456abc", &v, &n_v) < 0);
|
|
+ assert_se(tpm2_parse_pcr_argument("1,2:invalid", &v, &n_v) < 0);
|
|
+ assert_se(tpm2_parse_pcr_argument("1:sha1=invalid", &v, &n_v) < 0);
|
|
+ assert_se(v == NULL);
|
|
+ assert_se(n_v == 0);
|
|
+
|
|
+ check_parse_pcr_argument_to_mask("", 0x0);
|
|
+ check_parse_pcr_argument_to_mask("0", 0x1);
|
|
+ check_parse_pcr_argument_to_mask("1", 0x2);
|
|
+ check_parse_pcr_argument_to_mask("0,1", 0x3);
|
|
+ check_parse_pcr_argument_to_mask("0+1", 0x3);
|
|
+ check_parse_pcr_argument_to_mask("0-1", -EINVAL);
|
|
+ check_parse_pcr_argument_to_mask("foo", -EINVAL);
|
|
+ check_parse_pcr_argument_to_mask("0,1,2", 0x7);
|
|
+ check_parse_pcr_argument_to_mask("0+1+2", 0x7);
|
|
+ check_parse_pcr_argument_to_mask("0+1,2", 0x7);
|
|
+ check_parse_pcr_argument_to_mask("0,1+2", 0x7);
|
|
+ check_parse_pcr_argument_to_mask("0,2", 0x5);
|
|
+ check_parse_pcr_argument_to_mask("0+2", 0x5);
|
|
+ check_parse_pcr_argument_to_mask("7+application-support", 0x800080);
|
|
+ check_parse_pcr_argument_to_mask("8+boot-loader-code", 0x110);
|
|
+ check_parse_pcr_argument_to_mask("7,shim-policy,4", 0x4090);
|
|
+ check_parse_pcr_argument_to_mask("sysexts,shim-policy+kernel-boot", 0x6800);
|
|
+ check_parse_pcr_argument_to_mask("sysexts,shim+kernel-boot", -EINVAL);
|
|
+ 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);
|
|
+}
|
|
+
|
|
static void tpm2b_public_init(TPM2B_PUBLIC *public) {
|
|
TPMT_PUBLIC tpmt = {
|
|
.type = TPM2_ALG_RSA,
|
|
@@ -598,7 +751,7 @@ TEST(calculate_name) {
|
|
TEST(calculate_policy_auth_value) {
|
|
TPM2B_DIGEST d;
|
|
|
|
- digest_init_sha256(&d, "0000000000000000000000000000000000000000000000000000000000000000");
|
|
+ digest_init(&d, "0000000000000000000000000000000000000000000000000000000000000000");
|
|
assert_se(tpm2_calculate_policy_auth_value(&d) == 0);
|
|
assert_se(digest_check(&d, "8fcd2169ab92694e0c633f1ab772842b8241bbc20288981fc7ac1eddc1fddb0e"));
|
|
assert_se(tpm2_calculate_policy_auth_value(&d) == 0);
|
|
@@ -610,7 +763,7 @@ TEST(calculate_policy_authorize) {
|
|
TPM2B_DIGEST d;
|
|
|
|
tpm2b_public_init(&public);
|
|
- digest_init_sha256(&d, "0000000000000000000000000000000000000000000000000000000000000000");
|
|
+ digest_init(&d, "0000000000000000000000000000000000000000000000000000000000000000");
|
|
assert_se(tpm2_calculate_policy_authorize(&public, NULL, &d) == 0);
|
|
assert_se(digest_check(&d, "95213a3784eaab04f427bc7e8851c2f1df0903be8e42428ec25dcefd907baff1"));
|
|
assert_se(tpm2_calculate_policy_authorize(&public, NULL, &d) == 0);
|
|
@@ -620,24 +773,24 @@ TEST(calculate_policy_authorize) {
|
|
TEST(calculate_policy_pcr) {
|
|
TPM2B_DIGEST d, dN[16];
|
|
|
|
- digest_init_sha256(&dN[ 0], "2124793cbbe60c3a8637d3b84a5d054e87c351e1469a285acc04755e8b204dec");
|
|
- digest_init_sha256(&dN[ 1], "bf7592f18adcfdc549fc0b94939f5069a24697f9cff4a0dca29014767b97559d");
|
|
- digest_init_sha256(&dN[ 2], "4b00cff9dee3a364979b2dc241b34568a8ad49fcf2713df259e47dff8875feed");
|
|
- digest_init_sha256(&dN[ 3], "3d458cfe55cc03ea1f443f1562beec8df51c75e14a9fcf9a7234a13f198e7969");
|
|
- digest_init_sha256(&dN[ 4], "368f85b3013041dfe203faaa364f00b07c5da7b1e5f1dbf2efb06fa6b9bd92de");
|
|
- digest_init_sha256(&dN[ 5], "c97c40369691c8e4aa78fb3a52655cd193b780a838b8e23f5f476576919db5e5");
|
|
- digest_init_sha256(&dN[ 6], "3d458cfe55cc03ea1f443f1562beec8df51c75e14a9fcf9a7234a13f198e7969");
|
|
- digest_init_sha256(&dN[ 7], "aa1154c9e0a774854ccbed4c8ce7e9b906b3d700a1a8db1772d0341a62dbe51b");
|
|
- digest_init_sha256(&dN[ 8], "cfde439a2c06af3479ca6bdc60429b90553d65300c5cfcc40004a08c6b5ad81a");
|
|
- digest_init_sha256(&dN[ 9], "9c2bac22ef5ec84fcdb71c3ebf776cba1247e5da980e5ee08e45666a2edf0b8b");
|
|
- digest_init_sha256(&dN[10], "9885873f4d7348199ad286f8f2476d4f866940950f6f9fb9f945ed352dbdcbd2");
|
|
- digest_init_sha256(&dN[11], "42400ab950d21aa79d12cc4fdef67d1087a39ad64900619831c0974dbae54e44");
|
|
- digest_init_sha256(&dN[12], "767d064382e56ca1ad3bdcc6bc596112e6c2008b593d3570d24c2bfa64c4628c");
|
|
- digest_init_sha256(&dN[13], "30c16133175959408c9745d8dafadef5daf4b39cb2be04df0d60089bd46d3cc4");
|
|
- digest_init_sha256(&dN[14], "e3991b7ddd47be7e92726a832d6874c5349b52b789fa0db8b558c69fea29574e");
|
|
- digest_init_sha256(&dN[15], "852dae3ecb992bdeb13d6002fefeeffdd90feca8b378d56681ef2c885d0e5137");
|
|
-
|
|
- digest_init_sha256(&d, "0000000000000000000000000000000000000000000000000000000000000000");
|
|
+ digest_init(&dN[ 0], "2124793cbbe60c3a8637d3b84a5d054e87c351e1469a285acc04755e8b204dec");
|
|
+ digest_init(&dN[ 1], "bf7592f18adcfdc549fc0b94939f5069a24697f9cff4a0dca29014767b97559d");
|
|
+ digest_init(&dN[ 2], "4b00cff9dee3a364979b2dc241b34568a8ad49fcf2713df259e47dff8875feed");
|
|
+ digest_init(&dN[ 3], "3d458cfe55cc03ea1f443f1562beec8df51c75e14a9fcf9a7234a13f198e7969");
|
|
+ digest_init(&dN[ 4], "368f85b3013041dfe203faaa364f00b07c5da7b1e5f1dbf2efb06fa6b9bd92de");
|
|
+ digest_init(&dN[ 5], "c97c40369691c8e4aa78fb3a52655cd193b780a838b8e23f5f476576919db5e5");
|
|
+ digest_init(&dN[ 6], "3d458cfe55cc03ea1f443f1562beec8df51c75e14a9fcf9a7234a13f198e7969");
|
|
+ digest_init(&dN[ 7], "aa1154c9e0a774854ccbed4c8ce7e9b906b3d700a1a8db1772d0341a62dbe51b");
|
|
+ digest_init(&dN[ 8], "cfde439a2c06af3479ca6bdc60429b90553d65300c5cfcc40004a08c6b5ad81a");
|
|
+ digest_init(&dN[ 9], "9c2bac22ef5ec84fcdb71c3ebf776cba1247e5da980e5ee08e45666a2edf0b8b");
|
|
+ digest_init(&dN[10], "9885873f4d7348199ad286f8f2476d4f866940950f6f9fb9f945ed352dbdcbd2");
|
|
+ digest_init(&dN[11], "42400ab950d21aa79d12cc4fdef67d1087a39ad64900619831c0974dbae54e44");
|
|
+ digest_init(&dN[12], "767d064382e56ca1ad3bdcc6bc596112e6c2008b593d3570d24c2bfa64c4628c");
|
|
+ digest_init(&dN[13], "30c16133175959408c9745d8dafadef5daf4b39cb2be04df0d60089bd46d3cc4");
|
|
+ digest_init(&dN[14], "e3991b7ddd47be7e92726a832d6874c5349b52b789fa0db8b558c69fea29574e");
|
|
+ digest_init(&dN[15], "852dae3ecb992bdeb13d6002fefeeffdd90feca8b378d56681ef2c885d0e5137");
|
|
+
|
|
+ digest_init(&d, "0000000000000000000000000000000000000000000000000000000000000000");
|
|
Tpm2PCRValue v1[] = {
|
|
TPM2_PCR_VALUE_MAKE(4, TPM2_ALG_SHA256, dN[4]),
|
|
TPM2_PCR_VALUE_MAKE(7, TPM2_ALG_SHA256, dN[7]),
|
|
@@ -648,7 +801,7 @@ TEST(calculate_policy_pcr) {
|
|
assert_se(tpm2_calculate_policy_pcr(v1, ELEMENTSOF(v1), &d) == 0);
|
|
assert_se(digest_check(&d, "97e64bcabb64c1fa4b726528644926c8029f5b4458b0575c98c04fe225629a0b"));
|
|
|
|
- digest_init_sha256(&d, "0000000000000000000000000000000000000000000000000000000000000000");
|
|
+ digest_init(&d, "0000000000000000000000000000000000000000000000000000000000000000");
|
|
Tpm2PCRValue v2[] = {
|
|
TPM2_PCR_VALUE_MAKE( 0, TPM2_ALG_SHA256, dN[ 0]),
|
|
TPM2_PCR_VALUE_MAKE( 1, TPM2_ALG_SHA256, dN[ 1]),
|