diff options
Diffstat (limited to 'nitrokey/tests/device.rs')
-rw-r--r-- | nitrokey/tests/device.rs | 496 |
1 files changed, 0 insertions, 496 deletions
diff --git a/nitrokey/tests/device.rs b/nitrokey/tests/device.rs deleted file mode 100644 index 849d2ff..0000000 --- a/nitrokey/tests/device.rs +++ /dev/null @@ -1,496 +0,0 @@ -mod util; - -use std::ffi::CStr; -use std::process::Command; -use std::{thread, time}; - -use nitrokey::{ - Authenticate, CommandError, Config, ConfigureOtp, Device, GenerateOtp, GetPasswordSafe, - OtpMode, OtpSlotData, Storage, VolumeMode, -}; -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"; -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() { - assert!(nitrokey::connect().is_err()); - assert!(nitrokey::connect_model(nitrokey::Model::Pro).is_err()); - assert!(nitrokey::connect_model(nitrokey::Model::Storage).is_err()); - assert!(nitrokey::Pro::connect().is_err()); - assert!(nitrokey::Storage::connect().is_err()); -} - -#[test_device] -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()); -} - -#[test_device] -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()); -} - -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 result = device.get_serial_number(); - assert!(result.is_ok()); - let serial_number = result.unwrap(); - 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); -} - -fn admin_retry<T: Authenticate + Device>(device: T, suffix: &str, count: u8) -> T { - let result = device.authenticate_admin(&(ADMIN_PASSWORD.to_owned() + suffix)); - let device = match result { - Ok(admin) => admin.device(), - Err((device, _)) => device, - }; - assert_eq!(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 device = match result { - Ok(admin) => admin.device(), - Err((device, _)) => device, - }; - assert_eq!(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 admin = device.authenticate_admin(ADMIN_PASSWORD).unwrap(); - let config = Config::new(None, None, None, true); - assert_eq!(Ok(()), admin.write_config(config)); - let get_config = admin.get_config().unwrap(); - assert_eq!(config, get_config); - - let config = Config::new(None, Some(9), None, true); - assert_eq!(Err(CommandError::InvalidSlot), admin.write_config(config)); - - let config = Config::new(Some(1), None, Some(0), false); - assert_eq!(Ok(()), admin.write_config(config)); - let get_config = admin.get_config().unwrap(); - assert_eq!(config, get_config); - - let config = Config::new(None, None, None, false); - assert_eq!(Ok(()), admin.write_config(config)); - let get_config = admin.get_config().unwrap(); - assert_eq!(config, get_config); -} - -#[test_device] -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; - - assert!(device - .change_user_pin(USER_PASSWORD, USER_NEW_PASSWORD) - .is_ok()); - - let device = device.authenticate_user(USER_PASSWORD).unwrap_err().0; - let device = device - .authenticate_user(USER_NEW_PASSWORD) - .unwrap() - .device(); - - let result = device.change_user_pin(USER_PASSWORD, USER_PASSWORD); - assert_eq!(Err(CommandError::WrongPassword), result); - - assert!(device - .change_user_pin(USER_NEW_PASSWORD, USER_PASSWORD) - .is_ok()); - - let device = device.authenticate_user(USER_PASSWORD).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; - - assert!(device - .change_admin_pin(ADMIN_PASSWORD, ADMIN_NEW_PASSWORD) - .is_ok()); - - let device = device.authenticate_admin(ADMIN_PASSWORD).unwrap_err().0; - let device = device - .authenticate_admin(ADMIN_NEW_PASSWORD) - .unwrap() - .device(); - - assert_eq!( - Err(CommandError::WrongPassword), - device.change_admin_pin(ADMIN_PASSWORD, ADMIN_PASSWORD) - ); - - assert!(device - .change_admin_pin(ADMIN_NEW_PASSWORD, ADMIN_PASSWORD) - .is_ok()); - - let device = device.authenticate_admin(ADMIN_PASSWORD).unwrap().device(); - device.authenticate_admin(ADMIN_NEW_PASSWORD).unwrap_err(); -} - -fn require_failed_user_login<D>(device: D, password: &str, error: CommandError) -> D -where - D: Device + Authenticate, - nitrokey::User<D>: std::fmt::Debug, -{ - let result = device.authenticate_user(password); - assert!(result.is_err()); - let err = result.unwrap_err(); - assert_eq!(error, err.1); - err.0 -} - -#[test_device] -fn unlock_user_pin(device: DeviceWrapper) { - let device = device.authenticate_user(USER_PASSWORD).unwrap().device(); - assert!(device - .unlock_user_pin(ADMIN_PASSWORD, USER_PASSWORD) - .is_ok()); - assert_eq!( - Err(CommandError::WrongPassword), - device.unlock_user_pin(USER_PASSWORD, USER_PASSWORD) - ); - - // block user PIN - let wrong_password = USER_PASSWORD.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); - - // unblock with current PIN - assert_eq!( - Err(CommandError::WrongPassword), - device.unlock_user_pin(USER_PASSWORD, USER_PASSWORD) - ); - assert!(device - .unlock_user_pin(ADMIN_PASSWORD, USER_PASSWORD) - .is_ok()); - let device = device.authenticate_user(USER_PASSWORD).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); - - // unblock with new PIN - assert_eq!( - Err(CommandError::WrongPassword), - device.unlock_user_pin(USER_PASSWORD, USER_PASSWORD) - ); - assert!(device - .unlock_user_pin(ADMIN_PASSWORD, USER_NEW_PASSWORD) - .is_ok()); - - // reset user PIN - assert!(device - .change_user_pin(USER_NEW_PASSWORD, USER_PASSWORD) - .is_ok()); -} - -#[test_device] -fn factory_reset(device: DeviceWrapper) { - let admin = device.authenticate_admin(ADMIN_PASSWORD).unwrap(); - let otp_data = OtpSlotData::new(1, "test", "0123468790", OtpMode::SixDigits); - assert_eq!(Ok(()), admin.write_totp_slot(otp_data, 30)); - - let device = admin.device(); - let pws = device.get_password_safe(USER_PASSWORD).unwrap(); - assert_eq!(Ok(()), pws.write_slot(0, "test", "testlogin", "testpw")); - drop(pws); - - assert_eq!( - Ok(()), - device.change_user_pin(USER_PASSWORD, USER_NEW_PASSWORD) - ); - assert_eq!( - Ok(()), - device.change_admin_pin(ADMIN_PASSWORD, ADMIN_NEW_PASSWORD) - ); - - assert_eq!( - Err(CommandError::WrongPassword), - device.factory_reset(USER_NEW_PASSWORD) - ); - assert_eq!( - Err(CommandError::WrongPassword), - device.factory_reset(ADMIN_PASSWORD) - ); - assert_eq!(Ok(()), device.factory_reset(ADMIN_NEW_PASSWORD)); - - let device = device.authenticate_admin(ADMIN_PASSWORD).unwrap().device(); - - let user = device.authenticate_user(USER_PASSWORD).unwrap(); - assert_eq!( - 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()); - - assert_eq!(Ok(()), device.build_aes_key(ADMIN_PASSWORD)); -} - -#[test_device] -fn build_aes_key(device: DeviceWrapper) { - let pws = device.get_password_safe(USER_PASSWORD).unwrap(); - assert_eq!(Ok(()), pws.write_slot(0, "test", "testlogin", "testpw")); - drop(pws); - - assert_eq!( - Err(CommandError::WrongPassword), - device.build_aes_key(USER_PASSWORD) - ); - assert_eq!(Ok(()), device.build_aes_key(ADMIN_PASSWORD)); - - let device = device.authenticate_admin(ADMIN_PASSWORD).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()); -} - -#[test_device] -fn change_update_pin(device: Storage) { - assert_eq!( - Err(CommandError::WrongPassword), - device.change_update_pin(UPDATE_NEW_PIN, UPDATE_PIN) - ); - assert_eq!(Ok(()), device.change_update_pin(UPDATE_PIN, UPDATE_NEW_PIN)); - assert_eq!(Ok(()), device.change_update_pin(UPDATE_NEW_PIN, UPDATE_PIN)); -} - -#[test_device] -fn encrypted_volume(device: Storage) { - assert_eq!(Ok(()), device.lock()); - - assert_eq!(1, count_nitrokey_block_devices()); - assert_eq!(Ok(()), device.disable_encrypted_volume()); - assert_eq!(1, count_nitrokey_block_devices()); - assert_eq!( - Err(CommandError::WrongPassword), - device.enable_encrypted_volume("123") - ); - assert_eq!(1, count_nitrokey_block_devices()); - assert_eq!(Ok(()), device.enable_encrypted_volume(USER_PASSWORD)); - assert_eq!(2, count_nitrokey_block_devices()); - assert_eq!(Ok(()), device.disable_encrypted_volume()); - assert_eq!(1, count_nitrokey_block_devices()); -} - -#[test_device] -fn hidden_volume(device: Storage) { - assert_eq!(Ok(()), device.lock()); - - assert_eq!(1, count_nitrokey_block_devices()); - assert_eq!(Ok(()), device.disable_hidden_volume()); - assert_eq!(1, count_nitrokey_block_devices()); - - assert_eq!(Ok(()), device.enable_encrypted_volume(USER_PASSWORD)); - assert_eq!(2, count_nitrokey_block_devices()); - - // TODO: why this error code? - assert_eq!( - Err(CommandError::WrongPassword), - device.create_hidden_volume(5, 0, 100, "hiddenpw") - ); - assert_eq!(Ok(()), device.create_hidden_volume(0, 20, 21, "hidden-pw")); - assert_eq!( - Ok(()), - device.create_hidden_volume(0, 20, 21, "hiddenpassword") - ); - assert_eq!(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_eq!( - Err(CommandError::WrongPassword), - device.enable_hidden_volume("blubb") - ); - assert_eq!(Ok(()), device.enable_hidden_volume("hiddenpassword")); - assert_eq!(2, count_nitrokey_block_devices()); - assert_eq!(Ok(()), device.enable_hidden_volume("otherpw")); - assert_eq!(2, count_nitrokey_block_devices()); - - assert_eq!(Ok(()), device.disable_hidden_volume()); - assert_eq!(1, count_nitrokey_block_devices()); -} - -#[test_device] -fn lock(device: Storage) { - assert_eq!(Ok(()), device.enable_encrypted_volume(USER_PASSWORD)); - assert_eq!(Ok(()), device.lock()); - assert_eq!(1, count_nitrokey_block_devices()); -} - -#[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()); - assert_eq!( - status.unwrap().unencrypted_volume.read_only, - mode == VolumeMode::ReadOnly - ); - } - - fn assert_success(device: &Storage, mode: VolumeMode) { - assert_eq!( - Ok(()), - device.set_unencrypted_volume_mode(ADMIN_PASSWORD, mode) - ); - assert_mode(&device, mode); - } - - assert_success(&device, VolumeMode::ReadOnly); - - assert_eq!( - Err(CommandError::WrongPassword), - device.set_unencrypted_volume_mode(USER_PASSWORD, VolumeMode::ReadOnly) - ); - assert_mode(&device, VolumeMode::ReadOnly); - - assert_success(&device, VolumeMode::ReadWrite); - assert_success(&device, VolumeMode::ReadWrite); - assert_success(&device, VolumeMode::ReadOnly); -} - -#[test_device] -fn get_storage_status(device: Storage) { - let status = device.get_status().unwrap(); - - 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(); - 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 = device.get_status().unwrap(); - assert_eq!(status.firmware_version_major, info.firmware_version_major); - assert_eq!(status.firmware_version_minor, info.firmware_version_minor); - assert_eq!(status.serial_number_sd_card, info.sd_card.serial_number); -} - -#[test_device] -fn clear_new_sd_card_warning(device: Storage) { - assert_eq!(Ok(()), device.factory_reset(ADMIN_PASSWORD)); - thread::sleep(time::Duration::from_secs(3)); - assert_eq!(Ok(()), device.build_aes_key(ADMIN_PASSWORD)); - - // We have to perform an SD card operation to reset the new_sd_card_found field - assert_eq!(Ok(()), device.lock()); - - let status = device.get_status().unwrap(); - assert!(status.new_sd_card_found); - - assert_eq!(Ok(()), device.clear_new_sd_card_warning(ADMIN_PASSWORD)); - - let status = device.get_status().unwrap(); - assert!(!status.new_sd_card_found); -} - -#[test_device] -fn export_firmware(device: Storage) { - assert_eq!( - Err(CommandError::WrongPassword), - device.export_firmware("someadminpn") - ); - assert_eq!(Ok(()), device.export_firmware(ADMIN_PASSWORD)); - assert_eq!( - Ok(()), - device.set_unencrypted_volume_mode(ADMIN_PASSWORD, VolumeMode::ReadWrite) - ); - assert_eq!(Ok(()), device.export_firmware(ADMIN_PASSWORD)); - assert_eq!( - Ok(()), - device.set_unencrypted_volume_mode(ADMIN_PASSWORD, VolumeMode::ReadOnly) - ); -} |