@@ -18,137 +18,17 @@
#include "fsverity_uapi.h"
#include "hash_algs.h"
-static bool parse_hash_alg_option(const char *arg, u32 *alg_ptr)
-{
- char *end;
- unsigned long n = strtoul(arg, &end, 10);
- const struct fsverity_hash_alg *alg;
-
- if (*alg_ptr != 0) {
- error_msg("--hash-alg can only be specified once");
- return false;
- }
-
- /* Specified by number? */
- if (n > 0 && n < INT32_MAX && *end == '\0') {
- *alg_ptr = n;
- return true;
- }
-
- /* Specified by name? */
- alg = find_hash_alg_by_name(arg);
- if (alg != NULL) {
- *alg_ptr = alg - fsverity_hash_algs;
- return true;
- }
- return false;
-}
-
-static bool read_signature(const char *filename, u8 **sig_ret,
- u32 *sig_size_ret)
-{
- struct filedes file = { .fd = -1 };
- u64 file_size;
- u8 *sig = NULL;
- bool ok = false;
-
- if (!open_file(&file, filename, O_RDONLY, 0))
- goto out;
- if (!get_file_size(&file, &file_size))
- goto out;
- if (file_size <= 0) {
- error_msg("signature file '%s' is empty", filename);
- goto out;
- }
- if (file_size > 1000000) {
- error_msg("signature file '%s' is too large", filename);
- goto out;
- }
- sig = xmalloc(file_size);
- if (!full_read(&file, sig, file_size))
- goto out;
- *sig_ret = sig;
- *sig_size_ret = file_size;
- sig = NULL;
- ok = true;
-out:
- filedes_close(&file);
- free(sig);
- return ok;
-}
-
-enum {
- OPT_HASH_ALG,
- OPT_BLOCK_SIZE,
- OPT_SALT,
- OPT_SIGNATURE,
-};
-
-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},
- {"signature", required_argument, NULL, OPT_SIGNATURE},
- {NULL, 0, NULL, 0}
-};
-
/* Enable fs-verity on a file. */
-int fsverity_cmd_enable(const struct fsverity_command *cmd,
- int argc, char *argv[])
+int fsverity_cmd_enable(char *filename, struct fsverity_enable_arg *arg)
{
- struct fsverity_enable_arg arg = { .version = 1 };
u8 *salt = NULL;
u8 *sig = NULL;
struct filedes file;
int status;
- int c;
-
- while ((c = getopt_long(argc, argv, "", longopts, NULL)) != -1) {
- switch (c) {
- case OPT_HASH_ALG:
- if (!parse_hash_alg_option(optarg, &arg.hash_algorithm))
- goto out_usage;
- break;
- case OPT_BLOCK_SIZE:
- if (!parse_block_size_option(optarg, &arg.block_size))
- goto out_usage;
- break;
- case OPT_SALT:
- if (!parse_salt_option(optarg, &salt, &arg.salt_size))
- goto out_usage;
- arg.salt_ptr = (uintptr_t)salt;
- break;
- case OPT_SIGNATURE:
- if (sig != NULL) {
- error_msg("--signature can only be specified once");
- goto out_usage;
- }
- if (!read_signature(optarg, &sig, &arg.sig_size))
- goto out_err;
- arg.sig_ptr = (uintptr_t)sig;
- break;
- default:
- goto out_usage;
- }
- }
- argv += optind;
- argc -= optind;
-
- if (argc != 1)
- goto out_usage;
-
- if (arg.hash_algorithm == 0)
- arg.hash_algorithm = FS_VERITY_HASH_ALG_DEFAULT;
-
- if (arg.block_size == 0)
- arg.block_size = get_default_block_size();
-
- if (!open_file(&file, argv[0], O_RDONLY, 0))
+ if (!open_file(&file, filename, O_RDONLY, 0))
goto out_err;
- if (ioctl(file.fd, FS_IOC_ENABLE_VERITY, &arg) != 0) {
- error_msg_errno("FS_IOC_ENABLE_VERITY failed on '%s'",
- file.name);
+ if (ioctl(file.fd, FS_IOC_ENABLE_VERITY, arg) != 0) {
filedes_close(&file);
goto out_err;
}
@@ -164,9 +44,4 @@ out:
out_err:
status = 1;
goto out;
-
-out_usage:
- usage(cmd, stderr);
- status = 2;
- goto out;
}
@@ -26,8 +26,7 @@ struct fsverity_signed_digest {
void usage(const struct fsverity_command *cmd, FILE *fp);
-int fsverity_cmd_enable(const struct fsverity_command *cmd,
- int argc, char *argv[]);
+int fsverity_cmd_enable(char *filename, struct fsverity_enable_arg *arg);
int fsverity_cmd_measure(char *filename, struct fsverity_digest *d);
int fsverity_cmd_sign(char *filename, const struct fsverity_hash_alg *hash_alg,
u32 block_size, u8 *salt, u32 salt_size,
@@ -24,6 +24,7 @@ enum {
OPT_SALT,
OPT_KEY,
OPT_CERT,
+ OPT_SIGNATURE,
};
static const struct option longopts[] = {
@@ -35,6 +36,14 @@ static const struct option longopts[] = {
{NULL, 0, NULL, 0}
};
+static const struct option enable_longopts[] = {
+ {"hash-alg", required_argument, NULL, OPT_HASH_ALG},
+ {"block-size", required_argument, NULL, OPT_BLOCK_SIZE},
+ {"salt", required_argument, NULL, OPT_SALT},
+ {"signature", required_argument, NULL, OPT_SIGNATURE},
+ {NULL, 0, NULL, 0}
+};
+
static bool write_signature(const char *filename, const u8 *sig, u32 sig_size)
{
struct filedes file;
@@ -47,6 +56,65 @@ static bool write_signature(const char *filename, const u8 *sig, u32 sig_size)
return ok;
}
+static bool read_signature(const char *filename, u8 **sig_ret,
+ u32 *sig_size_ret)
+{
+ struct filedes file = { .fd = -1 };
+ u64 file_size;
+ u8 *sig = NULL;
+ bool ok = false;
+
+ if (!open_file(&file, filename, O_RDONLY, 0))
+ goto out;
+ if (!get_file_size(&file, &file_size))
+ goto out;
+ if (file_size <= 0) {
+ error_msg("signature file '%s' is empty", filename);
+ goto out;
+ }
+ if (file_size > 1000000) {
+ error_msg("signature file '%s' is too large", filename);
+ goto out;
+ }
+ sig = xmalloc(file_size);
+ if (!full_read(&file, sig, file_size))
+ goto out;
+ *sig_ret = sig;
+ *sig_size_ret = file_size;
+ sig = NULL;
+ ok = true;
+out:
+ filedes_close(&file);
+ free(sig);
+ return ok;
+}
+
+static bool parse_hash_alg_option(const char *arg, u32 *alg_ptr)
+{
+ char *end;
+ unsigned long n = strtoul(arg, &end, 10);
+ const struct fsverity_hash_alg *alg;
+
+ if (*alg_ptr != 0) {
+ error_msg("--hash-alg can only be specified once");
+ return false;
+ }
+
+ /* Specified by number? */
+ if (n > 0 && n < INT32_MAX && *end == '\0') {
+ *alg_ptr = n;
+ return true;
+ }
+
+ /* Specified by name? */
+ alg = find_hash_alg_by_name(arg);
+ if (alg != NULL) {
+ *alg_ptr = alg - fsverity_hash_algs;
+ return true;
+ }
+ return false;
+}
+
int wrap_cmd_sign(const struct fsverity_command *cmd, int argc, char *argv[])
{
struct fsverity_signed_digest *digest = NULL;
@@ -190,6 +258,73 @@ out_usage:
goto out;
}
+int wrap_cmd_enable(const struct fsverity_command *cmd,
+ int argc, char *argv[])
+{
+ struct fsverity_enable_arg arg = { .version = 1 };
+ u8 *salt = NULL;
+ u8 *sig = NULL;
+ int status;
+ int c;
+
+ while ((c = getopt_long(argc, argv, "", enable_longopts, NULL)) != -1) {
+ switch (c) {
+ case OPT_HASH_ALG:
+ if (!parse_hash_alg_option(optarg, &arg.hash_algorithm))
+ goto out_usage;
+ break;
+ case OPT_BLOCK_SIZE:
+ if (!parse_block_size_option(optarg, &arg.block_size))
+ goto out_usage;
+ break;
+ case OPT_SALT:
+ if (!parse_salt_option(optarg, &salt, &arg.salt_size))
+ goto out_usage;
+ arg.salt_ptr = (uintptr_t)salt;
+ break;
+ case OPT_SIGNATURE:
+ if (sig != NULL) {
+ error_msg("--signature can only be specified once");
+ goto out_usage;
+ }
+ if (!read_signature(optarg, &sig, &arg.sig_size)) {
+ error_msg("unable to read signature file %s",
+ optarg);
+ status = 1;
+ goto out;
+ }
+ arg.sig_ptr = (uintptr_t)sig;
+ break;
+ default:
+ goto out_usage;
+ }
+ }
+
+ argv += optind;
+ argc -= optind;
+
+ if (argc != 1)
+ goto out_usage;
+
+ if (arg.hash_algorithm == 0)
+ arg.hash_algorithm = FS_VERITY_HASH_ALG_DEFAULT;
+
+ if (arg.block_size == 0)
+ arg.block_size = get_default_block_size();
+
+ status = fsverity_cmd_enable(argv[0], &arg);
+
+out:
+ free(salt);
+ free(sig);
+ return status;
+
+out_usage:
+ usage(cmd, stderr);
+ status = 2;
+ goto out;
+}
+
static const struct fsverity_command {
const char *name;
int (*func)(const struct fsverity_command *cmd, int argc, char *argv[]);
@@ -198,7 +333,7 @@ static const struct fsverity_command {
} fsverity_commands[] = {
{
.name = "enable",
- .func = fsverity_cmd_enable,
+ .func = wrap_cmd_enable,
.short_desc = "Enable fs-verity on a file",
.usage_str =
" fsverity enable FILE\n"