mirror of
https://github.com/openharmony/third_party_fsverity-utils.git
synced 2026-07-01 10:05:35 -04:00
programs/fsverity: add --out-merkle-tree and --out-descriptor options
Make 'fsverity digest' and 'fsverity sign' support writing the Merkle tree and fs-verity descriptor to files, using new options '--out-merkle-tree=FILE' and '--out-descriptor=FILE'. Normally these new options aren't useful, but they can be needed in cases where the fs-verity metadata needs to be consumed by something other than one of the native Linux kernel implementations of fs-verity. This is different from 'fsverity dump_metadata' in that 'fsverity dump_metadata' only works on a file with fs-verity enabled, whereas these new options are for the userspace file digest computation. Link: https://lore.kernel.org/r/20210603195812.50838-5-ebiggers@kernel.org Reviewed-by: Victor Hsieh <victorhsieh@google.com> Signed-off-by: Eric Biggers <ebiggers@google.com>
This commit is contained in:
@@ -18,6 +18,8 @@ static const struct option longopts[] = {
|
||||
{"hash-alg", required_argument, NULL, OPT_HASH_ALG},
|
||||
{"block-size", required_argument, NULL, OPT_BLOCK_SIZE},
|
||||
{"salt", required_argument, NULL, OPT_SALT},
|
||||
{"out-merkle-tree", required_argument, NULL, OPT_OUT_MERKLE_TREE},
|
||||
{"out-descriptor", required_argument, NULL, OPT_OUT_DESCRIPTOR},
|
||||
{"compact", no_argument, NULL, OPT_COMPACT},
|
||||
{"for-builtin-sig", no_argument, NULL, OPT_FOR_BUILTIN_SIG},
|
||||
{NULL, 0, NULL, 0}
|
||||
@@ -40,6 +42,8 @@ int fsverity_cmd_digest(const struct fsverity_command *cmd,
|
||||
case OPT_HASH_ALG:
|
||||
case OPT_BLOCK_SIZE:
|
||||
case OPT_SALT:
|
||||
case OPT_OUT_MERKLE_TREE:
|
||||
case OPT_OUT_DESCRIPTOR:
|
||||
if (!parse_tree_param(c, optarg, &tree_params))
|
||||
goto out_usage;
|
||||
break;
|
||||
@@ -114,7 +118,8 @@ int fsverity_cmd_digest(const struct fsverity_command *cmd,
|
||||
}
|
||||
status = 0;
|
||||
out:
|
||||
destroy_tree_params(&tree_params);
|
||||
if (!destroy_tree_params(&tree_params) && status == 0)
|
||||
status = 1;
|
||||
return status;
|
||||
|
||||
out_err:
|
||||
|
||||
+11
-6
@@ -27,11 +27,13 @@ static bool write_signature(const char *filename, const u8 *sig, u32 sig_size)
|
||||
}
|
||||
|
||||
static const struct option longopts[] = {
|
||||
{"hash-alg", required_argument, NULL, OPT_HASH_ALG},
|
||||
{"block-size", required_argument, NULL, OPT_BLOCK_SIZE},
|
||||
{"salt", required_argument, NULL, OPT_SALT},
|
||||
{"key", required_argument, NULL, OPT_KEY},
|
||||
{"cert", required_argument, NULL, OPT_CERT},
|
||||
{"hash-alg", required_argument, NULL, OPT_HASH_ALG},
|
||||
{"block-size", required_argument, NULL, OPT_BLOCK_SIZE},
|
||||
{"salt", required_argument, NULL, OPT_SALT},
|
||||
{"out-merkle-tree", required_argument, NULL, OPT_OUT_MERKLE_TREE},
|
||||
{"out-descriptor", required_argument, NULL, OPT_OUT_DESCRIPTOR},
|
||||
{"key", required_argument, NULL, OPT_KEY},
|
||||
{"cert", required_argument, NULL, OPT_CERT},
|
||||
{NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
@@ -54,6 +56,8 @@ int fsverity_cmd_sign(const struct fsverity_command *cmd,
|
||||
case OPT_HASH_ALG:
|
||||
case OPT_BLOCK_SIZE:
|
||||
case OPT_SALT:
|
||||
case OPT_OUT_MERKLE_TREE:
|
||||
case OPT_OUT_DESCRIPTOR:
|
||||
if (!parse_tree_param(c, optarg, &tree_params))
|
||||
goto out_usage;
|
||||
break;
|
||||
@@ -117,7 +121,8 @@ int fsverity_cmd_sign(const struct fsverity_command *cmd,
|
||||
status = 0;
|
||||
out:
|
||||
filedes_close(&file);
|
||||
destroy_tree_params(&tree_params);
|
||||
if (!destroy_tree_params(&tree_params) && status == 0)
|
||||
status = 1;
|
||||
free(digest);
|
||||
free(sig);
|
||||
return status;
|
||||
|
||||
+87
-1
@@ -11,6 +11,7 @@
|
||||
|
||||
#include "fsverity.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
|
||||
static const struct fsverity_command {
|
||||
@@ -27,6 +28,7 @@ static const struct fsverity_command {
|
||||
.usage_str =
|
||||
" fsverity digest FILE...\n"
|
||||
" [--hash-alg=HASH_ALG] [--block-size=BLOCK_SIZE] [--salt=SALT]\n"
|
||||
" [--out-merkle-tree=FILE] [--out-descriptor=FILE]\n"
|
||||
" [--compact] [--for-builtin-sig]\n"
|
||||
#ifndef _WIN32
|
||||
}, {
|
||||
@@ -58,6 +60,7 @@ static const struct fsverity_command {
|
||||
.usage_str =
|
||||
" fsverity sign FILE OUT_SIGFILE --key=KEYFILE\n"
|
||||
" [--hash-alg=HASH_ALG] [--block-size=BLOCK_SIZE] [--salt=SALT]\n"
|
||||
" [--out-merkle-tree=FILE] [--out-descriptor=FILE]\n"
|
||||
" [--cert=CERTFILE]\n"
|
||||
}
|
||||
};
|
||||
@@ -200,6 +203,74 @@ static bool parse_salt_option(const char *arg, u8 **salt_ptr,
|
||||
return true;
|
||||
}
|
||||
|
||||
struct metadata_callback_ctx {
|
||||
struct filedes merkle_tree_file;
|
||||
struct filedes descriptor_file;
|
||||
struct libfsverity_metadata_callbacks callbacks;
|
||||
};
|
||||
|
||||
static int handle_merkle_tree_size(void *_ctx, u64 size)
|
||||
{
|
||||
struct metadata_callback_ctx *ctx = _ctx;
|
||||
|
||||
if (!preallocate_file(&ctx->merkle_tree_file, size))
|
||||
return -EIO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int handle_merkle_tree_block(void *_ctx, const void *block, size_t size,
|
||||
u64 offset)
|
||||
{
|
||||
struct metadata_callback_ctx *ctx = _ctx;
|
||||
|
||||
if (!full_pwrite(&ctx->merkle_tree_file, block, size, offset))
|
||||
return -EIO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int handle_descriptor(void *_ctx, const void *descriptor, size_t size)
|
||||
{
|
||||
struct metadata_callback_ctx *ctx = _ctx;
|
||||
|
||||
if (!full_write(&ctx->descriptor_file, descriptor, size))
|
||||
return -EIO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool parse_out_metadata_option(int opt_char, const char *arg,
|
||||
const struct libfsverity_metadata_callbacks **cbs)
|
||||
{
|
||||
struct metadata_callback_ctx *ctx;
|
||||
struct filedes *file;
|
||||
const char *opt_name;
|
||||
|
||||
if (*cbs) {
|
||||
ctx = (*cbs)->ctx;
|
||||
} else {
|
||||
ctx = xzalloc(sizeof(*ctx));
|
||||
ctx->merkle_tree_file.fd = -1;
|
||||
ctx->descriptor_file.fd = -1;
|
||||
ctx->callbacks.ctx = ctx;
|
||||
*cbs = &ctx->callbacks;
|
||||
}
|
||||
|
||||
if (opt_char == OPT_OUT_MERKLE_TREE) {
|
||||
file = &ctx->merkle_tree_file;
|
||||
opt_name = "--out-merkle-tree";
|
||||
ctx->callbacks.merkle_tree_size = handle_merkle_tree_size;
|
||||
ctx->callbacks.merkle_tree_block = handle_merkle_tree_block;
|
||||
} else {
|
||||
file = &ctx->descriptor_file;
|
||||
opt_name = "--out-descriptor";
|
||||
ctx->callbacks.descriptor = handle_descriptor;
|
||||
}
|
||||
if (file->fd >= 0) {
|
||||
error_msg("%s can only be specified once", opt_name);
|
||||
return false;
|
||||
}
|
||||
return open_file(file, arg, O_WRONLY|O_CREAT|O_TRUNC, 0644);
|
||||
}
|
||||
|
||||
bool parse_tree_param(int opt_char, const char *arg,
|
||||
struct libfsverity_merkle_tree_params *params)
|
||||
{
|
||||
@@ -211,15 +282,30 @@ bool parse_tree_param(int opt_char, const char *arg,
|
||||
case OPT_SALT:
|
||||
return parse_salt_option(arg, (u8 **)¶ms->salt,
|
||||
¶ms->salt_size);
|
||||
case OPT_OUT_MERKLE_TREE:
|
||||
case OPT_OUT_DESCRIPTOR:
|
||||
return parse_out_metadata_option(opt_char, arg,
|
||||
¶ms->metadata_callbacks);
|
||||
default:
|
||||
ASSERT(0);
|
||||
}
|
||||
}
|
||||
|
||||
void destroy_tree_params(struct libfsverity_merkle_tree_params *params)
|
||||
bool destroy_tree_params(struct libfsverity_merkle_tree_params *params)
|
||||
{
|
||||
bool ok = true;
|
||||
|
||||
free((u8 *)params->salt);
|
||||
if (params->metadata_callbacks) {
|
||||
struct metadata_callback_ctx *ctx =
|
||||
params->metadata_callbacks->ctx;
|
||||
|
||||
ok &= filedes_close(&ctx->merkle_tree_file);
|
||||
ok &= filedes_close(&ctx->descriptor_file);
|
||||
free(ctx);
|
||||
}
|
||||
memset(params, 0, sizeof(*params));
|
||||
return ok;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
|
||||
+3
-1
@@ -29,6 +29,8 @@ enum {
|
||||
OPT_KEY,
|
||||
OPT_LENGTH,
|
||||
OPT_OFFSET,
|
||||
OPT_OUT_DESCRIPTOR,
|
||||
OPT_OUT_MERKLE_TREE,
|
||||
OPT_SALT,
|
||||
OPT_SIGNATURE,
|
||||
};
|
||||
@@ -59,6 +61,6 @@ int fsverity_cmd_sign(const struct fsverity_command *cmd,
|
||||
void usage(const struct fsverity_command *cmd, FILE *fp);
|
||||
bool parse_tree_param(int opt_char, const char *arg,
|
||||
struct libfsverity_merkle_tree_params *params);
|
||||
void destroy_tree_params(struct libfsverity_merkle_tree_params *params);
|
||||
bool destroy_tree_params(struct libfsverity_merkle_tree_params *params);
|
||||
|
||||
#endif /* PROGRAMS_FSVERITY_H */
|
||||
|
||||
Reference in New Issue
Block a user