From ad76653b3be57c0cfd31c8056a8d68537034324e Mon Sep 17 00:00:00 2001 From: Robin Krahl Date: Thu, 31 Jan 2019 11:07:50 +0000 Subject: Add set_encrypted_volume_mode method to Storage Previously, we considered this command as unsupported as it only was available with firmware version 0.49. But as discussed in nitrocli issue 80 [0], it will probably be re-enabled in future firmware versions. Therefore this patch adds the set_encrypted_volume_mode to Storage. [0] https://github.com/d-e-s-o/nitrocli/issues/80 --- CHANGELOG.md | 1 + README.md | 3 +-- src/device.rs | 47 ++++++++++++++++++++++++++++++++++++++++++++++- tests/device.rs | 30 ++++++++++++++++++++++++++++++ 4 files changed, 78 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c51727e..a9e3065 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,6 +33,7 @@ SPDX-License-Identifier: MIT - Fix timing issues with the `totp_no_pin` and `totp_pin` test cases. - Always return a `Result` in functions that communicate with a device. - Combine `get_{major,minor}_firmware_version` into `get_firmware_version`. +- Add `set_encrypted_volume_mode` to `Storage`. # v0.3.4 (2019-01-20) - Fix authentication methods that assumed that `char` is signed. diff --git a/README.md b/README.md index 069fed1..8c596eb 100644 --- a/README.md +++ b/README.md @@ -38,8 +38,7 @@ supported by `nitrokey-rs`: - `NK_is_AES_supported`. This method is no longer needed for Nitrokey devices with a recent firmware version. - `NK_set_unencrypted_volume_rorw_pin_type_user`, - `NK_set_unencrypted_read_only`, `NK_set_unencrypted_read_write`, - `NK_set_encrypted_read_only` and `NK_set_encrypted_read_write`. These + `NK_set_unencrypted_read_only`, `NK_set_unencrypted_read_write`. These methods are only relevant for older firmware versions (pre-v0.51). As the Nitrokey Storage firmware can be updated easily, we do not support these outdated versions. diff --git a/src/device.rs b/src/device.rs index d199d9a..c985802 100644 --- a/src/device.rs +++ b/src/device.rs @@ -1142,7 +1142,7 @@ impl Storage { /// /// # fn try_main() -> Result<(), Error> { /// let device = nitrokey::Storage::connect()?; - /// match device.set_unencrypted_volume_mode("123456", VolumeMode::ReadWrite) { + /// match device.set_unencrypted_volume_mode("12345678", VolumeMode::ReadWrite) { /// Ok(()) => println!("Set the unencrypted volume to read-write mode."), /// Err(err) => eprintln!("Could not set the unencrypted volume to read-write mode: {}", err), /// }; @@ -1169,6 +1169,51 @@ impl Storage { get_command_result(result) } + /// Sets the access mode of the encrypted volume. + /// + /// This command will reconnect the encrypted volume so buffers should be flushed before + /// calling it. It is only available in firmware version 0.49. + /// + /// # Errors + /// + /// - [`InvalidString`][] if the provided password contains a null byte + /// - [`WrongPassword`][] if the provided admin password is wrong + /// + /// # Example + /// + /// ```no_run + /// # use nitrokey::Error; + /// use nitrokey::VolumeMode; + /// + /// # fn try_main() -> Result<(), Error> { + /// let device = nitrokey::Storage::connect()?; + /// match device.set_encrypted_volume_mode("12345678", VolumeMode::ReadWrite) { + /// Ok(()) => println!("Set the encrypted volume to read-write mode."), + /// Err(err) => eprintln!("Could not set the encrypted volume to read-write mode: {}", err), + /// }; + /// # Ok(()) + /// # } + /// ``` + /// + /// [`InvalidString`]: enum.LibraryError.html#variant.InvalidString + /// [`WrongPassword`]: enum.CommandError.html#variant.WrongPassword + pub fn set_encrypted_volume_mode( + &self, + admin_pin: &str, + mode: VolumeMode, + ) -> Result<(), Error> { + let admin_pin = get_cstring(admin_pin)?; + let result = match mode { + VolumeMode::ReadOnly => unsafe { + nitrokey_sys::NK_set_encrypted_read_only(admin_pin.as_ptr()) + }, + VolumeMode::ReadWrite => unsafe { + nitrokey_sys::NK_set_encrypted_read_write(admin_pin.as_ptr()) + }, + }; + get_command_result(result) + } + /// Returns the status of the connected storage device. /// /// # Example diff --git a/tests/device.rs b/tests/device.rs index 306b33f..969a7df 100644 --- a/tests/device.rs +++ b/tests/device.rs @@ -401,6 +401,36 @@ fn lock(device: Storage) { 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(()). + + assert_ok!( + (), + device.set_encrypted_volume_mode(ADMIN_PASSWORD, VolumeMode::ReadOnly) + ); + + // TODO: re-enable once the password is checked in the firmware + // assert_cmd_err!( + // CommandError::WrongPassword, + // device.set_encrypted_volume_mode(USER_PASSWORD, VolumeMode::ReadOnly) + // ); + + assert_ok!( + (), + device.set_encrypted_volume_mode(ADMIN_PASSWORD, VolumeMode::ReadOnly) + ); + assert_ok!( + (), + device.set_encrypted_volume_mode(ADMIN_PASSWORD, VolumeMode::ReadWrite) + ); + assert_ok!( + (), + device.set_encrypted_volume_mode(ADMIN_PASSWORD, VolumeMode::ReadOnly) + ); +} + #[test_device] fn set_unencrypted_volume_mode(device: Storage) { fn assert_mode(device: &Storage, mode: VolumeMode) { -- cgit v1.2.3