diff options
| author | Robin Krahl <robin.krahl@ireas.org> | 2019-01-28 12:27:15 +0000 | 
|---|---|---|
| committer | Robin Krahl <robin.krahl@ireas.org> | 2019-02-02 10:25:02 +0000 | 
| commit | f49e61589e32217f97c94aa86d826f6b65170fba (patch) | |
| tree | 0ca2fa9741197e6c496eaa5452165dcaee1373fa /tests | |
| parent | eef2118717878f3543248ebf2d099aebbedceacf (diff) | |
| download | nitrokey-rs-f49e61589e32217f97c94aa86d826f6b65170fba.tar.gz nitrokey-rs-f49e61589e32217f97c94aa86d826f6b65170fba.tar.bz2 | |
Require mutable reference if method changes device state
Previously, all methods that access a Nitrokey device took a reference
to the device as input.  This method changes methods that change the
device state to require a mutable reference instead.  In most case,
this is straightforward as the method writes data to the device (for
example write_config or change_user_pin).  But there are two edge cases:
- Authenticating with a PIN changes the device state as it may decrease
  the PIN retry counter if the authentication fails.
- Generating an HOTP code changes the device state as it increases the
  HOTP counter.
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/device.rs | 46 | ||||
| -rw-r--r-- | tests/otp.rs | 93 | ||||
| -rw-r--r-- | tests/pws.rs | 18 | 
3 files changed, 87 insertions, 70 deletions
| diff --git a/tests/device.rs b/tests/device.rs index 969a7df..7a69214 100644 --- a/tests/device.rs +++ b/tests/device.rs @@ -133,7 +133,7 @@ fn get_retry_count(device: DeviceWrapper) {  #[test_device]  fn config(device: DeviceWrapper) { -    let admin = unwrap_ok!(device.authenticate_admin(ADMIN_PASSWORD)); +    let mut admin = unwrap_ok!(device.authenticate_admin(ADMIN_PASSWORD));      let config = Config::new(None, None, None, true);      assert_ok!((), admin.write_config(config)); @@ -156,6 +156,7 @@ fn change_user_pin(device: DeviceWrapper) {      let device = device.authenticate_user(USER_PASSWORD).unwrap().device();      let device = device.authenticate_user(USER_NEW_PASSWORD).unwrap_err().0; +    let mut device = device;      assert_ok!((), device.change_user_pin(USER_PASSWORD, USER_NEW_PASSWORD));      let device = device.authenticate_user(USER_PASSWORD).unwrap_err().0; @@ -164,6 +165,7 @@ fn change_user_pin(device: DeviceWrapper) {          .unwrap()          .device(); +    let mut device = device;      let result = device.change_user_pin(USER_PASSWORD, USER_PASSWORD);      assert_cmd_err!(CommandError::WrongPassword, result); @@ -176,7 +178,7 @@ fn change_user_pin(device: DeviceWrapper) {  #[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 mut device = device.authenticate_admin(ADMIN_NEW_PASSWORD).unwrap_err().0;      assert_ok!(          (), @@ -184,7 +186,7 @@ fn change_admin_pin(device: DeviceWrapper) {      );      let device = device.authenticate_admin(ADMIN_PASSWORD).unwrap_err().0; -    let device = device +    let mut device = device          .authenticate_admin(ADMIN_NEW_PASSWORD)          .unwrap()          .device(); @@ -220,7 +222,7 @@ where  #[test_device]  fn unlock_user_pin(device: DeviceWrapper) { -    let device = device.authenticate_user(USER_PASSWORD).unwrap().device(); +    let mut device = device.authenticate_user(USER_PASSWORD).unwrap().device();      assert_ok!((), device.unlock_user_pin(ADMIN_PASSWORD, USER_PASSWORD));      assert_cmd_err!(          CommandError::WrongPassword, @@ -232,7 +234,7 @@ 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 device = require_failed_user_login(device, USER_PASSWORD, CommandError::WrongPassword); +    let mut device = require_failed_user_login(device, USER_PASSWORD, CommandError::WrongPassword);      // unblock with current PIN      assert_cmd_err!( @@ -246,7 +248,7 @@ 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 device = require_failed_user_login(device, USER_PASSWORD, CommandError::WrongPassword); +    let mut device = require_failed_user_login(device, USER_PASSWORD, CommandError::WrongPassword);      // unblock with new PIN      assert_cmd_err!( @@ -272,12 +274,12 @@ fn assert_utf8_err_or_ne(left: &str, right: Result<String, Error>) {  #[test_device]  fn factory_reset(device: DeviceWrapper) { -    let admin = unwrap_ok!(device.authenticate_admin(ADMIN_PASSWORD)); +    let mut admin = unwrap_ok!(device.authenticate_admin(ADMIN_PASSWORD));      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 = unwrap_ok!(device.get_password_safe(USER_PASSWORD)); +    let mut device = admin.device(); +    let mut pws = unwrap_ok!(device.get_password_safe(USER_PASSWORD));      assert_ok!((), pws.write_slot(0, "test", "testlogin", "testpw"));      drop(pws); @@ -302,18 +304,20 @@ fn factory_reset(device: DeviceWrapper) {      let user = unwrap_ok!(device.authenticate_user(USER_PASSWORD));      assert_cmd_err!(CommandError::SlotNotProgrammed, user.get_totp_slot_name(1)); -    let device = user.device(); +    let mut device = user.device();      let pws = unwrap_ok!(device.get_password_safe(USER_PASSWORD));      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));  }  #[test_device]  fn build_aes_key(device: DeviceWrapper) { -    let pws = unwrap_ok!(device.get_password_safe(USER_PASSWORD)); +    let mut device = device; +    let mut pws = unwrap_ok!(device.get_password_safe(USER_PASSWORD));      assert_ok!((), pws.write_slot(0, "test", "testlogin", "testpw"));      drop(pws); @@ -323,7 +327,7 @@ fn build_aes_key(device: DeviceWrapper) {      );      assert_ok!((), device.build_aes_key(ADMIN_PASSWORD)); -    let device = device.authenticate_admin(ADMIN_PASSWORD).unwrap().device(); +    let mut device = device.authenticate_admin(ADMIN_PASSWORD).unwrap().device();      let pws = unwrap_ok!(device.get_password_safe(USER_PASSWORD));      assert_utf8_err_or_ne("test", pws.get_slot_name(0)); @@ -333,6 +337,7 @@ fn build_aes_key(device: DeviceWrapper) {  #[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) @@ -343,6 +348,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()); @@ -361,6 +367,7 @@ 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()); @@ -396,6 +403,7 @@ fn hidden_volume(device: Storage) {  #[test_device]  fn lock(device: Storage) { +    let mut device = device;      assert_ok!((), device.enable_encrypted_volume(USER_PASSWORD));      assert_ok!((), device.lock());      assert_eq!(1, count_nitrokey_block_devices()); @@ -405,6 +413,7 @@ fn lock(device: Storage) {  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!(          (), @@ -441,12 +450,13 @@ fn set_unencrypted_volume_mode(device: Storage) {          );      } -    fn assert_success(device: &Storage, mode: VolumeMode) { +    fn assert_success(device: &mut Storage, mode: VolumeMode) {          assert_ok!((), device.set_unencrypted_volume_mode(ADMIN_PASSWORD, 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, @@ -454,9 +464,9 @@ fn set_unencrypted_volume_mode(device: Storage) {      );      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] @@ -488,6 +498,7 @@ fn get_production_info(device: Storage) {  #[test_device]  fn clear_new_sd_card_warning(device: Storage) { +    let mut device = device;      assert_ok!((), device.factory_reset(ADMIN_PASSWORD));      thread::sleep(time::Duration::from_secs(3));      assert_ok!((), device.build_aes_key(ADMIN_PASSWORD)); @@ -506,6 +517,7 @@ fn clear_new_sd_card_warning(device: Storage) {  #[test_device]  fn export_firmware(device: Storage) { +    let mut device = device;      assert_cmd_err!(          CommandError::WrongPassword,          device.export_firmware("someadminpn") diff --git a/tests/otp.rs b/tests/otp.rs index fc0e79e..28a8d7c 100644 --- a/tests/otp.rs +++ b/tests/otp.rs @@ -4,7 +4,7 @@  mod util;  use std::fmt::Debug; -use std::ops::Deref; +use std::ops::DerefMut;  use nitrokey::{      Admin, Authenticate, CommandError, Config, ConfigureOtp, Device, GenerateOtp, LibraryError, @@ -48,12 +48,12 @@ where          .expect("Could not login as admin.")  } -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 {              assert_ok!(code.to_string(), device.get_hotp_code(1)); @@ -63,6 +63,7 @@ fn check_hotp_codes(device: &GenerateOtp, offset: u8) {  #[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)); @@ -71,36 +72,36 @@ 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 = unwrap_ok!(admin.device().authenticate_user(USER_PASSWORD)); -    check_hotp_codes(&user, 0); +    configure_hotp(&mut admin, 0); +    let mut user = unwrap_ok!(admin.device().authenticate_user(USER_PASSWORD)); +    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)); @@ -111,7 +112,7 @@ fn hotp_slot_name(device: DeviceWrapper) {  #[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); @@ -130,7 +131,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); @@ -140,7 +141,7 @@ 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); @@ -149,13 +150,13 @@ fn hotp_erase(device: DeviceWrapper) {      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; @@ -177,49 +178,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 = unwrap_ok!(admin.device().authenticate_user(USER_PASSWORD)); -    check_totp_codes(&user, 1, TotpTimestampSize::U32); +    configure_totp(&mut admin, 1); +    let mut user = unwrap_ok!(admin.device().authenticate_user(USER_PASSWORD)); +    check_totp_codes(&mut user, 1, TotpTimestampSize::U32);      assert_cmd_err!(CommandError::NotAuthorized, user.device().get_totp_code(1));  } @@ -227,20 +226,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 = unwrap_ok!(admin.device().authenticate_user(USER_PASSWORD)); -    check_totp_codes(&user, 1, TotpTimestampSize::U64); +    configure_totp(&mut admin, 1); +    let mut user = unwrap_ok!(admin.device().authenticate_user(USER_PASSWORD)); +    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)); @@ -253,7 +252,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); @@ -272,7 +271,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); diff --git a/tests/pws.rs b/tests/pws.rs index 32dc8f7..7805803 100644 --- a/tests/pws.rs +++ b/tests/pws.rs @@ -33,7 +33,7 @@ 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,  { @@ -42,6 +42,7 @@ where  #[test_device]  fn enable(device: DeviceWrapper) { +    let mut device = device;      assert_cmd_err!(          CommandError::WrongPassword,          device.get_password_safe(&(USER_PASSWORD.to_owned() + "123")) @@ -56,8 +57,9 @@ fn enable(device: DeviceWrapper) {  #[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_ok!("name".to_string(), pws.get_slot_name(1));          let result = get_slot_name_direct(1); @@ -72,7 +74,8 @@ 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));      } @@ -93,7 +96,8 @@ fn get_status(device: DeviceWrapper) {  #[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_ok!("name".to_string(), pws.get_slot_name(1));      assert_ok!("login".to_string(), pws.get_slot_login(1)); @@ -119,7 +123,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, @@ -144,7 +149,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")); | 
