1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
use std::ffi::{CStr, CString};
use std::os::raw::{c_char, c_int};
use libc::{c_void, free};
use rand_core::RngCore;
use rand_os::OsRng;
use crate::error::{CommandError, Error};
/// Log level for libnitrokey.
///
/// Setting the log level to a lower level enables all output from higher levels too. Currently,
/// only the log levels `Warning`, `DebugL1`, `Debug` and `DebugL2` are actually used.
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum LogLevel {
/// Error messages. Currently not used.
Error,
/// Warning messages.
Warning,
/// Informational messages. Currently not used.
Info,
/// Basic debug messages, especially basic information on the sent and received packets.
DebugL1,
/// Detailed debug messages, especially detailed information on the sent and received packets.
Debug,
/// Very detailed debug messages, especially detailed information about the control flow for
/// device communication (for example function entries and exits).
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, Error> {
if ptr.is_null() {
return Err(CommandError::Undefined.into());
}
unsafe {
let s = owned_str_from_ptr(ptr);
free(ptr as *mut c_void);
// An empty string can both indicate an error or be a valid return value. In this case, we
// have to check the last command status to decide what to return.
if s.is_empty() {
get_last_result().map(|_| s)
} else {
Ok(s)
}
}
}
pub fn get_command_result(value: c_int) -> Result<(), Error> {
match value {
0 => Ok(()),
other => Err(CommandError::from(other).into()),
}
}
pub fn get_last_result() -> Result<(), Error> {
let value = unsafe { nitrokey_sys::NK_get_last_command_status() } as c_int;
get_command_result(value)
}
pub fn get_last_error() -> Error {
return match get_last_result() {
Ok(()) => CommandError::Undefined.into(),
Err(err) => err,
};
}
pub fn generate_password(length: usize) -> Result<Vec<u8>, Error> {
let mut rng = OsRng::new().map_err(CommandError::from)?;
let mut data = vec![0u8; length];
rng.fill_bytes(&mut data[..]);
Ok(data)
}
pub fn get_cstring<T: Into<Vec<u8>>>(s: T) -> Result<CString, Error> {
CString::new(s).or(Err(CommandError::InvalidString.into()))
}
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,
}
}
}
|