diff options
authorDaniel Mueller <>2019-06-01 11:19:08 -0700
committerDaniel Mueller <>2019-06-01 11:19:08 -0700
commit7c880699bb9a49037c09b1be990e677a1857af7a (patch)
parenta57449dcd2abe1fa5dae195470fccc9a9a398e04 (diff)
Clear cached PIN entry as part of pin set command
When a PIN is changed using the pin set command, the last action is to confirm the operation with the previously used PIN. This step will cause this PIN, which is now stale and no longer valid, to be cached, which in turn can cause follow up command using the same PIN type to use this wrong cached entry for authentication. To fix this problem, this change explicitly clear the PIN entry from the cache after the PIN has been changed.
3 files changed, 9 insertions, 2 deletions
diff --git a/nitrocli/ b/nitrocli/
index fe3ac74..71a54df 100644
--- a/nitrocli/
+++ b/nitrocli/
@@ -5,6 +5,8 @@ Unreleased
- Check the status of a PWS slot before accessing it in `pws get`
- Added `NITROCLI_NO_CACHE` environment variable to bypass caching of
+- Clear cached PIN entry as part of `pin set` command to prevent
+ spurious authentication failures
- Bumped `libc` dependency to `0.2.55`
- Bumped `cc` dependency to `1.0.37`
diff --git a/nitrocli/src/ b/nitrocli/src/
index a81859c..7bb314c 100644
--- a/nitrocli/src/
+++ b/nitrocli/src/
@@ -725,7 +725,12 @@ pub fn pin_set(ctx: &mut args::ExecCtx<'_>, pin_type: pinentry::PinType) -> Resu
pinentry::PinType::Admin => device.change_admin_pin(&current_pin, &new_pin),
pinentry::PinType::User => device.change_user_pin(&current_pin, &new_pin),
- )
+ )?;
+ // We just changed the PIN but confirmed the action with the old PIN,
+ // which may have caused it to be cached. Since it no longer applies,
+ // make sure to evict the corresponding entry from the cache.
+ pinentry::clear(&pin_entry)
/// Unblock and reset the user PIN.
diff --git a/nitrocli/src/tests/ b/nitrocli/src/tests/
index d99a6f8..39ddf29 100644
--- a/nitrocli/src/tests/
+++ b/nitrocli/src/tests/
@@ -51,7 +51,7 @@ fn status(device: nitrokey::DeviceWrapper) -> crate::Result<()> {
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.
+ // that there is one slot programmed.
let _ = ncli.handle(&["otp", "set", "0", "the-name", "123456"])?;
let out = ncli.handle(&["otp", "status"])?;