From 52afed9c6a17ec9c120a5a91b445afa74be87f0e Mon Sep 17 00:00:00 2001 From: Robin Krahl Date: Tue, 1 Jan 2019 23:38:14 +0000 Subject: Add force argument to ConfigureOtp::set_time This patch adds the force argument to the set_time method in the ConfigureOtp trait that allows the user to choose whether jumps to the past are allowed when updating the time. It is implemented by using the NK_totp_set_time_soft function. Previously, jumps where unconditionally allowed. --- CHANGELOG.md | 3 +++ TODO.md | 1 - src/otp.rs | 33 +++++++++++++++++++-------------- tests/otp.rs | 12 +++++++++++- 4 files changed, 33 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5064d4f..34f9ac9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +# Unreleased +- Add a `force` argument to `ConfigureOtp::set_time`. + # v0.2.3 (2018-12-31) - Dummy release to fix an issue with the crates.io tarball. diff --git a/TODO.md b/TODO.md index 6086ad8..16ec558 100644 --- a/TODO.md +++ b/TODO.md @@ -27,7 +27,6 @@ - `NK_get_major_library_version` - `NK_get_minor_libray_version` - `NK_get_storage_production_info` - - `NK_totp_set_time_soft` - `NK_wink` - Fix timing issues with the `totp_no_pin` and `totp_pin` test cases. - Clear passwords from memory. diff --git a/src/otp.rs b/src/otp.rs index 6f6bd80..9f0a388 100644 --- a/src/otp.rs +++ b/src/otp.rs @@ -151,27 +151,27 @@ pub trait ConfigureOtp { /// Provides methods to generate OTP codes and to query OTP slots on a Nitrokey /// device. pub trait GenerateOtp { - /// Sets the time on the Nitrokey. This command may set the time to arbitrary values. `time` - /// is the number of seconds since January 1st, 1970 (Unix timestamp). + /// Sets the time on the Nitrokey. + /// + /// `time` is the number of seconds since January 1st, 1970 (Unix timestamp). Unless `force` + /// is set to `true`, this command fails if the timestamp on the device is larger than the + /// given timestamp or if it is zero. /// /// The time is used for TOTP generation (see [`get_totp_code`][]). /// /// # Example /// - /// ```ignore - /// extern crate chrono; - /// - /// use chrono::Utc; - /// use nitrokey::Device; + /// ```no_run + /// use std::time; + /// use nitrokey::GenerateOtp; /// # use nitrokey::CommandError; /// /// # fn try_main() -> Result<(), CommandError> { /// let device = nitrokey::connect()?; - /// let time = Utc::now().timestamp(); - /// if time < 0 { - /// println!("Timestamps before 1970-01-01 are not supported!"); - /// } else { - /// device.set_time(time as u64); + /// let time = time::SystemTime::now().duration_since(time::UNIX_EPOCH); + /// match time { + /// Ok(time) => device.set_time(time.as_secs(), false)?, + /// Err(_) => println!("The system time is before the Unix epoch!"), /// } /// # Ok(()) /// # } @@ -183,8 +183,13 @@ pub trait GenerateOtp { /// /// [`get_totp_code`]: #method.get_totp_code /// [`Timestamp`]: enum.CommandError.html#variant.Timestamp - fn set_time(&self, time: u64) -> Result<(), CommandError> { - unsafe { get_command_result(nitrokey_sys::NK_totp_set_time(time)) } + fn set_time(&self, time: u64, force: bool) -> Result<(), CommandError> { + let result = if force { + unsafe { nitrokey_sys::NK_totp_set_time(time) } + } else { + unsafe { nitrokey_sys::NK_totp_set_time_soft(time) } + }; + get_command_result(result) } /// Returns the name of the given HOTP slot. diff --git a/tests/otp.rs b/tests/otp.rs index 8e7ae08..c7d6e68 100644 --- a/tests/otp.rs +++ b/tests/otp.rs @@ -53,6 +53,16 @@ fn check_hotp_codes(device: &GenerateOtp, offset: u8) { }); } +#[test] +#[cfg_attr(not(any(feature = "test-pro", feature = "test-storage")), ignore)] +fn set_time() { + let device = Target::connect().expect("Could not connect to the Nitrokey."); + assert_eq!(Ok(()), device.set_time(1546385382, true)); + assert_eq!(Ok(()), device.set_time(1546385392, false)); + assert_eq!(Err(CommandError::Timestamp), device.set_time(1546385292, false)); + assert_eq!(Ok(()), device.set_time(1546385382, true)); +} + #[test] #[cfg_attr(not(any(feature = "test-pro", feature = "test-storage")), ignore)] fn hotp_no_pin() { @@ -152,7 +162,7 @@ fn check_totp_codes(device: &GenerateOtp, factor: u64, timestamp_size: TotpTimes continue; } - assert!(device.set_time(time).is_ok()); + assert!(device.set_time(time, true).is_ok()); let result = device.get_totp_code(1); assert!(result.is_ok()); let result_code = result.unwrap(); -- cgit v1.2.1