From 813862a47ca866082ca3002441df6c13b47f1b0d Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Sun, 11 Feb 2018 12:35:15 -0500 Subject: [PATCH] add -c to cmd_unlock, to check if a device needs to be unlocked --- Makefile | 5 +++++ cmd_key.c | 58 ++++++++++++++++++++++++++++++++++++++++++------ crypto.c | 8 +++++++ crypto.h | 1 + initramfs/hook | 18 +++++++++++++++ initramfs/script | 25 +++++++++++++++++++++ 6 files changed, 108 insertions(+), 7 deletions(-) create mode 100755 initramfs/hook create mode 100755 initramfs/script diff --git a/Makefile b/Makefile index 075257b..e773b46 100644 --- a/Makefile +++ b/Makefile @@ -37,8 +37,10 @@ LDLIBS+=`pkg-config --libs ${PKGCONFIG_LIBS}` \ ifeq ($(PREFIX),/usr) ROOT_SBINDIR=/sbin + INITRAMFS_DIR=$(PREFIX)/share/initramfs-tools else ROOT_SBINDIR=$(PREFIX)/sbin + INITRAMFS_DIR=/etc/initramfs-tools endif .PHONY: all @@ -58,6 +60,9 @@ install: bcachefs $(INSTALL) -m0755 bcachefs $(DESTDIR)$(ROOT_SBINDIR) $(INSTALL) -m0755 fsck.bcachefs $(DESTDIR)$(ROOT_SBINDIR) $(INSTALL) -m0755 mkfs.bcachefs $(DESTDIR)$(ROOT_SBINDIR) + $(INSTALL) -m0755 -D initramfs/hook $(DESTDIR)$(INITRAMFS_DIR)/hooks/bcachefs + echo "copy_exec $(ROOT_SBINDIR)/bcachefs /sbin/bcachefs" >> $(DESTDIR)$(INITRAMFS_DIR)/hooks/bcachefs + $(INSTALL) -m0755 -D initramfs/script $(DESTDIR)$(INITRAMFS_DIR)/scripts/local-premount/bcachefs $(INSTALL) -m0644 bcachefs.8 $(DESTDIR)$(PREFIX)/share/man/man8/ .PHONY: clean diff --git a/cmd_key.c b/cmd_key.c index e670b50..0ca591c 100644 --- a/cmd_key.c +++ b/cmd_key.c @@ -7,23 +7,61 @@ #include "crypto.h" #include "libbcachefs.h" +static void unlock_usage(void) +{ + puts("bcachefs unlock - unlock an encrypted filesystem so it can be mounted\n" + "Usage: bcachefs unlock [OPTION] device\n" + "\n" + "Options:\n" + " -c Check if a device is encrypted\n" + " -h Display this help and exit\n" + "Report bugs to "); +} + int cmd_unlock(int argc, char *argv[]) { + bool check = false; + int opt; + + while ((opt = getopt(argc, argv, "ch")) != -1) + switch (opt) { + case 'c': + check = true; + break; + case 'h': + unlock_usage(); + exit(EXIT_SUCCESS); + } + args_shift(optind); + + char *dev = arg_pop(); + if (!dev) + die("Please supply a device"); + + if (argc) + die("Too many arguments"); + struct bch_opts opts = bch2_opts_empty(); - struct bch_sb_handle sb; - char *passphrase; - if (argc != 2) - die("Please supply a single device"); + opt_set(opts, noexcl, true); + opt_set(opts, nochanges, true); - int ret = bch2_read_super(argv[1], &opts, &sb); + struct bch_sb_handle sb; + int ret = bch2_read_super(dev, &opts, &sb); if (ret) - die("Error opening %s: %s", argv[1], strerror(-ret)); + die("Error opening %s: %s", dev, strerror(-ret)); + + if (!bch2_sb_is_encrypted(sb.sb)) + die("%s is not encrypted", dev); + + if (check) + exit(EXIT_SUCCESS); - passphrase = read_passphrase("Enter passphrase: "); + char *passphrase = read_passphrase("Enter passphrase: "); bch2_add_key(sb.sb, passphrase); + bch2_free_super(&sb); memzero_explicit(passphrase, strlen(passphrase)); free(passphrase); return 0; @@ -38,6 +76,12 @@ int cmd_set_passphrase(int argc, char *argv[]) die("Please supply one or more devices"); opt_set(opts, nostart, true); + + /* + * we use bch2_fs_open() here, instead of just reading the superblock, + * to make sure we're opening and updating every component device: + */ + c = bch2_fs_open(argv + 1, argc - 1, opts); if (IS_ERR(c)) die("Error opening %s: %s", argv[1], strerror(-PTR_ERR(c))); diff --git a/crypto.c b/crypto.c index 0e18b36..7f7fbd5 100644 --- a/crypto.c +++ b/crypto.c @@ -100,6 +100,14 @@ struct bch_key derive_passphrase(struct bch_sb_field_crypt *crypt, return key; } +bool bch2_sb_is_encrypted(struct bch_sb *sb) +{ + struct bch_sb_field_crypt *crypt; + + return (crypt = bch2_sb_get_crypt(sb)) && + bch2_key_is_encrypted(&crypt->key); +} + void bch2_passphrase_check(struct bch_sb *sb, const char *passphrase, struct bch_key *passphrase_key, struct bch_encrypted_key *sb_key) diff --git a/crypto.h b/crypto.h index d6c2061..7f523c0 100644 --- a/crypto.h +++ b/crypto.h @@ -12,6 +12,7 @@ char *read_passphrase(const char *); char *read_passphrase_twice(const char *); struct bch_key derive_passphrase(struct bch_sb_field_crypt *, const char *); +bool bch2_sb_is_encrypted(struct bch_sb *); void bch2_passphrase_check(struct bch_sb *, const char *, struct bch_key *, struct bch_encrypted_key *); void bch2_add_key(struct bch_sb *, const char *); diff --git a/initramfs/hook b/initramfs/hook new file mode 100755 index 0000000..aa91469 --- /dev/null +++ b/initramfs/hook @@ -0,0 +1,18 @@ +#!/bin/sh + +PREREQ="" + +prereqs() +{ + echo "$PREREQ" +} + +case $1 in +prereqs) + prereqs + exit 0 + ;; +esac + +. /usr/share/initramfs-tools/hook-functions + diff --git a/initramfs/script b/initramfs/script new file mode 100755 index 0000000..bd64b41 --- /dev/null +++ b/initramfs/script @@ -0,0 +1,25 @@ +#!/bin/sh + +PREREQ="" + +prereqs() +{ + echo "$PREREQ" +} + +case $1 in +# get pre-requisites +prereqs) + prereqs + exit 0 + ;; +esac + +# Check if it needs unlocking: +if bcachefs unlock -c $ROOT >/dev/null 2>&1; then + echo "Unlocking $ROOT:" + + while true; do + bcachefs unlock $ROOT && break + done +fi -- 2.39.2