mirror of
https://github.com/koverstreet/bcachefs-tools.git
synced 2025-02-09 00:00:04 +03:00
Add decryption by key_file
- Add key_file option to Cli - Rework decryption flow logic to first attempt key_file - Read password from file and pass to decrypt_master_key Explicity specify '-k' for key_location Signed-off-by: Roland Vet <RlndVt@protonmail.com>
This commit is contained in:
parent
0ff96b2a0f
commit
d67643f24c
@ -128,6 +128,14 @@ fn get_devices_by_uuid(uuid: Uuid) -> anyhow::Result<Vec<(PathBuf, bch_sb_handle
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(author, version, about, long_about = None)]
|
||||
pub struct Cli {
|
||||
/// Path to password key file
|
||||
///
|
||||
/// Precedes key_location: if the filesystem can be decrypted by the
|
||||
/// specified key_file; it is decrypted. (i.e. Regardless if "fail"
|
||||
/// is specified for key_location.)
|
||||
#[arg(short = 'f', long)]
|
||||
key_file: Option<PathBuf>,
|
||||
|
||||
/// Where the password would be loaded from.
|
||||
///
|
||||
/// Possible values are:
|
||||
@ -143,7 +151,7 @@ pub struct Cli {
|
||||
/// Where the filesystem should be mounted. If not set, then the filesystem
|
||||
/// won't actually be mounted. But all steps preceeding mounting the
|
||||
/// filesystem (e.g. asking for passphrase) will still be performed.
|
||||
mountpoint: Option<std::path::PathBuf>,
|
||||
mountpoint: Option<PathBuf>,
|
||||
|
||||
/// Mount options
|
||||
#[arg(short, default_value = "")]
|
||||
@ -196,8 +204,31 @@ fn cmd_mount_inner(opt: Cli) -> anyhow::Result<()> {
|
||||
|
||||
if sbs.len() == 0 {
|
||||
Err(anyhow::anyhow!("No device found from specified parameters"))?;
|
||||
} else if unsafe { bcachefs::bch2_sb_is_encrypted(sbs[0].sb) } {
|
||||
key::prepare_key(&sbs[0], opt.key_location)?;
|
||||
}
|
||||
// Check if the filesystem's master key is encrypted
|
||||
if unsafe { bcachefs::bch2_sb_is_encrypted(sbs[0].sb) } {
|
||||
// Filesystem's master key is encrypted, attempt to decrypt
|
||||
// First by key_file, if available
|
||||
let fallback_to_prepare_key = if let Some(key_file) = &opt.key_file {
|
||||
match key::read_from_key_file(&sbs[0], key_file.as_path()) {
|
||||
Ok(()) => {
|
||||
// Decryption succeeded
|
||||
false
|
||||
}
|
||||
Err(err) => {
|
||||
// Decryption failed, fall back to prepare_key
|
||||
error!("Failed to decrypt using key_file: {}", err);
|
||||
true
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// No key_file specified, fall back to prepare_key
|
||||
true
|
||||
};
|
||||
// If decryption by key_file was unsuccesful, prompt for password (or follow key_policy)
|
||||
if fallback_to_prepare_key {
|
||||
key::prepare_key(&sbs[0], opt.key_location)?;
|
||||
};
|
||||
}
|
||||
|
||||
if let Some(mountpoint) = opt.mountpoint {
|
||||
|
12
src/key.rs
12
src/key.rs
@ -1,4 +1,4 @@
|
||||
use std::{fmt, io::{stdin, IsTerminal}};
|
||||
use std::{fmt, fs, io::{stdin, IsTerminal}};
|
||||
|
||||
use log::{info};
|
||||
use bch_bindgen::bcachefs::bch_sb_handle;
|
||||
@ -150,6 +150,16 @@ fn decrypt_master_key(sb: &bch_sb_handle, pass: String) -> anyhow::Result<()> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_from_key_file(sb: &bch_sb_handle, key_file: &std::path::Path) -> anyhow::Result<()> {
|
||||
// Attempts to decrypt the master key by key_file
|
||||
// Return true if decryption was successful, false otherwise
|
||||
info!("Attempting to decrypt master key for filesystem {}, using key file {}", sb.sb().uuid(), key_file.display());
|
||||
// Read the contents of the key file into a string
|
||||
let pass = fs::read_to_string(key_file)?;
|
||||
// Call decrypt_master_key with the read string
|
||||
decrypt_master_key(sb, pass)
|
||||
}
|
||||
|
||||
pub fn prepare_key(sb: &bch_sb_handle, password: KeyLocation) -> anyhow::Result<()> {
|
||||
info!("checking if key exists for filesystem {}", sb.sb().uuid());
|
||||
match password {
|
||||
|
Loading…
Reference in New Issue
Block a user