Merge branch 'master' into smartcard-relay

This commit is contained in:
Grayson Martin 2023-07-13 17:14:19 -05:00
commit efea49415d
No known key found for this signature in database
GPG key ID: 4914C62F2696A273
13 changed files with 206 additions and 58 deletions

View file

@ -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); 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) { 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) { 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) {

View file

@ -78,6 +78,8 @@ THE SOFTWARE.
#define DEBUG_KEY_ELIMINATION 1 #define DEBUG_KEY_ELIMINATION 1
// #define DEBUG_BRUTE_FORCE // #define DEBUG_BRUTE_FORCE
#define MIN_BUCKETS_SIZE 128
typedef enum { typedef enum {
EVEN_STATE = 0, EVEN_STATE = 0,
ODD_STATE = 1 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_2nd_byte[256];
static uint8_t bf_test_nonce_par[256]; static uint8_t bf_test_nonce_par[256];
static uint32_t bucket_count = 0; 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 uint32_t keys_found = 0;
static uint64_t num_keys_tested; static uint64_t num_keys_tested;
static uint64_t found_bs_key = 0; static uint64_t found_bs_key = 0;
@ -157,6 +160,7 @@ crack_states_thread(void *x) {
uint8_t *best_first_bytes; uint8_t *best_first_bytes;
} *thread_arg; } *thread_arg;
const int num_brute_force_threads = NUM_BRUTE_FORCE_THREADS;
thread_arg = (struct arg *)x; thread_arg = (struct arg *)x;
const int thread_id = thread_arg->thread_ID; const int thread_id = thread_arg->thread_ID;
uint32_t current_bucket = 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; return NULL;
} }
@ -294,12 +298,34 @@ static void write_benchfile(statelist_t *candidates) {
#endif #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) { 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) #if defined (WRITE_BENCH_FILE)
write_benchfile(candidates); write_benchfile(candidates);
#endif #endif
bool silent = (bf_rate != NULL); bool silent = (bf_rate != NULL);
const int num_brute_force_threads = NUM_BRUTE_FORCE_THREADS;
keys_found = 0; keys_found = 0;
num_keys_tested = 0; num_keys_tested = 0;
found_bs_key = 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; bucket_count = 0;
for (statelist_t *p = candidates; p != NULL; p = p->next) { for (statelist_t *p = candidates; p != NULL; p = p->next) {
if (p->states[ODD_STATE] != NULL && p->states[EVEN_STATE] != NULL) { 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; buckets[bucket_count] = p;
bucket_count++; bucket_count++;
} }
@ -322,7 +353,7 @@ bool brute_force_bs(float *bf_rate, statelist_t *candidates, uint32_t cuid, uint
return false; return false;
#endif #endif
pthread_t threads[NUM_BRUTE_FORCE_THREADS]; pthread_t threads[num_brute_force_threads];
struct args { struct args {
bool silent; bool silent;
int thread_ID; 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; uint64_t maximum_states;
noncelist_t *nonces; noncelist_t *nonces;
uint8_t *best_first_bytes; 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].thread_ID = i;
thread_args[i].silent = silent; thread_args[i].silent = silent;
thread_args[i].cuid = cuid; 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; thread_args[i].best_first_bytes = best_first_bytes;
pthread_create(&threads[i], NULL, crack_states_thread, (void *)&thread_args[i]); 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); pthread_join(threads[i], 0);
} }
free(buckets);
buckets = NULL;
buckets_allocated = 0;
uint64_t elapsed_time = msclock() - start_time; uint64_t elapsed_time = msclock() - start_time;
if (bf_rate != NULL) if (bf_rate != NULL)
@ -434,30 +469,31 @@ static bool read_bench_data(statelist_t *test_candidates) {
float brute_force_benchmark(void) { 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[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)); 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].next = test_candidates + i + 1;
test_candidates[i + 1].states[ODD_STATE] = test_candidates[0].states[ODD_STATE]; 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[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)) { 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); 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; 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[ODD_STATE] = TEST_BENCH_SIZE;
test_candidates[i].len[EVEN_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[ODD_STATE][TEST_BENCH_SIZE] = -1;
test_candidates[i].states[EVEN_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; float bf_rate;
uint64_t found_key = 0; uint64_t found_key = 0;

View file

@ -57,6 +57,11 @@
"description": "" "description": ""
}, },
{
"value": "6a02c3020602ffff",
"name": "Access: Hotel: Hilton",
"description": "TCI might be a wildcard before a reservation is made"
},
{ {
"value": "6a02cb0206021100deadbeefdeadbeef", "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" "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", "value": "6a02c30209010201",
"name": "Access: Mercedes Pairing", "name": "Access: Car Pairing: Mercedes",
"description": "Device does not respond to this frame. Displays a car pairing popup for 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"
}, },

View file

@ -2241,28 +2241,29 @@ static int CmdHF14AMfNestedHard(const char *Cmd) {
snprintf(filename, FILE_PATH_SIZE, "hf-mf-%s-nonces.bin", uid); snprintf(filename, FILE_PATH_SIZE, "hf-mf-%s-nonces.bin", uid);
} }
// detect MFC EV1 Signature if (g_session.pm3_present && !tests) {
if (detect_mfc_ev1_signature() && keylen == 0) { // detect MFC EV1 Signature
PrintAndLogEx(INFO, "MIFARE Classic EV1 card detected"); if (detect_mfc_ev1_signature() && keylen == 0) {
blockno = 69; PrintAndLogEx(INFO, "MIFARE Classic EV1 card detected");
keytype = MF_KEY_B; blockno = 69;
memcpy(key, g_mifare_signature_key_b, sizeof(g_mifare_signature_key_b)); 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;
} }
uint64_t key64 = 0; if (known_target_key == false && nonce_file_read == false) {
// check if we can authenticate to sector // check if tag doesn't have static nonce
if (mfCheckKeys(blockno, keytype, true, 1, key, &key64) != PM3_SUCCESS) { if (detect_classic_static_nonce() == NONCE_STATIC) {
PrintAndLogEx(WARNING, "Key is wrong. Can't authenticate to block: %3d key type: %c", blockno, (keytype == MF_KEY_B) ? 'B' : 'A'); PrintAndLogEx(WARNING, "Static nonce detected. Quitting...");
return PM3_EWRONGANSWER; 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;
}
} }
} }

View file

@ -52,6 +52,7 @@
#define STATE_FILES_DIRECTORY "hardnested_tables/" #define STATE_FILES_DIRECTORY "hardnested_tables/"
#define STATE_FILE_TEMPLATE "bitflip_%d_%03" PRIx16 "_states.bin.bz2" #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_KEY_ELIMINATION
// #define DEBUG_REDUCTION // #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_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_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++) { for (odd_even_t odd_even = EVEN_STATE; odd_even <= ODD_STATE; odd_even++) {
num_effective_bitflips[odd_even] = 0; num_effective_bitflips[odd_even] = 0;
for (uint16_t bitflip = 0x001; bitflip < 0x400; bitflip++) { for (uint16_t bitflip = 0x001; bitflip < 0x400; bitflip++) {
bool open_uncompressed = false;
bitflip_bitarrays[odd_even][bitflip] = NULL; bitflip_bitarrays[odd_even][bitflip] = NULL;
count_bitflip_bitarrays[odd_even][bitflip] = 1 << 24; count_bitflip_bitarrays[odd_even][bitflip] = 1 << 24;
@ -273,14 +277,21 @@ static void init_bitflip_bitarrays(void) {
char *path; char *path;
if (searchFile(&path, RESOURCES_SUBDIR, state_files_path, "", true) != PM3_SUCCESS) { 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"); FILE *statesfile = fopen(path, "rb");
free(path); free(path);
if (statesfile == NULL) { if (statesfile == NULL) {
continue; continue;
} else { } else if (!open_uncompressed) {
fseek(statesfile, 0, SEEK_END); fseek(statesfile, 0, SEEK_END);
int fsize = ftell(statesfile); int fsize = ftell(statesfile);
if (fsize == -1) { if (fsize == -1) {
@ -335,6 +346,52 @@ static void init_bitflip_bitarrays(void) {
#endif #endif
} }
BZ2_bzDecompressEnd(&compressed_stream); 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 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) { static void check_for_BitFlipProperties(bool time_budget) {
// create and run worker threads // 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]; uint8_t args[num_check_bitflip_threads][3];
uint16_t bytes_per_thread = (256 + (NUM_CHECK_BITFLIPS_THREADS / 2)) / NUM_CHECK_BITFLIPS_THREADS; uint16_t bytes_per_thread = (256 + (num_check_bitflip_threads / 2)) / num_check_bitflip_threads;
for (uint32_t i = 0; i < NUM_CHECK_BITFLIPS_THREADS; i++) { for (uint32_t i = 0; i < num_check_bitflip_threads; i++) {
args[i][0] = i * bytes_per_thread; args[i][0] = i * bytes_per_thread;
args[i][1] = MIN(args[i][0] + bytes_per_thread - 1, 255); args[i][1] = MIN(args[i][0] + bytes_per_thread - 1, 255);
args[i][2] = time_budget; args[i][2] = time_budget;
} }
// args[][] is uint8_t so max 255, no need to check it // 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 // 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]); pthread_create(&thread_id[i], NULL, check_for_BitFlipProperties_thread, args[i]);
} }
// wait for threads to terminate: // 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); pthread_join(thread_id[i], NULL);
} }
if (hardnested_stage & CHECK_2ND_BYTES) { if (hardnested_stage & CHECK_2ND_BYTES) {
hardnested_stage &= ~CHECK_1ST_BYTES; // we are done with 1st stage, except... 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) { if (args[i][1] != 0) {
hardnested_stage |= CHECK_1ST_BYTES; // ... when any of the threads didn't complete in time hardnested_stage |= CHECK_1ST_BYTES; // ... when any of the threads didn't complete in time
break; break;
@ -2057,10 +2115,11 @@ static void generate_candidates(uint8_t sum_a0_idx, uint8_t sum_a8_idx) {
init_book_of_work(); init_book_of_work();
// create and run worker threads // 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]; uint16_t sums1[num_reduction_working_threads][3];
for (uint32_t i = 0; i < NUM_REDUCTION_WORKING_THREADS; i++) { for (uint32_t i = 0; i < num_reduction_working_threads; i++) {
sums1[i][0] = sum_a0_idx; sums1[i][0] = sum_a0_idx;
sums1[i][1] = sum_a8_idx; sums1[i][1] = sum_a8_idx;
sums1[i][2] = i + 1; 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: // 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); pthread_join(thread_id[i], NULL);
} }

View file

@ -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 // check if we can communicate with Pm3
int TestProxmark(pm3_device_t *dev) { int TestProxmark(pm3_device_t *dev) {
PacketResponseNG resp;
uint16_t len = 32; uint16_t len = 32;
bool is_tcp_conn = false;
uint8_t data[len]; uint8_t data[len];
for (uint16_t i = 0; i < len; i++) for (uint16_t i = 0; i < len; i++)
data[i] = i & 0xFF; data[i] = i & 0xFF;
@ -643,6 +641,7 @@ int TestProxmark(pm3_device_t *dev) {
timeout = 1000; timeout = 1000;
#endif #endif
PacketResponseNG resp;
if (WaitForResponseTimeoutW(CMD_PING, &resp, timeout, false) == 0) { if (WaitForResponseTimeoutW(CMD_PING, &resp, timeout, false) == 0) {
return PM3_ETIMEOUT; 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)); 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.send_via_fpc_usart = g_pm3_capabilities.via_fpc;
g_conn.uart_speed = g_pm3_capabilities.baudrate; 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", PrintAndLogEx(INFO, "Communicating with PM3 over %s%s%s",
g_conn.send_via_fpc_usart ? _YELLOW_("FPC UART") : _YELLOW_("USB-CDC"), (g_conn.send_via_fpc_usart) ? _YELLOW_("FPC UART") : _YELLOW_("USB-CDC"),
is_tcp_conn ? " over " _YELLOW_("TCP") : "", (is_tcp_conn) ? " over " _YELLOW_("TCP") : "",
memcmp(g_conn.serial_port_name, "bt:", 3) == 0 ? " over " _YELLOW_("BT") : ""); (is_bt_conn) ? " over " _YELLOW_("BT") : ""
);
if (g_conn.send_via_fpc_usart) { if (g_conn.send_via_fpc_usart) {
PrintAndLogEx(INFO, "PM3 UART serial baudrate: " _YELLOW_("%u") "\n", g_conn.uart_speed); 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) { if (msclock() - tmp_clk > 3000 && show_warning) {
// 3 seconds elapsed (but this doesn't mean the timeout was exceeded) // 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"); PrintAndLogEx(INFO, "You can cancel this operation by pressing the pm3 button");
show_warning = false; show_warning = false;
} }

View file

@ -268,12 +268,20 @@ static size_t removeEm410xParity(uint8_t *bits, size_t startIdx, bool isLong, bo
*validLong = false; *validLong = false;
uint8_t bLen = isLong ? 110 : 55; uint8_t bLen = isLong ? 110 : 55;
uint16_t parityCol[4] = { 0, 0, 0, 0 }; uint16_t parityCol[4] = { 0, 0, 0, 0 };
for (int word = 0; word < bLen; word += 5) { for (int word = 0; word < bLen; word += 5) {
for (int bit = 0; bit < 5; bit++) { for (int bit = 0; bit < 5; bit++) {
if (word + bit >= bLen) break;
if (word + bit >= bLen) {
break;
}
parityWd = (parityWd << 1) | bits[startIdx + word + bit]; 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]; parityCol[bit] = (parityCol[bit] << 1) | bits[startIdx + word + bit];
}
bits[bitCnt++] = (bits[startIdx + word + bit]); bits[bitCnt++] = (bits[startIdx + word + bit]);
} }
if (word + 5 > bLen) break; 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) { if (!isLong && validRowParitySkipColP && validColParity) {
*validShort = true; *validShort = true;
} }
if (isLong && validRowParity) { if (isLong && validRowParity) {
*validLong = true; *validLong = true;
} }
if (isLong && validRowParitySkipColP && validColParity) { if (isLong && validRowParitySkipColP && validColParity) {
*validShortExtended = true; *validShortExtended = true;
} }
if (*validShort || *validShortExtended || *validLong) { if (*validShort || *validShortExtended || *validLong) {
return bitCnt; return bitCnt;
} else { } else {

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -221,7 +221,7 @@ reg curbit;
`ifdef PM3ICOPYX `ifdef PM3ICOPYX
`define EDGE_DETECT_THRESHOLD 3 `define EDGE_DETECT_THRESHOLD 3
`else `else
`define EDGE_DETECT_THRESHOLD 5 `define EDGE_DETECT_THRESHOLD 7
`endif `endif
`define EDGE_DETECT_THRESHOLDHIGH 20 `define EDGE_DETECT_THRESHOLDHIGH 20