mirror of
https://github.com/openharmony/third_party_fsverity-utils.git
synced 2026-07-01 10:05:35 -04:00
test_compute_digest: add more test cases
Signed-off-by: Eric Biggers <ebiggers@google.com>
This commit is contained in:
@@ -43,6 +43,12 @@ typedef uint64_t u64;
|
||||
_a < _b ? _a : _b; \
|
||||
})
|
||||
|
||||
#define max(a, b) ({ \
|
||||
__typeof__(a) _a = (a); \
|
||||
__typeof__(b) _b = (b); \
|
||||
_a > _b ? _a : _b; \
|
||||
})
|
||||
|
||||
#define roundup(x, y) ({ \
|
||||
__typeof__(y) _y = (y); \
|
||||
(((x) + _y - 1) / _y) * _y; \
|
||||
|
||||
+255
-17
@@ -7,7 +7,8 @@
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
#define SHA256_DIGEST_SIZE 32
|
||||
#include <ctype.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
struct mem_file {
|
||||
u8 *data;
|
||||
@@ -25,40 +26,277 @@ static int read_fn(void *fd, void *buf, size_t count)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
static int error_read_fn(void *fd __attribute__((unused)),
|
||||
void *buf __attribute__((unused)),
|
||||
size_t count __attribute__((unused)))
|
||||
{
|
||||
struct mem_file f = { .size = 1000000 };
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static const struct test_case {
|
||||
u32 hash_algorithm;
|
||||
u32 block_size;
|
||||
const char *salt;
|
||||
u64 file_size;
|
||||
const char *digest;
|
||||
} test_cases[] = {
|
||||
{ /* large file */
|
||||
.hash_algorithm = FS_VERITY_HASH_ALG_SHA256,
|
||||
.file_size = 1000000,
|
||||
.block_size = 4096,
|
||||
.digest = "\x48\xdf\x0c\x46\x23\x29\xcd\x87"
|
||||
"\x96\x61\xbd\x05\xb3\x9a\xa8\x1b"
|
||||
"\x05\xcc\x16\xaf\xd2\x7a\x71\x96"
|
||||
"\xa5\x59\xda\x83\x53\x1d\x39\xd9",
|
||||
}, { /* small file */
|
||||
.hash_algorithm = FS_VERITY_HASH_ALG_SHA256,
|
||||
.file_size = 100000,
|
||||
.block_size = 4096,
|
||||
.digest = "\xf2\x09\x6a\x36\xc5\xcd\xca\x4f"
|
||||
"\xa3\x3e\xe8\x85\x28\x33\x15\x0b"
|
||||
"\xb3\x24\x99\x2e\x54\x17\xa9\xd5"
|
||||
"\x71\xf1\xbf\xff\xf7\x3b\x9e\xfc",
|
||||
}, { /* single-block file */
|
||||
.hash_algorithm = FS_VERITY_HASH_ALG_SHA256,
|
||||
.file_size = 4096,
|
||||
.block_size = 4096,
|
||||
.digest = "\x6a\xc3\x99\x79\x01\x6e\x3d\xdf"
|
||||
"\x3d\x39\xff\xf6\xcb\x98\x4f\x7c"
|
||||
"\x11\x8a\xcd\xf1\x85\x29\x19\xf5"
|
||||
"\xc1\x00\xc4\xb1\x42\xc1\x81\x8e",
|
||||
}, { /* tiny file */
|
||||
.hash_algorithm = FS_VERITY_HASH_ALG_SHA256,
|
||||
.file_size = 1,
|
||||
.block_size = 4096,
|
||||
.digest = "\xb8\x03\x42\x95\x03\xd9\x59\x15"
|
||||
"\x82\x9b\x29\xfd\xbc\x8b\xba\xd1"
|
||||
"\x42\xf3\xab\xfd\x11\xb1\xca\xdf"
|
||||
"\x55\x26\x58\x2e\x68\x5c\x05\x51",
|
||||
}, { /* empty file */
|
||||
.hash_algorithm = FS_VERITY_HASH_ALG_SHA256,
|
||||
.file_size = 0,
|
||||
.block_size = 4096,
|
||||
.digest = "\x3d\x24\x8c\xa5\x42\xa2\x4f\xc6"
|
||||
"\x2d\x1c\x43\xb9\x16\xea\xe5\x01"
|
||||
"\x68\x78\xe2\x53\x3c\x88\x23\x84"
|
||||
"\x80\xb2\x61\x28\xa1\xf1\xaf\x95",
|
||||
}, { /* salt */
|
||||
.hash_algorithm = FS_VERITY_HASH_ALG_SHA256,
|
||||
.file_size = 1000000,
|
||||
.block_size = 4096,
|
||||
.salt = "abcd",
|
||||
.digest = "\x91\x79\x00\xb0\xd2\x99\x45\x4a"
|
||||
"\xa3\x04\xd5\xde\xbc\x6f\x39\xe4"
|
||||
"\xaf\x7b\x5a\xbe\x33\xbd\xbc\x56"
|
||||
"\x8d\x5d\x8f\x1e\x5c\x4d\x86\x52",
|
||||
}, { /* max length salt (32 bytes) */
|
||||
.hash_algorithm = FS_VERITY_HASH_ALG_SHA256,
|
||||
.file_size = 1000000,
|
||||
.block_size = 4096,
|
||||
.salt = "0123456789:;<=>?@ABCDEFGHIJKLMNO",
|
||||
.digest = "\xbc\x2d\x70\x32\x4c\x04\x8c\x22"
|
||||
"\x0a\x2c\xb1\x90\x83\x21\x40\x86"
|
||||
"\x3e\xb2\x68\xe6\x80\x42\x79\x39"
|
||||
"\xe5\xd4\x67\xbe\xa5\xec\x5a\xd9",
|
||||
}, { /* 1K block size */
|
||||
.hash_algorithm = FS_VERITY_HASH_ALG_SHA256,
|
||||
.file_size = 1000000,
|
||||
.block_size = 1024,
|
||||
.digest = "\xe9\xdf\x92\x7c\x14\xfc\xb9\x61"
|
||||
"\xd5\xf5\x1c\x66\x6d\x8a\xe4\xc1"
|
||||
"\x4f\xe4\xff\x98\xa3\x74\xc7\x33"
|
||||
"\xe8\x98\xd0\x0c\x9e\x74\xa8\xe3",
|
||||
}, { /* 512-byte block size */
|
||||
.hash_algorithm = FS_VERITY_HASH_ALG_SHA256,
|
||||
.file_size = 1000000,
|
||||
.block_size = 512,
|
||||
.digest = "\x03\x93\xee\x3d\xfd\x4a\x28\x96"
|
||||
"\x6e\x2a\xf4\xe0\x7c\xfa\x5b\x03"
|
||||
"\x2c\x30\xda\x5b\xb8\xe8\xef\x63"
|
||||
"\xb9\xa5\x5b\xf9\x63\x26\x23\x34",
|
||||
}, { /* 64K block size */
|
||||
.hash_algorithm = FS_VERITY_HASH_ALG_SHA256,
|
||||
.file_size = 1000000,
|
||||
.block_size = 65536,
|
||||
.digest = "\xf3\xb6\x41\x8f\x26\xd4\xd0\xe7"
|
||||
"\x47\x28\x19\x3b\xae\x76\xf1\x5c"
|
||||
"\xb4\xbb\x2c\xe9\x77\x74\x48\xd7"
|
||||
"\x6b\xd8\x13\x8b\x69\xec\x61\xc2",
|
||||
}, { /* SHA-512 */
|
||||
.hash_algorithm = FS_VERITY_HASH_ALG_SHA512,
|
||||
.file_size = 1000000,
|
||||
.block_size = 4096,
|
||||
.salt = "abcd",
|
||||
.digest = "\x84\x25\xc6\xd0\xc9\x4f\x84\xed"
|
||||
"\x90\x4c\x12\x93\x68\x45\xfb\xb7"
|
||||
"\xaf\x99\x53\x75\x37\x89\x71\x2d"
|
||||
"\xcc\x3b\xe1\x42\xdb\x3d\x4b\x6b"
|
||||
"\x47\xa3\x99\xad\x52\xaa\x60\x92"
|
||||
"\x56\xce\x29\xa9\x60\xbf\x4b\xb0"
|
||||
"\xe5\x95\xec\x38\x6c\xa5\x8c\x06"
|
||||
"\x51\x9d\x54\x6d\xc5\xb1\x97\xbb",
|
||||
}
|
||||
};
|
||||
|
||||
static void fix_digest_and_print(const struct test_case *t,
|
||||
const struct libfsverity_digest *d)
|
||||
{
|
||||
char alg_name[32] = {};
|
||||
size_t i;
|
||||
const struct libfsverity_merkle_tree_params params = {
|
||||
|
||||
strncpy(alg_name, libfsverity_get_hash_name(t->hash_algorithm),
|
||||
sizeof(alg_name) - 1);
|
||||
for (i = 0; i < sizeof(alg_name) - 1; i++)
|
||||
alg_name[i] = toupper((u8)alg_name[i]);
|
||||
|
||||
printf("\t}, {\n"
|
||||
"\t\t.hash_algorithm = FS_VERITY_HASH_ALG_%s,\n"
|
||||
"\t\t.file_size = %" PRIu64 ",\n"
|
||||
"\t\t.block_size = %u,\n",
|
||||
alg_name, t->file_size, t->block_size);
|
||||
if (t->salt != NULL)
|
||||
printf("\t\t.salt = \"%s\",\n", t->salt);
|
||||
for (i = 0; i < d->digest_size; i++) {
|
||||
if (i == 0)
|
||||
printf("\t\t.digest = \"");
|
||||
else if (i % 8 == 0)
|
||||
printf("\t\t\t \"");
|
||||
printf("\\x%02x", d->digest[i]);
|
||||
if (i + 1 == d->digest_size)
|
||||
printf("\",\n");
|
||||
else if (i % 8 == 7)
|
||||
printf("\"\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void test_invalid_params(void)
|
||||
{
|
||||
struct mem_file f = { .data = (u8 *)"abcd", .size = 4 };
|
||||
struct libfsverity_merkle_tree_params good_params = {
|
||||
.version = 1,
|
||||
.hash_algorithm = FS_VERITY_HASH_ALG_SHA256,
|
||||
.file_size = 4,
|
||||
.block_size = 4096,
|
||||
.salt_size = 4,
|
||||
.salt = (u8 *)"abcd",
|
||||
.file_size = f.size,
|
||||
};
|
||||
struct libfsverity_merkle_tree_params params;
|
||||
struct libfsverity_digest *d = NULL;
|
||||
|
||||
libfsverity_set_error_callback(NULL);
|
||||
|
||||
ASSERT(libfsverity_compute_digest(&f, read_fn, &good_params, &d) == 0);
|
||||
f.offset = 0;
|
||||
free(d);
|
||||
d = NULL;
|
||||
|
||||
/* missing required arguments */
|
||||
ASSERT(libfsverity_compute_digest(&f, NULL, &good_params, &d) == -EINVAL);
|
||||
ASSERT(libfsverity_compute_digest(&f, read_fn, NULL, &d) == -EINVAL);
|
||||
ASSERT(libfsverity_compute_digest(&f, read_fn, &good_params, NULL) == -EINVAL);
|
||||
|
||||
/* bad version */
|
||||
params = good_params;
|
||||
params.version = 0;
|
||||
ASSERT(libfsverity_compute_digest(&f, read_fn, ¶ms, &d) == -EINVAL);
|
||||
params.version = 1000;
|
||||
ASSERT(libfsverity_compute_digest(&f, read_fn, ¶ms, &d) == -EINVAL);
|
||||
|
||||
/* bad hash_algorithm */
|
||||
params = good_params;
|
||||
params.hash_algorithm = 0;
|
||||
ASSERT(libfsverity_compute_digest(&f, read_fn, ¶ms, &d) == -EINVAL);
|
||||
params.hash_algorithm = 1000;
|
||||
ASSERT(libfsverity_compute_digest(&f, read_fn, ¶ms, &d) == -EINVAL);
|
||||
|
||||
/* bad block_size */
|
||||
params = good_params;
|
||||
params.block_size = 0;
|
||||
ASSERT(libfsverity_compute_digest(&f, read_fn, ¶ms, &d) == -EINVAL);
|
||||
params.block_size = 1;
|
||||
ASSERT(libfsverity_compute_digest(&f, read_fn, ¶ms, &d) == -EINVAL);
|
||||
params.block_size = 4097;
|
||||
ASSERT(libfsverity_compute_digest(&f, read_fn, ¶ms, &d) == -EINVAL);
|
||||
|
||||
/* bad salt_size */
|
||||
params = good_params;
|
||||
params.salt_size = 1000;
|
||||
ASSERT(libfsverity_compute_digest(&f, read_fn, ¶ms, &d) == -EINVAL);
|
||||
params.salt = (u8 *)"";
|
||||
ASSERT(libfsverity_compute_digest(&f, read_fn, ¶ms, &d) == -EINVAL);
|
||||
|
||||
/* bad reserved fields */
|
||||
params = good_params;
|
||||
params.reserved1[0] = 1;
|
||||
ASSERT(libfsverity_compute_digest(&f, read_fn, ¶ms, &d) == -EINVAL);
|
||||
params = good_params;
|
||||
params.reserved1[ARRAY_SIZE(params.reserved1) - 1] = 1;
|
||||
ASSERT(libfsverity_compute_digest(&f, read_fn, ¶ms, &d) == -EINVAL);
|
||||
params = good_params;
|
||||
params.reserved2[0] = 1;
|
||||
ASSERT(libfsverity_compute_digest(&f, read_fn, ¶ms, &d) == -EINVAL);
|
||||
params = good_params;
|
||||
params.reserved2[ARRAY_SIZE(params.reserved2) - 1] = 1;
|
||||
ASSERT(libfsverity_compute_digest(&f, read_fn, ¶ms, &d) == -EINVAL);
|
||||
|
||||
/* error reading file */
|
||||
ASSERT(libfsverity_compute_digest(&f, error_read_fn, &good_params, &d) == -EIO);
|
||||
|
||||
ASSERT(d == NULL);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
const bool update = (argc == 2 && !strcmp(argv[1], "--update"));
|
||||
size_t i;
|
||||
struct mem_file f = {};
|
||||
struct libfsverity_merkle_tree_params params;
|
||||
struct libfsverity_digest *d;
|
||||
static const u8 expected_digest[SHA256_DIGEST_SIZE] =
|
||||
"\x91\x79\x00\xb0\xd2\x99\x45\x4a\xa3\x04\xd5\xde\xbc\x6f\x39"
|
||||
"\xe4\xaf\x7b\x5a\xbe\x33\xbd\xbc\x56\x8d\x5d\x8f\x1e\x5c\x4d"
|
||||
"\x86\x52";
|
||||
int err;
|
||||
|
||||
install_libfsverity_error_handler();
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(test_cases); i++)
|
||||
f.size = max(f.size, test_cases[i].file_size);
|
||||
|
||||
f.data = xmalloc(f.size);
|
||||
for (i = 0; i < f.size; i++)
|
||||
f.data[i] = (i % 11) + (i % 439) + (i % 1103);
|
||||
|
||||
err = libfsverity_compute_digest(&f, read_fn, ¶ms, &d);
|
||||
ASSERT(err == 0);
|
||||
for (i = 0; i < ARRAY_SIZE(test_cases); i++) {
|
||||
|
||||
ASSERT(d->digest_algorithm == FS_VERITY_HASH_ALG_SHA256);
|
||||
ASSERT(d->digest_size == SHA256_DIGEST_SIZE);
|
||||
ASSERT(!memcmp(d->digest, expected_digest, SHA256_DIGEST_SIZE));
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
params.version = 1;
|
||||
params.hash_algorithm = test_cases[i].hash_algorithm;
|
||||
params.file_size = test_cases[i].file_size;
|
||||
params.block_size = test_cases[i].block_size;
|
||||
if (test_cases[i].salt) {
|
||||
params.salt = (const u8 *)test_cases[i].salt;
|
||||
params.salt_size = strlen(test_cases[i].salt);
|
||||
}
|
||||
|
||||
f.size = test_cases[i].file_size;
|
||||
f.offset = 0;
|
||||
|
||||
err = libfsverity_compute_digest(&f, read_fn, ¶ms, &d);
|
||||
ASSERT(err == 0);
|
||||
|
||||
ASSERT(d->digest_algorithm == test_cases[i].hash_algorithm);
|
||||
ASSERT(d->digest_size ==
|
||||
libfsverity_get_digest_size(test_cases[i].hash_algorithm));
|
||||
if (update)
|
||||
fix_digest_and_print(&test_cases[i], d);
|
||||
else
|
||||
ASSERT(!memcmp(d->digest, test_cases[i].digest,
|
||||
d->digest_size));
|
||||
free(d);
|
||||
d = NULL;
|
||||
}
|
||||
free(f.data);
|
||||
free(d);
|
||||
if (update) {
|
||||
printf("\t}\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
test_invalid_params();
|
||||
printf("test_compute_digest passed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user