diff --git a/armsrc/Makefile b/armsrc/Makefile index 413570565..5505119b7 100644 --- a/armsrc/Makefile +++ b/armsrc/Makefile @@ -35,6 +35,7 @@ APP_CFLAGS = $(PLATFORM_DEFS) \ -ffunction-sections -fdata-sections SRC_LF = lfops.c lfsampling.c pcf7931.c lfdemod.c lfadc.c +SRC_HF = hfops.c SRC_ISO15693 = iso15693.c iso15693tools.c SRC_ISO14443a = iso14443a.c mifareutil.c mifarecmd.c epa.c mifaresim.c #UNUSED: mifaresniff.c @@ -132,6 +133,7 @@ THUMBSRC = start.c \ $(SRC_EM4x50) \ $(SRC_EM4x70) \ $(SRC_SPIFFS) \ + $(SRC_HF) \ $(SRC_ISO14443a) \ $(SRC_ISO14443b) \ $(SRC_CRAPTO1) \ diff --git a/armsrc/appmain.c b/armsrc/appmain.c index afcdc04ac..5254368ae 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -33,6 +33,7 @@ #include "legicrf.h" #include "BigBuf.h" #include "iclass_cmd.h" +#include "hfops.h" #include "iso14443a.h" #include "iso14443b.h" #include "iso15693.h" @@ -1384,6 +1385,15 @@ static void PacketReceived(PacketCommandNG *packet) { } #endif +#ifdef WITH_GENERAL_HF + case CMD_HF_ACQ_RAW_ADC: { + uint32_t samplesCount = 0; + memcpy(&samplesCount, packet->data.asBytes, 4); + HfReadADC(samplesCount, true); + break; + } +#endif + #ifdef WITH_ISO14443a case CMD_HF_ISO14443A_PRINT_CONFIG: { printHf14aConfig(); diff --git a/armsrc/hfops.c b/armsrc/hfops.c new file mode 100644 index 000000000..3bf060c56 --- /dev/null +++ b/armsrc/hfops.c @@ -0,0 +1,93 @@ +//----------------------------------------------------------------------------- +// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// See LICENSE.txt for the text of the license. +//----------------------------------------------------------------------------- +// HF general operations +//----------------------------------------------------------------------------- + +#include "hfops.h" + +#include +#include "proxmark3_arm.h" +#include "cmd.h" +#include "BigBuf.h" +#include "fpgaloader.h" +#include "ticks.h" +#include "dbprint.h" +#include "util.h" +#include "commonutil.h" +#include "lfsampling.h" + +int HfReadADC(uint32_t samplesCount, bool ledcontrol) { + if (ledcontrol) LEDsoff(); + + BigBuf_Clear_ext(false); + // connect Demodulated Signal to ADC: + SetAdcMuxFor(GPIO_MUXSEL_HIPKD); + + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + // And put the FPGA in the appropriate mode + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_SUBCARRIER_212_KHZ | FPGA_HF_READER_MODE_RECEIVE_AMPLITUDE); + + // Setup + FpgaSetupSsc(FPGA_MAJOR_MODE_HF_READER); + + if (ledcontrol) LED_A_ON(); + + uint32_t sbs = samplesCount; + initSampleBuffer(&sbs); + + uint32_t wdtcntr = 0; + for (;;) { + if (BUTTON_PRESS()) { + break; + } + + if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { + volatile uint16_t sample = AT91C_BASE_SSC->SSC_RHR; + + // FPGA side: + // corr_i_out <= {2'b00, corr_amplitude[13:8]}; + // corr_q_out <= corr_amplitude[7:0]; + if (sample > 0x1fff) + sample = 0xff; + else + sample = sample >> 5; + logSample(sample & 0xff, 1, 8, false); + if (getSampleCounter() >= samplesCount) + break; + + if (wdtcntr++ > 512) { + WDT_HIT(); + wdtcntr = 0; + } + } else { + continue; + } + } + + FpgaDisableTracing(); + + FpgaSetupSsc(FPGA_MAJOR_MODE_OFF); + // Turn the field off + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + + uint32_t scnt = getSampleCounter(); + reply_ng(CMD_HF_ACQ_RAW_ADC, PM3_SUCCESS, (uint8_t *)&scnt, 4); + if (ledcontrol) LEDsoff(); + + return 0; +} + + diff --git a/armsrc/hfops.h b/armsrc/hfops.h new file mode 100644 index 000000000..489c99bc6 --- /dev/null +++ b/armsrc/hfops.h @@ -0,0 +1,26 @@ +//----------------------------------------------------------------------------- +// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// See LICENSE.txt for the text of the license. +//----------------------------------------------------------------------------- +// HF general operations +//----------------------------------------------------------------------------- + +#ifndef HFOPS_H +#define HFOPS_H + +#include "common.h" + +int HfReadADC(uint32_t samplesCount, bool ledcontrol); + +#endif \ No newline at end of file diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index b86335c66..750c83c6b 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -294,6 +294,7 @@ set (TARGET_SOURCES ${PM3_ROOT}/client/src/cmdhfst25ta.c ${PM3_ROOT}/client/src/cmdhfthinfilm.c ${PM3_ROOT}/client/src/cmdhftopaz.c + ${PM3_ROOT}/client/src/cmdhftexkom.c ${PM3_ROOT}/client/src/cmdhfwaveshare.c ${PM3_ROOT}/client/src/cmdhw.c ${PM3_ROOT}/client/src/cmdlf.c diff --git a/client/Makefile b/client/Makefile index e2dd1a224..d4893b341 100644 --- a/client/Makefile +++ b/client/Makefile @@ -576,6 +576,7 @@ SRCS = mifare/aiddesfire.c \ cmdhfst25ta.c \ cmdhfthinfilm.c \ cmdhftopaz.c \ + cmdhftexkom.c \ cmdhfwaveshare.c \ cmdhw.c \ cmdlf.c \ diff --git a/client/src/cmdhf.c b/client/src/cmdhf.c index ccb697966..9ed214eac 100644 --- a/client/src/cmdhf.c +++ b/client/src/cmdhf.c @@ -47,6 +47,7 @@ #include "cmdhfseos.h" // SEOS #include "cmdhfst25ta.h" // ST25TA #include "cmdhfwaveshare.h" // Waveshare +#include "cmdhftexkom.h" // Texkom #include "cmdtrace.h" // trace list #include "ui.h" #include "proxgui.h" @@ -435,6 +436,7 @@ static command_t CommandTable[] = { {"st25ta", CmdHFST25TA, AlwaysAvailable, "{ ST25TA RFIDs... }"}, {"thinfilm", CmdHFThinfilm, AlwaysAvailable, "{ Thinfilm RFIDs... }"}, {"topaz", CmdHFTopaz, AlwaysAvailable, "{ TOPAZ (NFC Type 1) RFIDs... }"}, + {"texkom", CmdHFTexkom, AlwaysAvailable, "{ Texkom RFIDs... }"}, {"waveshare", CmdHFWaveshare, AlwaysAvailable, "{ Waveshare NFC ePaper... }"}, {"-----------", CmdHelp, AlwaysAvailable, "--------------------- " _CYAN_("General") " ---------------------"}, {"help", CmdHelp, AlwaysAvailable, "This help"}, diff --git a/client/src/cmdhftexkom.c b/client/src/cmdhftexkom.c new file mode 100644 index 000000000..d810c2f16 --- /dev/null +++ b/client/src/cmdhftexkom.c @@ -0,0 +1,569 @@ +//----------------------------------------------------------------------------- +// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// See LICENSE.txt for the text of the license. +//----------------------------------------------------------------------------- +// High frequency proximity cards from TEXCOM commands +//----------------------------------------------------------------------------- + +#include "cmdhftexkom.h" + +#include +#include +#include +#include "cliparser.h" +#include "cmdparser.h" // command_t +#include "comms.h" +#include "ui.h" +#include "cmdhf14a.h" +#include "cmddata.h" +#include "graph.h" + +#define TEXKOM_NOISE_THRESHOLD (10) + +inline uint32_t GetGraphBuffer(uint32_t indx) { + if (g_GraphBuffer[indx] < -128) + return 0; + else + return g_GraphBuffer[indx] + 128; +} + +static uint32_t TexkomAVGField(void) { + if (g_GraphTraceLen == 0) + return 0; + + uint64_t vsum = 0; + for (uint32_t i = 0; i < g_GraphTraceLen; i++) + vsum += GetGraphBuffer(i); + + return vsum / g_GraphTraceLen; +} + +static uint32_t TexkomSearchStart(uint32_t indx, uint32_t threshold) { + // one bit length = 27, minimal noise = 60 + uint32_t lownoisectr = 0; + for (uint32_t i = indx; i < g_GraphTraceLen; i++) { + if (lownoisectr > 60) { + if (GetGraphBuffer(i) > threshold) + return i; + } else { + if (GetGraphBuffer(i) > threshold) + lownoisectr = 0; + else + lownoisectr++; + } + } + + return 0; +} + +static uint32_t TexkomSearchLength(uint32_t indx, uint32_t threshold) { + // one bit length = 27, minimal noise = 60 + uint32_t lownoisectr = 0; + uint32_t datalen = 0; + for (uint32_t i = indx; i < g_GraphTraceLen; i++) { + if (lownoisectr > 60) { + break; + } else { + if (GetGraphBuffer(i) > threshold) { + lownoisectr = 0; + datalen = i - indx + 27; + } else { + lownoisectr++; + } + } + } + + return datalen; +} + +static uint32_t TexkomSearchMax(uint32_t indx, uint32_t len) { + uint32_t res = 0; + + for (uint32_t i = 0; i < len; i++) { + if (i + indx > g_GraphTraceLen) + break; + + if (GetGraphBuffer(indx + i) > res) + res = GetGraphBuffer(indx + i); + } + + return res; +} + +static bool TexkomCorrelate(uint32_t indx, uint32_t threshold) { + if (indx < 2 || indx + 2 > g_GraphTraceLen) + return false; + + uint32_t g1 = GetGraphBuffer(indx - 2); + uint32_t g2 = GetGraphBuffer(indx - 1); + uint32_t g3 = GetGraphBuffer(indx); + uint32_t g4 = GetGraphBuffer(indx + 1); + uint32_t g5 = GetGraphBuffer(indx + 2); + + return ( + (g3 > threshold) && + (g3 >= g2) && (g3 >= g1) && (g3 > g4) && (g3 > g5) + ); +} + +static bool TexkomCalculateMaxMin(uint32_t *data, uint32_t len, uint32_t *dmax, uint32_t *dmin) { + *dmax = 0; + *dmin = 0xffffffff; + for (size_t i = 0; i < len; i++) { + if (data[i] > *dmax) + *dmax = data[i]; + if (data[i] < *dmin) + *dmin = data[i]; + } + + return (*dmax != 0) && (*dmin != 0xffffffff) && (*dmax > *dmin); +} + +static bool TexkomCalculateBitLengths(uint32_t *data, uint32_t len, uint32_t *hi, uint32_t *low, uint32_t *lmax, uint32_t *lmin) { + *hi = 0; + *low = 0; + + uint32_t dmax = 0; + uint32_t dmin = 0xffffffff; + if (!TexkomCalculateMaxMin(data, len, &dmax, &dmin)) + return false; + + uint32_t dmiddle = (dmax + dmin) / 2; + uint32_t sumhi = 0; + uint32_t lenhi = 0; + uint32_t sumlow = 0; + uint32_t lenlow = 0; + for (size_t i = 0; i < len; i++) { + if (data[i] > dmiddle) { + sumhi += data[i]; + lenhi++; + } else { + sumlow += data[i]; + lenlow++; + } + } + + *hi = sumhi / lenhi; + *low = sumlow / lenlow; + + if (lmax != NULL) + *lmax = dmax; + if (lmin != NULL) + *lmin = dmin; + + return (*hi != 0) && (*low != 0) && (*hi > *low); +} + +inline bool TexcomCalculateBit(uint32_t data, uint32_t bitlen, uint32_t threshold) { + return + (data < (bitlen + threshold)) && + (data > (bitlen - threshold)); +} + +// code from https://github.com/li0ard/crclib/blob/main/index.js +static uint8_t TexcomTK13CRC(uint8_t *data) { + uint8_t crc = 0; + uint8_t indx = 0; + while (indx < 4) { + crc = crc ^ data[indx++]; + + for (uint8_t i = 0; i < 8; i++) + if (crc & 0x80) { + crc = 0x31 ^ (crc << 1); + } else + crc <<= 1; + }; + + return crc; +} + +static unsigned char dallas_crc8(const unsigned char *data, const unsigned int size) { + unsigned char crc = 0; + for (unsigned int i = 0; i < size; ++i) { + unsigned char inbyte = data[i]; + for (unsigned char j = 0; j < 8; ++j) { + unsigned char mix = (crc ^ inbyte) & 0x01; + crc >>= 1; + if (mix) crc ^= 0x8C; + inbyte >>= 1; + } + } + return crc; +} + +// code from https://github.com/li0ard/crclib/blob/main/index.js +static uint8_t TexcomTK17CRC(uint8_t *data) { + uint8_t ddata[8] = {0x00, 0x00, 0x00, data[0], data[1], data[2], data[3], 0x00}; + + return dallas_crc8(ddata, 7); +} + +static bool TexcomTK13Decode(uint32_t *implengths, uint32_t implengthslen, char *bitstring, char *cbitstring, bool verbose) { + bitstring[0] = 0; + cbitstring[0] = 0; + + uint32_t hilength = 0; + uint32_t lowlength = 0; + if (!TexkomCalculateBitLengths(implengths, implengthslen, &hilength, &lowlength, NULL, NULL)) + return false; + + uint32_t threshold = (hilength - lowlength) / 3 + 1; + //PrintAndLogEx(WARNING, "--- hi: %d, low: %d, threshold: %d", hilength, lowlength, threshold); + + bool biterror = false; + for (uint32_t i = 0; i < implengthslen; i++) { + if (TexcomCalculateBit(implengths[i], hilength, threshold)) + strcat(bitstring, "1"); + else if (TexcomCalculateBit(implengths[i], lowlength, threshold)) + strcat(bitstring, "0"); + else { + //PrintAndLogEx(INFO, "ERROR string [%zu]: %s, bit: %d, blen: %d", strlen(bitstring), bitstring, i, implengths[i]); + + biterror = true; + break; + } + } + + if (biterror || strlen(bitstring) == 0) + return false; + + if (verbose) + PrintAndLogEx(INFO, "raw bit string [%zu]: %s", strlen(bitstring), bitstring); + + // add trailing impulse (some tags just ignore it) + if (strlen(bitstring) % 2 != 0) { + if (bitstring[strlen(bitstring) - 1] == '1') + strcat(bitstring, "0"); + else + strcat(bitstring, "1"); + } + + for (uint32_t i = 0; i < strlen(bitstring); i = i + 2) { + if (bitstring[i] == bitstring[i + 1]) { + cbitstring[0] = 0; + if (verbose) + PrintAndLogEx(WARNING, "Raw bit string have error at offset %d.", i); + break; + } + if (bitstring[i] == '1') + strcat(cbitstring, "1"); + else + strcat(cbitstring, "0"); + } + + if (strlen(cbitstring) == 0) + return false; + + if (verbose) + PrintAndLogEx(INFO, "bit string [%zu]: %s", strlen(cbitstring), cbitstring); + + return ((strlen(cbitstring) == 64) && (strncmp(cbitstring, "1111111111111111", 16) == 0)); +} + +inline int TexcomTK17Get2Bits(uint32_t len1, uint32_t len2) { + uint32_t xlen = (len2 * 100) / (len1 + len2); + if (xlen < 10 || xlen > 90) + return TK17WrongBit; + if (xlen < 30) + return TK17Bit00; + if (xlen < 50) + return TK17Bit10; + if (xlen < 70) + return TK17Bit01; + return TK17Bit11; +} + +static bool TexcomTK17Decode(uint32_t *implengths, uint32_t implengthslen, char *bitstring, char *cbitstring, bool verbose) { + bitstring[0] = 0; + cbitstring[0] = 0; + + for (uint32_t i = 0; i < implengthslen; i = i + 2) { + int dbit = TexcomTK17Get2Bits(implengths[i], implengths[i + 1]); + if (dbit == TK17WrongBit) + return false; + + switch (dbit) { + case TK17Bit00: + strcat(bitstring, "00"); + break; + case TK17Bit01: + strcat(bitstring, "01"); + break; + case TK17Bit10: + strcat(bitstring, "10"); + break; + case TK17Bit11: + strcat(bitstring, "11"); + break; + default: + return false; + } + } + + if (verbose) + PrintAndLogEx(INFO, "TK17 raw bit string [%zu]: %s", strlen(bitstring), bitstring); + + for (uint32_t i = 0; i < 8; i++) { + memcpy(&cbitstring[i * 8 + 0], &bitstring[i * 8 + 6], 2); + memcpy(&cbitstring[i * 8 + 2], &bitstring[i * 8 + 4], 2); + memcpy(&cbitstring[i * 8 + 4], &bitstring[i * 8 + 2], 2); + memcpy(&cbitstring[i * 8 + 6], &bitstring[i * 8 + 0], 2); + } + + if (verbose) + PrintAndLogEx(INFO, "TK17 bit string [%zu]: %s", strlen(cbitstring), cbitstring); + + return (strlen(bitstring) == 64) && (strncmp(cbitstring, "1111111111111111", 16) == 0); +} + +static bool TexcomGeneralDecode(uint32_t *implengths, uint32_t implengthslen, char *bitstring, bool verbose) { + uint32_t hilength = 0; + uint32_t lowlength = 0; + if (!TexkomCalculateBitLengths(implengths, implengthslen, &hilength, &lowlength, NULL, NULL)) + return false; + + uint32_t threshold = (hilength - lowlength) / 3 + 1; + + bitstring[0] = 0; + bool biterror = false; + for (uint32_t i = 0; i < implengthslen; i++) { + if (TexcomCalculateBit(implengths[i], hilength, threshold)) + strcat(bitstring, "1"); + else if (TexcomCalculateBit(implengths[i], lowlength, threshold)) + strcat(bitstring, "0"); + else { + if (verbose) { + PrintAndLogEx(INFO, "ERROR string [%zu]: %s, bit: %d, blen: %d", strlen(bitstring), bitstring, i, implengths[i]); + printf("Length array: \r\n"); + for (uint32_t j = 0; j < implengthslen; j++) + printf("%d,", implengths[j]); + printf("\r\n"); + } + + biterror = true; + break; + } + } + if (verbose) + PrintAndLogEx(INFO, "General raw bit string [%zu]: %s", strlen(bitstring), bitstring); + + return (!biterror && strlen(bitstring) > 0); +} + +static void TexcomReverseCode(const uint8_t *code, int length, uint8_t *reverse_code) { + for (int i = 0; i < length; i++) { + reverse_code[i] = code[(length - 1) - i]; + } +}; + +static int CmdHFTexkomReader(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf texkom reader", + "Read a texkom tag", + "hf texkom reader"); + + void *argtable[] = { + arg_param_begin, + arg_lit0("v", "verbose", "Verbose scan and output"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + + bool verbose = arg_get_lit(ctx, 1); + + CLIParserFree(ctx); + + uint32_t samplesCount = 30000; + clearCommandBuffer(); + SendCommandNG(CMD_HF_ACQ_RAW_ADC, (uint8_t *)&samplesCount, sizeof(uint32_t)); + + PacketResponseNG resp; + if (!WaitForResponseTimeout(CMD_HF_ACQ_RAW_ADC, &resp, 2500)) { + PrintAndLogEx(WARNING, "(hf texkom reader) command execution time out"); + return PM3_ETIMEOUT; + } + + uint32_t size = (resp.data.asDwords[0]); + if (size > 0) { + if (getSamples(samplesCount, false) != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Get samples error"); + return PM3_EFAILED; + }; + } + + char bitstring[256] = {0}; + char cbitstring[128] = {0}; + char genbitstring[256] = {0}; + int codefound = TexkomModError; + uint32_t sindx = 0; + while (sindx < samplesCount - 5) { + sindx = TexkomSearchStart(sindx, TEXKOM_NOISE_THRESHOLD); + if (sindx == 0 || sindx > samplesCount - 5) { + if (TexkomAVGField() > 30) + PrintAndLogEx(WARNING, "Too noisy environment. Try to move the tag from the antenna a bit."); + break; + } + + uint32_t slen = TexkomSearchLength(sindx, TEXKOM_NOISE_THRESHOLD); + if (slen == 0) + continue; + + uint32_t maxlvl = TexkomSearchMax(sindx, 1760); + if (maxlvl < TEXKOM_NOISE_THRESHOLD) { + sindx += 1700; + continue; + } + + uint32_t noiselvl = maxlvl / 5; + if (noiselvl < TEXKOM_NOISE_THRESHOLD) + noiselvl = TEXKOM_NOISE_THRESHOLD; + + //PrintAndLogEx(WARNING, "--- indx: %d, len: %d, max: %d, noise: %d", sindx, slen, maxlvl, noiselvl); + + uint32_t implengths[256] = {}; + uint32_t implengthslen = 0; + uint32_t impulseindx = 0; + uint32_t impulsecnt = 0; + for (uint32_t i = 0; i < slen; i++) { + if (TexkomCorrelate(sindx + i, noiselvl)) { + impulsecnt++; + + if (impulseindx != 0) { + if (implengthslen < 256) + implengths[implengthslen++] = sindx + i - impulseindx; + } + impulseindx = sindx + i; + } + } + //PrintAndLogEx(WARNING, "--- impulses: %d, lenarray: %d, [%d,%d]", impulsecnt, implengthslen, implengths[0], implengths[1]); + + // check if it TK-17 modulation + // 65 impulses and 64 intervals (1 interval = 2 bits, interval length encoding) that represents 128 bit of card code + if (impulsecnt == 65) { + if (TexcomTK17Decode(implengths, implengthslen, bitstring, cbitstring, verbose)) { + codefound = TexkomModTK17; + break; + } + } + + // check if it TK-13 modulation + // it have 127 or 128 impulses and 128 double-intervals that represents 128 bit of card code + if (impulsecnt == 127 || impulsecnt == 128) { + if (TexcomTK13Decode(implengths, implengthslen, bitstring, cbitstring, verbose)) { + codefound = TexkomModTK13; + break; + } + } + + // general decoding. it thought that there is 2 types of intervals "long" (1) and "short" (0) + // and tries to decode sequence. shows only raw data + if (verbose) + TexcomGeneralDecode(implengths, implengthslen, genbitstring, verbose); + } + + if (codefound != TexkomModError) { + uint8_t tcode[8] = {0}; + for (uint32_t i = 0; i < strlen(cbitstring); i++) { + tcode[i / 8] = (tcode[i / 8] << 1) | ((cbitstring[i] == '1') ? 1 : 0); + } + + uint8_t rtcode[8] = {0}; + TexcomReverseCode(tcode, 8, rtcode); + + if (verbose) { + PrintAndLogEx(INFO, "Hex code: %s", sprint_hex(tcode, 8)); + PrintAndLogEx(INFO, "Hex code reversed: %s", sprint_hex(rtcode, 8)); + } + + if (tcode[0] == 0xff && tcode[1] == 0xff) { + // decoding code + + if (!verbose) { + PrintAndLogEx(INFO, "Texkom: %s", sprint_hex(tcode, 8)); + PrintAndLogEx(INFO, "Texkom duplicator: %s", sprint_hex(rtcode, 8)); + } + + if (codefound == TexkomModTK13) + PrintAndLogEx(INFO, "modulation: TK13"); + else if (codefound == TexkomModTK17) + PrintAndLogEx(INFO, "modulation: TK17"); + else + PrintAndLogEx(INFO, "modulation: unknown"); + + if (tcode[2] == 0x63) { + // TK13 + if (codefound != TexkomModTK13) + PrintAndLogEx(WARNING, " mod type: WRONG"); + PrintAndLogEx(INFO, "type : TK13"); + PrintAndLogEx(INFO, "uid : %s", sprint_hex(&tcode[3], 4)); + + if (TexcomTK13CRC(&tcode[3]) == tcode[7]) + PrintAndLogEx(INFO, "crc : OK"); + else + PrintAndLogEx(WARNING, "crc : WRONG"); + + } else if (tcode[2] == 0xca) { + // TK17 + if (codefound != TexkomModTK17) + PrintAndLogEx(WARNING, " mod type: WRONG"); + PrintAndLogEx(INFO, "type : TK17"); + PrintAndLogEx(INFO, "uid : %s", sprint_hex(&tcode[3], 4)); + + if (TexcomTK17CRC(&tcode[3]) == tcode[7]) + PrintAndLogEx(INFO, "crc : OK"); + else + PrintAndLogEx(WARNING, "crc : WRONG"); + + } else { + PrintAndLogEx(INFO, "type : unknown"); + PrintAndLogEx(INFO, "uid : %s (maybe)", sprint_hex(&tcode[3], 4)); + } + } else { + PrintAndLogEx(ERR, "Code have no preamble FFFF: %s", sprint_hex(tcode, 8)); + } + } else { + if (strlen(genbitstring) > 0) + PrintAndLogEx(INFO, "General decoding bitstring: %s", genbitstring); + if (strlen(bitstring) > 0) + PrintAndLogEx(INFO, "last raw bit string [%zu]: %s", strlen(bitstring), bitstring); + if (strlen(cbitstring) > 0) + PrintAndLogEx(INFO, "last bit string [%zu]: %s", strlen(cbitstring), cbitstring); + + PrintAndLogEx(ERR, "Texkom card is not found"); + } + + return PM3_SUCCESS; +} + + +static int CmdHelp(const char *Cmd); + +static command_t CommandTable[] = { + {"help", CmdHelp, AlwaysAvailable, "This help"}, + {"reader", CmdHFTexkomReader, IfPm3Iso14443a, "Act like a Texkom reader"}, + //{"sim", CmdHFTexkomSim, IfPm3Iso14443a, "Simulate a Texkom tag"}, + //{"write", CmdHFTexkomWrite, IfPm3Iso14443a, "Write a Texkom tag"}, + {NULL, NULL, 0, NULL} +}; + +static int CmdHelp(const char *Cmd) { + (void)Cmd; // Cmd is not used so far + CmdsHelp(CommandTable); + return PM3_SUCCESS; +} + +int CmdHFTexkom(const char *Cmd) { + clearCommandBuffer(); + return CmdsParse(CommandTable, Cmd); +} diff --git a/client/src/cmdhftexkom.h b/client/src/cmdhftexkom.h new file mode 100644 index 000000000..a90d36033 --- /dev/null +++ b/client/src/cmdhftexkom.h @@ -0,0 +1,41 @@ +//----------------------------------------------------------------------------- +// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// See LICENSE.txt for the text of the license. +//----------------------------------------------------------------------------- +// High frequency proximity cards from TEXCOM commands +//----------------------------------------------------------------------------- + +#ifndef CMDHFTEXCOM_H__ +#define CMDHFTEXCOM_H__ + +#include "common.h" +#include "pm3_cmd.h" + +enum TK17Bits { + TK17WrongBit, + TK17Bit00, + TK17Bit01, + TK17Bit10, + TK17Bit11 +}; + +enum TexkomModulation { + TexkomModError, + TexkomModTK13, + TexkomModTK17 +}; + +int CmdHFTexkom(const char *Cmd); + +#endif diff --git a/common_arm/Makefile.hal b/common_arm/Makefile.hal index 62b99020d..68417eb60 100644 --- a/common_arm/Makefile.hal +++ b/common_arm/Makefile.hal @@ -143,6 +143,9 @@ ifneq ($(SKIP_ZX8211),1) endif # common HF support +ifneq ($(SKIP_HF),1) + PLATFORM_DEFS += -DWITH_GENERAL_HF +endif ifneq ($(SKIP_ISO15693),1) PLATFORM_DEFS += -DWITH_ISO15693 endif diff --git a/doc/commands.json b/doc/commands.json index 4f6703656..db5be2717 100644 --- a/doc/commands.json +++ b/doc/commands.json @@ -2661,7 +2661,7 @@ }, "hf help": { "command": "hf help", - "description": "-------- ----------------------- High Frequency ----------------------- 14a { ISO14443A RFIDs... } 14b { ISO14443B RFIDs... } 15 { ISO15693 RFIDs... } cipurse { Cipurse transport Cards... } epa { German Identification Card... } emrtd { Machine Readable Travel Document... } felica { ISO18092 / FeliCa RFIDs... } fido { FIDO and FIDO2 authenticators... } gallagher { Gallagher DESFire RFIDs... } ksx6924 { KS X 6924 (T-Money, Snapper+) RFIDs } jooki { Jooki RFIDs... } iclass { ICLASS RFIDs... } legic { LEGIC RFIDs... } lto { LTO Cartridge Memory RFIDs... } mf { MIFARE RFIDs... } mfp { MIFARE Plus RFIDs... } mfu { MIFARE Ultralight RFIDs... } mfdes { MIFARE Desfire RFIDs... } ntag424 { NXP NTAG 4242 DNA RFIDs... } seos { SEOS RFIDs... } st25ta { ST25TA RFIDs... } thinfilm { Thinfilm RFIDs... } topaz { TOPAZ (NFC Type 1) RFIDs... } waveshare { Waveshare NFC ePaper... } ----------- --------------------- General --------------------- help This help list List protocol data in trace buffer search Search for known HF tags", + "description": "-------- ----------------------- High Frequency ----------------------- 14a { ISO14443A RFIDs... } 14b { ISO14443B RFIDs... } 15 { ISO15693 RFIDs... } cipurse { Cipurse transport Cards... } epa { German Identification Card... } emrtd { Machine Readable Travel Document... } felica { ISO18092 / FeliCa RFIDs... } fido { FIDO and FIDO2 authenticators... } gallagher { Gallagher DESFire RFIDs... } ksx6924 { KS X 6924 (T-Money, Snapper+) RFIDs } jooki { Jooki RFIDs... } iclass { ICLASS RFIDs... } legic { LEGIC RFIDs... } lto { LTO Cartridge Memory RFIDs... } mf { MIFARE RFIDs... } mfp { MIFARE Plus RFIDs... } mfu { MIFARE Ultralight RFIDs... } mfdes { MIFARE Desfire RFIDs... } ntag424 { NXP NTAG 4242 DNA RFIDs... } seos { SEOS RFIDs... } st25ta { ST25TA RFIDs... } thinfilm { Thinfilm RFIDs... } topaz { TOPAZ (NFC Type 1) RFIDs... } texkom { Texkom RFIDs... } waveshare { Waveshare NFC ePaper... } ----------- --------------------- General --------------------- help This help list List protocol data in trace buffer search Search for known HF tags", "notes": [], "offline": true, "options": [], @@ -6302,6 +6302,27 @@ ], "usage": "hf st25ta sim [-h] -u " }, + "hf texkom help": { + "command": "hf texkom help", + "description": "help This help", + "notes": [], + "offline": true, + "options": [], + "usage": "" + }, + "hf texkom reader": { + "command": "hf texkom reader", + "description": "Read a texkom tag", + "notes": [ + "hf texkom reader" + ], + "offline": false, + "options": [ + "-h, --help This help", + "-v, --verbose Verbose scan and output" + ], + "usage": "hf texkom reader [-hv]" + }, "hf thinfilm help": { "command": "hf thinfilm help", "description": "help This help list List NFC Barcode / Thinfilm history - not correct", @@ -6528,8 +6549,8 @@ "command": "hw connect", "description": "Connects to a Proxmark3 device via specified serial port. Baudrate here is only for physical UART or UART-BT, NOT for USB-CDC or blue shark add-on", "notes": [ - "hw connect -p /dev/ttyACM0", - "hw connect -p /dev/ttyACM0 -b 115200" + "hw connect -p /dev/ttyacm0", + "hw connect -p /dev/ttyacm0 -b 115200" ], "offline": true, "options": [ @@ -10998,8 +11019,8 @@ } }, "metadata": { - "commands_extracted": 693, + "commands_extracted": 695, "extracted_by": "PM3Help2JSON v1.00", - "extracted_on": "2022-06-12T09:54:12" + "extracted_on": "2022-06-28T08:43:20" } } \ No newline at end of file diff --git a/doc/commands.md b/doc/commands.md index 6421ba761..b9689c5c2 100644 --- a/doc/commands.md +++ b/doc/commands.md @@ -646,6 +646,16 @@ Check column "offline" for their availability. |`hf topaz raw `|N |`Send raw hex data to tag` +### hf texkom + + { Texkom RFIDs... } + +|command |offline |description +|------- |------- |----------- +|`hf texkom help `|Y |`This help` +|`hf texkom reader `|N |`Act like a Texkom reader` + + ### hf waveshare { Waveshare NFC ePaper... } diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index c900eb952..e53132309 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -511,6 +511,7 @@ typedef struct { // For the 13.56 MHz tags #define CMD_HF_ISO15693_ACQ_RAW_ADC 0x0300 +#define CMD_HF_ACQ_RAW_ADC 0x0301 #define CMD_HF_SRI_READ 0x0303 #define CMD_HF_ISO14443B_COMMAND 0x0305 #define CMD_HF_ISO15693_READER 0x0310