1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2017 Merlok
4 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
5 // at your option, any later version. See the LICENSE.txt file for the text of
7 //-----------------------------------------------------------------------------
8 // APDU status bytes information
9 //-----------------------------------------------------------------------------
13 #include <string.h> // memmove
16 #include "ui.h" // Print...
18 #include "commonutil.h" // ARRAYLEN
20 const APDUCode APDUCodeTable
[] = {
21 // ID Type Description
22 {"XXXX", APDUCODE_TYPE_NONE
, ""}, // blank string
23 {"6---", APDUCODE_TYPE_ERROR
, "Class not supported."},
24 {"61--", APDUCODE_TYPE_INFO
, "Response bytes still available"},
25 {"61XX", APDUCODE_TYPE_INFO
, "Command successfully executed; 'XX' bytes of data are available and can be requested using GET RESPONSE."},
26 {"62--", APDUCODE_TYPE_WARNING
, "State of non-volatile memory unchanged"},
27 {"6200", APDUCODE_TYPE_WARNING
, "No information given (NV-Ram not changed)"},
28 {"6201", APDUCODE_TYPE_WARNING
, "NV-Ram not changed 1."},
29 {"6281", APDUCODE_TYPE_WARNING
, "Part of returned data may be corrupted"},
30 {"6282", APDUCODE_TYPE_WARNING
, "End of file/record reached before reading Le bytes"},
31 {"6283", APDUCODE_TYPE_WARNING
, "Selected file invalidated"},
32 {"6284", APDUCODE_TYPE_WARNING
, "Selected file is not valid. FCI not formatted according to ISO"},
33 {"6285", APDUCODE_TYPE_WARNING
, "No input data available from a sensor on the card. No Purse Engine enslaved for R3bc"},
34 {"62A2", APDUCODE_TYPE_WARNING
, "Wrong R-MAC"},
35 {"62A4", APDUCODE_TYPE_WARNING
, "Card locked (during reset( ))"},
36 {"62CX", APDUCODE_TYPE_WARNING
, "Counter with value x (command dependent)"},
37 {"62F1", APDUCODE_TYPE_WARNING
, "Wrong C-MAC"},
38 {"62F3", APDUCODE_TYPE_WARNING
, "Internal reset"},
39 {"62F5", APDUCODE_TYPE_WARNING
, "Default agent locked"},
40 {"62F7", APDUCODE_TYPE_WARNING
, "Cardholder locked"},
41 {"62F8", APDUCODE_TYPE_WARNING
, "Basement is current agent"},
42 {"62F9", APDUCODE_TYPE_WARNING
, "CALC Key Set not unblocked"},
43 {"62FX", APDUCODE_TYPE_WARNING
, "-"},
44 {"62XX", APDUCODE_TYPE_WARNING
, "RFU"},
45 {"63--", APDUCODE_TYPE_WARNING
, "State of non-volatile memory changed"},
46 {"6300", APDUCODE_TYPE_WARNING
, "No information given (NV-Ram changed)"},
47 {"6381", APDUCODE_TYPE_WARNING
, "File filled up by the last write. Loading/updating is not allowed."},
48 {"6382", APDUCODE_TYPE_WARNING
, "Card key not supported."},
49 {"6383", APDUCODE_TYPE_WARNING
, "Reader key not supported."},
50 {"6384", APDUCODE_TYPE_WARNING
, "Plaintext transmission not supported."},
51 {"6385", APDUCODE_TYPE_WARNING
, "Secured transmission not supported."},
52 {"6386", APDUCODE_TYPE_WARNING
, "Volatile memory is not available."},
53 {"6387", APDUCODE_TYPE_WARNING
, "Non-volatile memory is not available."},
54 {"6388", APDUCODE_TYPE_WARNING
, "Key number not valid."},
55 {"6389", APDUCODE_TYPE_WARNING
, "Key length is not correct."},
56 {"63C0", APDUCODE_TYPE_WARNING
, "Verify fail, no try left."},
57 {"63C1", APDUCODE_TYPE_WARNING
, "Verify fail, 1 try left."},
58 {"63C2", APDUCODE_TYPE_WARNING
, "Verify fail, 2 tries left."},
59 {"63C3", APDUCODE_TYPE_WARNING
, "Verify fail, 3 tries left."},
60 {"63CX", APDUCODE_TYPE_WARNING
, "The counter has reached the value 'x' (0 = x = 15) (command dependent)."},
61 {"63F1", APDUCODE_TYPE_WARNING
, "More data expected."},
62 {"63F2", APDUCODE_TYPE_WARNING
, "More data expected and proactive command pending."},
63 {"63FX", APDUCODE_TYPE_WARNING
, "-"},
64 {"63XX", APDUCODE_TYPE_WARNING
, "RFU"},
65 {"64--", APDUCODE_TYPE_ERROR
, "State of non-volatile memory unchanged"},
66 {"6400", APDUCODE_TYPE_ERROR
, "No information given (NV-Ram not changed)"},
67 {"6401", APDUCODE_TYPE_ERROR
, "Command timeout. Immediate response required by the card."},
68 {"64XX", APDUCODE_TYPE_ERROR
, "RFU"},
69 {"65--", APDUCODE_TYPE_ERROR
, "State of non-volatile memory changed"},
70 {"6500", APDUCODE_TYPE_ERROR
, "No information given"},
71 {"6501", APDUCODE_TYPE_ERROR
, "Write error. Memory failure. There have been problems in writing or reading the EEPROM. Other hardware problems may also bring this error."},
72 {"6581", APDUCODE_TYPE_ERROR
, "Memory failure"},
73 {"65FX", APDUCODE_TYPE_ERROR
, "-"},
74 {"65XX", APDUCODE_TYPE_ERROR
, "RFU"},
75 {"66--", APDUCODE_TYPE_SECURITY
, " "},
76 {"6600", APDUCODE_TYPE_SECURITY
, "Error while receiving (timeout)"},
77 {"6601", APDUCODE_TYPE_SECURITY
, "Error while receiving (character parity error)"},
78 {"6602", APDUCODE_TYPE_SECURITY
, "Wrong checksum"},
79 {"6603", APDUCODE_TYPE_SECURITY
, "The current DF file without FCI"},
80 {"6604", APDUCODE_TYPE_SECURITY
, "No SF or KF under the current DF"},
81 {"6669", APDUCODE_TYPE_SECURITY
, "Incorrect Encryption/Decryption Padding"},
82 {"66XX", APDUCODE_TYPE_SECURITY
, "-"},
83 {"67--", APDUCODE_TYPE_ERROR
, " "},
84 {"6700", APDUCODE_TYPE_ERROR
, "Wrong length"},
85 {"67XX", APDUCODE_TYPE_ERROR
, "length incorrect (procedure)(ISO 7816-3)"},
86 {"68--", APDUCODE_TYPE_ERROR
, "Functions in CLA not supported"},
87 {"6800", APDUCODE_TYPE_ERROR
, "No information given (The request function is not supported by the card)"},
88 {"6881", APDUCODE_TYPE_ERROR
, "Logical channel not supported"},
89 {"6882", APDUCODE_TYPE_ERROR
, "Secure messaging not supported"},
90 {"6883", APDUCODE_TYPE_ERROR
, "Last command of the chain expected"},
91 {"6884", APDUCODE_TYPE_ERROR
, "Command chaining not supported"},
92 {"68FX", APDUCODE_TYPE_ERROR
, "-"},
93 {"68XX", APDUCODE_TYPE_ERROR
, "RFU"},
94 {"69--", APDUCODE_TYPE_ERROR
, "Command not allowed"},
95 {"6900", APDUCODE_TYPE_ERROR
, "No information given (Command not allowed)"},
96 {"6901", APDUCODE_TYPE_ERROR
, "Command not accepted (inactive state)"},
97 {"6981", APDUCODE_TYPE_ERROR
, "Command incompatible with file structure"},
98 {"6982", APDUCODE_TYPE_ERROR
, "Security condition not satisfied."},
99 {"6983", APDUCODE_TYPE_ERROR
, "Authentication method blocked"},
100 {"6984", APDUCODE_TYPE_ERROR
, "Referenced data reversibly blocked (invalidated)"},
101 {"6985", APDUCODE_TYPE_ERROR
, "Conditions of use not satisfied."},
102 {"6986", APDUCODE_TYPE_ERROR
, "Command not allowed (no current EF)"},
103 {"6987", APDUCODE_TYPE_ERROR
, "Expected secure messaging (SM) object missing"},
104 {"6988", APDUCODE_TYPE_ERROR
, "Incorrect secure messaging (SM) data object"},
105 {"698D", APDUCODE_TYPE_NONE
, "Reserved"},
106 {"6996", APDUCODE_TYPE_ERROR
, "Data must be updated again"},
107 {"69E1", APDUCODE_TYPE_ERROR
, "POL1 of the currently Enabled Profile prevents this action."},
108 {"69F0", APDUCODE_TYPE_ERROR
, "Permission Denied"},
109 {"69F1", APDUCODE_TYPE_ERROR
, "Permission Denied - Missing Privilege"},
110 {"69FX", APDUCODE_TYPE_ERROR
, "-"},
111 {"69XX", APDUCODE_TYPE_ERROR
, "RFU"},
112 {"6A--", APDUCODE_TYPE_ERROR
, "Wrong parameter(s) P1-P2"},
113 {"6A00", APDUCODE_TYPE_ERROR
, "No information given (Bytes P1 and/or P2 are incorrect)"},
114 {"6A80", APDUCODE_TYPE_ERROR
, "The parameters in the data field are incorrect."},
115 {"6A81", APDUCODE_TYPE_ERROR
, "Function not supported"},
116 {"6A82", APDUCODE_TYPE_ERROR
, "File not found"},
117 {"6A83", APDUCODE_TYPE_ERROR
, "Record not found"},
118 {"6A84", APDUCODE_TYPE_ERROR
, "There is insufficient memory space in record or file"},
119 {"6A85", APDUCODE_TYPE_ERROR
, "Lc inconsistent with TLV structure"},
120 {"6A86", APDUCODE_TYPE_ERROR
, "Incorrect P1 or P2 parameter."},
121 {"6A87", APDUCODE_TYPE_ERROR
, "Lc inconsistent with P1-P2"},
122 {"6A88", APDUCODE_TYPE_ERROR
, "Referenced data not found"},
123 {"6A89", APDUCODE_TYPE_ERROR
, "File already exists"},
124 {"6A8A", APDUCODE_TYPE_ERROR
, "DF name already exists."},
125 {"6AF0", APDUCODE_TYPE_ERROR
, "Wrong parameter value"},
126 {"6AFX", APDUCODE_TYPE_ERROR
, "-"},
127 {"6AXX", APDUCODE_TYPE_ERROR
, "RFU"},
128 {"6B--", APDUCODE_TYPE_ERROR
, " "},
129 {"6B00", APDUCODE_TYPE_ERROR
, "Wrong parameter(s) P1-P2"},
130 {"6BXX", APDUCODE_TYPE_ERROR
, "Reference incorrect (procedure byte), (ISO 7816-3)"},
131 {"6C--", APDUCODE_TYPE_ERROR
, "Wrong length Le"},
132 {"6C00", APDUCODE_TYPE_ERROR
, "Incorrect P3 length."},
133 {"6CXX", APDUCODE_TYPE_ERROR
, "Bad length value in Le; 'xx' is the correct exact Le"},
134 {"6D--", APDUCODE_TYPE_ERROR
, " "},
135 {"6D00", APDUCODE_TYPE_ERROR
, "Instruction code not supported or invalid"},
136 {"6DXX", APDUCODE_TYPE_ERROR
, "Instruction code not programmed or invalid (procedure byte), (ISO 7816-3)"},
137 {"6E--", APDUCODE_TYPE_ERROR
, " "},
138 {"6E00", APDUCODE_TYPE_ERROR
, "Class not supported"},
139 {"6EXX", APDUCODE_TYPE_ERROR
, "Instruction class not supported (procedure byte), (ISO 7816-3)"},
140 {"6F--", APDUCODE_TYPE_ERROR
, "Internal exception"},
141 {"6F00", APDUCODE_TYPE_ERROR
, "Command aborted - more exact diagnosis not possible (e.g., operating system error)."},
142 {"6FFF", APDUCODE_TYPE_ERROR
, "Card dead (overuse)"},
143 {"6FXX", APDUCODE_TYPE_ERROR
, "No precise diagnosis (procedure byte), (ISO 7816-3)"},
144 {"9---", APDUCODE_TYPE_NONE
, ""},
145 {"9000", APDUCODE_TYPE_INFO
, "Command successfully executed (OK)."},
146 {"9004", APDUCODE_TYPE_WARNING
, "PIN not successfully verified, 3 or more PIN tries left"},
147 {"9008", APDUCODE_TYPE_NONE
, "Key/file not found"},
148 {"9080", APDUCODE_TYPE_WARNING
, "Unblock Try Counter has reached zero"},
149 {"9100", APDUCODE_TYPE_NONE
, "OK"},
150 {"9101", APDUCODE_TYPE_NONE
, "States.activity, States.lock Status or States.lockable has wrong value"},
151 {"9102", APDUCODE_TYPE_NONE
, "Transaction number reached its limit"},
152 {"910C", APDUCODE_TYPE_NONE
, "No changes"},
153 {"910E", APDUCODE_TYPE_NONE
, "Insufficient NV-Memory to complete command"},
154 {"911C", APDUCODE_TYPE_NONE
, "Command code not supported"},
155 {"911E", APDUCODE_TYPE_NONE
, "CRC or MAC does not match data"},
156 {"9140", APDUCODE_TYPE_NONE
, "Invalid key number specified"},
157 {"917E", APDUCODE_TYPE_NONE
, "Length of command string invalid"},
158 {"919D", APDUCODE_TYPE_NONE
, "Not allow the requested command"},
159 {"919E", APDUCODE_TYPE_NONE
, "Value of the parameter invalid"},
160 {"91A0", APDUCODE_TYPE_NONE
, "Requested AID not present on PICC"},
161 {"91A1", APDUCODE_TYPE_NONE
, "Unrecoverable error within application"},
162 {"91AE", APDUCODE_TYPE_NONE
, "Authentication status does not allow the requested command"},
163 {"91AF", APDUCODE_TYPE_NONE
, "Additional data frame is expected to be sent"},
164 {"91BE", APDUCODE_TYPE_NONE
, "Out of boundary"},
165 {"91C1", APDUCODE_TYPE_NONE
, "Unrecoverable error within PICC"},
166 {"91CA", APDUCODE_TYPE_NONE
, "Previous Command was not fully completed"},
167 {"91CD", APDUCODE_TYPE_NONE
, "PICC was disabled by an unrecoverable error"},
168 {"91CE", APDUCODE_TYPE_NONE
, "Number of Applications limited to 28"},
169 {"91DE", APDUCODE_TYPE_NONE
, "File or application already exists"},
170 {"91EE", APDUCODE_TYPE_NONE
, "Could not complete NV-write operation due to loss of power"},
171 {"91F0", APDUCODE_TYPE_NONE
, "Specified file number does not exist"},
172 {"91F1", APDUCODE_TYPE_NONE
, "Unrecoverable error within file"},
173 {"920x", APDUCODE_TYPE_INFO
, "Writing to EEPROM successful after 'x' attempts."},
174 {"9210", APDUCODE_TYPE_ERROR
, "Insufficient memory. No more storage available."},
175 {"9240", APDUCODE_TYPE_ERROR
, "Writing to EEPROM not successful."},
176 {"9301", APDUCODE_TYPE_NONE
, "Integrity error"},
177 {"9302", APDUCODE_TYPE_NONE
, "Candidate S2 invalid"},
178 {"9303", APDUCODE_TYPE_ERROR
, "Application is permanently locked"},
179 {"9400", APDUCODE_TYPE_ERROR
, "No EF selected."},
180 {"9401", APDUCODE_TYPE_NONE
, "Candidate currency code does not match purse currency"},
181 {"9402", APDUCODE_TYPE_NONE
, "Candidate amount too high"},
182 {"9402", APDUCODE_TYPE_ERROR
, "Address range exceeded."},
183 {"9403", APDUCODE_TYPE_NONE
, "Candidate amount too low"},
184 {"9404", APDUCODE_TYPE_ERROR
, "FID not found, record not found or comparison pattern not found."},
185 {"9405", APDUCODE_TYPE_NONE
, "Problems in the data field"},
186 {"9406", APDUCODE_TYPE_ERROR
, "Required MAC unavailable"},
187 {"9407", APDUCODE_TYPE_NONE
, "Bad currency : purse engine has no slot with R3bc currency"},
188 {"9408", APDUCODE_TYPE_NONE
, "R3bc currency not supported in purse engine"},
189 {"9408", APDUCODE_TYPE_ERROR
, "Selected file type does not match command."},
190 {"9580", APDUCODE_TYPE_NONE
, "Bad sequence"},
191 {"9681", APDUCODE_TYPE_NONE
, "Slave not found"},
192 {"9700", APDUCODE_TYPE_NONE
, "PIN blocked and Unblock Try Counter is 1 or 2"},
193 {"9702", APDUCODE_TYPE_NONE
, "Main keys are blocked"},
194 {"9704", APDUCODE_TYPE_NONE
, "PIN not successfully verified, 3 or more PIN tries left"},
195 {"9784", APDUCODE_TYPE_NONE
, "Base key"},
196 {"9785", APDUCODE_TYPE_NONE
, "Limit exceeded - C-MAC key"},
197 {"9786", APDUCODE_TYPE_NONE
, "SM error - Limit exceeded - R-MAC key"},
198 {"9787", APDUCODE_TYPE_NONE
, "Limit exceeded - sequence counter"},
199 {"9788", APDUCODE_TYPE_NONE
, "Limit exceeded - R-MAC length"},
200 {"9789", APDUCODE_TYPE_NONE
, "Service not available"},
201 {"9802", APDUCODE_TYPE_ERROR
, "No PIN defined."},
202 {"9804", APDUCODE_TYPE_ERROR
, "Access conditions not satisfied, authentication failed."},
203 {"9835", APDUCODE_TYPE_ERROR
, "ASK RANDOM or GIVE RANDOM not executed."},
204 {"9840", APDUCODE_TYPE_ERROR
, "PIN verification not successful."},
205 {"9850", APDUCODE_TYPE_ERROR
, "INCREASE or DECREASE could not be executed because a limit has been reached."},
206 {"9862", APDUCODE_TYPE_ERROR
, "Authentication Error, application specific (incorrect MAC)"},
207 {"9900", APDUCODE_TYPE_NONE
, "1 PIN try left"},
208 {"9904", APDUCODE_TYPE_NONE
, "PIN not successfully verified, 1 PIN try left"},
209 {"9985", APDUCODE_TYPE_NONE
, "Wrong status - Cardholder lock"},
210 {"9986", APDUCODE_TYPE_ERROR
, "Missing privilege"},
211 {"9987", APDUCODE_TYPE_NONE
, "PIN is not installed"},
212 {"9988", APDUCODE_TYPE_NONE
, "Wrong status - R-MAC state"},
213 {"9A00", APDUCODE_TYPE_NONE
, "2 PIN try left"},
214 {"9A04", APDUCODE_TYPE_NONE
, "PIN not successfully verified, 2 PIN try left"},
215 {"9A71", APDUCODE_TYPE_NONE
, "Wrong parameter value - Double agent AID"},
216 {"9A72", APDUCODE_TYPE_NONE
, "Wrong parameter value - Double agent Type"},
217 {"9D05", APDUCODE_TYPE_ERROR
, "Incorrect certificate type"},
218 {"9D07", APDUCODE_TYPE_ERROR
, "Incorrect session data size"},
219 {"9D08", APDUCODE_TYPE_ERROR
, "Incorrect DIR file record size"},
220 {"9D09", APDUCODE_TYPE_ERROR
, "Incorrect FCI record size"},
221 {"9D0A", APDUCODE_TYPE_ERROR
, "Incorrect code size"},
222 {"9D10", APDUCODE_TYPE_ERROR
, "Insufficient memory to load application"},
223 {"9D11", APDUCODE_TYPE_ERROR
, "Invalid AID"},
224 {"9D12", APDUCODE_TYPE_ERROR
, "Duplicate AID"},
225 {"9D13", APDUCODE_TYPE_ERROR
, "Application previously loaded"},
226 {"9D14", APDUCODE_TYPE_ERROR
, "Application history list full"},
227 {"9D15", APDUCODE_TYPE_ERROR
, "Application not open"},
228 {"9D17", APDUCODE_TYPE_ERROR
, "Invalid offset"},
229 {"9D18", APDUCODE_TYPE_ERROR
, "Application already loaded"},
230 {"9D19", APDUCODE_TYPE_ERROR
, "Invalid certificate"},
231 {"9D1A", APDUCODE_TYPE_ERROR
, "Invalid signature"},
232 {"9D1B", APDUCODE_TYPE_ERROR
, "Invalid KTU"},
233 {"9D1D", APDUCODE_TYPE_ERROR
, "MSM controls not set"},
234 {"9D1E", APDUCODE_TYPE_ERROR
, "Application signature does not exist"},
235 {"9D1F", APDUCODE_TYPE_ERROR
, "KTU does not exist"},
236 {"9D20", APDUCODE_TYPE_ERROR
, "Application not loaded"},
237 {"9D21", APDUCODE_TYPE_ERROR
, "Invalid Open command data length"},
238 {"9D30", APDUCODE_TYPE_ERROR
, "Check data parameter is incorrect (invalid start address)"},
239 {"9D31", APDUCODE_TYPE_ERROR
, "Check data parameter is incorrect (invalid length)"},
240 {"9D32", APDUCODE_TYPE_ERROR
, "Check data parameter is incorrect (illegal memory check area)"},
241 {"9D40", APDUCODE_TYPE_ERROR
, "Invalid MSM Controls ciphertext"},
242 {"9D41", APDUCODE_TYPE_ERROR
, "MSM controls already set"},
243 {"9D42", APDUCODE_TYPE_ERROR
, "Set MSM Controls data length less than 2 bytes"},
244 {"9D43", APDUCODE_TYPE_ERROR
, "Invalid MSM Controls data length"},
245 {"9D44", APDUCODE_TYPE_ERROR
, "Excess MSM Controls ciphertext"},
246 {"9D45", APDUCODE_TYPE_ERROR
, "Verification of MSM Controls data failed"},
247 {"9D50", APDUCODE_TYPE_ERROR
, "Invalid MCD Issuer production ID"},
248 {"9D51", APDUCODE_TYPE_ERROR
, "Invalid MCD Issuer ID"},
249 {"9D52", APDUCODE_TYPE_ERROR
, "Invalid set MSM controls data date"},
250 {"9D53", APDUCODE_TYPE_ERROR
, "Invalid MCD number"},
251 {"9D54", APDUCODE_TYPE_ERROR
, "Reserved field error"},
252 {"9D55", APDUCODE_TYPE_ERROR
, "Reserved field error"},
253 {"9D56", APDUCODE_TYPE_ERROR
, "Reserved field error"},
254 {"9D57", APDUCODE_TYPE_ERROR
, "Reserved field error"},
255 {"9D60", APDUCODE_TYPE_ERROR
, "MAC verification failed"},
256 {"9D61", APDUCODE_TYPE_ERROR
, "Maximum number of unblocks reached"},
257 {"9D62", APDUCODE_TYPE_ERROR
, "Card was not blocked"},
258 {"9D63", APDUCODE_TYPE_ERROR
, "Crypto functions not available"},
259 {"9D64", APDUCODE_TYPE_ERROR
, "No application loaded"},
260 {"9E00", APDUCODE_TYPE_NONE
, "PIN not installed"},
261 {"9E04", APDUCODE_TYPE_NONE
, "PIN not successfully verified, PIN not installed"},
262 {"9F00", APDUCODE_TYPE_NONE
, "PIN blocked and Unblock Try Counter is 3"},
263 {"9F04", APDUCODE_TYPE_NONE
, "PIN not successfully verified, PIN blocked and Unblock Try Counter is 3"},
264 {"9FXX", APDUCODE_TYPE_NONE
, "Command successfully executed; 'xx' bytes of data are available and can be requested using GET RESPONSE."},
265 {"9XXX", APDUCODE_TYPE_NONE
, "Application related status, (ISO 7816-3)"}
268 static int CodeCmp(const char *code1
, const char *code2
) {
271 for (int i
= 0; i
< 4; i
++) {
272 if (code1
[i
] == code2
[i
])
274 if (code1
[i
] == 'X' || code2
[i
] == 'X')
280 if (cmp
+ xsymb
== 4)
286 const APDUCode
*GetAPDUCode(uint8_t sw1
, uint8_t sw2
) {
288 int mineq
= ARRAYLEN(APDUCodeTable
);
291 sprintf(buf
, "%02X%02X", sw1
, sw2
);
293 for (int i
= 0; i
< ARRAYLEN(APDUCodeTable
); i
++) {
294 int res
= CodeCmp(APDUCodeTable
[i
].ID
, buf
);
298 return &APDUCodeTable
[i
];
302 if (res
> 0 && mineq
> res
) {
308 // if we have not equal, but with some 'X'
309 if (mineqindx
< ARRAYLEN(APDUCodeTable
)) {
310 return &APDUCodeTable
[mineqindx
];
316 const char *GetAPDUCodeDescription(uint8_t sw1
, uint8_t sw2
) {
317 const APDUCode
*cd
= GetAPDUCode(sw1
, sw2
);
319 return cd
->Description
;
321 return APDUCodeTable
[0].Description
; //empty string
324 int APDUDecode(uint8_t *data
, int len
, APDUStruct
*apdu
) {
325 ExtAPDUHeader
*hapdu
= (ExtAPDUHeader
*)data
;
327 apdu
->cla
= hapdu
->cla
;
328 apdu
->ins
= hapdu
->ins
;
329 apdu
->p1
= hapdu
->p1
;
330 apdu
->p2
= hapdu
->p2
;
335 apdu
->extended_apdu
= false;
336 apdu
->case_type
= 0x00;
338 uint8_t b0
= hapdu
->lc
[0];
342 apdu
->case_type
= 0x01;
347 apdu
->case_type
= 0x02;
353 // case 3S (Lc + data)
354 if (len
== 5U + b0
&& b0
!= 0) {
355 apdu
->case_type
= 0x03;
359 // case 4S (Lc + data + Le)
360 if (len
== 5U + b0
+ 1U && b0
!= 0) {
361 apdu
->case_type
= 0x04;
363 apdu
->le
= data
[len
- 1];
368 // extended length apdu
369 if (len
>= 7 && b0
== 0) {
370 uint16_t extlen
= (hapdu
->lc
[1] << 8) + hapdu
->lc
[2];
372 // case 2E (Le) - extended
374 apdu
->case_type
= 0x12;
375 apdu
->extended_apdu
= true;
381 // case 3E (Lc + data) - extended
382 if (len
== 7U + extlen
) {
383 apdu
->case_type
= 0x13;
384 apdu
->extended_apdu
= true;
388 // case 4E (Lc + data + Le) - extended 2-byte Le
389 if (len
== 7U + extlen
+ 2U) {
390 apdu
->case_type
= 0x14;
391 apdu
->extended_apdu
= true;
393 apdu
->le
= (data
[len
- 2] << 8) + data
[len
- 1];
398 // case 4E (Lc + data + Le) - extended 3-byte Le
399 if (len
== 7U + extlen
+ 3U && data
[len
- 3] == 0) {
400 apdu
->case_type
= 0x24;
401 apdu
->extended_apdu
= true;
403 apdu
->le
= (data
[len
- 2] << 8) + data
[len
- 1];
409 if (!apdu
->case_type
)
413 if (apdu
->extended_apdu
) {
414 apdu
->data
= data
+ 7;
416 apdu
->data
= data
+ 5;
424 int APDUEncode(APDUStruct
*apdu
, uint8_t *data
, int *len
) {
428 if (apdu
->le
> 0x10000)
432 data
[dptr
++] = apdu
->cla
;
433 data
[dptr
++] = apdu
->ins
;
434 data
[dptr
++] = apdu
->p1
;
435 data
[dptr
++] = apdu
->p2
;
437 if (apdu
->lc
) { // apdu->lc is uint16_t so max 0xffff
438 if (apdu
->extended_apdu
|| apdu
->lc
> 0xff || apdu
->le
> 0x100) {
440 data
[dptr
++] = (apdu
->lc
>> 8) & 0xff;
441 data
[dptr
++] = (apdu
->lc
) & 0xff;
442 memmove(&data
[dptr
], apdu
->data
, apdu
->lc
);
444 apdu
->extended_apdu
= true;
446 data
[dptr
++] = apdu
->lc
;
447 memmove(&data
[dptr
], apdu
->data
, apdu
->lc
);
453 if (apdu
->extended_apdu
) {
454 if (apdu
->le
!= 0x10000) {
456 data
[dptr
++] = (apdu
->le
>> 8) & 0xff;
457 data
[dptr
++] = (apdu
->le
) & 0xff;
464 if (apdu
->le
!= 0x100)
465 data
[dptr
++] = apdu
->le
;
476 int APDUEncodeS(sAPDU
*sapdu
, bool extended
, uint16_t le
, uint8_t *data
, int *len
) {
477 if (extended
&& le
> 0x100)
482 apdu
.cla
= sapdu
->CLA
;
483 apdu
.ins
= sapdu
->INS
;
489 apdu
.data
= sapdu
->data
;
494 apdu
.extended_apdu
= extended
;
495 apdu
.case_type
= 0x00;
497 return APDUEncode(&apdu
, data
, len
);
500 void APDUPrint(APDUStruct apdu
) {
501 APDUPrintEx(apdu
, 0);
504 void APDUPrintEx(APDUStruct apdu
, size_t maxdatalen
) {
505 PrintAndLogEx(INFO
, "APDU: %scase=0x%02x cla=0x%02x ins=0x%02x p1=0x%02x p2=0x%02x Lc=0x%02x(%d) Le=0x%02x(%d)",
506 apdu
.extended_apdu
? "[e]" : "",
518 PrintAndLogEx(INFO
, "data: %s%s", sprint_hex(apdu
.data
, MIN(apdu
.lc
, maxdatalen
)), apdu
.lc
> maxdatalen
? "..." : "");
521 void SAPDUPrint(sAPDU apdu
, size_t maxdatalen
) {
522 PrintAndLogEx(INFO
, "APDU: CLA 0x%02x, INS 0x%02x, P1 0x%02x, P2 0x%02x, Lc 0x%02x(%d)",
531 size_t len
= apdu
.Lc
;
533 len
= MIN(apdu
.Lc
, maxdatalen
);
535 PrintAndLogEx(INFO
, "data { %s%s }", sprint_hex(apdu
.data
, len
), apdu
.Lc
> len
? "..." : "");