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.
This commit is contained in:
Dan Streetman 2023-07-12 22:36:37 -04:00
parent 6e8fb3ad5f
commit 07c0406117
7 changed files with 358 additions and 125 deletions

View file

@ -860,7 +860,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;
@ -874,7 +874,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;

View file

@ -356,7 +356,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;
@ -377,7 +377,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;

View file

@ -399,7 +399,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;

View file

@ -6447,7 +6447,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;
@ -6461,7 +6461,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;

View file

@ -4259,45 +4259,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;
int r;
@ -4678,29 +4639,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 */
if (isempty(arg)) {
*mask = 0;
return 0;
}
r = tpm2_pcr_mask_from_string(arg, &m);
_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;
if (*mask == UINT32_MAX)
*mask = m;
else
*mask |= m;
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;
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;
}
size_t hash_count;
r = tpm2_pcr_values_hash_count(pcr_values, n_pcr_values, &hash_count);
if (r < 0)
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 (*ret_mask == UINT32_MAX)
*ret_mask = new_mask;
else
*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) {

View file

@ -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;
@ -257,7 +256,9 @@ enum {
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);

View file

@ -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", 0, -EINVAL);
}
TEST(pcr_index_from_string) {
assert_se(pcr_index_from_string("platform-code") == 0);
assert_se(pcr_index_from_string("0") == 0);
@ -463,18 +430,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;
@ -485,11 +453,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, }, };
@ -553,6 +521,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,
@ -599,7 +752,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);
@ -611,7 +764,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);
@ -621,24 +774,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(&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_sha256(&d, "0000000000000000000000000000000000000000000000000000000000000000");
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]),
@ -649,7 +802,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]),