aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Biggers <ebiggers@google.com>2018-03-21 17:53:20 -0700
committerEric Biggers <ebiggers@google.com>2018-03-21 17:53:20 -0700
commit1e64b3d34ef07017c00772aad35cd0970d84c581 (patch)
treece3be1d87c27018b7aba287bb38a57701af85cf5
parent6d8d3d205f8a59bbe2caa95f022cfa4a202c7039 (diff)
downloadfsverity-utils-1e64b3d34ef07017c00772aad35cd0970d84c581.tar.gz
Update for API changes
Signed-off-by: Eric Biggers <ebiggers@google.com>
-rw-r--r--.gitignore3
-rw-r--r--Makefile2
-rw-r--r--fsverity.c204
-rw-r--r--fsverity_api.h46
-rw-r--r--fsveritymeasure.c44
-rw-r--r--fsverityset.c34
-rwxr-xr-xfsveritysetup.py4
-rwxr-xr-xfull-run-fsverity.sh4
8 files changed, 223 insertions, 118 deletions
diff --git a/.gitignore b/.gitignore
index 7393bea..256af29 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,4 @@
-fsveritymeasure
-fsverityset
+fsverity
fsveritysetup.pyc
tags
cscope.*
diff --git a/Makefile b/Makefile
index 5cf2c22..36e64f8 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
CFLAGS := -O2 -Wall
-EXE := fsverityset fsveritymeasure
+EXE := fsverity
all:$(EXE)
diff --git a/fsverity.c b/fsverity.c
new file mode 100644
index 0000000..931cb07
--- /dev/null
+++ b/fsverity.c
@@ -0,0 +1,204 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * fs-verity userspace tool
+ *
+ * Copyright (C) 2018, Google, Inc.
+ */
+
+#include <fcntl.h>
+#include <getopt.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+#include "fsverity_api.h"
+
+#define ARRAY_SIZE(A) (sizeof(A) / sizeof((A)[0]))
+
+static const struct fsverity_hash_alg {
+ const char *name;
+ int digest_size;
+} fsverity_hash_algs[] = {
+ [FS_VERITY_ALG_SHA256] = {
+ .name = "sha256",
+ .digest_size = 32,
+ },
+ [FS_VERITY_ALG_CRC32] = {
+ .name = "crc32",
+ .digest_size = 4,
+ },
+};
+
+static void show_hash_algs(void)
+{
+ size_t i;
+
+ fprintf(stderr, "Available hash algorithms:");
+ for (i = 0; i < ARRAY_SIZE(fsverity_hash_algs); i++) {
+ if (fsverity_hash_algs[i].name)
+ fprintf(stderr, " %s", fsverity_hash_algs[i].name);
+ }
+ fprintf(stderr, "\n");
+}
+
+static const struct fsverity_hash_alg *find_hash_alg(const char *name)
+{
+ size_t i;
+
+ for (i = 0; i < ARRAY_SIZE(fsverity_hash_algs); i++) {
+ if (fsverity_hash_algs[i].name &&
+ !strcmp(name, fsverity_hash_algs[i].name))
+ return &fsverity_hash_algs[i];
+ }
+ return NULL;
+}
+
+static int hex2bin_char(char c)
+{
+ if (c >= 'a' && c <= 'f')
+ return 10 + c - 'a';
+ if (c >= 'A' && c <= 'F')
+ return 10 + c - 'A';
+ if (c >= '0' && c <= '9')
+ return c - '0';
+ return -1;
+}
+
+static bool parse_hex_digest(const char *hex, __u8 *bin, size_t bin_len)
+{
+ size_t i;
+
+ if (strlen(hex) != 2 * bin_len)
+ return false;
+
+ for (i = 0; i < bin_len; i++) {
+ int hi = hex2bin_char(hex[i * 2]);
+ int lo = hex2bin_char(hex[i * 2 + 1]);
+
+ if (hi < 0 || lo < 0)
+ return false;
+ bin[i] = (hi << 4) | lo;
+ }
+ return true;
+}
+
+enum {
+ OPT_HASH,
+};
+
+static void usage(void)
+{
+ const char * const usage_str =
+"Usage: fsverity enable FILE\n"
+" fsverity set_measurement [--hash=HASH] FILE EXPECTED_MEASUREMENT\n"
+"\n"
+"EXPECTED_MEASUREMENT must be given as a hex string.\n"
+"The default HASH algorithm is sha256.\n"
+ ;
+ fputs(usage_str, stderr);
+ show_hash_algs();
+ exit(2);
+}
+
+static int fsverity_enable(int argc, char *argv[])
+{
+ int fd;
+
+ if (argc != 2)
+ usage();
+
+ fd = open(argv[1], O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "Can't open %s: %m\n", argv[1]);
+ return 1;
+ }
+ if (ioctl(fd, FS_IOC_ENABLE_VERITY, NULL)) {
+ fprintf(stderr, "FS_IOC_ENABLE_VERITY: %m\n");
+ return 1;
+ }
+ close(fd);
+ return 0;
+}
+
+static int fsverity_set_measurement(int argc, char *argv[])
+{
+ static const struct option longopts[] = {
+ {"hash", required_argument, NULL, OPT_HASH},
+ {NULL, 0, NULL, 0},
+ };
+ const struct fsverity_hash_alg *alg =
+ &fsverity_hash_algs[FS_VERITY_ALG_SHA256];
+ int c;
+ int fd;
+ struct fsverity_measurement *measurement;
+
+ while ((c = getopt_long(argc, argv, "", longopts, NULL)) != -1) {
+ switch (c) {
+ case OPT_HASH:
+ alg = find_hash_alg(optarg);
+ if (!alg) {
+ fprintf(stderr,
+ "Unknown hash algorithm: '%s'\n",
+ optarg);
+ show_hash_algs();
+ return 2;
+ }
+ break;
+ default:
+ usage();
+ }
+ }
+ argv += optind;
+ argc -= optind;
+
+ if (argc != 2)
+ usage();
+
+ fd = open(argv[0], O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "Can't open %s: %m\n", argv[0]);
+ return 1;
+ }
+
+ measurement = calloc(1, sizeof(*measurement) + alg->digest_size);
+ measurement->digest_algorithm = alg - &fsverity_hash_algs[0];
+ measurement->digest_size = alg->digest_size;
+ if (!parse_hex_digest(argv[1], measurement->digest, alg->digest_size)) {
+ fprintf(stderr,
+ "Invalid EXPECTED_MEASUREMENT hex string. Expected %u-character hex string for hash algorithm '%s'\n",
+ alg->digest_size * 2, alg->name);
+ return 2;
+ }
+
+ if (ioctl(fd, FS_IOC_SET_VERITY_MEASUREMENT, measurement)) {
+ fprintf(stderr, "FS_IOC_SET_VERITY_MEASUREMENT: %m\n");
+ return 1;
+ }
+ close(fd);
+ return 0;
+}
+
+static const struct {
+ const char *name;
+ int (*func)(int argc, char *argv[]);
+} commands[] = {
+ { "enable", fsverity_enable },
+ { "set_measurement", fsverity_set_measurement },
+};
+
+int main(int argc, char *argv[])
+{
+ size_t i;
+
+ if (argc < 2)
+ usage();
+
+ for (i = 0; i < ARRAY_SIZE(commands); i++) {
+ if (!strcmp(argv[1], commands[i].name))
+ return commands[i].func(argc - 1, argv + 1);
+ }
+ usage();
+}
diff --git a/fsverity_api.h b/fsverity_api.h
index db0483f..e4cc960 100644
--- a/fsverity_api.h
+++ b/fsverity_api.h
@@ -1,5 +1,5 @@
-#ifndef _FSVERITY_KERNEL_DEFS_H
-#define _FSVERITY_KERNEL_DEFS_H
+#ifndef _FSVERITY_API_H
+#define _FSVERITY_API_H
#include <linux/limits.h>
#include <linux/ioctl.h>
@@ -7,38 +7,18 @@
/* file-based verity support */
-/*
- * TODO(ebiggers): What is the purpose of this structure? It's not actually
- * used for anything.
- */
-struct fsverity_set {
- __u64 offset;
- __u64 flags;
-};
-
-/*
- * TODO(ebiggers): why isn't this using the same type code as used in the
- * fsverity_header?
- */
-#define FS_VERITY_ROOT_HASH_ALGO_SHA256 0x0000
+#define FS_VERITY_ALG_SHA256 1
+#define FS_VERITY_ALG_CRC32 2
-/*
- * TODO(ebiggers): rename this to 'struct fsverity_measurement' to avoid
- * confusion with the Merkle tree root hash?
- */
-struct fsverity_root_hash {
- __u32 root_hash_algorithm;
- __u32 flags;
- __u8 reserved[4];
- __u8 root_hash[64];
+struct fsverity_measurement {
+ __u16 digest_algorithm;
+ __u16 digest_size;
+ __u32 reserved1;
+ __u64 reserved2[3];
+ __u8 digest[];
};
-/*
- * TODO(ebiggers): is there a less confusing name for this? "measure" makes it
- * sound like it's returning something...
- */
-#define FS_IOC_MEASURE_FSVERITY _IOW('f', 133, \
- struct fsverity_root_hash)
-#define FS_IOC_SET_FSVERITY _IOW('f', 134, struct fsverity_set)
+#define FS_IOC_ENABLE_VERITY _IO('f', 133)
+#define FS_IOC_SET_VERITY_MEASUREMENT _IOW('f', 134, struct fsverity_measurement)
-#endif /* _FSVERITY_KERNEL_DEFS_H */
+#endif /* _FSVERITY_API_H */
diff --git a/fsveritymeasure.c b/fsveritymeasure.c
deleted file mode 100644
index 0be1c25..0000000
--- a/fsveritymeasure.c
+++ /dev/null
@@ -1,44 +0,0 @@
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <unistd.h>
-
-#include "fsverity_api.h"
-
-static void usage(void)
-{
- fprintf(stderr,
-"Usage: fsveritymeasure FILE EXPECTED_MEASUREMENT\n"
-"\n"
-"EXPECTED_MEASUREMENT must be a 64-character hex string.\n");
- exit(2);
-}
-
-int main(int args, char *argv[])
-{
- int fd, i;
- unsigned int byte;
- struct fsverity_root_hash measurement = { 0 };
-
- if (args != 3 || strlen(argv[2]) != 64)
- usage();
-
- for (i = 0; i < 32; i++) {
- if (sscanf(&argv[2][i*2], "%02x", &byte) != 1)
- usage();
- measurement.root_hash[i] = byte;
- }
- fd = open(argv[1], O_RDONLY);
- if (fd < 0) {
- fprintf(stderr, "Can't open %s: %m\n", argv[1]);
- return 1;
- }
- if (ioctl(fd, FS_IOC_MEASURE_FSVERITY, &measurement)) {
- fprintf(stderr, "FS_IOC_MEASURE_FSVERITY: %m\n");
- return 1;
- }
- close(fd);
- return 0;
-}
diff --git a/fsverityset.c b/fsverityset.c
deleted file mode 100644
index 6075071..0000000
--- a/fsverityset.c
+++ /dev/null
@@ -1,34 +0,0 @@
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/ioctl.h>
-#include <unistd.h>
-
-#include "fsverity_api.h"
-
-static void usage(void)
-{
- fprintf(stderr, "Usage: fsverityset FILE\n");
- exit(2);
-}
-
-int main(int args, char *argv[])
-{
- int fd;
- struct fsverity_set set = { 0 };
-
- if (args != 2)
- usage();
-
- fd = open(argv[1], O_RDONLY);
- if (fd < 0) {
- fprintf(stderr, "Can't open %s: %m\n", argv[1]);
- return 1;
- }
- if (ioctl(fd, FS_IOC_SET_FSVERITY, &set)) {
- fprintf(stderr, "FS_IOC_SET_FSVERITY: %m\n");
- return 1;
- }
- close(fd);
- return 0;
-}
diff --git a/fsveritysetup.py b/fsveritysetup.py
index 692304c..282bff7 100755
--- a/fsveritysetup.py
+++ b/fsveritysetup.py
@@ -21,8 +21,8 @@ FS_VERITY_MAGIC = b'TrueBrew'
FS_VERITY_SALT_SIZE = 8
FS_VERITY_EXT_ELIDE = 0
FS_VERITY_EXT_PATCH = 1
-FS_VERITY_ALG_CRC32 = 0
FS_VERITY_ALG_SHA256 = 1
+FS_VERITY_ALG_CRC32 = 2
class CRC32Hash(object):
@@ -68,8 +68,8 @@ class HashAlgorithm(object):
HASH_ALGORITHMS = [
- HashAlgorithm(FS_VERITY_ALG_CRC32, 'crc32', 4),
HashAlgorithm(FS_VERITY_ALG_SHA256, 'sha256', 32),
+ HashAlgorithm(FS_VERITY_ALG_CRC32, 'crc32', 4),
]
diff --git a/full-run-fsverity.sh b/full-run-fsverity.sh
index 14bb3dc..2507f57 100755
--- a/full-run-fsverity.sh
+++ b/full-run-fsverity.sh
@@ -7,8 +7,8 @@ dd if=/dev/zero of=/root/f2fs.img seek=$(($1<16384000?128000:$1/128)) bs=512 cou
mount -o loop /root/f2fs.img /mnt/f2fs
cp /root/output-$1.apk /mnt/f2fs/output-$1.apk
make
-./fsverityset /mnt/f2fs/output-$1.apk
-./fsveritymeasure /mnt/f2fs/output-$1.apk $2
+./fsverity enable /mnt/f2fs/output-$1.apk
+./fsverity set_measurement /mnt/f2fs/output-$1.apk $2
sync
echo 3 > /proc/sys/vm/drop_caches
dd if=/mnt/f2fs/output-$1.apk of=byte0-$1 count=1 bs=1