From: Jes Sorensen <jes.sorensen@gmail.com>
To: linux-fscrypt@vger.kernel.org
Cc: kernel-team@fb.com, Jes Sorensen <jsorensen@fb.com>
Subject: [PATCH 2/7] Restructure fsverity_cmd_sign for shared libraries
Date: Mon, 10 Feb 2020 19:00:32 -0500 [thread overview]
Message-ID: <20200211000037.189180-3-Jes.Sorensen@gmail.com> (raw)
In-Reply-To: <20200211000037.189180-1-Jes.Sorensen@gmail.com>
From: Jes Sorensen <jsorensen@fb.com>
This moves the command line parsing, error reporting etc. to the command
line tool, and turns fsverity_cmd_sign() into a call returning the
digest and the signature.
It is the responsibility of the caller to decide what to do with the
returned objects.
Signed-off-by: Jes Sorensen <jsorensen@fb.com>
---
cmd_sign.c | 132 ++++++-----------------------------------------------
commands.h | 23 +++++++++-
fsverity.c | 129 ++++++++++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 163 insertions(+), 121 deletions(-)
diff --git a/cmd_sign.c b/cmd_sign.c
index dcb37ce..2d3fa54 100644
--- a/cmd_sign.c
+++ b/cmd_sign.c
@@ -8,7 +8,6 @@
*/
#include <fcntl.h>
-#include <getopt.h>
#include <limits.h>
#include <openssl/bio.h>
#include <openssl/err.h>
@@ -38,19 +37,6 @@ struct fsverity_descriptor {
__u8 signature[]; /* optional PKCS#7 signature */
};
-/*
- * Format in which verity file measurements are signed. This is the same as
- * 'struct fsverity_digest', except here some magic bytes are prepended to
- * provide some context about what is being signed in case the same key is used
- * for non-fsverity purposes, and here the fields have fixed endianness.
- */
-struct fsverity_signed_digest {
- char magic[8]; /* must be "FSVerity" */
- __le16 digest_algorithm;
- __le16 digest_size;
- __u8 digest[];
-};
-
static void __printf(1, 2) __cold
error_msg_openssl(const char *format, ...)
{
@@ -340,18 +326,6 @@ out:
return ok;
}
-static bool write_signature(const char *filename, const u8 *sig, u32 sig_size)
-{
- struct filedes file;
- bool ok;
-
- if (!open_file(&file, filename, O_WRONLY|O_CREAT|O_TRUNC, 0644))
- return false;
- ok = full_write(&file, sig, sig_size);
- ok &= filedes_close(&file);
- return ok;
-}
-
#define FS_VERITY_MAX_LEVELS 64
struct block_buffer {
@@ -507,93 +481,27 @@ out:
return ok;
}
-enum {
- OPT_HASH_ALG,
- OPT_BLOCK_SIZE,
- OPT_SALT,
- OPT_KEY,
- OPT_CERT,
-};
-
-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},
- {NULL, 0, NULL, 0}
-};
-
/* Sign a file for fs-verity by computing its measurement, then signing it. */
-int fsverity_cmd_sign(const struct fsverity_command *cmd,
- int argc, char *argv[])
+int fsverity_cmd_sign(char *filename, const struct fsverity_hash_alg *hash_alg,
+ u32 block_size, u8 *salt, u32 salt_size,
+ const char *keyfile, const char *certfile,
+ struct fsverity_signed_digest **retdigest,
+ u8 **sig, u32 *sig_size)
{
- const struct fsverity_hash_alg *hash_alg = NULL;
- u32 block_size = 0;
- u8 *salt = NULL;
- u32 salt_size = 0;
- const char *keyfile = NULL;
- const char *certfile = NULL;
struct fsverity_signed_digest *digest = NULL;
- char digest_hex[FS_VERITY_MAX_DIGEST_SIZE * 2 + 1];
- u8 *sig = NULL;
- u32 sig_size;
int status;
- int c;
-
- while ((c = getopt_long(argc, argv, "", longopts, NULL)) != -1) {
- switch (c) {
- case OPT_HASH_ALG:
- if (hash_alg != NULL) {
- error_msg("--hash-alg can only be specified once");
- goto out_usage;
- }
- hash_alg = find_hash_alg_by_name(optarg);
- if (hash_alg == NULL)
- goto out_usage;
- break;
- case OPT_BLOCK_SIZE:
- if (!parse_block_size_option(optarg, &block_size))
- goto out_usage;
- break;
- case OPT_SALT:
- if (!parse_salt_option(optarg, &salt, &salt_size))
- goto out_usage;
- break;
- case OPT_KEY:
- if (keyfile != NULL) {
- error_msg("--key can only be specified once");
- goto out_usage;
- }
- keyfile = optarg;
- break;
- case OPT_CERT:
- if (certfile != NULL) {
- error_msg("--cert can only be specified once");
- goto out_usage;
- }
- certfile = optarg;
- break;
- default:
- goto out_usage;
- }
- }
- argv += optind;
- argc -= optind;
-
- if (argc != 2)
- goto out_usage;
-
- if (hash_alg == NULL)
- hash_alg = &fsverity_hash_algs[FS_VERITY_HASH_ALG_DEFAULT];
+ if (hash_alg == NULL) {
+ status = -EINVAL;
+ goto out;
+ }
if (block_size == 0)
block_size = get_default_block_size();
if (keyfile == NULL) {
- error_msg("Missing --key argument");
- goto out_usage;
+ status = -EINVAL;
+ goto out;
}
if (certfile == NULL)
certfile = keyfile;
@@ -603,33 +511,21 @@ int fsverity_cmd_sign(const struct fsverity_command *cmd,
digest->digest_algorithm = cpu_to_le16(hash_alg - fsverity_hash_algs);
digest->digest_size = cpu_to_le16(hash_alg->digest_size);
- if (!compute_file_measurement(argv[0], hash_alg, block_size,
+ if (!compute_file_measurement(filename, hash_alg, block_size,
salt, salt_size, digest->digest))
goto out_err;
if (!sign_data(digest, sizeof(*digest) + hash_alg->digest_size,
- keyfile, certfile, hash_alg, &sig, &sig_size))
- goto out_err;
-
- if (!write_signature(argv[1], sig, sig_size))
+ keyfile, certfile, hash_alg, sig, sig_size))
goto out_err;
- bin2hex(digest->digest, hash_alg->digest_size, digest_hex);
- printf("Signed file '%s' (%s:%s)\n", argv[0], hash_alg->name,
- digest_hex);
+ *retdigest = digest;
status = 0;
out:
- free(salt);
- free(digest);
- free(sig);
return status;
out_err:
status = 1;
goto out;
-out_usage:
- usage(cmd, stderr);
- status = 2;
- goto out;
}
diff --git a/commands.h b/commands.h
index 98f9745..c38fcea 100644
--- a/commands.h
+++ b/commands.h
@@ -5,17 +5,36 @@
#include <stdio.h>
#include "util.h"
+#include "hash_algs.h"
+#include "fsverity_uapi.h"
struct fsverity_command;
+/*
+ * Format in which verity file measurements are signed. This is the same as
+ * 'struct fsverity_digest', except here some magic bytes are prepended to
+ * provide some context about what is being signed in case the same key is used
+ * for non-fsverity purposes, and here the fields have fixed endianness.
+ */
+struct fsverity_signed_digest {
+ char magic[8]; /* must be "FSVerity" */
+ __le16 digest_algorithm;
+ __le16 digest_size;
+ __u8 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_measure(const struct fsverity_command *cmd,
int argc, char *argv[]);
-int fsverity_cmd_sign(const struct fsverity_command *cmd,
- int argc, char *argv[]);
+int fsverity_cmd_sign(char *filename, const struct fsverity_hash_alg *hash_alg,
+ u32 block_size, u8 *salt, u32 salt_size,
+ const char *keyfile, const char *certfile,
+ struct fsverity_signed_digest **retdigest,
+ u8 **sig, u32 *sig_size);
bool parse_block_size_option(const char *arg, u32 *size_ptr);
u32 get_default_block_size(void);
diff --git a/fsverity.c b/fsverity.c
index 9a44df1..6246031 100644
--- a/fsverity.c
+++ b/fsverity.c
@@ -7,14 +7,141 @@
* Written by Eric Biggers.
*/
+#include <fcntl.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <getopt.h>
+#include <errno.h>
#include "commands.h"
#include "hash_algs.h"
+enum {
+ OPT_HASH_ALG,
+ OPT_BLOCK_SIZE,
+ OPT_SALT,
+ OPT_KEY,
+ OPT_CERT,
+};
+
+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},
+ {NULL, 0, NULL, 0}
+};
+
+static bool write_signature(const char *filename, const u8 *sig, u32 sig_size)
+{
+ struct filedes file;
+ bool ok;
+
+ if (!open_file(&file, filename, O_WRONLY|O_CREAT|O_TRUNC, 0644))
+ return false;
+ ok = full_write(&file, sig, sig_size);
+ ok &= filedes_close(&file);
+ return ok;
+}
+
+int wrap_cmd_sign(const struct fsverity_command *cmd, int argc, char *argv[])
+{
+ struct fsverity_signed_digest *digest = NULL;
+ u8 *sig = NULL;
+ u32 sig_size;
+ const struct fsverity_hash_alg *hash_alg = NULL;
+ u32 block_size = 0;
+ u8 *salt = NULL;
+ u32 salt_size = 0;
+ const char *keyfile = NULL;
+ const char *certfile = NULL;
+ int c, status;
+ char digest_hex[FS_VERITY_MAX_DIGEST_SIZE * 2 + 1];
+
+ while ((c = getopt_long(argc, argv, "", longopts, NULL)) != -1) {
+ switch (c) {
+ case OPT_HASH_ALG:
+ if (hash_alg != NULL) {
+ error_msg("--hash-alg can only be specified once");
+ goto out_usage;
+ }
+ hash_alg = find_hash_alg_by_name(optarg);
+ if (hash_alg == NULL)
+ goto out_usage;
+ break;
+ case OPT_BLOCK_SIZE:
+ if (!parse_block_size_option(optarg, &block_size))
+ goto out_usage;
+ break;
+ case OPT_SALT:
+ if (!parse_salt_option(optarg, &salt, &salt_size))
+ goto out_usage;
+ break;
+ case OPT_KEY:
+ if (keyfile != NULL) {
+ error_msg("--key can only be specified once");
+ goto out_usage;
+ }
+ keyfile = optarg;
+ break;
+ case OPT_CERT:
+ if (certfile != NULL) {
+ error_msg("--cert can only be specified once");
+ goto out_usage;
+ }
+ certfile = optarg;
+ break;
+ default:
+ goto out_usage;
+ }
+ }
+
+ if (keyfile == NULL) {
+ status = -EINVAL;
+ error_msg("Missing --key argument");
+ goto out_usage;
+ }
+
+ argv += optind;
+ argc -= optind;
+
+ if (hash_alg == NULL)
+ hash_alg = &fsverity_hash_algs[FS_VERITY_HASH_ALG_DEFAULT];
+
+ if (argc != 2)
+ goto out_usage;
+
+ status = fsverity_cmd_sign(argv[0], hash_alg, block_size, salt, salt_size,
+ keyfile, certfile, &digest, &sig, &sig_size);
+ if (status == -EINVAL)
+ goto out_usage;
+ if (status != 0)
+ goto out;
+
+ if (!write_signature(argv[1], sig, sig_size)) {
+ status = -EIO;
+ goto out;
+ }
+
+ bin2hex(digest->digest, hash_alg->digest_size, digest_hex);
+ printf("Signed file '%s' (%s:%s)\n", argv[0], hash_alg->name,
+ digest_hex);
+
+ out:
+ free(salt);
+ free(digest);
+ 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[]);
@@ -38,7 +165,7 @@ static const struct fsverity_command {
" fsverity measure FILE...\n"
}, {
.name = "sign",
- .func = fsverity_cmd_sign,
+ .func = wrap_cmd_sign,
.short_desc = "Sign a file for fs-verity",
.usage_str =
" fsverity sign FILE OUT_SIGFILE --key=KEYFILE\n"
--
2.24.1
next prev parent reply other threads:[~2020-02-11 0:00 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-02-11 0:00 [PATCH 0/7] Split fsverity-utils into a shared library Jes Sorensen
2020-02-11 0:00 ` [PATCH 1/7] Build basic " Jes Sorensen
2020-02-11 0:00 ` Jes Sorensen [this message]
2020-02-11 0:00 ` [PATCH 3/7] Make fsverity_cmd_measure() a library function Jes Sorensen
2020-02-11 0:00 ` [PATCH 4/7] Make fsverity_cmd_enable a library call() Jes Sorensen
2020-02-11 0:00 ` [PATCH 5/7] Rename commands.h to fsverity.h Jes Sorensen
2020-02-11 0:00 ` [PATCH 6/7] Move cmdline helper functions to fsverity.c Jes Sorensen
2020-02-11 0:00 ` [PATCH 7/7] cmd_sign: fsverity_cmd_sign() into two functions Jes Sorensen
2020-02-11 19:22 ` [PATCH 0/7] Split fsverity-utils into a shared library Eric Biggers
2020-02-11 22:09 ` Jes Sorensen
2020-02-11 23:14 ` Eric Biggers
2020-02-11 23:35 ` Jes Sorensen
2020-02-14 20:35 ` Eric Biggers
2020-02-19 23:49 ` Jes Sorensen
2020-07-30 17:52 ` Eric Biggers
2020-07-31 17:40 ` Jes Sorensen
2020-07-31 17:47 ` Chris Mason
2020-07-31 19:14 ` Eric Biggers
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200211000037.189180-3-Jes.Sorensen@gmail.com \
--to=jes.sorensen@gmail.com \
--cc=jsorensen@fb.com \
--cc=kernel-team@fb.com \
--cc=linux-fscrypt@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).