diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/device.rs | 99 | ||||
| -rw-r--r-- | src/tests/device.rs | 50 | 
2 files changed, 149 insertions, 0 deletions
| diff --git a/src/device.rs b/src/device.rs index d6b9780..f901306 100644 --- a/src/device.rs +++ b/src/device.rs @@ -408,6 +408,30 @@ pub trait Device: Authenticate + GetPasswordSafe + GenerateOtp {              ))          }      } + +    /// Locks the Nitrokey device. +    /// +    /// This disables the password store if it has been unlocked.  On the Nitrokey Storage, this +    /// also disables the volumes if they have been enabled. +    /// +    /// # Example +    /// +    /// ```no_run +    /// use nitrokey::{CommandStatus, Device}; +    /// # use nitrokey::CommandError; +    /// +    /// # fn try_main() -> Result<(), CommandError> { +    /// let device = nitrokey::connect()?; +    /// match device.lock() { +    ///     CommandStatus::Success => println!("Locked the Nitrokey device."), +    ///     CommandStatus::Error(err) => println!("Could not lock the Nitrokey device: {:?}", err), +    /// }; +    /// #     Ok(()) +    /// # } +    /// ``` +    fn lock(&self) -> CommandStatus { +        unsafe { CommandStatus::from(nitrokey_sys::NK_lock_device()) } +    }  }  /// Connects to a Nitrokey device.  This method can be used to connect to any connected device, @@ -509,6 +533,81 @@ impl Storage {              false => Err(CommandError::Unknown),          }      } + +    /// Enables the encrypted storage volume. +    /// +    /// Once the encrypted volume is enabled, it is presented to the operating system as a block +    /// device.  The API does not provide any information on the name or path of this block device. +    /// +    /// # Errors +    /// +    /// - [`InvalidString`][] if the provided password contains a null byte +    /// - [`WrongPassword`][] if the provided user password is wrong +    /// +    /// # Example +    /// +    /// ```no_run +    /// use nitrokey::{CommandStatus}; +    /// # use nitrokey::CommandError; +    /// +    /// # fn try_main() -> Result<(), CommandError> { +    /// let device = nitrokey::Storage::connect()?; +    /// match device.enable_encrypted_volume("123456") { +    ///     CommandStatus::Success => println!("Enabled the encrypted volume."), +    ///     CommandStatus::Error(err) => println!("Could not enable the encrypted volume: {:?}", err), +    /// }; +    /// #     Ok(()) +    /// # } +    /// ``` +    /// +    /// [`InvalidString`]: enum.CommandError.html#variant.InvalidString +    /// [`WrongPassword`]: enum.CommandError.html#variant.WrongPassword +    pub fn enable_encrypted_volume(&self, user_pin: &str) -> CommandStatus { +        let user_pin = CString::new(user_pin); +        if user_pin.is_err() { +            return CommandStatus::Error(CommandError::InvalidString); +        } +        let user_pin = user_pin.unwrap(); +        unsafe { CommandStatus::from(nitrokey_sys::NK_unlock_encrypted_volume(user_pin.as_ptr())) } +    } + +    /// Disables the encrypted storage volume. +    /// +    /// Once the volume is disabled, it can be no longer accessed as a block device.  If the +    /// encrypted volume has not been enabled, this method still returns a success. +    /// +    /// # Example +    /// +    /// ```no_run +    /// use nitrokey::{CommandStatus}; +    /// # use nitrokey::CommandError; +    /// +    /// fn use_volume() {} +    /// +    /// # fn try_main() -> Result<(), CommandError> { +    /// let device = nitrokey::Storage::connect()?; +    /// match device.enable_encrypted_volume("123456") { +    ///     CommandStatus::Success => { +    ///         println!("Enabled the encrypted volume."); +    ///         use_volume(); +    ///         match device.disable_encrypted_volume() { +    ///             CommandStatus::Success => println!("Disabled the encrypted volume."), +    ///             CommandStatus::Err(err) => { +    ///                 println!("Could not disable the encrypted volume: {:?}", err); +    ///             }, +    ///         }; +    ///     }, +    ///     CommandStatus::Error(err) => println!("Could not enable the encrypted volume: {:?}", err), +    /// }; +    /// #     Ok(()) +    /// # } +    /// ``` +    /// +    /// [`InvalidString`]: enum.CommandError.html#variant.InvalidString +    /// [`WrongPassword`]: enum.CommandError.html#variant.WrongPassword +    pub fn disable_encrypted_volume(&self) -> CommandStatus { +        unsafe { CommandStatus::from(nitrokey_sys::NK_lock_encrypted_volume()) } +    }  }  impl Drop for Storage { diff --git a/src/tests/device.rs b/src/tests/device.rs index 68f1a39..7f7a819 100644 --- a/src/tests/device.rs +++ b/src/tests/device.rs @@ -1,10 +1,24 @@  use std::ffi::CStr; +use std::process::Command; +use std::{thread, time};  use tests::util::{Target, ADMIN_PASSWORD, USER_PASSWORD};  use {Authenticate, CommandError, CommandStatus, Config, Device};  static ADMIN_NEW_PASSWORD: &str = "1234567890";  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 == "Nitrokey Storage") +        .count() +} +  #[test]  #[cfg_attr(not(feature = "test-no-device"), ignore)]  fn connect_no_device() { @@ -227,3 +241,39 @@ fn unlock_user_pin() {      );      device.authenticate_user(USER_PASSWORD).unwrap();  } + +#[test] +#[cfg_attr(not(feature = "test-storage"), ignore)] +fn encrypted_volume() { +    let device = Target::connect().unwrap(); +    assert_eq!(CommandStatus::Success, device.lock()); + +    assert_eq!(1, count_nitrokey_block_devices()); +    assert_eq!(CommandStatus::Success, device.disable_encrypted_volume()); +    assert_eq!(1, count_nitrokey_block_devices()); +    assert_eq!( +        CommandStatus::Error(CommandError::WrongPassword), +        device.enable_encrypted_volume("123") +    ); +    assert_eq!(1, count_nitrokey_block_devices()); +    assert_eq!( +        CommandStatus::Success, +        device.enable_encrypted_volume(USER_PASSWORD) +    ); +    assert_eq!(2, count_nitrokey_block_devices()); +    assert_eq!(CommandStatus::Success, device.disable_encrypted_volume()); +    assert_eq!(1, count_nitrokey_block_devices()); +} + +#[test] +#[cfg_attr(not(feature = "test-storage"), ignore)] +fn lock() { +    let device = Target::connect().unwrap(); + +    assert_eq!( +        CommandStatus::Success, +        device.enable_encrypted_volume(USER_PASSWORD) +    ); +    assert_eq!(CommandStatus::Success, device.lock()); +    assert_eq!(1, count_nitrokey_block_devices()); +} | 
