mirror of
https://github.com/Proxmark/proxmark3.git
synced 2025-08-22 14:13:42 -07:00
Merge branch 'master' of github.com:merlokk/proxmark3 into argtable
# resolved: # client/Makefile # client/cmdhf14a.c # client/reveng/cli.c --- deleted
This commit is contained in:
commit
843373d47e
145 changed files with 3781 additions and 6271 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -18,8 +18,10 @@
|
||||||
!client/hardnested/tables/*.z
|
!client/hardnested/tables/*.z
|
||||||
usb_cmd.lua
|
usb_cmd.lua
|
||||||
version.c
|
version.c
|
||||||
|
armsrc/fpga_version_info.c
|
||||||
client/ui/ui_overlays.h
|
client/ui/ui_overlays.h
|
||||||
*.Td
|
*.Td
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
*.exe
|
*.exe
|
||||||
hardnested_stats.txt
|
hardnested_stats.txt
|
||||||
|
|
|
@ -6,6 +6,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
|
||||||
## [unreleased][unreleased]
|
## [unreleased][unreleased]
|
||||||
|
|
||||||
### Changed
|
### 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)
|
- Improved backdoor detection missbehaving magic s50/1k tag (Fl0-0)
|
||||||
- Deleted wipe functionality from `hf mf csetuid` (Merlok)
|
- Deleted wipe functionality from `hf mf csetuid` (Merlok)
|
||||||
- Changed `hf mf nested` logic (Merlok)
|
- Changed `hf mf nested` logic (Merlok)
|
||||||
|
@ -20,8 +21,10 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- Changed start sequence in Qt mode (fix: short commands hangs main Qt thread) (Merlok)
|
- 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
|
||||||
|
- 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 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 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)
|
- Added hf mf c* commands compatibity for 4k and gen1b backdoor (Fl0-0)
|
||||||
|
@ -47,6 +50,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` 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 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 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]
|
## [3.0.1][2017-06-08]
|
||||||
|
|
||||||
|
@ -62,7 +66,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 lf hitag write 24, the command writes a block to hitag2 tags in crypto mode (henjo)
|
||||||
|
|
||||||
### Added
|
### 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 experimental testmode write option for t55xx (danger) (marshmellow)
|
||||||
- Added t55xx p1detect to `lf search` chip detections (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)
|
- Added lf t55xx p1detect, detect page 1 of a t55xx tag based on E015 mfg code (marshmellow)
|
||||||
|
|
55
CI/.travis.yml
Normal file
55
CI/.travis.yml
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
# Travis-CI config
|
||||||
|
# variable REPOSITORY_EP must be filled with repository name. as sample: "merlokk/proxmark3"
|
||||||
|
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.3 # OS X 10.12
|
||||||
|
- os: osx
|
||||||
|
osx_image: xcode9 # OS X 10.12
|
||||||
|
- os: osx
|
||||||
|
osx_image: xcode9.2 # 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
|
||||||
|
echo $REPOSITORY_EP;
|
||||||
|
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;
|
||||||
|
if [[ "$REPOSITORY_EP" == "" ]]; then
|
||||||
|
brew tap proxmark/proxmark3;
|
||||||
|
else
|
||||||
|
brew tap "$REPOSITORY_EP" --env=std;
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
install:
|
||||||
|
if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
|
||||||
|
brew info proxmark3;
|
||||||
|
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
|
20
CI/readme.md
Normal file
20
CI/readme.md
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
# 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 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
|
||||||
|
|
||||||
|
- Just copy appveyor.yml file to root and configure it from http://appveyor.com
|
3
CI/travis_test_commands.scr
Normal file
3
CI/travis_test_commands.scr
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
hf mf hardnested t 1 000000000000
|
||||||
|
hf emv test
|
||||||
|
exit
|
|
@ -28,6 +28,7 @@ The Proxmark3 is available for purchase (assembled and tested) from the
|
||||||
following locations:
|
following locations:
|
||||||
|
|
||||||
* [RyscCorp](https://proxmark3.com/) (US)
|
* [RyscCorp](https://proxmark3.com/) (US)
|
||||||
|
* [Hackerwarehouse](https://hackerwarehouse.com/) (US)
|
||||||
* [Elechouse](http://www.elechouse.com/) (HK)
|
* [Elechouse](http://www.elechouse.com/) (HK)
|
||||||
* [Lab401](https://lab401.com/) (FR)
|
* [Lab401](https://lab401.com/) (FR)
|
||||||
* [RFxSecure](http://www.rfxsecure.com/) (SG)
|
* [RFxSecure](http://www.rfxsecure.com/) (SG)
|
||||||
|
|
|
@ -10,10 +10,16 @@ APP_INCLUDES = apps.h
|
||||||
|
|
||||||
#remove one of the following defines and comment out the relevant line
|
#remove one of the following defines and comment out the relevant line
|
||||||
#in the next section to remove that particular feature from compilation
|
#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 \
|
APP_CFLAGS = -DON_DEVICE \
|
||||||
-fno-strict-aliasing -ffunction-sections -fdata-sections
|
-fno-strict-aliasing -ffunction-sections -fdata-sections
|
||||||
#-DWITH_LCD
|
|
||||||
|
|
||||||
|
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_LCD = fonts.c LCD.c
|
||||||
SRC_LF = lfops.c hitag2.c hitagS.c lfsampling.c pcf7931.c lfdemod.c protocols.c
|
SRC_LF = lfops.c hitag2.c hitagS.c lfsampling.c pcf7931.c lfdemod.c protocols.c
|
||||||
SRC_ISO15693 = iso15693.c iso15693tools.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_ISO14443b = iso14443b.c
|
||||||
SRC_CRAPTO1 = crypto1.c des.c
|
SRC_CRAPTO1 = crypto1.c des.c
|
||||||
SRC_CRC = iso14443crc.c crc.c crc16.c crc32.c parity.c
|
SRC_CRC = iso14443crc.c crc.c crc16.c crc32.c parity.c
|
||||||
|
|
||||||
#the FPGA bitstream files. Note: order matters!
|
#the FPGA bitstream files. Note: order matters!
|
||||||
FPGA_BITSTREAMS = fpga_lf.bit fpga_hf.bit
|
FPGA_BITSTREAMS = fpga_lf.bit fpga_hf.bit
|
||||||
|
|
||||||
|
@ -59,6 +64,9 @@ ARMSRC = fpgaloader.c \
|
||||||
optimized_cipher.c \
|
optimized_cipher.c \
|
||||||
hfsnoop.c
|
hfsnoop.c
|
||||||
|
|
||||||
|
VERSIONSRC = version.c \
|
||||||
|
fpga_version_info.c
|
||||||
|
|
||||||
# Do not move this inclusion before the definition of {THUMB,ASM,ARM}SRC
|
# Do not move this inclusion before the definition of {THUMB,ASM,ARM}SRC
|
||||||
include ../common/Makefile.common
|
include ../common/Makefile.common
|
||||||
|
|
||||||
|
@ -69,6 +77,14 @@ all: $(OBJS)
|
||||||
|
|
||||||
.DELETE_ON_ERROR:
|
.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
|
$(OBJDIR)/fpga_all.o: $(OBJDIR)/fpga_all.bit.z
|
||||||
$(OBJCOPY) -O elf32-littlearm -I binary -B arm --prefix-sections=fpga_all_bit $^ $@
|
$(OBJCOPY) -O elf32-littlearm -I binary -B arm --prefix-sections=fpga_all_bit $^ $@
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include "cmd.h"
|
#include "cmd.h"
|
||||||
#include "proxmark3.h"
|
#include "proxmark3.h"
|
||||||
#include "apps.h"
|
#include "apps.h"
|
||||||
|
#include "fpga.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "printf.h"
|
#include "printf.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
|
@ -31,7 +32,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Craig Young - 14a stand-alone code
|
// Craig Young - 14a stand-alone code
|
||||||
#ifdef WITH_ISO14443a_StandAlone
|
#ifdef WITH_ISO14443a
|
||||||
#include "iso14443a.h"
|
#include "iso14443a.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -136,34 +137,27 @@ void Dbhexdump(int len, uint8_t *d, bool bAsci) {
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
static int ReadAdc(int ch)
|
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.
|
// 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
|
// 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 = 10MOhm * 12pF = 120us. Even after the maximum configurable sample&hold time of 40us the input capacitor will not be fully charged.
|
// 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:
|
// 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
|
// 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%)
|
// 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%)
|
||||||
//
|
|
||||||
// Note: with the "historic" values in the comments above, the error was 34% !!!
|
AT91C_BASE_ADC->ADC_CR = AT91C_ADC_SWRST;
|
||||||
|
AT91C_BASE_ADC->ADC_MR =
|
||||||
|
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_CHER = ADC_CHANNEL(ch);
|
||||||
|
|
||||||
AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START;
|
AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START;
|
||||||
|
|
||||||
while(!(AT91C_BASE_ADC->ADC_SR & ADC_END_OF_CONVERSION(ch)))
|
while(!(AT91C_BASE_ADC->ADC_SR & ADC_END_OF_CONVERSION(ch))) {};
|
||||||
;
|
|
||||||
d = AT91C_BASE_ADC->ADC_CDR[ch];
|
|
||||||
|
|
||||||
return d;
|
return AT91C_BASE_ADC->ADC_CDR[ch];
|
||||||
}
|
}
|
||||||
|
|
||||||
int AvgAdc(int ch) // was static - merlok
|
int AvgAdc(int ch) // was static - merlok
|
||||||
|
@ -193,6 +187,8 @@ void MeasureAntennaTuningLfOnly(int *vLf125, int *vLf134, int *peakf, int *peakv
|
||||||
|
|
||||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
|
||||||
|
SpinDelay(50);
|
||||||
|
|
||||||
for (i=255; i>=19; i--) {
|
for (i=255; i>=19; i--) {
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, i);
|
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, i);
|
||||||
|
@ -201,7 +197,7 @@ void MeasureAntennaTuningLfOnly(int *vLf125, int *vLf134, int *peakf, int *peakv
|
||||||
if (i==95) *vLf125 = adcval; // voltage at 125Khz
|
if (i==95) *vLf125 = adcval; // voltage at 125Khz
|
||||||
if (i==89) *vLf134 = adcval; // voltage at 134Khz
|
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) {
|
if(LF_Results[i] > peak) {
|
||||||
*peakv = adcval;
|
*peakv = adcval;
|
||||||
peak = LF_Results[i];
|
peak = LF_Results[i];
|
||||||
|
@ -249,7 +245,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);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
LED_B_OFF();
|
LED_B_OFF();
|
||||||
return;
|
return;
|
||||||
|
@ -291,6 +287,7 @@ void ReadMem(int addr)
|
||||||
extern struct version_information version_information;
|
extern struct version_information version_information;
|
||||||
/* bootrom version information is pointed to from _bootphase1_version_pointer */
|
/* 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__;
|
extern char *_bootphase1_version_pointer, _flash_start, _flash_end, _bootrom_start, _bootrom_end, __data_src_start__;
|
||||||
|
|
||||||
void SendVersion(void)
|
void SendVersion(void)
|
||||||
{
|
{
|
||||||
char temp[USB_CMD_DATA_SIZE]; /* Limited data payload in USB packets */
|
char temp[USB_CMD_DATA_SIZE]; /* Limited data payload in USB packets */
|
||||||
|
@ -311,10 +308,12 @@ void SendVersion(void)
|
||||||
FormatVersionInformation(temp, sizeof(temp), "os: ", &version_information);
|
FormatVersionInformation(temp, sizeof(temp), "os: ", &version_information);
|
||||||
strncat(VersionString, temp, sizeof(VersionString) - strlen(VersionString) - 1);
|
strncat(VersionString, temp, sizeof(VersionString) - strlen(VersionString) - 1);
|
||||||
|
|
||||||
FpgaGatherVersion(FPGA_BITSTREAM_LF, temp, sizeof(temp));
|
for (int i = 0; i < fpga_bitstream_num; i++) {
|
||||||
strncat(VersionString, temp, sizeof(VersionString) - strlen(VersionString) - 1);
|
strncat(VersionString, fpga_version_information[i], sizeof(VersionString) - strlen(VersionString) - 1);
|
||||||
FpgaGatherVersion(FPGA_BITSTREAM_HF, temp, sizeof(temp));
|
if (i < fpga_bitstream_num - 1) {
|
||||||
strncat(VersionString, temp, sizeof(VersionString) - strlen(VersionString) - 1);
|
strncat(VersionString, "\n", sizeof(VersionString) - strlen(VersionString) - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Send Chip ID and used flash memory
|
// Send Chip ID and used flash memory
|
||||||
uint32_t text_and_rodata_section_size = (uint32_t)&__data_src_start__ - (uint32_t)&_flash_start;
|
uint32_t text_and_rodata_section_size = (uint32_t)&__data_src_start__ - (uint32_t)&_flash_start;
|
||||||
|
@ -368,7 +367,7 @@ void SendStatus(void)
|
||||||
cmd_send(CMD_ACK,1,0,0,0,0);
|
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
|
#define OPTS 2
|
||||||
|
|
||||||
|
@ -399,8 +398,8 @@ void StandAloneMode14a()
|
||||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||||
|
|
||||||
int selected = 0;
|
int selected = 0;
|
||||||
int playing = 0, iGotoRecord = 0, iGotoClone = 0;
|
bool playing = false, GotoRecord = false, GotoClone = false;
|
||||||
int cardRead[OPTS] = {0};
|
bool cardRead[OPTS] = {false};
|
||||||
uint8_t readUID[10] = {0};
|
uint8_t readUID[10] = {0};
|
||||||
uint32_t uid_1st[OPTS]={0};
|
uint32_t uid_1st[OPTS]={0};
|
||||||
uint32_t uid_2nd[OPTS]={0};
|
uint32_t uid_2nd[OPTS]={0};
|
||||||
|
@ -416,9 +415,9 @@ void StandAloneMode14a()
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
SpinDelay(300);
|
SpinDelay(300);
|
||||||
|
|
||||||
if (iGotoRecord == 1 || cardRead[selected] == 0)
|
if (GotoRecord || !cardRead[selected])
|
||||||
{
|
{
|
||||||
iGotoRecord = 0;
|
GotoRecord = false;
|
||||||
LEDsoff();
|
LEDsoff();
|
||||||
LED(selected + 1, 0);
|
LED(selected + 1, 0);
|
||||||
LED(LED_RED2, 0);
|
LED(LED_RED2, 0);
|
||||||
|
@ -443,7 +442,7 @@ void StandAloneMode14a()
|
||||||
else if (cardRead[(selected+1)%OPTS]) {
|
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);
|
Dbprintf("Button press detected but no card in bank[%d] so playing from bank[%d]", selected, (selected+1)%OPTS);
|
||||||
selected = (selected+1)%OPTS;
|
selected = (selected+1)%OPTS;
|
||||||
break; // playing = 1;
|
break;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Dbprintf("Button press detected but no stored tag to play. (Ignoring button)");
|
Dbprintf("Button press detected but no stored tag to play. (Ignoring button)");
|
||||||
|
@ -493,14 +492,14 @@ void StandAloneMode14a()
|
||||||
LED(selected + 1, 0);
|
LED(selected + 1, 0);
|
||||||
|
|
||||||
// Next state is replay:
|
// Next state is replay:
|
||||||
playing = 1;
|
playing = true;
|
||||||
|
|
||||||
cardRead[selected] = 1;
|
cardRead[selected] = true;
|
||||||
}
|
}
|
||||||
/* MF Classic UID clone */
|
/* MF Classic UID clone */
|
||||||
else if (iGotoClone==1)
|
else if (GotoClone)
|
||||||
{
|
{
|
||||||
iGotoClone=0;
|
GotoClone=false;
|
||||||
LEDsoff();
|
LEDsoff();
|
||||||
LED(selected + 1, 0);
|
LED(selected + 1, 0);
|
||||||
LED(LED_ORANGE, 250);
|
LED(LED_ORANGE, 250);
|
||||||
|
@ -551,7 +550,7 @@ void StandAloneMode14a()
|
||||||
MifareCGetBlock(0x3F, 1, 0, oldBlock0);
|
MifareCGetBlock(0x3F, 1, 0, oldBlock0);
|
||||||
if (oldBlock0[0] == 0 && oldBlock0[0] == oldBlock0[1] && oldBlock0[1] == oldBlock0[2] && oldBlock0[2] == oldBlock0[3]) {
|
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);
|
Dbprintf("No changeable tag detected. Returning to replay mode for bank[%d]", selected);
|
||||||
playing = 1;
|
playing = true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Dbprintf("UID from target tag: %02X%02X%02X%02X", oldBlock0[0],oldBlock0[1],oldBlock0[2],oldBlock0[3]);
|
Dbprintf("UID from target tag: %02X%02X%02X%02X", oldBlock0[0],oldBlock0[1],oldBlock0[2],oldBlock0[3]);
|
||||||
|
@ -569,14 +568,14 @@ void StandAloneMode14a()
|
||||||
if (memcmp(testBlock0,newBlock0,16)==0)
|
if (memcmp(testBlock0,newBlock0,16)==0)
|
||||||
{
|
{
|
||||||
DbpString("Cloned successfull!");
|
DbpString("Cloned successfull!");
|
||||||
cardRead[selected] = 0; // Only if the card was cloned successfully should we clear it
|
cardRead[selected] = false; // Only if the card was cloned successfully should we clear it
|
||||||
playing = 0;
|
playing = false;
|
||||||
iGotoRecord = 1;
|
GotoRecord = true;
|
||||||
selected = (selected+1) % OPTS;
|
selected = (selected+1) % OPTS;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Dbprintf("Clone failed. Back to replay mode on bank[%d]", selected);
|
Dbprintf("Clone failed. Back to replay mode on bank[%d]", selected);
|
||||||
playing = 1;
|
playing = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LEDsoff();
|
LEDsoff();
|
||||||
|
@ -584,14 +583,12 @@ void StandAloneMode14a()
|
||||||
|
|
||||||
}
|
}
|
||||||
// Change where to record (or begin playing)
|
// 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();
|
LEDsoff();
|
||||||
LED(selected + 1, 0);
|
LED(selected + 1, 0);
|
||||||
|
|
||||||
// Begin transmitting
|
// Begin transmitting
|
||||||
if (playing)
|
|
||||||
{
|
|
||||||
LED(LED_GREEN, 0);
|
LED(LED_GREEN, 0);
|
||||||
DbpString("Playing");
|
DbpString("Playing");
|
||||||
for ( ; ; ) {
|
for ( ; ; ) {
|
||||||
|
@ -620,12 +617,12 @@ void StandAloneMode14a()
|
||||||
else if (button_action == BUTTON_SINGLE_CLICK) {
|
else if (button_action == BUTTON_SINGLE_CLICK) {
|
||||||
selected = (selected + 1) % OPTS;
|
selected = (selected + 1) % OPTS;
|
||||||
Dbprintf("Done playing. Switching to record mode on bank %d",selected);
|
Dbprintf("Done playing. Switching to record mode on bank %d",selected);
|
||||||
iGotoRecord = 1;
|
GotoRecord = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (button_action == BUTTON_HOLD) {
|
else if (button_action == BUTTON_HOLD) {
|
||||||
Dbprintf("Playtime over. Begin cloning...");
|
Dbprintf("Playtime over. Begin cloning...");
|
||||||
iGotoClone = 1;
|
GotoClone = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
|
@ -636,13 +633,9 @@ void StandAloneMode14a()
|
||||||
LEDsoff();
|
LEDsoff();
|
||||||
LED(selected + 1, 0);
|
LED(selected + 1, 0);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
while(BUTTON_PRESS())
|
|
||||||
WDT_HIT();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#elif WITH_LF
|
#elif WITH_LF_StandAlone
|
||||||
// samy's sniff and repeat routine
|
// samy's sniff and repeat routine
|
||||||
void SamyRun()
|
void SamyRun()
|
||||||
{
|
{
|
||||||
|
@ -1435,7 +1428,7 @@ void __attribute__((noreturn)) AppMain(void)
|
||||||
}
|
}
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
|
|
||||||
#ifdef WITH_LF
|
#ifdef WITH_LF_StandAlone
|
||||||
#ifndef WITH_ISO14443a_StandAlone
|
#ifndef WITH_ISO14443a_StandAlone
|
||||||
if (BUTTON_HELD(1000) > 0)
|
if (BUTTON_HELD(1000) > 0)
|
||||||
SamyRun();
|
SamyRun();
|
||||||
|
|
|
@ -10,20 +10,21 @@
|
||||||
// mode once it is configured.
|
// mode once it is configured.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "fpgaloader.h"
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "fpgaloader.h"
|
#include "apps.h"
|
||||||
|
#include "fpga.h"
|
||||||
#include "proxmark3.h"
|
#include "proxmark3.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
#include "BigBuf.h"
|
#include "BigBuf.h"
|
||||||
#include "zlib.h"
|
#include "zlib.h"
|
||||||
|
|
||||||
extern void Dbprintf(const char *fmt, ...);
|
|
||||||
|
|
||||||
// remember which version of the bitstream we have already downloaded to the FPGA
|
// 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:
|
// 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;
|
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 uint8_t *fpga_image_ptr = NULL;
|
||||||
static uint32_t uncompressed_bytes_cnt;
|
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 OUTPUT_BUFFER_LEN 80
|
||||||
#define FPGA_INTERLEAVE_SIZE 288
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Set up the Serial Peripheral Interface as master
|
// 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)
|
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
|
// skip undesired data belonging to other bitstream_versions
|
||||||
get_from_fpga_combined_stream(compressed_fpga_stream, output_buffer);
|
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:
|
// initialize z_stream structure for inflate:
|
||||||
compressed_fpga_stream->next_in = &_binary_obj_fpga_all_bit_z_start;
|
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->next_out = output_buffer;
|
||||||
compressed_fpga_stream->avail_out = OUTPUT_BUFFER_LEN;
|
compressed_fpga_stream->avail_out = OUTPUT_BUFFER_LEN;
|
||||||
compressed_fpga_stream->zalloc = &fpga_inflate_malloc;
|
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);
|
header[i] = get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for a valid .bit file (starts with _bitparse_fixed_header)
|
// Check for a valid .bit file (starts with bitparse_fixed_header)
|
||||||
if(memcmp(_bitparse_fixed_header, header, FPGA_BITSTREAM_FIXED_HEADER_SIZE) == 0) {
|
if(memcmp(bitparse_fixed_header, header, FPGA_BITSTREAM_FIXED_HEADER_SIZE) == 0) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
|
@ -427,7 +425,7 @@ void FpgaDownloadAndGo(int bitstream_version)
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int bitstream_length;
|
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);
|
DownloadFPGA(bitstream_version, bitstream_length, &compressed_fpga_stream, output_buffer);
|
||||||
downloaded_bitstream = bitstream_version;
|
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.
|
// 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
|
// 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) {
|
void Fpga_print_status(void) {
|
||||||
Dbprintf("Fgpa");
|
Dbprintf("Currently loaded FPGA image:");
|
||||||
switch(downloaded_bitstream) {
|
Dbprintf(" %s", fpga_version_information[downloaded_bitstream-1]);
|
||||||
case FPGA_BITSTREAM_HF: Dbprintf(" mode....................HF"); break;
|
|
||||||
case FPGA_BITSTREAM_LF: Dbprintf(" mode....................LF"); break;
|
|
||||||
default: Dbprintf(" mode....................%d", downloaded_bitstream); break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int FpgaGetCurrent() {
|
int FpgaGetCurrent() {
|
||||||
|
|
|
@ -10,10 +10,15 @@
|
||||||
// mode once it is configured.
|
// mode once it is configured.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef __FPGALOADER_H
|
||||||
|
#define __FPGALOADER_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
void FpgaSendCommand(uint16_t cmd, uint16_t v);
|
void FpgaSendCommand(uint16_t cmd, uint16_t v);
|
||||||
void FpgaWriteConfWord(uint8_t v);
|
void FpgaWriteConfWord(uint8_t v);
|
||||||
void FpgaDownloadAndGo(int bitstream_version);
|
void FpgaDownloadAndGo(int bitstream_version);
|
||||||
void FpgaGatherVersion(int bitstream_version, char *dst, int len);
|
|
||||||
void FpgaSetupSsc(void);
|
void FpgaSetupSsc(void);
|
||||||
void SetupSpi(int mode);
|
void SetupSpi(int mode);
|
||||||
bool FpgaSetupSscDma(uint8_t *buf, int len);
|
bool FpgaSetupSscDma(uint8_t *buf, int len);
|
||||||
|
@ -24,12 +29,9 @@ int FpgaGetCurrent();
|
||||||
void SetAdcMuxFor(uint32_t whichGpio);
|
void SetAdcMuxFor(uint32_t whichGpio);
|
||||||
|
|
||||||
// definitions for multiple FPGA config files support
|
// 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_LF 1
|
||||||
#define FPGA_BITSTREAM_HF 2
|
#define FPGA_BITSTREAM_HF 2
|
||||||
|
|
||||||
|
|
||||||
// Definitions for the FPGA commands.
|
// Definitions for the FPGA commands.
|
||||||
#define FPGA_CMD_SET_CONFREG (1<<12)
|
#define FPGA_CMD_SET_CONFREG (1<<12)
|
||||||
#define FPGA_CMD_SET_DIVISOR (2<<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_TAGSIM_MOD (2<<0)
|
||||||
#define FPGA_HF_ISO14443A_READER_LISTEN (3<<0)
|
#define FPGA_HF_ISO14443A_READER_LISTEN (3<<0)
|
||||||
#define FPGA_HF_ISO14443A_READER_MOD (4<<0)
|
#define FPGA_HF_ISO14443A_READER_MOD (4<<0)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -813,13 +813,13 @@ void SnoopHitag(uint32_t type) {
|
||||||
int lastbit;
|
int lastbit;
|
||||||
bool bSkip;
|
bool bSkip;
|
||||||
int tag_sof;
|
int tag_sof;
|
||||||
byte_t rx[HITAG_FRAME_LEN];
|
byte_t rx[HITAG_FRAME_LEN] = {0};
|
||||||
size_t rxlen=0;
|
size_t rxlen=0;
|
||||||
|
|
||||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||||
|
|
||||||
// Clean up trace and prepare it for storing frames
|
// Clean up trace and prepare it for storing frames
|
||||||
set_tracing(TRUE);
|
set_tracing(true);
|
||||||
clear_trace();
|
clear_trace();
|
||||||
|
|
||||||
auth_table_len = 0;
|
auth_table_len = 0;
|
||||||
|
@ -1032,7 +1032,7 @@ void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) {
|
||||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||||
|
|
||||||
// Clean up trace and prepare it for storing frames
|
// Clean up trace and prepare it for storing frames
|
||||||
set_tracing(TRUE);
|
set_tracing(true);
|
||||||
clear_trace();
|
clear_trace();
|
||||||
|
|
||||||
auth_table_len = 0;
|
auth_table_len = 0;
|
||||||
|
@ -1225,7 +1225,7 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) {
|
||||||
bSuccessful = false;
|
bSuccessful = false;
|
||||||
|
|
||||||
// Clean up trace and prepare it for storing frames
|
// Clean up trace and prepare it for storing frames
|
||||||
set_tracing(TRUE);
|
set_tracing(true);
|
||||||
clear_trace();
|
clear_trace();
|
||||||
|
|
||||||
//DbpString("Starting Hitag reader family");
|
//DbpString("Starting Hitag reader family");
|
||||||
|
@ -1548,7 +1548,7 @@ void WriterHitag(hitag_function htf, hitag_data* htd, int page) {
|
||||||
bSuccessful = false;
|
bSuccessful = false;
|
||||||
|
|
||||||
// Clean up trace and prepare it for storing frames
|
// Clean up trace and prepare it for storing frames
|
||||||
set_tracing(TRUE);
|
set_tracing(true);
|
||||||
clear_trace();
|
clear_trace();
|
||||||
|
|
||||||
//DbpString("Starting Hitag reader family");
|
//DbpString("Starting Hitag reader family");
|
||||||
|
|
|
@ -210,7 +210,7 @@ static void hitag_send_bit(int bit) {
|
||||||
;
|
;
|
||||||
LOW(GPIO_SSC_DOUT);
|
LOW(GPIO_SSC_DOUT);
|
||||||
while (AT91C_BASE_TC0->TC_CV < T0 * 32)
|
while (AT91C_BASE_TC0->TC_CV < T0 * 32)
|
||||||
;;
|
;
|
||||||
}
|
}
|
||||||
LED_A_OFF();
|
LED_A_OFF();
|
||||||
break;
|
break;
|
||||||
|
@ -945,7 +945,6 @@ void SimulateHitagSTag(bool tag_mem_supplied, byte_t* data) {
|
||||||
int i, j;
|
int i, j;
|
||||||
byte_t rx[HITAG_FRAME_LEN];
|
byte_t rx[HITAG_FRAME_LEN];
|
||||||
size_t rxlen = 0;
|
size_t rxlen = 0;
|
||||||
//bool bQuitTraceFull = false;
|
|
||||||
bQuiet = false;
|
bQuiet = false;
|
||||||
byte_t txbuf[HITAG_FRAME_LEN];
|
byte_t txbuf[HITAG_FRAME_LEN];
|
||||||
byte_t* tx = txbuf;
|
byte_t* tx = txbuf;
|
||||||
|
@ -953,7 +952,7 @@ void SimulateHitagSTag(bool tag_mem_supplied, byte_t* data) {
|
||||||
BigBuf_free();
|
BigBuf_free();
|
||||||
|
|
||||||
// Clean up trace and prepare it for storing frames
|
// Clean up trace and prepare it for storing frames
|
||||||
set_tracing(TRUE);
|
set_tracing(true);
|
||||||
clear_trace();
|
clear_trace();
|
||||||
|
|
||||||
DbpString("Starting HitagS simulation");
|
DbpString("Starting HitagS simulation");
|
||||||
|
@ -985,39 +984,39 @@ void SimulateHitagSTag(bool tag_mem_supplied, byte_t* data) {
|
||||||
tag.max_page=0;
|
tag.max_page=0;
|
||||||
//con1
|
//con1
|
||||||
tag.auth=0;
|
tag.auth=0;
|
||||||
if((tag.pages[1][2]&0x80)==1)
|
if (tag.pages[1][2]&0x80)
|
||||||
tag.auth=1;
|
tag.auth=1;
|
||||||
tag.LCON=0;
|
tag.LCON=0;
|
||||||
if((tag.pages[1][2]&0x2)==1)
|
if (tag.pages[1][2]&0x2)
|
||||||
tag.LCON=1;
|
tag.LCON=1;
|
||||||
tag.LKP=0;
|
tag.LKP=0;
|
||||||
if((tag.pages[1][2]&0x1)==1)
|
if (tag.pages[1][2]&0x1)
|
||||||
tag.LKP=1;
|
tag.LKP=1;
|
||||||
//con2
|
//con2
|
||||||
//0=read write 1=read only
|
//0=read write 1=read only
|
||||||
tag.LCK7=0;
|
tag.LCK7=0;
|
||||||
if((tag.pages[1][1]&0x80)==1)
|
if (tag.pages[1][1]&0x80)
|
||||||
tag.LCK7=1;
|
tag.LCK7=1;
|
||||||
tag.LCK6=0;
|
tag.LCK6=0;
|
||||||
if((tag.pages[1][1]&0x40)==1)
|
if (tag.pages[1][1]&0x40)
|
||||||
tag.LCK6=1;
|
tag.LCK6=1;
|
||||||
tag.LCK5=0;
|
tag.LCK5=0;
|
||||||
if((tag.pages[1][1]&0x20)==1)
|
if (tag.pages[1][1]&0x20)
|
||||||
tag.LCK5=1;
|
tag.LCK5=1;
|
||||||
tag.LCK4=0;
|
tag.LCK4=0;
|
||||||
if((tag.pages[1][1]&0x10)==1)
|
if (tag.pages[1][1]&0x10)
|
||||||
tag.LCK4=1;
|
tag.LCK4=1;
|
||||||
tag.LCK3=0;
|
tag.LCK3=0;
|
||||||
if((tag.pages[1][1]&0x8)==1)
|
if (tag.pages[1][1]&0x8)
|
||||||
tag.LCK3=1;
|
tag.LCK3=1;
|
||||||
tag.LCK2=0;
|
tag.LCK2=0;
|
||||||
if((tag.pages[1][1]&0x4)==1)
|
if (tag.pages[1][1]&0x4)
|
||||||
tag.LCK2=1;
|
tag.LCK2=1;
|
||||||
tag.LCK1=0;
|
tag.LCK1=0;
|
||||||
if((tag.pages[1][1]&0x2)==1)
|
if (tag.pages[1][1]&0x2)
|
||||||
tag.LCK1=1;
|
tag.LCK1=1;
|
||||||
tag.LCK0=0;
|
tag.LCK0=0;
|
||||||
if((tag.pages[1][1]&0x1)==1)
|
if (tag.pages[1][1]&0x1)
|
||||||
tag.LCK0=1;
|
tag.LCK0=1;
|
||||||
|
|
||||||
// Set up simulator mode, frequency divisor which will drive the FPGA
|
// Set up simulator mode, frequency divisor which will drive the FPGA
|
||||||
|
@ -1216,7 +1215,7 @@ void ReadHitagS(hitag_function htf, hitag_data* htd) {
|
||||||
bSuccessful = false;
|
bSuccessful = false;
|
||||||
|
|
||||||
// Clean up trace and prepare it for storing frames
|
// Clean up trace and prepare it for storing frames
|
||||||
set_tracing(TRUE);
|
set_tracing(true);
|
||||||
clear_trace();
|
clear_trace();
|
||||||
|
|
||||||
bQuiet = false;
|
bQuiet = false;
|
||||||
|
@ -1560,7 +1559,7 @@ void WritePageHitagS(hitag_function htf, hitag_data* htd,int page_) {
|
||||||
tag.tstate = NO_OP;
|
tag.tstate = NO_OP;
|
||||||
|
|
||||||
// Clean up trace and prepare it for storing frames
|
// Clean up trace and prepare it for storing frames
|
||||||
set_tracing(TRUE);
|
set_tracing(true);
|
||||||
clear_trace();
|
clear_trace();
|
||||||
|
|
||||||
bQuiet = false;
|
bQuiet = false;
|
||||||
|
@ -1847,7 +1846,7 @@ void check_challenges(bool file_given, byte_t* data) {
|
||||||
bSuccessful = false;
|
bSuccessful = false;
|
||||||
|
|
||||||
// Clean up trace and prepare it for storing frames
|
// Clean up trace and prepare it for storing frames
|
||||||
set_tracing(TRUE);
|
set_tracing(true);
|
||||||
clear_trace();
|
clear_trace();
|
||||||
|
|
||||||
bQuiet = false;
|
bQuiet = false;
|
||||||
|
|
|
@ -91,7 +91,7 @@ static RAMFUNC int OutOfNDecoding(int bit)
|
||||||
|
|
||||||
if(!Uart.bitBuffer) {
|
if(!Uart.bitBuffer) {
|
||||||
Uart.bitBuffer = bit ^ 0xFF0;
|
Uart.bitBuffer = bit ^ 0xFF0;
|
||||||
return FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Uart.bitBuffer <<= 4;
|
Uart.bitBuffer <<= 4;
|
||||||
|
@ -102,7 +102,7 @@ static RAMFUNC int OutOfNDecoding(int bit)
|
||||||
Uart.output[Uart.byteCnt] = Uart.bitBuffer & 0xFF;
|
Uart.output[Uart.byteCnt] = Uart.bitBuffer & 0xFF;
|
||||||
Uart.byteCnt++;
|
Uart.byteCnt++;
|
||||||
Uart.swapper = 0;
|
Uart.swapper = 0;
|
||||||
if(Uart.byteCnt > 15) { return TRUE; }
|
if(Uart.byteCnt > 15) { return true; }
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Uart.swapper = 1;
|
Uart.swapper = 1;
|
||||||
|
@ -139,12 +139,12 @@ static RAMFUNC int OutOfNDecoding(int bit)
|
||||||
Uart.highCnt = 0;
|
Uart.highCnt = 0;
|
||||||
if(Uart.byteCnt == 0) {
|
if(Uart.byteCnt == 0) {
|
||||||
// Its not straightforward to show single EOFs
|
// 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.output[0] = 0xf0;
|
||||||
Uart.byteCnt++;
|
Uart.byteCnt++;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(Uart.state != STATE_START_OF_COMMUNICATION) {
|
else if(Uart.state != STATE_START_OF_COMMUNICATION) {
|
||||||
|
@ -263,7 +263,7 @@ static RAMFUNC int OutOfNDecoding(int bit)
|
||||||
Uart.byteCnt++;
|
Uart.byteCnt++;
|
||||||
Uart.output[Uart.byteCnt] = 0xAA;
|
Uart.output[Uart.byteCnt] = 0xAA;
|
||||||
Uart.byteCnt++;
|
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) {
|
if(Demod.buff < 3) {
|
||||||
Demod.buff++;
|
Demod.buff++;
|
||||||
return FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Demod.state==DEMOD_UNSYNCD) {
|
if(Demod.state==DEMOD_UNSYNCD) {
|
||||||
|
@ -473,7 +473,7 @@ static RAMFUNC int ManchesterDecoding(int v)
|
||||||
Demod.len++;
|
Demod.len++;
|
||||||
Demod.state = DEMOD_UNSYNCD;
|
Demod.state = DEMOD_UNSYNCD;
|
||||||
// error = 0x0f;
|
// error = 0x0f;
|
||||||
return TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Demod.state = DEMOD_ERROR_WAIT;
|
Demod.state = DEMOD_ERROR_WAIT;
|
||||||
|
@ -557,7 +557,7 @@ static RAMFUNC int ManchesterDecoding(int v)
|
||||||
}
|
}
|
||||||
|
|
||||||
Demod.state = DEMOD_UNSYNCD;
|
Demod.state = DEMOD_UNSYNCD;
|
||||||
return TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Demod.output[Demod.len] = 0xad;
|
Demod.output[Demod.len] = 0xad;
|
||||||
|
@ -612,14 +612,14 @@ static RAMFUNC int ManchesterDecoding(int v)
|
||||||
Demod.len++;
|
Demod.len++;
|
||||||
Demod.output[Demod.len] = 0xBB;
|
Demod.output[Demod.len] = 0xBB;
|
||||||
Demod.len++;
|
Demod.len++;
|
||||||
return TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end (state != UNSYNCED)
|
} // 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;
|
// 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
|
// a good trigger condition to get started is probably when we see a
|
||||||
// response from the tag.
|
// 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 command (reader -> tag) that we're receiving.
|
||||||
// The length of a received command will in most cases be no more than 18 bytes.
|
// 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
|
// The DMA buffer, used to stream samples from the FPGA
|
||||||
uint8_t *dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE);
|
uint8_t *dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE);
|
||||||
|
|
||||||
set_tracing(TRUE);
|
set_tracing(true);
|
||||||
clear_trace();
|
clear_trace();
|
||||||
iso14a_set_trigger(FALSE);
|
iso14a_set_trigger(false);
|
||||||
|
|
||||||
int lastRxCounter;
|
int lastRxCounter;
|
||||||
uint8_t *upTo;
|
uint8_t *upTo;
|
||||||
|
@ -749,12 +749,12 @@ void RAMFUNC SnoopIClass(void)
|
||||||
time_stop = (GetCountSspClk()-time_0) << 4;
|
time_stop = (GetCountSspClk()-time_0) << 4;
|
||||||
LED_C_ON();
|
LED_C_ON();
|
||||||
|
|
||||||
//if(!LogTrace(Uart.output,Uart.byteCnt, rsamples, Uart.parityBits,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(!LogTrace(NULL, 0, Uart.endTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER, 0, true)) break;
|
||||||
if(tracing) {
|
if(tracing) {
|
||||||
uint8_t parity[MAX_PARITY_SIZE];
|
uint8_t parity[MAX_PARITY_SIZE];
|
||||||
GetParity(Uart.output, Uart.byteCnt, parity);
|
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) {
|
if(tracing) {
|
||||||
uint8_t parity[MAX_PARITY_SIZE];
|
uint8_t parity[MAX_PARITY_SIZE];
|
||||||
GetParity(Demod.output, Demod.len, parity);
|
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.
|
// And ready to receive another response.
|
||||||
|
@ -830,7 +830,7 @@ void rotateCSN(uint8_t* originalCSN, uint8_t* rotatedCSN) {
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Wait for commands from reader
|
// Wait for commands from reader
|
||||||
// Stop when button is pressed
|
// 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)
|
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(;;) {
|
for(;;) {
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
|
|
||||||
if(BUTTON_PRESS()) return FALSE;
|
if(BUTTON_PRESS()) return false;
|
||||||
|
|
||||||
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
|
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
|
||||||
AT91C_BASE_SSC->SSC_THR = 0x00;
|
AT91C_BASE_SSC->SSC_THR = 0x00;
|
||||||
|
@ -858,7 +858,7 @@ static int GetIClassCommandFromReader(uint8_t *received, int *len, int maxLen)
|
||||||
|
|
||||||
if(OutOfNDecoding(b & 0x0f)) {
|
if(OutOfNDecoding(b & 0x0f)) {
|
||||||
*len = Uart.byteCnt;
|
*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);
|
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||||
|
|
||||||
// Enable and clear the trace
|
// Enable and clear the trace
|
||||||
set_tracing(TRUE);
|
set_tracing(true);
|
||||||
clear_trace();
|
clear_trace();
|
||||||
//Use the emulator memory for SIM
|
//Use the emulator memory for SIM
|
||||||
uint8_t *emulator = BigBuf_get_EM_addr();
|
uint8_t *emulator = BigBuf_get_EM_addr();
|
||||||
|
@ -1325,11 +1325,11 @@ int doIClassSimulation( int simulationMode, uint8_t *reader_mac_buf)
|
||||||
if (tracing) {
|
if (tracing) {
|
||||||
uint8_t parity[MAX_PARITY_SIZE];
|
uint8_t parity[MAX_PARITY_SIZE];
|
||||||
GetParity(receivedCmd, len, parity);
|
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) {
|
if (trace_data != NULL) {
|
||||||
GetParity(trace_data, trace_data_size, parity);
|
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) {
|
if(!tracing) {
|
||||||
DbpString("Trace full");
|
DbpString("Trace full");
|
||||||
|
@ -1420,7 +1420,7 @@ static void TransmitIClassCommand(const uint8_t *cmd, int len, int *samples, int
|
||||||
|
|
||||||
|
|
||||||
uint8_t sendbyte;
|
uint8_t sendbyte;
|
||||||
bool firstpart = TRUE;
|
bool firstpart = true;
|
||||||
c = 0;
|
c = 0;
|
||||||
for(;;) {
|
for(;;) {
|
||||||
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
|
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
|
||||||
|
@ -1512,14 +1512,14 @@ void ReaderTransmitIClass(uint8_t* frame, int len)
|
||||||
if (tracing) {
|
if (tracing) {
|
||||||
uint8_t par[MAX_PARITY_SIZE];
|
uint8_t par[MAX_PARITY_SIZE];
|
||||||
GetParity(frame, len, par);
|
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
|
// Wait a certain time for tag response
|
||||||
// If a response is captured return TRUE
|
// If a response is captured return true
|
||||||
// If it takes too long return FALSE
|
// If it takes too long return false
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
static int GetIClassAnswer(uint8_t *receivedResponse, int maxLen, int *samples, int *elapsed) //uint8_t *buffer
|
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;
|
uint8_t b;
|
||||||
if (elapsed) *elapsed = 0;
|
if (elapsed) *elapsed = 0;
|
||||||
|
|
||||||
bool skip = FALSE;
|
bool skip = false;
|
||||||
|
|
||||||
c = 0;
|
c = 0;
|
||||||
for(;;) {
|
for(;;) {
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
|
|
||||||
if(BUTTON_PRESS()) return FALSE;
|
if(BUTTON_PRESS()) return false;
|
||||||
|
|
||||||
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
|
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!!
|
AT91C_BASE_SSC->SSC_THR = 0x00; // To make use of exact timing of next command from reader!!
|
||||||
if (elapsed) (*elapsed)++;
|
if (elapsed) (*elapsed)++;
|
||||||
}
|
}
|
||||||
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
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;
|
b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||||
skip = !skip;
|
skip = !skip;
|
||||||
if(skip) continue;
|
if(skip) continue;
|
||||||
|
|
||||||
if(ManchesterDecoding(b & 0x0f)) {
|
if(ManchesterDecoding(b & 0x0f)) {
|
||||||
*samples = c << 3;
|
*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 ReaderReceiveIClass(uint8_t* receivedAnswer)
|
||||||
{
|
{
|
||||||
int samples = 0;
|
int samples = 0;
|
||||||
if (!GetIClassAnswer(receivedAnswer,160,&samples,0)) return FALSE;
|
if (!GetIClassAnswer(receivedAnswer,160,&samples,0)) return false;
|
||||||
rsamples += samples;
|
rsamples += samples;
|
||||||
if (tracing) {
|
if (tracing) {
|
||||||
uint8_t parity[MAX_PARITY_SIZE];
|
uint8_t parity[MAX_PARITY_SIZE];
|
||||||
GetParity(receivedAnswer, Demod.len, parity);
|
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;
|
return Demod.len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1582,7 +1582,7 @@ void setupIclassReader()
|
||||||
{
|
{
|
||||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||||
// Reset trace buffer
|
// Reset trace buffer
|
||||||
set_tracing(TRUE);
|
set_tracing(true);
|
||||||
clear_trace();
|
clear_trace();
|
||||||
|
|
||||||
// Setup SSC
|
// Setup SSC
|
||||||
|
@ -1822,7 +1822,7 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) {
|
||||||
uint8_t resp[ICLASS_BUFFER_SIZE];
|
uint8_t resp[ICLASS_BUFFER_SIZE];
|
||||||
|
|
||||||
setupIclassReader();
|
setupIclassReader();
|
||||||
set_tracing(TRUE);
|
set_tracing(true);
|
||||||
|
|
||||||
while(!BUTTON_PRESS()) {
|
while(!BUTTON_PRESS()) {
|
||||||
|
|
||||||
|
|
|
@ -2151,9 +2151,7 @@ void ReaderMifare(bool first_try)
|
||||||
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
|
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
|
||||||
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_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.
|
// free eventually allocated BigBuf memory. We want all for tracing.
|
||||||
BigBuf_free();
|
BigBuf_free();
|
||||||
|
@ -2161,9 +2159,9 @@ void ReaderMifare(bool first_try)
|
||||||
clear_trace();
|
clear_trace();
|
||||||
set_tracing(true);
|
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
|
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;
|
bool led_on = true;
|
||||||
uint8_t uid[10] ={0};
|
uint8_t uid[10] ={0};
|
||||||
uint32_t cuid;
|
uint32_t cuid;
|
||||||
|
@ -2171,11 +2169,11 @@ void ReaderMifare(bool first_try)
|
||||||
uint32_t nt = 0;
|
uint32_t nt = 0;
|
||||||
uint32_t previous_nt = 0;
|
uint32_t previous_nt = 0;
|
||||||
static uint32_t nt_attacked = 0;
|
static uint32_t nt_attacked = 0;
|
||||||
byte_t par_list[8] = {0x00};
|
uint8_t par_list[8] = {0x00};
|
||||||
byte_t ks_list[8] = {0x00};
|
uint8_t ks_list[8] = {0x00};
|
||||||
|
|
||||||
#define PRNG_SEQUENCE_LENGTH (1 << 16);
|
#define PRNG_SEQUENCE_LENGTH (1 << 16);
|
||||||
static uint32_t sync_time;
|
uint32_t sync_time = GetCountSspClk() & 0xfffffff8;
|
||||||
static int32_t sync_cycles;
|
static int32_t sync_cycles;
|
||||||
int catch_up_cycles = 0;
|
int catch_up_cycles = 0;
|
||||||
int last_catch_up = 0;
|
int last_catch_up = 0;
|
||||||
|
@ -2185,10 +2183,9 @@ void ReaderMifare(bool first_try)
|
||||||
|
|
||||||
if (first_try) {
|
if (first_try) {
|
||||||
mf_nr_ar3 = 0;
|
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).
|
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;
|
nt_attacked = 0;
|
||||||
par[0] = 0;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// we were unsuccessful on a previous call. Try another READER nonce (first 3 parity bits remain the same)
|
// 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_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 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 NUM_DEBUG_INFOS 8 // per strategy
|
||||||
#define MAX_STRATEGY 3
|
#define MAX_STRATEGY 3
|
||||||
uint16_t unexpected_random = 0;
|
uint16_t unexpected_random = 0;
|
||||||
|
@ -2253,8 +2251,8 @@ void ReaderMifare(bool first_try)
|
||||||
sync_time = (sync_time & 0xfffffff8) + sync_cycles + catch_up_cycles;
|
sync_time = (sync_time & 0xfffffff8) + sync_cycles + catch_up_cycles;
|
||||||
catch_up_cycles = 0;
|
catch_up_cycles = 0;
|
||||||
|
|
||||||
// if we missed the sync time already, advance to the next nonce repeat
|
// if we missed the sync time already or are about to miss it, advance to the next nonce repeat
|
||||||
while(GetCountSspClk() > sync_time) {
|
while(sync_time < GetCountSspClk() + SYNC_TIME_BUFFER) {
|
||||||
elapsed_prng_sequences++;
|
elapsed_prng_sequences++;
|
||||||
sync_time = (sync_time & 0xfffffff8) + sync_cycles;
|
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);
|
memcpy(buf + 0, uid, 4);
|
||||||
num_to_bytes(nt, 4, buf + 4);
|
num_to_bytes(nt, 4, buf + 4);
|
||||||
memcpy(buf + 8, par_list, 8);
|
memcpy(buf + 8, par_list, 8);
|
||||||
memcpy(buf + 16, ks_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...
|
// Thats it...
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
|
@ -2482,7 +2480,7 @@ void RAMFUNC SniffMifare(uint8_t param) {
|
||||||
for(uint32_t sniffCounter = 0; true; ) {
|
for(uint32_t sniffCounter = 0; true; ) {
|
||||||
|
|
||||||
if(BUTTON_PRESS()) {
|
if(BUTTON_PRESS()) {
|
||||||
DbpString("cancelled by button");
|
DbpString("Canceled by button.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2539,7 +2537,9 @@ void RAMFUNC SniffMifare(uint8_t param) {
|
||||||
if(!TagIsActive) { // no need to try decoding tag data if the reader is sending
|
if(!TagIsActive) { // no need to try decoding tag data if the reader is sending
|
||||||
uint8_t readerdata = (previous_data & 0xF0) | (*data >> 4);
|
uint8_t readerdata = (previous_data & 0xF0) | (*data >> 4);
|
||||||
if(MillerDecoding(readerdata, (sniffCounter-1)*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;
|
if (MfSniffLogic(receivedCmd, Uart.len, Uart.parity, Uart.bitCount, true)) break;
|
||||||
|
|
||||||
/* And ready to receive another command. */
|
/* And ready to receive another command. */
|
||||||
|
@ -2554,7 +2554,8 @@ void RAMFUNC SniffMifare(uint8_t param) {
|
||||||
if(!ReaderIsActive) { // no need to try decoding tag data if the reader is sending
|
if(!ReaderIsActive) { // no need to try decoding tag data if the reader is sending
|
||||||
uint8_t tagdata = (previous_data << 4) | (*data & 0x0F);
|
uint8_t tagdata = (previous_data << 4) | (*data & 0x0F);
|
||||||
if(ManchesterDecoding(tagdata, 0, (sniffCounter-1)*4)) {
|
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;
|
if (MfSniffLogic(receivedResponse, Demod.len, Demod.parity, Demod.bitCount, false)) break;
|
||||||
|
|
||||||
|
@ -2576,7 +2577,7 @@ void RAMFUNC SniffMifare(uint8_t param) {
|
||||||
|
|
||||||
} // main cycle
|
} // main cycle
|
||||||
|
|
||||||
DbpString("COMMAND FINISHED");
|
DbpString("COMMAND FINISHED.");
|
||||||
|
|
||||||
FpgaDisableSscDma();
|
FpgaDisableSscDma();
|
||||||
MfSniffEnd();
|
MfSniffEnd();
|
||||||
|
|
|
@ -243,7 +243,7 @@ static RAMFUNC int Handle14443bUartBit(uint8_t bit)
|
||||||
LED_A_OFF(); // Finished receiving
|
LED_A_OFF(); // Finished receiving
|
||||||
Uart.state = STATE_UNSYNCD;
|
Uart.state = STATE_UNSYNCD;
|
||||||
if (Uart.byteCnt != 0) {
|
if (Uart.byteCnt != 0) {
|
||||||
return TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// this is an error
|
// this is an error
|
||||||
|
@ -259,7 +259,7 @@ static RAMFUNC int Handle14443bUartBit(uint8_t bit)
|
||||||
break;
|
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),
|
// 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
|
// 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
|
// 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
|
// Assume that we're called with the SSC (to the FPGA) and ADC path set
|
||||||
// correctly.
|
// correctly.
|
||||||
|
@ -302,20 +302,20 @@ static int GetIso14443bCommandFromReader(uint8_t *received, uint16_t *len)
|
||||||
for(;;) {
|
for(;;) {
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
|
|
||||||
if(BUTTON_PRESS()) return FALSE;
|
if(BUTTON_PRESS()) return false;
|
||||||
|
|
||||||
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
||||||
uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||||
for(uint8_t mask = 0x80; mask != 0x00; mask >>= 1) {
|
for(uint8_t mask = 0x80; mask != 0x00; mask >>= 1) {
|
||||||
if(Handle14443bUartBit(b & mask)) {
|
if(Handle14443bUartBit(b & mask)) {
|
||||||
*len = Uart.byteCnt;
|
*len = Uart.byteCnt;
|
||||||
return TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -347,7 +347,7 @@ void SimulateIso14443bTag(void)
|
||||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||||
|
|
||||||
clear_trace();
|
clear_trace();
|
||||||
set_tracing(TRUE);
|
set_tracing(true);
|
||||||
|
|
||||||
const uint8_t *resp;
|
const uint8_t *resp;
|
||||||
uint8_t *respCode;
|
uint8_t *respCode;
|
||||||
|
@ -387,7 +387,7 @@ void SimulateIso14443bTag(void)
|
||||||
|
|
||||||
if (tracing) {
|
if (tracing) {
|
||||||
uint8_t parity[MAX_PARITY_SIZE];
|
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.
|
// Good, look at the command now.
|
||||||
|
@ -464,7 +464,7 @@ void SimulateIso14443bTag(void)
|
||||||
// trace the response:
|
// trace the response:
|
||||||
if (tracing) {
|
if (tracing) {
|
||||||
uint8_t parity[MAX_PARITY_SIZE];
|
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();
|
LED_C_OFF();
|
||||||
if(s == 0x000) {
|
if(s == 0x000) {
|
||||||
// This is EOF (start, stop and all data bits == '0'
|
// 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;
|
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
|
* 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)
|
static void GetSamplesFor14443bDemod(int n, bool quiet)
|
||||||
{
|
{
|
||||||
int max = 0;
|
int max = 0;
|
||||||
bool gotFrame = FALSE;
|
bool gotFrame = false;
|
||||||
int lastRxCounter, ci, cq, samples = 0;
|
int lastRxCounter, ci, cq, samples = 0;
|
||||||
|
|
||||||
// Allocate memory from BigBuf for some buffers
|
// Allocate memory from BigBuf for some buffers
|
||||||
|
@ -792,7 +792,7 @@ static void GetSamplesFor14443bDemod(int n, bool quiet)
|
||||||
samples += 2;
|
samples += 2;
|
||||||
|
|
||||||
if(Handle14443bSamplesDemod(ci, cq)) {
|
if(Handle14443bSamplesDemod(ci, cq)) {
|
||||||
gotFrame = TRUE;
|
gotFrame = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -808,7 +808,7 @@ static void GetSamplesFor14443bDemod(int n, bool quiet)
|
||||||
//Tracing
|
//Tracing
|
||||||
if (tracing && Demod.len > 0) {
|
if (tracing && Demod.len > 0) {
|
||||||
uint8_t parity[MAX_PARITY_SIZE];
|
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();
|
TransmitFor14443b();
|
||||||
if (tracing) {
|
if (tracing) {
|
||||||
uint8_t parity[MAX_PARITY_SIZE];
|
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
|
// send
|
||||||
CodeAndTransmit14443bAsReader(message_frame, message_length + 4);
|
CodeAndTransmit14443bAsReader(message_frame, message_length + 4);
|
||||||
// get response
|
// get response
|
||||||
GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT*100, TRUE);
|
GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT*100, true);
|
||||||
if(Demod.len < 3)
|
if(Demod.len < 3)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -981,7 +981,7 @@ int iso14443b_select_card()
|
||||||
|
|
||||||
// first, wake up the tag
|
// first, wake up the tag
|
||||||
CodeAndTransmit14443bAsReader(wupb, sizeof(wupb));
|
CodeAndTransmit14443bAsReader(wupb, sizeof(wupb));
|
||||||
GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE);
|
GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, true);
|
||||||
// ATQB too short?
|
// ATQB too short?
|
||||||
if (Demod.len < 14)
|
if (Demod.len < 14)
|
||||||
{
|
{
|
||||||
|
@ -996,7 +996,7 @@ int iso14443b_select_card()
|
||||||
attrib[7] = Demod.output[10] & 0x0F;
|
attrib[7] = Demod.output[10] & 0x0F;
|
||||||
ComputeCrc14443(CRC_14443_B, attrib, 9, attrib + 9, attrib + 10);
|
ComputeCrc14443(CRC_14443_B, attrib, 9, attrib + 9, attrib + 10);
|
||||||
CodeAndTransmit14443bAsReader(attrib, sizeof(attrib));
|
CodeAndTransmit14443bAsReader(attrib, sizeof(attrib));
|
||||||
GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE);
|
GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, true);
|
||||||
// Answer to ATTRIB too short?
|
// Answer to ATTRIB too short?
|
||||||
if(Demod.len < 3)
|
if(Demod.len < 3)
|
||||||
{
|
{
|
||||||
|
@ -1056,12 +1056,12 @@ void ReadSTMemoryIso14443b(uint32_t dwLast)
|
||||||
SpinDelay(200);
|
SpinDelay(200);
|
||||||
|
|
||||||
clear_trace();
|
clear_trace();
|
||||||
set_tracing(TRUE);
|
set_tracing(true);
|
||||||
|
|
||||||
// First command: wake up the tag using the INITIATE command
|
// First command: wake up the tag using the INITIATE command
|
||||||
uint8_t cmd1[] = {0x06, 0x00, 0x97, 0x5b};
|
uint8_t cmd1[] = {0x06, 0x00, 0x97, 0x5b};
|
||||||
CodeAndTransmit14443bAsReader(cmd1, sizeof(cmd1));
|
CodeAndTransmit14443bAsReader(cmd1, sizeof(cmd1));
|
||||||
GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE);
|
GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, true);
|
||||||
|
|
||||||
if (Demod.len == 0) {
|
if (Demod.len == 0) {
|
||||||
DbpString("No response from tag");
|
DbpString("No response from tag");
|
||||||
|
@ -1077,7 +1077,7 @@ void ReadSTMemoryIso14443b(uint32_t dwLast)
|
||||||
cmd1[1] = Demod.output[0];
|
cmd1[1] = Demod.output[0];
|
||||||
ComputeCrc14443(CRC_14443_B, cmd1, 2, &cmd1[2], &cmd1[3]);
|
ComputeCrc14443(CRC_14443_B, cmd1, 2, &cmd1[2], &cmd1[3]);
|
||||||
CodeAndTransmit14443bAsReader(cmd1, sizeof(cmd1));
|
CodeAndTransmit14443bAsReader(cmd1, sizeof(cmd1));
|
||||||
GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE);
|
GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, true);
|
||||||
if (Demod.len != 3) {
|
if (Demod.len != 3) {
|
||||||
Dbprintf("Expected 3 bytes from tag, got %d", Demod.len);
|
Dbprintf("Expected 3 bytes from tag, got %d", Demod.len);
|
||||||
return;
|
return;
|
||||||
|
@ -1099,7 +1099,7 @@ void ReadSTMemoryIso14443b(uint32_t dwLast)
|
||||||
cmd1[0] = 0x0B;
|
cmd1[0] = 0x0B;
|
||||||
ComputeCrc14443(CRC_14443_B, cmd1, 1 , &cmd1[1], &cmd1[2]);
|
ComputeCrc14443(CRC_14443_B, cmd1, 1 , &cmd1[1], &cmd1[2]);
|
||||||
CodeAndTransmit14443bAsReader(cmd1, 3); // Only first three bytes for this one
|
CodeAndTransmit14443bAsReader(cmd1, 3); // Only first three bytes for this one
|
||||||
GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE);
|
GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, true);
|
||||||
if (Demod.len != 10) {
|
if (Demod.len != 10) {
|
||||||
Dbprintf("Expected 10 bytes from tag, got %d", Demod.len);
|
Dbprintf("Expected 10 bytes from tag, got %d", Demod.len);
|
||||||
return;
|
return;
|
||||||
|
@ -1128,7 +1128,7 @@ void ReadSTMemoryIso14443b(uint32_t dwLast)
|
||||||
cmd1[1] = i;
|
cmd1[1] = i;
|
||||||
ComputeCrc14443(CRC_14443_B, cmd1, 2, &cmd1[2], &cmd1[3]);
|
ComputeCrc14443(CRC_14443_B, cmd1, 2, &cmd1[2], &cmd1[3]);
|
||||||
CodeAndTransmit14443bAsReader(cmd1, sizeof(cmd1));
|
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
|
if (Demod.len != 6) { // Check if we got an answer from the tag
|
||||||
DbpString("Expected 6 bytes from tag, got less...");
|
DbpString("Expected 6 bytes from tag, got less...");
|
||||||
return;
|
return;
|
||||||
|
@ -1174,13 +1174,13 @@ void RAMFUNC SnoopIso14443b(void)
|
||||||
// We won't start recording the frames that we acquire until we trigger;
|
// 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
|
// a good trigger condition to get started is probably when we see a
|
||||||
// response from the tag.
|
// 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);
|
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||||
BigBuf_free();
|
BigBuf_free();
|
||||||
|
|
||||||
clear_trace();
|
clear_trace();
|
||||||
set_tracing(TRUE);
|
set_tracing(true);
|
||||||
|
|
||||||
// The DMA buffer, used to stream samples from the FPGA
|
// The DMA buffer, used to stream samples from the FPGA
|
||||||
int8_t *dmaBuf = (int8_t*) BigBuf_malloc(ISO14443B_DMA_BUFFER_SIZE);
|
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);
|
FpgaSetupSscDma((uint8_t*) dmaBuf, ISO14443B_DMA_BUFFER_SIZE);
|
||||||
uint8_t parity[MAX_PARITY_SIZE];
|
uint8_t parity[MAX_PARITY_SIZE];
|
||||||
|
|
||||||
bool TagIsActive = FALSE;
|
bool TagIsActive = false;
|
||||||
bool ReaderIsActive = FALSE;
|
bool ReaderIsActive = false;
|
||||||
|
|
||||||
// And now we loop, receiving samples.
|
// And now we loop, receiving samples.
|
||||||
for(;;) {
|
for(;;) {
|
||||||
|
@ -1259,7 +1259,7 @@ void RAMFUNC SnoopIso14443b(void)
|
||||||
if (!TagIsActive) { // no need to try decoding reader data if the tag is sending
|
if (!TagIsActive) { // no need to try decoding reader data if the tag is sending
|
||||||
if(Handle14443bUartBit(ci & 0x01)) {
|
if(Handle14443bUartBit(ci & 0x01)) {
|
||||||
if(triggered && tracing) {
|
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. */
|
/* And ready to receive another command. */
|
||||||
UartReset();
|
UartReset();
|
||||||
|
@ -1269,7 +1269,7 @@ void RAMFUNC SnoopIso14443b(void)
|
||||||
}
|
}
|
||||||
if(Handle14443bUartBit(cq & 0x01)) {
|
if(Handle14443bUartBit(cq & 0x01)) {
|
||||||
if(triggered && tracing) {
|
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. */
|
/* And ready to receive another command. */
|
||||||
UartReset();
|
UartReset();
|
||||||
|
@ -1287,9 +1287,9 @@ void RAMFUNC SnoopIso14443b(void)
|
||||||
if(tracing)
|
if(tracing)
|
||||||
{
|
{
|
||||||
uint8_t parity[MAX_PARITY_SIZE];
|
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.
|
// And ready to receive another response.
|
||||||
DemodReset();
|
DemodReset();
|
||||||
|
@ -1330,12 +1330,12 @@ void SendRawCommand14443B(uint32_t datalen, uint32_t recv, uint8_t powerfield, u
|
||||||
FpgaSetupSsc();
|
FpgaSetupSsc();
|
||||||
|
|
||||||
if (datalen){
|
if (datalen){
|
||||||
set_tracing(TRUE);
|
set_tracing(true);
|
||||||
|
|
||||||
CodeAndTransmit14443bAsReader(data, datalen);
|
CodeAndTransmit14443bAsReader(data, datalen);
|
||||||
|
|
||||||
if(recv) {
|
if(recv) {
|
||||||
GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE);
|
GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, true);
|
||||||
uint16_t iLen = MIN(Demod.len, USB_CMD_DATA_SIZE);
|
uint16_t iLen = MIN(Demod.len, USB_CMD_DATA_SIZE);
|
||||||
cmd_send(CMD_ACK, iLen, 0, 0, Demod.output, iLen);
|
cmd_send(CMD_ACK, iLen, 0, 0, Demod.output, iLen);
|
||||||
}
|
}
|
||||||
|
|
|
@ -305,7 +305,7 @@ static int GetIso15693AnswerFromTag(uint8_t *receivedResponse, int maxLen, int *
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
|
||||||
//spindelay(60); // greg - experiment to get rid of some of the 0 byte/failed reads
|
//spindelay(60); // greg - experiment to get rid of some of the 0 byte/failed reads
|
||||||
c = 0;
|
c = 0;
|
||||||
getNext = FALSE;
|
getNext = false;
|
||||||
for(;;) {
|
for(;;) {
|
||||||
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
|
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
|
||||||
AT91C_BASE_SSC->SSC_THR = 0x43;
|
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);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
|
||||||
//spindelay(60); // greg - experiment to get rid of some of the 0 byte/failed reads
|
//spindelay(60); // greg - experiment to get rid of some of the 0 byte/failed reads
|
||||||
c = 0;
|
c = 0;
|
||||||
getNext = FALSE;
|
getNext = false;
|
||||||
for(;;) {
|
for(;;) {
|
||||||
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
|
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
|
||||||
AT91C_BASE_SSC->SSC_THR = 0x43;
|
AT91C_BASE_SSC->SSC_THR = 0x43;
|
||||||
|
@ -612,7 +612,7 @@ void AcquireRawAdcSamplesIso15693(void)
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
|
||||||
|
|
||||||
c = 0;
|
c = 0;
|
||||||
getNext = FALSE;
|
getNext = false;
|
||||||
for(;;) {
|
for(;;) {
|
||||||
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
|
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
|
||||||
AT91C_BASE_SSC->SSC_THR = 0x43;
|
AT91C_BASE_SSC->SSC_THR = 0x43;
|
||||||
|
@ -666,7 +666,7 @@ void RecordRawAdcSamplesIso15693(void)
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
|
||||||
|
|
||||||
c = 0;
|
c = 0;
|
||||||
getNext = FALSE;
|
getNext = false;
|
||||||
for(;;) {
|
for(;;) {
|
||||||
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
|
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
|
||||||
AT91C_BASE_SSC->SSC_THR = 0x43;
|
AT91C_BASE_SSC->SSC_THR = 0x43;
|
||||||
|
|
108
armsrc/lfops.c
108
armsrc/lfops.c
|
@ -4,7 +4,7 @@
|
||||||
// the license.
|
// the license.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Miscellaneous routines for low frequency tag operations.
|
// 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
|
// Also routines for raw mode reading/simulating of LF waveform
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -28,51 +28,103 @@
|
||||||
*/
|
*/
|
||||||
void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint32_t period_1, uint8_t *command)
|
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
|
// use lf config settings
|
||||||
// see if 'h' was specified
|
sample_config *sc = getSamplingConfig();
|
||||||
|
|
||||||
if (command[strlen((char *) command) - 1] == 'h')
|
// Make sure the tag is reset
|
||||||
divisor_used = 88; // 134.8 KHz
|
|
||||||
|
|
||||||
sample_config sc = { 0,0,1, divisor_used, 0};
|
|
||||||
setSamplingConfig(&sc);
|
|
||||||
//clear read buffer
|
|
||||||
BigBuf_Clear_keep_EM();
|
|
||||||
|
|
||||||
/* Make sure the tag is reset */
|
|
||||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
SpinDelay(2500);
|
WaitMS(2500);
|
||||||
|
|
||||||
LFSetupFPGAForADC(sc.divisor, 1);
|
// clear read buffer (after fpga bitstream loaded...)
|
||||||
|
BigBuf_Clear_keep_EM();
|
||||||
|
|
||||||
|
// power on
|
||||||
|
LFSetupFPGAForADC(sc->divisor, 1);
|
||||||
|
|
||||||
// And a little more time for the tag to fully power up
|
// 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
|
// now modulate the reader field
|
||||||
|
|
||||||
|
if (bitbang) {
|
||||||
|
// 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 7us in bit bang mode");
|
||||||
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
|
LED_D_OFF();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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++;
|
||||||
|
|
||||||
|
int counter = 0;
|
||||||
|
bool off = false;
|
||||||
|
for (counter = 0; counter < cmd_len; counter++) {
|
||||||
|
// 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 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);
|
||||||
|
LED_D_ON();
|
||||||
|
off = false;
|
||||||
|
}
|
||||||
|
// note we appear to take about 7us 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 != ' ') {
|
while(*command != '\0' && *command != ' ') {
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
LED_D_OFF();
|
LED_D_OFF();
|
||||||
SpinDelayUs(delay_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);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
|
||||||
LED_D_ON();
|
LED_D_ON();
|
||||||
if(*(command++) == '0')
|
if(*(command++) == '0') {
|
||||||
SpinDelayUs(period_0);
|
WaitUS(period_0);
|
||||||
else
|
} else {
|
||||||
SpinDelayUs(period_1);
|
WaitUS(period_1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
LED_D_OFF();
|
LED_D_OFF();
|
||||||
SpinDelayUs(delay_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);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
|
||||||
|
|
||||||
// now do the read
|
// now do the read
|
||||||
DoAcquisition_config(false, 0);
|
DoAcquisition_config(false, 0);
|
||||||
|
|
||||||
|
// 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
|
/* blank r/w tag data stream
|
||||||
|
@ -516,7 +568,7 @@ static void fcAll(uint8_t fc, int *n, uint8_t clock, uint16_t *modCnt)
|
||||||
uint8_t wavesPerClock = clock/fc;
|
uint8_t wavesPerClock = clock/fc;
|
||||||
uint8_t mod = clock % fc; //modifier
|
uint8_t mod = clock % fc; //modifier
|
||||||
uint8_t modAdj = fc/mod; //how often to apply 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
|
// loop through clock - step field clock
|
||||||
for (uint8_t idx=0; idx < wavesPerClock; idx++){
|
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)
|
// put 1/2 FC length 1's and 1/2 0's per field clock wave (to create the wave)
|
||||||
|
@ -768,9 +820,9 @@ void CmdPSKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream)
|
||||||
|
|
||||||
for (i=0; i<size; i++){
|
for (i=0; i<size; i++){
|
||||||
if (BitStream[i] == curPhase){
|
if (BitStream[i] == curPhase){
|
||||||
pskSimBit(carrier, &n, clk, &curPhase, FALSE);
|
pskSimBit(carrier, &n, clk, &curPhase, false);
|
||||||
} else {
|
} else {
|
||||||
pskSimBit(carrier, &n, clk, &curPhase, TRUE);
|
pskSimBit(carrier, &n, clk, &curPhase, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Dbprintf("Simulating with Carrier: %d, clk: %d, invert: %d, n: %d",carrier, clk, invert, n);
|
Dbprintf("Simulating with Carrier: %d, clk: %d, invert: %d, n: %d",carrier, clk, invert, n);
|
||||||
|
|
|
@ -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
|
* and is Manchester?, we directly gather the manchester data into bigbuff
|
||||||
**/
|
**/
|
||||||
#define COTAG_T1 384
|
#define COTAG_T1 384
|
||||||
|
|
|
@ -20,6 +20,9 @@
|
||||||
#include "parity.h"
|
#include "parity.h"
|
||||||
#include "crc.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
|
// the block number for the ISO14443-4 PCB
|
||||||
static uint8_t pcb_blocknum = 0;
|
static uint8_t pcb_blocknum = 0;
|
||||||
// Deselect card by sending a s-block. the crc is precalced for speed
|
// 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) {
|
if (slow) {
|
||||||
timeout = GetCountSspClk() + PRE_AUTHENTICATION_LEADTIME;
|
timeout = GetCountSspClk() + HARDNESTED_PRE_AUTHENTICATION_LEADTIME;
|
||||||
while(GetCountSspClk() < timeout);
|
while(GetCountSspClk() < timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -694,9 +697,11 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// send a dummy response in order to trigger the cards authentication failure timeout
|
// send an incomplete dummy response in order to trigger the card's authentication failure timeout
|
||||||
uint8_t dummy_answer[8] = {0};
|
uint8_t dummy_answer[1] = {0};
|
||||||
ReaderTransmit(dummy_answer, 8, NULL);
|
ReaderTransmit(dummy_answer, 1, NULL);
|
||||||
|
|
||||||
|
timeout = GetCountSspClk() + HARDNESTED_AUTHENTICATION_TIMEOUT;
|
||||||
|
|
||||||
num_nonces++;
|
num_nonces++;
|
||||||
if (num_nonces % 2) {
|
if (num_nonces % 2) {
|
||||||
|
@ -709,6 +714,9 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags,
|
||||||
i += 9;
|
i += 9;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// wait for the card to become ready again
|
||||||
|
while(GetCountSspClk() < timeout);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LED_C_OFF();
|
LED_C_OFF();
|
||||||
|
@ -1141,7 +1149,7 @@ static bool isBlockTrailer(int blockN) {
|
||||||
if (blockN >= 128 && blockN <= 256) {
|
if (blockN >= 128 && blockN <= 256) {
|
||||||
return ((blockN & 0x0F) == 0x0F);
|
return ((blockN & 0x0F) == 0x0F);
|
||||||
}
|
}
|
||||||
return FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MifareCWipe(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){
|
void MifareCWipe(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
#include "proxmark3.h"
|
#include "proxmark3.h"
|
||||||
#include "apps.h"
|
#include "apps.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "string.h"
|
|
||||||
|
|
||||||
#include "iso14443crc.h"
|
#include "iso14443crc.h"
|
||||||
#include "iso14443a.h"
|
#include "iso14443a.h"
|
||||||
|
|
|
@ -35,7 +35,7 @@ bool MfSniffInit(void){
|
||||||
sniffSAK = 0;
|
sniffSAK = 0;
|
||||||
sniffUIDType = SNF_UID_4;
|
sniffUIDType = SNF_UID_4;
|
||||||
|
|
||||||
return FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MfSniffEnd(void){
|
bool MfSniffEnd(void){
|
||||||
|
@ -43,7 +43,7 @@ bool MfSniffEnd(void){
|
||||||
cmd_send(CMD_ACK,0,0,0,0,0);
|
cmd_send(CMD_ACK,0,0,0,0,0);
|
||||||
LED_B_OFF();
|
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) {
|
bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint8_t *parity, uint16_t bitCnt, bool reader) {
|
||||||
|
@ -59,32 +59,27 @@ bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint8_t *parity, ui
|
||||||
memset(sniffUID, 0x00, 8);
|
memset(sniffUID, 0x00, 8);
|
||||||
memset(sniffATQA, 0x00, 2);
|
memset(sniffATQA, 0x00, 2);
|
||||||
sniffSAK = 0;
|
sniffSAK = 0;
|
||||||
sniffState = SNF_WUPREQ;
|
sniffState = SNF_ATQA;
|
||||||
|
if (data[0] == 0x40)
|
||||||
|
sniffState = SNF_MAGIC_WUPC2;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SNF_WUPREQ:{
|
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
|
if ((!reader) && (len == 2)) { // ATQA from tag
|
||||||
memcpy(sniffATQA, data, 2);
|
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;
|
sniffState = SNF_UID1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SNF_UID1:{
|
case SNF_UID1:{
|
||||||
if ((reader) && (len == 9) && (data[0] == 0x93) && (data[1] == 0x70) && (CheckCrc14443(CRC_14443_A, data, 9))) { // Select 4 Byte UID from reader
|
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;
|
sniffState = SNF_SAK;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -92,25 +87,19 @@ bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint8_t *parity, ui
|
||||||
case SNF_SAK:{
|
case SNF_SAK:{
|
||||||
if ((!reader) && (len == 3) && (CheckCrc14443(CRC_14443_A, data, 3))) { // SAK from card?
|
if ((!reader) && (len == 3) && (CheckCrc14443(CRC_14443_A, data, 3))) { // SAK from card?
|
||||||
sniffSAK = data[0];
|
sniffSAK = data[0];
|
||||||
if (sniffUID[3] == 0x88) { // CL2 UID part to be expected
|
if ((sniffUID[3] == 0x88) && (sniffUIDType == SNF_UID_4)) { // CL2 UID part to be expected
|
||||||
sniffState = SNF_ANTICOL2;
|
sniffUIDType = SNF_UID_7;
|
||||||
|
memcpy(sniffUID, sniffUID + 4, 3);
|
||||||
|
sniffState = SNF_UID2;
|
||||||
} else { // select completed
|
} else { // select completed
|
||||||
sniffState = SNF_CARD_IDLE;
|
sniffState = SNF_CARD_IDLE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
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;
|
|
||||||
}
|
|
||||||
case SNF_UID2:{
|
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 == 9) && (data[0] == 0x95) && (data[1] == 0x70) && (CheckCrc14443(CRC_14443_A, data, 9))) {
|
||||||
|
memcpy(sniffUID + 3, &data[2], 4);
|
||||||
sniffState = SNF_SAK;
|
sniffState = SNF_SAK;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -123,17 +112,11 @@ bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint8_t *parity, ui
|
||||||
sniffBuf[11] = sniffSAK;
|
sniffBuf[11] = sniffSAK;
|
||||||
sniffBuf[12] = 0xFF;
|
sniffBuf[12] = 0xFF;
|
||||||
sniffBuf[13] = 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;
|
} // intentionally no break;
|
||||||
case SNF_CARD_CMD:{
|
case SNF_CARD_CMD:{
|
||||||
LogTrace(data, len, 0, 0, NULL, TRUE);
|
LogTrace(data, len, 0, 0, parity, reader);
|
||||||
sniffState = SNF_CARD_RESP;
|
|
||||||
timerData = GetTickCount();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SNF_CARD_RESP:{
|
|
||||||
LogTrace(data, len, 0, 0, NULL, FALSE);
|
|
||||||
sniffState = SNF_CARD_CMD;
|
|
||||||
timerData = GetTickCount();
|
timerData = GetTickCount();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -144,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) {
|
bool RAMFUNC MfSniffSend(uint16_t maxTimeoutMs) {
|
||||||
if (BigBuf_get_traceLen() && (GetTickCount() > timerData + maxTimeoutMs)) {
|
if (BigBuf_get_traceLen() && (GetTickCount() > timerData + maxTimeoutMs)) {
|
||||||
return intMfSniffSend();
|
return intMfSniffSend();
|
||||||
}
|
}
|
||||||
return FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// internal sending function. not a RAMFUNC.
|
// internal sending function. not a RAMFUNC.
|
||||||
|
@ -179,5 +162,5 @@ bool intMfSniffSend() {
|
||||||
|
|
||||||
clear_trace();
|
clear_trace();
|
||||||
|
|
||||||
return TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#define SNF_CARD_IDLE 9
|
#define SNF_CARD_IDLE 9
|
||||||
#define SNF_CARD_CMD 10
|
#define SNF_CARD_CMD 10
|
||||||
#define SNF_CARD_RESP 11
|
#define SNF_CARD_RESP 11
|
||||||
|
#define SNF_MAGIC_WUPC2 12
|
||||||
|
|
||||||
#define SNF_UID_4 0
|
#define SNF_UID_4 0
|
||||||
#define SNF_UID_7 0
|
#define SNF_UID_7 0
|
||||||
|
|
|
@ -405,29 +405,46 @@ int mifare_ultra_auth(uint8_t *keybytes){
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define MFU_MAX_RETRIES 5
|
||||||
int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData)
|
int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData)
|
||||||
{
|
{
|
||||||
uint16_t len;
|
uint16_t len;
|
||||||
uint8_t bt[2];
|
uint8_t bt[2];
|
||||||
uint8_t receivedAnswer[MAX_FRAME_SIZE];
|
uint8_t receivedAnswer[MAX_FRAME_SIZE];
|
||||||
uint8_t receivedAnswerPar[MAX_PARITY_SIZE];
|
uint8_t receivedAnswerPar[MAX_PARITY_SIZE];
|
||||||
|
uint8_t retries;
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
for (retries = 0; retries < MFU_MAX_RETRIES; retries++) {
|
||||||
len = mifare_sendcmd_short(NULL, 1, 0x30, blockNo, receivedAnswer, receivedAnswerPar, NULL);
|
len = mifare_sendcmd_short(NULL, 1, 0x30, blockNo, receivedAnswer, receivedAnswerPar, NULL);
|
||||||
if (len == 1) {
|
if (len == 1) {
|
||||||
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
|
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
|
||||||
return 1;
|
result = 1;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
if (len != 18) {
|
if (len != 18) {
|
||||||
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: card timeout. len: %x", len);
|
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: card timeout. len: %x", len);
|
||||||
return 2;
|
result = 2;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(bt, receivedAnswer + 16, 2);
|
memcpy(bt, receivedAnswer + 16, 2);
|
||||||
AppendCrc14443a(receivedAnswer, 16);
|
AppendCrc14443a(receivedAnswer, 16);
|
||||||
if (bt[0] != receivedAnswer[16] || bt[1] != receivedAnswer[17]) {
|
if (bt[0] != receivedAnswer[16] || bt[1] != receivedAnswer[17]) {
|
||||||
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd CRC response error.");
|
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd CRC response error.");
|
||||||
return 3;
|
result = 3;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No errors encountered; don't retry
|
||||||
|
result = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result != 0) {
|
||||||
|
Dbprintf("Cmd Error: too many retries; read failed");
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(blockData, receivedAnswer, 14);
|
memcpy(blockData, receivedAnswer, 14);
|
||||||
|
|
|
@ -24,8 +24,6 @@
|
||||||
#define CRYPT_REQUEST 2
|
#define CRYPT_REQUEST 2
|
||||||
#define AUTH_FIRST 0
|
#define AUTH_FIRST 0
|
||||||
#define AUTH_NESTED 2
|
#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
|
// mifare 4bit card answers
|
||||||
#define CARD_ACK 0x0A // 1010 - ACK
|
#define CARD_ACK 0x0A // 1010 - ACK
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
*
|
*
|
||||||
* This is free software: you can redistribute it and/or modify
|
* 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
|
* 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,
|
* This file is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef OPTIMIZED_CIPHER_H
|
||||||
#define OPTIMIZED_CIPHER_H
|
#define OPTIMIZED_CIPHER_H
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
|
@ -175,6 +175,7 @@ reswitch: switch (ch = (u_char)*fmt++) {
|
||||||
padc = '0';
|
padc = '0';
|
||||||
goto reswitch;
|
goto reswitch;
|
||||||
}
|
}
|
||||||
|
// intentionally fall through to next case
|
||||||
case '1': case '2': case '3': case '4':
|
case '1': case '2': case '3': case '4':
|
||||||
case '5': case '6': case '7': case '8': case '9':
|
case '5': case '6': case '7': case '8': case '9':
|
||||||
for (n = 0;; ++fmt) {
|
for (n = 0;; ++fmt) {
|
||||||
|
|
|
@ -452,27 +452,48 @@ uint32_t RAMFUNC GetCountSspClk(){
|
||||||
// 1us = 1.5ticks
|
// 1us = 1.5ticks
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
void StartTicks(void){
|
void StartTicks(void){
|
||||||
//initialization of the timer
|
// initialization of the timer
|
||||||
// tc1 is higher 0xFFFF0000
|
|
||||||
// tc0 is lower 0x0000FFFF
|
|
||||||
AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1);
|
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_TCB->TCB_BMR = AT91C_TCB_TC0XC0S_NONE | AT91C_TCB_TC1XC1S_TIOA0 | AT91C_TCB_TC2XC2S_NONE;
|
||||||
|
|
||||||
|
// disable TC0 and TC1 for re-configuration
|
||||||
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
|
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_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_WAVE | AT91C_TC_WAVESEL_UP_AUTO |
|
||||||
AT91C_TC_ACPC_SET | AT91C_TC_ASWTRG_SET;
|
AT91C_TC_ACPA_CLEAR | // RA comperator clears TIOA (carry bit)
|
||||||
AT91C_BASE_TC0->TC_RA = 1;
|
AT91C_TC_ACPC_SET | // RC comperator sets TIOA (carry bit)
|
||||||
AT91C_BASE_TC0->TC_RC = 0;
|
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
|
||||||
|
|
||||||
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; // timer disable
|
// synchronized startup procedure
|
||||||
AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_XC1; // from TC0
|
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)
|
||||||
|
|
||||||
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
|
// return to zero
|
||||||
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
|
AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG;
|
||||||
AT91C_BASE_TCB->TCB_BCR = 1;
|
AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
|
||||||
|
while (AT91C_BASE_TC0->TC_CV > 0);
|
||||||
|
}
|
||||||
|
|
||||||
// wait until timer becomes zero.
|
|
||||||
while (AT91C_BASE_TC1->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...
|
// if called with a high number, this will trigger the WDT...
|
||||||
void WaitTicks(uint32_t ticks){
|
void WaitTicks(uint32_t ticks){
|
||||||
if ( ticks == 0 ) return;
|
if ( ticks == 0 ) return;
|
||||||
ticks += GET_TICKS;
|
ticks += GetTicks();
|
||||||
while (GET_TICKS < ticks);
|
while (GetTicks() < ticks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Wait / Spindelay in us (microseconds)
|
// Wait / Spindelay in us (microseconds)
|
||||||
// 1us = 1.5ticks.
|
// 1us = 1.5ticks.
|
||||||
void WaitUS(uint16_t us){
|
void WaitUS(uint16_t us){
|
||||||
if ( us == 0 ) return;
|
WaitTicks( (uint32_t)us * 3 / 2 ) ;
|
||||||
WaitTicks( (uint32_t)(us * 1.5) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void WaitMS(uint16_t ms){
|
void WaitMS(uint16_t ms){
|
||||||
if (ms == 0) return;
|
WaitTicks( (uint32_t)ms * 1500 );
|
||||||
WaitTicks( (uint32_t)(ms * 1500) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Starts Clock and waits until its reset
|
// Starts Clock and waits until its reset
|
||||||
void ResetTicks(void){
|
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;
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,7 @@ void FormatVersionInformation(char *dst, int len, const char *prefix, void *vers
|
||||||
|
|
||||||
//iceman's ticks.h
|
//iceman's ticks.h
|
||||||
#ifndef GET_TICKS
|
#ifndef GET_TICKS
|
||||||
# define GET_TICKS (uint32_t)((AT91C_BASE_TC1->TC_CV << 16) | AT91C_BASE_TC0->TC_CV)
|
# define GET_TICKS GetTicks()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void SpinDelay(int ms);
|
void SpinDelay(int ms);
|
||||||
|
@ -62,6 +62,7 @@ void ResetSspClk(void);
|
||||||
uint32_t RAMFUNC GetCountSspClk();
|
uint32_t RAMFUNC GetCountSspClk();
|
||||||
|
|
||||||
extern void StartTicks(void);
|
extern void StartTicks(void);
|
||||||
|
extern uint32_t GetTicks(void);
|
||||||
extern void WaitTicks(uint32_t ticks);
|
extern void WaitTicks(uint32_t ticks);
|
||||||
extern void WaitUS(uint16_t us);
|
extern void WaitUS(uint16_t us);
|
||||||
extern void WaitMS(uint16_t ms);
|
extern void WaitMS(uint16_t ms);
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
ARMSRC =
|
ARMSRC =
|
||||||
THUMBSRC = cmd.c usb_cdc.c bootrom.c
|
THUMBSRC = cmd.c usb_cdc.c bootrom.c
|
||||||
ASMSRC = ram-reset.s flash-reset.s
|
ASMSRC = ram-reset.s flash-reset.s
|
||||||
|
VERSIONSRC = version.c
|
||||||
|
|
||||||
## There is a strange bug with the linker: Sometimes it will not emit the glue to call
|
## 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
|
## BootROM from ARM mode. The symbol is emitted, but the section will be filled with
|
||||||
|
@ -21,6 +22,11 @@ ASMSRC = ram-reset.s flash-reset.s
|
||||||
# stdint.h provided locally until GCC 4.5 becomes C99 compliant
|
# stdint.h provided locally until GCC 4.5 becomes C99 compliant
|
||||||
APP_CFLAGS = -I.
|
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
|
# Do not move this inclusion before the definition of {THUMB,ASM,ARM}SRC
|
||||||
include ../common/Makefile.common
|
include ../common/Makefile.common
|
||||||
|
|
||||||
|
|
|
@ -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
|
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
|
CXXFLAGS = -I../include -Wall -O3
|
||||||
|
|
||||||
|
APP_CFLAGS =
|
||||||
|
include ../common/Makefile_Enabled_Options.common
|
||||||
|
CFLAGS += $(APP_CFLAGS)
|
||||||
|
|
||||||
LUAPLATFORM = generic
|
LUAPLATFORM = generic
|
||||||
platform = $(shell uname)
|
platform = $(shell uname)
|
||||||
ifneq (,$(findstring MINGW,$(platform)))
|
ifneq (,$(findstring MINGW,$(platform)))
|
||||||
|
@ -37,22 +41,23 @@ else
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Check for correctly configured Qt5
|
ifneq (,$(findstring WITH_GUI,$(APP_CFLAGS)))
|
||||||
QTINCLUDES = $(shell pkg-config --cflags Qt5Core Qt5Widgets 2>/dev/null)
|
# Check for correctly configured Qt5
|
||||||
QTLDLIBS = $(shell pkg-config --libs Qt5Core Qt5Widgets 2>/dev/null)
|
QTINCLUDES = $(shell pkg-config --cflags Qt5Core Qt5Widgets 2>/dev/null)
|
||||||
MOC = $(shell pkg-config --variable=host_bins Qt5Core)/moc
|
QTLDLIBS = $(shell pkg-config --libs Qt5Core Qt5Widgets 2>/dev/null)
|
||||||
UIC = $(shell pkg-config --variable=host_bins Qt5Core)/uic
|
MOC = $(shell pkg-config --variable=host_bins Qt5Core)/moc
|
||||||
ifeq ($(QTINCLUDES), )
|
UIC = $(shell pkg-config --variable=host_bins Qt5Core)/uic
|
||||||
# if Qt5 not found check for correctly configured Qt4
|
ifeq ($(QTINCLUDES), )
|
||||||
|
# if Qt5 not found check for correctly configured Qt4
|
||||||
QTINCLUDES = $(shell pkg-config --cflags QtCore QtGui 2>/dev/null)
|
QTINCLUDES = $(shell pkg-config --cflags QtCore QtGui 2>/dev/null)
|
||||||
QTLDLIBS = $(shell pkg-config --libs QtCore QtGui 2>/dev/null)
|
QTLDLIBS = $(shell pkg-config --libs QtCore QtGui 2>/dev/null)
|
||||||
MOC = $(shell pkg-config --variable=moc_location QtCore)
|
MOC = $(shell pkg-config --variable=moc_location QtCore)
|
||||||
UIC = $(shell pkg-config --variable=uic_location QtCore)
|
UIC = $(shell pkg-config --variable=uic_location QtCore)
|
||||||
else
|
else
|
||||||
CXXFLAGS += -std=c++11 -fPIC
|
CXXFLAGS += -std=c++11 -fPIC
|
||||||
endif
|
endif
|
||||||
ifeq ($(QTINCLUDES), )
|
ifeq ($(QTINCLUDES), )
|
||||||
# if both pkg-config commands failed, search in common places
|
# if both pkg-config commands failed, search in common places
|
||||||
ifneq ($(QTDIR), )
|
ifneq ($(QTDIR), )
|
||||||
QTINCLUDES = -I$(QTDIR)/include -I$(QTDIR)/include/QtCore -I$(QTDIR)/include/QtGui
|
QTINCLUDES = -I$(QTDIR)/include -I$(QTDIR)/include/QtCore -I$(QTDIR)/include/QtGui
|
||||||
QTLDLIBS = -L$(QTDIR)/lib -lQtCore4 -lQtGui4
|
QTLDLIBS = -L$(QTDIR)/lib -lQtCore4 -lQtGui4
|
||||||
|
@ -64,6 +69,7 @@ ifeq ($(QTINCLUDES), )
|
||||||
MOC = $(QTDIR)/bin/moc
|
MOC = $(QTDIR)/bin/moc
|
||||||
UIC = $(QTDIR)/bin/uic
|
UIC = $(QTDIR)/bin/uic
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -79,10 +85,13 @@ DEPFLAGS = -MT $@ -MMD -MP -MF $(OBJDIR)/$*.Td
|
||||||
# make temporary to final dependeny files after successful compilation
|
# make temporary to final dependeny files after successful compilation
|
||||||
POSTCOMPILE = $(MV) -f $(OBJDIR)/$*.Td $(OBJDIR)/$*.d
|
POSTCOMPILE = $(MV) -f $(OBJDIR)/$*.Td $(OBJDIR)/$*.d
|
||||||
|
|
||||||
|
|
||||||
CORESRCS = uart_posix.c \
|
CORESRCS = uart_posix.c \
|
||||||
uart_win32.c \
|
uart_win32.c \
|
||||||
util.c \
|
util.c \
|
||||||
util_posix.c
|
util_posix.c \
|
||||||
|
ui.c \
|
||||||
|
comms.c
|
||||||
|
|
||||||
CMDSRCS = crapto1/crapto1.c\
|
CMDSRCS = crapto1/crapto1.c\
|
||||||
crapto1/crypto1.c\
|
crapto1/crypto1.c\
|
||||||
|
@ -107,9 +116,7 @@ CMDSRCS = crapto1/crapto1.c\
|
||||||
crc64.c \
|
crc64.c \
|
||||||
iso14443crc.c \
|
iso14443crc.c \
|
||||||
iso15693tools.c \
|
iso15693tools.c \
|
||||||
data.c \
|
|
||||||
graph.c \
|
graph.c \
|
||||||
ui.c \
|
|
||||||
cmddata.c \
|
cmddata.c \
|
||||||
lfdemod.c \
|
lfdemod.c \
|
||||||
emv/crypto_polarssl.c\
|
emv/crypto_polarssl.c\
|
||||||
|
@ -130,6 +137,7 @@ CMDSRCS = crapto1/crapto1.c\
|
||||||
emv/test/cda_test.c\
|
emv/test/cda_test.c\
|
||||||
emv/cmdemv.c\
|
emv/cmdemv.c\
|
||||||
cmdhf.c \
|
cmdhf.c \
|
||||||
|
cmdhflist.c \
|
||||||
cmdhf14a.c \
|
cmdhf14a.c \
|
||||||
cmdhf14b.c \
|
cmdhf14b.c \
|
||||||
cmdhf15.c \
|
cmdhf15.c \
|
||||||
|
@ -171,14 +179,7 @@ CMDSRCS = crapto1/crapto1.c\
|
||||||
cmdscript.c\
|
cmdscript.c\
|
||||||
pm3_binlib.c\
|
pm3_binlib.c\
|
||||||
pm3_bitlib.c\
|
pm3_bitlib.c\
|
||||||
protocols.c\
|
protocols.c
|
||||||
cmdcrc.c\
|
|
||||||
reveng/reveng.c\
|
|
||||||
reveng/cli.c\
|
|
||||||
reveng/bmpbit.c\
|
|
||||||
reveng/model.c\
|
|
||||||
reveng/poly.c\
|
|
||||||
#reveng/getopt.c\
|
|
||||||
|
|
||||||
cpu_arch = $(shell uname -m)
|
cpu_arch = $(shell uname -m)
|
||||||
ifneq ($(findstring 86, $(cpu_arch)), )
|
ifneq ($(findstring 86, $(cpu_arch)), )
|
||||||
|
@ -311,6 +312,7 @@ DEPENDENCY_FILES = $(patsubst %.c, $(OBJDIR)/%.d, $(CORESRCS) $(CMDSRCS) $(ZLIBS
|
||||||
$(patsubst %.cpp, $(OBJDIR)/%.d, $(QTGUISRCS)) \
|
$(patsubst %.cpp, $(OBJDIR)/%.d, $(QTGUISRCS)) \
|
||||||
$(OBJDIR)/proxmark3.d $(OBJDIR)/flash.d $(OBJDIR)/flasher.d $(OBJDIR)/fpga_compress.d
|
$(OBJDIR)/proxmark3.d $(OBJDIR)/flash.d $(OBJDIR)/flasher.d $(OBJDIR)/fpga_compress.d
|
||||||
|
|
||||||
|
|
||||||
$(DEPENDENCY_FILES): ;
|
$(DEPENDENCY_FILES): ;
|
||||||
.PRECIOUS: $(DEPENDENCY_FILES)
|
.PRECIOUS: $(DEPENDENCY_FILES)
|
||||||
|
|
||||||
|
|
547
client/cmdcrc.c
547
client/cmdcrc.c
|
@ -1,547 +0,0 @@
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Copyright (C) 2015 iceman <iceman at iuse.se>
|
|
||||||
//
|
|
||||||
// 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 <io.h>
|
|
||||||
# include <fcntl.h>
|
|
||||||
# ifndef STDIN_FILENO
|
|
||||||
# define STDIN_FILENO 0
|
|
||||||
# endif /* STDIN_FILENO */
|
|
||||||
#endif /* _WIN32 */
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#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;
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Copyright (C) 2015 iceman <iceman at iuse.se>
|
|
||||||
//
|
|
||||||
// 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
|
|
|
@ -8,15 +8,15 @@
|
||||||
// Data and Graph commands
|
// Data and Graph commands
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "cmddata.h"
|
||||||
|
|
||||||
#include <stdio.h> // also included in util.h
|
#include <stdio.h> // also included in util.h
|
||||||
#include <string.h> // also included in util.h
|
#include <string.h> // also included in util.h
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <limits.h> // for CmdNorm INT_MIN && INT_MAX
|
#include <limits.h> // for CmdNorm INT_MIN && INT_MAX
|
||||||
#include "data.h" // also included in util.h
|
|
||||||
#include "cmddata.h"
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "cmdmain.h"
|
#include "cmdmain.h"
|
||||||
#include "proxmark3.h"
|
#include "comms.h"
|
||||||
#include "ui.h" // for show graph controls
|
#include "ui.h" // for show graph controls
|
||||||
#include "graph.h" // for graph data
|
#include "graph.h" // for graph data
|
||||||
#include "cmdparser.h"// already included in cmdmain.h
|
#include "cmdparser.h"// already included in cmdmain.h
|
||||||
|
@ -591,8 +591,7 @@ int CmdBitsamples(const char *Cmd)
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
uint8_t got[12288];
|
uint8_t got[12288];
|
||||||
|
|
||||||
GetFromBigBuf(got,sizeof(got),0);
|
GetFromBigBuf(got, sizeof(got), 0 , NULL, -1, false);
|
||||||
WaitForResponse(CMD_ACK,NULL);
|
|
||||||
|
|
||||||
for (int j = 0; j < sizeof(got); j++) {
|
for (int j = 0; j < sizeof(got); j++) {
|
||||||
for (int k = 0; k < 8; k++) {
|
for (int k = 0; k < 8; k++) {
|
||||||
|
@ -1131,8 +1130,7 @@ int CmdHexsamples(const char *Cmd)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
GetFromBigBuf(got,requested,offset);
|
GetFromBigBuf(got, requested, offset, NULL, -1, false);
|
||||||
WaitForResponse(CMD_ACK,NULL);
|
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
for (j = 0; j < requested; j++) {
|
for (j = 0; j < requested; j++) {
|
||||||
|
@ -1200,10 +1198,9 @@ int getSamples(int n, bool silent)
|
||||||
n = sizeof(got);
|
n = sizeof(got);
|
||||||
|
|
||||||
if (!silent) PrintAndLog("Reading %d bytes from device memory\n", n);
|
if (!silent) PrintAndLog("Reading %d bytes from device memory\n", n);
|
||||||
GetFromBigBuf(got,n,0);
|
|
||||||
if (!silent) PrintAndLog("Data fetched");
|
|
||||||
UsbCommand response;
|
UsbCommand response;
|
||||||
WaitForResponse(CMD_ACK, &response);
|
GetFromBigBuf(got, n, 0, &response, -1, false);
|
||||||
|
if (!silent) PrintAndLog("Data fetched");
|
||||||
uint8_t bits_per_sample = 8;
|
uint8_t bits_per_sample = 8;
|
||||||
|
|
||||||
//Old devices without this feature would send 0 at arg[0]
|
//Old devices without this feature would send 0 at arg[0]
|
||||||
|
@ -1281,26 +1278,36 @@ int CmdTuneSamples(const char *Cmd)
|
||||||
peakf = resp.arg[2] & 0xffff;
|
peakf = resp.arg[2] & 0xffff;
|
||||||
peakv = resp.arg[2] >> 16;
|
peakv = resp.arg[2] >> 16;
|
||||||
PrintAndLog("");
|
PrintAndLog("");
|
||||||
PrintAndLog("# LF antenna: %5.2f V @ 125.00 kHz", vLf125/1000.0);
|
if (arg & FLAG_TUNE_LF)
|
||||||
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));
|
||||||
|
}
|
||||||
|
if (arg & FLAG_TUNE_HF)
|
||||||
PrintAndLog("# HF antenna: %5.2f V @ 13.56 MHz", vHf/1000.0);
|
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_UNUSABLE_V 3000
|
||||||
#define LF_MARGINAL_V 14739 // was 10000. Changed due to bugfix bug in voltage measurements. LF results are now 47% higher.
|
#define LF_MARGINAL_V 15000
|
||||||
#define HF_UNUSABLE_V 3167 // was 2000. Changed due to bugfix in voltage measurements. HF results are now 58% higher.
|
#define HF_UNUSABLE_V 3200
|
||||||
#define HF_MARGINAL_V 7917 // was 5000. Changed due to bugfix in voltage measurements. HF results are now 58% higher.
|
#define HF_MARGINAL_V 8000
|
||||||
|
|
||||||
if (peakv < LF_UNUSABLE_V)
|
if (arg & FLAG_TUNE_LF)
|
||||||
|
{
|
||||||
|
if (peakv<<1 < LF_UNUSABLE_V)
|
||||||
PrintAndLog("# Your LF antenna is unusable.");
|
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.");
|
PrintAndLog("# Your LF antenna is marginal.");
|
||||||
|
}
|
||||||
|
if (arg & FLAG_TUNE_HF)
|
||||||
|
{
|
||||||
if (vHf < HF_UNUSABLE_V)
|
if (vHf < HF_UNUSABLE_V)
|
||||||
PrintAndLog("# Your HF antenna is unusable.");
|
PrintAndLog("# Your HF antenna is unusable.");
|
||||||
else if (vHf < HF_MARGINAL_V)
|
else if (vHf < HF_MARGINAL_V)
|
||||||
PrintAndLog("# Your HF antenna is marginal.");
|
PrintAndLog("# Your HF antenna is marginal.");
|
||||||
|
}
|
||||||
|
|
||||||
if (peakv >= LF_UNUSABLE_V) {
|
if (peakv<<1 >= LF_UNUSABLE_V) {
|
||||||
for (int i = 0; i < 256; i++) {
|
for (int i = 0; i < 256; i++) {
|
||||||
GraphBuffer[i] = resp.d.asBytes[i] - 128;
|
GraphBuffer[i] = resp.d.asBytes[i] - 128;
|
||||||
}
|
}
|
||||||
|
|
400
client/cmdhf.c
400
client/cmdhf.c
|
@ -1,5 +1,6 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Copyright (C) 2010 iZsh <izsh at fail0verflow.com>
|
// Copyright (C) 2010 iZsh <izsh at fail0verflow.com>
|
||||||
|
// Merlok - 2017
|
||||||
//
|
//
|
||||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
// 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
|
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||||
|
@ -8,18 +9,18 @@
|
||||||
// High frequency commands
|
// High frequency commands
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "cmdhf.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "proxmark3.h"
|
#include "comms.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "data.h"
|
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
#include "iso14443crc.h"
|
#include "iso14443crc.h"
|
||||||
#include "parity.h"
|
#include "parity.h"
|
||||||
#include "cmdmain.h"
|
#include "cmdmain.h"
|
||||||
#include "cmdparser.h"
|
#include "cmdparser.h"
|
||||||
#include "cmdhf.h"
|
|
||||||
#include "cmdhf14a.h"
|
#include "cmdhf14a.h"
|
||||||
#include "cmdhf14b.h"
|
#include "cmdhf14b.h"
|
||||||
#include "cmdhf15.h"
|
#include "cmdhf15.h"
|
||||||
|
@ -31,6 +32,7 @@
|
||||||
#include "cmdhftopaz.h"
|
#include "cmdhftopaz.h"
|
||||||
#include "protocols.h"
|
#include "protocols.h"
|
||||||
#include "emv/cmdemv.h"
|
#include "emv/cmdemv.h"
|
||||||
|
#include "cmdhflist.h"
|
||||||
|
|
||||||
static int CmdHelp(const char *Cmd);
|
static int CmdHelp(const char *Cmd);
|
||||||
|
|
||||||
|
@ -41,236 +43,6 @@ int CmdHFTune(const char *Cmd)
|
||||||
return 0;
|
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])
|
|
||||||
{
|
|
||||||
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 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
|
* @brief iso14443B_CRC_check Checks CRC in command or response
|
||||||
* @param isResponse
|
* @param isResponse
|
||||||
|
@ -418,6 +190,8 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui
|
||||||
uint8_t topaz_reader_command[9];
|
uint8_t topaz_reader_command[9];
|
||||||
uint32_t timestamp, first_timestamp, EndOfTransmissionTimestamp;
|
uint32_t timestamp, first_timestamp, EndOfTransmissionTimestamp;
|
||||||
char explanation[30] = {0};
|
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;
|
if (tracepos + sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t) > traceLen) return traceLen;
|
||||||
|
|
||||||
|
@ -466,6 +240,9 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui
|
||||||
case TOPAZ:
|
case TOPAZ:
|
||||||
crcStatus = iso14443B_CRC_check(isResponse, frame, data_len);
|
crcStatus = iso14443B_CRC_check(isResponse, frame, data_len);
|
||||||
break;
|
break;
|
||||||
|
case PROTO_MIFARE:
|
||||||
|
crcStatus = mifare_CRC_check(isResponse, frame, data_len);
|
||||||
|
break;
|
||||||
case ISO_14443A:
|
case ISO_14443A:
|
||||||
crcStatus = iso14443A_CRC_check(isResponse, frame, data_len);
|
crcStatus = iso14443A_CRC_check(isResponse, frame, data_len);
|
||||||
break;
|
break;
|
||||||
|
@ -514,6 +291,9 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui
|
||||||
|
|
||||||
EndOfTransmissionTimestamp = timestamp + duration;
|
EndOfTransmissionTimestamp = timestamp + duration;
|
||||||
|
|
||||||
|
if (protocol == PROTO_MIFARE)
|
||||||
|
annotateMifare(explanation, sizeof(explanation), frame, data_len, parityBytes, parity_len, isResponse);
|
||||||
|
|
||||||
if(!isResponse)
|
if(!isResponse)
|
||||||
{
|
{
|
||||||
switch(protocol) {
|
switch(protocol) {
|
||||||
|
@ -543,6 +323,19 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (DecodeMifareData(frame, data_len, parityBytes, isResponse, 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 : "");
|
||||||
|
};
|
||||||
|
|
||||||
if (is_last_record(tracepos, trace, traceLen)) return traceLen;
|
if (is_last_record(tracepos, trace, traceLen)) return traceLen;
|
||||||
|
|
||||||
if (showWaitCycles && !isResponse && next_record_is_response(tracepos, trace)) {
|
if (showWaitCycles && !isResponse && next_record_is_response(tracepos, trace)) {
|
||||||
|
@ -562,75 +355,150 @@ int CmdHFList(const char *Cmd)
|
||||||
{
|
{
|
||||||
bool showWaitCycles = false;
|
bool showWaitCycles = false;
|
||||||
bool markCRCBytes = false;
|
bool markCRCBytes = false;
|
||||||
|
bool loadFromFile = false;
|
||||||
|
bool saveToFile = false;
|
||||||
|
char param1 = '\0';
|
||||||
|
char param2 = '\0';
|
||||||
|
char param3 = '\0';
|
||||||
char type[40] = {0};
|
char type[40] = {0};
|
||||||
int tlen = param_getstr(Cmd,0,type, sizeof(type));
|
char filename[FILE_PATH_SIZE] = {0};
|
||||||
char param1 = param_getchar(Cmd, 1);
|
|
||||||
char param2 = param_getchar(Cmd, 2);
|
|
||||||
bool errors = false;
|
|
||||||
uint8_t protocol = 0;
|
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) {
|
if(tlen == 0) {
|
||||||
errors = true;
|
errors = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(param1 == 'h'
|
if(param1 == 'h'
|
||||||
|| (param1 != 0 && param1 != 'f' && param1 != 'c')
|
|| (param1 != 0 && param1 != 'f' && param1 != 'c' && param1 != 'l')
|
||||||
|| (param2 != 0 && param2 != 'f' && param2 != 'c')) {
|
|| (param2 != 0 && param2 != 'f' && param2 != 'c' && param2 != 'l')
|
||||||
|
|| (param3 != 0 && param3 != 'f' && param3 != 'c' && param3 != 'l')) {
|
||||||
errors = true;
|
errors = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!errors) {
|
if(!errors) {
|
||||||
if(strcmp(type, "iclass") == 0) {
|
if(strcmp(type, "iclass") == 0) {
|
||||||
protocol = ICLASS;
|
protocol = ICLASS;
|
||||||
|
} else if(strcmp(type, "mf") == 0) {
|
||||||
|
protocol = PROTO_MIFARE;
|
||||||
} else if(strcmp(type, "14a") == 0) {
|
} else if(strcmp(type, "14a") == 0) {
|
||||||
protocol = ISO_14443A;
|
protocol = ISO_14443A;
|
||||||
} else if(strcmp(type, "14b") == 0) {
|
} else if(strcmp(type, "14b") == 0) {
|
||||||
protocol = ISO_14443B;
|
protocol = ISO_14443B;
|
||||||
} else if(strcmp(type,"topaz")== 0) {
|
} else if(strcmp(type,"topaz") == 0) {
|
||||||
protocol = TOPAZ;
|
protocol = TOPAZ;
|
||||||
} else if(strcmp(type,"raw")== 0) {
|
} else if(strcmp(type,"raw") == 0) {
|
||||||
protocol = -1;//No crc, no annotations
|
protocol = -1; //No crc, no annotations
|
||||||
|
} else if (strcmp(type, "save") == 0) {
|
||||||
|
saveToFile = true;
|
||||||
} else {
|
} else {
|
||||||
errors = true;
|
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) {
|
if (errors) {
|
||||||
PrintAndLog("List protocol data in trace buffer.");
|
PrintAndLog("List or save protocol data.");
|
||||||
PrintAndLog("Usage: hf list <protocol> [f][c]");
|
PrintAndLog("Usage: hf list <protocol> [f] [c] [l <filename>]");
|
||||||
|
PrintAndLog(" hf list save <filename>");
|
||||||
PrintAndLog(" f - show frame delay times as well");
|
PrintAndLog(" f - show frame delay times as well");
|
||||||
PrintAndLog(" c - mark CRC bytes");
|
PrintAndLog(" c - mark CRC bytes");
|
||||||
|
PrintAndLog(" l - load data from file instead of trace buffer");
|
||||||
|
PrintAndLog(" save - save data to file");
|
||||||
PrintAndLog("Supported <protocol> values:");
|
PrintAndLog("Supported <protocol> values:");
|
||||||
PrintAndLog(" raw - just show raw data without annotations");
|
PrintAndLog(" raw - just show raw data without annotations");
|
||||||
PrintAndLog(" 14a - interpret data as iso14443a communications");
|
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(" 14b - interpret data as iso14443b communications");
|
||||||
PrintAndLog(" iclass - interpret data as iclass communications");
|
PrintAndLog(" iclass - interpret data as iclass communications");
|
||||||
PrintAndLog(" topaz - interpret data as topaz communications");
|
PrintAndLog(" topaz - interpret data as topaz communications");
|
||||||
PrintAndLog("");
|
PrintAndLog("");
|
||||||
PrintAndLog("example: hf list 14a f");
|
PrintAndLog("example: hf list 14a f");
|
||||||
PrintAndLog("example: hf list iclass");
|
PrintAndLog("example: hf list iclass");
|
||||||
|
PrintAndLog("example: hf list save myCardTrace.trc");
|
||||||
|
PrintAndLog("example: hf list 14a l myCardTrace.trc");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (param1 == 'f' || param2 == 'f') {
|
|
||||||
showWaitCycles = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (param1 == 'c' || param2 == 'c') {
|
|
||||||
markCRCBytes = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t *trace;
|
uint8_t *trace;
|
||||||
uint16_t tracepos = 0;
|
uint32_t tracepos = 0;
|
||||||
trace = malloc(USB_CMD_DATA_SIZE);
|
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");
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
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
|
// Query for the size of the trace
|
||||||
UsbCommand response;
|
UsbCommand response;
|
||||||
GetFromBigBuf(trace, USB_CMD_DATA_SIZE, 0);
|
GetFromBigBuf(trace, USB_CMD_DATA_SIZE, 0, &response, -1, false);
|
||||||
WaitForResponse(CMD_ACK, &response);
|
traceLen = response.arg[2];
|
||||||
uint16_t traceLen = response.arg[2];
|
|
||||||
if (traceLen > USB_CMD_DATA_SIZE) {
|
if (traceLen > USB_CMD_DATA_SIZE) {
|
||||||
uint8_t *p = realloc(trace, traceLen);
|
uint8_t *p = realloc(trace, traceLen);
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
|
@ -639,10 +507,20 @@ int CmdHFList(const char *Cmd)
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
trace = p;
|
trace = p;
|
||||||
GetFromBigBuf(trace, traceLen, 0);
|
GetFromBigBuf(trace, traceLen, 0, NULL, -1, false);
|
||||||
WaitForResponse(CMD_ACK, NULL);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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("Recorded Activity (TraceLen = %d bytes)", traceLen);
|
||||||
PrintAndLog("");
|
PrintAndLog("");
|
||||||
PrintAndLog("Start = Start of Start Bit, End = End of last modulation. Src = Source of Transfer");
|
PrintAndLog("Start = Start of Start Bit, End = End of last modulation. Src = Source of Transfer");
|
||||||
|
@ -652,10 +530,12 @@ int CmdHFList(const char *Cmd)
|
||||||
PrintAndLog(" Start | End | Src | Data (! denotes parity error) | CRC | Annotation |");
|
PrintAndLog(" Start | End | Src | Data (! denotes parity error) | CRC | Annotation |");
|
||||||
PrintAndLog("------------|------------|-----|-----------------------------------------------------------------|-----|--------------------|");
|
PrintAndLog("------------|------------|-----|-----------------------------------------------------------------|-----|--------------------|");
|
||||||
|
|
||||||
|
ClearAuthData();
|
||||||
while(tracepos < traceLen)
|
while(tracepos < traceLen)
|
||||||
{
|
{
|
||||||
tracepos = printTraceLine(tracepos, traceLen, trace, protocol, showWaitCycles, markCRCBytes);
|
tracepos = printTraceLine(tracepos, traceLen, trace, protocol, showWaitCycles, markCRCBytes);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
free(trace);
|
free(trace);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -20,8 +20,7 @@
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "util_posix.h"
|
#include "util_posix.h"
|
||||||
#include "iso14443crc.h"
|
#include "iso14443crc.h"
|
||||||
#include "data.h"
|
#include "comms.h"
|
||||||
#include "proxmark3.h"
|
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
#include "cmdparser.h"
|
#include "cmdparser.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
@ -36,8 +35,13 @@
|
||||||
static int CmdHelp(const char *Cmd);
|
static int CmdHelp(const char *Cmd);
|
||||||
static int waitCmd(uint8_t iLen);
|
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"
|
// ID, "Vendor Country"
|
||||||
{ 0x01, "Motorola UK" },
|
{ 0x01, "Motorola UK" },
|
||||||
{ 0x02, "ST Microelectronics SA France" },
|
{ 0x02, "ST Microelectronics SA France" },
|
||||||
|
@ -187,7 +191,7 @@ int CmdHF14AReader(const char *Cmd) {
|
||||||
|
|
||||||
PrintAndLog(" UID : %s", sprint_hex(card.uid, card.uidlen));
|
PrintAndLog(" UID : %s", sprint_hex(card.uid, card.uidlen));
|
||||||
PrintAndLog("ATQA : %02x %02x", card.atqa[1], card.atqa[0]);
|
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
|
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));
|
PrintAndLog(" ATS : %s", sprint_hex(card.ats, card.ats_len));
|
||||||
}
|
}
|
||||||
|
@ -239,7 +243,7 @@ int CmdHF14AInfo(const char *Cmd)
|
||||||
|
|
||||||
PrintAndLog(" UID : %s", sprint_hex(card.uid, card.uidlen));
|
PrintAndLog(" UID : %s", sprint_hex(card.uid, card.uidlen));
|
||||||
PrintAndLog("ATQA : %02x %02x", card.atqa[1], card.atqa[0]);
|
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;
|
bool isMifareClassic = true;
|
||||||
switch (card.sak) {
|
switch (card.sak) {
|
||||||
|
@ -477,12 +481,12 @@ int CmdHF14AInfo(const char *Cmd)
|
||||||
|
|
||||||
|
|
||||||
// try to see if card responses to "chinese magic backdoor" commands.
|
// try to see if card responses to "chinese magic backdoor" commands.
|
||||||
mfCIdentify();
|
(void)mfCIdentify();
|
||||||
|
|
||||||
if (isMifareClassic) {
|
if (isMifareClassic) {
|
||||||
switch(DetectClassicPrng()) {
|
switch(DetectClassicPrng()) {
|
||||||
case 0:
|
case 0:
|
||||||
PrintAndLog("Prng detection: HARDEND (hardnested)");
|
PrintAndLog("Prng detection: HARDENED (hardnested)");
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
PrintAndLog("Prng detection: WEAK");
|
PrintAndLog("Prng detection: WEAK");
|
||||||
|
@ -949,10 +953,7 @@ static command_t CommandTable[] =
|
||||||
};
|
};
|
||||||
|
|
||||||
int CmdHF14A(const char *Cmd) {
|
int CmdHF14A(const char *Cmd) {
|
||||||
// flush
|
(void)WaitForResponseTimeout(CMD_ACK,NULL,100);
|
||||||
WaitForResponseTimeout(CMD_ACK,NULL,100);
|
|
||||||
|
|
||||||
// parse
|
|
||||||
CmdsParse(CommandTable, Cmd);
|
CmdsParse(CommandTable, Cmd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,12 +15,6 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
// structure and database for uid -> tagtype lookups
|
|
||||||
typedef struct {
|
|
||||||
uint8_t uid;
|
|
||||||
char* desc;
|
|
||||||
} manufactureName;
|
|
||||||
|
|
||||||
int CmdHF14A(const char *Cmd);
|
int CmdHF14A(const char *Cmd);
|
||||||
int CmdHF14AList(const char *Cmd);
|
int CmdHF14AList(const char *Cmd);
|
||||||
int CmdHF14AMifare(const char *Cmd);
|
int CmdHF14AMifare(const char *Cmd);
|
||||||
|
|
|
@ -8,19 +8,19 @@
|
||||||
// High frequency ISO14443B commands
|
// High frequency ISO14443B commands
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "cmdhf14b.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "iso14443crc.h"
|
#include "iso14443crc.h"
|
||||||
#include "proxmark3.h"
|
#include "comms.h"
|
||||||
#include "data.h"
|
|
||||||
#include "graph.h"
|
#include "graph.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
#include "cmdparser.h"
|
#include "cmdparser.h"
|
||||||
#include "cmdhf14b.h"
|
|
||||||
#include "cmdmain.h"
|
#include "cmdmain.h"
|
||||||
#include "cmdhf14a.h"
|
#include "cmdhf14a.h"
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
#ifndef CMDHF14B_H__
|
#ifndef CMDHF14B_H__
|
||||||
#define CMDHF14B_H__
|
#define CMDHF14B_H__
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
int CmdHF14B(const char *Cmd);
|
int CmdHF14B(const char *Cmd);
|
||||||
int CmdHF14BList(const char *Cmd);
|
int CmdHF14BList(const char *Cmd);
|
||||||
int CmdHF14BInfo(const char *Cmd);
|
int CmdHF14BInfo(const char *Cmd);
|
||||||
|
|
|
@ -22,18 +22,18 @@
|
||||||
// the client. Signal Processing & decoding is done on the pc. This is the slowest
|
// the client. Signal Processing & decoding is done on the pc. This is the slowest
|
||||||
// variant, but offers the possibility to analyze the waveforms directly.
|
// variant, but offers the possibility to analyze the waveforms directly.
|
||||||
|
|
||||||
|
#include "cmdhf15.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "proxmark3.h"
|
#include "comms.h"
|
||||||
#include "data.h"
|
|
||||||
#include "graph.h"
|
#include "graph.h"
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "cmdparser.h"
|
#include "cmdparser.h"
|
||||||
#include "cmdhf15.h"
|
|
||||||
#include "iso15693tools.h"
|
#include "iso15693tools.h"
|
||||||
#include "cmdmain.h"
|
#include "cmdmain.h"
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
#ifndef CMDHF15_H__
|
#ifndef CMDHF15_H__
|
||||||
#define CMDHF15_H__
|
#define CMDHF15_H__
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
int CmdHF15(const char *Cmd);
|
int CmdHF15(const char *Cmd);
|
||||||
|
|
||||||
int CmdHF15Demod(const char *Cmd);
|
int CmdHF15Demod(const char *Cmd);
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "util_posix.h"
|
#include "util_posix.h"
|
||||||
#include "proxmark3.h"
|
#include "comms.h"
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
#include "cmdparser.h"
|
#include "cmdparser.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
@ -202,10 +202,7 @@ int CmdHelp(const char *Cmd)
|
||||||
|
|
||||||
int CmdHFEPA(const char *Cmd)
|
int CmdHFEPA(const char *Cmd)
|
||||||
{
|
{
|
||||||
// flush
|
(void)WaitForResponseTimeout(CMD_ACK,NULL,100);
|
||||||
WaitForResponseTimeout(CMD_ACK,NULL,100);
|
|
||||||
|
|
||||||
// parse
|
|
||||||
CmdsParse(CommandTable, Cmd);
|
CmdsParse(CommandTable, Cmd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,8 +16,7 @@
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include "iso14443crc.h" // Can also be used for iClass, using 0xE012 as CRC-type
|
#include "iso14443crc.h" // Can also be used for iClass, using 0xE012 as CRC-type
|
||||||
#include "data.h"
|
#include "comms.h"
|
||||||
#include "proxmark3.h"
|
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
#include "cmdparser.h"
|
#include "cmdparser.h"
|
||||||
#include "cmdhficlass.h"
|
#include "cmdhficlass.h"
|
||||||
|
@ -750,8 +749,7 @@ int CmdHFiClassReader_Dump(const char *Cmd) {
|
||||||
blocksRead = (sizeof(tag_data)/8) - blockno;
|
blocksRead = (sizeof(tag_data)/8) - blockno;
|
||||||
}
|
}
|
||||||
// response ok - now get bigbuf content of the dump
|
// response ok - now get bigbuf content of the dump
|
||||||
GetFromBigBuf(tag_data+(blockno*8), blocksRead*8, startindex);
|
GetFromBigBuf(tag_data+(blockno*8), blocksRead*8, startindex, NULL, -1, false);
|
||||||
WaitForResponse(CMD_ACK,NULL);
|
|
||||||
size_t gotBytes = blocksRead*8 + blockno*8;
|
size_t gotBytes = blocksRead*8 + blockno*8;
|
||||||
|
|
||||||
// try AA2
|
// try AA2
|
||||||
|
@ -793,8 +791,7 @@ int CmdHFiClassReader_Dump(const char *Cmd) {
|
||||||
blocksRead = (sizeof(tag_data) - gotBytes)/8;
|
blocksRead = (sizeof(tag_data) - gotBytes)/8;
|
||||||
}
|
}
|
||||||
// get dumped data from bigbuf
|
// get dumped data from bigbuf
|
||||||
GetFromBigBuf(tag_data+gotBytes, blocksRead*8, startindex);
|
GetFromBigBuf(tag_data+gotBytes, blocksRead*8, startindex, NULL, -1, false);
|
||||||
WaitForResponse(CMD_ACK,NULL);
|
|
||||||
|
|
||||||
gotBytes += blocksRead*8;
|
gotBytes += blocksRead*8;
|
||||||
} else { //field is still on - turn it off...
|
} else { //field is still on - turn it off...
|
||||||
|
|
|
@ -8,16 +8,17 @@
|
||||||
// High frequency Legic commands
|
// High frequency Legic commands
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "cmdhflegic.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include "proxmark3.h"
|
#include "comms.h"
|
||||||
#include "data.h"
|
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
#include "cmdparser.h"
|
#include "cmdparser.h"
|
||||||
#include "cmdhflegic.h"
|
|
||||||
#include "cmdmain.h"
|
#include "cmdmain.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
static int CmdHelp(const char *Cmd);
|
static int CmdHelp(const char *Cmd);
|
||||||
|
|
||||||
static command_t CommandTable[] =
|
static command_t CommandTable[] =
|
||||||
|
@ -64,8 +65,7 @@ int CmdLegicDecode(const char *Cmd)
|
||||||
char token_type[4];
|
char token_type[4];
|
||||||
|
|
||||||
// copy data from proxmark into buffer
|
// copy data from proxmark into buffer
|
||||||
GetFromBigBuf(data_buf,sizeof(data_buf),0);
|
GetFromBigBuf(data_buf, sizeof(data_buf), 0, NULL, -1, false);
|
||||||
WaitForResponse(CMD_ACK,NULL);
|
|
||||||
|
|
||||||
// Output CDF System area (9 bytes) plus remaining header area (12 bytes)
|
// Output CDF System area (9 bytes) plus remaining header area (12 bytes)
|
||||||
|
|
||||||
|
@ -294,8 +294,7 @@ int CmdLegicSave(const char *Cmd)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
GetFromBigBuf(got,requested,offset);
|
GetFromBigBuf(got, requested, offset, NULL, -1, false);
|
||||||
WaitForResponse(CMD_ACK,NULL);
|
|
||||||
|
|
||||||
for (int j = 0; j < requested; j += 8) {
|
for (int j = 0; j < requested; j += 8) {
|
||||||
fprintf(f, "%02x %02x %02x %02x %02x %02x %02x %02x\n",
|
fprintf(f, "%02x %02x %02x %02x %02x %02x %02x %02x\n",
|
||||||
|
|
606
client/cmdhflist.c
Normal file
606
client/cmdhflist.c
Normal file
|
@ -0,0 +1,606 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// 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 <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "util.h"
|
||||||
|
#include "ui.h"
|
||||||
|
#include "iso14443crc.h"
|
||||||
|
#include "parity.h"
|
||||||
|
#include "protocols.h"
|
||||||
|
#include "crapto1/crapto1.h"
|
||||||
|
#include "mifarehost.h"
|
||||||
|
#include "mifaredefault.h"
|
||||||
|
|
||||||
|
|
||||||
|
enum MifareAuthSeq {
|
||||||
|
masNone,
|
||||||
|
masNt,
|
||||||
|
masNrAr,
|
||||||
|
masAt,
|
||||||
|
masAuthComplete,
|
||||||
|
masFirstData,
|
||||||
|
masData,
|
||||||
|
masError,
|
||||||
|
};
|
||||||
|
static enum MifareAuthSeq MifareAuthState;
|
||||||
|
static TAuthData AuthData;
|
||||||
|
|
||||||
|
void ClearAuthData() {
|
||||||
|
AuthData.uid = 0;
|
||||||
|
AuthData.nt = 0;
|
||||||
|
AuthData.first_auth = true;
|
||||||
|
AuthData.ks2 = 0;
|
||||||
|
AuthData.ks3 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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 masError:
|
||||||
|
return iso14443A_CRC_check(isResponse, data, len);
|
||||||
|
default:
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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])
|
||||||
|
{
|
||||||
|
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, 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) {
|
||||||
|
ClearAuthData();
|
||||||
|
AuthData.uid = bytes_to_num(&cmd[2], 4);
|
||||||
|
}
|
||||||
|
if (cmdsize == 9 && 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", (AuthData.first_auth) ? "" : "(enc)");
|
||||||
|
MifareAuthState = masNrAr;
|
||||||
|
if (AuthData.first_auth) {
|
||||||
|
AuthData.nt = bytes_to_num(cmd, 4);
|
||||||
|
} else {
|
||||||
|
AuthData.nt_enc = bytes_to_num(cmd, 4);
|
||||||
|
AuthData.nt_enc_par = parity[0];
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
MifareAuthState = masError;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case masNrAr:
|
||||||
|
if (cmdsize == 8 && !isResponse) {
|
||||||
|
snprintf(exp,size,"AUTH: nr ar (enc)");
|
||||||
|
MifareAuthState = masAt;
|
||||||
|
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 {
|
||||||
|
MifareAuthState = masError;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case masAt:
|
||||||
|
if (cmdsize == 4 && isResponse) {
|
||||||
|
snprintf(exp,size,"AUTH: at (enc)");
|
||||||
|
MifareAuthState = masAuthComplete;
|
||||||
|
AuthData.at_enc = bytes_to_num(cmd, 4);
|
||||||
|
AuthData.at_enc_par = parity[0];
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
MifareAuthState = masError;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isResponse && ((MifareAuthState == masNone) || (MifareAuthState == masError)))
|
||||||
|
annotateIso14443a(exp, size, cmd, cmdsize);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
*mfDataLen = 0;
|
||||||
|
|
||||||
|
if (MifareAuthState == masAuthComplete) {
|
||||||
|
if (traceCrypto1) {
|
||||||
|
crypto1_destroy(traceCrypto1);
|
||||||
|
traceCrypto1 = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
MifareAuthState = masFirstData;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmdsize > 32)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (MifareAuthState == masFirstData) {
|
||||||
|
if (AuthData.first_auth) {
|
||||||
|
AuthData.ks2 = AuthData.ar_enc ^ prng_successor(AuthData.nt, 64);
|
||||||
|
AuthData.ks3 = AuthData.at_enc ^ prng_successor(AuthData.nt, 96);
|
||||||
|
|
||||||
|
mfLastKey = GetCrypto1ProbableKey(&AuthData);
|
||||||
|
PrintAndLog(" | * | key | probable key:%012"PRIx64" Prng:%s ks2:%08x ks3:%08x | |",
|
||||||
|
mfLastKey,
|
||||||
|
validate_prng_nonce(AuthData.nt) ? "WEAK": "HARD",
|
||||||
|
AuthData.ks2,
|
||||||
|
AuthData.ks3);
|
||||||
|
|
||||||
|
AuthData.first_auth = false;
|
||||||
|
|
||||||
|
traceCrypto1 = lfsr_recovery64(AuthData.ks2, AuthData.ks3);
|
||||||
|
} else {
|
||||||
|
if (traceCrypto1) {
|
||||||
|
crypto1_destroy(traceCrypto1);
|
||||||
|
traceCrypto1 = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check last used key
|
||||||
|
if (mfLastKey) {
|
||||||
|
if (NestedCheckKey(mfLastKey, &AuthData, cmd, cmdsize, parity)) {
|
||||||
|
PrintAndLog(" | * | key | last used key:%012"PRIx64" ks2:%08x ks3:%08x | |",
|
||||||
|
mfLastKey,
|
||||||
|
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, parity)) {
|
||||||
|
PrintAndLog(" | * | key | default key:%012"PRIx64" ks2:%08x ks3:%08x | |",
|
||||||
|
MifareDefaultKeys[defaultKeyCounter],
|
||||||
|
AuthData.ks2,
|
||||||
|
AuthData.ks3);
|
||||||
|
|
||||||
|
mfLastKey = MifareDefaultKeys[defaultKeyCounter];
|
||||||
|
traceCrypto1 = lfsr_recovery64(AuthData.ks2, AuthData.ks3);
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// nested
|
||||||
|
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 (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:%012"PRIx64" ks2:%08x ks3:%08x | |",
|
||||||
|
mfLastKey,
|
||||||
|
AuthData.ks2,
|
||||||
|
AuthData.ks3);
|
||||||
|
|
||||||
|
traceCrypto1 = lfsr_recovery64(AuthData.ks2, AuthData.ks3);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//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);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
MifareAuthState = masData;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MifareAuthState == masData && traceCrypto1) {
|
||||||
|
memcpy(mfData, cmd, cmdsize);
|
||||||
|
mf_crypto1_decrypt(traceCrypto1, mfData, cmdsize, 0);
|
||||||
|
*mfDataLen = cmdsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
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, 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);
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
if (!(ar == ar1 && at == at1 && NTParityChk(ad, nt1))) {
|
||||||
|
crypto1_destroy(pcs);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(buf, cmd, cmdsize);
|
||||||
|
mf_crypto1_decrypt(pcs, buf, cmdsize, 0);
|
||||||
|
|
||||||
|
crypto1_destroy(pcs);
|
||||||
|
|
||||||
|
if (!CheckCrypto1Parity(cmd, cmdsize, buf, parity))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(!CheckCrc14443(CRC_14443_A, buf, cmdsize))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
AuthData.nt = nt1;
|
||||||
|
AuthData.ks2 = AuthData.ar_enc ^ ar;
|
||||||
|
AuthData.ks3 = AuthData.at_enc ^ at;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CheckCrypto1Parity(uint8_t *cmd_enc, uint8_t cmdsize, uint8_t *cmd, uint8_t *parity_enc) {
|
||||||
|
for (int i = 0; i < cmdsize - 1; 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
47
client/cmdhflist.h
Normal file
47
client/cmdhflist.h
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// 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.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
#ifndef CMDHFLIST_H
|
||||||
|
#define CMDHFLIST_H
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
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
|
||||||
|
uint32_t ks2; // ar ^ ar_enc
|
||||||
|
uint32_t ks3; // at ^ at_enc
|
||||||
|
} 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 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);
|
||||||
|
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
|
|
@ -15,9 +15,10 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include "proxmark3.h"
|
#include "comms.h"
|
||||||
#include "cmdmain.h"
|
#include "cmdmain.h"
|
||||||
#include "cmdhfmfhard.h"
|
#include "cmdhfmfhard.h"
|
||||||
|
#include "parity.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "util_posix.h"
|
#include "util_posix.h"
|
||||||
#include "usb_cmd.h"
|
#include "usb_cmd.h"
|
||||||
|
@ -25,6 +26,7 @@
|
||||||
#include "mifarehost.h"
|
#include "mifarehost.h"
|
||||||
#include "mifare.h"
|
#include "mifare.h"
|
||||||
#include "mfkey.h"
|
#include "mfkey.h"
|
||||||
|
#include "hardnested/hardnested_bf_core.h"
|
||||||
|
|
||||||
#define NESTED_SECTOR_RETRY 10 // how often we try mfested() until we give up
|
#define NESTED_SECTOR_RETRY 10 // how often we try mfested() until we give up
|
||||||
|
|
||||||
|
@ -682,9 +684,9 @@ int CmdHF14AMfNested(const char *Cmd)
|
||||||
if (transferToEml) {
|
if (transferToEml) {
|
||||||
uint8_t sectortrailer;
|
uint8_t sectortrailer;
|
||||||
if (trgBlockNo < 32*4) { // 4 block sector
|
if (trgBlockNo < 32*4) { // 4 block sector
|
||||||
sectortrailer = (trgBlockNo & 0x03) + 3;
|
sectortrailer = trgBlockNo | 0x03;
|
||||||
} else { // 16 block sector
|
} else { // 16 block sector
|
||||||
sectortrailer = (trgBlockNo & 0x0f) + 15;
|
sectortrailer = trgBlockNo | 0x0f;
|
||||||
}
|
}
|
||||||
mfEmlGetMem(keyBlock, sectortrailer, 1);
|
mfEmlGetMem(keyBlock, sectortrailer, 1);
|
||||||
|
|
||||||
|
@ -724,7 +726,6 @@ int CmdHF14AMfNested(const char *Cmd)
|
||||||
blockNo = i * 4;
|
blockNo = i * 4;
|
||||||
keyType = j;
|
keyType = j;
|
||||||
num_to_bytes(e_sector[i].Key[j], 6, key);
|
num_to_bytes(e_sector[i].Key[j], 6, key);
|
||||||
|
|
||||||
keyFound = true;
|
keyFound = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -735,6 +736,7 @@ int CmdHF14AMfNested(const char *Cmd)
|
||||||
// Can't found a key....
|
// Can't found a key....
|
||||||
if (!keyFound) {
|
if (!keyFound) {
|
||||||
PrintAndLog("Can't found any of the known keys.");
|
PrintAndLog("Can't found any of the known keys.");
|
||||||
|
free(e_sector);
|
||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
PrintAndLog("--auto key. block no:%3d, key type:%c key:%s", blockNo, keyType?'B':'A', sprint_hex(key, 6));
|
PrintAndLog("--auto key. block no:%3d, key type:%c key:%s", blockNo, keyType?'B':'A', sprint_hex(key, 6));
|
||||||
|
@ -862,6 +864,13 @@ int CmdHF14AMfNestedHard(const char *Cmd)
|
||||||
PrintAndLog(" w: Acquire nonces and write them to binary file nonces.bin");
|
PrintAndLog(" w: Acquire nonces and write them to binary file nonces.bin");
|
||||||
PrintAndLog(" s: Slower acquisition (required by some non standard cards)");
|
PrintAndLog(" s: Slower acquisition (required by some non standard cards)");
|
||||||
PrintAndLog(" r: Read nonces.bin and start attack");
|
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(" ");
|
||||||
PrintAndLog(" sample1: hf mf hardnested 0 A FFFFFFFFFFFF 4 A");
|
PrintAndLog(" sample1: hf mf hardnested 0 A FFFFFFFFFFFF 4 A");
|
||||||
PrintAndLog(" sample2: hf mf hardnested 0 A FFFFFFFFFFFF 4 A w");
|
PrintAndLog(" sample2: hf mf hardnested 0 A FFFFFFFFFFFF 4 A w");
|
||||||
|
@ -880,15 +889,20 @@ int CmdHF14AMfNestedHard(const char *Cmd)
|
||||||
int tests = 0;
|
int tests = 0;
|
||||||
|
|
||||||
|
|
||||||
|
uint16_t iindx = 0;
|
||||||
if (ctmp == 'R' || ctmp == 'r') {
|
if (ctmp == 'R' || ctmp == 'r') {
|
||||||
nonce_file_read = true;
|
nonce_file_read = true;
|
||||||
|
iindx = 1;
|
||||||
if (!param_gethex(Cmd, 1, trgkey, 12)) {
|
if (!param_gethex(Cmd, 1, trgkey, 12)) {
|
||||||
know_target_key = true;
|
know_target_key = true;
|
||||||
|
iindx = 2;
|
||||||
}
|
}
|
||||||
} else if (ctmp == 'T' || ctmp == 't') {
|
} else if (ctmp == 'T' || ctmp == 't') {
|
||||||
tests = param_get32ex(Cmd, 1, 100, 10);
|
tests = param_get32ex(Cmd, 1, 100, 10);
|
||||||
|
iindx = 2;
|
||||||
if (!param_gethex(Cmd, 2, trgkey, 12)) {
|
if (!param_gethex(Cmd, 2, trgkey, 12)) {
|
||||||
know_target_key = true;
|
know_target_key = true;
|
||||||
|
iindx = 3;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
blockNo = param_get8(Cmd, 0);
|
blockNo = param_get8(Cmd, 0);
|
||||||
|
@ -922,20 +936,55 @@ int CmdHF14AMfNestedHard(const char *Cmd)
|
||||||
know_target_key = true;
|
know_target_key = true;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
iindx = i;
|
||||||
|
|
||||||
while ((ctmp = param_getchar(Cmd, i))) {
|
while ((ctmp = param_getchar(Cmd, i))) {
|
||||||
if (ctmp == 's' || ctmp == 'S') {
|
if (ctmp == 's' || ctmp == 'S') {
|
||||||
slow = true;
|
slow = true;
|
||||||
} else if (ctmp == 'w' || ctmp == 'W') {
|
} else if (ctmp == 'w' || ctmp == 'W') {
|
||||||
nonce_file_write = true;
|
nonce_file_write = true;
|
||||||
|
} else if (param_getlength(Cmd, i) == 2 && ctmp == 'i') {
|
||||||
|
iindx = i;
|
||||||
} else {
|
} else {
|
||||||
PrintAndLog("Possible options are w and/or s");
|
PrintAndLog("Possible options are w , s and/or iX");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
i++;
|
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 ",
|
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,
|
trgBlockNo,
|
||||||
trgKeyType?'B':'A',
|
trgKeyType?'B':'A',
|
||||||
|
@ -1138,7 +1187,10 @@ int CmdHF14AMfChk(const char *Cmd)
|
||||||
|
|
||||||
// initialize storage for found keys
|
// initialize storage for found keys
|
||||||
e_sector = calloc(SectorsCnt, sizeof(sector_t));
|
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 (uint8_t keyAB = 0; keyAB < 2; keyAB++) {
|
||||||
for (uint16_t sectorNo = 0; sectorNo < SectorsCnt; sectorNo++) {
|
for (uint16_t sectorNo = 0; sectorNo < SectorsCnt; sectorNo++) {
|
||||||
e_sector[sectorNo].Key[keyAB] = 0xffffffffffff;
|
e_sector[sectorNo].Key[keyAB] = 0xffffffffffff;
|
||||||
|
@ -1637,10 +1689,7 @@ int CmdHF14AMfESet(const char *Cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1 - blocks count
|
// 1 - blocks count
|
||||||
UsbCommand c = {CMD_MIFARE_EML_MEMSET, {blockNo, 1, 0}};
|
return mfEmlSetMem(memBlock, blockNo, 1);
|
||||||
memcpy(c.d.asBytes, memBlock, 16);
|
|
||||||
SendCommand(&c);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1859,7 +1908,7 @@ int CmdHF14AMfECFill(const char *Cmd)
|
||||||
default: numSectors = 16;
|
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}};
|
UsbCommand c = {CMD_MIFARE_EML_CARDLOAD, {numSectors, keyType, 0}};
|
||||||
SendCommand(&c);
|
SendCommand(&c);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2425,6 +2474,7 @@ int CmdHF14AMfSniff(const char *Cmd){
|
||||||
//var
|
//var
|
||||||
int res = 0;
|
int res = 0;
|
||||||
int len = 0;
|
int len = 0;
|
||||||
|
int parlen = 0;
|
||||||
int blockLen = 0;
|
int blockLen = 0;
|
||||||
int pckNum = 0;
|
int pckNum = 0;
|
||||||
int num = 0;
|
int num = 0;
|
||||||
|
@ -2436,6 +2486,7 @@ int CmdHF14AMfSniff(const char *Cmd){
|
||||||
uint8_t *buf = NULL;
|
uint8_t *buf = NULL;
|
||||||
uint16_t bufsize = 0;
|
uint16_t bufsize = 0;
|
||||||
uint8_t *bufPtr = NULL;
|
uint8_t *bufPtr = NULL;
|
||||||
|
uint8_t parity[16];
|
||||||
|
|
||||||
char ctmp = param_getchar(Cmd, 0);
|
char ctmp = param_getchar(Cmd, 0);
|
||||||
if ( ctmp == 'h' || ctmp == 'H' ) {
|
if ( ctmp == 'h' || ctmp == 'H' ) {
|
||||||
|
@ -2479,14 +2530,13 @@ int CmdHF14AMfSniff(const char *Cmd){
|
||||||
}
|
}
|
||||||
|
|
||||||
UsbCommand resp;
|
UsbCommand resp;
|
||||||
if (WaitForResponseTimeout(CMD_ACK,&resp,2000)) {
|
if (WaitForResponseTimeoutW(CMD_ACK, &resp, 2000, false)) {
|
||||||
res = resp.arg[0] & 0xff;
|
res = resp.arg[0] & 0xff;
|
||||||
uint16_t traceLen = resp.arg[1];
|
uint16_t traceLen = resp.arg[1];
|
||||||
len = resp.arg[2];
|
len = resp.arg[2];
|
||||||
|
|
||||||
if (res == 0) { // we are done
|
if (res == 0) { // we are done
|
||||||
free(buf);
|
break;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res == 1) { // there is (more) data to be transferred
|
if (res == 1) { // there is (more) data to be transferred
|
||||||
|
@ -2528,6 +2578,7 @@ int CmdHF14AMfSniff(const char *Cmd){
|
||||||
} else {
|
} else {
|
||||||
isTag = false;
|
isTag = false;
|
||||||
}
|
}
|
||||||
|
parlen = (len - 1) / 8 + 1;
|
||||||
bufPtr += 2;
|
bufPtr += 2;
|
||||||
if ((len == 14) && (bufPtr[0] == 0xff) && (bufPtr[1] == 0xff) && (bufPtr[12] == 0xff) && (bufPtr[13] == 0xff)) {
|
if ((len == 14) && (bufPtr[0] == 0xff) && (bufPtr[1] == 0xff) && (bufPtr[12] == 0xff) && (bufPtr[13] == 0xff)) {
|
||||||
memcpy(uid, bufPtr + 2, 7);
|
memcpy(uid, bufPtr + 2, 7);
|
||||||
|
@ -2546,15 +2597,22 @@ int CmdHF14AMfSniff(const char *Cmd){
|
||||||
if (wantDecrypt)
|
if (wantDecrypt)
|
||||||
mfTraceInit(uid, atqa, sak, wantSaveToEmlFile);
|
mfTraceInit(uid, atqa, sak, wantSaveToEmlFile);
|
||||||
} else {
|
} 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)
|
if (wantLogToFile)
|
||||||
AddLogHex(logHexFileName, isTag ? "TAG: ":"RDR: ", bufPtr, len);
|
AddLogHex(logHexFileName, isTag ? "TAG: ":"RDR: ", bufPtr, len);
|
||||||
if (wantDecrypt)
|
if (wantDecrypt)
|
||||||
mfTraceDecode(bufPtr, len, wantSaveToEmlFile);
|
mfTraceDecode(bufPtr, len, bufPtr[len], wantSaveToEmlFile);
|
||||||
num++;
|
num++;
|
||||||
}
|
}
|
||||||
bufPtr += len;
|
bufPtr += len;
|
||||||
bufPtr += ((len-1)/8+1); // ignore parity
|
bufPtr += parlen; // ignore parity
|
||||||
}
|
}
|
||||||
pckNum = 0;
|
pckNum = 0;
|
||||||
}
|
}
|
||||||
|
@ -2562,6 +2620,9 @@ int CmdHF14AMfSniff(const char *Cmd){
|
||||||
} // while (true)
|
} // while (true)
|
||||||
|
|
||||||
free(buf);
|
free(buf);
|
||||||
|
|
||||||
|
msleep(300); // wait for exiting arm side.
|
||||||
|
PrintAndLog("Done.");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2608,9 +2669,7 @@ static command_t CommandTable[] =
|
||||||
|
|
||||||
int CmdHFMF(const char *Cmd)
|
int CmdHFMF(const char *Cmd)
|
||||||
{
|
{
|
||||||
// flush
|
(void)WaitForResponseTimeout(CMD_ACK,NULL,100);
|
||||||
WaitForResponseTimeout(CMD_ACK,NULL,100);
|
|
||||||
|
|
||||||
CmdsParse(CommandTable, Cmd);
|
CmdsParse(CommandTable, Cmd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include "proxmark3.h"
|
#include "proxmark3.h"
|
||||||
|
#include "comms.h"
|
||||||
#include "cmdmain.h"
|
#include "cmdmain.h"
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
@ -32,6 +33,7 @@
|
||||||
#include "crapto1/crapto1.h"
|
#include "crapto1/crapto1.h"
|
||||||
#include "parity.h"
|
#include "parity.h"
|
||||||
#include "hardnested/hardnested_bruteforce.h"
|
#include "hardnested/hardnested_bruteforce.h"
|
||||||
|
#include "hardnested/hardnested_bf_core.h"
|
||||||
#include "hardnested/hardnested_bitarray_core.h"
|
#include "hardnested/hardnested_bitarray_core.h"
|
||||||
#include "zlib.h"
|
#include "zlib.h"
|
||||||
|
|
||||||
|
@ -71,27 +73,32 @@ static float brute_force_per_second;
|
||||||
|
|
||||||
|
|
||||||
static void get_SIMD_instruction_set(char* instruction_set) {
|
static void get_SIMD_instruction_set(char* instruction_set) {
|
||||||
#if defined (__i386__) || defined (__x86_64__)
|
switch(GetSIMDInstrAuto()) {
|
||||||
#if !defined(__APPLE__) || (defined(__APPLE__) && (__clang_major__ > 8 || __clang_major__ == 8 && __clang_minor__ >= 1))
|
case SIMD_AVX512:
|
||||||
#if (__GNUC__ >= 5) && (__GNUC__ > 5 || __GNUC_MINOR__ > 2)
|
strcpy(instruction_set, "AVX512F");
|
||||||
if (__builtin_cpu_supports("avx512f")) strcpy(instruction_set, "AVX512F");
|
break;
|
||||||
else if (__builtin_cpu_supports("avx2")) strcpy(instruction_set, "AVX2");
|
case SIMD_AVX2:
|
||||||
#else
|
strcpy(instruction_set, "AVX2");
|
||||||
if (__builtin_cpu_supports("avx2")) strcpy(instruction_set, "AVX2");
|
break;
|
||||||
#endif
|
case SIMD_AVX:
|
||||||
else if (__builtin_cpu_supports("avx")) strcpy(instruction_set, "AVX");
|
strcpy(instruction_set, "AVX");
|
||||||
else if (__builtin_cpu_supports("sse2")) strcpy(instruction_set, "SSE2");
|
break;
|
||||||
else if (__builtin_cpu_supports("mmx")) strcpy(instruction_set, "MMX");
|
case SIMD_SSE2:
|
||||||
else
|
strcpy(instruction_set, "SSE2");
|
||||||
#endif
|
break;
|
||||||
#endif
|
case SIMD_MMX:
|
||||||
|
strcpy(instruction_set, "MMX");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
strcpy(instruction_set, "no");
|
strcpy(instruction_set, "no");
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void print_progress_header(void) {
|
static void print_progress_header(void) {
|
||||||
char progress_text[80];
|
char progress_text[80];
|
||||||
char instr_set[12] = "";
|
char instr_set[12] = {0};
|
||||||
get_SIMD_instruction_set(instr_set);
|
get_SIMD_instruction_set(instr_set);
|
||||||
sprintf(progress_text, "Start using %d threads and %s SIMD core", num_CPUs(), instr_set);
|
sprintf(progress_text, "Start using %d threads and %s SIMD core", num_CPUs(), instr_set);
|
||||||
PrintAndLog("\n\n");
|
PrintAndLog("\n\n");
|
||||||
|
@ -144,12 +151,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)
|
static inline uint32_t test_bit24(uint32_t *bitarray, uint32_t index)
|
||||||
{
|
{
|
||||||
return bitarray[index>>5] & (0x80000000>>(index&0x0000001f));
|
return bitarray[index>>5] & (0x80000000>>(index&0x0000001f));
|
||||||
|
@ -190,40 +191,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
|
#define BITFLIP_2ND_BYTE 0x0200
|
||||||
|
@ -309,7 +276,6 @@ static void init_bitflip_bitarrays(void)
|
||||||
if (bytesread != filesize) {
|
if (bytesread != filesize) {
|
||||||
printf("File read error with %s. Aborting...\n", state_file_name);
|
printf("File read error with %s. Aborting...\n", state_file_name);
|
||||||
fclose(statesfile);
|
fclose(statesfile);
|
||||||
inflateEnd(&compressed_stream);
|
|
||||||
exit(5);
|
exit(5);
|
||||||
}
|
}
|
||||||
fclose(statesfile);
|
fclose(statesfile);
|
||||||
|
@ -1192,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 first_byte = ((uint8_t *)args)[0];
|
||||||
uint8_t last_byte = ((uint8_t *)args)[1];
|
uint8_t last_byte = ((uint8_t *)args)[1];
|
||||||
|
@ -1940,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_args = (uint16_t *)args;
|
||||||
uint16_t sum_a0 = sums[sum_args[0]];
|
uint16_t sum_a0 = sums[sum_args[0]];
|
||||||
|
@ -2529,6 +2507,10 @@ int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBloc
|
||||||
{
|
{
|
||||||
char progress_text[80];
|
char progress_text[80];
|
||||||
|
|
||||||
|
char instr_set[12] = {0};
|
||||||
|
get_SIMD_instruction_set(instr_set);
|
||||||
|
PrintAndLog("Using %s SIMD core.", instr_set);
|
||||||
|
|
||||||
srand((unsigned) time(NULL));
|
srand((unsigned) time(NULL));
|
||||||
brute_force_per_second = brute_force_benchmark();
|
brute_force_per_second = brute_force_benchmark();
|
||||||
write_stats = false;
|
write_stats = false;
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "proxmark3.h"
|
#include "comms.h"
|
||||||
#include "usb_cmd.h"
|
#include "usb_cmd.h"
|
||||||
#include "cmdmain.h"
|
#include "cmdmain.h"
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
|
@ -22,7 +22,6 @@
|
||||||
#include "mifare.h"
|
#include "mifare.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "protocols.h"
|
#include "protocols.h"
|
||||||
#include "data.h"
|
|
||||||
|
|
||||||
#define MAX_UL_BLOCKS 0x0f
|
#define MAX_UL_BLOCKS 0x0f
|
||||||
#define MAX_ULC_BLOCKS 0x2b
|
#define MAX_ULC_BLOCKS 0x2b
|
||||||
|
@ -1325,8 +1324,7 @@ int CmdHF14AMfUDump(const char *Cmd){
|
||||||
PrintAndLog("Data exceeded Buffer size!");
|
PrintAndLog("Data exceeded Buffer size!");
|
||||||
bufferSize = sizeof(data);
|
bufferSize = sizeof(data);
|
||||||
}
|
}
|
||||||
GetFromBigBuf(data, bufferSize, startindex);
|
GetFromBigBuf(data, bufferSize, startindex, NULL, -1, false);
|
||||||
WaitForResponse(CMD_ACK,NULL);
|
|
||||||
|
|
||||||
Pages = bufferSize/4;
|
Pages = bufferSize/4;
|
||||||
// Load lock bytes.
|
// Load lock bytes.
|
||||||
|
@ -1836,7 +1834,7 @@ static command_t CommandTable[] =
|
||||||
};
|
};
|
||||||
|
|
||||||
int CmdHFMFUltra(const char *Cmd){
|
int CmdHFMFUltra(const char *Cmd){
|
||||||
WaitForResponseTimeout(CMD_ACK,NULL,100);
|
(void)WaitForResponseTimeout(CMD_ACK,NULL,100);
|
||||||
CmdsParse(CommandTable, Cmd);
|
CmdsParse(CommandTable, Cmd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,17 +8,18 @@
|
||||||
// High frequency Topaz (NFC Type 1) commands
|
// High frequency Topaz (NFC Type 1) commands
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "cmdhftopaz.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include "cmdmain.h"
|
#include "cmdmain.h"
|
||||||
#include "cmdparser.h"
|
#include "cmdparser.h"
|
||||||
#include "cmdhftopaz.h"
|
|
||||||
#include "cmdhf14a.h"
|
#include "cmdhf14a.h"
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
#include "mifare.h"
|
#include "mifare.h"
|
||||||
#include "proxmark3.h"
|
#include "comms.h"
|
||||||
#include "iso14443crc.h"
|
#include "iso14443crc.h"
|
||||||
#include "protocols.h"
|
#include "protocols.h"
|
||||||
|
|
||||||
|
@ -454,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],
|
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] & 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]);
|
PrintAndLog("HR1 : %02x", rid_response[1]);
|
||||||
|
|
||||||
status = topaz_rall(uid_echo, rall_response);
|
status = topaz_rall(uid_echo, rall_response);
|
||||||
|
@ -553,10 +554,7 @@ static command_t CommandTable[] =
|
||||||
|
|
||||||
|
|
||||||
int CmdHFTopaz(const char *Cmd) {
|
int CmdHFTopaz(const char *Cmd) {
|
||||||
// flush
|
(void)WaitForResponseTimeout(CMD_ACK,NULL,100);
|
||||||
WaitForResponseTimeout(CMD_ACK,NULL,100);
|
|
||||||
|
|
||||||
// parse
|
|
||||||
CmdsParse(CommandTable, Cmd);
|
CmdsParse(CommandTable, Cmd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,17 +8,17 @@
|
||||||
// Hardware commands
|
// Hardware commands
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "cmdhw.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
#include "proxmark3.h"
|
#include "comms.h"
|
||||||
#include "cmdparser.h"
|
#include "cmdparser.h"
|
||||||
#include "cmdhw.h"
|
|
||||||
#include "cmdmain.h"
|
#include "cmdmain.h"
|
||||||
#include "cmddata.h"
|
#include "cmddata.h"
|
||||||
#include "data.h"
|
|
||||||
|
|
||||||
/* low-level hardware control */
|
/* low-level hardware control */
|
||||||
|
|
||||||
|
@ -408,34 +408,23 @@ int CmdVersion(const char *Cmd)
|
||||||
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
UsbCommand c = {CMD_VERSION};
|
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);
|
SendCommand(&c);
|
||||||
if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) {
|
if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) {
|
||||||
PrintAndLog("Prox/RFID mark3 RFID instrument");
|
PrintAndLog("Prox/RFID mark3 RFID instrument");
|
||||||
PrintAndLog((char*)resp.d.asBytes);
|
PrintAndLog((char*)resp.d.asBytes);
|
||||||
lookupChipID(resp.arg[0], resp.arg[1]);
|
lookupChipID(resp.arg[0], resp.arg[1]);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
PrintAndLog("[[[ Cached information ]]]\n");
|
|
||||||
PrintAndLog("Prox/RFID mark3 RFID instrument");
|
|
||||||
PrintAndLog((char*)resp.d.asBytes);
|
|
||||||
lookupChipID(resp.arg[0], resp.arg[1]);
|
|
||||||
PrintAndLog("");
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CmdStatus(const char *Cmd)
|
int CmdStatus(const char *Cmd)
|
||||||
{
|
{
|
||||||
uint8_t speed_test_buffer[USB_CMD_DATA_SIZE];
|
|
||||||
sample_buf = speed_test_buffer;
|
|
||||||
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
UsbCommand c = {CMD_STATUS};
|
UsbCommand c = {CMD_STATUS};
|
||||||
SendCommand(&c);
|
SendCommand(&c);
|
||||||
if (!WaitForResponseTimeout(CMD_ACK,&c,1900)) {
|
if (!WaitForResponseTimeout(CMD_ACK, &c, 1900)) {
|
||||||
PrintAndLog("Status command failed. USB Speed Test timed out");
|
PrintAndLog("Status command failed. USB Speed Test timed out");
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -8,21 +8,21 @@
|
||||||
// Low frequency commands
|
// Low frequency commands
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "cmdlf.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "proxmark3.h"
|
#include "comms.h"
|
||||||
#include "cmdlf.h"
|
|
||||||
#include "lfdemod.h" // for psk2TOpsk1
|
#include "lfdemod.h" // for psk2TOpsk1
|
||||||
#include "util.h" // for parsing cli command utils
|
#include "util.h" // for parsing cli command utils
|
||||||
#include "ui.h" // for show graph controls
|
#include "ui.h" // for show graph controls
|
||||||
#include "graph.h" // for graph data
|
#include "graph.h" // for graph data
|
||||||
#include "cmdparser.h" // for getting cli commands included in cmdmain.h
|
#include "cmdparser.h" // for getting cli commands included in cmdmain.h
|
||||||
#include "cmdmain.h" // for sending cmds to device
|
#include "cmdmain.h" // for sending cmds to device
|
||||||
#include "data.h" // for GetFromBigBuf
|
|
||||||
#include "cmddata.h" // for `lf search`
|
#include "cmddata.h" // for `lf search`
|
||||||
#include "cmdlfawid.h" // for awid menu
|
#include "cmdlfawid.h" // for awid menu
|
||||||
#include "cmdlfem4x.h" // for em4x menu
|
#include "cmdlfem4x.h" // for em4x menu
|
||||||
|
@ -54,26 +54,24 @@ static int CmdHelp(const char *Cmd);
|
||||||
|
|
||||||
int usage_lf_cmdread(void)
|
int usage_lf_cmdread(void)
|
||||||
{
|
{
|
||||||
PrintAndLog("Usage: lf cmdread d <delay period> z <zero period> o <one period> c <cmdbytes> [H] ");
|
PrintAndLog("Usage: lf cmdread d <delay period> z <zero period> o <one period> c <cmdbytes> ");
|
||||||
PrintAndLog("Options: ");
|
PrintAndLog("Options: ");
|
||||||
PrintAndLog(" h This help");
|
PrintAndLog(" h This help");
|
||||||
PrintAndLog(" L Low frequency (125 KHz)");
|
PrintAndLog(" d <delay> delay OFF period between bits (0 for bitbang mode)");
|
||||||
PrintAndLog(" H High frequency (134 KHz)");
|
PrintAndLog(" z <zero> time period ZERO (antenna off in bitbang mode)");
|
||||||
PrintAndLog(" d <delay> delay OFF period");
|
PrintAndLog(" o <one> time period ONE (antenna on in bitbang mode)");
|
||||||
PrintAndLog(" z <zero> time period ZERO");
|
|
||||||
PrintAndLog(" o <one> time period ONE");
|
|
||||||
PrintAndLog(" c <cmd> Command bytes");
|
PrintAndLog(" c <cmd> Command bytes");
|
||||||
PrintAndLog(" ************* All periods in microseconds");
|
PrintAndLog(" ************* All periods in microseconds");
|
||||||
|
PrintAndLog(" ************* Use lf config to configure options.");
|
||||||
PrintAndLog("Examples:");
|
PrintAndLog("Examples:");
|
||||||
PrintAndLog(" lf cmdread d 80 z 100 o 200 c 11000");
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* send a command before reading */
|
/* send a command before reading */
|
||||||
int CmdLFCommandRead(const char *Cmd)
|
int CmdLFCommandRead(const char *Cmd)
|
||||||
{
|
{
|
||||||
static char dummy[3] = {0x20,0x00,0x00};
|
|
||||||
UsbCommand c = {CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K};
|
UsbCommand c = {CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K};
|
||||||
bool errors = false;
|
bool errors = false;
|
||||||
//uint8_t divisor = 95; //125khz
|
//uint8_t divisor = 95; //125khz
|
||||||
|
@ -84,14 +82,6 @@ int CmdLFCommandRead(const char *Cmd)
|
||||||
{
|
{
|
||||||
case 'h':
|
case 'h':
|
||||||
return usage_lf_cmdread();
|
return usage_lf_cmdread();
|
||||||
case 'H':
|
|
||||||
//divisor = 88;
|
|
||||||
dummy[1]='h';
|
|
||||||
cmdp++;
|
|
||||||
break;
|
|
||||||
case 'L':
|
|
||||||
cmdp++;
|
|
||||||
break;
|
|
||||||
case 'c':
|
case 'c':
|
||||||
param_getstr(Cmd, cmdp+1, (char *)&c.d.asBytes, sizeof(c.d.asBytes));
|
param_getstr(Cmd, cmdp+1, (char *)&c.d.asBytes, sizeof(c.d.asBytes));
|
||||||
cmdp+=2;
|
cmdp+=2;
|
||||||
|
@ -121,11 +111,13 @@ int CmdLFCommandRead(const char *Cmd)
|
||||||
//Validations
|
//Validations
|
||||||
if(errors) return usage_lf_cmdread();
|
if(errors) return usage_lf_cmdread();
|
||||||
|
|
||||||
// in case they specified 'H'
|
|
||||||
strcpy((char *)&c.d.asBytes + strlen((char *)c.d.asBytes), dummy);
|
|
||||||
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommand(&c);
|
SendCommand(&c);
|
||||||
|
|
||||||
|
WaitForResponse(CMD_ACK,NULL);
|
||||||
|
getSamples(0, true);
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -335,7 +327,7 @@ int CmdLFSetConfig(const char *Cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool lf_read(bool silent, uint32_t samples) {
|
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}};
|
UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_125K, {silent,samples,0}};
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
//And ship it to device
|
//And ship it to device
|
||||||
|
@ -878,7 +870,7 @@ int CmdVchDemod(const char *Cmd)
|
||||||
int CheckChipType(char cmdp) {
|
int CheckChipType(char cmdp) {
|
||||||
uint32_t wordData = 0;
|
uint32_t wordData = 0;
|
||||||
|
|
||||||
if (offline || cmdp == '1') return 0;
|
if (IsOffline() || cmdp == '1') return 0;
|
||||||
|
|
||||||
save_restoreGB(GRAPH_SAVE);
|
save_restoreGB(GRAPH_SAVE);
|
||||||
save_restoreDB(GRAPH_SAVE);
|
save_restoreDB(GRAPH_SAVE);
|
||||||
|
@ -923,7 +915,7 @@ int CmdLFfind(const char *Cmd)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!offline && (cmdp != '1')) {
|
if (!IsOffline() && (cmdp != '1')) {
|
||||||
lf_read(true, 30000);
|
lf_read(true, 30000);
|
||||||
} else if (GraphTraceLen < minLength) {
|
} else if (GraphTraceLen < minLength) {
|
||||||
PrintAndLog("Data in Graphbuffer was too small.");
|
PrintAndLog("Data in Graphbuffer was too small.");
|
||||||
|
@ -939,7 +931,7 @@ int CmdLFfind(const char *Cmd)
|
||||||
// only run if graphbuffer is just noise as it should be for hitag/cotag
|
// only run if graphbuffer is just noise as it should be for hitag/cotag
|
||||||
if (graphJustNoise(GraphBuffer, testLen)) {
|
if (graphJustNoise(GraphBuffer, testLen)) {
|
||||||
// only run these tests if we are in online mode
|
// 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.
|
// test for em4x05 in reader talk first mode.
|
||||||
if (EM4x05Block0Test(&wordData)) {
|
if (EM4x05Block0Test(&wordData)) {
|
||||||
PrintAndLog("\nValid EM4x05/EM4x69 Chip Found\nUse lf em 4x05readword/dump commands to read\n");
|
PrintAndLog("\nValid EM4x05/EM4x69 Chip Found\nUse lf em 4x05readword/dump commands to read\n");
|
||||||
|
@ -955,6 +947,7 @@ int CmdLFfind(const char *Cmd)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
PrintAndLog("\nNo Data Found! - maybe not an LF tag?\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,10 +11,11 @@
|
||||||
// FSK2a, RF/50, 96 bits (complete)
|
// FSK2a, RF/50, 96 bits (complete)
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "cmdlfawid.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h> // sscanf
|
#include <stdio.h> // sscanf
|
||||||
#include "proxmark3.h" // Definitions, USB controls, etc
|
#include "comms.h" // Definitions, USB controls, etc
|
||||||
#include "cmdlfawid.h"
|
|
||||||
#include "ui.h" // PrintAndLog
|
#include "ui.h" // PrintAndLog
|
||||||
#include "cmdparser.h" // CmdsParse, CmdsHelp
|
#include "cmdparser.h" // CmdsParse, CmdsHelp
|
||||||
#include "lfdemod.h" // parityTest +
|
#include "lfdemod.h" // parityTest +
|
||||||
|
|
|
@ -7,14 +7,15 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Low frequency COTAG commands
|
// Low frequency COTAG commands
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "cmdlfcotag.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "proxmark3.h"
|
#include "comms.h"
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
#include "cmddata.h"
|
#include "cmddata.h"
|
||||||
#include "data.h"
|
|
||||||
#include "cmdlfcotag.h"
|
|
||||||
#include "lfdemod.h"
|
#include "lfdemod.h"
|
||||||
#include "usb_cmd.h"
|
#include "usb_cmd.h"
|
||||||
#include "cmdmain.h"
|
#include "cmdmain.h"
|
||||||
|
@ -99,10 +100,9 @@ int CmdCOTAGRead(const char *Cmd) {
|
||||||
getSamples(0, true); break;
|
getSamples(0, true); break;
|
||||||
}
|
}
|
||||||
case 1: {
|
case 1: {
|
||||||
GetFromBigBuf(DemodBuffer, COTAG_BITS, 0);
|
|
||||||
DemodBufferLen = COTAG_BITS;
|
|
||||||
UsbCommand response;
|
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.");
|
PrintAndLog("timeout while waiting for reply.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,14 +8,14 @@
|
||||||
// Low frequency EM4x commands
|
// Low frequency EM4x commands
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "cmdlfem4x.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include "cmdlfem4x.h"
|
#include "comms.h"
|
||||||
#include "proxmark3.h"
|
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "data.h"
|
|
||||||
#include "graph.h"
|
#include "graph.h"
|
||||||
#include "cmdparser.h"
|
#include "cmdparser.h"
|
||||||
#include "cmddata.h"
|
#include "cmddata.h"
|
||||||
|
@ -804,8 +804,7 @@ int usage_lf_em_read(void) {
|
||||||
bool downloadSamplesEM() {
|
bool downloadSamplesEM() {
|
||||||
// 8 bit preamble + 32 bit word response (max clock (128) * 40bits = 5120 samples)
|
// 8 bit preamble + 32 bit word response (max clock (128) * 40bits = 5120 samples)
|
||||||
uint8_t got[6000];
|
uint8_t got[6000];
|
||||||
GetFromBigBuf(got, sizeof(got), 0);
|
if (!GetFromBigBuf(got, sizeof(got), 0, NULL, 4000, true)) {
|
||||||
if ( !WaitForResponseTimeout(CMD_ACK, NULL, 4000) ) {
|
|
||||||
PrintAndLog("command execution time out");
|
PrintAndLog("command execution time out");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "proxmark3.h"
|
#include "comms.h"
|
||||||
#include "ui.h" // for PrintAndLog
|
#include "ui.h" // for PrintAndLog
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "cmdparser.h"
|
#include "cmdparser.h"
|
||||||
|
|
|
@ -6,20 +6,193 @@
|
||||||
// the license.
|
// the license.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Low frequency HID commands (known)
|
// 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"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "cmdlfhid.h"
|
#include "comms.h"
|
||||||
#include "proxmark3.h"
|
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
#include "graph.h"
|
#include "graph.h"
|
||||||
#include "cmdparser.h"
|
#include "cmdparser.h"
|
||||||
#include "cmddata.h" //for g_debugMode, demodbuff cmds
|
#include "cmddata.h" //for g_debugMode, demodbuff cmds
|
||||||
#include "lfdemod.h" // for HIDdemodFSK
|
#include "lfdemod.h" // for HIDdemodFSK
|
||||||
|
#include "parity.h" // for parity
|
||||||
|
#include "util.h" // for param_get8,32
|
||||||
|
|
||||||
static int CmdHelp(const char *Cmd);
|
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)
|
//by marshmellow (based on existing demod + holiman's refactor)
|
||||||
//HID Prox demod - FSK RF/50 with preamble of 00011101 (then manchester encoded)
|
//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
|
//print full HID Prox ID and some bit format details if found
|
||||||
|
@ -59,45 +232,19 @@ int CmdFSKdemodHID(const char *Cmd)
|
||||||
(unsigned int) hi2, (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF);
|
(unsigned int) hi2, (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF);
|
||||||
}
|
}
|
||||||
else { //standard HID tags <38 bits
|
else { //standard HID tags <38 bits
|
||||||
uint8_t fmtLen = 0;
|
short_hid_info card_info;
|
||||||
uint32_t fc = 0;
|
bool ret = unpack_short_hid(&card_info, (uint32_t)hi, (uint32_t)lo);
|
||||||
uint32_t cardnum = 0;
|
PrintAndLog("HID Prox TAG ID: %x%08x (%d) - Format Len: %u bits - FC: %u - Card: %u",
|
||||||
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",
|
|
||||||
(unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF,
|
(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);
|
setDemodBuf(BitStream,BitLen,idx);
|
||||||
setClockGrid(50, waveIdx + (idx*50));
|
setClockGrid(50, waveIdx + (idx*50));
|
||||||
|
@ -121,11 +268,10 @@ int CmdHIDReadFSK(const char *Cmd)
|
||||||
int CmdHIDSim(const char *Cmd)
|
int CmdHIDSim(const char *Cmd)
|
||||||
{
|
{
|
||||||
uint32_t hi = 0, lo = 0;
|
uint32_t hi = 0, lo = 0;
|
||||||
int n = 0, i = 0;
|
hexstring_to_int64(&hi, &lo, Cmd);
|
||||||
|
if (hi >= 0x40) {
|
||||||
while (sscanf(&Cmd[i++], "%1x", &n ) == 1) {
|
PrintAndLog("This looks like a long tag ID. Use 'lf simfsk' for long tags. Aborting!");
|
||||||
hi = (hi << 4) | (lo >> 28);
|
return 0;
|
||||||
lo = (lo << 4) | (n & 0xf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLog("Emulating tag with ID %x%08x", hi, lo);
|
PrintAndLog("Emulating tag with ID %x%08x", hi, lo);
|
||||||
|
@ -139,10 +285,11 @@ int CmdHIDSim(const char *Cmd)
|
||||||
int CmdHIDClone(const char *Cmd)
|
int CmdHIDClone(const char *Cmd)
|
||||||
{
|
{
|
||||||
unsigned int hi2 = 0, hi = 0, lo = 0;
|
unsigned int hi2 = 0, hi = 0, lo = 0;
|
||||||
int n = 0, i = 0;
|
|
||||||
UsbCommand c;
|
UsbCommand c;
|
||||||
|
|
||||||
if (strchr(Cmd,'l') != 0) {
|
if (strchr(Cmd,'l') != 0) {
|
||||||
|
int n = 0, i = 0;
|
||||||
|
|
||||||
while (sscanf(&Cmd[i++], "%1x", &n ) == 1) {
|
while (sscanf(&Cmd[i++], "%1x", &n ) == 1) {
|
||||||
hi2 = (hi2 << 4) | (hi >> 28);
|
hi2 = (hi2 << 4) | (hi >> 28);
|
||||||
hi = (hi << 4) | (lo >> 28);
|
hi = (hi << 4) | (lo >> 28);
|
||||||
|
@ -154,9 +301,10 @@ int CmdHIDClone(const char *Cmd)
|
||||||
c.d.asBytes[0] = 1;
|
c.d.asBytes[0] = 1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
while (sscanf(&Cmd[i++], "%1x", &n ) == 1) {
|
hexstring_to_int64(&hi, &lo, Cmd);
|
||||||
hi = (hi << 4) | (lo >> 28);
|
if (hi >= 0x40) {
|
||||||
lo = (lo << 4) | (n & 0xf);
|
PrintAndLog("This looks like a long tag ID. Aborting!");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLog("Cloning tag with ID %x%08x", hi, lo);
|
PrintAndLog("Cloning tag with ID %x%08x", hi, lo);
|
||||||
|
@ -174,6 +322,73 @@ int CmdHIDClone(const char *Cmd)
|
||||||
return 0;
|
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 <length> <facility code (decimal)> <card number (decimal)>");
|
||||||
|
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 <ID>");
|
||||||
|
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[] =
|
static command_t CommandTable[] =
|
||||||
{
|
{
|
||||||
{"help", CmdHelp, 1, "This help"},
|
{"help", CmdHelp, 1, "This help"},
|
||||||
|
@ -181,6 +396,8 @@ static command_t CommandTable[] =
|
||||||
{"read", CmdHIDReadFSK, 0, "['1'] Realtime HID FSK Read from antenna (option '1' for one tag only)"},
|
{"read", CmdHIDReadFSK, 0, "['1'] Realtime HID FSK Read from antenna (option '1' for one tag only)"},
|
||||||
{"sim", CmdHIDSim, 0, "<ID> -- HID tag simulator"},
|
{"sim", CmdHIDSim, 0, "<ID> -- HID tag simulator"},
|
||||||
{"clone", CmdHIDClone, 0, "<ID> ['l'] -- Clone HID to T55x7 (tag must be in antenna)(option 'l' for 84bit ID)"},
|
{"clone", CmdHIDClone, 0, "<ID> ['l'] -- Clone HID to T55x7 (tag must be in antenna)(option 'l' for 84bit ID)"},
|
||||||
|
{"pack", CmdHIDPack, 1, "<len> <fc> <num> -- packs a <38 bit (short) HID ID from its length, facility code and card number"},
|
||||||
|
{"unpack", CmdHIDUnpack, 1, "<ID> -- unpacks a <38 bit (short) HID ID to its length, facility code and card number"},
|
||||||
{NULL, NULL, 0, NULL}
|
{NULL, NULL, 0, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -11,10 +11,39 @@
|
||||||
#ifndef CMDLFHID_H__
|
#ifndef CMDLFHID_H__
|
||||||
#define CMDLFHID_H__
|
#define CMDLFHID_H__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
// 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 CmdLFHID(const char *Cmd);
|
||||||
int CmdFSKdemodHID(const char *Cmd);
|
int CmdFSKdemodHID(const char *Cmd);
|
||||||
int CmdHIDReadDemod(const char *Cmd);
|
int CmdHIDReadDemod(const char *Cmd);
|
||||||
int CmdHIDSim(const char *Cmd);
|
int CmdHIDSim(const char *Cmd);
|
||||||
int CmdHIDClone(const char *Cmd);
|
int CmdHIDClone(const char *Cmd);
|
||||||
|
int CmdHIDPack(const char *Cmd);
|
||||||
|
int CmdHIDUnpack(const char *Cmd);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -8,11 +8,12 @@
|
||||||
// Low frequency Hitag support
|
// Low frequency Hitag support
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "cmdlfhitag.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "data.h"
|
#include "comms.h"
|
||||||
#include "proxmark3.h"
|
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
#include "cmdparser.h"
|
#include "cmdparser.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
@ -34,8 +35,7 @@ int CmdLFHitagList(const char *Cmd)
|
||||||
|
|
||||||
// Query for the actual size of the trace
|
// Query for the actual size of the trace
|
||||||
UsbCommand response;
|
UsbCommand response;
|
||||||
GetFromBigBuf(got, USB_CMD_DATA_SIZE, 0);
|
GetFromBigBuf(got, USB_CMD_DATA_SIZE, 0, &response, -1, false);
|
||||||
WaitForResponse(CMD_ACK, &response);
|
|
||||||
uint16_t traceLen = response.arg[2];
|
uint16_t traceLen = response.arg[2];
|
||||||
if (traceLen > USB_CMD_DATA_SIZE) {
|
if (traceLen > USB_CMD_DATA_SIZE) {
|
||||||
uint8_t *p = realloc(got, traceLen);
|
uint8_t *p = realloc(got, traceLen);
|
||||||
|
@ -45,8 +45,7 @@ int CmdLFHitagList(const char *Cmd)
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
got = p;
|
got = p;
|
||||||
GetFromBigBuf(got, traceLen, 0);
|
GetFromBigBuf(got, traceLen, 0, NULL, -1, false);
|
||||||
WaitForResponse(CMD_ACK,NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLog("recorded activity (TraceLen = %d bytes):");
|
PrintAndLog("recorded activity (TraceLen = %d bytes):");
|
||||||
|
@ -67,6 +66,7 @@ int CmdLFHitagList(const char *Cmd)
|
||||||
if (strlen(filename) > 0) {
|
if (strlen(filename) > 0) {
|
||||||
if ((pf = fopen(filename,"wb")) == NULL) {
|
if ((pf = fopen(filename,"wb")) == NULL) {
|
||||||
PrintAndLog("Error: Could not open file [%s]",filename);
|
PrintAndLog("Error: Could not open file [%s]",filename);
|
||||||
|
free(got);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -167,7 +167,7 @@ int CmdLFHitagSim(const char *Cmd) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
tag_mem_supplied = true;
|
tag_mem_supplied = true;
|
||||||
if (fread(c.d.asBytes,48,1,pf) == 0) {
|
if (fread(c.d.asBytes,1,48,pf) != 48) {
|
||||||
PrintAndLog("Error: File reading error");
|
PrintAndLog("Error: File reading error");
|
||||||
fclose(pf);
|
fclose(pf);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -290,7 +290,7 @@ int CmdLFHitagSimS(const char *Cmd) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
tag_mem_supplied = true;
|
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");
|
PrintAndLog("Error: File reading error");
|
||||||
fclose(pf);
|
fclose(pf);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -322,7 +322,7 @@ int CmdLFHitagCheckChallenges(const char *Cmd) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
file_given = true;
|
file_given = true;
|
||||||
if (fread(c.d.asBytes,8*60,1,pf) == 0) {
|
if (fread(c.d.asBytes,1,8*60,pf) != 8*60) {
|
||||||
PrintAndLog("Error: File reading error");
|
PrintAndLog("Error: File reading error");
|
||||||
fclose(pf);
|
fclose(pf);
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -8,10 +8,11 @@
|
||||||
// PSK1, rf/32, 64 or 224 bits (known)
|
// PSK1, rf/32, 64 or 224 bits (known)
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "cmdlfindala.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "cmdlfindala.h"
|
#include "comms.h"
|
||||||
#include "proxmark3.h"
|
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
#include "graph.h"
|
#include "graph.h"
|
||||||
#include "cmdparser.h"
|
#include "cmdparser.h"
|
||||||
|
@ -286,7 +287,7 @@ int CmdIndalaDemod(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int CmdIndalaClone(const char *Cmd) {
|
int CmdIndalaClone(const char *Cmd) {
|
||||||
UsbCommand c;
|
UsbCommand c = {0};
|
||||||
unsigned int uid1, uid2, uid3, uid4, uid5, uid6, uid7;
|
unsigned int uid1, uid2, uid3, uid4, uid5, uid6, uid7;
|
||||||
|
|
||||||
uid1 = uid2 = uid3 = uid4 = uid5 = uid6 = uid7 = 0;
|
uid1 = uid2 = uid3 = uid4 = uid5 = uid6 = uid7 = 0;
|
||||||
|
|
|
@ -8,14 +8,14 @@
|
||||||
// FSK2a, rf/64, 64 bits (complete)
|
// FSK2a, rf/64, 64 bits (complete)
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "cmdlfio.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include "cmdlfio.h"
|
#include "comms.h"
|
||||||
#include "proxmark3.h"
|
|
||||||
#include "data.h"
|
|
||||||
#include "graph.h"
|
#include "graph.h"
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
#include "cmdparser.h"
|
#include "cmdparser.h"
|
||||||
|
|
|
@ -9,10 +9,11 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
#include "cmdlfjablotron.h"
|
#include "cmdlfjablotron.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "proxmark3.h"
|
#include "comms.h"
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "graph.h"
|
#include "graph.h"
|
||||||
|
|
|
@ -7,12 +7,14 @@
|
||||||
// Low frequency Honeywell NexWatch tag commands
|
// Low frequency Honeywell NexWatch tag commands
|
||||||
// PSK1 RF/16, RF/2, 128 bits long (known)
|
// PSK1 RF/16, RF/2, 128 bits long (known)
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "cmdlfnexwatch.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "cmdlfnexwatch.h"
|
#include "comms.h"
|
||||||
#include "proxmark3.h"
|
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "graph.h"
|
#include "graph.h"
|
||||||
|
|
|
@ -7,11 +7,13 @@
|
||||||
// Low frequency Noralsy tag commands
|
// Low frequency Noralsy tag commands
|
||||||
// ASK/Manchester, STT, RF/32, 96 bits long (some bits unknown)
|
// ASK/Manchester, STT, RF/32, 96 bits long (some bits unknown)
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
#include "cmdlfnoralsy.h"
|
#include "cmdlfnoralsy.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include "proxmark3.h"
|
#include "comms.h"
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "graph.h"
|
#include "graph.h"
|
||||||
|
|
|
@ -7,10 +7,12 @@
|
||||||
// Low frequency Stanley/PAC tag commands
|
// Low frequency Stanley/PAC tag commands
|
||||||
// NRZ, RF/32, 128 bits long (unknown cs)
|
// NRZ, RF/32, 128 bits long (unknown cs)
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
#include "cmdlfpac.h"
|
#include "cmdlfpac.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include "proxmark3.h"
|
#include "comms.h"
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "graph.h"
|
#include "graph.h"
|
||||||
|
|
|
@ -8,9 +8,12 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Low frequency PCF7931 commands
|
// Low frequency PCF7931 commands
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "cmdlfpcf7931.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "proxmark3.h"
|
#include "comms.h"
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "graph.h"
|
#include "graph.h"
|
||||||
|
@ -18,7 +21,6 @@
|
||||||
#include "cmddata.h"
|
#include "cmddata.h"
|
||||||
#include "cmdmain.h"
|
#include "cmdmain.h"
|
||||||
#include "cmdlf.h"
|
#include "cmdlf.h"
|
||||||
#include "cmdlfpcf7931.h"
|
|
||||||
|
|
||||||
static int CmdHelp(const char *Cmd);
|
static int CmdHelp(const char *Cmd);
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
#ifndef CMDLFPCF7931_H__
|
#ifndef CMDLFPCF7931_H__
|
||||||
#define CMDLFPCF7931_H__
|
#define CMDLFPCF7931_H__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
struct pcf7931_config{
|
struct pcf7931_config{
|
||||||
uint8_t Pwd[7];
|
uint8_t Pwd[7];
|
||||||
uint16_t InitDelay;
|
uint16_t InitDelay;
|
||||||
|
|
|
@ -7,11 +7,13 @@
|
||||||
// Low frequency Presco tag commands
|
// Low frequency Presco tag commands
|
||||||
// ASK/Manchester, rf/32, 128 bits (complete)
|
// ASK/Manchester, rf/32, 128 bits (complete)
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "cmdlfpresco.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "cmdlfpresco.h"
|
#include "comms.h"
|
||||||
#include "proxmark3.h"
|
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "graph.h"
|
#include "graph.h"
|
||||||
|
|
|
@ -7,11 +7,13 @@
|
||||||
// Low frequency Farpoint / Pyramid tag commands
|
// Low frequency Farpoint / Pyramid tag commands
|
||||||
// FSK2a, rf/50, 128 bits (complete)
|
// FSK2a, rf/50, 128 bits (complete)
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "cmdlfpyramid.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "cmdlfpyramid.h"
|
#include "comms.h"
|
||||||
#include "proxmark3.h"
|
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "graph.h"
|
#include "graph.h"
|
||||||
|
|
|
@ -7,11 +7,13 @@
|
||||||
// Low frequency Securakey tag commands
|
// Low frequency Securakey tag commands
|
||||||
// ASK/Manchester, RF/40, 96 bits long (unknown cs)
|
// ASK/Manchester, RF/40, 96 bits long (unknown cs)
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
#include "cmdlfsecurakey.h"
|
#include "cmdlfsecurakey.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include "proxmark3.h"
|
#include "comms.h"
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "graph.h"
|
#include "graph.h"
|
||||||
|
|
|
@ -7,21 +7,21 @@
|
||||||
// Low frequency T55xx commands
|
// Low frequency T55xx commands
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "cmdlft55xx.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include "proxmark3.h"
|
#include "comms.h"
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
#include "graph.h"
|
#include "graph.h"
|
||||||
#include "cmdmain.h"
|
#include "cmdmain.h"
|
||||||
#include "cmdparser.h"
|
#include "cmdparser.h"
|
||||||
#include "cmddata.h"
|
#include "cmddata.h"
|
||||||
#include "cmdlf.h"
|
#include "cmdlf.h"
|
||||||
#include "cmdlft55xx.h"
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "data.h"
|
|
||||||
#include "lfdemod.h"
|
#include "lfdemod.h"
|
||||||
#include "cmdhf14a.h" //for getTagInfo
|
#include "cmdhf14a.h" //for getTagInfo
|
||||||
#include "protocols.h"
|
#include "protocols.h"
|
||||||
|
@ -207,7 +207,7 @@ void printT5xxHeader(uint8_t page){
|
||||||
int CmdT55xxSetConfig(const char *Cmd) {
|
int CmdT55xxSetConfig(const char *Cmd) {
|
||||||
|
|
||||||
uint8_t offset = 0;
|
uint8_t offset = 0;
|
||||||
char modulation[5] = {0x00};
|
char modulation[6] = {0x00};
|
||||||
char tmp = 0x00;
|
char tmp = 0x00;
|
||||||
uint8_t bitRate = 0;
|
uint8_t bitRate = 0;
|
||||||
uint8_t rates[9] = {8,16,32,40,50,64,100,128,0};
|
uint8_t rates[9] = {8,16,32,40,50,64,100,128,0};
|
||||||
|
@ -1355,8 +1355,7 @@ int CmdResetRead(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t got[BIGBUF_SIZE-1];
|
uint8_t got[BIGBUF_SIZE-1];
|
||||||
GetFromBigBuf(got,sizeof(got),0);
|
GetFromBigBuf(got, sizeof(got), 0, NULL, -1 , 0);
|
||||||
WaitForResponse(CMD_ACK,NULL);
|
|
||||||
setGraphBuf(got, sizeof(got));
|
setGraphBuf(got, sizeof(got));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,9 @@
|
||||||
#ifndef CMDLFT55XX_H__
|
#ifndef CMDLFT55XX_H__
|
||||||
#define CMDLFT55XX_H__
|
#define CMDLFT55XX_H__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t bl1;
|
uint32_t bl1;
|
||||||
uint32_t bl2;
|
uint32_t bl2;
|
||||||
|
|
|
@ -8,16 +8,17 @@
|
||||||
// Low frequency TI commands
|
// Low frequency TI commands
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "cmdlfti.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include "crc16.h"
|
#include "crc16.h"
|
||||||
#include "proxmark3.h"
|
#include "comms.h"
|
||||||
#include "data.h"
|
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
#include "graph.h"
|
#include "graph.h"
|
||||||
#include "cmdparser.h"
|
#include "cmdparser.h"
|
||||||
#include "cmdlfti.h"
|
#include "util.h"
|
||||||
|
|
||||||
static int CmdHelp(const char *Cmd);
|
static int CmdHelp(const char *Cmd);
|
||||||
|
|
||||||
|
|
|
@ -7,11 +7,13 @@
|
||||||
// Low frequency Viking tag commands (AKA FDI Matalec Transit)
|
// Low frequency Viking tag commands (AKA FDI Matalec Transit)
|
||||||
// ASK/Manchester, RF/32, 64 bits (complete)
|
// ASK/Manchester, RF/32, 64 bits (complete)
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "cmdlfviking.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include "proxmark3.h"
|
#include "comms.h"
|
||||||
#include "cmdlfviking.h"
|
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "graph.h"
|
#include "graph.h"
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "proxmark3.h"
|
#include "comms.h"
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "graph.h"
|
#include "graph.h"
|
||||||
|
|
168
client/cmdmain.c
168
client/cmdmain.c
|
@ -17,7 +17,6 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "cmdparser.h"
|
#include "cmdparser.h"
|
||||||
#include "proxmark3.h"
|
#include "proxmark3.h"
|
||||||
#include "data.h"
|
|
||||||
#include "usb_cmd.h"
|
#include "usb_cmd.h"
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
#include "cmdhf.h"
|
#include "cmdhf.h"
|
||||||
|
@ -27,24 +26,11 @@
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "util_posix.h"
|
#include "util_posix.h"
|
||||||
#include "cmdscript.h"
|
#include "cmdscript.h"
|
||||||
#include "cmdcrc.h"
|
|
||||||
|
|
||||||
|
|
||||||
unsigned int current_command = CMD_UNKNOWN;
|
|
||||||
|
|
||||||
static int CmdHelp(const char *Cmd);
|
static int CmdHelp(const char *Cmd);
|
||||||
static int CmdQuit(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
|
|
||||||
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[] =
|
static command_t CommandTable[] =
|
||||||
{
|
{
|
||||||
|
@ -53,7 +39,6 @@ static command_t CommandTable[] =
|
||||||
{"hf", CmdHF, 1, "{ High Frequency commands... }"},
|
{"hf", CmdHF, 1, "{ High Frequency commands... }"},
|
||||||
{"hw", CmdHW, 1, "{ Hardware commands... }"},
|
{"hw", CmdHW, 1, "{ Hardware commands... }"},
|
||||||
{"lf", CmdLF, 1, "{ Low Frequency commands... }"},
|
{"lf", CmdLF, 1, "{ Low Frequency commands... }"},
|
||||||
{"reveng",CmdRev, 1, "Crc calculations from the software reveng1-30"},
|
|
||||||
{"script",CmdScript,1, "{ Scripting commands }"},
|
{"script",CmdScript,1, "{ Scripting commands }"},
|
||||||
{"quit", CmdQuit, 1, "Exit program"},
|
{"quit", CmdQuit, 1, "Exit program"},
|
||||||
{"exit", CmdQuit, 1, "Exit program"},
|
{"exit", CmdQuit, 1, "Exit program"},
|
||||||
|
@ -64,130 +49,18 @@ command_t* getTopLevelCommandTable()
|
||||||
{
|
{
|
||||||
return CommandTable;
|
return CommandTable;
|
||||||
}
|
}
|
||||||
int CmdHelp(const char *Cmd)
|
|
||||||
|
static int CmdHelp(const char *Cmd)
|
||||||
{
|
{
|
||||||
CmdsHelp(CommandTable);
|
CmdsHelp(CommandTable);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CmdQuit(const char *Cmd)
|
static int CmdQuit(const char *Cmd)
|
||||||
{
|
{
|
||||||
return 99;
|
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.
|
|
||||||
* 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("Don't forget to cancel its operation first by pressing on the 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
|
// Entry point into our code: called whenever the user types a command and
|
||||||
// then presses Enter, which the full command line that they typed.
|
// then presses Enter, which the full command line that they typed.
|
||||||
|
@ -196,38 +69,3 @@ int CommandReceived(char *Cmd) {
|
||||||
return CmdsParse(CommandTable, 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -11,17 +11,9 @@
|
||||||
#ifndef CMDMAIN_H__
|
#ifndef CMDMAIN_H__
|
||||||
#define CMDMAIN_H__
|
#define CMDMAIN_H__
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include "usb_cmd.h"
|
|
||||||
#include "cmdparser.h"
|
#include "cmdparser.h"
|
||||||
|
|
||||||
extern void UsbCommandReceived(UsbCommand *UC);
|
|
||||||
extern int CommandReceived(char *Cmd);
|
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();
|
extern command_t* getTopLevelCommandTable();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -8,12 +8,14 @@
|
||||||
// Command parser
|
// Command parser
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "cmdparser.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
#include "cmdparser.h"
|
|
||||||
#include "proxmark3.h"
|
#include "proxmark3.h"
|
||||||
|
#include "comms.h"
|
||||||
|
|
||||||
|
|
||||||
void CmdsHelp(const command_t Commands[])
|
void CmdsHelp(const command_t Commands[])
|
||||||
|
@ -23,7 +25,7 @@ void CmdsHelp(const command_t Commands[])
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (Commands[i].Name)
|
while (Commands[i].Name)
|
||||||
{
|
{
|
||||||
if (!offline || Commands[i].Offline)
|
if (!IsOffline() || Commands[i].Offline)
|
||||||
PrintAndLog("%-16s %s", Commands[i].Name, Commands[i].Help);
|
PrintAndLog("%-16s %s", Commands[i].Name, Commands[i].Help);
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
|
|
||||||
#include "proxmark3.h"
|
#include "proxmark3.h"
|
||||||
#include "scripting.h"
|
#include "scripting.h"
|
||||||
#include "data.h"
|
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
#include "graph.h"
|
#include "graph.h"
|
||||||
#include "cmdparser.h"
|
#include "cmdparser.h"
|
||||||
|
|
411
client/comms.c
Normal file
411
client/comms.c
Normal file
|
@ -0,0 +1,411 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Copyright (C) 2009 Michael Gernoth <michael at gernoth.net>
|
||||||
|
// Copyright (C) 2010 iZsh <izsh at fail0verflow.com>
|
||||||
|
//
|
||||||
|
// 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 "comms.h"
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
#if defined(__linux__) && !defined(NO_UNLINK)
|
||||||
|
#include <unistd.h> // for unlink()
|
||||||
|
#endif
|
||||||
|
#include "uart.h"
|
||||||
|
#include "ui.h"
|
||||||
|
#include "common.h"
|
||||||
|
#include "util_posix.h"
|
||||||
|
|
||||||
|
|
||||||
|
// Serial port that we are communicating with the PM3 on.
|
||||||
|
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.
|
||||||
|
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 rxBuffer[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 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.
|
||||||
|
|
||||||
|
void SetOffline(bool new_offline) {
|
||||||
|
offline = new_offline;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsOffline() {
|
||||||
|
return offline;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SendCommand(UsbCommand *c) {
|
||||||
|
#ifdef COMMS_DEBUG
|
||||||
|
printf("Sending %04x cmd\n", c->cmd);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (offline) {
|
||||||
|
PrintAndLog("Sending bytes to proxmark failed - offline");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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(&rxBufferMutex);
|
||||||
|
cmd_tail = cmd_head;
|
||||||
|
pthread_mutex_unlock(&rxBufferMutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief storeCommand stores a USB command in a circular buffer
|
||||||
|
* @param UC
|
||||||
|
*/
|
||||||
|
static void storeCommand(UsbCommand *command)
|
||||||
|
{
|
||||||
|
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
|
||||||
|
// circular buffer.
|
||||||
|
PrintAndLog("WARNING: Command buffer about to overwrite command! This needs to be fixed!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store the command at the 'head' location
|
||||||
|
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(&rxBufferMutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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
|
||||||
|
*/
|
||||||
|
static int getCommand(UsbCommand* response)
|
||||||
|
{
|
||||||
|
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(&rxBufferMutex);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Pick out the next unread command
|
||||||
|
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(&rxBufferMutex);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// 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) {
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
default:
|
||||||
|
storeCommand(UC);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
#ifdef __has_attribute
|
||||||
|
#if __has_attribute(force_align_arg_pointer)
|
||||||
|
__attribute__((force_align_arg_pointer))
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
*uart_communication(void *targ) {
|
||||||
|
communication_arg_t *conn = (communication_arg_t*)targ;
|
||||||
|
size_t rxlen;
|
||||||
|
UsbCommand rx;
|
||||||
|
UsbCommand *prx = ℞
|
||||||
|
|
||||||
|
while (conn->run) {
|
||||||
|
rxlen = 0;
|
||||||
|
bool ACK_received = false;
|
||||||
|
if (uart_receive(sp, (uint8_t *)prx, sizeof(UsbCommand) - (prx-&rx), &rxlen) && rxlen) {
|
||||||
|
prx += rxlen;
|
||||||
|
if (prx-&rx < sizeof(UsbCommand)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
UsbCommandReceived(&rx);
|
||||||
|
if (rx.cmd == CMD_ACK) {
|
||||||
|
ACK_received = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
prx = ℞
|
||||||
|
|
||||||
|
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
txBuffer_pending = false;
|
||||||
|
pthread_cond_signal(&txBufferSig); // tell main thread that txBuffer is empty
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&txBufferMutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_exit(NULL);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (sp) {
|
||||||
|
uart_close(sp);
|
||||||
|
}
|
||||||
|
|
||||||
|
#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);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Clean up our state
|
||||||
|
sp = NULL;
|
||||||
|
serial_port_name = 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, or CMD_UNKNOWN to take any command.
|
||||||
|
* @param response struct to copy received command into.
|
||||||
|
* @param ms_timeout
|
||||||
|
* @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) {
|
||||||
|
|
||||||
|
UsbCommand resp;
|
||||||
|
|
||||||
|
#ifdef COMMS_DEBUG
|
||||||
|
printf("Waiting for %04x cmd\n", cmd);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (response == NULL) {
|
||||||
|
response = &resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t start_time = msclock();
|
||||||
|
|
||||||
|
// Wait until the command is received
|
||||||
|
while (true) {
|
||||||
|
while(getCommand(response)) {
|
||||||
|
if (cmd == CMD_UNKNOWN || response->cmd == cmd) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msclock() - start_time > ms_timeout) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
39
client/comms.h
Normal file
39
client/comms.h
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Copyright (C) 2009 Michael Gernoth <michael at gernoth.net>
|
||||||
|
// Copyright (C) 2010 iZsh <izsh at fail0verflow.com>
|
||||||
|
//
|
||||||
|
// 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 <stdbool.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
#include "usb_cmd.h"
|
||||||
|
#include "uart.h"
|
||||||
|
|
||||||
|
#ifndef CMD_BUFFER_SIZE
|
||||||
|
#define CMD_BUFFER_SIZE 50
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void SetOffline(bool new_offline);
|
||||||
|
bool IsOffline();
|
||||||
|
|
||||||
|
bool OpenProxmark(void *port, bool wait_for_port, int timeout, bool flash_mode);
|
||||||
|
void CloseProxmark(void);
|
||||||
|
|
||||||
|
void SendCommand(UsbCommand *c);
|
||||||
|
|
||||||
|
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_
|
|
@ -1,25 +0,0 @@
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Copyright (C) 2010 iZsh <izsh at fail0verflow.com>
|
|
||||||
//
|
|
||||||
// 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 <string.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#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);
|
|
||||||
}
|
|
|
@ -1,23 +0,0 @@
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Copyright (C) 2010 iZsh <izsh at fail0verflow.com>
|
|
||||||
//
|
|
||||||
// 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 <stdint.h>
|
|
||||||
|
|
||||||
#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
|
|
|
@ -132,7 +132,7 @@ const APDUCode APDUCodeTable[] = {
|
||||||
{"6EXX", APDUCODE_TYPE_ERROR, "Instruction class not supported (procedure byte), (ISO 7816-3)"},
|
{"6EXX", APDUCODE_TYPE_ERROR, "Instruction class not supported (procedure byte), (ISO 7816-3)"},
|
||||||
{"6F--", APDUCODE_TYPE_ERROR, "Internal exception"},
|
{"6F--", APDUCODE_TYPE_ERROR, "Internal exception"},
|
||||||
{"6F00", APDUCODE_TYPE_ERROR, "Command aborted - more exact diagnosis not possible (e.g., operating system error)."},
|
{"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)"},
|
{"6FXX", APDUCODE_TYPE_ERROR, "No precise diagnosis (procedure byte), (ISO 7816-3)"},
|
||||||
{"9---", APDUCODE_TYPE_NONE, ""},
|
{"9---", APDUCODE_TYPE_NONE, ""},
|
||||||
{"9000", APDUCODE_TYPE_INFO, "Command successfully executed (OK)."},
|
{"9000", APDUCODE_TYPE_INFO, "Command successfully executed (OK)."},
|
||||||
|
|
|
@ -105,7 +105,7 @@ static struct crypto_pk *crypto_pk_polarssl_open_rsa(va_list vl)
|
||||||
int res = rsa_check_pubkey(&cp->ctx);
|
int res = rsa_check_pubkey(&cp->ctx);
|
||||||
if(res != 0) {
|
if(res != 0) {
|
||||||
fprintf(stderr, "PolarSSL public key error res=%x exp=%d mod=%d.\n", res * -1, explen, modlen);
|
fprintf(stderr, "PolarSSL public key error res=%x exp=%d mod=%d.\n", res * -1, explen, modlen);
|
||||||
|
free(cp);
|
||||||
return NULL;
|
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);
|
int res = rsa_check_privkey(&cp->ctx);
|
||||||
if(res != 0) {
|
if(res != 0) {
|
||||||
fprintf(stderr, "PolarSSL private key error res=%x exp=%d mod=%d.\n", res * -1, explen, modlen);
|
fprintf(stderr, "PolarSSL private key error res=%x exp=%d mod=%d.\n", res * -1, explen, modlen);
|
||||||
|
free(cp);
|
||||||
return NULL;
|
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);
|
int res = rsa_gen_key(&cp->ctx, &myrand, NULL, nbits, exp);
|
||||||
if (res) {
|
if (res) {
|
||||||
fprintf(stderr, "PolarSSL private key generation error res=%x exp=%d nbits=%d.\n", res * -1, exp, nbits);
|
fprintf(stderr, "PolarSSL private key generation error res=%x exp=%d nbits=%d.\n", res * -1, exp, nbits);
|
||||||
|
free(cp);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,7 +217,8 @@ static unsigned char *crypto_pk_polarssl_encrypt(const struct crypto_pk *_cp, co
|
||||||
|
|
||||||
res = rsa_public(&cp->ctx, buf, result);
|
res = rsa_public(&cp->ctx, buf, result);
|
||||||
if(res) {
|
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);
|
||||||
|
free(result);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,7 +244,8 @@ static unsigned char *crypto_pk_polarssl_decrypt(const struct crypto_pk *_cp, co
|
||||||
|
|
||||||
res = rsa_private(&cp->ctx, buf, result); // CHECK???
|
res = rsa_private(&cp->ctx, buf, result); // CHECK???
|
||||||
if(res) {
|
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);
|
||||||
|
free(result);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,7 @@ static unsigned char *emv_pki_decode_message(const struct emv_pk *enc_pk,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cert_tlv->len != enc_pk->mlen) {
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
kcp = crypto_pk_open(enc_pk->pk_algo,
|
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,
|
un_tlv,
|
||||||
NULL);
|
NULL);
|
||||||
if (!data || data_len < 3) {
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -221,7 +221,7 @@ struct tlvdb *GetdCVVRawFromTrack2(const struct tlv *track2) {
|
||||||
return tlvdb_fixed(0x02, dCVVlen, dCVV);
|
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};
|
uint8_t data[APDU_RES_LEN] = {0};
|
||||||
|
|
||||||
*ResultLen = 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);
|
memcpy(&data[5], apdu.data, apdu.Lc);
|
||||||
|
|
||||||
if (APDULogging)
|
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 + <data = Nc> + Le
|
// 6 byes + data = INS + CLA + P1 + P2 + Lc + <data = Nc> + Le(?IncludeLe)
|
||||||
int res = ExchangeAPDU14a(data, 6 + apdu.Lc, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen);
|
int res = ExchangeAPDU14a(data, (IncludeLe?6:5) + apdu.Lc, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen);
|
||||||
|
|
||||||
if (res) {
|
if (res) {
|
||||||
return 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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
||||||
|
|
|
@ -219,7 +219,7 @@ static int test_pk(bool verbose)
|
||||||
|
|
||||||
tmp = crypto_pk_get_parameter(pubk, 0, &tmp_len);
|
tmp = crypto_pk_get_parameter(pubk, 0, &tmp_len);
|
||||||
if (tmp_len != sizeof(pk_N) || memcmp(tmp, pk_N, 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);
|
free(tmp);
|
||||||
goto close_pub;
|
goto close_pub;
|
||||||
}
|
}
|
||||||
|
@ -256,7 +256,7 @@ static int test_pk(bool verbose)
|
||||||
|
|
||||||
tmp = crypto_pk_get_parameter(privk, 0, &tmp_len);
|
tmp = crypto_pk_get_parameter(privk, 0, &tmp_len);
|
||||||
if (tmp_len != sizeof(pk_N) || memcmp(tmp, pk_N, 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);
|
free(tmp);
|
||||||
goto close;
|
goto close;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,14 +20,7 @@
|
||||||
#include "elf.h"
|
#include "elf.h"
|
||||||
#include "proxendian.h"
|
#include "proxendian.h"
|
||||||
#include "usb_cmd.h"
|
#include "usb_cmd.h"
|
||||||
|
#include "comms.h"
|
||||||
void SendCommand(UsbCommand* txcmd);
|
|
||||||
void ReceiveCommand(UsbCommand* rxcmd);
|
|
||||||
void CloseProxmark();
|
|
||||||
int OpenProxmark(size_t i);
|
|
||||||
|
|
||||||
// FIXME: what the fuckity fuck
|
|
||||||
unsigned int current_command = CMD_UNKNOWN;
|
|
||||||
|
|
||||||
#define FLASH_START 0x100000
|
#define FLASH_START 0x100000
|
||||||
#define FLASH_SIZE (256*1024)
|
#define FLASH_SIZE (256*1024)
|
||||||
|
@ -44,9 +37,10 @@ static const uint8_t elf_ident[] = {
|
||||||
EV_CURRENT
|
EV_CURRENT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Turn PHDRs into flasher segments, checking for PHDR sanity and merging adjacent
|
// Turn PHDRs into flasher segments, checking for PHDR sanity and merging adjacent
|
||||||
// unaligned segments if needed
|
// 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;
|
Elf32_Phdr *phdr = phdrs;
|
||||||
flash_seg_t *seg;
|
flash_seg_t *seg;
|
||||||
|
@ -192,12 +186,12 @@ static int check_segs(flash_file_t *ctx, int can_write_bl) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load an ELF file and prepare it for flashing
|
// 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;
|
FILE *fd = NULL;
|
||||||
Elf32_Ehdr ehdr;
|
Elf32_Ehdr ehdr;
|
||||||
Elf32_Phdr *phdrs = NULL;
|
Elf32_Phdr *phdrs = NULL;
|
||||||
int num_phdrs;
|
uint16_t num_phdrs;
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
fd = fopen(name, "rb");
|
fd = fopen(name, "rb");
|
||||||
|
@ -276,11 +270,11 @@ fail:
|
||||||
// Get the state of the proxmark, backwards compatible
|
// Get the state of the proxmark, backwards compatible
|
||||||
static int get_proxmark_state(uint32_t *state)
|
static int get_proxmark_state(uint32_t *state)
|
||||||
{
|
{
|
||||||
UsbCommand c;
|
UsbCommand c = {0};
|
||||||
c.cmd = CMD_DEVICE_INFO;
|
c.cmd = CMD_DEVICE_INFO;
|
||||||
SendCommand(&c);
|
SendCommand(&c);
|
||||||
UsbCommand resp;
|
UsbCommand resp;
|
||||||
ReceiveCommand(&resp);
|
WaitForResponse(CMD_UNKNOWN, &resp); // wait for any response. No timeout.
|
||||||
|
|
||||||
// Three outcomes:
|
// Three outcomes:
|
||||||
// 1. The old bootrom code will ignore CMD_DEVICE_INFO, but respond with an ACK
|
// 1. The old bootrom code will ignore CMD_DEVICE_INFO, but respond with an ACK
|
||||||
|
@ -338,17 +332,18 @@ static int enter_bootloader(char *serial_port_name)
|
||||||
SendCommand(&c);
|
SendCommand(&c);
|
||||||
fprintf(stderr,"Press and hold down button NOW if your bootloader requires it.\n");
|
fprintf(stderr,"Press and hold down button NOW if your bootloader requires it.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
msleep(100);
|
msleep(100);
|
||||||
CloseProxmark();
|
CloseProxmark();
|
||||||
|
|
||||||
fprintf(stderr,"Waiting for Proxmark to reappear on %s",serial_port_name);
|
bool opened = OpenProxmark(serial_port_name, true, 120, true); // wait for 2 minutes
|
||||||
do {
|
if (opened) {
|
||||||
sleep(1);
|
|
||||||
fprintf(stderr, ".");
|
|
||||||
} while (!OpenProxmark(0));
|
|
||||||
fprintf(stderr," Found.\n");
|
fprintf(stderr," Found.\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr,"Error: Proxmark not found.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stderr, "Error: Unknown Proxmark mode\n");
|
fprintf(stderr, "Error: Unknown Proxmark mode\n");
|
||||||
|
@ -358,7 +353,7 @@ static int enter_bootloader(char *serial_port_name)
|
||||||
static int wait_for_ack(void)
|
static int wait_for_ack(void)
|
||||||
{
|
{
|
||||||
UsbCommand ack;
|
UsbCommand ack;
|
||||||
ReceiveCommand(&ack);
|
WaitForResponse(CMD_UNKNOWN, &ack);
|
||||||
if (ack.cmd != CMD_ACK) {
|
if (ack.cmd != CMD_ACK) {
|
||||||
printf("Error: Unexpected reply 0x%04" PRIx64 " (expected ACK)\n", ack.cmd);
|
printf("Error: Unexpected reply 0x%04" PRIx64 " (expected ACK)\n", ack.cmd);
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
#define __FLASH_H__
|
#define __FLASH_H__
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "elf.h"
|
#include <stdbool.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
void *data;
|
void *data;
|
||||||
|
@ -25,11 +25,10 @@ typedef struct {
|
||||||
flash_seg_t *segments;
|
flash_seg_t *segments;
|
||||||
} flash_file_t;
|
} 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_start_flashing(int enable_bl_writes, char *serial_port_name);
|
||||||
int flash_write(flash_file_t *ctx);
|
int flash_write(flash_file_t *ctx);
|
||||||
void flash_free(flash_file_t *ctx);
|
void flash_free(flash_file_t *ctx);
|
||||||
int flash_stop_flashing(void);
|
int flash_stop_flashing(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -10,21 +10,14 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
#include <pthread.h>
|
||||||
#include "proxmark3.h"
|
#include "proxmark3.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "util_posix.h"
|
#include "util_posix.h"
|
||||||
#include "flash.h"
|
#include "flash.h"
|
||||||
#include "uart.h"
|
#include "comms.h"
|
||||||
#include "usb_cmd.h"
|
#include "usb_cmd.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
# define unlink(x)
|
|
||||||
#else
|
|
||||||
# include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static serial_port sp;
|
|
||||||
static char* serial_port_name;
|
|
||||||
|
|
||||||
void cmd_debug(UsbCommand* UC) {
|
void cmd_debug(UsbCommand* UC) {
|
||||||
// Debug
|
// Debug
|
||||||
|
@ -40,62 +33,24 @@ void cmd_debug(UsbCommand* UC) {
|
||||||
printf("...\n");
|
printf("...\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendCommand(UsbCommand* txcmd) {
|
|
||||||
// printf("send: ");
|
|
||||||
// cmd_debug(txcmd);
|
|
||||||
if (!uart_send(sp,(byte_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;
|
|
||||||
size_t rxlen;
|
|
||||||
while (true) {
|
|
||||||
if (uart_receive(sp, prx, sizeof(UsbCommand) - (prx-prxcmd), &rxlen)) {
|
|
||||||
prx += rxlen;
|
|
||||||
if ((prx-prxcmd) >= sizeof(UsbCommand)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
static void usage(char *argv0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Usage: %s <port> [-b] image.elf [image.elf...]\n\n", argv0);
|
fprintf(stderr, "Usage: %s <port> [-b] image.elf [image.elf...]\n\n", argv0);
|
||||||
fprintf(stderr, "\t-b\tEnable flashing of bootloader area (DANGEROUS)\n\n");
|
fprintf(stderr, "\t-b\tEnable flashing of bootloader area (DANGEROUS)\n\n");
|
||||||
//Is the example below really true? /Martin
|
fprintf(stderr, "\nExample:\n\n\t %s "SERIAL_PORT_H" armsrc/obj/fullimage.elf\n", argv0);
|
||||||
fprintf(stderr, "Example:\n\n\t %s path/to/osimage.elf path/to/fpgaimage.elf\n", argv0);
|
#ifdef __linux__
|
||||||
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 at 'Waiting for Proxmark to reappear',\n");
|
||||||
fprintf(stderr, "\nNote (Linux): if the flasher gets stuck in 'Waiting for Proxmark to reappear on <DEVICE>',\n");
|
fprintf(stderr, " you may need to blacklist proxmark for modem-manager. v1.4.14 and later\n");
|
||||||
fprintf(stderr, " you need to blacklist proxmark for modem-manager - see wiki for more details:\n");
|
fprintf(stderr, " include this configuration patch already. The change can be found at:\n");
|
||||||
fprintf(stderr, " http://code.google.com/p/proxmark3/wiki/Linux\n\n");
|
fprintf(stderr, " https://cgit.freedesktop.org/ModemManager/ModemManager/commit/?id=6e7ff47\n\n");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MAX_FILES 4
|
#define MAX_FILES 4
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int can_write_bl = 0;
|
int can_write_bl = false;
|
||||||
int num_files = 0;
|
int num_files = 0;
|
||||||
int res;
|
int res;
|
||||||
flash_file_t files[MAX_FILES];
|
flash_file_t files[MAX_FILES];
|
||||||
|
@ -110,7 +65,7 @@ int main(int argc, char **argv)
|
||||||
for (int i = 2; i < argc; i++) {
|
for (int i = 2; i < argc; i++) {
|
||||||
if (argv[i][0] == '-') {
|
if (argv[i][0] == '-') {
|
||||||
if (!strcmp(argv[i], "-b")) {
|
if (!strcmp(argv[i], "-b")) {
|
||||||
can_write_bl = 1;
|
can_write_bl = true;
|
||||||
} else {
|
} else {
|
||||||
usage(argv[0]);
|
usage(argv[0]);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -126,16 +81,16 @@ int main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
serial_port_name = argv[1];
|
char* serial_port_name = argv[1];
|
||||||
|
|
||||||
fprintf(stderr,"Waiting for Proxmark to appear on %s",serial_port_name);
|
if (!OpenProxmark(serial_port_name, true, 120, true)) { // wait for 2 minutes
|
||||||
do {
|
fprintf(stderr, "Could not find Proxmark on %s.\n\n", serial_port_name);
|
||||||
msleep(1000);
|
return -1;
|
||||||
fprintf(stderr, ".");
|
} else {
|
||||||
} while (!OpenProxmark(0));
|
|
||||||
fprintf(stderr," Found.\n");
|
fprintf(stderr," Found.\n");
|
||||||
|
}
|
||||||
|
|
||||||
res = flash_start_flashing(can_write_bl,serial_port_name);
|
res = flash_start_flashing(can_write_bl, serial_port_name);
|
||||||
if (res < 0)
|
if (res < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
@ -155,6 +110,7 @@ int main(int argc, char **argv)
|
||||||
if (res < 0)
|
if (res < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
// Stop the command thread.
|
||||||
CloseProxmark();
|
CloseProxmark();
|
||||||
|
|
||||||
fprintf(stderr, "All done.\n\n");
|
fprintf(stderr, "All done.\n\n");
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
// piwi, 2017, 2018
|
||||||
|
//
|
||||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
// 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
|
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||||
// the license.
|
// the license.
|
||||||
|
@ -11,9 +13,11 @@
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <libgen.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include "fpga.h"
|
||||||
#include "zlib.h"
|
#include "zlib.h"
|
||||||
|
|
||||||
#define MAX(a,b) ((a)>(b)?(a):(b))
|
#define MAX(a,b) ((a)>(b)?(a):(b))
|
||||||
|
@ -37,18 +41,18 @@
|
||||||
#define COMPRESS_MAX_NICE_LENGTH 258
|
#define COMPRESS_MAX_NICE_LENGTH 258
|
||||||
#define COMPRESS_MAX_CHAIN 8192
|
#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))
|
#define HARDNESTED_TABLE_SIZE (sizeof(uint32_t) * ((1L<<19)+1))
|
||||||
|
|
||||||
static void usage(void)
|
static void usage(void)
|
||||||
{
|
{
|
||||||
fprintf(stdout, "Usage: fpga_compress <infile1> <infile2> ... <infile_n> <outfile>\n");
|
fprintf(stdout, "Usage: fpga_compress <infile1> <infile2> ... <infile_n> <outfile>\n");
|
||||||
fprintf(stdout, " Combine n FPGA bitstream files and compress them into one.\n\n");
|
fprintf(stdout, " Combine n FPGA bitstream files and compress them into one.\n\n");
|
||||||
fprintf(stdout, " fpga_compress -d <infile> <outfile>");
|
fprintf(stdout, " fpga_compress -v <infile1> <infile2> ... <infile_n> <outfile>\n");
|
||||||
fprintf(stdout, " Decompress <infile>. Write result to <outfile>");
|
fprintf(stdout, " Extract Version Information from FPGA bitstream files and write it to <outfile>\n\n");
|
||||||
fprintf(stdout, " fpga_compress -t <infile> <outfile>");
|
fprintf(stdout, " fpga_compress -d <infile> <outfile>\n");
|
||||||
fprintf(stdout, " Compress hardnested table <infile>. Write result to <outfile>");
|
fprintf(stdout, " Decompress <infile>. Write result to <outfile>\n\n");
|
||||||
|
fprintf(stdout, " fpga_compress -t <infile> <outfile>\n");
|
||||||
|
fprintf(stdout, " Compress hardnested table <infile>. Write result to <outfile>\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)
|
static void fpga_deflate_free(voidpf opaque, voidpf address)
|
||||||
{
|
{
|
||||||
return free(address);
|
free(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -108,7 +112,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 j = 0; j < num_infiles; j++) {
|
||||||
for(uint16_t k = 0; k < FPGA_INTERLEAVE_SIZE; k++) {
|
for(uint16_t k = 0; k < FPGA_INTERLEAVE_SIZE; k++) {
|
||||||
c = fgetc(infile[j]);
|
c = (uint8_t)fgetc(infile[j]);
|
||||||
if (!feof(infile[j])) {
|
if (!feof(infile[j])) {
|
||||||
fpga_config[i++] = c;
|
fpga_config[i++] = c;
|
||||||
} else if (num_infiles > 1) {
|
} else if (num_infiles > 1) {
|
||||||
|
@ -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), <length> 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)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
FILE **infiles;
|
FILE **infiles;
|
||||||
|
char **infile_names;
|
||||||
FILE *outfile;
|
FILE *outfile;
|
||||||
|
|
||||||
if (argc == 1 || argc == 2) {
|
if (argc == 1 || argc == 2) {
|
||||||
|
@ -271,43 +428,56 @@ int main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
infiles[0] = fopen(argv[2], "rb");
|
infiles[0] = fopen(argv[2], "rb");
|
||||||
if (infiles[0] == NULL) {
|
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);
|
return(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
outfile = fopen(argv[3], "wb");
|
outfile = fopen(argv[3], "wb");
|
||||||
if (outfile == NULL) {
|
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(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
return zlib_decompress(infiles[0], outfile);
|
return zlib_decompress(infiles[0], outfile);
|
||||||
|
|
||||||
} else { // Compress
|
} else { // Compress or gemerate version info
|
||||||
|
|
||||||
bool hardnested_mode = false;
|
bool hardnested_mode = false;
|
||||||
|
bool generate_version_file = false;
|
||||||
int num_input_files = 0;
|
int num_input_files = 0;
|
||||||
if (!strcmp(argv[1], "-t")) { // hardnested table
|
if (!strcmp(argv[1], "-t")) { // compress one hardnested table
|
||||||
if (argc != 4) {
|
if (argc != 4) {
|
||||||
usage();
|
usage();
|
||||||
return(EXIT_FAILURE);
|
return(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
hardnested_mode = true;
|
hardnested_mode = true;
|
||||||
num_input_files = 1;
|
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;
|
num_input_files = argc-2;
|
||||||
}
|
}
|
||||||
|
|
||||||
infiles = calloc(num_input_files, sizeof(FILE*));
|
infiles = calloc(num_input_files, sizeof(FILE*));
|
||||||
|
infile_names = calloc(num_input_files, sizeof(char*));
|
||||||
for (uint16_t i = 0; i < num_input_files; i++) {
|
for (uint16_t i = 0; i < num_input_files; i++) {
|
||||||
infiles[i] = fopen(argv[i+hardnested_mode?2:1], "rb");
|
infile_names[i] = argv[i+((hardnested_mode || generate_version_file)?2:1)];
|
||||||
|
infiles[i] = fopen(infile_names[i], "rb");
|
||||||
if (infiles[i] == NULL) {
|
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);
|
return(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
outfile = fopen(argv[argc-1], "wb");
|
outfile = fopen(argv[argc-1], "wb");
|
||||||
if (outfile == NULL) {
|
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(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
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);
|
return zlib_compress(infiles, num_input_files, outfile, hardnested_mode);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -548,44 +548,105 @@ out:
|
||||||
crack_states_bitsliced_t *crack_states_bitsliced_function_p = &crack_states_bitsliced_dispatch;
|
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;
|
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
|
static SIMDExecInstr intSIMDInstr = SIMD_AUTO;
|
||||||
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) {
|
|
||||||
|
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() {
|
||||||
|
SIMDExecInstr instr = SIMD_NONE;
|
||||||
|
|
||||||
#if defined (__i386__) || defined (__x86_64__)
|
#if defined (__i386__) || defined (__x86_64__)
|
||||||
#if !defined(__APPLE__) || (defined(__APPLE__) && (__clang_major__ > 8 || __clang_major__ == 8 && __clang_minor__ >= 1))
|
#if !defined(__APPLE__) || (defined(__APPLE__) && (__clang_major__ > 8 || __clang_major__ == 8 && __clang_minor__ >= 1))
|
||||||
#if (__GNUC__ >= 5) && (__GNUC__ > 5 || __GNUC_MINOR__ > 2)
|
#if (__GNUC__ >= 5) && (__GNUC__ > 5 || __GNUC_MINOR__ > 2)
|
||||||
if (__builtin_cpu_supports("avx512f")) crack_states_bitsliced_function_p = &crack_states_bitsliced_AVX512;
|
if (__builtin_cpu_supports("avx512f")) instr = SIMD_AVX512;
|
||||||
else if (__builtin_cpu_supports("avx2")) crack_states_bitsliced_function_p = &crack_states_bitsliced_AVX2;
|
else if (__builtin_cpu_supports("avx2")) instr = SIMD_AVX2;
|
||||||
#else
|
#else
|
||||||
if (__builtin_cpu_supports("avx2")) crack_states_bitsliced_function_p = &crack_states_bitsliced_AVX2;
|
if (__builtin_cpu_supports("avx2")) instr = SIMD_AVX2;
|
||||||
#endif
|
#endif
|
||||||
else if (__builtin_cpu_supports("avx")) crack_states_bitsliced_function_p = &crack_states_bitsliced_AVX;
|
else if (__builtin_cpu_supports("avx")) instr = SIMD_AVX;
|
||||||
else if (__builtin_cpu_supports("sse2")) crack_states_bitsliced_function_p = &crack_states_bitsliced_SSE2;
|
else if (__builtin_cpu_supports("sse2")) instr = SIMD_SSE2;
|
||||||
else if (__builtin_cpu_supports("mmx")) crack_states_bitsliced_function_p = &crack_states_bitsliced_MMX;
|
else if (__builtin_cpu_supports("mmx")) instr = SIMD_MMX;
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
instr = SIMD_NONE;
|
||||||
|
|
||||||
|
return instr;
|
||||||
|
}
|
||||||
|
|
||||||
|
SIMDExecInstr GetSIMDInstrAuto() {
|
||||||
|
SIMDExecInstr instr = intSIMDInstr;
|
||||||
|
if (instr == SIMD_AUTO)
|
||||||
|
return GetSIMDInstr();
|
||||||
|
|
||||||
|
return instr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
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;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
crack_states_bitsliced_function_p = &crack_states_bitsliced_NOSIMD;
|
crack_states_bitsliced_function_p = &crack_states_bitsliced_NOSIMD;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// call the most optimized function for this CPU
|
// 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);
|
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) {
|
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 (__i386__) || defined (__x86_64__)
|
||||||
#if !defined(__APPLE__) || (defined(__APPLE__) && (__clang_major__ > 8 || __clang_major__ == 8 && __clang_minor__ >= 1))
|
#if !defined(__APPLE__) || (defined(__APPLE__) && (__clang_major__ > 8 || __clang_major__ == 8 && __clang_minor__ >= 1))
|
||||||
#if (__GNUC__ >= 5) && (__GNUC__ > 5 || __GNUC_MINOR__ > 2)
|
#if (__GNUC__ >= 5) && (__GNUC__ > 5 || __GNUC_MINOR__ > 2)
|
||||||
if (__builtin_cpu_supports("avx512f")) bitslice_test_nonces_function_p = &bitslice_test_nonces_AVX512;
|
case SIMD_AVX512:
|
||||||
else if (__builtin_cpu_supports("avx2")) bitslice_test_nonces_function_p = &bitslice_test_nonces_AVX2;
|
bitslice_test_nonces_function_p = &bitslice_test_nonces_AVX512;
|
||||||
#else
|
break;
|
||||||
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
|
#endif
|
||||||
|
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;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
bitslice_test_nonces_function_p = &bitslice_test_nonces_NOSIMD;
|
bitslice_test_nonces_function_p = &bitslice_test_nonces_NOSIMD;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// call the most optimized function for this CPU
|
// call the most optimized function for this CPU
|
||||||
(*bitslice_test_nonces_function_p)(nonces_to_bruteforce, bf_test_nonce, bf_test_nonce_par);
|
(*bitslice_test_nonces_function_p)(nonces_to_bruteforce, bf_test_nonce, bf_test_nonce_par);
|
||||||
|
|
|
@ -52,6 +52,18 @@ THE SOFTWARE.
|
||||||
|
|
||||||
#include "hardnested_bruteforce.h" // statelist_t
|
#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 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);
|
extern void bitslice_test_nonces(uint32_t nonces_to_bruteforce, uint32_t *bf_test_nonces, uint8_t *bf_test_nonce_par);
|
||||||
|
|
||||||
|
|
|
@ -139,8 +139,13 @@ bool verify_key(uint32_t cuid, noncelist_t *nonces, uint8_t *best_first_bytes, u
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void*
|
||||||
static void* crack_states_thread(void* x){
|
#ifdef __has_attribute
|
||||||
|
#if __has_attribute(force_align_arg_pointer)
|
||||||
|
__attribute__((force_align_arg_pointer))
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
crack_states_thread(void* x){
|
||||||
|
|
||||||
struct arg {
|
struct arg {
|
||||||
bool silent;
|
bool silent;
|
||||||
|
|
|
@ -31,7 +31,6 @@ usb_dev_handle *devh = NULL;
|
||||||
static unsigned int claimed_iface = 0;
|
static unsigned int claimed_iface = 0;
|
||||||
unsigned char return_on_error = 0;
|
unsigned char return_on_error = 0;
|
||||||
unsigned char error_occured = 0;
|
unsigned char error_occured = 0;
|
||||||
extern unsigned int current_command;
|
|
||||||
|
|
||||||
void SendCommand(UsbCommand *c)
|
void SendCommand(UsbCommand *c)
|
||||||
{
|
{
|
||||||
|
@ -40,7 +39,6 @@ void SendCommand(UsbCommand *c)
|
||||||
#if 0
|
#if 0
|
||||||
printf("Sending %d bytes\n", sizeof(UsbCommand));
|
printf("Sending %d bytes\n", sizeof(UsbCommand));
|
||||||
#endif
|
#endif
|
||||||
current_command = c->cmd;
|
|
||||||
ret = usb_bulk_write(devh, 0x01, (char*)c, sizeof(UsbCommand), 1000);
|
ret = usb_bulk_write(devh, 0x01, (char*)c, sizeof(UsbCommand), 1000);
|
||||||
if (ret<0) {
|
if (ret<0) {
|
||||||
error_occured = 1;
|
error_occured = 1;
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
This is a library to read 14443a tags. It can be used something like this
|
This is a library to read 14443a tags. It can be used something like this
|
||||||
|
|
||||||
local reader = require('read14a')
|
local reader = require('read14a')
|
||||||
result, err = reader.read1443a()
|
result, err = reader.read14443a()
|
||||||
if not result then
|
if not result then
|
||||||
print(err)
|
print(err)
|
||||||
return
|
return
|
||||||
|
@ -43,11 +43,11 @@ ISO14443a_TYPES[0x88] = "Infineon MIFARE CLASSIC 1K"
|
||||||
ISO14443a_TYPES[0x98] = "Gemplus MPCOS"
|
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)
|
return ISO14443a_TYPES[sak] or ("Unknown (SAK=%x)"):format(sak)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function parse1443a(data)
|
local function parse14443a(data)
|
||||||
--[[
|
--[[
|
||||||
|
|
||||||
Based on this struct :
|
Based on this struct :
|
||||||
|
@ -66,8 +66,8 @@ local function parse1443a(data)
|
||||||
local count,uid,uidlen, atqa, sak, ats_len, ats= bin.unpack('H10CH2CC',data)
|
local count,uid,uidlen, atqa, sak, ats_len, ats= bin.unpack('H10CH2CC',data)
|
||||||
uid = uid:sub(1,2*uidlen)
|
uid = uid:sub(1,2*uidlen)
|
||||||
--print("uid, atqa, sak: ",uid, atqa, sak)
|
--print("uid, atqa, sak: ",uid, atqa, sak)
|
||||||
--print("TYPE: ", tostring_1443a(sak))
|
--print("TYPE: ", tostring_14443a(sak))
|
||||||
return { uid = uid, atqa = atqa, sak = sak, name = tostring_1443a(sak)}
|
return { uid = uid, atqa = atqa, sak = sak, name = tostring_14443a(sak)}
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Sends a USBpacket to the device
|
--- Sends a USBpacket to the device
|
||||||
|
@ -114,7 +114,7 @@ local function read14443a(dont_disconnect, no_rats)
|
||||||
return nil, "iso14443a card select failed"
|
return nil, "iso14443a card select failed"
|
||||||
end
|
end
|
||||||
data = string.sub(result,count)
|
data = string.sub(result,count)
|
||||||
info, err = parse1443a(data)
|
info, err = parse14443a(data)
|
||||||
else
|
else
|
||||||
err ="No response from card"
|
err ="No response from card"
|
||||||
end
|
end
|
||||||
|
@ -139,12 +139,12 @@ local function waitFor14443a()
|
||||||
end
|
end
|
||||||
return nil, "Aborted by user"
|
return nil, "Aborted by user"
|
||||||
end
|
end
|
||||||
local library = {
|
|
||||||
|
|
||||||
read1443a = read14443a,
|
local library = {
|
||||||
|
read14443a = read14443a,
|
||||||
read = read14443a,
|
read = read14443a,
|
||||||
waitFor14443a = waitFor14443a,
|
waitFor14443a = waitFor14443a,
|
||||||
parse1443a = parse1443a,
|
parse14443a = parse14443a,
|
||||||
sendToDevice = sendToDevice,
|
sendToDevice = sendToDevice,
|
||||||
ISO14A_COMMAND = ISO14A_COMMAND,
|
ISO14A_COMMAND = ISO14A_COMMAND,
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,10 +16,11 @@
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
#include "crapto1/crapto1.h"
|
#include "crapto1/crapto1.h"
|
||||||
#include "proxmark3.h"
|
#include "comms.h"
|
||||||
#include "usb_cmd.h"
|
#include "usb_cmd.h"
|
||||||
#include "cmdmain.h"
|
#include "cmdmain.h"
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
|
#include "parity.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "iso14443crc.h"
|
#include "iso14443crc.h"
|
||||||
|
|
||||||
|
@ -73,13 +74,12 @@ static uint32_t intersection(uint64_t *list1, uint64_t *list2)
|
||||||
|
|
||||||
|
|
||||||
// Darkside attack (hf mf mifare)
|
// 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;
|
struct Crypto1State *states;
|
||||||
uint32_t i, pos, rr; //nr_diff;
|
uint32_t i, pos;
|
||||||
uint8_t bt, ks3x[8], par[8][8];
|
uint8_t bt, ks3x[8], par[8][8];
|
||||||
uint64_t key_recovered;
|
uint64_t key_recovered;
|
||||||
static uint64_t *keylist;
|
uint64_t *keylist;
|
||||||
rr = 0;
|
|
||||||
|
|
||||||
// Reset the last three significant bits of the reader nonce
|
// Reset the last three significant bits of the reader nonce
|
||||||
nr &= 0xffffff1f;
|
nr &= 0xffffff1f;
|
||||||
|
@ -92,7 +92,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) {
|
if (states == NULL) {
|
||||||
*keys = NULL;
|
*keys = NULL;
|
||||||
|
@ -116,7 +116,7 @@ static uint32_t nonce2key(uint32_t uid, uint32_t nt, uint32_t nr, uint64_t par_i
|
||||||
int mfDarkside(uint64_t *key)
|
int mfDarkside(uint64_t *key)
|
||||||
{
|
{
|
||||||
uint32_t uid = 0;
|
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 par_list = 0, ks_list = 0;
|
||||||
uint64_t *keylist = NULL, *last_keylist = NULL;
|
uint64_t *keylist = NULL, *last_keylist = NULL;
|
||||||
uint32_t keycount = 0;
|
uint32_t keycount = 0;
|
||||||
|
@ -159,18 +159,18 @@ int mfDarkside(uint64_t *key)
|
||||||
nt = (uint32_t)bytes_to_num(resp.d.asBytes + 4, 4);
|
nt = (uint32_t)bytes_to_num(resp.d.asBytes + 4, 4);
|
||||||
par_list = bytes_to_num(resp.d.asBytes + 8, 8);
|
par_list = bytes_to_num(resp.d.asBytes + 8, 8);
|
||||||
ks_list = bytes_to_num(resp.d.asBytes + 16, 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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (par_list == 0 && c.arg[0] == true) {
|
if (par_list == 0 && c.arg[0] == true) {
|
||||||
PrintAndLog("Parity is all zero. Most likely this card sends NACK on every failed authentication.");
|
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;
|
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) {
|
if (keycount == 0) {
|
||||||
PrintAndLog("Key not found (lfsr_common_prefix list is null). Nt=%08x", nt);
|
PrintAndLog("Key not found (lfsr_common_prefix list is null). Nt=%08x", nt);
|
||||||
|
@ -178,6 +178,7 @@ int mfDarkside(uint64_t *key)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (par_list == 0) {
|
||||||
qsort(keylist, keycount, sizeof(*keylist), compare_uint64);
|
qsort(keylist, keycount, sizeof(*keylist), compare_uint64);
|
||||||
keycount = intersection(last_keylist, keylist);
|
keycount = intersection(last_keylist, keylist);
|
||||||
if (keycount == 0) {
|
if (keycount == 0) {
|
||||||
|
@ -185,6 +186,7 @@ int mfDarkside(uint64_t *key)
|
||||||
last_keylist = keylist;
|
last_keylist = keylist;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (keycount > 1) {
|
if (keycount > 1) {
|
||||||
PrintAndLog("Found %u possible keys. Trying to authenticate with each of them ...\n", keycount);
|
PrintAndLog("Found %u possible keys. Trying to authenticate with each of them ...\n", keycount);
|
||||||
|
@ -198,10 +200,10 @@ int mfDarkside(uint64_t *key)
|
||||||
for (int i = 0; i < keycount; i += max_keys) {
|
for (int i = 0; i < keycount; i += max_keys) {
|
||||||
int size = keycount - i > max_keys ? max_keys : keycount - i;
|
int size = keycount - i > max_keys ? max_keys : keycount - i;
|
||||||
for (int j = 0; j < size; j++) {
|
for (int j = 0; j < size; j++) {
|
||||||
if (last_keylist == NULL) {
|
if (par_list == 0) {
|
||||||
num_to_bytes(keylist[i*max_keys + j], 6, keyBlock);
|
num_to_bytes(last_keylist[i*max_keys + j], 6, keyBlock+(j*6));
|
||||||
} else {
|
} else {
|
||||||
num_to_bytes(last_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)) {
|
if (!mfCheckKeys(0, 0, false, size, keyBlock, key)) {
|
||||||
|
@ -295,7 +297,13 @@ typedef
|
||||||
|
|
||||||
|
|
||||||
// wrapper function for multi-threaded lfsr_recovery32
|
// 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;
|
struct Crypto1State *p1;
|
||||||
StateList_t *statelist = arg;
|
StateList_t *statelist = arg;
|
||||||
|
@ -309,6 +317,7 @@ void* nested_worker_thread(void *arg)
|
||||||
return statelist->head.slhead;
|
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)
|
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;
|
uint16_t i;
|
||||||
|
@ -319,7 +328,7 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo,
|
||||||
struct Crypto1State *p1, *p2, *p3, *p4;
|
struct Crypto1State *p1, *p2, *p3, *p4;
|
||||||
|
|
||||||
// flush queue
|
// 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}};
|
UsbCommand c = {CMD_MIFARE_NESTED, {blockNo + keyType * 0x100, trgBlockNo + trgKeyType * 0x100, calibrate}};
|
||||||
memcpy(c.d.asBytes, key, 6);
|
memcpy(c.d.asBytes, key, 6);
|
||||||
|
@ -574,14 +583,19 @@ struct Crypto1State *traceCrypto1 = NULL;
|
||||||
|
|
||||||
struct Crypto1State *revstate;
|
struct Crypto1State *revstate;
|
||||||
uint64_t lfsr;
|
uint64_t lfsr;
|
||||||
|
uint64_t ui64Key;
|
||||||
uint32_t ks2;
|
uint32_t ks2;
|
||||||
uint32_t ks3;
|
uint32_t ks3;
|
||||||
|
|
||||||
uint32_t uid; // serial number
|
uint32_t uid; // serial number
|
||||||
uint32_t nt; // tag challenge
|
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 nr_enc; // encrypted reader challenge
|
||||||
uint32_t ar_enc; // encrypted reader response
|
uint32_t ar_enc; // encrypted reader response
|
||||||
|
uint8_t ar_enc_par; // encrypted reader response parity
|
||||||
uint32_t at_enc; // encrypted tag response
|
uint32_t at_enc; // encrypted tag response
|
||||||
|
uint8_t at_enc_par; // encrypted tag response parity
|
||||||
|
|
||||||
int isTraceCardEmpty(void) {
|
int isTraceCardEmpty(void) {
|
||||||
return ((traceCard[0] == 0) && (traceCard[1] == 0) && (traceCard[2] == 0) && (traceCard[3] == 0));
|
return ((traceCard[0] == 0) && (traceCard[1] == 0) && (traceCard[2] == 0) && (traceCard[3] == 0));
|
||||||
|
@ -609,6 +623,7 @@ int saveTraceCard(void) {
|
||||||
for (int i = 0; i < 64; i++) { // blocks
|
for (int i = 0; i < 64; i++) { // blocks
|
||||||
for (int j = 0; j < 16; j++) // bytes
|
for (int j = 0; j < 16; j++) // bytes
|
||||||
fprintf(f, "%02x", *(traceCard + i * 16 + j));
|
fprintf(f, "%02x", *(traceCard + i * 16 + j));
|
||||||
|
if (i < 63)
|
||||||
fprintf(f,"\n");
|
fprintf(f,"\n");
|
||||||
}
|
}
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
@ -699,8 +714,36 @@ void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len, bool i
|
||||||
return;
|
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;
|
||||||
|
|
||||||
int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) {
|
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;
|
||||||
|
|
||||||
|
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];
|
uint8_t data[64];
|
||||||
|
|
||||||
if (traceState == TRACE_ERROR) return 1;
|
if (traceState == TRACE_ERROR) return 1;
|
||||||
|
@ -712,7 +755,9 @@ int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) {
|
||||||
memcpy(data, data_src, len);
|
memcpy(data, data_src, len);
|
||||||
if ((traceCrypto1) && ((traceState == TRACE_IDLE) || (traceState > TRACE_AUTH_OK))) {
|
if ((traceCrypto1) && ((traceState == TRACE_IDLE) || (traceState > TRACE_AUTH_OK))) {
|
||||||
mf_crypto1_decrypt(traceCrypto1, data, len, 0);
|
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);
|
AddLogHex(logHexFileName, "dec> ", data, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -801,7 +846,12 @@ int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) {
|
||||||
case TRACE_AUTH1:
|
case TRACE_AUTH1:
|
||||||
if (len == 4) {
|
if (len == 4) {
|
||||||
traceState = TRACE_AUTH2;
|
traceState = TRACE_AUTH2;
|
||||||
|
if (!traceCrypto1) {
|
||||||
nt = bytes_to_num(data, 4);
|
nt = bytes_to_num(data, 4);
|
||||||
|
} else {
|
||||||
|
nt_enc = bytes_to_num(data, 4);
|
||||||
|
nt_enc_par = parity;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
traceState = TRACE_ERROR;
|
traceState = TRACE_ERROR;
|
||||||
|
@ -815,6 +865,7 @@ int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) {
|
||||||
|
|
||||||
nr_enc = bytes_to_num(data, 4);
|
nr_enc = bytes_to_num(data, 4);
|
||||||
ar_enc = bytes_to_num(data + 4, 4);
|
ar_enc = bytes_to_num(data + 4, 4);
|
||||||
|
ar_enc_par = parity << 4;
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
traceState = TRACE_ERROR;
|
traceState = TRACE_ERROR;
|
||||||
|
@ -827,6 +878,8 @@ int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) {
|
||||||
traceState = TRACE_IDLE;
|
traceState = TRACE_IDLE;
|
||||||
|
|
||||||
at_enc = bytes_to_num(data, 4);
|
at_enc = bytes_to_num(data, 4);
|
||||||
|
at_enc_par = parity;
|
||||||
|
if (!traceCrypto1) {
|
||||||
|
|
||||||
// decode key here)
|
// decode key here)
|
||||||
ks2 = ar_enc ^ prng_successor(nt, 64);
|
ks2 = ar_enc ^ prng_successor(nt, 64);
|
||||||
|
@ -838,8 +891,77 @@ int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) {
|
||||||
lfsr_rollback_word(revstate, uid ^ nt, 0);
|
lfsr_rollback_word(revstate, uid ^ nt, 0);
|
||||||
|
|
||||||
crypto1_get_lfsr(revstate, &lfsr);
|
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);
|
AddLogUint64(logHexFileName, "key> ", lfsr);
|
||||||
|
} else {
|
||||||
|
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;
|
||||||
|
crypto1_destroy(pcs);
|
||||||
|
printf("key> the same key test. nr1: %08x ar1: %08x at1: %08x \n", nr1, ar1, at1);
|
||||||
|
|
||||||
|
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;
|
int blockShift = ((traceCurBlock & 0xFC) + 3) * 16;
|
||||||
if (isBlockEmpty((traceCurBlock & 0xFC) + 3)) memcpy(traceCard + blockShift + 6, trailerAccessBytes, 4);
|
if (isBlockEmpty((traceCurBlock & 0xFC) + 3)) memcpy(traceCard + blockShift + 6, trailerAccessBytes, 4);
|
||||||
|
@ -857,15 +979,6 @@ int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) {
|
||||||
|
|
||||||
// set cryptosystem state
|
// set cryptosystem state
|
||||||
traceCrypto1 = lfsr_recovery64(ks2, ks3);
|
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;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
traceState = TRACE_ERROR;
|
traceState = TRACE_ERROR;
|
||||||
|
|
|
@ -13,7 +13,8 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "data.h"
|
#include "crapto1/crapto1.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
// defaults
|
// defaults
|
||||||
// timeout in units. (ms * 106)/10 or us*0.0106
|
// timeout in units. (ms * 106)/10 or us*0.0106
|
||||||
|
@ -50,7 +51,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 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 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 isTraceCardEmpty(void);
|
||||||
extern int isBlockEmpty(int blockN);
|
extern int isBlockEmpty(int blockN);
|
||||||
|
@ -61,5 +62,7 @@ extern int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t
|
||||||
|
|
||||||
extern int mfCIdentify();
|
extern int mfCIdentify();
|
||||||
extern int DetectClassicPrng(void);
|
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
|
#endif
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue