]> git.sesse.net Git - bcachefs-tools-debian/commitdiff
Add commands for changing and removing passphrase
authorKent Overstreet <kent.overstreet@gmail.com>
Thu, 9 Nov 2017 01:03:59 +0000 (16:03 -0900)
committerKent Overstreet <kent.overstreet@gmail.com>
Thu, 9 Nov 2017 01:06:37 +0000 (16:06 -0900)
bcachefs.c
cmd_format.c
cmd_key.c
cmd_migrate.c
cmds.h
crypto.c
crypto.h
libbcachefs.c
libbcachefs.h

index 9b6b057f85c8f450824ae83e0d20356ffd5d7cc5..d57a46ea066ac416711157ede10e4f369af79bb9 100644 (file)
@@ -36,7 +36,6 @@ static void usage(void)
             "  fsck             Check an existing filesystem for errors\n"
             "\n"
             "Startup/shutdown, assembly of multi device filesystems:\n"
-            "  unlock           Unlock an encrypted filesystem prior to running/mounting\n"
             "  assemble         Assemble an existing multi device filesystem\n"
             "  incremental      Incrementally assemble an existing multi device filesystem\n"
             "  run              Start a partially assembled filesystem\n"
@@ -54,6 +53,11 @@ static void usage(void)
             "  device evacuate  Migrate data off of a specific device\n"
             "  device set-state Mark a device as failed\n"
             "\n"
+            "Encryption:\n"
+            "  unlock           Unlock an encrypted filesystem prior to running/mounting\n"
+            "  set-passphrase   Change passphrase on an existing (unmounted) filesystem\n"
+            "  remove-passphrase Remove passphrase on an existing (unmounted) filesystem\n"
+            "\n"
             "Migrate:\n"
             "  migrate          Migrate an existing filesystem to bcachefs, in place\n"
             "  migrate-superblock\n"
@@ -133,8 +137,6 @@ int main(int argc, char *argv[])
        if (!strcmp(cmd, "fsck"))
                return cmd_fsck(argc, argv);
 
-       if (!strcmp(cmd, "unlock"))
-               return cmd_unlock(argc, argv);
        if (!strcmp(cmd, "assemble"))
                return cmd_assemble(argc, argv);
        if (!strcmp(cmd, "incremental"))
@@ -150,6 +152,13 @@ int main(int argc, char *argv[])
        if (!strcmp(cmd, "device"))
                return device_cmds(argc, argv);
 
+       if (!strcmp(cmd, "unlock"))
+               return cmd_unlock(argc, argv);
+       if (!strcmp(cmd, "set-passphrase"))
+               return cmd_set_passphrase(argc, argv);
+       if (!strcmp(cmd, "remove-passphrase"))
+               return cmd_remove_passphrase(argc, argv);
+
        if (!strcmp(cmd, "migrate"))
                return cmd_migrate(argc, argv);
        if (!strcmp(cmd, "migrate-superblock"))
index 40b75e74c6ff5ee87df92902075b2a09cf7cdee3..fbe75d08bdd5e950cd6e8aefd870a1c868c83539 100644 (file)
@@ -25,6 +25,7 @@
 #include "libbcachefs.h"
 #include "crypto.h"
 #include "opts.h"
+#include "super-io.h"
 #include "util.h"
 
 #define OPTS                                                                   \
@@ -250,24 +251,8 @@ int cmd_format(int argc, char *argv[])
        if (!darray_size(devices))
                die("Please supply a device");
 
-       if (opts.encrypted && !no_passphrase) {
-               opts.passphrase = read_passphrase("Enter passphrase: ");
-
-               if (isatty(STDIN_FILENO)) {
-                       char *pass2 =
-                               read_passphrase("Enter same passphrase again: ");
-
-                       if (strcmp(opts.passphrase, pass2)) {
-                               memzero_explicit(opts.passphrase,
-                                                strlen(opts.passphrase));
-                               memzero_explicit(pass2, strlen(pass2));
-                               die("Passphrases do not match");
-                       }
-
-                       memzero_explicit(pass2, strlen(pass2));
-                       free(pass2);
-               }
-       }
+       if (opts.encrypted && !no_passphrase)
+               opts.passphrase = read_passphrase_twice("Enter passphrase: ");
 
        darray_foreach(dev, devices)
                dev->fd = open_for_format(dev->path, force);
@@ -289,12 +274,16 @@ int cmd_format(int argc, char *argv[])
 
 int cmd_show_super(int argc, char *argv[])
 {
-       struct bch_sb *sb;
+       struct bch_sb_handle sb;
+       const char *err;
 
        if (argc != 2)
                die("please supply a single device");
 
-       sb = bch2_super_read(argv[1]);
-       bch2_super_print(sb, HUMAN_READABLE);
+       err = bch2_read_super(argv[1], bch2_opts_empty(), &sb);
+       if (err)
+               die("Error opening %s: %s", argv[1], err);
+
+       bch2_super_print(sb.sb, HUMAN_READABLE);
        return 0;
 }
index b22de8158f9200c2d3b835d8bc3a86c1a52d0b96..b5bacf1c991ffd301e3b3aa3add29000b9fd1d71 100644 (file)
--- a/cmd_key.c
+++ b/cmd_key.c
@@ -9,19 +9,92 @@
 
 int cmd_unlock(int argc, char *argv[])
 {
-       struct bch_sb *sb;
+       struct bch_sb_handle sb;
+       const char *err;
        char *passphrase;
 
        if (argc != 2)
-               die("please supply a single device");
+               die("Please supply a single device");
 
-       sb = bch2_super_read(argv[1]);
+       err = bch2_read_super(argv[1], bch2_opts_empty(), &sb);
+       if (err)
+               die("Error opening %s: %s", argv[1], err);
 
        passphrase = read_passphrase("Enter passphrase: ");
 
-       bch2_add_key(sb, passphrase);
+       bch2_add_key(sb.sb, passphrase);
 
        memzero_explicit(passphrase, strlen(passphrase));
        free(passphrase);
        return 0;
 }
+
+int cmd_set_passphrase(int argc, char *argv[])
+{
+       struct bch_opts opts = bch2_opts_empty();
+       struct bch_fs *c = NULL;
+       const char *err;
+
+       if (argc < 2)
+               die("Please supply one or more devices");
+
+       opt_set(opts, nostart, true);
+       err = bch2_fs_open(argv + 1, argc - 1, opts, &c);
+       if (err)
+               die("Error opening %s: %s", argv[1], err);
+
+       struct bch_sb_field_crypt *crypt = bch2_sb_get_crypt(c->disk_sb);
+       if (!crypt)
+               die("Filesystem does not have encryption enabled");
+
+       struct bch_encrypted_key new_key;
+       new_key.magic = BCH_KEY_MAGIC;
+
+       int ret = bch2_decrypt_sb_key(c, crypt, &new_key.key);
+       if (ret)
+               die("Error getting current key");
+
+       char *new_passphrase = read_passphrase_twice("Enter new passphrase: ");
+       struct bch_key passphrase_key = derive_passphrase(crypt, new_passphrase);
+
+       if (bch2_chacha_encrypt_key(&passphrase_key, __bch2_sb_key_nonce(c->disk_sb),
+                                   &new_key, sizeof(new_key)))
+               die("error encrypting key");
+       crypt->key = new_key;
+
+       bch2_write_super(c);
+       bch2_fs_stop(c);
+       return 0;
+}
+
+int cmd_remove_passphrase(int argc, char *argv[])
+{
+       struct bch_opts opts = bch2_opts_empty();
+       struct bch_fs *c = NULL;
+       const char *err;
+
+       if (argc < 2)
+               die("Please supply one or more devices");
+
+       opt_set(opts, nostart, true);
+       err = bch2_fs_open(argv + 1, argc - 1, opts, &c);
+       if (err)
+               die("Error opening %s: %s", argv[1], err);
+
+       struct bch_sb_field_crypt *crypt = bch2_sb_get_crypt(c->disk_sb);
+       if (!crypt)
+               die("Filesystem does not have encryption enabled");
+
+       struct bch_encrypted_key new_key;
+       new_key.magic = BCH_KEY_MAGIC;
+
+       int ret = bch2_decrypt_sb_key(c, crypt, &new_key.key);
+       if (ret)
+               die("Error getting current key");
+
+       crypt->key = new_key;
+
+       bch2_write_super(c);
+       bch2_fs_stop(c);
+       return 0;
+}
index 4b0dd9bca97f24effa315fb179956703d9637e04..519e85daae69e2cfdf093925ee0390b062a2f0ec 100644 (file)
@@ -701,24 +701,8 @@ int cmd_migrate(int argc, char *argv[])
 
        find_superblock_space(extents, &dev);
 
-       if (format_opts.encrypted && !no_passphrase) {
-               format_opts.passphrase = read_passphrase("Enter passphrase: ");
-
-               if (isatty(STDIN_FILENO)) {
-                       char *pass2 =
-                               read_passphrase("Enter same passphrase again: ");
-
-                       if (strcmp(format_opts.passphrase, pass2)) {
-                               memzero_explicit(format_opts.passphrase,
-                                                strlen(format_opts.passphrase));
-                               memzero_explicit(pass2, strlen(pass2));
-                               die("Passphrases do not match");
-                       }
-
-                       memzero_explicit(pass2, strlen(pass2));
-                       free(pass2);
-               }
-       }
+       if (format_opts.encrypted && !no_passphrase)
+               format_opts.passphrase = read_passphrase_twice("Enter passphrase: ");
 
        struct bch_sb *sb = bch2_format(format_opts, &dev, 1);
        u64 sb_offset = le64_to_cpu(sb->layout.sb_offset[0]);
diff --git a/cmds.h b/cmds.h
index 7e4712a5b3e06db445eadb8415f4cd631308931c..fa28904cd66f9525655b853e4181dac325c37fc4 100644 (file)
--- a/cmds.h
+++ b/cmds.h
@@ -12,7 +12,6 @@
 int cmd_format(int argc, char *argv[]);
 int cmd_show_super(int argc, char *argv[]);
 
-int cmd_unlock(int argc, char *argv[]);
 int cmd_assemble(int argc, char *argv[]);
 int cmd_incremental(int argc, char *argv[]);
 int cmd_run(int argc, char *argv[]);
@@ -28,6 +27,10 @@ int cmd_device_offline(int argc, char *argv[]);
 int cmd_device_evacuate(int argc, char *argv[]);
 int cmd_device_set_state(int argc, char *argv[]);
 
+int cmd_unlock(int argc, char *argv[]);
+int cmd_set_passphrase(int argc, char *argv[]);
+int cmd_remove_passphrase(int argc, char *argv[]);
+
 int cmd_fsck(int argc, char *argv[]);
 
 int cmd_dump(int argc, char *argv[]);
index f9ac57f7bf5ce9253c86677e983989f12606df74..306071f96ccf23050e5a09789e699f9063342e65 100644 (file)
--- a/crypto.c
+++ b/crypto.c
@@ -54,11 +54,32 @@ char *read_passphrase(const char *prompt)
        return buf;
 }
 
-void derive_passphrase(struct bch_sb_field_crypt *crypt,
-                      struct bch_key *key,
-                      const char *passphrase)
+char *read_passphrase_twice(const char *prompt)
+{
+       char *pass = read_passphrase(prompt);
+
+       if (!isatty(STDIN_FILENO))
+               return pass;
+
+       char *pass2 = read_passphrase("Enter same passphrase again: ");
+
+       if (strcmp(pass, pass2)) {
+               memzero_explicit(pass, strlen(pass));
+               memzero_explicit(pass2, strlen(pass2));
+               die("Passphrases do not match");
+       }
+
+       memzero_explicit(pass2, strlen(pass2));
+       free(pass2);
+
+       return pass;
+}
+
+struct bch_key derive_passphrase(struct bch_sb_field_crypt *crypt,
+                                const char *passphrase)
 {
        const unsigned char salt[] = "bcache";
+       struct bch_key key;
        int ret;
 
        switch (BCH_CRYPT_KDF_TYPE(crypt)) {
@@ -68,35 +89,49 @@ void derive_passphrase(struct bch_sb_field_crypt *crypt,
                                       1ULL << BCH_KDF_SCRYPT_N(crypt),
                                       1ULL << BCH_KDF_SCRYPT_R(crypt),
                                       1ULL << BCH_KDF_SCRYPT_P(crypt),
-                                      (void *) key, sizeof(*key));
+                                      (void *) &key, sizeof(key));
                if (ret)
                        die("scrypt error: %i", ret);
                break;
        default:
                die("unknown kdf type %llu", BCH_CRYPT_KDF_TYPE(crypt));
        }
+
+       return key;
 }
 
-void bch2_add_key(struct bch_sb *sb, const char *passphrase)
+void bch2_passphrase_check(struct bch_sb *sb, const char *passphrase,
+                          struct bch_key *passphrase_key,
+                          struct bch_encrypted_key *sb_key)
 {
        struct bch_sb_field_crypt *crypt = bch2_sb_get_crypt(sb);
        if (!crypt)
                die("filesystem is not encrypted");
 
-       struct bch_encrypted_key sb_key = crypt->key;
-       if (!bch2_key_is_encrypted(&sb_key))
+       *sb_key = crypt->key;
+
+       if (!bch2_key_is_encrypted(sb_key))
                die("filesystem does not have encryption key");
 
-       struct bch_key passphrase_key;
-       derive_passphrase(crypt, &passphrase_key, passphrase);
+       *passphrase_key = derive_passphrase(crypt, passphrase);
 
        /* Check if the user supplied the correct passphrase: */
-       if (bch2_chacha_encrypt_key(&passphrase_key, __bch2_sb_key_nonce(sb),
-                                  &sb_key, sizeof(sb_key)))
+       if (bch2_chacha_encrypt_key(passphrase_key, __bch2_sb_key_nonce(sb),
+                                   sb_key, sizeof(*sb_key)))
                die("error encrypting key");
 
-       if (bch2_key_is_encrypted(&sb_key))
+       if (bch2_key_is_encrypted(sb_key))
                die("incorrect passphrase");
+}
+
+void bch2_add_key(struct bch_sb *sb, const char *passphrase)
+{
+       struct bch_key passphrase_key;
+       struct bch_encrypted_key sb_key;
+
+       bch2_passphrase_check(sb, passphrase,
+                             &passphrase_key,
+                             &sb_key);
 
        char uuid[40];
        uuid_unparse_lower(sb->user_uuid.b, uuid);
@@ -125,14 +160,13 @@ void bch_sb_crypt_init(struct bch_sb *sb,
        get_random_bytes(&crypt->key.key, sizeof(crypt->key.key));
 
        if (passphrase) {
-               struct bch_key passphrase_key;
 
                SET_BCH_CRYPT_KDF_TYPE(crypt, BCH_KDF_SCRYPT);
                SET_BCH_KDF_SCRYPT_N(crypt, ilog2(SCRYPT_N));
                SET_BCH_KDF_SCRYPT_R(crypt, ilog2(SCRYPT_r));
                SET_BCH_KDF_SCRYPT_P(crypt, ilog2(SCRYPT_p));
 
-               derive_passphrase(crypt, &passphrase_key, passphrase);
+               struct bch_key passphrase_key = derive_passphrase(crypt, passphrase);
 
                assert(!bch2_key_is_encrypted(&crypt->key));
 
index 1e66a4335fc881be753d663531b94130d1986a16..d6c206190d6e2880597046c522251356818d89f1 100644 (file)
--- a/crypto.h
+++ b/crypto.h
@@ -6,10 +6,14 @@
 struct bch_sb;
 struct bch_sb_field_crypt;
 struct bch_key;
+struct bch_encrypted_key;
 
 char *read_passphrase(const char *);
-void derive_passphrase(struct bch_sb_field_crypt *,
-                      struct bch_key *, const char *);
+char *read_passphrase_twice(const char *);
+
+struct bch_key derive_passphrase(struct bch_sb_field_crypt *, const char *);
+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 *);
 void bch_sb_crypt_init(struct bch_sb *sb, struct bch_sb_field_crypt *,
                       const char *);
index 56851a04326379c43cf9cf02e4878c7bcaa68375..b9c3d57a67fb898b61f644d22a60e8d03174529d 100644 (file)
@@ -293,14 +293,6 @@ struct bch_sb *__bch2_super_read(int fd, u64 sector)
        return ret;
 }
 
-struct bch_sb *bch2_super_read(const char *path)
-{
-       int fd = xopen(path, O_RDONLY);
-       struct bch_sb *sb = __bch2_super_read(fd, BCH_SB_SECTOR);
-       close(fd);
-       return sb;
-}
-
 static unsigned get_dev_has_data(struct bch_sb *sb, unsigned dev)
 {
        struct bch_sb_field_replicas *replicas;
index 21dc8598cc8158699a3957ef10a9f97503c86cbb..bea80bb9ba48f46c822e952e0f0c611a9d8e19ec 100644 (file)
@@ -73,7 +73,6 @@ struct bch_sb *bch2_format(struct format_opts, struct dev_opts *, size_t);
 
 void bch2_super_write(int, struct bch_sb *);
 struct bch_sb *__bch2_super_read(int, u64);
-struct bch_sb *bch2_super_read(const char *);
 
 void bch2_super_print(struct bch_sb *, int);