From b35c11f95e563899956ba1ac14f2ea2576453e3c Mon Sep 17 00:00:00 2001 From: merlokk Date: Fri, 1 Dec 2017 18:49:31 +0200 Subject: [PATCH 001/127] init travis from https://github.com/pwpiwi/proxmark3/tree/travis_test --- travis.yml | 48 ++++++++++++++++++++++++++++++++++++++++ travis_test_commands.scr | 2 ++ 2 files changed, 50 insertions(+) create mode 100644 travis.yml create mode 100644 travis_test_commands.scr diff --git a/travis.yml b/travis.yml new file mode 100644 index 00000000..f9d505b9 --- /dev/null +++ b/travis.yml @@ -0,0 +1,48 @@ +# Travis-CI config +language: c + +compiler: gcc + +# Test on Linux and MacOS +matrix: + include: + - os: osx + osx_image: xcode7.3 # OS X 10.11 + - os: osx + osx_image: xcode8 # OS X 10.11 + - os: osx + osx_image: xcode8.1 # OS X 10.12 + - os: osx + osx_image: xcode8.3 # OS X 10.12 + - os: linux + dist: trusty + sudo: required + +before_install: +## Install ARM toolchain on Linux. +## add our homebrew tap for MacOS +## Note: all dependencies on MacOS should be resolved by the brew install command + if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then + sudo apt-get update -qq; + sudo apt-get install -y gcc-arm-none-eabi; + elif [[ "$TRAVIS_OS_NAME" == "osx" ]]; then + brew update; + brew tap pwpiwi/proxmark3; + fi + +install: + if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then + brew install -v --HEAD proxmark3; + elif [[ "$TRAVIS_OS_NAME" == "linux" ]]; then + make all; + fi + +before_script: + +script: +## for the time being we are satisfied if it can be build and then successfully started + if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then + proxmark3 /dev/notexists travis_test_commands.scr ; + elif [[ "$TRAVIS_OS_NAME" == "linux" ]]; then + ./client/proxmark3 /dev/notexists travis_test_commands.scr ; + fi diff --git a/travis_test_commands.scr b/travis_test_commands.scr new file mode 100644 index 00000000..0dba3526 --- /dev/null +++ b/travis_test_commands.scr @@ -0,0 +1,2 @@ +hf mf hardnested t 1 000000000000 +exit From b6c370f1714a5731cc438b4d9f2dfd90684c875e Mon Sep 17 00:00:00 2001 From: merlokk Date: Fri, 1 Dec 2017 18:54:54 +0200 Subject: [PATCH 002/127] added REPOSITORY_EP var --- travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/travis.yml b/travis.yml index f9d505b9..b52d1f65 100644 --- a/travis.yml +++ b/travis.yml @@ -1,4 +1,5 @@ # Travis-CI config +# variable REPOSITORY_EP must be filled with repository name. as sample: "merlokk/proxmark3" language: c compiler: gcc @@ -27,7 +28,7 @@ before_install: sudo apt-get install -y gcc-arm-none-eabi; elif [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update; - brew tap pwpiwi/proxmark3; + brew tap "$REPOSITORY_EP"; fi install: From 755c72b798438b795aa15688b9a3d5ac92487818 Mon Sep 17 00:00:00 2001 From: merlokk Date: Fri, 1 Dec 2017 18:57:31 +0200 Subject: [PATCH 003/127] rename travis file --- travis.yml => .travis.yml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename travis.yml => .travis.yml (100%) diff --git a/travis.yml b/.travis.yml similarity index 100% rename from travis.yml rename to .travis.yml From 2e35aa3aa7d09cf2caa85a5a9f2b6cdfc74afb87 Mon Sep 17 00:00:00 2001 From: merlokk Date: Sat, 2 Dec 2017 11:51:12 +0200 Subject: [PATCH 004/127] added info --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index b52d1f65..22f6ed7b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,6 +33,7 @@ before_install: install: if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then + brew info proxmark3; brew install -v --HEAD proxmark3; elif [[ "$TRAVIS_OS_NAME" == "linux" ]]; then make all; From a36b278fadd47997b4d8e69dfeb4a126aa1932ee Mon Sep 17 00:00:00 2001 From: merlokk Date: Sat, 2 Dec 2017 13:06:51 +0200 Subject: [PATCH 005/127] add options show --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 22f6ed7b..ecff0810 100644 --- a/.travis.yml +++ b/.travis.yml @@ -34,6 +34,7 @@ before_install: install: if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew info proxmark3; + brew options proxmark3; brew install -v --HEAD proxmark3; elif [[ "$TRAVIS_OS_NAME" == "linux" ]]; then make all; From 3c9b6573ecb23e7888e8077bc980de0ade361afa Mon Sep 17 00:00:00 2001 From: merlokk Date: Sat, 2 Dec 2017 16:24:47 +0200 Subject: [PATCH 006/127] remove show options --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index ecff0810..22f6ed7b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -34,7 +34,6 @@ before_install: install: if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew info proxmark3; - brew options proxmark3; brew install -v --HEAD proxmark3; elif [[ "$TRAVIS_OS_NAME" == "linux" ]]; then make all; From 245a6b208328a0a1df819af53b182d720b3e2196 Mon Sep 17 00:00:00 2001 From: merlokk Date: Sat, 2 Dec 2017 16:41:39 +0200 Subject: [PATCH 007/127] added xcode 9 and 9.1 coz 8 and 8.1 links to 8.3 --- .travis.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 22f6ed7b..eed0f8e5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,12 +9,12 @@ matrix: include: - os: osx osx_image: xcode7.3 # OS X 10.11 - - os: osx - osx_image: xcode8 # OS X 10.11 - - os: osx - osx_image: xcode8.1 # OS X 10.12 - os: osx osx_image: xcode8.3 # OS X 10.12 + - os: osx + osx_image: xcode9 # OS X 10.13 + - os: osx + osx_image: xcode9.1 # OS X 10.13.1 - os: linux dist: trusty sudo: required From b0c73387f0cd76d921ea2102a63462aad66008e8 Mon Sep 17 00:00:00 2001 From: merlokk Date: Sat, 2 Dec 2017 22:10:25 +0200 Subject: [PATCH 008/127] added if --- .travis.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index eed0f8e5..94030db5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -28,7 +28,11 @@ before_install: sudo apt-get install -y gcc-arm-none-eabi; elif [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update; - brew tap "$REPOSITORY_EP"; + if [[ "$REPOSITORY_EP" == "" ]]; then + brew tap proxmark/proxmark3; + else + brew tap "$REPOSITORY_EP"; + fi fi install: From 1e431c5d360fc1fde456c0dac3fb5c6085826aff Mon Sep 17 00:00:00 2001 From: merlokk Date: Sat, 2 Dec 2017 22:12:41 +0200 Subject: [PATCH 009/127] get rid of tabs) --- .travis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 94030db5..918240c7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -28,11 +28,11 @@ before_install: sudo apt-get install -y gcc-arm-none-eabi; elif [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update; - if [[ "$REPOSITORY_EP" == "" ]]; then + if [[ "$REPOSITORY_EP" == "" ]]; then brew tap proxmark/proxmark3; - else + else brew tap "$REPOSITORY_EP"; - fi + fi fi install: From b1c0f020988313a286f45669dcc505e66533640c Mon Sep 17 00:00:00 2001 From: merlokk Date: Sun, 24 Dec 2017 00:28:38 +0200 Subject: [PATCH 010/127] added xcode 9.2 and some logging --- .travis.yml | 7 ++++--- travis_test_commands.scr | 1 + 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 918240c7..8e9289b1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,9 +12,9 @@ matrix: - os: osx osx_image: xcode8.3 # OS X 10.12 - os: osx - osx_image: xcode9 # OS X 10.13 + osx_image: xcode9 # OS X 10.12 - os: osx - osx_image: xcode9.1 # OS X 10.13.1 + osx_image: xcode9.2 # OS X 10.12 - os: linux dist: trusty sudo: required @@ -23,6 +23,7 @@ before_install: ## Install ARM toolchain on Linux. ## add our homebrew tap for MacOS ## Note: all dependencies on MacOS should be resolved by the brew install command + echo $REPOSITORY_EP; if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get update -qq; sudo apt-get install -y gcc-arm-none-eabi; @@ -31,7 +32,7 @@ before_install: if [[ "$REPOSITORY_EP" == "" ]]; then brew tap proxmark/proxmark3; else - brew tap "$REPOSITORY_EP"; + brew tap "$REPOSITORY_EP" --env=std; fi fi diff --git a/travis_test_commands.scr b/travis_test_commands.scr index 0dba3526..4f5b025c 100644 --- a/travis_test_commands.scr +++ b/travis_test_commands.scr @@ -1,2 +1,3 @@ hf mf hardnested t 1 000000000000 +hf emv test exit From b838c4ff272c2e48cc24b73dba35eda7e810d0b8 Mon Sep 17 00:00:00 2001 From: pwpiwi Date: Thu, 28 Dec 2017 08:49:07 +0100 Subject: [PATCH 011/127] Minor fixes * fix compiler warnings on Ubuntu * cmdhf14a.c: make manufactureMapping static * cmdhf14a.c: fix format strings --- client/cmdhf14a.c | 14 ++++++++++---- client/cmdhf14a.h | 6 ------ client/emv/crypto_polarssl.c | 4 ++-- client/emv/emv_pki.c | 4 ++-- client/emv/test/crypto_test.c | 4 ++-- client/util.c | 2 +- 6 files changed, 17 insertions(+), 17 deletions(-) diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index 8064724c..856d37b3 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "util.h" #include "util_posix.h" #include "iso14443crc.h" @@ -34,8 +35,13 @@ static int CmdHelp(const char *Cmd); static int waitCmd(uint8_t iLen); +// structure and database for uid -> tagtype lookups +typedef struct { + uint8_t uid; + char* desc; +} manufactureName; -const manufactureName manufactureMapping[] = { +static const manufactureName manufactureMapping[] = { // ID, "Vendor Country" { 0x01, "Motorola UK" }, { 0x02, "ST Microelectronics SA France" }, @@ -153,7 +159,7 @@ int CmdHF14AReader(const char *Cmd) { break; case 'x': case 'X': - cm = cm - ISO14A_CONNECT; + cm &= ~ISO14A_CONNECT; break; default: PrintAndLog("Unknown command."); @@ -191,7 +197,7 @@ int CmdHF14AReader(const char *Cmd) { PrintAndLog(" UID : %s", sprint_hex(card.uid, card.uidlen)); PrintAndLog("ATQA : %02x %02x", card.atqa[1], card.atqa[0]); - PrintAndLog(" SAK : %02x [%d]", card.sak, resp.arg[0]); + PrintAndLog(" SAK : %02x [%" PRIu64 "]", card.sak, resp.arg[0]); if(card.ats_len >= 3) { // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes PrintAndLog(" ATS : %s", sprint_hex(card.ats, card.ats_len)); } @@ -243,7 +249,7 @@ int CmdHF14AInfo(const char *Cmd) PrintAndLog(" UID : %s", sprint_hex(card.uid, card.uidlen)); PrintAndLog("ATQA : %02x %02x", card.atqa[1], card.atqa[0]); - PrintAndLog(" SAK : %02x [%d]", card.sak, resp.arg[0]); + PrintAndLog(" SAK : %02x [%" PRIu64 "]", card.sak, resp.arg[0]); bool isMifareClassic = true; switch (card.sak) { diff --git a/client/cmdhf14a.h b/client/cmdhf14a.h index 401cead0..71007f95 100644 --- a/client/cmdhf14a.h +++ b/client/cmdhf14a.h @@ -15,12 +15,6 @@ #include #include -// structure and database for uid -> tagtype lookups -typedef struct { - uint8_t uid; - char* desc; -} manufactureName; - int CmdHF14A(const char *Cmd); int CmdHF14AList(const char *Cmd); int CmdHF14AMifare(const char *Cmd); diff --git a/client/emv/crypto_polarssl.c b/client/emv/crypto_polarssl.c index 760395c4..3d11afe5 100644 --- a/client/emv/crypto_polarssl.c +++ b/client/emv/crypto_polarssl.c @@ -215,7 +215,7 @@ static unsigned char *crypto_pk_polarssl_encrypt(const struct crypto_pk *_cp, co res = rsa_public(&cp->ctx, buf, result); if(res) { - printf("RSA encrypt failed. Error: %x data len: %d key len: %d\n", res * -1, len, keylen); + printf("RSA encrypt failed. Error: %x data len: %zd key len: %zd\n", res * -1, len, keylen); return NULL; } @@ -241,7 +241,7 @@ static unsigned char *crypto_pk_polarssl_decrypt(const struct crypto_pk *_cp, co res = rsa_private(&cp->ctx, buf, result); // CHECK??? if(res) { - printf("RSA decrypt failed. Error: %x data len: %d key len: %d\n", res * -1, len, keylen); + printf("RSA decrypt failed. Error: %x data len: %zd key len: %zd\n", res * -1, len, keylen); return NULL; } diff --git a/client/emv/emv_pki.c b/client/emv/emv_pki.c index 7803060e..f79e3045 100644 --- a/client/emv/emv_pki.c +++ b/client/emv/emv_pki.c @@ -53,7 +53,7 @@ static unsigned char *emv_pki_decode_message(const struct emv_pk *enc_pk, } if (cert_tlv->len != enc_pk->mlen) { - printf("ERROR: Certificate length (%d) not equal key length (%d)\n", cert_tlv->len, enc_pk->mlen); + printf("ERROR: Certificate length (%zd) not equal key length (%zd)\n", cert_tlv->len, enc_pk->mlen); return NULL; } kcp = crypto_pk_open(enc_pk->pk_algo, @@ -451,7 +451,7 @@ struct tlvdb *emv_pki_perform_cda_ex(const struct emv_pk *enc_pk, const struct t un_tlv, NULL); if (!data || data_len < 3) { - printf("ERROR: can't decode message. len %d\n", data_len); + printf("ERROR: can't decode message. len %zd\n", data_len); return NULL; } diff --git a/client/emv/test/crypto_test.c b/client/emv/test/crypto_test.c index ff18b9da..352f48b4 100644 --- a/client/emv/test/crypto_test.c +++ b/client/emv/test/crypto_test.c @@ -219,7 +219,7 @@ static int test_pk(bool verbose) tmp = crypto_pk_get_parameter(pubk, 0, &tmp_len); if (tmp_len != sizeof(pk_N) || memcmp(tmp, pk_N, tmp_len)) { - fprintf(stderr, "ERROR: crypto_pk_get_parameter(0) Modulus. param len %d len %d\n", tmp_len, sizeof(pk_N)); + fprintf(stderr, "ERROR: crypto_pk_get_parameter(0) Modulus. param len %zd len %zd\n", tmp_len, sizeof(pk_N)); free(tmp); goto close_pub; } @@ -256,7 +256,7 @@ static int test_pk(bool verbose) tmp = crypto_pk_get_parameter(privk, 0, &tmp_len); if (tmp_len != sizeof(pk_N) || memcmp(tmp, pk_N, tmp_len)) { - fprintf(stderr, "ERROR: crypto_pk_get_parameter(0) Modulus. param len %d len %d\n", tmp_len, sizeof(pk_N)); + fprintf(stderr, "ERROR: crypto_pk_get_parameter(0) Modulus. param len %zd len %zd\n", tmp_len, sizeof(pk_N)); free(tmp); goto close; } diff --git a/client/util.c b/client/util.c index b7f07bde..568992ab 100644 --- a/client/util.c +++ b/client/util.c @@ -620,7 +620,7 @@ int hextobinarray(char *target, char *source) else if (x >= 'A' && x <= 'F') x -= 'A' - 10; else { - printf("Discovered unknown character %c %d at idx %d of %s\n", x, x, source - start, start); + printf("Discovered unknown character %c %d at idx %d of %s\n", x, x, (unsigned int)(source - start), start); return 0; } // output From 4a768458d2335fc3594f7a7f09bb4066442bed3f Mon Sep 17 00:00:00 2001 From: merlokk Date: Tue, 2 Jan 2018 19:05:12 +0200 Subject: [PATCH 012/127] hardnested SIMD select --- client/cmdhfmfhard.c | 40 ++++++---- client/hardnested/hardnested_bf_core.c | 106 ++++++++++++++++++------- client/hardnested/hardnested_bf_core.h | 12 +++ 3 files changed, 112 insertions(+), 46 deletions(-) diff --git a/client/cmdhfmfhard.c b/client/cmdhfmfhard.c index 0153541e..cbdf3f60 100644 --- a/client/cmdhfmfhard.c +++ b/client/cmdhfmfhard.c @@ -32,6 +32,7 @@ #include "crapto1/crapto1.h" #include "parity.h" #include "hardnested/hardnested_bruteforce.h" +#include "hardnested/hardnested_bf_core.h" #include "hardnested/hardnested_bitarray_core.h" #include "zlib.h" @@ -71,27 +72,32 @@ static float brute_force_per_second; static void get_SIMD_instruction_set(char* instruction_set) { -#if defined (__i386__) || defined (__x86_64__) - #if !defined(__APPLE__) || (defined(__APPLE__) && (__clang_major__ > 8 || __clang_major__ == 8 && __clang_minor__ >= 1)) - #if (__GNUC__ >= 5) && (__GNUC__ > 5 || __GNUC_MINOR__ > 2) - if (__builtin_cpu_supports("avx512f")) strcpy(instruction_set, "AVX512F"); - else if (__builtin_cpu_supports("avx2")) strcpy(instruction_set, "AVX2"); - #else - if (__builtin_cpu_supports("avx2")) strcpy(instruction_set, "AVX2"); - #endif - else if (__builtin_cpu_supports("avx")) strcpy(instruction_set, "AVX"); - else if (__builtin_cpu_supports("sse2")) strcpy(instruction_set, "SSE2"); - else if (__builtin_cpu_supports("mmx")) strcpy(instruction_set, "MMX"); - else - #endif -#endif - strcpy(instruction_set, "no"); + switch(GetSIMDInstrAuto()) { + case SIMD_AVX512: + strcpy(instruction_set, "AVX512F"); + break; + case SIMD_AVX2: + strcpy(instruction_set, "AVX2"); + break; + case SIMD_AVX: + strcpy(instruction_set, "AVX"); + break; + case SIMD_SSE2: + strcpy(instruction_set, "SSE2"); + break; + case SIMD_MMX: + strcpy(instruction_set, "MMX"); + break; + default: + strcpy(instruction_set, "no"); + break; + } } static void print_progress_header(void) { char progress_text[80]; - char instr_set[12] = ""; + char instr_set[12] = {0}; get_SIMD_instruction_set(instr_set); sprintf(progress_text, "Start using %d threads and %s SIMD core", num_CPUs(), instr_set); PrintAndLog("\n\n"); @@ -2528,6 +2534,8 @@ static void set_test_state(uint8_t byte) int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *trgkey, bool nonce_file_read, bool nonce_file_write, bool slow, int tests) { char progress_text[80]; + + SetSIMDInstr(SIMD_NONE); srand((unsigned) time(NULL)); brute_force_per_second = brute_force_benchmark(); diff --git a/client/hardnested/hardnested_bf_core.c b/client/hardnested/hardnested_bf_core.c index 3c0c044f..d716f702 100644 --- a/client/hardnested/hardnested_bf_core.c +++ b/client/hardnested/hardnested_bf_core.c @@ -544,48 +544,94 @@ out: #ifndef __MMX__ +static SIMDExecInstr intSIMDInstr = SIMD_AUTO; + +void SetSIMDInstr(SIMDExecInstr instr) { + intSIMDInstr = instr; +} + +SIMDExecInstr GetSIMDInstr() { + SIMDExecInstr instr = SIMD_NONE; + +#if defined (__i386__) || defined (__x86_64__) + #if !defined(__APPLE__) || (defined(__APPLE__) && (__clang_major__ > 8 || __clang_major__ == 8 && __clang_minor__ >= 1)) + #if (__GNUC__ >= 5) && (__GNUC__ > 5 || __GNUC_MINOR__ > 2) + if (__builtin_cpu_supports("avx512f")) instr = SIMD_AVX512; + else if (__builtin_cpu_supports("avx2")) instr = SIMD_AVX2; + #else + if (__builtin_cpu_supports("avx2")) instr = SIMD_AVX2; + #endif + else if (__builtin_cpu_supports("avx")) instr = SIMD_AVX; + else if (__builtin_cpu_supports("sse2")) instr = SIMD_SSE2; + else if (__builtin_cpu_supports("mmx")) instr = SIMD_MMX; + else + #endif +#endif + instr = SIMD_NONE; + + return instr; +} + +SIMDExecInstr GetSIMDInstrAuto() { + SIMDExecInstr instr = intSIMDInstr; + if (instr == SIMD_AUTO) + return GetSIMDInstr(); + + return instr; +} + // pointers to functions: crack_states_bitsliced_t *crack_states_bitsliced_function_p = &crack_states_bitsliced_dispatch; bitslice_test_nonces_t *bitslice_test_nonces_function_p = &bitslice_test_nonces_dispatch; // determine the available instruction set at runtime and call the correct function const uint64_t crack_states_bitsliced_dispatch(uint32_t cuid, uint8_t *best_first_bytes, statelist_t *p, uint32_t *keys_found, uint64_t *num_keys_tested, uint32_t nonces_to_bruteforce, uint8_t *bf_test_nonce_2nd_byte, noncelist_t *nonces) { -#if defined (__i386__) || defined (__x86_64__) - #if !defined(__APPLE__) || (defined(__APPLE__) && (__clang_major__ > 8 || __clang_major__ == 8 && __clang_minor__ >= 1)) - #if (__GNUC__ >= 5) && (__GNUC__ > 5 || __GNUC_MINOR__ > 2) - if (__builtin_cpu_supports("avx512f")) crack_states_bitsliced_function_p = &crack_states_bitsliced_AVX512; - else if (__builtin_cpu_supports("avx2")) crack_states_bitsliced_function_p = &crack_states_bitsliced_AVX2; - #else - if (__builtin_cpu_supports("avx2")) crack_states_bitsliced_function_p = &crack_states_bitsliced_AVX2; - #endif - else if (__builtin_cpu_supports("avx")) crack_states_bitsliced_function_p = &crack_states_bitsliced_AVX; - else if (__builtin_cpu_supports("sse2")) crack_states_bitsliced_function_p = &crack_states_bitsliced_SSE2; - else if (__builtin_cpu_supports("mmx")) crack_states_bitsliced_function_p = &crack_states_bitsliced_MMX; - else - #endif -#endif - crack_states_bitsliced_function_p = &crack_states_bitsliced_NOSIMD; + switch(GetSIMDInstrAuto()) { + case SIMD_AVX512: + crack_states_bitsliced_function_p = &crack_states_bitsliced_AVX512; + break; + case SIMD_AVX2: + crack_states_bitsliced_function_p = &crack_states_bitsliced_AVX2; + break; + case SIMD_AVX: + crack_states_bitsliced_function_p = &crack_states_bitsliced_AVX; + break; + case SIMD_SSE2: + crack_states_bitsliced_function_p = &crack_states_bitsliced_SSE2; + break; + case SIMD_MMX: + crack_states_bitsliced_function_p = &crack_states_bitsliced_MMX; + break; + default: + crack_states_bitsliced_function_p = &crack_states_bitsliced_NOSIMD; + break; + } // call the most optimized function for this CPU return (*crack_states_bitsliced_function_p)(cuid, best_first_bytes, p, keys_found, num_keys_tested, nonces_to_bruteforce, bf_test_nonce_2nd_byte, nonces); } void bitslice_test_nonces_dispatch(uint32_t nonces_to_bruteforce, uint32_t *bf_test_nonce, uint8_t *bf_test_nonce_par) { -#if defined (__i386__) || defined (__x86_64__) - #if !defined(__APPLE__) || (defined(__APPLE__) && (__clang_major__ > 8 || __clang_major__ == 8 && __clang_minor__ >= 1)) - #if (__GNUC__ >= 5) && (__GNUC__ > 5 || __GNUC_MINOR__ > 2) - if (__builtin_cpu_supports("avx512f")) bitslice_test_nonces_function_p = &bitslice_test_nonces_AVX512; - else if (__builtin_cpu_supports("avx2")) bitslice_test_nonces_function_p = &bitslice_test_nonces_AVX2; - #else - if (__builtin_cpu_supports("avx2")) bitslice_test_nonces_function_p = &bitslice_test_nonces_AVX2; - #endif - else if (__builtin_cpu_supports("avx")) bitslice_test_nonces_function_p = &bitslice_test_nonces_AVX; - else if (__builtin_cpu_supports("sse2")) bitslice_test_nonces_function_p = &bitslice_test_nonces_SSE2; - else if (__builtin_cpu_supports("mmx")) bitslice_test_nonces_function_p = &bitslice_test_nonces_MMX; - else - #endif -#endif - bitslice_test_nonces_function_p = &bitslice_test_nonces_NOSIMD; + switch(GetSIMDInstrAuto()) { + case SIMD_AVX512: + bitslice_test_nonces_function_p = &bitslice_test_nonces_AVX512; + break; + case SIMD_AVX2: + bitslice_test_nonces_function_p = &bitslice_test_nonces_AVX2; + break; + case SIMD_AVX: + bitslice_test_nonces_function_p = &bitslice_test_nonces_AVX; + break; + case SIMD_SSE2: + bitslice_test_nonces_function_p = &bitslice_test_nonces_SSE2; + break; + case SIMD_MMX: + bitslice_test_nonces_function_p = &bitslice_test_nonces_MMX; + break; + default: + bitslice_test_nonces_function_p = &bitslice_test_nonces_NOSIMD; + break; + } // call the most optimized function for this CPU (*bitslice_test_nonces_function_p)(nonces_to_bruteforce, bf_test_nonce, bf_test_nonce_par); diff --git a/client/hardnested/hardnested_bf_core.h b/client/hardnested/hardnested_bf_core.h index 7a445993..b3df0547 100644 --- a/client/hardnested/hardnested_bf_core.h +++ b/client/hardnested/hardnested_bf_core.h @@ -52,6 +52,18 @@ THE SOFTWARE. #include "hardnested_bruteforce.h" // statelist_t +typedef enum { + SIMD_AUTO, + SIMD_AVX512, + SIMD_AVX2, + SIMD_AVX, + SIMD_SSE2, + SIMD_MMX, + SIMD_NONE, +} SIMDExecInstr; +extern void SetSIMDInstr(SIMDExecInstr instr); +extern SIMDExecInstr GetSIMDInstrAuto(); + extern const uint64_t crack_states_bitsliced(uint32_t cuid, uint8_t *best_first_bytes, statelist_t *p, uint32_t *keys_found, uint64_t *num_keys_tested, uint32_t nonces_to_bruteforce, uint8_t *bf_test_nonces_2nd_byte, noncelist_t *nonces); extern void bitslice_test_nonces(uint32_t nonces_to_bruteforce, uint32_t *bf_test_nonces, uint8_t *bf_test_nonce_par); From eaecd7f541bf64c9ae0681d1f9c4b6bac2c7322b Mon Sep 17 00:00:00 2001 From: merlokk Date: Tue, 2 Jan 2018 19:11:26 +0200 Subject: [PATCH 013/127] add print SIMD core at the beginning --- client/cmdhfmfhard.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/client/cmdhfmfhard.c b/client/cmdhfmfhard.c index cbdf3f60..652a3cad 100644 --- a/client/cmdhfmfhard.c +++ b/client/cmdhfmfhard.c @@ -2536,6 +2536,9 @@ int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBloc char progress_text[80]; SetSIMDInstr(SIMD_NONE); + char instr_set[12] = {0}; + get_SIMD_instruction_set(instr_set); + PrintAndLog("Using %s SIMD core.", instr_set); srand((unsigned) time(NULL)); brute_force_per_second = brute_force_benchmark(); From 362d20390902245e943e307500c9ef02986160e2 Mon Sep 17 00:00:00 2001 From: merlokk Date: Tue, 2 Jan 2018 22:28:13 +0200 Subject: [PATCH 014/127] works --- client/cmdhfmf.c | 50 +++++++++++++++++++++++++- client/cmdhfmfhard.c | 1 - client/hardnested/hardnested_bf_core.c | 11 +++--- 3 files changed, 56 insertions(+), 6 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index d9578af2..ed08917a 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -25,6 +25,7 @@ #include "mifarehost.h" #include "mifare.h" #include "mfkey.h" +#include "hardnested/hardnested_bf_core.h" #define NESTED_SECTOR_RETRY 10 // how often we try mfested() until we give up @@ -862,6 +863,13 @@ int CmdHF14AMfNestedHard(const char *Cmd) PrintAndLog(" w: Acquire nonces and write them to binary file nonces.bin"); PrintAndLog(" s: Slower acquisition (required by some non standard cards)"); PrintAndLog(" r: Read nonces.bin and start attack"); + PrintAndLog(" iX: set type of SIMD instructions. Without this flag programs autodetect it."); + PrintAndLog(" i5: AVX512"); + PrintAndLog(" i2: AVX2"); + PrintAndLog(" ia: AVX"); + PrintAndLog(" is: SSE2"); + PrintAndLog(" im: MMX"); + PrintAndLog(" in: none (use CPU regular instruction set)"); PrintAndLog(" "); PrintAndLog(" sample1: hf mf hardnested 0 A FFFFFFFFFFFF 4 A"); PrintAndLog(" sample2: hf mf hardnested 0 A FFFFFFFFFFFF 4 A w"); @@ -880,15 +888,20 @@ int CmdHF14AMfNestedHard(const char *Cmd) int tests = 0; + uint16_t iindx = 0; if (ctmp == 'R' || ctmp == 'r') { nonce_file_read = true; + iindx = 1; if (!param_gethex(Cmd, 1, trgkey, 12)) { know_target_key = true; + iindx = 2; } } else if (ctmp == 'T' || ctmp == 't') { tests = param_get32ex(Cmd, 1, 100, 10); + iindx = 2; if (!param_gethex(Cmd, 2, trgkey, 12)) { know_target_key = true; + iindx = 3; } } else { blockNo = param_get8(Cmd, 0); @@ -922,19 +935,54 @@ int CmdHF14AMfNestedHard(const char *Cmd) know_target_key = true; i++; } + iindx = i; while ((ctmp = param_getchar(Cmd, i))) { if (ctmp == 's' || ctmp == 'S') { slow = true; } else if (ctmp == 'w' || ctmp == 'W') { nonce_file_write = true; + } else if (param_getlength(Cmd, i) == 2 && ctmp == 'i') { + iindx = i; } else { - PrintAndLog("Possible options are w and/or s"); + PrintAndLog("Possible options are w , s and/or iX"); return 1; } i++; } } + + SetSIMDInstr(SIMD_AUTO); + if (iindx > 0) { + while ((ctmp = param_getchar(Cmd, iindx))) { + if (param_getlength(Cmd, iindx) == 2 && ctmp == 'i') { + switch(param_getchar_indx(Cmd, 1, iindx)) { + case '5': + SetSIMDInstr(SIMD_AVX512); + break; + case '2': + SetSIMDInstr(SIMD_AVX2); + break; + case 'a': + SetSIMDInstr(SIMD_AVX); + break; + case 's': + SetSIMDInstr(SIMD_SSE2); + break; + case 'm': + SetSIMDInstr(SIMD_MMX); + break; + case 'n': + SetSIMDInstr(SIMD_NONE); + break; + default: + PrintAndLog("Unknown SIMD type. %c", param_getchar_indx(Cmd, 1, iindx)); + return 1; + } + } + iindx++; + } + } PrintAndLog("--target block no:%3d, target key type:%c, known target key: 0x%02x%02x%02x%02x%02x%02x%s, file action: %s, Slow: %s, Tests: %d ", trgBlockNo, diff --git a/client/cmdhfmfhard.c b/client/cmdhfmfhard.c index 652a3cad..96c3a989 100644 --- a/client/cmdhfmfhard.c +++ b/client/cmdhfmfhard.c @@ -2535,7 +2535,6 @@ int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBloc { char progress_text[80]; - SetSIMDInstr(SIMD_NONE); char instr_set[12] = {0}; get_SIMD_instruction_set(instr_set); PrintAndLog("Using %s SIMD core.", instr_set); diff --git a/client/hardnested/hardnested_bf_core.c b/client/hardnested/hardnested_bf_core.c index d716f702..78384bbc 100644 --- a/client/hardnested/hardnested_bf_core.c +++ b/client/hardnested/hardnested_bf_core.c @@ -544,10 +544,17 @@ out: #ifndef __MMX__ +// pointers to functions: +crack_states_bitsliced_t *crack_states_bitsliced_function_p = &crack_states_bitsliced_dispatch; +bitslice_test_nonces_t *bitslice_test_nonces_function_p = &bitslice_test_nonces_dispatch; + static SIMDExecInstr intSIMDInstr = SIMD_AUTO; void SetSIMDInstr(SIMDExecInstr instr) { intSIMDInstr = instr; + + crack_states_bitsliced_function_p = &crack_states_bitsliced_dispatch; + bitslice_test_nonces_function_p = &bitslice_test_nonces_dispatch; } SIMDExecInstr GetSIMDInstr() { @@ -580,10 +587,6 @@ SIMDExecInstr GetSIMDInstrAuto() { return instr; } -// pointers to functions: -crack_states_bitsliced_t *crack_states_bitsliced_function_p = &crack_states_bitsliced_dispatch; -bitslice_test_nonces_t *bitslice_test_nonces_function_p = &bitslice_test_nonces_dispatch; - // determine the available instruction set at runtime and call the correct function const uint64_t crack_states_bitsliced_dispatch(uint32_t cuid, uint8_t *best_first_bytes, statelist_t *p, uint32_t *keys_found, uint64_t *num_keys_tested, uint32_t nonces_to_bruteforce, uint8_t *bf_test_nonce_2nd_byte, noncelist_t *nonces) { switch(GetSIMDInstrAuto()) { From 58f0ae45c1f3bbe6d962aece3694c61f78475da3 Mon Sep 17 00:00:00 2001 From: merlokk Date: Fri, 5 Jan 2018 11:51:51 +0200 Subject: [PATCH 015/127] move travis files --- .travis.yml => CI/.travis.yml | 0 CI/readme.md | 19 +++++++++++++++++++ .../travis_test_commands.scr | 0 3 files changed, 19 insertions(+) rename .travis.yml => CI/.travis.yml (100%) create mode 100644 CI/readme.md rename travis_test_commands.scr => CI/travis_test_commands.scr (100%) diff --git a/.travis.yml b/CI/.travis.yml similarity index 100% rename from .travis.yml rename to CI/.travis.yml diff --git a/CI/readme.md b/CI/readme.md new file mode 100644 index 00000000..bcfc4542 --- /dev/null +++ b/CI/readme.md @@ -0,0 +1,19 @@ +# How to configure continuous integration + +Here 2 CI configuration files: + +1. for [travis](travis-ci.org) +2. for [appveyor](appveyor.com) + +It needs to put files from this directory to repository root and then configure CI from appropriate WEB portal. + +## travis + +- Copy .travis.yml and travis_test_commands.scr files to repository root +- Configure CI from http://travis-ci.org +- It needs to clone https://github.com/Proxmark/homebrew-proxmark3 from your proxmark repository home + + +## appveyor + +- Just copy appveyor.yml file to root and configure it from http://appveyor.com diff --git a/travis_test_commands.scr b/CI/travis_test_commands.scr similarity index 100% rename from travis_test_commands.scr rename to CI/travis_test_commands.scr From 7421ab0b43ba71f214f3cf24e28aa32d4e2ed844 Mon Sep 17 00:00:00 2001 From: merlokk Date: Fri, 5 Jan 2018 13:04:17 +0200 Subject: [PATCH 016/127] fix readme --- CI/readme.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CI/readme.md b/CI/readme.md index bcfc4542..d4159290 100644 --- a/CI/readme.md +++ b/CI/readme.md @@ -11,7 +11,8 @@ It needs to put files from this directory to repository root and then configure - Copy .travis.yml and travis_test_commands.scr files to repository root - Configure CI from http://travis-ci.org -- It needs to clone https://github.com/Proxmark/homebrew-proxmark3 from your proxmark repository home +- It needs to fork https://github.com/Proxmark/homebrew-proxmark3 from your proxmark repository home +- Put to file `proxmark3.rb` in line `head "https://github.com/proxmark/proxmark3.git"` your repository link. As sample: `head "https://github.com/merlokk/proxmark3.git"` ## appveyor From 4ed45d444b68b9a9e521618ae412d90c51695b31 Mon Sep 17 00:00:00 2001 From: merlokk Date: Fri, 5 Jan 2018 18:36:00 +0200 Subject: [PATCH 017/127] fix #404 --- client/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/Makefile b/client/Makefile index 52a106bd..0cda2b18 100644 --- a/client/Makefile +++ b/client/Makefile @@ -207,7 +207,7 @@ MULTIARCHOBJS = $(MULTIARCHSRCS:%.c=$(OBJDIR)/%_NOSIMD.o) \ SUPPORTS_AVX512 := $(shell echo | gcc -E -mavx512f - > /dev/null 2>&1 && echo "True" ) HARD_SWITCH_NOSIMD = -mno-mmx -mno-sse2 -mno-avx -mno-avx2 HARD_SWITCH_MMX = -mmmx -mno-sse2 -mno-avx -mno-avx2 -HARD_SWITCH_SSE2 = -mmmx -msse2 -mno-avx -mno-avx2 +HARD_SWITCH_SSE2 = -mmmx -msse2 -mno-avx -mno-avx2 -mstackrealign HARD_SWITCH_AVX = -mmmx -msse2 -mavx -mno-avx2 HARD_SWITCH_AVX2 = -mmmx -msse2 -mavx -mavx2 HARD_SWITCH_AVX512 = -mmmx -msse2 -mavx -mavx2 -mavx512f From ab0582d672e1c2cbb1a49652cc8358218f672244 Mon Sep 17 00:00:00 2001 From: merlokk Date: Sat, 6 Jan 2018 19:14:34 +0200 Subject: [PATCH 018/127] fix another way --- client/Makefile | 2 +- client/hardnested/hardnested_bruteforce.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/Makefile b/client/Makefile index 0cda2b18..52a106bd 100644 --- a/client/Makefile +++ b/client/Makefile @@ -207,7 +207,7 @@ MULTIARCHOBJS = $(MULTIARCHSRCS:%.c=$(OBJDIR)/%_NOSIMD.o) \ SUPPORTS_AVX512 := $(shell echo | gcc -E -mavx512f - > /dev/null 2>&1 && echo "True" ) HARD_SWITCH_NOSIMD = -mno-mmx -mno-sse2 -mno-avx -mno-avx2 HARD_SWITCH_MMX = -mmmx -mno-sse2 -mno-avx -mno-avx2 -HARD_SWITCH_SSE2 = -mmmx -msse2 -mno-avx -mno-avx2 -mstackrealign +HARD_SWITCH_SSE2 = -mmmx -msse2 -mno-avx -mno-avx2 HARD_SWITCH_AVX = -mmmx -msse2 -mavx -mno-avx2 HARD_SWITCH_AVX2 = -mmmx -msse2 -mavx -mavx2 HARD_SWITCH_AVX512 = -mmmx -msse2 -mavx -mavx2 -mavx512f diff --git a/client/hardnested/hardnested_bruteforce.c b/client/hardnested/hardnested_bruteforce.c index 718b7c5d..3072fc52 100644 --- a/client/hardnested/hardnested_bruteforce.c +++ b/client/hardnested/hardnested_bruteforce.c @@ -140,7 +140,7 @@ bool verify_key(uint32_t cuid, noncelist_t *nonces, uint8_t *best_first_bytes, u } -static void* crack_states_thread(void* x){ +static void* __attribute__((force_align_arg_pointer)) crack_states_thread(void* x){ struct arg { bool silent; From 84e86ed9e3c435bd386370ea4c18887decfb48c6 Mon Sep 17 00:00:00 2001 From: merlokk Date: Sun, 7 Jan 2018 23:23:35 +0200 Subject: [PATCH 019/127] move appveyor.yml --- appveyor.yml => CI/appveyor.yml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename appveyor.yml => CI/appveyor.yml (100%) diff --git a/appveyor.yml b/CI/appveyor.yml similarity index 100% rename from appveyor.yml rename to CI/appveyor.yml From 2d51da38f380302722bc91264c620190ce76a73f Mon Sep 17 00:00:00 2001 From: Iceman Date: Wed, 10 Jan 2018 13:56:27 +0100 Subject: [PATCH 020/127] HW TUNE adapting for powerful antennas. (#540) CHG: 'hw tune' adapting LF measuring from ( >> 8) max 65v, to ( >>9 ) max 130v in the graph data. Max LF voltage is 140.8v to measure. Added a delay for antenna coil and caps to power up before measuring, removed a variable in ReadAdc --- armsrc/appmain.c | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index e292483b..65fc6de6 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -135,15 +135,7 @@ void Dbhexdump(int len, uint8_t *d, bool bAsci) { // return that. //----------------------------------------------------------------------------- static int ReadAdc(int ch) -{ - uint32_t d; - - AT91C_BASE_ADC->ADC_CR = AT91C_ADC_SWRST; - AT91C_BASE_ADC->ADC_MR = - ADC_MODE_PRESCALE(63 /* was 32 */) | // ADC_CLK = MCK / ((63+1) * 2) = 48MHz / 128 = 375kHz - ADC_MODE_STARTUP_TIME(1 /* was 16 */) | // Startup Time = (1+1) * 8 / ADC_CLK = 16 / 375kHz = 42,7us Note: must be > 20us - ADC_MODE_SAMPLE_HOLD_TIME(15 /* was 8 */); // Sample & Hold Time SHTIM = 15 / ADC_CLK = 15 / 375kHz = 40us - +{ // Note: ADC_MODE_PRESCALE and ADC_MODE_SAMPLE_HOLD_TIME are set to the maximum allowed value. // Both AMPL_LO and AMPL_HI are very high impedance (10MOhm) outputs, the input capacitance of the ADC is 12pF (typical). This results in a time constant // of RC = 10MOhm * 12pF = 120us. Even after the maximum configurable sample&hold time of 40us the input capacitor will not be fully charged. @@ -154,16 +146,19 @@ static int ReadAdc(int ch) // v_cap = v_in * (1 - exp(-RC/SHTIM)) = v_in * (1 - exp(-3)) = v_in * 0,95 (i.e. an error of 5%) // // Note: with the "historic" values in the comments above, the error was 34% !!! - - AT91C_BASE_ADC->ADC_CHER = ADC_CHANNEL(ch); + AT91C_BASE_ADC->ADC_CR = AT91C_ADC_SWRST; + AT91C_BASE_ADC->ADC_MR = + ADC_MODE_PRESCALE(63 /* was 32 */) | // ADC_CLK = MCK / ((63+1) * 2) = 48MHz / 128 = 375kHz + ADC_MODE_STARTUP_TIME(1 /* was 16 */) | // Startup Time = (1+1) * 8 / ADC_CLK = 16 / 375kHz = 42,7us Note: must be > 20us + ADC_MODE_SAMPLE_HOLD_TIME(15 /* was 8 */); // Sample & Hold Time SHTIM = 15 / ADC_CLK = 15 / 375kHz = 40us + + AT91C_BASE_ADC->ADC_CHER = ADC_CHANNEL(ch); AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START; - while(!(AT91C_BASE_ADC->ADC_SR & ADC_END_OF_CONVERSION(ch))) - ; - d = AT91C_BASE_ADC->ADC_CDR[ch]; - - return d; + while(!(AT91C_BASE_ADC->ADC_SR & ADC_END_OF_CONVERSION(ch))) {}; + + return AT91C_BASE_ADC->ADC_CDR[ch]; } int AvgAdc(int ch) // was static - merlok @@ -180,7 +175,8 @@ int AvgAdc(int ch) // was static - merlok void MeasureAntennaTuningLfOnly(int *vLf125, int *vLf134, int *peakf, int *peakv, uint8_t LF_Results[]) { - int i, adcval = 0, peak = 0; + uint8_t i; + int adcval = 0, peak = 0; /* * Sweeps the useful LF range of the proxmark from @@ -193,6 +189,8 @@ void MeasureAntennaTuningLfOnly(int *vLf125, int *vLf134, int *peakf, int *peakv FpgaDownloadAndGo(FPGA_BITSTREAM_LF); FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); + SpinDelay(50); + for (i=255; i>=19; i--) { WDT_HIT(); FpgaSendCommand(FPGA_CMD_SET_DIVISOR, i); @@ -201,7 +199,7 @@ void MeasureAntennaTuningLfOnly(int *vLf125, int *vLf134, int *peakf, int *peakv if (i==95) *vLf125 = adcval; // voltage at 125Khz if (i==89) *vLf134 = adcval; // voltage at 134Khz - LF_Results[i] = adcval>>8; // scale int to fit in byte for graphing purposes + LF_Results[i] = adcval >> 9; // scale int to fit in byte for graphing purposes if(LF_Results[i] > peak) { *peakv = adcval; peak = LF_Results[i]; From 9b32625c2c1d7ef36e4788c9a5f827470078f81d Mon Sep 17 00:00:00 2001 From: pwpiwi Date: Thu, 11 Jan 2018 08:32:01 +0100 Subject: [PATCH 021/127] hw tune minor fix, comments updated --- armsrc/appmain.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 65fc6de6..1c3d9398 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -137,21 +137,19 @@ void Dbhexdump(int len, uint8_t *d, bool bAsci) { static int ReadAdc(int ch) { // Note: ADC_MODE_PRESCALE and ADC_MODE_SAMPLE_HOLD_TIME are set to the maximum allowed value. - // Both AMPL_LO and AMPL_HI are very high impedance (10MOhm) outputs, the input capacitance of the ADC is 12pF (typical). This results in a time constant - // of RC = 10MOhm * 12pF = 120us. Even after the maximum configurable sample&hold time of 40us the input capacitor will not be fully charged. + // AMPL_HI is are high impedance (10MOhm || 1MOhm) output, the input capacitance of the ADC is 12pF (typical). This results in a time constant + // of RC = (0.91MOhm) * 12pF = 10.9us. Even after the maximum configurable sample&hold time of 40us the input capacitor will not be fully charged. // // The maths are: // If there is a voltage v_in at the input, the voltage v_cap at the capacitor (this is what we are measuring) will be // - // v_cap = v_in * (1 - exp(-RC/SHTIM)) = v_in * (1 - exp(-3)) = v_in * 0,95 (i.e. an error of 5%) - // - // Note: with the "historic" values in the comments above, the error was 34% !!! + // v_cap = v_in * (1 - exp(-SHTIM/RC)) = v_in * (1 - exp(-40us/10.9us)) = v_in * 0,97 (i.e. an error of 3%) AT91C_BASE_ADC->ADC_CR = AT91C_ADC_SWRST; AT91C_BASE_ADC->ADC_MR = - ADC_MODE_PRESCALE(63 /* was 32 */) | // ADC_CLK = MCK / ((63+1) * 2) = 48MHz / 128 = 375kHz - ADC_MODE_STARTUP_TIME(1 /* was 16 */) | // Startup Time = (1+1) * 8 / ADC_CLK = 16 / 375kHz = 42,7us Note: must be > 20us - ADC_MODE_SAMPLE_HOLD_TIME(15 /* was 8 */); // Sample & Hold Time SHTIM = 15 / ADC_CLK = 15 / 375kHz = 40us + ADC_MODE_PRESCALE(63) | // ADC_CLK = MCK / ((63+1) * 2) = 48MHz / 128 = 375kHz + ADC_MODE_STARTUP_TIME(1) | // Startup Time = (1+1) * 8 / ADC_CLK = 16 / 375kHz = 42,7us Note: must be > 20us + ADC_MODE_SAMPLE_HOLD_TIME(15); // Sample & Hold Time SHTIM = 15 / ADC_CLK = 15 / 375kHz = 40us AT91C_BASE_ADC->ADC_CHER = ADC_CHANNEL(ch); AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START; @@ -175,8 +173,7 @@ int AvgAdc(int ch) // was static - merlok void MeasureAntennaTuningLfOnly(int *vLf125, int *vLf134, int *peakf, int *peakv, uint8_t LF_Results[]) { - uint8_t i; - int adcval = 0, peak = 0; + int i, adcval = 0, peak = 0; /* * Sweeps the useful LF range of the proxmark from From d040cb90240062a2c164800edce6a93e440ff693 Mon Sep 17 00:00:00 2001 From: pwpiwi Date: Fri, 12 Jan 2018 21:48:42 +0100 Subject: [PATCH 022/127] hw tune: * scale results to allow higher LF voltages * remove historic comments --- armsrc/appmain.c | 2 +- client/cmddata.c | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 1c3d9398..64768922 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -244,7 +244,7 @@ void MeasureAntennaTuning(int mode) } } - cmd_send(CMD_MEASURED_ANTENNA_TUNING, vLf125 | (vLf134<<16), vHf, peakf | (peakv<<16), LF_Results, 256); + cmd_send(CMD_MEASURED_ANTENNA_TUNING, vLf125>>1 | (vLf134>>1<<16), vHf, peakf | (peakv>>1<<16), LF_Results, 256); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LED_B_OFF(); return; diff --git a/client/cmddata.c b/client/cmddata.c index 1f548284..9b960de9 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -1281,26 +1281,26 @@ int CmdTuneSamples(const char *Cmd) peakf = resp.arg[2] & 0xffff; peakv = resp.arg[2] >> 16; PrintAndLog(""); - PrintAndLog("# LF antenna: %5.2f V @ 125.00 kHz", vLf125/1000.0); - PrintAndLog("# LF antenna: %5.2f V @ 134.00 kHz", vLf134/1000.0); - PrintAndLog("# LF optimal: %5.2f V @%9.2f kHz", peakv/1000.0, 12000.0/(peakf+1)); + PrintAndLog("# LF antenna: %5.2f V @ 125.00 kHz", vLf125/500.0); + PrintAndLog("# LF antenna: %5.2f V @ 134.00 kHz", vLf134/500.0); + PrintAndLog("# LF optimal: %5.2f V @%9.2f kHz", peakv/500.0, 12000.0/(peakf+1)); PrintAndLog("# HF antenna: %5.2f V @ 13.56 MHz", vHf/1000.0); - #define LF_UNUSABLE_V 2948 // was 2000. Changed due to bugfix in voltage measurements. LF results are now 47% higher. - #define LF_MARGINAL_V 14739 // was 10000. Changed due to bugfix bug in voltage measurements. LF results are now 47% higher. - #define HF_UNUSABLE_V 3167 // was 2000. Changed due to bugfix in voltage measurements. HF results are now 58% higher. - #define HF_MARGINAL_V 7917 // was 5000. Changed due to bugfix in voltage measurements. HF results are now 58% higher. + #define LF_UNUSABLE_V 3000 + #define LF_MARGINAL_V 15000 + #define HF_UNUSABLE_V 3200 + #define HF_MARGINAL_V 8000 - if (peakv < LF_UNUSABLE_V) + if (peakv<<1 < LF_UNUSABLE_V) PrintAndLog("# Your LF antenna is unusable."); - else if (peakv < LF_MARGINAL_V) + else if (peakv<<1 < LF_MARGINAL_V) PrintAndLog("# Your LF antenna is marginal."); if (vHf < HF_UNUSABLE_V) PrintAndLog("# Your HF antenna is unusable."); else if (vHf < HF_MARGINAL_V) PrintAndLog("# Your HF antenna is marginal."); - if (peakv >= LF_UNUSABLE_V) { + if (peakv<<1 >= LF_UNUSABLE_V) { for (int i = 0; i < 256; i++) { GraphBuffer[i] = resp.d.asBytes[i] - 128; } From 078e2bd238dfddb39c33de775f5e0a68657c4504 Mon Sep 17 00:00:00 2001 From: Oleg Moiseenko Date: Fri, 12 Jan 2018 23:04:16 +0200 Subject: [PATCH 023/127] fix: SIMD instruction set detection on non-x86 hardware should fix issue #542 --- client/hardnested/hardnested_bf_core.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/client/hardnested/hardnested_bf_core.c b/client/hardnested/hardnested_bf_core.c index 78384bbc..d02209e9 100644 --- a/client/hardnested/hardnested_bf_core.c +++ b/client/hardnested/hardnested_bf_core.c @@ -590,9 +590,13 @@ SIMDExecInstr GetSIMDInstrAuto() { // determine the available instruction set at runtime and call the correct function const uint64_t crack_states_bitsliced_dispatch(uint32_t cuid, uint8_t *best_first_bytes, statelist_t *p, uint32_t *keys_found, uint64_t *num_keys_tested, uint32_t nonces_to_bruteforce, uint8_t *bf_test_nonce_2nd_byte, noncelist_t *nonces) { switch(GetSIMDInstrAuto()) { +#if defined (__i386__) || defined (__x86_64__) +#if !defined(__APPLE__) || (defined(__APPLE__) && (__clang_major__ > 8 || __clang_major__ == 8 && __clang_minor__ >= 1)) +#if (__GNUC__ >= 5) && (__GNUC__ > 5 || __GNUC_MINOR__ > 2) case SIMD_AVX512: crack_states_bitsliced_function_p = &crack_states_bitsliced_AVX512; break; +#endif case SIMD_AVX2: crack_states_bitsliced_function_p = &crack_states_bitsliced_AVX2; break; @@ -605,6 +609,8 @@ const uint64_t crack_states_bitsliced_dispatch(uint32_t cuid, uint8_t *best_firs case SIMD_MMX: crack_states_bitsliced_function_p = &crack_states_bitsliced_MMX; break; +#endif +#endif default: crack_states_bitsliced_function_p = &crack_states_bitsliced_NOSIMD; break; @@ -616,9 +622,13 @@ const uint64_t crack_states_bitsliced_dispatch(uint32_t cuid, uint8_t *best_firs void bitslice_test_nonces_dispatch(uint32_t nonces_to_bruteforce, uint32_t *bf_test_nonce, uint8_t *bf_test_nonce_par) { switch(GetSIMDInstrAuto()) { +#if defined (__i386__) || defined (__x86_64__) +#if !defined(__APPLE__) || (defined(__APPLE__) && (__clang_major__ > 8 || __clang_major__ == 8 && __clang_minor__ >= 1)) +#if (__GNUC__ >= 5) && (__GNUC__ > 5 || __GNUC_MINOR__ > 2) case SIMD_AVX512: bitslice_test_nonces_function_p = &bitslice_test_nonces_AVX512; break; +#endif case SIMD_AVX2: bitslice_test_nonces_function_p = &bitslice_test_nonces_AVX2; break; @@ -631,6 +641,8 @@ void bitslice_test_nonces_dispatch(uint32_t nonces_to_bruteforce, uint32_t *bf_t case SIMD_MMX: bitslice_test_nonces_function_p = &bitslice_test_nonces_MMX; break; +#endif +#endif default: bitslice_test_nonces_function_p = &bitslice_test_nonces_NOSIMD; break; From 8ec06f5ef3c5c63a420b8292dd3ea5d0a5d6974e Mon Sep 17 00:00:00 2001 From: Oleg Moiseenko Date: Fri, 12 Jan 2018 23:37:55 +0200 Subject: [PATCH 024/127] hf mf sniff: small fixes --- armsrc/iso14443a.c | 4 ++-- client/cmdhfmf.c | 8 +++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index 94ca52f5..7d589f0e 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -2482,7 +2482,7 @@ void RAMFUNC SniffMifare(uint8_t param) { for(uint32_t sniffCounter = 0; true; ) { if(BUTTON_PRESS()) { - DbpString("cancelled by button"); + DbpString("Canceled by button."); break; } @@ -2576,7 +2576,7 @@ void RAMFUNC SniffMifare(uint8_t param) { } // main cycle - DbpString("COMMAND FINISHED"); + DbpString("COMMAND FINISHED."); FpgaDisableSscDma(); MfSniffEnd(); diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 4956df8c..b653cf30 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -2527,14 +2527,13 @@ int CmdHF14AMfSniff(const char *Cmd){ } UsbCommand resp; - if (WaitForResponseTimeout(CMD_ACK,&resp,2000)) { + if (WaitForResponseTimeoutW(CMD_ACK, &resp, 2000, false)) { res = resp.arg[0] & 0xff; uint16_t traceLen = resp.arg[1]; len = resp.arg[2]; if (res == 0) { // we are done - free(buf); - return 0; + break; } if (res == 1) { // there is (more) data to be transferred @@ -2610,6 +2609,9 @@ int CmdHF14AMfSniff(const char *Cmd){ } // while (true) free(buf); + + msleep(300); // wait for exiting arm side. + PrintAndLog("Done."); return 0; } From d1f9ec06aec73db05a48df42fc1eb51a399754ba Mon Sep 17 00:00:00 2001 From: pwpiwi Date: Mon, 15 Jan 2018 15:29:14 +0100 Subject: [PATCH 025/127] Revert changes in hardnested nonces collection. Sacrifice some speed in favor of stability for some card types (#547) --- armsrc/mifarecmd.c | 16 ++++++++++++---- armsrc/mifareutil.h | 2 -- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index fcfd7e8f..3854b589 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -20,6 +20,9 @@ #include "parity.h" #include "crc.h" +#define HARDNESTED_AUTHENTICATION_TIMEOUT 848 // card times out 1ms after wrong authentication (according to NXP documentation) +#define HARDNESTED_PRE_AUTHENTICATION_LEADTIME 400 // some (non standard) cards need a pause after select before they are ready for first authentication + // the block number for the ISO14443-4 PCB static uint8_t pcb_blocknum = 0; // Deselect card by sending a s-block. the crc is precalced for speed @@ -677,7 +680,7 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, } if (slow) { - timeout = GetCountSspClk() + PRE_AUTHENTICATION_LEADTIME; + timeout = GetCountSspClk() + HARDNESTED_PRE_AUTHENTICATION_LEADTIME; while(GetCountSspClk() < timeout); } @@ -694,10 +697,12 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, continue; } - // send a dummy response in order to trigger the cards authentication failure timeout - uint8_t dummy_answer[8] = {0}; - ReaderTransmit(dummy_answer, 8, NULL); + // send an incomplete dummy response in order to trigger the card's authentication failure timeout + uint8_t dummy_answer[1] = {0}; + ReaderTransmit(dummy_answer, 1, NULL); + timeout = GetCountSspClk() + HARDNESTED_AUTHENTICATION_TIMEOUT; + num_nonces++; if (num_nonces % 2) { memcpy(buf+i, receivedAnswer, 4); @@ -709,6 +714,9 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, i += 9; } + // wait for the card to become ready again + while(GetCountSspClk() < timeout); + } LED_C_OFF(); diff --git a/armsrc/mifareutil.h b/armsrc/mifareutil.h index c34dc8f4..b2912895 100644 --- a/armsrc/mifareutil.h +++ b/armsrc/mifareutil.h @@ -24,8 +24,6 @@ #define CRYPT_REQUEST 2 #define AUTH_FIRST 0 #define AUTH_NESTED 2 -#define AUTHENTICATION_TIMEOUT 848 // card times out 1ms after wrong authentication (according to NXP documentation) -#define PRE_AUTHENTICATION_LEADTIME 400 // some (non standard) cards need a pause after select before they are ready for first authentication // mifare 4bit card answers #define CARD_ACK 0x0A // 1010 - ACK From feb328c90ab6287c691b578d6a41fe5cf50a987d Mon Sep 17 00:00:00 2001 From: merlokk Date: Tue, 16 Jan 2018 14:34:04 +0200 Subject: [PATCH 026/127] `hf mf sniff` small fix --- armsrc/iso14443a.c | 9 +++++++-- armsrc/mifaresniff.c | 12 +++--------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index 7d589f0e..bd37fe9a 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -2539,7 +2539,9 @@ void RAMFUNC SniffMifare(uint8_t param) { if(!TagIsActive) { // no need to try decoding tag data if the reader is sending uint8_t readerdata = (previous_data & 0xF0) | (*data >> 4); if(MillerDecoding(readerdata, (sniffCounter-1)*4)) { - LED_C_INV(); + LED_B_ON(); + LED_C_OFF(); + if (MfSniffLogic(receivedCmd, Uart.len, Uart.parity, Uart.bitCount, true)) break; /* And ready to receive another command. */ @@ -2549,12 +2551,14 @@ void RAMFUNC SniffMifare(uint8_t param) { DemodReset(); } ReaderIsActive = (Uart.state != STATE_UNSYNCD); + TagIsActive = !ReaderIsActive; } if(!ReaderIsActive) { // no need to try decoding tag data if the reader is sending uint8_t tagdata = (previous_data << 4) | (*data & 0x0F); if(ManchesterDecoding(tagdata, 0, (sniffCounter-1)*4)) { - LED_C_INV(); + LED_B_OFF(); + LED_C_ON(); if (MfSniffLogic(receivedResponse, Demod.len, Demod.parity, Demod.bitCount, false)) break; @@ -2564,6 +2568,7 @@ void RAMFUNC SniffMifare(uint8_t param) { UartInit(receivedCmd, receivedCmdPar); } TagIsActive = (Demod.state != DEMOD_UNSYNCD); + ReaderIsActive = !TagIsActive; } } diff --git a/armsrc/mifaresniff.c b/armsrc/mifaresniff.c index 7f94b0fe..b9ab3df4 100644 --- a/armsrc/mifaresniff.c +++ b/armsrc/mifaresniff.c @@ -124,16 +124,10 @@ bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint8_t *parity, ui sniffBuf[12] = 0xFF; sniffBuf[13] = 0xFF; LogTrace(sniffBuf, 14, 0, 0, NULL, TRUE); - } // intentionally no break; - case SNF_CARD_CMD:{ - LogTrace(data, len, 0, 0, NULL, TRUE); - sniffState = SNF_CARD_RESP; - timerData = GetTickCount(); - break; - } - case SNF_CARD_RESP:{ - LogTrace(data, len, 0, 0, NULL, FALSE); sniffState = SNF_CARD_CMD; + } // intentionally no break; + case SNF_CARD_CMD:{ + LogTrace(data, len, 0, 0, NULL, reader); timerData = GetTickCount(); break; } From 3544b99715671fa9809ad2e2565a436cf79316f8 Mon Sep 17 00:00:00 2001 From: merlokk Date: Tue, 16 Jan 2018 17:54:54 +0200 Subject: [PATCH 027/127] fixed #541 --- armsrc/mifaresniff.c | 341 ++++++++++++++++++++++--------------------- 1 file changed, 174 insertions(+), 167 deletions(-) diff --git a/armsrc/mifaresniff.c b/armsrc/mifaresniff.c index b9ab3df4..08fb9f23 100644 --- a/armsrc/mifaresniff.c +++ b/armsrc/mifaresniff.c @@ -1,177 +1,184 @@ -//----------------------------------------------------------------------------- -// Merlok - 2012 -// -// This code is licensed to you under the terms of the GNU GPL, version 2 or, -// at your option, any later version. See the LICENSE.txt file for the text of -// the license. -//----------------------------------------------------------------------------- -// Routines to support mifare classic sniffer. -//----------------------------------------------------------------------------- - -#include "mifaresniff.h" -#include "apps.h" -#include "proxmark3.h" -#include "util.h" -#include "string.h" -#include "iso14443crc.h" -#include "iso14443a.h" -#include "crapto1/crapto1.h" -#include "mifareutil.h" -#include "common.h" - - -static int sniffState = SNF_INIT; -static uint8_t sniffUIDType; -static uint8_t sniffUID[8] = {0x00}; -static uint8_t sniffATQA[2] = {0x00}; -static uint8_t sniffSAK; -static uint8_t sniffBuf[16] = {0x00}; -static uint32_t timerData = 0; - - -bool MfSniffInit(void){ - memset(sniffUID, 0x00, 8); - memset(sniffATQA, 0x00, 2); - sniffSAK = 0; - sniffUIDType = SNF_UID_4; - - return FALSE; -} - -bool MfSniffEnd(void){ - LED_B_ON(); - cmd_send(CMD_ACK,0,0,0,0,0); - LED_B_OFF(); - - return FALSE; -} - -bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint8_t *parity, uint16_t bitCnt, bool reader) { - - if (reader && (len == 1) && (bitCnt == 7)) { // reset on 7-Bit commands from reader - sniffState = SNF_INIT; - } - - switch (sniffState) { - case SNF_INIT:{ - if ((len == 1) && (reader) && (bitCnt == 7) ) { // REQA or WUPA from reader - sniffUIDType = SNF_UID_4; - memset(sniffUID, 0x00, 8); - memset(sniffATQA, 0x00, 2); - sniffSAK = 0; - sniffState = SNF_WUPREQ; - } - break; - } - case SNF_WUPREQ:{ - if ((!reader) && (len == 2)) { // ATQA from tag - memcpy(sniffATQA, data, 2); - sniffState = SNF_ATQA; - } - break; - } - case SNF_ATQA:{ - if ((reader) && (len == 2) && (data[0] == 0x93) && (data[1] == 0x20)) { // Select ALL from reader - sniffState = SNF_ANTICOL1; - } - break; - } - case SNF_ANTICOL1:{ - if ((!reader) && (len == 5) && ((data[0] ^ data[1] ^ data[2] ^ data[3]) == data[4])) { // UID from tag (CL1) - memcpy(sniffUID + 3, data, 4); - sniffState = SNF_UID1; - } - break; - } +//----------------------------------------------------------------------------- +// Merlok - 2012 +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Routines to support mifare classic sniffer. +//----------------------------------------------------------------------------- + +#include "mifaresniff.h" +#include "apps.h" +#include "proxmark3.h" +#include "util.h" +#include "string.h" +#include "iso14443crc.h" +#include "iso14443a.h" +#include "crapto1/crapto1.h" +#include "mifareutil.h" +#include "common.h" + + +static int sniffState = SNF_INIT; +static uint8_t sniffUIDType; +static uint8_t sniffUID[8] = {0x00}; +static uint8_t sniffATQA[2] = {0x00}; +static uint8_t sniffSAK; +static uint8_t sniffBuf[16] = {0x00}; +static uint32_t timerData = 0; + + +bool MfSniffInit(void){ + memset(sniffUID, 0x00, 8); + memset(sniffATQA, 0x00, 2); + sniffSAK = 0; + sniffUIDType = SNF_UID_4; + + return FALSE; +} + +bool MfSniffEnd(void){ + LED_B_ON(); + cmd_send(CMD_ACK,0,0,0,0,0); + LED_B_OFF(); + + return FALSE; +} + +bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint8_t *parity, uint16_t bitCnt, bool reader) { + + if (reader && (len == 1) && (bitCnt == 7)) { // reset on 7-Bit commands from reader + sniffState = SNF_INIT; + } + + switch (sniffState) { + case SNF_INIT:{ + if ((len == 1) && (reader) && (bitCnt == 7) ) { // REQA or WUPA from reader + sniffUIDType = SNF_UID_4; + memset(sniffUID, 0x00, 8); + memset(sniffATQA, 0x00, 2); + sniffSAK = 0; + sniffState = SNF_WUPREQ; + } + break; + } + case SNF_WUPREQ:{ + if ((!reader) && (len == 2)) { // ATQA from tag + memcpy(sniffATQA, data, 2); + sniffState = SNF_ATQA; + } + break; + } + case SNF_ATQA: case SNF_UID1:{ + // SNF_ATQA + if ((reader) && (len == 2) && (data[0] == 0x93) && (data[1] == 0x20)) { // Select ALL from reader + sniffState = SNF_ANTICOL1; + } + + // SNF_UID1 if ((reader) && (len == 9) && (data[0] == 0x93) && (data[1] == 0x70) && (CheckCrc14443(CRC_14443_A, data, 9))) { // Select 4 Byte UID from reader + memcpy(sniffUID + 3, &data[2], 4); sniffState = SNF_SAK; } - break; - } - case SNF_SAK:{ - if ((!reader) && (len == 3) && (CheckCrc14443(CRC_14443_A, data, 3))) { // SAK from card? - sniffSAK = data[0]; - if (sniffUID[3] == 0x88) { // CL2 UID part to be expected - sniffState = SNF_ANTICOL2; - } else { // select completed - sniffState = SNF_CARD_IDLE; - } - } - break; - } - case SNF_ANTICOL2:{ - if ((!reader) && (len == 5) && ((data[0] ^ data[1] ^ data[2] ^ data[3]) == data[4])) { // CL2 UID - memcpy(sniffUID, sniffUID+4, 3); - memcpy(sniffUID+3, data, 4); - sniffUIDType = SNF_UID_7; - sniffState = SNF_UID2; - } - break; + break; } + case SNF_ANTICOL1:{ + if ((!reader) && (len == 5) && ((data[0] ^ data[1] ^ data[2] ^ data[3]) == data[4])) { // UID from tag (CL1) + memcpy(sniffUID + 3, data, 4); + sniffState = SNF_UID1; + } + break; + } + case SNF_SAK:{ + if ((!reader) && (len == 3) && (CheckCrc14443(CRC_14443_A, data, 3))) { // SAK from card? + sniffSAK = data[0]; + if ((sniffUID[3] == 0x88) && (sniffUIDType == SNF_UID_4)) { // CL2 UID part to be expected + sniffUIDType = SNF_UID_7; + memcpy(sniffUID, sniffUID + 4, 3); + sniffState = SNF_UID2; + } else { // select completed + sniffState = SNF_CARD_IDLE; + } + } + break; + } + case SNF_ANTICOL2:{ + if ((!reader) && (len == 5) && ((data[0] ^ data[1] ^ data[2] ^ data[3]) == data[4])) { // CL2 UID + memcpy(sniffUID + 3, data, 4); + sniffState = SNF_UID2; + } + break; + } case SNF_UID2:{ - if ((reader) && (len == 9) && (data[0] == 0x95) && (data[1] == 0x70) && (CheckCrc14443(CRC_14443_A, data, 9))) { // Select 2nd part of 7 Byte UID + if ((reader) && (len == 2) && (data[0] == 0x95) && (data[1] == 0x20)) { + sniffState = SNF_ANTICOL2; + } + + if ((reader) && (len == 9) && (data[0] == 0x95) && (data[1] == 0x70) && (CheckCrc14443(CRC_14443_A, data, 9))) { + memcpy(sniffUID + 3, &data[2], 4); sniffState = SNF_SAK; } break; } - case SNF_CARD_IDLE:{ // trace the card select sequence - sniffBuf[0] = 0xFF; - sniffBuf[1] = 0xFF; - memcpy(sniffBuf + 2, sniffUID, 7); - memcpy(sniffBuf + 9, sniffATQA, 2); - sniffBuf[11] = sniffSAK; - sniffBuf[12] = 0xFF; - sniffBuf[13] = 0xFF; - LogTrace(sniffBuf, 14, 0, 0, NULL, TRUE); - sniffState = SNF_CARD_CMD; - } // intentionally no break; - case SNF_CARD_CMD:{ - LogTrace(data, len, 0, 0, NULL, reader); - timerData = GetTickCount(); - break; - } - - default: - sniffState = SNF_INIT; - break; - } - - - return FALSE; -} - -bool RAMFUNC MfSniffSend(uint16_t maxTimeoutMs) { - if (BigBuf_get_traceLen() && (GetTickCount() > timerData + maxTimeoutMs)) { - return intMfSniffSend(); - } - return FALSE; -} - -// internal sending function. not a RAMFUNC. -bool intMfSniffSend() { - - int pckSize = 0; - int pckLen = BigBuf_get_traceLen(); - int pckNum = 0; - uint8_t *trace = BigBuf_get_addr(); - - FpgaDisableSscDma(); - while (pckLen > 0) { - pckSize = MIN(USB_CMD_DATA_SIZE, pckLen); - LED_B_ON(); - cmd_send(CMD_ACK, 1, BigBuf_get_traceLen(), pckSize, trace + BigBuf_get_traceLen() - pckLen, pckSize); - LED_B_OFF(); - - pckLen -= pckSize; - pckNum++; - } - - LED_B_ON(); - cmd_send(CMD_ACK,2,0,0,0,0); - LED_B_OFF(); - - clear_trace(); - - return TRUE; -} + case SNF_CARD_IDLE:{ // trace the card select sequence + sniffBuf[0] = 0xFF; + sniffBuf[1] = 0xFF; + memcpy(sniffBuf + 2, sniffUID, 7); + memcpy(sniffBuf + 9, sniffATQA, 2); + sniffBuf[11] = sniffSAK; + sniffBuf[12] = 0xFF; + sniffBuf[13] = 0xFF; + LogTrace(sniffBuf, 14, 0, 0, NULL, TRUE); + sniffState = SNF_CARD_CMD; + } // intentionally no break; + case SNF_CARD_CMD:{ + LogTrace(data, len, 0, 0, NULL, reader); + timerData = GetTickCount(); + break; + } + + default: + sniffState = SNF_INIT; + break; + } + + + return FALSE; +} + +bool RAMFUNC MfSniffSend(uint16_t maxTimeoutMs) { + if (BigBuf_get_traceLen() && (GetTickCount() > timerData + maxTimeoutMs)) { + return intMfSniffSend(); + } + return FALSE; +} + +// internal sending function. not a RAMFUNC. +bool intMfSniffSend() { + + int pckSize = 0; + int pckLen = BigBuf_get_traceLen(); + int pckNum = 0; + uint8_t *trace = BigBuf_get_addr(); + + FpgaDisableSscDma(); + while (pckLen > 0) { + pckSize = MIN(USB_CMD_DATA_SIZE, pckLen); + LED_B_ON(); + cmd_send(CMD_ACK, 1, BigBuf_get_traceLen(), pckSize, trace + BigBuf_get_traceLen() - pckLen, pckSize); + LED_B_OFF(); + + pckLen -= pckSize; + pckNum++; + } + + LED_B_ON(); + cmd_send(CMD_ACK,2,0,0,0,0); + LED_B_OFF(); + + clear_trace(); + + return TRUE; +} From 35cc71b0752a8595c96f127eced98112fe2a5a0b Mon Sep 17 00:00:00 2001 From: merlokk Date: Wed, 17 Jan 2018 14:10:26 +0200 Subject: [PATCH 028/127] delete opposite states fix --- armsrc/iso14443a.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index bd37fe9a..6703cc65 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -2551,7 +2551,6 @@ void RAMFUNC SniffMifare(uint8_t param) { DemodReset(); } ReaderIsActive = (Uart.state != STATE_UNSYNCD); - TagIsActive = !ReaderIsActive; } if(!ReaderIsActive) { // no need to try decoding tag data if the reader is sending @@ -2568,7 +2567,6 @@ void RAMFUNC SniffMifare(uint8_t param) { UartInit(receivedCmd, receivedCmdPar); } TagIsActive = (Demod.state != DEMOD_UNSYNCD); - ReaderIsActive = !TagIsActive; } } From 968cb35498c6d6331a4c65b1f23dad2bbeb79f6f Mon Sep 17 00:00:00 2001 From: merlokk Date: Wed, 17 Jan 2018 14:14:36 +0200 Subject: [PATCH 029/127] deleted save UID from card --- armsrc/mifaresniff.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/armsrc/mifaresniff.c b/armsrc/mifaresniff.c index 08fb9f23..f4879329 100644 --- a/armsrc/mifaresniff.c +++ b/armsrc/mifaresniff.c @@ -86,7 +86,6 @@ bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint8_t *parity, ui } case SNF_ANTICOL1:{ if ((!reader) && (len == 5) && ((data[0] ^ data[1] ^ data[2] ^ data[3]) == data[4])) { // UID from tag (CL1) - memcpy(sniffUID + 3, data, 4); sniffState = SNF_UID1; } break; @@ -106,7 +105,6 @@ bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint8_t *parity, ui } case SNF_ANTICOL2:{ if ((!reader) && (len == 5) && ((data[0] ^ data[1] ^ data[2] ^ data[3]) == data[4])) { // CL2 UID - memcpy(sniffUID + 3, data, 4); sniffState = SNF_UID2; } break; From 543a6ed3c99fb1f1324b25d7d2132133dce904dc Mon Sep 17 00:00:00 2001 From: merlokk Date: Wed, 17 Jan 2018 15:48:01 +0200 Subject: [PATCH 030/127] SNF_WUPREQ and SNF_SAK harmonized) --- armsrc/mifaresniff.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/armsrc/mifaresniff.c b/armsrc/mifaresniff.c index f4879329..3929561e 100644 --- a/armsrc/mifaresniff.c +++ b/armsrc/mifaresniff.c @@ -59,25 +59,22 @@ bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint8_t *parity, ui memset(sniffUID, 0x00, 8); memset(sniffATQA, 0x00, 2); sniffSAK = 0; - sniffState = SNF_WUPREQ; - } - break; - } - case SNF_WUPREQ:{ - if ((!reader) && (len == 2)) { // ATQA from tag - memcpy(sniffATQA, data, 2); sniffState = SNF_ATQA; } break; } - case SNF_ATQA: + case SNF_ATQA:{ + if ((!reader) && (len == 2)) { // ATQA from tag + memcpy(sniffATQA, data, 2); + sniffState = SNF_UID1; + } + break; + } case SNF_UID1:{ - // SNF_ATQA if ((reader) && (len == 2) && (data[0] == 0x93) && (data[1] == 0x20)) { // Select ALL from reader sniffState = SNF_ANTICOL1; } - // SNF_UID1 if ((reader) && (len == 9) && (data[0] == 0x93) && (data[1] == 0x70) && (CheckCrc14443(CRC_14443_A, data, 9))) { // Select 4 Byte UID from reader memcpy(sniffUID + 3, &data[2], 4); sniffState = SNF_SAK; From 3e77c7a7b4859c18345dac5652c70c280eb1ca10 Mon Sep 17 00:00:00 2001 From: merlokk Date: Wed, 17 Jan 2018 15:57:24 +0200 Subject: [PATCH 031/127] ignore SELECT ALL --- armsrc/mifaresniff.c | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/armsrc/mifaresniff.c b/armsrc/mifaresniff.c index 3929561e..20b54e82 100644 --- a/armsrc/mifaresniff.c +++ b/armsrc/mifaresniff.c @@ -71,22 +71,12 @@ bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint8_t *parity, ui break; } case SNF_UID1:{ - if ((reader) && (len == 2) && (data[0] == 0x93) && (data[1] == 0x20)) { // Select ALL from reader - sniffState = SNF_ANTICOL1; - } - if ((reader) && (len == 9) && (data[0] == 0x93) && (data[1] == 0x70) && (CheckCrc14443(CRC_14443_A, data, 9))) { // Select 4 Byte UID from reader memcpy(sniffUID + 3, &data[2], 4); sniffState = SNF_SAK; } break; } - case SNF_ANTICOL1:{ - if ((!reader) && (len == 5) && ((data[0] ^ data[1] ^ data[2] ^ data[3]) == data[4])) { // UID from tag (CL1) - sniffState = SNF_UID1; - } - break; - } case SNF_SAK:{ if ((!reader) && (len == 3) && (CheckCrc14443(CRC_14443_A, data, 3))) { // SAK from card? sniffSAK = data[0]; @@ -100,17 +90,7 @@ bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint8_t *parity, ui } break; } - case SNF_ANTICOL2:{ - if ((!reader) && (len == 5) && ((data[0] ^ data[1] ^ data[2] ^ data[3]) == data[4])) { // CL2 UID - sniffState = SNF_UID2; - } - break; - } case SNF_UID2:{ - if ((reader) && (len == 2) && (data[0] == 0x95) && (data[1] == 0x20)) { - sniffState = SNF_ANTICOL2; - } - if ((reader) && (len == 9) && (data[0] == 0x95) && (data[1] == 0x70) && (CheckCrc14443(CRC_14443_A, data, 9))) { memcpy(sniffUID + 3, &data[2], 4); sniffState = SNF_SAK; From f7887fa82efb7a30b9a572bb2f379b90e62fde6a Mon Sep 17 00:00:00 2001 From: merlokk Date: Wed, 17 Jan 2018 16:01:56 +0200 Subject: [PATCH 032/127] added magic cards --- armsrc/mifaresniff.c | 7 +++++++ armsrc/mifaresniff.h | 1 + 2 files changed, 8 insertions(+) diff --git a/armsrc/mifaresniff.c b/armsrc/mifaresniff.c index 20b54e82..4e573be7 100644 --- a/armsrc/mifaresniff.c +++ b/armsrc/mifaresniff.c @@ -60,9 +60,16 @@ bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint8_t *parity, ui memset(sniffATQA, 0x00, 2); sniffSAK = 0; sniffState = SNF_ATQA; + if (data[0] == 0x40) + sniffState = SNF_MAGIC_WUPC2; } break; } + case SNF_MAGIC_WUPC2: + if ((len == 1) && (reader) && (data[0] == 0x43) ) { + sniffState = SNF_CARD_IDLE; + } + break; case SNF_ATQA:{ if ((!reader) && (len == 2)) { // ATQA from tag memcpy(sniffATQA, data, 2); diff --git a/armsrc/mifaresniff.h b/armsrc/mifaresniff.h index 8a8e31a9..b181f982 100644 --- a/armsrc/mifaresniff.h +++ b/armsrc/mifaresniff.h @@ -27,6 +27,7 @@ #define SNF_CARD_IDLE 9 #define SNF_CARD_CMD 10 #define SNF_CARD_RESP 11 +#define SNF_MAGIC_WUPC2 12 #define SNF_UID_4 0 #define SNF_UID_7 0 From a0349483636de9ceb91fdecde41fbbf56d6fc79b Mon Sep 17 00:00:00 2001 From: merlokk Date: Wed, 17 Jan 2018 16:12:50 +0200 Subject: [PATCH 033/127] fix eml file format --- client/mifarehost.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/mifarehost.c b/client/mifarehost.c index 67277b59..398e4f15 100644 --- a/client/mifarehost.c +++ b/client/mifarehost.c @@ -609,7 +609,8 @@ int saveTraceCard(void) { for (int i = 0; i < 64; i++) { // blocks for (int j = 0; j < 16; j++) // bytes fprintf(f, "%02x", *(traceCard + i * 16 + j)); - fprintf(f,"\n"); + if (i < 63) + fprintf(f,"\n"); } fclose(f); return 0; From 2ba37081ec005c623baf69accca493662cbaa4c3 Mon Sep 17 00:00:00 2001 From: merlokk Date: Wed, 17 Jan 2018 18:16:37 +0200 Subject: [PATCH 034/127] added nested authentication "not implemented" warning --- client/mifarehost.c | 43 ++++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/client/mifarehost.c b/client/mifarehost.c index 398e4f15..d204bf12 100644 --- a/client/mifarehost.c +++ b/client/mifarehost.c @@ -827,20 +827,30 @@ int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) { if (len ==4) { traceState = TRACE_IDLE; - at_enc = bytes_to_num(data, 4); + if (!traceCrypto1) { + at_enc = bytes_to_num(data, 4); - // decode key here) - ks2 = ar_enc ^ prng_successor(nt, 64); - ks3 = at_enc ^ prng_successor(nt, 96); - revstate = lfsr_recovery64(ks2, ks3); - lfsr_rollback_word(revstate, 0, 0); - lfsr_rollback_word(revstate, 0, 0); - lfsr_rollback_word(revstate, nr_enc, 1); - lfsr_rollback_word(revstate, uid ^ nt, 0); + // decode key here) + ks2 = ar_enc ^ prng_successor(nt, 64); + ks3 = at_enc ^ prng_successor(nt, 96); + revstate = lfsr_recovery64(ks2, ks3); + lfsr_rollback_word(revstate, 0, 0); + lfsr_rollback_word(revstate, 0, 0); + lfsr_rollback_word(revstate, nr_enc, 1); + lfsr_rollback_word(revstate, uid ^ nt, 0); - crypto1_get_lfsr(revstate, &lfsr); - printf("key> %x%x\n", (unsigned int)((lfsr & 0xFFFFFFFF00000000) >> 32), (unsigned int)(lfsr & 0xFFFFFFFF)); - AddLogUint64(logHexFileName, "key> ", lfsr); + crypto1_get_lfsr(revstate, &lfsr); + printf("key> %x%x\n", (unsigned int)((lfsr & 0xFFFFFFFF00000000) >> 32), (unsigned int)(lfsr & 0xFFFFFFFF)); + AddLogUint64(logHexFileName, "key> ", lfsr); + } else { + printf("key> nested not implemented!\n"); + at_enc = bytes_to_num(data, 4); + + crypto1_destroy(traceCrypto1); + + // not implemented + traceState = TRACE_ERROR; + } int blockShift = ((traceCurBlock & 0xFC) + 3) * 16; if (isBlockEmpty((traceCurBlock & 0xFC) + 3)) memcpy(traceCard + blockShift + 6, trailerAccessBytes, 4); @@ -858,15 +868,6 @@ int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) { // set cryptosystem state traceCrypto1 = lfsr_recovery64(ks2, ks3); - -// nt = crypto1_word(traceCrypto1, nt ^ uid, 1) ^ nt; - - /* traceCrypto1 = crypto1_create(lfsr); // key in lfsr - crypto1_word(traceCrypto1, nt ^ uid, 0); - crypto1_word(traceCrypto1, ar, 1); - crypto1_word(traceCrypto1, 0, 0); - crypto1_word(traceCrypto1, 0, 0);*/ - return 0; } else { traceState = TRACE_ERROR; From fc175230f431e7e33c7628c6b31064d4f7d1e1ad Mon Sep 17 00:00:00 2001 From: rkblackfire Date: Mon, 22 Jan 2018 18:54:29 +0100 Subject: [PATCH 035/127] dbg: Watchdog resets while 'hw tune lf' loop does not finish, u_int is always '>=0' --- armsrc/appmain.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 64768922..3aeb4c8a 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -205,7 +205,7 @@ void MeasureAntennaTuningLfOnly(int *vLf125, int *vLf134, int *peakf, int *peakv } } - for (i=18; i >= 0; i--) LF_Results[i] = 0; + for (i=0; i <= 18; i++) LF_Results[i] = 0; return; } From 095173f72d354f7fee70cdc84115302e633f3cb0 Mon Sep 17 00:00:00 2001 From: rkblackfire Date: Mon, 22 Jan 2018 18:59:48 +0100 Subject: [PATCH 036/127] chg: print only valid tuning data only print the ranges which were tuned, thus not showing an error for 'lf antenna' when called 'hw tune hf' and vice versa --- client/cmddata.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/client/cmddata.c b/client/cmddata.c index 9b960de9..9bfe58f9 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -1281,24 +1281,34 @@ int CmdTuneSamples(const char *Cmd) peakf = resp.arg[2] & 0xffff; peakv = resp.arg[2] >> 16; PrintAndLog(""); - PrintAndLog("# LF antenna: %5.2f V @ 125.00 kHz", vLf125/500.0); - PrintAndLog("# LF antenna: %5.2f V @ 134.00 kHz", vLf134/500.0); - PrintAndLog("# LF optimal: %5.2f V @%9.2f kHz", peakv/500.0, 12000.0/(peakf+1)); - PrintAndLog("# HF antenna: %5.2f V @ 13.56 MHz", vHf/1000.0); + if (arg & FLAG_TUNE_LF) + { + PrintAndLog("# LF antenna: %5.2f V @ 125.00 kHz", vLf125/500.0); + PrintAndLog("# LF antenna: %5.2f V @ 134.00 kHz", vLf134/500.0); + PrintAndLog("# LF optimal: %5.2f V @%9.2f kHz", peakv/500.0, 12000.0/(peakf+1)); + } + if (arg & FLAG_TUNE_HF) + PrintAndLog("# HF antenna: %5.2f V @ 13.56 MHz", vHf/1000.0); #define LF_UNUSABLE_V 3000 #define LF_MARGINAL_V 15000 #define HF_UNUSABLE_V 3200 #define HF_MARGINAL_V 8000 - if (peakv<<1 < LF_UNUSABLE_V) - PrintAndLog("# Your LF antenna is unusable."); - else if (peakv<<1 < LF_MARGINAL_V) - PrintAndLog("# Your LF antenna is marginal."); - if (vHf < HF_UNUSABLE_V) - PrintAndLog("# Your HF antenna is unusable."); - else if (vHf < HF_MARGINAL_V) - PrintAndLog("# Your HF antenna is marginal."); + if (arg & FLAG_TUNE_LF) + { + if (peakv<<1 < LF_UNUSABLE_V) + PrintAndLog("# Your LF antenna is unusable."); + else if (peakv<<1 < LF_MARGINAL_V) + PrintAndLog("# Your LF antenna is marginal."); + } + if (arg & FLAG_TUNE_HF) + { + if (vHf < HF_UNUSABLE_V) + PrintAndLog("# Your HF antenna is unusable."); + else if (vHf < HF_MARGINAL_V) + PrintAndLog("# Your HF antenna is marginal."); + } if (peakv<<1 >= LF_UNUSABLE_V) { for (int i = 0; i < 256; i++) { From f3ffd5a24f6e4488505ff1c98bc6512dff5a69ed Mon Sep 17 00:00:00 2001 From: rkblackfire Date: Mon, 22 Jan 2018 19:25:22 +0100 Subject: [PATCH 037/127] Revert "dbg: Watchdog resets while 'hw tune lf'" This reverts commit fc175230f431e7e33c7628c6b31064d4f7d1e1ad. --- armsrc/appmain.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 3aeb4c8a..64768922 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -205,7 +205,7 @@ void MeasureAntennaTuningLfOnly(int *vLf125, int *vLf134, int *peakf, int *peakv } } - for (i=0; i <= 18; i++) LF_Results[i] = 0; + for (i=18; i >= 0; i--) LF_Results[i] = 0; return; } From ec0872181b882afe69213c2443f074426ccaa94f Mon Sep 17 00:00:00 2001 From: pwpiwi Date: Tue, 23 Jan 2018 08:27:58 +0100 Subject: [PATCH 038/127] fix clang compiler warnings identified in http://www.proxmark.org/forum/viewtopic.php?id=5388 --- client/cmdhfmfhard.c | 40 ----------------------- client/emv/apduinfo.c | 2 +- client/fpga_compress.c | 4 +-- client/hardnested/hardnested_bruteforce.c | 9 +++-- client/util_posix.c | 4 +++ 5 files changed, 14 insertions(+), 45 deletions(-) diff --git a/client/cmdhfmfhard.c b/client/cmdhfmfhard.c index 96c3a989..69ad898d 100644 --- a/client/cmdhfmfhard.c +++ b/client/cmdhfmfhard.c @@ -150,12 +150,6 @@ static inline void set_bit24(uint32_t *bitarray, uint32_t index) } -static inline void clear_bit24(uint32_t *bitarray, uint32_t index) -{ - bitarray[index>>5] &= ~(0x80000000>>(index&0x0000001f)); -} - - static inline uint32_t test_bit24(uint32_t *bitarray, uint32_t index) { return bitarray[index>>5] & (0x80000000>>(index&0x0000001f)); @@ -196,40 +190,6 @@ static inline uint32_t next_state(uint32_t *bitarray, uint32_t state) } -static inline uint32_t next_not_state(uint32_t *bitarray, uint32_t state) -{ - if (++state == 1<<24) return 1<<24; - uint32_t index = state >> 5; - uint_fast8_t bit = state & 0x1f; - uint32_t line = bitarray[index] << bit; - while (bit <= 0x1f) { - if ((line & 0x80000000) == 0) return state; - state++; - bit++; - line <<= 1; - } - index++; - while (bitarray[index] == 0xffffffff && state < 1<<24) { - index++; - state += 0x20; - } - if (state >= 1<<24) return 1<<24; -#if defined __GNUC__ - return state + __builtin_clz(~bitarray[index]); -#else - bit = 0x00; - line = bitarray[index]; - while (bit <= 0x1f) { - if ((line & 0x80000000) == 0) return state; - state++; - bit++; - line <<= 1; - } - return 1<<24; -#endif -} - - #define BITFLIP_2ND_BYTE 0x0200 diff --git a/client/emv/apduinfo.c b/client/emv/apduinfo.c index ec7a64a1..a631c614 100644 --- a/client/emv/apduinfo.c +++ b/client/emv/apduinfo.c @@ -132,7 +132,7 @@ const APDUCode APDUCodeTable[] = { {"6EXX", APDUCODE_TYPE_ERROR, "Instruction class not supported (procedure byte), (ISO 7816-3)"}, {"6F--", APDUCODE_TYPE_ERROR, "Internal exception"}, {"6F00", APDUCODE_TYPE_ERROR, "Command aborted - more exact diagnosis not possible (e.g., operating system error)."}, - {"6FFF", APDUCODE_TYPE_ERROR, "Card dead (overuse, …)"}, + {"6FFF", APDUCODE_TYPE_ERROR, "Card dead (overuse, ...)"}, {"6FXX", APDUCODE_TYPE_ERROR, "No precise diagnosis (procedure byte), (ISO 7816-3)"}, {"9---", APDUCODE_TYPE_NONE, ""}, {"9000", APDUCODE_TYPE_INFO, "Command successfully executed (OK)."}, diff --git a/client/fpga_compress.c b/client/fpga_compress.c index a672ab58..fc298a8b 100644 --- a/client/fpga_compress.c +++ b/client/fpga_compress.c @@ -297,9 +297,9 @@ int main(int argc, char **argv) } infiles = calloc(num_input_files, sizeof(FILE*)); for (uint16_t i = 0; i < num_input_files; i++) { - infiles[i] = fopen(argv[i+hardnested_mode?2:1], "rb"); + infiles[i] = fopen(argv[i+(hardnested_mode?2:1)], "rb"); if (infiles[i] == NULL) { - fprintf(stderr, "Error. Cannot open input file %s", argv[i+hardnested_mode?2:1]); + fprintf(stderr, "Error. Cannot open input file %s", argv[i+(hardnested_mode?2:1)]); return(EXIT_FAILURE); } } diff --git a/client/hardnested/hardnested_bruteforce.c b/client/hardnested/hardnested_bruteforce.c index 3072fc52..deea69d8 100644 --- a/client/hardnested/hardnested_bruteforce.c +++ b/client/hardnested/hardnested_bruteforce.c @@ -139,8 +139,13 @@ bool verify_key(uint32_t cuid, noncelist_t *nonces, uint8_t *best_first_bytes, u return true; } - -static void* __attribute__((force_align_arg_pointer)) crack_states_thread(void* x){ +static void* +#ifdef __has_attribute +#if __has_attribute(force_align_arg_pointer) +__attribute__((force_align_arg_pointer)) +#endif +#endif +crack_states_thread(void* x){ struct arg { bool silent; diff --git a/client/util_posix.c b/client/util_posix.c index 8f3ed46b..32158ada 100644 --- a/client/util_posix.c +++ b/client/util_posix.c @@ -37,8 +37,12 @@ void msleep(uint32_t n) { #ifdef __APPLE__ +#ifndef CLOCK_MONOTONIC #define CLOCK_MONOTONIC (1) +#endif +#ifndef CLOCK_REALTIME #define CLOCK_REALTIME (2) +#endif #include #include From 757221f5d6db8f1d9447d59c71a9807c6a9f522f Mon Sep 17 00:00:00 2001 From: pwpiwi Date: Mon, 8 Jan 2018 07:48:13 +0100 Subject: [PATCH 039/127] Remove reveng (its license was not compatible with PM3 license, see issue #527) --- client/Makefile | 9 +- client/cmdcrc.c | 547 ----------------- client/cmdcrc.h | 20 - client/cmdmain.c | 9 - client/obj/reveng/.dummy | 0 client/reveng/bmpbit.c | 86 --- client/reveng/cli.c | 628 -------------------- client/reveng/config.h | 96 --- client/reveng/getopt.c | 81 --- client/reveng/getopt.h | 25 - client/reveng/model.c | 823 -------------------------- client/reveng/poly.c | 1196 -------------------------------------- client/reveng/reveng.c | 489 ---------------- client/reveng/reveng.h | 214 ------- client/scripting.c | 60 +- client/scripts/e.lua | 72 --- 16 files changed, 2 insertions(+), 4353 deletions(-) delete mode 100644 client/cmdcrc.c delete mode 100644 client/cmdcrc.h delete mode 100644 client/obj/reveng/.dummy delete mode 100644 client/reveng/bmpbit.c delete mode 100644 client/reveng/cli.c delete mode 100644 client/reveng/config.h delete mode 100644 client/reveng/getopt.c delete mode 100644 client/reveng/getopt.h delete mode 100644 client/reveng/model.c delete mode 100644 client/reveng/poly.c delete mode 100644 client/reveng/reveng.c delete mode 100644 client/reveng/reveng.h delete mode 100644 client/scripts/e.lua diff --git a/client/Makefile b/client/Makefile index 52a106bd..bf642803 100644 --- a/client/Makefile +++ b/client/Makefile @@ -169,14 +169,7 @@ CMDSRCS = crapto1/crapto1.c\ cmdscript.c\ pm3_binlib.c\ pm3_bitlib.c\ - protocols.c\ - cmdcrc.c\ - reveng/reveng.c\ - reveng/cli.c\ - reveng/bmpbit.c\ - reveng/model.c\ - reveng/poly.c\ - reveng/getopt.c\ + protocols.c cpu_arch = $(shell uname -m) ifneq ($(findstring 86, $(cpu_arch)), ) diff --git a/client/cmdcrc.c b/client/cmdcrc.c deleted file mode 100644 index 0ca2b8b1..00000000 --- a/client/cmdcrc.c +++ /dev/null @@ -1,547 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (C) 2015 iceman -// -// This code is licensed to you under the terms of the GNU GPL, version 2 or, -// at your option, any later version. See the LICENSE.txt file for the text of -// the license. -//----------------------------------------------------------------------------- -// CRC Calculations from the software reveng commands -//----------------------------------------------------------------------------- - -#ifdef _WIN32 -# include -# include -# ifndef STDIN_FILENO -# define STDIN_FILENO 0 -# endif /* STDIN_FILENO */ -#endif /* _WIN32 */ - -#include -#include -#include -#include -#include "cmdmain.h" -#include "cmdcrc.h" -#include "reveng/reveng.h" -#include "ui.h" -#include "util.h" - -#define MAX_ARGS 20 - -int uerr(char *msg){ - PrintAndLog("%s",msg); - return 0; -} - -int split(char *str, char *arr[MAX_ARGS]){ - int beginIndex = 0; - int endIndex; - int maxWords = MAX_ARGS; - int wordCnt = 0; - - while(1){ - while(isspace((unsigned char)str[beginIndex])){ - ++beginIndex; - } - if(str[beginIndex] == '\0') { - break; - } - endIndex = beginIndex; - while (str[endIndex] && !isspace((unsigned char)str[endIndex])){ - ++endIndex; - } - int len = endIndex - beginIndex; - char *tmp = calloc(len + 1, sizeof(char)); - memcpy(tmp, &str[beginIndex], len); - arr[wordCnt++] = tmp; - //PrintAndLog("DEBUG cnt: %d, %s",wordCnt-1, arr[wordCnt-1]); - beginIndex = endIndex; - if (wordCnt == maxWords) - break; - } - return wordCnt; -} - -int CmdCrc(const char *Cmd) -{ - char name[] = {"reveng "}; - char Cmd2[50 + 7]; - memcpy(Cmd2, name, 7); - memcpy(Cmd2 + 7, Cmd, 50); - char *argv[MAX_ARGS]; - int argc = split(Cmd2, argv); - - if (argc == 3 && memcmp(argv[1],"-g",2)==0) { - CmdrevengSearch(argv[2]); - } else { - reveng_main(argc, argv); - } - //PrintAndLog("DEBUG argc: %d, %s %s Cmd: %s",argc, argv[0], Cmd2, Cmd); - for(int i = 0; i < argc; ++i){ - free(argv[i]); - } - - return 0; -} - -//returns array of model names and the count of models returning -// as well as a width array for the width of each model -int GetModels(char *Models[], int *count, uint8_t *width){ - /* default values */ - static model_t model = { - PZERO, /* no CRC polynomial, user must specify */ - PZERO, /* Init = 0 */ - P_BE, /* RefIn = false, RefOut = false, plus P_RTJUST setting in reveng.h */ - PZERO, /* XorOut = 0 */ - PZERO, /* check value unused */ - NULL /* no model name */ - }; - - int ibperhx = 8;//, obperhx = 8; - int rflags = 0, uflags = 0; /* search and UI flags */ - poly_t apoly, crc, qpoly = PZERO, *apolys = NULL, *pptr = NULL, *qptr = NULL; - model_t pset = model, *candmods, *mptr; - - /* stdin must be binary */ - #ifdef _WIN32 - _setmode(STDIN_FILENO, _O_BINARY); - #endif /* _WIN32 */ - - SETBMP(); - - int args = 0, psets, pass; - int Cnt = 0; - if (width[0] == 0) { //reveng -D - *count = mcount(); - if(!*count) - return uerr("no preset models available"); - - for(int mode = 0; mode < *count; ++mode) { - mbynum(&model, mode); - mcanon(&model); - size_t size = (model.name && *model.name) ? strlen(model.name) : 6; - char *tmp = calloc(size+1, sizeof(char)); - if (tmp==NULL) - return uerr("out of memory?"); - - memcpy(tmp, model.name, size); - Models[mode] = tmp; - width[mode] = plen(model.spoly); - } - mfree(&model); - } else { //reveng -s - - if(~model.flags & P_MULXN) - return uerr("cannot search for non-Williams compliant models"); - - praloc(&model.spoly, (unsigned long)width[0]); - praloc(&model.init, (unsigned long)width[0]); - praloc(&model.xorout, (unsigned long)width[0]); - if(!plen(model.spoly)) - palloc(&model.spoly, (unsigned long)width[0]); - else - width[0] = (uint8_t)plen(model.spoly); - - /* special case if qpoly is zero, search to end of range */ - if(!ptst(qpoly)) - rflags &= ~R_HAVEQ; - - - /* not going to be sending additional args at this time (maybe future?) - - // allocate argument array - args = argc - optind; - if(!(apolys = malloc(args * sizeof(poly_t)))) - return uerr("cannot allocate memory for argument list"); - - for(pptr = apolys; optind < argc; ++optind) { - if(uflags & C_INFILE) - *pptr++ = rdpoly(argv[optind], model.flags, ibperhx); - else - *pptr++ = strtop(argv[optind], model.flags, ibperhx); - } - // exit value of pptr is used hereafter! - - */ - - /* if endianness not specified, try - * little-endian then big-endian. - * NB: crossed-endian algorithms will not be - * searched. - */ - /* scan against preset models */ - if(~uflags & C_FORCE) { - pass = 0; - Cnt = 0; - do { - psets = mcount(); - //PrintAndLog("psets: %d",psets); - while(psets) { - mbynum(&pset, --psets); - - /* skip if different width, or refin or refout don't match */ - if(plen(pset.spoly) != width[0] || (model.flags ^ pset.flags) & (P_REFIN | P_REFOUT)) - continue; - /* skip if the preset doesn't match specified parameters */ - if(rflags & R_HAVEP && pcmp(&model.spoly, &pset.spoly)) - continue; - if(rflags & R_HAVEI && psncmp(&model.init, &pset.init)) - continue; - if(rflags & R_HAVEX && psncmp(&model.xorout, &pset.xorout)) - continue; - - //for additional args (not used yet, maybe future?) - apoly = pclone(pset.xorout); - if(pset.flags & P_REFOUT) - prev(&apoly); - - for(qptr = apolys; qptr < pptr; ++qptr) { - crc = pcrc(*qptr, pset.spoly, pset.init, apoly, 0); - if(ptst(crc)) { - pfree(&crc); - break; - } else - pfree(&crc); - } - pfree(&apoly); - if(qptr == pptr) { - - /* the selected model solved all arguments */ - - mcanon(&pset); - - size_t size = (pset.name && *pset.name) ? strlen(pset.name) : 6; - //PrintAndLog("Size: %d, %s, count: %d",size,pset.name, Cnt); - char *tmp = calloc(size+1, sizeof(char)); - if (tmp==NULL){ - PrintAndLog("out of memory?"); - return 0; - } - width[Cnt] = width[0]; - memcpy(tmp, pset.name, size); - Models[Cnt++] = tmp; - *count = Cnt; - uflags |= C_RESULT; - } - } - mfree(&pset); - - /* toggle refIn/refOut and reflect arguments */ - if(~rflags & R_HAVERI) { - model.flags ^= P_REFIN | P_REFOUT; - for(qptr = apolys; qptr < pptr; ++qptr) - prevch(qptr, ibperhx); - } - } while(~rflags & R_HAVERI && ++pass < 2); - } - //got everything now free the memory... - - if(uflags & C_RESULT) { - for(qptr = apolys; qptr < pptr; ++qptr) - pfree(qptr); - } - if(!(model.flags & P_REFIN) != !(model.flags & P_REFOUT)) - return uerr("cannot search for crossed-endian models"); - - pass = 0; - do { - mptr = candmods = reveng(&model, qpoly, rflags, args, apolys); - if(mptr && plen(mptr->spoly)) - uflags |= C_RESULT; - while(mptr && plen(mptr->spoly)) { - mfree(mptr++); - } - free(candmods); - if(~rflags & R_HAVERI) { - model.flags ^= P_REFIN | P_REFOUT; - for(qptr = apolys; qptr < pptr; ++qptr) - prevch(qptr, ibperhx); - } - } while(~rflags & R_HAVERI && ++pass < 2); - for(qptr = apolys; qptr < pptr; ++qptr) - pfree(qptr); - free(apolys); - if(~uflags & C_RESULT) - return uerr("no models found"); - mfree(&model); - } - return 1; -} - -//test call to GetModels -int CmdrevengTest(const char *Cmd){ - char *Models[80]; - int count = 0; - uint8_t widtharr[80] = {0}; - uint8_t width = 0; - width = param_get8(Cmd, 0); - //PrintAndLog("width: %d",width); - if (width > 89) - return uerr("Width cannot exceed 89"); - - widtharr[0] = width; - int ans = GetModels(Models, &count, widtharr); - if (!ans) return 0; - - PrintAndLog("Count: %d",count); - for (int i = 0; i < count; i++){ - PrintAndLog("Model %d: %s, width: %d",i,Models[i], widtharr[i]); - free(Models[i]); - } - return 1; -} - -//-c || -v -//inModel = valid model name string - CRC-8 -//inHexStr = input hex string to calculate crc on -//reverse = reverse calc option if true -//endian = {0 = calc default endian input and output, b = big endian input and output, B = big endian output, r = right justified -// l = little endian input and output, L = little endian output only, t = left justified} -//result = calculated crc hex string -int RunModel(char *inModel, char *inHexStr, bool reverse, char endian, char *result){ - /* default values */ - static model_t model = { - PZERO, // no CRC polynomial, user must specify - PZERO, // Init = 0 - P_BE, // RefIn = false, RefOut = false, plus P_RTJUST setting in reveng.h - PZERO, // XorOut = 0 - PZERO, // check value unused - NULL // no model name - }; - int ibperhx = 8, obperhx = 8; - int rflags = 0; // search flags - int c; - //unsigned long width; - poly_t apoly, crc; - - char *string; - - // stdin must be binary - #ifdef _WIN32 - _setmode(STDIN_FILENO, _O_BINARY); - #endif /* _WIN32 */ - - SETBMP(); - //set model - if(!(c = mbynam(&model, inModel))) { - fprintf(stderr,"error: preset model '%s' not found. Use reveng -D to list presets.\n", inModel); - return 0; - } - if(c < 0) - return uerr("no preset models available"); - - // must set width so that parameter to -ipx is not zeroed - //width = plen(model.spoly); - rflags |= R_HAVEP | R_HAVEI | R_HAVERI | R_HAVERO | R_HAVEX; - - //set flags - switch (endian) { - case 'b': /* b big-endian (RefIn = false, RefOut = false ) */ - model.flags &= ~P_REFIN; - rflags |= R_HAVERI; - /* fall through: */ - case 'B': /* B big-endian output (RefOut = false) */ - model.flags &= ~P_REFOUT; - rflags |= R_HAVERO; - mnovel(&model); - /* fall through: */ - case 'r': /* r right-justified */ - model.flags |= P_RTJUST; - break; - case 'l': /* l little-endian input and output */ - model.flags |= P_REFIN; - rflags |= R_HAVERI; - /* fall through: */ - case 'L': /* L little-endian output */ - model.flags |= P_REFOUT; - rflags |= R_HAVERO; - mnovel(&model); - /* fall through: */ - case 't': /* t left-justified */ - model.flags &= ~P_RTJUST; - break; - } - - mcanon(&model); - - if (reverse) { - // v calculate reversed CRC - /* Distinct from the -V switch as this causes - * the arguments and output to be reversed as well. - */ - // reciprocate Poly - prcp(&model.spoly); - - /* mrev() does: - * if(refout) prev(init); else prev(xorout); - * but here the entire argument polynomial is - * reflected, not just the characters, so RefIn - * and RefOut are not inverted as with -V. - * Consequently Init is the mirror image of the - * one resulting from -V, and so we have: - */ - if(~model.flags & P_REFOUT) { - prev(&model.init); - prev(&model.xorout); - } - - // swap init and xorout - apoly = model.init; - model.init = model.xorout; - model.xorout = apoly; - } - // c calculate CRC - - // validate inputs - /* if(plen(model.spoly) == 0) { - * fprintf(stderr,"%s: no polynomial specified for -%c (add -w WIDTH -p POLY)\n", myname, mode); - * exit(EXIT_FAILURE); - * } - */ - - /* in the Williams model, xorout is applied after the refout stage. - * as refout is part of ptostr(), we reverse xorout here. - */ - if(model.flags & P_REFOUT) - prev(&model.xorout); - - apoly = strtop(inHexStr, model.flags, ibperhx); - - if(reverse) - prev(&apoly); - - crc = pcrc(apoly, model.spoly, model.init, model.xorout, model.flags); - - if(reverse) - prev(&crc); - - string = ptostr(crc, model.flags, obperhx); - for (int i = 0; i < 50; i++){ - result[i] = string[i]; - if (result[i]==0) break; - } - free(string); - pfree(&crc); - pfree(&apoly); - return 1; -} - -//test call to RunModel -int CmdrevengTestC(const char *Cmd){ - int cmdp = 0; - char inModel[30] = {0x00}; - char inHexStr[30] = {0x00}; - char result[30]; - int dataLen; - char endian = 0; - dataLen = param_getstr(Cmd, cmdp++, inModel, sizeof(inModel)); - if (dataLen < 4) return 0; - dataLen = param_getstr(Cmd, cmdp++, inHexStr, sizeof(inHexStr)); - if (dataLen < 4) return 0; - bool reverse = (param_get8(Cmd, cmdp++)) ? true : false; - endian = param_getchar(Cmd, cmdp++); - - //PrintAndLog("mod: %s, hex: %s, rev %d", inModel, inHexStr, reverse); - int ans = RunModel(inModel, inHexStr, reverse, endian, result); - if (!ans) return 0; - - PrintAndLog("Result: %s",result); - return 1; -} - -//returns a calloced string (needs to be freed) -char *SwapEndianStr(const char *inStr, const size_t len, const uint8_t blockSize){ - char *tmp = calloc(len+1, sizeof(char)); - for (uint8_t block=0; block < (uint8_t)(len/blockSize); block++){ - for (size_t i = 0; i < blockSize; i+=2){ - tmp[i+(blockSize*block)] = inStr[(blockSize-1-i-1)+(blockSize*block)]; - tmp[i+(blockSize*block)+1] = inStr[(blockSize-1-i)+(blockSize*block)]; - } - } - return tmp; -} - -// takes hex string in and searches for a matching result (hex string must include checksum) -int CmdrevengSearch(const char *Cmd){ - char inHexStr[50] = {0x00}; - int dataLen = param_getstr(Cmd, 0, inHexStr, sizeof(inHexStr)); - if (dataLen < 4) return 0; - - char *Models[80]; - int count = 0; - uint8_t width[80]; - width[0] = 0; - uint8_t crcChars = 0; - char result[30]; - char revResult[30]; - int ans = GetModels(Models, &count, width); - bool found = false; - if (!ans) return 0; - - // try each model and get result - for (int i = 0; i < count; i++){ - /*if (found) { - free(Models[i]); - continue; - }*/ - // round up to # of characters in this model's crc - crcChars = ((width[i]+7)/8)*2; - // can't test a model that has more crc digits than our data - if (crcChars >= dataLen) - continue; - memset(result, 0, 30); - char *inCRC = calloc(crcChars+1, sizeof(char)); - memcpy(inCRC, inHexStr+(dataLen-crcChars), crcChars); - - char *outHex = calloc(dataLen-crcChars+1, sizeof(char)); - memcpy(outHex, inHexStr, dataLen-crcChars); - - //PrintAndLog("DEBUG: dataLen: %d, crcChars: %d, Model: %s, CRC: %s, width: %d, outHex: %s",dataLen, crcChars, Models[i], inCRC, width[i], outHex); - ans = RunModel(Models[i], outHex, false, 0, result); - if (ans) { - //test for match - if (memcmp(result, inCRC, crcChars)==0){ - PrintAndLog("\nFound a possible match!\nModel: %s\nValue: %s\n",Models[i], result); - //optional - stop searching if found... - found = true; - } else { - if (crcChars > 2){ - char *swapEndian = SwapEndianStr(result, crcChars, crcChars); - if (memcmp(swapEndian, inCRC, crcChars)==0){ - PrintAndLog("\nFound a possible match!\nModel: %s\nValue EndianSwapped: %s\n",Models[i], swapEndian); - //optional - stop searching if found... - found = true; - } - free(swapEndian); - } - } - } - - //if (!found){ - ans = RunModel(Models[i], outHex, true, 0, revResult); - if (ans) { - //test for match - if (memcmp(revResult, inCRC, crcChars)==0){ - PrintAndLog("\nFound a possible match!\nModel Reversed: %s\nValue: %s\n",Models[i], revResult); - //optional - stop searching if found... - found = true; - } else { - if (crcChars > 2){ - char *swapEndian = SwapEndianStr(revResult, crcChars, crcChars); - if (memcmp(swapEndian, inCRC, crcChars)==0){ - PrintAndLog("\nFound a possible match!\nModel Reversed: %s\nValue EndianSwapped: %s\n",Models[i], swapEndian); - //optional - stop searching if found... - found = true; - } - free(swapEndian); - } - } - } - //} - free(inCRC); - free(outHex); - free(Models[i]); - } - if (!found) PrintAndLog("\nNo matches found\n"); - return 1; -} diff --git a/client/cmdcrc.h b/client/cmdcrc.h deleted file mode 100644 index 5041554d..00000000 --- a/client/cmdcrc.h +++ /dev/null @@ -1,20 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (C) 2015 iceman -// -// This code is licensed to you under the terms of the GNU GPL, version 2 or, -// at your option, any later version. See the LICENSE.txt file for the text of -// the license. -//----------------------------------------------------------------------------- -// CRC Calculations from the software reveng commands -//----------------------------------------------------------------------------- - -#ifndef CMDCRC_H__ -#define CMDCRC_H__ - -int CmdCrc(const char *Cmd); -int CmdrevengTest(const char *Cmd); -int CmdrevengTestC(const char *Cmd); -int CmdrevengSearch(const char *Cmd); -int GetModels(char *Models[], int *count, uint8_t *width); -int RunModel(char *inModel, char *inHexStr, bool reverse, char endian, char *result); -#endif diff --git a/client/cmdmain.c b/client/cmdmain.c index ae059ea2..719617fd 100644 --- a/client/cmdmain.c +++ b/client/cmdmain.c @@ -27,14 +27,12 @@ #include "util.h" #include "util_posix.h" #include "cmdscript.h" -#include "cmdcrc.h" unsigned int current_command = CMD_UNKNOWN; static int CmdHelp(const char *Cmd); static int CmdQuit(const char *Cmd); -static int CmdRev(const char *Cmd); //For storing command that are received from the device #define CMD_BUFFER_SIZE 50 @@ -53,7 +51,6 @@ static command_t CommandTable[] = {"hf", CmdHF, 1, "{ High Frequency commands... }"}, {"hw", CmdHW, 1, "{ Hardware commands... }"}, {"lf", CmdLF, 1, "{ Low Frequency commands... }"}, - {"reveng",CmdRev, 1, "Crc calculations from the software reveng1-30"}, {"script",CmdScript,1, "{ Scripting commands }"}, {"quit", CmdQuit, 1, "Exit program"}, {"exit", CmdQuit, 1, "Exit program"}, @@ -75,12 +72,6 @@ int CmdQuit(const char *Cmd) return 99; } -int CmdRev(const char *Cmd) -{ - CmdCrc(Cmd); - return 0; -} - /** * @brief This method should be called when sending a new command to the pm3. In case any old * responses from previous commands are stored in the buffer, a call to this method should clear them. diff --git a/client/obj/reveng/.dummy b/client/obj/reveng/.dummy deleted file mode 100644 index e69de29b..00000000 diff --git a/client/reveng/bmpbit.c b/client/reveng/bmpbit.c deleted file mode 100644 index 39a29e61..00000000 --- a/client/reveng/bmpbit.c +++ /dev/null @@ -1,86 +0,0 @@ -/* bmpbit.c - * Greg Cook, 9/Apr/2015 - */ - -/* CRC RevEng, an arbitrary-precision CRC calculator and algorithm finder - * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015 Gregory Cook - * - * This file is part of CRC RevEng. - * - * CRC RevEng 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. - * - * CRC RevEng 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. - * - * You should have received a copy of the GNU General Public License - * along with CRC RevEng. If not, see . - */ - -#ifdef BMPTST -# include -# include -#else -# define FILE void -#endif -#include "reveng.h" - -#if (defined BMPTST) || (BMP_BIT < 32) -/* Size in bits of a bmp_t. Not necessarily a power of two. */ -int bmpbit; - -/* The highest power of two that is strictly less than BMP_BIT. - * Initialises the index of a binary search for set bits in a bmp_t. - * (Computed correctly for BMP_BIT >= 2) - */ -int bmpsub; - -void -setbmp(void) { - /* Initialise BMP_BIT and BMP_SUB for the local architecture. */ - bmp_t bmpmax = ~(bmp_t) 0; - - bmpbit = 0; bmpsub = 1; - - while(bmpmax) { - bmpmax <<= 1; - ++bmpbit; - } - - while((bmpsub | (bmpsub - 1)) < bmpbit - 1) - bmpsub <<= 1; -} -#endif - -#ifdef BMPTST -int -main(int argc, char *argv[]) { - /* check the compile-time bitmap width is correct, otherwise - * searches run forever. */ -# if BMP_BIT > 0 - setbmp(); - if(BMP_BIT != bmpbit || BMP_SUB != bmpsub) { - fprintf(stderr,"reveng: configuration fault. Update " - "config.h with these definitions and " - "recompile:\n" - "\t#define BMP_BIT %d\n" - "\t#define BMP_SUB %d\n", - bmpbit, bmpsub); - exit(EXIT_FAILURE); - } -# endif /* BMP_BIT > 0 */ - /* check the bitmap constant macro */ - if(~(bmp_t) 0 != ~BMP_C(0)) { - fprintf(stderr, "reveng: configuration fault. Edit " - "the definition of BMP_C() in config.h to " - "match BMP_T and recompile.\n"); - exit(EXIT_FAILURE); - } - exit(EXIT_SUCCESS); -} - -#endif /* BMPTST */ diff --git a/client/reveng/cli.c b/client/reveng/cli.c deleted file mode 100644 index 224eedd6..00000000 --- a/client/reveng/cli.c +++ /dev/null @@ -1,628 +0,0 @@ -/* cli.c - * Greg Cook, 9/Apr/2015 - */ - -/* CRC RevEng, an arbitrary-precision CRC calculator and algorithm finder - * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015 Gregory Cook - * - * This file is part of CRC RevEng. - * - * CRC RevEng 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. - * - * CRC RevEng 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. - * - * You should have received a copy of the GNU General Public License - * along with CRC RevEng. If not, see . - */ - -/* 2015-04-03: added -z - * 2013-09-16: do not search with -M - * 2013-06-11: uprog() suppresses first progress report - * 2013-04-22: uprog() prints poly same as mtostr() - * 2013-02-07: added -q, uprog(), removed -W, R_ODDLY - * 2012-05-24: -D dumps parameters of all models - * 2012-03-03: added code to test sort order of model table - * 2012-02-20: set stdin to binary (MinGW). offer -D if preset unknown. - * 2011-09-06: -s reads arguments once. stdin not closed. - * 2011-09-06: fixed bad argument-freeing loops. - * 2011-08-27: validates BMP_C() - * 2011-08-26: validates BMPBIT and BMPSUB - * 2011-08-25: fixed Init/Xorout reflection logic in -V and -v - * 2011-01-17: fixed ANSI C warnings - * 2011-01-15: added NOFORCE - * 2011-01-14: added -k, -P - * 2011-01-10: reorganised switches, added -V, -X - * 2010-12-26: renamed CRC RevEng - * 2010-12-18: implemented -c, -C - * 2010-12-14: added and implemented -d, -D, fixed -ipx entry - * 2010-12-11: implemented -e. first tests - * 2010-12-10: finalised option processing. started input validation - * 2010-12-07: started cli - */ - -#include -#include -#include "getopt.h" -#ifdef _WIN32 -# include -# include -# ifndef STDIN_FILENO -# define STDIN_FILENO 0 -# endif /* STDIN_FILENO */ -#endif /* _WIN32 */ - -#include "reveng.h" - -static FILE *oread(const char *); -static poly_t rdpoly(const char *, int, int); -static void usage(void); - -static const char *myname = "reveng"; /* name of our program */ - -int reveng_main(int argc, char *argv[]) { - /* Command-line interface for CRC RevEng. - * Process options and switches in the argument list and - * run the required function. - */ - - /* default values */ - model_t model = { - PZERO, /* no CRC polynomial, user must specify */ - PZERO, /* Init = 0 */ - P_BE, /* RefIn = false, RefOut = false, plus P_RTJUST setting in reveng.h */ - PZERO, /* XorOut = 0 */ - PZERO, /* check value unused */ - NULL /* no model name */ - }; - int ibperhx = 8, obperhx = 8; - int rflags = 0, uflags = 0; /* search and UI flags */ - - unsigned long width = 0UL; - int c, mode = 0, args, psets, pass; - poly_t apoly, crc, qpoly = PZERO, *apolys, *pptr = NULL, *qptr = NULL; - model_t pset = model, *candmods, *mptr; - char *string; - - myname = argv[0]; - - /* stdin must be binary */ -#ifdef _WIN32 - _setmode(STDIN_FILENO, _O_BINARY); -#endif /* _WIN32 */ - - SETBMP(); - - pos=0; - optind=1; - do { - c=getopt(argc, argv, "?A:BDFLMP:SVXa:bcdefhi:k:lm:p:q:rstuvw:x:yz"); - switch(c) { - case 'A': /* A: bits per output character */ - case 'a': /* a: bits per character */ - if((obperhx = atoi(optarg)) > BMP_BIT) { - fprintf(stderr,"%s: argument to -%c must be between 1 and %d\n", myname, c, BMP_BIT); - return 0; - //exit(EXIT_FAILURE); - } - if(c == 'a') ibperhx = obperhx; - break; - case 'b': /* b big-endian (RefIn = false, RefOut = false ) */ - model.flags &= ~P_REFIN; - rflags |= R_HAVERI; - /* fall through: */ - case 'B': /* B big-endian output (RefOut = false) */ - model.flags &= ~P_REFOUT; - rflags |= R_HAVERO; - mnovel(&model); - /* fall through: */ - case 'r': /* r right-justified */ - model.flags |= P_RTJUST; - break; - case 'c': /* c calculate CRC */ - case 'D': /* D list primary model names */ - case 'd': /* d dump CRC model */ - case 'e': /* e echo arguments */ - case 's': /* s search for algorithm */ - case 'v': /* v calculate reversed CRC */ - if(mode) { - fprintf(stderr,"%s: more than one mode switch specified. Use %s -h for help.\n", myname, myname); - return 0; - //exit(EXIT_FAILURE); - } - mode = c; - break; - case 'F': /* F force search */ -#ifndef NOFORCE - uflags |= C_FORCE; -#endif - break; - case 'f': /* f arguments are filenames */ - uflags |= C_INFILE; - break; - case 'h': /* h get help / usage */ - case 'u': /* u get help / usage */ - case '?': /* ? get help / usage */ - default: - usage(); - return 0; - //exit(EXIT_FAILURE); - break; - case 'i': /* i: Init value */ - pptr = &model.init; - rflags |= R_HAVEI; - goto ippx; - case 'k': /* k: polynomial in Koopman notation */ - pfree(&model.spoly); - model.spoly = strtop(optarg, 0, 4); - pkchop(&model.spoly); - width = plen(model.spoly); - rflags |= R_HAVEP; - mnovel(&model); - break; - case 'l': /* l little-endian input and output */ - model.flags |= P_REFIN; - rflags |= R_HAVERI; - /* fall through: */ - case 'L': /* L little-endian output */ - model.flags |= P_REFOUT; - rflags |= R_HAVERO; - mnovel(&model); - /* fall through: */ - case 't': /* t left-justified */ - model.flags &= ~P_RTJUST; - break; - case 'm': /* m: select preset CRC model */ - if(!(c = mbynam(&model, optarg))) { - fprintf(stderr,"%s: preset model '%s' not found. Use %s -D to list presets.\n", myname, optarg, myname); - return 0; - //exit(EXIT_FAILURE); - } - if(c < 0){ - uerror("no preset models available"); - return 0; - } - /* must set width so that parameter to -ipx is not zeroed */ - width = plen(model.spoly); - rflags |= R_HAVEP | R_HAVEI | R_HAVERI | R_HAVERO | R_HAVEX; - break; - case 'M': /* M non-augmenting algorithm */ - model.flags &= ~P_MULXN; - break; - case 'P': /* P: reversed polynomial */ - case 'p': /* p: polynomial */ - pptr = &model.spoly; - rflags &= ~R_HAVEQ; - rflags |= R_HAVEP; -ippx: - pfree(pptr); - *pptr = strtop(optarg, 0, 4); - pright(pptr, width); - if(c == 'P') - prev(pptr); - mnovel(&model); - break; - case 'q': /* q: range end polynomial */ - pptr = &qpoly; - rflags &= ~R_HAVEP; - rflags |= R_HAVEQ; - goto ippx; - case 'S': /* s space between output characters */ - model.flags |= P_SPACE; - break; - case 'V': /* v reverse algorithm */ - /* Distinct from the -v switch as the - * user will have to reverse his or her - * own arguments. The user cannot dump - * the model generated by -v either. - */ - mrev(&model); - break; - case 'w': /* w: CRC width = order - 1 */ - width = (unsigned long) atol(optarg); - break; - case 'X': /* X print uppercase hex */ - model.flags |= P_UPPER; - break; - case 'x': /* x: XorOut value */ - pptr = &model.xorout; - rflags |= R_HAVEX; - goto ippx; - case 'y': /* y little-endian byte order in files */ - model.flags |= P_LTLBYT; - break; - case 'z': /* z raw binary arguments */ - model.flags |= P_DIRECT; - break; - case -1: /* no more options, continue */ - ; - } - } while(c != -1); - - /* canonicalise the model, so the one we dump is the one we - * calculate with (not with -s, spoly may be blank which will - * normalise to zero and clear init and xorout.) - */ - if(mode != 's') - mcanon(&model); - - switch(mode) { - case 'v': /* v calculate reversed CRC */ - /* Distinct from the -V switch as this causes - * the arguments and output to be reversed as well. - */ - /* reciprocate Poly */ - prcp(&model.spoly); - - /* mrev() does: - * if(refout) prev(init); else prev(xorout); - * but here the entire argument polynomial is - * reflected, not just the characters, so RefIn - * and RefOut are not inverted as with -V. - * Consequently Init is the mirror image of the - * one resulting from -V, and so we have: - */ - if(~model.flags & P_REFOUT) { - prev(&model.init); - prev(&model.xorout); - } - - /* swap init and xorout */ - apoly = model.init; - model.init = model.xorout; - model.xorout = apoly; - - /* fall through: */ - case 'c': /* c calculate CRC */ - - /* validate inputs */ - /* if(plen(model.spoly) == 0) { - * fprintf(stderr,"%s: no polynomial specified for -%c (add -w WIDTH -p POLY)\n", myname, mode); - * exit(EXIT_FAILURE); - * } - */ - - /* in the Williams model, xorout is applied after the refout stage. - * as refout is part of ptostr(), we reverse xorout here. - */ - if(model.flags & P_REFOUT) - prev(&model.xorout); - - for(; optind < argc; ++optind) { - if(uflags & C_INFILE) - apoly = rdpoly(argv[optind], model.flags, ibperhx); - else - apoly = strtop(argv[optind], model.flags, ibperhx); - - if(mode == 'v') - prev(&apoly); - - crc = pcrc(apoly, model.spoly, model.init, model.xorout, model.flags); - - if(mode == 'v') - prev(&crc); - - string = ptostr(crc, model.flags, obperhx); - puts(string); - free(string); - pfree(&crc); - pfree(&apoly); - } - break; - case 'D': /* D dump all models */ - args = mcount(); - if(!args){ - uerror("no preset models available"); - return 0; - } - for(mode = 0; mode < args; ++mode) { - mbynum(&model, mode); - mcanon(&model); - ufound(&model); - } - break; - case 'd': /* d dump CRC model */ - /* maybe we don't want to do this: - * either attaching names to arbitrary models or forcing to a preset - * mmatch(&model, M_OVERWR); - */ - if(~model.flags & P_MULXN){ - uerror("not a Williams model compliant algorithm"); - return 0; - } - string = mtostr(&model); - puts(string); - free(string); - break; - case 'e': /* e echo arguments */ - for(; optind < argc; ++optind) { - if(uflags & C_INFILE) - apoly = rdpoly(argv[optind], model.flags, ibperhx); - else - apoly = strtop(argv[optind], model.flags, ibperhx); - - psum(&apoly, model.init, 0UL); - string = ptostr(apoly, model.flags, obperhx); - puts(string); - free(string); - pfree(&apoly); - } - break; - case 's': /* s search for algorithm */ - if(!width){ - uerror("must specify positive -k or -w before -s"); - return 0; - } - if(~model.flags & P_MULXN){ - uerror("cannot search for non-Williams compliant models"); - return 0; - } - praloc(&model.spoly, width); - praloc(&model.init, width); - praloc(&model.xorout, width); - if(!plen(model.spoly)) - palloc(&model.spoly, width); - else - width = plen(model.spoly); - - /* special case if qpoly is zero, search to end of range */ - if(!ptst(qpoly)) - rflags &= ~R_HAVEQ; - - /* allocate argument array */ - args = argc - optind; - if(!(apolys = malloc(args * sizeof(poly_t)))){ - uerror("cannot allocate memory for argument list"); - return 0; - } - - for(pptr = apolys; optind < argc; ++optind) { - if(uflags & C_INFILE) - *pptr++ = rdpoly(argv[optind], model.flags, ibperhx); - else - *pptr++ = strtop(argv[optind], model.flags, ibperhx); - } - /* exit value of pptr is used hereafter! */ - - /* if endianness not specified, try - * little-endian then big-endian. - * NB: crossed-endian algorithms will not be - * searched. - */ - - /* scan against preset models */ - if(~uflags & C_FORCE) { - pass = 0; - do { - psets = mcount(); - while(psets) { - mbynum(&pset, --psets); - /* skip if different width, or refin or refout don't match */ - if(plen(pset.spoly) != width || (model.flags ^ pset.flags) & (P_REFIN | P_REFOUT)) - continue; - /* skip if the preset doesn't match specified parameters */ - if(rflags & R_HAVEP && pcmp(&model.spoly, &pset.spoly)) - continue; - if(rflags & R_HAVEI && psncmp(&model.init, &pset.init)) - continue; - if(rflags & R_HAVEX && psncmp(&model.xorout, &pset.xorout)) - continue; - apoly = pclone(pset.xorout); - if(pset.flags & P_REFOUT) - prev(&apoly); - for(qptr = apolys; qptr < pptr; ++qptr) { - crc = pcrc(*qptr, pset.spoly, pset.init, apoly, 0); - if(ptst(crc)) { - pfree(&crc); - break; - } else - pfree(&crc); - } - pfree(&apoly); - if(qptr == pptr) { - /* the selected model solved all arguments */ - mcanon(&pset); - ufound(&pset); - uflags |= C_RESULT; - } - } - mfree(&pset); - - /* toggle refIn/refOut and reflect arguments */ - if(~rflags & R_HAVERI) { - model.flags ^= P_REFIN | P_REFOUT; - for(qptr = apolys; qptr < pptr; ++qptr) - prevch(qptr, ibperhx); - } - } while(~rflags & R_HAVERI && ++pass < 2); - } - if(uflags & C_RESULT) { - for(qptr = apolys; qptr < pptr; ++qptr) - pfree(qptr); - //return 1; - //exit(EXIT_SUCCESS); - } - if(!(model.flags & P_REFIN) != !(model.flags & P_REFOUT)){ - uerror("cannot search for crossed-endian models"); - return 0; - } - pass = 0; - do { - mptr = candmods = reveng(&model, qpoly, rflags, args, apolys); - if(mptr && plen(mptr->spoly)) - uflags |= C_RESULT; - while(mptr && plen(mptr->spoly)) { - /* results were printed by the callback - * string = mtostr(mptr); - * puts(string); - * free(string); - */ - mfree(mptr++); - } - free(candmods); - if(~rflags & R_HAVERI) { - model.flags ^= P_REFIN | P_REFOUT; - for(qptr = apolys; qptr < pptr; ++qptr) - prevch(qptr, ibperhx); - } - } while(~rflags & R_HAVERI && ++pass < 2); - for(qptr = apolys; qptr < pptr; ++qptr) - pfree(qptr); - free(apolys); - if(~uflags & C_RESULT) - uerror("no models found"); - break; - default: /* no mode specified */ - fprintf(stderr, "%s: no mode switch specified. Use %s -h for help.\n", myname, myname); - //exit(EXIT_FAILURE); - } - - return 1; - //exit(EXIT_SUCCESS); -} - -void -ufound(const model_t *model) { - /* Callback function to report each model found */ - char *string; - - if(!model) return; - /* generated models will be canonical */ - string = mtostr(model); - puts(string); - free(string); -} - -void -uerror(const char *msg) { - /* Callback function to report fatal errors */ - fprintf(stderr, "%s: %s\n", myname, msg); - return; - //exit(EXIT_FAILURE); -} - -void -uprog(const poly_t gpoly, int flags, unsigned long seq) { - /* Callback function to report search progress */ - char *string; - - /* Suppress first report in CLI */ - if(!seq) - return; - string = ptostr(gpoly, P_RTJUST, 4); - fprintf(stderr, "%s: searching: width=%ld poly=0x%s refin=%s refout=%s\n", - myname, plen(gpoly), string, - (flags & P_REFIN ? "true" : "false"), - (flags & P_REFOUT ? "true" : "false") - ); - free(string); -} - -static poly_t -rdpoly(const char *name, int flags, int bperhx) { - /* read poly from file in chunks and report errors */ - - poly_t apoly = PZERO, chunk = PZERO; - FILE *input; - - input = oread(name); - while(!feof(input) && !ferror(input)) { - chunk = filtop(input, BUFFER, flags, bperhx); - psum(&apoly, chunk, plen(apoly)); - pfree(&chunk); - } - if(ferror(input)) { - fprintf(stderr,"%s: error condition on file '%s'\n", myname, name); - exit(EXIT_FAILURE); - } - /* close file unless stdin */ - if(input == stdin) - /* reset EOF condition */ - clearerr(input); - else if(fclose(input)) { - fprintf(stderr,"%s: error closing file '%s'\n", myname, name); - exit(EXIT_FAILURE); - } - return(apoly); -} - -static FILE * -oread(const char *name) { - /* open file for reading and report errors */ - FILE *handle; - - /* recognise special name '-' as standard input */ - if(*name == '-' && name[1] == '\0') - return(stdin); - if(!(handle = fopen(name, "rb"))) { - fprintf(stderr, "%s: cannot open '%s' for reading\n", myname, name); - return 0; - //exit(EXIT_FAILURE); - } - return(handle); -} - -static void -usage(void) { - /* print usage if asked, or if syntax incorrect */ - fprintf(stderr, - "CRC RevEng, an arbitrary-precision CRC calculator and algorithm finder\n" - "Usage:\t"); - fputs(myname, stderr); - fprintf(stderr, - "\t-cdDesvhu? [-bBfFlLMrStVXyz]\n" - "\t\t[-a BITS] [-A OBITS] [-i INIT] [-k KPOLY] [-m MODEL]\n" - "\t\t[-p POLY] [-P RPOLY] [-q QPOLY] [-w WIDTH] [-x XOROUT]\n" - "\t\t[STRING...]\n" - "Options:\n" - "\t-a BITS\t\tbits per character (1 to %d)\n" - "\t-A OBITS\tbits per output character (1 to %d)\n" - "\t-i INIT\t\tinitial register value\n" - "\t-k KPOLY\tgenerator in Koopman notation (implies WIDTH)\n" - "\t-m MODEL\tpreset CRC algorithm\n" - "\t-p POLY\t\tgenerator or search range start polynomial\n" - "\t-P RPOLY\treversed generator polynomial\n", - BMP_BIT, BMP_BIT); - fprintf(stderr, - "\t-q QPOLY\tsearch range end polynomial\n" - "\t-w WIDTH\tregister size, in bits\n" - "\t-x XOROUT\tfinal register XOR value\n" - "Modifier switches:\n" - "\t-b big-endian CRC\t\t-B big-endian CRC output\n" - "\t-f read files named in STRINGs\t-F find presets less quickly\n" - "\t-l little-endian CRC\t\t-L little-endian CRC output\n" - "\t-M non-augmenting algorithm\t-r right-justified output\n" - "\t-S print spaces between chars\t-t left-justified output\n" - "\t-V reverse algorithm only\t-X print uppercase hex\n" - "\t-y low bytes first in files\t-z raw binary STRINGs\n"); - fprintf(stderr, - "Mode switches:\n" - "\t-c calculate CRCs\t\t-d dump algorithm parameters\n" - "\t-D list preset algorithms\t-e echo (and reformat) input\n" - "\t-s search for algorithm\t\t-v calculate reversed CRCs\n" - "\t-g search for alg given hex+crc\t-h | -u | -? show this help\n" - "Common Use Examples:\n" - "\t reveng -g 01020304e3\n" - "\t Searches for a known/common crc preset that computes the crc\n" - "\t on the end of the given hex string\n" - "\t reveng -w 8 -s 01020304e3 010204039d\n" - "\t Searches for any possible 8 bit width crc calc that computes\n" - "\t the crc on the end of the given hex string(s)\n" - "\t reveng -m CRC-8 -c 01020304\n" - "\t Calculates the crc-8 of the given hex string\n" - "\t reveng -D\n" - "\t Outputs a list of all known/common crc models with their\n" - "\t preset values\n" - "\n" - "Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015 Gregory Cook\n" - "This is free software; see the source for copying conditions. There is NO\n" - "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n" - "Version " - VERSION - "\t\t\t\t \n"); -} diff --git a/client/reveng/config.h b/client/reveng/config.h deleted file mode 100644 index 2f5108f0..00000000 --- a/client/reveng/config.h +++ /dev/null @@ -1,96 +0,0 @@ -/* config.h - * Greg Cook, 9/Apr/2015 - */ - -/* CRC RevEng, an arbitrary-precision CRC calculator and algorithm finder - * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015 Gregory Cook - * - * This file is part of CRC RevEng. - * - * CRC RevEng 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. - * - * CRC RevEng 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. - * - * You should have received a copy of the GNU General Public License - * along with CRC RevEng. If not, see . - */ - -#ifndef CONFIG_H -#define CONFIG_H 1 - -/***************************************** - * * - * Start of user configuration options * - * * - *****************************************/ - -/* A type to contain polynomial coefficient bitmaps. - * Can be changed to 'unsigned long long' for some extended compilers. - * Adjust BMP_C(), BMP_BIT and BMP_SUB below if this is changed. - */ - -#define BMP_T unsigned long - -/* Creates an appropriate numeric constant for bmp_t. - * If the underlying type is 'unsigned long long', change UL to ULL. - */ - -#define BMP_C(n) (n##UL) - -/* Define BMPMACRO to turn the definitions of the size of a bmp_t into - * compile-time constants. This improves efficiency but makes the code - * platform-specific. - */ - -/* #define BMPMACRO 1 */ - -/* Some enterprise users may wish to disable the -F switch to minimise CPU - * usage. To do this, define the macro NOFORCE. - */ - -/* #define NOFORCE 1 */ - -/* Define PRESETS to compile CRC RevEng with the preset models from the - * CRC Catalogue. This implies BMPMACRO and so makes the code platform- - * specific. - */ - - -// PM3 NOTES: -// only PRESETS tested on windows -// PRESETS was commented out of original code -// but to enable preset models it must be enabled -// (marshmellow) -#define PRESETS 1 - - -/* Macros defining the size of a bmp_t. - * Their values only matter if PRESETS and/or BMPMACRO are defined, in - * which case edit the macros below to suit your architecture. - * Otherwise, BMP_BIT and BMP_SUB will be redefined as aliases of bmpbit - * and bmpsub, global objects initialised at run time. - */ - -/* Size in bits of a bmp_t. Not necessarily a power of two. */ - -#define BMP_BIT 32 - -/* The highest power of two that is strictly less than BMP_BIT. - * Initialises the index of a binary search for set bits in a bmp_t. - */ - -#define BMP_SUB 16 - -/***************************************** - * * - * End of user configuration options * - * * - *****************************************/ - -#endif /* CONFIG_H */ diff --git a/client/reveng/getopt.c b/client/reveng/getopt.c deleted file mode 100644 index abe99634..00000000 --- a/client/reveng/getopt.c +++ /dev/null @@ -1,81 +0,0 @@ -/*---------------------------------------------------------------------- - - Replacement for Unix "getopt()", for DOS/Windows/etc. - - getopt.c 1.3 2003/09/17 16:17:59 - - Copyright (C) 1998, 2003 by David A. Hinds -- All Rights Reserved - - This file is part of ASPEX. - - ASPEX 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 2 of the License, or - (at your option) any later version. - - ASPEX 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. - - You should have received a copy of the GNU General Public License - along with ASPEX; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -----------------------------------------------------------------------*/ - -#include "string.h" -#include "stdio.h" -#include "getopt.h" - -char *optarg; -int optind = 1, opterr, optopt; -int pos = 0; -int getopt(int argc, char *argv[], const char *optstring) -{ - //static int pos = 0; - char *str; - - if (pos == 0) { - if ((optind >= argc) || (*argv[optind] != '-')) - return EOF; - pos = 1; - if (argv[optind][pos] == '\0') - return EOF; - } - - str = strchr(optstring, argv[optind][pos]); - if (str == NULL) { - optopt = argv[optind][pos]; - if (opterr) - fprintf(stderr, "%s: illegal option -- %c\n", argv[0], - optopt); - return '?'; - } - - if (str[1] == ':') { - if (argv[optind][pos+1] != '\0') { - optarg = &argv[optind][pos+1]; - return *str; - } - optind++; - if (optind >= argc) { - optopt = *str; - if (opterr) - fprintf(stderr, "%s: option requires an argument -- %c\n", - argv[0], optopt); - return '?'; - } - optarg = argv[optind]; - optind++; pos = 0; - return *str; - } - else { - pos++; - if (argv[optind][pos] == '\0') { - optind++; - pos = 0; - } - return *str; - } -} diff --git a/client/reveng/getopt.h b/client/reveng/getopt.h deleted file mode 100644 index bf66d9b1..00000000 --- a/client/reveng/getopt.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - getopt.h 1.2 2003/09/17 16:17:59 - - Copyright (C) 1998, 2003 by David A. Hinds -- All Rights Reserved - - This file is part of ASPEX. - - ASPEX 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 2 of the License, or - (at your option) any later version. - - ASPEX 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. - - You should have received a copy of the GNU General Public License - along with ASPEX; if not, write to the Free Software Foundation, - Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -extern char *optarg; -extern int optind, opterr, optopt, pos; -int getopt(int argc, char *argv[], const char *optstring); diff --git a/client/reveng/model.c b/client/reveng/model.c deleted file mode 100644 index 5a9b6580..00000000 --- a/client/reveng/model.c +++ /dev/null @@ -1,823 +0,0 @@ -/* model.c - * Greg Cook, 9/Apr/2015 - */ - -/* CRC RevEng, an arbitrary-precision CRC calculator and algorithm finder - * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015 Gregory Cook - * - * This file is part of CRC RevEng. - * - * CRC RevEng 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. - * - * CRC RevEng 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. - * - * You should have received a copy of the GNU General Public License - * along with CRC RevEng. If not, see . - */ - -/* 2014-01-14: added CRC-8/DVB-S2 - * 2014-01-11: corrected CRC-40/GSM, added alias CRC-8/AES - * 2013-10-14: added CRC-13/BBC and six cdma2000 algorithms - * 2013-06-11: ensure BMP_BIT is an integer constant to compile presets - * 2013-01-20: big polynomials autogenerated, corrected CRC-82/DARC - * 2012-07-19: added CRC-8/EBU - * 2012-07-16: added CRC-15/MPT1327 - * 2012-05-25: removed CRC-1/PARITY-EVEN, CRC-1/PARITY-ODD - * 2012-04-12: added model CRC-31/PHILIPS - * 2012-03-03: single-line Williams model string conversion - * 2012-02-20: corrected model CRC-6/DARC - * 2011-09-03: added mrev(), mnovel() - * 2011-08-28: added model CRC-64/XZ - * 2011-04-30: added models CRC-16/TMS37157 and CRC-A, and alias CRC-B - * 2011-02-10: made preset models ANSI C compliant - * 2011-01-17: fixed ANSI C warnings (except preset models) - * 2011-01-01: added mbynum(), mcount() - * 2010-12-26: renamed CRC RevEng - * 2010-12-18: minor change to mtostr() output format - * 2010-12-15: added mcmp(), mmatch() - * 2010-12-14: finished mbynam(), mnames(), mtostr() - * 2010-12-13: restarted with PCONST macros - * 2010-12-12: was having so much fun I didn't think to try compiling. :( - * 2010-12-12: started models.c - */ - -#include -#include -#include -#include -#include "reveng.h" - -/* Private declarations */ - -struct mpreset { - const unsigned long width; /* width of CRC algorithm */ - const bmp_t *const bspoly; /* polynomial with highest-order term removed. length determines CRC width */ - const bmp_t *const binit; /* initial register value. length == poly.length */ - const int flags; /* P_REFIN and P_REFOUT indicate reflected input/output */ - const bmp_t *const bxorout; /* final register XOR mask. length == poly.length */ - const bmp_t *const bcheck; /* optional check value, the CRC of the UTF-8 string "123456789" */ - const char *const name; /* optional canonical name of the model */ -}; - -struct malias { - const char *name; - const struct mpreset *model; - const int isprimry; -}; - -#ifdef PRESETS -# if BMP_BIT < 32 -# error config.h: BMP_BIT must be an integer constant macro to compile presets -# else /* BMP_BIT */ - -/* Big polynomial constants. */ - -/* Directives for relink.pl */ -/* CONSTANT b40 = (40, 0x0004820009) */ -/* CONSTANT b40a = (40, 0xffffffffff) */ -/* CONSTANT b40b = (40, 0xd4164fc646) */ -/* CONSTANT b64 = (64, 0x42f0e1eba9ea3693) */ -/* CONSTANT b64a = (64, 0x6c40df5f0b497347) */ -/* CONSTANT b64b = (64, 0xffffffffffffffff) */ -/* CONSTANT b64c = (64, 0x62ec59e3f1a4f00a) */ -/* CONSTANT b64d = (64, 0x995dc9bbdf1939fa) */ -/* CONSTANT b82 = (82, 0x0308c0111011401440411) */ -/* CONSTANT b82a = (82, 0x09ea83f625023801fd612) */ - -/* The next section was generated by relink.pl from the directives above. */ - -/* DO NOT EDIT the section below, INCLUDING the next comment. */ -/* BEGIN AUTO-GENERATED CONSTANTS */ -# if BMP_BIT >= 40 -static const bmp_t b40[] = { - BMP_C(0x0004820009) << (BMP_BIT - 40), -}; -static const bmp_t b40a[] = { - BMP_C(0xffffffffff) << (BMP_BIT - 40), -}; -static const bmp_t b40b[] = { - BMP_C(0xd4164fc646) << (BMP_BIT - 40), -}; -# else /* BMP_BIT */ -static const bmp_t b40[] = { - BMP_C(0x00048200) << (BMP_BIT - 32) | BMP_C(0x04) >> (39 - BMP_BIT), - BMP_C(0x09) << (BMP_BIT * 2 - 40), -}; -static const bmp_t b40a[] = { - BMP_C(0xffffffff) << (BMP_BIT - 32) | BMP_C(0x7f) >> (39 - BMP_BIT), - BMP_C(0xff) << (BMP_BIT * 2 - 40), -}; -static const bmp_t b40b[] = { - BMP_C(0xd4164fc6) << (BMP_BIT - 32) | BMP_C(0x23) >> (39 - BMP_BIT), - BMP_C(0x46) << (BMP_BIT * 2 - 40), -}; -# endif /* BMP_BIT */ - -# if BMP_BIT >= 64 -static const bmp_t b64[] = { - BMP_C(0x42f0e1eba9ea3693) << (BMP_BIT - 64), -}; -static const bmp_t b64a[] = { - BMP_C(0x6c40df5f0b497347) << (BMP_BIT - 64), -}; -static const bmp_t b64b[] = { - BMP_C(0xffffffffffffffff) << (BMP_BIT - 64), -}; -static const bmp_t b64c[] = { - BMP_C(0x62ec59e3f1a4f00a) << (BMP_BIT - 64), -}; -static const bmp_t b64d[] = { - BMP_C(0x995dc9bbdf1939fa) << (BMP_BIT - 64), -}; -# else /* BMP_BIT */ -static const bmp_t b64[] = { - BMP_C(0x42f0e1eb) << (BMP_BIT - 32) | BMP_C(0x54f51b49) >> (63 - BMP_BIT), - BMP_C(0xa9ea3693) << (BMP_BIT * 2 - 64), -}; -static const bmp_t b64a[] = { - BMP_C(0x6c40df5f) << (BMP_BIT - 32) | BMP_C(0x05a4b9a3) >> (63 - BMP_BIT), - BMP_C(0x0b497347) << (BMP_BIT * 2 - 64), -}; -static const bmp_t b64b[] = { - BMP_C(0xffffffff) << (BMP_BIT - 32) | BMP_C(0x7fffffff) >> (63 - BMP_BIT), - BMP_C(0xffffffff) << (BMP_BIT * 2 - 64), -}; -static const bmp_t b64c[] = { - BMP_C(0x62ec59e3) << (BMP_BIT - 32) | BMP_C(0x78d27805) >> (63 - BMP_BIT), - BMP_C(0xf1a4f00a) << (BMP_BIT * 2 - 64), -}; -static const bmp_t b64d[] = { - BMP_C(0x995dc9bb) << (BMP_BIT - 32) | BMP_C(0x6f8c9cfd) >> (63 - BMP_BIT), - BMP_C(0xdf1939fa) << (BMP_BIT * 2 - 64), -}; -# endif /* BMP_BIT */ - -# if BMP_BIT >= 82 -static const bmp_t b82[] = { - BMP_C(0x0308c0111011401440411) << (BMP_BIT - 82), -}; -static const bmp_t b82a[] = { - BMP_C(0x09ea83f625023801fd612) << (BMP_BIT - 82), -}; -# elif BMP_BIT >= 41 -static const bmp_t b82[] = { - BMP_C(0x01846008880) << (BMP_BIT - 41) | BMP_C(0x08a00a20208) >> (81 - BMP_BIT), - BMP_C(0x11401440411) << (BMP_BIT * 2 - 82), -}; -static const bmp_t b82a[] = { - BMP_C(0x04f541fb128) << (BMP_BIT - 41) | BMP_C(0x011c00feb09) >> (81 - BMP_BIT), - BMP_C(0x023801fd612) << (BMP_BIT * 2 - 82), -}; -# else /* BMP_BIT */ -static const bmp_t b82[] = { - BMP_C(0x0c230044) << (BMP_BIT - 32) | BMP_C(0x040) >> (40 - BMP_BIT), - BMP_C(0x40450051) << (BMP_BIT * 2 - 64) | BMP_C(0x00104) >> (80 - BMP_BIT * 2), - BMP_C(0x00411) << (BMP_BIT * 3 - 82), -}; -static const bmp_t b82a[] = { - BMP_C(0x27aa0fd8) << (BMP_BIT - 32) | BMP_C(0x094) >> (40 - BMP_BIT), - BMP_C(0x9408e007) << (BMP_BIT * 2 - 64) | BMP_C(0x0f584) >> (80 - BMP_BIT * 2), - BMP_C(0x3d612) << (BMP_BIT * 3 - 82), -}; -# endif /* BMP_BIT */ - -/* END AUTO-GENERATED CONSTANTS */ -/* DO NOT EDIT the section above, INCLUDING the previous comment. */ - -/* Array of the polynomial bitmaps used in the model table. */ -static const bmp_t b32[] = { - BMP_C(0x00000000) << (BMP_BIT - 32), /* 0 -- 5, 00 */ - BMP_C(0x000000af) << (BMP_BIT - 32), /* 1 -- 32,000000af */ - BMP_C(0x00010000) << (BMP_BIT - 32), /* 2 -- 16, 0001 */ - BMP_C(0x00020000) << (BMP_BIT - 32), /* 3 -- 15, 0001 */ - BMP_C(0x007e0000) << (BMP_BIT - 32), /* 4 -- 16, 007e */ - BMP_C(0x007f0000) << (BMP_BIT - 32), /* 5 -- 16, 007f */ - BMP_C(0x03400000) << (BMP_BIT - 32), /* 6 -- 11, 01a */ - BMP_C(0x0376e6e7) << (BMP_BIT - 32), /* 7 -- 32,0376e6e7 */ - BMP_C(0x04c11db7) << (BMP_BIT - 32), /* 8 -- 32,04c11db7 */ - BMP_C(0x05890000) << (BMP_BIT - 32), /* 9 -- 16, 0589 */ - BMP_C(0x07000000) << (BMP_BIT - 32), /* 10 -- 8, 07 */ - BMP_C(0x09823b6e) << (BMP_BIT - 32), /* 11 -- 31,04c11db7 */ - BMP_C(0x0b3c0000) << (BMP_BIT - 32), /* 12 -- 15, 059e */ - BMP_C(0x0c000000) << (BMP_BIT - 32), /* 13 -- 6, 03 */ - BMP_C(0x0fb30000) << (BMP_BIT - 32), /* 14 -- 16, 0fb3 */ - BMP_C(0x10210000) << (BMP_BIT - 32), /* 15 -- 16, 1021 */ - BMP_C(0x12000000) << (BMP_BIT - 32), /* 16 -- 7, 09 */ - BMP_C(0x15000000) << (BMP_BIT - 32), /* 17 -- 8, 15 */ - BMP_C(0x18000000) << (BMP_BIT - 32), /* 18 -- 6, 06 */ - BMP_C(0x19d3c8d8) << (BMP_BIT - 32), /* 19 -- 31,0ce9e46c */ - BMP_C(0x1c000000) << (BMP_BIT - 32), /* 20 -- 6, 07 */ - BMP_C(0x1d000000) << (BMP_BIT - 32), /* 21 -- 8, 1d */ - BMP_C(0x1d0f0000) << (BMP_BIT - 32), /* 22 -- 16, 1d0f */ - BMP_C(0x1edc6f41) << (BMP_BIT - 32), /* 23 -- 32,1edc6f41 */ - BMP_C(0x1f23b800) << (BMP_BIT - 32), /* 24 -- 24, 1f23b8 */ - BMP_C(0x20140000) << (BMP_BIT - 32), /* 25 -- 14, 0805 */ - BMP_C(0x20b40000) << (BMP_BIT - 32), /* 26 -- 14, 082d */ - BMP_C(0x21890000) << (BMP_BIT - 32), /* 27 -- 16, 2189 */ - BMP_C(0x21cf0200) << (BMP_BIT - 32), /* 28 -- 24, 21cf02 */ - BMP_C(0x25000000) << (BMP_BIT - 32), /* 29 -- 8, 25 */ - BMP_C(0x26b10000) << (BMP_BIT - 32), /* 30 -- 16, 26b1 */ - BMP_C(0x27d00000) << (BMP_BIT - 32), /* 31 -- 13, 04fa */ - BMP_C(0x28000000) << (BMP_BIT - 32), /* 32 -- 5, 05 */ - BMP_C(0x29b10000) << (BMP_BIT - 32), /* 33 -- 16, 29b1 */ - BMP_C(0x30000000) << (BMP_BIT - 32), /* 34 -- 4, 3 */ - BMP_C(0x3010bf7f) << (BMP_BIT - 32), /* 35 -- 32,3010bf7f */ - BMP_C(0x31000000) << (BMP_BIT - 32), /* 36 -- 8, 31 */ - BMP_C(0x31c30000) << (BMP_BIT - 32), /* 37 -- 16, 31c3 */ - BMP_C(0x34000000) << (BMP_BIT - 32), /* 38 -- 6, 0d */ - BMP_C(0x340bc6d9) << (BMP_BIT - 32), /* 39 -- 32,340bc6d9 */ - BMP_C(0x38000000) << (BMP_BIT - 32), /* 40 -- 5, 07 */ - BMP_C(0x39000000) << (BMP_BIT - 32), /* 41 -- 8, 39 */ - BMP_C(0x3d650000) << (BMP_BIT - 32), /* 42 -- 16, 3d65 */ - BMP_C(0x44c20000) << (BMP_BIT - 32), /* 43 -- 16, 44c2 */ - BMP_C(0x48000000) << (BMP_BIT - 32), /* 44 -- 5, 09 */ - BMP_C(0x4acc0000) << (BMP_BIT - 32), /* 45 -- 15, 2566 */ - BMP_C(0x4b370000) << (BMP_BIT - 32), /* 46 -- 16, 4b37 */ - BMP_C(0x4c060000) << (BMP_BIT - 32), /* 47 -- 16, 4c06 */ - BMP_C(0x55000000) << (BMP_BIT - 32), /* 48 -- 8, 55 */ - BMP_C(0x5d6dcb00) << (BMP_BIT - 32), /* 49 -- 24, 5d6dcb */ - BMP_C(0x60000000) << (BMP_BIT - 32), /* 50 -- 3, 3 */ - BMP_C(0x63d00000) << (BMP_BIT - 32), /* 51 -- 16, 63d0 */ - BMP_C(0x64000000) << (BMP_BIT - 32), /* 52 -- 6, 19 */ - BMP_C(0x66400000) << (BMP_BIT - 32), /* 53 -- 10, 199 */ - BMP_C(0x6f910000) << (BMP_BIT - 32), /* 54 -- 16, 6f91 */ - BMP_C(0x70000000) << (BMP_BIT - 32), /* 55 -- 4, 7 */ - BMP_C(0x70a00000) << (BMP_BIT - 32), /* 56 -- 11, 385 */ - BMP_C(0x765e7680) << (BMP_BIT - 32), /* 57 -- 32,765e7680 */ - BMP_C(0x7979bd00) << (BMP_BIT - 32), /* 58 -- 24, 7979bd */ - BMP_C(0x7e000000) << (BMP_BIT - 32), /* 59 -- 8, 7e */ - BMP_C(0x80050000) << (BMP_BIT - 32), /* 60 -- 16, 8005 */ - BMP_C(0x800d0000) << (BMP_BIT - 32), /* 61 -- 16, 800d */ - BMP_C(0x80f00000) << (BMP_BIT - 32), /* 62 -- 12, 80f */ - BMP_C(0x814141ab) << (BMP_BIT - 32), /* 63 -- 32,814141ab */ - BMP_C(0x864cfb00) << (BMP_BIT - 32), /* 64 -- 24, 864cfb */ - BMP_C(0x87315576) << (BMP_BIT - 32), /* 65 -- 32,87315576 */ - BMP_C(0x89ec0000) << (BMP_BIT - 32), /* 66 -- 16, 89ec */ - BMP_C(0x8b320000) << (BMP_BIT - 32), /* 67 -- 15, 4599 */ - BMP_C(0x8bb70000) << (BMP_BIT - 32), /* 68 -- 16, 8bb7 */ - BMP_C(0x8cc00000) << (BMP_BIT - 32), /* 69 -- 10, 233 */ - BMP_C(0x906e0000) << (BMP_BIT - 32), /* 70 -- 16, 906e */ - BMP_C(0x97000000) << (BMP_BIT - 32), /* 71 -- 8, 97 */ - BMP_C(0x98000000) << (BMP_BIT - 32), /* 72 -- 6, 26 */ - BMP_C(0x9b000000) << (BMP_BIT - 32), /* 73 -- 8, 9b */ - BMP_C(0x9c000000) << (BMP_BIT - 32), /* 74 -- 6, 27 */ - BMP_C(0x9e000000) << (BMP_BIT - 32), /* 75 -- 7, 4f */ - BMP_C(0x9ecf0000) << (BMP_BIT - 32), /* 76 -- 16, 9ecf */ - BMP_C(0xa0970000) << (BMP_BIT - 32), /* 77 -- 16, a097 */ - BMP_C(0xa1000000) << (BMP_BIT - 32), /* 78 -- 8, a1 */ - BMP_C(0xa6000000) << (BMP_BIT - 32), /* 79 -- 7, 53 */ - BMP_C(0xa8000000) << (BMP_BIT - 32), /* 80 -- 5, 15 */ - BMP_C(0xa833982b) << (BMP_BIT - 32), /* 81 -- 32,a833982b */ - BMP_C(0xabcdef00) << (BMP_BIT - 32), /* 82 -- 24, abcdef */ - BMP_C(0xb2aa0000) << (BMP_BIT - 32), /* 83 -- 16, b2aa */ - BMP_C(0xb4600000) << (BMP_BIT - 32), /* 84 -- 11, 5a3 */ - BMP_C(0xb4c80000) << (BMP_BIT - 32), /* 85 -- 16, b4c8 */ - BMP_C(0xb704ce00) << (BMP_BIT - 32), /* 86 -- 24, b704ce */ - BMP_C(0xbb3d0000) << (BMP_BIT - 32), /* 87 -- 16, bb3d */ - BMP_C(0xbc000000) << (BMP_BIT - 32), /* 88 -- 8, bc */ - BMP_C(0xbd0be338) << (BMP_BIT - 32), /* 89 -- 32,bd0be338 */ - BMP_C(0xbf050000) << (BMP_BIT - 32), /* 90 -- 16, bf05 */ - BMP_C(0xc0000000) << (BMP_BIT - 32), /* 91 -- 3, 6 */ - BMP_C(0xc2b70000) << (BMP_BIT - 32), /* 92 -- 16, c2b7 */ - BMP_C(0xc6c60000) << (BMP_BIT - 32), /* 93 -- 16, c6c6 */ - BMP_C(0xc8000000) << (BMP_BIT - 32), /* 94 -- 5, 19 */ - BMP_C(0xc8670000) << (BMP_BIT - 32), /* 95 -- 16, c867 */ - BMP_C(0xcbf43926) << (BMP_BIT - 32), /* 96 -- 32,cbf43926 */ - BMP_C(0xd0000000) << (BMP_BIT - 32), /* 97 -- 8, d0 */ - BMP_C(0xd02a0000) << (BMP_BIT - 32), /* 98 -- 15, 6815 */ - BMP_C(0xd0db0000) << (BMP_BIT - 32), /* 99 -- 16, d0db */ - BMP_C(0xd4d00000) << (BMP_BIT - 32), /* 100 -- 12, d4d */ - BMP_C(0xd5000000) << (BMP_BIT - 32), /* 101 -- 8, d5 */ - BMP_C(0xd64e0000) << (BMP_BIT - 32), /* 102 -- 16, d64e */ - BMP_C(0xda000000) << (BMP_BIT - 32), /* 103 -- 8, da */ - BMP_C(0xdaf00000) << (BMP_BIT - 32), /* 104 -- 12, daf */ - BMP_C(0xe0000000) << (BMP_BIT - 32), /* 105 -- 3, 7 */ - BMP_C(0xe3069283) << (BMP_BIT - 32), /* 106 -- 32,e3069283 */ - BMP_C(0xe5cc0000) << (BMP_BIT - 32), /* 107 -- 16, e5cc */ - BMP_C(0xe7a80000) << (BMP_BIT - 32), /* 108 -- 13, 1cf5 */ - BMP_C(0xea000000) << (BMP_BIT - 32), /* 109 -- 7, 75 */ - BMP_C(0xea820000) << (BMP_BIT - 32), /* 110 -- 16, ea82 */ - BMP_C(0xec000000) << (BMP_BIT - 32), /* 111 -- 6, 3b */ - BMP_C(0xf1300000) << (BMP_BIT - 32), /* 112 -- 12, f13 */ - BMP_C(0xf4000000) << (BMP_BIT - 32), /* 113 -- 8, f4 */ - BMP_C(0xf5b00000) << (BMP_BIT - 32), /* 114 -- 12, f5b */ - BMP_C(0xf6400000) << (BMP_BIT - 32), /* 115 -- 10, 3d9 */ - BMP_C(0xf8000000) << (BMP_BIT - 32), /* 116 -- 5, 1f */ - BMP_C(0xfc000000) << (BMP_BIT - 32), /* 117 -- 6, 3f */ - BMP_C(0xfc891918) << (BMP_BIT - 32), /* 118 -- 32,fc891918 */ - BMP_C(0xfd000000) << (BMP_BIT - 32), /* 119 -- 8, fd */ - BMP_C(0xfe000000) << (BMP_BIT - 32), /* 120 -- 7, 7f */ - BMP_C(0xfedcba00) << (BMP_BIT - 32), /* 121 -- 24, fedcba */ - BMP_C(0xfee80000) << (BMP_BIT - 32), /* 122 -- 16, fee8 */ - BMP_C(0xff000000) << (BMP_BIT - 32), /* 123 -- 8, ff */ - BMP_C(0xffc00000) << (BMP_BIT - 32), /* 124 -- 10, 3ff */ - BMP_C(0xfff00000) << (BMP_BIT - 32), /* 125 -- 12, fff */ - BMP_C(0xffff0000) << (BMP_BIT - 32), /* 126 -- 16, ffff */ - BMP_C(0xfffffffe) << (BMP_BIT - 32), /* 127 -- 31,7fffffff */ - BMP_C(0xffffffff) << (BMP_BIT - 32), /* 128 -- 32,ffffffff */ -}; - -/* Table of preset CRC models. - * Sorted by left-justified polynomial for bsearch(). - */ -static const struct mpreset models[] = { - {32UL, b32+ 1, 0, P_BE, 0, b32+ 89, "XFER" }, /* 0 */ - {40UL, b40, 0, P_BE, b40a, b40b, "CRC-40/GSM" }, /* 1 */ - {32UL, b32+ 8, 0, P_BE, b32+128, b32+ 57, "CRC-32/POSIX" }, /* 2 */ - {32UL, b32+ 8, b32+128, P_BE, 0, b32+ 7, "CRC-32/MPEG-2" }, /* 3 */ - {32UL, b32+ 8, b32+128, P_BE, b32+128, b32+118, "CRC-32/BZIP2" }, /* 4 */ - {32UL, b32+ 8, b32+128, P_LE, 0, b32+ 39, "JAMCRC" }, /* 5 */ - {32UL, b32+ 8, b32+128, P_LE, b32+128, b32+ 96, "CRC-32" }, /* 6 */ - {16UL, b32+ 9, 0, P_BE, 0, b32+ 5, "CRC-16/DECT-X" }, /* 7 */ - {16UL, b32+ 9, 0, P_BE, b32+ 2, b32+ 4, "CRC-16/DECT-R" }, /* 8 */ - { 8UL, b32+ 10, 0, P_BE, 0, b32+113, "CRC-8" }, /* 9 */ - { 8UL, b32+ 10, 0, P_BE, b32+ 48, b32+ 78, "CRC-8/ITU" }, /* 10 */ - { 8UL, b32+ 10, b32+123, P_LE, 0, b32+ 97, "CRC-8/ROHC" }, /* 11 */ - {31UL, b32+ 11, b32+127, P_BE, b32+127, b32+ 19, "CRC-31/PHILIPS" }, /* 12 */ - { 6UL, b32+ 13, 0, P_LE, 0, b32+ 18, "CRC-6/ITU" }, /* 13 */ - {82UL, b82, 0, P_LE, 0, b82a, "CRC-82/DARC" }, /* 14 */ - {16UL, b32+ 15, 0, P_BE, 0, b32+ 37, "XMODEM" }, /* 15 */ - {16UL, b32+ 15, 0, P_LE, 0, b32+ 27, "KERMIT" }, /* 16 */ - {16UL, b32+ 15, b32+ 22, P_BE, 0, b32+107, "CRC-16/AUG-CCITT" }, /* 17 */ - {16UL, b32+ 15, b32+ 66, P_LE, 0, b32+ 30, "CRC-16/TMS37157" }, /* 18 */ - {16UL, b32+ 15, b32+ 83, P_LE, 0, b32+ 51, "CRC-16/RIELLO" }, /* 19 */ - {16UL, b32+ 15, b32+ 93, P_LE, 0, b32+ 90, "CRC-A" }, /* 20 */ - {16UL, b32+ 15, b32+126, P_BE, 0, b32+ 33, "CRC-16/CCITT-FALSE"}, /* 21 */ - {16UL, b32+ 15, b32+126, P_BE, b32+126, b32+102, "CRC-16/GENIBUS" }, /* 22 */ - {16UL, b32+ 15, b32+126, P_LE, 0, b32+ 54, "CRC-16/MCRF4XX" }, /* 23 */ - {16UL, b32+ 15, b32+126, P_LE, b32+126, b32+ 70, "X-25" }, /* 24 */ - { 7UL, b32+ 16, 0, P_BE, 0, b32+109, "CRC-7" }, /* 25 */ - { 6UL, b32+ 20, b32+117, P_BE, 0, b32+111, "CRC-6/CDMA2000-B" }, /* 26 */ - { 8UL, b32+ 21, b32+119, P_BE, 0, b32+ 59, "CRC-8/I-CODE" }, /* 27 */ - { 8UL, b32+ 21, b32+123, P_LE, 0, b32+ 71, "CRC-8/EBU" }, /* 28 */ - {32UL, b32+ 23, b32+128, P_LE, b32+128, b32+106, "CRC-32C" }, /* 29 */ - {14UL, b32+ 25, 0, P_LE, 0, b32+ 26, "CRC-14/DARC" }, /* 30 */ - { 5UL, b32+ 32, b32+116, P_LE, b32+116, b32+ 94, "CRC-5/USB" }, /* 31 */ - { 4UL, b32+ 34, 0, P_LE, 0, b32+ 55, "CRC-4/ITU" }, /* 32 */ - { 8UL, b32+ 36, 0, P_LE, 0, b32+ 78, "CRC-8/MAXIM" }, /* 33 */ - { 8UL, b32+ 41, 0, P_LE, 0, b32+ 17, "CRC-8/DARC" }, /* 34 */ - {16UL, b32+ 42, 0, P_BE, b32+126, b32+ 92, "CRC-16/EN-13757" }, /* 35 */ - {16UL, b32+ 42, 0, P_LE, b32+126, b32+110, "CRC-16/DNP" }, /* 36 */ - {64UL, b64, 0, P_BE, 0, b64a, "CRC-64" }, /* 37 */ - {64UL, b64, b64b, P_BE, b64b, b64c, "CRC-64/WE" }, /* 38 */ - {64UL, b64, b64b, P_LE, b64b, b64d, "CRC-64/XZ" }, /* 39 */ - { 5UL, b32+ 44, b32+ 44, P_BE, 0, b32+ 0, "CRC-5/EPC" }, /* 40 */ - {24UL, b32+ 49, b32+ 82, P_BE, 0, b32+ 24, "CRC-24/FLEXRAY-B" }, /* 41 */ - {24UL, b32+ 49, b32+121, P_BE, 0, b32+ 58, "CRC-24/FLEXRAY-A" }, /* 42 */ - { 3UL, b32+ 50, b32+105, P_LE, 0, b32+ 91, "CRC-3/ROHC" }, /* 43 */ - { 6UL, b32+ 52, 0, P_LE, 0, b32+ 72, "CRC-6/DARC" }, /* 44 */ - {11UL, b32+ 56, b32+ 6, P_BE, 0, b32+ 84, "CRC-11" }, /* 45 */ - {16UL, b32+ 60, 0, P_BE, 0, b32+122, "CRC-16/BUYPASS" }, /* 46 */ - {16UL, b32+ 60, 0, P_LE, 0, b32+ 87, "ARC" }, /* 47 */ - {16UL, b32+ 60, 0, P_LE, b32+126, b32+ 43, "CRC-16/MAXIM" }, /* 48 */ - {16UL, b32+ 60, b32+ 61, P_BE, 0, b32+ 76, "CRC-16/DDS-110" }, /* 49 */ - {16UL, b32+ 60, b32+126, P_LE, 0, b32+ 46, "MODBUS" }, /* 50 */ - {16UL, b32+ 60, b32+126, P_LE, b32+126, b32+ 85, "CRC-16/USB" }, /* 51 */ - {12UL, b32+ 62, 0, P_BE, 0, b32+114, "CRC-12/DECT" }, /* 52 */ - {12UL, b32+ 62, 0, P_BELE, 0, b32+104, "CRC-12/3GPP" }, /* 53 */ - {32UL, b32+ 63, 0, P_BE, 0, b32+ 35, "CRC-32Q" }, /* 54 */ - {24UL, b32+ 64, b32+ 86, P_BE, 0, b32+ 28, "CRC-24" }, /* 55 */ - {15UL, b32+ 67, 0, P_BE, 0, b32+ 12, "CRC-15" }, /* 56 */ - {16UL, b32+ 68, 0, P_BE, 0, b32+ 99, "CRC-16/T10-DIF" }, /* 57 */ - {10UL, b32+ 69, 0, P_BE, 0, b32+ 53, "CRC-10" }, /* 58 */ - { 8UL, b32+ 73, 0, P_LE, 0, b32+ 29, "CRC-8/WCDMA" }, /* 59 */ - { 8UL, b32+ 73, b32+123, P_BE, 0, b32+103, "CRC-8/CDMA2000" }, /* 60 */ - { 6UL, b32+ 74, b32+117, P_BE, 0, b32+ 38, "CRC-6/CDMA2000-A" }, /* 61 */ - { 7UL, b32+ 75, b32+120, P_LE, 0, b32+ 79, "CRC-7/ROHC" }, /* 62 */ - {16UL, b32+ 77, 0, P_BE, 0, b32+ 14, "CRC-16/TELEDISK" }, /* 63 */ - { 5UL, b32+ 80, 0, P_LE, 0, b32+ 40, "CRC-5/ITU" }, /* 64 */ - {32UL, b32+ 81, b32+128, P_LE, b32+128, b32+ 65, "CRC-32D" }, /* 65 */ - {16UL, b32+ 95, b32+126, P_BE, 0, b32+ 47, "CRC-16/CDMA2000" }, /* 66 */ - {15UL, b32+ 98, 0, P_BE, b32+ 3, b32+ 45, "CRC-15/MPT1327" }, /* 67 */ - { 8UL, b32+101, 0, P_BE, 0, b32+ 88, "CRC-8/DVB-S2" }, /* 68 */ - {13UL, b32+108, 0, P_BE, 0, b32+ 31, "CRC-13/BBC" }, /* 69 */ - {12UL, b32+112, b32+125, P_BE, 0, b32+100, "CRC-12/CDMA2000" }, /* 70 */ - {10UL, b32+115, b32+124, P_BE, 0, b32+ 69, "CRC-10/CDMA2000" }, /* 71 */ -}; -# define NPRESETS 72 - -/* List of names with pointers to models, pre-sorted for use with bsearch() */ -static const struct malias aliases[] = { - {"ARC", models+47, 1}, /* 0 */ - {"B-CRC-32", models+ 4, 0}, /* 1 */ - {"CKSUM", models+ 2, 0}, /* 2 */ - {"CRC-10", models+58, 1}, /* 3 */ - {"CRC-10/CDMA2000", models+71, 1}, /* 4 */ - {"CRC-11", models+45, 1}, /* 5 */ - {"CRC-12/3GPP", models+53, 1}, /* 6 */ - {"CRC-12/CDMA2000", models+70, 1}, /* 7 */ - {"CRC-12/DECT", models+52, 1}, /* 8 */ - {"CRC-13/BBC", models+69, 1}, /* 9 */ - {"CRC-14/DARC", models+30, 1}, /* 10 */ - {"CRC-15", models+56, 1}, /* 11 */ - {"CRC-15/MPT1327", models+67, 1}, /* 12 */ - {"CRC-16", models+47, 0}, /* 13 */ - {"CRC-16/ACORN", models+15, 0}, /* 14 */ - {"CRC-16/ARC", models+47, 0}, /* 15 */ - {"CRC-16/AUG-CCITT", models+17, 1}, /* 16 */ - {"CRC-16/BUYPASS", models+46, 1}, /* 17 */ - {"CRC-16/CCITT", models+16, 0}, /* 18 */ - {"CRC-16/CCITT-FALSE", models+21, 1}, /* 19 */ - {"CRC-16/CCITT-TRUE", models+16, 0}, /* 20 */ - {"CRC-16/CDMA2000", models+66, 1}, /* 21 */ - {"CRC-16/DARC", models+22, 0}, /* 22 */ - {"CRC-16/DDS-110", models+49, 1}, /* 23 */ - {"CRC-16/DECT-R", models+ 8, 1}, /* 24 */ - {"CRC-16/DECT-X", models+ 7, 1}, /* 25 */ - {"CRC-16/DNP", models+36, 1}, /* 26 */ - {"CRC-16/EN-13757", models+35, 1}, /* 27 */ - {"CRC-16/EPC", models+22, 0}, /* 28 */ - {"CRC-16/GENIBUS", models+22, 1}, /* 29 */ - {"CRC-16/I-CODE", models+22, 0}, /* 30 */ - {"CRC-16/IBM-SDLC", models+24, 0}, /* 31 */ - {"CRC-16/ISO-HDLC", models+24, 0}, /* 32 */ - {"CRC-16/LHA", models+47, 0}, /* 33 */ - {"CRC-16/MAXIM", models+48, 1}, /* 34 */ - {"CRC-16/MCRF4XX", models+23, 1}, /* 35 */ - {"CRC-16/RIELLO", models+19, 1}, /* 36 */ - {"CRC-16/SPI-FUJITSU", models+17, 0}, /* 37 */ - {"CRC-16/T10-DIF", models+57, 1}, /* 38 */ - {"CRC-16/TELEDISK", models+63, 1}, /* 39 */ - {"CRC-16/TMS37157", models+18, 1}, /* 40 */ - {"CRC-16/USB", models+51, 1}, /* 41 */ - {"CRC-16/VERIFONE", models+46, 0}, /* 42 */ - {"CRC-24", models+55, 1}, /* 43 */ - {"CRC-24/FLEXRAY-A", models+42, 1}, /* 44 */ - {"CRC-24/FLEXRAY-B", models+41, 1}, /* 45 */ - {"CRC-24/OPENPGP", models+55, 0}, /* 46 */ - {"CRC-3/ROHC", models+43, 1}, /* 47 */ - {"CRC-31/PHILIPS", models+12, 1}, /* 48 */ - {"CRC-32", models+ 6, 1}, /* 49 */ - {"CRC-32/AAL5", models+ 4, 0}, /* 50 */ - {"CRC-32/ADCCP", models+ 6, 0}, /* 51 */ - {"CRC-32/BZIP2", models+ 4, 1}, /* 52 */ - {"CRC-32/CASTAGNOLI", models+29, 0}, /* 53 */ - {"CRC-32/DECT-B", models+ 4, 0}, /* 54 */ - {"CRC-32/ISCSI", models+29, 0}, /* 55 */ - {"CRC-32/MPEG-2", models+ 3, 1}, /* 56 */ - {"CRC-32/POSIX", models+ 2, 1}, /* 57 */ - {"CRC-32C", models+29, 1}, /* 58 */ - {"CRC-32D", models+65, 1}, /* 59 */ - {"CRC-32Q", models+54, 1}, /* 60 */ - {"CRC-4/ITU", models+32, 1}, /* 61 */ - {"CRC-40/GSM", models+ 1, 1}, /* 62 */ - {"CRC-5/EPC", models+40, 1}, /* 63 */ - {"CRC-5/ITU", models+64, 1}, /* 64 */ - {"CRC-5/USB", models+31, 1}, /* 65 */ - {"CRC-6/CDMA2000-A", models+61, 1}, /* 66 */ - {"CRC-6/CDMA2000-B", models+26, 1}, /* 67 */ - {"CRC-6/DARC", models+44, 1}, /* 68 */ - {"CRC-6/ITU", models+13, 1}, /* 69 */ - {"CRC-64", models+37, 1}, /* 70 */ - {"CRC-64/WE", models+38, 1}, /* 71 */ - {"CRC-64/XZ", models+39, 1}, /* 72 */ - {"CRC-7", models+25, 1}, /* 73 */ - {"CRC-7/ROHC", models+62, 1}, /* 74 */ - {"CRC-8", models+ 9, 1}, /* 75 */ - {"CRC-8/AES", models+28, 0}, /* 76 */ - {"CRC-8/CDMA2000", models+60, 1}, /* 77 */ - {"CRC-8/DARC", models+34, 1}, /* 78 */ - {"CRC-8/DVB-S2", models+68, 1}, /* 79 */ - {"CRC-8/EBU", models+28, 1}, /* 80 */ - {"CRC-8/I-CODE", models+27, 1}, /* 81 */ - {"CRC-8/ITU", models+10, 1}, /* 82 */ - {"CRC-8/MAXIM", models+33, 1}, /* 83 */ - {"CRC-8/ROHC", models+11, 1}, /* 84 */ - {"CRC-8/WCDMA", models+59, 1}, /* 85 */ - {"CRC-82/DARC", models+14, 1}, /* 86 */ - {"CRC-A", models+20, 1}, /* 87 */ - {"CRC-B", models+24, 0}, /* 88 */ - {"CRC-CCITT", models+16, 0}, /* 89 */ - {"CRC-IBM", models+47, 0}, /* 90 */ - {"DOW-CRC", models+33, 0}, /* 91 */ - {"JAMCRC", models+ 5, 1}, /* 92 */ - {"KERMIT", models+16, 1}, /* 93 */ - {"MODBUS", models+50, 1}, /* 94 */ - {"PKZIP", models+ 6, 0}, /* 95 */ - {"R-CRC-16", models+ 8, 0}, /* 96 */ - {"X-25", models+24, 1}, /* 97 */ - {"X-CRC-12", models+52, 0}, /* 98 */ - {"X-CRC-16", models+ 7, 0}, /* 99 */ - {"XFER", models+ 0, 1}, /* 100 */ - {"XMODEM", models+15, 1}, /* 101 */ - {"ZMODEM", models+15, 0}, /* 102 */ - {NULL, NULL, 0}, /* terminating entry */ -}; -# define NALIASES 103 - -# endif /* BMP_BIT */ -#else /* PRESETS */ - -static const struct mpreset models[] = { - { 0UL, 0, 0, P_BE, 0, 0, NULL }, /* terminating entry */ -}; -# define NPRESETS 0 - -static const struct malias aliases[] = { - {NULL, NULL, 0}, /* terminating entry */ -}; -# define NALIASES 0 - -#endif /* PRESETS */ - -static const poly_t pzero = PZERO; - -static int acmp(const struct malias *, const struct malias *); -static void munpack(model_t *, const struct mpreset *); - -/* copy a parameter of a preset into a model */ -#define MUNPACK(parm) \ - praloc(&dest->parm, (src->b##parm ? src->width : 0UL)); \ - for(iter=0UL, idx=0UL; iter < dest->parm.length; iter += BMP_BIT, ++idx)\ - dest->parm.bitmap[idx] = src->b##parm[idx]; - -/* Definitions */ - -void -mcpy(model_t *dest, const model_t *src) { - /* Copies the parameters of src to dest. - * dest must be an initialised model. - */ - if(!dest || !src) return; - pcpy(&dest->spoly, src->spoly); - pcpy(&dest->init, src->init); - pcpy(&dest->xorout, src->xorout); - pcpy(&dest->check, src->check); - dest->flags = src->flags; - /* link to the name as it is static */ - dest->name = src->name; -} - -void -mfree(model_t *model) { - /* Frees the parameters of model. */ - if(!model) return; - pfree(&model->spoly); - pfree(&model->init); - pfree(&model->xorout); - pfree(&model->check); - /* not name as it is static */ - /* not model either, it might point to an array! */ -} - -int -mcmp(const model_t *a, const model_t *b) { - /* Compares a and b for identical effect, i.e. disregarding - * trailing zeroes in parameter polys. - * Intended for bsearch() to find a matching model in models[]. - */ - int result; - if(!a || !b) return(!b - !a); - if((result = psncmp(&a->spoly, &b->spoly))) return(result); - if((result = psncmp(&a->init, &b->init))) return(result); - if((a->flags & P_REFIN) && (~b->flags & P_REFIN)) return(1); - if((~a->flags & P_REFIN) && (b->flags & P_REFIN)) return(-1); - if((a->flags & P_REFOUT) && (~b->flags & P_REFOUT)) return(1); - if((~a->flags & P_REFOUT) && (b->flags & P_REFOUT)) return(-1); - return(psncmp(&a->xorout, &b->xorout)); -} - -int -mbynam(model_t *dest, const char *key) { - /* Sets parameters in dest according to the model named by key. - */ - struct malias akey = {NULL, NULL, 0}, *aptr; - char *ukey, *uptr; - - if(!aliases->name) - return(-1); - if(!(ukey = malloc((size_t) 1 + strlen(key)))) - uerror("cannot allocate memory for comparison string"); - akey.name = uptr = ukey; - do - *uptr++ = toupper((unsigned char)*key); - while(*key++); - - aptr = bsearch(&akey, aliases, NALIASES, sizeof(struct malias), (int (*)(const void *, const void *)) &acmp); - free(ukey); - - if(aptr == NULL) - return(0); - munpack(dest, aptr->model); - return(1); -} - -void -mbynum(model_t *dest, int num) { - /* Sets parameters in dest according to the model indexed by num. */ - if(num > NPRESETS) - num = NPRESETS; - munpack(dest, models+num); -} - -int -mcount(void) { - /* Returns the number of preset models. */ - return(NPRESETS); -} - -char * -mnames(void) { - /* Returns a malloc()-ed string of the names of all preset - * models, separated by newlines and terminated by NULL. - * Aliases are not listed. - */ - size_t size = 0; - char *string, *sptr; - const struct malias *aptr = aliases; - - while(aptr->name) { - if(aptr->isprimry) - size += strlen(aptr->name) + 1; - ++aptr; - } - if(!size) return(NULL); - if((string = malloc(size))) { - aptr = aliases; - sptr = string; - while(aptr->name) { - if(aptr->isprimry) { - strcpy(sptr, aptr->name); - sptr += strlen(aptr->name); - *sptr++ = '\n'; - } - ++aptr; - } - *--sptr = '\0'; - } else - uerror("cannot allocate memory for list of models"); - - return(string); -} - -char * -mtostr(const model_t *model) { - /* Returns a malloc()-ed string containing a Williams model - * record representing the input model. - * mcanon() should be called on the argument before printing. - */ - size_t size; - char *polystr, *initstr, *xorotstr, *checkstr, strbuf[512], *string = NULL; - - if(!model) return(NULL); - polystr = ptostr(model->spoly, P_RTJUST, 4); - initstr = ptostr(model->init, P_RTJUST, 4); - xorotstr = ptostr(model->xorout, P_RTJUST, 4); - checkstr = ptostr(model->check, P_RTJUST, 4); - - sprintf(strbuf, "%lu", plen(model->spoly)); - size = - 70 - + (model->name && *model->name ? 2 + strlen(model->name) : 6) - + strlen(strbuf) - + (polystr && *polystr ? strlen(polystr) : 6) - + (initstr && *initstr ? strlen(initstr) : 6) - + (model->flags & P_REFIN ? 4 : 5) - + (model->flags & P_REFOUT ? 4 : 5) - + (xorotstr && *xorotstr ? strlen(xorotstr) : 6) - + (checkstr && *checkstr ? strlen(checkstr) : 6); - if((string = malloc(size))) { - sprintf(strbuf, "\"%s\"", model->name); - sprintf(string, - "width=%lu " - "poly=0x%s " - "init=0x%s " - "refin=%s " - "refout=%s " - "xorout=0x%s " - "check=0x%s " - "name=%s", - plen(model->spoly), - polystr && *polystr ? polystr : "(none)", - initstr && *initstr ? initstr : "(none)", - (model->flags & P_REFIN) ? "true" : "false", - (model->flags & P_REFOUT) ? "true" : "false", - xorotstr && *xorotstr ? xorotstr : "(none)", - checkstr && *checkstr ? checkstr : "(none)", - (model->name && *model->name) ? strbuf : "(none)"); - } - free(polystr); - free(initstr); - free(xorotstr); - free(checkstr); - if(!string) - uerror("cannot allocate memory for model description"); - return(string); -} - -void -mmatch(model_t *model, int flags) { - /* searches models[] for a model matching the argument, and links a name if found - * if flags & M_OVERWR, copies the found model onto the argument. */ - model_t *mptr; - if(!model) return; - - mptr = bsearch(model, models, NPRESETS, sizeof(model_t), (int (*)(const void *, const void *)) &mcmp); - if(mptr) { - model->name = mptr->name; - if(flags & M_OVERWR) - mcpy(model, mptr); - } -} - -void -mcanon(model_t *model) { - /* canonicalise a model */ - unsigned long dlen; - - if(!model) return; - - /* extending on the right here. This preserves the functionality - * of a presumed working model. - */ - psnorm(&model->spoly); - dlen = plen(model->spoly); - praloc(&model->init, dlen); - praloc(&model->xorout, dlen); - - if(!plen(model->check)) - mcheck(model); -} - -void -mcheck(model_t *model) { - /* calculate a check for the model */ - poly_t checkstr, check; - - /* generate the check string with the correct bit order */ - checkstr = strtop("313233343536373839", model->flags, 8); - check = pcrc(checkstr, model->spoly, model->init, pzero, model->flags); - if(model->flags & P_REFOUT) - prev(&check); - psum(&check, model->xorout, 0UL); - model->check = check; - pfree(&checkstr); -} - -void -mrev(model_t *model) { - /* reverse the model to calculate reversed CRCs */ - /* Here we invert RefIn and RefOut so that the user need only - * reverse the order of characters in the arguments, not the - * characters themselves. If RefOut=True, the mirror image of - * Init seen through RefOut becomes XorOut, and as RefOut - * becomes false, the XorOut value moved to Init stays upright. - * If RefOut=False, Init transfers to XorOut without reflection - * but the new Init must be reflected to present the same image, - * as RefOut becomes true. - */ - poly_t temp; - - prcp(&model->spoly); - if(model->flags & P_REFOUT) - prev(&model->init); - else - prev(&model->xorout); - - /* exchange init and xorout */ - temp = model->init; - model->init = model->xorout; - model->xorout = temp; - - /* invert refin and refout */ - model->flags ^= P_REFIN | P_REFOUT; - - mnovel(model); -} - -void -mnovel(model_t *model) { - /* remove name and check string from modified model */ - model->name = NULL; - pfree(&model->check); -} - -static int -acmp(const struct malias *a, const struct malias *b) { - /* compares two aliases, for use in bsearch */ - if(!a || !b) return(!b - !a); - if(!a->name || !b->name) return(!b->name - !a->name); - return(strcmp(a->name, b->name)); -} - -static void -munpack(model_t *dest, const struct mpreset *src) { - /* Copies the parameters of src to dest. - * dest must be an initialised model. - */ - unsigned long iter, idx; - if(!dest || !src) return; - MUNPACK(spoly); - MUNPACK(init); - MUNPACK(xorout); - MUNPACK(check); - dest->flags = src->flags; - /* link to the name as it is static */ - dest->name = src->name; -} diff --git a/client/reveng/poly.c b/client/reveng/poly.c deleted file mode 100644 index e4a8e8f9..00000000 --- a/client/reveng/poly.c +++ /dev/null @@ -1,1196 +0,0 @@ -/* poly.c - * Greg Cook, 9/Apr/2015 - */ - -/* CRC RevEng, an arbitrary-precision CRC calculator and algorithm finder - * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015 Gregory Cook - * - * This file is part of CRC RevEng. - * - * CRC RevEng 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. - * - * CRC RevEng 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. - * - * You should have received a copy of the GNU General Public License - * along with CRC RevEng. If not, see . - */ - -/* 2015-04-03: added direct mode to strtop() - * 2014-01-11: added LOFS(), RNDUP() - * 2013-09-16: SIZE(), IDX(), OFS() macros bitshift if BMP_POF2 - * 2013-02-07: conditional non-2^n fix, pmpar() return mask constant type - * 2013-01-17: fixed pfirst(), plast() for non-2^n BMP_BIT - * 2012-07-16: added pident() - * 2012-05-23: added pmpar() - * 2012-03-03: internal lookup tables stored better - * 2012-03-02: fixed full-width masking in filtop() - * 2011-09-06: added prevch() - * 2011-08-27: fixed zero test in piter() - * 2011-01-17: fixed ANSI C warnings, uses bmp_t type - * 2011-01-15: palloc() and praloc() gracefully handle lengths slightly - * less than ULONG_MAX - * 2011-01-15: strtop() error on invalid argument. pkchop() special case - * when argument all zeroes - * 2011-01-14: added pkchop() - * 2011-01-04: fixed bogus final length calculation in wide pcrc() - * 2011-01-02: faster, more robust prcp() - * 2011-01-01: commented functions, full const declarations, all-LUT rev() - * 2010-12-26: renamed CRC RevEng - * 2010-12-18: removed pmods(), finished pcrc(), added piter() - * 2010-12-17: roughed out pcrc(). difficult, etiam aberat musa heri :( - * 2010-12-15: added psnorm(), psncmp(); optimised pnorm(); fix to praloc() - * 2010-12-14: strtop() resets count between passes - * 2010-12-12: added pright() - * 2010-12-11: filtop won't read more than length bits - * 2010-12-10: finished filtop. 26 public functions - * 2010-12-05: finished strtop, pxsubs; unit tests - * 2010-12-02: project started - */ - -/* Note: WELL-FORMED poly_t objects have a valid bitmap pointer pointing - * to a malloc()-ed array of at least as many bits as stated in its - * length field. Any poly_t with a length of 0 is also a WELL-FORMED - * poly_t (whatever value the bitmap pointer has.) - * All poly_t objects passed to and from functions must be WELL-FORMED - * unless otherwise stated. - * - * CLEAN (or CANONICAL) poly_t objects are WELL-FORMED objects in which - * all spare bits in the bitmap word containing the last bit are zero. - * (Any excess allocated words will not be accessed.) - * - * SEMI-NORMALISED poly_t objects are CLEAN objects in which the last - * bit, at position (length - 1), is one. - * - * NORMALISED poly_t objects are SEMI-NORMALISED objects in which the - * first bit is one. - * - * pfree() should be called on every poly_t object (including - * those returned by functions) after its last use. - * As always, free() should be called on every malloc()-ed string after - * its last use. - */ - -#include -#include -#include -#include "reveng.h" - -static bmp_t getwrd(const poly_t poly, unsigned long iter); -static bmp_t rev(bmp_t accu, int bits); -static void prhex(char **spp, bmp_t bits, int flags, int bperhx); - -static const poly_t pzero = PZERO; - -/* word number (0..m-1) of var'th bit (0..n-1) */ -#if BMP_POF2 >= 5 -# define IDX(var) ((var) >> BMP_POF2) -#else -# define IDX(var) ((var) / BMP_BIT) -#endif - -/* size of polynomial with var bits */ -#if BMP_POF2 >= 5 -# define SIZE(var) ((BMP_BIT - 1UL + (var)) >> BMP_POF2) -#else -# define SIZE(var) ((BMP_BIT - 1UL + (var)) / BMP_BIT) -#endif - -/* polynomial length rounded up to BMP_BIT */ -#ifdef BMP_POF2 -# define RNDUP(var) (~(BMP_BIT - 1UL) & (BMP_BIT - 1UL + (var))) -#else -# define RNDUP(var) ((BMP_BIT - (var) % BMP_BIT) % BMP_BIT + (var)) -#endif - -/* bit offset (0..BMP_BIT-1, 0 = LSB) of var'th bit (0..n-1) */ -#ifdef BMP_POF2 -# define OFS(var) ((int) ((BMP_BIT - 1UL) & ~(var))) -#else -# define OFS(var) ((int) (BMP_BIT - 1UL - (var) % BMP_BIT)) -#endif - -/* bit offset (0..BMP_BIT-1, 0 = MSB) of var'th bit (0..n-1) */ -#ifdef BMP_POF2 -# define LOFS(var) ((int) ((BMP_BIT - 1UL) & (var))) -#else -# define LOFS(var) ((int) ((var) % BMP_BIT)) -#endif - -poly_t -filtop(FILE *input, unsigned long length, int flags, int bperhx) { - /* reads binary data from input into a poly_t until EOF or until - * length bits are read. Characters are read until - * ceil(bperhx / CHAR_BIT) bits are collected; if P_LTLBYT is - * set in flags then the first character contains the LSB, - * otherwise the last one does. The least significant bperhx - * bits are taken, reflected (if P_REFIN) and appended to the - * result, then more characters are read. The maximum number of - * characters read is - * floor(length / bperhx) * ceil(bperhx / * CHAR_BIT). - * The returned poly_t is CLEAN. - */ - - bmp_t accu = BMP_C(0); - bmp_t mask = bperhx == BMP_BIT ? ~BMP_C(0) : (BMP_C(1) << bperhx) - BMP_C(1); - unsigned long iter = 0UL, idx; - int cmask = ~(~0U << CHAR_BIT), c; - int count = 0, ofs; - poly_t poly = PZERO; - if(bperhx == 0) return(poly); - - length -= length % bperhx; - palloc(&poly, length); /* >= 0 */ - - while(iter < length && (c = fgetc(input)) != EOF) { - if(flags & P_LTLBYT) - accu |= (bmp_t) (c & cmask) << count; - else - accu = (accu << CHAR_BIT) | (bmp_t) (c & cmask); - count += CHAR_BIT; - if(count >= bperhx) { - /* the low bperhx bits of accu contain bits of the poly.*/ - iter += bperhx; - count = 0; - if(flags & P_REFIN) - accu = rev(accu, bperhx); - accu &= mask; - - /* iter >= bperhx > 0 */ - idx = IDX(iter - 1UL); - ofs = OFS(iter - 1UL); - poly.bitmap[idx] |= accu << ofs; - if(ofs + bperhx > BMP_BIT) { - poly.bitmap[idx-1] |= accu >> (BMP_BIT - ofs); - } - accu = BMP_C(0); /* only needed for P_LTLBYT */ - } - } - praloc(&poly, iter); - return(poly); -} - -poly_t -strtop(const char *string, int flags, int bperhx) { - /* Converts a hex or character string to a poly_t. - * Each character is converted to a hex nibble yielding 4 bits - * unless P_DIRECT, when each character yields CHAR_BIT bits. - * Nibbles and characters are accumulated left-to-right - * unless P_DIRECT && P_LTLBYT, when they are accumulated - * right-to-left without reflection. - * As soon as at least bperhx bits are accumulated, the - * rightmost bperhx bits are reflected (if P_REFIN) - * and appended to the poly. When !P_DIRECT: - * bperhx=8 reads hex nibbles in pairs - * bperhx=7 reads hex nibbles in pairs and discards - * b3 of first nibble - * bperhx=4 reads hex nibbles singly - * bperhx=3 reads octal - * bperhx=1 reads longhand binary - * in theory if !P_REFIN, bperhx can be any multiple of 4 - * with equal effect - * The returned poly_t is CLEAN. - */ - - /* make two passes, one to determine the poly size - * one to populate the bitmap - */ - unsigned long length = 1UL, idx; - bmp_t accu; - bmp_t mask = bperhx == BMP_BIT ? ~BMP_C(0) : (BMP_C(1) << bperhx) - BMP_C(1); - int pass, count, ofs; - int cmask = ~(~0U << CHAR_BIT), c; - const char *s; - - poly_t poly = PZERO; - if(bperhx > BMP_BIT || bperhx <= 0 || string == NULL || *string == '\0') - return(poly); - - for(pass=0; pass<2 && length > 0UL; ++pass) { - s = string; - length = 0UL; - count = 0; - accu = BMP_C(0); - while((c = *s++)) { - if(flags & P_DIRECT) { - if(flags & P_LTLBYT) - accu |= (bmp_t) (c & cmask) << count; - else - accu = (accu << CHAR_BIT) | (bmp_t) (c & cmask); - count += CHAR_BIT; - } else { - if(c == ' ' || c == '\t' || c == '\r' || c == '\n') continue; - accu <<= 4; - count += 4; - switch(c) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - accu |= (bmp_t) c - '0'; - break; - case 'A': - case 'a': - accu |= BMP_C(0xa); - break; - case 'B': - case 'b': - accu |= BMP_C(0xb); - break; - case 'C': - case 'c': - accu |= BMP_C(0xc); - break; - case 'D': - case 'd': - accu |= BMP_C(0xd); - break; - case 'E': - case 'e': - accu |= BMP_C(0xe); - break; - case 'F': - case 'f': - accu |= BMP_C(0xf); - break; - default: - uerror("invalid character in hexadecimal argument"); - } - } - - if(count >= bperhx) { - /* the low bperhx bits of accu contain bits of the poly. - * in pass 0, increment length by bperhx. - * in pass 1, put the low bits of accu into the bitmap. */ - length += bperhx; - count = 0; - if(pass == 1) { - if(flags & P_REFIN) - accu = rev(accu, bperhx); - accu &= mask; - - /* length >= bperhx > 0 */ - idx = IDX(length - 1); - ofs = OFS(length - 1); - poly.bitmap[idx] |= accu << ofs; - if(ofs + bperhx > BMP_BIT) - poly.bitmap[idx-1] |= accu >> (BMP_BIT - ofs); - accu = BMP_C(0); /* only needed for P_LTLBYT */ - } - } - } - if(pass == 0) palloc(&poly, length); - } - return(poly); -} - -char * -ptostr(const poly_t poly, int flags, int bperhx) { - /* Returns a malloc()-ed string containing a hexadecimal - * representation of poly. See phxsubs(). - */ - return(pxsubs(poly, flags, bperhx, 0UL, poly.length)); -} - -char * -pxsubs(const poly_t poly, int flags, int bperhx, unsigned long start, unsigned long end) { - /* Returns a malloc()-ed string containing a hexadecimal - * representation of a portion of poly, from bit offset start to - * (end - 1) inclusive. The output is grouped into words of - * bperhx bits each. If P_RTJUST then the first word is padded - * with zeroes at the MSB end to make a whole number of words, - * otherwise the last word is padded at the LSB end. After - * justification the bperhx bits of each word are reversed (if - * P_REFOUT) and printed as a hex sequence, with words - * optionally separated by spaces (P_SPACE). - * If end exceeds the length of poly then zero bits are appended - * to make up the difference, in which case poly must be CLEAN. - */ - char *string, *sptr; - unsigned long size, iter; - bmp_t accu; - bmp_t mask = bperhx == BMP_BIT ? ~BMP_C(0) : (BMP_C(1) << bperhx) - BMP_C(1); - int cperhx, part; - - if(bperhx <= 0 || bperhx > BMP_BIT) return(NULL); - - if(start > poly.length) start = poly.length; - if(end > poly.length) end = poly.length; - if(end < start) end = start; - - cperhx = (bperhx + 3) >> 2; - if(flags & P_SPACE) ++cperhx; - - size = (end - start + bperhx - 1UL) / bperhx; - size *= cperhx; - if(!size || ~flags & P_SPACE) ++size; /* for trailing null */ - - if(!(sptr = string = (char *) malloc(size))) - uerror("cannot allocate memory for string"); - - size = end - start; - part = (int) size % bperhx; - if(part && flags & P_RTJUST) { - iter = start + part; - accu = getwrd(poly, iter - 1UL) & ((BMP_C(1) << part) - BMP_C(1)); - if(flags & P_REFOUT) - /* best to reverse over bperhx rather than part, I think - * e.g. converting a 7-bit poly to 8-bit little-endian hex - */ - accu = rev(accu, bperhx); - prhex(&sptr, accu, flags, bperhx); - if(flags & P_SPACE && size > iter) *sptr++ = ' '; - } else { - iter = start; - } - - while((iter+=bperhx) <= end) { - accu = getwrd(poly, iter - 1UL) & mask; - if(flags & P_REFOUT) - accu = rev(accu, bperhx); - prhex(&sptr, accu, flags, bperhx); - if(flags & P_SPACE && size > iter) *sptr++ = ' '; - } - - if(part && ~flags & P_RTJUST) { - accu = getwrd(poly, end - 1UL); - if(flags & P_REFOUT) - accu = rev(accu, part); - else - accu = accu << (bperhx - part) & mask; - prhex(&sptr, accu, flags, bperhx); - } - *sptr = '\0'; - return(string); -} - -poly_t -pclone(const poly_t poly) { - /* Returns a freestanding copy of poly. Does not clean poly or - * the result. - */ - poly_t clone = PZERO; - - pcpy(&clone, poly); - return(clone); -} - -void -pcpy(poly_t *dest, const poly_t src) { - /* Assigns (copies) src into dest. Does not clean src or dest. - */ - unsigned long iter, idx; - - praloc(dest, src.length); - for(iter=0UL, idx=0UL; iter < src.length; iter += BMP_BIT, ++idx) - dest->bitmap[idx] = src.bitmap[idx]; -} - -void -pcanon(poly_t *poly) { - /* Converts poly into a CLEAN object by freeing unused bitmap words - * and clearing any bits in the last word beyond the last bit. - * The length field has absolute priority over the contents of the bitmap. - * Canonicalisation differs from normalisation in that leading and trailing - * zero terms are significant and preserved. - * poly may or may not be WELL-FORMED. - */ - praloc(poly, poly->length); -} - -void -pnorm(poly_t *poly) { - /* Converts poly into a NORMALISED object by removing leading - * and trailing zeroes, so that the polynomial starts and ends - * with significant terms. - * poly may or may not be WELL-FORMED. - */ - unsigned long first; - - /* call pcanon() here so pfirst() and plast() return the correct - * results - */ - pcanon(poly); - first = pfirst(*poly); - if(first) - pshift(poly, *poly, 0UL, first, plast(*poly), 0UL); - else - praloc(poly, plast(*poly)); -} - -void -psnorm(poly_t *poly) { - /* Converts poly into a SEMI-NORMALISED object by removing - * trailing zeroes, so that the polynomial ends with a - * significant term. - * poly may or may not be WELL-FORMED. - */ - - /* call pcanon() here so plast() returns the correct result */ - pcanon(poly); - praloc(poly, plast(*poly)); -} - -void -pchop(poly_t *poly) { - /* Normalise poly, then chop off the highest significant term - * (produces a SEMI-NORMALISED object). poly becomes a suitable - * divisor for pcrc(). - * poly may or may not be WELL-FORMED. - */ - - /* call pcanon() here so pfirst() and plast() return correct - * results - */ - pcanon(poly); - pshift(poly, *poly, 0UL, pfirst(*poly) + 1UL, plast(*poly), 0UL); -} - -void -pkchop(poly_t *poly) { - /* Convert poly from Koopman notation to chopped form (produces - * a SEMI-NORMALISED object). poly becomes a suitable divisor - * for pcrc(). - * poly may or may not be WELL-FORMED. - */ - unsigned long first; - - /* call pcanon() here so pfirst() returns the correct result */ - pcanon(poly); - first = pfirst(*poly); - if(first >= poly->length) { - pfree(poly); - return; - } - pshift(poly, *poly, 0UL, first + 1UL, poly->length, 1UL); - piter(poly); -} - -unsigned long -plen(const poly_t poly) { - /* Return length of polynomial. - * poly may or may not be WELL-FORMED. - */ - return(poly.length); -} - -int -pcmp(const poly_t *a, const poly_t *b) { - /* Compares poly_t objects for identical sizes and contents. - * a and b must be CLEAN. - * Defines a total order relation for sorting, etc. although - * mathematically, polynomials of equal degree are no greater or - * less than one another. - */ - unsigned long iter; - bmp_t *aptr, *bptr; - - if(!a || !b) return(!b - !a); - if(a->length < b->length) return(-1); - if(a->length > b->length) return(1); - aptr = a->bitmap; - bptr = b->bitmap; - for(iter=0UL; iter < a->length; iter += BMP_BIT) { - if(*aptr < *bptr) - return(-1); - if(*aptr++ > *bptr++) - return(1); - } - return(0); -} - -int -psncmp(const poly_t *a, const poly_t *b) { - /* Compares polys for identical effect, i.e. as though the - * shorter poly were padded with zeroes to the length of the - * longer. - * a and b must still be CLEAN, therefore psncmp() is *not* - * identical to pcmp() on semi-normalised polys as psnorm() - * clears the slack space. - */ - unsigned long length, iter, idx; - bmp_t aword, bword; - if(!a || !b) return(!b - !a); - length = (a->length > b->length) ? a->length : b->length; - for(iter = 0UL, idx = 0UL; iter < length; iter += BMP_BIT, ++idx) { - aword = (iter < a->length) ? a->bitmap[idx] : BMP_C(0); - bword = (iter < b->length) ? b->bitmap[idx] : BMP_C(0); - if(aword < bword) - return(-1); - if(aword > bword) - return(1); - } - return(0); -} - - -int -ptst(const poly_t poly) { - /* Tests whether a polynomial equals zero. Returns 0 if equal, - * a nonzero value otherwise. - * poly must be CLEAN. - */ - unsigned long iter; - bmp_t *bptr; - if(!poly.bitmap) return(0); - for(iter = 0UL, bptr = poly.bitmap; iter < poly.length; iter += BMP_BIT) - if(*bptr++) return(1); - return(0); -} - -unsigned long -pfirst(const poly_t poly) { - /* Returns the index of the first nonzero term in poly. If none - * is found, returns the length of poly. - * poly must be CLEAN. - */ - unsigned long idx = 0UL, size = SIZE(poly.length); - bmp_t accu = BMP_C(0); /* initialiser for Acorn C */ - unsigned int probe = BMP_SUB, ofs = 0; - - while(idx < size && !(accu = poly.bitmap[idx])) ++idx; - if(idx >= size) return(poly.length); - while(probe) { -#ifndef BMP_POF2 - while((ofs | probe) >= (unsigned int) BMP_BIT) probe >>= 1; -#endif - if(accu >> (ofs | probe)) ofs |= probe; - probe >>= 1; - } - - return(BMP_BIT - 1UL - ofs + idx * BMP_BIT); -} - -unsigned long -plast(const poly_t poly) { - /* Returns 1 plus the index of the last nonzero term in poly. - * If none is found, returns zero. - * poly must be CLEAN. - */ - unsigned long idx, size = SIZE(poly.length); - bmp_t accu; - unsigned int probe = BMP_SUB, ofs = 0; - - if(!poly.length) return(0UL); - idx = size - 1UL; - while(idx && !(accu = poly.bitmap[idx])) --idx; - if(!idx && !(accu = poly.bitmap[idx])) return(0UL); - /* now accu == poly.bitmap[idx] and contains last significant term */ - while(probe) { -#ifndef BMP_POF2 - while((ofs | probe) >= (unsigned int) BMP_BIT) probe >>= 1; -#endif - if(accu << (ofs | probe)) ofs |= probe; - probe >>= 1; - } - - return(idx * BMP_BIT + ofs + 1UL); -} - -poly_t -psubs(const poly_t src, unsigned long head, unsigned long start, unsigned long end, unsigned long tail) { - poly_t dest = PZERO; - pshift(&dest, src, head, start, end, tail); - return(dest); -} - -void -pright(poly_t *poly, unsigned long length) { - /* Trims or extends poly to length at the left edge, prepending - * zeroes if necessary. Analogous to praloc() except the - * rightmost terms of poly are preserved. - * On entry, poly may or may not be WELL-FORMED. - * On exit, poly is CLEAN. - */ - - if(length > poly->length) - pshift(poly, *poly, length - poly->length, 0UL, poly->length, 0UL); - else if(length < poly->length) - pshift(poly, *poly, 0UL, poly->length - length, poly->length, 0UL); - else - praloc(poly, poly->length); -} - -void -pshift(poly_t *dest, const poly_t src, unsigned long head, unsigned long start, unsigned long end, unsigned long tail) { - /* copies bits start to end-1 of src to dest, plus the number of leading and trailing zeroes given by head and tail. - * end may exceed the length of src in which case more zeroes are appended. - * dest may point to src, in which case the poly is edited in place. - * On exit, dest is CLEAN. - */ - - unsigned long length, fulllength, size, fullsize, iter, idx, datidx; - /* condition inputs; end, head and tail may be any value */ - if(end < start) end = start; - - length = end - start + head; - fulllength = length + tail; - if(fulllength > src.length) - praloc(dest, fulllength); - else - praloc(dest, src.length); - - /* number of words in new poly */ - size = SIZE(length); - fullsize = SIZE(fulllength); - /* array index of first word ending up with source material */ - datidx = IDX(head); - - if(head > start && end > start) { - /* shifting right, size > 0 */ - /* index of the source bit ending up in the LSB of the last word - * size * BMP_BIT >= length > head > 0 */ - iter = size * BMP_BIT - head - 1UL; - for(idx = size - 1UL; idx > datidx; iter -= BMP_BIT, --idx) - dest->bitmap[idx] = getwrd(src, iter); - dest->bitmap[idx] = getwrd(src, iter); - /* iter == size * BMP_BIT - head - 1 - BMP_BIT * (size - 1 - datidx) - * == BMP_BIT * (size - size + 1 + datidx) - head - 1 - * == BMP_BIT * (1 + head / BMP_BIT) - head - 1 - * == BMP_BIT + head - head % BMP_BIT - head - 1 - * == BMP_BIT - head % BMP_BIT - 1 - * >= 0 - */ - } else if(head <= start) { - /* shifting left or copying */ - /* index of the source bit ending up in the LSB of bitmap[idx] */ - iter = start - head + BMP_BIT - 1UL; - for(idx = datidx; idx < size; iter += BMP_BIT, ++idx) - dest->bitmap[idx] = getwrd(src, iter); - } - - /* clear head */ - for(idx = 0UL; idx < datidx; ++idx) - dest->bitmap[idx] = BMP_C(0); - if(size) - dest->bitmap[datidx] &= ~BMP_C(0) >> LOFS(head); - - /* clear tail */ - if(LOFS(length)) - dest->bitmap[size - 1UL] &= ~(~BMP_C(0) >> LOFS(length)); - for(idx = size; idx < fullsize; ++idx) - dest->bitmap[idx] = BMP_C(0); - - /* call praloc to shrink poly if required */ - if(dest->length > fulllength) - praloc(dest, fulllength); -} - -void -ppaste(poly_t *dest, const poly_t src, unsigned long skip, unsigned long seek, unsigned long end, unsigned long fulllength) { - /* pastes terms of src, starting from skip, to positions seek to end-1 of dest - * then sets length of dest to fulllength (>= end) - * to paste n terms of src, give end = seek + n - * to truncate dest at end of paste, set fulllength = end - * to avoid truncating, set fulllength = plen(*dest) - * dest may point to src, in which case the poly is edited in place. - * src must be CLEAN in the case that the end is overrun. - * On exit, dest is CLEAN. - */ - bmp_t mask; - unsigned long seekidx, endidx, iter; - int seekofs; - if(end < seek) end = seek; - if(fulllength < end) fulllength = end; - - /* expand dest if necessary. don't shrink as dest may be src */ - if(fulllength > dest->length) - praloc(dest, fulllength); - seekidx = IDX(seek); - endidx = IDX(end); - seekofs = OFS(seek); - /* index of the source bit ending up in the LSB of the first modified word */ - iter = skip + seekofs; - if(seekidx == endidx) { - /* paste affects one word (traps end = seek case) */ - mask = ((BMP_C(1) << seekofs) - (BMP_C(1) << OFS(end))) << 1; - dest->bitmap[seekidx] = (dest->bitmap[seekidx] & ~mask) | (getwrd(src, iter) & mask); - } else if(seek > skip) { - /* shifting right */ - /* index of the source bit ending up in the LSB of the last modified word */ - iter += (endidx - seekidx) * BMP_BIT; - mask = ~BMP_C(0) >> LOFS(end); - dest->bitmap[endidx] = (dest->bitmap[endidx] & mask) | (getwrd(src, iter) & ~mask); - for(iter -= BMP_BIT, --endidx; endidx > seekidx; iter -= BMP_BIT, --endidx) - dest->bitmap[endidx] = getwrd(src, iter); - mask = ~BMP_C(0) >> LOFS(seek); - dest->bitmap[endidx] = (dest->bitmap[endidx] & ~mask) | (getwrd(src, iter) & mask); - /* iter == skip + seekofs + (endidx - seekidx) * BMP_BIT - BMP_BIT * (endidx - seekidx) - * == skip + seekofs + BMP_BIT * (endidx - seekidx - endidx + seekidx) - * == skip + seekofs - * >= 0 - */ - } else { - /* shifting left or copying */ - mask = ~BMP_C(0) >> LOFS(seek); - dest->bitmap[seekidx] = (dest->bitmap[seekidx] & ~mask) | (getwrd(src, iter) & mask); - for(iter += BMP_BIT, ++seekidx; seekidx < endidx; iter += BMP_BIT, ++seekidx) - dest->bitmap[seekidx] = getwrd(src, iter); - mask = ~BMP_C(0) >> LOFS(end); - dest->bitmap[seekidx] = (dest->bitmap[seekidx] & mask) | (getwrd(src, iter) & ~mask); - } - /* shrink poly if required */ - if(dest->length > fulllength) - praloc(dest, fulllength); -} - -void -pdiff(poly_t *dest, const poly_t src, unsigned long ofs) { - /* Subtract src from dest (modulo 2) at offset ofs. - * In modulo 2 arithmetic, subtraction is equivalent to addition - * We include an alias for those who wish to retain the distinction - * src and dest must be CLEAN. - */ - psum(dest, src, ofs); -} - -void -psum(poly_t *dest, const poly_t src, unsigned long ofs) { - /* Adds src to dest (modulo 2) at offset ofs. - * When ofs == dest->length, catenates src on to dest. - * src and dest must be CLEAN. - */ - unsigned long fulllength, idx, iter, end; - - fulllength = ofs + src.length; - if(fulllength > dest->length) - praloc(dest, fulllength); - /* array index of first word in dest to be modified */ - idx = IDX(ofs); - /* index of bit in src to be added to LSB of dest->bitmap[idx] */ - iter = OFS(ofs); - /* stop value for iter */ - end = BMP_BIT - 1UL + src.length; - for(; iter < end; iter += BMP_BIT, ++idx) - dest->bitmap[idx] ^= getwrd(src, iter); -} - -void -prev(poly_t *poly) { - /* Reverse or reciprocate a polynomial. - * On exit, poly is CLEAN. - */ - unsigned long leftidx = 0UL, rightidx = SIZE(poly->length); - unsigned long ofs = LOFS(BMP_BIT - LOFS(poly->length)); - unsigned long fulllength = poly->length + ofs; - bmp_t accu; - - if(ofs) { - /* removable optimisation */ - if(poly->length < (unsigned long) BMP_BIT) { - *poly->bitmap = rev(*poly->bitmap >> ofs, (int) poly->length) << ofs; - return; - } - } - - /* claim remaining bits of last word (as we use public function pshift()) */ - poly->length = fulllength; - - /* reverse and swap words in the array, leaving it right-justified */ - while(leftidx < rightidx) { - /* rightidx > 0 */ - accu = rev(poly->bitmap[--rightidx], BMP_BIT); - poly->bitmap[rightidx] = rev(poly->bitmap[leftidx], BMP_BIT); - poly->bitmap[leftidx++] = accu; - } - /* shift polynomial to left edge if required */ - if(ofs) - pshift(poly, *poly, 0UL, ofs, fulllength, 0UL); -} - -void -prevch(poly_t *poly, int bperhx) { - /* Reverse each group of bperhx bits in a polynomial. - * Does not clean poly. - */ - unsigned long iter = 0, idx, ofs; - bmp_t mask, accu; - - if(bperhx < 2 || bperhx > BMP_BIT) - return; - if(poly->length % bperhx) - praloc(poly, bperhx - (poly->length % bperhx) + poly->length); - mask = ~BMP_C(0) >> (BMP_BIT - bperhx); - for(iter = (unsigned long) (bperhx - 1); iter < poly->length; iter += bperhx) { - accu = getwrd(*poly, iter) & mask; - accu ^= rev(accu, bperhx); - idx = IDX(iter); - ofs = OFS(iter); - poly->bitmap[idx] ^= accu << ofs; - if(ofs + bperhx > (unsigned int) BMP_BIT) - /* (BMP_BIT - 1UL - (iter) % BMP_BIT) + bperhx > BMP_BIT - * (-1UL - (iter) % BMP_BIT) + bperhx > 0 - * (- (iter % BMP_BIT)) + bperhx > 1 - * - (iter % BMP_BIT) > 1 - bperhx - * iter % BMP_BIT < bperhx - 1, iter >= bperhx - 1 - * iter >= BMP_BIT - * idx >= 1 - */ - poly->bitmap[idx-1] ^= accu >> (BMP_BIT - ofs); - } -} - -void -prcp(poly_t *poly) { - /* Reciprocate a chopped polynomial. Use prev() on whole - * polynomials. - * On exit, poly is SEMI-NORMALISED. - */ - unsigned long first; - - praloc(poly, RNDUP(poly->length)); - prev(poly); - first = pfirst(*poly); - if(first >= poly->length) { - pfree(poly); - return; - } - pshift(poly, *poly, 0UL, first + 1UL, poly->length, 1UL); - piter(poly); -} - -void -pinv(poly_t *poly) { - /* Invert a polynomial, i.e. add 1 (modulo 2) to the coefficient of each term - * on exit, poly is CLEAN. - */ - unsigned long idx, size = SIZE(poly->length); - - for(idx = 0UL; idxbitmap[idx] = ~poly->bitmap[idx]; - if(LOFS(poly->length)) - poly->bitmap[size - 1UL] &= ~(~BMP_C(0) >> LOFS(poly->length)); -} - -poly_t -pmod(const poly_t dividend, const poly_t divisor) { - /* Divide dividend by normalised divisor and return the remainder - * This function generates a temporary 'chopped' divisor for pcrc() - * If calling repeatedly with a constant divisor, produce a chopped copy - * with pchop() and call pcrc() directly for higher efficiency. - * dividend and divisor must be CLEAN. - */ - - /* perhaps generate an error if divisor is zero */ - poly_t subdivisor = psubs(divisor, 0UL, pfirst(divisor) + 1UL, plast(divisor), 0UL); - poly_t result = pcrc(dividend, subdivisor, pzero, pzero, 0); - pfree(&subdivisor); - return(result); -} - -poly_t -pcrc(const poly_t message, const poly_t divisor, const poly_t init, const poly_t xorout, int flags) { - /* Divide message by divisor and return the remainder. - * init is added to divisor, highest terms aligned, before - * division. - * xorout is added to the remainder, highest terms aligned. - * If P_MULXN is set in flags, message is multiplied by x^n - * (i.e. trailing zeroes equal to the CRC width are appended) - * before adding init and division. Set P_MULXN for most CRC - * calculations. - * All inputs must be CLEAN. - * If all inputs are CLEAN, the returned poly_t will be CLEAN. - */ - unsigned long max = 0UL, iter, ofs, resiter; - bmp_t probe, rem, dvsr, *rptr, *sptr; - const bmp_t *bptr, *eptr; - poly_t result = PZERO; - - if(flags & P_MULXN) - max = message.length; - else if(message.length > divisor.length) - max = message.length - divisor.length; - bptr=message.bitmap; - eptr=message.bitmap+SIZE(message.length); - probe=~(~BMP_C(0) >> 1); - if(divisor.length <= (unsigned long) BMP_BIT - && init.length <= (unsigned long) BMP_BIT) { - rem = init.length ? *init.bitmap : BMP_C(0); - dvsr = divisor.length ? *divisor.bitmap : BMP_C(0); - for(iter = 0UL, ofs = 0UL; iter < max; ++iter, --ofs) { - if(!ofs) { - ofs = BMP_BIT; - rem ^= *bptr++; - } - if(rem & probe) - rem = (rem << 1) ^ dvsr; - else - rem <<= 1; - } - if(bptr < eptr) - /* max < message.length */ - rem ^= *bptr >> OFS(BMP_BIT - 1UL + max); - if(init.length > max && init.length - max > divisor.length) { - palloc(&result, init.length - max); - *result.bitmap = rem; - } else if(divisor.length) { - palloc(&result, divisor.length); - *result.bitmap = rem; - } - } else { - /* allocate maximum size plus one word for shifted divisors and one word containing zero. - * This also ensures that result[1] exists - */ - palloc(&result, (init.length > divisor.length ? init.length : divisor.length) + (unsigned long) (BMP_BIT << 1)); - /*if there is content in init, there will be an extra word in result to clear it */ - psum(&result, init, 0UL); - if(max) - *result.bitmap ^= *bptr++; - for(iter = 0UL, ofs = 0UL; iter < max; ++iter, probe >>= 1) { - if(!probe) { - probe = ~(~BMP_C(0) >> 1); - ofs = 0UL; - sptr = rptr = result.bitmap; - ++sptr; - /* iter < max <= message.length, so bptr is valid - * shift result one word to the left, splicing in a message word - * and clearing the last active word - */ - *rptr++ = *sptr++ ^ *bptr++; - for(resiter = (unsigned long) (BMP_BIT << 1); resiter < result.length; resiter += BMP_BIT) - *rptr++ = *sptr++; - } - ++ofs; - if(*result.bitmap & probe) - psum(&result, divisor, ofs); - } - rptr = result.bitmap; - ++rptr; - while(bptr < eptr) - *rptr++ ^= *bptr++; - /* 0 <= ofs <= BMP_BIT, location of the first bit of the result */ - pshift(&result, result, 0UL, ofs, (init.length > max + divisor.length ? init.length - max - divisor.length : 0UL) + divisor.length + ofs, 0UL); - } - psum(&result, xorout, 0UL); - return(result); -} - -int -piter(poly_t *poly) { - /* Replace poly with the 'next' polynomial of equal length. - * Returns zero if the next polynomial is all zeroes, a nonzero - * value otherwise. - * Does not clean poly. - */ - bmp_t *bptr; - if(!poly->length) return(0); - - bptr = poly->bitmap + IDX(poly->length - 1UL); - *bptr += BMP_C(1) << OFS(poly->length - 1UL); - while(bptr != poly->bitmap && !*bptr) - ++(*--bptr); - return(*bptr != BMP_C(0)); -} - -void -palloc(poly_t *poly, unsigned long length) { - /* Replaces poly with a CLEAN object of the specified length, - * consisting of all zeroes. - * It is safe to call with length = 0, in which case the object - * is freed. - * poly may or may not be WELL-FORMED. - * On exit, poly is CLEAN. - */ - unsigned long size = SIZE(length); - - poly->length = 0UL; - free(poly->bitmap); - poly->bitmap = NULL; - if(!length) return; - if(!size) - size = IDX(length) + 1UL; - poly->bitmap = (bmp_t *) calloc(size, sizeof(bmp_t)); - if(poly->bitmap) { - poly->length = length; - } else - uerror("cannot allocate memory for poly"); -} - -void -pfree(poly_t *poly) { - /* Frees poly's bitmap storage and sets poly equal to the empty - * polynomial (PZERO). - * poly may or may not be WELL-FORMED. - * On exit, poly is CLEAN. - */ - - /* palloc(poly, 0UL); */ - - poly->length = 0UL; - free(poly->bitmap); - poly->bitmap = NULL; -} - -void -praloc(poly_t *poly, unsigned long length) { - /* Trims or extends poly to length at the right edge, appending - * zeroes if necessary. - * On entry, poly may or may not be WELL-FORMED. - * On exit, poly is CLEAN. - */ - unsigned long oldsize, size = SIZE(length); - if(!poly) return; - if(!length) { - poly->length = 0UL; - free(poly->bitmap); - poly->bitmap = NULL; - return; - } - if(!size) - size = IDX(length) + 1UL; - if(!poly->bitmap) - poly->length = 0UL; - oldsize = SIZE(poly->length); - if(oldsize != size) - /* reallocate if array pointer is null or array resized */ - poly->bitmap = (bmp_t *) realloc((void *)poly->bitmap, size * sizeof(bmp_t)); - if(poly->bitmap) { - if(poly->length < length) { - /* poly->length >= 0, length > 0, size > 0. - * poly expanded. clear old last word and all new words - */ - if(LOFS(poly->length)) - poly->bitmap[oldsize - 1UL] &= ~(~BMP_C(0) >> LOFS(poly->length)); - while(oldsize < size) - poly->bitmap[oldsize++] = BMP_C(0); - } else if(LOFS(length)) - /* poly->length >= length > 0. - * poly shrunk. clear new last word - */ - poly->bitmap[size - 1UL] &= ~(~BMP_C(0) >> LOFS(length)); - poly->length = length; - } else - uerror("cannot reallocate memory for poly"); -} - -int -pmpar(const poly_t poly, const poly_t mask) { - /* Return even parity of poly masked with mask. - * Poly and mask must be CLEAN. - */ - bmp_t res = BMP_C(0); - int i = BMP_SUB; - const bmp_t *pptr = poly.bitmap, *mptr = mask.bitmap; - const bmp_t *const pend = poly.bitmap + SIZE(poly.length); - const bmp_t *const mend = mask.bitmap + SIZE(mask.length); - - while(pptr < pend && mptr < mend) - res ^= *pptr++ & *mptr++; - do - res ^= res >> i; - while(i >>= 1); - - return((int) (res & BMP_C(1))); -} - -int -pident(const poly_t a, const poly_t b) { - /* Return nonzero if a and b have the same length - * and point to the same bitmap. - * a and b need not be CLEAN. - */ - return(a.length == b.length && a.bitmap == b.bitmap); -} - -/* Private functions */ - -static bmp_t -getwrd(const poly_t poly, unsigned long iter) { - /* Fetch unaligned word from poly where LSB of result is - * bit iter of the bitmap (counting from zero). If iter exceeds - * the length of poly then zeroes are appended as necessary. - * Factored from ptostr(). - * poly must be CLEAN. - */ - bmp_t accu = BMP_C(0); - unsigned long idx, size; - int ofs; - - idx = IDX(iter); - ofs = OFS(iter); - size = SIZE(poly.length); - - if(idx < size) - accu |= poly.bitmap[idx] >> ofs; - if(idx && idx <= size && ofs > 0) - accu |= poly.bitmap[idx - 1UL] << (BMP_BIT - ofs); - return(accu); -} - -static bmp_t -rev(bmp_t accu, int bits) { - /* Returns the bitmap word argument with the given number of - * least significant bits reversed and the rest cleared. - */ - static const unsigned char revtab[256] = { - 0x00,0x80,0x40,0xc0,0x20,0xa0,0x60,0xe0, - 0x10,0x90,0x50,0xd0,0x30,0xb0,0x70,0xf0, - 0x08,0x88,0x48,0xc8,0x28,0xa8,0x68,0xe8, - 0x18,0x98,0x58,0xd8,0x38,0xb8,0x78,0xf8, - 0x04,0x84,0x44,0xc4,0x24,0xa4,0x64,0xe4, - 0x14,0x94,0x54,0xd4,0x34,0xb4,0x74,0xf4, - 0x0c,0x8c,0x4c,0xcc,0x2c,0xac,0x6c,0xec, - 0x1c,0x9c,0x5c,0xdc,0x3c,0xbc,0x7c,0xfc, - 0x02,0x82,0x42,0xc2,0x22,0xa2,0x62,0xe2, - 0x12,0x92,0x52,0xd2,0x32,0xb2,0x72,0xf2, - 0x0a,0x8a,0x4a,0xca,0x2a,0xaa,0x6a,0xea, - 0x1a,0x9a,0x5a,0xda,0x3a,0xba,0x7a,0xfa, - 0x06,0x86,0x46,0xc6,0x26,0xa6,0x66,0xe6, - 0x16,0x96,0x56,0xd6,0x36,0xb6,0x76,0xf6, - 0x0e,0x8e,0x4e,0xce,0x2e,0xae,0x6e,0xee, - 0x1e,0x9e,0x5e,0xde,0x3e,0xbe,0x7e,0xfe, - 0x01,0x81,0x41,0xc1,0x21,0xa1,0x61,0xe1, - 0x11,0x91,0x51,0xd1,0x31,0xb1,0x71,0xf1, - 0x09,0x89,0x49,0xc9,0x29,0xa9,0x69,0xe9, - 0x19,0x99,0x59,0xd9,0x39,0xb9,0x79,0xf9, - 0x05,0x85,0x45,0xc5,0x25,0xa5,0x65,0xe5, - 0x15,0x95,0x55,0xd5,0x35,0xb5,0x75,0xf5, - 0x0d,0x8d,0x4d,0xcd,0x2d,0xad,0x6d,0xed, - 0x1d,0x9d,0x5d,0xdd,0x3d,0xbd,0x7d,0xfd, - 0x03,0x83,0x43,0xc3,0x23,0xa3,0x63,0xe3, - 0x13,0x93,0x53,0xd3,0x33,0xb3,0x73,0xf3, - 0x0b,0x8b,0x4b,0xcb,0x2b,0xab,0x6b,0xeb, - 0x1b,0x9b,0x5b,0xdb,0x3b,0xbb,0x7b,0xfb, - 0x07,0x87,0x47,0xc7,0x27,0xa7,0x67,0xe7, - 0x17,0x97,0x57,0xd7,0x37,0xb7,0x77,0xf7, - 0x0f,0x8f,0x4f,0xcf,0x2f,0xaf,0x6f,0xef, - 0x1f,0x9f,0x5f,0xdf,0x3f,0xbf,0x7f,0xff - }; - bmp_t result = BMP_C(0); - while(bits > 8) { - bits -= 8; - result = result << 8 | revtab[accu & 0xff]; - accu >>= 8; - } - result = result << bits | (bmp_t) (revtab[accu & 0xff] >> (8 - bits)); - return(result); -} - -static void -prhex(char **spp, bmp_t bits, int flags, int bperhx) { - /* Appends a hexadecimal string representing the bperhx least - * significant bits of bits to an external string. - * spp points to a character pointer that in turn points to the - * end of a hex string being built. prhex() advances this - * second pointer by the number of characters written. - * The unused MSBs of bits MUST be cleared. - * Set P_UPPER in flags to write A-F in uppercase. - */ - static const char hex[] = "0123456789abcdef0123456789ABCDEF"; - const int upper = (flags & P_UPPER ? 0x10 : 0); - while(bperhx > 0) { - bperhx -= ((bperhx + 3) & 3) + 1; - *(*spp)++ = hex[(bits >> bperhx & BMP_C(0xf)) | upper]; - } -} diff --git a/client/reveng/reveng.c b/client/reveng/reveng.c deleted file mode 100644 index dd50987c..00000000 --- a/client/reveng/reveng.c +++ /dev/null @@ -1,489 +0,0 @@ -/* reveng.c - * Greg Cook, 9/Apr/2015 - */ - -/* CRC RevEng, an arbitrary-precision CRC calculator and algorithm finder - * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015 Gregory Cook - * - * This file is part of CRC RevEng. - * - * CRC RevEng 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. - * - * CRC RevEng 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. - * - * You should have received a copy of the GNU General Public License - * along with CRC RevEng. If not, see . - */ - -/* 2013-09-16: calini(), calout() work on shortest argument - * 2013-06-11: added sequence number to uprog() calls - * 2013-02-08: added polynomial range search - * 2013-01-18: refactored model checking to pshres(); renamed chkres() - * 2012-05-24: efficiently build Init contribution string - * 2012-05-24: removed broken search for crossed-endian algorithms - * 2012-05-23: rewrote engini() after Ewing; removed modini() - * 2011-01-17: fixed ANSI C warnings - * 2011-01-08: fixed calini(), modini() caters for crossed-endian algos - * 2011-01-04: renamed functions, added calini(), factored pshres(); - * rewrote engini() and implemented quick Init search - * 2011-01-01: reveng() initialises terminating entry, addparms() - * initialises all fields - * 2010-12-26: renamed CRC RevEng. right results, rejects polys faster - * 2010-12-24: completed, first tests (unsuccessful) - * 2010-12-21: completed modulate(), partial sketch of reveng() - * 2010-12-19: started reveng - */ - -/* reveng() can in theory be modified to search for polynomials shorter - * than the full width as well, but this imposes a heavy time burden on - * the full width search, which is the primary use case, as well as - * complicating the search range function introduced in version 1.1.0. - * It is more effective to search for each shorter width directly. - */ - -#include - -#define FILE void -#include "reveng.h" - -static poly_t *modpol(const poly_t init, int rflags, int args, const poly_t *argpolys); -static void engini(int *resc, model_t **result, const poly_t divisor, int flags, int args, const poly_t *argpolys); -static void calout(int *resc, model_t **result, const poly_t divisor, const poly_t init, int flags, int args, const poly_t *argpolys); -static void calini(int *resc, model_t **result, const poly_t divisor, int flags, const poly_t xorout, int args, const poly_t *argpolys); -static void chkres(int *resc, model_t **result, const poly_t divisor, const poly_t init, int flags, const poly_t xorout, int args, const poly_t *argpolys); - -static const poly_t pzero = PZERO; - -model_t * -reveng(const model_t *guess, const poly_t qpoly, int rflags, int args, const poly_t *argpolys) { - /* Complete the parameters of a model by calculation or brute search. */ - poly_t *pworks, *wptr, rem, gpoly; - model_t *result = NULL, *rptr; - int resc = 0; - unsigned long spin = 0, seq = 0; - - if(~rflags & R_HAVEP) { - /* The poly is not known. - * Produce a list of differences between the arguments. - */ - pworks = modpol(guess->init, rflags, args, argpolys); - if(!pworks || !plen(*pworks)) { - free(pworks); - goto requit; - } - /* Initialise the guessed poly to the starting value. */ - gpoly = pclone(guess->spoly); - /* Clear the least significant term, to be set in the - * loop. qpoly does not need fixing as it is only - * compared with odd polys. - */ - if(plen(gpoly)) - pshift(&gpoly, gpoly, 0UL, 0UL, plen(gpoly) - 1UL, 1UL); - - while(piter(&gpoly) && (~rflags & R_HAVEQ || pcmp(&gpoly, &qpoly) < 0)) { - /* For each possible poly of this size, try - * dividing all the differences in the list. - */ - if(!(spin++ & R_SPMASK)) { - uprog(gpoly, guess->flags, seq++); - } - for(wptr = pworks; plen(*wptr); ++wptr) { - /* straight divide message by poly, don't multiply by x^n */ - rem = pcrc(*wptr, gpoly, pzero, pzero, 0); - if(ptst(rem)) { - pfree(&rem); - break; - } else - pfree(&rem); - } - /* If gpoly divides all the differences, it is a - * candidate. Search for an Init value for this - * poly or if Init is known, log the result. - */ - if(!plen(*wptr)) { - /* gpoly is a candidate poly */ - if(rflags & R_HAVEI && rflags & R_HAVEX) - chkres(&resc, &result, gpoly, guess->init, guess->flags, guess->xorout, args, argpolys); - else if(rflags & R_HAVEI) - calout(&resc, &result, gpoly, guess->init, guess->flags, args, argpolys); - else if(rflags & R_HAVEX) - calini(&resc, &result, gpoly, guess->flags, guess->xorout, args, argpolys); - else - engini(&resc, &result, gpoly, guess->flags, args, argpolys); - } - if(!piter(&gpoly)) - break; - } - /* Finished with gpoly and the differences list, free them. - */ - pfree(&gpoly); - for(wptr = pworks; plen(*wptr); ++wptr) - pfree(wptr); - free(pworks); - } - else if(rflags & R_HAVEI && rflags & R_HAVEX) - /* All parameters are known! Submit the result if we get here */ - chkres(&resc, &result, guess->spoly, guess->init, guess->flags, guess->xorout, args, argpolys); - else if(rflags & R_HAVEI) - /* Poly and Init are known, calculate XorOut */ - calout(&resc, &result, guess->spoly, guess->init, guess->flags, args, argpolys); - else if(rflags & R_HAVEX) - /* Poly and XorOut are known, calculate Init */ - calini(&resc, &result, guess->spoly, guess->flags, guess->xorout, args, argpolys); - else - /* Poly is known but not Init; search for Init. */ - engini(&resc, &result, guess->spoly, guess->flags, args, argpolys); - -requit: - if(!(result = realloc(result, ++resc * sizeof(model_t)))) - uerror("cannot reallocate result array"); - rptr = result + resc - 1; - rptr->spoly = pzero; - rptr->init = pzero; - rptr->flags = 0; - rptr->xorout = pzero; - rptr->check = pzero; - rptr->name = NULL; - - return(result); -} - -static poly_t * -modpol(const poly_t init, int rflags, int args, const poly_t *argpolys) { - /* Produce, in ascending length order, a list of differences - * between the arguments in the list by summing pairs of arguments. - * If R_HAVEI is not set in rflags, only pairs of equal length are - * summed. - * Otherwise, sums of right-aligned pairs are also returned, with - * the supplied init poly added to the leftmost terms of each - * poly of the pair. - */ - poly_t work, swap, *result, *rptr, *iptr; - const poly_t *aptr, *bptr, *eptr = argpolys + args; - unsigned long alen, blen; - - if(args < 2) return(NULL); - - if(!(result = malloc(((((args - 1) * args) >> 1) + 1) * sizeof(poly_t)))) - uerror("cannot allocate memory for codeword table"); - - rptr = result; - - for(aptr = argpolys; aptr < eptr; ++aptr) { - alen = plen(*aptr); - for(bptr = aptr + 1; bptr < eptr; ++bptr) { - blen = plen(*bptr); - if(alen == blen) { - work = pclone(*aptr); - psum(&work, *bptr, 0UL); - } else if(rflags & R_HAVEI && alen < blen) { - work = pclone(*bptr); - psum(&work, *aptr, blen - alen); - psum(&work, init, 0UL); - psum(&work, init, blen - alen); - } else if(rflags & R_HAVEI /* && alen > blen */) { - work = pclone(*aptr); - psum(&work, *bptr, alen - blen); - psum(&work, init, 0UL); - psum(&work, init, alen - blen); - } else - work = pzero; - - if(plen(work)) - pnorm(&work); - if((blen = plen(work))) { - /* insert work into result[] in ascending order of length */ - for(iptr = result; iptr < rptr; ++iptr) { - if(plen(work) < plen(*iptr)) { - swap = *iptr; - *iptr = work; - work = swap; - } - else if(plen(*iptr) == blen && !pcmp(&work, iptr)) { - pfree(&work); - work = *--rptr; - break; - } - } - *rptr++ = work; - } - } - } - *rptr = pzero; - return(result); -} - -static void -engini(int *resc, model_t **result, const poly_t divisor, int flags, int args, const poly_t *argpolys) { - /* Search for init values implied by the arguments. - * Method from: Ewing, Gregory C. (March 2010). - * "Reverse-Engineering a CRC Algorithm". Christchurch: - * University of Canterbury. - * - */ - poly_t apoly = PZERO, bpoly, pone = PZERO, *mat, *jptr; - const poly_t *aptr, *bptr, *iptr; - unsigned long alen, blen, dlen, ilen, i, j; - int cy; - - dlen = plen(divisor); - - /* Allocate the CRC matrix */ - if(!(mat = (poly_t *) malloc((dlen << 1) * sizeof(poly_t)))) - uerror("cannot allocate memory for CRC matrix"); - - /* Find arguments of the two shortest lengths */ - alen = blen = plen(*(aptr = bptr = iptr = argpolys)); - for(++iptr; iptr < argpolys + args; ++iptr) { - ilen = plen(*iptr); - if(ilen < alen) { - bptr = aptr; blen = alen; - aptr = iptr; alen = ilen; - } else if(ilen > alen && (aptr == bptr || ilen < blen)) { - bptr = iptr; blen = ilen; - } - } - if(aptr == bptr) { - /* if no arguments are suitable, calculate Init with an - * assumed XorOut of 0. Create a padded XorOut - */ - palloc(&apoly, dlen); - calini(resc, result, divisor, flags, apoly, args, argpolys); - pfree(&apoly); - free(mat); - return; - } - - /* Find the potential contribution of the bottom bit of Init */ - palloc(&pone, 1UL); - piter(&pone); - if(blen < (dlen << 1)) { - palloc(&apoly, dlen); /* >= 1 */ - psum(&apoly, pone, (dlen << 1) - 1UL - blen); /* >= 0 */ - psum(&apoly, pone, (dlen << 1) - 1UL - alen); /* >= 1 */ - } else { - palloc(&apoly, blen - dlen + 1UL); /* > dlen */ - psum(&apoly, pone, 0UL); - psum(&apoly, pone, blen - alen); /* >= 1 */ - } - if(plen(apoly) > dlen) { - mat[dlen] = pcrc(apoly, divisor, pzero, pzero, 0); - pfree(&apoly); - } else { - mat[dlen] = apoly; - } - - /* Find the actual contribution of Init */ - apoly = pcrc(*aptr, divisor, pzero, pzero, 0); - bpoly = pcrc(*bptr, divisor, pzero, apoly, 0); - - /* Populate the matrix */ - palloc(&apoly, 1UL); - for(jptr=mat; jptr j */ - j = pfirst(apoly); - } - if(j < dlen) - mat[j] = apoly; /* pident(mat[j], pzero) || pfirst(mat[j]) == j */ - else - pfree(&apoly); - } - palloc(&bpoly, dlen + 1UL); - psum(&bpoly, pone, dlen); - - /* Iterate through all solutions */ - do { - /* Solve the matrix by Gaussian elimination. - * The parity of the result, masked by each row, should be even. - */ - cy = 1; - apoly = pclone(bpoly); - jptr = mat + dlen; - for(i=0UL; ispoly = pclone(divisor); - rptr->init = pclone(init); - rptr->flags = flags; - rptr->xorout = pclone(xorout); - rptr->name = NULL; - - /* compute check value for this model */ - mcheck(rptr); - - /* callback to notify new model */ - ufound(rptr); -} diff --git a/client/reveng/reveng.h b/client/reveng/reveng.h deleted file mode 100644 index 48dcb31c..00000000 --- a/client/reveng/reveng.h +++ /dev/null @@ -1,214 +0,0 @@ -/* reveng.h - * Greg Cook, 9/Apr/2015 - */ - -/* CRC RevEng, an arbitrary-precision CRC calculator and algorithm finder - * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015 Gregory Cook - * - * This file is part of CRC RevEng. - * - * CRC RevEng 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. - * - * CRC RevEng 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. - * - * You should have received a copy of the GNU General Public License - * along with CRC RevEng. If not, see . - */ - -#ifndef REVENG_H -#define REVENG_H 1 - -/* Configuration options */ - -#include "config.h" - -#ifndef BMP_T -# error config.h: BMP_T must be defined as unsigned long or a longer unsigned type -#endif - -#ifndef BMP_C -# error config.h: BMP_C() must define a BMP_T constant -#endif - -#if !defined PRESETS && !defined BMPMACRO -# undef BMP_BIT -# undef BMP_SUB -#endif - -#undef BMP_POF2 - -#ifdef BMP_BIT -# ifndef BMP_SUB -# error config.h: BMP_SUB must be defined as the highest power of two that is strictly less than BMP_BIT -# elif BMP_BIT < 32 -# error config.h: BMP_BIT must be at least 32 -# elif BMP_SUB < 16 -# error config.h: BMP_SUB must be at least 16 -# elif (BMP_SUB >= BMP_BIT || BMP_SUB << 1 < BMP_BIT || BMP_SUB & (BMP_SUB - 1)) -# error config.h: BMP_SUB must be defined as the highest power of two that is strictly less than BMP_BIT -# else /* BMP_SUB */ -# define SETBMP() -# endif /* BMP_SUB */ -# if BMP_BIT == 32 -# define BMP_POF2 5 -# elif BMP_BIT == 64 -# define BMP_POF2 6 -# elif BMP_BIT == 128 -# define BMP_POF2 7 -# elif BMP_BIT == 256 -# define BMP_POF2 8 -# elif BMP_BIT == 512 -# define BMP_POF2 9 -# elif BMP_BIT == 1024 -# define BMP_POF2 10 -# elif BMP_BIT == 2048 -# define BMP_POF2 11 -# elif BMP_BIT == 4096 -# define BMP_POF2 12 -# elif BMP_BIT == 8192 -# define BMP_POF2 13 -# elif BMP_BIT == 16384 -# define BMP_POF2 14 -# elif BMP_BIT == 32768 -# define BMP_POF2 15 -# elif BMP_BIT == 65536 -# define BMP_POF2 16 -/* may extend list as required */ -# elif (BMP_BIT & (BMP_BIT - 1)) == 0 -# define BMP_POF2 1 -# endif -#else /* BMP_BIT */ -# define BMP_BIT bmpbit -# define BMP_SUB bmpsub -# define SETBMP() setbmp() -#endif /* BMP_BIT */ - -/* Global definitions */ - -/* CRC RevEng version string */ -#define VERSION "1.3.0" - -/* bmpbit.c */ -typedef BMP_T bmp_t; - -extern int bmpbit, bmpsub; -extern void setbmp(void); - -/* poly.c */ -#define P_REFIN 1 -#define P_REFOUT 2 -#define P_MULXN 4 -#define P_RTJUST 8 -#define P_UPPER 16 -#define P_SPACE 32 -#define P_LTLBYT 64 -#define P_DIRECT 128 - -/* default flags */ -#define P_BE (P_RTJUST | P_MULXN) -#define P_LE (P_REFIN | P_REFOUT | P_MULXN) -#define P_BELE (P_REFOUT | P_MULXN) -#define P_LEBE (P_REFIN | P_RTJUST | P_MULXN) - -/* A poly_t constant representing the polynomial 0. */ -#define PZERO {0UL, (bmp_t *) 0} - -typedef struct { - unsigned long length; /* number of significant bits */ - bmp_t *bitmap; /* bitmap, MSB first, */ - /* left-justified in each word */ -} poly_t; - -extern poly_t filtop(FILE *input, unsigned long length, int flags, int bperhx); -extern poly_t strtop(const char *string, int flags, int bperhx); -extern char *ptostr(const poly_t poly, int flags, int bperhx); -extern char *pxsubs(const poly_t poly, int flags, int bperhx, unsigned long start, unsigned long end); -extern poly_t pclone(const poly_t poly); -extern void pcpy(poly_t *dest, const poly_t src); -extern void pcanon(poly_t *poly); -extern void pnorm(poly_t *poly); -extern void psnorm(poly_t *poly); -extern void pchop(poly_t *poly); -extern void pkchop(poly_t *poly); -extern unsigned long plen(const poly_t poly); -extern int pcmp(const poly_t *a, const poly_t *b); -extern int psncmp(const poly_t *a, const poly_t *b); -extern int ptst(const poly_t poly); -extern unsigned long pfirst(const poly_t poly); -extern unsigned long plast(const poly_t poly); -extern poly_t psubs(const poly_t src, unsigned long head, unsigned long start, unsigned long end, unsigned long tail); -extern void pright(poly_t *poly, unsigned long length); -extern void pshift(poly_t *dest, const poly_t src, unsigned long head, unsigned long start, unsigned long end, unsigned long tail); -extern void ppaste(poly_t *dest, const poly_t src, unsigned long skip, unsigned long seek, unsigned long end, unsigned long fulllength); -extern void pdiff(poly_t *dest, const poly_t src, unsigned long ofs); -extern void psum(poly_t *dest, const poly_t src, unsigned long ofs); -extern void prev(poly_t *poly); -extern void prevch(poly_t *poly, int bperhx); -extern void prcp(poly_t *poly); -extern void pinv(poly_t *poly); -extern poly_t pmod(const poly_t dividend, const poly_t divisor); -extern poly_t pcrc(const poly_t message, const poly_t divisor, const poly_t init, const poly_t xorout, int flags); -extern int piter(poly_t *poly); -extern void palloc(poly_t *poly, unsigned long length); -extern void pfree(poly_t *poly); -extern void praloc(poly_t *poly, unsigned long length); -extern int pmpar(const poly_t poly, const poly_t mask); -extern int pident(const poly_t a, const poly_t b); - -/* model.c */ -#define M_OVERWR 256 - -typedef struct { - poly_t spoly; /* polynomial with highest-order term removed. length determines CRC width */ - poly_t init; /* initial register value. length == poly.length */ - int flags; /* P_REFIN and P_REFOUT indicate reflected input/output */ - poly_t xorout; /* final register XOR mask. length == poly.length */ - poly_t check; /* optional check value, the CRC of the UTF-8 string "123456789" */ - const char *name; /* optional canonical name of the model */ -} model_t; - -extern void mcpy(model_t *dest, const model_t *src); -extern void mfree(model_t *model); -extern int mcmp(const model_t *a, const model_t *b); -extern int mbynam(model_t *dest, const char *key); -extern void mbynum(model_t *dest, int num); -extern int mcount(void); -extern char *mnames(void); -extern char *mtostr(const model_t *model); -extern void mmatch(model_t *model, int flags); -extern void mcanon(model_t *model); -extern void mcheck(model_t *model); -extern void mrev(model_t *model); -extern void mnovel(model_t *model); - -/* reveng.c */ -#define R_HAVEP 512 -#define R_HAVEI 1024 -#define R_HAVERI 2048 -#define R_HAVERO 4096 -#define R_HAVEX 8192 -#define R_HAVEQ 16384 - -#define R_SPMASK 0x7FFFFFFUL - -extern model_t *reveng(const model_t *guess, const poly_t qpoly, int rflags, int args, const poly_t *argpolys); - -/* cli.c */ -#define C_INFILE 1 -#define C_FORCE 2 -#define C_RESULT 4 - -#define BUFFER 32768 - -extern int reveng_main(int argc, char *argv[]); -extern void ufound(const model_t *model); -extern void uerror(const char *msg); -extern void uprog(const poly_t gpoly, int flags, unsigned long seq); - -#endif /* REVENG_H */ diff --git a/client/scripting.c b/client/scripting.c index 3859fd48..0c761cb2 100644 --- a/client/scripting.c +++ b/client/scripting.c @@ -25,7 +25,7 @@ #include "../common/crc64.h" #include "../common/polarssl/sha1.h" #include "../common/polarssl/aes.h" -#include "cmdcrc.h" + /** * The following params expected: * UsbCommand c @@ -391,62 +391,6 @@ static int l_sha1(lua_State *L) return 1; } -static int l_reveng_models(lua_State *L){ - - char *models[80]; - int count = 0; - int in_width = luaL_checkinteger(L, 1); - - if( in_width > 89 ) return returnToLuaWithError(L,"Width cannot exceed 89, got %d", in_width); - - uint8_t width[80]; - width[0] = (uint8_t)in_width; - int ans = GetModels(models, &count, width); - if (!ans) return 0; - - lua_newtable(L); - - for (int i = 0; i < count; i++){ - lua_pushstring(L, (const char*)models[i]); - lua_rawseti(L,-2,i+1); - free(models[i]); - } - - return 1; -} - -//Called with 4 parameters. -// inModel ,string containing the crc model name: 'CRC-8' -// inHexStr ,string containing the hex representation of the data that will be used for CRC calculations. -// reverse ,int 0/1 (bool) if 1, calculate the reverse CRC -// endian ,char, 'B','b','L','l','t','r' describing if Big-Endian or Little-Endian should be used in different combinations. -// -// outputs: string with hex representation of the CRC result -static int l_reveng_RunModel(lua_State *L){ - //-c || -v - //inModel = valid model name string - CRC-8 - //inHexStr = input hex string to calculate crc on - //reverse = reverse calc option if true - //endian = {0 = calc default endian input and output, b = big endian input and output, B = big endian output, r = right justified - // l = little endian input and output, L = little endian output only, t = left justified} - //result = calculated crc hex string - char result[50]; - - const char *inModel = luaL_checkstring(L, 1); - const char *inHexStr = luaL_checkstring(L, 2); - bool reverse = lua_toboolean(L, 3); - const char endian = luaL_checkstring(L, 4)[0]; - - //PrintAndLog("mod: %s, hex: %s, rev %d", inModel, inHexStr, reverse); - //int RunModel(char *inModel, char *inHexStr, bool reverse, char endian, char *result) - int ans = RunModel( (char *)inModel, (char *)inHexStr, reverse, endian, result); - if (!ans) - return returnToLuaWithError(L,"Reveng failed"); - - lua_pushstring(L, (const char*)result); - return 1; -} - /** * @brief Sets the lua path to include "./lualibs/?.lua", in order for a script to be * able to do "require('foobar')" if foobar.lua is within lualibs folder. @@ -493,8 +437,6 @@ int set_pm3_libraries(lua_State *L) {"crc16", l_crc16}, {"crc64", l_crc64}, {"sha1", l_sha1}, - {"reveng_models", l_reveng_models}, - {"reveng_runmodel", l_reveng_RunModel}, {NULL, NULL} }; diff --git a/client/scripts/e.lua b/client/scripts/e.lua deleted file mode 100644 index a20b8e47..00000000 --- a/client/scripts/e.lua +++ /dev/null @@ -1,72 +0,0 @@ -local getopt = require('getopt') -local utils = require('utils') - -example = "script calculates many different checksums (CRC) over the provided hex input" -author = "Iceman" -desc = -[[ -This script calculates many checksums (CRC) over the provided hex input. - -Arguments: - -b data in hex - -w bitwidth of the CRC family of algorithm. defaults to all known CRC presets. -Examples : - script run e -b 010203040506070809 - script run e -b 010203040506070809 -w 16 -]] - ---- --- A debug printout-function -function dbg(args) - if DEBUG then - print("###", args) - end -end ---- --- This is only meant to be used when errors occur -function oops(err) - print("ERROR: ",err) - return nil,err -end ---- --- Usage help -function help() - print(desc) - print("Example usage") - print(example) -end ---- --- The main entry point -function main(args) - - local data - local width = 0 - - -- Read the parameters - for o, a in getopt.getopt(args, 'hb:w:') do - if o == "h" then return help() end - if o == "b" then data = a end - if o == "w" then width = a end - end - - data = data or '01020304' - - print( string.rep('-',60) ) - print('Bit width of CRC | '..width) - print('Bytes | '..data) - print('') - print( ('%-20s| %-16s| %s'):format('Model','CRC', 'CRC reverse')) - print( string.rep('-',60) ) - local lists = core.reveng_models(width) - for _,i in pairs(lists) do - local a1 = core.reveng_runmodel(i, data, false, '0') - local a2 = core.reveng_runmodel(i, data, true, '0') - local a3 = core.reveng_runmodel(i, data, false, 'b') - local a4 = core.reveng_runmodel(i, data, false, 'B') - local a5 = core.reveng_runmodel(i, data, false, 'l') - local a6 = core.reveng_runmodel(i, data, false, 'L') - print( ('%-20s| %-16s| %-16s| %-16s| %-16s| %-16s| %-16s'):format(i, a1:upper(), a2:upper(),a3:upper(),a4:upper(),a5:upper(),a6:upper() ) ) - end -end - -main(args) \ No newline at end of file From e98389b355020a7baa9a82aef200a2a25cc78f47 Mon Sep 17 00:00:00 2001 From: Arnie97 Date: Thu, 25 Jan 2018 13:43:01 +0800 Subject: [PATCH 040/127] Fix typo in lua scripts: 1443a -> 14443a. --- client/lualibs/read14a.lua | 40 +++++++++++++++---------------- client/scripts/14araw.lua | 2 +- client/scripts/didump.lua | 2 +- client/scripts/formatMifare.lua | 2 +- client/scripts/mfkeys.lua | 2 +- client/scripts/mifare_autopwn.lua | 2 +- client/scripts/tnp3clone.lua | 2 +- client/scripts/tnp3dump.lua | 2 +- 8 files changed, 27 insertions(+), 27 deletions(-) diff --git a/client/lualibs/read14a.lua b/client/lualibs/read14a.lua index ec227b17..60fc0e68 100644 --- a/client/lualibs/read14a.lua +++ b/client/lualibs/read14a.lua @@ -2,7 +2,7 @@ This is a library to read 14443a tags. It can be used something like this local reader = require('read14a') - result, err = reader.read1443a() + result, err = reader.read14443a() if not result then print(err) return @@ -26,7 +26,7 @@ local ISO14A_COMMAND = { ISO14A_NO_RATS = 0x200 } -local ISO14443a_TYPES = {} +local ISO14443a_TYPES = {} ISO14443a_TYPES[0x00] = "NXP MIFARE Ultralight | Ultralight C" ISO14443a_TYPES[0x01] = "NXP MIFARE TNP3xxx Activision Game Appliance" ISO14443a_TYPES[0x04] = "NXP MIFARE (various !DESFire !DESFire EV1)" @@ -43,14 +43,14 @@ ISO14443a_TYPES[0x88] = "Infineon MIFARE CLASSIC 1K" ISO14443a_TYPES[0x98] = "Gemplus MPCOS" -local function tostring_1443a(sak) +local function tostring_14443a(sak) return ISO14443a_TYPES[sak] or ("Unknown (SAK=%x)"):format(sak) end -local function parse1443a(data) +local function parse14443a(data) --[[ - Based on this struct : + Based on this struct : typedef struct { byte_t uid[10]; @@ -66,14 +66,14 @@ local function parse1443a(data) local count,uid,uidlen, atqa, sak, ats_len, ats= bin.unpack('H10CH2CC',data) uid = uid:sub(1,2*uidlen) --print("uid, atqa, sak: ",uid, atqa, sak) - --print("TYPE: ", tostring_1443a(sak)) - return { uid = uid, atqa = atqa, sak = sak, name = tostring_1443a(sak)} + --print("TYPE: ", tostring_14443a(sak)) + return { uid = uid, atqa = atqa, sak = sak, name = tostring_14443a(sak)} end --- Sends a USBpacket to the device -- @param command - the usb packet to send --- @param ignoreresponse - if set to true, we don't read the device answer packet --- which is usually recipe for fail. If not sent, the host will wait 2s for a +-- @param ignoreresponse - if set to true, we don't read the device answer packet +-- which is usually recipe for fail. If not sent, the host will wait 2s for a -- response of type CMD_ACK -- @return packet,nil if successfull -- nil, errormessage if unsuccessfull @@ -99,7 +99,7 @@ end local function read14443a(dont_disconnect, no_rats) local command, result, info, err, data - command = Command:new{cmd = cmds.CMD_READER_ISO_14443a, + command = Command:new{cmd = cmds.CMD_READER_ISO_14443a, arg1 = ISO14A_COMMAND.ISO14A_CONNECT} if dont_disconnect then command.arg1 = command.arg1 + ISO14A_COMMAND.ISO14A_NO_DISCONNECT @@ -110,24 +110,24 @@ local function read14443a(dont_disconnect, no_rats) local result,err = sendToDevice(command) if result then local count,cmd,arg0,arg1,arg2 = bin.unpack('LLLL',result) - if arg0 == 0 then + if arg0 == 0 then return nil, "iso14443a card select failed" end data = string.sub(result,count) - info, err = parse1443a(data) + info, err = parse14443a(data) else err ="No response from card" end - if err then - print(err) + if err then + print(err) return nil, err end return info end --- --- Waits for a mifare card to be placed within the vicinity of the reader. +-- Waits for a mifare card to be placed within the vicinity of the reader. -- @return if successfull: an table containing card info -- @return if unsuccessfull : nil, error local function waitFor14443a() @@ -139,14 +139,14 @@ local function waitFor14443a() end return nil, "Aborted by user" end + local library = { - - read1443a = read14443a, - read = read14443a, + read14443a = read14443a, + read = read14443a, waitFor14443a = waitFor14443a, - parse1443a = parse1443a, + parse14443a = parse14443a, sendToDevice = sendToDevice, ISO14A_COMMAND = ISO14A_COMMAND, } -return library \ No newline at end of file +return library diff --git a/client/scripts/14araw.lua b/client/scripts/14araw.lua index 94b3020c..e2530929 100644 --- a/client/scripts/14araw.lua +++ b/client/scripts/14araw.lua @@ -106,7 +106,7 @@ function main(args) dbg("doconnect") -- We reuse the connect functionality from a -- common library - info, err = lib14a.read1443a(true, no_rats) + info, err = lib14a.read14443a(true, no_rats) if err then return oops(err) end print(("Connected to card, uid = %s"):format(info.uid)) diff --git a/client/scripts/didump.lua b/client/scripts/didump.lua index 124c3dc3..71bfd99c 100644 --- a/client/scripts/didump.lua +++ b/client/scripts/didump.lua @@ -406,7 +406,7 @@ function main(args) -- GET TAG UID - result, err = lib14a.read1443a(false, true) + result, err = lib14a.read14443a(false, true) if not result then return oops(err) end diff --git a/client/scripts/formatMifare.lua b/client/scripts/formatMifare.lua index 56397acd..2861b542 100644 --- a/client/scripts/formatMifare.lua +++ b/client/scripts/formatMifare.lua @@ -71,7 +71,7 @@ end -- -- Read information from a card function GetCardInfo() - result, err = lib14a.read1443a(false, true) + result, err = lib14a.read14443a(false, true) if not result then print(err) return diff --git a/client/scripts/mfkeys.lua b/client/scripts/mfkeys.lua index 8e54f908..90aeafc2 100644 --- a/client/scripts/mfkeys.lua +++ b/client/scripts/mfkeys.lua @@ -170,7 +170,7 @@ local function main( args) print(desc); - result, err = reader.read1443a(false, true) + result, err = reader.read14443a(false, true) if not result then print(err) return diff --git a/client/scripts/mifare_autopwn.lua b/client/scripts/mifare_autopwn.lua index bede483b..d743f21e 100644 --- a/client/scripts/mifare_autopwn.lua +++ b/client/scripts/mifare_autopwn.lua @@ -56,7 +56,7 @@ end -- @return if unsuccessfull : nil, error function wait_for_mifare() while not core.ukbhit() do - res, err = reader.read1443a(false, true) + res, err = reader.read14443a(false, true) if res then return res end -- err means that there was no response from card end diff --git a/client/scripts/tnp3clone.lua b/client/scripts/tnp3clone.lua index 2a8d2763..9441559b 100644 --- a/client/scripts/tnp3clone.lua +++ b/client/scripts/tnp3clone.lua @@ -122,7 +122,7 @@ local function main(args) -- find tag - result, err = lib14a.read1443a(false, true) + result, err = lib14a.read14443a(false, true) if not result then return oops(err) end -- load keys diff --git a/client/scripts/tnp3dump.lua b/client/scripts/tnp3dump.lua index aca7d046..3955137e 100644 --- a/client/scripts/tnp3dump.lua +++ b/client/scripts/tnp3dump.lua @@ -127,7 +127,7 @@ local function main(args) local cmdSetDbgOff = "hf mf dbg 0" core.console( cmdSetDbgOff) - result, err = lib14a.read1443a(false, true) + result, err = lib14a.read14443a(false, true) if not result then return oops(err) end From 4e002980af3da9a88518082d36135ca0d65b6e9c Mon Sep 17 00:00:00 2001 From: Arnie97 Date: Thu, 25 Jan 2018 13:49:40 +0800 Subject: [PATCH 041/127] hf mf ecfill: Add the missing line break. --- client/cmdhfmf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index b653cf30..d0320148 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -1907,7 +1907,7 @@ int CmdHF14AMfECFill(const char *Cmd) default: numSectors = 16; } - printf("--params: numSectors: %d, keyType:%d", numSectors, keyType); + printf("--params: numSectors: %d, keyType:%d\n", numSectors, keyType); UsbCommand c = {CMD_MIFARE_EML_CARDLOAD, {numSectors, keyType, 0}}; SendCommand(&c); return 0; From 392301aaabe4622b3fece54c9cf8d07aa26f9a60 Mon Sep 17 00:00:00 2001 From: Arnie97 Date: Thu, 25 Jan 2018 14:10:41 +0800 Subject: [PATCH 042/127] mfkeys.lua: Remove the user input helpers (now in lualibs/utils.lua) --- client/scripts/mfkeys.lua | 42 ++++----------------------------------- 1 file changed, 4 insertions(+), 38 deletions(-) diff --git a/client/scripts/mfkeys.lua b/client/scripts/mfkeys.lua index 90aeafc2..ee1ee2d7 100644 --- a/client/scripts/mfkeys.lua +++ b/client/scripts/mfkeys.lua @@ -14,49 +14,15 @@ local cmds = require('commands') local keys = require('mf_default_keys') -- Ability to read what card is there local reader = require('read14a') +-- Asks the user for input +local utils = require('utils') -local desc = -("This script implements check keys. It utilises a large list of default keys (currently %d keys).\ +local desc = ("This script implements check keys. \ +It utilises a large list of default keys (currently %d keys).\ If you want to add more, just put them inside mf_default_keys.lua. "):format(#keys) local TIMEOUT = 10000 -- 10 seconds - ---[[This may be moved to a separate library at some point]] -local utils = -{ - --- - -- Asks the user for Yes or No - confirm = function(message, ...) - local answer - message = message .. " [y]/[n] ?" - repeat - io.write(message) - io.flush() - answer=io.read() - if answer == 'Y' or answer == "y" then - return true - elseif answer == 'N' or answer == 'n' then - return false - end - until false - end, - --- - -- Asks the user for input - input = function (message , default) - local answer - if default ~= nil then - message = message .. " (default: ".. default.. " )" - end - message = message .." \n > " - io.write(message) - io.flush() - answer=io.read() - if answer == '' then answer = default end - - return answer - end, -} local function checkCommand(command) From f88fa399bc3855f38676e68ba228e31302f7ce6a Mon Sep 17 00:00:00 2001 From: Arnie97 Date: Thu, 25 Jan 2018 14:48:12 +0800 Subject: [PATCH 043/127] mfkeys.lua: Align empty cells in the table. --- client/scripts/mfkeys.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/scripts/mfkeys.lua b/client/scripts/mfkeys.lua index ee1ee2d7..919dadb8 100644 --- a/client/scripts/mfkeys.lua +++ b/client/scripts/mfkeys.lua @@ -85,7 +85,7 @@ local function displayresults(results) for sector,_ in pairs(results) do blockNo, keyA, keyB = unpack(_) - print(("| %3d | %3d |%s|%s|"):format(sector, blockNo, keyA, keyB )) + print(("| %3d | %3d |%12s|%12s|"):format(sector, blockNo, keyA, keyB)) end print("|--------------------------------------|") From b5cf8b07e22e96309a066149344673dfc19d1960 Mon Sep 17 00:00:00 2001 From: Arnie97 Date: Thu, 25 Jan 2018 14:48:26 +0800 Subject: [PATCH 044/127] mfkeys.lua: Remove trailing whitespaces. --- client/scripts/mfkeys.lua | 59 ++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/client/scripts/mfkeys.lua b/client/scripts/mfkeys.lua index 919dadb8..33027d31 100644 --- a/client/scripts/mfkeys.lua +++ b/client/scripts/mfkeys.lua @@ -1,11 +1,11 @@ --[[ This is an example of Lua-scripting within proxmark3. This is a lua-side - implementation of hf mf chk + implementation of hf mf chk This code is licensed to you under the terms of the GNU GPL, version 2 or, at your option, any later version. See the LICENSE.txt file for the text of the license. - + Copyright (C) 2013 m h swende --]] -- Loads the commands-library @@ -49,7 +49,7 @@ end function checkBlock(blockNo, keys, keyType) - -- The command data is only 512 bytes, each key is 6 bytes, meaning that we can send max 85 keys in one go. + -- The command data is only 512 bytes, each key is 6 bytes, meaning that we can send max 85 keys in one go. -- If there's more, we need to split it up local start, remaining= 1, #keys local arg1 = bit32.bor(bit32.lshift(keyType, 8), blockNo) @@ -61,10 +61,10 @@ function checkBlock(blockNo, keys, keyType) --print("data",data) --print("data len", #data) print(("Testing block %d, keytype %d, with %d keys"):format(blockNo, keyType, n)) - local command = Command:new{cmd = cmds.CMD_MIFARE_CHKKEYS, - arg1 = arg1, - arg2 = 1, - arg3 = n, + local command = Command:new{cmd = cmds.CMD_MIFARE_CHKKEYS, + arg1 = arg1, + arg2 = 1, + arg3 = n, data = data} local status = checkCommand(command) if status then return status, blockNo end @@ -90,36 +90,38 @@ local function displayresults(results) print("|--------------------------------------|") end + -- A little helper to place an item first in the list local function placeFirst(akey, list) - akey = akey:lower() - if list[1] == akey then + akey = akey:lower() + if list[1] == akey then -- Already at pole position return list end local result = {akey} --print(("Putting '%s' first"):format(akey)) for i,v in ipairs(list) do - if v ~= akey then + if v ~= akey then result[#result+1] = v end end return result end + local function dumptofile(results) local sector, blockNo, keyA, keyB,_ - if utils.confirm("Do you wish to save the keys to dumpfile?") then + if utils.confirm("Do you wish to save the keys to dumpfile?") then local destination = utils.input("Select a filename to store to", "dumpkeys.bin") local file = io.open(destination, "w") - if file == nil then + if file == nil then print("Could not write to file ", destination) return end local key_a = "" local key_b = "" - + for sector,_ in pairs(results) do blockNo, keyA, keyB = unpack(_) key_a = key_a .. bin.pack("H",keyA); @@ -132,7 +134,7 @@ local function dumptofile(results) end -local function main( args) +local function main(args) print(desc); @@ -147,11 +149,11 @@ local function main( args) core.clearCommandBuffer() local blockNo local keyType = 0 -- A=0, B=1 - local numSectors = 16 + local numSectors = 16 - if 0x18 == result.sak then --NXP MIFARE Classic 4k | Plus 4k - -- IFARE Classic 4K offers 4096 bytes split into forty sectors, - -- of which 32 are same size as in the 1K with eight more that are quadruple size sectors. + if 0x18 == result.sak then -- NXP MIFARE Classic 4k | Plus 4k + -- IFARE Classic 4K offers 4096 bytes split into forty sectors, + -- of which 32 are same size as in the 1K with eight more that are quadruple size sectors. numSectors = 40 elseif 0x08 == result.sak then -- NXP MIFARE CLASSIC 1k | Plus 2k -- 1K offers 1024 bytes of data storage, split into 16 sector @@ -159,7 +161,7 @@ local function main( args) elseif 0x09 == result.sak then -- NXP MIFARE Mini 0.3k -- MIFARE Classic mini offers 320 bytes split into five sectors. numSectors = 5 - elseif 0x10 == result.sak then-- "NXP MIFARE Plus 2k" + elseif 0x10 == result.sak then -- NXP MIFARE Plus 2k numSectors = 32 else print("I don't know how many sectors there are on this type of card, defaulting to 16") @@ -169,25 +171,25 @@ local function main( args) for sector=1,numSectors,1 do --[[ - The mifare Classic 1k card has 16 sectors of 4 data blocks each. + The mifare Classic 1k card has 16 sectors of 4 data blocks each. The first 32 sectors of a mifare Classic 4k card consists of 4 data blocks and the remaining - 8 sectors consist of 16 data blocks. + 8 sectors consist of 16 data blocks. --]] - local blockNo = sector * 4 -1 - + local blockNo = sector * 4 - 1 + if sector > 32 then - blockNo = 32*4+ (sector-32)*16 -1 + blockNo = 32*4 + (sector-32)*16 - 1 end local keyA = checkBlock(blockNo, keys, 0) - if keyA then keys = placeFirst(keyA, keys) end + if keyA then keys = placeFirst(keyA, keys) end keyA = keyA or "" local keyB = checkBlock(blockNo, keys, 1) - if keyB then keys = placeFirst(keyB, keys) end + if keyB then keys = placeFirst(keyB, keys) end keyB = keyB or "" - result[sector] = {blockNo, keyA, keyB } + result[sector] = {blockNo, keyA, keyB} -- Check if user aborted if core.ukbhit() then @@ -199,5 +201,4 @@ local function main( args) dumptofile(result) end -main( args) - +main(args) From 36545f0a5617d71b06e6d5773802fcf33ed5525a Mon Sep 17 00:00:00 2001 From: Arnie97 Date: Sat, 27 Jan 2018 01:09:56 +0800 Subject: [PATCH 045/127] hf mf eset: reuse mfEmlSetMem(). --- client/cmdhfmf.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index d0320148..ddfb1c02 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -1685,10 +1685,7 @@ int CmdHF14AMfESet(const char *Cmd) } // 1 - blocks count - UsbCommand c = {CMD_MIFARE_EML_MEMSET, {blockNo, 1, 0}}; - memcpy(c.d.asBytes, memBlock, 16); - SendCommand(&c); - return 0; + return mfEmlSetMem(memBlock, blockNo, 1); } From 7b7416bd3b7e0b9a3003ec33da943bd26b505d82 Mon Sep 17 00:00:00 2001 From: Arnie97 Date: Sat, 27 Jan 2018 01:55:38 +0800 Subject: [PATCH 046/127] hf mf nested: transfer keys to the correct block in one sector mode. --- client/cmdhfmf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index ddfb1c02..dbb6d092 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -683,9 +683,9 @@ int CmdHF14AMfNested(const char *Cmd) if (transferToEml) { uint8_t sectortrailer; if (trgBlockNo < 32*4) { // 4 block sector - sectortrailer = (trgBlockNo & 0x03) + 3; + sectortrailer = (trgBlockNo & ~0x03) + 3; } else { // 16 block sector - sectortrailer = (trgBlockNo & 0x0f) + 15; + sectortrailer = (trgBlockNo & ~0x0f) + 15; } mfEmlGetMem(keyBlock, sectortrailer, 1); From 298e1a2d0da6ad10a5db57f1529496306e47e009 Mon Sep 17 00:00:00 2001 From: pwpiwi Date: Wed, 31 Jan 2018 08:14:56 +0100 Subject: [PATCH 047/127] update license conditions in armsrc/optimized_cipher.[ch] (#554) --- armsrc/optimized_cipher.c | 2 +- armsrc/optimized_cipher.h | 39 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/armsrc/optimized_cipher.c b/armsrc/optimized_cipher.c index 005f473b..b1f33737 100644 --- a/armsrc/optimized_cipher.c +++ b/armsrc/optimized_cipher.c @@ -22,7 +22,7 @@ * * This is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. + * by the Free Software Foundation, or, at your option, any later version. * * This file is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/armsrc/optimized_cipher.h b/armsrc/optimized_cipher.h index c10aea28..6a4e2641 100644 --- a/armsrc/optimized_cipher.h +++ b/armsrc/optimized_cipher.h @@ -1,4 +1,41 @@ -#ifndef OPTIMIZED_CIPHER_H +/***************************************************************************** + * WARNING + * + * THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY. + * + * USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL + * PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL, + * AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES. + * + * THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS. + * + ***************************************************************************** + * + * This file is part of loclass. It is a reconstructon of the cipher engine + * used in iClass, and RFID techology. + * + * The implementation is based on the work performed by + * Flavio D. Garcia, Gerhard de Koning Gans, Roel Verdult and + * Milosch Meriac in the paper "Dismantling IClass". + * + * Copyright (C) 2014 Martin Holst Swende + * + * This is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation, or, at your option, any later version. + * + * This file 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. + * + * You should have received a copy of the GNU General Public License + * along with loclass. If not, see . + * + * + ****************************************************************************/ + + #ifndef OPTIMIZED_CIPHER_H #define OPTIMIZED_CIPHER_H #include From f921c113c91ed6940f030db837e83afe4dab9ca8 Mon Sep 17 00:00:00 2001 From: pwpiwi Date: Wed, 31 Jan 2018 18:31:51 +0100 Subject: [PATCH 048/127] add force_align_arg_pointer attribute to all callback functions * inspired by issue #404 and respective fix PR #538 * possible fix for mysterious crashes, e.g. issue #497 and http://www.proxmark.org/forum/viewtopic.php?id=5388 --- client/cmdhfmfhard.c | 16 ++++++++++++++-- client/mifarehost.c | 9 ++++++++- client/proxmark3.c | 17 +++++++++++++++-- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/client/cmdhfmfhard.c b/client/cmdhfmfhard.c index 69ad898d..cf19436c 100644 --- a/client/cmdhfmfhard.c +++ b/client/cmdhfmfhard.c @@ -1158,7 +1158,13 @@ static bool timeout(void) } -static void *check_for_BitFlipProperties_thread(void *args) +static void +#ifdef __has_attribute +#if __has_attribute(force_align_arg_pointer) +__attribute__((force_align_arg_pointer)) +#endif +#endif +*check_for_BitFlipProperties_thread(void *args) { uint8_t first_byte = ((uint8_t *)args)[0]; uint8_t last_byte = ((uint8_t *)args)[1]; @@ -1906,7 +1912,13 @@ static void init_book_of_work(void) } -static void *generate_candidates_worker_thread(void *args) +static void +#ifdef __has_attribute +#if __has_attribute(force_align_arg_pointer) +__attribute__((force_align_arg_pointer)) +#endif +#endif +*generate_candidates_worker_thread(void *args) { uint16_t *sum_args = (uint16_t *)args; uint16_t sum_a0 = sums[sum_args[0]]; diff --git a/client/mifarehost.c b/client/mifarehost.c index d204bf12..dd656ee1 100644 --- a/client/mifarehost.c +++ b/client/mifarehost.c @@ -295,7 +295,13 @@ typedef // wrapper function for multi-threaded lfsr_recovery32 -void* nested_worker_thread(void *arg) +void +#ifdef __has_attribute +#if __has_attribute(force_align_arg_pointer) +__attribute__((force_align_arg_pointer)) +#endif +#endif +*nested_worker_thread(void *arg) { struct Crypto1State *p1; StateList_t *statelist = arg; @@ -309,6 +315,7 @@ void* nested_worker_thread(void *arg) return statelist->head.slhead; } + int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *resultKey, bool calibrate) { uint16_t i; diff --git a/client/proxmark3.c b/client/proxmark3.c index 99ba9fba..95dd7cb9 100644 --- a/client/proxmark3.c +++ b/client/proxmark3.c @@ -67,7 +67,14 @@ struct receiver_arg { byte_t rx[sizeof(UsbCommand)]; byte_t* prx = rx; -static void *uart_receiver(void *targ) { + +static void +#ifdef __has_attribute +#if __has_attribute(force_align_arg_pointer) +__attribute__((force_align_arg_pointer)) +#endif +#endif +*uart_receiver(void *targ) { struct receiver_arg *arg = (struct receiver_arg*)targ; size_t rxlen; @@ -95,7 +102,13 @@ static void *uart_receiver(void *targ) { } -void main_loop(char *script_cmds_file, char *script_cmd, bool usb_present) { +void +#ifdef __has_attribute +#if __has_attribute(force_align_arg_pointer) +__attribute__((force_align_arg_pointer)) +#endif +#endif +main_loop(char *script_cmds_file, char *script_cmd, bool usb_present) { struct receiver_arg rarg; char *cmd = NULL; pthread_t reader_thread; From 32e6891a05f70ebdfae44671c9e5fde3035bb598 Mon Sep 17 00:00:00 2001 From: Arnie97 Date: Thu, 1 Feb 2018 15:09:14 +0800 Subject: [PATCH 049/127] hf mf nested: use bitwise or instead. (#556) --- client/cmdhfmf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index dbb6d092..f5d7a5be 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -683,9 +683,9 @@ int CmdHF14AMfNested(const char *Cmd) if (transferToEml) { uint8_t sectortrailer; if (trgBlockNo < 32*4) { // 4 block sector - sectortrailer = (trgBlockNo & ~0x03) + 3; + sectortrailer = trgBlockNo | 0x03; } else { // 16 block sector - sectortrailer = (trgBlockNo & ~0x0f) + 15; + sectortrailer = trgBlockNo | 0x0f; } mfEmlGetMem(keyBlock, sectortrailer, 1); From d86ee73da53a701b3e47de9eb2a047c6bf0b0bd1 Mon Sep 17 00:00:00 2001 From: pwpiwi Date: Sat, 3 Feb 2018 18:24:32 +0100 Subject: [PATCH 050/127] fix: prevent hf mf mifare from always running twice (issue #510) --- client/mifarehost.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/client/mifarehost.c b/client/mifarehost.c index d204bf12..b6eb60f0 100644 --- a/client/mifarehost.c +++ b/client/mifarehost.c @@ -178,12 +178,14 @@ int mfDarkside(uint64_t *key) continue; } - qsort(keylist, keycount, sizeof(*keylist), compare_uint64); - keycount = intersection(last_keylist, keylist); - if (keycount == 0) { - free(last_keylist); - last_keylist = keylist; - continue; + if (par_list == 0) { + qsort(keylist, keycount, sizeof(*keylist), compare_uint64); + keycount = intersection(last_keylist, keylist); + if (keycount == 0) { + free(last_keylist); + last_keylist = keylist; + continue; + } } if (keycount > 1) { @@ -198,10 +200,10 @@ int mfDarkside(uint64_t *key) for (int i = 0; i < keycount; i += max_keys) { int size = keycount - i > max_keys ? max_keys : keycount - i; for (int j = 0; j < size; j++) { - if (last_keylist == NULL) { - num_to_bytes(keylist[i*max_keys + j], 6, keyBlock); - } else { + if (par_list == 0) { num_to_bytes(last_keylist[i*max_keys + j], 6, keyBlock); + } else { + num_to_bytes(keylist[i*max_keys + j], 6, keyBlock); } } if (!mfCheckKeys(0, 0, false, size, keyBlock, key)) { From 948b49c4077946bc5aea7b8def79e5f856997197 Mon Sep 17 00:00:00 2001 From: Proxcloud Date: Wed, 7 Feb 2018 01:07:48 +0800 Subject: [PATCH 051/127] Add BOS USB descriptor. This allows non-root access on Android devices --- common/usb_cdc.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/common/usb_cdc.c b/common/usb_cdc.c index 348b97e9..36df2a86 100644 --- a/common/usb_cdc.c +++ b/common/usb_cdc.c @@ -156,6 +156,28 @@ static const char cfgDescriptor[] = { 0x00, 0x00 // bInterval }; +const char BOSDescriptor[] = { + // BOS descriptor header + 0x05, 0x0F, 0x39, 0x00, 0x02, + + // Microsoft OS 2.0 Platform Capability Descriptor + 0x1C, // Descriptor size (28 bytes) + 0x10, // Descriptor type (Device Capability) + 0x05, // Capability type (Platform) + 0x00, // Reserved + + // MS OS 2.0 Platform Capability ID (D8DD60DF-4589-4CC7-9CD2-659D9E648A9F) + 0xDF, 0x60, 0xDD, 0xD8, + 0x89, 0x45, + 0xC7, 0x4C, + 0x9C, 0xD2, + 0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F, + + 0x00, 0x00, 0x03, 0x06, // Windows version (8.1) (0x06030000) + 0x1e, 0x00, + 252, // Vendor-assigned bMS_VendorCode + 0x00 // Doesn’t support alternate enumeration +}; static const char StrDescLanguageCodes[] = { 4, // Length @@ -550,6 +572,10 @@ void AT91F_CDC_Enumerate() { AT91F_USB_SendData(pUdp, devDescriptor, MIN(sizeof(devDescriptor), wLength)); else if (wValue == 0x200) // Return Configuration Descriptor AT91F_USB_SendData(pUdp, cfgDescriptor, MIN(sizeof(cfgDescriptor), wLength)); + else if ((wValue & 0xF00) == 0xF00) // Return BOS Descriptor + AT91F_USB_SendData(pUdp, BOSDescriptor, MIN(sizeof(BOSDescriptor), wLength)); + else if ((wValue & 0x300) == 0x300) // Return Manufacturer Descriptor - this is needed by Android + AT91F_USB_SendData(pUdp, StrDescManufacturer, MIN(sizeof(StrDescManufacturer), wLength)); else if ((wValue & 0xF00) == 0x300) { // Return String Descriptor const char *strDescriptor = getStringDescriptor(wValue & 0xff); if (strDescriptor != NULL) { From 02515642bc81dc44d08e47b2f3454e29609dd0fe Mon Sep 17 00:00:00 2001 From: Iceman Date: Thu, 8 Feb 2018 04:15:42 +0100 Subject: [PATCH 052/127] fix: hf mf mifare - populate keylist (#568) This will solve the long running of the attack, since all candidate keys will be tested. --- client/mifarehost.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/mifarehost.c b/client/mifarehost.c index a01d3b5f..2bd21077 100644 --- a/client/mifarehost.c +++ b/client/mifarehost.c @@ -201,9 +201,9 @@ int mfDarkside(uint64_t *key) int size = keycount - i > max_keys ? max_keys : keycount - i; for (int j = 0; j < size; j++) { if (par_list == 0) { - num_to_bytes(last_keylist[i*max_keys + j], 6, keyBlock); + num_to_bytes(last_keylist[i*max_keys + j], 6, keyBlock+(j*6)); } else { - num_to_bytes(keylist[i*max_keys + j], 6, keyBlock); + num_to_bytes(keylist[i*max_keys + j], 6, keyBlock+(j*6)); } } if (!mfCheckKeys(0, 0, false, size, keyBlock, key)) { From 8b9de94afe7436eb14bf6e6c801bd4054842abe2 Mon Sep 17 00:00:00 2001 From: Proxcloud Date: Thu, 8 Feb 2018 17:47:40 +0800 Subject: [PATCH 053/127] Remove BOS descriptor, leave just manufacturer descriptor for Android --- common/usb_cdc.c | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/common/usb_cdc.c b/common/usb_cdc.c index 36df2a86..3553d850 100644 --- a/common/usb_cdc.c +++ b/common/usb_cdc.c @@ -156,28 +156,6 @@ static const char cfgDescriptor[] = { 0x00, 0x00 // bInterval }; -const char BOSDescriptor[] = { - // BOS descriptor header - 0x05, 0x0F, 0x39, 0x00, 0x02, - - // Microsoft OS 2.0 Platform Capability Descriptor - 0x1C, // Descriptor size (28 bytes) - 0x10, // Descriptor type (Device Capability) - 0x05, // Capability type (Platform) - 0x00, // Reserved - - // MS OS 2.0 Platform Capability ID (D8DD60DF-4589-4CC7-9CD2-659D9E648A9F) - 0xDF, 0x60, 0xDD, 0xD8, - 0x89, 0x45, - 0xC7, 0x4C, - 0x9C, 0xD2, - 0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F, - - 0x00, 0x00, 0x03, 0x06, // Windows version (8.1) (0x06030000) - 0x1e, 0x00, - 252, // Vendor-assigned bMS_VendorCode - 0x00 // Doesn’t support alternate enumeration -}; static const char StrDescLanguageCodes[] = { 4, // Length @@ -572,8 +550,6 @@ void AT91F_CDC_Enumerate() { AT91F_USB_SendData(pUdp, devDescriptor, MIN(sizeof(devDescriptor), wLength)); else if (wValue == 0x200) // Return Configuration Descriptor AT91F_USB_SendData(pUdp, cfgDescriptor, MIN(sizeof(cfgDescriptor), wLength)); - else if ((wValue & 0xF00) == 0xF00) // Return BOS Descriptor - AT91F_USB_SendData(pUdp, BOSDescriptor, MIN(sizeof(BOSDescriptor), wLength)); else if ((wValue & 0x300) == 0x300) // Return Manufacturer Descriptor - this is needed by Android AT91F_USB_SendData(pUdp, StrDescManufacturer, MIN(sizeof(StrDescManufacturer), wLength)); else if ((wValue & 0xF00) == 0x300) { // Return String Descriptor From c179e7b1f886f5ca0c2f924197349195a8925215 Mon Sep 17 00:00:00 2001 From: Proxcloud Date: Thu, 8 Feb 2018 19:37:55 +0800 Subject: [PATCH 054/127] remove old Manufacturer description code. fix Product description length --- common/usb_cdc.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/common/usb_cdc.c b/common/usb_cdc.c index 3553d850..d3f5cd0c 100644 --- a/common/usb_cdc.c +++ b/common/usb_cdc.c @@ -183,7 +183,7 @@ static const char StrDescManufacturer[] = { }; static const char StrDescProduct[] = { - 8, // Length + 4, // Length 0x03, // Type is string 'P', 0x00, 'M', 0x00, @@ -550,16 +550,15 @@ void AT91F_CDC_Enumerate() { AT91F_USB_SendData(pUdp, devDescriptor, MIN(sizeof(devDescriptor), wLength)); else if (wValue == 0x200) // Return Configuration Descriptor AT91F_USB_SendData(pUdp, cfgDescriptor, MIN(sizeof(cfgDescriptor), wLength)); - else if ((wValue & 0x300) == 0x300) // Return Manufacturer Descriptor - this is needed by Android - AT91F_USB_SendData(pUdp, StrDescManufacturer, MIN(sizeof(StrDescManufacturer), wLength)); else if ((wValue & 0xF00) == 0x300) { // Return String Descriptor const char *strDescriptor = getStringDescriptor(wValue & 0xff); if (strDescriptor != NULL) { AT91F_USB_SendData(pUdp, strDescriptor, MIN(strDescriptor[0], wLength)); } else { - AT91F_USB_SendStall(pUdp); + AT91F_USB_SendData(pUdp, StrDescManufacturer, MIN(sizeof(StrDescManufacturer), wLength)); } } + else AT91F_USB_SendStall(pUdp); break; From 13c25f892e003f1fa3639b7154782c3146aad4eb Mon Sep 17 00:00:00 2001 From: Proxcloud Date: Thu, 8 Feb 2018 19:43:03 +0800 Subject: [PATCH 055/127] remove debug change --- common/usb_cdc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/common/usb_cdc.c b/common/usb_cdc.c index d3f5cd0c..51dcacdb 100644 --- a/common/usb_cdc.c +++ b/common/usb_cdc.c @@ -555,10 +555,9 @@ void AT91F_CDC_Enumerate() { if (strDescriptor != NULL) { AT91F_USB_SendData(pUdp, strDescriptor, MIN(strDescriptor[0], wLength)); } else { - AT91F_USB_SendData(pUdp, StrDescManufacturer, MIN(sizeof(StrDescManufacturer), wLength)); + AT91F_USB_SendStall(pUdp); } } - else AT91F_USB_SendStall(pUdp); break; From d03a573eee1e2d9f87990524fee3502d5e730665 Mon Sep 17 00:00:00 2001 From: Proxcloud Date: Thu, 8 Feb 2018 20:40:57 +0800 Subject: [PATCH 056/127] change product desc to 9 and add extra null byte --- common/usb_cdc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/common/usb_cdc.c b/common/usb_cdc.c index 51dcacdb..82522623 100644 --- a/common/usb_cdc.c +++ b/common/usb_cdc.c @@ -183,11 +183,12 @@ static const char StrDescManufacturer[] = { }; static const char StrDescProduct[] = { - 4, // Length + 9, // Length 0x03, // Type is string 'P', 0x00, 'M', 0x00, - '3', 0x00 + '3', 0x00, + 0x00 }; const char* getStringDescriptor(uint8_t idx) From 664e132f882e04cf8aafe9a6d8fc137d57816ab8 Mon Sep 17 00:00:00 2001 From: pwpiwi Date: Thu, 8 Feb 2018 14:50:03 +0100 Subject: [PATCH 057/127] hf mf mifare: * prevent WDT crash on repeated tries * comes with faster execution as side effect * use uint8_t instead of byte_t * populate ar instead of (correctly) assuming that it is zero * remove the "will take a few seconds longer" message because it is no longer true --- armsrc/iso14443a.c | 28 +++++++++++++--------------- client/mifarehost.c | 17 ++++++++--------- 2 files changed, 21 insertions(+), 24 deletions(-) diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index 6703cc65..a8273e5e 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -2151,9 +2151,7 @@ void ReaderMifare(bool first_try) uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE]; uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE]; - if (first_try) { - iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD); - } + iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD); // free eventually allocated BigBuf memory. We want all for tracing. BigBuf_free(); @@ -2161,9 +2159,9 @@ void ReaderMifare(bool first_try) clear_trace(); set_tracing(true); - byte_t nt_diff = 0; + uint8_t nt_diff = 0; uint8_t par[1] = {0}; // maximum 8 Bytes to be sent here, 1 byte parity is therefore enough - static byte_t par_low = 0; + static uint8_t par_low = 0; bool led_on = true; uint8_t uid[10] ={0}; uint32_t cuid; @@ -2171,11 +2169,11 @@ void ReaderMifare(bool first_try) uint32_t nt = 0; uint32_t previous_nt = 0; static uint32_t nt_attacked = 0; - byte_t par_list[8] = {0x00}; - byte_t ks_list[8] = {0x00}; + uint8_t par_list[8] = {0x00}; + uint8_t ks_list[8] = {0x00}; #define PRNG_SEQUENCE_LENGTH (1 << 16); - static uint32_t sync_time; + uint32_t sync_time = GetCountSspClk() & 0xfffffff8; static int32_t sync_cycles; int catch_up_cycles = 0; int last_catch_up = 0; @@ -2185,10 +2183,9 @@ void ReaderMifare(bool first_try) if (first_try) { mf_nr_ar3 = 0; - sync_time = GetCountSspClk() & 0xfffffff8; + par[0] = par_low = 0; sync_cycles = PRNG_SEQUENCE_LENGTH; // theory: Mifare Classic's random generator repeats every 2^16 cycles (and so do the tag nonces). nt_attacked = 0; - par[0] = 0; } else { // we were unsuccessful on a previous call. Try another READER nonce (first 3 parity bits remain the same) @@ -2204,6 +2201,7 @@ void ReaderMifare(bool first_try) #define MAX_UNEXPECTED_RANDOM 4 // maximum number of unexpected (i.e. real) random numbers when trying to sync. Then give up. #define MAX_SYNC_TRIES 32 + #define SYNC_TIME_BUFFER 16 // if there is only SYNC_TIME_BUFFER left before next planned sync, wait for next PRNG cycle #define NUM_DEBUG_INFOS 8 // per strategy #define MAX_STRATEGY 3 uint16_t unexpected_random = 0; @@ -2253,8 +2251,8 @@ void ReaderMifare(bool first_try) sync_time = (sync_time & 0xfffffff8) + sync_cycles + catch_up_cycles; catch_up_cycles = 0; - // if we missed the sync time already, advance to the next nonce repeat - while(GetCountSspClk() > sync_time) { + // if we missed the sync time already or are about to miss it, advance to the next nonce repeat + while(sync_time < GetCountSspClk() + SYNC_TIME_BUFFER) { elapsed_prng_sequences++; sync_time = (sync_time & 0xfffffff8) + sync_cycles; } @@ -2410,14 +2408,14 @@ void ReaderMifare(bool first_try) } } - byte_t buf[28]; + uint8_t buf[32]; memcpy(buf + 0, uid, 4); num_to_bytes(nt, 4, buf + 4); memcpy(buf + 8, par_list, 8); memcpy(buf + 16, ks_list, 8); - memcpy(buf + 24, mf_nr_ar, 4); + memcpy(buf + 24, mf_nr_ar, 8); - cmd_send(CMD_ACK, isOK, 0, 0, buf, 28); + cmd_send(CMD_ACK, isOK, 0, 0, buf, 32); // Thats it... FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); diff --git a/client/mifarehost.c b/client/mifarehost.c index 2bd21077..471fbc42 100644 --- a/client/mifarehost.c +++ b/client/mifarehost.c @@ -73,13 +73,12 @@ static uint32_t intersection(uint64_t *list1, uint64_t *list2) // Darkside attack (hf mf mifare) -static uint32_t nonce2key(uint32_t uid, uint32_t nt, uint32_t nr, uint64_t par_info, uint64_t ks_info, uint64_t **keys) { +static uint32_t nonce2key(uint32_t uid, uint32_t nt, uint32_t nr, uint32_t ar, uint64_t par_info, uint64_t ks_info, uint64_t **keys) { struct Crypto1State *states; - uint32_t i, pos, rr; //nr_diff; + uint32_t i, pos; uint8_t bt, ks3x[8], par[8][8]; uint64_t key_recovered; - static uint64_t *keylist; - rr = 0; + uint64_t *keylist; // Reset the last three significant bits of the reader nonce nr &= 0xffffff1f; @@ -92,7 +91,7 @@ static uint32_t nonce2key(uint32_t uid, uint32_t nt, uint32_t nr, uint64_t par_i } } - states = lfsr_common_prefix(nr, rr, ks3x, par, (par_info == 0)); + states = lfsr_common_prefix(nr, ar, ks3x, par, (par_info == 0)); if (states == NULL) { *keys = NULL; @@ -116,7 +115,7 @@ static uint32_t nonce2key(uint32_t uid, uint32_t nt, uint32_t nr, uint64_t par_i int mfDarkside(uint64_t *key) { uint32_t uid = 0; - uint32_t nt = 0, nr = 0; + uint32_t nt = 0, nr = 0, ar = 0; uint64_t par_list = 0, ks_list = 0; uint64_t *keylist = NULL, *last_keylist = NULL; uint32_t keycount = 0; @@ -159,18 +158,18 @@ int mfDarkside(uint64_t *key) nt = (uint32_t)bytes_to_num(resp.d.asBytes + 4, 4); par_list = bytes_to_num(resp.d.asBytes + 8, 8); ks_list = bytes_to_num(resp.d.asBytes + 16, 8); - nr = bytes_to_num(resp.d.asBytes + 24, 4); + nr = (uint32_t)bytes_to_num(resp.d.asBytes + 24, 4); + ar = (uint32_t)bytes_to_num(resp.d.asBytes + 28, 4); break; } } if (par_list == 0 && c.arg[0] == true) { PrintAndLog("Parity is all zero. Most likely this card sends NACK on every failed authentication."); - PrintAndLog("Attack will take a few seconds longer because we need two consecutive successful runs."); } c.arg[0] = false; - keycount = nonce2key(uid, nt, nr, par_list, ks_list, &keylist); + keycount = nonce2key(uid, nt, nr, ar, par_list, ks_list, &keylist); if (keycount == 0) { PrintAndLog("Key not found (lfsr_common_prefix list is null). Nt=%08x", nt); From f3dc6d59f45e25fd199cb20cdf4d3af270d93963 Mon Sep 17 00:00:00 2001 From: Proxcloud Date: Thu, 8 Feb 2018 22:32:08 +0800 Subject: [PATCH 058/127] make product string even length --- common/usb_cdc.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/common/usb_cdc.c b/common/usb_cdc.c index 82522623..d33bca7b 100644 --- a/common/usb_cdc.c +++ b/common/usb_cdc.c @@ -183,12 +183,17 @@ static const char StrDescManufacturer[] = { }; static const char StrDescProduct[] = { - 9, // Length + 20, // Length 0x03, // Type is string - 'P', 0x00, - 'M', 0x00, - '3', 0x00, - 0x00 + 'p', 0x00, + 'r', 0x00, + 'o', 0x00, + 'x', 0x00, + 'm', 0x00, + 'a', 0x00, + 'r', 0x00, + 'k', 0x00, + '3', 0x00 }; const char* getStringDescriptor(uint8_t idx) From a37725facfb70e0d699f423c6d986173ef890531 Mon Sep 17 00:00:00 2001 From: Oleg Moiseenko Date: Fri, 9 Feb 2018 16:50:55 +0200 Subject: [PATCH 059/127] add nested auth decoding to `hf mf sniff` --- armsrc/mifarecmd.h | 1 - armsrc/mifaresniff.c | 2 +- client/cmdhfmf.c | 17 +++++- client/mifarehost.c | 134 +++++++++++++++++++++++++++++++++++++------ client/mifarehost.h | 3 +- client/util.c | 17 ++++++ client/util.h | 1 + common/parity.h | 6 ++ 8 files changed, 159 insertions(+), 22 deletions(-) diff --git a/armsrc/mifarecmd.h b/armsrc/mifarecmd.h index 145e2989..e17fa998 100644 --- a/armsrc/mifarecmd.h +++ b/armsrc/mifarecmd.h @@ -16,7 +16,6 @@ #include "proxmark3.h" #include "apps.h" #include "util.h" -#include "string.h" #include "iso14443crc.h" #include "iso14443a.h" diff --git a/armsrc/mifaresniff.c b/armsrc/mifaresniff.c index 4e573be7..f20f2557 100644 --- a/armsrc/mifaresniff.c +++ b/armsrc/mifaresniff.c @@ -116,7 +116,7 @@ bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint8_t *parity, ui sniffState = SNF_CARD_CMD; } // intentionally no break; case SNF_CARD_CMD:{ - LogTrace(data, len, 0, 0, NULL, reader); + LogTrace(data, len, 0, 0, parity, reader); timerData = GetTickCount(); break; } diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index f5d7a5be..a2da01c9 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -18,6 +18,7 @@ #include "proxmark3.h" #include "cmdmain.h" #include "cmdhfmfhard.h" +#include "parity.h" #include "util.h" #include "util_posix.h" #include "usb_cmd.h" @@ -2470,6 +2471,7 @@ int CmdHF14AMfSniff(const char *Cmd){ //var int res = 0; int len = 0; + int parlen = 0; int blockLen = 0; int pckNum = 0; int num = 0; @@ -2481,6 +2483,7 @@ int CmdHF14AMfSniff(const char *Cmd){ uint8_t *buf = NULL; uint16_t bufsize = 0; uint8_t *bufPtr = NULL; + uint8_t parity[16]; char ctmp = param_getchar(Cmd, 0); if ( ctmp == 'h' || ctmp == 'H' ) { @@ -2572,6 +2575,7 @@ int CmdHF14AMfSniff(const char *Cmd){ } else { isTag = false; } + parlen = (len - 1) / 8 + 1; bufPtr += 2; if ((len == 14) && (bufPtr[0] == 0xff) && (bufPtr[1] == 0xff) && (bufPtr[12] == 0xff) && (bufPtr[13] == 0xff)) { memcpy(uid, bufPtr + 2, 7); @@ -2590,15 +2594,22 @@ int CmdHF14AMfSniff(const char *Cmd){ if (wantDecrypt) mfTraceInit(uid, atqa, sak, wantSaveToEmlFile); } else { - PrintAndLog("%s(%d):%s", isTag ? "TAG":"RDR", num, sprint_hex(bufPtr, len)); + oddparitybuf(bufPtr, len, parity); + PrintAndLog("%s(%d):%s [%s] c[%s]%c", + isTag ? "TAG":"RDR", + num, + sprint_hex(bufPtr, len), + printBitsPar(bufPtr + len, len), + printBitsPar(parity, len), + memcmp(bufPtr + len, parity, len / 8 + 1) ? '!' : ' '); if (wantLogToFile) AddLogHex(logHexFileName, isTag ? "TAG: ":"RDR: ", bufPtr, len); if (wantDecrypt) - mfTraceDecode(bufPtr, len, wantSaveToEmlFile); + mfTraceDecode(bufPtr, len, bufPtr[len], wantSaveToEmlFile); num++; } bufPtr += len; - bufPtr += ((len-1)/8+1); // ignore parity + bufPtr += parlen; // ignore parity } pckNum = 0; } diff --git a/client/mifarehost.c b/client/mifarehost.c index 471fbc42..e1ced176 100644 --- a/client/mifarehost.c +++ b/client/mifarehost.c @@ -20,6 +20,7 @@ #include "usb_cmd.h" #include "cmdmain.h" #include "ui.h" +#include "parity.h" #include "util.h" #include "iso14443crc.h" @@ -582,14 +583,19 @@ struct Crypto1State *traceCrypto1 = NULL; struct Crypto1State *revstate; uint64_t lfsr; +uint64_t ui64Key; uint32_t ks2; uint32_t ks3; -uint32_t uid; // serial number -uint32_t nt; // tag challenge -uint32_t nr_enc; // encrypted reader challenge -uint32_t ar_enc; // encrypted reader response -uint32_t at_enc; // encrypted tag response +uint32_t uid; // serial number +uint32_t nt; // tag challenge +uint32_t nt_enc; // encrypted tag challenge +uint8_t nt_enc_par; // encrypted tag challenge parity +uint32_t nr_enc; // encrypted reader challenge +uint32_t ar_enc; // encrypted reader response +uint8_t ar_enc_par; // encrypted reader response parity +uint32_t at_enc; // encrypted tag response +uint8_t at_enc_par; // encrypted tag response parity int isTraceCardEmpty(void) { return ((traceCard[0] == 0) && (traceCard[1] == 0) && (traceCard[2] == 0) && (traceCard[3] == 0)); @@ -708,8 +714,36 @@ void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len, bool i return; } +bool NTParityCheck(uint32_t ntx) { + if ( + (oddparity8(ntx >> 8 & 0xff) ^ (ntx & 0x01) ^ ((nt_enc_par >> 5) & 0x01) ^ (nt_enc & 0x01)) || + (oddparity8(ntx >> 16 & 0xff) ^ (ntx >> 8 & 0x01) ^ ((nt_enc_par >> 6) & 0x01) ^ (nt_enc >> 8 & 0x01)) || + (oddparity8(ntx >> 24 & 0xff) ^ (ntx >> 16 & 0x01) ^ ((nt_enc_par >> 7) & 0x01) ^ (nt_enc >> 16 & 0x01)) + ) + return false; + + uint32_t ar = prng_successor(ntx, 64); + if ( + (oddparity8(ar >> 8 & 0xff) ^ (ar & 0x01) ^ ((ar_enc_par >> 5) & 0x01) ^ (ar_enc & 0x01)) || + (oddparity8(ar >> 16 & 0xff) ^ (ar >> 8 & 0x01) ^ ((ar_enc_par >> 6) & 0x01) ^ (ar_enc >> 8 & 0x01)) || + (oddparity8(ar >> 24 & 0xff) ^ (ar >> 16 & 0x01) ^ ((ar_enc_par >> 7) & 0x01) ^ (ar_enc >> 16 & 0x01)) + ) + return false; -int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) { + uint32_t at = prng_successor(ntx, 96); + if ( + (oddparity8(ar & 0xff) ^ (at >> 24 & 0x01) ^ ((ar_enc_par >> 4) & 0x01) ^ (at_enc >> 24 & 0x01)) || + (oddparity8(at >> 8 & 0xff) ^ (at & 0x01) ^ ((at_enc_par >> 5) & 0x01) ^ (at_enc & 0x01)) || + (oddparity8(at >> 16 & 0xff) ^ (at >> 8 & 0x01) ^ ((at_enc_par >> 6) & 0x01) ^ (at_enc >> 8 & 0x01)) || + (oddparity8(at >> 24 & 0xff) ^ (at >> 16 & 0x01) ^ ((at_enc_par >> 7) & 0x01) ^ (at_enc >> 16 & 0x01)) + ) + return false; + + return true; +} + + +int mfTraceDecode(uint8_t *data_src, int len, uint8_t parity, bool wantSaveToEmlFile) { uint8_t data[64]; if (traceState == TRACE_ERROR) return 1; @@ -721,7 +755,9 @@ int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) { memcpy(data, data_src, len); if ((traceCrypto1) && ((traceState == TRACE_IDLE) || (traceState > TRACE_AUTH_OK))) { mf_crypto1_decrypt(traceCrypto1, data, len, 0); - PrintAndLog("dec> %s", sprint_hex(data, len)); + uint8_t parity[16]; + oddparitybuf(data, len, parity); + PrintAndLog("dec> %s [%s]", sprint_hex(data, len), printBitsPar(parity, len)); AddLogHex(logHexFileName, "dec> ", data, len); } @@ -810,7 +846,12 @@ int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) { case TRACE_AUTH1: if (len == 4) { traceState = TRACE_AUTH2; - nt = bytes_to_num(data, 4); + if (!traceCrypto1) { + nt = bytes_to_num(data, 4); + } else { + nt_enc = bytes_to_num(data, 4); + nt_enc_par = parity; + } return 0; } else { traceState = TRACE_ERROR; @@ -824,6 +865,7 @@ int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) { nr_enc = bytes_to_num(data, 4); ar_enc = bytes_to_num(data + 4, 4); + ar_enc_par = parity << 4; return 0; } else { traceState = TRACE_ERROR; @@ -835,8 +877,9 @@ int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) { if (len ==4) { traceState = TRACE_IDLE; + at_enc = bytes_to_num(data, 4); + at_enc_par = parity; if (!traceCrypto1) { - at_enc = bytes_to_num(data, 4); // decode key here) ks2 = ar_enc ^ prng_successor(nt, 64); @@ -848,16 +891,75 @@ int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) { lfsr_rollback_word(revstate, uid ^ nt, 0); crypto1_get_lfsr(revstate, &lfsr); - printf("key> %x%x\n", (unsigned int)((lfsr & 0xFFFFFFFF00000000) >> 32), (unsigned int)(lfsr & 0xFFFFFFFF)); + crypto1_destroy(revstate); + ui64Key = lfsr; + printf("key> probable key:%x%x Prng:%s ks2:%08x ks3:%08x\n", + (unsigned int)((lfsr & 0xFFFFFFFF00000000) >> 32), (unsigned int)(lfsr & 0xFFFFFFFF), + validate_prng_nonce(nt) ? "WEAK": "HARDEND", + ks2, + ks3); AddLogUint64(logHexFileName, "key> ", lfsr); } else { - printf("key> nested not implemented!\n"); - at_enc = bytes_to_num(data, 4); - - crypto1_destroy(traceCrypto1); + if (validate_prng_nonce(nt)) { + struct Crypto1State *pcs; + pcs = crypto1_create(ui64Key); + uint32_t nt1 = crypto1_word(pcs, nt_enc ^ uid, 1) ^ nt_enc; + uint32_t ar = prng_successor(nt1, 64); + uint32_t at = prng_successor(nt1, 96); + printf("key> nested auth uid: %08x nt: %08x nt_parity: %s ar: %08x at: %08x\n", uid, nt1, printBitsPar(&nt_enc_par, 4), ar, at); + uint32_t nr1 = crypto1_word(pcs, nr_enc, 1) ^ nr_enc; + uint32_t ar1 = crypto1_word(pcs, 0, 0) ^ ar_enc; + uint32_t at1 = crypto1_word(pcs, 0, 0) ^ at_enc; + printf("key> the same key test. nr1: %08x ar1: %08x at1: %08x \n", nr1, ar1, at1); - // not implemented - traceState = TRACE_ERROR; + if (NTParityCheck(nt1)) + printf("key> the same key test OK. key=%x%x\n", (unsigned int)((ui64Key & 0xFFFFFFFF00000000) >> 32), (unsigned int)(ui64Key & 0xFFFFFFFF)); + else + printf("key> the same key test. check nt parity error.\n"); + + uint32_t ntc = prng_successor(nt, 90); + uint32_t ntx = 0; + int ntcnt = 0; + for (int i = 0; i < 16383; i++) { + ntc = prng_successor(ntc, 1); + if (NTParityCheck(ntc)){ + if (!ntcnt) + ntx = ntc; + ntcnt++; + } + } + if (ntcnt) + printf("key> nt candidate=%08x nonce distance=%d candidates count=%d\n", ntx, nonce_distance(nt, ntx), ntcnt); + else + printf("key> don't have any nt candidate( \n"); + + nt = ntx; + ks2 = ar_enc ^ prng_successor(ntx, 64); + ks3 = at_enc ^ prng_successor(ntx, 96); + + // decode key + revstate = lfsr_recovery64(ks2, ks3); + lfsr_rollback_word(revstate, 0, 0); + lfsr_rollback_word(revstate, 0, 0); + lfsr_rollback_word(revstate, nr_enc, 1); + lfsr_rollback_word(revstate, uid ^ nt, 0); + + crypto1_get_lfsr(revstate, &lfsr); + crypto1_destroy(revstate); + ui64Key = lfsr; + printf("key> probable key:%x%x ks2:%08x ks3:%08x\n", + (unsigned int)((lfsr & 0xFFFFFFFF00000000) >> 32), (unsigned int)(lfsr & 0xFFFFFFFF), + ks2, + ks3); + AddLogUint64(logHexFileName, "key> ", lfsr); + } else { + printf("key> hardnested not implemented!\n"); + + crypto1_destroy(traceCrypto1); + + // not implemented + traceState = TRACE_ERROR; + } } int blockShift = ((traceCurBlock & 0xFC) + 3) * 16; diff --git a/client/mifarehost.h b/client/mifarehost.h index 031dac1b..bef397bb 100644 --- a/client/mifarehost.h +++ b/client/mifarehost.h @@ -50,7 +50,7 @@ extern int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, bool wantWi extern int mfCGetBlock(uint8_t blockNo, uint8_t *data, uint8_t params); extern int mfTraceInit(uint8_t *tuid, uint8_t *atqa, uint8_t sak, bool wantSaveToEmlFile); -extern int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile); +extern int mfTraceDecode(uint8_t *data_src, int len, uint8_t parity, bool wantSaveToEmlFile); extern int isTraceCardEmpty(void); extern int isBlockEmpty(int blockN); @@ -61,5 +61,6 @@ extern int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t extern int mfCIdentify(); extern int DetectClassicPrng(void); +extern bool validate_prng_nonce(uint32_t nonce); #endif diff --git a/client/util.c b/client/util.c index 7e6b4074..bbc7f2cf 100644 --- a/client/util.c +++ b/client/util.c @@ -356,6 +356,23 @@ char * printBits(size_t const size, void const * const ptr) return buf; } +char * printBitsPar(const uint8_t *b, size_t len) { + static char buf1[512] = {0}; + static char buf2[512] = {0}; + static char *buf; + if (buf != buf1) + buf = buf1; + else + buf = buf2; + memset(buf, 0x00, 512); + + for (int i = 0; i < len; i++) { + buf[i] = ((b[i / 8] << (i % 8)) & 0x80) ? '1':'0'; + } + return buf; +} + + // ------------------------------------------------------------------------- // string parameters lib // ------------------------------------------------------------------------- diff --git a/client/util.h b/client/util.h index fd7ceaff..2e64d7ca 100644 --- a/client/util.h +++ b/client/util.h @@ -54,6 +54,7 @@ extern uint64_t bytes_to_num(uint8_t* src, size_t len); extern void num_to_bytebits(uint64_t n, size_t len, uint8_t *dest); extern void num_to_bytebitsLSBF(uint64_t n, size_t len, uint8_t *dest); extern char *printBits(size_t const size, void const * const ptr); +extern char * printBitsPar(const uint8_t *b, size_t len); extern uint32_t SwapBits(uint32_t value, int nrbits); extern uint8_t *SwapEndian64(const uint8_t *src, const size_t len, const uint8_t blockSize); extern void SwapEndian64ex(const uint8_t *src, const size_t len, const uint8_t blockSize, uint8_t *dest); diff --git a/common/parity.h b/common/parity.h index 615fdeee..c574db55 100644 --- a/common/parity.h +++ b/common/parity.h @@ -13,6 +13,7 @@ #include #include +#include "string.h" extern const uint8_t OddByteParity[256]; @@ -21,6 +22,11 @@ static inline bool oddparity8(const uint8_t x) { return OddByteParity[x]; } +static inline void oddparitybuf(const uint8_t *x, size_t len, uint8_t *parity) { + memset(parity, 0x00, (len - 1) / 8 + 1); + for (int i = 0; i < len; i++) + parity[i / 8] |= oddparity8(x[i]) << (7 - (i % 8)); +} static inline bool evenparity8(const uint8_t x) { return !OddByteParity[x]; From 4f131b53ea7e9a66f5c7269fc35b11f8038cbf3e Mon Sep 17 00:00:00 2001 From: merlokk Date: Fri, 9 Feb 2018 17:37:31 +0200 Subject: [PATCH 060/127] added cmdhflist file --- client/Makefile | 1 + client/cmdhf.c | 7 +++++++ client/cmdhflist.c | 17 +++++++++++++++++ client/cmdhflist.h | 11 +++++++++++ common/protocols.h | 9 +++++---- 5 files changed, 41 insertions(+), 4 deletions(-) create mode 100644 client/cmdhflist.c create mode 100644 client/cmdhflist.h diff --git a/client/Makefile b/client/Makefile index bf642803..bf3c8d36 100644 --- a/client/Makefile +++ b/client/Makefile @@ -128,6 +128,7 @@ CMDSRCS = crapto1/crapto1.c\ emv/test/cda_test.c\ emv/cmdemv.c\ cmdhf.c \ + cmdhflist.c \ cmdhf14a.c \ cmdhf14b.c \ cmdhf15.c \ diff --git a/client/cmdhf.c b/client/cmdhf.c index 7a2f3252..34d95c50 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -1,5 +1,6 @@ //----------------------------------------------------------------------------- // Copyright (C) 2010 iZsh +// Merlok - 2017 // // This code is licensed to you under the terms of the GNU GPL, version 2 or, // at your option, any later version. See the LICENSE.txt file for the text of @@ -31,6 +32,7 @@ #include "cmdhftopaz.h" #include "protocols.h" #include "emv/cmdemv.h" +#include "cmdhflist.h" static int CmdHelp(const char *Cmd); @@ -466,6 +468,7 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui case TOPAZ: crcStatus = iso14443B_CRC_check(isResponse, frame, data_len); break; + case PROTO_MIFARE: case ISO_14443A: crcStatus = iso14443A_CRC_check(isResponse, frame, data_len); break; @@ -518,6 +521,7 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui { switch(protocol) { case ICLASS: annotateIclass(explanation,sizeof(explanation),frame,data_len); break; + case PROTO_MIFARE: case ISO_14443A: annotateIso14443a(explanation,sizeof(explanation),frame,data_len); break; case ISO_14443B: annotateIso14443b(explanation,sizeof(explanation),frame,data_len); break; case TOPAZ: annotateTopaz(explanation,sizeof(explanation),frame,data_len); break; @@ -583,6 +587,8 @@ int CmdHFList(const char *Cmd) if(!errors) { if(strcmp(type, "iclass") == 0) { protocol = ICLASS; + } else if(strcmp(type, "mf") == 0) { + protocol = PROTO_MIFARE; } else if(strcmp(type, "14a") == 0) { protocol = ISO_14443A; } else if(strcmp(type, "14b") == 0) { @@ -604,6 +610,7 @@ int CmdHFList(const char *Cmd) PrintAndLog("Supported values:"); PrintAndLog(" raw - just show raw data without annotations"); PrintAndLog(" 14a - interpret data as iso14443a communications"); + PrintAndLog(" mf - interpret data as iso14443a communications and decrypt crypto1 stream"); PrintAndLog(" 14b - interpret data as iso14443b communications"); PrintAndLog(" iclass - interpret data as iclass communications"); PrintAndLog(" topaz - interpret data as topaz communications"); diff --git a/client/cmdhflist.c b/client/cmdhflist.c new file mode 100644 index 00000000..86562e4c --- /dev/null +++ b/client/cmdhflist.c @@ -0,0 +1,17 @@ +//----------------------------------------------------------------------------- +// Copyright (C) Merlok - 2017 +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Command: hf mf list. It shows data from arm buffer. +//----------------------------------------------------------------------------- + +#include "cmdhflist.h" + +#include +#include +#include + + diff --git a/client/cmdhflist.h b/client/cmdhflist.h new file mode 100644 index 00000000..138e5590 --- /dev/null +++ b/client/cmdhflist.h @@ -0,0 +1,11 @@ +//----------------------------------------------------------------------------- +// Copyright (C) Merlok - 2017 +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Command: hf mf list. It shows data from arm buffer. +//----------------------------------------------------------------------------- + + diff --git a/common/protocols.h b/common/protocols.h index 31252ad3..57e6011f 100644 --- a/common/protocols.h +++ b/common/protocols.h @@ -200,10 +200,11 @@ NXP/Philips CUSTOM COMMANDS #define TOPAZ_WRITE_NE8 0x1B // Write-no-erase (eight bytes) -#define ISO_14443A 0 -#define ICLASS 1 -#define ISO_14443B 2 -#define TOPAZ 3 +#define ISO_14443A 0 +#define ICLASS 1 +#define ISO_14443B 2 +#define TOPAZ 3 +#define PROTO_MIFARE 4 //-- Picopass fuses #define FUSE_FPERS 0x80 From 6612a5a20136d0d4b11bd7f3fd113f4dd836119f Mon Sep 17 00:00:00 2001 From: merlokk Date: Fri, 9 Feb 2018 18:23:04 +0200 Subject: [PATCH 061/127] moved some functions and added auth sequence annotation --- client/cmdhf.c | 126 ++--------------------------- client/cmdhflist.c | 196 +++++++++++++++++++++++++++++++++++++++++++++ client/cmdhflist.h | 12 +++ 3 files changed, 213 insertions(+), 121 deletions(-) diff --git a/client/cmdhf.c b/client/cmdhf.c index 34d95c50..ae1b12a6 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -43,99 +43,6 @@ int CmdHFTune(const char *Cmd) return 0; } - -void annotateIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) -{ - switch(cmd[0]) - { - case ISO14443A_CMD_WUPA: snprintf(exp,size,"WUPA"); break; - case ISO14443A_CMD_ANTICOLL_OR_SELECT:{ - // 93 20 = Anticollision (usage: 9320 - answer: 4bytes UID+1byte UID-bytes-xor) - // 93 70 = Select (usage: 9370+5bytes 9320 answer - answer: 1byte SAK) - if(cmd[1] == 0x70) - { - snprintf(exp,size,"SELECT_UID"); break; - }else - { - snprintf(exp,size,"ANTICOLL"); break; - } - } - case ISO14443A_CMD_ANTICOLL_OR_SELECT_2:{ - //95 20 = Anticollision of cascade level2 - //95 70 = Select of cascade level2 - if(cmd[2] == 0x70) - { - snprintf(exp,size,"SELECT_UID-2"); break; - }else - { - snprintf(exp,size,"ANTICOLL-2"); break; - } - } - case ISO14443A_CMD_REQA: snprintf(exp,size,"REQA"); break; - case ISO14443A_CMD_READBLOCK: snprintf(exp,size,"READBLOCK(%d)",cmd[1]); break; - case ISO14443A_CMD_WRITEBLOCK: snprintf(exp,size,"WRITEBLOCK(%d)",cmd[1]); break; - case ISO14443A_CMD_HALT: snprintf(exp,size,"HALT"); break; - case ISO14443A_CMD_RATS: snprintf(exp,size,"RATS"); break; - case MIFARE_CMD_INC: snprintf(exp,size,"INC(%d)",cmd[1]); break; - case MIFARE_CMD_DEC: snprintf(exp,size,"DEC(%d)",cmd[1]); break; - case MIFARE_CMD_RESTORE: snprintf(exp,size,"RESTORE(%d)",cmd[1]); break; - case MIFARE_CMD_TRANSFER: snprintf(exp,size,"TRANSFER(%d)",cmd[1]); break; - case MIFARE_AUTH_KEYA:{ - if ( cmdsize > 3) - snprintf(exp,size,"AUTH-A(%d)",cmd[1]); - else - // case MIFARE_ULEV1_VERSION : both 0x60. - snprintf(exp,size,"EV1 VERSION"); - break; - } - case MIFARE_AUTH_KEYB: snprintf(exp,size,"AUTH-B(%d)",cmd[1]); break; - case MIFARE_MAGICWUPC1: snprintf(exp,size,"MAGIC WUPC1"); break; - case MIFARE_MAGICWUPC2: snprintf(exp,size,"MAGIC WUPC2"); break; - case MIFARE_MAGICWIPEC: snprintf(exp,size,"MAGIC WIPEC"); break; - case MIFARE_ULC_AUTH_1: snprintf(exp,size,"AUTH "); break; - case MIFARE_ULC_AUTH_2: snprintf(exp,size,"AUTH_ANSW"); break; - case MIFARE_ULEV1_AUTH: - if ( cmdsize == 7 ) - snprintf(exp,size,"PWD-AUTH KEY: 0x%02x%02x%02x%02x", cmd[1], cmd[2], cmd[3], cmd[4] ); - else - snprintf(exp,size,"PWD-AUTH"); - break; - case MIFARE_ULEV1_FASTREAD:{ - if ( cmdsize >=3 && cmd[2] <= 0xE6) - snprintf(exp,size,"READ RANGE (%d-%d)",cmd[1],cmd[2]); - else - snprintf(exp,size,"?"); - break; - } - case MIFARE_ULC_WRITE:{ - if ( cmd[1] < 0x21 ) - snprintf(exp,size,"WRITEBLOCK(%d)",cmd[1]); - else - snprintf(exp,size,"?"); - break; - } - case MIFARE_ULEV1_READ_CNT:{ - if ( cmd[1] < 5 ) - snprintf(exp,size,"READ CNT(%d)",cmd[1]); - else - snprintf(exp,size,"?"); - break; - } - case MIFARE_ULEV1_INCR_CNT:{ - if ( cmd[1] < 5 ) - snprintf(exp,size,"INCR(%d)",cmd[1]); - else - snprintf(exp,size,"?"); - break; - } - case MIFARE_ULEV1_READSIG: snprintf(exp,size,"READ_SIG"); break; - case MIFARE_ULEV1_CHECKTEAR: snprintf(exp,size,"CHK_TEARING(%d)",cmd[1]); break; - case MIFARE_ULEV1_VCSL: snprintf(exp,size,"VCSL"); break; - default: snprintf(exp,size,"?"); break; - } - return; -} - void annotateIclass(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) { switch(cmd[0]) @@ -246,33 +153,6 @@ void annotateIso14443b(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) } -/** - * @brief iso14443A_CRC_check Checks CRC in command or response - * @param isResponse - * @param data - * @param len - * @return 0 : CRC-command, CRC not ok - * 1 : CRC-command, CRC ok - * 2 : Not crc-command - */ - -uint8_t iso14443A_CRC_check(bool isResponse, uint8_t* data, uint8_t len) -{ - uint8_t b1,b2; - - if(len <= 2) return 2; - - if(isResponse & (len < 6)) return 2; - - ComputeCrc14443(CRC_14443_A, data, len-2, &b1, &b2); - if (b1 != data[len-2] || b2 != data[len-1]) { - return 0; - } else { - return 1; - } -} - - /** * @brief iso14443B_CRC_check Checks CRC in command or response * @param isResponse @@ -469,6 +349,8 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui crcStatus = iso14443B_CRC_check(isResponse, frame, data_len); break; case PROTO_MIFARE: + crcStatus = mifare_CRC_check(isResponse, frame, data_len); + break; case ISO_14443A: crcStatus = iso14443A_CRC_check(isResponse, frame, data_len); break; @@ -517,11 +399,13 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui EndOfTransmissionTimestamp = timestamp + duration; + if (protocol == PROTO_MIFARE) + annotateMifare(explanation, sizeof(explanation), frame, data_len, isResponse); + if(!isResponse) { switch(protocol) { case ICLASS: annotateIclass(explanation,sizeof(explanation),frame,data_len); break; - case PROTO_MIFARE: case ISO_14443A: annotateIso14443a(explanation,sizeof(explanation),frame,data_len); break; case ISO_14443B: annotateIso14443b(explanation,sizeof(explanation),frame,data_len); break; case TOPAZ: annotateTopaz(explanation,sizeof(explanation),frame,data_len); break; diff --git a/client/cmdhflist.c b/client/cmdhflist.c index 86562e4c..b1d432ee 100644 --- a/client/cmdhflist.c +++ b/client/cmdhflist.c @@ -13,5 +13,201 @@ #include #include #include +#include +#include +#include "util.h" +#include "data.h" +#include "ui.h" +#include "iso14443crc.h" +#include "parity.h" +#include "protocols.h" +enum MifareAuthSeq { + masNone, + masNt, + masNrAr, + masAt, + masData, + masDataNested, + masError, +}; +static enum MifareAuthSeq MifareAuthState; + +/** + * @brief iso14443A_CRC_check Checks CRC in command or response + * @param isResponse + * @param data + * @param len + * @return 0 : CRC-command, CRC not ok + * 1 : CRC-command, CRC ok + * 2 : Not crc-command + */ +uint8_t iso14443A_CRC_check(bool isResponse, uint8_t* data, uint8_t len) +{ + uint8_t b1,b2; + + if(len <= 2) return 2; + + if(isResponse & (len < 6)) return 2; + + ComputeCrc14443(CRC_14443_A, data, len-2, &b1, &b2); + if (b1 != data[len-2] || b2 != data[len-1]) { + return 0; + } else { + return 1; + } +} + +uint8_t mifare_CRC_check(bool isResponse, uint8_t* data, uint8_t len) +{ + switch(MifareAuthState) { + case masNone: + case masData: + case masDataNested: + case masError: + return iso14443A_CRC_check(isResponse, data, len); + default: + return 2; + } + +} + +void annotateIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) +{ + switch(cmd[0]) + { + case ISO14443A_CMD_WUPA: snprintf(exp,size,"WUPA"); break; + case ISO14443A_CMD_ANTICOLL_OR_SELECT:{ + // 93 20 = Anticollision (usage: 9320 - answer: 4bytes UID+1byte UID-bytes-xor) + // 93 70 = Select (usage: 9370+5bytes 9320 answer - answer: 1byte SAK) + if(cmd[1] == 0x70) + { + snprintf(exp,size,"SELECT_UID"); break; + }else + { + snprintf(exp,size,"ANTICOLL"); break; + } + } + case ISO14443A_CMD_ANTICOLL_OR_SELECT_2:{ + //95 20 = Anticollision of cascade level2 + //95 70 = Select of cascade level2 + if(cmd[2] == 0x70) + { + snprintf(exp,size,"SELECT_UID-2"); break; + }else + { + snprintf(exp,size,"ANTICOLL-2"); break; + } + } + case ISO14443A_CMD_REQA: snprintf(exp,size,"REQA"); break; + case ISO14443A_CMD_READBLOCK: snprintf(exp,size,"READBLOCK(%d)",cmd[1]); break; + case ISO14443A_CMD_WRITEBLOCK: snprintf(exp,size,"WRITEBLOCK(%d)",cmd[1]); break; + case ISO14443A_CMD_HALT: + snprintf(exp,size,"HALT"); + MifareAuthState = masNone; + break; + case ISO14443A_CMD_RATS: snprintf(exp,size,"RATS"); break; + case MIFARE_CMD_INC: snprintf(exp,size,"INC(%d)",cmd[1]); break; + case MIFARE_CMD_DEC: snprintf(exp,size,"DEC(%d)",cmd[1]); break; + case MIFARE_CMD_RESTORE: snprintf(exp,size,"RESTORE(%d)",cmd[1]); break; + case MIFARE_CMD_TRANSFER: snprintf(exp,size,"TRANSFER(%d)",cmd[1]); break; + case MIFARE_AUTH_KEYA: + if ( cmdsize > 3) { + snprintf(exp,size,"AUTH-A(%d)",cmd[1]); + MifareAuthState = masNt; + } else { + // case MIFARE_ULEV1_VERSION : both 0x60. + snprintf(exp,size,"EV1 VERSION"); + } + break; + case MIFARE_AUTH_KEYB: + MifareAuthState = masNt; + snprintf(exp,size,"AUTH-B(%d)",cmd[1]); + break; + case MIFARE_MAGICWUPC1: snprintf(exp,size,"MAGIC WUPC1"); break; + case MIFARE_MAGICWUPC2: snprintf(exp,size,"MAGIC WUPC2"); break; + case MIFARE_MAGICWIPEC: snprintf(exp,size,"MAGIC WIPEC"); break; + case MIFARE_ULC_AUTH_1: snprintf(exp,size,"AUTH "); break; + case MIFARE_ULC_AUTH_2: snprintf(exp,size,"AUTH_ANSW"); break; + case MIFARE_ULEV1_AUTH: + if ( cmdsize == 7 ) + snprintf(exp,size,"PWD-AUTH KEY: 0x%02x%02x%02x%02x", cmd[1], cmd[2], cmd[3], cmd[4] ); + else + snprintf(exp,size,"PWD-AUTH"); + break; + case MIFARE_ULEV1_FASTREAD:{ + if ( cmdsize >=3 && cmd[2] <= 0xE6) + snprintf(exp,size,"READ RANGE (%d-%d)",cmd[1],cmd[2]); + else + snprintf(exp,size,"?"); + break; + } + case MIFARE_ULC_WRITE:{ + if ( cmd[1] < 0x21 ) + snprintf(exp,size,"WRITEBLOCK(%d)",cmd[1]); + else + snprintf(exp,size,"?"); + break; + } + case MIFARE_ULEV1_READ_CNT:{ + if ( cmd[1] < 5 ) + snprintf(exp,size,"READ CNT(%d)",cmd[1]); + else + snprintf(exp,size,"?"); + break; + } + case MIFARE_ULEV1_INCR_CNT:{ + if ( cmd[1] < 5 ) + snprintf(exp,size,"INCR(%d)",cmd[1]); + else + snprintf(exp,size,"?"); + break; + } + case MIFARE_ULEV1_READSIG: snprintf(exp,size,"READ_SIG"); break; + case MIFARE_ULEV1_CHECKTEAR: snprintf(exp,size,"CHK_TEARING(%d)",cmd[1]); break; + case MIFARE_ULEV1_VCSL: snprintf(exp,size,"VCSL"); break; + default: snprintf(exp,size,"?"); break; + } + return; +} + +void annotateMifare(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize, bool isResponse) { + switch(MifareAuthState) { + case masNt: + if (cmdsize == 4) { + snprintf(exp,size,"AUTH: nt"); + MifareAuthState = masNrAr; + printf("--ntok\n"); + return; + } else { + MifareAuthState = masError; + printf("--err %d\n", cmdsize); + } + break; + case masNrAr: + if (cmdsize == 8) { + snprintf(exp,size,"AUTH: nr ar"); + MifareAuthState = masAt; + return; + } else { + MifareAuthState = masError; + } + break; + case masAt: + if (cmdsize == 4) { + snprintf(exp,size,"AUTH: at"); + MifareAuthState = masData; + return; + } else { + MifareAuthState = masError; + } + break; + default: + break; + } + + if (!isResponse) + annotateIso14443a(exp, size, cmd, cmdsize); + +} diff --git a/client/cmdhflist.h b/client/cmdhflist.h index 138e5590..9bed08ab 100644 --- a/client/cmdhflist.h +++ b/client/cmdhflist.h @@ -7,5 +7,17 @@ //----------------------------------------------------------------------------- // Command: hf mf list. It shows data from arm buffer. //----------------------------------------------------------------------------- +#ifndef CMDHFLIST_H +#define CMDHFLIST_H + +#include +#include +#include + +extern uint8_t iso14443A_CRC_check(bool isResponse, uint8_t* data, uint8_t len); +extern uint8_t mifare_CRC_check(bool isResponse, uint8_t* data, uint8_t len); +extern void annotateIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize); +extern void annotateMifare(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize, bool isResponse); +#endif // CMDHFLIST From 6c30a244eb553ed342318ad2ec11a45b2db3a909 Mon Sep 17 00:00:00 2001 From: merlokk Date: Fri, 9 Feb 2018 19:32:17 +0200 Subject: [PATCH 062/127] added some get auth data --- client/cmdhflist.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/client/cmdhflist.c b/client/cmdhflist.c index b1d432ee..a91df26a 100644 --- a/client/cmdhflist.c +++ b/client/cmdhflist.c @@ -70,7 +70,6 @@ uint8_t mifare_CRC_check(bool isResponse, uint8_t* data, uint8_t len) default: return 2; } - } void annotateIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) @@ -173,22 +172,33 @@ void annotateIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) } void annotateMifare(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize, bool isResponse) { +// uint32_t uid; // UID + static uint32_t nt; // tag challenge +// uint32_t nt_enc; // encrypted tag challenge +// uint8_t nt_enc_par; // encrypted tag challenge parity + static uint32_t nr_enc; // encrypted reader challenge + static uint32_t ar_enc; // encrypted reader response +// uint8_t ar_enc_par; // encrypted reader response parity + static uint32_t at_enc; // encrypted tag response +// uint8_t at_enc_par; // encrypted tag response parity + switch(MifareAuthState) { case masNt: if (cmdsize == 4) { - snprintf(exp,size,"AUTH: nt"); + snprintf(exp,size,"AUTH: nt %s", (MifareAuthState == masData) ? "(enc)" : ""); MifareAuthState = masNrAr; - printf("--ntok\n"); + nt = bytes_to_num(cmd, cmdsize); return; } else { MifareAuthState = masError; - printf("--err %d\n", cmdsize); } break; case masNrAr: if (cmdsize == 8) { - snprintf(exp,size,"AUTH: nr ar"); + snprintf(exp,size,"AUTH: nr ar (enc)"); MifareAuthState = masAt; + nr_enc = bytes_to_num(cmd, cmdsize); + ar_enc = bytes_to_num(&cmd[3], cmdsize); return; } else { MifareAuthState = masError; @@ -196,8 +206,9 @@ void annotateMifare(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize, bool break; case masAt: if (cmdsize == 4) { - snprintf(exp,size,"AUTH: at"); + snprintf(exp,size,"AUTH: at (enc)"); MifareAuthState = masData; + at_enc = bytes_to_num(cmd, cmdsize); return; } else { MifareAuthState = masError; From fb30f5a1013a4e37280c72dda7b37052e317634f Mon Sep 17 00:00:00 2001 From: merlokk Date: Fri, 9 Feb 2018 19:40:39 +0200 Subject: [PATCH 063/127] added check reader/tag --- client/cmdhflist.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/cmdhflist.c b/client/cmdhflist.c index a91df26a..065cbde2 100644 --- a/client/cmdhflist.c +++ b/client/cmdhflist.c @@ -184,8 +184,8 @@ void annotateMifare(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize, bool switch(MifareAuthState) { case masNt: - if (cmdsize == 4) { - snprintf(exp,size,"AUTH: nt %s", (MifareAuthState == masData) ? "(enc)" : ""); + if (cmdsize == 4 && isResponse) { + snprintf(exp,size,"AUTH: nt %s", (nt) ? "(enc)" : ""); MifareAuthState = masNrAr; nt = bytes_to_num(cmd, cmdsize); return; @@ -194,7 +194,7 @@ void annotateMifare(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize, bool } break; case masNrAr: - if (cmdsize == 8) { + if (cmdsize == 8 && !isResponse) { snprintf(exp,size,"AUTH: nr ar (enc)"); MifareAuthState = masAt; nr_enc = bytes_to_num(cmd, cmdsize); @@ -205,7 +205,7 @@ void annotateMifare(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize, bool } break; case masAt: - if (cmdsize == 4) { + if (cmdsize == 4 && isResponse) { snprintf(exp,size,"AUTH: at (enc)"); MifareAuthState = masData; at_enc = bytes_to_num(cmd, cmdsize); From 61e96805add5df3ceade89eaafed4695fa31a422 Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Fri, 9 Feb 2018 15:49:55 -0500 Subject: [PATCH 064/127] add bitbang option to lf cmdread by setting delay to 0 we can use cmd binary to bitbang the antenna. note that the timing isn't perfect (especially on the off periods) but is fairly close. worst i've seen it off is 8us on a large off period. but i don't have the best test equipment... --- armsrc/lfops.c | 79 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 63 insertions(+), 16 deletions(-) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 4344742b..5e9fb193 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -29,6 +29,7 @@ void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint32_t period_1, uint8_t *command) { + StartTicks(); int divisor_used = 95; // 125 KHz // see if 'h' was specified @@ -43,36 +44,82 @@ void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint /* Make sure the tag is reset */ FpgaDownloadAndGo(FPGA_BITSTREAM_LF); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - SpinDelay(2500); + WaitMS(2500); + //power on LFSetupFPGAForADC(sc.divisor, 1); // And a little more time for the tag to fully power up - SpinDelay(2000); - + WaitMS(2000); + // if delay_off = 0 then just bitbang 1 = antenna on 0 = off for respective periods. + bool bitbang = delay_off == 0; // now modulate the reader field - while(*command != '\0' && *command != ' ') { + + if (bitbang) { + //HACK it appears my loop and if statements take up about 7 us so adjust waits accordingly... + uint8_t hack_cnt = 7; + if (period_0 < hack_cnt || period_1 < hack_cnt) { + DbpString("Warning periods cannot be less than 7 in bit bang mode"); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LED_D_OFF(); + return; + } + //prime cmd_len to save time comparing strings while modulating + int cmd_len = 0; + while(command[cmd_len] != '\0' && command[cmd_len] != ' ') + cmd_len++; + + int counter = 0; + bool off = false; + for (counter = 0; counter < cmd_len; counter++) { + //while(*command != '\0' && *command != ' ') { + // if cmd = 0 then turn field off + if (command[counter] == '0') { + // if field already off leave alone (affects timing otherwise) + if (off == false) { + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LED_D_OFF(); + off = true; + } + // note we appear to take about 6us to switch over (or run the if statements/loop...) + WaitUS(period_0-hack_cnt); + // else if cmd = 1 then turn field on + } else { + // if field already on leave alone (affects timing otherwise) + if (off) { + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); + LED_D_ON(); + off = false; + } + // note we appear to take about 6us to switch over (or run the if statements/loop...) + WaitUS(period_1-hack_cnt); + } + } + } else { // old mode of cmd read using delay as off period + while(*command != '\0' && *command != ' ') { + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LED_D_OFF(); + WaitUS(delay_off); + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, sc.divisor); + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); + LED_D_ON(); + if(*(command++) == '0') { + WaitUS(period_0); + } else { + WaitUS(period_1); + } + } FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LED_D_OFF(); - SpinDelayUs(delay_off); + WaitUS(delay_off); FpgaSendCommand(FPGA_CMD_SET_DIVISOR, sc.divisor); - - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); - LED_D_ON(); - if(*(command++) == '0') - SpinDelayUs(period_0); - else - SpinDelayUs(period_1); } - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LED_D_OFF(); - SpinDelayUs(delay_off); - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, sc.divisor); FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); // now do the read DoAcquisition_config(false, 0); + // note leaves field on... (for future commands?) } /* blank r/w tag data stream From aadc6bf1e162316eab391ca2ca61d05bdac7db80 Mon Sep 17 00:00:00 2001 From: Oleg Moiseenko Date: Sat, 10 Feb 2018 19:03:29 +0200 Subject: [PATCH 065/127] combine all auth data to single struct and fill it --- client/cmdhf.c | 1 + client/cmdhflist.c | 46 ++++++++++++++++++++++++++++++---------------- client/cmdhflist.h | 14 ++++++++++++++ 3 files changed, 45 insertions(+), 16 deletions(-) diff --git a/client/cmdhf.c b/client/cmdhf.c index ae1b12a6..2557607b 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -543,6 +543,7 @@ int CmdHFList(const char *Cmd) PrintAndLog(" Start | End | Src | Data (! denotes parity error) | CRC | Annotation |"); PrintAndLog("------------|------------|-----|-----------------------------------------------------------------|-----|--------------------|"); + ClearAuthData(); while(tracepos < traceLen) { tracepos = printTraceLine(tracepos, traceLen, trace, protocol, showWaitCycles, markCRCBytes); diff --git a/client/cmdhflist.c b/client/cmdhflist.c index 065cbde2..ec710b2c 100644 --- a/client/cmdhflist.c +++ b/client/cmdhflist.c @@ -28,11 +28,19 @@ enum MifareAuthSeq { masNt, masNrAr, masAt, + masFirstData, masData, masDataNested, masError, }; static enum MifareAuthSeq MifareAuthState; +static TAuthData AuthData; + +void ClearAuthData() { + AuthData.uid = 0; + AuthData.nt = 0; + AuthData.first_auth = false; +} /** * @brief iso14443A_CRC_check Checks CRC in command or response @@ -63,6 +71,7 @@ uint8_t mifare_CRC_check(bool isResponse, uint8_t* data, uint8_t len) { switch(MifareAuthState) { case masNone: + case masFirstData: case masData: case masDataNested: case masError: @@ -172,22 +181,27 @@ void annotateIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) } void annotateMifare(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize, bool isResponse) { -// uint32_t uid; // UID - static uint32_t nt; // tag challenge -// uint32_t nt_enc; // encrypted tag challenge -// uint8_t nt_enc_par; // encrypted tag challenge parity - static uint32_t nr_enc; // encrypted reader challenge - static uint32_t ar_enc; // encrypted reader response -// uint8_t ar_enc_par; // encrypted reader response parity - static uint32_t at_enc; // encrypted tag response -// uint8_t at_enc_par; // encrypted tag response parity - + // get UID + if (MifareAuthState == masNone) { + if (cmdsize == 7 && cmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && cmd[1] == 0x70) { + ClearAuthData(); + AuthData.uid = bytes_to_num(&cmd[2], 4); + } + if (cmdsize == 7 && cmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2 && cmd[1] == 0x70) { + ClearAuthData(); + AuthData.uid = bytes_to_num(&cmd[2], 4); + } + } + switch(MifareAuthState) { case masNt: if (cmdsize == 4 && isResponse) { - snprintf(exp,size,"AUTH: nt %s", (nt) ? "(enc)" : ""); + snprintf(exp,size,"AUTH: nt %s", (AuthData.first_auth) ? "" : "(enc)"); MifareAuthState = masNrAr; - nt = bytes_to_num(cmd, cmdsize); + if (AuthData.first_auth) + AuthData.nt = bytes_to_num(cmd, cmdsize); + else + AuthData.nt_enc = bytes_to_num(cmd, cmdsize); return; } else { MifareAuthState = masError; @@ -197,8 +211,8 @@ void annotateMifare(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize, bool if (cmdsize == 8 && !isResponse) { snprintf(exp,size,"AUTH: nr ar (enc)"); MifareAuthState = masAt; - nr_enc = bytes_to_num(cmd, cmdsize); - ar_enc = bytes_to_num(&cmd[3], cmdsize); + AuthData.nr_enc = bytes_to_num(cmd, cmdsize); + AuthData.ar_enc = bytes_to_num(&cmd[3], cmdsize); return; } else { MifareAuthState = masError; @@ -207,8 +221,8 @@ void annotateMifare(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize, bool case masAt: if (cmdsize == 4 && isResponse) { snprintf(exp,size,"AUTH: at (enc)"); - MifareAuthState = masData; - at_enc = bytes_to_num(cmd, cmdsize); + MifareAuthState = masFirstData; + AuthData.at_enc = bytes_to_num(cmd, cmdsize); return; } else { MifareAuthState = masError; diff --git a/client/cmdhflist.h b/client/cmdhflist.h index 9bed08ab..6ec2f6fc 100644 --- a/client/cmdhflist.h +++ b/client/cmdhflist.h @@ -14,6 +14,20 @@ #include #include +typedef struct { + uint32_t uid; // UID + uint32_t nt; // tag challenge + uint32_t nt_enc; // encrypted tag challenge + uint8_t nt_enc_par; // encrypted tag challenge parity + uint32_t nr_enc; // encrypted reader challenge + uint32_t ar_enc; // encrypted reader response + uint8_t ar_enc_par; // encrypted reader response parity + uint32_t at_enc; // encrypted tag response + uint8_t at_enc_par; // encrypted tag response parity + bool first_auth; // is first authentication +} TAuthData; +extern void ClearAuthData(); + extern uint8_t iso14443A_CRC_check(bool isResponse, uint8_t* data, uint8_t len); extern uint8_t mifare_CRC_check(bool isResponse, uint8_t* data, uint8_t len); extern void annotateIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize); From a31f7f899b6d62c94bc236fce4330d6bbb8996e7 Mon Sep 17 00:00:00 2001 From: Oleg Moiseenko Date: Sat, 10 Feb 2018 19:06:34 +0200 Subject: [PATCH 066/127] small fix --- client/cmdhflist.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/client/cmdhflist.c b/client/cmdhflist.c index ec710b2c..8e7b7f6e 100644 --- a/client/cmdhflist.c +++ b/client/cmdhflist.c @@ -85,7 +85,10 @@ void annotateIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) { switch(cmd[0]) { - case ISO14443A_CMD_WUPA: snprintf(exp,size,"WUPA"); break; + case ISO14443A_CMD_WUPA: + snprintf(exp,size,"WUPA"); + MifareAuthState = masNone; + break; case ISO14443A_CMD_ANTICOLL_OR_SELECT:{ // 93 20 = Anticollision (usage: 9320 - answer: 4bytes UID+1byte UID-bytes-xor) // 93 70 = Select (usage: 9370+5bytes 9320 answer - answer: 1byte SAK) @@ -108,7 +111,10 @@ void annotateIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) snprintf(exp,size,"ANTICOLL-2"); break; } } - case ISO14443A_CMD_REQA: snprintf(exp,size,"REQA"); break; + case ISO14443A_CMD_REQA: + snprintf(exp,size,"REQA"); + MifareAuthState = masNone; + break; case ISO14443A_CMD_READBLOCK: snprintf(exp,size,"READBLOCK(%d)",cmd[1]); break; case ISO14443A_CMD_WRITEBLOCK: snprintf(exp,size,"WRITEBLOCK(%d)",cmd[1]); break; case ISO14443A_CMD_HALT: From b957bcd382bf718f766c0774839752eb99f668af Mon Sep 17 00:00:00 2001 From: Oleg Moiseenko Date: Sat, 10 Feb 2018 19:19:56 +0200 Subject: [PATCH 067/127] added get parity --- client/cmdhf.c | 5 ++++- client/cmdhflist.c | 5 ++++- client/cmdhflist.h | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/client/cmdhf.c b/client/cmdhf.c index 2557607b..3256b69a 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -400,7 +400,7 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui EndOfTransmissionTimestamp = timestamp + duration; if (protocol == PROTO_MIFARE) - annotateMifare(explanation, sizeof(explanation), frame, data_len, isResponse); + annotateMifare(explanation, sizeof(explanation), frame, data_len, parityBytes, parity_len, isResponse); if(!isResponse) { @@ -430,6 +430,9 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui (j == num_lines-1) ? explanation : ""); } } + +// if (DecodeMifareData(frame, data_len, isResponse)) { +// }; if (is_last_record(tracepos, trace, traceLen)) return traceLen; diff --git a/client/cmdhflist.c b/client/cmdhflist.c index 8e7b7f6e..5ff3192b 100644 --- a/client/cmdhflist.c +++ b/client/cmdhflist.c @@ -186,7 +186,7 @@ void annotateIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) return; } -void annotateMifare(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize, bool isResponse) { +void annotateMifare(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize, uint8_t* parity, uint8_t paritysize, bool isResponse) { // get UID if (MifareAuthState == masNone) { if (cmdsize == 7 && cmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && cmd[1] == 0x70) { @@ -208,6 +208,7 @@ void annotateMifare(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize, bool AuthData.nt = bytes_to_num(cmd, cmdsize); else AuthData.nt_enc = bytes_to_num(cmd, cmdsize); + AuthData.nt_enc_par = parity[0]; return; } else { MifareAuthState = masError; @@ -219,6 +220,7 @@ void annotateMifare(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize, bool MifareAuthState = masAt; AuthData.nr_enc = bytes_to_num(cmd, cmdsize); AuthData.ar_enc = bytes_to_num(&cmd[3], cmdsize); + AuthData.ar_enc_par = parity[0] << 4; return; } else { MifareAuthState = masError; @@ -229,6 +231,7 @@ void annotateMifare(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize, bool snprintf(exp,size,"AUTH: at (enc)"); MifareAuthState = masFirstData; AuthData.at_enc = bytes_to_num(cmd, cmdsize); + AuthData.at_enc_par = parity[0]; return; } else { MifareAuthState = masError; diff --git a/client/cmdhflist.h b/client/cmdhflist.h index 6ec2f6fc..329df7db 100644 --- a/client/cmdhflist.h +++ b/client/cmdhflist.h @@ -31,7 +31,7 @@ extern void ClearAuthData(); extern uint8_t iso14443A_CRC_check(bool isResponse, uint8_t* data, uint8_t len); extern uint8_t mifare_CRC_check(bool isResponse, uint8_t* data, uint8_t len); extern void annotateIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize); -extern void annotateMifare(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize, bool isResponse); +extern void annotateMifare(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize, uint8_t* parity, uint8_t paritysize, bool isResponse); #endif // CMDHFLIST From 7b215d149ac4fd5709635111d86a2062fc7ac3ad Mon Sep 17 00:00:00 2001 From: Oleg Moiseenko Date: Sat, 10 Feb 2018 20:28:30 +0200 Subject: [PATCH 068/127] correct 1st key calculation --- client/cmdhf.c | 10 ++++++-- client/cmdhflist.c | 62 ++++++++++++++++++++++++++++++++++++++++------ client/cmdhflist.h | 2 +- 3 files changed, 63 insertions(+), 11 deletions(-) diff --git a/client/cmdhf.c b/client/cmdhf.c index 3256b69a..9f3ff4e4 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -300,6 +300,8 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui uint8_t topaz_reader_command[9]; uint32_t timestamp, first_timestamp, EndOfTransmissionTimestamp; char explanation[30] = {0}; + uint8_t mfData[32] = {0}; + size_t mfDataLen = 0; if (tracepos + sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t) > traceLen) return traceLen; @@ -431,8 +433,12 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui } } -// if (DecodeMifareData(frame, data_len, isResponse)) { -// }; + if (DecodeMifareData(frame, data_len, isResponse, mfData, &mfDataLen)) { + PrintAndLog(" | | |%-64s | %s| %s", + sprint_hex(mfData, mfDataLen), + "", + (false) ? explanation : ""); + }; if (is_last_record(tracepos, trace, traceLen)) return traceLen; diff --git a/client/cmdhflist.c b/client/cmdhflist.c index 5ff3192b..0eaafa68 100644 --- a/client/cmdhflist.c +++ b/client/cmdhflist.c @@ -21,6 +21,8 @@ #include "iso14443crc.h" #include "parity.h" #include "protocols.h" +#include "crapto1/crapto1.h" +#include "mifarehost.h" enum MifareAuthSeq { @@ -39,7 +41,7 @@ static TAuthData AuthData; void ClearAuthData() { AuthData.uid = 0; AuthData.nt = 0; - AuthData.first_auth = false; + AuthData.first_auth = true; } /** @@ -189,11 +191,11 @@ void annotateIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) void annotateMifare(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize, uint8_t* parity, uint8_t paritysize, bool isResponse) { // get UID if (MifareAuthState == masNone) { - if (cmdsize == 7 && cmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && cmd[1] == 0x70) { + if (cmdsize == 9 && cmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && cmd[1] == 0x70) { ClearAuthData(); AuthData.uid = bytes_to_num(&cmd[2], 4); } - if (cmdsize == 7 && cmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2 && cmd[1] == 0x70) { + if (cmdsize == 9 && cmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2 && cmd[1] == 0x70) { ClearAuthData(); AuthData.uid = bytes_to_num(&cmd[2], 4); } @@ -205,9 +207,9 @@ void annotateMifare(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize, uint8 snprintf(exp,size,"AUTH: nt %s", (AuthData.first_auth) ? "" : "(enc)"); MifareAuthState = masNrAr; if (AuthData.first_auth) - AuthData.nt = bytes_to_num(cmd, cmdsize); + AuthData.nt = bytes_to_num(cmd, 4); else - AuthData.nt_enc = bytes_to_num(cmd, cmdsize); + AuthData.nt_enc = bytes_to_num(cmd, 4); AuthData.nt_enc_par = parity[0]; return; } else { @@ -218,8 +220,8 @@ void annotateMifare(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize, uint8 if (cmdsize == 8 && !isResponse) { snprintf(exp,size,"AUTH: nr ar (enc)"); MifareAuthState = masAt; - AuthData.nr_enc = bytes_to_num(cmd, cmdsize); - AuthData.ar_enc = bytes_to_num(&cmd[3], cmdsize); + AuthData.nr_enc = bytes_to_num(cmd, 4); + AuthData.ar_enc = bytes_to_num(&cmd[4], 4); AuthData.ar_enc_par = parity[0] << 4; return; } else { @@ -230,7 +232,7 @@ void annotateMifare(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize, uint8 if (cmdsize == 4 && isResponse) { snprintf(exp,size,"AUTH: at (enc)"); MifareAuthState = masFirstData; - AuthData.at_enc = bytes_to_num(cmd, cmdsize); + AuthData.at_enc = bytes_to_num(cmd, 4); AuthData.at_enc_par = parity[0]; return; } else { @@ -245,3 +247,47 @@ void annotateMifare(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize, uint8 annotateIso14443a(exp, size, cmd, cmdsize); } + +bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, bool isResponse, uint8_t *mfData, size_t *mfDataLen) { + *mfDataLen = 0; + + if (cmdsize > 32) + return false; + + if (MifareAuthState == masFirstData) { + if (AuthData.first_auth) { + uint32_t ks2 = AuthData.ar_enc ^ prng_successor(AuthData.nt, 64); + uint32_t ks3 = AuthData.at_enc ^ prng_successor(AuthData.nt, 96); + struct Crypto1State *revstate = lfsr_recovery64(ks2, ks3); + lfsr_rollback_word(revstate, 0, 0); + lfsr_rollback_word(revstate, 0, 0); + lfsr_rollback_word(revstate, AuthData.nr_enc, 1); + lfsr_rollback_word(revstate, AuthData.uid ^ AuthData.nt, 0); + + uint64_t lfsr = 0; + crypto1_get_lfsr(revstate, &lfsr); + crypto1_destroy(revstate); +// LastKey = lfsr; + printf("uid:%x nt:%x ar_enc:%x at_enc:%x\n", AuthData.uid, AuthData.nt, AuthData.ar_enc, AuthData.at_enc); + printf("AUTH: probable key:%x%x Prng:%s ks2:%08x ks3:%08x\n", + (unsigned int)((lfsr & 0xFFFFFFFF00000000) >> 32), (unsigned int)(lfsr & 0xFFFFFFFF), + validate_prng_nonce(AuthData.nt) ? "WEAK": "HARDEND", + ks2, + ks3); + + AuthData.first_auth = false; + } else { + } + + + + MifareAuthState = masData; + return true; + } + + if (MifareAuthState == masData) { + } + + return *mfDataLen > 0; +} + diff --git a/client/cmdhflist.h b/client/cmdhflist.h index 329df7db..7d95cc1c 100644 --- a/client/cmdhflist.h +++ b/client/cmdhflist.h @@ -32,6 +32,6 @@ extern uint8_t iso14443A_CRC_check(bool isResponse, uint8_t* data, uint8_t len); extern uint8_t mifare_CRC_check(bool isResponse, uint8_t* data, uint8_t len); extern void annotateIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize); extern void annotateMifare(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize, uint8_t* parity, uint8_t paritysize, bool isResponse); - +extern bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, bool isResponse, uint8_t *mfData, size_t *mfDataLen); #endif // CMDHFLIST From 28ee794f59aac1fac7aa18bfbaa4050d48a90260 Mon Sep 17 00:00:00 2001 From: Oleg Moiseenko Date: Sat, 10 Feb 2018 20:41:56 +0200 Subject: [PATCH 069/127] fix appearance --- client/cmdhf.c | 6 ++++-- client/cmdhflist.c | 6 +++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/client/cmdhf.c b/client/cmdhf.c index 9f3ff4e4..00b1aa8d 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -434,10 +434,12 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui } if (DecodeMifareData(frame, data_len, isResponse, mfData, &mfDataLen)) { - PrintAndLog(" | | |%-64s | %s| %s", + annotateIso14443a(explanation, sizeof(explanation), mfData, mfDataLen); + + PrintAndLog(" | * | dec |%-64s | %-4s| %s", sprint_hex(mfData, mfDataLen), "", - (false) ? explanation : ""); + (true) ? explanation : ""); }; if (is_last_record(tracepos, trace, traceLen)) return traceLen; diff --git a/client/cmdhflist.c b/client/cmdhflist.c index 0eaafa68..3dd03970 100644 --- a/client/cmdhflist.c +++ b/client/cmdhflist.c @@ -268,15 +268,15 @@ bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, bool isResponse, uint8_t *m crypto1_get_lfsr(revstate, &lfsr); crypto1_destroy(revstate); // LastKey = lfsr; - printf("uid:%x nt:%x ar_enc:%x at_enc:%x\n", AuthData.uid, AuthData.nt, AuthData.ar_enc, AuthData.at_enc); - printf("AUTH: probable key:%x%x Prng:%s ks2:%08x ks3:%08x\n", + PrintAndLog(" | * | key | probable key:%x%x Prng:%s ks2:%08x ks3:%08x | |", (unsigned int)((lfsr & 0xFFFFFFFF00000000) >> 32), (unsigned int)(lfsr & 0xFFFFFFFF), - validate_prng_nonce(AuthData.nt) ? "WEAK": "HARDEND", + validate_prng_nonce(AuthData.nt) ? "WEAK": "HARD", ks2, ks3); AuthData.first_auth = false; } else { + printf("uid:%x nt:%x ar_enc:%x at_enc:%x\n", AuthData.uid, AuthData.nt, AuthData.ar_enc, AuthData.at_enc); } From edd4c8385b3d6efb1467f5cee3c9ad5fe1491d11 Mon Sep 17 00:00:00 2001 From: Oleg Moiseenko Date: Sat, 10 Feb 2018 22:10:38 +0200 Subject: [PATCH 070/127] small fix util.c --- client/util.c | 1 + 1 file changed, 1 insertion(+) diff --git a/client/util.c b/client/util.c index bbc7f2cf..5dc9a455 100644 --- a/client/util.c +++ b/client/util.c @@ -116,6 +116,7 @@ void hex_to_buffer(const uint8_t *buf, const uint8_t *hex_data, const size_t hex char *tmp = (char *)buf; size_t i; + memset(tmp, 0x00, hex_max_len); int maxLen = ( hex_len > hex_max_len) ? hex_max_len : hex_len; From 747885a6ed9670c06a17140dd5385a9bac25c6b0 Mon Sep 17 00:00:00 2001 From: Oleg Moiseenko Date: Sat, 10 Feb 2018 22:33:32 +0200 Subject: [PATCH 071/127] hf list mf 1st auth works --- client/cmdhf.c | 10 +++++++--- client/cmdhflist.c | 44 +++++++++++++++++++++++++++++++++++--------- client/mifarehost.h | 2 ++ 3 files changed, 44 insertions(+), 12 deletions(-) diff --git a/client/cmdhf.c b/client/cmdhf.c index 00b1aa8d..06382abb 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -434,11 +434,15 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui } if (DecodeMifareData(frame, data_len, isResponse, mfData, &mfDataLen)) { - annotateIso14443a(explanation, sizeof(explanation), mfData, mfDataLen); - + memset(explanation, 0x00, sizeof(explanation)); + if (!isResponse) { + explanation[0] = '>'; + annotateIso14443a(&explanation[1], sizeof(explanation) - 1, mfData, mfDataLen); + } + uint8_t crcc = iso14443A_CRC_check(isResponse, mfData, mfDataLen); PrintAndLog(" | * | dec |%-64s | %-4s| %s", sprint_hex(mfData, mfDataLen), - "", + (crcc == 0 ? "!crc" : (crcc == 1 ? " ok " : " ")), (true) ? explanation : ""); }; diff --git a/client/cmdhflist.c b/client/cmdhflist.c index 3dd03970..43e0e562 100644 --- a/client/cmdhflist.c +++ b/client/cmdhflist.c @@ -30,9 +30,9 @@ enum MifareAuthSeq { masNt, masNrAr, masAt, + masAuthComplete, masFirstData, masData, - masDataNested, masError, }; static enum MifareAuthSeq MifareAuthState; @@ -73,9 +73,6 @@ uint8_t mifare_CRC_check(bool isResponse, uint8_t* data, uint8_t len) { switch(MifareAuthState) { case masNone: - case masFirstData: - case masData: - case masDataNested: case masError: return iso14443A_CRC_check(isResponse, data, len); default: @@ -231,7 +228,7 @@ void annotateMifare(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize, uint8 case masAt: if (cmdsize == 4 && isResponse) { snprintf(exp,size,"AUTH: at (enc)"); - MifareAuthState = masFirstData; + MifareAuthState = masAuthComplete; AuthData.at_enc = bytes_to_num(cmd, 4); AuthData.at_enc_par = parity[0]; return; @@ -243,14 +240,26 @@ void annotateMifare(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize, uint8 break; } - if (!isResponse) + if (!isResponse && ((MifareAuthState == masNone) || (MifareAuthState == masError))) annotateIso14443a(exp, size, cmd, cmdsize); } bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, bool isResponse, uint8_t *mfData, size_t *mfDataLen) { + static struct Crypto1State *traceCrypto1; + uint64_t mfLastKey; + *mfDataLen = 0; + if (MifareAuthState == masAuthComplete) { + if (traceCrypto1) { + crypto1_destroy(traceCrypto1); + } + + MifareAuthState = masFirstData; + return false; + } + if (cmdsize > 32) return false; @@ -267,7 +276,7 @@ bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, bool isResponse, uint8_t *m uint64_t lfsr = 0; crypto1_get_lfsr(revstate, &lfsr); crypto1_destroy(revstate); -// LastKey = lfsr; + mfLastKey = lfsr; PrintAndLog(" | * | key | probable key:%x%x Prng:%s ks2:%08x ks3:%08x | |", (unsigned int)((lfsr & 0xFFFFFFFF00000000) >> 32), (unsigned int)(lfsr & 0xFFFFFFFF), validate_prng_nonce(AuthData.nt) ? "WEAK": "HARD", @@ -275,17 +284,34 @@ bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, bool isResponse, uint8_t *m ks3); AuthData.first_auth = false; + + traceCrypto1 = lfsr_recovery64(ks2, ks3); } else { printf("uid:%x nt:%x ar_enc:%x at_enc:%x\n", AuthData.uid, AuthData.nt, AuthData.ar_enc, AuthData.at_enc); + + // check last used key + if (mfLastKey) { + + } + + // check default keys + + // nested + if (validate_prng_nonce(AuthData.nt)) { + } + + //hardnested } MifareAuthState = masData; - return true; } - if (MifareAuthState == masData) { + if (MifareAuthState == masData && traceCrypto1) { + memcpy(mfData, cmd, cmdsize); + mf_crypto1_decrypt(traceCrypto1, mfData, cmdsize, 0); + *mfDataLen = cmdsize; } return *mfDataLen > 0; diff --git a/client/mifarehost.h b/client/mifarehost.h index bef397bb..457a879f 100644 --- a/client/mifarehost.h +++ b/client/mifarehost.h @@ -14,6 +14,7 @@ #include #include #include "data.h" +#include "crapto1/crapto1.h" // defaults // timeout in units. (ms * 106)/10 or us*0.0106 @@ -62,5 +63,6 @@ extern int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t extern int mfCIdentify(); extern int DetectClassicPrng(void); extern bool validate_prng_nonce(uint32_t nonce); +extern void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len, bool isEncrypted); #endif From c6a886fb4f25b8925956a267ed3d2f60455adf4a Mon Sep 17 00:00:00 2001 From: Oleg Moiseenko Date: Sat, 10 Feb 2018 23:06:01 +0200 Subject: [PATCH 072/127] added mock of key check --- client/cmdhflist.c | 13 ++++++++++++- client/cmdhflist.h | 1 + 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/client/cmdhflist.c b/client/cmdhflist.c index 43e0e562..30249579 100644 --- a/client/cmdhflist.c +++ b/client/cmdhflist.c @@ -23,6 +23,7 @@ #include "protocols.h" #include "crapto1/crapto1.h" #include "mifarehost.h" +#include "mifaredefault.h" enum MifareAuthSeq { @@ -291,10 +292,17 @@ bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, bool isResponse, uint8_t *m // check last used key if (mfLastKey) { - + if (NestedCheckKey(mfLastKey, &AuthData, cmd, cmdsize)) { + }; } // check default keys + for (int defaultKeyCounter = 0; defaultKeyCounter < MifareDefaultKeysSize; defaultKeyCounter++){ + if (NestedCheckKey(MifareDefaultKeys[defaultKeyCounter], &AuthData, cmd, cmdsize)) { + + break; + }; + } // nested if (validate_prng_nonce(AuthData.nt)) { @@ -317,3 +325,6 @@ bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, bool isResponse, uint8_t *m return *mfDataLen > 0; } +bool NestedCheckKey(uint64_t key, TAuthData *ad, uint8_t *cmd, uint8_t cmdsize) { + return false; +} \ No newline at end of file diff --git a/client/cmdhflist.h b/client/cmdhflist.h index 7d95cc1c..d0298de5 100644 --- a/client/cmdhflist.h +++ b/client/cmdhflist.h @@ -33,5 +33,6 @@ extern uint8_t mifare_CRC_check(bool isResponse, uint8_t* data, uint8_t len); extern void annotateIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize); extern void annotateMifare(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize, uint8_t* parity, uint8_t paritysize, bool isResponse); extern bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, bool isResponse, uint8_t *mfData, size_t *mfDataLen); +extern bool NestedCheckKey(uint64_t key, TAuthData *ad, uint8_t *cmd, uint8_t cmdsize); #endif // CMDHFLIST From dca8220f729d7855b12c89ecb402958ce6dbc81b Mon Sep 17 00:00:00 2001 From: Oleg Moiseenko Date: Sat, 10 Feb 2018 23:25:28 +0200 Subject: [PATCH 073/127] mock of key checking --- client/cmdhflist.c | 55 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 53 insertions(+), 2 deletions(-) diff --git a/client/cmdhflist.c b/client/cmdhflist.c index 30249579..dc3d9640 100644 --- a/client/cmdhflist.c +++ b/client/cmdhflist.c @@ -248,7 +248,7 @@ void annotateMifare(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize, uint8 bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, bool isResponse, uint8_t *mfData, size_t *mfDataLen) { static struct Crypto1State *traceCrypto1; - uint64_t mfLastKey; + static uint64_t mfLastKey; *mfDataLen = 0; @@ -325,6 +325,57 @@ bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, bool isResponse, uint8_t *m return *mfDataLen > 0; } +bool NTParityChk(TAuthData *ad, uint32_t ntx) { + if ( + (oddparity8(ntx >> 8 & 0xff) ^ (ntx & 0x01) ^ ((ad->nt_enc_par >> 5) & 0x01) ^ (ad->nt_enc & 0x01)) || + (oddparity8(ntx >> 16 & 0xff) ^ (ntx >> 8 & 0x01) ^ ((ad->nt_enc_par >> 6) & 0x01) ^ (ad->nt_enc >> 8 & 0x01)) || + (oddparity8(ntx >> 24 & 0xff) ^ (ntx >> 16 & 0x01) ^ ((ad->nt_enc_par >> 7) & 0x01) ^ (ad->nt_enc >> 16 & 0x01)) + ) + return false; + + uint32_t ar = prng_successor(ntx, 64); + if ( + (oddparity8(ar >> 8 & 0xff) ^ (ar & 0x01) ^ ((ad->ar_enc_par >> 5) & 0x01) ^ (ad->ar_enc & 0x01)) || + (oddparity8(ar >> 16 & 0xff) ^ (ar >> 8 & 0x01) ^ ((ad->ar_enc_par >> 6) & 0x01) ^ (ad->ar_enc >> 8 & 0x01)) || + (oddparity8(ar >> 24 & 0xff) ^ (ar >> 16 & 0x01) ^ ((ad->ar_enc_par >> 7) & 0x01) ^ (ad->ar_enc >> 16 & 0x01)) + ) + return false; + + uint32_t at = prng_successor(ntx, 96); + if ( + (oddparity8(ar & 0xff) ^ (at >> 24 & 0x01) ^ ((ad->ar_enc_par >> 4) & 0x01) ^ (ad->at_enc >> 24 & 0x01)) || + (oddparity8(at >> 8 & 0xff) ^ (at & 0x01) ^ ((ad->at_enc_par >> 5) & 0x01) ^ (ad->at_enc & 0x01)) || + (oddparity8(at >> 16 & 0xff) ^ (at >> 8 & 0x01) ^ ((ad->at_enc_par >> 6) & 0x01) ^ (ad->at_enc >> 8 & 0x01)) || + (oddparity8(at >> 24 & 0xff) ^ (at >> 16 & 0x01) ^ ((ad->at_enc_par >> 7) & 0x01) ^ (ad->at_enc >> 16 & 0x01)) + ) + return false; + + return true; +} + bool NestedCheckKey(uint64_t key, TAuthData *ad, uint8_t *cmd, uint8_t cmdsize) { - return false; + uint8_t buf[32] = {0}; + struct Crypto1State *pcs; + + pcs = crypto1_create(key); + uint32_t nt1 = crypto1_word(pcs, ad->nt_enc ^ ad->uid, 1) ^ ad->nt_enc; + uint32_t ar = prng_successor(nt1, 64); + uint32_t at = prng_successor(nt1, 96); + printf("key> nested auth uid: %08x nt: %08x nt_parity: %s ar: %08x at: %08x\n", ad->uid, nt1, printBitsPar(&ad->nt_enc_par, 4), ar, at); + uint32_t nr1 = crypto1_word(pcs, ad->nr_enc, 1) ^ ad->nr_enc; + uint32_t ar1 = crypto1_word(pcs, 0, 0) ^ ad->ar_enc; + uint32_t at1 = crypto1_word(pcs, 0, 0) ^ ad->at_enc; + printf("key> the same key test. nr1: %08x ar1: %08x at1: %08x \n", nr1, ar1, at1); + + if (NTParityChk(ad, nt1)) + printf("key> the same key test OK. key=%x%x\n", (unsigned int)((key & 0xFFFFFFFF00000000) >> 32), (unsigned int)(key & 0xFFFFFFFF)); + else { + printf("key> the same key test. check nt parity error.\n"); + return false; + } + + memcpy(buf, cmd, cmdsize); + mf_crypto1_decrypt(pcs, buf, cmdsize, 0); + + return CheckCrc14443(CRC_14443_A, buf, cmdsize); } \ No newline at end of file From e0158d33736110e3fbcdd8331acb7ce747ee9ba2 Mon Sep 17 00:00:00 2001 From: Oleg Moiseenko Date: Sat, 10 Feb 2018 23:28:15 +0200 Subject: [PATCH 074/127] added destroy --- client/cmdhflist.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/cmdhflist.c b/client/cmdhflist.c index dc3d9640..b1bd8a7a 100644 --- a/client/cmdhflist.c +++ b/client/cmdhflist.c @@ -377,5 +377,7 @@ bool NestedCheckKey(uint64_t key, TAuthData *ad, uint8_t *cmd, uint8_t cmdsize) memcpy(buf, cmd, cmdsize); mf_crypto1_decrypt(pcs, buf, cmdsize, 0); + crypto1_destroy(pcs); + return CheckCrc14443(CRC_14443_A, buf, cmdsize); } \ No newline at end of file From 7bea15816e2c9c4277df4670ab841ca5694c61d0 Mon Sep 17 00:00:00 2001 From: Oleg Moiseenko Date: Sun, 11 Feb 2018 00:28:23 +0200 Subject: [PATCH 075/127] added some cone in nested. not tested. --- client/cmdhflist.c | 38 ++++++++++++++++++++++++++++++++------ client/cmdhflist.h | 1 + 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/client/cmdhflist.c b/client/cmdhflist.c index b1bd8a7a..06bd8d18 100644 --- a/client/cmdhflist.c +++ b/client/cmdhflist.c @@ -297,18 +297,44 @@ bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, bool isResponse, uint8_t *m } // check default keys - for (int defaultKeyCounter = 0; defaultKeyCounter < MifareDefaultKeysSize; defaultKeyCounter++){ - if (NestedCheckKey(MifareDefaultKeys[defaultKeyCounter], &AuthData, cmd, cmdsize)) { - - break; - }; + if (!traceCrypto1) { + for (int defaultKeyCounter = 0; defaultKeyCounter < MifareDefaultKeysSize; defaultKeyCounter++){ + if (NestedCheckKey(MifareDefaultKeys[defaultKeyCounter], &AuthData, cmd, cmdsize)) { + + break; + }; + } } // nested - if (validate_prng_nonce(AuthData.nt)) { + if (!traceCrypto1 && validate_prng_nonce(AuthData.nt)) { + uint32_t ntx = prng_successor(AuthData.nt, 90); + for (int i = 0; i < 16383; i++) { + ntx = prng_successor(ntx, 1); + if (NTParityChk(&AuthData, ntx)){ + + uint32_t ks2 = AuthData.ar_enc ^ prng_successor(ntx, 64); + uint32_t ks3 = AuthData.at_enc ^ prng_successor(ntx, 96); + struct Crypto1State *pcs = lfsr_recovery64(ks2, ks3); + memcpy(mfData, cmd, cmdsize); + mf_crypto1_decrypt(pcs, mfData, cmdsize, 0); + + crypto1_destroy(pcs); + if (CheckCrc14443(CRC_14443_A, mfData, cmdsize)) { + traceCrypto1 = lfsr_recovery64(ks2, ks3); + break; + } + } + } + if (traceCrypto1) + printf("key> nt=%08x nonce distance=%d \n", ntx, nonce_distance(AuthData.nt, ntx)); + else + printf("key> don't have any valid nt( \n"); } //hardnested + if (!traceCrypto1) { + } } diff --git a/client/cmdhflist.h b/client/cmdhflist.h index d0298de5..aa037658 100644 --- a/client/cmdhflist.h +++ b/client/cmdhflist.h @@ -33,6 +33,7 @@ extern uint8_t mifare_CRC_check(bool isResponse, uint8_t* data, uint8_t len); extern void annotateIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize); extern void annotateMifare(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize, uint8_t* parity, uint8_t paritysize, bool isResponse); extern bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, bool isResponse, uint8_t *mfData, size_t *mfDataLen); +extern bool NTParityChk(TAuthData *ad, uint32_t ntx); extern bool NestedCheckKey(uint64_t key, TAuthData *ad, uint8_t *cmd, uint8_t cmdsize); #endif // CMDHFLIST From 779d9a0e90a20392785adbaa4974cafaa27005a8 Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Sat, 10 Feb 2018 17:30:32 -0500 Subject: [PATCH 076/127] reconfigure lf cmdread ... to use lf config settings instead of it's own settings. (now allows full options of lf config...) also it will now run `data samples` when the command completes making it not necessary to run manually... note: adjusted client wait message as it was confusing. --- armsrc/lfops.c | 48 ++++++++++++++++++++++++++---------------------- client/cmdlf.c | 30 +++++++++++------------------- client/cmdmain.c | 2 +- 3 files changed, 38 insertions(+), 42 deletions(-) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 5e9fb193..c7a7a59d 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -4,7 +4,7 @@ // the license. //----------------------------------------------------------------------------- // Miscellaneous routines for low frequency tag operations. -// Tags supported here so far are Texas Instruments (TI), HID +// Tags supported here so far are Texas Instruments (TI), HID, EM4x05, EM410x // Also routines for raw mode reading/simulating of LF waveform //----------------------------------------------------------------------------- @@ -28,17 +28,12 @@ */ void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint32_t period_1, uint8_t *command) { - + // start timer StartTicks(); - int divisor_used = 95; // 125 KHz - // see if 'h' was specified - if (command[strlen((char *) command) - 1] == 'h') - divisor_used = 88; // 134.8 KHz - - sample_config sc = { 0,0,1, divisor_used, 0}; - setSamplingConfig(&sc); - //clear read buffer + // use lf config settings + sample_config *sc = getSamplingConfig(); + // clear read buffer BigBuf_Clear_keep_EM(); /* Make sure the tag is reset */ @@ -46,8 +41,8 @@ void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); WaitMS(2500); - //power on - LFSetupFPGAForADC(sc.divisor, 1); + // power on + LFSetupFPGAForADC(sc->divisor, 1); // And a little more time for the tag to fully power up WaitMS(2000); @@ -56,15 +51,21 @@ void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint // now modulate the reader field if (bitbang) { - //HACK it appears my loop and if statements take up about 7 us so adjust waits accordingly... + // HACK it appears the loop and if statements take up about 7us so adjust waits accordingly... uint8_t hack_cnt = 7; if (period_0 < hack_cnt || period_1 < hack_cnt) { - DbpString("Warning periods cannot be less than 7 in bit bang mode"); + DbpString("Warning periods cannot be less than 7us in bit bang mode"); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LED_D_OFF(); return; } - //prime cmd_len to save time comparing strings while modulating + + // hack2 needed--- it appears to take about 8-16us to turn the antenna back on + // leading to ~ 1 to 2 125khz samples extra in every off period + // so we should test for last 0 before next 1 and reduce period_0 by this extra amount... + // but is this time different for every antenna or other hw builds??? more testing needed + + // prime cmd_len to save time comparing strings while modulating int cmd_len = 0; while(command[cmd_len] != '\0' && command[cmd_len] != ' ') cmd_len++; @@ -72,7 +73,6 @@ void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint int counter = 0; bool off = false; for (counter = 0; counter < cmd_len; counter++) { - //while(*command != '\0' && *command != ' ') { // if cmd = 0 then turn field off if (command[counter] == '0') { // if field already off leave alone (affects timing otherwise) @@ -81,17 +81,17 @@ void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint LED_D_OFF(); off = true; } - // note we appear to take about 6us to switch over (or run the if statements/loop...) + // note we appear to take about 7us to switch over (or run the if statements/loop...) WaitUS(period_0-hack_cnt); // else if cmd = 1 then turn field on } else { // if field already on leave alone (affects timing otherwise) if (off) { - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); LED_D_ON(); off = false; } - // note we appear to take about 6us to switch over (or run the if statements/loop...) + // note we appear to take about 7us to switch over (or run the if statements/loop...) WaitUS(period_1-hack_cnt); } } @@ -100,7 +100,7 @@ void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LED_D_OFF(); WaitUS(delay_off); - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, sc.divisor); + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, sc->divisor); FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); LED_D_ON(); if(*(command++) == '0') { @@ -112,14 +112,18 @@ void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LED_D_OFF(); WaitUS(delay_off); - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, sc.divisor); + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, sc->divisor); } FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); // now do the read DoAcquisition_config(false, 0); - // note leaves field on... (for future commands?) + + // Turn off antenna + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + // tell client we are done + cmd_send(CMD_ACK,0,0,0,0,0); } /* blank r/w tag data stream diff --git a/client/cmdlf.c b/client/cmdlf.c index ef9c3cbb..42f73fa1 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -54,26 +54,24 @@ static int CmdHelp(const char *Cmd); int usage_lf_cmdread(void) { - PrintAndLog("Usage: lf cmdread d z o c [H] "); + PrintAndLog("Usage: lf cmdread d z o c "); PrintAndLog("Options: "); PrintAndLog(" h This help"); - PrintAndLog(" L Low frequency (125 KHz)"); - PrintAndLog(" H High frequency (134 KHz)"); - PrintAndLog(" d delay OFF period"); - PrintAndLog(" z time period ZERO"); - PrintAndLog(" o time period ONE"); + PrintAndLog(" d delay OFF period between bits (0 for bitbang mode)"); + PrintAndLog(" z time period ZERO (antenna off in bitbang mode)"); + PrintAndLog(" o time period ONE (antenna on in bitbang mode)"); PrintAndLog(" c Command bytes"); PrintAndLog(" ************* All periods in microseconds"); + PrintAndLog(" ************* Use lf config to configure options."); PrintAndLog("Examples:"); PrintAndLog(" lf cmdread d 80 z 100 o 200 c 11000"); - PrintAndLog(" lf cmdread d 80 z 100 o 100 c 11000 H"); + PrintAndLog(" lf cmdread d 80 z 100 o 100 c 11000"); return 0; } /* send a command before reading */ int CmdLFCommandRead(const char *Cmd) { - static char dummy[3] = {0x20,0x00,0x00}; UsbCommand c = {CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K}; bool errors = false; //uint8_t divisor = 95; //125khz @@ -84,14 +82,6 @@ int CmdLFCommandRead(const char *Cmd) { case 'h': return usage_lf_cmdread(); - case 'H': - //divisor = 88; - dummy[1]='h'; - cmdp++; - break; - case 'L': - cmdp++; - break; case 'c': param_getstr(Cmd, cmdp+1, (char *)&c.d.asBytes, sizeof(c.d.asBytes)); cmdp+=2; @@ -121,11 +111,13 @@ int CmdLFCommandRead(const char *Cmd) //Validations if(errors) return usage_lf_cmdread(); - // in case they specified 'H' - strcpy((char *)&c.d.asBytes + strlen((char *)c.d.asBytes), dummy); - clearCommandBuffer(); SendCommand(&c); + + WaitForResponse(CMD_ACK,NULL); + getSamples(0, true); + + return 0; } diff --git a/client/cmdmain.c b/client/cmdmain.c index 719617fd..8d9313f9 100644 --- a/client/cmdmain.c +++ b/client/cmdmain.c @@ -162,7 +162,7 @@ bool WaitForResponseTimeoutW(uint32_t cmd, UsbCommand* response, size_t ms_timeo } if (msclock() - start_time > 2000 && show_warning) { PrintAndLog("Waiting for a response from the proxmark..."); - PrintAndLog("Don't forget to cancel its operation first by pressing on the button"); + PrintAndLog("You can cancel this operation by pressing the pm3 button"); show_warning = false; } } From e01bc7942cb7dc87350fd095388be58560f32f9a Mon Sep 17 00:00:00 2001 From: Oleg Moiseenko Date: Sun, 11 Feb 2018 00:40:24 +0200 Subject: [PATCH 077/127] move ks to authdata --- client/cmdhflist.c | 18 +++++++++++------- client/cmdhflist.h | 2 ++ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/client/cmdhflist.c b/client/cmdhflist.c index 06bd8d18..1701c13a 100644 --- a/client/cmdhflist.c +++ b/client/cmdhflist.c @@ -43,6 +43,8 @@ void ClearAuthData() { AuthData.uid = 0; AuthData.nt = 0; AuthData.first_auth = true; + AuthData.ks2 = 0; + AuthData.ks3 = 0; } /** @@ -266,9 +268,9 @@ bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, bool isResponse, uint8_t *m if (MifareAuthState == masFirstData) { if (AuthData.first_auth) { - uint32_t ks2 = AuthData.ar_enc ^ prng_successor(AuthData.nt, 64); - uint32_t ks3 = AuthData.at_enc ^ prng_successor(AuthData.nt, 96); - struct Crypto1State *revstate = lfsr_recovery64(ks2, ks3); + AuthData.ks2 = AuthData.ar_enc ^ prng_successor(AuthData.nt, 64); + AuthData.ks3 = AuthData.at_enc ^ prng_successor(AuthData.nt, 96); + struct Crypto1State *revstate = lfsr_recovery64(AuthData.ks2, AuthData.ks3); lfsr_rollback_word(revstate, 0, 0); lfsr_rollback_word(revstate, 0, 0); lfsr_rollback_word(revstate, AuthData.nr_enc, 1); @@ -281,12 +283,12 @@ bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, bool isResponse, uint8_t *m PrintAndLog(" | * | key | probable key:%x%x Prng:%s ks2:%08x ks3:%08x | |", (unsigned int)((lfsr & 0xFFFFFFFF00000000) >> 32), (unsigned int)(lfsr & 0xFFFFFFFF), validate_prng_nonce(AuthData.nt) ? "WEAK": "HARD", - ks2, - ks3); + AuthData.ks2, + AuthData.ks3); AuthData.first_auth = false; - traceCrypto1 = lfsr_recovery64(ks2, ks3); + traceCrypto1 = lfsr_recovery64(AuthData.ks2, AuthData.ks3); } else { printf("uid:%x nt:%x ar_enc:%x at_enc:%x\n", AuthData.uid, AuthData.nt, AuthData.ar_enc, AuthData.at_enc); @@ -321,7 +323,9 @@ bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, bool isResponse, uint8_t *m crypto1_destroy(pcs); if (CheckCrc14443(CRC_14443_A, mfData, cmdsize)) { - traceCrypto1 = lfsr_recovery64(ks2, ks3); + AuthData.ks2 = ks2; + AuthData.ks3 = ks3; + traceCrypto1 = lfsr_recovery64(AuthData.ks2, AuthData.ks3); break; } } diff --git a/client/cmdhflist.h b/client/cmdhflist.h index aa037658..76b57392 100644 --- a/client/cmdhflist.h +++ b/client/cmdhflist.h @@ -25,6 +25,8 @@ typedef struct { uint32_t at_enc; // encrypted tag response uint8_t at_enc_par; // encrypted tag response parity bool first_auth; // is first authentication + uint32_t ks2; // ar ^ ar_enc + uint32_t ks3; // at ^ at_enc } TAuthData; extern void ClearAuthData(); From 856da9a1c081abedef9af96220723eb1031f49e2 Mon Sep 17 00:00:00 2001 From: Oleg Moiseenko Date: Sun, 11 Feb 2018 00:44:24 +0200 Subject: [PATCH 078/127] added cipherstream recovery --- client/cmdhflist.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/client/cmdhflist.c b/client/cmdhflist.c index 1701c13a..64ffed5c 100644 --- a/client/cmdhflist.c +++ b/client/cmdhflist.c @@ -295,6 +295,7 @@ bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, bool isResponse, uint8_t *m // check last used key if (mfLastKey) { if (NestedCheckKey(mfLastKey, &AuthData, cmd, cmdsize)) { + traceCrypto1 = lfsr_recovery64(AuthData.ks2, AuthData.ks3); }; } @@ -302,7 +303,7 @@ bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, bool isResponse, uint8_t *m if (!traceCrypto1) { for (int defaultKeyCounter = 0; defaultKeyCounter < MifareDefaultKeysSize; defaultKeyCounter++){ if (NestedCheckKey(MifareDefaultKeys[defaultKeyCounter], &AuthData, cmd, cmdsize)) { - + traceCrypto1 = lfsr_recovery64(AuthData.ks2, AuthData.ks3); break; }; } @@ -409,5 +410,11 @@ bool NestedCheckKey(uint64_t key, TAuthData *ad, uint8_t *cmd, uint8_t cmdsize) crypto1_destroy(pcs); - return CheckCrc14443(CRC_14443_A, buf, cmdsize); + if(CheckCrc14443(CRC_14443_A, buf, cmdsize)) { + AuthData.ks2 = AuthData.ar_enc ^ ar; + AuthData.ks3 = AuthData.at_enc ^ at; + return true; + } else { + return false; + } } \ No newline at end of file From bf52d74adcfbe3947970d9c2984c36f77af0c9c7 Mon Sep 17 00:00:00 2001 From: Oleg Moiseenko Date: Sun, 11 Feb 2018 00:45:12 +0200 Subject: [PATCH 079/127] small fix --- client/cmdhflist.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdhflist.c b/client/cmdhflist.c index 64ffed5c..7b3fdca5 100644 --- a/client/cmdhflist.c +++ b/client/cmdhflist.c @@ -417,4 +417,4 @@ bool NestedCheckKey(uint64_t key, TAuthData *ad, uint8_t *cmd, uint8_t cmdsize) } else { return false; } -} \ No newline at end of file +} From 2d7bdee30b93e3669850b9c16eed23174cf07b65 Mon Sep 17 00:00:00 2001 From: merlokk Date: Mon, 12 Feb 2018 18:53:12 +0200 Subject: [PATCH 080/127] added parity check of deciphered command --- client/cmdhf.c | 2 +- client/cmdhflist.c | 88 +++++++++++++++++++++++++++++++++------------- client/cmdhflist.h | 5 +-- 3 files changed, 68 insertions(+), 27 deletions(-) diff --git a/client/cmdhf.c b/client/cmdhf.c index 06382abb..ffbc4515 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -433,7 +433,7 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui } } - if (DecodeMifareData(frame, data_len, isResponse, mfData, &mfDataLen)) { + if (DecodeMifareData(frame, data_len, parityBytes, isResponse, mfData, &mfDataLen)) { memset(explanation, 0x00, sizeof(explanation)); if (!isResponse) { explanation[0] = '>'; diff --git a/client/cmdhflist.c b/client/cmdhflist.c index 7b3fdca5..a9691aa3 100644 --- a/client/cmdhflist.c +++ b/client/cmdhflist.c @@ -89,7 +89,6 @@ void annotateIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) { case ISO14443A_CMD_WUPA: snprintf(exp,size,"WUPA"); - MifareAuthState = masNone; break; case ISO14443A_CMD_ANTICOLL_OR_SELECT:{ // 93 20 = Anticollision (usage: 9320 - answer: 4bytes UID+1byte UID-bytes-xor) @@ -115,7 +114,6 @@ void annotateIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) } case ISO14443A_CMD_REQA: snprintf(exp,size,"REQA"); - MifareAuthState = masNone; break; case ISO14443A_CMD_READBLOCK: snprintf(exp,size,"READBLOCK(%d)",cmd[1]); break; case ISO14443A_CMD_WRITEBLOCK: snprintf(exp,size,"WRITEBLOCK(%d)",cmd[1]); break; @@ -189,6 +187,17 @@ void annotateIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) } void annotateMifare(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize, uint8_t* parity, uint8_t paritysize, bool isResponse) { + if (!isResponse && cmdsize == 1) { + switch(cmd[0]) { + case ISO14443A_CMD_WUPA: + case ISO14443A_CMD_REQA: + MifareAuthState = masNone; + break; + default: + break; + } + } + // get UID if (MifareAuthState == masNone) { if (cmdsize == 9 && cmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && cmd[1] == 0x70) { @@ -248,7 +257,7 @@ void annotateMifare(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize, uint8 } -bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, bool isResponse, uint8_t *mfData, size_t *mfDataLen) { +bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, uint8_t *parity, bool isResponse, uint8_t *mfData, size_t *mfDataLen) { static struct Crypto1State *traceCrypto1; static uint64_t mfLastKey; @@ -281,7 +290,8 @@ bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, bool isResponse, uint8_t *m crypto1_destroy(revstate); mfLastKey = lfsr; PrintAndLog(" | * | key | probable key:%x%x Prng:%s ks2:%08x ks3:%08x | |", - (unsigned int)((lfsr & 0xFFFFFFFF00000000) >> 32), (unsigned int)(lfsr & 0xFFFFFFFF), + (unsigned int)((lfsr & 0xFFFFFFFF00000000) >> 32), + (unsigned int)(lfsr & 0xFFFFFFFF), validate_prng_nonce(AuthData.nt) ? "WEAK": "HARD", AuthData.ks2, AuthData.ks3); @@ -290,19 +300,29 @@ bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, bool isResponse, uint8_t *m traceCrypto1 = lfsr_recovery64(AuthData.ks2, AuthData.ks3); } else { - printf("uid:%x nt:%x ar_enc:%x at_enc:%x\n", AuthData.uid, AuthData.nt, AuthData.ar_enc, AuthData.at_enc); - // check last used key if (mfLastKey) { - if (NestedCheckKey(mfLastKey, &AuthData, cmd, cmdsize)) { - traceCrypto1 = lfsr_recovery64(AuthData.ks2, AuthData.ks3); + if (NestedCheckKey(mfLastKey, &AuthData, cmd, cmdsize, parity)) { + PrintAndLog(" | * | key | last used key:%x%x ks2:%08x ks3:%08x | |", + (unsigned int)((mfLastKey & 0xFFFFFFFF00000000) >> 32), + (unsigned int)(mfLastKey & 0xFFFFFFFF), + AuthData.ks2, + AuthData.ks3); + + traceCrypto1 = lfsr_recovery64(AuthData.ks2, AuthData.ks3); }; } // check default keys if (!traceCrypto1) { for (int defaultKeyCounter = 0; defaultKeyCounter < MifareDefaultKeysSize; defaultKeyCounter++){ - if (NestedCheckKey(MifareDefaultKeys[defaultKeyCounter], &AuthData, cmd, cmdsize)) { + if (NestedCheckKey(MifareDefaultKeys[defaultKeyCounter], &AuthData, cmd, cmdsize, parity)) { + PrintAndLog(" | * | key | default key:%x%x ks2:%08x ks3:%08x | |", + (unsigned int)((MifareDefaultKeys[defaultKeyCounter] & 0xFFFFFFFF00000000) >> 32), + (unsigned int)(MifareDefaultKeys[defaultKeyCounter] & 0xFFFFFFFF), + AuthData.ks2, + AuthData.ks3); + traceCrypto1 = lfsr_recovery64(AuthData.ks2, AuthData.ks3); break; }; @@ -311,6 +331,7 @@ bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, bool isResponse, uint8_t *m // nested if (!traceCrypto1 && validate_prng_nonce(AuthData.nt)) { +printf("nested. uid:%x nt:%x ar_enc:%x at_enc:%x\n", AuthData.uid, AuthData.nt, AuthData.ar_enc, AuthData.at_enc); uint32_t ntx = prng_successor(AuthData.nt, 90); for (int i = 0; i < 16383; i++) { ntx = prng_successor(ntx, 1); @@ -339,6 +360,7 @@ bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, bool isResponse, uint8_t *m //hardnested if (!traceCrypto1) { + printf("hardnested not implemented. uid:%x nt:%x ar_enc:%x at_enc:%x\n", AuthData.uid, AuthData.nt, AuthData.ar_enc, AuthData.at_enc); } } @@ -384,37 +406,55 @@ bool NTParityChk(TAuthData *ad, uint32_t ntx) { return true; } -bool NestedCheckKey(uint64_t key, TAuthData *ad, uint8_t *cmd, uint8_t cmdsize) { +bool NestedCheckKey(uint64_t key, TAuthData *ad, uint8_t *cmd, uint8_t cmdsize, uint8_t *parity) { uint8_t buf[32] = {0}; struct Crypto1State *pcs; + AuthData.ks2 = 0; + AuthData.ks3 = 0; + pcs = crypto1_create(key); uint32_t nt1 = crypto1_word(pcs, ad->nt_enc ^ ad->uid, 1) ^ ad->nt_enc; uint32_t ar = prng_successor(nt1, 64); uint32_t at = prng_successor(nt1, 96); - printf("key> nested auth uid: %08x nt: %08x nt_parity: %s ar: %08x at: %08x\n", ad->uid, nt1, printBitsPar(&ad->nt_enc_par, 4), ar, at); - uint32_t nr1 = crypto1_word(pcs, ad->nr_enc, 1) ^ ad->nr_enc; + + crypto1_word(pcs, ad->nr_enc, 1); +// uint32_t nr1 = crypto1_word(pcs, ad->nr_enc, 1) ^ ad->nr_enc; // if needs deciphered nr uint32_t ar1 = crypto1_word(pcs, 0, 0) ^ ad->ar_enc; uint32_t at1 = crypto1_word(pcs, 0, 0) ^ ad->at_enc; - printf("key> the same key test. nr1: %08x ar1: %08x at1: %08x \n", nr1, ar1, at1); - if (NTParityChk(ad, nt1)) - printf("key> the same key test OK. key=%x%x\n", (unsigned int)((key & 0xFFFFFFFF00000000) >> 32), (unsigned int)(key & 0xFFFFFFFF)); - else { - printf("key> the same key test. check nt parity error.\n"); + if (!(ar == ar1 && at == at1 && NTParityChk(ad, nt1))) return false; - } memcpy(buf, cmd, cmdsize); mf_crypto1_decrypt(pcs, buf, cmdsize, 0); crypto1_destroy(pcs); - if(CheckCrc14443(CRC_14443_A, buf, cmdsize)) { - AuthData.ks2 = AuthData.ar_enc ^ ar; - AuthData.ks3 = AuthData.at_enc ^ at; - return true; - } else { + if(!CheckCrc14443(CRC_14443_A, buf, cmdsize)) return false; - } + + if (!CheckCrypto1Parity(cmd, cmdsize, buf, parity)) + return false; + + AuthData.ks2 = AuthData.ar_enc ^ ar; + AuthData.ks3 = AuthData.at_enc ^ at; + + return true; +} + +bool CheckCrypto1Parity(uint8_t *cmd, uint8_t cmdsize, uint8_t *cmd_enc, uint8_t *parity_enc) { + printf("parity check. size=%d\n", cmdsize); + printf("cmd =%s\n", sprint_hex(cmd, cmdsize)); + printf("cmd_enc=%s\n", sprint_hex(cmd_enc, cmdsize)); + printf("parity=%s\n", printBitsPar(parity_enc, cmdsize)); +// (oddparity8(ntx >> 8 & 0xff) ^ (ntx & 0x01) ^ ((ad->nt_enc_par >> 5) & 0x01) ^ (ad->nt_enc & 0x01)) || + for (int i = 0; i < cmdsize - 1; i++) { + bool b = oddparity8(cmd[i]) ^ (cmd[i + 1] & 0x01) ^ ((parity_enc[i / 8] >> (6 - i % 8)) & 0x01) ^ (cmd_enc[i + 1] & 0x01); + printf("i=%d b=%d\n", i, b); + if (b) + return false; + } + + return true; } diff --git a/client/cmdhflist.h b/client/cmdhflist.h index 76b57392..977be288 100644 --- a/client/cmdhflist.h +++ b/client/cmdhflist.h @@ -34,8 +34,9 @@ extern uint8_t iso14443A_CRC_check(bool isResponse, uint8_t* data, uint8_t len); extern uint8_t mifare_CRC_check(bool isResponse, uint8_t* data, uint8_t len); extern void annotateIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize); extern void annotateMifare(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize, uint8_t* parity, uint8_t paritysize, bool isResponse); -extern bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, bool isResponse, uint8_t *mfData, size_t *mfDataLen); +extern bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, uint8_t *parity, bool isResponse, uint8_t *mfData, size_t *mfDataLen); extern bool NTParityChk(TAuthData *ad, uint32_t ntx); -extern bool NestedCheckKey(uint64_t key, TAuthData *ad, uint8_t *cmd, uint8_t cmdsize); +extern bool NestedCheckKey(uint64_t key, TAuthData *ad, uint8_t *cmd, uint8_t cmdsize, uint8_t *parity); +extern bool CheckCrypto1Parity(uint8_t *cmd, uint8_t cmdsize, uint8_t *cmd_enc, uint8_t *parity_enc); #endif // CMDHFLIST From 597fca4ff17facc186df1de069d52b3f343c44f6 Mon Sep 17 00:00:00 2001 From: merlokk Date: Tue, 13 Feb 2018 12:33:15 +0200 Subject: [PATCH 081/127] check parity works --- client/cmdhflist.c | 19 +++++++++++-------- client/cmdhflist.h | 2 +- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/client/cmdhflist.c b/client/cmdhflist.c index a9691aa3..7059a223 100644 --- a/client/cmdhflist.c +++ b/client/cmdhflist.c @@ -431,29 +431,32 @@ bool NestedCheckKey(uint64_t key, TAuthData *ad, uint8_t *cmd, uint8_t cmdsize, crypto1_destroy(pcs); - if(!CheckCrc14443(CRC_14443_A, buf, cmdsize)) - return false; - if (!CheckCrypto1Parity(cmd, cmdsize, buf, parity)) return false; + if(!CheckCrc14443(CRC_14443_A, buf, cmdsize)) + return false; + AuthData.ks2 = AuthData.ar_enc ^ ar; AuthData.ks3 = AuthData.at_enc ^ at; return true; } -bool CheckCrypto1Parity(uint8_t *cmd, uint8_t cmdsize, uint8_t *cmd_enc, uint8_t *parity_enc) { +bool CheckCrypto1Parity(uint8_t *cmd_enc, uint8_t cmdsize, uint8_t *cmd, uint8_t *parity_enc) { + uint8_t parity[16]; + oddparitybuf(cmd, cmdsize, parity); printf("parity check. size=%d\n", cmdsize); printf("cmd =%s\n", sprint_hex(cmd, cmdsize)); printf("cmd_enc=%s\n", sprint_hex(cmd_enc, cmdsize)); - printf("parity=%s\n", printBitsPar(parity_enc, cmdsize)); + printf("parity =%s\n", printBitsPar(parity, cmdsize)); + printf("parity_enc=%s\n", printBitsPar(parity_enc, cmdsize)); // (oddparity8(ntx >> 8 & 0xff) ^ (ntx & 0x01) ^ ((ad->nt_enc_par >> 5) & 0x01) ^ (ad->nt_enc & 0x01)) || +// (oddparity8(ntx >> 24 & 0xff) ^ (ntx >> 16 & 0x01) ^ ((ad->nt_enc_par >> 7) & 0x01) ^ (ad->nt_enc >> 16 & 0x01)) for (int i = 0; i < cmdsize - 1; i++) { - bool b = oddparity8(cmd[i]) ^ (cmd[i + 1] & 0x01) ^ ((parity_enc[i / 8] >> (6 - i % 8)) & 0x01) ^ (cmd_enc[i + 1] & 0x01); - printf("i=%d b=%d\n", i, b); + bool b = oddparity8(cmd[i]) ^ (cmd[i + 1] & 0x01) ^ ((parity_enc[i / 8] >> (7 - i % 8)) & 0x01) ^ (cmd_enc[i + 1] & 0x01); if (b) - return false; + printf("!!! i=%d \n", i); } return true; diff --git a/client/cmdhflist.h b/client/cmdhflist.h index 977be288..835b17e2 100644 --- a/client/cmdhflist.h +++ b/client/cmdhflist.h @@ -37,6 +37,6 @@ extern void annotateMifare(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize extern bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, uint8_t *parity, bool isResponse, uint8_t *mfData, size_t *mfDataLen); extern bool NTParityChk(TAuthData *ad, uint32_t ntx); extern bool NestedCheckKey(uint64_t key, TAuthData *ad, uint8_t *cmd, uint8_t cmdsize, uint8_t *parity); -extern bool CheckCrypto1Parity(uint8_t *cmd, uint8_t cmdsize, uint8_t *cmd_enc, uint8_t *parity_enc); +extern bool CheckCrypto1Parity(uint8_t *cmd_enc, uint8_t cmdsize, uint8_t *cmd, uint8_t *parity_enc); #endif // CMDHFLIST From 8253ca0e1b91fd5163483badbfd5c4a345cfbdb8 Mon Sep 17 00:00:00 2001 From: merlokk Date: Tue, 13 Feb 2018 12:35:33 +0200 Subject: [PATCH 082/127] code cleaning --- client/cmdhflist.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/client/cmdhflist.c b/client/cmdhflist.c index 7059a223..962c4f82 100644 --- a/client/cmdhflist.c +++ b/client/cmdhflist.c @@ -444,19 +444,9 @@ bool NestedCheckKey(uint64_t key, TAuthData *ad, uint8_t *cmd, uint8_t cmdsize, } bool CheckCrypto1Parity(uint8_t *cmd_enc, uint8_t cmdsize, uint8_t *cmd, uint8_t *parity_enc) { - uint8_t parity[16]; - oddparitybuf(cmd, cmdsize, parity); - printf("parity check. size=%d\n", cmdsize); - printf("cmd =%s\n", sprint_hex(cmd, cmdsize)); - printf("cmd_enc=%s\n", sprint_hex(cmd_enc, cmdsize)); - printf("parity =%s\n", printBitsPar(parity, cmdsize)); - printf("parity_enc=%s\n", printBitsPar(parity_enc, cmdsize)); -// (oddparity8(ntx >> 8 & 0xff) ^ (ntx & 0x01) ^ ((ad->nt_enc_par >> 5) & 0x01) ^ (ad->nt_enc & 0x01)) || -// (oddparity8(ntx >> 24 & 0xff) ^ (ntx >> 16 & 0x01) ^ ((ad->nt_enc_par >> 7) & 0x01) ^ (ad->nt_enc >> 16 & 0x01)) for (int i = 0; i < cmdsize - 1; i++) { - bool b = oddparity8(cmd[i]) ^ (cmd[i + 1] & 0x01) ^ ((parity_enc[i / 8] >> (7 - i % 8)) & 0x01) ^ (cmd_enc[i + 1] & 0x01); - if (b) - printf("!!! i=%d \n", i); + if (oddparity8(cmd[i]) ^ (cmd[i + 1] & 0x01) ^ ((parity_enc[i / 8] >> (7 - i % 8)) & 0x01) ^ (cmd_enc[i + 1] & 0x01)) + return false; } return true; From 0113dcf3fd2d22217c481edac525f907be3c0e0b Mon Sep 17 00:00:00 2001 From: merlokk Date: Tue, 13 Feb 2018 15:12:41 +0200 Subject: [PATCH 083/127] nested works --- client/cmdhflist.c | 68 ++++++++++++++++++++++++++++------------------ client/cmdhflist.h | 1 + 2 files changed, 42 insertions(+), 27 deletions(-) diff --git a/client/cmdhflist.c b/client/cmdhflist.c index 962c4f82..eb61c301 100644 --- a/client/cmdhflist.c +++ b/client/cmdhflist.c @@ -266,6 +266,7 @@ bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, uint8_t *parity, bool isRes if (MifareAuthState == masAuthComplete) { if (traceCrypto1) { crypto1_destroy(traceCrypto1); + traceCrypto1 = NULL; } MifareAuthState = masFirstData; @@ -279,19 +280,10 @@ bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, uint8_t *parity, bool isRes if (AuthData.first_auth) { AuthData.ks2 = AuthData.ar_enc ^ prng_successor(AuthData.nt, 64); AuthData.ks3 = AuthData.at_enc ^ prng_successor(AuthData.nt, 96); - struct Crypto1State *revstate = lfsr_recovery64(AuthData.ks2, AuthData.ks3); - lfsr_rollback_word(revstate, 0, 0); - lfsr_rollback_word(revstate, 0, 0); - lfsr_rollback_word(revstate, AuthData.nr_enc, 1); - lfsr_rollback_word(revstate, AuthData.uid ^ AuthData.nt, 0); - uint64_t lfsr = 0; - crypto1_get_lfsr(revstate, &lfsr); - crypto1_destroy(revstate); - mfLastKey = lfsr; - PrintAndLog(" | * | key | probable key:%x%x Prng:%s ks2:%08x ks3:%08x | |", - (unsigned int)((lfsr & 0xFFFFFFFF00000000) >> 32), - (unsigned int)(lfsr & 0xFFFFFFFF), + mfLastKey = GetCrypto1ProbableKey(&AuthData); + PrintAndLog(" | * | key | probable key:%010"PRIx64" Prng:%s ks2:%08x ks3:%08x | |", + mfLastKey, validate_prng_nonce(AuthData.nt) ? "WEAK": "HARD", AuthData.ks2, AuthData.ks3); @@ -300,12 +292,16 @@ bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, uint8_t *parity, bool isRes traceCrypto1 = lfsr_recovery64(AuthData.ks2, AuthData.ks3); } else { + if (traceCrypto1) { + crypto1_destroy(traceCrypto1); + traceCrypto1 = NULL; + } + // check last used key - if (mfLastKey) { + if (false && mfLastKey) { if (NestedCheckKey(mfLastKey, &AuthData, cmd, cmdsize, parity)) { - PrintAndLog(" | * | key | last used key:%x%x ks2:%08x ks3:%08x | |", - (unsigned int)((mfLastKey & 0xFFFFFFFF00000000) >> 32), - (unsigned int)(mfLastKey & 0xFFFFFFFF), + PrintAndLog(" | * | key | last used key:%010"PRIx64" ks2:%08x ks3:%08x | |", + mfLastKey, AuthData.ks2, AuthData.ks3); @@ -314,15 +310,15 @@ bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, uint8_t *parity, bool isRes } // check default keys - if (!traceCrypto1) { + if (false && !traceCrypto1) { for (int defaultKeyCounter = 0; defaultKeyCounter < MifareDefaultKeysSize; defaultKeyCounter++){ if (NestedCheckKey(MifareDefaultKeys[defaultKeyCounter], &AuthData, cmd, cmdsize, parity)) { - PrintAndLog(" | * | key | default key:%x%x ks2:%08x ks3:%08x | |", - (unsigned int)((MifareDefaultKeys[defaultKeyCounter] & 0xFFFFFFFF00000000) >> 32), - (unsigned int)(MifareDefaultKeys[defaultKeyCounter] & 0xFFFFFFFF), + PrintAndLog(" | * | key | default key:%010"PRIx64" ks2:%08x ks3:%08x | |", + MifareDefaultKeys[defaultKeyCounter], AuthData.ks2, AuthData.ks3); + mfLastKey = MifareDefaultKeys[defaultKeyCounter]; traceCrypto1 = lfsr_recovery64(AuthData.ks2, AuthData.ks3); break; }; @@ -331,8 +327,7 @@ bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, uint8_t *parity, bool isRes // nested if (!traceCrypto1 && validate_prng_nonce(AuthData.nt)) { -printf("nested. uid:%x nt:%x ar_enc:%x at_enc:%x\n", AuthData.uid, AuthData.nt, AuthData.ar_enc, AuthData.at_enc); - uint32_t ntx = prng_successor(AuthData.nt, 90); + uint32_t ntx = prng_successor(AuthData.nt, 90); for (int i = 0; i < 16383; i++) { ntx = prng_successor(ntx, 1); if (NTParityChk(&AuthData, ntx)){ @@ -344,18 +339,22 @@ printf("nested. uid:%x nt:%x ar_enc:%x at_enc:%x\n", AuthData.uid, AuthData.nt, mf_crypto1_decrypt(pcs, mfData, cmdsize, 0); crypto1_destroy(pcs); - if (CheckCrc14443(CRC_14443_A, mfData, cmdsize)) { + if (CheckCrypto1Parity(cmd, cmdsize, mfData, parity) && CheckCrc14443(CRC_14443_A, mfData, cmdsize)) { AuthData.ks2 = ks2; AuthData.ks3 = ks3; + + AuthData.nt = ntx; + mfLastKey = GetCrypto1ProbableKey(&AuthData); + PrintAndLog(" | * | key | nested probable key:%010"PRIx64" ks2:%08x ks3:%08x | |", + mfLastKey, + AuthData.ks2, + AuthData.ks3); + traceCrypto1 = lfsr_recovery64(AuthData.ks2, AuthData.ks3); break; } } } - if (traceCrypto1) - printf("key> nt=%08x nonce distance=%d \n", ntx, nonce_distance(AuthData.nt, ntx)); - else - printf("key> don't have any valid nt( \n"); } //hardnested @@ -437,6 +436,7 @@ bool NestedCheckKey(uint64_t key, TAuthData *ad, uint8_t *cmd, uint8_t cmdsize, if(!CheckCrc14443(CRC_14443_A, buf, cmdsize)) return false; + AuthData.nt = nt1; AuthData.ks2 = AuthData.ar_enc ^ ar; AuthData.ks3 = AuthData.at_enc ^ at; @@ -451,3 +451,17 @@ bool CheckCrypto1Parity(uint8_t *cmd_enc, uint8_t cmdsize, uint8_t *cmd, uint8_t return true; } + +uint64_t GetCrypto1ProbableKey(TAuthData *ad) { + struct Crypto1State *revstate = lfsr_recovery64(ad->ks2, ad->ks3); + lfsr_rollback_word(revstate, 0, 0); + lfsr_rollback_word(revstate, 0, 0); + lfsr_rollback_word(revstate, ad->nr_enc, 1); + lfsr_rollback_word(revstate, ad->uid ^ ad->nt, 0); + + uint64_t lfsr = 0; + crypto1_get_lfsr(revstate, &lfsr); + crypto1_destroy(revstate); + + return lfsr; +} diff --git a/client/cmdhflist.h b/client/cmdhflist.h index 835b17e2..c2c9c03e 100644 --- a/client/cmdhflist.h +++ b/client/cmdhflist.h @@ -38,5 +38,6 @@ extern bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, uint8_t *parity, boo extern bool NTParityChk(TAuthData *ad, uint32_t ntx); extern bool NestedCheckKey(uint64_t key, TAuthData *ad, uint8_t *cmd, uint8_t cmdsize, uint8_t *parity); extern bool CheckCrypto1Parity(uint8_t *cmd_enc, uint8_t cmdsize, uint8_t *cmd, uint8_t *parity_enc); +extern uint64_t GetCrypto1ProbableKey(TAuthData *ad); #endif // CMDHFLIST From 45b4ac09c9ef89b9e5892156e69eda860b29381e Mon Sep 17 00:00:00 2001 From: merlokk Date: Tue, 13 Feb 2018 17:07:49 +0200 Subject: [PATCH 084/127] added hardnested sketch. final cleaning. --- client/cmdhflist.c | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/client/cmdhflist.c b/client/cmdhflist.c index eb61c301..1fa02cb3 100644 --- a/client/cmdhflist.c +++ b/client/cmdhflist.c @@ -298,7 +298,7 @@ bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, uint8_t *parity, bool isRes } // check last used key - if (false && mfLastKey) { + if (mfLastKey) { if (NestedCheckKey(mfLastKey, &AuthData, cmd, cmdsize, parity)) { PrintAndLog(" | * | key | last used key:%010"PRIx64" ks2:%08x ks3:%08x | |", mfLastKey, @@ -310,7 +310,7 @@ bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, uint8_t *parity, bool isRes } // check default keys - if (false && !traceCrypto1) { + if (!traceCrypto1) { for (int defaultKeyCounter = 0; defaultKeyCounter < MifareDefaultKeysSize; defaultKeyCounter++){ if (NestedCheckKey(MifareDefaultKeys[defaultKeyCounter], &AuthData, cmd, cmdsize, parity)) { PrintAndLog(" | * | key | default key:%010"PRIx64" ks2:%08x ks3:%08x | |", @@ -360,6 +360,33 @@ bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, uint8_t *parity, bool isRes //hardnested if (!traceCrypto1) { printf("hardnested not implemented. uid:%x nt:%x ar_enc:%x at_enc:%x\n", AuthData.uid, AuthData.nt, AuthData.ar_enc, AuthData.at_enc); + MifareAuthState = masError; + + /* TOO SLOW( needs to have more strong filter. with this filter - aprox 4 mln tests + uint32_t t = msclock(); + uint32_t t1 = t; + int n = 0; + for (uint32_t i = 0; i < 0xFFFFFFFF; i++) { + if (NTParityChk(&AuthData, i)){ + + uint32_t ks2 = AuthData.ar_enc ^ prng_successor(i, 64); + uint32_t ks3 = AuthData.at_enc ^ prng_successor(i, 96); + struct Crypto1State *pcs = lfsr_recovery64(ks2, ks3); + + + + + n++; + + if (!(n % 100000)) { + printf("delta=%d n=%d ks2=%x ks3=%x \n", msclock() - t1 , n, ks2, ks3); + t1 = msclock(); + } + + } + } + printf("delta=%d n=%d\n", msclock() - t, n); + */ } } From 868deeb783002631e3d57c0358986c6fd866e11a Mon Sep 17 00:00:00 2001 From: merlokk Date: Tue, 13 Feb 2018 17:14:51 +0200 Subject: [PATCH 085/127] move annotate* functions --- client/cmdhf.c | 110 --------------------------------------------- client/cmdhflist.c | 110 +++++++++++++++++++++++++++++++++++++++++++++ client/cmdhflist.h | 4 ++ 3 files changed, 114 insertions(+), 110 deletions(-) diff --git a/client/cmdhf.c b/client/cmdhf.c index ffbc4515..ab7bfcdf 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -43,116 +43,6 @@ int CmdHFTune(const char *Cmd) return 0; } -void annotateIclass(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) -{ - switch(cmd[0]) - { - case ICLASS_CMD_ACTALL: snprintf(exp,size,"ACTALL"); break; - case ICLASS_CMD_READ_OR_IDENTIFY:{ - if(cmdsize > 1){ - snprintf(exp,size,"READ(%d)",cmd[1]); - }else{ - snprintf(exp,size,"IDENTIFY"); - } - break; - } - case ICLASS_CMD_SELECT: snprintf(exp,size,"SELECT"); break; - case ICLASS_CMD_PAGESEL: snprintf(exp,size,"PAGESEL(%d)", cmd[1]); break; - case ICLASS_CMD_READCHECK_KC:snprintf(exp,size,"READCHECK[Kc](%d)", cmd[1]); break; - case ICLASS_CMD_READCHECK_KD:snprintf(exp,size,"READCHECK[Kd](%d)", cmd[1]); break; - case ICLASS_CMD_CHECK: snprintf(exp,size,"CHECK"); break; - case ICLASS_CMD_DETECT: snprintf(exp,size,"DETECT"); break; - case ICLASS_CMD_HALT: snprintf(exp,size,"HALT"); break; - case ICLASS_CMD_UPDATE: snprintf(exp,size,"UPDATE(%d)",cmd[1]); break; - case ICLASS_CMD_ACT: snprintf(exp,size,"ACT"); break; - case ICLASS_CMD_READ4: snprintf(exp,size,"READ4(%d)",cmd[1]); break; - default: snprintf(exp,size,"?"); break; - } - return; -} - -void annotateIso15693(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) -{ - - if(cmd[0] == 0x26) - { - switch(cmd[1]){ - case ISO15693_INVENTORY :snprintf(exp, size, "INVENTORY");break; - case ISO15693_STAYQUIET :snprintf(exp, size, "STAY_QUIET");break; - default: snprintf(exp,size,"?"); break; - - } - }else if(cmd[0] == 0x02) - { - switch(cmd[1]) - { - case ISO15693_READBLOCK :snprintf(exp, size, "READBLOCK");break; - case ISO15693_WRITEBLOCK :snprintf(exp, size, "WRITEBLOCK");break; - case ISO15693_LOCKBLOCK :snprintf(exp, size, "LOCKBLOCK");break; - case ISO15693_READ_MULTI_BLOCK :snprintf(exp, size, "READ_MULTI_BLOCK");break; - case ISO15693_SELECT :snprintf(exp, size, "SELECT");break; - case ISO15693_RESET_TO_READY :snprintf(exp, size, "RESET_TO_READY");break; - case ISO15693_WRITE_AFI :snprintf(exp, size, "WRITE_AFI");break; - case ISO15693_LOCK_AFI :snprintf(exp, size, "LOCK_AFI");break; - case ISO15693_WRITE_DSFID :snprintf(exp, size, "WRITE_DSFID");break; - case ISO15693_LOCK_DSFID :snprintf(exp, size, "LOCK_DSFID");break; - case ISO15693_GET_SYSTEM_INFO :snprintf(exp, size, "GET_SYSTEM_INFO");break; - case ISO15693_READ_MULTI_SECSTATUS :snprintf(exp, size, "READ_MULTI_SECSTATUS");break; - default: snprintf(exp,size,"?"); break; - } - } -} - - -void annotateTopaz(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) -{ - switch(cmd[0]) { - case TOPAZ_REQA :snprintf(exp, size, "REQA");break; - case TOPAZ_WUPA :snprintf(exp, size, "WUPA");break; - case TOPAZ_RID :snprintf(exp, size, "RID");break; - case TOPAZ_RALL :snprintf(exp, size, "RALL");break; - case TOPAZ_READ :snprintf(exp, size, "READ");break; - case TOPAZ_WRITE_E :snprintf(exp, size, "WRITE-E");break; - case TOPAZ_WRITE_NE :snprintf(exp, size, "WRITE-NE");break; - case TOPAZ_RSEG :snprintf(exp, size, "RSEG");break; - case TOPAZ_READ8 :snprintf(exp, size, "READ8");break; - case TOPAZ_WRITE_E8 :snprintf(exp, size, "WRITE-E8");break; - case TOPAZ_WRITE_NE8 :snprintf(exp, size, "WRITE-NE8");break; - default: snprintf(exp,size,"?"); break; - } -} - - -/** -06 00 = INITIATE -0E xx = SELECT ID (xx = Chip-ID) -0B = Get UID -08 yy = Read Block (yy = block number) -09 yy dd dd dd dd = Write Block (yy = block number; dd dd dd dd = data to be written) -0C = Reset to Inventory -0F = Completion -0A 11 22 33 44 55 66 = Authenticate (11 22 33 44 55 66 = data to authenticate) -**/ - -void annotateIso14443b(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) -{ - switch(cmd[0]){ - case ISO14443B_REQB : snprintf(exp,size,"REQB");break; - case ISO14443B_ATTRIB : snprintf(exp,size,"ATTRIB");break; - case ISO14443B_HALT : snprintf(exp,size,"HALT");break; - case ISO14443B_INITIATE : snprintf(exp,size,"INITIATE");break; - case ISO14443B_SELECT : snprintf(exp,size,"SELECT(%d)",cmd[1]);break; - case ISO14443B_GET_UID : snprintf(exp,size,"GET UID");break; - case ISO14443B_READ_BLK : snprintf(exp,size,"READ_BLK(%d)", cmd[1]);break; - case ISO14443B_WRITE_BLK : snprintf(exp,size,"WRITE_BLK(%d)",cmd[1]);break; - case ISO14443B_RESET : snprintf(exp,size,"RESET");break; - case ISO14443B_COMPLETION : snprintf(exp,size,"COMPLETION");break; - case ISO14443B_AUTHENTICATE : snprintf(exp,size,"AUTHENTICATE");break; - default : snprintf(exp,size ,"?");break; - } - -} - /** * @brief iso14443B_CRC_check Checks CRC in command or response * @param isResponse diff --git a/client/cmdhflist.c b/client/cmdhflist.c index 1fa02cb3..bbfb24c8 100644 --- a/client/cmdhflist.c +++ b/client/cmdhflist.c @@ -83,6 +83,116 @@ uint8_t mifare_CRC_check(bool isResponse, uint8_t* data, uint8_t len) } } +void annotateIclass(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) +{ + switch(cmd[0]) + { + case ICLASS_CMD_ACTALL: snprintf(exp,size,"ACTALL"); break; + case ICLASS_CMD_READ_OR_IDENTIFY:{ + if(cmdsize > 1){ + snprintf(exp,size,"READ(%d)",cmd[1]); + }else{ + snprintf(exp,size,"IDENTIFY"); + } + break; + } + case ICLASS_CMD_SELECT: snprintf(exp,size,"SELECT"); break; + case ICLASS_CMD_PAGESEL: snprintf(exp,size,"PAGESEL(%d)", cmd[1]); break; + case ICLASS_CMD_READCHECK_KC:snprintf(exp,size,"READCHECK[Kc](%d)", cmd[1]); break; + case ICLASS_CMD_READCHECK_KD:snprintf(exp,size,"READCHECK[Kd](%d)", cmd[1]); break; + case ICLASS_CMD_CHECK: snprintf(exp,size,"CHECK"); break; + case ICLASS_CMD_DETECT: snprintf(exp,size,"DETECT"); break; + case ICLASS_CMD_HALT: snprintf(exp,size,"HALT"); break; + case ICLASS_CMD_UPDATE: snprintf(exp,size,"UPDATE(%d)",cmd[1]); break; + case ICLASS_CMD_ACT: snprintf(exp,size,"ACT"); break; + case ICLASS_CMD_READ4: snprintf(exp,size,"READ4(%d)",cmd[1]); break; + default: snprintf(exp,size,"?"); break; + } + return; +} + +void annotateIso15693(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) +{ + + if(cmd[0] == 0x26) + { + switch(cmd[1]){ + case ISO15693_INVENTORY :snprintf(exp, size, "INVENTORY");break; + case ISO15693_STAYQUIET :snprintf(exp, size, "STAY_QUIET");break; + default: snprintf(exp,size,"?"); break; + + } + }else if(cmd[0] == 0x02) + { + switch(cmd[1]) + { + case ISO15693_READBLOCK :snprintf(exp, size, "READBLOCK");break; + case ISO15693_WRITEBLOCK :snprintf(exp, size, "WRITEBLOCK");break; + case ISO15693_LOCKBLOCK :snprintf(exp, size, "LOCKBLOCK");break; + case ISO15693_READ_MULTI_BLOCK :snprintf(exp, size, "READ_MULTI_BLOCK");break; + case ISO15693_SELECT :snprintf(exp, size, "SELECT");break; + case ISO15693_RESET_TO_READY :snprintf(exp, size, "RESET_TO_READY");break; + case ISO15693_WRITE_AFI :snprintf(exp, size, "WRITE_AFI");break; + case ISO15693_LOCK_AFI :snprintf(exp, size, "LOCK_AFI");break; + case ISO15693_WRITE_DSFID :snprintf(exp, size, "WRITE_DSFID");break; + case ISO15693_LOCK_DSFID :snprintf(exp, size, "LOCK_DSFID");break; + case ISO15693_GET_SYSTEM_INFO :snprintf(exp, size, "GET_SYSTEM_INFO");break; + case ISO15693_READ_MULTI_SECSTATUS :snprintf(exp, size, "READ_MULTI_SECSTATUS");break; + default: snprintf(exp,size,"?"); break; + } + } +} + + +void annotateTopaz(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) +{ + switch(cmd[0]) { + case TOPAZ_REQA :snprintf(exp, size, "REQA");break; + case TOPAZ_WUPA :snprintf(exp, size, "WUPA");break; + case TOPAZ_RID :snprintf(exp, size, "RID");break; + case TOPAZ_RALL :snprintf(exp, size, "RALL");break; + case TOPAZ_READ :snprintf(exp, size, "READ");break; + case TOPAZ_WRITE_E :snprintf(exp, size, "WRITE-E");break; + case TOPAZ_WRITE_NE :snprintf(exp, size, "WRITE-NE");break; + case TOPAZ_RSEG :snprintf(exp, size, "RSEG");break; + case TOPAZ_READ8 :snprintf(exp, size, "READ8");break; + case TOPAZ_WRITE_E8 :snprintf(exp, size, "WRITE-E8");break; + case TOPAZ_WRITE_NE8 :snprintf(exp, size, "WRITE-NE8");break; + default: snprintf(exp,size,"?"); break; + } +} + + +/** +06 00 = INITIATE +0E xx = SELECT ID (xx = Chip-ID) +0B = Get UID +08 yy = Read Block (yy = block number) +09 yy dd dd dd dd = Write Block (yy = block number; dd dd dd dd = data to be written) +0C = Reset to Inventory +0F = Completion +0A 11 22 33 44 55 66 = Authenticate (11 22 33 44 55 66 = data to authenticate) +**/ + +void annotateIso14443b(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) +{ + switch(cmd[0]){ + case ISO14443B_REQB : snprintf(exp,size,"REQB");break; + case ISO14443B_ATTRIB : snprintf(exp,size,"ATTRIB");break; + case ISO14443B_HALT : snprintf(exp,size,"HALT");break; + case ISO14443B_INITIATE : snprintf(exp,size,"INITIATE");break; + case ISO14443B_SELECT : snprintf(exp,size,"SELECT(%d)",cmd[1]);break; + case ISO14443B_GET_UID : snprintf(exp,size,"GET UID");break; + case ISO14443B_READ_BLK : snprintf(exp,size,"READ_BLK(%d)", cmd[1]);break; + case ISO14443B_WRITE_BLK : snprintf(exp,size,"WRITE_BLK(%d)",cmd[1]);break; + case ISO14443B_RESET : snprintf(exp,size,"RESET");break; + case ISO14443B_COMPLETION : snprintf(exp,size,"COMPLETION");break; + case ISO14443B_AUTHENTICATE : snprintf(exp,size,"AUTHENTICATE");break; + default : snprintf(exp,size ,"?");break; + } + +} + void annotateIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) { switch(cmd[0]) diff --git a/client/cmdhflist.h b/client/cmdhflist.h index c2c9c03e..8f289b48 100644 --- a/client/cmdhflist.h +++ b/client/cmdhflist.h @@ -32,6 +32,10 @@ extern void ClearAuthData(); extern uint8_t iso14443A_CRC_check(bool isResponse, uint8_t* data, uint8_t len); extern uint8_t mifare_CRC_check(bool isResponse, uint8_t* data, uint8_t len); +extern void annotateIclass(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize); +extern void annotateIso15693(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize); +extern void annotateTopaz(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize); +extern void annotateIso14443b(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize); extern void annotateIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize); extern void annotateMifare(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize, uint8_t* parity, uint8_t paritysize, bool isResponse); extern bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, uint8_t *parity, bool isResponse, uint8_t *mfData, size_t *mfDataLen); From 079563a092d41495df0cc5ac00772d08b802d465 Mon Sep 17 00:00:00 2001 From: merlokk Date: Wed, 14 Feb 2018 12:36:22 +0200 Subject: [PATCH 086/127] small fix and added line to changelog. --- CHANGELOG.md | 1 + client/cmdhflist.c | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4162c638..f1d32ae0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,6 +46,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Added to `hf emv exec` MSD path for VISA and Mastercard and some other compatible EMV cards (Merlok) - Added to `hf emv exec` SDA, DDA, fast DDA, CDA calculations for VISA and Mastercard and some other compatible EMV cards (Merlok) - Added `hf emv test` - crypto tests for DES, AES, SHA, RSA, SDA, DDA, CDA and some other crypto functions (Merlok) +- Added `hf list mf` - deciphers crypto1 stream and works with first authentication and weak nested authentications (Merlok) ## [3.0.1][2017-06-08] diff --git a/client/cmdhflist.c b/client/cmdhflist.c index bbfb24c8..82e35c27 100644 --- a/client/cmdhflist.c +++ b/client/cmdhflist.c @@ -325,11 +325,12 @@ void annotateMifare(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize, uint8 if (cmdsize == 4 && isResponse) { snprintf(exp,size,"AUTH: nt %s", (AuthData.first_auth) ? "" : "(enc)"); MifareAuthState = masNrAr; - if (AuthData.first_auth) + if (AuthData.first_auth) { AuthData.nt = bytes_to_num(cmd, 4); - else + } else { AuthData.nt_enc = bytes_to_num(cmd, 4); AuthData.nt_enc_par = parity[0]; + } return; } else { MifareAuthState = masError; From 2896e490d9851053666f6b83c0ec3ffe7eb686ab Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Wed, 14 Feb 2018 15:41:39 -0500 Subject: [PATCH 087/127] update changelog +fix a comment typo + move clear bigbuf after fpgadownloadandgo... --- CHANGELOG.md | 2 ++ armsrc/lfops.c | 7 ++++--- armsrc/lfsampling.c | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4162c638..36e57b5b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac ## [unreleased][unreleased] ### Changed +- Adjusted `lf cmdread` to respond to client when complete and the client will then automatically call `data samples` - Improved backdoor detection missbehaving magic s50/1k tag (Fl0-0) - Deleted wipe functionality from `hf mf csetuid` (Merlok) - Changed `hf mf nested` logic (Merlok) @@ -21,6 +22,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Changed start sequence in Qt mode (fix: short commands hangs main Qt thread) (Merlok) ### Added +- Added a bitbang mode to `lf cmdread` if delay is 0 the cmd bits turn off and on the antenna with 0 and 1 respectively (marshmellow) - Added PAC/Stanley detection to lf search (marshmellow) - Added lf pac demod and lf pac read - extracts the raw blocks from a PAC/Stanley tag (marshmellow) - Added hf mf c* commands compatibity for 4k and gen1b backdoor (Fl0-0) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index c7a7a59d..f3bbbf84 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -33,14 +33,15 @@ void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint // use lf config settings sample_config *sc = getSamplingConfig(); - // clear read buffer - BigBuf_Clear_keep_EM(); - /* Make sure the tag is reset */ + // Make sure the tag is reset FpgaDownloadAndGo(FPGA_BITSTREAM_LF); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); WaitMS(2500); + // clear read buffer (after fpga bitstream loaded...) + BigBuf_Clear_keep_EM(); + // power on LFSetupFPGAForADC(sc->divisor, 1); diff --git a/armsrc/lfsampling.c b/armsrc/lfsampling.c index 084201a5..3b076265 100644 --- a/armsrc/lfsampling.c +++ b/armsrc/lfsampling.c @@ -266,7 +266,7 @@ uint32_t SnoopLF() } /** -* acquisition of Cotag LF signal. Similart to other LF, since the Cotag has such long datarate RF/384 +* acquisition of Cotag LF signal. Similar to other LF, since the Cotag has such long datarate RF/384 * and is Manchester?, we directly gather the manchester data into bigbuff **/ #define COTAG_T1 384 From 6dec58aa4492e4b8cc465e8c148d03ace52392f7 Mon Sep 17 00:00:00 2001 From: merlokk Date: Thu, 15 Feb 2018 00:18:02 +0200 Subject: [PATCH 088/127] small fix `hf list mf` --- client/cmdhflist.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/cmdhflist.c b/client/cmdhflist.c index 82e35c27..87d5b67d 100644 --- a/client/cmdhflist.c +++ b/client/cmdhflist.c @@ -393,7 +393,7 @@ bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, uint8_t *parity, bool isRes AuthData.ks3 = AuthData.at_enc ^ prng_successor(AuthData.nt, 96); mfLastKey = GetCrypto1ProbableKey(&AuthData); - PrintAndLog(" | * | key | probable key:%010"PRIx64" Prng:%s ks2:%08x ks3:%08x | |", + PrintAndLog(" | * | key | probable key:%012"PRIx64" Prng:%s ks2:%08x ks3:%08x | |", mfLastKey, validate_prng_nonce(AuthData.nt) ? "WEAK": "HARD", AuthData.ks2, @@ -411,7 +411,7 @@ bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, uint8_t *parity, bool isRes // check last used key if (mfLastKey) { if (NestedCheckKey(mfLastKey, &AuthData, cmd, cmdsize, parity)) { - PrintAndLog(" | * | key | last used key:%010"PRIx64" ks2:%08x ks3:%08x | |", + PrintAndLog(" | * | key | last used key:%012"PRIx64" ks2:%08x ks3:%08x | |", mfLastKey, AuthData.ks2, AuthData.ks3); @@ -424,7 +424,7 @@ bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, uint8_t *parity, bool isRes if (!traceCrypto1) { for (int defaultKeyCounter = 0; defaultKeyCounter < MifareDefaultKeysSize; defaultKeyCounter++){ if (NestedCheckKey(MifareDefaultKeys[defaultKeyCounter], &AuthData, cmd, cmdsize, parity)) { - PrintAndLog(" | * | key | default key:%010"PRIx64" ks2:%08x ks3:%08x | |", + PrintAndLog(" | * | key | default key:%012"PRIx64" ks2:%08x ks3:%08x | |", MifareDefaultKeys[defaultKeyCounter], AuthData.ks2, AuthData.ks3); From 738ed6e476ad7298db771d74931aa6d58fd8889b Mon Sep 17 00:00:00 2001 From: merlokk Date: Thu, 15 Feb 2018 00:20:00 +0200 Subject: [PATCH 089/127] small fix --- client/cmdhflist.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdhflist.c b/client/cmdhflist.c index 87d5b67d..cf69abba 100644 --- a/client/cmdhflist.c +++ b/client/cmdhflist.c @@ -456,7 +456,7 @@ bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, uint8_t *parity, bool isRes AuthData.nt = ntx; mfLastKey = GetCrypto1ProbableKey(&AuthData); - PrintAndLog(" | * | key | nested probable key:%010"PRIx64" ks2:%08x ks3:%08x | |", + PrintAndLog(" | * | key | nested probable key:%012"PRIx64" ks2:%08x ks3:%08x | |", mfLastKey, AuthData.ks2, AuthData.ks3); From f43b1038a21c1339c2fa1279409080943980b165 Mon Sep 17 00:00:00 2001 From: Tom Harkness Date: Thu, 22 Feb 2018 23:38:53 +1100 Subject: [PATCH 090/127] fix for swapped parity bits --- client/scripts/lf_bulk_program.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/scripts/lf_bulk_program.lua b/client/scripts/lf_bulk_program.lua index 4758c203..274f7510 100644 --- a/client/scripts/lf_bulk_program.lua +++ b/client/scripts/lf_bulk_program.lua @@ -61,8 +61,8 @@ local function cardHex(i,f) --As the function defaults to even parity and returns a boolean, --perform a 'not' function to get odd parity - high = evenparity(string.sub(stream,0,12)) and 1 or 0 - low = not evenparity(string.sub(stream,13)) and 1 or 0 + high = not evenparity(string.sub(stream,0,12)) and 1 or 0 + low = evenparity(string.sub(stream,13)) and 1 or 0 bits = bit32.bor(bit32.lshift(id,1), low) bits = bit32.bor(bits, bit32.lshift(high,25)) From d4d439a8aa5520671293ac7d9f01d8b7c424ebc0 Mon Sep 17 00:00:00 2001 From: Iceman Date: Mon, 26 Feb 2018 07:16:08 +0100 Subject: [PATCH 091/127] Update README.md Added hackerwarehouse --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 7258f918..09f23a6b 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,7 @@ The Proxmark3 is available for purchase (assembled and tested) from the following locations: * [RyscCorp](https://proxmark3.com/) (US) +* [Hackerwarehouse](https://hackerwarehouse.com/) (US) * [Elechouse](http://www.elechouse.com/) (HK) * [Lab401](https://lab401.com/) (FR) * [RFxSecure](http://www.rfxsecure.com/) (SG) From a5a830168fd3f6760b5b7cad51e3f2f0505097e9 Mon Sep 17 00:00:00 2001 From: Michael Farrell Date: Thu, 22 Mar 2018 02:05:03 +1100 Subject: [PATCH 092/127] OSX: Multiple libedit/readline fixes (#585) * OSX: Multiple libedit/readline fixes. --- client/proxmark3.c | 2 +- client/ui.c | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/client/proxmark3.c b/client/proxmark3.c index 95dd7cb9..1b64f68b 100644 --- a/client/proxmark3.c +++ b/client/proxmark3.c @@ -132,7 +132,7 @@ main_loop(char *script_cmds_file, char *script_cmd, bool usb_present) { printf("executing commands from file: %s\n", script_cmds_file); } } - + read_history(".history"); while(1) { diff --git a/client/ui.c b/client/ui.c index 8faed6e8..dc122d2f 100644 --- a/client/ui.c +++ b/client/ui.c @@ -53,8 +53,11 @@ void PrintAndLog(char *fmt, ...) } } + // If there is an incoming message from the hardware (eg: lf hid read) in + // the background (while the prompt is displayed and accepting user input), + // stash the prompt and bring it back later. #ifdef RL_STATE_READCMD - // We are using GNU readline. + // We are using GNU readline. libedit (OSX) doesn't support this flag. int need_hack = (rl_readline_state & RL_STATE_READCMD) > 0; if (need_hack) { @@ -64,9 +67,6 @@ void PrintAndLog(char *fmt, ...) rl_replace_line("", 0); rl_redisplay(); } -#else - // We are using libedit (OSX), which doesn't support this flag. - int need_hack = 0; #endif va_start(argptr, fmt); @@ -76,6 +76,8 @@ void PrintAndLog(char *fmt, ...) va_end(argptr); printf("\n"); +#ifdef RL_STATE_READCMD + // We are using GNU readline. libedit (OSX) doesn't support this flag. if (need_hack) { rl_restore_prompt(); rl_replace_line(saved_line, 0); @@ -83,6 +85,7 @@ void PrintAndLog(char *fmt, ...) rl_redisplay(); free(saved_line); } +#endif if (logging && logfile) { vfprintf(logfile, fmt, argptr2); From b24930c764849e16048936d62ff426a05083d2b1 Mon Sep 17 00:00:00 2001 From: James Chambers Date: Fri, 23 Mar 2018 15:26:30 -0400 Subject: [PATCH 093/127] mfu read block: retry block with bad CRC (#584) * mfu read block: retry block with bad CRC, command timeout, or unknown response. --- armsrc/mifareutil.c | 49 ++++++++++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/armsrc/mifareutil.c b/armsrc/mifareutil.c index 38ca934a..684b5e36 100644 --- a/armsrc/mifareutil.c +++ b/armsrc/mifareutil.c @@ -405,31 +405,48 @@ int mifare_ultra_auth(uint8_t *keybytes){ return 1; } + +#define MFU_MAX_RETRIES 5 int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData) { uint16_t len; uint8_t bt[2]; uint8_t receivedAnswer[MAX_FRAME_SIZE]; uint8_t receivedAnswerPar[MAX_PARITY_SIZE]; - + uint8_t retries; + int result = 0; - len = mifare_sendcmd_short(NULL, 1, 0x30, blockNo, receivedAnswer, receivedAnswerPar, NULL); - if (len == 1) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); - return 1; + for (retries = 0; retries < MFU_MAX_RETRIES; retries++) { + len = mifare_sendcmd_short(NULL, 1, 0x30, blockNo, receivedAnswer, receivedAnswerPar, NULL); + if (len == 1) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); + result = 1; + continue; + } + if (len != 18) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: card timeout. len: %x", len); + result = 2; + continue; + } + + memcpy(bt, receivedAnswer + 16, 2); + AppendCrc14443a(receivedAnswer, 16); + if (bt[0] != receivedAnswer[16] || bt[1] != receivedAnswer[17]) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd CRC response error."); + result = 3; + continue; + } + + // No errors encountered; don't retry + result = 0; + break; } - if (len != 18) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: card timeout. len: %x", len); - return 2; + + if (result != 0) { + Dbprintf("Cmd Error: too many retries; read failed"); + return result; } - - memcpy(bt, receivedAnswer + 16, 2); - AppendCrc14443a(receivedAnswer, 16); - if (bt[0] != receivedAnswer[16] || bt[1] != receivedAnswer[17]) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd CRC response error."); - return 3; - } - + memcpy(blockData, receivedAnswer, 14); return 0; } From b05611a30bc5d4815a7603afe6593f2e852be91a Mon Sep 17 00:00:00 2001 From: Matthew Daley Date: Wed, 28 Mar 2018 23:37:07 +1300 Subject: [PATCH 094/127] Fix offset Indala UID display Commit 1dae9811f22b7f2cea340cee6945cb349046129d extended the amount of fixed bits searched for when decoding 64-bit Indala. These additional bits come from the end of one UID, and therefore need to be skipped past when actually retrieving the UID. --- common/lfdemod.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/common/lfdemod.c b/common/lfdemod.c index f470371a..fd149045 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -1780,6 +1780,7 @@ int IOdemodFSK(uint8_t *dest, size_t size, int *waveStartIdx) { // indala id decoding int indala64decode(uint8_t *bitStream, size_t *size, uint8_t *invert) { //standard 64 bit indala formats including 26 bit 40134 format + // Note: these start with 3 bits from the end of one UID; the rest are from a subsequent one uint8_t preamble64[] = {1,0,1,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 1}; uint8_t preamble64_i[] = {0,1,0,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 0}; size_t startidx = 0; @@ -1791,6 +1792,10 @@ int indala64decode(uint8_t *bitStream, size_t *size, uint8_t *invert) { *invert ^= 1; } if (found_size != 64) return -2; + + // Skip the aforementioned 3 bits from the previous UID + startidx += 3; + if (*invert==1) for (size_t i = startidx; i < found_size + startidx; i++) bitStream[i] ^= 1; From 7ecf7cf6cc7620a34306902ee3505afc17dc0de0 Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Wed, 28 Mar 2018 08:50:08 -0400 Subject: [PATCH 095/127] Revert "Fix offset Indala UID display" --- common/lfdemod.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/common/lfdemod.c b/common/lfdemod.c index fd149045..f470371a 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -1780,7 +1780,6 @@ int IOdemodFSK(uint8_t *dest, size_t size, int *waveStartIdx) { // indala id decoding int indala64decode(uint8_t *bitStream, size_t *size, uint8_t *invert) { //standard 64 bit indala formats including 26 bit 40134 format - // Note: these start with 3 bits from the end of one UID; the rest are from a subsequent one uint8_t preamble64[] = {1,0,1,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 1}; uint8_t preamble64_i[] = {0,1,0,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 0}; size_t startidx = 0; @@ -1792,10 +1791,6 @@ int indala64decode(uint8_t *bitStream, size_t *size, uint8_t *invert) { *invert ^= 1; } if (found_size != 64) return -2; - - // Skip the aforementioned 3 bits from the previous UID - startidx += 3; - if (*invert==1) for (size_t i = startidx; i < found_size + startidx; i++) bitStream[i] ^= 1; From 53c7a7053d06af60388507c7d38252af1b96696a Mon Sep 17 00:00:00 2001 From: AnthraX1 Date: Sat, 31 Mar 2018 02:54:45 +1100 Subject: [PATCH 096/127] Fix empty key list bug in mfkeys.lua (#579) When input key list size is greater than 85, table.concat() returns empty because the last parameter is the end offset not the increment value. --- client/scripts/mfkeys.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/scripts/mfkeys.lua b/client/scripts/mfkeys.lua index 33027d31..671ce03d 100644 --- a/client/scripts/mfkeys.lua +++ b/client/scripts/mfkeys.lua @@ -57,7 +57,7 @@ function checkBlock(blockNo, keys, keyType) while remaining > 0 do local n,data = remaining, nil if remaining > 85 then n = 85 end - local data = table.concat(keys,"",start,n) + local data = table.concat(keys, "", start, start + n - 1) --print("data",data) --print("data len", #data) print(("Testing block %d, keytype %d, with %d keys"):format(blockNo, keyType, n)) From 3bcc4d77e1ea1d383e3dd15935efda2f36af4881 Mon Sep 17 00:00:00 2001 From: pwpiwi Date: Fri, 30 Mar 2018 17:55:41 +0200 Subject: [PATCH 097/127] add: save and load options in hf list (#577) --- client/cmdhf.c | 181 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 133 insertions(+), 48 deletions(-) diff --git a/client/cmdhf.c b/client/cmdhf.c index ab7bfcdf..82313ae0 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -355,21 +355,44 @@ int CmdHFList(const char *Cmd) { bool showWaitCycles = false; bool markCRCBytes = false; + bool loadFromFile = false; + bool saveToFile = false; + char param1 = '\0'; + char param2 = '\0'; + char param3 = '\0'; char type[40] = {0}; - int tlen = param_getstr(Cmd,0,type, sizeof(type)); - char param1 = param_getchar(Cmd, 1); - char param2 = param_getchar(Cmd, 2); - bool errors = false; + char filename[FILE_PATH_SIZE]; uint8_t protocol = 0; - //Validate params + + // parse command line + int tlen = param_getstr(Cmd, 0, type, sizeof(type)); + if (param_getlength(Cmd, 1) == 1) { + param1 = param_getchar(Cmd, 1); + } else { + param_getstr(Cmd, 1, filename, sizeof(filename)); + } + if (param_getlength(Cmd, 2) == 1) { + param2 = param_getchar(Cmd, 2); + } else if (strlen(filename) == 0) { + param_getstr(Cmd, 2, filename, sizeof(filename)); + } + if (param_getlength(Cmd, 3) == 1) { + param3 = param_getchar(Cmd, 3); + } else if (strlen(filename) == 0) { + param_getstr(Cmd, 3, filename, sizeof(filename)); + } + + // Validate param1 + bool errors = false; if(tlen == 0) { errors = true; } if(param1 == 'h' - || (param1 != 0 && param1 != 'f' && param1 != 'c') - || (param2 != 0 && param2 != 'f' && param2 != 'c')) { + || (param1 != 0 && param1 != 'f' && param1 != 'c' && param1 != 'l') + || (param2 != 0 && param2 != 'f' && param2 != 'c' && param2 != 'l') + || (param3 != 0 && param3 != 'f' && param3 != 'c' && param3 != 'l')) { errors = true; } @@ -382,20 +405,45 @@ int CmdHFList(const char *Cmd) protocol = ISO_14443A; } else if(strcmp(type, "14b") == 0) { protocol = ISO_14443B; - } else if(strcmp(type,"topaz")== 0) { + } else if(strcmp(type,"topaz") == 0) { protocol = TOPAZ; - } else if(strcmp(type,"raw")== 0) { - protocol = -1;//No crc, no annotations + } else if(strcmp(type,"raw") == 0) { + protocol = -1; //No crc, no annotations + } else if (strcmp(type, "save") == 0) { + saveToFile = true; } else { errors = true; } } + + if (param1 == 'f' || param2 == 'f' || param3 == 'f') { + showWaitCycles = true; + } + if (param1 == 'c' || param2 == 'c' || param3 == 'c') { + markCRCBytes = true; + } + + if (param1 == 'l' || param2 == 'l' || param3 == 'l') { + loadFromFile = true; + } + + if ((loadFromFile || saveToFile) && strlen(filename) == 0) { + errors = true; + } + + if (loadFromFile && saveToFile) { + errors = true; + } + if (errors) { - PrintAndLog("List protocol data in trace buffer."); - PrintAndLog("Usage: hf list [f][c]"); + PrintAndLog("List or save protocol data."); + PrintAndLog("Usage: hf list [f] [c] [l ]"); + PrintAndLog(" hf list save "); PrintAndLog(" f - show frame delay times as well"); PrintAndLog(" c - mark CRC bytes"); + PrintAndLog(" l - load data from file instead of trace buffer"); + PrintAndLog(" save - save data to file"); PrintAndLog("Supported values:"); PrintAndLog(" raw - just show raw data without annotations"); PrintAndLog(" 14a - interpret data as iso14443a communications"); @@ -406,52 +454,89 @@ int CmdHFList(const char *Cmd) PrintAndLog(""); PrintAndLog("example: hf list 14a f"); PrintAndLog("example: hf list iclass"); + PrintAndLog("example: hf list save myCardTrace.trc"); + PrintAndLog("example: hf list 14a l myCardTrace.trc"); return 0; } - if (param1 == 'f' || param2 == 'f') { - showWaitCycles = true; - } - - if (param1 == 'c' || param2 == 'c') { - markCRCBytes = true; - } - uint8_t *trace; - uint16_t tracepos = 0; - trace = malloc(USB_CMD_DATA_SIZE); - - // Query for the size of the trace - UsbCommand response; - GetFromBigBuf(trace, USB_CMD_DATA_SIZE, 0); - WaitForResponse(CMD_ACK, &response); - uint16_t traceLen = response.arg[2]; - if (traceLen > USB_CMD_DATA_SIZE) { - uint8_t *p = realloc(trace, traceLen); - if (p == NULL) { + uint32_t tracepos = 0; + uint32_t traceLen = 0; + + if (loadFromFile) { + #define TRACE_CHUNK_SIZE (1<<16) // 64K to start with. Will be enough for BigBuf and some room for future extensions + FILE *tracefile = NULL; + size_t bytes_read; + trace = malloc(TRACE_CHUNK_SIZE); + if (trace == NULL) { PrintAndLog("Cannot allocate memory for trace"); - free(trace); return 2; } - trace = p; - GetFromBigBuf(trace, traceLen, 0); - WaitForResponse(CMD_ACK, NULL); + if ((tracefile = fopen(filename,"rb")) == NULL) { + PrintAndLog("Could not open file %s", filename); + free(trace); + return 0; + } + while (!feof(tracefile)) { + bytes_read = fread(trace+traceLen, 1, TRACE_CHUNK_SIZE, tracefile); + traceLen += bytes_read; + if (!feof(tracefile)) { + uint8_t *p = realloc(trace, traceLen + TRACE_CHUNK_SIZE); + if (p == NULL) { + PrintAndLog("Cannot allocate memory for trace"); + free(trace); + fclose(tracefile); + return 2; + } + trace = p; + } + } + fclose(tracefile); + } else { + trace = malloc(USB_CMD_DATA_SIZE); + // Query for the size of the trace + UsbCommand response; + GetFromBigBuf(trace, USB_CMD_DATA_SIZE, 0); + WaitForResponse(CMD_ACK, &response); + traceLen = response.arg[2]; + if (traceLen > USB_CMD_DATA_SIZE) { + uint8_t *p = realloc(trace, traceLen); + if (p == NULL) { + PrintAndLog("Cannot allocate memory for trace"); + free(trace); + return 2; + } + trace = p; + GetFromBigBuf(trace, traceLen, 0); + WaitForResponse(CMD_ACK, NULL); + } } - - PrintAndLog("Recorded Activity (TraceLen = %d bytes)", traceLen); - PrintAndLog(""); - PrintAndLog("Start = Start of Start Bit, End = End of last modulation. Src = Source of Transfer"); - PrintAndLog("iso14443a - All times are in carrier periods (1/13.56Mhz)"); - PrintAndLog("iClass - Timings are not as accurate"); - PrintAndLog(""); - PrintAndLog(" Start | End | Src | Data (! denotes parity error) | CRC | Annotation |"); - PrintAndLog("------------|------------|-----|-----------------------------------------------------------------|-----|--------------------|"); - ClearAuthData(); - while(tracepos < traceLen) - { - tracepos = printTraceLine(tracepos, traceLen, trace, protocol, showWaitCycles, markCRCBytes); + if (saveToFile) { + FILE *tracefile = NULL; + if ((tracefile = fopen(filename,"wb")) == NULL) { + PrintAndLog("Could not create file %s", filename); + return 1; + } + fwrite(trace, 1, traceLen, tracefile); + PrintAndLog("Recorded Activity (TraceLen = %d bytes) written to file %s", traceLen, filename); + fclose(tracefile); + } else { + PrintAndLog("Recorded Activity (TraceLen = %d bytes)", traceLen); + PrintAndLog(""); + PrintAndLog("Start = Start of Start Bit, End = End of last modulation. Src = Source of Transfer"); + PrintAndLog("iso14443a - All times are in carrier periods (1/13.56Mhz)"); + PrintAndLog("iClass - Timings are not as accurate"); + PrintAndLog(""); + PrintAndLog(" Start | End | Src | Data (! denotes parity error) | CRC | Annotation |"); + PrintAndLog("------------|------------|-----|-----------------------------------------------------------------|-----|--------------------|"); + + ClearAuthData(); + while(tracepos < traceLen) + { + tracepos = printTraceLine(tracepos, traceLen, trace, protocol, showWaitCycles, markCRCBytes); + } } free(trace); From f5ecd97b15797e14e691bb6f3562ec1685c96bca Mon Sep 17 00:00:00 2001 From: pwpiwi Date: Sat, 31 Mar 2018 09:52:43 +0200 Subject: [PATCH 098/127] USB comm: prepare for @micolous change (PR#463) (#587) * move communication related code from proxmark3.c and cmdmain.c to new file comms.c * replace byte_t by uint8_t in uart_posix.c and uart_win32.c * move OpenProxmark() and CloseProxmark() from flasher.c to flash.c * move print_lock mutex including initializer to ui.c * minor changes in printing help texts * no changes in comms functionality yet --- client/Makefile | 3 +- client/cmdmain.c | 152 +-------------------------- client/cmdmain.h | 7 +- client/cmdparser.c | 4 +- client/comms.c | 252 +++++++++++++++++++++++++++++++++++++++++++++ client/comms.h | 45 ++++++++ client/flash.c | 39 +++++-- client/flash.h | 6 +- client/flasher.c | 58 ++++------- client/proxgui.h | 1 - client/proxmark3.c | 98 ++---------------- client/ui.c | 3 +- client/ui.h | 1 - uart/uart.h | 14 ++- uart/uart_posix.c | 4 +- uart/uart_win32.c | 4 +- 16 files changed, 384 insertions(+), 307 deletions(-) create mode 100644 client/comms.c create mode 100644 client/comms.h diff --git a/client/Makefile b/client/Makefile index bf3c8d36..883f3b6f 100644 --- a/client/Makefile +++ b/client/Makefile @@ -170,7 +170,8 @@ CMDSRCS = crapto1/crapto1.c\ cmdscript.c\ pm3_binlib.c\ pm3_bitlib.c\ - protocols.c + protocols.c\ + comms.c cpu_arch = $(shell uname -m) ifneq ($(findstring 86, $(cpu_arch)), ) diff --git a/client/cmdmain.c b/client/cmdmain.c index 8d9313f9..10948c97 100644 --- a/client/cmdmain.c +++ b/client/cmdmain.c @@ -34,15 +34,6 @@ unsigned int current_command = CMD_UNKNOWN; static int CmdHelp(const char *Cmd); static int CmdQuit(const char *Cmd); -//For storing command that are received from the device -#define CMD_BUFFER_SIZE 50 -static UsbCommand cmdBuffer[CMD_BUFFER_SIZE]; -//Points to the next empty position to write to -static int cmd_head;//Starts as 0 -//Points to the position of the last unread command -static int cmd_tail;//Starts as 0 -// to lock cmdBuffer operations from different threads -static pthread_mutex_t cmdBufferMutex = PTHREAD_MUTEX_INITIALIZER; static command_t CommandTable[] = { @@ -61,6 +52,7 @@ command_t* getTopLevelCommandTable() { return CommandTable; } + int CmdHelp(const char *Cmd) { CmdsHelp(CommandTable); @@ -72,113 +64,6 @@ int CmdQuit(const char *Cmd) return 99; } -/** - * @brief This method should be called when sending a new command to the pm3. In case any old - * responses from previous commands are stored in the buffer, a call to this method should clear them. - * A better method could have been to have explicit command-ACKS, so we can know which ACK goes to which - * operation. Right now we'll just have to live with this. - */ -void clearCommandBuffer() -{ - //This is a very simple operation - pthread_mutex_lock(&cmdBufferMutex); - cmd_tail = cmd_head; - pthread_mutex_unlock(&cmdBufferMutex); -} - -/** - * @brief storeCommand stores a USB command in a circular buffer - * @param UC - */ -void storeCommand(UsbCommand *command) -{ - pthread_mutex_lock(&cmdBufferMutex); - if( ( cmd_head+1) % CMD_BUFFER_SIZE == cmd_tail) - { - //If these two are equal, we're about to overwrite in the - // circular buffer. - PrintAndLog("WARNING: Command buffer about to overwrite command! This needs to be fixed!"); - } - //Store the command at the 'head' location - UsbCommand* destination = &cmdBuffer[cmd_head]; - memcpy(destination, command, sizeof(UsbCommand)); - - cmd_head = (cmd_head +1) % CMD_BUFFER_SIZE; //increment head and wrap - pthread_mutex_unlock(&cmdBufferMutex); -} - - -/** - * @brief getCommand gets a command from an internal circular buffer. - * @param response location to write command - * @return 1 if response was returned, 0 if nothing has been received - */ -int getCommand(UsbCommand* response) -{ - pthread_mutex_lock(&cmdBufferMutex); - //If head == tail, there's nothing to read, or if we just got initialized - if(cmd_head == cmd_tail){ - pthread_mutex_unlock(&cmdBufferMutex); - return 0; - } - //Pick out the next unread command - UsbCommand* last_unread = &cmdBuffer[cmd_tail]; - memcpy(response, last_unread, sizeof(UsbCommand)); - //Increment tail - this is a circular buffer, so modulo buffer size - cmd_tail = (cmd_tail +1 ) % CMD_BUFFER_SIZE; - pthread_mutex_unlock(&cmdBufferMutex); - return 1; -} - - -/** - * Waits for a certain response type. This method waits for a maximum of - * ms_timeout milliseconds for a specified response command. - *@brief WaitForResponseTimeout - * @param cmd command to wait for - * @param response struct to copy received command into. - * @param ms_timeout - * @return true if command was returned, otherwise false - */ -bool WaitForResponseTimeoutW(uint32_t cmd, UsbCommand* response, size_t ms_timeout, bool show_warning) { - - UsbCommand resp; - - if (response == NULL) { - response = &resp; - } - - uint64_t start_time = msclock(); - - // Wait until the command is received - while (true) { - while(getCommand(response)) { - if(response->cmd == cmd){ - return true; - } - } - if (msclock() - start_time > ms_timeout) { - break; - } - if (msclock() - start_time > 2000 && show_warning) { - PrintAndLog("Waiting for a response from the proxmark..."); - PrintAndLog("You can cancel this operation by pressing the pm3 button"); - show_warning = false; - } - } - return false; -} - - -bool WaitForResponseTimeout(uint32_t cmd, UsbCommand* response, size_t ms_timeout) { - return WaitForResponseTimeoutW(cmd, response, ms_timeout, true); -} - -bool WaitForResponse(uint32_t cmd, UsbCommand* response) { - return WaitForResponseTimeoutW(cmd, response, -1, true); -} - - //----------------------------------------------------------------------------- // Entry point into our code: called whenever the user types a command and // then presses Enter, which the full command line that they typed. @@ -187,38 +72,3 @@ int CommandReceived(char *Cmd) { return CmdsParse(CommandTable, Cmd); } - -//----------------------------------------------------------------------------- -// Entry point into our code: called whenever we received a packet over USB -// that we weren't necessarily expecting, for example a debug print. -//----------------------------------------------------------------------------- -void UsbCommandReceived(UsbCommand *UC) -{ - switch(UC->cmd) { - // First check if we are handling a debug message - case CMD_DEBUG_PRINT_STRING: { - char s[USB_CMD_DATA_SIZE+1]; - memset(s, 0x00, sizeof(s)); - size_t len = MIN(UC->arg[0],USB_CMD_DATA_SIZE); - memcpy(s,UC->d.asBytes,len); - PrintAndLog("#db# %s", s); - return; - } break; - - case CMD_DEBUG_PRINT_INTEGERS: { - PrintAndLog("#db# %08x, %08x, %08x \r\n", UC->arg[0], UC->arg[1], UC->arg[2]); - return; - } break; - - case CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K: { - memcpy(sample_buf+(UC->arg[0]),UC->d.asBytes,UC->arg[1]); - return; - } break; - - default: - storeCommand(UC); - break; - } - -} - diff --git a/client/cmdmain.h b/client/cmdmain.h index d39bc114..a833b41e 100644 --- a/client/cmdmain.h +++ b/client/cmdmain.h @@ -15,13 +15,10 @@ #include #include "usb_cmd.h" #include "cmdparser.h" +#include "comms.h" + -extern void UsbCommandReceived(UsbCommand *UC); extern int CommandReceived(char *Cmd); -extern bool WaitForResponseTimeoutW(uint32_t cmd, UsbCommand* response, size_t ms_timeout, bool show_warning); -extern bool WaitForResponseTimeout(uint32_t cmd, UsbCommand* response, size_t ms_timeout); -extern bool WaitForResponse(uint32_t cmd, UsbCommand* response); -extern void clearCommandBuffer(); extern command_t* getTopLevelCommandTable(); #endif diff --git a/client/cmdparser.c b/client/cmdparser.c index 32508997..f4d3c404 100644 --- a/client/cmdparser.c +++ b/client/cmdparser.c @@ -8,12 +8,14 @@ // Command parser //----------------------------------------------------------------------------- +#include "cmdparser.h" + #include #include #include #include "ui.h" -#include "cmdparser.h" #include "proxmark3.h" +#include "comms.h" void CmdsHelp(const command_t Commands[]) diff --git a/client/comms.c b/client/comms.c new file mode 100644 index 00000000..5b8266fe --- /dev/null +++ b/client/comms.c @@ -0,0 +1,252 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2009 Michael Gernoth +// Copyright (C) 2010 iZsh +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Code for communicating with the proxmark3 hardware. +//----------------------------------------------------------------------------- + +#include + +#include "comms.h" +#include "uart.h" +#include "ui.h" +#include "common.h" +#include "data.h" +#include "util_posix.h" + +// Declare globals. + +// Serial port that we are communicating with the PM3 on. +serial_port sp; + +// If TRUE, then there is no active connection to the PM3, and we will drop commands sent. +bool offline; + +// Transmit buffer. +// TODO: Use locks and execute this on the main thread, rather than the receiver +// thread. Running on the main thread means we need to be careful in the +// flasher, as it means SendCommand is no longer async, and can't be used as a +// buffer for a pending command when the connection is re-established. +static UsbCommand txcmd; +volatile static bool txcmd_pending = false; + +// Used by UsbReceiveCommand as a ring buffer for messages that are yet to be +// processed by a command handler (WaitForResponse{,Timeout}) +static UsbCommand cmdBuffer[CMD_BUFFER_SIZE]; + +// Points to the next empty position to write to +static int cmd_head = 0; + +// Points to the position of the last unread command +static int cmd_tail = 0; + +// to lock cmdBuffer operations from different threads +static pthread_mutex_t cmdBufferMutex = PTHREAD_MUTEX_INITIALIZER; + + +void SendCommand(UsbCommand *c) { + #if 0 + printf("Sending %d bytes\n", sizeof(UsbCommand)); + #endif + + if (offline) { + PrintAndLog("Sending bytes to proxmark failed - offline"); + return; + } + /** + The while-loop below causes hangups at times, when the pm3 unit is unresponsive + or disconnected. The main console thread is alive, but comm thread just spins here. + Not good.../holiman + **/ + while(txcmd_pending); + txcmd = *c; + txcmd_pending = true; +} + + +/** + * @brief This method should be called when sending a new command to the pm3. In case any old + * responses from previous commands are stored in the buffer, a call to this method should clear them. + * A better method could have been to have explicit command-ACKS, so we can know which ACK goes to which + * operation. Right now we'll just have to live with this. + */ +void clearCommandBuffer() +{ + //This is a very simple operation + pthread_mutex_lock(&cmdBufferMutex); + cmd_tail = cmd_head; + pthread_mutex_unlock(&cmdBufferMutex); +} + +/** + * @brief storeCommand stores a USB command in a circular buffer + * @param UC + */ +void storeCommand(UsbCommand *command) +{ + pthread_mutex_lock(&cmdBufferMutex); + if( (cmd_head+1) % CMD_BUFFER_SIZE == cmd_tail) + { + // If these two are equal, we're about to overwrite in the + // circular buffer. + PrintAndLog("WARNING: Command buffer about to overwrite command! This needs to be fixed!"); + } + + // Store the command at the 'head' location + UsbCommand* destination = &cmdBuffer[cmd_head]; + memcpy(destination, command, sizeof(UsbCommand)); + + cmd_head = (cmd_head +1) % CMD_BUFFER_SIZE; //increment head and wrap + pthread_mutex_unlock(&cmdBufferMutex); +} + + +/** + * @brief getCommand gets a command from an internal circular buffer. + * @param response location to write command + * @return 1 if response was returned, 0 if nothing has been received + */ +int getCommand(UsbCommand* response) +{ + pthread_mutex_lock(&cmdBufferMutex); + //If head == tail, there's nothing to read, or if we just got initialized + if (cmd_head == cmd_tail){ + pthread_mutex_unlock(&cmdBufferMutex); + return 0; + } + + //Pick out the next unread command + UsbCommand* last_unread = &cmdBuffer[cmd_tail]; + memcpy(response, last_unread, sizeof(UsbCommand)); + //Increment tail - this is a circular buffer, so modulo buffer size + cmd_tail = (cmd_tail + 1) % CMD_BUFFER_SIZE; + + pthread_mutex_unlock(&cmdBufferMutex); + return 1; +} + + +//----------------------------------------------------------------------------- +// Entry point into our code: called whenever we received a packet over USB +// that we weren't necessarily expecting, for example a debug print. +//----------------------------------------------------------------------------- +void UsbCommandReceived(UsbCommand *UC) +{ + switch(UC->cmd) { + // First check if we are handling a debug message + case CMD_DEBUG_PRINT_STRING: { + char s[USB_CMD_DATA_SIZE+1]; + memset(s, 0x00, sizeof(s)); + size_t len = MIN(UC->arg[0],USB_CMD_DATA_SIZE); + memcpy(s,UC->d.asBytes,len); + PrintAndLog("#db# %s", s); + return; + } break; + + case CMD_DEBUG_PRINT_INTEGERS: { + PrintAndLog("#db# %08x, %08x, %08x \r\n", UC->arg[0], UC->arg[1], UC->arg[2]); + return; + } break; + + case CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K: { + memcpy(sample_buf+(UC->arg[0]),UC->d.asBytes,UC->arg[1]); + return; + } break; + + default: + storeCommand(UC); + break; + } + +} + + +void +#ifdef __has_attribute +#if __has_attribute(force_align_arg_pointer) +__attribute__((force_align_arg_pointer)) +#endif +#endif +*uart_receiver(void *targ) { + receiver_arg *arg = (receiver_arg*)targ; + size_t rxlen; + uint8_t rx[sizeof(UsbCommand)]; + uint8_t *prx = rx; + + while (arg->run) { + rxlen = 0; + if (uart_receive(sp, prx, sizeof(UsbCommand) - (prx-rx), &rxlen) && rxlen) { + prx += rxlen; + if (prx-rx < sizeof(UsbCommand)) { + continue; + } + UsbCommandReceived((UsbCommand*)rx); + } + prx = rx; + + if(txcmd_pending) { + if (!uart_send(sp, (uint8_t*) &txcmd, sizeof(UsbCommand))) { + PrintAndLog("Sending bytes to proxmark failed"); + } + txcmd_pending = false; + } + } + + pthread_exit(NULL); + return NULL; +} + + +/** + * Waits for a certain response type. This method waits for a maximum of + * ms_timeout milliseconds for a specified response command. + *@brief WaitForResponseTimeout + * @param cmd command to wait for + * @param response struct to copy received command into. + * @param ms_timeout + * @return true if command was returned, otherwise false + */ +bool WaitForResponseTimeoutW(uint32_t cmd, UsbCommand* response, size_t ms_timeout, bool show_warning) { + + UsbCommand resp; + + if (response == NULL) { + response = &resp; + } + + uint64_t start_time = msclock(); + + // Wait until the command is received + while (true) { + while(getCommand(response)) { + if(response->cmd == cmd){ + return true; + } + } + + if (msclock() - start_time > ms_timeout) { + break; + } + + if (msclock() - start_time > 2000 && show_warning) { + PrintAndLog("Waiting for a response from the proxmark..."); + PrintAndLog("You can cancel this operation by pressing the pm3 button"); + show_warning = false; + } + } + return false; +} + + +bool WaitForResponseTimeout(uint32_t cmd, UsbCommand* response, size_t ms_timeout) { + return WaitForResponseTimeoutW(cmd, response, ms_timeout, true); +} + +bool WaitForResponse(uint32_t cmd, UsbCommand* response) { + return WaitForResponseTimeoutW(cmd, response, -1, true); +} + diff --git a/client/comms.h b/client/comms.h new file mode 100644 index 00000000..40576018 --- /dev/null +++ b/client/comms.h @@ -0,0 +1,45 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2009 Michael Gernoth +// Copyright (C) 2010 iZsh +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Code for communicating with the proxmark3 hardware. +//----------------------------------------------------------------------------- + +#ifndef COMMS_H_ +#define COMMS_H_ + +#include +#include + +#include "usb_cmd.h" +#include "uart.h" + +#ifndef CMD_BUFFER_SIZE +#define CMD_BUFFER_SIZE 50 +#endif + +typedef struct { + // If TRUE, continue running the uart_receiver thread + bool run; + + // Lock around serial port receives + pthread_mutex_t recv_lock; +} receiver_arg; + +void SendCommand(UsbCommand *c); + +void *uart_receiver(void *targ); +void UsbCommandReceived(UsbCommand *UC); +void clearCommandBuffer(); +bool WaitForResponseTimeoutW(uint32_t cmd, UsbCommand* response, size_t ms_timeout, bool show_warning); +bool WaitForResponseTimeout(uint32_t cmd, UsbCommand* response, size_t ms_timeout); +bool WaitForResponse(uint32_t cmd, UsbCommand* response); + +extern serial_port sp; +extern bool offline; + +#endif // COMMS_H_ diff --git a/client/flash.c b/client/flash.c index 7622e8a5..894095e7 100644 --- a/client/flash.c +++ b/client/flash.c @@ -20,11 +20,12 @@ #include "elf.h" #include "proxendian.h" #include "usb_cmd.h" +#include "uart.h" void SendCommand(UsbCommand* txcmd); void ReceiveCommand(UsbCommand* rxcmd); -void CloseProxmark(); -int OpenProxmark(size_t i); + +serial_port sp; // FIXME: what the fuckity fuck unsigned int current_command = CMD_UNKNOWN; @@ -44,6 +45,22 @@ static const uint8_t elf_ident[] = { EV_CURRENT }; +void CloseProxmark(const char *serial_port_name) { + // Clean up the port + uart_close(sp); + // Fix for linux, it seems that it is extremely slow to release the serial port file descriptor /dev/* + unlink(serial_port_name); +} + +int OpenProxmark(size_t i, const char *serial_port_name) { + sp = uart_open(serial_port_name); + if (sp == INVALID_SERIAL_PORT || sp == CLAIMED_SERIAL_PORT) { + //poll once a second + return 0; + } + return 1; +} + // Turn PHDRs into flasher segments, checking for PHDR sanity and merging adjacent // unaligned segments if needed static int build_segs_from_phdrs(flash_file_t *ctx, FILE *fd, Elf32_Phdr *phdrs, int num_phdrs) @@ -278,7 +295,7 @@ static int get_proxmark_state(uint32_t *state) { UsbCommand c; c.cmd = CMD_DEVICE_INFO; - SendCommand(&c); + SendCommand(&c); UsbCommand resp; ReceiveCommand(&resp); @@ -338,14 +355,14 @@ static int enter_bootloader(char *serial_port_name) SendCommand(&c); fprintf(stderr,"Press and hold down button NOW if your bootloader requires it.\n"); } - msleep(100); - CloseProxmark(); + msleep(100); + CloseProxmark(serial_port_name); fprintf(stderr,"Waiting for Proxmark to reappear on %s",serial_port_name); - do { + do { sleep(1); fprintf(stderr, "."); - } while (!OpenProxmark(0)); + } while (!OpenProxmark(0, serial_port_name)); fprintf(stderr," Found.\n"); return 0; @@ -357,7 +374,7 @@ static int enter_bootloader(char *serial_port_name) static int wait_for_ack(void) { - UsbCommand ack; + UsbCommand ack; ReceiveCommand(&ack); if (ack.cmd != CMD_ACK) { printf("Error: Unexpected reply 0x%04" PRIx64 " (expected ACK)\n", ack.cmd); @@ -472,7 +489,7 @@ void flash_free(flash_file_t *ctx) // just reset the unit int flash_stop_flashing(void) { UsbCommand c = {CMD_HARDWARE_RESET}; - SendCommand(&c); - msleep(100); - return 0; + SendCommand(&c); + msleep(100); + return 0; } diff --git a/client/flash.h b/client/flash.h index 3e9f77a7..7f365924 100644 --- a/client/flash.h +++ b/client/flash.h @@ -11,6 +11,7 @@ #include #include "elf.h" +#include "uart.h" typedef struct { void *data; @@ -26,10 +27,13 @@ typedef struct { } flash_file_t; int flash_load(flash_file_t *ctx, const char *name, int can_write_bl); -int flash_start_flashing(int enable_bl_writes,char *serial_port_name); +int flash_start_flashing(int enable_bl_writes, char *serial_port_name); int flash_write(flash_file_t *ctx); void flash_free(flash_file_t *ctx); int flash_stop_flashing(void); +void CloseProxmark(const char *serial_port_name); +int OpenProxmark(size_t i, const char *serial_port_name); +extern serial_port sp; #endif diff --git a/client/flasher.c b/client/flasher.c index f257d994..2bb87df9 100644 --- a/client/flasher.c +++ b/client/flasher.c @@ -23,9 +23,6 @@ # include #endif -static serial_port sp; -static char* serial_port_name; - void cmd_debug(UsbCommand* UC) { // Debug printf("UsbCommand length[len=%zd]\n",sizeof(UsbCommand)); @@ -43,15 +40,15 @@ void cmd_debug(UsbCommand* UC) { void SendCommand(UsbCommand* txcmd) { // printf("send: "); // cmd_debug(txcmd); - if (!uart_send(sp,(byte_t*)txcmd,sizeof(UsbCommand))) { + if (!uart_send(sp,(uint8_t*)txcmd,sizeof(UsbCommand))) { printf("Sending bytes to proxmark failed\n"); exit(1); } } void ReceiveCommand(UsbCommand* rxcmd) { - byte_t* prxcmd = (byte_t*)rxcmd; - byte_t* prx = prxcmd; + uint8_t* prxcmd = (uint8_t*)rxcmd; + uint8_t* prx = prxcmd; size_t rxlen; while (true) { if (uart_receive(sp, prx, sizeof(UsbCommand) - (prx-prxcmd), &rxlen)) { @@ -63,32 +60,17 @@ void ReceiveCommand(UsbCommand* rxcmd) { } } -void CloseProxmark() { - // Clean up the port - uart_close(sp); - // Fix for linux, it seems that it is extremely slow to release the serial port file descriptor /dev/* - unlink(serial_port_name); -} - -int OpenProxmark(size_t i) { - sp = uart_open(serial_port_name); - if (sp == INVALID_SERIAL_PORT || sp == CLAIMED_SERIAL_PORT) { - //poll once a second - return 0; - } - return 1; -} - static void usage(char *argv0) { fprintf(stderr, "Usage: %s [-b] image.elf [image.elf...]\n\n", argv0); fprintf(stderr, "\t-b\tEnable flashing of bootloader area (DANGEROUS)\n\n"); - //Is the example below really true? /Martin - fprintf(stderr, "Example:\n\n\t %s path/to/osimage.elf path/to/fpgaimage.elf\n", argv0); - fprintf(stderr, "\nExample (Linux):\n\n\t %s /dev/ttyACM0 armsrc/obj/fullimage.elf\n", argv0); - fprintf(stderr, "\nNote (Linux): if the flasher gets stuck in 'Waiting for Proxmark to reappear on ',\n"); - fprintf(stderr, " you need to blacklist proxmark for modem-manager - see wiki for more details:\n"); - fprintf(stderr, " http://code.google.com/p/proxmark3/wiki/Linux\n\n"); + fprintf(stderr, "\nExample:\n\n\t %s "SERIAL_PORT_H" armsrc/obj/fullimage.elf\n", argv0); +#ifdef __linux__ + fprintf(stderr, "\nNote (Linux): if the flasher gets stuck at 'Waiting for Proxmark to reappear',\n"); + fprintf(stderr, " you may need to blacklist proxmark for modem-manager. v1.4.14 and later\n"); + fprintf(stderr, " include this configuration patch already. The change can be found at:\n"); + fprintf(stderr, " https://cgit.freedesktop.org/ModemManager/ModemManager/commit/?id=6e7ff47\n\n"); +#endif } #define MAX_FILES 4 @@ -126,16 +108,16 @@ int main(int argc, char **argv) } } - serial_port_name = argv[1]; - - fprintf(stderr,"Waiting for Proxmark to appear on %s",serial_port_name); - do { - msleep(1000); - fprintf(stderr, "."); - } while (!OpenProxmark(0)); - fprintf(stderr," Found.\n"); + char* serial_port_name = argv[1]; - res = flash_start_flashing(can_write_bl,serial_port_name); + fprintf(stderr,"Waiting for Proxmark to appear on %s", serial_port_name); + do { + msleep(1000); + fprintf(stderr, "."); + } while (!OpenProxmark(0, serial_port_name)); + fprintf(stderr," Found.\n"); + + res = flash_start_flashing(can_write_bl, serial_port_name); if (res < 0) return -1; @@ -155,7 +137,7 @@ int main(int argc, char **argv) if (res < 0) return -1; - CloseProxmark(); + CloseProxmark(serial_port_name); fprintf(stderr, "All done.\n\n"); fprintf(stderr, "Have a nice day!\n"); diff --git a/client/proxgui.h b/client/proxgui.h index 77bcbf01..5cad6e3a 100644 --- a/client/proxgui.h +++ b/client/proxgui.h @@ -30,7 +30,6 @@ extern int s_Buff[MAX_GRAPH_TRACE_LEN]; extern double CursorScaleFactor; extern int PlotGridX, PlotGridY, PlotGridXdefault, PlotGridYdefault, CursorCPos, CursorDPos, GridOffset; extern int CommandFinished; -extern int offline; extern bool GridLocked; //Operations defined in data_operations diff --git a/client/proxmark3.c b/client/proxmark3.c index 1b64f68b..fc258609 100644 --- a/client/proxmark3.c +++ b/client/proxmark3.c @@ -28,79 +28,6 @@ #include "cmdhw.h" #include "whereami.h" -#ifdef _WIN32 -#define SERIAL_PORT_H "com3" -#else -#define SERIAL_PORT_H "/dev/ttyACM0" -#endif - -// a global mutex to prevent interlaced printing from different threads -pthread_mutex_t print_lock; - -static serial_port sp; -static UsbCommand txcmd; -volatile static bool txcmd_pending = false; - -void SendCommand(UsbCommand *c) { - #if 0 - printf("Sending %d bytes\n", sizeof(UsbCommand)); - #endif - - if (offline) { - PrintAndLog("Sending bytes to proxmark failed - offline"); - return; - } - /** - The while-loop below causes hangups at times, when the pm3 unit is unresponsive - or disconnected. The main console thread is alive, but comm thread just spins here. - Not good.../holiman - **/ - while(txcmd_pending); - txcmd = *c; - txcmd_pending = true; -} - -struct receiver_arg { - int run; -}; - -byte_t rx[sizeof(UsbCommand)]; -byte_t* prx = rx; - - -static void -#ifdef __has_attribute -#if __has_attribute(force_align_arg_pointer) -__attribute__((force_align_arg_pointer)) -#endif -#endif -*uart_receiver(void *targ) { - struct receiver_arg *arg = (struct receiver_arg*)targ; - size_t rxlen; - - while (arg->run) { - rxlen = 0; - if (uart_receive(sp, prx, sizeof(UsbCommand) - (prx-rx), &rxlen) && rxlen) { - prx += rxlen; - if (prx-rx < sizeof(UsbCommand)) { - continue; - } - UsbCommandReceived((UsbCommand*)rx); - } - prx = rx; - - if(txcmd_pending) { - if (!uart_send(sp, (byte_t*) &txcmd, sizeof(UsbCommand))) { - PrintAndLog("Sending bytes to proxmark failed"); - } - txcmd_pending = false; - } - } - - pthread_exit(NULL); - return NULL; -} - void #ifdef __has_attribute @@ -109,15 +36,17 @@ __attribute__((force_align_arg_pointer)) #endif #endif main_loop(char *script_cmds_file, char *script_cmd, bool usb_present) { - struct receiver_arg rarg; + receiver_arg conn; char *cmd = NULL; pthread_t reader_thread; bool execCommand = (script_cmd != NULL); bool stdinOnPipe = !isatty(STDIN_FILENO); + memset(&conn, 0, sizeof(receiver_arg)); + if (usb_present) { - rarg.run = 1; - pthread_create(&reader_thread, NULL, &uart_receiver, &rarg); + conn.run = true; + pthread_create(&reader_thread, NULL, &uart_receiver, &conn); // cache Version information now: CmdVersion(NULL); } @@ -135,7 +64,7 @@ main_loop(char *script_cmds_file, char *script_cmd, bool usb_present) { read_history(".history"); - while(1) { + while (1) { // If there is a script file if (script_file) { @@ -207,7 +136,7 @@ main_loop(char *script_cmds_file, char *script_cmd, bool usb_present) { write_history(".history"); if (usb_present) { - rarg.run = 0; + conn.run = false; pthread_join(reader_thread, NULL); } @@ -257,9 +186,8 @@ static void set_my_executable_path(void) static void show_help(bool showFullHelp, char *command_line){ printf("syntax: %s [-h|-help|-m|-f|-flush|-w|-wait|-c|-command|-l|-lua] [cmd_script_file_name] [command][lua_script_name]\n", command_line); - printf("\tLinux example:'%s /dev/ttyACM0'\n", command_line); - printf("\tWindows example:'%s com3'\n\n", command_line); - + printf("\texample: %s "SERIAL_PORT_H"\n\n", command_line); + if (showFullHelp){ printf("help: <-h|-help> Dump all interactive command's help at once.\n"); printf("\t%s -h\n\n", command_line); @@ -287,7 +215,7 @@ int main(int argc, char* argv[]) { bool addLuaExec = false; char *script_cmds_file = NULL; char *script_cmd = NULL; - + if (argc < 2) { show_help(true, argv[0]); return 1; @@ -392,9 +320,6 @@ int main(int argc, char* argv[]) { usb_present = true; offline = 0; } - - // create a mutex to avoid interlacing print commands from our different threads - pthread_mutex_init(&print_lock, NULL); #ifdef HAVE_GUI #ifdef _WIN32 @@ -422,8 +347,5 @@ int main(int argc, char* argv[]) { uart_close(sp); } - // clean up mutex - pthread_mutex_destroy(&print_lock); - exit(0); } diff --git a/client/ui.c b/client/ui.c index dc122d2f..b0669a22 100644 --- a/client/ui.c +++ b/client/ui.c @@ -31,8 +31,7 @@ bool showDemod = true; static char *logfilename = "proxmark3.log"; #ifndef EXTERNAL_PRINTANDLOG -// Declared in proxmark3.c -extern pthread_mutex_t print_lock; +static pthread_mutex_t print_lock = PTHREAD_MUTEX_INITIALIZER; void PrintAndLog(char *fmt, ...) { diff --git a/client/ui.h b/client/ui.h index 4049033d..28512ca9 100644 --- a/client/ui.h +++ b/client/ui.h @@ -23,7 +23,6 @@ void SetLogFilename(char *fn); extern double CursorScaleFactor; extern int PlotGridX, PlotGridY, PlotGridXdefault, PlotGridYdefault, CursorCPos, CursorDPos, GridOffset; -extern int offline; extern int flushAfterWrite; //buzzy extern bool GridLocked; extern bool showDemod; diff --git a/uart/uart.h b/uart/uart.h index fe75a683..3b563be2 100644 --- a/uart/uart.h +++ b/uart/uart.h @@ -39,7 +39,15 @@ #include #include -typedef unsigned char byte_t; +/* Used to substitute for an example serial port path on each platform. + */ +#ifdef _WIN32 +#define SERIAL_PORT_H "com3" +#elif __APPLE__ +#define SERIAL_PORT_H "/dev/tty.usbmodem*" +#else +#define SERIAL_PORT_H "/dev/ttyACM0" +#endif /* serial_port is declared as a void*, which you should cast to whatever type * makes sense to your connection method. Both the posix and win32 @@ -78,13 +86,13 @@ void uart_close(const serial_port sp); * partial read may have completed into the buffer by the corresponding * implementation, so pszRxLen should be checked to see if any data was written. */ -bool uart_receive(const serial_port sp, byte_t* pbtRx, size_t pszMaxRxLen, size_t* pszRxLen); +bool uart_receive(const serial_port sp, uint8_t* pbtRx, size_t pszMaxRxLen, size_t* pszRxLen); /* Sends a buffer to a given serial port. * pbtTx: A pointer to a buffer containing the data to send. * szTxLen: The amount of data to be sent. */ -bool uart_send(const serial_port sp, const byte_t* pbtTx, const size_t szTxLen); +bool uart_send(const serial_port sp, const uint8_t* pbtTx, const size_t szTxLen); /* Sets the current speed of the serial port, in baud. */ diff --git a/uart/uart_posix.c b/uart/uart_posix.c index 45e0d3d2..0e7f7f47 100644 --- a/uart/uart_posix.c +++ b/uart/uart_posix.c @@ -133,7 +133,7 @@ void uart_close(const serial_port sp) { free(sp); } -bool uart_receive(const serial_port sp, byte_t* pbtRx, size_t pszMaxRxLen, size_t* pszRxLen) { +bool uart_receive(const serial_port sp, uint8_t* pbtRx, size_t pszMaxRxLen, size_t* pszRxLen) { int res; int byteCount; fd_set rfds; @@ -192,7 +192,7 @@ bool uart_receive(const serial_port sp, byte_t* pbtRx, size_t pszMaxRxLen, size_ return true; } -bool uart_send(const serial_port sp, const byte_t* pbtTx, const size_t szTxLen) { +bool uart_send(const serial_port sp, const uint8_t* pbtTx, const size_t szTxLen) { int32_t res; size_t szPos = 0; fd_set rfds; diff --git a/uart/uart_win32.c b/uart/uart_win32.c index 121b2b51..b15e8786 100644 --- a/uart/uart_win32.c +++ b/uart/uart_win32.c @@ -107,11 +107,11 @@ void uart_close(const serial_port sp) { free(sp); } -bool uart_receive(const serial_port sp, byte_t *pbtRx, size_t pszMaxRxLen, size_t *pszRxLen) { +bool uart_receive(const serial_port sp, uint8_t *pbtRx, size_t pszMaxRxLen, size_t *pszRxLen) { return ReadFile(((serial_port_windows*)sp)->hPort, pbtRx, pszMaxRxLen, (LPDWORD)pszRxLen, NULL); } -bool uart_send(const serial_port sp, const byte_t* pbtTx, const size_t szTxLen) { +bool uart_send(const serial_port sp, const uint8_t* pbtTx, const size_t szTxLen) { DWORD dwTxLen = 0; return WriteFile(((serial_port_windows*)sp)->hPort, pbtTx, szTxLen, &dwTxLen, NULL); } From e069547c27276069fd8d1cf93a281b819127bec4 Mon Sep 17 00:00:00 2001 From: Tom Harkness Date: Tue, 3 Apr 2018 16:14:51 +1000 Subject: [PATCH 099/127] Fix for swapped parity when using lf_bulk_program.lua (#591) --- client/scripts/lf_bulk_program.lua | 43 +++++++++++++++--------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/client/scripts/lf_bulk_program.lua b/client/scripts/lf_bulk_program.lua index 274f7510..2556f8a5 100644 --- a/client/scripts/lf_bulk_program.lua +++ b/client/scripts/lf_bulk_program.lua @@ -9,7 +9,7 @@ bit32 = require('bit32') usage = [[ script run lf_bulk_program.lua -f facility -b base_id_num -c count - e.g: + e.g: script run lf_bulk_program.lua -f 1 -b 1000 -c 10 ]] author = "Brian Redbeard" @@ -32,12 +32,12 @@ function toBits(num,bits) end --[[Likely, I'm an idiot, but I couldn't find any parity functions in Lua - This can also be done with a combination of bitwise operations (in fact, + This can also be done with a combination of bitwise operations (in fact, is the canonically "correct" way to do it, but my brain doesn't just default to this and so counting some ones is good enough for me]]-- local function evenparity(s) local _, count = string.gsub(s, "1", "") - + local p = count % 2 if (p == 0) then return(false) @@ -45,7 +45,7 @@ local function evenparity(s) return(true) end end - + local function isempty(s) return s == nil or s == '' @@ -57,12 +57,13 @@ end local function cardHex(i,f) fac = bit32.lshift(f,16) id = bit32.bor(i, fac) - stream=toBits(id,26) + stream=toBits(id,24) --As the function defaults to even parity and returns a boolean, --perform a 'not' function to get odd parity - high = not evenparity(string.sub(stream,0,12)) and 1 or 0 - low = evenparity(string.sub(stream,13)) and 1 or 0 + high = evenparity(string.sub(stream,1,12)) and 1 or 0 + low = not evenparity(string.sub(stream,13)) and 1 or 0 + bits = bit32.bor(bit32.lshift(id,1), low) bits = bit32.bor(bits, bit32.lshift(high,25)) @@ -71,13 +72,13 @@ local function cardHex(i,f) --to create a higher order and lower order component which we will --then assemble in the return. The math above defines the proper --encoding as per HID/Weigand/etc. These bit flips are due to the - --format length check on bit 38 (cmdlfhid.c:64) and + --format length check on bit 38 (cmdlfhid.c:64) and --bit 31 (cmdlfhid.c:66). preamble = bit32.bor(0, bit32.lshift(1,5)) bits = bit32.bor(bits, bit32.lshift(1,26)) return ("%04x%08x"):format(preamble,bits) - + end local function main(args) @@ -86,22 +87,22 @@ local function main(args) --long arguments, but it seems this library was chosen for BSD style --compatibility for o, a in getopt.getopt(args, 'f:b:c:h') do - if o == 'f' then - if isempty(a) then + if o == 'f' then + if isempty(a) then print("You did not supply a facility code, using 0") facility = 0 - else + else facility = a end - elseif o == 'b' then - if isempty(a) then + elseif o == 'b' then + if isempty(a) then print("You must supply the flag -b (base id)") return else baseid = a end - elseif o == 'c' then - if isempty(a) then + elseif o == 'c' then + if isempty(a) then print("You must supply the flag -c (count)") return else @@ -118,22 +119,22 @@ local function main(args) --works, specifying ":" does not enforce supplying a value, thus we --need to do these checks all over again. - if isempty(baseid) then + if isempty(baseid) then print("You must supply the flag -b (base id)") print(usage) return end - if isempty(count) then + if isempty(count) then print("You must supply the flag -c (count)") print(usage) return end --If the facility ID is non specified, ensure we code it as zero - if isempty(facility) then + if isempty(facility) then print("Using 0 for the facility code as -f was not supplied") - facility = 0 + facility = 0 end --The next baseid + count function presents a logic/UX conflict @@ -144,7 +145,7 @@ local function main(args) endid = baseid + count - for cardnum = baseid,endid do + for cardnum = baseid,endid do local card = cardHex(cardnum, facility) print("Press enter to program card "..cardnum..":"..facility.." (hex: "..card..")") --This would be better with "press any key", but we'll take From 61aaee35cc838af65f943c9b6f62db28beb48c93 Mon Sep 17 00:00:00 2001 From: pwpiwi Date: Tue, 24 Apr 2018 08:27:29 +0200 Subject: [PATCH 100/127] USB comms: part 2 towards @micolous PR#463 (#595) * change variable 'offline' from global to static * change variable 'FlushAfterWrite' from global to static * remove unused global variable 'current_command' * WaitForResponseTimeoutW(CMD_UNKNOWN, ...) waits for any command * #include "printf.h" or in iso15693tools.c to define sprintf() * and some minor changes/comments --- client/cmdlf.c | 8 ++++---- client/cmdmain.c | 2 -- client/cmdparser.c | 2 +- client/comms.c | 28 +++++++++++++++++++++++----- client/comms.h | 6 +++++- client/flash.c | 12 ++++++------ client/flash.h | 2 +- client/hid-flasher/proxusb.c | 2 -- client/proxmark3.c | 12 ++++++------ client/ui.c | 10 +++++++--- client/ui.h | 2 +- common/Makefile.common | 2 +- common/iso15693tools.c | 8 ++++++-- 13 files changed, 61 insertions(+), 35 deletions(-) diff --git a/client/cmdlf.c b/client/cmdlf.c index 42f73fa1..63dd737e 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -327,7 +327,7 @@ int CmdLFSetConfig(const char *Cmd) } bool lf_read(bool silent, uint32_t samples) { - if (offline) return false; + if (IsOffline()) return false; UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_125K, {silent,samples,0}}; clearCommandBuffer(); //And ship it to device @@ -870,7 +870,7 @@ int CmdVchDemod(const char *Cmd) int CheckChipType(char cmdp) { uint32_t wordData = 0; - if (offline || cmdp == '1') return 0; + if (IsOffline() || cmdp == '1') return 0; save_restoreGB(GRAPH_SAVE); save_restoreDB(GRAPH_SAVE); @@ -915,7 +915,7 @@ int CmdLFfind(const char *Cmd) return 0; } - if (!offline && (cmdp != '1')) { + if (!IsOffline() && (cmdp != '1')) { lf_read(true, 30000); } else if (GraphTraceLen < minLength) { PrintAndLog("Data in Graphbuffer was too small."); @@ -931,7 +931,7 @@ int CmdLFfind(const char *Cmd) // only run if graphbuffer is just noise as it should be for hitag/cotag if (graphJustNoise(GraphBuffer, testLen)) { // only run these tests if we are in online mode - if (!offline && (cmdp != '1')) { + if (!IsOffline() && (cmdp != '1')) { // test for em4x05 in reader talk first mode. if (EM4x05Block0Test(&wordData)) { PrintAndLog("\nValid EM4x05/EM4x69 Chip Found\nUse lf em 4x05readword/dump commands to read\n"); diff --git a/client/cmdmain.c b/client/cmdmain.c index 10948c97..a45e3430 100644 --- a/client/cmdmain.c +++ b/client/cmdmain.c @@ -29,8 +29,6 @@ #include "cmdscript.h" -unsigned int current_command = CMD_UNKNOWN; - static int CmdHelp(const char *Cmd); static int CmdQuit(const char *Cmd); diff --git a/client/cmdparser.c b/client/cmdparser.c index f4d3c404..34230d52 100644 --- a/client/cmdparser.c +++ b/client/cmdparser.c @@ -25,7 +25,7 @@ void CmdsHelp(const command_t Commands[]) int i = 0; while (Commands[i].Name) { - if (!offline || Commands[i].Offline) + if (!IsOffline() || Commands[i].Offline) PrintAndLog("%-16s %s", Commands[i].Name, Commands[i].Help); ++i; } diff --git a/client/comms.c b/client/comms.c index 5b8266fe..2dd5534c 100644 --- a/client/comms.c +++ b/client/comms.c @@ -24,7 +24,7 @@ serial_port sp; // If TRUE, then there is no active connection to the PM3, and we will drop commands sent. -bool offline; +static bool offline; // Transmit buffer. // TODO: Use locks and execute this on the main thread, rather than the receiver @@ -47,10 +47,20 @@ static int cmd_tail = 0; // to lock cmdBuffer operations from different threads static pthread_mutex_t cmdBufferMutex = PTHREAD_MUTEX_INITIALIZER; +// These wrappers are required because it is not possible to access a static +// global variable outside of the context of a single file. + +void SetOffline(bool new_offline) { + offline = new_offline; +} + +bool IsOffline() { + return offline; +} void SendCommand(UsbCommand *c) { - #if 0 - printf("Sending %d bytes\n", sizeof(UsbCommand)); + #ifdef COMMS_DEBUG + printf("Sending %04x cmd\n", c->cmd); #endif if (offline) { @@ -153,6 +163,8 @@ void UsbCommandReceived(UsbCommand *UC) } break; case CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K: { + // FIXME: This does unsanitised copies into memory when we don't know + // the size of the buffer. memcpy(sample_buf+(UC->arg[0]),UC->d.asBytes,UC->arg[1]); return; } break; @@ -205,15 +217,20 @@ __attribute__((force_align_arg_pointer)) * Waits for a certain response type. This method waits for a maximum of * ms_timeout milliseconds for a specified response command. *@brief WaitForResponseTimeout - * @param cmd command to wait for + * @param cmd command to wait for, or CMD_UNKNOWN to take any command. * @param response struct to copy received command into. * @param ms_timeout + * @param show_warning * @return true if command was returned, otherwise false */ bool WaitForResponseTimeoutW(uint32_t cmd, UsbCommand* response, size_t ms_timeout, bool show_warning) { UsbCommand resp; + #ifdef COMMS_DEBUG + printf("Waiting for %04x cmd\n", cmd); + #endif + if (response == NULL) { response = &resp; } @@ -223,7 +240,7 @@ bool WaitForResponseTimeoutW(uint32_t cmd, UsbCommand* response, size_t ms_timeo // Wait until the command is received while (true) { while(getCommand(response)) { - if(response->cmd == cmd){ + if (cmd == CMD_UNKNOWN || response->cmd == cmd) { return true; } } @@ -233,6 +250,7 @@ bool WaitForResponseTimeoutW(uint32_t cmd, UsbCommand* response, size_t ms_timeo } if (msclock() - start_time > 2000 && show_warning) { + // 2 seconds elapsed (but this doesn't mean the timeout was exceeded) PrintAndLog("Waiting for a response from the proxmark..."); PrintAndLog("You can cancel this operation by pressing the pm3 button"); show_warning = false; diff --git a/client/comms.h b/client/comms.h index 40576018..51a1467d 100644 --- a/client/comms.h +++ b/client/comms.h @@ -30,6 +30,11 @@ typedef struct { pthread_mutex_t recv_lock; } receiver_arg; + +// Wrappers required as static variables can only be used in one file. +void SetOffline(bool new_offline); +bool IsOffline(); + void SendCommand(UsbCommand *c); void *uart_receiver(void *targ); @@ -40,6 +45,5 @@ bool WaitForResponseTimeout(uint32_t cmd, UsbCommand* response, size_t ms_timeou bool WaitForResponse(uint32_t cmd, UsbCommand* response); extern serial_port sp; -extern bool offline; #endif // COMMS_H_ diff --git a/client/flash.c b/client/flash.c index 894095e7..e3714185 100644 --- a/client/flash.c +++ b/client/flash.c @@ -27,9 +27,6 @@ void ReceiveCommand(UsbCommand* rxcmd); serial_port sp; -// FIXME: what the fuckity fuck -unsigned int current_command = CMD_UNKNOWN; - #define FLASH_START 0x100000 #define FLASH_SIZE (256*1024) #define FLASH_END (FLASH_START + FLASH_SIZE) @@ -52,13 +49,14 @@ void CloseProxmark(const char *serial_port_name) { unlink(serial_port_name); } -int OpenProxmark(size_t i, const char *serial_port_name) { +bool OpenProxmark(size_t i, const char *serial_port_name) { sp = uart_open(serial_port_name); if (sp == INVALID_SERIAL_PORT || sp == CLAIMED_SERIAL_PORT) { //poll once a second - return 0; + return false; } - return 1; + + return true; } // Turn PHDRs into flasher segments, checking for PHDR sanity and merging adjacent @@ -355,6 +353,7 @@ static int enter_bootloader(char *serial_port_name) SendCommand(&c); fprintf(stderr,"Press and hold down button NOW if your bootloader requires it.\n"); } + msleep(100); CloseProxmark(serial_port_name); @@ -363,6 +362,7 @@ static int enter_bootloader(char *serial_port_name) sleep(1); fprintf(stderr, "."); } while (!OpenProxmark(0, serial_port_name)); + fprintf(stderr," Found.\n"); return 0; diff --git a/client/flash.h b/client/flash.h index 7f365924..f8ffd221 100644 --- a/client/flash.h +++ b/client/flash.h @@ -32,7 +32,7 @@ int flash_write(flash_file_t *ctx); void flash_free(flash_file_t *ctx); int flash_stop_flashing(void); void CloseProxmark(const char *serial_port_name); -int OpenProxmark(size_t i, const char *serial_port_name); +bool OpenProxmark(size_t i, const char *serial_port_name); extern serial_port sp; #endif diff --git a/client/hid-flasher/proxusb.c b/client/hid-flasher/proxusb.c index 04dbb784..364b21a3 100644 --- a/client/hid-flasher/proxusb.c +++ b/client/hid-flasher/proxusb.c @@ -31,7 +31,6 @@ usb_dev_handle *devh = NULL; static unsigned int claimed_iface = 0; unsigned char return_on_error = 0; unsigned char error_occured = 0; -extern unsigned int current_command; void SendCommand(UsbCommand *c) { @@ -40,7 +39,6 @@ void SendCommand(UsbCommand *c) #if 0 printf("Sending %d bytes\n", sizeof(UsbCommand)); #endif - current_command = c->cmd; ret = usb_bulk_write(devh, 0x01, (char*)c, sizeof(UsbCommand), 1000); if (ret<0) { error_occured = 1; diff --git a/client/proxmark3.c b/client/proxmark3.c index fc258609..6587bcff 100644 --- a/client/proxmark3.c +++ b/client/proxmark3.c @@ -41,14 +41,17 @@ main_loop(char *script_cmds_file, char *script_cmd, bool usb_present) { pthread_t reader_thread; bool execCommand = (script_cmd != NULL); bool stdinOnPipe = !isatty(STDIN_FILENO); - + memset(&conn, 0, sizeof(receiver_arg)); if (usb_present) { conn.run = true; + SetOffline(false); pthread_create(&reader_thread, NULL, &uart_receiver, &conn); // cache Version information now: CmdVersion(NULL); + } else { + SetOffline(true); } // file with script @@ -64,7 +67,7 @@ main_loop(char *script_cmds_file, char *script_cmd, bool usb_present) { read_history(".history"); - while (1) { + while (1) { // If there is a script file if (script_file) { @@ -235,7 +238,7 @@ int main(int argc, char* argv[]) { if(strcmp(argv[i],"-f") == 0 || strcmp(argv[i],"-flush") == 0){ printf("Output will be flushed after every print.\n"); - flushAfterWrite = 1; + SetFlushAfterWrite(true); } if(strcmp(argv[i],"-w") == 0 || strcmp(argv[i],"-wait") == 0){ @@ -311,14 +314,11 @@ int main(int argc, char* argv[]) { if (sp == INVALID_SERIAL_PORT) { printf("ERROR: invalid serial port\n"); usb_present = false; - offline = 1; } else if (sp == CLAIMED_SERIAL_PORT) { printf("ERROR: serial port is claimed by another process\n"); usb_present = false; - offline = 1; } else { usb_present = true; - offline = 0; } #ifdef HAVE_GUI diff --git a/client/ui.c b/client/ui.c index b0669a22..50a6ec7d 100644 --- a/client/ui.c +++ b/client/ui.c @@ -22,8 +22,7 @@ double CursorScaleFactor = 1; int PlotGridX=0, PlotGridY=0, PlotGridXdefault= 64, PlotGridYdefault= 64, CursorCPos= 0, CursorDPos= 0; -int offline; -int flushAfterWrite = 0; //buzzy +bool flushAfterWrite = false; //buzzy int GridOffset = 0; bool GridLocked = false; bool showDemod = true; @@ -93,7 +92,7 @@ void PrintAndLog(char *fmt, ...) } va_end(argptr2); - if (flushAfterWrite == 1) //buzzy + if (flushAfterWrite) //buzzy { fflush(NULL); } @@ -106,3 +105,8 @@ void SetLogFilename(char *fn) { logfilename = fn; } + +void SetFlushAfterWrite(bool flush_after_write) { + flushAfterWrite = flush_after_write; +} + diff --git a/client/ui.h b/client/ui.h index 28512ca9..1273fe9e 100644 --- a/client/ui.h +++ b/client/ui.h @@ -20,10 +20,10 @@ void ShowGraphWindow(void); void RepaintGraphWindow(void); void PrintAndLog(char *fmt, ...); void SetLogFilename(char *fn); +void SetFlushAfterWrite(bool flush_after_write); extern double CursorScaleFactor; extern int PlotGridX, PlotGridY, PlotGridXdefault, PlotGridYdefault, CursorCPos, CursorDPos, GridOffset; -extern int flushAfterWrite; //buzzy extern bool GridLocked; extern bool showDemod; diff --git a/common/Makefile.common b/common/Makefile.common index 29b72a4c..f31ff7bb 100644 --- a/common/Makefile.common +++ b/common/Makefile.common @@ -29,7 +29,7 @@ GZIP=gzip OBJDIR = obj -INCLUDE = -I../include -I../common +INCLUDE = -I../include -I../common -I. TAR=tar TARFLAGS = -C .. -rvf diff --git a/common/iso15693tools.c b/common/iso15693tools.c index 26e636ca..f1214458 100644 --- a/common/iso15693tools.c +++ b/common/iso15693tools.c @@ -11,6 +11,12 @@ #include #include //#include "iso15693tools.h" +#ifdef ON_DEVICE +#include "printf.h" +#else +#include +#endif + #define POLY 0x8408 @@ -51,8 +57,6 @@ int Iso15693AddCrc(uint8_t *req, int n) { } -int sprintf(char *str, const char *format, ...); - // returns a string representation of the UID // UID is transmitted and stored LSB first, displayed MSB first // target char* buffer, where to put the UID, if NULL a static buffer is returned From 818efbebb87ec5485fbf367021dca42514dfdee0 Mon Sep 17 00:00:00 2001 From: pwpiwi Date: Sat, 28 Apr 2018 10:09:16 +0200 Subject: [PATCH 101/127] USB comms: part 3 towards @micolous PR#463 * change variable 'sp' from global to static * move code to open and close USB port to comms.c (OpenProxmark() and CloseProxmark()) * change scope of USBCommandReceived() to static * (flasher still unchanged) --- client/comms.c | 47 +++++++++++++++++++++++++++++++++++++--------- client/comms.h | 7 +++---- client/proxmark3.c | 33 ++++---------------------------- 3 files changed, 45 insertions(+), 42 deletions(-) diff --git a/client/comms.c b/client/comms.c index 2dd5534c..97d58ef9 100644 --- a/client/comms.c +++ b/client/comms.c @@ -21,7 +21,7 @@ // Declare globals. // Serial port that we are communicating with the PM3 on. -serial_port sp; +static serial_port sp; // If TRUE, then there is no active connection to the PM3, and we will drop commands sent. static bool offline; @@ -58,6 +58,38 @@ bool IsOffline() { return offline; } +bool OpenProxmark(char *portname, bool waitCOMPort, int timeout) { + if (!waitCOMPort) { + sp = uart_open(portname); + } else { + printf("Waiting for Proxmark to appear on %s ", portname); + fflush(stdout); + int openCount = 0; + do { + sp = uart_open(portname); + msleep(1000); + printf("."); + fflush(stdout); + } while(++openCount < timeout && (sp == INVALID_SERIAL_PORT || sp == CLAIMED_SERIAL_PORT)); + printf("\n"); + } + + // check result of uart opening + if (sp == INVALID_SERIAL_PORT) { + printf("ERROR: invalid serial port\n"); + return false; + } else if (sp == CLAIMED_SERIAL_PORT) { + printf("ERROR: serial port is claimed by another process\n"); + return false; + } else { + return true; + } +} + +void CloseProxmark(void) { + uart_close(sp); +} + void SendCommand(UsbCommand *c) { #ifdef COMMS_DEBUG printf("Sending %04x cmd\n", c->cmd); @@ -73,6 +105,7 @@ void SendCommand(UsbCommand *c) { Not good.../holiman **/ while(txcmd_pending); + txcmd = *c; txcmd_pending = true; } @@ -140,11 +173,7 @@ int getCommand(UsbCommand* response) } -//----------------------------------------------------------------------------- -// Entry point into our code: called whenever we received a packet over USB -// that we weren't necessarily expecting, for example a debug print. -//----------------------------------------------------------------------------- -void UsbCommandReceived(UsbCommand *UC) +static void UsbCommandReceived(UsbCommand *UC) { switch(UC->cmd) { // First check if we are handling a debug message @@ -170,7 +199,7 @@ void UsbCommandReceived(UsbCommand *UC) } break; default: - storeCommand(UC); + storeCommand(UC); break; } @@ -184,12 +213,12 @@ __attribute__((force_align_arg_pointer)) #endif #endif *uart_receiver(void *targ) { - receiver_arg *arg = (receiver_arg*)targ; + receiver_arg *conn = (receiver_arg*)targ; size_t rxlen; uint8_t rx[sizeof(UsbCommand)]; uint8_t *prx = rx; - while (arg->run) { + while (conn->run) { rxlen = 0; if (uart_receive(sp, prx, sizeof(UsbCommand) - (prx-rx), &rxlen) && rxlen) { prx += rxlen; diff --git a/client/comms.h b/client/comms.h index 51a1467d..616f7ddb 100644 --- a/client/comms.h +++ b/client/comms.h @@ -31,19 +31,18 @@ typedef struct { } receiver_arg; -// Wrappers required as static variables can only be used in one file. void SetOffline(bool new_offline); bool IsOffline(); +bool OpenProxmark(char *portname, bool waitCOMPort, int timeout); +void CloseProxmark(void); + void SendCommand(UsbCommand *c); void *uart_receiver(void *targ); -void UsbCommandReceived(UsbCommand *UC); void clearCommandBuffer(); bool WaitForResponseTimeoutW(uint32_t cmd, UsbCommand* response, size_t ms_timeout, bool show_warning); bool WaitForResponseTimeout(uint32_t cmd, UsbCommand* response, size_t ms_timeout); bool WaitForResponse(uint32_t cmd, UsbCommand* response); -extern serial_port sp; - #endif // COMMS_H_ diff --git a/client/proxmark3.c b/client/proxmark3.c index 6587bcff..88cb5fa7 100644 --- a/client/proxmark3.c +++ b/client/proxmark3.c @@ -21,7 +21,6 @@ #include "util_posix.h" #include "proxgui.h" #include "cmdmain.h" -#include "uart.h" #include "ui.h" #include "util.h" #include "cmdparser.h" @@ -137,7 +136,7 @@ main_loop(char *script_cmds_file, char *script_cmd, bool usb_present) { } write_history(".history"); - + if (usb_present) { conn.run = false; pthread_join(reader_thread, NULL); @@ -293,33 +292,9 @@ int main(int argc, char* argv[]) { // set global variables set_my_executable_path(); - - // open uart - if (!waitCOMPort) { - sp = uart_open(argv[1]); - } else { - printf("Waiting for Proxmark to appear on %s ", argv[1]); - fflush(stdout); - int openCount = 0; - do { - sp = uart_open(argv[1]); - msleep(1000); - printf("."); - fflush(stdout); - } while(++openCount < 20 && (sp == INVALID_SERIAL_PORT || sp == CLAIMED_SERIAL_PORT)); - printf("\n"); - } - // check result of uart opening - if (sp == INVALID_SERIAL_PORT) { - printf("ERROR: invalid serial port\n"); - usb_present = false; - } else if (sp == CLAIMED_SERIAL_PORT) { - printf("ERROR: serial port is claimed by another process\n"); - usb_present = false; - } else { - usb_present = true; - } + // try to open USB connection to Proxmark + usb_present = OpenProxmark(argv[1], waitCOMPort, 20); #ifdef HAVE_GUI #ifdef _WIN32 @@ -344,7 +319,7 @@ int main(int argc, char* argv[]) { // Clean up the port if (usb_present) { - uart_close(sp); + CloseProxmark(); } exit(0); From 854fdf15e074c6d282f08ff0bea555810f52c664 Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Thu, 3 May 2018 13:36:51 -0400 Subject: [PATCH 102/127] fix bug if -DWITH_ISO14443a_StandAlone is removed from makefile (#598) --- armsrc/appmain.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 64768922..679a533a 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -31,7 +31,7 @@ #endif // Craig Young - 14a stand-alone code -#ifdef WITH_ISO14443a_StandAlone +#ifdef WITH_ISO14443a #include "iso14443a.h" #endif From dbac9ffb40d8a1a390918613f122bb0a0e60e904 Mon Sep 17 00:00:00 2001 From: pwpiwi Date: Fri, 4 May 2018 08:19:37 +0200 Subject: [PATCH 103/127] Change driver file proxmark3.inf to support both old and new Vendor/Product IDs (see http://www.proxmark.org/forum/viewtopic.php?pid=32072#p32072) --- driver/proxmark3.inf | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/driver/proxmark3.inf b/driver/proxmark3.inf index 122ebd55..52dbd251 100644 --- a/driver/proxmark3.inf +++ b/driver/proxmark3.inf @@ -3,16 +3,18 @@ Signature="$Windows NT$" Class=Ports ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318} Provider=%ProviderName% -DriverVer=31/05/2017,1.1.0.0 +DriverVer=03/05/2018,1.1.1.0 [MANUFACTURER] %ProviderName%=DeviceList, NTx86, NTamd64 [DeviceList.NTx86] %DeviceName%=DriverInstall,USB\VID_9AC4&PID_4B8F +%DeviceName_old%=DriverInstall,USB\VID_2d2d&PID_504d [DeviceList.NTamd64] %DeviceName%=DriverInstall,USB\VID_9AC4&PID_4B8F +%DeviceName_old%=DriverInstall,USB\VID_2d2d&PID_504d [DriverInstall] include=mdmcpq.inf @@ -30,3 +32,4 @@ HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider" [Strings] ProviderName = "proxmark.org" DeviceName = "Proxmark3" +DeviceName_old = "Proxmark3 (old)" From e475fce44d187f6a22f74263dd8e07e30dbd1672 Mon Sep 17 00:00:00 2001 From: pwpiwi Date: Fri, 4 May 2018 08:25:08 +0200 Subject: [PATCH 104/127] Update CHANGELOG.md --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b7d20dcf..13fc97fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac ### Fixed - Changed start sequence in Qt mode (fix: short commands hangs main Qt thread) (Merlok) +- Changed driver file proxmark3.inf to support both old and new Product/Vendor IDs (piwi) ### Added - Added a bitbang mode to `lf cmdread` if delay is 0 the cmd bits turn off and on the antenna with 0 and 1 respectively (marshmellow) @@ -64,7 +65,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Added lf hitag write 24, the command writes a block to hitag2 tags in crypto mode (henjo) ### Added -- Added hf mf hardnested, an attack working for hardened Mifare cards (EV1, Mifare Plus SL1) where hf mf nested fails +- Added hf mf hardnested, an attack working for hardened Mifare cards (EV1, Mifare Plus SL1) where hf mf nested fails (piwi) - Added experimental testmode write option for t55xx (danger) (marshmellow) - Added t55xx p1detect to `lf search` chip detections (marshmellow) - Added lf t55xx p1detect, detect page 1 of a t55xx tag based on E015 mfg code (marshmellow) From a468b4277ac961158b6984be92b1be186e30797a Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Fri, 4 May 2018 23:54:01 -0400 Subject: [PATCH 105/127] more graceful exit to lf search if no signal found --- client/cmdlf.c | 1 + 1 file changed, 1 insertion(+) diff --git a/client/cmdlf.c b/client/cmdlf.c index 63dd737e..51e89581 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -947,6 +947,7 @@ int CmdLFfind(const char *Cmd) return 1; } } + PrintAndLog("\nNo Data Found! - maybe not an LF tag?\n"); return 0; } From babca445ffa9f7af6f5e1deb78476754c484a2b1 Mon Sep 17 00:00:00 2001 From: pwpiwi Date: Tue, 8 May 2018 07:54:49 +0200 Subject: [PATCH 106/127] rework of GetFromBigBuf() (#597) * this should fix crashes reported in issue #497 * don't allow receiver thread to write directly into arbitrary main thread's memory * instead use cmdBuffer[] for CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K as well * add timeout and warning options to GetFromBigBuf(), same as in WaitForResponseTimeoutW() * move GetFromBigBuf() from data.c to comms.c * remove data.c and data.h --- client/Makefile | 1 - client/cmddata.c | 12 +++----- client/cmdhf.c | 7 ++--- client/cmdhf14a.c | 1 - client/cmdhf14b.c | 1 - client/cmdhf15.c | 1 - client/cmdhficlass.c | 7 ++--- client/cmdhflegic.c | 7 ++--- client/cmdhflist.c | 1 - client/cmdhfmfu.c | 4 +-- client/cmdhw.c | 6 +--- client/cmdlf.c | 1 - client/cmdlfcotag.c | 6 ++-- client/cmdlfem4x.c | 4 +-- client/cmdlfhitag.c | 7 ++--- client/cmdlfio.c | 1 - client/cmdlft55xx.c | 4 +-- client/cmdlfti.c | 5 ++-- client/cmdmain.c | 1 - client/cmdscript.c | 1 - client/comms.c | 66 ++++++++++++++++++++++++++++++++++++++------ client/comms.h | 1 + client/data.c | 25 ----------------- client/data.h | 23 --------------- client/mifarehost.h | 2 +- client/util.c | 1 - client/util.h | 7 +++++ 27 files changed, 87 insertions(+), 116 deletions(-) delete mode 100644 client/data.c delete mode 100644 client/data.h diff --git a/client/Makefile b/client/Makefile index 883f3b6f..d4ac33b2 100644 --- a/client/Makefile +++ b/client/Makefile @@ -105,7 +105,6 @@ CMDSRCS = crapto1/crapto1.c\ crc64.c \ iso14443crc.c \ iso15693tools.c \ - data.c \ graph.c \ ui.c \ cmddata.c \ diff --git a/client/cmddata.c b/client/cmddata.c index 9bfe58f9..471665b7 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -12,7 +12,6 @@ #include // also included in util.h #include #include // for CmdNorm INT_MIN && INT_MAX -#include "data.h" // also included in util.h #include "cmddata.h" #include "util.h" #include "cmdmain.h" @@ -591,8 +590,7 @@ int CmdBitsamples(const char *Cmd) int cnt = 0; uint8_t got[12288]; - GetFromBigBuf(got,sizeof(got),0); - WaitForResponse(CMD_ACK,NULL); + GetFromBigBuf(got, sizeof(got), 0 , NULL, -1, false); for (int j = 0; j < sizeof(got); j++) { for (int k = 0; k < 8; k++) { @@ -1131,8 +1129,7 @@ int CmdHexsamples(const char *Cmd) return 0; } - GetFromBigBuf(got,requested,offset); - WaitForResponse(CMD_ACK,NULL); + GetFromBigBuf(got, requested, offset, NULL, -1, false); i = 0; for (j = 0; j < requested; j++) { @@ -1200,10 +1197,9 @@ int getSamples(int n, bool silent) n = sizeof(got); if (!silent) PrintAndLog("Reading %d bytes from device memory\n", n); - GetFromBigBuf(got,n,0); - if (!silent) PrintAndLog("Data fetched"); UsbCommand response; - WaitForResponse(CMD_ACK, &response); + GetFromBigBuf(got, n, 0, &response, -1, false); + if (!silent) PrintAndLog("Data fetched"); uint8_t bits_per_sample = 8; //Old devices without this feature would send 0 at arg[0] diff --git a/client/cmdhf.c b/client/cmdhf.c index 82313ae0..4a672255 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -14,7 +14,6 @@ #include #include "proxmark3.h" #include "util.h" -#include "data.h" #include "ui.h" #include "iso14443crc.h" #include "parity.h" @@ -497,8 +496,7 @@ int CmdHFList(const char *Cmd) trace = malloc(USB_CMD_DATA_SIZE); // Query for the size of the trace UsbCommand response; - GetFromBigBuf(trace, USB_CMD_DATA_SIZE, 0); - WaitForResponse(CMD_ACK, &response); + GetFromBigBuf(trace, USB_CMD_DATA_SIZE, 0, &response, -1, false); traceLen = response.arg[2]; if (traceLen > USB_CMD_DATA_SIZE) { uint8_t *p = realloc(trace, traceLen); @@ -508,8 +506,7 @@ int CmdHFList(const char *Cmd) return 2; } trace = p; - GetFromBigBuf(trace, traceLen, 0); - WaitForResponse(CMD_ACK, NULL); + GetFromBigBuf(trace, traceLen, 0, NULL, -1, false); } } diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index 480923d6..4684ae29 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -20,7 +20,6 @@ #include "util.h" #include "util_posix.h" #include "iso14443crc.h" -#include "data.h" #include "proxmark3.h" #include "ui.h" #include "cmdparser.h" diff --git a/client/cmdhf14b.c b/client/cmdhf14b.c index 36932cbd..bae40c09 100644 --- a/client/cmdhf14b.c +++ b/client/cmdhf14b.c @@ -15,7 +15,6 @@ #include #include "iso14443crc.h" #include "proxmark3.h" -#include "data.h" #include "graph.h" #include "util.h" #include "ui.h" diff --git a/client/cmdhf15.c b/client/cmdhf15.c index 8ddbea89..570a0420 100644 --- a/client/cmdhf15.c +++ b/client/cmdhf15.c @@ -28,7 +28,6 @@ #include #include "proxmark3.h" -#include "data.h" #include "graph.h" #include "ui.h" #include "util.h" diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index d42f7eef..e99c3285 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -16,7 +16,6 @@ #include #include #include "iso14443crc.h" // Can also be used for iClass, using 0xE012 as CRC-type -#include "data.h" #include "proxmark3.h" #include "ui.h" #include "cmdparser.h" @@ -750,8 +749,7 @@ int CmdHFiClassReader_Dump(const char *Cmd) { blocksRead = (sizeof(tag_data)/8) - blockno; } // response ok - now get bigbuf content of the dump - GetFromBigBuf(tag_data+(blockno*8), blocksRead*8, startindex); - WaitForResponse(CMD_ACK,NULL); + GetFromBigBuf(tag_data+(blockno*8), blocksRead*8, startindex, NULL, -1, false); size_t gotBytes = blocksRead*8 + blockno*8; // try AA2 @@ -793,8 +791,7 @@ int CmdHFiClassReader_Dump(const char *Cmd) { blocksRead = (sizeof(tag_data) - gotBytes)/8; } // get dumped data from bigbuf - GetFromBigBuf(tag_data+gotBytes, blocksRead*8, startindex); - WaitForResponse(CMD_ACK,NULL); + GetFromBigBuf(tag_data+gotBytes, blocksRead*8, startindex, NULL, -1, false); gotBytes += blocksRead*8; } else { //field is still on - turn it off... diff --git a/client/cmdhflegic.c b/client/cmdhflegic.c index c9f3485e..9c9613ae 100644 --- a/client/cmdhflegic.c +++ b/client/cmdhflegic.c @@ -12,7 +12,6 @@ #include #include #include "proxmark3.h" -#include "data.h" #include "ui.h" #include "cmdparser.h" #include "cmdhflegic.h" @@ -64,8 +63,7 @@ int CmdLegicDecode(const char *Cmd) char token_type[4]; // copy data from proxmark into buffer - GetFromBigBuf(data_buf,sizeof(data_buf),0); - WaitForResponse(CMD_ACK,NULL); + GetFromBigBuf(data_buf, sizeof(data_buf), 0, NULL, -1, false); // Output CDF System area (9 bytes) plus remaining header area (12 bytes) @@ -294,8 +292,7 @@ int CmdLegicSave(const char *Cmd) return -1; } - GetFromBigBuf(got,requested,offset); - WaitForResponse(CMD_ACK,NULL); + GetFromBigBuf(got, requested, offset, NULL, -1, false); for (int j = 0; j < requested; j += 8) { fprintf(f, "%02x %02x %02x %02x %02x %02x %02x %02x\n", diff --git a/client/cmdhflist.c b/client/cmdhflist.c index cf69abba..c87aa237 100644 --- a/client/cmdhflist.c +++ b/client/cmdhflist.c @@ -16,7 +16,6 @@ #include #include #include "util.h" -#include "data.h" #include "ui.h" #include "iso14443crc.h" #include "parity.h" diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index 63c41728..ac76c8dd 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -22,7 +22,6 @@ #include "mifare.h" #include "util.h" #include "protocols.h" -#include "data.h" #define MAX_UL_BLOCKS 0x0f #define MAX_ULC_BLOCKS 0x2b @@ -1325,8 +1324,7 @@ int CmdHF14AMfUDump(const char *Cmd){ PrintAndLog("Data exceeded Buffer size!"); bufferSize = sizeof(data); } - GetFromBigBuf(data, bufferSize, startindex); - WaitForResponse(CMD_ACK,NULL); + GetFromBigBuf(data, bufferSize, startindex, NULL, -1, false); Pages = bufferSize/4; // Load lock bytes. diff --git a/client/cmdhw.c b/client/cmdhw.c index 8f7243ad..4ede122f 100644 --- a/client/cmdhw.c +++ b/client/cmdhw.c @@ -18,7 +18,6 @@ #include "cmdhw.h" #include "cmdmain.h" #include "cmddata.h" -#include "data.h" /* low-level hardware control */ @@ -429,13 +428,10 @@ int CmdVersion(const char *Cmd) int CmdStatus(const char *Cmd) { - uint8_t speed_test_buffer[USB_CMD_DATA_SIZE]; - sample_buf = speed_test_buffer; - clearCommandBuffer(); UsbCommand c = {CMD_STATUS}; SendCommand(&c); - if (!WaitForResponseTimeout(CMD_ACK,&c,1900)) { + if (!WaitForResponseTimeout(CMD_ACK, &c, 1900)) { PrintAndLog("Status command failed. USB Speed Test timed out"); } return 0; diff --git a/client/cmdlf.c b/client/cmdlf.c index 51e89581..285d377a 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -22,7 +22,6 @@ #include "graph.h" // for graph data #include "cmdparser.h" // for getting cli commands included in cmdmain.h #include "cmdmain.h" // for sending cmds to device -#include "data.h" // for GetFromBigBuf #include "cmddata.h" // for `lf search` #include "cmdlfawid.h" // for awid menu #include "cmdlfem4x.h" // for em4x menu diff --git a/client/cmdlfcotag.c b/client/cmdlfcotag.c index 6d035e8c..ca163480 100644 --- a/client/cmdlfcotag.c +++ b/client/cmdlfcotag.c @@ -13,7 +13,6 @@ #include "proxmark3.h" #include "ui.h" #include "cmddata.h" -#include "data.h" #include "cmdlfcotag.h" #include "lfdemod.h" #include "usb_cmd.h" @@ -99,10 +98,9 @@ int CmdCOTAGRead(const char *Cmd) { getSamples(0, true); break; } case 1: { - GetFromBigBuf(DemodBuffer, COTAG_BITS, 0); - DemodBufferLen = COTAG_BITS; UsbCommand response; - if ( !WaitForResponseTimeout(CMD_ACK, &response, 1000) ) { + DemodBufferLen = COTAG_BITS; + if (!GetFromBigBuf(DemodBuffer, COTAG_BITS, 0, &response, 1000, true)) { PrintAndLog("timeout while waiting for reply."); return -1; } diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c index 6d562be0..ff2ae5b0 100644 --- a/client/cmdlfem4x.c +++ b/client/cmdlfem4x.c @@ -15,7 +15,6 @@ #include "proxmark3.h" #include "ui.h" #include "util.h" -#include "data.h" #include "graph.h" #include "cmdparser.h" #include "cmddata.h" @@ -804,8 +803,7 @@ int usage_lf_em_read(void) { bool downloadSamplesEM() { // 8 bit preamble + 32 bit word response (max clock (128) * 40bits = 5120 samples) uint8_t got[6000]; - GetFromBigBuf(got, sizeof(got), 0); - if ( !WaitForResponseTimeout(CMD_ACK, NULL, 4000) ) { + if (!GetFromBigBuf(got, sizeof(got), 0, NULL, 4000, true)) { PrintAndLog("command execution time out"); return false; } diff --git a/client/cmdlfhitag.c b/client/cmdlfhitag.c index 73c02a14..26ba9238 100644 --- a/client/cmdlfhitag.c +++ b/client/cmdlfhitag.c @@ -11,7 +11,6 @@ #include #include #include -#include "data.h" #include "proxmark3.h" #include "ui.h" #include "cmdparser.h" @@ -34,8 +33,7 @@ int CmdLFHitagList(const char *Cmd) // Query for the actual size of the trace UsbCommand response; - GetFromBigBuf(got, USB_CMD_DATA_SIZE, 0); - WaitForResponse(CMD_ACK, &response); + GetFromBigBuf(got, USB_CMD_DATA_SIZE, 0, &response, -1, false); uint16_t traceLen = response.arg[2]; if (traceLen > USB_CMD_DATA_SIZE) { uint8_t *p = realloc(got, traceLen); @@ -45,8 +43,7 @@ int CmdLFHitagList(const char *Cmd) return 2; } got = p; - GetFromBigBuf(got, traceLen, 0); - WaitForResponse(CMD_ACK,NULL); + GetFromBigBuf(got, traceLen, 0, NULL, -1, false); } PrintAndLog("recorded activity (TraceLen = %d bytes):"); diff --git a/client/cmdlfio.c b/client/cmdlfio.c index 4ccd5538..f2f2df06 100644 --- a/client/cmdlfio.c +++ b/client/cmdlfio.c @@ -15,7 +15,6 @@ #include #include "cmdlfio.h" #include "proxmark3.h" -#include "data.h" #include "graph.h" #include "ui.h" #include "cmdparser.h" diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index c5a6dd3f..a9fbb71e 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -21,7 +21,6 @@ #include "cmdlf.h" #include "cmdlft55xx.h" #include "util.h" -#include "data.h" #include "lfdemod.h" #include "cmdhf14a.h" //for getTagInfo #include "protocols.h" @@ -1355,8 +1354,7 @@ int CmdResetRead(const char *Cmd) { } uint8_t got[BIGBUF_SIZE-1]; - GetFromBigBuf(got,sizeof(got),0); - WaitForResponse(CMD_ACK,NULL); + GetFromBigBuf(got, sizeof(got), 0, NULL, -1 , 0); setGraphBuf(got, sizeof(got)); return 1; } diff --git a/client/cmdlfti.c b/client/cmdlfti.c index 5dae9c0e..7e0af94b 100644 --- a/client/cmdlfti.c +++ b/client/cmdlfti.c @@ -8,16 +8,17 @@ // Low frequency TI commands //----------------------------------------------------------------------------- +#include "cmdlfti.h" + #include #include #include #include "crc16.h" #include "proxmark3.h" -#include "data.h" #include "ui.h" #include "graph.h" #include "cmdparser.h" -#include "cmdlfti.h" +#include "util.h" static int CmdHelp(const char *Cmd); diff --git a/client/cmdmain.c b/client/cmdmain.c index a45e3430..c3b46145 100644 --- a/client/cmdmain.c +++ b/client/cmdmain.c @@ -17,7 +17,6 @@ #include #include "cmdparser.h" #include "proxmark3.h" -#include "data.h" #include "usb_cmd.h" #include "ui.h" #include "cmdhf.h" diff --git a/client/cmdscript.c b/client/cmdscript.c index 0d19f496..7b0e9000 100644 --- a/client/cmdscript.c +++ b/client/cmdscript.c @@ -17,7 +17,6 @@ #include "proxmark3.h" #include "scripting.h" -#include "data.h" #include "ui.h" #include "graph.h" #include "cmdparser.h" diff --git a/client/comms.c b/client/comms.c index 97d58ef9..b62f6fda 100644 --- a/client/comms.c +++ b/client/comms.c @@ -15,7 +15,6 @@ #include "uart.h" #include "ui.h" #include "common.h" -#include "data.h" #include "util_posix.h" // Declare globals. @@ -173,6 +172,10 @@ int getCommand(UsbCommand* response) } +//---------------------------------------------------------------------------------- +// Entry point into our code: called whenever we received a packet over USB. +// Handle debug commands directly, store all other commands in circular buffer. +//---------------------------------------------------------------------------------- static void UsbCommandReceived(UsbCommand *UC) { switch(UC->cmd) { @@ -191,13 +194,6 @@ static void UsbCommandReceived(UsbCommand *UC) return; } break; - case CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K: { - // FIXME: This does unsanitised copies into memory when we don't know - // the size of the buffer. - memcpy(sample_buf+(UC->arg[0]),UC->d.asBytes,UC->arg[1]); - return; - } break; - default: storeCommand(UC); break; @@ -242,6 +238,58 @@ __attribute__((force_align_arg_pointer)) } + +/** + * Data transfer from Proxmark to client. This method times out after + * ms_timeout milliseconds. + * @brief GetFromBigBuf + * @param dest Destination address for transfer + * @param bytes number of bytes to be transferred + * @param start_index offset into Proxmark3 BigBuf[] + * @param response struct to copy last command (CMD_ACK) into + * @param ms_timeout timeout in milliseconds + * @param show_warning display message after 2 seconds + * @return true if command was returned, otherwise false + */ +bool GetFromBigBuf(uint8_t *dest, int bytes, int start_index, UsbCommand *response, size_t ms_timeout, bool show_warning) +{ + UsbCommand c = {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K, {start_index, bytes, 0}}; + SendCommand(&c); + + uint64_t start_time = msclock(); + + UsbCommand resp; + if (response == NULL) { + response = &resp; + } + + int bytes_completed = 0; + while(true) { + if (getCommand(response)) { + if (response->cmd == CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) { + int copy_bytes = MIN(bytes - bytes_completed, response->arg[1]); + memcpy(dest + response->arg[0], response->d.asBytes, copy_bytes); + bytes_completed += copy_bytes; + } else if (response->cmd == CMD_ACK) { + return true; + } + } + + if (msclock() - start_time > ms_timeout) { + break; + } + + if (msclock() - start_time > 2000 && show_warning) { + PrintAndLog("Waiting for a response from the proxmark..."); + PrintAndLog("You can cancel this operation by pressing the pm3 button"); + show_warning = false; + } + } + + return false; +} + + /** * Waits for a certain response type. This method waits for a maximum of * ms_timeout milliseconds for a specified response command. @@ -249,7 +297,7 @@ __attribute__((force_align_arg_pointer)) * @param cmd command to wait for, or CMD_UNKNOWN to take any command. * @param response struct to copy received command into. * @param ms_timeout - * @param show_warning + * @param show_warning display message after 2 seconds * @return true if command was returned, otherwise false */ bool WaitForResponseTimeoutW(uint32_t cmd, UsbCommand* response, size_t ms_timeout, bool show_warning) { diff --git a/client/comms.h b/client/comms.h index 616f7ddb..111677ad 100644 --- a/client/comms.h +++ b/client/comms.h @@ -44,5 +44,6 @@ void clearCommandBuffer(); bool WaitForResponseTimeoutW(uint32_t cmd, UsbCommand* response, size_t ms_timeout, bool show_warning); bool WaitForResponseTimeout(uint32_t cmd, UsbCommand* response, size_t ms_timeout); bool WaitForResponse(uint32_t cmd, UsbCommand* response); +bool GetFromBigBuf(uint8_t *dest, int bytes, int start_index, UsbCommand *response, size_t ms_timeout, bool show_warning); #endif // COMMS_H_ diff --git a/client/data.c b/client/data.c deleted file mode 100644 index 4d7d1e41..00000000 --- a/client/data.c +++ /dev/null @@ -1,25 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (C) 2010 iZsh -// -// This code is licensed to you under the terms of the GNU GPL, version 2 or, -// at your option, any later version. See the LICENSE.txt file for the text of -// the license. -//----------------------------------------------------------------------------- -// Data utilities -//----------------------------------------------------------------------------- - -#include -#include -#include "data.h" -#include "ui.h" -#include "proxmark3.h" -#include "cmdmain.h" - -uint8_t* sample_buf; - -void GetFromBigBuf(uint8_t *dest, int bytes, int start_index) -{ - sample_buf = dest; - UsbCommand c = {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K, {start_index, bytes, 0}}; - SendCommand(&c); -} diff --git a/client/data.h b/client/data.h deleted file mode 100644 index 7d85e1f1..00000000 --- a/client/data.h +++ /dev/null @@ -1,23 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (C) 2010 iZsh -// -// This code is licensed to you under the terms of the GNU GPL, version 2 or, -// at your option, any later version. See the LICENSE.txt file for the text of -// the license. -//----------------------------------------------------------------------------- -// Data utilities -//----------------------------------------------------------------------------- - -#ifndef DATA_H__ -#define DATA_H__ - -#include - -#define FILE_PATH_SIZE 1000 - -extern uint8_t* sample_buf; -#define arraylen(x) (sizeof(x)/sizeof((x)[0])) - -void GetFromBigBuf(uint8_t *dest, int bytes, int start_index); - -#endif diff --git a/client/mifarehost.h b/client/mifarehost.h index 457a879f..6a37fef1 100644 --- a/client/mifarehost.h +++ b/client/mifarehost.h @@ -13,8 +13,8 @@ #include #include -#include "data.h" #include "crapto1/crapto1.h" +#include "util.h" // defaults // timeout in units. (ms * 106)/10 or us*0.0106 diff --git a/client/util.c b/client/util.c index 5dc9a455..4f84e3b5 100644 --- a/client/util.c +++ b/client/util.c @@ -16,7 +16,6 @@ #include #include #include -#include "data.h" #ifdef _WIN32 #include diff --git a/client/util.h b/client/util.h index 2e64d7ca..878938f4 100644 --- a/client/util.h +++ b/client/util.h @@ -24,10 +24,17 @@ #ifndef MAX # define MAX(a, b) (((a) > (b)) ? (a) : (b)) #endif +#ifndef arraylen +#define arraylen(x) (sizeof(x)/sizeof((x)[0])) +#endif #define EVEN 0 #define ODD 1 +#ifndef FILE_PATH_SIZE +#define FILE_PATH_SIZE 2000 +#endif + extern int ukbhit(void); extern void AddLogLine(char *fileName, char *extData, char *c); From 0000a4cda2598535c278570465be973743951c5d Mon Sep 17 00:00:00 2001 From: pwpiwi Date: Fri, 11 May 2018 05:24:02 +0200 Subject: [PATCH 107/127] fix HitagS simulation erors (issue #605) (#606) --- armsrc/hitagS.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/armsrc/hitagS.c b/armsrc/hitagS.c index dc2281b9..7d36d84b 100644 --- a/armsrc/hitagS.c +++ b/armsrc/hitagS.c @@ -985,39 +985,39 @@ void SimulateHitagSTag(bool tag_mem_supplied, byte_t* data) { tag.max_page=0; //con1 tag.auth=0; - if((tag.pages[1][2]&0x80)==1) + if (tag.pages[1][2]&0x80) tag.auth=1; tag.LCON=0; - if((tag.pages[1][2]&0x2)==1) + if (tag.pages[1][2]&0x2) tag.LCON=1; tag.LKP=0; - if((tag.pages[1][2]&0x1)==1) + if (tag.pages[1][2]&0x1) tag.LKP=1; //con2 //0=read write 1=read only tag.LCK7=0; - if((tag.pages[1][1]&0x80)==1) + if (tag.pages[1][1]&0x80) tag.LCK7=1; tag.LCK6=0; - if((tag.pages[1][1]&0x40)==1) + if (tag.pages[1][1]&0x40) tag.LCK6=1; tag.LCK5=0; - if((tag.pages[1][1]&0x20)==1) + if (tag.pages[1][1]&0x20) tag.LCK5=1; tag.LCK4=0; - if((tag.pages[1][1]&0x10)==1) + if (tag.pages[1][1]&0x10) tag.LCK4=1; tag.LCK3=0; - if((tag.pages[1][1]&0x8)==1) + if (tag.pages[1][1]&0x8) tag.LCK3=1; tag.LCK2=0; - if((tag.pages[1][1]&0x4)==1) + if (tag.pages[1][1]&0x4) tag.LCK2=1; tag.LCK1=0; - if((tag.pages[1][1]&0x2)==1) + if (tag.pages[1][1]&0x2) tag.LCK1=1; tag.LCK0=0; - if((tag.pages[1][1]&0x1)==1) + if (tag.pages[1][1]&0x1) tag.LCK0=1; // Set up simulator mode, frequency divisor which will drive the FPGA From e8924be8bac6e8ddc91d1950368ef51c454a6e55 Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Tue, 15 May 2018 02:19:49 -0400 Subject: [PATCH 108/127] fix gui (plot) bugs (#604) G keypress event would cause a crash if no data Q keypress didn't work. Thanks to @iceman1001 for identifying and providing the fixes. --- client/proxguiqt.cpp | 5 ++++- client/proxguiqt.h | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/client/proxguiqt.cpp b/client/proxguiqt.cpp index dc8279b5..ab0976cc 100644 --- a/client/proxguiqt.cpp +++ b/client/proxguiqt.cpp @@ -269,6 +269,7 @@ int Plot::xCoordOf(int i, QRect r ) int Plot::yCoordOf(int v, QRect r, int maxVal) { int z = (r.bottom() - r.top())/2; + if ( maxVal == 0 ) maxVal++; return -(z * v) / maxVal + z; } @@ -579,6 +580,8 @@ Plot::Plot(QWidget *parent) : QWidget(parent), GraphStart(0), GraphPixelsPerPoin CursorBPos = 0; setWindowTitle(tr("Sliders")); + + master = parent; } void Plot::closeEvent(QCloseEvent *event) @@ -688,7 +691,7 @@ void Plot::keyPressEvent(QKeyEvent *event) break; case Qt::Key_Q: - this->hide(); + master->hide(); break; default: diff --git a/client/proxguiqt.h b/client/proxguiqt.h index 45a65b04..e43311ee 100644 --- a/client/proxguiqt.h +++ b/client/proxguiqt.h @@ -28,6 +28,7 @@ class Plot: public QWidget { private: + QWidget *master; int GraphStart; double GraphPixelsPerPoint; int CursorAPos; From 803674b2d60e78d29c45fc08db2c454c6c6389e1 Mon Sep 17 00:00:00 2001 From: Dominic Celiano Date: Mon, 28 May 2018 20:32:48 +0100 Subject: [PATCH 109/127] Added mifarePlus.lua script for communication with Mifare Plus. (#593) Personalize MifarePlus EV1 cards --- .DS_Store | Bin 0 -> 12292 bytes client/scripts/mifarePlus.lua | 340 ++++++++++++++++++++++++++++++++++ 2 files changed, 340 insertions(+) create mode 100644 .DS_Store create mode 100644 client/scripts/mifarePlus.lua diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..ecae787283f908888f99eb9d6fa860cbb5da7cff GIT binary patch literal 12292 zcmeHN3s6+o89pDP-d(S9AqdOLvWtL-A}uD5c~m+v<}s7DX`0DQlT6ZdVyDyo=bXFC-USow zXm#w~nS0MY=iGDep2Pp2@B98A#uys!Y(--jt1L5`FP?*YYEiJqwIN0J2 z2G)kWyuZ^O^!N7$!rfZB+vRun`&|+5GQYpwx5rCuX<>IL==ZM;hJE}s8@eLiT@l_l zrmJgXI2ejFikEe3T7TGkm6zV-8}K&K8^c{b`XnEy!E|I=c5Z&robu|r`o@toEj>fc zRI@qjasW{t)|Waxw5ixvARS_N2#gH z9qjF;-yN3CPHTgrJ*!;Jzuo2vN7nRt1N3=5i>5rQbpvl-=J9wvilP)a@7pIVvB1f9 zemV+d!I-JQS)t!6%*Lu%6Ki8zS%?j>+t@*NgdJta*<Z#2|)oJ#NHJ*oV7t z0Ecil9>BNp9XyKf;YmD;-{S;E@CUq(x9}d`m%lHC+b%y=%OZNkX?^ar8p?>(l9OS} zx3wrr+zP~I8=JrQlbbXU(%IN7R?D2MgKc9$c0Jq24%4KcU_WKQVJFxt><#t~`-uI6 zoo4?8gNde_gM7?EDdwRJ3(Od1=%;hTD5BvNfyX)wRNhhrIK!t zy-Vt;cM>TC+1t=ay^Jdu(|MryobCRR=sjn-lZe`1L9{*}#l&(KVkwpp&s|PTcMb8} zc64AJaow$Op@+CGC-y;)b?w-N0Zp!S}QB!^?Dq|J1 zVxDT=(oRaXJ>rV=hZ|g>O}w_&71`0F-**Iq{@A^%XFX}zZY{Gh7>Kxh0dGhQChbU% zZ0;me2o5#``vab^cu%|RP!yA5>eehnLzQ*arH-nqs=cL-q1xK{rH%#FReSfElG3F=PVGa{>79&Dk5sy4MY_59Ja}nLkDr73 zR;OF-1+#_gjZ78pXg0^G>@#_c@UC?D$-McftZa+LsJ^vnX;aO)mb|g*oA+39Ei)6; zw-``lDIQhdqGgV`bX0wdq2=bvIQ1=>s?9Y9^(`9f%!?D$w`i`nILA}pd=?G47E7G= z?;6)EoL*$eDNQr&-IZ?eCz zw@7)v&$TxIGdZX#9CRiMQABc->+TwI)hmUYHj@HhgDz|k`de!6od}U2y$Ltt7JMFG zB_Yb)k?Zc`cuZPc%mrIw7AS7;6cxIg#YxQ0@$AsHJkz}L;@IKKsx&^rg1my_xfKf* zEj`ajKqgANyV-VjNWh=AJ8U)`33%01Xfq2W;FZ~h)W?y4S4!tmk3<4qt*kQJbR^)_ znuTVwjs(2A_)6-PNRX3l$uci9H&Q6eZ_?N~ncMvo;CY-(?F2i?UMDkqhfM5a_HRt2 zC`UHMIdWk`9$`QU=8AYn4Qf$`MQ9X8wi0V8z{9a%Jq37Na8r=SD}p>Bgb^Vu_$&o_ zZqVZ&`|%~*iLc;Zd|et>%-EV`J$l8%qsEr7)2C95rjKoBuFG|=k4-Rcw|^w+Wn*Hp z&1Gt9EDCzj;;`fTdMvDX;X<=K)M?AJss>Uge2e$Yq#$TK!y_*fap4Oan&n?!>aJ}LkM*UKQ!f0%YQy9_xd6dt5V)UF7m$%tRlqQ%= zX@U$`$u?(`ZC0b6?6MiHB0;bookUVLQj&mMri`6)>l`5K=HLR+;;a?6nawAHDL4GK&=SFbt~6d3I>c(5(CkFBiOi_U2*+=!pL0y8`5{09#1lqZ! z2B58|Gyv^_8UxTST5JH?rOp`8Mge_=iQrs0Q|kIGp!e_WG==ge3h+I9=;gq>n?iXU zdO10~RY30niWeLd(EAX+NufLry~lXm08im(I$h+UyjLY=#-v>$MSLw0e-Z%L@P8?n zB{p3o{ZH%8v7e6FJpaG^%>Vx<9!g%4E0A1)%X0;g+SK0EKy!;G9TKO>bL|c~x6;WE z{@k!E#Spsa>3Gp6Qt{MQL63-o?w$OG%3)d39UcGke*&N!jUkbj#Q#s1-bwtwunE13 Hg#Z5m#5c2R literal 0 HcmV?d00001 diff --git a/client/scripts/mifarePlus.lua b/client/scripts/mifarePlus.lua new file mode 100644 index 00000000..061ff736 --- /dev/null +++ b/client/scripts/mifarePlus.lua @@ -0,0 +1,340 @@ +local cmds = require('commands') +local lib14a = require('read14a') +getopt = require('getopt') -- Used to get command line arguments + +example = "script run mifarePlus" +author = "Dominic Celiano" +desc = +[[ +Purpose: Lua script to communicate with the Mifare Plus EV1, including personalization (setting the keys) and proximity check. Manually edit the file to add to the commands you can send the card. + +Please read the NXP manual before running this script to prevent making irreversible changes. Also note: + - The Mifare Plus must start in SL0 for personalization. Card can then be moved to SL1 or SL3. + - The keys are hardcoded in the script to "00...". Unless you change this, only use this script for testing purposes. + - Make sure you choose your card size correctly (2kB or 4kB). + +Small changes can be to made this script to communicate with the Mifare Plus S, X, or SE. + +Arguments: + -h : this help +]] + +SIXTEEN_BYTES_ZEROS = "00000000000000000000000000000000" + +GETVERS_INIT = "0360" -- Begins the GetVersion command +GETVERS_CONT = "03AF" -- Continues the GetVersion command +POWEROFF = "OFF" +WRITEPERSO = "03A8" +COMMITPERSO = "03AA" +AUTH_FIRST = "0370" +AUTH_CONT = "0372" +AUTH_NONFIRST = "0376" +PREPAREPC = "03F0" +PROXIMITYCHECK = "03F2" +VERIFYPC = "03FD" +READPLAINNOMACUNMACED = "0336" + +--- +-- This is only meant to be used when errors occur +function oops(err) + print("ERROR: ",err) +end + +--- +-- Usage help +function help() + print(desc) + print("Example usage") + print(example) +end + +--- +-- Used to send raw data to the firmware to subsequently forward the data to the card. +function sendRaw(rawdata, crc, power) + print((": %s"):format(rawdata)) + + local flags = lib14a.ISO14A_COMMAND.ISO14A_RAW + if crc then + flags = flags + lib14a.ISO14A_COMMAND.ISO14A_APPEND_CRC + end + if power then + flags = flags + lib14a.ISO14A_COMMAND.ISO14A_NO_DISCONNECT + end + + local command = Command:new{cmd = cmds.CMD_READER_ISO_14443a, + arg1 = flags, -- Send raw + arg2 = string.len(rawdata) / 2, -- arg2 contains the length, which is half the length of the ASCII-string rawdata + data = rawdata} + local ignore_response = false + local result, err = lib14a.sendToDevice(command, ignore_response) + if result then + --unpack the first 4 parts of the result as longs, and the last as an extremely long string to later be cut down based on arg1, the number of bytes returned + local count,cmd,arg1,arg2,arg3,data = bin.unpack('LLLLH512',result) + returned_bytes = string.sub(data, 1, arg1 * 2) + if returned_bytes ~= "" then + print((": %s"):format(returned_bytes)) -- need to multiply by 2 because the hex digits are actually two bytes when they are strings + end + return returned_bytes + else + err = "Error sending the card raw data." + oops(err) + end +end + +function writePerso() + -- Used to write any data, including the keys (Key A and Key B), for all the sectors. + -- writePerso() command parameters: + -- 1 byte - 0xA8 - Command Code + -- 2 bytes - Address of the first block or key to be written to (40 blocks are numbered from 0x0000 to 0x00FF) + -- X bytes - The data bytes to be written, starting from the first block. Amount of data sent can be from 16 to 240 bytes in 16 byte increments. This allows + -- up to 15 blocks to be written at once. + -- response from PICC: + -- 0x90 - OK + -- 0x09 - targeted block is invalid for writes, i.e. block 0, which contains manufacturer data + -- 0x0B - command invalid + -- 0x0C - unexpected command length + + + + cardsize = 4 --need to set to 4 for 4k or 2 for 2k + if(cardsize == 4) then + numsectors = 39 + elseif(cardsize == 2) then + numsectors = 31 + else + oops("Invalid card size") + end + + -- Write to the AES sector keys + print("Setting AES Sector keys") + for i=0,numsectors do --for each sector number + local keyA_block = "40" .. string.format("%02x", i * 2) + local keyB_block = "40" .. string.format("%02x", (i * 2) + 1) + --Can also calculate the keys fancily to make them unique, if desired + keyA = SIXTEEN_BYTES_ZEROS + keyB = SIXTEEN_BYTES_ZEROS + writeBlock(keyA_block, keyA) + writeBlock(keyB_block, keyB) + end + print("Finished setting AES Sector keys") + + print("Setting misc keys which haven't been set yet.") + --CardMasterKey + blocknum = "9000" + writeBlock(blocknum, SIXTEEN_BYTES_ZEROS) + --CardConfigurationKey + blocknum = "9001" + writeBlock(blocknum, SIXTEEN_BYTES_ZEROS) + --L3SwitchKey + blocknum = "9003" + writeBlock(blocknum, SIXTEEN_BYTES_ZEROS) + --SL1CardAuthKey + blocknum = "9004" + writeBlock(blocknum, SIXTEEN_BYTES_ZEROS) + --L3SectorSwitchKey + blocknum = "9006" + writeBlock(blocknum, SIXTEEN_BYTES_ZEROS) + --L1L3MixSectorSwitchKey + blocknum = "9007" + writeBlock(blocknum, SIXTEEN_BYTES_ZEROS) + --VC Keys + --VCProximityKey + blocknum = "A001" + writeBlock(blocknum, SIXTEEN_BYTES_ZEROS) + --VCSelectENCKey + blocknum = "A080" + writeBlock(blocknum, SIXTEEN_BYTES_ZEROS) + --VCSelectMACKey + blocknum = "A081" + writeBlock(blocknum, SIXTEEN_BYTES_ZEROS) + --TransactionMACKey1 + blocknum = "C000" + writeBlock(blocknum, SIXTEEN_BYTES_ZEROS) + --TransactionMACConfKey1 + blocknum = "C001" + writeBlock(blocknum, SIXTEEN_BYTES_ZEROS) + print("Finished setting misc keys.") + + print("WritePerso finished! Card is ready to move into new security level.") +end + +function writeBlock(blocknum, data) + -- Method writes 16 bytes of the string sent (data) to the specified block number + -- The block numbers sent to the card need to be in little endian format (i.e. block 0x0001 is sent as 0x1000) + blocknum_little_endian = string.sub(blocknum, 3, 4) .. string.sub(blocknum, 1, 2) + commandString = WRITEPERSO .. blocknum_little_endian .. data --Write 16 bytes (32 hex chars). + response = sendRaw(commandString, true, true) --0x90 is returned upon success + if string.sub(response, 3, 4) ~= "90" then + oops(("error occurred while trying to write to block %s"):format(blocknum)) + end +end + +function authenticateAES() + -- Used to try to authenticate with the AES keys we programmed into the card, to ensure the authentication works correctly. + commandString = AUTH_FIRST + commandString = commandString .. "" +end + +function getVersion() + sendRaw(GETVERS_INIT, true, true) + sendRaw(GETVERS_CONT, true, true) + sendRaw(GETVERS_CONT, true, true) +end + +function commitPerso(SL) + --pass SL as "01" to move to SL1 or "03" to move to SL3. + commandString = COMMITPERSO .. SL + response = sendRaw(commandString, true, true) --0x90 is returned upon success + if string.sub(response, 3, 4) ~= "90" then + oops("error occurred while trying to switch security level") + end +end + +function calculateMAC(MAC_input) + -- Pad the input if it is not a multiple of 16 bytes (32 nibbles). + if(string.len(MAC_input) % 32 ~= 0) then + MAC_input = MAC_input .. "80" + end + while(string.len(MAC_input) % 32 ~= 0) do + MAC_input = MAC_input .. "0" + end + print("Padded MAC Input = " .. MAC_input .. ", length (bytes) = " .. string.len(MAC_input) / 2) + + --The MAC would actually be calculated here, and the output stored in raw_output + raw_output = "00010203040506070001020304050607" -- Dummy filler for now of 16-byte output. To be filled with actual MAC for testing purposes. + + -- The final 8-byte MAC output is a concatenation of every 2nd byte starting from the second MSB. + final_output = "" + j = 3 + for i = 1,8 do + final_output = final_output .. string.sub(RndR, j, j + 1) .. string.sub(RndC, j, j + 1) + j = j + 4 + end + return final_output +end + +function proximityCheck() + --PreparePC-- + commandString = PREPAREPC + response = sendRaw(commandString, true, true) + if(response == "") then + print("ERROR: This card does not support the Proximity Check command.") + return + end + OPT = string.sub(response, 5, 6) + if(tonumber(OPT) == 1) then + pps_present = true + else + pps_present = false + end + pubRespTime = string.sub(response, 7, 10) + if(pps_present == true) then + pps = string.sub(response, 11, 12) + else + pps = nil + end + print("OPT = " .. OPT .. " pubRespTime = " .. pubRespTime .. " pps = " .. pps) + + --PC-- + RndC = "0001020304050607" --Random Challenge + num_rounds = 8 --Needs to be 1, 2, 4, or 8 + part_len = 8 / num_rounds + j = 1 + RndR = "" + for i = 1,num_rounds do + pRndC = "" + for q = 1,(part_len*2) do + pRndC = pRndC .. string.sub(RndC,j,j) + j = j + 1 + end + commandString = PROXIMITYCHECK .. "0" .. tostring(part_len) .. pRndC + pRndR = string.sub(sendRaw(commandString, true, true), 3, 3+part_len) + RndR = RndR .. pRndR + end + print("RndC = " .. RndC .. " RndR = " .. RndR) + + --VerifyPC-- + MAC_input = "FD" .. OPT .. pubRespTime + if(pps_present == true) then + MAC_input = MAC_input .. pps + end + rnum_concat = "" + rnum_concat = RndR .. RndC --temporary (only works for when a single random challenge (8 bytes) is sent) + -- j = 1 + -- for i = 1,8 do + -- rnum_concat = rnum_concat .. string.sub(RndR, j, j + 1) .. string.sub(RndC, j, j + 1) + -- j = j + 2 + -- end + MAC_input = MAC_input .. rnum_concat + print("Concatenation of random numbers = " .. rnum_concat) + print("Final PCD concatenation before input into MAC function = " .. MAC_input) + MAC_tag = calculateMAC(MAC_input) + print("8-byte PCD MAC_tag (placeholder - currently incorrect) = " .. MAC_tag) + commandString = VERIFYPC .. MAC_tag + response = sendRaw(commandString, true, true) + print(response) + PICC_MAC = string.sub(response, 5, 20) + print("8-byte MAC returned by PICC = " .. PICC_MAC) + MAC_input = "90" .. string.sub(MAC_input, 3) + print("Final PICC concatenation before input into MAC function = " .. MAC_input) + MAC_tag = calculateMAC(MAC_input) + print("8-byte PICC MAC_tag (placeholder - currently incorrect) = " .. MAC_tag) + +end + +--- +-- The main entry point +function main(args) + print("") -- Print a blank line to make things look cleaner + for o, a in getopt.getopt(args, 'h') do -- Populate command line arguments + if o == "h" then help() return end + end + + -- Initialize the card using the already-present read14a library + info,err = lib14a.read14443a(true, false) + --Perform RATS and PPS (Protocol and Parameter Selection) check to finish the ISO 14443-4 protocol. + response = sendRaw("e050", true, true) + if(response == "") then + print("No response from RATS.") + end + response = sendRaw("D01100", true, true) + if(response == "") then + print("No response from PPS check.") + end + if err then + oops(err) + sendRaw(POWEROFF, false, false) + return + else + print(("Connected to card with a UID of %s."):format(info.uid)) + end + + + -- Now, the card is initialized and we can do more interesting things. + + --writePerso() + --commitPerso("03") --move to SL3 + --getVersion() + proximityCheck() + + --commandString = VERIFYPC .. "186EFDE8DDC7D30B" + -- MAC = f5180d6e 40fdeae8 e9dd6ac7 bcd3350b + -- response = sendRaw(commandString, true, true) + + -- attempt to read VCProximityKey at block A001 + -- commandString = READPLAINNOMACUNMACED .. "01A0" .. "01" + -- response = sendRaw(commandString, true, true) + + -- authenticate with CardConfigurationKey + -- commandString = AUTH_FIRST .. "0190" .. "00" + -- response = sendRaw(commandString, true, true) + + -- Power off the Proxmark + sendRaw(POWEROFF, false, false) + + + +end + + +main(args) -- Call the main function From 9b4661c53baa99a649b26bd123b6f5d71e7bd812 Mon Sep 17 00:00:00 2001 From: Fl0-0 Date: Tue, 29 May 2018 18:05:32 +0200 Subject: [PATCH 110/127] Delete .DS_Store (#613) Mac hidden file accidentally merged in PR #593. --- .DS_Store | Bin 12292 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index ecae787283f908888f99eb9d6fa860cbb5da7cff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12292 zcmeHN3s6+o89pDP-d(S9AqdOLvWtL-A}uD5c~m+v<}s7DX`0DQlT6ZdVyDyo=bXFC-USow zXm#w~nS0MY=iGDep2Pp2@B98A#uys!Y(--jt1L5`FP?*YYEiJqwIN0J2 z2G)kWyuZ^O^!N7$!rfZB+vRun`&|+5GQYpwx5rCuX<>IL==ZM;hJE}s8@eLiT@l_l zrmJgXI2ejFikEe3T7TGkm6zV-8}K&K8^c{b`XnEy!E|I=c5Z&robu|r`o@toEj>fc zRI@qjasW{t)|Waxw5ixvARS_N2#gH z9qjF;-yN3CPHTgrJ*!;Jzuo2vN7nRt1N3=5i>5rQbpvl-=J9wvilP)a@7pIVvB1f9 zemV+d!I-JQS)t!6%*Lu%6Ki8zS%?j>+t@*NgdJta*<Z#2|)oJ#NHJ*oV7t z0Ecil9>BNp9XyKf;YmD;-{S;E@CUq(x9}d`m%lHC+b%y=%OZNkX?^ar8p?>(l9OS} zx3wrr+zP~I8=JrQlbbXU(%IN7R?D2MgKc9$c0Jq24%4KcU_WKQVJFxt><#t~`-uI6 zoo4?8gNde_gM7?EDdwRJ3(Od1=%;hTD5BvNfyX)wRNhhrIK!t zy-Vt;cM>TC+1t=ay^Jdu(|MryobCRR=sjn-lZe`1L9{*}#l&(KVkwpp&s|PTcMb8} zc64AJaow$Op@+CGC-y;)b?w-N0Zp!S}QB!^?Dq|J1 zVxDT=(oRaXJ>rV=hZ|g>O}w_&71`0F-**Iq{@A^%XFX}zZY{Gh7>Kxh0dGhQChbU% zZ0;me2o5#``vab^cu%|RP!yA5>eehnLzQ*arH-nqs=cL-q1xK{rH%#FReSfElG3F=PVGa{>79&Dk5sy4MY_59Ja}nLkDr73 zR;OF-1+#_gjZ78pXg0^G>@#_c@UC?D$-McftZa+LsJ^vnX;aO)mb|g*oA+39Ei)6; zw-``lDIQhdqGgV`bX0wdq2=bvIQ1=>s?9Y9^(`9f%!?D$w`i`nILA}pd=?G47E7G= z?;6)EoL*$eDNQr&-IZ?eCz zw@7)v&$TxIGdZX#9CRiMQABc->+TwI)hmUYHj@HhgDz|k`de!6od}U2y$Ltt7JMFG zB_Yb)k?Zc`cuZPc%mrIw7AS7;6cxIg#YxQ0@$AsHJkz}L;@IKKsx&^rg1my_xfKf* zEj`ajKqgANyV-VjNWh=AJ8U)`33%01Xfq2W;FZ~h)W?y4S4!tmk3<4qt*kQJbR^)_ znuTVwjs(2A_)6-PNRX3l$uci9H&Q6eZ_?N~ncMvo;CY-(?F2i?UMDkqhfM5a_HRt2 zC`UHMIdWk`9$`QU=8AYn4Qf$`MQ9X8wi0V8z{9a%Jq37Na8r=SD}p>Bgb^Vu_$&o_ zZqVZ&`|%~*iLc;Zd|et>%-EV`J$l8%qsEr7)2C95rjKoBuFG|=k4-Rcw|^w+Wn*Hp z&1Gt9EDCzj;;`fTdMvDX;X<=K)M?AJss>Uge2e$Yq#$TK!y_*fap4Oan&n?!>aJ}LkM*UKQ!f0%YQy9_xd6dt5V)UF7m$%tRlqQ%= zX@U$`$u?(`ZC0b6?6MiHB0;bookUVLQj&mMri`6)>l`5K=HLR+;;a?6nawAHDL4GK&=SFbt~6d3I>c(5(CkFBiOi_U2*+=!pL0y8`5{09#1lqZ! z2B58|Gyv^_8UxTST5JH?rOp`8Mge_=iQrs0Q|kIGp!e_WG==ge3h+I9=;gq>n?iXU zdO10~RY30niWeLd(EAX+NufLry~lXm08im(I$h+UyjLY=#-v>$MSLw0e-Z%L@P8?n zB{p3o{ZH%8v7e6FJpaG^%>Vx<9!g%4E0A1)%X0;g+SK0EKy!;G9TKO>bL|c~x6;WE z{@k!E#Spsa>3Gp6Qt{MQL63-o?w$OG%3)d39UcGke*&N!jUkbj#Q#s1-bwtwunE13 Hg#Z5m#5c2R From ad939de5017f3451376d6f559858a30bae675964 Mon Sep 17 00:00:00 2001 From: pwpiwi Date: Sun, 3 Jun 2018 14:25:20 +0200 Subject: [PATCH 111/127] USB comms: part 4 towards @micolous PR #463 * make uart_communication(), storeCommand() and getCommand() static in comms.c * move receiver thread creation and respective mutexes to comms.c * add mutex and signal for tx buffer * use comms.c for flasher as well * remove comm functions from client/proxmark3.h * this completes isolating all USB communication related functions in comms.c * don't assume a port to be defined by a name. Change parameter in OpenProxmark() to void* * comms.c: set sp and serial_port_name to NULL when offline --- client/Makefile | 8 +- client/cmddata.c | 5 +- client/cmdhf.c | 5 +- client/cmdhf14a.c | 2 +- client/cmdhf14b.c | 5 +- client/cmdhf14b.h | 2 + client/cmdhf15.c | 5 +- client/cmdhf15.h | 2 + client/cmdhfepa.c | 2 +- client/cmdhficlass.c | 2 +- client/cmdhflegic.c | 6 +- client/cmdhfmf.c | 2 +- client/cmdhfmfhard.c | 1 + client/cmdhfmfu.c | 2 +- client/cmdhftopaz.c | 5 +- client/cmdhw.c | 5 +- client/cmdlf.c | 5 +- client/cmdlfawid.c | 5 +- client/cmdlfcotag.c | 6 +- client/cmdlfem4x.c | 5 +- client/cmdlffdx.c | 2 +- client/cmdlfhid.c | 5 +- client/cmdlfhitag.c | 4 +- client/cmdlfindala.c | 5 +- client/cmdlfio.c | 5 +- client/cmdlfjablotron.c | 3 +- client/cmdlfnexwatch.c | 6 +- client/cmdlfnoralsy.c | 4 +- client/cmdlfpac.c | 4 +- client/cmdlfpcf7931.c | 6 +- client/cmdlfpcf7931.h | 2 + client/cmdlfpresco.c | 6 +- client/cmdlfpyramid.c | 6 +- client/cmdlfsecurakey.c | 4 +- client/cmdlft55xx.c | 5 +- client/cmdlft55xx.h | 3 + client/cmdlfti.c | 2 +- client/cmdlfviking.c | 6 +- client/cmdlfvisa2000.c | 2 +- client/cmdmain.c | 4 +- client/cmdmain.h | 5 - client/comms.c | 208 +++++++++++++++++++++++++--------------- client/comms.h | 12 +-- client/flash.c | 54 ++++------- client/flash.h | 9 +- client/flasher.c | 50 +++------- client/mifarehost.c | 2 +- client/proxmark3.c | 16 +--- client/proxmark3.h | 1 - client/scripting.c | 1 + 50 files changed, 274 insertions(+), 248 deletions(-) diff --git a/client/Makefile b/client/Makefile index d4ac33b2..917dc767 100644 --- a/client/Makefile +++ b/client/Makefile @@ -82,7 +82,9 @@ POSTCOMPILE = $(MV) -f $(OBJDIR)/$*.Td $(OBJDIR)/$*.d CORESRCS = uart_posix.c \ uart_win32.c \ util.c \ - util_posix.c + util_posix.c \ + ui.c \ + comms.c CMDSRCS = crapto1/crapto1.c\ crapto1/crypto1.c\ @@ -106,7 +108,6 @@ CMDSRCS = crapto1/crapto1.c\ iso14443crc.c \ iso15693tools.c \ graph.c \ - ui.c \ cmddata.c \ lfdemod.c \ emv/crypto_polarssl.c\ @@ -169,8 +170,7 @@ CMDSRCS = crapto1/crapto1.c\ cmdscript.c\ pm3_binlib.c\ pm3_bitlib.c\ - protocols.c\ - comms.c + protocols.c cpu_arch = $(shell uname -m) ifneq ($(findstring 86, $(cpu_arch)), ) diff --git a/client/cmddata.c b/client/cmddata.c index 471665b7..c4f0e8a3 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -8,14 +8,15 @@ // Data and Graph commands //----------------------------------------------------------------------------- +#include "cmddata.h" + #include // also included in util.h #include // also included in util.h #include #include // for CmdNorm INT_MIN && INT_MAX -#include "cmddata.h" #include "util.h" #include "cmdmain.h" -#include "proxmark3.h" +#include "comms.h" #include "ui.h" // for show graph controls #include "graph.h" // for graph data #include "cmdparser.h"// already included in cmdmain.h diff --git a/client/cmdhf.c b/client/cmdhf.c index 4a672255..17c31209 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -9,17 +9,18 @@ // High frequency commands //----------------------------------------------------------------------------- +#include "cmdhf.h" + #include #include #include -#include "proxmark3.h" +#include "comms.h" #include "util.h" #include "ui.h" #include "iso14443crc.h" #include "parity.h" #include "cmdmain.h" #include "cmdparser.h" -#include "cmdhf.h" #include "cmdhf14a.h" #include "cmdhf14b.h" #include "cmdhf15.h" diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index 4684ae29..859dec2f 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -20,7 +20,7 @@ #include "util.h" #include "util_posix.h" #include "iso14443crc.h" -#include "proxmark3.h" +#include "comms.h" #include "ui.h" #include "cmdparser.h" #include "common.h" diff --git a/client/cmdhf14b.c b/client/cmdhf14b.c index bae40c09..ff0bf7c9 100644 --- a/client/cmdhf14b.c +++ b/client/cmdhf14b.c @@ -8,18 +8,19 @@ // High frequency ISO14443B commands //----------------------------------------------------------------------------- +#include "cmdhf14b.h" + #include #include #include #include #include #include "iso14443crc.h" -#include "proxmark3.h" +#include "comms.h" #include "graph.h" #include "util.h" #include "ui.h" #include "cmdparser.h" -#include "cmdhf14b.h" #include "cmdmain.h" #include "cmdhf14a.h" diff --git a/client/cmdhf14b.h b/client/cmdhf14b.h index a45b7434..4fcae927 100644 --- a/client/cmdhf14b.h +++ b/client/cmdhf14b.h @@ -11,6 +11,8 @@ #ifndef CMDHF14B_H__ #define CMDHF14B_H__ +#include + int CmdHF14B(const char *Cmd); int CmdHF14BList(const char *Cmd); int CmdHF14BInfo(const char *Cmd); diff --git a/client/cmdhf15.c b/client/cmdhf15.c index 570a0420..08cc3b15 100644 --- a/client/cmdhf15.c +++ b/client/cmdhf15.c @@ -22,17 +22,18 @@ // the client. Signal Processing & decoding is done on the pc. This is the slowest // variant, but offers the possibility to analyze the waveforms directly. +#include "cmdhf15.h" + #include #include #include #include -#include "proxmark3.h" +#include "comms.h" #include "graph.h" #include "ui.h" #include "util.h" #include "cmdparser.h" -#include "cmdhf15.h" #include "iso15693tools.h" #include "cmdmain.h" diff --git a/client/cmdhf15.h b/client/cmdhf15.h index c6264604..d0517fe5 100644 --- a/client/cmdhf15.h +++ b/client/cmdhf15.h @@ -11,6 +11,8 @@ #ifndef CMDHF15_H__ #define CMDHF15_H__ +#include + int CmdHF15(const char *Cmd); int CmdHF15Demod(const char *Cmd); diff --git a/client/cmdhfepa.c b/client/cmdhfepa.c index f3456afb..ac1f4268 100644 --- a/client/cmdhfepa.c +++ b/client/cmdhfepa.c @@ -17,7 +17,7 @@ #include #include "util.h" #include "util_posix.h" -#include "proxmark3.h" +#include "comms.h" #include "ui.h" #include "cmdparser.h" #include "common.h" diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index e99c3285..499f7aae 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -16,7 +16,7 @@ #include #include #include "iso14443crc.h" // Can also be used for iClass, using 0xE012 as CRC-type -#include "proxmark3.h" +#include "comms.h" #include "ui.h" #include "cmdparser.h" #include "cmdhficlass.h" diff --git a/client/cmdhflegic.c b/client/cmdhflegic.c index 9c9613ae..691e1978 100644 --- a/client/cmdhflegic.c +++ b/client/cmdhflegic.c @@ -8,15 +8,17 @@ // High frequency Legic commands //----------------------------------------------------------------------------- +#include "cmdhflegic.h" + #include #include #include -#include "proxmark3.h" +#include "comms.h" #include "ui.h" #include "cmdparser.h" -#include "cmdhflegic.h" #include "cmdmain.h" #include "util.h" + static int CmdHelp(const char *Cmd); static command_t CommandTable[] = diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index a2da01c9..b50d6013 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -15,7 +15,7 @@ #include #include #include -#include "proxmark3.h" +#include "comms.h" #include "cmdmain.h" #include "cmdhfmfhard.h" #include "parity.h" diff --git a/client/cmdhfmfhard.c b/client/cmdhfmfhard.c index cf19436c..be618d6e 100644 --- a/client/cmdhfmfhard.c +++ b/client/cmdhfmfhard.c @@ -25,6 +25,7 @@ #include #include #include "proxmark3.h" +#include "comms.h" #include "cmdmain.h" #include "ui.h" #include "util.h" diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index ac76c8dd..e4115d71 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -12,7 +12,7 @@ #include #include -#include "proxmark3.h" +#include "comms.h" #include "usb_cmd.h" #include "cmdmain.h" #include "ui.h" diff --git a/client/cmdhftopaz.c b/client/cmdhftopaz.c index 39ff1804..b0b8a3d2 100644 --- a/client/cmdhftopaz.c +++ b/client/cmdhftopaz.c @@ -8,17 +8,18 @@ // High frequency Topaz (NFC Type 1) commands //----------------------------------------------------------------------------- +#include "cmdhftopaz.h" + #include #include #include #include #include "cmdmain.h" #include "cmdparser.h" -#include "cmdhftopaz.h" #include "cmdhf14a.h" #include "ui.h" #include "mifare.h" -#include "proxmark3.h" +#include "comms.h" #include "iso14443crc.h" #include "protocols.h" diff --git a/client/cmdhw.c b/client/cmdhw.c index 4ede122f..bdab01eb 100644 --- a/client/cmdhw.c +++ b/client/cmdhw.c @@ -8,14 +8,15 @@ // Hardware commands //----------------------------------------------------------------------------- +#include "cmdhw.h" + #include #include #include #include #include "ui.h" -#include "proxmark3.h" +#include "comms.h" #include "cmdparser.h" -#include "cmdhw.h" #include "cmdmain.h" #include "cmddata.h" diff --git a/client/cmdlf.c b/client/cmdlf.c index 285d377a..c09a299c 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -8,14 +8,15 @@ // Low frequency commands //----------------------------------------------------------------------------- +#include "cmdlf.h" + #include #include #include #include #include #include -#include "proxmark3.h" -#include "cmdlf.h" +#include "comms.h" #include "lfdemod.h" // for psk2TOpsk1 #include "util.h" // for parsing cli command utils #include "ui.h" // for show graph controls diff --git a/client/cmdlfawid.c b/client/cmdlfawid.c index 141ba172..cde94555 100644 --- a/client/cmdlfawid.c +++ b/client/cmdlfawid.c @@ -11,10 +11,11 @@ // FSK2a, RF/50, 96 bits (complete) //----------------------------------------------------------------------------- +#include "cmdlfawid.h" + #include #include // sscanf -#include "proxmark3.h" // Definitions, USB controls, etc -#include "cmdlfawid.h" +#include "comms.h" // Definitions, USB controls, etc #include "ui.h" // PrintAndLog #include "cmdparser.h" // CmdsParse, CmdsHelp #include "lfdemod.h" // parityTest + diff --git a/client/cmdlfcotag.c b/client/cmdlfcotag.c index ca163480..d1808c9a 100644 --- a/client/cmdlfcotag.c +++ b/client/cmdlfcotag.c @@ -7,13 +7,15 @@ //----------------------------------------------------------------------------- // Low frequency COTAG commands //----------------------------------------------------------------------------- + +#include "cmdlfcotag.h" + #include #include #include -#include "proxmark3.h" +#include "comms.h" #include "ui.h" #include "cmddata.h" -#include "cmdlfcotag.h" #include "lfdemod.h" #include "usb_cmd.h" #include "cmdmain.h" diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c index ff2ae5b0..cdaeb5ed 100644 --- a/client/cmdlfem4x.c +++ b/client/cmdlfem4x.c @@ -8,11 +8,12 @@ // Low frequency EM4x commands //----------------------------------------------------------------------------- +#include "cmdlfem4x.h" + #include #include #include -#include "cmdlfem4x.h" -#include "proxmark3.h" +#include "comms.h" #include "ui.h" #include "util.h" #include "graph.h" diff --git a/client/cmdlffdx.c b/client/cmdlffdx.c index 2e2ee9fd..20f834ce 100644 --- a/client/cmdlffdx.c +++ b/client/cmdlffdx.c @@ -13,7 +13,7 @@ #include #include #include -#include "proxmark3.h" +#include "comms.h" #include "ui.h" // for PrintAndLog #include "util.h" #include "cmdparser.h" diff --git a/client/cmdlfhid.c b/client/cmdlfhid.c index 19b5a142..ca58d8ab 100644 --- a/client/cmdlfhid.c +++ b/client/cmdlfhid.c @@ -8,10 +8,11 @@ // Low frequency HID commands (known) //----------------------------------------------------------------------------- +#include "cmdlfhid.h" + #include #include -#include "cmdlfhid.h" -#include "proxmark3.h" +#include "comms.h" #include "ui.h" #include "graph.h" #include "cmdparser.h" diff --git a/client/cmdlfhitag.c b/client/cmdlfhitag.c index 26ba9238..0fd8801b 100644 --- a/client/cmdlfhitag.c +++ b/client/cmdlfhitag.c @@ -8,10 +8,12 @@ // Low frequency Hitag support //----------------------------------------------------------------------------- +#include "cmdlfhitag.h" + #include #include #include -#include "proxmark3.h" +#include "comms.h" #include "ui.h" #include "cmdparser.h" #include "common.h" diff --git a/client/cmdlfindala.c b/client/cmdlfindala.c index 0a4f7834..b30231c5 100644 --- a/client/cmdlfindala.c +++ b/client/cmdlfindala.c @@ -8,10 +8,11 @@ // PSK1, rf/32, 64 or 224 bits (known) //----------------------------------------------------------------------------- +#include "cmdlfindala.h" + #include #include -#include "cmdlfindala.h" -#include "proxmark3.h" +#include "comms.h" #include "ui.h" #include "graph.h" #include "cmdparser.h" diff --git a/client/cmdlfio.c b/client/cmdlfio.c index f2f2df06..feb7d373 100644 --- a/client/cmdlfio.c +++ b/client/cmdlfio.c @@ -8,13 +8,14 @@ // FSK2a, rf/64, 64 bits (complete) //----------------------------------------------------------------------------- +#include "cmdlfio.h" + #include #include #include #include #include -#include "cmdlfio.h" -#include "proxmark3.h" +#include "comms.h" #include "graph.h" #include "ui.h" #include "cmdparser.h" diff --git a/client/cmdlfjablotron.c b/client/cmdlfjablotron.c index 9c69099e..4756266c 100644 --- a/client/cmdlfjablotron.c +++ b/client/cmdlfjablotron.c @@ -9,10 +9,11 @@ //----------------------------------------------------------------------------- #include "cmdlfjablotron.h" + #include #include #include -#include "proxmark3.h" +#include "comms.h" #include "ui.h" #include "util.h" #include "graph.h" diff --git a/client/cmdlfnexwatch.c b/client/cmdlfnexwatch.c index caabe835..d44c2a27 100644 --- a/client/cmdlfnexwatch.c +++ b/client/cmdlfnexwatch.c @@ -7,12 +7,14 @@ // Low frequency Honeywell NexWatch tag commands // PSK1 RF/16, RF/2, 128 bits long (known) //----------------------------------------------------------------------------- + +#include "cmdlfnexwatch.h" + #include #include #include #include -#include "cmdlfnexwatch.h" -#include "proxmark3.h" +#include "comms.h" #include "ui.h" #include "util.h" #include "graph.h" diff --git a/client/cmdlfnoralsy.c b/client/cmdlfnoralsy.c index 2c90fa14..52c35081 100644 --- a/client/cmdlfnoralsy.c +++ b/client/cmdlfnoralsy.c @@ -7,11 +7,13 @@ // Low frequency Noralsy tag commands // ASK/Manchester, STT, RF/32, 96 bits long (some bits unknown) //----------------------------------------------------------------------------- + #include "cmdlfnoralsy.h" + #include #include #include -#include "proxmark3.h" +#include "comms.h" #include "ui.h" #include "util.h" #include "graph.h" diff --git a/client/cmdlfpac.c b/client/cmdlfpac.c index ef6b394b..190361ec 100644 --- a/client/cmdlfpac.c +++ b/client/cmdlfpac.c @@ -7,10 +7,12 @@ // Low frequency Stanley/PAC tag commands // NRZ, RF/32, 128 bits long (unknown cs) //----------------------------------------------------------------------------- + #include "cmdlfpac.h" + #include #include -#include "proxmark3.h" +#include "comms.h" #include "ui.h" #include "util.h" #include "graph.h" diff --git a/client/cmdlfpcf7931.c b/client/cmdlfpcf7931.c index ffaf946f..9c694b8d 100644 --- a/client/cmdlfpcf7931.c +++ b/client/cmdlfpcf7931.c @@ -8,9 +8,12 @@ //----------------------------------------------------------------------------- // Low frequency PCF7931 commands //----------------------------------------------------------------------------- + +#include "cmdlfpcf7931.h" + #include #include -#include "proxmark3.h" +#include "comms.h" #include "ui.h" #include "util.h" #include "graph.h" @@ -18,7 +21,6 @@ #include "cmddata.h" #include "cmdmain.h" #include "cmdlf.h" -#include "cmdlfpcf7931.h" static int CmdHelp(const char *Cmd); diff --git a/client/cmdlfpcf7931.h b/client/cmdlfpcf7931.h index e093039c..8b24f03a 100644 --- a/client/cmdlfpcf7931.h +++ b/client/cmdlfpcf7931.h @@ -12,6 +12,8 @@ #ifndef CMDLFPCF7931_H__ #define CMDLFPCF7931_H__ +#include + struct pcf7931_config{ uint8_t Pwd[7]; uint16_t InitDelay; diff --git a/client/cmdlfpresco.c b/client/cmdlfpresco.c index 2f4bacfe..865b384b 100644 --- a/client/cmdlfpresco.c +++ b/client/cmdlfpresco.c @@ -7,11 +7,13 @@ // Low frequency Presco tag commands // ASK/Manchester, rf/32, 128 bits (complete) //----------------------------------------------------------------------------- + +#include "cmdlfpresco.h" + #include #include #include -#include "cmdlfpresco.h" -#include "proxmark3.h" +#include "comms.h" #include "ui.h" #include "util.h" #include "graph.h" diff --git a/client/cmdlfpyramid.c b/client/cmdlfpyramid.c index 366889f3..82367720 100644 --- a/client/cmdlfpyramid.c +++ b/client/cmdlfpyramid.c @@ -7,11 +7,13 @@ // Low frequency Farpoint / Pyramid tag commands // FSK2a, rf/50, 128 bits (complete) //----------------------------------------------------------------------------- + +#include "cmdlfpyramid.h" + #include #include #include -#include "cmdlfpyramid.h" -#include "proxmark3.h" +#include "comms.h" #include "ui.h" #include "util.h" #include "graph.h" diff --git a/client/cmdlfsecurakey.c b/client/cmdlfsecurakey.c index 8ae81250..44b77060 100644 --- a/client/cmdlfsecurakey.c +++ b/client/cmdlfsecurakey.c @@ -7,11 +7,13 @@ // Low frequency Securakey tag commands // ASK/Manchester, RF/40, 96 bits long (unknown cs) //----------------------------------------------------------------------------- + #include "cmdlfsecurakey.h" + #include #include #include -#include "proxmark3.h" +#include "comms.h" #include "ui.h" #include "util.h" #include "graph.h" diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index a9fbb71e..f53ff0d6 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -7,19 +7,20 @@ // Low frequency T55xx commands //----------------------------------------------------------------------------- +#include "cmdlft55xx.h" + #include #include #include #include #include -#include "proxmark3.h" +#include "comms.h" #include "ui.h" #include "graph.h" #include "cmdmain.h" #include "cmdparser.h" #include "cmddata.h" #include "cmdlf.h" -#include "cmdlft55xx.h" #include "util.h" #include "lfdemod.h" #include "cmdhf14a.h" //for getTagInfo diff --git a/client/cmdlft55xx.h b/client/cmdlft55xx.h index 4f0fd21d..2ae3e69b 100644 --- a/client/cmdlft55xx.h +++ b/client/cmdlft55xx.h @@ -10,6 +10,9 @@ #ifndef CMDLFT55XX_H__ #define CMDLFT55XX_H__ +#include +#include + typedef struct { uint32_t bl1; uint32_t bl2; diff --git a/client/cmdlfti.c b/client/cmdlfti.c index 7e0af94b..ff463971 100644 --- a/client/cmdlfti.c +++ b/client/cmdlfti.c @@ -14,7 +14,7 @@ #include #include #include "crc16.h" -#include "proxmark3.h" +#include "comms.h" #include "ui.h" #include "graph.h" #include "cmdparser.h" diff --git a/client/cmdlfviking.c b/client/cmdlfviking.c index 779156c8..73a9126a 100644 --- a/client/cmdlfviking.c +++ b/client/cmdlfviking.c @@ -7,11 +7,13 @@ // Low frequency Viking tag commands (AKA FDI Matalec Transit) // ASK/Manchester, RF/32, 64 bits (complete) //----------------------------------------------------------------------------- + +#include "cmdlfviking.h" + #include #include #include -#include "proxmark3.h" -#include "cmdlfviking.h" +#include "comms.h" #include "ui.h" #include "util.h" #include "graph.h" diff --git a/client/cmdlfvisa2000.c b/client/cmdlfvisa2000.c index 04589ba5..33259794 100644 --- a/client/cmdlfvisa2000.c +++ b/client/cmdlfvisa2000.c @@ -13,7 +13,7 @@ #include #include -#include "proxmark3.h" +#include "comms.h" #include "ui.h" #include "util.h" #include "graph.h" diff --git a/client/cmdmain.c b/client/cmdmain.c index c3b46145..01d4c9a7 100644 --- a/client/cmdmain.c +++ b/client/cmdmain.c @@ -50,13 +50,13 @@ command_t* getTopLevelCommandTable() return CommandTable; } -int CmdHelp(const char *Cmd) +static int CmdHelp(const char *Cmd) { CmdsHelp(CommandTable); return 0; } -int CmdQuit(const char *Cmd) +static int CmdQuit(const char *Cmd) { return 99; } diff --git a/client/cmdmain.h b/client/cmdmain.h index a833b41e..42b49145 100644 --- a/client/cmdmain.h +++ b/client/cmdmain.h @@ -11,12 +11,7 @@ #ifndef CMDMAIN_H__ #define CMDMAIN_H__ -#include -#include -#include "usb_cmd.h" #include "cmdparser.h" -#include "comms.h" - extern int CommandReceived(char *Cmd); extern command_t* getTopLevelCommandTable(); diff --git a/client/comms.c b/client/comms.c index b62f6fda..eeaff79c 100644 --- a/client/comms.c +++ b/client/comms.c @@ -9,33 +9,42 @@ // Code for communicating with the proxmark3 hardware. //----------------------------------------------------------------------------- -#include - #include "comms.h" + +#include +#ifdef __linux__ +#include // for unlink() +#endif #include "uart.h" #include "ui.h" #include "common.h" #include "util_posix.h" -// Declare globals. // Serial port that we are communicating with the PM3 on. -static serial_port sp; +static serial_port sp = NULL; +static char *serial_port_name = NULL; // If TRUE, then there is no active connection to the PM3, and we will drop commands sent. static bool offline; +typedef struct { + bool run; // If TRUE, continue running the uart_communication thread + bool block_after_ACK; // if true, block after receiving an ACK package +} communication_arg_t; + +static communication_arg_t conn; +static pthread_t USB_communication_thread; + // Transmit buffer. -// TODO: Use locks and execute this on the main thread, rather than the receiver -// thread. Running on the main thread means we need to be careful in the -// flasher, as it means SendCommand is no longer async, and can't be used as a -// buffer for a pending command when the connection is re-established. -static UsbCommand txcmd; -volatile static bool txcmd_pending = false; +static UsbCommand txBuffer; +static bool txBuffer_pending = false; +static pthread_mutex_t txBufferMutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t txBufferSig = PTHREAD_COND_INITIALIZER; // Used by UsbReceiveCommand as a ring buffer for messages that are yet to be // processed by a command handler (WaitForResponse{,Timeout}) -static UsbCommand cmdBuffer[CMD_BUFFER_SIZE]; +static UsbCommand rxBuffer[CMD_BUFFER_SIZE]; // Points to the next empty position to write to static int cmd_head = 0; @@ -43,8 +52,8 @@ static int cmd_head = 0; // Points to the position of the last unread command static int cmd_tail = 0; -// to lock cmdBuffer operations from different threads -static pthread_mutex_t cmdBufferMutex = PTHREAD_MUTEX_INITIALIZER; +// to lock rxBuffer operations from different threads +static pthread_mutex_t rxBufferMutex = PTHREAD_MUTEX_INITIALIZER; // These wrappers are required because it is not possible to access a static // global variable outside of the context of a single file. @@ -57,38 +66,6 @@ bool IsOffline() { return offline; } -bool OpenProxmark(char *portname, bool waitCOMPort, int timeout) { - if (!waitCOMPort) { - sp = uart_open(portname); - } else { - printf("Waiting for Proxmark to appear on %s ", portname); - fflush(stdout); - int openCount = 0; - do { - sp = uart_open(portname); - msleep(1000); - printf("."); - fflush(stdout); - } while(++openCount < timeout && (sp == INVALID_SERIAL_PORT || sp == CLAIMED_SERIAL_PORT)); - printf("\n"); - } - - // check result of uart opening - if (sp == INVALID_SERIAL_PORT) { - printf("ERROR: invalid serial port\n"); - return false; - } else if (sp == CLAIMED_SERIAL_PORT) { - printf("ERROR: serial port is claimed by another process\n"); - return false; - } else { - return true; - } -} - -void CloseProxmark(void) { - uart_close(sp); -} - void SendCommand(UsbCommand *c) { #ifdef COMMS_DEBUG printf("Sending %04x cmd\n", c->cmd); @@ -98,15 +75,22 @@ void SendCommand(UsbCommand *c) { PrintAndLog("Sending bytes to proxmark failed - offline"); return; } - /** - The while-loop below causes hangups at times, when the pm3 unit is unresponsive - or disconnected. The main console thread is alive, but comm thread just spins here. - Not good.../holiman - **/ - while(txcmd_pending); - txcmd = *c; - txcmd_pending = true; + pthread_mutex_lock(&txBufferMutex); + /** + This causes hangups at times, when the pm3 unit is unresponsive or disconnected. The main console thread is alive, + but comm thread just spins here. Not good.../holiman + **/ + while (txBuffer_pending) { + pthread_cond_wait(&txBufferSig, &txBufferMutex); // wait for communication thread to complete sending a previous commmand + } + + txBuffer = *c; + txBuffer_pending = true; + pthread_cond_signal(&txBufferSig); // tell communication thread that a new command can be send + + pthread_mutex_unlock(&txBufferMutex); + } @@ -119,18 +103,18 @@ void SendCommand(UsbCommand *c) { void clearCommandBuffer() { //This is a very simple operation - pthread_mutex_lock(&cmdBufferMutex); + pthread_mutex_lock(&rxBufferMutex); cmd_tail = cmd_head; - pthread_mutex_unlock(&cmdBufferMutex); + pthread_mutex_unlock(&rxBufferMutex); } /** * @brief storeCommand stores a USB command in a circular buffer * @param UC */ -void storeCommand(UsbCommand *command) +static void storeCommand(UsbCommand *command) { - pthread_mutex_lock(&cmdBufferMutex); + pthread_mutex_lock(&rxBufferMutex); if( (cmd_head+1) % CMD_BUFFER_SIZE == cmd_tail) { // If these two are equal, we're about to overwrite in the @@ -139,11 +123,11 @@ void storeCommand(UsbCommand *command) } // Store the command at the 'head' location - UsbCommand* destination = &cmdBuffer[cmd_head]; + UsbCommand* destination = &rxBuffer[cmd_head]; memcpy(destination, command, sizeof(UsbCommand)); cmd_head = (cmd_head +1) % CMD_BUFFER_SIZE; //increment head and wrap - pthread_mutex_unlock(&cmdBufferMutex); + pthread_mutex_unlock(&rxBufferMutex); } @@ -152,22 +136,22 @@ void storeCommand(UsbCommand *command) * @param response location to write command * @return 1 if response was returned, 0 if nothing has been received */ -int getCommand(UsbCommand* response) +static int getCommand(UsbCommand* response) { - pthread_mutex_lock(&cmdBufferMutex); + pthread_mutex_lock(&rxBufferMutex); //If head == tail, there's nothing to read, or if we just got initialized if (cmd_head == cmd_tail){ - pthread_mutex_unlock(&cmdBufferMutex); + pthread_mutex_unlock(&rxBufferMutex); return 0; } //Pick out the next unread command - UsbCommand* last_unread = &cmdBuffer[cmd_tail]; + UsbCommand* last_unread = &rxBuffer[cmd_tail]; memcpy(response, last_unread, sizeof(UsbCommand)); //Increment tail - this is a circular buffer, so modulo buffer size cmd_tail = (cmd_tail + 1) % CMD_BUFFER_SIZE; - pthread_mutex_unlock(&cmdBufferMutex); + pthread_mutex_unlock(&rxBufferMutex); return 1; } @@ -202,35 +186,54 @@ static void UsbCommandReceived(UsbCommand *UC) } -void +static void #ifdef __has_attribute #if __has_attribute(force_align_arg_pointer) __attribute__((force_align_arg_pointer)) #endif #endif -*uart_receiver(void *targ) { - receiver_arg *conn = (receiver_arg*)targ; +*uart_communication(void *targ) { + communication_arg_t *conn = (communication_arg_t*)targ; size_t rxlen; - uint8_t rx[sizeof(UsbCommand)]; - uint8_t *prx = rx; + UsbCommand rx; + UsbCommand *prx = ℞ while (conn->run) { rxlen = 0; - if (uart_receive(sp, prx, sizeof(UsbCommand) - (prx-rx), &rxlen) && rxlen) { + bool ACK_received = false; + if (uart_receive(sp, (uint8_t *)prx, sizeof(UsbCommand) - (prx-&rx), &rxlen) && rxlen) { prx += rxlen; - if (prx-rx < sizeof(UsbCommand)) { + if (prx-&rx < sizeof(UsbCommand)) { continue; } - UsbCommandReceived((UsbCommand*)rx); + UsbCommandReceived(&rx); + if (rx.cmd == CMD_ACK) { + ACK_received = true; + } } - prx = rx; + prx = ℞ - if(txcmd_pending) { - if (!uart_send(sp, (uint8_t*) &txcmd, sizeof(UsbCommand))) { + + pthread_mutex_lock(&txBufferMutex); + + if (conn->block_after_ACK) { + // if we just received an ACK, wait here until a new command is to be transmitted + if (ACK_received) { + while (!txBuffer_pending) { + pthread_cond_wait(&txBufferSig, &txBufferMutex); + } + } + } + + if(txBuffer_pending) { + if (!uart_send(sp, (uint8_t*) &txBuffer, sizeof(UsbCommand))) { PrintAndLog("Sending bytes to proxmark failed"); } - txcmd_pending = false; + txBuffer_pending = false; + pthread_cond_signal(&txBufferSig); // tell main thread that txBuffer is empty } + + pthread_mutex_unlock(&txBufferMutex); } pthread_exit(NULL); @@ -238,7 +241,6 @@ __attribute__((force_align_arg_pointer)) } - /** * Data transfer from Proxmark to client. This method times out after * ms_timeout milliseconds. @@ -289,6 +291,58 @@ bool GetFromBigBuf(uint8_t *dest, int bytes, int start_index, UsbCommand *respon return false; } + +bool OpenProxmark(void *port, bool wait_for_port, int timeout, bool flash_mode) { + char *portname = (char *)port; + if (!wait_for_port) { + sp = uart_open(portname); + } else { + printf("Waiting for Proxmark to appear on %s ", portname); + fflush(stdout); + int openCount = 0; + do { + sp = uart_open(portname); + msleep(1000); + printf("."); + fflush(stdout); + } while(++openCount < timeout && (sp == INVALID_SERIAL_PORT || sp == CLAIMED_SERIAL_PORT)); + printf("\n"); + } + + // check result of uart opening + if (sp == INVALID_SERIAL_PORT) { + printf("ERROR: invalid serial port\n"); + sp = NULL; + serial_port_name = NULL; + return false; + } else if (sp == CLAIMED_SERIAL_PORT) { + printf("ERROR: serial port is claimed by another process\n"); + sp = NULL; + serial_port_name = NULL; + return false; + } else { + // start the USB communication thread + serial_port_name = portname; + conn.run = true; + conn.block_after_ACK = flash_mode; + pthread_create(&USB_communication_thread, NULL, &uart_communication, &conn); + return true; + } +} + + +void CloseProxmark(void) { + conn.run = false; + pthread_join(USB_communication_thread, NULL); + uart_close(sp); +#ifdef __linux__ + // Fix for linux, it seems that it is extremely slow to release the serial port file descriptor /dev/* + if (serial_port_name) { + unlink(serial_port_name); + } +#endif +} + /** * Waits for a certain response type. This method waits for a maximum of diff --git a/client/comms.h b/client/comms.h index 111677ad..68981165 100644 --- a/client/comms.h +++ b/client/comms.h @@ -22,24 +22,14 @@ #define CMD_BUFFER_SIZE 50 #endif -typedef struct { - // If TRUE, continue running the uart_receiver thread - bool run; - - // Lock around serial port receives - pthread_mutex_t recv_lock; -} receiver_arg; - - void SetOffline(bool new_offline); bool IsOffline(); -bool OpenProxmark(char *portname, bool waitCOMPort, int timeout); +bool OpenProxmark(void *port, bool wait_for_port, int timeout, bool flash_mode); void CloseProxmark(void); void SendCommand(UsbCommand *c); -void *uart_receiver(void *targ); void clearCommandBuffer(); bool WaitForResponseTimeoutW(uint32_t cmd, UsbCommand* response, size_t ms_timeout, bool show_warning); bool WaitForResponseTimeout(uint32_t cmd, UsbCommand* response, size_t ms_timeout); diff --git a/client/flash.c b/client/flash.c index e3714185..e43ebd1b 100644 --- a/client/flash.c +++ b/client/flash.c @@ -20,12 +20,7 @@ #include "elf.h" #include "proxendian.h" #include "usb_cmd.h" -#include "uart.h" - -void SendCommand(UsbCommand* txcmd); -void ReceiveCommand(UsbCommand* rxcmd); - -serial_port sp; +#include "comms.h" #define FLASH_START 0x100000 #define FLASH_SIZE (256*1024) @@ -42,22 +37,6 @@ static const uint8_t elf_ident[] = { EV_CURRENT }; -void CloseProxmark(const char *serial_port_name) { - // Clean up the port - uart_close(sp); - // Fix for linux, it seems that it is extremely slow to release the serial port file descriptor /dev/* - unlink(serial_port_name); -} - -bool OpenProxmark(size_t i, const char *serial_port_name) { - sp = uart_open(serial_port_name); - if (sp == INVALID_SERIAL_PORT || sp == CLAIMED_SERIAL_PORT) { - //poll once a second - return false; - } - - return true; -} // Turn PHDRs into flasher segments, checking for PHDR sanity and merging adjacent // unaligned segments if needed @@ -207,7 +186,7 @@ static int check_segs(flash_file_t *ctx, int can_write_bl) { } // Load an ELF file and prepare it for flashing -int flash_load(flash_file_t *ctx, const char *name, int can_write_bl) +int flash_load(flash_file_t *ctx, const char *name, bool can_write_bl) { FILE *fd = NULL; Elf32_Ehdr ehdr; @@ -295,7 +274,7 @@ static int get_proxmark_state(uint32_t *state) c.cmd = CMD_DEVICE_INFO; SendCommand(&c); UsbCommand resp; - ReceiveCommand(&resp); + WaitForResponse(CMD_UNKNOWN, &resp); // wait for any response. No timeout. // Three outcomes: // 1. The old bootrom code will ignore CMD_DEVICE_INFO, but respond with an ACK @@ -355,17 +334,16 @@ static int enter_bootloader(char *serial_port_name) } msleep(100); - CloseProxmark(serial_port_name); + CloseProxmark(); - fprintf(stderr,"Waiting for Proxmark to reappear on %s",serial_port_name); - do { - sleep(1); - fprintf(stderr, "."); - } while (!OpenProxmark(0, serial_port_name)); - - fprintf(stderr," Found.\n"); - - return 0; + bool opened = OpenProxmark(serial_port_name, true, 120, true); // wait for 2 minutes + if (opened) { + fprintf(stderr," Found.\n"); + return 0; + } else { + fprintf(stderr,"Error: Proxmark not found.\n"); + return -1; + } } fprintf(stderr, "Error: Unknown Proxmark mode\n"); @@ -375,7 +353,7 @@ static int enter_bootloader(char *serial_port_name) static int wait_for_ack(void) { UsbCommand ack; - ReceiveCommand(&ack); + WaitForResponse(CMD_UNKNOWN, &ack); if (ack.cmd != CMD_ACK) { printf("Error: Unexpected reply 0x%04" PRIx64 " (expected ACK)\n", ack.cmd); return -1; @@ -424,12 +402,12 @@ static int write_block(uint32_t address, uint8_t *data, uint32_t length) memset(block_buf, 0xFF, BLOCK_SIZE); memcpy(block_buf, data, length); - UsbCommand c; + UsbCommand c; c.cmd = CMD_FINISH_WRITE; c.arg[0] = address; memcpy(c.d.asBytes, block_buf, length); - SendCommand(&c); - return wait_for_ack(); + SendCommand(&c); + return wait_for_ack(); } // Write a file's segments to Flash diff --git a/client/flash.h b/client/flash.h index f8ffd221..06c7c96e 100644 --- a/client/flash.h +++ b/client/flash.h @@ -10,8 +10,7 @@ #define __FLASH_H__ #include -#include "elf.h" -#include "uart.h" +#include typedef struct { void *data; @@ -26,14 +25,10 @@ typedef struct { flash_seg_t *segments; } flash_file_t; -int flash_load(flash_file_t *ctx, const char *name, int can_write_bl); +int flash_load(flash_file_t *ctx, const char *name, bool can_write_bl); int flash_start_flashing(int enable_bl_writes, char *serial_port_name); int flash_write(flash_file_t *ctx); void flash_free(flash_file_t *ctx); int flash_stop_flashing(void); -void CloseProxmark(const char *serial_port_name); -bool OpenProxmark(size_t i, const char *serial_port_name); - -extern serial_port sp; #endif diff --git a/client/flasher.c b/client/flasher.c index 2bb87df9..a008f7bc 100644 --- a/client/flasher.c +++ b/client/flasher.c @@ -10,18 +10,14 @@ #include #include #include +#include #include "proxmark3.h" #include "util.h" #include "util_posix.h" #include "flash.h" -#include "uart.h" +#include "comms.h" #include "usb_cmd.h" -#ifdef _WIN32 -# define unlink(x) -#else -# include -#endif void cmd_debug(UsbCommand* UC) { // Debug @@ -37,29 +33,6 @@ void cmd_debug(UsbCommand* UC) { printf("...\n"); } -void SendCommand(UsbCommand* txcmd) { -// printf("send: "); -// cmd_debug(txcmd); - if (!uart_send(sp,(uint8_t*)txcmd,sizeof(UsbCommand))) { - printf("Sending bytes to proxmark failed\n"); - exit(1); - } -} - -void ReceiveCommand(UsbCommand* rxcmd) { - uint8_t* prxcmd = (uint8_t*)rxcmd; - uint8_t* prx = prxcmd; - size_t rxlen; - while (true) { - if (uart_receive(sp, prx, sizeof(UsbCommand) - (prx-prxcmd), &rxlen)) { - prx += rxlen; - if ((prx-prxcmd) >= sizeof(UsbCommand)) { - return; - } - } - } -} - static void usage(char *argv0) { fprintf(stderr, "Usage: %s [-b] image.elf [image.elf...]\n\n", argv0); @@ -77,7 +50,7 @@ static void usage(char *argv0) int main(int argc, char **argv) { - int can_write_bl = 0; + int can_write_bl = false; int num_files = 0; int res; flash_file_t files[MAX_FILES]; @@ -92,7 +65,7 @@ int main(int argc, char **argv) for (int i = 2; i < argc; i++) { if (argv[i][0] == '-') { if (!strcmp(argv[i], "-b")) { - can_write_bl = 1; + can_write_bl = true; } else { usage(argv[0]); return -1; @@ -110,12 +83,12 @@ int main(int argc, char **argv) char* serial_port_name = argv[1]; - fprintf(stderr,"Waiting for Proxmark to appear on %s", serial_port_name); - do { - msleep(1000); - fprintf(stderr, "."); - } while (!OpenProxmark(0, serial_port_name)); - fprintf(stderr," Found.\n"); + if (!OpenProxmark(serial_port_name, true, 120, true)) { // wait for 2 minutes + fprintf(stderr, "Could not find Proxmark on %s.\n\n", serial_port_name); + return -1; + } else { + fprintf(stderr," Found.\n"); + } res = flash_start_flashing(can_write_bl, serial_port_name); if (res < 0) @@ -137,7 +110,8 @@ int main(int argc, char **argv) if (res < 0) return -1; - CloseProxmark(serial_port_name); + // Stop the command thread. + CloseProxmark(); fprintf(stderr, "All done.\n\n"); fprintf(stderr, "Have a nice day!\n"); diff --git a/client/mifarehost.c b/client/mifarehost.c index e1ced176..2d69cfae 100644 --- a/client/mifarehost.c +++ b/client/mifarehost.c @@ -16,7 +16,7 @@ #include #include "crapto1/crapto1.h" -#include "proxmark3.h" +#include "comms.h" #include "usb_cmd.h" #include "cmdmain.h" #include "ui.h" diff --git a/client/proxmark3.c b/client/proxmark3.c index 88cb5fa7..40c46613 100644 --- a/client/proxmark3.c +++ b/client/proxmark3.c @@ -9,6 +9,8 @@ // Main binary //----------------------------------------------------------------------------- +#include "proxmark3.h" + #include #include #include @@ -17,7 +19,6 @@ #include #include -#include "proxmark3.h" #include "util_posix.h" #include "proxgui.h" #include "cmdmain.h" @@ -26,7 +27,7 @@ #include "cmdparser.h" #include "cmdhw.h" #include "whereami.h" - +#include "comms.h" void #ifdef __has_attribute @@ -35,18 +36,12 @@ __attribute__((force_align_arg_pointer)) #endif #endif main_loop(char *script_cmds_file, char *script_cmd, bool usb_present) { - receiver_arg conn; char *cmd = NULL; - pthread_t reader_thread; bool execCommand = (script_cmd != NULL); bool stdinOnPipe = !isatty(STDIN_FILENO); - memset(&conn, 0, sizeof(receiver_arg)); - if (usb_present) { - conn.run = true; SetOffline(false); - pthread_create(&reader_thread, NULL, &uart_receiver, &conn); // cache Version information now: CmdVersion(NULL); } else { @@ -138,8 +133,7 @@ main_loop(char *script_cmds_file, char *script_cmd, bool usb_present) { write_history(".history"); if (usb_present) { - conn.run = false; - pthread_join(reader_thread, NULL); + CloseProxmark(); } if (script_file) { @@ -294,7 +288,7 @@ int main(int argc, char* argv[]) { set_my_executable_path(); // try to open USB connection to Proxmark - usb_present = OpenProxmark(argv[1], waitCOMPort, 20); + usb_present = OpenProxmark(argv[1], waitCOMPort, 20, false); #ifdef HAVE_GUI #ifdef _WIN32 diff --git a/client/proxmark3.h b/client/proxmark3.h index c6185c43..86d09bc0 100644 --- a/client/proxmark3.h +++ b/client/proxmark3.h @@ -20,7 +20,6 @@ extern "C" { #endif -void SendCommand(UsbCommand *c); const char *get_my_executable_path(void); const char *get_my_executable_directory(void); void main_loop(char *script_cmds_file, char *script_cmd, bool usb_present); diff --git a/client/scripting.c b/client/scripting.c index 0c761cb2..e73c7138 100644 --- a/client/scripting.c +++ b/client/scripting.c @@ -15,6 +15,7 @@ #include #include #include "proxmark3.h" +#include "comms.h" #include "usb_cmd.h" #include "cmdmain.h" #include "util.h" From 2bb7f7e327df13f288b2b98a71bb390c516cc982 Mon Sep 17 00:00:00 2001 From: Michael Farrell Date: Mon, 4 Jun 2018 21:54:41 +1000 Subject: [PATCH 112/127] Fixes a double-free issue in CloseProxmark: (#617) - CloseProxmark now clears global state. - CloseProxmark now checks for a non-null serial_port before calling uart_close, to avoid unintentional double-free'ing serial_port. - main now calls CloseProxmark once. --- client/comms.c | 10 +++++++++- client/proxmark3.c | 4 ---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/client/comms.c b/client/comms.c index eeaff79c..be0cfd10 100644 --- a/client/comms.c +++ b/client/comms.c @@ -334,13 +334,21 @@ bool OpenProxmark(void *port, bool wait_for_port, int timeout, bool flash_mode) void CloseProxmark(void) { conn.run = false; pthread_join(USB_communication_thread, NULL); - uart_close(sp); + + if (sp) { + uart_close(sp); + } + #ifdef __linux__ // Fix for linux, it seems that it is extremely slow to release the serial port file descriptor /dev/* if (serial_port_name) { unlink(serial_port_name); } #endif + + // Clean up our state + sp = NULL; + serial_port_name = NULL; } diff --git a/client/proxmark3.c b/client/proxmark3.c index 40c46613..6fb066e8 100644 --- a/client/proxmark3.c +++ b/client/proxmark3.c @@ -131,10 +131,6 @@ main_loop(char *script_cmds_file, char *script_cmd, bool usb_present) { } write_history(".history"); - - if (usb_present) { - CloseProxmark(); - } if (script_file) { fclose(script_file); From 44964fd181988c54ed4df58dc015dc09e1a7ac3a Mon Sep 17 00:00:00 2001 From: pwpiwi Date: Wed, 13 Jun 2018 08:13:20 +0200 Subject: [PATCH 113/127] Code cleanup (#616) * coverity fixes (including a real bug in cmdhftopaz.c) * Typo fix * replace TRUE/FALSE by stdbool true/false --- armsrc/appmain.c | 112 +++++++++++++++++------------------ armsrc/hitag2.c | 10 ++-- armsrc/hitagS.c | 11 ++-- armsrc/iclass.c | 74 +++++++++++------------ armsrc/iso14443b.c | 68 ++++++++++----------- armsrc/iso15693.c | 8 +-- armsrc/lfops.c | 6 +- armsrc/mifarecmd.c | 2 +- armsrc/mifaresniff.c | 12 ++-- armsrc/printf.c | 1 + client/cmdhf.c | 2 +- client/cmdhf14a.c | 13 ++-- client/cmdhfepa.c | 9 +-- client/cmdhflist.c | 4 +- client/cmdhfmf.c | 15 ++--- client/cmdhfmfhard.c | 1 - client/cmdhfmfu.c | 2 +- client/cmdhftopaz.c | 7 +-- client/cmdlfhitag.c | 17 +++--- client/cmdlfindala.c | 2 +- client/emv/crypto_polarssl.c | 6 +- client/flash.c | 6 +- client/fpga_compress.c | 2 +- client/mifarehost.c | 3 +- client/proxgui.cpp | 7 +-- client/proxguiqt.h | 1 - client/scripting.c | 2 +- client/util_posix.c | 2 +- include/proxmark3.h | 3 - tools/mfkey/mfkey32.c | 2 +- 30 files changed, 198 insertions(+), 212 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 679a533a..e8581216 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -394,8 +394,8 @@ void StandAloneMode14a() FpgaDownloadAndGo(FPGA_BITSTREAM_HF); int selected = 0; - int playing = 0, iGotoRecord = 0, iGotoClone = 0; - int cardRead[OPTS] = {0}; + bool playing = false, GotoRecord = false, GotoClone = false; + bool cardRead[OPTS] = {false}; uint8_t readUID[10] = {0}; uint32_t uid_1st[OPTS]={0}; uint32_t uid_2nd[OPTS]={0}; @@ -411,9 +411,9 @@ void StandAloneMode14a() WDT_HIT(); SpinDelay(300); - if (iGotoRecord == 1 || cardRead[selected] == 0) + if (GotoRecord || !cardRead[selected]) { - iGotoRecord = 0; + GotoRecord = false; LEDsoff(); LED(selected + 1, 0); LED(LED_RED2, 0); @@ -438,7 +438,7 @@ void StandAloneMode14a() else if (cardRead[(selected+1)%OPTS]) { Dbprintf("Button press detected but no card in bank[%d] so playing from bank[%d]", selected, (selected+1)%OPTS); selected = (selected+1)%OPTS; - break; // playing = 1; + break; } else { Dbprintf("Button press detected but no stored tag to play. (Ignoring button)"); @@ -488,14 +488,14 @@ void StandAloneMode14a() LED(selected + 1, 0); // Next state is replay: - playing = 1; + playing = true; - cardRead[selected] = 1; + cardRead[selected] = true; } /* MF Classic UID clone */ - else if (iGotoClone==1) + else if (GotoClone) { - iGotoClone=0; + GotoClone=false; LEDsoff(); LED(selected + 1, 0); LED(LED_ORANGE, 250); @@ -546,7 +546,7 @@ void StandAloneMode14a() MifareCGetBlock(0x3F, 1, 0, oldBlock0); if (oldBlock0[0] == 0 && oldBlock0[0] == oldBlock0[1] && oldBlock0[1] == oldBlock0[2] && oldBlock0[2] == oldBlock0[3]) { Dbprintf("No changeable tag detected. Returning to replay mode for bank[%d]", selected); - playing = 1; + playing = true; } else { Dbprintf("UID from target tag: %02X%02X%02X%02X", oldBlock0[0],oldBlock0[1],oldBlock0[2],oldBlock0[3]); @@ -564,14 +564,14 @@ void StandAloneMode14a() if (memcmp(testBlock0,newBlock0,16)==0) { DbpString("Cloned successfull!"); - cardRead[selected] = 0; // Only if the card was cloned successfully should we clear it - playing = 0; - iGotoRecord = 1; + cardRead[selected] = false; // Only if the card was cloned successfully should we clear it + playing = false; + GotoRecord = true; selected = (selected+1) % OPTS; } else { Dbprintf("Clone failed. Back to replay mode on bank[%d]", selected); - playing = 1; + playing = true; } } LEDsoff(); @@ -579,61 +579,55 @@ void StandAloneMode14a() } // Change where to record (or begin playing) - else if (playing==1) // button_pressed == BUTTON_SINGLE_CLICK && cardRead[selected]) + else if (playing) // button_pressed == BUTTON_SINGLE_CLICK && cardRead[selected]) { LEDsoff(); LED(selected + 1, 0); // Begin transmitting - if (playing) - { - LED(LED_GREEN, 0); - DbpString("Playing"); - for ( ; ; ) { - WDT_HIT(); - int button_action = BUTTON_HELD(1000); - if (button_action == 0) { // No button action, proceed with sim - uint8_t data[512] = {0}; // in case there is a read command received we shouldn't break - Dbprintf("Simulating ISO14443a tag with uid[0]: %08x, uid[1]: %08x [Bank: %u]", uid_1st[selected],uid_2nd[selected],selected); - if (hi14a_card[selected].sak == 8 && hi14a_card[selected].atqa[0] == 4 && hi14a_card[selected].atqa[1] == 0) { - DbpString("Mifare Classic"); - SimulateIso14443aTag(1,uid_1st[selected], uid_2nd[selected], data); // Mifare Classic - } - else if (hi14a_card[selected].sak == 0 && hi14a_card[selected].atqa[0] == 0x44 && hi14a_card[selected].atqa[1] == 0) { - DbpString("Mifare Ultralight"); - SimulateIso14443aTag(2,uid_1st[selected],uid_2nd[selected],data); // Mifare Ultralight - } - else if (hi14a_card[selected].sak == 20 && hi14a_card[selected].atqa[0] == 0x44 && hi14a_card[selected].atqa[1] == 3) { - DbpString("Mifare DESFire"); - SimulateIso14443aTag(3,uid_1st[selected],uid_2nd[selected],data); // Mifare DESFire - } - else { - Dbprintf("Unrecognized tag type -- defaulting to Mifare Classic emulation"); - SimulateIso14443aTag(1,uid_1st[selected], uid_2nd[selected], data); - } + LED(LED_GREEN, 0); + DbpString("Playing"); + for ( ; ; ) { + WDT_HIT(); + int button_action = BUTTON_HELD(1000); + if (button_action == 0) { // No button action, proceed with sim + uint8_t data[512] = {0}; // in case there is a read command received we shouldn't break + Dbprintf("Simulating ISO14443a tag with uid[0]: %08x, uid[1]: %08x [Bank: %u]", uid_1st[selected],uid_2nd[selected],selected); + if (hi14a_card[selected].sak == 8 && hi14a_card[selected].atqa[0] == 4 && hi14a_card[selected].atqa[1] == 0) { + DbpString("Mifare Classic"); + SimulateIso14443aTag(1,uid_1st[selected], uid_2nd[selected], data); // Mifare Classic } - else if (button_action == BUTTON_SINGLE_CLICK) { - selected = (selected + 1) % OPTS; - Dbprintf("Done playing. Switching to record mode on bank %d",selected); - iGotoRecord = 1; - break; + else if (hi14a_card[selected].sak == 0 && hi14a_card[selected].atqa[0] == 0x44 && hi14a_card[selected].atqa[1] == 0) { + DbpString("Mifare Ultralight"); + SimulateIso14443aTag(2,uid_1st[selected],uid_2nd[selected],data); // Mifare Ultralight } - else if (button_action == BUTTON_HOLD) { - Dbprintf("Playtime over. Begin cloning..."); - iGotoClone = 1; - break; + else if (hi14a_card[selected].sak == 20 && hi14a_card[selected].atqa[0] == 0x44 && hi14a_card[selected].atqa[1] == 3) { + DbpString("Mifare DESFire"); + SimulateIso14443aTag(3,uid_1st[selected],uid_2nd[selected],data); // Mifare DESFire + } + else { + Dbprintf("Unrecognized tag type -- defaulting to Mifare Classic emulation"); + SimulateIso14443aTag(1,uid_1st[selected], uid_2nd[selected], data); } - WDT_HIT(); } - - /* We pressed a button so ignore it here with a delay */ - SpinDelay(300); - LEDsoff(); - LED(selected + 1, 0); + else if (button_action == BUTTON_SINGLE_CLICK) { + selected = (selected + 1) % OPTS; + Dbprintf("Done playing. Switching to record mode on bank %d",selected); + GotoRecord = true; + break; + } + else if (button_action == BUTTON_HOLD) { + Dbprintf("Playtime over. Begin cloning..."); + GotoClone = true; + break; + } + WDT_HIT(); } - else - while(BUTTON_PRESS()) - WDT_HIT(); + + /* We pressed a button so ignore it here with a delay */ + SpinDelay(300); + LEDsoff(); + LED(selected + 1, 0); } } } diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index aec01860..8e690a7b 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -813,13 +813,13 @@ void SnoopHitag(uint32_t type) { int lastbit; bool bSkip; int tag_sof; - byte_t rx[HITAG_FRAME_LEN]; + byte_t rx[HITAG_FRAME_LEN] = {0}; size_t rxlen=0; FpgaDownloadAndGo(FPGA_BITSTREAM_LF); // Clean up trace and prepare it for storing frames - set_tracing(TRUE); + set_tracing(true); clear_trace(); auth_table_len = 0; @@ -1032,7 +1032,7 @@ void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) { FpgaDownloadAndGo(FPGA_BITSTREAM_LF); // Clean up trace and prepare it for storing frames - set_tracing(TRUE); + set_tracing(true); clear_trace(); auth_table_len = 0; @@ -1225,7 +1225,7 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) { bSuccessful = false; // Clean up trace and prepare it for storing frames - set_tracing(TRUE); + set_tracing(true); clear_trace(); //DbpString("Starting Hitag reader family"); @@ -1548,7 +1548,7 @@ void WriterHitag(hitag_function htf, hitag_data* htd, int page) { bSuccessful = false; // Clean up trace and prepare it for storing frames - set_tracing(TRUE); + set_tracing(true); clear_trace(); //DbpString("Starting Hitag reader family"); diff --git a/armsrc/hitagS.c b/armsrc/hitagS.c index 7d36d84b..f6ba0c6b 100644 --- a/armsrc/hitagS.c +++ b/armsrc/hitagS.c @@ -210,7 +210,7 @@ static void hitag_send_bit(int bit) { ; LOW(GPIO_SSC_DOUT); while (AT91C_BASE_TC0->TC_CV < T0 * 32) - ;; + ; } LED_A_OFF(); break; @@ -945,7 +945,6 @@ void SimulateHitagSTag(bool tag_mem_supplied, byte_t* data) { int i, j; byte_t rx[HITAG_FRAME_LEN]; size_t rxlen = 0; -//bool bQuitTraceFull = false; bQuiet = false; byte_t txbuf[HITAG_FRAME_LEN]; byte_t* tx = txbuf; @@ -953,7 +952,7 @@ void SimulateHitagSTag(bool tag_mem_supplied, byte_t* data) { BigBuf_free(); // Clean up trace and prepare it for storing frames - set_tracing(TRUE); + set_tracing(true); clear_trace(); DbpString("Starting HitagS simulation"); @@ -1216,7 +1215,7 @@ void ReadHitagS(hitag_function htf, hitag_data* htd) { bSuccessful = false; // Clean up trace and prepare it for storing frames - set_tracing(TRUE); + set_tracing(true); clear_trace(); bQuiet = false; @@ -1560,7 +1559,7 @@ void WritePageHitagS(hitag_function htf, hitag_data* htd,int page_) { tag.tstate = NO_OP; // Clean up trace and prepare it for storing frames - set_tracing(TRUE); + set_tracing(true); clear_trace(); bQuiet = false; @@ -1847,7 +1846,7 @@ void check_challenges(bool file_given, byte_t* data) { bSuccessful = false; // Clean up trace and prepare it for storing frames - set_tracing(TRUE); + set_tracing(true); clear_trace(); bQuiet = false; diff --git a/armsrc/iclass.c b/armsrc/iclass.c index f9aedc95..c587f8ea 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -91,7 +91,7 @@ static RAMFUNC int OutOfNDecoding(int bit) if(!Uart.bitBuffer) { Uart.bitBuffer = bit ^ 0xFF0; - return FALSE; + return false; } else { Uart.bitBuffer <<= 4; @@ -102,7 +102,7 @@ static RAMFUNC int OutOfNDecoding(int bit) Uart.output[Uart.byteCnt] = Uart.bitBuffer & 0xFF; Uart.byteCnt++; Uart.swapper = 0; - if(Uart.byteCnt > 15) { return TRUE; } + if(Uart.byteCnt > 15) { return true; } } else { Uart.swapper = 1; @@ -139,12 +139,12 @@ static RAMFUNC int OutOfNDecoding(int bit) Uart.highCnt = 0; if(Uart.byteCnt == 0) { // Its not straightforward to show single EOFs - // So just leave it and do not return TRUE + // So just leave it and do not return true Uart.output[0] = 0xf0; Uart.byteCnt++; } else { - return TRUE; + return true; } } else if(Uart.state != STATE_START_OF_COMMUNICATION) { @@ -263,7 +263,7 @@ static RAMFUNC int OutOfNDecoding(int bit) Uart.byteCnt++; Uart.output[Uart.byteCnt] = 0xAA; Uart.byteCnt++; - return TRUE; + return true; }*/ } @@ -318,7 +318,7 @@ static RAMFUNC int OutOfNDecoding(int bit) } } - return FALSE; + return false; } //============================================================================= @@ -371,7 +371,7 @@ static RAMFUNC int ManchesterDecoding(int v) if(Demod.buff < 3) { Demod.buff++; - return FALSE; + return false; } if(Demod.state==DEMOD_UNSYNCD) { @@ -473,7 +473,7 @@ static RAMFUNC int ManchesterDecoding(int v) Demod.len++; Demod.state = DEMOD_UNSYNCD; // error = 0x0f; - return TRUE; + return true; } else { Demod.state = DEMOD_ERROR_WAIT; @@ -557,7 +557,7 @@ static RAMFUNC int ManchesterDecoding(int v) } Demod.state = DEMOD_UNSYNCD; - return TRUE; + return true; } else { Demod.output[Demod.len] = 0xad; @@ -612,14 +612,14 @@ static RAMFUNC int ManchesterDecoding(int v) Demod.len++; Demod.output[Demod.len] = 0xBB; Demod.len++; - return TRUE; + return true; } } } // end (state != UNSYNCED) - return FALSE; + return false; } //============================================================================= @@ -639,7 +639,7 @@ void RAMFUNC SnoopIClass(void) // We won't start recording the frames that we acquire until we trigger; // a good trigger condition to get started is probably when we see a // response from the tag. - //int triggered = FALSE; // FALSE to wait first for card + //int triggered = false; // false to wait first for card // The command (reader -> tag) that we're receiving. // The length of a received command will in most cases be no more than 18 bytes. @@ -656,9 +656,9 @@ void RAMFUNC SnoopIClass(void) // The DMA buffer, used to stream samples from the FPGA uint8_t *dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE); - set_tracing(TRUE); + set_tracing(true); clear_trace(); - iso14a_set_trigger(FALSE); + iso14a_set_trigger(false); int lastRxCounter; uint8_t *upTo; @@ -749,12 +749,12 @@ void RAMFUNC SnoopIClass(void) time_stop = (GetCountSspClk()-time_0) << 4; LED_C_ON(); - //if(!LogTrace(Uart.output,Uart.byteCnt, rsamples, Uart.parityBits,TRUE)) break; - //if(!LogTrace(NULL, 0, Uart.endTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER, 0, TRUE)) break; + //if(!LogTrace(Uart.output,Uart.byteCnt, rsamples, Uart.parityBits,true)) break; + //if(!LogTrace(NULL, 0, Uart.endTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER, 0, true)) break; if(tracing) { uint8_t parity[MAX_PARITY_SIZE]; GetParity(Uart.output, Uart.byteCnt, parity); - LogTrace(Uart.output,Uart.byteCnt, time_start, time_stop, parity, TRUE); + LogTrace(Uart.output,Uart.byteCnt, time_start, time_stop, parity, true); } @@ -782,7 +782,7 @@ void RAMFUNC SnoopIClass(void) if(tracing) { uint8_t parity[MAX_PARITY_SIZE]; GetParity(Demod.output, Demod.len, parity); - LogTrace(Demod.output, Demod.len, time_start, time_stop, parity, FALSE); + LogTrace(Demod.output, Demod.len, time_start, time_stop, parity, false); } // And ready to receive another response. @@ -830,7 +830,7 @@ void rotateCSN(uint8_t* originalCSN, uint8_t* rotatedCSN) { //----------------------------------------------------------------------------- // Wait for commands from reader // Stop when button is pressed -// Or return TRUE when command is captured +// Or return true when command is captured //----------------------------------------------------------------------------- static int GetIClassCommandFromReader(uint8_t *received, int *len, int maxLen) { @@ -848,7 +848,7 @@ static int GetIClassCommandFromReader(uint8_t *received, int *len, int maxLen) for(;;) { WDT_HIT(); - if(BUTTON_PRESS()) return FALSE; + if(BUTTON_PRESS()) return false; if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { AT91C_BASE_SSC->SSC_THR = 0x00; @@ -858,7 +858,7 @@ static int GetIClassCommandFromReader(uint8_t *received, int *len, int maxLen) if(OutOfNDecoding(b & 0x0f)) { *len = Uart.byteCnt; - return TRUE; + return true; } } } @@ -993,7 +993,7 @@ void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain FpgaDownloadAndGo(FPGA_BITSTREAM_HF); // Enable and clear the trace - set_tracing(TRUE); + set_tracing(true); clear_trace(); //Use the emulator memory for SIM uint8_t *emulator = BigBuf_get_EM_addr(); @@ -1325,11 +1325,11 @@ int doIClassSimulation( int simulationMode, uint8_t *reader_mac_buf) if (tracing) { uint8_t parity[MAX_PARITY_SIZE]; GetParity(receivedCmd, len, parity); - LogTrace(receivedCmd,len, (r2t_time-time_0)<< 4, (r2t_time-time_0) << 4, parity, TRUE); + LogTrace(receivedCmd,len, (r2t_time-time_0)<< 4, (r2t_time-time_0) << 4, parity, true); if (trace_data != NULL) { GetParity(trace_data, trace_data_size, parity); - LogTrace(trace_data, trace_data_size, (t2r_time-time_0) << 4, (t2r_time-time_0) << 4, parity, FALSE); + LogTrace(trace_data, trace_data_size, (t2r_time-time_0) << 4, (t2r_time-time_0) << 4, parity, false); } if(!tracing) { DbpString("Trace full"); @@ -1420,7 +1420,7 @@ static void TransmitIClassCommand(const uint8_t *cmd, int len, int *samples, int uint8_t sendbyte; - bool firstpart = TRUE; + bool firstpart = true; c = 0; for(;;) { if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { @@ -1512,14 +1512,14 @@ void ReaderTransmitIClass(uint8_t* frame, int len) if (tracing) { uint8_t par[MAX_PARITY_SIZE]; GetParity(frame, len, par); - LogTrace(frame, len, rsamples, rsamples, par, TRUE); + LogTrace(frame, len, rsamples, rsamples, par, true); } } //----------------------------------------------------------------------------- // Wait a certain time for tag response -// If a response is captured return TRUE -// If it takes too long return FALSE +// If a response is captured return true +// If it takes too long return false //----------------------------------------------------------------------------- static int GetIClassAnswer(uint8_t *receivedResponse, int maxLen, int *samples, int *elapsed) //uint8_t *buffer { @@ -1538,27 +1538,27 @@ static int GetIClassAnswer(uint8_t *receivedResponse, int maxLen, int *samples, uint8_t b; if (elapsed) *elapsed = 0; - bool skip = FALSE; + bool skip = false; c = 0; for(;;) { WDT_HIT(); - if(BUTTON_PRESS()) return FALSE; + if(BUTTON_PRESS()) return false; if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { AT91C_BASE_SSC->SSC_THR = 0x00; // To make use of exact timing of next command from reader!! if (elapsed) (*elapsed)++; } if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { - if(c < timeout) { c++; } else { return FALSE; } + if(c < timeout) { c++; } else { return false; } b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; skip = !skip; if(skip) continue; if(ManchesterDecoding(b & 0x0f)) { *samples = c << 3; - return TRUE; + return true; } } } @@ -1567,14 +1567,14 @@ static int GetIClassAnswer(uint8_t *receivedResponse, int maxLen, int *samples, int ReaderReceiveIClass(uint8_t* receivedAnswer) { int samples = 0; - if (!GetIClassAnswer(receivedAnswer,160,&samples,0)) return FALSE; + if (!GetIClassAnswer(receivedAnswer,160,&samples,0)) return false; rsamples += samples; if (tracing) { uint8_t parity[MAX_PARITY_SIZE]; GetParity(receivedAnswer, Demod.len, parity); - LogTrace(receivedAnswer,Demod.len,rsamples,rsamples,parity,FALSE); + LogTrace(receivedAnswer,Demod.len,rsamples,rsamples,parity,false); } - if(samples == 0) return FALSE; + if(samples == 0) return false; return Demod.len; } @@ -1582,7 +1582,7 @@ void setupIclassReader() { FpgaDownloadAndGo(FPGA_BITSTREAM_HF); // Reset trace buffer - set_tracing(TRUE); + set_tracing(true); clear_trace(); // Setup SSC @@ -1822,7 +1822,7 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) { uint8_t resp[ICLASS_BUFFER_SIZE]; setupIclassReader(); - set_tracing(TRUE); + set_tracing(true); while(!BUTTON_PRESS()) { diff --git a/armsrc/iso14443b.c b/armsrc/iso14443b.c index 22227e74..75769859 100644 --- a/armsrc/iso14443b.c +++ b/armsrc/iso14443b.c @@ -243,7 +243,7 @@ static RAMFUNC int Handle14443bUartBit(uint8_t bit) LED_A_OFF(); // Finished receiving Uart.state = STATE_UNSYNCD; if (Uart.byteCnt != 0) { - return TRUE; + return true; } } else { // this is an error @@ -259,7 +259,7 @@ static RAMFUNC int Handle14443bUartBit(uint8_t bit) break; } - return FALSE; + return false; } @@ -283,7 +283,7 @@ static void UartInit(uint8_t *data) // Receive a command (from the reader to us, where we are the simulated tag), // and store it in the given buffer, up to the given maximum length. Keeps // spinning, waiting for a well-framed command, until either we get one -// (returns TRUE) or someone presses the pushbutton on the board (FALSE). +// (returns true) or someone presses the pushbutton on the board (false). // // Assume that we're called with the SSC (to the FPGA) and ADC path set // correctly. @@ -302,20 +302,20 @@ static int GetIso14443bCommandFromReader(uint8_t *received, uint16_t *len) for(;;) { WDT_HIT(); - if(BUTTON_PRESS()) return FALSE; + if(BUTTON_PRESS()) return false; if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; for(uint8_t mask = 0x80; mask != 0x00; mask >>= 1) { if(Handle14443bUartBit(b & mask)) { *len = Uart.byteCnt; - return TRUE; + return true; } } } } - return FALSE; + return false; } //----------------------------------------------------------------------------- @@ -347,7 +347,7 @@ void SimulateIso14443bTag(void) FpgaDownloadAndGo(FPGA_BITSTREAM_HF); clear_trace(); - set_tracing(TRUE); + set_tracing(true); const uint8_t *resp; uint8_t *respCode; @@ -387,7 +387,7 @@ void SimulateIso14443bTag(void) if (tracing) { uint8_t parity[MAX_PARITY_SIZE]; - LogTrace(receivedCmd, len, 0, 0, parity, TRUE); + LogTrace(receivedCmd, len, 0, 0, parity, true); } // Good, look at the command now. @@ -464,7 +464,7 @@ void SimulateIso14443bTag(void) // trace the response: if (tracing) { uint8_t parity[MAX_PARITY_SIZE]; - LogTrace(resp, respLen, 0, 0, parity, FALSE); + LogTrace(resp, respLen, 0, 0, parity, false); } } @@ -702,7 +702,7 @@ static RAMFUNC int Handle14443bSamplesDemod(int ci, int cq) LED_C_OFF(); if(s == 0x000) { // This is EOF (start, stop and all data bits == '0' - return TRUE; + return true; } } } @@ -716,7 +716,7 @@ static RAMFUNC int Handle14443bSamplesDemod(int ci, int cq) break; } - return FALSE; + return false; } @@ -739,12 +739,12 @@ static void DemodInit(uint8_t *data) /* * Demodulate the samples we received from the tag, also log to tracebuffer - * quiet: set to 'TRUE' to disable debug output + * quiet: set to 'true' to disable debug output */ static void GetSamplesFor14443bDemod(int n, bool quiet) { int max = 0; - bool gotFrame = FALSE; + bool gotFrame = false; int lastRxCounter, ci, cq, samples = 0; // Allocate memory from BigBuf for some buffers @@ -792,7 +792,7 @@ static void GetSamplesFor14443bDemod(int n, bool quiet) samples += 2; if(Handle14443bSamplesDemod(ci, cq)) { - gotFrame = TRUE; + gotFrame = true; break; } } @@ -808,7 +808,7 @@ static void GetSamplesFor14443bDemod(int n, bool quiet) //Tracing if (tracing && Demod.len > 0) { uint8_t parity[MAX_PARITY_SIZE]; - LogTrace(Demod.output, Demod.len, 0, 0, parity, FALSE); + LogTrace(Demod.output, Demod.len, 0, 0, parity, false); } } @@ -929,7 +929,7 @@ static void CodeAndTransmit14443bAsReader(const uint8_t *cmd, int len) TransmitFor14443b(); if (tracing) { uint8_t parity[MAX_PARITY_SIZE]; - LogTrace(cmd,len, 0, 0, parity, TRUE); + LogTrace(cmd,len, 0, 0, parity, true); } } @@ -951,7 +951,7 @@ int iso14443b_apdu(uint8_t const *message, size_t message_length, uint8_t *respo // send CodeAndTransmit14443bAsReader(message_frame, message_length + 4); // get response - GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT*100, TRUE); + GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT*100, true); if(Demod.len < 3) { return 0; @@ -981,7 +981,7 @@ int iso14443b_select_card() // first, wake up the tag CodeAndTransmit14443bAsReader(wupb, sizeof(wupb)); - GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE); + GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, true); // ATQB too short? if (Demod.len < 14) { @@ -996,7 +996,7 @@ int iso14443b_select_card() attrib[7] = Demod.output[10] & 0x0F; ComputeCrc14443(CRC_14443_B, attrib, 9, attrib + 9, attrib + 10); CodeAndTransmit14443bAsReader(attrib, sizeof(attrib)); - GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE); + GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, true); // Answer to ATTRIB too short? if(Demod.len < 3) { @@ -1056,12 +1056,12 @@ void ReadSTMemoryIso14443b(uint32_t dwLast) SpinDelay(200); clear_trace(); - set_tracing(TRUE); + set_tracing(true); // First command: wake up the tag using the INITIATE command uint8_t cmd1[] = {0x06, 0x00, 0x97, 0x5b}; CodeAndTransmit14443bAsReader(cmd1, sizeof(cmd1)); - GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE); + GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, true); if (Demod.len == 0) { DbpString("No response from tag"); @@ -1077,7 +1077,7 @@ void ReadSTMemoryIso14443b(uint32_t dwLast) cmd1[1] = Demod.output[0]; ComputeCrc14443(CRC_14443_B, cmd1, 2, &cmd1[2], &cmd1[3]); CodeAndTransmit14443bAsReader(cmd1, sizeof(cmd1)); - GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE); + GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, true); if (Demod.len != 3) { Dbprintf("Expected 3 bytes from tag, got %d", Demod.len); return; @@ -1099,7 +1099,7 @@ void ReadSTMemoryIso14443b(uint32_t dwLast) cmd1[0] = 0x0B; ComputeCrc14443(CRC_14443_B, cmd1, 1 , &cmd1[1], &cmd1[2]); CodeAndTransmit14443bAsReader(cmd1, 3); // Only first three bytes for this one - GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE); + GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, true); if (Demod.len != 10) { Dbprintf("Expected 10 bytes from tag, got %d", Demod.len); return; @@ -1128,7 +1128,7 @@ void ReadSTMemoryIso14443b(uint32_t dwLast) cmd1[1] = i; ComputeCrc14443(CRC_14443_B, cmd1, 2, &cmd1[2], &cmd1[3]); CodeAndTransmit14443bAsReader(cmd1, sizeof(cmd1)); - GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE); + GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, true); if (Demod.len != 6) { // Check if we got an answer from the tag DbpString("Expected 6 bytes from tag, got less..."); return; @@ -1174,13 +1174,13 @@ void RAMFUNC SnoopIso14443b(void) // We won't start recording the frames that we acquire until we trigger; // a good trigger condition to get started is probably when we see a // response from the tag. - int triggered = TRUE; // TODO: set and evaluate trigger condition + int triggered = true; // TODO: set and evaluate trigger condition FpgaDownloadAndGo(FPGA_BITSTREAM_HF); BigBuf_free(); clear_trace(); - set_tracing(TRUE); + set_tracing(true); // The DMA buffer, used to stream samples from the FPGA int8_t *dmaBuf = (int8_t*) BigBuf_malloc(ISO14443B_DMA_BUFFER_SIZE); @@ -1217,8 +1217,8 @@ void RAMFUNC SnoopIso14443b(void) FpgaSetupSscDma((uint8_t*) dmaBuf, ISO14443B_DMA_BUFFER_SIZE); uint8_t parity[MAX_PARITY_SIZE]; - bool TagIsActive = FALSE; - bool ReaderIsActive = FALSE; + bool TagIsActive = false; + bool ReaderIsActive = false; // And now we loop, receiving samples. for(;;) { @@ -1259,7 +1259,7 @@ void RAMFUNC SnoopIso14443b(void) if (!TagIsActive) { // no need to try decoding reader data if the tag is sending if(Handle14443bUartBit(ci & 0x01)) { if(triggered && tracing) { - LogTrace(Uart.output, Uart.byteCnt, samples, samples, parity, TRUE); + LogTrace(Uart.output, Uart.byteCnt, samples, samples, parity, true); } /* And ready to receive another command. */ UartReset(); @@ -1269,7 +1269,7 @@ void RAMFUNC SnoopIso14443b(void) } if(Handle14443bUartBit(cq & 0x01)) { if(triggered && tracing) { - LogTrace(Uart.output, Uart.byteCnt, samples, samples, parity, TRUE); + LogTrace(Uart.output, Uart.byteCnt, samples, samples, parity, true); } /* And ready to receive another command. */ UartReset(); @@ -1287,9 +1287,9 @@ void RAMFUNC SnoopIso14443b(void) if(tracing) { uint8_t parity[MAX_PARITY_SIZE]; - LogTrace(Demod.output, Demod.len, samples, samples, parity, FALSE); + LogTrace(Demod.output, Demod.len, samples, samples, parity, false); } - triggered = TRUE; + triggered = true; // And ready to receive another response. DemodReset(); @@ -1330,12 +1330,12 @@ void SendRawCommand14443B(uint32_t datalen, uint32_t recv, uint8_t powerfield, u FpgaSetupSsc(); if (datalen){ - set_tracing(TRUE); + set_tracing(true); CodeAndTransmit14443bAsReader(data, datalen); if(recv) { - GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE); + GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, true); uint16_t iLen = MIN(Demod.len, USB_CMD_DATA_SIZE); cmd_send(CMD_ACK, iLen, 0, 0, Demod.output, iLen); } diff --git a/armsrc/iso15693.c b/armsrc/iso15693.c index e11e5a9c..1f0b8193 100644 --- a/armsrc/iso15693.c +++ b/armsrc/iso15693.c @@ -305,7 +305,7 @@ static int GetIso15693AnswerFromTag(uint8_t *receivedResponse, int maxLen, int * FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR); //spindelay(60); // greg - experiment to get rid of some of the 0 byte/failed reads c = 0; - getNext = FALSE; + getNext = false; for(;;) { if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { AT91C_BASE_SSC->SSC_THR = 0x43; @@ -444,7 +444,7 @@ static int GetIso15693AnswerFromSniff(uint8_t *receivedResponse, int maxLen, int FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR); //spindelay(60); // greg - experiment to get rid of some of the 0 byte/failed reads c = 0; - getNext = FALSE; + getNext = false; for(;;) { if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { AT91C_BASE_SSC->SSC_THR = 0x43; @@ -612,7 +612,7 @@ void AcquireRawAdcSamplesIso15693(void) FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR); c = 0; - getNext = FALSE; + getNext = false; for(;;) { if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { AT91C_BASE_SSC->SSC_THR = 0x43; @@ -666,7 +666,7 @@ void RecordRawAdcSamplesIso15693(void) FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR); c = 0; - getNext = FALSE; + getNext = false; for(;;) { if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { AT91C_BASE_SSC->SSC_THR = 0x43; diff --git a/armsrc/lfops.c b/armsrc/lfops.c index f3bbbf84..911ba8da 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -568,7 +568,7 @@ static void fcAll(uint8_t fc, int *n, uint8_t clock, uint16_t *modCnt) uint8_t wavesPerClock = clock/fc; uint8_t mod = clock % fc; //modifier uint8_t modAdj = fc/mod; //how often to apply modifier - bool modAdjOk = !(fc % mod); //if (fc % mod==0) modAdjOk=TRUE; + bool modAdjOk = !(fc % mod); //if (fc % mod==0) modAdjOk=true; // loop through clock - step field clock for (uint8_t idx=0; idx < wavesPerClock; idx++){ // put 1/2 FC length 1's and 1/2 0's per field clock wave (to create the wave) @@ -820,9 +820,9 @@ void CmdPSKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream) for (i=0; i= 128 && blockN <= 256) { return ((blockN & 0x0F) == 0x0F); } - return FALSE; + return false; } void MifareCWipe(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){ diff --git a/armsrc/mifaresniff.c b/armsrc/mifaresniff.c index f20f2557..5391e5f9 100644 --- a/armsrc/mifaresniff.c +++ b/armsrc/mifaresniff.c @@ -35,7 +35,7 @@ bool MfSniffInit(void){ sniffSAK = 0; sniffUIDType = SNF_UID_4; - return FALSE; + return false; } bool MfSniffEnd(void){ @@ -43,7 +43,7 @@ bool MfSniffEnd(void){ cmd_send(CMD_ACK,0,0,0,0,0); LED_B_OFF(); - return FALSE; + return false; } bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint8_t *parity, uint16_t bitCnt, bool reader) { @@ -112,7 +112,7 @@ bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint8_t *parity, ui sniffBuf[11] = sniffSAK; sniffBuf[12] = 0xFF; sniffBuf[13] = 0xFF; - LogTrace(sniffBuf, 14, 0, 0, NULL, TRUE); + LogTrace(sniffBuf, 14, 0, 0, NULL, true); sniffState = SNF_CARD_CMD; } // intentionally no break; case SNF_CARD_CMD:{ @@ -127,14 +127,14 @@ bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint8_t *parity, ui } - return FALSE; + return false; } bool RAMFUNC MfSniffSend(uint16_t maxTimeoutMs) { if (BigBuf_get_traceLen() && (GetTickCount() > timerData + maxTimeoutMs)) { return intMfSniffSend(); } - return FALSE; + return false; } // internal sending function. not a RAMFUNC. @@ -162,5 +162,5 @@ bool intMfSniffSend() { clear_trace(); - return TRUE; + return true; } diff --git a/armsrc/printf.c b/armsrc/printf.c index 94ed809d..79c123df 100644 --- a/armsrc/printf.c +++ b/armsrc/printf.c @@ -175,6 +175,7 @@ reswitch: switch (ch = (u_char)*fmt++) { padc = '0'; goto reswitch; } + // intentionally fall through to next case case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': for (n = 0;; ++fmt) { diff --git a/client/cmdhf.c b/client/cmdhf.c index 17c31209..93906a7d 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -361,7 +361,7 @@ int CmdHFList(const char *Cmd) char param2 = '\0'; char param3 = '\0'; char type[40] = {0}; - char filename[FILE_PATH_SIZE]; + char filename[FILE_PATH_SIZE] = {0}; uint8_t protocol = 0; // parse command line diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index 859dec2f..03ab0b5a 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -486,12 +486,12 @@ int CmdHF14AInfo(const char *Cmd) // try to see if card responses to "chinese magic backdoor" commands. - mfCIdentify(); + (void)mfCIdentify(); if (isMifareClassic) { switch(DetectClassicPrng()) { case 0: - PrintAndLog("Prng detection: HARDEND (hardnested)"); + PrintAndLog("Prng detection: HARDENED (hardnested)"); break; case 1: PrintAndLog("Prng detection: WEAK"); @@ -1032,12 +1032,9 @@ static command_t CommandTable[] = }; int CmdHF14A(const char *Cmd) { - // flush - WaitForResponseTimeout(CMD_ACK,NULL,100); - - // parse - CmdsParse(CommandTable, Cmd); - return 0; + (void)WaitForResponseTimeout(CMD_ACK,NULL,100); + CmdsParse(CommandTable, Cmd); + return 0; } int CmdHelp(const char *Cmd) diff --git a/client/cmdhfepa.c b/client/cmdhfepa.c index ac1f4268..76664bf5 100644 --- a/client/cmdhfepa.c +++ b/client/cmdhfepa.c @@ -202,10 +202,7 @@ int CmdHelp(const char *Cmd) int CmdHFEPA(const char *Cmd) { - // flush - WaitForResponseTimeout(CMD_ACK,NULL,100); - - // parse - CmdsParse(CommandTable, Cmd); - return 0; + (void)WaitForResponseTimeout(CMD_ACK,NULL,100); + CmdsParse(CommandTable, Cmd); + return 0; } diff --git a/client/cmdhflist.c b/client/cmdhflist.c index c87aa237..5538b6fb 100644 --- a/client/cmdhflist.c +++ b/client/cmdhflist.c @@ -559,8 +559,10 @@ bool NestedCheckKey(uint64_t key, TAuthData *ad, uint8_t *cmd, uint8_t cmdsize, uint32_t ar1 = crypto1_word(pcs, 0, 0) ^ ad->ar_enc; uint32_t at1 = crypto1_word(pcs, 0, 0) ^ ad->at_enc; - if (!(ar == ar1 && at == at1 && NTParityChk(ad, nt1))) + if (!(ar == ar1 && at == at1 && NTParityChk(ad, nt1))) { + crypto1_destroy(pcs); return false; + } memcpy(buf, cmd, cmdsize); mf_crypto1_decrypt(pcs, buf, cmdsize, 0); diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index b50d6013..e2a4ba1e 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -726,7 +726,6 @@ int CmdHF14AMfNested(const char *Cmd) blockNo = i * 4; keyType = j; num_to_bytes(e_sector[i].Key[j], 6, key); - keyFound = true; break; } @@ -737,6 +736,7 @@ int CmdHF14AMfNested(const char *Cmd) // Can't found a key.... if (!keyFound) { PrintAndLog("Can't found any of the known keys."); + free(e_sector); return 4; } PrintAndLog("--auto key. block no:%3d, key type:%c key:%s", blockNo, keyType?'B':'A', sprint_hex(key, 6)); @@ -1187,7 +1187,10 @@ int CmdHF14AMfChk(const char *Cmd) // initialize storage for found keys e_sector = calloc(SectorsCnt, sizeof(sector_t)); - if (e_sector == NULL) return 1; + if (e_sector == NULL) { + free(keyBlock); + return 1; + } for (uint8_t keyAB = 0; keyAB < 2; keyAB++) { for (uint16_t sectorNo = 0; sectorNo < SectorsCnt; sectorNo++) { e_sector[sectorNo].Key[keyAB] = 0xffffffffffff; @@ -2666,11 +2669,9 @@ static command_t CommandTable[] = int CmdHFMF(const char *Cmd) { - // flush - WaitForResponseTimeout(CMD_ACK,NULL,100); - - CmdsParse(CommandTable, Cmd); - return 0; + (void)WaitForResponseTimeout(CMD_ACK,NULL,100); + CmdsParse(CommandTable, Cmd); + return 0; } int CmdHelp(const char *Cmd) diff --git a/client/cmdhfmfhard.c b/client/cmdhfmfhard.c index be618d6e..4a379c71 100644 --- a/client/cmdhfmfhard.c +++ b/client/cmdhfmfhard.c @@ -276,7 +276,6 @@ static void init_bitflip_bitarrays(void) if (bytesread != filesize) { printf("File read error with %s. Aborting...\n", state_file_name); fclose(statesfile); - inflateEnd(&compressed_stream); exit(5); } fclose(statesfile); diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index e4115d71..1077ec99 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -1834,7 +1834,7 @@ static command_t CommandTable[] = }; int CmdHFMFUltra(const char *Cmd){ - WaitForResponseTimeout(CMD_ACK,NULL,100); + (void)WaitForResponseTimeout(CMD_ACK,NULL,100); CmdsParse(CommandTable, Cmd); return 0; } diff --git a/client/cmdhftopaz.c b/client/cmdhftopaz.c index b0b8a3d2..6058cabe 100644 --- a/client/cmdhftopaz.c +++ b/client/cmdhftopaz.c @@ -455,7 +455,7 @@ int CmdHFTopazReader(const char *Cmd) PrintAndLog("HR0 : %02x (%sa Topaz tag (%scapable of carrying a NDEF message), %s memory map)", rid_response[0], (rid_response[0] & 0xF0) == 0x10 ? "" : "not ", (rid_response[0] & 0xF0) == 0x10 ? "" : "not ", - (rid_response[0] & 0x0F) == 0x10 ? "static" : "dynamic"); + (rid_response[0] & 0x0F) == 0x01 ? "static" : "dynamic"); PrintAndLog("HR1 : %02x", rid_response[1]); status = topaz_rall(uid_echo, rall_response); @@ -554,10 +554,7 @@ static command_t CommandTable[] = int CmdHFTopaz(const char *Cmd) { - // flush - WaitForResponseTimeout(CMD_ACK,NULL,100); - - // parse + (void)WaitForResponseTimeout(CMD_ACK,NULL,100); CmdsParse(CommandTable, Cmd); return 0; } diff --git a/client/cmdlfhitag.c b/client/cmdlfhitag.c index 0fd8801b..8eef2359 100644 --- a/client/cmdlfhitag.c +++ b/client/cmdlfhitag.c @@ -66,6 +66,7 @@ int CmdLFHitagList(const char *Cmd) if (strlen(filename) > 0) { if ((pf = fopen(filename,"wb")) == NULL) { PrintAndLog("Error: Could not open file [%s]",filename); + free(got); return 1; } } @@ -166,11 +167,11 @@ int CmdLFHitagSim(const char *Cmd) { return 1; } tag_mem_supplied = true; - if (fread(c.d.asBytes,48,1,pf) == 0) { - PrintAndLog("Error: File reading error"); - fclose(pf); + if (fread(c.d.asBytes,1,48,pf) != 48) { + PrintAndLog("Error: File reading error"); + fclose(pf); return 1; - } + } fclose(pf); } else { tag_mem_supplied = false; @@ -289,7 +290,7 @@ int CmdLFHitagSimS(const char *Cmd) { return 1; } tag_mem_supplied = true; - if (fread(c.d.asBytes, 4*64, 1, pf) == 0) { + if (fread(c.d.asBytes, 1, 4*64, pf) != 4*64) { PrintAndLog("Error: File reading error"); fclose(pf); return 1; @@ -321,9 +322,9 @@ int CmdLFHitagCheckChallenges(const char *Cmd) { return 1; } file_given = true; - if (fread(c.d.asBytes,8*60,1,pf) == 0) { - PrintAndLog("Error: File reading error"); - fclose(pf); + if (fread(c.d.asBytes,1,8*60,pf) != 8*60) { + PrintAndLog("Error: File reading error"); + fclose(pf); return 1; } fclose(pf); diff --git a/client/cmdlfindala.c b/client/cmdlfindala.c index b30231c5..02c906d0 100644 --- a/client/cmdlfindala.c +++ b/client/cmdlfindala.c @@ -287,7 +287,7 @@ int CmdIndalaDemod(const char *Cmd) { } int CmdIndalaClone(const char *Cmd) { - UsbCommand c; + UsbCommand c = {0}; unsigned int uid1, uid2, uid3, uid4, uid5, uid6, uid7; uid1 = uid2 = uid3 = uid4 = uid5 = uid6 = uid7 = 0; diff --git a/client/emv/crypto_polarssl.c b/client/emv/crypto_polarssl.c index 3d11afe5..5a3db8ea 100644 --- a/client/emv/crypto_polarssl.c +++ b/client/emv/crypto_polarssl.c @@ -105,7 +105,7 @@ static struct crypto_pk *crypto_pk_polarssl_open_rsa(va_list vl) int res = rsa_check_pubkey(&cp->ctx); if(res != 0) { fprintf(stderr, "PolarSSL public key error res=%x exp=%d mod=%d.\n", res * -1, explen, modlen); - + free(cp); return NULL; } @@ -150,6 +150,7 @@ static struct crypto_pk *crypto_pk_polarssl_open_priv_rsa(va_list vl) int res = rsa_check_privkey(&cp->ctx); if(res != 0) { fprintf(stderr, "PolarSSL private key error res=%x exp=%d mod=%d.\n", res * -1, explen, modlen); + free(cp); return NULL; } @@ -184,6 +185,7 @@ static struct crypto_pk *crypto_pk_polarssl_genkey_rsa(va_list vl) int res = rsa_gen_key(&cp->ctx, &myrand, NULL, nbits, exp); if (res) { fprintf(stderr, "PolarSSL private key generation error res=%x exp=%d nbits=%d.\n", res * -1, exp, nbits); + free(cp); return NULL; } @@ -216,6 +218,7 @@ static unsigned char *crypto_pk_polarssl_encrypt(const struct crypto_pk *_cp, co res = rsa_public(&cp->ctx, buf, result); if(res) { printf("RSA encrypt failed. Error: %x data len: %zd key len: %zd\n", res * -1, len, keylen); + free(result); return NULL; } @@ -242,6 +245,7 @@ static unsigned char *crypto_pk_polarssl_decrypt(const struct crypto_pk *_cp, co res = rsa_private(&cp->ctx, buf, result); // CHECK??? if(res) { printf("RSA decrypt failed. Error: %x data len: %zd key len: %zd\n", res * -1, len, keylen); + free(result); return NULL; } diff --git a/client/flash.c b/client/flash.c index e43ebd1b..9a443cb8 100644 --- a/client/flash.c +++ b/client/flash.c @@ -40,7 +40,7 @@ static const uint8_t elf_ident[] = { // Turn PHDRs into flasher segments, checking for PHDR sanity and merging adjacent // unaligned segments if needed -static int build_segs_from_phdrs(flash_file_t *ctx, FILE *fd, Elf32_Phdr *phdrs, int num_phdrs) +static int build_segs_from_phdrs(flash_file_t *ctx, FILE *fd, Elf32_Phdr *phdrs, uint16_t num_phdrs) { Elf32_Phdr *phdr = phdrs; flash_seg_t *seg; @@ -191,7 +191,7 @@ int flash_load(flash_file_t *ctx, const char *name, bool can_write_bl) FILE *fd = NULL; Elf32_Ehdr ehdr; Elf32_Phdr *phdrs = NULL; - int num_phdrs; + uint16_t num_phdrs; int res; fd = fopen(name, "rb"); @@ -270,7 +270,7 @@ fail: // Get the state of the proxmark, backwards compatible static int get_proxmark_state(uint32_t *state) { - UsbCommand c; + UsbCommand c = {0}; c.cmd = CMD_DEVICE_INFO; SendCommand(&c); UsbCommand resp; diff --git a/client/fpga_compress.c b/client/fpga_compress.c index fc298a8b..bd1e8be2 100644 --- a/client/fpga_compress.c +++ b/client/fpga_compress.c @@ -108,7 +108,7 @@ int zlib_compress(FILE *infile[], uint8_t num_infiles, FILE *outfile, bool hardn for(uint16_t j = 0; j < num_infiles; j++) { for(uint16_t k = 0; k < FPGA_INTERLEAVE_SIZE; k++) { - c = fgetc(infile[j]); + c = (uint8_t)fgetc(infile[j]); if (!feof(infile[j])) { fpga_config[i++] = c; } else if (num_infiles > 1) { diff --git a/client/mifarehost.c b/client/mifarehost.c index 2d69cfae..9be04b4d 100644 --- a/client/mifarehost.c +++ b/client/mifarehost.c @@ -328,7 +328,7 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, struct Crypto1State *p1, *p2, *p3, *p4; // flush queue - WaitForResponseTimeout(CMD_ACK, NULL, 100); + (void)WaitForResponseTimeout(CMD_ACK,NULL,100); UsbCommand c = {CMD_MIFARE_NESTED, {blockNo + keyType * 0x100, trgBlockNo + trgKeyType * 0x100, calibrate}}; memcpy(c.d.asBytes, key, 6); @@ -910,6 +910,7 @@ int mfTraceDecode(uint8_t *data_src, int len, uint8_t parity, bool wantSaveToEml uint32_t nr1 = crypto1_word(pcs, nr_enc, 1) ^ nr_enc; uint32_t ar1 = crypto1_word(pcs, 0, 0) ^ ar_enc; uint32_t at1 = crypto1_word(pcs, 0, 0) ^ at_enc; + crypto1_destroy(pcs); printf("key> the same key test. nr1: %08x ar1: %08x at1: %08x \n", nr1, ar1, at1); if (NTParityCheck(nt1)) diff --git a/client/proxgui.cpp b/client/proxgui.cpp index e899174c..18749158 100644 --- a/client/proxgui.cpp +++ b/client/proxgui.cpp @@ -62,12 +62,9 @@ extern "C" void MainGraphics(void) extern "C" void InitGraphics(int argc, char **argv, char *script_cmds_file, char *script_cmd, bool usb_present) { #ifdef Q_WS_X11 - bool useGUI = getenv("DISPLAY") != 0; -#else - bool useGUI = true; -#endif - if (!useGUI) + if (getenv("DISPLAY") == NULL) return; +#endif main_loop_thread = new WorkerThread(script_cmds_file, script_cmd, usb_present); gui = new ProxGuiQT(argc, argv, main_loop_thread); diff --git a/client/proxguiqt.h b/client/proxguiqt.h index e43311ee..5f7199fc 100644 --- a/client/proxguiqt.h +++ b/client/proxguiqt.h @@ -110,7 +110,6 @@ class ProxGuiQT : public QObject ProxWidget *plotwidget; int argc; char **argv; - void (*main_func)(void); WorkerThread *proxmarkThread; public: diff --git a/client/scripting.c b/client/scripting.c index e73c7138..232da889 100644 --- a/client/scripting.c +++ b/client/scripting.c @@ -221,7 +221,7 @@ static int l_iso14443b_crc(lua_State *L) unsigned char buf[USB_CMD_DATA_SIZE]; size_t len = 0; const char *data = luaL_checklstring(L, 1, &len); - if (USB_CMD_DATA_SIZE < len) + if (len > USB_CMD_DATA_SIZE-2) len = USB_CMD_DATA_SIZE-2; for (int i = 0; i < len; i += 2) { diff --git a/client/util_posix.c b/client/util_posix.c index 32158ada..435e41f3 100644 --- a/client/util_posix.c +++ b/client/util_posix.c @@ -117,7 +117,7 @@ uint64_t msclock() { #include struct _timeb t; _ftime(&t); - return 1000 * t.time + t.millitm; + return 1000 * (uint64_t)t.time + t.millitm; // NORMAL CODE (use _ftime_s) //struct _timeb t; diff --git a/include/proxmark3.h b/include/proxmark3.h index 4a59636e..6fb6624f 100644 --- a/include/proxmark3.h +++ b/include/proxmark3.h @@ -61,9 +61,6 @@ #define SPI_FPGA_MODE 0 #define SPI_LCD_MODE 1 -#define TRUE 1 -#define FALSE 0 - //#define PACKED __attribute__((__packed__)) #define LED_A_ON() HIGH(GPIO_LED_A) diff --git a/tools/mfkey/mfkey32.c b/tools/mfkey/mfkey32.c index a5665ab2..d84305d0 100755 --- a/tools/mfkey/mfkey32.c +++ b/tools/mfkey/mfkey32.c @@ -10,7 +10,7 @@ // 32 bit recover key from 2 nonces int main (int argc, char *argv[]) { - nonces_t data; + nonces_t data = {0}; uint32_t ks2; // keystream used to encrypt reader response uint64_t key; // recovered key From fdee1ffa8419e8357913582f53e74218cae5b3d4 Mon Sep 17 00:00:00 2001 From: stuiterveer Date: Wed, 20 Jun 2018 06:34:00 +0200 Subject: [PATCH 114/127] Ignore DS_Store (#620) Prevent further commits containing DS_Store files --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index a7cc8803..85f92ea8 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,7 @@ usb_cmd.lua version.c client/ui/ui_overlays.h *.Td +.DS_Store *.exe hardnested_stats.txt From 577b1c27f5baab911609412a5dc15a95b92504d9 Mon Sep 17 00:00:00 2001 From: Michael Farrell Date: Mon, 9 Jul 2018 15:49:03 +0800 Subject: [PATCH 115/127] Allow disabling unlink() with -DNO_UNLINK. (#625) --- client/comms.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/client/comms.c b/client/comms.c index be0cfd10..2030f8f3 100644 --- a/client/comms.c +++ b/client/comms.c @@ -12,7 +12,7 @@ #include "comms.h" #include -#ifdef __linux__ +#if defined(__linux__) && !defined(NO_UNLINK) #include // for unlink() #endif #include "uart.h" @@ -339,8 +339,10 @@ void CloseProxmark(void) { uart_close(sp); } -#ifdef __linux__ +#if defined(__linux__) && !defined(NO_UNLINK) // Fix for linux, it seems that it is extremely slow to release the serial port file descriptor /dev/* + // + // This may be disabled at compile-time with -DNO_UNLINK (used for a JNI-based serial port on Android). if (serial_port_name) { unlink(serial_port_name); } From b2e0ac5d3bd01ac9383d321efc483304cc7e0d6d Mon Sep 17 00:00:00 2001 From: pwpiwi Date: Thu, 19 Jul 2018 18:01:18 +0200 Subject: [PATCH 116/127] fix: array index out of range in mfkeys.log (thanks to @TomHarkness) --- client/scripts/mfkeys.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/scripts/mfkeys.lua b/client/scripts/mfkeys.lua index 671ce03d..e8abd0b9 100644 --- a/client/scripts/mfkeys.lua +++ b/client/scripts/mfkeys.lua @@ -68,7 +68,7 @@ function checkBlock(blockNo, keys, keyType) data = data} local status = checkCommand(command) if status then return status, blockNo end - start = start+n+1 + start = start + n remaining = remaining - n end return nil From 00349d82044bae7fce7c0da8ed1a9449ef602c8a Mon Sep 17 00:00:00 2001 From: Fl0-0 Date: Thu, 26 Jul 2018 17:17:11 +0200 Subject: [PATCH 117/127] Fix Gcc 8 warnings (#632) --- client/util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/util.c b/client/util.c index 4f84e3b5..2be1e46b 100644 --- a/client/util.c +++ b/client/util.c @@ -226,7 +226,7 @@ char *sprint_hex_ascii(const uint8_t *data, const size_t len) { memset(buf, 0x00, 1024); size_t max_len = (len > 255) ? 255 : len; // max 255 bytes * 3 + 2 characters = 767 in buffer - sprintf(tmp, "%s| ", sprint_hex(data, max_len) ); + sprintf(tmp, "%.765s| ", sprint_hex(data, max_len) ); size_t i = 0; size_t pos = (max_len * 3)+2; From 913a54a86accab2a6959c4fcaf53711502f2d954 Mon Sep 17 00:00:00 2001 From: pwpiwi Date: Thu, 26 Jul 2018 17:18:10 +0200 Subject: [PATCH 118/127] save 2.3K flash-memory by avoiding a single floating point operation (#630) --- armsrc/util.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/armsrc/util.c b/armsrc/util.c index e25c6e0b..59dfe07b 100644 --- a/armsrc/util.c +++ b/armsrc/util.c @@ -489,13 +489,13 @@ void WaitTicks(uint32_t ticks){ // 1us = 1.5ticks. void WaitUS(uint16_t us){ if ( us == 0 ) return; - WaitTicks( (uint32_t)(us * 1.5) ); + WaitTicks( (uint32_t)us * 3 / 2 ) ; } void WaitMS(uint16_t ms){ if (ms == 0) return; - WaitTicks( (uint32_t)(ms * 1500) ); + WaitTicks( (uint32_t)ms * 1500 ); } From ab20cc35b7cef4e69a4e74f2b59d9e9b7fe2d022 Mon Sep 17 00:00:00 2001 From: Michael Farrell Date: Tue, 31 Jul 2018 03:33:06 +1000 Subject: [PATCH 119/127] Adds `lf hid pack` and `lf hid unpack` offline commands. (#614) * These are used to pack and unpack the bit length, facility code and card number from "short" HID Prox IDs. * This also simplifies some repeated code that is used to parse hex digits in lfhid, and adds basic client-side validation to the `lf hid clone` and `lf hid sim` commands, for when an ID that is too long is entered. * Implements parity checks/calculation for 26-bit H10301 cards. * Adds links to useful resources for HID Prox cards. * Adds an explicit warning about the lack of parities on non-26-bit cards. * Changes all the examples to use 26-bit IDs that have a parity bit set. --- client/cmdlfhid.c | 328 ++++++++++++++++++++++++++++++++++++++-------- client/cmdlfhid.h | 29 ++++ 2 files changed, 301 insertions(+), 56 deletions(-) diff --git a/client/cmdlfhid.c b/client/cmdlfhid.c index ca58d8ab..433a093d 100644 --- a/client/cmdlfhid.c +++ b/client/cmdlfhid.c @@ -6,6 +6,16 @@ // the license. //----------------------------------------------------------------------------- // Low frequency HID commands (known) +// +// Useful resources: +// RF interface, programming a T55x7 clone, 26-bit HID H10301 encoding: +// http://www.proxmark.org/files/Documents/125%20kHz%20-%20HID/HID_format_example.pdf +// +// "Understanding Card Data Formats" +// https://www.hidglobal.com/sites/default/files/hid-understanding_card_data_formats-wp-en.pdf +// +// "What Format Do You Need?" +// https://www.hidglobal.com/sites/default/files/resource_files/hid-prox-br-en.pdf //----------------------------------------------------------------------------- #include "cmdlfhid.h" @@ -18,9 +28,171 @@ #include "cmdparser.h" #include "cmddata.h" //for g_debugMode, demodbuff cmds #include "lfdemod.h" // for HIDdemodFSK +#include "parity.h" // for parity +#include "util.h" // for param_get8,32 static int CmdHelp(const char *Cmd); + +/** + * Packs a "short" (<38-bit) HID ID from component parts. + * + * This only works with 26, 34, 35 and 37 bit card IDs. + * + * NOTE: Parity calculation is only supported on 26-bit tags. Other card lengths + * may have invalid parity. + * + * Returns false on invalid inputs. + */ +bool pack_short_hid(/* out */ uint32_t *hi, /* out */ uint32_t *lo, /* in */ const short_hid_info *info) { + uint32_t high = 0, low = 0; + + switch (info->fmtLen) { + case 26: // HID H10301 + low |= (info->cardnum & 0xffff) << 1; + low |= (info->fc & 0xff) << 17; + + if (info->parityValid) { + // Calculate parity + low |= oddparity32((low >> 1) & 0xfff) & 1; + low |= (evenparity32((low >> 13) & 0xfff) & 1) << 25; + } + break; + + case 34: + low |= (info->cardnum & 0xffff) << 1; + low |= (info->fc & 0x7fff) << 17; + high |= (info->fc & 0x8000) >> 15; + // TODO: Calculate parity + break; + + case 35: + low |= (info->cardnum & 0xfffff) << 1; + low |= (info->fc & 0x7ff) << 21; + high |= (info->fc & 0x800) >> 11; + // TODO: Calculate parity + break; + + case 37: + low |= (info->cardnum & 0x7ffff) << 1; + low |= (info->fc & 0xfff) << 20; + high |= (info->fc & 0xf000) >> 12; + // TODO: Calculate parity + break; + + default: + // Invalid / unsupported length + return false; + } + + // Set the highest bit + if (info->fmtLen != 37) { + // Bit 37 is always set + high |= 0x20; + + // Set the bit corresponding to the length. + if (info->fmtLen < 32) { + low |= 1 << info->fmtLen; + } else { + high |= 1 << (info->fmtLen - 32); + } + } + + // Return result only if successful. + *hi = high; + *lo = low; + return true; +} + + +/** + * Unpacks a "short" (<38-bit) HID ID into its component parts. + * + * This only works with 26, 34, 35 and 37 bit card IDs. + * + * NOTE: Parity checking is only supported on 26-bit tags. + * + * Returns false on invalid inputs. + */ +bool unpack_short_hid(short_hid_info *out, uint32_t hi, uint32_t lo) { + memset(out, 0, sizeof(short_hid_info)); + + if (((hi >> 5) & 1) == 1) { + // if bit 38 is set then < 37 bit format is used + uint32_t lo2 = 0; + // get bits 21-37 to check for format len bit + lo2 = (((hi & 31) << 12) | (lo >> 20)); + uint8_t idx3 = 1; + // find last bit set to 1 (format len bit) + while (lo2 > 1) { + lo2 = lo2 >> 1; + idx3++; + } + + out->fmtLen = idx3 + 19; + + switch (out->fmtLen) { + case 26: // HID H10301 + out->cardnum = (lo >> 1) & 0xFFFF; + out->fc = (lo >> 17) & 0xFF; + + if (g_debugMode) { + PrintAndLog("oddparity : input=%x, calculated=%d, provided=%d", + (lo >> 1) & 0xFFF, oddparity32((lo >> 1) & 0xFFF), lo & 1); + PrintAndLog("evenparity: input=%x, calculated=%d, provided=%d", + (lo >> 13) & 0xFFF, evenparity32((lo >> 13) & 0xFFF) & 1, (lo >> 25) & 1); + } + + out->parityValid = + (oddparity32((lo >> 1) & 0xFFF) == (lo & 1)) && + ((evenparity32((lo >> 13) & 0xFFF) & 1) == ((lo >> 25) & 1)); + break; + + case 34: + out->cardnum = (lo >> 1) & 0xFFFF; + out->fc = ((hi & 1) << 15) | (lo >> 17); + // TODO: Calculate parity + break; + + case 35: + out->cardnum = (lo >> 1) & 0xFFFFF; + out->fc = ((hi & 1) << 11) | (lo >> 21); + // TODO: Calculate parity + break; + + default: + return false; + } + } else { + // If bit 38 is not set, then 37 bit format is used + out->fmtLen = 37; + out->cardnum = (lo >> 1) & 0x7FFFF; + out->fc = ((hi & 0xF) << 12) | (lo >> 20); + // TODO: Calculate parity + } + return true; +} + + +/** + * Converts a hex string to component "hi" and "lo" 32-bit integers, one nibble + * at a time. + * + * Returns the number of nibbles (4 bits) entered. + */ +int hexstring_to_int64(/* out */ uint32_t* hi, /* out */ uint32_t* lo, const char* str) { + // TODO: Replace this with param_gethex when it supports arbitrary length + // inputs. + int n = 0, i = 0; + + while (sscanf(&str[i++], "%1x", &n ) == 1) { + *hi = (*hi << 4) | (*lo >> 28); + *lo = (*lo << 4) | (n & 0xf); + } + + return i - 1; +} + //by marshmellow (based on existing demod + holiman's refactor) //HID Prox demod - FSK RF/50 with preamble of 00011101 (then manchester encoded) //print full HID Prox ID and some bit format details if found @@ -60,45 +232,19 @@ int CmdFSKdemodHID(const char *Cmd) (unsigned int) hi2, (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF); } else { //standard HID tags <38 bits - uint8_t fmtLen = 0; - uint32_t fc = 0; - uint32_t cardnum = 0; - if (((hi>>5)&1)==1){//if bit 38 is set then < 37 bit format is used - uint32_t lo2=0; - lo2=(((hi & 31) << 12) | (lo>>20)); //get bits 21-37 to check for format len bit - uint8_t idx3 = 1; - while(lo2>1){ //find last bit set to 1 (format len bit) - lo2=lo2>>1; - idx3++; - } - fmtLen =idx3+19; - fc =0; - cardnum=0; - if(fmtLen==26){ - cardnum = (lo>>1)&0xFFFF; - fc = (lo>>17)&0xFF; - } - if(fmtLen==34){ - cardnum = (lo>>1)&0xFFFF; - fc= ((hi&1)<<15)|(lo>>17); - } - if(fmtLen==35){ - cardnum = (lo>>1)&0xFFFFF; - fc = ((hi&1)<<11)|(lo>>21); - } - } - else { //if bit 38 is not set then 37 bit format is used - fmtLen = 37; - fc = 0; - cardnum = 0; - if(fmtLen == 37){ - cardnum = (lo>>1)&0x7FFFF; - fc = ((hi&0xF)<<12)|(lo>>20); - } - } - PrintAndLog("HID Prox TAG ID: %x%08x (%d) - Format Len: %dbit - FC: %d - Card: %d", + short_hid_info card_info; + bool ret = unpack_short_hid(&card_info, (uint32_t)hi, (uint32_t)lo); + PrintAndLog("HID Prox TAG ID: %x%08x (%d) - Format Len: %u bits - FC: %u - Card: %u", (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF, - (unsigned int) fmtLen, (unsigned int) fc, (unsigned int) cardnum); + card_info.fmtLen, card_info.fc, card_info.cardnum); + + if (card_info.fmtLen == 26) { + PrintAndLog("Parity: %s", card_info.parityValid ? "valid" : "invalid"); + } + + if (!ret) { + PrintAndLog("Invalid or unsupported tag length."); + } } setDemodBuf(BitStream,BitLen,idx); setClockGrid(50, waveIdx + (idx*50)); @@ -112,7 +258,7 @@ int CmdFSKdemodHID(const char *Cmd) int CmdHIDReadFSK(const char *Cmd) { int findone=0; - if(Cmd[0]=='1') findone=1; + if(Cmd[0]=='1') findone=1; UsbCommand c={CMD_HID_DEMOD_FSK}; c.arg[0]=findone; SendCommand(&c); @@ -121,30 +267,30 @@ int CmdHIDReadFSK(const char *Cmd) int CmdHIDSim(const char *Cmd) { - uint32_t hi = 0, lo = 0; - int n = 0, i = 0; + uint32_t hi = 0, lo = 0; + hexstring_to_int64(&hi, &lo, Cmd); + if (hi >= 0x40) { + PrintAndLog("This looks like a long tag ID. Use 'lf simfsk' for long tags. Aborting!"); + return 0; + } - while (sscanf(&Cmd[i++], "%1x", &n ) == 1) { - hi = (hi << 4) | (lo >> 28); - lo = (lo << 4) | (n & 0xf); - } + PrintAndLog("Emulating tag with ID %x%08x", hi, lo); + PrintAndLog("Press pm3-button to abort simulation"); - PrintAndLog("Emulating tag with ID %x%08x", hi, lo); - PrintAndLog("Press pm3-button to abort simulation"); - - UsbCommand c = {CMD_HID_SIM_TAG, {hi, lo, 0}}; - SendCommand(&c); - return 0; + UsbCommand c = {CMD_HID_SIM_TAG, {hi, lo, 0}}; + SendCommand(&c); + return 0; } int CmdHIDClone(const char *Cmd) { unsigned int hi2 = 0, hi = 0, lo = 0; - int n = 0, i = 0; UsbCommand c; if (strchr(Cmd,'l') != 0) { - while (sscanf(&Cmd[i++], "%1x", &n ) == 1) { + int n = 0, i = 0; + + while (sscanf(&Cmd[i++], "%1x", &n ) == 1) { hi2 = (hi2 << 4) | (hi >> 28); hi = (hi << 4) | (lo >> 28); lo = (lo << 4) | (n & 0xf); @@ -155,9 +301,10 @@ int CmdHIDClone(const char *Cmd) c.d.asBytes[0] = 1; } else { - while (sscanf(&Cmd[i++], "%1x", &n ) == 1) { - hi = (hi << 4) | (lo >> 28); - lo = (lo << 4) | (n & 0xf); + hexstring_to_int64(&hi, &lo, Cmd); + if (hi >= 0x40) { + PrintAndLog("This looks like a long tag ID. Aborting!"); + return 0; } PrintAndLog("Cloning tag with ID %x%08x", hi, lo); @@ -175,6 +322,73 @@ int CmdHIDClone(const char *Cmd) return 0; } + +int CmdHIDPack(const char *Cmd) { + uint32_t hi = 0, lo = 0; + short_hid_info card_info; + + if (strlen(Cmd)<3) { + PrintAndLog("Usage: lf hid pack "); + PrintAndLog(" sample: lf hid pack 26 123 4567"); + return 0; + } + + card_info.fmtLen = param_get8(Cmd, 0); + card_info.fc = param_get32ex(Cmd, 1, 0, 10); + card_info.cardnum = param_get32ex(Cmd, 2, 0, 10); + card_info.parityValid = true; + + // TODO + if (card_info.fmtLen != 26) { + PrintAndLog("Warning: Parity bits are only calculated for 26 bit IDs -- this may be invalid!"); + } + + bool ret = pack_short_hid(&hi, &lo, &card_info); + + if (ret) { + PrintAndLog("HID Prox TAG ID: %x%08x (%d) - Format Len: %u bits - FC: %u - Card: %u", + (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF, + card_info.fmtLen, card_info.fc, card_info.cardnum); + } else { + PrintAndLog("Invalid or unsupported tag length."); + } + return 0; +} + + +int CmdHIDUnpack(const char *Cmd) +{ + uint32_t hi = 0, lo = 0; + if (strlen(Cmd)<1) { + PrintAndLog("Usage: lf hid unpack "); + PrintAndLog(" sample: lf hid unpack 2006f623ae"); + return 0; + } + + hexstring_to_int64(&hi, &lo, Cmd); + if (hi >= 0x40) { + PrintAndLog("This looks like a long tag ID. Aborting!"); + return 0; + } + + short_hid_info card_info; + bool ret = unpack_short_hid(&card_info, hi, lo); + + PrintAndLog("HID Prox TAG ID: %x%08x (%d) - Format Len: %u bits - FC: %u - Card: %u", + (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF, + card_info.fmtLen, card_info.fc, card_info.cardnum); + + if (card_info.fmtLen == 26) { + PrintAndLog("Parity: %s", card_info.parityValid ? "valid" : "invalid"); + } + + if (!ret) { + PrintAndLog("Invalid or unsupported tag length."); + } + return 0; +} + + static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, @@ -182,6 +396,8 @@ static command_t CommandTable[] = {"read", CmdHIDReadFSK, 0, "['1'] Realtime HID FSK Read from antenna (option '1' for one tag only)"}, {"sim", CmdHIDSim, 0, " -- HID tag simulator"}, {"clone", CmdHIDClone, 0, " ['l'] -- Clone HID to T55x7 (tag must be in antenna)(option 'l' for 84bit ID)"}, + {"pack", CmdHIDPack, 1, " -- packs a <38 bit (short) HID ID from its length, facility code and card number"}, + {"unpack", CmdHIDUnpack, 1, " -- unpacks a <38 bit (short) HID ID to its length, facility code and card number"}, {NULL, NULL, 0, NULL} }; diff --git a/client/cmdlfhid.h b/client/cmdlfhid.h index b03f7041..e53a95c6 100644 --- a/client/cmdlfhid.h +++ b/client/cmdlfhid.h @@ -11,10 +11,39 @@ #ifndef CMDLFHID_H__ #define CMDLFHID_H__ +#include +#include + +// Structure for unpacked "short" (<38 bits) HID Prox tags. +typedef struct { + // Format length, in bits. + uint8_t fmtLen; + + // Facility code. + uint32_t fc; + + // Card number. + uint32_t cardnum; + + // Parity validity. + // + // When used with pack_short_hid, this determines if we should calculate + // parity values for the ID. + // + // When used with unpack_short_hid, this indicates if we got valid parity + // values for the ID. + bool parityValid; +} short_hid_info; + +bool pack_short_hid(/* out */ uint32_t *hi, /* out */ uint32_t *lo, /* in */ const short_hid_info *info); +bool unpack_short_hid(short_hid_info* out, uint32_t hi, uint32_t lo); + int CmdLFHID(const char *Cmd); int CmdFSKdemodHID(const char *Cmd); int CmdHIDReadDemod(const char *Cmd); int CmdHIDSim(const char *Cmd); int CmdHIDClone(const char *Cmd); +int CmdHIDPack(const char *Cmd); +int CmdHIDUnpack(const char *Cmd); #endif From b6a04aff48853b786aa0be1256bb8b01b35d8bbc Mon Sep 17 00:00:00 2001 From: grauerfuchs <42082416+grauerfuchs@users.noreply.github.com> Date: Sat, 4 Aug 2018 06:26:36 -0400 Subject: [PATCH 120/127] fix truncation issue on "lf t55 config" modulation Fix for issue #637 --- client/cmdlft55xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index f53ff0d6..2a096cd0 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -207,7 +207,7 @@ void printT5xxHeader(uint8_t page){ int CmdT55xxSetConfig(const char *Cmd) { uint8_t offset = 0; - char modulation[5] = {0x00}; + char modulation[6] = {0x00}; char tmp = 0x00; uint8_t bitRate = 0; uint8_t rates[9] = {8,16,32,40,50,64,100,128,0}; From 5125e4263c36063f49d3b410b78da293b705b7d2 Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Sun, 5 Aug 2018 12:13:44 -0400 Subject: [PATCH 121/127] allow common makefile options-defines (#635) --- armsrc/Makefile | 13 ++++-- client/Makefile | 58 +++++++++++++++----------- common/Makefile_Enabled_Options.common | 40 ++++++++++++++++++ 3 files changed, 82 insertions(+), 29 deletions(-) create mode 100644 common/Makefile_Enabled_Options.common diff --git a/armsrc/Makefile b/armsrc/Makefile index dea5d06c..3a7293e5 100644 --- a/armsrc/Makefile +++ b/armsrc/Makefile @@ -10,10 +10,16 @@ APP_INCLUDES = apps.h #remove one of the following defines and comment out the relevant line #in the next section to remove that particular feature from compilation -APP_CFLAGS = -DWITH_ISO14443a_StandAlone -DWITH_LF -DWITH_ISO15693 -DWITH_ISO14443a -DWITH_ISO14443b -DWITH_ICLASS -DWITH_LEGICRF -DWITH_HITAG -DWITH_CRC -DON_DEVICE -DWITH_HFSNOOP \ - -fno-strict-aliasing -ffunction-sections -fdata-sections -#-DWITH_LCD +APP_CFLAGS = -DON_DEVICE \ + -fno-strict-aliasing -ffunction-sections -fdata-sections +include ../common/Makefile_Enabled_Options.common + +ifneq (,$(findstring LCD,$(APP_CFLAGS))) + SRC_LCD = fonts.c LCD.c +else + SRC_LCD = +endif #SRC_LCD = fonts.c LCD.c SRC_LF = lfops.c hitag2.c hitagS.c lfsampling.c pcf7931.c lfdemod.c protocols.c SRC_ISO15693 = iso15693.c iso15693tools.c @@ -21,7 +27,6 @@ SRC_ISO14443a = epa.c iso14443a.c mifareutil.c mifarecmd.c mifaresniff.c mifares SRC_ISO14443b = iso14443b.c SRC_CRAPTO1 = crypto1.c des.c SRC_CRC = iso14443crc.c crc.c crc16.c crc32.c parity.c - #the FPGA bitstream files. Note: order matters! FPGA_BITSTREAMS = fpga_lf.bit fpga_hf.bit diff --git a/client/Makefile b/client/Makefile index 917dc767..2d256b72 100644 --- a/client/Makefile +++ b/client/Makefile @@ -23,6 +23,10 @@ LDFLAGS = $(ENV_LDFLAGS) CFLAGS = $(ENV_CFLAGS) -std=c99 -D_ISOC99_SOURCE -I. -I../include -I../common -I../common/polarssl -I../zlib -I../uart -I/opt/local/include -I../liblua -Wall -g -O3 CXXFLAGS = -I../include -Wall -O3 +APP_CFLAGS = +include ../common/Makefile_Enabled_Options.common +CFLAGS += $(APP_CFLAGS) + LUAPLATFORM = generic platform = $(shell uname) ifneq (,$(findstring MINGW,$(platform))) @@ -37,32 +41,34 @@ else endif endif -# Check for correctly configured Qt5 -QTINCLUDES = $(shell pkg-config --cflags Qt5Core Qt5Widgets 2>/dev/null) -QTLDLIBS = $(shell pkg-config --libs Qt5Core Qt5Widgets 2>/dev/null) -MOC = $(shell pkg-config --variable=host_bins Qt5Core)/moc -UIC = $(shell pkg-config --variable=host_bins Qt5Core)/uic -ifeq ($(QTINCLUDES), ) -# if Qt5 not found check for correctly configured Qt4 - QTINCLUDES = $(shell pkg-config --cflags QtCore QtGui 2>/dev/null) - QTLDLIBS = $(shell pkg-config --libs QtCore QtGui 2>/dev/null) - MOC = $(shell pkg-config --variable=moc_location QtCore) - UIC = $(shell pkg-config --variable=uic_location QtCore) -else - CXXFLAGS += -std=c++11 -fPIC -endif -ifeq ($(QTINCLUDES), ) -# if both pkg-config commands failed, search in common places - ifneq ($(QTDIR), ) - QTINCLUDES = -I$(QTDIR)/include -I$(QTDIR)/include/QtCore -I$(QTDIR)/include/QtGui - QTLDLIBS = -L$(QTDIR)/lib -lQtCore4 -lQtGui4 - ifneq ($(wildcard $(QTDIR)/include/QtWidgets),) - QTINCLUDES += -I$(QTDIR)/include/QtWidgets - QTLDLIBS = -L$(QTDIR)/lib -lQt5Widgets -lQt5Gui -lQt5Core - CXXFLAGS += -std=c++11 -fPIC +ifneq (,$(findstring WITH_GUI,$(APP_CFLAGS))) + # Check for correctly configured Qt5 + QTINCLUDES = $(shell pkg-config --cflags Qt5Core Qt5Widgets 2>/dev/null) + QTLDLIBS = $(shell pkg-config --libs Qt5Core Qt5Widgets 2>/dev/null) + MOC = $(shell pkg-config --variable=host_bins Qt5Core)/moc + UIC = $(shell pkg-config --variable=host_bins Qt5Core)/uic + ifeq ($(QTINCLUDES), ) + # if Qt5 not found check for correctly configured Qt4 + QTINCLUDES = $(shell pkg-config --cflags QtCore QtGui 2>/dev/null) + QTLDLIBS = $(shell pkg-config --libs QtCore QtGui 2>/dev/null) + MOC = $(shell pkg-config --variable=moc_location QtCore) + UIC = $(shell pkg-config --variable=uic_location QtCore) + else + CXXFLAGS += -std=c++11 -fPIC + endif + ifeq ($(QTINCLUDES), ) + # if both pkg-config commands failed, search in common places + ifneq ($(QTDIR), ) + QTINCLUDES = -I$(QTDIR)/include -I$(QTDIR)/include/QtCore -I$(QTDIR)/include/QtGui + QTLDLIBS = -L$(QTDIR)/lib -lQtCore4 -lQtGui4 + ifneq ($(wildcard $(QTDIR)/include/QtWidgets),) + QTINCLUDES += -I$(QTDIR)/include/QtWidgets + QTLDLIBS = -L$(QTDIR)/lib -lQt5Widgets -lQt5Gui -lQt5Core + CXXFLAGS += -std=c++11 -fPIC + endif + MOC = $(QTDIR)/bin/moc + UIC = $(QTDIR)/bin/uic endif - MOC = $(QTDIR)/bin/moc - UIC = $(QTDIR)/bin/uic endif endif @@ -79,6 +85,7 @@ DEPFLAGS = -MT $@ -MMD -MP -MF $(OBJDIR)/$*.Td # make temporary to final dependeny files after successful compilation POSTCOMPILE = $(MV) -f $(OBJDIR)/$*.Td $(OBJDIR)/$*.d + CORESRCS = uart_posix.c \ uart_win32.c \ util.c \ @@ -303,6 +310,7 @@ DEPENDENCY_FILES = $(patsubst %.c, $(OBJDIR)/%.d, $(CORESRCS) $(CMDSRCS) $(ZLIBS $(patsubst %.cpp, $(OBJDIR)/%.d, $(QTGUISRCS)) \ $(OBJDIR)/proxmark3.d $(OBJDIR)/flash.d $(OBJDIR)/flasher.d $(OBJDIR)/fpga_compress.d + $(DEPENDENCY_FILES): ; .PRECIOUS: $(DEPENDENCY_FILES) diff --git a/common/Makefile_Enabled_Options.common b/common/Makefile_Enabled_Options.common new file mode 100644 index 00000000..acb413bf --- /dev/null +++ b/common/Makefile_Enabled_Options.common @@ -0,0 +1,40 @@ +#NOTES: +# Do not put any comments inside the definition below (before the final flag) +# All definition lines except the last must end in a \ +# +#BEGIN +APP_CFLAGS += -DWITH_ISO14443a_StandAlone \ + -DWITH_ISO15693 \ + -DWITH_ISO14443a \ + -DWITH_ISO14443b \ + -DWITH_ICLASS \ + -DWITH_LEGICRF \ + -DWITH_HITAG \ + -DWITH_CRC \ + -DWITH_HFSNOOP \ + -DWITH_GUI +#END + + +### Standalone modes: +#-DWITH_ISO14443a_StandAlone +#-DWITH_LF +# +# if both WITH_LF and WITH_ISO4443a_StandAlone are defined +# ISO14443a_StandAlone will be the only one that runs +# You must remove it and define WITH_LF for LF standalone mode + +### Other options: +#-DWITH_ISO15693 \ Include ISO15693 support in build +#-DWITH_ISO14443a \ include ISO14443a support in build +#-DWITH_ISO14443b \ include ISO14443b support in build +#-DWITH_ICLASS \ include ICLASS support in build +#-DWITH_LEGICRF \ include LEGIC support in build +#-DWITH_HITAG \ include HITAG support in build +#-DWITH_CRC \ include CRC support in build +#-DWITH_HFSNOOP \ include HFSNOOP support in build +#-DWITH_SMARTCARD \ include SMARTCARD support in build +#-DWITH_GUI \ include QT GUI/Graph support in build +#-DWITH_LCD \ include LCD support in build (experimental?) + +#marshmellow NOTE: tested GUI, and SMARTCARD removal only... From 472345daee388f8d6786ead2f04b4ae0ff0462d4 Mon Sep 17 00:00:00 2001 From: pwpiwi Date: Sun, 5 Aug 2018 18:15:03 +0200 Subject: [PATCH 122/127] mod hw version: (#631) * create fpga version info at compile time (by additional functionality in fpgacompress) * remove hw version caching (prepare USB reconnect) * fix calculation of available compressed bytes in fpga_loader.c --- armsrc/Makefile | 11 +++ armsrc/appmain.c | 12 ++- armsrc/fpgaloader.c | 101 +++----------------- armsrc/fpgaloader.h | 12 ++- bootrom/Makefile | 1 + client/cmdhw.c | 14 +-- client/fpga_compress.c | 204 +++++++++++++++++++++++++++++++++++++---- common/Makefile.common | 7 +- common/fpga.h | 18 ++++ 9 files changed, 249 insertions(+), 131 deletions(-) create mode 100644 common/fpga.h diff --git a/armsrc/Makefile b/armsrc/Makefile index 3a7293e5..f0a0c0ff 100644 --- a/armsrc/Makefile +++ b/armsrc/Makefile @@ -64,6 +64,9 @@ ARMSRC = fpgaloader.c \ optimized_cipher.c \ hfsnoop.c +VERSIONSRC = version.c \ + fpga_version_info.c + # Do not move this inclusion before the definition of {THUMB,ASM,ARM}SRC include ../common/Makefile.common @@ -74,6 +77,14 @@ all: $(OBJS) .DELETE_ON_ERROR: +# version.c should be remade on every compilation +.PHONY: version.c +version.c: default_version.c + perl ../tools/mkversion.pl .. > $@ || $(COPY) $^ $@ + +fpga_version_info.c: $(FPGA_BITSTREAMS) $(FPGA_COMPRESSOR) + $(FPGA_COMPRESSOR) -v $(filter %.bit,$^) $@ + $(OBJDIR)/fpga_all.o: $(OBJDIR)/fpga_all.bit.z $(OBJCOPY) -O elf32-littlearm -I binary -B arm --prefix-sections=fpga_all_bit $^ $@ diff --git a/armsrc/appmain.c b/armsrc/appmain.c index e8581216..eabe9fbe 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -16,6 +16,7 @@ #include "cmd.h" #include "proxmark3.h" #include "apps.h" +#include "fpga.h" #include "util.h" #include "printf.h" #include "string.h" @@ -286,6 +287,7 @@ void ReadMem(int addr) extern struct version_information version_information; /* bootrom version information is pointed to from _bootphase1_version_pointer */ extern char *_bootphase1_version_pointer, _flash_start, _flash_end, _bootrom_start, _bootrom_end, __data_src_start__; + void SendVersion(void) { char temp[USB_CMD_DATA_SIZE]; /* Limited data payload in USB packets */ @@ -306,10 +308,12 @@ void SendVersion(void) FormatVersionInformation(temp, sizeof(temp), "os: ", &version_information); strncat(VersionString, temp, sizeof(VersionString) - strlen(VersionString) - 1); - FpgaGatherVersion(FPGA_BITSTREAM_LF, temp, sizeof(temp)); - strncat(VersionString, temp, sizeof(VersionString) - strlen(VersionString) - 1); - FpgaGatherVersion(FPGA_BITSTREAM_HF, temp, sizeof(temp)); - strncat(VersionString, temp, sizeof(VersionString) - strlen(VersionString) - 1); + for (int i = 0; i < fpga_bitstream_num; i++) { + strncat(VersionString, fpga_version_information[i], sizeof(VersionString) - strlen(VersionString) - 1); + if (i < fpga_bitstream_num - 1) { + strncat(VersionString, "\n", sizeof(VersionString) - strlen(VersionString) - 1); + } + } // Send Chip ID and used flash memory uint32_t text_and_rodata_section_size = (uint32_t)&__data_src_start__ - (uint32_t)&_flash_start; diff --git a/armsrc/fpgaloader.c b/armsrc/fpgaloader.c index c0b04f3c..77223bd0 100644 --- a/armsrc/fpgaloader.c +++ b/armsrc/fpgaloader.c @@ -10,20 +10,21 @@ // mode once it is configured. //----------------------------------------------------------------------------- +#include "fpgaloader.h" + #include #include #include -#include "fpgaloader.h" +#include "apps.h" +#include "fpga.h" #include "proxmark3.h" #include "util.h" #include "string.h" #include "BigBuf.h" #include "zlib.h" -extern void Dbprintf(const char *fmt, ...); - // remember which version of the bitstream we have already downloaded to the FPGA -static int downloaded_bitstream = FPGA_BITSTREAM_ERR; +static int downloaded_bitstream = 0; // this is where the bitstreams are located in memory: extern uint8_t _binary_obj_fpga_all_bit_z_start, _binary_obj_fpga_all_bit_z_end; @@ -31,10 +32,7 @@ extern uint8_t _binary_obj_fpga_all_bit_z_start, _binary_obj_fpga_all_bit_z_end; static uint8_t *fpga_image_ptr = NULL; static uint32_t uncompressed_bytes_cnt; -static const uint8_t _bitparse_fixed_header[] = {0x00, 0x09, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x00, 0x00, 0x01}; -#define FPGA_BITSTREAM_FIXED_HEADER_SIZE sizeof(_bitparse_fixed_header) #define OUTPUT_BUFFER_LEN 80 -#define FPGA_INTERLEAVE_SIZE 288 //----------------------------------------------------------------------------- // Set up the Serial Peripheral Interface as master @@ -201,7 +199,7 @@ static int get_from_fpga_combined_stream(z_streamp compressed_fpga_stream, uint8 //---------------------------------------------------------------------------- static int get_from_fpga_stream(int bitstream_version, z_streamp compressed_fpga_stream, uint8_t *output_buffer) { - while((uncompressed_bytes_cnt / FPGA_INTERLEAVE_SIZE) % FPGA_BITSTREAM_MAX != (bitstream_version - 1)) { + while((uncompressed_bytes_cnt / FPGA_INTERLEAVE_SIZE) % fpga_bitstream_num != (bitstream_version - 1)) { // skip undesired data belonging to other bitstream_versions get_from_fpga_combined_stream(compressed_fpga_stream, output_buffer); } @@ -234,7 +232,7 @@ static bool reset_fpga_stream(int bitstream_version, z_streamp compressed_fpga_s // initialize z_stream structure for inflate: compressed_fpga_stream->next_in = &_binary_obj_fpga_all_bit_z_start; - compressed_fpga_stream->avail_in = &_binary_obj_fpga_all_bit_z_start - &_binary_obj_fpga_all_bit_z_end; + compressed_fpga_stream->avail_in = &_binary_obj_fpga_all_bit_z_end - &_binary_obj_fpga_all_bit_z_start; compressed_fpga_stream->next_out = output_buffer; compressed_fpga_stream->avail_out = OUTPUT_BUFFER_LEN; compressed_fpga_stream->zalloc = &fpga_inflate_malloc; @@ -248,8 +246,8 @@ static bool reset_fpga_stream(int bitstream_version, z_streamp compressed_fpga_s header[i] = get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer); } - // Check for a valid .bit file (starts with _bitparse_fixed_header) - if(memcmp(_bitparse_fixed_header, header, FPGA_BITSTREAM_FIXED_HEADER_SIZE) == 0) { + // Check for a valid .bit file (starts with bitparse_fixed_header) + if(memcmp(bitparse_fixed_header, header, FPGA_BITSTREAM_FIXED_HEADER_SIZE) == 0) { return true; } else { return false; @@ -427,7 +425,7 @@ void FpgaDownloadAndGo(int bitstream_version) } unsigned int bitstream_length; - if(bitparse_find_section(bitstream_version, 'e', &bitstream_length, &compressed_fpga_stream, output_buffer)) { + if (bitparse_find_section(bitstream_version, 'e', &bitstream_length, &compressed_fpga_stream, output_buffer)) { DownloadFPGA(bitstream_version, bitstream_length, &compressed_fpga_stream, output_buffer); downloaded_bitstream = bitstream_version; } @@ -442,77 +440,6 @@ void FpgaDownloadAndGo(int bitstream_version) } -//----------------------------------------------------------------------------- -// Gather version information from FPGA image. Needs to decompress the begin -// of the respective (HF or LF) image. -// Note: decompression makes use of (i.e. overwrites) BigBuf[]. It is therefore -// advisable to call this only once and store the results for later use. -//----------------------------------------------------------------------------- -void FpgaGatherVersion(int bitstream_version, char *dst, int len) -{ - unsigned int fpga_info_len; - char tempstr[40] = {0x00}; - z_stream compressed_fpga_stream; - uint8_t output_buffer[OUTPUT_BUFFER_LEN] = {0x00}; - - dst[0] = '\0'; - - // ensure that we can allocate enough memory for decompression: - BigBuf_free(); BigBuf_Clear_ext(false); - - if (!reset_fpga_stream(bitstream_version, &compressed_fpga_stream, output_buffer)) - return; - - if(bitparse_find_section(bitstream_version, 'a', &fpga_info_len, &compressed_fpga_stream, output_buffer)) { - for (uint16_t i = 0; i < fpga_info_len; i++) { - char c = (char)get_from_fpga_stream(bitstream_version, &compressed_fpga_stream, output_buffer); - if (i < sizeof(tempstr)) { - tempstr[i] = c; - } - } - if (!memcmp("fpga_lf", tempstr, 7)) - strncat(dst, "LF ", len-1); - else if (!memcmp("fpga_hf", tempstr, 7)) - strncat(dst, "HF ", len-1); - } - strncat(dst, "FPGA image built", len-1); - if(bitparse_find_section(bitstream_version, 'b', &fpga_info_len, &compressed_fpga_stream, output_buffer)) { - strncat(dst, " for ", len-1); - for (uint16_t i = 0; i < fpga_info_len; i++) { - char c = (char)get_from_fpga_stream(bitstream_version, &compressed_fpga_stream, output_buffer); - if (i < sizeof(tempstr)) { - tempstr[i] = c; - } - } - strncat(dst, tempstr, len-1); - } - if(bitparse_find_section(bitstream_version, 'c', &fpga_info_len, &compressed_fpga_stream, output_buffer)) { - strncat(dst, " on ", len-1); - for (uint16_t i = 0; i < fpga_info_len; i++) { - char c = (char)get_from_fpga_stream(bitstream_version, &compressed_fpga_stream, output_buffer); - if (i < sizeof(tempstr)) { - tempstr[i] = c; - } - } - strncat(dst, tempstr, len-1); - } - if(bitparse_find_section(bitstream_version, 'd', &fpga_info_len, &compressed_fpga_stream, output_buffer)) { - strncat(dst, " at ", len-1); - for (uint16_t i = 0; i < fpga_info_len; i++) { - char c = (char)get_from_fpga_stream(bitstream_version, &compressed_fpga_stream, output_buffer); - if (i < sizeof(tempstr)) { - tempstr[i] = c; - } - } - strncat(dst, tempstr, len-1); - } - - strncat(dst, "\n", len-1); - - inflateEnd(&compressed_fpga_stream); -} - - //----------------------------------------------------------------------------- // Send a 16 bit command/data pair to the FPGA. // The bit format is: C3 C2 C1 C0 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0 @@ -562,12 +489,8 @@ void SetAdcMuxFor(uint32_t whichGpio) } void Fpga_print_status(void) { - Dbprintf("Fgpa"); - switch(downloaded_bitstream) { - case FPGA_BITSTREAM_HF: Dbprintf(" mode....................HF"); break; - case FPGA_BITSTREAM_LF: Dbprintf(" mode....................LF"); break; - default: Dbprintf(" mode....................%d", downloaded_bitstream); break; - } + Dbprintf("Currently loaded FPGA image:"); + Dbprintf(" %s", fpga_version_information[downloaded_bitstream-1]); } int FpgaGetCurrent() { diff --git a/armsrc/fpgaloader.h b/armsrc/fpgaloader.h index 7dfc5c12..fa16771d 100644 --- a/armsrc/fpgaloader.h +++ b/armsrc/fpgaloader.h @@ -10,10 +10,15 @@ // mode once it is configured. //----------------------------------------------------------------------------- +#ifndef __FPGALOADER_H +#define __FPGALOADER_H + +#include +#include + void FpgaSendCommand(uint16_t cmd, uint16_t v); void FpgaWriteConfWord(uint8_t v); void FpgaDownloadAndGo(int bitstream_version); -void FpgaGatherVersion(int bitstream_version, char *dst, int len); void FpgaSetupSsc(void); void SetupSpi(int mode); bool FpgaSetupSscDma(uint8_t *buf, int len); @@ -24,12 +29,9 @@ int FpgaGetCurrent(); void SetAdcMuxFor(uint32_t whichGpio); // definitions for multiple FPGA config files support -#define FPGA_BITSTREAM_MAX 2 // the total number of FPGA bitstreams (configs) -#define FPGA_BITSTREAM_ERR 0 #define FPGA_BITSTREAM_LF 1 #define FPGA_BITSTREAM_HF 2 - // Definitions for the FPGA commands. #define FPGA_CMD_SET_CONFREG (1<<12) #define FPGA_CMD_SET_DIVISOR (2<<12) @@ -72,3 +74,5 @@ void SetAdcMuxFor(uint32_t whichGpio); #define FPGA_HF_ISO14443A_TAGSIM_MOD (2<<0) #define FPGA_HF_ISO14443A_READER_LISTEN (3<<0) #define FPGA_HF_ISO14443A_READER_MOD (4<<0) + +#endif diff --git a/bootrom/Makefile b/bootrom/Makefile index 92373995..59c22aa2 100644 --- a/bootrom/Makefile +++ b/bootrom/Makefile @@ -10,6 +10,7 @@ ARMSRC = THUMBSRC = cmd.c usb_cdc.c bootrom.c ASMSRC = ram-reset.s flash-reset.s +VERSIONSRC = ## There is a strange bug with the linker: Sometimes it will not emit the glue to call ## BootROM from ARM mode. The symbol is emitted, but the section will be filled with diff --git a/client/cmdhw.c b/client/cmdhw.c index bdab01eb..f994e938 100644 --- a/client/cmdhw.c +++ b/client/cmdhw.c @@ -408,21 +408,13 @@ int CmdVersion(const char *Cmd) clearCommandBuffer(); UsbCommand c = {CMD_VERSION}; - static UsbCommand resp = {0, {0, 0, 0}}; + UsbCommand resp = {0, {0, 0, 0}}; - if (resp.arg[0] == 0 && resp.arg[1] == 0) { // no cached information available - SendCommand(&c); - if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) { - PrintAndLog("Prox/RFID mark3 RFID instrument"); - PrintAndLog((char*)resp.d.asBytes); - lookupChipID(resp.arg[0], resp.arg[1]); - } - } else { - PrintAndLog("[[[ Cached information ]]]\n"); + SendCommand(&c); + if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) { PrintAndLog("Prox/RFID mark3 RFID instrument"); PrintAndLog((char*)resp.d.asBytes); lookupChipID(resp.arg[0], resp.arg[1]); - PrintAndLog(""); } return 0; } diff --git a/client/fpga_compress.c b/client/fpga_compress.c index bd1e8be2..418a02b8 100644 --- a/client/fpga_compress.c +++ b/client/fpga_compress.c @@ -1,4 +1,6 @@ //----------------------------------------------------------------------------- +// piwi, 2017, 2018 +// // This code is licensed to you under the terms of the GNU GPL, version 2 or, // at your option, any later version. See the LICENSE.txt file for the text of // the license. @@ -11,9 +13,11 @@ #include #include +#include #include #include #include +#include "fpga.h" #include "zlib.h" #define MAX(a,b) ((a)>(b)?(a):(b)) @@ -37,18 +41,18 @@ #define COMPRESS_MAX_NICE_LENGTH 258 #define COMPRESS_MAX_CHAIN 8192 -#define FPGA_INTERLEAVE_SIZE 288 // (the FPGA's internal config frame size is 288 bits. Interleaving with 288 bytes should give best compression) -#define FPGA_CONFIG_SIZE 42336L // our current fpga_[lh]f.bit files are 42175 bytes. Rounded up to next multiple of FPGA_INTERLEAVE_SIZE #define HARDNESTED_TABLE_SIZE (sizeof(uint32_t) * ((1L<<19)+1)) static void usage(void) { fprintf(stdout, "Usage: fpga_compress ... \n"); fprintf(stdout, " Combine n FPGA bitstream files and compress them into one.\n\n"); - fprintf(stdout, " fpga_compress -d "); - fprintf(stdout, " Decompress . Write result to "); - fprintf(stdout, " fpga_compress -t "); - fprintf(stdout, " Compress hardnested table . Write result to "); + fprintf(stdout, " fpga_compress -v ... \n"); + fprintf(stdout, " Extract Version Information from FPGA bitstream files and write it to \n\n"); + fprintf(stdout, " fpga_compress -d \n"); + fprintf(stdout, " Decompress . Write result to \n\n"); + fprintf(stdout, " fpga_compress -t \n"); + fprintf(stdout, " Compress hardnested table . Write result to \n\n"); } @@ -60,7 +64,7 @@ static voidpf fpga_deflate_malloc(voidpf opaque, uInt items, uInt size) static void fpga_deflate_free(voidpf opaque, voidpf address) { - return free(address); + free(address); } @@ -252,9 +256,162 @@ int zlib_decompress(FILE *infile, FILE *outfile) } +/* Simple Xilinx .bit parser. The file starts with the fixed opaque byte sequence + * 00 09 0f f0 0f f0 0f f0 0f f0 00 00 01 + * After that the format is 1 byte section type (ASCII character), 2 byte length + * (big endian), bytes content. Except for section 'e' which has 4 bytes + * length. + */ +static int bitparse_find_section(FILE *infile, char section_name, unsigned int *section_length) +{ + int result = 0; + #define MAX_FPGA_BIT_STREAM_HEADER_SEARCH 100 // maximum number of bytes to search for the requested section + uint16_t numbytes = 0; + while(numbytes < MAX_FPGA_BIT_STREAM_HEADER_SEARCH) { + char current_name = (char)fgetc(infile); + numbytes++; + if(current_name < 'a' || current_name > 'e') { + /* Strange section name, abort */ + break; + } + unsigned int current_length = 0; + switch(current_name) { + case 'e': + /* Four byte length field */ + current_length += fgetc(infile) << 24; + current_length += fgetc(infile) << 16; + numbytes += 2; + default: /* Fall through, two byte length field */ + current_length += fgetc(infile) << 8; + current_length += fgetc(infile) << 0; + numbytes += 2; + } + + if(current_name != 'e' && current_length > 255) { + /* Maybe a parse error */ + break; + } + + if(current_name == section_name) { + /* Found it */ + *section_length = current_length; + result = 1; + break; + } + + for (uint16_t i = 0; i < current_length && numbytes < MAX_FPGA_BIT_STREAM_HEADER_SEARCH; i++) { + (void)fgetc(infile); + numbytes++; + } + } + + return result; +} + + +static int FpgaGatherVersion(FILE *infile, char* infile_name, char *dst, int len) +{ + unsigned int fpga_info_len; + char tempstr[40] = {0x00}; + + dst[0] = '\0'; + + for (uint16_t i = 0; i < FPGA_BITSTREAM_FIXED_HEADER_SIZE; i++) { + if (fgetc(infile) != bitparse_fixed_header[i]) { + fprintf(stderr, "Invalid FPGA file. Aborting...\n\n"); + return(EXIT_FAILURE); + } + } + + strncat(dst, basename(infile_name), len-1); + // if (bitparse_find_section(infile, 'a', &fpga_info_len)) { + // for (uint16_t i = 0; i < fpga_info_len; i++) { + // char c = (char)fgetc(infile); + // if (i < sizeof(tempstr)) { + // tempstr[i] = c; + // } + // } + // strncat(dst, tempstr, len-1); + // } + strncat(dst, " built", len-1); + if (bitparse_find_section(infile, 'b', &fpga_info_len)) { + strncat(dst, " for ", len-1); + for (uint16_t i = 0; i < fpga_info_len; i++) { + char c = (char)fgetc(infile); + if (i < sizeof(tempstr)) { + tempstr[i] = c; + } + } + strncat(dst, tempstr, len-1); + } + if (bitparse_find_section(infile, 'c', &fpga_info_len)) { + strncat(dst, " on ", len-1); + for (uint16_t i = 0; i < fpga_info_len; i++) { + char c = (char)fgetc(infile); + if (i < sizeof(tempstr)) { + tempstr[i] = c; + } + } + strncat(dst, tempstr, len-1); + } + if (bitparse_find_section(infile, 'd', &fpga_info_len)) { + strncat(dst, " at ", len-1); + for (uint16_t i = 0; i < fpga_info_len; i++) { + char c = (char)fgetc(infile); + if (i < sizeof(tempstr)) { + tempstr[i] = c; + } + } + strncat(dst, tempstr, len-1); + } + return 0; +} + + +static void print_version_info_preamble(FILE *outfile, int num_infiles) { + fprintf(outfile, "//-----------------------------------------------------------------------------\n"); + fprintf(outfile, "// piwi, 2018\n"); + fprintf(outfile, "//\n"); + fprintf(outfile, "// This code is licensed to you under the terms of the GNU GPL, version 2 or,\n"); + fprintf(outfile, "// at your option, any later version. See the LICENSE.txt file for the text of\n"); + fprintf(outfile, "// the license.\n"); + fprintf(outfile, "//-----------------------------------------------------------------------------\n"); + fprintf(outfile, "// Version information on fpga images\n"); + fprintf(outfile, "//\n"); + fprintf(outfile, "// This file is generated by fpga_compress. Don't edit!\n"); + fprintf(outfile, "//-----------------------------------------------------------------------------\n"); + fprintf(outfile, "\n"); + fprintf(outfile, "\n"); + fprintf(outfile, "const int fpga_bitstream_num = %d;\n", num_infiles); + fprintf(outfile, "const char* const fpga_version_information[%d] = {\n", num_infiles); +} + + +static int generate_fpga_version_info(FILE *infile[], char *infile_names[], int num_infiles, FILE *outfile) { + + char version_string[80] = ""; + + print_version_info_preamble(outfile, num_infiles); + + for (int i = 0; i < num_infiles; i++) { + FpgaGatherVersion(infile[i], infile_names[i], version_string, sizeof(version_string)); + fprintf(outfile, "\t\"%s\"", version_string); + if (i != num_infiles-1) { + fprintf(outfile, ","); + } + fprintf(outfile,"\n"); + } + + fprintf(outfile, "};\n"); + + return 0; +} + + int main(int argc, char **argv) { FILE **infiles; + char **infile_names; FILE *outfile; if (argc == 1 || argc == 2) { @@ -271,43 +428,56 @@ int main(int argc, char **argv) } infiles[0] = fopen(argv[2], "rb"); if (infiles[0] == NULL) { - fprintf(stderr, "Error. Cannot open input file %s", argv[2]); + fprintf(stderr, "Error. Cannot open input file %s\n\n", argv[2]); return(EXIT_FAILURE); } outfile = fopen(argv[3], "wb"); if (outfile == NULL) { - fprintf(stderr, "Error. Cannot open output file %s", argv[3]); + fprintf(stderr, "Error. Cannot open output file %s\n\n", argv[3]); return(EXIT_FAILURE); } return zlib_decompress(infiles[0], outfile); - } else { // Compress + } else { // Compress or gemerate version info bool hardnested_mode = false; + bool generate_version_file = false; int num_input_files = 0; - if (!strcmp(argv[1], "-t")) { // hardnested table + if (!strcmp(argv[1], "-t")) { // compress one hardnested table if (argc != 4) { usage(); return(EXIT_FAILURE); } hardnested_mode = true; num_input_files = 1; - } else { + } else if (!strcmp(argv[1], "-v")) { // generate version info + generate_version_file = true; + num_input_files = argc-3; + } else { // compress 1..n fpga files num_input_files = argc-2; } + infiles = calloc(num_input_files, sizeof(FILE*)); - for (uint16_t i = 0; i < num_input_files; i++) { - infiles[i] = fopen(argv[i+(hardnested_mode?2:1)], "rb"); + infile_names = calloc(num_input_files, sizeof(char*)); + for (uint16_t i = 0; i < num_input_files; i++) { + infile_names[i] = argv[i+((hardnested_mode || generate_version_file)?2:1)]; + infiles[i] = fopen(infile_names[i], "rb"); if (infiles[i] == NULL) { - fprintf(stderr, "Error. Cannot open input file %s", argv[i+(hardnested_mode?2:1)]); + fprintf(stderr, "Error. Cannot open input file %s\n\n", infile_names[i]); return(EXIT_FAILURE); } } outfile = fopen(argv[argc-1], "wb"); if (outfile == NULL) { - fprintf(stderr, "Error. Cannot open output file %s", argv[argc-1]); + fprintf(stderr, "Error. Cannot open output file %s\n\n", argv[argc-1]); return(EXIT_FAILURE); } - return zlib_compress(infiles, num_input_files, outfile, hardnested_mode); + if (generate_version_file) { + if (generate_fpga_version_info(infiles, infile_names, num_input_files, outfile)) { + return(EXIT_FAILURE); + } + } else { + return zlib_compress(infiles, num_input_files, outfile, hardnested_mode); + } } } diff --git a/common/Makefile.common b/common/Makefile.common index f31ff7bb..0ab89b3d 100644 --- a/common/Makefile.common +++ b/common/Makefile.common @@ -75,7 +75,7 @@ LIBS = -lgcc THUMBOBJ = $(patsubst %.c,$(OBJDIR)/%.o,$(notdir $(THUMBSRC))) ARMOBJ = $(patsubst %.c,$(OBJDIR)/%.o,$(notdir $(ARMSRC))) ASMOBJ = $(patsubst %.s,$(OBJDIR)/%.o,$(notdir $(ASMSRC))) -VERSIONOBJ = $(OBJDIR)/version.o +VERSIONOBJ = $(patsubst %.c,$(OBJDIR)/%.o,$(notdir $(VERSIONSRC))) $(THUMBOBJ): $(OBJDIR)/%.o: %.c $(INCLUDES) $(CC) $(CFLAGS) -mthumb -mthumb-interwork -o $@ $< @@ -99,11 +99,6 @@ OBJCOPY_TRANSLATIONS = --no-change-warnings \ $(OBJDIR)/%.s19: $(OBJDIR)/%.elf $(OBJCOPY) -Osrec --srec-forceS3 --strip-debug $(OBJCOPY_TRANSLATIONS) $^ $@ -# version.c should be remade on every compilation -.PHONY: version.c -version.c: default_version.c - perl ../tools/mkversion.pl .. > $@ || $(COPY) $^ $@ - # Automatic dependency generation DEPENDENCY_FILES = $(patsubst %.c,$(OBJDIR)/%.d,$(notdir $(THUMBSRC))) \ $(patsubst %.c,$(OBJDIR)/%.d,$(notdir $(ARMSRC))) \ diff --git a/common/fpga.h b/common/fpga.h new file mode 100644 index 00000000..b99a7593 --- /dev/null +++ b/common/fpga.h @@ -0,0 +1,18 @@ +//----------------------------------------------------------------------------- +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- + +#ifndef __FPGA_H +#define __FPGA_H + +#define FPGA_BITSTREAM_FIXED_HEADER_SIZE sizeof(bitparse_fixed_header) +#define FPGA_INTERLEAVE_SIZE 288 +#define FPGA_CONFIG_SIZE 42336L // our current fpga_[lh]f.bit files are 42175 bytes. Rounded up to next multiple of FPGA_INTERLEAVE_SIZE + +static const uint8_t bitparse_fixed_header[] = {0x00, 0x09, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x00, 0x00, 0x01}; +extern const int fpga_bitstream_num; +extern const char* const fpga_version_information[]; + +#endif From a2937cea8db9a2ef51becff18d3b0227b837b576 Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Mon, 6 Aug 2018 07:27:37 -0400 Subject: [PATCH 123/127] Separate WITH_LF and WITH_LF_StandAlone --- armsrc/appmain.c | 6 +++--- common/Makefile_Enabled_Options.common | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index eabe9fbe..27f43b3f 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -367,7 +367,7 @@ void SendStatus(void) cmd_send(CMD_ACK,1,0,0,0,0); } -#if defined(WITH_ISO14443a_StandAlone) || defined(WITH_LF) +#if defined(WITH_ISO14443a_StandAlone) || defined(WITH_LF_StandAlone) #define OPTS 2 @@ -635,7 +635,7 @@ void StandAloneMode14a() } } } -#elif WITH_LF +#elif WITH_LF_StandAlone // samy's sniff and repeat routine void SamyRun() { @@ -1428,7 +1428,7 @@ void __attribute__((noreturn)) AppMain(void) } WDT_HIT(); -#ifdef WITH_LF +#ifdef WITH_LF_StandAlone #ifndef WITH_ISO14443a_StandAlone if (BUTTON_HELD(1000) > 0) SamyRun(); diff --git a/common/Makefile_Enabled_Options.common b/common/Makefile_Enabled_Options.common index acb413bf..462ae56a 100644 --- a/common/Makefile_Enabled_Options.common +++ b/common/Makefile_Enabled_Options.common @@ -4,6 +4,7 @@ # #BEGIN APP_CFLAGS += -DWITH_ISO14443a_StandAlone \ + -DWITH_LF\ -DWITH_ISO15693 \ -DWITH_ISO14443a \ -DWITH_ISO14443b \ @@ -18,7 +19,7 @@ APP_CFLAGS += -DWITH_ISO14443a_StandAlone \ ### Standalone modes: #-DWITH_ISO14443a_StandAlone -#-DWITH_LF +#-DWITH_LF_StandAlone # # if both WITH_LF and WITH_ISO4443a_StandAlone are defined # ISO14443a_StandAlone will be the only one that runs From dfdca20c6cdbac73c620754572d49f1def70ff1f Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Mon, 6 Aug 2018 07:39:39 -0400 Subject: [PATCH 124/127] fix option comments to be more clear --- common/Makefile_Enabled_Options.common | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/common/Makefile_Enabled_Options.common b/common/Makefile_Enabled_Options.common index 462ae56a..8774946e 100644 --- a/common/Makefile_Enabled_Options.common +++ b/common/Makefile_Enabled_Options.common @@ -21,12 +21,13 @@ APP_CFLAGS += -DWITH_ISO14443a_StandAlone \ #-DWITH_ISO14443a_StandAlone #-DWITH_LF_StandAlone # -# if both WITH_LF and WITH_ISO4443a_StandAlone are defined +# if both WITH_LF_StandAlone and WITH_ISO4443a_StandAlone are defined # ISO14443a_StandAlone will be the only one that runs -# You must remove it and define WITH_LF for LF standalone mode +# You must remove it and define WITH_LF_StandAlone for LF standalone mode ### Other options: -#-DWITH_ISO15693 \ Include ISO15693 support in build +#-DWITH_LF \ include LF support in build +#-DWITH_ISO15693 \ include ISO15693 support in build #-DWITH_ISO14443a \ include ISO14443a support in build #-DWITH_ISO14443b \ include ISO14443b support in build #-DWITH_ICLASS \ include ICLASS support in build From 6a0915eac23a40d8ca0bdcaa5203164a7fb16e0e Mon Sep 17 00:00:00 2001 From: Fl0-0 Date: Tue, 7 Aug 2018 09:23:11 +0200 Subject: [PATCH 125/127] Bootrom version fix + .gitignore (#645) * Fix bootrom Makefile * Add armsrc/fpga_version_info.c to .gitignore --- .gitignore | 1 + bootrom/Makefile | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 85f92ea8..c551f7a2 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,7 @@ !client/hardnested/tables/*.z usb_cmd.lua version.c +armsrc/fpga_version_info.c client/ui/ui_overlays.h *.Td .DS_Store diff --git a/bootrom/Makefile b/bootrom/Makefile index 59c22aa2..dd1e7e08 100644 --- a/bootrom/Makefile +++ b/bootrom/Makefile @@ -10,7 +10,7 @@ ARMSRC = THUMBSRC = cmd.c usb_cdc.c bootrom.c ASMSRC = ram-reset.s flash-reset.s -VERSIONSRC = +VERSIONSRC = version.c ## There is a strange bug with the linker: Sometimes it will not emit the glue to call ## BootROM from ARM mode. The symbol is emitted, but the section will be filled with @@ -22,6 +22,11 @@ VERSIONSRC = # stdint.h provided locally until GCC 4.5 becomes C99 compliant APP_CFLAGS = -I. +# version.c should be remade on every compilation +.PHONY: version.c +version.c: default_version.c + perl ../tools/mkversion.pl .. > $@ || $(COPY) $^ $@ + # Do not move this inclusion before the definition of {THUMB,ASM,ARM}SRC include ../common/Makefile.common From 8ff31e935d19bc53dd8f27877b7450cafba4a942 Mon Sep 17 00:00:00 2001 From: AntiCat Date: Tue, 14 Aug 2018 09:24:02 +0200 Subject: [PATCH 126/127] fix: 32bit tick timer based on TC0 and TC1 (#653) TC1 counts the number of TC0 overflows (carry bits). In random conditions TC1 would return or stay at zero, instead of counting up. This due to the behavior of the reset signal. SAM7S Series Datasheet, 33.5.6 Trigger: Regardless of the trigger used, it will be taken into account at the following active edge of the selected clock. This means that the counter value can be read differently from zero just after a trigger, especially when a low frequency signal is selected as the clock. The new code first prepares TC1 and asserts TC1 trigger and then prepares TC0 and asserts TC0 trigger. The TC0 start-up will reset TC1. --- armsrc/util.c | 69 ++++++++++++++++++++++++++++++++------------------- armsrc/util.h | 3 ++- 2 files changed, 46 insertions(+), 26 deletions(-) diff --git a/armsrc/util.c b/armsrc/util.c index 59dfe07b..8a8d6657 100644 --- a/armsrc/util.c +++ b/armsrc/util.c @@ -448,31 +448,52 @@ uint32_t RAMFUNC GetCountSspClk(){ // ------------------------------------------------------------------------- -// Timer for bitbanging, or LF stuff when you need a very precis timer +// Timer for bitbanging, or LF stuff when you need a very precis timer // 1us = 1.5ticks // ------------------------------------------------------------------------- void StartTicks(void){ - //initialization of the timer - // tc1 is higher 0xFFFF0000 - // tc0 is lower 0x0000FFFF + // initialization of the timer AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1); AT91C_BASE_TCB->TCB_BMR = AT91C_TCB_TC0XC0S_NONE | AT91C_TCB_TC1XC1S_TIOA0 | AT91C_TCB_TC2XC2S_NONE; - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; - AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV3_CLOCK | // MCK(48MHz) / 32 - AT91C_TC_WAVE | AT91C_TC_WAVESEL_UP_AUTO | AT91C_TC_ACPA_CLEAR | - AT91C_TC_ACPC_SET | AT91C_TC_ASWTRG_SET; - AT91C_BASE_TC0->TC_RA = 1; - AT91C_BASE_TC0->TC_RC = 0; - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; // timer disable - AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_XC1; // from TC0 - - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - AT91C_BASE_TCB->TCB_BCR = 1; - - // wait until timer becomes zero. - while (AT91C_BASE_TC1->TC_CV > 0); + // disable TC0 and TC1 for re-configuration + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; + + // first configure TC1 (higher, 0xFFFF0000) 16 bit counter + AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_XC1; // just connect to TIOA0 from TC0 + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; // re-enable timer and wait for TC0 + + // second configure TC0 (lower, 0x0000FFFF) 16 bit counter + AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV3_CLOCK | // MCK(48MHz) / 32 + AT91C_TC_WAVE | AT91C_TC_WAVESEL_UP_AUTO | + AT91C_TC_ACPA_CLEAR | // RA comperator clears TIOA (carry bit) + AT91C_TC_ACPC_SET | // RC comperator sets TIOA (carry bit) + AT91C_TC_ASWTRG_SET; // SWTriger sets TIOA (carry bit) + AT91C_BASE_TC0->TC_RC = 0; // set TIOA (carry bit) on overflow, return to zero + AT91C_BASE_TC0->TC_RA = 1; // clear carry bit on next clock cycle + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; // reset and re-enable timer + + // synchronized startup procedure + while (AT91C_BASE_TC0->TC_CV > 0); // wait until TC0 returned to zero + while (AT91C_BASE_TC0->TC_CV < 2); // and has started (TC_CV > TC_RA, now TC1 is cleared) + + // return to zero + AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG; + AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; + while (AT91C_BASE_TC0->TC_CV > 0); +} + + +uint32_t GetTicks(void) { + uint32_t hi, lo; + + do { + hi = AT91C_BASE_TC1->TC_CV; + lo = AT91C_BASE_TC0->TC_CV; + } while(hi != AT91C_BASE_TC1->TC_CV); + + return (hi << 16) | lo; } @@ -480,30 +501,28 @@ void StartTicks(void){ // if called with a high number, this will trigger the WDT... void WaitTicks(uint32_t ticks){ if ( ticks == 0 ) return; - ticks += GET_TICKS; - while (GET_TICKS < ticks); + ticks += GetTicks(); + while (GetTicks() < ticks); } // Wait / Spindelay in us (microseconds) // 1us = 1.5ticks. void WaitUS(uint16_t us){ - if ( us == 0 ) return; WaitTicks( (uint32_t)us * 3 / 2 ) ; } void WaitMS(uint16_t ms){ - if (ms == 0) return; WaitTicks( (uint32_t)ms * 1500 ); } // Starts Clock and waits until its reset void ResetTicks(void){ - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - while (AT91C_BASE_TC1->TC_CV > 0); + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + while (AT91C_BASE_TC0->TC_CV > 0); } diff --git a/armsrc/util.h b/armsrc/util.h index 0148e1dd..58dcdd52 100644 --- a/armsrc/util.h +++ b/armsrc/util.h @@ -44,7 +44,7 @@ void FormatVersionInformation(char *dst, int len, const char *prefix, void *vers //iceman's ticks.h #ifndef GET_TICKS -# define GET_TICKS (uint32_t)((AT91C_BASE_TC1->TC_CV << 16) | AT91C_BASE_TC0->TC_CV) +# define GET_TICKS GetTicks() #endif void SpinDelay(int ms); @@ -62,6 +62,7 @@ void ResetSspClk(void); uint32_t RAMFUNC GetCountSspClk(); extern void StartTicks(void); +extern uint32_t GetTicks(void); extern void WaitTicks(uint32_t ticks); extern void WaitUS(uint16_t us); extern void WaitMS(uint16_t ms); From c80eb8ba79b86a157f9769203b7ddc26960d2dc4 Mon Sep 17 00:00:00 2001 From: Oleg Moiseenko Date: Tue, 14 Aug 2018 11:15:51 +0300 Subject: [PATCH 127/127] some cards need to have Le=0x00, some need to not have... (#651) --- client/emv/emvcore.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/client/emv/emvcore.c b/client/emv/emvcore.c index 08c6e3db..36f6f8eb 100644 --- a/client/emv/emvcore.c +++ b/client/emv/emvcore.c @@ -221,7 +221,7 @@ struct tlvdb *GetdCVVRawFromTrack2(const struct tlv *track2) { return tlvdb_fixed(0x02, dCVVlen, dCVV); } -int EMVExchangeEx(bool ActivateField, bool LeaveFieldON, sAPDU apdu, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) { +int EMVExchangeEx(bool ActivateField, bool LeaveFieldON, sAPDU apdu, bool IncludeLe, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) { uint8_t data[APDU_RES_LEN] = {0}; *ResultLen = 0; @@ -237,10 +237,10 @@ int EMVExchangeEx(bool ActivateField, bool LeaveFieldON, sAPDU apdu, uint8_t *Re memcpy(&data[5], apdu.data, apdu.Lc); if (APDULogging) - PrintAndLog(">>>> %s", sprint_hex(data, 6 + apdu.Lc)); + PrintAndLog(">>>> %s", sprint_hex(data, (IncludeLe?6:5) + apdu.Lc)); - // 6 byes + data = INS + CLA + P1 + P2 + Lc + + Le - int res = ExchangeAPDU14a(data, 6 + apdu.Lc, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen); + // 6 byes + data = INS + CLA + P1 + P2 + Lc + + Le(?IncludeLe) + int res = ExchangeAPDU14a(data, (IncludeLe?6:5) + apdu.Lc, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen); if (res) { return res; @@ -270,11 +270,11 @@ int EMVExchangeEx(bool ActivateField, bool LeaveFieldON, sAPDU apdu, uint8_t *Re } int EMVExchange(bool LeaveFieldON, sAPDU apdu, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) { - return EMVExchangeEx(false, LeaveFieldON, apdu, Result, MaxResultLen, ResultLen, sw, tlv); + return EMVExchangeEx(false, LeaveFieldON, apdu, true, Result, MaxResultLen, ResultLen, sw, tlv); } int EMVSelect(bool ActivateField, bool LeaveFieldON, uint8_t *AID, size_t AIDLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) { - return EMVExchangeEx(ActivateField, LeaveFieldON, (sAPDU){0x00, 0xa4, 0x04, 0x00, AIDLen, AID}, Result, MaxResultLen, ResultLen, sw, tlv); + return EMVExchangeEx(ActivateField, LeaveFieldON, (sAPDU){0x00, 0xa4, 0x04, 0x00, AIDLen, AID}, true, Result, MaxResultLen, ResultLen, sw, tlv); } int EMVSelectPSE(bool ActivateField, bool LeaveFieldON, uint8_t PSENum, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { @@ -453,7 +453,12 @@ int EMVGPO(bool LeaveFieldON, uint8_t *PDOL, size_t PDOLLen, uint8_t *Result, si } int EMVReadRecord(bool LeaveFieldON, uint8_t SFI, uint8_t SFIrec, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) { - return EMVExchange(LeaveFieldON, (sAPDU){0x00, 0xb2, SFIrec, (SFI << 3) | 0x04, 0, NULL}, Result, MaxResultLen, ResultLen, sw, tlv); + int res = EMVExchange(LeaveFieldON, (sAPDU){0x00, 0xb2, SFIrec, (SFI << 3) | 0x04, 0, NULL}, Result, MaxResultLen, ResultLen, sw, tlv); + if (*sw == 0x6700) { + PrintAndLog(">>> trying to reissue command withouth Le..."); + res = EMVExchangeEx(false, LeaveFieldON, (sAPDU){0x00, 0xb2, SFIrec, (SFI << 3) | 0x04, 0, NULL}, false, Result, MaxResultLen, ResultLen, sw, tlv); + } + return res; } int EMVAC(bool LeaveFieldON, uint8_t RefControl, uint8_t *CDOL, size_t CDOLLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) { @@ -461,7 +466,12 @@ int EMVAC(bool LeaveFieldON, uint8_t RefControl, uint8_t *CDOL, size_t CDOLLen, } int EMVGenerateChallenge(bool LeaveFieldON, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) { - return EMVExchange(LeaveFieldON, (sAPDU){0x00, 0x84, 0x00, 0x00, 0x00, NULL}, Result, MaxResultLen, ResultLen, sw, tlv); + int res = EMVExchange(LeaveFieldON, (sAPDU){0x00, 0x84, 0x00, 0x00, 0x00, NULL}, Result, MaxResultLen, ResultLen, sw, tlv); + if (*sw == 0x6700) { + PrintAndLog(">>> trying to reissue command withouth Le..."); + res = EMVExchangeEx(false, LeaveFieldON, (sAPDU){0x00, 0x84, 0x00, 0x00, 0x00, NULL}, false, Result, MaxResultLen, ResultLen, sw, tlv); + } + return res; } int EMVInternalAuthenticate(bool LeaveFieldON, uint8_t *DDOL, size_t DDOLLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) {