diff --git a/src/luks.rs b/src/luks.rs index efdc0fc..67a9540 100644 --- a/src/luks.rs +++ b/src/luks.rs @@ -7,7 +7,7 @@ use libcryptsetup_rs::{ use std::collections::{HashMap, HashSet}; use std::path::Path; -struct LuksDevice { +pub struct LuksDevice { device: CryptDevice, luks2: Option, } @@ -38,36 +38,42 @@ impl LuksDevice { &'a mut self, ) -> Fido2LuksResult> + 'a>> { - Ok(Box::new((0..32).filter_map(move |i| { - let status = match self.device.token_handle().status(i) { - Ok(status) => status, - Err(err) => return Some(Err(Fido2LuksError::from(err))), - }; - match status { - CryptTokenInfo::Inactive => return None, - CryptTokenInfo::Internal(s) - | CryptTokenInfo::InternalUnknown(s) - | CryptTokenInfo::ExternalUnknown(s) - | CryptTokenInfo::External(s) - if &s != "fido2luks" => - { - return None - } - _ => (), - }; - let json = match self.device.token_handle().json_get(i) { - Ok(json) => json, - Err(err) => return Some(Err(Fido2LuksError::from(err))), - }; - let info: Fido2LuksToken = - match serde_json::from_value(json.clone()).map_err(|_| Fido2LuksError::LuksError { - cause: LuksError::InvalidToken(json.to_string()), - }) { - Ok(info) => info, - Err(err) => return Some(Err(Fido2LuksError::from(err))), - }; - Some(Ok((i, info))) - }))) + Ok(Box::new( + (0..32) + .map(move |i| { + let status = match self.device.token_handle().status(i) { + Ok(status) => status, + Err(err) => return Some(Err(Fido2LuksError::from(err))), + }; + match status { + CryptTokenInfo::Inactive => return None, + CryptTokenInfo::Internal(s) + | CryptTokenInfo::InternalUnknown(s) + | CryptTokenInfo::ExternalUnknown(s) + | CryptTokenInfo::External(s) + if &s != Fido2LuksToken::default_type() => + { + return None + } + _ => (), + }; + let json = match self.device.token_handle().json_get(i) { + Ok(json) => json, + Err(err) => return Some(Err(Fido2LuksError::from(err))), + }; + let info: Fido2LuksToken = + match serde_json::from_value(json.clone()).map_err(|_| { + Fido2LuksError::LuksError { + cause: LuksError::InvalidToken(json.to_string()), + } + }) { + Ok(info) => info, + Err(err) => return Some(Err(Fido2LuksError::from(err))), + }; + Some(Ok((i, info))) + }) + .filter_map(|o| o), + )) } pub fn find_token(&mut self, slot: u32) -> Fido2LuksResult> { @@ -81,6 +87,11 @@ impl LuksDevice { Ok(None) } + pub fn remove_token(&mut self, token: u32) -> Fido2LuksResult<()> { + self.device.token_handle().json_set(TokenInput::RemoveToken(token))?; + Ok(()) + } + pub fn add_key( &mut self, secret: &[u8], @@ -129,9 +140,7 @@ impl LuksDevice { // Ensure indices stay valid tokens.sort(); for token in tokens.iter().rev() { - self.device - .token_handle() - .json_set(TokenInput::RemoveToken(*token))?; + self.remove_token(*token)?; } Ok(destroyed) } @@ -245,19 +254,32 @@ impl LuksDevice { } #[derive(Debug, Clone, Serialize, Deserialize)] -struct Fido2LuksToken { +pub struct Fido2LuksToken { #[serde(rename = "type")] - type_: String, - credential: Vec, - keyslots: Vec, + pub type_: String, + pub credential: Vec, + pub keyslots: Vec, } impl Fido2LuksToken { fn new(credential_id: impl AsRef<[u8]>, slot: u32) -> Self { Self { - type_: "fido2luks\0".into(), // Doubles as c style string credential: vec![hex::encode(credential_id)], keyslots: vec![slot.to_string()], + ..Default::default() + } + } + fn default_type() -> &'static str { + "fido2luks" + } +} + +impl Default for Fido2LuksToken { + fn default() -> Self { + Self { + type_: Self::default_type().into(), + credential: Vec::new(), + keyslots: Vec::new(), } } }