aboutsummaryrefslogtreecommitdiff
path: root/src/util.rs
diff options
context:
space:
mode:
authorRobin Krahl <robin.krahl@ireas.org>2018-05-22 00:32:12 +0000
committerRobin Krahl <robin.krahl@ireas.org>2018-05-22 02:35:28 +0200
commita9657c48c8c92f6c82834a2abd90e27904e2cf6b (patch)
tree6991987c5fd21a169a233c30b17706330ae085c6 /src/util.rs
parent2a736067581dd44288b43a01bf47e0d28801e0a8 (diff)
downloadnitrokey-rs-a9657c48c8c92f6c82834a2abd90e27904e2cf6b.tar.gz
nitrokey-rs-a9657c48c8c92f6c82834a2abd90e27904e2cf6b.tar.bz2
Restructure code by functionality
In future versions, we want to support not only the Nitrokey Pro, but also the Nitrokey Storage. This requires a better code layout. This patch introduces two main changes: First, the OTP-specific methods are moved from the Device trait and the AdminAuthenticatedDevice struct to the functionality-based traits ConfigureOtp and GenerateOtp. This will hopefully make it easier to integrate the Nitrokey Storage. Secondly, the code is split into separate modules. These modules are currently all private and re-exported in the lib module, but we can consider making them public in the future.
Diffstat (limited to 'src/util.rs')
-rw-r--r--src/util.rs154
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,
+ }
+ }
+}