203 changes: 202 additions & 1 deletion test/unit/test_tpm2_alg_util.c
Expand Up @@ -228,6 +228,199 @@ static void test_tpm2_alg_util_everything_is_tested(void **state) {
}
}

/* Test the digest specification langauge */

#define HASH_SHA "f1d2d2f924e986ac86fdf7b36c94bcdf32beec15"
#define HASH_SHA256 "c324d5e9514f00b1a42052666721fb0911090ca197bf831f6568e735bc8522c3"
#define HASH_SHA384 "8effdabfe14416214a250f935505250bd991f106065d899db6e19bdc8bf648f3ac0f1935c4f65fe8f798289b1a0d1e06"
#define HASH_SHA512 "0cf9180a764aba863a67b6d72f0918bc131c6772642cb2dce5a34f0a702f9470ddc2bf125c12198b1995c233c34b4afd346c54a2334c350a948a51b6e8b4e6b6"

#define test_digest(digest, expected_hash_str, expected_alg, expected_hash_len) \
do { \
UINT16 _expected_hash_len = expected_hash_len; \
BYTE expected_hash[expected_hash_len]; \
int rc = tpm2_util_hex_to_byte_structure(expected_hash_str, &_expected_hash_len, expected_hash); \
assert_true(rc == 0); \
\
assert_int_equal(digest->hashAlg, expected_alg); \
assert_memory_equal((BYTE *)&digest->digest, expected_hash, \
expected_hash_len); \
} while (0)

#define test_digest_sha1(digest) test_digest(digest, HASH_SHA, ALG_SHA1_VALUE, SHA1_DIGEST_SIZE)
#define test_digest_sha256(digest) test_digest(digest, HASH_SHA256, ALG_SHA256_VALUE, SHA256_DIGEST_SIZE)
#define test_digest_sha384(digest) test_digest(digest, HASH_SHA384, ALG_SHA384_VALUE, SHA384_DIGEST_SIZE)
#define test_digest_sha512(digest) test_digest(digest, HASH_SHA512, ALG_SHA512_VALUE, SHA512_DIGEST_SIZE)

#define get_single_digest_pcr_parse_test(friendly_hash) \
cmocka_unit_test(test_pcr_parse_digest_list_##friendly_hash)

#define add_single_digest_pcr_parse_test(pcrindex, friendly_hash, hash_value, hash_id, hash_size) \
static void test_pcr_parse_digest_list_##friendly_hash(void **state) { \
(void) state; \
\
char mutable_1[] = str(pcrindex)":"str(friendly_hash)"="hash_value; \
tpm2_pcr_digest_spec digest_spec[1]; \
char *optstr[1] = { \
mutable_1 \
}; \
\
bool res = pcr_parse_digest_list(optstr, 1, digest_spec); \
assert_true(res); \
\
TPMT_HA *digest = &digest_spec->digests.digests[0]; \
test_digest(digest, hash_value, hash_id, hash_size); \
}

add_single_digest_pcr_parse_test(4, sha, HASH_SHA,
ALG_SHA1_VALUE, SHA1_DIGEST_SIZE)

add_single_digest_pcr_parse_test(9, sha256, HASH_SHA256,
ALG_SHA256_VALUE, SHA256_DIGEST_SIZE)

add_single_digest_pcr_parse_test(67, sha384, HASH_SHA384,
ALG_SHA384_VALUE, SHA384_DIGEST_SIZE)

add_single_digest_pcr_parse_test(21, sha512, HASH_SHA512,
ALG_SHA512_VALUE, SHA512_DIGEST_SIZE)

static void test_pcr_parse_digest_list_many_items(void **state) {
(void) state;

char mutable_1[] = "12:sha="HASH_SHA;
char mutable_2[] = "5:sha256="HASH_SHA256;
char mutable_3[] = "7:sha512="HASH_SHA512;
char *optstr[] = {
mutable_1,
mutable_2,
mutable_3
};

tpm2_pcr_digest_spec digest_spec[ARRAY_LEN(optstr)];
bool res = pcr_parse_digest_list(optstr, ARRAY_LEN(digest_spec), digest_spec);
assert_true(res);

size_t i;
for (i=0; i < ARRAY_LEN(digest_spec); i++) {
tpm2_pcr_digest_spec *dspec = &digest_spec[i];

/* each pcr only has 1 alg hash specified */
assert_int_equal(dspec->digests.count, 1);

TPMT_HA *digest = &dspec->digests.digests[0];

switch (i) {
case 0:
assert_int_equal(dspec->pcr_index, 12);
test_digest_sha1(digest);
break;
case 1:
assert_int_equal(dspec->pcr_index, 5);
test_digest_sha256(digest);
break;
case 2:
assert_int_equal(dspec->pcr_index, 7);
test_digest_sha512(digest);
break;
default:
fail_msg("Missing algorithm test for: %s", optstr[i]);
}
}
}

static void test_pcr_parse_digest_list_compound(void **state) {
(void) state;

char mutable_1[] = "12:sha="HASH_SHA",sha256="HASH_SHA256",sha512="HASH_SHA512;
char *optstr[] = {
mutable_1,
};

tpm2_pcr_digest_spec digest_spec[ARRAY_LEN(optstr)];
bool res = pcr_parse_digest_list(optstr, ARRAY_LEN(digest_spec), digest_spec);
assert_true(res);

tpm2_pcr_digest_spec *dspec = &digest_spec[0];

assert_int_equal(12, dspec->pcr_index);
assert_int_equal(3, dspec->digests.count);

size_t i;
for (i=0; i < dspec->digests.count; i++) {
TPMT_HA *digest = &dspec->digests.digests[i];

switch (i) {
case 0:
test_digest_sha1(digest);
break;
case 1:
test_digest_sha256(digest);
break;
case 2:
test_digest_sha512(digest);
break;
default:
fail_msg("Missing algorithm test for: %u", dspec->digests.digests[i].hashAlg);
}
}
}

static void test_pcr_parse_digest_list_bad(void **state) {
(void) state;

char mutable_1[] = "12";
char *optstr[] = {
mutable_1,
};

tpm2_pcr_digest_spec digest_spec[ARRAY_LEN(optstr)];
bool res = pcr_parse_digest_list(optstr, ARRAY_LEN(digest_spec), digest_spec);
assert_false(res);

char mutable_2[] = "12:sha256";
optstr[0] = mutable_2;
res = pcr_parse_digest_list(optstr, ARRAY_LEN(digest_spec), digest_spec);
assert_false(res);

char mutable_3[] = "12:sha256=";
optstr[0] = mutable_3;
res = pcr_parse_digest_list(optstr, ARRAY_LEN(digest_spec), digest_spec);
assert_false(res);

char mutable_4[] = "12:sha256="HASH_SHA;
optstr[0] = mutable_4;
res = pcr_parse_digest_list(optstr, ARRAY_LEN(digest_spec), digest_spec);
assert_false(res);

char mutable_5[] = "12:sha256="HASH_SHA512;
optstr[0] = mutable_5;
res = pcr_parse_digest_list(optstr, ARRAY_LEN(digest_spec), digest_spec);
assert_false(res);

char mutable_6[] = "12:";
optstr[0] = mutable_6;
res = pcr_parse_digest_list(optstr, ARRAY_LEN(digest_spec), digest_spec);
assert_false(res);
}

static void test_pcr_parse_digest_list_bad_alg(void **state) {
(void) state;

char mutable_1[] = "12";
char *optstr[] = {
mutable_1,
};

tpm2_pcr_digest_spec digest_spec[ARRAY_LEN(optstr)];
bool res = pcr_parse_digest_list(optstr, ARRAY_LEN(digest_spec), digest_spec);
assert_false(res);

char mutable_2[] = "12:rsa="HASH_SHA;
optstr[0] = mutable_2;
res = pcr_parse_digest_list(optstr, ARRAY_LEN(digest_spec), digest_spec);
assert_false(res);
}

int main(int argc, char* argv[]) {
(void) argc;
(void) argv;
Expand Down Expand Up @@ -270,7 +463,15 @@ int main(int argc, char* argv[]) {
single_item_test_get(cbc),
single_item_test_get(cfb),
single_item_test_get(ecb),
cmocka_unit_test(test_tpm2_alg_util_everything_is_tested)
cmocka_unit_test(test_tpm2_alg_util_everything_is_tested),
get_single_digest_pcr_parse_test(sha),
get_single_digest_pcr_parse_test(sha256),
get_single_digest_pcr_parse_test(sha384),
get_single_digest_pcr_parse_test(sha512),
cmocka_unit_test(test_pcr_parse_digest_list_many_items),
cmocka_unit_test(test_pcr_parse_digest_list_compound),
cmocka_unit_test(test_pcr_parse_digest_list_bad),
cmocka_unit_test(test_pcr_parse_digest_list_bad_alg)
};

return cmocka_run_group_tests(tests, NULL, NULL);
Expand Down