" 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"
" 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"
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"))
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"))
#include "libbcachefs.h"
#include "crypto.h"
#include "opts.h"
+#include "super-io.h"
#include "util.h"
#define OPTS \
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);
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;
}
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;
+}
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]);
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[]);
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[]);
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)) {
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);
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));
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 *);
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;
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);