mirror of
https://github.com/koverstreet/bcachefs-tools.git
synced 2025-02-23 00:00:02 +03:00
Add commands for changing and removing passphrase
This commit is contained in:
parent
b984559329
commit
097fd2a5e6
15
bcachefs.c
15
bcachefs.c
@ -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"))
|
||||
|
31
cmd_format.c
31
cmd_format.c
@ -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;
|
||||
}
|
||||
|
81
cmd_key.c
81
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;
|
||||
}
|
||||
|
@ -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]);
|
||||
|
5
cmds.h
5
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[]);
|
||||
|
60
crypto.c
60
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,
|
||||
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));
|
||||
|
||||
|
8
crypto.h
8
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 *);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user