diff options
-rw-r--r-- | nitrocli/src/commands.rs | 15 | ||||
-rw-r--r-- | nitrocli/src/tests/otp.rs | 16 |
2 files changed, 29 insertions, 2 deletions
diff --git a/nitrocli/src/commands.rs b/nitrocli/src/commands.rs index eac8549..a65f070 100644 --- a/nitrocli/src/commands.rs +++ b/nitrocli/src/commands.rs @@ -646,7 +646,7 @@ fn prepare_base32_secret(secret: &str) -> Result<String> { /// Configure a one-time password slot on the Nitrokey device. pub fn otp_set( ctx: &mut args::ExecCtx<'_>, - data: nitrokey::OtpSlotData, + mut data: nitrokey::OtpSlotData, algorithm: args::OtpAlgorithm, counter: u64, time_window: u16, @@ -656,7 +656,18 @@ pub fn otp_set( let secret = match secret_format { args::OtpSecretFormat::Ascii => prepare_ascii_secret(&data.secret)?, args::OtpSecretFormat::Base32 => prepare_base32_secret(&data.secret)?, - args::OtpSecretFormat::Hex => data.secret, + args::OtpSecretFormat::Hex => { + // We need to ensure to provide a string with an even number of + // characters in it, just because that's what libnitrokey + // expects. So prepend a '0' if that is not the case. + // TODO: This code can be removed once upstream issue #164 + // (https://github.com/Nitrokey/libnitrokey/issues/164) is + // addressed. + if data.secret.len() % 2 != 0 { + data.secret.insert(0, '0') + } + data.secret + } }; let data = nitrokey::OtpSlotData { secret, ..data }; let device = authenticate_admin(ctx, device)?; diff --git a/nitrocli/src/tests/otp.rs b/nitrocli/src/tests/otp.rs index 39ddf29..531ed5f 100644 --- a/nitrocli/src/tests/otp.rs +++ b/nitrocli/src/tests/otp.rs @@ -19,6 +19,8 @@ use super::*; +use crate::args; + #[test_device] fn set_invalid_slot_raw(device: nitrokey::DeviceWrapper) { let (rc, out, err) = Nitrocli::with_dev(device).run(&["otp", "set", "100", "name", "1234"]); @@ -97,6 +99,20 @@ fn set_get_totp(device: nitrokey::DeviceWrapper) -> crate::Result<()> { } #[test_device] +fn set_totp_uneven_chars(device: nitrokey::DeviceWrapper) -> crate::Result<()> { + let secrets = [ + (args::OtpSecretFormat::Hex, "123"), + (args::OtpSecretFormat::Base32, "FBILDWWGA2"), + ]; + + let mut ncli = Nitrocli::with_dev(device); + for (format, secret) in &secrets { + let _ = ncli.handle(&["otp", "set", "-f", format.as_ref(), "3", "foobar", &secret])?; + } + Ok(()) +} + +#[test_device] fn clear(device: nitrokey::DeviceWrapper) -> crate::Result<()> { let mut ncli = Nitrocli::with_dev(device); let _ = ncli.handle(&["otp", "set", "3", "hotp-test", "abcdef"])?; |