aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Mueller <deso@posteo.net>2019-08-12 22:07:44 -0700
committerDaniel Mueller <deso@posteo.net>2019-08-12 22:07:44 -0700
commit4dc73375e0364aea70b52682b916635b7b75a2eb (patch)
treeb92b238d61c14bb634db699dedcd714918b84975
parenta18066a1a10792ddbd57527ad58f75fc84fafad2 (diff)
downloadnitrocli-4dc73375e0364aea70b52682b916635b7b75a2eb.tar.gz
nitrocli-4dc73375e0364aea70b52682b916635b7b75a2eb.tar.bz2
Update nitrokey crate to 0.4.0-alpha.2
This change updates the dependency to nitrokey to version 0.4.0-alpha.2. In addition to minor interface changes for the get_*_firmware_version and get_*_retry_count functions, several functions that change the device state now require a mutable handle to the nitrokey. Hence, this patch a number of function signatures to accept mutable device objects. Import subrepo nitrokey/:nitrokey at 34efcfadf1436102e42144f710edabaa2c4b55cd
-rw-r--r--nitrocli/CHANGELOG.md2
-rw-r--r--nitrocli/Cargo.lock4
-rw-r--r--nitrocli/Cargo.toml2
-rw-r--r--nitrocli/src/commands.rs54
-rw-r--r--nitrocli/src/tests/pin.rs4
-rw-r--r--nitrocli/src/tests/reset.rs2
-rw-r--r--nitrokey/.builds/archlinux-use-system-lib.yml (renamed from nitrokey/.builds/archlinux-use-system-lib.yaml)0
-rw-r--r--nitrokey/CHANGELOG.md7
-rw-r--r--nitrokey/Cargo.toml7
-rw-r--r--nitrokey/README.md3
-rw-r--r--nitrokey/src/auth.rs38
-rw-r--r--nitrokey/src/device.rs242
-rw-r--r--nitrokey/src/lib.rs10
-rw-r--r--nitrokey/src/otp.rs54
-rw-r--r--nitrokey/src/pws.rs39
-rw-r--r--nitrokey/src/util.rs4
-rw-r--r--nitrokey/tests/device.rs266
-rw-r--r--nitrokey/tests/lib.rs4
-rw-r--r--nitrokey/tests/otp.rs116
-rw-r--r--nitrokey/tests/pws.rs54
-rw-r--r--nitrokey/tests/util/mod.rs31
21 files changed, 560 insertions, 383 deletions
diff --git a/nitrocli/CHANGELOG.md b/nitrocli/CHANGELOG.md
index 7099c6a..dd40acd 100644
--- a/nitrocli/CHANGELOG.md
+++ b/nitrocli/CHANGELOG.md
@@ -1,6 +1,6 @@
Unreleased
----------
-- Bumped `nitrokey` dependency to `0.4.0-alpha.0`
+- Bumped `nitrokey` dependency to `0.4.0-alpha.2`
0.3.0
diff --git a/nitrocli/Cargo.lock b/nitrocli/Cargo.lock
index d2362af..168be50 100644
--- a/nitrocli/Cargo.lock
+++ b/nitrocli/Cargo.lock
@@ -77,7 +77,7 @@ dependencies = [
"argparse 0.2.2",
"base32 0.4.0",
"libc 0.2.66",
- "nitrokey 0.4.0-alpha.0",
+ "nitrokey 0.4.0-alpha.2",
"nitrokey-test 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"nitrokey-test-state 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -85,7 +85,7 @@ dependencies = [
[[package]]
name = "nitrokey"
-version = "0.4.0-alpha.0"
+version = "0.4.0-alpha.2"
dependencies = [
"libc 0.2.66",
"nitrokey-sys 3.4.3",
diff --git a/nitrocli/Cargo.toml b/nitrocli/Cargo.toml
index f8db130..1eb301e 100644
--- a/nitrocli/Cargo.toml
+++ b/nitrocli/Cargo.toml
@@ -53,7 +53,7 @@ path = "../base32"
version = "0.2"
[dependencies.nitrokey]
-version = "0.4.0-alpha.0"
+version = "0.4.0-alpha.2"
[dev-dependencies.nitrokey-test]
version = "0.2.1"
diff --git a/nitrocli/src/commands.rs b/nitrocli/src/commands.rs
index ec09223..ee410e5 100644
--- a/nitrocli/src/commands.rs
+++ b/nitrocli/src/commands.rs
@@ -101,7 +101,7 @@ fn with_password_safe<F>(ctx: &mut args::ExecCtx<'_>, mut op: F) -> Result<()>
where
F: FnMut(&mut args::ExecCtx<'_>, nitrokey::PasswordSafe<'_>) -> Result<()>,
{
- with_device(ctx, |ctx, device| {
+ with_device(ctx, |ctx, mut device| {
let pin_entry = pinentry::PinEntry::from(pinentry::PinType::User, &device)?;
try_with_pin_and_data(
ctx,
@@ -333,15 +333,14 @@ fn print_status(
r#"Status:
model: {model}
serial number: 0x{id}
- firmware version: {fwv0}.{fwv1}
+ firmware version: {fwv}
user retry count: {urc}
admin retry count: {arc}"#,
model = model,
id = serial_number,
- fwv0 = device.get_major_firmware_version(),
- fwv1 = device.get_minor_firmware_version(),
- urc = device.get_user_retry_count(),
- arc = device.get_admin_retry_count(),
+ fwv = device.get_firmware_version()?,
+ urc = device.get_user_retry_count()?,
+ arc = device.get_admin_retry_count()?,
)?;
if let nitrokey::DeviceWrapper::Storage(device) = device {
@@ -368,7 +367,7 @@ pub fn status(ctx: &mut args::ExecCtx<'_>) -> Result<()> {
/// Perform a factory reset.
pub fn reset(ctx: &mut args::ExecCtx<'_>) -> Result<()> {
- with_device(ctx, |ctx, device| {
+ with_device(ctx, |ctx, mut device| {
let pin_entry = pinentry::PinEntry::from(pinentry::PinType::Admin, &device)?;
// To force the user to enter the admin PIN before performing a
@@ -395,7 +394,7 @@ pub fn unencrypted_set(
ctx: &mut args::ExecCtx<'_>,
mode: args::UnencryptedVolumeMode,
) -> Result<()> {
- with_storage_device(ctx, |ctx, device| {
+ with_storage_device(ctx, |ctx, mut device| {
let pin_entry = pinentry::PinEntry::from(pinentry::PinType::Admin, &device)?;
let mode = match mode {
args::UnencryptedVolumeMode::ReadWrite => nitrokey::VolumeMode::ReadWrite,
@@ -417,7 +416,7 @@ pub fn unencrypted_set(
/// Open the encrypted volume on the Nitrokey.
pub fn encrypted_open(ctx: &mut args::ExecCtx<'_>) -> Result<()> {
- with_storage_device(ctx, |ctx, device| {
+ with_storage_device(ctx, |ctx, mut device| {
let pin_entry = pinentry::PinEntry::from(pinentry::PinType::User, &device)?;
// We may forcefully close a hidden volume, if active, so be sure to
@@ -432,7 +431,7 @@ pub fn encrypted_open(ctx: &mut args::ExecCtx<'_>) -> Result<()> {
/// Close the previously opened encrypted volume.
pub fn encrypted_close(ctx: &mut args::ExecCtx<'_>) -> Result<()> {
- with_storage_device(ctx, |_ctx, device| {
+ with_storage_device(ctx, |_ctx, mut device| {
// Flush all filesystem caches to disk. We are mostly interested in
// making sure that the encrypted volume on the Nitrokey we are
// about to close is not closed while not all data was written to
@@ -447,7 +446,7 @@ pub fn encrypted_close(ctx: &mut args::ExecCtx<'_>) -> Result<()> {
/// Create a hidden volume.
pub fn hidden_create(ctx: &mut args::ExecCtx<'_>, slot: u8, start: u8, end: u8) -> Result<()> {
- with_storage_device(ctx, |ctx, device| {
+ with_storage_device(ctx, |ctx, mut device| {
let pwd_entry = pinentry::PwdEntry::from(&device)?;
let pwd = if let Some(pwd) = &ctx.password {
pwd
@@ -466,7 +465,7 @@ pub fn hidden_create(ctx: &mut args::ExecCtx<'_>, slot: u8, start: u8, end: u8)
/// Open a hidden volume.
pub fn hidden_open(ctx: &mut args::ExecCtx<'_>) -> Result<()> {
- with_storage_device(ctx, |ctx, device| {
+ with_storage_device(ctx, |ctx, mut device| {
let pwd_entry = pinentry::PwdEntry::from(&device)?;
let pwd = if let Some(pwd) = &ctx.password {
pwd
@@ -489,7 +488,7 @@ pub fn hidden_open(ctx: &mut args::ExecCtx<'_>) -> Result<()> {
/// Close a previously opened hidden volume.
pub fn hidden_close(ctx: &mut args::ExecCtx<'_>) -> Result<()> {
- with_storage_device(ctx, |_ctx, device| {
+ with_storage_device(ctx, |_ctx, mut device| {
unsafe { sync() };
device
@@ -537,7 +536,7 @@ pub fn config_set(
user_password: Option<bool>,
) -> Result<()> {
with_device(ctx, |ctx, device| {
- let device = authenticate_admin(ctx, device)?;
+ let mut device = authenticate_admin(ctx, device)?;
let config = device
.get_config()
.map_err(|err| get_error("Could not get configuration", err))?;
@@ -555,14 +554,17 @@ pub fn config_set(
/// Lock the Nitrokey device.
pub fn lock(ctx: &mut args::ExecCtx<'_>) -> Result<()> {
- with_device(ctx, |_ctx, device| {
+ with_device(ctx, |_ctx, mut device| {
device
.lock()
.map_err(|err| get_error("Could not lock the device", err))
})
}
-fn get_otp<T: GenerateOtp>(slot: u8, algorithm: args::OtpAlgorithm, device: &T) -> Result<String> {
+fn get_otp<T>(slot: u8, algorithm: args::OtpAlgorithm, device: &mut T) -> Result<String>
+where
+ T: GenerateOtp,
+{
match algorithm {
args::OtpAlgorithm::Hotp => device.get_hotp_code(slot),
args::OtpAlgorithm::Totp => device.get_totp_code(slot),
@@ -584,7 +586,7 @@ pub fn otp_get(
algorithm: args::OtpAlgorithm,
time: Option<u64>,
) -> Result<()> {
- with_device(ctx, |ctx, device| {
+ with_device(ctx, |ctx, mut device| {
if algorithm == args::OtpAlgorithm::Totp {
device
.set_time(
@@ -600,10 +602,10 @@ pub fn otp_get(
.get_config()
.map_err(|err| get_error("Could not get device configuration", err))?;
let otp = if config.user_password {
- let user = authenticate_user(ctx, device)?;
- get_otp(slot, algorithm, &user)
+ let mut user = authenticate_user(ctx, device)?;
+ get_otp(slot, algorithm, &mut user)
} else {
- get_otp(slot, algorithm, &device)
+ get_otp(slot, algorithm, &mut device)
}?;
println!(ctx, "{}", otp)?;
Ok(())
@@ -668,7 +670,7 @@ pub fn otp_set(
}
};
let data = nitrokey::OtpSlotData { secret, ..data };
- let device = authenticate_admin(ctx, device)?;
+ let mut device = authenticate_admin(ctx, device)?;
match algorithm {
args::OtpAlgorithm::Hotp => device.write_hotp_slot(data, counter),
args::OtpAlgorithm::Totp => device.write_totp_slot(data, time_window),
@@ -685,7 +687,7 @@ pub fn otp_clear(
algorithm: args::OtpAlgorithm,
) -> Result<()> {
with_device(ctx, |ctx, device| {
- let device = authenticate_admin(ctx, device)?;
+ let mut device = authenticate_admin(ctx, device)?;
match algorithm {
args::OtpAlgorithm::Hotp => device.erase_hotp_slot(slot),
args::OtpAlgorithm::Totp => device.erase_totp_slot(slot),
@@ -789,7 +791,7 @@ fn choose_pin(
/// Change a PIN.
pub fn pin_set(ctx: &mut args::ExecCtx<'_>, pin_type: pinentry::PinType) -> Result<()> {
- with_device(ctx, |ctx, device| {
+ with_device(ctx, |ctx, mut device| {
let pin_entry = pinentry::PinEntry::from(pin_type, &device)?;
let new_pin = choose_pin(ctx, &pin_entry, true)?;
@@ -812,7 +814,7 @@ pub fn pin_set(ctx: &mut args::ExecCtx<'_>, pin_type: pinentry::PinType) -> Resu
/// Unblock and reset the user PIN.
pub fn pin_unblock(ctx: &mut args::ExecCtx<'_>) -> Result<()> {
- with_device(ctx, |ctx, device| {
+ with_device(ctx, |ctx, mut device| {
let pin_entry = pinentry::PinEntry::from(pinentry::PinType::User, &device)?;
let user_pin = choose_pin(ctx, &pin_entry, false)?;
let pin_entry = pinentry::PinEntry::from(pinentry::PinType::Admin, &device)?;
@@ -892,7 +894,7 @@ pub fn pws_set(
login: &str,
password: &str,
) -> Result<()> {
- with_password_safe(ctx, |_ctx, pws| {
+ with_password_safe(ctx, |_ctx, mut pws| {
pws
.write_slot(slot, name, login, password)
.map_err(|err| get_error("Could not write PWS slot", err))
@@ -901,7 +903,7 @@ pub fn pws_set(
/// Clear a PWS slot.
pub fn pws_clear(ctx: &mut args::ExecCtx<'_>, slot: u8) -> Result<()> {
- with_password_safe(ctx, |_ctx, pws| {
+ with_password_safe(ctx, |_ctx, mut pws| {
pws
.erase_slot(slot)
.map_err(|err| get_error("Could not clear PWS slot", err))
diff --git a/nitrocli/src/tests/pin.rs b/nitrocli/src/tests/pin.rs
index 051129c..e4cd316 100644
--- a/nitrocli/src/tests/pin.rs
+++ b/nitrocli/src/tests/pin.rs
@@ -29,12 +29,12 @@ fn unblock(device: nitrokey::DeviceWrapper) -> crate::Result<()> {
nitrokey::Error::CommandError(err) if err == nitrokey::CommandError::WrongPassword => (),
_ => panic!("Unexpected error variant found: {:?}", err),
}
- assert!(device.get_user_retry_count() < 3);
+ assert!(device.get_user_retry_count()? < 3);
let model = device.get_model();
let _ = Nitrocli::with_dev(device).handle(&["pin", "unblock"])?;
let device = nitrokey::connect_model(model)?;
- assert_eq!(device.get_user_retry_count(), 3);
+ assert_eq!(device.get_user_retry_count()?, 3);
Ok(())
}
diff --git a/nitrocli/src/tests/reset.rs b/nitrocli/src/tests/reset.rs
index 12d7023..f9452ec 100644
--- a/nitrocli/src/tests/reset.rs
+++ b/nitrocli/src/tests/reset.rs
@@ -42,7 +42,7 @@ fn reset(device: nitrokey::DeviceWrapper) -> crate::Result<()> {
// Check that the admin PIN has been reset.
let device = nitrokey::connect_model(ncli.model().unwrap())?;
- let device = device
+ let mut device = device
.authenticate_admin(nitrokey::DEFAULT_ADMIN_PIN)
.unwrap();
diff --git a/nitrokey/.builds/archlinux-use-system-lib.yaml b/nitrokey/.builds/archlinux-use-system-lib.yml
index ac0fc0f..ac0fc0f 100644
--- a/nitrokey/.builds/archlinux-use-system-lib.yaml
+++ b/nitrokey/.builds/archlinux-use-system-lib.yml
diff --git a/nitrokey/CHANGELOG.md b/nitrokey/CHANGELOG.md
index 24c79af..e98e857 100644
--- a/nitrokey/CHANGELOG.md
+++ b/nitrokey/CHANGELOG.md
@@ -31,6 +31,13 @@ SPDX-License-Identifier: MIT
- Return `Error::Utf8Error` if libnitrokey returns an invalid UTF-8 string.
- Implement `From<(T: Device, Error)>` for `Error`.
- Fix timing issues with the `totp_no_pin` and `totp_pin` test cases.
+- Always return a `Result` in functions that communicate with a device.
+- Combine `get_{major,minor}_firmware_version` into `get_firmware_version`.
+- Add `set_encrypted_volume_mode` to `Storage`.
+- Use mutability to represent changes to the device status:
+ - Implement `DerefMut` for `User<T>` and `Admin<T>`.
+ - Add `device_mut` method to `DeviceWrapper`.
+ - Require a mutable `Device` reference if a method changes the device state.
# v0.3.4 (2019-01-20)
- Fix authentication methods that assumed that `char` is signed.
diff --git a/nitrokey/Cargo.toml b/nitrokey/Cargo.toml
index 084bcea..fd6fef7 100644
--- a/nitrokey/Cargo.toml
+++ b/nitrokey/Cargo.toml
@@ -3,7 +3,7 @@
[package]
name = "nitrokey"
-version = "0.4.0-alpha.0"
+version = "0.4.0-alpha.2"
authors = ["Robin Krahl <robin.krahl@ireas.org>"]
edition = "2018"
homepage = "https://code.ireas.org/nitrokey-rs/"
@@ -14,12 +14,13 @@ keywords = ["nitrokey", "otp"]
categories = ["api-bindings"]
readme = "README.md"
license = "MIT"
+exclude = [".builds/*"]
[dependencies]
libc = "0.2"
-nitrokey-sys = "3.4"
+nitrokey-sys = "~3.4"
rand_core = {version = "0.3", default-features = false, features = ["std"] }
rand_os = {version = "0.1"}
[dev-dependencies]
-nitrokey-test = {version = "0.2"}
+nitrokey-test = {version = "=0.2.0"}
diff --git a/nitrokey/README.md b/nitrokey/README.md
index 069fed1..8c596eb 100644
--- a/nitrokey/README.md
+++ b/nitrokey/README.md
@@ -38,8 +38,7 @@ supported by `nitrokey-rs`:
- `NK_is_AES_supported`. This method is no longer needed for Nitrokey devices
with a recent firmware version.
- `NK_set_unencrypted_volume_rorw_pin_type_user`,
- `NK_set_unencrypted_read_only`, `NK_set_unencrypted_read_write`,
- `NK_set_encrypted_read_only` and `NK_set_encrypted_read_write`. These
+ `NK_set_unencrypted_read_only`, `NK_set_unencrypted_read_write`. These
methods are only relevant for older firmware versions (pre-v0.51). As the
Nitrokey Storage firmware can be updated easily, we do not support these
outdated versions.
diff --git a/nitrokey/src/auth.rs b/nitrokey/src/auth.rs
index 18b6572..f9f50fa 100644
--- a/nitrokey/src/auth.rs
+++ b/nitrokey/src/auth.rs
@@ -1,7 +1,7 @@
// Copyright (C) 2018-2019 Robin Krahl <robin.krahl@ireas.org>
// SPDX-License-Identifier: MIT
-use std::ops::Deref;
+use std::ops;
use std::os::raw::c_char;
use std::os::raw::c_int;
@@ -49,7 +49,7 @@ pub trait Authenticate {
/// user.device()
/// },
/// Err((device, err)) => {
- /// println!("Could not authenticate as user: {}", err);
+ /// eprintln!("Could not authenticate as user: {}", err);
/// device
/// },
/// };
@@ -95,7 +95,7 @@ pub trait Authenticate {
/// admin.device()
/// },
/// Err((device, err)) => {
- /// println!("Could not authenticate as admin: {}", err);
+ /// eprintln!("Could not authenticate as admin: {}", err);
/// device
/// },
/// };
@@ -211,7 +211,7 @@ impl<T: Device> User<T> {
}
}
-impl<T: Device> Deref for User<T> {
+impl<T: Device> ops::Deref for User<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
@@ -219,8 +219,14 @@ impl<T: Device> Deref for User<T> {
}
}
+impl<T: Device> ops::DerefMut for User<T> {
+ fn deref_mut(&mut self) -> &mut T {
+ &mut self.device
+ }
+}
+
impl<T: Device> GenerateOtp for User<T> {
- fn get_hotp_code(&self, slot: u8) -> Result<String, Error> {
+ fn get_hotp_code(&mut self, slot: u8) -> Result<String, Error> {
result_from_string(unsafe {
nitrokey_sys::NK_get_hotp_code_PIN(slot, self.temp_password_ptr())
})
@@ -246,7 +252,7 @@ impl<T: Device> AuthenticatedDevice<T> for User<T> {
}
}
-impl<T: Device> Deref for Admin<T> {
+impl<T: Device> ops::Deref for Admin<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
@@ -254,6 +260,12 @@ impl<T: Device> Deref for Admin<T> {
}
}
+impl<T: Device> ops::DerefMut for Admin<T> {
+ fn deref_mut(&mut self) -> &mut T {
+ &mut self.device
+ }
+}
+
impl<T: Device> Admin<T> {
/// Forgets the user authentication and returns an unauthenticated device. This method
/// consumes the authenticated device. It does not perform any actual commands on the
@@ -278,18 +290,18 @@ impl<T: Device> Admin<T> {
/// let device = nitrokey::connect()?;
/// let config = Config::new(None, None, None, false);
/// match device.authenticate_admin("12345678") {
- /// Ok(admin) => {
+ /// Ok(mut admin) => {
/// admin.write_config(config);
/// ()
/// },
- /// Err((_, err)) => println!("Could not authenticate as admin: {}", err),
+ /// Err((_, err)) => eprintln!("Could not authenticate as admin: {}", err),
/// };
/// # Ok(())
/// # }
/// ```
///
/// [`InvalidSlot`]: enum.LibraryError.html#variant.InvalidSlot
- pub fn write_config(&self, config: Config) -> Result<(), Error> {
+ pub fn write_config(&mut self, config: Config) -> Result<(), Error> {
let raw_config = RawConfig::try_from(config)?;
get_command_result(unsafe {
nitrokey_sys::NK_write_config(
@@ -305,7 +317,7 @@ impl<T: Device> Admin<T> {
}
impl<T: Device> ConfigureOtp for Admin<T> {
- fn write_hotp_slot(&self, data: OtpSlotData, counter: u64) -> Result<(), Error> {
+ fn write_hotp_slot(&mut self, data: OtpSlotData, counter: u64) -> Result<(), Error> {
let raw_data = RawOtpSlotData::new(data)?;
get_command_result(unsafe {
nitrokey_sys::NK_write_hotp_slot(
@@ -322,7 +334,7 @@ impl<T: Device> ConfigureOtp for Admin<T> {
})
}
- fn write_totp_slot(&self, data: OtpSlotData, time_window: u16) -> Result<(), Error> {
+ fn write_totp_slot(&mut self, data: OtpSlotData, time_window: u16) -> Result<(), Error> {
let raw_data = RawOtpSlotData::new(data)?;
get_command_result(unsafe {
nitrokey_sys::NK_write_totp_slot(
@@ -339,13 +351,13 @@ impl<T: Device> ConfigureOtp for Admin<T> {
})
}
- fn erase_hotp_slot(&self, slot: u8) -> Result<(), Error> {
+ fn erase_hotp_slot(&mut self, slot: u8) -> Result<(), Error> {
get_command_result(unsafe {
nitrokey_sys::NK_erase_hotp_slot(slot, self.temp_password_ptr())
})
}
- fn erase_totp_slot(&self, slot: u8) -> Result<(), Error> {
+ fn erase_totp_slot(&mut self, slot: u8) -> Result<(), Error> {
get_command_result(unsafe {
nitrokey_sys::NK_erase_totp_slot(slot, self.temp_password_ptr())
})
diff --git a/nitrokey/src/device.rs b/nitrokey/src/device.rs
index 386ce94..f6492cd 100644
--- a/nitrokey/src/device.rs
+++ b/nitrokey/src/device.rs
@@ -12,7 +12,9 @@ use crate::config::{Config, RawConfig};
use crate::error::{CommunicationError, Error};
use crate::otp::GenerateOtp;
use crate::pws::GetPasswordSafe;
-use crate::util::{get_command_result, get_cstring, get_last_error, result_from_string};
+use crate::util::{
+ get_command_result, get_cstring, get_last_error, result_from_string, result_or_error,
+};
/// Available Nitrokey models.
#[derive(Clone, Copy, Debug, PartialEq)]
@@ -76,7 +78,7 @@ impl fmt::Display for VolumeMode {
/// user.device()
/// },
/// Err((device, err)) => {
-/// println!("Could not authenticate as user: {}", err);
+/// eprintln!("Could not authenticate as user: {}", err);
/// device
/// },
/// };
@@ -140,7 +142,7 @@ pub enum DeviceWrapper {
/// user.device()
/// },
/// Err((device, err)) => {
-/// println!("Could not authenticate as user: {}", err);
+/// eprintln!("Could not authenticate as user: {}", err);
/// device
/// },
/// };
@@ -186,7 +188,7 @@ pub struct Pro {
/// user.device()
/// },
/// Err((device, err)) => {
-/// println!("Could not authenticate as user: {}", err);
+/// eprintln!("Could not authenticate as user: {}", err);
/// device
/// },
/// };
@@ -323,7 +325,7 @@ pub trait Device: Authenticate + GetPasswordSafe + GenerateOtp + fmt::Debug {
/// let device = nitrokey::connect()?;
/// match device.get_serial_number() {
/// Ok(number) => println!("serial no: {}", number),
- /// Err(err) => println!("Could not get serial number: {}", err),
+ /// Err(err) => eprintln!("Could not get serial number: {}", err),
/// };
/// # Ok(())
/// # }
@@ -343,13 +345,15 @@ pub trait Device: Authenticate + GetPasswordSafe + GenerateOtp + fmt::Debug {
///
/// # fn try_main() -> Result<(), Error> {
/// let device = nitrokey::connect()?;
- /// let count = device.get_user_retry_count();
- /// println!("{} remaining authentication attempts (user)", count);
+ /// match device.get_user_retry_count() {
+ /// Ok(count) => println!("{} remaining authentication attempts (user)", count),
+ /// Err(err) => eprintln!("Could not get user retry count: {}", err),
+ /// }
/// # Ok(())
/// # }
/// ```
- fn get_user_retry_count(&self) -> u8 {
- unsafe { nitrokey_sys::NK_get_user_retry_count() }
+ fn get_user_retry_count(&self) -> Result<u8, Error> {
+ result_or_error(unsafe { nitrokey_sys::NK_get_user_retry_count() })
}
/// Returns the number of remaining authentication attempts for the admin. The total number of
@@ -364,15 +368,18 @@ pub trait Device: Authenticate + GetPasswordSafe + GenerateOtp + fmt::Debug {
/// # fn try_main() -> Result<(), Error> {
/// let device = nitrokey::connect()?;
/// let count = device.get_admin_retry_count();
- /// println!("{} remaining authentication attempts (admin)", count);
+ /// match device.get_admin_retry_count() {
+ /// Ok(count) => println!("{} remaining authentication attempts (admin)", count),
+ /// Err(err) => eprintln!("Could not get admin retry count: {}", err),
+ /// }
/// # Ok(())
/// # }
/// ```
- fn get_admin_retry_count(&self) -> u8 {
- unsafe { nitrokey_sys::NK_get_admin_retry_count() }
+ fn get_admin_retry_count(&self) -> Result<u8, Error> {
+ result_or_error(unsafe { nitrokey_sys::NK_get_admin_retry_count() })
}
- /// Returns the major part of the firmware version (should be zero).
+ /// Returns the firmware version.
///
/// # Example
///
@@ -382,37 +389,24 @@ pub trait Device: Authenticate + GetPasswordSafe + GenerateOtp + fmt::Debug {
///
/// # fn try_main() -> Result<(), Error> {
/// let device = nitrokey::connect()?;
- /// println!(
- /// "Firmware version: {}.{}",
- /// device.get_major_firmware_version(),
- /// device.get_minor_firmware_version(),
- /// );
+ /// match device.get_firmware_version() {
+ /// Ok(version) => println!("Firmware version: {}", version),
+ /// Err(err) => eprintln!("Could not access firmware version: {}", err),
+ /// };
/// # Ok(())
/// # }
/// ```
- fn get_major_firmware_version(&self) -> i32 {
- unsafe { nitrokey_sys::NK_get_major_firmware_version() }
- }
-
- /// Returns the minor part of the firmware version (for example 8 for version 0.8).
- ///
- /// # Example
- ///
- /// ```no_run
- /// use nitrokey::Device;
- /// # use nitrokey::Error;
- ///
- /// # fn try_main() -> Result<(), Error> {
- /// let device = nitrokey::connect()?;
- /// println!(
- /// "Firmware version: {}.{}",
- /// device.get_major_firmware_version(),
- /// device.get_minor_firmware_version(),
- /// );
- /// # Ok(())
- /// # }
- fn get_minor_firmware_version(&self) -> i32 {
- unsafe { nitrokey_sys::NK_get_minor_firmware_version() }
+ fn get_firmware_version(&self) -> Result<FirmwareVersion, Error> {
+ let major = result_or_error(unsafe { nitrokey_sys::NK_get_major_firmware_version() })?;
+ let minor = result_or_error(unsafe { nitrokey_sys::NK_get_minor_firmware_version() })?;
+ let max = i32::from(u8::max_value());
+ if major < 0 || minor < 0 || major > max || minor > max {
+ return Err(Error::UnexpectedError);
+ }
+ Ok(FirmwareVersion {
+ major: major as u8,
+ minor: minor as u8,
+ })
}
/// Returns the current configuration of the Nitrokey device.
@@ -458,10 +452,10 @@ pub trait Device: Authenticate + GetPasswordSafe + GenerateOtp + fmt::Debug {
/// # use nitrokey::Error;
///
/// # fn try_main() -> Result<(), Error> {
- /// let device = nitrokey::connect()?;
+ /// let mut device = nitrokey::connect()?;
/// match device.change_admin_pin("12345678", "12345679") {
/// Ok(()) => println!("Updated admin PIN."),
- /// Err(err) => println!("Failed to update admin PIN: {}", err),
+ /// Err(err) => eprintln!("Failed to update admin PIN: {}", err),
/// };
/// # Ok(())
/// # }
@@ -469,7 +463,7 @@ pub trait Device: Authenticate + GetPasswordSafe + GenerateOtp + fmt::Debug {
///
/// [`InvalidString`]: enum.LibraryError.html#variant.InvalidString
/// [`WrongPassword`]: enum.CommandError.html#variant.WrongPassword
- fn change_admin_pin(&self, current: &str, new: &str) -> Result<(), Error> {
+ fn change_admin_pin(&mut self, current: &str, new: &str) -> Result<(), Error> {
let current_string = get_cstring(current)?;
let new_string = get_cstring(new)?;
get_command_result(unsafe {
@@ -491,10 +485,10 @@ pub trait Device: Authenticate + GetPasswordSafe + GenerateOtp + fmt::Debug {
/// # use nitrokey::Error;
///
/// # fn try_main() -> Result<(), Error> {
- /// let device = nitrokey::connect()?;
+ /// let mut device = nitrokey::connect()?;
/// match device.change_user_pin("123456", "123457") {
/// Ok(()) => println!("Updated admin PIN."),
- /// Err(err) => println!("Failed to update admin PIN: {}", err),
+ /// Err(err) => eprintln!("Failed to update admin PIN: {}", err),
/// };
/// # Ok(())
/// # }
@@ -502,7 +496,7 @@ pub trait Device: Authenticate + GetPasswordSafe + GenerateOtp + fmt::Debug {
///
/// [`InvalidString`]: enum.LibraryError.html#variant.InvalidString
/// [`WrongPassword`]: enum.CommandError.html#variant.WrongPassword
- fn change_user_pin(&self, current: &str, new: &str) -> Result<(), Error> {
+ fn change_user_pin(&mut self, current: &str, new: &str) -> Result<(), Error> {
let current_string = get_cstring(current)?;
let new_string = get_cstring(new)?;
get_command_result(unsafe {
@@ -524,10 +518,10 @@ pub trait Device: Authenticate + GetPasswordSafe + GenerateOtp + fmt::Debug {
/// # use nitrokey::Error;
///
/// # fn try_main() -> Result<(), Error> {
- /// let device = nitrokey::connect()?;
+ /// let mut device = nitrokey::connect()?;
/// match device.unlock_user_pin("12345678", "123456") {
/// Ok(()) => println!("Unlocked user PIN."),
- /// Err(err) => println!("Failed to unlock user PIN: {}", err),
+ /// Err(err) => eprintln!("Failed to unlock user PIN: {}", err),
/// };
/// # Ok(())
/// # }
@@ -535,7 +529,7 @@ pub trait Device: Authenticate + GetPasswordSafe + GenerateOtp + fmt::Debug {
///
/// [`InvalidString`]: enum.LibraryError.html#variant.InvalidString
/// [`WrongPassword`]: enum.CommandError.html#variant.WrongPassword
- fn unlock_user_pin(&self, admin_pin: &str, user_pin: &str) -> Result<(), Error> {
+ fn unlock_user_pin(&mut self, admin_pin: &str, user_pin: &str) -> Result<(), Error> {
let admin_pin_string = get_cstring(admin_pin)?;
let user_pin_string = get_cstring(user_pin)?;
get_command_result(unsafe {
@@ -558,15 +552,15 @@ pub trait Device: Authenticate + GetPasswordSafe + GenerateOtp + fmt::Debug {
/// # use nitrokey::Error;
///
/// # fn try_main() -> Result<(), Error> {
- /// let device = nitrokey::connect()?;
+ /// let mut device = nitrokey::connect()?;
/// match device.lock() {
/// Ok(()) => println!("Locked the Nitrokey device."),
- /// Err(err) => println!("Could not lock the Nitrokey device: {}", err),
+ /// Err(err) => eprintln!("Could not lock the Nitrokey device: {}", err),
/// };
/// # Ok(())
/// # }
/// ```
- fn lock(&self) -> Result<(), Error> {
+ fn lock(&mut self) -> Result<(), Error> {
get_command_result(unsafe { nitrokey_sys::NK_lock_device() })
}
@@ -589,17 +583,17 @@ pub trait Device: Authenticate + GetPasswordSafe + GenerateOtp + fmt::Debug {
/// # use nitrokey::Error;
///
/// # fn try_main() -> Result<(), Error> {
- /// let device = nitrokey::connect()?;
+ /// let mut device = nitrokey::connect()?;
/// match device.factory_reset("12345678") {
/// Ok(()) => println!("Performed a factory reset."),
- /// Err(err) => println!("Could not perform a factory reset: {}", err),
+ /// Err(err) => eprintln!("Could not perform a factory reset: {}", err),
/// };
/// # Ok(())
/// # }
/// ```
///
/// [`build_aes_key`]: #method.build_aes_key
- fn factory_reset(&self, admin_pin: &str) -> Result<(), Error> {
+ fn factory_reset(&mut self, admin_pin: &str) -> Result<(), Error> {
let admin_pin_string = get_cstring(admin_pin)?;
get_command_result(unsafe { nitrokey_sys::NK_factory_reset(admin_pin_string.as_ptr()) })
}
@@ -623,17 +617,17 @@ pub trait Device: Authenticate + GetPasswordSafe + GenerateOtp + fmt::Debug {
/// # use nitrokey::Error;
///
/// # fn try_main() -> Result<(), Error> {
- /// let device = nitrokey::connect()?;
+ /// let mut device = nitrokey::connect()?;
/// match device.build_aes_key("12345678") {
/// Ok(()) => println!("New AES keys have been built."),
- /// Err(err) => println!("Could not build new AES keys: {}", err),
+ /// Err(err) => eprintln!("Could not build new AES keys: {}", err),
/// };
/// # Ok(())
/// # }
/// ```
///
/// [`factory_reset`]: #method.factory_reset
- fn build_aes_key(&self, admin_pin: &str) -> Result<(), Error> {
+ fn build_aes_key(&mut self, admin_pin: &str) -> Result<(), Error> {
let admin_pin_string = get_cstring(admin_pin)?;
get_command_result(unsafe { nitrokey_sys::NK_build_aes_key(admin_pin_string.as_ptr()) })
}
@@ -655,7 +649,7 @@ pub trait Device: Authenticate + GetPasswordSafe + GenerateOtp + fmt::Debug {
///
/// match nitrokey::connect() {
/// Ok(device) => do_something(device),
-/// Err(err) => println!("Could not connect to a Nitrokey: {}", err),
+/// Err(err) => eprintln!("Could not connect to a Nitrokey: {}", err),
/// }
/// ```
///
@@ -687,7 +681,7 @@ pub fn connect() -> Result<DeviceWrapper, Error> {
///
/// match nitrokey::connect_model(Model::Pro) {
/// Ok(device) => do_something(device),
-/// Err(err) => println!("Could not connect to a Nitrokey Pro: {}", err),
+/// Err(err) => eprintln!("Could not connect to a Nitrokey Pro: {}", err),
/// }
/// ```
///
@@ -734,6 +728,13 @@ impl DeviceWrapper {
DeviceWrapper::Pro(ref pro) => pro,
}
}
+
+ fn device_mut(&mut self) -> &mut dyn Device {
+ match *self {
+ DeviceWrapper::Storage(ref mut storage) => storage,
+ DeviceWrapper::Pro(ref mut pro) => pro,
+ }
+ }
}
impl From<Pro> for DeviceWrapper {
@@ -757,8 +758,8 @@ impl GenerateOtp for DeviceWrapper {
self.device().get_totp_slot_name(slot)
}
- fn get_hotp_code(&self, slot: u8) -> Result<String, Error> {
- self.device().get_hotp_code(slot)
+ fn get_hotp_code(&mut self, slot: u8) -> Result<String, Error> {
+ self.device_mut().get_hotp_code(slot)
}
fn get_totp_code(&self, slot: u8) -> Result<String, Error> {
@@ -791,7 +792,7 @@ impl Pro {
///
/// match nitrokey::Pro::connect() {
/// Ok(device) => use_pro(device),
- /// Err(err) => println!("Could not connect to the Nitrokey Pro: {}", err),
+ /// Err(err) => eprintln!("Could not connect to the Nitrokey Pro: {}", err),
/// }
/// ```
///
@@ -844,7 +845,7 @@ impl Storage {
///
/// match nitrokey::Storage::connect() {
/// Ok(device) => use_storage(device),
- /// Err(err) => println!("Could not connect to the Nitrokey Storage: {}", err),
+ /// Err(err) => eprintln!("Could not connect to the Nitrokey Storage: {}", err),
/// }
/// ```
///
@@ -881,10 +882,10 @@ impl Storage {
/// # use nitrokey::Error;
///
/// # fn try_main() -> Result<(), Error> {
- /// let device = nitrokey::Storage::connect()?;
+ /// let mut device = nitrokey::Storage::connect()?;
/// match device.change_update_pin("12345678", "87654321") {
/// Ok(()) => println!("Updated update PIN."),
- /// Err(err) => println!("Failed to update update PIN: {}", err),
+ /// Err(err) => eprintln!("Failed to update update PIN: {}", err),
/// };
/// # Ok(())
/// # }
@@ -892,7 +893,7 @@ impl Storage {
///
/// [`InvalidString`]: enum.LibraryError.html#variant.InvalidString
/// [`WrongPassword`]: enum.CommandError.html#variant.WrongPassword
- pub fn change_update_pin(&self, current: &str, new: &str) -> Result<(), Error> {
+ pub fn change_update_pin(&mut self, current: &str, new: &str) -> Result<(), Error> {
let current_string = get_cstring(current)?;
let new_string = get_cstring(new)?;
get_command_result(unsafe {
@@ -918,10 +919,10 @@ impl Storage {
/// # use nitrokey::Error;
///
/// # fn try_main() -> Result<(), Error> {
- /// let device = nitrokey::Storage::connect()?;
+ /// let mut device = nitrokey::Storage::connect()?;
/// match device.enable_firmware_update("12345678") {
/// Ok(()) => println!("Nitrokey entered update mode."),
- /// Err(err) => println!("Could not enter update mode: {}", err),
+ /// Err(err) => eprintln!("Could not enter update mode: {}", err),
/// };
/// # Ok(())
/// # }
@@ -929,7 +930,7 @@ impl Storage {
///
/// [`InvalidString`]: enum.LibraryError.html#variant.InvalidString
/// [`WrongPassword`]: enum.CommandError.html#variant.WrongPassword
- pub fn enable_firmware_update(&self, update_pin: &str) -> Result<(), Error> {
+ pub fn enable_firmware_update(&mut self, update_pin: &str) -> Result<(), Error> {
let update_pin_string = get_cstring(update_pin)?;
get_command_result(unsafe {
nitrokey_sys::NK_enable_firmware_update(update_pin_string.as_ptr())
@@ -952,10 +953,10 @@ impl Storage {
/// # use nitrokey::Error;
///
/// # fn try_main() -> Result<(), Error> {
- /// let device = nitrokey::Storage::connect()?;
+ /// let mut device = nitrokey::Storage::connect()?;
/// match device.enable_encrypted_volume("123456") {
/// Ok(()) => println!("Enabled the encrypted volume."),
- /// Err(err) => println!("Could not enable the encrypted volume: {}", err),
+ /// Err(err) => eprintln!("Could not enable the encrypted volume: {}", err),
/// };
/// # Ok(())
/// # }
@@ -963,7 +964,7 @@ impl Storage {
///
/// [`InvalidString`]: enum.LibraryError.html#variant.InvalidString
/// [`WrongPassword`]: enum.CommandError.html#variant.WrongPassword
- pub fn enable_encrypted_volume(&self, user_pin: &str) -> Result<(), Error> {
+ pub fn enable_encrypted_volume(&mut self, user_pin: &str) -> Result<(), Error> {
let user_pin = get_cstring(user_pin)?;
get_command_result(unsafe { nitrokey_sys::NK_unlock_encrypted_volume(user_pin.as_ptr()) })
}
@@ -981,7 +982,7 @@ impl Storage {
/// fn use_volume() {}
///
/// # fn try_main() -> Result<(), Error> {
- /// let device = nitrokey::Storage::connect()?;
+ /// let mut device = nitrokey::Storage::connect()?;
/// match device.enable_encrypted_volume("123456") {
/// Ok(()) => {
/// println!("Enabled the encrypted volume.");
@@ -989,16 +990,16 @@ impl Storage {
/// match device.disable_encrypted_volume() {
/// Ok(()) => println!("Disabled the encrypted volume."),
/// Err(err) => {
- /// println!("Could not disable the encrypted volume: {}", err);
+ /// eprintln!("Could not disable the encrypted volume: {}", err);
/// },
/// };
/// },
- /// Err(err) => println!("Could not enable the encrypted volume: {}", err),
+ /// Err(err) => eprintln!("Could not enable the encrypted volume: {}", err),
/// };
/// # Ok(())
/// # }
/// ```
- pub fn disable_encrypted_volume(&self) -> Result<(), Error> {
+ pub fn disable_encrypted_volume(&mut self) -> Result<(), Error> {
get_command_result(unsafe { nitrokey_sys::NK_lock_encrypted_volume() })
}
@@ -1027,11 +1028,11 @@ impl Storage {
/// # use nitrokey::Error;
///
/// # fn try_main() -> Result<(), Error> {
- /// let device = nitrokey::Storage::connect()?;
+ /// let mut device = nitrokey::Storage::connect()?;
/// device.enable_encrypted_volume("123445")?;
/// match device.enable_hidden_volume("hidden-pw") {
/// Ok(()) => println!("Enabled a hidden volume."),
- /// Err(err) => println!("Could not enable the hidden volume: {}", err),
+ /// Err(err) => eprintln!("Could not enable the hidden volume: {}", err),
/// };
/// # Ok(())
/// # }
@@ -1040,7 +1041,7 @@ impl Storage {
/// [`enable_encrypted_volume`]: #method.enable_encrypted_volume
/// [`AesDecryptionFailed`]: enum.CommandError.html#variant.AesDecryptionFailed
/// [`InvalidString`]: enum.LibraryError.html#variant.InvalidString
- pub fn enable_hidden_volume(&self, volume_password: &str) -> Result<(), Error> {
+ pub fn enable_hidden_volume(&mut self, volume_password: &str) -> Result<(), Error> {
let volume_password = get_cstring(volume_password)?;
get_command_result(unsafe {
nitrokey_sys::NK_unlock_hidden_volume(volume_password.as_ptr())
@@ -1060,7 +1061,7 @@ impl Storage {
/// fn use_volume() {}
///
/// # fn try_main() -> Result<(), Error> {
- /// let device = nitrokey::Storage::connect()?;
+ /// let mut device = nitrokey::Storage::connect()?;
/// device.enable_encrypted_volume("123445")?;
/// match device.enable_hidden_volume("hidden-pw") {
/// Ok(()) => {
@@ -1069,16 +1070,16 @@ impl Storage {
/// match device.disable_hidden_volume() {
/// Ok(()) => println!("Disabled the hidden volume."),
/// Err(err) => {
- /// println!("Could not disable the hidden volume: {}", err);
+ /// eprintln!("Could not disable the hidden volume: {}", err);
/// },
/// };
/// },
- /// Err(err) => println!("Could not enable the hidden volume: {}", err),
+ /// Err(err) => eprintln!("Could not enable the hidden volume: {}", err),
/// };
/// # Ok(())
/// # }
/// ```
- pub fn disable_hidden_volume(&self) -> Result<(), Error> {
+ pub fn disable_hidden_volume(&mut self) -> Result<(), Error> {
get_command_result(unsafe { nitrokey_sys::NK_lock_hidden_volume() })
}
@@ -1107,7 +1108,7 @@ impl Storage {
/// # use nitrokey::Error;
///
/// # fn try_main() -> Result<(), Error> {
- /// let device = nitrokey::Storage::connect()?;
+ /// let mut device = nitrokey::Storage::connect()?;
/// device.enable_encrypted_volume("123445")?;
/// device.create_hidden_volume(0, 0, 100, "hidden-pw")?;
/// # Ok(())
@@ -1117,7 +1118,7 @@ impl Storage {
/// [`AesDecryptionFailed`]: enum.CommandError.html#variant.AesDecryptionFailed
/// [`InvalidString`]: enum.LibraryError.html#variant.InvalidString
pub fn create_hidden_volume(
- &self,
+ &mut self,
slot: u8,
start: u8,
end: u8,
@@ -1147,10 +1148,10 @@ impl Storage {
/// use nitrokey::VolumeMode;
///
/// # fn try_main() -> Result<(), Error> {
- /// let device = nitrokey::Storage::connect()?;
- /// match device.set_unencrypted_volume_mode("123456", VolumeMode::ReadWrite) {
+ /// let mut device = nitrokey::Storage::connect()?;
+ /// match device.set_unencrypted_volume_mode("12345678", VolumeMode::ReadWrite) {
/// Ok(()) => println!("Set the unencrypted volume to read-write mode."),
- /// Err(err) => println!("Could not set the unencrypted volume to read-write mode: {}", err),
+ /// Err(err) => eprintln!("Could not set the unencrypted volume to read-write mode: {}", err),
/// };
/// # Ok(())
/// # }
@@ -1159,7 +1160,7 @@ impl Storage {
/// [`InvalidString`]: enum.LibraryError.html#variant.InvalidString
/// [`WrongPassword`]: enum.CommandError.html#variant.WrongPassword
pub fn set_unencrypted_volume_mode(
- &self,
+ &mut self,
admin_pin: &str,
mode: VolumeMode,
) -> Result<(), Error> {
@@ -1175,6 +1176,51 @@ impl Storage {
get_command_result(result)
}
+ /// Sets the access mode of the encrypted volume.
+ ///
+ /// This command will reconnect the encrypted volume so buffers should be flushed before
+ /// calling it. It is only available in firmware version 0.49.
+ ///
+ /// # Errors
+ ///
+ /// - [`InvalidString`][] if the provided password contains a null byte
+ /// - [`WrongPassword`][] if the provided admin password is wrong
+ ///
+ /// # Example
+ ///
+ /// ```no_run
+ /// # use nitrokey::Error;
+ /// use nitrokey::VolumeMode;
+ ///
+ /// # fn try_main() -> Result<(), Error> {
+ /// let mut device = nitrokey::Storage::connect()?;
+ /// match device.set_encrypted_volume_mode("12345678", VolumeMode::ReadWrite) {
+ /// Ok(()) => println!("Set the encrypted volume to read-write mode."),
+ /// Err(err) => eprintln!("Could not set the encrypted volume to read-write mode: {}", err),
+ /// };
+ /// # Ok(())
+ /// # }
+ /// ```
+ ///
+ /// [`InvalidString`]: enum.LibraryError.html#variant.InvalidString
+ /// [`WrongPassword`]: enum.CommandError.html#variant.WrongPassword
+ pub fn set_encrypted_volume_mode(
+ &mut self,
+ admin_pin: &str,
+ mode: VolumeMode,
+ ) -> Result<(), Error> {
+ let admin_pin = get_cstring(admin_pin)?;
+ let result = match mode {
+ VolumeMode::ReadOnly => unsafe {
+ nitrokey_sys::NK_set_encrypted_read_only(admin_pin.as_ptr())
+ },
+ VolumeMode::ReadWrite => unsafe {
+ nitrokey_sys::NK_set_encrypted_read_write(admin_pin.as_ptr())
+ },
+ };
+ get_command_result(result)
+ }
+
/// Returns the status of the connected storage device.
///
/// # Example
@@ -1190,7 +1236,7 @@ impl Storage {
/// Ok(status) => {
/// println!("SD card ID: {:#x}", status.serial_number_sd_card);
/// },
- /// Err(err) => println!("Could not get Storage status: {}", err),
+ /// Err(err) => eprintln!("Could not get Storage status: {}", err),
/// };
/// # Ok(())
/// # }
@@ -1234,7 +1280,7 @@ impl Storage {
/// println!("SD card ID: {:#x}", data.sd_card.serial_number);
/// println!("SD card size: {} GB", data.sd_card.size);
/// },
- /// Err(err) => println!("Could not get Storage production info: {}", err),
+ /// Err(err) => eprintln!("Could not get Storage production info: {}", err),
/// };
/// # Ok(())
/// # }
@@ -1276,10 +1322,10 @@ impl Storage {
/// # use nitrokey::Error;
///
/// # fn try_main() -> Result<(), Error> {
- /// let device = nitrokey::Storage::connect()?;
+ /// let mut device = nitrokey::Storage::connect()?;
/// match device.clear_new_sd_card_warning("12345678") {
/// Ok(()) => println!("Cleared the new SD card warning."),
- /// Err(err) => println!("Could not set the clear the new SD card warning: {}", err),
+ /// Err(err) => eprintln!("Could not set the clear the new SD card warning: {}", err),
/// };
/// # Ok(())
/// # }
@@ -1287,7 +1333,7 @@ impl Storage {
///
/// [`InvalidString`]: enum.LibraryError.html#variant.InvalidString
/// [`WrongPassword`]: enum.CommandError.html#variant.WrongPassword
- pub fn clear_new_sd_card_warning(&self, admin_pin: &str) -> Result<(), Error> {
+ pub fn clear_new_sd_card_warning(&mut self, admin_pin: &str) -> Result<(), Error> {
let admin_pin = get_cstring(admin_pin)?;
get_command_result(unsafe {
nitrokey_sys::NK_clear_new_sd_card_warning(admin_pin.as_ptr())
@@ -1295,7 +1341,7 @@ impl Storage {
}
/// Blinks the red and green LED alternatively and infinitely until the device is reconnected.
- pub fn wink(&self) -> Result<(), Error> {
+ pub fn wink(&mut self) -> Result<(), Error> {
get_command_result(unsafe { nitrokey_sys::NK_wink() })
}
@@ -1315,7 +1361,7 @@ impl Storage {
///
/// [`InvalidString`]: enum.LibraryError.html#variant.InvalidString
/// [`WrongPassword`]: enum.CommandError.html#variant.WrongPassword
- pub fn export_firmware(&self, admin_pin: &str) -> Result<(), Error> {
+ pub fn export_firmware(&mut self, admin_pin: &str) -> Result<(), Error> {
let admin_pin_string = get_cstring(admin_pin)?;
get_command_result(unsafe { nitrokey_sys::NK_export_firmware(admin_pin_string.as_ptr()) })
}
diff --git a/nitrokey/src/lib.rs b/nitrokey/src/lib.rs
index f2d524e..c35829c 100644
--- a/nitrokey/src/lib.rs
+++ b/nitrokey/src/lib.rs
@@ -47,13 +47,13 @@
//! let device = nitrokey::connect()?;
//! let slot_data = OtpSlotData::new(1, "test", "01234567890123456689", OtpMode::SixDigits);
//! match device.authenticate_admin("12345678") {
-//! Ok(admin) => {
+//! Ok(mut admin) => {
//! match admin.write_hotp_slot(slot_data, 0) {
//! Ok(()) => println!("Successfully wrote slot."),
-//! Err(err) => println!("Could not write slot: {}", err),
+//! Err(err) => eprintln!("Could not write slot: {}", err),
//! }
//! },
-//! Err((_, err)) => println!("Could not authenticate as admin: {}", err),
+//! Err((_, err)) => eprintln!("Could not authenticate as admin: {}", err),
//! }
//! # Ok(())
//! # }
@@ -66,10 +66,10 @@
//! # use nitrokey::Error;
//!
//! # fn try_main() -> Result<(), Error> {
-//! let device = nitrokey::connect()?;
+//! let mut device = nitrokey::connect()?;
//! match device.get_hotp_code(1) {
//! Ok(code) => println!("Generated HOTP code: {}", code),
-//! Err(err) => println!("Could not generate HOTP code: {}", err),
+//! Err(err) => eprintln!("Could not generate HOTP code: {}", err),
//! }
//! # Ok(())
//! # }
diff --git a/nitrokey/src/otp.rs b/nitrokey/src/otp.rs
index 6e0379b..ee142c7 100644
--- a/nitrokey/src/otp.rs
+++ b/nitrokey/src/otp.rs
@@ -38,13 +38,13 @@ pub trait ConfigureOtp {
/// let device = nitrokey::connect()?;
/// let slot_data = OtpSlotData::new(1, "test", "01234567890123456689", OtpMode::SixDigits);
/// match device.authenticate_admin("12345678") {
- /// Ok(admin) => {
+ /// Ok(mut admin) => {
/// match admin.write_hotp_slot(slot_data, 0) {
/// Ok(()) => println!("Successfully wrote slot."),
- /// Err(err) => println!("Could not write slot: {}", err),
+ /// Err(err) => eprintln!("Could not write slot: {}", err),
/// }
/// },
- /// Err((_, err)) => println!("Could not authenticate as admin: {}", err),
+ /// Err((_, err)) => eprintln!("Could not authenticate as admin: {}", err),
/// }
/// # Ok(())
/// # }
@@ -53,7 +53,7 @@ pub trait ConfigureOtp {
/// [`InvalidSlot`]: enum.LibraryError.html#variant.InvalidSlot
/// [`InvalidString`]: enum.LibraryError.html#variant.InvalidString
/// [`NoName`]: enum.CommandError.html#variant.NoName
- fn write_hotp_slot(&self, data: OtpSlotData, counter: u64) -> Result<(), Error>;
+ fn write_hotp_slot(&mut self, data: OtpSlotData, counter: u64) -> Result<(), Error>;
/// Configure a TOTP slot with the given data and set the TOTP time window to the given value
/// (default 30).
@@ -74,13 +74,13 @@ pub trait ConfigureOtp {
/// let device = nitrokey::connect()?;
/// let slot_data = OtpSlotData::new(1, "test", "01234567890123456689", OtpMode::EightDigits);
/// match device.authenticate_admin("12345678") {
- /// Ok(admin) => {
+ /// Ok(mut admin) => {
/// match admin.write_totp_slot(slot_data, 30) {
/// Ok(()) => println!("Successfully wrote slot."),
- /// Err(err) => println!("Could not write slot: {}", err),
+ /// Err(err) => eprintln!("Could not write slot: {}", err),
/// }
/// },
- /// Err((_, err)) => println!("Could not authenticate as admin: {}", err),
+ /// Err((_, err)) => eprintln!("Could not authenticate as admin: {}", err),
/// }
/// # Ok(())
/// # }
@@ -89,7 +89,7 @@ pub trait ConfigureOtp {
/// [`InvalidSlot`]: enum.LibraryError.html#variant.InvalidSlot
/// [`InvalidString`]: enum.LibraryError.html#variant.InvalidString
/// [`NoName`]: enum.CommandError.html#variant.NoName
- fn write_totp_slot(&self, data: OtpSlotData, time_window: u16) -> Result<(), Error>;
+ fn write_totp_slot(&mut self, data: OtpSlotData, time_window: u16) -> Result<(), Error>;
/// Erases an HOTP slot.
///
@@ -106,20 +106,20 @@ pub trait ConfigureOtp {
/// # fn try_main() -> Result<(), Error> {
/// let device = nitrokey::connect()?;
/// match device.authenticate_admin("12345678") {
- /// Ok(admin) => {
+ /// Ok(mut admin) => {
/// match admin.erase_hotp_slot(1) {
/// Ok(()) => println!("Successfully erased slot."),
- /// Err(err) => println!("Could not erase slot: {}", err),
+ /// Err(err) => eprintln!("Could not erase slot: {}", err),
/// }
/// },
- /// Err((_, err)) => println!("Could not authenticate as admin: {}", err),
+ /// Err((_, err)) => eprintln!("Could not authenticate as admin: {}", err),
/// }
/// # Ok(())
/// # }
/// ```
///
/// [`InvalidSlot`]: enum.LibraryError.html#variant.InvalidSlot
- fn erase_hotp_slot(&self, slot: u8) -> Result<(), Error>;
+ fn erase_hotp_slot(&mut self, slot: u8) -> Result<(), Error>;
/// Erases a TOTP slot.
///
@@ -136,20 +136,20 @@ pub trait ConfigureOtp {
/// # fn try_main() -> Result<(), Error> {
/// let device = nitrokey::connect()?;
/// match device.authenticate_admin("12345678") {
- /// Ok(admin) => {
+ /// Ok(mut admin) => {
/// match admin.erase_totp_slot(1) {
/// Ok(()) => println!("Successfully erased slot."),
- /// Err(err) => println!("Could not erase slot: {}", err),
+ /// Err(err) => eprintln!("Could not erase slot: {}", err),
/// }
/// },
- /// Err((_, err)) => println!("Could not authenticate as admin: {}", err),
+ /// Err((_, err)) => eprintln!("Could not authenticate as admin: {}", err),
/// }
/// # Ok(())
/// # }
/// ```
///
/// [`InvalidSlot`]: enum.LibraryError.html#variant.InvalidSlot
- fn erase_totp_slot(&self, slot: u8) -> Result<(), Error>;
+ fn erase_totp_slot(&mut self, slot: u8) -> Result<(), Error>;
}
/// Provides methods to generate OTP codes and to query OTP slots on a Nitrokey
@@ -171,11 +171,11 @@ pub trait GenerateOtp {
/// # use nitrokey::Error;
///
/// # fn try_main() -> Result<(), Error> {
- /// let device = nitrokey::connect()?;
+ /// let mut device = nitrokey::connect()?;
/// let time = time::SystemTime::now().duration_since(time::UNIX_EPOCH);
/// match time {
/// Ok(time) => device.set_time(time.as_secs(), false)?,
- /// Err(_) => println!("The system time is before the Unix epoch!"),
+ /// Err(_) => eprintln!("The system time is before the Unix epoch!"),
/// }
/// # Ok(())
/// # }
@@ -187,7 +187,7 @@ pub trait GenerateOtp {
///
/// [`get_totp_code`]: #method.get_totp_code
/// [`Timestamp`]: enum.CommandError.html#variant.Timestamp
- fn set_time(&self, time: u64, force: bool) -> Result<(), Error> {
+ fn set_time(&mut self, time: u64, force: bool) -> Result<(), Error> {
let result = if force {
unsafe { nitrokey_sys::NK_totp_set_time(time) }
} else {
@@ -212,8 +212,8 @@ pub trait GenerateOtp {
/// let device = nitrokey::connect()?;
/// match device.get_hotp_slot_name(1) {
/// Ok(name) => println!("HOTP slot 1: {}", name),
- /// Err(Error::CommandError(CommandError::SlotNotProgrammed)) => println!("HOTP slot 1 not programmed"),
- /// Err(err) => println!("Could not get slot name: {}", err),
+ /// Err(Error::CommandError(CommandError::SlotNotProgrammed)) => eprintln!("HOTP slot 1 not programmed"),
+ /// Err(err) => eprintln!("Could not get slot name: {}", err),
/// };
/// # Ok(())
/// # }
@@ -241,8 +241,8 @@ pub trait GenerateOtp {
/// let device = nitrokey::connect()?;
/// match device.get_totp_slot_name(1) {
/// Ok(name) => println!("TOTP slot 1: {}", name),
- /// Err(Error::CommandError(CommandError::SlotNotProgrammed)) => println!("TOTP slot 1 not programmed"),
- /// Err(err) => println!("Could not get slot name: {}", err),
+ /// Err(Error::CommandError(CommandError::SlotNotProgrammed)) => eprintln!("TOTP slot 1 not programmed"),
+ /// Err(err) => eprintln!("Could not get slot name: {}", err),
/// };
/// # Ok(())
/// # }
@@ -270,7 +270,7 @@ pub trait GenerateOtp {
/// # use nitrokey::Error;
///
/// # fn try_main() -> Result<(), Error> {
- /// let device = nitrokey::connect()?;
+ /// let mut device = nitrokey::connect()?;
/// let code = device.get_hotp_code(1)?;
/// println!("Generated HOTP code on slot 1: {}", code);
/// # Ok(())
@@ -281,7 +281,7 @@ pub trait GenerateOtp {
/// [`InvalidSlot`]: enum.LibraryError.html#variant.InvalidSlot
/// [`NotAuthorized`]: enum.CommandError.html#variant.NotAuthorized
/// [`SlotNotProgrammed`]: enum.CommandError.html#variant.SlotNotProgrammed
- fn get_hotp_code(&self, slot: u8) -> Result<String, Error> {
+ fn get_hotp_code(&mut self, slot: u8) -> Result<String, Error> {
result_from_string(unsafe { nitrokey_sys::NK_get_hotp_code(slot) })
}
@@ -305,7 +305,7 @@ pub trait GenerateOtp {
/// # use nitrokey::Error;
///
/// # fn try_main() -> Result<(), Error> {
- /// let device = nitrokey::connect()?;
+ /// let mut device = nitrokey::connect()?;
/// let time = time::SystemTime::now().duration_since(time::UNIX_EPOCH);
/// match time {
/// Ok(time) => {
@@ -313,7 +313,7 @@ pub trait GenerateOtp {
/// let code = device.get_totp_code(1)?;
/// println!("Generated TOTP code on slot 1: {}", code);
/// },
- /// Err(_) => println!("Timestamps before 1970-01-01 are not supported!"),
+ /// Err(_) => eprintln!("Timestamps before 1970-01-01 are not supported!"),
/// }
/// # Ok(())
/// # }
diff --git a/nitrokey/src/pws.rs b/nitrokey/src/pws.rs
index fcf057b..371de6e 100644
--- a/nitrokey/src/pws.rs
+++ b/nitrokey/src/pws.rs
@@ -43,9 +43,10 @@ pub const SLOT_COUNT: u8 = 16;
/// }
///
/// # fn try_main() -> Result<(), Error> {
-/// let device = nitrokey::connect()?;
+/// let mut device = nitrokey::connect()?;
/// let pws = device.get_password_safe("123456")?;
/// use_password_safe(&pws);
+/// drop(pws);
/// device.lock()?;
/// # Ok(())
/// # }
@@ -97,14 +98,14 @@ pub trait GetPasswordSafe {
/// fn use_password_safe(pws: &PasswordSafe) {}
///
/// # fn try_main() -> Result<(), Error> {
- /// let device = nitrokey::connect()?;
+ /// let mut device = nitrokey::connect()?;
/// match device.get_password_safe("123456") {
/// Ok(pws) => {
/// use_password_safe(&pws);
- /// device.lock()?;
/// },
- /// Err(err) => println!("Could not open the password safe: {}", err),
+ /// Err(err) => eprintln!("Could not open the password safe: {}", err),
/// };
+ /// device.lock()?;
/// # Ok(())
/// # }
/// ```
@@ -116,7 +117,7 @@ pub trait GetPasswordSafe {
/// [`InvalidString`]: enum.LibraryError.html#variant.InvalidString
/// [`Unknown`]: enum.CommandError.html#variant.Unknown
/// [`WrongPassword`]: enum.CommandError.html#variant.WrongPassword
- fn get_password_safe(&self, user_pin: &str) -> Result<PasswordSafe<'_>, Error>;
+ fn get_password_safe(&mut self, user_pin: &str) -> Result<PasswordSafe<'_>, Error>;
}
fn get_password_safe<'a>(
@@ -148,7 +149,7 @@ impl<'a> PasswordSafe<'a> {
/// # use nitrokey::Error;
///
/// # fn try_main() -> Result<(), Error> {
- /// let device = nitrokey::connect()?;
+ /// let mut device = nitrokey::connect()?;
/// let pws = device.get_password_safe("123456")?;
/// pws.get_slot_status()?.iter().enumerate().for_each(|(slot, programmed)| {
/// let status = match *programmed {
@@ -193,7 +194,7 @@ impl<'a> PasswordSafe<'a> {
/// # use nitrokey::Error;
///
/// # fn try_main() -> Result<(), Error> {
- /// let device = nitrokey::connect()?;
+ /// let mut device = nitrokey::connect()?;
/// match device.get_password_safe("123456") {
/// Ok(pws) => {
/// let name = pws.get_slot_name(0)?;
@@ -201,7 +202,7 @@ impl<'a> PasswordSafe<'a> {
/// let password = pws.get_slot_login(0)?;
/// println!("Credentials for {}: login {}, password {}", name, login, password);
/// },
- /// Err(err) => println!("Could not open the password safe: {}", err),
+ /// Err(err) => eprintln!("Could not open the password safe: {}", err),
/// };
/// # Ok(())
/// # }
@@ -230,7 +231,7 @@ impl<'a> PasswordSafe<'a> {
/// # use nitrokey::Error;
///
/// # fn try_main() -> Result<(), Error> {
- /// let device = nitrokey::connect()?;
+ /// let mut device = nitrokey::connect()?;
/// let pws = device.get_password_safe("123456")?;
/// let name = pws.get_slot_name(0)?;
/// let login = pws.get_slot_login(0)?;
@@ -263,7 +264,7 @@ impl<'a> PasswordSafe<'a> {
/// # use nitrokey::Error;
///
/// # fn try_main() -> Result<(), Error> {
- /// let device = nitrokey::connect()?;
+ /// let mut device = nitrokey::connect()?;
/// let pws = device.get_password_safe("123456")?;
/// let name = pws.get_slot_name(0)?;
/// let login = pws.get_slot_login(0)?;
@@ -294,7 +295,7 @@ impl<'a> PasswordSafe<'a> {
/// # use nitrokey::Error;
///
/// # fn try_main() -> Result<(), Error> {
- /// let device = nitrokey::connect()?;
+ /// let mut device = nitrokey::connect()?;
/// let pws = device.get_password_safe("123456")?;
/// let name = pws.get_slot_name(0)?;
/// let login = pws.get_slot_login(0)?;
@@ -307,7 +308,7 @@ impl<'a> PasswordSafe<'a> {
/// [`InvalidSlot`]: enum.LibraryError.html#variant.InvalidSlot
/// [`InvalidString`]: enum.LibraryError.html#variant.InvalidString
pub fn write_slot(
- &self,
+ &mut self,
slot: u8,
name: &str,
login: &str,
@@ -340,18 +341,18 @@ impl<'a> PasswordSafe<'a> {
/// # use nitrokey::Error;
///
/// # fn try_main() -> Result<(), Error> {
- /// let device = nitrokey::connect()?;
- /// let pws = device.get_password_safe("123456")?;
+ /// let mut device = nitrokey::connect()?;
+ /// let mut pws = device.get_password_safe("123456")?;
/// match pws.erase_slot(0) {
/// Ok(()) => println!("Erased slot 0."),
- /// Err(err) => println!("Could not erase slot 0: {}", err),
+ /// Err(err) => eprintln!("Could not erase slot 0: {}", err),
/// };
/// # Ok(())
/// # }
/// ```
///
/// [`InvalidSlot`]: enum.LibraryError.html#variant.InvalidSlot
- pub fn erase_slot(&self, slot: u8) -> Result<(), Error> {
+ pub fn erase_slot(&mut self, slot: u8) -> Result<(), Error> {
get_command_result(unsafe { nitrokey_sys::NK_erase_password_safe_slot(slot) })
}
}
@@ -364,19 +365,19 @@ impl<'a> Drop for PasswordSafe<'a> {
}
impl GetPasswordSafe for Pro {
- fn get_password_safe(&self, user_pin: &str) -> Result<PasswordSafe<'_>, Error> {
+ fn get_password_safe(&mut self, user_pin: &str) -> Result<PasswordSafe<'_>, Error> {
get_password_safe(self, user_pin)
}
}
impl GetPasswordSafe for Storage {
- fn get_password_safe(&self, user_pin: &str) -> Result<PasswordSafe<'_>, Error> {
+ fn get_password_safe(&mut self, user_pin: &str) -> Result<PasswordSafe<'_>, Error> {
get_password_safe(self, user_pin)
}
}
impl GetPasswordSafe for DeviceWrapper {
- fn get_password_safe(&self, user_pin: &str) -> Result<PasswordSafe<'_>, Error> {
+ fn get_password_safe(&mut self, user_pin: &str) -> Result<PasswordSafe<'_>, Error> {
get_password_safe(self, user_pin)
}
}
diff --git a/nitrokey/src/util.rs b/nitrokey/src/util.rs
index b7e8cd3..fdb73c3 100644
--- a/nitrokey/src/util.rs
+++ b/nitrokey/src/util.rs
@@ -53,6 +53,10 @@ pub fn result_from_string(ptr: *const c_char) -> Result<String, Error> {
}
}
+pub fn result_or_error<T>(value: T) -> Result<T, Error> {
+ get_last_result().and(Ok(value))
+}
+
pub fn get_command_result(value: c_int) -> Result<(), Error> {
if value == 0 {
Ok(())
diff --git a/nitrokey/tests/device.rs b/nitrokey/tests/device.rs
index c790049..5c52024 100644
--- a/nitrokey/tests/device.rs
+++ b/nitrokey/tests/device.rs
@@ -10,11 +10,10 @@ use std::{thread, time};
use nitrokey::{
Authenticate, CommandError, CommunicationError, Config, ConfigureOtp, Device, Error,
GenerateOtp, GetPasswordSafe, LibraryError, OtpMode, OtpSlotData, Storage, VolumeMode,
+ DEFAULT_ADMIN_PIN, DEFAULT_USER_PIN,
};
use nitrokey_test::test as test_device;
-use crate::util::{ADMIN_PASSWORD, USER_PASSWORD};
-
static ADMIN_NEW_PASSWORD: &str = "1234567890";
static UPDATE_PIN: &str = "12345678";
static UPDATE_NEW_PIN: &str = "87654321";
@@ -55,9 +54,9 @@ fn connect_pro(device: Pro) {
assert_eq!(device.get_model(), nitrokey::Model::Pro);
drop(device);
- assert!(nitrokey::connect().is_ok());
- assert!(nitrokey::connect_model(nitrokey::Model::Pro).is_ok());
- assert!(nitrokey::Pro::connect().is_ok());
+ assert_any_ok!(nitrokey::connect());
+ assert_any_ok!(nitrokey::connect_model(nitrokey::Model::Pro));
+ assert_any_ok!(nitrokey::Pro::connect());
}
#[test_device]
@@ -65,9 +64,9 @@ fn connect_storage(device: Storage) {
assert_eq!(device.get_model(), nitrokey::Model::Storage);
drop(device);
- assert!(nitrokey::connect().is_ok());
- assert!(nitrokey::connect_model(nitrokey::Model::Storage).is_ok());
- assert!(nitrokey::Storage::connect().is_ok());
+ assert_any_ok!(nitrokey::connect());
+ assert_any_ok!(nitrokey::connect_model(nitrokey::Model::Storage));
+ assert_any_ok!(nitrokey::Storage::connect());
}
fn assert_empty_serial_number() {
@@ -87,36 +86,34 @@ fn disconnect(device: DeviceWrapper) {
#[test_device]
fn get_serial_number(device: DeviceWrapper) {
- let result = device.get_serial_number();
- assert!(result.is_ok());
- let serial_number = result.unwrap();
+ let serial_number = unwrap_ok!(device.get_serial_number());
assert!(serial_number.is_ascii());
assert!(serial_number.chars().all(|c| c.is_ascii_hexdigit()));
}
#[test_device]
fn get_firmware_version(device: Pro) {
- assert_eq!(0, device.get_major_firmware_version());
- let minor = device.get_minor_firmware_version();
- assert!(minor > 0);
+ let version = unwrap_ok!(device.get_firmware_version());
+ assert_eq!(0, version.major);
+ assert!(version.minor > 0);
}
fn admin_retry<T: Authenticate + Device>(device: T, suffix: &str, count: u8) -> T {
- let result = device.authenticate_admin(&(ADMIN_PASSWORD.to_owned() + suffix));
+ let result = device.authenticate_admin(&(DEFAULT_ADMIN_PIN.to_owned() + suffix));
let device = match result {
Ok(admin) => admin.device(),
Err((device, _)) => device,
};
- assert_eq!(count, device.get_admin_retry_count());
+ assert_ok!(count, device.get_admin_retry_count());
return device;
}
fn user_retry<T: Authenticate + Device>(device: T, suffix: &str, count: u8) -> T {
- let result = device.authenticate_user(&(USER_PASSWORD.to_owned() + suffix));
+ let result = device.authenticate_user(&(DEFAULT_USER_PIN.to_owned() + suffix));
let device = match result {
Ok(admin) => admin.device(),
Err((device, _)) => device,
};
- assert_eq!(count, device.get_user_retry_count());
+ assert_ok!(count, device.get_user_retry_count());
return device;
}
@@ -135,7 +132,7 @@ fn get_retry_count(device: DeviceWrapper) {
#[test_device]
fn config(device: DeviceWrapper) {
- let admin = device.authenticate_admin(ADMIN_PASSWORD).unwrap();
+ let mut admin = unwrap_ok!(device.authenticate_admin(DEFAULT_ADMIN_PIN));
let config = Config::new(None, None, None, true);
assert_ok!((), admin.write_config(config));
@@ -155,53 +152,67 @@ fn config(device: DeviceWrapper) {
#[test_device]
fn change_user_pin(device: DeviceWrapper) {
- let device = device.authenticate_user(USER_PASSWORD).unwrap().device();
+ let device = device.authenticate_user(DEFAULT_USER_PIN).unwrap().device();
let device = device.authenticate_user(USER_NEW_PASSWORD).unwrap_err().0;
- assert_ok!((), device.change_user_pin(USER_PASSWORD, USER_NEW_PASSWORD));
+ let mut device = device;
+ assert_ok!(
+ (),
+ device.change_user_pin(DEFAULT_USER_PIN, USER_NEW_PASSWORD)
+ );
- let device = device.authenticate_user(USER_PASSWORD).unwrap_err().0;
+ let device = device.authenticate_user(DEFAULT_USER_PIN).unwrap_err().0;
let device = device
.authenticate_user(USER_NEW_PASSWORD)
.unwrap()
.device();
- let result = device.change_user_pin(USER_PASSWORD, USER_PASSWORD);
+ let mut device = device;
+ let result = device.change_user_pin(DEFAULT_USER_PIN, DEFAULT_USER_PIN);
assert_cmd_err!(CommandError::WrongPassword, result);
- assert_ok!((), device.change_user_pin(USER_NEW_PASSWORD, USER_PASSWORD));
+ assert_ok!(
+ (),
+ device.change_user_pin(USER_NEW_PASSWORD, DEFAULT_USER_PIN)
+ );
- let device = device.authenticate_user(USER_PASSWORD).unwrap().device();
+ let device = device.authenticate_user(DEFAULT_USER_PIN).unwrap().device();
assert!(device.authenticate_user(USER_NEW_PASSWORD).is_err());
}
#[test_device]
fn change_admin_pin(device: DeviceWrapper) {
- let device = device.authenticate_admin(ADMIN_PASSWORD).unwrap().device();
- let device = device.authenticate_admin(ADMIN_NEW_PASSWORD).unwrap_err().0;
+ let device = device
+ .authenticate_admin(DEFAULT_ADMIN_PIN)
+ .unwrap()
+ .device();
+ let mut device = device.authenticate_admin(ADMIN_NEW_PASSWORD).unwrap_err().0;
assert_ok!(
(),
- device.change_admin_pin(ADMIN_PASSWORD, ADMIN_NEW_PASSWORD)
+ device.change_admin_pin(DEFAULT_ADMIN_PIN, ADMIN_NEW_PASSWORD)
);
- let device = device.authenticate_admin(ADMIN_PASSWORD).unwrap_err().0;
- let device = device
+ let device = device.authenticate_admin(DEFAULT_ADMIN_PIN).unwrap_err().0;
+ let mut device = device
.authenticate_admin(ADMIN_NEW_PASSWORD)
.unwrap()
.device();
assert_cmd_err!(
CommandError::WrongPassword,
- device.change_admin_pin(ADMIN_PASSWORD, ADMIN_PASSWORD)
+ device.change_admin_pin(DEFAULT_ADMIN_PIN, DEFAULT_ADMIN_PIN)
);
assert_ok!(
(),
- device.change_admin_pin(ADMIN_NEW_PASSWORD, ADMIN_PASSWORD)
+ device.change_admin_pin(ADMIN_NEW_PASSWORD, DEFAULT_ADMIN_PIN)
);
- let device = device.authenticate_admin(ADMIN_PASSWORD).unwrap().device();
+ let device = device
+ .authenticate_admin(DEFAULT_ADMIN_PIN)
+ .unwrap()
+ .device();
device.authenticate_admin(ADMIN_NEW_PASSWORD).unwrap_err();
}
@@ -222,63 +233,85 @@ where
#[test_device]
fn unlock_user_pin(device: DeviceWrapper) {
- let device = device.authenticate_user(USER_PASSWORD).unwrap().device();
- assert_ok!((), device.unlock_user_pin(ADMIN_PASSWORD, USER_PASSWORD));
+ let mut device = device.authenticate_user(DEFAULT_USER_PIN).unwrap().device();
+ assert_ok!(
+ (),
+ device.unlock_user_pin(DEFAULT_ADMIN_PIN, DEFAULT_USER_PIN)
+ );
assert_cmd_err!(
CommandError::WrongPassword,
- device.unlock_user_pin(USER_PASSWORD, USER_PASSWORD)
+ device.unlock_user_pin(DEFAULT_USER_PIN, DEFAULT_USER_PIN)
);
// block user PIN
- let wrong_password = USER_PASSWORD.to_owned() + "foo";
+ let wrong_password = DEFAULT_USER_PIN.to_owned() + "foo";
let device = require_failed_user_login(device, &wrong_password, CommandError::WrongPassword);
let device = require_failed_user_login(device, &wrong_password, CommandError::WrongPassword);
let device = require_failed_user_login(device, &wrong_password, CommandError::WrongPassword);
- let device = require_failed_user_login(device, USER_PASSWORD, CommandError::WrongPassword);
+ let mut device =
+ require_failed_user_login(device, DEFAULT_USER_PIN, CommandError::WrongPassword);
// unblock with current PIN
assert_cmd_err!(
CommandError::WrongPassword,
- device.unlock_user_pin(USER_PASSWORD, USER_PASSWORD)
+ device.unlock_user_pin(DEFAULT_USER_PIN, DEFAULT_USER_PIN)
);
- assert_ok!((), device.unlock_user_pin(ADMIN_PASSWORD, USER_PASSWORD));
- let device = device.authenticate_user(USER_PASSWORD).unwrap().device();
+ assert_ok!(
+ (),
+ device.unlock_user_pin(DEFAULT_ADMIN_PIN, DEFAULT_USER_PIN)
+ );
+ let device = device.authenticate_user(DEFAULT_USER_PIN).unwrap().device();
// block user PIN
let device = require_failed_user_login(device, &wrong_password, CommandError::WrongPassword);
let device = require_failed_user_login(device, &wrong_password, CommandError::WrongPassword);
let device = require_failed_user_login(device, &wrong_password, CommandError::WrongPassword);
- let device = require_failed_user_login(device, USER_PASSWORD, CommandError::WrongPassword);
+ let mut device =
+ require_failed_user_login(device, DEFAULT_USER_PIN, CommandError::WrongPassword);
// unblock with new PIN
assert_cmd_err!(
CommandError::WrongPassword,
- device.unlock_user_pin(USER_PASSWORD, USER_PASSWORD)
+ device.unlock_user_pin(DEFAULT_USER_PIN, DEFAULT_USER_PIN)
);
assert_ok!(
(),
- device.unlock_user_pin(ADMIN_PASSWORD, USER_NEW_PASSWORD)
+ device.unlock_user_pin(DEFAULT_ADMIN_PIN, USER_NEW_PASSWORD)
);
// reset user PIN
- assert_ok!((), device.change_user_pin(USER_NEW_PASSWORD, USER_PASSWORD));
+ assert_ok!(
+ (),
+ device.change_user_pin(USER_NEW_PASSWORD, DEFAULT_USER_PIN)
+ );
+}
+
+fn assert_utf8_err_or_ne(left: &str, right: Result<String, Error>) {
+ match right {
+ Ok(s) => assert_ne!(left.to_string(), s),
+ Err(Error::Utf8Error(_)) => {}
+ Err(err) => panic!("Expected Utf8Error, got {}!", err),
+ }
}
#[test_device]
fn factory_reset(device: DeviceWrapper) {
- let admin = device.authenticate_admin(ADMIN_PASSWORD).unwrap();
+ let mut admin = unwrap_ok!(device.authenticate_admin(DEFAULT_ADMIN_PIN));
let otp_data = OtpSlotData::new(1, "test", "0123468790", OtpMode::SixDigits);
assert_ok!((), admin.write_totp_slot(otp_data, 30));
- let device = admin.device();
- let pws = device.get_password_safe(USER_PASSWORD).unwrap();
+ let mut device = admin.device();
+ let mut pws = unwrap_ok!(device.get_password_safe(DEFAULT_USER_PIN));
assert_ok!((), pws.write_slot(0, "test", "testlogin", "testpw"));
drop(pws);
- assert_ok!((), device.change_user_pin(USER_PASSWORD, USER_NEW_PASSWORD));
assert_ok!(
(),
- device.change_admin_pin(ADMIN_PASSWORD, ADMIN_NEW_PASSWORD)
+ device.change_user_pin(DEFAULT_USER_PIN, USER_NEW_PASSWORD)
+ );
+ assert_ok!(
+ (),
+ device.change_admin_pin(DEFAULT_ADMIN_PIN, ADMIN_NEW_PASSWORD)
);
assert_cmd_err!(
@@ -287,46 +320,55 @@ fn factory_reset(device: DeviceWrapper) {
);
assert_cmd_err!(
CommandError::WrongPassword,
- device.factory_reset(ADMIN_PASSWORD)
+ device.factory_reset(DEFAULT_ADMIN_PIN)
);
assert_ok!((), device.factory_reset(ADMIN_NEW_PASSWORD));
- let device = device.authenticate_admin(ADMIN_PASSWORD).unwrap().device();
+ let device = device
+ .authenticate_admin(DEFAULT_ADMIN_PIN)
+ .unwrap()
+ .device();
- let user = device.authenticate_user(USER_PASSWORD).unwrap();
+ let user = unwrap_ok!(device.authenticate_user(DEFAULT_USER_PIN));
assert_cmd_err!(CommandError::SlotNotProgrammed, user.get_totp_slot_name(1));
- let device = user.device();
- let pws = device.get_password_safe(USER_PASSWORD).unwrap();
- assert_ne!("test".to_string(), pws.get_slot_name(0).unwrap());
- assert_ne!("testlogin".to_string(), pws.get_slot_login(0).unwrap());
- assert_ne!("testpw".to_string(), pws.get_slot_password(0).unwrap());
+ let mut device = user.device();
+ let pws = unwrap_ok!(device.get_password_safe(DEFAULT_USER_PIN));
+ assert_utf8_err_or_ne("test", pws.get_slot_name(0));
+ assert_utf8_err_or_ne("testlogin", pws.get_slot_login(0));
+ assert_utf8_err_or_ne("testpw", pws.get_slot_password(0));
+ drop(pws);
- assert_ok!((), device.build_aes_key(ADMIN_PASSWORD));
+ assert_ok!((), device.build_aes_key(DEFAULT_ADMIN_PIN));
}
#[test_device]
fn build_aes_key(device: DeviceWrapper) {
- let pws = device.get_password_safe(USER_PASSWORD).unwrap();
+ let mut device = device;
+ let mut pws = unwrap_ok!(device.get_password_safe(DEFAULT_USER_PIN));
assert_ok!((), pws.write_slot(0, "test", "testlogin", "testpw"));
drop(pws);
assert_cmd_err!(
CommandError::WrongPassword,
- device.build_aes_key(USER_PASSWORD)
+ device.build_aes_key(DEFAULT_USER_PIN)
);
- assert_ok!((), device.build_aes_key(ADMIN_PASSWORD));
+ assert_ok!((), device.build_aes_key(DEFAULT_ADMIN_PIN));
- let device = device.authenticate_admin(ADMIN_PASSWORD).unwrap().device();
+ let mut device = device
+ .authenticate_admin(DEFAULT_ADMIN_PIN)
+ .unwrap()
+ .device();
- let pws = device.get_password_safe(USER_PASSWORD).unwrap();
- assert_ne!("test".to_string(), pws.get_slot_name(0).unwrap());
- assert_ne!("testlogin".to_string(), pws.get_slot_login(0).unwrap());
- assert_ne!("testpw".to_string(), pws.get_slot_password(0).unwrap());
+ let pws = unwrap_ok!(device.get_password_safe(DEFAULT_USER_PIN));
+ assert_utf8_err_or_ne("test", pws.get_slot_name(0));
+ assert_utf8_err_or_ne("testlogin", pws.get_slot_login(0));
+ assert_utf8_err_or_ne("testpw", pws.get_slot_password(0));
}
#[test_device]
fn change_update_pin(device: Storage) {
+ let mut device = device;
assert_cmd_err!(
CommandError::WrongPassword,
device.change_update_pin(UPDATE_NEW_PIN, UPDATE_PIN)
@@ -337,6 +379,7 @@ fn change_update_pin(device: Storage) {
#[test_device]
fn encrypted_volume(device: Storage) {
+ let mut device = device;
assert_ok!((), device.lock());
assert_eq!(1, count_nitrokey_block_devices());
@@ -347,7 +390,7 @@ fn encrypted_volume(device: Storage) {
device.enable_encrypted_volume("123")
);
assert_eq!(1, count_nitrokey_block_devices());
- assert_ok!((), device.enable_encrypted_volume(USER_PASSWORD));
+ assert_ok!((), device.enable_encrypted_volume(DEFAULT_USER_PIN));
assert_eq!(2, count_nitrokey_block_devices());
assert_ok!((), device.disable_encrypted_volume());
assert_eq!(1, count_nitrokey_block_devices());
@@ -355,13 +398,14 @@ fn encrypted_volume(device: Storage) {
#[test_device]
fn hidden_volume(device: Storage) {
+ let mut device = device;
assert_ok!((), device.lock());
assert_eq!(1, count_nitrokey_block_devices());
assert_ok!((), device.disable_hidden_volume());
assert_eq!(1, count_nitrokey_block_devices());
- assert_ok!((), device.enable_encrypted_volume(USER_PASSWORD));
+ assert_ok!((), device.enable_encrypted_volume(DEFAULT_USER_PIN));
assert_eq!(2, count_nitrokey_block_devices());
// TODO: why this error code?
@@ -390,51 +434,85 @@ fn hidden_volume(device: Storage) {
#[test_device]
fn lock(device: Storage) {
- assert_ok!((), device.enable_encrypted_volume(USER_PASSWORD));
+ let mut device = device;
+ assert_ok!((), device.enable_encrypted_volume(DEFAULT_USER_PIN));
assert_ok!((), device.lock());
assert_eq!(1, count_nitrokey_block_devices());
}
#[test_device]
+fn set_encrypted_volume_mode(device: Storage) {
+ // This test case does not check the device status as the command only works with firmware
+ // version 0.49. For later versions, it does not do anything and always returns Ok(()).
+ let mut device = device;
+
+ assert_ok!(
+ (),
+ device.set_encrypted_volume_mode(DEFAULT_ADMIN_PIN, VolumeMode::ReadOnly)
+ );
+
+ // TODO: re-enable once the password is checked in the firmware
+ // assert_cmd_err!(
+ // CommandError::WrongPassword,
+ // device.set_encrypted_volume_mode(DEFAULT_USER_PIN, VolumeMode::ReadOnly)
+ // );
+
+ assert_ok!(
+ (),
+ device.set_encrypted_volume_mode(DEFAULT_ADMIN_PIN, VolumeMode::ReadOnly)
+ );
+ assert_ok!(
+ (),
+ device.set_encrypted_volume_mode(DEFAULT_ADMIN_PIN, VolumeMode::ReadWrite)
+ );
+ assert_ok!(
+ (),
+ device.set_encrypted_volume_mode(DEFAULT_ADMIN_PIN, VolumeMode::ReadOnly)
+ );
+}
+
+#[test_device]
fn set_unencrypted_volume_mode(device: Storage) {
fn assert_mode(device: &Storage, mode: VolumeMode) {
- let status = device.get_status();
- assert!(status.is_ok());
+ let status = unwrap_ok!(device.get_status());
assert_eq!(
- status.unwrap().unencrypted_volume.read_only,
+ status.unencrypted_volume.read_only,
mode == VolumeMode::ReadOnly
);
}
- fn assert_success(device: &Storage, mode: VolumeMode) {
- assert_ok!((), device.set_unencrypted_volume_mode(ADMIN_PASSWORD, mode));
+ fn assert_success(device: &mut Storage, mode: VolumeMode) {
+ assert_ok!(
+ (),
+ device.set_unencrypted_volume_mode(DEFAULT_ADMIN_PIN, mode)
+ );
assert_mode(&device, mode);
}
- assert_success(&device, VolumeMode::ReadOnly);
+ let mut device = device;
+ assert_success(&mut device, VolumeMode::ReadOnly);
assert_cmd_err!(
CommandError::WrongPassword,
- device.set_unencrypted_volume_mode(USER_PASSWORD, VolumeMode::ReadOnly)
+ device.set_unencrypted_volume_mode(DEFAULT_USER_PIN, VolumeMode::ReadOnly)
);
assert_mode(&device, VolumeMode::ReadOnly);
- assert_success(&device, VolumeMode::ReadWrite);
- assert_success(&device, VolumeMode::ReadWrite);
- assert_success(&device, VolumeMode::ReadOnly);
+ assert_success(&mut device, VolumeMode::ReadWrite);
+ assert_success(&mut device, VolumeMode::ReadWrite);
+ assert_success(&mut device, VolumeMode::ReadOnly);
}
#[test_device]
fn get_storage_status(device: Storage) {
- let status = device.get_status().unwrap();
-
+ let status = unwrap_ok!(device.get_status());
assert!(status.serial_number_sd_card > 0);
assert!(status.serial_number_smart_card > 0);
}
#[test_device]
fn get_production_info(device: Storage) {
- let info = device.get_production_info().unwrap();
+ let info = unwrap_ok!(device.get_production_info());
assert_eq!(0, info.firmware_version.major);
assert!(info.firmware_version.minor != 0);
assert!(info.serial_number_cpu != 0);
@@ -447,43 +525,45 @@ fn get_production_info(device: Storage) {
assert!(info.sd_card.oem != 0);
assert!(info.sd_card.manufacturer != 0);
- let status = device.get_status().unwrap();
+ let status = unwrap_ok!(device.get_status());
assert_eq!(status.firmware_version, info.firmware_version);
assert_eq!(status.serial_number_sd_card, info.sd_card.serial_number);
}
#[test_device]
fn clear_new_sd_card_warning(device: Storage) {
- assert_ok!((), device.factory_reset(ADMIN_PASSWORD));
+ let mut device = device;
+ assert_ok!((), device.factory_reset(DEFAULT_ADMIN_PIN));
thread::sleep(time::Duration::from_secs(3));
- assert_ok!((), device.build_aes_key(ADMIN_PASSWORD));
+ assert_ok!((), device.build_aes_key(DEFAULT_ADMIN_PIN));
// We have to perform an SD card operation to reset the new_sd_card_found field
assert_ok!((), device.lock());
- let status = device.get_status().unwrap();
+ let status = unwrap_ok!(device.get_status());
assert!(status.new_sd_card_found);
- assert_ok!((), device.clear_new_sd_card_warning(ADMIN_PASSWORD));
+ assert_ok!((), device.clear_new_sd_card_warning(DEFAULT_ADMIN_PIN));
- let status = device.get_status().unwrap();
+ let status = unwrap_ok!(device.get_status());
assert!(!status.new_sd_card_found);
}
#[test_device]
fn export_firmware(device: Storage) {
+ let mut device = device;
assert_cmd_err!(
CommandError::WrongPassword,
device.export_firmware("someadminpn")
);
- assert_ok!((), device.export_firmware(ADMIN_PASSWORD));
+ assert_ok!((), device.export_firmware(DEFAULT_ADMIN_PIN));
assert_ok!(
(),
- device.set_unencrypted_volume_mode(ADMIN_PASSWORD, VolumeMode::ReadWrite)
+ device.set_unencrypted_volume_mode(DEFAULT_ADMIN_PIN, VolumeMode::ReadWrite)
);
- assert_ok!((), device.export_firmware(ADMIN_PASSWORD));
+ assert_ok!((), device.export_firmware(DEFAULT_ADMIN_PIN));
assert_ok!(
(),
- device.set_unencrypted_volume_mode(ADMIN_PASSWORD, VolumeMode::ReadOnly)
+ device.set_unencrypted_volume_mode(DEFAULT_ADMIN_PIN, VolumeMode::ReadOnly)
);
}
diff --git a/nitrokey/tests/lib.rs b/nitrokey/tests/lib.rs
index 697024d..8ab75f6 100644
--- a/nitrokey/tests/lib.rs
+++ b/nitrokey/tests/lib.rs
@@ -1,9 +1,11 @@
// Copyright (C) 2019 Robin Krahl <robin.krahl@ireas.org>
// SPDX-License-Identifier: MIT
+mod util;
+
#[test]
fn get_library_version() {
- let version = nitrokey::get_library_version().unwrap();
+ let version = unwrap_ok!(nitrokey::get_library_version());
assert!(version.git.is_empty() || version.git.starts_with("v"));
assert!(version.major > 0);
diff --git a/nitrokey/tests/otp.rs b/nitrokey/tests/otp.rs
index e424673..c0bbecf 100644
--- a/nitrokey/tests/otp.rs
+++ b/nitrokey/tests/otp.rs
@@ -4,16 +4,14 @@
mod util;
use std::fmt::Debug;
-use std::ops::Deref;
+use std::ops::DerefMut;
use nitrokey::{
Admin, Authenticate, CommandError, Config, ConfigureOtp, Device, GenerateOtp, LibraryError,
- OtpMode, OtpSlotData,
+ OtpMode, OtpSlotData, DEFAULT_ADMIN_PIN, DEFAULT_USER_PIN,
};
use nitrokey_test::test as test_device;
-use crate::util::{ADMIN_PASSWORD, USER_PASSWORD};
-
// test suite according to RFC 4226, Appendix D
static HOTP_SECRET: &str = "3132333435363738393031323334353637383930";
static HOTP_CODES: &[&str] = &[
@@ -43,27 +41,25 @@ where
T: Device,
(T, nitrokey::Error): Debug,
{
- device
- .authenticate_admin(ADMIN_PASSWORD)
- .expect("Could not login as admin.")
+ unwrap_ok!(device.authenticate_admin(DEFAULT_ADMIN_PIN))
}
-fn configure_hotp(admin: &ConfigureOtp, counter: u8) {
+fn configure_hotp(admin: &mut ConfigureOtp, counter: u8) {
let slot_data = OtpSlotData::new(1, "test-hotp", HOTP_SECRET, OtpMode::SixDigits);
assert_ok!((), admin.write_hotp_slot(slot_data, counter.into()));
}
-fn check_hotp_codes(device: &GenerateOtp, offset: u8) {
+fn check_hotp_codes(device: &mut GenerateOtp, offset: u8) {
HOTP_CODES.iter().enumerate().for_each(|(i, code)| {
if i >= offset as usize {
- let result = device.get_hotp_code(1);
- assert_eq!(code, &result.unwrap());
+ assert_ok!(code.to_string(), device.get_hotp_code(1));
}
});
}
#[test_device]
fn set_time(device: DeviceWrapper) {
+ let mut device = device;
assert_ok!((), device.set_time(1546385382, true));
assert_ok!((), device.set_time(1546385392, false));
assert_cmd_err!(CommandError::Timestamp, device.set_time(1546385292, false));
@@ -72,49 +68,47 @@ fn set_time(device: DeviceWrapper) {
#[test_device]
fn hotp_no_pin(device: DeviceWrapper) {
- let admin = make_admin_test_device(device);
+ let mut admin = make_admin_test_device(device);
let config = Config::new(None, None, None, false);
assert_ok!((), admin.write_config(config));
- configure_hotp(&admin, 0);
- check_hotp_codes(admin.deref(), 0);
+ configure_hotp(&mut admin, 0);
+ check_hotp_codes(admin.deref_mut(), 0);
- configure_hotp(&admin, 5);
- check_hotp_codes(admin.deref(), 5);
+ configure_hotp(&mut admin, 5);
+ check_hotp_codes(admin.deref_mut(), 5);
- configure_hotp(&admin, 0);
- check_hotp_codes(&admin.device(), 0);
+ configure_hotp(&mut admin, 0);
+ check_hotp_codes(&mut admin.device(), 0);
}
#[test_device]
fn hotp_pin(device: DeviceWrapper) {
- let admin = make_admin_test_device(device);
+ let mut admin = make_admin_test_device(device);
let config = Config::new(None, None, None, true);
assert_ok!((), admin.write_config(config));
- configure_hotp(&admin, 0);
- let user = admin.device().authenticate_user(USER_PASSWORD).unwrap();
- check_hotp_codes(&user, 0);
+ configure_hotp(&mut admin, 0);
+ let mut user = unwrap_ok!(admin.device().authenticate_user(DEFAULT_USER_PIN));
+ check_hotp_codes(&mut user, 0);
assert_cmd_err!(CommandError::NotAuthorized, user.device().get_hotp_code(1));
}
#[test_device]
fn hotp_slot_name(device: DeviceWrapper) {
- let admin = make_admin_test_device(device);
+ let mut admin = make_admin_test_device(device);
let slot_data = OtpSlotData::new(1, "test-hotp", HOTP_SECRET, OtpMode::SixDigits);
assert_ok!((), admin.write_hotp_slot(slot_data, 0));
let device = admin.device();
- let result = device.get_hotp_slot_name(1);
- assert_eq!("test-hotp", result.unwrap());
- let result = device.get_hotp_slot_name(4);
- assert_lib_err!(LibraryError::InvalidSlot, result);
+ assert_ok!("test-hotp".to_string(), device.get_hotp_slot_name(1));
+ assert_lib_err!(LibraryError::InvalidSlot, device.get_hotp_slot_name(4));
}
#[test_device]
fn hotp_error(device: DeviceWrapper) {
- let admin = make_admin_test_device(device);
+ let mut admin = make_admin_test_device(device);
let slot_data = OtpSlotData::new(1, "", HOTP_SECRET, OtpMode::SixDigits);
assert_cmd_err!(CommandError::NoName, admin.write_hotp_slot(slot_data, 0));
let slot_data = OtpSlotData::new(4, "test", HOTP_SECRET, OtpMode::SixDigits);
@@ -133,7 +127,7 @@ fn hotp_error(device: DeviceWrapper) {
#[test_device]
fn hotp_erase(device: DeviceWrapper) {
- let admin = make_admin_test_device(device);
+ let mut admin = make_admin_test_device(device);
let config = Config::new(None, None, None, false);
assert_ok!((), admin.write_config(config));
let slot_data = OtpSlotData::new(1, "test1", HOTP_SECRET, OtpMode::SixDigits);
@@ -143,22 +137,22 @@ fn hotp_erase(device: DeviceWrapper) {
assert_ok!((), admin.erase_hotp_slot(1));
- let device = admin.device();
+ let mut device = admin.device();
let result = device.get_hotp_slot_name(1);
assert_cmd_err!(CommandError::SlotNotProgrammed, result);
let result = device.get_hotp_code(1);
assert_cmd_err!(CommandError::SlotNotProgrammed, result);
- assert_eq!("test2", device.get_hotp_slot_name(2).unwrap());
+ assert_ok!("test2".to_string(), device.get_hotp_slot_name(2));
}
-fn configure_totp(admin: &ConfigureOtp, factor: u64) {
+fn configure_totp(admin: &mut ConfigureOtp, factor: u64) {
let slot_data = OtpSlotData::new(1, "test-totp", TOTP_SECRET, OtpMode::EightDigits);
let time_window = 30u64.checked_mul(factor).unwrap();
assert_ok!((), admin.write_totp_slot(slot_data, time_window as u16));
}
-fn check_totp_codes(device: &GenerateOtp, factor: u64, timestamp_size: TotpTimestampSize) {
+fn check_totp_codes(device: &mut GenerateOtp, factor: u64, timestamp_size: TotpTimestampSize) {
for (base_time, codes) in TOTP_CODES {
let time = base_time.checked_mul(factor).unwrap();
let is_u64 = time > u32::max_value() as u64;
@@ -167,7 +161,7 @@ fn check_totp_codes(device: &GenerateOtp, factor: u64, timestamp_size: TotpTimes
}
assert_ok!((), device.set_time(time, true));
- let code = device.get_totp_code(1).unwrap();
+ let code = unwrap_ok!(device.get_totp_code(1));
assert!(
code.contains(&code),
"Generated TOTP code {} for {}, but expected one of {}",
@@ -180,49 +174,47 @@ fn check_totp_codes(device: &GenerateOtp, factor: u64, timestamp_size: TotpTimes
#[test_device]
fn totp_no_pin(device: DeviceWrapper) {
- // TODO: this test may fail due to bad timing --> find solution
- let admin = make_admin_test_device(device);
+ let mut admin = make_admin_test_device(device);
let config = Config::new(None, None, None, false);
assert_ok!((), admin.write_config(config));
- configure_totp(&admin, 1);
- check_totp_codes(admin.deref(), 1, TotpTimestampSize::U32);
+ configure_totp(&mut admin, 1);
+ check_totp_codes(admin.deref_mut(), 1, TotpTimestampSize::U32);
- configure_totp(&admin, 2);
- check_totp_codes(admin.deref(), 2, TotpTimestampSize::U32);
+ configure_totp(&mut admin, 2);
+ check_totp_codes(admin.deref_mut(), 2, TotpTimestampSize::U32);
- configure_totp(&admin, 1);
- check_totp_codes(&admin.device(), 1, TotpTimestampSize::U32);
+ configure_totp(&mut admin, 1);
+ check_totp_codes(&mut admin.device(), 1, TotpTimestampSize::U32);
}
#[test_device]
// Nitrokey Storage does only support timestamps that fit in a 32-bit
// unsigned integer, so don't test with it.
fn totp_no_pin_64(device: Pro) {
- let admin = make_admin_test_device(device);
+ let mut admin = make_admin_test_device(device);
let config = Config::new(None, None, None, false);
assert_ok!((), admin.write_config(config));
- configure_totp(&admin, 1);
- check_totp_codes(admin.deref(), 1, TotpTimestampSize::U64);
+ configure_totp(&mut admin, 1);
+ check_totp_codes(admin.deref_mut(), 1, TotpTimestampSize::U64);
- configure_totp(&admin, 2);
- check_totp_codes(admin.deref(), 2, TotpTimestampSize::U64);
+ configure_totp(&mut admin, 2);
+ check_totp_codes(admin.deref_mut(), 2, TotpTimestampSize::U64);
- configure_totp(&admin, 1);
- check_totp_codes(&admin.device(), 1, TotpTimestampSize::U64);
+ configure_totp(&mut admin, 1);
+ check_totp_codes(&mut admin.device(), 1, TotpTimestampSize::U64);
}
#[test_device]
fn totp_pin(device: DeviceWrapper) {
- // TODO: this test may fail due to bad timing --> find solution
- let admin = make_admin_test_device(device);
+ let mut admin = make_admin_test_device(device);
let config = Config::new(None, None, None, true);
assert_ok!((), admin.write_config(config));
- configure_totp(&admin, 1);
- let user = admin.device().authenticate_user(USER_PASSWORD).unwrap();
- check_totp_codes(&user, 1, TotpTimestampSize::U32);
+ configure_totp(&mut admin, 1);
+ let mut user = unwrap_ok!(admin.device().authenticate_user(DEFAULT_USER_PIN));
+ check_totp_codes(&mut user, 1, TotpTimestampSize::U32);
assert_cmd_err!(CommandError::NotAuthorized, user.device().get_totp_code(1));
}
@@ -230,20 +222,20 @@ fn totp_pin(device: DeviceWrapper) {
#[test_device]
// See comment for totp_no_pin_64.
fn totp_pin_64(device: Pro) {
- let admin = make_admin_test_device(device);
+ let mut admin = make_admin_test_device(device);
let config = Config::new(None, None, None, true);
assert_ok!((), admin.write_config(config));
- configure_totp(&admin, 1);
- let user = admin.device().authenticate_user(USER_PASSWORD).unwrap();
- check_totp_codes(&user, 1, TotpTimestampSize::U64);
+ configure_totp(&mut admin, 1);
+ let mut user = unwrap_ok!(admin.device().authenticate_user(DEFAULT_USER_PIN));
+ check_totp_codes(&mut user, 1, TotpTimestampSize::U64);
assert_cmd_err!(CommandError::NotAuthorized, user.device().get_totp_code(1));
}
#[test_device]
fn totp_slot_name(device: DeviceWrapper) {
- let admin = make_admin_test_device(device);
+ let mut admin = make_admin_test_device(device);
let slot_data = OtpSlotData::new(1, "test-totp", TOTP_SECRET, OtpMode::EightDigits);
assert_ok!((), admin.write_totp_slot(slot_data, 0));
@@ -256,7 +248,7 @@ fn totp_slot_name(device: DeviceWrapper) {
#[test_device]
fn totp_error(device: DeviceWrapper) {
- let admin = make_admin_test_device(device);
+ let mut admin = make_admin_test_device(device);
let slot_data = OtpSlotData::new(1, "", TOTP_SECRET, OtpMode::SixDigits);
assert_cmd_err!(CommandError::NoName, admin.write_totp_slot(slot_data, 0));
let slot_data = OtpSlotData::new(20, "test", TOTP_SECRET, OtpMode::SixDigits);
@@ -275,7 +267,7 @@ fn totp_error(device: DeviceWrapper) {
#[test_device]
fn totp_erase(device: DeviceWrapper) {
- let admin = make_admin_test_device(device);
+ let mut admin = make_admin_test_device(device);
let config = Config::new(None, None, None, false);
assert_ok!((), admin.write_config(config));
let slot_data = OtpSlotData::new(1, "test1", TOTP_SECRET, OtpMode::SixDigits);
@@ -291,5 +283,5 @@ fn totp_erase(device: DeviceWrapper) {
let result = device.get_totp_code(1);
assert_cmd_err!(CommandError::SlotNotProgrammed, result);
- assert_eq!("test2", device.get_totp_slot_name(2).unwrap());
+ assert_ok!("test2".to_string(), device.get_totp_slot_name(2));
}
diff --git a/nitrokey/tests/pws.rs b/nitrokey/tests/pws.rs
index df99e1c..b0e5abe 100644
--- a/nitrokey/tests/pws.rs
+++ b/nitrokey/tests/pws.rs
@@ -7,13 +7,12 @@ use std::ffi::CStr;
use libc::{c_int, c_void, free};
use nitrokey::{
- CommandError, Device, Error, GetPasswordSafe, LibraryError, PasswordSafe, SLOT_COUNT,
+ CommandError, Device, Error, GetPasswordSafe, LibraryError, PasswordSafe, DEFAULT_ADMIN_PIN,
+ DEFAULT_USER_PIN, SLOT_COUNT,
};
use nitrokey_sys;
use nitrokey_test::test as test_device;
-use crate::util::{ADMIN_PASSWORD, USER_PASSWORD};
-
fn get_slot_name_direct(slot: u8) -> Result<String, Error> {
let ptr = unsafe { nitrokey_sys::NK_get_password_safe_slot_name(slot) };
if ptr.is_null() {
@@ -33,33 +32,35 @@ fn get_slot_name_direct(slot: u8) -> Result<String, Error> {
}
}
-fn get_pws<T>(device: &T) -> PasswordSafe
+fn get_pws<T>(device: &mut T) -> PasswordSafe
where
T: Device,
{
- device.get_password_safe(USER_PASSWORD).unwrap()
+ unwrap_ok!(device.get_password_safe(DEFAULT_USER_PIN))
}
#[test_device]
fn enable(device: DeviceWrapper) {
+ let mut device = device;
assert_cmd_err!(
CommandError::WrongPassword,
- device.get_password_safe(&(USER_PASSWORD.to_owned() + "123"))
+ device.get_password_safe(&(DEFAULT_USER_PIN.to_owned() + "123"))
);
- assert!(device.get_password_safe(USER_PASSWORD).is_ok());
+ assert_any_ok!(device.get_password_safe(DEFAULT_USER_PIN));
assert_cmd_err!(
CommandError::WrongPassword,
- device.get_password_safe(ADMIN_PASSWORD)
+ device.get_password_safe(DEFAULT_ADMIN_PIN)
);
- assert!(device.get_password_safe(USER_PASSWORD).is_ok());
+ assert_any_ok!(device.get_password_safe(DEFAULT_USER_PIN));
}
#[test_device]
fn drop(device: DeviceWrapper) {
+ let mut device = device;
{
- let pws = get_pws(&device);
+ let mut pws = get_pws(&mut device);
assert_ok!((), pws.write_slot(1, "name", "login", "password"));
- assert_eq!("name", pws.get_slot_name(1).unwrap());
+ assert_ok!("name".to_string(), pws.get_slot_name(1));
let result = get_slot_name_direct(1);
assert_ok!(String::from("name"), result);
}
@@ -72,15 +73,16 @@ fn drop(device: DeviceWrapper) {
#[test_device]
fn get_status(device: DeviceWrapper) {
- let pws = get_pws(&device);
+ let mut device = device;
+ let mut pws = get_pws(&mut device);
for i in 0..SLOT_COUNT {
assert_ok!((), pws.erase_slot(i));
}
- let status = pws.get_slot_status().unwrap();
+ let status = unwrap_ok!(pws.get_slot_status());
assert_eq!(status, [false; SLOT_COUNT as usize]);
assert_ok!((), pws.write_slot(1, "name", "login", "password"));
- let status = pws.get_slot_status().unwrap();
+ let status = unwrap_ok!(pws.get_slot_status());
for i in 0..SLOT_COUNT {
assert_eq!(i == 1, status[i as usize]);
}
@@ -88,17 +90,17 @@ fn get_status(device: DeviceWrapper) {
for i in 0..SLOT_COUNT {
assert_ok!((), pws.write_slot(i, "name", "login", "password"));
}
- let status = pws.get_slot_status().unwrap();
- assert_eq!(status, [true; SLOT_COUNT as usize]);
+ assert_ok!([true; SLOT_COUNT as usize], pws.get_slot_status());
}
#[test_device]
fn get_data(device: DeviceWrapper) {
- let pws = get_pws(&device);
+ let mut device = device;
+ let mut pws = get_pws(&mut device);
assert_ok!((), pws.write_slot(1, "name", "login", "password"));
- assert_eq!("name", pws.get_slot_name(1).unwrap());
- assert_eq!("login", pws.get_slot_login(1).unwrap());
- assert_eq!("password", pws.get_slot_password(1).unwrap());
+ assert_ok!("name".to_string(), pws.get_slot_name(1));
+ assert_ok!("login".to_string(), pws.get_slot_login(1));
+ assert_ok!("password".to_string(), pws.get_slot_password(1));
assert_ok!((), pws.erase_slot(1));
assert_cmd_err!(CommandError::SlotNotProgrammed, pws.get_slot_name(1));
@@ -109,9 +111,9 @@ fn get_data(device: DeviceWrapper) {
let login = "pär@test.com";
let password = "'i3lJc[09?I:,[u7dWz9";
assert_ok!((), pws.write_slot(1, name, login, password));
- assert_eq!(name, pws.get_slot_name(1).unwrap());
- assert_eq!(login, pws.get_slot_login(1).unwrap());
- assert_eq!(password, pws.get_slot_password(1).unwrap());
+ assert_ok!(name.to_string(), pws.get_slot_name(1));
+ assert_ok!(login.to_string(), pws.get_slot_login(1));
+ assert_ok!(password.to_string(), pws.get_slot_password(1));
assert_lib_err!(LibraryError::InvalidSlot, pws.get_slot_name(SLOT_COUNT));
assert_lib_err!(LibraryError::InvalidSlot, pws.get_slot_login(SLOT_COUNT));
@@ -120,7 +122,8 @@ fn get_data(device: DeviceWrapper) {
#[test_device]
fn write(device: DeviceWrapper) {
- let pws = get_pws(&device);
+ let mut device = device;
+ let mut pws = get_pws(&mut device);
assert_lib_err!(
LibraryError::InvalidSlot,
@@ -145,7 +148,8 @@ fn write(device: DeviceWrapper) {
#[test_device]
fn erase(device: DeviceWrapper) {
- let pws = get_pws(&device);
+ let mut device = device;
+ let mut pws = get_pws(&mut device);
assert_lib_err!(LibraryError::InvalidSlot, pws.erase_slot(SLOT_COUNT));
assert_ok!((), pws.write_slot(0, "name", "login", "password"));
diff --git a/nitrokey/tests/util/mod.rs b/nitrokey/tests/util/mod.rs
index 49ec13e..f2b20ec 100644
--- a/nitrokey/tests/util/mod.rs
+++ b/nitrokey/tests/util/mod.rs
@@ -1,8 +1,35 @@
// Copyright (C) 2018-2019 Robin Krahl <robin.krahl@ireas.org>
// SPDX-License-Identifier: MIT
-pub static ADMIN_PASSWORD: &str = "12345678";
-pub static USER_PASSWORD: &str = "123456";
+#[macro_export]
+macro_rules! unwrap_ok {
+ ($val:expr) => {{
+ match $val {
+ Ok(val) => val,
+ Err(err) => panic!(
+ r#"assertion failed: `(left == right)`
+ left: `Ok(_)`,
+ right: `Err({:?})`"#,
+ err
+ ),
+ }
+ }};
+}
+
+#[macro_export]
+macro_rules! assert_any_ok {
+ ($val:expr) => {{
+ match &$val {
+ Ok(_) => {}
+ Err(err) => panic!(
+ r#"assertion failed: `(left == right)`
+ left: `Ok(_)`,
+ right: `Err({:?})`"#,
+ err
+ ),
+ }
+ }};
+}
#[macro_export]
macro_rules! assert_ok {