X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=cmd_key.c;h=96206c4c36b5a62cce4cc27fd445a383bdfa87df;hb=a0398cf66f08c722202f45f36660670ab2889e41;hp=b22de8158f9200c2d3b835d8bc3a86c1a52d0b96;hpb=2831b89a7c8ba9262a00ec6d70d1355c02f84a67;p=bcachefs-tools-debian diff --git a/cmd_key.c b/cmd_key.c index b22de81..96206c4 100644 --- a/cmd_key.c +++ b/cmd_key.c @@ -3,25 +3,147 @@ #include #include "cmds.h" -#include "checksum.h" +#include "libbcachefs/checksum.h" #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" + " -k (session|user|user_session)\n" + " Keyring to add to (default: user)\n" + " -h Display this help and exit\n" + "Report bugs to "); +} + int cmd_unlock(int argc, char *argv[]) { - struct bch_sb *sb; - char *passphrase; + const char *keyring = "user"; + bool check = false; + int opt; + + while ((opt = getopt(argc, argv, "ck:h")) != -1) + switch (opt) { + case 'c': + check = true; + break; + case 'k': + keyring = strdup(optarg); + 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(); + + opt_set(opts, noexcl, true); + opt_set(opts, nochanges, true); + + struct bch_sb_handle sb; + int ret = bch2_read_super(dev, &opts, &sb); + if (ret) + die("Error opening %s: %s", dev, bch2_err_str(ret)); - if (argc != 2) - die("please supply a single device"); + if (!bch2_sb_is_encrypted(sb.sb)) + die("%s is not encrypted", dev); - sb = bch2_super_read(argv[1]); + if (check) + exit(EXIT_SUCCESS); - passphrase = read_passphrase("Enter passphrase: "); + char *passphrase = read_passphrase("Enter passphrase: "); - bch2_add_key(sb, passphrase); + bch2_add_key(sb.sb, "user", keyring, passphrase); + 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], bch2_err_str(PTR_ERR(c))); + + struct bch_sb_field_crypt *crypt = bch2_sb_field_get(c->disk_sb.sb, crypt); + 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_revoke_key(c->disk_sb.sb); + 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], bch2_err_str(PTR_ERR(c))); + + struct bch_sb_field_crypt *crypt = bch2_sb_field_get(c->disk_sb.sb, crypt); + 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; +}