diff --git a/Cargo.lock b/Cargo.lock index cc44930..98fccf4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -55,9 +55,9 @@ dependencies = [ [[package]] name = "backtrace-sys" -version = "0.1.35" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7de8aba10a69c8e8d7622c5710229485ec32e9d55fdad160ea559c086fdcd118" +checksum = "78848718ee1255a2485d1309ad9cdecfc2e7d0362dd11c6829364c6b35ae1bc7" dependencies = [ "cc", "libc", @@ -111,9 +111,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.50" +version = "1.0.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd" +checksum = "c3d87b23d6a92cd03af510a5ade527033f6aa6fa92161e2d5863a907d4c5e31d" [[package]] name = "cexpr" @@ -287,7 +287,7 @@ dependencies = [ "proc-macro2 1.0.10", "quote 1.0.3", "strsim 0.9.3", - "syn 1.0.17", + "syn 1.0.18", ] [[package]] @@ -298,7 +298,7 @@ checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72" dependencies = [ "darling_core", "quote 1.0.3", - "syn 1.0.17", + "syn 1.0.18", ] [[package]] @@ -311,7 +311,7 @@ dependencies = [ "derive_builder_core", "proc-macro2 1.0.10", "quote 1.0.3", - "syn 1.0.17", + "syn 1.0.18", ] [[package]] @@ -323,7 +323,7 @@ dependencies = [ "darling", "proc-macro2 1.0.10", "quote 1.0.3", - "syn 1.0.17", + "syn 1.0.18", ] [[package]] @@ -363,13 +363,13 @@ checksum = "030a733c8287d6213886dd487564ff5c8f6aae10278b3588ed177f9d18f8d231" dependencies = [ "proc-macro2 1.0.10", "quote 1.0.3", - "syn 1.0.17", + "syn 1.0.18", "synstructure", ] [[package]] name = "fido2luks" -version = "0.2.7" +version = "0.2.8" dependencies = [ "ctap_hmac", "failure", @@ -418,9 +418,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.1.10" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "725cf19794cf90aa94e65050cb4191ff5d8fa87a498383774c47b332e3af952e" +checksum = "61565ff7aaace3525556587bd2dc31d4a07071957be715e63ce7b1eccf51a8f4" dependencies = [ "libc", ] @@ -466,20 +466,20 @@ checksum = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" [[package]] name = "libc" -version = "0.2.68" +version = "0.2.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dea0c0405123bba743ee3f91f49b1c7cfb684eef0da0a50110f758ccf24cdff0" +checksum = "99e85c08494b21a9054e7fe1374a732aeadaff3980b6990b94bfd3a70f690005" [[package]] name = "libcryptsetup-rs" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0177fd0ec022a5adb247e13e3238309913c28102a811227ad5de6a55697f152" +version = "0.3.0" +source = "git+https://github.com/shimunn/libcryptsetup-rs.git?branch=luks2_token_set#3578c05e5d2e23bb19ff8cb0932a778061281844" dependencies = [ "either", "libc", "libcryptsetup-rs-sys", "pkg-config", + "semver", "serde_json", "uuid", ] @@ -487,8 +487,7 @@ dependencies = [ [[package]] name = "libcryptsetup-rs-sys" version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c605998e81e2a99c1f4c5d0be45ea1df6f1dc45dc64f5ca2847b0dbebf49ae7" +source = "git+https://github.com/shimunn/libcryptsetup-rs.git?branch=luks2_token_set#3578c05e5d2e23bb19ff8cb0932a778061281844" dependencies = [ "bindgen", "cc", @@ -580,26 +579,26 @@ checksum = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677" [[package]] name = "proc-macro-error" -version = "0.4.12" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18f33027081eba0a6d8aba6d1b1c3a3be58cbb12106341c2d5759fcd9b5277e7" +checksum = "98e9e4b82e0ef281812565ea4751049f1bdcdfccda7d3f459f2e138a40c08678" dependencies = [ "proc-macro-error-attr", "proc-macro2 1.0.10", "quote 1.0.3", - "syn 1.0.17", + "syn 1.0.18", "version_check", ] [[package]] name = "proc-macro-error-attr" -version = "0.4.12" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a5b4b77fdb63c1eca72173d68d24501c54ab1269409f6b672c85deb18af69de" +checksum = "4f5444ead4e9935abd7f27dc51f7e852a0569ac888096d5ec2499470794e2e53" dependencies = [ "proc-macro2 1.0.10", "quote 1.0.3", - "syn 1.0.17", + "syn 1.0.18", "syn-mid", "version_check", ] @@ -784,17 +783,11 @@ dependencies = [ "rand_core 0.3.1", ] -[[package]] -name = "redox_syscall" -version = "0.1.56" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" - [[package]] name = "regex" -version = "1.3.6" +version = "1.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f6946991529684867e47d86474e3a6d0c0ab9b82d5821e314b1ede31fa3a4b3" +checksum = "a6020f034922e3194c711b82a627453881bc4682166cabb07134a10c26ba7692" dependencies = [ "aho-corasick", "memchr", @@ -863,9 +856,9 @@ checksum = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" [[package]] name = "ryu" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "535622e6be132bccd223f4bb2b8ac8d53cda3c7a6394944d3b2b33fb974f9d76" +checksum = "ed3d612bc64430efeb3f7ee6ef26d590dce0c43249217bddc62112540c7941e1" [[package]] name = "scopeguard" @@ -902,7 +895,7 @@ checksum = "9e549e3abf4fb8621bd1609f11dfc9f5e50320802273b12f3811a67e6716ea6c" dependencies = [ "proc-macro2 1.0.10", "quote 1.0.3", - "syn 1.0.17", + "syn 1.0.18", ] [[package]] @@ -936,9 +929,9 @@ checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" [[package]] name = "structopt" -version = "0.3.12" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8faa2719539bbe9d77869bfb15d4ee769f99525e707931452c97b693b3f159d" +checksum = "863246aaf5ddd0d6928dfeb1a9ca65f505599e4e1b399935ef7e75107516b4ef" dependencies = [ "clap", "lazy_static", @@ -947,15 +940,15 @@ dependencies = [ [[package]] name = "structopt-derive" -version = "0.4.5" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f88b8e18c69496aad6f9ddf4630dd7d585bcaf765786cb415b9aec2fe5a0430" +checksum = "d239ca4b13aee7a2142e6795cbd69e457665ff8037aed33b3effdc430d2f927a" dependencies = [ "heck", "proc-macro-error", "proc-macro2 1.0.10", "quote 1.0.3", - "syn 1.0.17", + "syn 1.0.18", ] [[package]] @@ -971,9 +964,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0df0eb663f387145cab623dea85b09c2c5b4b0aef44e945d928e682fce71bb03" +checksum = "410a7488c0a728c7ceb4ad59b9567eb4053d02e8cc7f5c0e0eeeb39518369213" dependencies = [ "proc-macro2 1.0.10", "quote 1.0.3", @@ -988,7 +981,7 @@ checksum = "7be3539f6c128a931cf19dcee741c1af532c7fd387baa739c03dd2e96479338a" dependencies = [ "proc-macro2 1.0.10", "quote 1.0.3", - "syn 1.0.17", + "syn 1.0.18", ] [[package]] @@ -999,7 +992,7 @@ checksum = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545" dependencies = [ "proc-macro2 1.0.10", "quote 1.0.3", - "syn 1.0.17", + "syn 1.0.18", "unicode-xid 0.2.0", ] @@ -1032,12 +1025,11 @@ dependencies = [ [[package]] name = "time" -version = "0.1.42" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" +checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" dependencies = [ "libc", - "redox_syscall", "winapi", ] @@ -1119,9 +1111,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa515c5163a99cc82bab70fd3bfdd36d827be85de63737b40fcef2ce084a436e" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" dependencies = [ "winapi", ] diff --git a/Cargo.toml b/Cargo.toml index 4d308c9..21b74c9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fido2luks" -version = "0.2.7" +version = "0.2.8" authors = ["shimunn "] edition = "2018" @@ -20,7 +20,8 @@ ring = "0.13.5" failure = "0.1.5" rpassword = "4.0.1" structopt = "0.3.2" -libcryptsetup-rs = "0.2.0" +#libcryptsetup-rs = "0.3.0" +libcryptsetup-rs = { git = "https://github.com/shimunn/libcryptsetup-rs.git", branch = "luks2_token_set" } serde_json = "1.0.51" serde_derive = "1.0.106" serde = "1.0.106" diff --git a/src/cli.rs b/src/cli.rs index 200e1de..c1fa2b1 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -267,6 +267,15 @@ pub enum Command { #[structopt(flatten)] secret_gen: SecretGeneration, }, + /// Open the LUKS device using information embedded into the LUKS 2 header + #[structopt(name = "open-token")] + OpenToken { + #[structopt(env = "FIDO2LUKS_DEVICE")] + device: PathBuf, + #[structopt(env = "FIDO2LUKS_MAPPER_NAME")] + name: String, + salt: String, + }, /// Generate a new FIDO credential #[structopt(name = "credential")] Credential { @@ -404,6 +413,26 @@ pub fn run_cli() -> Fido2LuksResult<()> { } } } + Command::OpenToken { device, name, salt } => luks::open_container_token( + device, + &name[..], + Box::new(|mut creds| { + let secret = SecretGeneration { + credential_ids: CommaSeparated( + creds + .iter() + .map(|c| HexEncoded::from_str(&c[..]).unwrap()) + .collect(), + ), + salt: InputSalt::String("".into()), + password_helper: Default::default(), + await_authenticator: 100, + verify_password: None, + } + .obtain_secret("Password"); + secret.map(|s| s.to_vec().into_boxed_slice()) + }), + ), Command::Connected => match get_devices() { Ok(ref devs) if !devs.is_empty() => { println!("Found {} devices", devs.len()); diff --git a/src/error.rs b/src/error.rs index eb3685d..2959de7 100644 --- a/src/error.rs +++ b/src/error.rs @@ -54,6 +54,8 @@ pub enum LuksError { Luks2Required, #[fail(display = "Invalid token: {}", _0)] InvalidToken(String), + #[fail(display = "No token found")] + NoToken, } use libcryptsetup_rs::LibcryptErr; diff --git a/src/luks.rs b/src/luks.rs index bbc123c..03b1807 100644 --- a/src/luks.rs +++ b/src/luks.rs @@ -1,13 +1,22 @@ use crate::error::*; use failure::{Fail, ResultExt}; -use libcryptsetup_rs::{CryptActivateFlags, CryptDevice, CryptInit, CryptTokenInfo, EncryptionFormat, KeyslotInfo, CryptLuks2Token, LibcryptErr}; +use libcryptsetup_rs::{ + size_t, CryptActivateFlags, CryptDevice, CryptInit, CryptLuks2Token, CryptTokenInfo, + EncryptionFormat, KeyslotInfo, LibcryptErr, +}; use std::path::Path; +use std::result::Result; fn load_device_handle>(path: P) -> Fido2LuksResult { let mut device = CryptInit::init(path.as_ref())?; //TODO: determine luks version some way other way than just trying - let mut load = |format| device.context_handle().load::<()>(Some(format), None).map(|_| ()); + let mut load = |format| { + device + .context_handle() + .load::<()>(Some(format), None) + .map(|_| ()) + }; vec![EncryptionFormat::Luks2, EncryptionFormat::Luks1] .into_iter() .fold(None, |res, format| match res { @@ -21,7 +30,7 @@ fn load_device_handle>(path: P) -> Fido2LuksResult { fn check_luks2(device: &mut CryptDevice) -> Fido2LuksResult<()> { Ok(()) - /* match device.format_handle().get_type()? { + /* match device.format_handle().get_type()? { EncryptionFormat::Luks2 => Ok(()), _ => Err(Fido2LuksError::LuksError { cause: LuksError::Luks2Required, @@ -40,7 +49,7 @@ struct Fido2LuksToken { impl Fido2LuksToken { fn new(credential_id: impl AsRef<[u8]>, slot: u32) -> Self { Self { - type_: "fido2luks".into(), + type_: "fido2luks\0".into(), credential: vec![hex::encode(credential_id)], keyslots: vec![slot.to_string()], } @@ -56,15 +65,105 @@ pub fn open_container>(path: P, name: &str, secret: &[u8]) -> Fid .map_err(|_e| Fido2LuksError::WrongSecret) } -/*pub fn open_container_token>(path: P, name: &str, secret: &[u8]) -> Fido2LuksResult<()> { +pub fn open_container_token>( + path: P, + name: &str, + mut secret: Box) -> Fido2LuksResult>>, +) -> Fido2LuksResult<()> { let mut device = load_device_handle(path)?; check_luks2(&mut device)?; - fn open_token(mut device: CryptDevice, token: u32, ptr: &()) -> Result, LibcryptErr> { + /* + // https://gitlab.com/cryptsetup/cryptsetup/-/blob/0b38128e21175b24f8dd1ad06257754af3d4437f/lib/libcryptsetup.h#L2096 + let mut token_data: Option = None; + fn open_token( + mut device: CryptDevice, + id: i32, + data: Option<&mut Box) -> Fido2LuksResult>>>, + ) -> Result, LibcryptErr> { + dbg!("handler"); + let token: Fido2LuksToken = serde_json::from_value( device.token_handle().json_get(id as u32)?).map_err(|e| LibcryptErr::Other(e.to_string()))?; + if let Some(secret_gen) = data { + secret_gen(token.credential).map_err(|e| LibcryptErr::Other(dbg!(e).to_string())) + } else { + Err(LibcryptErr::Other("No secret_gen".into())) + } + } + //c_token_handler_open!(ext_open_token, Fido2LuksToken, open_token); + extern "C" fn ext_open_token( + cd: *mut libcryptsetup_rs_sys::crypt_device, + token_id: std::os::raw::c_int, + buffer: *mut *mut std::os::raw::c_char, + buffer_len: *mut size_t, + usrptr: *mut std::os::raw::c_void, + ) -> std::os::raw::c_int { + let device = CryptDevice::from_ptr(cd); + let generic_ptr = usrptr as *mut Box) -> Fido2LuksResult>>; + let generic_ref = unsafe { generic_ptr.as_mut() }; + match open_token(device, token_id, generic_ref) { + Ok(secret) => unsafe { + *buffer = Box::into_raw(secret) as *mut std::os::raw::c_char; + 0 + }, + Err(_) => -1, + } + } + fn free_token(boxed: Box<[u8]>) {} + c_token_handler_free!(ext_free_token, free_token); + + fn validate_token( + device: &mut CryptDevice, + json: serde_json::value::Value, + ) -> Result<(), LibcryptErr> { + Ok(()) + } + c_token_handler_validate!(ext_validate_token, validate_token); + + + fn dump_token(device: &mut CryptDevice, json: serde_json::value::Value) { } - CryptLuks2Token::register("fido2luks", c_token_handler_open!(ext_open_token,(), open_token),) - unimplemented!() -}*/ + c_token_handler_dump!(ext_dump_token, dump_token);*/ + /*CryptLuks2Token::register("fido2luks\0", Some(ext_open_token), None, None, None)?; + dbg!("here"); + //let mut salt = salt.to_vec().into_boxed_slice(); + match device.token_handle().activate_by_token(Some(&name),None, Some(&mut secret), CryptActivateFlags::empty()) { + Err(e) => match e { + LibcryptErr::IOError(_) => Err(Fido2LuksError::LuksError { cause: LuksError::NoToken}), + _ => Err(e)? + }, + ok => Ok(ok?) + }*/ + let mut creds = Vec::new(); + for i in 0..256 { + let (status, type_) = device.token_handle().status(i)?; + if status == CryptTokenInfo::Inactive { + break; + } + if let Some(s) = type_ { + if &s != "fido2luks" { + continue; + } + } else { + continue; + } + let json = device.token_handle().json_get(i)?; + let info: Fido2LuksToken = + serde_json::from_value(json.clone()).map_err(|_| Fido2LuksError::LuksError { + cause: LuksError::InvalidToken(json.to_string()), + })?; + creds.extend_from_slice(&info.credential[..]); + } + device + .activate_handle() + .activate_by_passphrase( + Some(name), + None, + secret(dbg!(creds))?.as_ref(), + CryptActivateFlags::empty(), + ) + .map(|_slot| ()) + .map_err(|_e| Fido2LuksError::WrongSecret) +} pub fn add_key>( path: P, @@ -79,9 +178,9 @@ pub fn add_key>( } let slot = device .keyslot_handle() - .add_by_passphrase(None,old_secret, secret)?; + .add_by_passphrase(None, old_secret, secret)?; if let Some(id) = credential_id { - /* if let e @ Err(_) = check_luks2(&mut device) { + /* if let e @ Err(_) = check_luks2(&mut device) { //rollback device.keyslot_handle(Some(slot)).destroy()?; return e.map(|_| 0u32); @@ -126,7 +225,7 @@ fn find_token( fn remove_token(device: &mut CryptDevice, slot: u32) -> Fido2LuksResult<()> { if let Some((token, _)) = find_token(device, slot)? { // remove API?? - device.token_handle().json_set(Some(token), None)?; + device.token_handle().json_set(Some(token), None)?; } Ok(()) } @@ -138,14 +237,14 @@ pub fn remove_keyslots>(path: P, exclude: &[u32]) -> Fido2LuksRes for slot in 0..256 { match device.keyslot_handle().status(slot)? { KeyslotInfo::Inactive => continue, - KeyslotInfo::Active | KeyslotInfo::ActiveLast if !exclude.contains(&slot) => { + KeyslotInfo::Active | KeyslotInfo::ActiveLast if !exclude.contains(&slot) => { if let Ok(_) = check_luks2(&mut device) { - if let Some((token,_)) = dbg!(find_token(&mut device, slot))? { + if let Some((token, _)) = dbg!(find_token(&mut device, slot))? { tokens.push(token); } } - device.keyslot_handle().destroy(slot)?; - destroyed += 1; + device.keyslot_handle().destroy(slot)?; + destroyed += 1; } KeyslotInfo::ActiveLast => break, _ => (), diff --git a/src/main.rs b/src/main.rs index d23eda4..ea6982a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,8 @@ extern crate failure; extern crate ctap_hmac as ctap; #[macro_use] extern crate serde_derive; +#[macro_use] +extern crate libcryptsetup_rs; use crate::cli::*; use crate::config::*; use crate::device::*;