summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--nitrocli/src/args.rs6
-rw-r--r--nitrocli/src/tests/otp.rs72
2 files changed, 75 insertions, 3 deletions
diff --git a/nitrocli/src/args.rs b/nitrocli/src/args.rs
index b15ca65..789001e 100644
--- a/nitrocli/src/args.rs
+++ b/nitrocli/src/args.rs
@@ -463,7 +463,7 @@ fn otp_get(ctx: &mut ExecCtx<'_>, args: Vec<String>) -> Result<()> {
let _ = parser.refer(&mut algorithm).add_option(
&["-a", "--algorithm"],
argparse::Store,
- "The OTP algorithm to use (hotp|totp)",
+ "The OTP algorithm to use (hotp|totp, default: totp)",
);
let _ = parser.refer(&mut time).add_option(
&["-t", "--time"],
@@ -497,7 +497,7 @@ pub fn otp_set(ctx: &mut ExecCtx<'_>, args: Vec<String>) -> Result<()> {
let _ = parser.refer(&mut algorithm).add_option(
&["-a", "--algorithm"],
argparse::Store,
- "The OTP algorithm to use (hotp or totp, default: totp)",
+ "The OTP algorithm to use (hotp|totp, default: totp)",
);
let _ = parser.refer(&mut name).required().add_argument(
"name",
@@ -577,7 +577,7 @@ fn otp_clear(ctx: &mut ExecCtx<'_>, args: Vec<String>) -> Result<()> {
let _ = parser.refer(&mut algorithm).add_option(
&["-a", "--algorithm"],
argparse::Store,
- "The OTP algorithm to use (hotp|totp)",
+ "The OTP algorithm to use (hotp|totp, default: totp)",
);
parse(ctx, &parser, args)?;
drop(parser);
diff --git a/nitrocli/src/tests/otp.rs b/nitrocli/src/tests/otp.rs
index 403cc80..d99a6f8 100644
--- a/nitrocli/src/tests/otp.rs
+++ b/nitrocli/src/tests/otp.rs
@@ -40,3 +40,75 @@ fn set_invalid_slot(device: nitrokey::DeviceWrapper) {
)
);
}
+
+#[test_device]
+fn status(device: nitrokey::DeviceWrapper) -> crate::Result<()> {
+ let re = regex::Regex::new(
+ r#"^alg\tslot\tname
+((totp|hotp)\t\d+\t.+\n)+$"#,
+ )
+ .unwrap();
+
+ let mut ncli = Nitrocli::with_dev(device);
+ // Make sure that we have at least something to display by ensuring
+ // that there are there is one slot programmed.
+ let _ = ncli.handle(&["otp", "set", "0", "the-name", "123456"])?;
+
+ let out = ncli.handle(&["otp", "status"])?;
+ assert!(re.is_match(&out), out);
+ Ok(())
+}
+
+#[test_device]
+fn set_get_hotp(device: nitrokey::DeviceWrapper) -> crate::Result<()> {
+ // Secret and expected HOTP values as per RFC 4226: Appendix D -- HOTP
+ // Algorithm: Test Values.
+ const SECRET: &str = "12345678901234567890";
+ const OTP1: &str = concat!(755224, "\n");
+ const OTP2: &str = concat!(287082, "\n");
+
+ let mut ncli = Nitrocli::with_dev(device);
+ let _ = ncli.handle(&[
+ "otp", "set", "-a", "hotp", "-f", "ascii", "1", "name", &SECRET,
+ ])?;
+
+ let out = ncli.handle(&["otp", "get", "-a", "hotp", "1"])?;
+ assert_eq!(out, OTP1);
+
+ let out = ncli.handle(&["otp", "get", "-a", "hotp", "1"])?;
+ assert_eq!(out, OTP2);
+ Ok(())
+}
+
+#[test_device]
+fn set_get_totp(device: nitrokey::DeviceWrapper) -> crate::Result<()> {
+ // Secret and expected TOTP values as per RFC 6238: Appendix B --
+ // Test Vectors.
+ const SECRET: &str = "12345678901234567890";
+ const TIME: &str = stringify!(1111111111);
+ const OTP: &str = concat!(14050471, "\n");
+
+ let mut ncli = Nitrocli::with_dev(device);
+ let _ = ncli.handle(&["otp", "set", "-d", "8", "-f", "ascii", "2", "name", &SECRET])?;
+
+ let out = ncli.handle(&["otp", "get", "-t", TIME, "2"])?;
+ assert_eq!(out, OTP);
+ 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"])?;
+ let _ = ncli.handle(&["otp", "clear", "3"])?;
+ let res = ncli.handle(&["otp", "get", "3"]);
+
+ assert_eq!(
+ res.unwrap_cmd_err(),
+ (
+ Some("Could not generate OTP"),
+ nitrokey::CommandError::SlotNotProgrammed
+ )
+ );
+ Ok(())
+}