diff options
| -rw-r--r-- | TODO.md | 1 | ||||
| -rw-r--r-- | src/pws.rs | 24 | ||||
| -rw-r--r-- | tests/device.rs | 41 | 
3 files changed, 45 insertions, 21 deletions
| @@ -13,6 +13,7 @@ SPDX-License-Identifier: MIT  - Clear passwords from memory.  - Lock password safe in `PasswordSafe::drop()` (see [nitrokey-storage-firmware    issue 65][]). +- Disable creation of multiple password safes at the same time.  - Check timing in Storage tests.  - Consider restructuring `device::StorageStatus`. @@ -18,7 +18,8 @@ pub const SLOT_COUNT: u8 = 16;  /// The password safe stores a tuple consisting of a name, a login and a password on a slot.  The  /// number of available slots is [`SLOT_COUNT`][].  The slots are addressed starting with zero.  To  /// retrieve a password safe from a Nitrokey device, use the [`get_password_safe`][] method from -/// the [`GetPasswordSafe`][] trait. +/// the [`GetPasswordSafe`][] trait.  Note that the device must live at least as long as the +/// password safe.  ///  /// Once the password safe has been unlocked, it can be accessed without a password.  Therefore it  /// is mandatory to call [`lock`][] on the corresponding device after the password store is used. @@ -57,17 +58,21 @@ pub const SLOT_COUNT: u8 = 16;  /// [`GetPasswordSafe`]: trait.GetPasswordSafe.html  #[derive(Debug)]  pub struct PasswordSafe<'a> { -    device: &'a mut dyn Device, +    _device: &'a dyn Device,  }  /// Provides access to a [`PasswordSafe`][].  /// +/// The device that implements this trait must always live at least as long as a password safe +/// retrieved from it. +///  /// [`PasswordSafe`]: struct.PasswordSafe.html  pub trait GetPasswordSafe {      /// Enables and returns the password safe.      /// -    /// It is mandatory to lock the underlying device using [`lock`][] after the password safe has -    /// been used.  Otherwise, other applications can access the password store without +    /// The underlying device must always live at least as long as a password safe retrieved from +    /// it.  It is mandatory to lock the underlying device using [`lock`][] after the password safe +    /// has been used.  Otherwise, other applications can access the password store without      /// authentication.      ///      /// If this method returns an `AesDecryptionFailed` (Nitrokey Pro) or `Unknown` (Nitrokey @@ -116,17 +121,12 @@ pub trait GetPasswordSafe {  }  fn get_password_safe<'a>( -    device: &'a mut dyn Device, +    device: &'a dyn Device,      user_pin: &str,  ) -> Result<PasswordSafe<'a>, Error> {      let user_pin_string = get_cstring(user_pin)?; -    let result = get_command_result(unsafe { -        nitrokey_sys::NK_enable_password_safe(user_pin_string.as_ptr()) -    }); -    match result { -        Ok(()) => Ok(PasswordSafe { device }), -        Err(err) => Err(err), -    } +    get_command_result(unsafe { nitrokey_sys::NK_enable_password_safe(user_pin_string.as_ptr()) }) +        .map(|_| PasswordSafe { _device: device })  }  fn get_pws_result(s: String) -> Result<String, Error> { diff --git a/tests/device.rs b/tests/device.rs index 6a3683b..5c52024 100644 --- a/tests/device.rs +++ b/tests/device.rs @@ -156,7 +156,10 @@ fn change_user_pin(device: DeviceWrapper) {      let device = device.authenticate_user(USER_NEW_PASSWORD).unwrap_err().0;      let mut device = device; -    assert_ok!((), device.change_user_pin(DEFAULT_USER_PIN, USER_NEW_PASSWORD)); +    assert_ok!( +        (), +        device.change_user_pin(DEFAULT_USER_PIN, USER_NEW_PASSWORD) +    );      let device = device.authenticate_user(DEFAULT_USER_PIN).unwrap_err().0;      let device = device @@ -179,7 +182,10 @@ fn change_user_pin(device: DeviceWrapper) {  #[test_device]  fn change_admin_pin(device: DeviceWrapper) { -    let device = device.authenticate_admin(DEFAULT_ADMIN_PIN).unwrap().device(); +    let device = device +        .authenticate_admin(DEFAULT_ADMIN_PIN) +        .unwrap() +        .device();      let mut device = device.authenticate_admin(ADMIN_NEW_PASSWORD).unwrap_err().0;      assert_ok!( @@ -203,7 +209,10 @@ fn change_admin_pin(device: DeviceWrapper) {          device.change_admin_pin(ADMIN_NEW_PASSWORD, DEFAULT_ADMIN_PIN)      ); -    let device = device.authenticate_admin(DEFAULT_ADMIN_PIN).unwrap().device(); +    let device = device +        .authenticate_admin(DEFAULT_ADMIN_PIN) +        .unwrap() +        .device();      device.authenticate_admin(ADMIN_NEW_PASSWORD).unwrap_err();  } @@ -225,7 +234,10 @@ where  #[test_device]  fn unlock_user_pin(device: DeviceWrapper) {      let mut device = device.authenticate_user(DEFAULT_USER_PIN).unwrap().device(); -    assert_ok!((), device.unlock_user_pin(DEFAULT_ADMIN_PIN, DEFAULT_USER_PIN)); +    assert_ok!( +        (), +        device.unlock_user_pin(DEFAULT_ADMIN_PIN, DEFAULT_USER_PIN) +    );      assert_cmd_err!(          CommandError::WrongPassword,          device.unlock_user_pin(DEFAULT_USER_PIN, DEFAULT_USER_PIN) @@ -236,21 +248,26 @@ fn unlock_user_pin(device: DeviceWrapper) {      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 mut device = require_failed_user_login(device, DEFAULT_USER_PIN, 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(DEFAULT_USER_PIN, DEFAULT_USER_PIN)      ); -    assert_ok!((), device.unlock_user_pin(DEFAULT_ADMIN_PIN, DEFAULT_USER_PIN)); +    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 mut device = require_failed_user_login(device, DEFAULT_USER_PIN, CommandError::WrongPassword); +    let mut device = +        require_failed_user_login(device, DEFAULT_USER_PIN, CommandError::WrongPassword);      // unblock with new PIN      assert_cmd_err!( @@ -307,7 +324,10 @@ fn factory_reset(device: DeviceWrapper) {      );      assert_ok!((), device.factory_reset(ADMIN_NEW_PASSWORD)); -    let device = device.authenticate_admin(DEFAULT_ADMIN_PIN).unwrap().device(); +    let device = device +        .authenticate_admin(DEFAULT_ADMIN_PIN) +        .unwrap() +        .device();      let user = unwrap_ok!(device.authenticate_user(DEFAULT_USER_PIN));      assert_cmd_err!(CommandError::SlotNotProgrammed, user.get_totp_slot_name(1)); @@ -335,7 +355,10 @@ fn build_aes_key(device: DeviceWrapper) {      );      assert_ok!((), device.build_aes_key(DEFAULT_ADMIN_PIN)); -    let mut device = device.authenticate_admin(DEFAULT_ADMIN_PIN).unwrap().device(); +    let mut device = device +        .authenticate_admin(DEFAULT_ADMIN_PIN) +        .unwrap() +        .device();      let pws = unwrap_ok!(device.get_password_safe(DEFAULT_USER_PIN));      assert_utf8_err_or_ne("test", pws.get_slot_name(0)); | 
