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