diff options
Diffstat (limited to 'nitrokey/tests')
-rw-r--r-- | nitrokey/tests/device.rs | 575 | ||||
-rw-r--r-- | nitrokey/tests/lib.rs | 28 | ||||
-rw-r--r-- | nitrokey/tests/otp.rs | 287 | ||||
-rw-r--r-- | nitrokey/tests/pws.rs | 159 | ||||
-rw-r--r-- | nitrokey/tests/util/mod.rs | 113 |
5 files changed, 0 insertions, 1162 deletions
diff --git a/nitrokey/tests/device.rs b/nitrokey/tests/device.rs deleted file mode 100644 index e367558..0000000 --- a/nitrokey/tests/device.rs +++ /dev/null @@ -1,575 +0,0 @@ -// Copyright (C) 2018-2019 Robin Krahl <robin.krahl@ireas.org> -// SPDX-License-Identifier: MIT - -mod util; - -use std::ffi::CStr; -use std::process::Command; -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; - -static ADMIN_NEW_PASSWORD: &str = "1234567890"; -static UPDATE_PIN: &str = "12345678"; -static UPDATE_NEW_PIN: &str = "87654321"; -static USER_NEW_PASSWORD: &str = "abcdefghij"; - -fn count_nitrokey_block_devices() -> usize { - thread::sleep(time::Duration::from_secs(2)); - let output = Command::new("lsblk") - .args(&["-o", "MODEL"]) - .output() - .expect("Could not list block devices"); - String::from_utf8_lossy(&output.stdout) - .split("\n") - .filter(|&s| s.replace("_", " ") == "Nitrokey Storage") - .count() -} - -#[test_device] -fn connect_no_device() { - let mut manager = unwrap_ok!(nitrokey::take()); - - assert_cmu_err!(CommunicationError::NotConnected, manager.connect()); - assert_cmu_err!( - CommunicationError::NotConnected, - manager.connect_model(nitrokey::Model::Pro) - ); - assert_cmu_err!( - CommunicationError::NotConnected, - manager.connect_model(nitrokey::Model::Storage) - ); - assert_cmu_err!(CommunicationError::NotConnected, manager.connect_pro()); - assert_cmu_err!(CommunicationError::NotConnected, manager.connect_storage()); -} - -#[test_device] -fn connect_pro(device: Pro) { - assert_eq!(device.get_model(), nitrokey::Model::Pro); - - let manager = device.into_manager(); - assert_any_ok!(manager.connect()); - assert_any_ok!(manager.connect_model(nitrokey::Model::Pro)); - assert_any_ok!(manager.connect_pro()); -} - -#[test_device] -fn connect_storage(device: Storage) { - assert_eq!(device.get_model(), nitrokey::Model::Storage); - - let manager = device.into_manager(); - assert_any_ok!(manager.connect()); - assert_any_ok!(manager.connect_model(nitrokey::Model::Storage)); - assert_any_ok!(manager.connect_storage()); -} - -fn assert_empty_serial_number() { - unsafe { - let ptr = nitrokey_sys::NK_device_serial_number(); - assert!(!ptr.is_null()); - let cstr = CStr::from_ptr(ptr); - assert_eq!(cstr.to_string_lossy(), ""); - } -} - -#[test_device] -fn disconnect(device: DeviceWrapper) { - drop(device); - assert_empty_serial_number(); -} - -#[test_device] -fn get_serial_number(device: DeviceWrapper) { - 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) { - let version = unwrap_ok!(device.get_firmware_version()); - assert_eq!(0, version.major); - assert!(version.minor > 0); -} - -fn admin_retry<'a, T>(device: T, suffix: &str, count: u8) -> T -where - T: Authenticate<'a> + Device<'a> + 'a, -{ - let result = device.authenticate_admin(&(DEFAULT_ADMIN_PIN.to_owned() + suffix)); - let device = match result { - Ok(admin) => admin.device(), - Err((device, _)) => device, - }; - assert_ok!(count, device.get_admin_retry_count()); - return device; -} - -fn user_retry<'a, T>(device: T, suffix: &str, count: u8) -> T -where - T: Authenticate<'a> + Device<'a> + 'a, -{ - let result = device.authenticate_user(&(DEFAULT_USER_PIN.to_owned() + suffix)); - let device = match result { - Ok(admin) => admin.device(), - Err((device, _)) => device, - }; - assert_ok!(count, device.get_user_retry_count()); - return device; -} - -#[test_device] -fn get_retry_count(device: DeviceWrapper) { - let device = admin_retry(device, "", 3); - let device = admin_retry(device, "123", 2); - let device = admin_retry(device, "456", 1); - let device = admin_retry(device, "", 3); - - let device = user_retry(device, "", 3); - let device = user_retry(device, "123", 2); - let device = user_retry(device, "456", 1); - user_retry(device, "", 3); -} - -#[test_device] -fn config(device: DeviceWrapper) { - 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)); - assert_ok!(config, admin.get_config()); - - let config = Config::new(None, Some(9), None, true); - assert_lib_err!(LibraryError::InvalidSlot, admin.write_config(config)); - - let config = Config::new(Some(1), None, Some(0), false); - assert_ok!((), admin.write_config(config)); - assert_ok!(config, admin.get_config()); - - let config = Config::new(None, None, None, false); - assert_ok!((), admin.write_config(config)); - assert_ok!(config, admin.get_config()); -} - -#[test_device] -fn change_user_pin(device: DeviceWrapper) { - let device = device.authenticate_user(DEFAULT_USER_PIN).unwrap().device(); - 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) - ); - - let device = device.authenticate_user(DEFAULT_USER_PIN).unwrap_err().0; - let device = device - .authenticate_user(USER_NEW_PASSWORD) - .unwrap() - .device(); - - 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, DEFAULT_USER_PIN) - ); - - 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(DEFAULT_ADMIN_PIN) - .unwrap() - .device(); - let mut device = device.authenticate_admin(ADMIN_NEW_PASSWORD).unwrap_err().0; - - assert_ok!( - (), - device.change_admin_pin(DEFAULT_ADMIN_PIN, ADMIN_NEW_PASSWORD) - ); - - 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(DEFAULT_ADMIN_PIN, DEFAULT_ADMIN_PIN) - ); - - assert_ok!( - (), - device.change_admin_pin(ADMIN_NEW_PASSWORD, DEFAULT_ADMIN_PIN) - ); - - let device = device - .authenticate_admin(DEFAULT_ADMIN_PIN) - .unwrap() - .device(); - device.authenticate_admin(ADMIN_NEW_PASSWORD).unwrap_err(); -} - -fn require_failed_user_login<'a, D>(device: D, password: &str, error: CommandError) -> D -where - D: Device<'a> + Authenticate<'a> + 'a, - nitrokey::User<'a, D>: std::fmt::Debug, -{ - let result = device.authenticate_user(password); - assert!(result.is_err()); - let err = result.unwrap_err(); - match err.1 { - Error::CommandError(err) => assert_eq!(error, err), - _ => assert!(false), - }; - err.0 -} - -#[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_cmd_err!( - CommandError::WrongPassword, - device.unlock_user_pin(DEFAULT_USER_PIN, DEFAULT_USER_PIN) - ); - - // block user PIN - 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 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) - ); - 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); - - // unblock with new 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, USER_NEW_PASSWORD) - ); - - // reset user PIN - 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 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 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(DEFAULT_USER_PIN, USER_NEW_PASSWORD) - ); - assert_ok!( - (), - device.change_admin_pin(DEFAULT_ADMIN_PIN, ADMIN_NEW_PASSWORD) - ); - - assert_cmd_err!( - CommandError::WrongPassword, - device.factory_reset(USER_NEW_PASSWORD) - ); - assert_cmd_err!( - CommandError::WrongPassword, - device.factory_reset(DEFAULT_ADMIN_PIN) - ); - assert_ok!((), device.factory_reset(ADMIN_NEW_PASSWORD)); - - 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)); - - 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!(3, device.get_user_retry_count()); - assert_ok!((), device.build_aes_key(DEFAULT_ADMIN_PIN)); -} - -#[test_device] -fn build_aes_key(device: DeviceWrapper) { - 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(DEFAULT_USER_PIN) - ); - assert_ok!((), device.build_aes_key(DEFAULT_ADMIN_PIN)); - - 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)); - 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) - ); - assert_ok!((), device.change_update_pin(UPDATE_PIN, UPDATE_NEW_PIN)); - assert_ok!((), device.change_update_pin(UPDATE_NEW_PIN, UPDATE_PIN)); -} - -#[test_device] -fn encrypted_volume(device: Storage) { - let mut device = device; - assert_ok!((), device.lock()); - - assert_eq!(1, count_nitrokey_block_devices()); - assert_ok!((), device.disable_encrypted_volume()); - assert_eq!(1, count_nitrokey_block_devices()); - assert_cmd_err!( - CommandError::WrongPassword, - device.enable_encrypted_volume("123") - ); - assert_eq!(1, count_nitrokey_block_devices()); - 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()); -} - -#[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(DEFAULT_USER_PIN)); - assert_eq!(2, count_nitrokey_block_devices()); - - // TODO: why this error code? - assert_cmd_err!( - CommandError::WrongPassword, - device.create_hidden_volume(5, 0, 100, "hiddenpw") - ); - assert_ok!((), device.create_hidden_volume(0, 20, 21, "hidden-pw")); - assert_ok!((), device.create_hidden_volume(0, 20, 21, "hiddenpassword")); - assert_ok!((), device.create_hidden_volume(1, 0, 1, "otherpw")); - // TODO: test invalid range (not handled by libnitrokey) - assert_eq!(2, count_nitrokey_block_devices()); - - assert_cmd_err!( - CommandError::WrongPassword, - device.enable_hidden_volume("blubb") - ); - assert_ok!((), device.enable_hidden_volume("hiddenpassword")); - assert_eq!(2, count_nitrokey_block_devices()); - assert_ok!((), device.enable_hidden_volume("otherpw")); - assert_eq!(2, count_nitrokey_block_devices()); - - assert_ok!((), device.disable_hidden_volume()); - assert_eq!(1, count_nitrokey_block_devices()); -} - -#[test_device] -fn lock(device: Storage) { - 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 = unwrap_ok!(device.get_status()); - assert_eq!( - status.unencrypted_volume.read_only, - mode == VolumeMode::ReadOnly - ); - } - - fn assert_success(device: &mut Storage, mode: VolumeMode) { - assert_ok!( - (), - device.set_unencrypted_volume_mode(DEFAULT_ADMIN_PIN, mode) - ); - assert_mode(&device, mode); - } - - let mut device = device; - assert_success(&mut device, VolumeMode::ReadOnly); - - assert_cmd_err!( - CommandError::WrongPassword, - device.set_unencrypted_volume_mode(DEFAULT_USER_PIN, VolumeMode::ReadOnly) - ); - assert_mode(&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 = 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 = 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); - assert!(info.sd_card.serial_number != 0); - assert!(info.sd_card.size > 0); - assert!(info.sd_card.manufacturing_year > 10); - assert!(info.sd_card.manufacturing_year < 100); - // TODO: month value is not valid atm - // assert!(info.sd_card.manufacturing_month < 12); - assert!(info.sd_card.oem != 0); - assert!(info.sd_card.manufacturer != 0); - - 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) { - 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(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 = unwrap_ok!(device.get_status()); - assert!(status.new_sd_card_found); - - assert_ok!((), device.clear_new_sd_card_warning(DEFAULT_ADMIN_PIN)); - - 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(DEFAULT_ADMIN_PIN)); - assert_ok!( - (), - device.set_unencrypted_volume_mode(DEFAULT_ADMIN_PIN, VolumeMode::ReadWrite) - ); - assert_ok!((), device.export_firmware(DEFAULT_ADMIN_PIN)); - assert_ok!( - (), - device.set_unencrypted_volume_mode(DEFAULT_ADMIN_PIN, VolumeMode::ReadOnly) - ); -} diff --git a/nitrokey/tests/lib.rs b/nitrokey/tests/lib.rs deleted file mode 100644 index 25aae0f..0000000 --- a/nitrokey/tests/lib.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (C) 2019 Robin Krahl <robin.krahl@ireas.org> -// SPDX-License-Identifier: MIT - -mod util; - -#[test] -fn get_library_version() { - let version = unwrap_ok!(nitrokey::get_library_version()); - - assert!(version.git.is_empty() || version.git.starts_with("v")); - assert!(version.major > 0); -} - -#[test] -fn take_manager() { - assert!(nitrokey::take().is_ok()); - - let result = nitrokey::take(); - assert!(result.is_ok()); - let result2 = nitrokey::take(); - match result2 { - Ok(_) => panic!("Expected error, got Ok(_)!"), - Err(nitrokey::Error::ConcurrentAccessError) => {} - Err(err) => panic!("Expected ConcurrentAccessError, got {}", err), - } - drop(result); - assert!(nitrokey::take().is_ok()); -} diff --git a/nitrokey/tests/otp.rs b/nitrokey/tests/otp.rs deleted file mode 100644 index 38cd8a9..0000000 --- a/nitrokey/tests/otp.rs +++ /dev/null @@ -1,287 +0,0 @@ -// Copyright (C) 2018-2019 Robin Krahl <robin.krahl@ireas.org> -// SPDX-License-Identifier: MIT - -mod util; - -use std::fmt::Debug; -use std::ops::DerefMut; - -use nitrokey::{ - Admin, Authenticate, CommandError, Config, ConfigureOtp, Device, GenerateOtp, LibraryError, - OtpMode, OtpSlotData, DEFAULT_ADMIN_PIN, DEFAULT_USER_PIN, -}; -use nitrokey_test::test as test_device; - -// test suite according to RFC 4226, Appendix D -static HOTP_SECRET: &str = "3132333435363738393031323334353637383930"; -static HOTP_CODES: &[&str] = &[ - "755224", "287082", "359152", "969429", "338314", "254676", "287922", "162583", "399871", - "520489", -]; - -// test suite according to RFC 6238, Appendix B -static TOTP_SECRET: &str = "3132333435363738393031323334353637383930"; -static TOTP_CODES: &[(u64, &[&str])] = &[ - (59, &["94287082", "37359152"]), - (1111111109, &["07081804"]), - (1111111111, &["14050471"]), - (1234567890, &["89005924"]), - (2000000000, &["69279037"]), - (20000000000, &["65353130"]), -]; - -#[derive(PartialEq)] -enum TotpTimestampSize { - U32, - U64, -} - -fn make_admin_test_device<'a, T>(device: T) -> Admin<'a, T> -where - T: Device<'a>, - (T, nitrokey::Error): Debug, -{ - unwrap_ok!(device.authenticate_admin(DEFAULT_ADMIN_PIN)) -} - -fn configure_hotp(admin: &mut dyn 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: &mut dyn 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)); - } - }); -} - -#[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)); - assert_ok!((), device.set_time(1546385382, true)); -} - -#[test_device] -fn hotp_no_pin(device: DeviceWrapper) { - let mut admin = make_admin_test_device(device); - let config = Config::new(None, None, None, false); - assert_ok!((), admin.write_config(config)); - - configure_hotp(&mut admin, 0); - check_hotp_codes(admin.deref_mut(), 0); - - configure_hotp(&mut admin, 5); - check_hotp_codes(admin.deref_mut(), 5); - - configure_hotp(&mut admin, 0); - check_hotp_codes(&mut admin.device(), 0); -} - -#[test_device] -fn hotp_pin(device: DeviceWrapper) { - let mut admin = make_admin_test_device(device); - let config = Config::new(None, None, None, true); - assert_ok!((), admin.write_config(config)); - - 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 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(); - 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 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); - assert_lib_err!( - LibraryError::InvalidSlot, - admin.write_hotp_slot(slot_data, 0) - ); - let slot_data = OtpSlotData::new(1, "test", "foobar", OtpMode::SixDigits); - assert_lib_err!( - LibraryError::InvalidHexString, - admin.write_hotp_slot(slot_data, 0) - ); - let code = admin.get_hotp_code(4); - assert_lib_err!(LibraryError::InvalidSlot, code); -} - -#[test_device] -fn hotp_erase(device: DeviceWrapper) { - 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); - assert_ok!((), admin.write_hotp_slot(slot_data, 0)); - let slot_data = OtpSlotData::new(2, "test2", HOTP_SECRET, OtpMode::SixDigits); - assert_ok!((), admin.write_hotp_slot(slot_data, 0)); - - assert_ok!((), admin.erase_hotp_slot(1)); - - 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_ok!("test2".to_string(), device.get_hotp_slot_name(2)); -} - -fn configure_totp(admin: &mut dyn 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: &mut dyn 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; - if is_u64 != (timestamp_size == TotpTimestampSize::U64) { - continue; - } - - assert_ok!((), device.set_time(time, true)); - let code = unwrap_ok!(device.get_totp_code(1)); - assert!( - code.contains(&code), - "Generated TOTP code {} for {}, but expected one of {}", - code, - base_time, - codes.join(", ") - ); - } -} - -#[test_device] -fn totp_no_pin(device: DeviceWrapper) { - let mut admin = make_admin_test_device(device); - let config = Config::new(None, None, None, false); - assert_ok!((), admin.write_config(config)); - - configure_totp(&mut admin, 1); - check_totp_codes(admin.deref_mut(), 1, TotpTimestampSize::U32); - - configure_totp(&mut admin, 2); - check_totp_codes(admin.deref_mut(), 2, 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 mut admin = make_admin_test_device(device); - let config = Config::new(None, None, None, false); - assert_ok!((), admin.write_config(config)); - - configure_totp(&mut admin, 1); - check_totp_codes(admin.deref_mut(), 1, TotpTimestampSize::U64); - - configure_totp(&mut admin, 2); - check_totp_codes(admin.deref_mut(), 2, TotpTimestampSize::U64); - - configure_totp(&mut admin, 1); - check_totp_codes(&mut admin.device(), 1, TotpTimestampSize::U64); -} - -#[test_device] -fn totp_pin(device: DeviceWrapper) { - let mut admin = make_admin_test_device(device); - let config = Config::new(None, None, None, true); - assert_ok!((), admin.write_config(config)); - - 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)); -} - -#[test_device] -// See comment for totp_no_pin_64. -fn totp_pin_64(device: Pro) { - let mut admin = make_admin_test_device(device); - let config = Config::new(None, None, None, true); - assert_ok!((), admin.write_config(config)); - - 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 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)); - - let device = admin.device(); - let result = device.get_totp_slot_name(1); - assert_ok!("test-totp", result); - let result = device.get_totp_slot_name(16); - assert_lib_err!(LibraryError::InvalidSlot, result); -} - -#[test_device] -fn totp_error(device: DeviceWrapper) { - 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); - assert_lib_err!( - LibraryError::InvalidSlot, - admin.write_totp_slot(slot_data, 0) - ); - let slot_data = OtpSlotData::new(4, "test", "foobar", OtpMode::SixDigits); - assert_lib_err!( - LibraryError::InvalidHexString, - admin.write_totp_slot(slot_data, 0) - ); - let code = admin.get_totp_code(20); - assert_lib_err!(LibraryError::InvalidSlot, code); -} - -#[test_device] -fn totp_erase(device: DeviceWrapper) { - 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); - assert_ok!((), admin.write_totp_slot(slot_data, 0)); - let slot_data = OtpSlotData::new(2, "test2", TOTP_SECRET, OtpMode::SixDigits); - assert_ok!((), admin.write_totp_slot(slot_data, 0)); - - assert_ok!((), admin.erase_totp_slot(1)); - - let device = admin.device(); - let result = device.get_totp_slot_name(1); - assert_cmd_err!(CommandError::SlotNotProgrammed, result); - let result = device.get_totp_code(1); - assert_cmd_err!(CommandError::SlotNotProgrammed, result); - - assert_ok!("test2".to_string(), device.get_totp_slot_name(2)); -} diff --git a/nitrokey/tests/pws.rs b/nitrokey/tests/pws.rs deleted file mode 100644 index 7169695..0000000 --- a/nitrokey/tests/pws.rs +++ /dev/null @@ -1,159 +0,0 @@ -// Copyright (C) 2018-2019 Robin Krahl <robin.krahl@ireas.org> -// SPDX-License-Identifier: MIT - -mod util; - -use std::ffi::CStr; - -use libc::{c_int, c_void, free}; -use nitrokey::{ - CommandError, Device, Error, GetPasswordSafe, LibraryError, PasswordSafe, DEFAULT_ADMIN_PIN, - DEFAULT_USER_PIN, SLOT_COUNT, -}; -use nitrokey_sys; -use nitrokey_test::test as test_device; - -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() { - return Err(Error::UnexpectedError); - } - let s = unsafe { CStr::from_ptr(ptr).to_string_lossy().into_owned() }; - unsafe { free(ptr as *mut c_void) }; - match s.is_empty() { - true => { - let error = unsafe { nitrokey_sys::NK_get_last_command_status() } as c_int; - match error { - 0 => Ok(s), - other => Err(Error::from(other)), - } - } - false => Ok(s), - } -} - -fn get_pws<'a, T>(device: &mut T) -> PasswordSafe<'_, 'a> -where - T: Device<'a>, -{ - 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(&(DEFAULT_USER_PIN.to_owned() + "123")) - ); - assert_any_ok!(device.get_password_safe(DEFAULT_USER_PIN)); - assert_cmd_err!( - CommandError::WrongPassword, - device.get_password_safe(DEFAULT_ADMIN_PIN) - ); - assert_any_ok!(device.get_password_safe(DEFAULT_USER_PIN)); -} - -#[test_device] -fn drop(device: DeviceWrapper) { - 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)); - let result = get_slot_name_direct(1); - assert_ok!(String::from("name"), result); - } - let result = get_slot_name_direct(1); - assert_ok!(String::from("name"), result); - assert_ok!((), device.lock()); - let result = get_slot_name_direct(1); - assert_cmd_err!(CommandError::NotAuthorized, result); -} - -#[test_device] -fn get_status(device: DeviceWrapper) { - 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 = 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 = unwrap_ok!(pws.get_slot_status()); - for i in 0..SLOT_COUNT { - assert_eq!(i == 1, status[i as usize]); - } - - for i in 0..SLOT_COUNT { - assert_ok!((), pws.write_slot(i, "name", "login", "password")); - } - assert_ok!([true; SLOT_COUNT as usize], pws.get_slot_status()); -} - -#[test_device] -fn get_data(device: DeviceWrapper) { - 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)); - 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)); - assert_cmd_err!(CommandError::SlotNotProgrammed, pws.get_slot_login(1)); - assert_cmd_err!(CommandError::SlotNotProgrammed, pws.get_slot_password(1)); - - let name = "with å"; - let login = "pär@test.com"; - let password = "'i3lJc[09?I:,[u7dWz9"; - 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)); - 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)); - assert_lib_err!(LibraryError::InvalidSlot, pws.get_slot_password(SLOT_COUNT)); -} - -#[test_device] -fn write(device: DeviceWrapper) { - let mut device = device; - let mut pws = get_pws(&mut device); - - assert_lib_err!( - LibraryError::InvalidSlot, - pws.write_slot(SLOT_COUNT, "name", "login", "password") - ); - - assert_ok!((), pws.write_slot(0, "", "login", "password")); - assert_cmd_err!(CommandError::SlotNotProgrammed, pws.get_slot_name(0)); - assert_ok!(String::from("login"), pws.get_slot_login(0)); - assert_ok!(String::from("password"), pws.get_slot_password(0)); - - assert_ok!((), pws.write_slot(0, "name", "", "password")); - assert_ok!(String::from("name"), pws.get_slot_name(0)); - assert_cmd_err!(CommandError::SlotNotProgrammed, pws.get_slot_login(0)); - assert_ok!(String::from("password"), pws.get_slot_password(0)); - - assert_ok!((), pws.write_slot(0, "name", "login", "")); - assert_ok!(String::from("name"), pws.get_slot_name(0)); - assert_ok!(String::from("login"), pws.get_slot_login(0)); - assert_cmd_err!(CommandError::SlotNotProgrammed, pws.get_slot_password(0)); -} - -#[test_device] -fn erase(device: DeviceWrapper) { - 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")); - assert_ok!((), pws.erase_slot(0)); - assert_ok!((), pws.erase_slot(0)); - assert_cmd_err!(CommandError::SlotNotProgrammed, pws.get_slot_name(0)); -} diff --git a/nitrokey/tests/util/mod.rs b/nitrokey/tests/util/mod.rs deleted file mode 100644 index f2b20ec..0000000 --- a/nitrokey/tests/util/mod.rs +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright (C) 2018-2019 Robin Krahl <robin.krahl@ireas.org> -// SPDX-License-Identifier: MIT - -#[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 { - ($left:expr, $right:expr) => {{ - match &$right { - Ok(right) => match &$left { - left => { - if !(*left == *right) { - panic!( - r#"assertion failed: `(left == right)` - left: `{:?}`, - right: `{:?}`"#, - left, right - ) - } - } - }, - Err(right_err) => panic!( - r#"assertion failed: `(left == right)` - left: `Ok({:?})`, - right: `Err({:?})`"#, - $left, right_err - ), - } - }}; -} - -#[macro_export] -macro_rules! assert_err { - ($err:path, $left:expr, $right:expr) => { - match &$right { - Err($err(ref right_err)) => match &$left { - left_err => { - if !(*left_err == *right_err) { - panic!( - r#"assertion failed: `(left == right)` - left: `{:?}`, - right: `{:?}`"#, - left_err, right_err - ) - } - } - }, - Err(ref right_err) => panic!( - r#"assertion failed: `(left == right)` - left: `{:?}`, - right: `{:?}`"#, - $err($left), - right_err - ), - Ok(right_ok) => panic!( - r#"assertion failed: `(left == right)` - left: `Err({:?})`, - right: `Ok({:?})`"#, - $err($left), - right_ok - ), - } - }; -} - -#[macro_export] -macro_rules! assert_cmd_err { - ($left:expr, $right:expr) => { - assert_err!(::nitrokey::Error::CommandError, $left, $right); - }; -} - -#[macro_export] -macro_rules! assert_cmu_err { - ($left:expr, $right:expr) => { - assert_err!(::nitrokey::Error::CommunicationError, $left, $right); - }; -} - -#[macro_export] -macro_rules! assert_lib_err { - ($left:expr, $right:expr) => { - assert_err!(::nitrokey::Error::LibraryError, $left, $right); - }; -} |