hint slots

This commit is contained in:
shimun 2020-04-28 19:09:53 +02:00
parent 2ec8679c47
commit 0b19760175
Signed by: shimun
GPG Key ID: E81D8382DC2F971B
3 changed files with 56 additions and 77 deletions

View File

@ -417,7 +417,7 @@ pub fn run_cli() -> Fido2LuksResult<()> {
device, device,
&name[..], &name[..],
Box::new(|mut creds| { Box::new(|mut creds| {
let secret = SecretGeneration { let (secret, cred) = SecretGeneration {
credential_ids: CommaSeparated( credential_ids: CommaSeparated(
creds creds
.iter() .iter()
@ -429,8 +429,8 @@ pub fn run_cli() -> Fido2LuksResult<()> {
await_authenticator: 100, await_authenticator: 100,
verify_password: None, verify_password: None,
} }
.obtain_secret("Password"); .obtain_secret_and_credential("Password")?;
secret.map(|s| s.to_vec().into_boxed_slice()) Ok((secret, hex::encode(cred.id)))
}), }),
), ),
Command::Connected => match get_devices() { Command::Connected => match get_devices() {

View File

@ -56,9 +56,27 @@ pub enum LuksError {
InvalidToken(String), InvalidToken(String),
#[fail(display = "No token found")] #[fail(display = "No token found")]
NoToken, NoToken,
#[fail(display = "The device already exists")]
DeviceExists,
}
impl LuksError {
pub fn activate(e: LibcryptErr) -> Fido2LuksError {
match e {
LibcryptErr::IOError(ref io) => match io.raw_os_error() {
Some(1) if io.kind() == ErrorKind::PermissionDenied => Fido2LuksError::WrongSecret,
Some(17) => Fido2LuksError::LuksError {
cause: LuksError::DeviceExists,
},
_ => return Fido2LuksError::CryptsetupError { cause: e },
},
_ => Fido2LuksError::CryptsetupError { cause: e },
}
}
} }
use libcryptsetup_rs::LibcryptErr; use libcryptsetup_rs::LibcryptErr;
use std::io::ErrorKind;
use std::string::FromUtf8Error; use std::string::FromUtf8Error;
use Fido2LuksError::*; use Fido2LuksError::*;

View File

@ -5,6 +5,7 @@ use libcryptsetup_rs::{
size_t, CryptActivateFlags, CryptDevice, CryptInit, CryptLuks2Token, CryptTokenInfo, size_t, CryptActivateFlags, CryptDevice, CryptInit, CryptLuks2Token, CryptTokenInfo,
EncryptionFormat, KeyslotInfo, LibcryptErr, EncryptionFormat, KeyslotInfo, LibcryptErr,
}; };
use std::collections::{HashMap, HashSet};
use std::path::Path; use std::path::Path;
use std::result::Result; use std::result::Result;
@ -49,7 +50,7 @@ struct Fido2LuksToken {
impl Fido2LuksToken { impl Fido2LuksToken {
fn new(credential_id: impl AsRef<[u8]>, slot: u32) -> Self { fn new(credential_id: impl AsRef<[u8]>, slot: u32) -> Self {
Self { Self {
type_: "fido2luks\0".into(), type_: "fido2luks\0".into(), // Doubles as c style string
credential: vec![hex::encode(credential_id)], credential: vec![hex::encode(credential_id)],
keyslots: vec![slot.to_string()], keyslots: vec![slot.to_string()],
} }
@ -68,72 +69,12 @@ pub fn open_container<P: AsRef<Path>>(path: P, name: &str, secret: &[u8]) -> Fid
pub fn open_container_token<P: AsRef<Path>>( pub fn open_container_token<P: AsRef<Path>>(
path: P, path: P,
name: &str, name: &str,
mut secret: Box<Fn(Vec<String>) -> Fido2LuksResult<Box<[u8]>>>, mut secret: Box<Fn(Vec<String>) -> Fido2LuksResult<([u8; 32], String)>>,
) -> Fido2LuksResult<()> { ) -> Fido2LuksResult<()> {
let mut device = load_device_handle(path)?; let mut device = load_device_handle(path)?;
check_luks2(&mut device)?; check_luks2(&mut device)?;
/*
// https://gitlab.com/cryptsetup/cryptsetup/-/blob/0b38128e21175b24f8dd1ad06257754af3d4437f/lib/libcryptsetup.h#L2096
let mut token_data: Option<Fido2LuksToken> = None;
fn open_token(
mut device: CryptDevice,
id: i32,
data: Option<&mut Box<Fn(Vec<String>) -> Fido2LuksResult<Box<[u8]>>>>,
) -> Result<Box<[u8]>, 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<Fn(Vec<String>) -> Fido2LuksResult<Box<[u8]>>>;
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( let mut creds = HashMap::new();
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) {
}
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 { for i in 0..256 {
let (status, type_) = device.token_handle().status(i)?; let (status, type_) = device.token_handle().status(i)?;
if status == CryptTokenInfo::Inactive { if status == CryptTokenInfo::Inactive {
@ -151,18 +92,38 @@ pub fn open_container_token<P: AsRef<Path>>(
serde_json::from_value(json.clone()).map_err(|_| Fido2LuksError::LuksError { serde_json::from_value(json.clone()).map_err(|_| Fido2LuksError::LuksError {
cause: LuksError::InvalidToken(json.to_string()), cause: LuksError::InvalidToken(json.to_string()),
})?; })?;
creds.extend_from_slice(&info.credential[..]); let slots = || {
info.keyslots
.iter()
.filter_map(|slot| slot.parse::<u32>().ok())
};
for cred in info.credential.iter().cloned() {
creds
.entry(cred)
.or_insert_with(|| slots().collect::<HashSet<u32>>())
.extend(slots());
} }
device }
let (secret, credential) = secret(dbg!(creds.keys().cloned().collect()))?;
let slots = creds.get(&credential).unwrap();
let mut slots = slots
.iter()
.cloned()
.map(Option::Some)
.chain(std::iter::once(None).take(slots.is_empty() as usize));
for slot in slots {
match device
.activate_handle() .activate_handle()
.activate_by_passphrase( .activate_by_passphrase(Some(name), slot, &secret, CryptActivateFlags::empty())
Some(name),
None,
secret(dbg!(creds))?.as_ref(),
CryptActivateFlags::empty(),
)
.map(|_slot| ()) .map(|_slot| ())
.map_err(|_e| Fido2LuksError::WrongSecret) .map_err(LuksError::activate)
{
Err(Fido2LuksError::WrongSecret) => (),
res => return res,
}
}
Err(Fido2LuksError::WrongSecret)
} }
pub fn add_key<P: AsRef<Path>>( pub fn add_key<P: AsRef<Path>>(