Require auth to reset a locked applet
The applet gates RESET behind authentication when a password is set (unlike Yubico OATH, which allows an unauthenticated reset). --reset now authenticates with the applet password (--password or prompt) before resetting a locked applet, and the RESET error includes the status-word meaning.
This commit is contained in:
@@ -446,10 +446,12 @@ class OathSession:
|
|||||||
return
|
return
|
||||||
|
|
||||||
def reset(self):
|
def reset(self):
|
||||||
"""RESET: wipe all credentials and any password (P1P2 = 0xDEAD)."""
|
"""RESET: wipe all credentials and any password (P1P2 = 0xDEAD).
|
||||||
|
Unlike Yubico's OATH, this applet gates RESET behind authentication when
|
||||||
|
a password is set, so a locked applet must be VALIDATEd first."""
|
||||||
data, sw = self.ch.send(0x00, INS_RESET, 0xDE, 0xAD)
|
data, sw = self.ch.send(0x00, INS_RESET, 0xDE, 0xAD)
|
||||||
if sw != 0x9000:
|
if sw != 0x9000:
|
||||||
raise OathError(sw, "RESET failed")
|
raise OathError(sw, f"RESET failed ({sw_message(sw)})")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
@@ -642,6 +644,10 @@ def main(argv=None):
|
|||||||
return 1
|
return 1
|
||||||
oath = OathSession(CardChannel(connection))
|
oath = OathSession(CardChannel(connection))
|
||||||
oath.select()
|
oath.select()
|
||||||
|
if oath.locked:
|
||||||
|
# This applet requires authentication before RESET (unlike Yubico).
|
||||||
|
pw = args.password or getpass.getpass("Applet password (required to reset): ")
|
||||||
|
oath.validate(pw)
|
||||||
oath.reset()
|
oath.reset()
|
||||||
print(f"Applet reset on '{reader}' (all credentials and any password wiped).")
|
print(f"Applet reset on '{reader}' (all credentials and any password wiped).")
|
||||||
return 0
|
return 0
|
||||||
|
|||||||
Reference in New Issue
Block a user