diff --git a/armsrc/mifareutil.c b/armsrc/mifareutil.c index e94d09f40..5dfbfd26b 100644 --- a/armsrc/mifareutil.c +++ b/armsrc/mifareutil.c @@ -139,7 +139,7 @@ int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, return mifare_classic_authex(pcs, uid, blockNo, keyType, ui64Key, isNested, NULL, NULL); } int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing) { - return mifare_classic_authex_cmd(pcs, uid, blockNo, keyType ? MIFARE_AUTH_KEYA : MIFARE_AUTH_KEYB, ui64Key, isNested, ntptr, timing); + return mifare_classic_authex_cmd(pcs, uid, blockNo, (keyType & 1) == 0 ? MIFARE_AUTH_KEYA : MIFARE_AUTH_KEYB, ui64Key, isNested, ntptr, timing); } int mifare_classic_authex_cmd(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t cmd, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing) { diff --git a/client/deps/hardnested/hardnested_bruteforce.c b/client/deps/hardnested/hardnested_bruteforce.c index 7766b28d3..17edfaad0 100644 --- a/client/deps/hardnested/hardnested_bruteforce.c +++ b/client/deps/hardnested/hardnested_bruteforce.c @@ -78,6 +78,8 @@ THE SOFTWARE. #define DEBUG_KEY_ELIMINATION 1 // #define DEBUG_BRUTE_FORCE +#define MIN_BUCKETS_SIZE 128 + typedef enum { EVEN_STATE = 0, ODD_STATE = 1 @@ -88,7 +90,8 @@ static uint32_t bf_test_nonce[256]; static uint8_t bf_test_nonce_2nd_byte[256]; static uint8_t bf_test_nonce_par[256]; static uint32_t bucket_count = 0; -static statelist_t *buckets[128]; +static size_t buckets_allocated = 0; +static statelist_t **buckets = NULL; static uint32_t keys_found = 0; static uint64_t num_keys_tested; static uint64_t found_bs_key = 0; @@ -157,6 +160,7 @@ crack_states_thread(void *x) { uint8_t *best_first_bytes; } *thread_arg; + const int num_brute_force_threads = NUM_BRUTE_FORCE_THREADS; thread_arg = (struct arg *)x; const int thread_id = thread_arg->thread_ID; uint32_t current_bucket = thread_id; @@ -188,7 +192,7 @@ crack_states_thread(void *x) { } } } - current_bucket += NUM_BRUTE_FORCE_THREADS; + current_bucket += num_brute_force_threads; } return NULL; } @@ -294,12 +298,34 @@ static void write_benchfile(statelist_t *candidates) { #endif +static bool ensure_buckets_alloc(size_t need_buckets) { + if (need_buckets > buckets_allocated) { + size_t alloc_sz = ((buckets_allocated == 0) ? MIN_BUCKETS_SIZE : (buckets_allocated * 2)); + while (need_buckets > alloc_sz) { + alloc_sz *= 2; + } + + buckets = realloc(buckets, sizeof(statelist_t *) * alloc_sz); + if (buckets == NULL) { + buckets_allocated = 0; + return false; + } + memset(buckets + buckets_allocated, 0, (alloc_sz - buckets_allocated) * sizeof(statelist_t *)); + buckets_allocated = alloc_sz; + } + + return true; +} + + bool brute_force_bs(float *bf_rate, statelist_t *candidates, uint32_t cuid, uint32_t num_acquired_nonces, uint64_t maximum_states, noncelist_t *nonces, uint8_t *best_first_bytes, uint64_t *found_key) { #if defined (WRITE_BENCH_FILE) write_benchfile(candidates); #endif bool silent = (bf_rate != NULL); + const int num_brute_force_threads = NUM_BRUTE_FORCE_THREADS; + keys_found = 0; num_keys_tested = 0; found_bs_key = 0; @@ -310,6 +336,11 @@ bool brute_force_bs(float *bf_rate, statelist_t *candidates, uint32_t cuid, uint bucket_count = 0; for (statelist_t *p = candidates; p != NULL; p = p->next) { if (p->states[ODD_STATE] != NULL && p->states[EVEN_STATE] != NULL) { + if (!ensure_buckets_alloc(bucket_count + 1)) { + PrintAndLogEx(ERR, "Can't allocate buckets, abort!"); + return false; + } + buckets[bucket_count] = p; bucket_count++; } @@ -322,7 +353,7 @@ bool brute_force_bs(float *bf_rate, statelist_t *candidates, uint32_t cuid, uint return false; #endif - pthread_t threads[NUM_BRUTE_FORCE_THREADS]; + pthread_t threads[num_brute_force_threads]; struct args { bool silent; int thread_ID; @@ -331,9 +362,9 @@ bool brute_force_bs(float *bf_rate, statelist_t *candidates, uint32_t cuid, uint uint64_t maximum_states; noncelist_t *nonces; uint8_t *best_first_bytes; - } thread_args[NUM_BRUTE_FORCE_THREADS]; + } thread_args[num_brute_force_threads]; - for (uint32_t i = 0; i < NUM_BRUTE_FORCE_THREADS; i++) { + for (uint32_t i = 0; i < num_brute_force_threads; i++) { thread_args[i].thread_ID = i; thread_args[i].silent = silent; thread_args[i].cuid = cuid; @@ -343,10 +374,14 @@ bool brute_force_bs(float *bf_rate, statelist_t *candidates, uint32_t cuid, uint thread_args[i].best_first_bytes = best_first_bytes; pthread_create(&threads[i], NULL, crack_states_thread, (void *)&thread_args[i]); } - for (uint32_t i = 0; i < NUM_BRUTE_FORCE_THREADS; i++) { + for (uint32_t i = 0; i < num_brute_force_threads; i++) { pthread_join(threads[i], 0); } + free(buckets); + buckets = NULL; + buckets_allocated = 0; + uint64_t elapsed_time = msclock() - start_time; if (bf_rate != NULL) @@ -434,30 +469,31 @@ static bool read_bench_data(statelist_t *test_candidates) { float brute_force_benchmark(void) { - statelist_t test_candidates[NUM_BRUTE_FORCE_THREADS]; + const int num_brute_force_threads = NUM_BRUTE_FORCE_THREADS; + statelist_t test_candidates[num_brute_force_threads]; test_candidates[0].states[ODD_STATE] = calloc(1, (TEST_BENCH_SIZE + 1) * sizeof(uint32_t)); test_candidates[0].states[EVEN_STATE] = calloc(1, (TEST_BENCH_SIZE + 1) * sizeof(uint32_t)); - for (uint32_t i = 0; i < NUM_BRUTE_FORCE_THREADS - 1; i++) { + for (uint32_t i = 0; i < num_brute_force_threads - 1; i++) { test_candidates[i].next = test_candidates + i + 1; test_candidates[i + 1].states[ODD_STATE] = test_candidates[0].states[ODD_STATE]; test_candidates[i + 1].states[EVEN_STATE] = test_candidates[0].states[EVEN_STATE]; } - test_candidates[NUM_BRUTE_FORCE_THREADS - 1].next = NULL; + test_candidates[num_brute_force_threads - 1].next = NULL; if (!read_bench_data(test_candidates)) { PrintAndLogEx(NORMAL, "Couldn't read benchmark data. Assuming brute force rate of %1.0f states per second", DEFAULT_BRUTE_FORCE_RATE); return DEFAULT_BRUTE_FORCE_RATE; } - for (uint32_t i = 0; i < NUM_BRUTE_FORCE_THREADS; i++) { + for (uint32_t i = 0; i < num_brute_force_threads; i++) { test_candidates[i].len[ODD_STATE] = TEST_BENCH_SIZE; test_candidates[i].len[EVEN_STATE] = TEST_BENCH_SIZE; test_candidates[i].states[ODD_STATE][TEST_BENCH_SIZE] = -1; test_candidates[i].states[EVEN_STATE][TEST_BENCH_SIZE] = -1; } - uint64_t maximum_states = TEST_BENCH_SIZE * TEST_BENCH_SIZE * (uint64_t)NUM_BRUTE_FORCE_THREADS; + uint64_t maximum_states = TEST_BENCH_SIZE * TEST_BENCH_SIZE * (uint64_t)num_brute_force_threads; float bf_rate; uint64_t found_key = 0; diff --git a/client/resources/ecplist.json b/client/resources/ecplist.json index 0ce7fcda5..3902e2f2d 100644 --- a/client/resources/ecplist.json +++ b/client/resources/ecplist.json @@ -57,6 +57,11 @@ "description": "" }, + { + "value": "6a02c3020602ffff", + "name": "Access: Hotel: Hilton", + "description": "TCI might be a wildcard before a reservation is made" + }, { "value": "6a02cb0206021100deadbeefdeadbeef", @@ -64,10 +69,45 @@ "description": "Last 8 bytes refer to reader group identifier, common for all readers in same home installation, allows to differentiate between keys for different homes" }, + { + "value": "6a02c30209010001", + "name": "Access: Car Pairing: BMW", + "description": "Device does not respond to poll after this frame. Displays a car pairing popup for BMW" + }, { "value": "6a02c30209010201", - "name": "Access: Mercedes Pairing", - "description": "Device does not respond to this frame. Displays a car pairing popup for Mercedes" + "name": "Access: Car Pairing: Mercedes", + "description": "Device does not respond to poll after this frame. Displays a car pairing popup for Mercedes" + }, + { + "value": "6a02c30209010051", + "name": "Access: Car Pairing: Genesis", + "description": "Device does not respond to poll after this frame. Displays a car pairing popup for Genesis" + }, + { + "value": "6a02c30209010041", + "name": "Access: Car Pairing: KIA", + "description": "Device does not respond to poll after this frame. Displays a car pairing popup for KIA" + }, + { + "value": "6a02c30209010301", + "name": "Access: Car Pairing: Hyundai", + "description": "Device does not respond to poll after this frame. Displays a car pairing popup for Hyundai" + }, + { + "value": "6a02c30209010701", + "name": "Access: Car Pairing: BYD", + "description": "Device does not respond to poll after this frame. Displays a car pairing popup for BYD" + }, + { + "value": "6a02c30209010241", + "name": "Access: Car Pairing: Denza", + "description": "Device does not respond to poll after this frame. Displays a car pairing popup for Denza" + }, + { + "value": "6a02c30209010091", + "name": "Access: Car Pairing: Lotus", + "description": "Device does not respond to poll after this frame. Displays a car pairing popup for Lotus" }, diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index cbca722cd..b48fd3d0a 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -2241,28 +2241,29 @@ static int CmdHF14AMfNestedHard(const char *Cmd) { snprintf(filename, FILE_PATH_SIZE, "hf-mf-%s-nonces.bin", uid); } - // detect MFC EV1 Signature - if (detect_mfc_ev1_signature() && keylen == 0) { - PrintAndLogEx(INFO, "MIFARE Classic EV1 card detected"); - blockno = 69; - keytype = MF_KEY_B; - memcpy(key, g_mifare_signature_key_b, sizeof(g_mifare_signature_key_b)); - } - - if (known_target_key == false && nonce_file_read == false) { - - // check if tag doesn't have static nonce - if (detect_classic_static_nonce() == NONCE_STATIC) { - PrintAndLogEx(WARNING, "Static nonce detected. Quitting..."); - PrintAndLogEx(HINT, "\tTry use `" _YELLOW_("hf mf staticnested") "`"); - return PM3_EOPABORTED; + if (g_session.pm3_present && !tests) { + // detect MFC EV1 Signature + if (detect_mfc_ev1_signature() && keylen == 0) { + PrintAndLogEx(INFO, "MIFARE Classic EV1 card detected"); + blockno = 69; + keytype = MF_KEY_B; + memcpy(key, g_mifare_signature_key_b, sizeof(g_mifare_signature_key_b)); } - uint64_t key64 = 0; - // check if we can authenticate to sector - if (mfCheckKeys(blockno, keytype, true, 1, key, &key64) != PM3_SUCCESS) { - PrintAndLogEx(WARNING, "Key is wrong. Can't authenticate to block: %3d key type: %c", blockno, (keytype == MF_KEY_B) ? 'B' : 'A'); - return PM3_EWRONGANSWER; + if (known_target_key == false && nonce_file_read == false) { + // check if tag doesn't have static nonce + if (detect_classic_static_nonce() == NONCE_STATIC) { + PrintAndLogEx(WARNING, "Static nonce detected. Quitting..."); + PrintAndLogEx(HINT, "\tTry use `" _YELLOW_("hf mf staticnested") "`"); + return PM3_EOPABORTED; + } + + uint64_t key64 = 0; + // check if we can authenticate to sector + if (mfCheckKeys(blockno, keytype, true, 1, key, &key64) != PM3_SUCCESS) { + PrintAndLogEx(WARNING, "Key is wrong. Can't authenticate to block: %3d key type: %c", blockno, (keytype == MF_KEY_B) ? 'B' : 'A'); + return PM3_EWRONGANSWER; + } } } diff --git a/client/src/cmdhfmfhard.c b/client/src/cmdhfmfhard.c index c885e41c9..090dcf531 100644 --- a/client/src/cmdhfmfhard.c +++ b/client/src/cmdhfmfhard.c @@ -52,6 +52,7 @@ #define STATE_FILES_DIRECTORY "hardnested_tables/" #define STATE_FILE_TEMPLATE "bitflip_%d_%03" PRIx16 "_states.bin.bz2" +#define STATE_FILE_TEMPLATE_RAW "bitflip_%d_%03" PRIx16 "_states.bin" #define DEBUG_KEY_ELIMINATION // #define DEBUG_REDUCTION @@ -260,10 +261,13 @@ static void init_bitflip_bitarrays(void) { char state_files_path[strlen(get_my_executable_directory()) + strlen(STATE_FILES_DIRECTORY) + strlen(STATE_FILE_TEMPLATE) + 1]; char state_file_name[strlen(STATE_FILE_TEMPLATE) + 1]; + char state_file_raw_name[strlen(STATE_FILE_TEMPLATE_RAW) + 1]; for (odd_even_t odd_even = EVEN_STATE; odd_even <= ODD_STATE; odd_even++) { num_effective_bitflips[odd_even] = 0; for (uint16_t bitflip = 0x001; bitflip < 0x400; bitflip++) { + bool open_uncompressed = false; + bitflip_bitarrays[odd_even][bitflip] = NULL; count_bitflip_bitarrays[odd_even][bitflip] = 1 << 24; @@ -273,14 +277,21 @@ static void init_bitflip_bitarrays(void) { char *path; if (searchFile(&path, RESOURCES_SUBDIR, state_files_path, "", true) != PM3_SUCCESS) { - continue; + snprintf(state_file_raw_name, sizeof(state_file_raw_name), STATE_FILE_TEMPLATE_RAW, odd_even, bitflip); + strncpy(state_files_path, STATE_FILES_DIRECTORY, sizeof(state_files_path) - 1); + strncat(state_files_path, state_file_raw_name, sizeof(state_files_path) - (strlen(STATE_FILES_DIRECTORY) + 1)); + if (searchFile(&path, RESOURCES_SUBDIR, state_files_path, "", true) == PM3_SUCCESS) { + open_uncompressed = true; + } else { + continue; + } } FILE *statesfile = fopen(path, "rb"); free(path); if (statesfile == NULL) { continue; - } else { + } else if (!open_uncompressed) { fseek(statesfile, 0, SEEK_END); int fsize = ftell(statesfile); if (fsize == -1) { @@ -335,6 +346,52 @@ static void init_bitflip_bitarrays(void) { #endif } BZ2_bzDecompressEnd(&compressed_stream); + } else { + fseek(statesfile, 0, SEEK_END); + int fsize = ftell(statesfile); + if (fsize == -1) { + PrintAndLogEx(ERR, "File read error with %s. Aborting...\n", state_file_name); + fclose(statesfile); + exit(5); + } + uint32_t filesize = (uint32_t)fsize; + rewind(statesfile); + + uint32_t count = 0; + size_t bytesread = fread(&count, 1, sizeof(count), statesfile); + if (bytesread != 4) { + PrintAndLogEx(ERR, "File read error with %s. Aborting...\n", state_file_name); + fclose(statesfile); + exit(5); + } + + if ((float)count / (1 << 24) < IGNORE_BITFLIP_THRESHOLD) { + uint32_t *bitset = (uint32_t *)malloc_bitarray(sizeof(uint32_t) * (1 << 19)); + if (bitset == NULL) { + PrintAndLogEx(ERR, "Out of memory error in init_bitflip_statelists(). Aborting...\n"); + fclose(statesfile); + exit(4); + } + + bytesread = fread(bitset, 1, filesize-sizeof(count), statesfile); + if (bytesread != filesize-sizeof(count)) { + PrintAndLogEx(ERR, "File read error with %s. Aborting...\n", state_file_name); + fclose(statesfile); + exit(5); + } + + effective_bitflip[odd_even][num_effective_bitflips[odd_even]++] = bitflip; + bitflip_bitarrays[odd_even][bitflip] = bitset; + count_bitflip_bitarrays[odd_even][bitflip] = count; +#if defined (DEBUG_REDUCTION) + PrintAndLogEx(INFO, "(%03" PRIx16 " %s:%5.1f%%) ", bitflip, odd_even ? "odd " : "even", (float)count / (1 << 24) * 100.0); + line++; + if (line == 8) { + PrintAndLogEx(NORMAL, ""); + line = 0; + } +#endif + } } } effective_bitflip[odd_even][num_effective_bitflips[odd_even]] = 0x400; // EndOfList marker @@ -1223,31 +1280,32 @@ __attribute__((force_align_arg_pointer)) static void check_for_BitFlipProperties(bool time_budget) { // create and run worker threads - pthread_t thread_id[NUM_CHECK_BITFLIPS_THREADS]; + const size_t num_check_bitflip_threads = NUM_CHECK_BITFLIPS_THREADS; + pthread_t thread_id[num_check_bitflip_threads]; - uint8_t args[NUM_CHECK_BITFLIPS_THREADS][3]; - uint16_t bytes_per_thread = (256 + (NUM_CHECK_BITFLIPS_THREADS / 2)) / NUM_CHECK_BITFLIPS_THREADS; - for (uint32_t i = 0; i < NUM_CHECK_BITFLIPS_THREADS; i++) { + uint8_t args[num_check_bitflip_threads][3]; + uint16_t bytes_per_thread = (256 + (num_check_bitflip_threads / 2)) / num_check_bitflip_threads; + for (uint32_t i = 0; i < num_check_bitflip_threads; i++) { args[i][0] = i * bytes_per_thread; args[i][1] = MIN(args[i][0] + bytes_per_thread - 1, 255); args[i][2] = time_budget; } // args[][] is uint8_t so max 255, no need to check it - // args[NUM_CHECK_BITFLIPS_THREADS - 1][1] = MAX(args[NUM_CHECK_BITFLIPS_THREADS - 1][1], 255); + // args[num_check_bitflip_threads - 1][1] = MAX(args[num_check_bitflip_threads - 1][1], 255); // start threads - for (uint32_t i = 0; i < NUM_CHECK_BITFLIPS_THREADS; i++) { + for (uint32_t i = 0; i < num_check_bitflip_threads; i++) { pthread_create(&thread_id[i], NULL, check_for_BitFlipProperties_thread, args[i]); } // wait for threads to terminate: - for (uint32_t i = 0; i < NUM_CHECK_BITFLIPS_THREADS; i++) { + for (uint32_t i = 0; i < num_check_bitflip_threads; i++) { pthread_join(thread_id[i], NULL); } if (hardnested_stage & CHECK_2ND_BYTES) { hardnested_stage &= ~CHECK_1ST_BYTES; // we are done with 1st stage, except... - for (uint32_t i = 0; i < NUM_CHECK_BITFLIPS_THREADS; i++) { + for (uint32_t i = 0; i < num_check_bitflip_threads; i++) { if (args[i][1] != 0) { hardnested_stage |= CHECK_1ST_BYTES; // ... when any of the threads didn't complete in time break; @@ -2057,10 +2115,11 @@ static void generate_candidates(uint8_t sum_a0_idx, uint8_t sum_a8_idx) { init_book_of_work(); // create and run worker threads - pthread_t thread_id[NUM_REDUCTION_WORKING_THREADS]; + const size_t num_reduction_working_threads = NUM_REDUCTION_WORKING_THREADS; + pthread_t thread_id[num_reduction_working_threads]; - uint16_t sums1[NUM_REDUCTION_WORKING_THREADS][3]; - for (uint32_t i = 0; i < NUM_REDUCTION_WORKING_THREADS; i++) { + uint16_t sums1[num_reduction_working_threads][3]; + for (uint32_t i = 0; i < num_reduction_working_threads; i++) { sums1[i][0] = sum_a0_idx; sums1[i][1] = sum_a8_idx; sums1[i][2] = i + 1; @@ -2068,7 +2127,7 @@ static void generate_candidates(uint8_t sum_a0_idx, uint8_t sum_a8_idx) { } // wait for threads to terminate: - for (uint32_t i = 0; i < NUM_REDUCTION_WORKING_THREADS; i++) { + for (uint32_t i = 0; i < num_reduction_working_threads; i++) { pthread_join(thread_id[i], NULL); } diff --git a/client/src/comms.c b/client/src/comms.c index a17bdbaf9..1c3d1f686 100644 --- a/client/src/comms.c +++ b/client/src/comms.c @@ -621,9 +621,7 @@ bool OpenProxmark(pm3_device_t **dev, const char *port, bool wait_for_port, int // check if we can communicate with Pm3 int TestProxmark(pm3_device_t *dev) { - PacketResponseNG resp; uint16_t len = 32; - bool is_tcp_conn = false; uint8_t data[len]; for (uint16_t i = 0; i < len; i++) data[i] = i & 0xFF; @@ -643,6 +641,7 @@ int TestProxmark(pm3_device_t *dev) { timeout = 1000; #endif + PacketResponseNG resp; if (WaitForResponseTimeoutW(CMD_PING, &resp, timeout, false) == 0) { return PM3_ETIMEOUT; } @@ -666,12 +665,15 @@ int TestProxmark(pm3_device_t *dev) { memcpy(&g_pm3_capabilities, resp.data.asBytes, MIN(sizeof(capabilities_t), resp.length)); g_conn.send_via_fpc_usart = g_pm3_capabilities.via_fpc; g_conn.uart_speed = g_pm3_capabilities.baudrate; - is_tcp_conn = memcmp(g_conn.serial_port_name, "tcp:", 4) == 0; + + bool is_tcp_conn = (memcmp(g_conn.serial_port_name, "tcp:", 4) == 0); + bool is_bt_conn = (memcmp(g_conn.serial_port_name, "bt:", 3) == 0); PrintAndLogEx(INFO, "Communicating with PM3 over %s%s%s", - g_conn.send_via_fpc_usart ? _YELLOW_("FPC UART") : _YELLOW_("USB-CDC"), - is_tcp_conn ? " over " _YELLOW_("TCP") : "", - memcmp(g_conn.serial_port_name, "bt:", 3) == 0 ? " over " _YELLOW_("BT") : ""); + (g_conn.send_via_fpc_usart) ? _YELLOW_("FPC UART") : _YELLOW_("USB-CDC"), + (is_tcp_conn) ? " over " _YELLOW_("TCP") : "", + (is_bt_conn) ? " over " _YELLOW_("BT") : "" + ); if (g_conn.send_via_fpc_usart) { PrintAndLogEx(INFO, "PM3 UART serial baudrate: " _YELLOW_("%u") "\n", g_conn.uart_speed); @@ -771,7 +773,6 @@ bool WaitForResponseTimeoutW(uint32_t cmd, PacketResponseNG *response, size_t ms if (msclock() - tmp_clk > 3000 && show_warning) { // 3 seconds elapsed (but this doesn't mean the timeout was exceeded) -// PrintAndLogEx(INFO, "Waiting for a response from the Proxmark3..."); PrintAndLogEx(INFO, "You can cancel this operation by pressing the pm3 button"); show_warning = false; } diff --git a/common/lfdemod.c b/common/lfdemod.c index bf0bfd4c6..73b580a6b 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -268,12 +268,20 @@ static size_t removeEm410xParity(uint8_t *bits, size_t startIdx, bool isLong, bo *validLong = false; uint8_t bLen = isLong ? 110 : 55; uint16_t parityCol[4] = { 0, 0, 0, 0 }; + for (int word = 0; word < bLen; word += 5) { for (int bit = 0; bit < 5; bit++) { - if (word + bit >= bLen) break; + + if (word + bit >= bLen) { + break; + } + parityWd = (parityWd << 1) | bits[startIdx + word + bit]; - if ((word <= 50) && (bit < 4)) + + if ((word <= 50) && (bit < 4)) { parityCol[bit] = (parityCol[bit] << 1) | bits[startIdx + word + bit]; + } + bits[bitCnt++] = (bits[startIdx + word + bit]); } if (word + 5 > bLen) break; @@ -293,12 +301,15 @@ static size_t removeEm410xParity(uint8_t *bits, size_t startIdx, bool isLong, bo if (!isLong && validRowParitySkipColP && validColParity) { *validShort = true; } + if (isLong && validRowParity) { *validLong = true; } + if (isLong && validRowParitySkipColP && validColParity) { *validShortExtended = true; } + if (*validShort || *validShortExtended || *validLong) { return bitCnt; } else { diff --git a/fpga/fpga_icopyx_hf.bit b/fpga/fpga_icopyx_hf.bit index b62cdace6..053f5cce8 100644 Binary files a/fpga/fpga_icopyx_hf.bit and b/fpga/fpga_icopyx_hf.bit differ diff --git a/fpga/fpga_pm3_felica.bit b/fpga/fpga_pm3_felica.bit index a903f180e..13338bda0 100644 Binary files a/fpga/fpga_pm3_felica.bit and b/fpga/fpga_pm3_felica.bit differ diff --git a/fpga/fpga_pm3_hf.bit b/fpga/fpga_pm3_hf.bit index 76dcb8d98..3b9372dc0 100644 Binary files a/fpga/fpga_pm3_hf.bit and b/fpga/fpga_pm3_hf.bit differ diff --git a/fpga/fpga_pm3_hf_15.bit b/fpga/fpga_pm3_hf_15.bit index 92a00a357..366c1c281 100644 Binary files a/fpga/fpga_pm3_hf_15.bit and b/fpga/fpga_pm3_hf_15.bit differ diff --git a/fpga/fpga_pm3_lf.bit b/fpga/fpga_pm3_lf.bit index 593a9031f..864274cca 100644 Binary files a/fpga/fpga_pm3_lf.bit and b/fpga/fpga_pm3_lf.bit differ diff --git a/fpga/hi_iso14443a.v b/fpga/hi_iso14443a.v index 7ccd7f610..6fd450528 100644 --- a/fpga/hi_iso14443a.v +++ b/fpga/hi_iso14443a.v @@ -221,7 +221,7 @@ reg curbit; `ifdef PM3ICOPYX `define EDGE_DETECT_THRESHOLD 3 `else -`define EDGE_DETECT_THRESHOLD 5 +`define EDGE_DETECT_THRESHOLD 7 `endif `define EDGE_DETECT_THRESHOLDHIGH 20