diff options
Diffstat (limited to 'src/util.rs')
-rw-r--r-- | src/util.rs | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/src/util.rs b/src/util.rs new file mode 100644 index 0000000..8a6c411 --- /dev/null +++ b/src/util.rs @@ -0,0 +1,154 @@ +use libc::{c_void, free}; +use nitrokey_sys; +use rand::{OsRng, Rng}; +use std; +use std::ffi::CStr; +use std::os::raw::{c_char, c_int}; + +/// Error types returned by Nitrokey device or by the library. +#[derive(Debug, PartialEq)] +pub enum CommandError { + /// A packet with a wrong checksum has been sent or received. + WrongCrc, + /// A command tried to access an OTP slot that does not exist. + WrongSlot, + /// A command tried to generate an OTP on a slot that is not configured. + SlotNotProgrammed, + /// The provided password is wrong. + WrongPassword, + /// You are not authorized for this command or provided a wrong temporary + /// password. + NotAuthorized, + /// An error occured when getting or setting the time. + Timestamp, + /// You did not provide a name for the OTP slot. + NoName, + /// This command is not supported by this device. + NotSupported, + /// This command is unknown. + UnknownCommand, + /// AES decryptionfailed. + AesDecryptionFailed, + /// An unknown error occured. + Unknown, + /// You passed a string containing a null byte. + InvalidString, + /// You passed an invalid slot. + InvalidSlot, + /// An error occured during random number generation. + RngError, +} + +/// Command execution status. +#[derive(Debug, PartialEq)] +pub enum CommandStatus { + /// The command was successful. + Success, + /// An error occured during command execution. + Error(CommandError), +} + +/// Log level for libnitrokey. +#[derive(Debug, PartialEq)] +pub enum LogLevel { + /// Only log error messages. + Error, + /// Log error messages and warnings. + Warning, + /// Log error messages, warnings and info messages. + Info, + /// Log error messages, warnings, info messages and debug messages. + DebugL1, + /// Log error messages, warnings, info messages and detailed debug + /// messages. + Debug, + /// Log error messages, warnings, info messages and very detailed debug + /// messages. + DebugL2, +} + +pub fn owned_str_from_ptr(ptr: *const c_char) -> String { + unsafe { + return CStr::from_ptr(ptr).to_string_lossy().into_owned(); + } +} + +pub fn result_from_string(ptr: *const c_char) -> Result<String, CommandError> { + if ptr.is_null() { + return Err(CommandError::Unknown); + } + unsafe { + let s = owned_str_from_ptr(ptr); + if s.is_empty() { + return Err(get_last_error()); + } + // TODO: move up for newer libnitrokey versions + free(ptr as *mut c_void); + return Ok(s); + } +} + +pub fn get_last_status() -> CommandStatus { + unsafe { + let status = nitrokey_sys::NK_get_last_command_status(); + return CommandStatus::from(status as c_int); + } +} + +pub fn get_last_error() -> CommandError { + return match get_last_status() { + CommandStatus::Success => CommandError::Unknown, + CommandStatus::Error(err) => err, + }; +} + +pub fn generate_password(length: usize) -> std::io::Result<Vec<u8>> { + let mut rng = match OsRng::new() { + Ok(rng) => rng, + Err(err) => return Err(err), + }; + let mut data = vec![0u8; length]; + rng.fill_bytes(&mut data[..]); + return Ok(data); +} + +impl From<c_int> for CommandError { + fn from(value: c_int) -> Self { + match value { + 1 => CommandError::WrongCrc, + 2 => CommandError::WrongSlot, + 3 => CommandError::SlotNotProgrammed, + 4 => CommandError::WrongPassword, + 5 => CommandError::NotAuthorized, + 6 => CommandError::Timestamp, + 7 => CommandError::NoName, + 8 => CommandError::NotSupported, + 9 => CommandError::UnknownCommand, + 10 => CommandError::AesDecryptionFailed, + 201 => CommandError::InvalidSlot, + _ => CommandError::Unknown, + } + } +} + +impl From<c_int> for CommandStatus { + fn from(value: c_int) -> Self { + match value { + 0 => CommandStatus::Success, + other => CommandStatus::Error(CommandError::from(other)), + } + } +} + +impl Into<i32> for LogLevel { + fn into(self) -> i32 { + match self { + LogLevel::Error => 0, + LogLevel::Warning => 1, + LogLevel::Info => 2, + LogLevel::DebugL1 => 3, + LogLevel::Debug => 4, + LogLevel::DebugL2 => 5, + } + } +} |