aboutsummaryrefslogtreecommitdiff
path: root/nitrokey/src/device.rs
diff options
context:
space:
mode:
Diffstat (limited to 'nitrokey/src/device.rs')
-rw-r--r--nitrokey/src/device.rs153
1 files changed, 149 insertions, 4 deletions
diff --git a/nitrokey/src/device.rs b/nitrokey/src/device.rs
index 9c6608d..78d0d82 100644
--- a/nitrokey/src/device.rs
+++ b/nitrokey/src/device.rs
@@ -510,6 +510,74 @@ pub trait Device: Authenticate + GetPasswordSafe + GenerateOtp {
fn lock(&self) -> Result<(), CommandError> {
unsafe { get_command_result(nitrokey_sys::NK_lock_device()) }
}
+
+ /// Performs a factory reset on the Nitrokey device.
+ ///
+ /// This commands performs a factory reset on the smart card (like the factory reset via `gpg
+ /// --card-edit`) and then clears the flash memory (password safe, one-time passwords etc.).
+ /// After a factory reset, [`build_aes_key`][] has to be called before the password safe or the
+ /// encrypted volume can be used.
+ ///
+ /// # Errors
+ ///
+ /// - [`InvalidString`][] if the provided password contains a null byte
+ /// - [`WrongPassword`][] if the admin password is wrong
+ ///
+ /// # Example
+ ///
+ /// ```no_run
+ /// use nitrokey::Device;
+ /// # use nitrokey::CommandError;
+ ///
+ /// # fn try_main() -> Result<(), CommandError> {
+ /// let device = nitrokey::connect()?;
+ /// match device.factory_reset("12345678") {
+ /// Ok(()) => println!("Performed a factory reset."),
+ /// Err(err) => println!("Could not perform a factory reset: {}", err),
+ /// };
+ /// # Ok(())
+ /// # }
+ /// ```
+ ///
+ /// [`build_aes_key`]: #method.build_aes_key
+ fn factory_reset(&self, admin_pin: &str) -> Result<(), CommandError> {
+ let admin_pin_string = get_cstring(admin_pin)?;
+ unsafe { get_command_result(nitrokey_sys::NK_factory_reset(admin_pin_string.as_ptr())) }
+ }
+
+ /// Builds a new AES key on the Nitrokey.
+ ///
+ /// The AES key is used to encrypt the password safe and the encrypted volume. You may need
+ /// to call this method after a factory reset, either using [`factory_reset`][] or using `gpg
+ /// --card-edit`. You can also use it to destory the data stored in the password safe or on
+ /// the encrypted volume.
+ ///
+ /// # Errors
+ ///
+ /// - [`InvalidString`][] if the provided password contains a null byte
+ /// - [`WrongPassword`][] if the admin password is wrong
+ ///
+ /// # Example
+ ///
+ /// ```no_run
+ /// use nitrokey::Device;
+ /// # use nitrokey::CommandError;
+ ///
+ /// # fn try_main() -> Result<(), CommandError> {
+ /// let device = nitrokey::connect()?;
+ /// match device.build_aes_key("12345678") {
+ /// Ok(()) => println!("New AES keys have been built."),
+ /// Err(err) => println!("Could not build new AES keys: {}", err),
+ /// };
+ /// # Ok(())
+ /// # }
+ /// ```
+ ///
+ /// [`factory_reset`]: #method.factory_reset
+ fn build_aes_key(&self, admin_pin: &str) -> Result<(), CommandError> {
+ let admin_pin_string = get_cstring(admin_pin)?;
+ unsafe { get_command_result(nitrokey_sys::NK_build_aes_key(admin_pin_string.as_ptr())) }
+ }
}
/// Connects to a Nitrokey device. This method can be used to connect to any connected device,
@@ -532,9 +600,9 @@ pub fn connect() -> Result<DeviceWrapper, CommandError> {
match nitrokey_sys::NK_login_auto() {
1 => match get_connected_device() {
Some(wrapper) => Ok(wrapper),
- None => Err(CommandError::Unknown),
+ None => Err(CommandError::Undefined),
},
- _ => Err(CommandError::Unknown),
+ _ => Err(CommandError::Undefined),
}
}
}
@@ -623,7 +691,7 @@ impl Pro {
// TODO: maybe Option instead of Result?
match connect_model(Model::Pro) {
true => Ok(Pro {}),
- false => Err(CommandError::Unknown),
+ false => Err(CommandError::Undefined),
}
}
}
@@ -663,7 +731,84 @@ impl Storage {
// TODO: maybe Option instead of Result?
match connect_model(Model::Storage) {
true => Ok(Storage {}),
- false => Err(CommandError::Unknown),
+ false => Err(CommandError::Undefined),
+ }
+ }
+
+ /// Changes the update PIN.
+ ///
+ /// The update PIN is used to enable firmware updates. Unlike the user and the admin PIN, the
+ /// update PIN is not managed by the OpenPGP smart card but by the Nitrokey firmware. There is
+ /// no retry counter as with the other PIN types.
+ ///
+ /// # Errors
+ ///
+ /// - [`InvalidString`][] if one of the provided passwords contains a null byte
+ /// - [`WrongPassword`][] if the current update password is wrong
+ ///
+ /// # Example
+ ///
+ /// ```no_run
+ /// # use nitrokey::CommandError;
+ ///
+ /// # fn try_main() -> Result<(), CommandError> {
+ /// let device = nitrokey::Storage::connect()?;
+ /// match device.change_update_pin("12345678", "87654321") {
+ /// Ok(()) => println!("Updated update PIN."),
+ /// Err(err) => println!("Failed to update update PIN: {}", err),
+ /// };
+ /// # Ok(())
+ /// # }
+ /// ```
+ ///
+ /// [`InvalidString`]: enum.CommandError.html#variant.InvalidString
+ /// [`WrongPassword`]: enum.CommandError.html#variant.WrongPassword
+ pub fn change_update_pin(&self, current: &str, new: &str) -> Result<(), CommandError> {
+ let current_string = get_cstring(current)?;
+ let new_string = get_cstring(new)?;
+ unsafe {
+ get_command_result(nitrokey_sys::NK_change_update_password(
+ current_string.as_ptr(),
+ new_string.as_ptr(),
+ ))
+ }
+ }
+
+ /// Enables the firmware update mode.
+ ///
+ /// During firmware update mode, the Nitrokey can no longer be accessed using HID commands.
+ /// To resume normal operation, run `dfu-programmer at32uc3a3256s launch`. In order to enter
+ /// the firmware update mode, you need the update password that can be changed using the
+ /// [`change_update_pin`][] method.
+ ///
+ /// # Errors
+ ///
+ /// - [`InvalidString`][] if one of the provided passwords contains a null byte
+ /// - [`WrongPassword`][] if the current update password is wrong
+ ///
+ /// # Example
+ ///
+ /// ```no_run
+ /// # use nitrokey::CommandError;
+ ///
+ /// # fn try_main() -> Result<(), CommandError> {
+ /// let device = nitrokey::Storage::connect()?;
+ /// match device.enable_firmware_update("12345678") {
+ /// Ok(()) => println!("Nitrokey entered update mode."),
+ /// Err(err) => println!("Could not enter update mode: {}", err),
+ /// };
+ /// # Ok(())
+ /// # }
+ /// ```
+ ///
+ /// [`InvalidString`]: enum.CommandError.html#variant.InvalidString
+ /// [`WrongPassword`]: enum.CommandError.html#variant.WrongPassword
+ pub fn enable_firmware_update(&self, update_pin: &str) -> Result<(), CommandError> {
+ let update_pin_string = get_cstring(update_pin)?;
+ unsafe {
+ get_command_result(nitrokey_sys::NK_enable_firmware_update(
+ update_pin_string.as_ptr(),
+ ))
}
}