From 2d610b8dc00041c5b721cebfc7f47c1fece32d5f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 8 Jun 2025 10:02:00 +0200 Subject: [PATCH] text & style --- CHANGELOG.md | 2 + Makefile.platform.sample | 3 + armsrc/iclass.c | 4 +- client/src/cmdhficlass.c | 64 ++++++------ client/src/cmdhfmf.c | 99 ++++++++++--------- common_arm/Makefile.hal | 28 ++++-- common_fpga/fpga.h | 3 + doc/commands.json | 5 +- doc/md/Development/Makefile-vs-CMake.md | 2 +- .../4_Advanced-compilation-parameters.md | 11 ++- fpga/fpga_pm3_top.v | 2 + 11 files changed, 124 insertions(+), 99 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ce8505419..2e0d6debc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] +- Added the `PM3ULTIMATE` platform in the build / docs. *untested* (@iceman1001) +- Added fpga compilation for PM3ULTIMATE device (@n-hutton) - Updated the ATR list (@iceman1001) - Fixed fpga binary images to use fixed seed 2 (@n-hutton) - Changed `hf iclass sim -t 7` - implemented simulation that glitches key block responses (@antiklesys) diff --git a/Makefile.platform.sample b/Makefile.platform.sample index 5ff0c4748..fb5114f5f 100644 --- a/Makefile.platform.sample +++ b/Makefile.platform.sample @@ -14,6 +14,9 @@ PLATFORM=PM3RDV4 #PLATFORM=PM3ICOPYX #PLATFORM_EXTRAS=FLASH +# For PM3 Ultimate: +# uncomment the line below +#PLATFORM=PM3ULTIMATE # If you want more than one PLATFORM_EXTRAS option, separate them by spaces: #PLATFORM_EXTRAS=BTADDON diff --git a/armsrc/iclass.c b/armsrc/iclass.c index ff267f899..5a4466567 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -667,7 +667,7 @@ int do_iclass_simulation(int simulationMode, uint8_t *reader_mac_buf) { if (simulationMode == ICLASS_SIM_MODE_FULL || simulationMode == ICLASS_SIM_MODE_FULL_GLITCH || simulationMode == ICLASS_SIM_MODE_FULL_GLITCH_KEY) { - if(glitch_key_read){ + if (glitch_key_read) { goto send; } @@ -792,7 +792,7 @@ int do_iclass_simulation(int simulationMode, uint8_t *reader_mac_buf) { cipher_state_KD[current_page] = opt_doTagMAC_1(card_challenge_data, diversified_kd); if (simulationMode == ICLASS_SIM_MODE_FULL || simulationMode == ICLASS_SIM_MODE_FULL_GLITCH || simulationMode == ICLASS_SIM_MODE_FULL_GLITCH_KEY) { memcpy(emulator + (current_page * page_size) + (8 * 3), diversified_kd, 8); - if(simulationMode == ICLASS_SIM_MODE_FULL_GLITCH_KEY){ + if (simulationMode == ICLASS_SIM_MODE_FULL_GLITCH_KEY) { glitch_key_read = true; goto send; } diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index 51c90f9b7..66ae6d634 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -2250,7 +2250,8 @@ write_dump: return PM3_SUCCESS; } -static int iclass_write_block(uint8_t blockno, uint8_t *bldata, uint8_t *macdata, uint8_t *KEY, bool use_credit_key, bool elite, bool rawkey, bool replay, bool verbose, bool use_secure_pagemode, bool shallow_mod) { +static int iclass_write_block(uint8_t blockno, uint8_t *bldata, uint8_t *macdata, uint8_t *KEY, bool use_credit_key, + bool elite, bool rawkey, bool replay, bool verbose, bool use_secure_pagemode, bool shallow_mod) { iclass_writeblock_req_t payload = { .req.use_raw = rawkey, @@ -5067,56 +5068,49 @@ static int CmdHFiClassLookUp(const char *Cmd) { }; CLIExecWithReturn(ctx, Cmd, argtable, false); - bool use_vb6kdf = arg_get_lit(ctx, 7); int fnlen = 0; char filename[FILE_PATH_SIZE] = {0}; - bool use_elite = arg_get_lit(ctx, 5); - bool use_raw = arg_get_lit(ctx, 6); - if (use_vb6kdf) { - use_elite = true; - } else { - CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); - } - int csn_len = 0; uint8_t csn[8] = {0}; CLIGetHexWithReturn(ctx, 2, csn, &csn_len); - if (csn_len > 0) { - if (csn_len != 8) { - PrintAndLogEx(ERR, "CSN is incorrect length"); - CLIParserFree(ctx); - return PM3_EINVARG; - } - } - int epurse_len = 0; uint8_t epurse[8] = {0}; CLIGetHexWithReturn(ctx, 3, epurse, &epurse_len); - if (epurse_len > 0) { - if (epurse_len != 8) { - PrintAndLogEx(ERR, "ePurse is incorrect length"); - CLIParserFree(ctx); - return PM3_EINVARG; - } - } - int macs_len = 0; uint8_t macs[8] = {0}; CLIGetHexWithReturn(ctx, 4, macs, &macs_len); - if (macs_len > 0) { - if (macs_len != 8) { - PrintAndLogEx(ERR, "MAC is incorrect length"); - CLIParserFree(ctx); - return PM3_EINVARG; - } + bool use_elite = arg_get_lit(ctx, 5); + bool use_raw = arg_get_lit(ctx, 6); + bool use_vb6kdf = arg_get_lit(ctx, 7); + + if (use_vb6kdf == false) { + CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); } CLIParserFree(ctx); + // santity checks + + if (csn_len > 0 && csn_len != 8) { + PrintAndLogEx(ERR, "CSN is incorrect length"); + return PM3_EINVARG; + } + + if (epurse_len > 0 && epurse_len != 8) { + PrintAndLogEx(ERR, "ePurse is incorrect length"); + return PM3_EINVARG; + } + + if (macs_len > 0 && macs_len != 8) { + PrintAndLogEx(ERR, "MAC is incorrect length"); + return PM3_EINVARG; + } + + uint8_t CCNR[12]; uint8_t MAC_TAG[4] = { 0, 0, 0, 0 }; @@ -5161,7 +5155,8 @@ static int CmdHFiClassLookUp(const char *Cmd) { // Iclass_prekey_t iclass_prekey_t *prekey = calloc(keycount, sizeof(iclass_prekey_t)); - if (!prekey) { + if (prekey == NULL) { + PrintAndLogEx(WARNING, "Failed to allocate memory"); free(keyBlock); return PM3_EMALLOC; } @@ -5182,13 +5177,14 @@ static int CmdHFiClassLookUp(const char *Cmd) { // Sort mac list qsort(prekey, keycount, sizeof(iclass_prekey_t), cmp_uint32); - PrintAndLogEx(SUCCESS, "Searching for " _YELLOW_("%s") " key...", "DEBIT"); + PrintAndLogEx(SUCCESS, "Searching for %s key...", _YELLOW_("DEBIT")); iclass_prekey_t *item; iclass_prekey_t lookup; memcpy(lookup.mac, MAC_TAG, 4); // Binsearch item = (iclass_prekey_t *) bsearch(&lookup, prekey, keycount, sizeof(iclass_prekey_t), cmp_uint32); + if (item != NULL) { PrintAndLogEx(SUCCESS, "Found valid key " _GREEN_("%s"), sprint_hex(item->key, 8)); add_key(item->key); diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index 9963d8a68..09614fc82 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -48,21 +48,15 @@ #include "mifare/mifarehost.h" #include "crypto/originality.h" - // Defines for Saflok parsing #define SAFLOK_YEAR_OFFSET 1980 #define SAFLOK_BASIC_ACCESS_BYTE_NUM 17 -#define SAFLOK_KEY_LENGTH 6 -#define SAFLOK_UID_LENGTH 4 // Matches Mifare 4-byte UID -#define SAFLOK_MAGIC_TABLE_SIZE 192 -#define SAFLOK_CHECK_SECTOR 1 typedef struct { uint64_t a; uint64_t b; } MfClassicKeyPair; - // Structure for Saflok key levels typedef struct { uint8_t level_num; @@ -114,8 +108,8 @@ static const uint8_t saflok_c_aDecode[256] = { // Function to decrypt Saflok card data static void DecryptSaflokCardData( const uint8_t strCard[SAFLOK_BASIC_ACCESS_BYTE_NUM], - // int length, // length is always SAFLOK_BASIC_ACCESS_BYTE_NUM - uint8_t decryptedCard[SAFLOK_BASIC_ACCESS_BYTE_NUM]) { + uint8_t decryptedCard[SAFLOK_BASIC_ACCESS_BYTE_NUM] +) { int i; int num; int num2; @@ -163,8 +157,8 @@ static uint8_t CalculateCheckSum(uint8_t data[SAFLOK_BASIC_ACCESS_BYTE_NUM]) { static void ParseAndPrintSaflokData(const sector_t *sector0_info, const sector_t *sector1_info) { (void)sector1_info; // Not directly used for payload parsing currently - if (!sector0_info) { - PrintAndLogEx(WARNING, "Saflok: Sector 0 information not available for parsing."); + if (sector0_info == NULL) { + PrintAndLogEx(WARNING, "Saflok: Sector 0 information not available for parsing"); return; } @@ -177,16 +171,16 @@ static void ParseAndPrintSaflokData(const sector_t *sector0_info, const sector_t num_to_bytes(sector0_info->Key[MF_KEY_A], MIFARE_KEY_SIZE, key_bytes_for_s0); key_type_for_s0 = MF_KEY_A; // MF_KEY_A is typically #define'd as 0x60 s0_key_found = true; - PrintAndLogEx(DEBUG, "Saflok: Using Sector 0 Key A for reading blocks."); + PrintAndLogEx(DEBUG, "Saflok: Using Sector 0 Key A for reading blocks"); } else if (sector0_info->foundKey[MF_KEY_B]) { // Fallback to Key B for Sector 0 num_to_bytes(sector0_info->Key[MF_KEY_B], MIFARE_KEY_SIZE, key_bytes_for_s0); key_type_for_s0 = MF_KEY_B; // MF_KEY_B is typically #define'd as 0x61 s0_key_found = true; - PrintAndLogEx(DEBUG, "Saflok: Using Sector 0 Key B for reading blocks."); + PrintAndLogEx(DEBUG, "Saflok: Using Sector 0 Key B for reading blocks"); } - if (!s0_key_found) { - PrintAndLogEx(WARNING, "Saflok: No known keys for Sector 0. Cannot read blocks 1 & 2 for parsing."); + if (s0_key_found == false) { + PrintAndLogEx(WARNING, "Saflok: No known keys for Sector 0. Cannot read blocks 1 & 2 for parsing"); return; } @@ -195,23 +189,23 @@ static void ParseAndPrintSaflokData(const sector_t *sector0_info, const sector_t // Read absolute block 1 (data block within sector 0) if (mf_read_block(1, key_type_for_s0, key_bytes_for_s0, block1_content) != PM3_SUCCESS) { - PrintAndLogEx(WARNING, "Saflok: Failed to read card Block 1 using Sector 0 %s key.", (key_type_for_s0 == MF_KEY_A) ? "A" : "B"); + PrintAndLogEx(WARNING, "Saflok: Failed to read card Block 1 using Sector 0 %s key", (key_type_for_s0 == MF_KEY_A) ? "A" : "B"); return; } - PrintAndLogEx(DEBUG, "Saflok: Successfully read card Block 1."); + PrintAndLogEx(DEBUG, "Saflok: Successfully read card Block 1"); // Read absolute block 2 (data block within sector 0) if (mf_read_block(2, key_type_for_s0, key_bytes_for_s0, block2_content) != PM3_SUCCESS) { - PrintAndLogEx(WARNING, "Saflok: Failed to read card Block 2 using Sector 0 %s key.", (key_type_for_s0 == MF_KEY_A) ? "A" : "B"); + PrintAndLogEx(WARNING, "Saflok: Failed to read card Block 2 using Sector 0 %s key", (key_type_for_s0 == MF_KEY_A) ? "A" : "B"); return; } - PrintAndLogEx(DEBUG, "Saflok: Successfully read card Block 2."); + PrintAndLogEx(DEBUG, "Saflok: Successfully read card Block 2"); uint8_t basicAccess[SAFLOK_BASIC_ACCESS_BYTE_NUM]; uint8_t decodedBA[SAFLOK_BASIC_ACCESS_BYTE_NUM]; - memcpy(basicAccess, block1_content, 16); // 16 bytes from Block 1 - memcpy(basicAccess + 16, block2_content, 1); // 1 byte from Block 2 + memcpy(basicAccess, block1_content, MFBLOCK_SIZE); // 16 bytes from Block 1 + memcpy(basicAccess + MFBLOCK_SIZE, block2_content, 1); // 1 byte from Block 2 DecryptSaflokCardData(basicAccess, decodedBA); @@ -298,18 +292,25 @@ static void ParseAndPrintSaflokData(const sector_t *sector0_info, const sector_t // Handle day rollover for expiration static const uint8_t days_in_month_lookup[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; // 1-indexed month if (expire_month > 0 && expire_month <= 12) { + while (true) { + uint8_t max_days = days_in_month_lookup[expire_month]; - if (expire_month == 2 && (expire_year % 4 == 0 && (expire_year % 100 != 0 || expire_year % 400 == 0))) { + if (expire_month == 2 && + (expire_year % 4 == 0 && + (expire_year % 100 != 0 || expire_year % 400 == 0))) { max_days = 29; // Leap year } + if (expire_day <= max_days) { break; } + if (max_days == 0) { // Should not happen with valid month - PrintAndLogEx(WARNING, "Saflok: Invalid day/month for expiration rollover calculation."); + PrintAndLogEx(WARNING, "Saflok: Invalid day/month for expiration rollover calculation"); break; } + expire_day -= max_days; expire_month++; if (expire_month > 12) { @@ -317,8 +318,9 @@ static void ParseAndPrintSaflokData(const sector_t *sector0_info, const sector_t expire_year++; } } + } else if (expire_month != 0) { // Allow 0 if it signifies no expiration or error - PrintAndLogEx(WARNING, "Saflok: Invalid expiration month (%u) before day rollover.", expire_month); + PrintAndLogEx(WARNING, "Saflok: Invalid expiration month (%u) before day rollover", expire_month); } uint8_t checksum = decodedBA[16]; @@ -326,19 +328,19 @@ static void ParseAndPrintSaflokData(const sector_t *sector0_info, const sector_t bool checksum_valid = (checksum_calculated == checksum); PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, "--- " _CYAN_("Saflok Details")); - PrintAndLogEx(SUCCESS, "Key Level: %u (%s)", saflok_key_levels[key_level].level_num, saflok_key_levels[key_level].level_name); - PrintAndLogEx(SUCCESS, "LED Warning: %s", led_warning ? "Yes" : "No"); - PrintAndLogEx(SUCCESS, "Key ID: %u (0x%02X)", key_id, key_id); - PrintAndLogEx(SUCCESS, "Key Record: %u (0x%04X)", key_record, key_record); - PrintAndLogEx(SUCCESS, "Opening Key: %s", opening_key ? "Yes" : "No"); - PrintAndLogEx(SUCCESS, "Sequence Number & Combination: %u (0x%02X)", sequence_combination_number, sequence_combination_number); - PrintAndLogEx(SUCCESS, "Override Deadbolt: %s", override_deadbolt ? "Yes" : "No"); - PrintAndLogEx(SUCCESS, "Restricted Weekdays: %s", restricted_weekday_string); - PrintAndLogEx(SUCCESS, "Property ID: %u (0x%04X)", property_id, property_id); - PrintAndLogEx(SUCCESS, "Creation Date: %04u-%02u-%02u %02u:%02u", creation_year, creation_month, creation_day, creation_hour, creation_minute); - PrintAndLogEx(SUCCESS, "Expiration Date: %04u-%02u-%02u %02u:%02u", expire_year, expire_month, expire_day, expiry_hour, expiry_minute); - PrintAndLogEx(SUCCESS, "Checksum Valid: %s", checksum_valid ? "Yes" : "No"); + PrintAndLogEx(INFO, "--- " _CYAN_("SAFLOK details")); + PrintAndLogEx(SUCCESS, "Key Level............. %u (%s)", saflok_key_levels[key_level].level_num, saflok_key_levels[key_level].level_name); + PrintAndLogEx(SUCCESS, "LED Warning........... %s", led_warning ? "Yes" : "No"); + PrintAndLogEx(SUCCESS, "Key ID................ %u (0x%02X)", key_id, key_id); + PrintAndLogEx(SUCCESS, "Key Record............ %u (0x%04X)", key_record, key_record); + PrintAndLogEx(SUCCESS, "Opening Key........... %s", opening_key ? "Yes" : "No"); + PrintAndLogEx(SUCCESS, "Sequence & Combination: %u (0x%02X)", sequence_combination_number, sequence_combination_number); + PrintAndLogEx(SUCCESS, "Override Deadbolt..... %s", override_deadbolt ? "Yes" : "No"); + PrintAndLogEx(SUCCESS, "Restricted Weekdays... %s", restricted_weekday_string); + PrintAndLogEx(SUCCESS, "Property ID........... %u (0x%04X)", property_id, property_id); + PrintAndLogEx(SUCCESS, "Creation Date......... %04u-%02u-%02u %02u:%02u", creation_year, creation_month, creation_day, creation_hour, creation_minute); + PrintAndLogEx(SUCCESS, "Expiration Date....... %04u-%02u-%02u %02u:%02u", expire_year, expire_month, expire_day, expiry_hour, expiry_minute); + PrintAndLogEx(SUCCESS, "Checksum Valid........ ( %s )", checksum_valid ? _GREEN_("ok") : _RED_("fail")); } @@ -434,20 +436,19 @@ static int initSectorTable(sector_t **src, size_t items) { static void decode_print_st(uint16_t blockno, uint8_t *data) { if (mfIsSectorTrailer(blockno)) { PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, "-------------------------- " _CYAN_("Sector trailer decoder") " --------------------------"); - PrintAndLogEx(INFO, "key A........ " _GREEN_("%s"), sprint_hex_inrow(data, 6)); - PrintAndLogEx(INFO, "acr.......... " _GREEN_("%s"), sprint_hex_inrow(data + 6, 3)); - PrintAndLogEx(INFO, "user / gpb... " _GREEN_("%02x"), data[9]); - PrintAndLogEx(INFO, "key B........ " _GREEN_("%s"), sprint_hex_inrow(data + 10, 6)); + PrintAndLogEx(INFO, "------------------------ " _CYAN_("Sector trailer decoder") " ------------------------"); + PrintAndLogEx(INFO, " Key A........ " _BRIGHT_GREEN_("%s"), sprint_hex_inrow(data, 6)); + PrintAndLogEx(INFO, " ACR.......... " _MAGENTA_("%s"), sprint_hex_inrow(data + 6, 3)); + PrintAndLogEx(INFO, " User / gpb... %02x", data[9]); + PrintAndLogEx(INFO, " Key B........ " _GREEN_("%s"), sprint_hex_inrow(data + 10, 6)); PrintAndLogEx(INFO, ""); PrintAndLogEx(INFO, " # | access rights"); - PrintAndLogEx(INFO, "----+-----------------------------------------------------------------------"); + PrintAndLogEx(INFO, "----+-------------------------------------------------------------------"); if (mfValidateAccessConditions(&data[6]) == false) { - PrintAndLogEx(WARNING, _RED_("Invalid Access Conditions")); + PrintAndLogEx(WARNING, _RED_("Invalid access conditions")); } - int bln = mfFirstBlockOfSector(mfSectorNum(blockno)); int blinc = (mfNumBlocksPerSector(mfSectorNum(blockno)) > 4) ? 5 : 1; for (int i = 0; i < 4; i++) { @@ -458,13 +459,13 @@ static void decode_print_st(uint16_t blockno, uint8_t *data) { uint8_t cond = mf_get_accesscondition(i, &data[6]); if (cond == 0 || cond == 1 || cond == 2) { PrintAndLogEx(INFO, ""); - PrintAndLogEx(INFO, "OBS! Key B is readable, it SHALL NOT be able to authenticate on original MFC"); + PrintAndLogEx(INFO, "OBS!"); + PrintAndLogEx(INFO, "Key B is readable, it SHALL NOT be able to authenticate on original MFC"); } } } - - PrintAndLogEx(INFO, "----------------------------------------------------------------------------"); + PrintAndLogEx(INFO, "------------------------------------------------------------------------"); PrintAndLogEx(NORMAL, ""); } } @@ -541,7 +542,7 @@ void mf_print_block_one(uint8_t blockno, uint8_t *d, bool verbose) { char ascii[24] = {0}; ascii_to_buffer((uint8_t *)ascii, d, MFBLOCK_SIZE, sizeof(ascii) - 1, 1); - PrintAndLogEx(INFO, "%3d | " _YELLOW_("%s") _MAGENTA_("%s") "%02X " _YELLOW_("%s") "| " _YELLOW_("%s"), + PrintAndLogEx(INFO, "%3d | " _BRIGHT_GREEN_("%s") _MAGENTA_("%s") "%02X " _GREEN_("%s") "| " _YELLOW_("%s"), blockno, keya, acl, @@ -1428,7 +1429,7 @@ static int CmdHF14AMfRdSc(const char *Cmd) { } int keylen = 0; - uint8_t key[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + uint8_t key[MIFARE_KEY_SIZE] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; CLIGetHexWithReturn(ctx, 4, key, &keylen); int s = arg_get_int_def(ctx, 5, 0); diff --git a/common_arm/Makefile.hal b/common_arm/Makefile.hal index e317ea247..568c245ba 100644 --- a/common_arm/Makefile.hal +++ b/common_arm/Makefile.hal @@ -29,15 +29,17 @@ define KNOWN_PLATFORM_DEFINITIONS Known definitions: -+============================================+ ++==================================================+ | PLATFORM | DESCRIPTION | -+============================================+ ++==================================================+ | PM3RDV4 (def) | Proxmark3 RDV4 | -+--------------------------------------------+ ++--------------------------------------------------+ | PM3GENERIC | Proxmark3 generic target | -+--------------------------------------------+ ++--------------------------------------------------+ | PM3ICOPYX | iCopy-X with XC3S100E | -+--------------------------------------------+ ++--------------------------------------------------+ +| PM3ULTIMATE | Proxmark3 Ultimate with XC2S50 | ++--------------------------------------------------+ +============================================+ | PLATFORM_EXTRAS | DESCRIPTION | @@ -153,7 +155,21 @@ else ifeq ($(PLATFORM),PM3ICOPYX) PLATFORM_DEFS = -DWITH_FLASH -DICOPYX -DXC3 PLTNAME = iCopy-X with XC3S100E PLATFORM_FPGA = xc3s100e - +else ifeq ($(PLATFORM),PM3ULTIMATE) + # FPGA bitstream files, the order doesn't matter anymore - only hf has a bitstream + FPGA_BITSTREAMS = fpga_pm3_ult_hf.bit + ifneq ($(SKIP_LF),1) + FPGA_BITSTREAMS += fpga_pm3_ult_lf.bit + endif + ifneq ($(SKIP_FELICA),1) + FPGA_BITSTREAMS += fpga_pm3_ult_felica.bit + endif + ifneq ($(SKIP_ISO15693),1) + FPGA_BITSTREAMS += fpga_pm3_ult_hf_15.bit + endif + PLATFORM_DEFS = -DWITH_FLASH -DXC2S50 + PLTNAME = Proxmark3 Ultimate with XC2S50 + PLATFORM_FPGA = xc2s50 else $(error Invalid or empty PLATFORM: $(PLATFORM). $(KNOWN_DEFINITIONS)) endif diff --git a/common_fpga/fpga.h b/common_fpga/fpga.h index c383d2d44..1b009cd62 100644 --- a/common_fpga/fpga.h +++ b/common_fpga/fpga.h @@ -25,6 +25,9 @@ #if defined XC3 #define FPGA_TYPE "3s100evq100" #define FPGA_CONFIG_SIZE 72864L // FPGA .bit file rounded up to next multiple of FPGA_INTERLEAVE_SIZE +#elif defined XC2S50 +#define FPGA_TYPE "2s50vq144" +#define FPGA_CONFIG_SIZE 69984L // FPGA .bit file rounded up to next multiple of FPGA_INTERLEAVE_SIZE #else #define FPGA_TYPE "2s30vq100" #define FPGA_CONFIG_SIZE 42336L // FPGA .bit file rounded up to next multiple of FPGA_INTERLEAVE_SIZE diff --git a/doc/commands.json b/doc/commands.json index af1995257..7cbab59af 100644 --- a/doc/commands.json +++ b/doc/commands.json @@ -3695,7 +3695,8 @@ "hf iclass sim -t 2 -> execute loclass attack online part", "hf iclass sim -t 3 -> simulate full iCLASS 2k tag", "hf iclass sim -t 4 -> Reader-attack, adapted for KeyRoll mode, gather reader responses to extract elite key", - "hf iclass sim -t 6 -> simulate full iCLASS 2k tag that doesn't respond to r/w requests to the last SIO block" + "hf iclass sim -t 6 -> simulate full iCLASS 2k tag that doesn't respond to r/w requests to the last SIO block", + "hf iclass sim -t 7 -> simulate full iCLASS 2k tag that doesn't XOR or respond to r/w requests on block 3" ], "offline": false, "options": [ @@ -13375,6 +13376,6 @@ "metadata": { "commands_extracted": 768, "extracted_by": "PM3Help2JSON v1.00", - "extracted_on": "2025-06-07T09:11:06" + "extracted_on": "2025-06-08T07:56:09" } } diff --git a/doc/md/Development/Makefile-vs-CMake.md b/doc/md/Development/Makefile-vs-CMake.md index 2d1094970..b561ef2d2 100644 --- a/doc/md/Development/Makefile-vs-CMake.md +++ b/doc/md/Development/Makefile-vs-CMake.md @@ -112,7 +112,7 @@ At the moment both are maintained because they don't perfectly overlap yet. | Feature | Makefile | Remarks | |-----|---|---| -| Platform choice | `PLATFORM=` | values: `PM3RDV4`, `PM3GENERIC`, `PM3ICOPYX` | +| Platform choice | `PLATFORM=` | values: `PM3RDV4`, `PM3GENERIC`, `PM3ICOPYX`, `PM3ULTIMATE` | | Platform size | `PLATFORM_SIZE=` | values: `256`, `512` | | Platform extras | `PLATFORM_EXTRAS=` | values: `BTADDON`, `FPC_USART_DEV` | | Skip LF/HF techs in the firmware | `SKIP_`*`=1` | see `common_arm/Makefile.hal` for a list | diff --git a/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md b/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md index 0beddec7c..cb1fc583e 100644 --- a/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md +++ b/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md @@ -61,11 +61,12 @@ For an up-to-date exhaustive list of options, you can run `make PLATFORM=`. Here are the supported values you can assign to `PLATFORM` in `Makefile.platform`: -| PLATFORM | DESCRIPTION | -|-----------------|--------------------------| -| PM3RDV4 (def) | Proxmark3 RDV4 | -| PM3GENERIC | Proxmark3 generic target | -| PM3ICOPYX | iCopy-X with XC3S100E | +| PLATFORM | DESCRIPTION | +|-----------------|-------------------------------| +| PM3RDV4 (def) | Proxmark3 RDV4 | +| PM3GENERIC | Proxmark3 generic target | +| PM3ICOPYX | iCopy-X with XC3S100E | +| PM3ULTIMATE | Proxmar3 Ultimate with XC2S50 | By default `PLATFORM=PM3RDV4`. diff --git a/fpga/fpga_pm3_top.v b/fpga/fpga_pm3_top.v index a36cd3e6d..a183d34d2 100644 --- a/fpga/fpga_pm3_top.v +++ b/fpga/fpga_pm3_top.v @@ -28,6 +28,8 @@ //`define PM3GENERIC // iCopy-X with XC3S100E //`define PM3ICOPYX +// Proxmark3 Ultimate with XC2S50 +//`define PM3ULTIMATE // Pass desired defines to compiler to enable required modules // WITH_LF enables Low Frequency mode when defined else HF is enabled