//----------------------------------------------------------------------------- // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // See LICENSE.txt for the text of the license. //----------------------------------------------------------------------------- // NFC commands //----------------------------------------------------------------------------- #include "cmdnfc.h" #include "nfc/ndef.h" #include "cliparser.h" #include "ui.h" #include "cmdparser.h" #include "cmdhf14a.h" #include "cmdhf14b.h" #include "cmdhfmf.h" #include "cmdhfmfp.h" #include "cmdhfmfu.h" #include "cmdhfst25ta.h" #include "cmdhfthinfilm.h" #include "cmdhftopaz.h" #include "cmdnfc.h" #include "fileutils.h" #include "mifare/mifaredefault.h" #include "mifare/mad.h" void print_type4_cc_info(uint8_t *d, uint8_t n) { if (n < 0x0F) { PrintAndLogEx(WARNING, "Not enough bytes read from CC file"); return; } PrintAndLogEx(NORMAL, ""); PrintAndLogEx(SUCCESS, "------------ " _CYAN_("Capability Container file") " ------------"); PrintAndLogEx(SUCCESS, " Version... %s ( " _GREEN_("0x%02X") " )", (d[2] == 0x20) ? "v2.0" : "v1.0", d[2]); PrintAndLogEx(SUCCESS, " Len....... %u bytes ( " _GREEN_("0x%02X") " )", d[1], d[1]); uint16_t maxr = (d[3] << 8 | d[4]); PrintAndLogEx(SUCCESS, " Max bytes read %u bytes ( 0x%04X )", maxr, maxr); uint16_t maxw = (d[5] << 8 | d[6]); PrintAndLogEx(SUCCESS, " Max bytes write %u bytes ( 0x%04X )", maxw, maxw); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(SUCCESS, " NDEF file control TLV"); PrintAndLogEx(SUCCESS, " (t) type of file.... %02X", d[7]); PrintAndLogEx(SUCCESS, " (v) ................ %02X", d[8]); PrintAndLogEx(SUCCESS, " file id............. %02X%02X", d[9], d[10]); uint16_t maxndef = (d[11] << 8 | d[12]); PrintAndLogEx(SUCCESS, " Max NDEF filesize... %u bytes ( 0x%04X )", maxndef, maxndef); PrintAndLogEx(SUCCESS, " " _CYAN_("Access rights")); PrintAndLogEx(SUCCESS, " read ( %02X ) protection: %s", d[13], ((d[13] & 0x80) == 0x80) ? _RED_("enabled") : _GREEN_("disabled")); PrintAndLogEx(SUCCESS, " write ( %02X ) protection: %s", d[14], ((d[14] & 0x80) == 0x80) ? _RED_("enabled") : _GREEN_("disabled")); PrintAndLogEx(SUCCESS, ""); PrintAndLogEx(SUCCESS, "----------------- " _CYAN_("raw") " -----------------"); PrintAndLogEx(SUCCESS, "%s", sprint_hex_inrow(d, n)); PrintAndLogEx(NORMAL, ""); } static int CmdNfcDecode(const char *Cmd) { #ifndef MAX_NDEF_LEN #define MAX_NDEF_LEN 2048 #endif CLIParserContext *ctx; CLIParserInit(&ctx, "nfc decode", "Decode and print NFC Data Exchange Format (NDEF)\n" "You must provide either data in hex or a filename, but not both", "nfc decode -d 9101085402656e48656c6c6f5101085402656e576f726c64\n" "nfc decode -d 0103d020240203e02c040300fe\n" "nfc decode -f myfilename" ); void *argtable[] = { arg_param_begin, arg_str0("d", "data", "", "NDEF data to decode"), arg_str0("f", "file", "", "file to load"), arg_lit0(NULL, "override", "override failed crc check"), arg_lit0("v", "verbose", "verbose output"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); int datalen = 0; uint8_t data[MAX_NDEF_LEN] = {0}; CLIGetHexWithReturn(ctx, 1, data, &datalen); int fnlen = 0; char filename[FILE_PATH_SIZE] = {0}; CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); bool override = arg_get_lit(ctx, 3); bool verbose = arg_get_lit(ctx, 4); CLIParserFree(ctx); if (((datalen != 0) && (fnlen != 0)) || ((datalen == 0) && (fnlen == 0))) { PrintAndLogEx(ERR, "You must provide either data in hex or a filename"); return PM3_EINVARG; } int res = PM3_SUCCESS; if (fnlen != 0) { // read dump file uint8_t *dump = NULL; size_t bytes_read = 4096; res = pm3_load_dump(filename, (void **)&dump, &bytes_read, 4096); if (res != PM3_SUCCESS || dump == NULL || bytes_read > 4096) { return res; } uint8_t *tmp = dump; // if not MIFARE Classic default sizes, assume its Ultralight/NTAG if (bytes_read != MIFARE_4K_MAX_BYTES && bytes_read != MIFARE_2K_MAX_BYTES && bytes_read != MIFARE_1K_MAX_BYTES && bytes_read != MIFARE_1K_EV1_MAX_BYTES && bytes_read != MIFARE_MINI_MAX_BYTES) { uint8_t **pd = &tmp; mfu_df_e df = detect_mfu_dump_format(pd, verbose); if (df == MFU_DF_OLDBIN) { tmp += OLD_MFU_DUMP_PREFIX_LENGTH + (4 * 4); bytes_read -= OLD_MFU_DUMP_PREFIX_LENGTH + (4 * 4); } else if (df == MFU_DF_NEWBIN) { tmp += MFU_DUMP_PREFIX_LENGTH + (4 * 4); bytes_read -= MFU_DUMP_PREFIX_LENGTH + (4 * 4); } pd = NULL; } else { // convert from MFC dump file to a pure NDEF byte array if (bytes_read >= sizeof(mad1_sector_t) && HasMADKey((const mad1_sector_t *)tmp)) { PrintAndLogEx(SUCCESS, "MFC dump file detected. Converting..."); uint8_t ndef[4096] = {0}; size_t ndeflen = 0; const mad1_sector_t *s0 = (const mad1_sector_t *)tmp; const mad2_sector_t *s16 = NULL; size_t mad2_off = mfFirstBlockOfSector(MF_MAD2_SECTOR) * MFBLOCK_SIZE; if (bytes_read >= mad2_off + sizeof(mad2_sector_t)) s16 = (const mad2_sector_t *)(tmp + mad2_off); if (convert_mad_to_arr(s0, s16, bytes_read, ndef, sizeof(ndef), &ndeflen, override) != PM3_SUCCESS) { PrintAndLogEx(FAILED, "Failed converting, aborting..."); free(dump); return PM3_ESOFT; } memcpy(tmp, ndef, ndeflen); bytes_read = ndeflen; } } res = NDEFDecodeAndPrint(tmp, bytes_read, verbose); if (res != PM3_SUCCESS) { PrintAndLogEx(INFO, "Trying to parse NDEF records w/o NDEF header"); res = NDEFRecordsDecodeAndPrint(tmp, bytes_read, verbose); } free(dump); } else { res = NDEFDecodeAndPrint(data, datalen, verbose); if (res != PM3_SUCCESS) { PrintAndLogEx(INFO, "Trying to parse NDEF records w/o NDEF header"); res = NDEFRecordsDecodeAndPrint(data, datalen, verbose); } } return res; } static int CmdNfcEncode(const char *Cmd) { #ifndef MAX_NDEF_LEN #define MAX_NDEF_LEN 2048 #endif CLIParserContext *ctx; CLIParserInit(&ctx, "nfc encode", "Encode NFC Data Exchange Format (NDEF) records.\n" "Combine several options to build a multi record message,\n" "records are added in the order listed below.\n" "\n" "By default a bare NDEF message is emitted. Use `--tlv` to wrap it in a\n" "NFC Forum Type 2 tag container ( 03 ... FE ), which is what the\n" "`-d` parameter of `hf mf ndefwrite` and `hf 14a ndefwrite` expects.\n" "`hf mfu ndefwrite` adds the container itself, so it does not need `--tlv`", "nfc encode --uri https://proxmark.com\n" "nfc encode --uri tel:+123456789\n" "nfc encode --text \"hello world\"\n" "nfc encode --aar com.example.app\n" "nfc encode --uri https://proxmark.com --aar com.example.app\n" "nfc encode --uri https://proxmark.com --tlv -f myfilename" ); void *argtable[] = { arg_param_begin, arg_str0(NULL, "uri", "", "URI record. URL, tel:, mailto:, ..."), arg_str0(NULL, "text", "", "Text record"), arg_str0(NULL, "lang", "", "language code for the text record (default: en)"), arg_str0(NULL, "aar", "", "Android Application Record, ie an app package name"), arg_lit0(NULL, "tlv", "wrap message in a NFC Forum Type 2 tag TLV container"), arg_str0("f", "file", "", "save raw bytes to file"), arg_lit0("v", "verbose", "verbose output"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); // CLIParamStrToBuf copies the trailing NUL as well but only rejects lengths // strictly above maxdatalen, so leave room for that byte int urilen = 0; char uri[1024] = {0}; CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)uri, sizeof(uri) - 1, &urilen); int textlen = 0; char text[1024] = {0}; CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)text, sizeof(text) - 1, &textlen); int langlen = 0; char lang[32] = {0}; CLIParamStrToBuf(arg_get_str(ctx, 3), (uint8_t *)lang, sizeof(lang) - 1, &langlen); int aarlen = 0; char aar[256] = {0}; CLIParamStrToBuf(arg_get_str(ctx, 4), (uint8_t *)aar, sizeof(aar) - 1, &aarlen); bool use_tlv = arg_get_lit(ctx, 5); int fnlen = 0; char filename[FILE_PATH_SIZE] = {0}; CLIParamStrToBuf(arg_get_str(ctx, 6), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); bool verbose = arg_get_lit(ctx, 7); CLIParserFree(ctx); if ((urilen == 0) && (textlen == 0) && (aarlen == 0)) { PrintAndLogEx(ERR, "Must specify at least one record. See `" _YELLOW_("nfc encode -h") "`"); return PM3_EINVARG; } if ((langlen != 0) && (textlen == 0)) { PrintAndLogEx(WARNING, "`--lang` only applies to a text record, ignoring"); } NDEFRecordDesc_t recs[3] = {{0}}; size_t count = 0; int res = PM3_SUCCESS; uint8_t p_uri[sizeof(uri) + 1] = {0}; size_t p_uri_len = 0; if (urilen) { res = NDEFEncodePayloadURI(uri, p_uri, sizeof(p_uri), &p_uri_len); if (res != PM3_SUCCESS) { PrintAndLogEx(ERR, "Failed to encode URI record"); return res; } recs[count].tnf = tnfWellKnownRecord; recs[count].type = (const uint8_t *)NDEF_TYPE_URI; recs[count].typeLen = strlen(NDEF_TYPE_URI); recs[count].payload = p_uri; recs[count].payloadLen = p_uri_len; count++; } uint8_t p_text[sizeof(text) + sizeof(lang) + 1] = {0}; size_t p_text_len = 0; if (textlen) { res = NDEFEncodePayloadText(text, lang, p_text, sizeof(p_text), &p_text_len); if (res != PM3_SUCCESS) { PrintAndLogEx(ERR, "Failed to encode Text record"); return res; } recs[count].tnf = tnfWellKnownRecord; recs[count].type = (const uint8_t *)NDEF_TYPE_TEXT; recs[count].typeLen = strlen(NDEF_TYPE_TEXT); recs[count].payload = p_text; recs[count].payloadLen = p_text_len; count++; } uint8_t p_aar[sizeof(aar)] = {0}; size_t p_aar_len = 0; if (aarlen) { res = NDEFEncodePayloadAAR(aar, p_aar, sizeof(p_aar), &p_aar_len); if (res != PM3_SUCCESS) { PrintAndLogEx(ERR, "Failed to encode Android Application Record"); return res; } recs[count].tnf = tnfExternalRecord; recs[count].type = (const uint8_t *)NDEF_ANDROID_AAR; recs[count].typeLen = strlen(NDEF_ANDROID_AAR); recs[count].payload = p_aar; recs[count].payloadLen = p_aar_len; count++; } uint8_t msg[MAX_NDEF_LEN] = {0}; size_t msglen = 0; res = NDEFEncodeMessage(recs, count, msg, sizeof(msg), &msglen); if (res != PM3_SUCCESS) { PrintAndLogEx(ERR, "Failed to encode NDEF message"); return res; } uint8_t tlv[MAX_NDEF_LEN] = {0}; uint8_t *out = msg; size_t outlen = msglen; if (use_tlv) { size_t tlvlen = 0; res = NDEFEncodeTLV(msg, msglen, tlv, sizeof(tlv), &tlvlen); if (res != PM3_SUCCESS) { PrintAndLogEx(ERR, "Failed to wrap NDEF message in a TLV container"); return res; } out = tlv; outlen = tlvlen; } PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "--- " _CYAN_("NDEF encoding") " ----------------"); PrintAndLogEx(SUCCESS, "Records......... " _YELLOW_("%zu"), count); PrintAndLogEx(SUCCESS, "Message size.... " _YELLOW_("%zu") " bytes", msglen); if (use_tlv) { PrintAndLogEx(SUCCESS, "TLV size........ " _YELLOW_("%zu") " bytes", outlen); } PrintAndLogEx(NORMAL, ""); if (outlen > 64) { print_hex_noascii_break(out, outlen, 32); } else { PrintAndLogEx(SUCCESS, _GREEN_("%s"), sprint_hex_inrow(out, outlen)); } if (fnlen) { saveFile(filename, ".bin", out, outlen); } // round trip it back through the decoder, so the user can see what a reader will see if (use_tlv) { NDEFDecodeAndPrint(out, outlen, verbose); } else { NDEFRecordsDecodeAndPrint(out, outlen, verbose); } return PM3_SUCCESS; } static int CmdNFCType1Read(const char *Cmd) { return CmdHFTopazInfo(Cmd); } static int CmdNFCType1Help(const char *Cmd); static command_t CommandNFCType1Table[] = { {"--------", CmdNFCType1Help, AlwaysAvailable, "-------------- " _CYAN_("NFC Forum Tag Type 1") " ---------------"}, // {"format", CmdNFCType1Format, IfPm3Iso14443a, "format ISO-14443-a tag as NFC Tag"}, {"read", CmdNFCType1Read, IfPm3Iso14443a, "read NFC Forum Tag Type 1"}, // {"write", CmdNFCType1Write, IfPm3Iso14443a, "write NFC Forum Tag Type 1"}, {"--------", CmdNFCType1Help, AlwaysAvailable, "--------------------- " _CYAN_("General") " ---------------------"}, {"help", CmdNFCType1Help, AlwaysAvailable, "This help"}, {NULL, NULL, NULL, NULL} }; static int CmdNFCType1(const char *Cmd) { clearCommandBuffer(); return CmdsParse(CommandNFCType1Table, Cmd); } static int CmdNFCType1Help(const char *Cmd) { (void)Cmd; // Cmd is not used so far CmdsHelp(CommandNFCType1Table); return PM3_SUCCESS; } static int CmdNFCType2Read(const char *Cmd) { return CmdHF14MfuNDEFRead(Cmd); } static int CmdNFCType2Write(const char *Cmd) { return CmdHF14MfuNDEFWrite(Cmd); } static int CmdNFCType2Format(const char *Cmd) { return CmdHF14MfuNDEFFormat(Cmd); } static int CmdNFCType2Help(const char *Cmd); static command_t CommandNFCType2Table[] = { {"--------", CmdNFCType2Help, AlwaysAvailable, "-------------- " _CYAN_("NFC Forum Tag Type 2") " ---------------"}, {"format", CmdNFCType2Format, IfPm3Iso14443a, "format MIFARE Ultralight / NTAG as NFC Forum Tag Type 2"}, {"read", CmdNFCType2Read, IfPm3Iso14443a, "read NFC Forum Tag Type 2"}, {"write", CmdNFCType2Write, IfPm3Iso14443a, "write NFC Forum Tag Type 2"}, {"--------", CmdNFCType2Help, AlwaysAvailable, "--------------------- " _CYAN_("General") " ---------------------"}, {"help", CmdNFCType2Help, AlwaysAvailable, "This help"}, {NULL, NULL, NULL, NULL} }; static int CmdNFCType2(const char *Cmd) { clearCommandBuffer(); return CmdsParse(CommandNFCType2Table, Cmd); } static int CmdNFCType2Help(const char *Cmd) { (void)Cmd; // Cmd is not used so far CmdsHelp(CommandNFCType2Table); return PM3_SUCCESS; } /* static int CmdNFCType3Read(const char *Cmd) { return CmdHFFelicaXXX(Cmd); } static int CmdNFCType3Help(const char *Cmd); static command_t CommandNFCType3Table[] = { {"--------", CmdNFCType3Help, AlwaysAvailable, "-------------- " _CYAN_("NFC Forum Tag Type 3") " ---------------"}, // {"format", CmdNFCType3Format, IfPm3Felica, "format FeliCa tag as NFC Tag"}, {"read", CmdNFCType3Read, IfPm3Felica, "read NFC Forum Tag Type 3"}, // {"write", CmdNFCType3Write, IfPm3Felica, "write NFC Forum Tag Type 3"}, {"--------", CmdNFCType3Help, AlwaysAvailable, "--------------------- " _CYAN_("General") " ---------------------"}, {"help", CmdNFCType3Help, AlwaysAvailable, "This help"}, {NULL, NULL, NULL, NULL} }; static int CmdNFCType3(const char *Cmd) { clearCommandBuffer(); return CmdsParse(CommandNFCType3Table, Cmd); } static int CmdNFCType3Help(const char *Cmd) { (void)Cmd; // Cmd is not used so far CmdsHelp(CommandNFCType3Table); return PM3_SUCCESS; } */ static int CmdNFCType4ARead(const char *Cmd) { return CmdHF14ANdefRead(Cmd); } static int CmdNFCST25TARead(const char *Cmd) { return CmdHFST25TANdefRead(Cmd); } static int CmdNFCType4AFormat(const char *Cmd) { return CmdHF14ANdefFormat(Cmd); } static int CmdNFCType4AWrite(const char *Cmd) { return CmdHF14ANdefWrite(Cmd); } static int CmdNFCType4AHelp(const char *Cmd); static command_t CommandNFCType4ATable[] = { {"--------", CmdNFCType4AHelp, AlwaysAvailable, "--------- " _CYAN_("NFC Forum Tag Type 4 ISO14443A") " ----------"}, {"format", CmdNFCType4AFormat, IfPm3Iso14443a, "format ISO-14443-a tag as NFC Tag"}, {"read", CmdNFCType4ARead, IfPm3Iso14443a, "read NFC Forum Tag Type 4 A"}, {"write", CmdNFCType4AWrite, IfPm3Iso14443a, "write NFC Forum Tag Type 4 A"}, // {"mfdesread", CmdNFCMFDESRead, IfPm3Iso14443a, "read NDEF from MIFARE DESfire"}, // hf mfdes ndefread // {"mfdesformat", CmdNFCMFDESFormat, IfPm3Iso14443a, "format MIFARE DESfire as NFC Forum Tag Type 4"}, {"st25taread", CmdNFCST25TARead, IfPm3Iso14443a, "read ST25TA as NFC Forum Tag Type 4"}, {"--------", CmdNFCType4AHelp, AlwaysAvailable, "--------------------- " _CYAN_("General") " ---------------------"}, {"help", CmdNFCType4AHelp, AlwaysAvailable, "This help"}, {NULL, NULL, NULL, NULL} }; static int CmdNFCType4A(const char *Cmd) { clearCommandBuffer(); return CmdsParse(CommandNFCType4ATable, Cmd); } static int CmdNFCType4AHelp(const char *Cmd) { (void)Cmd; // Cmd is not used so far CmdsHelp(CommandNFCType4ATable); return PM3_SUCCESS; } static int CmdNFCType4BRead(const char *Cmd) { return CmdHF14BNdefRead(Cmd); } static int CmdNFCType4BHelp(const char *Cmd); static command_t CommandNFCType4BTable[] = { {"--------", CmdNFCType4BHelp, AlwaysAvailable, "--------- " _CYAN_("NFC Forum Tag Type 4 ISO14443B") " -------------"}, // {"format", CmdNFCType4BFormat, IfPm3Iso14443b, "format ISO-14443-b tag as NFC Tag"}, {"read", CmdNFCType4BRead, IfPm3Iso14443b, "read NFC Forum Tag Type 4 B"}, // {"write", CmdNFCType4BWrite, IfPm3Iso14443b, "write NFC Forum Tag Type 4 B"}, {"--------", CmdNFCType4BHelp, AlwaysAvailable, "--------------------- " _CYAN_("General") " ---------------------"}, {"help", CmdNFCType4BHelp, AlwaysAvailable, "This help"}, {NULL, NULL, NULL, NULL} }; static int CmdNFCType4B(const char *Cmd) { clearCommandBuffer(); return CmdsParse(CommandNFCType4BTable, Cmd); } static int CmdNFCType4BHelp(const char *Cmd) { (void)Cmd; // Cmd is not used so far CmdsHelp(CommandNFCType4BTable); return PM3_SUCCESS; } /* static int CmdNFCType5Read(const char *Cmd) { return CmdHF15XXX(Cmd); } static int CmdNFCType5Help(const char *Cmd); static command_t CommandNFCType5Table[] = { {"--------", CmdNFCType5Help, AlwaysAvailable, "-------------- " _CYAN_("NFC Forum Tag Type 5") " ---------------"}, // {"format", CmdNFCType5Format, IfPm3Iso15693, "format ISO-15693 tag as NFC Tag"}, {"read", CmdNFCType5Read, IfPm3Iso15693, "read NFC Forum Tag Type 5"}, // {"write", CmdNFCType5Write, IfPm3Iso15693, "write NFC Forum Tag Type 5"}, {"--------", CmdNFCType5Help, AlwaysAvailable, "--------------------- " _CYAN_("General") " ---------------------"}, {"help", CmdNFCType5Help, AlwaysAvailable, "This help"}, {NULL, NULL, NULL, NULL} }; static int CmdNFCType5(const char *Cmd) { clearCommandBuffer(); return CmdsParse(CommandNFCType5Table, Cmd); } static int CmdNFCType5Help(const char *Cmd) { (void)Cmd; // Cmd is not used so far CmdsHelp(CommandNFCType5Table); return PM3_SUCCESS; } */ static int CmdNFCMFCRead(const char *Cmd) { return CmdHFMFNDEFRead(Cmd); } static int CmdNFCMFCFormat(const char *Cmd) { return CmdHFMFNDEFFormat(Cmd); } static int CmdNFCMFCWrite(const char *Cmd) { return CmdHFMFNDEFWrite(Cmd); } static int CmdNFCMFPRead(const char *Cmd) { return CmdHFMFPNDEFRead(Cmd); } static int CmdNFCMFHelp(const char *Cmd); static command_t CommandMFTable[] = { {"--------", CmdNFCMFHelp, AlwaysAvailable, "--------- " _CYAN_("NFC Type MIFARE Classic/Plus Tag") " --------"}, {"cformat", CmdNFCMFCFormat, IfPm3Iso14443a, "format MIFARE Classic Tag as NFC Tag"}, {"cread", CmdNFCMFCRead, IfPm3Iso14443a, "read NFC Type MIFARE Classic Tag"}, {"cwrite", CmdNFCMFCWrite, IfPm3Iso14443a, "write NFC Type MIFARE Classic Tag"}, {"pread", CmdNFCMFPRead, IfPm3Iso14443a, "read NFC Type MIFARE Plus Tag"}, {"--------", CmdNFCMFHelp, AlwaysAvailable, "--------------------- " _CYAN_("General") " ---------------------"}, {"help", CmdNFCMFHelp, AlwaysAvailable, "This help"}, {NULL, NULL, NULL, NULL} }; static int CmdNFCMF(const char *Cmd) { clearCommandBuffer(); return CmdsParse(CommandMFTable, Cmd); } static int CmdNFCMFHelp(const char *Cmd) { (void)Cmd; // Cmd is not used so far CmdsHelp(CommandMFTable); return PM3_SUCCESS; } static int CmdNFCBarcodeRead(const char *Cmd) { return CmdHfThinFilmInfo(Cmd); } static int CmdNFCBarcodeSim(const char *Cmd) { return CmdHfThinFilmSim(Cmd); } static int CmdNFCBarcodeHelp(const char *Cmd); static command_t CommandBarcodeTable[] = { {"--------", CmdNFCBarcodeHelp, AlwaysAvailable, "------------------ " _CYAN_("NFC Barcode") " --------------------"}, {"read", CmdNFCBarcodeRead, IfPm3Iso14443a, "read NFC Barcode"}, {"sim", CmdNFCBarcodeSim, IfPm3Iso14443a, "simulate NFC Barcode"}, {"--------", CmdNFCBarcodeHelp, AlwaysAvailable, "--------------------- " _CYAN_("General") " ---------------------"}, {"help", CmdNFCBarcodeHelp, AlwaysAvailable, "This help"}, {NULL, NULL, NULL, NULL} }; static int CmdNFCBarcode(const char *Cmd) { clearCommandBuffer(); return CmdsParse(CommandBarcodeTable, Cmd); } static int CmdNFCBarcodeHelp(const char *Cmd) { (void)Cmd; // Cmd is not used so far CmdsHelp(CommandBarcodeTable); return PM3_SUCCESS; } static int CmdHelp(const char *Cmd); static command_t CommandTable[] = { {"--------", CmdHelp, AlwaysAvailable, "--------------------- " _CYAN_("NFC Tags") " --------------------"}, {"type1", CmdNFCType1, AlwaysAvailable, "{ NFC Forum Tag Type 1... }"}, {"type2", CmdNFCType2, AlwaysAvailable, "{ NFC Forum Tag Type 2... }"}, // {"type3", CmdNFCType3, AlwaysAvailable, "{ NFC Forum Tag Type 3... }"}, {"type4a", CmdNFCType4A, AlwaysAvailable, "{ NFC Forum Tag Type 4 ISO14443A... }"}, {"type4b", CmdNFCType4B, AlwaysAvailable, "{ NFC Forum Tag Type 4 ISO14443B... }"}, // {"type5", CmdNFCType5, AlwaysAvailable, "{ NFC Forum Tag Type 5... }"}, {"mf", CmdNFCMF, AlwaysAvailable, "{ NFC Type MIFARE Classic/Plus Tag... }"}, {"barcode", CmdNFCBarcode, AlwaysAvailable, "{ NFC Barcode Tag... }"}, // {"--------", CmdHelp, AlwaysAvailable, "--------------------- " _CYAN_("NFC peer-to-peer") " ------------"}, // {"isodep", CmdISODEP, AlwaysAvailable, "{ ISO-DEP protocol... }"}, // {"llcp", CmdNFCLLCP, AlwaysAvailable, "{ Logical Link Control Protocol... }"}, // {"snep", CmdNFCSNEP, AlwaysAvailable, "{ Simple NDEF Exchange Protocol... }"}, {"--------", CmdHelp, AlwaysAvailable, "--------------------- " _CYAN_("General") " ---------------------"}, {"help", CmdHelp, AlwaysAvailable, "This help"}, {"decode", CmdNfcDecode, AlwaysAvailable, "Decode NDEF records"}, {"encode", CmdNfcEncode, AlwaysAvailable, "Encode NDEF records"}, {NULL, NULL, NULL, NULL} }; int CmdNFC(const char *Cmd) { clearCommandBuffer(); return CmdsParse(CommandTable, Cmd); } int CmdHelp(const char *Cmd) { (void)Cmd; // Cmd is not used so far CmdsHelp(CommandTable); return PM3_SUCCESS; }