Skip to content

Commit 049b789

Browse files
committed
misc: refactor CommandChainingTransform
stop sending data to key if not Success SW
1 parent 094ec8e commit 049b789

File tree

1 file changed

+54
-29
lines changed

1 file changed

+54
-29
lines changed

Yubico.YubiKey/src/Yubico/YubiKey/Pipelines/CommandChainingTransform.cs

Lines changed: 54 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ public CommandChainingTransform(IApduTransform pipeline)
3838
}
3939

4040
public void Cleanup() => _pipeline.Cleanup();
41+
public void Setup() => _pipeline.Setup();
4142

4243
public ResponseApdu Invoke(CommandApdu command, Type commandType, Type responseType)
4344
{
@@ -46,53 +47,77 @@ public ResponseApdu Invoke(CommandApdu command, Type commandType, Type responseT
4647
throw new ArgumentNullException(nameof(command));
4748
}
4849

49-
// Send regular short APDU
50+
// Send single short APDU
5051
int commandDataSize = command.Data.Length;
5152
if (commandDataSize <= MaxChunkSize)
5253
{
5354
_log.LogDebug("Sending short APDU");
5455
return _pipeline.Invoke(command, commandType, responseType);
5556
}
5657

57-
// Send chained short APDU
58-
var sourceData = command.Data;
59-
ResponseApdu? responseApdu = null;
58+
// Send a series of short APDU's
6059
_log.LogDebug("APDU size exceeds size of short APDU, proceeding to send data in chunks instead");
60+
return SendChainedApdu(command, commandType, responseType);
61+
}
62+
63+
private ResponseApdu SendChainedApdu(CommandApdu command, Type commandType, Type responseType)
64+
{
65+
ResponseApdu? responseApdu = null;
66+
var sourceData = command.Data;
6167
while (!sourceData.IsEmpty)
6268
{
63-
int chunkLength = Math.Min(MaxChunkSize, sourceData.Length);
64-
var dataChunk = sourceData[..chunkLength];
65-
sourceData = sourceData[chunkLength..];
66-
67-
var partialApdu = new CommandApdu
68-
{
69-
Cla = (byte)(command.Cla | (sourceData.IsEmpty
70-
? 0
71-
: 0x10)),
72-
Ins = command.Ins,
73-
P1 = command.P1,
74-
P2 = command.P2,
75-
Data = dataChunk
76-
};
77-
78-
responseApdu = _pipeline.Invoke(partialApdu, commandType, responseType);
79-
80-
// Stop sending data when the YubiKey response is 0x6700 (when the chained data
81-
// sent exceeds the max allowed length) and let caller handle the response
82-
if (responseApdu.SW != SWConstants.WrongLength)
69+
responseApdu = SendPartial(command, commandType, responseType, ref sourceData);
70+
if (responseApdu.SW == SWConstants.Success)
8371
{
8472
continue;
8573
}
8674

87-
_log.LogWarning("Sent data exceeds max allowed length by YubiKey. (SW: 0x{StatusWord})",
88-
responseApdu.SW.ToString("X4", CultureInfo.InvariantCulture));
89-
90-
return responseApdu;
75+
return FailedResponse(responseApdu);
9176
}
9277

9378
return responseApdu!;
9479
}
9580

96-
public void Setup() => _pipeline.Setup();
81+
private ResponseApdu SendPartial(
82+
CommandApdu command,
83+
Type commandType,
84+
Type responseType,
85+
ref ReadOnlyMemory<byte> sourceData)
86+
{
87+
int chunkLength = Math.Min(MaxChunkSize, sourceData.Length);
88+
var dataChunk = sourceData[..chunkLength];
89+
sourceData = sourceData[chunkLength..];
90+
91+
var partialApdu = new CommandApdu
92+
{
93+
Cla = (byte)(command.Cla | (sourceData.IsEmpty
94+
? 0
95+
: 0x10)),
96+
Ins = command.Ins,
97+
P1 = command.P1,
98+
P2 = command.P2,
99+
Data = dataChunk
100+
};
101+
102+
var responseApdu = _pipeline.Invoke(partialApdu, commandType, responseType);
103+
return responseApdu;
104+
}
105+
106+
private ResponseApdu FailedResponse(ResponseApdu responseApdu)
107+
{
108+
var currentCulture = CultureInfo.CurrentCulture;
109+
string errorMessage = responseApdu.SW switch
110+
{
111+
SWConstants.WrongLength => string.Format(
112+
currentCulture, "Sent data exceeds max allowed length by YubiKey. (SW: 0x{0})",
113+
responseApdu.SW.ToString("X4", currentCulture)),
114+
_ => string.Format(
115+
currentCulture, "Received error response from YubiKey. (SW: 0x{0})",
116+
responseApdu.SW.ToString("X4", currentCulture))
117+
};
118+
119+
_log.LogWarning(errorMessage);
120+
return responseApdu;
121+
}
97122
}
98123
}

0 commit comments

Comments
 (0)