@@ -38,6 +38,7 @@ public CommandChainingTransform(IApduTransform pipeline)
38
38
}
39
39
40
40
public void Cleanup ( ) => _pipeline . Cleanup ( ) ;
41
+ public void Setup ( ) => _pipeline . Setup ( ) ;
41
42
42
43
public ResponseApdu Invoke ( CommandApdu command , Type commandType , Type responseType )
43
44
{
@@ -46,53 +47,77 @@ public ResponseApdu Invoke(CommandApdu command, Type commandType, Type responseT
46
47
throw new ArgumentNullException ( nameof ( command ) ) ;
47
48
}
48
49
49
- // Send regular short APDU
50
+ // Send single short APDU
50
51
int commandDataSize = command . Data . Length ;
51
52
if ( commandDataSize <= MaxChunkSize )
52
53
{
53
54
_log . LogDebug ( "Sending short APDU" ) ;
54
55
return _pipeline . Invoke ( command , commandType , responseType ) ;
55
56
}
56
57
57
- // Send chained short APDU
58
- var sourceData = command . Data ;
59
- ResponseApdu ? responseApdu = null ;
58
+ // Send a series of short APDU's
60
59
_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 ;
61
67
while ( ! sourceData . IsEmpty )
62
68
{
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 )
83
71
{
84
72
continue ;
85
73
}
86
74
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 ) ;
91
76
}
92
77
93
78
return responseApdu ! ;
94
79
}
95
80
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
+ }
97
122
}
98
123
}
0 commit comments