X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=cmd_key.c;h=6052cb0061762b8ed8d6a1f4c56dfc8c7e54ee41;hb=4e69c09f4b5e38d8aeb72e300d18b15e9964a635;hp=587ecbe383c0623f2d572f0a9d02c6be3a90f204;hpb=a5b5eba7f788bb77cf57f9c94f3474a2d439ab0b;p=bcachefs-tools-debian diff --git a/cmd_key.c b/cmd_key.c index 587ecbe..6052cb0 100644 --- a/cmd_key.c +++ b/cmd_key.c @@ -1,62 +1,142 @@ #include #include -#include #include #include "cmds.h" -#include "checksum.h" +#include "libbcachefs/checksum.h" #include "crypto.h" -#include "libbcache.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[]) { - struct bch_encrypted_key sb_key; - struct bch_key passphrase_key; - struct bch_sb *sb; - struct bch_sb_field_crypt *crypt; - char *passphrase; - char uuid[40]; - char description[60]; + bool check = false; + int opt; - if (argc != 2) - die("please supply a single device"); + while ((opt = getopt(argc, argv, "ch")) != -1) + switch (opt) { + case 'c': + check = true; + break; + case 'h': + unlock_usage(); + exit(EXIT_SUCCESS); + } + args_shift(optind); - sb = bcache_super_read(argv[1]); + char *dev = arg_pop(); + if (!dev) + die("Please supply a device"); - crypt = bch_sb_get_crypt(sb); - if (!crypt) - die("filesystem is not encrypted"); + if (argc) + die("Too many arguments"); - sb_key = crypt->key; + struct bch_opts opts = bch2_opts_empty(); - if (!bch_key_is_encrypted(&sb_key)) - die("filesystem does not have encryption key"); + opt_set(opts, noexcl, true); + opt_set(opts, nochanges, true); - passphrase = read_passphrase("Enter passphrase: "); - derive_passphrase(crypt, &passphrase_key, passphrase); + struct bch_sb_handle sb; + int ret = bch2_read_super(dev, &opts, &sb); + if (ret) + die("Error opening %s: %s", dev, strerror(-ret)); - /* Check if the user supplied the correct passphrase: */ - if (bch_chacha_encrypt_key(&passphrase_key, __bch_sb_key_nonce(sb), - &sb_key, sizeof(sb_key))) - die("error encrypting key"); + if (!bch2_sb_is_encrypted(sb.sb)) + die("%s is not encrypted", dev); - if (bch_key_is_encrypted(&sb_key)) - die("incorrect passphrase"); + if (check) + exit(EXIT_SUCCESS); - uuid_unparse_lower(sb->user_uuid.b, uuid); - sprintf(description, "bcache:%s", uuid); + char *passphrase = read_passphrase("Enter passphrase: "); - if (add_key("logon", description, - &passphrase_key, sizeof(passphrase_key), - KEY_SPEC_USER_KEYRING) < 0 || - add_key("user", description, - &passphrase_key, sizeof(passphrase_key), - KEY_SPEC_USER_KEYRING) < 0) - die("add_key error: %s", strerror(errno)); + bch2_add_key(sb.sb, passphrase); - memzero_explicit(&sb_key, sizeof(sb_key)); - memzero_explicit(&passphrase_key, sizeof(passphrase_key)); + bch2_free_super(&sb); 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; + + if (argc < 2) + 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))); + + struct bch_sb_field_crypt *crypt = bch2_sb_get_crypt(c->disk_sb.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.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; + + if (argc < 2) + die("Please supply one or more devices"); + + opt_set(opts, nostart, true); + c = bch2_fs_open(argv + 1, argc - 1, opts); + if (IS_ERR(c)) + die("Error opening %s: %s", argv[1], strerror(-PTR_ERR(c))); + + struct bch_sb_field_crypt *crypt = bch2_sb_get_crypt(c->disk_sb.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; +}