Skip to content

Commit 76e03fb

Browse files
committed
fix(otp): Handle case when last slot is deleted
Fixes #182
1 parent 420b079 commit 76e03fb

File tree

1 file changed

+18
-6
lines changed

1 file changed

+18
-6
lines changed

Yubico.YubiKey/src/Yubico/YubiKey/Pipelines/OtpErrorTransform.cs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
using Microsoft.Extensions.Logging;
1717
using Yubico.Core.Iso7816;
1818
using Yubico.Core.Logging;
19+
using Yubico.YubiKey.Otp;
1920
using Yubico.YubiKey.Otp.Commands;
2021

2122
namespace Yubico.YubiKey.Pipelines
@@ -57,25 +58,36 @@ public ResponseApdu Invoke(CommandApdu command, Type commandType, Type responseT
5758
try
5859
{
5960
var responseApdu = _nextTransform.Invoke(command, commandType, responseType);
60-
int afterSequence = new ReadStatusResponse(responseApdu).GetData().SequenceNumber;
61-
int expectedSequence = (beforeSequence + 1) % 0x100;
61+
var readStatusResponse = new ReadStatusResponse(responseApdu);
62+
var otpStatus = readStatusResponse.GetData();
63+
byte nextSequence = otpStatus.SequenceNumber;
6264

6365
// If we see the sequence number change, we can assume that the configuration was applied successfully. Otherwise
6466
// we just invent an error in the response.
65-
return afterSequence != expectedSequence
66-
? new ResponseApdu(responseApdu.Data.ToArray(), SWConstants.WarningNvmUnchanged)
67-
: responseApdu;
67+
return IsValidSequenceProgression(beforeSequence, nextSequence, otpStatus)
68+
? responseApdu
69+
: FailedApdu(responseApdu.Data.ToArray());
6870
}
6971
catch (KeyboardConnectionException e)
7072
{
7173
_logger.LogWarning(e, "Handling keyboard connection exception. Translating to APDU response.");
7274

73-
return new ResponseApdu(Array.Empty<byte>(), SWConstants.WarningNvmUnchanged);
75+
return FailedApdu([]);
7476
}
77+
78+
static ResponseApdu FailedApdu(byte[] data) => new(data, SWConstants.WarningNvmUnchanged);
7579
}
7680

7781
public void Setup() => _nextTransform.Setup();
7882

7983
public void Cleanup() => _nextTransform.Cleanup();
84+
85+
private static bool IsValidSequenceProgression(int beforeSequence, int nextSequence, OtpStatus afterStatus)
86+
{
87+
const int configStatusMask = 0x1F;
88+
89+
return nextSequence == beforeSequence + 1 || // Normal increment
90+
(beforeSequence > 0 && nextSequence == 0 && (afterStatus.TouchLevel & configStatusMask) == 0); // When deleting the "last" slot
91+
}
8092
}
8193
}

0 commit comments

Comments
 (0)