fix one too small
[RRG-proxmark3.git] / client / src / cmdhfmfdes.c
blob6002aa83799570a6b699f710e7d1602c5df53a99
1 //-----------------------------------------------------------------------------
2 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // See LICENSE.txt for the text of the license.
15 //-----------------------------------------------------------------------------
16 // High frequency MIFARE Desfire commands
17 //-----------------------------------------------------------------------------
18 // Code heavily modified by B.Kerler :)
20 #include "cmdhfmfdes.h"
21 #include <stdio.h>
22 #include <string.h>
23 #include "commonutil.h" // ARRAYLEN
24 #include "cmdparser.h" // command_t
25 #include "comms.h"
26 #include "ui.h"
27 #include "cmdhf14a.h"
28 #include "aes.h"
29 #include "crypto/libpcrypto.h"
30 #include "protocols.h"
31 #include "cmdtrace.h"
32 #include "cliparser.h"
33 #include "iso7816/apduinfo.h" // APDU manipulation / errorcodes
34 #include "iso7816/iso7816core.h" // APDU logging
35 #include "util_posix.h" // msleep
36 #include "mifare/desfirecore.h"
37 #include "mifare/desfiretest.h"
38 #include "mifare/desfiresecurechan.h"
39 #include "mifare/mifaredefault.h" // default keys
40 #include "crapto1/crapto1.h"
41 #include "fileutils.h"
42 //#include "nfc/ndef.h" // NDEF
43 #include "mifare/mad.h"
44 #include "mifare/mifaredefault.h"
45 #include "generator.h"
46 #include "mifare/aiddesfire.h"
47 #include "util.h"
49 #define MAX_KEY_LEN 24
50 #define MAX_KEYS_LIST_LEN 1024
52 #define status(x) ( ((uint16_t)(0x91 << 8)) + (uint16_t)x )
54 static uint8_t desdefaultkeys[3][8] = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //Official
55 {0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47},
56 {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}
59 static uint8_t aesdefaultkeys[5][16] = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //Official, TRF7970A
60 {0x79, 0x70, 0x25, 0x53, 0x79, 0x70, 0x25, 0x53, 0x79, 0x70, 0x25, 0x53, 0x79, 0x70, 0x25, 0x53}, // TRF7970A
61 {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}, // TRF7970A
62 {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f},
63 {0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f}
66 static uint8_t k3kdefaultkeys[1][24] = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
68 typedef struct mfdes_authinput {
69 uint8_t mode;
70 uint8_t algo;
71 uint8_t keyno;
72 uint8_t keylen;
73 uint8_t key[24];
74 uint8_t kdfAlgo;
75 uint8_t kdfInputLen;
76 uint8_t kdfInput[31];
77 } PACKED mfdes_authinput_t;
79 typedef struct mfdes_auth_res {
80 uint8_t sessionkeylen;
81 uint8_t sessionkey[24];
82 } PACKED mfdes_auth_res_t;
84 typedef struct mfdes_data {
85 uint8_t fileno; //01
86 uint8_t offset[3];
87 uint8_t length[3];
88 uint8_t *data;
89 } PACKED mfdes_data_t;
91 typedef struct mfdes_info_res {
92 uint8_t isOK;
93 uint8_t uid[7];
94 uint8_t uidlen;
95 uint8_t versionHW[7];
96 uint8_t versionSW[7];
97 uint8_t details[14];
98 } PACKED mfdes_info_res_t;
100 typedef struct mfdes_value {
101 uint8_t fileno; //01
102 uint8_t value[16];
103 } PACKED mfdes_value_t;
105 typedef struct mfdes_file {
106 uint8_t fileno; //01
107 uint8_t fid[2]; //03E1
108 uint8_t comset; //00
109 uint8_t access_rights[2]; ///EEEE
110 uint8_t filesize[3]; //0F0000
111 } PACKED mfdes_file_t;
113 typedef struct mfdes_linear {
114 uint8_t fileno; //01
115 uint8_t fid[2]; //03E1
116 uint8_t comset; //00
117 uint8_t access_rights[2]; ///EEEE
118 uint8_t recordsize[3];
119 uint8_t maxnumrecords[3];
120 } PACKED mfdes_linear_t;
122 typedef struct mfdes_value_file {
123 uint8_t fileno; //01
124 uint8_t comset; //00
125 uint8_t access_rights[2]; ///EEEE
126 uint8_t lowerlimit[4];
127 uint8_t upperlimit[4];
128 uint8_t value[4];
129 uint8_t limitedcreditenabled;
130 } PACKED mfdes_value_file_t;
132 typedef enum {
133 MFDES_DATA_FILE = 0,
134 MFDES_RECORD_FILE,
135 MFDES_VALUE_FILE
136 } MFDES_FILE_TYPE_T;
138 typedef enum {
139 DESFIRE_UNKNOWN = 0,
140 DESFIRE_MF3ICD40,
141 DESFIRE_EV1,
142 DESFIRE_EV2,
143 DESFIRE_EV2_XL,
144 DESFIRE_EV3,
145 DESFIRE_LIGHT,
146 PLUS_EV1,
147 PLUS_EV2,
148 NTAG413DNA,
149 NTAG424,
150 } nxp_cardtype_t;
152 typedef enum {
153 DESFIRE_UNKNOWN_PROD = 0,
154 DESFIRE_PHYSICAL,
155 DESFIRE_LIGHT_PHYSICAL,
156 DESFIRE_MICROCONTROLLER,
157 DESFIRE_JAVACARD,
158 DESFIRE_HCE,
159 } nxp_producttype_t;
161 typedef struct dfname {
162 uint8_t aid[3];
163 uint8_t fid[2];
164 uint8_t name[16];
165 } PACKED dfname_t;
167 typedef struct aidhdr {
168 uint8_t aid[3];
169 uint8_t keysetting1;
170 uint8_t keysetting2;
171 uint8_t fid[2];
172 uint8_t name[16];
173 } PACKED aidhdr_t;
175 typedef struct {
176 const char *aid;
177 const char *comment;
178 } mfdesCommonAID_t;
180 static const mfdesCommonAID_t commonAids[] = {
181 // AID, name/comment
182 { "\xf4\x81\x2f", "Gallagher card data application" },
183 { "\xf4\x81\x20", "Gallagher card application directory" }, // Can be 0xF48120 - 0xF4812B, but I've only ever seen 0xF48120
186 static int CmdHelp(const char *Cmd);
188 static int CLIGetUint32Hex(CLIParserContext *ctx, uint8_t paramnum, uint32_t defaultValue, uint32_t *value, bool *valuePresent, uint8_t nlen, const char *lengthErrorStr) {
189 *value = defaultValue;
190 if (valuePresent != NULL)
191 *valuePresent = false;
193 int res = arg_get_u32_hexstr_def_nlen(ctx, paramnum, defaultValue, value, nlen, true);
195 if (valuePresent != NULL)
196 *valuePresent = (res == 1);
198 if (res == 2) {
199 PrintAndLogEx(ERR, lengthErrorStr);
200 return PM3_EINVARG;
202 if (res == 0) {
203 return PM3_EINVARG;
206 return PM3_SUCCESS;
210 The 7 MSBits (= n) code the storage size itself based on 2^n,
211 the LSBit is set to '0' if the size is exactly 2^n
212 and set to '1' if the storage size is between 2^n and 2^(n+1).
213 For this version of DESFire the 7 MSBits are set to 0x0C (2^12 = 4096) and the LSBit is '0'.
215 static char *getCardSizeStr(uint8_t fsize) {
217 static char buf[40] = {0x00};
218 char *retStr = buf;
220 uint16_t usize = 1 << (((uint16_t)fsize >> 1) + 1);
221 uint16_t lsize = 1 << ((uint16_t)fsize >> 1);
223 // is LSB set?
224 if (fsize & 1)
225 snprintf(retStr, sizeof(buf), "0x%02X ( " _GREEN_("%d - %d bytes") " )", fsize, usize, lsize);
226 else
227 snprintf(retStr, sizeof(buf), "0x%02X ( " _GREEN_("%d bytes") " )", fsize, lsize);
228 return buf;
231 static char *getProtocolStr(uint8_t id, bool hw) {
233 static char buf[50] = {0x00};
234 char *retStr = buf;
236 if (id == 0x04) {
237 snprintf(retStr, sizeof(buf), "0x%02X ( " _YELLOW_("ISO 14443-3 MIFARE, 14443-4") " )", id);
238 } else if (id == 0x05) {
239 if (hw)
240 snprintf(retStr, sizeof(buf), "0x%02X ( " _YELLOW_("ISO 14443-2, 14443-3") " )", id);
241 else
242 snprintf(retStr, sizeof(buf), "0x%02X ( " _YELLOW_("ISO 14443-3, 14443-4") " )", id);
243 } else {
244 snprintf(retStr, sizeof(buf), "0x%02X ( " _YELLOW_("Unknown") " )", id);
246 return buf;
249 static char *getVersionStr(uint8_t type, uint8_t major, uint8_t minor) {
251 static char buf[40] = {0x00};
252 char *retStr = buf;
254 if (type == 0x01 && major == 0x00)
255 snprintf(retStr, sizeof(buf), "%x.%x ( " _GREEN_("DESFire MF3ICD40") " )", major, minor);
256 else if (major == 0x10 && minor == 0x00)
257 snprintf(retStr, sizeof(buf), "%x.%x ( " _GREEN_("NTAG413DNA") " )", major, minor);
258 else if (type == 0x01 && major == 0x01 && minor == 0x00)
259 snprintf(retStr, sizeof(buf), "%x.%x ( " _GREEN_("DESFire EV1") " )", major, minor);
260 else if (type == 0x01 && major == 0x12 && minor == 0x00)
261 snprintf(retStr, sizeof(buf), "%x.%x ( " _GREEN_("DESFire EV2") " )", major, minor);
262 else if (type == 0x01 && major == 0x22 && minor == 0x00)
263 snprintf(retStr, sizeof(buf), "%x.%x ( " _GREEN_("DESFire EV2 XL") " )", major, minor);
264 else if (type == 0x01 && major == 0x42 && minor == 0x00)
265 snprintf(retStr, sizeof(buf), "%x.%x ( " _GREEN_("DESFire EV2") " )", major, minor);
266 else if (type == 0x01 && major == 0x33 && minor == 0x00)
267 snprintf(retStr, sizeof(buf), "%x.%x ( " _GREEN_("DESFire EV3") " )", major, minor);
268 else if (type == 0x01 && major == 0x30 && minor == 0x00)
269 snprintf(retStr, sizeof(buf), "%x.%x ( " _GREEN_("DESFire Light") " )", major, minor);
270 else if (type == 0x02 && major == 0x11 && minor == 0x00)
271 snprintf(retStr, sizeof(buf), "%x.%x ( " _GREEN_("Plus EV1") " )", major, minor);
272 else if (type == 0x02 && major == 0x22 && minor == 0x00)
273 snprintf(retStr, sizeof(buf), "%x.%x ( " _GREEN_("Plus EV2") " )", major, minor);
274 else
275 snprintf(retStr, sizeof(buf), "%x.%x ( " _YELLOW_("Unknown") " )", major, minor);
276 return buf;
278 //04 01 01 01 00 1A 05
281 static char *getTypeStr(uint8_t type) {
283 static char buf[40] = {0x00};
284 char *retStr = buf;
286 switch (type) {
287 case 0x01:
288 snprintf(retStr, sizeof(buf), "0x%02X ( " _YELLOW_("DESFire") " )", type);
289 break;
290 case 0x02:
291 snprintf(retStr, sizeof(buf), "0x%02X ( " _YELLOW_("Plus") " )", type);
292 break;
293 case 0x03:
294 snprintf(retStr, sizeof(buf), "0x%02X ( " _YELLOW_("Ultralight") " )", type);
295 break;
296 case 0x04:
297 snprintf(retStr, sizeof(buf), "0x%02X ( " _YELLOW_("NTAG") " )", type);
298 break;
299 case 0x81:
300 snprintf(retStr, sizeof(buf), "0x%02X ( " _YELLOW_("Smartcard") " )", type);
301 break;
302 default:
303 break;
305 return buf;
309 static char noCommentStr[1] = { 0x00 };
310 static const char *getAidCommentStr(uint8_t *aid) {
311 for (int i = 0; i < ARRAYLEN(commonAids); i++) {
312 if (memcmp(aid, commonAids[i].aid, 3) == 0) {
313 return commonAids[i].comment;
316 return noCommentStr;
319 static nxp_cardtype_t getCardType(uint8_t type, uint8_t major, uint8_t minor) {
321 // DESFire MF3ICD40
322 if (type == 0x01 && major == 0x00 && minor == 0x02)
323 return DESFIRE_MF3ICD40;
325 // DESFire EV1
326 if (type == 0x01 && major == 0x01 && minor == 0x00)
327 return DESFIRE_EV1;
329 // DESFire EV2
330 if (type == 0x01 && major == 0x12 && minor == 0x00)
331 return DESFIRE_EV2;
333 if (type == 0x01 && major == 0x22 && minor == 0x00)
334 return DESFIRE_EV2_XL;
336 // DESFire EV3
337 if (type == 0x01 && major == 0x33 && minor == 0x00)
338 return DESFIRE_EV3;
340 // DESFire Light
341 if (type == 0x08 && major == 0x30 && minor == 0x00)
342 return DESFIRE_LIGHT;
344 // combo card DESFire / EMV
345 if (type == 0x81 && major == 0x42 && minor == 0x00)
346 return DESFIRE_EV2;
348 // Plus EV1
349 if (type == 0x02 && major == 0x11 && minor == 0x00)
350 return PLUS_EV1;
352 // Plus Ev2
353 if (type == 0x02 && major == 0x22 && minor == 0x00)
354 return PLUS_EV2;
356 // NTAG 413 DNA
357 if (major == 0x10 && minor == 0x00)
358 return NTAG413DNA;
360 // NTAG 424
361 if (type == 0x04 && major == 0x30 && minor == 0x00)
362 return NTAG424;
364 return DESFIRE_UNKNOWN;
367 // ref: https://www.nxp.com/docs/en/application-note/AN12343.pdf p7
368 static nxp_producttype_t getProductType(const uint8_t *versionhw) {
370 uint8_t product = versionhw[2];
372 if (product == 0x01)
373 return DESFIRE_PHYSICAL;
374 if (product == 0x08)
375 return DESFIRE_LIGHT_PHYSICAL;
376 if (product == 0x81 || product == 0x83)
377 return DESFIRE_MICROCONTROLLER;
378 if (product == 0x91)
379 return DESFIRE_JAVACARD;
380 if (product == 0xA1)
381 return DESFIRE_HCE;
382 return DESFIRE_UNKNOWN_PROD;
385 static const char *getProductTypeStr(const uint8_t *versionhw) {
387 uint8_t product = versionhw[2];
389 if (product == 0x01)
390 return "MIFARE DESFire native IC (physical card)";
391 if (product == 0x08)
392 return "MIFARE DESFire Light native IC (physical card)";
393 if (product == 0x81 || product == 0x83)
394 return "MIFARE DESFire implementation on microcontroller (physical card)";
395 if (product == 0x91)
396 return "MIFARE DESFire applet on Java card / secure element";
397 if (product == 0xA1)
398 return "MIFARE DESFire HCE (MIFARE 2GO)";
399 return "UNKNOWN PROD";
402 static int mfdes_get_info(mfdes_info_res_t *info) {
404 PacketResponseNG resp;
405 SendCommandNG(CMD_HF_DESFIRE_INFO, NULL, 0);
406 if (WaitForResponseTimeout(CMD_HF_DESFIRE_INFO, &resp, 1500) == false) {
407 PrintAndLogEx(WARNING, "Command execute timeout");
408 DropField();
409 return PM3_ETIMEOUT;
412 memcpy(info, resp.data.asBytes, sizeof(mfdes_info_res_t));
414 if (resp.status != PM3_SUCCESS) {
416 switch (info->isOK) {
417 case 1:
418 PrintAndLogEx(WARNING, "Can't select card");
419 break;
420 case 2:
421 PrintAndLogEx(WARNING, "Card is most likely not DESFire. Wrong size UID");
422 break;
423 case 3:
424 default:
425 PrintAndLogEx(WARNING, _RED_("Command unsuccessful"));
426 break;
428 return PM3_ESOFT;
431 return PM3_SUCCESS;
434 // --- GET SIGNATURE
435 int desfire_print_signature(uint8_t *uid, uint8_t uidlen, uint8_t *signature, size_t signature_len) {
437 if (uid == NULL) {
438 PrintAndLogEx(DEBUG, "UID=NULL");
439 return PM3_EINVARG;
441 if (signature == NULL) {
442 PrintAndLogEx(DEBUG, "SIGNATURE=NULL");
443 return PM3_EINVARG;
445 // ref: MIFARE Desfire Originality Signature Validation
446 // See tools/recover_pk.py to recover Pk from UIDs and signatures
447 #define PUBLIC_DESFIRE_ECDA_KEYLEN 57
448 const ecdsa_publickey_t nxp_desfire_public_keys[] = {
449 {"NTAG424DNA, DESFire Ev2", "048A9B380AF2EE1B98DC417FECC263F8449C7625CECE82D9B916C992DA209D68422B81EC20B65A66B5102A61596AF3379200599316A00A1410"},
450 {"NTAG413DNA, DESFire Ev1", "04BB5D514F7050025C7D0F397310360EEC91EAF792E96FC7E0F496CB4E669D414F877B7B27901FE67C2E3B33CD39D1C797715189AC951C2ADD"},
451 {"DESFire Ev2", "04B304DC4C615F5326FE9383DDEC9AA892DF3A57FA7FFB3276192BC0EAA252ED45A865E3B093A3D0DCE5BE29E92F1392CE7DE321E3E5C52B3A"},
452 {"DESFire Ev3", "041DB46C145D0A36539C6544BD6D9B0AA62FF91EC48CBC6ABAE36E0089A46F0D08C8A715EA40A63313B92E90DDC1730230E0458A33276FB743"},
453 {"NTAG424DNA, NTAG424DNATT, DESFire Light Ev2", "04B304DC4C615F5326FE9383DDEC9AA892DF3A57FA7FFB3276192BC0EAA252ED45A865E3B093A3D0DCE5BE29E92F1392CE7DE321E3E5C52B3B"},
454 {"DESFire Light", "040E98E117AAA36457F43173DC920A8757267F44CE4EC5ADD3C54075571AEBBF7B942A9774A1D94AD02572427E5AE0A2DD36591B1FB34FCF3D"},
455 {"MIFARE Plus Ev1", "044409ADC42F91A8394066BA83D872FB1D16803734E911170412DDF8BAD1A4DADFD0416291AFE1C748253925DA39A5F39A1C557FFACD34C62E"},
456 {"MIFARE Plus Ev2", "04BB49AE4447E6B1B6D21C098C1538B594A11A4A1DBF3D5E673DEACDEB3CC512D1C08AFA1A2768CE20A200BACD2DC7804CD7523A0131ABF607"},
457 {"DESFire Ev2 XL", "04CD5D45E50B1502F0BA4656FF37669597E7E183251150F9574CC8DA56BF01C7ABE019E29FEA48F9CE22C3EA4029A765E1BC95A89543BAD1BC"},
458 {"MIFARE Plus Troika", "040F732E0EA7DF2B38F791BF89425BF7DCDF3EE4D976669E3831F324FF15751BD52AFF1782F72FF2731EEAD5F63ABE7D126E03C856FFB942AF"},
462 uint32_t i;
463 bool is_valid = false;
465 for (i = 0; i < ARRAYLEN(nxp_desfire_public_keys); i++) {
467 int dl = 0;
468 uint8_t key[PUBLIC_DESFIRE_ECDA_KEYLEN];
469 param_gethex_to_eol(nxp_desfire_public_keys[i].value, 0, key, PUBLIC_DESFIRE_ECDA_KEYLEN, &dl);
471 int res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP224R1, key, uid, uidlen, signature, signature_len, false);
472 is_valid = (res == 0);
473 if (is_valid)
474 break;
476 // PrintAndLogEx(NORMAL, "");
477 // PrintAndLogEx(INFO, "--- " _CYAN_("Tag Signature"));
478 if (is_valid == false || i == ARRAYLEN(nxp_desfire_public_keys)) {
479 PrintAndLogEx(INFO, " Elliptic curve parameters: NID_secp224r1");
480 PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, 16));
481 PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 16, 16));
482 PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 32, 16));
483 PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 48, signature_len - 48));
484 PrintAndLogEx(SUCCESS, " Signature verification: " _RED_("failed"));
485 return PM3_ESOFT;
488 PrintAndLogEx(INFO, " IC signature public key name: " _GREEN_("%s"), nxp_desfire_public_keys[i].desc);
489 PrintAndLogEx(INFO, "IC signature public key value: %.32s", nxp_desfire_public_keys[i].value);
490 PrintAndLogEx(INFO, " : %.32s", nxp_desfire_public_keys[i].value + 32);
491 PrintAndLogEx(INFO, " : %.32s", nxp_desfire_public_keys[i].value + 64);
492 PrintAndLogEx(INFO, " : %.32s", nxp_desfire_public_keys[i].value + 96);
493 PrintAndLogEx(INFO, " Elliptic curve parameters: NID_secp224r1");
494 PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, 16));
495 PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 16, 16));
496 PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 32, 16));
497 PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 48, signature_len - 48));
498 PrintAndLogEx(SUCCESS, " Signature verification: " _GREEN_("successful"));
499 return PM3_SUCCESS;
502 static void swap24(uint8_t *data) {
503 if (data == NULL) return;
504 uint8_t tmp = data[0];
505 data[0] = data[2];
506 data[2] = tmp;
509 // default parameters
510 static uint8_t defaultKeyNum = 0;
511 static DesfireCryptoAlgorithm defaultAlgoId = T_DES;
512 static uint8_t defaultKey[DESFIRE_MAX_KEY_SIZE] = {0};
513 static int defaultKdfAlgo = MFDES_KDF_ALGO_NONE;
514 static int defaultKdfInputLen = 0;
515 static uint8_t defaultKdfInput[50] = {0};
516 static DesfireSecureChannel defaultSecureChannel = DACEV1;
517 static DesfireCommandSet defaultCommSet = DCCNativeISO;
518 static DesfireCommunicationMode defaultCommMode = DCMPlain;
519 static uint32_t transactionCounter = 0;
521 static int CmdDesGetSessionParameters(CLIParserContext *ctx, DesfireContext_t *dctx,
522 uint8_t keynoid, uint8_t algoid, uint8_t keyid,
523 uint8_t kdfid, uint8_t kdfiid,
524 uint8_t cmodeid, uint8_t ccsetid, uint8_t schannid,
525 uint8_t appid,
526 uint8_t appisoid,
527 int *securechannel,
528 DesfireCommunicationMode defcommmode,
529 uint32_t *id,
530 DesfireISOSelectWay *selectway) {
532 uint8_t keynum = defaultKeyNum;
533 int algores = defaultAlgoId;
534 uint8_t key[DESFIRE_MAX_KEY_SIZE] = {0};
535 memcpy(key, defaultKey, DESFIRE_MAX_KEY_SIZE);
537 int kdfAlgo = defaultKdfAlgo;
539 int kdfInputLen = defaultKdfInputLen;
540 uint8_t kdfInput[50] = {0};
541 memcpy(kdfInput, defaultKdfInput, defaultKdfInputLen);
543 int commmode = defaultCommMode;
544 if (defcommmode != DCMNone)
545 commmode = defcommmode;
547 int commset = defaultCommSet;
548 int secchann = defaultSecureChannel;
550 if (keynoid) {
551 keynum = arg_get_int_def(ctx, keynoid, keynum);
554 if (algoid) {
555 if (CLIGetOptionList(arg_get_str(ctx, algoid), DesfireAlgoOpts, &algores)) {
556 return PM3_ESOFT;
560 if (keyid) {
561 int keylen = 0;
562 uint8_t keydata[200] = {0};
563 if (CLIParamHexToBuf(arg_get_str(ctx, keyid), keydata, sizeof(keydata), &keylen)) {
564 return PM3_ESOFT;
567 if (keylen && keylen != desfire_get_key_length(algores)) {
568 PrintAndLogEx(ERR, "%s key must have %d bytes length instead of %d.", CLIGetOptionListStr(DesfireAlgoOpts, algores), desfire_get_key_length(algores), keylen);
569 return PM3_EINVARG;
572 if (keylen) {
573 memcpy(key, keydata, keylen);
577 if (kdfid) {
578 if (CLIGetOptionList(arg_get_str(ctx, kdfid), DesfireKDFAlgoOpts, &kdfAlgo)) {
579 return PM3_ESOFT;
583 if (kdfiid) {
584 int datalen = kdfInputLen;
585 uint8_t data[200] = {0};
586 if (CLIParamHexToBuf(arg_get_str(ctx, kdfiid), data, sizeof(data), &datalen)) {
587 return PM3_ESOFT;
590 if (datalen) {
591 kdfInputLen = datalen;
592 memcpy(kdfInput, data, datalen);
596 if (cmodeid) {
597 if (CLIGetOptionList(arg_get_str(ctx, cmodeid), DesfireCommunicationModeOpts, &commmode))
598 return PM3_ESOFT;
601 if (ccsetid) {
602 if (CLIGetOptionList(arg_get_str(ctx, ccsetid), DesfireCommandSetOpts, &commset))
603 return PM3_ESOFT;
606 if (schannid) {
608 if (CLIGetOptionList(arg_get_str(ctx, schannid), DesfireSecureChannelOpts, &secchann))
609 return PM3_ESOFT;
612 if (appid && id) {
613 *id = 0x000000;
614 if (CLIGetUint32Hex(ctx, appid, 0x000000, id, NULL, 3, "AID must have 3 bytes length"))
615 return PM3_EINVARG;
616 if (selectway)
617 *selectway = ISW6bAID;
620 if (appisoid && id) {
621 uint32_t xisoid = 0x0000;
622 bool isoidpresent = false;
623 if (CLIGetUint32Hex(ctx, appisoid, 0x0000, &xisoid, &isoidpresent, 2, "Application ISO ID (for EF) must have 2 bytes length"))
624 return PM3_EINVARG;
626 if (isoidpresent) {
627 *id = xisoid & 0xffff;
628 if (selectway)
629 *selectway = ISWIsoID;
633 DesfireSetKey(dctx, keynum, algores, key);
634 DesfireSetKdf(dctx, kdfAlgo, kdfInput, kdfInputLen);
635 DesfireSetCommandSet(dctx, commset);
636 DesfireSetCommMode(dctx, commmode);
637 if (securechannel)
638 *securechannel = secchann;
640 return PM3_SUCCESS;
643 static int CmdHF14ADesDefault(const char *Cmd) {
644 CLIParserContext *ctx;
645 CLIParserInit(&ctx, "hf mfdes default",
646 "Set default parameters for access to MIFARE DESfire card.",
647 "hf mfdes default -n 0 -t des -k 0000000000000000 --kdf none -> save to the default parameters");
649 void *argtable[] = {
650 arg_param_begin,
651 arg_int0("n", "keyno", "<dec>", "Key number"),
652 arg_str0("t", "algo", "<DES|2TDEA|3TDEA|AES>", "Crypt algo"),
653 arg_str0("k", "key", "<hex>", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"),
654 arg_str0(NULL, "kdf", "<none|AN10922|gallagher>", "Key Derivation Function (KDF)"),
655 arg_str0("i", "kdfi", "<hex>", "KDF input (1-31 hex bytes)"),
656 arg_str0("m", "cmode", "<plain|mac|encrypt>", "Communicaton mode"),
657 arg_str0("c", "ccset", "<native|niso|iso>", "Communicaton command set"),
658 arg_str0(NULL, "schann", "<d40|ev1|ev2|lrp>", "Secure channel"),
659 arg_param_end
661 CLIExecWithReturn(ctx, Cmd, argtable, true);
663 DesfireContext_t dctx;
664 int securechann = defaultSecureChannel;
665 int res = CmdDesGetSessionParameters(ctx, &dctx, 1, 2, 3, 4, 5, 6, 7, 8, 0, 0, &securechann, DCMNone, NULL, NULL);
666 if (res) {
667 CLIParserFree(ctx);
668 return res;
671 CLIParserFree(ctx);
673 defaultKeyNum = dctx.keyNum;
674 defaultAlgoId = dctx.keyType;
675 memcpy(defaultKey, dctx.key, DESFIRE_MAX_KEY_SIZE);
676 defaultKdfAlgo = dctx.kdfAlgo;
677 defaultKdfInputLen = dctx.kdfInputLen;
678 memcpy(defaultKdfInput, dctx.kdfInput, sizeof(dctx.kdfInput));
679 defaultSecureChannel = securechann;
680 defaultCommSet = dctx.cmdSet;
681 defaultCommMode = dctx.commMode;
683 PrintAndLogEx(INFO, "-----------" _CYAN_("Default parameters") "---------------------------------");
685 PrintAndLogEx(INFO, "Key Num : %d", defaultKeyNum);
686 PrintAndLogEx(INFO, "Algo : %s", CLIGetOptionListStr(DesfireAlgoOpts, defaultAlgoId));
687 PrintAndLogEx(INFO, "Key : %s", sprint_hex(defaultKey, desfire_get_key_length(defaultAlgoId)));
688 PrintAndLogEx(INFO, "KDF algo : %s", CLIGetOptionListStr(DesfireKDFAlgoOpts, defaultKdfAlgo));
689 PrintAndLogEx(INFO, "KDF input : [%d] %s", defaultKdfInputLen, sprint_hex(defaultKdfInput, defaultKdfInputLen));
690 PrintAndLogEx(INFO, "Secure chan : %s", CLIGetOptionListStr(DesfireSecureChannelOpts, defaultSecureChannel));
691 PrintAndLogEx(INFO, "Command set : %s", CLIGetOptionListStr(DesfireCommandSetOpts, defaultCommSet));
692 PrintAndLogEx(INFO, "Comm mode : %s", CLIGetOptionListStr(DesfireCommunicationModeOpts, defaultCommMode));
694 return PM3_SUCCESS;
697 static int CmdHF14ADesInfo(const char *Cmd) {
698 CLIParserContext *ctx;
699 CLIParserInit(&ctx, "hf mfdes info",
700 "Get info from MIFARE DESfire tags",
701 "hf mfdes info");
703 void *argtable[] = {
704 arg_param_begin,
705 arg_param_end
707 CLIExecWithReturn(ctx, Cmd, argtable, true);
708 CLIParserFree(ctx);
710 SetAPDULogging(false);
711 DropField();
713 mfdes_info_res_t info;
714 int res = mfdes_get_info(&info);
715 if (res != PM3_SUCCESS) {
716 DropField();
717 return res;
720 nxp_cardtype_t cardtype = getCardType(info.versionHW[1], info.versionHW[3], info.versionHW[4]);
721 if (cardtype == PLUS_EV1) {
722 PrintAndLogEx(INFO, "Card seems to be MIFARE Plus EV1. Try " _YELLOW_("`hf mfp info`"));
723 DropField();
724 return PM3_SUCCESS;
727 if (cardtype == PLUS_EV2) {
728 PrintAndLogEx(INFO, "Card seems to be MIFARE Plus EV2. Try " _YELLOW_("`hf mfp info`"));
729 DropField();
730 return PM3_SUCCESS;
733 if (cardtype == NTAG424) {
734 PrintAndLogEx(INFO, "Card seems to be NTAG 424. Try " _YELLOW_("`hf ntag424 info`"));
735 DropField();
736 return PM3_SUCCESS;
739 if (cardtype == DESFIRE_UNKNOWN) {
740 PrintAndLogEx(INFO, "HW Version.. %s", sprint_hex_inrow(info.versionHW, sizeof(info.versionHW)));
741 PrintAndLogEx(INFO, "SW Version.. %s", sprint_hex_inrow(info.versionSW, sizeof(info.versionSW)));
742 PrintAndLogEx(INFO, "Version data identification failed. Report to Iceman!");
743 DropField();
744 return PM3_SUCCESS;
747 PrintAndLogEx(NORMAL, "");
748 PrintAndLogEx(INFO, "---------------------------------- " _CYAN_("Tag Information") " ----------------------------------");
749 PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(info.uid, info.uidlen));
750 PrintAndLogEx(SUCCESS, " Batch number: " _GREEN_("%s"), sprint_hex(info.details + 7, 5));
751 PrintAndLogEx(SUCCESS, " Production date: week " _GREEN_("%02x") " / " _GREEN_("20%02x"), info.details[12], info.details[13]);
753 nxp_producttype_t prodtype = getProductType(info.versionHW);
754 if (prodtype != DESFIRE_UNKNOWN_PROD) {
755 PrintAndLogEx(SUCCESS, " Product type: %s", getProductTypeStr(info.versionHW));
758 PrintAndLogEx(NORMAL, "");
759 PrintAndLogEx(INFO, "--- " _CYAN_("Hardware Information"));
760 PrintAndLogEx(INFO, " raw: %s", sprint_hex_inrow(info.versionHW, sizeof(info.versionHW)));
762 PrintAndLogEx(INFO, " Vendor Id: " _YELLOW_("%s"), getTagInfo(info.versionHW[0]));
763 PrintAndLogEx(INFO, " Type: %s", getTypeStr(info.versionHW[1]));
764 PrintAndLogEx(INFO, " Subtype: " _YELLOW_("0x%02X"), info.versionHW[2]);
765 PrintAndLogEx(INFO, " Version: %s", getVersionStr(info.versionHW[1], info.versionHW[3], info.versionHW[4]));
766 PrintAndLogEx(INFO, " Storage size: %s", getCardSizeStr(info.versionHW[5]));
767 PrintAndLogEx(INFO, " Protocol: %s", getProtocolStr(info.versionHW[6], true));
768 PrintAndLogEx(NORMAL, "");
769 PrintAndLogEx(INFO, "--- " _CYAN_("Software Information"));
770 PrintAndLogEx(INFO, " raw: %s", sprint_hex_inrow(info.versionSW, sizeof(info.versionSW)));
771 PrintAndLogEx(INFO, " Vendor Id: " _YELLOW_("%s"), getTagInfo(info.versionSW[0]));
772 PrintAndLogEx(INFO, " Type: %s", getTypeStr(info.versionSW[1]));
773 PrintAndLogEx(INFO, " Subtype: " _YELLOW_("0x%02X"), info.versionSW[2]);
774 PrintAndLogEx(INFO, " Version: " _YELLOW_("%d.%d"), info.versionSW[3], info.versionSW[4]);
775 PrintAndLogEx(INFO, " Storage size: %s", getCardSizeStr(info.versionSW[5]));
776 PrintAndLogEx(INFO, " Protocol: %s", getProtocolStr(info.versionSW[6], false));
777 PrintAndLogEx(NORMAL, "");
778 PrintAndLogEx(INFO, "--------------------------------- " _CYAN_("Card capabilities") " ---------------------------------");
779 uint8_t major = info.versionSW[3];
780 uint8_t minor = info.versionSW[4];
781 if (major == 0 && minor == 4)
782 PrintAndLogEx(INFO, "\t0.4 - DESFire MF3ICD40, No support for APDU (only native commands)");
783 if (major == 0 && minor == 5)
784 PrintAndLogEx(INFO, "\t0.5 - DESFire MF3ICD40, Support for wrapping commands inside ISO 7816 style APDUs");
785 if (major == 0 && minor == 6)
786 PrintAndLogEx(INFO, "\t0.6 - DESFire MF3ICD40, Add ISO/IEC 7816 command set compatibility");
787 if (major == 1 && minor == 3)
788 PrintAndLogEx(INFO, "\t1.3 - DESFire Ev1 MF3ICD21/41/81, Support extended APDU commands, EAL4+");
789 if (major == 1 && minor == 4)
790 PrintAndLogEx(INFO, "\t1.4 - DESFire Ev1 MF3ICD21/41/81, EAL4+");
791 if (major == 2 && minor == 0)
792 PrintAndLogEx(INFO, "\t2.0 - DESFire Ev2, Originality check, proximity check, EAL5");
793 if (major == 2 && minor == 2)
794 PrintAndLogEx(INFO, "\t2.2 - DESFire Ev2 XL, Originality check, proximity check, EAL5");
795 if (major == 3 && minor == 0)
796 PrintAndLogEx(INFO, "\t3.0 - DESFire Ev3, Originality check, proximity check, badass EAL6 ?");
798 if (major == 0 && minor == 2)
799 PrintAndLogEx(INFO, "\t0.2 - DESFire Light, Originality check, ");
801 DesfireContext_t dctx = {0};
802 dctx.commMode = DCMPlain;
803 dctx.cmdSet = DCCNative;
805 res = DesfireAnticollision(false);
806 if (res != PM3_SUCCESS) {
807 DropField();
808 return res;
811 if (cardtype == DESFIRE_EV2 || cardtype == DESFIRE_EV2_XL ||
812 cardtype == DESFIRE_LIGHT ||
813 cardtype == DESFIRE_EV3 ||
814 cardtype == NTAG413DNA) {
815 // Signature originality check
816 uint8_t signature[250] = {0}; // must be 56
817 size_t signature_len = 0;
819 PrintAndLogEx(NORMAL, "");
820 PrintAndLogEx(INFO, "--- " _CYAN_("Tag Signature"));
821 res = DesfireReadSignature(&dctx, 0x00, signature, &signature_len);
822 if (res == PM3_SUCCESS) {
823 if (signature_len == 56)
824 desfire_print_signature(info.uid, info.uidlen, signature, signature_len);
825 else
826 PrintAndLogEx(WARNING, "--- GetSignature returned wrong signature length: %zu", signature_len);
827 } else {
828 PrintAndLogEx(WARNING, "--- Card doesn't support GetSignature cmd");
832 PICCInfo_t PICCInfo = {0};
834 uint8_t aidbuf[250] = {0};
835 size_t aidbuflen = 0;
836 res = DesfireGetAIDList(&dctx, aidbuf, &aidbuflen);
837 if (res == PM3_SUCCESS) {
838 PICCInfo.appCount = aidbuflen / 3;
841 if (aidbuflen > 2) {
842 PrintAndLogEx(NORMAL, "");
843 PrintAndLogEx(SUCCESS, "--- " _CYAN_("AID list"));
844 PrintAndLogEx(SUCCESS, "AIDs: " NOLF);
845 for (int i = 0; i < aidbuflen; i += 3)
846 PrintAndLogEx(NORMAL, "%s %06x" NOLF, (i == 0) ? "" : ",", DesfireAIDByteToUint(&aidbuf[i]));
847 PrintAndLogEx(NORMAL, "\n");
850 DesfireFillPICCInfo(&dctx, &PICCInfo, true);
851 DesfirePrintPICCInfo(&dctx, &PICCInfo);
853 if (cardtype != DESFIRE_LIGHT) {
854 // Free memory on card
855 PrintAndLogEx(NORMAL, "");
856 PrintAndLogEx(INFO, "--- " _CYAN_("Free memory"));
857 if (PICCInfo.freemem != 0xffffffff) {
858 PrintAndLogEx(SUCCESS, " Available free memory on card : " _GREEN_("%d bytes"), PICCInfo.freemem);
859 } else {
860 PrintAndLogEx(SUCCESS, " Card doesn't support 'free mem' cmd");
864 if (cardtype == DESFIRE_LIGHT) {
865 PrintAndLogEx(NORMAL, "");
866 PrintAndLogEx(INFO, "--- " _CYAN_("Desfire Light info"));
868 if (DesfireSelect(&dctx, ISWIsoID, 0xdf01, NULL) == PM3_SUCCESS) {
869 PrintAndLogEx(SUCCESS, " Card have " _GREEN_("default (0xdf01)") " iso id for application");
871 if (DesfireCheckAuthCmd(ISWIsoID, 0xdf01, 0, MFDES_AUTHENTICATE_EV2F, false)) {
872 PrintAndLogEx(SUCCESS, " Card in the " _GREEN_("AES") " mode");
873 } else if (DesfireCheckAuthCmd(ISWIsoID, 0xdf01, 0, MFDES_AUTHENTICATE_EV2F, true)) {
874 PrintAndLogEx(SUCCESS, " Card in the " _GREEN_("LRP") " mode");
876 } else {
877 PrintAndLogEx(SUCCESS, " Card have " _RED_("not a default") " iso id for application");
880 if (DesfireCheckAuthCmd(ISWIsoID, 0x3f00, 1, MFDES_AUTHENTICATE_EV2F, true)) {
881 PrintAndLogEx(SUCCESS, " Card have " _GREEN_("LRP") " key in the MF/key1");
885 PrintAndLogEx(NORMAL, "");
887 iso14a_card_select_t card;
888 res = SelectCard14443A_4(true, false, &card);
889 if (res == PM3_SUCCESS) {
890 static const uint8_t STANDALONE_DESFIRE[] = { 0x75, 0x77, 0x81, 0x02 };
891 static const uint8_t JCOP_DESFIRE[] = { 0x75, 0xf7, 0xb1, 0x02 };
892 static const uint8_t JCOP3_DESFIRE[] = { 0x78, 0x77, 0x71, 0x02 };
894 if (card.sak == 0x20) {
896 if (card.ats_len >= 5) {
897 if (0 == memcmp(card.ats + 1, STANDALONE_DESFIRE, 4)) {
898 PrintAndLogEx(INFO, "Standalone DESFire");
900 if (0 == memcmp(card.ats + 1, JCOP_DESFIRE, 4)) {
901 PrintAndLogEx(INFO, "JCOP DESFire");
904 if (card.ats_len == 4) {
905 if (0 == memcmp(card.ats + 1, JCOP3_DESFIRE, 4)) {
906 PrintAndLogEx(INFO, "JCOP3 DESFire");
913 Card Master key (CMK) 0x00 AID = 00 00 00 (card level)
914 Application Master Key (AMK) 0x00 AID != 00 00 00
915 Application keys (APK) 0x01-0x0D
916 Application free 0x0E
917 Application never 0x0F
919 ACCESS RIGHTS:
920 keys 0,1,2,3 C
921 keys 4,5,6,7 RW
922 keys 8,9,10,11 W
923 keys 12,13,14,15 R
927 DropField();
928 return PM3_SUCCESS;
931 static void DesFill2bPattern(
932 uint8_t deskeyList[MAX_KEYS_LIST_LEN][8], uint32_t *deskeyListLen,
933 uint8_t aeskeyList[MAX_KEYS_LIST_LEN][16], uint32_t *aeskeyListLen,
934 uint8_t k3kkeyList[MAX_KEYS_LIST_LEN][24], uint32_t *k3kkeyListLen, uint32_t *startPattern) {
936 for (uint32_t pt = *startPattern; pt < 0x10000; pt++) {
937 if (*deskeyListLen != MAX_KEYS_LIST_LEN) {
938 deskeyList[*deskeyListLen][0] = (pt >> 8) & 0xff;
939 deskeyList[*deskeyListLen][1] = pt & 0xff;
940 memcpy(&deskeyList[*deskeyListLen][2], &deskeyList[*deskeyListLen][0], 2);
941 memcpy(&deskeyList[*deskeyListLen][4], &deskeyList[*deskeyListLen][0], 4);
942 (*deskeyListLen)++;
944 if (*aeskeyListLen != MAX_KEYS_LIST_LEN) {
945 aeskeyList[*aeskeyListLen][0] = (pt >> 8) & 0xff;
946 aeskeyList[*aeskeyListLen][1] = pt & 0xff;
947 memcpy(&aeskeyList[*aeskeyListLen][2], &aeskeyList[*aeskeyListLen][0], 2);
948 memcpy(&aeskeyList[*aeskeyListLen][4], &aeskeyList[*aeskeyListLen][0], 4);
949 memcpy(&aeskeyList[*aeskeyListLen][8], &aeskeyList[*aeskeyListLen][0], 8);
950 (*aeskeyListLen)++;
952 if (*k3kkeyListLen != MAX_KEYS_LIST_LEN) {
953 k3kkeyList[*k3kkeyListLen][0] = (pt >> 8) & 0xff;
954 k3kkeyList[*k3kkeyListLen][1] = pt & 0xff;
955 memcpy(&k3kkeyList[*k3kkeyListLen][2], &k3kkeyList[*k3kkeyListLen][0], 2);
956 memcpy(&k3kkeyList[*k3kkeyListLen][4], &k3kkeyList[*k3kkeyListLen][0], 4);
957 memcpy(&k3kkeyList[*k3kkeyListLen][8], &k3kkeyList[*k3kkeyListLen][0], 8);
958 memcpy(&k3kkeyList[*k3kkeyListLen][16], &k3kkeyList[*k3kkeyListLen][0], 4);
959 (*k3kkeyListLen)++;
962 *startPattern = pt;
963 if ((*deskeyListLen == MAX_KEYS_LIST_LEN) &&
964 (*aeskeyListLen == MAX_KEYS_LIST_LEN) &&
965 (*k3kkeyListLen == MAX_KEYS_LIST_LEN)) {
966 break;
969 (*startPattern)++;
972 static int AuthCheckDesfire(DesfireContext_t *dctx,
973 DesfireSecureChannel secureChannel,
974 const uint8_t *aid,
975 uint8_t deskeyList[MAX_KEYS_LIST_LEN][8], uint32_t deskeyListLen,
976 uint8_t aeskeyList[MAX_KEYS_LIST_LEN][16], uint32_t aeskeyListLen,
977 uint8_t k3kkeyList[MAX_KEYS_LIST_LEN][24], uint32_t k3kkeyListLen,
978 uint8_t cmdKdfAlgo, uint8_t kdfInputLen, uint8_t *kdfInput,
979 uint8_t foundKeys[4][0xE][24 + 1],
980 bool *result,
981 bool verbose) {
983 uint32_t curaid = (aid[0] & 0xFF) + ((aid[1] & 0xFF) << 8) + ((aid[2] & 0xFF) << 16);
985 int res = DesfireSelectAIDHex(dctx, curaid, false, 0);
986 if (res != PM3_SUCCESS) {
987 PrintAndLogEx(ERR, "AID 0x%06X does not exist.", curaid);
988 DropField();
989 return PM3_ESOFT;
992 int usedkeys[0xF] = {0};
993 bool des = false;
994 bool tdes = false;
995 bool aes = false;
996 bool k3kdes = false;
998 uint8_t data[250] = {0};
999 size_t datalen = 0;
1001 res = DesfireGetKeySettings(dctx, data, &datalen);
1002 if (res != PM3_SUCCESS && datalen < 2) {
1003 PrintAndLogEx(ERR, "Could not get key settings");
1004 return res;
1006 uint8_t num_keys = data[1];
1007 switch (num_keys >> 6) {
1008 case 0:
1009 des = true;
1010 tdes = true;
1011 break;
1012 case 1:
1013 k3kdes = true;
1014 break;
1015 case 2:
1016 aes = true;
1017 break;
1018 default:
1019 break;
1022 // always check master key
1023 usedkeys[0] = 1;
1025 if (curaid != 0) {
1026 FileList_t fileList = {{0}};
1027 size_t filescount = 0;
1028 bool isopresent = 0;
1029 res = DesfireFillFileList(dctx, fileList, &filescount, &isopresent);
1030 if (res == PM3_SUCCESS) {
1031 if (filescount > 0) {
1032 for (int i = 0; i < filescount; i++) {
1033 if (fileList[i].fileSettings.rAccess < 0x0e)
1034 usedkeys[fileList[i].fileSettings.rAccess] = 1;
1035 if (fileList[i].fileSettings.wAccess < 0x0e)
1036 usedkeys[fileList[i].fileSettings.wAccess] = 1;
1037 if (fileList[i].fileSettings.rwAccess < 0x0e)
1038 usedkeys[fileList[i].fileSettings.rwAccess] = 1;
1039 if (fileList[i].fileSettings.chAccess < 0x0e)
1040 usedkeys[fileList[i].fileSettings.chAccess] = 1;
1042 } else {
1043 for (int i = 0; i < 0xE; i++)
1044 usedkeys[i] = 1;
1046 } else {
1047 for (int i = 0; i < 0xE; i++)
1048 usedkeys[i] = 1;
1052 if (verbose) {
1053 PrintAndLogEx(INFO, "Check: %s %s %s %s " NOLF, (des) ? "DES" : "", (tdes) ? "2TDEA" : "", (k3kdes) ? "3TDEA" : "", (aes) ? "AES" : "");
1054 PrintAndLogEx(NORMAL, "keys: " NOLF);
1055 for (int i = 0; i < 0xE; i++)
1056 if (usedkeys[i] == 1)
1057 PrintAndLogEx(NORMAL, "%02x " NOLF, i);
1058 PrintAndLogEx(NORMAL, "");
1061 bool badlen = false;
1063 if (des) {
1065 for (uint8_t keyno = 0; keyno < 0xE; keyno++) {
1067 if (usedkeys[keyno] == 1 && foundKeys[0][keyno][0] == 0) {
1068 for (uint32_t curkey = 0; curkey < deskeyListLen; curkey++) {
1069 DesfireSetKeyNoClear(dctx, keyno, T_DES, deskeyList[curkey]);
1070 res = DesfireAuthenticate(dctx, secureChannel, false);
1071 if (res == PM3_SUCCESS) {
1072 PrintAndLogEx(SUCCESS, "AID 0x%06X, Found DES Key %02u : " _GREEN_("%s"), curaid, keyno, sprint_hex(deskeyList[curkey], 8));
1073 foundKeys[0][keyno][0] = 0x01;
1074 *result = true;
1075 memcpy(&foundKeys[0][keyno][1], deskeyList[curkey], 8);
1076 break;
1077 } else if (res < 7) {
1078 badlen = true;
1079 DropField();
1080 res = DesfireSelectAIDHex(dctx, curaid, false, 0);
1081 if (res != PM3_SUCCESS) {
1082 return res;
1084 break;
1087 if (badlen == true) {
1088 badlen = false;
1089 break;
1095 if (tdes) {
1097 for (uint8_t keyno = 0; keyno < 0xE; keyno++) {
1099 if (usedkeys[keyno] == 1 && foundKeys[1][keyno][0] == 0) {
1100 for (uint32_t curkey = 0; curkey < aeskeyListLen; curkey++) {
1101 DesfireSetKeyNoClear(dctx, keyno, T_3DES, aeskeyList[curkey]);
1102 res = DesfireAuthenticate(dctx, secureChannel, false);
1103 if (res == PM3_SUCCESS) {
1104 PrintAndLogEx(SUCCESS, "AID 0x%06X, Found 2TDEA Key %02u : " _GREEN_("%s"), curaid, keyno, sprint_hex(aeskeyList[curkey], 16));
1105 foundKeys[1][keyno][0] = 0x01;
1106 *result = true;
1107 memcpy(&foundKeys[1][keyno][1], aeskeyList[curkey], 16);
1108 break;
1109 } else if (res < 7) {
1110 badlen = true;
1111 DropField();
1112 res = DesfireSelectAIDHex(dctx, curaid, false, 0);
1113 if (res != PM3_SUCCESS) {
1114 return res;
1116 break;
1119 if (badlen == true) {
1120 badlen = false;
1121 break;
1127 if (aes) {
1129 for (uint8_t keyno = 0; keyno < 0xE; keyno++) {
1131 if (usedkeys[keyno] == 1 && foundKeys[2][keyno][0] == 0) {
1132 for (uint32_t curkey = 0; curkey < aeskeyListLen; curkey++) {
1133 DesfireSetKeyNoClear(dctx, keyno, T_AES, aeskeyList[curkey]);
1134 res = DesfireAuthenticate(dctx, secureChannel, false);
1135 if (res == PM3_SUCCESS) {
1136 PrintAndLogEx(SUCCESS, "AID 0x%06X, Found AES Key %02u : " _GREEN_("%s"), curaid, keyno, sprint_hex(aeskeyList[curkey], 16));
1137 foundKeys[2][keyno][0] = 0x01;
1138 *result = true;
1139 memcpy(&foundKeys[2][keyno][1], aeskeyList[curkey], 16);
1140 break;
1141 } else if (res < 7) {
1142 badlen = true;
1143 DropField();
1144 res = DesfireSelectAIDHex(dctx, curaid, false, 0);
1145 if (res != PM3_SUCCESS) {
1146 return res;
1148 break;
1151 if (badlen == true) {
1152 badlen = false;
1153 break;
1159 if (k3kdes) {
1161 for (uint8_t keyno = 0; keyno < 0xE; keyno++) {
1163 if (usedkeys[keyno] == 1 && foundKeys[3][keyno][0] == 0) {
1164 for (uint32_t curkey = 0; curkey < k3kkeyListLen; curkey++) {
1165 DesfireSetKeyNoClear(dctx, keyno, T_3K3DES, k3kkeyList[curkey]);
1166 res = DesfireAuthenticate(dctx, secureChannel, false);
1167 if (res == PM3_SUCCESS) {
1168 PrintAndLogEx(SUCCESS, "AID 0x%06X, Found 3TDEA Key %02u : " _GREEN_("%s"), curaid, keyno, sprint_hex(k3kkeyList[curkey], 24));
1169 foundKeys[3][keyno][0] = 0x01;
1170 *result = true;
1171 memcpy(&foundKeys[3][keyno][1], k3kkeyList[curkey], 16);
1172 break;
1173 } else if (res < 7) {
1174 badlen = true;
1175 DropField();
1176 res = DesfireSelectAIDHex(dctx, curaid, false, 0);
1177 if (res != PM3_SUCCESS) {
1178 return res;
1180 break;
1184 if (badlen == true) {
1185 break;
1190 DropField();
1191 return PM3_SUCCESS;
1194 static int CmdHF14aDesChk(const char *Cmd) {
1195 int res;
1196 uint8_t deskeyList[MAX_KEYS_LIST_LEN][8] = {{0}};
1197 uint8_t aeskeyList[MAX_KEYS_LIST_LEN][16] = {{0}};
1198 uint8_t k3kkeyList[MAX_KEYS_LIST_LEN][MAX_KEY_LEN] = {{0}};
1199 uint32_t deskeyListLen = 0;
1200 uint32_t aeskeyListLen = 0;
1201 uint32_t k3kkeyListLen = 0;
1202 uint8_t foundKeys[4][0xE][24 + 1] = {{{0}}};
1204 CLIParserContext *ctx;
1205 CLIParserInit(&ctx, "hf mfdes chk",
1206 "Checks keys with MIFARE DESFire card.",
1207 "hf mfdes chk --aid 123456 -k 000102030405060708090a0b0c0d0e0f -> check key on aid 0x123456\n"
1208 "hf mfdes chk -d mfdes_default_keys -> check keys against all existing aid on card\n"
1209 "hf mfdes chk -d mfdes_default_keys --aid 123456 -> check keys against aid 0x123456\n"
1210 "hf mfdes chk --aid 123456 --pattern1b -j keys -> check all 1-byte keys pattern on aid 0x123456 and save found keys to `keys.json`\n"
1211 "hf mfdes chk --aid 123456 --pattern2b --startp2b FA00 -> check all 2-byte keys pattern on aid 0x123456. Start from key FA00FA00...FA00");
1213 void *argtable[] = {
1214 arg_param_begin,
1215 arg_str0(NULL, "aid", "<hex>", "Use specific AID (3 hex bytes, big endian)"),
1216 arg_str0("k", "key", "<hex>", "Key for checking (HEX 16 bytes)"),
1217 arg_str0("d", "dict", "<fn>", "Dictionary file with keys"),
1218 arg_lit0(NULL, "pattern1b", "Check all 1-byte combinations of key (0000...0000, 0101...0101, 0202...0202, ...)"),
1219 arg_lit0(NULL, "pattern2b", "Check all 2-byte combinations of key (0000...0000, 0001...0001, 0002...0002, ...)"),
1220 arg_str0(NULL, "startp2b", "<pattern>", "Start key (2-byte HEX) for 2-byte search (use with `--pattern2b`)"),
1221 arg_str0("j", "json", "<fn>", "Json file name to save keys"),
1222 arg_lit0("v", "verbose", "Verbose output"),
1223 arg_int0(NULL, "kdf", "<0|1|2>", "Key Derivation Function (KDF) (0=None, 1=AN10922, 2=Gallagher)"),
1224 arg_str0("i", "kdfi", "<hex>", "KDF input (1-31 hex bytes)"),
1225 arg_lit0("a", "apdu", "Show APDU requests and responses"),
1226 arg_param_end
1228 CLIExecWithReturn(ctx, Cmd, argtable, false);
1230 bool APDULogging = arg_get_lit(ctx, 11);
1232 int aidlength = 0;
1233 uint8_t aid[3] = {0};
1234 CLIGetHexWithReturn(ctx, 1, aid, &aidlength);
1235 swap24(aid);
1236 uint8_t vkey[16] = {0};
1237 int vkeylen = 0;
1238 CLIGetHexWithReturn(ctx, 2, vkey, &vkeylen);
1240 if (vkeylen > 0) {
1241 if (vkeylen == 8) {
1242 memcpy(&deskeyList[deskeyListLen], vkey, 8);
1243 deskeyListLen++;
1244 } else if (vkeylen == 16) {
1245 memcpy(&aeskeyList[aeskeyListLen], vkey, 16);
1246 aeskeyListLen++;
1247 } else if (vkeylen == 24) {
1248 memcpy(&k3kkeyList[k3kkeyListLen], vkey, 16);
1249 k3kkeyListLen++;
1250 } else {
1251 PrintAndLogEx(ERR, "Specified key must have 8, 16 or 24 bytes length.");
1252 CLIParserFree(ctx);
1253 return PM3_EINVARG;
1257 uint8_t dict_filename[FILE_PATH_SIZE + 2] = {0};
1258 int dict_filenamelen = 0;
1259 if (CLIParamStrToBuf(arg_get_str(ctx, 3), dict_filename, FILE_PATH_SIZE, &dict_filenamelen)) {
1260 PrintAndLogEx(FAILED, "File name too long or invalid.");
1261 CLIParserFree(ctx);
1262 return PM3_EINVARG;
1265 bool pattern1b = arg_get_lit(ctx, 4);
1266 bool pattern2b = arg_get_lit(ctx, 5);
1268 if (pattern1b && pattern2b) {
1269 PrintAndLogEx(ERR, "Pattern search mode must be 2-byte or 1-byte only.");
1270 CLIParserFree(ctx);
1271 return PM3_EINVARG;
1274 if (dict_filenamelen && (pattern1b || pattern2b)) {
1275 PrintAndLogEx(ERR, "Pattern search mode and dictionary mode can't be used in one command.");
1276 CLIParserFree(ctx);
1277 return PM3_EINVARG;
1280 uint32_t startPattern = 0x0000;
1281 uint8_t vpattern[2];
1282 int vpatternlen = 0;
1283 CLIGetHexWithReturn(ctx, 6, vpattern, &vpatternlen);
1284 if (vpatternlen > 0) {
1285 if (vpatternlen <= 2) {
1286 startPattern = (vpattern[0] << 8) + vpattern[1];
1287 } else {
1288 PrintAndLogEx(ERR, "Pattern must be 2-byte length.");
1289 CLIParserFree(ctx);
1290 return PM3_EINVARG;
1292 if (!pattern2b)
1293 PrintAndLogEx(WARNING, "Pattern entered, but search mode not is 2-byte search.");
1296 uint8_t jsonname[250] = {0};
1297 int jsonnamelen = 0;
1298 if (CLIParamStrToBuf(arg_get_str(ctx, 7), jsonname, sizeof(jsonname), &jsonnamelen)) {
1299 PrintAndLogEx(ERR, "Invalid json name.");
1300 CLIParserFree(ctx);
1301 return PM3_EINVARG;
1303 jsonname[jsonnamelen] = 0;
1305 bool verbose = arg_get_lit(ctx, 8);
1307 // Get KDF input
1308 uint8_t cmdKDFAlgo = arg_get_int_def(ctx, 9, 0);
1310 uint8_t kdfInput[31] = {0};
1311 int kdfInputLen = 0;
1312 CLIGetHexWithReturn(ctx, 10, kdfInput, &kdfInputLen);
1314 CLIParserFree(ctx);
1315 SetAPDULogging(APDULogging);
1317 // 1-byte pattern search mode
1318 if (pattern1b) {
1319 for (uint32_t i = 0; i < 0x100; i++)
1320 memset(aeskeyList[i], i, 16);
1321 for (uint32_t i = 0; i < 0x100; i++)
1322 memset(deskeyList[i], i, 8);
1323 for (uint32_t i = 0; i < 0x100; i++)
1324 memset(k3kkeyList[i], i, 24);
1325 aeskeyListLen = 0x100;
1326 deskeyListLen = 0x100;
1327 k3kkeyListLen = 0x100;
1330 // 2-byte pattern search mode
1331 if (pattern2b) {
1332 DesFill2bPattern(deskeyList, &deskeyListLen, aeskeyList, &aeskeyListLen, k3kkeyList, &k3kkeyListLen, &startPattern);
1335 // dictionary mode
1336 size_t endFilePosition = 0;
1337 if (dict_filenamelen) {
1339 res = loadFileDICTIONARYEx((char *)dict_filename, deskeyList, sizeof(deskeyList), NULL, 8, &deskeyListLen, 0, &endFilePosition, true);
1340 if (res == PM3_SUCCESS && endFilePosition)
1341 PrintAndLogEx(SUCCESS, "First part of des dictionary successfully loaded.");
1343 endFilePosition = 0;
1344 res = loadFileDICTIONARYEx((char *)dict_filename, aeskeyList, sizeof(aeskeyList), NULL, 16, &aeskeyListLen, 0, &endFilePosition, true);
1345 if (res == PM3_SUCCESS && endFilePosition)
1346 PrintAndLogEx(SUCCESS, "First part of aes dictionary successfully loaded.");
1348 endFilePosition = 0;
1349 res = loadFileDICTIONARYEx((char *)dict_filename, k3kkeyList, sizeof(k3kkeyList), NULL, 24, &k3kkeyListLen, 0, &endFilePosition, true);
1350 if (res == PM3_SUCCESS && endFilePosition)
1351 PrintAndLogEx(SUCCESS, "First part of k3kdes dictionary successfully loaded.");
1353 endFilePosition = 0;
1356 if (aeskeyListLen == 0 && deskeyListLen == 0 && k3kkeyListLen == 0) {
1357 PrintAndLogEx(ERR, "No keys provided. Nothing to check.");
1358 return PM3_EINVARG;
1361 if (aeskeyListLen != 0) {
1362 PrintAndLogEx(INFO, "Loaded " _YELLOW_("%"PRIu32) " aes keys", aeskeyListLen);
1365 if (deskeyListLen != 0) {
1366 PrintAndLogEx(INFO, "Loaded " _YELLOW_("%"PRIu32) " des keys", deskeyListLen);
1369 if (k3kkeyListLen != 0) {
1370 PrintAndLogEx(INFO, "Loaded " _YELLOW_("%"PRIu32) " k3kdes keys", k3kkeyListLen);
1373 if (verbose == false)
1374 PrintAndLogEx(INFO, "Search keys:");
1376 bool result = false;
1377 uint8_t app_ids[78] = {0};
1378 size_t app_ids_len = 0;
1380 clearCommandBuffer();
1382 DesfireContext_t dctx;
1383 DesfireSetKdf(&dctx, cmdKDFAlgo, kdfInput, kdfInputLen);
1384 DesfireSetCommandSet(&dctx, DCCNativeISO);
1385 DesfireSetCommMode(&dctx, DCMPlain);
1386 DesfireSecureChannel secureChannel = DACEV1;
1388 // save card UID to dctx
1389 DesfireGetCardUID(&dctx);
1391 res = DesfireSelectAIDHex(&dctx, 0x000000, false, 0);
1392 if (res != PM3_SUCCESS) {
1393 PrintAndLogEx(ERR, "Can't select PICC level.");
1394 DropField();
1395 return PM3_ESOFT;
1399 res = DesfireGetAIDList(&dctx, app_ids, &app_ids_len);
1400 if (res != PM3_SUCCESS) {
1401 PrintAndLogEx(ERR, "Can't get list of applications on tag");
1402 DropField();
1403 return PM3_ESOFT;
1406 if (aidlength != 0) {
1407 memcpy(&app_ids[0], aid, 3);
1408 app_ids_len = 3;
1411 for (uint32_t x = 0; x < app_ids_len / 3; x++) {
1413 uint32_t curaid = (app_ids[x * 3] & 0xFF) + ((app_ids[(x * 3) + 1] & 0xFF) << 8) + ((app_ids[(x * 3) + 2] & 0xFF) << 16);
1414 PrintAndLogEx(ERR, "Checking aid 0x%06X...", curaid);
1416 res = AuthCheckDesfire(&dctx, secureChannel, &app_ids[x * 3], deskeyList, deskeyListLen, aeskeyList, aeskeyListLen, k3kkeyList, k3kkeyListLen, cmdKDFAlgo, kdfInputLen, kdfInput, foundKeys, &result, (verbose == false));
1417 if (res == PM3_EOPABORTED) {
1418 break;
1421 if (pattern2b && startPattern < 0x10000) {
1422 if (verbose == false) {
1423 PrintAndLogEx(NORMAL, "p" NOLF);
1426 aeskeyListLen = 0;
1427 deskeyListLen = 0;
1428 k3kkeyListLen = 0;
1429 DesFill2bPattern(deskeyList, &deskeyListLen, aeskeyList, &aeskeyListLen, k3kkeyList, &k3kkeyListLen, &startPattern);
1430 continue;
1433 if (dict_filenamelen) {
1434 if (verbose == false) {
1435 PrintAndLogEx(NORMAL, "d" NOLF);
1438 uint32_t keycnt = 0;
1439 res = loadFileDICTIONARYEx((char *)dict_filename, deskeyList, sizeof(deskeyList), NULL, 16, &keycnt, endFilePosition, &endFilePosition, false);
1440 if (res == PM3_SUCCESS && endFilePosition) {
1441 deskeyListLen = keycnt;
1444 keycnt = 0;
1445 res = loadFileDICTIONARYEx((char *)dict_filename, aeskeyList, sizeof(aeskeyList), NULL, 16, &keycnt, endFilePosition, &endFilePosition, false);
1446 if (res == PM3_SUCCESS && endFilePosition) {
1447 aeskeyListLen = keycnt;
1450 keycnt = 0;
1451 res = loadFileDICTIONARYEx((char *)dict_filename, k3kkeyList, sizeof(k3kkeyList), NULL, 16, &keycnt, endFilePosition, &endFilePosition, false);
1452 if (res == PM3_SUCCESS && endFilePosition) {
1453 k3kkeyListLen = keycnt;
1456 continue;
1459 if (verbose == false) {
1460 PrintAndLogEx(NORMAL, "");
1463 // save keys to json
1464 if ((jsonnamelen > 0) && result) {
1465 DropField();
1466 // MIFARE DESFire info
1467 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0);
1469 PacketResponseNG resp;
1470 WaitForResponse(CMD_ACK, &resp);
1472 iso14a_card_select_t card;
1473 memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));
1475 uint64_t select_status = resp.oldarg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision
1477 uint8_t data[10 + 1 + 2 + 1 + 256 + (4 * 0xE * (24 + 1))] = {0};
1478 uint8_t atslen = 0;
1479 if (select_status == 1 || select_status == 2) {
1480 memcpy(data, card.uid, card.uidlen);
1481 data[10] = card.sak;
1482 data[11] = card.atqa[1];
1483 data[12] = card.atqa[0];
1484 atslen = card.ats_len;
1485 data[13] = atslen;
1486 memcpy(&data[14], card.ats, atslen);
1489 // length: UID(10b)+SAK(1b)+ATQA(2b)+ATSlen(1b)+ATS(atslen)+foundKeys[2][64][AES_KEY_LEN + 1]
1490 memcpy(&data[14 + atslen], foundKeys, 4 * 0xE * (24 + 1));
1491 saveFileJSON((char *)jsonname, jsfMfDesfireKeys, data, 0xE, NULL);
1494 DropField();
1495 return PM3_SUCCESS;
1498 static int CmdHF14ADesList(const char *Cmd) {
1499 return CmdTraceListAlias(Cmd, "hf mfdes", "des -c");
1502 static int DesfireAuthCheck(DesfireContext_t *dctx, DesfireISOSelectWay way, uint32_t appID, DesfireSecureChannel secureChannel, uint8_t *key) {
1503 DesfireSetKeyNoClear(dctx, dctx->keyNum, dctx->keyType, key);
1505 int res = DesfireAuthenticate(dctx, secureChannel, false);
1506 if (res == PM3_SUCCESS) {
1507 memcpy(dctx->key, key, desfire_get_key_length(dctx->keyType));
1508 return PM3_SUCCESS;
1509 } else if (res < 7) {
1510 DropField();
1511 res = DesfireSelect(dctx, way, appID, NULL);
1512 if (res != PM3_SUCCESS) {
1513 return -10;
1515 return -11;
1517 return -1;
1521 static int CmdHF14aDesDetect(const char *Cmd) {
1522 CLIParserContext *ctx;
1523 CLIParserInit(&ctx, "hf mfdes detect",
1524 "Detect key type and tries to find one from the list.",
1525 "hf mfdes detect -> detect key 0 from PICC level\n"
1526 "hf mfdes detect --schann d40 -> detect key 0 from PICC level via secure channel D40\n"
1527 "hf mfdes detect --dict mfdes_default_keys -> detect key 0 from PICC level with help of the standard dictionary\n"
1528 "hf mfdes detect --aid 123456 -n 2 --save -> detect key 2 from app 123456 and if succeed - save params to defaults (`default` command)\n"
1529 "hf mfdes detect --isoid df01 --save -> detect key 0 and save to defaults with card in the LRP mode");
1531 void *argtable[] = {
1532 arg_param_begin,
1533 arg_lit0("a", "apdu", "Show APDU requests and responses"),
1534 arg_lit0("v", "verbose", "Verbose output"),
1535 arg_int0("n", "keyno", "<dec>", "Key number"),
1536 arg_str0("t", "algo", "<DES|2TDEA|3TDEA|AES>", "Crypt algo"),
1537 arg_str0("k", "key", "<hex>", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"),
1538 arg_str0(NULL, "kdf", "<none|AN10922|gallagher>", "Key Derivation Function (KDF)"),
1539 arg_str0("i", "kdfi", "<hex>", "KDF input (1-31 hex bytes)"),
1540 arg_str0("m", "cmode", "<plain|mac|encrypt>", "Communicaton mode"),
1541 arg_str0("c", "ccset", "<native|niso|iso>", "Communicaton command set"),
1542 arg_str0(NULL, "schann", "<d40|ev1|ev2|lrp>", "Secure channel"),
1543 arg_str0(NULL, "aid", "<hex>", "Application ID (3 hex bytes, big endian)"),
1544 arg_str0(NULL, "isoid", "<hex>", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian)."),
1545 arg_str0(NULL, "dict", "<fn>", "Dictionary file name with keys"),
1546 arg_lit0(NULL, "save", "Save found key and parameters to defaults"),
1547 arg_param_end
1549 CLIExecWithReturn(ctx, Cmd, argtable, true);
1551 bool APDULogging = arg_get_lit(ctx, 1);
1552 bool verbose = arg_get_lit(ctx, 2);
1554 DesfireContext_t dctx;
1555 int securechann = defaultSecureChannel;
1556 uint32_t id = 0x000000;
1557 DesfireISOSelectWay selectway = ISW6bAID;
1558 int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, &securechann, DCMMACed, &id, &selectway);
1559 if (res) {
1560 CLIParserFree(ctx);
1561 return res;
1564 uint8_t dict_filename[FILE_PATH_SIZE + 2] = {0};
1565 int dict_filenamelen = 0;
1566 if (CLIParamStrToBuf(arg_get_str(ctx, 13), dict_filename, FILE_PATH_SIZE, &dict_filenamelen)) {
1567 PrintAndLogEx(FAILED, "File name too long or invalid.");
1568 CLIParserFree(ctx);
1569 return PM3_EINVARG;
1572 bool save = arg_get_lit(ctx, 14);
1574 SetAPDULogging(APDULogging);
1575 CLIParserFree(ctx);
1577 // no auth and fill KDF if needs
1578 res = DesfireSelectAndAuthenticateAppW(&dctx, securechann, selectway, id, true, verbose);
1579 if (res != PM3_SUCCESS) {
1580 DropField();
1581 PrintAndLogEx(FAILED, "Select or authentication %s " _RED_("failed") ". Result [%d] %s", DesfireWayIDStr(selectway, id), res, DesfireAuthErrorToStr(res));
1582 return res;
1585 bool keytypes[4] = {0};
1586 bool uselrp = false;
1588 uint8_t data[250] = {0};
1589 size_t datalen = 0;
1590 res = DesfireGetKeySettings(&dctx, data, &datalen);
1591 if (res == PM3_SUCCESS && datalen >= 2) {
1592 uint8_t num_keys = data[1];
1593 switch (num_keys >> 6) {
1594 case 0:
1595 keytypes[T_DES] = true;
1596 keytypes[T_3DES] = true;
1597 break;
1598 case 1:
1599 keytypes[T_3K3DES] = true;
1600 break;
1601 case 2:
1602 keytypes[T_AES] = true;
1603 break;
1604 default:
1605 break;
1607 } else {
1608 // if fail - check auth commands
1609 AuthCommandsChk_t authCmdCheck = {0};
1610 DesfireCheckAuthCommands(selectway, id, NULL, 0, &authCmdCheck);
1611 if (authCmdCheck.checked) {
1612 if (authCmdCheck.auth) {
1613 keytypes[T_DES] = true;
1614 keytypes[T_3DES] = true;
1616 if (authCmdCheck.authISO) {
1617 keytypes[T_3K3DES] = true;
1620 if (authCmdCheck.authAES || authCmdCheck.authEV2) {
1621 keytypes[T_AES] = true;
1623 if (authCmdCheck.authLRP) {
1624 keytypes[T_AES] = true;
1625 uselrp = true;
1626 securechann = DACLRP;
1628 } else {
1629 // if nothing helps - we check DES only
1630 keytypes[T_DES] = true;
1633 res = DesfireSelectAndAuthenticateAppW(&dctx, securechann, selectway, id, true, verbose);
1634 if (res != PM3_SUCCESS) {
1635 DropField();
1636 PrintAndLogEx(FAILED, "Select or authentication %s " _RED_("failed") ". Result [%d] %s", DesfireWayIDStr(selectway, id), res, DesfireAuthErrorToStr(res));
1637 return res;
1641 if (verbose) {
1642 if (DesfireMFSelected(selectway, id))
1643 PrintAndLogEx(INFO, "Check PICC key num: %d (0x%02x)", dctx.keyNum, dctx.keyNum);
1644 else
1645 PrintAndLogEx(INFO, "Check: %s key num: %d (0x%02x)", DesfireWayIDStr(selectway, id), dctx.keyNum, dctx.keyNum);
1646 PrintAndLogEx(INFO, "keys: DES: %s 2TDEA: %s 3TDEA: %s AES: %s LRP: %s",
1647 keytypes[T_DES] ? _GREEN_("YES") : _RED_("NO"),
1648 keytypes[T_3DES] ? _GREEN_("YES") : _RED_("NO"),
1649 keytypes[T_3K3DES] ? _GREEN_("YES") : _RED_("NO"),
1650 keytypes[T_AES] ? _GREEN_("YES") : _RED_("NO"),
1651 uselrp ? _GREEN_("YES") : _RED_("NO")
1655 // for key types
1656 bool found = false;
1657 size_t errcount = 0;
1658 for (uint8_t ktype = T_DES; ktype <= T_AES; ktype++) {
1659 if (!keytypes[ktype])
1660 continue;
1661 dctx.keyType = ktype;
1662 if (verbose)
1663 PrintAndLogEx(INFO, "Scan key type: %s", CLIGetOptionListStr(DesfireAlgoOpts, dctx.keyType));
1665 if (dict_filenamelen == 0) {
1666 // keys from mifaredefault.h
1667 for (int i = 0; i < g_mifare_plus_default_keys_len; i++) {
1668 uint8_t key[DESFIRE_MAX_KEY_SIZE] = {0};
1669 if (hex_to_bytes(g_mifare_plus_default_keys[i], key, 16) != 16)
1670 continue;
1671 if (ktype == T_3K3DES)
1672 memcpy(&key[16], key, 8);
1674 res = DesfireAuthCheck(&dctx, selectway, id, securechann, key);
1675 if (res == PM3_SUCCESS) {
1676 found = true;
1677 break; // all the params already in the dctx
1679 if (res == -10) {
1680 if (verbose)
1681 PrintAndLogEx(ERR, "Can't select AID. There is no connection with card.");
1683 found = false;
1684 break; // we can't select app after invalid 1st auth stages
1686 if (res == -11) {
1687 if (errcount > 10) {
1688 if (verbose)
1689 PrintAndLogEx(ERR, "Too much errors (%zu) from card", errcount);
1690 break;
1692 errcount++;
1693 } else
1694 errcount = 0;
1696 } else {
1697 // keys from file
1698 uint8_t keyList[MAX_KEYS_LIST_LEN * MAX_KEY_LEN] = {0};
1699 uint32_t keyListLen = 0;
1700 size_t keylen = desfire_get_key_length(dctx.keyType);
1701 size_t endFilePosition = 0;
1703 while (!found) {
1704 res = loadFileDICTIONARYEx((char *)dict_filename, keyList, sizeof(keyList), NULL, keylen, &keyListLen, endFilePosition, &endFilePosition, verbose);
1705 if (res != 1 && res != PM3_SUCCESS)
1706 break;
1708 for (int i = 0; i < keyListLen; i++) {
1709 res = DesfireAuthCheck(&dctx, selectway, id, securechann, &keyList[i * keylen]);
1710 if (res == PM3_SUCCESS) {
1711 found = true;
1712 break; // all the params already in the dctx
1714 if (res == -10) {
1715 if (verbose)
1716 PrintAndLogEx(ERR, "Can't select AID. There is no connection with card.");
1718 found = false;
1719 break; // we can't select app after invalid 1st auth stages
1721 if (res == -11) {
1722 if (errcount > 10) {
1723 if (verbose)
1724 PrintAndLogEx(ERR, "Too much errors (%zu) from card", errcount);
1725 break;
1727 errcount++;
1728 } else
1729 errcount = 0;
1732 if (endFilePosition == 0)
1733 break;
1737 if (found)
1738 break;
1741 if (found) {
1742 if (DesfireMFSelected(selectway, id))
1743 PrintAndLogEx(INFO, _GREEN_("Found") " key num: %d (0x%02x)", dctx.keyNum, dctx.keyNum);
1744 else
1745 PrintAndLogEx(INFO, "Found key for: %s key num: %d (0x%02x)", DesfireWayIDStr(selectway, id), dctx.keyNum, dctx.keyNum);
1747 PrintAndLogEx(INFO, "channel " _GREEN_("%s") " key " _GREEN_("%s") " [%d]: " _GREEN_("%s"),
1748 CLIGetOptionListStr(DesfireSecureChannelOpts, securechann),
1749 CLIGetOptionListStr(DesfireAlgoOpts, dctx.keyType),
1750 desfire_get_key_length(dctx.keyType),
1751 sprint_hex(dctx.key, desfire_get_key_length(dctx.keyType)));
1753 } else {
1754 PrintAndLogEx(INFO, "Key " _RED_("not found"));
1757 DropField();
1759 if (found && save) {
1760 defaultKeyNum = dctx.keyNum;
1761 defaultAlgoId = dctx.keyType;
1762 memcpy(defaultKey, dctx.key, DESFIRE_MAX_KEY_SIZE);
1763 defaultKdfAlgo = dctx.kdfAlgo;
1764 defaultKdfInputLen = dctx.kdfInputLen;
1765 memcpy(defaultKdfInput, dctx.kdfInput, sizeof(dctx.kdfInput));
1766 defaultSecureChannel = securechann;
1767 defaultCommSet = dctx.cmdSet;
1769 PrintAndLogEx(INFO, "-----------" _CYAN_("Default parameters") "---------------------------------");
1771 PrintAndLogEx(INFO, "Key Num : %d", defaultKeyNum);
1772 PrintAndLogEx(INFO, "Algo : %s", CLIGetOptionListStr(DesfireAlgoOpts, defaultAlgoId));
1773 PrintAndLogEx(INFO, "Key : %s", sprint_hex(defaultKey, desfire_get_key_length(defaultAlgoId)));
1774 PrintAndLogEx(INFO, "KDF algo : %s", CLIGetOptionListStr(DesfireKDFAlgoOpts, defaultKdfAlgo));
1775 PrintAndLogEx(INFO, "KDF input : [%d] %s", defaultKdfInputLen, sprint_hex(defaultKdfInput, defaultKdfInputLen));
1776 PrintAndLogEx(INFO, "Secure chan : %s", CLIGetOptionListStr(DesfireSecureChannelOpts, defaultSecureChannel));
1777 PrintAndLogEx(INFO, "Command set : %s", CLIGetOptionListStr(DesfireCommandSetOpts, defaultCommSet));
1778 PrintAndLogEx(INFO, _GREEN_("Saved"));
1781 return PM3_SUCCESS;
1784 // https://www.nxp.com/docs/en/application-note/AN10787.pdf
1785 // MIFARE Application Directory (MAD)
1786 // test cardholder data 0a53616d706c656d616e00475068696c697000826d00d054656c2b312f313233342f3536373800
1787 static int CmdHF14aDesMAD(const char *Cmd) {
1788 CLIParserContext *ctx;
1789 CLIParserInit(&ctx, "hf mfdes mad",
1790 "Reads and prints MIFARE Application directory (MAD).",
1791 "MAD consists of one file with issuer info (AID ffffff) and several files with AID in the special format `faaaav` (a - MAD ID, v - multiple AID over one MAD ID)\n"
1792 "The MIFARE DESFire Card Master Key settings have to allow the MIFARE DESFire command GetApplicationIDs without authentication (from datasheet)\n"
1793 "\n"
1794 "hf mfdes mad -> shows MAD data\n"
1795 "hf mfdes mad -v -> shows MAD parsed and raw data\n"
1796 "hf mfdes mad -a e103 -k d3f7d3f7d3f7d3f7d3f7d3f7d3f7d3f7 -> shows MAD data with custom AID and key");
1798 void *argtable[] = {
1799 arg_param_begin,
1800 arg_lit0("a", "apdu", "Show APDU requests and responses"),
1801 arg_lit0("v", "verbose", "Verbose output"),
1802 arg_int0("n", "keyno", "<dec>", "Key number"),
1803 arg_str0("t", "algo", "<DES|2TDEA|3TDEA|AES>", "Crypt algo"),
1804 arg_str0("k", "key", "<hex>", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"),
1805 arg_str0(NULL, "kdf", "<none|AN10922|gallagher>", "Key Derivation Function (KDF)"),
1806 arg_str0("i", "kdfi", "<hex>", "KDF input (1-31 hex bytes)"),
1807 arg_str0("m", "cmode", "<plain|mac|encrypt>", "Communicaton mode"),
1808 arg_str0("c", "ccset", "<native|niso|iso>", "Communicaton command set"),
1809 arg_str0(NULL, "schann", "<d40|ev1|ev2|lrp>", "Secure channel"),
1810 arg_str0(NULL, "aid", "<hex>", "Application ID of issuer info file, (3 hex bytes, big endian), (non-standard feature!)"),
1811 arg_lit0(NULL, "auth", "Authenticate to get info from GetApplicationIDs command (non-standard feature!)"),
1812 arg_param_end
1814 CLIExecWithReturn(ctx, Cmd, argtable, true);
1817 bool APDULogging = arg_get_lit(ctx, 1);
1818 bool verbose = arg_get_lit(ctx, 2);
1820 DesfireContext_t dctx;
1821 int securechann = defaultSecureChannel;
1822 uint32_t appid = 0x000000;
1823 int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, DCMPlain, &appid, NULL);
1824 if (res) {
1825 CLIParserFree(ctx);
1826 return res;
1829 bool authen = arg_get_lit(ctx, 12);
1831 SetAPDULogging(APDULogging);
1832 CLIParserFree(ctx);
1834 res = DesfireSelectAndAuthenticateEx(&dctx, securechann, appid, !authen, verbose);
1835 if (res != PM3_SUCCESS) {
1836 DropField();
1837 return res;
1840 PICCInfo_t PICCInfo = {0};
1841 AppListS AppList = {{0}};
1842 DesfireFillAppList(&dctx, &PICCInfo, AppList, false, false, false); // no deep scan, no scan files
1844 PrintAndLogEx(SUCCESS, "# Applications... " _GREEN_("%zu"), PICCInfo.appCount);
1845 if (PICCInfo.freemem == 0xffffffff) {
1846 PrintAndLogEx(SUCCESS, "Free memory...... " _YELLOW_("n/a"));
1847 } else {
1848 PrintAndLogEx(SUCCESS, "Free memory...... " _GREEN_("%d") " bytes", PICCInfo.freemem);
1851 if ((PICCInfo.keySettings & (1 << 1)) == 0) {
1852 PrintAndLogEx(WARNING, "Directory list access with CMK... ( " _RED_("Enabled") " )");
1853 PrintAndLogEx(HINT, "Try to read MAD with Card Master Key (CMK)");
1856 PrintAndLogEx(SUCCESS, "----------------------------------------- " _CYAN_("MAD") " ------------------------------------------");
1857 bool foundFFFFFF = false;
1858 for (int i = 0; i < PICCInfo.appCount; i++) {
1859 if (AppList[i].appNum == 0xffffff) {
1860 foundFFFFFF = true;
1861 break;
1865 PrintAndLogEx(SUCCESS, _CYAN_("Issuer"));
1867 if (foundFFFFFF) {
1868 res = DesfireSelectAIDHexNoFieldOn(&dctx, 0xffffff);
1869 if (res == PM3_SUCCESS) {
1870 uint32_t madver = 0;
1871 res = DesfireValueFileOperations(&dctx, 0x00, MFDES_GET_VALUE, &madver);
1872 if (res != PM3_SUCCESS) {
1873 PrintAndLogEx(SUCCESS, "MAD version... " _RED_("n/a"));
1874 } else {
1875 if (madver == 3)
1876 PrintAndLogEx(SUCCESS, "MAD version... " _GREEN_("3"));
1877 else
1878 PrintAndLogEx(WARNING, "MAD version... " _YELLOW_("%d"), madver);
1881 uint8_t data[250] = {0};
1882 size_t datalen = 0;
1884 res = DesfireReadFile(&dctx, 01, 0x000000, 0, data, &datalen);
1885 if (res != PM3_SUCCESS) {
1886 PrintAndLogEx(SUCCESS, "Card Holder... " _RED_("n/a"));
1887 } else {
1888 if (datalen > 0) {
1889 PrintAndLogEx(SUCCESS, "Card Holder... ");
1890 if (verbose) {
1891 print_buffer_with_offset(data, datalen, 0, true);
1892 PrintAndLogEx(NORMAL, "");
1894 MADCardHolderInfoDecode(data, datalen, verbose);
1895 PrintAndLogEx(NORMAL, "");
1896 } else {
1897 PrintAndLogEx(SUCCESS, "Card Holder... " _YELLOW_("none"));
1901 res = DesfireReadFile(&dctx, 02, 0x000000, 0, data, &datalen);
1902 if (res != PM3_SUCCESS) {
1903 PrintAndLogEx(SUCCESS, "Card Publisher: " _RED_("n/a"));
1904 } else {
1905 if (datalen > 0) {
1906 PrintAndLogEx(SUCCESS, "Card Publisher: ");
1907 print_buffer_with_offset(data, datalen, 0, true);
1908 PrintAndLogEx(NORMAL, "");
1909 } else {
1910 PrintAndLogEx(SUCCESS, "Card Publisher: " _YELLOW_("none"));
1913 } else {
1914 PrintAndLogEx(WARNING, _RED_("Can't select") " issuer information app (0xffffff).");
1916 } else {
1917 PrintAndLogEx(WARNING, "Issuer information " _RED_("not found") " on the card.");
1920 size_t madappcount = 0;
1921 PrintAndLogEx(SUCCESS, "");
1922 PrintAndLogEx(SUCCESS, _CYAN_("Applications"));
1923 for (int i = 0; i < PICCInfo.appCount; i++) {
1924 if ((AppList[i].appNum & 0xf00000) == 0xf00000) {
1925 DesfirePrintMADAID(AppList[i].appNum, verbose);
1927 // read file 0, 1, 2
1928 res = DesfireSelectAIDHexNoFieldOn(&dctx, AppList[i].appNum);
1929 if (res == PM3_SUCCESS) {
1930 uint8_t buf[APDU_RES_LEN] = {0};
1931 size_t buflen = 0;
1933 res = DesfireGetFileIDList(&dctx, buf, &buflen);
1934 if (res != PM3_SUCCESS) {
1935 PrintAndLogEx(ERR, "Desfire GetFileIDList command " _RED_("error") ". Result: %d", res);
1936 DropField();
1937 return PM3_ESOFT;
1940 if (buflen > 0) {
1941 for (int j = 0; j < buflen; j++) {
1942 PrintAndLogEx(INFO, " File ID... %02x", buf[j]);
1947 madappcount++;
1951 if (madappcount == 0) {
1952 PrintAndLogEx(SUCCESS, "There is no MAD applications on the card");
1953 DropField();
1954 return PM3_SUCCESS;
1957 DropField();
1958 return PM3_SUCCESS;
1961 static int CmdHF14ADesSelectApp(const char *Cmd) {
1962 CLIParserContext *ctx;
1963 CLIParserInit(&ctx, "hf mfdes selectapp",
1964 "Select application on the card. It selects app if it is a valid one or returns an error.",
1965 "hf mfdes selectapp --aid 123456 -> select application 123456\n"
1966 "hf mfdes selectapp --mf -> select master file (PICC level)\n"
1967 "hf mfdes selectapp --dfname aid123456 -> select application aid123456 by DF name\n"
1968 "hf mfdes selectapp --isoid 1111 -> select application 1111 by ISO ID\n"
1969 "hf mfdes selectapp --isoid 1111 --fileisoid 2222 -> select application 1111 file 2222 by ISO ID\n"
1970 "hf mfdes selectapp --isoid 01df --fileisoid 00ef -> select file 00 on the Desfire Light");
1972 void *argtable[] = {
1973 arg_param_begin,
1974 arg_lit0("a", "apdu", "Show APDU requests and responses"),
1975 arg_lit0("v", "verbose", "Verbose output"),
1976 arg_int0("n", "keyno", "<dec>", "Key number"),
1977 arg_str0("t", "algo", "<DES|2TDEA|3TDEA|AES>", "Crypt algo"),
1978 arg_str0("k", "key", "<hex>", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"),
1979 arg_str0(NULL, "kdf", "<none|AN10922|gallagher>", "Key Derivation Function (KDF)"),
1980 arg_str0("i", "kdfi", "<hex>", "KDF input (1-31 hex bytes)"),
1981 arg_str0("m", "cmode", "<plain|mac|encrypt>", "Communicaton mode"),
1982 arg_str0("c", "ccset", "<native|niso|iso>", "Communicaton command set"),
1983 arg_str0(NULL, "schann", "<d40|ev1|ev2|lrp>", "Secure channel"),
1984 arg_str0(NULL, "aid", "<hex>", "Application ID of application for some parameters (3 hex bytes, big endian)"),
1985 arg_str0(NULL, "dfname", "<str>", "Application DF Name (string, max 16 chars). Selects application via ISO SELECT command"),
1986 arg_lit0(NULL, "mf", "Select MF (master file) via ISO channel"),
1987 arg_str0(NULL, "isoid", "<hex>", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian)"),
1988 arg_str0(NULL, "fileisoid", "<hex>", "Select file inside application by ISO ID (ISO DF ID) (2 hex bytes, big endian)."),
1989 arg_param_end
1991 CLIExecWithReturn(ctx, Cmd, argtable, false);
1993 bool APDULogging = arg_get_lit(ctx, 1);
1994 bool verbose = arg_get_lit(ctx, 2);
1996 DesfireContext_t dctx;
1997 int securechann = defaultSecureChannel;
1998 uint32_t appid = 0x000000;
1999 int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, DCMPlain, &appid, NULL);
2000 if (res) {
2001 CLIParserFree(ctx);
2002 return res;
2005 uint8_t dfname[32] = {0};
2006 int dfnamelen = 16;
2007 CLIGetStrWithReturn(ctx, 12, dfname, &dfnamelen);
2009 bool selectmf = arg_get_lit(ctx, 13);
2011 uint32_t isoid = 0x0000;
2012 bool isoidpresent = false;
2013 if (CLIGetUint32Hex(ctx, 14, 0x0000, &isoid, &isoidpresent, 2, "ISO ID for EF or DF must have 2 bytes length")) {
2014 CLIParserFree(ctx);
2015 return PM3_EINVARG;
2018 uint32_t fileisoid = 0x0000;
2019 bool fileisoidpresent = false;
2020 if (CLIGetUint32Hex(ctx, 15, 0x0000, &fileisoid, &fileisoidpresent, 2, "ISO ID for EF or DF must have 2 bytes length")) {
2021 CLIParserFree(ctx);
2022 return PM3_EINVARG;
2025 SetAPDULogging(APDULogging);
2026 CLIParserFree(ctx);
2028 uint8_t resp[250] = {0};
2029 size_t resplen = 0;
2031 if (selectmf) {
2032 res = DesfireISOSelect(&dctx, ISSMFDFEF, NULL, 0, resp, &resplen);
2033 if (res != PM3_SUCCESS) {
2034 DropField();
2035 PrintAndLogEx(FAILED, "ISO Select MF " _RED_("failed"));
2036 return res;
2039 if (resplen > 0)
2040 PrintAndLogEx(FAILED, "Application " _CYAN_("FCI template") " [%zu]%s", resplen, sprint_hex(resp, resplen));
2042 PrintAndLogEx(SUCCESS, "PICC MF selected " _GREEN_("succesfully"));
2043 } else if (isoidpresent) {
2044 uint8_t data[2] = {0};
2045 Uint2byteToMemLe(data, isoid);
2046 res = DesfireISOSelect(&dctx, ISSMFDFEF, data, 2, resp, &resplen);
2047 if (res != PM3_SUCCESS) {
2048 DropField();
2049 PrintAndLogEx(FAILED, "ISO Select DF 0x%04x " _RED_("failed"), isoid);
2050 return res;
2053 if (resplen > 0)
2054 PrintAndLogEx(FAILED, "Application " _CYAN_("FCI template") " [%zu]%s", resplen, sprint_hex(resp, resplen));
2056 PrintAndLogEx(SUCCESS, "PICC DF 0x%04x selected " _GREEN_("succesfully"), isoid);
2057 } else if (dctx.cmdSet == DCCISO || dfnamelen > 0) {
2058 if (dfnamelen > 0)
2059 res = DesfireISOSelectDF(&dctx, (char *)dfname, resp, &resplen);
2060 else
2061 res = DesfireISOSelect(&dctx, ISSMFDFEF, NULL, 0, resp, &resplen);
2062 if (res != PM3_SUCCESS) {
2063 DropField();
2064 PrintAndLogEx(FAILED, "ISO Select application `%s` " _RED_("failed"), (char *)dfname);
2065 return res;
2068 if (resplen > 0)
2069 PrintAndLogEx(FAILED, "Application " _CYAN_("FCI template") " [%zu]%s", resplen, sprint_hex(resp, resplen));
2071 if (dfnamelen > 0)
2072 PrintAndLogEx(SUCCESS, "Application `%s` selected " _GREEN_("succesfully"), (char *)dfname);
2073 else
2074 PrintAndLogEx(SUCCESS, "PICC MF selected " _GREEN_("succesfully"));
2075 } else {
2076 res = DesfireSelectAndAuthenticateEx(&dctx, securechann, appid, true, verbose);
2077 if (res != PM3_SUCCESS) {
2078 DropField();
2079 PrintAndLogEx(FAILED, "Select application 0x%06x " _RED_("failed") " ", appid);
2080 return res;
2083 PrintAndLogEx(SUCCESS, "Application 0x%06x selected " _GREEN_("succesfully") " ", appid);
2086 if (fileisoidpresent) {
2087 res = DesfireSelectEx(&dctx, false, ISWIsoID, fileisoid, NULL);
2088 if (res != PM3_SUCCESS) {
2089 DropField();
2090 PrintAndLogEx(FAILED, "Select file 0x%04x " _RED_("failed") " ", fileisoid);
2091 return res;
2094 PrintAndLogEx(SUCCESS, "File 0x%04x selected " _GREEN_("succesfully") " ", fileisoid);
2097 DropField();
2098 return res;
2101 static int CmdHF14ADesBruteApps(const char *Cmd) {
2102 CLIParserContext *ctx;
2103 CLIParserInit(&ctx, "hf mfdes bruteaid",
2104 "Recover AIDs by bruteforce.\n"
2105 "WARNING: This command takes a loooong time",
2106 "hf mfdes bruteaid -> Search all apps\n"
2107 "hf mfdes bruteaid --start F0000F -i 16 -> Search MAD range manually");
2109 void *argtable[] = {
2110 arg_param_begin,
2111 arg_str0(NULL, "start", "<hex>", "Starting App ID as hex bytes (3 bytes, big endian)"),
2112 arg_str0(NULL, "end", "<hex>", "Last App ID as hex bytes (3 bytes, big endian)"),
2113 arg_int0("i", "step", "<dec>", "Increment step when bruteforcing"),
2114 arg_lit0("m", "mad", "Only bruteforce the MAD range"),
2115 arg_param_end
2117 CLIExecWithReturn(ctx, Cmd, argtable, true);
2119 DesfireContext_t dctx;
2120 int securechann = defaultSecureChannel;
2121 int res = CmdDesGetSessionParameters(ctx, &dctx, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, &securechann, DCMNone, NULL, NULL);
2122 if (res) {
2123 CLIParserFree(ctx);
2124 return res;
2127 uint8_t startAid[3] = {0};
2128 uint8_t endAid[3] = {0xFF, 0xFF, 0xFF};
2129 int startLen = 0;
2130 int endLen = 0;
2131 CLIGetHexWithReturn(ctx, 1, startAid, &startLen);
2132 CLIGetHexWithReturn(ctx, 2, endAid, &endLen);
2133 uint32_t idIncrement = arg_get_int_def(ctx, 3, 1);
2134 bool mad = arg_get_lit(ctx, 4);
2136 CLIParserFree(ctx);
2138 // tru select PICC
2139 res = DesfireSelectAIDHex(&dctx, 0x000000, false, 0);
2140 if (res != PM3_SUCCESS) {
2141 DropField();
2142 PrintAndLogEx(FAILED, "Desfire PICC level select " _RED_("failed") ". Maybe wrong card or no card in the field.");
2143 return res;
2146 // TODO: We need to check the tag version, EV1 should stop after 26 apps are found
2147 if (mad) {
2148 idIncrement = 0x10;
2149 startAid[0] = 0xF0;
2150 startAid[1] = 0x00;
2151 startAid[2] = 0x0F;
2153 uint32_t idStart = DesfireAIDByteToUint(startAid);
2154 uint32_t idEnd = DesfireAIDByteToUint(endAid);
2155 if (idStart > idEnd) {
2156 PrintAndLogEx(ERR, "Start should be lower than end. start: %06x end: %06x", idStart, idEnd);
2157 return PM3_EINVARG;
2159 PrintAndLogEx(INFO, "Bruteforce from %06x to %06x", idStart, idEnd);
2160 PrintAndLogEx(INFO, "Enumerating through all AIDs manually, this will take a while!");
2161 for (uint32_t id = idStart; id <= idEnd && id >= idStart; id += idIncrement) {
2162 if (kbd_enter_pressed()) break;
2164 int progress = ((id - idStart) * 100) / ((idEnd - idStart));
2165 PrintAndLogEx(INPLACE, "Progress: %d %%, current AID: %06X", progress, id);
2167 res = DesfireSelectAIDHexNoFieldOn(&dctx, id);
2169 if (res == PM3_SUCCESS) {
2170 printf("\33[2K\r"); // clear current line before printing
2171 PrintAndLogEx(SUCCESS, "Got new APPID %06X", id);
2175 PrintAndLogEx(NORMAL, "");
2176 PrintAndLogEx(SUCCESS, _GREEN_("Done"));
2177 DropField();
2178 return PM3_SUCCESS;
2181 // MIAFRE DESFire Authentication
2182 // keys:
2183 // NR DESC KEYLENGHT
2184 // ------------------------
2185 // 1 = DES 8
2186 // 2 = 3DES 16
2187 // 3 = 3K 3DES 24
2188 // 4 = AES 16
2189 static int CmdHF14ADesAuth(const char *Cmd) {
2190 CLIParserContext *ctx;
2191 CLIParserInit(&ctx, "hf mfdes auth",
2192 "Select application on the card. It selects app if it is a valid one or returns an error.",
2193 "hf mfdes auth -n 0 -t des -k 0000000000000000 --kdf none -> select PICC level and authenticate with key num=0, key type=des, key=00..00 and key derivation = none\n"
2194 "hf mfdes auth -n 0 -t aes -k 00000000000000000000000000000000 -> select PICC level and authenticate with key num=0, key type=aes, key=00..00 and key derivation = none\n"
2195 "hf mfdes auth -n 0 -t des -k 0000000000000000 --save -> select PICC level and authenticate and in case of successful authentication - save channel parameters to defaults\n"
2196 "hf mfdes auth --aid 123456 -> select application 123456 and authenticate via parameters from `default` command");
2198 void *argtable[] = {
2199 arg_param_begin,
2200 arg_lit0("a", "apdu", "Show APDU requests and responses"),
2201 arg_lit0("v", "verbose", "Verbose output"),
2202 arg_int0("n", "keyno", "<dec>", "Key number"),
2203 arg_str0("t", "algo", "<DES|2TDEA|3TDEA|AES>", "Crypt algo"),
2204 arg_str0("k", "key", "<hex>", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"),
2205 arg_str0(NULL, "kdf", "<none|AN10922|gallagher>", "Key Derivation Function (KDF)"),
2206 arg_str0("i", "kdfi", "<hex>", "KDF input (1-31 hex bytes)"),
2207 arg_str0("m", "cmode", "<plain|mac|encrypt>", "Communicaton mode"),
2208 arg_str0("c", "ccset", "<native|niso|iso>", "Communicaton command set"),
2209 arg_str0(NULL, "schann", "<d40|ev1|ev2|lrp>", "Secure channel"),
2210 arg_str0(NULL, "aid", "<hex>", "Application ID of application for some parameters (3 hex bytes, big endian)"),
2211 arg_str0(NULL, "isoid", "<hex>", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian)"),
2212 arg_lit0(NULL, "save", "saves channels parameters to defaults if authentication succeeds"),
2213 arg_param_end
2215 CLIExecWithReturn(ctx, Cmd, argtable, false);
2217 bool APDULogging = arg_get_lit(ctx, 1);
2218 bool verbose = arg_get_lit(ctx, 2);
2220 DesfireContext_t dctx;
2221 int securechann = defaultSecureChannel;
2222 uint32_t id = 0x000000;
2223 DesfireISOSelectWay selectway = ISW6bAID;
2224 int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, &securechann, DCMPlain, &id, &selectway);
2225 if (res) {
2226 CLIParserFree(ctx);
2227 return res;
2230 bool save = arg_get_lit(ctx, 13);
2232 SetAPDULogging(APDULogging);
2233 CLIParserFree(ctx);
2235 res = DesfireSelectAndAuthenticateAppW(&dctx, securechann, selectway, id, false, verbose);
2236 if (res != PM3_SUCCESS) {
2237 DropField();
2238 PrintAndLogEx(FAILED, "Select or authentication %s " _RED_("failed") ". Result [%d] %s", DesfireWayIDStr(selectway, id), res, DesfireAuthErrorToStr(res));
2239 return res;
2242 if (DesfireMFSelected(selectway, id))
2243 PrintAndLogEx(SUCCESS, "PICC selected and authenticated " _GREEN_("succesfully"));
2244 else
2245 PrintAndLogEx(SUCCESS, "Application " _CYAN_("%s") " selected and authenticated " _GREEN_("succesfully"), DesfireWayIDStr(selectway, id));
2247 PrintAndLogEx(SUCCESS, _CYAN_("Context: "));
2248 DesfirePrintContext(&dctx);
2250 if (save) {
2251 defaultKeyNum = dctx.keyNum;
2252 defaultAlgoId = dctx.keyType;
2253 memcpy(defaultKey, dctx.key, DESFIRE_MAX_KEY_SIZE);
2254 defaultKdfAlgo = dctx.kdfAlgo;
2255 defaultKdfInputLen = dctx.kdfInputLen;
2256 memcpy(defaultKdfInput, dctx.kdfInput, sizeof(dctx.kdfInput));
2257 defaultSecureChannel = securechann;
2258 defaultCommSet = dctx.cmdSet;
2259 defaultCommMode = dctx.commMode;
2261 PrintAndLogEx(SUCCESS, "Context saved to defaults " _GREEN_("succesfully") ". You can check them by command " _YELLOW_("hf mfdes default"));
2264 DropField();
2265 return res;
2268 static int CmdHF14ADesSetConfiguration(const char *Cmd) {
2269 CLIParserContext *ctx;
2270 CLIParserInit(&ctx, "hf mfdes setconfig",
2271 "Set card configuration. \n"
2272 "WARNING! Danger zone!\n"
2273 "Needs to provide card's master key and works if not blocked by config.",
2274 "More about options MF2DLHX0.pdf.\n"
2275 "Options list:\n"
2276 " 00h PICC configuration.\n"
2277 " 02h ATS update.\n"
2278 " 03h SAK update\n"
2279 " 04h Secure Messaging Configuration.\n"
2280 " 05h Capability data. (here change for LRP in the Desfire Light [enable 00000000010000000000])\n"
2281 " 06h DF Name renaming (one-time)\n"
2282 " 08h File renaming (one-time)\n"
2283 " 09h Value file configuration (one-time)\n"
2284 " 0Ah Failed authentication counter setting [disable 00ffffffff]\n"
2285 " 0Bh HW configuration\n"
2286 "\n"
2287 "hf mfdes setconfig --param 03 --data 0428 -> set SAK\n"
2288 "hf mfdes setconfig --param 02 --data 0875778102637264 -> set ATS (first byte - length)\n"
2289 "hf mfdes setconfig --isoid df01 -t aes --schann ev2 --param 05 --data 00000000020000000000 -> set LRP mode enable for Desfire Light\n"
2290 "hf mfdes setconfig --isoid df01 -t aes --schann ev2 --param 0a --data 00ffffffff -> Disable failed auth counters for Desfire Light\n"
2291 "hf mfdes setconfig --isoid df01 -t aes --schann lrp --param 0a --data 00ffffffff -> Disable failed auth counters for Desfire Light via lrp");
2293 void *argtable[] = {
2294 arg_param_begin,
2295 arg_lit0("a", "apdu", "Show APDU requests and responses"),
2296 arg_lit0("v", "verbose", "Verbose output"),
2297 arg_int0("n", "keyno", "<dec>", "Key number"),
2298 arg_str0("t", "algo", "<DES|2TDEA|3TDEA|AES>", "Crypt algo"),
2299 arg_str0("k", "key", "<hex>", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"),
2300 arg_str0(NULL, "kdf", "<none|AN10922|gallagher>", "Key Derivation Function (KDF)"),
2301 arg_str0("i", "kdfi", "<hex>", "KDF input (1-31 hex bytes)"),
2302 arg_str0("m", "cmode", "<plain|mac|encrypt>", "Communicaton mode"),
2303 arg_str0("c", "ccset", "<native|niso|iso>", "Communicaton command set"),
2304 arg_str0(NULL, "schann", "<d40|ev1|ev2|lrp>", "Secure channel"),
2305 arg_str0(NULL, "aid", "<hex>", "Application ID of application for some parameters (3 hex bytes, big endian)"),
2306 arg_str0(NULL, "isoid", "<hex>", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian)."),
2307 arg_str0("p", "param", "<hex>", "Parameter id (1 hex byte)"),
2308 arg_str0("d", "data", "<hex>", "Data for parameter (1..30 hex bytes)"),
2309 arg_param_end
2311 CLIExecWithReturn(ctx, Cmd, argtable, false);
2313 bool APDULogging = arg_get_lit(ctx, 1);
2314 bool verbose = arg_get_lit(ctx, 2);
2316 DesfireContext_t dctx;
2317 int securechann = defaultSecureChannel;
2318 uint32_t id = 0x000000;
2319 DesfireISOSelectWay selectway = ISW6bAID;
2320 int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, &securechann, DCMEncrypted, &id, &selectway);
2321 if (res) {
2322 CLIParserFree(ctx);
2323 return res;
2326 uint32_t paramid = 0;
2327 if (CLIGetUint32Hex(ctx, 13, 0, &paramid, NULL, 1, "Parameter ID must have 1 bytes length")) {
2328 CLIParserFree(ctx);
2329 return PM3_EINVARG;
2332 uint8_t param[250] = {0};
2333 int paramlen = sizeof(param);
2334 CLIGetHexWithReturn(ctx, 14, param, &paramlen);
2335 if (paramlen == 0) {
2336 PrintAndLogEx(ERR, "Parameter must have a data.");
2337 CLIParserFree(ctx);
2338 return PM3_EINVARG;
2340 if (paramlen > 50) {
2341 PrintAndLogEx(ERR, "Parameter data length must be less than 50 instead of %d.", paramlen);
2342 CLIParserFree(ctx);
2343 return PM3_EINVARG;
2346 SetAPDULogging(APDULogging);
2347 CLIParserFree(ctx);
2349 if (verbose) {
2350 if (DesfireMFSelected(selectway, id)) {
2351 PrintAndLogEx(INFO, _CYAN_("PICC") " param ID: 0x%02x param[%d]: %s",
2352 paramid,
2353 paramlen,
2354 sprint_hex(param, paramlen)
2356 } else {
2357 PrintAndLogEx(INFO, _CYAN_("%s %06x") " param ID: 0x%02x param[%d]: %s",
2358 DesfireSelectWayToStr(selectway),
2360 paramid,
2361 paramlen,
2362 sprint_hex(param, paramlen)
2367 res = DesfireSelectAndAuthenticateAppW(&dctx, securechann, selectway, id, false, verbose);
2368 if (res != PM3_SUCCESS) {
2369 DropField();
2370 PrintAndLogEx(FAILED, "Select or authentication ( %s ) Result [%d] %s %s",
2371 DesfireWayIDStr(selectway, id),
2372 res,
2373 DesfireAuthErrorToStr(res),
2374 _RED_("failed")
2376 return res;
2379 res = DesfireSetConfiguration(&dctx, paramid, param, paramlen);
2380 if (res == PM3_SUCCESS) {
2381 PrintAndLogEx(SUCCESS, "Set configuration 0x%02x ( %s )", paramid, _GREEN_("ok"));
2382 } else {
2383 PrintAndLogEx(FAILED, "Set configuration 0x%02x ( %s )", paramid, _RED_("failed"));
2386 DropField();
2387 return res;
2390 static int CmdHF14ADesChangeKey(const char *Cmd) {
2391 CLIParserContext *ctx;
2392 CLIParserInit(&ctx, "hf mfdes changekey",
2393 "Change PICC/Application key. Needs to provide keynum/key for a valid authentication (may get from default parameters).",
2394 "Change crypto algorithm for PICC key is possible, \n"
2395 "but for APP keys crypto algorithm is set by createapp command and can't be changed wo application delete\n"
2396 "\n"
2397 "hf mfdes changekey --aid 123456 -> execute with default factory setup. change des key 0 in the app 123456 from 00..00 to 00..00\n"
2398 "hf mfdes changekey --isoid df01 -t aes --schann lrp --newkeyno 01 -> change key 01 via lrp channel"
2399 "hf mfdes changekey -t des --newalgo aes --newkey 11223344556677889900112233445566 --newver a5 -> change card master key to AES one\n"
2400 "hf mfdes changekey --aid 123456 -t aes --key 00000000000000000000000000000000 --newkey 11223344556677889900112233445566 -> change app master key\n"
2401 "hf mfdes changekey --aid 123456 -t des -n 0 --newkeyno 1 --oldkey 5555555555555555 --newkey 1122334455667788 -> change key 1 with auth from key 0\n"
2402 "hf mfdes changekey --aid 123456 -t 3tdea --newkey 112233445566778899001122334455667788990011223344 -> change 3tdea key 0 from default 00..00 to provided");
2404 void *argtable[] = {
2405 arg_param_begin,
2406 arg_lit0("a", "apdu", "Show APDU requests and responses"),
2407 arg_lit0("v", "verbose", "Verbose output"),
2408 arg_int0("n", "keyno", "<dec>", "Key number"),
2409 arg_str0("t", "algo", "<DES|2TDEA|3TDEA|AES>", "Crypt algo"),
2410 arg_str0("k", "key", "<hex>", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"),
2411 arg_str0(NULL, "kdf", "<none|AN10922|gallagher>", "Key Derivation Function (KDF)"),
2412 arg_str0("i", "kdfi", "<hex>", "KDF input (1-31 hex bytes)"),
2413 arg_str0("m", "cmode", "<plain|mac|encrypt>", "Communicaton mode"),
2414 arg_str0("c", "ccset", "<native|niso|iso>", "Communicaton command set"),
2415 arg_str0(NULL, "schann", "<d40|ev1|ev2|lrp>", "Secure channel"),
2416 arg_str0(NULL, "aid", "<hex>", "Application ID of application (3 hex bytes, big endian)"),
2417 arg_str0(NULL, "isoid", "<hex>", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian)."),
2418 arg_str0(NULL, "oldalgo", "<DES|2TDEA|3TDEA|AES>", "Old key crypto algorithm"),
2419 arg_str0(NULL, "oldkey", "<old key>", "Old key (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"),
2420 arg_int0(NULL, "newkeyno", "<dec>", "Key number for change"),
2421 arg_str0(NULL, "newalgo", "<DES|2TDEA|3TDEA|AES>", "New key crypto algorithm"),
2422 arg_str0(NULL, "newkey", "<hex>", "New key (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"),
2423 arg_str0(NULL, "newver", "<hex>", "Version of new key (1 hex byte)"),
2424 arg_param_end
2426 CLIExecWithReturn(ctx, Cmd, argtable, false);
2428 bool APDULogging = arg_get_lit(ctx, 1);
2429 bool verbose = arg_get_lit(ctx, 2);
2431 DesfireContext_t dctx;
2432 int securechann = defaultSecureChannel;
2433 uint32_t id = 0x000000;
2434 DesfireISOSelectWay selectway = ISW6bAID;
2435 int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, &securechann, DCMEncrypted, &id, &selectway);
2436 if (res) {
2437 CLIParserFree(ctx);
2438 return res;
2441 int oldkeytype = dctx.keyType;
2442 if (CLIGetOptionList(arg_get_str(ctx, 13), DesfireAlgoOpts, &oldkeytype)) {
2443 CLIParserFree(ctx);
2444 return PM3_ESOFT;
2447 uint8_t oldkey[DESFIRE_MAX_KEY_SIZE] = {0};
2448 uint8_t keydata[200] = {0};
2449 int oldkeylen = sizeof(keydata);
2450 CLIGetHexWithReturn(ctx, 14, keydata, &oldkeylen);
2451 if (oldkeylen && oldkeylen != desfire_get_key_length(oldkeytype)) {
2452 PrintAndLogEx(ERR, "%s old key must have %d bytes length instead of %d.", CLIGetOptionListStr(DesfireAlgoOpts, oldkeytype), desfire_get_key_length(oldkeytype), oldkeylen);
2453 CLIParserFree(ctx);
2454 return PM3_EINVARG;
2456 if (oldkeylen)
2457 memcpy(oldkey, keydata, oldkeylen);
2459 uint8_t newkeynum = arg_get_int_def(ctx, 15, 0);
2461 int newkeytype = oldkeytype;
2462 if (CLIGetOptionList(arg_get_str(ctx, 16), DesfireAlgoOpts, &newkeytype)) {
2463 CLIParserFree(ctx);
2464 return PM3_ESOFT;
2467 uint8_t newkey[DESFIRE_MAX_KEY_SIZE] = {0};
2468 memset(keydata, 0x00, sizeof(keydata));
2469 int keylen = sizeof(keydata);
2470 CLIGetHexWithReturn(ctx, 17, keydata, &keylen);
2471 if (keylen && keylen != desfire_get_key_length(newkeytype)) {
2472 PrintAndLogEx(ERR, "%s new key must have %d bytes length instead of %d.", CLIGetOptionListStr(DesfireAlgoOpts, newkeytype), desfire_get_key_length(newkeytype), keylen);
2473 CLIParserFree(ctx);
2474 return PM3_EINVARG;
2476 if (keylen)
2477 memcpy(newkey, keydata, keylen);
2479 uint32_t newkeyver = 0x100;
2480 if (CLIGetUint32Hex(ctx, 18, 0x100, &newkeyver, NULL, 1, "Key version must have 1 bytes length")) {
2481 CLIParserFree(ctx);
2482 return PM3_EINVARG;
2485 SetAPDULogging(APDULogging);
2486 CLIParserFree(ctx);
2488 // if we change the same key
2489 if (oldkeylen == 0 && newkeynum == dctx.keyNum) {
2490 oldkeytype = dctx.keyType;
2491 memcpy(oldkey, dctx.key, desfire_get_key_length(dctx.keyType));
2494 if (DesfireMFSelected(selectway, id)) {
2495 if (verbose)
2496 PrintAndLogEx(WARNING, "Changing the PICC level keys");
2497 PrintAndLogEx(INFO, _CYAN_("Changing PICC key"));
2498 } else {
2499 PrintAndLogEx(INFO, _CYAN_("Changing key for ") _YELLOW_("%s"), DesfireWayIDStr(selectway, id));
2502 PrintAndLogEx(INFO, "auth key %d: %s [%d] %s", dctx.keyNum, CLIGetOptionListStr(DesfireAlgoOpts, dctx.keyType), desfire_get_key_length(dctx.keyType), sprint_hex(dctx.key, desfire_get_key_length(dctx.keyType)));
2503 PrintAndLogEx(INFO, "changing key number " _YELLOW_("0x%02x") " (%d)", newkeynum, newkeynum);
2504 PrintAndLogEx(INFO, "old key: %s [%d] %s", CLIGetOptionListStr(DesfireAlgoOpts, oldkeytype), desfire_get_key_length(oldkeytype), sprint_hex(oldkey, desfire_get_key_length(oldkeytype)));
2505 PrintAndLogEx(INFO, "new key: %s [%d] %s", CLIGetOptionListStr(DesfireAlgoOpts, newkeytype), desfire_get_key_length(newkeytype), sprint_hex(newkey, desfire_get_key_length(newkeytype)));
2506 if (newkeyver < 0x100 || newkeytype == T_AES)
2507 PrintAndLogEx(INFO, "new key version: 0x%02x", newkeyver & 0x00);
2509 res = DesfireSelectAndAuthenticateAppW(&dctx, securechann, selectway, id, false, verbose);
2510 if (res != PM3_SUCCESS) {
2511 DropField();
2512 PrintAndLogEx(FAILED, "Select or authentication %s " _RED_("failed") ". Result [%d] %s", DesfireWayIDStr(selectway, id), res, DesfireAuthErrorToStr(res));
2513 return res;
2516 DesfireSetCommMode(&dctx, DCMEncryptedPlain);
2517 res = DesfireChangeKey(&dctx, (DesfireMFSelected(selectway, id)) && (newkeynum == 0) && (dctx.keyNum == 0), newkeynum, newkeytype, newkeyver, newkey, oldkeytype, oldkey, true);
2518 if (res == PM3_SUCCESS) {
2519 PrintAndLogEx(SUCCESS, "Change key ( " _GREEN_("ok") " )");
2520 } else {
2521 PrintAndLogEx(FAILED, "Change key ( " _RED_("failed") " )");
2523 DesfireSetCommMode(&dctx, DCMEncrypted);
2525 DropField();
2526 return res;
2529 static int CmdHF14ADesCreateApp(const char *Cmd) {
2530 CLIParserContext *ctx;
2531 CLIParserInit(&ctx, "hf mfdes createapp",
2532 "Create application. Master key needs to be provided.",
2533 "option rawdata have priority over the rest settings, and options ks1 and ks2 have priority over corresponded key settings\n"
2534 "\n"\
2535 "KeySetting 1 (AMK Setting, ks1):\n"\
2536 " 0: Allow change master key. 1 - allow, 0 - frozen\n"\
2537 " 1: Free Directory list access without master key\n"\
2538 " 0: AMK auth needed for GetFileSettings and GetKeySettings\n"\
2539 " 1: No AMK auth needed for GetFileIDs, GetISOFileIDs, GetFileSettings, GetKeySettings\n"\
2540 " 2: Free create/delete without master key\n"\
2541 " 0: CreateFile/DeleteFile only with AMK auth\n"\
2542 " 1: CreateFile/DeleteFile always\n"\
2543 " 3: Configuration changeable\n"\
2544 " 0: Configuration frozen\n"\
2545 " 1: Configuration changeable if authenticated with AMK (default)\n"\
2546 " 4-7: ChangeKey Access Rights\n"\
2547 " 0: Application master key needed (default)\n"\
2548 " 0x1..0xD: Auth with specific key needed to change any key\n"\
2549 " 0xE: Auth with the key to be changed (same KeyNo) is necessary to change a key\n"\
2550 " 0xF: All Keys within this application are frozen\n"\
2551 "\n"\
2552 "KeySetting 2 (ks2):\n"\
2553 " 0..3: Number of keys stored within the application (max. 14 keys)\n"\
2554 " 4: ks3 is present\n"\
2555 " 5: Use of 2 byte ISO FID, 0: No, 1: Yes\n"\
2556 " 6..7: Crypto Method 00: DES|2TDEA, 01: 3TDEA, 10: AES, 11: RFU\n"\
2557 " Example:\n"\
2558 " 2E = with FID, DES|2TDEA, 14 keys\n"\
2559 " 6E = with FID, 3TDEA, 14 keys\n"\
2560 " AE = with FID, AES, 14 keys\n"\
2561 "\n"\
2562 "hf mfdes createapp --rawdata 5634122F2E4523616964313233343536 -> execute create by rawdata\n"\
2563 "hf mfdes createapp --aid 123456 --fid 2345 --dfname aid123456 -> app aid, iso file id, and iso df name is specified\n"
2564 "hf mfdes createapp --aid 123456 --fid 2345 --dfname aid123456 --dstalgo aes -> with algorithm for key AES");
2566 void *argtable[] = {
2567 arg_param_begin,
2568 arg_lit0("a", "apdu", "Show APDU requests and responses"),
2569 arg_lit0("v", "verbose", "Verbose output"),
2570 arg_int0("n", "keyno", "<dec>", "Key number"),
2571 arg_str0("t", "algo", "<DES|2TDEA|3TDEA|AES>", "Crypt algo"),
2572 arg_str0("k", "key", "<hex>", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"),
2573 arg_str0(NULL, "kdf", "<none|AN10922|gallagher>", "Key Derivation Function (KDF)"),
2574 arg_str0("i", "kdfi", "<hex>", "KDF input (1-31 hex bytes)"),
2575 arg_str0("m", "cmode", "<plain|mac|encrypt>", "Communicaton mode"),
2576 arg_str0("c", "ccset", "<native|niso|iso>", "Communicaton command set"),
2577 arg_str0(NULL, "schann", "<d40|ev1|ev2|lrp>", "Secure channel"),
2578 arg_str0(NULL, "rawdata", "<hex>", "Raw data that sends to command"),
2579 arg_str0(NULL, "aid", "<hex>", "Application ID for create. Mandatory. (3 hex bytes, big endian)"),
2580 arg_str0(NULL, "fid", "<hex>", "ISO file ID. Forbidden values: 0000 3F00, 3FFF, FFFF. (2 hex bytes, big endian)"),
2581 arg_str0(NULL, "dfname", "<string>", "ISO DF Name (1..16 chars)"),
2582 arg_str0(NULL, "dfhex", "<hex>", "ISO DF Name as hex (1..16 bytes)"),
2583 arg_str0(NULL, "ks1", "<hex>", "Key settings 1 (1 hex byte). Application Master Key Settings (def: 0x0F)"),
2584 arg_str0(NULL, "ks2", "<hex>", "Key settings 2 (1 hex byte). (def: 0x0E)"),
2585 arg_str0(NULL, "dstalgo", "<DES|2TDEA|3TDEA|AES>", "Application key crypt algo (def: DES)"),
2586 arg_int0(NULL, "numkeys", "<dec>", "Number of keys 0x00..0x0e (def: 0x0E)"),
2587 arg_lit0(NULL, "no-auth", "Execute without authentication"),
2588 arg_param_end
2590 CLIExecWithReturn(ctx, Cmd, argtable, false);
2592 bool APDULogging = arg_get_lit(ctx, 1);
2593 bool verbose = arg_get_lit(ctx, 2);
2595 DesfireContext_t dctx;
2596 int securechann = defaultSecureChannel;
2597 uint32_t appid = 0x000000;
2598 int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 12, 0, &securechann, DCMMACed, &appid, NULL);
2599 if (res) {
2600 CLIParserFree(ctx);
2601 return res;
2604 uint8_t rawdata[250] = {0};
2605 int rawdatalen = sizeof(rawdata);
2606 CLIGetHexWithReturn(ctx, 11, rawdata, &rawdatalen);
2608 uint32_t fileid = 0x0000;
2609 bool fileidpresent = false;
2610 if (CLIGetUint32Hex(ctx, 13, 0x0000, &fileid, &fileidpresent, 2, "ISO file ID must have 2 bytes length")) {
2611 CLIParserFree(ctx);
2612 return PM3_EINVARG;
2615 uint8_t dfname[250] = {0};
2616 int dfnamelen = 16;
2617 CLIGetStrWithReturn(ctx, 14, dfname, &dfnamelen);
2619 if (dfnamelen == 0) { // no text DF Name supplied
2620 dfnamelen = 16;
2621 CLIGetHexWithReturn(ctx, 15, dfname, &dfnamelen);
2624 uint32_t ks1 = 0x0f;
2625 if (CLIGetUint32Hex(ctx, 16, 0x0f, &ks1, NULL, 1, "Key settings 1 must have 1 byte length")) {
2626 CLIParserFree(ctx);
2627 return PM3_EINVARG;
2630 uint32_t ks2 = 0x0e;
2631 bool ks2present = false;
2632 if (CLIGetUint32Hex(ctx, 17, 0x0e, &ks2, &ks2present, 1, "Key settings 2 must have 1 byte length")) {
2633 CLIParserFree(ctx);
2634 return PM3_EINVARG;
2637 int dstalgo = T_DES;
2638 if (CLIGetOptionList(arg_get_str(ctx, 18), DesfireAlgoOpts, &dstalgo)) {
2639 CLIParserFree(ctx);
2640 return PM3_ESOFT;
2643 int keycount = arg_get_int_def(ctx, 19, 0x0e);
2644 bool noauth = arg_get_lit(ctx, 20);
2646 SetAPDULogging(APDULogging);
2647 CLIParserFree(ctx);
2649 if (rawdatalen == 0 && appid == 0x000000) {
2650 PrintAndLogEx(ERR, "Creating the root aid (0x000000) is " _RED_("forbidden"));
2651 return PM3_ESOFT;
2654 if (rawdatalen == 0 && (fileidpresent || (ks2 & 0x20) != 0) && fileid == 0x0000) {
2655 PrintAndLogEx(ERR, "Creating the application with ISO file ID 0x0000 is " _RED_("forbidden"));
2656 return PM3_ESOFT;
2659 if (keycount > 0x0e || keycount < 1) {
2660 PrintAndLogEx(ERR, "Key count must be in the range 1..14");
2661 return PM3_ESOFT;
2664 if (dfnamelen > 16) {
2665 PrintAndLogEx(ERR, "DF name must be a maximum of 16 bytes in length");
2666 return PM3_EINVARG;
2669 res = DesfireSelectAndAuthenticateEx(&dctx, securechann, 0x000000, noauth, verbose);
2670 if (res != PM3_SUCCESS) {
2671 DropField();
2672 return res;
2675 uint8_t data[250] = {0};
2676 size_t datalen = 0;
2677 if (rawdatalen > 0) {
2678 memcpy(data, rawdata, rawdatalen);
2679 datalen = rawdatalen;
2680 } else {
2681 DesfireAIDUintToByte(appid, &data[0]);
2682 data[3] = ks1 & 0xff;
2683 data[4] = ks2 & 0xff;
2685 if (!ks2present) {
2686 if (keycount > 0) {
2687 data[4] &= 0xf0;
2688 data[4] |= keycount & 0x0f;
2690 uint8_t kt = DesfireKeyAlgoToType(dstalgo);
2691 data[4] &= 0x3f;
2692 data[4] |= (kt & 0x03) << 6;
2695 datalen = 5;
2696 if (fileidpresent || (data[4] & 0x20) != 0) {
2697 Uint2byteToMemLe(&data[5], fileid);
2698 data[4] |= 0x20; // set bit FileID in the ks2
2699 memcpy(&data[7], dfname, dfnamelen);
2700 datalen = 7 + dfnamelen;
2704 if (verbose) {
2705 PrintAndLogEx(INFO, "---------------------------");
2706 PrintAndLogEx(INFO, _CYAN_("Creating Application using:"));
2707 PrintAndLogEx(INFO, "AID 0x%02X%02X%02X", data[2], data[1], data[0]);
2708 PrintAndLogEx(INFO, "Key Set 1 0x%02X", data[3]);
2709 PrintAndLogEx(INFO, "Key Set 2 0x%02X", data[4]);
2710 PrintAndLogEx(INFO, "ISO file ID %s", (data[4] & 0x20) ? "enabled" : "disabled");
2711 if ((data[4] & 0x20)) {
2712 PrintAndLogEx(INFO, "ISO file ID 0x%04x", MemLeToUint2byte(&data[5]));
2713 PrintAndLogEx(INFO, "DF Name[%02d] %s | %s\n", dfnamelen, sprint_ascii(dfname, dfnamelen), sprint_hex(dfname, dfnamelen));
2715 PrintKeySettings(data[3], data[4], true, true);
2716 PrintAndLogEx(INFO, "---------------------------");
2719 res = DesfireCreateApplication(&dctx, data, datalen);
2720 if (res != PM3_SUCCESS) {
2721 PrintAndLogEx(ERR, "Desfire CreateApplication command " _RED_("error") ". Result: %d", res);
2722 DropField();
2723 return PM3_ESOFT;
2726 PrintAndLogEx(SUCCESS, "Desfire application %06x successfully " _GREEN_("created"), appid);
2728 DropField();
2729 return PM3_SUCCESS;
2732 static int CmdHF14ADesDeleteApp(const char *Cmd) {
2733 CLIParserContext *ctx;
2734 CLIParserInit(&ctx, "hf mfdes deleteapp",
2735 "Delete application by its 3-byte AID. Master key needs to be provided. ",
2736 "hf mfdes deleteapp --aid 123456 -> execute with default factory setup");
2738 void *argtable[] = {
2739 arg_param_begin,
2740 arg_lit0("a", "apdu", "Show APDU requests and responses"),
2741 arg_lit0("v", "verbose", "Verbose output"),
2742 arg_int0("n", "keyno", "<dec>", "Key number"),
2743 arg_str0("t", "algo", "<DES|2TDEA|3TDEA|AES>", "Crypt algo"),
2744 arg_str0("k", "key", "<hex>", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"),
2745 arg_str0(NULL, "kdf", "<none|AN10922|gallagher>", "Key Derivation Function (KDF)"),
2746 arg_str0("i", "kdfi", "<hex>", "KDF input (1-31 hex bytes)"),
2747 arg_str0("m", "cmode", "<plain|mac|encrypt>", "Communicaton mode"),
2748 arg_str0("c", "ccset", "<native|niso|iso>", "Communicaton command set"),
2749 arg_str0(NULL, "schann", "<d40|ev1|ev2|lrp>", "Secure channel"),
2750 arg_str0(NULL, "aid", "<hex>", "Application ID to delete (3 hex bytes, big endian)"),
2751 arg_param_end
2753 CLIExecWithReturn(ctx, Cmd, argtable, false);
2755 bool APDULogging = arg_get_lit(ctx, 1);
2756 bool verbose = arg_get_lit(ctx, 2);
2758 DesfireContext_t dctx;
2759 int securechann = defaultSecureChannel;
2760 uint32_t appid = 0x000000;
2761 int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, DCMMACed, &appid, NULL);
2762 if (res) {
2763 CLIParserFree(ctx);
2764 return res;
2767 SetAPDULogging(APDULogging);
2768 CLIParserFree(ctx);
2770 if (appid == 0x000000) {
2771 PrintAndLogEx(WARNING, "Deleting the root aid (0x000000) is " _RED_("forbidden"));
2772 return PM3_ESOFT;
2775 res = DesfireSelectAndAuthenticate(&dctx, securechann, 0x000000, verbose);
2776 if (res != PM3_SUCCESS) {
2777 DropField();
2778 return res;
2781 res = DesfireDeleteApplication(&dctx, appid);
2782 if (res != PM3_SUCCESS) {
2783 PrintAndLogEx(ERR, "Desfire DeleteApplication command " _RED_("error") ". Result: %d", res);
2784 DropField();
2785 return PM3_ESOFT;
2788 PrintAndLogEx(SUCCESS, "Desfire application %06x " _GREEN_("deleted"), appid);
2790 DropField();
2791 return PM3_SUCCESS;
2794 static int CmdHF14ADesGetUID(const char *Cmd) {
2795 CLIParserContext *ctx;
2796 CLIParserInit(&ctx, "hf mfdes getuid",
2797 "Get UID from card. Get the real UID if the random UID bit is on and get the same UID as in anticollision if not. Any card's key needs to be provided. ",
2798 "hf mfdes getuid -> execute with default factory setup\n"
2799 "hf mfdes getuid --isoid df01 -t aes --schan lrp -> for desfire lights default settings");
2801 void *argtable[] = {
2802 arg_param_begin,
2803 arg_lit0("a", "apdu", "Show APDU requests and responses"),
2804 arg_lit0("v", "verbose", "Verbose output"),
2805 arg_int0("n", "keyno", "<dec>", "Key number"),
2806 arg_str0("t", "algo", "<DES|2TDEA|3TDEA|AES>", "Crypt algo"),
2807 arg_str0("k", "key", "<hex>", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"),
2808 arg_str0(NULL, "kdf", "<none|AN10922|gallagher>", "Key Derivation Function (KDF)"),
2809 arg_str0("i", "kdfi", "<hex>", "KDF input (1-31 hex bytes)"),
2810 arg_str0("m", "cmode", "<plain|mac|encrypt>", "Communicaton mode"),
2811 arg_str0("c", "ccset", "<native|niso|iso>", "Communicaton command set"),
2812 arg_str0(NULL, "schann", "<d40|ev1|ev2|lrp>", "Secure channel"),
2813 arg_str0(NULL, "aid", "<hex>", "Application ID (3 hex bytes, big endian)"),
2814 arg_str0(NULL, "isoid", "<hex>", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian)"),
2815 arg_param_end
2817 CLIExecWithReturn(ctx, Cmd, argtable, true);
2819 bool APDULogging = arg_get_lit(ctx, 1);
2820 bool verbose = arg_get_lit(ctx, 2);
2822 DesfireContext_t dctx;
2823 int securechann = defaultSecureChannel;
2824 uint32_t id = 0x000000;
2825 DesfireISOSelectWay selectway = ISW6bAID;
2826 int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, &securechann, DCMEncrypted, &id, &selectway);
2827 if (res) {
2828 CLIParserFree(ctx);
2829 return res;
2832 SetAPDULogging(APDULogging);
2833 CLIParserFree(ctx);
2835 res = DesfireSelectAndAuthenticateAppW(&dctx, securechann, selectway, id, false, verbose);
2836 if (res != PM3_SUCCESS) {
2837 DropField();
2838 PrintAndLogEx(FAILED, "Select or authentication %s " _RED_("failed") ". Result [%d] %s", DesfireWayIDStr(selectway, id), res, DesfireAuthErrorToStr(res));
2839 return res;
2842 uint8_t buf[APDU_RES_LEN] = {0};
2843 size_t buflen = 0;
2845 res = DesfireGetUID(&dctx, buf, &buflen);
2846 if (res != PM3_SUCCESS) {
2847 PrintAndLogEx(ERR, "Desfire GetUID command " _RED_("error") ". Result: %d", res);
2848 DropField();
2849 return PM3_ESOFT;
2852 if (verbose)
2853 PrintAndLogEx(SUCCESS, "received data[%zu]: %s", buflen, sprint_hex(buf, buflen));
2855 if (buflen > 0) {
2856 if (buf[0] != 0) {
2857 PrintAndLogEx(SUCCESS, "Desfire UID[%zu]: " _GREEN_("%s"), buflen, sprint_hex(buf, buflen));
2858 } else {
2859 if (buf[1] == 0x04) {
2860 PrintAndLogEx(SUCCESS, "Desfire UID4: " _GREEN_("%s"), sprint_hex(&buf[2], 4));
2861 } else if (buf[1] == 0x0a) {
2862 PrintAndLogEx(SUCCESS, "Desfire UID10: " _GREEN_("%s"), sprint_hex(&buf[2], 10));
2863 } else {
2864 PrintAndLogEx(WARNING, "Card returned wrong uid length: %d (0x%02x)", buf[1], buf[1]);
2867 } else {
2868 PrintAndLogEx(WARNING, "Card returned no data");
2871 DropField();
2872 return PM3_SUCCESS;
2875 static int CmdHF14ADesFormatPICC(const char *Cmd) {
2876 CLIParserContext *ctx;
2877 CLIParserInit(&ctx, "hf mfdes formatpicc",
2878 "Format card. Can be done only if enabled in the configuration. Master key needs to be provided. ",
2879 "hf mfdes formatpicc -> execute with default factory setup");
2881 void *argtable[] = {
2882 arg_param_begin,
2883 arg_lit0("a", "apdu", "Show APDU requests and responses"),
2884 arg_lit0("v", "verbose", "Verbose output"),
2885 arg_int0("n", "keyno", "<dec>", "Key number"),
2886 arg_str0("t", "algo", "<DES|2TDEA|3TDEA|AES>", "Crypt algo"),
2887 arg_str0("k", "key", "<hex>", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"),
2888 arg_str0(NULL, "kdf", "<none|AN10922|gallagher>", "Key Derivation Function (KDF)"),
2889 arg_str0("i", "kdfi", "<hex>", "KDF input (1-31 hex bytes)"),
2890 arg_str0("m", "cmode", "<plain|mac|encrypt>", "Communicaton mode"),
2891 arg_str0("c", "ccset", "<native|niso|iso>", "Communicaton command set"),
2892 arg_str0(NULL, "schann", "<d40|ev1|ev2|lrp>", "Secure channel"),
2893 arg_str0(NULL, "aid", "<hex>", "Application ID of delegated application (3 hex bytes, big endian)"),
2894 arg_param_end
2896 CLIExecWithReturn(ctx, Cmd, argtable, true);
2898 bool APDULogging = arg_get_lit(ctx, 1);
2899 bool verbose = arg_get_lit(ctx, 2);
2901 DesfireContext_t dctx;
2902 int securechann = defaultSecureChannel;
2903 uint32_t appid = 0x000000;
2904 int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, DCMMACed, &appid, NULL);
2905 if (res) {
2906 CLIParserFree(ctx);
2907 return res;
2910 SetAPDULogging(APDULogging);
2911 CLIParserFree(ctx);
2913 res = DesfireSelectAndAuthenticate(&dctx, securechann, appid, verbose);
2914 if (res != PM3_SUCCESS) {
2915 DropField();
2916 return res;
2919 res = DesfireFormatPICC(&dctx);
2920 if (res != PM3_SUCCESS) {
2921 PrintAndLogEx(ERR, "Desfire FormatPICC command " _RED_("error") ". Result: %d", res);
2922 DropField();
2923 return PM3_ESOFT;
2926 PrintAndLogEx(SUCCESS, "Desfire format: " _GREEN_("done"));
2928 DropField();
2929 return PM3_SUCCESS;
2932 static int CmdHF14ADesGetFreeMem(const char *Cmd) {
2933 CLIParserContext *ctx;
2934 CLIParserInit(&ctx, "hf mfdes getfreemem",
2935 "Get card's free memory. Can be done with or without authentication. Master key may be provided.",
2936 "hf mfdes getfreemem -> execute with default factory setup");
2938 void *argtable[] = {
2939 arg_param_begin,
2940 arg_lit0("a", "apdu", "Show APDU requests and responses"),
2941 arg_lit0("v", "verbose", "Verbose output"),
2942 arg_int0("n", "keyno", "<dec>", "Key number"),
2943 arg_str0("t", "algo", "<DES|2TDEA|3TDEA|AES>", "Crypt algo"),
2944 arg_str0("k", "key", "<hex>", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"),
2945 arg_str0(NULL, "kdf", "<none|AN10922|gallagher>", "Key Derivation Function (KDF)"),
2946 arg_str0("i", "kdfi", "<hex>", "KDF input (1-31 hex bytes)"),
2947 arg_str0("m", "cmode", "<plain|mac|encrypt>", "Communicaton mode"),
2948 arg_str0("c", "ccset", "<native|niso|iso>", "Communicaton command set"),
2949 arg_str0(NULL, "schann", "<d40|ev1|ev2|lrp>", "Secure channel"),
2950 arg_lit0(NULL, "no-auth", "Execute without authentication"),
2951 arg_param_end
2953 CLIExecWithReturn(ctx, Cmd, argtable, true);
2955 bool APDULogging = arg_get_lit(ctx, 1);
2956 bool verbose = arg_get_lit(ctx, 2);
2958 bool noauth = arg_get_lit(ctx, 11);
2960 DesfireContext_t dctx;
2961 int securechann = defaultSecureChannel;
2962 int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, &securechann, (noauth) ? DCMPlain : DCMMACed, NULL, NULL);
2963 if (res) {
2964 CLIParserFree(ctx);
2965 return res;
2968 SetAPDULogging(APDULogging);
2969 CLIParserFree(ctx);
2971 res = DesfireSelectAndAuthenticateEx(&dctx, securechann, 0x000000, noauth, verbose);
2972 if (res != PM3_SUCCESS) {
2973 DropField();
2974 return res;
2977 uint32_t freemem = 0;
2979 res = DesfireGetFreeMem(&dctx, &freemem);
2980 if (res != PM3_SUCCESS) {
2981 PrintAndLogEx(ERR, "Desfire GetFreeMem command " _RED_("error") ". Result: %d", res);
2982 DropField();
2983 return PM3_ESOFT;
2986 PrintAndLogEx(SUCCESS, "Free memory [0x%06x] %d bytes", freemem, freemem);
2988 DropField();
2989 return PM3_SUCCESS;
2992 static int CmdHF14ADesChKeySettings(const char *Cmd) {
2993 CLIParserContext *ctx;
2994 CLIParserInit(&ctx, "hf mfdes chkeysettings",
2995 "Change key settings for card level or application level.\n"
2996 "WARNING: card level changes may block the card!",
2997 "hf mfdes chkeysettings -d 0f -> set picc key settings with default key/channel setup\n"\
2998 "hf mfdes chkeysettings --aid 123456 -d 0f -> set app 123456 key settings with default key/channel setup");
3000 void *argtable[] = {
3001 arg_param_begin,
3002 arg_lit0("a", "apdu", "Show APDU requests and responses"),
3003 arg_lit0("v", "verbose", "Verbose output"),
3004 arg_int0("n", "keyno", "<dec>", "Key number"),
3005 arg_str0("t", "algo", "<DES|2TDEA|3TDEA|AES>", "Crypt algo"),
3006 arg_str0("k", "key", "<hex>", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"),
3007 arg_str0(NULL, "kdf", "<none|AN10922|gallagher>", "Key Derivation Function (KDF)"),
3008 arg_str0("i", "kdfi", "<hex>", "KDF input (1-31 hex bytes)"),
3009 arg_str0("m", "cmode", "<plain|mac|encrypt>", "Communicaton mode"),
3010 arg_str0("c", "ccset", "<native|niso|iso>", "Communicaton command set"),
3011 arg_str0(NULL, "schann", "<d40|ev1|ev2|lrp>", "Secure channel"),
3012 arg_str0(NULL, "aid", "<hex>", "Application ID (3 hex bytes, big endian)"),
3013 arg_str0("d", "data", "<HEX>", "Key settings (1 hex byte)"),
3014 arg_param_end
3016 CLIExecWithReturn(ctx, Cmd, argtable, false);
3018 bool APDULogging = arg_get_lit(ctx, 1);
3019 bool verbose = arg_get_lit(ctx, 2);
3021 DesfireContext_t dctx;
3022 int securechann = defaultSecureChannel;
3023 uint32_t appid = 0x000000;
3024 int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, DCMEncrypted, &appid, NULL);
3025 if (res) {
3026 CLIParserFree(ctx);
3027 return res;
3030 uint32_t ksett32 = 0;
3031 if (CLIGetUint32Hex(ctx, 12, 0x0f, &ksett32, NULL, 1, "Key settings must have 1 byte length")) {
3032 CLIParserFree(ctx);
3033 return PM3_EINVARG;
3036 SetAPDULogging(APDULogging);
3037 CLIParserFree(ctx);
3039 if (verbose) {
3040 PrintAndLogEx(SUCCESS, "\nNew key settings:");
3041 PrintKeySettings(ksett32, 0, (appid != 0x000000), false);
3044 res = DesfireSelectAndAuthenticate(&dctx, securechann, appid, verbose);
3045 if (res != PM3_SUCCESS) {
3046 DropField();
3047 return res;
3050 uint8_t keysett = ksett32 & 0xff;
3051 res = DesfireChangeKeySettings(&dctx, &keysett, 1);
3052 if (res != PM3_SUCCESS) {
3053 PrintAndLogEx(ERR, "Desfire ChangeKeySettings command " _RED_("error") ". Result: %d", res);
3054 DropField();
3055 return PM3_ESOFT;
3058 PrintAndLogEx(INFO, "Key settings " _GREEN_("changed"));
3060 DropField();
3061 return PM3_SUCCESS;
3064 static int CmdHF14ADesGetKeyVersions(const char *Cmd) {
3065 CLIParserContext *ctx;
3066 CLIParserInit(&ctx, "hf mfdes getkeyversions",
3067 "Get key versions for card level or application level.",
3068 "--keynum parameter: App level: key number. PICC level: 00..0d - keys count, 21..23 vc keys, default 0x00.\n"\
3069 "hf mfdes getkeyversions --keynum 00 -> get picc master key version with default key/channel setup\n"\
3070 "hf mfdes getkeyversions --aid 123456 --keynum 0d -> get app 123456 all key versions with default key/channel setup\n"
3071 "hf mfdes getkeyversions --aid 123456 --keynum 0d --no-auth -> get key version without authentication");
3073 void *argtable[] = {
3074 arg_param_begin,
3075 arg_lit0("a", "apdu", "Show APDU requests and responses"),
3076 arg_lit0("v", "verbose", "Verbose output"),
3077 arg_int0("n", "keyno", "<dec>", "Key number for authentication"),
3078 arg_str0("t", "algo", "<DES|2TDEA|3TDEA|AES>", "Crypt algo"),
3079 arg_str0("k", "key", "<hex>", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"),
3080 arg_str0(NULL, "kdf", "<none|AN10922|gallagher>", "Key Derivation Function (KDF)"),
3081 arg_str0("i", "kdfi", "<hex>", "KDF input (1-31 hex bytes)"),
3082 arg_str0("m", "cmode", "<plain|mac|encrypt>", "Communicaton mode"),
3083 arg_str0("c", "ccset", "<native|niso|iso>", "Communicaton command set"),
3084 arg_str0(NULL, "schann", "<d40|ev1|ev2|lrp>", "Secure channel"),
3085 arg_str0(NULL, "aid", "<hex>", "Application ID (3 hex bytes, big endian)"),
3086 arg_str0(NULL, "isoid", "<hex>", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian)."),
3087 arg_str0(NULL, "keynum", "<hex>", "Key number/count (1 hex byte). (def: 0x00)"),
3088 arg_str0(NULL, "keyset", "<hex>", "Keyset number (1 hex byte)"),
3089 arg_lit0(NULL, "no-auth", "Execute without authentication"),
3090 arg_param_end
3092 CLIExecWithReturn(ctx, Cmd, argtable, true);
3094 bool APDULogging = arg_get_lit(ctx, 1);
3095 bool verbose = arg_get_lit(ctx, 2);
3096 bool noauth = arg_get_lit(ctx, 15);
3098 DesfireContext_t dctx;
3099 int securechann = defaultSecureChannel;
3100 uint32_t id = 0x000000;
3101 DesfireISOSelectWay selectway = ISW6bAID;
3102 int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, &securechann, DCMMACed, &id, &selectway);
3103 if (res) {
3104 CLIParserFree(ctx);
3105 return res;
3108 uint32_t keynum32 = 0x00;
3109 if (CLIGetUint32Hex(ctx, 13, 0x00, &keynum32, NULL, 1, "Key number must have 1 byte length")) {
3110 CLIParserFree(ctx);
3111 return PM3_EINVARG;
3114 uint32_t keysetnum32 = 0x00;
3115 bool keysetpresent = false;
3116 if (CLIGetUint32Hex(ctx, 14, 0x00, &keysetnum32, &keysetpresent, 1, "Keyset number must have 1 byte length")) {
3117 CLIParserFree(ctx);
3118 return PM3_EINVARG;
3121 if (keysetpresent && DesfireMFSelected(selectway, id)) {
3122 PrintAndLogEx(WARNING, "Keyset only at Application level");
3123 keysetpresent = false;
3126 SetAPDULogging(APDULogging);
3127 CLIParserFree(ctx);
3129 res = DesfireSelectAndAuthenticateAppW(&dctx, securechann, selectway, id, noauth, verbose);
3130 if (res != PM3_SUCCESS) {
3131 DropField();
3132 PrintAndLogEx(FAILED, "Select or authentication %s " _RED_("failed") ". Result [%d] %s", DesfireWayIDStr(selectway, id), res, DesfireAuthErrorToStr(res));
3133 return res;
3136 uint8_t buf[APDU_RES_LEN] = {0};
3137 size_t buflen = 0;
3139 uint8_t data[2] = {0};
3140 data[0] = keynum32 & 0xff;
3141 if (keysetpresent) {
3142 data[0] |= 0x40;
3143 data[1] = keysetnum32 & 0xff;
3146 res = DesfireGetKeyVersion(&dctx, data, (keysetpresent) ? 2 : 1, buf, &buflen);
3147 if (res != PM3_SUCCESS) {
3148 PrintAndLogEx(ERR, "Desfire GetKeyVersion command " _RED_("error") ". Result: %d", res);
3149 DropField();
3150 return PM3_ESOFT;
3153 if (verbose)
3154 PrintAndLogEx(INFO, "GetKeyVersion[%zu]: %s", buflen, sprint_hex(buf, buflen));
3156 if (buflen > 0) {
3157 PrintAndLogEx(INFO, "----------------------- " _CYAN_("Key Versions") " -----------------------");
3158 for (int i = 0; i < buflen; i++)
3159 PrintAndLogEx(INFO, "Key 0x%02x version 0x%02x", i, buf[i]);
3160 } else {
3161 PrintAndLogEx(INFO, "No key versions returned.");
3164 DropField();
3165 return PM3_SUCCESS;
3168 static int CmdHF14ADesGetKeySettings(const char *Cmd) {
3169 CLIParserContext *ctx;
3170 CLIParserInit(&ctx, "hf mfdes getkeysettings",
3171 "Get key settings for card level or application level.",
3172 "hf mfdes getkeysettings -> get picc key settings with default key/channel setup\n"\
3173 "hf mfdes getkeysettings --aid 123456 -> get app 123456 key settings with default key/channel setup");
3175 void *argtable[] = {
3176 arg_param_begin,
3177 arg_lit0("a", "apdu", "Show APDU requests and responses"),
3178 arg_lit0("v", "verbose", "Verbose output"),
3179 arg_int0("n", "keyno", "<dec>", "Key number"),
3180 arg_str0("t", "algo", "<DES|2TDEA|3TDEA|AES>", "Crypt algo"),
3181 arg_str0("k", "key", "<hex>", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"),
3182 arg_str0(NULL, "kdf", "<none|AN10922|gallagher>", "Key Derivation Function (KDF)"),
3183 arg_str0("i", "kdfi", "<hex>", "KDF input (1-31 hex bytes)"),
3184 arg_str0("m", "cmode", "<plain|mac|encrypt>", "Communicaton mode"),
3185 arg_str0("c", "ccset", "<native|niso|iso>", "Communicaton command set"),
3186 arg_str0(NULL, "schann", "<d40|ev1|ev2|lrp>", "Secure channel"),
3187 arg_str0(NULL, "aid", "<hex>", "Application ID (3 hex bytes, big endian)"),
3188 arg_param_end
3190 CLIExecWithReturn(ctx, Cmd, argtable, true);
3192 bool APDULogging = arg_get_lit(ctx, 1);
3193 bool verbose = arg_get_lit(ctx, 2);
3195 DesfireContext_t dctx;
3196 int securechann = defaultSecureChannel;
3197 uint32_t appid = 0x000000;
3198 int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, DCMMACed, &appid, NULL);
3199 if (res) {
3200 CLIParserFree(ctx);
3201 return res;
3204 SetAPDULogging(APDULogging);
3205 CLIParserFree(ctx);
3207 res = DesfireSelectAndAuthenticate(&dctx, securechann, appid, verbose);
3208 if (res != PM3_SUCCESS) {
3209 DropField();
3210 return res;
3213 uint8_t buf[APDU_RES_LEN] = {0};
3214 size_t buflen = 0;
3216 res = DesfireGetKeySettings(&dctx, buf, &buflen);
3217 if (res != PM3_SUCCESS) {
3218 PrintAndLogEx(ERR, "Desfire GetKeySettings command " _RED_("error") ". Result: %d", res);
3219 DropField();
3220 return PM3_ESOFT;
3223 if (verbose)
3224 PrintAndLogEx(INFO, "GetKeySettings[%zu]: %s", buflen, sprint_hex(buf, buflen));
3226 if (buflen < 2) {
3227 PrintAndLogEx(ERR, "Command GetKeySettings returned wrong length: %zu", buflen);
3228 DropField();
3229 return PM3_ESOFT;
3232 PrintAndLogEx(INFO, "----------------------- " _CYAN_("Key settings") " -----------------------");
3233 PrintKeySettings(buf[0], buf[1], (appid != 0x000000), true);
3234 if (buflen > 2)
3235 PrintAndLogEx(INFO, "ak ver: %d", buf[2]);
3236 if (buflen > 3)
3237 PrintAndLogEx(INFO, "num keysets: %d", buf[3]);
3238 if (buflen > 4)
3239 PrintAndLogEx(INFO, "max keysize: %d", buf[4]);
3240 if (buflen > 5)
3241 PrintAndLogEx(INFO, "app key settings: 0x%02x", buf[5]);
3243 DropField();
3244 return PM3_SUCCESS;
3247 static int CmdHF14ADesGetAIDs(const char *Cmd) {
3248 CLIParserContext *ctx;
3249 CLIParserInit(&ctx, "hf mfdes getaids",
3250 "Get Application IDs list from card. Master key needs to be provided or flag --no-auth set.",
3251 "hf mfdes getaids -n 0 -t des -k 0000000000000000 --kdf none -> execute with default factory setup");
3253 void *argtable[] = {
3254 arg_param_begin,
3255 arg_lit0("a", "apdu", "Show APDU requests and responses"),
3256 arg_lit0("v", "verbose", "Verbose output"),
3257 arg_int0("n", "keyno", "<dec>", "Key number"),
3258 arg_str0("t", "algo", "<DES|2TDEA|3TDEA|AES>", "Crypt algo"),
3259 arg_str0("k", "key", "<hex>", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"),
3260 arg_str0(NULL, "kdf", "<none|AN10922|gallagher>", "Key Derivation Function (KDF)"),
3261 arg_str0("i", "kdfi", "<hex>", "KDF input (1-31 hex bytes)"),
3262 arg_str0("m", "cmode", "<plain|mac|encrypt>", "Communicaton mode"),
3263 arg_str0("c", "ccset", "<native|niso|iso>", "Communicaton command set"),
3264 arg_str0(NULL, "schann", "<d40|ev1|ev2|lrp>", "Secure channel"),
3265 arg_lit0(NULL, "no-auth", "Execute without authentication"),
3266 arg_param_end
3268 CLIExecWithReturn(ctx, Cmd, argtable, true);
3270 bool APDULogging = arg_get_lit(ctx, 1);
3271 bool verbose = arg_get_lit(ctx, 2);
3272 bool noauth = arg_get_lit(ctx, 11);
3274 DesfireContext_t dctx;
3275 int securechann = defaultSecureChannel;
3276 int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, &securechann, DCMMACed, NULL, NULL);
3277 if (res) {
3278 CLIParserFree(ctx);
3279 return res;
3282 SetAPDULogging(APDULogging);
3283 CLIParserFree(ctx);
3285 res = DesfireSelectAndAuthenticateEx(&dctx, securechann, 0x000000, noauth, verbose);
3286 if (res != PM3_SUCCESS) {
3287 DropField();
3288 return res;
3291 uint8_t buf[APDU_RES_LEN] = {0};
3292 size_t buflen = 0;
3294 res = DesfireGetAIDList(&dctx, buf, &buflen);
3295 if (res != PM3_SUCCESS) {
3296 PrintAndLogEx(ERR, "Desfire GetAIDList command " _RED_("error") ". Result: %d", res);
3297 DropField();
3298 return PM3_ESOFT;
3301 if (buflen >= 3) {
3302 PrintAndLogEx(INFO, "---- " _CYAN_("AID list") " ----");
3303 for (int i = 0; i < buflen; i += 3) {
3304 const char *commentStr = getAidCommentStr(&buf[i]);
3305 if ((void *) commentStr == &noCommentStr)
3306 PrintAndLogEx(INFO, "AID: %06x", DesfireAIDByteToUint(&buf[i]));
3307 else
3308 PrintAndLogEx(INFO, "AID: %06x (%s)", DesfireAIDByteToUint(&buf[i]), commentStr);
3310 } else {
3311 PrintAndLogEx(INFO, "There is no applications on the card");
3314 DropField();
3315 return PM3_SUCCESS;
3318 static int CmdHF14ADesGetAppNames(const char *Cmd) {
3319 CLIParserContext *ctx;
3320 CLIParserInit(&ctx, "hf mfdes getappnames",
3321 "Get Application IDs, ISO IDs and DF names from card. Master key needs to be provided or flag --no-auth set.",
3322 "hf mfdes getappnames -n 0 -t des -k 0000000000000000 --kdf none -> execute with default factory setup");
3324 void *argtable[] = {
3325 arg_param_begin,
3326 arg_lit0("a", "apdu", "Show APDU requests and responses"),
3327 arg_lit0("v", "verbose", "Verbose output"),
3328 arg_int0("n", "keyno", "<dec>", "Key number"),
3329 arg_str0("t", "algo", "<DES|2TDEA|3TDEA|AES>", "Crypt algo"),
3330 arg_str0("k", "key", "<hex>", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"),
3331 arg_str0(NULL, "kdf", "<none|AN10922|gallagher>", "Key Derivation Function (KDF)"),
3332 arg_str0("i", "kdfi", "<hex>", "KDF input (1-31 hex bytes)"),
3333 arg_str0("m", "cmode", "<plain|mac|encrypt>", "Communicaton mode"),
3334 arg_str0("c", "ccset", "<native|niso|iso>", "Communicaton command set"),
3335 arg_str0(NULL, "schann", "<d40|ev1|ev2|lrp>", "Secure channel"),
3336 arg_lit0(NULL, "no-auth", "Execute without authentication"),
3337 arg_param_end
3339 CLIExecWithReturn(ctx, Cmd, argtable, true);
3341 bool APDULogging = arg_get_lit(ctx, 1);
3342 bool verbose = arg_get_lit(ctx, 2);
3343 bool noauth = arg_get_lit(ctx, 11);
3345 DesfireContext_t dctx;
3346 int securechann = defaultSecureChannel;
3347 int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, &securechann, DCMMACed, NULL, NULL);
3348 if (res) {
3349 CLIParserFree(ctx);
3350 return res;
3353 SetAPDULogging(APDULogging);
3354 CLIParserFree(ctx);
3356 res = DesfireSelectAndAuthenticateEx(&dctx, securechann, 0x000000, noauth, verbose);
3357 if (res != PM3_SUCCESS) {
3358 DropField();
3359 return res;
3362 uint8_t buf[APDU_RES_LEN] = {0};
3363 size_t buflen = 0;
3365 // result bytes: 3, 2, 1-16. total record size = 24
3366 res = DesfireGetDFList(&dctx, buf, &buflen);
3367 if (res != PM3_SUCCESS) {
3368 PrintAndLogEx(ERR, "Desfire GetDFList command " _RED_("error") ". Result: %d", res);
3369 DropField();
3370 return PM3_ESOFT;
3373 if (buflen > 0) {
3374 PrintAndLogEx(INFO, "----------------------- " _CYAN_("File list") " -----------------------");
3375 for (int i = 0; i < buflen; i++)
3376 PrintAndLogEx(INFO, "AID: %06x ISO file id: %02x%02x ISO DF name[%zu]: %s",
3377 DesfireAIDByteToUint(&buf[i * 24 + 1]),
3378 buf[i * 24 + 1 + 3], buf[i * 24 + 1 + 4],
3379 strlen((char *)&buf[i * 24 + 1 + 5]),
3380 &buf[i * 24 + 1 + 5]);
3381 } else {
3382 PrintAndLogEx(INFO, "There is no applications on the card");
3385 DropField();
3386 return PM3_SUCCESS;
3389 static int CmdHF14ADesGetFileIDs(const char *Cmd) {
3390 CLIParserContext *ctx;
3391 CLIParserInit(&ctx, "hf mfdes getfileids",
3392 "Get File IDs list from card. Master key needs to be provided or flag --no-auth set.",
3393 "hf mfdes getfileids --aid 123456 -> execute with defaults from `default` command\n"
3394 "hf mfdes getfileids -n 0 -t des -k 0000000000000000 --kdf none --aid 123456 -> execute with default factory setup");
3396 void *argtable[] = {
3397 arg_param_begin,
3398 arg_lit0("a", "apdu", "Show APDU requests and responses"),
3399 arg_lit0("v", "verbose", "Verbose output"),
3400 arg_int0("n", "keyno", "<dec>", "Key number"),
3401 arg_str0("t", "algo", "<DES|2TDEA|3TDEA|AES>", "Crypt algo"),
3402 arg_str0("k", "key", "<hex>", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"),
3403 arg_str0(NULL, "kdf", "<none|AN10922|gallagher>", "Key Derivation Function (KDF)"),
3404 arg_str0("i", "kdfi", "<hex>", "KDF input (1-31 hex bytes)"),
3405 arg_str0("m", "cmode", "<plain|mac|encrypt>", "Communicaton mode"),
3406 arg_str0("c", "ccset", "<native|niso|iso>", "Communicaton command set"),
3407 arg_str0(NULL, "schann", "<d40|ev1|ev2|lrp>", "Secure channel"),
3408 arg_str0(NULL, "aid", "<hex>", "Application ID (3 hex bytes, big endian)"),
3409 arg_str0(NULL, "isoid", "<hex>", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian)."),
3410 arg_lit0(NULL, "no-auth", "Execute without authentication"),
3411 arg_param_end
3413 CLIExecWithReturn(ctx, Cmd, argtable, false);
3415 bool APDULogging = arg_get_lit(ctx, 1);
3416 bool verbose = arg_get_lit(ctx, 2);
3417 bool noauth = arg_get_lit(ctx, 13);
3419 DesfireContext_t dctx;
3420 int securechann = defaultSecureChannel;
3421 uint32_t id = 0x000000;
3422 DesfireISOSelectWay selectway = ISW6bAID;
3423 int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, &securechann, DCMMACed, &id, &selectway);
3424 if (res) {
3425 CLIParserFree(ctx);
3426 return res;
3429 SetAPDULogging(APDULogging);
3430 CLIParserFree(ctx);
3432 res = DesfireSelectAndAuthenticateAppW(&dctx, securechann, selectway, id, noauth, verbose);
3433 if (res != PM3_SUCCESS) {
3434 DropField();
3435 PrintAndLogEx(FAILED, "Select or authentication %s " _RED_("failed") ". Result [%d] %s", DesfireWayIDStr(selectway, id), res, DesfireAuthErrorToStr(res));
3436 return res;
3439 uint8_t buf[APDU_RES_LEN] = {0};
3440 size_t buflen = 0;
3442 res = DesfireGetFileIDList(&dctx, buf, &buflen);
3443 if (res != PM3_SUCCESS) {
3444 PrintAndLogEx(ERR, "Desfire GetFileIDList command " _RED_("error") ". Result: %d", res);
3445 DropField();
3446 return PM3_ESOFT;
3449 if (buflen > 0) {
3450 PrintAndLogEx(INFO, "---- " _CYAN_("File ID list") " ----");
3451 for (int i = 0; i < buflen; i++)
3452 PrintAndLogEx(INFO, "File ID: %02x", buf[i]);
3453 } else {
3454 PrintAndLogEx(INFO, "There is no files in the application %06x", id);
3457 DropField();
3458 return PM3_SUCCESS;
3461 static int CmdHF14ADesGetFileISOIDs(const char *Cmd) {
3462 CLIParserContext *ctx;
3463 CLIParserInit(&ctx, "hf mfdes getfileisoids",
3464 "Get File IDs list from card. Master key needs to be provided or flag --no-auth set.",
3465 "hf mfdes getfileisoids --aid 123456 -> execute with defaults from `default` command\n"
3466 "hf mfdes getfileisoids -n 0 -t des -k 0000000000000000 --kdf none --aid 123456 -> execute with default factory setup\n"
3467 "hf mfdes getfileisoids --isoid df01 -> get iso file ids from Desfire Light with factory card settings\n"
3468 "hf mfdes getfileisoids --isoid df01 --schann lrp -t aes -> get iso file ids from Desfire Light via lrp channel with default key authentication");
3470 void *argtable[] = {
3471 arg_param_begin,
3472 arg_lit0("a", "apdu", "Show APDU requests and responses"),
3473 arg_lit0("v", "verbose", "Verbose output"),
3474 arg_int0("n", "keyno", "<dec>", "Key number"),
3475 arg_str0("t", "algo", "<DES|2TDEA|3TDEA|AES>", "Crypt algo"),
3476 arg_str0("k", "key", "<hex>", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"),
3477 arg_str0(NULL, "kdf", "<none|AN10922|gallagher>", "Key Derivation Function (KDF)"),
3478 arg_str0("i", "kdfi", "<hex>", "KDF input (1-31 hex bytes)"),
3479 arg_str0("m", "cmode", "<plain|mac|encrypt>", "Communicaton mode"),
3480 arg_str0("c", "ccset", "<native|niso|iso>", "Communicaton command set"),
3481 arg_str0(NULL, "schann", "<d40|ev1|ev2|lrp>", "Secure channel"),
3482 arg_str0(NULL, "aid", "<hex>", "Application ID (3 hex bytes, big endian)"),
3483 arg_str0(NULL, "isoid", "<hex>", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian)."),
3484 arg_lit0(NULL, "no-auth", "Execute without authentication"),
3485 arg_param_end
3487 CLIExecWithReturn(ctx, Cmd, argtable, false);
3489 bool APDULogging = arg_get_lit(ctx, 1);
3490 bool verbose = arg_get_lit(ctx, 2);
3491 bool noauth = arg_get_lit(ctx, 13);
3493 DesfireContext_t dctx;
3494 int securechann = defaultSecureChannel;
3495 uint32_t id = 0x000000;
3496 DesfireISOSelectWay selectway = ISW6bAID;
3497 int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, &securechann, DCMMACed, &id, &selectway);
3498 if (res) {
3499 CLIParserFree(ctx);
3500 return res;
3503 SetAPDULogging(APDULogging);
3504 CLIParserFree(ctx);
3506 res = DesfireSelectAndAuthenticateAppW(&dctx, securechann, selectway, id, noauth, verbose);
3507 if (res != PM3_SUCCESS) {
3508 DropField();
3509 PrintAndLogEx(FAILED, "Select or authentication %s " _RED_("failed") ". Result [%d] %s", DesfireWayIDStr(selectway, id), res, DesfireAuthErrorToStr(res));
3510 return res;
3513 uint8_t buf[APDU_RES_LEN] = {0};
3514 size_t buflen = 0;
3516 res = DesfireGetFileISOIDList(&dctx, buf, &buflen);
3517 if (res != PM3_SUCCESS) {
3518 PrintAndLogEx(ERR, "Desfire GetFileISOIDList command " _RED_("error") ". Result: %d", res);
3519 DropField();
3520 return PM3_ESOFT;
3523 if (buflen > 1) {
3524 PrintAndLogEx(INFO, "---- " _CYAN_("File ISO ID list") " ----");
3525 for (int i = 0; i < buflen; i += 2)
3526 PrintAndLogEx(INFO, "File ID: %04x", MemLeToUint2byte(&buf[i]));
3527 } else {
3528 PrintAndLogEx(INFO, "There is no files in the application %06x", id);
3531 DropField();
3532 return PM3_SUCCESS;
3535 static int CmdHF14ADesGetFileSettings(const char *Cmd) {
3536 CLIParserContext *ctx;
3537 CLIParserInit(&ctx, "hf mfdes getfilesettings",
3538 "Get File Settings from file from application. Master key needs to be provided or flag --no-auth set (depend on cards settings).",
3539 "hf mfdes getfilesettings --aid 123456 --fid 01 -> execute with defaults from `default` command\n"
3540 "hf mfdes getfilesettings --isoid df01 --fid 00 --no-auth -> get file settings with select by iso id\n"
3541 "hf mfdes getfilesettings -n 0 -t des -k 0000000000000000 --kdf none --aid 123456 --fid 01 -> execute with default factory setup");
3543 void *argtable[] = {
3544 arg_param_begin,
3545 arg_lit0("a", "apdu", "Show APDU requests and responses"),
3546 arg_lit0("v", "verbose", "Verbose output"),
3547 arg_int0("n", "keyno", "<dec>", "Key number"),
3548 arg_str0("t", "algo", "<DES|2TDEA|3TDEA|AES>", "Crypt algo"),
3549 arg_str0("k", "key", "<hex>", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"),
3550 arg_str0(NULL, "kdf", "<none|AN10922|gallagher>", "Key Derivation Function (KDF)"),
3551 arg_str0("i", "kdfi", "<hex>", "KDF input (1-31 hex bytes)"),
3552 arg_str0("m", "cmode", "<plain|mac|encrypt>", "Communicaton mode"),
3553 arg_str0("c", "ccset", "<native|niso|iso>", "Communicaton command set"),
3554 arg_str0(NULL, "schann", "<d40|ev1|ev2|lrp>", "Secure channel"),
3555 arg_str0(NULL, "aid", "<hex>", "Application ID (3 hex bytes, big endian)"),
3556 arg_str0(NULL, "isoid", "<hex>", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian)"),
3557 arg_str0(NULL, "fid", "<hex>", "File ID (1 hex byte). (def: 1)"),
3558 arg_lit0(NULL, "no-auth", "Execute without authentication"),
3559 arg_param_end
3561 CLIExecWithReturn(ctx, Cmd, argtable, false);
3563 bool APDULogging = arg_get_lit(ctx, 1);
3564 bool verbose = arg_get_lit(ctx, 2);
3565 bool noauth = arg_get_lit(ctx, 14);
3567 DesfireContext_t dctx;
3568 int securechann = defaultSecureChannel;
3569 uint32_t id = 0x000000;
3570 DesfireISOSelectWay selectway = ISW6bAID;
3571 int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, &securechann, DCMMACed, &id, &selectway);
3572 if (res) {
3573 CLIParserFree(ctx);
3574 return res;
3577 uint32_t fileid = 1;
3578 if (CLIGetUint32Hex(ctx, 13, 1, &fileid, NULL, 1, "File ID must have 1 byte length")) {
3579 CLIParserFree(ctx);
3580 return PM3_EINVARG;
3583 SetAPDULogging(APDULogging);
3584 CLIParserFree(ctx);
3586 res = DesfireSelectAndAuthenticateAppW(&dctx, securechann, selectway, id, noauth, verbose);
3587 if (res != PM3_SUCCESS) {
3588 DropField();
3589 PrintAndLogEx(FAILED, "Select or authentication %s " _RED_("failed") ". Result [%d] %s", DesfireWayIDStr(selectway, id), res, DesfireAuthErrorToStr(res));
3590 return res;
3593 uint8_t buf[APDU_RES_LEN] = {0};
3594 size_t buflen = 0;
3596 res = DesfireGetFileSettings(&dctx, fileid, buf, &buflen);
3597 if (res != PM3_SUCCESS) {
3598 PrintAndLogEx(ERR, "Desfire GetFileSettings command " _RED_("error") ". Result: %d", res);
3599 DropField();
3600 return PM3_ESOFT;
3603 if (verbose)
3604 PrintAndLogEx(INFO, "%s file %02x settings[%zu]: %s", DesfireWayIDStr(selectway, id), fileid, buflen, sprint_hex(buf, buflen));
3606 DesfirePrintFileSettings(buf, buflen);
3608 PrintAndLogEx(NORMAL, "");
3609 DropField();
3610 return PM3_SUCCESS;
3613 static int DesfireCreateFileParameters(
3614 CLIParserContext *ctx,
3615 uint8_t pfileid, uint8_t pisofileid,
3616 uint8_t amodeid, uint8_t frightsid,
3617 uint8_t r_modeid, uint8_t w_modeid, uint8_t rw_modeid, uint8_t ch_modeid,
3618 uint8_t *data, size_t *datalen) {
3620 *datalen = 0;
3622 uint32_t fileid = 1;
3623 if (pfileid) {
3624 if (CLIGetUint32Hex(ctx, pfileid, 1, &fileid, NULL, 1, "File ID must have 1 byte length"))
3625 return PM3_EINVARG;
3628 uint32_t isofileid = 0;
3629 if (pisofileid) {
3630 if (CLIGetUint32Hex(ctx, pisofileid, 0, &isofileid, NULL, 2, "ISO file ID must have 2 bytes length"))
3631 return PM3_EINVARG;
3634 data[0] = fileid;
3635 *datalen = 1;
3637 if (isofileid > 0) {
3638 Uint2byteToMemLe(&data[1], isofileid);
3639 *datalen += 2;
3642 uint8_t *settings = &data[*datalen];
3644 // file access mode
3645 int cmode = DCMNone;
3646 if (amodeid) {
3647 if (CLIGetOptionList(arg_get_str(ctx, amodeid), DesfireCommunicationModeOpts, &cmode)) {
3648 return PM3_ESOFT;
3651 if (cmode == DCMPlain)
3652 settings[0] = 0x00;
3653 if (cmode == DCMMACed)
3654 settings[0] = 0x01;
3655 if (cmode == DCMEncrypted)
3656 settings[0] = 0x03;
3657 (*datalen)++;
3660 // file rights
3661 uint32_t frights = 0xeeee;
3662 bool userawfrights = false;
3663 if (frightsid) {
3664 if (CLIGetUint32Hex(ctx, frightsid, 0xeeee, &frights, &userawfrights, 2, "File rights must have 2 bytes length")) {
3665 return PM3_EINVARG;
3668 settings[1] = frights & 0xff;
3669 settings[2] = (frights >> 8) & 0xff;
3671 if (userawfrights == false) {
3672 int r_mode = 0x0e;
3673 if (r_modeid) {
3674 if (CLIGetOptionList(arg_get_str(ctx, r_modeid), DesfireFileAccessModeOpts, &r_mode))
3675 return PM3_ESOFT;
3678 int w_mode = 0x0e;
3679 if (w_modeid) {
3680 if (CLIGetOptionList(arg_get_str(ctx, w_modeid), DesfireFileAccessModeOpts, &w_mode))
3681 return PM3_ESOFT;
3684 int rw_mode = 0x0e;
3685 if (rw_modeid) {
3686 if (CLIGetOptionList(arg_get_str(ctx, rw_modeid), DesfireFileAccessModeOpts, &rw_mode))
3687 return PM3_ESOFT;
3690 int ch_mode = 0x0e;
3691 if (ch_modeid) {
3692 if (CLIGetOptionList(arg_get_str(ctx, ch_modeid), DesfireFileAccessModeOpts, &ch_mode))
3693 return PM3_ESOFT;
3696 DesfireEncodeFileAcessMode(&settings[1], r_mode, w_mode, rw_mode, ch_mode) ;
3698 *datalen += 2;
3700 return PM3_SUCCESS;
3703 static int CmdHF14ADesChFileSettings(const char *Cmd) {
3704 CLIParserContext *ctx;
3705 CLIParserInit(&ctx, "hf mfdes chfilesettings",
3706 "Get File Settings from file from application. Master key needs to be provided or flag --no-auth set (depend on cards settings).",
3707 "hf mfdes chfilesettings --aid 123456 --fid 01 --amode plain --rrights free --wrights free --rwrights free --chrights key0 -> change file settings app=123456, file=01 with defaults from `default` command\n"
3708 "hf mfdes chfilesettings -n 0 -t des -k 0000000000000000 --kdf none --aid 123456 --fid 01 --rawdata 00EEEE -> execute with default factory setup\n"
3709 "hf mfdes chfilesettings --aid 123456 --fid 01 --rawdata 810000021f112f22 -> change file settings with additional rights for keys 1 and 2\n"
3710 "hf mfdes chfilesettings --isoid df01 --fid 00 --amode plain --rawrights eee0 --schann lrp -t aes -> change file settings via lrp channel");
3712 void *argtable[] = {
3713 arg_param_begin,
3714 arg_lit0("a", "apdu", "Show APDU requests and responses"),
3715 arg_lit0("v", "verbose", "Verbose output"),
3716 arg_int0("n", "keyno", "<dec>", "Key number"),
3717 arg_str0("t", "algo", "<DES|2TDEA|3TDEA|AES>", "Crypt algo"),
3718 arg_str0("k", "key", "<hex>", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"),
3719 arg_str0(NULL, "kdf", "<none|AN10922|gallagher>", "Key Derivation Function (KDF)"),
3720 arg_str0("i", "kdfi", "<hex>", "KDF input (1-31 hex bytes)"),
3721 arg_str0("m", "cmode", "<plain|mac|encrypt>", "Communicaton mode"),
3722 arg_str0("c", "ccset", "<native|niso|iso>", "Communicaton command set"),
3723 arg_str0(NULL, "schann", "<d40|ev1|ev2|lrp>", "Secure channel"),
3724 arg_str0(NULL, "aid", "<hex>", "Application ID (3 hex bytes, big endian)"),
3725 arg_str0(NULL, "isoid", "<hex>", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian)"),
3726 arg_str0(NULL, "fid", "<hex>", "File ID (1 hex byte)"),
3727 arg_str0(NULL, "rawdata", "<hex>", "File settings (HEX > 5 bytes). Have priority over the other settings"),
3728 arg_str0(NULL, "amode", "<plain|mac|encrypt>", "File access mode"),
3729 arg_str0(NULL, "rawrights", "<hex>", "Access rights for file (2 hex bytes) R/W/RW/Chg, 0x0 - 0xD Key, 0xE Free, 0xF Denied"),
3730 arg_str0(NULL, "rrights", "<key0..13|free|deny>", "Read file access mode: the specified key, free, deny"),
3731 arg_str0(NULL, "wrights", "<key0..13|free|deny>", "Write file access mode: the specified key, free, deny"),
3732 arg_str0(NULL, "rwrights", "<key0..13|free|deny>", "Read/Write file access mode: the specified key, free, deny"),
3733 arg_str0(NULL, "chrights", "<key0..13|free|deny>", "Change file settings access mode: the specified key, free, deny"),
3734 arg_lit0(NULL, "no-auth", "Execute without authentication"),
3735 arg_param_end
3737 CLIExecWithReturn(ctx, Cmd, argtable, false);
3739 bool APDULogging = arg_get_lit(ctx, 1);
3740 bool verbose = arg_get_lit(ctx, 2);
3741 bool noauth = arg_get_lit(ctx, 21);
3743 DesfireContext_t dctx;
3744 int securechann = defaultSecureChannel;
3745 uint32_t id = 0x000000;
3746 DesfireISOSelectWay selectway = ISW6bAID;
3747 int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, &securechann, DCMEncrypted, &id, &selectway);
3748 if (res) {
3749 CLIParserFree(ctx);
3750 return res;
3753 uint8_t data[250] = {0};
3754 uint8_t *settings = &data[1];
3755 size_t datalen = 0;
3757 res = DesfireCreateFileParameters(ctx, 13, 0, 15, 16, 17, 18, 19, 20, data, &datalen);
3758 if (res) {
3759 CLIParserFree(ctx);
3760 return res;
3763 uint8_t sdata[250] = {0};
3764 int sdatalen = sizeof(sdata);
3765 CLIGetHexWithReturn(ctx, 14, sdata, &sdatalen);
3766 if (res) {
3767 CLIParserFree(ctx);
3768 return PM3_EINVARG;
3771 if (sdatalen > 18) {
3772 PrintAndLogEx(ERR, "File settings length must be less than 18 instead of %d.", sdatalen);
3773 CLIParserFree(ctx);
3774 return PM3_EINVARG;
3777 // rawdata have priority over all the rest methods
3778 if (sdatalen > 0) {
3779 memcpy(settings, sdata, sdatalen);
3780 datalen = 1 + sdatalen;
3783 SetAPDULogging(APDULogging);
3784 CLIParserFree(ctx);
3786 uint8_t fileid = data[0];
3788 res = DesfireSelectAndAuthenticateAppW(&dctx, securechann, selectway, id, noauth, verbose);
3789 if (res != PM3_SUCCESS) {
3790 DropField();
3791 PrintAndLogEx(FAILED, "Select or authentication %s " _RED_("failed") ". Result [%d] %s", DesfireWayIDStr(selectway, id), res, DesfireAuthErrorToStr(res));
3792 return res;
3795 uint8_t buf[APDU_RES_LEN] = {0};
3796 size_t buflen = 0;
3798 // check current file settings
3799 DesfireCommunicationMode commMode = dctx.commMode;
3800 DesfireSetCommMode(&dctx, DCMMACed);
3801 res = DesfireGetFileSettings(&dctx, fileid, buf, &buflen);
3802 if (res == PM3_SUCCESS && buflen > 5) {
3803 uint8_t chright = 0;
3804 DesfireDecodeFileAcessMode(&buf[2], NULL, NULL, NULL, &chright) ;
3805 if (verbose)
3806 PrintAndLogEx(INFO, "Current access right for change file settings: %s", GetDesfireAccessRightStr(chright));
3808 if (chright == 0x0f)
3809 PrintAndLogEx(WARNING, "Change file settings disabled");
3811 if (chright == 0x0e && (!(commMode == DCMPlain || commMode == DCMMACed || noauth)))
3812 PrintAndLogEx(WARNING, "File settings have free access for change. Change command must be sent via plain communications mode or without authentication (--no-auth option)");
3814 if (chright < 0x0e && dctx.keyNum != chright)
3815 PrintAndLogEx(WARNING, "File settings must be changed with auth key=0x%02x but current auth with key 0x%02x", chright, dctx.keyNum);
3817 if (chright < 0x0e && commMode != DCMEncrypted)
3818 PrintAndLogEx(WARNING, "File settings must be changed via encryted (full) communication mode");
3820 DesfireSetCommMode(&dctx, commMode);
3822 // print the new file settings
3823 if (verbose)
3824 PrintAndLogEx(INFO, "%s file %02x settings[%zu]: %s", DesfireWayIDStr(selectway, id), fileid, datalen - 1, sprint_hex(settings, datalen - 1));
3826 DesfirePrintSetFileSettings(settings, datalen - 1);
3828 // set file settings
3829 data[0] = fileid;
3830 res = DesfireChangeFileSettings(&dctx, data, datalen);
3831 if (res != PM3_SUCCESS) {
3832 PrintAndLogEx(ERR, "Desfire ChangeFileSettings command " _RED_("error") ". Result: %d", res);
3833 DropField();
3834 return PM3_ESOFT;
3837 PrintAndLogEx(SUCCESS, "File settings changed " _GREEN_("successfully"));
3839 DropField();
3840 return PM3_SUCCESS;
3843 static int CmdHF14ADesCreateFile(const char *Cmd) {
3844 CLIParserContext *ctx;
3845 CLIParserInit(&ctx, "hf mfdes createfile",
3846 "Create Standard/Backup file in the application. Application master key needs to be provided or flag --no-auth set (depend on application settings).",
3847 "--rawtype/--rawdata have priority over the other settings. and with these parameters you can create any file. file id comes from parameters, all the rest data must be in the --rawdata parameter\n"
3848 "--rawrights have priority over the separate rights settings.\n"
3849 "Key/mode/etc of the authentication depends on application settings\n"
3850 "hf mfdes createfile --aid 123456 --fid 01 --isofid 0001 --size 000010 -> create file with iso id. Authentication with defaults from `default` command\n"
3851 "hf mfdes createfile --aid 123456 --fid 01 --rawtype 01 --rawdata 000100EEEE000100 -> create file via sending rawdata to the card. Can be used to create any type of file. Authentication with defaults from `default` command\n"
3852 "hf mfdes createfile --aid 123456 --fid 01 --amode plain --rrights free --wrights free --rwrights free --chrights key0 -> create file app=123456, file=01 and mentioned rights with defaults from `default` command\n"
3853 "hf mfdes createfile -n 0 -t des -k 0000000000000000 --kdf none --aid 123456 --fid 01 --rawtype 00 --rawdata 00EEEE000100 -> execute with default factory setup");
3855 void *argtable[] = {
3856 arg_param_begin,
3857 arg_lit0("a", "apdu", "Show APDU requests and responses"),
3858 arg_lit0("v", "verbose", "Verbose output"),
3859 arg_int0("n", "keyno", "<dec>", "Key number"),
3860 arg_str0("t", "algo", "<DES|2TDEA|3TDEA|AES>", "Crypt algo"),
3861 arg_str0("k", "key", "<hex>", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"),
3862 arg_str0(NULL, "kdf", "<none|AN10922|gallagher>", "Key Derivation Function (KDF)"),
3863 arg_str0("i", "kdfi", "<hex>", "KDF input (1-31 hex bytes)"),
3864 arg_str0("m", "cmode", "<plain|mac|encrypt>", "Communicaton mode"),
3865 arg_str0("c", "ccset", "<native|niso|iso>", "Communicaton command set"),
3866 arg_str0(NULL, "schann", "<d40|ev1|ev2|lrp>", "Secure channel"),
3867 arg_str0(NULL, "aid", "<hex>", "Application ID (3 hex bytes, big endian)"),
3868 arg_str0(NULL, "fid", "<hex>", "File ID (1 hex byte)"),
3869 arg_str0(NULL, "isofid", "<hex>", "ISO File ID (2 hex bytes)"),
3870 arg_str0(NULL, "rawtype", "<hex>", "Raw file type (1 hex byte)"),
3871 arg_str0(NULL, "rawdata", "<hex>", "Raw file settings (hex > 5 bytes)"),
3872 arg_str0(NULL, "amode", "<plain|mac|encrypt>", "File access mode"),
3873 arg_str0(NULL, "rawrights", "<hex>", "Access rights for file (2 hex bytes) R/W/RW/Chg, 0x0 - 0xD Key, 0xE Free, 0xF Denied"),
3874 arg_str0(NULL, "rrights", "<key0..key13|free|deny>", "Read file access mode: the specified key, free, deny"),
3875 arg_str0(NULL, "wrights", "<key0..key13|free|deny>", "Write file access mode: the specified key, free, deny"),
3876 arg_str0(NULL, "rwrights", "<key0..key13|free|deny>", "Read/Write file access mode: the specified key, free, deny"),
3877 arg_str0(NULL, "chrights", "<key0..key13|free|deny>", "Change file settings access mode: the specified key, free, deny"),
3878 arg_lit0(NULL, "no-auth", "Execute without authentication"),
3879 arg_str0(NULL, "size", "<hex>", "File size (3 hex bytes, big endian)"),
3880 arg_lit0(NULL, "backup", "Create backupfile instead of standard file"),
3881 arg_param_end
3883 CLIExecWithReturn(ctx, Cmd, argtable, false);
3885 bool APDULogging = arg_get_lit(ctx, 1);
3886 bool verbose = arg_get_lit(ctx, 2);
3887 bool noauth = arg_get_lit(ctx, 22);
3888 bool backup = arg_get_lit(ctx, 24);
3889 uint8_t filetype = (backup) ? 0x01 : 0x00; // backup / standard data file
3891 DesfireContext_t dctx;
3892 int securechann = defaultSecureChannel;
3893 uint32_t appid = 0x000000;
3894 int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, DCMMACed, &appid, NULL);
3895 if (res) {
3896 CLIParserFree(ctx);
3897 return res;
3900 if (appid == 0x000000) {
3901 PrintAndLogEx(ERR, "Can't create files at card level.");
3902 CLIParserFree(ctx);
3903 return PM3_EINVARG;
3906 uint8_t data[250] = {0};
3907 size_t datalen = 0;
3909 res = DesfireCreateFileParameters(ctx, 12, 13, 16, 17, 18, 19, 20, 21, data, &datalen);
3910 if (res) {
3911 CLIParserFree(ctx);
3912 return res;
3915 uint32_t rawftype = 0x00;
3916 bool useraw = false;
3917 if (CLIGetUint32Hex(ctx, 14, 0x00, &rawftype, &useraw, 1, "Raw file type must have 1 byte length")) {
3918 CLIParserFree(ctx);
3919 return PM3_EINVARG;
3922 uint8_t sdata[250] = {0};
3923 int sdatalen = sizeof(sdata);
3924 CLIGetHexWithReturn(ctx, 15, sdata, &sdatalen);
3925 if (sdatalen > 20) {
3926 PrintAndLogEx(ERR, "Rawdata length must be less than 20 bytes instead of %d.", sdatalen);
3927 CLIParserFree(ctx);
3928 return PM3_EINVARG;
3931 if (useraw && sdatalen > 0) {
3932 filetype = rawftype;
3933 memcpy(&data[1], sdata, sdatalen);
3934 datalen = 1 + sdatalen;
3935 } else {
3936 useraw = false;
3939 if (useraw == false) {
3940 uint32_t filesize = 0;
3941 if (CLIGetUint32Hex(ctx, 23, 0, &filesize, NULL, 3, "File size must have 3 bytes length")) {
3942 CLIParserFree(ctx);
3943 return PM3_EINVARG;
3946 if (filesize == 0) {
3947 PrintAndLogEx(ERR, "File size must be greater than 0");
3948 CLIParserFree(ctx);
3949 return PM3_EINVARG;
3952 Uint3byteToMemLe(&data[datalen], filesize);
3953 datalen += 3;
3956 SetAPDULogging(APDULogging);
3957 CLIParserFree(ctx);
3959 res = DesfireSelectAndAuthenticateEx(&dctx, securechann, appid, noauth, verbose);
3960 if (res != PM3_SUCCESS) {
3961 DropField();
3962 return res;
3965 if (verbose)
3966 PrintAndLogEx(INFO, "App: %06x. File num: 0x%02x type: 0x%02x data[%zu]: %s", appid, data[0], filetype, datalen, sprint_hex(data, datalen));
3967 DesfirePrintCreateFileSettings(filetype, data, datalen);
3970 res = DesfireCreateFile(&dctx, filetype, data, datalen, useraw == false); // check length only if we nont use raw mode
3971 if (res != PM3_SUCCESS) {
3972 PrintAndLogEx(ERR, "Desfire CreateFile command " _RED_("error") ". Result: %d", res);
3973 DropField();
3974 return PM3_ESOFT;
3977 PrintAndLogEx(SUCCESS, "%s file %02x in the app %06x created " _GREEN_("successfully"), GetDesfireFileType(filetype), data[0], appid);
3979 DropField();
3980 return PM3_SUCCESS;
3983 static int CmdHF14ADesCreateValueFile(const char *Cmd) {
3984 CLIParserContext *ctx;
3985 CLIParserInit(&ctx, "hf mfdes createvaluefile",
3986 "Create Value file in the application. Application master key needs to be provided or flag --no-auth set (depend on application settings).",
3987 "--rawrights have priority over the separate rights settings.\n"
3988 "Key/mode/etc of the authentication depends on application settings\n"
3989 "hf mfdes createvaluefile --aid 123456 --fid 01 --lower 00000010 --upper 00010000 --value 00000100 -> create file with parameters. Rights from default. Authentication with defaults from `default` command\n"
3990 "hf mfdes createvaluefile --aid 123456 --fid 01 --amode plain --rrights free --wrights free --rwrights free --chrights key0 -> create file app=123456, file=01 and mentioned rights with defaults from `default` command\n"
3991 "hf mfdes createvaluefile -n 0 -t des -k 0000000000000000 --kdf none --aid 123456 --fid 01 -> execute with default factory setup");
3993 void *argtable[] = {
3994 arg_param_begin,
3995 arg_lit0("a", "apdu", "Show APDU requests and responses"),
3996 arg_lit0("v", "verbose", "Verbose output"),
3997 arg_int0("n", "keyno", "<dec>", "Key number"),
3998 arg_str0("t", "algo", "<DES|2TDEA|3TDEA|AES>", "Crypt algo"),
3999 arg_str0("k", "key", "<hex>", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"),
4000 arg_str0(NULL, "kdf", "<none|AN10922|gallagher>", "Key Derivation Function (KDF)"),
4001 arg_str0("i", "kdfi", "<hex>", "KDF input (1-31 hex bytes)"),
4002 arg_str0("m", "cmode", "<plain|mac|encrypt>", "Communicaton mode"),
4003 arg_str0("c", "ccset", "<native|niso|iso>", "Communicaton command set"),
4004 arg_str0(NULL, "schann", "<d40|ev1|ev2|lrp>", "Secure channel"),
4005 arg_str0(NULL, "aid", "<hex>", "Application ID (3 hex bytes, big endian)"),
4006 arg_str0(NULL, "fid", "<hex>", "File ID (1 hex byte)"),
4007 arg_str0(NULL, "amode", "<plain|mac|encrypt>", "File access mode"),
4008 arg_str0(NULL, "rawrights", "<hex>", "Access rights for file (2 hex bytes) R/W/RW/Chg, 0x0 - 0xD Key, 0xE Free, 0xF Denied"),
4009 arg_str0(NULL, "rrights", "<key0..key13|free|deny>", "Read file access mode: the specified key, free, deny"),
4010 arg_str0(NULL, "wrights", "<key0..key13|free|deny>", "Write file access mode: the specified key, free, deny"),
4011 arg_str0(NULL, "rwrights", "<key0..key13|free|deny>", "Read/Write file access mode: the specified key, free, deny"),
4012 arg_str0(NULL, "chrights", "<key0..key13|free|deny>", "Change file settings access mode: the specified key, free, deny"),
4013 arg_lit0(NULL, "no-auth", "Execute without authentication"),
4014 arg_str0(NULL, "lower", "<hex>", "Lower limit (4 hex bytes, big endian)"),
4015 arg_str0(NULL, "upper", "<hex>", "Upper limit (4 hex bytes, big endian)"),
4016 arg_str0(NULL, "value", "<hex>", "Value (4 hex bytes, big endian)"),
4017 arg_int0(NULL, "lcredit", "<dec>", "Limited Credit enabled (Bit 0 = Limited Credit, 1 = FreeValue)"),
4018 arg_param_end
4020 CLIExecWithReturn(ctx, Cmd, argtable, false);
4022 bool APDULogging = arg_get_lit(ctx, 1);
4023 bool verbose = arg_get_lit(ctx, 2);
4024 bool noauth = arg_get_lit(ctx, 19);
4026 uint8_t filetype = 0x02; // value file
4028 DesfireContext_t dctx;
4029 int securechann = defaultSecureChannel;
4030 uint32_t appid = 0x000000;
4031 int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, DCMMACed, &appid, NULL);
4032 if (res) {
4033 CLIParserFree(ctx);
4034 return res;
4037 if (appid == 0x000000) {
4038 PrintAndLogEx(ERR, "Can't create files at card level.");
4039 CLIParserFree(ctx);
4040 return PM3_EINVARG;
4043 uint8_t data[250] = {0};
4044 size_t datalen = 0;
4046 res = DesfireCreateFileParameters(ctx, 12, 0, 13, 14, 15, 16, 17, 18, data, &datalen);
4047 if (res) {
4048 CLIParserFree(ctx);
4049 return res;
4052 uint32_t lowerlimit = 0;
4053 if (CLIGetUint32Hex(ctx, 20, 0, &lowerlimit, NULL, 4, "Lower limit value must have 4 bytes length")) {
4054 CLIParserFree(ctx);
4055 return PM3_EINVARG;
4058 uint32_t upperlimit = 0;
4059 if (CLIGetUint32Hex(ctx, 21, 0, &upperlimit, NULL, 4, "Upper limit value must have 4 bytes length")) {
4060 CLIParserFree(ctx);
4061 return PM3_EINVARG;
4064 uint32_t value = 0;
4065 if (CLIGetUint32Hex(ctx, 22, 0, &value, NULL, 4, "Value must have 4 bytes length")) {
4066 CLIParserFree(ctx);
4067 return PM3_EINVARG;
4070 uint32_t lcredit = arg_get_int_def(ctx, 23, 0);
4072 SetAPDULogging(APDULogging);
4073 CLIParserFree(ctx);
4076 Uint4byteToMemLe(&data[datalen], lowerlimit);
4077 datalen += 4;
4078 Uint4byteToMemLe(&data[datalen], upperlimit);
4079 datalen += 4;
4080 Uint4byteToMemLe(&data[datalen], value);
4081 datalen += 4;
4082 data[datalen] = lcredit;
4083 datalen++;
4085 res = DesfireSelectAndAuthenticateEx(&dctx, securechann, appid, noauth, verbose);
4086 if (res != PM3_SUCCESS) {
4087 DropField();
4088 return res;
4091 if (verbose)
4092 PrintAndLogEx(INFO, "App: %06x. File num: 0x%02x type: 0x%02x data[%zu]: %s", appid, data[0], filetype, datalen, sprint_hex(data, datalen));
4093 DesfirePrintCreateFileSettings(filetype, data, datalen);
4096 res = DesfireCreateFile(&dctx, filetype, data, datalen, true);
4097 if (res != PM3_SUCCESS) {
4098 PrintAndLogEx(ERR, "Desfire CreateFile command " _RED_("error") ". Result: %d", res);
4099 DropField();
4100 return PM3_ESOFT;
4103 PrintAndLogEx(SUCCESS, "Value file %02x in the app %06x created " _GREEN_("successfully"), data[0], appid);
4105 DropField();
4106 return PM3_SUCCESS;
4109 static int CmdHF14ADesCreateRecordFile(const char *Cmd) {
4110 CLIParserContext *ctx;
4111 CLIParserInit(&ctx, "hf mfdes createrecordfile",
4112 "Create Linear/Cyclic Record file in the application. Application master key needs to be provided or flag --no-auth set (depend on application settings).",
4113 "--rawrights have priority over the separate rights settings.\n"
4114 "Key/mode/etc of the authentication depends on application settings\n"
4115 "hf mfdes createrecordfile --aid 123456 --fid 01 --size 000010 --maxrecord 000010 --cyclic -> create cyclic record file with parameters. Rights from default. Authentication with defaults from `default` command\n"
4116 "hf mfdes createrecordfile --aid 123456 --fid 01 --amode plain --rrights free --wrights free --rwrights free --chrights key0 --size 000010 --maxrecord 000010 -> create linear record file app=123456, file=01 and mentioned rights with defaults from `default` command\n"
4117 "hf mfdes createrecordfile -n 0 -t des -k 0000000000000000 --kdf none --aid 123456 --fid 01 --size 000010 --maxrecord 000010 -> execute with default factory setup");
4119 void *argtable[] = {
4120 arg_param_begin,
4121 arg_lit0("a", "apdu", "Show APDU requests and responses"),
4122 arg_lit0("v", "verbose", "Verbose output"),
4123 arg_int0("n", "keyno", "<dec>", "Key number"),
4124 arg_str0("t", "algo", "<DES|2TDEA|3TDEA|AES>", "Crypt algo"),
4125 arg_str0("k", "key", "<hex>", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"),
4126 arg_str0(NULL, "kdf", "<none|AN10922|gallagher>", "Key Derivation Function (KDF)"),
4127 arg_str0("i", "kdfi", "<hex>", "KDF input (1-31 hex bytes)"),
4128 arg_str0("m", "cmode", "<plain|mac|encrypt>", "Communicaton mode"),
4129 arg_str0("c", "ccset", "<native|niso|iso>", "Communicaton command set"),
4130 arg_str0(NULL, "schann", "<d40|ev1|ev2|lrp>", "Secure channel"),
4131 arg_str0(NULL, "aid", "<hex>", "Application ID (3 hex bytes, big endian)"),
4132 arg_str0(NULL, "fid", "<hex>", "File ID (1 hex byte)"),
4133 arg_str0(NULL, "isofid", "<hex>", "ISO File ID (2 hex bytes)"),
4134 arg_str0(NULL, "amode", "<plain|mac|encrypt>", "File access mode"),
4135 arg_str0(NULL, "rawrights", "<hex>", "Access rights for file (2 hex bytes) R/W/RW/Chg, 0x0 - 0xD Key, 0xE Free, 0xF Denied"),
4136 arg_str0(NULL, "rrights", "<key0..key13|free|deny>", "Read file access mode: the specified key, free, deny"),
4137 arg_str0(NULL, "wrights", "<key0..key13|free|deny>", "Write file access mode: the specified key, free, deny"),
4138 arg_str0(NULL, "rwrights", "<key0..key13|free|deny>", "Read/Write file access mode: the specified key, free, deny"),
4139 arg_str0(NULL, "chrights", "<key0..key13|free|deny>", "Change file settings access mode: the specified key, free, deny"),
4140 arg_lit0(NULL, "no-auth", "Execute without authentication"),
4141 arg_str0(NULL, "size", "<hex>", "Record size (3 hex bytes, big endian, 000001 to FFFFFF)"),
4142 arg_str0(NULL, "maxrecord", "<hex>", "Max. Number of Records (3 hex bytes, big endian)"),
4143 arg_lit0(NULL, "cyclic", "Create cyclic record file instead of linear record file"),
4144 arg_param_end
4146 CLIExecWithReturn(ctx, Cmd, argtable, false);
4148 bool APDULogging = arg_get_lit(ctx, 1);
4149 bool verbose = arg_get_lit(ctx, 2);
4150 bool noauth = arg_get_lit(ctx, 20);
4152 bool cyclic = arg_get_lit(ctx, 23);
4153 uint8_t filetype = (cyclic) ? 0x04 : 0x03; // linear(03) / cyclic(04) record file
4155 DesfireContext_t dctx;
4156 int securechann = defaultSecureChannel;
4157 uint32_t appid = 0x000000;
4158 int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, DCMMACed, &appid, NULL);
4159 if (res) {
4160 CLIParserFree(ctx);
4161 return res;
4164 if (appid == 0x000000) {
4165 PrintAndLogEx(ERR, "Can't create files at card level.");
4166 CLIParserFree(ctx);
4167 return PM3_EINVARG;
4170 uint8_t data[250] = {0};
4171 size_t datalen = 0;
4173 res = DesfireCreateFileParameters(ctx, 12, 13, 14, 15, 16, 17, 18, 19, data, &datalen);
4174 if (res) {
4175 CLIParserFree(ctx);
4176 return res;
4179 uint32_t size = 0;
4180 if (CLIGetUint32Hex(ctx, 21, 0, &size, NULL, 3, "Record size must have 3 bytes length")) {
4181 CLIParserFree(ctx);
4182 return PM3_EINVARG;
4185 uint32_t maxrecord = 0;
4186 if (CLIGetUint32Hex(ctx, 22, 0, &maxrecord, NULL, 3, "Max number of records must have 3 bytes length")) {
4187 CLIParserFree(ctx);
4188 return PM3_EINVARG;
4191 SetAPDULogging(APDULogging);
4192 CLIParserFree(ctx);
4195 Uint3byteToMemLe(&data[datalen], size);
4196 datalen += 3;
4197 Uint3byteToMemLe(&data[datalen], maxrecord);
4198 datalen += 3;
4200 res = DesfireSelectAndAuthenticateEx(&dctx, securechann, appid, noauth, verbose);
4201 if (res != PM3_SUCCESS) {
4202 DropField();
4203 return res;
4206 if (verbose)
4207 PrintAndLogEx(INFO, "App: %06x. File num: 0x%02x type: 0x%02x data[%zu]: %s", appid, data[0], filetype, datalen, sprint_hex(data, datalen));
4208 DesfirePrintCreateFileSettings(filetype, data, datalen);
4211 res = DesfireCreateFile(&dctx, filetype, data, datalen, true);
4212 if (res != PM3_SUCCESS) {
4213 PrintAndLogEx(ERR, "Desfire CreateFile command " _RED_("error") ". Result: %d", res);
4214 DropField();
4215 return PM3_ESOFT;
4218 PrintAndLogEx(SUCCESS, "%s file %02x in the app %06x created " _GREEN_("successfully"), GetDesfireFileType(filetype), data[0], appid);
4220 DropField();
4221 return PM3_SUCCESS;
4224 static int CmdHF14ADesCreateTrMACFile(const char *Cmd) {
4225 CLIParserContext *ctx;
4226 CLIParserInit(&ctx, "hf mfdes createmacfile",
4227 "Create Transaction MAC file in the application. Application master key needs to be provided or flag --no-auth set (depend on application settings).",
4228 "--rawrights have priority over the separate rights settings.\n"
4229 "Key/mode/etc of the authentication depends on application settings\n"
4230 "Write right should be always 0xF. Read-write right should be 0xF if you not need to submit CommitReaderID command each time transaction starts\n"
4231 "\n"
4232 "hf mfdes createmacfile --aid 123456 --fid 01 --rawrights 0FF0 --mackey 00112233445566778899aabbccddeeff --mackeyver 01 -> create transaction mac file with parameters. Rights from default. Authentication with defaults from `default` command\n"
4233 "hf mfdes createmacfile --aid 123456 --fid 01 --amode plain --rrights free --wrights deny --rwrights free --chrights key0 --mackey 00112233445566778899aabbccddeeff -> create file app=123456, file=01, with key, and mentioned rights with defaults from `default` command\n"
4234 "hf mfdes createmacfile -n 0 -t des -k 0000000000000000 --kdf none --aid 123456 --fid 01 -> execute with default factory setup. key and keyver == 0x00..00\n"
4235 "hf mfdes createmacfile --isoid df01 --fid 0f --schann lrp -t aes --rawrights 0FF0 --mackey 00112233445566778899aabbccddeeff --mackeyver 01 -> create transaction mac file via lrp channel\n"
4236 "hf mfdes createmacfile --isoid df01 --fid 0f --schann lrp -t aes --rawrights 0F10 --mackey 00112233445566778899aabbccddeeff --mackeyver 01 -> create transaction mac file via lrp channel with CommitReaderID command enable");
4238 void *argtable[] = {
4239 arg_param_begin,
4240 arg_lit0("a", "apdu", "Show APDU requests and responses"),
4241 arg_lit0("v", "verbose", "Verbose output"),
4242 arg_int0("n", "keyno", "<dec>", "Key number"),
4243 arg_str0("t", "algo", "<DES|2TDEA|3TDEA|AES>", "Crypt algo"),
4244 arg_str0("k", "key", "<hex>", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"),
4245 arg_str0(NULL, "kdf", "<none|AN10922|gallagher>", "Key Derivation Function (KDF)"),
4246 arg_str0("i", "kdfi", "<hex>", "KDF input (1-31 hex bytes)"),
4247 arg_str0("m", "cmode", "<plain|mac|encrypt>", "Communicaton mode"),
4248 arg_str0("c", "ccset", "<native|niso|iso>", "Communicaton command set"),
4249 arg_str0(NULL, "schann", "<d40|ev1|ev2|lrp>", "Secure channel"),
4250 arg_str0(NULL, "aid", "<hex>", "Application ID (3 hex bytes, big endian)"),
4251 arg_str0(NULL, "isoid", "<hex>", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian)"),
4252 arg_str0(NULL, "fid", "<hex>", "File ID (1 hex byte)"),
4253 arg_str0(NULL, "amode", "<plain|mac|encrypt>", "File access mode"),
4254 arg_str0(NULL, "rawrights", "<hex>", "Access rights for file (2 hex bytes) R/W/RW/Chg, 0x0 - 0xD Key, 0xE Free, 0xF Denied"),
4255 arg_str0(NULL, "rrights", "<key0..key13|free|deny>", "Read file access mode: the specified key, free, deny"),
4256 arg_str0(NULL, "wrights", "<key0..key13|free|deny>", "Write file access mode: the specified key, free, deny"),
4257 arg_str0(NULL, "rwrights", "<key0..key13|free|deny>", "Read/Write file access mode: the specified key, free, deny"),
4258 arg_str0(NULL, "chrights", "<key0..key13|free|deny>", "Change file settings access mode: the specified key, free, deny"),
4259 arg_lit0(NULL, "no-auth", "Execute without authentication"),
4260 arg_str0(NULL, "mackey", "<hex>", "AES-128 key for MAC (16 hex bytes, big endian). (def: all zeros)"),
4261 arg_str0(NULL, "mackeyver", "<hex>", "AES key version for MAC (1 hex byte). (def: 0x0)"),
4262 arg_param_end
4264 CLIExecWithReturn(ctx, Cmd, argtable, false);
4266 bool APDULogging = arg_get_lit(ctx, 1);
4267 bool verbose = arg_get_lit(ctx, 2);
4268 bool noauth = arg_get_lit(ctx, 20);
4270 uint8_t filetype = 0x05; // transaction mac file
4272 DesfireContext_t dctx;
4273 int securechann = defaultSecureChannel;
4274 uint32_t id = 0x000000;
4275 DesfireISOSelectWay selectway = ISW6bAID;
4276 int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, &securechann, DCMEncrypted, &id, &selectway);
4277 if (res) {
4278 CLIParserFree(ctx);
4279 return res;
4282 if (DesfireMFSelected(selectway, id)) {
4283 PrintAndLogEx(ERR, "Can't create files at card level.");
4284 CLIParserFree(ctx);
4285 return PM3_EINVARG;
4288 uint8_t data[250] = {0};
4289 size_t datalen = 0;
4291 res = DesfireCreateFileParameters(ctx, 13, 0, 14, 15, 16, 17, 18, 19, data, &datalen);
4292 if (res) {
4293 CLIParserFree(ctx);
4294 return res;
4297 uint8_t sdata[250] = {0};
4298 int sdatalen = sizeof(sdata);
4299 CLIGetHexWithReturn(ctx, 21, sdata, &sdatalen);
4300 if (sdatalen != 0 && sdatalen != 16) {
4301 PrintAndLogEx(ERR, "AES-128 key must be 16 bytes instead of %d.", sdatalen);
4302 CLIParserFree(ctx);
4303 return PM3_EINVARG;
4306 uint32_t keyver = 0x00;
4307 if (CLIGetUint32Hex(ctx, 22, 0x00, &keyver, NULL, 1, "Key version must have 1 bytes length")) {
4308 CLIParserFree(ctx);
4309 return PM3_EINVARG;
4312 SetAPDULogging(APDULogging);
4313 CLIParserFree(ctx);
4315 data[datalen] = 0x02; // AES key
4316 datalen++;
4317 if (sdatalen > 0)
4318 memcpy(&data[datalen], sdata, sdatalen);
4319 datalen += 16;
4320 data[datalen] = keyver & 0xff;
4321 datalen++;
4323 res = DesfireSelectAndAuthenticateAppW(&dctx, securechann, selectway, id, noauth, verbose);
4324 if (res != PM3_SUCCESS) {
4325 DropField();
4326 PrintAndLogEx(FAILED, "Select or authentication %s " _RED_("failed") ". Result [%d] %s", DesfireWayIDStr(selectway, id), res, DesfireAuthErrorToStr(res));
4327 return res;
4330 if (verbose)
4331 PrintAndLogEx(INFO, "%s. File num: 0x%02x type: 0x%02x data[%zu]: %s", DesfireWayIDStr(selectway, id), data[0], filetype, datalen, sprint_hex(data, datalen));
4333 DesfirePrintCreateFileSettings(filetype, data, datalen);
4335 res = DesfireCreateFile(&dctx, filetype, data, datalen, true);
4336 if (res != PM3_SUCCESS) {
4337 PrintAndLogEx(ERR, "Desfire CreateFile command " _RED_("error") ". Result: %d", res);
4338 DropField();
4339 return PM3_ESOFT;
4342 PrintAndLogEx(SUCCESS, "%s file %02x in the %s created " _GREEN_("successfully"), GetDesfireFileType(filetype), data[0], DesfireWayIDStr(selectway, id));
4344 DropField();
4345 return PM3_SUCCESS;
4348 static int CmdHF14ADesDeleteFile(const char *Cmd) {
4349 CLIParserContext *ctx;
4350 CLIParserInit(&ctx, "hf mfdes deletefile",
4351 "Delete file from application. Master key needs to be provided or flag --no-auth set (depend on cards settings).",
4352 "hf mfdes deletefile --aid 123456 --fid 01 -> delete file for: app=123456, file=01 with defaults from `default` command\n"
4353 "hf mfdes deletefile --isoid df01 --fid 0f --schann lrp -t aes -> delete file for lrp channel");
4355 void *argtable[] = {
4356 arg_param_begin,
4357 arg_lit0("a", "apdu", "Show APDU requests and responses"),
4358 arg_lit0("v", "verbose", "Verbose output"),
4359 arg_int0("n", "keyno", "<dec>", "Key number"),
4360 arg_str0("t", "algo", "<DES|2TDEA|3TDEA|AES>", "Crypt algo"),
4361 arg_str0("k", "key", "<hex>", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"),
4362 arg_str0(NULL, "kdf", "<none|AN10922|gallagher>", "Key Derivation Function (KDF)"),
4363 arg_str0("i", "kdfi", "<hex>", "KDF input (1-31 hex bytes)"),
4364 arg_str0("m", "cmode", "<plain|mac|encrypt>", "Communicaton mode"),
4365 arg_str0("c", "ccset", "<native|niso|iso>", "Communicaton command set"),
4366 arg_str0(NULL, "schann", "<d40|ev1|ev2|lrp>", "Secure channel"),
4367 arg_str0(NULL, "aid", "<hex>", "Application ID (3 hex bytes, big endian)"),
4368 arg_str0(NULL, "isoid", "<hex>", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian)"),
4369 arg_str0(NULL, "fid", "<hex>", "File ID (1 hex byte)"),
4370 arg_lit0(NULL, "no-auth", "Execute without authentication"),
4371 arg_param_end
4373 CLIExecWithReturn(ctx, Cmd, argtable, false);
4375 bool APDULogging = arg_get_lit(ctx, 1);
4376 bool verbose = arg_get_lit(ctx, 2);
4377 bool noauth = arg_get_lit(ctx, 14);
4379 DesfireContext_t dctx;
4380 int securechann = defaultSecureChannel;
4381 uint32_t id = 0x000000;
4382 DesfireISOSelectWay selectway = ISW6bAID;
4383 int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, &securechann, DCMMACed, &id, &selectway);
4384 if (res) {
4385 CLIParserFree(ctx);
4386 return res;
4389 uint32_t fnum = 1;
4390 if (CLIGetUint32Hex(ctx, 13, 1, &fnum, NULL, 1, "File ID must have 1 byte length")) {
4391 CLIParserFree(ctx);
4392 return PM3_EINVARG;
4395 SetAPDULogging(APDULogging);
4396 CLIParserFree(ctx);
4398 if (fnum > 0x1F) {
4399 PrintAndLogEx(ERR, "File number range is invalid (exp 0x00 - 0x1f), got 0x%02x", fnum);
4400 return PM3_EINVARG;
4403 res = DesfireSelectAndAuthenticateAppW(&dctx, securechann, selectway, id, noauth, verbose);
4404 if (res != PM3_SUCCESS) {
4405 DropField();
4406 PrintAndLogEx(FAILED, "Select or authentication %s " _RED_("failed") ". Result [%d] %s", DesfireWayIDStr(selectway, id), res, DesfireAuthErrorToStr(res));
4407 return res;
4410 res = DesfireDeleteFile(&dctx, fnum);
4411 if (res != PM3_SUCCESS) {
4412 PrintAndLogEx(ERR, "Desfire DeleteFile command " _RED_("error") ". Result: %d", res);
4413 DropField();
4414 return PM3_ESOFT;
4417 PrintAndLogEx(SUCCESS, "File %02x in the %s deleted " _GREEN_("successfully"), fnum, DesfireWayIDStr(selectway, id));
4419 DropField();
4420 return PM3_SUCCESS;
4423 static int CmdHF14ADesValueOperations(const char *Cmd) {
4424 CLIParserContext *ctx;
4425 CLIParserInit(&ctx, "hf mfdes value",
4426 "Get File Settings from file from application. Master key needs to be provided or flag --no-auth set (depend on cards settings).",
4427 "hf mfdes value --aid 123456 --fid 01 -> get value app=123456, file=01 with defaults from `default` command\n"
4428 "hf mfdes value --aid 123456 --fid 01 --op credit -d 00000001 -> credit value app=123456, file=01 with defaults from `default` command\n"
4429 "hf mfdes value -n 0 -t des -k 0000000000000000 --kdf none --aid 123456 --fid 01 -> get value with default factory setup\n"
4430 "hf mfdes val --isoid df01 --fid 03 --schann lrp -t aes -n 1 --op credit --d 00000001 -m encrypt -> credit value in the lrp encrypted mode\n"
4431 "hf mfdes val --isoid df01 --fid 03 --schann lrp -t aes -n 1 --op get -m plain -> get value in plain (nevertheless of mode) works for desfire light (look SetConfiguration option 0x09)");
4433 void *argtable[] = {
4434 arg_param_begin,
4435 arg_lit0("a", "apdu", "Show APDU requests and responses"),
4436 arg_lit0("v", "verbose", "Verbose output"),
4437 arg_int0("n", "keyno", "<dec>", "Key number"),
4438 arg_str0("t", "algo", "<DES|2TDEA|3TDEA|AES>", "Crypt algo"),
4439 arg_str0("k", "key", "<hex>", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"),
4440 arg_str0(NULL, "kdf", "<none|AN10922|gallagher>", "Key Derivation Function (KDF)"),
4441 arg_str0("i", "kdfi", "<hex>", "KDF input (1-31 hex bytes)"),
4442 arg_str0("m", "cmode", "<plain|mac|encrypt>", "Communicaton mode"),
4443 arg_str0("c", "ccset", "<native|niso|iso>", "Communicaton command set"),
4444 arg_str0(NULL, "schann", "<d40|ev1|ev2|lrp>", "Secure channel"),
4445 arg_str0(NULL, "aid", "<hex>", "Application ID (3 hex bytes, big endian)"),
4446 arg_str0(NULL, "isoid", "<hex>", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian)"),
4447 arg_str0(NULL, "fid", "<hex>", "File ID (1 hex byte)"),
4448 arg_str0("o", "op", "<get/credit/limcredit/debit/clear>", "Operation: get(default)/credit/limcredit(limited credit)/debit/clear. Operation clear: get-getopt-debit to min value"),
4449 arg_str0("d", "data", "<hex>", "Value for operation (HEX 4 bytes)"),
4450 arg_lit0(NULL, "no-auth", "Execute without authentication"),
4451 arg_param_end
4453 CLIExecWithReturn(ctx, Cmd, argtable, false);
4455 bool APDULogging = arg_get_lit(ctx, 1);
4456 bool verbose = arg_get_lit(ctx, 2);
4457 bool noauth = arg_get_lit(ctx, 16);
4459 DesfireContext_t dctx;
4460 int securechann = defaultSecureChannel;
4461 uint32_t id = 0x000000;
4462 DesfireISOSelectWay selectway = ISW6bAID;
4463 int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, &securechann, DCMMACed, &id, &selectway);
4464 if (res) {
4465 CLIParserFree(ctx);
4466 return res;
4469 uint32_t fileid = 1;
4470 if (CLIGetUint32Hex(ctx, 13, 1, &fileid, NULL, 1, "File ID must have 1 byte length")) {
4471 CLIParserFree(ctx);
4472 return PM3_EINVARG;
4475 int op = MFDES_GET_VALUE;
4476 if (CLIGetOptionList(arg_get_str(ctx, 14), DesfireValueFileOperOpts, &op)) {
4477 CLIParserFree(ctx);
4478 return PM3_ESOFT;
4481 uint32_t value = 0;
4482 if (CLIGetUint32Hex(ctx, 15, 0, &value, NULL, 4, "Value must have 4 byte length")) {
4483 CLIParserFree(ctx);
4484 return PM3_EINVARG;
4487 SetAPDULogging(APDULogging);
4488 CLIParserFree(ctx);
4490 // iso chaining works in the lrp mode
4491 dctx.isoChaining |= (dctx.secureChannel == DACLRP);
4493 // select
4494 res = DesfireSelectAndAuthenticateAppW(&dctx, securechann, selectway, id, noauth, verbose);
4495 if (res != PM3_SUCCESS) {
4496 DropField();
4497 PrintAndLogEx(FAILED, "Select or authentication ( %s )" _RED_("failed") " Result [%d] %s", DesfireWayIDStr(selectway, id), res, DesfireAuthErrorToStr(res));
4498 return res;
4501 if (verbose)
4502 PrintAndLogEx(INFO, "%s file %02x operation: %s value: 0x%08x", DesfireWayIDStr(selectway, id), fileid, CLIGetOptionListStr(DesfireValueFileOperOpts, op), value);
4504 if (op != 0xff) {
4505 res = DesfireValueFileOperations(&dctx, fileid, op, &value);
4506 if (res != PM3_SUCCESS) {
4507 PrintAndLogEx(ERR, "Desfire ValueFileOperations (0x%02x) command ( " _RED_("error") " ) Result: %d", op, res);
4508 DropField();
4509 return PM3_ESOFT;
4511 if (verbose)
4512 PrintAndLogEx(INFO, "Operation ( %s )" _GREEN_("ok"), CLIGetOptionListStr(DesfireValueFileOperOpts, op));
4514 if (op == MFDES_GET_VALUE) {
4515 PrintAndLogEx(SUCCESS, "Value: " _GREEN_("%d (0x%08x)"), value, value);
4516 } else {
4517 DesfireSetCommMode(&dctx, DCMMACed);
4518 res = DesfireCommitTransaction(&dctx, false, 0);
4519 if (res != PM3_SUCCESS) {
4520 PrintAndLogEx(ERR, "Desfire CommitTransaction command ( " _RED_("error") ") Result: %d", res);
4521 DropField();
4522 return PM3_ESOFT;
4524 if (verbose)
4525 PrintAndLogEx(INFO, "Commit ( " _GREEN_("ok") " )");
4527 PrintAndLogEx(SUCCESS, "Value changed " _GREEN_("successfully"));
4529 } else {
4530 res = DesfireValueFileOperations(&dctx, fileid, MFDES_GET_VALUE, &value);
4531 if (res != PM3_SUCCESS) {
4532 PrintAndLogEx(ERR, "Desfire GetValue command ( " _RED_("error") ") Result: %d", res);
4533 DropField();
4534 return PM3_ESOFT;
4536 if (verbose)
4537 PrintAndLogEx(INFO, "current value: 0x%08x", value);
4539 uint8_t buf[250] = {0};
4540 size_t buflen = 0;
4542 res = DesfireGetFileSettings(&dctx, fileid, buf, &buflen);
4543 if (res != PM3_SUCCESS) {
4544 PrintAndLogEx(ERR, "Desfire GetFileSettings command ( " _RED_("error") " ) Result: %d", res);
4545 DropField();
4546 return PM3_ESOFT;
4549 if (verbose)
4550 PrintAndLogEx(INFO, "file settings[%zu]: %s", buflen, sprint_hex(buf, buflen));
4552 if (buflen < 8 || buf[0] != 0x02) {
4553 PrintAndLogEx(ERR, "Desfire GetFileSettings command returns " _RED_("wrong") " data");
4554 DropField();
4555 return PM3_ESOFT;
4558 uint32_t minvalue = MemLeToUint4byte(&buf[4]);
4559 uint32_t delta = (value > minvalue) ? value - minvalue : 0;
4560 if (verbose) {
4561 PrintAndLogEx(INFO, "minimum value: 0x%08x", minvalue);
4562 PrintAndLogEx(INFO, "delta value : 0x%08x", delta);
4565 if (delta > 0) {
4566 res = DesfireValueFileOperations(&dctx, fileid, MFDES_DEBIT, &delta);
4567 if (res != PM3_SUCCESS) {
4568 PrintAndLogEx(ERR, "Desfire Debit operation ( " _RED_("error") " ) Result: %d", res);
4569 DropField();
4570 return PM3_ESOFT;
4573 if (verbose)
4574 PrintAndLogEx(INFO, "Value debited");
4576 DesfireSetCommMode(&dctx, DCMMACed);
4577 res = DesfireCommitTransaction(&dctx, false, 0);
4578 if (res != PM3_SUCCESS) {
4579 PrintAndLogEx(ERR, "Desfire CommitTransaction command ( " _RED_("error") " ) Result: %d", res);
4580 DropField();
4581 return PM3_ESOFT;
4584 if (verbose)
4585 PrintAndLogEx(INFO, "Transaction committed");
4586 } else {
4587 if (verbose)
4588 PrintAndLogEx(INFO, "Nothing to clear. Value already in the minimum level.");
4591 PrintAndLogEx(SUCCESS, "Value cleared " _GREEN_("successfully"));
4594 DropField();
4595 return PM3_SUCCESS;
4598 static int CmdHF14ADesClearRecordFile(const char *Cmd) {
4599 CLIParserContext *ctx;
4600 CLIParserInit(&ctx, "hf mfdes clearrecfile",
4601 "Clear record file. Master key needs to be provided or flag --no-auth set (depend on cards settings).",
4602 "hf mfdes clearrecfile --aid 123456 --fid 01 -> clear record file for: app=123456, file=01 with defaults from `default` command\n"
4603 "hf mfdes clearrecfile --isoid df01 --fid 01 --schann lrp -t aes -n 3 -> clear record file for lrp channel with key number 3");
4605 void *argtable[] = {
4606 arg_param_begin,
4607 arg_lit0("a", "apdu", "Show APDU requests and responses"),
4608 arg_lit0("v", "verbose", "Verbose output"),
4609 arg_int0("n", "keyno", "<dec>", "Key number"),
4610 arg_str0("t", "algo", "<DES|2TDEA|3TDEA|AES>", "Crypt algo"),
4611 arg_str0("k", "key", "<hex>", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"),
4612 arg_str0(NULL, "kdf", "<none|AN10922|gallagher>", "Key Derivation Function (KDF)"),
4613 arg_str0("i", "kdfi", "<hex>", "KDF input (1-31 hex bytes)"),
4614 arg_str0("m", "cmode", "<plain|mac|encrypt>", "Communicaton mode"),
4615 arg_str0("c", "ccset", "<native|niso|iso>", "Communicaton command set"),
4616 arg_str0(NULL, "schann", "<d40|ev1|ev2|lrp>", "Secure channel"),
4617 arg_str0(NULL, "aid", "<hex>", "Application ID (3 hex bytes, big endian)"),
4618 arg_str0(NULL, "isoid", "<hex>", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian)"),
4619 arg_str0(NULL, "fid", "<hex>", "File ID for clearing (1 hex byte)"),
4620 arg_lit0(NULL, "no-auth", "Execute without authentication"),
4621 arg_param_end
4623 CLIExecWithReturn(ctx, Cmd, argtable, false);
4625 bool APDULogging = arg_get_lit(ctx, 1);
4626 bool verbose = arg_get_lit(ctx, 2);
4627 bool noauth = arg_get_lit(ctx, 14);
4629 DesfireContext_t dctx;
4630 int securechann = defaultSecureChannel;
4631 uint32_t id = 0x000000;
4632 DesfireISOSelectWay selectway = ISW6bAID;
4633 int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, &securechann, DCMMACed, &id, &selectway);
4634 if (res) {
4635 CLIParserFree(ctx);
4636 return res;
4639 uint32_t fnum = 1;
4640 if (CLIGetUint32Hex(ctx, 13, 1, &fnum, NULL, 1, "File ID must have 1 byte length")) {
4641 CLIParserFree(ctx);
4642 return PM3_EINVARG;
4645 SetAPDULogging(APDULogging);
4646 CLIParserFree(ctx);
4648 if (fnum > 0x1F) {
4649 PrintAndLogEx(ERR, "File number range is invalid (exp 0x00 - 0x1f), got 0x%02x", fnum);
4650 return PM3_EINVARG;
4653 res = DesfireSelectAndAuthenticateAppW(&dctx, securechann, selectway, id, noauth, verbose);
4654 if (res != PM3_SUCCESS) {
4655 DropField();
4656 PrintAndLogEx(FAILED, "Select or authentication %s " _RED_("failed") ". Result [%d] %s", DesfireWayIDStr(selectway, id), res, DesfireAuthErrorToStr(res));
4657 return res;
4660 res = DesfireClearRecordFile(&dctx, fnum);
4661 if (res != PM3_SUCCESS) {
4662 PrintAndLogEx(ERR, "Desfire ClearRecordFile command " _RED_("error") ". Result: %d", res);
4663 DropField();
4664 return PM3_ESOFT;
4667 if (verbose)
4668 PrintAndLogEx(INFO, "File cleared");
4670 DesfireSetCommMode(&dctx, DCMMACed);
4671 res = DesfireCommitTransaction(&dctx, false, 0);
4672 if (res != PM3_SUCCESS) {
4673 PrintAndLogEx(ERR, "Desfire CommitTransaction command " _RED_("error") ". Result: %d", res);
4674 DropField();
4675 return PM3_ESOFT;
4678 if (verbose)
4679 PrintAndLogEx(INFO, "Transaction committed");
4681 PrintAndLogEx(SUCCESS, "File %02x in the %s cleared " _GREEN_("successfully"), fnum, DesfireWayIDStr(selectway, id));
4683 DropField();
4684 return PM3_SUCCESS;
4687 static int DesfileReadISOFileAndPrint(DesfireContext_t *dctx,
4688 bool select_current_file, uint8_t fnum,
4689 uint16_t fisoid, int filetype,
4690 uint32_t offset, uint32_t length,
4691 bool noauth, bool verbose) {
4693 if (filetype == RFTAuto) {
4694 PrintAndLogEx(ERR, "ISO mode needs to specify file type");
4695 return PM3_EINVARG;
4698 if (filetype == RFTValue) {
4699 PrintAndLogEx(ERR, "ISO mode can't read Value file type");
4700 return PM3_EINVARG;
4703 if (filetype == RFTMAC) {
4704 PrintAndLogEx(ERR, "ISO mode can't read Transaction MAC file type");
4705 return PM3_EINVARG;
4708 if (select_current_file)
4709 PrintAndLogEx(INFO, "------------------------------- " _CYAN_("File ISO %04x data") " -------------------------------", fisoid);
4710 else
4711 PrintAndLogEx(INFO, "---------------------------- " _CYAN_("File ISO short %02x data") " ----------------------------", fnum);
4713 uint8_t resp[2048] = {0};
4714 size_t resplen = 0;
4715 int res;
4717 if (filetype == RFTData) {
4718 res = DesfireISOReadBinary(dctx, !select_current_file, (select_current_file) ? 0x00 : fnum, offset, length, resp, &resplen);
4719 if (res != PM3_SUCCESS) {
4720 PrintAndLogEx(ERR, "Desfire ISOReadBinary command " _RED_("error") ". Result: %d", res);
4721 DropField();
4722 return PM3_ESOFT;
4725 if (resplen > 0) {
4726 if (select_current_file)
4727 PrintAndLogEx(SUCCESS, "Read %zu bytes from file 0x%04x offset %u", resplen, fisoid, offset);
4728 else
4729 PrintAndLogEx(SUCCESS, "Read %zu bytes from file 0x%02x offset %u", resplen, fnum, offset);
4730 print_buffer_with_offset(resp, resplen, offset, true);
4731 } else {
4732 if (select_current_file)
4733 PrintAndLogEx(SUCCESS, "Read operation returned no data from file %04x", fisoid);
4734 else
4735 PrintAndLogEx(SUCCESS, "Read operation returned no data from file %02x", fnum);
4739 if (filetype == RFTRecord) {
4740 size_t reclen = 0;
4741 res = DesfireISOReadRecords(dctx, offset, false, (select_current_file) ? 0x00 : fnum, 0, resp, &resplen);
4742 if (res != PM3_SUCCESS) {
4743 PrintAndLogEx(ERR, "Desfire ISOReadRecords (one record) command " _RED_("error") ". Result: %d", res);
4744 DropField();
4745 return PM3_ESOFT;
4747 reclen = resplen;
4749 if (verbose)
4750 PrintAndLogEx(INFO, "Record length %zu", reclen);
4752 if (length != 1) {
4753 res = DesfireISOReadRecords(dctx, offset, true, (select_current_file) ? 0x00 : fnum, 0, resp, &resplen);
4754 if (res != PM3_SUCCESS) {
4755 PrintAndLogEx(ERR, "Desfire ISOReadRecords (one record) command " _RED_("error") ". Result: %d", res);
4756 DropField();
4757 return PM3_ESOFT;
4761 if (resplen > 0) {
4762 size_t reccount = resplen / reclen;
4763 if (select_current_file)
4764 PrintAndLogEx(SUCCESS, "Read %zu bytes from file 0x%04x from record %d record count %zu record length %zu", resplen, fisoid, offset, reccount, reclen);
4765 else
4766 PrintAndLogEx(SUCCESS, "Read %zu bytes from file 0x%02x from record %d record count %zu record length %zu", resplen, fnum, offset, reccount, reclen);
4767 if (reccount > 1)
4768 PrintAndLogEx(SUCCESS, "Lastest record at the bottom.");
4769 for (int i = 0; i < reccount; i++) {
4770 if (i != 0)
4771 PrintAndLogEx(SUCCESS, "Record %zu", reccount - (i + offset + 1));
4772 print_buffer_with_offset(&resp[i * reclen], reclen, offset, (i == 0));
4774 } else {
4775 if (select_current_file)
4776 PrintAndLogEx(SUCCESS, "Read operation returned no data from file %04x", fisoid);
4777 else
4778 PrintAndLogEx(SUCCESS, "Read operation returned no data from file %02x", fnum);
4782 return PM3_SUCCESS;
4785 static int DesfileReadFileAndPrint(DesfireContext_t *dctx,
4786 uint8_t fnum, int filetype,
4787 uint32_t offset, uint32_t length,
4788 uint32_t maxdatafilelength, bool noauth, bool verbose) {
4790 int res;
4791 // length of record for record file
4792 size_t reclen = 0;
4794 // iso chaining works in the lrp mode
4795 dctx->isoChaining |= (dctx->secureChannel == DACLRP);
4797 // get file settings
4798 if (filetype == RFTAuto) {
4799 FileSettings_t fsettings;
4801 DesfireCommunicationMode commMode = dctx->commMode;
4802 DesfireSetCommMode(dctx, DCMMACed);
4803 res = DesfireFileSettingsStruct(dctx, fnum, &fsettings);
4804 DesfireSetCommMode(dctx, commMode);
4806 if (res == PM3_SUCCESS) {
4807 switch (fsettings.fileType) {
4808 case 0x00:
4809 case 0x01: {
4810 filetype = RFTData;
4811 break;
4813 case 0x02: {
4814 filetype = RFTValue;
4815 break;
4817 case 0x03:
4818 case 0x04: {
4819 filetype = RFTRecord;
4820 reclen = fsettings.recordSize;
4821 break;
4823 case 0x05: {
4824 filetype = RFTMAC;
4825 break;
4827 default: {
4828 break;
4832 commMode = fsettings.commMode;
4833 // lrp needs to point exact mode
4834 if (dctx->secureChannel == DACLRP) {
4835 // read right == free
4836 if (fsettings.rAccess == 0xe)
4837 commMode = DCMPlain;
4838 // get value access == free
4839 if (filetype == RFTValue && (fsettings.limitedCredit & 0x02) != 0)
4840 commMode = DCMPlain;
4843 // calc max length
4844 if (filetype == RFTData && maxdatafilelength && (maxdatafilelength < fsettings.fileSize)) {
4845 length = maxdatafilelength;
4848 DesfireSetCommMode(dctx, commMode);
4850 if (fsettings.fileCommMode != 0 && noauth)
4851 PrintAndLogEx(WARNING, "File needs communication mode `%s` but there is no authentication", CLIGetOptionListStr(DesfireCommunicationModeOpts, fsettings.commMode));
4853 if ((fsettings.rAccess < 0x0e && fsettings.rAccess != dctx->keyNum) && (fsettings.rwAccess < 0x0e && fsettings.rwAccess != dctx->keyNum))
4854 PrintAndLogEx(WARNING, "File needs to be authenticated with key 0x%02x or 0x%02x but current authentication key is 0x%02x", fsettings.rAccess, fsettings.rwAccess, dctx->keyNum);
4856 if (fsettings.rAccess == 0x0f && fsettings.rwAccess == 0x0f)
4857 PrintAndLogEx(WARNING, "File access denied. All read access rights is 0x0F");
4859 if (verbose) {
4860 PrintAndLogEx(INFO, _CYAN_("File type:") " %s Option: %s comm mode: %s",
4861 GetDesfireFileType(fsettings.fileType),
4862 CLIGetOptionListStr(DesfireReadFileTypeOpts, filetype),
4863 CLIGetOptionListStr(DesfireCommunicationModeOpts, fsettings.commMode)
4866 } else {
4867 PrintAndLogEx(WARNING, "GetFileSettings error. Can't get file type.");
4871 PrintAndLogEx(INFO, "------------------------------- " _CYAN_("File %02x data") " -------------------------------", fnum);
4873 uint8_t *resp = calloc(DESFIRE_BUFFER_SIZE, 1);
4874 if (resp == NULL) {
4875 PrintAndLogEx(ERR, "Desfire calloc " _RED_("error"));
4876 DropField();
4877 return PM3_EMALLOC;
4879 size_t resplen = 0;
4881 if (filetype == RFTData) {
4882 res = DesfireReadFile(dctx, fnum, offset, length, resp, &resplen);
4883 if (res != PM3_SUCCESS) {
4884 PrintAndLogEx(ERR, "Desfire ReadFile command " _RED_("error") ". Result: %d", res);
4885 DropField();
4886 free(resp);
4887 return PM3_ESOFT;
4890 if (resplen > 0) {
4891 PrintAndLogEx(SUCCESS, "Read %zu bytes from file 0x%02x offset %u", resplen, fnum, offset);
4892 print_buffer_with_offset(resp, resplen, offset, true);
4893 } else {
4894 PrintAndLogEx(SUCCESS, "Read operation returned no data from file %d", fnum);
4898 if (filetype == RFTValue) {
4899 uint32_t value = 0;
4900 res = DesfireValueFileOperations(dctx, fnum, MFDES_GET_VALUE, &value);
4901 if (res != PM3_SUCCESS) {
4902 PrintAndLogEx(ERR, "Desfire GetValue operation " _RED_("error") ". Result: %d", res);
4903 DropField();
4904 free(resp);
4905 return PM3_ESOFT;
4907 PrintAndLogEx(SUCCESS, "Read file 0x%02x value: %d (0x%08x)", fnum, value, value);
4910 if (filetype == RFTRecord) {
4911 resplen = 0;
4912 if (reclen == 0) {
4913 res = DesfireReadRecords(dctx, fnum, offset, 1, resp, &resplen);
4914 if (res != PM3_SUCCESS) {
4915 PrintAndLogEx(ERR, "Desfire ReadRecords (len=1) command " _RED_("error") ". Result: %d", res);
4916 DropField();
4917 free(resp);
4918 return PM3_ESOFT;
4920 reclen = resplen;
4923 if (verbose)
4924 PrintAndLogEx(INFO, "Record length %zu", reclen);
4926 // if we got one record via the DesfireReadRecords before -- we not need to get it 2nd time
4927 if (length != 1 || resplen == 0) {
4928 res = DesfireReadRecords(dctx, fnum, offset, length, resp, &resplen);
4929 if (res != PM3_SUCCESS) {
4930 PrintAndLogEx(ERR, "Desfire ReadRecords command " _RED_("error") ". Result: %d", res);
4931 DropField();
4932 free(resp);
4933 return PM3_ESOFT;
4937 if (resplen > 0 && reclen > 0) {
4938 size_t reccount = resplen / reclen;
4939 PrintAndLogEx(SUCCESS, "Read %zu bytes from file 0x%02x from record %d record count %zu record length %zu", resplen, fnum, offset, reccount, reclen);
4940 if (reccount > 1) {
4941 PrintAndLogEx(SUCCESS, "Lastest record at the bottom.");
4944 for (int i = 0; i < reccount; i++) {
4945 if (i != 0) {
4946 PrintAndLogEx(SUCCESS, "Record %zu", reccount - (i + offset + 1));
4948 print_buffer_with_offset(&resp[i * reclen], reclen, offset, (i == 0));
4950 } else {
4951 PrintAndLogEx(SUCCESS, "Read operation returned no data from file %d", fnum);
4955 if (filetype == RFTMAC) {
4956 res = DesfireReadFile(dctx, fnum, 0, 0, resp, &resplen);
4957 if (res != PM3_SUCCESS) {
4958 PrintAndLogEx(ERR, "Desfire ReadFile command " _RED_("error") ". Result: %d", res);
4959 DropField();
4960 free(resp);
4961 return PM3_ESOFT;
4964 if (resplen > 0) {
4965 if (resplen != 12) {
4966 PrintAndLogEx(WARNING, "Read wrong %zu bytes from file 0x%02x offset %u", resplen, fnum, offset);
4967 print_buffer_with_offset(resp, resplen, offset, true);
4968 } else {
4969 uint32_t cnt = MemLeToUint4byte(&resp[0]);
4970 transactionCounter = cnt;
4971 if (dctx->secureChannel != DACLRP) {
4972 PrintAndLogEx(SUCCESS, "Transaction counter: %d (0x%08x)", cnt, cnt);
4973 } else {
4974 // For composing TMC the two subparts are concatenated as follows: actTMC || sesTMC. Both subparts are represented LSB first.
4975 // MF2DLHX0.pdf, 10.3.2.1 Transaction MAC Counter, page 41
4976 uint32_t actTMC = MemLeToUint2byte(&resp[0]);
4977 uint32_t sessTMC = MemLeToUint2byte(&resp[2]);
4978 PrintAndLogEx(SUCCESS, "Session tr counter : %d (0x%04x)", sessTMC, sessTMC);
4979 PrintAndLogEx(SUCCESS, "Actual tr counter : %d (0x%04x)", actTMC, actTMC);
4981 PrintAndLogEx(SUCCESS, "Transaction MAC : %s", sprint_hex(&resp[4], 8));
4983 } else {
4984 PrintAndLogEx(SUCCESS, "Read operation returned no data from file %d", fnum);
4988 free(resp);
4989 return PM3_SUCCESS;
4992 static int CmdHF14ADesReadData(const char *Cmd) {
4993 CLIParserContext *ctx;
4994 CLIParserInit(&ctx, "hf mfdes read",
4995 "Read data from file. Key needs to be provided or flag --no-auth set (depend on file settings).",
4996 "It reads file via all command sets. \n"
4997 "For ISO command set it can be read by specifying full 2-byte iso id or 1-byte short iso id (first byte of the full iso id). ISO id lays in the data in BIG ENDIAN format.\n"
4998 "ISO record commands: offset - record number (0-current, 1..ff-number, 1-lastest), length - if 0 - all records, if 1 - one\n"
4999 "\n"
5000 "hf mfdes read --aid 123456 --fid 01 -> read file: app=123456, file=01, offset=0, all the data. use default channel settings from `default` command\n"
5001 "hf mfdes read --aid 123456 --fid 01 --type record --offset 000000 --length 000001 -> read one last record from record file. use default channel settings from `default` command\n"
5002 "hf mfdes read --aid 123456 --fid 10 --type data -c iso -> read file via ISO channel: app=123456, short iso id=10, offset=0.\n"
5003 "hf mfdes read --aid 123456 --fileisoid 1000 --type data -c iso -> read file via ISO channel: app=123456, iso id=1000, offset=0. Select via native ISO wrapper\n"
5004 "hf mfdes read --isoid 0102 --fileisoid 1000 --type data -c iso -> read file via ISO channel: app iso id=0102, iso id=1000, offset=0. Select via ISO commands\n"
5005 "hf mfdes read --isoid 0102 --fileisoid 1100 --type record -c iso --offset 000005 --length 000001 -> get one record (number 5) from file 1100 via iso commands\n"
5006 "hf mfdes read --isoid 0102 --fileisoid 1100 --type record -c iso --offset 000005 --length 000000 -> get all record (from 5 to 1) from file 1100 via iso commands\n"
5007 "hf mfdes read --isoid df01 --fid 00 --schann lrp -t aes --length 000010 -> read via lrp channel\n"
5008 "hf mfdes read --isoid df01 --fid 00 --schann ev2 -t aes --length 000010 --isochain -> read Desfire Light via ev2 channel");
5010 void *argtable[] = {
5011 arg_param_begin,
5012 arg_lit0("a", "apdu", "Show APDU requests and responses"),
5013 arg_lit0("v", "verbose", "Verbose output"),
5014 arg_int0("n", "keyno", "<dec>", "Key number"),
5015 arg_str0("t", "algo", "<DES|2TDEA|3TDEA|AES>", "Crypt algo"),
5016 arg_str0("k", "key", "<hex>", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"),
5017 arg_str0(NULL, "kdf", "<none|AN10922|gallagher>", "Key Derivation Function (KDF)"),
5018 arg_str0("i", "kdfi", "<hex>", "KDF input (1-31 hex bytes)"),
5019 arg_str0("m", "cmode", "<plain|mac|encrypt>", "Communicaton mode"),
5020 arg_str0("c", "ccset", "<native|niso|iso>", "Communicaton command set"),
5021 arg_str0(NULL, "schann", "<d40|ev1|ev2|lrp>", "Secure channel"),
5022 arg_str0(NULL, "aid", "<hex>", "Application ID (3 hex bytes, big endian)"),
5023 arg_str0(NULL, "fid", "<hex>", "File ID (1 hex byte)"),
5024 arg_lit0(NULL, "no-auth", "Execute without authentication"),
5025 arg_str0(NULL, "type", "<auto|data|value|record|mac>", "File Type, Auto - check file settings and then read. (def: auto)"),
5026 arg_str0("o", "offset", "<hex>", "File Offset (3 hex bytes, big endian). For records - record number (0 - lastest record). (def: 0)"),
5027 arg_str0("l", "length", "<hex>", "Length to read (3 hex bytes, big endian -> 000000 = Read all data). For records - records count (0 - all). (def: 0)"),
5028 arg_str0(NULL, "isoid", "<hex>", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian)"),
5029 arg_str0(NULL, "fileisoid", "<hex>", "File ISO ID (ISO DF ID) (2 hex bytes, big endian). Works only for ISO read commands"),
5030 arg_lit0(NULL, "isochain", "use iso chaining commands. Switched on by default if secure channel = lrp"),
5031 arg_param_end
5033 CLIExecWithReturn(ctx, Cmd, argtable, false);
5035 bool APDULogging = arg_get_lit(ctx, 1);
5036 bool verbose = arg_get_lit(ctx, 2);
5037 bool noauth = arg_get_lit(ctx, 13);
5039 DesfireContext_t dctx;
5040 int securechann = defaultSecureChannel;
5041 uint32_t id = 0x000000;
5042 DesfireISOSelectWay selectway = ISW6bAID;
5043 int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 17, &securechann, DCMMACed, &id, &selectway);
5044 if (res) {
5045 CLIParserFree(ctx);
5046 return res;
5049 uint32_t fnum = 1;
5050 if (CLIGetUint32Hex(ctx, 12, 1, &fnum, NULL, 1, "File ID must have 1 byte length")) {
5051 CLIParserFree(ctx);
5052 return PM3_EINVARG;
5055 int op = RFTAuto;
5056 if (CLIGetOptionList(arg_get_str(ctx, 14), DesfireReadFileTypeOpts, &op)) {
5057 CLIParserFree(ctx);
5058 return PM3_ESOFT;
5061 uint32_t offset = 0;
5062 if (CLIGetUint32Hex(ctx, 15, 0, &offset, NULL, 3, "Offset must have 3 byte length")) {
5063 CLIParserFree(ctx);
5064 return PM3_EINVARG;
5067 uint32_t length = 0;
5068 if (CLIGetUint32Hex(ctx, 16, 0, &length, NULL, 3, "Length parameter must have 3 byte length")) {
5069 CLIParserFree(ctx);
5070 return PM3_EINVARG;
5073 uint32_t fileisoid = 0x0000;
5074 bool fileisoidpresent = false;
5075 if (CLIGetUint32Hex(ctx, 18, 0x0000, &fileisoid, &fileisoidpresent, 2, "File ISO ID (for DF) must have 2 bytes length")) {
5076 CLIParserFree(ctx);
5077 return PM3_EINVARG;
5080 dctx.isoChaining = arg_get_lit(ctx, 19);
5082 SetAPDULogging(APDULogging);
5083 CLIParserFree(ctx);
5085 if (fnum > 0x1F) {
5086 PrintAndLogEx(ERR, "File number range is invalid (exp 0x00 - 0x1f), got 0x%02x", fnum);
5087 return PM3_EINVARG;
5090 res = DesfireSelectAndAuthenticateW(&dctx, securechann, selectway, id, fileisoidpresent, fileisoid, noauth, verbose);
5091 if (res != PM3_SUCCESS) {
5092 DropField();
5093 PrintAndLogEx(FAILED, "Select or authentication %s " _RED_("failed") ". Result [%d] %s", DesfireWayIDStr(selectway, id), res, DesfireAuthErrorToStr(res));
5094 return res;
5097 if (dctx.cmdSet != DCCISO)
5098 res = DesfileReadFileAndPrint(&dctx, fnum, op, offset, length, 0, noauth, verbose);
5099 else
5100 res = DesfileReadISOFileAndPrint(&dctx, fileisoidpresent, fnum, fileisoid, op, offset, length, noauth, verbose);
5102 DropField();
5103 return res;
5106 static int DesfileWriteISOFile(DesfireContext_t *dctx,
5107 bool select_current_file, uint8_t fnum,
5108 uint16_t fisoid, int filetype,
5109 uint32_t offset, uint8_t *data,
5110 uint32_t datalen, bool verbose) {
5112 if (filetype == RFTAuto) {
5113 PrintAndLogEx(ERR, "ISO mode needs to specify file type");
5114 return PM3_EINVARG;
5117 if (filetype == RFTValue) {
5118 PrintAndLogEx(ERR, "ISO mode can't write Value file type");
5119 return PM3_EINVARG;
5122 if (filetype == RFTMAC) {
5123 PrintAndLogEx(ERR, "ISO mode can't write Transaction MAC file type");
5124 return PM3_EINVARG;
5127 if (dctx->commMode != DCMPlain) {
5128 PrintAndLogEx(ERR, "ISO mode can write only in plain mode");
5129 return PM3_EINVARG;
5132 int res;
5133 if (filetype == RFTData) {
5134 res = DesfireISOUpdateBinary(dctx, !select_current_file, (select_current_file) ? 0x00 : fnum, offset, data, datalen);
5135 if (res != PM3_SUCCESS) {
5136 PrintAndLogEx(ERR, "Desfire ISOUpdateBinary command " _RED_("error") ". Result: %d", res);
5137 return PM3_ESOFT;
5140 if (select_current_file)
5141 PrintAndLogEx(INFO, "Write data file %04x " _GREEN_("success"), fisoid);
5142 else
5143 PrintAndLogEx(INFO, "Write data file %02x " _GREEN_("success"), fnum);
5146 if (filetype == RFTRecord) {
5147 res = DesfireISOAppendRecord(dctx, (select_current_file) ? 0x00 : fnum, data, datalen);
5148 if (res != PM3_SUCCESS) {
5149 PrintAndLogEx(ERR, "Desfire WriteRecord command " _RED_("error") ". Result: %d", res);
5150 return PM3_ESOFT;
5152 if (select_current_file)
5153 PrintAndLogEx(INFO, "Write record to file %04x " _GREEN_("success"), fisoid);
5154 else
5155 PrintAndLogEx(INFO, "Write record to file %02x " _GREEN_("success"), fnum);
5158 return PM3_SUCCESS;
5161 static int CmdHF14ADesWriteData(const char *Cmd) {
5162 CLIParserContext *ctx;
5163 CLIParserInit(&ctx, "hf mfdes write",
5164 "Write data from file. Key needs to be provided or flag --no-auth set (depend on file settings).",
5165 "In the mode with CommitReaderID to decode previous reader id command needs to read transaction counter via dump/read command and specify --trkey\n"
5166 "\n"
5167 "hf mfdes write --aid 123456 --fid 01 -d 01020304 -> AID 123456, file=01, offset=0, get file type from card. use default channel settings from `default` command\n"
5168 "hf mfdes write --aid 123456 --fid 01 --type data -d 01020304 --0ffset 000100 -> write data to std file with offset 0x100\n"
5169 "hf mfdes write --aid 123456 --fid 01 --type data -d 01020304 --commit -> write data to backup file with commit\n"
5170 "hf mfdes write --aid 123456 --fid 01 --type value -d 00000001 -> increment value file\n"
5171 "hf mfdes write --aid 123456 --fid 01 --type value -d 00000001 --debit -> decrement value file\n"
5172 "hf mfdes write --aid 123456 --fid 01 -d 01020304 -> write data to file with `auto` type\n"
5173 "hf mfdes write --aid 123456 --fid 01 --type record -d 01020304 -> write data to record file\n"
5174 "hf mfdes write --aid 123456 --fid 01 --type record -d 01020304 --updaterec 0 -> update record in the record file. record 0 - lastest record.\n"
5175 "hf mfdes write --aid 123456 --fid 01 --type record --offset 000000 -d 11223344 -> write record to record file. use default channel settings from `default` command\n"
5176 "hf mfdes write --isoid 1234 --fileisoid 1000 --type data -c iso -d 01020304 -> write data to std/backup file via iso commandset\n"
5177 "hf mfdes write --isoid 1234 --fileisoid 2000 --type record -c iso -d 01020304 -> send record to record file via iso commandset\n"
5178 "hf mfdes write --aid 123456 --fid 01 -d 01020304 --readerid 010203 -> write data to file with CommitReaderID command before write and CommitTransaction after write\n"
5179 "hf mfdes write --isoid df01 --fid 04 -d 01020304 --trkey 00112233445566778899aabbccddeeff --readerid 5532 -t aes --schann lrp -> advanced CommitReaderID via lrp channel sample");
5181 void *argtable[] = {
5182 arg_param_begin,
5183 arg_lit0("a", "apdu", "Show APDU requests and responses"),
5184 arg_lit0("v", "verbose", "Verbose output"),
5185 arg_int0("n", "keyno", "<dec>", "Key number"),
5186 arg_str0("t", "algo", "<DES|2TDEA|3TDEA|AES>", "Crypt algo"),
5187 arg_str0("k", "key", "<hex>", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"),
5188 arg_str0(NULL, "kdf", "<none|AN10922|gallagher>", "Key Derivation Function (KDF)"),
5189 arg_str0("i", "kdfi", "<hex>", "KDF input (1-31 hex bytes)"),
5190 arg_str0("m", "cmode", "<plain|mac|encrypt>", "Communicaton mode"),
5191 arg_str0("c", "ccset", "<native|niso|iso>", "Communicaton command set"),
5192 arg_str0(NULL, "schann", "<d40|ev1|ev2|lrp>", "Secure channel"),
5193 arg_str0(NULL, "aid", "<hex>", "Application ID (3 hex bytes, big endian)"),
5194 arg_str0(NULL, "fid", "<hex>", "File ID (1 hex byte)"),
5195 arg_lit0(NULL, "no-auth", "Execute without authentication"),
5196 arg_str0(NULL, "type", "<auto|data|value|record|mac>", "File Type, Auto - check file settings and then write. (def: auto)"),
5197 arg_str0("o", "offset", "<hex>", "File Offset (3 hex bytes, big endian). For records - record number (0 - lastest record). (def: 0)"),
5198 arg_str0("d", "data", "<hex>", "data for write (data/record file), credit/debit(value file)"),
5199 arg_lit0(NULL, "debit", "use for value file debit operation instead of credit"),
5200 arg_lit0(NULL, "commit", "commit needs for backup file only. For the other file types and in the `auto` mode - command set it automatically"),
5201 arg_int0(NULL, "updaterec", "<dec>", "Record number for update record command. Updates record instead of write. Lastest record - 0"),
5202 arg_str0(NULL, "isoid", "<hex>", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian)"),
5203 arg_str0(NULL, "fileisoid", "<hex>", "File ISO ID (ISO DF ID) (2 hex bytes, big endian). Works only for ISO write commands"),
5204 arg_str0(NULL, "readerid", "<hex>", "reader id for CommitReaderID command. If present - the command issued before write command"),
5205 arg_str0(NULL, "trkey", "<hex>", "key for decode previous reader id"),
5206 arg_param_end
5208 CLIExecWithReturn(ctx, Cmd, argtable, false);
5210 bool APDULogging = arg_get_lit(ctx, 1);
5211 bool verbose = arg_get_lit(ctx, 2);
5212 bool noauth = arg_get_lit(ctx, 13);
5214 DesfireContext_t dctx;
5215 int securechann = defaultSecureChannel;
5216 uint32_t id = 0x000000;
5217 DesfireISOSelectWay selectway = ISW6bAID;
5218 int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 20, &securechann, DCMMACed, &id, &selectway);
5219 if (res) {
5220 CLIParserFree(ctx);
5221 return res;
5224 uint32_t fnum = 1;
5225 if (CLIGetUint32Hex(ctx, 12, 1, &fnum, NULL, 1, "File ID must have 1 byte length")) {
5226 CLIParserFree(ctx);
5227 return PM3_EINVARG;
5230 int op = RFTAuto;
5231 if (CLIGetOptionList(arg_get_str(ctx, 14), DesfireReadFileTypeOpts, &op)) {
5232 CLIParserFree(ctx);
5233 return PM3_ESOFT;
5236 uint32_t offset = 0;
5237 if (CLIGetUint32Hex(ctx, 15, 0, &offset, NULL, 3, "Offset must have 3 byte length")) {
5238 CLIParserFree(ctx);
5239 return PM3_EINVARG;
5242 uint8_t data[1024] = {0};
5243 int datalen = sizeof(data);
5244 CLIGetHexWithReturn(ctx, 16, data, &datalen);
5245 if (datalen == 0) {
5246 PrintAndLogEx(ERR, "Data for write must be present.");
5247 CLIParserFree(ctx);
5248 return PM3_EINVARG;
5251 bool debit = arg_get_lit(ctx, 17);
5252 bool commit = arg_get_lit(ctx, 18);
5254 int updaterecno = arg_get_int_def(ctx, 19, -1);
5256 uint32_t fileisoid = 0x0000;
5257 bool fileisoidpresent = false;
5258 if (CLIGetUint32Hex(ctx, 21, 0x0000, &fileisoid, &fileisoidpresent, 2, "File ISO ID (for DF) must have 2 bytes length")) {
5259 CLIParserFree(ctx);
5260 return PM3_EINVARG;
5263 uint8_t readerid[250] = {0};
5264 int readeridlen = sizeof(readerid);
5265 CLIGetHexWithReturn(ctx, 22, readerid, &readeridlen);
5266 if (readeridlen > 16) {
5267 PrintAndLogEx(ERR, "ReaderID must be up to 16 bytes length.");
5268 CLIParserFree(ctx);
5269 return PM3_EINVARG;
5272 uint8_t trkey[250] = {0};
5273 int trkeylen = sizeof(trkey);
5274 CLIGetHexWithReturn(ctx, 23, trkey, &trkeylen);
5275 if (trkeylen > 0 && trkeylen != 16) {
5276 PrintAndLogEx(ERR, "Transaction key must be 16 bytes length.");
5277 CLIParserFree(ctx);
5278 return PM3_EINVARG;
5281 SetAPDULogging(APDULogging);
5282 CLIParserFree(ctx);
5284 if (fnum > 0x1F) {
5285 PrintAndLogEx(ERR, "File number range is invalid (exp 0x00 - 0x1f), got 0x%02x", fnum);
5286 return PM3_EINVARG;
5289 // get uid
5290 if (trkeylen > 0)
5291 DesfireGetCardUID(&dctx);
5293 res = DesfireSelectAndAuthenticateW(&dctx, securechann, selectway, id, fileisoidpresent, fileisoid, noauth, verbose);
5294 if (res != PM3_SUCCESS) {
5295 DropField();
5296 PrintAndLogEx(FAILED, "Select or authentication %s " _RED_("failed") ". Result [%d] %s", DesfireWayIDStr(selectway, id), res, DesfireAuthErrorToStr(res));
5297 return res;
5300 // ISO command set
5301 if (dctx.cmdSet == DCCISO) {
5302 if (op == RFTRecord && updaterecno >= 0) {
5303 PrintAndLogEx(ERR, "ISO mode can't update record. Only append.");
5304 DropField();
5305 return PM3_EINVARG;
5308 res = DesfileWriteISOFile(&dctx, fileisoidpresent, fnum, fileisoid, op, offset, data, datalen, verbose);
5309 DropField();
5310 return res;
5313 // get file settings
5314 if (op == RFTAuto) {
5315 FileSettings_t fsettings;
5317 DesfireCommunicationMode commMode = dctx.commMode;
5318 DesfireSetCommMode(&dctx, DCMMACed);
5319 res = DesfireFileSettingsStruct(&dctx, fnum, &fsettings);
5320 DesfireSetCommMode(&dctx, commMode);
5322 if (res == PM3_SUCCESS) {
5323 switch (fsettings.fileType) {
5324 case 0x00:
5325 case 0x01: {
5326 op = RFTData;
5327 if (!commit)
5328 commit = (fsettings.fileType == 0x01);
5329 break;
5331 case 0x02: {
5332 op = RFTValue;
5333 commit = true;
5334 break;
5336 case 0x03:
5337 case 0x04: {
5338 op = RFTRecord;
5339 commit = true;
5340 if (datalen > fsettings.recordSize)
5341 PrintAndLogEx(WARNING, "Record size (%d) " _RED_("is less") " than data length (%d)", fsettings.recordSize, datalen);
5342 break;
5344 case 0x05: {
5345 op = RFTMAC;
5346 commit = false;
5347 break;
5349 default: {
5350 break;
5354 DesfireSetCommMode(&dctx, fsettings.commMode);
5356 if (fsettings.fileCommMode != 0 && noauth)
5357 PrintAndLogEx(WARNING, "File needs communication mode `%s` but there is no authentication", CLIGetOptionListStr(DesfireCommunicationModeOpts, fsettings.commMode));
5359 if ((fsettings.rAccess < 0x0e && fsettings.rAccess != dctx.keyNum) && (fsettings.rwAccess < 0x0e && fsettings.rwAccess != dctx.keyNum))
5360 PrintAndLogEx(WARNING, "File needs to be authenticated with key 0x%02x or 0x%02x but current authentication key is 0x%02x", fsettings.rAccess, fsettings.rwAccess, dctx.keyNum);
5362 if (fsettings.rAccess == 0x0f && fsettings.rwAccess == 0x0f)
5363 PrintAndLogEx(WARNING, "File access denied. All read access rights is 0x0f.");
5365 if (verbose)
5366 PrintAndLogEx(INFO, "Got file type: %s. Option: %s. comm mode: %s",
5367 GetDesfireFileType(fsettings.fileType),
5368 CLIGetOptionListStr(DesfireReadFileTypeOpts, op),
5369 CLIGetOptionListStr(DesfireCommunicationModeOpts, fsettings.commMode));
5370 } else {
5371 PrintAndLogEx(WARNING, "GetFileSettings error. Can't get file type.");
5375 // CommitReaderID command
5376 bool readeridpushed = false;
5377 if (readeridlen > 0) {
5378 uint8_t resp[250] = {0};
5379 size_t resplen = 0;
5381 DesfireCommunicationMode commMode = dctx.commMode;
5382 DesfireSetCommMode(&dctx, DCMMACed);
5383 res = DesfireCommitReaderID(&dctx, readerid, readeridlen, resp, &resplen);
5384 DesfireSetCommMode(&dctx, commMode);
5386 if (res == PM3_SUCCESS) {
5387 PrintAndLogEx(INFO, _GREEN_("Commit Reader ID: "));
5388 PrintAndLogEx(INFO, "Prev reader id encoded [%zu]: %s", resplen, sprint_hex(resp, resplen));
5390 if (trkeylen > 0) {
5391 uint8_t prevReaderID[CRYPTO_AES_BLOCK_SIZE] = {0};
5392 DesfireDecodePrevReaderID(&dctx, trkey, transactionCounter, resp, prevReaderID);
5393 PrintAndLogEx(INFO, "Prev reader id: %s", sprint_hex(prevReaderID, CRYPTO_AES_BLOCK_SIZE));
5396 readeridpushed = true;
5397 if (verbose)
5398 PrintAndLogEx(INFO, "CommitReaderID ( " _GREEN_("ok") " )");
5399 } else
5400 PrintAndLogEx(WARNING, "Desfire CommitReaderID command " _RED_("error") ". Result: %d", res);
5403 // iso chaining works in the lrp mode
5404 dctx.isoChaining |= (dctx.secureChannel == DACLRP);
5406 // write
5407 if (op == RFTData) {
5408 res = DesfireWriteFile(&dctx, fnum, offset, datalen, data);
5409 if (res != PM3_SUCCESS) {
5410 PrintAndLogEx(ERR, "Desfire WriteFile command " _RED_("error") ". Result: %d", res);
5411 DropField();
5412 return PM3_ESOFT;
5415 if (verbose)
5416 PrintAndLogEx(INFO, "Write data file %02x " _GREEN_("success"), fnum);
5419 if (op == RFTValue) {
5420 if (datalen != 4) {
5421 PrintAndLogEx(ERR, "Value " _RED_("should be") " 4 byte length instead of %d", datalen);
5422 DropField();
5423 return PM3_EINVARG;
5426 uint32_t value = MemBeToUint4byte(data);
5427 uint8_t vop = (debit) ? MFDES_DEBIT : MFDES_CREDIT;
5428 res = DesfireValueFileOperations(&dctx, fnum, vop, &value);
5429 if (res != PM3_SUCCESS) {
5430 PrintAndLogEx(ERR, "Desfire %s operation " _RED_("error") ". Result: %d", CLIGetOptionListStr(DesfireValueFileOperOpts, vop), res);
5431 DropField();
5432 return PM3_ESOFT;
5435 if (verbose)
5436 PrintAndLogEx(INFO, "%s value file %02x (%s) " _GREEN_("success"), (debit) ? "Debit" : "Credit", fnum, CLIGetOptionListStr(DesfireValueFileOperOpts, vop));
5437 commit = true;
5440 if (op == RFTRecord) {
5441 if (updaterecno < 0) {
5442 res = DesfireWriteRecord(&dctx, fnum, offset, datalen, data);
5443 if (res != PM3_SUCCESS) {
5444 PrintAndLogEx(ERR, "Desfire WriteRecord command " _RED_("error") ". Result: %d", res);
5445 DropField();
5446 return PM3_ESOFT;
5448 if (verbose)
5449 PrintAndLogEx(INFO, "Write record file %02x " _GREEN_("success"), fnum);
5450 } else {
5451 res = DesfireUpdateRecord(&dctx, fnum, updaterecno, offset, datalen, data);
5452 if (res != PM3_SUCCESS) {
5453 PrintAndLogEx(ERR, "Desfire UpdateRecord command " _RED_("error") ". Result: %d", res);
5454 DropField();
5455 return PM3_ESOFT;
5457 if (verbose)
5458 PrintAndLogEx(INFO, "Update record %06x in the file %02x " _GREEN_("success"), updaterecno, fnum);
5461 commit = true;
5464 if (op == RFTMAC) {
5465 PrintAndLogEx(ERR, "Can't " _RED_("write") " to transaction MAC file");
5466 DropField();
5467 return PM3_EINVARG;
5470 // commit phase
5471 if (commit || readeridpushed) {
5472 uint8_t resp[250] = {0};
5473 size_t resplen = 0;
5474 DesfireSetCommMode(&dctx, DCMMACed);
5475 res = DesfireCommitTransactionEx(&dctx, readeridpushed, 0x01, resp, &resplen);
5476 if (res != PM3_SUCCESS) {
5477 PrintAndLogEx(ERR, "Desfire CommitTransaction command " _RED_("error") ". Result: %d", res);
5478 DropField();
5479 return PM3_ESOFT;
5482 if (verbose) {
5483 if (readeridpushed)
5484 PrintAndLogEx(INFO, "TMC and TMV[%zu]: %s", resplen, sprint_hex(resp, resplen));
5485 PrintAndLogEx(INFO, "Commit ( " _GREEN_("ok") " )");
5488 if (resplen == 4 + 8) {
5489 PrintAndLogEx(INFO, _GREEN_("Commit result:"));
5490 uint32_t cnt = MemLeToUint4byte(&resp[0]);
5491 transactionCounter = cnt;
5492 if (dctx.secureChannel != DACLRP) {
5493 PrintAndLogEx(SUCCESS, "Transaction counter: %d (0x%08x)", cnt, cnt);
5494 } else {
5495 // For composing TMC the two subparts are concatenated as follows: actTMC || sesTMC. Both subparts are represented LSB first.
5496 // MF2DLHX0.pdf, 10.3.2.1 Transaction MAC Counter, page 41
5497 uint32_t actTMC = MemLeToUint2byte(&resp[0]);
5498 uint32_t sessTMC = MemLeToUint2byte(&resp[2]);
5499 PrintAndLogEx(SUCCESS, "Session tr counter : %d (0x%04x)", sessTMC, sessTMC);
5500 PrintAndLogEx(SUCCESS, "Actual tr counter : %d (0x%04x)", actTMC, actTMC);
5502 PrintAndLogEx(SUCCESS, "Transaction MAC : %s", sprint_hex(&resp[4], 8));
5506 PrintAndLogEx(INFO, "Write %s file %02x " _GREEN_("success"), CLIGetOptionListStr(DesfireReadFileTypeOpts, op), fnum);
5508 DropField();
5509 return PM3_SUCCESS;
5512 static int CmdHF14ADesLsFiles(const char *Cmd) {
5513 CLIParserContext *ctx;
5514 CLIParserInit(&ctx, "hf mfdes lsfiles",
5515 "This commands List files inside application AID / ISOID.\n"
5516 "Master key needs to be provided or flag --no-auth set (depend on cards settings).",
5517 "hf mfdes lsfiles --aid 123456 -> AID 123456, list files using `default` command creds\n"
5518 "hf mfdes lsfiles --isoid df01 --no-auth -> list files for DESFire light");
5520 void *argtable[] = {
5521 arg_param_begin,
5522 arg_lit0("a", "apdu", "Show APDU requests and responses"),
5523 arg_lit0("v", "verbose", "Verbose output"),
5524 arg_int0("n", "keyno", "<dec>", "Key number"),
5525 arg_str0("t", "algo", "<DES|2TDEA|3TDEA|AES>", "Crypt algo"),
5526 arg_str0("k", "key", "<hex>", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"),
5527 arg_str0(NULL, "kdf", "<none|AN10922|gallagher>", "Key Derivation Function (KDF)"),
5528 arg_str0("i", "kdfi", "<hex>", "KDF input (1-31 hex bytes)"),
5529 arg_str0("m", "cmode", "<plain|mac|encrypt>", "Communicaton mode"),
5530 arg_str0("c", "ccset", "<native|niso|iso>", "Communicaton command set"),
5531 arg_str0(NULL, "schann", "<d40|ev1|ev2|lrp>", "Secure channel"),
5532 arg_str0(NULL, "aid", "<hex>", "Application ID (3 hex bytes, big endian)"),
5533 arg_str0(NULL, "isoid", "<hex>", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian)"),
5534 arg_lit0(NULL, "no-auth", "Execute without authentication"),
5535 arg_param_end
5537 CLIExecWithReturn(ctx, Cmd, argtable, false);
5539 bool APDULogging = arg_get_lit(ctx, 1);
5540 bool verbose = arg_get_lit(ctx, 2);
5541 bool noauth = arg_get_lit(ctx, 13);
5543 DesfireContext_t dctx;
5544 int securechann = defaultSecureChannel;
5545 uint32_t id = 0x000000;
5546 DesfireISOSelectWay selectway = ISW6bAID;
5547 int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, &securechann, DCMMACed, &id, &selectway);
5548 if (res) {
5549 CLIParserFree(ctx);
5550 return res;
5553 SetAPDULogging(APDULogging);
5554 CLIParserFree(ctx);
5556 res = DesfireSelectAndAuthenticateAppW(&dctx, securechann, selectway, id, noauth, verbose);
5557 if (res != PM3_SUCCESS) {
5558 DropField();
5559 PrintAndLogEx(FAILED, "Select or authentication %s " _RED_("failed") ". Result [%d] %s", DesfireWayIDStr(selectway, id), res, DesfireAuthErrorToStr(res));
5560 return res;
5563 FileList_t FileList = {{0}};
5564 size_t filescount = 0;
5565 bool isopresent = false;
5566 res = DesfireFillFileList(&dctx, FileList, &filescount, &isopresent);
5567 if (res != PM3_SUCCESS) {
5568 DropField();
5569 return res;
5572 if (filescount == 0) {
5573 PrintAndLogEx(INFO, "There is no files in the %s", DesfireWayIDStr(selectway, id));
5574 DropField();
5575 return res;
5578 PrintAndLogEx(INFO, "------------------------------------------ " _CYAN_("File list") " -----------------------------------------------------");
5579 for (int i = 0; i < filescount; i++)
5580 DesfirePrintFileSettingsTable((i == 0), FileList[i].fileNum, isopresent, FileList[i].fileISONum, &FileList[i].fileSettings);
5582 DropField();
5583 return PM3_SUCCESS;
5586 static int CmdHF14ADesLsApp(const char *Cmd) {
5587 CLIParserContext *ctx;
5588 CLIParserInit(&ctx, "hf mfdes lsapp",
5589 "Show application list. Master key needs to be provided or flag --no-auth set (depend on cards settings).",
5590 "hf mfdes lsapp -> show application list with defaults from `default` command\n"
5591 "hf mfdes lsapp --files -> show application list and show each file type/settings/etc");
5593 void *argtable[] = {
5594 arg_param_begin,
5595 arg_lit0("a", "apdu", "Show APDU requests and responses"),
5596 arg_lit0("v", "verbose", "Verbose output"),
5597 arg_int0("n", "keyno", "<dec>", "Key number"),
5598 arg_str0("t", "algo", "<DES|2TDEA|3TDEA|AES>", "Crypt algo"),
5599 arg_str0("k", "key", "<hex>", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"),
5600 arg_str0(NULL, "kdf", "<none|AN10922|gallagher>", "Key Derivation Function (KDF)"),
5601 arg_str0("i", "kdfi", "<hex>", "KDF input (1-31 hex bytes)"),
5602 arg_str0("m", "cmode", "<plain|mac|encrypt>", "Communicaton mode"),
5603 arg_str0("c", "ccset", "<native|niso|iso>", "Communicaton command set"),
5604 arg_str0(NULL, "schann", "<d40|ev1|ev2|lrp>", "Secure channel"),
5605 arg_lit0(NULL, "no-auth", "Execute without authentication"),
5606 arg_lit0(NULL, "no-deep", "not to check authentication commands that avail for any application"),
5607 arg_lit0(NULL, "files", "scan files and print file settings"),
5608 arg_param_end
5610 CLIExecWithReturn(ctx, Cmd, argtable, true);
5612 bool APDULogging = arg_get_lit(ctx, 1);
5613 bool verbose = arg_get_lit(ctx, 2);
5614 bool noauth = arg_get_lit(ctx, 11);
5615 bool nodeep = arg_get_lit(ctx, 12);
5616 bool scanfiles = arg_get_lit(ctx, 13);
5618 DesfireContext_t dctx;
5619 int securechann = defaultSecureChannel;
5620 int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, &securechann, (noauth) ? DCMPlain : DCMMACed, NULL, NULL);
5621 if (res) {
5622 CLIParserFree(ctx);
5623 return res;
5626 SetAPDULogging(APDULogging);
5627 CLIParserFree(ctx);
5629 PrintAndLogEx(INPLACE, _YELLOW_("It may take up to 15 seconds. Processing...."));
5631 res = DesfireSelectAndAuthenticateEx(&dctx, securechann, 0x000000, noauth, verbose);
5632 if (res != PM3_SUCCESS) {
5633 DropField();
5634 return res;
5637 PICCInfo_t PICCInfo = {0};
5638 AppListS AppList = {{0}};
5639 DesfireFillAppList(&dctx, &PICCInfo, AppList, !nodeep, scanfiles, true);
5641 printf("\33[2K\r"); // clear current line before printing
5642 PrintAndLogEx(NORMAL, "");
5644 // print zone
5645 DesfirePrintPICCInfo(&dctx, &PICCInfo);
5646 DesfirePrintAppList(&dctx, &PICCInfo, AppList);
5648 DropField();
5649 return PM3_SUCCESS;
5652 static int CmdHF14ADesDump(const char *Cmd) {
5653 CLIParserContext *ctx;
5654 CLIParserInit(&ctx, "hf mfdes dump",
5655 "For each application show fil list and then file content. Key needs to be provided for authentication or flag --no-auth set (depend on cards settings).",
5656 "hf mfdes dump --aid 123456 -> show file dump for: app=123456 with channel defaults from `default` command/n"
5657 "hf mfdes dump --isoid df01 --schann lrp -t aes --length 000090 -> lrp default settings with length limit");
5659 void *argtable[] = {
5660 arg_param_begin,
5661 arg_lit0("a", "apdu", "Show APDU requests and responses"),
5662 arg_lit0("v", "verbose", "Verbose output"),
5663 arg_int0("n", "keyno", "<dec>", "Key number"),
5664 arg_str0("t", "algo", "<DES|2TDEA|3TDEA|AES>", "Crypt algo"),
5665 arg_str0("k", "key", "<hex>", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"),
5666 arg_str0(NULL, "kdf", "<none|AN10922|gallagher>", "Key Derivation Function (KDF)"),
5667 arg_str0("i", "kdfi", "<hex>", "KDF input (1-31 hex bytes)"),
5668 arg_str0("m", "cmode", "<plain|mac|encrypt>", "Communicaton mode"),
5669 arg_str0("c", "ccset", "<native|niso|iso>", "Communicaton command set"),
5670 arg_str0(NULL, "schann", "<d40|ev1|ev2|lrp>", "Secure channel"),
5671 arg_str0(NULL, "aid", "<hex>", "Application ID (3 hex bytes, big endian)"),
5672 arg_str0(NULL, "isoid", "<hex>", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian)"),
5673 arg_str0("l", "length", "<hex>", "Maximum length for read data files (3 hex bytes, big endian)"),
5674 arg_lit0(NULL, "no-auth", "Execute without authentication"),
5675 arg_param_end
5677 CLIExecWithReturn(ctx, Cmd, argtable, false);
5679 bool APDULogging = arg_get_lit(ctx, 1);
5680 bool verbose = arg_get_lit(ctx, 2);
5681 bool noauth = arg_get_lit(ctx, 14);
5683 DesfireContext_t dctx;
5684 int securechann = defaultSecureChannel;
5685 uint32_t id = 0x000000;
5686 DesfireISOSelectWay selectway = ISW6bAID;
5687 int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, &securechann, (noauth) ? DCMPlain : DCMMACed, &id, &selectway);
5688 if (res) {
5689 CLIParserFree(ctx);
5690 return res;
5693 uint32_t maxlength = 0;
5694 if (CLIGetUint32Hex(ctx, 13, 0, &maxlength, NULL, 3, "Length parameter must have 3 byte length")) {
5695 CLIParserFree(ctx);
5696 return PM3_EINVARG;
5699 SetAPDULogging(APDULogging);
5700 CLIParserFree(ctx);
5702 res = DesfireSelectAndAuthenticateAppW(&dctx, securechann, selectway, id, noauth, verbose);
5703 if (res != PM3_SUCCESS) {
5704 DropField();
5705 PrintAndLogEx(FAILED, "Select or authentication %s " _RED_("failed") ". Result [%d] %s", DesfireWayIDStr(selectway, id), res, DesfireAuthErrorToStr(res));
5706 return res;
5709 FileList_t FileList = {{0}};
5710 size_t filescount = 0;
5711 bool isopresent = false;
5712 res = DesfireFillFileList(&dctx, FileList, &filescount, &isopresent);
5713 if (res != PM3_SUCCESS) {
5714 DropField();
5715 return res;
5718 PrintAndLogEx(NORMAL, "");
5719 PrintAndLogEx(SUCCESS, "Application " _CYAN_("%s") " have " _GREEN_("%zu") " files", DesfireWayIDStr(selectway, id), filescount);
5721 if (selectway == ISW6bAID)
5722 DesfirePrintAIDFunctions(id);
5724 if (filescount == 0) {
5725 PrintAndLogEx(INFO, "There is no files in the application %s", DesfireWayIDStr(selectway, id));
5726 DropField();
5727 return res;
5730 res = PM3_SUCCESS;
5731 for (int i = 0; i < filescount; i++) {
5732 if (res != PM3_SUCCESS) {
5733 DesfireSetCommMode(&dctx, DCMPlain);
5734 res = DesfireSelectAndAuthenticateAppW(&dctx, securechann, selectway, id, noauth, verbose);
5735 if (res != PM3_SUCCESS) {
5736 DropField();
5737 return res;
5741 PrintAndLogEx(NORMAL, "");
5742 PrintAndLogEx(INFO, "--------------------------------- " _CYAN_("File %02x") " ----------------------------------", FileList[i].fileNum);
5743 PrintAndLogEx(SUCCESS, "File ID : " _GREEN_("%02x"), FileList[i].fileNum);
5744 if (isopresent) {
5745 if (FileList[i].fileISONum != 0)
5746 PrintAndLogEx(SUCCESS, "File ISO ID : %04x", FileList[i].fileISONum);
5747 else
5748 PrintAndLogEx(SUCCESS, "File ISO ID : " _YELLOW_("n/a"));
5750 DesfirePrintFileSettingsExtended(&FileList[i].fileSettings);
5752 res = DesfileReadFileAndPrint(&dctx, FileList[i].fileNum, RFTAuto, 0, 0, maxlength, noauth, verbose);
5755 DropField();
5756 return PM3_SUCCESS;
5759 static int CmdHF14ADesTest(const char *Cmd) {
5760 CLIParserContext *ctx;
5761 CLIParserInit(&ctx, "hf mfdes test",
5762 "Regression crypto tests",
5763 "hf mfdes test");
5765 void *argtable[] = {
5766 arg_param_begin,
5767 arg_param_end
5769 CLIExecWithReturn(ctx, Cmd, argtable, true);
5770 CLIParserFree(ctx);
5771 DesfireTest(true);
5772 return PM3_SUCCESS;
5775 static command_t CommandTable[] = {
5776 {"help", CmdHelp, AlwaysAvailable, "This help"},
5777 {"list", CmdHF14ADesList, AlwaysAvailable, "List DESFire (ISO 14443A) history"},
5778 {"-----------", CmdHelp, IfPm3Iso14443a, "---------------------- " _CYAN_("General") " ----------------------"},
5779 {"auth", CmdHF14ADesAuth, IfPm3Iso14443a, "MIFARE DesFire Authentication"},
5780 {"chk", CmdHF14aDesChk, IfPm3Iso14443a, "Check keys"},
5781 {"default", CmdHF14ADesDefault, IfPm3Iso14443a, "Set defaults for all the commands"},
5782 {"detect", CmdHF14aDesDetect, IfPm3Iso14443a, "Detect key type and tries to find one from the list"},
5783 {"formatpicc", CmdHF14ADesFormatPICC, IfPm3Iso14443a, "Format PICC"},
5784 {"freemem", CmdHF14ADesGetFreeMem, IfPm3Iso14443a, "Get free memory size"},
5785 {"getuid", CmdHF14ADesGetUID, IfPm3Iso14443a, "Get uid from card"},
5786 {"info", CmdHF14ADesInfo, IfPm3Iso14443a, "Tag information"},
5787 {"mad", CmdHF14aDesMAD, IfPm3Iso14443a, "Prints MAD records / files from the card"},
5788 {"setconfig", CmdHF14ADesSetConfiguration, IfPm3Iso14443a, "Set card configuration"},
5789 {"-----------", CmdHelp, IfPm3Iso14443a, "-------------------- " _CYAN_("Applications") " -------------------"},
5790 {"lsapp", CmdHF14ADesLsApp, IfPm3Iso14443a, "Show all applications with files list"},
5791 {"getaids", CmdHF14ADesGetAIDs, IfPm3Iso14443a, "Get Application IDs list"},
5792 {"getappnames", CmdHF14ADesGetAppNames, IfPm3Iso14443a, "Get Applications list"},
5793 {"bruteaid", CmdHF14ADesBruteApps, IfPm3Iso14443a, "Recover AIDs by bruteforce"},
5794 {"createapp", CmdHF14ADesCreateApp, IfPm3Iso14443a, "Create Application"},
5795 {"deleteapp", CmdHF14ADesDeleteApp, IfPm3Iso14443a, "Delete Application"},
5796 {"selectapp", CmdHF14ADesSelectApp, IfPm3Iso14443a, "Select Application ID"},
5797 {"-----------", CmdHelp, IfPm3Iso14443a, "------------------------ " _CYAN_("Keys") " -----------------------"},
5798 {"changekey", CmdHF14ADesChangeKey, IfPm3Iso14443a, "Change Key"},
5799 {"chkeysettings", CmdHF14ADesChKeySettings, IfPm3Iso14443a, "Change Key Settings"},
5800 {"getkeysettings", CmdHF14ADesGetKeySettings, IfPm3Iso14443a, "Get Key Settings"},
5801 {"getkeyversions", CmdHF14ADesGetKeyVersions, IfPm3Iso14443a, "Get Key Versions"},
5802 {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("Files") " -----------------------"},
5803 {"getfileids", CmdHF14ADesGetFileIDs, IfPm3Iso14443a, "Get File IDs list"},
5804 {"getfileisoids", CmdHF14ADesGetFileISOIDs, IfPm3Iso14443a, "Get File ISO IDs list"},
5805 {"lsfiles", CmdHF14ADesLsFiles, IfPm3Iso14443a, "Show all files list"},
5806 {"dump", CmdHF14ADesDump, IfPm3Iso14443a, "Dump all files"},
5807 {"createfile", CmdHF14ADesCreateFile, IfPm3Iso14443a, "Create Standard/Backup File"},
5808 {"createvaluefile", CmdHF14ADesCreateValueFile, IfPm3Iso14443a, "Create Value File"},
5809 {"createrecordfile", CmdHF14ADesCreateRecordFile, IfPm3Iso14443a, "Create Linear/Cyclic Record File"},
5810 {"createmacfile", CmdHF14ADesCreateTrMACFile, IfPm3Iso14443a, "Create Transaction MAC File"},
5811 {"deletefile", CmdHF14ADesDeleteFile, IfPm3Iso14443a, "Delete File"},
5812 {"getfilesettings", CmdHF14ADesGetFileSettings, IfPm3Iso14443a, "Get file settings"},
5813 {"chfilesettings", CmdHF14ADesChFileSettings, IfPm3Iso14443a, "Change file settings"},
5814 {"read", CmdHF14ADesReadData, IfPm3Iso14443a, "Read data from standard/backup/record/value/mac file"},
5815 {"write", CmdHF14ADesWriteData, IfPm3Iso14443a, "Write data to standard/backup/record/value file"},
5816 {"value", CmdHF14ADesValueOperations, IfPm3Iso14443a, "Operations with value file (get/credit/limited credit/debit/clear)"},
5817 {"clearrecfile", CmdHF14ADesClearRecordFile, IfPm3Iso14443a, "Clear record File"},
5818 {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("System") " -----------------------"},
5819 {"test", CmdHF14ADesTest, AlwaysAvailable, "Regression crypto tests"},
5820 {NULL, NULL, NULL, NULL}
5823 static int CmdHelp(const char *Cmd) {
5824 (void)Cmd; // Cmd is not used so far
5825 CmdsHelp(CommandTable);
5826 return PM3_SUCCESS;
5829 int CmdHFMFDes(const char *Cmd) {
5830 clearCommandBuffer();
5831 return CmdsParse(CommandTable, Cmd);