use ctap::FidoError; use libcryptsetup_rs::LibcryptErr; use std::io; use std::io::ErrorKind; use std::string::FromUtf8Error; use Fido2LuksError::*; pub type Fido2LuksResult = Result; #[derive(Debug, Fail)] pub enum Fido2LuksError { #[fail(display = "unable to retrieve password: {}", cause)] AskPassError { cause: AskPassError }, #[fail(display = "unable to read keyfile: {}", cause)] KeyfileError { cause: io::Error }, #[fail(display = "authenticator error: {}", cause)] AuthenticatorError { cause: ctap::FidoError }, #[fail(display = "no authenticator found, please ensure your device is plugged in")] NoAuthenticatorError, #[fail(display = " {}", cause)] CryptsetupError { cause: libcryptsetup_rs::LibcryptErr, }, #[fail(display = "{}", cause)] LuksError { cause: LuksError }, #[fail(display = "{}", cause)] IoError { cause: io::Error }, #[fail(display = "supplied secret isn't valid for this device")] WrongSecret, #[fail(display = "not an utf8 string")] StringEncodingError { cause: FromUtf8Error }, #[fail(display = "not an hex string: {}", string)] HexEncodingError { string: String }, #[fail(display = "couldn't obtain at least one credential")] InsufficientCredentials, } impl Fido2LuksError { pub fn exit_code(&self) -> i32 { use Fido2LuksError::*; match self { AskPassError { .. } | KeyfileError { .. } => 2, AuthenticatorError { .. } => 3, NoAuthenticatorError => 4, WrongSecret => 5, _ => 1, } } } #[derive(Debug, Fail)] pub enum AskPassError { #[fail(display = "unable to retrieve password: {}", _0)] IO(io::Error), #[fail(display = "provided passwords don't match")] Mismatch, #[fail(display = "failed to call password helper")] FailedHelper, } #[derive(Debug, Fail)] pub enum LuksError { #[fail(display = "This feature requires to the LUKS device to be formatted as LUKS 2")] Luks2Required, #[fail(display = "Invalid token: {}", _0)] InvalidToken(String), #[fail(display = "No token found")] 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 }, } } } impl From for Fido2LuksError { fn from(e: LuksError) -> Self { Fido2LuksError::LuksError { cause: e } } } impl From for Fido2LuksError { fn from(e: FidoError) -> Self { AuthenticatorError { cause: e } } } impl From for Fido2LuksError { fn from(e: LibcryptErr) -> Self { match e { LibcryptErr::IOError(e) if e.raw_os_error().iter().any(|code| code == &1i32) => { WrongSecret } _ => CryptsetupError { cause: e }, } } } impl From for Fido2LuksError { fn from(e: io::Error) -> Self { IoError { cause: e } } } impl From for Fido2LuksError { fn from(e: FromUtf8Error) -> Self { StringEncodingError { cause: e } } }