diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 609381ace..3c4cce49a 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -1518,43 +1518,6 @@ static int handler_desfire_getkeysettings(uint8_t *key_settings, uint8_t *num_ke return res; } -/* -static int handler_desfire_getuid(uint8_t *uid) { - if (uid == NULL) { - PrintAndLogEx(DEBUG, "UID=NULL"); - return PM3_EINVARG; - } - sAPDU apdu = {0x90, MFDES_GET_UID, 0x00, 0x00, 0x00, NULL}; //0x51 - uint32_t recv_len = 0; - uint16_t sw = 0; - - // Setup the pre-process to update the IV etc. (not needed in the apdu to send to card) - size_t plen = 1; - uint8_t tmp_data[100] = { 0x00 }; // Note sure on size, but 100 is more then enough - tmp_data[0] = MFDES_GET_UID; - int8_t *p = mifare_cryto_preprocess_data(tag, tmp_data, &plen, 0, MDCM_PLAIN | CMAC_COMMAND); - (void)p; - - // Send request/apdu - int res = send_desfire_cmd(&apdu, false, uid, &recv_len, &sw, 0, true); - - if (res != PM3_SUCCESS) - return res; - - if (sw != status(MFDES_S_OPERATION_OK)) - return PM3_ESOFT; - - // decrypt response - size_t dlen = recv_len; - p = mifare_cryto_postprocess_data(tag, uid, &dlen, CMAC_COMMAND | CMAC_VERIFY | MAC_VERIFY | MDCM_ENCIPHERED); - (void)p; - - DropFieldDesfire(); - - return res; -} -*/ - static int handler_desfire_commit_transaction(void) { sAPDU apdu = {0x90, MFDES_COMMIT_TRANSACTION, 0x00, 0x00, 0x00, NULL}; //0xC7 uint32_t recv_len = 0; @@ -1726,7 +1689,7 @@ static int handler_desfire_filesettings(uint8_t file_id, uint8_t *dest, uint32_t return res; } -static int handler_desfire_createapp(aidhdr_t *aidhdr, bool usename, bool usefid) { +/*static int handler_desfire_createapp(aidhdr_t *aidhdr, bool usename, bool usefid) { if (aidhdr == NULL) return PM3_EINVARG; sAPDU apdu = {0x90, MFDES_CREATE_APPLICATION, 0x00, 0x00, sizeof(aidhdr_t), (uint8_t *)aidhdr}; // 0xCA @@ -1763,22 +1726,7 @@ static int handler_desfire_createapp(aidhdr_t *aidhdr, bool usename, bool usefid DropFieldDesfire(); } return res; -} - -static int handler_desfire_deleteapp(const uint8_t *aid) { - if (aid == NULL) { - return PM3_EINVARG; - } - sAPDU apdu = {0x90, MFDES_DELETE_APPLICATION, 0x00, 0x00, 3, (uint8_t *)aid}; // 0xDA - uint16_t sw = 0; - uint32_t recvlen = 0; - int res = send_desfire_cmd(&apdu, false, NULL, &recvlen, &sw, 0, true); - if (res != PM3_SUCCESS) { - PrintAndLogEx(WARNING, _RED_(" Can't delete aid -> %s"), DesfireGetErrorString(res, &sw)); - DropFieldDesfire(); - } - return res; -} +}*/ static int handler_desfire_credit(mfdes_value_t *value, uint8_t cs) { sAPDU apdu = {0x90, MFDES_CREDIT, 0x00, 0x00, 1 + 4, (uint8_t *)value}; // 0x0C @@ -2312,51 +2260,6 @@ static int desfire_authenticate(int cmdAuthMode, int cmdAuthAlgo, uint8_t *aid, return error; } -/* -static int CmdHF14ADesGetUID(const char *Cmd) { - CLIParserContext *ctx; - CLIParserInit(&ctx, "hf mfdes getuid", - "Get UID from a MIFARE DESfire tag", - "hf mfdes getuid"); - - void *argtable[] = { - arg_param_begin, - arg_param_end - }; - CLIExecWithReturn(ctx, Cmd, argtable, true); - CLIParserFree(ctx); - - uint8_t uid[16] = {0}; - int res = handler_desfire_getuid(uid); - if (res != PM3_SUCCESS) { - DropFieldDesfire(); - PrintAndLogEx(ERR, "Error on getting uid."); - return res; - } - - // This could be done better. by the crc calc checks. - // Extract the Card UID length (needs rework to allow for 10 Byte UID - uint8_t uidlen = 16; - - // Get datalen + by removing padding. - while ((uidlen > 0) && (uid[uidlen - 1] == 0x00)) - uidlen--; - - if (tag->authentication_scheme == AS_LEGACY) - uidlen -= 2; // 2 byte crc - else - uidlen -= 4; // 4 byte crc - - if (uidlen <= 4) // < incase we trimmed a CRC 00 or more - uidlen = 4; - else - uidlen = 7; - - PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(uid, uidlen)); - return res; -} -*/ - static int CmdHF14ADesSelectApp(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfdes selectaid", @@ -2392,190 +2295,6 @@ static int CmdHF14ADesSelectApp(const char *Cmd) { return res; } -static int CmdHF14ADesCreateApp(const char *Cmd) { - CLIParserContext *ctx; - CLIParserInit(&ctx, "hf mfdes createaid", - "Create Application ID", - "hf mfdes createaid -a 123456 -f 1111 -k 0E -l 2E --name Test" - ); - - void *argtable[] = { - arg_param_begin, - arg_strx0("a", "aid", "", "App ID to create as hex bytes (3 hex bytes)"), - arg_strx0("f", "fid", "", "File ID to create"), - arg_strx0("k", "ks1", "", "Key Setting 1 (Application Master Key Settings)"), - arg_strx0("l", "ks2", "", "Key Setting 2"), - arg_str0(NULL, "name", "", "App ISO-4 Name"), - arg_param_end - }; - CLIExecWithReturn(ctx, Cmd, argtable, false); - /* KeySetting 1 (AMK Setting): - 0: Allow change master key - 1: Free Directory list access without master key - 0: AMK auth needed for GetFileSettings and GetKeySettings - 1: No AMK auth needed for GetFileIDs, GetISOFileIDs, GetFileSettings, GetKeySettings - 2: Free create/delete without master key - 0: CreateFile/DeleteFile only with AMK auth - 1: CreateFile/DeleteFile always - 3: Configuration changable - 0: Configuration frozen - 1: Configuration changable if authenticated with AMK (default) - 4-7: ChangeKey Access Rights - 0: Application master key needed (default) - 0x1..0xD: Auth with specific key needed to change any key - 0xE: Auth with the key to be changed (same KeyNo) is necessary to change a key - 0xF: All Keys within this application are frozen - - */ - /* KeySetting 2: - 0..3: Number of keys stored within the application (max. 14 keys) - 4: RFU - 5: Use of 2 byte ISO FID, 0: No, 1: Yes - 6..7: Crypto Method 00: DES/3DES, 01: 3K3DES, 10: AES - Example: - 2E = FID, DES, 14 keys - 6E = FID, 3K3DES, 14 keys - AE = FID, AES, 14 keys - */ - int aidlength = 3; - uint8_t aid[3] = {0}; - CLIGetHexWithReturn(ctx, 1, aid, &aidlength); - - int fidlength = 2; - uint8_t fid[2] = {0}; - CLIGetHexWithReturn(ctx, 2, fid, &fidlength); - - int keylen1 = 1; - uint8_t keysetting1[1] = {0}; - CLIGetHexWithReturn(ctx, 3, keysetting1, &keylen1); - - int keylen2 = 1; - uint8_t keysetting2[1] = {0}; - CLIGetHexWithReturn(ctx, 4, keysetting2, &keylen2); - - int namelen = 16; - uint8_t name[16] = {0}; - CLIGetStrWithReturn(ctx, 5, name, &namelen); - CLIParserFree(ctx); - - swap24(aid); - swap16(fid); - - if (aidlength != 3) { - PrintAndLogEx(ERR, "AID must have 3 bytes length"); - return PM3_EINVARG; - } - - if (fidlength != 2 && fidlength != 0) { - PrintAndLogEx(ERR, "FID must have 2 bytes length"); - return PM3_EINVARG; - } - - bool usefid = (fidlength != 0); - - if (keylen1 != 1) { - PrintAndLogEx(ERR, "Keysetting1 must have 1 byte length"); - return PM3_EINVARG; - } - - if (keylen2 != 1) { - PrintAndLogEx(ERR, "Keysetting2 must have 1 byte length"); - return PM3_EINVARG; - } - - if (namelen > 16) { - PrintAndLogEx(ERR, "Name has a max. of 16 bytes length"); - return PM3_EINVARG; - } - bool usename = true; - if (namelen == 0) usename = false; - - //90 ca 00 00 0e 3cb849 09 22 10e1 d27600 00850101 00 - /*char name[]="Test"; - uint8_t aid[]={0x12,0x34,0x56}; - uint8_t fid[]={0x11,0x22}; - uint8_t keysetting1=0xEE; - uint8_t keysetting2=0xEE;*/ - - if (memcmp(aid, "\x00\x00\x00", 3) == 0) { - PrintAndLogEx(WARNING, _RED_(" Creating root aid 000000 is forbidden")); - return PM3_ESOFT; - } - - aidhdr_t aidhdr; - memcpy(aidhdr.aid, aid, sizeof(aid)); - aidhdr.keysetting1 = keysetting1[0]; - aidhdr.keysetting2 = keysetting2[0]; - - if (usefid) - memcpy(aidhdr.fid, fid, sizeof(aidhdr.fid)); - - if (usename) - memcpy(aidhdr.name, name, sizeof(aidhdr.name)); - - PrintAndLogEx(INFO, "Creating AID using:"); - PrintAndLogEx(INFO, "AID %s", sprint_hex_inrow(aidhdr.aid, sizeof(aidhdr.aid))); - PrintAndLogEx(INFO, "Key set1 0x%02X", aidhdr.keysetting1); - PrintAndLogEx(INFO, "Key Set2 0x%02X", aidhdr.keysetting2); - if (usefid) - PrintAndLogEx(INFO, "FID %s", sprint_hex_inrow(aidhdr.fid, sizeof(aidhdr.fid))); - if (usename) - PrintAndLogEx(INFO, "DF Name %s", aidhdr.name); - - /* - uint8_t rootaid[3] = {0x00, 0x00, 0x00}; - int res = handler_desfire_select_application(rootaid); - if (res != PM3_SUCCESS) { - DropFieldDesfire(); - return res; - } - */ - - int res = handler_desfire_createapp(&aidhdr, usename, usefid); - DropFieldDesfire(); - if (res == PM3_SUCCESS) { - PrintAndLogEx(SUCCESS, "Successfully created aid."); - } - return res; -} - -static int CmdHF14ADesDeleteApp(const char *Cmd) { - CLIParserContext *ctx; - CLIParserInit(&ctx, "hf mfdes deleteaid", - "Delete Application ID", - "hf mfdes deleteaid -a 123456" - ); - - void *argtable[] = { - arg_param_begin, - arg_strx0("a", "aid", "", "App ID to delete (3 hex bytes, big endian)"), - arg_param_end - }; - CLIExecWithReturn(ctx, Cmd, argtable, false); - int aidlength = 3; - uint8_t aid[3] = {0}; - CLIGetHexWithReturn(ctx, 1, aid, &aidlength); - CLIParserFree(ctx); - swap24(aid); - if (aidlength != 3) { - PrintAndLogEx(ERR, "AID must have 3 bytes length."); - return PM3_EINVARG; - } - - if (memcmp(aid, "\x00\x00\x00", 3) == 0) { - PrintAndLogEx(WARNING, _RED_(" Deleting root aid 000000 is forbidden.")); - return PM3_ESOFT; - } - - int res = handler_desfire_deleteapp(aid); - DropFieldDesfire(); - - if (res == PM3_SUCCESS) { - PrintAndLogEx(SUCCESS, "Successfully deleted aid."); - } - return res; -} - static int selectfile(uint8_t *aid, uint8_t fileno, uint8_t *cs) { if (handler_desfire_select_application(aid) != PM3_SUCCESS) { PrintAndLogEx(ERR, _RED_(" Couldn't select aid.")); @@ -5115,8 +4834,8 @@ static int CmdDesGetSessionParameters(CLIParserContext *ctx, DesfireContext *dct static int CmdHF14ADesDefault(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfdes default", - "Get Application IDs, ISO IDs and DF names from card. Master key needs to be provided.", - "hf mfdes getappnames -n 0 -t des -k 0000000000000000 -f none -> execute with default factory setup"); + "Set default parameters for access to desfire card.", + "hf mfdes default -n 0 -t des -k 0000000000000000 -f none -> save to the default parameters"); void *argtable[] = { arg_param_begin, @@ -5166,12 +4885,271 @@ static int CmdHF14ADesDefault(const char *Cmd) { return PM3_SUCCESS; } +static int CmdHF14ADesCreateApp(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mfdes createapp", + "Create application. Master key needs to be provided.", + "option rawdata have priority over the rest settings, and options ks1 and ks2 have priority over corresponded key settings\n" + "\n"\ + "KeySetting 1 (AMK Setting, ks1):\n"\ + " 0: Allow change master key. 1 - allow, 0 - frozen\n"\ + " 1: Free Directory list access without master key\n"\ + " 0: AMK auth needed for GetFileSettings and GetKeySettings\n"\ + " 1: No AMK auth needed for GetFileIDs, GetISOFileIDs, GetFileSettings, GetKeySettings\n"\ + " 2: Free create/delete without master key\n"\ + " 0: CreateFile/DeleteFile only with AMK auth\n"\ + " 1: CreateFile/DeleteFile always\n"\ + " 3: Configuration changable\n"\ + " 0: Configuration frozen\n"\ + " 1: Configuration changable if authenticated with AMK (default)\n"\ + " 4-7: ChangeKey Access Rights\n"\ + " 0: Application master key needed (default)\n"\ + " 0x1..0xD: Auth with specific key needed to change any key\n"\ + " 0xE: Auth with the key to be changed (same KeyNo) is necessary to change a key\n"\ + " 0xF: All Keys within this application are frozen\n"\ + "\n"\ + "KeySetting 2 (ks2):\n"\ + " 0..3: Number of keys stored within the application (max. 14 keys)\n"\ + " 4: ks3 is present\n"\ + " 5: Use of 2 byte ISO FID, 0: No, 1: Yes\n"\ + " 6..7: Crypto Method 00: DES/2TDEA, 01: 3TDEA, 10: AES, 11: RFU\n"\ + " Example:\n"\ + " 2E = with FID, DES/2TDEA, 14 keys\n"\ + " 6E = with FID, 3TDEA, 14 keys\n"\ + " AE = with FID, AES, 14 keys\n"\ + "\n"\ + "hf mfdes createapp --rawdata 5634122F2E4523616964313233343536 -> execute create by rawdata\n"\ + "hf mfdes createapp --aid 123456 --fid 2345 --dfname aid123456 -> app aid, iso file id, and iso df name is specified\n" + "hf mfdes createapp --aid 123456 --fid 2345 --dfname aid123456 --dstalgo aes -> with algorithm for key AES"); + + void *argtable[] = { + arg_param_begin, + arg_lit0("a", "apdu", "show APDU requests and responses"), + arg_lit0("v", "verbose", "show technical data"), + arg_int0("n", "keyno", "", "Key number"), + arg_str0("t", "algo", "", "Crypt algo: DES, 2TDEA, 3TDEA, AES"), + arg_str0("k", "key", "", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"), + arg_str0("f", "kdf", "", "Key Derivation Function (KDF): None, AN10922, Gallagher"), + arg_str0("i", "kdfi", "", "KDF input (HEX 1-31 bytes)"), + arg_str0("m", "cmode", "", "Communicaton mode: plain/mac/encrypt"), + arg_str0("c", "ccset", "", "Communicaton command set: native/niso/iso"), + arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2"), + arg_str0(NULL, "rawdata", "", "Rawdata that sends to command"), + arg_str0(NULL, "aid", "", "Application ID for create. Mandatory. (3 hex bytes, big endian)"), + arg_str0(NULL, "fid", "", "ISO file ID. Forbidden values: 0000 3F00, 3FFF, FFFF. (2 hex bytes, big endian). If specified - enable iso file id over all the files in the app."), + arg_str0(NULL, "dfname", "", "ISO DF Name 1..16 chars string"), + arg_str0(NULL, "ks1", "", "Key settings 1 (HEX 1 byte). Application Master Key Settings. default 0x2f"), + arg_str0(NULL, "ks2", "", "Key settings 2 (HEX 1 byte). default 0x0e"), + arg_str0(NULL, "dstalgo", "", "Application key crypt algo: DES, 2TDEA, 3TDEA, AES. default DES"), + arg_int0(NULL, "numkeys", "", "Keys count. 0x00..0x0e. default 0x0e"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + + bool APDULogging = arg_get_lit(ctx, 1); + bool verbose = arg_get_lit(ctx, 2); + + DesfireContext dctx; + int securechann = defaultSecureChannel; + uint32_t appid = 0x000000; + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 12, &securechann, DCMPlain, &appid); + if (res) { + CLIParserFree(ctx); + return res; + } + + uint8_t rawdata[250] = {0}; + int rawdatalen = sizeof(rawdata); + CLIGetHexWithReturn(ctx, 11, rawdata, &rawdatalen); + + uint32_t fileid = 0x0000; + res = arg_get_u32_hexstr_def_nlen(ctx, 13, 0x0000, &fileid, 2, true); + bool fileidpresent = (res == 1); + if (res == 2) { + PrintAndLogEx(ERR, "ISO file ID must have 2 bytes length"); + return PM3_EINVARG; + } + + uint8_t dfname[250] = {0}; + int dfnamelen = 16; + CLIGetStrWithReturn(ctx, 14, dfname, &dfnamelen); + + uint32_t ks1 = 0x2f; + res = arg_get_u32_hexstr_def_nlen(ctx, 15, 0x2f, &ks1, 1, true); + if (res == 2) { + PrintAndLogEx(ERR, "Key settings 1 must have 1 byte length"); + return PM3_EINVARG; + } + + uint32_t ks2 = 0x0e; + res = arg_get_u32_hexstr_def_nlen(ctx, 16, 0x0e, &ks2, 1, true); + bool ks2present = (res == 1); + if (res == 2) { + PrintAndLogEx(ERR, "Key settings 2 must have 1 byte length"); + return PM3_EINVARG; + } + + int dstalgo = T_DES; + if (CLIGetOptionList(arg_get_str(ctx, 17), DesfireAlgoOpts, &dstalgo)) + return PM3_ESOFT; + + int keycount = arg_get_int_def(ctx, 18, 0x0e); + + SetAPDULogging(APDULogging); + CLIParserFree(ctx); + + if (rawdatalen == 0 && appid == 0x000000) { + PrintAndLogEx(ERR, "Creating the root aid (0x000000) is " _RED_("forbidden")); + return PM3_ESOFT; + } + + if (rawdatalen == 0 && (fileidpresent || (ks2 & 0x20) != 0) && fileid == 0x0000) { + PrintAndLogEx(ERR, "Creating the application with ISO file ID 0x0000 is " _RED_("forbidden")); + return PM3_ESOFT; + } + + if (keycount > 0x0e || keycount < 1) { + PrintAndLogEx(ERR, "Key count must be in the range 1..14"); + return PM3_ESOFT; + } + + if (dfnamelen > 16) { + PrintAndLogEx(ERR, "DF name must be a maximum of 16 bytes in length"); + return PM3_EINVARG; + } + + res = DesfireSelectAndAuthenticate(&dctx, securechann, 0x000000, verbose); + if (res != PM3_SUCCESS) { + DropField(); + return res; + } + + uint8_t data[250] = {0}; + size_t datalen = 0; + if (rawdatalen > 0) { + memcpy(data, rawdata, rawdatalen); + datalen = rawdatalen; + } else { + DesfireAIDUintToByte(appid, &data[0]); + data[3] = ks1 & 0xff; + data[4] = ks2 & 0xff; + + if (!ks2present) { + if (keycount > 0) { + data[4] &= 0xf0; + data[4] |= keycount & 0x0f; + } + uint8_t kt = DesfireKeyAlgoToType(dstalgo); + data[4] &= 0x3f; + data[4] |= (kt & 0x03) << 6; + } + + datalen = 5; + if (fileidpresent || (data[4] & 0x20) != 0) { + data[5] = fileid & 0xff; + data[6] = (fileid >> 8) & 0xff; + data[4] |= 0x20; // set bit FileID in the ks2 + memcpy(&data[7], dfname, dfnamelen); + datalen = 7 + dfnamelen; + } + } + + if (verbose) { + PrintAndLogEx(INFO, "---------------------------"); + PrintAndLogEx(INFO, _CYAN_("Creating Application using:")); + PrintAndLogEx(INFO, "AID 0x%02X%02X%02X", data[2], data[1], data[0]); + PrintAndLogEx(INFO, "Key Set 1 0x%02X", data[3]); + PrintAndLogEx(INFO, "Key Set 2 0x%02X", data[4]); + PrintAndLogEx(INFO, "ISO file ID %s", (data[4] & 0x20) ? "enabled" : "disabled"); + if ((data[4] & 0x20)) { + PrintAndLogEx(INFO, "FID 0x%02x%02x", data[6], data[5]); + PrintAndLogEx(INFO, "DF Name[%02d] %s\n", strnlen((char *)&data[7], 16), (char *)&data[7]); + } + PrintKeySettings(data[3], data[4], true, true); + PrintAndLogEx(INFO, "---------------------------"); + } + + res = DesfireCreateApplication(&dctx, data, datalen); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Desfire CreateApplication command " _RED_("error") ". Result: %d", res); + DropField(); + return PM3_ESOFT; + } + + PrintAndLogEx(SUCCESS, "Desfire application %06x successfully " _GREEN_("created"), appid); + + DropField(); + return PM3_SUCCESS; +} + +static int CmdHF14ADesDeleteApp(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mfdes deleteapp", + "Delete application by its 3-byte AID. Master key needs to be provided. ", + "hf mfdes deleteapp --aid 123456 -> execute with default factory setup"); + + void *argtable[] = { + arg_param_begin, + arg_lit0("a", "apdu", "show APDU requests and responses"), + arg_lit0("v", "verbose", "show technical data"), + arg_int0("n", "keyno", "", "Key number"), + arg_str0("t", "algo", "", "Crypt algo: DES, 2TDEA, 3TDEA, AES"), + arg_str0("k", "key", "", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"), + arg_str0("f", "kdf", "", "Key Derivation Function (KDF): None, AN10922, Gallagher"), + arg_str0("i", "kdfi", "", "KDF input (HEX 1-31 bytes)"), + arg_str0("m", "cmode", "", "Communicaton mode: plain/mac/encrypt"), + arg_str0("c", "ccset", "", "Communicaton command set: native/niso/iso"), + arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2"), + arg_str0(NULL, "aid", "", "Application ID of delegated application (3 hex bytes, big endian)"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + + bool APDULogging = arg_get_lit(ctx, 1); + bool verbose = arg_get_lit(ctx, 2); + + DesfireContext dctx; + int securechann = defaultSecureChannel; + uint32_t appid = 0x000000; + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, &securechann, DCMPlain, &appid); + if (res) { + CLIParserFree(ctx); + return res; + } + + SetAPDULogging(APDULogging); + CLIParserFree(ctx); + + if (appid == 0x000000) { + PrintAndLogEx(WARNING, "Deleting the root aid (0x000000) is " _RED_("forbidden")); + return PM3_ESOFT; + } + + res = DesfireSelectAndAuthenticate(&dctx, securechann, appid, verbose); + if (res != PM3_SUCCESS) { + DropField(); + return res; + } + + res = DesfireDeleteApplication(&dctx, appid); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Desfire DeleteApplication command " _RED_("error") ". Result: %d", res); + DropField(); + return PM3_ESOFT; + } + + PrintAndLogEx(SUCCESS, "Desfire application %06x " _GREEN_("deleted"), appid); + + DropField(); + return PM3_SUCCESS; +} + static int CmdHF14ADesGetUID(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfdes getuid", "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. Master key needs to be provided. ", "hf mfdes getuid -> execute with default factory setup"); - + void *argtable[] = { arg_param_begin, arg_lit0("a", "apdu", "show APDU requests and responses"), @@ -5213,7 +5191,7 @@ static int CmdHF14ADesGetUID(const char *Cmd) { res = DesfireGetUID(&dctx, buf, &buflen); if (res != PM3_SUCCESS) { - PrintAndLogEx(ERR, "Desfire DesfireGetUID command " _RED_("error") ". Result: %d", res); + PrintAndLogEx(ERR, "Desfire GetUID command " _RED_("error") ". Result: %d", res); DropField(); return PM3_ESOFT; } @@ -5229,7 +5207,7 @@ static int CmdHF14ADesFormatPICC(const char *Cmd) { CLIParserInit(&ctx, "hf mfdes formatpicc", "Format card. Can be done only if enabled in the configuration. Master key needs to be provided. ", "hf mfdes formatpicc -> execute with default factory setup"); - + void *argtable[] = { arg_param_begin, arg_lit0("a", "apdu", "show APDU requests and responses"), @@ -5270,7 +5248,7 @@ static int CmdHF14ADesFormatPICC(const char *Cmd) { res = DesfireFormatPICC(&dctx); if (res != PM3_SUCCESS) { - PrintAndLogEx(ERR, "Desfire DesfireFormatPICC command " _RED_("error") ". Result: %d", res); + PrintAndLogEx(ERR, "Desfire FormatPICC command " _RED_("error") ". Result: %d", res); DropField(); return PM3_ESOFT; } @@ -5284,9 +5262,9 @@ static int CmdHF14ADesFormatPICC(const char *Cmd) { static int CmdHF14ADesGetFreeMem(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfdes getfreemem", - "Get card's free memory. Can be doe with ot without authentication. Master key may be provided. ", + "Get card's free memory. Can be done with ot without authentication. Master key may be provided.", "hf mfdes getfreemem -> execute with default factory setup"); - + void *argtable[] = { arg_param_begin, arg_lit0("a", "apdu", "show APDU requests and responses"), @@ -5326,7 +5304,7 @@ static int CmdHF14ADesGetFreeMem(const char *Cmd) { PrintAndLogEx(ERR, "Desfire select " _RED_("error") "."); DropField(); return res; - } + } } else { res = DesfireSelectAndAuthenticate(&dctx, securechann, 0x000000, verbose); if (res != PM3_SUCCESS) { @@ -5339,7 +5317,7 @@ static int CmdHF14ADesGetFreeMem(const char *Cmd) { res = DesfireGetFreeMem(&dctx, &freemem); if (res != PM3_SUCCESS) { - PrintAndLogEx(ERR, "Desfire DesfireGetFreeMem command " _RED_("error") ". Result: %d", res); + PrintAndLogEx(ERR, "Desfire GetFreeMem command " _RED_("error") ". Result: %d", res); DropField(); return PM3_ESOFT; } @@ -5352,10 +5330,10 @@ static int CmdHF14ADesGetFreeMem(const char *Cmd) { static int CmdHF14ADesChKeySettings(const char *Cmd) { CLIParserContext *ctx; - CLIParserInit(&ctx, "hf mfdes chkeysetings", - "Change key settings for card level or application level. WARNING: card level changes may block card!", - "hf mfdes chkeysetings -d 0e -> set picc key settings with default key/channel setup\n"\ - "hf mfdes chkeysetings --aid 123456 -d 0e -> set app 123456 key settings with default key/channel setup"); + CLIParserInit(&ctx, "hf mfdes chkeysettings", + "Change key settings for card level or application level. WARNING: card level changes may block the card!", + "hf mfdes chkeysettings -d 0f -> set picc key settings with default key/channel setup\n"\ + "hf mfdes chkeysettings --aid 123456 -d 0f -> set app 123456 key settings with default key/channel setup"); void *argtable[] = { arg_param_begin, @@ -5373,7 +5351,7 @@ static int CmdHF14ADesChKeySettings(const char *Cmd) { arg_str0("d", "data", "", "Key settings (HEX 1 byte)"), arg_param_end }; - CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIExecWithReturn(ctx, Cmd, argtable, false); bool APDULogging = arg_get_lit(ctx, 1); bool verbose = arg_get_lit(ctx, 2); @@ -5388,7 +5366,7 @@ static int CmdHF14ADesChKeySettings(const char *Cmd) { } uint32_t ksett32 = 0; - res = arg_get_u32_hexstr_def_nlen(ctx, 12, 0x000000, &ksett32, 1, false); + res = arg_get_u32_hexstr_def_nlen(ctx, 12, 0x0f, &ksett32, 1, false); if (res == 0) { CLIParserFree(ctx); return PM3_ESOFT; @@ -5413,10 +5391,10 @@ static int CmdHF14ADesChKeySettings(const char *Cmd) { return res; } - uint8_t keysett = ksett32 & 0x0f; + uint8_t keysett = ksett32 & 0xff; res = DesfireChangeKeySettings(&dctx, &keysett, 1); if (res != PM3_SUCCESS) { - PrintAndLogEx(ERR, "Desfire DesfireChangeKeySettings command " _RED_("error") ". Result: %d", res); + PrintAndLogEx(ERR, "Desfire ChangeKeySettings command " _RED_("error") ". Result: %d", res); DropField(); return PM3_ESOFT; } @@ -5505,7 +5483,7 @@ static int CmdHF14ADesGetKeyVersions(const char *Cmd) { uint8_t buf[APDU_RES_LEN] = {0}; size_t buflen = 0; - + uint8_t data[2] = {0}; data[0] = keynum32 & 0xff; if (keysetpresent) { @@ -5515,13 +5493,13 @@ static int CmdHF14ADesGetKeyVersions(const char *Cmd) { res = DesfireGetKeyVersion(&dctx, data, (keysetpresent) ? 2 : 1, buf, &buflen); if (res != PM3_SUCCESS) { - PrintAndLogEx(ERR, "Desfire DesfireGetKeyVersion command " _RED_("error") ". Result: %d", res); + PrintAndLogEx(ERR, "Desfire GetKeyVersion command " _RED_("error") ". Result: %d", res); DropField(); return PM3_ESOFT; } if (verbose) - PrintAndLogEx(INFO, "DesfireGetKeyVersion[%zu]: %s", buflen, sprint_hex(buf, buflen)); + PrintAndLogEx(INFO, "GetKeyVersion[%zu]: %s", buflen, sprint_hex(buf, buflen)); if (buflen > 0) { PrintAndLogEx(INFO, "----------------------- " _CYAN_("Key Versions") " -----------------------"); @@ -5530,17 +5508,17 @@ static int CmdHF14ADesGetKeyVersions(const char *Cmd) { } else { PrintAndLogEx(INFO, "No key versions returned."); } - + DropField(); return PM3_SUCCESS; } static int CmdHF14ADesGetKeySettings(const char *Cmd) { CLIParserContext *ctx; - CLIParserInit(&ctx, "hf mfdes getkeysetings", + CLIParserInit(&ctx, "hf mfdes getkeysettings", "Get key settings for card level or application level.", - "hf mfdes getkeysetings -> get picc key settings with default key/channel setup\n"\ - "hf mfdes getkeysetings --aid 123456 -> get app 123456 key settings with default key/channel setup"); + "hf mfdes getkeysettings -> get picc key settings with default key/channel setup\n"\ + "hf mfdes getkeysettings --aid 123456 -> get app 123456 key settings with default key/channel setup"); void *argtable[] = { arg_param_begin, @@ -5585,16 +5563,16 @@ static int CmdHF14ADesGetKeySettings(const char *Cmd) { res = DesfireGetKeySettings(&dctx, buf, &buflen); if (res != PM3_SUCCESS) { - PrintAndLogEx(ERR, "Desfire DesfireGetKeySettings command " _RED_("error") ". Result: %d", res); + PrintAndLogEx(ERR, "Desfire GetKeySettings command " _RED_("error") ". Result: %d", res); DropField(); return PM3_ESOFT; } if (verbose) - PrintAndLogEx(INFO, "DesfireGetKeySettings[%zu]: %s", buflen, sprint_hex(buf, buflen)); + PrintAndLogEx(INFO, "GetKeySettings[%zu]: %s", buflen, sprint_hex(buf, buflen)); if (buflen < 2) { - PrintAndLogEx(ERR, "Command DesfireGetKeySettings returned wrong length: %zu", buflen); + PrintAndLogEx(ERR, "Command GetKeySettings returned wrong length: %zu", buflen); DropField(); return PM3_ESOFT; } @@ -5617,7 +5595,7 @@ static int CmdHF14ADesGetKeySettings(const char *Cmd) { static int CmdHF14ADesGetAIDs(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfdes getaids", - "Get Application IDs list from card. Master key needs to be provided.", + "Get Application IDs list from card. Master key needs to be provided or flag --no-auth set.", "hf mfdes getaids -n 0 -t des -k 0000000000000000 -f none -> execute with default factory setup"); void *argtable[] = { @@ -5632,12 +5610,14 @@ static int CmdHF14ADesGetAIDs(const char *Cmd) { arg_str0("m", "cmode", "", "Communicaton mode: plain/mac/encrypt"), arg_str0("c", "ccset", "", "Communicaton command set: native/niso/iso"), arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2"), + arg_lit0(NULL, "no-auth", "execute without authentication"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); bool APDULogging = arg_get_lit(ctx, 1); bool verbose = arg_get_lit(ctx, 2); + bool noauth = arg_get_lit(ctx, 11); DesfireContext dctx; int securechann = defaultSecureChannel; @@ -5650,10 +5630,19 @@ static int CmdHF14ADesGetAIDs(const char *Cmd) { SetAPDULogging(APDULogging); CLIParserFree(ctx); - res = DesfireSelectAndAuthenticate(&dctx, securechann, 0x000000, verbose); - if (res != PM3_SUCCESS) { - DropField(); - return res; + if (noauth) { + res = DesfireSelectAIDHex(&dctx, 0x000000, false, 0); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Desfire select " _RED_("error") "."); + DropField(); + return res; + } + } else { + res = DesfireSelectAndAuthenticate(&dctx, securechann, 0x000000, verbose); + if (res != PM3_SUCCESS) { + DropField(); + return res; + } } uint8_t buf[APDU_RES_LEN] = {0}; @@ -5681,7 +5670,7 @@ static int CmdHF14ADesGetAIDs(const char *Cmd) { static int CmdHF14ADesGetAppNames(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfdes getappnames", - "Get Application IDs, ISO IDs and DF names from card. Master key needs to be provided.", + "Get Application IDs, ISO IDs and DF names from card. Master key needs to be provided or flag --no-auth set.", "hf mfdes getappnames -n 0 -t des -k 0000000000000000 -f none -> execute with default factory setup"); void *argtable[] = { @@ -5696,12 +5685,14 @@ static int CmdHF14ADesGetAppNames(const char *Cmd) { arg_str0("m", "cmode", "", "Communicaton mode: plain/mac/encrypt"), arg_str0("c", "ccset", "", "Communicaton command set: native/niso/iso"), arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2"), + arg_lit0(NULL, "no-auth", "execute without authentication"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); bool APDULogging = arg_get_lit(ctx, 1); bool verbose = arg_get_lit(ctx, 2); + bool noauth = arg_get_lit(ctx, 11); DesfireContext dctx; int securechann = defaultSecureChannel; @@ -5714,13 +5705,19 @@ static int CmdHF14ADesGetAppNames(const char *Cmd) { SetAPDULogging(APDULogging); CLIParserFree(ctx); - if (verbose) - DesfirePrintContext(&dctx); - - res = DesfireSelectAndAuthenticate(&dctx, securechann, 0x000000, verbose); - if (res != PM3_SUCCESS) { - DropField(); - return res; + if (noauth) { + res = DesfireSelectAIDHex(&dctx, 0x000000, false, 0); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Desfire select " _RED_("error") "."); + DropField(); + return res; + } + } else { + res = DesfireSelectAndAuthenticate(&dctx, securechann, 0x000000, verbose); + if (res != PM3_SUCCESS) { + DropField(); + return res; + } } uint8_t buf[APDU_RES_LEN] = {0}; @@ -5729,7 +5726,7 @@ static int CmdHF14ADesGetAppNames(const char *Cmd) { // result bytes: 3, 2, 1-16. total record size = 24 res = DesfireGetDFList(&dctx, buf, &buflen); if (res != PM3_SUCCESS) { - PrintAndLogEx(ERR, "Desfire DesfireGetDFList command " _RED_("error") ". Result: %d", res); + PrintAndLogEx(ERR, "Desfire GetDFList command " _RED_("error") ". Result: %d", res); DropField(); return PM3_ESOFT; } @@ -5771,13 +5768,13 @@ static command_t CommandTable[] = { // {"mad", CmdHF14aDesMAD, IfPm3Iso14443a, "Prints MAD records from card"}, {"-----------", CmdHelp, IfPm3Iso14443a, "------------------------ " _CYAN_("Keys") " -----------------------"}, {"changekey", CmdHF14ADesChangeKey, IfPm3Iso14443a, "Change Key"}, - {"chkeysetings", CmdHF14ADesChKeySettings, IfPm3Iso14443a, "[new]Change Key Settings"}, - {"getkeysetings", CmdHF14ADesGetKeySettings, IfPm3Iso14443a, "[new]Get Key Settings"}, + {"chkeysettings", CmdHF14ADesChKeySettings, IfPm3Iso14443a, "[new]Change Key Settings"}, + {"getkeysettings", CmdHF14ADesGetKeySettings, IfPm3Iso14443a, "[new]Get Key Settings"}, {"getkeyversions", CmdHF14ADesGetKeyVersions, IfPm3Iso14443a, "[new]Get Key Versions"}, {"-----------", CmdHelp, IfPm3Iso14443a, "-------------------- " _CYAN_("Applications") " -------------------"}, {"bruteaid", CmdHF14ADesBruteApps, IfPm3Iso14443a, "Recover AIDs by bruteforce"}, - {"createaid", CmdHF14ADesCreateApp, IfPm3Iso14443a, "Create Application ID"}, - {"deleteaid", CmdHF14ADesDeleteApp, IfPm3Iso14443a, "Delete Application ID"}, + {"createapp", CmdHF14ADesCreateApp, IfPm3Iso14443a, "[new]Create Application"}, + {"deleteapp", CmdHF14ADesDeleteApp, IfPm3Iso14443a, "[new]Delete Application"}, {"selectaid", CmdHF14ADesSelectApp, IfPm3Iso14443a, "Select Application ID"}, {"getaids", CmdHF14ADesGetAIDs, IfPm3Iso14443a, "[new]Get Application IDs list"}, {"getappnames", CmdHF14ADesGetAppNames, IfPm3Iso14443a, "[new]Get Applications list"}, diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index f1328a568..b0c4d9b8d 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -624,7 +624,7 @@ int DesfireSelectAndAuthenticate(DesfireContext *dctx, DesfireSecureChannel secu } else { return PM3_ESOFT; } - + return PM3_SUCCESS; } @@ -904,7 +904,7 @@ int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel static int DesfireCommandEx(DesfireContext *dctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *resp, size_t *resplen, int checklength, size_t splitbysize) { if (resplen) *resplen = 0; - + uint8_t respcode = 0xff; uint8_t xresp[257] = {0}; size_t xresplen = 0; @@ -919,7 +919,7 @@ static int DesfireCommandEx(DesfireContext *dctx, uint8_t cmd, uint8_t *data, si if (resplen) *resplen = xresplen; if (resp) - memcpy(resp, xresp, xresplen); + memcpy(resp, xresp, (splitbysize == 0) ? xresplen : xresplen * splitbysize); return PM3_SUCCESS; } @@ -945,9 +945,9 @@ int DesfireFormatPICC(DesfireContext *dctx) { int DesfireGetFreeMem(DesfireContext *dctx, uint32_t *freemem) { *freemem = 0; - + uint8_t resp[257] = {0}; - size_t resplen = 0; + size_t resplen = 0; int res = DesfireCommandRxData(dctx, MFDES_GET_FREE_MEMORY, resp, &resplen, 3); if (res == PM3_SUCCESS) *freemem = DesfireAIDByteToUint(resp); @@ -988,6 +988,19 @@ int DesfireChangeKeySettings(DesfireContext *dctx, uint8_t *data, size_t len) { return DesfireCommandTxData(dctx, MFDES_CHANGE_KEY_SETTINGS, data, len); } +uint8_t DesfireKeyAlgoToType(DesfireCryptoAlgorythm keyType) { + switch (keyType) { + case T_DES: + return 0x00; + case T_3DES: + return 0x00; + case T_3K3DES: + return 0x01; + case T_AES: + return 0x02; + } + return 0; +} static void PrintKeyType(uint8_t keytype) { switch (keytype) { case 00: @@ -1049,6 +1062,9 @@ static void PrintKeySettingsApp(uint8_t keysettings, uint8_t numkeys, bool print if (print2ndbyte) { PrintKeyType(numkeys >> 6); PrintAndLogEx(SUCCESS, "key count: %d", numkeys & 0x0f); + if (numkeys & 0x20) + PrintAndLogEx(SUCCESS, "iso file id: enabled"); + PrintAndLogEx(SUCCESS, ""); } } diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index acc7bd7af..c6b092b59 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -53,5 +53,6 @@ int DesfireGetKeyVersion(DesfireContext *dctx, uint8_t *data, size_t len, uint8_ int DesfireGetKeySettings(DesfireContext *dctx, uint8_t *resp, size_t *resplen); int DesfireChangeKeySettings(DesfireContext *dctx, uint8_t *data, size_t len); void PrintKeySettings(uint8_t keysettings, uint8_t numkeys, bool applevel, bool print2ndbyte); +uint8_t DesfireKeyAlgoToType(DesfireCryptoAlgorythm keyType); #endif // __DESFIRECORE_H