mirror of
https://github.com/openharmony/third_party_fsverity-utils.git
synced 2026-07-01 10:05:35 -04:00
lib/compute_digest: add default hash_algorithm and block_size
If hash_algorithm is left 0, default it to FS_VERITY_HASH_ALG_SHA256; and if block_size is left 0, default it to 4096 bytes. While it's nice to be explicit, having defaults makes things easier for library users. Acked-by: Luca Boccassi <luca.boccassi@microsoft.com> Link: https://lore.kernel.org/r/20201116205628.262173-3-ebiggers@kernel.org Signed-off-by: Eric Biggers <ebiggers@google.com>
This commit is contained in:
+36
-11
@@ -27,15 +27,42 @@ extern "C" {
|
||||
#define FS_VERITY_HASH_ALG_SHA256 1
|
||||
#define FS_VERITY_HASH_ALG_SHA512 2
|
||||
|
||||
/**
|
||||
* struct libfsverity_merkle_tree_params - properties of a file's Merkle tree
|
||||
*
|
||||
* Zero this, then fill in at least @version and @file_size.
|
||||
*/
|
||||
struct libfsverity_merkle_tree_params {
|
||||
uint32_t version; /* must be 1 */
|
||||
uint32_t hash_algorithm; /* one of FS_VERITY_HASH_ALG_* */
|
||||
uint64_t file_size; /* file size in bytes */
|
||||
uint32_t block_size; /* Merkle tree block size in bytes */
|
||||
uint32_t salt_size; /* salt size in bytes (0 if unsalted) */
|
||||
const uint8_t *salt; /* pointer to salt (optional) */
|
||||
uint64_t reserved1[8]; /* must be 0 */
|
||||
uintptr_t reserved2[8]; /* must be 0 */
|
||||
|
||||
/** @version: must be 1 */
|
||||
uint32_t version;
|
||||
|
||||
/**
|
||||
* @hash_algorithm: one of FS_VERITY_HASH_ALG_*, or 0 to use the default
|
||||
* of FS_VERITY_HASH_ALG_SHA256
|
||||
*/
|
||||
uint32_t hash_algorithm;
|
||||
|
||||
/** @file_size: the file size in bytes */
|
||||
uint64_t file_size;
|
||||
|
||||
/**
|
||||
* @block_size: the Merkle tree block size in bytes, or 0 to use the
|
||||
* default of 4096 bytes
|
||||
*/
|
||||
uint32_t block_size;
|
||||
|
||||
/** @salt_size: the salt size in bytes, or 0 if unsalted */
|
||||
uint32_t salt_size;
|
||||
|
||||
/** @salt: pointer to the salt, or NULL if unsalted */
|
||||
const uint8_t *salt;
|
||||
|
||||
/** @reserved1: must be 0 */
|
||||
uint64_t reserved1[8];
|
||||
|
||||
/** @reserved2: must be 0 */
|
||||
uintptr_t reserved2[8];
|
||||
};
|
||||
|
||||
struct libfsverity_digest {
|
||||
@@ -69,9 +96,7 @@ typedef int (*libfsverity_read_fn_t)(void *fd, void *buf, size_t count);
|
||||
* digest computed over the entire file.
|
||||
* @fd: context that will be passed to @read_fn
|
||||
* @read_fn: a function that will read the data of the file
|
||||
* @params: struct libfsverity_merkle_tree_params specifying the fs-verity
|
||||
* version, the hash algorithm, the file size, the block size, and
|
||||
* optionally a salt. Reserved fields must be zero.
|
||||
* @params: Pointer to the Merkle tree parameters
|
||||
* @digest_ret: Pointer to pointer for computed digest.
|
||||
*
|
||||
* Returns:
|
||||
|
||||
+16
-11
@@ -164,6 +164,8 @@ libfsverity_compute_digest(void *fd, libfsverity_read_fn_t read_fn,
|
||||
const struct libfsverity_merkle_tree_params *params,
|
||||
struct libfsverity_digest **digest_ret)
|
||||
{
|
||||
u32 alg_num;
|
||||
u32 block_size;
|
||||
const struct fsverity_hash_alg *hash_alg;
|
||||
struct hash_ctx *hash = NULL;
|
||||
struct libfsverity_digest *digest;
|
||||
@@ -179,9 +181,13 @@ libfsverity_compute_digest(void *fd, libfsverity_read_fn_t read_fn,
|
||||
params->version);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!is_power_of_2(params->block_size)) {
|
||||
|
||||
alg_num = params->hash_algorithm ?: FS_VERITY_HASH_ALG_DEFAULT;
|
||||
block_size = params->block_size ?: FS_VERITY_BLOCK_SIZE_DEFAULT;
|
||||
|
||||
if (!is_power_of_2(block_size)) {
|
||||
libfsverity_error_msg("unsupported block size (%u)",
|
||||
params->block_size);
|
||||
block_size);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (params->salt_size > sizeof(desc.salt)) {
|
||||
@@ -201,16 +207,15 @@ libfsverity_compute_digest(void *fd, libfsverity_read_fn_t read_fn,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
hash_alg = libfsverity_find_hash_alg_by_num(params->hash_algorithm);
|
||||
hash_alg = libfsverity_find_hash_alg_by_num(alg_num);
|
||||
if (!hash_alg) {
|
||||
libfsverity_error_msg("unknown hash algorithm: %u",
|
||||
params->hash_algorithm);
|
||||
libfsverity_error_msg("unknown hash algorithm: %u", alg_num);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (params->block_size < 2 * hash_alg->digest_size) {
|
||||
if (block_size < 2 * hash_alg->digest_size) {
|
||||
libfsverity_error_msg("block size (%u) too small for hash algorithm %s",
|
||||
params->block_size, hash_alg->name);
|
||||
block_size, hash_alg->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -220,8 +225,8 @@ libfsverity_compute_digest(void *fd, libfsverity_read_fn_t read_fn,
|
||||
|
||||
memset(&desc, 0, sizeof(desc));
|
||||
desc.version = 1;
|
||||
desc.hash_algorithm = params->hash_algorithm;
|
||||
desc.log_blocksize = ilog2(params->block_size);
|
||||
desc.hash_algorithm = alg_num;
|
||||
desc.log_blocksize = ilog2(block_size);
|
||||
desc.data_size = cpu_to_le64(params->file_size);
|
||||
if (params->salt_size != 0) {
|
||||
memcpy(desc.salt, params->salt, params->salt_size);
|
||||
@@ -229,7 +234,7 @@ libfsverity_compute_digest(void *fd, libfsverity_read_fn_t read_fn,
|
||||
}
|
||||
|
||||
err = compute_root_hash(fd, read_fn, params->file_size, hash,
|
||||
params->block_size, params->salt,
|
||||
block_size, params->salt,
|
||||
params->salt_size, desc.root_hash);
|
||||
if (err)
|
||||
goto out;
|
||||
@@ -239,7 +244,7 @@ libfsverity_compute_digest(void *fd, libfsverity_read_fn_t read_fn,
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
digest->digest_algorithm = params->hash_algorithm;
|
||||
digest->digest_algorithm = alg_num;
|
||||
digest->digest_size = hash_alg->digest_size;
|
||||
libfsverity_hash_full(hash, &desc, sizeof(desc), digest->digest);
|
||||
*digest_ret = digest;
|
||||
|
||||
@@ -19,6 +19,12 @@
|
||||
|
||||
#define LIBEXPORT __attribute__((visibility("default")))
|
||||
|
||||
/* The hash algorithm that libfsverity assumes when none is specified */
|
||||
#define FS_VERITY_HASH_ALG_DEFAULT FS_VERITY_HASH_ALG_SHA256
|
||||
|
||||
/* The block size that libfsverity assumes when none is specified */
|
||||
#define FS_VERITY_BLOCK_SIZE_DEFAULT 4096
|
||||
|
||||
/* hash_algs.c */
|
||||
|
||||
struct fsverity_hash_alg {
|
||||
|
||||
@@ -86,12 +86,6 @@ int fsverity_cmd_digest(const struct fsverity_command *cmd,
|
||||
if (argc < 1)
|
||||
goto out_usage;
|
||||
|
||||
if (tree_params.hash_algorithm == 0)
|
||||
tree_params.hash_algorithm = FS_VERITY_HASH_ALG_DEFAULT;
|
||||
|
||||
if (tree_params.block_size == 0)
|
||||
tree_params.block_size = 4096;
|
||||
|
||||
for (int i = 0; i < argc; i++) {
|
||||
struct fsverity_signed_digest *d = NULL;
|
||||
struct libfsverity_digest *digest = NULL;
|
||||
@@ -137,7 +131,7 @@ int fsverity_cmd_digest(const struct fsverity_command *cmd,
|
||||
printf("%s %s\n", digest_hex, argv[i]);
|
||||
else
|
||||
printf("%s:%s %s\n",
|
||||
libfsverity_get_hash_name(tree_params.hash_algorithm),
|
||||
libfsverity_get_hash_name(digest->digest_algorithm),
|
||||
digest_hex, argv[i]);
|
||||
|
||||
filedes_close(&file);
|
||||
|
||||
+1
-8
@@ -101,12 +101,6 @@ int fsverity_cmd_sign(const struct fsverity_command *cmd,
|
||||
if (argc != 2)
|
||||
goto out_usage;
|
||||
|
||||
if (tree_params.hash_algorithm == 0)
|
||||
tree_params.hash_algorithm = FS_VERITY_HASH_ALG_DEFAULT;
|
||||
|
||||
if (tree_params.block_size == 0)
|
||||
tree_params.block_size = 4096;
|
||||
|
||||
if (sig_params.keyfile == NULL) {
|
||||
error_msg("Missing --key argument");
|
||||
goto out_usage;
|
||||
@@ -138,8 +132,7 @@ int fsverity_cmd_sign(const struct fsverity_command *cmd,
|
||||
ASSERT(digest->digest_size <= FS_VERITY_MAX_DIGEST_SIZE);
|
||||
bin2hex(digest->digest, digest->digest_size, digest_hex);
|
||||
printf("Signed file '%s' (%s:%s)\n", argv[0],
|
||||
libfsverity_get_hash_name(tree_params.hash_algorithm),
|
||||
digest_hex);
|
||||
libfsverity_get_hash_name(digest->digest_algorithm), digest_hex);
|
||||
status = 0;
|
||||
out:
|
||||
filedes_close(&file);
|
||||
|
||||
@@ -139,7 +139,13 @@ static const struct test_case {
|
||||
"\x56\xce\x29\xa9\x60\xbf\x4b\xb0"
|
||||
"\xe5\x95\xec\x38\x6c\xa5\x8c\x06"
|
||||
"\x51\x9d\x54\x6d\xc5\xb1\x97\xbb",
|
||||
}
|
||||
}, { /* default hash algorithm (SHA-256) and block size (4096) */
|
||||
.file_size = 100000,
|
||||
.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",
|
||||
},
|
||||
};
|
||||
|
||||
static void fix_digest_and_print(const struct test_case *t,
|
||||
@@ -206,15 +212,11 @@ static void test_invalid_params(void)
|
||||
|
||||
/* 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;
|
||||
@@ -266,6 +268,8 @@ int main(int argc, char *argv[])
|
||||
f.data[i] = (i % 11) + (i % 439) + (i % 1103);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(test_cases); i++) {
|
||||
u32 expected_alg = test_cases[i].hash_algorithm ?:
|
||||
FS_VERITY_HASH_ALG_SHA256;
|
||||
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
params.version = 1;
|
||||
@@ -283,9 +287,9 @@ int main(int argc, char *argv[])
|
||||
err = libfsverity_compute_digest(&f, read_fn, ¶ms, &d);
|
||||
ASSERT(err == 0);
|
||||
|
||||
ASSERT(d->digest_algorithm == test_cases[i].hash_algorithm);
|
||||
ASSERT(d->digest_algorithm == expected_alg);
|
||||
ASSERT(d->digest_size ==
|
||||
libfsverity_get_digest_size(test_cases[i].hash_algorithm));
|
||||
libfsverity_get_digest_size(expected_alg));
|
||||
if (update)
|
||||
fix_digest_and_print(&test_cases[i], d);
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user